Extracting fulldate from yyyy-m-dd? - php

i've got 100s of files with names like:
CPC_2001_5_21_7.pdf
CPC_YYYY_M_DD_7.pdf
The last number is a page number and its irrelevant. I want to sort them out into directories like:
YYYYMMDD (ie: 20010521)

You can extract the year, month and day with:
if (preg_match('/^CPC_(\d{4})_(\d{1,2})_(\d{1,2}).*$/', $filename, $matches)) {
list($file, $year, $month, $day) = $matches;
}

If I were you, I would use the heavenly DateTime::createFromFormat. This allows you to designate a pattern and create a DateTime object from it.
So, for example,
$date = 'CPC_2001_5_21_7.pdf';
$dt = DateTime::createFromFormat('!*Y_n_d_*.*', $date);
You can then build a string with the data you want:
$filename = $dt->format('Ymd') . '.pdf';

You should split by underscore, then format the new filename using nullpadding.
<?php
$filenames = array(
"CPC_2001_5_21_7.pdf",
"CPC_2002_2_13_7.pdf",
"CPC_2004_6_23_7.pdf"
);
$newfilenames = array();
foreach($filenames as $filename)
{
$split = explode("_", $filename);
$newfilenames[] = sprintf("%04s%02s%02s", $split[1], $split[2], $split[3]) . ".pdf";
}
print_r($newfilenames);
?>
outputs
Array
(
[0] => 20010521.pdf
[1] => 20020213.pdf
[2] => 20040623.pdf
)

Related

How to split the time from a timestamp from a nested array of result?

I have been doing a project in php and i get a nested array from where i have to extract the values.
Here from this array i have to get only the time from the timestamp i.e from [ArrTime] and [DepTIme]
[Segment] => stdClass Object
(
[WSSegment] => stdClass Object
(
[DepTIme] => 2014-12-10T15:40:00
[ArrTime] => 2014-12-10T18:25:00
[ETicketEligible] => 1
[OperatingCarrier] => HW
)
)
I have being trying to apply the implode function on the timestamp but it is not working for me .
Try this one:
$DeptTime = date('H:i:s',strtotime($yourObject->Segment->WSSegment->DepTIme));
$ArrTime = date('H:i:s',strtotime($yourObject->Segment->WSSegment->ArrTime));
Write a function to retrieve it in php
<?php
$str = '2014-12-10T15:40:00';
function getOnlyTime($str = '') {
$time = '';
if (empty($str)) {
return $time;
}
return substr($str, 11);
}
echo getOnlyTime($yourObject->Segment->WSSegment->DepTIme);
echo getOnlyTime($yourObject->Segment->WSSegment->ArrTime);
?>
Live Example:
http://3v4l.org/1qChm
You could loop through the nested objects and see if the format matches a date. If it does, make an array of the matched elements. You could choose to index the array according to the index where it came from (if that matters later on in your code;
// Starts at "Segment"
foreach ($array as $segment => $item)
{
// Loops through the values of"WSSegment"
foreach ($item as $part => $value)
{
// Checks if the value is a valid date, might need to check type; $value must be a string
if ($date = date_create_from_format('Y-m-d\TH:i:s', $value))
{
// Dump to an array.
$dates[$part][] = $date;
}
}
}
$dates is now an array containing all valid dates in \DateTime format.
Here's another way that I recommend for several reasons. It saves one from having to manually extract the data by using substr() or explode(). The code uses two foreach loops to 'drill down to the desired items, namely the departure and arrival date-time data. If any of the names of the nested objects were to change, the code will still run since it makes use of variables in referring to those entities. Using a DateTime object's format property provides a handy way to access just the time information and you can easily exclude the seconds as the following example illustrates:
<?php
/**
* getTime()
* #param $str - date/time string
* returns time in hours and minutes
**/
function getTime( $str ){
$format = "H:i"; // Hours:Minutes
$timeObj = new DateTime( $str );
return $timeObj->format( $format );
}
foreach( $obj as $nested ) {
foreach( $nested as $n ){
echo 'DEP - ',getTime( $n->DepTime ),"\n";
echo 'ARV - ',getTime( $n->ArrTime ),"\n";
}
}
See http://3v4l.org/IdQN1

Double explode a text field containing date and time in PHP

I have a lengthy text field containing multiple date and time separated by comma. Following is the example
2013-08-26 10:00:00,2013-08-26 15:00:00,2013-08-26 20:00:00
2013-08-27 01:00:00,2013-08-27 06:00:00,2013-08-27 11:00:00
2013-08-27 16:00:00,2013-08-27 21:00:00,2013-08-28 02:00:00
2013-08-28 07:00:00,2013-08-28 12:00:00,2013-08-28 17:00:00
From the above example I need the following structure
Step 1: Split comma separated values into one array.
Step 2: From the above obtained array push all 2013-08-26 dates to one array, the 2013-08-27 to another array and then 2013-08-28.
I successfully exploded the main text to one array but did not succeed to obtain list of values of one particular date.
foreach (explode(PHP_EOL, $dates) as $line)
{
foreach (explode(',', $line) as $dt)
{
$dateVal = date('Y-m-d', strtotime($dt));
switch ($dateVal)
{
case '2013-08-26':
$arr1[] = $dt;
break;
case '2013-08-27':
$arr2[] = $dt;
break;
case '2013-08-28':
$arr3[] = $dt;
break;
}
}
}
Online demo
$dates = "2013-08-26 10:00:00,2013-08-26 15:00:00,2013-08-26 20:00:00
2013-08-27 01:00:00,2013-08-27 06:00:00,2013-08-27 11:00:00
2013-08-27 16:00:00,2013-08-27 21:00:00,2013-08-28 02:00:00
2013-08-28 07:00:00,2013-08-28 12:00:00,2013-08-28 17:00:00";
$dates = explode("\n", $dates);
foreach($dates as $date) {
$date = explode(",", $date);
var_dump($date);
// i.e. with $date[1] I will get the middle date of particular line.
}
$date inside foreach, as you can see becomes an array (after exploding) containing all dates separated by commas in one line.
it's been a while since the last time I used PHP, but this is my rusty solution:
$map = array();
$records = explode(',', $input);
foreach( $records as $record )
{
$a = explode(" ", $record);
if(!array_key_exists( $a[0], $map ))
$map[$a[0]] = array();
$map[$a[0]][] = $a[1];
}
var_dump($map);
I haven't tested it, sorry. But it might work...
it should give you something like:
array(2)
(
['2014-03-14'] => array(2)
(
[0] => '04:03:24'
[1] => '04:03:25'
)
['2014-03-14'] => array(2)
(
[0] => '04:03:24'
[1] => '04:03:25'
)
)

Return number after an underscore, dynamic preceeding

I have various values in a PHP array, that look like below:
$values = array("news_24", "news_81", "blog_56", "member_55", "news_27");
The first part before the underscore (news, blog, member) is dynamic so I would like to get all the matches in a specific section (news) followed by the numbers.
Something like below:
$section = "news";
$matches = preg_match('$section/[_])GETNUMBER/', $values);
This would return 24 and 27, but only where news was before the underscore.
Thanks.
$values = array("news_24", "news_81", "blog_56", "member_55", "news_27");
$section = "news";
foreach($values as $value) {
$matches = preg_match("/{$section}_(\\d+)/", $value, $number);
if ($matches)
echo $number[1], PHP_EOL;
}
$values = array("news_24", "news_81", "blog_56", "member_55", "news_27");
function func($type){
$results = null;
foreach($values as $val){
$curr = explode('_',$val);
if($curr[0]==$type){
$results[] = $curr[1];
}
}
return $results;
}
$News = func('news');
Good luck! :P
Note I added two cases:
$values = array ("news_24", "news_81", "blog_56", "member_55", "news_27",
"blognews_99", "news_2012_12");
$section = "news";
preg_match_all("/^{$section}_(\\d+)\$/m", implode("\n", $values), $matches);
print_r($matches[1]);
The implode might not be super efficient, but it's less code.
The difference is in the matching & regex.
This solution only outputs
Array
(
[0] => 24
[1] => 81
[2] => 27
)
While the others also output 2012 and the solution of Mark also 99.

Counting unique values in flatfile and updating them to an array

What is the most sensible way to count unique names and the last occurence (from the data) in a pipe-separated flatfile, where the data is formed like this:
Artist|YYYY-MM-DD|Location|\n
So when the data is for example (with newline in the end):
The Band|2011-04-01|Club Bulc|
Le Artist|1999-12-24|Reindeer Row|
Soundmakers|2012-03-22|Pub Pizza|
The Band|2010-12-01|Someplace|
Soundmakers|2009-07-07|Faraway|
Soundmakers|2010-08-18|ShowEr|
And the desired format would be:
Artist|Times listed|Latest year
How would you loop through the flatfile to get the following data into a second flatfile:
Le Artist|1|1999|
Soundmakers|3|2012|
The Band|2|2011|
At first I thought it would be quite a simple undertaking, but it turned out a bit more challenging!
I have one implementation that half-works (some items are written twice, and sometimes the year is in the wrong line!), so I would like to see if there are some better methods for accomplishing this.
I've tried both an OOP and procedural approach for this, and so far I've gotten better results with procedural. But for me the method really doesn't matter, as this is for my personal learning (and use).
Update:
The file is roughly 1 MB and will be far less than 10 MB in any foreseeable future.
Seems pretty simple indeed. You'll want the results to be stored an array like this:
$bands = array(
'Le Artist' => array('count' => 1, 'year' => 1999),
...
);
You can use fgetcsv to read in the lines and break them apart at the same time:
$line = fgetcsv($fh, 0, '|');
You can then check whether you already have this artist and increment the count:
$artist = $line[0];
if (!isset($bands[$artist])) {
$bands[$artist] = array('count' => 0, 'year' => null);
}
$bands[$artist]['count']++;
For the year, just explode $line[1] to extract the year, check if it's greater than $bands[$artist]['year'] and replace it if so.
First, make an array with artist name as key, and a list of years as values:
$grouped = array();
while (!feof($fd) && $line = fgets($fd)) {
list($artist, $date) = explode('|', $line);
list($year) = explode('-', $date);
$grouped[$artist][] = $year;
}
Then output the result:
foreach ($grouped as $artist => $years) {
printf("%s|%s|%s|\n", $artist, count($years), max($years));
}
Here is the version I ended up using, and it works as I hoped for:
<?php
$file = 'seen.txt';
$shows = array();
$sourceData = file($file);
foreach($sourceData as $row) {
list($date, $artist, $venue, $city, $country) = explode('|', $row);
$year = date('Y', strtotime($date));
if(!isset($shows[$artist])) {
$shows[$artist] = array('count' => 1, 'year' => $year);
} else {
$shows[$artist]['count']++;
if($shows[$artist]['year'] < $year) {
$shows[$artist]['year'] = $year;
}
}
}
echo '<h1>Bands and Shows</h1>';
ksort($shows);
foreach($shows as $band => $data) {
echo 'I have seen <b>',$band,'</b> perform ',$data['count'],' times, most recently in ',$data['year'],'<br/>';
}
?>

How to explode date like 09.06.2010 and get the "2010" with php?

How to explode date into pieces and get last part from it. Lets say, we have 09.06.2010 and we wanna get "2010" from it.How to do it with php?
Try this method:
end( explode( '.', $date ) );
OR
date( 'Y', strtotime( $date ) );
$sDate = "09.06.2010";
$aDate = explode(".", $sDate);
$iYear = $aDate[2];
var_dump($iYear);
There are other methods, like parsing the date. But you asked:
$date_output = explode('.', $date_input);
$date_output = $date_output[2];
You mean like 4 last digits of such string?
substr("09.06.2010",-4);
Although just like Pekka says in his comment, doing actual date processing will make your code more robust and easier to change in future.
if you always want the last position, you can try with strrpos(), it will find the last occurrence of a given character. So you may do:
$string = '11.22.3456';
$pos = strrpos($string, '.');
$year = ($pos !== false) ? substr($string, $pos + 1) : 'N/a';
var_dump($year);
explode() is always an option, just wanted to give another one.
$timestamp = time();
list($dd, $mm, $yy) = explode('.', strftime('%d.%m.%Y', $timestamp));
echo $mm;
See: strftime
See: list
function dateExp($date, $sign=null, $argIndex = '0'){
$exp = null;
if(!empty($date) && !empty($sign)){
$exp = explode($sign, $date);
} else {
$exp = explode('/', $date);
}
if($argIndex!=='0'){
$exp = $exp[$argIndex];
}
return $exp;
}
$setDate = '2015-10-20';
$date1 = dateExp($setDate,'-');
print '<pre>';
print_r($date1);
print_r($date1[0]);
Output:
Array
(
[0] => 2015
[1] => 10
[2] => 20
)
2015

Categories