python| python中日期時間處理

隨著得物越做越大越做越強, 國際化的腳步也越來越快. 國際化給程序帶來2大類需要處理的問題: 語言日期時間. 這篇主要聊 日期時間處理.

詞匯 abbr

很多問題往往只是語言的迷霧, 穿透語言表達的概念和定義, 就能解決很多問題.

  • area.地區(qū) i18n.國際化.zh_CN.語言代碼(iso639).國家代碼(iso3166) i10n.本地化
  • dt.datetime.日期時間 date.日期 time.時間
  • tz.timezone.時區(qū) UTC.協(xié)調(diào)世界時=GMT.格林尼治標準時.gmt loc.localtime.localWallClockTime DST.夏令時.人為
    • CST.中國標準時間=PRC=Asia/Shanghai=+0800=東八區(qū)
    • EST.美國東部標準時間 EDT.美國東部夏令時
  • ts.timestamp.時間戳
  • fmt.fromat.日期時間的顯示格式

后文遇到相關詞匯可以直接對照來看.

最佳實踐 BestPractice

The preferred way of dealing with times is to always work in UTC, converting to localtime only when generating output to be read by humans. -- https://pypi.org/project/pytz

  • 簡單概括: 在處理時間問題時, 一直使用 UTC, 只在需要展示時按照對應地區(qū)進行處理. gmt? loc?
    • 只使用包含時區(qū)的時期時間數(shù)據(jù)
    • ts.時間戳 即 UTC, 需要增加 tz 信息進行 fmt
    • 處理時保持一致性: gmt 歸 gmt, loc 歸 loc

py 中相關包與函數(shù)

在進入代碼之前, 約定 本地地區(qū)CST.中國標準時間.

  • 包: time datetime pytz calendar
    • strptime: str-parse-time
    • strftime: str-format-time
  • 相關日期時間表示: ts.時間戳 class time.struct_time(后面簡寫為 st) class datetime.datetime(后面簡寫為 dt) str.fmt
    • ts
      • st>ts: calendar.timegm(gmt_st) time.mktime(loc_st)
      • dt>ts: dt.timestamp()
    • st
      • ts>st: gmt_st=time.gmtime() loc_st=time.localtime()
      • dt>st: dt.timetuple()
      • str>st: time.strptime(str, fmt)
    • dt
      • ts>dt: datetime.fromtimestamp(ts, tz=utc) datetime.fromtimestamp(ts, tz=cst)
        • datetime.now(tz=utc)使用當前時間作為ts
        • datetime.today() 也使用當前時間作為ts, 但是無時區(qū)信息, 不建議使用
      • str>dt: dt.strptime(str, fmt)
    • str
      • st>str: time.strftime(fmt, st)
      • dt>str: dt.strftime(fmt)
  • gmt 歸 gmt
    • time.gmtime() calendar.timegm()
    • utc=pytz.utc
  • loc 歸 loc: 以 CST 為例
    • time.localtime() time.mktime()
    • time.zone=-28800 cst=pytz.timezone('PRC')
      py中不同時間表示

關于時期時間的顯示 format

查看 formt 文檔:

[圖片上傳失敗...(image-90d990-1634529818435)]

簡單示例:

import time

fmt = '%Y-%m-%d %H:%M:%S %Z%z' # 'date time timezone`
s = time.strftime(fmt, time.localtime()) # '2021-10-17 01:11:22 CST+0800'
print(s)

關于時間戳

  • 簡單處理, 約定: ts.時間戳使用int, 精確到
  • 重要的事情再強調(diào)一遍: ts.時間戳 都是 UTC 下的, 需要時區(qū)信息 fmt 成 datetime str
-0800 UTC CST=+0800
ts.offset 28800s 0 -28800s
同一時刻ts相等 ts ts ts
相同日期時間的ts ts+offset ts+offset ts+offset

當前 ts:

import calendar
import time

ts = int(time.time()) # 1634447629
loc_ts = int(time.mktime(time.localtime())) # 1634447629
print(ts, loc_ts)

指定時刻的 ts:

import calendar
import time

fmt = '%Y-%m-%d %H:%M:%S %Z%z'
st = time.strptime('2021-10-17 01:11:22 CST+0800', fmt)
ts = calendar.timegm(st) # 1634433082
loc_ts = int(time.mktime(st)) # 1634433082
print(ts, loc_ts)

同一時刻

  • 同一個時刻: ts 相等, st/dt 表示的時刻相同, str 根據(jù) fmt 變化
import calendar
import time
from datetime import datetime

import pytz

utc = pytz.utc  # utc.zone
cst = pytz.timezone('PRC')  # CST.中國標準時間=PRC=Asia/Shanghai

fmt_datetime = '%Y-%m-%d %H:%M:%S'

# 同一個時刻: ts 相等, st/dt 表示的時刻相同, str 根據(jù) fmt 變化
# ts>st
gmt_st = time.gmtime()
loc_st = time.localtime()
# st>ts ts=gmt_ts=loc_ts
ts = int(time.time())
gmt_ts = calendar.timegm(gmt_st)
loc_ts = int(time.mktime(loc_st))
# ts>dt
gmt_dt = datetime.now(tz=utc)
loc_dt = datetime.now(tz=cst)
gmt_dt2 = datetime.today().astimezone(tz=utc)
loc_dt2 = datetime.today().astimezone(tz=cst)
gmt_ts2dt = datetime.fromtimestamp(ts, tz=utc)
loc_ts2dt = datetime.fromtimestamp(ts, tz=cst)
# dt>ts
gmt_dt_ts = int(gmt_dt.timestamp())
loc_dt_ts = int(loc_dt.timestamp())
# dt>st
gmt_dt_st = gmt_dt.timetuple()
loc_dt_st = loc_dt.timetuple()

# fmt_datetime: 不含時區(qū)的日期時間字符串
# st/dt>str
gmt_str = time.strftime(fmt_datetime, gmt_st)
loc_str = time.strftime(fmt_datetime, loc_st)
gmt_dt_str = gmt_dt.strftime(fmt_datetime)
loc_dt_str = loc_dt.strftime(fmt_datetime)
# str>st: 無時區(qū), 不建議使用
gmt_str2st = time.strptime(gmt_str, fmt_datetime)
loc_str2st = time.strptime(loc_str, fmt_datetime)
# str>ts
gmt_str2ts = calendar.timegm(time.strptime(gmt_str, fmt_datetime))
loc_str2ts = int(time.mktime(time.strptime(loc_str, fmt_datetime)))
# str>dt
gmt_str2dt = datetime.strptime(loc_str, fmt_datetime).astimezone(tz=utc)  # ?
gmt_str2dt2 = datetime.strptime(gmt_str, fmt_datetime).astimezone(tz=utc)  # ?
loc_str2dt = datetime.strptime(loc_str, fmt_datetime).astimezone(tz=cst)
py日期時間: 同一時刻

相同日期時間

  • 相同零點時間, 比如 本地時間零點 2021-10-18 00:00:00
import time
from datetime import datetime

import pytz

utc = pytz.utc  # utc.zone
cst = pytz.timezone('PRC')  # CST.中國標準時間=PRC=Asia/Shanghai
fmt_date = '%Y-%m-%d'

# 相同日期時間: 當日零點
# fmt_datetime 相同: 當日零點
ts = int(time.time())
offset = time.timezone
gmt_ts_zero = ts - ts % 86400
loc_ts_zero = gmt_ts_zero + time.timezone
gmt_dt_zero = datetime.fromtimestamp(gmt_ts_zero).astimezone(tz=utc)
loc_dt_zero = datetime.fromtimestamp(loc_ts_zero).astimezone(tz=cst)
gmt_str_zero = time.strftime(fmt_date, time.gmtime(gmt_ts_zero))
loc_str_zero = time.strftime(fmt_date, time.localtime(loc_ts_zero))
loc_dt2str_zero = datetime.now(tz=cst).date()
py 相同零點日期時間
  • 相同零點時間: 某日零點時的 date 與 ts
import calendar
import time

fmt = '%Y-%m-%d %H:%M:%S %Z%z'
fmt_date = '%Y-%m-%d'

st = time.strptime('2021-10-17 01:11:22 CST+0800', fmt)
ts = calendar.timegm(st) # 1634433082
print(ts)

ts = ts - ts % 86400  # '2021-10-17 00:00:00 +0000'
d = time.strftime(fmt_date, time.gmtime(ts))
loc_d = time.strftime(fmt_date, time.localtime(ts))
print(ts, d, loc_d)

offset = time.timezone  # -28800
loc_date_ts = ts - offset  # '2021-10-16 16:00:00 +0000' '2021-10-17 00:00:00 +0800'
print(offset, loc_date_ts)
  • 任一相同日期時間字符串
import calendar
import time
from datetime import datetime

import pytz

utc = pytz.utc  # utc.zone
cst = pytz.timezone('PRC')  # CST.中國標準時間=PRC=Asia/Shanghai
s = '2021-10-18 10:57:10'
fmt_datetime = '%Y-%m-%d %H:%M:%S'
st = time.strptime(s, fmt_datetime)  # 無時區(qū)信息, 不建議使用
gmt_ts = calendar.timegm(st)
loc_ts = int(time.mktime(st))  # loc_ts=gmt_ts+time.zone
gmt_dt = datetime.strptime(s, fmt_datetime).astimezone(tz=utc)
loc_dt = datetime.strptime(s, fmt_datetime).astimezone(tz=cst)
py 任一相同日期時間

時區(qū)的那些事兒

  • py 中使用 pytz 設置時區(qū)
import pytz

utc = pytz.utc  # utc.zone
cst = pytz.timezone('PRC')  # CST.中國標準時間=PRC=Asia/Shanghai
print(pytz.all_timezones)  # 查看時區(qū)

更詳細的 timezone 信息: https://en.wikipedia.org/wiki/Time_zone

  • 時間差(秒)轉timezone
import time
from datetime import datetime, timezone, timedelta

seconds = 28800
ts = int(time.time())
tz = timezone(timedelta(seconds=seconds))
dt = datetime.fromtimestamp(ts, tz)
s = dt.strftime('%Y-%m-%d %H:%M:%S')
py 時間差(秒)轉timezone
  • py 中修改本地時區(qū)
import os
import time

import pytz

cst_off = time.timezone # -28800
os.environ['TZ'] = 'UTC'
time.tzset()
off = time.timezone
print(cst_off, off) # 0

寫在最后

再強調(diào)下最佳實踐:

  • 所有處理都在 UTC 下, 只在需要 fmt 時轉成對應時區(qū)
  • ts 即 UTC, 需要 tz 信息進行 fmt
  • 不建議使用不帶時區(qū)信息的日期時間表示格式(st dt str)
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末憎兽,一起剝皮案震驚了整個濱河市氢橙,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖匣掸,帶你破解...
    沈念sama閱讀 212,718評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件霸琴,死亡現(xiàn)場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機布隔,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,683評論 3 385
  • 文/潘曉璐 我一進店門离陶,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人衅檀,你說我怎么就攤上這事招刨。” “怎么了哀军?”我有些...
    開封第一講書人閱讀 158,207評論 0 348
  • 文/不壞的土叔 我叫張陵沉眶,是天一觀的道長。 經(jīng)常有香客問我杉适,道長沦寂,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 56,755評論 1 284
  • 正文 為了忘掉前任淘衙,我火速辦了婚禮传藏,結果婚禮上,老公的妹妹穿的比我還像新娘彤守。我一直安慰自己毯侦,他們只是感情好,可當我...
    茶點故事閱讀 65,862評論 6 386
  • 文/花漫 我一把揭開白布具垫。 她就那樣靜靜地躺著侈离,像睡著了一般。 火紅的嫁衣襯著肌膚如雪筝蚕。 梳的紋絲不亂的頭發(fā)上卦碾,一...
    開封第一講書人閱讀 50,050評論 1 291
  • 那天,我揣著相機與錄音起宽,去河邊找鬼洲胖。 笑死,一個胖子當著我的面吹牛坯沪,可吹牛的內(nèi)容都是我干的绿映。 我是一名探鬼主播,決...
    沈念sama閱讀 39,136評論 3 410
  • 文/蒼蘭香墨 我猛地睜開眼腐晾,長吁一口氣:“原來是場噩夢啊……” “哼叉弦!你這毒婦竟也來了?” 一聲冷哼從身側響起藻糖,我...
    開封第一講書人閱讀 37,882評論 0 268
  • 序言:老撾萬榮一對情侶失蹤淹冰,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后巨柒,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體樱拴,經(jīng)...
    沈念sama閱讀 44,330評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡凝颇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,651評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了疹鳄。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拧略。...
    茶點故事閱讀 38,789評論 1 341
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖瘪弓,靈堂內(nèi)的尸體忽然破棺而出垫蛆,到底是詐尸還是另有隱情,我是刑警寧澤腺怯,帶...
    沈念sama閱讀 34,477評論 4 333
  • 正文 年R本政府宣布袱饭,位于F島的核電站,受9級特大地震影響呛占,放射性物質發(fā)生泄漏虑乖。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 40,135評論 3 317
  • 文/蒙蒙 一晾虑、第九天 我趴在偏房一處隱蔽的房頂上張望疹味。 院中可真熱鬧,春花似錦帜篇、人聲如沸糙捺。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,864評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽洪灯。三九已至,卻和暖如春竟痰,著一層夾襖步出監(jiān)牢的瞬間签钩,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 32,099評論 1 267
  • 我被黑心中介騙來泰國打工坏快, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留铅檩,地道東北人。 一個月前我還...
    沈念sama閱讀 46,598評論 2 362
  • 正文 我出身青樓假消,卻偏偏與公主長得像柠并,于是被迫代替她去往敵國和親岭接。 傳聞我的和親對象是個殘疾皇子富拗,可洞房花燭夜當晚...
    茶點故事閱讀 43,697評論 2 351

推薦閱讀更多精彩內(nèi)容