nominaldelta

nominal difference of date/datetime
git clone https://git.ce9e.org/nominaldelta.git

commit
125a4fbda06d0b6f3ca17f5a427cf98af43a9a3c
parent
e002791230c5a023287eb8414bbe54dab84dc889
Author
Tobias Bengfort <tobias.bengfort@posteo.de>
Date
2024-08-31 14:09
add allow_months parameter

Diffstat

M README.md 7 +++----
M nominaldelta.py 16 +++++++++-------
M test.py 16 ++++++++++++++++

3 files changed, 28 insertions, 11 deletions


diff --git a/README.md b/README.md

@@ -77,7 +77,7 @@ that and seconds are added last.
   77    77 
   78    78 When adding to a `date`, seconds are ignored.
   79    79 
   80    -1 ### `NominalDelta.diff(a, b)`
   -1    80 ### `NominalDelta.diff(a, b, allow_months=True)`
   81    81 
   82    82 Calculate the delta between two `date` or `datetime` objects. This will first
   83    83 check how many months can be added without overshooting. Then it will check how
@@ -85,11 +85,10 @@ many days can be added on top of the month. Last, the remaining difference in
   85    85 seconds is calculated. This approach is called "top heavy" because it
   86    86 prioritizes larger units over smaller ones.
   87    87 
   88    -1 If you prefer to get a difference in days or seconds, you can derive them from
   89    -1 the absolute differences:
   -1    88 Set `allow_months=False` if you only want to get days and seconds. If you only
   -1    89 want seconds, use the absolute difference instead:
   90    90 
   91    91 ```python
   92    -1 delta = NominalDelta(days=dt1.toordinal() - dt2.toordinal())
   93    92 delta = NominalDelta(seconds=dt1.timestamp() - dt2.timestamp())
   94    93 ```
   95    94 

diff --git a/nominaldelta.py b/nominaldelta.py

@@ -51,18 +51,20 @@ def binary_search(a, b, delta):
   51    51     return lower * delta
   52    52 
   53    53 
   54    -1 def date_diff(a, b):
   -1    54 def date_diff(a, b, *, allow_months=True):
   55    55     if a > b:
   56    56         return -date_diff(b, a)
   57    -1     delta = binary_search(a, b, NominalDelta(months=1))
   -1    57     delta = NominalDelta()
   -1    58     if allow_months:
   -1    59         delta += binary_search(a, b, NominalDelta(months=1))
   58    60     days = b.toordinal() - (a + delta).toordinal()
   59    61     return delta + NominalDelta(days=days)
   60    62 
   61    63 
   62    -1 def dt_diff(a, b):
   -1    64 def dt_diff(a, b, *, allow_months=True):
   63    65     if a > b:
   64    66         return -dt_diff(b, a)
   65    -1     delta = date_diff(a, b)
   -1    67     delta = date_diff(a, b, allow_months=allow_months)
   66    68     seconds = b.timestamp() - (a + delta).timestamp()
   67    69     if seconds < 0:
   68    70         delta -= NominalDelta(days=1)
@@ -155,9 +157,9 @@ class NominalDelta:
  155   157         return (-self).__radd__(other)
  156   158 
  157   159     @classmethod
  158    -1     def diff(cls: type[Self], a: date, b: date) -> Self:
   -1   160     def diff(cls: type[Self], a: date, b: date, *, allow_months: bool = True) -> Self:
  159   161         if isinstance(a, datetime) and isinstance(b, datetime):
  160    -1             return dt_diff(a, b)
   -1   162             return dt_diff(a, b, allow_months=allow_months)
  161   163         elif isinstance(a, date) and isinstance(b, date):
  162    -1             return date_diff(a, b)
   -1   164             return date_diff(a, b, allow_months=allow_months)
  163   165         raise TypeError('Unsupported types')

diff --git a/test.py b/test.py

@@ -386,3 +386,19 @@ class DiffTests(unittest.TestCase):
  386   386             ),
  387   387             NominalDelta(months=-1, seconds=-1),
  388   388         )
   -1   389 
   -1   390     def test_diff_no_allow_months(self):
   -1   391         self.assertEqual(
   -1   392             NominalDelta.diff(
   -1   393                 date(1970, 1, 15), date(1970, 2, 15), allow_months=False
   -1   394             ),
   -1   395             NominalDelta(days=31),
   -1   396         )
   -1   397         self.assertEqual(
   -1   398             NominalDelta.diff(
   -1   399                 datetime(2001, 1, 1),
   -1   400                 datetime(2003, 9, 17, 20, 54, 47),
   -1   401                 allow_months=False,
   -1   402             ),
   -1   403             NominalDelta(days=989, seconds=75287),
   -1   404         )