From 6b574a9d461bb1dd8ce3cade61f471f96b3dc419 Mon Sep 17 00:00:00 2001 From: leodube-aot <122323255+leodube-aot@users.noreply.github.com> Date: Tue, 9 Jul 2024 11:41:28 -0600 Subject: [PATCH] 21953 Create datetime method to add business days to a date (#2815) --- legal-api/src/legal_api/utils/datetime.py | 16 ++++++++- legal-api/tests/unit/utils/test_datetime.py | 39 ++++++++++++++++++++- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/legal-api/src/legal_api/utils/datetime.py b/legal-api/src/legal_api/utils/datetime.py index 87711ca8eb..8ac66acc53 100644 --- a/legal-api/src/legal_api/utils/datetime.py +++ b/legal-api/src/legal_api/utils/datetime.py @@ -14,7 +14,7 @@ """Date time utilities.""" # from datetime import datetime, timezone import time as _time -from datetime import date, datetime as _datetime, timezone # pylint: disable=unused-import # noqa: F401, I001, I005 +from datetime import date, datetime as _datetime, timedelta, timezone # pylint: disable=unused-import # noqa: E501, F401, I001, I005 # noqa: I003,I005 @@ -31,3 +31,17 @@ def utcnow(cls): def from_date(cls, date_obj): """Get a datetime object from a date object.""" return datetime(date_obj.year, date_obj.month, date_obj.day) + + @classmethod + def add_business_days(cls, from_date: _datetime, num_days: int): + """Add business days to an initial date. Only accounts for weekends, not holidays.""" + current_date = from_date + business_days_to_add = abs(num_days) + inc = 1 if num_days > 0 else -1 + while business_days_to_add > 0: + current_date += timedelta(days=inc) + weekday = current_date.weekday() + if weekday >= 5: # sunday = 6 + continue + business_days_to_add -= 1 + return current_date diff --git a/legal-api/tests/unit/utils/test_datetime.py b/legal-api/tests/unit/utils/test_datetime.py index ccddc7c9c3..616641cb4d 100644 --- a/legal-api/tests/unit/utils/test_datetime.py +++ b/legal-api/tests/unit/utils/test_datetime.py @@ -13,8 +13,9 @@ # limitations under the License. """Tests to ensure the datetime wrappers are working as expected.""" -from datetime import datetime, timezone +from datetime import date, datetime, timezone +import pytest from freezegun import freeze_time @@ -38,3 +39,39 @@ def test_datetime_isoformat(): iso = d.isoformat() tz = iso[iso.find('+'):] assert tz == '+00:00' + + +@pytest.mark.parametrize( + 'test_name, from_date_str, num_days, expected_date_str', [ + ( + 'ADD_WITHIN_WEEKDAYS', + '2024-06-19', + 2, + '2024-06-21' + ), + ( + 'ADD_OVER_WEEKEND', + '2024-06-19', + 5, + '2024-06-26' + ), + ( + 'SUB_WITHIN_WEEKDAYS', + '2024-06-19', + -2, + '2024-06-17' + ), + ( + 'SUB_OVER_WEEKEND', + '2024-06-19', + -5, + '2024-06-12' + ), + ] +) +def test_datetime_add_business_days(test_name, from_date_str, num_days, expected_date_str): + """Assert that business days are added to a date correctly.""" + import legal_api.utils.datetime as _datetime + from_date = date.fromisoformat(from_date_str) + new_date = _datetime.datetime.add_business_days(from_date, num_days) + assert new_date == date.fromisoformat(expected_date_str)