Fixed saving contact birthday/anniversary dates before 01-01-1970

pull/145/merge
Aleksander Machniak 11 years ago
parent a23d446996
commit b1f3c3bee8

@ -747,40 +747,13 @@ class rcube_utils
*/
public static function strtotime($date)
{
$date = trim($date);
// check for MS Outlook vCard date format YYYYMMDD
if (preg_match('/^([12][90]\d\d)([01]\d)([0123]\d)$/', $date, $m)) {
return mktime(0,0,0, intval($m[2]), intval($m[3]), intval($m[1]));
}
// common little-endian formats, e.g. dd/mm/yyyy (not all are supported by strtotime)
if (preg_match('/^(\d{1,2})[.\/-](\d{1,2})[.\/-](\d{4})$/', $date, $m)
&& $m[1] > 0 && $m[1] <= 31 && $m[2] > 0 && $m[2] <= 12 && $m[3] >= 1970
) {
return mktime(0,0,0, intval($m[2]), intval($m[1]), intval($m[3]));
}
$date = self::clean_datestr($date);
// unix timestamp
if (is_numeric($date)) {
return (int) $date;
}
// Clean malformed data
$date = preg_replace(
array(
'/GMT\s*([+-][0-9]+)/', // support non-standard "GMTXXXX" literal
'/[^a-z0-9\x20\x09:+-]/i', // remove any invalid characters
'/\s*(Mon|Tue|Wed|Thu|Fri|Sat|Sun)\s*/i', // remove weekday names
),
array(
'\\1',
'',
'',
), $date);
$date = trim($date);
// if date parsing fails, we have a date in non-rfc format.
// remove token from the end and try again
while ((($ts = @strtotime($date)) === false) || ($ts < 0)) {
@ -809,7 +782,7 @@ class rcube_utils
}
$dt = false;
$date = trim($date);
$date = self::clean_datestr($date);
// try to parse string with DateTime first
if (!empty($date)) {
@ -834,6 +807,52 @@ class rcube_utils
return $dt;
}
/**
* Clean up date string for strtotime() input
*
* @param string $date Date string
*
* @return string Date string
*/
public static function clean_datestr($date)
{
$date = trim($date);
// check for MS Outlook vCard date format YYYYMMDD
if (preg_match('/^([12][90]\d\d)([01]\d)([0123]\d)$/', $date, $m)) {
return sprintf('%04d-%02d-%02d 00:00:00', intval($m[1]), intval($m[2]), intval($m[3]));
}
// Clean malformed data
$date = preg_replace(
array(
'/GMT\s*([+-][0-9]+)/', // support non-standard "GMTXXXX" literal
'/[^a-z0-9\x20\x09:+-\/]/i', // remove any invalid characters
'/\s*(Mon|Tue|Wed|Thu|Fri|Sat|Sun)\s*/i', // remove weekday names
),
array(
'\\1',
'',
'',
), $date);
$date = trim($date);
// try to fix dd/mm vs. mm/dd discrepancy, we can't do more here
if (preg_match('/^(\d{1,2})[.\/-](\d{1,2})[.\/-](\d{4})$/', $date, $m)) {
$mdy = $m[2] > 12 && $m[1] <= 12;
$day = $mdy ? $m[2] : $m[1];
$month = $mdy ? $m[1] : $m[2];
$date = sprintf('%04d-%02d-%02d 00:00:00', intval($m[3]), $month, $day);
}
// I've found that YYYY.MM.DD is recognized wrong, so here's a fix
else if (preg_match('/^(\d{4})\.(\d{1,2})\.(\d{1,2})$/', $date)) {
$date = str_replace('.', '-', $date) . ' 00:00:00';
}
return $date;
}
/*
* Idn_to_ascii wrapper.
* Intl/Idn modules version of this function doesn't work with e-mail address

@ -80,8 +80,8 @@ foreach ($GLOBALS['CONTACT_COLTYPES'] as $col => $colprop) {
// normalize the submitted date strings
if ($colprop['type'] == 'date') {
if ($timestamp = rcube_utils::strtotime($a_record[$col])) {
$a_record[$col] = date('Y-m-d', $timestamp);
if ($a_record[$col] && ($dt = rcube_utils::anytodatetime($a_record[$col]))) {
$a_record[$col] = $dt->format('Y-m-d');
}
else {
unset($a_record[$col]);

@ -293,6 +293,32 @@ class Framework_Utils extends PHPUnit_Framework_TestCase
}
}
/**
* rcube:utils::anytodatetime()
*/
function test_anytodatetime()
{
$test = array(
'2013-04-22' => '2013-04-22',
'2013/04/22' => '2013-04-22',
'2013.04.22' => '2013-04-22',
'22-04-2013' => '2013-04-22',
'22/04/2013' => '2013-04-22',
'22.04.2013' => '2013-04-22',
'04/22/2013' => '2013-04-22',
'22.4.2013' => '2013-04-22',
'20130422' => '2013-04-22',
'1900-10-10' => '1900-10-10',
'01-01-1900' => '1900-01-01',
'01/30/1960' => '1960-01-30'
);
foreach ($test as $datetime => $ts) {
$result = rcube_utils::anytodatetime($datetime);
$this->assertSame($ts, $result ? $result->format('Y-m-d') : '', "Error parsing date: $datetime");
}
}
/**
* rcube:utils::normalize _string()
*/

Loading…
Cancel
Save