在python编程中我们常常需要处理时间和日期信息,例如需要获取当前时间、生成特定字符串格式的时间信息等等。python为我们提供了一个现成的标准库——datetime,内置了许多有用的类和函数,现整理如下。
1 datetime标准库
datetime库中有一个同名的类——datetime类,采用该类可以做很多工作。
- timestamp时间戳。首先我们要了解日期和时间在计算机中是如何表示的。我们看到的日期都是像xxxx年xx月xx日的形式,但在计算机中并不是以这种字符串的形式来存储时间的。而是以一种非常简单粗暴的方式来存储——浮点数。这也是所谓的时间戳,我们将1970年1月1日 00:00:00 UTC+00:00时区的时刻的时间戳记为0,在此之前的为负数;在此之后的为正数。其整数部分表示秒(Java的整数部分表示毫秒,原理一样)。用这种方式存储的时间简单高效没有二义性,全世界都适用。
from datetime import datetime
d = datetime.now() # 当前时间(东八区)
t = d.timestamp() # 时间戳
print(d, t)
# 将时间戳转换为当前时间和当前utc时间
print(datetime.fromtimestamp(t), datetime.utcfromtimestamp(t))
2021-02-05 10:52:06.093800 1612493526.0938
2021-02-05 10:52:06.093800 2021-02-05 02:52:06.093800
- 获取标准日期和时间。这里包含获取当前的时间和获取指定的时间。获取指定时间的方法就是向datetime类传入对应参数,包括年月日时分秒毫秒时区等,其中年月日是必须的,其他可选,参考源码datetime如下。
"""datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]])
The year, month and day arguments are required. tzinfo may be None, or an
instance of a tzinfo subclass. The remaining arguments may be ints.
"""
def __new__(cls, year, month=None, day=None, hour=0, minute=0, second=0,
microsecond=0, tzinfo=None, *, fold=0):
# 获取当前时间
from datetime import datetime
d = datetime.now()
print(d)
2021-02-05 10:53:08.753610
# 获取指定时间
from datetime import datetime
d = datetime(2019, 12, 18, 18, 20)
print(d)
2019-12-18 18:20:00
- 日期/时间转换。这里的转换形式非常多,包括时间戳(timestamp)与标准时间(datetime)之间的转换、datetime与字符串之间的转换、timestamp与字符串之间的转换等等。但我认为这里只需要抓住一个准则就可以应对多种情形——所有的转换都以标准时间(datetime)为中心展开。例如timestamp转为字符串,那么就先将timestamp转为datetime,再将datetime转为字符串。
# 这里需要掌握四个函数即可
d.timestamp() # datetime->timestamp
datetime.fromtimestamp(t) # timestamp->datetime
datetime.strptime(s, f) # string->datetime
d.strftime(f) # datetime->string
- 上面介绍了timestamp和datetime的转换,这里只介绍字符串和datetime之间的转换实例。
# 字符串转datetime
from datetime import datetime
time_str = '2019-12-18 18:20:10' # 指定需要转换的字符串
str_format = '%Y-%m-%d %H:%M:%S' # 指定转换格式
d = datetime.strptime(time_str, str_format)
print(d)
2019-12-18 18:20:10
# datetime转字符串
from datetime import datetime
d = datetime(2019, 12, 18, 18, 20, 10) # datetime对象
str_format = '%Y year %m month %d day %H hour %M min %S sec'
time_str = d.strftime(str_format)
print(time_str)
2019 year 12 month 18 day 18 hour 20 min 10 sec
- 有一些常用的时间Format的记号,这里整理如下:
%y 两位数的年份表示(00-99)
%Y 四位数的年份表示(000-9999)
%m 月份(01-12)
%d 月内中的一天(0-31)
%H 24小时制小时数(0-23)
%I 12小时制小时数(01-12)
%M 分钟数(00=59)
%S 秒(00-59)
%a 本地简化星期名称
%A 本地完整星期名称
%b 本地简化的月份名称
%B 本地完整的月份名称
%c 本地相应的日期表示和时间表示
%j 年内的一天(001-366)
%p 本地A.M.或P.M.的等价符
%U 一年中的星期数(00-53)星期天为星期的开始
%w 星期(0-6),星期天为星期的开始
%W 一年中的星期数(00-53)星期一为星期的开始
%x 本地相应的日期表示
%X 本地相应的时间表示
%Z 当前时区的名称
%% %号本身
- datetime时间推移。有时候我们想要获取当前时间之前2小时的时间,此时应该如何做呢?有两种方式,1)是获取当前时间的timestamp,然后通过对timestamp做加减运算,得到想要时间的时间戳,再将其转换为标准时间;2)是datetime模块中有一个timedelta类,可以直接对datetime对象做加减运算。
# 第一种方式
from datetime import datetime
d = datetime(2021, 1, 1)
t = d.timestamp()
t += 60 * 60 * 12 # 12小时
d1 = datetime.fromtimestamp(t)
print(d1)
2021-01-01 12:00:00
from datetime import datetime, timedelta
d = datetime(2021, 1, 1)
d += timedelta(hours=12) # 12小时
print(d)
2021-01-01 12:00:00
- 时区问题。从上面datetime源码可以看到,其中有一个tzinfo的选项默认为None,其用来表示时区。可以通过以下方式强制设置某个datetime的时区。
from datetime import datetime, timedelta, timezone
tz_utc_8 = timezone(timedelta(hours=8)) # 创建时区UTC+8:00
now = datetime.now()
dt = now.replace(tzinfo=tz_utc_8) # 强制设置为UTC+8:00
2 小试牛刀
例1:编写一个函数能够将输入的一个MM/DD/YYYY格式的字符串日期转换为YYYYDDMM。
format_date(“11/12/2019”) ➞ “20191211”
format_date(“12/31/2019”) ➞ “20193112”
format_date(“01/15/2019”) ➞ “20191501”
# 用datetime库实现
from datetime import datetime
def format_date(date):
d = datetime.strptime(date, '%m/%d/%Y')
return d.strftime('%Y%d%m')
# 当然有更简单的方式
def format_date(date):
m, d, y = date.split('/')
return ''.join((y, d, m))
例2:假设你获取了用户输入的日期和时间如2015-1-21 9:01:30,以及一个时区信息如UTC+5:00,均是str,请编写一个函数将其转换为timestamp。
import re
from datetime import datetime, timezone, timedelta
def to_timestamp(dt_str, tz_str):
dt = datetime.strptime(dt_str, '%Y-%m-%d %H:%M:%S')
tz_r = re.match(r'^UTC([+|-]\d{1,2}):00$', tz_str) # UTC中获取时区信息
# 利用tzinfo属性将datetime强制设置成指定时区
dt = dt.replace(tzinfo=timezone(timedelta(hours=int(tz_r.group(1)))))
return dt.timestamp()
# 测试:
t1 = to_timestamp('2015-6-1 08:10:30', 'UTC+7:00')
assert t1 == 1433121030.0, t1
t2 = to_timestamp('2015-5-31 16:10:30', 'UTC-09:00')
assert t2 == 1433121030.0, t2
print('ok')