2011-09-19 15 views
9

में वापस लेना मैं राष्ट्रीय मौसम सेवा अलर्ट को वेब एप्लिकेशन में फ़ीड कर रहा हूं। जब वे अपने समाप्ति समय को दबाते हैं तो मैं अलर्ट को शुद्ध करना चाहता हूं। मैं उन भौगोलिक क्षेत्र के लिए स्थानीय समय प्रारूप में समाप्ति समय भी प्रदर्शित करना चाहता हूं जो वे संबंधित हैं।यूटीसी को टाइमज़ोन-जागरूक दिनांक स्ट्रिंग को परिवर्तित करना और पाइथन

अलर्ट पूरे अमेरिका को कवर करते हैं, इसलिए मुझे लगता है कि यूटीसी टाइमस्टैम्प में समय को स्टोर और तुलना करना सबसे अच्छा तरीका है। समाप्ति समय फ़ीड में इस तरह की स्ट्रिंग के रूप में आता है: 2011-09-09T22:12:00-04:00

मैं Labix dateutils पैकेज का उपयोग कर रहा एक समय क्षेत्र अवगत ढंग से स्ट्रिंग पार्स करने में:

>>> from dateutil.parser import parse 
>>> d = parse("2011-09-18T15:52:00-04:00") 
>>> d 
datetime.datetime(2011, 9, 18, 15, 52, tzinfo=tzoffset(None, -14400)) 

मैं भी यूटीसी घंटे में ऑफसेट को पकड़ने में सक्षम हूँ:

>>> offset_hours = (d.utcoffset().days * 86400 + d.utcoffset().seconds)/3600 
>>> offset_hours 
-4 

:

datetime.utctimetuple() और time.mktime() तरीकों का उपयोग करना, मैं एक यूटीसी टाइमस्टैम्प पर पार्स तारीख बदलने में सक्षम हूँ

इस बिंदु पर, मुझे बहुत अच्छा लगता है कि मैं कच्चे तारों को यूटीसी में समाप्ति समय का प्रतिनिधित्व करने वाले टाइमस्टैम्प में परिवर्तित करने में सक्षम हूं।

>>> now_utc_ts = time.mktime(time.gmtime()) 
>>> now_utc_ts 
1316398744.0 
>>> now_utc_ts >= expiration_tc_ts 
True 

कठिनाई मैं हो रही है मेरी संग्रहीत यूटीसी टाइमस्टैम्प मूल करने के लिए वापस परिवर्तित करने के लिए कोशिश कर रहा है: मैं अगर यह साफ़ कर दिया की जरूरत समाप्ति के लिए एक यूटीसी टाइमस्टैम्प के रूप में वर्तमान समय की तुलना करने और निर्धारित करने में सक्षम हूँ स्थानीय प्रारूप। मैं मूल रूपांतरण और एक स्ट्रिंग से संग्रहीत ऑफसेट घंटे मैं समय क्षेत्र लेबल स्टोर करने के लिए पार्स है:

>>> print offset_hours 
-4 
>>> print timezone 
EDT 

मैं यूटीसी टाइमस्टैम्प एक स्थानीय रूप से स्वरूपित समय के लिए वापस रूपांतरित करना चाहते हैं, लेकिन यह करने के लिए परिवर्तित करने के लिए वापस एक datetime काम नहीं लगता है:

>>> import datetime 
>>> datetime.datetime.fromtimestamp(expiration_utc_ts) + datetime.timedelta(hours=offset_hours) 
datetime.datetime(2011, 9, 18, 16, 52) # The hour is 16 but it should be 15 

ऐसा लगता है कि यह एक घंटे से बंद है की तरह। मुझे यकीन नहीं है कि त्रुटि कहां पेश की गई थी? मैंने एक और परीक्षण एक साथ रखा और इसी तरह के परिणाम मिल गए:

>>> # Running this at 21:29pm EDT 
>>> utc_now = datetime.datetime.utcnow() 
>>> utc_now_ts = time.mktime(right_now.utctimetuple()) 
>>> datetime.datetime.fromtimestamp(utc_now_ts) 
datetime.datetime(2011, 9, 18, 22, 29, 47) # Off by 1 hour 

क्या कोई मेरी गलती ढूंढने में मेरी सहायता कर सकता है? मुझे यकीन नहीं है कि यह डेलाइट बचत मुद्दा है या नहीं? मैं कुछ सामानों में आया जो मुझे विश्वास दिलाता है कि यह मेरी तिथियों और समय को स्थानीयकृत करने की कोशिश कर रहा है लेकिन इस बिंदु पर मैं काफी स्टंप हूं। मैं समय-समय पर अज्ञात तरीके से इन सभी गणनाओं/तुलनाओं को करने की उम्मीद कर रहा था।

+0

[स्थानीय समय क्षेत्र से यूटीसी में कनवर्ट कर फिर वापस अजगर/pytz साथ जारी करना] (के संभावित डुप्लिकेट http://stackoverflow.com/questions/7465181/issue-with-python-pytz-converting- स्थानीय-टाइमज़ोन-टू-यूटीसी-बैक-बैक) – agf

+0

मैंने सोचा होगा कि आप यह सब डेटाटाइम ऑब्जेक्ट्स के साथ कर सकते हैं, और टुपल्स या टाइमस्टैम्प में कनवर्ट नहीं कर सकते हैं। यदि आप टाइमज़ोन-जागरूक "अब" डेटाटाइम ऑब्जेक्ट बनाते हैं तो बस "अगर x

+0

मुझे आशा है कि, लेकिन PostgreSQL डेटाटाइम वैल्यू को स्थानीयकृत करना चाहता था। (मुझे यकीन है कि इसके चारों ओर एक रास्ता है, लेकिन मुझे लगा कि यूटीसी टाइमस्टैम्प स्टोर करने के लिए अभी यह आसान होगा) – Scott

उत्तर

3

समस्या यह है कि डेलाइट सेविंग्स समय दो बार लागू किया जा रहा है।

एक तुच्छ उदाहरण:

>>> time_tuple = datetime(2011,3,13,2,1,1).utctimetuple() 
time.struct_time(tm_year=2011, tm_mon=3, tm_mday=13, tm_hour=2, tm_min=1, tm_sec=1, tm_wday=6, tm_yday=72, tm_isdst=0) 
>>> datetime.fromtimestamp(time.mktime(time_tuple)) 
datetime.datetime(2011, 3, 13, 3, 1, 1) 

मैं काफी हद तक निश्चित है कि गलती time.mktime() के भीतर निहित है। जैसा कि यह documentation:

यह स्थानीय समय() के व्यस्त कार्य है। इसका तर्क स्ट्रक्चर_टाइम या पूर्ण 9-टुपल है (चूंकि डीएसटी ध्वज आवश्यक है; डीएस फ्लैग के रूप में उपयोग करें यदि यह अज्ञात है) जो यूटीसी नहीं, स्थानीय समय में समय व्यक्त करता है।यह समय() के साथ संगतता के लिए एक फ़्लोटिंग पॉइंट नंबर देता है। यदि इनपुट मान को के रूप में मान्य समय के रूप में प्रदर्शित नहीं किया जा सकता है, तो ओवरफ़्लो त्रुटि या ValueError उठाया जाएगा (जो पर निर्भर करता है कि अमान्य मान पाइथन या अंतर्निहित सी पुस्तकालयों द्वारा पकड़ा गया है या नहीं)। सबसे पुरानी तारीख जिसके लिए यह समय उत्पन्न कर सकता है प्लेटफ़ॉर्म-निर्भर है।

जब आप time.mktime() करने के लिए एक समय टपल गुजरती हैं, यह है कि क्या समय डेलाइट सेविंग टाइम या नहीं में है पर एक ध्वज की उम्मीद है। आप ऊपर देख सकते हैं, utctimetuple() देता है कि ध्वज के साथ एक टपल 0 चिह्नित, के रूप में यह कहते हैं कि यह में क्या करेंगे इसका documentation:

तो datetime उदाहरण घ अनुभवहीन है, यह d.timetuple रूप में ही है() सिवाय इसके कि tm_isdst को d.dst() रिटर्न के बावजूद 0 पर मजबूर होना पड़ता है। यूटीसी समय के लिए डीएसटी कभी प्रभावी नहीं है।

तो घ बारे में पता है, घ UTC समय सामान्यीकृत है, d.utcoffset() को घटा कर, और सामान्यीकृत समय के लिए एक time.struct_time वापस लौटा है। tm_isdst को 0 पर मजबूर किया गया है। ध्यान दें कि परिणाम का tm_year सदस्य MINYEAR-1 या MAXYEAR + 1 हो सकता है, यदि d.year MINYEAR या MAXYEAR और यूटीसी एडजस्टमेंट एक साल की सीमा से अधिक हो जाता है।

आप time.mktime() बता दिया है के बाद से है कि आपका समय डीएसटी नहीं है, और अपना काम स्थानीय समय में हर समय परिवर्तित करने के लिए है, और यह वर्तमान में अपने क्षेत्र में डेलाइट बचत समय है, यह इसे बनाने के लिए एक घंटे के कहते हैं दिन का प्रकाश समय बचा रहा। इसलिए परिणाम।


जब मैं पद आसान नहीं है, मैं कुछ दिनों के पहले एक विधि में आए अपने स्थानीय समय में अनुभवहीन लोगों में समय क्षेत्र अवगत datetimes कन्वर्ट करने के लिए। यह बहुत क्या आप वर्तमान में क्या कर रहे हैं (उत्कृष्ट pytz मॉड्यूल का उपयोग करता है) की तुलना में आपके आवेदन के लिए बेहतर काम कर सकते हैं:

import pytz 
def convert_to_local_time(dt_aware): 
    tz = pytz.timezone('America/Los_Angeles') # Replace this with your time zone string 
    dt_my_tz = dt_aware.astimezone(tz) 
    dt_naive = dt_my_tz.replace(tzinfo=None) 
    return dt_naive 

अपने खुद के समय क्षेत्र स्ट्रिंग है, जो आप pytz.all_timezones में कहीं पा सकते हैं इससे बदलें 'अमेरिका/losangeles'।

+0

यह गलत है। 'mktime()' उम्मीद * स्थानीय समय * जबकि ओपी यूटीसी समय गुजरता है। यह स्थानीय विफल रहता है यदि स्थानीय टाइमज़ोन यूटीसी नहीं है। 'Naive_datetime_object.utctimetuple()' का उपयोग न करें - यह इसे यूटीसी में परिवर्तित नहीं करता है (ओपी 'aware_datetime.object.utctimetuple() 'का उपयोग करता है जो अपेक्षित काम करता है)। आपको 'tz.normalize() 'कॉल की आवश्यकता हो सकती है।'astimezone()' अगर 'aware_dt' यूटीसी में नहीं है। – jfs

0

datetime.fromtimestamp() स्थानीय समय POSIX टाइमस्टैंप से प्राप्त करने का सही तरीका है। आपके प्रश्न में समस्या यह है कि आप time.mktime() का उपयोग करके एक परिचित डेटाटाइम ऑब्जेक्ट को POSIX टाइमस्टैम्प में परिवर्तित करते हैं जो गलत है। यहाँ one of correct ways to do it है:

expiration_utc_ts = (d - datetime(1970, 1, 1, tzinfo=utc)).total_seconds() 
local_dt = datetime.fromtimestamp(expiration_utc_ts)