如何在本地时区打印日期时间?

Posted

技术标签:

【中文标题】如何在本地时区打印日期时间?【英文标题】:How do I print a datetime in the local timezone? 【发布时间】:2010-11-09 19:48:45 【问题描述】:

假设我有一个变量 t 设置为:

datetime.datetime(2009, 7, 10, 18, 44, 59, 193982, tzinfo=<UTC>)

如果我说str(t),我会得到:

'2009-07-10 18:44:59.193982+00:00'

我怎样才能得到一个类似的字符串,除了打印在当地时区而不是UTC?

【问题讨论】:

相关:How to convert a python utc datetime to a local datetime using only python standard library? Python >= 3.6:使用astimezone(),例如datetime.datetime(2010, 4, 27, 12, 0, 0, 0).astimezone().isoformat() -> '2010-04-27T12:00:00+02:00' 【参考方案1】:

此脚本演示了几种使用astimezone() 显示本地时区的方法:

#!/usr/bin/env python3

import pytz
from datetime import datetime, timezone
from tzlocal import get_localzone

utc_dt = datetime.now(timezone.utc)

PST = pytz.timezone('US/Pacific')
EST = pytz.timezone('US/Eastern')
JST = pytz.timezone('Asia/Tokyo')
NZST = pytz.timezone('Pacific/Auckland')

print("Pacific time ".format(utc_dt.astimezone(PST).isoformat()))
print("Eastern time ".format(utc_dt.astimezone(EST).isoformat()))
print("UTC time     ".format(utc_dt.isoformat()))
print("Japan time   ".format(utc_dt.astimezone(JST).isoformat()))

# Use astimezone() without an argument
print("Local time   ".format(utc_dt.astimezone().isoformat()))

# Use tzlocal get_localzone
print("Local time   ".format(utc_dt.astimezone(get_localzone()).isoformat()))

# Explicitly create a pytz timezone object
# Substitute a pytz.timezone object for your timezone
print("Local time   ".format(utc_dt.astimezone(NZST).isoformat()))

它输出以下内容:

$ ./timezones.py 
Pacific time 2019-02-22T17:54:14.957299-08:00
Eastern time 2019-02-22T20:54:14.957299-05:00
UTC time     2019-02-23T01:54:14.957299+00:00
Japan time   2019-02-23T10:54:14.957299+09:00
Local time   2019-02-23T14:54:14.957299+13:00
Local time   2019-02-23T14:54:14.957299+13:00
Local time   2019-02-23T14:54:14.957299+13:00

从 python 3.6 开始,在没有时区对象的情况下调用 astimezone() 默认为本地区域 (docs)。这意味着您无需导入tzlocal,只需执行以下操作:

#!/usr/bin/env python3

from datetime import datetime, timezone

utc_dt = datetime.now(timezone.utc)

print("Local time ".format(utc_dt.astimezone().isoformat()))

【讨论】:

这是最好的答案! 对了,python 3.6支持astimezone()不带tz表示系统本地时间(refer)的特性。 @CodeUnsolved 感谢您澄清在没有 tz 对象的情况下调用 astimezone() 的行为。【参考方案2】:

从 python 3.2 开始,仅使用标准库函数:

u_tm = datetime.datetime.utcfromtimestamp(0)
l_tm = datetime.datetime.fromtimestamp(0)
l_tz = datetime.timezone(l_tm - u_tm)

t = datetime.datetime(2009, 7, 10, 18, 44, 59, 193982, tzinfo=l_tz)
str(t)
'2009-07-10 18:44:59.193982-07:00'

只需要使用l_tm - u_tmu_tm - l_tm,具体取决于您希望显示为UTC 时间的+ 或- 小时。我在 MST,这就是 -07 的来源。更聪明的代码应该能够找出减去的方法。

并且只需要计算一次本地时区。这不会改变。至少在您切换到夏令时之前。

【讨论】:

这不考虑夏令时。 在基本设置中,它使用 UTC 和本地之间的增量作为纪元日期。其他任何事情都不能是“自动的”。在显示最后时间时,如果 当前 日期是 DST,或者如果显示的日期是/曾经/将是 DST,是否要使用 DST?所以这需要由周围的程序逻辑来决定,并在适当的时候调整l_tz。可能通过在 1 月 1 日与当前或目标年份的当前日期或目标日期之间进行类似的增量。【参考方案3】:

前几天我写了这样一段话:

import time, datetime
def nowString():
    # we want something like '2007-10-18 14:00+0100'
    mytz="%+4.4d" % (time.timezone / -(60*60) * 100) # time.timezone counts westwards!
    dt  = datetime.datetime.now()
    dts = dt.strftime('%Y-%m-%d %H:%M')  # %Z (timezone) would be empty
    nowstring="%s%s" % (dts,mytz)
    return nowstring

所以对您来说有趣的部分可能是以“mytz=...”开头的那一行。 time.timezone 返回本地时区,尽管与 UTC 相比符号相反。所以它说“-3600”来表示UTC+1。

尽管它对夏令时(DST,见评论)一无所知,但我还是把它留给那些摆弄time.timezone的人。

【讨论】:

-1。如果您处于使用 DST 的时区,这将有一半的时间返回错误的结果。 time.timezone 包含在 DST 无效时使用的 UTC 偏移量,无论它当前是否有效。【参考方案4】:

认为您应该环顾四周:datetime.astimezone()

http://docs.python.org/library/datetime.html#datetime.datetime.astimezone

另请参阅 pytz 模块 - 它非常易于使用 - 例如:

eastern = timezone('US/Eastern')

http://pytz.sourceforge.net/

例子:

from datetime import datetime
import pytz
from tzlocal import get_localzone # $ pip install tzlocal

utc_dt = datetime(2009, 7, 10, 18, 44, 59, 193982, tzinfo=pytz.utc)
print(utc_dt.astimezone(get_localzone())) # print local time
# -> 2009-07-10 14:44:59.193982-04:00

【讨论】:

那么如何获取当前本地时区? 不是 datetime.datetime(2009, 7, 10, 18, 44, 59, 193982) - 你需要什么? 这个答案是错误的。我住在英格兰,美国/东部不是本地时区。 @Muhail - 不,因为生成的对象不知道日期时间。你不知道你在哪个时区。 @Philluminati: tzlocal.get_localzone() 为您提供当地时区。【参考方案5】:

我使用这个函数datetime_to_local_timezone(),它看起来过于复杂,但我发现没有更简单的函数版本可以将datetime 实例转换为本地时区,就像在操作系统中配置的那样 , 使用 当时有效的 UTC 偏移量

import time, datetime

def datetime_to_local_timezone(dt):
    epoch = dt.timestamp() # Get POSIX timestamp of the specified datetime.
    st_time = time.localtime(epoch) #  Get struct_time for the timestamp. This will be created using the system's locale and it's time zone information.
    tz = datetime.timezone(datetime.timedelta(seconds = st_time.tm_gmtoff)) # Create a timezone object with the computed offset in the struct_time.

    return dt.astimezone(tz) # Move the datetime instance to the new time zone.

utc = datetime.timezone(datetime.timedelta())
dt1 = datetime.datetime(2009, 7, 10, 18, 44, 59, 193982, utc) # DST was in effect
dt2 = datetime.datetime(2009, 1, 10, 18, 44, 59, 193982, utc) # DST was not in effect

print(dt1)
print(datetime_to_local_timezone(dt1))

print(dt2)
print(datetime_to_local_timezone(dt2))

此示例打印四个日期。对于两个时间点,一个在 2009 年 1 月,一个在 2009 年 7 月,每个时间点都在 UTC 和本地时区打印一次时间戳。这里,冬季使用 CET (UTC+01:00),夏季使用 CEST (UTC+02:00),它会打印以下内容:

2009-07-10 18:44:59.193982+00:00
2009-07-10 20:44:59.193982+02:00

2009-01-10 18:44:59.193982+00:00
2009-01-10 19:44:59.193982+01:00

【讨论】:

它看起来像 Python 3.3+ 代码(.timestamp() 方法)在这种情况下,您可以使用更简单的代码:dt.astimezone(tz=None)。也使用timezone.utc 而不是timezone(datetime.timedelta())【参考方案6】:

我认为最好的方法是使用 datetime.tzinfo 文档中定义的 LocalTimezone 类(转到 http://docs.python.org/library/datetime.html#tzinfo-objects 并向下滚动到“示例 tzinfo 类”部分):

假设LocalLocalTimezone 的一个实例

t = datetime.datetime(2009, 7, 10, 18, 44, 59, 193982, tzinfo=utc)
local_t = t.astimezone(Local)

然后str(local_t) 给出:

'2009-07-11 04:44:59.193982+10:00'

这就是你想要的。

(注意:这对您来说可能看起来很奇怪,因为我在澳大利亚新南威尔士州,比 UTC提前小时 10 或 11 小时)

【讨论】:

如果您根据日期时间文档定义了本地,这也可以:str(datetime.datetime.now(tz=Local)) 请注意,这将打印当前有效的 UTC 偏移量的任何使用,这可能与 datetime 实例给出的时间(由于夏令时)。 LocalTimezone 如果基础time 实现不使用历史时区数据库(Windows 尤其属于此类),则过去日期可能会失败。 我认为 astimezone 的参数应该为空:t.astimezone()

以上是关于如何在本地时区打印日期时间?的主要内容,如果未能解决你的问题,请参考以下文章

Log4cpp:在 UTC/GMT 时区打印日期

如何在python烧瓶中获取具有本地时区的模板文件的修改日期

如何在熊猫中使用 read_csv 将时区感知日期时间作为时区天真的本地 DatetimeIndex 读取?

如何将日期/时间从 GMT 转换为本地时区

在 VBA 中,如何以简单的方式将 UTC UNIX 时间戳转换为本地时区日期?

Swift 3 Playground 以本地格式记录日期。如何?