ariebovenberg / whenever

⏰ Sensible and typesafe datetimes for Python
https://whenever.rtfd.io
MIT License
361 stars 7 forks source link

UTCDateTime.__sub__ returns only TimeDelta without Date-Delta #108

Open ArneBachmannDLR opened 2 months ago

ArneBachmannDLR commented 2 months ago

I was expecting it to return a DateTimeDelta, but it is:

    def __sub__(self, other: _AwareDateTime) -> TimeDelta: ...

Hint: I want to compute (dt - UTCDateTime(1970, 1, 1)).days.

Update: this seems to work: (dt._py_dt - datetime.datetime(1970, 1, 1, tzinfo=datetime.UTC)).days

ariebovenberg commented 2 months ago

Hi @ArneBachmannDLR, thanks for posting this issue—this is indeed a part of the API I'd like to see improved myself as well.

Before I go into detail about potential solutions, here are two workarounds, with different semantics:

  1. if you care about calendar days, do your arithmetic on Date objects:

    >>> dt.date() - Date(1970, 1, 1)
    DateDelta(P54Y3M8D)
    # note that this may be different, depending on `dt` UTC offset!
    >>> dt.as_utc().date() - Date(1970, 1, 1)
    DateDelta(P54Y3M9D)
  2. If you care about days as exact 24-hour time units, make this explicit:

    >>> (dt - UTCDateTime(1970, 1, 1)).in_hours() / 24
    19822.5

    the reason there is no in_days() is because days are sometimes more or less than 24 hours long, due to daylight saving time.

A note on your workaround

A long-term solution

The complicating factor here is that if UTCDateTime - x simply returns a DateTimeDelta, that you can't do .in_hours() or similar since calendar units aren't exact.

The solution is perhaps some kind of Difference object which can be interpreted on the calendar, as well as the timeline. I will create an issue about this in the future, and link it here.

ArneBachmannDLR commented 2 months ago

Just noticed that

ariebovenberg commented 2 months ago

Indeed:

edit: mistaken first conclusion