Postgres के दो अलग-अलग टाइमस्टैम्प डेटा प्रकार हैं:
timestamp with time zone
, संक्षिप्त नाम:timestamptz
timestamp without time zone
, संक्षिप्त नाम:timestamp
timestamptz
पसंदीदा है दिनांक/समय परिवार में शाब्दिक रूप से टाइप करें। इसमें typispreferred
है pg_type
. में सेट करें , जो प्रासंगिक हो सकता है:
- PostgreSQL में दो तिथियों के बीच समय श्रृंखला उत्पन्न करना
आंतरिक संग्रहण और युग
आंतरिक रूप से, टाइमस्टैम्प 8 बाइट्स पर कब्जा कर लेते हैं डिस्क पर और रैम में स्टोरेज की। यह पोस्टग्रेज युग, 2000-01-01 00:00:00 यूटीसी से माइक्रोसेकंड की गिनती का प्रतिनिधित्व करने वाला एक पूर्णांक मान है।
पोस्टग्रेज़ को UNIX युग, 1970-01-01 00:00:00 UTC से आमतौर पर उपयोग किए जाने वाले UNIX समय की गिनती के सेकंड का अंतर्निहित ज्ञान भी है, और इसका उपयोग to_timestamp(double precision)
के कार्यों में करता है। या EXTRACT(EPOCH FROM timestamptz)
।
स्रोत कोड:
* Timestamps, as well as the h/m/s fields of intervals, are stored as * int64 values with units of microseconds. (Once upon a time they were * double values with units of seconds.)
और:
/* Julian-date equivalents of Day 0 in Unix and Postgres reckoning */ #define UNIX_EPOCH_JDATE 2440588 /* == date2j(1970, 1, 1) */ #define POSTGRES_EPOCH_JDATE 2451545 /* == date2j(2000, 1, 1) */
माइक्रोसेकंड रिज़ॉल्यूशन सेकंड के लिए अधिकतम 6 भिन्न अंकों में अनुवाद करता है।
timestamp
timestamp
के लिए कोई समय क्षेत्र स्पष्ट रूप से प्रदान नहीं किया गया है। पोस्टग्रेज अनदेखा करता है किसी भी समय क्षेत्र संशोधक को गलती से इनपुट शाब्दिक में जोड़ा गया!
प्रदर्शन के लिए कोई घंटे स्थानांतरित नहीं किए गए हैं। सब कुछ एक ही समय क्षेत्र में होने के साथ यह ठीक है। किसी भिन्न समय क्षेत्र के लिए अर्थ बदलता है, लेकिन मान और प्रदर्शन वही रहें।
timestamptz
timestamptz
. को संभालना सूक्ष्म रूप से भिन्न है। मैं यहां मैनुअल को उद्धृत करता हूं:
timestamp with time zone
. के लिए , आंतरिक रूप से संग्रहीत मान हमेशा UTC में होता है (सार्वभौमिक समन्वित समय ...)
बोल्ड जोर मेरा। समय क्षेत्र स्वयं कभी संग्रहीत नहीं होता . यह एक इनपुट संशोधक है जिसका उपयोग यूटीसी टाइमस्टैम्प के अनुसार गणना करने के लिए किया जाता है, जिसे संग्रहीत किया जाता है - या आउटपुट डेकोरेटर प्रदर्शन के लिए स्थानीय समय की गणना करने के लिए उपयोग किया जाता है - संलग्न समय क्षेत्र ऑफसेट के साथ। अगर आप timestamptz
. के लिए ऑफ़सेट नहीं जोड़ते हैं इनपुट पर, सत्र की वर्तमान समय क्षेत्र सेटिंग मान ली जाती है। सभी गणनाएं यूटीसी टाइमस्टैम्प मानों के साथ की जाती हैं। यदि आपको (हो सकता है) एक से अधिक समय क्षेत्र से निपटना पड़े, तो timestamptz
. का उपयोग करें . दूसरे शब्दों में:यदि कल्पित समय क्षेत्र के बारे में कोई संदेह या गलतफहमी हो सकती है, तो timestamptz
के साथ जाएं . अधिकांश उपयोग के मामलों में लागू होता है।
psql या pgAdmin जैसे क्लाइंट या libpq के माध्यम से संचार करने वाला कोई भी एप्लिकेशन (जैसे रूबी पीजी मणि के साथ) को टाइमस्टैम्प प्लस ऑफ़सेट के साथ वर्तमान समय क्षेत्र के लिए प्रस्तुत किया जाता है या अनुरोधित . के अनुसार समय क्षेत्र (नीचे देखें)। यह हमेशा एक ही समय में होता है , केवल प्रदर्शन प्रारूप भिन्न होता है। या, जैसा कि मैनुअल कहता है:
<ब्लॉकक्वॉट>
सभी समयक्षेत्र-जागरूक दिनांक और समय UTC में आंतरिक रूप से संग्रहीत किए जाते हैं। वे TimeZone
. द्वारा निर्दिष्ट क्षेत्र में स्थानीय समय में परिवर्तित हो जाते हैं क्लाइंट को प्रदर्शित होने से पहले कॉन्फ़िगरेशन पैरामीटर।
psql में उदाहरण:
db=# SELECT timestamptz '2012-03-05 20:00+03';
timestamptz
------------------------
2012-03-05 18:00:00+01
यहाँ क्या हुआ?
मैंने एक मनमाना समय क्षेत्र ऑफ़सेट चुना +3
इनपुट शाब्दिक के लिए। पोस्टग्रेज करने के लिए, यह यूटीसी टाइमस्टैम्प 2012-03-05 17:00:00
को इनपुट करने के कई तरीकों में से एक है . क्वेरी का परिणाम प्रदर्शित है वर्तमान समय क्षेत्र सेटिंग के लिए वियना/ऑस्ट्रिया मेरे परीक्षण में, जिसमें एक ऑफ़सेट है +1
सर्दियों के दौरान और +2
गर्मी के समय के दौरान ("डेलाइट सेविंग टाइम", डीएसटी)। तो 2012-03-05 18:00:00+01
चूंकि डीएसटी केवल बाद में शुरू होता है।
Postgres इनपुट शाब्दिक तुरंत भूल जाता है। यह सब याद रखता है डेटा प्रकार के लिए मूल्य है। ठीक वैसे ही जैसे दशमलव संख्या के साथ। numeric '003.4'
या numeric '+3.4'
- दोनों का एक ही आंतरिक मूल्य होता है।
AT TIME ZONE
अब जो कुछ भी नहीं है, वह एक विशिष्ट समय क्षेत्र के अनुसार टाइमस्टैम्प शाब्दिक व्याख्या या प्रतिनिधित्व करने का एक उपकरण है। वहीं AT TIME ZONE
निर्माण आता है। दो अलग-अलग उपयोग के मामले हैं। timestamptz
timestamp
. में कनवर्ट किया जाता है और इसके विपरीत।
UTC timestamptz
दर्ज करने के लिए 2012-03-05 17:00:00+0
:
SELECT timestamp '2012-03-05 17:00:00' AT TIME ZONE 'UTC'
... जो इसके बराबर है:
SELECT timestamptz '2012-03-05 17:00:00 UTC'
ईएसटी timestamp
के समान समय पर प्रदर्शित करने के लिए (पूर्वी मानक समय):
SELECT timestamp '2012-03-05 17:00:00' AT TIME ZONE 'UTC' AT TIME ZONE 'EST'
यह सही है, AT TIME ZONE 'UTC'
दो बार . पहला timestamp
की व्याख्या करता है मान के रूप में (दिया गया) UTC टाइमस्टैम्प timestamptz
. प्रकार लौटा रहा है . दूसरा timestamptz
. को रूपांतरित करता है timestamp
. के लिए दिए गए समय क्षेत्र 'ईएसटी' में - इस समय समय क्षेत्र ईएसटी में एक दीवार घड़ी क्या प्रदर्शित करती है।
उदाहरण
SELECT ts AT TIME ZONE 'UTC'
FROM (
VALUES
(1, timestamptz '2012-03-05 17:00:00+0')
, (2, timestamptz '2012-03-05 18:00:00+1')
, (3, timestamptz '2012-03-05 17:00:00 UTC')
, (4, timestamp '2012-03-05 11:00:00' AT TIME ZONE '+6')
, (5, timestamp '2012-03-05 17:00:00' AT TIME ZONE 'UTC')
, (6, timestamp '2012-03-05 07:00:00' AT TIME ZONE 'US/Hawaii') -- ①
, (7, timestamptz '2012-03-05 07:00:00 US/Hawaii') -- ①
, (8, timestamp '2012-03-05 07:00:00' AT TIME ZONE 'HST') -- ①
, (9, timestamp '2012-03-05 18:00:00+1') -- ② loaded footgun!
) t(id, ts);
रिटर्न 8 (या 9) समान समान UTC टाइमस्टैम्प वाले टाइमस्टैम्प्टज़ कॉलम वाली पंक्तियाँ 2012-03-05 17:00:00
. 9वीं पंक्ति मेरे समय क्षेत्र में काम करने के लिए होती है, लेकिन यह एक बुरा जाल है। नीचे देखें।
① पंक्तियाँ 6 - 8 समय क्षेत्र के साथ नाम और समय क्षेत्र संक्षिप्त नाम हवाई समय के लिए डीएसटी (डेलाइट सेविंग टाइम) के अधीन हैं और भिन्न हो सकते हैं, हालांकि वर्तमान में नहीं। एक समय क्षेत्र का नाम जैसे 'US/Hawaii'
डीएसटी नियमों और सभी ऐतिहासिक बदलावों से स्वचालित रूप से अवगत है, जबकि एक संक्षिप्त नाम जैसे HST
एक निश्चित ऑफसेट के लिए सिर्फ एक गूंगा कोड है। आपको गर्मी/मानक समय के लिए एक अलग संक्षिप्त नाम जोड़ने की आवश्यकता हो सकती है। नाम कोई भी की सही व्याख्या करता है दिए गए समय क्षेत्र पर टाइमस्टैम्प। एक संक्षिप्त नाम सस्ता है, लेकिन दिए गए टाइमस्टैम्प के लिए सही होना चाहिए:
- समय क्षेत्र के नाम समान गुणों वाले टाइमस्टैम्प पर लागू होने पर अलग परिणाम देते हैं
डेलाइट सेविंग टाइम मानवता के अब तक के सबसे उज्ज्वल विचारों में से नहीं है। उप>
② पंक्ति 9, लोडेड फ़ुटगन . के रूप में चिह्नित काम करता है मेरे लिए , लेकिन केवल संयोग से। यदि आप स्पष्ट रूप से timestamp [without time zone]
. के लिए एक शाब्दिक कास्ट करते हैं , किसी भी समय क्षेत्र ऑफ़सेट पर ध्यान नहीं दिया जाता है! केवल नंगे टाइमस्टैम्प का उपयोग किया जाता है। फिर मान को स्वचालित रूप से timestamptz
. के लिए बाध्य किया जाता है उदाहरण में कॉलम प्रकार से मेल खाने के लिए। इस चरण के लिए, timezone
वर्तमान सत्र की सेटिंग मान ली जाती है, जो एक ही समय क्षेत्र +1
. होता है मेरे मामले में (यूरोप/वियना)। लेकिन शायद आपके मामले में नहीं - जिसके परिणामस्वरूप एक अलग मूल्य होगा। संक्षेप में:कास्ट न करें timestamptz
timestamp
. के लिए शाब्दिक या आप समय क्षेत्र ऑफ़सेट खो देते हैं।
आपके प्रश्न
<ब्लॉकक्वॉट>उपयोगकर्ता एक समय संग्रहीत करता है, मान लीजिए 17 मार्च 2012, शाम 7 बजे। मैं नहीं चाहता कि समयक्षेत्ररूपांतरण या समयक्षेत्र संगृहीत किया जाए।
समय क्षेत्र स्वयं कभी संग्रहीत नहीं होता है। UTC टाइमस्टैम्प दर्ज करने के लिए उपरोक्त विधियों में से किसी एक का उपयोग करें।
<ब्लॉकक्वॉट>मैं उपयोगकर्ताओं के स्थानीय समय क्षेत्र में वर्तमान समय के 'पहले' या 'बाद' रिकॉर्ड प्राप्त करने के लिए केवल निर्दिष्ट समय क्षेत्र का उपयोग करता हूं।
आप अलग-अलग समय क्षेत्रों में सभी क्लाइंट के लिए एक क्वेरी का उपयोग कर सकते हैं।
संपूर्ण वैश्विक समय के लिए:
SELECT * FROM tbl WHERE time_col > (now() AT TIME ZONE 'UTC')::time
स्थानीय घड़ी के अनुसार समय के लिए:
SELECT * FROM tbl WHERE time_col > now()::time
पृष्ठभूमि की जानकारी से थके नहीं हैं, फिर भी? मैनुअल में और भी बहुत कुछ है।