python 有很多种方式处理日期和时间,常见的时间处理的模块是datetime、time、calendar。能融汇贯通的了解和使用这三个模块,才能轻而易举地用python处理时间。本文以此为目的,通过讲述各个时间模块的概述、函数及相关知识细节、以及相应的示例来讲透它们的使用方式。
这三个模块中,datetime(日期时间)模块主要是用来表示日期的,就是我们常说的年月日时分秒,calendar(日历)模块主要是用来表示年月日,是星期几之类的信息,time(时间)模块主要侧重点在时分秒,粗略从功能来看,我们可以认为三者是一个互补的关系,各自专注一块。方便用户依据不同的使用目的选用趁手的模块。
文章着重点在于梳理出三个模块的设计脉络,便于大家记忆里面的api。在需要的时候能够去查找相应的方法。由于文章篇幅较长,故将三个模块和示例的讲解拆分成几篇前后关联的文章,本文中重点讲解datetime模块。
一、概述
time模块是比较基础的一个模块,可满足对时间类型数据的基本处理;而 datetime模块可以看做是对time模块的一个高级封装,功能更加强大。time模块解决了时间的获取和表示,datetime模块则进一步解决了快速获取并操作时间中的年月日时分秒信息的能力。
datetime模块是这三个时间模块中使用的相对较为频繁,datetime有六个类,比较常用的有datetime、date、time、timedelta这四个,类date和类time可以看作是类datetime的子类别,虽然是分开的,但实际上这三个类的使用方法(函数)基本上是一样的,所以学精通类datetime的属性和方法,基本上可以无障碍的使用另两个类了。
需要特别注意的是,datetime模块中的类time和time模块间的区别,不要混淆它们的用法,它们其中一个只是datetime模块中的一个类别,需要用from datetime import time来进行引用,而另一个是一个独立的模块,只需要用import time。如果同时使用这两个'time',那请直接导入datetime模块和time模块,更细致的导入datetime模块中的类time会混淆两者的使用。
timedelta是datetime模块中的一个非常有用的模块,时间类型数据的计算可以通过timedelta方便快捷的实行,可以通过timedelta设置一个时间间隔,然后与指定时间进行计算,既可以获取某个时间范围内的目标,也可以计算时间间隔前后的日期时间。
有一点需要提前说明一下,time类和datetime类都有一个属性,它的值是一个tzinfo对象,里面包含了该time或者datetime的时区信息,一般称这个time或者datetime对象是aware的,它能够准确换算成自epoch开始的秒数。
如果该属性设置为None,那么,这时的time对象或者datetime对象就没有时区信息,具体它表示的是local time还是utc time,需要我们自己在程序中去决定。
这里我们所说的local time是指我们所在时区的时间, utc time指的就是国际标准时间,也就是格林尼治时间。在本文中不会涉及讲解市区和夏令时的相关操作,一切默认为localtime。
datetime对象就是date对象和time对象的组合。
# 导入datetime模块三个核心的类 from datetime import datetime # class one:datetime 日期时间 from datetime import date # class two:date 日期 from datetime import time # class three:time 时间
直接将时间的值逐个以参数的形式来创建
## 直接创建 datetime(2020,1,1,19,30,0,520) date(2020,1,1) time(19,30,0,520)
执行结果:
datetime.datetime(2020, 1, 1, 19, 30, 0, 520) datetime.date(2020, 1, 1) datetime.time(19, 30, 0, 520)
获取当前日期用today,因为日期的最小计算单位是天,当前日期就是今天;date对象只有today一种获取当前时间的方法,datetime对象却有today和now两种,结果是一致的,time对象没有获取当前时间的方法,不过可以通过datetime对象来获取。
datetime.now() # 获取当前日期时间 datetime.today() # 获取当前日期时间 date.today() # 获取当前日期
执行结果:
datetime.datetime(2019, 12, 31, 14, 26, 21, 655429) datetime.datetime(2019, 12, 31, 14, 26, 21, 658430) datetime.date(2019, 12, 31)
类date和类time可以从类datetime中分离出来,也可以通过combine方法合并成新的类datetime变量。
dt = datetime.now() # 获取当前日期时间
dt
dt.date() # 提取日期部分
dt.time() # 提取时间部分
datetime.combine(dt.date(),dt.time()) # 合并日期和时间
执行结果:
datetime.datetime(2019, 12, 31, 14, 28, 36, 804160) datetime.date(2019, 12, 31) datetime.time(14, 28, 36, 804160) datetime.datetime(2019, 12, 31, 14, 28, 36, 804160)
除了直接以参数形式创建时间和获取当前时间这两种方式之外,还有三种通过其他形式的时间格式转换的方法可以创建时间:
其中时间戳最小单位为秒,包含了日期和时间的信息;ISO日历公历序数最小单位为天,仅包含了日期的信息。这两种方法只适用于datetime对象和date对象,time对象无法使用。
fromisoformat方法三种类都可以使用,但是它有着固定的输入格式要求,如果是非标准格式的字符串,那么无法使用该方法,后面的strptime方法才可以装换非标准格式的时间。
## datetime datetime.fromtimestamp(1577777777.32452) # 时间戳转时间(以秒为单位) datetime.fromordinal(737425) # 多格勒公历序树转日期(以天为单位) datetime.fromisoformat("2020-01-01 12:00:00") # YYYY-MM-DD[*HH[:MM[:SS[.fff[fff]]]]
## date date.fromtimestamp(1577784872) # 时间戳转时间(以秒为单位) date.fromordinal(739032) # 多格勒公历序树转日期(以天为单位) date.fromisoformat("2020-01-01") # 字符转时间,仅支持格式 YYYY-MM-DD,注意01的0也要有
## time time.fromisoformat("12:45:10") # 字符转时间,仅支持格式HH:MM:DD
执行结果:
datetime.datetime(2019, 12, 31, 15, 36, 17, 324520) datetime.datetime(2020, 1, 1, 0, 0) datetime.datetime(2020, 1, 1, 12, 0) datetime.date(2019, 12, 31) datetime.date(2024, 5, 26) datetime.date(2020, 1, 1) datetime.time(12, 45, 10)
datetime每一个类里面的参数,都是可以通过获取类属性的方式单独取出来的。
dt = datetime.today()
dt
dt.year
dt.month
dt.day
dt.hour
dt.minute
dt.second
dt.microsecond
执行结果:
2019 12 31 15 22 40 354681
修改替换时间中的时间参数,适用于三种类,例如:
dt = datetime.now()
dt
dt.replace(year=2020,day=15,hour=12)
执行结果:
返回time模块中的时间元组,适用于datetime对象和date对象,不适用于time对象,例如:
dt = datetime.now()
dt.timetuple()
执行结果:
datetime.datetime(2019, 12, 31, 15, 27, 5, 882867) time.struct_time(tm_year=2019, tm_mon=12, tm_mday=31, tm_hour=15, tm_min=27, tm_sec=5, tm_wday=1, tm_yday=365, tm_isdst=-1)
返回ISO公历序数,即从公元0年1月1日起到目标日期的天数。适用于datetime对象和date对象,不适用于time,例如:
dt = datetime.now()
dt.toordinal()
d = date.today()
d.toordinal()
执行结果:
737424 737424
返回时间戳,即从公元1970年1月1日0时0分0秒起,到目标时间的秒数。仅适用于datetime对象,不适用于time对象和date对象,例如:
dt = datetime.now()
dt.timestamp()
执行结果:
1577777225.882867
返回目标日期的工作日,0代表星期一,6代表星期日,适用于datetime对象和date对象,不适用于time对象,例如:
dt = datetime.now()
dt.weekday()
d = date.today()
d.weekday()
执行结果:
1 1
返回目标日期的工作日,1代表星期一,7代表星期日,它和weekday的区别仅仅在于起始序数的不同,适用于datetime对象和date对象,不适用于time对象,例如:
dt = datetime.now()
dt.isoweekday()
d = date.today()
d.isoweekday()
执行结果:
2 2
返回一个包含目标日期的年份、在一年中的第几周、周几三个元素在内的元组,适用于datetime对象和date对象,不适用于time,例如:
dt = datetime.now()
dt.isocalendar()
d = date.today()
d.isocalendar()
执行结果:
(2020, 1, 2) (2020, 1, 2)
返回一个标准化的时间字符串,适用三种类;datetime对象使用时返回完整的字符串,日期和时间的分隔部分默认为字符“T”,可设定;date对象使用时只返回日期部分的字符串,time对象使用时只返回时间部分的字符串,例如:
dt = datetime.now()
dt.isoformat() # 默认以字符“T”分隔日期和时间 dt.isoformat(sep=" ") # 以空格“ ”分隔日期和时间 d = date.today() d.isoformat() # 日期部分 t = datetime.now().time() t.isoformat() # 时间部分
执行结果:
'2019-12-31T15:27:05.882867' '2019-12-31 15:27:05.882867' '2019-12-31' '15:27:05.882867'
返回表示日期和时间的字符串,由明确的格式字符串控制,适用三种类。
详细的字符串格式如下所示:
格式含义示例%a工作日(缩写)Sun, Mon, …, Sat%A工作日(全称)Sunday, Monday, …, Saturday%w以十进制数表示的工作日,其中0是星期日,6是星期六。0,1,…,6%d月份中的一天,十进制数字表示。01,02,…,31%b月份,缩写名称。Jan, Feb, …, Dec%B月份,全名。January, February, …, December%m月份,十进制数字01,02,…,12%y年份(无世纪的年份,后两位),十进制数字。00,01,…,99%Y年份(四位完整),十进制数字。0001,0002,…,2013,2014,…,9998,9999%H小时(24小时制),十进制数字。00,01,…,23%I小时(12小时制)01,02,…,12%pAM或PMAM, PM%M分钟,十进制数字。00,01,…,59%S秒,以零填充的十进制数。00,01,…,59%f微秒,以零填充的十进制数。000000,000001,…,999999%zUTC偏移量的格式 ±HHMM[SS[.ffffff]](empty), +0000, -0400, +1030, +063415, -030712.345216%Z时区名称(empty), UTC, EST, CST%j一年中的一天,十进制数字。001,002,…,366%U一年中的第几周(星期日为一周的第一天),以零填充的十进制数表示。以周六所在年份为基准。00,01,…,53%W一年中的第几周(星期一为一周的第一天),以零填充的十进制数表示。以周日所在年份为基准00,01,…,53%c日期和时间Tue Aug 16 21:30:00 2019%x日期12/30/19%X时间17:24:13%%文字'%'字符。%%G年份,以零填充的十进制数表示。0001,0002,…,2013,2014,…,9998,9999%u工作日,十进制数字,其中1为星期一。1,2,…,7%V一年中的第几周(星期一为一周的第一天)。第01周是包含1月4日的一周。01,02,…,53
示例:
dt = datetime.now()
d = dt.date()
t = dt.time()
dt.strftime("%Y-%m-%d") # 常用日期一
d.strftime("%Y/%m/%d") # 常用日期二
t.strftime("%H:%M") # 时分
t.strftime("%p %I:%M") # 12时制时分
dt.strftime("%Y%m%d%H%M%S%f")+str(".txt") # 文件名 print("现在是北京时间{0}年{1}月{2}日,今天是{0}年的第{3}周,是{0}年的第{4}天".format(dt.strftime("%Y"),dt.strftime("%m"),dt.strftime("%d"),dt.strftime("%U"),dt.strftime("%j")))
执行结果:
'2019-12-31' '2019/12/31' '15:27' 'PM 03:27' '20191231152705882867.txt' 现在是北京时间2019年12月31日,今天是2019年的第52周,是2019年的第365天
将字符串解析为datetime指定格式的对象,由明确的格式字符串控制,与strftime方法相对应。其内部还是先调用的time模块中的striptime方法,获取struct_time对象,再利用struct_time对象中的年月日时分秒信息构建datetime对象。
strftime 即 string format time,用来将时间格式化成字符串
strptime 即string parse time,用来将字符串解析成时间。
strptime方法只适用于datetime对象。例如:
datetime.strptime("2020-01-01 12:00:00","%Y-%m-%d %H:%M:%S")
执行结果:
datetime.datetime(2020, 1, 1, 12, 0)
以上介绍的方法中:
在日常的实际使用中,我们经常需要对日期进行比较和加减运算。得益于python的操作符重载能力,python中可以方便地对date对象之间,或者datetime对象之间进行大小比较和减法(-)操作。
需要注意的是,这里仅限于同类对象之间的比较和减法运算,而且,不包括与time模块对象的比较和运算。datetime模块中的三个类,time对象仅能与同类做比较,不能进行任何运算,而date对象和datetime对象是可以和同中类型对象做减法运算的。
示例一:
## time对象只能同类做比较 time(21,2,4) >time(20,3,2)
# output1: True
## datetime对象可以比较,也可以做运算
dt = datetime(2019, 12, 31, 15, 22, 40, 354681)
dt - datetime(2019,1,1,0,0,0)
dt > datetime(2020,1,1,0,0,0)
# output2: datetime.timedelta(days=363, seconds=62653, microseconds=913011)
# output3: False
## date对象可以比较,也可以做运算 date(2020,1,1) - date(2019,1,1) date(2020,1,1) > date(2019,12,31)
# output4: datetime.timedelta(days=365)
# output5: True
datetime模块中三种对象的比较运算对比:
类能否同类比较能否同类作运算(仅减法)能否和timedelta类进行运算datetime能能能date能能能time能不能不能
从示例中可以看到,datetime对象和date对象同类中做减法返回的结果是datetime.timedelta对象,而这个就是datetime模块中专门用于时间运算的类。个人认为,类timedelta是datetime模块中最有价值的一部分,需要重点学习一下。
timedelta对象表示持续时间,两个日期或时间之间的差,它一共有7个参数可以用来定义timedelta对象。
但不是所有参数都会保留显示,timedelta对象定义后,内部仅存储天(day),秒(seconds)和微秒(microseconds)。其余参数将按以下单位换算转换为天、秒、微秒:
相应的转换公式为:
它们之间的装换
示例:
t = timedelta(50,27,10,29000,7,8,2) # output: datetime.timedelta(days=64, seconds=29276, microseconds=10)
timedelta对象进行多种合理的时间运算,如timedelta对象间加减法,timedelta对象与数值的乘除法运算。
示例二:
## timedelta对象可以进行的运算 t = timedelta(50,27,10,29000,7,8,2) d = timedelta(5,3,234,324,35,16,0) t + d # timedelta对象间加减法 t - d t * 2.3 # timedelta对象与数值乘除法 t / 2.8
示例三:
t // 2 # timedelta对象整除,返回timedelta对象 t // d # timedelta对象间整除,返回整数 t / d # timedelta对象间相除,返回float t % d # timedelta对象间相除取余数,返回timedelta对象 divmod(t,d) # 求模
执行结果:
datetime.timedelta(days=32, seconds=14638, microseconds=5) 11 11.305345573308651 datetime.timedelta(days=1, seconds=63739, microseconds=433436)
(11, datetime.timedelta(days=1, seconds=63739, microseconds=433436))
可以用total_seconds()方法获得一个timedelta对象的秒数表示,可用于和时间戳进行运算。
timedelta.total_seconds(t) t.days * 86400 + t.seconds + t.microseconds/1000000 # output1: 5558876.00001 # output2: 5558876.00001
timedelta对象含有三个属性:days,seconds, microseconds,days属性可以取负值,另外两个属性都只能是正值。示例
t = timedelta(days=27,seconds=47283,microseconds=123942)
t
n = -t # 去t的负数 n t + n # 等于0 t.seconds + n.seconds # 秒数相加等于86399 t.microseconds + n.microseconds # 微秒相加等于1,000,000 # timedelta对象也可以使用abs()函数求绝对值 abs(n) # 返回对应正数的timedelta对象
执行结果:
datetime.timedelta(days=27, seconds=47283, microseconds=123942) datetime.timedelta(days=-28, seconds=39116, microseconds=876058) datetime.timedelta(0) 86399 1000000 datetime.timedelta(days=27, seconds=47283, microseconds=123942)
前面提到的只是timedelta对象的一些基础内容,实际使用上更多的是和date对象或者datetime对象进行计算,计算主体是date对象或者datetime对象,timedelta对象作为辅助。
示例:
# date运算 date(2020,1,1) - timedelta(days=100) date(2020,1,1) + timedelta(days=100)
# datetime运算
dt = datetime(2020,2,22,20,2,2)
dt
dt + timedelta(days=20,seconds=4023)
dt - timedelta(days=20,seconds=4023)
执行结果:
# date运算结果 datetime.date(2019, 9, 23) datetime.date(2020, 4, 10)
# datetime运算结果 datetime.datetime(2020, 2, 22, 20, 2, 2) datetime.datetime(2020, 3, 13, 21, 9, 5) datetime.datetime(2020, 2, 2, 18, 54, 59)
通过以上对datetime模块的各种对象的详细介绍,相信足以对它的各种操作有了比较完整的了解,这些都是基础的示例运用,更进一步的使用要通过实际运用中各种不一样的需求来实践。
数据分析咨询请扫描二维码
在准备数据分析师面试时,掌握高频考题及其解答是应对面试的关键。为了帮助大家轻松上岸,以下是10个高频考题及其详细解析,外加 ...
2024-12-20互联网数据分析师是一个热门且综合性的职业,他们通过数据挖掘和分析,为企业的业务决策和运营优化提供强有力的支持。尤其在如今 ...
2024-12-20在现代商业环境中,数据分析师是不可或缺的角色。他们的工作不仅仅是对数据进行深入分析,更是协助企业从复杂的数据信息中提炼出 ...
2024-12-20随着大数据时代的到来,数据驱动的决策方式开始受到越来越多企业的青睐。近年来,数据分析在人力资源管理中正在扮演着至关重要的 ...
2024-12-20在数据分析的世界里,表面上的技术操作只是“入门票”,而真正的高手则需要打破一些“看不见的墙”。这些“隐形天花板”限制了数 ...
2024-12-19在数据分析领域,尽管行业前景广阔、岗位需求旺盛,但实际的工作难度却远超很多人的想象。很多新手初入数据分析岗位时,常常被各 ...
2024-12-19入门数据分析,许多人都会感到“难”,但这“难”究竟难在哪儿?对于新手而言,往往不是技术不行,而是思维方式、业务理解和实践 ...
2024-12-19在如今的行业动荡背景下,数据分析师的职业前景虽然面临一些挑战,但也充满了许多新的机会。随着技术的不断发展和多领域需求的提 ...
2024-12-19在信息爆炸的时代,数据分析师如同探险家,在浩瀚的数据海洋中寻觅有价值的宝藏。这不仅需要技术上的过硬实力,还需要一种艺术家 ...
2024-12-19在当今信息化社会,大数据已成为各行各业不可或缺的宝贵资源。大数据专业应运而生,旨在培养具备扎实理论基础和实践能力,能够应 ...
2024-12-19阿里P8、P9失业都找不到工作?是我们孤陋寡闻还是世界真的已经“癫”成这样了? 案例一:本硕都是 985,所学的专业也是当红专业 ...
2024-12-19CDA持证人Louis CDA持证人基本情况 我大学是在一个二线城市的一所普通二本院校读的,专业是旅游管理,非计算机非统计学。毕业之 ...
2024-12-18最近,知乎上有个很火的话题:“一个人为何会陷入社会底层”? 有人说,这个世界上只有一个分水岭,就是“羊水”;还有人说,一 ...
2024-12-18在这个数据驱动的时代,数据分析师的技能需求快速增长。掌握适当的编程语言不仅能增强分析能力,还能帮助分析师从海量数据中提取 ...
2024-12-17在当今信息爆炸的时代,数据分析已经成为许多行业中不可或缺的一部分。想要在这个领域脱颖而出,除了热情和毅力外,你还需要掌握 ...
2024-12-17数据分析,是一项通过科学方法处理数据以获取洞察并支持决策的艺术。无论是在商业环境中提升业绩,还是在科研领域推动创新,数据 ...
2024-12-17在数据分析领域,图表是我们表达数据故事的重要工具。它们不仅让数据变得更加直观,也帮助我们更好地理解数据中的趋势和模式。相 ...
2024-12-16在当今社会,我们身处着一个飞速发展、变化迅猛的时代。不同行业在科技进步、市场需求和政策支持的推动下蓬勃发展,呈现出令人瞩 ...
2024-12-16在现代商业世界中,数据分析师扮演着至关重要的角色。他们通过解析海量数据,为企业战略决策提供有力支持。要有效完成这项任务, ...
2024-12-16在当今数据爆炸的时代,数据分析师是组织中不可或缺的导航者。他们通过从大量数据中提取可操作的洞察力,帮助企业在竞争激烈的市 ...
2024-12-16