Fix #2161 incorrect timestamp when seconds are missing or negative time zone is given

This commit is contained in:
Kijin Sung 2023-08-04 12:13:09 +09:00
parent f1a898ea50
commit 2dbdfbaadb
2 changed files with 16 additions and 15 deletions

View file

@ -526,7 +526,7 @@ function ztime($str)
{
return intval($str);
}
elseif ($len >= 19 && preg_match('/^(\d{4})-(\d{2})-(\d{2})[ T](\d{2}):(\d{2}):(\d{2})(?:[+-](\d{2}):(\d{2}))?/', $str, $matches))
elseif ($len >= 19 && preg_match('/^(\d{4})-(\d{2})-(\d{2})[ T](\d{2}):(\d{2}):(\d{2})(?:([+-])(\d{2}):(\d{2}))?/', $str, $matches))
{
$has_time = true;
$year = intval($matches[1], 10);
@ -538,7 +538,8 @@ function ztime($str)
if (isset($matches[7]))
{
$has_offset = true;
$offset = (intval($matches[7], 10) * 3600) + (intval($matches[8], 10) * 60);
$offset = (intval($matches[8], 10) * 3600) + (intval($matches[9], 10) * 60);
$offset = $offset * (($matches[7] === '+') ? 1 : -1);
}
else
{
@ -546,7 +547,7 @@ function ztime($str)
$offset = 0;
}
}
elseif (preg_match('/^(\d{4})(\d{2})(\d{2})(?:(\d{2})(\d{2})(\d{2}))?$/', $str, $matches))
elseif (preg_match('/^(\d{4})(\d{2})(\d{2})(?:(\d{2})(\d{2})?(\d{2})?)?$/', $str, $matches))
{
$year = intval($matches[1], 10);
$month = intval($matches[2], 10);
@ -555,9 +556,9 @@ function ztime($str)
{
$has_time = true;
$hour = intval($matches[4], 10);
$min = intval($matches[5], 10);
$sec = intval($matches[6], 10);
}
$min = intval($matches[5] ?? 0, 10);
$sec = intval($matches[6] ?? 0, 10);
}
else
{
$has_time = false;
@ -573,14 +574,7 @@ function ztime($str)
$timestamp = gmmktime($hour, $min, $sec, $month, $day, $year);
if (!$has_offset)
{
if ($has_time)
{
$offset = Rhymix\Framework\Config::get('locale.internal_timezone') ?: date('Z', $timestamp);
}
else
{
$offset = 0;
}
$offset = $has_time ? (Rhymix\Framework\Config::get('locale.internal_timezone') ?: date('Z', $timestamp)) : 0;
}
return $timestamp - $offset;
}

View file

@ -51,6 +51,13 @@ class DateTimeTest extends \Codeception\TestCase\Test
Rhymix\Framework\Config::set('locale.internal_timezone', 32400);
$this->assertEquals($timestamp, ztime('20160129015320'));
// Test ztime() with alternative formats.
$this->assertEquals(1576555660, ztime('2019-12-17 13:07:40'));
$this->assertEquals(1576555660, ztime('2019-12-17T13:07:40+09:00'));
$this->assertEquals(1576555660, ztime('2019-12-17T02:07:40-02:00'));
$this->assertEquals(1576555640, ztime('20191217130720'));
$this->assertEquals(1576555620, ztime('201912171307'));
// Restore the internal timezone.
Rhymix\Framework\Config::set('locale.internal_timezone', 10800);
}
@ -79,7 +86,7 @@ class DateTimeTest extends \Codeception\TestCase\Test
Rhymix\Framework\Config::set('locale.internal_timezone', 10800);
$this->assertEquals($expected, zdate('20160128195320'));
$this->assertEquals($expected, zdate('2016-01-28 19:53:20'));
$this->assertEquals($expected, zdate('2016-01-28T23:53:20-07:00'));
$this->assertEquals($expected, zdate('2016-01-28T09:53:20-07:00'));
$this->assertEquals($expected, zdate('2016-01-28 21:23:20+04:30'));
// Test zdate() when the internal time zone is the same as the default time zone.