moment.js timezones .valueOf() not returning expected values
Solution 1
Moment is calculating this correctly.
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.
Note: To get the unix time stamp you can use .unix()
e.g.
moment(tick.TimeStamp).unix()
Or this will return the same value
moment(tick.TimeStamp).tz("Europe/London").unix()
Solution 2
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)
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.
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.
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.
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...
Corey
Updated on June 04, 2022Comments
-
Corey almost 2 years
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.
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.
London is currently in BST (as of the time of posting this), so it is +1:00.
tick.TimeStamp > "2015-04-21T16:06:06.0786392-04:00"
tick.TimeStamp is my "America/New_York" time (currently in 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...
var d = moment(tick.TimeStamp).tz("Europe/London").format() moment(d).valueOf()
which yields
1429646766000
The issue is that this tick value result as a datetime is
Tue, 21 Apr 2015 20:06:06 GMT
where it should be
Tue, 21 Apr 2015 21:06:06 GMT
since London is currently in 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.
-
Matt Johnson-Pint almost 9 years+1. Also,
moment(tick.TimeStamp).valueOf()
would work if he needs the timestamp in milliseconds instead of seconds. You're correct thattz
is redundant and unnecessary for this purpose. -
Matt Johnson-Pint almost 9 yearsThat's interesting, except it would mean that the offset would need to be stable over the range covered by the chart. See "Time Zone != Offset" in the timezone tag wiki. If the offset is stable, then that would work fine. Otherwise, converting to UTC is probably a good idea.
-
sohjsolwin almost 9 years@Matt, very valid point. Highcharts, in my experience, doesn't handle (or even seem to know about) legitimate time zones. The closest functionality seems to be the offset. Using a library like moment.js to find the appropriate offset from UTC for the timezone you want to display on the graph and placing it in the offset, either prior to rendering the graph or dynamically like above, seems to be the only way to make it show a non-UTC, non-current locale timezone. It does affect the entire graph, like you mentioned, so all data should be UTC'd first for proper comparison.
-
Corey almost 9 years@sohjsolwin - This looks promising, but the issue here is that I'm not using highstocks, so as soon as you set "useHighStocks: false" this method no longer works.
-
sohjsolwin almost 9 years@Corey That's due to some defaults that Highstocks sets automatically. The xAxis being a datetime type is one of them. You just need this statement to tell it that the x-point data is meant to be times and not numbers. I'll update the example with the changes too.
xAxis: { type:'datetime' }
-
Corey almost 9 years@rob - thanks for the reply, it was helpful. I did find a solution, you can view my comment below. Thanks!