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); 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; $has_time = true;
$year = intval($matches[1], 10); $year = intval($matches[1], 10);
@ -538,7 +538,8 @@ function ztime($str)
if (isset($matches[7])) if (isset($matches[7]))
{ {
$has_offset = true; $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 else
{ {
@ -546,7 +547,7 @@ function ztime($str)
$offset = 0; $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); $year = intval($matches[1], 10);
$month = intval($matches[2], 10); $month = intval($matches[2], 10);
@ -555,9 +556,9 @@ function ztime($str)
{ {
$has_time = true; $has_time = true;
$hour = intval($matches[4], 10); $hour = intval($matches[4], 10);
$min = intval($matches[5], 10); $min = intval($matches[5] ?? 0, 10);
$sec = intval($matches[6], 10); $sec = intval($matches[6] ?? 0, 10);
} }
else else
{ {
$has_time = false; $has_time = false;
@ -573,14 +574,7 @@ function ztime($str)
$timestamp = gmmktime($hour, $min, $sec, $month, $day, $year); $timestamp = gmmktime($hour, $min, $sec, $month, $day, $year);
if (!$has_offset) if (!$has_offset)
{ {
if ($has_time) $offset = $has_time ? (Rhymix\Framework\Config::get('locale.internal_timezone') ?: date('Z', $timestamp)) : 0;
{
$offset = Rhymix\Framework\Config::get('locale.internal_timezone') ?: date('Z', $timestamp);
}
else
{
$offset = 0;
}
} }
return $timestamp - $offset; return $timestamp - $offset;
} }

View file

@ -51,6 +51,13 @@ class DateTimeTest extends \Codeception\TestCase\Test
Rhymix\Framework\Config::set('locale.internal_timezone', 32400); Rhymix\Framework\Config::set('locale.internal_timezone', 32400);
$this->assertEquals($timestamp, ztime('20160129015320')); $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. // Restore the internal timezone.
Rhymix\Framework\Config::set('locale.internal_timezone', 10800); 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); Rhymix\Framework\Config::set('locale.internal_timezone', 10800);
$this->assertEquals($expected, zdate('20160128195320')); $this->assertEquals($expected, zdate('20160128195320'));
$this->assertEquals($expected, zdate('2016-01-28 19:53:20')); $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')); $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. // Test zdate() when the internal time zone is the same as the default time zone.