відняти два рази в пітон


117

У мене є два datetime.timeзначення, exitі enterя хочу зробити що - щось на кшталт:

duration = exit - enter

Однак я отримую цю помилку:

TypeError: непідтримувані типи операндів для -: 'datetime.time' та 'datetime.time

Як це зробити правильно? Одне з можливих рішень - перетворення timeзмінних у datetimeзмінні, а потім підривання, але я впевнений, що ви, хлопці, повинні мати кращий і чистіший спосіб.

Відповіді:


91

Спробуйте це:

from datetime import datetime, date

datetime.combine(date.today(), exit) - datetime.combine(date.today(), enter)

combine будує дату, яку можна відняти.


2
Для точки зору @ IgnacioVazquez-Abrams, можна сказати, datetime(1,1,1,0,0,0)замість цього date.today().
Акавал

25
Не називайте a datetime exit, оскільки exitце вбудована функція.
orokusaki

1
використовуючи python 2.7, у мене немає combineметоду в моєму datetimeмодулі: AttributeError: 'module' object has no attribute 'combine'
mtoloo

6
mtoloo: Є datetimeмодуль, і він має datetimeоб'єкт всередині. Об'єкт всередині має combineметод. Якщо ви просто імпортуєте datetime(так:) import datetime, то, що вам потрібно зробити пізніше, це це datetime.datetime.combine.
gruszczy

1
Є дуже рідкісний випадок, коли ви викликаєте цю функцію в якийсь час, наприклад, 23: 59: 59: 9999. У такому випадку date.today() попередні та date.today()пізніші повернуть інше значення. Краще було б надати значення date.today()змінній.
ramwin

44

Використання:

from datetime import datetime, date

duration = datetime.combine(date.min, end) - datetime.combine(date.min, beginning)

Використання date.minтрохи коротше і працює навіть опівночі.

Це може бути не так, якщо date.today()це може призвести до несподіваних результатів, якщо перший дзвінок відбудеться о 23:59:59, а наступний - о 00:00:00.


1
Згоден з вами.
ramwin

27

замість використання часу спробуйте timedelta:

from datetime import timedelta

t1 = timedelta(hours=7, minutes=36)
t2 = timedelta(hours=11, minutes=32)
t3 = timedelta(hours=13, minutes=7)
t4 = timedelta(hours=21, minutes=0)

arrival = t2 - t1
lunch = (t3 - t2 - timedelta(hours=1))
departure = t4 - t3

print(arrival, lunch, departure)

2
Дякую. Це дуже чистий і краще , ніж всі відповіді тут - stackoverflow.com/questions/3096953 / ...
Pushpak Dagade

7

datetime.timeне підтримує цього, оскільки майже безглуздо віднімати рази таким чином. Використовуйте повнуdatetime.datetime якщо ви хочете це зробити.


53
Якщо ви знаєте зі свого домену, що два datetime.timeоб’єкти aі bє з того самого дня, і це b > a, то операція b - aмає ідеальне значення.
сволог

4
Навіть якщо вони не в той же день, це все одно має сенс. Принаймні стільки ж сенсу arctan(0) = (0, pi, 2pi, ...), але нам просто не байдуже жодне з цих значень після першого. Таким чином, 4:00 - 20:00це 8:00- це також ( 32:00, 56:00, ...), але кого це хвилює?
naught101


7
Крім того, Python навіть не залишається послідовним. Якщо a - b є безглуздим для двох часових об'єктів, то як це, що a> b або a <b поводиться так, як це відбувається? Порівняння передбачається вже в той же день, інакше воно повністю порушене. Оскільки припущення зроблено для порівняння, то цілком припущення робити те саме припущення для різницьких операцій.
Шон

1
Сказати, що це безглуздо, це суб'єктивно, але я бачу, звідки ти родом. Додавання двох разів разом здається мені безглуздим уявленням. Я думаю, що віднімання двох часових значень має повернути тиммедель. Якщо ця тимдельта виявиться негативною, так і нехай буде. Що я хочу знати, це те, чому python не може додавати або віднімати тиммедель з часу, щоб повернути нове значення часу.
aj.toulan

7

У вас є два об'єкти datetime.time, щоб ви просто створили два timedelta, використовуючи datetime.timedetla, а потім субстратуйте, як це робите зараз, використовуючи операнд "-". Далі наведено приклад способу субстракції два рази без використання дати.

enter = datetime.time(hour=1)  # Example enter time
exit = datetime.time(hour=2)  # Example start time
enter_delta = datetime.timedelta(hours=enter.hour, minutes=enter.minute, seconds=enter.second)
exit_delta = datetime.timedelta(hours=exit.hour, minutes=exit.minute, seconds=exit.second)
difference_delta = exit_delta - enter_delta

razlika_delta - це ваша різниця, яку ви можете використовувати з ваших причин.


Можна перетворити об'єкт timedelta назад в дату? Я маю на увазі, що у нас є value_delta .seconds (), чи є можливість повернути об’єкт дати чи часу? Thx
dejdej

Так. datetime.min + delta
sourcedelica

6

Бібліотека python timedelta повинна робити все, що вам потрібно. A timedeltaповертається, коли ви віднімаєте два datetimeекземпляри.

import datetime
dt_started = datetime.datetime.utcnow()

# do some stuff

dt_ended = datetime.datetime.utcnow()
print((dt_ended - dt_started).total_seconds())

4
import datetime

def diff_times_in_seconds(t1, t2):
    # caveat emptor - assumes t1 & t2 are python times, on the same day and t2 is after t1
    h1, m1, s1 = t1.hour, t1.minute, t1.second
    h2, m2, s2 = t2.hour, t2.minute, t2.second
    t1_secs = s1 + 60 * (m1 + 60*h1)
    t2_secs = s2 + 60 * (m2 + 60*h2)
    return( t2_secs - t1_secs)

# using it
diff_times_in_seconds( datetime.datetime.strptime( "13:23:34", '%H:%M:%S').time(),datetime.datetime.strptime( "14:02:39", '%H:%M:%S').time())

3

datetime.time не можеш цього зробити - Але ти міг би скористатися datetime.datetime.now()

start = datetime.datetime.now()
sleep(10)
end = datetime.datetime.now()
duration = end - start

2

У мене була подібна ситуація, як у вас, і я закінчив використання зовнішньої бібліотеки під назвою стрілка .

Ось як це виглядає:

>>> import arrow
>>> enter = arrow.get('12:30:45', 'HH:mm:ss')
>>> exit = arrow.now()
>>> duration = exit - enter
>>> duration
datetime.timedelta(736225, 14377, 757451)

1
Тут ви просто демонструєте віднімання повних об’єктів дати, а не часу, як у
першому
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.