कुछ समय पहले, हमने सिस्टम को नए बाजार के अनुकूल बनाना शुरू किया, जिसमें समय क्षेत्रों के लिए समर्थन की आवश्यकता होती है। प्रारंभिक शोध का वर्णन पिछले लेख में किया गया था। अब दृष्टिकोण वास्तविकताओं के प्रभाव में थोड़ा विकसित हुआ है। यह लेख चर्चा के दौरान आने वाली समस्याओं और लागू किए गए अंतिम निर्णय का वर्णन करता है।
TL;DR
- शब्दों में अंतर करना आवश्यक है:
- यूटीसी +00:00 क्षेत्र में डीएसटी प्रभाव के बिना स्थानीय समय है
- DateTimeOffset - UTC ± NN:NN से स्थानीय समय ऑफ़सेट, जहां ऑफ़सेट DST प्रभाव के बिना UTC से बेस ऑफ़सेट है (C# TimeZoneInfo.BaseUtcOffset में)
- दिनांक समय - समय क्षेत्र के बारे में जानकारी के बिना स्थानीय समय (हम तरह की विशेषता को अनदेखा करते हैं)
- उपयोग को बाहरी और आंतरिक में विभाजित करें:
- एपीआई, संदेश, फ़ाइल निर्यात/आयात के माध्यम से इनपुट और आउटपुट डेटा सख्ती से यूटीसी (दिनांक समय प्रकार) में होना चाहिए
- सिस्टम के अंदर, डेटा को ऑफ़सेट (DateTimeOffset type) के साथ स्टोर किया जाता है
- पुराने कोड में उपयोग को गैर-डीबी कोड (सी#, जेएस) और डीबी में विभाजित करें:
- गैर-डीबी कोड केवल स्थानीय मानों (दिनांक समय प्रकार) के साथ काम करता है
- डेटाबेस स्थानीय मानों + ऑफ़सेट (DateTimeOffset प्रकार) के साथ काम करता है
- नए प्रोजेक्ट (घटक) डेटटाइम ऑफसेट का उपयोग करते हैं।
- डेटाबेस में, डेटटाइम प्रकार केवल डेटटाइम ऑफसेट में बदल जाता है:
- टेबल फ़ील्ड प्रकारों में
- संग्रहीत कार्यविधियों के मापदंडों में
- असंगत निर्माण कोड में तय किए गए हैं
- ऑफ़सेट जानकारी प्राप्त मूल्य (सरल संयोजन) से जुड़ी होती है
- गैर-डीबी कोड पर लौटने से पहले, मान को स्थानीय में बदल दिया जाता है
- गैर-डीबी कोड में कोई बदलाव नहीं
- डीएसटी को सीएलआर संग्रहित प्रक्रियाओं का उपयोग करके हल किया जाता है (एसक्यूएल सर्वर 2016 के लिए आप एटी टाइम ज़ोन का उपयोग कर सकते हैं)।
अब, उन कठिनाइयों के बारे में विस्तार से, जिन्हें दूर किया गया था।
आईटी उद्योग के "गहरी जड़ें" मानक
ऑफसेट के साथ स्थानीय समय में तारीखों को स्टोर करने के डर से लोगों को राहत देने में काफी समय लगा। कुछ समय पहले, यदि आप एक अनुभवी प्रोग्रामर से पूछते हैं:"समय क्षेत्र का समर्थन कैसे करें?" - एकमात्र विकल्प था:"यूटीसी का प्रयोग करें और प्रदर्शन से ठीक पहले स्थानीय समय में कनवर्ट करें"। तथ्य यह है कि सामान्य वर्कफ़्लो के लिए आपको अभी भी अतिरिक्त जानकारी की आवश्यकता होती है, जैसे कि ऑफ़सेट और समय क्षेत्र के नाम, कार्यान्वयन के हुड के नीचे छिपा हुआ था। डेटटाइम ऑफसेट के आगमन के साथ, इस तरह के विवरण सामने आए, लेकिन "प्रोग्रामिंग अनुभव" की जड़ता एक और तथ्य के साथ जल्दी से सहमत होने की अनुमति नहीं देती है:"एक मूल यूटीसी ऑफसेट के साथ एक स्थानीय तिथि को संग्रहीत करना" यूटीसी को संग्रहीत करने के समान है। हर जगह DateTimeOffset का उपयोग करने का एक अन्य लाभ आपको .NET फ्रेमवर्क और SQL सर्वर समय क्षेत्रों के पालन पर नियंत्रण सौंपने की अनुमति देता है, मानव नियंत्रण के लिए केवल सिस्टम से डेटा इनपुट और आउटपुट के क्षण छोड़ देता है। मानव नियंत्रण एक प्रोग्रामर द्वारा दिनांक/समय मानों के साथ काम करने के लिए लिखा गया कोड है।
इस डर को दूर करने के लिए, मुझे स्पष्टीकरण, उदाहरण प्रस्तुत करने और अवधारणा के प्रमाण के साथ एक से अधिक सत्र आयोजित करने पड़े। परियोजना में हल किए गए कार्यों के उदाहरण जितने सरल और करीब होंगे, उतना ही बेहतर होगा। यदि आप "सामान्य रूप से" चर्चा में शुरू करते हैं, तो यह समझने और समय बर्बाद करने की जटिलता की ओर जाता है। संक्षेप में:कम सिद्धांत - अधिक अभ्यास। UTC के लिए और DateTimeOffset के विरुद्ध तर्क दो श्रेणियों से संबंधित हो सकते हैं:
- “हर समय यूटीसी” मानक है और बाकी काम नहीं करता
- यूटीसी डीएसटी के साथ समस्या का समाधान करता है
यह ध्यान दिया जाना चाहिए कि न तो यूटीसी और न ही डेटटाइम ऑफसेट डीएसटी के साथ समस्या को हल करता है, बिना ज़ोन के बीच कनवर्ट करने के नियमों के बारे में जानकारी का उपयोग किए, जो सी # में टाइमज़ोनइन्फो क्लास के माध्यम से उपलब्ध है।
सरलीकृत मॉडल
जैसा कि मैंने ऊपर उल्लेख किया है, पुराने कोड में, परिवर्तन केवल डेटाबेस में होते हैं। इसका आकलन एक साधारण उदाहरण से किया जा सकता है।
टी-एसक्यूएल में एक मॉडल का उदाहरण
// 1) data storage // input data in the user's locale, as he sees them declare @input_user1 datetime = '2017-10-27 10:00:00' // there is information about the zone in the user configuration declare @timezoneOffset_user1 varchar(10) = '+03:00' declare @storedValue datetimeoffset // upon receiving values, attach the user’s offset set @storedValue = TODATETIMEOFFSET(@input_user1, @timezoneOffset_user1) // this value will be saved select @storedValue 'stored' // 2) display of information // a different time zone is specified in the second user’s configuration, declare @timezoneOffset_user2 varchar(10) = '-05:00' // before returning to the client code, values are reduced to local ones // this is how the data will look like in the database and on users’ displays select @storedValue 'stored value', CONVERT(DATETIME, SWITCHOFFSET(@storedValue, @timezoneOffset_user1)) 'user1 Moscow', CONVERT(DATETIME, SWITCHOFFSET(@storedValue, @timezoneOffset_user2)) 'user2 NY' // 3) now the second user saves the data declare @input_user2 datetime // input local values are received, as the user sees them in New York set @input_user2 = '2017-10-27 02:00:00.000' // link to the offset information set @storedValue = TODATETIMEOFFSET(@input_user2, @timezoneOffset_user2) select @storedValue 'stored' // 4) display of information select @storedValue 'stored value', CONVERT(DATETIME, SWITCHOFFSET(@storedValue, @timezoneOffset_user1)) 'user1 Moscow', CONVERT(DATETIME, SWITCHOFFSET(@storedValue, @timezoneOffset_user2)) 'user2 NY'
स्क्रिप्ट निष्पादन का परिणाम इस प्रकार होगा।
उदाहरण से पता चलता है कि यह मॉडल केवल डेटाबेस में परिवर्तन करने की अनुमति देता है, जो दोषों के जोखिम को काफी कम करता है।
दिनांक/समय मानों को संसाधित करने के लिए कार्यों के उदाहरण
// When receiving values from the non-DB code in DateTimeOffset, they will be local, // but with offset +00:00, so you must attach a user’s offset, but you cannot convert between // time zones. To do this, we translate the value into DateTime and then back with the indication of the offset // DateTime is converted to DateTimeOffset without problems, // so you do not need to change the call of the stored procedures in the client code create function fn_ConcatinateWithTimeOffset(@dto datetimeoffset, @userId int) returns DateTimeOffset as begin declare @user_time_zone varchar(10) set @user_time_zone = '-05:00' // from the user's settings @userId return todatetimeoffset(convert(datetime, @dto), @user_time_zone) end // Client code cannot read DateTimeOffset into variables of the DateTime type, // so you need to not only convert to a correct time zone but also reduce to DateTime, // otherwise, there will be an error create function fn_GetUserDateTime(@dto datetimeoffset, @userId int) returns DateTime as begin declare @user_time_zone varchar(10) set @user_time_zone = '-05:00' // from the user's settings @userId return convert(datetime, switchoffset(@dto, @user_time_zone)) end
छोटी कलाकृतियां
SQL कोड के समायोजन के दौरान, कुछ चीजें पाई गईं जो डेटटाइम के लिए काम करती हैं, लेकिन डेटटाइम ऑफसेट के साथ असंगत हैं:
GETDATE()+1 को DATEADD से बदला जाना चाहिए (दिन, 1, SYSDATETIMEOFFSET ())
DEFAULT कीवर्ड DateTimeOffset के साथ असंगत है, आपको SYSDATETIMEOFFSET()
का उपयोग करने की आवश्यकता हैISNULL(date_field, NULL)> 0″ निर्माण डेटटाइम के साथ काम करता है, लेकिन डेटटाइम ऑफसेट को "date_field IS NOT NULL" से बदला जाना चाहिए
निष्कर्ष या UTC बनाम DateTimeOffset
कोई यह देख सकता है कि, जैसा कि यूटीसी के दृष्टिकोण में है, हम डेटा प्राप्त करते और वापस करते समय रूपांतरण से निपटते हैं। फिर हमें इस सब की आवश्यकता क्यों है, अगर एक अच्छी तरह से आजमाया हुआ और काम करने वाला समाधान है? इसके कई कारण हैं:
- DateTimeOffset आपको यह भूलने की अनुमति देता है कि SQL सर्वर कहाँ स्थित है।
- इससे आप काम के कुछ हिस्से को सिस्टम में शिफ्ट कर सकते हैं।
- रूपांतरण को कम किया जा सकता है यदि DateTimeOffset का उपयोग हर जगह किया जाता है, इसे केवल डेटा प्रदर्शित करने या बाहरी सिस्टम पर आउटपुट करने से पहले निष्पादित किया जाता है।
इस दृष्टिकोण का उपयोग करने के कारण ये कारण मुझे आवश्यक लगे।
मुझे आपके सवालों का जवाब देने में खुशी होगी, कृपया टिप्पणी लिखें।