note 71395 deleted from function.strptime by nlopess
| From: | nlopess@php.net | Date: | Mon, 05 Mar 2007 16:38:05 +0000 |
| Subject: | note 71395 deleted from function.strptime by nlopess | ||
| References: | 1 | Groups: | php.notes |
| Request: | Send a blank email to php-notes+get-124105@lists.php.net to get a copy of this message | ||
Note Submitter: marjar-4 at student dot ltu dot se
----
I wanted to parse ISO-8601 dates from GPX-files. It turned out that this wasn't the simplest
thing to do, especially on a windows system.
This is what I've come up with. Please tell me if I've missed something (other than week
format and ordinal format).
<?php
function iso8601Date($datestring) {
$iso8601_re = array(
'/^([0-9W-]{4,10})T([0-9:]{2,8})(Z|[+-][0-9:]{2,8})$/',
'/^([0-9W-]{4,10})T([0-9:]{2,8})()$/',
'/^([0-9W-]{4,10})()()$/',
'/^()([0-9:]{2,8})(Z|[+-][0-9:]{2,8})$/',
'/^()([0-9:]{2,8})()$/',
);
$date_re = array(
'/^(\d{4})-(\d\d)-(\d\d)$/',
'/^(\d{4})(\d\d)(\d\d)$/',
'/^(\d{4})-(\d\d)()$/',
'/^(\d{4})(\d\d)()$/',
'/^(\d{4})()()$/'
/* Disabled for now
'/^(\d{4})-(W\d\d)-(\d)$/',
'/^(\d{4})(W\d\d)(\d)$/',
'/^(\d{4})-W(\d\d)$/',
'/^(\d{4})W(\d\d)$/',
*/
/* Disabled for now
'/^(\d{4})-(\d{3})()$/',
'/^(\d{4})(\d{3})()$/'
*/
);
$time_re = array(
'/^(\d\d):(\d\d):(\d\d)$/',
'/^(\d\d)(\d\d)(\d\d)$/',
'/^(\d\d):(\d\d)()$/',
'/^(\d\d)(\d\d)()$/',
'/^(\d\d)()()$/'
);
$zone_re = array(
'/^(Z)()()()$/',
'/^([+-])(\d\d):(\d\d):(\d\d)$/',
'/^([+-])(\d\d)(\d\d)(\d\d)$/',
'/^([+-])(\d\d):(\d\d)()$/',
'/^([+-])(\d\d)(\d\d)()$/',
'/^([+-])(\d\d)()()$/'
);
$found = FALSE;
foreach ($iso8601_re as $re) {
$matches = array();
if (preg_match($re, $datestring, $matches)) {
$date_part = $matches[1];
$time_part = $matches[2];
$zone_part = $matches[3];
$found = TRUE;
break;
}
}
if (!$found) {
return FALSE;
}
$ftime = array(
'tm_sec' => 0,
'tm_min' => 0,
'tm_hour' => 0,
'tm_mday' => 1,
'tm_mon' => 1,
'tm_year' => 0,
);
if (strlen($date_part) > 0) {
$found = FALSE;
foreach ($date_re as $re) {
$matches = array();
if (preg_match($re, $date_part, $matches)) {
if (strlen($matches[1]) > 0)
$ftime['tm_year'] = 0 + $matches[1];
if (strlen($matches[2]) == 3 && substr($matches[2], 0, 1) == 'W') {
// TODO Week format
}
elseif (strlen($matches[2]) == 3) {
// TODO Ordinal format
}
else {
if (strlen($matches[2]) > 0)
$ftime['tm_mon'] = 0 + $matches[2];
if (strlen($matches[3]) > 0)
$ftime['tm_mday'] = 0 + $matches[3];
}
$found = TRUE;
break;
}
}
if (!$found) {
return FALSE;
}
}
if (strlen($time_part) > 0) {
$found = FALSE;
foreach ($time_re as $re) {
$matches = array();
if (preg_match($re, $time_part, $matches)) {
if (strlen($matches[1]) > 0)
$ftime['tm_hour'] = 0 + $matches[1];
if (strlen($matches[2]) > 0)
$ftime['tm_min'] = 0 + $matches[2];
if (strlen($matches[3]) > 0)
$ftime['tm_sec'] = 0 + $matches[3];
$found = TRUE;
break;
}
}
if (!$found) {
return FALSE;
}
}
if (strlen($zone_part) > 0) {
$found = FALSE;
foreach ($zone_re as $re) {
$matches = array();
if (preg_match($re, $zone_part, $matches)) {
$sign = 0;
if (strlen($matches[1]) > 0) {
if ($matches[1] == '+')
$sign = 1;
elseif ($matches[1] == '-')
$sign = -1;
else // 'Z'
$sign = 0;
}
if (strlen($matches[2]) > 0)
$ftime['tm_hour'] -= $sign * (0 + $matches[2]);
if (strlen($matches[3]) > 0)
$ftime['tm_min'] -= $sign * (0 + $matches[3]);
if (strlen($matches[4]) > 0)
$ftime['tm_sec'] -= $sign * (0 + $matches[4]);
$found = TRUE;
break;
}
}
if (!$found) {
return FALSE;
}
}
$timestamp = gmmktime(
$ftime['tm_hour'],
$ftime['tm_min'],
$ftime['tm_sec'],
$ftime['tm_mon'],
$ftime['tm_mday'],
$ftime['tm_year']
);
return $timestamp;
}
?>