datetime — 基本日期和時間型別

原始碼: Lib/datetime.py


datetime 模組提供了用於操作日期和時間的類。

雖然支援日期和時間算術,但實現重點在於為輸出格式化和操作提供高效的屬性提取。

提示

跳到格式程式碼

另請參閱

模組calendar

通用的日曆相關函式。

模組time

時間訪問和轉換。

模組zoneinfo

表示 IANA 時區資料庫的具體時區。

dateutil

具有擴充套件時區和解析支援的第三方庫。

DateType

引入不同的靜態型別的第三方庫,例如,允許靜態型別檢查器區分簡單型和感知型日期時間。

感知型和簡單型物件

日期和時間物件可以根據是否包含時區資訊分為“感知型”或“簡單型”。

憑藉對適用的演算法和政治時間調整(例如時區和夏令時資訊)的充分了解,一個感知型物件可以相對於其他感知型物件定位自身。一個感知型物件表示一個特定的時間點,不容解釋。[1]

一個簡單型物件不包含足夠的資訊來明確地相對於其他日期/時間物件定位自身。一個簡單型物件表示協調世界時 (UTC)、本地時間還是其他時區的時間,完全取決於程式,就像一個特定的數字表示米、英里還是質量取決於程式一樣。簡單型物件易於理解和使用,但代價是忽略了現實的某些方面。

對於需要感知型物件的應用程式,datetimetime 物件有一個可選的時區資訊屬性 tzinfo,可以將其設定為抽象 tzinfo 類的子類的例項。這些 tzinfo 物件捕獲有關與 UTC 時間的偏移量、時區名稱以及夏令時是否生效的資訊。

datetime 模組只提供一個具體的 tzinfo 類,即 timezone 類。timezone 類可以表示與 UTC 具有固定偏移量的簡單時區,例如 UTC 本身或北美 EST 和 EDT 時區。支援更深層次的詳細時區取決於應用程式。世界各地的時間調整規則更多是政治性的而非理性的,並且經常變化,除了 UTC 之外,沒有適合每個應用程式的標準。

常量

datetime 模組匯出以下常量

datetime.MINYEAR

datedatetime 物件中允許的最小年份數字。MINYEAR 為 1。

datetime.MAXYEAR

datedatetime 物件中允許的最大年份數字。MAXYEAR 為 9999。

datetime.UTC

UTC 時區單例 datetime.timezone.utc 的別名。

在 3.11 版本中新增。

可用型別

class datetime.date

一個理想化的簡單日期,假設當前的公曆始終有效。屬性:yearmonthday

class datetime.time

一個理想化的時間,獨立於任何特定的日期,假設每天正好有 24*60*60 秒。(這裡沒有“閏秒”的概念。)屬性:hour, minute, second, microsecond, 和 tzinfo

class datetime.datetime

日期和時間的組合。 屬性:year, month, day, hour, minute, second, microsecond, 和 tzinfo

class datetime.timedelta

一個表示兩個 datetimedate 例項之間的時間差,精確到微秒的解析度。

class datetime.tzinfo

時間區域資訊物件的抽象基類。 datetimetime 類使用它們來提供時間調整的可定製概念(例如,考慮時區和/或夏令時)。

class datetime.timezone

一個實現了 tzinfo 抽象基類,作為與 UTC 的固定偏移量的類。

在版本 3.2 中新增。

這些型別的物件是不可變的。

子類關係

object
    timedelta
    tzinfo
        timezone
    time
    date
        datetime

常用屬性

date, datetime, time, 和 timezone 型別共享這些共同的特性

  • 這些型別的物件是不可變的。

  • 這些型別的物件是 可雜湊的,這意味著它們可以被用作字典的鍵。

  • 這些型別的物件透過 pickle 模組支援高效的序列化。

確定物件是否為感知型或簡單型

date 型別的物件始終是簡單型的。

型別為 timedatetime 的物件可以是感知型或簡單型的。

如果滿足以下兩個條件,則 datetime 物件 d 是感知型的

  1. d.tzinfo 不是 None

  2. d.tzinfo.utcoffset(d) 不返回 None

否則,d 是簡單型的。

如果滿足以下兩個條件,則 time 物件 t 是感知型的

  1. t.tzinfo 不是 None

  2. t.tzinfo.utcoffset(None) 不返回 None

否則,t 是簡單型的。

感知型和簡單型之間的區別不適用於 timedelta 物件。

timedelta 物件

timedelta 物件表示一個時間段,即兩個 datetimedate 例項之間的差值。

class datetime.timedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)

所有引數都是可選的,預設為 0。引數可以是整數或浮點數,也可以是正數或負數。

內部只儲存天數秒數微秒數。引數會被轉換為這些單位

  • 一毫秒轉換為 1000 微秒。

  • 一分鐘轉換為 60 秒。

  • 一小時轉換為 3600 秒。

  • 一週轉換為 7 天。

然後對天數、秒數和微秒數進行標準化,以使表示是唯一的,其中

  • 0 <= microseconds < 1000000

  • 0 <= seconds < 3600*24 (一天中的秒數)

  • -999999999 <= days <= 999999999

以下示例說明了除天數秒數微秒數之外的任何引數如何“合併”並標準化為這三個結果屬性

>>> from datetime import timedelta
>>> delta = timedelta(
...     days=50,
...     seconds=27,
...     microseconds=10,
...     milliseconds=29000,
...     minutes=5,
...     hours=8,
...     weeks=2
... )
>>> # Only days, seconds, and microseconds remain
>>> delta
datetime.timedelta(days=64, seconds=29156, microseconds=10)

如果任何引數是浮點數並且存在小數微秒,則所有引數中剩餘的小數微秒會合並,並且它們的總和會使用四捨五入到偶數的舍入方式舍入到最接近的微秒。如果沒有引數是浮點數,則轉換和標準化過程是精確的(不會丟失資訊)。

如果天數的標準化值超出指示的範圍,則會引發 OverflowError

請注意,負值的標準化起初可能會令人驚訝。例如

>>> from datetime import timedelta
>>> d = timedelta(microseconds=-1)
>>> (d.days, d.seconds, d.microseconds)
(-1, 86399, 999999)

類屬性

timedelta.min

最負的 timedelta 物件,timedelta(-999999999)

timedelta.max

最正的 timedelta 物件,timedelta(days=999999999, hours=23, minutes=59, seconds=59, microseconds=999999)

timedelta.resolution

非相等的 timedelta 物件之間最小的可能差值,timedelta(microseconds=1)

請注意,由於標準化,timedelta.max 大於 -timedelta.min-timedelta.max 不能表示為 timedelta 物件。

例項屬性(只讀)

timedelta.days

介於 -999,999,999 和 999,999,999 之間(包括這兩個值)。

timedelta.seconds

介於 0 和 86,399 之間,包含邊界值。

注意

程式碼無意中使用此屬性,而實際上是想獲取 total_seconds() 值,這是一個很常見的錯誤。

>>> from datetime import timedelta
>>> duration = timedelta(seconds=11235813)
>>> duration.days, duration.seconds
(130, 3813)
>>> duration.total_seconds()
11235813.0
timedelta.microseconds

介於 0 和 999,999 之間,包含邊界值。

支援的操作

操作

結果

t1 = t2 + t3

t2t3 的和。之後 t1 - t2 == t3t1 - t3 == t2 為真。(1)

t1 = t2 - t3

t2t3 的差。之後 t1 == t2 - t3t2 == t1 + t3 為真。(1)(6)

t1 = t2 * i t1 = i * t2

Delta 乘以一個整數。之後,如果 i != 0,則 t1 // i == t2 為真。

一般來說,t1  * i == t1 * (i-1) + t1 為真。(1)

t1 = t2 * f t1 = f * t2

Delta 乘以一個浮點數。結果使用四捨五入到偶數的規則舍入到 timedelta.resolution 的最接近倍數。

f = t2 / t3

用間隔單元 t3 除以總持續時間 t2 的除法 (3)。返回一個 float 物件。

t1 = t2 / f t1 = t2 / i

Delta 除以一個浮點數或整數。結果使用四捨五入到偶數的規則舍入到 timedelta.resolution 的最接近倍數。

t1 = t2 // it1 = t2 // t3

計算向下取整的值,並丟棄餘數(如果有)。在第二種情況下,返回一個整數。(3)

t1 = t2 % t3

餘數被計算為一個 timedelta 物件。(3)

q, r = divmod(t1, t2)

計算商和餘數:q = t1 // t2 (3) 和 r = t1 % t2q 是一個整數,r 是一個 timedelta 物件。

+t1

返回一個具有相同值的 timedelta 物件。(2)

-t1

等價於 timedelta(-t1.days, -t1.seconds, -t1.microseconds),也等價於 t1 * -1。(1)(4)

abs(t)

t.days >= 0 時,等價於 +t;當 t.days < 0 時,等價於 -t。(2)

str(t)

返回一個格式為 [D day[s], ][H]H:MM:SS[.UUUUUU] 的字串,其中 D 對於負數 t 為負數。(5)

repr(t)

返回 timedelta 物件的字串表示形式,作為帶有規範屬性值的建構函式呼叫。

備註

  1. 這是精確的,但可能會溢位。

  2. 這是精確的,不會溢位。

  3. 除以零會引發 ZeroDivisionError

  4. -timedelta.max 不能表示為 timedelta 物件。

  5. timedelta 物件的字串表示形式與其內部表示形式類似地進行了規範化。這導致了負時間間隔的一些不尋常的結果。例如

    >>> timedelta(hours=-5)
    datetime.timedelta(days=-1, seconds=68400)
    >>> print(_)
    -1 day, 19:00:00
    
  6. 表示式 t2 - t3 將始終等於表示式 t2 + (-t3),除非 t3 等於 timedelta.max;在這種情況下,前者將產生結果,而後者將溢位。

除了上面列出的操作外,timedelta 物件還支援與 datedatetime 物件進行某些加法和減法(見下文)。

在 3.2 版本中更改: 現在支援 timedelta 物件與另一個 timedelta 物件的向下取整除法和真除法,以及餘數運算和 divmod() 函式。 現在支援 timedelta 物件與 float 物件的真除法和乘法。

timedelta 物件支援相等和順序比較。

在布林上下文中,當且僅當 timedelta 物件不等於 timedelta(0) 時,才將其視為 true。

例項方法

timedelta.total_seconds()

返回持續時間包含的總秒數。 等價於 td / timedelta(seconds=1)。 對於秒以外的間隔單位,請直接使用除法形式(例如,td / timedelta(microseconds=1))。

請注意,對於非常大的時間間隔(在大多數平臺上大於 270 年),此方法將失去微秒精度。

在版本 3.2 中新增。

用法示例: timedelta

規範化的其他示例

>>> # Components of another_year add up to exactly 365 days
>>> from datetime import timedelta
>>> year = timedelta(days=365)
>>> another_year = timedelta(weeks=40, days=84, hours=23,
...                          minutes=50, seconds=600)
>>> year == another_year
True
>>> year.total_seconds()
31536000.0

timedelta 算術示例

>>> from datetime import timedelta
>>> year = timedelta(days=365)
>>> ten_years = 10 * year
>>> ten_years
datetime.timedelta(days=3650)
>>> ten_years.days // 365
10
>>> nine_years = ten_years - year
>>> nine_years
datetime.timedelta(days=3285)
>>> three_years = nine_years // 3
>>> three_years, three_years.days // 365
(datetime.timedelta(days=1095), 3)

date 物件

date 物件表示理想日曆中的日期(年、月和日),當前公曆在兩個方向上無限延伸。

1 年 1 月 1 日稱為第 1 天,1 年 1 月 2 日稱為第 2 天,依此類推。 [2]

class datetime.date(year, month, day)

所有引數都是必需的。引數必須是整數,並且在以下範圍內

  • MINYEAR <= year <= MAXYEAR

  • 1 <= month <= 12

  • 1 <= day <= 給定月份和年份的天數

如果給定的引數超出這些範圍,則會引發 ValueError 異常。

其他建構函式,均為類方法

classmethod date.today()

返回當前本地日期。

這等價於 date.fromtimestamp(time.time())

classmethod date.fromtimestamp(timestamp)

返回與 POSIX 時間戳對應的本地日期,例如 time.time() 返回的時間戳。

如果時間戳超出平臺 C localtime() 函式支援的值範圍,則可能引發 OverflowError 異常;在 localtime() 失敗時,會引發 OSError 異常。 這通常限制在 1970 年到 2038 年之間。請注意,在非 POSIX 系統上,如果其時間戳概念包含閏秒,則 fromtimestamp() 會忽略閏秒。

在 3.3 版本中更改: 如果時間戳超出平臺 C localtime() 函式支援的值範圍,則會引發 OverflowError 異常,而不是 ValueError 異常。 在 localtime() 失敗時,會引發 OSError 異常,而不是 ValueError 異常。

classmethod date.fromordinal(ordinal)

返回與前格里高利序數對應的日期,其中 1 年 1 月 1 日的序數為 1。

除非 1 <= ordinal <= date.max.toordinal(),否則會引發 ValueError 異常。 對於任何日期 ddate.fromordinal(d.toordinal()) == d

classmethod date.fromisoformat(date_string)

返回與任何有效的 ISO 8601 格式給定的 date_string 對應的 date,但以下情況例外

  1. 目前不支援降低精度的日期 (YYYY-MM, YYYY)。

  2. 目前不支援擴充套件日期表示形式 (±YYYYYY-MM-DD)。

  3. 目前不支援序數日期 (YYYY-OOO)。

示例

>>> from datetime import date
>>> date.fromisoformat('2019-12-04')
datetime.date(2019, 12, 4)
>>> date.fromisoformat('20191204')
datetime.date(2019, 12, 4)
>>> date.fromisoformat('2021-W01-1')
datetime.date(2021, 1, 4)

3.7 版本中新增。

在 3.11 版本中更改: 以前,此方法僅支援 YYYY-MM-DD 格式。

classmethod date.fromisocalendar(year, week, day)

返回與 year、week 和 day 指定的 ISO 日曆日期對應的 date。 這是函式 date.isocalendar() 的逆函式。

3.8 版本中新增。

類屬性

date.min

最早的可表示日期,date(MINYEAR, 1, 1)

date.max

最晚的可表示日期,date(MAXYEAR, 12, 31)

date.resolution

不相等日期物件之間最小的可能差異,timedelta(days=1)

例項屬性(只讀)

date.year

介於 MINYEARMAXYEAR (含) 之間。

date.month

介於 1 和 12 (含) 之間。

date.day

介於 1 和給定年份的給定月份的天數之間。

支援的操作

操作

結果

date2 = date1 + timedelta

date2 將是 date1 之後 timedelta.days 天的日期。(1)

date2 = date1 - timedelta

計算 date2,使得 date2 + timedelta == date1。(2)

timedelta = date1 - date2

(3)

date1 == date2
date1 != date2

相等性比較。(4)

date1 < date2
date1 > date2
date1 <= date2
date1 >= date2

順序比較。(5)

備註

  1. 如果 timedelta.days > 0,則 date2 在時間上向前移動;如果 timedelta.days < 0,則向後移動。之後,date2 - date1 == timedelta.days。 將忽略 timedelta.secondstimedelta.microseconds。 如果 date2.year 小於 MINYEAR 或大於 MAXYEAR,則會引發 OverflowError 異常。

  2. timedelta.secondstimedelta.microseconds 會被忽略。

  3. 這是精確的,不會溢位。timedelta.secondstimedelta.microseconds 為 0,之後 date2 + timedelta == date1

  4. 如果 date 物件表示同一日期,則它們相等。

    不是 datetime 例項的 date 物件永遠不會與 datetime 物件相等,即使它們表示同一日期。

  5. date1 在時間上早於 date2 時,認為 date1 小於 date2。換句話說,當且僅當 date1.toordinal() < date2.toordinal() 時,date1 < date2

    將不是 datetime 例項的 date 物件與 datetime 物件進行順序比較會引發 TypeError

3.13 版本更改: datetime 物件與不是 datetime 子類的 date 子類的例項之間的比較不再將後者轉換為 date,從而忽略時間部分和時區。可以透過覆蓋子類中的特殊比較方法來更改預設行為。

在布林上下文中,所有 date 物件都被認為是 true。

例項方法

date.replace(year=self.year, month=self.month, day=self.day)

返回一個具有相同值的日期,但透過指定的關鍵字引數賦予新值的引數除外。

示例

>>> from datetime import date
>>> d = date(2002, 12, 31)
>>> d.replace(day=26)
datetime.date(2002, 12, 26)

通用函式 copy.replace() 也支援 date 物件。

date.timetuple()

返回一個 time.struct_time,如 time.localtime() 返回的那樣。

小時、分鐘和秒為 0,DST 標誌為 -1。

d.timetuple() 等價於

time.struct_time((d.year, d.month, d.day, 0, 0, 0, d.weekday(), yday, -1))

其中 yday = d.toordinal() - date(d.year, 1, 1).toordinal() + 1 是當年中的天數,從 1 月 1 日的 1 開始。

date.toordinal()

返回日期的預期格里高利序數,其中第 1 年的 1 月 1 日的序數為 1。對於任何 date 物件 ddate.fromordinal(d.toordinal()) == d

date.weekday()

返回星期幾的整數,其中星期一為 0,星期日為 6。例如,date(2002, 12, 4).weekday() == 2,是星期三。另請參閱 isoweekday()

date.isoweekday()

返回星期幾的整數,其中星期一為 1,星期日為 7。例如,date(2002, 12, 4).isoweekday() == 3,是星期三。另請參閱 weekday(), isocalendar()

date.isocalendar()

返回一個具有三個元件的 命名元組 物件:yearweekweekday

ISO 日曆是格里高利曆的廣泛使用的變體。[3]

ISO 年由 52 或 53 個整週組成,其中一週從星期一開始,到星期日結束。ISO 年的第一週是包含星期四的年份的第一個(格里高利)日曆周。這被稱為第 1 周,該星期四的 ISO 年份與其格里高利年份相同。

例如,2004 年從星期四開始,因此 ISO 2004 年的第一週從 2003 年 12 月 29 日星期一開始,到 2004 年 1 月 4 日星期日結束

>>> from datetime import date
>>> date(2003, 12, 29).isocalendar()
datetime.IsoCalendarDate(year=2004, week=1, weekday=1)
>>> date(2004, 1, 4).isocalendar()
datetime.IsoCalendarDate(year=2004, week=1, weekday=7)

3.9 版本更改: 結果從元組更改為 命名元組

date.isoformat()

返回一個表示 ISO 8601 格式的日期的字串,YYYY-MM-DD

>>> from datetime import date
>>> date(2002, 12, 4).isoformat()
'2002-12-04'
date.__str__()

對於日期 dstr(d) 等價於 d.isoformat()

date.ctime()

返回一個表示日期的字串

>>> from datetime import date
>>> date(2002, 12, 4).ctime()
'Wed Dec  4 00:00:00 2002'

d.ctime() 等價於

time.ctime(time.mktime(d.timetuple()))

在本地 C ctime() 函式(time.ctime() 呼叫它,但 date.ctime() 不呼叫它)符合 C 標準的平臺上。

date.strftime(format)

返回一個由顯式格式字串控制的表示日期的字串。引用小時、分鐘或秒的格式程式碼將看到 0 值。另請參閱 strftime() 和 strptime() 的行為 以及 date.isoformat()

date.__format__(format)

date.strftime() 相同。 這使得在 格式化字串字面值 中以及使用 str.format() 時可以為 date 物件指定格式字串。 另請參閱 strftime() 和 strptime() 的行為date.isoformat()

用法示例:date

計算事件天數的示例

>>> import time
>>> from datetime import date
>>> today = date.today()
>>> today
datetime.date(2007, 12, 5)
>>> today == date.fromtimestamp(time.time())
True
>>> my_birthday = date(today.year, 6, 24)
>>> if my_birthday < today:
...     my_birthday = my_birthday.replace(year=today.year + 1)
...
>>> my_birthday
datetime.date(2008, 6, 24)
>>> time_to_birthday = abs(my_birthday - today)
>>> time_to_birthday.days
202

更多使用 date 的示例

>>> from datetime import date
>>> d = date.fromordinal(730920) # 730920th day after 1. 1. 0001
>>> d
datetime.date(2002, 3, 11)

>>> # Methods related to formatting string output
>>> d.isoformat()
'2002-03-11'
>>> d.strftime("%d/%m/%y")
'11/03/02'
>>> d.strftime("%A %d. %B %Y")
'Monday 11. March 2002'
>>> d.ctime()
'Mon Mar 11 00:00:00 2002'
>>> 'The {1} is {0:%d}, the {2} is {0:%B}.'.format(d, "day", "month")
'The day is 11, the month is March.'

>>> # Methods for to extracting 'components' under different calendars
>>> t = d.timetuple()
>>> for i in t:     
...     print(i)
2002                # year
3                   # month
11                  # day
0
0
0
0                   # weekday (0 = Monday)
70                  # 70th day in the year
-1
>>> ic = d.isocalendar()
>>> for i in ic:    
...     print(i)
2002                # ISO year
11                  # ISO week number
1                   # ISO day number ( 1 = Monday )

>>> # A date object is immutable; all operations produce a new object
>>> d.replace(year=2005)
datetime.date(2005, 3, 11)

datetime 物件

datetime 物件是一個包含來自 date 物件和 time 物件的所有資訊的單一物件。

date 物件一樣,datetime 假設當前公曆在兩個方向上都進行了擴充套件;與 time 物件一樣,datetime 假設每天正好有 3600*24 秒。

建構函式

class datetime.datetime(year, month, day, hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0)

yearmonthday 引數是必需的。tzinfo 可以是 None,也可以是 tzinfo 子類的例項。 其餘引數必須是以下範圍內的整數

  • MINYEAR <= year <= MAXYEAR,

  • 1 <= month <= 12,

  • 1 <= day <= 給定月份和年份的天數,

  • 0 <= hour < 24,

  • 0 <= minute < 60,

  • 0 <= second < 60,

  • 0 <= microsecond < 1000000,

  • fold in [0, 1].

如果給定的引數超出這些範圍,則會引發 ValueError 異常。

在 3.6 版本中更改: 添加了 fold 引數。

其他建構函式,均為類方法

classmethod datetime.today()

返回當前的本地日期和時間,其中 tzinfoNone

等效於

datetime.fromtimestamp(time.time())

另請參閱 now()fromtimestamp()

此方法在功能上等效於 now(),但沒有 tz 引數。

classmethod datetime.now(tz=None)

返回當前的本地日期和時間。

如果可選引數 tzNone 或未指定,則此方法與 today() 類似,但如果可能,它會提供比從 time.time() 時間戳獲得的更高的精度(例如,這在提供 C gettimeofday() 函式的平臺上可能是可能的)。

如果 tz 不為 None,則它必須是 tzinfo 子類的例項,並且當前日期和時間將轉換為 tz 的時區。

此函式優於 today()utcnow()

注意

根據底層時鐘的精度,後續對 datetime.now() 的呼叫可能會返回相同的時刻。

classmethod datetime.utcnow()

返回當前的 UTC 日期和時間,其中 tzinfoNone

這與 now() 類似,但會返回當前的 UTC 日期和時間,作為樸素的 datetime 物件。 透過呼叫 datetime.now(timezone.utc) 可以獲得感知當前 UTC datetime。 另請參閱 now()

警告

由於許多 datetime 方法將樸素的 datetime 物件視為本地時間,因此最好使用感知 datetime 來表示 UTC 中的時間。因此,建立表示當前 UTC 時間的物件的建議方法是呼叫 datetime.now(timezone.utc)

自 3.12 版本起已棄用: 請改用帶 UTCdatetime.now()

classmethod datetime.fromtimestamp(timestamp, tz=None)

返回與 POSIX 時間戳(例如 time.time() 返回的時間戳)對應的本地日期和時間。 如果可選引數 tzNone 或未指定,則時間戳將轉換為平臺的本地日期和時間,並且返回的 datetime 物件是樸素的。

如果 tz 不為 None,則它必須是 tzinfo 子類的例項,並且時間戳將轉換為 tz 的時區。

fromtimestamp() 方法可能會引發 OverflowError 異常,如果時間戳超出了平臺 C localtime()gmtime() 函式支援的值範圍;並且在 localtime()gmtime() 函式呼叫失敗時會引發 OSError 異常。通常,這會被限制在 1970 年到 2038 年之間的年份。請注意,在非 POSIX 系統中,如果時間戳的概念中包含閏秒,則 fromtimestamp() 會忽略閏秒,因此可能存在相差一秒的兩個時間戳產生相同的 datetime 物件的情況。此方法優先於 utcfromtimestamp() 方法。

在 3.3 版本中變更: 如果時間戳超出了平臺 C localtime()gmtime() 函式支援的值範圍,則引發 OverflowError 異常,而不是 ValueError 異常。 在 localtime()gmtime() 函式呼叫失敗時,則引發 OSError 異常,而不是 ValueError 異常。

在 3.6 版本中變更: fromtimestamp() 可能會返回 fold 設定為 1 的例項。

classmethod datetime.utcfromtimestamp(timestamp)

返回與 POSIX 時間戳對應的 UTC datetime 物件,其 tzinfo 屬性為 None。(結果物件是樸素的。)

如果時間戳超出了平臺 C gmtime() 函式支援的值範圍,則此方法可能會引發 OverflowError 異常;並且在 gmtime() 函式呼叫失敗時會引發 OSError 異常。通常,這會被限制在 1970 年到 2038 年之間的年份。

要獲取感知時區的 datetime 物件,請呼叫 fromtimestamp() 方法。

datetime.fromtimestamp(timestamp, timezone.utc)

在符合 POSIX 標準的平臺上,它等效於以下表達式:

datetime(1970, 1, 1, tzinfo=timezone.utc) + timedelta(seconds=timestamp)

但後一種公式始終支援完整的年份範圍:包括 MINYEARMAXYEAR

警告

由於許多 datetime 方法將樸素的 datetime 物件視為本地時間,因此建議使用感知時區的 datetime 物件來表示 UTC 時間。 因此,建立表示 UTC 中特定時間戳的物件的推薦方法是呼叫 datetime.fromtimestamp(timestamp, tz=timezone.utc)

在 3.3 版本中變更: 如果時間戳超出了平臺 C gmtime() 函式支援的值範圍,則引發 OverflowError 異常,而不是 ValueError 異常。 在 gmtime() 函式呼叫失敗時,則引發 OSError 異常,而不是 ValueError 異常。

自 3.12 版本起棄用: 請改用帶有 UTCdatetime.fromtimestamp() 方法。

classmethod datetime.fromordinal(ordinal)

返回與前格里高利序數對應的 datetime 物件,其中 1 年 1 月 1 日的序數為 1。 除非 1 <= ordinal <= datetime.max.toordinal(),否則會引發 ValueError 異常。結果的小時、分鐘、秒和微秒均為 0,並且 tzinfoNone

classmethod datetime.combine(date, time, tzinfo=time.tzinfo)

返回一個新的 datetime 物件,其日期部分等於給定的 date 物件的日期部分,其時間部分等於給定的 time 物件的時間部分。如果提供了 *tzinfo* 引數,則使用其值設定結果的 tzinfo 屬性,否則使用 *time* 引數的 tzinfo 屬性。如果 *date* 引數是一個 datetime 物件,則會忽略其時間部分和 tzinfo 屬性。

對於任何 datetime 物件 dd == datetime.combine(d.date(), d.time(), d.tzinfo)

在 3.6 版本中變更: 添加了 *tzinfo* 引數。

classmethod datetime.fromisoformat(date_string)

返回與任何有效的 ISO 8601 格式的 *date_string* 對應的 datetime 物件,但以下情況除外:

  1. 時區偏移量可能包含小數秒。

  2. T 分隔符可以替換為任何單個 Unicode 字元。

  3. 不支援小數小時和分鐘。

  4. 目前不支援降低精度的日期 (YYYY-MM, YYYY)。

  5. 目前不支援擴充套件日期表示形式 (±YYYYYY-MM-DD)。

  6. 目前不支援序數日期 (YYYY-OOO)。

示例

>>> from datetime import datetime
>>> datetime.fromisoformat('2011-11-04')
datetime.datetime(2011, 11, 4, 0, 0)
>>> datetime.fromisoformat('20111104')
datetime.datetime(2011, 11, 4, 0, 0)
>>> datetime.fromisoformat('2011-11-04T00:05:23')
datetime.datetime(2011, 11, 4, 0, 5, 23)
>>> datetime.fromisoformat('2011-11-04T00:05:23Z')
datetime.datetime(2011, 11, 4, 0, 5, 23, tzinfo=datetime.timezone.utc)
>>> datetime.fromisoformat('20111104T000523')
datetime.datetime(2011, 11, 4, 0, 5, 23)
>>> datetime.fromisoformat('2011-W01-2T00:05:23.283')
datetime.datetime(2011, 1, 4, 0, 5, 23, 283000)
>>> datetime.fromisoformat('2011-11-04 00:05:23.283')
datetime.datetime(2011, 11, 4, 0, 5, 23, 283000)
>>> datetime.fromisoformat('2011-11-04 00:05:23.283+00:00')
datetime.datetime(2011, 11, 4, 0, 5, 23, 283000, tzinfo=datetime.timezone.utc)
>>> datetime.fromisoformat('2011-11-04T00:05:23+04:00')   
datetime.datetime(2011, 11, 4, 0, 5, 23,
    tzinfo=datetime.timezone(datetime.timedelta(seconds=14400)))

3.7 版本中新增。

3.11 版本更改: 之前,此方法僅支援 date.isoformat()datetime.isoformat() 可以發出的格式。

classmethod datetime.fromisocalendar(year, week, day)

返回一個 datetime 物件,該物件對應於由 year、week 和 day 指定的 ISO 日曆日期。datetime 的非日期元件將使用其正常的預設值填充。 這是函式 datetime.isocalendar() 的逆運算。

3.8 版本中新增。

classmethod datetime.strptime(date_string, format)

返回一個 datetime 物件,該物件對應於根據 *format* 解析的 *date_string*。

如果 *format* 不包含微秒或時區資訊,則這等效於

datetime(*(time.strptime(date_string, format)[0:6]))

如果 time.strptime() 無法解析 *date_string* 和 *format*,或者它返回的值不是時間元組,則會引發 ValueError。另請參閱 strftime() 和 strptime() 的行為 以及 datetime.fromisoformat()

3.13 版本更改: 如果 *format* 指定了沒有年份的月份日期,現在會發出 DeprecationWarning。這是為了避免程式碼中尋求僅解析月份和日期時出現四年一次的閏年錯誤,因為格式中缺少年份時使用的預設年份不是閏年。 從 Python 3.15 開始,此類 *format* 值可能會引發錯誤。解決方法是在你的 *format* 中始終包含年份。如果解析沒有年份的 *date_string* 值,請在解析之前顯式新增一個閏年年份

>>> from datetime import datetime
>>> date_string = "02/29"
>>> when = datetime.strptime(f"{date_string};1984", "%m/%d;%Y")  # Avoids leap year bug.
>>> when.strftime("%B %d")  
'February 29'

類屬性

datetime.min

最早的可表示 datetimedatetime(MINYEAR, 1, 1, tzinfo=None)

datetime.max

最晚的可表示 datetimedatetime(MAXYEAR, 12, 31, 23, 59, 59, 999999, tzinfo=None)

datetime.resolution

非相等 datetime 物件之間最小的可能差異,timedelta(microseconds=1)

例項屬性(只讀)

datetime.year

介於 MINYEARMAXYEAR (含) 之間。

datetime.month

介於 1 和 12 (含) 之間。

datetime.day

介於 1 和給定年份的給定月份的天數之間。

datetime.hour

range(24) 中。

datetime.minute

range(60) 中。

datetime.second

range(60) 中。

datetime.microsecond

range(1000000) 中。

datetime.tzinfo

作為 *tzinfo* 引數傳遞給 datetime 建構函式的物件,如果沒有傳遞則為 None

datetime.fold

[0, 1] 中。用於消除重複間隔期間的掛鐘時間的歧義。(當夏令時結束時時鐘回撥或由於政治原因當前區域的 UTC 偏移量減小時,會發生重複間隔。)值 0 和 1 分別表示具有相同掛鐘時間表示的兩個時刻的較早和較晚時刻。

3.6 版本新增。

支援的操作

操作

結果

datetime2 = datetime1 + timedelta

(1)

datetime2 = datetime1 - timedelta

(2)

timedelta = datetime1 - datetime2

(3)

datetime1 == datetime2
datetime1 != datetime2

相等性比較。(4)

datetime1 < datetime2
datetime1 > datetime2
datetime1 <= datetime2
datetime1 >= datetime2

順序比較。(5)

  1. datetime2 是從 datetime1 中移除的 timedelta 持續時間,如果 timedelta.days > 0,則時間向前移動,如果 timedelta.days < 0,則時間向後移動。結果具有與輸入 datetime 相同的 tzinfo 屬性,並且之後 datetime2 - datetime1 == timedelta。如果 datetime2.year 小於 MINYEAR 或大於 MAXYEAR,則會引發 OverflowError。請注意,即使輸入是感知物件,也不會進行時區調整。

  2. 計算 datetime2,使得 datetime2 + timedelta == datetime1。與加法一樣,結果具有與輸入 datetime 相同的 tzinfo 屬性,並且即使輸入是感知的,也不會進行時區調整。

  3. 只有當兩個運算元都是樸素的,或者都是感知的時,才定義從 datetime 中減去 datetime。如果一個是感知的而另一個是樸素的,則會引發 TypeError

    如果兩者都是樸素的,或者兩者都是感知的並且具有相同的 tzinfo 屬性,則會忽略 tzinfo 屬性,結果是一個 timedelta 物件 t,使得 datetime2 + t == datetime1。 在這種情況下,不會進行時區調整。

    如果兩者都是 aware 且具有不同的 tzinfo 屬性,則 a-b 的行為就像 ab 首先被轉換為 naive UTC datetime 一樣。結果是 (a.replace(tzinfo=None) - a.utcoffset()) - (b.replace(tzinfo=None) - b.utcoffset()),但實現永遠不會溢位。

  4. 如果 datetime 物件表示相同的日期和時間(考慮到時區),則它們是相等的。

    Naive 和 aware 的 datetime 物件永遠不相等。

    如果兩個比較物件都是 aware,並且具有相同的 tzinfo 屬性,則會忽略 tzinfofold 屬性,並比較基本 datetime。如果兩個比較物件都是 aware 且具有不同的 tzinfo 屬性,則比較行為就像比較物件首先被轉換為 UTC datetime 一樣,但實現永遠不會溢位。重複間隔中的 datetime 例項永遠不等於其他時區中的 datetime 例項。

  5. datetime1 在時間上早於 datetime2 時(考慮到時區),則認為 datetime1 小於 datetime2

    Naive 和 aware 的 datetime 物件之間的順序比較會引發 TypeError

    如果兩個比較物件都是 aware,並且具有相同的 tzinfo 屬性,則會忽略 tzinfofold 屬性,並比較基本 datetime。如果兩個比較物件都是 aware 且具有不同的 tzinfo 屬性,則比較行為就像比較物件首先被轉換為 UTC datetime 一樣,但實現永遠不會溢位。

在 3.3 版本中更改: aware 和 naive 的 datetime 例項之間的相等性比較不會引發 TypeError

3.13 版本更改: datetime 物件與不是 datetime 子類的 date 子類的例項之間的比較不再將後者轉換為 date,從而忽略時間部分和時區。可以透過覆蓋子類中的特殊比較方法來更改預設行為。

例項方法

datetime.date()

返回具有相同年、月和日的 date 物件。

datetime.time()

返回具有相同的小時、分鐘、秒、微秒和 fold 的 time 物件。tzinfoNone。另請參閱方法 timetz()

在 3.6 版本中更改: fold 值被複制到返回的 time 物件中。

datetime.timetz()

返回具有相同的小時、分鐘、秒、微秒、fold 和 tzinfo 屬性的 time 物件。另請參閱方法 time()

在 3.6 版本中更改: fold 值被複制到返回的 time 物件中。

datetime.replace(year=self.year, month=self.month, day=self.day, hour=self.hour, minute=self.minute, second=self.second, microsecond=self.microsecond, tzinfo=self.tzinfo, *, fold=0)

返回具有相同屬性的 datetime,但透過指定的任何關鍵字引數賦予新值的屬性除外。請注意,可以指定 tzinfo=None 以從 aware datetime 建立 naive datetime,而無需轉換日期和時間資料。

datetime 物件也受通用函式 copy.replace() 支援。

在 3.6 版本中更改: 添加了 fold 引數。

datetime.astimezone(tz=None)

返回一個新的 datetime 物件,其具有新的 tzinfo 屬性 tz,並調整日期和時間資料,以使結果與 self 具有相同的 UTC 時間,但採用 tz 的本地時間。

如果提供,則 tz 必須是 tzinfo 子類的例項,並且其 utcoffset()dst() 方法不能返回 None。如果 self 是 naive 的,則假定它表示系統時區的時間。

如果在沒有引數(或使用 tz=None)的情況下呼叫,則假定系統本地時區為目標時區。轉換後的 datetime 例項的 .tzinfo 屬性將設定為 timezone 的例項,其區域名稱和偏移量從作業系統獲取。

如果 self.tzinfotz,則 self.astimezone(tz) 等於 self:不執行日期或時間資料的調整。否則,結果是時區 tz 中的本地時間,表示與 self 相同的 UTC 時間:在 astz = dt.astimezone(tz) 之後,astz - astz.utcoffset() 將具有與 dt - dt.utcoffset() 相同的日期和時間資料。

如果只想將 timezone 物件 tz 附加到 datetime dt,而無需調整日期和時間資料,請使用 dt.replace(tzinfo=tz)。如果只想從 aware datetime dt 中刪除 timezone 物件,而無需轉換日期和時間資料,請使用 dt.replace(tzinfo=None)

請注意,預設的 tzinfo.fromutc() 方法可以在 tzinfo 子類中被重寫,以影響 astimezone() 返回的結果。忽略錯誤情況,astimezone() 的行為類似於:

def astimezone(self, tz):
    if self.tzinfo is tz:
        return self
    # Convert self to UTC, and attach the new timezone object.
    utc = (self - self.utcoffset()).replace(tzinfo=tz)
    # Convert from UTC to tz's local time.
    return tz.fromutc(utc)

在 3.3 版本中變更:tz 現在可以省略。

在 3.6 版本中變更:現在可以在假定代表系統本地時間的樸素例項上呼叫 astimezone() 方法。

datetime.utcoffset()

如果 tzinfoNone,則返回 None,否則返回 self.tzinfo.utcoffset(self),如果後者沒有返回 None 或一個幅度小於一天的 timedelta 物件,則引發異常。

在 3.7 版本中變更:UTC 偏移量不再限制為整數分鐘。

datetime.dst()

如果 tzinfoNone,則返回 None,否則返回 self.tzinfo.dst(self),如果後者沒有返回 None 或一個幅度小於一天的 timedelta 物件,則引發異常。

在 3.7 版本中變更:DST 偏移量不再限制為整數分鐘。

datetime.tzname()

如果 tzinfoNone,則返回 None,否則返回 self.tzinfo.tzname(self),如果後者沒有返回 None 或一個字串物件,則引發異常。

datetime.timetuple()

返回一個 time.struct_time,如 time.localtime() 返回的那樣。

d.timetuple() 等價於

time.struct_time((d.year, d.month, d.day,
                  d.hour, d.minute, d.second,
                  d.weekday(), yday, dst))

其中 yday = d.toordinal() - date(d.year, 1, 1).toordinal() + 1 是當前年份中的日期編號,從 1 月 1 日的 1 開始。tm_isdst 結果的標誌根據 dst() 方法設定:tzinfoNonedst() 返回 Nonetm_isdst 設定為 -1;否則如果 dst() 返回非零值,則 tm_isdst 設定為 1;否則 tm_isdst 設定為 0。

datetime.utctimetuple()

如果 datetime 例項 d 是樸素的,則這與 d.timetuple() 相同,只是 tm_isdst 強制設定為 0,而不管 d.dst() 返回什麼。DST 永遠不會對 UTC 時間生效。

如果 d 是感知的,則 d 透過減去 d.utcoffset() 來標準化為 UTC 時間,並返回標準化時間的 time.struct_timetm_isdst 強制設定為 0。請注意,如果 d.yearMINYEARMAXYEAR 且 UTC 調整溢位年份邊界,則可能會引發 OverflowError

警告

由於許多 datetime 方法將樸素的 datetime 物件視為本地時間,因此最好使用感知的日期時間來表示 UTC 時間;因此,使用 datetime.utctimetuple() 可能會給出誤導性的結果。如果您有一個表示 UTC 的樸素 datetime,請使用 datetime.replace(tzinfo=timezone.utc) 使其感知,此時您可以使用 datetime.timetuple()

datetime.toordinal()

返回日期的普羅勒普提格里高利序號。與 self.date().toordinal() 相同。

datetime.timestamp()

返回與 datetime 例項對應的 POSIX 時間戳。返回值是一個 float,類似於 time.time() 返回的值。

假定樸素的 datetime 例項代表本地時間,並且此方法依賴於平臺 C mktime() 函式來執行轉換。由於 datetime 支援比許多平臺上的 mktime() 更廣泛的值範圍,因此對於過去或將來很遠的時間,此方法可能會引發 OverflowErrorOSError

對於感知的 datetime 例項,返回值計算為

(dt - datetime(1970, 1, 1, tzinfo=timezone.utc)).total_seconds()

在 3.3 版本中新增。

在 3.6 版本中變更:timestamp() 方法使用 fold 屬性來消除重複間隔期間的時間歧義。

注意

沒有直接從表示 UTC 時間的樸素 datetime 例項獲取 POSIX 時間戳的方法。如果您的應用程式使用此約定並且您的系統時區未設定為 UTC,則可以透過提供 tzinfo=timezone.utc 來獲取 POSIX 時間戳

timestamp = dt.replace(tzinfo=timezone.utc).timestamp()

或透過直接計算時間戳

timestamp = (dt - datetime(1970, 1, 1)) / timedelta(seconds=1)
datetime.weekday()

將星期幾作為整數返回,其中星期一為 0,星期日為 6。與 self.date().weekday() 相同。另請參見 isoweekday()

datetime.isoweekday()

將星期幾作為整數返回,其中星期一為 1,星期日為 7。與 self.date().isoweekday() 相同。另請參見 weekday()isocalendar()

datetime.isocalendar()

返回一個包含三個元件的命名元組year, weekweekday。與 self.date().isocalendar() 相同。

datetime.isoformat(sep='T', timespec='auto')

返回一個以 ISO 8601 格式表示日期和時間的字串

如果 utcoffset() 不返回 None,則會附加一個字串,給出 UTC 偏移量

  • YYYY-MM-DDTHH:MM:SS.ffffff+HH:MM[:SS[.ffffff]], 如果 microsecond 不為 0

  • YYYY-MM-DDTHH:MM:SS+HH:MM[:SS[.ffffff]], 如果 microsecond 為 0

示例

>>> from datetime import datetime, timezone
>>> datetime(2019, 5, 18, 15, 17, 8, 132263).isoformat()
'2019-05-18T15:17:08.132263'
>>> datetime(2019, 5, 18, 15, 17, tzinfo=timezone.utc).isoformat()
'2019-05-18T15:17:00+00:00'

可選引數 sep (預設值 'T') 是一個單字元分隔符,放置在結果的日期和時間部分之間。例如

>>> from datetime import tzinfo, timedelta, datetime
>>> class TZ(tzinfo):
...     """A time zone with an arbitrary, constant -06:39 offset."""
...     def utcoffset(self, dt):
...         return timedelta(hours=-6, minutes=-39)
...
>>> datetime(2002, 12, 25, tzinfo=TZ()).isoformat(' ')
'2002-12-25 00:00:00-06:39'
>>> datetime(2009, 11, 27, microsecond=100, tzinfo=TZ()).isoformat()
'2009-11-27T00:00:00.000100-06:39'

可選引數 timespec 指定要包含的時間的附加組成部分的數量(預設為 'auto')。它可以是以下之一

  • 'auto':如果 microsecond 為 0,則與 'seconds' 相同,否則與 'microseconds' 相同。

  • 'hours': 在兩位數的 HH 格式中包含 hour

  • 'minutes': 以 HH:MM 格式包含 hourminute

  • 'seconds': 以 HH:MM:SS 格式包含 hourminutesecond

  • 'milliseconds': 包括完整時間,但將小數秒部分截斷為毫秒。 HH:MM:SS.sss 格式。

  • 'microseconds': 以 HH:MM:SS.ffffff 格式包括完整時間。

注意

排除的時間組成部分被截斷,而不是四捨五入。

如果 timespec 引數無效,則會引發 ValueError

>>> from datetime import datetime
>>> datetime.now().isoformat(timespec='minutes')   
'2002-12-25T00:00'
>>> dt = datetime(2015, 1, 1, 12, 30, 59, 0)
>>> dt.isoformat(timespec='microseconds')
'2015-01-01T12:30:59.000000'

在 3.6 版本中更改: 添加了 timespec 引數。

datetime.__str__()

對於 datetime 例項 dstr(d) 等效於 d.isoformat(' ')

datetime.ctime()

返回表示日期和時間的字串

>>> from datetime import datetime
>>> datetime(2002, 12, 4, 20, 30, 40).ctime()
'Wed Dec  4 20:30:40 2002'

無論輸入是有感知還是無感知,輸出字串都將包括時區資訊。

d.ctime() 等價於

time.ctime(time.mktime(d.timetuple()))

在本地 C ctime() 函式(time.ctime() 呼叫該函式,但 datetime.ctime() 不呼叫該函式)符合 C 標準的平臺上。

datetime.strftime(format)

返回一個表示日期和時間的字串,由顯式格式字串控制。另請參閱 strftime() 和 strptime() 行為 以及 datetime.isoformat()

datetime.__format__(format)

datetime.strftime() 相同。這使得可以在格式化字串字面值中和使用 str.format() 時為 datetime 物件指定格式字串。另請參閱 strftime() 和 strptime() 行為 以及 datetime.isoformat()

用法示例:datetime

使用 datetime 物件的示例

>>> from datetime import datetime, date, time, timezone

>>> # Using datetime.combine()
>>> d = date(2005, 7, 14)
>>> t = time(12, 30)
>>> datetime.combine(d, t)
datetime.datetime(2005, 7, 14, 12, 30)

>>> # Using datetime.now()
>>> datetime.now()   
datetime.datetime(2007, 12, 6, 16, 29, 43, 79043)   # GMT +1
>>> datetime.now(timezone.utc)   
datetime.datetime(2007, 12, 6, 15, 29, 43, 79060, tzinfo=datetime.timezone.utc)

>>> # Using datetime.strptime()
>>> dt = datetime.strptime("21/11/06 16:30", "%d/%m/%y %H:%M")
>>> dt
datetime.datetime(2006, 11, 21, 16, 30)

>>> # Using datetime.timetuple() to get tuple of all attributes
>>> tt = dt.timetuple()
>>> for it in tt:   
...     print(it)
...
2006    # year
11      # month
21      # day
16      # hour
30      # minute
0       # second
1       # weekday (0 = Monday)
325     # number of days since 1st January
-1      # dst - method tzinfo.dst() returned None

>>> # Date in ISO format
>>> ic = dt.isocalendar()
>>> for it in ic:   
...     print(it)
...
2006    # ISO year
47      # ISO week
2       # ISO weekday

>>> # Formatting a datetime
>>> dt.strftime("%A, %d. %B %Y %I:%M%p")
'Tuesday, 21. November 2006 04:30PM'
>>> 'The {1} is {0:%d}, the {2} is {0:%B}, the {3} is {0:%I:%M%p}.'.format(dt, "day", "month", "time")
'The day is 21, the month is November, the time is 04:30PM.'

下面的示例定義了一個 tzinfo 子類,用於捕獲阿富汗喀布林的時區資訊,該子類在 1945 年之前使用 +4 UTC,之後使用 +4:30 UTC

from datetime import timedelta, datetime, tzinfo, timezone

class KabulTz(tzinfo):
    # Kabul used +4 until 1945, when they moved to +4:30
    UTC_MOVE_DATE = datetime(1944, 12, 31, 20, tzinfo=timezone.utc)

    def utcoffset(self, dt):
        if dt.year < 1945:
            return timedelta(hours=4)
        elif (1945, 1, 1, 0, 0) <= dt.timetuple()[:5] < (1945, 1, 1, 0, 30):
            # An ambiguous ("imaginary") half-hour range representing
            # a 'fold' in time due to the shift from +4 to +4:30.
            # If dt falls in the imaginary range, use fold to decide how
            # to resolve. See PEP495.
            return timedelta(hours=4, minutes=(30 if dt.fold else 0))
        else:
            return timedelta(hours=4, minutes=30)

    def fromutc(self, dt):
        # Follow same validations as in datetime.tzinfo
        if not isinstance(dt, datetime):
            raise TypeError("fromutc() requires a datetime argument")
        if dt.tzinfo is not self:
            raise ValueError("dt.tzinfo is not self")

        # A custom implementation is required for fromutc as
        # the input to this function is a datetime with utc values
        # but with a tzinfo set to self.
        # See datetime.astimezone or fromtimestamp.
        if dt.replace(tzinfo=timezone.utc) >= self.UTC_MOVE_DATE:
            return dt + timedelta(hours=4, minutes=30)
        else:
            return dt + timedelta(hours=4)

    def dst(self, dt):
        # Kabul does not observe daylight saving time.
        return timedelta(0)

    def tzname(self, dt):
        if dt >= self.UTC_MOVE_DATE:
            return "+04:30"
        return "+04"

上面 KabulTz 的用法

>>> tz1 = KabulTz()

>>> # Datetime before the change
>>> dt1 = datetime(1900, 11, 21, 16, 30, tzinfo=tz1)
>>> print(dt1.utcoffset())
4:00:00

>>> # Datetime after the change
>>> dt2 = datetime(2006, 6, 14, 13, 0, tzinfo=tz1)
>>> print(dt2.utcoffset())
4:30:00

>>> # Convert datetime to another time zone
>>> dt3 = dt2.astimezone(timezone.utc)
>>> dt3
datetime.datetime(2006, 6, 14, 8, 30, tzinfo=datetime.timezone.utc)
>>> dt2
datetime.datetime(2006, 6, 14, 13, 0, tzinfo=KabulTz())
>>> dt2 == dt3
True

time 物件

time 物件表示一天中的(本地)時間,獨立於任何特定的一天,並且可以透過 tzinfo 物件進行調整。

class datetime.time(hour=0, minute=0, second=0, microsecond=0, tzinfo=None, *, fold=0)

所有引數都是可選的。 tzinfo 可以是 None,也可以是 tzinfo 子類的例項。其餘引數必須是以下範圍內的整數

  • 0 <= hour < 24,

  • 0 <= minute < 60,

  • 0 <= second < 60,

  • 0 <= microsecond < 1000000,

  • fold in [0, 1].

如果給出的引數超出這些範圍,則會引發 ValueError。所有引數的預設值都為 0,除了 tzinfo,其預設值為 None

類屬性

time.min

最早可表示的 timetime(0, 0, 0, 0)

time.max

最新的可表示的 time,即 time(23, 59, 59, 999999)

time.resolution

不相等的 time 物件之間最小的可能差異,即 timedelta(microseconds=1),但請注意,不支援對 time 物件進行算術運算。

例項屬性(只讀)

time.hour

range(24) 中。

time.minute

range(60) 中。

time.second

range(60) 中。

time.microsecond

range(1000000) 中。

time.tzinfo

作為 tzinfo 引數傳遞給 time 建構函式的物件,如果沒有傳遞則為 None

time.fold

[0, 1] 中。用於消除重複間隔期間的掛鐘時間的歧義。(當夏令時結束時時鐘回撥或由於政治原因當前區域的 UTC 偏移量減小時,會發生重複間隔。)值 0 和 1 分別表示具有相同掛鐘時間表示的兩個時刻的較早和較晚時刻。

3.6 版本新增。

time 物件支援相等和順序比較,其中當 a 在時間上早於 b 時,則認為 a 小於 b

樸素(Naive)和感知(Aware)的 time 物件永遠不相等。 樸素和感知的 time 物件之間的順序比較會引發 TypeError

如果兩個比較物件都是感知的,並且具有相同的 tzinfo 屬性,則忽略 tzinfofold 屬性,並比較基本時間。如果兩個比較物件都是感知的,並且具有不同的 tzinfo 屬性,則首先透過減去它們的 UTC 偏移量(從 self.utcoffset() 獲取)來調整比較物件。

在 3.3 版本中更改: 感知和樸素 time 例項之間的相等比較不會引發 TypeError

在布林上下文中,time 物件始終被視為 true。

在 3.5 版本中更改: 在 Python 3.5 之前,如果 time 物件表示 UTC 午夜,則會被視為 false。此行為被認為是晦澀難懂且容易出錯的,已在 Python 3.5 中刪除。有關完整詳細資訊,請參閱 bpo-13936

其他建構函式

classmethod time.fromisoformat(time_string)

返回與任何有效的 ISO 8601 格式的 time_string 對應的 time,但有以下例外:

  1. 時區偏移量可能包含小數秒。

  2. 在日期和時間之間可能存在歧義的情況下,通常需要的開頭 T 是不需要的。

  3. 小數秒可以有任意位數(超過 6 位的任何位數都將被截斷)。

  4. 不支援小數小時和分鐘。

示例

>>> from datetime import time
>>> time.fromisoformat('04:23:01')
datetime.time(4, 23, 1)
>>> time.fromisoformat('T04:23:01')
datetime.time(4, 23, 1)
>>> time.fromisoformat('T042301')
datetime.time(4, 23, 1)
>>> time.fromisoformat('04:23:01.000384')
datetime.time(4, 23, 1, 384)
>>> time.fromisoformat('04:23:01,000384')
datetime.time(4, 23, 1, 384)
>>> time.fromisoformat('04:23:01+04:00')
datetime.time(4, 23, 1, tzinfo=datetime.timezone(datetime.timedelta(seconds=14400)))
>>> time.fromisoformat('04:23:01Z')
datetime.time(4, 23, 1, tzinfo=datetime.timezone.utc)
>>> time.fromisoformat('04:23:01+00:00')
datetime.time(4, 23, 1, tzinfo=datetime.timezone.utc)

3.7 版本中新增。

在 3.11 版本中更改: 以前,此方法僅支援可以由 time.isoformat() 發出的格式。

例項方法

time.replace(hour=self.hour, minute=self.minute, second=self.second, microsecond=self.microsecond, tzinfo=self.tzinfo, *, fold=0)

返回一個具有相同值的 time,但由指定的任何關鍵字引數賦予新值的屬性除外。請注意,可以指定 tzinfo=None 從一個感知的 time 建立一個樸素的 time,而無需轉換時間資料。

time 物件也受通用函式 copy.replace() 支援。

在 3.6 版本中更改: 添加了 fold 引數。

time.isoformat(timespec='auto')

返回一個以 ISO 8601 格式表示時間的字串,以下之一:

可選引數 timespec 指定要包含的時間的附加組成部分的數量(預設為 'auto')。它可以是以下之一

  • 'auto':如果 microsecond 為 0,則與 'seconds' 相同,否則與 'microseconds' 相同。

  • 'hours':以兩位數 HH 格式包含 hour

  • 'minutes':以 HH:MM 格式包含 hourminute

  • 'seconds':包括 hourminutesecond,格式為 HH:MM:SS

  • 'milliseconds': 包括完整時間,但將小數秒部分截斷為毫秒。 HH:MM:SS.sss 格式。

  • 'microseconds': 以 HH:MM:SS.ffffff 格式包括完整時間。

注意

排除的時間組成部分被截斷,而不是四捨五入。

如果 timespec 引數無效,將引發 ValueError 異常。

示例

>>> from datetime import time
>>> time(hour=12, minute=34, second=56, microsecond=123456).isoformat(timespec='minutes')
'12:34'
>>> dt = time(hour=12, minute=34, second=56, microsecond=0)
>>> dt.isoformat(timespec='microseconds')
'12:34:56.000000'
>>> dt.isoformat(timespec='auto')
'12:34:56'

在 3.6 版本中更改: 添加了 timespec 引數。

time.__str__()

對於時間 tstr(t) 等同於 t.isoformat()

time.strftime(format)

返回一個字串,表示由顯式格式字串控制的時間。另請參閱 strftime() 和 strptime() 的行為time.isoformat()

time.__format__(format)

time.strftime() 相同。 這使得可以在 格式化字串字面值 中以及使用 str.format() 時為 time 物件指定格式字串。另請參閱 strftime() 和 strptime() 的行為time.isoformat()

time.utcoffset()

如果 tzinfoNone,則返回 None,否則返回 self.tzinfo.utcoffset(None),如果後者沒有返回 None 或一個大小小於一天的 timedelta 物件,則會引發異常。

在 3.7 版本中變更:UTC 偏移量不再限制為整數分鐘。

time.dst()

如果 tzinfoNone,則返回 None,否則返回 self.tzinfo.dst(None),如果後者沒有返回 None,或者返回一個大小小於一天的 timedelta 物件,則會引發異常。

在 3.7 版本中變更:DST 偏移量不再限制為整數分鐘。

time.tzname()

如果 tzinfoNone,則返回 None,否則返回 self.tzinfo.tzname(None),如果後者沒有返回 None 或一個字串物件,則會引發異常。

用法示例:time

使用 time 物件的示例

>>> from datetime import time, tzinfo, timedelta
>>> class TZ1(tzinfo):
...     def utcoffset(self, dt):
...         return timedelta(hours=1)
...     def dst(self, dt):
...         return timedelta(0)
...     def tzname(self,dt):
...         return "+01:00"
...     def  __repr__(self):
...         return f"{self.__class__.__name__}()"
...
>>> t = time(12, 10, 30, tzinfo=TZ1())
>>> t
datetime.time(12, 10, 30, tzinfo=TZ1())
>>> t.isoformat()
'12:10:30+01:00'
>>> t.dst()
datetime.timedelta(0)
>>> t.tzname()
'+01:00'
>>> t.strftime("%H:%M:%S %Z")
'12:10:30 +01:00'
>>> 'The {} is {:%H:%M}.'.format("time", t)
'The time is 12:10.'

tzinfo 物件

class datetime.tzinfo

這是一個抽象基類,這意味著不應直接例項化此類。定義 tzinfo 的子類,以捕獲有關特定時區的資訊。

tzinfo 的(具體子類的)例項可以傳遞給 datetimetime 物件的建構函式。 後者物件將其屬性視為本地時間,並且 tzinfo 物件支援顯示本地時間與 UTC 偏移量、時區名稱和 DST 偏移量的方法,所有這些都相對於傳遞給它們的日期或時間物件。

你需要派生一個具體的子類,並且(至少)提供你使用的 datetime 方法所需的標準 tzinfo 方法的實現。 datetime 模組提供了 timezone,它是 tzinfo 的一個簡單的具體子類,可以表示與 UTC 有固定偏移量的時區,例如 UTC 本身或北美 EST 和 EDT。

pickling 的特殊要求: tzinfo 子類必須有一個可以使用無引數呼叫的 __init__() 方法,否則可以對其進行 pickled 處理,但可能無法再次 unpickled。這是一項技術要求,將來可能會放寬。

tzinfo 的具體子類可能需要實現以下方法。具體需要哪些方法取決於對 aware datetime 物件的使用情況。 如果有疑問,只需實現所有這些方法即可。

tzinfo.utcoffset(dt)

返回本地時間與 UTC 的偏移量,以 timedelta 物件的形式返回,該物件在 UTC 東邊為正值。如果本地時間位於 UTC 西邊,則該值應為負值。

這表示與 UTC 的偏移量; 例如,如果 tzinfo 物件表示時區和 DST 調整,則 utcoffset() 應該返回它們的總和。如果 UTC 偏移量未知,則返回 None。 否則,返回的值必須是一個 timedelta 物件,其值嚴格介於 -timedelta(hours=24)timedelta(hours=24) 之間(偏移量的大小必須小於一天)。 大多數 utcoffset() 的實現可能類似於以下兩種之一

return CONSTANT                 # fixed-offset class
return CONSTANT + self.dst(dt)  # daylight-aware class

如果 utcoffset() 不返回 None,則 dst() 也不應返回 None

utcoffset() 的預設實現會引發 NotImplementedError

在 3.7 版本中變更:UTC 偏移量不再限制為整數分鐘。

tzinfo.dst(dt)

返回夏令時 (DST) 調整,以 timedelta 物件的形式返回,如果 DST 資訊未知,則返回 None

如果夏令時未生效,則返回 timedelta(0)。如果夏令時生效,則返回偏移量,型別為 timedelta 物件(詳見 utcoffset())。請注意,夏令時偏移量(如果適用)已新增到 utcoffset() 返回的 UTC 偏移量中,因此無需查詢 dst(),除非您想單獨獲取夏令時資訊。例如,datetime.timetuple() 會呼叫其 tzinfo 屬性的 dst() 方法,以確定應如何設定 tm_isdst 標誌,並且 tzinfo.fromutc() 會呼叫 dst() 來考慮跨時區時夏令時的變化。

一個 tzinfo 子類的例項 tz,如果它同時模擬標準時間和夏令時,則必須在此意義上保持一致:

tz.utcoffset(dt) - tz.dst(dt)

對於每個滿足 dt.tzinfo == tzdatetime dt,都必須返回相同的結果。對於合理的 tzinfo 子類,此表示式會產生時區的“標準偏移量”,該偏移量不應取決於日期或時間,而只取決於地理位置。datetime.astimezone() 的實現依賴於此,但無法檢測到違規行為;程式設計師有責任確保這一點。如果一個 tzinfo 子類無法保證這一點,它或許可以重寫 tzinfo.fromutc() 的預設實現,以便無論如何都能與 astimezone() 正確工作。

大多數 dst() 的實現可能看起來像以下兩種之一:

def dst(self, dt):
    # a fixed-offset class:  doesn't account for DST
    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.

    if dston <= dt.replace(tzinfo=None) < dstoff:
        return timedelta(hours=1)
    else:
        return timedelta(0)

dst() 的預設實現會引發 NotImplementedError

在 3.7 版本中變更:DST 偏移量不再限制為整數分鐘。

tzinfo.tzname(dt)

返回與 datetime 物件 dt 對應的時區名稱,型別為字串。 datetime 模組沒有定義關於字串名稱的任何內容,並且也沒有要求它必須具有任何特定的含義。例如,"GMT""UTC""-500""-5:00""EDT""US/Eastern""America/New York" 都是有效的回覆。如果字串名稱未知,則返回 None。請注意,這是一個方法而不是固定的字串,主要是因為某些 tzinfo 子類希望根據傳遞的 dt 的特定值返回不同的名稱,尤其是在 tzinfo 類考慮夏令時的情況下。

tzname() 的預設實現會引發 NotImplementedError

這些方法由 datetimetime 物件呼叫,以響應其具有相同名稱的方法。datetime 物件將其自身作為引數傳遞,而 time 物件則將 None 作為引數傳遞。因此,tzinfo 子類的方法應準備好接受 dt 引數為 Nonedatetime 類。

當傳遞 None 時,由類設計者決定最佳響應。例如,如果類希望表示 time 物件不參與 tzinfo 協議,則返回 None 是合適的。 對於 utcoffset(None),返回標準 UTC 偏移量可能更有用,因為沒有其他約定來發現標準偏移量。

當為了響應 datetime 方法而傳遞 datetime 物件時,dt.tzinfoself 是同一個物件。tzinfo 方法可以依賴於此,除非使用者程式碼直接呼叫 tzinfo 方法。其目的是 tzinfo 方法將 dt 解釋為本地時間,而無需擔心其他時區的物件。

還有一個 tzinfo 方法,子類可能希望重寫:

tzinfo.fromutc(dt)

這是從預設的 datetime.astimezone() 實現中呼叫的。當從該方法呼叫時,dt.tzinfoself,並且 dt 的日期和時間資料應視為表達 UTC 時間。fromutc() 的目的是調整日期和時間資料,返回 self 本地時間中等效的 datetime。

大多數 tzinfo 子類應該能夠毫無問題地繼承預設的 fromutc() 實現。它足夠強大,可以處理固定偏移時區,以及同時考慮標準時間和夏令時的時區,即使不同年份的夏令時轉換時間不同也是如此。預設的 fromutc() 實現在所有情況下可能都無法正確處理的時區示例是,標準偏移量(與 UTC 的偏移量)取決於傳遞的特定日期和時間,這可能因政治原因而發生。如果結果是跨越標準偏移量變化時刻的某個小時,則 astimezone()fromutc() 的預設實現可能不會產生您想要的結果。

省略錯誤情況的程式碼,預設的 fromutc() 實現類似於:

def fromutc(self, dt):
    # raise ValueError error if dt.tzinfo is not self
    dtoff = dt.utcoffset()
    dtdst = dt.dst()
    # raise ValueError if dtoff is None or dtdst is None
    delta = dtoff - dtdst  # this is self's standard offset
    if delta:
        dt += delta   # convert to standard local time
        dtdst = dt.dst()
        # raise ValueError if dtdst is None
    if dtdst:
        return dt + dtdst
    else:
        return dt

在下面的 tzinfo_examples.py 檔案中,有一些關於 tzinfo 類的示例。

from datetime import tzinfo, timedelta, datetime

ZERO = timedelta(0)
HOUR = timedelta(hours=1)
SECOND = timedelta(seconds=1)

# A class capturing the platform's idea of local time.
# (May result in wrong values on historical times in
#  timezones where UTC offset and/or the DST rules had
#  changed in the past.)
import time as _time

STDOFFSET = timedelta(seconds = -_time.timezone)
if _time.daylight:
    DSTOFFSET = timedelta(seconds = -_time.altzone)
else:
    DSTOFFSET = STDOFFSET

DSTDIFF = DSTOFFSET - STDOFFSET

class LocalTimezone(tzinfo):

    def fromutc(self, dt):
        assert dt.tzinfo is self
        stamp = (dt - datetime(1970, 1, 1, tzinfo=self)) // SECOND
        args = _time.localtime(stamp)[:6]
        dst_diff = DSTDIFF // SECOND
        # Detect fold
        fold = (args == _time.localtime(stamp - dst_diff))
        return datetime(*args, microsecond=dt.microsecond,
                        tzinfo=self, fold=fold)

    def utcoffset(self, dt):
        if self._isdst(dt):
            return DSTOFFSET
        else:
            return STDOFFSET

    def dst(self, dt):
        if self._isdst(dt):
            return DSTDIFF
        else:
            return ZERO

    def tzname(self, dt):
        return _time.tzname[self._isdst(dt)]

    def _isdst(self, dt):
        tt = (dt.year, dt.month, dt.day,
              dt.hour, dt.minute, dt.second,
              dt.weekday(), 0, 0)
        stamp = _time.mktime(tt)
        tt = _time.localtime(stamp)
        return tt.tm_isdst > 0

Local = LocalTimezone()


# A complete implementation of current DST rules for major US time zones.

def first_sunday_on_or_after(dt):
    days_to_go = 6 - dt.weekday()
    if days_to_go:
        dt += timedelta(days_to_go)
    return dt


# US DST Rules
#
# This is a simplified (i.e., wrong for a few cases) set of rules for US
# DST start and end times. For a complete and up-to-date set of DST rules
# and timezone definitions, visit the Olson Database (or try pytz):
# http://www.twinsun.com/tz/tz-link.htm
# https://sourceforge.net/projects/pytz/ (might not be up-to-date)
#
# In the US, since 2007, DST starts at 2am (standard time) on the second
# Sunday in March, which is the first Sunday on or after Mar 8.
DSTSTART_2007 = datetime(1, 3, 8, 2)
# and ends at 2am (DST time) on the first Sunday of Nov.
DSTEND_2007 = datetime(1, 11, 1, 2)
# From 1987 to 2006, DST used to start at 2am (standard time) on the first
# Sunday in April and to end at 2am (DST time) on the last
# Sunday of October, which is the first Sunday on or after Oct 25.
DSTSTART_1987_2006 = datetime(1, 4, 1, 2)
DSTEND_1987_2006 = datetime(1, 10, 25, 2)
# From 1967 to 1986, DST used to start at 2am (standard time) on the last
# Sunday in April (the one on or after April 24) and to end at 2am (DST time)
# on the last Sunday of October, which is the first Sunday
# on or after Oct 25.
DSTSTART_1967_1986 = datetime(1, 4, 24, 2)
DSTEND_1967_1986 = DSTEND_1987_2006

def us_dst_range(year):
    # Find start and end times for US DST. For years before 1967, return
    # start = end for no DST.
    if 2006 < year:
        dststart, dstend = DSTSTART_2007, DSTEND_2007
    elif 1986 < year < 2007:
        dststart, dstend = DSTSTART_1987_2006, DSTEND_1987_2006
    elif 1966 < year < 1987:
        dststart, dstend = DSTSTART_1967_1986, DSTEND_1967_1986
    else:
        return (datetime(year, 1, 1), ) * 2

    start = first_sunday_on_or_after(dststart.replace(year=year))
    end = first_sunday_on_or_after(dstend.replace(year=year))
    return start, end


class USTimeZone(tzinfo):

    def __init__(self, hours, reprname, stdname, dstname):
        self.stdoffset = timedelta(hours=hours)
        self.reprname = reprname
        self.stdname = stdname
        self.dstname = dstname

    def __repr__(self):
        return self.reprname

    def tzname(self, dt):
        if self.dst(dt):
            return self.dstname
        else:
            return self.stdname

    def utcoffset(self, dt):
        return self.stdoffset + self.dst(dt)

    def dst(self, dt):
        if dt is None or dt.tzinfo is None:
            # An exception may be sensible here, in one or both cases.
            # It depends on how you want to treat them.  The default
            # fromutc() implementation (called by the default astimezone()
            # implementation) passes a datetime with dt.tzinfo is self.
            return ZERO
        assert dt.tzinfo is self
        start, end = us_dst_range(dt.year)
        # Can't compare naive to aware objects, so strip the timezone from
        # dt first.
        dt = dt.replace(tzinfo=None)
        if start + HOUR <= dt < end - HOUR:
            # DST is in effect.
            return HOUR
        if end - HOUR <= dt < end:
            # Fold (an ambiguous hour): use dt.fold to disambiguate.
            return ZERO if dt.fold else HOUR
        if start <= dt < start + HOUR:
            # Gap (a non-existent hour): reverse the fold rule.
            return HOUR if dt.fold else ZERO
        # DST is off.
        return ZERO

    def fromutc(self, dt):
        assert dt.tzinfo is self
        start, end = us_dst_range(dt.year)
        start = start.replace(tzinfo=self)
        end = end.replace(tzinfo=self)
        std_time = dt + self.stdoffset
        dst_time = std_time + HOUR
        if end <= dst_time < end + HOUR:
            # Repeated hour
            return std_time.replace(fold=1)
        if std_time < start or dst_time >= end:
            # Standard time
            return std_time
        if start <= std_time < end - HOUR:
            # Daylight saving time
            return dst_time


Eastern  = USTimeZone(-5, "Eastern",  "EST", "EDT")
Central  = USTimeZone(-6, "Central",  "CST", "CDT")
Mountain = USTimeZone(-7, "Mountain", "MST", "MDT")
Pacific  = USTimeZone(-8, "Pacific",  "PST", "PDT")

請注意,在考慮標準時間和夏令時的 tzinfo 子類中,每年在夏令時轉換點會不可避免地出現兩次細微差別。為了具體起見,考慮美國東部時間(UTC-0500),其中夏令時在三月第二個星期日的 1:59 (EST) 之後開始,並在十一月第一個星期日的 1:59 (EDT) 之後結束。

  UTC   3:MM  4:MM  5:MM  6:MM  7:MM  8:MM
  EST  22:MM 23:MM  0:MM  1:MM  2:MM  3:MM
  EDT  23:MM  0:MM  1:MM  2:MM  3:MM  4:MM

start  22:MM 23:MM  0:MM  1:MM  3:MM  4:MM

  end  23:MM  0:MM  1:MM  1:MM  2:MM  3:MM

當夏令時開始(“開始”行)時,本地時間會從 1:59 跳到 3:00。形式為 2:MM 的本地時間在那一天實際上沒有意義,因此 astimezone(Eastern) 不會在夏令時開始的當天產生 hour == 2 的結果。例如,在 2016 年的春季前進轉換時,我們得到:

>>> from datetime import datetime, timezone
>>> from tzinfo_examples import HOUR, Eastern
>>> u0 = datetime(2016, 3, 13, 5, tzinfo=timezone.utc)
>>> for i in range(4):
...     u = u0 + i*HOUR
...     t = u.astimezone(Eastern)
...     print(u.time(), 'UTC =', t.time(), t.tzname())
...
05:00:00 UTC = 00:00:00 EST
06:00:00 UTC = 01:00:00 EST
07:00:00 UTC = 03:00:00 EDT
08:00:00 UTC = 04:00:00 EDT

當夏令時結束(“結束”行)時,可能會出現更嚴重的問題:在本地時間中,有一個小時無法明確表達,即夏令時的最後一個小時。在東部時間,這是夏令時結束當天的形式為 5:MM UTC 的時間。本地時間會從 1:59(夏令時)跳回 1:00(標準時間)。形式為 1:MM 的本地時間是不明確的。 astimezone() 透過將兩個相鄰的 UTC 小時對映到相同的本地小時來模擬本地時鐘的行為。在東部時間的例子中,形式為 5:MM 和 6:MM 的 UTC 時間在轉換為東部時間時都對映到 1:MM,但較早的時間的 fold 屬性設定為 0,而較晚的時間將其設定為 1。例如,在 2016 年的秋季回退轉換時,我們得到:

>>> u0 = datetime(2016, 11, 6, 4, tzinfo=timezone.utc)
>>> for i in range(4):
...     u = u0 + i*HOUR
...     t = u.astimezone(Eastern)
...     print(u.time(), 'UTC =', t.time(), t.tzname(), t.fold)
...
04:00:00 UTC = 00:00:00 EDT 0
05:00:00 UTC = 01:00:00 EDT 0
06:00:00 UTC = 01:00:00 EST 1
07:00:00 UTC = 02:00:00 EST 0

請注意,僅 datetime 例項的 fold 屬性值不同,在比較時被認為是相等的。

無法忍受本地時間歧義的應用程式應顯式檢查 fold 屬性的值,或避免使用混合的 tzinfo 子類;當使用 timezone 或任何其他固定偏移量的 tzinfo 子類時(例如,僅表示 EST(固定偏移 -5 小時)或僅表示 EDT(固定偏移 -4 小時)的類),不會出現歧義。

另請參閱

zoneinfo

datetime 模組具有基本的 timezone 類(用於處理來自 UTC 的任意固定偏移量)及其 timezone.utc 屬性(一個 UTC timezone 例項)。

zoneinfoIANA 時區資料庫(也稱為 Olson 資料庫)引入 Python,建議使用它。

IANA 時區資料庫

時區資料庫(通常稱為 tz、tzdata 或 zoneinfo)包含程式碼和資料,這些程式碼和資料表示全球許多代表性位置的本地時間歷史。它會定期更新,以反映政治機構對時區邊界、UTC 偏移量和夏令時規則所做的更改。

timezone 物件

timezone 類是 tzinfo 的子類,其每個例項表示由來自 UTC 的固定偏移量定義的時區。

此類物件不能用於表示在一年中的不同日期使用不同偏移量或對民用時間進行歷史更改的位置的時區資訊。

class datetime.timezone(offset, name=None)

offset 引數必須指定為表示本地時間與 UTC 之間差異的 timedelta 物件。它必須嚴格介於 -timedelta(hours=24)timedelta(hours=24) 之間,否則會引發 ValueError

name 引數是可選的。如果指定,它必須是一個字串,該字串將用作 datetime.tzname() 方法返回的值。

在版本 3.2 中新增。

在 3.7 版本中變更:UTC 偏移量不再限制為整數分鐘。

timezone.utcoffset(dt)

返回構造 timezone 例項時指定的固定值。

dt 引數被忽略。返回值是 timedelta 例項,等於本地時間與 UTC 之間的差異。

在 3.7 版本中變更:UTC 偏移量不再限制為整數分鐘。

timezone.tzname(dt)

返回構造 timezone 例項時指定的固定值。

如果在建構函式中未提供 name,則 tzname(dt) 返回的名稱將根據 offset 的值生成,如下所示。如果 offsettimedelta(0),則名稱為 “UTC”,否則它是一個格式為 UTC±HH:MM 的字串,其中 ± 是 offset 的符號,HH 和 MM 分別是 offset.hoursoffset.minutes 的兩位數字。

在 3.6 版本中更改: offset=timedelta(0) 生成的名稱現在是純粹的 'UTC',而不是 'UTC+00:00'

timezone.dst(dt)

始終返回 None

timezone.fromutc(dt)

返回 dt + offsetdt 引數必須是具有 tzinfo 設定為 self 的感知 datetime 例項。

類屬性

timezone.utc

UTC 時區,timezone(timedelta(0))

strftime()strptime() 行為

datedatetimetime 物件都支援 strftime(format) 方法,以建立在顯式格式字串控制下表示時間的字串。

相反, datetime.strptime() 類方法根據表示日期和時間的字串和相應的格式字串建立一個 datetime 物件。

下表提供了 strftime()strptime() 的高階比較

strftime

strptime

用法

根據給定的格式將物件轉換為字串

根據相應的格式將字串解析為 datetime 物件。

方法型別

例項方法

類方法

所屬方法

date; datetime; time

datetime

簽名

strftime(format)

strptime(date_string, format)

strftime()strptime() 格式程式碼

這些方法接受格式程式碼,可用於解析和格式化日期。

>>> datetime.strptime('31/01/22 23:59:59.999999',
...                   '%d/%m/%y %H:%M:%S.%f')
datetime.datetime(2022, 1, 31, 23, 59, 59, 999999)
>>> _.strftime('%a %d %b %Y, %I:%M%p')
'Mon 31 Jan 2022, 11:59PM'

以下是 1989 C 標準要求的所有格式程式碼的列表,這些程式碼在所有具有標準 C 實現的平臺上都能工作。

指令

含義

示例

備註

%a

以區域設定的縮寫形式表示星期幾。

Sun, Mon, …, Sat (en_US);
So, Mo, …, Sa (de_DE)

(1)

%A

以區域設定的全名錶示星期幾。

Sunday, Monday, …, Saturday (en_US);
Sonntag, Montag, …, Samstag (de_DE)

(1)

%w

以十進位制數字表示星期幾,其中 0 表示星期日,6 表示星期六。

0, 1, …, 6

%d

以零填充的十進位制數字表示月份中的第幾天。

01, 02, …, 31

(9)

%b

以區域設定的縮寫形式表示月份。

Jan, Feb, …, Dec (en_US);
Jan, Feb, …, Dez (de_DE)

(1)

%B

以區域設定的全名錶示月份。

January, February, …, December (en_US);
Januar, Februar, …, Dezember (de_DE)

(1)

%m

以零填充的十進位制數字表示月份。

01, 02, …, 12

(9)

%y

以零填充的十進位制數字表示不帶世紀的年份。

00, 01, …, 99

(9)

%Y

以十進位制數字表示帶世紀的年份。

0001, 0002, …, 2013, 2014, …, 9998, 9999

(2)

%H

以零填充的十進位制數字表示小時(24 小時制)。

00, 01, …, 23

(9)

%I

以零填充的十進位制數字表示小時(12 小時制)。

01, 02, …, 12

(9)

%p

區域設定中與 AM 或 PM 等效的表示。

AM, PM (en_US);
am, pm (de_DE)

(1), (3)

%M

以零填充的十進位制數字表示分鐘。

00, 01, …, 59

(9)

%S

以零填充的十進位制數字表示秒。

00, 01, …, 59

(4), (9)

%f

以十進位制數字表示微秒,零填充至 6 位。

000000, 000001, …, 999999

(5)

%z

±HHMM[SS[.ffffff]] 格式表示 UTC 偏移量(如果物件是 naive,則為空字串)。

(empty), +0000, -0400, +1030, +063415, -030712.345216

(6)

%Z

時區名稱(如果物件是 naive,則為空字串)。

(empty), UTC, GMT

(6)

%j

以零填充的十進位制數字表示一年中的第幾天。

001, 002, …, 366

(9)

%U

以零填充的十進位制數字表示一年中的週數(星期日為一週的第一天)。 新年中第一個星期日之前的所有天數都視為第 0 周。

00, 01, …, 53

(7), (9)

%W

以零填充的十進位制數字表示一年中的週數(星期一為一週的第一天)。 新年中第一個星期一之前的所有天數都視為第 0 周。

00, 01, …, 53

(7), (9)

%c

區域設定的適當日期和時間表示。

Tue Aug 16 21:30:00 1988 (en_US);
Di 16 Aug 21:30:00 1988 (de_DE)

(1)

%x

區域設定的適當日期表示。

08/16/88 (None);
08/16/1988 (en_US);
16.08.1988 (de_DE)

(1)

%X

區域設定的適當時間表示。

21:30:00 (en_US);
21:30:00 (de_DE)

(1)

%%

文字字元 '%'

%

為了方便起見,還包括了 C89 標準未要求的其他幾個指令。 這些引數都對應於 ISO 8601 日期值。

指令

含義

示例

備註

%G

表示包含 ISO 周(%V)大部分的年份的帶世紀 ISO 8601 年份。

0001, 0002, …, 2013, 2014, …, 9998, 9999

(8)

%u

以十進位制數字表示 ISO 8601 星期幾,其中 1 表示星期一。

1, 2, …, 7

%V

以十進位制數字表示 ISO 8601 周,其中星期一為一週的第一天。 第 01 周是包含 1 月 4 日的那一週。

01, 02, …, 53

(8), (9)

%:z

±HH:MM[:SS[.ffffff]] 格式表示 UTC 偏移量(如果物件是 naive,則為空字串)。

(empty), +00:00, -04:00, +10:30, +06:34:15, -03:07:12.345216

(6)

strftime() 方法一起使用時,這些方法可能並非在所有平臺上都可用。 ISO 8601 年份和 ISO 8601 周指令與上面的年份和週數指令不可互換。 呼叫帶有不完整或不明確的 ISO 8601 指令的 strptime() 會引發 ValueError

支援的完整格式程式碼集因平臺而異,因為 Python 呼叫平臺 C 庫的 strftime() 函式,並且平臺差異很常見。 要檢視平臺上支援的完整格式程式碼集,請查閱 strftime(3) 文件。 在處理不受支援的格式說明符時,平臺之間也存在差異。

3.6 版本中新增: 添加了 %G%u%V

3.12 版本中新增: 添加了 %:z

技術細節

廣義而言,d.strftime(fmt) 的行為類似於 time 模組的 time.strftime(fmt, d.timetuple()),儘管並非所有物件都支援 timetuple() 方法。

對於 datetime.strptime() 類方法,預設值為 1900-01-01T00:00:00.000:格式字串中未指定的任何元件都將從預設值中提取。 [4]

使用 datetime.strptime(date_string, format) 等效於

datetime(*(time.strptime(date_string, format)[0:6]))

除非格式包含亞秒級元件或時區偏移量資訊,這些資訊在 datetime.strptime 中受支援,但在 time.strptime 中會被丟棄。

對於 time 物件,不應使用年、月和日的格式程式碼,因為 time 物件沒有這些值。 如果仍然使用,則年份將替換為 1900,月份和日期將替換為 1。

對於 date 物件,不應使用小時、分鐘、秒和微秒的格式程式碼,因為 date 物件沒有這些值。 如果仍然使用,則將它們替換為 0。

出於同樣的原因,處理包含當前區域設定字元集中無法表示的 Unicode 程式碼點的格式字串也取決於平臺。 在某些平臺上,此類程式碼點在輸出中完整保留,而在其他平臺上,strftime 可能會引發 UnicodeError 或返回空字串。

備註

  1. 由於格式取決於當前區域設定,因此在對輸出值進行假設時應格外小心。 欄位順序會有所不同(例如,“月/日/年”與“日/月/年”),並且輸出可能包含非 ASCII 字元。

  2. strptime() 方法可以解析 [1, 9999] 範圍內的年份,但 < 1000 的年份必須零填充為 4 位寬度。

    在 3.2 版本中更改: 在以前的版本中,strftime() 方法僅限於 >= 1900 的年份。

    在 3.3 版本中更改: 在 3.2 版本中,strftime() 方法僅限於 >= 1000 的年份。

  3. 當與 strptime() 方法一起使用時,%p 指令僅在使用 %I 指令解析小時時才會影響輸出的小時欄位。

  4. time 模組不同,datetime 模組不支援閏秒。

  5. 當與 strptime() 方法一起使用時,%f 指令接受一到六位數字,並在右側填充零。%f 是對 C 標準中格式字元集的擴充套件(但在 datetime 物件中單獨實現,因此始終可用)。

  6. 對於樸素物件,%z%:z%Z 格式程式碼將替換為空字串。

    對於感知物件

    %z

    utcoffset() 被轉換為 ±HHMM[SS[.ffffff]] 形式的字串,其中 HH 是一個 2 位字串,表示 UTC 偏移小時數,MM 是一個 2 位字串,表示 UTC 偏移分鐘數,SS 是一個 2 位字串,表示 UTC 偏移秒數,ffffff 是一個 6 位字串,表示 UTC 偏移微秒數。當偏移量為整數秒時,將省略 ffffff 部分;當偏移量為整數分鐘時,將省略 ffffffSS 部分。例如,如果 utcoffset() 返回 timedelta(hours=-3, minutes=-30),則 %z 將被替換為字串 '-0330'

    在 3.7 版本中變更:UTC 偏移量不再限制為整數分鐘。

    在 3.7 版本中更改: 當向 strptime() 方法提供 %z 指令時,UTC 偏移量的小時、分鐘和秒之間可以使用冒號作為分隔符。例如,'+01:00:00' 將被解析為一小時的偏移量。此外,提供 'Z''+00:00' 相同。

    %:z

    行為與 %z 完全相同,但小時、分鐘和秒之間添加了冒號分隔符。

    %Z

    strftime() 中,如果 tzname() 返回 None,則 %Z 將被替換為空字串;否則,%Z 將被替換為返回的值,該值必須是字串。

    strptime() 僅接受 %Z 的某些值

    1. 您的機器區域設定中 time.tzname 中的任何值

    2. 硬編碼的值 UTCGMT

    因此,住在日本的人可能會將 JSTUTCGMT 作為有效值,但可能不包括 EST。對於無效值,它將引發 ValueError

    在 3.2 版本中更改: 當向 strptime() 方法提供 %z 指令時,將生成一個感知 datetime 物件。結果的 tzinfo 將被設定為 timezone 例項。

  7. 當與 strptime() 方法一起使用時,%U%W 僅在指定星期幾和日曆年份 (%Y) 時才在計算中使用。

  8. %U%W 類似,%V 僅在 strptime() 格式字串中指定星期幾和 ISO 年份 (%G) 時才在計算中使用。另請注意,%G%Y 不可互換。

  9. 當與 strptime() 方法一起使用時,對於格式 %d%m%H%I%M%S%j%U%W%V,前導零是可選的。格式 %y 需要前導零。

  10. 當使用 strptime() 解析月份和日期時,請始終在格式中包含年份。如果您需要解析的值缺少年份,請附加一個顯式的虛擬閏年。否則,您的程式碼在遇到閏日時會引發異常,因為解析器使用的預設年份不是閏年。使用者每四年都會遇到此錯誤……

    >>> month_day = "02/29"
    >>> datetime.strptime(f"{month_day};1984", "%m/%d;%Y")  # No leap year bug.
    datetime.datetime(1984, 2, 29, 0, 0)
    

    在 3.13 版本中已棄用,將在 3.15 版本中移除: 使用包含沒有年份的月份日期格式字串呼叫 strptime() 現在會發出 DeprecationWarning。在 3.15 或更高版本中,我們可能會將其更改為錯誤,或者將預設年份更改為閏年。請參閱 gh-70647

腳註