प्रश्न डेलाइट सेविंग टाइम और टाइम ज़ोन सर्वोत्तम अभ्यास पढ़ें। आपका मूल रूप से एक डुप्लिकेट है।
UTC में सर्वर
हां, आम तौर पर सर्वरों को अपने ओएस को समय क्षेत्र के रूप में यूटीसी पर सेट करना चाहिए, या यदि प्रदान नहीं किया गया है तो GMT
का उपयोग करें। या रेकजाविक आइसलैंड समय क्षेत्र। आपका जावा कार्यान्वयन शायद इस सेटिंग को अपने वर्तमान डिफ़ॉल्ट समय क्षेत्र के रूप में चुनता है।
समय क्षेत्र निर्दिष्ट करें
लेकिन यूटीसी पर सेट किए जा रहे समय क्षेत्र पर निर्भर न रहें। एक sysadmin इसे बदल सकता है। और आपके JVM के किसी भी ऐप के किसी भी थ्रेड में कोई भी जावा कोड JVM के वर्तमान डिफ़ॉल्ट समय क्षेत्र को रनटाइम पर बदल सकता है। TimeZone.setDefault
. पर कॉल करके . इसलिए इसके बजाय, अपने जावा कोड में वैकल्पिक तर्क पास करके हमेशा वांछित/अपेक्षित समय क्षेत्र निर्दिष्ट करने की आदत डालें।
मैं इसे एक डिज़ाइन दोष मानता हूं कि कोई भी दिनांक-समय ढांचा समय क्षेत्र को वैकल्पिक बना देगा। वैकल्पिक होना अनंत मात्रा में भ्रम पैदा करता है क्योंकि प्रोग्रामर, हर किसी की तरह, अनजाने में अपने स्वयं के व्यक्तिगत समय क्षेत्र के संदर्भ में सोचते हैं जब तक कि संकेत न दिया जाए। इसलिए अक्सर डेट-टाइम काम में इस मुद्दे पर कोई ध्यान नहीं दिया जाता है। समस्या पर जोड़ें कि JVM डिफ़ॉल्ट भिन्न होता है। वैसे, Locale
. के लिए ठीक वैसा ही , वही समस्याएं, हमेशा स्पष्ट रूप से निर्दिष्ट की जानी चाहिए।
यूटीसी
आपका व्यावसायिक तर्क, डेटा संग्रहण, और डेटा विनिमय लगभग हमेशा UTC में किया जाना चाहिए। लगभग हर डेटाबेस में किसी भी इनपुट को यूटीसी में एडजस्ट करने और यूटीसी में स्टोर करने की सुविधा होती है।
किसी उपयोगकर्ता को दिनांक-समय प्रस्तुत करते समय, अपेक्षित समय क्षेत्र में समायोजित करें। दिनांक-समय मान को क्रमबद्ध करते समय, ISO 8601 स्ट्रिंग स्वरूपों का उपयोग करें। विशेष रूप से Oracle के लिए विक्की अरोड़ा द्वारा उत्तर देखें (मैं एक पोस्टग्रेज व्यक्ति हूं)। दस्तावेज़ को ध्यान से पढ़ना सुनिश्चित करें, और अपने डेटाबेस के व्यवहार को पूरी तरह से समझने के लिए प्रयोग करके अभ्यास करें। इस संबंध में SQL विनिर्देश बहुत अधिक स्पष्ट नहीं करता है, और व्यवहार व्यापक रूप से भिन्न होता है।
java.sql
याद रखें कि Java और JDBC का उपयोग करते समय, आप java.sql.Timestamp
का उपयोग करेंगे। और संबंधित डेटा प्रकार। वे हमेशा यूटीसी में स्वचालित रूप से होते हैं। भविष्य में JDBC ड्राइवरों को जावा 8 और बाद में निर्मित java.time ढांचे में परिभाषित नए डेटा प्रकारों का सीधे उपयोग करने के लिए अद्यतन देखने की उम्मीद है।
java.time
पुराने वर्ग java.time द्वारा पुराने हो गए हैं। java.time का उपयोग करना सीखें पुराने java.util.Date/.Calendar से बचते हुए और अपने प्रोग्रामिंग जीवन को और अधिक सुखद बनाएं।
जब तक आपका JDBC ड्राइवर अपडेट नहीं हो जाता, तब तक आप java.time में निर्मित रूपांतरण सुविधा विधियों का उपयोग कर सकते हैं। आगे उदाहरण देखें, जहां Instant
UTC और ZonedDateTime
. में एक क्षण है एक समय क्षेत्र में तत्काल समायोजित किया गया है।
Instant instant = myJavaSqlTimestamp.toInstant();
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
दूसरी दिशा में जाने के लिए।
java.sql.Timestamp myJavaSqlTimestamp = java.sql.Timestamp.from( zdt.toInstant() );
यदि आपको मूल समय क्षेत्र चाहिए, तो उसे संगृहीत करें
यदि आपकी व्यावसायिक आवश्यकताएं मूल इनपुट डेटा के समय क्षेत्र को याद रखने के लिए महत्वपूर्ण मानती हैं, तो उसे स्पष्ट रूप से अपनी डेटाबेस तालिका में एक अलग कॉलम के रूप में संग्रहीत करें। आप ऑफ़सेट-से-UTC का उपयोग कर सकते हैं, लेकिन यह पूरी जानकारी प्रदान नहीं करता है। समय क्षेत्र एक ऑफ़सेट है प्लस डेलाइट सेविंग टाइम जैसी विसंगतियों के अतीत, वर्तमान और भविष्य से निपटने के लिए नियमों का एक सेट। तो एक उचित समय क्षेत्र का नाम सबसे उपयुक्त है जैसे America/Montreal
।
केवल दिनांक अस्पष्ट है
आपने कहा था कि आप दिन के समय और समय क्षेत्र के बिना, कई केवल-दिनांक मान एकत्र करते हैं। java.time में इसके लिए क्लास LocalDate
. है . जैसा कि LocalTime
के साथ होता है और LocalDateTime
, "स्थानीय..." भाग का अर्थ कोई विशेष स्थान नहीं है, इसलिए कोई समय क्षेत्र नहीं है, और इसलिए समयरेखा पर कोई बिंदु नहीं है -- इसका कोई वास्तविक अर्थ नहीं है।
ध्यान रखें कि केवल-दिनांक मान परिभाषा के अनुसार अस्पष्ट है। किसी भी समय, दुनिया भर में तारीख बदलती रहती है। उदाहरण के लिए, पेरिस में मध्यरात्रि के ठीक बाद फ्रांस एक नया दिन है लेकिन मॉन्ट्रियल क्यूबेक में तारीख अभी भी "कल" है।
आमतौर पर व्यापार में कुछ समय क्षेत्र निहित होता है, यहां तक कि अनजाने में भी। डेटा बिंदुओं के बारे में अचेतन अंतर्ज्ञान लंबे समय तक अच्छी तरह से काम नहीं करता है, खासकर सॉफ्टवेयर में। यह स्पष्ट करना बेहतर है कि किस समय क्षेत्र का इरादा था। आप तिथि के साथ-साथ इच्छित क्षेत्र को संग्रहीत कर सकते हैं जैसे डेटाबेस तालिका में एक और कॉलम, या आप अपने प्रोग्रामिंग कोड में एक टिप्पणी कर सकते हैं। मेरा मानना है कि डेट-टाइम वैल्यू स्टोर करना काफी बेहतर और सुरक्षित होगा। तो हम केवल-तिथि को दिनांक-समय में कैसे बदलते हैं?
अक्सर एक नया दिन मध्यरात्रि के बाद का क्षण होता है, दिन का पहला क्षण। आप सोच सकते हैं कि इसका मतलब दिन का समय है 00:00:00.0
लेकिन हमेशा नहीं। डेलाइट सेविंग टाइम (डीएसटी) और संभवतः अन्य विसंगतियां पहले क्षण को एक अलग दीवार-घड़ी के समय में धकेल सकती हैं। java.time को LocalDate
के माध्यम से पहले पल के लिए सही समय-समय निर्धारित करने दें क्लास और उसका atStartOfDay
विधि।
ZoneId zoneId = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( zoneId );
ZonedDateTime todayStart = today.atStartOfDay( zoneId );
कुछ व्यावसायिक संदर्भों में एक नए दिन को व्यावसायिक घंटे के रूप में परिभाषित (या मान लिया गया) किया जा सकता है। उदाहरण के लिए, मान लें कि न्यूयॉर्क में एक प्रकाशक का मतलब है कि उनके स्थानीय समय में सुबह 9 बजे जब वे कहते हैं कि "पुस्तक का मसौदा 2 जनवरी तक है"। आइए उस समय क्षेत्र में उस तिथि के लिए उस समय-समय को प्राप्त करें।
ZoneId zoneId = ZoneId.of( "America/New_York" );
ZonedDateTime zdt = ZonedDateTime.of( 2016 , 1 , 2 , 9 , 0 , 0 , 0 , zoneId );
न्यूज़ीलैंड में कार्यरत लेखक के लिए इसका क्या अर्थ है? withZoneSameInstant
. पर कॉल करके उसे प्रस्तुति के लिए उसके विशेष समय क्षेत्र में समायोजित करें ।
ZoneId zoneId_Pacific_Auckland = ZoneId.of( "Pacific/Auckland" );
ZonedDateTime zdt_Pacific_Auckland = zdt.withZoneSameInstant( zoneId_Pacific_Auckland );
डेटाबेस
डेटाबेस स्टोरेज के लिए हम एक Instant
. में बदल देते हैं (UTC में टाइमलाइन पर एक पल) और java.sql.Timestamp
के रूप में पास करें जैसा कि ऊपर देखा गया है।
java.sql.Timestamp ts = java.sql.Timestamp.from( zdt.toInstant() );
डेटाबेस से पुनर्प्राप्त होने पर, वापस न्यूयॉर्क दिनांक-समय में रूपांतरित करें। java.sql.Timestamp
. से कनवर्ट करें एक Instant
, फिर एक समय क्षेत्र लागू करें ZoneId
ZonedDateTime
. प्राप्त करने के लिए ।
Instant instant = ts.toInstant();
ZoneId zoneId = ZoneId.of( "America/New_York" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId );
यदि आपका डेटाबेस ड्राइवर JDBC 4.2 या बाद के संस्करण का अनुपालन करता है, तो आप java.sql प्रकारों में/से कनवर्ट करने के बजाय सीधे java.time प्रकारों को पास/लाने में सक्षम हो सकते हैं। PreparedStatement::setObject
आज़माएं और ResultSet::getObject
तरीके।