UNPKG

3 kBJavaScriptView Raw
1import {Transform} from 'vega-dataflow';
2import {
3 TIME_UNITS, timeBin, timeFloor, timeInterval, timeUnits,
4 utcFloor, utcInterval
5} from 'vega-time';
6import {accessorFields, extent, inherits, peek} from 'vega-util';
7
8/**
9 * Discretize dates to specific time units.
10 * @constructor
11 * @param {object} params - The parameters for this operator.
12 * @param {function(object): *} params.field - The data field containing date/time values.
13 */
14export default function TimeUnit(params) {
15 Transform.call(this, null, params);
16}
17
18const OUTPUT = ['unit0', 'unit1'];
19
20TimeUnit.Definition = {
21 'type': 'TimeUnit',
22 'metadata': {'modifies': true},
23 'params': [
24 { 'name': 'field', 'type': 'field', 'required': true },
25 { 'name': 'interval', 'type': 'boolean', 'default': true },
26 { 'name': 'units', 'type': 'enum', 'values': TIME_UNITS, 'array': true },
27 { 'name': 'step', 'type': 'number', 'default': 1 },
28 { 'name': 'maxbins', 'type': 'number', 'default': 40 },
29 { 'name': 'extent', 'type': 'date', 'array': true},
30 { 'name': 'timezone', 'type': 'enum', 'default': 'local', 'values': ['local', 'utc'] },
31 { 'name': 'as', 'type': 'string', 'array': true, 'length': 2, 'default': OUTPUT }
32 ]
33};
34
35inherits(TimeUnit, Transform, {
36 transform(_, pulse) {
37 const field = _.field,
38 band = _.interval !== false,
39 utc = _.timezone === 'utc',
40 floor = this._floor(_, pulse),
41 offset = (utc ? utcInterval : timeInterval)(floor.unit).offset,
42 as = _.as || OUTPUT,
43 u0 = as[0],
44 u1 = as[1],
45 step = floor.step;
46
47 let min = floor.start || Infinity,
48 max = floor.stop || -Infinity,
49 flag = pulse.ADD;
50
51 if (
52 _.modified() ||
53 pulse.changed(pulse.REM) ||
54 pulse.modified(accessorFields(field))
55 ) {
56 pulse = pulse.reflow(true);
57 flag = pulse.SOURCE;
58 min = Infinity;
59 max = -Infinity;
60 }
61
62 pulse.visit(flag, t => {
63 const v = field(t);
64 let a, b;
65 if (v == null) {
66 t[u0] = null;
67 if (band) t[u1] = null;
68 } else {
69 t[u0] = a = b = floor(v);
70 if (band) t[u1] = b = offset(a, step);
71 if (a < min) min = a;
72 if (b > max) max = b;
73 }
74 });
75
76 floor.start = min;
77 floor.stop = max;
78
79 return pulse.modifies(band ? as : u0);
80 },
81
82 _floor(_, pulse) {
83 const utc = _.timezone === 'utc';
84
85 // get parameters
86 const {units, step} = _.units
87 ? {units: _.units, step: _.step || 1}
88 : timeBin({
89 extent: _.extent || extent(pulse.materialize(pulse.SOURCE).source, _.field),
90 maxbins: _.maxbins
91 });
92
93 // check / standardize time units
94 const tunits = timeUnits(units),
95 prev = this.value || {},
96 floor = (utc ? utcFloor : timeFloor)(tunits, step);
97
98 floor.unit = peek(tunits);
99 floor.units = tunits;
100 floor.step = step;
101 floor.start = prev.start;
102 floor.stop = prev.stop;
103 return this.value = floor;
104 }
105});