Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/394.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用JavaScript/MomentJS显示一致的时间,而不考虑时区_Javascript_Timezone_Momentjs - Fatal编程技术网

使用JavaScript/MomentJS显示一致的时间,而不考虑时区

使用JavaScript/MomentJS显示一致的时间,而不考虑时区,javascript,timezone,momentjs,Javascript,Timezone,Momentjs,使用存储为时间戳(从历元开始的毫秒)的日期时出现问题,其中我有事件的时间戳和时区,但JavaScript/MomentJS显示的时间偏移量似乎不正确 为简洁起见,以下是我拥有的对象类型: { "name" : "Something happening", "timezone" : "America/Los_Angeles", "start" : 1586631607338 } 上述活动于年月日(“start”)在加利福尼亚州洛杉矶举行。

使用存储为时间戳(从历元开始的毫秒)的日期时出现问题,其中我有事件的时间戳和时区,但JavaScript/MomentJS显示的时间偏移量似乎不正确

为简洁起见,以下是我拥有的对象类型:

    {
       "name" : "Something happening",
       "timezone" : "America/Los_Angeles",
       "start" : 1586631607338
    }
上述活动于年月日(“
start
”)在加利福尼亚州洛杉矶举行。该事件在东部夏时制通过浏览器保存到数据库中。因此,在创建此事件的浏览器中,时间是正确的

当浏览器的时区更改(从EDT更改为PDT)时,上述事件的时间现在提前3小时

这是不准确的,事件需要显示事件开始的正确时间,在本例中,该时间应为
3:00 PM
,但显示为
12:00 PM

基本上,如果用户在LA,他们将看到此事件的开始时间为
12:00 PM
,但作者将开始时间定义为
3:00 PM

使用MomentJS,将每个事件的日期转换为UTC时间戳并写入数据库

在创作方面,我们有代码,基本上可以:

// event.startTime is an instance of a JS Date object
var startTime = moment(event.startTime.getTime()).utc().valueOf();
// startTime is now a UTC time stamp
startTime
与事件的时区一起写入数据库

在前端/显示器上,我们执行以下操作:

var startTime = moment.tz(event.startTime, event.timezone);
// startTime is now a MomentJS object, which we then use format()
在作者方面,他们为下午3:00创建了一个事件,它显示在他们的事件详细信息屏幕中,从下午3:00开始

但洛杉矶的用户将看到此事件在下午12:00开始

目标是将此事件显示为从下午3:00开始,无论用户在哪里,因为事件的日期应为:

太平洋时间下午3:00-5:00,但内容为:太平洋时间下午12:00-2:00

我的理解是,存储带有时区的UTC时间戳意味着可以避免这个确切的问题,但某些地方出了问题。任何指导都将不胜感激。

时刻(event.startTime.getTime()).utc().valueOf()
将等于
event.startTime.getTime()
,因为
Date
对象的
getTime
函数返回Unix时间戳(以毫秒为单位),Unix时间戳始终基于utc。从瞬间的本地模式切换到UTC模式不会改变底层的时间戳,因此您在这里做的并不多

让我们看看您在这里应用的各种上下文中给出的时间戳:

moment.utc(1586631607338).format()                        //=> "2020-04-11T19:00:07Z"
moment.tz(1586631607338, 'America/New_York').format()     //=> "2020-04-11T15:00:07-04:00"
moment.tz(1586631607338, 'America/Los_Angeles').format()  //=> "2020-04-11T12:00:07-07:00"
如您所见,此UTC时间戳表示东部时间的下午3点,太平洋时间的中午。(您的时间戳中还有一个额外的
7338
毫秒,您可能需要四舍五入。)

如果您希望时间戳表示当天太平洋时间的下午3点,则时间戳应为
1586642407338

moment.utc(1586642407338).format()                        //=> "2020-04-11T22:00:07Z"
moment.tz(1586642407338, 'America/New_York').format()     //=> "2020-04-11T18:00:07-04:00"
moment.tz(1586642407338, 'America/Los_Angeles').format()  //=> "2020-04-11T15:00:07-07:00"
在我看来,您遇到的问题是,您从浏览器的本地时间生成的
Date
对象开始。可能是某个日期/时间选取者。由于这个问题,许多选择器被编写为返回ISO 8601字符串,而不是
Date
对象。您还会发现,内置于HTML5的
浏览器中的对象也使用字符串,而不是
日期
对象。还有一些选择器是基于时刻的,并且具有时区设置,所以您在这方面有选择

但是,如果您不想更改选择器,那么您可以通过调整时区来作弊:

var startTime = moment(event.startTime).tz(event.timezone, true).valueOf();
这里的关键部分是传递给
tz
实例函数的
keepTime
参数的
true
标志。它提供与
utcOffset
实例函数中类似的行为,但使用命名时区而不是固定偏移量。该报告描述如下:

utcOffset
函数有一个可选的第二个参数,该参数接受 一个布尔值,指示是否保留一天中的现有时间

  • 传递
    false
    (默认值)将在Universal中保持相同的瞬间 时间,但当地时间会改变

  • 传递
    true
    将保持相同的本地时间,但代价是 在世界时间中选择一个不同的点

tz
函数中有关于这一点的说明,但它的工作方式是相同的,将有助于为您的场景创建正确的时间戳

这种“作弊”方式的缺点是,用户将无法选择在其本地时区中属于DST间隔的时间,即使该时间在事件的时区中有效。例如,2020-03-08的凌晨2点在
美国/纽约
中无效,但在
美国/菲尼克斯
中完全正常。不使用
Date
对象的选择器将允许这样做,但以我上面描述的方式“欺骗”将不允许这样做。

时刻(event.startTime.getTime()).utc().valueOf()
将等于
event.startTime.getTime()
因为
Date
对象的
getTime
函数返回Unix时间戳(以毫秒为单位),并且Unix时间戳始终基于UTC。从瞬间的本地模式切换到UTC模式不会改变底层的时间戳,因此您在这里做的并不多

让我们看看您在这里应用的各种上下文中给出的时间戳:

moment.utc(1586631607338).format()                        //=> "2020-04-11T19:00:07Z"
moment.tz(1586631607338, 'America/New_York').format()     //=> "2020-04-11T15:00:07-04:00"
moment.tz(1586631607338, 'America/Los_Angeles').format()  //=> "2020-04-11T12:00:07-07:00"
如您所见,此UTC时间戳表示东部时间的下午3点,太平洋时间的中午。(您的时间戳中还有一个额外的
7338
毫秒,您可能需要四舍五入。)

如果您希望时间戳表示当天太平洋时间的下午3点,则时间戳应为
1586642407338

moment.utc(1586642407338).format()                        //=> "2020-04-11T22:00:07Z"
moment.tz(1586642407338, 'America/New_York').format()     //=> "2020-04-11T18:00:07-04:00"
moment.tz(1586642407338, 'America/Los_Angeles').format()  //=> "2020-04-11T15:00:07-07:00"
在我看来,您遇到的问题是,您从浏览器的本地时间生成的
Date
对象开始。可能来自日期/时间选择器o