问题: 1970年之前的时间戳,python该如何处理呢? 如何与js等处理结果保持一致?
在做接口自动化时遇到如下情况,需要根据身份证号中的出生年月,自动生成出生日期时间戳:
先看下java时间的处理 以1955-05-07为列:
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.text.DateFormat;
import java.util.Calendar;
public class timeTest {
public static void main(String[] args) throws ParseException {
DateFormat df = new SimpleDateFormat("yyyy-MM-dd");
java.util.Date date = df.parse("1955-05-07");
Calendar cal = Calendar.getInstance();
cal.setTime(date);
long timestamp = cal.getTimeInMillis();
System.out.println(timestamp); // -462528000000
}
}
首先大家一定会想到用time模块,简单粗暴易上手,结果:
import time
stamp=time.mktime(time.strptime('1955-05-07', '%Y-%m-%d'))
print(int(stamp))
>>> Traceback (most recent call last):
File "<input>", line 3, in <module>
OverflowError: mktime argument out of range
查阅资料会发现:
- mktime()是localtime()的反函数,localtime根据秒数返回时间戳
- 它的参数是struct_time或完整的9个元组,它返回一个浮点数,可以视为从最早时间戳开始的描述。
- Windows中时间戳是有范围的,参考官方文档,只要不在这个范围内,使用时就会报错
- 文档中提到不能早于midnight, January 1, 1970,不能晚于23:59:59 January 18, 2038
于是通过datetime模块反推,最简单的方法:
import datetime
timestamp = -462528000000
print(datetime.datetime(1970, 1, 1) + datetime.timedelta(milliseconds=timestamp))
>>> 1955-05-06 16:00:00
结果1955-05-06 16:00:00,同样的时间为毛反推出来差了一天,
经查阅资料发现,这个和地区时间有关,中国使用东八区时间,datetime.datetime(1970, 1, 1),只给定年月日,系统默认是1970-1-1 00:00:00
而东八区的时间戳0为:datetime.datetime(1970, 1, 1, 8)
所以将上面的零点换成datetime.datetime(1970, 1, 1, 8)
print(datetime.datetime(1970, 1, 1, 8) + datetime.timedelta(milliseconds=-462528000000))
>>> 1955-05-07 00:00:00
总结一下:windows系统下python 时间模块time和datetime目前还无法直接处理负数时间戳(linux据说可以直接处理),所以只能反推
为了方便使用简单的封装了一下:
def id_card():
"""
随机生成1970年之前的出生日期,时间戳
:return:
"""
days = random.randint(0, 8000)
timestamp = days * 24 * 60 * 60 * -1000
date_tuple = datetime.datetime(1970, 1, 1, 8) + datetime.timedelta(milliseconds=timestamp) # 将时间戳生成时间元组
date_str = date_tuple.strftime('%Y-%m-%d')
return timestamp, date_str
if __name__ == '__main__':
timestamp, id_no = id_card()
print(timestamp, id_no)
>>> -557366400000 629016195205047242
如此生成的时间戳和身份证号完美匹配。