Added support for UTC date time labels.
authorJoan Pau Beltran <joanpau.beltran@socib.cat>
Wed, 22 Jan 2014 12:55:51 +0000 (13:55 +0100)
committerJoan Pau Beltran <joanpau.beltran@socib.cat>
Fri, 31 Jan 2014 13:04:07 +0000 (14:04 +0100)
  * dygraph-utils.js:
    new utc switch parameter for `Dygraph.dateString_`
    and new signature for `Dygraph.hhmmss_`.

  * dygraph.js:
    support for UTC date time labels in date formatter.
    Also rename it to `dateAxisLabelFormatter`  for homogeneity
    with the numeric one. and add  a `dateValueFormatter`.

  * dygraph-options-reference.js:
    new `labelsDateUTC` option.

dygraph-options-reference.js
dygraph-utils.js
dygraph.js

index 3ecc531..958a1ce 100644 (file)
@@ -486,6 +486,12 @@ Dygraph.OPTIONS_REFERENCE =  // <JSON>
     "type": "boolean",
     "description": "When set, display the graph as a step plot instead of a line plot. This option may either be set for the whole graph or for single series."
   },
+  "labelsDateUTC": {
+    "default": "false",
+    "labels": ["Value display/formatting"],
+    "type": "boolean",
+    "description": "Show date/time labels according to UTC (instead of local time)."
+  },
   "labelsKMB": {
     "default": "false",
     "labels": ["Value display/formatting"],
index 36ad10e..a5d3c26 100644 (file)
@@ -477,45 +477,60 @@ Dygraph.zeropad = function(x) {
 
 /**
  * Return a string version of the hours, minutes and seconds portion of a date.
- *
- * @param {number} date The JavaScript date (ms since epoch)
- * @return {string} A time of the form "HH:MM:SS"
+ * @param {number} hh The hours (from 0-23)
+ * @param {number} mm The minutes (from 0-59)
+ * @param {number} ss The seconds (from 0-59)
+ * @return {string} A time of the form "HH:MM" or "HH:MM:SS"
  * @private
  */
-Dygraph.hmsString_ = function(date) {
+Dygraph.hmsString_ = function(hh, mm, ss) {
   var zeropad = Dygraph.zeropad;
-  var d = new Date(date);
-  if (d.getSeconds()) {
-    return zeropad(d.getHours()) + ":" +
-           zeropad(d.getMinutes()) + ":" +
-           zeropad(d.getSeconds());
-  } else {
-    return zeropad(d.getHours()) + ":" + zeropad(d.getMinutes());
+  var ret = zeropad(hh) + ":" + zeropad(mm);
+  if (ss) {
+    ret += ":" + zeropad(ss);
   }
+  return ret;
 };
 
 /**
- * Convert a JS date (millis since epoch) to YYYY/MM/DD
+ * Convert a JS date (millis since epoch) to a formatted string.
  * @param {number} date The JavaScript date (ms since epoch)
- * @return {string} A date of the form "YYYY/MM/DD"
+ * @param {boolean} utc Wether output UTC or local time
+ * @return {string} A date of one of these forms:
+ *     "YYYY/MM/DD", "YYYY/MM/DD HH:MM" or "YYYY/MM/DD HH:MM:SS"
  * @private
  */
-Dygraph.dateString_ = function(date) {
+Dygraph.dateString_ = function(date, utc) {
   var zeropad = Dygraph.zeropad;
-  var d = new Date(date);
-
-  // Get the year:
-  var year = "" + d.getFullYear();
+  var dt = new Date(date);
+  var y, m, d, hh, mm, ss;
+  if (utc) {
+    y = dt.getUTCFullYear();
+    m = dt.getUTCMonth();
+    d = dt.getUTCDate();
+    hh = dt.getUTCHours();
+    mm = dt.getUTCMinutes();
+    ss = dt.getUTCSeconds();
+  } else {
+    y = dt.getFullYear();
+    m = dt.getMonth();
+    d = dt.getDate();
+    hh = dt.getHours();
+    mm = dt.getMinutes();
+    ss = dt.getSeconds();
+  }
+  // Get a year string:
+  var year = "" + y;
   // Get a 0 padded month string
-  var month = zeropad(d.getMonth() + 1);  //months are 0-offset, sigh
+  var month = zeropad(m + 1);  //months are 0-offset, sigh
   // Get a 0 padded day string
-  var day = zeropad(d.getDate());
-
-  var ret = "";
-  var frac = d.getHours() * 3600 + d.getMinutes() * 60 + d.getSeconds();
-  if (frac) ret = " " + Dygraph.hmsString_(date);
-
-  return year + "/" + month + "/" + day + ret;
+  var day = zeropad(d);
+  var frac = hh * 3600 + mm * 60 + ss
+  var ret = year + "/" + month + "/" + day;
+  if (frac) {
+    ret += " " + Dygraph.hmsString_(hh,mm,ss);
+  }
+  return ret;
 };
 
 /**
index e6b971b..2a6f827 100644 (file)
@@ -202,30 +202,62 @@ Dygraph.SHORT_MONTH_NAMES_ = ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', '
 
 /**
  * Convert a JS date to a string appropriate to display on an axis that
- * is displaying values at the stated granularity.
+ * is displaying values at the stated granularity. This respects the 
+ * labelsDateUTC option.
  * @param {Date} date The date to format
  * @param {number} granularity One of the Dygraph granularity constants
- * @return {string} The formatted date
+ * @param {Dygraph} opts An options view
+ * @return {string} The date formatted as local time
  * @private
  */
-Dygraph.dateAxisFormatter = function(date, granularity) {
+Dygraph.dateAxisLabelFormatter = function(date, granularity, opts) {
+  var utc = opts('labelsDateUTC');
+  var year, month, day, hours, mins, secs, millis;
+  if (utc) {
+    year = date.getUTCFullYear();
+    month = date.getUTCMonth();
+    day = date.getUTCDate();
+    hours = date.getUTCHours();
+    mins = date.getUTCMinutes();
+    secs = date.getUTCSeconds();
+    millis = date.getUTCMilliseconds();
+  } else {
+    year = date.getFullYear();
+    month = date.getMonth();
+    day = date.getDate();
+    hours = date.getHours();
+    mins = date.getMinutes();
+    secs = date.getSeconds();
+    millis = date.getMilliseconds();
+  };
   if (granularity >= Dygraph.DECADAL) {
-    return '' + date.getFullYear();
+    return '' + year;
   } else if (granularity >= Dygraph.MONTHLY) {
-    return Dygraph.SHORT_MONTH_NAMES_[date.getMonth()] + ' ' + date.getFullYear();
+    return Dygraph.SHORT_MONTH_NAMES_[month] + ' ' + year;
   } else {
-    var frac = date.getHours() * 3600 + date.getMinutes() * 60 + date.getSeconds() + date.getMilliseconds();
+    // 1e-3 factor on millis missing in original implementation
+    var frac = hours * 3600 + mins * 60 + secs + 1e-3 * millis;
     if (frac === 0 || granularity >= Dygraph.DAILY) {
       // e.g. '21Jan' (%d%b)
-      var nd = new Date(date.getTime() + 3600*1000);
-      return Dygraph.zeropad(nd.getDate()) + Dygraph.SHORT_MONTH_NAMES_[nd.getMonth()];
+      return Dygraph.zeropad(day) + Dygraph.SHORT_MONTH_NAMES_[month];
     } else {
-      return Dygraph.hmsString_(date.getTime());
+      return Dygraph.hmsString_(hours, mins, secs);
     }
   }
 };
 
 /**
+ * @private
+ * Return a string version of a JS date for a value label. This respects the 
+ * labelsDateUTC option.
+ * @param {Date} date The number to be formatted
+ * @param {Dygraph} opts An options view
+ */
+Dygraph.dateValueFormatter = function(d, opts) {
+  return Dygraph.dateString_(d, opts('labelsDateUTC'))
+}
+
+/**
  * Standard plotters. These may be used by clients.
  * Available plotters are:
  * - Dygraph.Plotters.linePlotter: draws central lines (most common)
@@ -335,8 +367,8 @@ Dygraph.DEFAULT_ATTRS = {
   axes: {
     x: {
       pixelsPerLabel: 60,
-      axisLabelFormatter: Dygraph.dateAxisFormatter,
-      valueFormatter: Dygraph.dateString_,
+      axisLabelFormatter: Dygraph.dateAxisLabelFormatter,
+      valueFormatter: Dygraph.dateValueFormatter,
       drawGrid: true,
       drawAxis: true,
       independentTicks: true,
@@ -2908,9 +2940,9 @@ Dygraph.prototype.detectTypeFromString_ = function(str) {
 Dygraph.prototype.setXAxisOptions_ = function(isDate) {
   if (isDate) {
     this.attrs_.xValueParser = Dygraph.dateParser;
-    this.attrs_.axes.x.valueFormatter = Dygraph.dateString_;
+    this.attrs_.axes.x.valueFormatter = Dygraph.dateValueFormatter;
     this.attrs_.axes.x.ticker = Dygraph.dateTicker;
-    this.attrs_.axes.x.axisLabelFormatter = Dygraph.dateAxisFormatter;
+    this.attrs_.axes.x.axisLabelFormatter = Dygraph.dateAxisLabelFormatter;
   } else {
     /** @private (shut up, jsdoc!) */
     this.attrs_.xValueParser = function(x) { return parseFloat(x); };
@@ -3108,9 +3140,9 @@ Dygraph.prototype.parseArray_ = function(data) {
 
   if (Dygraph.isDateLike(data[0][0])) {
     // Some intelligent defaults for a date x-axis.
-    this.attrs_.axes.x.valueFormatter = Dygraph.dateString_;
+    this.attrs_.axes.x.valueFormatter = Dygraph.dateValueFormatter;
     this.attrs_.axes.x.ticker = Dygraph.dateTicker;
-    this.attrs_.axes.x.axisLabelFormatter = Dygraph.dateAxisFormatter;
+    this.attrs_.axes.x.axisLabelFormatter = Dygraph.dateAxisLabelFormatter;
 
     // Assume they're all dates.
     var parsedData = Dygraph.clone(data);
@@ -3167,9 +3199,9 @@ Dygraph.prototype.parseDataTable_ = function(data) {
   var indepType = data.getColumnType(0);
   if (indepType == 'date' || indepType == 'datetime') {
     this.attrs_.xValueParser = Dygraph.dateParser;
-    this.attrs_.axes.x.valueFormatter = Dygraph.dateString_;
+    this.attrs_.axes.x.valueFormatter = Dygraph.dateValueFormatter;
     this.attrs_.axes.x.ticker = Dygraph.dateTicker;
-    this.attrs_.axes.x.axisLabelFormatter = Dygraph.dateAxisFormatter;
+    this.attrs_.axes.x.axisLabelFormatter = Dygraph.dateAxisLabelFormatter;
   } else if (indepType == 'number') {
     this.attrs_.xValueParser = function(x) { return parseFloat(x); };
     this.attrs_.axes.x.valueFormatter = function(x) { return x; };