2012-08-30 15 views
6

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

प्रशांत समय क्षेत्र में अब से एक datetime वस्तु बनाने के लिए, मैं इस समय इस (अजगर 2.7.2+)

from datetime import datetime 
import pytz 
la = pytz.timezone("America/Los_Angeles") 
now = datetime.now(la) 

डीएसटी के संबंध में यह सही है कर रहा हूँ? यदि नहीं, तो मुझे लगता है कि मुझे करना चाहिए:

now2 = la.localize(datetime.now()) 

मेरा प्रश्न है क्यों? क्या कोई मुझे एक मामला दिखा सकता है जहां पहला गलत है और सेकंड सही है?

मेरे सेकेंड के प्रश्न के लिए, मान लीजिए कि मेरे पास लॉस एंजिल्स, सीए में 9/1/2012 सुबह 8:00 बजे कुछ उपयोगकर्ता इनपुट से एक निष्क्रिय तिथि और समय था। इस तरह डेटाटाइम बनाने का सही तरीका है:

la.localize(datetime(2012, 9, 1, 8, 0)) 

यदि नहीं, तो मुझे इन डेटाटाइम का निर्माण कैसे करना चाहिए?

उत्तर

9

pytz documentation से:

बार से निपटने का पसंदीदा तरीका हमेशा यूटीसी में काम करने के लिए, जब उत्पादन पैदा मनुष्य द्वारा पढ़ा जा करने के लिए केवल LOCALTIME को बदलने है।

तो आदर्श रूप से आपको now के बजाय utcnow का उपयोग करना चाहिए।

कुछ कारणों से मान लें कि आपके हाथ बंधे हैं और आपको स्थानीय समय के साथ काम करने की ज़रूरत है, फिर भी यदि आप डेलाइट सेविंग ट्रांज़िशन विंडो के दौरान ऐसा कर रहे हैं तो आप वर्तमान समय को स्थानीयकृत करने की कोशिश कर समस्या में भाग सकते हैं। उसी datetime दो बार हो सकता है, एक बार दिन के समय के दौरान और फिर मानक समय के दौरान, और localize विधि को तब तक पता नहीं चलता जब तक आप इसे is_dst पैरामीटर के साथ स्पष्ट रूप से नहीं बताते।

तो वर्तमान UTC समय प्राप्त करने के लिए:

utc = pytz.timezone('UTC') 
now = utc.localize(datetime.datetime.utcnow()) 

और यह आपके स्थानीय समय में कनवर्ट करने के लिए (लेकिन केवल जब तुम चाहिए):

la = pytz.timezone('America/Los_Angeles') 
local_time = now.astimezone(la) 

संपादित करें: के रूप में टिप्पणी में कहा @J.F. Sebastian द्वारा, datetime.now(tz) का उपयोग करने वाला आपका पहला उदाहरण सभी मामलों में काम करेगा। आपका दूसरा उदाहरण उपरोक्त रूपरेखा के रूप में गिरावट संक्रमण के दौरान विफल रहता है। मैं अभी भी प्रदर्शन को छोड़कर सबकुछ के लिए स्थानीय समय के बजाय यूटीसी का उपयोग करने का समर्थन करता हूं।

+1

किसी दिए गए टाइमज़ोन में वर्तमान समय प्राप्त करने का बेहतर तरीका यह है: 'datetime.now (tz)'। – jfs

+0

@ जेएफ। सेबेस्टियन मुझे संदेह है कि 'pytz' timezones के साथ विश्वसनीय रूप से काम नहीं करता है, इसी कारण से' डेटाटाइम 'कन्स्ट्रक्टर उनके साथ काम नहीं करता है। –

+1

यह काम करता है: [datetime.now (pytz_timezone) 'विफल क्यों होता है?] (Http://stackoverflow.com/q/31886808/4279) – jfs

0

pytz website का कहना है:

दुर्भाग्य से मानक datetime कंस्ट्रक्टर्स 'pytz के साथ कई समय क्षेत्रों के लिए' काम नहीं करता है 'की tzinfo तर्क का उपयोग।

तो आपको datetime.now(la) का उपयोग नहीं करना चाहिए। मैं विनिर्देशों को नहीं जानता, लेकिन कुछ टाइमज़ोन अधिक विदेशी नियमों पर काम करते हैं, फिर हम इसका उपयोग करते हैं, और पायथन का डेटाटाइम कोड उन्हें संभाल नहीं सकता है। Pytz के कोड का उपयोग करके, उन्हें pytz के उद्देश्य के बाद से सही ढंग से संभाला जाना चाहिए। इसमें उन दिनों के लिए भी समस्याएं हो सकती हैं जो डेलाइट बचत में कूदने के समय के लिए दो बार धन्यवाद होती हैं।

दूसरे प्रश्न के लिए, यह दस्तावेज दिखाता है, इसलिए आपको अच्छा होना चाहिए।

+0

'डेटाटाइम .now (tz)' मामला है तो यह काम करता है (आपको '.localize()' का उपयोग नहीं करना चाहिए)। – jfs

+0

आपको datetime.datetime.utcnow()। Astimezone (tz) का उपयोग करना चाहिए - यह समय यूटीसी में मिलता है और फिर इसे यूटीसी से ऑफसेट करता है जो कि टाइमज़ोन टीजे में जो भी नियम लागू होता है। (कन्स्ट्रक्टर में एक पायट्ज़ टाइमज़ोन पास करने से आपको कुछ ऑफसेट मिल जाएगा जो कि घंटों की संख्या भी नहीं है।) – jobermark

+0

@jobermark: 'utcnow() के बजाय' अब (tz) 'का उपयोग करें। Astimezone (tz)'। [यह काम करता है] (http://stackoverflow.com/questions/12203676/daylight-savings-time-in-python/12204612#comment62276833_12204612) – jfs

5

पहला समाधान डीएसटी के संबंध में सही है, और दूसरा समाधान खराब है।

मैं एक उदाहरण दूंगा। यहाँ यूरोप में, जब यह कोड चलाने:

2012-08-30 12:34:06 PDT-0700 
2012-08-30 21:34:06 PDT-0700 
2012-08-30 21:34:06 

datetime.now(la) ला में वर्तमान समय के साथ एक दिनांक, प्लस ला के लिए समय क्षेत्र जानकारी बनाता है:

from datetime import datetime 
import pytz # $ pip install pytz 

la = pytz.timezone("America/Los_Angeles") 
fmt = '%Y-%m-%d %H:%M:%S %Z%z' 
now = datetime.now(la) 
now2 = la.localize(datetime.now()) 
now3 = datetime.now() 
print(now.strftime(fmt)) 
print(now2.strftime(fmt)) 
print(now3.strftime(fmt)) 

मैं निम्नलिखित मिलता है।

la.localize(datetime.now()) बेवकूफ डेटाटाइम को टाइमज़ोन जानकारी जोड़ता है, लेकिन कोई टाइमज़ोन रूपांतरण नहीं करता है; यह मानता है कि समय पहले से ही इस समय क्षेत्र में था।

datetime.now() स्थानीय समय के साथ एक बेवकूफ डेटाटाइम (टाइमज़ोन जानकारी के बिना) बनाता है।

जब तक आप ला में हों, आपको अंतर दिखाई नहीं देगा, लेकिन यदि आपका कोड कहीं और चलता है, तो शायद यह वही नहीं होगा जो आप चाहते थे।

इसके अलावा, यदि आपको कभी भी समय क्षेत्र के साथ गंभीरता से निपटने की आवश्यकता है, तो यूटीसी में अपने सभी समय बेहतर है, डीएसटी के साथ खुद को बहुत परेशानी बचाएं।

+0

'अब 2' अंत में ऑफ-ऑफ के दौरान गलत परिणाम (एक घंटे का बंद) वापस कर सकता है। यदि आप एलए में हैं तो भी डीएसटी संक्रमण ("वापस आना")। 'datetime.now (ला) 'यूटीसी संक्रमण के दौरान भी काम करता है। – jfs

0

यह काम करता है:

# naive datetime 
d = datetime.datetime(2016, 11, 5, 16, 43, 45) 
utc = pytz.UTC# UTC timezone 
pst = pytz.timezone('America/Los_Angeles') # LA timezone 

# Convert to UTC timezone aware datetime 
d = utc.localize(d) 
>>> datetime.datetime(2016, 11, 5, 16, 43, 45, tzinfo=<UTC>) 

# show as in LA time zone (not converting here) 
d.astimezone(pst) 
>>> datetime.datetime(2016, 11, 5, 9, 43, 45, 
tzinfo=<DstTzInfo 'America/Los_Angeles' PDT-1 day, 17:00:00 DST>) 
# we get Pacific Daylight Time: PDT 

# add 1 day to UTC date 
d = d + datetime.timedelta(days=1) 
>>> datetime.datetime(2016, 11, 6, 16, 43, 45, tzinfo=<UTC>) 

d.astimezone(pst) # now cast to LA time zone 
>>> datetime.datetime(2016, 11, 6, 8, 43, 45, 
tzinfo=<DstTzInfo 'America/Los_Angeles' PST-1 day, 16:00:00 STD>) 
# Daylight saving is applied -> we get Pacific Standard Time PST 

यह काम नहीं करता:

# naive datetime 
d = datetime.datetime(2016, 11, 5, 16, 43, 45) 
utc = pytz.UTC# UTC timezone 
pst = pytz.timezone('America/Los_Angeles') # LA timezone 

# convert to UTC timezone aware datetime 
d = utc.localize(d) 
>>> datetime.datetime(2016, 11, 5, 16, 43, 45, tzinfo=<UTC>) 

# convert to 'America/Los_Angeles' timezone: DON'T DO THIS 
d = d.astimezone(pst) 
>>> datetime.datetime(2016, 11, 5, 9, 43, 45, 
tzinfo=<DstTzInfo 'America/Los_Angeles' PDT-1 day, 17:00:00 DST>) 
# we are in Pacific Daylight Time PDT 

# add 1 day to LA local date: DON'T DO THAT 
d = d + datetime.timedelta(days=1) 
>>> datetime.datetime(2016, 11, 6, 9, 43, 45, 
tzinfo=<DstTzInfo 'America/Los_Angeles' PDT-1 day, 17:00:00 DST>) 
# Daylight Saving is NOT respected, we are still in PDT time, not PST 

निष्कर्ष:

datetime.timedelta()पुष्टि नहीं करता खाता डेलाइट सेविंग के लिए।

अपना समय हमेशा यूटीसी टाइमज़ोन में जोड़ें/घटाएं। केवल आउटपुट/डिस्प्ले के लिए स्थानीय समय पर कास्ट करें।

संबंधित मुद्दे

 संबंधित मुद्दे