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
			| 
								 
											4 years ago
										 
									 | 
							
								
							 | 
						||
| 
								 | 
							
								/*
							 | 
						||
| 
								 | 
							
								* 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;
							 |