From 2dbdfbaadb3f21c7a01dd8e78ac21d52b9b6cb4e Mon Sep 17 00:00:00 2001 From: Kijin Sung Date: Fri, 4 Aug 2023 12:13:09 +0900 Subject: [PATCH] Fix #2161 incorrect timestamp when seconds are missing or negative time zone is given --- common/legacy.php | 22 ++++++++-------------- tests/unit/framework/DateTimeTest.php | 9 ++++++++- 2 files changed, 16 insertions(+), 15 deletions(-) diff --git a/common/legacy.php b/common/legacy.php index 6a35e076c..9270979fa 100644 --- a/common/legacy.php +++ b/common/legacy.php @@ -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; } diff --git a/tests/unit/framework/DateTimeTest.php b/tests/unit/framework/DateTimeTest.php index 60fd05705..4cb6b7994 100644 --- a/tests/unit/framework/DateTimeTest.php +++ b/tests/unit/framework/DateTimeTest.php @@ -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.