8.1. datetime-基本日期和时间类型

2.3 版的新Function。

datetime模块提供了用于以简单和复杂方式操纵日期和时间的类。虽然支持日期和时间算术,但实现的重点是针对输出格式和操作的有效属性提取。有关相关Function,另请参见timecalendar模块。

有两种日期和时间对象:“天真”和“意识”。

一个有意识的对象对适用的算法和政治时间调整(例如时区和夏时制时间信息)具有足够的知识,可以相对于其他有意识的对象定位自己。有意识的对象用于表示特定时间,该特定时间对解释[1]不开放。

天真的对象没有足够的信息来明确地相对于其他日期/时间对象定位自己。天真对象是代表协调世界时(UTC),本地时间还是在其他时区中的时间,完全取决于程序,就像特定数字代表米,英里或质量取决于程序一样。天真的对象易于理解和使用,以忽略现实的某些方面为代价。

对于需要感知对象的应用程序,datetimetime对象具有可选的时区信息属性tzinfo,可以将其设置为抽象tzinfo类的子类的实例。这些tzinfo对象捕获有关 UTC 时间的偏移量,时区名称以及夏时制是否有效的信息。请注意,datetime模块未提供任何具体的tzinfo类。支持时区的详细程度取决于应用程序。Global 范围内的时间调整规则更具政治性,而不是理性性,并且没有适用于每种应用程序的标准。

datetime模块导出以下常量:

See also

  • Module calendar

  • 常规 calendar 相关Function。

  • Module time

  • 时间访问和转换。

8.1.1. 可用类型

这些类型的对象是不可变的。

date类型的对象总是幼稚的。

类型timedatetime的对象可能是幼稚的或感知的。 datetime对象* d 知道d.tzinfo不是None并且d.tzinfo.utcoffset(d)不返回None。如果d.tzinfoNone,或者d.tzinfo不是None而是d.tzinfo.utcoffset(d)返回None,则 d 是幼稚的。 time对象 t 知道t.tzinfo不是None并且t.tzinfo.utcoffset(None)不返回None。否则, t *是幼稚的。

天真和有意识之间的区别不适用于timedelta个对象。

Subclass relationships:

object
    timedelta
    tzinfo
    time
    date
        datetime

8.1.2. timedelta 对象

timedelta对象代表持续时间,即两个日期或时间之间的差。

内部仅存储* day seconds microseconds *。参数将转换为以下单位:

然后将天,秒和微秒标准化,以使表示形式唯一

如果任何自变量是浮点型并且有分数微秒,则将从所有自变量剩余的分数微秒进行合并,并且它们的和将四舍五入到最接近的微秒。如果没有参数是浮点数,则转换和规范化过程是精确的(不会丢失任何信息)。

如果天的归一化值超出指定的范围,则将引发OverflowError

请注意,负值的标准化一开始可能令人惊讶。例如,

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

类属性是:

请注意,由于标准化,timedelta.max> -timedelta.min-timedelta.max不能表示为timedelta对象。

实例属性(只读):

Attribute Value
days -999999999 至 999999999(含)之间
seconds 0 至 86399(含)之间
microseconds 0 至 999999(含)之间

Supported operations:

Operation Result
t1 = t2 + t3 * t2 t3 的总和。之后 t1 - t2 * == * t3 t1 - t3 * == * t2 *为真。 (1)
t1 = t2 - t3 * t2 t3 的差。之后 t1 * == * t2 - t3 t2 * == * t1 * * t3 *为真。 (1)
t1 = t2 * i or t1 = i * t2 Delta 乘以整数或 long。之后,* t1 * // i == * t2 *为 true,前提是i != 0
通常,* t1 * * i == * t1 * (i-1) t1 *为 true。 (1)
t1 = t2 // i 计算底数,其余部分(如果有)被丢弃。 (3)
+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) 返回格式为datetime.timedelta(D[, S[, U]])的字符串,其中 D 表示负数t的负数。 (5)

Notes:

>>> timedelta(hours=-5)
datetime.timedelta(-1, 68400)
>>> print(_)
-1 day, 19:00:00

除了上面列出的操作外,timedelta对象还支持对datedatetime对象进行某些加法和减法(请参见下文)。

支持timedelta对象的比较,而timedelta对象则代表较小的持续时间,该较小的持续时间被认为是较小的时间增量。为了阻止混合类型比较回退到按对象地址进行的默认比较,将timedelta对象与不同类型的对象进行比较时,除非比较是==!=,否则将引发TypeError。后一种情况分别返回FalseTrue

timedelta对象是hashable(可用作字典键),支持有效的 Pickling,并且在布尔上下文中,当且仅当timedelta不等于timedelta(0)时,才认为timedelta对象为 true。

Instance methods:

请注意,对于非常长的时间间隔(在大多数平台上大于 270 年),此方法将失去微秒的精度。

2.7 版的新Function。

Example usage:

>>> from datetime import timedelta
>>> year = timedelta(days=365)
>>> another_year = timedelta(weeks=40, days=84, hours=23,
...                          minutes=50, seconds=600)  # adds up to 365 days
>>> year.total_seconds()
31536000.0
>>> year == another_year
True
>>> ten_years = 10 * year
>>> ten_years, ten_years.days // 365
(datetime.timedelta(3650), 10)
>>> nine_years = ten_years - year
>>> nine_years, nine_years.days // 365
(datetime.timedelta(3285), 9)
>>> three_years = nine_years // 3;
>>> three_years, three_years.days // 365
(datetime.timedelta(1095), 3)
>>> abs(three_years - ten_years) == 2 * three_years + year
True

8.1.3. 日期对象

date对象代表理想 calendar 中的日期(年,月和日),当前公历 calendar 在两个方向上无限期扩展。第 1 年的 1 月 1 日称为第 1 天,第 1 年的 1 月 2 日称为第 2 天,依此类推。这与 Dershowitz 和 Reingold 的《calendar 计算》一书中“多用格里高利历”calendar 的定义相匹配,它是所有计算的基础 calendar。请参阅本书,以了解在公历和其他 calendar 系统之间进行转换的算法。

如果给出了超出这些范围的参数,则引发ValueError

其他构造函数,所有类方法:

Class attributes:

实例属性(只读):

Supported operations:

Operation Result
date2 = date1 + timedelta * date2 已从 date1 *中删除timedelta.days天。 (1)
date2 = date1 - timedelta 计算* date2 *这样的date2 + timedelta == date1。 (2)
timedelta = date1 - date2 (3)
date1 < date2 如果* date1 在时间上早于 date2 ,则 date1 被认为小于 date2 *。 (4)

Notes:

日期可以用作字典键。在布尔上下文中,所有date对象都被视为正确。

Instance methods:

ISOcalendar 是公历的一种广泛使用的变体。有关详细说明,请参见https://www.staff.science.uu.nl/~gent0113/calendar/isocalendar.htm

ISO 年度包括 52 或 53 个整周,其中一个星期从星期一开始,在星期日结束。 ISO 年的第一周是包含星期四的一年中的第一个(格里高利历)calendar 周。这称为第 1 周,该周四的 ISO 年与其公历年相同。

例如,2004 年在星期四开始,因此 ISO 2004 年的第一周从 2003 年 12 月 29 日星期一开始,到 2004 年 1 月 4 日星期日结束,因此date(2003, 12, 29).isocalendar() == (2004, 1, 1)date(2004, 1, 4).isocalendar() == (2004, 1, 7)

计算事件天数的示例:

>>> 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)
>>> 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 )
>>> d.isoformat()
'2002-03-11'
>>> d.strftime("%d/%m/%y")
'11/03/02'
>>> d.strftime("%A %d. %B %Y")
'Monday 11. March 2002'
>>> 'The {1} is {0:%d}, the {2} is {0:%B}.'.format(d, "day", "month")
'The day is 11, the month is March.'

8.1.4. 日期时间对象

datetime对象是包含来自date对象和time对象的所有信息的单个对象。像date对象一样,datetime假定当前的公历沿两个方向延伸。像时间对象一样,datetime假设每天恰好有 3600 * 24 秒。

Constructor:

如果给出了超出这些范围的参数,则引发ValueError

其他构造函数,所有类方法:

如果* tz 不是None,则它必须是tzinfo子类的实例,并且当前日期和时间将转换为 tz *的时区。在这种情况下,结果等于tz.fromutc(datetime.utcnow().replace(tzinfo=tz))。另请参见today()utcnow()

如果* tz 不是None,则它必须是tzinfo子类的实例,并且时间戳将转换为 tz *的时区。在这种情况下,结果等于tz.fromutc(datetime.utcfromtimestamp(timestamp).replace(tzinfo=tz))

如果时间戳不在平台 C localtime()gmtime()函数支持的值范围内,则fromtimestamp()可能会引发ValueError。通常将其限制在 1970 年到 2038 年之间。请注意,在非 POSIX 系统中,在时间戳概念中包含 leap 秒的情况下,fromtimestamp()会忽略 leap 秒,然后可能会有两个时间戳之间的差异第二个产生相同的datetime对象。另请参见utcfromtimestamp()

2.5 版的新Function。

Class attributes:

实例属性(只读):

Supported operations:

Operation Result
datetime2 = datetime1 + timedelta (1)
datetime2 = datetime1 - timedelta (2)
timedelta = datetime1 - datetime2 (3)
datetime1 < datetime2 比较datetimedatetime。 (4)

如果两者都很幼稚,或者两者都知道并且具有相同的tzinfo属性,则tzinfo属性将被忽略,结果是timedelta对象* t *,例如datetime2 + t == datetime1。在这种情况下,不进行时区调整。

如果两者都知道并具有不同的tzinfo属性,则a-b的行为就好像首先将* a b *转换为原始 UTC 日期时间一样。结果为(a.replace(tzinfo=None) - a.utcoffset()) - (b.replace(tzinfo=None) - b.utcoffset()),除了实现永不溢出。

如果一个比较项是幼稚的而另一个比较项知道的,则将引发TypeError。如果两个比较符都知道并且具有相同的tzinfo属性,则将忽略公共tzinfo属性,并比较基本日期时间。如果两个比较器都知道并且具有不同的tzinfo属性,则首先pass减去其 UTC 偏移量(从self.utcoffset()获得)来调整比较器。

Note

为了防止比较结果退回到默认的比较对象地址的方案,如果另一个比较符也不是datetime对象,则日期时间比较通常会提高TypeError。但是,如果另一个比较符具有timetuple()属性,则返回NotImplemented。该钩子为其他日期对象提供了实现混合类型比较的机会。如果不是,则将datetime对象与不同类型的对象进行比较时,除非比较是==!=,否则将引发TypeError。后一种情况分别返回FalseTrue

datetime对象可用作字典键。在布尔上下文中,所有datetime对象都被认为是正确的。

Instance methods:

如果self.tzinfo是* tz ,则self.astimezone(tz)等于 self :不执行日期或时间数据的调整。其他结果是时区 tz 中的本地时间,表示与 self 相同的 UTC 时间:在astz = dt.astimezone(tz)之后,astz - astz.utcoffset()通常具有与dt - dt.utcoffset()相同的日期和时间数据。 tzinfo类的讨论解释了夏令时过渡边界上无法实现的情况(仅当 tz *同时模拟标准时间和夏令时时才出现此问题)。

如果只想将时区对象* tz 附加到日期时间 dt 而不调整日期和时间数据,请使用dt.replace(tzinfo=tz)。如果您只想从已知的日期时间 dt *中删除时区对象而不转换日期和时间数据,请使用dt.replace(tzinfo=None)

请注意,可以在tzinfo子类中覆盖默认的tzinfo.fromutc()方法,以影响astimezone()返回的结果。忽略错误情况,astimezone()的行为类似于:

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

如果* d 知道,则pass减去d.utcoffset() d 标准化为 UTC 时间,并返回标准化时间的time.struct_timetm_isdst强制为 0.请注意,如果 d * .year 是MINYEARMAXYEAR并且 UTC 调整超出年份边界,则结果的tm_year成员可能是MINYEAR -1 或MAXYEAR1.

如果utcoffset()不返回None,则会附加一个 6 个字符的字符串,并以(带符号的)小时和分钟表示 UTC 偏移量:YYYY-MM-DDTHH:MM:SS.mmmmmm HH:MM;或者,如果microsecond为 0 YYYY-MM -DDTHH:MM:SS HH:MM

可选参数* sep *(默认为'T')是一个单字符分隔符,位于结果的日期和时间部分之间。例如,

>>> from datetime import tzinfo, timedelta, datetime
>>> class TZ(tzinfo):
...     def utcoffset(self, dt): return timedelta(minutes=-399)
...
>>> datetime(2002, 12, 25, tzinfo=TZ()).isoformat(' ')
'2002-12-25 00:00:00-06:39'

使用日期时间对象的示例:

>>> from datetime import datetime, date, time
>>> # 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() or datetime.utcnow()
>>> datetime.now()   
datetime.datetime(2007, 12, 6, 16, 29, 43, 79043)   # GMT +1
>>> datetime.utcnow()   
datetime.datetime(2007, 12, 6, 15, 29, 43, 79060)
>>> # 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 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 中使用 datetime:

>>> from datetime import timedelta, datetime, tzinfo
>>> class GMT1(tzinfo):
...     def utcoffset(self, dt):
...         return timedelta(hours=1) + self.dst(dt)
...     def dst(self, dt):
...         # DST starts last Sunday in March
...         d = datetime(dt.year, 4, 1)   # ends last Sunday in October
...         self.dston = d - timedelta(days=d.weekday() + 1)
...         d = datetime(dt.year, 11, 1)
...         self.dstoff = d - timedelta(days=d.weekday() + 1)
...         if self.dston <=  dt.replace(tzinfo=None) < self.dstoff:
...             return timedelta(hours=1)
...         else:
...             return timedelta(0)
...     def tzname(self,dt):
...          return "GMT +1"
...
>>> class GMT2(tzinfo):
...     def utcoffset(self, dt):
...         return timedelta(hours=2) + self.dst(dt)
...     def dst(self, dt):
...         d = datetime(dt.year, 4, 1)
...         self.dston = d - timedelta(days=d.weekday() + 1)
...         d = datetime(dt.year, 11, 1)
...         self.dstoff = d - timedelta(days=d.weekday() + 1)
...         if self.dston <=  dt.replace(tzinfo=None) < self.dstoff:
...             return timedelta(hours=1)
...         else:
...             return timedelta(0)
...     def tzname(self,dt):
...         return "GMT +2"
...
>>> gmt1 = GMT1()
>>> # Daylight Saving Time
>>> dt1 = datetime(2006, 11, 21, 16, 30, tzinfo=gmt1)
>>> dt1.dst()
datetime.timedelta(0)
>>> dt1.utcoffset()
datetime.timedelta(0, 3600)
>>> dt2 = datetime(2006, 6, 14, 13, 0, tzinfo=gmt1)
>>> dt2.dst()
datetime.timedelta(0, 3600)
>>> dt2.utcoffset()
datetime.timedelta(0, 7200)
>>> # Convert datetime to another time zone
>>> dt3 = dt2.astimezone(GMT2())
>>> dt3     
datetime.datetime(2006, 6, 14, 14, 0, tzinfo=<GMT2 object at 0x...>)
>>> dt2     
datetime.datetime(2006, 6, 14, 13, 0, tzinfo=<GMT1 object at 0x...>)
>>> dt2.utctimetuple() == dt3.utctimetuple()
True

8.1.5. 时间对象

时间对象表示一天中的(本地)时间,与任何特定的日期无关,并且可以passtzinfo对象进行调整。

如果给出了超出这些范围的参数,则引发ValueError。除* tzinfo *(默认为None)外,其他所有默认值为0

Class attributes:

实例属性(只读):

Supported operations:

Instance methods:

Example:

>>> from datetime import time, tzinfo, timedelta
>>> class GMT1(tzinfo):
...     def utcoffset(self, dt):
...         return timedelta(hours=1)
...     def dst(self, dt):
...         return timedelta(0)
...     def tzname(self,dt):
...         return "Europe/Prague"
...
>>> t = time(12, 10, 30, tzinfo=GMT1())
>>> t                               
datetime.time(12, 10, 30, tzinfo=<GMT1 object at 0x...>)
>>> gmt = GMT1()
>>> t.isoformat()
'12:10:30+01:00'
>>> t.dst()
datetime.timedelta(0)
>>> t.tzname()
'Europe/Prague'
>>> t.strftime("%H:%M:%S %Z")
'12:10:30 Europe/Prague'
>>> 'The {} is {:%H:%M}.'.format("time", t)
'The time is 12:10.'

8.1.6. tzinfo 对象

tzinfo的实例(具体子类)可以传递给datetimetime对象的构造函数。后者的对象将其属性视为本地时间,而tzinfo对象则支持显示相对于传递给它们的日期或时间对象而言,相对于 UTC 的本地时间偏移,时区名称和 DST 偏移的方法。

腌制的特殊要求:tzinfo子类必须具有init()方法,可以不带任何参数调用该方法,否则可以对其进行腌制,但可能无法再次对其进行腌制。这是一项技术要求,将来可能会放宽。

tzinfo的具体子类可能需要实现以下方法。究竟需要哪种方法取决于对已知的datetime对象的使用。如有疑问,只需实施所有这些。

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

如果utcoffset()不返回None,则dst()也不应返回None

默认实现utcoffset()引发NotImplementedError

从这个意义上讲,同时模拟标准时间和夏令时的tzinfo子类的实例* tz *必须保持一致:

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

对于带有dt.tzinfo == tz的每个datetime * 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)

or

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)

默认实现dst()引发NotImplementedError

默认实现tzname()引发NotImplementedError

响应它们的相同名称的方法,这些方法由datetimetime对象调用。 datetime对象将自身作为参数传递,而time对象将None作为参数传递。因此,应准备tzinfo子类的方法以接受None或类datetime的* dt *参数。

传递None时,由类设计者决定最佳响应。例如,如果类希望说时间对象不参与tzinfo协议,则返回None是适当的。 utcoffset(None)返回标准 UTC 偏移量可能更有用,因为没有其他约定可以发现标准偏移量。

当响应datetime对象而传递datetime对象时,dt.tzinfo与* self 是同Pair象。 tzinfo方法可以依赖于此,除非用户代码直接调用tzinfo方法。目的是tzinfo方法将 dt *解释为本地时间,而不必担心其他时区的对象。

子类可能希望重写另一个tzinfo方法:

大多数tzinfo子类应该能够继承默认的fromutc()实现,而不会出现问题。它具有足够的能力来处理固定偏移的时区,并且时区同时考虑了标准时间和夏令时,即使 DST 转换时间在不同年份有所不同,后者也是如此。默认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类:

from datetime import tzinfo, timedelta, datetime

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

# A UTC class.

class UTC(tzinfo):
    """UTC"""

    def utcoffset(self, dt):
        return ZERO

    def tzname(self, dt):
        return "UTC"

    def dst(self, dt):
        return ZERO

utc = UTC()

# A class building tzinfo objects for fixed-offset time zones.
# Note that FixedOffset(0, "UTC") is a different way to build a
# UTC tzinfo object.

class FixedOffset(tzinfo):
    """Fixed offset in minutes east from UTC."""

    def __init__(self, offset, name):
        self.__offset = timedelta(minutes = offset)
        self.__name = name

    def utcoffset(self, dt):
        return self.__offset

    def tzname(self, dt):
        return self.__name

    def dst(self, dt):
        return ZERO

# A class capturing the platform's idea of local time.

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 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
# http://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; 1am standard time) on the first Sunday of Nov.
DSTEND_2007 = datetime(1, 11, 1, 1)
# 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; 1am standard 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, 1)
# 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;
# 1am standard 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

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

        # Find start and end times for US DST. For years before 1967, return
        # ZERO for no DST.
        if 2006 < dt.year:
            dststart, dstend = DSTSTART_2007, DSTEND_2007
        elif 1986 < dt.year < 2007:
            dststart, dstend = DSTSTART_1987_2006, DSTEND_1987_2006
        elif 1966 < dt.year < 1987:
            dststart, dstend = DSTSTART_1967_1986, DSTEND_1967_1986
        else:
            return ZERO

        start = first_sunday_on_or_after(dststart.replace(year=dt.year))
        end = first_sunday_on_or_after(dstend.replace(year=dt.year))

        # Can't compare naive to aware objects, so strip the timezone from
        # dt first.
        if start <= dt.replace(tzinfo=None) < end:
            return HOUR
        else:
            return ZERO

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子类中,每年 DST 过渡点的标准时间和夏时制都有不可避免的细微之处。具体而言,请考虑美国东部(UTC -0500),EDT 在 3 月的第二个星期日的 1:59(EST)之后的分钟开始,并在 11 月的第一个星期日的 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

DST 开始时(“开始”行),本地壁钟从 1:59 跳到 3:00.格式为 2:MM 的有效时间在该天实际上没有意义,因此astimezone(Eastern)不会在 DST 开始的那一天与hour == 2传递结果。为了使astimezone()做出此保证,rzinfo.dst()方法必须考虑“缺少时间”(东部时间为 2:MM)中的时间为夏令时。

当 DST 结束(“结束”行)时,可能会出现一个更严重的问题:在当地的墙上时间,不能明确地拼写一个小时:夏令时的最后一个小时。在东部,白天的时间是 5:MM UTC。当地壁钟再次从 1:59(夏令时)跳回到 1:00(标准时间)。 1:MM 形式的当地时间是模棱两可的。 astimezone()pass将两个相邻的 UTC 小时 Map 到同一本地时间来模仿本地时钟的行为。在东部示例中,格式为 5:MM 和 6:MM 的 UTC 时间在转换为东部时都 Map 为 1:MM。为了使astimezone()做出此保证,tzinfo.dst()方法必须将“重复小时”中的时间视为标准时间。如示例中所示,可以pass在时区的标准本地时间中表示 DST 切换时间来轻松地进行安排。

不能承受此类歧义的应用程序应避免使用混合tzinfo子类。使用 UTC 或任何其他固定偏移tzinfo子类(例如仅表示 EST(固定偏移-5 小时)或仅 EDT(固定偏移-4 小时)的类)时,没有任何歧义。

See also

  • pytz

  • 标准库没有tzinfo实例,但是存在一个第三方库,它将* IANA 时区数据库*(也称为 Olson 数据库)带到 Python:* pytz *。

  • pytz *包含最新信息,建议使用。
  • IANA 时区数据库

  • 时区数据库(通常称为 tz 或 zoneinfo)包含代表 Global 许多代表性位置的本地时间历史的代码和数据。它会定期更新,以反映政治机构对时区边界,UTC 偏移量和夏令时规则所做的更改。

8.1.7. strftime()和 strptime()行为

datedatetimetime对象都支持strftime(format)方法,以在显式格式字符串的控制下创建表示时间的字符串。从广义上讲,d.strftime(fmt)的行为类似于time模块的time.strftime(fmt, d.timetuple()),尽管并非所有对象都支持timetuple()方法。

相反,datetime.strptime()类方法从表示日期和时间的字符串以及相应的格式字符串中创建datetime对象。 datetime.strptime(date_string, format)等效于datetime(*(time.strptime(date_string, format)[0:6])),但格式中包含datetime.strptime支持但被time.strptime丢弃的亚秒分量或时区偏移信息。

对于time个对象,不应使用年,月和日的格式代码,因为时间对象没有这样的值。如果仍然使用它们,则用1900代替年份,用1代替月份和日期。

对于date个对象,不应使用小时,分钟,秒和微秒的格式代码,因为date个对象没有这样的值。如果仍然使用它们,则用0代替它们。

在不同平台上,支持的全部格式代码集会有所不同,因为 Python 会调用平台 C 库的strftime()函数,并且平台版本也很常见。要查看平台所支持的全套格式代码,请查阅* strftime(3)*文档。

出于同样的原因,对包含无法在当前语言环境的字符集中表示的 Unicode 代码点的格式字符串的处理也取决于平台。在某些平台上,此类代码点会保留在输出中,而在其他平台上,strftime可能会引发UnicodeError或返回空字符串。

以下是 C 标准(1989 版)要求的所有格式代码的列表,这些格式代码在所有使用标准 C 实现的平台上都可以使用。请注意,C 标准的 1999 版本增加了其他格式代码。

strftime()工作的确切年份范围也因平台而异。无论平台如何,都无法使用 1900 年之前的年份。

Directive Meaning Example Notes
%a 工作日为语言环境的缩写名称。 周日,周一,…,周六(en_US);

因此,Mo,...,Sa(de_DE)
(1)
%A 工作日为语言环境的全名。 星期日,星期一,…,星期六(zh_CN);
桑塔格,蒙塔格,…,萨姆斯塔格(de_DE)
(1)
%w 工作日作为十进制数字,其中 0 是星期日,6 是星期六。 0,1,…,6
%d 每月的一天,以零填充的十进制数。 01、02,…,31
%b 月份为语言环境的缩写名称。 1 月,2 月,…,12 月(zh_CN);
一月,二月,…,迪斯(de_DE)
(1)
%B 月份为语言环境的全名。 1 月,2 月,…,12 月(en_US);
Januar,Februar,...,Dezember(de_DE)
(1)
%m 月份为零填充的十进制数字。 01、02,…,12
%y 无世纪的年份作为补零的十进制数字。 00,01,…,99
%Y 以世纪作为十进制数字的年份。 1970、1988、2001、2013
%H 小时(24 小时制),为零填充的十进制数字。 00、01,…,23
%I 小时(12 小时制),为零填充的十进制数字。 01、02,…,12
%p 相当于 AM 或 PM 的语言环境。 AM,PM(en_US);
上午,下午(de_DE)
(1),(2)
%M 分钟,为零填充的十进制数字。 00,01,…,59
%S 第二个为零填充的十进制数字。 00,01,…,59 (3)
%f 微秒为十进制数字,左侧为零。 000000,000001,…,999999 (4)
%z UTC 偏移量,格式为 HHMM 或-HHMM(如果对象是天真对象,则为空字符串)。 (空),0000,-0400、1030 (5)
%Z 时区名称(如果对象是天真对象,则为空字符串)。 (空),UTC,EST,CST
%j 一年中的一天,用零填充的十进制数字。 001、002,…,366
%U 一年中的周号(星期日为一周的第一天),为零填充的十进制数。第一个星期日之前的新的一年中的所有天都被认为是第 0 周。 00,01,…,53 (6)
%W 一年中的星期几(星期一为星期几),以十进制数表示。第一个星期一之前的新的一年中的所有天都视为在第 0 周。 00,01,…,53 (6)
%c 语言环境的适当日期和时间表示形式。 1988 年 8 月 16 日,星期二,21:30:00(en_US);
Di 16 Aug 21:30:00 1988(de_DE)
(1)
%x 区域设置的适当日期表示形式。 08/16/88(无);
08/16/1988 (en_US);
16.08.1988 (de_DE)
(1)
%X 语言环境的适当时间表示形式。 21:30:00(en_US);
21:30:00 (de_DE)
(1)
%% Literals'%'字符。

Notes:

2.6 版的新Function。

对于有意识的对象:

Footnotes

首页