# 8.1. `datetime` — 基本日期和时间类型

源代码: Lib/datetime.py

`datetime`模块提供处理日期和时间的类，既有简单的方式又有复杂的方式。虽然支持日期和时间算法，但实现的重点是为输出格式化和操作提供高效的属性提取。有关相关功能，另请参阅`time`和`calendar`模块。

有两种日期和时间对象：“naive”和“aware”。

aware 对象具有关于应用规则和时间调整的充分的信息，例如时区和夏令时信息，来定位相对其他aware 对象的位置。aware 对象用于表示时间的一个特定的时刻，它是明确无二的。 [1].

Naive对象不包含足够的信息来明确地确定其本身相对于其它日期/时间对象的偏移。一个naive对象表示的是协调世界时（UTC）、本地时间还是某些其它时区的时间，完全取决于程序，就像某个特定数字对程序是代表米、英里还是质量一样。Naive对象很容易理解和使用，代价是忽视某些现实因素。

对于需要aware对象的应用程序，`datetime`和`time`对象具有可选的时区信息属性`tzinfo`，可以设置为抽象`tzinfo`类的子类的一个实例。这些`tzinfo`对象从UTC时间，时区名称和夏令时是否生效获得偏移量信息。请注意，`datetime`模块只提供一个具体的`tzinfo`类叫`timezone`类。`timezone`类可以用与UTC固定的偏移表示简单的时区，例如UTC本身或北美EST和EDT时区。支持更深层细节的时区取决于应用程序。世界各地的时间调整规则更加具有政治色彩而不是合乎理性，且经常变化，除了UTC之外，没有适合于每个应用的标准。

`datetime`模块导出以下常量：

`datetime.``MINYEAR`

  `date`和`datetime`对象中允许的最小年份。`MINYEAR`为`1`。

`datetime.``MAXYEAR`

  `date`和`datetime`对象中允许的最大年份数。`MAXYEAR`为`9999`。

也可以看看

模块`calendar`
  日历相关的一般函数。
模块`time`
  时间访问和转化。

## 8.1.1. 可用类型

class `datetime.` `date`

  一个理想化的naive日期，假设当前的公历总是，并将永远是有效的。属性：`year`，`month`和`day`。

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`

  表示两个`date`、`time`或`datetime`实例之间相差的时间，分辨率达到微秒。

class `datetime.` `tzinfo`

  时区信息对象的抽象基类。它们由`datetime`和`time`类使用，以提供自定义时间的调整（例如，计算时区和/或夏令时）。

class `datetime.` `timezone`

  实现`tzinfo`抽象基类的类，表示与UTC的固定偏移量。

  版本3.2中的新功能。

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

`date`类型的对象总是naive的。

`time`或`datetime`类型的对象可能是naive的或aware的。如果`d.tzinfo`不为`None`且`d.tzinfo.utcoffset(d)`不返回`None`，则`datetime`对象d是aware的。如果`d.tzinfo`为`None`或者`d.tzinfo`不为`None`但是`d.tzinfo .utcoffset(d)`返回`None`，则d是naive的。如果`t.tzinfo`不为`None`且`t.tzinfo.utcoffset(None)`不返回`None`，则`time`对象t是aware的。否则，t是naive的。

Naive和aware之间的区别不适用于`timedelta`对象。

子类关系：

    object
        timedelta
        tzinfo
            timezone
        time
        date
            datetime

## 8.1.2. `timedelta`对象

`timedelta`对象表示时间的间隔，即两个日期或时间之间的差值。

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

  所有参数都是可选的且默认为`0`。参数可以是整数或浮点数，也可以是正数或负数。

  只有days（天），seconds（秒）和microseconds（微秒）存储在内部。参数被转换为这些单位：

  - 1毫秒转换为1000微秒。
  - 1分钟转换为60秒。
  - 1小时转换为3600秒。
  - 1周被转换为7天。

  然后对天，秒和微秒进行归一化，以便表示是唯一的

  - `0 <= microseconds < 1000000`
  - `0 <= seconds < 3600*24`（一天中的秒数）
  - `-999999999 <= days <= 999999999`

  如果有任何一个参数是浮点数并且有微秒数，则将所有参数剩余的小数微秒相加，并使用round-half-to-even规则将它们的和舍入到最接近的微秒。如果没有参数是浮点数，则转换和规范化过程是精确的（不会丢失任何信息）。

  如果days的归一化值超出表示的范围，则会引发`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`对象。

实例属性（只读）：

属性 | 值
--- | ---
`days` | 介于-999999999和999999999之间（包括-999999999和999999999）
`seconds` | 介于0和86399之间（包括0和86399）
`microseconds` | 介于0和999999之间（包括0和999999）

支持的操作：

操作 | 结果
--- | ---
`t1 = t2 + t3` | t2和t3的和。之后，t1-t2 == t3 and t1-t3 == t2为真。（1）
`t1 = t2 - t3` | t2和t3的差。之后t1 == t2 - t3 and t2 == t1 + t3为真。（1）
`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乘以一个浮点数。结果使用round-half-to-even舍入到timedelta.resolution最近的倍数。
`f = t2 / t3` | t2除以t3（3）。返回一个`float`对象。
`t1 = t2 / f 或 t1 = t2 / i` | Delta除以一个浮点数或整数。结果使用round-half-to-even舍入到timedelta.resolution最近的倍数。
`t1 = t2 // i`或`t1 = t2 // t3` | 计算商，余数（如果有的话）被丢弃。在第二种情况下，返回一个整数。（3）
`t1 = t2 % t3` | 计算余数，为一个`timedelta`对象。（3）
`q, r = divmod(t1, t2)` | 计算商和余数：`q = t1 // t2` (3)且`r = t1 % t2`。q一个是整数，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]`形式返回一个字符串，其中对于负`t`D为负数。(5)
`repr(t)` | 以`datetime.timedelta(D[, S[, U]])`形式返回一个字符串，其中对于负`t`D为负数。(5)

注：

1. 虽然相等，但可能会溢出。

2. 相等且不会溢出。

3. 除0引发`ZeroDivisionError`。

4. - timedelta.max不能表示成一个`timedelta`对象。

5. `timedelta`对象的字符串表示形式与其内部表示形式相似。这导致负面timedeltas有点不寻常的结果。例如：

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

除了上面列出的操作，`timedelta`对象支持与`date`和`datetime`对象相加和相减（见下文）。

在版本3.2中更改：现在支持一个`timedelta`对象和另一个`timedelta`对象的整除和真除，以及余数操作和`divmod()`函数。现在支持`timedelta`对象与`float`对象的真除和乘法。

支持`timedelta`对象的比较，表示较小时间差的`timedelta`对象被认为是较小的timedelta。为了阻止混合类型之间的比较回退到默认的以对象地址进行的比较，当将`timedelta`对象与不同类型的对象进行比较时，会引发`TypeError`除非比较是`==`或`!=`。后一种情况分别返回`False`或`True`。

`timedelta`对象是可哈希的（可用作字典键），支持高效的pickling，在布尔上下文中，`timedelta`当且仅当它不等于`timedelta(0)`时才为真。

实例方法：

`timedelta.``total_seconds`()

  返回持续时间中包含的总秒数。等同于`td / timedelta(seconds=1)`。

  请注意，对于非常大的时间间隔（在大多数平台上超过270年），此方法将失去微秒精度。

  版本3.2中的新功能。

用法示例：

    >>> 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`对象

`date`对象表示理想化日历中的日期（年、月和日），即当前公历日历在两个方向上无限延伸。第1年的1月1日被称为第1日，第1年的1月2日被称为第2日，依此类推。这与Dershowitz和Reingold的书Calendrical Calculations中的“预测格里历”日历的定义相匹配，它是所有计算的基准日历。请参阅本书，了解在格雷戈里公会和许多其他日历系统之间进行转换的算法。

class `datetime.``date`(year, month, day)

  所有参数都是必需的。参数可以是以下范围内的整数：

  - `MINYEAR <= year <= MAXYEAR`
  - `1 <= month <= 12`
  - `1 <= day <= number of days in the given month and year`

  如果给出了这些范围之外的参数，则会引发`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`。对于任何日期d，`date.fromordinal(d.toordinal()) == d`。

类属性：

`date.``min`

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

`date.``max`

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

`date.``resolution`

  不相等的日期对象之间的最小可能差异，`timedelta(days=1)`。

实例属性（只读）：

`date.``year`

  在`MINYEAR`和`MAXYEAR`之间，包括这两个值。

`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之前，则date1小于date2。（4）

注：

1. 如果`timedelta.days > 0`，则date2在时间上向前移，如果`timedelta.days < 0`，则向后移。之后，`date2 - date1 == timedelta.days`。`timedelta.seconds`和`timedelta.microseconds`被忽略。如果`date2.year`小于`MINYEAR`或大于`MAXYEAR`，则引发`OverflowError`。
2. 这不完全等同于date1 + (-timedelta)，因为-timedelta在单独的情况下可能会溢出，而date1 - timedelta不会。`timedelta.seconds`和`timedelta.microseconds`被忽略。
3. 相等且不会溢出。timedelta.seconds和timedelta.microseconds为0，并且之后date2 + timedelta == date1。
4. 换句话说，`date1 < date2`当且仅当`date1.toordinal() < date2.toordinal()`。为了停止比较回退到默认的比较对象地址的方式，如果另一比较对象不是`date`对象，日期比较通常引发`TypeError`。但是，如果另一个比较对象具有`timetuple()`属性，则会返回`NotImplemented`。这个钩子给其他种类的日期对象实现混合型比较的机会。如果不是，当将`date`对象与不同类型的对象进行比较时，则会引发`TypeError`，除非比较为`==`或`!=`。后一种情况分别返回`False`或`True`。

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

实例方法：

`date.``replace`(year, month, day)

  使用相同的值返回一个日期，除了那些由指定的关键字参数给定新值的参数。例如，如果`d == date(2002, 12, 31)`，那么`d.replace(day=26) == date(2002, 12, 26)`。

`date.``timetuple`()

  返回一个`time.struct_time`，类似`time.localtime()`的返回值。Hours、minutes和seconds为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。对于任何`date`对象d，`date.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`()

  返回3元组（ISO年，ISO周编号，ISO工作日）。

  ISO日历是公历日历的广泛使用的变体。有关详细说明，请参阅https://www.staff.science.uu.nl/~gent0113/calendar/isocalendar.htm。

  ISO年包括52或53个整周，其中一周从星期一开始并在星期日结束。ISO年的第一周是一年的第一个包含星期四的（公历）日历周。这称为周数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)`。

`date.``isoformat`()

  以ISO 8601格式返回表示日期的字符串'YYYY-MM-DD'。例如，`date(2002, 12, 4).isoformat() == '2002-12-04'`。

`date.``__str__`()

  对于日期d，`str(d)`等同于`d.isoformat()`。

`date.``ctime`()

  返回表示日期的字符串，例如`date(2002, 12, 4).ctime() == 'Wed Dec 4 00:00:00 2002'`。在原生的C函数`ctime()`（`time.ctime()`调用它，但是`date.ctime()` 不调用它）遵守C标准的平台上，`d.ctime()`等效于`time.ctime(time.mktime(d.timetuple()))`。

`date.``strftime`(format)

  返回一个表示日期的字符串，由一个明确的格式字符串控制。指代小时，分钟或秒的格式代码将会看到0个值。有关格式化指令的完整列表，请参阅strftime()和strptime()行为。

`date.``__format__`(format)

  与`date.strftime()`相同。这使得可以在使用`str.format()`时为`date`对象指定格式字符串。有关格式化指令的完整列表，请参见strftime()和strptime()的行为。

计算事件日期的示例：

    >>> 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`对象

`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)

  年，月和日的参数是必需的。tzinfo可以是`None`或`tzinfo`子类的实例。其余的参数可以是以下范围内的整数：

  - `MINYEAR <= year <= MAXYEAR`
  - `1 <= month <= 12`
  - `1 <= day <= number of days in the given month and year`
  - `0 <= hour < 24`
  - `0 <= minute < 60`
  - `0 <= second < 60`
  - `0 <= microsecond < 1000000`

  如果给出了这些范围之外的参数，则会引发`ValueError`。

其他构造函数，所有类方法：

classmethod `datetime.``today`()

  返回当前本地日期时间，其中`tzinfo`为`None`。这相当于`datetime.fromtimestamp(time.time())`。另请参见`now()`、`fromtimestamp()`。

classmethod `datetime.``now`(tz=None)

  返回当前的本地日期和时间。如果可选参数tz为`None`或未指定，则这类似于`today()`，但如果可能，通过`time.time()`时间戳提供更高的精度（例如，这在提供C `gettimeofday()`函数的平台上是可能的）。

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

classmethod `datetime.``utcnow`()

  返回当前UTC日期和时间，其中`tzinfo`为`None`。这类似`now()`，但返回当前UTC日期和时间，作为一个naive的`datetime`对象。可以通过调用`datetime.now(timezone.utc)`来得到aware的当前UTC datetime。另请参见`now()`。

classmethod `datetime.``fromtimestamp`(timestamp, tz=None)

  返回与POSIX时间戳对应的本地日期和时间，例如`time.time()`返回的时间戳。如果可选参数tz为`None`或未指定，则时间戳将转换为平台的本地日期和时间，返回的`datetime`对象是naive的。

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

  如果时间戳超出平台C `localtime()`或`gmtime()`函数支持的值的范围，则`fromtimestamp()`可能引发`OverflowError`；如果`localtime()`或`gmtime()`函数失败，则引发`OSError`。常见的做法是限制年份在1970和2038之间。请注意，在时间戳中包含闰秒的非POSIX系统上，`fromtimestamp()`会忽略闰秒，这可能使得两个相差1秒的时间戳产生相同的`datetime`对象。另请参见`utcfromtimestamp()`。

  在版本3.3中更改：如果时间戳超出平台C `localtime ()`或`gmtime()`函数支持的值范围，则引发`OverflowError`而不是`ValueError` 。在`localtime()`或`gmtime()`失败时引发`OSError`而不是`ValueError`

classmethod `datetime.``utcfromtimestamp`(timestamp)

  返回与POSIX时间戳对应的UTC `datetime`，其中`tzinfo`为`None`。如果时间戳超出平台C `gmtime()`函数支持的值的范围，则它可能引发`OverflowError`；如果`gmtime()`函数失败，则引发`OSError`。常见的做法是限制年份在1970和2038之间。

  要获取aware的`datetime`对象，请调用`fromtimestamp()`：

      datetime.fromtimestamp(timestamp, timezone.utc)

  在POSIX兼容平台上，它等效于以下表达式：

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

  但后者公式始终支持全部的年份范围：`MINYEAR`和`MAXYEAR`之间。

  在版本3.3中更改：如果时间戳超出平台C `gmtime()`函数支持的值范围，则引发`OverflowError`而不是`ValueError` 。在`gmtime()`失败时引发`OSError`而不是`ValueError`

classmethod `datetime.``fromordinal`(ordinal)

  返回对应于普通公历的序数的`datetime`，其中第1年的1月1日为序数1。如果不满足`1 <= ordinal <= datetime.max.toordinal()`，则引发`ValueError`。结果的hour、minute、second和microsecond都是0，并且`tzinfo`为`None`。

classmethod `datetime.``combine`(date, time)

  返回一个新的`datetime`对象，其日期部分等于给定的`date`对象，其时间部分和`tzinfo`属性等于给定`time`对象。对于任何`datetime`对象d，`d == datetime.combine(d.date(), d.timetz())`。如果date是一个`datetime`对象，则会忽略其时间部分和`tzinfo`属性。

classmethod `datetime.``strptime`(date_string, format)

  返回对应于date_string的`datetime`，根据format进行解析。这相当于`datetime(*(time.strptime(date_string, format)[0:6]))`如果`time.strptime()`无法解析date_string和format，或者如果返回的值不是时间元组，则会引发`ValueError`。有关格式化指令的完整列表，请参见strftime()和strptime()的行为。

类属性：

`datetime.``min`

  可表示的最早`datetime`，`datetime(MINYEAR, 1, 1, tzinfo=None)`。

`datetime.``max`

  可表示的最晚`datetime`，`datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999, tzinfo=None)`。

`datetime.``resolution`

  不相等的`datetime`对象之间的最小可能差值，`timedelta(microseconds=1)`。

实例属性（只读）：

`datetime.``year`

  在`MINYEAR`和`MAXYEAR`之间，包括这两个值。

`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`。

支持的操作：

操作 | 结果
--- | ---
`datetime2 = datetime1 + timedelta` | （1）
`datetime2 = datetime1 - timedelta` | （2）
`timedelta = datetime1 - datetime2` | （3）
`datetime1 < datetime2` | 比较`datetime`和`datetime`。（4）

1. datetime2是从datetime1移除timedelta的时间，如果`timedelta.days` > 0则向前移动，如果`timedelta.days` < 0则向后移动。结果具有与输入datetime相同的`tzinfo`属性，并且之后datetime2 - datetime1 == timedelta。如果datetime2.year小于`MINYEAR`或大于`MAXYEAR`，则会引发`OverflowError`。请注意，即使输入是aware对象，也不会执行时区调整。

2. 计算datetime2，使datetime2 + timedelta == datetime1。与加法一样，结果具有与输入日期时间相同的`tzinfo`属性，即使输入是aware的，也不执行时区调整。这不完全等同于 datetime1 + (-timedelta)，因为单独的-timedelta可能会溢出，而在此情况下datetime1 - timedelta不会。

3. 只有当两个操作数都是naive的或者两者都是aware的时，才定义从`datetime`减去一个`datetime`。如果一个是aware的而另一个是naive的，则会引发`TypeError`。

   如果两者都是naive的，或者两者都是aware的且具有相同的`tzinfo`属性，则会忽略`tzinfo`属性，结果是一个`timedelta`对象t，使得`datetime2 + t == datetime1`。在这种情况下不进行时区调整。

   如果两者都是aware的且具有不同的`tzinfo`属性，则`a-b`表现得好像a和b被首先转换成naive的UTC时间。结果是`(a.replace(tzinfo=None) - a.utcoffset()) - (b.replace(tzinfo=None) - b.utcoffset())`，除非具体的实现永远不会溢出。

4. 当datetime1在时间上位于datetime2 之前，则认为datetime1小于datetime2。

   如果一个比较数据是naive的，而另一个是aware的，则尝试进行顺序比较时会产生`TypeError`。对于相等性比较，naive实例永远不等于aware实例。

   如果两个比较数都是aware的并且具有相同的`tzinfo`属性，则忽略共同的`tzinfo`属性，并比较基本的时间数据。如果两个比较数都是aware并且具有不同的`tzinfo`属性，则首先通过减去它们的UTC偏移（从`self.utcoffset()`获得）来调整比较数。

   在版本3.3中已更改：naive的和aware的`datetime`实例之间的相等性比较不引发`TypeError`。

   注意

   为了停止比较回退到默认的比较对象地址的方式，如果另一比较对象不是`datetime`对象，datetime比较通常引发`TypeError`。但是，如果另一个比较对象具有`timetuple()`属性，则会返回`NotImplemented`。这个钩子给其他种类的日期对象实现混合型比较的机会。如果不是，当将`datetime`对象与不同类型的对象进行比较时，则会引发`TypeError`，除非比较为`==`或`!=`。后一种情况分别返回`False`或`True`。

`datetime`对象可以用作字典的键。在布尔上下文中，所有`datetime`对象都被视为真。

实例方法：

`datetime.``date`()

  返回具有相同年、月和日的`date`对象。

`datetime.``time`()

  返回具有相同小时、分钟、秒和微秒的`time`对象。`tzinfo`为`None`。另请参见方法`timetz()`。

`datetime.``timetz`()

  返回具有相同小时、分钟、秒、微秒和tzinfo属性的`time`对象。另请参见方法`time()`。

`datetime.``replace`([year[, month[, day[, hour[, minute[, second[, microsecond[, tzinfo]]]]]]]])

  使用相同的属性返回一个日期时间，除了那些通过指定任何关键字参数给出新值的属性。请注意，可以指定`tzinfo=None`来从aware的datetime创建一个naive的datetime，而不需对date和time数据进行转换。

`datetime.``astimezone`(tz=None)

  返回带有新`tzinfo`属性tz的`datetime`对象，调整日期和时间数据使结果与self 的UTC时间相同，但为tz的本地时间。

  如果提供，tz必须是`tzinfo`子类的实例，并且其`utcoffset()`和`dst()`方法不得返回`None`。self必须是aware的（`self.tzinfo`不能是`None`，以及`self.utcoffset()`不能返回`None`）。

  如果不带参数调用（或`tz=None`），则假定使用系统本地时区。转换后的datetime实例的`.tzinfo`属性将设置为`timezone`的实例，其带有从操作系统获取的时区名称和偏移量。

  如果`self.tzinfo`为tz，则`self.astimezone(tz)`等于self：日期调整和时间数据不会调整。否则结果是时区tz中的本地时间，表示与self相同的UTC时间：`astz = dt.astimezone(tz)`之后，`astz - astz.utcoffset()`通常具有与`dt - dt.utcoffset()`相同的日期和时间数据。类`tzinfo`的讨论解释了无法实现的在夏令时转换边界的情况（仅当tz同时建模标准时和夏令时的时候才出现问题）。

  如果你只想在不调整日期和时间数据的情况下将时区对象tz附加到datetimedt，请使用`dt.replace(tzinfo=tz)`。如果你只想从aware的datetime 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)

  在版本3.3中更改： tz现在可以省略。

`datetime.``utcoffset`()

  如果`tzinfo`为`None`，则返回`None`，否则返回`self.tzinfo.utcoffset(self)`；如果后者未返回`None`或表示小于一天的整数分钟的`timedelta`对象，则引发一个异常。

`datetime.``dst`()

  如果`tzinfo`为`None`，则返回`None`，否则返回`self.tzinfo.dst(self)`；如果后者未返回`None`或表示小于一天的整数分钟的`timedelta`对象，则引发一个异常。

`datetime.``tzname`()

  如果`tzinfo`为`None`，则返回`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`天。根据`dst()`方法设置结果的`tm_isdst`标志：如果`tzinfo`为`None`或`dst()`返回`None`，则`tm_isdst`设置为`-1`；如果`dst()`返回非零值，`tm_isdst`设置为`1`；否则`tm_isdst`设置为`0`。

`datetime.``utctimetuple`()

  如果`datetime`实例d是naive的，它等同于`d.timetuple()`，但是无论`d.dst()`返回什么，`tm_isdst`都被强制设置为0。对于UTC时间DST始终不会生效。

  如果d是aware的，则通过减去`d.utcoffset()`归一化d，并返回归一化的时间`time.struct_time`。`tm_isdst`被强制为0。请注意，如果d.year是`MINYEAR`或`MAXYEAR`且UTC调整溢出超过一年的边界，则可能会引发`OverflowError`。

`datetime.``toordinal`()

  返回日期的公历序数。等同于`self.date().toordinal()`。

`datetime.``timestamp`()

  返回对应于`datetime`实例的POSIX时间戳。返回值类似于`time.time()`返回的`float`。

  Naive的`datetime`实例假设表示本地时间，并且此方法依赖于平台C `mktime()`函数来执行转换。由于在许多平台上，`datetime`支持的值范围比`mktime()`的范围更广，因此此方法可能会在很远的过去或很远的未来时间引发`OverflowError`。

  对于aware的`datetime`实例，返回值计算为：

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

  版本3.3中的新功能。

  注意

  没有任何方法直接从表示UTC时间的一个naive的`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`()

  返回3元组（ISO年，ISO周编号，ISO工作日）。等同于`self.date().isocalendar()`。

`datetime.``isoformat`(sep='T')

  返回以ISO 8601 格式YYYY-MM-DDTHH:MM:SS.mmmmmm表示日期和时间的字符串，如果`microsecond`为0，则以YYYY-MM-DDTHH:MM:SS的格式。

  如果`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'

`datetime.``__str__`()

  对于`datetime`实例d，`str(d)`等效于`d.isoformat(' ')`。

`datetime.``ctime`()

  返回一个表示日期和时间的字符串，例如`datetime(2002, 12, 4, 20, 30, 40).ctime() == 'Wed Dec 4 20:30:40 2002'`。在原生的C函数`ctime()`（`time.ctime()`调用它，但是`datetime.ctime()` 不调用它）遵守C标准的平台上，`d.ctime()`等效于`time.ctime(time.mktime(d.timetuple()))`。

`datetime.``strftime`(format)

  返回一个表示日期和时间的字符串，由显式的格式字符串控制。有关格式化指令的完整列表，请参见strftime()和strptime()的行为。

`datetime.``__format__`(format)

  与`datetime.strftime()`相同。这使得可以在使用`str.format()`时为`datetime`对象指定格式字符串。有关格式化指令的完整列表，请参见strftime()和strptime()的行为。

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

    >>> 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. `time`对象

Time对象表示一天中的（本地）时间，独立于任何特定的日子，并且可以通过`tzinfo`对象进行调整。

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

  所有参数都是可选的。tzinfo可以是`None`或`tzinfo`子类的实例。其余的参数可以是以下范围内的整数：

  - `0 <= hour < 24`
  - `0 <= minute < 60`
  - `0 <= second < 60`
  - `0 <= microsecond < 1000000`.

  如果给出了这些范围之外的参数，则会引发`ValueError`。所有默认值为`0`，除了tzinfo默认为`None`。

类属性：

`time.``min`

  可表示的最早的`time`，`time(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`和`time`比较，其中如果a在时间上位于b之前，则认为a小于b。如果一个比较数据是naive的，而另一个是aware的，则尝试进行顺序比较时会产生`TypeError`。对于相等性比较，naive实例永远不等于aware实例。

  如果两个比较数都是aware的并且具有相同的`tzinfo`属性，则忽略共同的`tzinfo`属性，并比较基本的times数据。如果两个比较数都是aware并且具有不同的`tzinfo`属性，则首先通过减去它们的UTC偏移（从`self.utcoffset()`获得）来调整比较数。为了阻止混合类型之间的比较回退到默认的以对象地址进行的比较，当将`time`对象与不同类型的对象进行比较时，会引发`TypeError`除非比较是`==`或`!=`。后一种情况分别返回`False`或`True`。

  在版本3.3中已更改：naive的和aware的`time`实例之间的相等性比较不引发`TypeError`。

- 哈希，用作字典的键

- 高效的pickling

在布尔上下文中，`time`对象始终被视为真。

在3.5版本中已更改：在Python 3.5之前，如果某个`time`对象表示UTC的午夜，则将其视为假。这个行为被认为是晦涩的且容易出错的，已在Python 3.5中删除。有关详细信息，请参见issue 13936。

实例方法：

`time.``replace`([hour[, minute[, second[, microsecond[, tzinfo]]]]])

  返回具有相同值的`time`，但通过任何关键字参数指定新值的那些属性除外。请注意，可以指定`tzinfo=None`来从aware的`time`创建一个naive的`time`，而不需对time数据进行转换。

`time.``isoformat`()

  返回以ISO 8601 格式HH:MM:SS.mmmmmm表示间的字符串，如果self.microsecond为0，则以HH:MM:SS的格式。如果`utcoffset()`不返回`None`，则会附加一个6个字符的字符串，以（带符号）的小时和分钟为单位提供UTC偏移量：HH:MM:SS.mmmmmm+HH:MM，如果self.microsecond为0，则为HH:MM:SS+HH:MM。

`time.``__str__`()

  对于时间t，`str(t)`等同于`t.isoformat()`。

`time.``strftime`(format)

  返回一个表示time的字符串，由显式的格式字符串控制。有关格式化指令的完整列表，请参见strftime()和strptime()的行为。

`time.``__format__`(format)

  与`time.strftime()`相同。这使得可以在使用`str.format()`时为`time`对象指定格式字符串。有关格式化指令的完整列表，请参见strftime()和strptime()的行为。

`time.``utcoffset`()

  如果`tzinfo`为`None`，则返回`None`，否则返回`self.tzinfo.utcoffset(None)`；如果后者未返回`None`或表示小于一天的整数分钟的`timedelta`对象，则引发一个异常。

`time.``dst`()

  如果`tzinfo`为`None`，则返回`None`，否则返回`self.tzinfo.utcoffset(None)`；如果后者未返回`None`或表示小于一天的整数分钟的`timedelta`对象，则引发一个异常。

`time.``tzname`()

  如果`tzinfo`为`None`，则返回`None`，否则返回`self.tzinfo.tzname(None)`；如果后者不返回`None`或字符串对象，则引发一个异常。

例：

    >>> from datetime import time, tzinfo
    >>> 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`对象

class `datetime.``tzinfo`

  这是一个抽象的基类，意味着这个类不应该直接实例化。你需要派生一个具体的子类，并且（至少）提供你使用的`datetime`方法所需的标准`tzinfo`方法的实现。`datetime`模块提供`tzinfo`的一个简单的具体子类`timezone`，它可以表示与UTC有固定偏移的时区，如UTC本身或北美EST和EDT。

  可以将`tzinfo`（的具体子类）的实例传递给`datetime`和`time`对象的构造函数。后面的对象将它们的属性视为在本地时间，并且`tzinfo`对象支持显示本地时间与UTC的偏移量、时区的名称和DST偏移量，所有这些都相对于传递给它们的日期或时间对象。

  用于pickling的特殊要求：`tzinfo`子类必须有一个可以无参数调用的`__init__()`方法，否则它可以被pickled，但可能不能再次unpickled。这是一个在将来可能放松的技术要求。

  `tzinfo`的具体子类可能需要实现以下方法。需要哪些方法取决于对aware的`datetime`对象的使用。如果有疑问，请实施所有这些。

`tzinfo.``utcoffset`(dt)

  返回本地时间与UTC的偏移量，以UTC东部分钟数为单位。如果本地时间在UTC的西边，它应该是负的。注意，这是UTC的总偏移量；例如，如果`tzinfo`对象同时表示时区和DST调整，则`utcoffset()`应返回它们的和。如果UTC偏移未知，则返回`None`。否则返回的值必须是`timedelta`对象，指定-1439到1439范围内的整数分钟（1440 = 24*60；偏移量必须小于一天）。大多数`utcoffset()`的实现可能看起来像这两个：

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

  如果`utcoffset()`不返回`None`，则`dst()`也不应返回`None`。

  默认实现的`utcoffset()`引发`NotImplementedError`。

`tzinfo.``dst`(dt)

  如果DST信息未知，则返回夏令时（DST）调整（以UTC以东为单位），或者`None`。如果DST不起作用，则返回`timedelta(0)`。如果DST有效，则将偏移返回为`timedelta`对象（有关详细信息，请参阅`utcoffset()`）。请注意，DST偏移（如果适用）已添加到`utcoffset()`返回的UTC偏移，因此除非你感兴趣，否则不需要单独查阅`dst()`获得DST信息。例如，`datetime.timetuple()`调用其`tzinfo`属性的`dst()`方法来确定`tm_isdst`应如何设置，并且`tzinfo.fromutc()`调用`dst()`来计算跨越时区的DST更改。

  对标准时和夏令时同时进行建模的`tzinfo`子类的实例tz必须在此意义上保持一致：

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

  必须对每个`datetime` dt返回相同的结果`dt.tzinfo == tz`。对于正确的`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.  Then

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

  默认实现的`dst()`引发`NotImplementedError`。

`tzinfo.``tzname`(dt)

  将与`datetime`对象dt对应的时区名称作为字符串返回。`datetime`模块没有定义有关字符串名称的内容，并且没有要求它有任何特别的意思。例如，“GMT”、“UTC”、“-500”、“-5:00”、“EDT”、“US/Eastern”、“America/New York”都是有效的返回。如果字符串名称未知，则返回`None`。注意，这是一种方法而不是固定字符串，主要是因为一些`tzinfo`子类希望根据传递的dt的具体值返回不同的名称，特别是如果`tzinfo`类正在考虑夏令时。

  默认实现的`tzname()`引发`NotImplementedError`。

这些方法由`datetime`或`time`对象调用，以对应其相同名称的方法。`datetime`对象传递自身作为参数，`time`对象传递`None`作为参数。因此，`tzinfo`子类的方法应该准备接受一个为`None`或类`datetime`的dt参数。

当传递的是`None`时，由类设计器决定最佳响应。例如，如果类想要说time对象不参与`tzinfo`协议，则返回`None`是适当的。对于`utcoffset(None)`返回标准UTC偏移可能更有用，因为没有发现标准偏移的其他约定。

当`datetime`对象传递给`datetime`方法时，`dt.tzinfo`与self是同一个对象 。`tzinfo`方法可以依赖于此，除非用户代码直接调用`tzinfo`方法。目的是`tzinfo`方法将dt解释为在本地时间，并且不需要担心其他时区中的对象。

还有一个子类可能希望覆盖的另一个`tzinfo`方法：

`tzinfo.``fromutc`(dt)

  这是从默认的`datetime.astimezone()`实现中调用的。当从中调用时，`dt.tzinfo`为self，并且dt的日期和时间数据被视为表示UTC时间。`fromutc()`的目的是调整日期和时间数据，在self的本地时间返回等效的日期时间。

  大多数`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")

请注意，在DST转换点，在标准时和夏令时都考虑的`tzinfo`子类中，每年有两次不可避免的微妙。具体来说，考虑美国东部（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开始（“start行）时，本地挂钟从1:59走到3:00。格式2:MM的挂钟时间在当天没有任何意义，因此在DST开始的时候，`astimezone(Eastern)`不会产生结果`hour == 2`。为了使`astimezone()`作出此保证，`tzinfo.dst()`方法必须考虑在夏令时“缺少的小时”（东部时间2:MM）。

当DST结束（“end”行）时，有一个可能更糟糕的问题：有一个小时不能在本地墙上时间明确拼写：白天的最后一个小时。在东部，这是在日间时间结束时5:MM UTC形式的间。本地挂钟再次从1:59（白昼时间）回到1:00（标准时间）。表格1：MM的当地时间不明确。`astimezone()`模拟本地时钟的行为，通过将两个相邻的UTC小时映射到相同的当地小时。在Eastern这个示例中，5:MM形式和6:MM形式的UTC时间在转换到Eastern时都映射到1:MM。为了使`astimezone()`作出此保证，`tzinfo.dst()`方法必须将“重复小时”中的时间考虑为标准时间。通过在时区的标准本地时间中表示DST切换时间，这可以容易地做到，如在该示例中。

不能承受这种歧义的应用程序应避免使用混合`tzinfo`子类；使用`timezone`或任何其他固定偏移的`tzinfo`子类（例如只表示EST（固定偏移-5小时）或只表示ED（T固定偏移-4小时）的类）。

也可以看看

pytz

  标准库有`timezone`类来处理UTC任意固定偏移和`timezone.utc`作为UTC时区实例。

  pytz库将IANA时区数据库（也称为Olson数据库）带到Python，建议使用它。

IANA timezone database
  时区数据库（通常称为tz或zoneinfo）包含代表世界各地许多代表性位置的本地时间历史的代码和数据。它定期更新，以反映政治机构对时区边界、UTC偏移和夏令时规则所做的更改。

## 8.1.7. `timezone`对象

`timezone`类是`tzinfo`的子类，其每个实例表示由与UTC的固定偏移量定义的时区。请注意，此类的对象不能用于在一年中不同日期使用不同偏移量的位置，或者对民用时间进行历史更改的位置来表示时区信息。

class `datetime.``timezone`(offset[, name])

  offset参数必须指定为表示本地时间和UTC之间差异的`timedelta`对象。它必须严格在`-timedelta(hours=24)`和`timedelta(hours=24)`之间并表示整分钟数，否则引发`ValueError`。

  name参数是可选的。如果指定，它必须是用作`tzname(dt)`方法返回的值的字符串。否则，`tzname(dt)`返回字符串'UTCsHH：MM'，其中s是offset的符号，HH和MM分别是`offset.hours`和`offset.minutes`。

  版本3.2中的新功能。

`timezone.``utcoffset`(dt)

  返回构建`timezone`实例时指定的固定值。忽略dt参数。返回值是等于本地时间和UTC之差的`timedelta`实例。

`timezone.``tzname`(dt)

  返回在构建`timezone`实例时指定的固定值或字符串'UTCsHH:MM'，其中s是offset的符号，HH和MM分别是`offset.hours`和`offset.minutes`。

`timezone.``dst`(dt)

  始终返回`None`。

`timezone.``fromutc`(dt)

  返回`dt + offset`。dt参数必须是一个aware的`datetime`实例，其中`tzinfo`设置为`self`。

类属性：

`timezone.``utc`

  UTC时区，`timezone(timedelta(0))`。

## 8.1.8. `strftime()`和`strptime()`的行为

`date`、`datetime`和`time`对象都支持`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]))`。

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

对于`date`对象，不应使用小时、分钟、秒和微秒的格式代码，因为`date`对象没有此类值。如果仍然使用它们，则用`0`代替它们。

支持的全套格式代码因平台而异，因为Python调用平台C库的`strftime()`函数，平台的变化是常见的。要查看平台上支持的全套格式代码，请参阅strftime（3）文档。

以下是C标准（1989版本）要求的所有格式代码的列表，并且这些代码可以在所有平台上使用标准的C实现。请注意，1999版本的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 |
`%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 |
`%y` | 没有世纪的一年是一个零填充的十进制数。 | 00, 01, ..., 99 |
`%y` | 年份以世纪为十进制数。 | 0001, 0002, ..., 2013, 2014, ..., 9998, 9999 | （2）
`%H` | 小时（24小时制）作为零填充十进制数字。 | 00, 01, ..., 23 |
`%I` | 小时（12小时制）作为零填充的十进制数字。 | 01, 02, ..., 12 |
`%p` | Locale相当于AM或PM。 | AM, PM (en_US); am, pm (de_DE) | （1），（3）
`%m` | 分为零填充十进制数字。 | 00，01，...，59 |
`%S` | 其次作为零填充十进制数。 | 00，01，...，59 | （4）
`%f` | 微秒为十进制数字，左侧为零填充。 | 000000，000001，...，999999 | （5）
`%z` | +HHMM或-HHMM形式的UTC偏移（如果对象是naive的，则为空字符串）。 | (empty), +0000, -0400, +1030 | （6）
`%z` | 时区名称（如果对象天真，则为空字符串）。 | (empty), UTC, EST, CST |
`%j` | 一年中的一天为零填充的十进制数字。 | 001，002，...，366 |
`%U` | 一年中的星期数（星期日为一周的第一天）作为零填充十进制数。在第一个星期日之前的新的一年的所有天被认为是在第0周。 | 00，01，...，53 | （7）
`%w` | 一年中的星期数（星期一作为一周中的第一天）作为十进制数。在第一个星期一之前的新的一年中的所有天被认为是在第0周。 | 00，01，...，53 | （7）
`%c` | 语言环境的适当日期和时间表示。 | 星期二8月16日21:30:00 1988（en_US）； Di 8月16日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）
`%%` | 字面值`'％'`字符。 | % |

笔记：

1. 因为格式取决于当前的区域设置，在做出关于输出值的假设时应该小心。字段顺序将有所不同（例如，“月/日/年”和“日/月/年”），输出可能包含使用区域设置的默认编码进行编码的Unicode字符（例如，如果当前区域设置为`ja_JP`，默认编码可以是`eucJP`、`SJIS`或`utf-8`中的任何一个；使用`locale.getlocale()`以确定当前区域设置的编码）。

2. `strptime()`方法可以解析完整稍微[1,9999]范围内的年份，但 < 1000的年份必须使用0填充到4位数。

   在版本3.2中更改：在以前的版本中，`strftime()`方法仅限于>= 1900的年份。

   在版本3.3中更改：在版本3.2中，`strftime()`方法仅限于>= 1000的年份。

3. 当与`strptime()`方法一起使用时，只有在使用`%I`指令解析小时的时候，`%p`指令才会影响输出。

4. 与`time`模块不同，`datetime`模块不支持闰秒。

5. 当与`strptime()`方法一起使用时，`％f`指令接受一到六个数字，并在右边以零填充。`％f`是C标准中的一组格式字符的扩展（但是在datetime对象中单独实现，因此始终可用）。

6. 对于naive对象，`％z`和`％Z`格式代码将替换为空字符串。

   对于aware对象：

   `%z`

     `utcoffset()`被转换为+HHMM或-HHMM形式的5个字符的字符串，其中HH是给出UTC偏移小时数的2位字符串，MM是给出UTC偏移分钟数的2位字符串。例如，如果`utcoffset()`返回`timedelta(hours=-3, minutes=-30)`，那么`%z` 替换为字符串`'-0330'`。

   `%z`

     如果`tzname()`返回`None`，则以空字符串替换`％Z`。否则，`％Z`被替换为返回值，它必须是字符串。

   在版本3.2中更改：当向`strptime()`方法提供`％z`指令时，将产生aware的`datetime`对象。结果的`tzinfo`将设置为一个`timezone`实例。

7. 与`strptime()`方法一起使用时，`％U`和`％W`仅在指定星期和年份时使用。

脚注

[1] | 如果，也就是说，我们忽略相对论的影响