/ / अजगर के साथ स्थानीय जीवनकाल / django - अजगर, डीजे, डेटाइम, फीडपर

पाइथन / डीजेंगो के साथ डेटाटाइम स्थानीयकरण - पायथन, डीजेंगो, डेटाटाइम, फीडपार्सर

मैं एक आरएसएस फ़ीड को पार्स करने की कोशिश कर रहा हूं। फ़ीड में प्रविष्टियां दिनांक तत्व जैसे हैं:

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

फीडप्रेसर का उपयोग करते हुए, मैं करने की कोशिश करता हूं:

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

लेकिन समस्या यह है कि मुझे डेटाबेस में संग्रहीत गलत समय मिल रहा है। इस विशेष मामले में, डेटाइम के रूप में संग्रहीत किया जाता है:

2016-09-21 13:00:00

... जब मुझे 14:00 की उम्मीद होगी - सही यूटीसी समय

मुझे लगता है कि समस्या हमारी django सेटिंग्स में है, जहां हमारे पास है:

TIME_ZONE = "Europe/Berlin"

क्योंकि जब मैं स्विच करता हूं:

TIME_ZONE = "UTC"

... डेटाटाइम को सही UTC समय के रूप में संग्रहीत किया जाता है:

2016-09-21 14:00:00

वहाँ django सेटिंग्स रखने के लिए कोई रास्ता नहीं के रूप में वे कर रहे हैं, लेकिन पार्स करने के लिए और सही ढंग से इस स्टोर, django timezone सेटिंग इसे प्रभावित किए बिना सही ढंग से स्टोर?

संपादित करें: शायद यह इस तरह अधिक स्पष्ट है ...

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

उत्तर:

जवाब के लिए 2 № 1

feedparser "रों entry.published_parsed हमेशा एक utc टाइम टपल होता है जो भी इनपुट टाइम स्ट्रिंग है टाइमजोन-जागरूक होने के लिए datetime वस्तु:

from datetime import datetime

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

कहा पे utc एक tzinfo ऑब्जेक्ट है जैसे कि datetime.timezone.utc, pytz.utc, या सिर्फ अपने कस्टम tzinfo (पुराने अजगर संस्करणों के लिए).

आपको "t उत्तीर्ण समय" नहीं होना चाहिए mktime() एक स्थानीय समय की उम्मीद है। वही त्रुटि: सही टाइमजोन के साथ एक सही डेटाइम रखें.

सुनिश्चित करो USE_TZ=True ताकि django हर जगह जागरूक डेटाइम वस्तुओं का उपयोग करे। एक टाइमजोन-जागरूक डेटाटाइम ऑब्जेक्ट को देखते हुए, django को इसे सही ढंग से db में सहेजना चाहिए जो भी आपके TIME_ZONE या timezone.get_current_timezone() कर रहे हैं.


उत्तर № 2 के लिए 1

क्या आपने इसका उपयोग करने की कोशिश की है datetime.utcfromtimestamp() के बजाय datetime.fromtimestamp()?

एक माध्यमिक समाधान के रूप में, आप अप्रकाशित डेटा प्राप्त कर सकते हैं (मेरा मानना ​​है कि यह उपलब्ध है entry.published;) और सिर्फ स्ट्रिंग को पार्स करने के लिए अजगर-डेट्यूटिल का उपयोग करें, फिर इसे में कनवर्ट करें pytz.utc इस तरह timezone।

>>> 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>)

उत्तर № 3 के लिए 1

उपयोग

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

फीडपर्सर बड़े पैमाने पर तारीख प्रारूपों को पार्स कर सकता है, आप उन्हें पा सकते हैं यहाँ.

जैसा कि आप देख सकते हैं feedparser/feedparser/datetimes/__init__.pyफीडपर्सर से अंतर्निहित फ़ंक्शन _parse_date निम्नलिखित करता है:

जीएमटी में 9-ट्यूपल में विभिन्न प्रकार के दिनांक स्वरूप दिए गए हैं

इसका मतलब है कि में parsed_entry.published_parsed तुम्हारे पास एक time.struct_time जीएमटी समयक्षेत्र में वस्तु।

जब आप इसे एक में परिवर्तित करते हैं datetime वस्तु का उपयोग कर

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

समस्या यह है कि mktime माना जाता है कि गुज़रा हुआ टपल अंदर है स्थानीय समय, जो नहीं है, यह GMT / UTC है! इसके अलावा आप इसे ठीक से स्थानीयकृत नहीं करते हैं datetime रूपांतरण के अंत में ऑब्जेक्ट।

आपको उस रूपांतरण को निम्नलिखित के साथ बदलने की आवश्यकता है, यह याद करते हुए कि फीडपारर एक जीएमटी लौटाता है struct_time, और स्थानीयकरण करें कि टाइमजोन के साथ आपको पसंद है (सादगी के लिए UTC)।

  • तुम इस्तेमाल calendar.timegm, जो एक पैरामीटर के रूप में युग और तारीख के बीच सेकंड की संख्या देता है, यह मानते हुए कि उत्तीर्ण वस्तु UTC / GMT में है (हम इसे फीडरसेर से जानते हैं)
  • तुम इस्तेमाल utcfromtimestamp भोला पाने के लिए datetime ऑब्जेक्ट (जिसे हम जानते हैं कि यूटीसी में एक डेटाइम का प्रतिनिधित्व करता है, लेकिन पायथन इस समय नहीं है)
  • साथ में 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)))

जब तक आप सुसंगत हैं, तब तक यह उपयोग नहीं करता है fromtimestamp या utcfromtimestamp। यदि तुम प्रयोग करते हो fromtimestamp आपको पायथन को यह बताने की आवश्यकता है कि द datetime आपके द्वारा बनाई गई वस्तु में स्थानीय समय क्षेत्र है। मान लें कि आप यूरोप / बर्लिन में हैं, यह भी ठीक है:

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

थे parsed_entry.published_parsed स्थानीय समय क्षेत्र में भी, mktime के स्थान पर उपयोग किया जाना चाहिए calendar.timegm.

एक विकल्प के रूप में आप फीडप्रेसर से प्राप्त डेटा स्ट्रिंग को खुद को पार्स कर सकते हैं 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 सत्य है, तो यह डिफ़ॉल्ट समय क्षेत्र है जो Django टेम्पलेट्स में डेटासेट प्रदर्शित करने और रूपों में दर्ज किए गए डेटासेट की व्याख्या करने के लिए उपयोग करेगा।

यह महत्वपूर्ण है कि हमेशा स्थानीयकृत डेटाटाइम का उपयोग करें, कोई फर्क नहीं पड़ता कि समय क्षेत्र का उपयोग किया जाता है। जब तक वे भोले प्रारूप में नहीं होते हैं, तब तक वे Django द्वारा ठीक से नियंत्रित किए जाएंगे।