一、时间、时间戳
时间,是物质的运动、变化的持续性、顺序性的表现,包含时刻和时段两个概念。时间是人类用以描述物质运动过程或事件发生过程的一个参数,确定时间,是靠不受外界影响的物质周期变化的规律。
时间戳(timestamp),一个能表示一份数据在某个特定时间之前已经存在的、 完整的、 可验证的数据,通常是一个字符序列,唯一地标识某一刻的时间。
Unix时间戳(Unix timestamp),或称Unix时间(Unix time)、POSIX时间(POSIX time),是一种时间表示方式,定义为从格林威治时间1970年01月01日00时00分00秒(北京时间1970年01月01日08时00分00秒)起至现在的总毫秒数(在python中默认计算总秒数)。
由于时区的存在,世界上的时间并不完全统一。北京时间比格林威治时间提前8个小时,比美国东部时间提前13个小时。
倒时差:一个人晚上9点从国内坐飞机到伦敦,假设飞了8个小时,他在飞机上睡了8个小时。可是当他下飞机后,他会发现机场大厅的时钟还是晚上9点。由于他刚刚睡了8个小时,所以他到酒店后晚上失眠了,第二天白天了,他开始睡了,从而生物钟被打乱,可能几天缓不过劲来。
时间戳的不一致性:数据中的日期字段date中如果纪录的是一个整数或者浮点数,数据类型极有可能是时间戳,由于存储数据的计算机可能和分析数据的计算机位于不同时区,所以面对同一个时间戳,极有可能存在理解差异,需要分析该时间戳是相对于哪个时刻的时间戳。
2038年问题是指在使用POSIX时间的32位计算机应用程序上,格林尼治时间2038年1月19日凌晨03:14:07(北京时间:2038年1月19日中午11:14:07)之后无法正常工作。
计算机通常用一个10位的整数来描述时间戳对应的总秒数。10位的十进制数最大数为9999999999,一年(365天)的总秒数为31536000,所以9999999999/31536000=317.0979198059361,由于有闰年,时间戳最多可以表示到1970年后的316年左右,即到2286/11/21 01:46:40 会变成11位(10000000000)。但在32位计算机中,通常用一个32位的有符号整数来存储这个时间戳,这样时间戳的二进制数最大就是(01111111 11111111 11111111 11111111)。其后一秒,二进制数字会变为10000000 00000000 00000000 00000000,发生溢出错误,造成系统将时间误解为1901年12月13日20时45分52秒。这很可能会引起软件故障,甚至是系统瘫痪。使用64位二进制数字表示时间的系统(最多可以使用到格林威治时间292,277,026,596年12月04日15时30分08秒)则基本不会遇到这类溢出问题。
现在用Python来验证一下:
from datetime import datetime
int('01111111111111111111111111111111', 2) #将二进制值转换为十进制,输出2147483647
datetime.utcfromtimestamp(2147483647) #datetime.datetime(2038, 1, 19, 3, 14, 7)
可以看到,受计算机存储能力限制,32位有符号二进制整数对应的十进制数最大不是9999999999,而是2147483647,对应时刻为datetime(2038, 1, 19, 3, 14, 7)
二、Python世界中的时间
对于一个时间(时刻),可以有两种视角,一种是计算其距离某一时刻,比如1970年1月1日零时零分经过的秒数总和,即格林威治时间时间戳。另个一种是比较直观的datetime形式(年,月,日,时,分,秒,微秒,时区)。python提供了一个函数:
datetime(year, month, day[, hour[, minute[, second[, microsecond[,tzinfo]]]]]),
此函数可以创建datetime对象,它同时包含date和time对象的所有特性。
其中microsecond为6位数字表示的微秒值,tzinfo参数代表时区。可表示的时间最大值和最小值如下:
max = datetime(9999, 12, 31, 23, 59, 59, 999999)
min = datetime(1, 1, 1, 0, 0)
通常情况下,我们只关注自己的时间即可,比如你手机或手表上的时间,这个时间称之为localtime,比如北京时间早八点整,你不用操心英国、美国现在是几点,他们是睡觉了还是吃饭了。
import pandas as pd
import time
from datetime import datetime
time.time() #获得localtime的时间戳
datetime.now() #datetime.now() 获得当前的localtime,注意不是格林威治时间
pandas中的Timestamp类型与python的datetime类型基本等价:
pd.Timestamp.now()
创建任意时间点:
a = pd.Timestamp('2018-03-16 21:01:34')
b = pd.datetime(2018,3,16,21,1,34)
c = datetime(2018,3,16,21,1,34)
print(a == b == c) #True
print(type(b)) #<class 'datetime.datetime'>
三、时间类型的相互转换
1. 时间戳转datetime
常用场景:分析时需要将数据date字段存储的数字转为直观形式
datetime.fromtimestamp(1580572800.0) #输出:datetime.datetime(2020, 2, 2, 0, 0)
datetime.utcfromtimestamp(1580572800.0) #输出: datetime.datetime(2020, 2, 1, 16, 0)
可以发现同一