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模块的各种对象的详细介绍,相信足以对它的各种操作有了比较完整的了解,这些都是基础的示例运用,更进一步的使用要通过实际运用中各种不一样的需求来实践。
数据分析咨询请扫描二维码
若不方便扫码,搜微信号:CDAshujufenxi
以下文章来源于数有道 ,作者数据星爷 SQL查询是数据分析工作的基础,也是CDA数据分析师一级的核心考点,人工智能时代,AI能为 ...
2025-02-19在当今这个数据驱动的时代,几乎每一个业务决策都离不开对数据的深入分析。而其中,指标波动归因分析更是至关重要的一环。无论是 ...
2025-02-18当数据开始说谎:那些年我们交过的学费 你有没有经历过这样的场景?熬了三个通宵做的数据分析报告,在会议上被老板一句"这数据靠 ...
2025-02-17数据分析作为一门跨学科领域,融合了统计学、编程、业务理解和可视化技术。无论是初学者还是有一定经验的从业者,系统化的学习路 ...
2025-02-17挖掘用户价值本质是让企业从‘赚今天的钱’升级为‘赚未来的钱’,同时让用户从‘被推销’变为‘被满足’。询问deepseek关于挖 ...
2025-02-17近来deepseek爆火,看看deepseek能否帮我们快速实现数据看板实时更新。 可以看出这对不知道怎么动手的小白来说是相当友好的, ...
2025-02-14一秒精通 Deepseek,不用找教程,不用买资料,更不用报一堆垃圾课程,所有这么去做的,都是舍近求远,因为你忽略了 deepseek 的 ...
2025-02-12自学 Python 的关键在于高效规划 + 实践驱动。以下是一份适合零基础快速入门的自学路径,结合资源推荐和实用技巧: 一、快速入 ...
2025-02-12“我们的利润率上升了,但销售额却没变,这是为什么?” “某个业务的市场份额在下滑,到底是什么原因?” “公司整体业绩 ...
2025-02-08活动介绍 为了助力大家在数据分析领域不断精进技能,我们特别举办本期打卡活动。在这里,你可以充分利用碎片化时间在线学习,让 ...
2025-02-071、闺女,醒醒,媒人把相亲的带来了。 我。。。。。。。 2、前年春节相亲相了40个, 去年春节相亲50个, 祖宗,今年你想相多少个 ...
2025-02-06在数据科学的广阔领域中,统计分析与数据挖掘占据了重要位置。尽管它们常常被视为有关联的领域,但两者在理论基础、目标、方法及 ...
2025-02-05在数据分析的世界里,“对比”是一种简单且有效的方法。这就像两个女孩子穿同一款式的衣服,效果不一样。 很多人都听过“货比三 ...
2025-02-05当我们只有非常少量的已标记数据,同时有大量未标记数据点时,可以使用半监督学习算法来处理。在sklearn中,基于图算法的半监督 ...
2025-02-05考虑一种棘手的情况:训练数据中大部分样本没有标签。此时,我们可以考虑使用半监督学习方法来处理。半监督学习能够利用这些额 ...
2025-02-04一、数学函数 1、取整 =INT(数字) 2、求余数 =MOD(除数,被除数) 3、四舍五入 =ROUND(数字,保留小数位数) 4、取绝对值 =AB ...
2025-02-03作者:CDA持证人 余治国 一般各平台出薪资报告,都会哀嚎遍野。举个例子,去年某招聘平台发布《中国女性职场现状调查报告》, ...
2025-02-02真正的数据分析大神是什么样的呢?有人认为他们能轻松驾驭各种分析工具,能够从海量数据中找到潜在关联,或者一眼识别报告中的数 ...
2025-02-01现今社会,“转行”似乎成无数职场人无法回避的话题。但行业就像座围城:外行人看光鲜,内行人看心酸。数据分析这个行业,近几年 ...
2025-01-31本人基本情况: 学校及专业:厦门大学经济学院应用统计 实习经历:快手数据分析、字节数据分析、百度数据分析 Offer情况:北京 ...
2025-01-30