diff --git a/core/lib/Drupal/Component/Datetime/DateTimePlus.php b/core/lib/Drupal/Component/Datetime/DateTimePlus.php index 1d8bbb77ff4b0c7f721fff4c7b160d098f18a3e7..1d71ae6b384658c0ea7937c61092979d11f13ab6 100644 --- a/core/lib/Drupal/Component/Datetime/DateTimePlus.php +++ b/core/lib/Drupal/Component/Datetime/DateTimePlus.php @@ -294,6 +294,30 @@ public function __call($method, $args) { return call_user_func_array(array($this->dateTimeObject, $method), $args); } + /** + * Returns the difference between two DateTimePlus objects. + * + * @param \Drupal\Component\Datetime\DateTimePlus|\DateTime $datetime2 + * The date to compare to. + * @param bool $absolute + * Should the interval be forced to be positive? + * + * @return \DateInterval + * A DateInterval object representing the difference between the two dates. + * + * @throws \BadMethodCallException + * If the input isn't a DateTime or DateTimePlus object. + */ + public function diff($datetime2, $absolute = FALSE) { + if ($datetime2 instanceof DateTimePlus) { + $datetime2 = $datetime2->dateTimeObject; + } + if (!($datetime2 instanceof \DateTime)) { + throw new \BadMethodCallException(sprintf('Method %s expects parameter 1 to be a \DateTime or \Drupal\Component\Datetime\DateTimePlus object', __METHOD__)); + } + return $this->dateTimeObject->diff($datetime2, $absolute); + } + /** * Implements the magic __callStatic method. * diff --git a/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php b/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php index 7f5e200caea67deeff71cac88b150d16bab4c391..d4cd751e5836f3a767e84c58b4f71d2366a7bda3 100644 --- a/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php +++ b/core/tests/Drupal/Tests/Component/Datetime/DateTimePlusTest.php @@ -55,6 +55,42 @@ public function testDateArrays($input, $timezone, $expected) { $this->assertEquals($expected, $value, sprintf("Test new DateTimePlus(%s, %s): should be %s, found %s.", $input, $timezone, $expected, $value)); } + /** + * Test date diffs. + * + * @param mixed $input1 + * A DateTimePlus object. + * @param mixed $input2 + * Date argument for DateTimePlus::diff method. + * @param bool $absolute + * Absolute flag for DateTimePlus::diff method. + * @param \DateInterval $expected + * The expected result of the DateTimePlus::diff operation. + * + * @dataProvider providerTestDateDiff + */ + public function testDateDiff($input1, $input2, $absolute, \DateInterval $expected) { + $interval = $input1->diff($input2, $absolute); + $this->assertEquals($interval, $expected); + } + + /** + * Test date diff exception caused by invalid input. + * + * @param mixed $input1 + * A DateTimePlus object. + * @param mixed $input2 + * Date argument for DateTimePlus::diff method. + * @param bool $absolute + * Absolute flag for DateTimePlus::diff method. + * + * @dataProvider providerTestInvalidDateDiff + */ + public function testInvalidDateDiff($input1, $input2, $absolute) { + $this->setExpectedException(\BadMethodCallException::class, 'Method Drupal\Component\Datetime\DateTimePlus::diff expects parameter 1 to be a \DateTime or \Drupal\Component\Datetime\DateTimePlus object'); + $interval = $input1->diff($input2, $absolute); + } + /** * Test creating dates from invalid array input. * @@ -528,4 +564,106 @@ public function providerTestDateTimestamp() { ); } + /** + * Provides data for date tests. + * + * @return array + * An array of arrays, each containing the input parameters for + * DateTimePlusTest::testDateDiff(). + * + * @see DateTimePlusTest::testDateDiff() + */ + public function providerTestDateDiff() { + + $empty_interval = new \DateInterval('PT0S'); + + $positive_19_hours = new \DateInterval('PT19H'); + + $positive_18_hours = new \DateInterval('PT18H'); + + $positive_1_hour = new \DateInterval('PT1H'); + + $negative_1_hour = new \DateInterval('PT1H'); + $negative_1_hour->invert = 1; + + return array( + // There should be a 19 hour time interval between + // new years in Sydney and new years in LA in year 2000. + array( + 'input2' => DateTimePlus::createFromFormat('Y-m-d H:i:s', '2000-01-01 00:00:00', new \DateTimeZone('Australia/Sydney')), + 'input1' => DateTimePlus::createFromFormat('Y-m-d H:i:s', '2000-01-01 00:00:00', new \DateTimeZone('America/Los_Angeles')), + 'absolute' => FALSE, + 'expected' => $positive_19_hours, + ), + // In 1970 Sydney did not observe daylight savings time + // So there is only a 18 hour time interval. + array( + 'input2' => DateTimePlus::createFromFormat('Y-m-d H:i:s', '1970-01-01 00:00:00', new \DateTimeZone('Australia/Sydney')), + 'input1' => DateTimePlus::createFromFormat('Y-m-d H:i:s', '1970-01-01 00:00:00', new \DateTimeZone('America/Los_Angeles')), + 'absolute' => FALSE, + 'expected' => $positive_18_hours, + ), + array( + 'input1' => DateTimePlus::createFromFormat('U', 3600, new \DateTimeZone('America/Los_Angeles')), + 'input2' => DateTimePlus::createFromFormat('U', 0, new \DateTimeZone('UTC')), + 'absolute' => FALSE, + 'expected' => $negative_1_hour, + ), + array( + 'input1' => DateTimePlus::createFromFormat('U', 3600), + 'input2' => DateTimePlus::createFromFormat('U', 0), + 'absolute' => FALSE, + 'expected' => $negative_1_hour, + ), + array( + 'input1' => DateTimePlus::createFromFormat('U', 3600), + 'input2' => \DateTime::createFromFormat('U', 0), + 'absolute' => FALSE, + 'expected' => $negative_1_hour, + ), + array( + 'input1' => DateTimePlus::createFromFormat('U', 3600), + 'input2' => DateTimePlus::createFromFormat('U', 0), + 'absolute' => TRUE, + 'expected' => $positive_1_hour, + ), + array( + 'input1' => DateTimePlus::createFromFormat('U', 3600), + 'input2' => \DateTime::createFromFormat('U', 0), + 'absolute' => TRUE, + 'expected' => $positive_1_hour, + ), + array( + 'input1' => DateTimePlus::createFromFormat('U', 0), + 'input2' => DateTimePlus::createFromFormat('U', 0), + 'absolute' => FALSE, + 'expected' => $empty_interval, + ), + ); + } + + /** + * Provides data for date tests. + * + * @return array + * An array of arrays, each containing the input parameters for + * DateTimePlusTest::testInvalidDateDiff(). + * + * @see DateTimePlusTest::testInvalidDateDiff() + */ + public function providerTestInvalidDateDiff() { + return array( + array( + 'input1' => DateTimePlus::createFromFormat('U', 3600), + 'input2' => '1970-01-01 00:00:00', + 'absolute' => FALSE, + ), + array( + 'input1' => DateTimePlus::createFromFormat('U', 3600), + 'input2' => NULL, + 'absolute' => FALSE, + ), + ); + } + } diff --git a/core/tests/Drupal/Tests/Core/Datetime/DrupalDateTimeTest.php b/core/tests/Drupal/Tests/Core/Datetime/DrupalDateTimeTest.php new file mode 100644 index 0000000000000000000000000000000000000000..e77542bc7b55f05d988bd7b30c24426441bacd68 --- /dev/null +++ b/core/tests/Drupal/Tests/Core/Datetime/DrupalDateTimeTest.php @@ -0,0 +1,159 @@ +diff($input2, $absolute); + $this->assertEquals($interval, $expected); + } + + /** + * Test date diff exception caused by invalid input. + * + * @param mixed $input1 + * A DateTimePlus object. + * @param mixed $input2 + * Date argument for DateTimePlus::diff method. + * @param bool $absolute + * Absolute flag for DateTimePlus::diff method. + * + * @dataProvider providerTestInvalidDateDiff + */ + public function testInvalidDateDiff($input1, $input2, $absolute) { + $this->setExpectedException(\BadMethodCallException::class, 'Method Drupal\Component\Datetime\DateTimePlus::diff expects parameter 1 to be a \DateTime or \Drupal\Component\Datetime\DateTimePlus object'); + $interval = $input1->diff($input2, $absolute); + } + + /** + * Provides data for date tests. + * + * @return array + * An array of arrays, each containing the input parameters for + * DrupalDateTimeTest::testDateDiff(). + * + * @see DrupalDateTimeTest::testDateDiff() + */ + public function providerTestDateDiff() { + + $settings = ['langcode' => 'en']; + + $utc_tz = new \DateTimeZone('UTC'); + + $empty_interval = new \DateInterval('PT0S'); + + $positive_19_hours = new \DateInterval('PT19H'); + + $positive_18_hours = new \DateInterval('PT18H'); + + $positive_1_hour = new \DateInterval('PT1H'); + + $negative_1_hour = new \DateInterval('PT1H'); + $negative_1_hour->invert = 1; + + return array( + + // There should be a 19 hour time interval between + // new years in Sydney and new years in LA in year 2000. + array( + 'input2' => DrupalDateTime::createFromFormat('Y-m-d H:i:s', '2000-01-01 00:00:00', new \DateTimeZone('Australia/Sydney'), $settings), + 'input1' => DrupalDateTime::createFromFormat('Y-m-d H:i:s', '2000-01-01 00:00:00', new \DateTimeZone('America/Los_Angeles'), $settings), + 'absolute' => FALSE, + 'expected' => $positive_19_hours, + ), + // In 1970 Sydney did not observe daylight savings time + // So there is only a 18 hour time interval. + array( + 'input2' => DrupalDateTime::createFromFormat('Y-m-d H:i:s', '1970-01-01 00:00:00', new \DateTimeZone('Australia/Sydney'), $settings), + 'input1' => DrupalDateTime::createFromFormat('Y-m-d H:i:s', '1970-01-01 00:00:00', new \DateTimeZone('America/Los_Angeles'), $settings), + 'absolute' => FALSE, + 'expected' => $positive_18_hours, + ), + array( + 'input1' => DrupalDateTime::createFromFormat('U', 3600, new \DateTimeZone('America/Los_Angeles'), $settings), + 'input2' => DrupalDateTime::createFromFormat('U', 0, $utc_tz, $settings), + 'absolute' => FALSE, + 'expected' => $negative_1_hour, + ), + array( + 'input1' => DrupalDateTime::createFromFormat('U', 3600, $utc_tz, $settings), + 'input2' => DrupalDateTime::createFromFormat('U', 0, $utc_tz, $settings), + 'absolute' => FALSE, + 'expected' => $negative_1_hour, + ), + array( + 'input1' => DrupalDateTime::createFromFormat('U', 3600, $utc_tz, $settings), + 'input2' => \DateTime::createFromFormat('U', 0), + 'absolute' => FALSE, + 'expected' => $negative_1_hour, + ), + array( + 'input1' => DrupalDateTime::createFromFormat('U', 3600, $utc_tz, $settings), + 'input2' => DrupalDateTime::createFromFormat('U', 0, $utc_tz, $settings), + 'absolute' => TRUE, + 'expected' => $positive_1_hour, + ), + array( + 'input1' => DrupalDateTime::createFromFormat('U', 3600, $utc_tz, $settings), + 'input2' => \DateTime::createFromFormat('U', 0), + 'absolute' => TRUE, + 'expected' => $positive_1_hour, + ), + array( + 'input1' => DrupalDateTime::createFromFormat('U', 0, $utc_tz, $settings), + 'input2' => DrupalDateTime::createFromFormat('U', 0, $utc_tz, $settings), + 'absolute' => FALSE, + 'expected' => $empty_interval, + ), + ); + } + + /** + * Provides data for date tests. + * + * @return array + * An array of arrays, each containing the input parameters for + * DateTimePlusTest::testInvalidDateDiff(). + * + * @see DateTimePlusTest::testInvalidDateDiff() + */ + public function providerTestInvalidDateDiff() { + $settings = ['langcode' => 'en']; + $utc_tz = new \DateTimeZone('UTC'); + return array( + array( + 'input1' => DrupalDateTime::createFromFormat('U', 3600, $utc_tz, $settings), + 'input2' => '1970-01-01 00:00:00', + 'absolute' => FALSE, + ), + array( + 'input1' => DrupalDateTime::createFromFormat('U', 3600, $utc_tz, $settings), + 'input2' => NULL, + 'absolute' => FALSE, + ), + ); + } + +}