You can not select more than 25 topics
			Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
		
		
		
		
		
			
		
			
				
					
					
						
							243 lines
						
					
					
						
							7.9 KiB
						
					
					
				
			
		
		
	
	
							243 lines
						
					
					
						
							7.9 KiB
						
					
					
				
 | 
						|
/* | 
						|
* Licensed to the Apache Software Foundation (ASF) under one | 
						|
* or more contributor license agreements.  See the NOTICE file | 
						|
* distributed with this work for additional information | 
						|
* regarding copyright ownership.  The ASF licenses this file | 
						|
* to you under the Apache License, Version 2.0 (the | 
						|
* "License"); you may not use this file except in compliance | 
						|
* with the License.  You may obtain a copy of the License at | 
						|
* | 
						|
*   http://www.apache.org/licenses/LICENSE-2.0 | 
						|
* | 
						|
* Unless required by applicable law or agreed to in writing, | 
						|
* software distributed under the License is distributed on an | 
						|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | 
						|
* KIND, either express or implied.  See the License for the | 
						|
* specific language governing permissions and limitations | 
						|
* under the License. | 
						|
*/ | 
						|
 | 
						|
var zrUtil = require("zrender/lib/core/util"); | 
						|
 | 
						|
var numberUtil = require("../util/number"); | 
						|
 | 
						|
var formatUtil = require("../util/format"); | 
						|
 | 
						|
var scaleHelper = require("./helper"); | 
						|
 | 
						|
var IntervalScale = require("./Interval"); | 
						|
 | 
						|
/* | 
						|
* Licensed to the Apache Software Foundation (ASF) under one | 
						|
* or more contributor license agreements.  See the NOTICE file | 
						|
* distributed with this work for additional information | 
						|
* regarding copyright ownership.  The ASF licenses this file | 
						|
* to you under the Apache License, Version 2.0 (the | 
						|
* "License"); you may not use this file except in compliance | 
						|
* with the License.  You may obtain a copy of the License at | 
						|
* | 
						|
*   http://www.apache.org/licenses/LICENSE-2.0 | 
						|
* | 
						|
* Unless required by applicable law or agreed to in writing, | 
						|
* software distributed under the License is distributed on an | 
						|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY | 
						|
* KIND, either express or implied.  See the License for the | 
						|
* specific language governing permissions and limitations | 
						|
* under the License. | 
						|
*/ | 
						|
 | 
						|
/* | 
						|
* A third-party license is embeded for some of the code in this file: | 
						|
* The "scaleLevels" was originally copied from "d3.js" with some | 
						|
* modifications made for this project. | 
						|
* (See more details in the comment on the definition of "scaleLevels" below.) | 
						|
* The use of the source code of this file is also subject to the terms | 
						|
* and consitions of the license of "d3.js" (BSD-3Clause, see | 
						|
* </licenses/LICENSE-d3>). | 
						|
*/ | 
						|
// [About UTC and local time zone]: | 
						|
// In most cases, `number.parseDate` will treat input data string as local time | 
						|
// (except time zone is specified in time string). And `format.formateTime` returns | 
						|
// local time by default. option.useUTC is false by default. This design have | 
						|
// concidered these common case: | 
						|
// (1) Time that is persistent in server is in UTC, but it is needed to be diplayed | 
						|
// in local time by default. | 
						|
// (2) By default, the input data string (e.g., '2011-01-02') should be displayed | 
						|
// as its original time, without any time difference. | 
						|
var intervalScaleProto = IntervalScale.prototype; | 
						|
var mathCeil = Math.ceil; | 
						|
var mathFloor = Math.floor; | 
						|
var ONE_SECOND = 1000; | 
						|
var ONE_MINUTE = ONE_SECOND * 60; | 
						|
var ONE_HOUR = ONE_MINUTE * 60; | 
						|
var ONE_DAY = ONE_HOUR * 24; // FIXME 公用? | 
						|
 | 
						|
var bisect = function (a, x, lo, hi) { | 
						|
  while (lo < hi) { | 
						|
    var mid = lo + hi >>> 1; | 
						|
 | 
						|
    if (a[mid][1] < x) { | 
						|
      lo = mid + 1; | 
						|
    } else { | 
						|
      hi = mid; | 
						|
    } | 
						|
  } | 
						|
 | 
						|
  return lo; | 
						|
}; | 
						|
/** | 
						|
 * @alias module:echarts/coord/scale/Time | 
						|
 * @constructor | 
						|
 */ | 
						|
 | 
						|
 | 
						|
var TimeScale = IntervalScale.extend({ | 
						|
  type: 'time', | 
						|
 | 
						|
  /** | 
						|
   * @override | 
						|
   */ | 
						|
  getLabel: function (val) { | 
						|
    var stepLvl = this._stepLvl; | 
						|
    var date = new Date(val); | 
						|
    return formatUtil.formatTime(stepLvl[0], date, this.getSetting('useUTC')); | 
						|
  }, | 
						|
 | 
						|
  /** | 
						|
   * @override | 
						|
   */ | 
						|
  niceExtent: function (opt) { | 
						|
    var extent = this._extent; // If extent start and end are same, expand them | 
						|
 | 
						|
    if (extent[0] === extent[1]) { | 
						|
      // Expand extent | 
						|
      extent[0] -= ONE_DAY; | 
						|
      extent[1] += ONE_DAY; | 
						|
    } // If there are no data and extent are [Infinity, -Infinity] | 
						|
 | 
						|
 | 
						|
    if (extent[1] === -Infinity && extent[0] === Infinity) { | 
						|
      var d = new Date(); | 
						|
      extent[1] = +new Date(d.getFullYear(), d.getMonth(), d.getDate()); | 
						|
      extent[0] = extent[1] - ONE_DAY; | 
						|
    } | 
						|
 | 
						|
    this.niceTicks(opt.splitNumber, opt.minInterval, opt.maxInterval); // var extent = this._extent; | 
						|
 | 
						|
    var interval = this._interval; | 
						|
 | 
						|
    if (!opt.fixMin) { | 
						|
      extent[0] = numberUtil.round(mathFloor(extent[0] / interval) * interval); | 
						|
    } | 
						|
 | 
						|
    if (!opt.fixMax) { | 
						|
      extent[1] = numberUtil.round(mathCeil(extent[1] / interval) * interval); | 
						|
    } | 
						|
  }, | 
						|
 | 
						|
  /** | 
						|
   * @override | 
						|
   */ | 
						|
  niceTicks: function (approxTickNum, minInterval, maxInterval) { | 
						|
    approxTickNum = approxTickNum || 10; | 
						|
    var extent = this._extent; | 
						|
    var span = extent[1] - extent[0]; | 
						|
    var approxInterval = span / approxTickNum; | 
						|
 | 
						|
    if (minInterval != null && approxInterval < minInterval) { | 
						|
      approxInterval = minInterval; | 
						|
    } | 
						|
 | 
						|
    if (maxInterval != null && approxInterval > maxInterval) { | 
						|
      approxInterval = maxInterval; | 
						|
    } | 
						|
 | 
						|
    var scaleLevelsLen = scaleLevels.length; | 
						|
    var idx = bisect(scaleLevels, approxInterval, 0, scaleLevelsLen); | 
						|
    var level = scaleLevels[Math.min(idx, scaleLevelsLen - 1)]; | 
						|
    var interval = level[1]; // Same with interval scale if span is much larger than 1 year | 
						|
 | 
						|
    if (level[0] === 'year') { | 
						|
      var yearSpan = span / interval; // From "Nice Numbers for Graph Labels" of Graphic Gems | 
						|
      // var niceYearSpan = numberUtil.nice(yearSpan, false); | 
						|
 | 
						|
      var yearStep = numberUtil.nice(yearSpan / approxTickNum, true); | 
						|
      interval *= yearStep; | 
						|
    } | 
						|
 | 
						|
    var timezoneOffset = this.getSetting('useUTC') ? 0 : new Date(+extent[0] || +extent[1]).getTimezoneOffset() * 60 * 1000; | 
						|
    var niceExtent = [Math.round(mathCeil((extent[0] - timezoneOffset) / interval) * interval + timezoneOffset), Math.round(mathFloor((extent[1] - timezoneOffset) / interval) * interval + timezoneOffset)]; | 
						|
    scaleHelper.fixExtent(niceExtent, extent); | 
						|
    this._stepLvl = level; // Interval will be used in getTicks | 
						|
 | 
						|
    this._interval = interval; | 
						|
    this._niceExtent = niceExtent; | 
						|
  }, | 
						|
  parse: function (val) { | 
						|
    // val might be float. | 
						|
    return +numberUtil.parseDate(val); | 
						|
  } | 
						|
}); | 
						|
zrUtil.each(['contain', 'normalize'], function (methodName) { | 
						|
  TimeScale.prototype[methodName] = function (val) { | 
						|
    return intervalScaleProto[methodName].call(this, this.parse(val)); | 
						|
  }; | 
						|
}); | 
						|
/** | 
						|
 * This implementation was originally copied from "d3.js" | 
						|
 * <https://github.com/d3/d3/blob/b516d77fb8566b576088e73410437494717ada26/src/time/scale.js> | 
						|
 * with some modifications made for this program. | 
						|
 * See the license statement at the head of this file. | 
						|
 */ | 
						|
 | 
						|
var scaleLevels = [// Format              interval | 
						|
['hh:mm:ss', ONE_SECOND], // 1s | 
						|
['hh:mm:ss', ONE_SECOND * 5], // 5s | 
						|
['hh:mm:ss', ONE_SECOND * 10], // 10s | 
						|
['hh:mm:ss', ONE_SECOND * 15], // 15s | 
						|
['hh:mm:ss', ONE_SECOND * 30], // 30s | 
						|
['hh:mm\nMM-dd', ONE_MINUTE], // 1m | 
						|
['hh:mm\nMM-dd', ONE_MINUTE * 5], // 5m | 
						|
['hh:mm\nMM-dd', ONE_MINUTE * 10], // 10m | 
						|
['hh:mm\nMM-dd', ONE_MINUTE * 15], // 15m | 
						|
['hh:mm\nMM-dd', ONE_MINUTE * 30], // 30m | 
						|
['hh:mm\nMM-dd', ONE_HOUR], // 1h | 
						|
['hh:mm\nMM-dd', ONE_HOUR * 2], // 2h | 
						|
['hh:mm\nMM-dd', ONE_HOUR * 6], // 6h | 
						|
['hh:mm\nMM-dd', ONE_HOUR * 12], // 12h | 
						|
['MM-dd\nyyyy', ONE_DAY], // 1d | 
						|
['MM-dd\nyyyy', ONE_DAY * 2], // 2d | 
						|
['MM-dd\nyyyy', ONE_DAY * 3], // 3d | 
						|
['MM-dd\nyyyy', ONE_DAY * 4], // 4d | 
						|
['MM-dd\nyyyy', ONE_DAY * 5], // 5d | 
						|
['MM-dd\nyyyy', ONE_DAY * 6], // 6d | 
						|
['week', ONE_DAY * 7], // 7d | 
						|
['MM-dd\nyyyy', ONE_DAY * 10], // 10d | 
						|
['week', ONE_DAY * 14], // 2w | 
						|
['week', ONE_DAY * 21], // 3w | 
						|
['month', ONE_DAY * 31], // 1M | 
						|
['week', ONE_DAY * 42], // 6w | 
						|
['month', ONE_DAY * 62], // 2M | 
						|
['week', ONE_DAY * 70], // 10w | 
						|
['quarter', ONE_DAY * 95], // 3M | 
						|
['month', ONE_DAY * 31 * 4], // 4M | 
						|
['month', ONE_DAY * 31 * 5], // 5M | 
						|
['half-year', ONE_DAY * 380 / 2], // 6M | 
						|
['month', ONE_DAY * 31 * 8], // 8M | 
						|
['month', ONE_DAY * 31 * 10], // 10M | 
						|
['year', ONE_DAY * 380] // 1Y | 
						|
]; | 
						|
/** | 
						|
 * @param {module:echarts/model/Model} | 
						|
 * @return {module:echarts/scale/Time} | 
						|
 */ | 
						|
 | 
						|
TimeScale.create = function (model) { | 
						|
  return new TimeScale({ | 
						|
    useUTC: model.ecModel.get('useUTC') | 
						|
  }); | 
						|
}; | 
						|
 | 
						|
var _default = TimeScale; | 
						|
module.exports = _default; |