I needed to get Dygraph to respect arbitrary timezones. All dates shown in/on/around the graph should be able to be shown in an arbitrary timezone.
The problem:
- Javascript does not support timezones other than the browser local timezone.
- There are libraries out there (timezone-js, moment-js with moment-timezone-js) to address this, but Dygraph doesn't know about them.
UPDATED answer, now works with Dygraph version 1.1.1. For old answer skip past horizontal rule.
There is now an easier way to make Dygraph work with arbitrary timezones. The old way (implementing custom
valueFormatter
,axisLabelFormatter
, andticker
functions) should theoretically still work provided the functions are compatible (the code in the old answer is not compatible with Dygraph v. 1.1.1.)However, I decided to go a different route this time around. This new way does not use documented options, so it is a bit more hacky. However, it does have the benefit of being much less code (no need to re-implement the
ticker
function, etc). So while it is a little hacky, it's an elegant hack IMO. Note that the new version still requires moment and moment timezone 3rd party libraries.Note that this version requires that you use the new
labelsUTC
option, set totrue
. You can think of this hack as turning Dygraph's UTC option into a timezone of your choosing.(Note: I still like to specify
valueFormatter
because I want labels in "YYYY-MM-DD" format instead of "YYYY/MM/DD", but it's not necessary to specifyvalueFormatter
anymore just to get arbitrary timezone support.)Tested using Dygraph 1.1.1, Moment 2.10.6, and Moment Timezone v 0.4.1
Old answer, works with Dygraph version 1.0.1.
My first attempt was to simply pass Dygraph some timezone-js objects instead of Date objects, due to their purported ability to be used as drop-in replacements for javascript Date objects (you can use them like Date objects). Unfortunately this didn't work because Dygraph creates Date objects from scratch and doesn't seem to use the timezone-js ones I'm passing to it.
Digging into the Dygraph documentation shows that there are some hooks that we can use to override how dates are displayed:
That last one actually depends on the timezone too, so we'll need to override it as well as the formatters.
So I first wrote replacements for valueFormatter and axisLabelFormatter using timezone-js, but it turns out timezone-js didn't actually work correctly for non-DST dates (browser currently in DST). So first I setup moment-js, moment-timezone-js, and the timezone data I need. (For this example we only need 'Etc/UTC'). Note that I am using a global variable to store the timezone that I pass to moment-timezone-js. If you come up with a better way, please comment. Here are the valueFormatter and axisLabelFormatters I wrote using moment-js:
While testing these formatters, I noticed that the tick marks were a little strange. For instance, my graph covered two days worth of data, yet I didn't see any dates in the tick labels. Instead, I only saw time values. Dygraph by default would show a date in the middle when the graph covers two days of data.
So, to fix this we need to supply our own Ticker. What better ticker to use than a modified version of Dygraph's?
Finally, we have to tell Dygraph to use this ticker and formatters, by adding them to the options object like this:
If you want to change the timezone and then refresh the graph, do this:
These code snippets were tested with Dygraphs.VERSION 1.0.1, moment.version 2.7.0, and moment.tz.version 0.0.6.
It's a bit late, but Eddified's answer no longer works with the current version of dygraph.js, on the upside there is now an option to use UTC times:
labelsUTC: true
example is provided here:http://dygraphs.com/tests/labelsDateUTC.html