Python:如何将日期时间/时间戳从一个时区转换为另一个时区?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31977563/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-19 10:50:12  来源:igfitidea点击:

Python: How do you convert a datetime/timestamp from one timezone to another timezone?

pythondatetimetimezonepytztimedelta

提问by kfan

Specifically, given the timezone of my server (system time perspective) and a timezone input, how do I calculate the system time as if it were in that new timezone (regardless of daylight savings, etc)?

具体来说,鉴于我的服务器的时区(系统时间透视图)和时区输入,我如何计算系统时间,就好像它在新时区中一样(不管夏令时等)?

import datetime
current_time = datetime.datetime.now() #system time

server_timezone = "US/Eastern"
new_timezone = "US/Pacific"

current_time_in_new_timezone = ???

采纳答案by kfan

If you know your origin timezone and the new timezone that you want to convert it to, it turns out to be very straightforward:

如果您知道您的原始时区和要将其转换为的新时区,结果会非常简单:

1) Make a pytz.timezoneobject for both the current timezone and the new timezone e.g. pytz.timezone("US/Pacific"). If you don't know a timezone's official name, you can find a list of all official timezones by simply calling pytz.all_timezones

1)pytz.timezone为当前时区和新时区创建一个对象,例如pytz.timezone("US/Pacific")。如果您不知道时区的官方名称,只需拨打以下电话即可找到所有官方时区的列表pytz.all_timezones

2) Call .localize()using the current timezone's pytz object with your datetime/timestamp as input to localize it to the current timezone. e.g. current_timezone.localize(timestamp)

2).localize()使用当前时区的 pytz 对象和日期时间/时间戳作为输入调用以将其本地化到当前时区。例如current_timezone.localize(timestamp)

3) Finally, call .astimezone()on the newly localized datetime/timestamp from step 2 with the desired new timezone's pytz object as input e.g. localized_timestamp.astimezone(new_timezone).

3) 最后,.astimezone()使用所需的新时区的 pytz 对象作为输入调用步骤 2 中新本地化的日期时间/时间戳,例如localized_timestamp.astimezone(new_timezone).

Done!

完毕!

As a full example:

作为一个完整的例子:

import datetime
import pytz

# a timestamp I'd like to convert
my_timestamp = datetime.datetime.now()

# create both timezone objects
old_timezone = pytz.timezone("US/Eastern")
new_timezone = pytz.timezone("US/Pacific")

# two-step process
localized_timestamp = old_timezone.localize(my_timestamp)
new_timezone_timestamp = timezone_localized_timestamp.astimezone(new_timezone)

# or alternatively, as an one-liner
new_timezone_timestamp = old_timezone.localize(my_timestamp).astimezone(new_timezone) 

Bonus: but if all you need is the current time in a specific timezone, you can conveniently pass that timezone directly into datetime.now() to get the current times directly:

奖励:但如果您只需要特定时区中的当前时间,您可以方便地将该时区直接传递给 datetime.now() 以直接获取当前时间:

datetime.datetime.now(new_timezone)

When it comes to needing timezones conversions generally, I would strongly advise that one should store all timestamps in your database in UTC, which has no daylight savings time (DST) transition. And as a good practice, one should always choose to enable time zone support (even if your users are all in a single time zone!). This will help you avoid the DST transition problem that plagues so much software today.

当谈到通常需要时区转换时,我强烈建议您将所有时间戳以 UTC 格式存储在您的数据库中,它没有夏令时 (DST) 转换。作为一种好的做法,应该始终选择启用时区支持(即使您的用户都在一个时区!)。这将帮助您避免困扰当今众多软件的 DST 转换问题。

Beyond DST, time in software can be generally quite tricky. To get a sense of just how difficult it is to deal with time in software in general, here is a potentially enlightening resource: http://yourcalendricalfallacyis.com

除了夏令时,软件中的时间通常非常棘手。为了大致了解在软件中处理时间是多么困难,这里有一个潜在的启发性资源:http: //yourcalendricalfallacyis.com

Even a seemingly simple operation as converting a datetime/timestamp into a date can become non-obvious. As this helpful documentationpoints out:

即使是将日期时间/时间戳转换为日期的看似简单的操作也可能变得不明显。正如这个有用的文档指出的那样:

A datetime represents a point in time. It's absolute: it doesn't depend on anything. On the contrary, a date is a calendaring concept. It's a period of time whose bounds depend on the time zone in which the date is considered. As you can see, these two concepts are fundamentally different.

日期时间代表一个时间点。这是绝对的:它不依赖于任何东西。相反,日期是一个日历概念。这是一段时间,其界限取决于考虑日期的时区。如您所见,这两个概念有着根本的不同。

Understanding this difference is a key step towards avoiding time-based bugs. Good luck.

了解这种差异是避免基于时间的错误的关键一步。祝你好运。

回答by jfs

How do you convert datetime/timestamp from one timezone to another timezone?

如何将日期时间/时间戳从一个时区转换为另一个时区?

There are two steps:

有两个步骤:

  1. Create an aware datetime objects from the system time and timezonee.g., to get the current system time in the given timezone:

    #!/usr/bin/env python
    from datetime import datetime
    import pytz
    
    server_timezone = pytz.timezone("US/Eastern")
    server_time = datetime.now(server_timezone) # you could pass *tz* directly
    

    Note: datetime.now(server_timezone)works even during ambiguous timese.g., during DST transitions while server_timezone.localize(datetime.now())may fail (50% chance).

    If you are sure that your input time exists in the server's timezone and it is unique then you could pass is_dst=Noneto assert that:

    server_time = server_timezone.localize(naive_time, is_dst=None)
    

    It raises an exception for invalid times.
    If it is acceptable to ignore upto a dayerror (though typically an error due to DST is around an hour) then you could drop is_dstparameter:

    server_time = server_timezone.normalize(server_timezone.localize(naive_time))
    

    .normalize()is called to adjust non-existing times (local time in the gap, during "spring forward" transitions). If the time zone rules haven't changed; your server shouldn't generate non-existing times. See "Can I just always set is_dst=True?"

  2. Convert an aware datetime object to the target timezone tz:

    tz = pytz.timezone("US/Pacific")
    server_time_in_new_timezone = server_time.astimezone(tz)
    
  1. 从系统时间和时区创建一个感知日期时间对象,例如,获取给定时区中的当前系统时间:

    #!/usr/bin/env python
    from datetime import datetime
    import pytz
    
    server_timezone = pytz.timezone("US/Eastern")
    server_time = datetime.now(server_timezone) # you could pass *tz* directly
    

    注意:datetime.now(server_timezone)即使在不明确的时间也能工作,例如在 DST 转换期间,但server_timezone.localize(datetime.now())可能会失败(50% 的几率)。

    如果您确定您的输入时间存在于服务器的时区中并且它是唯一的,那么您可以通过is_dst=None断言:

    server_time = server_timezone.localize(naive_time, is_dst=None)
    

    它引发无效时间的异常。
    如果可以忽略最多一天的错误(尽管通常由于 DST 导致的错误大约是一个小时),那么您可以删除is_dst参数:

    server_time = server_timezone.normalize(server_timezone.localize(naive_time))
    

    .normalize()被调用来调整不存在的时间(间隙中的本地时间,在“spring forward”转换期间)。如果时区规则没有改变;您的服务器不应生成不存在的时间。请参阅“我可以始终设置 is_dst=True 吗?”

  2. 将感知日期时间对象转换为目标时区tz

    tz = pytz.timezone("US/Pacific")
    server_time_in_new_timezone = server_time.astimezone(tz)