簡體   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