javascript moment.js 时区 .valueOf() 不返回预期值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29782362/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
moment.js timezones .valueOf() not returning expected values
提问by Corey
I have an angular application using highcharts-ng to make a line graph. The y-axis is numbers and the x-axis is datetime's.
我有一个使用 highcharts-ng 制作折线图的角度应用程序。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.
伦敦目前处于英国夏令时(截至发帖时),所以现在是 +1:00。
tick.TimeStamp
> "2015-04-21T16:06:06.0786392-04:00"
tick.TimeStampis my "America/New_York" time (currently in EDT). I convert that to London time using...
tick.TimeStamp是我的“America/New_York”时间(目前在 EDT)。我将其转换为伦敦时间使用...
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 Epoch 刻度中的结果在 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 日,星期二 20:06:06 GMT
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 是他们网站上最新的,包含所有时区信息。
回答by rob
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. When you call .tz()
you are just changing how that time will be formatted. You aren't changing the actual time.
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()
您只是在更改该时间的格式。你没有改变实际时间。
Note: To get the unix time stamp you can use .unix()
e.g.
注意:要获取unix时间戳,您可以使用.unix()
例如
moment(tick.TimeStamp).unix()
Or this will return the same value
或者这将返回相同的值
moment(tick.TimeStamp).tz("Europe/London").unix()
回答by sohjsolwin
I've updated a JS fiddle to provide a sample. http://jsfiddle.net/x0z90vqg/(Updated fiddle showing type
property on xAxis if not using HighStock)
我已经更新了一个 JS 小提琴来提供一个示例。http://jsfiddle.net/x0z90vqg/(type
如果不使用 HighStock,则更新小提琴显示xAxis 上的属性)
I believe your issue is that you're not using the Highcharts global object's properties useUTC and timezoneOffset properties appropriately. 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 全局对象的属性 useUTC 和 timezoneOffset 属性。使用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. 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 全局对象设置为不为日期/时间序列使用 UTC,并将偏移量设置为 -5 小时(您可以像已经使用的一样使用 moment.js 获取所需的偏移量),然后告诉图表通过highcharts-ng
的公开getHighcharts()
方法重绘。该方法返回实际的图表对象,从那里就好像您直接使用 highcharts 而不是通过任何中间组件。
Edit
编辑
@Matt brought up a very good point. Setting the timezoneOffset like this isn't quite the same thing as setting a true timezone. A true timezone would take into account DST changes and such, this is just a static offset from UTC. Setting the UTC offset like this also affects the entire graph, not just one series. 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. 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. 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.
@Matt 提出了一个很好的观点。像这样设置 timezoneOffset 与设置真正的时区并不完全相同。真正的时区会考虑 DST 的变化等,这只是 UTC 的静态偏移量。像这样设置 UTC 偏移量也会影响整个图表,而不仅仅是一个系列。如果您需要在不同时区的同一图表上显示(和比较)两个或更多系列,并将该数据显示为各自的时区,您可以启用多个 X 轴,并在每个轴的格式标签逻辑中,取 X 值对于刻度线,并通过 javascript 函数将其转换为您要显示的时区值和标签。这应该会导致两个 X 轴在两个不同的时区中带有标签,但图表中心部分的数据运行在相同的 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. I don't believe Highcharts has any way of representing that, and I'm not aware of another charting library that does either. It seems like it would be a fairly common problem though, so I'm sure it's been solved somewhere...
所有这些仍然没有解决显示跨越 DST 切换点的时间序列数据的问题。我不相信 Highcharts 有任何表示这一点的方式,而且我不知道另一个图表库也这样做。不过,这似乎是一个相当普遍的问题,所以我确定它已经在某处解决了......
回答by Corey
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). Instead of just returning the timestamp (tick.TimeStamp), I now return EasternTimeStampand LondonTimeStamp. I was able to accomplish this using a nice method off of the TimeZoneInfo class.
只是想发布一个我发现的快速更新。由于我在客户端尝试执行此操作时遇到了很多怪癖,因此我在我的控制器代码 (.NET) 中找到了一种在服务器端处理此问题的好方法。我现在不只是返回时间戳 (tick.TimeStamp),而是返回EasternTimeStamp和LondonTimeStamp。我能够使用 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 和时区的好方法时压力很大。