उपयोगकर्ता के समय क्षेत्र और बल को कैसे अनदेखा करें () विशिष्ट समय क्षेत्र का उपयोग करें


104

जेएस ऐप में, मुझे 1270544790922सर्वर (अजाक्स) से टाइमस्टैम्प (eq। ) मिलता है।

उस टाइमस्टैम्प पर आधारित मैं Dateउपयोग करके ऑब्जेक्ट बनाता हूं :

var _date = new Date();
_date.setTime(1270544790922);

अब, _dateवर्तमान उपयोगकर्ता स्थान समय क्षेत्र में टाइमस्टैम्प को डीकोड करें। मैं ऐसा नहीं चाहता।

मैं dateइस टाइमस्टैम्प को यूरोप के हेलसिंकी शहर में वर्तमान समय में परिवर्तित करना चाहूंगा (उपयोगकर्ता के वर्तमान समय क्षेत्र की उपेक्षा)।

मैं उसे कैसे कर सकता हूँ?


मुझे पता है कि हेलसिंकी में टाइम ज़ोन ऑफसेट सर्दियों में +2 और डीएसटी में +3 है। लेकिन कौन जानता है कि डीएसटी कब है? केवल कुछ स्थान तंत्र है जो नहीं उपलब्ध में जे एस है
warpech

यह संभव है, लेकिन जावास्क्रिप्ट के मूल तरीकों का उपयोग नहीं करना, क्योंकि जावास्क्रिप्ट में उपयोगकर्ता के सिस्टम के वर्तमान समयक्षेत्र की तुलना में अन्य टाइमज़ोन के टाइमज़ोन संक्रमण के इतिहास को निर्धारित करने की कोई विधि नहीं है (और यह उस तरह से ब्राउज़र है जो कम से कम जब हम 80 की तारीखों पर निर्भर होते हैं)। लेकिन इस तरह से यह संभव है: stackoverflow.com/a/12814213/1691517 और मुझे लगता है कि मेरा जवाब आपको सही परिणाम देता है।
तिमो किक्कॉन

जवाबों:


64

किसी दिनांक ऑब्जेक्ट का अंतर्निहित मान वास्तव में UTC में है। यह साबित करने के लिए, ध्यान दें कि अगर आप टाइप new Date(0)आप की तरह कुछ दिखाई देगा: Wed Dec 31 1969 16:00:00 GMT-0800 (PST)। 0 को GMT में 0 माना जाता है, लेकिन .toString()विधि स्थानीय समय को दर्शाती है।

बड़े नोट, यूटीसी यूनिवर्सल टाइम कोड के लिए है। 2 अलग-अलग स्थानों में वर्तमान समय एक ही UTC है, लेकिन आउटपुट को अलग-अलग स्वरूपित किया जा सकता है।

हमें यहाँ जो कुछ चाहिए वह है कुछ स्वरूपण

var _date = new Date(1270544790922); 
// outputs > "Tue Apr 06 2010 02:06:30 GMT-0700 (PDT)", for me
_date.toLocaleString('fi-FI', { timeZone: 'Europe/Helsinki' });
// outputs > "6.4.2010 klo 12.06.30"
_date.toLocaleString('en-US', { timeZone: 'Europe/Helsinki' });
// outputs > "4/6/2010, 12:06:30 PM"

यह काम करता है लेकिन .... जब आप उपयोगकर्ता के टाइमज़ोन का वर्णन करते हैं तो आप वास्तव में आपके उद्देश्यों के लिए किसी भी अन्य तारीख के तरीकों का उपयोग नहीं कर सकते हैं। आप जो चाहते हैं, वह दिनांक ऑब्जेक्ट है जो हेलसिंकी टाइमज़ोन से संबंधित है। इस बिंदु पर आपके विकल्प कुछ 3 पार्टी लाइब्रेरी (मैं यह सलाह देता हूं), या दिनांक ऑब्जेक्ट को हैक करने का उपयोग कर रहा हूं ताकि आप इसे अधिकांश तरीकों का उपयोग कर सकें।

विकल्प 1 - पल-समय क्षेत्र की तरह एक 3 पार्टी

moment(1270544790922).tz('Europe/Helsinki').format('YYYY-MM-DD HH:mm:ss')
// outputs > 2010-04-06 12:06:30
moment(1270544790922).tz('Europe/Helsinki').hour()
// outputs > 12

यह एक बहुत अधिक सुंदर लग रहा है कि हम आगे क्या करने जा रहे हैं।

विकल्प 2 - दिनांक ऑब्जेक्ट को हैक करें

var currentHelsinkiHoursOffset = 2; // sometimes it is 3
var date = new Date(1270544790922);
var helsenkiOffset = currentHelsinkiHoursOffset*60*60000;
var userOffset = _date.getTimezoneOffset()*60000; // [min*60000 = ms]
var helsenkiTime = new Date(date.getTime()+ helsenkiOffset + userOffset);
// Outputs > Tue Apr 06 2010 12:06:30 GMT-0700 (PDT)

यह अभी भी सोचता है कि यह GMT-0700 (PDT) है, लेकिन यदि आप बहुत कठिन नहीं हैं, तो आप गलती कर सकते हैं कि किसी दिनांक ऑब्जेक्ट के लिए जो आपके उद्देश्यों के लिए उपयोगी है।

मैंने आसानी से एक हिस्सा छोड़ दिया। आपको परिभाषित करने में सक्षम होने की आवश्यकता है currentHelsinkiOffset। यदि आप date.getTimezoneOffset()सर्वर की ओर से उपयोग कर सकते हैं , या समय क्षेत्र परिवर्तन होने पर वर्णन करने के लिए केवल कुछ का उपयोग कर सकते हैं, जिससे आपकी समस्या का समाधान होना चाहिए।

निष्कर्ष - मुझे लगता है कि विशेष रूप से इस उद्देश्य के लिए आपको क्षण-समय सारणी की तरह एक पुस्तकालय का उपयोग करना चाहिए ।


भी ... एक समान कार्य किया जा सकता है, बस एक स्थान से gmt ऑफसेट का उपयोग करके। आपको उस मामले में जावास्क्रिप्ट की आवश्यकता नहीं है।
पैरिस

क्षमा करें, लेकिन नहीं, मेरा मतलब है इसके विपरीत :) मैंने सवाल संपादित किया, शायद अब यह स्पष्ट हो गया है
वॉरपेच

ठीक है मैंने अपना समाधान बदल दिया। मुझे लगता है कि तुम इसे खोज रहे हो।
पैरिस

दुर्भाग्य से केवल यही एक चीज है जिसके साथ मैं भी आया था। मुझे लगा कि शायद ब्राउज़र मेरे लिए "_helsinkiOffset" उत्पन्न कर सकता है।
प्रातः

2
मेरा मानना ​​है कि *60*60इसके बजाय होना चाहिए *60000, क्योंकि गेटटाइम मिलिसेकंड में है और गेटटाइमज़ोनऑफसेट मिनटों में है, जिसमें से एक मिनट में 60000 मिलीसेकंड हैं, न कि 60 * 60 == 3600
एरोनल्स

20

मिलीसेकंड और उपयोगकर्ता के समय क्षेत्र के लिए, निम्नलिखित का उपयोग करें:

var _userOffset = _date.getTimezoneOffset()*60*1000; // user's offset time
var _centralOffset = 6*60*60*1000; // 6 for central time - use whatever you need
_date = new Date(_date.getTime() - _userOffset + _centralOffset); // redefine variable

केंद्रीय के लिए एक निश्चित ऑफसेट का उपयोग करने के लिए, मैंने 00:00 के एक निश्चित समय के साथ सीएसटी का उपयोग करके एक तिथि बनाने की अवधारणा का उपयोग किया, फिर उस तिथि का परिणाम प्राप्त करें।
बजकर

+1 यह मेरे लिए काम कर गया। यह सुनिश्चित नहीं है कि मिलीसेकंड में निपटने के बिना sure उत्तर ’कैसे काम कर सकता है।
क्रिस वालेस

2
@ ईआरएन आपको समय-सारणी को जोड़ने के लिए नहीं चाहिए, ताकि gmt पर जा सकें और फिर केंद्रीय ऑफसेट को घटा सकें?
कोडर

15

बस एक और दृष्टिकोण

function parseTimestamp(timestampStr) {
  return new Date(new Date(timestampStr).getTime() + (new Date(timestampStr).getTimezoneOffset() * 60 * 1000));
};

//Sun Jan 01 2017 12:00:00
var timestamp = 1483272000000;
date = parseTimestamp(timestamp);
document.write(date);

चीयर्स!


2
यह डेलाइट सेविंग टाइम के कारण अनपेक्षित परिणाम हो सकता है। यदि ग्राहक एक समयक्षेत्र में है जो डीएसटी का उपयोग करता है, तो पार्सिंग का परिणाम एक घंटे तक बंद हो सकता है (कुछ क्षेत्र एक घंटे के अंशों का उपयोग करते हैं)। उदा: उपयोगकर्ता NY में है और आज 4 जुलाई है। इसका मतलब है कि उपयोगकर्ता GMT -0400 (पूर्वी डेलाइट टाइमज़ोन में है क्योंकि डीएसटी ने किक किया है); टाइमस्टैम्प में पारित 30 जनवरी के लिए है, जो GMT-0500 है (पूर्वी मानक Timezone - वर्ष का कोई DST नहीं)। इसका परिणाम एक घंटे का होगा, क्योंकि getTimezoneOffset () आपको अभी ऑफसेट देता है, न कि जनवरी में जो था।
दिमितर दराज़न्स्की

2
इस समस्या को ठीक करने के लिए, आपको उस दिनांक की समय-सीमा लेने की आवश्यकता है , जिसमें आप (वर्तमान समय की शिफ्ट नहीं) पास कर रहे हैं : new Date().getTimezoneOffset()को परिवर्तित किया जाना चाहिएnew Date(timestampStr).getTimezoneOffset()
दिमितर दाराज़ांकी

13

मुझे संदेह है, कि उत्तर सही परिणाम नहीं देता है। प्रश्न में पूछनेवाला उपयोगकर्ता के वर्तमान समय क्षेत्र की अवहेलना करके हेलीसिंकी में सर्वर से वर्तमान समय में टाइमस्टैम्प को परिवर्तित करना चाहता है।

यह तथ्य है कि उपयोगकर्ता का समयक्षेत्र ऐसा हो सकता है जिससे हम कभी भी उस पर भरोसा न कर सकें।

अगर उदाहरण के लिए। टाइमस्टैम्प 1270544790922 है और हमारे पास एक फंक्शन है:

var _date = new Date();
_date.setTime(1270544790922);
var _helsenkiOffset = 2*60*60;//maybe 3
var _userOffset = _date.getTimezoneOffset()*60*60; 
var _helsenkiTime = new Date(_date.getTime()+_helsenkiOffset+_userOffset);

जब कोई न्यू यॉर्कर पृष्ठ पर जाता है, तो अलर्ट (_helsenkiTime) प्रिंट करता है:

Tue Apr 06 2010 05:21:02 GMT-0400 (EDT)

और जब एक फ़िनलैंडर पृष्ठ पर जाता है, तो अलर्ट (_helsenkiTime) प्रिंट करता है:

Tue Apr 06 2010 11:55:50 GMT+0300 (EEST)

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

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

लेकिन अगर आपके पास सर्वर (या किसी भी अन्य सर्वर) के टाइमज़ोन डेटाबेस तक कोई पहुंच नहीं है और टाइमस्टैम्प यूटीसी में है, तो आप जावास्क्रिप्ट में डीएसटी नियमों को कठिन कोड करके समान कार्यक्षमता प्राप्त कर सकते हैं।

वर्ष 1998 - 2099 में यूरोप / हेलसिंकी में तारीखों को कवर करने के लिए आप निम्न कार्य ( jsfiddled ) का उपयोग कर सकते हैं :

function timestampToHellsinki(server_timestamp) {
    function pad(num) {
        num = num.toString();
        if (num.length == 1) return "0" + num;
        return num;
    }

    var _date = new Date();
    _date.setTime(server_timestamp);

    var _year = _date.getUTCFullYear();

    // Return false, if DST rules have been different than nowadays:
    if (_year<=1998 && _year>2099) return false;

    // Calculate DST start day, it is the last sunday of March
    var start_day = (31 - ((((5 * _year) / 4) + 4) % 7));
    var SUMMER_start = new Date(Date.UTC(_year, 2, start_day, 1, 0, 0));

    // Calculate DST end day, it is the last sunday of October
    var end_day = (31 - ((((5 * _year) / 4) + 1) % 7))
    var SUMMER_end = new Date(Date.UTC(_year, 9, end_day, 1, 0, 0));

    // Check if the time is between SUMMER_start and SUMMER_end
    // If the time is in summer, the offset is 2 hours
    // else offset is 3 hours
    var hellsinkiOffset = 2 * 60 * 60 * 1000;
    if (_date > SUMMER_start && _date < SUMMER_end) hellsinkiOffset = 
    3 * 60 * 60 * 1000;

    // Add server timestamp to midnight January 1, 1970
    // Add Hellsinki offset to that
    _date.setTime(server_timestamp + hellsinkiOffset);
    var hellsinkiTime = pad(_date.getUTCDate()) + "." + 
    pad(_date.getUTCMonth()) + "." + _date.getUTCFullYear() + 
    " " + pad(_date.getUTCHours()) + ":" +
    pad(_date.getUTCMinutes()) + ":" + pad(_date.getUTCSeconds());

    return hellsinkiTime;
}

उपयोग के उदाहरण:

var server_timestamp = 1270544790922;
document.getElementById("time").innerHTML = "The timestamp " + 
server_timestamp + " is in Hellsinki " + 
timestampToHellsinki(server_timestamp);

server_timestamp = 1349841923 * 1000;
document.getElementById("time").innerHTML += "<br><br>The timestamp " + 
server_timestamp + " is in Hellsinki " + timestampToHellsinki(server_timestamp);

var now = new Date();
server_timestamp = now.getTime();
document.getElementById("time").innerHTML += "<br><br>The timestamp is now " +
server_timestamp + " and the current local time in Hellsinki is " +
timestampToHellsinki(server_timestamp);​

और यह उपयोगकर्ता टाइमज़ोन की परवाह किए बिना निम्नलिखित प्रिंट करें:

The timestamp 1270544790922 is in Hellsinki 06.03.2010 12:06:30

The timestamp 1349841923000 is in Hellsinki 10.09.2012 07:05:23

The timestamp is now 1349853751034 and the current local time in Hellsinki is 10.09.2012 10:22:31

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


2
nb। हेलसिंकी में केवल एक 'एल' है। यह गलती वास्तव में इस जवाब से अलग है।
बेन मैकइंटायर

@BenMcIntyre यह थोड़ा मजाक है। या ऐसा ही माना जाता है। :)
तिमो काहेकोनेन

आह, कभी भी अपने समय / समय-कार्यान्वयन को लागू न करें ... लेकिन मैं बहुत आलसी हूँ
mb21

3

यह मानते हुए कि आपको हेलसिंकी समय में टाइमस्टैम्प मिलता है, मैं 1 जनवरी 1970 की आधी रात को यूटीसी (ब्राउज़र के स्थानीय समयक्षेत्र सेटिंग्स की अवहेलना के लिए) के लिए एक दिनांक ऑब्जेक्ट बनाऊंगा। फिर बस इसमें मिलीसेकंड की आवश्यक संख्या जोड़ें।

var _date	= new Date( Date.UTC(1970, 0, 1, 0, 0, 0, 0) );
_date.setUTCMilliseconds(1270544790922);

alert(_date); //date shown shifted corresponding to local time settings
alert(_date.getUTCFullYear());    //the UTC year value
alert(_date.getUTCMonth());       //the UTC month value
alert(_date.getUTCDate());        //the UTC day of month value
alert(_date.getUTCHours());       //the UTC hour value
alert(_date.getUTCMinutes());     //the UTC minutes value

तिथि ऑब्जेक्ट से हमेशा UTC मान पूछने के लिए बाद में देखें। इस तरह से उपयोगकर्ताओं को स्थानीय सेटिंग्स की परवाह किए बिना समान दिनांक मान दिखाई देंगे। अन्यथा दिनांक मानों को स्थानीय समय सेटिंग्स के अनुरूप स्थानांतरित कर दिया जाएगा।


0

आप उपयोग कर सकते हैं setUTCMilliseconds()

var _date = new Date();
_date.setUTCMilliseconds(1270544790922);

यह उत्तर गलत है। setUTCMilliseconds तिथि में निर्दिष्ट मिलीसेकंड की संख्या जोड़ता है।
टाइबर

@ टिबोर: मोज़देव से: setUTCMilliseconds()विधि सार्वभौमिक समय के अनुसार एक निर्दिष्ट तिथि के लिए मिलीसेकंड सेट करती है। [...] यदि आपके द्वारा निर्दिष्ट कोई पैरामीटर अपेक्षित सीमा से बाहर है, setUTCMilliseconds()तो दिनांक जानकारी को दिनांक ऑब्जेक्ट में तदनुसार अद्यतन करने का प्रयास करता है। दूसरे शब्दों में, आप Dateयूटीसी पर दिए गए यूनिक्स टाइमस्टैम्प वाले ऑब्जेक्ट बनाते हैं ।
जिमासुन

W3schools से: setUTCMilliseconds () विधि सार्वभौमिक समय के अनुसार मिलीसेकंड (0 से 999 तक) सेट करती है। कृपया ऊपर दिए गए उत्तर का प्रयास करें और अपने लिए देखें।
टिबोर

MDN से: पैरामीटर्स मिलीसेकेंडवेल्यू: 0 और 999 के बीच की संख्या, मिलीसेकंड का प्रतिनिधित्व ...
टिबर

आपका उदाहरण अपेक्षित रूप से काम नहीं करता है, क्योंकि नई तिथि () वर्तमान स्थानीय तिथि के साथ एक दिनांक ऑब्जेक्ट बनाती है। और इसके बाद इसमें निर्दिष्ट मिलीसेकंड की संख्या को जोड़ता है। तो आपके उदाहरण में यदि वर्तमान स्थानीय तिथि 2017-05-04 है, तो परिणामी तिथि वर्ष 4027 के बाद कहीं होगी ...
टिबोर
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.