在 Python 中正確處理時間,只需這樣做

在 Python 的世界,時間是什么

不光是在 Python 的世界,在計算機世界,時間的表示都是混亂的。

首先,有Unix時間戳, 然后還有 UTC( 雖然只是一種標準 ), GMT等等, 不僅如此, 還有各種時區的概念( 世界上有好幾百種時區, 比如美國, 各個州定義各種時區 )。 另外, 矯情的美國人還定義了夏令時( DST )這種奇怪的東西。

怎一個亂字了得。

與時間相關的標準庫 & 三方庫

在 Python 的標準庫里面,與時間相關的標準庫有:

  1. time
  2. datetime
  3. calendar

處理時間的第三方庫有:

  1. dateutil (推薦)
  2. pytz

其中,標準庫提供的 API 繁多且混亂,各種不一致,每次使用都需要臨時去查文檔,每次使用,給人帶來的都是痛苦。

處理時間(元數據的思想)

什么是元數據呢?

最純粹,最干凈的數據。舉個例子,在 Excel 中,你認為最重要的是什么呢? 肯定是那些一行行干干凈凈的數據。有了它們,我們就可以做出各種漂亮的圖表,以及在這一堆數據上面做各種分析。這樣的數據有什么特點?一是干凈,應該是純粹的,不帶其他修飾的;二是粒度足夠細,不能在往下進行拆分。

在 Python 中表示某個時間,你可以用 Unix時間戳, 也可以用datetime這種面向對象感十足的,也可以用「適合人類閱讀的字符串形式」。對應到上面的例子,誰是我們的選擇?

當然是Unix時間戳了。因為它有如下特點:

  1. 足夠純粹(從 1970/1/1 以來的秒數,而且是絕對偏移量)
  2. 沒有任何多余的含義(就是一個絕對偏移量)

使用時間戳,從一開始就避免各種時區問題,因為它是絕對的。另外,處理時間戳是一件方便且容易的事情。

特別是存儲數據庫,直接存成時間戳就行了(BITINT 就可以搞定), 再也不用和各種 DateTime 打交道了,避免了許許多多麻煩。

如何用呢?

  1. 在程序中,使用時間戳;
  2. 當需要展示給用戶時,轉化成字符串;
  3. 在其他需要的情況,轉化成類似 datetime 這種對象

下面結合標準庫 API 來說明,順便給混亂的標準庫 API 總結下,梳理出那些重要的 API 。

# 保持和 JS 一致,統一放大到毫秒級別
def now_timestamp():
    return int(time.time() * 1000)

# 時間戳轉化成時間字符串,展示給用戶
def timestamp2str(ts, fmt=None):
    if fmt is None:
        fmt = '%Y/%m/%d %H:%M:%S'

    timetuple = time.localtime(ts)
    return time.strftime(fmt, timetuple)


def datetime2timestamp(dt, is_utc=True):
    if is_utc:
        ts = time.mktime(dt.utctimetuple())
    else:
        ts = time.mktime(dt.timetuple())
    return ts


# datetime 對象轉化成 ISO8601 格式的時間字符串
def datetime2iso8601(dt):
    return dt.isoformat()


def timestamp2iso8601(ts):
    dt = timestamp2datetime(ts)
    return datetime2iso8601(dt)


def timestamp2datetime(ts):
    return datetime.fromtimestamp(ts)


def datetime2str(dt, fmt):
    return dt.strftime(fmt)


def timestr2datetime(time_str, fmt='%Y-%m-%dT%H:%M:%S'):
    return datetime.strptime(time_str, fmt)


def timestr2timestamp(time_str):
    dt = timestr2datetime(time_str)
    return datetime2timestamp(dt)

第三方庫又能干什么

第三方庫中,只推薦 dateutil (主要因為使用得熟),主要有以下原因:

  1. 強大(你所考慮的事情,它都考慮好了)
  2. API 簡潔且一致,能讓人減少很多心智負擔

API 誰都能寫,但是 API 的法則從來都是宜精不宜多,寫出容易使用,符合直覺,拓展性好,抽象性強的 API 可不是容易的事情,少許的幾個 API 就能滿足你全部的需要,還有比這更爽的事情嗎?

如果用標準庫不爽了,那就用 dateutil 吧。

關于 dateutil 的使用,其官方文檔有非常詳盡的例子,在此不贅述了。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容