2013-03-16 47 views
16

Vấn đề của tôi: Tôi cần chuyển đổi múi giờ UTC thành dấu thời gian UTC. Nhưng tôi có một số nhầm lẫn.Python: Chuyển đổi thời gian UTC thành dấu thời gian UTC

Lần đầu tiên một thông tin bit:

  • time.mktime(tuple): chức năng này luôn trả về dấu thời gian trong địa phương thời gian.

    Đây là hàm nghịch đảo của giờ địa phương(). Đối số của nó là struct_time hoặc toàn bộ 9-tuple thể hiện thời gian trong giờ địa phương, chứ không phải UTC.

  • calendar.timegm(tuple): đây trả về UTC timestamp từ thời tuple cung cấp

    mất một tuple thời gian như được trả về bởi các gmtime() chức năng trong module thời gian, và trả về tương ứng Giá trị dấu thời gian Unix. Trong thực tế, time.gmtime() và timegm() là của nhau nghịch đảo

Bây giờ chúng ta hãy làm một bài kiểm tra: Tại sao

>>> from datetime import datetime 
>>> import time 
>>> import calendar as cal 

>>> utc_now = datetime.utcnow() 
>>> now = datetime.now() 
>>> utc_now 
datetime.datetime(2013, 3, 16, 9, 17, 22, 489225) 
>>> now 
datetime.datetime(2013, 3, 16, 5, 17, 29, 736903) 

>>> time.mktime(datetime.timetuple(utc_now)), time.mktime(datetime.timetuple(now)) 
(1363439842.0, 1363425449.0) 
>>> cal.timegm(datetime.timetuple(utc_now)), cal.timegm(datetime.timetuple(now)) 
(1363425442, 1363411049) 

có bốn giá trị khác nhau? Và cái nào là đúng khi tôi muốn chuyển đổi một thời gian UTC thành dấu thời gian UTC?

UPDATTE


Tôi nghĩ rằng tôi đã tìm thấy câu trả lời cho những nhầm lẫn của tôi, vì vậy hãy để tôi giải thích.

Đầu tiên, chúng ta cần phải biết điều gì đó quan trọng:

Có hai loại ngày và thời gian đối tượng: “ngây thơ” và “nhận thức”.

Một đối tượng nhận thức có đủ kiến ​​thức về điều chỉnh thời gian chính trị và thuật toán, chẳng hạn như múi giờ và thông tin thời gian tiết kiệm ánh sáng ban ngày, để xác định vị trí của nó so với các đối tượng nhận thức khác. Một đối tượng nhận thức được sử dụng để đại diện cho một thời điểm cụ thể trong thời gian mà không phải là mở để giải thích [1].

Một đối tượng ngây thơ không chứa đủ thông tin để định vị chính xác tương đối so với các đối tượng ngày/giờ khác. Cho dù một đối tượng ngây thơ đại diện phối hợp quốc tế (UTC), theo giờ địa phương, hoặc thời gian ở một số múi giờ khác hoàn toàn là đến chương trình, giống như nó tùy thuộc vào chương trình cho dù một số đặc biệt đại diện cho mét, dặm, hoặc hàng loạt. Các đối tượng Naive dễ hiểu và phù hợp, với chi phí bỏ qua một số khía cạnh của thực tế.

Những gì chúng tôi nhận được từ datetime.utcnow() hoặc datetime.now() là các đối tượng "ngây thơ".Điều này có nghĩa là đối tượng datetime được trả về không, dù sao, nói bất cứ điều gì về thời gian địa phương của bạn hoặc thời gian UTC - nó chỉ đại diện cho "một thời gian". Nó chỉ đóng gói ngày & thông tin thời gian (năm, tháng, ngày, giờ, phút, giây, v.v.). Trách nhiệm của BẠN là liên kết nó với khái niệm địa phương hoặc UTC.

Vì vậy, hãy nhớ rằng một đối tượng datetime ngây thơ chỉ đại diện cho "một thời gian". Hàm datetime.now() trả về một "thời gian" tương đương với thời gian hiện tại của bạn và hàm datetime.utcnow() trả về "một thời gian" là thời gian hiện tại ở Greenwich England (đó là UTC).

"Thời gian" chỉ là giá trị cho ngày & thời gian. Và lưu ý rằng trên các địa điểm khác nhau trên trái đất, "một thời gian" xảy ra vào những thời điểm khác nhau. Ví dụ: nếu giá trị "một thời gian" là ngày 1 tháng 1, 10:30, thì giờ sẽ là thời gian hiện tại ở Greenwich England khoảng 5 giờ TRƯỚC KHI nó trở thành thời gian hiện tại ở New York. Do đó chúng ta có thể thấy rằng có hai điều: một giá trị "một thời gian" chung, và khái niệm rằng "một thời gian" trở thành thời gian hiện tại tại các địa điểm khác nhau tại "thời gian" khác nhau. (không chơi chữ ở đây, đọc tiếp)

Bây giờ, trước hết hãy định nghĩa "epoch" là gì. Chúng ta biết rằng "một thời gian" chỉ là một giá trị chung của thời gian. Sau đó, thời đại là một "thời gian" đã xảy ra ở Anh Greenwich, nơi các giá trị của các tham số là: January 1 1970, 00:00:00.

Dấu thời gian "" là không. số giây đã trôi qua kể từ khi sử thi. Điều này có nghĩa là dấu thời gian là 0 khi thời gian là Jan 1, 1970, 00:00:00 ở Greenwich Anh. Nhưng dấu thời gian là khoảng. (5 * 60 * 60) khi thời gian là Jan 1, 1970, 00:00:00 ở New York.

>>> tt = datetime.timetuple(datetime(1970, 1, 1, 0, 0, 0)) 
>>> cal.timegm(tt) 
0 

Vì vậy, chúng ta có thể thấy cùng một giá trị "một thời gian" của Jan 1, 1970, 00:00:00 có dấu thời gian khác nhau khi chúng tôi thay đổi vị trí. Do đó, khi bạn nói về dấu thời gian, bạn cũng cần phải nói "vị trí nào" là dấu thời gian có liên quan đến, và bao nhiêu về phía đông hoặc phía tây vị trí đó có liên quan đến Greenwich England. Vị trí đó được biểu thị dưới dạng "múi giờ".

Hiện tại, mọi hệ thống (máy tính) đều có múi giờ được định cấu hình và tất cả dấu thời gian có liên quan đến múi giờ đó có hiệu quả trở thành "cục bộ". UTC là tham chiếu toàn cục.

Vì vậy, giả sử bạn có một giá trị X cho "một thời gian" mà chuyển đổi thành:

  • Y timestamp theo giờ địa phương của bạn
  • Z timestamp trong UTC

sau đó phương tiện này rằng Y không. số giây sẽ phải trôi qua trong "một thời gian" để trở thành thời điểm hiện tại ở vị trí của bạn và Z không có giây nào sẽ phải qua để có thời gian hiện tại ở Greenwich nước Anh trở thành "một thời gian".

Bây giờ, cuối cùng, hãy quay lại các chức năng của chúng tôi mktimetimegm. Chúng mất một thời gian-tuple, mà chỉ là một đại diện cho "một thời gian". Hãy nhớ rằng chúng tôi đang cho họ một thời gian ngây thơ mà không có bất kỳ khái niệm nào của địa phương hoặc UTC.

Giả sử X là thời gian đại diện cho một "thời gian" ngây thơ.Sau đó,

  • mktime(X) sẽ trả về giá trị không. số giây sẽ phải trôi qua để thời gian hiện tại tại địa phương của bạn trở thành "một thời gian" và
  • timegm(X) sẽ trả về số giây sẽ phải chi tiêu để làm cho thời gian hiện tại của Greenwich England bằng "thỉnh thoảng".

Trong ví dụ trên, nowutc_now đại diện ngây thơ "một thời gian", và khi chúng ta ăn những "một thời gian" giá trị vào mktimetimegm, họ chỉ đơn giản là trả lại không. của giây mà phải vượt qua cho các vị trí tương ứng (vị trí của bạn và Greenwich Anh) để có thời gian hiện tại của họ là "một thời gian".


Cuối cùng, quay lại vấn đề của mình: Tôi cần phải chuyển đổi múi giờ UTC thành dấu thời gian UTC.

Thứ nhất, không có khái niệm về "thời gian UTC" - nó chỉ là "một thời gian". Nếu tôi cần phải chuyển nó sang UTC, tôi chỉ cần sử dụng timegm:

cal.timegm(datetime.timetuple(utc_now)) 

mà sẽ cung cấp cho tôi những dấu thời gian cho lần UTC hiện tại (ví dụ: hiện tại "một thời gian" ở Greenwich Anh).

+1

rất thông tin. cảm ơn. – smartnut007

+0

Epoch là 'Jan 1, 1970, 00: 00: 00' ** UTC + 0000 **. Đó là 'ngày 31 tháng 12 năm 1969, 19:00:00 EST-0500' ở New York. Epoch là cùng một trường hợp thời gian trên toàn thế giới bất cứ điều gì đồng hồ địa phương cho thấy (đồng hồ địa phương ở New York sẽ hiển thị 7:00 cho epoch POSIX). Dấu thời gian không phụ thuộc vào múi giờ địa phương - nó giống hệt nhau trên toàn thế giới tại bất kỳ thời điểm cụ thể nào. – jfs

+0

liên quan: [Chuyển đổi datetime.date thành UTC timestamp in Python] (http://stackoverflow.com/q/8777753/4279) – jfs

Trả lời

6

Chỉ có hiệu quả ba các giá trị khác nhau. Hai giá trị này:

1363425449.0 (time.mktime(datetime.timetuple(now)) 
1363425442 (cal.timegm(datetime.timetuple(utc_now))) 

chỉ khác nhau bởi 7 giây, đó là những gì bạn ban đầu nhìn thấy khi bạn đổ các biến:

>>> utc_now 
datetime.datetime(2013, 3, 16, 9, 17, 22, 489225) 
>>> now 
datetime.datetime(2013, 3, 16, 5, 17, 29, 736903) 

(Lưu ý 22 vs 29 trong giây một phần của đầu ra.)

Hai giá trị khác đơn giản là sai, vì bạn đang áp dụng sai loại đối số - bạn đang gọi time.mktime với giá trị UTC thay vì giá trị cục bộ và bạn đang gọi cal.timegm với giá trị địa phương thay vì giá trị UTC . Các tài liệu rõ ràng nói những gì mong đợi - vì vậy hãy chắc chắn rằng bạn chỉ sử dụng các giá trị thích hợp. Về cơ bản bạn đang nhìn thấy thời gian bù đắp địa phương của bạn (4 giờ, bởi vẻ ngoài của nó) đang được áp dụng khi nó không nên (theo các hướng khác nhau tùy thuộc vào nơi lỗi).

Khi bạn đang chẩn đoán những thứ như thế này, việc sử dụng epochconverter.com sẽ cung cấp cho bạn dấu thời gian Unix hiện tại, vì vậy bạn có thể so sánh nó với đầu ra của mình.

+0

Tài liệu KHÔNG nói bất cứ điều gì về việc các đối số có nên là cục bộ hay UTC hay không. Và tại sao bạn nói rằng hai giá trị kia không chính xác? – treecoder

+1

@good_computer: Ý của bạn là gì?Các tài liệu * bạn trích dẫn * cho 'mktime' rõ ràng nói rằng nó phải là địa phương, và documentat * bạn trích dẫn * cho' timegm' nói tuple nên là loại trả về từ 'gmtime' (là UTC). Nếu bạn chuyển giá trị UTC khi hàm đang chờ thời gian cục bộ hoặc ngược lại, thì hàm sẽ áp dụng chuyển đổi cục bộ/UTC khi bạn không muốn, hoặc * không * áp dụng nó khi bạn * làm * muốn nó. (Thật đáng tiếc là API không thể tự phát hiện ra điều này, nhưng đó là cuộc sống ... bạn cần cẩn thận) –

+0

@good_computer: Khái niệm "một thời gian" của bạn còn được gọi là "ngày giờ địa phương" trong nhiều khung công tác - chẳng hạn như 'LocalDateTime' trong Thời gian Joda. Đó là ngày/giờ không có múi giờ liên quan. Vì vậy, bạn thực sự vẫn còn có một vấn đề, hoặc là bạn được sắp xếp? –

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