問題: 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
如此生成的時間戳和身份證號完美匹配。