diff options
Diffstat (limited to 'tests/parsing')
-rw-r--r-- | tests/parsing/__init__.py | 0 | ||||
-rw-r--r-- | tests/parsing/test_parse_iso8601.py | 465 | ||||
-rw-r--r-- | tests/parsing/test_parsing.py | 687 | ||||
-rw-r--r-- | tests/parsing/test_parsing_duration.py | 298 |
4 files changed, 1450 insertions, 0 deletions
diff --git a/tests/parsing/__init__.py b/tests/parsing/__init__.py new file mode 100644 index 0000000..e69de29 --- /dev/null +++ b/tests/parsing/__init__.py diff --git a/tests/parsing/test_parse_iso8601.py b/tests/parsing/test_parse_iso8601.py new file mode 100644 index 0000000..0047791 --- /dev/null +++ b/tests/parsing/test_parse_iso8601.py @@ -0,0 +1,465 @@ +from __future__ import annotations + +from datetime import date +from datetime import datetime +from datetime import time + +import pytest + +from pendulum.parsing import parse_iso8601 + +try: + from pendulum.parsing._extension import TZFixedOffset as FixedTimezone +except ImportError: + from pendulum.tz.timezone import FixedTimezone + + +def test_parse_iso8601(): + # Date + assert date(2016, 1, 1) == parse_iso8601("2016") + assert date(2016, 10, 1) == parse_iso8601("2016-10") + assert date(2016, 10, 6) == parse_iso8601("2016-10-06") + assert date(2016, 10, 6) == parse_iso8601("20161006") + + # Time + assert time(20, 16, 10, 0) == parse_iso8601("201610") + + # Datetime + assert datetime(2016, 10, 6, 12, 34, 56, 123456) == parse_iso8601( + "2016-10-06T12:34:56.123456" + ) + assert datetime(2016, 10, 6, 12, 34, 56, 123000) == parse_iso8601( + "2016-10-06T12:34:56.123" + ) + assert datetime(2016, 10, 6, 12, 34, 56, 123) == parse_iso8601( + "2016-10-06T12:34:56.000123" + ) + assert datetime(2016, 10, 6, 12, 0, 0, 0) == parse_iso8601("2016-10-06T12") + assert datetime(2016, 10, 6, 12, 34, 56, 0) == parse_iso8601("2016-10-06T123456") + assert datetime(2016, 10, 6, 12, 34, 56, 123456) == parse_iso8601( + "2016-10-06T123456.123456" + ) + assert datetime(2016, 10, 6, 12, 34, 56, 123456) == parse_iso8601( + "20161006T123456.123456" + ) + assert datetime(2016, 10, 6, 12, 34, 56, 123456) == parse_iso8601( + "20161006 123456.123456" + ) + + # Datetime with offset + assert datetime( + 2016, 10, 6, 12, 34, 56, 123456, FixedTimezone(19800) + ) == parse_iso8601("2016-10-06T12:34:56.123456+05:30") + assert datetime( + 2016, 10, 6, 12, 34, 56, 123456, FixedTimezone(19800) + ) == parse_iso8601("2016-10-06T12:34:56.123456+0530") + assert datetime( + 2016, 10, 6, 12, 34, 56, 123456, FixedTimezone(-19800) + ) == parse_iso8601("2016-10-06T12:34:56.123456-05:30") + assert datetime( + 2016, 10, 6, 12, 34, 56, 123456, FixedTimezone(-19800) + ) == parse_iso8601("2016-10-06T12:34:56.123456-0530") + assert datetime( + 2016, 10, 6, 12, 34, 56, 123456, FixedTimezone(18000) + ) == parse_iso8601("2016-10-06T12:34:56.123456+05") + assert datetime( + 2016, 10, 6, 12, 34, 56, 123456, FixedTimezone(-18000) + ) == parse_iso8601("2016-10-06T12:34:56.123456-05") + assert datetime( + 2016, 10, 6, 12, 34, 56, 123456, FixedTimezone(-18000) + ) == parse_iso8601("20161006T123456,123456-05") + assert datetime( + 2016, 10, 6, 12, 34, 56, 123456, FixedTimezone(+19800) + ) == parse_iso8601("2016-10-06T12:34:56.123456789+05:30") + + # Ordinal date + assert date(2012, 1, 7) == parse_iso8601("2012-007") + assert date(2012, 1, 7) == parse_iso8601("2012007") + assert date(2017, 3, 20) == parse_iso8601("2017-079") + + # Week date + assert date(2012, 1, 30) == parse_iso8601("2012-W05") + assert date(2008, 9, 27) == parse_iso8601("2008-W39-6") + assert date(2010, 1, 3) == parse_iso8601("2009-W53-7") + assert date(2008, 12, 29) == parse_iso8601("2009-W01-1") + + # Week date wth time + assert datetime(2008, 9, 27, 9, 0, 0, 0) == parse_iso8601("2008-W39-6T09") + + +def test_parse_ios8601_invalid(): + # Invalid month + with pytest.raises(ValueError): + parse_iso8601("20161306T123456") + + # Invalid day + with pytest.raises(ValueError): + parse_iso8601("20161033T123456") + + # Invalid day for month + with pytest.raises(ValueError): + parse_iso8601("20161131T123456") + + # Invalid hour + with pytest.raises(ValueError): + parse_iso8601("20161006T243456") + + # Invalid minute + with pytest.raises(ValueError): + parse_iso8601("20161006T126056") + + # Invalid second + with pytest.raises(ValueError): + parse_iso8601("20161006T123460") + + # Extraneous separator + with pytest.raises(ValueError): + parse_iso8601("20140203 04:05:.123456") + with pytest.raises(ValueError): + parse_iso8601("2009-05-19 14:") + + # Invalid ordinal + with pytest.raises(ValueError): + parse_iso8601("2009367") + with pytest.raises(ValueError): + parse_iso8601("2009-367") + with pytest.raises(ValueError): + parse_iso8601("2015-366") + with pytest.raises(ValueError): + parse_iso8601("2015-000") + + # Invalid date + with pytest.raises(ValueError): + parse_iso8601("2009-") + + # Invalid time + with pytest.raises(ValueError): + parse_iso8601("2009-05-19T14:3924") + with pytest.raises(ValueError): + parse_iso8601("2010-02-18T16.5:23.35:48") + with pytest.raises(ValueError): + parse_iso8601("2010-02-18T16:23.35:48.45") + with pytest.raises(ValueError): + parse_iso8601("2010-02-18T16:23.33.600") + + # Invalid offset + with pytest.raises(ValueError): + parse_iso8601("2009-05-19 14:39:22+063") + with pytest.raises(ValueError): + parse_iso8601("2009-05-19 14:39:22+06a00") + with pytest.raises(ValueError): + parse_iso8601("2009-05-19 14:39:22+0:6:00") + + # Missing time separator + with pytest.raises(ValueError): + parse_iso8601("2009-05-1914:39") + + # Invalid week date + with pytest.raises(ValueError): + parse_iso8601("2012-W63") + with pytest.raises(ValueError): + parse_iso8601("2012-W12-9") + with pytest.raises(ValueError): + parse_iso8601("2012W12-3") # Missing separator + with pytest.raises(ValueError): + parse_iso8601("2012-W123") # Missing separator + + +def test_parse_ios8601_duration(): + text = "P2Y3M4DT5H6M7S" + parsed = parse_iso8601(text) + + assert parsed.years == 2 + assert parsed.months == 3 + assert parsed.weeks == 0 + assert parsed.remaining_days == 4 + assert parsed.hours == 5 + assert parsed.minutes == 6 + assert parsed.remaining_seconds == 7 + assert parsed.microseconds == 0 + + text = "P1Y2M3DT4H5M6.5S" + parsed = parse_iso8601(text) + + assert parsed.years == 1 + assert parsed.months == 2 + assert parsed.weeks == 0 + assert parsed.remaining_days == 3 + assert parsed.hours == 4 + assert parsed.minutes == 5 + assert parsed.remaining_seconds == 6 + assert parsed.microseconds == 500000 + + text = "P1Y2M3DT4H5M6,5S" + parsed = parse_iso8601(text) + + assert parsed.years == 1 + assert parsed.months == 2 + assert parsed.weeks == 0 + assert parsed.remaining_days == 3 + assert parsed.hours == 4 + assert parsed.minutes == 5 + assert parsed.remaining_seconds == 6 + assert parsed.microseconds == 500000 + + text = "P1Y2M3D" + parsed = parse_iso8601(text) + + assert parsed.years == 1 + assert parsed.months == 2 + assert parsed.weeks == 0 + assert parsed.remaining_days == 3 + assert parsed.hours == 0 + assert parsed.minutes == 0 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "P1Y2M3.5D" + parsed = parse_iso8601(text) + + assert parsed.years == 1 + assert parsed.months == 2 + assert parsed.weeks == 0 + assert parsed.remaining_days == 3 + assert parsed.hours == 12 + assert parsed.minutes == 0 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "P1Y2M3,5D" + parsed = parse_iso8601(text) + + assert parsed.years == 1 + assert parsed.months == 2 + assert parsed.weeks == 0 + assert parsed.remaining_days == 3 + assert parsed.hours == 12 + assert parsed.minutes == 0 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "PT4H54M6.5S" + parsed = parse_iso8601(text) + + assert parsed.years == 0 + assert parsed.months == 0 + assert parsed.weeks == 0 + assert parsed.remaining_days == 0 + assert parsed.hours == 4 + assert parsed.minutes == 54 + assert parsed.remaining_seconds == 6 + assert parsed.microseconds == 500000 + + text = "PT4H54M6,5S" + parsed = parse_iso8601(text) + + assert parsed.years == 0 + assert parsed.months == 0 + assert parsed.weeks == 0 + assert parsed.remaining_days == 0 + assert parsed.hours == 4 + assert parsed.minutes == 54 + assert parsed.remaining_seconds == 6 + assert parsed.microseconds == 500000 + + text = "P1Y" + parsed = parse_iso8601(text) + + assert parsed.years == 1 + assert parsed.months == 0 + assert parsed.weeks == 0 + assert parsed.remaining_days == 0 + assert parsed.hours == 0 + assert parsed.minutes == 0 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "P1.5Y" + with pytest.raises(ValueError): + parse_iso8601(text) + + text = "P1,5Y" + with pytest.raises(ValueError): + parse_iso8601(text) + + text = "P1M" + parsed = parse_iso8601(text) + + assert parsed.years == 0 + assert parsed.months == 1 + assert parsed.weeks == 0 + assert parsed.remaining_days == 0 + assert parsed.hours == 0 + assert parsed.minutes == 0 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "P1.5M" + with pytest.raises(ValueError): + parse_iso8601(text) + + text = "P1,5M" + with pytest.raises(ValueError): + parse_iso8601(text) + + text = "P1W" + parsed = parse_iso8601(text) + + assert parsed.years == 0 + assert parsed.months == 0 + assert parsed.weeks == 1 + assert parsed.remaining_days == 0 + assert parsed.hours == 0 + assert parsed.minutes == 0 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "P1.5W" + parsed = parse_iso8601(text) + + assert parsed.years == 0 + assert parsed.months == 0 + assert parsed.weeks == 1 + assert parsed.remaining_days == 3 + assert parsed.hours == 12 + assert parsed.minutes == 0 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "P1,5W" + parsed = parse_iso8601(text) + + assert parsed.years == 0 + assert parsed.months == 0 + assert parsed.weeks == 1 + assert parsed.remaining_days == 3 + assert parsed.hours == 12 + assert parsed.minutes == 0 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "P1D" + parsed = parse_iso8601(text) + + assert parsed.years == 0 + assert parsed.months == 0 + assert parsed.weeks == 0 + assert parsed.remaining_days == 1 + assert parsed.hours == 0 + assert parsed.minutes == 0 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "P1.5D" + parsed = parse_iso8601(text) + + assert parsed.years == 0 + assert parsed.months == 0 + assert parsed.weeks == 0 + assert parsed.remaining_days == 1 + assert parsed.hours == 12 + assert parsed.minutes == 0 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "P1,5D" + parsed = parse_iso8601(text) + + assert parsed.years == 0 + assert parsed.months == 0 + assert parsed.weeks == 0 + assert parsed.remaining_days == 1 + assert parsed.hours == 12 + assert parsed.minutes == 0 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "PT1H" + parsed = parse_iso8601(text) + + assert parsed.years == 0 + assert parsed.months == 0 + assert parsed.weeks == 0 + assert parsed.remaining_days == 0 + assert parsed.hours == 1 + assert parsed.minutes == 0 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "PT1.5H" + parsed = parse_iso8601(text) + + assert parsed.years == 0 + assert parsed.months == 0 + assert parsed.weeks == 0 + assert parsed.remaining_days == 0 + assert parsed.hours == 1 + assert parsed.minutes == 30 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "PT1,5H" + parsed = parse_iso8601(text) + + assert parsed.years == 0 + assert parsed.months == 0 + assert parsed.weeks == 0 + assert parsed.remaining_days == 0 + assert parsed.hours == 1 + assert parsed.minutes == 30 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + # Double digit with 0 + text = "P2Y30M4DT5H6M7S" + parsed = parse_iso8601(text) + + assert parsed.years == 2 + assert parsed.months == 30 + assert parsed.weeks == 0 + assert parsed.remaining_days == 4 + assert parsed.hours == 5 + assert parsed.minutes == 6 + assert parsed.remaining_seconds == 7 + assert parsed.microseconds == 0 + + # No P operator + with pytest.raises(ValueError): + parse_iso8601("2Y3M4DT5H6M7S") + + # Week and other units combined + with pytest.raises(ValueError): + parse_iso8601("P1Y2W") + + # Invalid units order + with pytest.raises(ValueError): + parse_iso8601("P1S") + + with pytest.raises(ValueError): + parse_iso8601("P1D1S") + + with pytest.raises(ValueError): + parse_iso8601("1Y2M3D1SPT1M") + + with pytest.raises(ValueError): + parse_iso8601("P1Y2M3D2MT1S") + + with pytest.raises(ValueError): + parse_iso8601("P2M3D1ST1Y1M") + + with pytest.raises(ValueError): + parse_iso8601("P1Y2M2MT3D1S") + + with pytest.raises(ValueError): + parse_iso8601("P1D1Y1M") + + with pytest.raises(ValueError): + parse_iso8601("PT1S1H") + + # Invalid + with pytest.raises(ValueError): + parse_iso8601("P1Dasdfasdf") + + # Invalid fractional + with pytest.raises(ValueError): + parse_iso8601("P2Y3M4DT5.5H6M7S") diff --git a/tests/parsing/test_parsing.py b/tests/parsing/test_parsing.py new file mode 100644 index 0000000..35dcf86 --- /dev/null +++ b/tests/parsing/test_parsing.py @@ -0,0 +1,687 @@ +from __future__ import annotations + +import datetime + +import pytest + +import pendulum + +from pendulum.parsing import ParserError +from pendulum.parsing import parse + + +def test_y(): + text = "2016" + + parsed = parse(text) + + assert parsed.year == 2016 + assert parsed.month == 1 + assert parsed.day == 1 + assert parsed.hour == 0 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + +def test_ym(): + text = "2016-10" + + parsed = parse(text) + + assert parsed.year == 2016 + assert parsed.month == 10 + assert parsed.day == 1 + assert parsed.hour == 0 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + +def test_ymd(): + text = "2016-10-06" + + parsed = parse(text) + + assert parsed.year == 2016 + assert parsed.month == 10 + assert parsed.day == 6 + assert parsed.hour == 0 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + +def test_ymd_one_character(): + text = "2016-2-6" + + parsed = parse(text, strict=False) + + assert parsed.year == 2016 + assert parsed.month == 2 + assert parsed.day == 6 + assert parsed.hour == 0 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + +def test_ymd_hms(): + text = "2016-10-06 12:34:56" + + parsed = parse(text) + + assert parsed.year == 2016 + assert parsed.month == 10 + assert parsed.day == 6 + assert parsed.hour == 12 + assert parsed.minute == 34 + assert parsed.second == 56 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + text = "2016-10-06 12:34:56.123456" + + parsed = parse(text) + + assert parsed.year == 2016 + assert parsed.month == 10 + assert parsed.day == 6 + assert parsed.hour == 12 + assert parsed.minute == 34 + assert parsed.second == 56 + assert parsed.microsecond == 123456 + assert parsed.tzinfo is None + + +def test_rfc_3339(): + text = "2016-10-06T12:34:56+05:30" + + parsed = parse(text) + + assert parsed.year == 2016 + assert parsed.month == 10 + assert parsed.day == 6 + assert parsed.hour == 12 + assert parsed.minute == 34 + assert parsed.second == 56 + assert parsed.microsecond == 0 + assert parsed.utcoffset().total_seconds() == 19800 + + +def test_rfc_3339_extended(): + text = "2016-10-06T12:34:56.123456+05:30" + + parsed = parse(text) + + assert parsed.year == 2016 + assert parsed.month == 10 + assert parsed.day == 6 + assert parsed.hour == 12 + assert parsed.minute == 34 + assert parsed.second == 56 + assert parsed.microsecond == 123456 + assert parsed.utcoffset().total_seconds() == 19800 + + text = "2016-10-06T12:34:56.000123+05:30" + + parsed = parse(text) + + assert parsed.year == 2016 + assert parsed.month == 10 + assert parsed.day == 6 + assert parsed.hour == 12 + assert parsed.minute == 34 + assert parsed.second == 56 + assert parsed.microsecond == 123 + assert parsed.utcoffset().total_seconds() == 19800 + + +def test_rfc_3339_extended_nanoseconds(): + text = "2016-10-06T12:34:56.123456789+05:30" + + parsed = parse(text) + + assert parsed.year == 2016 + assert parsed.month == 10 + assert parsed.day == 6 + assert parsed.hour == 12 + assert parsed.minute == 34 + assert parsed.second == 56 + assert parsed.microsecond == 123456 + assert parsed.utcoffset().total_seconds() == 19800 + + +def test_iso_8601_date(): + text = "2012" + + parsed = parse(text) + + assert parsed.year == 2012 + assert parsed.month == 1 + assert parsed.day == 1 + assert parsed.hour == 0 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + text = "2012-05-03" + + parsed = parse(text) + + assert parsed.year == 2012 + assert parsed.month == 5 + assert parsed.day == 3 + assert parsed.hour == 0 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + text = "20120503" + + parsed = parse(text) + + assert parsed.year == 2012 + assert parsed.month == 5 + assert parsed.day == 3 + assert parsed.hour == 0 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + text = "2012-05" + + parsed = parse(text) + + assert parsed.year == 2012 + assert parsed.month == 5 + assert parsed.day == 1 + assert parsed.hour == 0 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + +def test_iso8601_datetime(): + text = "2016-10-01T14" + + parsed = parse(text) + + assert parsed.year == 2016 + assert parsed.month == 10 + assert parsed.day == 1 + assert parsed.hour == 14 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + text = "2016-10-01T14:30" + + parsed = parse(text) + + assert parsed.year == 2016 + assert parsed.month == 10 + assert parsed.day == 1 + assert parsed.hour == 14 + assert parsed.minute == 30 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + text = "20161001T14" + + parsed = parse(text) + + assert parsed.year == 2016 + assert parsed.month == 10 + assert parsed.day == 1 + assert parsed.hour == 14 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + text = "20161001T1430" + + parsed = parse(text) + + assert parsed.year == 2016 + assert parsed.month == 10 + assert parsed.day == 1 + assert parsed.hour == 14 + assert parsed.minute == 30 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + text = "20161001T1430+0530" + + parsed = parse(text) + + assert parsed.year == 2016 + assert parsed.month == 10 + assert parsed.day == 1 + assert parsed.hour == 14 + assert parsed.minute == 30 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.utcoffset().total_seconds() == 19800 + + text = "20161001T1430,4+0530" + + parsed = parse(text) + + assert parsed.year == 2016 + assert parsed.month == 10 + assert parsed.day == 1 + assert parsed.hour == 14 + assert parsed.minute == 30 + assert parsed.second == 0 + assert parsed.microsecond == 400000 + assert parsed.utcoffset().total_seconds() == 19800 + + text = "2008-09-03T20:56:35.450686+01" + + parsed = parse(text) + + assert parsed.year == 2008 + assert parsed.month == 9 + assert parsed.day == 3 + assert parsed.hour == 20 + assert parsed.minute == 56 + assert parsed.second == 35 + assert parsed.microsecond == 450686 + assert parsed.utcoffset().total_seconds() == 3600 + + +def test_iso8601_week_number(): + text = "2012-W05" + + parsed = parse(text) + + assert parsed.year == 2012 + assert parsed.month == 1 + assert parsed.day == 30 + assert parsed.hour == 0 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + text = "2012W05" + + parsed = parse(text) + + assert parsed.year == 2012 + assert parsed.month == 1 + assert parsed.day == 30 + assert parsed.hour == 0 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + # Long Year + text = "2015W53" + + parsed = parse(text) + + assert parsed.year == 2015 + assert parsed.month == 12 + assert parsed.day == 28 + assert parsed.hour == 0 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + text = "2012-W05-5" + + parsed = parse(text) + + assert parsed.year == 2012 + assert parsed.month == 2 + assert parsed.day == 3 + assert parsed.hour == 0 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + text = "2012W055" + + parsed = parse(text) + + assert parsed.year == 2012 + assert parsed.month == 2 + assert parsed.day == 3 + assert parsed.hour == 0 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + text = "2009-W53-7" + parsed = parse(text) + + assert parsed.year == 2010 + assert parsed.month == 1 + assert parsed.day == 3 + assert parsed.hour == 0 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + text = "2009-W01-1" + parsed = parse(text) + + assert parsed.year == 2008 + assert parsed.month == 12 + assert parsed.day == 29 + assert parsed.hour == 0 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + +def test_iso8601_week_number_with_time(): + text = "2012-W05T09" + + parsed = parse(text) + + assert parsed.year == 2012 + assert parsed.month == 1 + assert parsed.day == 30 + assert parsed.hour == 9 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + text = "2012W05T09" + + parsed = parse(text) + + assert parsed.year == 2012 + assert parsed.month == 1 + assert parsed.day == 30 + assert parsed.hour == 9 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + text = "2012-W05-5T09" + + parsed = parse(text) + + assert parsed.year == 2012 + assert parsed.month == 2 + assert parsed.day == 3 + assert parsed.hour == 9 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + text = "2012W055T09" + + parsed = parse(text) + + assert parsed.year == 2012 + assert parsed.month == 2 + assert parsed.day == 3 + assert parsed.hour == 9 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + +def test_iso8601_ordinal(): + text = "2012-007" + + parsed = parse(text) + + assert parsed.year == 2012 + assert parsed.month == 1 + assert parsed.day == 7 + assert parsed.hour == 0 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + text = "2012007" + + parsed = parse(text) + + assert parsed.year == 2012 + assert parsed.month == 1 + assert parsed.day == 7 + assert parsed.hour == 0 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + +def test_iso8601_time(): + now = pendulum.datetime(2015, 11, 12) + + text = "201205" + + parsed = parse(text, now=now) + + assert parsed.year == 2015 + assert parsed.month == 11 + assert parsed.day == 12 + assert parsed.hour == 20 + assert parsed.minute == 12 + assert parsed.second == 5 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + text = "20:12:05" + + parsed = parse(text, now=now) + + assert parsed.year == 2015 + assert parsed.month == 11 + assert parsed.day == 12 + assert parsed.hour == 20 + assert parsed.minute == 12 + assert parsed.second == 5 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + text = "20:12:05.123456" + + parsed = parse(text, now=now) + + assert parsed.year == 2015 + assert parsed.month == 11 + assert parsed.day == 12 + assert parsed.hour == 20 + assert parsed.minute == 12 + assert parsed.second == 5 + assert parsed.microsecond == 123456 + assert parsed.tzinfo is None + + +def test_iso8601_ordinal_invalid(): + text = "2012-007-05" + + with pytest.raises(ParserError): + parse(text) + + +def test_exact(): + text = "2012" + + parsed = parse(text, exact=True) + + assert isinstance(parsed, datetime.date) + assert parsed.year == 2012 + assert parsed.month == 1 + assert parsed.day == 1 + + text = "2012-03" + + parsed = parse(text, exact=True) + + assert isinstance(parsed, datetime.date) + assert parsed.year == 2012 + assert parsed.month == 3 + assert parsed.day == 1 + + text = "2012-03-13" + + parsed = parse(text, exact=True) + + assert isinstance(parsed, datetime.date) + assert parsed.year == 2012 + assert parsed.month == 3 + assert parsed.day == 13 + + text = "2012W055" + + parsed = parse(text, exact=True) + + assert isinstance(parsed, datetime.date) + assert parsed.year == 2012 + assert parsed.month == 2 + assert parsed.day == 3 + + text = "2012007" + + parsed = parse(text, exact=True) + + assert isinstance(parsed, datetime.date) + assert parsed.year == 2012 + assert parsed.month == 1 + assert parsed.day == 7 + + text = "20:12:05" + + parsed = parse(text, exact=True) + + assert isinstance(parsed, datetime.time) + assert parsed.hour == 20 + assert parsed.minute == 12 + assert parsed.second == 5 + assert parsed.microsecond == 0 + + +def test_edge_cases(): + text = "2013-11-1" + + parsed = parse(text, strict=False) + assert parsed.year == 2013 + assert parsed.month == 11 + assert parsed.day == 1 + assert parsed.hour == 0 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + text = "10-01-01" + + parsed = parse(text, strict=False) + assert parsed.year == 2010 + assert parsed.month == 1 + assert parsed.day == 1 + assert parsed.hour == 0 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + text = "31-01-01" + + parsed = parse(text, strict=False) + assert parsed.year == 2031 + assert parsed.month == 1 + assert parsed.day == 1 + assert parsed.hour == 0 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + text = "32-01-01" + + parsed = parse(text, strict=False) + assert parsed.year == 2032 + assert parsed.month == 1 + assert parsed.day == 1 + assert parsed.hour == 0 + assert parsed.minute == 0 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + +def test_strict(): + text = "4 Aug 2015 - 11:20 PM" + + with pytest.raises(ParserError): + parse(text) + + parsed = parse(text, strict=False) + assert parsed.year == 2015 + assert parsed.month == 8 + assert parsed.day == 4 + assert parsed.hour == 23 + assert parsed.minute == 20 + assert parsed.second == 0 + assert parsed.microsecond == 0 + assert parsed.tzinfo is None + + +def test_invalid(): + text = "201610T" + + with pytest.raises(ParserError): + parse(text) + + text = "2012-W54" + + with pytest.raises(ParserError): + parse(text) + + text = "2012-W13-8" + + with pytest.raises(ParserError): + parse(text) + + # W53 in normal year (not long) + text = "2017W53" + + with pytest.raises(ParserError): + parse(text) + + +def test_exif_edge_case(): + text = "2016:12:26 15:45:28" + + parsed = parse(text) + + assert parsed.year == 2016 + assert parsed.month == 12 + assert parsed.day == 26 + assert parsed.hour == 15 + assert parsed.minute == 45 + assert parsed.second == 28 diff --git a/tests/parsing/test_parsing_duration.py b/tests/parsing/test_parsing_duration.py new file mode 100644 index 0000000..ab8b992 --- /dev/null +++ b/tests/parsing/test_parsing_duration.py @@ -0,0 +1,298 @@ +from __future__ import annotations + +import pytest + +from pendulum.parsing import ParserError +from pendulum.parsing import parse + + +def test_parse_duration(): + text = "P2Y3M4DT5H6M7S" + parsed = parse(text) + + assert parsed.years == 2 + assert parsed.months == 3 + assert parsed.weeks == 0 + assert parsed.remaining_days == 4 + assert parsed.hours == 5 + assert parsed.minutes == 6 + assert parsed.remaining_seconds == 7 + assert parsed.microseconds == 0 + + text = "P1Y2M3DT4H5M6.5S" + parsed = parse(text) + + assert parsed.years == 1 + assert parsed.months == 2 + assert parsed.weeks == 0 + assert parsed.remaining_days == 3 + assert parsed.hours == 4 + assert parsed.minutes == 5 + assert parsed.remaining_seconds == 6 + assert parsed.microseconds == 500000 + + text = "P1Y2M3DT4H5M6,5S" + parsed = parse(text) + + assert parsed.years == 1 + assert parsed.months == 2 + assert parsed.weeks == 0 + assert parsed.remaining_days == 3 + assert parsed.hours == 4 + assert parsed.minutes == 5 + assert parsed.remaining_seconds == 6 + assert parsed.microseconds == 500000 + + text = "P1Y2M3D" + parsed = parse(text) + + assert parsed.years == 1 + assert parsed.months == 2 + assert parsed.weeks == 0 + assert parsed.remaining_days == 3 + assert parsed.hours == 0 + assert parsed.minutes == 0 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "P1Y2M3.5D" + parsed = parse(text) + + assert parsed.years == 1 + assert parsed.months == 2 + assert parsed.weeks == 0 + assert parsed.remaining_days == 3 + assert parsed.hours == 12 + assert parsed.minutes == 0 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "P1Y2M3,5D" + parsed = parse(text) + + assert parsed.years == 1 + assert parsed.months == 2 + assert parsed.weeks == 0 + assert parsed.remaining_days == 3 + assert parsed.hours == 12 + assert parsed.minutes == 0 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "PT4H54M6.5S" + parsed = parse(text) + + assert parsed.years == 0 + assert parsed.months == 0 + assert parsed.weeks == 0 + assert parsed.remaining_days == 0 + assert parsed.hours == 4 + assert parsed.minutes == 54 + assert parsed.remaining_seconds == 6 + assert parsed.microseconds == 500000 + + text = "PT4H54M6,5S" + parsed = parse(text) + + assert parsed.years == 0 + assert parsed.months == 0 + assert parsed.weeks == 0 + assert parsed.remaining_days == 0 + assert parsed.hours == 4 + assert parsed.minutes == 54 + assert parsed.remaining_seconds == 6 + assert parsed.microseconds == 500000 + + text = "P1Y" + parsed = parse(text) + + assert parsed.years == 1 + assert parsed.months == 0 + assert parsed.weeks == 0 + assert parsed.remaining_days == 0 + assert parsed.hours == 0 + assert parsed.minutes == 0 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "P1.5Y" + with pytest.raises(ParserError): + parse(text) + + text = "P1,5Y" + with pytest.raises(ParserError): + parse(text) + + text = "P1M" + parsed = parse(text) + + assert parsed.years == 0 + assert parsed.months == 1 + assert parsed.weeks == 0 + assert parsed.remaining_days == 0 + assert parsed.hours == 0 + assert parsed.minutes == 0 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "P1.5M" + with pytest.raises(ParserError): + parse(text) + + text = "P1,5M" + with pytest.raises(ParserError): + parse(text) + + text = "P1W" + parsed = parse(text) + + assert parsed.years == 0 + assert parsed.months == 0 + assert parsed.weeks == 1 + assert parsed.remaining_days == 0 + assert parsed.hours == 0 + assert parsed.minutes == 0 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "P1.5W" + parsed = parse(text) + + assert parsed.years == 0 + assert parsed.months == 0 + assert parsed.weeks == 1 + assert parsed.remaining_days == 3 + assert parsed.hours == 12 + assert parsed.minutes == 0 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "P1,5W" + parsed = parse(text) + + assert parsed.years == 0 + assert parsed.months == 0 + assert parsed.weeks == 1 + assert parsed.remaining_days == 3 + assert parsed.hours == 12 + assert parsed.minutes == 0 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "P1D" + parsed = parse(text) + + assert parsed.years == 0 + assert parsed.months == 0 + assert parsed.weeks == 0 + assert parsed.remaining_days == 1 + assert parsed.hours == 0 + assert parsed.minutes == 0 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "P1.5D" + parsed = parse(text) + + assert parsed.years == 0 + assert parsed.months == 0 + assert parsed.weeks == 0 + assert parsed.remaining_days == 1 + assert parsed.hours == 12 + assert parsed.minutes == 0 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "P1,5D" + parsed = parse(text) + + assert parsed.years == 0 + assert parsed.months == 0 + assert parsed.weeks == 0 + assert parsed.remaining_days == 1 + assert parsed.hours == 12 + assert parsed.minutes == 0 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "PT1H" + parsed = parse(text) + + assert parsed.years == 0 + assert parsed.months == 0 + assert parsed.weeks == 0 + assert parsed.remaining_days == 0 + assert parsed.hours == 1 + assert parsed.minutes == 0 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "PT1.5H" + parsed = parse(text) + + assert parsed.years == 0 + assert parsed.months == 0 + assert parsed.weeks == 0 + assert parsed.remaining_days == 0 + assert parsed.hours == 1 + assert parsed.minutes == 30 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + text = "PT1,5H" + parsed = parse(text) + + assert parsed.years == 0 + assert parsed.months == 0 + assert parsed.weeks == 0 + assert parsed.remaining_days == 0 + assert parsed.hours == 1 + assert parsed.minutes == 30 + assert parsed.remaining_seconds == 0 + assert parsed.microseconds == 0 + + +def test_parse_duration_no_operator(): + with pytest.raises(ParserError): + parse("2Y3M4DT5H6M7S") + + +def test_parse_duration_weeks_combined(): + with pytest.raises(ParserError): + parse("P1Y2W") + + +def test_parse_duration_invalid_order(): + with pytest.raises(ParserError): + parse("P1S") + + with pytest.raises(ParserError): + parse("P1D1S") + + with pytest.raises(ParserError): + parse("1Y2M3D1SPT1M") + + with pytest.raises(ParserError): + parse("P1Y2M3D2MT1S") + + with pytest.raises(ParserError): + parse("P2M3D1ST1Y1M") + + with pytest.raises(ParserError): + parse("P1Y2M2MT3D1S") + + with pytest.raises(ParserError): + parse("P1D1Y1M") + + with pytest.raises(ParserError): + parse("PT1S1H") + + +def test_parse_duration_invalid(): + with pytest.raises(ParserError): + parse("P1Dasdfasdf") + + +def test_parse_duration_fraction_only_allowed_on_last_component(): + with pytest.raises(ParserError): + parse("P2Y3M4DT5.5H6M7S") |