Fork me on GitHub

一文搞定Python中的时间转化

一文搞定Python中的时间转化

在生活和工作中,我们每个人每天都在和时间打交道:

  • 早上什么时候起床?
  • 地铁几分钟来一趟?
  • 中午什么时候开始午休?
  • 明天是星期几?
  • 距离上次买衣服已经2个月呢?
  • 领导让我给代码加上一个定时任务的功能,怎么办?

不同的情况会遇到不同的时间问题:具体时间点、时间间隔、星期等,无时不刻我们在和时间碰撞。本文将利用Python对时间相关的类,及其方法与属性等进行详细的讲解

时间戳

时间戳简介

在正式讲解时间的相关函数之前,我们必须先一个概念:时间戳。本文中特指unix时间戳。

时间戳Timestamp是指在一连串的数据中加入辨识文字,如时间或者日期等,用以保障本地数据更新顺序和远程的一致。

unix时间戳是从1970年1月1日(UTC/GMT的午夜)开始所经过的秒数,不考虑闰秒。1970-01-01就是经常我们在MySQL中时间为空的时候,转化空的时间戳之后得到的时间。一个小时表示为UNIX时间戳格式为:3600秒;一天表示为UNIX时间戳为86400秒,闰秒不计算。具体的对照表如下:

时间
1分钟 60
1小时 3600
1天 86400
1周 604800
1月(30.44天) 2629743
1年(365.24天) 31556763

时间戳转化网站

下面介绍几个时间戳和具体时间之间相互转化的网站:

1、站长工具:https://tool.chinaz.com/tools/unixtime.aspx

2、在线工具:https://tool.lu/timestamp/

3、Json在线解析:https://www.sojson.com/unixtime.html

4、Unix时间戳在线转换(菜鸟工具):https://c.runoob.com/front-end/852

5、北京时间(时间与时间戳互换工具):http://www.beijing-time.org/shijianchuo/

介绍完时间戳的基本知识,下面重点讲解3个与时间和日期相关的Python库:

  • calendar
  • time
  • datetime

calendar

calendar的中文意思是"日历",所以它其实适合进行日期,尤其是以日历的形式展示。

模块内容

下面举例说明:

calendar

我们显示即将过去2020年的日历,使用默认的参数:

1
2
3
import calendar
year = calendar.calendar(2020)
print(year)

改变参数再来显示一次:

1
2
year = calendar.calendar(2020,w=3,l=1,c=8)
print(year)

我们发现整个日历变宽了,而且星期的英文也是3个字母来显示的,解释一下3个参数的含义:

  • c:每月间隔距离
  • w:每日宽度间隔
  • l:每星期行数

其中每行长度为:21*w+18+2*c,3个月一行

最后,看看即将到来的2021年日历:

isleap(year)

该函数的作用是判断某个年份到底是不是闰年。如果是则返回True,否则返回的是False。

普通年份能够被4整除,但是不能被100整除,称之为普通闰年

年份是整百数的,必须能够被400整除,称之为世纪闰年

leapdays(y1,y2)

判断两个年份之间有多少个闰年,包含y1,但是不包含y2,类似Python切片中的包含头部不包含尾部

month(year,month,w=2,l=1)

该函数返回的是year年的month月的日历,只有两行标题,一周一行。每日间隔宽度为w个字符,每行的长度为7*w + 6,其中l是每星期的行数

首先看看默认效果;

接下来我们改变w和l两个参数:

1、改变w,我们发现星期的表示变成了3个字母;同时每天之间的间隔变宽了(左右间隔)

2、改变参数l,我们发现每个星期之前的间隔(上下)变宽了

monthcalendar(year,month)

通过列表的形式返回year年month月的日历,列表中还是列表形式。每个子列表是一个星期。如果没有本月的日期则用0表示。每个子列表都是从星期1开始的,特点概括如下:

  • 每个子列表代表的是一个星期
  • 从星期一到星期日,没有出现在本月的日期用0代替

我们还是以2020年12月份为例:

和上面的日历进行对比,我们发现:出现0的位置的确是没有出现在12月份中

我们再看看2020年3月份的日历:

monthrange(year,month)

该函数返回的结果是一个元组,元组中有两个数值(a,b)

  • 数值a代表的是该月从星期几开始;规定6代表星期天,取值为0-6
  • 数值b代表该月总共有多少天

通过一个例子来讲解,还是以2020年12月份为例:

结果中的1表示12月份从星期2开始(0-6,6代表星期日),该月总共31天

weekday(y,m,d)

weekday方法是输入年月日,我们便可知道这天是星期几;返回值是0-6,0代表星期1,6代表星期天

通过一个例子来讲解,以12月12号为例:

双12是星期六,返回的结果是5,5代表的就是星期六,刚好吻合。

time

time模块是涉及到时间功能中最常用的一个模块,在Python的相关时间需求中经常会用到,下面具体讲解该模块的使用方法。

模块内容

先看模块的整体使用

time

time.time()是获取当前的时间,更加严格地说,是获取当前时间的时间戳

再次理解时间戳:它是以1970年1月1日0时0份0秒为计时起点,计算到当前的时间长度(不考虑闰秒)

localtime

time.localtime打印当前的时间,得到的结果是时间元组,具体含义:

笔记:结果是时间元组

序号 属性
0 tm_year 年,比如2020
1 tm_mon 月,1 到 12
2 tm_mday 日,1 到 31
3 tm_hour 时,0 到 23
4 tm_min 分,0 到 59
5 tm_sec 秒,0 到 61 (60或61 是闰秒)
6 tm_wday 一周中的第几天,0到6 (0是周一)
7 tm_yday 一年中的第几天,1 到 366
8 tm_isdst -1, 0, 1, -1是决定是否为夏令时的旗帜

time.localtime的参数默认是time.time()的时间戳,可以自己输入某个时间戳来获取其对应的时间

  • 默认当前时间戳
  • 指定某个时间戳

gmtime

localtime()得到的是本地时间,如果需要国际化,使用gmtime(),最好是使用格林威治时间。

格林威治标准时间:位于英国伦敦郊区的皇家格林威治天文台的标准时间,本初子午线经过那里。

asctime

time.asctime的参数为空时,默认是以time.localtime的值为参数,得到当前的日期、时间、星期;另外,我们也可以自己设置参数,参数是时间元组

  • 使用当前时间的默认时间元组localtime
  • 自己指定一个时间元组

获取当前时间的具体时间和日期:

ctime

ctime的参数默认是时间戳;如果没有,也可以指定一个时间戳

mktime

mktime()也是以时间元组为参数的,它返回的是时间戳,相当于是localtime的逆向过程

strftime

strftime()是按照我们指定的格式将时间元组转化为字符串;如果不指定时间元组,默认是当前时间localtime()。常用到的时间格式见下表:

格式 含义 取值范围(样式)
%y 去掉世纪的年份 00-99,如“19”
%Y 完整的年份 如2019
%j 指定日期是一年中的第几天 范围001-366
%m 返回的是月份 范围:01-12
%b 本地简化月份的名称 简写的英文月份
%B 本地完整月份的名称 完整的英文月份
%d 该月的第几日 如,5月1日返回的是“01”
%H 第几小时,24小时制 00-23
%l 第几小时,12小时制 00-12
%M 分钟 00-59
%S 00-59
%U 该年中的第几个星期(周日为一周的起点) 00-53
%W 同上,周一为起点 00-53
%w 一个星期中的第几天 0-6
%Z 时区 在大陆测试返回的是CST
%x 日期 日/月/年
%X 时间 时:分:秒
%c 详细日期时间 日/月/年时:分:秒
%% %字符 '%'字符
%p 上下午 AM or PM

我们举例说明:

  • 字符串中的分隔符我们可以任意指定
  • 可以同时显示年月日时分秒等

strptime

strptime()是将字符串转化为时间元组,我们需要特别注意的是,它有两个参数:

  • 待转化的字符串
  • 时间字符串对应的格式,格式就是上面👆表中提到的

datetime

虽然time模块已经能够解决很多的问题,但是实际工作和业务需求中需要更多的工具,让我们使用起来更方便和快捷,datetime便是其中一个很好用的模块。datetime模块中几个常用的类如下:

  • date:日期类,常用属性:year/month/day
  • time:时间类,常用属性:hour/minute/second/microsecond
  • datetime:日期时间类
  • timedelta:时间间隔,即两个时间点之间的时间长度
  • tzinfo:时区类

模块内容

内容 描述
2个常量
datetime.MINYEAR date和datetime对象允许的最小年份
datetime.MAXYEAR date和datetime对象允许的最大年份
多个属性
datetime.date 日期对象,属性(year, month, day)
datetime.time 时间对象,属性(hour, minute, second, microsecond, tzinfo)
datetime.datetime 日期时间对象,属性(date和time属性组合)
datetime.timedelta Difference between two datetime values(原文)
datetime.tzinfo 时区信息对象的抽象基类, datetime和time类使用它定制化时间调节

date

首先我们引入date类,并创建一个日期对象:

1、然后我们可以操作这个日期对象的各种属性:后面加上()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
print("当前日期:",today)  # 当前日期
print("当前日期(字符串):",today.ctime()) # 返回日期的字符串
print("时间元组信息:",today.timetuple()) # 当前日期的时间元组信息
print("年:",today.year) # 返回today对象的年份
print("月:",today.month) # 返回today对象的月份
print("日:",today.day) # 返回today对象的日
print("星期:",today.weekday()) # 0代表星期一,类推
print("公历序数:",today.toordinal()) # 返回公历日期的序数
print("年/周数/星期:",today.isocalendar()) # 返回一个元组:一年中的第几周,星期几

# 结果显示
当前日期: 2020-12-25
当前日期(字符串): Fri Dec 25 00:00:00 2020
时间元组信息: time.struct_time(tm_year=2020, tm_mon=12, tm_mday=25, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=4, tm_yday=360, tm_isdst=-1)
年: 2020
月: 12
日: 25
星期: 4
公历序数: 737784
年/周数/星期: (2020, 52, 5)

2、date类中时间和时间戳的转换:

具体时间的时间戳转成日期:

3、格式化时间相关,格式参照time模块中的strftime方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
from datetime import datetime, date, time
today = date.today()

print(today)
# 2020-12-26 默认连接符号是-

print(today.strftime("%Y/%m/%d")) # 指定连接符
# 2020/12/26

print(today.strftime("%Y:%m:%d"))
# 2020:12:26

print(today.strftime("%Y/%m/%d %H:%M:%S")) # 转化为具体的时间
# 2020/12/26 00:00:00

4、修改日期使用replace方法

time

time类也是要生成time对象,包含hour、minute、second、microsecond,我们还是通过例子来学习:

1
2
3
4
5
6
7
8
9
10
11
12
13
from datetime import time

t = time(10,20,30,40)
print(t.hour) # 时分秒
print(t.minute)
print(t.second)
print(t.microsecond) # 微秒

# 结果
10
20
30
40

datetime

datetime类包含date类和time类的全部信息,下面👇是类方法相关的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
from  datetime import datetime

print(datetime.today())
print(datetime.now())
print(datetime.utcnow())# 返回当前UTC日期和时间的datetime对象
print(datetime.fromtimestamp(1697302830)) # 时间戳的datetime对象
print(datetime.fromordinal(699000) )
print(datetime.combine(date(2020,12,25), time(11,22,54))) # 拼接日期和时间
print(datetime.strptime("2020-12-25","%Y-%m-%d"))

# 结果
2020-12-25 23:24:42.481845
2020-12-25 23:24:42.482056
2020-12-25 15:24:42.482140
2023-10-15 01:00:30
1914-10-19 00:00:00
2020-12-25 11:22:54
2020-12-25 00:00:00

再看看相关对象和属性相关:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
from datetime import datetime

d = datetime(2020,12,25,11,24,23)

print(d.date())
print(d.time())
print(d.timetz()) # 从datetime中拆分出具体时区属性的time
print(d.replace(year=2021,month=1)) # 替换
print(d.timetuple()) # 时间元组
print(d.toordinal()) # 和date.toordinal一样
print(d.weekday())
print(d.isoweekday())
print(d.isocalendar())
print(d.isoformat())
print(d.strftime("%Y-%m-%d :%H:%M:%S"))

# 结果
2020-12-25
11:24:23
11:24:23
2021-01-25 11:24:23
time.struct_time(tm_year=2020, tm_mon=12, tm_mday=25, tm_hour=11, tm_min=24, tm_sec=23, tm_wday=4, tm_yday=360, tm_isdst=-1)
737784
4
5
(2020, 52, 5)
2020-12-25T11:24:23
2020-12-25 :11:24:23

timedelta

timedelta对象表示的是一个时间段,即两个日期date或者日期时间datetime之间的差;支持参数:weeks、days、hours、minutes、seconds、milliseconds、microseconds

tzinfo

本地时间指的是我们系统本身设定时区的时间,例如中国处于北京时间,常说的东八区UTC+8:00datetime类有一个时区属性tzinfo

tzinfo是一个关于时区信息的类,是一个抽象的基类,不能直接被实例化来使用。它的默认值是None,无法区分具体是哪个时区,需要我们强制指定一个之后才能使用。

因为本身系统的时区刚好在中国处于东八区,所以上述代码是能够正常运行的,结果也是OK的。那如果我们想切换到其他时区的时间,该如何操作呢?这个时候我们需要进行时区的切换。

1、我们先通过utcnow()获取到当前的UTC时间

1
2
3
4
5
utc_now = datetime.utcnow().replace(tzinfo=timezone.utc)  # 指定utc时区
print(utc_now)

# 结果
2020-12-26 01:36:33.975427+00:00

2、通过astimezone()将时区指定为我们想转换的时区,比如东八区(北京时间):

1
2
3
4
5
6
7
# 通过astimezone切换到东八区

beijing = utc_now.astimezone(timezone(timedelta(hours=8)))
print(beijing)

# 结果
2020-12-26 09:36:33.975427+08:00

用同样的方法切到东九区,东京时间:

1
2
3
4
5
6
7
# UTC时区切换到东九区:东京时间

tokyo = utc_now.astimezone(timezone(timedelta(hours=9)))
print(tokyo)

# 结果
2020-12-26 10:36:33.975427+09:00

还可以直接从北京时间切换到东京时间

1
2
3
4
5
6
7
# 北京时间(东八区)直接切换到东京时间(东九区)

tokyo_new = beijing.astimezone(timezone(timedelta(hours=9)))
print(tokyo_new)

# 结果
2020-12-26 10:36:33.975427+09:00

常用时间转化

下面介绍几个工作中用到的时间转化小技巧:

  1. 时间戳转日期
  2. 日期转时间戳
  3. 格式化时间
  4. 指定格式获取当前时间

时间戳转成日期

时间戳转成具体时间,我们需要两个函数:

  • time.localtime:将时间戳转成时间元组形式
  • time.strftime:将时间元组数据转成我们需要的形式
1
2
3
4
5
6
7
8
9
import time
now_timestamp = time.time() # 获取当前时间的时间戳

# 时间戳先转成时间元组,strftime在转成指定格式
now_tuple = time.localtime(now_timestamp)
time.strftime("%Y/%m/%d %H:%M:%S", now_tuple)

# 结果
'2020/12/26 11:19:01'

假设我们指定一个具体的时间戳来进行转换:

1
2
3
4
5
6
7
8
9
10
import time
timestamp = 1608852741 # 指定时间戳

a = time.localtime(timestamp) # 获得时间元组形式数据
print("时间元组数据:",a)
time.strftime("%Y/%m/%d %H:%M:%S", a) # 格式化

# 结果
时间元组数据: time.struct_time(tm_year=2020, tm_mon=12, tm_mday=25, tm_hour=7, tm_min=32, tm_sec=21, tm_wday=4, tm_yday=360, tm_isdst=0)
'2020/12/25 07:32:21'

如果我们不想指定具体的格式,只想获取时间戳对应的时间,直接通过time.ctime即可:

1
2
3
4
5
import time
time.ctime(1608852741)

# 结果
'Fri Dec 25 07:32:21 2020'

日期时间转成时间戳

日期时间转成时间戳格式,我们需要使用两个方法:

  • strptime():将时间转换成时间数组
  • mktime():将时间数组转换成时间戳

通过具体的案例来学习一下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
date = "2020-12-26 11:45:34"

# 1、时间字符串转成时间数组形式
date_array = time.strptime(date, "%Y-%m-%d %H:%M:%S")

# 2、查看时间数组数据
print("时间数组:", date_array)

# 3、mktime时间数组转成时间戳
time.mktime(date_array)

# 结果
时间数组: time.struct_time(tm_year=2020, tm_mon=12, tm_mday=26, tm_hour=11, tm_min=45, tm_sec=34, tm_wday=5, tm_yday=361, tm_isdst=-1)
1608954334.0

格式化时间

工作需求中有时候给定的时间格式未必是我们能够直接使用,所以可能需要进行格式的转换,需要使用两个方法:

  • strptime():将时间转换成时间数组
  • strftime():重新格式化时间

通过案例来进行学习:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import time

old = "2020-12-12 12:28:45"

# 1、转换成时间数组
time_array = time.strptime(old, "%Y-%m-%d %H:%M:%S")

# 2、转换成新的时间格式(20201212-20:28:54)
new = time.strftime("%Y%m%d-%H:%M:%S",time_array) # 指定显示格式

print("原格式时间:",old)
print("新格式时间:",new)

# 结果
原格式时间: 2020-12-12 12:28:45
新格式时间: 20201212-12:28:45

指定格式获取当前时间

为了能够获取到指定格式的当前时间,我们分为3个步骤:

  • time.time():获取当前时间
  • time.localtime():转成时间元组
  • time.strftime():重新格式化时间

通过一个案例来学习:

1
2
3
4
5
6
7
8
9
10
# 1、时间戳
old_time = time.time()
# 2、时间元组
time_array = time.localtime(old_time)
# 3、指定格式输出
new_time = time.strftime("%Y/%m/%d %H:%M:%S", time_array)
print(new_time)

# 结果
2020/12/26 11:56:08

字符串转成datetime64类型

使用的方法是pd.to_datetime

1
df["new_time"] = df["old_time"].apply(lambda x: pd.to_datetime(x,format="%Y%m%d"))

将datetime64[ns]转成字符串

网上找到的一个方法,非常实用

总结

本文通过各种案例详细介绍了Python中关于时间输出和转化的3个模块:calendar、time、datetime,最后总结了4个工作中常用的时间转化技巧,希望对大家掌握Python中的时间输出和转化有所帮助,不再被时间困扰。

本文标题:一文搞定Python中的时间转化

发布时间:2020年12月26日 - 12:12

原始链接:http://www.renpeter.cn/2020/12/26/%E4%B8%80%E6%96%87%E6%90%9E%E5%AE%9APython%E4%B8%AD%E7%9A%84%E6%97%B6%E9%97%B4%E8%BD%AC%E5%8C%96.html

许可协议: 署名-非商业性使用-禁止演绎 4.0 国际 转载请保留原文链接及作者。

Coffee or Tea