繁体   English   中英

Python 日期时间库,在向日期时间添加天数时可以识别夏令时

[英]Python datetime library that is daylight savings aware when adding days to datetime

是否有执行此操作的 python 日期时间库?

dt = iso8601.parse_date("2016-03-13 00:00:00-08")
dt = dt.astimezone(us_pacific)
dt += timedelta(days=1)
self.assertEqual(dt, iso8601.parse_date("2016-03-14 00:00:00-07"))

换句话说,我正在寻找一个库,其中 datetime 对象足够聪明,知道 timedelta(days=1) 与 timedelta(hours=24) 不同(支持月份的奖励积分)。

目前,我发现错误风险最小的解决方法是使用日期,然后将其转换为日期时间,并在给定时区将时间设置为 0。 但问题是很容易假设上面的代码会按给定的方式工作,所以我想使用一个没有风险的库。 同样,如果给定了一个日期时间对象,将其转换回日期也很麻烦。

编辑:

这被搁置了,因为询问是否有一个软件库可以完成一项任务,而不是必须从头开始编写代码是离题的。 我不确定如何更好地表达,因为我已经解释过解决方法是使用日期然后添加时间,这可以通过多种方式完成。 我正在寻找一种更好的方法,我已经知道它不是 python 标准库的一部分。 我很确定会问“有没有更好的方法来做到这一点?”,或者“我怎样才能用大约相同数量的代码行来完成这个?” 也是完全有效的问题。

如果没有图书馆做这样的事情,我当然可以做到。 我将其称为 YADateTime,因为它将是另一个 Python 日期时间库。 也就是说,如果已经有一个图书馆,那么我再建一个就没有意义了。

这在Python 3.6.4上对我有用。 根据时区感知的日期时间对象(即日期增加且小时保持为0)正确添加了日期。 我遇到的问题是时区偏移是不正确的。

不漂亮,但它似乎工作。

EST = pytz.timezone('US/Eastern')
DAY = dt.timedelta(days = 1)

date = date + DAY
date_with_correct_timezone = EST.localize(dt.datetime(date.year,date.month,date.day,hour,minute,0))
if date != date_with_correct_timezone:
    print(f'     corrected {date} to {date_with_correct_timezone}')
    date = date_with_correct_timezone

示例输出:

corrected 2017-03-13 00:00:00-05:00 to 2017-03-13 00:00:00-04:00
corrected 2017-11-06 00:00:00-04:00 to 2017-11-06 00:00:00-05:00

这是一个老问题,但它是一个有用的问题,我没有在 SO 上找到它的任何更新版本,所以我在这里添加一个答案。

至少,应该能够在America/Chicago时区采用2022-03-13 01:30:00的日期时间,也就是夏令时从凌晨 2 点到凌晨 3 点“向前推进”之前,再加一个小时,并在同一America/Chicago时区获得2022-03-13 03:30:00

这甚至没有添加不同长度的间隔,它只是跨越 DST 边界,所以它应该是“容易的”。

以下事情失败了,但看起来它们应该可以工作:

# 0a. pytz timezone, datetime.timedelta math
import pytz
from datetime import datetime, timedelta
tz = pytz.timezone('America/Chicago')
d = datetime(2022, 3, 13, 1, 30, tzinfo=tz)  # already well-known to be wrong
result = d + timedelta(hours=1)
str(result)
# '2022-03-13 02:30:00-05:51'
# Wrong ↑
# 1a. pytz timezone, datetime.timedelta math
import pytz
from datetime import datetime, timedelta
tz = pytz.timezone('America/Chicago')
d = tz.localize(datetime(2022, 3, 13, 1, 30))
result = d + timedelta(hours=1)
str(result)
# '2022-03-13 02:30:00-06:00'
# Wrong ↑
# 2a. dateutil timezone, datetime.timedelta math, method 1
import dateutil.tz
from datetime import datetime, timedelta
tz = dateutil.tz.gettz('America/Chicago')
d = datetime(2022, 3, 13, 1, 30, tzinfo=tz)
result = d + timedelta(hours=1)
str(result)
# '2022-03-13 02:30:00-05:00'
# Wrong ↑
# 3a. dateutil timezone, datetime.timedelta math, method 2
import dateutil.tz
from datetime import datetime, timedelta
tz = dateutil.tz.gettz('America/Chicago')
d = datetime(2022, 3, 13, 1, 30).astimezone(tz)
result = d + timedelta(hours=1)
str(result)
# '2022-03-13 02:30:00-05:00'
# Wrong ↑
# 4a. dateutil timezone, pendulum math
import dateutil.tz
from datetime import datetime
import pendulum
tz = dateutil.tz.gettz('America/Chicago')
d = datetime(2022, 3, 13, 1, 30).astimezone(tz)
result = pendulum.instance(d).add(hours=1)
str(result)
# '2022-03-13T02:30:00-06:00'
# Wrong ↑

其中一些可以通过将结果转换为timestamp (自格林威治标准时间以来的秒数)并再次返回并重新应用时区来挽救 - 显然这是不应该做的事情:

# 1b. pytz timezone, datetime.timedelta math
import pytz
from datetime import datetime, timedelta
tz = pytz.timezone('America/Chicago')
d = tz.localize(datetime(2022, 3, 13, 1, 30))
result = d + timedelta(hours=1)
result = datetime.fromtimestamp(result.timestamp()).astimezone(tz)
str(result)
# '2022-03-13 03:30:00-05:00'
# Correct ↑
# 2b. dateutil timezone, datetime.timedelta math, method 1
import dateutil.tz
from datetime import datetime, timedelta
tz = dateutil.tz.gettz('America/Chicago')
d = datetime(2022, 3, 13, 1, 30, tzinfo=tz)
result = d + timedelta(hours=1)
result = datetime.fromtimestamp(result.timestamp()).astimezone(tz)
str(result)
# '2022-03-13 01:30:00-06:00'
# Wrong ↑ (worse!)
# 3b. dateutil timezone, datetime.timedelta math, method 2
import dateutil.tz
from datetime import datetime, timedelta
tz = dateutil.tz.gettz('America/Chicago')
d = datetime(2022, 3, 13, 1, 30).astimezone(tz)
result = d + timedelta(hours=1)
result = datetime.fromtimestamp(result.timestamp()).astimezone(tz)
str(result)
# '2022-03-13 01:30:00-06:00'
# Wrong ↑ (worse!)
# 4b. dateutil timezone, pendulum math
import dateutil.tz
from datetime import datetime
import pendulum
tz = dateutil.tz.gettz('America/Chicago')
d = datetime(2022, 3, 13, 1, 30).astimezone(tz)
result = pendulum.instance(d).add(hours=1)
result = datetime.fromtimestamp(result.timestamp()).astimezone(tz)
str(result)
# '2022-03-13 03:30:00-05:00'
# Correct ↑

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM