Trong Python, làm thế nào để bạn chuyển đổi một đối tượng `datetime` thành giây?


226

Xin lỗi cho câu hỏi đơn giản ... Tôi mới biết về Python ... Tôi đã tìm kiếm xung quanh và dường như không có gì hoạt động.

Tôi có một loạt các đối tượng datetime và tôi muốn tính số giây kể từ một thời gian cố định trong quá khứ cho mỗi đối tượng (ví dụ từ ngày 1 tháng 1 năm 1970).

import datetime
t = datetime.datetime(2009, 10, 21, 0, 0)

Điều này dường như chỉ khác biệt giữa các ngày có các ngày khác nhau:

t.toordinal()

Bất kỳ sự giúp đỡ nào cũng được đánh giá cao.



2
Tôi có thể chuyển đổi cả hai sang S kể từ epoch và đi từ đó: int(t.timestamp())
nerdwaller

cho hoạt động ngược lại ở đây: convert-giây-từ-epoch-to-a-datetime-object
Trevor Boyd Smith

Câu trả lời:


233

Đối với ngày đặc biệt của ngày 1 tháng 1 năm 1970 có nhiều lựa chọn.

Đối với bất kỳ ngày bắt đầu nào khác, bạn cần nhận được sự khác biệt giữa hai ngày tính bằng giây. Trừ hai ngày sẽ cho một timedeltađối tượng, mà Python 2.7 có một total_seconds()hàm.

>>> (t-datetime.datetime(1970,1,1)).total_seconds()
1256083200.0

Ngày bắt đầu thường được chỉ định trong UTC, vì vậy để có kết quả chính xác, datetimebạn cung cấp công thức này cũng phải bằng UTC. Nếu bạn datetimechưa có trong UTC, bạn sẽ cần chuyển đổi nó trước khi sử dụng hoặc đính kèm một tzinfolớp có phần bù thích hợp.

Như đã lưu ý trong các nhận xét, nếu bạn có tài liệu tzinfođính kèm datetimethì bạn sẽ cần một ngày vào ngày bắt đầu hoặc việc trừ sẽ không thành công; ví dụ ở trên tôi sẽ thêm tzinfo=pytz.utcnếu sử dụng Python 2 hoặc tzinfo=timezone.utcnếu sử dụng Python 3.


1
Bây giờ Python cảnh báo tôi: "TypeError: không thể trừ các datetimes ngây thơ và nhận biết bù đắp" Giải pháp tốt nhất để khắc phục điều đó là gì?
Aaron Ash

2
@Charybdis, thử datetime.datetime(1970,1,1,tzinfo=pytz.utc).
Đánh dấu tiền chuộc

9
Cân nhắc sử dụng: datetime.datetime.utcfromtimestamp(0) Tôi đã sử dụng điều này để có được 'kỷ nguyên' một cách dễ dàng. Lưu ý rằng epoch không phải lúc nào cũng giống nhau trên tất cả các hệ thống.
DA

3
Hãy thật cẩn thận với các múi giờ ở đây. Tôi đang ở UTC + 2, có nghĩa là đầu ra time.time()datetime.now() - datetime(1970, 1, 1)khác nhau 7200 giây. Thay vì sử dụng (t - datetime.datetime.fromtimestamp(0)).total_seconds(). Đừng không sử dụng utcfromtimestamp(0)nếu bạn muốn chuyển đổi một datetime trong múi giờ địa phương của bạn.
Carl

2
@DA: Python không hỗ trợ các kỷ nguyên không POSIX . Tất cả các hệ thống mà công trình python sử dụng cùng một Epoch: 1970/01/01 00:00:00 UTC
JFS

130

Để có được thời gian Unix (giây kể từ ngày 1 tháng 1 năm 1970):

>>> import datetime, time
>>> t = datetime.datetime(2011, 10, 21, 0, 0)
>>> time.mktime(t.timetuple())
1319148000.0

22
hãy cẩn thận khi sử dụng time.mktime vì nó thể hiện theo giờ địa phương và nó phụ thuộc vào nền tảng
Shih-Wen Su

7
Hãy cẩn thận thực sự. Nó cắn tôi vào mông tôi rất nhiều
Arg

nó giả định rằng đó tlà một giờ địa phương. Quá trình bù UTC cho múi giờ địa phương có thể khác trước đây và nếu mktime()(thư viện C) không có quyền truy cập vào dữ liệu múi giờ lịch sử trên nền tảng nhất định thì có thể không thành công ( pytzlà cách di động để truy cập cơ sở dữ liệu tz). Ngoài ra, giờ địa phương có thể không rõ ràng, ví dụ: trong quá trình chuyển đổi DST - bạn cần thêm thông tin để định hướng , ví dụ: nếu bạn biết rằng các giá trị ngày / giờ liên tiếp sẽ tăng trong tệp nhật ký
jfs

1
Hãy cẩn thận khi sử dụng điều này với thời gian có phân số của một giây. time.mktime(datetime.datetime(2019, 8, 3, 4, 5, 6, 912000).timetuple())kết quả là 1564819506.0, âm thầm giảm một phần nghìn giây, nhưng datetime.datetime(2019, 8, 3, 4, 5, 6, 912000).timestamp()(câu trả lời của Andrzej Pronobis) cho kết quả 1564819506.912như mong đợi.
Alex

128

Bắt đầu từ Python 3.3 điều này trở nên siêu dễ dàng với datetime.timestamp()phương thức. Điều này tất nhiên sẽ chỉ hữu ích nếu bạn cần số giây từ 1970-01-01 UTC.

from datetime import datetime
dt = datetime.today()  # Get timezone naive now
seconds = dt.timestamp()

Giá trị trả về sẽ là một số float biểu thị các phân số chẵn của một giây. Nếu datetime là ngây thơ múi giờ (như trong ví dụ ở trên), sẽ giả định rằng đối tượng datetime đại diện cho giờ địa phương, tức là nó sẽ là số giây từ thời điểm hiện tại tại vị trí của bạn đến 1970-01-01 UTC.


3
Bất cứ ai đánh giá thấp điều này, bạn có thể vui lòng giải thích tại sao?
Andrzej Pronobis

5
Tôi giả sử, downvote là do thẻ python-2.7 cho câu hỏi (nó chỉ là một phỏng đoán).
JFS

3
Đây phải là câu trả lời được chấp nhận / câu trả lời được chấp nhận nên được cập nhật tương ứng.
DreamFlasher

11
Thời gian để nâng cấp tôi đoán;)
DreamFlasher

có thể tính khoảng cách này từ ngày bắt đầu khác không? (ý tôi là thay đổi ngày 1970-01-01)
pellerossa pelles

29

Có thể ngoài chủ đề: để lấy thời gian UNIX / POSIX từ datetime và chuyển đổi lại:

>>> import datetime, time
>>> dt = datetime.datetime(2011, 10, 21, 0, 0)
>>> s = time.mktime(dt.timetuple())
>>> s
1319148000.0

# and back
>>> datetime.datetime.fromtimestamp(s)
datetime.datetime(2011, 10, 21, 0, 0)

Lưu ý rằng các múi giờ khác nhau có ảnh hưởng đến kết quả, ví dụ: lợi nhuận TZ / DST hiện tại của tôi:

>>>  time.mktime(datetime.datetime(1970, 1, 1, 0, 0).timetuple())
-3600 # -1h

do đó, người ta nên xem xét bình thường hóa thành UTC bằng cách sử dụng các phiên bản UTC của các chức năng.

Lưu ý rằng kết quả trước đó có thể được sử dụng để tính toán bù UTC của múi giờ hiện tại của bạn. Trong ví dụ này, đây là + 1h, tức là UTC + 0100.

Người giới thiệu:


mktime()có thể thất bại . Nói chung, bạn cần pytzchuyển đổi giờ địa phương sang utc, để có dấu thời gian POSIX.
jfs

calendar.timegm () dường như là phiên bản utc của time.mktime ()
frankster

27

int (t.strftime("%s")) cũng hoạt động


1
Hoạt động với tôi trong Python 2.7, với import datetime; t = datetime.datetime(2011, 10, 21, 0, 0)(như được chỉ định bởi OP). Nhưng thực sự, tôi nghi ngờ% s là định dạng thời gian được thêm gần đây.
dan3

1
@ dan3: sai rồi. %skhông được hỗ trợ (nó có thể hoạt động trên một số nền tảng iff tlà một đối tượng datetime ngây thơ đại diện cho giờ địa phương và nếu thư viện C cục bộ có quyền truy cập vào cơ sở dữ liệu tz nếu không kết quả có thể sai). Đừng sử dụng nó.
jfs

%skhông được ghi nhận ở bất cứ đâu. Tôi gieo nó trong mã thực và đã tự hỏi đây là cái gì và xem trong tài liệu và không có thứ gì như vậy %s. Chỉ có với S lớn chỉ trong vài giây.
VStoykov

13

từ các tài liệu python:

timedelta.total_seconds()

Trả về tổng số giây có trong thời lượng. Tương đương với

(td.microseconds + (td.seconds + td.days * 24 * 3600) * 10**6) / 10**6

tính toán với phân chia thực sự được kích hoạt.

Lưu ý rằng trong khoảng thời gian rất lớn (lớn hơn 270 năm trên hầu hết các nền tảng), phương pháp này sẽ mất độ chính xác đến micro giây.

Chức năng này là mới trong phiên bản 2.7.


1
có một vấn đề nhỏ với phép tính phải là 10 6 thay vì 10 * 6 ... td.microseconds + (td.seconds + td.days * 24 * 3600) * 10 6) / 10 ** 6
sdu

@sdu bắt tuyệt vời - dấu sao đôi nằm trong câu trả lời của tôi nhưng stackoverflow tiêu thụ nó, cố gắng khắc phục chỉ khắc phục văn bản.
Michael

2

Để chuyển đổi một đối tượng datetime biểu thị thời gian trong UTC sang dấu thời gian POSIX :

from datetime import timezone

seconds_since_epoch = utc_time.replace(tzinfo=timezone.utc).timestamp()

Để chuyển đổi một đối tượng datetime biểu thị thời gian trong múi giờ địa phương sang dấu thời gian POSIX:

import tzlocal # $ pip install tzlocal

local_timezone = tzlocal.get_localzone()
seconds_since_epoch = local_timezone.localize(local_time, is_dst=None).timestamp()

Xem Làm cách nào để chuyển đổi giờ địa phương sang UTC bằng Python? Nếu cơ sở dữ liệu tz có sẵn trên một nền tảng nhất định; một giải pháp chỉ stdlib có thể làm việc .

Theo liên kết nếu bạn cần giải pháp cho <3.3các phiên bản Python.


1

Tôi đã thử calendar.timegm của thư viện tiêu chuẩn và nó hoạt động khá tốt:

# convert a datetime to milliseconds since Epoch
def datetime_to_utc_milliseconds(aDateTime):
    return int(calendar.timegm(aDateTime.timetuple())*1000)

Tham chiếu: https://docs.python.org/2/l Library / calWiki.html # calWiki.timegm


nó tước các phân số của một giây. Nó giả định rằng đó aDateTimelà thời gian UTC
jfs
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.