Python學習:datetime模塊

timedelta

一個timedelta實例對象代表了一個時間差,當兩個date對象或者datetime進行減法操作時,將會返回一個timedelta對象,timedelta對象的構造函數爲:

class datetime.timedelta([days[, seconds[, microseconds[, milliseconds[, minutes[, hours[, weeks]]]]]]])

所有的參數都是可選參數,且默認爲0,當傳遞由以上某幾個參數值後,輸出的timedelta對象將通過days、seconds與microseconds三個參數來表示時間差值。

timedelta對象支持數學運算。

>>> t1 = datetime.timedelta(seconds=60)
>>> t2 = datetime.timedelta(seconds=30)
>>> t3 = t1 + t2
>>> t3.seconds
90
>>> t4 = t1 -t2
>>> t4.seconds
30
>>> t5 = t1 * 2
>>> t5
datetime.timedelta(0, 120)
>>> t6 = t1 * 0
>>> t6
datetime.timedelta(0)
>>> t7 = t1 / 3
>>> t7
datetime.timedelta(0, 20)
>>> t7 = t1 / 7
>>> t7
datetime.timedelta(0, 8, 571428)
>>> t7 = t1 // 7
>>> t7
datetime.timedelta(0, 8, 571428)
>>> t1 > t2
True
>>> t1 < t2
False
>>> t1 == t2
False
>>> t1 == 60
False
>>> t1 != 60
True
>>> t1 > 60
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
TypeError: can't compare datetime.timedelta to int

date

一個date對象代表使用年、月、日表示的時間。可以傳入參數年、月、日來構造date對象。當得到date對象後,就可以直接訪問date對象的年、月、日屬性:

>>> today = date.today()
>>> today
datetime.date(2016, 9, 1)
>>> today.year
2016
>>> today.month
9
>>> today.day
1

date對象也支持運算與比較操作:

>>> delta = timedelta(days=7)
>>> future = today + delta
>>> future
datetime.date(2016, 9, 8)
>>> future - delta
datetime.date(2016, 9, 1)
>>> future - today
datetime.timedelta(7)
>>> future > today
True

datetime

datetime從字面意思上看是datetime的結合,而實際上也是包含了這兩個對象的全部信息,我們可以手動構造datetime對象,也可以使用系統提供的靜態方法,當我們手動構造的時候,必須要傳入yearmonthday三個參數,他們的取值範圍與上面講到的date對象一致。

我們在處理時間問題時,始終無法迴避的是時區問題,在python中,使用datetime.tzinfo來表示時區,但這是一個抽象基類,python也並沒幫我們實現任意的時區,因此,我們首先來看下在不涉及時區的時候datetime都有哪些用法,然後我們會創建一個本地時區,也就是東八區,來說明datetime如何與tzinfo結合使用。

datetime對象的創建

我們可以通過指定年月日的形式來手動創建一個datetime實例。

>>> cur = datetime(year=2016, month=9, day=2)
>>> cur
datetime.datetime(2016, 9, 2, 0, 0)

也可以直接通過靜態方法來獲取:

>>> datetime.today()
datetime.datetime(2016, 9, 2, 17, 50, 21, 810692)
>>> datetime.now()
datetime.datetime(2016, 9, 2, 17, 50, 34, 89763)

這兩個方法都會返回一個本地當前時間,也就是上面的兩個寫法是等效的,但是要注意的是,now()方法可以傳入時區信息,我們稍後再一起討論。

除了上面的方法,我們還可以通過時間戳來獲取一個對象。

>>> datetime.fromtimestamp(time.time())
datetime.datetime(2016, 9, 2, 17, 54, 56, 65907)

除了通過時間戳獲取datetime實例外,我們還可以通過一個格式化的時間字符串來獲得實例,這個方法同樣是不帶時區信息的。

>>> datetime.strptime('2016-09-02 18:00:00', '%Y-%m-%d %H:%M:%S')
datetime.datetime(2016, 9, 2, 18, 0)

既然一個datetime對象包含了datetime的所有信息,那麼能不能通過這兩對象來生成一個datetime實例呢,答案是肯定的。

>>> d = date(year=2016, month=9, day=2)
>>> d
datetime.date(2016, 9, 2)
>>> t = time(hour=18, minute=14)
>>> t
datetime.time(18, 14)
>>> datetime.combine(d, t)
datetime.datetime(2016, 9, 2, 18, 14)

常用方法

有了datetime對象之後,我們就可以獲得對應的datetime對象了:

>>> today = datetime.today()
>>> today.date()
datetime.date(2016, 9, 2)
>>> today.time()
datetime.time(18, 30, 10, 304536)

那如果我希望得到下個月的今天,該怎麼做呢?方法有多種,但是最方便的是直接把月份進行加一操作(不考慮跨年和日期超過月份最大值的情況),這個時候replace函數就派上用場:

>>> next_month = today.replace(month=today.month+1)
>>> next_month
datetime.datetime(2016, 10, 2, 18, 30, 10, 304536)

replace()方法允許我們對datetime的任意字段進行替換,並返回一個新的datetime對象,這個新的對象在其他字段上與原有對象保持一致。

除此之外,還有一個比較常用的方法strftime(),通過它可以格式化成我們希望的樣式:

>>> next_month.strftime('%Y-%m-%d %H:%M:%S')
'2016-10-02 18:30:10'

還有一種情況,是我們希望將一個datetime對象轉成時間戳,很遺憾的是python並沒直接提供這個方法,但是提供了一個timetuple()方法,它返回一個time.struct_time對象,通過它我們可以構造出時間戳:

>>> dd = datetime.today()
>>> tt = time.mktime(dd.timetuple())
>>> print int(tt)
1472816083

時區的定義

python中給我們提供了datetime.tzinfo這一抽象的基類,如果我們想使用時區,則必須繼承這個類來實現自己的時區定義。需要我們實現的方法包括:

  1. tzinto.utcoffset(self, dt) 這個方法返回本地時間與UTC時間的時差,我們知道,我們國家使用的是東八區,也就是比世界協調時間(UTC)/格林尼治時間(GMT)快8小時的時區,因此我們可以如下實現這個方法:
def utcoffset(self, dt):
    return timedelta(hours=8)
  1. tzinfo.dst(self, dt) 這個方法主要是考慮到一些採用夏令時的國家,在固定月份來調整時間,而我們國家是沒有采用夏令時,所以直接返回0:
def dst(self, dt):
    return timedelta(0)

而對於採納了夏令時的國家,則需要把夏令時考慮進去:

def dst(self, dt):
    # Code to set dston and dstoff to the time zone's DST
    # transition times based on the input dt.year, and expressed
    # in standard local time.  Then
 
    if dston <= dt.replace(tzinfo=None) < dstoff:
        return timedelta(hours=1)
    else:
        return timedelta(0)

對於這些國家,我還要修改utcoffset函數,將夏令時的偏移量考慮進去:

def utcoffset(self, dt):
    return timedelta(hours=N) + self.dst(dt)
  1. tzinfo.tzname(self, dt) 這個方法用來返回時區的名稱。

一般情況下,我們只要實現上面三個方法就可以了,例如我們可以這樣定義一個UTC時區和我們所在的東八區。

ZERO = timedelta(0)
HOUR = timedelta(hours=1)
 
class UTC(tzinfo):
    """UTC"""
 
    def utcoffset(self, dt):
        return ZERO
 
    def tzname(self, dt):
        return "UTC"
 
    def dst(self, dt):
        return ZERO
 
 
class GMT8(tzinfo):
    """東八區"""
    
    def utcoffset(self, dt):
        return HOUR * 8
    def tzname(self, dt):
        return 'GMT-8'
    def dst(self, dt):
        return ZERO
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章