ลบสองครั้งใน python


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 อับราฮัมหนึ่งสามารถใช้พูดแทนdatetime(1,1,1,0,0,0) date.today()
Akavall

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

แทนที่จะใช้เวลาลองใช้เวลา:

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นั้นมีความหมายที่สมบูรณ์แบบ
swalog

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 จะทำงานอย่างไร? การเปรียบเทียบนั้นสมมติขึ้นในวันเดียวกันมิฉะนั้นจะเสียทั้งหมด เนื่องจากสมมติฐานถูกสร้างขึ้นเพื่อการเปรียบเทียบจึงมีความสอดคล้องโดยสิ้นเชิงที่จะสร้างสมมติฐานเดียวกันสำหรับการดำเนินการที่แตกต่างกัน
Sean

1
การบอกว่ามันไม่มีความหมายเป็นเรื่องส่วนตัว แต่ฉันเห็นว่าคุณมาจากไหน การบวกสองครั้งเข้าด้วยกันดูเหมือนจะเป็นการแสดงที่ไม่มีความหมายสำหรับฉัน ฉันคิดว่าการลบค่าเวลาสองค่าควรส่งคืนค่าเวลา หากเวลานั้นเกิดขึ้นเป็นลบก็ไม่ว่ากัน สิ่งที่ฉันอยากรู้คือทำไม python ไม่สามารถเพิ่มหรือลบ timedelta จากเวลาเพื่อส่งคืนค่าเวลาใหม่ได้
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

difference_deltaคือความแตกต่างของคุณซึ่งคุณสามารถใช้เพื่อเหตุผลของคุณ


เป็นไปได้ที่จะแปลงอ็อบเจ็กต์ timedelta กลับเป็น datetime? ฉันหมายความว่าเรามี different_delta .seconds () มีวิธีใดในการเรียกคืนวัตถุวันที่และเวลาหรือไม่ Thx
เดชเดช

ใช่. 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
ที่นี่คุณกำลังสาธิตการลบอ็อบเจ็กต์วันที่และเวลาทั้งหมดไม่ใช่ช่วงเวลาของวันเหมือนในคำถามเดิม
kleptog
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.