簡體   English   中英

使用python / django進行日期時間本地化

[英]Datetime localization with python/django

我正在嘗試解析RSS提要。 Feed中的條目包含以下日期元素:

<dc:date>2016-09-21T16:00:00+02:00</dc:date>

使用feedparser,我嘗試:

published_time = datetime.fromtimestamp(mktime(entry.published_parsed))

但問題是我似乎得到了存儲在數據庫中的錯誤時間。 在這種特殊情況下,日期時間存儲為:

2016-09-21 13:00:00

...當我期望14:00 - 正確的UTC時間。

我認為問題出在我們的django設置中,我們有:

TIME_ZONE = 'Europe/Berlin'

因為當我切換到:

TIME_ZONE = 'UTC'

...數據時間存儲為正確的UTC時間:

2016-09-21 14:00:00

有沒有辦法保持django設置不變,但要正確解析和存儲這個日期時間,而不會影響django時區設置?

編輯:也許這樣更清楚......

print entry.published_parsed
published_time = datetime.fromtimestamp(mktime(entry.published_parsed))
print published_time
localized_time = pytz.timezone(settings.TIME_ZONE).localize(published_time, is_dst=None)
print localized_time

time.struct_time(tm_year=2016, tm_mon=9, tm_mday=21, tm_hour=14, tm_min=0, tm_sec=0, tm_wday=2, tm_yday=265, tm_isdst=0)
2016-09-21 15:00:00
2016-09-21 15:00:00+02:00

feedparser的entry.published_parsed總是一個utc time tuple,無論輸入時間字符串是什么。 獲取時區感知datetime對象:

from datetime import datetime

utc_time = datetime(*entry.published_parsed[:6], tzinfo=utc)

其中utc是一個tzinfo對象,例如datetime.timezone.utcpytz.utc ,或者只是你的自定義tzinfo(對於較舊的python版本)

你不應該把utc時間傳遞給期望當地時間的mktime() 同樣的錯誤: 擁有正確的日期時間和正確的時區

確保USE_TZ=True以便django在任何地方使用感知日期時間對象。 給定一個時區感知日期時間對象,無論你的TIME_ZONEtimezone.get_current_timezone()什么,django都應該正確地將它保存到db。

您是否嘗試過使用datetime.utcfromtimestamp()而不是datetime.fromtimestamp()

作為輔助解決方案,您可以獲取未解析的數據(我相信它可以作為entry.published ?)並使用python-dateutil來解析字符串,然后將其轉換為pytz.utc時區。

>>> import pytz
>>> from dateutil import parser
>>> dt = parser.parse('2016-09-21T16:00:00+02:00')
>>> dt
datetime.datetime(2016, 9, 21, 16, 0, tzinfo=tzoffset(None, 7200))
>>> dt.astimezone(pytz.utc)
datetime.datetime(2016, 9, 21, 14, 0, tzinfo=<UTC>)

使用

published_time = pytz.utc.localize(datetime.utcfromtimestamp(calendar.timegm(parsed_entry.published_parsed)))

Feedparser可以解析大量日期格式,您可以在此處找到它們。

正如您在feedparser/feedparser/datetimes/__init__.py ,Feedparser _parse_date中的內置函數執行以下操作:

在GMT中將各種日期格式解析為9元組

這意味着在parsed_entry.published_parsed您在GMT時區中有一個time.struct_time對象。

使用時將其轉換為datetime對象

published_time = datetime.fromtimestamp(mktime(parsed_entry.published_parsed))

問題是mktime假定傳遞的元組是在本地時間 ,這不是,它是GMT / UTC! 除此之外,您沒有在轉換結束時正確本地化datetime對象。

您需要使用以下內容替換該轉換,記住Feedparser返回GMT struct_time ,並使用您喜歡的時區將其本地化(為簡單起見,UTC)。

  • 你使用calendar.timegm ,它給出了紀元和作為參數傳遞的日期之間的秒數,假設傳遞的對象是UTC / GMT(我們從Feedparser知道它是)
  • 您使用utcfromtimestamp來獲取一個天真的datetime對象(我們知道它代表一個UTC的日期時間,但此時Python不會)
  • 使用pytz.utc.localize您可以在UTC中正確地將datetime對象本地化。

例:

import calendar
from datetime import datetime
import pytz
localized_dt = pytz.utc.localize(datetime.utcfromtimestamp(calendar.timegm(parsed_entry.published_parsed)))

只要您保持一致,如果您使用fromtimestamputcfromtimestamp並不重要。 如果使用fromtimestamp ,則需要告訴Python您創建的datetime對象具有本地時區。 假設你在歐洲/柏林,這也很好:

pytz.timezone('Europe/Berlin').localize(datetime.fromtimestamp(calendar.timegm(parsed_entry.published_parsed)))

如果parsed_entry.published_parsed也在本地時區,則必須使用mktime代替calendar.timegm

作為替代方案,您可以自己解析從Feedparser解析的數據字符串parsed_entry['published']

from dateutil import parser
localized_dt = parser.parse(parsed_entry['published'])

您可以檢查以下內容是否返回True

parser.parse(parsed_entry['published']) == pytz.utc.localize(datetime.utcfromtimestamp(calendar.timegm(parsed_entry.published_parsed)))

Django TIME_ZONE設置實際上並不重要,因為它僅用於可視化目的或自動轉換天真的日期時間。

當USE_TZ為True時,這是Django用於在模板中顯示日期時間和解釋在表單中輸入的日期時間的默認時區。

重要的是始終使用正確的本地化日期時間,無論使用哪個時區。 只要它們不是天真的格式,它們將由Django正確處理。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM