diff --git a/.coveragerc b/.coveragerc index 38ef9b9..9a69990 100644 --- a/.coveragerc +++ b/.coveragerc @@ -1,6 +1,6 @@ [run] source = . -omit = ./venv/*,*tests*,*__init__.py,build/*,dist/*,docs/* +omit = ./venv/*,*tests*,*__init__.py,build/*,dist/*,docs/*,setup.py [report] -omit = ./venv/*,*tests*,*__init__.py,build/*,dist/*,docs/* +omit = ./venv/*,*tests*,*__init__.py,build/*,dist/*,docs/*,setup.py diff --git a/CHANGELOG.md b/CHANGELOG.md index 51133d5..eb6a589 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,12 +5,11 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). -## [1.1.0] - 2024-01-06 +--- -### Fixed - -- `generate_legal_process` [#325](https://github.com/brazilian-utils/brutils-python/pull/325) +## [1.1.0] - 2024-06-17 ### Added -- Utilitário `generate_voter_id` [#220](https://github.com/brazilian-utils/brutils-python/pull/220) +- Added support for `ISOWeekday`, meaning the int value of the weekdays follow the ISO-8601 standard: from 1 (Monday) to 7 (Sunday), to all weekday-based operations. You can also pass `int` or `str` objects corresponding to Pythonic weekdays. +- Added support for calling any method on sequences. Instead of passing a single temporal-like, you can pass any sequence of temporal-likes (for instance `list`, `np.ndarray`, `pd.Series`, etc.) and get back the same sequence with all temporal objects adjusted. diff --git a/pyproject.toml b/pyproject.toml index c3ad9a9..581ff36 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -5,7 +5,7 @@ build-backend = "setuptools.build_meta" [project] name = "temporal_adjuster" dynamic = ["dependencies"] -version = "1.0.2" +version = "1.1.0" description = "Adjusters are a key tool for modifying temporal objects. They exist to externalize the process of adjustment, permitting different approaches, as per the strategy design pattern. Temporal Adjuster provides tools that help pinpoint very specific moments in time, without having to manually count days, weeks, or months." requires-python = ">= 3.7" authors = [ diff --git a/temporal_adjuster/common/decorators/sequence_processor.py b/temporal_adjuster/common/decorators/sequence_processor.py index 357fd3e..71a18c0 100644 --- a/temporal_adjuster/common/decorators/sequence_processor.py +++ b/temporal_adjuster/common/decorators/sequence_processor.py @@ -10,7 +10,7 @@ def sequenceable(target: str): This decorator is used to process if a sequence of values passed as an argument to a function. The function is called for each value in the sequence, and the result is stored in the same position in the sequence. """ - def decorator(func: Callable[..., T]) -> Callable[..., Union[T, Sequence[T]]]: + def decorator(func): @wraps(func) def wrapper(*args, **kwargs) -> Union[T, Sequence[T]]: # Get the function signature diff --git a/temporal_adjuster/modules/weekday_operations.py b/temporal_adjuster/modules/weekday_operations.py index d89de9a..793f9ae 100644 --- a/temporal_adjuster/modules/weekday_operations.py +++ b/temporal_adjuster/modules/weekday_operations.py @@ -1,3 +1,5 @@ +from typing import Sequence, Union + from dateutil.relativedelta import relativedelta from ..common.decorators import sequenceable @@ -8,9 +10,31 @@ class _TemporalAdjusterForWeekday: + @staticmethod + def __normalize_weekday(weekday: Union[Weekday, ISOWeekday, str, int]) -> Weekday: + """ + Parses the given weekday to the Pythonic format. + + Args: + weekday (Union[Weekday, ISOWeekday, str, int]): The weekday to parse. + + Returns: + Weekday: The parsed weekday. + """ + if type(weekday) == str: + return Weekday[weekday.upper()] + + elif type(weekday) == int: + return Weekday(weekday) + + else: + return weekday if isinstance(weekday, Weekday) else Weekday[weekday.name] + @staticmethod @sequenceable(target="date") - def next(weekday: Weekday, date: DateT) -> DateT: + def next( + weekday: Union[Weekday, ISOWeekday], date: Union[DateT, Sequence[DateT]] + ) -> Union[DateT, Sequence[DateT]]: """ Returns the next date of the given day of the week. @@ -21,6 +45,8 @@ def next(weekday: Weekday, date: DateT) -> DateT: Returns: DateT: The next date of the given day of the week. """ + weekday = _TemporalAdjusterForWeekday.__normalize_weekday(weekday) + return ( date + relativedelta(weekday=weekday.value) if date.weekday() != weekday.value @@ -29,7 +55,9 @@ def next(weekday: Weekday, date: DateT) -> DateT: @staticmethod @sequenceable(target="date") - def next_or_same(weekday: Weekday, date: DateT) -> DateT: + def next_or_same( + weekday: Union[Weekday, ISOWeekday], date: Union[DateT, Sequence[DateT]] + ) -> Union[DateT, Sequence[DateT]]: """ Returns the next date of the given day of the week. If the given date is the same day of the week, the given date is returned. @@ -40,6 +68,8 @@ def next_or_same(weekday: Weekday, date: DateT) -> DateT: Returns: DateT: The next date of the given day of the week. """ + weekday = _TemporalAdjusterForWeekday.__normalize_weekday(weekday) + return ( date if date.weekday() == weekday.value @@ -48,7 +78,9 @@ def next_or_same(weekday: Weekday, date: DateT) -> DateT: @staticmethod @sequenceable(target="date") - def last(weekday: Weekday, date: DateT) -> DateT: + def last( + weekday: Union[Weekday, ISOWeekday], date: Union[DateT, Sequence[DateT]] + ) -> Union[DateT, Sequence[DateT]]: """ Returns the last date of the given day of the week. @@ -59,6 +91,8 @@ def last(weekday: Weekday, date: DateT) -> DateT: Returns: DateT: The last date of the given day of the week. """ + weekday = _TemporalAdjusterForWeekday.__normalize_weekday(weekday) + return ( _TemporalAdjusterForWeekday.next(weekday, date) - relativedelta(weeks=1) if date.weekday() != weekday.value @@ -68,7 +102,9 @@ def last(weekday: Weekday, date: DateT) -> DateT: @staticmethod @sequenceable(target="date") - def last_or_same(weekday: Weekday, date: DateT) -> DateT: + def last_or_same( + weekday: Union[Weekday, ISOWeekday], date: Union[DateT, Sequence[DateT]] + ) -> Union[DateT, Sequence[DateT]]: """ Returns the last date of the given day of the week. If the given date is the same day of the week, the given date is returned. @@ -79,6 +115,8 @@ def last_or_same(weekday: Weekday, date: DateT) -> DateT: Returns: DateT: The last date of the given day of the week. """ + weekday = _TemporalAdjusterForWeekday.__normalize_weekday(weekday) + return ( date if date.weekday() == weekday.value @@ -87,7 +125,9 @@ def last_or_same(weekday: Weekday, date: DateT) -> DateT: @staticmethod @sequenceable(target="date") - def first_of_month(weekday: Weekday, date: DateT) -> DateT: + def first_of_month( + weekday: Union[Weekday, ISOWeekday], date: Union[DateT, Sequence[DateT]] + ) -> Union[DateT, Sequence[DateT]]: """ Returns the first date of the given day of the week in the month of the given date. @@ -98,11 +138,15 @@ def first_of_month(weekday: Weekday, date: DateT) -> DateT: Returns: DateT: The first date of the given day of the week in the month of the given date. """ + weekday = _TemporalAdjusterForWeekday.__normalize_weekday(weekday) + return date.replace(day=1) + relativedelta(weekday=weekday.value) @staticmethod @sequenceable(target="date") - def first_of_next_month(weekday: Weekday, date: DateT) -> DateT: + def first_of_next_month( + weekday: Union[Weekday, ISOWeekday], date: Union[DateT, Sequence[DateT]] + ) -> Union[DateT, Sequence[DateT]]: """ Returns the first date of the given day of the week in the month after the month of the given date. @@ -113,13 +157,17 @@ def first_of_next_month(weekday: Weekday, date: DateT) -> DateT: Returns: DateT: The first date of the given day of the week in the month after the month of the given date. """ + weekday = _TemporalAdjusterForWeekday.__normalize_weekday(weekday) + return _TemporalAdjusterForWeekday.first_of_month( weekday, _TemporalAdjusterForFirstAndLastDays.first_day_of_next_month(date) ) @staticmethod @sequenceable(target="date") - def first_of_last_month(weekday: Weekday, date: DateT) -> DateT: + def first_of_last_month( + weekday: Union[Weekday, ISOWeekday], date: Union[DateT, Sequence[DateT]] + ) -> Union[DateT, Sequence[DateT]]: """ Returns the first date of the given day of the week in the month before the month of the given date. @@ -130,13 +178,17 @@ def first_of_last_month(weekday: Weekday, date: DateT) -> DateT: Returns: DateT: The first date of the given day of the week in the month before the month of the given date. """ + weekday = _TemporalAdjusterForWeekday.__normalize_weekday(weekday) + return _TemporalAdjusterForWeekday.first_of_month( weekday, _TemporalAdjusterForFirstAndLastDays.first_day_of_last_month(date) ) @staticmethod @sequenceable(target="date") - def last_of_month(weekday: Weekday, date: DateT) -> DateT: + def last_of_month( + weekday: Union[Weekday, ISOWeekday], date: Union[DateT, Sequence[DateT]] + ) -> Union[DateT, Sequence[DateT]]: """ Returns the last date of the given day of the week in the month of the given date. @@ -147,13 +199,17 @@ def last_of_month(weekday: Weekday, date: DateT) -> DateT: Returns: DateT: The last date of the given day of the week in the month of the given date. """ + weekday = _TemporalAdjusterForWeekday.__normalize_weekday(weekday) + return _TemporalAdjusterForWeekday.last( weekday, date.replace(day=1) + relativedelta(months=1) ) @staticmethod @sequenceable(target="date") - def last_of_next_month(weekday: Weekday, date: DateT) -> DateT: + def last_of_next_month( + weekday: Union[Weekday, ISOWeekday], date: Union[DateT, Sequence[DateT]] + ) -> Union[DateT, Sequence[DateT]]: """ Returns the last date of the given day of the week in the month after the month of the given date. @@ -164,13 +220,17 @@ def last_of_next_month(weekday: Weekday, date: DateT) -> DateT: Returns: DateT: The last date of the given day of the week in the month after the month of the given date. """ + weekday = _TemporalAdjusterForWeekday.__normalize_weekday(weekday) + return _TemporalAdjusterForWeekday.last_of_month( weekday, _TemporalAdjusterForFirstAndLastDays.first_day_of_next_month(date) ) @staticmethod @sequenceable(target="date") - def last_of_last_month(weekday: Weekday, date: DateT) -> DateT: + def last_of_last_month( + weekday: Union[Weekday, ISOWeekday], date: Union[DateT, Sequence[DateT]] + ) -> Union[DateT, Sequence[DateT]]: """ Returns the last date of the given day of the week in the month before the month of the given date. @@ -181,13 +241,17 @@ def last_of_last_month(weekday: Weekday, date: DateT) -> DateT: Returns: DateT: The last date of the given day of the week in the month before the month of the given date. """ + weekday = _TemporalAdjusterForWeekday.__normalize_weekday(weekday) + return _TemporalAdjusterForWeekday.last_of_month( weekday, _TemporalAdjusterForFirstAndLastDays.first_day_of_last_month(date) ) @staticmethod @sequenceable(target="date") - def first_of_year(weekday: Weekday, date: DateT) -> DateT: + def first_of_year( + weekday: Union[Weekday, ISOWeekday], date: Union[DateT, Sequence[DateT]] + ) -> Union[DateT, Sequence[DateT]]: """ Returns the first date of the given day of the week in the year of the given date. @@ -198,11 +262,15 @@ def first_of_year(weekday: Weekday, date: DateT) -> DateT: Returns: DateT: The first date of the given day of the week in the year of the given date. """ + weekday = _TemporalAdjusterForWeekday.__normalize_weekday(weekday) + return date.replace(month=1, day=1) + relativedelta(weekday=weekday.value) @staticmethod @sequenceable(target="date") - def first_of_next_year(weekday: Weekday, date: DateT) -> DateT: + def first_of_next_year( + weekday: Union[Weekday, ISOWeekday], date: Union[DateT, Sequence[DateT]] + ) -> Union[DateT, Sequence[DateT]]: """ Returns the first date of the given day of the week in the year after the year of the given date. @@ -213,13 +281,17 @@ def first_of_next_year(weekday: Weekday, date: DateT) -> DateT: Returns: DateT: The first date of the given day of the week in the year after the year of the given date. """ + weekday = _TemporalAdjusterForWeekday.__normalize_weekday(weekday) + return _TemporalAdjusterForWeekday.first_of_year( weekday, _TemporalAdjusterForFirstAndLastDays.first_day_of_next_year(date) ) @staticmethod @sequenceable(target="date") - def first_of_last_year(weekday: Weekday, date: DateT) -> DateT: + def first_of_last_year( + weekday: Union[Weekday, ISOWeekday], date: Union[DateT, Sequence[DateT]] + ) -> Union[DateT, Sequence[DateT]]: """ Returns the first date of the given day of the week in the year before the year of the given date. @@ -230,13 +302,17 @@ def first_of_last_year(weekday: Weekday, date: DateT) -> DateT: Returns: DateT: The first date of the given day of the week in the year before the year of the given date. """ + weekday = _TemporalAdjusterForWeekday.__normalize_weekday(weekday) + return _TemporalAdjusterForWeekday.first_of_year( weekday, _TemporalAdjusterForFirstAndLastDays.first_day_of_last_year(date) ) @staticmethod @sequenceable(target="date") - def last_of_year(weekday: Weekday, date: DateT) -> DateT: + def last_of_year( + weekday: Union[Weekday, ISOWeekday], date: Union[DateT, Sequence[DateT]] + ) -> Union[DateT, Sequence[DateT]]: """ Returns the last date of the given day of the week in the year of the given date. @@ -247,11 +323,15 @@ def last_of_year(weekday: Weekday, date: DateT) -> DateT: Returns: DateT: The last date of the given day of the week in the year of the given date. """ + weekday = _TemporalAdjusterForWeekday.__normalize_weekday(weekday) + return _TemporalAdjusterForWeekday.last(weekday, date.replace(month=12, day=31)) @staticmethod @sequenceable(target="date") - def last_of_next_year(weekday: Weekday, date: DateT) -> DateT: + def last_of_next_year( + weekday: Union[Weekday, ISOWeekday], date: Union[DateT, Sequence[DateT]] + ) -> Union[DateT, Sequence[DateT]]: """ Returns the last date of the given day of the week in the year after the year of the given date. @@ -262,13 +342,17 @@ def last_of_next_year(weekday: Weekday, date: DateT) -> DateT: Returns: DateT: The last date of the given day of the week in the year after the year of the given date. """ + weekday = _TemporalAdjusterForWeekday.__normalize_weekday(weekday) + return _TemporalAdjusterForWeekday.last_of_year( weekday, _TemporalAdjusterForFirstAndLastDays.first_day_of_next_year(date) ) @staticmethod @sequenceable(target="date") - def last_of_last_year(weekday: Weekday, date: DateT) -> DateT: + def last_of_last_year( + weekday: Union[Weekday, ISOWeekday], date: Union[DateT, Sequence[DateT]] + ) -> Union[DateT, Sequence[DateT]]: """ Returns the last date of the given day of the week in the year before the year of the given date. @@ -279,13 +363,17 @@ def last_of_last_year(weekday: Weekday, date: DateT) -> DateT: Returns: DateT: The last date of the given day of the week in the year before the year of the given date. """ + weekday = _TemporalAdjusterForWeekday.__normalize_weekday(weekday) + return _TemporalAdjusterForWeekday.last_of_year( weekday, _TemporalAdjusterForFirstAndLastDays.first_day_of_last_year(date) ) @staticmethod @sequenceable(target="date") - def nth_from_date(weekday: Weekday, date: DateT, n: int) -> DateT: + def nth_from_date( + weekday: Union[Weekday, ISOWeekday], date: Union[DateT, Sequence[DateT]], n: int + ) -> Union[DateT, Sequence[DateT]]: """ Returns the nth date of the given day of the week from the given date. @@ -301,11 +389,15 @@ def nth_from_date(weekday: Weekday, date: DateT, n: int) -> DateT: Returns: DateT: The nth date of the given day of the week from the given date. """ + weekday = _TemporalAdjusterForWeekday.__normalize_weekday(weekday) + return date + relativedelta(weekday=weekday.value, weeks=n - 1) @staticmethod @sequenceable(target="date") - def nth_of_month(weekday: Weekday, date: DateT, n: int) -> DateT: + def nth_of_month( + weekday: Union[Weekday, ISOWeekday], date: Union[DateT, Sequence[DateT]], n: int + ) -> Union[DateT, Sequence[DateT]]: """ Returns the nth date of the given day of the week in the month of the given date. @@ -321,6 +413,8 @@ def nth_of_month(weekday: Weekday, date: DateT, n: int) -> DateT: Returns: DateT: The nth date of the given day of the week in the month of the given date. """ + weekday = _TemporalAdjusterForWeekday.__normalize_weekday(weekday) + if n < 1 or n > 5: raise ValueError(f"The value of n must be between 1 and 5, but is {n}.") @@ -337,7 +431,9 @@ def nth_of_month(weekday: Weekday, date: DateT, n: int) -> DateT: @staticmethod @sequenceable(target="date") - def nth_of_year(weekday: Weekday, date: DateT, n: int) -> DateT: + def nth_of_year( + weekday: Union[Weekday, ISOWeekday], date: Union[DateT, Sequence[DateT]], n: int + ) -> Union[DateT, Sequence[DateT]]: """ Returns the nth date of the given day of the week in the year of the given date. @@ -353,6 +449,8 @@ def nth_of_year(weekday: Weekday, date: DateT, n: int) -> DateT: Returns: DateT: The nth date of the given day of the week in the year of the given date. """ + weekday = _TemporalAdjusterForWeekday.__normalize_weekday(weekday) + if n < 1 or n > 54: raise ValueError(f"The value of n must be between 1 and 54, but is {n}.") diff --git a/tests/test_sequenceable.py b/tests/test_sequenceable.py index a5b7571..83184b7 100644 --- a/tests/test_sequenceable.py +++ b/tests/test_sequenceable.py @@ -1,4 +1,4 @@ -from datetime import date, datetime +from datetime import date from unittest import TestCase from pandas import Series diff --git a/tests/test_weekday_operations.py b/tests/test_weekday_operations.py index 92d4c78..6296db4 100644 --- a/tests/test_weekday_operations.py +++ b/tests/test_weekday_operations.py @@ -1,10 +1,7 @@ from datetime import date, datetime from unittest import TestCase -from numpy import asarray -from pandas import Series - -from temporal_adjuster.common.enums import Weekday +from temporal_adjuster.common.enums import ISOWeekday, Weekday from temporal_adjuster.common.exceptions import DateError from temporal_adjuster.temporal_adjuster import TemporalAdjuster @@ -15,9 +12,15 @@ def test_next_success(self): (Weekday.SATURDAY, date(2024, 6, 13), date(2024, 6, 15)), (Weekday.SATURDAY, date(2024, 6, 15), date(2024, 6, 22)), (Weekday.SATURDAY, date(2024, 12, 31), date(2025, 1, 4)), - (Weekday.SATURDAY, datetime(2024, 6, 13), datetime(2024, 6, 15)), - (Weekday.SATURDAY, datetime(2024, 6, 15), datetime(2024, 6, 22)), - (Weekday.SATURDAY, datetime(2024, 12, 31), datetime(2025, 1, 4)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), datetime(2024, 6, 15)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 15), datetime(2024, 6, 22)), + (ISOWeekday.SATURDAY, datetime(2024, 12, 31), datetime(2025, 1, 4)), + ("SATURDAY", datetime(2024, 6, 13), datetime(2024, 6, 15)), + ("SATURDAY", datetime(2024, 6, 15), datetime(2024, 6, 22)), + ("SATURDAY", datetime(2024, 12, 31), datetime(2025, 1, 4)), + (5, datetime(2024, 6, 13), datetime(2024, 6, 15)), + (5, datetime(2024, 6, 15), datetime(2024, 6, 22)), + (5, datetime(2024, 12, 31), datetime(2025, 1, 4)), ] for index, test in enumerate(tests): @@ -26,23 +29,23 @@ def test_next_success(self): ): test_input_weekday, test_input_date, test_expected_output = test + output = TemporalAdjuster.next(test_input_weekday, test_input_date) + self.assertEqual( - TemporalAdjuster.next(test_input_weekday, test_input_date), + output, test_expected_output, ) - self.assertEqual( - test_input_weekday.value, test_expected_output.weekday() - ) + self.assertEqual(output.weekday(), test_expected_output.weekday()) def test_next_or_same_success(self): tests = [ (Weekday.SATURDAY, date(2024, 6, 13), date(2024, 6, 15)), (Weekday.SATURDAY, date(2024, 6, 15), date(2024, 6, 15)), (Weekday.SATURDAY, date(2024, 12, 31), date(2025, 1, 4)), - (Weekday.SATURDAY, datetime(2024, 6, 13), datetime(2024, 6, 15)), - (Weekday.SATURDAY, datetime(2024, 6, 15), datetime(2024, 6, 15)), - (Weekday.SATURDAY, datetime(2024, 12, 31), datetime(2025, 1, 4)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), datetime(2024, 6, 15)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 15), datetime(2024, 6, 15)), + (ISOWeekday.SATURDAY, datetime(2024, 12, 31), datetime(2025, 1, 4)), ] for index, test in enumerate(tests): @@ -51,23 +54,25 @@ def test_next_or_same_success(self): ): test_input_weekday, test_input_date, test_expected_output = test - self.assertEqual( - TemporalAdjuster.next_or_same(test_input_weekday, test_input_date), - test_expected_output, + output = TemporalAdjuster.next_or_same( + test_input_weekday, test_input_date ) self.assertEqual( - test_input_weekday.value, test_expected_output.weekday() + output, + test_expected_output, ) + self.assertEqual(output.weekday(), test_expected_output.weekday()) + def test_last_success(self): tests = [ (Weekday.SATURDAY, date(2024, 6, 13), date(2024, 6, 8)), (Weekday.SATURDAY, date(2024, 6, 15), date(2024, 6, 8)), (Weekday.SATURDAY, date(2025, 1, 1), date(2024, 12, 28)), - (Weekday.SATURDAY, datetime(2024, 6, 13), datetime(2024, 6, 8)), - (Weekday.SATURDAY, datetime(2024, 6, 15), datetime(2024, 6, 8)), - (Weekday.SATURDAY, datetime(2025, 1, 1), datetime(2024, 12, 28)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), datetime(2024, 6, 8)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 15), datetime(2024, 6, 8)), + (ISOWeekday.SATURDAY, datetime(2025, 1, 1), datetime(2024, 12, 28)), ] for index, test in enumerate(tests): @@ -76,23 +81,23 @@ def test_last_success(self): ): test_input_weekday, test_input_date, test_expected_output = test + output = TemporalAdjuster.last(test_input_weekday, test_input_date) + self.assertEqual( - TemporalAdjuster.last(test_input_weekday, test_input_date), + output, test_expected_output, ) - self.assertEqual( - test_input_weekday.value, test_expected_output.weekday() - ) + self.assertEqual(output.weekday(), test_expected_output.weekday()) def test_last_or_same_success(self): tests = [ (Weekday.SATURDAY, date(2024, 6, 13), date(2024, 6, 8)), (Weekday.SATURDAY, date(2024, 6, 15), date(2024, 6, 15)), (Weekday.SATURDAY, date(2025, 1, 1), date(2024, 12, 28)), - (Weekday.SATURDAY, datetime(2024, 6, 13), datetime(2024, 6, 8)), - (Weekday.SATURDAY, datetime(2024, 6, 15), datetime(2024, 6, 15)), - (Weekday.SATURDAY, datetime(2025, 1, 1), datetime(2024, 12, 28)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), datetime(2024, 6, 8)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 15), datetime(2024, 6, 15)), + (ISOWeekday.SATURDAY, datetime(2025, 1, 1), datetime(2024, 12, 28)), ] for index, test in enumerate(tests): @@ -101,23 +106,25 @@ def test_last_or_same_success(self): ): test_input_weekday, test_input_date, test_expected_output = test - self.assertEqual( - TemporalAdjuster.last_or_same(test_input_weekday, test_input_date), - test_expected_output, + output = TemporalAdjuster.last_or_same( + test_input_weekday, test_input_date ) self.assertEqual( - test_input_weekday.value, test_expected_output.weekday() + output, + test_expected_output, ) + self.assertEqual(output.weekday(), test_expected_output.weekday()) + def test_first_of_month_success(self): tests = [ (Weekday.SATURDAY, date(2024, 6, 13), date(2024, 6, 1)), (Weekday.SATURDAY, date(2024, 6, 15), date(2024, 6, 1)), (Weekday.SATURDAY, date(2025, 1, 1), date(2025, 1, 4)), - (Weekday.SATURDAY, datetime(2024, 6, 13), datetime(2024, 6, 1)), - (Weekday.SATURDAY, datetime(2024, 6, 15), datetime(2024, 6, 1)), - (Weekday.SATURDAY, datetime(2025, 1, 1), datetime(2025, 1, 4)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), datetime(2024, 6, 1)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 15), datetime(2024, 6, 1)), + (ISOWeekday.SATURDAY, datetime(2025, 1, 1), datetime(2025, 1, 4)), ] for index, test in enumerate(tests): @@ -126,25 +133,25 @@ def test_first_of_month_success(self): ): test_input_weekday, test_input_date, test_expected_output = test - self.assertEqual( - TemporalAdjuster.first_of_month( - test_input_weekday, test_input_date - ), - test_expected_output, + output = TemporalAdjuster.first_of_month( + test_input_weekday, test_input_date ) self.assertEqual( - test_input_weekday.value, test_expected_output.weekday() + output, + test_expected_output, ) + self.assertEqual(output.weekday(), test_expected_output.weekday()) + def test_first_of_next_month_success(self): tests = [ (Weekday.SATURDAY, date(2024, 6, 13), date(2024, 7, 6)), (Weekday.SATURDAY, date(2024, 6, 15), date(2024, 7, 6)), (Weekday.SATURDAY, date(2025, 1, 1), date(2025, 2, 1)), - (Weekday.SATURDAY, datetime(2024, 6, 13), datetime(2024, 7, 6)), - (Weekday.SATURDAY, datetime(2024, 6, 15), datetime(2024, 7, 6)), - (Weekday.SATURDAY, datetime(2025, 1, 1), datetime(2025, 2, 1)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), datetime(2024, 7, 6)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 15), datetime(2024, 7, 6)), + (ISOWeekday.SATURDAY, datetime(2025, 1, 1), datetime(2025, 2, 1)), ] for index, test in enumerate(tests): @@ -153,23 +160,23 @@ def test_first_of_next_month_success(self): ): test_input_weekday, test_input_date, test_expected_output = test - self.assertEqual( - TemporalAdjuster.first_of_next_month( - test_input_weekday, test_input_date - ), - test_expected_output, + output = TemporalAdjuster.first_of_next_month( + test_input_weekday, test_input_date ) self.assertEqual( - test_input_weekday.value, test_expected_output.weekday() + output, + test_expected_output, ) + self.assertEqual(output.weekday(), test_expected_output.weekday()) + def test_first_of_last_month_success(self): tests = [ (Weekday.SATURDAY, date(2024, 6, 13), date(2024, 5, 4)), (Weekday.SATURDAY, date(2025, 1, 1), date(2024, 12, 7)), - (Weekday.SATURDAY, datetime(2024, 6, 13), datetime(2024, 5, 4)), - (Weekday.SATURDAY, datetime(2025, 1, 1), datetime(2024, 12, 7)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), datetime(2024, 5, 4)), + (ISOWeekday.SATURDAY, datetime(2025, 1, 1), datetime(2024, 12, 7)), ] for index, test in enumerate(tests): @@ -178,25 +185,25 @@ def test_first_of_last_month_success(self): ): test_input_weekday, test_input_date, test_expected_output = test - self.assertEqual( - TemporalAdjuster.first_of_last_month( - test_input_weekday, test_input_date - ), - test_expected_output, + output = TemporalAdjuster.first_of_last_month( + test_input_weekday, test_input_date ) self.assertEqual( - test_input_weekday.value, test_expected_output.weekday() + output, + test_expected_output, ) + self.assertEqual(output.weekday(), test_expected_output.weekday()) + def test_last_of_month_success(self): tests = [ (Weekday.SATURDAY, date(2024, 6, 13), date(2024, 6, 29)), (Weekday.SATURDAY, date(2024, 6, 15), date(2024, 6, 29)), (Weekday.SATURDAY, date(2025, 1, 1), date(2025, 1, 25)), - (Weekday.SATURDAY, datetime(2024, 6, 13), datetime(2024, 6, 29)), - (Weekday.SATURDAY, datetime(2024, 6, 15), datetime(2024, 6, 29)), - (Weekday.SATURDAY, datetime(2025, 1, 1), datetime(2025, 1, 25)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), datetime(2024, 6, 29)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 15), datetime(2024, 6, 29)), + (ISOWeekday.SATURDAY, datetime(2025, 1, 1), datetime(2025, 1, 25)), ] for index, test in enumerate(tests): @@ -205,23 +212,25 @@ def test_last_of_month_success(self): ): test_input_weekday, test_input_date, test_expected_output = test - self.assertEqual( - TemporalAdjuster.last_of_month(test_input_weekday, test_input_date), - test_expected_output, + output = TemporalAdjuster.last_of_month( + test_input_weekday, test_input_date ) self.assertEqual( - test_input_weekday.value, test_expected_output.weekday() + output, + test_expected_output, ) + self.assertEqual(output.weekday(), test_expected_output.weekday()) + def test_last_of_next_month_success(self): tests = [ (Weekday.SATURDAY, date(2024, 6, 13), date(2024, 7, 27)), (Weekday.SATURDAY, date(2024, 6, 15), date(2024, 7, 27)), (Weekday.SATURDAY, date(2025, 1, 1), date(2025, 2, 22)), - (Weekday.SATURDAY, datetime(2024, 6, 13), datetime(2024, 7, 27)), - (Weekday.SATURDAY, datetime(2024, 6, 15), datetime(2024, 7, 27)), - (Weekday.SATURDAY, datetime(2025, 1, 1), datetime(2025, 2, 22)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), datetime(2024, 7, 27)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 15), datetime(2024, 7, 27)), + (ISOWeekday.SATURDAY, datetime(2025, 1, 1), datetime(2025, 2, 22)), ] for index, test in enumerate(tests): @@ -230,25 +239,25 @@ def test_last_of_next_month_success(self): ): test_input_weekday, test_input_date, test_expected_output = test - self.assertEqual( - TemporalAdjuster.last_of_next_month( - test_input_weekday, test_input_date - ), - test_expected_output, + output = TemporalAdjuster.last_of_next_month( + test_input_weekday, test_input_date ) self.assertEqual( - test_input_weekday.value, test_expected_output.weekday() + output, + test_expected_output, ) + self.assertEqual(output.weekday(), test_expected_output.weekday()) + def test_last_of_last_month_success(self): tests = [ (Weekday.SATURDAY, date(2024, 6, 13), date(2024, 5, 25)), (Weekday.SATURDAY, date(2024, 6, 15), date(2024, 5, 25)), (Weekday.SATURDAY, date(2025, 1, 1), date(2024, 12, 28)), - (Weekday.SATURDAY, datetime(2024, 6, 13), datetime(2024, 5, 25)), - (Weekday.SATURDAY, datetime(2024, 6, 15), datetime(2024, 5, 25)), - (Weekday.SATURDAY, datetime(2025, 1, 1), datetime(2024, 12, 28)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), datetime(2024, 5, 25)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 15), datetime(2024, 5, 25)), + (ISOWeekday.SATURDAY, datetime(2025, 1, 1), datetime(2024, 12, 28)), ] for index, test in enumerate(tests): @@ -257,25 +266,25 @@ def test_last_of_last_month_success(self): ): test_input_weekday, test_input_date, test_expected_output = test - self.assertEqual( - TemporalAdjuster.last_of_last_month( - test_input_weekday, test_input_date - ), - test_expected_output, + output = TemporalAdjuster.last_of_last_month( + test_input_weekday, test_input_date ) self.assertEqual( - test_input_weekday.value, test_expected_output.weekday() + output, + test_expected_output, ) + self.assertEqual(output.weekday(), test_expected_output.weekday()) + def test_first_of_year_success(self): tests = [ (Weekday.SATURDAY, date(2024, 6, 13), date(2024, 1, 6)), (Weekday.SATURDAY, date(2024, 6, 15), date(2024, 1, 6)), (Weekday.SATURDAY, date(2025, 1, 1), date(2025, 1, 4)), - (Weekday.SATURDAY, datetime(2024, 6, 13), datetime(2024, 1, 6)), - (Weekday.SATURDAY, datetime(2024, 6, 15), datetime(2024, 1, 6)), - (Weekday.SATURDAY, datetime(2025, 1, 1), datetime(2025, 1, 4)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), datetime(2024, 1, 6)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 15), datetime(2024, 1, 6)), + (ISOWeekday.SATURDAY, datetime(2025, 1, 1), datetime(2025, 1, 4)), ] for index, test in enumerate(tests): @@ -284,21 +293,23 @@ def test_first_of_year_success(self): ): test_input_weekday, test_input_date, test_expected_output = test - self.assertEqual( - TemporalAdjuster.first_of_year(test_input_weekday, test_input_date), - test_expected_output, + output = TemporalAdjuster.first_of_year( + test_input_weekday, test_input_date ) self.assertEqual( - test_input_weekday.value, test_expected_output.weekday() + output, + test_expected_output, ) + self.assertEqual(output.weekday(), test_expected_output.weekday()) + def test_first_of_last_year_success(self): tests = [ (Weekday.SATURDAY, date(2024, 6, 13), date(2023, 1, 7)), (Weekday.SATURDAY, date(2025, 1, 1), date(2024, 1, 6)), - (Weekday.SATURDAY, datetime(2024, 6, 13), datetime(2023, 1, 7)), - (Weekday.SATURDAY, datetime(2025, 1, 1), datetime(2024, 1, 6)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), datetime(2023, 1, 7)), + (ISOWeekday.SATURDAY, datetime(2025, 1, 1), datetime(2024, 1, 6)), ] for index, test in enumerate(tests): @@ -307,21 +318,21 @@ def test_first_of_last_year_success(self): ): test_input_weekday, test_input_date, test_expected_output = test - self.assertEqual( - TemporalAdjuster.first_of_last_year( - test_input_weekday, test_input_date - ), - test_expected_output, + output = TemporalAdjuster.first_of_last_year( + test_input_weekday, test_input_date ) self.assertEqual( - test_input_weekday.value, test_expected_output.weekday() + output, + test_expected_output, ) + self.assertEqual(output.weekday(), test_expected_output.weekday()) + def test_last_of_year_success(self): tests = [ (Weekday.SATURDAY, date(2024, 6, 13), date(2024, 12, 28)), - (Weekday.SATURDAY, datetime(2024, 6, 13), datetime(2024, 12, 28)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), datetime(2024, 12, 28)), ] for index, test in enumerate(tests): @@ -330,21 +341,23 @@ def test_last_of_year_success(self): ): test_input_weekday, test_input_date, test_expected_output = test - self.assertEqual( - TemporalAdjuster.last_of_year(test_input_weekday, test_input_date), - test_expected_output, + output = TemporalAdjuster.last_of_year( + test_input_weekday, test_input_date ) self.assertEqual( - test_input_weekday.value, test_expected_output.weekday() + output, + test_expected_output, ) + self.assertEqual(output.weekday(), test_expected_output.weekday()) + def test_first_of_next_year_success(self): tests = [ (Weekday.SATURDAY, date(2024, 6, 13), date(2025, 1, 4)), (Weekday.SATURDAY, date(2025, 1, 1), date(2026, 1, 3)), - (Weekday.SATURDAY, datetime(2024, 6, 13), datetime(2025, 1, 4)), - (Weekday.SATURDAY, datetime(2025, 1, 1), datetime(2026, 1, 3)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), datetime(2025, 1, 4)), + (ISOWeekday.SATURDAY, datetime(2025, 1, 1), datetime(2026, 1, 3)), ] for index, test in enumerate(tests): @@ -353,23 +366,23 @@ def test_first_of_next_year_success(self): ): test_input_weekday, test_input_date, test_expected_output = test - self.assertEqual( - TemporalAdjuster.first_of_next_year( - test_input_weekday, test_input_date - ), - test_expected_output, + output = TemporalAdjuster.first_of_next_year( + test_input_weekday, test_input_date ) self.assertEqual( - test_input_weekday.value, test_expected_output.weekday() + output, + test_expected_output, ) + self.assertEqual(output.weekday(), test_expected_output.weekday()) + def test_last_of_next_year_success(self): tests = [ (Weekday.SATURDAY, date(2024, 6, 13), date(2025, 12, 27)), (Weekday.SATURDAY, date(2025, 1, 1), date(2026, 12, 26)), - (Weekday.SATURDAY, datetime(2024, 6, 13), datetime(2025, 12, 27)), - (Weekday.SATURDAY, datetime(2025, 1, 1), datetime(2026, 12, 26)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), datetime(2025, 12, 27)), + (ISOWeekday.SATURDAY, datetime(2025, 1, 1), datetime(2026, 12, 26)), ] for index, test in enumerate(tests): @@ -378,23 +391,23 @@ def test_last_of_next_year_success(self): ): test_input_weekday, test_input_date, test_expected_output = test - self.assertEqual( - TemporalAdjuster.last_of_next_year( - test_input_weekday, test_input_date - ), - test_expected_output, + output = TemporalAdjuster.last_of_next_year( + test_input_weekday, test_input_date ) self.assertEqual( - test_input_weekday.value, test_expected_output.weekday() + output, + test_expected_output, ) + self.assertEqual(output.weekday(), test_expected_output.weekday()) + def test_last_of_last_year_success(self): tests = [ (Weekday.SATURDAY, date(2024, 6, 13), date(2023, 12, 30)), (Weekday.SATURDAY, date(2025, 1, 1), date(2024, 12, 28)), - (Weekday.SATURDAY, datetime(2024, 6, 13), datetime(2023, 12, 30)), - (Weekday.SATURDAY, datetime(2025, 1, 1), datetime(2024, 12, 28)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), datetime(2023, 12, 30)), + (ISOWeekday.SATURDAY, datetime(2025, 1, 1), datetime(2024, 12, 28)), ] for index, test in enumerate(tests): @@ -403,25 +416,25 @@ def test_last_of_last_year_success(self): ): test_input_weekday, test_input_date, test_expected_output = test - self.assertEqual( - TemporalAdjuster.last_of_last_year( - test_input_weekday, test_input_date - ), - test_expected_output, + output = TemporalAdjuster.last_of_last_year( + test_input_weekday, test_input_date ) self.assertEqual( - test_input_weekday.value, test_expected_output.weekday() + output, + test_expected_output, ) + self.assertEqual(output.weekday(), test_expected_output.weekday()) + def test_nth_from_date_success(self): tests = [ (Weekday.SATURDAY, date(2024, 6, 13), 1, date(2024, 6, 15)), (Weekday.SATURDAY, date(2024, 6, 13), 2, date(2024, 6, 22)), (Weekday.SATURDAY, date(2024, 6, 13), 3, date(2024, 6, 29)), - (Weekday.SATURDAY, datetime(2024, 6, 13), 1, datetime(2024, 6, 15)), - (Weekday.SATURDAY, datetime(2024, 6, 13), 2, datetime(2024, 6, 22)), - (Weekday.SATURDAY, datetime(2024, 6, 13), 3, datetime(2024, 6, 29)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), 1, datetime(2024, 6, 15)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), 2, datetime(2024, 6, 22)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), 3, datetime(2024, 6, 29)), ] for index, test in enumerate(tests): @@ -435,17 +448,17 @@ def test_nth_from_date_success(self): test_expected_output, ) = test - self.assertEqual( - TemporalAdjuster.nth_from_date( - test_input_weekday, test_input_date, test_input_n - ), - test_expected_output, + output = TemporalAdjuster.nth_from_date( + test_input_weekday, test_input_date, test_input_n ) self.assertEqual( - test_input_weekday.value, test_expected_output.weekday() + output, + test_expected_output, ) + self.assertEqual(output.weekday(), test_expected_output.weekday()) + def test_nth_of_month_success(self): tests = [ (Weekday.SATURDAY, date(2024, 6, 13), 1, date(2024, 6, 1)), @@ -453,11 +466,11 @@ def test_nth_of_month_success(self): (Weekday.SATURDAY, date(2024, 6, 13), 3, date(2024, 6, 15)), (Weekday.SATURDAY, date(2024, 6, 13), 4, date(2024, 6, 22)), (Weekday.SATURDAY, date(2024, 6, 13), 5, date(2024, 6, 29)), - (Weekday.SATURDAY, datetime(2024, 6, 13), 1, datetime(2024, 6, 1)), - (Weekday.SATURDAY, datetime(2024, 6, 13), 2, datetime(2024, 6, 8)), - (Weekday.SATURDAY, datetime(2024, 6, 13), 3, datetime(2024, 6, 15)), - (Weekday.SATURDAY, datetime(2024, 6, 13), 4, datetime(2024, 6, 22)), - (Weekday.SATURDAY, datetime(2024, 6, 13), 5, datetime(2024, 6, 29)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), 1, datetime(2024, 6, 1)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), 2, datetime(2024, 6, 8)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), 3, datetime(2024, 6, 15)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), 4, datetime(2024, 6, 22)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), 5, datetime(2024, 6, 29)), ] for index, test in enumerate(tests): @@ -471,27 +484,27 @@ def test_nth_of_month_success(self): test_expected_output, ) = test - self.assertEqual( - TemporalAdjuster.nth_of_month( - test_input_weekday, test_input_date, test_input_n - ), - test_expected_output, + output = TemporalAdjuster.nth_of_month( + test_input_weekday, test_input_date, test_input_n ) self.assertEqual( - test_input_weekday.value, test_expected_output.weekday() + output, + test_expected_output, ) + self.assertEqual(output.weekday(), test_expected_output.weekday()) + def test_nth_of_month_exception_invalid_n(self): tests = [ (Weekday.SATURDAY, date(2024, 6, 13), -1), (Weekday.SATURDAY, date(2024, 6, 13), 0), (Weekday.SATURDAY, date(2024, 6, 13), 6), (Weekday.SATURDAY, date(2024, 6, 13), 7), - (Weekday.SATURDAY, datetime(2024, 6, 13), -1), - (Weekday.SATURDAY, datetime(2024, 6, 13), 0), - (Weekday.SATURDAY, datetime(2024, 6, 13), 6), - (Weekday.SATURDAY, datetime(2024, 6, 13), 7), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), -1), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), 0), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), 6), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), 7), ] for index, test in enumerate(tests): @@ -514,8 +527,8 @@ def test_nth_of_month_exception_no_nth_weekday(self): tests = [ (Weekday.SATURDAY, date(2024, 7, 1), 5), (Weekday.SATURDAY, date(1992, 6, 13), 5), - (Weekday.SATURDAY, datetime(2024, 7, 1), 5), - (Weekday.SATURDAY, datetime(1992, 6, 13), 5), + (ISOWeekday.SATURDAY, datetime(2024, 7, 1), 5), + (ISOWeekday.SATURDAY, datetime(1992, 6, 13), 5), ] for index, test in enumerate(tests): @@ -540,8 +553,8 @@ def test_nth_of_year_success(self): tests = [ (Weekday.SATURDAY, date(2024, 6, 13), 1, date(2024, 1, 6)), (Weekday.SATURDAY, date(2024, 6, 13), 10, date(2024, 3, 9)), - (Weekday.SATURDAY, datetime(2024, 6, 13), 1, datetime(2024, 1, 6)), - (Weekday.SATURDAY, datetime(2024, 6, 13), 10, datetime(2024, 3, 9)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), 1, datetime(2024, 1, 6)), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), 10, datetime(2024, 3, 9)), ] for index, test in enumerate(tests): @@ -555,22 +568,25 @@ def test_nth_of_year_success(self): test_expected_output, ) = test - self.assertEqual( - TemporalAdjuster.nth_of_year( - test_input_weekday, test_input_date, test_input_n - ), - test_expected_output, + output = TemporalAdjuster.nth_of_year( + test_input_weekday, test_input_date, test_input_n ) self.assertEqual( - test_input_weekday.value, test_expected_output.weekday() + output, + test_expected_output, ) + self.assertEqual(output.weekday(), test_expected_output.weekday()) + def test_nth_of_year_exception_invalid_n(self): tests = [ (Weekday.SATURDAY, date(2024, 6, 13), -1), (Weekday.SATURDAY, date(2024, 6, 13), 0), (Weekday.SATURDAY, date(2024, 6, 13), 55), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), -1), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), 0), + (ISOWeekday.SATURDAY, datetime(2024, 6, 13), 55), ] for index, test in enumerate(tests): @@ -593,6 +609,8 @@ def test_nth_of_year_exception_no_nth_weekday(self): tests = [ (Weekday.SATURDAY, date(2024, 7, 1), 53), (Weekday.SATURDAY, date(1992, 6, 13), 53), + (ISOWeekday.SATURDAY, datetime(2024, 7, 1), 53), + (ISOWeekday.SATURDAY, datetime(1992, 6, 13), 53), ] for index, test in enumerate(tests):