角度的javascript日期和时区

时间:2017-05-28 09:45:59

标签: javascript date datetime

我绝对疯狂地试图弄清楚如何获得两个日期,从两个不同的时区显示相同的时间,无论你在哪里。

即:如果我早上7点在墨尔本(GMT +1000)有一段时间,而我在早上7点在珀斯(GMT +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);
    };
  }
}());

2 个答案:

答案 0 :(得分:1)

日期对象内部为UTC。主机时区用于涉及" local"值和解析" local"时生成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




答案 1 :(得分:0)

2017年7月29日星期六07:00:00"你不能拥有Date个对象。它将以任何方式具有相关的时区。无论如何,您可以使用IST创建一个29 May 9 am日期,并假设它是Australia/Melbourne。请参阅以下示例,您可以使用objForDatePicker与datepicker一起使用。然后,需要再次更正DatePicker返回的日期,如图所示。



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>
&#13;
&#13;
&#13;

检查您的时间选择器实现是否接受moment对象,如果是,则更容易,直接使用date。还要添加一个指向您正在使用的时间选择器的链接,Bootstrap有很多时间选择器实现。