How do I print a Python datetime in the local timezone?
假设我有一个变量t设置为:
1 | datetime.datetime(2009, 7, 10, 18, 44, 59, 193982, tzinfo=<UTC>) |
如果我说
1 | '2009-07-10 18:44:59.193982+00:00' |
我怎样才能获得类似的字符串,除了以本地时区而不是UTC打印?
认为你应该环顾四周:datetime.astimezone()
http://docs.python.org/library/datetime.html#datetime.datetime.astimezone
另请参阅pytz模块 - 它非常易于使用 - 例如:
1 | eastern = timezone('US/Eastern') |
http://pytz.sourceforge.net/
例:
1 2 3 4 5 6 7 | 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 |
我认为最好的方法是使用
假设
1 2 | t = datetime.datetime(2009, 7, 10, 18, 44, 59, 193982, tzinfo=utc) local_t = t.astimezone(Local) |
然后
1 | '2009-07-11 04:44:59.193982+10:00' |
这就是你想要的。
(注意:这可能看起来很奇怪,因为我在澳大利亚新南威尔士州,比UTC早10或11小时)
此脚本演示了使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 | #!/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 print("Local time {}".format(utc_dt.astimezone(NZST).isoformat())) |
它输出以下内容:
1 2 3 4 5 6 7 8 | $ ./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.2开始,仅使用标准库函数:
1 2 3 4 5 6 7 | 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' |
只需要使用
并且只需要计算一次本地时区。这不会改变。至少在您从/切换到白天时间之前。
我使用这个函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | 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)) |
此示例打印四个日期。在两个时刻,一个在1月,一个在2009年7月,每个时刻,它以UTC格式打印一次,在本地时区打印一次。这里,冬天使用CET(UTC + 01:00),夏天使用CEST(UTC + 02:00),打印如下:
1 2 3 4 5 | 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 |
我前几天写了这样的东西:
1 2 3 4 5 6 7 8 | 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,见评论)一无所知,但我还是留下了这个用于摆弄