Python:给定当前 UTC 时间,您如何确定特定时区一天的开始和结束时间?

2022-01-16 00:00:00 python datetime timezone utc

问题描述

我正在使用 Google App Engine,我了解到时区固定为 UTC.我想确定用户本地时区当天的开始和结束时间.所以基本上,给定 UTC 的当前时间,您如何确定当天的开始和结束时间,同时考虑夏令时转换.

我有一些笨拙的示例代码.请注意,我意识到如果我手动指定日期,我也可以指定明天的日期,但它们是示例,我想以编程方式确定它.我的主要问题是,如果我将 timedelta 添加到具有时区的日期时间,然后对其进行规范化(就像 pytz 文档中建议的那样),我会得到一个在夏令时切换期间休息一小时的日期时间.

代码中没有提到,但最终目的是将这些时间转换回 UTC,这就是了解时区的重要性.

#!/usr/bin/python导入日期时间从 pytz.gae 导入 pytzhobart_tz = pytz.timezone('澳大利亚/霍巴特')utc_dt = pytz.utc.localize(datetime.datetime.utcnow())hobart_dt = utc_dt.astimezone(hobart_tz)# 为一天的开始创建一个新的日期时间,并在其中添加一天以获得明天.today_start = datetime.datetime(hobart_dt.year, hobart_dt.month, hobart_dt.day)today_start = hobart_tz.localize(today_start)today_end = hobart_tz.normalize(today_start + datetime.timedelta(days=1))打印今天:",今天开始打印'下一个:',今天结束打印# 给出:# 今天:2011-08-28 00:00:00+10:00# 下一个:2011-08-29 00:00:00+10:00# 但是说今天是夏令时转换.# 正常化后,我们要休息一个小时.dst_finish_2011 = datetime.datetime(2011, 4, 3) # 这将来自 hobart_dtdst_finish_2011 = hobart_tz.localize(dst_finish_2011)下一个 = hobart_tz.normalize(dst_finish_2011 + datetime.timedelta(days=1))打印 '2011-04-03:', dst_finish_2011print '2011-04-04:', next # 预计 2011-04-04 00:00:00+10:00打印# 给出# 2011-04-03: 2011-04-03 00:00:00+11:00# 2011-04-04: 2011-04-03 23:00:00+10:00 (错误)dst_start_2011 = datetime.datetime(2011, 10, 2) # 这将来自 hobart_dtdst_start_2011 = hobart_tz.localize(dst_start_2011)下一个 = hobart_tz.normalize(dst_start_2011 + datetime.timedelta(days=1))打印 '2011-10-02:', dst_start_2011print '2011-10-03:', next # 预计 2011-10-03 00:00:00+11:00打印# 给出# 2011-10-02: 2011-10-02 00:00:00+10:00# 2011-10-03: 2011-10-03 01:00:00+11:00 (错误)# 我想我们可以忽略时区并本地化 *after* ?dst_finish_2011 = datetime.datetime(2011, 4, 3) # 这将来自 hobart_dt下一个 = dst_finish_2011 + datetime.timedelta(days=1)# 现在本地化dst_finish_2011 = hobart_tz.localize(dst_finish_2011)下一个 = hobart_tz.localize(下一个)打印 '2011-04-03:', dst_finish_2011print '2011-04-04:', next # 预计 2011-04-04 00:00:00+10:00打印# 给出# 2011-04-03: 2011-04-03 00:00:00+11:00# 2011-04-04: 2011-04-04 00:00:00+10:00

解决方案

在知道UTC时间的情况下,找出当地时区一天的开始时间(午夜)和一天的结束时间(明天):

p>

#!/usr/bin/env python从日期时间导入日期时间、时间、时间增量导入 pytz # $ pip install pytzfrom tzlocal import get_localzone # $ pip install tzlocaltz = get_localzone() # 获取本地时区为 pytz.timezonenow = datetime.now(pytz.utc) # 一些 UTC 时间dt = now.astimezone(tz) # 本地时区的同一时间today = dt.date() # 今天在本地时区(原始日期对象)午夜 = datetime.combine(today, time()) # 本地时区的午夜aware_midnight = tz.localize(midnight, is_dst=None) # 引发异常# 用于模棱两可的或# 不存在# 次明天 = 午夜 + timedelta(1)意识到明天= tz.localize(明天,is_dst=None)def print_time(aware_dt, fmt="%Y-%m-%d %H:%M:%S %Z%z"):打印(aware_dt.strftime(fmt))utc_dt = aware_dt.astimezone(pytz.utc) # UTC 时间打印(utc_dt.strftime(fmt))print_time(aware_midnight)print_time(aware_tomorrow)

输出

2014-09-01 00:00:00 EST+10002014-08-31 14:00:00 UTC+00002014-09-02 00:00:00 EST+10002014-09-01 14:00:00 UTC+0000

另见,

  • 如何获取给定时区的午夜"UTC 时间? -- 只有午夜(没有明天)
  • 如何从 python 日期中减去一天? -- 关于一天前和昨天的差异
  • python - datetime with timezone to epoch -- 演示产生错误答案是多么容易(对于某些日期, 时区).

I'm playing around with Google App Engine and I learned that the timezone is fixed to UTC. I want to determine the start and end time of the current day for the user's local timezone. So basically, given the current time in UTC, how do you determine the start and end time of the current day, taking into account daylight savings changeovers.

I have some clunky example code. Please note that I realise that if I'm manually specifying a date, I could specify tomorrow's date as well, but they are examples and I want to determinte it programatically. My main problem is that if I add a timedelta to a datetime with a timezone and then normalise it (like it is suggested in the pytz docs) I get a datetime which is an hour off during daylight savings switchovers.

Not mentioned in the code, but ultimately the aim is to convert these times back to UTC which is why it's important to be timezone aware.

#!/usr/bin/python

import datetime
from pytz.gae import pytz

hobart_tz = pytz.timezone('Australia/Hobart')

utc_dt = pytz.utc.localize(datetime.datetime.utcnow())
hobart_dt = utc_dt.astimezone(hobart_tz)

# create a new datetime for the start of the day and add a day to it to get tomorrow.
today_start = datetime.datetime(hobart_dt.year, hobart_dt.month, hobart_dt.day)
today_start = hobart_tz.localize(today_start)
today_end = hobart_tz.normalize(today_start + datetime.timedelta(days=1))
print 'today:', today_start
print ' next:', today_end
print
# gives:
# today: 2011-08-28 00:00:00+10:00
# next: 2011-08-29 00:00:00+10:00

# but say today is a daylight savings changeover.
# after normalisation, we are off by an hour.

dst_finish_2011 = datetime.datetime(2011, 4, 3)  # this would come from hobart_dt
dst_finish_2011 = hobart_tz.localize(dst_finish_2011)
next = hobart_tz.normalize(dst_finish_2011 + datetime.timedelta(days=1))
print '2011-04-03:', dst_finish_2011
print '2011-04-04:', next   # expect 2011-04-04 00:00:00+10:00
print
# gives
# 2011-04-03: 2011-04-03 00:00:00+11:00
# 2011-04-04: 2011-04-03 23:00:00+10:00 (wrong)

dst_start_2011 = datetime.datetime(2011, 10, 2)  # this would come from hobart_dt
dst_start_2011 = hobart_tz.localize(dst_start_2011)
next = hobart_tz.normalize(dst_start_2011 + datetime.timedelta(days=1))
print '2011-10-02:', dst_start_2011
print '2011-10-03:', next   # expect 2011-10-03 00:00:00+11:00
print
# gives
# 2011-10-02: 2011-10-02 00:00:00+10:00
# 2011-10-03: 2011-10-03 01:00:00+11:00 (wrong)

# I guess we could ignore the timezone and localise *after* ?

dst_finish_2011 = datetime.datetime(2011, 4, 3)  # this would come from hobart_dt
next = dst_finish_2011 + datetime.timedelta(days=1)
# now localise
dst_finish_2011 = hobart_tz.localize(dst_finish_2011)
next = hobart_tz.localize(next)
print '2011-04-03:', dst_finish_2011
print '2011-04-04:', next   # expect 2011-04-04 00:00:00+10:00
print
# gives
# 2011-04-03: 2011-04-03 00:00:00+11:00
# 2011-04-04: 2011-04-04 00:00:00+10:00

解决方案

To find out the start time of the day (midnight) and the end time of the day (tomorrow) in the local timezone, knowing UTC time:

#!/usr/bin/env python
from datetime import datetime, time, timedelta
import pytz # $ pip install pytz
from tzlocal import get_localzone # $ pip install tzlocal

tz = get_localzone() # get the local timezone as pytz.timezone
now = datetime.now(pytz.utc) # some UTC time
dt = now.astimezone(tz) # the same time in the local timezone
today = dt.date() # today in the local timezone (naive date object)
midnight = datetime.combine(today, time()) # midnight in the local timezone
aware_midnight = tz.localize(midnight, is_dst=None) # raise exception
                                                    # for ambiguous or
                                                    # non-existing
                                                    # times
tomorrow = midnight + timedelta(1)
aware_tomorrow = tz.localize(tomorrow, is_dst=None)

def print_time(aware_dt, fmt="%Y-%m-%d %H:%M:%S %Z%z"):
    print(aware_dt.strftime(fmt))
    utc_dt = aware_dt.astimezone(pytz.utc) # the same time in UTC
    print(utc_dt.strftime(fmt))

print_time(aware_midnight)
print_time(aware_tomorrow)

Output

2014-09-01 00:00:00 EST+1000
2014-08-31 14:00:00 UTC+0000
2014-09-02 00:00:00 EST+1000
2014-09-01 14:00:00 UTC+0000

See also,

  • How do I get the UTC time of "midnight" for a given timezone? -- only midnight (no tomorrow)
  • How can I subtract a day from a python date? -- about the difference between a day ago and yesterday
  • python - datetime with timezone to epoch -- demonstrate how easy it is to produce a wrong answer (for some dates, timezones).

相关文章