diff --git a/CHANGELOG.rst b/CHANGELOG.rst index bb6c11b..413537f 100644 --- a/CHANGELOG.rst +++ b/CHANGELOG.rst @@ -7,6 +7,7 @@ CHANGELOG * Fix descendant shortcut operator '//' * Fix text() function * Fix typed select of '(name)' token +* Fix 24-hour time for DateTime `v1.2.1`_ (2019-08-30) ====================== diff --git a/elementpath/datatypes.py b/elementpath/datatypes.py index fca89ef..ea08fe9 100644 --- a/elementpath/datatypes.py +++ b/elementpath/datatypes.py @@ -187,7 +187,10 @@ class AbstractDateTime(object): def __init__(self, year=2000, month=1, day=1, hour=0, minute=0, second=0, microsecond=0, tzinfo=None): if hour == 24 and minute == second == 0: + delta = datetime.timedelta(days=1) hour = 0 + else: + delta = 0 if 1 <= year <= 9999: self._year = None @@ -203,6 +206,9 @@ class AbstractDateTime(object): else: self._dt = datetime.datetime(6, month, day, hour, minute, second, microsecond, tzinfo) + if delta: + self._dt += delta + def __repr__(self): fields = self._pattern.groupindex.keys() arg_string = ', '.join( @@ -662,6 +668,8 @@ class Time(AbstractDateTime): r'(?PZ|[+-](?:(?:0[0-9]|1[0-3]):[0-5][0-9]|14:00))?$') def __init__(self, hour=0, minute=0, second=0, microsecond=0, tzinfo=None): + if hour == 24 and minute == second == 0: + hour = 0 super(Time, self).__init__(hour=hour, minute=minute, second=second, microsecond=microsecond, tzinfo=tzinfo) def __str__(self): diff --git a/tests/test_datatypes.py b/tests/test_datatypes.py index 64c0b27..a5fbca2 100644 --- a/tests/test_datatypes.py +++ b/tests/test_datatypes.py @@ -142,6 +142,10 @@ class DateTimeTypesTest(unittest.TestCase): "tzinfo=Timezone(datetime.timedelta(-1, 72000)))") self.assertEqual(str(dt), '-0100-04-13T10:30:00-04:00') + def test_24_hour_datetime(self): + dt = DateTime.fromstring('0000-09-19T24:00:00Z') + self.assertEqual(str(dt), '0000-09-20T00:00:00Z') + def test_date_repr(self): dt = Date.fromstring('2000-10-07') self.assertEqual(repr(dt), "Date(2000, 10, 7)") @@ -214,18 +218,18 @@ class DateTimeTypesTest(unittest.TestCase): self.assertFalse(mkdt("2002-04-02T12:00:00") == mkdt("2002-04-02T17:00:00")) self.assertTrue(mkdt("2002-04-02T12:00:00") == mkdt("2002-04-02T12:00:00")) self.assertTrue(mkdt("2002-04-02T23:00:00-04:00") == mkdt("2002-04-03T02:00:00-01:00")) - self.assertTrue(mkdt("1999-12-31T24:00:00") == mkdt("1999-12-31T00:00:00")) - self.assertTrue(mkdt("2005-04-04T24:00:00") == mkdt("2005-04-04T00:00:00")) + self.assertTrue(mkdt("1999-12-31T24:00:00") == mkdt("2000-01-01T00:00:00")) + self.assertTrue(mkdt("2005-04-04T24:00:00") == mkdt("2005-04-05T00:00:00")) self.assertTrue(mkdt("2002-04-02T12:00:00-01:00", tz) == mkdt("2002-04-02T17:00:00+04:00", tz)) self.assertTrue(mkdt("2002-04-02T12:00:00", tz) == mkdt("2002-04-02T23:00:00+06:00", tz)) self.assertFalse(mkdt("2002-04-02T12:00:00", tz) == mkdt("2002-04-02T17:00:00", tz)) self.assertTrue(mkdt("2002-04-02T12:00:00", tz) == mkdt("2002-04-02T12:00:00", tz)) self.assertTrue(mkdt("2002-04-02T23:00:00-04:00", tz) == mkdt("2002-04-03T02:00:00-01:00", tz)) - self.assertTrue(mkdt("1999-12-31T24:00:00", tz) == mkdt("1999-12-31T00:00:00", tz)) - self.assertTrue(mkdt("2005-04-04T24:00:00", tz) == mkdt("2005-04-04T00:00:00", tz)) + self.assertTrue(mkdt("1999-12-31T24:00:00", tz) == mkdt("2000-01-01T00:00:00", tz)) - self.assertFalse(mkdt("2005-04-04T24:00:00", tz) != mkdt("2005-04-04T00:00:00", tz)) + self.assertTrue(mkdt("2005-04-04T24:00:00", tz) == mkdt("2005-04-05T00:00:00", tz)) + self.assertFalse(mkdt("2005-04-04T24:00:00", tz) != mkdt("2005-04-05T00:00:00", tz)) self.assertTrue(DateTime.fromstring("-1000-01-01") == DateTime.fromstring("-1000-01-01")) self.assertTrue(DateTime.fromstring("-10000-01-01") == DateTime.fromstring("-10000-01-01")) diff --git a/tests/test_xpath2_parser.py b/tests/test_xpath2_parser.py index 58c0ed4..1f632a4 100644 --- a/tests/test_xpath2_parser.py +++ b/tests/test_xpath2_parser.py @@ -791,7 +791,7 @@ class XPath2ParserTest(test_xpath1_parser.XPath1ParserTest): ) self.check_value('xs:dateTime("2000-05-10T21:30:00+05:24")', datetime.datetime(2000, 5, 10, hour=21, minute=30, tzinfo=tz1)) - self.check_value('xs:dateTime("1999-12-31T24:00:00")', datetime.datetime(1999, 12, 31, 0, 0, tzinfo=tz0)) + self.check_value('xs:dateTime("1999-12-31T24:00:00")', datetime.datetime(2000, 1, 1, 0, 0, tzinfo=tz0)) self.wrong_value('xs:dateTime("2000-05-10t21:30:00+05:24")') self.wrong_value('xs:dateTime("2000-5-10T21:30:00+05:24")') @@ -850,7 +850,7 @@ class XPath2ParserTest(test_xpath1_parser.XPath1ParserTest): self.check_value('fn:year-from-dateTime(xs:dateTime("1999-05-31T13:20:00-05:00"))', 1999) self.check_value('fn:year-from-dateTime(xs:dateTime("1999-05-31T21:30:00-05:00"))', 1999) self.check_value('fn:year-from-dateTime(xs:dateTime("1999-12-31T19:20:00"))', 1999) - self.check_value('fn:year-from-dateTime(xs:dateTime("1999-12-31T24:00:00"))', 1999) + self.check_value('fn:year-from-dateTime(xs:dateTime("1999-12-31T24:00:00"))', 2000) def test_month_from_datetime_function(self): self.check_value('fn:month-from-dateTime(xs:dateTime("1999-05-31T13:20:00-05:00"))', 5)