trừ hai lần trong python


117

Tôi có hai datetime.timegiá trị exitentervà tôi muốn làm điều gì đó như:

duration = exit - enter

Tuy nhiên, tôi gặp lỗi này:

TypeError: (các) loại toán hạng không được hỗ trợ cho -: 'datetime.time' và 'datetime.time

Làm cách nào để làm điều này một cách chính xác? Một giải pháp khả thi là chuyển đổi các timebiến thành datetimebiến và sau đó tạo cấu trúc con, nhưng tôi chắc chắn rằng các bạn phải có cách tốt hơn và sạch hơn.

Câu trả lời:


91

Thử cái này:

from datetime import datetime, date

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

combine xây dựng một ngày giờ, có thể được trừ đi.


2
Đối với điểm @ IgnacioVazquez-Abrams, người ta có thể sử dụng, nói datetime(1,1,1,0,0,0)thay vì date.today().
Akavall

25
Đừng đặt tên a datetime exit, vì đây exitlà một hàm tích hợp.
orokusaki

1
sử dụng python 2.7, tôi không có combinephương pháp trong tôi datetimemô-đun: AttributeError: 'module' object has no attribute 'combine'
mtoloo

6
mtoloo: Có datetimemô-đun và nó có một datetimeđối tượng bên trong. Đối tượng bên trong có combinephương thức. Nếu bạn chỉ nhập datetime(như thế này import datetime:), thì những gì bạn cần làm sau đó là điều này datetime.datetime.combine.
gruszczy

1
Có một trường hợp rất hiếm khi bạn gọi hàm này vào một lúc nào đó như 23: 59: 59: 9999. Trong trường hợp đó, giá trị date.today() trước và date.today()sau sẽ trả về một giá trị khác nhau. Sẽ tốt hơn nếu cung cấp giá trị date.today()cho một biến.
ramwin

44

Sử dụng:

from datetime import datetime, date

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

Sử dụng date.minngắn gọn hơn một chút và hoạt động ngay cả lúc nửa đêm.

Điều này có thể không đúng với trường hợp date.today()đó có thể trả về kết quả không mong muốn nếu cuộc gọi đầu tiên xảy ra lúc 23:59:59 và cuộc gọi tiếp theo lúc 00:00:00.


1
Đồng ý với bạn.
ramwin

27

thay vì sử dụng thời gian, hãy thử bấm giờ:

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
Cảm ơn. Điều này rất rõ ràng và tốt hơn tất cả các câu trả lời ở đây - stackoverflow.com/questions/3096953/…
Pushpak Dagade,

7

datetime.timekhông hỗ trợ điều này, bởi vì việc trừ thời gian theo cách này là vô nghĩa. Sử dụng đầy đủ datetime.datetimenếu bạn muốn làm điều này.


53
Nếu bạn biết từ miền của mình rằng hai datetime.timeđối tượng abcó cùng một ngày và đó b > a, thì hoạt động b - acó ý nghĩa hoàn hảo.
swalog

4
Ngay cả khi chúng không giống nhau trong ngày, nó vẫn có ý nghĩa. Ít nhất cũng có ý nghĩa arctan(0) = (0, pi, 2pi, ...), nhưng chúng tôi không quan tâm đến bất kỳ giá trị nào sau giá trị đầu tiên. Vì vậy, 4:00 - 20:008:00- nó cũng ( 32:00, 56:00, ...), nhưng ai quan tâm?
naught101


7
Hơn nữa, Python thậm chí không nhất quán. Nếu a - b là vô nghĩa đối với hai đối tượng thời gian, thì a> b hoặc a <b hoạt động như thế nào? So sánh đã được giả định trong cùng một ngày, nếu không nó hoàn toàn bị phá vỡ. Vì giả định được đưa ra để so sánh nên việc đưa ra giả định tương tự cho các nghiệp vụ chênh lệch là hoàn toàn nhất quán.
Sean

1
Nói nó vô nghĩa là chủ quan, nhưng tôi hiểu bạn đến từ đâu. Thêm hai lần cùng nhau dường như là một đại diện vô nghĩa đối với tôi. Tôi nghĩ rằng trừ đi hai giá trị thời gian sẽ trả về một thời gian. Nếu thời gian đó xảy ra là số âm, hãy cứ như vậy. Điều tôi muốn biết là tại sao python không thể thêm hoặc trừ một thời gian theo thời gian để trả về giá trị thời gian mới.
aj.toulan

7

Bạn có hai đối tượng datetime.time để bạn chỉ cần tạo hai thời gian bằng cách sử dụng datetime.timedetla và sau đó rút ngắn con như hiện tại bằng toán hạng "-". Dưới đây là ví dụ về cách rút ngắn hai lần mà không sử dụng datetime.

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_deltasự khác biệt của bạn mà bạn có thể sử dụng vì lý do của mình.


Có thể chuyển đổi đối tượng hẹn giờ trở lại datetime không? Ý tôi là chúng ta có difference_delta .seconds (), có cách nào để lấy lại đối tượng datetime hoặc time không? Thx
dejdej

Đúng. datetime.min + delta
nguồn gốc từ

6

Thư viện thời gian của python sẽ làm những gì bạn cần. A timedeltađược trả về khi bạn trừ hai datetimetrường hợp.

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 không thể làm điều đó - Nhưng bạn có thể sử dụng datetime.datetime.now()

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

2

Tôi đã gặp trường hợp tương tự như bạn và tôi đã kết thúc với việc sử dụng thư viện bên ngoài có tên là arrow .

Đây là những gì nó trông giống như:

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

1
Ở đây bạn chỉ là chứng minh trừ đối tượng datetime hoàn chỉnh, không gian-of-ngày như trong câu hỏi ban đầu
kleptog
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.