From 665666d6f4213da8db57ebb480947b7caf1fe382 Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 17 Dec 2023 15:36:26 +0100 Subject: Merging upstream version 3.0.0. Signed-off-by: Daniel Baumann --- tests/benchmarks/__init__.py | 0 tests/benchmarks/test_parse_8601.py | 51 +++ tests/conftest.py | 51 ++- tests/date/test_comparison.py | 2 +- tests/date/test_day_of_week_modifiers.py | 18 +- tests/date/test_diff.py | 2 +- tests/datetime/test_add.py | 20 +- tests/datetime/test_behavior.py | 8 + tests/datetime/test_comparison.py | 2 +- tests/datetime/test_construct.py | 27 +- tests/datetime/test_day_of_week_modifiers.py | 18 +- tests/datetime/test_from_format.py | 35 +- tests/datetime/test_getters.py | 51 ++- tests/datetime/test_start_end_of.py | 40 +++ tests/datetime/test_strings.py | 10 +- tests/duration/test_behavior.py | 15 +- tests/formatting/test_formatter.py | 14 + tests/interval/test_add_subtract.py | 20 +- tests/interval/test_behavior.py | 21 +- tests/interval/test_construct.py | 28 +- tests/interval/test_hashing.py | 20 +- tests/interval/test_in_words.py | 38 +-- tests/interval/test_range.py | 2 +- tests/localization/test_cs.py | 1 + tests/localization/test_da.py | 1 + tests/localization/test_de.py | 1 + tests/localization/test_es.py | 1 + tests/localization/test_fa.py | 1 + tests/localization/test_fo.py | 1 + tests/localization/test_fr.py | 1 + tests/localization/test_he.py | 1 + tests/localization/test_id.py | 1 + tests/localization/test_it.py | 1 + tests/localization/test_ja.py | 1 + tests/localization/test_ko.py | 1 + tests/localization/test_lt.py | 1 + tests/localization/test_nb.py | 1 + tests/localization/test_nl.py | 1 + tests/localization/test_nn.py | 1 + tests/localization/test_pl.py | 1 + tests/localization/test_ru.py | 1 + tests/localization/test_sk.py | 1 + tests/localization/test_sv.py | 1 + tests/localization/test_tr.py | 66 ++++ tests/parsing/test_parse_iso8601.py | 485 +++++++-------------------- tests/parsing/test_parsing.py | 15 +- tests/test_helpers.py | 57 ++-- tests/test_main.py | 52 ++- tests/test_parsing.py | 53 +-- tests/testing/test_time_travel.py | 1 + tests/time/test_comparison.py | 2 +- tests/tz/test_helpers.py | 2 +- tests/tz/test_timezone.py | 10 +- 53 files changed, 679 insertions(+), 577 deletions(-) create mode 100644 tests/benchmarks/__init__.py create mode 100644 tests/benchmarks/test_parse_8601.py create mode 100644 tests/localization/test_tr.py (limited to 'tests') diff --git a/tests/benchmarks/__init__.py b/tests/benchmarks/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/tests/benchmarks/test_parse_8601.py b/tests/benchmarks/test_parse_8601.py new file mode 100644 index 0000000..1f838a8 --- /dev/null +++ b/tests/benchmarks/test_parse_8601.py @@ -0,0 +1,51 @@ +from __future__ import annotations + +import pytest + +from pendulum.parsing.iso8601 import parse_iso8601 + + +@pytest.mark.benchmark(group="Parsing") +def test_parse_iso8601() -> None: + # Date + parse_iso8601("2016") + parse_iso8601("2016-10") + parse_iso8601("2016-10-06") + parse_iso8601("20161006") + + # Time + parse_iso8601("201610") + + # Datetime + parse_iso8601("2016-10-06T12:34:56.123456") + parse_iso8601("2016-10-06T12:34:56.123") + parse_iso8601("2016-10-06T12:34:56.000123") + parse_iso8601("2016-10-06T12") + parse_iso8601("2016-10-06T123456") + parse_iso8601("2016-10-06T123456.123456") + parse_iso8601("20161006T123456.123456") + parse_iso8601("20161006 123456.123456") + + # Datetime with offset + parse_iso8601("2016-10-06T12:34:56.123456+05:30") + parse_iso8601("2016-10-06T12:34:56.123456+0530") + parse_iso8601("2016-10-06T12:34:56.123456-05:30") + parse_iso8601("2016-10-06T12:34:56.123456-0530") + parse_iso8601("2016-10-06T12:34:56.123456+05") + parse_iso8601("2016-10-06T12:34:56.123456-05") + parse_iso8601("20161006T123456,123456-05") + parse_iso8601("2016-10-06T12:34:56.123456789+05:30") + + # Ordinal date + parse_iso8601("2012-007") + parse_iso8601("2012007") + parse_iso8601("2017-079") + + # Week date + parse_iso8601("2012-W05") + parse_iso8601("2008-W39-6") + parse_iso8601("2009-W53-7") + parse_iso8601("2009-W01-1") + + # Week date wth time + parse_iso8601("2008-W39-6T09") diff --git a/tests/conftest.py b/tests/conftest.py index 060e951..99f4b93 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -1,25 +1,38 @@ from __future__ import annotations +from typing import TYPE_CHECKING + import pytest import pendulum +if TYPE_CHECKING: + from collections.abc import Iterator + + @pytest.fixture(autouse=True) -def setup(): +def setup() -> Iterator[None]: pendulum.set_local_timezone(pendulum.timezone("America/Toronto")) yield pendulum.set_locale("en") pendulum.set_local_timezone() - pendulum.week_starts_at(pendulum.MONDAY) - pendulum.week_ends_at(pendulum.SUNDAY) + pendulum.week_starts_at(pendulum.WeekDay.MONDAY) + pendulum.week_ends_at(pendulum.WeekDay.SUNDAY) def assert_datetime( - d, year, month, day, hour=None, minute=None, second=None, microsecond=None -): + d: pendulum.DateTime, + year: int, + month: int, + day: int, + hour: int | None = None, + minute: int | None = None, + second: int | None = None, + microsecond: int | None = None, +) -> None: assert year == d.year assert month == d.month assert day == d.day @@ -37,13 +50,19 @@ def assert_datetime( assert microsecond == d.microsecond -def assert_date(d, year, month, day): +def assert_date(d: pendulum.Date, year: int, month: int, day: int) -> None: assert year == d.year assert month == d.month assert day == d.day -def assert_time(t, hour, minute, second, microsecond=None): +def assert_time( + t: pendulum.Time, + hour: int, + minute: int, + second: int, + microsecond: int | None = None, +) -> None: assert hour == t.hour assert minute == t.minute assert second == t.second @@ -53,15 +72,15 @@ def assert_time(t, hour, minute, second, microsecond=None): def assert_duration( - dur, - years=None, - months=None, - weeks=None, - days=None, - hours=None, - minutes=None, - seconds=None, - microseconds=None, + dur: pendulum.Duration, + years: int | None = None, + months: int | None = None, + weeks: int | None = None, + days: int | None = None, + hours: int | None = None, + minutes: int | None = None, + seconds: int | None = None, + microseconds: int | None = None, ) -> None: expected = {} actual = {} diff --git a/tests/date/test_comparison.py b/tests/date/test_comparison.py index 94bf224..9fd999b 100644 --- a/tests/date/test_comparison.py +++ b/tests/date/test_comparison.py @@ -46,7 +46,7 @@ def test_not_equal_to_false(): def test_not_equal_to_none(): d1 = pendulum.Date(2000, 1, 1) - assert d1 != None # noqa + assert d1 is not None def test_greater_than_true(): diff --git a/tests/date/test_day_of_week_modifiers.py b/tests/date/test_day_of_week_modifiers.py index 55aba55..0363096 100644 --- a/tests/date/test_day_of_week_modifiers.py +++ b/tests/date/test_day_of_week_modifiers.py @@ -49,7 +49,7 @@ def test_next_monday(): def test_next_saturday(): - d = pendulum.date(1975, 5, 21).next(6) + d = pendulum.date(1975, 5, 21).next(5) assert_date(d, 1975, 5, 24) @@ -71,7 +71,7 @@ def test_previous_monday(): def test_previous_saturday(): - d = pendulum.date(1975, 5, 21).previous(6) + d = pendulum.date(1975, 5, 21).previous(5) assert_date(d, 1975, 5, 17) @@ -93,7 +93,7 @@ def test_first_wednesday_of_month(): def test_first_friday_of_month(): - d = pendulum.date(1975, 11, 21).first_of("month", 5) + d = pendulum.date(1975, 11, 21).first_of("month", 4) assert_date(d, 1975, 11, 7) @@ -108,7 +108,7 @@ def test_last_tuesday_of_month(): def test_last_friday_of_month(): - d = pendulum.date(1975, 12, 5).last_of("month", 5) + d = pendulum.date(1975, 12, 5).last_of("month", 4) assert_date(d, 1975, 12, 26) @@ -139,7 +139,7 @@ def test_2nd_monday_of_month(): def test_3rd_wednesday_of_month(): - d = pendulum.date(1975, 12, 5).nth_of("month", 3, 3) + d = pendulum.date(1975, 12, 5).nth_of("month", 3, 2) assert_date(d, 1975, 12, 17) @@ -155,7 +155,7 @@ def test_first_wednesday_of_quarter(): def test_first_friday_of_quarter(): - d = pendulum.date(1975, 11, 21).first_of("quarter", 5) + d = pendulum.date(1975, 11, 21).first_of("quarter", 4) assert_date(d, 1975, 10, 3) @@ -215,7 +215,7 @@ def test_2nd_monday_of_quarter(): def test_3rd_wednesday_of_quarter(): - d = pendulum.date(1975, 8, 5).nth_of("quarter", 3, 3) + d = pendulum.date(1975, 8, 5).nth_of("quarter", 3, 2) assert_date(d, 1975, 7, 16) @@ -230,7 +230,7 @@ def test_first_wednesday_of_year(): def test_first_friday_of_year(): - d = pendulum.date(1975, 11, 21).first_of("year", 5) + d = pendulum.date(1975, 11, 21).first_of("year", 4) assert_date(d, 1975, 1, 3) @@ -245,7 +245,7 @@ def test_last_tuesday_of_year(): def test_last_friday_of_year(): - d = pendulum.date(1975, 8, 5).last_of("year", 5) + d = pendulum.date(1975, 8, 5).last_of("year", 4) assert_date(d, 1975, 12, 26) diff --git a/tests/date/test_diff.py b/tests/date/test_diff.py index 56358cc..cfececf 100644 --- a/tests/date/test_diff.py +++ b/tests/date/test_diff.py @@ -9,7 +9,7 @@ import pendulum @pytest.fixture def today(): - return pendulum.today().date() + return pendulum.Date.today() def test_diff_in_years_positive(): diff --git a/tests/datetime/test_add.py b/tests/datetime/test_add.py index 87ea39f..409f5bd 100644 --- a/tests/datetime/test_add.py +++ b/tests/datetime/test_add.py @@ -252,17 +252,29 @@ def test_add_time_to_new_transition_repeated_big(): assert not dt.is_dst() -def test_add_interval(): +def test_add_duration_across_transition(): dt = pendulum.datetime(2017, 3, 11, 10, 45, tz="America/Los_Angeles") new = dt + pendulum.duration(hours=24) assert_datetime(new, 2017, 3, 12, 11, 45) -def test_period_over_midnight_tz(): +def test_add_duration_across_transition_days(): + dt = pendulum.datetime(2017, 3, 11, 10, 45, tz="America/Los_Angeles") + new = dt + pendulum.duration(days=1) + + assert_datetime(new, 2017, 3, 12, 10, 45) + + dt = pendulum.datetime(2023, 11, 5, 0, 0, tz="America/Chicago") + new = dt + pendulum.duration(days=1) + + assert_datetime(new, 2023, 11, 6, 0, 0) + + +def test_interval_over_midnight_tz(): start = pendulum.datetime(2018, 2, 25, tz="Europe/Paris") end = start.add(hours=1) - period = end - start - new_end = start + period + interval = end - start + new_end = start + interval assert new_end == end diff --git a/tests/datetime/test_behavior.py b/tests/datetime/test_behavior.py index e02323a..76de1d6 100644 --- a/tests/datetime/test_behavior.py +++ b/tests/datetime/test_behavior.py @@ -158,6 +158,14 @@ def test_deepcopy(): assert dt == deepcopy(dt) +def test_deepcopy_on_transition(): + dt = pendulum.datetime(2023, 11, 5, 1, 0, 0, tz="US/Pacific") + clone = deepcopy(dt) + + assert dt == clone + assert dt.offset == clone.offset + + def test_pickle_timezone(): dt1 = pendulum.timezone("Europe/Amsterdam") s = pickle.dumps(dt1) diff --git a/tests/datetime/test_comparison.py b/tests/datetime/test_comparison.py index ad81e73..c3cb064 100644 --- a/tests/datetime/test_comparison.py +++ b/tests/datetime/test_comparison.py @@ -75,7 +75,7 @@ def test_not_equal_with_timezone_true(): def test_not_equal_to_none(): d1 = pendulum.datetime(2000, 1, 1, 1, 2, 3) - assert d1 != None # noqa + assert d1 is not None def test_greater_than_true(): diff --git a/tests/datetime/test_construct.py b/tests/datetime/test_construct.py index 9488c08..b083cbe 100644 --- a/tests/datetime/test_construct.py +++ b/tests/datetime/test_construct.py @@ -5,17 +5,15 @@ import os from datetime import datetime import pytest -import pytz - -from dateutil import tz import pendulum from pendulum import DateTime -from pendulum.tz import timezone +from pendulum import timezone from pendulum.utils._compat import PYPY from tests.conftest import assert_datetime + if not PYPY: import time_machine else: @@ -82,27 +80,6 @@ def test_yesterday(): assert now.diff(yesterday, False).in_days() == -1 -def test_instance_naive_datetime_defaults_to_utc(): - now = pendulum.instance(datetime.now()) - assert now.timezone_name == "UTC" - - -def test_instance_timezone_aware_datetime(): - now = pendulum.instance(datetime.now(timezone("Europe/Paris"))) - assert now.timezone_name == "Europe/Paris" - - -def test_instance_timezone_aware_datetime_pytz(): - now = pendulum.instance(datetime.now(pytz.timezone("Europe/Paris"))) - assert now.timezone_name == "Europe/Paris" - - -def test_instance_timezone_aware_datetime_any_tzinfo(): - dt = datetime(2016, 8, 7, 12, 34, 56, tzinfo=tz.gettz("Europe/Paris")) - now = pendulum.instance(dt) - assert now.timezone_name == "+02:00" - - def test_now(): now = pendulum.now("America/Toronto") in_paris = pendulum.now("Europe/Paris") diff --git a/tests/datetime/test_day_of_week_modifiers.py b/tests/datetime/test_day_of_week_modifiers.py index 46de84e..eb4bc4f 100644 --- a/tests/datetime/test_day_of_week_modifiers.py +++ b/tests/datetime/test_day_of_week_modifiers.py @@ -49,7 +49,7 @@ def test_next_monday(): def test_next_saturday(): - d = pendulum.datetime(1975, 5, 21).next(6) + d = pendulum.datetime(1975, 5, 21).next(5) assert_datetime(d, 1975, 5, 24, 0, 0, 0) @@ -79,7 +79,7 @@ def test_previous_monday(): def test_previous_saturday(): - d = pendulum.datetime(1975, 5, 21).previous(6) + d = pendulum.datetime(1975, 5, 21).previous(5) assert_datetime(d, 1975, 5, 17, 0, 0, 0) @@ -109,7 +109,7 @@ def test_first_wednesday_of_month(): def test_first_friday_of_month(): - d = pendulum.datetime(1975, 11, 21).first_of("month", 5) + d = pendulum.datetime(1975, 11, 21).first_of("month", 4) assert_datetime(d, 1975, 11, 7, 0, 0, 0) @@ -124,7 +124,7 @@ def test_last_tuesday_of_month(): def test_last_friday_of_month(): - d = pendulum.datetime(1975, 12, 5).last_of("month", 5) + d = pendulum.datetime(1975, 12, 5).last_of("month", 4) assert_datetime(d, 1975, 12, 26, 0, 0, 0) @@ -155,7 +155,7 @@ def test_2nd_monday_of_month(): def test_3rd_wednesday_of_month(): - d = pendulum.datetime(1975, 12, 5).nth_of("month", 3, 3) + d = pendulum.datetime(1975, 12, 5).nth_of("month", 3, 2) assert_datetime(d, 1975, 12, 17, 0, 0, 0) @@ -171,7 +171,7 @@ def test_first_wednesday_of_quarter(): def test_first_friday_of_quarter(): - d = pendulum.datetime(1975, 11, 21).first_of("quarter", 5) + d = pendulum.datetime(1975, 11, 21).first_of("quarter", 4) assert_datetime(d, 1975, 10, 3, 0, 0, 0) @@ -231,7 +231,7 @@ def test_2nd_monday_of_quarter(): def test_3rd_wednesday_of_quarter(): - d = pendulum.datetime(1975, 8, 5).nth_of("quarter", 3, 3) + d = pendulum.datetime(1975, 8, 5).nth_of("quarter", 3, 2) assert_datetime(d, 1975, 7, 16, 0, 0, 0) @@ -246,7 +246,7 @@ def test_first_wednesday_of_year(): def test_first_friday_of_year(): - d = pendulum.datetime(1975, 11, 21).first_of("year", 5) + d = pendulum.datetime(1975, 11, 21).first_of("year", 4) assert_datetime(d, 1975, 1, 3, 0, 0, 0) @@ -261,7 +261,7 @@ def test_last_tuesday_of_year(): def test_last_friday_of_year(): - d = pendulum.datetime(1975, 8, 5).last_of("year", 5) + d = pendulum.datetime(1975, 8, 5).last_of("year", 4) assert_datetime(d, 1975, 12, 26, 0, 0, 0) diff --git a/tests/datetime/test_from_format.py b/tests/datetime/test_from_format.py index 10c4a23..184c0a0 100644 --- a/tests/datetime/test_from_format.py +++ b/tests/datetime/test_from_format.py @@ -81,9 +81,8 @@ def test_from_format_with_invalid_padded_day(): ("12/02/1999", "DD/MM/YYYY", "1999-02-12T00:00:00+00:00", None), ("12_02_1999", "DD_MM_YYYY", "1999-02-12T00:00:00+00:00", None), ("12:02:1999", "DD:MM:YYYY", "1999-02-12T00:00:00+00:00", None), - ("2-2-99", "D-M-YY", "2099-02-02T00:00:00+00:00", None), - ("2-2-99", "D-M-YY", "1999-02-02T00:00:00+00:00", "1990-01-01"), - ("99", "YY", "2099-01-01T00:00:00+00:00", None), + ("2-2-99", "D-M-YY", "1999-02-02T00:00:00+00:00", None), + ("99", "YY", "1999-01-01T00:00:00+00:00", None), ("300-1999", "DDD-YYYY", "1999-10-27T00:00:00+00:00", None), ("12-02-1999 2:45:10", "DD-MM-YYYY h:m:s", "1999-02-12T02:45:10+00:00", None), ("12-02-1999 12:45:10", "DD-MM-YYYY h:m:s", "1999-02-12T12:45:10+00:00", None), @@ -100,7 +99,8 @@ def test_from_format_with_invalid_padded_day(): ("Monday", "dddd", "2018-01-29T00:00:00+00:00", "2018-02-02"), ("Mon", "ddd", "2018-01-29T00:00:00+00:00", "2018-02-02"), ("Mo", "dd", "2018-01-29T00:00:00+00:00", "2018-02-02"), - ("0", "d", "2018-02-04T00:00:00+00:00", "2018-02-02"), + ("0", "d", "2018-01-29T00:00:00+00:00", "2018-02-02"), + ("6", "d", "2018-02-04T00:00:00+00:00", "2018-02-02"), ("1", "E", "2018-01-29T00:00:00+00:00", "2018-02-02"), ("March", "MMMM", "2018-03-01T00:00:00+00:00", "2018-02-02"), ("Mar", "MMM", "2018-03-01T00:00:00+00:00", "2018-02-02"), @@ -150,10 +150,7 @@ def test_from_format_with_invalid_padded_day(): ], ) def test_from_format(text, fmt, expected, now): - if now is None: - now = pendulum.datetime(2015, 11, 12) - else: - now = pendulum.parse(now) + now = pendulum.datetime(2015, 11, 12) if now is None else pendulum.parse(now) with pendulum.travel_to(now, freeze=True): assert pendulum.from_format(text, fmt).isoformat() == expected @@ -201,3 +198,25 @@ def test_strptime(): assert_datetime(d, 1975, 5, 21, 22, 32, 11) assert isinstance(d, pendulum.DateTime) assert d.timezone_name == "UTC" + + +def test_from_format_2_digit_year(): + """ + Complies with open group spec for 2 digit years + https://pubs.opengroup.org/onlinepubs/9699919799/ + + "If century is not specified, then values in the range [69,99] shall + refer to years 1969 to 1999 inclusive, and values in the + range [00,68] shall refer to years 2000 to 2068 inclusive." + """ + d = pendulum.from_format("00", "YY") + assert d.year == 2000 + + d = pendulum.from_format("68", "YY") + assert d.year == 2068 + + d = pendulum.from_format("69", "YY") + assert d.year == 1969 + + d = pendulum.from_format("99", "YY") + assert d.year == 1999 diff --git a/tests/datetime/test_getters.py b/tests/datetime/test_getters.py index 5074623..8f4c1ae 100644 --- a/tests/datetime/test_getters.py +++ b/tests/datetime/test_getters.py @@ -7,7 +7,7 @@ import pytest import pendulum from pendulum import DateTime -from pendulum.tz import timezone +from pendulum import timezone from tests.conftest import assert_date from tests.conftest import assert_time @@ -126,7 +126,8 @@ def test_utc(): assert pendulum.datetime(2012, 1, 1, tz="UTC").is_utc() assert pendulum.datetime(2012, 1, 1, tz=0).is_utc() assert not pendulum.datetime(2012, 1, 1, tz=5).is_utc() - # There is no time difference between Greenwich Mean Time and Coordinated Universal Time + # There is no time difference between Greenwich Mean Time + # and Coordinated Universal Time assert pendulum.datetime(2012, 1, 1, tz="GMT").is_utc() @@ -194,6 +195,14 @@ def test_week_of_year_last_week(): assert pendulum.datetime(2012, 12, 31).week_of_year == 1 +def test_week_of_month_edge_case(): + assert pendulum.datetime(2020, 1, 1).week_of_month == 1 + assert pendulum.datetime(2020, 1, 7).week_of_month == 2 + assert pendulum.datetime(2020, 1, 14).week_of_month == 3 + assert pendulum.datetime(2023, 1, 1).week_of_month == 1 + assert pendulum.datetime(2023, 1, 31).week_of_month == 6 + + def test_timezone(): d = pendulum.datetime(2000, 1, 1, tz="America/Toronto") assert d.timezone.name == "America/Toronto" @@ -246,3 +255,41 @@ def test_time(): t = dt.time() assert isinstance(t, pendulum.Time) assert_time(t, 10, 40, 34, 123456) + + +@pytest.mark.parametrize( + "date, expected", + [ + (pendulum.Date(2000, 1, 1), 1), + (pendulum.Date(2000, 1, 3), 2), + (pendulum.Date(2019, 12, 29), 5), + (pendulum.Date(2019, 12, 30), 6), + (pendulum.Date(2019, 12, 31), 6), + (pendulum.Date(2020, 1, 7), 2), + (pendulum.Date(2020, 1, 14), 3), + (pendulum.Date(2021, 1, 1), 1), + (pendulum.Date(2021, 1, 2), 1), + (pendulum.Date(2021, 1, 9), 2), + (pendulum.Date(2021, 1, 10), 2), + (pendulum.Date(2021, 1, 11), 3), + (pendulum.Date(2021, 1, 15), 3), + (pendulum.Date(2021, 1, 16), 3), + (pendulum.Date(2021, 1, 17), 3), + (pendulum.Date(2021, 1, 23), 4), + (pendulum.Date(2021, 1, 31), 5), + (pendulum.Date(2021, 12, 19), 3), + (pendulum.Date(2021, 12, 25), 4), + (pendulum.Date(2021, 12, 26), 4), + (pendulum.Date(2021, 12, 29), 5), + (pendulum.Date(2021, 12, 30), 5), + (pendulum.Date(2021, 12, 31), 5), + (pendulum.Date(2022, 1, 1), 1), + (pendulum.Date(2022, 1, 3), 2), + (pendulum.Date(2022, 1, 10), 3), + (pendulum.Date(2023, 1, 1), 1), + (pendulum.Date(2023, 1, 2), 2), + (pendulum.Date(2029, 12, 31), 6), + ], +) +def test_week_of_month_negative(date, expected): + assert date.week_of_month == expected diff --git a/tests/datetime/test_start_end_of.py b/tests/datetime/test_start_end_of.py index 597dbeb..1937e74 100644 --- a/tests/datetime/test_start_end_of.py +++ b/tests/datetime/test_start_end_of.py @@ -277,9 +277,49 @@ def test_start_of_with_transition(): assert d.start_of("year").offset == 3600 +def test_start_of_on_date_before_transition(): + d = pendulum.datetime(2013, 10, 27, 0, 59, 59, tz="UTC").in_timezone("Europe/Paris") + assert d.offset == 7200 + assert d.start_of("minute").offset == 7200 + assert d.start_of("hour").offset == 7200 + assert d.start_of("day").offset == 7200 + assert d.start_of("month").offset == 7200 + assert d.start_of("year").offset == 3600 + + +def test_start_of_on_date_after_transition(): + d = pendulum.datetime(2013, 10, 27, 1, 59, 59, tz="UTC").in_timezone("Europe/Paris") + assert d.offset == 3600 + assert d.start_of("minute").offset == 3600 + assert d.start_of("hour").offset == 3600 + assert d.start_of("day").offset == 7200 + assert d.start_of("month").offset == 7200 + assert d.start_of("year").offset == 3600 + + def test_end_of_with_transition(): d = pendulum.datetime(2013, 3, 31, tz="Europe/Paris") assert d.offset == 3600 assert d.end_of("month").offset == 7200 assert d.end_of("day").offset == 7200 assert d.end_of("year").offset == 3600 + + +def test_end_of_on_date_before_transition(): + d = pendulum.datetime(2013, 10, 27, 0, 0, 0, tz="UTC").in_timezone("Europe/Paris") + assert d.offset == 7200 + assert d.end_of("minute").offset == 7200 + assert d.end_of("hour").offset == 7200 + assert d.end_of("day").offset == 3600 + assert d.end_of("month").offset == 3600 + assert d.end_of("year").offset == 3600 + + +def test_end_of_on_date_after_transition(): + d = pendulum.datetime(2013, 10, 27, 1, 0, 0, tz="UTC").in_timezone("Europe/Paris") + assert d.offset == 3600 + assert d.end_of("minute").offset == 3600 + assert d.end_of("hour").offset == 3600 + assert d.end_of("day").offset == 3600 + assert d.end_of("month").offset == 3600 + assert d.end_of("year").offset == 3600 diff --git a/tests/datetime/test_strings.py b/tests/datetime/test_strings.py index 0de340d..e78dbc8 100644 --- a/tests/datetime/test_strings.py +++ b/tests/datetime/test_strings.py @@ -7,9 +7,9 @@ import pendulum def test_to_string(): d = pendulum.datetime(1975, 12, 25, 0, 0, 0, 0, tz="local") - assert str(d) == d.to_iso8601_string() + assert str(d) == "1975-12-25 00:00:00-05:00" d = pendulum.datetime(1975, 12, 25, 0, 0, 0, 123456, tz="local") - assert str(d) == d.to_iso8601_string() + assert str(d) == "1975-12-25 00:00:00.123456-05:00" def test_to_date_string(): @@ -109,11 +109,11 @@ def test_to_string_invalid(): def test_repr(): d = pendulum.datetime(1975, 12, 25, 14, 15, 16, tz="local") - expected = f"DateTime(1975, 12, 25, 14, 15, 16, tzinfo={repr(d.tzinfo)})" + expected = f"DateTime(1975, 12, 25, 14, 15, 16, tzinfo={d.tzinfo!r})" assert repr(d) == expected d = pendulum.datetime(1975, 12, 25, 14, 15, 16, 123456, tz="local") - expected = f"DateTime(1975, 12, 25, 14, 15, 16, 123456, tzinfo={repr(d.tzinfo)})" + expected = f"DateTime(1975, 12, 25, 14, 15, 16, 123456, tzinfo={d.tzinfo!r})" assert repr(d) == expected @@ -135,7 +135,7 @@ def test_for_json(): def test_format(): d = pendulum.datetime(1975, 12, 25, 14, 15, 16, tz="Europe/Paris") - assert f"{d}" == "1975-12-25T14:15:16+01:00" + assert f"{d}" == "1975-12-25 14:15:16+01:00" assert f"{d:YYYY}" == "1975" assert f"{d:%Y}" == "1975" assert f"{d:%H:%M %d.%m.%Y}" == "14:15 25.12.1975" diff --git a/tests/duration/test_behavior.py b/tests/duration/test_behavior.py index a97bbde..2442534 100644 --- a/tests/duration/test_behavior.py +++ b/tests/duration/test_behavior.py @@ -2,12 +2,15 @@ from __future__ import annotations import pickle +from copy import deepcopy from datetime import timedelta import pendulum +from tests.conftest import assert_duration -def test_pickle(): + +def test_pickle() -> None: it = pendulum.duration(days=3, seconds=2456, microseconds=123456) s = pickle.dumps(it) it2 = pickle.loads(s) @@ -15,7 +18,15 @@ def test_pickle(): assert it == it2 -def test_comparison_to_timedelta(): +def test_comparison_to_timedelta() -> None: duration = pendulum.duration(days=3) assert duration < timedelta(days=4) + + +def test_deepcopy() -> None: + duration = pendulum.duration(months=1) + copied_duration = deepcopy(duration) + + assert copied_duration == duration + assert_duration(copied_duration, months=1) diff --git a/tests/formatting/test_formatter.py b/tests/formatting/test_formatter.py index 76c7a7f..4c4b008 100644 --- a/tests/formatting/test_formatter.py +++ b/tests/formatting/test_formatter.py @@ -113,6 +113,20 @@ def test_day_of_week(): assert f.format(d, "do") == "0th" +def test_localized_day_of_week(): + f = Formatter() + d = pendulum.datetime(2016, 8, 28) + assert f.format(d, "e") == "0" + assert f.format(d, "e", locale="en-gb") == "6" + assert f.format(d.add(days=2), "e") == "2" + assert f.format(d.add(days=2), "e", locale="en-gb") == "1" + + assert f.format(d, "eo") == "1st" + assert f.format(d, "eo", locale="en-gb") == "7th" + assert f.format(d.add(days=2), "eo") == "3rd" + assert f.format(d.add(days=2), "eo", locale="en-gb") == "2nd" + + def test_day_of_iso_week(): f = Formatter() d = pendulum.datetime(2016, 8, 28) diff --git a/tests/interval/test_add_subtract.py b/tests/interval/test_add_subtract.py index 88525a3..d1f6036 100644 --- a/tests/interval/test_add_subtract.py +++ b/tests/interval/test_add_subtract.py @@ -6,8 +6,8 @@ import pendulum def test_dst_add(): start = pendulum.datetime(2017, 3, 7, tz="America/Toronto") end = start.add(days=6) - period = end - start - new_end = start + period + interval = end - start + new_end = start + interval assert new_end == end @@ -15,8 +15,8 @@ def test_dst_add(): def test_dst_add_non_variable_units(): start = pendulum.datetime(2013, 3, 31, 1, 30, tz="Europe/Paris") end = start.add(hours=1) - period = end - start - new_end = start + period + interval = end - start + new_end = start + interval assert new_end == end @@ -24,8 +24,8 @@ def test_dst_add_non_variable_units(): def test_dst_subtract(): start = pendulum.datetime(2017, 3, 7, tz="America/Toronto") end = start.add(days=6) - period = end - start - new_start = end - period + interval = end - start + new_start = end - interval assert new_start == start @@ -33,8 +33,8 @@ def test_dst_subtract(): def test_naive_subtract(): start = pendulum.naive(2013, 3, 31, 1, 30) end = start.add(hours=1) - period = end - start - new_end = start + period + interval = end - start + new_end = start + interval assert new_end == end @@ -43,7 +43,7 @@ def test_negative_difference_subtract(): start = pendulum.datetime(2018, 5, 28, 12, 34, 56, 123456) end = pendulum.datetime(2018, 1, 1) - period = end - start - new_end = start + period + interval = end - start + new_end = start + interval assert new_end == end diff --git a/tests/interval/test_behavior.py b/tests/interval/test_behavior.py index b5e057a..96a1f42 100644 --- a/tests/interval/test_behavior.py +++ b/tests/interval/test_behavior.py @@ -40,15 +40,28 @@ def test_comparison_to_timedelta(): dt1 = pendulum.datetime(2016, 11, 18) dt2 = pendulum.datetime(2016, 11, 20) - period = dt2 - dt1 + interval = dt2 - dt1 - assert period < timedelta(days=4) + assert interval < timedelta(days=4) def test_equality_to_timedelta(): dt1 = pendulum.datetime(2016, 11, 18) dt2 = pendulum.datetime(2016, 11, 20) - period = dt2 - dt1 + interval = dt2 - dt1 - assert period == timedelta(days=2) + assert interval == timedelta(days=2) + + +def test_inequality(): + dt1 = pendulum.datetime(2016, 11, 18) + dt2 = pendulum.datetime(2016, 11, 20) + dt3 = pendulum.datetime(2016, 11, 22) + + interval1 = dt2 - dt1 + interval2 = dt3 - dt2 + interval3 = dt3 - dt1 + + assert interval1 != interval2 + assert interval1 != interval3 diff --git a/tests/interval/test_construct.py b/tests/interval/test_construct.py index 024e741..550b808 100644 --- a/tests/interval/test_construct.py +++ b/tests/interval/test_construct.py @@ -72,17 +72,17 @@ def test_accuracy(): def test_dst_transition(): start = pendulum.datetime(2017, 3, 7, tz="America/Toronto") end = start.add(days=6) - period = end - start + interval = end - start - assert period.days == 5 - assert period.seconds == 82800 + assert interval.days == 5 + assert interval.seconds == 82800 - assert period.remaining_days == 6 - assert period.hours == 0 - assert period.remaining_seconds == 0 + assert interval.remaining_days == 6 + assert interval.hours == 0 + assert interval.remaining_seconds == 0 - assert period.in_days() == 6 - assert period.in_hours() == 5 * 24 + 23 + assert interval.in_days() == 6 + assert interval.in_hours() == 5 * 24 + 23 def test_timedelta_behavior(): @@ -108,14 +108,14 @@ def test_timedelta_behavior(): def test_different_timezones_same_time(): dt1 = pendulum.datetime(2013, 3, 31, 1, 30, tz="Europe/Paris") dt2 = pendulum.datetime(2013, 4, 1, 1, 30, tz="Europe/Paris") - period = dt2 - dt1 + interval = dt2 - dt1 - assert period.in_words() == "1 day" - assert period.in_hours() == 23 + assert interval.in_words() == "1 day" + assert interval.in_hours() == 23 dt1 = pendulum.datetime(2013, 3, 31, 1, 30, tz="Europe/Paris") dt2 = pendulum.datetime(2013, 4, 1, 1, 30, tz="America/Toronto") - period = dt2 - dt1 + interval = dt2 - dt1 - assert period.in_words() == "1 day 5 hours" - assert period.in_hours() == 29 + assert interval.in_words() == "1 day 5 hours" + assert interval.in_hours() == 29 diff --git a/tests/interval/test_hashing.py b/tests/interval/test_hashing.py index c18502f..ca9ef9c 100644 --- a/tests/interval/test_hashing.py +++ b/tests/interval/test_hashing.py @@ -3,21 +3,21 @@ from __future__ import annotations import pendulum -def test_periods_with_same_duration_and_different_dates(): +def test_intervals_with_same_duration_and_different_dates(): day1 = pendulum.DateTime(2018, 1, 1) day2 = pendulum.DateTime(2018, 1, 2) day3 = pendulum.DateTime(2018, 1, 2) - period1 = day2 - day1 - period2 = day3 - day2 + interval1 = day2 - day1 + interval2 = day3 - day2 - assert period1 != period2 - assert len({period1, period2}) == 2 + assert interval1 != interval2 + assert len({interval1, interval2}) == 2 -def test_periods_with_same_dates(): - period1 = pendulum.DateTime(2018, 1, 2) - pendulum.DateTime(2018, 1, 1) - period2 = pendulum.DateTime(2018, 1, 2) - pendulum.DateTime(2018, 1, 1) +def test_intervals_with_same_dates(): + interval1 = pendulum.DateTime(2018, 1, 2) - pendulum.DateTime(2018, 1, 1) + interval2 = pendulum.DateTime(2018, 1, 2) - pendulum.DateTime(2018, 1, 1) - assert period1 == period2 - assert len({period1, period2}) == 1 + assert interval1 == interval2 + assert len({interval1, interval2}) == 1 diff --git a/tests/interval/test_in_words.py b/tests/interval/test_in_words.py index 410e11f..f60e20d 100644 --- a/tests/interval/test_in_words.py +++ b/tests/interval/test_in_words.py @@ -5,66 +5,66 @@ import pendulum def test_week(): start_date = pendulum.datetime(2012, 1, 1) - period = pendulum.interval(start=start_date, end=start_date.add(weeks=1)) - assert period.in_words() == "1 week" + interval = pendulum.interval(start=start_date, end=start_date.add(weeks=1)) + assert interval.in_words() == "1 week" def test_week_and_day(): start_date = pendulum.datetime(2012, 1, 1) - period = pendulum.interval(start=start_date, end=start_date.add(weeks=1, days=1)) - assert period.in_words() == "1 week 1 day" + interval = pendulum.interval(start=start_date, end=start_date.add(weeks=1, days=1)) + assert interval.in_words() == "1 week 1 day" def test_all(): start_date = pendulum.datetime(2012, 1, 1) - period = pendulum.interval( + interval = pendulum.interval( start=start_date, end=start_date.add(years=1, months=1, days=1, seconds=1, microseconds=1), ) - assert period.in_words() == "1 year 1 month 1 day 1 second" + assert interval.in_words() == "1 year 1 month 1 day 1 second" def test_in_french(): start_date = pendulum.datetime(2012, 1, 1) - period = pendulum.interval( + interval = pendulum.interval( start=start_date, end=start_date.add(years=1, months=1, days=1, seconds=1, microseconds=1), ) - assert period.in_words(locale="fr") == "1 an 1 mois 1 jour 1 seconde" + assert interval.in_words(locale="fr") == "1 an 1 mois 1 jour 1 seconde" def test_singular_negative_values(): start_date = pendulum.datetime(2012, 1, 1) - period = pendulum.interval(start=start_date, end=start_date.subtract(days=1)) - assert period.in_words() == "-1 day" + interval = pendulum.interval(start=start_date, end=start_date.subtract(days=1)) + assert interval.in_words() == "-1 day" def test_separator(): start_date = pendulum.datetime(2012, 1, 1) - period = pendulum.interval( + interval = pendulum.interval( start=start_date, end=start_date.add(years=1, months=1, days=1, seconds=1, microseconds=1), ) - assert period.in_words(separator=", ") == "1 year, 1 month, 1 day, 1 second" + assert interval.in_words(separator=", ") == "1 year, 1 month, 1 day, 1 second" def test_subseconds(): start_date = pendulum.datetime(2012, 1, 1) - period = pendulum.interval( + interval = pendulum.interval( start=start_date, end=start_date.add(microseconds=123456) ) - assert period.in_words() == "0.12 second" + assert interval.in_words() == "0.12 second" def test_subseconds_with_seconds(): start_date = pendulum.datetime(2012, 1, 1) - period = pendulum.interval( + interval = pendulum.interval( start=start_date, end=start_date.add(seconds=12, microseconds=123456) ) - assert period.in_words() == "12 seconds" + assert interval.in_words() == "12 seconds" -def test_zero_period(): +def test_zero_interval(): start_date = pendulum.datetime(2012, 1, 1) - period = pendulum.interval(start=start_date, end=start_date) - assert period.in_words() == "0 microseconds" + interval = pendulum.interval(start=start_date, end=start_date) + assert interval.in_words() == "0 microseconds" diff --git a/tests/interval/test_range.py b/tests/interval/test_range.py index 28fe1ff..0b883e5 100644 --- a/tests/interval/test_range.py +++ b/tests/interval/test_range.py @@ -47,7 +47,7 @@ def test_iter(): dt2 = pendulum.datetime(2000, 1, 31, 12, 45, 37) p = Interval(dt1, dt2) - i = 0 # noqa: SIM113 (suggests use of enumerate) + i = 0 for dt in p: assert isinstance(dt, pendulum.DateTime) i += 1 diff --git a/tests/localization/test_cs.py b/tests/localization/test_cs.py index 71b8340..c3c2d1c 100644 --- a/tests/localization/test_cs.py +++ b/tests/localization/test_cs.py @@ -2,6 +2,7 @@ from __future__ import annotations import pendulum + locale = "cs" diff --git a/tests/localization/test_da.py b/tests/localization/test_da.py index b08adfe..34c69b1 100644 --- a/tests/localization/test_da.py +++ b/tests/localization/test_da.py @@ -2,6 +2,7 @@ from __future__ import annotations import pendulum + locale = "da" diff --git a/tests/localization/test_de.py b/tests/localization/test_de.py index 9c72b79..4abc3f5 100644 --- a/tests/localization/test_de.py +++ b/tests/localization/test_de.py @@ -2,6 +2,7 @@ from __future__ import annotations import pendulum + locale = "de" diff --git a/tests/localization/test_es.py b/tests/localization/test_es.py index 747ec6f..64d5dbb 100644 --- a/tests/localization/test_es.py +++ b/tests/localization/test_es.py @@ -2,6 +2,7 @@ from __future__ import annotations import pendulum + locale = "es" diff --git a/tests/localization/test_fa.py b/tests/localization/test_fa.py index 39d2e4a..5bb25ad 100644 --- a/tests/localization/test_fa.py +++ b/tests/localization/test_fa.py @@ -2,6 +2,7 @@ from __future__ import annotations import pendulum + locale = "fa" diff --git a/tests/localization/test_fo.py b/tests/localization/test_fo.py index f451553..a2b72de 100644 --- a/tests/localization/test_fo.py +++ b/tests/localization/test_fo.py @@ -2,6 +2,7 @@ from __future__ import annotations import pendulum + locale = "fo" diff --git a/tests/localization/test_fr.py b/tests/localization/test_fr.py index 1cfef5b..e689a19 100644 --- a/tests/localization/test_fr.py +++ b/tests/localization/test_fr.py @@ -2,6 +2,7 @@ from __future__ import annotations import pendulum + locale = "fr" diff --git a/tests/localization/test_he.py b/tests/localization/test_he.py index 6186ef2..0695a64 100644 --- a/tests/localization/test_he.py +++ b/tests/localization/test_he.py @@ -2,6 +2,7 @@ from __future__ import annotations import pendulum + locale = "he" diff --git a/tests/localization/test_id.py b/tests/localization/test_id.py index 3dd316c..3ae668d 100644 --- a/tests/localization/test_id.py +++ b/tests/localization/test_id.py @@ -2,6 +2,7 @@ from __future__ import annotations import pendulum + locale = "id" diff --git a/tests/localization/test_it.py b/tests/localization/test_it.py index 1918a2b..1f79c6e 100644 --- a/tests/localization/test_it.py +++ b/tests/localization/test_it.py @@ -2,6 +2,7 @@ from __future__ import annotations import pendulum + locale = "it" diff --git a/tests/localization/test_ja.py b/tests/localization/test_ja.py index 82457fd..6f38d05 100644 --- a/tests/localization/test_ja.py +++ b/tests/localization/test_ja.py @@ -2,6 +2,7 @@ from __future__ import annotations import pendulum + locale = "ja" diff --git a/tests/localization/test_ko.py b/tests/localization/test_ko.py index e33ca25..c03a372 100644 --- a/tests/localization/test_ko.py +++ b/tests/localization/test_ko.py @@ -2,6 +2,7 @@ from __future__ import annotations import pendulum + locale = "ko" diff --git a/tests/localization/test_lt.py b/tests/localization/test_lt.py index 71de1ac..4b75394 100644 --- a/tests/localization/test_lt.py +++ b/tests/localization/test_lt.py @@ -2,6 +2,7 @@ from __future__ import annotations import pendulum + locale = "lt" diff --git a/tests/localization/test_nb.py b/tests/localization/test_nb.py index 3f696e5..19b7d1c 100644 --- a/tests/localization/test_nb.py +++ b/tests/localization/test_nb.py @@ -2,6 +2,7 @@ from __future__ import annotations import pendulum + locale = "nb" diff --git a/tests/localization/test_nl.py b/tests/localization/test_nl.py index 68227ec..fde63b4 100644 --- a/tests/localization/test_nl.py +++ b/tests/localization/test_nl.py @@ -2,6 +2,7 @@ from __future__ import annotations import pendulum + locale = "nl" diff --git a/tests/localization/test_nn.py b/tests/localization/test_nn.py index d4b8099..7751858 100644 --- a/tests/localization/test_nn.py +++ b/tests/localization/test_nn.py @@ -2,6 +2,7 @@ from __future__ import annotations import pendulum + locale = "nn" diff --git a/tests/localization/test_pl.py b/tests/localization/test_pl.py index 2b6e707..7253096 100644 --- a/tests/localization/test_pl.py +++ b/tests/localization/test_pl.py @@ -2,6 +2,7 @@ from __future__ import annotations import pendulum + locale = "pl" diff --git a/tests/localization/test_ru.py b/tests/localization/test_ru.py index be0e645..b0a7712 100644 --- a/tests/localization/test_ru.py +++ b/tests/localization/test_ru.py @@ -2,6 +2,7 @@ from __future__ import annotations import pendulum + locale = "ru" diff --git a/tests/localization/test_sk.py b/tests/localization/test_sk.py index 5553e7f..2c18f93 100644 --- a/tests/localization/test_sk.py +++ b/tests/localization/test_sk.py @@ -2,6 +2,7 @@ from __future__ import annotations import pendulum + locale = "sk" diff --git a/tests/localization/test_sv.py b/tests/localization/test_sv.py index e0e4e65..e4b7051 100644 --- a/tests/localization/test_sv.py +++ b/tests/localization/test_sv.py @@ -2,6 +2,7 @@ from __future__ import annotations import pendulum + locale = "sv" diff --git a/tests/localization/test_tr.py b/tests/localization/test_tr.py new file mode 100644 index 0000000..5ec00ee --- /dev/null +++ b/tests/localization/test_tr.py @@ -0,0 +1,66 @@ +from __future__ import annotations + +import pendulum + + +locale = "tr" + + +def test_diff_for_humans(): + with pendulum.travel_to(pendulum.datetime(2016, 8, 29), freeze=True): + diff_for_humans() + + +def diff_for_humans(): + d = pendulum.now().subtract(seconds=1) + assert d.diff_for_humans(locale=locale) == "1 saniye önce" + + d = pendulum.now().subtract(seconds=2) + assert d.diff_for_humans(locale=locale) == "2 saniye önce" + + d = pendulum.now().subtract(minutes=1) + assert d.diff_for_humans(locale=locale) == "1 dakika önce" + + d = pendulum.now().subtract(minutes=2) + assert d.diff_for_humans(locale=locale) == "2 dakika önce" + + d = pendulum.now().subtract(hours=1) + assert d.diff_for_humans(locale=locale) == "1 saat önce" + + d = pendulum.now().subtract(hours=2) + assert d.diff_for_humans(locale=locale) == "2 saat önce" + + d = pendulum.now().subtract(days=1) + assert d.diff_for_humans(locale=locale) == "1 gün önce" + + d = pendulum.now().subtract(days=2) + assert d.diff_for_humans(locale=locale) == "2 gün önce" + + d = pendulum.now().subtract(weeks=1) + assert d.diff_for_humans(locale=locale) == "1 hafta önce" + + d = pendulum.now().subtract(weeks=2) + assert d.diff_for_humans(locale=locale) == "2 hafta önce" + + d = pendulum.now().subtract(months=1) + assert d.diff_for_humans(locale=locale) == "1 ay önce" + + d = pendulum.now().subtract(months=2) + assert d.diff_for_humans(locale=locale) == "2 ay önce" + + d = pendulum.now().subtract(years=1) + assert d.diff_for_humans(locale=locale) == "1 yıl önce" + + d = pendulum.now().subtract(years=2) + assert d.diff_for_humans(locale=locale) == "2 yıl önce" + + d = pendulum.now().add(seconds=1) + assert d.diff_for_humans(locale=locale) == "1 saniye sonra" + + d = pendulum.now().add(seconds=1) + d2 = pendulum.now() + assert d.diff_for_humans(d2, locale=locale) == "1 saniye sonra" + assert d2.diff_for_humans(d, locale=locale) == "1 saniye önce" + + assert d.diff_for_humans(d2, True, locale=locale) == "1 saniye" + assert d2.diff_for_humans(d.add(seconds=1), True, locale=locale) == "2 saniye" diff --git a/tests/parsing/test_parse_iso8601.py b/tests/parsing/test_parse_iso8601.py index 0047791..c15b9bd 100644 --- a/tests/parsing/test_parse_iso8601.py +++ b/tests/parsing/test_parse_iso8601.py @@ -8,83 +8,86 @@ import pytest from pendulum.parsing import parse_iso8601 + try: - from pendulum.parsing._extension import TZFixedOffset as FixedTimezone + from pendulum._pendulum import 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") +@pytest.mark.parametrize( + ["text", "expected"], + [ + ("2016-10", date(2016, 10, 1)), + ("2016-10-06", date(2016, 10, 6)), + # Ordinal date + ("2012-007", date(2012, 1, 7)), + ("2012007", date(2012, 1, 7)), + ("2017-079", date(2017, 3, 20)), + # Week date + ("2012-W05", date(2012, 1, 30)), + ("2008-W39-6", date(2008, 9, 27)), + ("2009-W53-7", date(2010, 1, 3)), + ("2009-W01-1", date(2008, 12, 29)), + # Time + ("12:34", time(12, 34, 0)), + ("12:34:56", time(12, 34, 56)), + ("12:34:56.123", time(12, 34, 56, 123000)), + ("12:34:56.123456", time(12, 34, 56, 123456)), + ("12:34+05:30", time(12, 34, 0, tzinfo=FixedTimezone(19800))), + ("12:34:56+05:30", time(12, 34, 56, tzinfo=FixedTimezone(19800))), + ("12:34:56.123+05:30", time(12, 34, 56, 123000, tzinfo=FixedTimezone(19800))), + ( + "12:34:56.123456+05:30", + time(12, 34, 56, 123456, tzinfo=FixedTimezone(19800)), + ), + # Datetime + ("2016-10-06T12:34:56.123456", datetime(2016, 10, 6, 12, 34, 56, 123456)), + ("2016-10-06T12:34:56.123", datetime(2016, 10, 6, 12, 34, 56, 123000)), + ("2016-10-06T12:34:56.000123", datetime(2016, 10, 6, 12, 34, 56, 123)), + ("20161006T12", datetime(2016, 10, 6, 12, 0, 0, 0)), + ("20161006T123456", datetime(2016, 10, 6, 12, 34, 56, 0)), + ("20161006T123456.123456", datetime(2016, 10, 6, 12, 34, 56, 123456)), + ("20161006 123456.123456", datetime(2016, 10, 6, 12, 34, 56, 123456)), + # Datetime with offset + ( + "2016-10-06T12:34:56.123456+05:30", + datetime(2016, 10, 6, 12, 34, 56, 123456, FixedTimezone(19800)), + ), + ( + "2016-10-06T12:34:56.123456+0530", + datetime(2016, 10, 6, 12, 34, 56, 123456, FixedTimezone(19800)), + ), + ( + "2016-10-06T12:34:56.123456-05:30", + datetime(2016, 10, 6, 12, 34, 56, 123456, FixedTimezone(-19800)), + ), + ( + "2016-10-06T12:34:56.123456-0530", + datetime(2016, 10, 6, 12, 34, 56, 123456, FixedTimezone(-19800)), + ), + ( + "2016-10-06T12:34:56.123456+05", + datetime(2016, 10, 6, 12, 34, 56, 123456, FixedTimezone(18000)), + ), + ( + "2016-10-06T12:34:56.123456-05", + datetime(2016, 10, 6, 12, 34, 56, 123456, FixedTimezone(-18000)), + ), + ( + "20161006T123456,123456-05", + datetime(2016, 10, 6, 12, 34, 56, 123456, FixedTimezone(-18000)), + ), + ( + "2016-10-06T12:34:56.123456789+05:30", + datetime(2016, 10, 6, 12, 34, 56, 123456, FixedTimezone(+19800)), + ), + # Week date with time + ("2008-W39-6T09", datetime(2008, 9, 27, 9, 0, 0, 0)), + ], +) +def test_parse_iso8601(text: str, expected: date) -> None: + assert parse_iso8601(text) == expected def test_parse_ios8601_invalid(): @@ -165,301 +168,43 @@ def test_parse_ios8601_invalid(): 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") +@pytest.mark.parametrize( + ["text", "expected"], + [ + ("P2Y3M4DT5H6M7S", (2, 3, 0, 4, 5, 6, 7, 0)), + ("P1Y2M3DT4H5M6.5S", (1, 2, 0, 3, 4, 5, 6, 500_000)), + ("P1Y2M3DT4H5M6,5S", (1, 2, 0, 3, 4, 5, 6, 500_000)), + ("P1Y2M3D", (1, 2, 0, 3, 0, 0, 0, 0)), + ("P1Y2M3.5D", (1, 2, 0, 3, 12, 0, 0, 0)), + ("P1Y2M3,5D", (1, 2, 0, 3, 12, 0, 0, 0)), + ("PT4H54M6.5S", (0, 0, 0, 0, 4, 54, 6, 500_000)), + ("PT4H54M6,5S", (0, 0, 0, 0, 4, 54, 6, 500_000)), + ("P1Y", (1, 0, 0, 0, 0, 0, 0, 0)), + ("P1M", (0, 1, 0, 0, 0, 0, 0, 0)), + ("P1W", (0, 0, 1, 0, 0, 0, 0, 0)), + ("P1.5W", (0, 0, 1, 3, 12, 0, 0, 0)), + ("P1,5W", (0, 0, 1, 3, 12, 0, 0, 0)), + ("P1D", (0, 0, 0, 1, 0, 0, 0, 0)), + ("P1.5D", (0, 0, 0, 1, 12, 0, 0, 0)), + ("P1,5D", (0, 0, 0, 1, 12, 0, 0, 0)), + ("PT1H", (0, 0, 0, 0, 1, 0, 0, 0)), + ("PT1.5H", (0, 0, 0, 0, 1, 30, 0, 0)), + ("PT1,5H", (0, 0, 0, 0, 1, 30, 0, 0)), + ("P2Y30M4DT5H6M7S", (2, 30, 0, 4, 5, 6, 7, 0)), + ], +) +def test_parse_ios8601_duration( + text: str, expected: tuple[int, int, int, int, int, int, int, int] +) -> None: + parsed = parse_iso8601(text) + + assert ( + parsed.years, + parsed.months, + parsed.weeks, + parsed.remaining_days, + parsed.hours, + parsed.minutes, + parsed.remaining_seconds, + parsed.microseconds, + ) == expected diff --git a/tests/parsing/test_parsing.py b/tests/parsing/test_parsing.py index 35dcf86..d57b82f 100644 --- a/tests/parsing/test_parsing.py +++ b/tests/parsing/test_parsing.py @@ -276,19 +276,6 @@ def test_iso8601_datetime(): 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) @@ -480,7 +467,7 @@ def test_iso8601_ordinal(): def test_iso8601_time(): now = pendulum.datetime(2015, 11, 12) - text = "201205" + text = "T201205" parsed = parse(text, now=now) diff --git a/tests/test_helpers.py b/tests/test_helpers.py index e3daeac..e9317b9 100644 --- a/tests/test_helpers.py +++ b/tests/test_helpers.py @@ -8,14 +8,22 @@ import pytz import pendulum from pendulum import timezone +from pendulum.helpers import PreciseDiff from pendulum.helpers import days_in_year from pendulum.helpers import precise_diff from pendulum.helpers import week_day def assert_diff( - diff, years=0, months=0, days=0, hours=0, minutes=0, seconds=0, microseconds=0 -): + diff: PreciseDiff, + years: int = 0, + months: int = 0, + days: int = 0, + hours: int = 0, + minutes: int = 0, + seconds: int = 0, + microseconds: int = 0, +) -> None: assert diff.years == years assert diff.months == months assert diff.days == days @@ -25,7 +33,7 @@ def assert_diff( assert diff.microseconds == microseconds -def test_precise_diff(): +def test_precise_diff() -> None: dt1 = datetime(2003, 3, 1, 0, 0, 0) dt2 = datetime(2003, 1, 31, 23, 59, 59) @@ -40,6 +48,7 @@ def test_precise_diff(): diff = precise_diff(dt1, dt2) assert_diff(diff, months=-1, seconds=-1) + assert diff.total_days == -30 diff = precise_diff(dt2, dt1) assert_diff(diff, months=1, seconds=1) @@ -76,7 +85,7 @@ def test_precise_diff(): assert_diff(diff, days=6, hours=0) -def test_precise_diff_timezone(): +def test_precise_diff_timezone() -> None: paris = pendulum.timezone("Europe/Paris") toronto = pendulum.timezone("America/Toronto") @@ -85,23 +94,26 @@ def test_precise_diff_timezone(): diff = precise_diff(dt1, dt2) assert_diff(diff, days=1, hours=0) + assert diff.total_days == 1 dt2 = toronto.datetime(2013, 4, 1, 1, 30) diff = precise_diff(dt1, dt2) assert_diff(diff, days=1, hours=5) + assert diff.total_days == 1 # pytz - paris = pytz.timezone("Europe/Paris") - toronto = pytz.timezone("America/Toronto") + paris_pytz = pytz.timezone("Europe/Paris") + toronto_pytz = pytz.timezone("America/Toronto") - dt1 = paris.localize(datetime(2013, 3, 31, 1, 30)) - dt2 = paris.localize(datetime(2013, 4, 1, 1, 30)) + dt1 = paris_pytz.localize(datetime(2013, 3, 31, 1, 30)) + dt2 = paris_pytz.localize(datetime(2013, 4, 1, 1, 30)) diff = precise_diff(dt1, dt2) assert_diff(diff, days=1, hours=0) + assert diff.total_days == 1 - dt2 = toronto.localize(datetime(2013, 4, 1, 1, 30)) + dt2 = toronto_pytz.localize(datetime(2013, 4, 1, 1, 30)) diff = precise_diff(dt1, dt2) assert_diff(diff, days=1, hours=5) @@ -111,19 +123,20 @@ def test_precise_diff_timezone(): dt2 = timezone("Europe/Paris").datetime(2018, 6, 20, 3, 40) # UTC+2 diff = precise_diff(dt1, dt2) assert_diff(diff, minutes=10) + assert diff.total_days == 0 -def test_week_day(): +def test_week_day() -> None: assert week_day(2017, 6, 2) == 5 assert week_day(2017, 1, 1) == 7 -def test_days_in_years(): +def test_days_in_years() -> None: assert days_in_year(2017) == 365 assert days_in_year(2016) == 366 -def test_locale(): +def test_locale() -> None: dt = pendulum.datetime(2000, 11, 10, 12, 34, 56, 123456) pendulum.set_locale("fr") @@ -133,7 +146,7 @@ def test_locale(): assert dt.date().format("MMMM") == "novembre" -def test_set_locale_invalid(): +def test_set_locale_invalid() -> None: with pytest.raises(ValueError): pendulum.set_locale("invalid") @@ -141,13 +154,13 @@ def test_set_locale_invalid(): @pytest.mark.parametrize( "locale", ["DE", "pt-BR", "pt-br", "PT-br", "PT-BR", "pt_br", "PT_BR", "PT_BR"] ) -def test_set_locale_malformed_locale(locale): +def test_set_locale_malformed_locale(locale: str) -> None: pendulum.set_locale(locale) pendulum.set_locale("en") -def test_week_starts_at(): +def test_week_starts_at() -> None: pendulum.week_starts_at(pendulum.SATURDAY) dt = pendulum.now().start_of("week") @@ -155,15 +168,15 @@ def test_week_starts_at(): assert dt.date().day_of_week == pendulum.SATURDAY -def test_week_starts_at_invalid_value(): +def test_week_starts_at_invalid_value() -> None: with pytest.raises(ValueError): - pendulum.week_starts_at(-1) + pendulum.week_starts_at(-1) # type: ignore[arg-type] with pytest.raises(ValueError): - pendulum.week_starts_at(11) + pendulum.week_starts_at(11) # type: ignore[arg-type] -def test_week_ends_at(): +def test_week_ends_at() -> None: pendulum.week_ends_at(pendulum.SATURDAY) dt = pendulum.now().end_of("week") @@ -171,9 +184,9 @@ def test_week_ends_at(): assert dt.date().day_of_week == pendulum.SATURDAY -def test_week_ends_at_invalid_value(): +def test_week_ends_at_invalid_value() -> None: with pytest.raises(ValueError): - pendulum.week_ends_at(-1) + pendulum.week_ends_at(-1) # type: ignore[arg-type] with pytest.raises(ValueError): - pendulum.week_ends_at(11) + pendulum.week_ends_at(11) # type: ignore[arg-type] diff --git a/tests/test_main.py b/tests/test_main.py index 1710bf2..011a6b1 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -1,12 +1,62 @@ from __future__ import annotations +from datetime import date +from datetime import datetime +from datetime import time + import pytz +from dateutil import tz + +import pendulum + from pendulum import _safe_timezone +from pendulum import timezone from pendulum.tz.timezone import Timezone -def test_safe_timezone_with_tzinfo_objects(): +def test_instance_with_naive_datetime_defaults_to_utc() -> None: + now = pendulum.instance(datetime.now()) + assert now.timezone_name == "UTC" + + +def test_instance_with_aware_datetime() -> None: + now = pendulum.instance(datetime.now(timezone("Europe/Paris"))) + assert now.timezone_name == "Europe/Paris" + + +def test_instance_with_aware_datetime_pytz() -> None: + now = pendulum.instance(datetime.now(pytz.timezone("Europe/Paris"))) + assert now.timezone_name == "Europe/Paris" + + +def test_instance_with_aware_datetime_any_tzinfo() -> None: + dt = datetime(2016, 8, 7, 12, 34, 56, tzinfo=tz.gettz("Europe/Paris")) + now = pendulum.instance(dt) + assert now.timezone_name == "+02:00" + + +def test_instance_with_date() -> None: + dt = pendulum.instance(date(2022, 12, 23)) + + assert isinstance(dt, pendulum.Date) + + +def test_instance_with_naive_time() -> None: + dt = pendulum.instance(time(12, 34, 56, 123456)) + + assert isinstance(dt, pendulum.Time) + + +def test_instance_with_aware_time() -> None: + dt = pendulum.instance(time(12, 34, 56, 123456, tzinfo=timezone("Europe/Paris"))) + + assert isinstance(dt, pendulum.Time) + assert isinstance(dt.tzinfo, Timezone) + assert dt.tzinfo.name == "Europe/Paris" + + +def test_safe_timezone_with_tzinfo_objects() -> None: tz = _safe_timezone(pytz.timezone("Europe/Paris")) assert isinstance(tz, Timezone) diff --git a/tests/test_parsing.py b/tests/test_parsing.py index 0e5308c..f01653a 100644 --- a/tests/test_parsing.py +++ b/tests/test_parsing.py @@ -8,13 +8,14 @@ from tests.conftest import assert_duration from tests.conftest import assert_time -def test_parse(): +def test_parse() -> None: text = "2016-10-16T12:34:56.123456+01:30" dt = pendulum.parse(text) assert isinstance(dt, pendulum.DateTime) assert_datetime(dt, 2016, 10, 16, 12, 34, 56, 123456) + assert dt.tz is not None assert dt.tz.name == "+01:30" assert dt.offset == 5400 @@ -36,16 +37,18 @@ def test_parse(): assert dt.offset == 0 -def test_parse_with_timezone(): +def test_parse_with_timezone() -> None: text = "2016-10-16T12:34:56.123456" dt = pendulum.parse(text, tz="Europe/Paris") + assert isinstance(dt, pendulum.DateTime) assert_datetime(dt, 2016, 10, 16, 12, 34, 56, 123456) + assert dt.tz is not None assert dt.tz.name == "Europe/Paris" assert dt.offset == 7200 -def test_parse_exact(): +def test_parse_exact() -> None: text = "2016-10-16T12:34:56.123456+01:30" dt = pendulum.parse(text, exact=True) @@ -76,7 +79,7 @@ def test_parse_exact(): assert_time(dt, 13, 0, 0) -def test_parse_duration(): +def test_parse_duration() -> None: text = "P2Y3M4DT5H6M7S" duration = pendulum.parse(text) @@ -92,39 +95,39 @@ def test_parse_duration(): assert_duration(duration, 0, 0, 2, 0, 0, 0, 0) -def test_parse_interval(): +def test_parse_interval() -> None: text = "2008-05-11T15:30:00Z/P1Y2M10DT2H30M" - period = pendulum.parse(text) + interval = pendulum.parse(text) - assert isinstance(period, pendulum.Interval) - assert_datetime(period.start, 2008, 5, 11, 15, 30, 0, 0) - assert period.start.offset == 0 - assert_datetime(period.end, 2009, 7, 21, 18, 0, 0, 0) - assert period.end.offset == 0 + assert isinstance(interval, pendulum.Interval) + assert_datetime(interval.start, 2008, 5, 11, 15, 30, 0, 0) + assert interval.start.offset == 0 + assert_datetime(interval.end, 2009, 7, 21, 18, 0, 0, 0) + assert interval.end.offset == 0 text = "P1Y2M10DT2H30M/2008-05-11T15:30:00Z" - period = pendulum.parse(text) + interval = pendulum.parse(text) - assert isinstance(period, pendulum.Interval) - assert_datetime(period.start, 2007, 3, 1, 13, 0, 0, 0) - assert period.start.offset == 0 - assert_datetime(period.end, 2008, 5, 11, 15, 30, 0, 0) - assert period.end.offset == 0 + assert isinstance(interval, pendulum.Interval) + assert_datetime(interval.start, 2007, 3, 1, 13, 0, 0, 0) + assert interval.start.offset == 0 + assert_datetime(interval.end, 2008, 5, 11, 15, 30, 0, 0) + assert interval.end.offset == 0 text = "2007-03-01T13:00:00Z/2008-05-11T15:30:00Z" - period = pendulum.parse(text) + interval = pendulum.parse(text) - assert isinstance(period, pendulum.Interval) - assert_datetime(period.start, 2007, 3, 1, 13, 0, 0, 0) - assert period.start.offset == 0 - assert_datetime(period.end, 2008, 5, 11, 15, 30, 0, 0) - assert period.end.offset == 0 + assert isinstance(interval, pendulum.Interval) + assert_datetime(interval.start, 2007, 3, 1, 13, 0, 0, 0) + assert interval.start.offset == 0 + assert_datetime(interval.end, 2008, 5, 11, 15, 30, 0, 0) + assert interval.end.offset == 0 -def test_parse_now(): +def test_parse_now() -> None: dt = pendulum.parse("now") assert dt.timezone_name == "America/Toronto" @@ -135,7 +138,7 @@ def test_parse_now(): assert pendulum.parse("now") == mock_now -def test_parse_with_utc_timezone(): +def test_parse_with_utc_timezone() -> None: dt = pendulum.parse("2020-02-05T20:05:37.364951Z") assert dt.to_iso8601_string() == "2020-02-05T20:05:37.364951Z" diff --git a/tests/testing/test_time_travel.py b/tests/testing/test_time_travel.py index dd496e3..5e7a49b 100644 --- a/tests/testing/test_time_travel.py +++ b/tests/testing/test_time_travel.py @@ -9,6 +9,7 @@ import pendulum from pendulum.utils._compat import PYPY + if TYPE_CHECKING: from typing import Generator diff --git a/tests/time/test_comparison.py b/tests/time/test_comparison.py index f1ef275..23dd176 100644 --- a/tests/time/test_comparison.py +++ b/tests/time/test_comparison.py @@ -28,7 +28,7 @@ def test_equal_to_false(): def test_not_equal_to_none(): t1 = pendulum.time(1, 2, 3) - assert t1 != None # noqa + assert t1 is not None def test_greater_than_true(): diff --git a/tests/tz/test_helpers.py b/tests/tz/test_helpers.py index edec6fd..9402372 100644 --- a/tests/tz/test_helpers.py +++ b/tests/tz/test_helpers.py @@ -2,7 +2,7 @@ from __future__ import annotations import pytest -from pendulum.tz import timezone +from pendulum import timezone from pendulum.tz.exceptions import InvalidTimezone from pendulum.tz.timezone import FixedTimezone from pendulum.tz.timezone import Timezone diff --git a/tests/tz/test_timezone.py b/tests/tz/test_timezone.py index 655267d..792beb0 100644 --- a/tests/tz/test_timezone.py +++ b/tests/tz/test_timezone.py @@ -274,7 +274,10 @@ def test_after_last_transition(): @pytest.mark.skip( - reason="zoneinfo does not currently support POSIX transition rules to go beyond the last fixed transition." + reason=( + "zoneinfo does not currently support POSIX transition" + " rules to go beyond the last fixed transition." + ) ) def test_on_last_transition(): tz = pendulum.timezone("Europe/Paris") @@ -406,7 +409,10 @@ def test_just_before_last_transition(): @pytest.mark.skip( - reason="zoneinfo does not currently support POSIX transition rules to go beyond the last fixed transition." + reason=( + "zoneinfo does not currently support POSIX transition" + " rules to go beyond the last fixed transition." + ) ) def test_timezones_are_extended(): tz = pendulum.timezone("Europe/Paris") -- cgit v1.2.3