time date datetme timestamp 傻傻分不清楚

栏目: Python · 发布时间: 6年前

内容简介:时间格式对于任何一个工程师来说都是绕不开的知识,爬虫工程师同样如此。爬虫工程师要将不同网站的相同类型内容存放在同一个数据表当中,常见的有:在数据库存储的时候,应该选用哪种时间格式合适呢?新建字段的时候是选择 DATE 格式还是 DATETIME 格式?YEAR 又是什么?Python 内置时间函数有 time 和 datetime,什么时候适合用 time ?什么时候选择 datetime 呢?

时间格式对于任何一个工程师来说都是绕不开的知识,爬虫工程师同样如此。爬虫工程师要将不同网站的相同类型内容存放在同一个数据表当中,常见的有:

* 站点 A 的时间格式为 “2018-5”
* 站点 B 的时间格式为 “3天前”
* 站点 C 的时间格式为 “5-10 8:25”
复制代码

在数据库存储的时候,应该选用哪种时间格式合适呢?新建字段的时候是选择 DATE 格式还是 DATETIME 格式?YEAR 又是什么?

Python 内置时间函数有 time 和 datetime,什么时候适合用 time ?什么时候选择 datetime 呢?

Mysql 时间类型

在数据库建表的时候,通常有5中字段类型让人选择: TIME、DATE、DATETIME、TIMESTAMP、YEAR

每种类型的存储空间和时间格式如下:

- TIME类型 :存储空间[3 bytes] - 时间格式[HH:MM:SS] - 时间范围[-838:59:59  到  ~ 838:59:59]
- DATE类型 :存储空间[3 bytes] - 时间格式[YYYY-MM-DD] - 时间范围[1000-01-01 到 9999-12-31] (可以理解为年月日)
- DATETIME类型 :存储空间[8 bytes] - 时间格式[YYYY-MM-DD HH:MM:SS] - 时间范围[1000-01-01 00:00:00 到 9999-12-31 23:59:59] (可以理解为年月日时分秒)
- TIMESTAMP类型 :存储空间[4 bytes] - 时间格式[YYYY-MM-DD HH:MM:SS] - 时间范围[1970-01-01 00:00:01 到 2038-01-19  03:14:07] (以秒为计算)
- YEAR类型 :存储空间[1 bytes] - 时间格式[YYYY] - 时间范围[1901  到  2155](按年计算)
复制代码

YEAR 这样的时间格式用的是比较少的,而 TIME 用的也不多,常见的还是 DATE、DATETIME 和时间戳 TIMESTAMP。

Python 的 time

Python提供了三种时间函数,时间模块 time、基本时间日期模块 datetime 和日历模块 Calendar。Python 的 time 模块下有很多函数可以转换常见日期格式。如函数 time.time() 用于获取当前时间戳:

import time

timestamp = time.time()
print(timestamp, type(timestamp))
复制代码

输出的时间戳是 float 类型:

1544788687.041193 <class 'float'>
复制代码

时间戳单位最适于做日期运算。但是1970年之前的日期就无法以此表示了。太遥远的日期也不行,UNIX和Windows只支持到2038年。Time 模块包含了以下内置函数,既有时间处理的,也有转换时间格式的:

time date datetme timestamp 傻傻分不清楚

Python 的日历

Calendar 函数都是日历相关的,星期一是默认的每周第一天,星期天是默认的最后一天。更改设置需调用calendar.setfirstweekday()函数。模块包含了以下内置函数:

time date datetme timestamp 傻傻分不清楚

日历模块 Calendar 是用的次数比较少的(在爬虫和Django开发的实际应用较少)。出现较多的是 time 模块和 dateteime 模块。那 time 和 datetime 是什么关系呢?

- time模块  --  比较接近底层的
- datetime模块  --  基于time新增了很过功能,提供了更多函数
复制代码

使用对比

1、获取当前时间

import datetime, time

""" 崔庆才丨静觅、韦世东丨奎因 邀你关注微信公众号【进击的Coder】 """
print(time.time())
print(datetime.datetime.now())
复制代码

得到的输出结果是:

1544789253.025471
2018-12-14 20:07:33.025502
复制代码

2、当前时间格式化

import datetime, time

""" 崔庆才丨静觅、韦世东丨奎因 邀你关注微信公众号【进击的Coder】 """
""" time当前时间 """
localtime = time.localtime(time.time())
print("当前时间元组 :", localtime)
print("不格式化:", time.time())
res1 = time.strftime('%Y-%m-%d', localtime)
print("strftime 可以把时间格式化为日期形式 :", res1)
res2 = time.strftime('%Y-%m-%d %H:%M:%S', localtime)
print("strftime 可以把时间转换为日期和时间 :", res2)
# ------------------------------------------------
""" datetime当前时间 """
time_now = datetime.datetime.now()
res3 = datetime.datetime.now().strftime("%Y-%m-%d")
res4 = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
print("不格式化的当前时间:", time_now)
print("datetime 也可以这样用:", res3)
print("datetime 也可以这样用:", res4)
复制代码

得到的结果是:

当前时间元组 : time.struct_time(tm_year=2018, tm_mon=12, tm_mday=14, tm_hour=20, tm_min=18, tm_sec=11, tm_wday=4, tm_yday=348, tm_isdst=0)
不格式化: 1544789891.681039
strftime 可以把时间格式化为日期形式 : 2018-12-14
strftime 可以把时间转换为日期和时间 : 2018-12-14 20:18:11
不格式化的当前时间: 2018-12-14 20:18:11.681079
datetime 也可以这样用: 2018-12-14
datetime 也可以这样用: 2018-12-14 20:18:11
复制代码

这里可以看出这两个模块获得的时间都不是人类容易阅读的,都需要通过strftime函数进行格式化。

3、文本时间转换

这里我指的是爬虫获取的其他网站的时间,通常有几种格式:

  • 长时间 -- 2018-01-06 18:35:05、2018-01-06 18:35
  • 日期 -- 2018-01-06
  • 月时间 -- 2018-01
  • 时间 -- 18:35:05

爬虫得到的时间都是给人阅读的,只不过分隔符不同。在入库的时候,爬虫工程师希望他们的时间格式是统一的,年月日时分秒或者年月日,如果可以就用时间戳,方便计算(年月日时分秒对应年月日时分秒,年月日不可直接转换为年月日时分秒)。

遇到日期类型 2018-01-06 的时间格式,是不可以用函数直接转成长时间 (比如 2018-01-06 18:35:05) 格式的,强行操作会报错。当遇到这种需要将时间格式统一的情况,没有直接操作的办法,只能对时间进行转换。转换又分为两种,相同时间格式转换与不同时间格式转换:

第一种情形

目标:2018-01-06 18:35:05 转换为2018/01/06 18:35:05

它有两种方法可以满足

方法一的逻辑是不同格式的时间转换要先转成时间数组,然后再由时间数组格式化成想要的类型:

import datetime,time

a = "2013-10-10 23:40:00"  # 想要转换成 a = "2013/10/10 23:40:00"

timeArray = time.strptime(a, "%Y-%m-%d %H:%M:%S")
otherStyleTime = time.strftime("%Y/%m/%d %H:%M:%S", timeArray)
print(timeArray)
print(otherStyleTime)
复制代码

从输出结果:

time.struct_time(tm_year=2013, tm_mon=10, tm_mday=10, tm_hour=23, tm_min=40, tm_sec=0, tm_wday=3, tm_yday=283, tm_isdst=-1)
2013/10/10 23:40:00
复制代码

可以看到,先通过 time.strptime 把它转换成时间数组,然后通过 time.strftime 把时间数组格式化成我想要的格式。

方法二,由于最终格式化的时间也是字符串 str,所以当遇到这种情况的时候,还可以直接用 replace 来进行转换:

a = "2013-10-10 23:40:00"  # 想要转换成 a = "2013/10/10 23:40:00"

print(a.replace("-", "/"))
复制代码

输出结果为:

2013/10/10 23:40:00
复制代码

第二种情形

目标:2018-01-06 转换为2018-01-06 18:35:05

它也有两种方法可以满足

它的逻辑是将年月日的字符串拼接上时分秒,然后再按照上面的两种方法进行转换,比如:

a = "2013-10-10 "  # 想要转换成 a = "2013/10/10 23:40:00"
ac = a + "00:00:00"
print(ac.replace("-", "/"))
复制代码

得到输出结果

2013/10/10 00:00:00
复制代码

第三种情形

目标:2018-01-06 18:35:05 转换为2018-01-06

思路与第一种一致,先转换为时间数组,然后再由时间数组进行格式化:

import datetime,time

a = "2013-10-10 23:40:00"  # 想要转换成 a = "2013/10/10"
timeArray = time.strptime(a, "%Y-%m-%d %H:%M:%S")
otherStyleTime = time.strftime("%Y/%m/%d", timeArray)
print(type(timeArray))
print(otherStyleTime)
复制代码

得到结果输出为(可以看到 timeArray 的类型是 time.struct_time):

<class 'time.struct_time'>
2013/10/10
复制代码

4、时间的比较运算

都知道字符串是不可以进行比较计算的,那么我们就需要用到其他的格式进行。time 的 strptime 转换成时间数组是不可以进行运算的,但是 datetime 可以。

第一种,时间格式相同

import datetime,time

d1 = datetime.datetime.strptime('2012-03-05 17:41:20', '%Y-%m-%d %H:%M:%S')
d2 = datetime.datetime.strptime('2012-03-05 16:41:20', '%Y-%m-%d %H:%M:%S')
delta = d1 - d2
print(type(d1))
print(delta.seconds)
print(delta)
复制代码

得到的输出是:

<class 'datetime.datetime'>
3600
1:00:00
复制代码

从结果上可以看到,格式相同的两种时间,可以通过datetime.datetime.strptime进行转换后再运算,在结果中还可以通过.seconds来计算 相差秒数 和通过.days来计算 相差天数

第二种,如果时间格式不一样,但是转换后的类型一样,也是可以比较的:

import datetime,time

d1 = datetime.datetime.strptime('2012/03/05 17:41:20', '%Y/%m/%d %H:%M:%S')

d2 = datetime.datetime.strptime('2012-03-05 16:41:20', '%Y-%m-%d %H:%M:%S')
delta = d1 - d2
print(delta.seconds)
print(delta)
复制代码

这段代码里面时间的字符串形式就不一样,但是通过同样的函数进行转换后就可以比较计算了。

第三种,年月日时分秒与年月日的计算,其实原理是一样的,转换后他们的格式都一样,所以也是可以计算的,2012/03/05 17:41:20与2012-03-05的时间相差:

import datetime,time

d1 = datetime.datetime.strptime('2012/03/05 17:41:20', '%Y/%m/%d %H:%M:%S')
d2 = datetime.datetime.strptime('2012-03-01', '%Y-%m-%d')
delta = d1 - d2
print(delta.days,delta.seconds)
print(delta)
print(type(delta))
复制代码

输出结果是

4 63680
4 days, 17:41:20
<class 'datetime.timedelta'>
复制代码

通过print的结果可以得到几点信息: 不同格式的时间在转化后是可以进行比较运算的 可以通过.days和.seconds来进行天数与时分秒的展示 计算后得到的数据类型是 'datetime.timedelta' 而不是str类型

比如计算3天后的时间:

import datetime,time

now = datetime.datetime.now()
delta = datetime.timedelta(days=3)
n_days = now + delta
print(type(n_days))
print(n_days.strftime('%Y-%m-%d %H:%M:%S'))
复制代码

得到的结果是:

<class 'datetime.datetime'>
2018-01-21 10:26:14
复制代码

用 datetime.timedelta 取得3天时间,然后将当前时间加上3天,得到的是 'datetime.datetime' 类型数据,变成人类阅读的格式则需要 strftime 函数进行格式化,最终得到想要的 2018-01-21 10:26:14。

5、时间戳

把字符串时间转换为时间戳:

import datetime,time

a = "2013-10-10 23:40:00"
# 转换为时间数组
timeArray = time.strptime(a, "%Y-%m-%d %H:%M:%S")
# 转换为时间戳:
timeStamp = time.mktime(timeArray)
print(timeArray)
print(timeStamp)
复制代码

输出结果为:

time.struct_time(tm_year=2013, tm_mon=10, tm_mday=10, tm_hour=23, tm_min=40, tm_sec=0, tm_wday=3, tm_yday=283, tm_isdst=-1)
1381419600.0
复制代码

可以看到time的时间数组与时间戳并不是同一样东西,他们是有区别的

6、strftime与strptime

这两个是 python 中常用的

strftime 函数:

  • 函数接收以时间元组,并返回以可读字符串表示的当地时间,格式由参数 format 决定。
  • time.strftime(format[, t])
  • format -- 格式字符串。t -- 可选的参数t是一个 struct_time 对象。
  • 返回以可读字符串表示的当地时间。
import time

t = (2009, 2, 17, 17, 3, 38, 1, 48, 0)
t = time.mktime(t)
print(time.strftime("%Y-%m-%d %H:%M:%S", time.gmtime(t)))
复制代码

得到结果输出:

2009-02-17 09:03:38
复制代码

strptime() 函数根据指定的格式把一个时间字符串解析为时间元组。 time.strptime(string[, format]) string -- 时间字符串。format -- 格式化字符串。 返回 struct_time 对象。

import datetime,time

d1 = datetime.datetime.strptime('20120305 17:41:20', '%Y%m%d %H:%M:%S')
d2 = datetime.datetime.strptime('2012-03-01', '%Y-%m-%d')
print(d1)
print(d2)
复制代码

得到结果:

2012-03-05 17:41:20
2012-03-01 00:00:00
复制代码

时间格式与入库

前面铺垫了这么多,最终的目的还是需要入库。这里以4种数据库时间类型为例:

  • 字段名 => 数据类型
  • r_time => time
  • r_date => date
  • r_datetime => datetime
  • r_timestamp => timestamp

根据最上方所写的 Mysql 时间类型,可以得出对应的时间格式为:

  • 时间格式 => 数据类型
  • 17:35:05 => time
  • 2018-3-1 => date
  • 2018/3/1 17:35 => datetime
  • 2018/3/1 17:35 => timestamp

time类型

time 类型的格式指定为 17:35:05,不可替换为(17-35-05 或者 17/35/05),会报错

可以简写成 17:35,数据库会自动补全后面的 00,入库后最终数据 17:35:00

如果简写成 17,则入库后变成 00:00:17

当然,如果更奇葩的写法 17:,17:35: 这种是会报错的

date类型

date 类型的格式指定为 2018-3-1 与 2018/3/1,最终入库格式是(2018-03-01),它会自动补全

可以简写成 [18/3/1]、[17/3/1]、[07/3/1]、[97/3/1],数据库会自动补全前面的年份,入库后最终数据 2018-03-01、2017-03-01、2007-03-01、1997-03-01

不可简写成 [2017]、[2017/3],会报错,必须是完整的日期格式

datetime类型

datetime 类型的格式指定为 2018-3-1 17:35:00 和 2018/3/1 17:35:00,最终入库格式是 2018-03-01 17:35:00

它是 date 与 time 的结合,有很多共同特性

可以简写成 [18/3/1 17:35:05]、[17/3/1 17:35]、[07/3/1 17]、[97/3/1 17],数据库会自动补全前面的年份,入库后最终数据 2018-03-01 17:35:05、2017-03-01 17:35:00、2007-03-01 17:00:00、1997-03-01 17:00:00。可以看到它自动将时间格式补全成统一格式,这里与 time 不同的是,如果只写 17 不写分秒,time 会默认将 17 当成秒,这里则是默认当成小时。

与 date 一样,年月日不可省略,必须以年月日格式出现

timestamp类型

根据上面的描述,timestamp的入库格式与datetime是一样的,不同的是时间范围和存储空间,它的格式与用法跟datetime一致


以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

重新理解创业

重新理解创业

周航 / 中信出版集团 / 2018-10-20 / 58.00

易到用车创始人/顺为资本投资合伙人周航,首度复盘20年创业经历,全方位坦陈创业得与失。这不是一本创业成功手册,却是思想的一次出走。 20年创业经历的咀嚼与反思,从战略、品牌、竞争,到流量、领导力、团队管理等,多角度多维度的重新认知,如李开复所言,“都是真刀真枪打出来的经验,值得每一位创业者多读几遍,吸收内化”。 雷军、李开复、徐小平作序,梁建章、张志东、曾鸣推荐。一起来看看 《重新理解创业》 这本书的介绍吧!

Base64 编码/解码
Base64 编码/解码

Base64 编码/解码

Markdown 在线编辑器
Markdown 在线编辑器

Markdown 在线编辑器

HSV CMYK 转换工具
HSV CMYK 转换工具

HSV CMYK互换工具