python中有两个和时间相关的模块time和datetime,我自己在使用的时候经常搞混。这一篇就来记录下这两个模块常见的一些功能。
time模块和datetime模块
time是python的内建模块,用与和时间相关的一些操作;datetime模块是第三方模块,为了方便操作,将和date与time相关的一些操作进行了封装。
所以本质上来讲,能用datetime来操作的都能用time来实现,通过后面的对比就能看到datetime模块确实方便很多。
时间的表示
首先要明确,python使用一个9元素的元组来表示时间,如下
元素
含义
取值范围
tm_year
年
1970-2038
tm_mon
月
1-12
tm_mday
日
1-31
tm_hour
小时
0-23
tm_min
分钟
0-59
tm_sec
秒
0-60(60或61 是闰秒)
tm_wday
周几
0-6(0为周一)
tm_yday
一年的第几天
1-366(儒略历)
tm_isdst
夏令时标记位
-1,0,1
将这9个数组成的元组传递到
time.struct_time
类中,就构成了python中的时间对象,也就是一个struct_time对象。
个性化这9个数就构成了代表不同时间的struct_time对象,同时还可以将struct_time对象与字符串按照特定格式去相互转换,或者转为时间戳。
通过修改初始化参数去操作时间还是很不方便的,例如计算类似获取7天后的时间或者5小时前的时间这种偏移类的计算。而datetime模块对struct_time对象进行了封装,使得操作更加便捷。
time模块操作
下面先来看看time模块的使用,首先是我们最常用的两个操作
>>> time.time() # 获取当前时间戳
1603451939.5721555
>>> time.sleep(2) # 程序休眠2秒
下面我们构建上面提到的struct_time对象,既可以传递包含9个元素的元组来构建
>>> time.struct_time((2020,10,23,19,22,10,4,297,0))
time.struct_time(tm_year=2020, tm_mon=10, tm_mday=23, tm_hour=19, tm_min=22, tm_sec=10, tm_wday=4, tm_yday=297, tm_isdst=0)
也可以直接通过时间戳来转换
>>> time.localtime(time.time())
time.struct_time(tm_year=2020, tm_mon=10, tm_mday=23, tm_hour=19, tm_min=22, tm_sec=7, tm_wday=4, tm_yday=297, tm_isdst=0)
有了struct_time对象就可以进行格式化输出了
>>> a=time.localtime(time.time())
>>> time.strftime('%Y-%m-%d|%H:%M:%S',a)
'2020-10-23|19:25:46'
strftime()
方法接受两个参数,一个字符串和一个struct_time对象,其中字符串内可以通过百分号来进行格式输出,常见的几种格式如下,完整的格式可以查看
这里
格式
含义
%Y
四位数表示的年份
%y
两位数表示的年份
%m
月份
%d
一月内的第几天
%H
24小时制小时数
%M
分钟数
%S
秒数
%Z
时区
既然可以从struct_time对象格式化为字符串,当然也可以反过来从字符串按照特定格式提取struct_time对象
>>> b=time.strptime('2020|10|23||20|05|10','%Y|%m|%d||%H|%M|%S')
>>> b
time.struct_time(tm_year=2020, tm_mon=10, tm_mday=23, tm_hour=20, tm_min=5, tm_sec=10, tm_wday=4, tm_yday=297, tm_isdst=-1)
有个很常见的场景,就是从网络上爬虫下来的时间可能是各种格式的,就可以用这种方式来处理。
datetime模块操作
查看一下源码就会发现,在
datetime.py
文件中,定义了5个类,分别是
timedelta
time
datetime
date
timezone
所以,
from datetime import xxx
之后只可能产生这5种对象,不会再有上面所说的struct_time对象了。
通常使用
datetime
类就够了
>>> import datetime
>>> datetime.datetime.__doc__
'datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])...'
可以看到至少要传递3个参数,分别是年月日
>>> a=datetime.datetime(2020,2,14)
>>> a
datetime.datetime(2020, 2, 14, 0, 0)
像分别得到
date
和
time
对象也很容易
>>> a.date()
datetime.date(2020, 2, 14)
>>> a.time()
datetime.time(0, 0)
当然通常是通过当前时间做一个偏移来得到想要的时间,也就是time模块比较难实现的部分
>>> b=a+datetime.timedelta(days=5)
>>> b
datetime.datetime(2020, 2, 19, 0, 0)
这里的
timedelta
专门用来生成时间偏移对象,通过下面的可以看到除了表示天数差异的
days
,也可以进行其余6种级别的偏移
>>> datetime.timedelta.__doc__
'Difference between two datetime values.\n\ntimedelta(days=0, seconds=0, microseconds=0, milliseconds=0, minutes=0, hours=0, weeks=0)\n\nAll arguments are optional and default to 0.\nArguments may be integers or floats, and may be positive or negative.'
而表示当前时间的
datetime
对象也可以直接获取
>>> now=datetime.datetime.now()
>>> now
datetime.datetime(2020, 10, 23, 23, 44, 15, 822505)
>>> today=datetime.date.today()
>>> today
datetime.date(2020, 10, 23)
至于字符串的格式输出和格式提取所用到的关键字和上面一样
>>> datetime.datetime.strptime('2020>10>23>23>50>10','%Y>%m>%d>%H>%M>%S')
datetime.datetime(2020, 10, 23, 23, 50, 10)
>>> datetime.datetime(2020,10,23,23,50,11).strftime('%Y
'2020<10<23<23<50<11'
最后是和时间戳之间的相互转换
>>> datetime.datetime(2020,10,23,23,50,11).timestamp()
1603468211.0
>>> datetime.datetime.fromtimestamp(1603468213.3)
datetime.datetime(2020, 10, 23, 23, 50, 13, 300000)
Mysql存储
Mysql中有如下几个时间相关的字段
字段
格式
date
YYYY-MM-DD
time
HH:MM:SS
year
YYYY
datetime
YYYY-MM-DD HH:MM:SS
timestamp
YYYYMMDD HHMMSSS
如果要用原生SQL语句去进行Insert操作,需要用
strftime
将datetime对象转变为指定格式的字符串然后存储,不然会有格式报错。
但既然是python操作,那么经常使用的是通过ORM来操作,下面以Django为例来做一下演示。
首先在models中创建一个测试用的表
class DateTest(models.Model):
dt = models.DateTimeField()
d = models.DateField()
class Meta:
db_table = 'DateTest'
迁移完成。
然后创建如下的路由和视图函数
path('test/', views.insert_date, name='test'),
def insert_date(request):
date_obj = DateTest(dt=datetime.datetime.now(), d=datetime.date.today())
date_obj.save()
return HttpResponse('数据插入成功')
可以看到Django中非常贴心的将ORM中的
DateTimeField
和
DateField
与python中的datetime和date数据类型进行了一一对应,直接将python对象赋值给对应字段即可。
如果访问上述url数据库中成功加入一条记录如下
点击选中对应的记录可以看到对应的SQL语句如下
INSERT INTO cmdb.DateTest (id, dt, d) VALUES (1, '2020-10-24 12:17:36.572617', '2020-10-24');
可以看到SQL中是以特定格式字符串来插入的。
我是T型人小付,一位坚持终身学习的互联网从业者。如果有问题欢迎在底下的评论区交流,谢谢。