Skip to content

Instantly share code, notes, and snippets.

@imhoffd
Created November 11, 2014 18:24
Show Gist options
  • Save imhoffd/a1754193bde215b6509f to your computer and use it in GitHub Desktop.
Save imhoffd/a1754193bde215b6509f to your computer and use it in GitHub Desktop.
strptime2 - parses dates given a format
<?php
require 'strptime2.php';
echo '<pre>';
echo strptime2('12/29/1989', 'm/d/Y') . "\n";
echo strptime2('7/15/1989 10:13am', 'n/d/Y h:ia') . "\n";
echo strptime2('07/15/1989 10:13AM', 'm/d/Y h:iA') . "\n";
echo strptime2('Sep 12, 2013 22:12', 'M j, Y H:i') . "\n";
echo strptime2('Thursday, July 26, 2012 - 2:48:12PM', 'l, F j, Y - g:i:sA') . "\n";
echo strptime2('February 29, 2008', 'F d, Y') . "\n"; // leap year
echo '</pre>';
<?php
/**
* A strptime() alternative.
*
* Large amounts of this code were inspired by the Drupal module Scheduler's
* _scheduler_strptime() function as well as the comment left on php.net:
* http://www.php.net/manual/en/function.strptime.php#82004
*
* @param string $time
* The string to be turned into a Unix Timestamp.
* @param string $format
* The string representing a format understood by date().
*
* @return int
* The integer that represents a Unix Timestamp or FALSE if failure.
*
* @see
* date()
*/
function strptime2($time, $format) {
// This associative array maps characters that the date() function understands
// with their regex validator.
$characters = array(
'/' => '\/',
'd' => '(\d{2})',
'D' => '(\w{3})',
'j' => '(\d{1,2})',
'l' => '(\w{6,9})',
'F' => '(\w{3,9})',
'm' => '(\d{2})',
'M' => '(\w{3})',
'n' => '(\d{1,2})',
'o' => '(\d{4})',
'Y' => '(\d{4})',
'y' => '(\d{2})',
'a' => '([ap]m)',
'A' => '([AP]M)',
'g' => '(\d{1,2})',
'G' => '(\d{1,2})',
'h' => '(\d{2})',
'H' => '(\d{2})',
'i' => '(\d{2})',
's' => '(\d{2})',
);
$format_matches = array();
// Get an array of characters that match a character the date() function can
// understand.
if (!preg_match_all('/(\w)/', $format, $format_matches)) {
return FALSE;
}
// Build a regular expression based upon the format.
$format = str_replace(array_keys($characters), array_values($characters), preg_quote($format));
// Get an array of values that match the regular expression we built.
if (!preg_match('/' . $format . '/', $time, $time_matches)) {
return FALSE;
}
$i = 0;
// We use $format_matches as a parallel array of $time_matches to get the
// actual value of each part of the $time string.
foreach ($format_matches[0] as $character) {
++$i;
switch ($character) {
case 'd':
case 'j':
$day = (int) $time_matches[$i];
break;
case 'm':
case 'n':
$month = (int) $time_matches[$i];
break;
case 'F':
case 'M':
$month_numbers = array(
'Jan' => 1,
'Feb' => 2,
'Mar' => 3,
'Apr' => 4,
'May' => 5,
'Jun' => 6,
'Jul' => 7,
'Aug' => 8,
'Sep' => 9,
'Oct' => 10,
'Nov' => 11,
'Dec' => 12,
);
$month = $month_numbers[substr($time_matches[$i], 0, 3)];
break;
case 'o':
case 'Y':
case 'y':
$year = (int) $time_matches[$i];
break;
case 'a':
case 'A':
$meridiem = strtolower($time_matches[$i]);
break;
case 'g':
case 'G':
case 'h':
case 'H':
$hour = (int) $time_matches[$i];
break;
case 'i':
$minute = (int) $time_matches[$i];
break;
case 's':
$second = (int) $time_matches[$i];
break;
}
}
// These are required to create a Unix Timestamp with mktime().
if (!isset($month) || !isset($day) || !isset($year)) {
return FALSE;
}
// A time cannot be in 24 hour format with an AM or PM as well.
if (isset($meridiem) && isset($hour) && $hour > 12) {
return FALSE;
}
// If it's PM and not 12:##PM, add 12 hours for 24 hour format.
if (isset($meridiem) && $meridiem == 'pm' && $hour < 12) {
$hour += 12;
}
// If it's 12:##am, it's 00:## in 24 hour format.
if (isset($meridiem) && $meridiem == 'am' && $hour == 12) {
$hour = 0;
}
// If mktime() failed, at this point.. this function will fail.
if (FALSE === $time = mktime(isset($hour) ? $hour : 0, isset($minute) ? $minute : 0, isset($second) ? $second : 0, $month, $day, $year)) {
return FALSE;
}
return $time;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment