找回密码
 会员注册
查看: 31|回复: 0

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

[复制链接]

2

主题

0

回帖

7

积分

新手上路

积分
7
发表于 2024-9-7 00:53:14 | 显示全部楼层 |阅读模式
1.官方文档datetime---基本日期和时间类型—Python3.12.2文档tz—dateutil3.9.0documentation2.背景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,然后可以使用时区偏移量(zoneoffset)将其转换为本地时间。InternetAssignedNumbersAuthority(IANA)负责维护一个包含所有时区偏移量的数据库。IANA会定期发布更新这些信息的变化。该数据库通常包含在操作系统中,某些应用程序也可能含有更新的副本。2.3标准的时间记法不同的语言和文化有不同的日期书写方式,例如,在美国,日期通常表示为:月日年,2020年1月12日通常被写成01-12-2020;在大多数欧洲和许多其他地区,日期通常表示为:日月年,2020年1月31日对应12-01-2020。在跨文化交流时,这种差异有可能造成理解上的偏差。为了避免沟通问题,国际标准化组织(ISO)制定了ISO8601标准,此标准规定所有的日期都应该按照最高到最低有效数据的顺序来写,即标准格式为年、月、日、时、分和秒。YYYY-MM-DDHH:MM:SSYYYY表示四位数字的年份,MM和DD表示两位数字的月和日,必要时以零开头,HH、MM和SS表示两位数的小时、分钟和秒,必要时以零开头。2.4程序中如何保存时间数据你可能会想到一种直接的方法:将本地时间转换为UTC并存储该值,以供以后使用。多数情况下,特别是在存储过去的日期时,这样做不会造成问题,因为能够获取到任何所需的信息用以进行运算。但是,如果用户在其本地时间中输入未来日期,由于时区和夏令时的规则可能发生变化,这样做可能会带来问题。时区和夏令时的规则变化非常频繁,比如,在美国和加拿大,2007年之前的夏令时规则是:在4月的第一个星期日调快一小时,在10月的最后一个星期日调慢一小时;2007年之后的夏令时规则是:在3月的第二个星期日调快一小时,在11月的第一个星期日调慢一小时。如果用户所在位置的夏令时或时区规则在未来日期到来之前发生了变化,那么未来日期对应的UTC也将变化,之前保存的UTC将无法转换为正确的本地时间。在这种情况下,您需要存储用户输入的本地时间(包括时区)以及用户保存时间时生效的IANA时区数据库的版本。2.5Python标准库中关于时间的模块Python标准库中包含三个独立的模块来处理日期和时间:calendar:用于创建和操作日历。它提供了许多方法来操作日期,如查找某个月份的天数、某个日期是星期几等。calendar模块中最常用的函数是calendar.month(),它可以输出指定月份的日历。time:用于操作时间。它提供了许多函数以实现获取当前时间、将时间戳与日期值互相转换等功能。time中许多函数返回一个struct_time实例,该对象是一个命名元组,可以通过索引或属性名访问时间信息,这一点与datetime实例类似,但datetime的功能更全面,特别是对时间值进行算术运算(arithmeticoperation)的能力。datetime:用于操作日期和时间。由于datetime功能强大,calendar也返回datetime类的实例。datetime提供了三个类:datetime.date:一个理想化的日期,它假设公历无限地延伸到未来和过去。该对象将年、月和日存储为属性。datetime.time:一个理想化的时间,假设每天有86400秒,没有闰秒。该对象存储时、分、秒、微秒和tzinfo(时区信息)。datetime.datetime:是datetime.date和datetime.time的结合,具有这两个类的所有属性。3.知识点感知型对象和简单型对象(AwareandNaiveObjects)datetime对象可以根据是否包含时区信息分为“感知型”和“简单型”两类。感知型对象:具有政治性时间调整信息(如时区和夏令时),能够定位自身相对于其他感知型对象的精确时间点。感知型对象是一个没有解释空间的固定时间点。对于要求感知型对象的应用程序,datetime 和 time 对象具有一个可选的时区信息属性tzinfo,它接受抽象类 tzinfo 的子类的一个实例。tzinfo 对象会捕获与UTC时间的差值、时区名称以及夏令时是否生效等信息。感知型datetime实例可以明确地将自己与其他感知型datetime实例进行比较,并且在进行算术运算时返回正确的时间差。简单型对象:没有足够多的信息,不能定位自身相对于其他datetime对象的时间点。一个简单型对象所代表的是世界标准时间(UTC)、当地时间还是某个其他时区的时间,完全取决于具体程序,就像一个特定数字所代表的是米、英里还是质量完全取决于具体程序一样。简单型对象更易于理解和使用,代价则是忽略了某些现实性考量。date 类型的对象都是简单型的。time 或 datetime 类型的对象可以是感知型或者简单型,对于一个x,以下两个条件同时成立时,x是感知型的:(1)x.tzinfo 不为 None(2)x.tzinfo.utcoffset() 不返回 None。感知型和简单型之间的区别不适用于timedelta对象。简单型 datetime 对象会被许多 datetime 方法当作本地时间来处理,如果你有一个表示UTC的简单型datetime,请使用datetime.replace(tzinfo=timezone.utc)将其改为感知型。4.datetime类4.1构造函数hour为24小时制。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()得到当前UTCdatetime对象。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() 解析或它返回一个不是时间元组的值则将引发 ValueErrordatetime.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对象,表示unixtime对应的本地日期和时间。datetime.utcfromtimestamp(timestamp)返回一个简单型datetime对象,表示unixtime对应的UTC。注:tzinfo值为None。4.3实例属性属性描述datetime.year--datetime.month1至12(含)datetime.day1到指定年月的天数间的数字。datetime.hourrange(24)datetime.minuterange(60)。datetime.secondrange(60)。datetime.microsecondrange(1000000)datetime.tzinfo传给datetime构造器的tzinfo 参数,如果没有传入值则为Nonedatetime.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')返回一个以ISO8601格式表示的日期和时间字符串(1)microsecond不为0YYYY-MM-DDTHH:MM:SS.ffffff,(2)microsecond为0YYYY-MM-DDTHH:MM:SS如果utcoffset()返回值不为None,则添加一个字符串来给出UTC时差:(1)microsecond不为0YYYY-MM-DDTHH:MM:SS.ffffff+HH:MM[:SS[.ffffff]](2)microsecond为0YYYY-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()返回一个由三部分组成的namedtuple:year,week和weekday。注:相当于self.date().isocalendar()。datetime.toordinal()返回 datetime对象的日期对应的Gregorian日历的序数(格列高利历序号)。注:Gregorian日历是一种常用的日历系统,从公元1年1月1日开始,每一天都有一个唯一的序数。datetime.timestamp()返回一个浮点数,表示 datetime对象对应的unixtime(秒表示的时间,也称POSIX)。(1)对于感知型datetime实对象,返回值的计算方式相当于:(dt-datetime(1970,1,1,tzinfo=timezone.utc)).total_seconds()(2)对于表示UTC时间的简单型datetime对象(且系统时区不是UTC),没有直接的方法能获取unixtime,不过可以使用: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.days0则在时间线上后退,如果timedelta.days datetime2datetime1 = 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 now=datetime.datetime.now(tz=tz.tzlocal())now#datetime.datetime(2024,3,12,9,55,52,94805,tzinfo=tzlocal())now.tzname()#'中国标准时间'#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上是相同的。#now=datetime.datetime.now(tz=tz.UTC)now#datetime.datetime(2024,3,12,1,55,52,104777,tzinfo=tzutc())now.ctime()#'TueMar1201:55:522024'now.isoformat()#'2024-03-12T01:55:52.104777+00:00''运行运行1.3dateutil.parser常用方法dateutil.parser提供了一个通用的date/time字符串解析器,能够解析大多数已知格式表示的日期(和/或)时间。dateutil.parser.parse(timestr,parserinfo=None,**kwargs)解析时间戳(可包含时区信息),返回datetime对象。代码示例:fromdateutilimportparserDATE1=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—dateutil3.9.0documentation   对于省略的日期/时间元素,应用以下规则1)如果不指定AM或PM,则假定为24小时制,但如果指定AM或PM,则必须指定12小时制中的一个小时(0Month->Day->Hours->Minutes->Seconds->Microseconds,每个参数首先应用绝对形式(将每个属性设置为该值),然后应用相对形式(向属性加或减对应值)。最用,应用weekday。代码示例:fromdateutil.relativedeltaimportrelativedelta#方法二:传参数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)fromdateutil.relativedeltaimportrelativedelta,FRfromdatetimeimportdateNOW=datetime.now()NOW#datetime.datetime(2024,3,27,12,13,0,320883)NOW+relativedelta(months=+1)#Nextmonth#datetime.datetime(2024,4,27,12,13,0,320883)NOW+relativedelta(months=+1,weeks=+1)#Nextmonth,plusoneweek.#datetime.datetime(2024,5,4,12,13,0,320883)NOW+relativedelta(months=+1,weeks=+1,hour=10)#Nextmonth,plusoneweek,at10am.#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)fromdateutil.relativedeltaimportrelativedeltafromdatetimeimportdate#addingonemonthwillnevercrossthemonthboundary.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)#Thelogicforyearsisthesame,evenonleapyears.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:计算时间差fromdatetimeimportdatetimePYCON_DATE=datetime(year=2024,month=7,day=26,hour=19,minute=30)countdown=PYCON_DATE-datetime.now()print(f"Countdownto2024SummerOlympics:{countdown}")#Countdownto2024SummerOlympics:137days,9:37:27.209829'运行运行注:当前使用减号计算时间差,输出结果的最大单位是天。代码版本2(优化点:添加时区信息)fromdateutilimportparser,tzimportdatetimeDATE=parser.parse('Jul26,202419:30:00')DATE=DATE.replace(tzinfo=tz.gettz("Europe/Paris"))now=datetime.datetime.now(tz=tz.tzlocal())countdown=DATE-nowprint(f"Countdownto2024SummerOlympics:{countdown}")#Countdownto2024SummerOlympics:136days,13:35:18.014367'运行运行代码版本3(优化点:时间差)fromdateutilimportparser,tz,relativedeltaimportdatetimeDATE=parser.parse('Jul26,202419:30:00')DATE=DATE.replace(tzinfo=tz.gettz("Europe/Paris"))now=datetime.datetime.now(tz=tz.tzlocal())countdown=relativedelta.relativedelta(DATE,now)print(f"Countdownto2024SummerOlympics:{countdown}")#Countdownto2024SummerOlympics:relativedelta(months=+4,days=+14,hours=+13,minutes=+13,seconds=+59,microseconds=+605048)'运行运行注:使用dateutil.relativedelta.relativedelta,时间最小的单位是月。代码版本4(优化点:美化输出)fromdateutilimportparser,tz,relativedeltaimportdatetimeDATE=parser.parse('Jul26,202419:30:00')DATE=DATE.replace(tzinfo=tz.gettz("Europe/Paris"))now=datetime.datetime.now(tz=tz.tzlocal())deftime_amount(time_unit:str,countdown:relativedelta)->str:t=getattr(countdown,time_unit)returnf"{t}{time_unit}"ift!=0else""countdown=relativedelta.relativedelta(DATE,now)time_units=["years","months","days","hours","minutes","seconds"]output=(tfortuintime_unitsif(t:=time_amount(tu,countdown)))print("CountdowntoPyConUS2021:",",".join(output))#CountdowntoPyConUS2021:3months,29days,9hours,48minutes,25seconds'运行运行
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 会员注册

本版积分规则

QQ|手机版|心飞设计-版权所有:微度网络信息技术服务中心 ( 鲁ICP备17032091号-12 )|网站地图

GMT+8, 2025-1-10 19:14 , Processed in 1.280837 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表