From 9b8d5a9c1c00964a52f1647b3736073175c7a110 Mon Sep 17 00:00:00 2001 From: Alexis Saettler Date: Wed, 23 Jan 2019 10:17:29 +0100 Subject: [PATCH] fix: fix datehelper parse date (#2333) --- CHANGELOG | 1 + app/Helpers/DateHelper.php | 39 ++++-- tests/Unit/Helpers/DateHelperTest.php | 176 ++++++++++++++++++++------ 3 files changed, 167 insertions(+), 49 deletions(-) diff --git a/CHANGELOG b/CHANGELOG index f468baf8b..a15554bc8 100644 --- a/CHANGELOG +++ b/CHANGELOG @@ -20,6 +20,7 @@ Enhancements: Fixes: +* Fix DateTime parse when compact format is used * Fix contact and relationship edit with reminder enabled * Fix broken migration for the activities table * Fix VCard import with partial N entry diff --git a/app/Helpers/DateHelper.php b/app/Helpers/DateHelper.php index b58df9f21..767ee7f49 100644 --- a/app/Helpers/DateHelper.php +++ b/app/Helpers/DateHelper.php @@ -24,6 +24,8 @@ class DateHelper /** * Creates a Carbon object from DateTime format. + * If timezone is given, it parse the date with this timezone. + * Always return a date with default timezone (UTC). * * @param \DateTime|Carbon|string date * @param string timezone @@ -34,15 +36,24 @@ class DateHelper if (is_null($date)) { return; } - if ($date instanceof \DateTime) { - $date = Carbon::instance($date); - } if ($date instanceof Carbon) { - $date = $date->toDateTimeString(); + // ok + } elseif ($date instanceof \DateTime) { + $date = Carbon::instance($date); + } else { + try { + $date = Carbon::parse($date); + } catch (\Exception $e) { + // Parse error + return; + } } - $date = Carbon::createFromFormat('Y-m-d H:i:s', $date, config('app.timezone')); - if ($timezone !== null) { - $date->setTimezone($timezone); + + $date = Carbon::create($date->year, $date->month, $date->day, $date->hour, $date->minute, $date->second, $timezone ?? $date->timezone); + + $appTimezone = config('app.timezone'); + if ($date->timezone !== $appTimezone) { + $date->setTimezone($appTimezone); } return $date; @@ -50,8 +61,11 @@ class DateHelper /** * Creates a Carbon object from Date format. + * If timezone is given, it parse the date with this timezone. + * Always return a date with default timezone (UTC). * - * @param string date + * @param Carbon|string date + * @param string timezone * @return Carbon */ public static function parseDate($date, $timezone = null) @@ -64,9 +78,12 @@ class DateHelper return; } } - $date = Carbon::create($date->year, $date->month, $date->day, 0, 0, 0, config('app.timezone')); - if ($timezone !== null) { - $date->setTimezone($timezone); + + $date = Carbon::create($date->year, $date->month, $date->day, 0, 0, 0, $timezone ?? $date->timezone); + + $appTimezone = config('app.timezone'); + if ($date->timezone !== $appTimezone) { + $date->setTimezone($appTimezone); } return $date; diff --git a/tests/Unit/Helpers/DateHelperTest.php b/tests/Unit/Helpers/DateHelperTest.php index 58f8f1d9e..3cdd4dd8a 100644 --- a/tests/Unit/Helpers/DateHelperTest.php +++ b/tests/Unit/Helpers/DateHelperTest.php @@ -12,16 +12,6 @@ class DateHelperTest extends FeatureTestCase { use DatabaseTransactions; - public function testParseDateTime() - { - $date = '2017-01-22 17:56:03'; - $timezone = 'America/New_York'; - - $testDate = DateHelper::parseDateTime($date, $timezone); - - $this->assertInstanceOf(Carbon::class, $testDate); - } - public function testGetShortDateWithEnglishLocale() { $date = '2017-01-22 17:56:03'; @@ -127,68 +117,178 @@ class DateHelperTest extends FeatureTestCase public function test_add_time_according_to_frequency_type_returns_the_right_value() { $date = '2017-01-22 17:56:03'; - $timezone = 'America/New_York'; - $testDate = DateHelper::parseDateTime($date, $timezone); + $testDate = DateHelper::parseDateTime($date); $this->assertEquals( '2017-01-29', DateHelper::addTimeAccordingToFrequencyType($testDate, 'week', 1)->toDateString() ); - $testDate = DateHelper::parseDateTime($date, $timezone); + $testDate = DateHelper::parseDateTime($date); $this->assertEquals( '2017-02-22', DateHelper::addTimeAccordingToFrequencyType($testDate, 'month', 1)->toDateString() ); - $testDate = DateHelper::parseDateTime($date, $timezone); + $testDate = DateHelper::parseDateTime($date); $this->assertEquals( '2018-01-22', DateHelper::addTimeAccordingToFrequencyType($testDate, 'year', 1)->toDateString() ); } - public function test_datetime_parse_timezone() + public function test_parse_dateTime() { - $date = '2018-01-01 00:01:00'; - $timezone = 'America/New_York'; + $date = '2017-01-22 17:56:03'; $testDate = DateHelper::parseDateTime($date); + + $this->assertInstanceOf(Carbon::class, $testDate); + } + + public function test_parse_dateTime_format() + { + $date = '20190120T232144Z'; + + $testDate = DateHelper::parseDateTime($date); + + $this->assertEquals(2019, $testDate->year); + $this->assertEquals(1, $testDate->month); + $this->assertEquals(20, $testDate->day); + $this->assertEquals(23, $testDate->hour); + $this->assertEquals(21, $testDate->minute); + $this->assertEquals(44, $testDate->second); + $this->assertEquals('UTC', $testDate->timezone->getName()); + $this->assertEquals( - '2018-01-01', + '2019-01-20', $testDate->toDateString() ); $this->assertEquals( - '2018-01-01T00:01:00Z', + '2019-01-20T23:21:44Z', DateHelper::getTimestamp($testDate) ); - - $testDate2 = DateHelper::parseDateTime($testDate, $timezone); - $this->assertEquals( - '2017-12-31', - $testDate2->toDateString() - ); - $this->assertEquals( - '2017-12-31T19:01:00Z', - DateHelper::getTimestamp($testDate2) - ); } - public function test_date_parse_timezone() + public function test_parse_dateTime_utc() { - $date = '2018-01-01 00:01:00'; - $timezone = 'America/New_York'; + $date = '2017-01-22 17:56:03'; + + $testDate = DateHelper::parseDateTime($date); + + $this->assertEquals(2017, $testDate->year); + $this->assertEquals(1, $testDate->month); + $this->assertEquals(22, $testDate->day); + $this->assertEquals(17, $testDate->hour); + $this->assertEquals(56, $testDate->minute); + $this->assertEquals(03, $testDate->second); + $this->assertEquals('UTC', $testDate->timezone->getName()); - $testDate = DateHelper::parseDate($date); $this->assertEquals( - '2018-01-01', + '2017-01-22', $testDate->toDateString() ); - - $testDate2 = DateHelper::parseDate($testDate, $timezone); $this->assertEquals( - '2017-12-31', - $testDate2->toDateString() + '2017-01-22T17:56:03Z', + DateHelper::getTimestamp($testDate) + ); + } + + public function test_parse_dateTime_new_york() + { + $date = '2017-01-22 17:56:03'; + $timezone = 'America/New_York'; + + $testDate = DateHelper::parseDateTime($date, $timezone); + + $this->assertEquals(2017, $testDate->year); + $this->assertEquals(1, $testDate->month); + $this->assertEquals(22, $testDate->day); + $this->assertEquals(22, $testDate->hour); + $this->assertEquals(56, $testDate->minute); + $this->assertEquals(03, $testDate->second); + $this->assertEquals('UTC', $testDate->timezone->getName()); + + $this->assertEquals( + '2017-01-22', + $testDate->toDateString() + ); + $this->assertEquals( + '2017-01-22T22:56:03Z', + DateHelper::getTimestamp($testDate) + ); + } + + public function test_parse_dateTime_paris() + { + $date = '2019-01-01 00:56:03'; + $timezone = 'Europe/Paris'; + + $testDate = DateHelper::parseDateTime($date, $timezone); + + $this->assertEquals(2018, $testDate->year); + $this->assertEquals(12, $testDate->month); + $this->assertEquals(31, $testDate->day); + $this->assertEquals(23, $testDate->hour); + $this->assertEquals(56, $testDate->minute); + $this->assertEquals(03, $testDate->second); + $this->assertEquals('UTC', $testDate->timezone->getName()); + + $this->assertEquals( + '2018-12-31', + $testDate->toDateString() + ); + $this->assertEquals( + '2018-12-31T23:56:03Z', + DateHelper::getTimestamp($testDate) + ); + } + + public function test_parse_dateTime_carbon() + { + $date = new Carbon('2019-01-01 00:56:03', 'Europe/Paris'); + + $testDate = DateHelper::parseDateTime($date); + + $this->assertEquals(2018, $testDate->year); + $this->assertEquals(12, $testDate->month); + $this->assertEquals(31, $testDate->day); + $this->assertEquals(23, $testDate->hour); + $this->assertEquals(56, $testDate->minute); + $this->assertEquals(03, $testDate->second); + $this->assertEquals('UTC', $testDate->timezone->getName()); + + $this->assertEquals( + '2018-12-31', + $testDate->toDateString() + ); + $this->assertEquals( + '2018-12-31T23:56:03Z', + DateHelper::getTimestamp($testDate) + ); + } + + public function test_parse_dateTime_dateTimeObject() + { + $date = new \DateTime('2019-01-01 00:56:03', new \DateTimeZone('Europe/Paris')); + + $testDate = DateHelper::parseDateTime($date); + + $this->assertEquals(2018, $testDate->year); + $this->assertEquals(12, $testDate->month); + $this->assertEquals(31, $testDate->day); + $this->assertEquals(23, $testDate->hour); + $this->assertEquals(56, $testDate->minute); + $this->assertEquals(03, $testDate->second); + $this->assertEquals('UTC', $testDate->timezone->getName()); + + $this->assertEquals( + '2018-12-31', + $testDate->toDateString() + ); + $this->assertEquals( + '2018-12-31T23:56:03Z', + DateHelper::getTimestamp($testDate) ); }