Python使用技巧--時區的轉換


技巧:用datetime模塊處理時區轉換,不要用time模塊

time模塊

time模塊只能轉換本地時區的時間,不能轉換其他時區的時間

比如以下例子對本地時區(CST)進行轉換,程序能運行:

time_format = "%Y-%m-%d %H:%M:%S %Z"
time_str = "2021-09-25 15:49:15 CST"
# 將字符串格式轉換成時間結構格式
time_tuple = time.strptime(time_str, time_format)
time_str = time.strftime(time_format, time_tuple)
print(time_str)
# "2021-09-25 15:49:15 CST"

但是如果將CST改成其他時區,比如“EDT”,則程序報錯。

time_format = "%Y-%m-%d %H:%M:%S %Z"
time_str = "2021-09-25 15:49:15 EDT"
# 將字符串格式轉換成時間結構格式
time_tuple = time.strptime(time_str, time_format)
time_str = time.strftime(time_format, time_tuple)
print(time_str)
# ValueError: time data '2021-09-25 15:49:15 EDT' does not match format '%Y-%m-%d %H:%M:%S %Z'

之所以出現這個問題,是因為time模塊本質上仍然要依賴具體的平台而運作。它的行為取決於底層的C函數與宿主操作系統之間的協作方式,這導致該模塊沒辦法穩定地處理多個時區,所以不要用這個模塊來編寫時區轉換這方面的代碼。如果一定要使用,那最多使用在UTC時間和宿主計算機的當地時區之間的轉換,涉及其他時區的轉換操作,最好還是通過datetime模塊來做。

datetime模塊

使用datetime模塊時將GMT(UTC+0)時間轉換成本地時間(CST時區,比GMT時區多8個小時):

time_format = "%Y-%m-%d %H:%M:%S"
time_str = "2021-09-25 15:49:15"
# 將字符串時間格式轉換成datetime格式
now = datetime.datetime.strptime(time_str, time_format)
now_utc = now.replace(tzinfo=datetime.timezone.utc)
now_local = now_utc.astimezone()
print(now_local)
# 2021-09-25 23:49:15+08:00

當使用datetime模塊時,可以把一個時區的本地時間可靠地轉化成另一個時區的本地時間。但需要配合pytz模塊進行使用。因為datetime的這套時區操作機制必須通過tzinfo類與相關的方法來運作,而系統在安裝python的時候,並不會默認安裝UTC之外的時區定義信息。

pytz的安裝,可通過pip進行安裝。一般把一個時區的本地時間轉化成另一個時區的本地時間的步驟是:

  1. 把要轉換的時間轉換成GMT(UTC+0)時間
  2. 把GMT時間轉化成另一個時區的本地時間

把要轉換的時區("Asia/Shanghai")轉換成GMT時區

import pytz
import datetime

time_str = "2021-09-25 15:49:15"
# 將字符串時間格式轉換成datetime形式
old_dt = datetime.datetime.strptime(time_str, time_format)

# 將源時區的datetime形式轉換成GMT時區的datetime形式
dt = pytz.timezone("Asia/Shanghai").localize(old_dt)
utc_dt = pytz.utc.normalize(dt.astimezone(pytz.utc))
print(utc_dt)
# 2021-09-25 15:49:15+00:00

把GMT時間轉化成另一個時區("Europe/London")的本地時間

_timezone = pytz.timezone("Europe/London")
new_dt = _timezone.normalize(utc_dt.astimezone(_timezone))
print(new_dt)
# 2021-09-25 08:49:15-07:00

以下是封裝好的方法:

import datetime
import pytz

def timezone_change(time_str, src_timezone, dst_timezone=None, time_format=None):
    """
    將任一時區的時間轉換成指定時區的時間
    如果沒有指定目的時區,則默認轉換成當地時區

    :param time_str:
    :param src_timezone: 要轉換的源時區,如"Asia/Shanghai", "UTC"
    :param dst_timezone: 要轉換的目的時區,如"Asia/Shanghai", 如果沒有指定目的時區,則默認轉換成當地時區
    :param dst_timezone: 時間格式
    :return: str, 字符串時間格式
    """
    if not time_format:
        time_format = "%Y-%m-%d %H:%M:%S"

    # 將字符串時間格式轉換成datetime形式
    old_dt = datetime.datetime.strptime(time_str, time_format)

    # 將源時區的datetime形式轉換成GMT時區(UTC+0)的datetime形式
    dt = pytz.timezone(src_timezone).localize(old_dt)
    utc_dt = pytz.utc.normalize(dt.astimezone(pytz.utc))

    # 將GMT時區的datetime形式轉換成指定的目的時區的datetime形式
    if dst_timezone:
        _timezone = pytz.timezone(dst_timezone)
        new_dt = _timezone.normalize(utc_dt.astimezone(_timezone))
    else:
        # 未指定目的時間,默認轉換成當地時區
        new_dt = utc_dt.astimezone()
    # 轉換成字符串時間格式
    return new_dt.strftime(time_format)

方法的使用:

print(timezone_change("2021-09-25 15:49:15", src_timezone="Asia/Shanghai", dst_timezone="Europe/London"))

# 北京時間比倫敦時間多7小時
# 2021-09-25 08:49:15


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM