python 1970年之前的时间戳和js中时间戳的统一问题


问题: 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

如此生成的时间戳和身份证号完美匹配。


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM