moment.js timezones .valueOf()没有返回预期值

时间:2015-04-21 20:21:29

标签: javascript angularjs timezone momentjs highcharts-ng

我有一个角度应用程序,使用highcharts-ng来制作折线图。 y轴是数字,x轴是日期时间。

我正在尝试在" America / New_York"的两个时区之间进行转换时正确考虑夏令时变化。和"欧洲/伦敦"使用moment.js。

伦敦目前在BST(截至发布时为止),所以它是+1:00。

tick.TimeStamp
> "2015-04-21T16:06:06.0786392-04:00"

tick.TimeStamp 是我的" America / New_York"时间(目前在美国东部时间)。我使用...将其转换为伦敦时间。

moment(tick.TimeStamp).tz("Europe/London").format()
> "2015-04-21T21:06:06+01:00"

我需要在Unix Epoch刻度中使用我的结果在highcharts-ng中为x轴绘制它们,所以我使用...

var d = moment(tick.TimeStamp).tz("Europe/London").format()
moment(d).valueOf()

产生

  

1429646766000

问题是此刻度值结果为日期时间

  

2015年4月21日星期二20:06:06 GMT

应该在哪里

  

2015年4月21日星期二21:06:06 GMT

因为伦敦目前在BST +1:00

我做错了什么,或者只是错误地计算了这个?

非常感谢任何帮助。谢谢!

编辑:我应该提一下,我的moment-timezones.js是他们网站上最新的所有时区信息。

3 个答案:

答案 0 :(得分:4)

时刻正确计算。

Tue, 21 Apr 2015 20:06:06 GMTTue, 21 Apr 2015 21:06:06 BSTTue, 21 Apr 2015 16:06:06 EDT都指的是同一时间,并且都具有相同的unix时间戳。当您致电.tz()时,您只是在改变格式化时间的方式。你不是在改变实际时间。

注意:要获取unix时间戳,您可以使用.unix()例如

moment(tick.TimeStamp).unix()

或者这将返回相同的值

moment(tick.TimeStamp).tz("Europe/London").unix()

答案 1 :(得分:2)

我已经更新了JS小提琴来提供样本。 http://jsfiddle.net/x0z90vqg/(如果不使用HighStock,则在xAxis上显示type属性的更新小提示)

我相信您的问题是您没有正确使用Highcharts global object的属性useUTC和timezoneOffset属性。使用highcharts-ng控件可以屏蔽Highcharts库的一些功能,但您仍然可以轻松访问所需的功能。

小提琴的相关部分是:

Highcharts.setOptions({
    global : {
        useUTC : false,
        timezoneOffset: -5
    }
});
$scope.chartConfig.getHighcharts().redraw();

上面的示例将Highcharts全局对象设置为不使用UTC作为日期/时间序列,并将偏移量设置为-5小时(您可以使用像您已经使用的moment.js获得所需的偏移量),然后告诉图表重绘highcharts-ng的公开getHighcharts()方法。该方法返回实际的图表对象,从那里就像你直接使用高图,而不是通过任何中间组件。

修改

@Matt提出了一个非常好的观点。像这样设置timezoneOffset与设置真实时区并不完全相同。真正的时区会考虑DST的变化等,这只是UTC的静态偏移量。像这样设置UTC偏移也会影响整个图形,而不仅仅影响一个系列。如果您需要在不同时区的同一图表上显示(和比较)两个或更多系列,并将该数据显示为各自的时区,您可以为每个轴启用多个X轴和格式标签逻辑,取X值用于勾选并通过javascript函数将其转换为您想要显示的时区值和标签。这应该导致两个X轴在两个不同的时区中带有标签,但是图表中心部分的数据以相同的UTC比例运行。如果这样做,您可能还希望覆盖工具提示弹出窗口的格式化程序,以便您可以转换工具提示中显示的值,以显示每个点的时区值,如果您不希望它显示UTC。

所有这些仍然无法解决显示跨越DST切换点的时间序列数据的问题。我不相信Highcharts有任何表示方式,而且我也不知道另一个图表库。这似乎是一个相当普遍的问题,所以我确信它已经在某个地方得到了解决......

答案 2 :(得分:0)

只想发布我想出的快速更新。 由于我在客户端尝试执行此操作遇到了很多怪癖,因此我在Controller代码(.NET)中找到了一种在服务器端处理此问题的好方法。我现在返回 EasternTimeStamp LondonTimeStamp ,而不仅仅返回时间戳(tick.TimeStamp)。我能够使用TimeZoneInfo类的一个很好的方法来完成这个。

    /// <summary>
    /// Converts the time to eastern standard time.
    /// This should properly account for DST, putting the time in EST (-5:00) or EDT (-4:00)
    /// </summary>
    public static DateTime ConvertTimeToEasternStandardTime(DateTime inputDateTime)
    {
        // US eastern timezone=Eastern Standard Time
        string targetTimeZoneId = "Eastern Standard Time";
        DateTime outputDateTime = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(inputDateTime, targetTimeZoneId);
        return outputDateTime;
    }

    /// <summary>
    /// Converts the time to GMT standard time.
    /// This should properly account for DST, putting the time in BST (+1:00) or GMT (+0:00)
    /// </summary>
    public static DateTime ConvertTimeToGMTStandardTime(DateTime inputDateTime)
    {
        // London timezone=GMT Standard Time
        string targetTimeZoneId = "GMT Standard Time";
        DateTime outputDateTime = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(inputDateTime, targetTimeZoneId);
        return outputDateTime;
    }

希望遇到此问题的任何人都能发现这个有用。我发现在过去一周内找到一个处理DST和时区的好方法是非常紧张的。