2017-05-28 101 views
1

我絕對瘋了,試圖弄清楚如何從兩個不同的時區獲得兩個日期,以顯示相同的時間,無論你在哪裏。角度的JavaScript日期和時區

ie:如果我在上午7點在墨爾本(格林威治標準時間+1000)有時間,我在上午7點在珀斯(格林威治標準時間+0800)有另一個時間,我希望他們都在07:00開始在自助式時間選擇器上顯示相同的頁面。

如果我在墨爾本,珀斯的實際時間是2小時。澳大利亞有許多不同的時區,夏令時會混入其中。

我知道JS日期本地化到計算機所在的區域,所以我假設有問題的計算機是正確的。

我已經創建了一個使用momentjs和moment-timezones的過濾器,但我無法讓它顯示正確的結果。

示例輸入是:「2017-07-28T23:00:00.000Z」 - 或2017年7月29日星期六07:00:00 GMT + 0800(AWST)。

我發現momentjs將時間轉換爲字符串的功能非常出色,但是如何將其成功轉換爲日期對象呢?

這裏是我到目前爲止的代碼:

(function() { 
    'use strict'; 

    angular 
    .module('bookings') 
    .filter('timezone', timezone); 

    timezone.$inject = []; 

    function timezone() { 

    function isCurrentTimeZone(code){ 
     var currentTimeCode = new Date().toString().split('(')[1].replace(')',''); 

     if (code.indexOf(currentTimeCode) >= 0) { 
     return true; 
     } 

     return false; 
    } 

    function getLocalAustralianTimeZone() { 

     var currentTimeCode = new Date().toString().split('(')[1].replace(')',''); 

     let timezones = [ 
     { state: 'NSW', tz: 'Australia/Sydney', code: 'AEST AEDT' }, 
     { state: 'QLD', tz: 'Australia/Brisbane', code: 'AEST AEDT' }, 
     { state: 'SA', tz: 'Australia/Adelaide', code: 'ACST ACDT' }, 
     { state: 'TAS', tz: 'Australia/Hobart', code: 'AEST AEDT' }, 
     { state: 'NT', tz: 'Australia/Darwin', code: 'ACST ACDT' }, 
     { state: 'VIC', tz: 'Australia/Melbourne', code: 'AEST AEDT' }, 
     { state: 'WA', tz: 'Australia/Perth', code: 'AWST AWDT' }, 
     { state: 'ACT', tz: 'Australia/Sydney', code: 'AEST AEDT' } 
     ]; 

     let selectedTz = _.find(timezones, function (o) { 
     return o.code.indexOf(currentTimeCode) >= 0; 
     }); 
     return selectedTz; 
    } 

    function getAustralianTimeZone(state) { 
     let timezones = [ 
     { state: 'NSW', tz: 'Australia/Sydney', code: 'AEST AEDT' }, 
     { state: 'QLD', tz: 'Australia/Brisbane', code: 'AEST AEDT' }, 
     { state: 'SA', tz: 'Australia/Adelaide', code: 'ACST ACDT' }, 
     { state: 'TAS', tz: 'Australia/Hobart', code: 'AEST AEDT' }, 
     { state: 'NT', tz: 'Australia/Darwin', code: 'ACST ACDT' }, 
     { state: 'VIC', tz: 'Australia/Melbourne', code: 'AEST AEDT' }, 
     { state: 'WA', tz: 'Australia/Perth', code: 'AWST AWDT' }, 
     { state: 'ACT', tz: 'Australia/Sydney', code: 'AEST AEDT' } 
     ]; 

     let selectedTz = _.find(timezones, function (o) { 
     return o.state === state; 
     }); 
     return selectedTz; 
    } 

    function createDateAsUTC(date) { 
     return new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds())); 
    } 

    function convertDateToUTC(date) { 
     return new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds()); 
    } 

    return function (val, state) { 
     moment.tz.add('Australia/Sydney|AEST AEDT|-a0 -b0|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101|-293lX xcX 10jd0 yL0 1cN0 1cL0 1fB0 19X0 17c10 LA0 1C00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 14o0 1o00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 U00 1qM0 WM0 1tA0 WM0 1tA0 U00 1tA0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 11A0 1o00 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 11A0 1o00 WM0 1qM0 14o0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0|40e5'); 
     moment.tz.add('Australia/Adelaide|ACST ACDT|-9u -au|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101|-293lt xcX 10jd0 yL0 1cN0 1cL0 1fB0 19X0 17c10 LA0 1C00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 U00 1qM0 WM0 1tA0 WM0 1tA0 U00 1tA0 U00 1tA0 Oo0 1zc0 WM0 1qM0 Rc0 1zc0 U00 1tA0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 11A0 1o00 WM0 1qM0 14o0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0|11e5'); 
     moment.tz.add('Australia/Brisbane|AEST AEDT|-a0 -b0|01010101010101010|-293lX xcX 10jd0 yL0 1cN0 1cL0 1fB0 19X0 17c10 LA0 H1A0 Oo0 1zc0 Oo0 1zc0 Oo0|20e5'); 
     moment.tz.add('Australia/Broken_Hill|ACST ACDT|-9u -au|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101|-293lt xcX 10jd0 yL0 1cN0 1cL0 1fB0 19X0 17c10 LA0 1C00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 14o0 1o00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 U00 1qM0 WM0 1tA0 WM0 1tA0 U00 1tA0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 11A0 1o00 WM0 1qM0 14o0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0|18e3'); 
     moment.tz.add('Australia/Currie|AEST AEDT|-a0 -b0|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101|-29E80 19X0 10jd0 yL0 1cN0 1cL0 1fB0 19X0 17c10 LA0 1C00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 11A0 1qM0 WM0 1qM0 Oo0 1zc0 Oo0 1zc0 Oo0 1wo0 WM0 1tA0 WM0 1tA0 U00 1tA0 U00 1tA0 11A0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 11A0 1o00 1io0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1cM0 1a00 1io0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0|746'); 
     moment.tz.add('Australia/Darwin|ACST ACDT|-9u -au|010101010|-293lt xcX 10jd0 yL0 1cN0 1cL0 1fB0 19X0|12e4'); 
     moment.tz.add('Australia/Eucla|+0845 +0945|-8J -9J|0101010101010101010|-293kI xcX 10jd0 yL0 1cN0 1cL0 1gSp0 Oo0 l5A0 Oo0 iJA0 G00 zU00 IM0 1qM0 11A0 1o00 11A0|368'); 
     moment.tz.add('Australia/Hobart|AEST AEDT|-a0 -b0|010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101|-29E80 19X0 10jd0 yL0 1cN0 1cL0 1fB0 19X0 VfB0 1cM0 1o00 Rc0 1wo0 Rc0 1wo0 U00 1wo0 LA0 1C00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 11A0 1qM0 WM0 1qM0 Oo0 1zc0 Oo0 1zc0 Oo0 1wo0 WM0 1tA0 WM0 1tA0 U00 1tA0 U00 1tA0 11A0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 11A0 1o00 1io0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1a00 1fA0 1cM0 1cM0 1a00 1io0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0|21e4'); 
     moment.tz.add('Australia/Lord_Howe|AEST +1030 +1130 +11|-a0 -au -bu -b0|0121212121313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313131313|raC0 1zdu Rb0 1zd0 On0 1zd0 On0 1zd0 On0 1zd0 TXu 1qMu WLu 1tAu WLu 1tAu TXu 1tAu Onu 1zcu Onu 1zcu Onu 1zcu Rbu 1zcu Onu 1zcu Onu 1zcu 11zu 1o0u 11zu 1o0u 11zu 1o0u 11zu 1qMu WLu 11Au 1nXu 1qMu 11zu 1o0u 11zu 1o0u 11zu 1qMu WLu 1qMu 11zu 1o0u WLu 1qMu 14nu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1fAu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1fAu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1fzu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1fAu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1cMu 1cLu 1fAu 1cLu 1cMu 1cLu 1cMu|347'); 
     moment.tz.add('Australia/Lindeman|AEST AEDT|-a0 -b0|010101010101010101010|-293lX xcX 10jd0 yL0 1cN0 1cL0 1fB0 19X0 17c10 LA0 H1A0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0|10'); 
     moment.tz.add('Australia/Melbourne|AEST AEDT|-a0 -b0|0101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101010101|-293lX xcX 10jd0 yL0 1cN0 1cL0 1fB0 19X0 17c10 LA0 1C00 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 Oo0 1zc0 Oo0 1zc0 U00 1qM0 WM0 1qM0 11A0 1tA0 U00 1tA0 U00 1tA0 Oo0 1zc0 Oo0 1zc0 Rc0 1zc0 Oo0 1zc0 WM0 1qM0 11A0 1o00 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 11A0 1o00 1qM0 11A0 1o00 11A0 1o00 11A0 1qM0 WM0 1qM0 11A0 1o00 WM0 1qM0 14o0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1cM0 1fA0 1cM0 1cM0 1cM0 1cM0|39e5'); 
     moment.tz.add('Australia/Perth|AWST AWDT|-80 -90|0101010101010101010|-293jX xcX 10jd0 yL0 1cN0 1cL0 1gSp0 Oo0 l5A0 Oo0 iJA0 G00 zU00 IM0 1qM0 11A0 1o00 11A0|18e5'); 

     if (state !== "") { 
     var timezone = getAustralianTimeZone(state); 
     var currentZone = getLocalAustralianTimeZone(); 
     var isCurrent = isCurrentTimeZone(timezone.code); 


     if (!isCurrent) { 

      var date = new Date(Date.parse(val)); 
      date = new Date(date.getTime() - (60000 * moment(val).tz(timezone.tz)._offset)); 
      return date; 
     } 

     return new Date(Date.parse(val)); 

     } 

     return new Date(val); 
    }; 
    } 
}()); 
+0

轉換'2017-07-28T23:00:00.000Z'的日期?什麼時候(「2017-07-28T23:00:00.000Z」)? –

+0

輸入是「2017-07-28T23:00:00.000Z」,墨爾本和珀斯的預期產出是多少?您的要求不明白。 – sabithpocker

+0

'Date.toString()'上的字符串操作不好。它在不同的瀏覽器中吐出不同的結果。使用時刻獲得時區。 – sabithpocker

回答

1

日期對象在內部是UTC。主機時區用於涉及「本地」值的計算以及解析「本地」字符串時生成UTC值。

2017年7月28日07:00創建「本地」日期對象的最可靠方法是將適當的值直接傳遞給Date構造函數。這將爲等效的UTC日期和時間生成一個UTC值,但無論主機時區如何,它都會顯示爲相同的日期和時間(但對於具有不同時區偏移量的每個主機當然實際上代表不同時刻) 。

您可以使用不帶時區的ISO 8601格式的日期和時間字符串,其中應該是應視爲本地。但是,字符串解析有些不可靠,因此不是首選解決方案(例如,Safari會解析ISO 8601格式的日期和時間字符串,而不使用UTC作爲時區,而不是本地)。

console.log(new Date(2017,6,28,7).toString()); 
 
console.log(new Date('2017-07-28T07:00').toString()); // Safari treats this as UTC

0

你不能有一個Date對象只有「星期六2017年7月29日7點00分00秒」。它將以任何方式擁有關聯的時區。反正你可以用29 May 9 am來創建一個IST的日期,並假設它是Australia/Melbourne。請參閱以下示例,因爲您可以使用objForDatePicker與datepicker一起使用。然後從DatePicker返回的Date將需要再次修正,如圖所示。

var input = "2017-07-28T23:00:00.000Z"; 
 
console.log('input :', input); 
 
var date = moment.tz(input, 'Australia/Melbourne'); 
 
//now you can use it like a Date object 
 

 
console.log("moment date :",date.format('MMMM Do YYYY, h:mm:ss a'), date.format('z')); 
 

 
// create a local date with that time but false timezone 
 

 
var objForDatePicker = moment(date.format('MMMM Do YYYY, h:mm:ss a'),'MMMM Do YYYY, h:mm:ss a').toDate(); 
 

 
console.log("js date :", objForDatePicker.toString(),' :Jul 29 9AM IST this is wrong timezone-date duo') 
 

 
// to convert back to UTC or a correct timezone-date duo 
 
dateStringWithoutTZ = moment(objForDatePicker).format('MMMM Do YYYY, h:mm:ss a'); 
 
var date2 = moment.tz(dateStringWithoutTZ, 'MMMM Do YYYY, h:mm:ss a', 'Australia/Melbourne'); 
 

 
console.log("moment date: ",date2.format('MMMM Do YYYY, h:mm:ss a'), date2.format('z')); 
 

 
console.log("output :", date2.toISOString());
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script> 
 

 
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.13/moment-timezone-with-data-2012-2022.js"></script>

檢查,如果你的時間選擇器實現接受moment對象,如果是的,它會更容易,直接使用date。還添加一個鏈接到你正在使用的時間選擇器,Bootstrap有很多時間選擇器實現。