基于代码示例,简要介绍python中基于datetime包的关于日期时间和时间戳相关的各种处理。
使用dir()命令可以检查datetime包中都有些什么东西。
# What is inside datetime?
import datetime
print(dir(datetime))
输出:['MAXYEAR', 'MINYEAR', '__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__spec__', 'date', 'datetime', 'datetime_CAPI', 'sys', 'time', 'timedelta', 'timezone', 'tzinfo']
第一个例子,获取当前日期时间:
# Example 1: Get Current Date and Time
now = datetime.datetime.now()
print(now)
输出(something like this): 2021-10-27 08:37:13.208591
datetime模块中常用的(工具)类有以下四种:
(1)date
(2)time
(3)datetime
(4)timedelta
以下逐一介绍。
例2:创建一个date对象,
from datetime import date
d = date(2021,10,26)
print(d)
date()是一个constructor,三个输入参数分别代表年,月,日。
例3:获取当前日期,用date class的today()方法
today = date.today()
print(today)
print("Current year:", today.year)
print("Current month:", today.month)
print("Current day:", today.day)
首先必须给出关于时间戳的一个定义。在这里,时间戳是指用一个实数来代表一个日期,这个实数表示这个日期对应的秒数,具体来说是指从计时起点1970年1月1日0时起到指定日期所经过的秒数。至于为什么是以1970年1月1日为起点。。。嗯,我也不知道,baidu, google一下就知道了。
例4:从一个时间戳中生成日期
d = date.fromtimestamp(1158676809.864)
print(d)
# What is the start for the timestamp?
d0 = date.fromtimestamp(0)
print(d0)
2006-09-19
1970-01-01
以上代码中,首先从一个绝对时间戳115....计算出它对应的日期(年月日)。接下来,既然是绝对的时间戳,就必定有一个计时起点,那么这个计时起点是什么时候呢?给fromtimestamp传入参数0就可以知道时间戳计时起点了。从以上结果可以看出,计时起点为1970年1月1日,单位为秒。换句话说,从1970年1月1日零点到2006-09-19为止经过了大约1158676800秒。
求一个日期的时间戳可以用timestamp()来实现,date和datetime都有timestamp()方法。timestamp()可以认为是以上fromtimestamp()的反函数。如以下例所示:
from datetime import datetime, date, datetime
import calendar
tstr = '10/23/2011 20:44:24.990'
dobj = datetime.strptime(tstr, "%m/%d/%Y %H:%M:%S.%f")
print(dobj)
print(datetime.fromtimestamp(dobj.timestamp()))
输出:
2011-10-23 20:44:24.990000
2011-10-23 20:44:24.990000
第二个输出结果表明,fromtimestamp()和timestamp()的级联作用抵消了。
有以下4种创建time object的方法。
缺省的constructor(无参数传入)创建一个零时零分零秒的time对象。可以传递的参数包括时、分、秒以及毫秒。未传入的参数赋缺省的0值。
# Example 5: Time object to represent time
# time(hour = 0, minute = 0, second = 0)
print('\nExample 5:...')
a = time()
print("a =", a)
# time(hour, minute and second)
b = time(11, 34, 56)
print("b =", b)
# time(hour, minute and second)
c = time(hour = 11, minute = 34, second = 56)
print("c =", c)
# time(hour, minute, second, microsecond)
d = time(11, 34, 56, 234566)
print("d =", d)
print("hour =", d.hour)
print("minute =", d.minute)
print("second =", d.second)
print("microsecond =", d.microsecond)
datetime对象可以看作时date对象和time对象的结合体。
print('\nExample 6:...')
#datetime(year, month, day)
a = datetime(2018, 11, 28)
print(a)
# datetime(year, month, day, hour, minute, second, microsecond)
b = datetime(2017, 11, 28, 23, 55, 59, 342380)
print(b)
print("year =", b.year)
print("month =", b.month)
print("hour =", b.hour)
print("minute =", b.minute)
print("timestamp =", b.timestamp())
datetime构造函数的参数按缺省顺序依此是年、月、日、时、分、秒、毫秒。 当然也可以如例5中那样以参数名的方式传递,这样就不一定要按这个顺序传递了。
timedelta对象表示两个时间(date or time or datetime)对象之间的时间差。
直接对两个时间对象做减法就能生成一个timedelta对象。
print('\nExample 7:...')
t1 = date(year = 2018, month = 7, day = 12)
t2 = date(year = 2017, month = 12, day = 23)
t3 = t1 - t2
print("t3 =", t3)
t4 = datetime(year = 2018, month = 7, day = 12, hour = 7, minute = 9, second = 33)
t5 = datetime(year = 2019, month = 6, day = 10, hour = 5, minute = 55, second = 13)
t6 = t4 - t5
print("t6 =", t6)
print("type of t3 =", type(t3))
print("type of t6 =", type(t6))
Example 7:...
t3 = 201 days, 0:00:00
t6 = -333 days, 1:14:20
type of t3 = <class 'datetime.timedelta'>
type of t6 = <class 'datetime.timedelta'>
print('\nExample 8:...')
from datetime import timedelta
t1 = timedelta(weeks = 2, days = 5, hours = 1, seconds = 33)
t2 = timedelta(days = 4, hours = 11, minutes = 4, seconds = 54)
t3 = t1 - t2
print("t3 =", t3)
print("type of t1 =", type(t1))
print("type of t2 =", type(t2))
print("type of t3 =", type(t3))
Example 8:...
t3 = 14 days, 13:55:39
type of t1 = <class 'datetime.timedelta'>
type of t2 = <class 'datetime.timedelta'>
type of t3 = <class 'datetime.timedelta'>
如上所示,可以直接基于构造函数创建timedelta对象。进一步,两个timedelta也可以进一步做减法生成第3个timedelta对象。
既然timedelta对象是由两个时间对象之差而得,自然就会有负的timedelta对象出现。负的timedelta打印出来会是什么样子呢?
print('\nExample 9:...')
t1 = timedelta(seconds = 33)
t2 = timedelta(seconds = 54)
t3 = t1 - t2
print("t3 =", t3)
print("t3 =", abs(t3))
Example 9:...
t3 = -1 day, 23:59:39
t3 = 0:00:21
注意,并不是打印出-21秒来。。。如果想要“-21”呢?参见下一节。
print('\nExample 10:...')
t1 = timedelta(seconds = 33)
t2 = timedelta(seconds = 54)
t3 = t1 - t2
print("total seconds =", t3.total_seconds())
t = timedelta(days = 5, hours = 1, seconds = 33, microseconds = 233423)
print("total seconds =", t.total_seconds())
Example 10:...
total seconds = -21.0
total seconds = 435633.233423
有多种不同的格式表示日期的格式,比如说mm/dd/yyyy,mm/dd/yy,dd/mm/yyyy,dd/mm/yy,yyyy-mm-dd, yy-mm-dd等等。
datetime中提供了strftime()和strptime()两个方法来处理这些不同的格式以及格式之间的转换。
在datetime, date和time类中都定义了strftime()方法,它用于基于不同的日期时间对象创建对应的格式化字符串。
print('\nExample 12:...')
now = datetime.now()
t = now.strftime("%H:%M:%S")
print('type of t is ',type(t))
print("time:", t)
s1 = now.strftime("%m/%d/%Y, %H:%M:%S")
# mm/dd/YY H:M:S format
print("s1:", s1)
s2 = now.strftime("%d/%m/%Y, %H:%M:%S")
# dd/mm/YY H:M:S format
print("s2:", s2)
s3 = now.strftime("%d/%m/%y, %H:%M:%S")
# dd/mm/YY H:M:S format
print("s3:", s3)
s4 = now.strftime("%y-%m-%d, %H:%M:%S")
# yy-mm-dd H:M:S format
print("s4:", s4)
Example 12:...
type of t is <class 'str'>
time: 09:57:02
s1: 10/27/2021, 09:57:02
s2: 27/10/2021, 09:57:02
s3: 27/10/21, 09:57:02
s4: 21-10-27, 09:57:02
如上所示,strftime()的输出为一个字符传。基于同一个对象,通过不同的格式控制字符串的控制可以生成不同格式的对应该时间日期对象的字符串表示。格式控制字符串如6.3所示.
strptime()可以看作是strftime()的相反的处理,即从字符串表示的日期生成时间日期对象。
print('\nExample 13:...')
date_string = "21 June, 2018"
print("date_string =", date_string)
date_object = datetime.strptime(date_string, "%d %B, %Y")
print("date_object =", date_object)
Example 13:...
date_string = 21 June, 2018
date_object = 2018-06-21 00:00:00
格式控制字符串如下表所示:
Directive | Meaning | Example |
%a | Abbreviated weekday name. | Sun, Mon, ... |
%A | Full weekday name. | Sunday, Monday, ... |
%w | Weekday as a decimal number. | 0, 1, ..., 6 |
%d | Day of the month as a zero-padded decimal. | 01, 02, ..., 31 |
%-d | Day of the month as a decimal number. | 1, 2, ..., 30 |
%b | Abbreviated month name. | Jan, Feb, ..., Dec |
%B | Full month name. | January, February, ... |
%m | Month as a zero-padded decimal number. | 01, 02, ..., 12 |
%-m | Month as a decimal number. | 1, 2, ..., 12 |
%y | Year without century as a zero-padded decimal number. | 00, 01, ..., 99 |
%-y | Year without century as a decimal number. | 0, 1, ..., 99 |
%Y | Year with century as a decimal number. | 2013, 2019 etc. |
%H | Hour (24-hour clock) as a zero-padded decimal number. | 00, 01, ..., 23 |
%-H | Hour (24-hour clock) as a decimal number. | 0, 1, ..., 23 |
%I | Hour (12-hour clock) as a zero-padded decimal number. | 01, 02, ..., 12 |
%-I | Hour (12-hour clock) as a decimal number. | 1, 2, ... 12 |
%p | Locale’s AM or PM. | AM, PM |
%M | Minute as a zero-padded decimal number. | 00, 01, ..., 59 |
%-M | Minute as a decimal number. | 0, 1, ..., 59 |
%S | Second as a zero-padded decimal number. | 00, 01, ..., 59 |
%-S | Second as a decimal number. | 0, 1, ..., 59 |
%f | Microsecond as a decimal number, zero-padded on the left. | 000000 - 999999 |
%z | UTC offset in the form +HHMM or -HHMM. | |
%Z | Time zone name. | |
%j | Day of the year as a zero-padded decimal number. | 001, 002, ..., 366 |
%-j | Day of the year as a decimal number. | 1, 2, ..., 366 |
%U | Week number of the year (Sunday as the first day of the week). All days in a new year preceding the first Sunday are considered to be in week 0. | 00, 01, ..., 53 |
%W | Week number of the year (Monday as the first day of the week). All days in a new year preceding the first Monday are considered to be in week 0. | 00, 01, ..., 53 |
%c | Locale’s appropriate date and time representation. | Mon Sep 30 07:06:05 2013 |
%x | Locale’s appropriate date representation. | 09/30/13 |
%X | Locale’s appropriate time representation. | 07:06:05 |
%% | A literal '%' character. | % |
其中有一些共同的规律(有例外):
(1)大小写字母:小写字母表示用缩写,大写字母表示用全称。比如1999年,%y表示用'99'表示,而%Y则表示用‘1999’表示
(2)前缀“-”: 无前缀表示前头补零的字符串格式,而前缀“-”则表示去掉前面的0改为十进制数的表示格式
(3)年月日之间通常用“/”或者“-”分隔,时分秒之间则通常用“:”分隔。秒与毫秒之间则用“.”连接。注意要保持格式控制字符串中与表示时间日期的字符串之中的分隔符保持一致。
python内置的工具库也可以进行跨时区的处理,但是这里推荐一个第三方库:pytz[4]。
利用pytz.common_timezones和pytz.total_timezones分别可以列出常用和全部时区,分别有439个和539(大差不差,所以,好像常用与全部也没有什么差别^-^).
print('\nExample 14...')
print('\ncommon pytz timezone list...')
print(len(pytz.common_timezones))
print(pytz.common_timezones)
print(len(pytz.all_timezones))
print(pytz.all_timezones)
以下代码段显式了当前时刻在上海本地的时间,以及在纽约当地的时间。
print('\nExample 15:...')
local = datetime.now()
print("Local:", local.strftime("%m/%d/%Y, %H:%M:%S"))
tz_NY = pytz.timezone('America/New_York')
datetime_NY = datetime.now(tz_NY)
print("NY:", datetime_NY.strftime("%m/%d/%Y, %H:%M:%S"))
tz_SH = pytz.timezone('Asia/Shanghai')
datetime_SH = datetime.now(tz_SH)
print("SH:", datetime_SH.strftime("%m/%d/%Y, %H:%M:%S"))
Example 15:...
Local: 10/27/2021, 10:44:05
NY: 10/26/2021, 22:44:05
SH: 10/27/2021, 10:44:05
这个问题并不像想象的那么简单。
比如说在以上代码段后面加一条语句:
timeDifference = (datetime_SH - datetime_NY)
print('Time difference between SH and NY is:',timeDifference) # Doesn't work properly.
你得到的是“0:00:00”,而并不是所期望的上海与纽约的时差。
网上搜了搜,这个似乎不是一个简单的问题,有兴趣的小伙伴可以参考[6]。抽空回头再来不全这部分内容。
关于Python中另一个与日期时间处理相关的模块calendar可参考:Python calendar模块的常用有趣用法
Reference:
[1]datetime — Basic date and time types — Python 3.10.0 documentation
[2]Python datetime (With Examples) (programiz.com)
[3]Python String to DateTime using Strptime() [5 Ways] – PYnative
[4]pytz - World Timezone Definitions for Python — pytz 2014.10 documentation (sourceforge.net)
[5]python - Is there a list of Pytz Timezones? - Stack Overflow
[6]datetime - How to compute the time difference between two time zones in python? - Stack Overflow