TSQL: स्थानीय समय को यूटीसी में कैसे बदलें? (SQL Server 2008)


82

हम एक ऐसे अनुप्रयोग के साथ काम कर रहे हैं, जिसमें विभिन्न समय क्षेत्रों और दिन के समय की बचत समय सेटिंग्स से वैश्विक समय के डेटा को संभालने की आवश्यकता है। यह विचार यूटीसी प्रारूप में सब कुछ आंतरिक रूप से संग्रहीत करने के लिए है और केवल स्थानीय उपयोगकर्ता इंटरफेस के लिए आगे और पीछे परिवर्तित करना है। क्या SQL सर्वर एक समय, एक देश और एक समयक्षेत्र दिए गए अनुवादों से निपटने के लिए कोई तंत्र प्रदान करता है?

यह एक सामान्य समस्या होनी चाहिए, इसलिए मुझे आश्चर्य है कि Google कुछ भी उपयोग करने योग्य नहीं होगा।

कोई संकेत?


मेरे पास मेरा mssql- सर्वर एक mysql- सर्वर से जुड़ा हुआ है। मुझे आश्चर्य है कि अगर प्रश्नों पर mysql CONVERT_TZ (समय, srczone, dstzone) को चलाना संभव है, तो इस फ़ंक्शन को याद नहीं है। यह linux में बनाया गया है।
लेईफ नेलैंड

1
@BuschnicK नीचे मेरा जवाब देखें। वास्तव में मुझे लगता है कि आप इसे स्वीकार कर सकते हैं यहां तक ​​कि दूसरों को ढूंढना आसान है।
पायोत्र ओविसक

संक्षिप्त उत्तर: SQL सर्वर 2016 से पहले ऐसा करने का कोई अंतर्निहित तरीका नहीं है, इसलिए इसे पूर्व संस्करणों पर कस्टम कोड की आवश्यकता होगी।
लेहिस्टर

मध्यम उत्तर: SQL सर्वर 2016 से पहले हर समय कार्यशीलता ऑफ़सेट केवल पूर्ण ऑफ़सेट के साथ काम करती है, दिन के समय की बचत समय के कारण अधिकांश समय क्षेत्रों में होने वाले चर ऑफ़सेट के लिए कोई समर्थन नहीं है। क्वेरी के पास सर्वर के स्थानीय समय की वर्तमान ऑफसेट होने के अलावा जो कुछ भी होता है, को छोड़कर समय के ऑफसेट तक पहुंचने का कोई तरीका नहीं है, जो रूपांतरण को स्वचालित करने की कोशिश के लिए बेकार है।
लेहिस्टर

जवाबों:


49

7 साल बीत गए और ...
वास्तव में यह नया SQL Server 2016 फीचर है जो वास्तव में आपकी आवश्यकता है।
इसे AT TIME ZONE कहा जाता है और यह DST (दिन के समय की बचत के समय) परिवर्तनों पर विचार करते हुए एक निर्दिष्ट समय क्षेत्र में तारीख को परिवर्तित करता है।
अधिक जानकारी यहां: https://msdn.microsoft.com/en-us/library/mt612795.aspx


19
अब इस पर काम नहीं कर रहा है - उस प्रोजेक्ट पर नहीं, SQL सर्वर पर नहीं, उसी कंपनी में नहीं और उसी देश में भी नहीं;; अभी।
बुसचेनिक

2
@BuschnicK हाँ, मैं आंकता हूं, लेकिन मैं यहां उसी समस्या का हल ढूंढ रहा हूं, जो आपने किया था इसलिए मैंने अब एक आसन पोस्ट करने का फैसला किया है कि एक वास्तविक समाधान है: D
Piotr Owsiak

5
प्रश्न SQL Server 2008 के लिए है। यदि आप इस उत्तर को स्वीकार करते हैं तो कृपया प्रश्न को अपडेट करें। Thx
रॉबर्ट

1
UTC में बदलने के लिए आप 'AT TIME ZONE' UTC 'कर सकते हैं।
क्रेज़ीसेरियस

1
@Piotr Owsiak: हाँ, लेकिन यह मानता है कि इनपुट समय UTC है, जो व्यर्थ है यदि आप स्थानीय समय से UTC में बदलना चाहते हैं ... तो 7 साल बीत गए, और उन्हें अभी भी नहीं लगता कि यह ठीक से संभालने लायक है। ..
स्टीफन स्टीगर

65

यह उन तारीखों के लिए काम करता है जो वर्तमान में SQL सर्वर के होस्ट के समान UTC ऑफसेट हैं; यह दिन के उजाले बचत के लिए जिम्मेदार नहीं है। बदलने YOUR_DATEके लिए स्थानीय तिथि के साथ बदलें ।

SELECT DATEADD(second, DATEDIFF(second, GETDATE(), GETUTCDATE()), YOUR_DATE);


2
धन्यवाद, यह एक अच्छा विचार है, लेकिन यह केवल एक टाइमज़ोन के लिए काम करता है - स्थानीय मशीन। हमें इसके लिए मनमाने समय के लिए काम करने की आवश्यकता है ...
BuschnicK

51
यह दिन के उजाले की बचत का समय नहीं है
गैब्रियल मैकएडम्स

10
नहीं! अंतर सटीक तिथि पर निर्भर है। यह दिन के उजाले-बचत पर निर्भर करता है।
usr

3
मेरे मामले में मुझे सिर्फ 1 टाइमज़ोन की ज़रूरत थी, और इसने बहुत काम किया! धन्यवाद।
एम थेलेन

10
यह अच्छी तरह से काम करता है अगर आप जानते हैं कि आपका आज का इतिहास ऐतिहासिक रूप से नहीं चल रहा है, तो धन्यवाद
डेविड एडलिंगटन

22

हालांकि इनमें से कुछ उत्तर आपको बॉलपार्क में मिलेंगे, आप वह नहीं कर सकते जो आप SqlServer 2005 के लिए मनमानी तारीखों के साथ करने की कोशिश कर रहे हैं और इससे पहले दिन की बचत समय की वजह से। वर्तमान स्थानीय और वर्तमान UTC के बीच के अंतर का उपयोग करने से मुझे ऑफसेट मिलेगा क्योंकि यह आज भी मौजूद है। मुझे यह निर्धारित करने का कोई तरीका नहीं मिला है कि प्रश्न में तारीख के लिए ऑफसेट क्या होता है।

उस ने कहा, मुझे पता है कि SqlServer 2008 कुछ नए कार्य प्रदान करता है जो उस मुद्दे को संबोधित कर सकते हैं, लेकिन पुराने संस्करण का उपयोग करने वाले लोगों को सीमाओं के बारे में पता होना चाहिए।

हमारा दृष्टिकोण यूटीसी को जारी रखने और ग्राहक पक्ष में रूपांतरण करने के लिए है जहां रूपांतरण की सटीकता पर हमारा अधिक नियंत्रण है।


16

SQL सर्वर 2016 और नए और Azure SQL डेटाबेस के लिए, अंतर्निहित AT TIME ZONEकथन का उपयोग करें ।

SQL सर्वर के पुराने संस्करणों के लिए, आप यहां सूचीबद्ध IANA मानक समय क्षेत्रों के बीच परिवर्तित करने के लिए मेरे SQL सर्वर टाइम ज़ोन समर्थन परियोजना का उपयोग कर सकते हैं

UTC to लोकल इस तरह है:

SELECT Tzdb.UtcToLocal('2015-07-01 00:00:00', 'America/Los_Angeles')

UTC के लिए स्थानीय ऐसा है:

SELECT Tzdb.LocalToUtc('2015-07-01 00:00:00', 'America/Los_Angeles', 1, 1)

सांख्यिक विकल्प व्यवहार को नियंत्रित करने के लिए ध्वज हैं जब स्थानीय समय मान दिन के समय की बचत से प्रभावित होते हैं। इन्हें परियोजना के प्रलेखन में विस्तार से वर्णित किया गया है।


1
कैसे आदमी ... मैट की यह परियोजना महान है और सीएलआर की आवश्यकता नहीं है। मैट इस क्रेडिट के लिए +100
बकले

14

SQL Server 2008 में एक प्रकार है datetimeoffset। यह इस प्रकार के सामान के लिए वास्तव में उपयोगी है।

http://msdn.microsoft.com/en-us/library/bb630289.aspx

फिर आप फ़ंक्शन SWITCHOFFSETको एक टाइमज़ोन से दूसरे तक ले जाने के लिए उपयोग कर सकते हैं , लेकिन फिर भी समान यूटीसी मूल्य रखते हुए।

http://msdn.microsoft.com/en-us/library/bb677244.aspx

लूटना


6
SWITCHOFFSET दिन की बचत के लिए खाता नहीं है, इसलिए यह केवल कुछ स्थितियों में ही उपयोगी है।
रोबोकट

2
नहीं। लेकिन सवाल यह था कि जो भी टाइम ज़ोन करने का अनुरोध किया गया था, उस पर स्विच करने में सक्षम था।
रोब फ़ार्ले

प्रश्न "विभिन्न समय क्षेत्रों और दिन के उजाले बचत समय सेटिंग्स" से। हम भी स्थानीय समय के लिए एक समाधान की तलाश कर रहे हैं। आपका सुझाव दिन के उजाले की बचत के मुद्दे को हल नहीं करता है?
रोबोकट

किसी भी समय जब आपको किसी क्लाइंट पर टाइम ज़ोन का पता लगाने की आवश्यकता होती है और फिर डेटाबेस को निर्दिष्ट समय क्षेत्र में वापसी समय होता है, तो SWITCHOFFSET फ़ंक्शन बहुत उपयोगी होता है।
रोब फार्ले

3
@RobFarley क्लाइंट में टाइम ज़ोन का पता लगाना और SWITCHOFFSET का उपयोग करना अभी भी गलत हो सकता है। आपको यह जानने की जरूरत है कि आप जिस तारीख और समय को परिवर्तित कर रहे हैं, वह डेलाइट सेविंग टाइम लागू है या नहीं। बस समय क्षेत्र का पता लगाना और यूटीसी के लिए वर्तमान ऑफसेट को लागू करना एक घंटे की छुट्टी हो सकती है - और यह एक साधारण मामले में है जहां आपके सभी रूपांतरण एक ही देश में हैं। प्रत्येक देश एक ही तारीखों पर दिन के उजाले बचत समय से / पर नहीं जाता है। यदि आप स्थानीय समय स्टोर करते हैं और उसी देश के भीतर मूल और लक्ष्य क्षेत्र के बीच अंतर जानते हैं, तो SWITCHOFFSET अच्छा काम करता है।
जेमीसी

12

यहाँ एक ज़ोन DateTimeको दूसरे ज़ोन में बदलने का कोड हैDateTime

DECLARE @UTCDateTime DATETIME = GETUTCDATE();
DECLARE @ConvertedZoneDateTime DATETIME;

-- 'UTC' to 'India Standard Time' DATETIME
SET @ConvertedZoneDateTime = @UTCDateTime AT TIME ZONE 'UTC' AT TIME ZONE 'India Standard Time'
SELECT @UTCDateTime AS UTCDATE,@ConvertedZoneDateTime AS IndiaStandardTime

-- 'India Standard Time' to 'UTC' DATETIME
SET @UTCDateTime = @ConvertedZoneDateTime AT TIME ZONE 'India Standard Time' AT TIME ZONE 'UTC'
SELECT @ConvertedZoneDateTime AS IndiaStandardTime,@UTCDateTime AS UTCDATE

नोट : AT TIME ZONE केवल SQL सर्वर 2016+ पर काम करता है और लाभ यह है कि किसी विशेष समय क्षेत्र में परिवर्तित होने पर यह स्वचालित रूप से डेलाइट पर विचार करता है


2
मुझे यह पसंद है, अगर इस तथ्य के अलावा कोई अन्य कारण नहीं है कि यह दिखाता है कि आप AT TIME ZONEएक साथ कई कॉल (वाक्यांश?) को चेन कर सकते हैं! बस सुरुचिपूर्ण। मैंने पहले कहा था कि stackoverflow.com/a/44579178/112764 मेरी जरूरतों को पूरा करता है, लेकिन यह और भी बेहतर है। प्रमुख कुडो।
नैटज

DECLARE @UTCDateTime DATETIME = GETUTCDATE(); DECLARE @ConvertedZoneDateTime DATETIME; -- 'UTC' to 'India Standard Time' to 'Eastern Standard Time' DATETIME SET @ConvertedZoneDateTime = @UTCDateTime AT TIME ZONE 'UTC' AT TIME ZONE 'India Standard Time' AT TIME ZONE 'Eastern Standard Time' SELECT @UTCDateTime AS UTCDATE,@ConvertedZoneDateTime AS EasternStandardTime हां, आप अनेक श्रृंखला कर सकते हैं AT TIME ZONEकॉल, लेकिन से और करने के लिए किसी भी रूपांतरण के लिए पर्याप्त है और सबसे हम की जरूरत
KarthikeyanMlp

4

मैं सभी तारीख-समय के भंडारण के लिए DateTimeOffset का उपयोग करने की ओर झुकाव करता हूं जो एक स्थानीय घटना से संबंधित नहीं है (जैसे: बैठक / पार्टी, आदि, दोपहर 12 बजे संग्रहालय में)।

वर्तमान DTO को UTC के रूप में प्राप्त करने के लिए:

DECLARE @utcNow DATETIMEOFFSET = CONVERT(DATETIMEOFFSET, SYSUTCDATETIME())
DECLARE @utcToday DATE = CONVERT(DATE, @utcNow);
DECLARE @utcTomorrow DATE = DATEADD(D, 1, @utcNow);
SELECT  @utcToday [today]
        ,@utcTomorrow [tomorrow]
        ,@utcNow [utcNow]

नोट: मैं हमेशा UTC का उपयोग तार पर भेजते समय करूंगा ... क्लाइंट-साइड JS आसानी से / स्थानीय UTC से प्राप्त कर सकता है। देखें: new Date().toJSON()...

निम्नलिखित JS ISO8601 प्रारूप में UTC / GMT दिनांक को स्थानीय डेटाइम में पार्स करने का काम करेगा।

if (typeof Date.fromISOString != 'function') {
  //method to handle conversion from an ISO-8601 style string to a Date object
  //  Date.fromISOString("2009-07-03T16:09:45Z")
  //    Fri Jul 03 2009 09:09:45 GMT-0700
  Date.fromISOString = function(input) {
    var date = new Date(input); //EcmaScript5 includes ISO-8601 style parsing
    if (!isNaN(date)) return date;

    //early shorting of invalid input
    if (typeof input !== "string" || input.length < 10 || input.length > 40) return null;

    var iso8601Format = /^(\d{4})-(\d{2})-(\d{2})((([T ](\d{2}):(\d{2})(:(\d{2})(\.(\d{1,12}))?)?)?)?)?([Zz]|([-+])(\d{2})\:?(\d{2}))?$/;

    //normalize input
    var input = input.toString().replace(/^\s+/,'').replace(/\s+$/,'');

    if (!iso8601Format.test(input))
      return null; //invalid format

    var d = input.match(iso8601Format);
    var offset = 0;

    date = new Date(+d[1], +d[2]-1, +d[3], +d[7] || 0, +d[8] || 0, +d[10] || 0, Math.round(+("0." + (d[12] || 0)) * 1000));

    //use specified offset
    if (d[13] == 'Z') offset = 0-date.getTimezoneOffset();
    else if (d[13]) offset = ((parseInt(d[15],10) * 60) + (parseInt(d[16],10)) * ((d[14] == '-') ? 1 : -1)) - date.getTimezoneOffset();

    date.setTime(date.getTime() + (offset * 60000));

    if (date.getTime() <= new Date(-62135571600000).getTime()) // CLR DateTime.MinValue
      return null;

    return date;
  };
}

+1 मैंने भी डेटटाइमऑफसेट पर स्विच कर लिया है। यह UTC + स्थानीय रूपांतरणों के साथ कई मुद्दों से बचा जाता है। हालांकि, इसी तरह के कारणों के लिए, मैं एक ऑफसेट ओवर-द-वायर (JSON के माध्यम से) के साथ ही मान भेजने की सलाह देता हूं।
user2864740

एक नोट के रूप में, मैं वही करता हूं जो आप दूसरे तरीके से करते हैं । DateTimes के लिए जो किसी स्थानीय ईवेंट से बंधे हैं, मैं एक DateTimeOffset स्टोर करता हूं। किसी स्थानीय ईवेंट से बंधे किसी डेटटाइम के लिए, मैं UTC में एक डेटटाइम स्टोर करता हूं। पूर्व में दो प्रासंगिक डेटा पॉइंट हैं (जब यह स्थानीय समय में होता है, और स्थानीय समय क्या होता है), बाद वाला केवल एक (जब यह होता है)
Martijn

@Martijn लेकिन टाइमज़ोन आपको स्थान नहीं देता है, और आपको किसी भी तरह अलग से संग्रहीत करना होगा।
ट्रैकर

@ tracker1 यह केवल तभी काम करता है जब स्थान के पास अपने समयक्षेत्र को जानने का एक तरीका होता है, और तब भी इसे बदलने के लिए एक पूर्ण पीड़ा होती है।
Martijn

3

हाँ, यहाँ कुछ हद तक विस्तृत है
मैंने (2008 से पहले) जो दृष्टिकोण का उपयोग किया है, वह डीबी में डालने से पहले .NET व्यापार तर्क में रूपांतरण करना है।


1

आप UTC डेटाइम प्राप्त करने के लिए GETUTCDATE () फ़ंक्शन का उपयोग कर सकते हैं संभवतः आप GETUTCDATE () और GETDATE () के बीच अंतर का चयन कर सकते हैं और इस अंतर का उपयोग करके UTC के लिए अपनी तिथियों को निर्धारित कर सकते हैं

लेकिन मैं पिछले संदेश से सहमत हूं, कि व्यापार परत में सही डेटाइम को नियंत्रित करना बहुत आसान है (उदाहरण के लिए .NET में)।


12
नहीं! अंतर सटीक तिथि पर निर्भर है। यह दिन के उजाले-बचत पर निर्भर करता है।
usr

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

-1

नमूना उपयोग:

SELECT
    Getdate=GETDATE()
    ,SysDateTimeOffset=SYSDATETIMEOFFSET()
    ,SWITCHOFFSET=SWITCHOFFSET(SYSDATETIMEOFFSET(),0)
    ,GetutcDate=GETUTCDATE()
GO

यह दिखाता है:

Getdate SysDateTimeOffset   SWITCHOFFSET    GetutcDate
2013-12-06 15:54:55.373 2013-12-06 15:54:55.3765498 -08:00  2013-12-06 23:54:55.3765498 +00:00  2013-12-06 23:54:55.373
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.