小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

python 用datetime和pytz來轉(zhuǎn)換時(shí)區(qū)

 java_laq小館 2014-06-26

python 用datetime和pytz來轉(zhuǎn)換時(shí)區(qū)

分類: Python 470人閱讀 評(píng)論(0) 收藏 舉報(bào)

原文:http://www./2010/12/14/%E7%94%A8datetime%E5%92%8Cpytz%E6%9D%A5%E8%BD%AC%E6%8D%A2%E6%97%B6%E5%8C%BA


Python標(biāo)準(zhǔn)庫里提供了time、datetime和calendar這3個(gè)模塊來進(jìn)行時(shí)間和日期的處理,其中應(yīng)用最廣的是datetime,而轉(zhuǎn)換時(shí)區(qū)也是靠它來做的。


時(shí)區(qū)這個(gè)玩意非常抽象,處理它時(shí)經(jīng)常弄得我頭暈,只好記錄下來,免得以后再犯暈。


首先要知道時(shí)區(qū)之間的轉(zhuǎn)換關(guān)系,其實(shí)這很簡(jiǎn)單:把當(dāng)?shù)貢r(shí)間減去當(dāng)?shù)貢r(shí)區(qū),剩下的就是格林威治時(shí)間了。
例如北京時(shí)間的18:00就是18:00+08:00,相減以后就是10:00+00:00,因此就是格林威治時(shí)間的10:00。

而把格林威治時(shí)間加上當(dāng)?shù)貢r(shí)區(qū),就能得到當(dāng)?shù)貢r(shí)間了。
例如格林威治時(shí)間的10:00是10:00+00:00,轉(zhuǎn)換成太平洋標(biāo)準(zhǔn)時(shí)間就是加上-8小時(shí),因此是02:00-08:00。

而太平洋標(biāo)準(zhǔn)時(shí)間轉(zhuǎn)換成北京時(shí)間轉(zhuǎn)換也一樣,時(shí)區(qū)相減即可。
例如太平洋標(biāo)準(zhǔn)時(shí)間的02:00-08:00,與北京時(shí)間相差-16小時(shí),因此結(jié)果是18:00+08:00。


而Python的datetime可以處理2種類型的時(shí)間,分別為offset-naive和offset-aware。前者是指沒有包含時(shí)區(qū)信息的時(shí)間,后者是指包含時(shí)區(qū)信息的時(shí)間,只有同類型的時(shí)間才能進(jìn)行減法運(yùn)算和比較。

不幸的是datetime模塊的函數(shù)在默認(rèn)情況下都只生成offset-naive類型的datetime對(duì)象,例如now()、utcnow()、fromtimestamp()、utcfromtimestamp()和strftime()。
其中now()和fromtimestamp()可以接受一個(gè)tzinfo對(duì)象來生成offset-aware類型的datetime對(duì)象,但是標(biāo)準(zhǔn)庫并不提供任何已實(shí)現(xiàn)的tzinfo類,只能自己動(dòng)手豐衣足食了…

下面就是實(shí)現(xiàn)格林威治時(shí)間和北京時(shí)間的tzinfo類的例子:

  1. ZERO_TIME_DELTA = timedelta(0)  
  2. LOCAL_TIME_DELTA = timedelta(hours=8# 本地時(shí)區(qū)偏差  
  3.   
  4. class UTC(tzinfo):  
  5.     def utcoffset(self, dt):  
  6.         return ZERO_TIME_DELTA  
  7.   
  8.     def dst(self, dt):  
  9.         return ZERO_TIME_DELTA  
  10.   
  11. class LocalTimezone(tzinfo):  
  12.     def utcoffset(self, dt):  
  13.         return LOCAL_TIME_DELTA  
  14.   
  15.     def dst(self, dt):  
  16.         return ZERO_TIME_DELTA  
  17.   
  18.     def tzname(self, dt):  
  19.         return '+08:00'  

一個(gè)tzinfo類需要實(shí)現(xiàn)utcoffset、dst和tzname這3個(gè)方法。其中utcoffset需要返回夏時(shí)令的時(shí)差調(diào)整;tzname需要返回時(shí)區(qū)名,如果你不需要用到的話,也可以不實(shí)現(xiàn)。

一旦生成了一個(gè)offset-aware類型的datetime對(duì)象,我們就能調(diào)用它的astimezone()方法,生成其他時(shí)區(qū)的時(shí)間(會(huì)根據(jù)時(shí)差來計(jì)算)。
而如果拿到的是offset-naive類型的datetime對(duì)象,也是可以調(diào)用它的replace()方法來替換tzinfo的,只不過這種替換不會(huì)根據(jù)時(shí)差來調(diào)整其他時(shí)間屬性。
因此,如果拿到一個(gè)格林威治時(shí)間的offset-naive類型的datetime對(duì)象,直接調(diào)用replace(tzinfo=UTC())即可轉(zhuǎn)換成offset-aware類型,然后再調(diào)用astimezone()生成其他時(shí)區(qū)的datetime對(duì)象。
而如果是+6:00時(shí)區(qū)的offset-naive類型的datetime對(duì)象,則可以創(chuàng)建一個(gè)+6:00時(shí)區(qū)的tzinfo類,然后用上述方式轉(zhuǎn)換。
而反過來要將offset-aware類型轉(zhuǎn)換成offset-naive類型時(shí),為了不至于弄混,建議先用astimezone(UTC())生成格林威治時(shí)間,然后再replace(tzinfo=None)。


看上去一切都很簡(jiǎn)單,但不知道你還是否記得上文所述的夏時(shí)令。
提起夏時(shí)令這個(gè)玩意,真是讓我頭疼,因?yàn)樗鼪]有規(guī)則可循:有的國家實(shí)行夏時(shí)令,有的國家不實(shí)行,有的國家只在部分地區(qū)實(shí)行夏時(shí)令,有的地區(qū)只在某些年實(shí)行 夏時(shí)令,每個(gè)地區(qū)實(shí)行夏時(shí)令的起止時(shí)間都不一定相同,而且有的地方TMD還不是用幾月幾日來指定夏時(shí)令的起止時(shí)間的,而是用某月的第幾個(gè)星期幾這種形 式,。
所以說要寫這樣一個(gè)通用的dst方法估計(jì)能把人氣死,于是我只好找來了pytz這個(gè)第三方庫。(注意不要去sourceforge下載,那個(gè)版本4年沒更新了,有嚴(yán)重bug。)

這個(gè)pytz的文檔初看起來很簡(jiǎn)單,用pytz.country_timezones('國家代碼')可以拿到這個(gè)國家的時(shí)區(qū)名列表,而用pytz.timezone('時(shí)區(qū)名')就能獲取一個(gè)tzinfo對(duì)象。
例如取中國的第一個(gè)時(shí)區(qū)來生成datetime對(duì)象:

  1. >>> from datetime import datetime  
  2. >>> import pytz  
  3. >>> tz = pytz.timezone(pytz.country_timezones('cn')[0])  
  4. >>> tz  
  5. <DstTzInfo 'Asia/Shanghai' LMT+8:06:00 STD>  
  6. >>> datetime.now(tz)  
  7. datetime.datetime(20101214192612656000, tzinfo=<DstTzInfo 'Asia/Shan  
  8. ghai' CST+8:00:00 STD>)  

可是它有個(gè)很奇怪的陷阱,注意看那個(gè)tz,它實(shí)際上是+8:06:00,比北京時(shí)間快了6分鐘。更扯淡的是,中國的時(shí)區(qū)里找不到北京時(shí)間,只能拿上海時(shí)間來湊數(shù)…
平時(shí)使用時(shí)可能沒什么問題,但是構(gòu)造datetime對(duì)象,或調(diào)用replace方法時(shí)就會(huì)莫名其妙地差6分鐘了:

  1. >>> dt = datetime.now(tz)  
  2. >>> dt  
  3. datetime.datetime(20101214193223281000, tzinfo=<DstTzInfo 'Asia/Shan  
  4. ghai' CST+8:00:00 STD>)  
  5. >>> dt2 = datetime(20101214193223281000, tzinfo=tz)  
  6. >>> dt2  
  7. datetime.datetime(20101214193223281000, tzinfo=<DstTzInfo 'Asia/Shan  
  8. ghai' LMT+8:06:00 STD>)  
  9. >>> dt == dt2  
  10. False  
  11. >>> dt - dt2  
  12. datetime.timedelta(0360)  
  13. >>> dt.tzinfo  
  14. <DstTzInfo 'Asia/Shanghai' CST+8:00:00 STD>  
  15. >>> dt2.tzinfo  
  16. <DstTzInfo 'Asia/Shanghai' LMT+8:06:00 STD>  

用同一個(gè)tz生成的datetime對(duì)象,居然會(huì)出現(xiàn)不相等的結(jié)果,而且連它們的tzinfo都不一樣…

要解決這個(gè)問題,最簡(jiǎn)單的方法就是使用臺(tái)北(Asia/Taipei)時(shí)間,它正好是+08:00。不過這樣治標(biāo)不治本,畢竟還有那么多不是整點(diǎn)的時(shí)區(qū),不可能一一去找替代時(shí)區(qū)。
實(shí)際上limodou在《關(guān)于pytz的一些記錄(續(xù))》這篇文章中也提到了這個(gè)問題,他指出只要構(gòu)造時(shí)生成offset-naive類型的datetime對(duì)象,再用tz.localize(dt)就能生成正確的時(shí)間了:

  1. >>> dt3 = datetime(20101214193223281000)  
  2. >>> dt3 = tz.localize(dt3)  
  3. >>> dt3  
  4. datetime.datetime(20101214193223281000, tzinfo=<DstTzInfo 'Asia/Shan  
  5. ghai' CST+8:00:00 STD>)  
  6. >>> dt == dt3  
  7. True  

最后就是關(guān)鍵的處理夏時(shí)令的代碼,需要用到normalize方法:

  1. >>> eastern = pytz.timezone('US/Eastern')  
  2. >>> dt4 = datetime(2002102710)  
  3. >>> dt4 = eastern.localize(dt4)  
  4. >>> print dt4  
  5. 2002-10-27 01:00:00-05:00  
  6. >>> dt5 = dt4 - timedelta(minutes=10)  
  7. >>> print dt5  
  8. 2002-10-27 00:50:00-05:00  
  9. >>> dt6 = eastern.normalize(dt5)  
  10. >>> print dt6  
  11. 2002-10-27 01:50:00-04:00  
  12. >>> dt5.tzinfo  
  13. <DstTzInfo 'US/Eastern' EST-1 day, 19:00:00 STD>  
  14. >>> dt6.tzinfo  
  15. <DstTzInfo 'US/Eastern' EDT-1 day, 20:00:00 DST>  

可以看到,normalize以后,就能正確處理夏時(shí)令的變更了。

來自:http://blog.csdn.net/wujingwen1111/article/details/8551957

    本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
    轉(zhuǎn)藏 分享 獻(xiàn)花(0

    0條評(píng)論

    發(fā)表

    請(qǐng)遵守用戶 評(píng)論公約

    類似文章 更多