Python3 将本地时间转换成指定时区时间

最近项目进行开发时,接收到一个时间字符串,需要把这个时间字符串转换成指定时区的时间,并计算出纪元时间。找了很多资料文档,介绍的虽然都比较详细,但是不符合我的需求,而且同一个点介绍的情况不一样,觉得有些混乱。经过大量资料查阅并亲自实际操作后终于实现了,这里做一下记录。

参考资料:How To Convert Non-UTC Timestamp Into UNIX Epoch Time In Python

这里分两种情况:1、服务器默认时区和目标时区一致;2、服务器默认时区和目标时区不一致。

1、服务器默认时区与目标时区一致的场合:

这种场合下就没必要去转换时区了,先将利用time模块的time.strptime()将时间转换成datetime时间元组,这样就可以直接使用time模块的time.mktime(datetime时间元组),获得纪元时间。

# 将datetime转换成纪元时间
# @param dt datetime时间
# @param format 时间格式
# @return 纪元时间
def __unix_time(dt, format):
    try:
        # 转换为时间数组
        time_arr = time.strptime(dt, format)
        # 转换为UNIX时间戳
        timestamp = time.mktime(time_arr)

        return timestamp
    except [OverflowError, ValueError]:
        return None

现在来测试一下:

print(__unix_time("2019-07-14 11:23:36", "%Y-%m-%d %H:%M:%S"))

执行结果:

1563074616.0

Process finished with exit code 0

可以使用@在线时间戳转换工具进行计算,计算结果为:1563074616。说明我们的转换是成功的。

2、服务器默认时区和目标时区不一致的场合:

扫描二维码关注公众号,回复: 11515133 查看本文章

这种场合情况稍微复杂一点,但是不要怕,只要有耐心,什么问题都可以解决的。

如果是在中国,那么使用的时区一般都是北京时间,属于东八区,意思就是与世界标准时区时间(格林威治时间)的偏移量为+8,为了保证正确地转换时区,一般遇到情况,先不管那么多,先把本地时间转换成UTC时间,然后拿到UTC时间转换到指定时区时间,这一定是没问题的。关于时区转换的问题,time模块就显得捉襟见肘了,因此需要使用pytz配合datetime。

但是在使用datetime模块的时候值得注意的是:我们转换为本地时间的时候,需要指定时区,但是,实际上,规定的时区时间偏移是不精确的。比如:北京所在的东八区,按照规定,是偏移+8.00时,但是实际上并不是这样。我们可以通过下面的方法来验证:

这里北京所用的时区名称是:Asia/Shanghai,但是他的时区偏移是+8.06,当我们将本地时间转换成UTC时间后,再将他转回来,这个时候会发现与原来的时间相差了6分钟。这是因为使用datetime.datetime时返回的格式是LMT,这不是而标准格式,当转回的时候返回的格式是标准格式CST,这个过程就损失掉了6分钟,为了解决这个问题,记住使用时区对象tz.localize()方法来进行转换,这样就可以了。

等拿到转换时区后的datetime后,使用time.mktime()就可以取得纪元时间了。

下面直接跟代码:

# 将本地时间转换到指定时区时间,并取得纪元时间
# @param dt_str datetime本地时间
# @param l_timezone 本地时区
# @param t_timezone 目标时区
# @param time_format 入力时间格式
# @return 目标时区纪元时间
def __datetime_to_utc_epoch(dt_str, l_timezone, t_timezone, time_format):
    # 本地时区
    local_tz = pytz.timezone(l_timezone)
    # 目标时区
    target_tz = pytz.timezone(t_timezone)
    # 将时间转换成datetime元组
    dt = datetime.strptime(dt_str, time_format)
    # 使用tz.localize()将datetime转换成本地时区时间
    dt = local_tz.localize(dt)
    # 利用datetime.astimezone(tz=timezone)将本地时间转换成目标时区UTC时间
    t_dt_str = str(dt.astimezone(tz=target_tz))[0:19]
    print("UTC 时间: {0}".format(t_dt_str))
    # 利用好time.mktime()将时间转换成纪元时间
    epoch = int(time.mktime(time.strptime(t_dt_str, "%Y-%m-%d %H:%M:%S")))
    print("纪元时间: {0}".format(epoch))

现在测试代码:

print("=" * 50)
    print("北京时区(东八区)- 东京时区(东九区)")
    __datetime_to_utc_epoch("20190714112336", "Asia/Shanghai", "Asia/Tokyo", "%Y%m%d%H%M%S")
    print("=" * 50)
    print("东京时区(东九区)- 东京时区(东九区)")
    __datetime_to_utc_epoch("2019-07-14 11:23:36", "Asia/Tokyo", "Asia/Tokyo", "%Y-%m-%d %H:%M:%S")

运行得到结果:

==================================================

北京时区(东八区)- 东京时区(东九区)

UTC 时间: 2019-07-14 12:23:36

纪元时间: 1563078216

==================================================

东京时区(东九区)- 东京时区(东九区)

UTC 时间: 2019-07-14 11:23:36

纪元时间: 1563074616

Process finished with exit code 0

借助在线转换工具:@国际时区转换 和 @在线时间戳转换工具 进行验证,成功。

下面是整个代码文件:

test_tz.py

import pytz, time
from datetime import datetime


# 将datetime转换成纪元时间
# @param dt datetime时间
# @param format 时间格式
# @return 纪元时间
def __unix_time(dt, format):
    try:
        # 转换为时间数组
        time_arr = time.strptime(dt, format)
        # 转换为UNIX时间戳
        timestamp = time.mktime(time_arr)

        return timestamp
    except [OverflowError, ValueError]:
        return None



# 将本地时间转换到指定时区时间,并取得纪元时间
# @param dt_str datetime本地时间
# @param l_timezone 本地时区
# @param t_timezone 目标时区
# @param time_format 入力时间格式
# @return 目标时区纪元时间
def __datetime_to_utc_epoch(dt_str, l_timezone, t_timezone, time_format):
    # 本地时区
    local_tz = pytz.timezone(l_timezone)
    # 目标时区
    target_tz = pytz.timezone(t_timezone)
    # 将时间转换成datetime元组
    dt = datetime.strptime(dt_str, time_format)
    # 使用tz.localize()将datetime转换成本地时区时间
    dt = local_tz.localize(dt)
    # 利用datetime.astimezone(tz=timezone)将本地时间转换成目标时区UTC时间
    t_dt_str = str(dt.astimezone(tz=target_tz))[0:19]
    print("UTC 时间: {0}".format(t_dt_str))
    # 利用好time.mktime()将时间转换成纪元时间
    epoch = int(time.mktime(time.strptime(t_dt_str, "%Y-%m-%d %H:%M:%S")))
    print("纪元时间: {0}".format(epoch))


if __name__ == "__main__":
    # print(__unix_time("2019-07-14 11:23:36", "%Y-%m-%d %H:%M:%S"))
    print("=" * 50)
    print("北京时区(东八区)- 东京时区(东九区)")
    __datetime_to_utc_epoch("20190714112336", "Asia/Shanghai", "Asia/Tokyo", "%Y%m%d%H%M%S")
    print("=" * 50)
    print("东京时区(东九区)- 东京时区(东九区)")
    __datetime_to_utc_epoch("2019-07-14 11:23:36", "Asia/Tokyo", "Asia/Tokyo", "%Y-%m-%d %H:%M:%S")

猜你喜欢

转载自blog.csdn.net/qq_41221030/article/details/95928953