2012-03-28 39 views
6

Tôi đang sử dụng datetime.fromtimestamp để chuyển đổi thời gian epoch thành giờ địa phương. Tôi thấy rằng datetime.fromtimestamp có một bước nhảy rời rạc của một giờ tại một thời điểm nhất định và tôi hoàn toàn bối rối về lý do tại sao nó làm điều đó.`fromtimestamp` của Python có một bước nhảy rời rạc

(Tôi cũng đang sử dụng time.mktime để chuyển đổi một đối tượng datetime vào thời gian kỷ nguyên, as suggested by Raymond Hettinger. Tôi không chắc chắn cho dù đây là thông tin liên quan cho câu hỏi này, vì vậy tôi nói điều này chỉ trong trường hợp.)

Python 2.7.1+ (r271:86832, Apr 11 2011, 18:05:24) 
[GCC 4.5.2] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> import time, datetime 
>>> def datetime_to_epoch_time(datetime_): 
...  return time.mktime(datetime_.timetuple()) + datetime_.microsecond/1e6 
... 

Chọn một thời gian kỷ nguyên cụ thể:

>>> x = datetime_to_epoch_time(datetime.datetime(2012, 3, 30, 3, 0)) 

Chuyển đổi nó vào một datetime sử dụng fromtimestamp:

>>> datetime.datetime.fromtimestamp(x) 
datetime.datetime(2012, 3, 30, 3, 0) 

Chúng tôi có thời gian 3 giờ sáng.

Bây giờ chúng ta hãy chuyển đổi thời gian đó là chính xác một giây trước khi nó:

>>> datetime.datetime.fromtimestamp(x-1) 
datetime.datetime(2012, 3, 30, 1, 59, 59) 

Chúng tôi bất ngờ nhận được 01:59!

Điều gì đã xảy ra? Tôi biết rằng những thứ như thế xảy ra xung quanh những ngày nhuận, nhưng kể từ khi nào là ngày 30 tháng 3 một ngày nhuận?

Tôi nên lưu ý rằng tôi đã có điều này xảy ra với tôi chỉ trên Linux chứ không phải trên Windows. Và tôi nghĩ rằng các máy tính Linux khác nhau (trong các múi giờ khác nhau) có thời điểm khác nhau trong đó fromtimestamp thực hiện bước nhảy.

Trả lời

4

Dễ dàng. Ngày 30 tháng 3 có lẽ là một công tắc thời gian tiết kiệm ánh sáng ban ngày trong múi giờ của bạn.

Vì vậy, vào ngày hôm đó, thời gian đã thực sự đi 1:59:59-03:00:00

+0

Tôi hiểu. Vì vậy, 'fromtimestamp' nhận thức được múi giờ tôi sống và biết giờ bỏ qua. Nhưng các đối tượng 'datetime' không nhận thức được bước nhảy này: Nếu tôi trừ đối tượng' datetime' cho 3 giờ sáng từ đối tượng trong 2 giờ sáng, tôi nhận được 'timedelta' trong một giờ, nơi tôi sẽ nhận được 0. –

+0

Làm thế nào, sau đó, tôi làm cho các đối tượng 'datetime' nhận biết múi giờ của tôi và làm cho chúng sử dụng * chính xác * một số múi giờ như' fromtimestamp', vì vậy chúng sẽ được đồng bộ hoàn toàn không? –

+0

@RamRachum Vượt qua cờ 'tzinfo' khi tạo dấu thời gian. thư viện 'pytz' có thể giúp bạn với điều đó. – Amber

7

fromtimestamp sử dụng "môi trường địa phương" của người dùng hiện nay, theo quy định của thư viện POSIX C (xem man (3) tzset, và tài liệu của mô-đun time).

Nếu bạn thực sự muốn nhận được thông báo pytz về thời gian cục bộ của môi trường người dùng hiện tại, gói datetime-tz có chức năng tự động phát hiện nó.

Tuy nhiên, sự khôn ngoan thông thường là làm việc luôn với UTC và tránh tất cả các vấn đề DST (chỉ sử dụng múi giờ địa phương để hiển thị cuối cùng). Sử dụng datetime.fromtimestamp(x, tz=pytz.UTC) hoặc nếu bạn không có pytz:

>>> datetime.datetime.fromtimestamp(x) 
datetime.datetime(2012, 3, 30, 3, 0) 
>>> datetime.datetime.utcfromtimestamp(x) 
datetime.datetime(2012, 3, 30, 0, 0) 
>>> datetime.datetime.utcfromtimestamp(x-1) 
datetime.datetime(2012, 3, 29, 23, 59, 59) 

P.S. Bạn cũng có thể đặt ngôn ngữ của quá trình thành UTC (nhưng điều này có thể không hoạt động trên hệ điều hành không phải POSIX):

>>> import os,time 
>>> os.environ["TZ"] = "UTC" 
>>> time.tzset() 
>>> datetime.datetime.fromtimestamp(x) 
datetime.datetime(2012, 3, 30, 0, 0) 
+0

+1 Lời khuyên tuyệt vời. –

Các vấn đề liên quan