Skip to content

Commit

Permalink
Merge pull request #285 from cakephp/cleanup-ignoretimezone
Browse files Browse the repository at this point in the history
Cleanup diffInMonthsIgnoreTimezone and tests
  • Loading branch information
othercorey committed Feb 6, 2021
2 parents d635099 + 509321a commit 5929b74
Show file tree
Hide file tree
Showing 3 changed files with 23 additions and 30 deletions.
8 changes: 4 additions & 4 deletions phpstan-baseline.neon
Original file line number Diff line number Diff line change
Expand Up @@ -12,21 +12,21 @@ parameters:

-
message: "#^Unsafe usage of new static\\(\\)\\.$#"
count: 11
count: 13
path: src/Chronos.php

-
message: "#^Unsafe usage of new static\\(\\)\\.$#"
count: 11
count: 13
path: src/Date.php

-
message: "#^Unsafe usage of new static\\(\\)\\.$#"
count: 11
count: 13
path: src/MutableDate.php

-
message: "#^Unsafe usage of new static\\(\\)\\.$#"
count: 11
count: 13
path: src/MutableDateTime.php

21 changes: 6 additions & 15 deletions src/Traits/DifferenceTrait.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@
use Cake\Chronos\DifferenceFormatter;
use Cake\Chronos\DifferenceFormatterInterface;
use DatePeriod;
use DateTime;
use DateTimeInterface;
use DateTimeZone;

Expand Down Expand Up @@ -71,8 +70,9 @@ public function diffInMonths(?ChronosInterface $dt = null, bool $abs = true): in
}

/**
* Get the difference in months without converting times to UTC which can cause
* a the month to change.
* Get the difference in months ignoring the timezone. This means the months are calculated
* in the specified timezone without converting to UTC first. This prevents the day from changing
* which can change the month.
*
* For example, if comparing `2019-06-01 Asia/Tokyo` and `2019-10-01 Asia/Tokyo`,
* the result would be 4 months instead of 3 when using normal `DateTime::diff()`.
Expand All @@ -84,21 +84,12 @@ public function diffInMonths(?ChronosInterface $dt = null, bool $abs = true): in
public function diffInMonthsIgnoreTimezone(?ChronosInterface $dt = null, bool $abs = true): int
{
$utcTz = new DateTimeZone('UTC');

$source = $this;
if ($this->getTimezone()->getName() !== 'UTC') {
$source = new DateTime($this->format('Y-m-d H:i:s.u'), $utcTz);
}
$source = new static($this->format('Y-m-d H:i:s.u'), $utcTz);

$dt = $dt ?? static::now($this->tz);
if ($dt->getTimezone()->getName() !== 'UTC') {
$dt = new DateTime($dt->format('Y-m-d H:i:s.u'), $utcTz);
}
$dt = new static($dt->format('Y-m-d H:i:s.u'), $utcTz);

$diff = $this->diff($dt ?? static::now($this->tz), $abs);
$months = $diff->y * ChronosInterface::MONTHS_PER_YEAR + $diff->m;

return $diff->invert ? -$months : $months;
return $this->diffInMonths($dt, $abs);
}

/**
Expand Down
24 changes: 13 additions & 11 deletions tests/TestCase/DateTime/DiffTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -134,17 +134,19 @@ public function testDiffInMonthsEnsureIsTruncated($class)
*/
public function testDiffInMonthsIgnoreTimezone($class)
{
$source = $class::createFromDate(2019, 06, 01, 'Asia/Tokyo');
$target = $class::createFromDate(2019, 10, 01, 'Asia/Tokyo');
$this->assertSame(4, $source->diffInMonthsIgnoreTimezone($target));

$source = $class::createFromDate(2019, 06, 01, 'UTC');
$target = $class::createFromDate(2019, 10, 01, 'UTC');
$this->assertSame(4, $source->diffInMonthsIgnoreTimezone($target));

$source = $class::createFromDate(2019, 06, 01, 'UTC');
$target = $class::createFromDate(2019, 10, 01, 'Asia/Tokyo');
$this->assertSame(4, $source->diffInMonthsIgnoreTimezone($target));
$start = $class::createFromDate(2019, 06, 01, 'Asia/Tokyo');
foreach ([1, 2, 3, 4, 5] as $monthOffset) {
$end = $class::createFromDate(2019, 6 + $monthOffset, 01, 'Asia/Tokyo');
$this->assertSame($monthOffset, $start->diffInMonthsIgnoreTimezone($end));
}

$start = $class::createFromDate(2019, 06, 01, 'UTC');
$end = $class::createFromDate(2019, 10, 01, 'UTC');
$this->assertSame(4, $start->diffInMonthsIgnoreTimezone($end));

$start = $class::createFromDate(2019, 06, 01, 'UTC');
$end = $class::createFromDate(2019, 10, 01, 'Asia/Tokyo');
$this->assertSame(4, $start->diffInMonthsIgnoreTimezone($end));

$this->wrapWithTestNow(function () use ($class) {
$this->assertSame(1, $class::now()->subMonth()->startOfMonth()->diffInMonthsIgnoreTimezone());
Expand Down

0 comments on commit 5929b74

Please sign in to comment.