| 1 | const t0 = new Date, t1 = new Date;
|
|---|
| 2 |
|
|---|
| 3 | export function timeInterval(floori, offseti, count, field) {
|
|---|
| 4 |
|
|---|
| 5 | function interval(date) {
|
|---|
| 6 | return floori(date = arguments.length === 0 ? new Date : new Date(+date)), date;
|
|---|
| 7 | }
|
|---|
| 8 |
|
|---|
| 9 | interval.floor = (date) => {
|
|---|
| 10 | return floori(date = new Date(+date)), date;
|
|---|
| 11 | };
|
|---|
| 12 |
|
|---|
| 13 | interval.ceil = (date) => {
|
|---|
| 14 | return floori(date = new Date(date - 1)), offseti(date, 1), floori(date), date;
|
|---|
| 15 | };
|
|---|
| 16 |
|
|---|
| 17 | interval.round = (date) => {
|
|---|
| 18 | const d0 = interval(date), d1 = interval.ceil(date);
|
|---|
| 19 | return date - d0 < d1 - date ? d0 : d1;
|
|---|
| 20 | };
|
|---|
| 21 |
|
|---|
| 22 | interval.offset = (date, step) => {
|
|---|
| 23 | return offseti(date = new Date(+date), step == null ? 1 : Math.floor(step)), date;
|
|---|
| 24 | };
|
|---|
| 25 |
|
|---|
| 26 | interval.range = (start, stop, step) => {
|
|---|
| 27 | const range = [];
|
|---|
| 28 | start = interval.ceil(start);
|
|---|
| 29 | step = step == null ? 1 : Math.floor(step);
|
|---|
| 30 | if (!(start < stop) || !(step > 0)) return range; // also handles Invalid Date
|
|---|
| 31 | let previous;
|
|---|
| 32 | do range.push(previous = new Date(+start)), offseti(start, step), floori(start);
|
|---|
| 33 | while (previous < start && start < stop);
|
|---|
| 34 | return range;
|
|---|
| 35 | };
|
|---|
| 36 |
|
|---|
| 37 | interval.filter = (test) => {
|
|---|
| 38 | return timeInterval((date) => {
|
|---|
| 39 | if (date >= date) while (floori(date), !test(date)) date.setTime(date - 1);
|
|---|
| 40 | }, (date, step) => {
|
|---|
| 41 | if (date >= date) {
|
|---|
| 42 | if (step < 0) while (++step <= 0) {
|
|---|
| 43 | while (offseti(date, -1), !test(date)) {} // eslint-disable-line no-empty
|
|---|
| 44 | } else while (--step >= 0) {
|
|---|
| 45 | while (offseti(date, +1), !test(date)) {} // eslint-disable-line no-empty
|
|---|
| 46 | }
|
|---|
| 47 | }
|
|---|
| 48 | });
|
|---|
| 49 | };
|
|---|
| 50 |
|
|---|
| 51 | if (count) {
|
|---|
| 52 | interval.count = (start, end) => {
|
|---|
| 53 | t0.setTime(+start), t1.setTime(+end);
|
|---|
| 54 | floori(t0), floori(t1);
|
|---|
| 55 | return Math.floor(count(t0, t1));
|
|---|
| 56 | };
|
|---|
| 57 |
|
|---|
| 58 | interval.every = (step) => {
|
|---|
| 59 | step = Math.floor(step);
|
|---|
| 60 | return !isFinite(step) || !(step > 0) ? null
|
|---|
| 61 | : !(step > 1) ? interval
|
|---|
| 62 | : interval.filter(field
|
|---|
| 63 | ? (d) => field(d) % step === 0
|
|---|
| 64 | : (d) => interval.count(0, d) % step === 0);
|
|---|
| 65 | };
|
|---|
| 66 | }
|
|---|
| 67 |
|
|---|
| 68 | return interval;
|
|---|
| 69 | }
|
|---|