Python 基础 (标准库):datetime (基本日期和时间类型)

1. 官方文档

datetime --- 基本日期和时间类型 — Python 3.12.2 文档

tz — dateutil 3.9.0 documentation

2. 背景

2.1 处理时间数据的难点

计算机程序喜欢有序的、有规则的事件,但对于时间数据,其涉及的规则复杂且可能有变化,最典型例子就是夏令时和时区。理想情况下,时区边界应该精确地遵循经度线,然而由于历史和政治原因,时区线很少是直线的,有些时区的形状会很奇怪:相隔很远的区域处于同一时区,而相邻的区域处于不同的时区。夏令时的规则变化也很常见,比如,美国和加拿大在2007年前,夏令时的调整在每年的4月和10月进行,在2007年之后,改为在每年的3月和11月进行。

2.2 计算机如何保存时间数据

Unix 时间:计算机系统中广泛使用的时间标准之一,指从协调世界时(UTC)1970年1月1日0时0分0秒起至现在的总秒数(UTC 协调世界时,指的是0°经度的时间,也被称为格林尼治标准时间 GMT,UTC 没有夏令时的概念,始终保持每天24小时)。Unix时间是一个连续的整数,因此可以方便地进行时间计算和比较,且不受时区和夏令时等因素的影响。

Unix 时间对于人类来说几乎是难以理解的。Unix 时间通常被转换为 UTC,然后可以使用时区偏移量(zone offset)将其转换为本地时间。

Internet Assigned Numbers Authority (IANA) 负责维护一个包含所有时区偏移量的数据库。IANA 会定期发布更新这些信息的变化。该数据库通常包含在操作系统中,某些应用程序也可能含有更新的副本。

2.3 标准的时间记法

不同的语言和文化有不同的日期书写方式,例如,在美国,日期通常表示为:月日年,2020年1月12日通常被写成01-12-2020;在大多数欧洲和许多其他地区,日期通常表示为:日月年,2020年1月31日对应12-01-2020。

在跨文化交流时,这种差异有可能造成理解上的偏差。为了避免沟通问题,国际标准化组织(ISO)制定了 ISO 8601 标准,此标准规定所有的日期都应该按照最高到最低有效数据的顺序来写,即标准格式为年、月、日、时、分和秒。

YYYY-MM-DD HH:MM:SS

YYYY表示四位数字的年份,MM和DD表示两位数字的月和日,必要时以零开头,HH、MM和SS表示两位数的小时、分钟和秒,必要时以零开头。

2.4 程序中如何保存时间数据

你可能会想到一种直接的方法:将本地时间转换为UTC并存储该值,以供以后使用。

多数情况下,特别是在存储过去的日期时,这样做不会造成问题,因为能够获取到任何所需的信息用以进行运算。但是,如果用户在其本地时间中输入未来日期,由于时区和夏令时的规则可能发生变化,这样做可能会带来问题。

时区和夏令时的规则变化非常频繁,比如,在美国和加拿大,2007年之前的夏令时规则是:在4月的第一个星期日调快一小时,在10月的最后一个星期日调慢一小时;2007年之后的夏令时规则是:在3月的第二个星期日调快一小时,在11月的第一个星期日调慢一小时。如果用户所在位置的夏令时或时区规则在未来日期到来之前发生了变化,那么未来日期对应的 UTC 也将变化,之前保存的 UTC 将无法转换为正确的本地时间。

在这种情况下,您需要存储用户输入的本地时间(包括时区)以及用户保存时间时生效的 IANA 时区数据库的版本。

2.5 Python 标准库中关于时间的模块

Python 标准库中包含三个独立的模块来处理日期和时间:

calendar:用于创建和操作日历。它提供了许多方法来操作日期,如查找某个月份的天数、某个日期是星期几等。calendar 模块中最常用的函数是 calendar.month(),它可以输出指定月份的日历。

time:用于操作时间。它提供了许多函数以实现获取当前时间、将时间戳与日期值互相转换等功能。time 中许多函数返回一个 struct_time 实例,该对象是一个命名元组,可以通过索引或属性名访问时间信息,这一点与 datetime 实例类似,但 datetime 的功能更全面,特别是对时间值进行算术运算(arithmetic operation)的能力。

datetime:用于操作日期和时间。由于datetime 功能强大,calendar 也返回datetime类的实例。

datetime 提供了三个类:

  1. datetime.date:一个理想化的日期,它假设公历无限地延伸到未来和过去。该对象将年、月和日存储为属性。
  2. datetime.time:一个理想化的时间,假设每天有86400秒,没有闰秒。该对象存储时、分、秒、微秒和 tzinfo (时区信息)。
  3. datetime.datetime:是 datetime.date 和 datetime.time 的结合,具有这两个类的所有属性。

3. 知识点

感知型对象和简单型对象(Aware and Naive Objects)

datetime 对象可以根据是否包含时区信息分为“感知型”和“简单型”两类。

  • 感知型对象:具有政治性时间调整信息(如时区和夏令时),能够定位自身相对于其他感知型对象的精确时间点。 感知型对象是一个没有解释空间的固定时间点。对于要求感知型对象的应用程序,datetime 和 time 对象具有一个可选的时区信息属性 tzinfo,它接受抽象类 tzinfo 的子类的一个实例。 tzinfo 对象会捕获与 UTC 时间的差值、时区名称以及夏令时是否生效等信息。

感知型 datetime 实例可以明确地将自己与其他感知型 datetime 实例进行比较,并且在进行算术运算时返回正确的时间差。

  • 简单型对象:没有足够多的信息,不能定位自身相对于其他 datetime 对象的时间点。 一个简单型对象所代表的是世界标准时间(UTC)、当地时间还是某个其他时区的时间,完全取决于具体程序,就像一个特定数字所代表的是米、英里还是质量完全取决于具体程序一样。 简单型对象更易于理解和使用,代价则是忽略了某些现实性考量。
  1. date 类型的对象都是简单型的。
  2. time 或 datetime 类型的对象可以是感知型或者简单型,对于一个x,以下两个条件同时成立时,x是感知型的:(1)x.tzinfo 不为 None(2)x.tzinfo.utcoffset() 不返回 None。
  3. 感知型和简单型之间的区别不适用于 timedelta 对象。
  4. 简单型 datetime 对象会被许多 datetime 方法当作本地时间来处理,如果你有一个表示 UTC 的简单型 datetime,请使用 datetime.replace(tzinfo=timezone.utc) 将其改为感知型。

4. datetime 类

4.1 构造函数

  1. hour 为24小时制。
  2. fold 用于指示在由本地时间转换为 UTC 时间时,可能会重复出现的本地时间。这种情况通常发生在夏令时结束时,当时钟被调回一小时时,同一本地时间会出现两次。为了避免数据丢失,datetime.datetime 对象中包含了一个 fold 属性,用于表示这个重复的本地时间是第一次出现还是第二次出现。fold 可以取值 0 或 1,0 表示第一次出现,1 表示第二次出现。

4.2 类方法

方法

描述

datetime.today()

返回一个简单型datetime 对象,表示当前地方时间。

注:tzinfo 为 None。

此方法的功能等价于 now(),但是不带 tz 形参。

datetime.now(tz=None)

返回 datetime 对象,表示当前地方时间。

(1)如果可选参数 tz 为 None 或未指定,这就类似于 today();

(2)如果 tz 不为 None,它必须是 tzinfo 子类的一个实例,并且当前日期和时间将被转换到 tz 时区;

(3)使用带 UTC(tz=timezone.utc)的 datetime.now() 得到当前 UTC datetime对象。

datetime.utcnow()

返回一个简单型 datetime 对象(其中 tzinfo 为 None),表示当前 UTC。

注:不推荐使用此方法,简单型 datetime 对象会被许多 datetime 方法当作本地时间来处理,因此最好使用感知型日期时间对象来表示 UTC 时间,推荐使用 datetime.now(timezone.utc)。

datetime.combine(date, time, 

tzinfo=time.tzinfo)

返回一个新的 datetime 对象,其日期部分等于给定的 date 对象的值,而其时间部分等于给定的 time 对象的值。

(1)如果提供了 tzinfo 参数,其值会被用来设置结果的 tzinfo 属性,否则将使用 time 参数的 tzinfo 属性。

(2)如果 date 参数是一个 datetime 对象,则其时间部分和 tzinfo 属性将被忽略。

(3)对于任意 datetime 对象 d,d == datetime.combine(d.date(), d.time(), d.tzinfo)。

datetime.strptime(date_string, format)

返回一个对应于 date_string,根据 format 进行解析得到的datetime对象。

(1)如果 format 不包含微秒或时区信息,等价于:

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

(2)如果 date_string 和 format 无法被 time.strptime() 解析或它返回一个不是时间元组的值则将引发 ValueError

datetime.fromisoformat(date_string)

返回一个对应于以任何有效的 8601 格式给出的 date_string 的 datetime。

datetime.fromisocalendar(year, week, day)

返回以 year, week 和 day 值指明的 ISO 历法日期所对应的 datetime。

datetime.fromordinal(ordinal)

返回一个简单型 datetime 对象,表示格列高利历序号对应的日期。

注:结果中的 hour, minute, second 和 microsecond 值均为 0,tzinfo 值为 None。

datetime.fromtimestamp(timestamp, tz=None)

返回一个简单型 datetime 对象,表示 unix time 对应的本地日期和时间。

datetime.utcfromtimestamp(timestamp)

返回一个简单型 datetime 对象,表示 unix time 对应的 UTC。

注:tzinfo 值为 None。

4.3 实例属性

属性

描述

datetime.year

--

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

传给 datetime 构造器的 tzinfo 参数,如果没有传入值则为 None

datetime.fold

取值范围是 [0,1],用于在重复的时间段中区分时间。(当夏令时结束时回拨或由于政治原因导致当前时区的 UTC 时差减少时,就会出现重复的时间段。)

4.4 实例方法

datetime.date()

返回具有同样 year, month 和 day 值的 date 对象。

datetime.time()

返回具有同样 hour, minute, second, microsecond 和 fold 值的 time 对象,tzinfo 值为 None。

datetime.timetz()

返回具有同样 hour, minute, second, microsecond, fold 和 tzinfo 属性性的 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 来从一个感知型 datetime 创建一个简单型 datetime 而不必转换日期和时间数据。

datetime.astimezone(tz=None)

返回一个具有新的 tzinfo 属性 tz 的 datetime 对象,并会调整日期和时间数据使得结果对应的 UTC 时间与 self 相同,但为 tz 时区的本地时间。

(1)如果 self 为简单型,假定其为基于系统时区表示的时间。

(2)如果调用时不传入参数 tz (或传入 tz=None) ,将假定目标时区为系统的本地时区。 转换后 datetime 实例的 .tzinfo 属性将被设为一个 timezone 实例,时区名称和时差值将从 OS 获取。

(3)如果给出了 tz,tz 必须是一个 tzinfo 子类的实例,并且其 utcoffset() 和 dst() 方法不可返回 None。 

(4)如果只是想要附加一个时区对象 tz 到一个 datetime 对象 dt 而不调整日期和时间数据,请使用 dt.replace(tzinfo=tz)。 如果只想从一个感知型 datetime 对象 dt 中移除时区对象,请使用 dt.replace(tzinfo=None)。

datetime.utcoffset()

utcoffset 指本地时间与 UTC 的时间差,如果 tzinfo 为 None,则返回 None,否则返回 self.tzinfo.utcoffset()。

注:如果返回结果即不为 None,也不为一个幅度小于一天的 timedelta 对象,将引发异常。

datetime.dst()

dst 指夏令时,如果 tzinfo 为 None,则返回 None,否则返回 self.tzinfo.dst(self)。

注:如果返回结果即不为 None,也不为一个幅度小于一天的 timedelta 对象,将引发异常。

datetime.tzname()

tzname 指时区名称,如果 tzinfo 为 None,则返回 None,否则返回 self.tzinfo.tzname(self)。

注:如果返回结果即不为 None 也不为一个字符串,则引发异常。

datetime.weekday()

返回一个整数代表星期几,星期一为 0,星期天为 6。

注:相当于 self.date().weekday()。

datetime.isoweekday()

返回一个整数代表星期几,星期一为 1,星期天为 7。

注:相当于 self.date().isoweekday()。

datetime.strftime(format)

返回一个由显式格式字符串所控制的,代表日期和时间的字符串。 

datetime.ctime()

返回一个表示日期和时间的字符串,无论输入的是感知型还是简单型,输出字符串均不包含时区信息。

注:d.ctime() 等效于:

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

datetime.isoformat(

sep='T', timespec='auto')

返回一个以 ISO 8601 格式表示的日期和时间字符串

(1)microsecond 不为 0

YYYY-MM-DDTHH:MM:SS.ffffff

(2)microsecond 为 0

YYYY-MM-DDTHH:MM:SS

如果 utcoffset() 返回值不为 None,则添加一个字符串来给出 UTC 时差:

(1)microsecond 不为 0

YYYY-MM-DDTHH:MM:SS.ffffff+HH:MM[:SS[.ffffff]]

(2)microsecond 为 0

YYYY-MM-DDTHH:MM:SS+HH:MM[:SS[.ffffff]]

可选参数 timespec 要包含的额外时间组件值 (默认为 'auto')。它可以是以下值之一:

1. 'auto': 如果 microsecond 为 0 则与 'seconds' 相同,否则与 'microseconds' 相同。

2. 'hours': 以两个数码的 HH 格式 包含 hour。

3. 'minutes': 以 HH:MM 格式包含 hour 和 minute。

4. 'seconds': 以 HH:MM:SS 格式包含 hour, minute 和 second。

5. 'milliseconds': 包含完整时间,但将秒值的小数部分截断至毫秒。 格式为 HH:MM:SS.sss。

6. 'microseconds': 以 HH:MM:SS.ffffff 格式包含完整时间。

无效的 timespec 参数将引发 ValueError。

datetime.isocalendar()

返回一个由三部分组成的 named tuple: year, week 和 weekday。

注:相当于 self.date().isocalendar()。

datetime.toordinal()

返回  datetime 对象的日期对应的 Gregorian 日历的序数(格列高利历序号)。

注:Gregorian 日历是一种常用的日历系统,从公元 1 年 1 月 1 日开始,每一天都有一个唯一的序数。

datetime.timestamp()

返回一个浮点数,表示 datetime 对象对应的 unix time(秒表示的时间,也称 POSIX)。

(1)对于感知型 datetime 实对象,返回值的计算方式相当于:(dt - datetime(1970, 1, 1, tzinfo=timezone.utc)).total_seconds()

(2)对于表示 UTC 时间的简单型 datetime 对象(且系统时区不是 UTC),没有直接的方法能获取 unix time,不过可以使用:dt.replace(tzinfo=timezone.utc).timestamp()

datetime.timetuple()

返回 datetime 对象对应的 time.struct_time。

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 根据 dst() 方法来设定:如果 tzinfo 为 None 或 dst() 返回 None,则将 dst 设为 -1;否则,如果 dst() 返回一个非零值则将 dst 设为 1;其他情况下设为 0。

datetime.utctimetuple()

返回 datetime 对象对应的 UTC time.struct_time。

(1)对于简单型 datetime 对象,功能类似于 d.timetuple(),区别是 tm_isdst 会强制设为 0 而不管 d.dst() 返回什么结果(DST 对于 UTC 时间无效)。

(2)对于感知型 datetime 对象,先通过 d.utcoffset() 等信息将 d 标准化为 UTC 时间,然后返回该标准化时间所对应的 time.struct_time,tm_isdst 为 0。

4.4 算术运算

运算

描述

datetime2 = datetime1 + timedelta

如果 timedelta.days > 0 则在时间线上前进,如果 timedelta.days < 0 则在时间线上后退。

(1)输出结果具有与输入的 datetime 相同的 tzinfo 属性,并且操作完成后 datetime2 - datetime1 == timedelta。

(2)即使输入的是一个感知型对象,该方法也不会进行时区调整。

datetime2 = datetime1 - timedelta

如果 timedelta.days > 0 则在时间线上后退,如果 timedelta.days < 0 则在时间线上前进。

计算时间差

timedelta = datetime1 - datetime2

仅对两个操作数均为简单型或均为感知型时有定义,如果一个是感知型而另一个是简单型,将会引发 TypeError。

(1)如果两个比较数都是感知的,并且具有相同的tzinfo属性,则忽略tzinfo和fold属性,基于基本的日期时间进行计算或比较。

(2)如果两个比较数都是感知的并且具有不同的tzinfo属性,则先将比较数转换为UTC(dt.replace(tzinfo=None) - dt.utcoffset()),再进行比较。

相等性比较

datetime1 == datetime2

datetime1 != datetime2

简单型和感知型 datetime 对象绝对不会相等,datetime 对象和不为 datetime 实例的 date 对象绝对不会相等(即使二者表示相同的日期)。

注:重复间隔中的日期时间实例永远不等于其他时区中的日期时间实例。

顺序比较

datetime1 < datetime2

datetime1 > datetime2

datetime1 <= datetime2

datetime1 >= datetime2

简单型和感知型对象之间,以及 datetime 对象与非 datetime 实例的 date 对象之间的顺序比较会引发 TypeError。

 5. date 类

类属性、类方法、实例属性、实例方法与 datetime 类似,详细内容参考官方文档。

6. time 类

类属性、类方法、实例属性、实例方法与 datetime 类似,详细内容参考官方文档。

7. timedelta类

timedelta 对象表示一段持续的时间,即两个 datetime 或 date 实例之间的差值。

7.1 构造函数

1)所有参数都是可选的,且默认为 0。 这些参数可以是整数,也可以是浮点数;可以是正数也可以是负数。

2)尽管构造函数中有很多时间单位,实际上,只有 days, seconds 和 microseconds 会存储在内部:

-999999999 <= days <= 999999999

0 <= seconds < 3600*24 (一天的秒数)

0 <= microseconds < 1000000(1秒的微秒数)

3)其他时间单位(星期、分钟、小时、毫秒)会被换算为天、秒、微秒(标准化),换算规则如下:

1星期会转换成7天;

1分钟会转换成60秒;1小时会转换成3600秒;

1毫秒会转换成1000微秒。

代码1:标准化为 days, seconds 和 microseconds

只有 days, seconds 和 microseconds 会存储在内部,对 days, seconds 和 microseconds 以外的参数执行“合并”操作

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

代码2:负数值场景

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

7.2 类属性

属性

描述

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)

7.3 实例属性

属性

描述

days

取值范围:-999999999 至 999999999 ,含999999999

seconds

取值范围:0 至 86399,包含86399

microseconds

取值范围:0 至 86399,包含86399

7.4 实例方法

timedelta.total_seconds()

返回占用了多少秒。等价于 td / timedelta(seconds=1)。

对于秒以外的间隔单位,使用除法形式,如: td / timedelta(microseconds=1)。

8. tzinfo | timezone

8.1 tzinfo

tzinfo是一个抽象基类,也就是说该类不应被直接实例化。需要定义tzinfo的子类来捕获有关特定时区的信息。

tzinfo 的 (某个实体子类) 的实例可以被传给 datetime 和 time 对象的构造器。 这些对象会将它们的属性视为对应的本地时间,并且 tzinfo 对象支持展示本地时间与 UTC 的差值、时区名称以及 DST 差值的方法,都是与传给它们的日期或时间对象的相对值。

8.2 timezone

timezone 类是 tzinfo 的子类,它的实例代表一个由与 UTC 的固定时差定义的时区。

类属性:timezone.utc (表示UTC时区,等价于 timezone(timedelta(0)))

实例方法:

timezone.utcoffset(dt)

返回当 timezone 实例创建时指定的时差。

dt 参数会被忽略。

返回值是一个 timedelta 实例,其值等于本地时间与 UTC 之间的时差。

timezone.tzname(dt)

返回当 timezone 实例被构造时指定的固定值。

timezone.fromutc(dt)

返回 dt + offset。 dt 参数必须为一个感知型 datetime 实例,其中 tzinfo 值设为 self。

代码示例:

tz1 = timezone.utc
tz2 = timezone(timedelta(hours=8), name='China')dt1 = datetime.now(tz=tz1)
# datetime.datetime(2024, 3, 27, 7, 8, 9, 605318, tzinfo=datetime.timezone.utc)
dt2 = datetime.now(tz=tz2)
# datetime.datetime(2024, 3, 27, 15, 8, 9, 605318, tzinfo=datetime.timezone(datetime.timedelta(seconds=28800), 'China'))
dt3 = datetime.now()
# datetime.datetime(2024, 3, 27, 15, 8, 9, 605318)tz2.utcoffset(None)
# datetime.timedelta(seconds=28800)
tz2.tzname(None)
# 'China'
tz2.fromutc(dt2)
# datetime.datetime(2024, 3, 27, 23, 8, 9, 605318, tzinfo=datetime.timezone(datetime.timedelta(seconds=28800), 'China'))

应用1:创建 datetime 实例

1. 基于构造函数(Instantiate Class

import datetimedatetime.date(year=2024, month=3, day=7)
# datetime.date(2024, 3, 7)
datetime.time(hour=14, minute=45, second=30)
# datetime.time(14, 45, 30)
datetime.datetime(year=2024, month=3, day =7, hour=14, minute=45, second=30)
# datetime.datetime(2024, 3, 7, 14, 45, 30)

2. 无具体时间值可提供时,可基于 datetime.datetime 类方法:today()/now()/combine() 创建 datetime 实例

from datetime import date, time, datetimedatetime.today()
# datetime.datetime(2024, 3, 7, 15, 40, 8, 156908)now = datetime.now()
# datetime.datetime(2024, 3, 7, 15, 40, 8, 158902)today_date = date.today()
# datetime.date(2024, 3, 7)current_time = time(now.hour, now.minute, now.second)
# datetime.time(15, 40, 8)combined_result = datetime.combine(today_date, current_time)
# datetime.datetime(2024, 3, 7, 15, 40, 8)

3. 将时间戳(用字符串表示的时间)转换为 datetime 对象

(1)针对满足 ISO 8601 格式的字符串,可使用类方法 datetime.fromisoformat() 

datetime.fromisoformat("2020-01-31 15:30:12")
# datetime.datetime(2020, 1, 31, 15, 30, 12)

(2)针对一般格式的字符串,可使用类方法 datetime.strptime() 

from datetime import datetimedate_string = "01-10-2020 14:45:37"
format_string = "%m-%d-%Y %H:%M:%S"
datetime.strptime(date_string, format_string)
# datetime.datetime(2020, 1, 31, 14, 45, 37)

4. 基于第三方库

某些第三方库也可以创建 datetime 实例,一个典型的例子是 dateparser 库,它可以将各种日期和时间格式的字符串转换为Python datetime对象,从而使 Python 程序可以更方便地处理日期和时间。

dateparser库支持多种语言的日期和时间格式,包括英语、中文、德语、法语、西班牙语等等,它可以自动识别日期和时间字符串中的格式,并将其转换为datetime对象,此外,它还可以处理相对时间,例如“2天前”、“3周后”等等。

# pip install dateparser
import dateparserdateparser.parse('today')
# datetime.datetime(2024, 3, 7, 15, 14, 44, 597584)
dateparser.parse('yesterday')
# datetime.datetime(2024, 3, 6, 15, 14, 44, 600549)
dateparser.parse('tomorrow')
# datetime.datetime(2024, 3, 8, 15, 14, 44, 602573)dateparser.parse('morgen')  # Morgen is the German word for tomorrow
# datetime.datetime(2024, 3, 8, 15, 14, 44, 602573)
import dateparserdate_string1 = "01-10-2020 14:45:37"
date_string2 = "01 10 2020 14:45:37"dateparser.parse(date_string1)
# datetime.datetime(2020, 1, 10, 14, 45, 37)
dateparser.parse(date_string2)
# datetime.datetime(2020, 1, 10, 14, 45, 37)

应用2:设计一个倒计时程序

1. 知识点:处理时区的Python 库 dateutil

1.1 dateutil 库介绍

如果需要比较世界不同地区的时间,需要关注时区信息,即,使用感知型 datetime 实例(Aware Instance)。Python datetime 提供了 tzinfo,它是一个抽象基类,允许使用datetime.datetime,datetime.time 包含时区以及夏令时信息。但是,datetime 不提供与 IANA 时区数据库交互的直接方式,因此,在涉及时区信息的场景下,建议使用名为 dateutil 的第三方库(可以使用pip安装dateuti)。

dateuti 官方文档:tz — dateutil 3.9.0 documentation

安装:pip install python-dateutil

1.2 dateutil.tz 常用方法

tz.tzlocal()

获取当前时区,返回 datetime.tzinfo 的具体实例,含有表示 datetime 所需的所有必要的时区偏移量和夏令时信息。

tz.gettz(name=None)

传入时区的官方IANA名称,获取指定时区;如果未提供参数或者传入空字符串,返回当前时区。

IANA名称参考:https://en.wikipedia.org/wiki/List_of_tz_database_time_zones

tz.UTC

表示协调世界时(UTC)时区。

from dateutil import tz
import datetime# <tz.local>
now = datetime.datetime.now(tz=tz.tzlocal())
now           # datetime.datetime(2024, 3, 12, 9, 55, 52, 94805, tzinfo=tzlocal())
now.tzname()  # '中国标准时间'# <tz.gettz>
London_tz = tz.gettz("Europe/London")
now = datetime.datetime.now(tz=London_tz)
now           
# datetime.datetime(2024, 3, 12, 1, 55, 52, 100788, tzinfo=tzfile('Europe/Belfast'))
# Windows系统,datetime.tzinfo 属性赋值 tzfile('Europe/Belfast')
now.tzname()  
# 'GMT'
# 此输出在Windows、macOS和Linux上是相同的。# <tz.UTC>
now = datetime.datetime.now(tz=tz.UTC)
now              # datetime.datetime(2024, 3, 12, 1, 55, 52, 104777, tzinfo=tzutc())
now.ctime()      # 'Tue Mar 12 01:55:52 2024'
now.isoformat()  # '2024-03-12T01:55:52.104777+00:00'

1.3 dateutil.parser 常用方法

dateutil.parser 提供了一个通用的 date/time 字符串解析器,能够解析大多数已知格式表示的日期(和/或)时间。

dateutil.parser.parse(timestr, parserinfo=None, **kwargs)

解析时间戳(可包含时区信息),返回datetime对象。

代码示例:

from dateutil import parserDATE1 = parser.parse('2024/01/03')
DATE1  # datetime.datetime(2024, 1, 3, 0, 0)DATE2 = parser.parse('2024/01/03', parser.parserinfo(dayfirst=True))
DATE2  # datetime.datetime(2024, 3, 1, 0, 0)

参数说明:

parserinfo

说明:

1)默认情况:dayfirst 和 yearfirst 的默认值都为Flase,即默认格式为月日年,MDY。第一个数字表示月;

2)如果 yearfirst 为 True,dayfirst 保持默认值 False,对应 YMD;

3)如果 yearfirst 为 False,dayfirst 保持默认值 True,对应 DMY;

     

kwargs

此处不做展开,下图展示部分内容,更多信息请参考官方文档​​​​​​

官方文档:parser — dateutil 3.9.0 documentation

     

对于省略的日期/时间元素,应用以下规则

1)如果不指定 AM 或 PM,则假定为24小时制,但如果指定 AM 或 PM,则必须指定12小时制中的一个小时(0 <= hour <= 12),不指定会报错(datetime 对象默认使用24小时制)。

2)如果省略时区,返回简单型 datetime 对象。

3)如果缺少任何其他元素,使用 parser 的 default 参数(datetime 对象)中的对应信息,如果天数超过每月的有效天数,则该值将回落到月末。

1.4 dateutil.relativedelt

relativedelta 1)可将 datetime 中某时间元素的值替换为指定值;2)表示时间间隔。

有两种不同的方法来构建 relativedelta 实例。

1)传递两个 date/datetime 对象

2)传递以下任意数量的关键字参数

关键字参数有绝对形式和相对形式两种。单数是绝对的,复数是相对的。按顺序 Year -> Month -> Day -> Hours -> Minutes -> Seconds -> Microseconds,每个参数首先应用绝对形式(将每个属性设置为该值),然后应用相对形式(向属性加或减对应值)。最用,应用weekday。

代码示例:

from dateutil.relativedelta import relativedelta# 方法二:传参数
dt1 = datetime.now()
delta = relativedelta(day=1, days=1)
dt1
# datetime.datetime(2024, 3, 27, 11, 59, 40, 611335)
dt2 = dt1 + delta
# datetime.datetime(2024, 3, 2, 11, 59, 40, 611335)# 方法一:传入两个 datetime 实例
relativedelta(dt1, dt2)
# relativedelta(days=+25)
relativedelta(date(2000, 1, 1), date(2003, 4, 1))
# relativedelta(years=-3, months=-3)
from dateutil.relativedelta import relativedelta, FR
from datetime import dateNOW = datetime.now()
NOW
# datetime.datetime(2024, 3, 27, 12, 13, 0, 320883)NOW+relativedelta(months=+1)                      
# Next month
# datetime.datetime(2024, 4, 27, 12, 13, 0, 320883)
NOW+relativedelta(months=+1, weeks=+1)            
# Next month, plus one week.
# datetime.datetime(2024, 5, 4, 12, 13, 0, 320883)
NOW+relativedelta(months=+1, weeks=+1, hour=10) 
# Next month, plus one week, at 10am.
# datetime.datetime(2024, 5, 4, 10, 13, 0, 320883)# 本周五和上周五
NOW+relativedelta(weekday=FR)
# datetime.datetime(2024, 3, 29, 12, 13, 0, 320883)
NOW+relativedelta(weekday=FR(-1))
# datetime.datetime(2024, 3, 22, 12, 13, 0, 320883)
NOW+relativedelta(weekday=FR(+1))
# datetime.datetime(2024, 3, 29, 12, 13, 0, 320883)
date(2024,3,29)+relativedelta(weekday=FR)
# datetime.date(2024, 3, 29)
date(2024,3,29)+relativedelta(weekday=FR(+1))
# datetime.date(2024, 3, 29)
from dateutil.relativedelta import relativedelta
from datetime import date# adding one month will never cross the month boundary.
date(2001,1,27)+relativedelta(months=+1)
# datetime.date(2001, 2, 27)
date(2001,1,31)+relativedelta(months=+1)
# datetime.date(2001, 2, 28)
date(2001,1,31)+relativedelta(months=+2)
# datetime.date(2001, 3, 31)
date(2003,1,30)+relativedelta(months=+1)
# datetime.date(2003, 2, 28)
date(2003,5,31)+relativedelta(months=-1)
# datetime.date(2003, 4, 30)# The logic for years is the same, even on leap years.
date(2000,2,29)+relativedelta(years=+1)
# datetime.date(2001, 2, 28)date(2023, 1, 1)+relativedelta(yearday=260)
# datetime.date(2024, 9, 17)
date(2023, 3, 1)+relativedelta(yearday=260)
# datetime.date(2024, 9, 17)
date(2000, 1, 1)+relativedelta(yearday=260)
# datetime.date(2000, 9, 16)
date(2000, 1, 1)+relativedelta(nlyearday=260)
# datetime.date(2000, 9, 17)

2. 问题描述

巴黎奥组委2024年3月8日向外界公布,备受瞩目的奥运会开幕式将于当地时间7月26日晚7点30分开始。届时巴黎处于夏令时,与北京的时差为6小时,这意味着国内的观众将在27日凌晨1点30分欣赏到这场开启于塞纳河的奥运开幕式。

设计一个倒计时器,随时随地计算距离奥运会开幕式的时间。

3. 代码

代码版本1:计算时间差

from datetime import datetimePYCON_DATE = datetime(year=2024, month=7, day=26, hour=19, minute=30)
countdown = PYCON_DATE - datetime.now()
print(f"Countdown to 2024 Summer Olympics: {countdown}")# Countdown to 2024 Summer Olympics: 137 days, 9:37:27.209829

注:当前使用减号计算时间差,输出结果的最大单位是天。

代码版本2(优化点:添加时区信息)

from dateutil import parser, tz
import datetimeDATE = parser.parse('Jul 26, 2024 19:30:00')
DATE = DATE.replace(tzinfo=tz.gettz("Europe/Paris"))
now = datetime.datetime.now(tz=tz.tzlocal())countdown = DATE - now
print(f"Countdown to 2024 Summer Olympics: {countdown}")
# Countdown to 2024 Summer Olympics: 136 days, 13:35:18.014367

代码版本3(优化点:时间差)

from dateutil import parser, tz, relativedelta
import datetimeDATE = parser.parse('Jul 26, 2024 19:30:00')
DATE = DATE.replace(tzinfo=tz.gettz("Europe/Paris"))
now = datetime.datetime.now(tz=tz.tzlocal())countdown = relativedelta.relativedelta(DATE, now)
print(f"Countdown to 2024 Summer Olympics: {countdown}")
# Countdown to 2024 Summer Olympics: relativedelta(months=+4, days=+14, hours=+13, minutes=+13, seconds=+59, microseconds=+605048)

注:使用 dateutil.relativedelta.relativedelta,时间最小的单位是月。

代码版本4(优化点:美化输出)

from dateutil import parser, tz, relativedelta
import datetimeDATE = parser.parse('Jul 26, 2024 19:30:00')
DATE = DATE.replace(tzinfo=tz.gettz("Europe/Paris"))
now = datetime.datetime.now(tz=tz.tzlocal())def time_amount(time_unit: str, countdown: relativedelta) -> str:t = getattr(countdown, time_unit)return f"{t} {time_unit}" if t != 0 else ""countdown = relativedelta.relativedelta(DATE, now)
time_units = ["years", "months", "days", "hours", "minutes", "seconds"]
output = (t for tu in time_units if (t := time_amount(tu, countdown)))
print("Countdown to PyCon US 2021:", ", ".join(output))# Countdown to PyCon US 2021: 3 months, 29 days, 9 hours, 48 minutes, 25 seconds

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/425823.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【homebrew安装】踩坑爬坑教程

homebrew官网&#xff0c;有安装教程提示&#xff0c;但是在实际安装时&#xff0c;由于待下载的包的尺寸过大&#xff0c;本地git缓存尺寸、超时时间的限制&#xff0c;会报如下错误&#xff1a; error: RPC failed; curl 92 HTTP/2 stream 5 was not closed cleanly&#xf…

2024永久激活版 Studio One 6 Pro for mac 音乐创作编辑软件 完美兼容

Studio One 6是一款功能强大的音乐制作软件&#xff0c;由PreSonus公司开发。它提供了全面的音频录制、编辑、混音和母带处理工具&#xff0c;适用于音乐制作人、音频工程师和创作人员。 Studio One 6拥有直观的用户界面&#xff0c;使用户能够快速而流畅地进行音乐创作。它采…

华为HarmonyOS地图服务 -- 如何实现地图呈现?-- HarmonyOS自学8

如何使用地图组件MapComponent和MapComponentController呈现地图&#xff0c;效果如下图所示。 MapComponent是地图组件&#xff0c;用于在您的页面中放置地图。MapComponentController是地图组件的主要功能入口类&#xff0c;用来操作地图&#xff0c;与地图有关的所有方法从此…

基于 onsemi NCV78343 NCV78964的汽车矩阵式大灯方案

一、方案描述 大联大世平集团针对汽车矩阵大灯&#xff0c;推出 基于 onsemi NCV78343 & NCV78964的汽车矩阵式大灯方案。 开发板搭载的主要器件有 onsemi 的 Matrix Controller NCV78343、LED Driver NCV78964、Motor Driver NCV70517、以及 NXP 的 MCU S32K344。 二、开…

【我的 PWN 学习手札】Fastbin Double Free

前言 Fastbin的Double Free实际上还是利用其特性产生UAF的效果&#xff0c;使得可以进行Fastbin Attack 一、Double Free double free&#xff0c;顾名思义&#xff0c;free两次。对于fastbin这种单链表的组织结构&#xff0c;会形成这样一个效果&#xff1a; 如果我们mallo…

记一次实战中对fastjson waf的绕过

最近遇到一个fastjson的站&#xff0c;很明显是有fastjson漏洞的&#xff0c;因为type这种字符&#xff0c;fastjson特征很明显的字符都被过滤了 于是开始了绕过之旅&#xff0c;顺便来学习一下如何waf 编码绕过 去网上搜索还是有绕过waf的文章&#xff0c;下面来分析一手&a…

分布式训练:(Pytorch)

分布式训练是将机器学习模型的训练过程分散到多个计算节点或设备上&#xff0c;以提高训练速度和效率&#xff0c;尤其是在处理大规模数据和模型时。分布式训练主要分为数据并行和模型并行两种主要策略&#xff1a; 1. 数据并行 (Data Parallelism) 数据并行是最常见的分布式…

【网络安全】逻辑漏洞之购买商品

未经授权,不得转载。 文章目录 正文正文 电子商务平台的核心功能,即购买商品功能。因为在这个场景下,任何功能错误都有可能对平台产生重大影响,特别是与商品价格和数量有关的问题。 将商品添加到购物车时拦截请求: 请求包的参数: 解码参数后,并没有发现价格相关的参数,…

Python(TensorFlow和PyTorch)及C++注意力网络导图

&#x1f3af;要点 谱图神经网络计算注意力分数对比图神经网络、卷积网络和图注意力网络药物靶标建模学习和预测相互作用腹侧和背侧皮质下结构手写字体字符序列文本识别组织病理学图像分析长短期记忆财务模式预测相关性生物医学图像特征学习和迭代纠正 Python注意力机制 对…

AE VM5000 Platform VarioMatch Match Network 手侧

AE VM5000 Platform VarioMatch Match Network 手侧

算法入门-贪心1

第八部分&#xff1a;贪心 409.最长回文串&#xff08;简单&#xff09; 给定一个包含大写字母和小写字母的字符串 s &#xff0c;返回通过这些字母构造成的最长的回文串 的长度。 在构造过程中&#xff0c;请注意 区分大小写 。比如 "Aa" 不能当做一个回文字符串…

Understanding the model of openAI 5 (1024 unit LSTM reinforcement learning)

题意&#xff1a;理解 OpenAI 5&#xff08;1024 单元 LSTM 强化学习&#xff09;的模型 问题背景&#xff1a; I recently came across openAI 5. I was curious to see how their model is built and understand it. I read in wikipedia that it "contains a single l…

从0-1 用AI做一个赚钱的小红书账号(不是广告不是广告)

大家好&#xff0c;我是胡广&#xff01;是不是被标题吸引过来的呢&#xff1f;是不是觉得自己天赋异禀&#xff0c;肯定是那万中无一的赚钱天才。哈哈哈&#xff0c;我告诉你&#xff0c;你我皆是牛马&#xff0c;不要老想着突然就成功了&#xff0c;一夜暴富了&#xff0c;瞬…

【SQL】百题计划:SQL对于空值的比较判断。

[SQL]百题计划 方法&#xff1a; 使用 <> (!) 和 IS NULL [Accepted] 想法 有的人也许会非常直观地想到如下解法。 SELECT name FROM customer WHERE referee_Id <> 2;然而&#xff0c;这个查询只会返回一个结果&#xff1a;Zach&#xff0c;尽管事实上有 4 个…

React js Router 路由 2, (把写过的几个 app 组合起来)

完整的项目&#xff0c;我已经上传了&#xff0c;资源链接. 起因&#xff0c; 目的: 每次都是新建一个 react 项目&#xff0c;有点繁琐。 刚刚学了路由&#xff0c;不如写一个 大一点的 app &#xff0c;把前面写过的几个 app, 都包含进去。 这部分感觉就像是&#xff0c; …

linux网络编程——UDP编程

写在前边 本文是B站up主韦东山的4_8-3.UDP编程示例_哔哩哔哩_bilibili视频的笔记&#xff0c;其中有些部分博主也没有理解&#xff0c;希望各位辩证的看。 UDP协议简介 UDP 是一个简单的面向数据报的运输层协议&#xff0c;在网络中用于处理数据包&#xff0c;是一种无连接的…

借助大模型将文档转换为视频

利用传统手段将文档内容转换为视频&#xff0c;比如根据文档内容录制一个视频&#xff0c;不仅需要投入大量的时间和精力&#xff0c;而且往往需要具备专业的视频编辑技能。使用大模型技术可以更加有效且智能化地解决上述问题。本实践方案旨在依托大语言模型&#xff08;Large …

JDBC导图

思维歹徒 一、使用步骤 二、SQL注入 三、数据库查询&#xff08;查询&#xff09; 四、数据库写入&#xff08;增删改&#xff09; 五、Date日期对象处理 六、连接池使用 创建连接是从连接池拿&#xff0c;释放连接是放回连接池 七、事务和批次插入 八、Apache Commons DBUtil…

Village Exteriors Kit 中世纪乡村房屋场景模型

此模块化工具包就是你一直在寻找的适合建造所有中世纪幻想村庄和城市建筑所需要的工具包。 皇家园区 - 村庄外饰套件的模型和纹理插件资源包 酒馆和客栈、魔法商店、市政大厅、公会大厅、布莱克史密斯锻造厂、百货商店、珠宝商店、药店、草药师、银行、铠甲、弗莱切、马厩、桌…

这个时代唯一“不变“的又是{变}

这个时代唯一不变的就是“变”&#xff0c;所以每个人都得有规划意识&#xff0c;首先要对自己的价值有清晰的认知&#xff0c;你核心卖点是什么。第二&#xff0c;你取得的成绩是通过平台成就的还是通过自身努力取得的&#xff0c;很多人在一家平台待久了之后&#xff0c;身上…