29

मुझे पोस्टग्रेस से तारीखों का चयन करने में कोई समस्या है - उन्हें यूटीसी में संग्रहीत किया जा रहा है, लेकिन दिनांक() फ़ंक्शन के साथ सही रूप से परिवर्तित नहीं हो रहा है।पोस्टग्रेएसक्यूएल तिथि() टाइमज़ोन

टाइमस्टैम्प को किसी तारीख में कनवर्ट करने से मुझे गलत तिथि मिलती है यदि यह पिछले 4 बजे पीएसटी है।

2012-06-21 इस मामले में 2012-06-20 होना चाहिए।

starts_at कॉलम डेटाटाइप timestamp without time zone है।

पीएसटी समय-क्षेत्र पर परिवर्तित करने के बिना::

Select starts_at from schedules where id = 40; 

     starts_at  
--------------------- 
2012-06-21 01:00:00 

परिवर्तित इस देता है: यहाँ मेरी क्वेरी दी गई हैं

Select (starts_at at time zone 'pst') from schedules where id = 40; 
     timezone   
------------------------ 
2012-06-21 02:00:00-07 

लेकिन न तो समय क्षेत्र में सही दिनांक में रूपांतरित करें।

उत्तर

22

मुझे आपके प्रश्न में सटीक प्रकार starts_at नहीं दिखाई देता है। आपको वास्तव में यह जानकारी शामिल करनी चाहिए, यह समाधान की कुंजी है। मुझे अनुमान लगाना होगा।

असल में, PostgreSQL हमेशाtimestamp with time zone प्रकार के लिए यूटीसी समय मान स्टोर करता है। केवल प्रदर्शन आपके वर्तमान timezone सेटिंग के साथ भिन्न होता है। AT TIME ZONE का प्रभाव अंतर्निहित डेटा प्रकार के साथ भी परिवर्तन करता है। this related answer में अधिक जानकारी।

यदि आप date टाइप timestamp [without time zone] से निकालें, तो आपको वर्तमान समय क्षेत्र की तारीख मिल जाएगी। आउटपुट में दिन timestamp मान के प्रदर्शन के समान होगा।

यदि आप date को timestamp with time zone (timestamptz से संक्षिप्त) से निकालते हैं, तो समय क्षेत्र ऑफ़सेट पहले "लागू" होता है। आपको अभी भी वर्तमान समय क्षेत्र की तारीख मिलती है, जो टाइमस्टैम्प के प्रदर्शन से सहमत है। समय के समान बिंदु यूरोप के कुछ हिस्सों में अगले दिन अनुवाद करता है, जब यह पिछले 4 पीएम है। उदाहरण के लिए कैलिफ़ोर्निया में। किसी निश्चित समय क्षेत्र की तिथि प्राप्त करने के लिए, पहले AT TIME ZONE लागू करें।

इसलिए, प्रश्न के शीर्ष पर आप जो वर्णन करते हैं, वह आपके उदाहरण के विपरीत है।

कि starts_at को देखते हुए एक timestamp [without time zone] है और अपने सर्वर पर समय स्थानीय समय के लिए निर्धारित है। इसके साथ परीक्षण:

SELECT now(); 

क्या यह आपकी दीवार पर घड़ी के समान समय प्रदर्शित करता है? यदि हां, तो timezone आपके वर्तमान सत्र की सेटिंग आपके स्थानीय समय क्षेत्र से सहमत है। यदि नहीं, तो आप अपने postgresql.conf में timezone की सेटिंग पर जा सकते हैं। या शायद आपका ग्राहक सेटिंग में कुछ करता है? (प्रति सत्र सेट किया जा सकता है।) Details in the manual.

starts_at से अपने स्थानीय तारीख प्राप्त करने के लिए बस

SELECT starts_at::date 

समान करने के लिए:

SELECT date(starts_at) 

Btw, अपने स्थानीय समय UTC-7 पर अभी है नहीं UTC-8, क्योंकि डेलाइट बचत समय प्रभावी है (मानव जाति के उज्ज्वल विचारों में से नहीं)।

प्रशांत मानक समय (पीएसटी) आमतौर पर यूटीसी (सार्वभौमिक समय क्षेत्र) से 8 घंटे पहले होता है, लेकिन डेलाइट सेविंग अवधि (जैसे अब) के दौरान यह 7 घंटे है। यही कारण है कि timestamptz आपके उदाहरण में 2012-06-21 02:00:00-07 के रूप में प्रदर्शित किया गया है। निर्माण AT TIME ZONE 'PST' खाता में डेलाइट सेविंग टाइम लेता है।

SELECT '2012-06-21 01:00:00'::timestamp AT TIME ZONE 'PST' 
     ,'2012-12-21 01:00:00'::timestamp AT TIME ZONE 'PST' 
+0

यह सही प्रकार का है - 'पीएसटी' डेलाइट बचत को ध्यान में नहीं लेता है, "यूएस/प्रशांत" बनाम "पीएसटी" या "पीडीटी" –

6

मैं जानता हूँ कि यह काफी पुराना पुराना है लेकिन आप अमेरिका "समय क्षेत्र एटी का उपयोग कर विचार कर सकते हैं: इन दो भाव अलग-अलग परिणाम (सर्दियों में एक, गर्मियों में एक) और जब डाली अलग तारीखों में हो सकता है उपज/प्रशांत "किसी भी पीएसटी/पीडीटी मुद्दों से बचने के लिए कास्टिंग करते समय। तो

SELECT start_at :: TIMESTAMPTZ समय क्षेत्र पर "यूएस/प्रशांत" शेड्यूल से आईडी = '40';

+0

का उपयोग करने के बारे में जॉन रेनफेर्डेड का जवाब देखें, यदि आपको ऐतिहासिक तिथियों की आवश्यकता है तो यह बिल्कुल सही है उनके द्वारा किए गए वास्तविक समय का प्रतिनिधित्व करने के लिए। –

19

असल में क्या आप चाहते हैं:

$ select starts_at AT TIME ZONE 'UTC' AT TIME ZONE 'US/Pacific' from schedules where id = 40 

मैं इस लेख से समाधान के नीचे है, जो सीधे स्वर्ण है मिल गया !!! यह इस गैर-मामूली मुद्दे को स्पष्ट रूप से बताता है, अगर आप pstgrsql TZ प्रबंधन को बेहतर समझना चाहते हैं तो इसे पढ़ लें।

Expressing PostgreSQL timestamps without zones in local time

यहाँ है क्या हो रहा है। सबसे पहले आपको पता होना चाहिए कि 'पीएसटी टाइमज़ोन यूटीसी टाइमज़ोन के पीछे 8 घंटे है, उदाहरण के लिए 1 जनवरी 2014, 4:30 अपराह्न पीएसटी (बुध, 01 जनवरी 2014 16:00:30 -0800) 2 जनवरी 2014, 00:30 के बराबर है एएम यूटीसी (गुरु, 02 जनवरी 2014 00:00:30 +0000)। पीएसटी में 4:00 बजे के बाद किसी भी समय अगले दिन तक फिसल जाता है, जिसे यूटीसी के रूप में व्याख्या किया जाता है।

इसके अलावा, जैसा कि ऊपर वर्णित इरविन ब्रैंडस्टेटर के रूप में, पोस्ट्रेसक्ल में दो प्रकार के टाइमस्टैम्प डेटा प्रकार हैं, एक टाइमज़ोन और बिना किसी के। अपने timestamps एक समयक्षेत्र, तो एक सरल शामिल हैं:

$ select starts_at AT TIME ZONE 'US/Pacific' from schedules where id = 40 

काम करेंगे। हालांकि यदि आपका टाइमस्टैम्प समयहीन है, तो ऊपर दिए गए कमांड को निष्पादित करने से काम नहीं होगा, और आपको पहले अपना टाइमज़ोनलेस टाइमस्टैम्प टाइम टाइम के साथ टाइमस्टैम्प में परिवर्तित करना होगा, अर्थात् यूटीसी टाइमज़ोन, और केवल इसे अपने वांछित 'पीएसटी' या 'यूएस/प्रशांत '(जो कुछ डेलाइट सेविंग टाइम मुद्दों के समान हैं। मुझे लगता है कि आपको या तो ठीक होना चाहिए)।

मुझे एक उदाहरण के साथ प्रदर्शित करने दें जहां मैं एक टाइमज़ोनलेस टाइमस्टैम्प बना देता हूं। आइए सुविधा के लिए मान लें कि हमारा स्थानीय टाइमज़ोन वास्तव में 'पीएसटी' है (यदि यह तब नहीं होता है तो यह थोड़ा और जटिल हो जाता है जो इस स्पष्टीकरण के उद्देश्य के लिए अनावश्यक है)।

मेरे पास है कहते हैं:

$ select timestamp '2014-01-2 00:30:00' AS a, timestamp '2014-01-2 00:30:00' AT TIME ZONE 'UTC' AS b, timestamp '2014-01-2 00:30:00' AT TIME ZONE 'UTC' AT TIME ZONE 'PST' AS c, timestamp '2014-01-2 00:30:00' AT TIME ZONE 'PST' AS d 

यह निकलेगा:

"a"=>"2014-01-02 00:30:00" (This is the timezoneless timestamp) 
"b"=>"2014-01-02 00:30:00+00" (This is the UTC TZ timestamp, note that up to a timezone, it is equivalent to the timezoneless one) 
"c"=>"2014-01-01 16:30:00" (This is the correct 'PST' TZ conversion of the UTC timezone, if you read the documentation postgresql will not print the actual TZ for this conversion) 
"d"=>"2014-01-02 08:30:00+00" 

पिछले टाइमस्टैम्प PostgreSQL में 'पीएसटी' के लिए यूटीसी से timezoneless टाइमस्टैम्प परिवर्तित करने के बारे में सब भ्रम के लिए कारण है। जब हम लिखें:

timestamp '2014-01-2 00:30:00' AT TIME ZONE 'PST' AS d 

हम एक timezoneless टाइमस्टैम्प लेती हैं और उसे 'पीएसटी TZ को बदलने की कोशिश कर रहे हैं (हम परोक्ष रूप से मान लेते हैं कि PostgreSQL समझ जाएगा कि हम इसे एक यूटीसी TZ से टाइमस्टैम्प परिवर्तित करना चाहते हैं, लेकिन postresql है अपनी योजनाएं!)। प्रैक्टिस में, पोस्टग्रेस्क्ल क्या करता है यह टाइमज़ोनलेस टाइमस्टैम्प ('2014-01-2 00:30:00) लेता है और इसका इलाज करता है जैसे कि यह पहले से ही' पीएसटी 'टीजेड टाइमस्टैम्प था (यानी: 2014-01-2 00:30 : 00 -0800) और यूटीसी टाइमज़ोन में परिवर्तित हो जाता है !!! तो यह वास्तव में वापस की बजाय 8 घंटे आगे धक्का देता है! इस प्रकार हम पाते हैं (2014-01-02 08: 30: 00 + 00)।

वैसे भी, यह अंतिम (अप्रचलित) व्यवहार सभी भ्रम का कारण है। यदि आप अधिक व्यापक स्पष्टीकरण चाहते हैं तो आलेख पढ़ें, मुझे वास्तव में परिणाम मिल गए हैं जो इस अंतिम भाग पर थोड़ा अलग हैं, लेकिन सामान्य विचार समान है।

+0

इस विस्तृत स्पष्टीकरण के लिए धन्यवाद। मैंने इसे पढ़ने से पहले कुल नुकसान में था! –

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