Identify date format from a string in PHP - php

I am trying to update all of the date fields in the database to add 5 days to each date in all tables.
I managed to pull the dates and row id into an array then generate a SQL code statement to update them. However, each table has a different date format some with time included some without. I want to add 5 days to a date then save it back. At the moment I can do this if all dates have the same format but that's not good enough to solve my problem.
What I want is a code that can generate string format from a date string. For example:
Date String 2014-12-04 I want the code to say this date has Y-m-d format. If date string is 2017-04-03 11:11:48.653 I want the code to say this date format is Y-m-d h:i:s.

If you don't need to preserve the format (i.e. you can change the format in the database while adding five days), you can just throw the string at strtotime. It will try and detect the format, if possible:
$timestamp = strtotime($string_with_unknown_format);
Alternatively, you can check for different formats with regex:
function extractDateTimeFormat($string) {
if (preg_match('/^\d{4}-\d{2}-\d{2}$/', $string))
return 'Y-m-d';
if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}$/', $string))
return 'Y-m-d H:i:s';
if (preg_match('/^\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2}\.\d{3}$/', $string))
return 'Y-m-d H:i:s.v';
if (preg_match('/^\d{2}\/\d{2}\/\d{4}$/', $string))
return 'm/d/Y';
if (preg_match('/^\d{2}\.\d{2}\.\d{4}$/', $string))
return 'd.m.Y';
}
However, that could get tiresome, depending on how many formats you expect. On the other hand - how many can there be?
The next alternative would be to replace the digits by their placeholders directly in the string - this would be more flexible, but possibly a little less predictable. In this case, the order of the lines is important. If you need to add 12 hour formats (AM / PM), you need to insert the lines prior to the line for H:i:s or it won't work.
function extractDateTimeFormat($string) {
$string = preg_replace('/\b\d{4}-\d{2}-\d{2}\b/', 'Y-m-d');
$string = preg_replace('/\b\d{2}\/\d{2}\/\d{4}\b/', 'm/d/Y');
$string = preg_replace('/\b\d{2}\.\d{2}\.\d{4}\b/', 'd.m.Y');
$string = preg_replace('/\b\d{2}:\d{2}\b:\d{2}\b/', 'H:i:s');
$string = preg_replace('/\b\d{2}:\d{2}\b/', 'H:i');
$string = preg_replace('/\.\d{3}\b/', '.v');
if (preg_match('/\d/', $string)
return false;
return $string;
}
That way, you'll detect date and time formats independently so you don't have to think of every possible combination.
You'll have to check with your live data which method works better.

The best way to format dates and know what date format, solution for those who are developing in date format. I also add the ISO8601 date format
function date_extract_format( $d, $null = '' ) {
// check Day -> (0[1-9]|[1-2][0-9]|3[0-1])
// check Month -> (0[1-9]|1[0-2])
// check Year -> [0-9]{4} or \d{4}
$patterns = array(
'/\b\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}.\d{3,8}Z\b/' => 'Y-m-d\TH:i:s.u\Z', // format DATE ISO 8601
'/\b\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])\b/' => 'Y-m-d',
'/\b\d{4}-(0[1-9]|[1-2][0-9]|3[0-1])-(0[1-9]|1[0-2])\b/' => 'Y-d-m',
'/\b(0[1-9]|[1-2][0-9]|3[0-1])-(0[1-9]|1[0-2])-\d{4}\b/' => 'd-m-Y',
'/\b(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])-\d{4}\b/' => 'm-d-Y',
'/\b\d{4}\/(0[1-9]|[1-2][0-9]|3[0-1])\/(0[1-9]|1[0-2])\b/' => 'Y/d/m',
'/\b\d{4}\/(0[1-9]|1[0-2])\/(0[1-9]|[1-2][0-9]|3[0-1])\b/' => 'Y/m/d',
'/\b(0[1-9]|[1-2][0-9]|3[0-1])\/(0[1-9]|1[0-2])\/\d{4}\b/' => 'd/m/Y',
'/\b(0[1-9]|1[0-2])\/(0[1-9]|[1-2][0-9]|3[0-1])\/\d{4}\b/' => 'm/d/Y',
'/\b\d{4}\.(0[1-9]|1[0-2])\.(0[1-9]|[1-2][0-9]|3[0-1])\b/' => 'Y.m.d',
'/\b\d{4}\.(0[1-9]|[1-2][0-9]|3[0-1])\.(0[1-9]|1[0-2])\b/' => 'Y.d.m',
'/\b(0[1-9]|[1-2][0-9]|3[0-1])\.(0[1-9]|1[0-2])\.\d{4}\b/' => 'd.m.Y',
'/\b(0[1-9]|1[0-2])\.(0[1-9]|[1-2][0-9]|3[0-1])\.\d{4}\b/' => 'm.d.Y',
// for 24-hour | hours seconds
'/\b(?:2[0-3]|[01][0-9]):[0-5][0-9](:[0-5][0-9])\.\d{3,6}\b/' => 'H:i:s.u',
'/\b(?:2[0-3]|[01][0-9]):[0-5][0-9](:[0-5][0-9])\b/' => 'H:i:s',
'/\b(?:2[0-3]|[01][0-9]):[0-5][0-9]\b/' => 'H:i',
// for 12-hour | hours seconds
'/\b(?:1[012]|0[0-9]):[0-5][0-9](:[0-5][0-9])\.\d{3,6}\b/' => 'h:i:s.u',
'/\b(?:1[012]|0[0-9]):[0-5][0-9](:[0-5][0-9])\b/' => 'h:i:s',
'/\b(?:1[012]|0[0-9]):[0-5][0-9]\b/' => 'h:i',
'/\.\d{3}\b/' => '.v'
);
//$d = preg_replace('/\b\d{2}:\d{2}\b/', 'H:i',$d);
$d = preg_replace( array_keys( $patterns ), array_values( $patterns ), $d );
return preg_match( '/\d/', $d ) ? $null : $d;
}
function date_formating( $date, $format = 'd/m/Y H:i', $in_format = false, $f = '' ) {
$isformat = date_extract_format( $date );
$d = DateTime::createFromFormat( $isformat, $date );
$format = $in_format ? $isformat : $format;
if ( $format ) {
if ( in_array( $format, [ 'Y-m-d\TH:i:s.u\Z', 'DATE_ISO8601', 'ISO8601' ] ) ) {
$f = $d ? $d->format( 'Y-m-d\TH:i:s.' ) . substr( $d->format( 'u' ), 0, 3 ) . 'Z': '';
} else {
$f = $d ? $d->format( $format ) : '';
}
}
return $f;
} // end function
function date_convert_format( $old = '' ) {
$old = trim( $old );
if ( preg_match( '/^[0-9]{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/', $old ) ) { // MySQL-compatible YYYY-MM-DD format
$new = $old;
} elseif ( preg_match( '/^[0-9]{4}-(0[1-9]|[1-2][0-9]|3[0-1])-(0[1-9]|1[0-2])$/', $old ) ) { // DD-MM-YYYY format
$new = substr( $old, 0, 4 ) . '-' . substr( $old, 5, 2 ) . '-' . substr( $old, 8, 2 );
} elseif ( preg_match( '/^(0[1-9]|[1-2][0-9]|3[0-1])-(0[1-9]|1[0-2])-[0-9]{4}$/', $old ) ) { // DD-MM-YYYY format
$new = substr( $old, 6, 4 ) . '-' . substr( $old, 3, 2 ) . '-' . substr( $old, 0, 2 );
} elseif ( preg_match( '/^(0[1-9]|[1-2][0-9]|3[0-1])-(0[1-9]|1[0-2])-[0-9]{2}$/', $old ) ) { // DD-MM-YY format
$new = substr( $old, 6, 4 ) . '-' . substr( $old, 3, 2 ) . '-20' . substr( $old, 0, 2 );
} else { // Any other format. Set it as an empty date.
$new = '0000-00-00';
}
return $new;
}
$date_1 = '13/05/2020 19:20:15.156457';
$date_2 = '25-05-2020 10:20';
$date_3 = '2020.05.20 10:20';
$date_4 = '2020.25.05 18:20';
$date_5 = '05/05/2020 12:20';
$date_6 = '05.05.2020 10:20';
$date_7 = '2020-20-05';
//-----------------------------
echo "1($date_1): " . date_formating( $date_1, false, true ) . PHP_EOL;
// echo-> isformat: d/m/Y H:i:s.u
// 1(13/05/2020 19:20:15): 2020-05-13 19:20
echo "2($date_2): " . date_formating( $date_2 ) . PHP_EOL;
// echo-> isformat: d-m-Y H:i
// 2(25-05-2020 10:20): 25/05/2020 10:20
echo "3($date_3): " . date_formating( $date_3 ) . PHP_EOL;
// echo-> isformat: Y.m.d H:i
// 3(2020.05.20 10:20): 20/05/2020 10:20
echo "4($date_4): " . date_formating( $date_4 ) . PHP_EOL;
// echo-> isformat: Y.d.m H:i
// 4(2020.25.05 18:20): 25/05/2020 18:20
echo "5($date_5): " . date_formating( $date_5 ) . PHP_EOL;
// echo-> isformat: d/m/Y H:i
// 5(05/05/2020 12:20): 05/05/2020 12:20
echo "6($date_6): " . date_formating( $date_6 ) . PHP_EOL;
// echo-> isformat: d.m.Y H:i
// 6(05.05.2020 10:20): 05/05/2020 10:20
echo "7($date_7): " . date_formating( $date_7, false, true ) . PHP_EOL;
// echo-> isformat: Y-d-m
// 7(2020-20-05): 2020-20-05
echo "Date ISO8601: = " . date_formating( $date_1, 'DATE_ISO8601' ) . PHP_EOL;
// echo-> isformat: d/m/Y H:i:s.u
// Date ISO8601: = 2020-05-13T19:20:15.156Z
echo "7($date_7): = " . date_convert_format( $date_7 );
// 7(2020-20-05): = 2020-20-05

Related

Foreach loop returning only last result

I need to format a YYYY-MM-DD date to output like "12 January 2020", I have got the date to output correctly, but the code will only output one of the five values that I want, I've obviously missed something.
I'm having an issue where the following code only outputs a single result:
function populate_dropdown($form){
//Reading posts for "Events" post type;
$posts = get_posts("post_type=el_events&orderby=date&order=asc&el_eventcategory=flo-talanoa&numberposts=-1");
//Creating drop down item array.
$items = array();
//Adding post dates titles to the items array
foreach($posts as $post)
$unformatteddate = $post->startdate;
$dateTime = DateTime::createFromFormat("Y-m-d", $unformatteddate);
$dateformatted = $dateTime->format('j F Y');
$items[] = array(
"value" => $dateformatted . ': ' . $post->location,
"text" => $dateformatted . ': ' . $post->location
);
//Adding items to field id 1.
foreach($form["fields"] as &$field)
if($field["id"] == 1){
$field["type"] = "select";
$field["choices"] = $items;
}
return $form;
}
If I replace:
$unformatteddate = $post->startdate;
$dateTime = DateTime::createFromFormat("Y-m-d", $unformatteddate);
$dateformatted = $dateTime->format('j F Y');
$items[] = array(
"value" => $dateformatted . ': ' . $post->location,
"text" => $dateformatted . ': ' . $post->location
);
With:
$items[] = array("value" => $post->startdate . ': ' . $post->location, "text" => $post->startdate . ': ' . $post->location);
The code outputs all five values (though with YYYY-MM-DD date format), what am I missing? I'm a novice when it comes to PHP.
Thanks in advance
You forgot to add {} in your foreach loop
foreach($posts as $post){
$unformatteddate = $post->startdate;
$dateTime = DateTime::createFromFormat("Y-m-d", $unformatteddate);
$dateformatted = $dateTime->format('j F Y');
$items[] = array(
"value" => $dateformatted . ': ' . $post->location,
"text" => $dateformatted . ': ' . $post->location
);
}
//Adding items to field id 1.
foreach($form["fields"] as &$field){
if($field["id"] == 1){
$field["type"] = "select";
$field["choices"] = $items;
}
}
You were missing the curly braces {} in foreach.

Removing date from string in PHP

I am trying to remove all dates from strings in PHP using preg_replace(). The dates are of the following formats: YYYY-MM-DD, YYYY/MM/DD or YYYY.MM.DD
$string1 = "Current from 2014-10-10 to 2015-05-23";
$output = preg_replace('/\d{4}[\/\-\.](0?[1-9]|1[012])[\/\-\.](0?[1-9]|[12][0-9]|3[01])/g', '', $string1);
Expected output is "Current from to ". Currently I am getting back "".
Any help greatly appreciated! Wonko
This should work.
$input = "Current from 2014-10-10 to 2015/05/23 and 2001.02.10";
$output = preg_replace('/(\d{4}[\.\/\-][01]\d[\.\/\-][0-3]\d)/', '', $input);
echo $output;
Update
To ensure that the date also is valid
<?php
$input = "Current from 2014-10-10 to 2015/05/23 and 2001.19.10";
$output = preg_replace_callback('/(\d{4}[\.\/\-][01]\d[\.\/\-][0-3]\d)/', function($matches) {
$date = str_replace(array('.','/'), '-', $matches[1]);
$newDate = DateTime::createFromFormat('Y-m-d', $date);
if($newDate->format('Y-m-d') == $date) {
return false;
}else {
return $matches[1];
}
}, $input);
echo $output;

Group 'Today's Events' under single Date Header?

I am trying to parse a Google Calendar to use on our TV's to display 'Today's Events'.
While I am most of the way there thanks to the help of a friend, I wanted to see if somebody could help me the rest of the way.
The code below generates the calendar with all the information, but for EVERY entry it shows the date. Since they are all the same day, this is kind of frustrating and confusing when looking at it. I am nowhere near a programmer, but I can make sense of some things.
How would I group all Todays events under a single date heading?
Thanks in advance.
<?php
$confirmed = 'http://schemas.google.com/g/2005#event.confirmed';
$three_months_in_seconds = 60 * 60 * 24 * 28 * 3;
$three_months_ago = date("Y-m-d\Th:i:s", time() - $three_months_in_seconds);
$three_months_from_today = date("Y-m-d\Th:i:s", time() + $three_months_in_seconds);
$params = "?orderby=starttime&start-min=" . $three_months_ago . "&start-max=" . $three_months_from_today;
//$params = "?orderby=starttime&start-min=2012-12-01T05:48:47&start-max=2013-05-07T05:48:47&sortorder=a&singleevents=true&futureevents=true";
$params = "?orderby=starttime&sortorder=a&singleevents=true&futureevents=true";
$feed = "https://www.google.com/calendar/feeds/REDACTED%40gmail.com/private-REDACTED/full".$params;
$doc = new DOMDocument();
if (!$doc->load( $feed )) echo 'failed to load';
$entries = $doc->getElementsByTagName( "entry" );
foreach ( $entries as $entry ) {
$status = $entry->getElementsByTagName( "eventStatus" );
$eventStatus = $status->item(0)->getAttributeNode("value")->value;
if ($eventStatus == $confirmed) {
$titles = $entry->getElementsByTagName( "title" );
$title = $titles->item(0)->nodeValue;
$times = $entry->getElementsByTagName( "when" );
$startTime = $times->item(0)->getAttributeNode("startTime")->value;
$when = date( "D M j, Y", strtotime( $startTime ) );
$time = date("g:i A",strtotime($startTime));
$places = $entry->getElementsByTagName( "where" );
$where = $places->item(0)->getAttributeNode("valueString")->value;
print "<div class='row when'>$when</div>";
echo "<div class='row event'><span class='time'>$time</span><span class='title'>$title</span><span class='where'>$where</span></div>";
// print $where . "\n";
print "\n";
}
}
?>
Have an answer:
just change this:
print "<div class='row when'>$when</div>";
to this:
if ($old_when!=$when) print "<div class='row when'>$when</div>"; $old_when=$when;
and add
$old_when = null;
before the foreach

Extract multiple date format from few string variables in php

I need to extract the date out of a string variable, and the date are formatted in various kind of formats as below:
$date1 = "03/12/2011 (Sat)";
$date2 = "3.12.2011 SAT";
$date3 = "Date: 03/12/2011 "; /* <-- the extra trailing space is intentional */
$date4 = "date:03/12/2011";
$date5 = "date: 03/12/2011";
$date6 = "03/12/2011";
$date7 = "13.12.2011 TUE";
What is the best way to create a PHP function which will work for all the input variables above in extracting the correct date info?
For more info on the DateTime object returned by the function, check the PHP documentation for the DateTime class.
/**
* Parses date from string
* #param string $str Uncorrected date string
* #return DateTime PHP datetime object
*/
function date_grab($str)
{
// regex pattern will match any date formatted dd-mm-yyy or d-mm-yyyy with
// separators: periods, slahes, dashes
$p = '{.*?(\d\d?)[\\/\.\-]([\d]{2})[\\/\.\-]([\d]{4}).*}';
$date = preg_replace($p, '$3-$2-$1', $str);
return new \DateTime($date);
}
// verify that it works correctly for your values:
$arr = array(
"03/12/2011 (Sat)",
"3.12.2011 SAT",
"Date: 03/12/2011 ", /* <-- the extra trailing space is intentional */
"date:03/12/2011",
"date: 03/12/2011",
"03/12/2011"
);
foreach ($arr as $str) {
$date = date_grab($str);
echo $date->format('Y-m-d') . "\n";
}
you can use the below function, it will match all the variables you spcecified.
function extractDates($mydate)
{
$date = explode(" ", $mydate);
$output = $date[0];
if ($date[0] == "Date:" || $date[0] == "date:")
{
$output = $date[1];
}
return $output;
}
$date1 = "Date: 03/12/2011";
echo extractDates($date1);
The output will be as you expected: "03/12/2011".
You can also test all your strings:
$date1 = "03/12/2011 (Sat)";
$date2 = "3.12.2011 SAT";
$date3 = "Date: 03/12/2011 "; /* <-- the extra trailing space is intentional */
$date4 = "date:03/12/2011";
$date5 = "date: 03/12/2011";
$date6 = "03/12/2011";
$date7 = "13.12.2011 TUE";

Sorting a google calendar feed (parsing with DOM)

I'm embedding dates from google calendar into a website, and it's all working, with the exception of sorting. For some reason, it sorts into reverse-chronological order, when I'd really just like it to be normal chronological (first event first).
this is the output:
August 11th: Intern depart
August 6th: Last Day of Summer Camp
July 7th: Ignore this
July 6th: This is another example event
July 5th: example
June 28th: Summer Camp Starts
June 24th: Summer Pool Party
June 21st: Intern arrival date
June 15th: Assistant Director Arrival Date
June 14th: Director's training begins
May 26th: Brainstorm day for directors
I'm really still just learning a lot of this stuff- thanks for the help in advance!
<?php
$confirmed = 'http://schemas.google.com/g/2005#event.confirmed';
$three_months_in_seconds = 60 * 60 * 24 * 28 * 3;
$three_months_ago = date("Y-m-d\Th:i:sP", time() - 172800);
$three_months_from_today = date("Y-m-d\Th:i:sP", time() + $three_months_in_seconds);
$feed = "http://www.google.com/calendar/feeds/qp6o02ka3iaoem2kr8odga6j7s%40group.calendar.google.com/" .
"public/full?orderby=starttime&singleevents=true&" .
"start-min=" . $three_months_ago . "&" .
"start-max=" . $three_months_from_today;
$doc = new DOMDocument();
$doc->load( $feed );
$entries = $doc->getElementsByTagName( "entry" );
foreach ( $entries as $entry ) {
$status = $entry->getElementsByTagName( "eventStatus" );
$eventStatus = $status->item(0)->getAttributeNode("value")->value;
if ($eventStatus == $confirmed) {
$titles = $entry->getElementsByTagName( "title" );
$title = $titles->item(0)->nodeValue;
$times = $entry->getElementsByTagName( "when" );
$startTime = $times->item(0)->getAttributeNode("startTime")->value;
$when = date( "F jS", strtotime( $startTime ) );
$whentime = date( "g:ia", strtotime ( $startTime ) );
$places = $entry->getElementsByTagName( "where" );
$where = $places->item(0)->getAttributeNode("valueString")->value;
$links = $entry->getElementsByTagName( "link" );
$link = $links->item(0)->nodeValue;
print $when;
if ($whentime == "12:00am"){
;
}
else{
echo " at ";
print $whentime;
}
echo ": ";
echo "<b>";
print $title . "\n";
echo "</b>";
echo " ";
if(empty($where)){;}else{
echo "<br />";
print $where . "\n";
}
print $link;
print "<br />";
}
}
?>
Add &sortorder=descending to your feed URL. You can find documentation for this in the FAQ

Categories