Petr Dvořáček
Petr Dvořáček

Reputation: 153

Datetime wrong deduction

Problem statement

It seems like there is a bug in python datetime module, following code snippet should be self-explanatory:

import datetime 

dep = datetime.datetime(2021, 9, 11, 7, 25)
arr = datetime.datetime(2021, 9, 11, 12, 35)

print(f"expected: -5h10m, real: {dep - arr}")
print(f"expected: 5h10m, real: {arr - dep}")

What I get with python 3.10:

expected: -5h10m, real: -1 day, 18:50:00
expected: 5h10m, real: 5:10:00

Question

Is it a bug or a feature? If it is a bug, what can I do to fix it?

Upvotes: 3

Views: 103

Answers (3)

Chris Doyle
Chris Doyle

Reputation: 11992

you can look at the implementation of subtract in datetime objects but it essentially does the same thing as the code below.

import datetime

dep = datetime.datetime(2021, 9, 11, 7, 25)
arr = datetime.datetime(2021, 9, 11, 12, 35)
dep_days = dep.toordinal()
arr_days = dep.toordinal()
dep_secs = dep.second + dep.minute * 60 + dep.hour * 3600
arr_secs = arr.second + arr.minute * 60 + arr.hour * 3600

day_diff = dep_days - arr_days
sec_diff = dep_secs - arr_secs
micro_diff = dep.microsecond - arr.microsecond

base = datetime.timedelta(day_diff,sec_diff,micro_diff)

print(base)

the timedelta is telling you that you go backwards one day in time then forwards 18 hours and 50 minutes, which really just means going back 24hours + 18 hours 50 = 5 hours 10 minutes

if you are only interested in this from a string presentation point of view you could just wrap this in a simple function that will give you a relative string representation of the time difference

import datetime

def relative_time_str(delta: datetime.timedelta):
    neutral = datetime.timedelta()
    if delta < neutral:
        return f"-{neutral - delta}"
    return f"{delta}"


dep = datetime.datetime(2021, 9, 11, 7, 25)
arr = datetime.datetime(2021, 9, 11, 12, 35)


print(f"expected: -5h10m, real: {relative_time_str(dep - arr)}")
print(f"expected: 5h10m, real: {relative_time_str(arr - dep)}")

OUTPUT

expected: -5h10m, real: -5:10:00
expected: 5h10m, real: 5:10:00

Upvotes: 1

matszwecja
matszwecja

Reputation: 7971

It is a feature - subtraction of datetime from datetime results in a timedelta object, which is normalised so that only negative value can be days. That behaviour is documented, eg. here: https://pl.python.org/docs/lib/datetime-timedelta.html

Upvotes: 3

Daweo
Daweo

Reputation: 36390

I would call this effect

expected: -5h10m, real: -1 day, 18:50:00
expected: 5h10m, real: 5:10:00

glitch, as it is limited solely to look, whilst both deltas hold same amount of seconds and are equal to their opposite, which can be checked as follows

import datetime 
dep = datetime.datetime(2021, 9, 11, 7, 25)
arr = datetime.datetime(2021, 9, 11, 12, 35)
delta1 = dep - arr
delta2 = arr - dep
print(delta1.total_seconds()) # -18600.0
print(delta2.total_seconds()) # 18600.0
print(delta1 == -delta2) # True
print(delta2 == -delta1) # True
print(delta1 + delta2) # 0:00:00

Upvotes: 3

Related Questions