2

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

在使用 moment.js 在“America/New_York”和“Europe/London”两个时区之间转换时,我正在尝试正确考虑夏令时的变化。

伦敦目前处于英国夏令时(截至发帖时),因此是 +1:00。

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

tick.TimeStamp是我的“America/New_York”时间(目前在 EDT)。我使用...将其转换为伦敦时间

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

它应该在哪里

格林威治标准时间 2015 年 4 月 21 日星期二 21:06:06

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

我是在做错什么,还是只是时刻计算不正确?

任何帮助将不胜感激。谢谢!

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

4

3 回答 3

4

Moment 计算正确。

Tue, 21 Apr 2015 20:06:06 GMT, Tue, 21 Apr 2015 21:06:06 BST, 和Tue, 21 Apr 2015 16:06:06 EDT都指的是相同的时间,并且都将具有相同的 unix 时间戳。当您打电话时,.tz()您只是在更改该时间的格式。你没有改变实际时间。

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

moment(tick.TimeStamp).unix()

或者这将返回相同的值

moment(tick.TimeStamp).tz("Europe/London").unix()
于 2015-04-21T20:32:57.123 回答
2

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

我相信您的问题是您没有正确使用Highcharts 全局对象的属性 useUTC 和 timezoneOffset 属性。使用highcharts-ng控件掩盖了 Highcharts 库的一些功能,但您仍然可以轻松访问所需的功能。

小提琴的相关部分是:

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

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

编辑

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

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

于 2015-04-21T22:15:48.063 回答
0

只是想快速更新一下我的发现。由于我在客户端尝试执行此操作时遇到了很多怪癖,因此我在我的控制器代码 (.NET) 中找到了一种在服务器端处理此问题的好方法。我现在不仅返回时间戳 (tick.TimeStamp),还返回EasternTimeStampLondonTimeStamp。我能够使用 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 和时区的好方法是非常有压力的。

于 2015-04-23T11:37:36.613 回答