diff --git a/src/ORM/FieldType/DBDatetime.php b/src/ORM/FieldType/DBDatetime.php index 877c707f260..cbc3b8e860f 100644 --- a/src/ORM/FieldType/DBDatetime.php +++ b/src/ORM/FieldType/DBDatetime.php @@ -2,6 +2,7 @@ namespace SilverStripe\ORM\FieldType; +use DateTime; use Exception; use IntlDateFormatter; use InvalidArgumentException; @@ -195,6 +196,69 @@ public function scaffoldFormField($title = null, $params = null) return $field; } + /** + * Get the amount of time inbetween two datetimes. + */ + public static function getTimeBetween(DBDateTime $from, DBDateTime $to): string + { + $fromRaw = new DateTime(); + $fromRaw->setTimestamp((int) $from->getTimestamp()); + $toRaw = new DateTime(); + $toRaw->setTimestamp((int) $to->getTimestamp()); + $diff = $fromRaw->diff($toRaw); + $result = []; + if ($diff->y) { + $result[] = _t( + __CLASS__ . '.nYears', + 'one year|{count} years', + ['count' => $diff->y] + ); + } + if ($diff->m) { + $result[] = _t( + __CLASS__ . '.nMonths', + 'one month|{count} months', + ['count' => $diff->m] + ); + } + if ($diff->d) { + $result[] = _t( + __CLASS__ . '.nDays', + 'one day|{count} days', + ['count' => $diff->d] + ); + } + if ($diff->h) { + $result[] = _t( + __CLASS__ . '.nHours', + 'one hour|{count} hours', + ['count' => $diff->h] + ); + } + if ($diff->i) { + $result[] = _t( + __CLASS__ . '.nMinutes', + 'one minute|{count} minutes', + ['count' => $diff->i] + ); + } + if ($diff->s) { + $result[] = _t( + __CLASS__ . '.nSeconds', + 'one second|{count} seconds', + ['count' => $diff->s] + ); + } + if (empty($result)) { + return _t( + __CLASS__ . '.nSeconds', + '{count} seconds', + ['count' => 0] + ); + } + return implode(', ', $result); + } + /** * */ diff --git a/tests/php/ORM/DBDatetimeTest.php b/tests/php/ORM/DBDatetimeTest.php index 71b24be225b..9196016d814 100644 --- a/tests/php/ORM/DBDatetimeTest.php +++ b/tests/php/ORM/DBDatetimeTest.php @@ -302,4 +302,50 @@ public function modifyProvider() ['-59 seconds', '2019-03-03 11:59:01'], ]; } + + public function provideGetTimeBetween(): array + { + return [ + 'no time between' => [ + 'timeBefore' => '2019-03-03 12:00:00', + 'timeAfter' => '2019-03-03 12:00:00', + 'expected' => '0 seconds', + ], + 'one second between' => [ + 'timeBefore' => '2019-03-03 12:00:00', + 'timeAfter' => '2019-03-03 12:00:01', + 'expected' => 'one second', + ], + 'some seconds between' => [ + 'timeBefore' => '2019-03-03 12:00:00', + 'timeAfter' => '2019-03-03 12:00:15', + 'expected' => '15 seconds', + ], + 'days and minutes between' => [ + 'timeBefore' => '2019-03-03 12:00:00', + 'timeAfter' => '2019-03-15 12:05:00', + 'expected' => '12 days, 5 minutes', + ], + 'years, months, and hours between' => [ + 'timeBefore' => '2019-03-03 12:00:00', + 'timeAfter' => '2028-01-03 17:00:00', + 'expected' => '8 years, 10 months, 5 hours', + ], + 'backwards in time doesnt say "negative" or "-"' => [ + 'timeBefore' => '2019-03-03 12:00:00', + 'timeAfter' => '2018-01-06 12:01:12', + 'expected' => 'one year, one month, 27 days, 23 hours, 58 minutes, 48 seconds', + ], + ]; + } + + /** + * @dataProvider provideGetTimeBetween + */ + public function testGetTimeBetween(string $timeBefore, string $timeAfter, string $expected): void + { + $before = (new DBDateTime())->setValue($timeBefore); + $after = (new DBDateTime())->setValue($timeAfter); + $this->assertSame($expected, DBDatetime::getTimeBetween($before, $after)); + } }