简体   繁体   English

moment.js时区.valueOf()未返回期望值

[英]moment.js timezones .valueOf() not returning expected values

I have an angular application using highcharts-ng to make a line graph. 我有一个使用highcharts-ng制作折线图的角度应用程序。 The y-axis is numbers and the x-axis is datetime's. y轴是数字,x轴是日期时间。

I am trying to properly account for Daylight Savings Time changes when converting between the two timezones of "America/New_York" and "Europe/London" using moment.js. 我在尝试使用moment.js在“美国/纽约州”和“欧洲/伦敦”两个时区之间进行转换时,正确考虑夏令时的更改。

London is currently in BST (as of the time of posting this), so it is +1:00. 伦敦目前是BST(截至发布之时),因此是+1:00。

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

tick.TimeStamp is my "America/New_York" time (currently in EDT). tick.TimeStamp是我的“ America / New_York”时间(当前为EDT)。 I convert that to London time using... 我使用...将其转换为伦敦时间

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

I need my result in Unix Epoch ticks to plot them for the x-axis in highcharts-ng, so I use... 我需要Unix纪元刻度中的结果以将它们绘制在highcharts-ng中的x轴上,所以我使用...

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

which yields 产生

1429646766000 1429646766000

The issue is that this tick value result as a datetime is 问题在于,此刻度值结果作为日期时间为

Tue, 21 Apr 2015 20:06:06 GMT 2015年4月21日,星期二,格林尼治标准时间

where it should be 应该在哪里

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

since London is currently in BST +1:00 因为伦敦目前在BST +1:00

Am I doing something wrong, or is moment just calculating this incorrectly? 我是在做错什么,还是现在只是计算不正确?

Any help would be greatly appreciated. 任何帮助将不胜感激。 Thank you! 谢谢!

EDIT: I should mention that my moment-timezones.js is the most recent from their site with all of the timezone info. 编辑:我应该提一下,我的moment-timezones.js是他们网站中包含所有时区信息的最新信息。

Moment is calculating this correctly. Moment正在正确计算。

Tue, 21 Apr 2015 20:06:06 GMT , Tue, 21 Apr 2015 21:06:06 BST , and Tue, 21 Apr 2015 16:06:06 EDT all refer to the same time and will all have the same unix timestamp. Tue, 21 Apr 2015 20:06:06 GMTTue, 21 Apr 2015 21:06:06 BST Tue, 21 Apr 2015 20:06:06 GMTTue, 21 Apr 2015 20:06:06 GMTTue, 21 Apr 2015 21:06:06 BSTTue, 21 Apr 2015 21:06:06 BSTTue, 21 Apr 2015 16:06:06 EDT都指同一时间,并且都具有相同的Unix时间戳。 When you call .tz() you are just changing how that time will be formatted. 当您调用.tz()您只是在更改该时间的格式。 You aren't changing the actual time. 您没有更改实际时间。

Note: To get the unix time stamp you can use .unix() eg 注意:要获取unix时间戳,您可以使用.unix()例如

moment(tick.TimeStamp).unix()

Or this will return the same value 否则将返回相同的值

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

I've updated a JS fiddle to provide a sample. 我更新了JS小提琴以提供示例。 http://jsfiddle.net/x0z90vqg/ (Updated fiddle showing type property on xAxis if not using HighStock) http://jsfiddle.net/x0z90vqg/ (如果未使用HighStock,则更新的小提琴将在xAxis上显示type属性)

I believe your issue is that you're not using the Highcharts global object 's properties useUTC and timezoneOffset properties appropriately. 我相信您的问题是您没有正确使用Highcharts全局对象的属性useUTC和timezoneOffset属性。 Using the highcharts-ng control masks some of the capabilities of the Highcharts library, but you're still able to access the features you need pretty easily. 使用highcharts-ng控件可以掩盖Highcharts库的某些功能,但是您仍然可以轻松访问所需的功能。

The relevant piece of the fiddle is: 小提琴的相关部分是:

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

The above example sets the Highcharts global object to not use UTC for the date/time series and set's the offset to -5 hours (you can obtain the needed offset using the moment.js like you already are), and then telling the chart to redraw through the highcharts-ng 's exposed getHighcharts() method. 上面的示例将Highcharts全局对象设置为在日期/时间序列中不使用UTC,并将偏移量设置为-5小时(您可以像现在一样使用moment.js获取所需的偏移量),然后告诉图表通过highcharts-ng公开的getHighcharts()方法重绘。 That method returns the actual chart object and from there it's like you're using highcharts directly and not through any intermediary component. 该方法返回实际的图表对象,从那里开始,就好像您在直接使用highcharts,而不是通过任何中间组件。

Edit 编辑

@Matt brought up a very good point. @Matt提出了一个非常好的观点。 Setting the timezoneOffset like this isn't quite the same thing as setting a true timezone. 像这样设置timezoneOffset与设置真实时区并不完全相同。 A true timezone would take into account DST changes and such, this is just a static offset from UTC. 真实的时区会考虑DST的更改,因此,这只是UTC的静态偏移量。 Setting the UTC offset like this also affects the entire graph, not just one series. 像这样设置UTC偏移量也会影响整个图形,而不仅仅是一个序列。 If you require displaying (and comparing) two or more series on the same graph in different timezones, and displaying that data as their respective timezones, you can enable multiple X-axis and in the format label logic for each axis, take the X value for the tick and convert it via javascript function into the timezone'd value and label you want to display. 如果您需要在同一图形上的不同时区中显示(和比较)两个或多个序列,并将该数据显示为它们各自的时区,则可以启用多个X轴,并在每个轴的格式标签逻辑中,取X值勾号,然后通过javascript函数将其转换为您要显示的时区值和标签。 This should result in two X-axis with labels in two different timezones, but the data in the central part of the graph running off the same UTC scale. 这将导致两个带有不同时区标签的X轴,但是图形中心部分的数据以相同的UTC刻度运行。 If doing this, you would likely also want to override the formatter for the tool tip popup as well so that you can convert the value displayed in the tool tip to show the timezone'd value for each point if you didn't want it to display UTC. 如果这样做,您可能还希望覆盖工具提示弹出窗口的格式化程序,以便您可以转换工具提示中显示的值以显示每个点的时区值(如果您不希望这样做)显示UTC。

All of this still doesn't solve the problem of displaying a time series of data that crosses over the point where DST switches. 所有这些仍然不能解决显示跨越DST切换点的时间序列数据的问题。 I don't believe Highcharts has any way of representing that, and I'm not aware of another charting library that does either. 我不认为Highcharts可以用任何方式表示这一点,而且我不知道有另一个图表库可以做到这一点。 It seems like it would be a fairly common problem though, so I'm sure it's been solved somewhere... 看来这将是一个相当普遍的问题,所以我确定它已经解决了……

just wanted to post a quick update of what I figured out. 只是想发布我所想的快速更新。 Since I ran into lots of quirks trying to do this on the client side, I found a nice way to handle this on the server side in my Controller code (.NET). 由于我在客户端上遇到很多奇怪的尝试,因此我在控制器代码(.NET)中找到了一种在服务器端处理此问题的好方法。 Instead of just returning the timestamp (tick.TimeStamp), I now return EasternTimeStamp and LondonTimeStamp . 现在,我不只是返回时间戳(tick.TimeStamp),而是返回EasternTimeStampLondonTimeStamp I was able to accomplish this using a nice method off of the TimeZoneInfo class. 我能够使用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;
    }

Hopefully anyone who runs into this issue can find this useful. 希望遇到此问题的任何人都可以找到有用的方法。 I've found it to be quite stressful trying to find a nice way to deal with DST and timezones like this over the past week. 我发现在过去一周中试图找到一种很好的方法来处理DST和时区,这对我来说压力很大。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM