Chuyển đổi datetime python thành epoch với strftime


209

Tôi có một thời gian ở UTC mà tôi muốn số giây kể từ kỷ nguyên.

Tôi đang sử dụng strftime để chuyển đổi nó thành số giây. Lấy ngày 1 tháng 4 năm 2012 làm ví dụ.

>>>datetime.datetime(2012,04,01,0,0).strftime('%s')
'1333234800'

Ngày 1 tháng 4 năm 2012 UTC từ epoch là 13.33238400 nhưng ở trên trả về 1333234800, khác nhau 1 giờ.

Vì vậy, có vẻ như các strftime đang tính đến thời gian hệ thống của tôi và áp dụng dịch chuyển múi giờ ở đâu đó. Tôi nghĩ datetime là hoàn toàn ngây thơ?

Làm thế nào tôi có thể nhận được xung quanh đó? Nếu có thể tránh để nhập các thư viện khác trừ khi tiêu chuẩn. (Tôi có mối quan tâm về tính di động).



11
Tôi có phải là người duy nhất lưu ý rằng bạn sử dụng chữ bát phân trong các số không?
Giám sát cá


3
Python mới hơn 3.3+ códatetime.datetime.timestamp(datetime.datetime.utcnow())
MarkHu

Câu trả lời:


389

Nếu bạn muốn chuyển đổi một datetime python thành giây kể từ epoch, bạn có thể làm điều đó một cách rõ ràng:

>>> (datetime.datetime(2012,04,01,0,0) - datetime.datetime(1970,1,1)).total_seconds()
1333238400.0

Trong Python 3.3+, bạn có thể sử dụng timestamp()thay thế:

>>> datetime.datetime(2012,4,1,0,0).timestamp()
1333234800.0

Tại sao bạn không nên sử dụng datetime.strftime('%s')

Python không thực sự hỗ trợ% s làm đối số cho strftime (nếu bạn kiểm tra tại http://docs.python.org/l Library / datetime.html # strftime-and-strptime-behavior thì nó không có trong danh sách), chỉ Lý do nó hoạt động là vì Python truyền thông tin đến các hệ thống của bạn, nơi sử dụng múi giờ địa phương của bạn.

>>> datetime.datetime(2012,04,01,0,0).strftime('%s')
'1333234800'

7
Tôi đã phát điên khi cố gắng tìm ra lý do tại sao tôi thấy strftime ("% s") rất nhiều, nhưng nó không có trong tài liệu. Cảm ơn bạn không có gì này!
Jonathan Vanasco

54
không sử dụng .strftime("%s"): nó không được hỗ trợ, nó không di động, nó có thể âm thầm tạo ra kết quả sai cho một đối tượng datetime nhận biết, nó không thành công nếu đầu vào là trong UTC (như trong câu hỏi) nhưng múi giờ địa phương không phải là UTC
jfs

2
@earthmeLon Dấu ngoặc của bạn là sai. Timedeltas (được thực hiện bằng cách trừ hai datetimes) có Total_seconds, nhưng datetimes thì không.
jleahy

2
Điều này không hiệu quả với tôi:AttributeError: 'datetime.timedelta' object has no attribute 'total_seconds'
Michael

3
@Michael Chức năng đó là mới trong Python 2.7, bạn phải sử dụng phiên bản cũ hơn. Đối với các phiên bản trước 2.7 bạn có thể làm td.seconds + td.days*24*3600. Điều này loại bỏ phần micro giây.
jleahy

100

Tôi đã có vấn đề nghiêm trọng với Timezones và như vậy. Cách Python xử lý tất cả những gì xảy ra khá khó hiểu (với tôi). Mọi thứ dường như hoạt động tốt khi sử dụng mô-đun lịch (xem liên kết 1 , 2 , 34 ).

>>> import datetime
>>> import calendar
>>> aprilFirst=datetime.datetime(2012, 04, 01, 0, 0)
>>> calendar.timegm(aprilFirst.timetuple())
1333238400

7
+1 vì đó là câu trả lời duy nhất hoạt động cho đầu vào trong câu hỏi.
jfs

cái này có cầm tay không?
benjaminz

1
Điều này nên được đánh dấu là câu trả lời đúng, vì điều này trả lời mối quan tâm trong câu hỏi. vnice kudos
Hoàng tử Leo

2
Điều này 'hoạt động', nhưng lưu ý câu hỏi đã nêu: "Tôi có thời gian ở UTC" Phương pháp này sẽ luôn sử dụng múi giờ địa phương của hệ thống. Không có cách nào để xác định múi giờ. Nếu aprilFirsttrong ví dụ này là một ví dụ 'nhận thức' và sử dụng múi giờ khác với múi giờ của hệ thống, kết quả sẽ không chính xác (múi giờ bị mất trong timetuple()cuộc gọi). Để có câu trả lời đúng cho thời gian 'nhận thức', bạn có thể sử dụng awaredt.timestamp()trên Python gần đây 3. Đối với Python 2 thì khó hơn; một cách là sử dụng arrowthư viện arrow.get(awaredt).timestampsẽ làm cho nó đúng
Adam Williamson

1
Điểm hay, @AdamWilliamson, nhưng mã trong ví dụ không phải là địa phương hóa datetimeđối tượng, vì vậy tôi cho rằng "Tôi có một thời gian ở UTC" có nghĩa là OP có một datetimeđối tượng không biết được cho là ở UTC mà anh ta muốn để có được một epoch(nếu datetimetình cờ nhận ra TZ, điều này thực sự có thể thay đổi mọi thứ). Ngoài ra, hãy nhớ rằng câu trả lời này đã gần 8 tuổi và rất nhiều điều đã xảy ra kể từ ( arrowđược phát hành năm 2013 chẳng hạn)
BorrajaX

35
import time
from datetime import datetime
now = datetime.now()

time.mktime(now.timetuple())

1
đó là một cách viết không chính xác time.time()( mktime()có thể thất bại trong quá trình chuyển đổi DST trong khi time.time()tiếp tục hoạt động). Và nó không trả lời câu hỏi trừ khi múi giờ địa phương là UTC (đầu vào trong câu hỏi là bằng UTC). Ngay cả khi đầu vào đại diện cho giờ địa phương thì mktime()cũng có thể thất bại cho các ngày trong quá khứ / tương lai nếu nó không sử dụng cơ sở dữ liệu tz và nếu múi giờ địa phương có thể có các mức chênh lệch utc khác nhau trong các năm, ví dụ: Châu Âu / Moscow trong năm 2010-2015 - - sử dụng thời gian UTC (như trong câu hỏi) hoặc các đối tượng datetime nhận biết múi giờ thay thế.
jfs

đây là nhiều vấn đề hơn với việc chuyển đổi giờ địa phương (chẳng hạn như được trả về .now()) sang dấu thời gian epoch (được trả về mktime()) . Nếu bạn đọc nó; bạn hiểu tại sao đầu vào UTC (được sử dụng trong câu hỏi) lại thích hợp hơn nhiều so với đối tượng datetime ngây thơ đại diện cho giờ địa phương
jfs

14
import time
from datetime import datetime
now = datetime.now()

# same as above except keeps microseconds
time.mktime(now.timetuple()) + now.microsecond * 1e-6

(Xin lỗi, nó sẽ không cho phép tôi nhận xét về câu trả lời hiện có)


Đó là bởi vì time.mktime không tính đến phần micro giây, phải không?
Eduardo

1
Chính xác. Cấu trúc tuple thời gian (dựa trên thanh C) không có khoảng trống cho micro giây, vì vậy chúng ta cần lấy thông tin từ đối tượng datetime và thêm nó vào cuối.
Charles Plager


Trên máy của tôi, điều này hoạt động chính xác mặc dù múi giờ của tôi là ET.
Charles Plager 17/2/2016

1
Điều này sẽ cung cấp cho bạn các dấu thời gian khác nhau trên các hệ thống khác nhau dựa trên thời gian cục bộ của hệ thống.
Yousaf

6

nếu bạn chỉ cần dấu thời gian trong thời gian unix / epoch, thì một dòng này hoạt động:

created_timestamp = int((datetime.datetime.now() - datetime.datetime(1970,1,1)).total_seconds())
>>> created_timestamp
1522942073L

và chỉ phụ thuộc vào datetime các tác phẩm trong python2 và python3


2

Điều này hoạt động trong Python 2 và 3:

>>> import time
>>> import calendar
>>> calendar.timegm(time.gmtime())
1504917998

Chỉ cần làm theo các tài liệu chính thức ... https://docs.python.org/2/l Library / time.html # model-time


1) Điều này giả sử bạn muốn chuyển đổi ngay bây giờ, không phải là một đối tượng datetime ngẫu nhiên. 2) Bạn không cần lịch. time.mktime (RandomDateTime.timetuple ()) + RandomDateTime.microsecond * 1e-6
Charles Plager 7/2/18

@CharlesPlager time.mktime không chính xác; nó diễn giải đối số theo múi giờ địa phương, trong khi OP muốn thời gian diễn giải bằng UTC (như calendar.timegm hiện).
stewbasic

Đây là câu trả lời chính xác nhất cho tôi, nếu bạn đang muốn chuyển đổi thời gian của mình theo GMT và bạn muốn tiếp tục theo cách đó trên chuyển đổi sang dấu thời gian epoch.
Yousaf

Chỉ cần làm theo câu trả lời của bạn, calendar.timegm (datetime.strptime ("2019-05-03T05: 40: 09.770494 + 00: 00" [: 16], '% Y-% m-% dT% H:% M'). timetuple ()) Tôi có dấu thời gian trong utc và bất kể bạn chạy hệ thống nào trên đó đều cho tôi dấu thời gian chính xác, mẹo là sử dụng strptime.timetumple
Yousaf

2

Đối với một giải pháp độc lập múi giờ rõ ràng, sử dụng thư viện pytz.

import datetime
import pytz

pytz.utc.localize(datetime.datetime(2012,4,1,0,0), is_dst=False).timestamp()

Đầu ra (float): 1333238400.0


đã thấy một câu trả lời tương tự tại stackoverflow.com/a/21145908/4355695 , nhưng câu hỏi này dưới dạng một lớp lót rất phù hợp với trường hợp sử dụng của tôi khi dữ liệu đến ở UTC và chỉ .timestamp () đã cho rằng nó ở trong giờ địa phương .
Nikhil VJ

Điều này không làm việc cho những ngày ít hơn 1970. Cảm ơn bạn. Câu trả lời được chấp nhận không hoạt động cho các ngày dưới 1970. (Python 3.7.3 64-bit Anaconda3)
canbax

-1

Trong Python 3.7

Trả về một datetime tương ứng với một date_ chuỗi ở một trong các định dạng được phát ra bởi date.isoformat () và datetime.isoformat (). Cụ thể, chức năng này hỗ trợ các chuỗi ở định dạng YYYY-MM-DD [* HH [: MM [: SS [.fff [fff]]]] [+ HH: MM [: SS [.ffffff]]]]] , trong đó * có thể khớp với bất kỳ ký tự đơn nào.

https://docs.python.org/3/l Library / datat.html.htmldatetime.datetime.fromisoformat


1
Xin lưu ý rằng điều này đã được giới thiệu trong Python 3.7.
keithpjcar 16/2/19
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.