flowerbi-dates 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,25 @@
1
+ **/build/**
2
+ **/coverage/**
3
+ **/dist/**
4
+ **/built/**
5
+
6
+ *.tf
7
+ *.sln
8
+ *.deployproj
9
+ *.targets
10
+ *.gitignore
11
+ *.png
12
+ *.svg
13
+ *.config
14
+ *.ps1
15
+ *.ico
16
+ *.lock
17
+ *.jsbeautifyrc
18
+ *.xml
19
+ *.csv
20
+ *.tsbuildinfo
21
+ *.eslintignore
22
+ *.env
23
+ *.bat
24
+ *.prettierignore
25
+ *.scss.d.ts
package/.prettierrc ADDED
@@ -0,0 +1,7 @@
1
+ {
2
+ "trailingComma": "es5",
3
+ "tabWidth": 4,
4
+ "semi": true,
5
+ "singleQuote": false,
6
+ "printWidth": 160
7
+ }
package/README.md ADDED
@@ -0,0 +1,3 @@
1
+ # FlowerBI
2
+
3
+ Core data/query helpers.
@@ -0,0 +1,99 @@
1
+ import { Moment } from "moment";
2
+ export declare type FillDate = Date | string | number | Moment;
3
+ /**
4
+ * Three operations on dates used by {@link fillDates}.
5
+ */
6
+ export declare type FillDateType = {
7
+ /** Round the given date down to the nearest whole unit (e.g. start of month, quarter, year) */
8
+ round(d: Moment): Moment;
9
+ /** Format the given date to a string */
10
+ format(d: Moment): string;
11
+ /** Increment the date by the unit. The given date will already be rounded down. */
12
+ increment(d: Moment): Moment;
13
+ };
14
+ /**
15
+ * Standard built-in date types. To customise, implement the {@link FillDateType} interface.
16
+ */
17
+ export declare const dateTypes: {
18
+ readonly days: FillDateType;
19
+ readonly months: FillDateType;
20
+ readonly quarters: FillDateType;
21
+ readonly years: FillDateType;
22
+ };
23
+ /**
24
+ * Examines a set of dates and chooses the most specific type that includes them all. If
25
+ * all fall on Jan, 1 then `years` is chosen, and so on.
26
+ */
27
+ export declare function detectDateType(dates: Moment[]): FillDateType;
28
+ /** Options for {@link fillDates} function. */
29
+ export interface FillDatesOptions<T, R> {
30
+ /** The records to base the filled list on. */
31
+ records: T[];
32
+ /** The operations to use for rounding, incrementing and formatting dates. */
33
+ type?: FillDateType;
34
+ /** Extracts a date value from a record in the input list. */
35
+ getDate(record: T): FillDate;
36
+ /**
37
+ * Generate a record for a date, from the formatted {@link dateText} and
38
+ * the input record for that date, if any.
39
+ */
40
+ fill(dateText: string, record: T | undefined): R;
41
+ /**
42
+ * The minimum date to generate. It will be rounded down by the {@link type}
43
+ * so doesn't need to be on an exact boundary.
44
+ */
45
+ min?: FillDate;
46
+ /**
47
+ * The maximum date to generate. It will be rounded down by the {@link type}
48
+ * so doesn't need to be on an exact boundary.
49
+ */
50
+ max?: FillDate;
51
+ }
52
+ /**
53
+ * When querying for a time series chart, e.g. x-axis is _Month_ and y-axis is
54
+ * _Total Sales_, there may be months where nothing was sold so they are
55
+ * missing from the list of records.
56
+ *
57
+ * To render a proper time-series, we need these gaps to be filled in with
58
+ * runs of fake records that give zero amounts for those months. e.g.
59
+ *
60
+ * ```ts
61
+ * const filled = fillDates({
62
+ * records: [
63
+ * { date: '2020-04-01', totalSales: 10 },
64
+ * { date: '2020-06-01', totalSales: 4 },
65
+ * { date: '2020-07-01', totalSales: 9 },
66
+ * ],
67
+ * type: dateTypes.months,
68
+ * getDate: rec => rec.date,
69
+ * fill: (label, rec) => ({
70
+ * label,
71
+ * totalSales: 0,
72
+ * ...rec
73
+ * })
74
+ * });
75
+ * ```
76
+ *
77
+ * In the above example we add a `label` property to all the records, and
78
+ * for the records that fill the gaps we set the `totalSales` property to 0.
79
+ * For the real records, `...rec` will copy the real value of `totalSales`.
80
+ *
81
+ * To do this, we need to know:
82
+ *
83
+ * - how to round a date to the start of a unit (year, month, quarter),
84
+ * - how to increment a date by that unit,
85
+ * - how to format a date to a string for display.
86
+ *
87
+ * These operations are encapsulated by the {@link FillDateType} interface.
88
+ * Several built-in types are provided in {@link dateTypes}, but you can
89
+ * implement your own.
90
+ *
91
+ * Optionally you can also pass `min` and `max` dates, which will cause
92
+ * extra records to be added at the start and end of the range if necessary.
93
+ *
94
+ * If you don't pass a `type`, a suitable type will be detected based on
95
+ * how the input record dates fall on unit boundaries.
96
+ */
97
+ export declare function fillDates<T, R>({ records, getDate, fill, min, max, type }: FillDatesOptions<T, R>): R[];
98
+ /** @deprecated */
99
+ export declare function smartDates<T, R>(records: T[], min: FillDate | undefined, max: FillDate | undefined, getDate: (record: T) => FillDate, fill: (dateText: string, record: T | undefined) => R): R[];
@@ -0,0 +1,175 @@
1
+ "use strict";
2
+ var __spreadArray = (this && this.__spreadArray) || function (to, from, pack) {
3
+ if (pack || arguments.length === 2) for (var i = 0, l = from.length, ar; i < l; i++) {
4
+ if (ar || !(i in from)) {
5
+ if (!ar) ar = Array.prototype.slice.call(from, 0, i);
6
+ ar[i] = from[i];
7
+ }
8
+ }
9
+ return to.concat(ar || Array.prototype.slice.call(from));
10
+ };
11
+ var __importDefault = (this && this.__importDefault) || function (mod) {
12
+ return (mod && mod.__esModule) ? mod : { "default": mod };
13
+ };
14
+ Object.defineProperty(exports, "__esModule", { value: true });
15
+ exports.smartDates = exports.fillDates = exports.detectDateType = exports.dateTypes = void 0;
16
+ var moment_1 = __importDefault(require("moment"));
17
+ function parseDate(val) {
18
+ // Ensure a numeric year is not interpreted as offset from 1970!
19
+ if (typeof val === "number") {
20
+ val = "" + val;
21
+ }
22
+ return (0, moment_1.default)(val);
23
+ }
24
+ var days = {
25
+ round: function (d) {
26
+ return d.clone().startOf("day");
27
+ },
28
+ format: function (d) {
29
+ return d.format("ll");
30
+ },
31
+ increment: function (d) {
32
+ return d.clone().add(1, "day");
33
+ }
34
+ };
35
+ var months = {
36
+ round: function (d) {
37
+ return d.clone().startOf("month");
38
+ },
39
+ format: function (d) {
40
+ return d.format("MMM YYYY");
41
+ },
42
+ increment: function (d) {
43
+ return d.clone().add(1, "month");
44
+ }
45
+ };
46
+ var quarters = {
47
+ round: function (d) {
48
+ return d.clone().startOf("quarter");
49
+ },
50
+ format: function (d) {
51
+ var monthFirst = d.format("MMM");
52
+ var monthLast = d.clone().add(2, "months").format("MMM");
53
+ var year = d.format("YYYY");
54
+ return "".concat(monthFirst, "-").concat(monthLast, " ").concat(year);
55
+ },
56
+ increment: function (d) {
57
+ return d.clone().add(3, "months");
58
+ }
59
+ };
60
+ var years = {
61
+ round: function (d) {
62
+ return d.clone().startOf("year");
63
+ },
64
+ format: function (d) {
65
+ return d.format("YYYY");
66
+ },
67
+ increment: function (d) {
68
+ return d.clone().add(1, "year");
69
+ }
70
+ };
71
+ /**
72
+ * Standard built-in date types. To customise, implement the {@link FillDateType} interface.
73
+ */
74
+ exports.dateTypes = {
75
+ days: days,
76
+ months: months,
77
+ quarters: quarters,
78
+ years: years
79
+ };
80
+ /**
81
+ * Examines a set of dates and chooses the most specific type that includes them all. If
82
+ * all fall on Jan, 1 then `years` is chosen, and so on.
83
+ */
84
+ function detectDateType(dates) {
85
+ return !dates.every(function (x) { return x.date() === 1; }) ? exports.dateTypes.days :
86
+ !dates.every(function (x) { return x.month() % 3 === 0; }) ? exports.dateTypes.months :
87
+ !dates.every(function (x) { return x.month() === 0; }) ? exports.dateTypes.quarters :
88
+ exports.dateTypes.years;
89
+ }
90
+ exports.detectDateType = detectDateType;
91
+ /**
92
+ * When querying for a time series chart, e.g. x-axis is _Month_ and y-axis is
93
+ * _Total Sales_, there may be months where nothing was sold so they are
94
+ * missing from the list of records.
95
+ *
96
+ * To render a proper time-series, we need these gaps to be filled in with
97
+ * runs of fake records that give zero amounts for those months. e.g.
98
+ *
99
+ * ```ts
100
+ * const filled = fillDates({
101
+ * records: [
102
+ * { date: '2020-04-01', totalSales: 10 },
103
+ * { date: '2020-06-01', totalSales: 4 },
104
+ * { date: '2020-07-01', totalSales: 9 },
105
+ * ],
106
+ * type: dateTypes.months,
107
+ * getDate: rec => rec.date,
108
+ * fill: (label, rec) => ({
109
+ * label,
110
+ * totalSales: 0,
111
+ * ...rec
112
+ * })
113
+ * });
114
+ * ```
115
+ *
116
+ * In the above example we add a `label` property to all the records, and
117
+ * for the records that fill the gaps we set the `totalSales` property to 0.
118
+ * For the real records, `...rec` will copy the real value of `totalSales`.
119
+ *
120
+ * To do this, we need to know:
121
+ *
122
+ * - how to round a date to the start of a unit (year, month, quarter),
123
+ * - how to increment a date by that unit,
124
+ * - how to format a date to a string for display.
125
+ *
126
+ * These operations are encapsulated by the {@link FillDateType} interface.
127
+ * Several built-in types are provided in {@link dateTypes}, but you can
128
+ * implement your own.
129
+ *
130
+ * Optionally you can also pass `min` and `max` dates, which will cause
131
+ * extra records to be added at the start and end of the range if necessary.
132
+ *
133
+ * If you don't pass a `type`, a suitable type will be detected based on
134
+ * how the input record dates fall on unit boundaries.
135
+ */
136
+ function fillDates(_a) {
137
+ var records = _a.records, getDate = _a.getDate, fill = _a.fill, min = _a.min, max = _a.max, type = _a.type;
138
+ records = __spreadArray([], records, true);
139
+ records.sort(function (x, y) { return parseDate(getDate(x)).diff(parseDate(getDate(y))); });
140
+ type = type !== null && type !== void 0 ? type : detectDateType(records.map(function (d) { return parseDate(getDate(d)); }));
141
+ var results = [];
142
+ var latest = undefined;
143
+ var lower = min ? type.round(parseDate(min)) : undefined;
144
+ for (var _i = 0, records_1 = records; _i < records_1.length; _i++) {
145
+ var record = records_1[_i];
146
+ var current = parseDate(getDate(record));
147
+ for (;;) {
148
+ latest = latest ? type.increment(latest) : lower;
149
+ if (!latest || latest >= current) {
150
+ break;
151
+ }
152
+ results.push(fill(type.format(latest), undefined));
153
+ }
154
+ results.push(fill(type.format(current), record));
155
+ latest = current;
156
+ }
157
+ if (latest && max) {
158
+ var upper = type.round(parseDate(max));
159
+ for (;;) {
160
+ latest = type.increment(latest);
161
+ if (latest > upper) {
162
+ break;
163
+ }
164
+ results.push(fill(type.format(latest), undefined));
165
+ }
166
+ }
167
+ return results;
168
+ }
169
+ exports.fillDates = fillDates;
170
+ /** @deprecated */
171
+ function smartDates(records, min, max, getDate, fill) {
172
+ return fillDates({ records: records, min: min, max: max, getDate: getDate, fill: fill });
173
+ }
174
+ exports.smartDates = smartDates;
175
+ //# sourceMappingURL=fillDates.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fillDates.js","sourceRoot":"","sources":["../src/fillDates.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export {};
@@ -0,0 +1,211 @@
1
+ "use strict";
2
+ var __assign = (this && this.__assign) || function () {
3
+ __assign = Object.assign || function(t) {
4
+ for (var s, i = 1, n = arguments.length; i < n; i++) {
5
+ s = arguments[i];
6
+ for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
7
+ t[p] = s[p];
8
+ }
9
+ return t;
10
+ };
11
+ return __assign.apply(this, arguments);
12
+ };
13
+ var __importDefault = (this && this.__importDefault) || function (mod) {
14
+ return (mod && mod.__esModule) ? mod : { "default": mod };
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ var fillDates_1 = require("./fillDates");
18
+ var moment_1 = __importDefault(require("moment"));
19
+ test("detects days", function () {
20
+ expect((0, fillDates_1.detectDateType)([
21
+ (0, moment_1.default)("2021-04-01"),
22
+ (0, moment_1.default)("2020-11-01"),
23
+ (0, moment_1.default)("2020-11-02"),
24
+ (0, moment_1.default)("2022-07-01"),
25
+ ])).toBe(fillDates_1.dateTypes.days);
26
+ });
27
+ test("detects months", function () {
28
+ expect((0, fillDates_1.detectDateType)([
29
+ (0, moment_1.default)("2021-04-01"),
30
+ (0, moment_1.default)("2020-11-01"),
31
+ (0, moment_1.default)("2022-07-01"),
32
+ ])).toBe(fillDates_1.dateTypes.months);
33
+ });
34
+ test("detects quarters", function () {
35
+ expect((0, fillDates_1.detectDateType)([
36
+ (0, moment_1.default)("2021-04-01"),
37
+ (0, moment_1.default)("2020-10-01"),
38
+ (0, moment_1.default)("2022-07-01"),
39
+ ])).toBe(fillDates_1.dateTypes.quarters);
40
+ });
41
+ test("detects years", function () {
42
+ expect((0, fillDates_1.detectDateType)([
43
+ (0, moment_1.default)("2021-01-01"),
44
+ (0, moment_1.default)("2020-01-01"),
45
+ (0, moment_1.default)("2022-01-01"),
46
+ ])).toBe(fillDates_1.dateTypes.years);
47
+ });
48
+ test("handles empty list", function () {
49
+ expect((0, fillDates_1.fillDates)({
50
+ records: [],
51
+ getDate: function (x) { return 0; },
52
+ fill: function () { return undefined; }
53
+ })).toStrictEqual([]);
54
+ });
55
+ test("leaves complete months alone", function () {
56
+ expect((0, fillDates_1.fillDates)({
57
+ records: [
58
+ { date: "2020-04-01", totalSales: 10 },
59
+ { date: "2020-05-01", totalSales: 4 },
60
+ { date: "2020-06-01", totalSales: 9 },
61
+ { date: "2020-07-01", totalSales: 3 },
62
+ ],
63
+ getDate: function (rec) { return rec.date; },
64
+ fill: function (label, rec) { return (__assign({ label: label, totalSales: 0 }, rec)); },
65
+ min: "2020-04-12",
66
+ max: "2020-07-06"
67
+ })).toStrictEqual([
68
+ { label: "Apr 2020", date: "2020-04-01", totalSales: 10 },
69
+ { label: "May 2020", date: "2020-05-01", totalSales: 4 },
70
+ { label: "Jun 2020", date: "2020-06-01", totalSales: 9 },
71
+ { label: "Jul 2020", date: "2020-07-01", totalSales: 3 },
72
+ ]);
73
+ });
74
+ test("fills in missing months", function () {
75
+ expect((0, fillDates_1.fillDates)({
76
+ records: [
77
+ { date: "2020-04-01", totalSales: 10 },
78
+ { date: "2020-06-01", totalSales: 4 },
79
+ { date: "2020-07-01", totalSales: 9 },
80
+ { date: "2020-11-01", totalSales: 3 },
81
+ ],
82
+ getDate: function (rec) { return rec.date; },
83
+ fill: function (label, rec) { return (__assign({ label: label, totalSales: 0 }, rec)); }
84
+ })).toStrictEqual([
85
+ { label: "Apr 2020", date: "2020-04-01", totalSales: 10 },
86
+ { label: "May 2020", totalSales: 0 },
87
+ { label: "Jun 2020", date: "2020-06-01", totalSales: 4 },
88
+ { label: "Jul 2020", date: "2020-07-01", totalSales: 9 },
89
+ { label: "Aug 2020", totalSales: 0 },
90
+ { label: "Sep 2020", totalSales: 0 },
91
+ { label: "Oct 2020", totalSales: 0 },
92
+ { label: "Nov 2020", date: "2020-11-01", totalSales: 3 },
93
+ ]);
94
+ });
95
+ test("fills in missing months and min/max range", function () {
96
+ expect((0, fillDates_1.fillDates)({
97
+ records: [
98
+ { date: "2020-04-01", totalSales: 10 },
99
+ { date: "2020-06-01", totalSales: 4 },
100
+ { date: "2020-07-01", totalSales: 9 },
101
+ { date: "2020-11-01", totalSales: 3 },
102
+ ],
103
+ getDate: function (rec) { return rec.date; },
104
+ fill: function (label, rec) { return (__assign({ label: label, totalSales: 0 }, rec)); },
105
+ min: "2020-02-15",
106
+ max: "2020-12-02"
107
+ })).toStrictEqual([
108
+ { label: "Feb 2020", totalSales: 0 },
109
+ { label: "Mar 2020", totalSales: 0 },
110
+ { label: "Apr 2020", date: "2020-04-01", totalSales: 10 },
111
+ { label: "May 2020", totalSales: 0 },
112
+ { label: "Jun 2020", date: "2020-06-01", totalSales: 4 },
113
+ { label: "Jul 2020", date: "2020-07-01", totalSales: 9 },
114
+ { label: "Aug 2020", totalSales: 0 },
115
+ { label: "Sep 2020", totalSales: 0 },
116
+ { label: "Oct 2020", totalSales: 0 },
117
+ { label: "Nov 2020", date: "2020-11-01", totalSales: 3 },
118
+ { label: "Dec 2020", totalSales: 0 },
119
+ ]);
120
+ });
121
+ test("leaves complete quarters alone", function () {
122
+ expect((0, fillDates_1.fillDates)({
123
+ records: [
124
+ { date: "2020-07-01", totalSales: 10 },
125
+ { date: "2020-10-01", totalSales: 4 },
126
+ { date: "2021-01-01", totalSales: 9 },
127
+ { date: "2021-04-01", totalSales: 3 },
128
+ ],
129
+ getDate: function (rec) { return rec.date; },
130
+ fill: function (label, rec) { return (__assign({ label: label, totalSales: 0 }, rec)); },
131
+ min: "2020-07-12",
132
+ max: "2020-04-06"
133
+ })).toStrictEqual([
134
+ { label: "Jul-Sep 2020", date: "2020-07-01", totalSales: 10 },
135
+ { label: "Oct-Dec 2020", date: "2020-10-01", totalSales: 4 },
136
+ { label: "Jan-Mar 2021", date: "2021-01-01", totalSales: 9 },
137
+ { label: "Apr-Jun 2021", date: "2021-04-01", totalSales: 3 },
138
+ ]);
139
+ });
140
+ test("fills in missing quarters", function () {
141
+ expect((0, fillDates_1.fillDates)({
142
+ records: [
143
+ { date: "2020-04-01", totalSales: 10 },
144
+ { date: "2020-10-01", totalSales: 4 },
145
+ { date: "2021-01-01", totalSales: 9 },
146
+ { date: "2021-10-01", totalSales: 3 },
147
+ ],
148
+ type: fillDates_1.dateTypes.quarters,
149
+ getDate: function (rec) { return rec.date; },
150
+ fill: function (label, rec) { return (__assign({ label: label, totalSales: 0 }, rec)); }
151
+ })).toStrictEqual([
152
+ { label: "Apr-Jun 2020", date: "2020-04-01", totalSales: 10 },
153
+ { label: "Jul-Sep 2020", totalSales: 0 },
154
+ { label: "Oct-Dec 2020", date: "2020-10-01", totalSales: 4 },
155
+ { label: "Jan-Mar 2021", date: "2021-01-01", totalSales: 9 },
156
+ { label: "Apr-Jun 2021", totalSales: 0 },
157
+ { label: "Jul-Sep 2021", totalSales: 0 },
158
+ { label: "Oct-Dec 2021", date: "2021-10-01", totalSales: 3 },
159
+ ]);
160
+ });
161
+ test("fills in missing quarters and min/max range", function () {
162
+ expect((0, fillDates_1.fillDates)({
163
+ records: [
164
+ { date: "2020-04-01", totalSales: 10 },
165
+ { date: "2020-10-01", totalSales: 4 },
166
+ { date: "2021-01-01", totalSales: 9 },
167
+ { date: "2021-10-01", totalSales: 3 },
168
+ ],
169
+ type: fillDates_1.dateTypes.quarters,
170
+ getDate: function (rec) { return rec.date; },
171
+ fill: function (label, rec) { return (__assign({ label: label, totalSales: 0 }, rec)); },
172
+ min: "2019-10-10",
173
+ max: "2022-01-06"
174
+ })).toStrictEqual([
175
+ { label: "Oct-Dec 2019", totalSales: 0 },
176
+ { label: "Jan-Mar 2020", totalSales: 0 },
177
+ { label: "Apr-Jun 2020", date: "2020-04-01", totalSales: 10 },
178
+ { label: "Jul-Sep 2020", totalSales: 0 },
179
+ { label: "Oct-Dec 2020", date: "2020-10-01", totalSales: 4 },
180
+ { label: "Jan-Mar 2021", date: "2021-01-01", totalSales: 9 },
181
+ { label: "Apr-Jun 2021", totalSales: 0 },
182
+ { label: "Jul-Sep 2021", totalSales: 0 },
183
+ { label: "Oct-Dec 2021", date: "2021-10-01", totalSales: 3 },
184
+ { label: "Jan-Mar 2022", totalSales: 0 },
185
+ ]);
186
+ });
187
+ test("explicit type overrides detection", function () {
188
+ expect((0, fillDates_1.fillDates)({
189
+ records: [
190
+ { date: "2020-07-01", totalSales: 10 },
191
+ { date: "2020-10-01", totalSales: 4 },
192
+ { date: "2021-01-01", totalSales: 9 },
193
+ { date: "2021-04-01", totalSales: 3 },
194
+ ],
195
+ getDate: function (rec) { return rec.date; },
196
+ fill: function (label, rec) { return (__assign({ label: label, totalSales: 0 }, rec)); },
197
+ type: fillDates_1.dateTypes.months
198
+ })).toStrictEqual([
199
+ { label: "Jul 2020", date: "2020-07-01", totalSales: 10 },
200
+ { label: "Aug 2020", totalSales: 0 },
201
+ { label: "Sep 2020", totalSales: 0 },
202
+ { label: "Oct 2020", date: "2020-10-01", totalSales: 4 },
203
+ { label: "Nov 2020", totalSales: 0 },
204
+ { label: "Dec 2020", totalSales: 0 },
205
+ { label: "Jan 2021", date: "2021-01-01", totalSales: 9 },
206
+ { label: "Feb 2021", totalSales: 0 },
207
+ { label: "Mar 2021", totalSales: 0 },
208
+ { label: "Apr 2021", date: "2021-04-01", totalSales: 3 },
209
+ ]);
210
+ });
211
+ //# sourceMappingURL=fillDates.test.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"fillDates.test.js","sourceRoot":"","sources":["../src/fillDates.test.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1 @@
1
+ export * from "./fillDates";
package/dist/index.js ADDED
@@ -0,0 +1,14 @@
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } });
5
+ }) : (function(o, m, k, k2) {
6
+ if (k2 === undefined) k2 = k;
7
+ o[k2] = m[k];
8
+ }));
9
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
10
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
11
+ };
12
+ Object.defineProperty(exports, "__esModule", { value: true });
13
+ __exportStar(require("./fillDates"), exports);
14
+ //# sourceMappingURL=index.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":";;;;;;;;;;;;AAAA,8CAA4B"}
package/jest.config.js ADDED
@@ -0,0 +1,4 @@
1
+ module.exports = {
2
+ preset: 'ts-jest',
3
+ testEnvironment: 'node',
4
+ };
package/package.json ADDED
@@ -0,0 +1,28 @@
1
+ {
2
+ "name": "flowerbi-dates",
3
+ "version": "2.0.0",
4
+ "author": "Daniel Earwicker <dan@earwicker.com>",
5
+ "license": "MIT",
6
+ "description": "FlowerBI: ultra-minimal BI analytics query and UI tools",
7
+ "main": "./dist/index.js",
8
+ "types": "./dist/index.d.ts",
9
+ "devDependencies": {
10
+ "@types/jest": "^27.4.0",
11
+ "jest": "^27.4.7",
12
+ "moment": "^2.29.1",
13
+ "prettier": "^2.5.1",
14
+ "ts-jest": "^27.1.3",
15
+ "typedoc": "^0.22.11",
16
+ "typescript": "^4.5.5"
17
+ },
18
+ "peerDependencies": {
19
+ "moment": "^2.29.1"
20
+ },
21
+ "scripts": {
22
+ "build": "tsc",
23
+ "watch": "tsc -w",
24
+ "test": "jest",
25
+ "docs": "typedoc --excludePrivate --readme home.md --out ../../../docs/typedoc/flowerbi src",
26
+ "prepare": "npm run test && npm run build && npm run docs"
27
+ }
28
+ }
@@ -0,0 +1,234 @@
1
+ import { fillDates, dateTypes, detectDateType } from "./fillDates";
2
+ import moment from "moment";
3
+
4
+ test("detects days", () => {
5
+ expect(detectDateType([
6
+ moment("2021-04-01"),
7
+ moment("2020-11-01"),
8
+ moment("2020-11-02"),
9
+ moment("2022-07-01"),
10
+ ])).toBe(dateTypes.days);
11
+ });
12
+
13
+ test("detects months", () => {
14
+ expect(detectDateType([
15
+ moment("2021-04-01"),
16
+ moment("2020-11-01"),
17
+ moment("2022-07-01"),
18
+ ])).toBe(dateTypes.months);
19
+ });
20
+
21
+ test("detects quarters", () => {
22
+ expect(detectDateType([
23
+ moment("2021-04-01"),
24
+ moment("2020-10-01"),
25
+ moment("2022-07-01"),
26
+ ])).toBe(dateTypes.quarters);
27
+ });
28
+
29
+ test("detects years", () => {
30
+ expect(detectDateType([
31
+ moment("2021-01-01"),
32
+ moment("2020-01-01"),
33
+ moment("2022-01-01"),
34
+ ])).toBe(dateTypes.years);
35
+ });
36
+
37
+ test("handles empty list", () => {
38
+ expect(fillDates({
39
+ records: [],
40
+ getDate: x => 0,
41
+ fill: () => undefined
42
+ })).toStrictEqual([]);
43
+ });
44
+
45
+ test("leaves complete months alone", () => {
46
+ expect(fillDates({
47
+ records: [
48
+ { date: "2020-04-01", totalSales: 10 },
49
+ { date: "2020-05-01", totalSales: 4 },
50
+ { date: "2020-06-01", totalSales: 9 },
51
+ { date: "2020-07-01", totalSales: 3 },
52
+ ],
53
+ getDate: rec => rec.date,
54
+ fill: (label, rec) => ({
55
+ label,
56
+ totalSales: 0,
57
+ ...rec
58
+ }),
59
+ min: "2020-04-12",
60
+ max: "2020-07-06"
61
+ })).toStrictEqual([
62
+ { label: "Apr 2020", date: "2020-04-01", totalSales: 10 },
63
+ { label: "May 2020", date: "2020-05-01", totalSales: 4 },
64
+ { label: "Jun 2020", date: "2020-06-01", totalSales: 9 },
65
+ { label: "Jul 2020", date: "2020-07-01", totalSales: 3 },
66
+ ]);
67
+ });
68
+
69
+ test("fills in missing months", () => {
70
+ expect(fillDates({
71
+ records: [
72
+ { date: "2020-04-01", totalSales: 10 },
73
+ { date: "2020-06-01", totalSales: 4 },
74
+ { date: "2020-07-01", totalSales: 9 },
75
+ { date: "2020-11-01", totalSales: 3 },
76
+ ],
77
+ getDate: rec => rec.date,
78
+ fill: (label, rec) => ({
79
+ label,
80
+ totalSales: 0,
81
+ ...rec
82
+ })
83
+ })).toStrictEqual([
84
+ { label: "Apr 2020", date: "2020-04-01", totalSales: 10 },
85
+ { label: "May 2020", totalSales: 0 },
86
+ { label: "Jun 2020", date: "2020-06-01", totalSales: 4 },
87
+ { label: "Jul 2020", date: "2020-07-01", totalSales: 9 },
88
+ { label: "Aug 2020", totalSales: 0 },
89
+ { label: "Sep 2020", totalSales: 0 },
90
+ { label: "Oct 2020", totalSales: 0 },
91
+ { label: "Nov 2020", date: "2020-11-01", totalSales: 3 },
92
+ ]);
93
+ });
94
+
95
+ test("fills in missing months and min/max range", () => {
96
+ expect(fillDates({
97
+ records: [
98
+ { date: "2020-04-01", totalSales: 10 },
99
+ { date: "2020-06-01", totalSales: 4 },
100
+ { date: "2020-07-01", totalSales: 9 },
101
+ { date: "2020-11-01", totalSales: 3 },
102
+ ],
103
+ getDate: rec => rec.date,
104
+ fill: (label, rec) => ({
105
+ label,
106
+ totalSales: 0,
107
+ ...rec
108
+ }),
109
+ min: "2020-02-15",
110
+ max: "2020-12-02"
111
+ })).toStrictEqual([
112
+ { label: "Feb 2020", totalSales: 0 },
113
+ { label: "Mar 2020", totalSales: 0 },
114
+ { label: "Apr 2020", date: "2020-04-01", totalSales: 10 },
115
+ { label: "May 2020", totalSales: 0 },
116
+ { label: "Jun 2020", date: "2020-06-01", totalSales: 4 },
117
+ { label: "Jul 2020", date: "2020-07-01", totalSales: 9 },
118
+ { label: "Aug 2020", totalSales: 0 },
119
+ { label: "Sep 2020", totalSales: 0 },
120
+ { label: "Oct 2020", totalSales: 0 },
121
+ { label: "Nov 2020", date: "2020-11-01", totalSales: 3 },
122
+ { label: "Dec 2020", totalSales: 0 },
123
+ ]);
124
+ });
125
+
126
+ test("leaves complete quarters alone", () => {
127
+ expect(fillDates({
128
+ records: [
129
+ { date: "2020-07-01", totalSales: 10 },
130
+ { date: "2020-10-01", totalSales: 4 },
131
+ { date: "2021-01-01", totalSales: 9 },
132
+ { date: "2021-04-01", totalSales: 3 },
133
+ ],
134
+ getDate: rec => rec.date,
135
+ fill: (label, rec) => ({
136
+ label,
137
+ totalSales: 0,
138
+ ...rec
139
+ }),
140
+ min: "2020-07-12",
141
+ max: "2020-04-06"
142
+ })).toStrictEqual([
143
+ { label: "Jul-Sep 2020", date: "2020-07-01", totalSales: 10 },
144
+ { label: "Oct-Dec 2020", date: "2020-10-01", totalSales: 4 },
145
+ { label: "Jan-Mar 2021", date: "2021-01-01", totalSales: 9 },
146
+ { label: "Apr-Jun 2021", date: "2021-04-01", totalSales: 3 },
147
+ ]);
148
+ });
149
+
150
+ test("fills in missing quarters", () => {
151
+ expect(fillDates({
152
+ records: [
153
+ { date: "2020-04-01", totalSales: 10 },
154
+ { date: "2020-10-01", totalSales: 4 },
155
+ { date: "2021-01-01", totalSales: 9 },
156
+ { date: "2021-10-01", totalSales: 3 },
157
+ ],
158
+ type: dateTypes.quarters,
159
+ getDate: rec => rec.date,
160
+ fill: (label, rec) => ({
161
+ label,
162
+ totalSales: 0,
163
+ ...rec
164
+ })
165
+ })).toStrictEqual([
166
+ { label: "Apr-Jun 2020", date: "2020-04-01", totalSales: 10 },
167
+ { label: "Jul-Sep 2020", totalSales: 0 },
168
+ { label: "Oct-Dec 2020", date: "2020-10-01", totalSales: 4 },
169
+ { label: "Jan-Mar 2021", date: "2021-01-01", totalSales: 9 },
170
+ { label: "Apr-Jun 2021", totalSales: 0 },
171
+ { label: "Jul-Sep 2021", totalSales: 0 },
172
+ { label: "Oct-Dec 2021", date: "2021-10-01", totalSales: 3 },
173
+ ]);
174
+ });
175
+
176
+ test("fills in missing quarters and min/max range", () => {
177
+ expect(fillDates({
178
+ records: [
179
+ { date: "2020-04-01", totalSales: 10 },
180
+ { date: "2020-10-01", totalSales: 4 },
181
+ { date: "2021-01-01", totalSales: 9 },
182
+ { date: "2021-10-01", totalSales: 3 },
183
+ ],
184
+ type: dateTypes.quarters,
185
+ getDate: rec => rec.date,
186
+ fill: (label, rec) => ({
187
+ label,
188
+ totalSales: 0,
189
+ ...rec
190
+ }),
191
+ min: "2019-10-10",
192
+ max: "2022-01-06"
193
+ })).toStrictEqual([
194
+ { label: "Oct-Dec 2019", totalSales: 0 },
195
+ { label: "Jan-Mar 2020", totalSales: 0 },
196
+ { label: "Apr-Jun 2020", date: "2020-04-01", totalSales: 10 },
197
+ { label: "Jul-Sep 2020", totalSales: 0 },
198
+ { label: "Oct-Dec 2020", date: "2020-10-01", totalSales: 4 },
199
+ { label: "Jan-Mar 2021", date: "2021-01-01", totalSales: 9 },
200
+ { label: "Apr-Jun 2021", totalSales: 0 },
201
+ { label: "Jul-Sep 2021", totalSales: 0 },
202
+ { label: "Oct-Dec 2021", date: "2021-10-01", totalSales: 3 },
203
+ { label: "Jan-Mar 2022", totalSales: 0 },
204
+ ]);
205
+ });
206
+
207
+ test("explicit type overrides detection", () => {
208
+ expect(fillDates({
209
+ records: [
210
+ { date: "2020-07-01", totalSales: 10 },
211
+ { date: "2020-10-01", totalSales: 4 },
212
+ { date: "2021-01-01", totalSales: 9 },
213
+ { date: "2021-04-01", totalSales: 3 },
214
+ ],
215
+ getDate: rec => rec.date,
216
+ fill: (label, rec) => ({
217
+ label,
218
+ totalSales: 0,
219
+ ...rec
220
+ }),
221
+ type: dateTypes.months
222
+ })).toStrictEqual([
223
+ { label: "Jul 2020", date: "2020-07-01", totalSales: 10 },
224
+ { label: "Aug 2020", totalSales: 0 },
225
+ { label: "Sep 2020", totalSales: 0 },
226
+ { label: "Oct 2020", date: "2020-10-01", totalSales: 4 },
227
+ { label: "Nov 2020", totalSales: 0 },
228
+ { label: "Dec 2020", totalSales: 0 },
229
+ { label: "Jan 2021", date: "2021-01-01", totalSales: 9 },
230
+ { label: "Feb 2021", totalSales: 0 },
231
+ { label: "Mar 2021", totalSales: 0 },
232
+ { label: "Apr 2021", date: "2021-04-01", totalSales: 3 },
233
+ ]);
234
+ });
@@ -0,0 +1,217 @@
1
+ import moment, { Moment } from "moment";
2
+
3
+ export type FillDate = Date | string | number | Moment;
4
+
5
+ function parseDate(val: FillDate) {
6
+ // Ensure a numeric year is not interpreted as offset from 1970!
7
+ if (typeof val === "number") {
8
+ val = "" + val;
9
+ }
10
+
11
+ return moment(val);
12
+ }
13
+
14
+ /**
15
+ * Three operations on dates used by {@link fillDates}.
16
+ */
17
+ export type FillDateType = {
18
+ /** Round the given date down to the nearest whole unit (e.g. start of month, quarter, year) */
19
+ round(d: Moment): Moment;
20
+ /** Format the given date to a string */
21
+ format(d: Moment): string;
22
+ /** Increment the date by the unit. The given date will already be rounded down. */
23
+ increment(d: Moment): Moment;
24
+ }
25
+
26
+ const days: FillDateType = {
27
+ round(d) {
28
+ return d.clone().startOf("day");
29
+ },
30
+ format(d) {
31
+ return d.format("ll");
32
+ },
33
+ increment(d) {
34
+ return d.clone().add(1, "day");
35
+ }
36
+ };
37
+
38
+ const months: FillDateType = {
39
+ round(d) {
40
+ return d.clone().startOf("month");
41
+ },
42
+ format(d) {
43
+ return d.format("MMM YYYY");
44
+ },
45
+ increment(d) {
46
+ return d.clone().add(1, "month");
47
+ }
48
+ }
49
+
50
+ const quarters: FillDateType = {
51
+ round(d) {
52
+ return d.clone().startOf("quarter");
53
+ },
54
+ format(d) {
55
+ const monthFirst = d.format("MMM");
56
+ const monthLast = d.clone().add(2, "months").format("MMM");
57
+ const year = d.format("YYYY");
58
+ return `${monthFirst}-${monthLast} ${year}`;
59
+ },
60
+ increment(d) {
61
+ return d.clone().add(3, "months");
62
+ }
63
+ }
64
+
65
+ const years: FillDateType = {
66
+ round(d) {
67
+ return d.clone().startOf("year");
68
+ },
69
+ format(d) {
70
+ return d.format("YYYY");
71
+ },
72
+ increment(d) {
73
+ return d.clone().add(1, "year");
74
+ }
75
+ }
76
+
77
+ /**
78
+ * Standard built-in date types. To customise, implement the {@link FillDateType} interface.
79
+ */
80
+ export const dateTypes = {
81
+ days, months, quarters, years
82
+ } as const;
83
+
84
+ /**
85
+ * Examines a set of dates and chooses the most specific type that includes them all. If
86
+ * all fall on Jan, 1 then `years` is chosen, and so on.
87
+ */
88
+ export function detectDateType(dates: Moment[]): FillDateType {
89
+ return !dates.every(x => x.date() === 1) ? dateTypes.days :
90
+ !dates.every(x => x.month() % 3 === 0) ? dateTypes.months :
91
+ !dates.every(x => x.month() === 0) ? dateTypes.quarters :
92
+ dateTypes.years;
93
+ }
94
+
95
+ /** Options for {@link fillDates} function. */
96
+ export interface FillDatesOptions<T, R> {
97
+ /** The records to base the filled list on. */
98
+ records: T[];
99
+ /** The operations to use for rounding, incrementing and formatting dates. */
100
+ type?: FillDateType;
101
+ /** Extracts a date value from a record in the input list. */
102
+ getDate(record: T): FillDate;
103
+ /**
104
+ * Generate a record for a date, from the formatted {@link dateText} and
105
+ * the input record for that date, if any.
106
+ */
107
+ fill(dateText: string, record: T | undefined): R;
108
+ /**
109
+ * The minimum date to generate. It will be rounded down by the {@link type}
110
+ * so doesn't need to be on an exact boundary.
111
+ */
112
+ min?: FillDate;
113
+ /**
114
+ * The maximum date to generate. It will be rounded down by the {@link type}
115
+ * so doesn't need to be on an exact boundary.
116
+ */
117
+ max?: FillDate;
118
+ }
119
+
120
+ /**
121
+ * When querying for a time series chart, e.g. x-axis is _Month_ and y-axis is
122
+ * _Total Sales_, there may be months where nothing was sold so they are
123
+ * missing from the list of records.
124
+ *
125
+ * To render a proper time-series, we need these gaps to be filled in with
126
+ * runs of fake records that give zero amounts for those months. e.g.
127
+ *
128
+ * ```ts
129
+ * const filled = fillDates({
130
+ * records: [
131
+ * { date: '2020-04-01', totalSales: 10 },
132
+ * { date: '2020-06-01', totalSales: 4 },
133
+ * { date: '2020-07-01', totalSales: 9 },
134
+ * ],
135
+ * type: dateTypes.months,
136
+ * getDate: rec => rec.date,
137
+ * fill: (label, rec) => ({
138
+ * label,
139
+ * totalSales: 0,
140
+ * ...rec
141
+ * })
142
+ * });
143
+ * ```
144
+ *
145
+ * In the above example we add a `label` property to all the records, and
146
+ * for the records that fill the gaps we set the `totalSales` property to 0.
147
+ * For the real records, `...rec` will copy the real value of `totalSales`.
148
+ *
149
+ * To do this, we need to know:
150
+ *
151
+ * - how to round a date to the start of a unit (year, month, quarter),
152
+ * - how to increment a date by that unit,
153
+ * - how to format a date to a string for display.
154
+ *
155
+ * These operations are encapsulated by the {@link FillDateType} interface.
156
+ * Several built-in types are provided in {@link dateTypes}, but you can
157
+ * implement your own.
158
+ *
159
+ * Optionally you can also pass `min` and `max` dates, which will cause
160
+ * extra records to be added at the start and end of the range if necessary.
161
+ *
162
+ * If you don't pass a `type`, a suitable type will be detected based on
163
+ * how the input record dates fall on unit boundaries.
164
+ */
165
+ export function fillDates<T, R>(
166
+ { records, getDate, fill, min, max, type }: FillDatesOptions<T, R>
167
+ ) {
168
+ records = [...records];
169
+ records.sort((x, y) => parseDate(getDate(x)).diff(parseDate(getDate(y))));
170
+
171
+ type = type ?? detectDateType(records.map(d => parseDate(getDate(d))));
172
+
173
+ const results: R[] = [];
174
+ let latest: Moment | undefined = undefined;
175
+ const lower = min ? type.round(parseDate(min)) : undefined;
176
+
177
+ for (const record of records) {
178
+ const current = parseDate(getDate(record));
179
+
180
+ for (;;) {
181
+ latest = latest ? type.increment(latest) : lower;
182
+ if (!latest || latest >= current) {
183
+ break;
184
+ }
185
+
186
+ results.push(fill(type.format(latest), undefined));
187
+ }
188
+
189
+ results.push(fill(type.format(current), record));
190
+ latest = current;
191
+ }
192
+
193
+ if (latest && max) {
194
+ const upper = type.round(parseDate(max))
195
+ for (;;) {
196
+ latest = type.increment(latest);
197
+ if (latest > upper) {
198
+ break;
199
+ }
200
+
201
+ results.push(fill(type.format(latest), undefined));
202
+ }
203
+ }
204
+
205
+ return results;
206
+ }
207
+
208
+ /** @deprecated */
209
+ export function smartDates<T, R>(
210
+ records: T[],
211
+ min: FillDate | undefined,
212
+ max: FillDate | undefined,
213
+ getDate: (record: T) => FillDate,
214
+ fill: (dateText: string, record: T | undefined) => R
215
+ ) {
216
+ return fillDates({ records, min, max, getDate, fill });
217
+ }
package/src/index.ts ADDED
@@ -0,0 +1 @@
1
+ export * from "./fillDates";
package/tsconfig.json ADDED
@@ -0,0 +1,21 @@
1
+ {
2
+ "compilerOptions": {
3
+ "target": "es5",
4
+ "lib": ["dom", "dom.iterable", "esnext"],
5
+ "allowJs": true,
6
+ "skipLibCheck": true,
7
+ "esModuleInterop": true,
8
+ "allowSyntheticDefaultImports": true,
9
+ "strict": true,
10
+ "forceConsistentCasingInFileNames": true,
11
+ "module": "commonjs",
12
+ "moduleResolution": "node",
13
+ "resolveJsonModule": true,
14
+ "isolatedModules": true,
15
+ "outDir": "dist",
16
+ "declaration": true,
17
+ "sourceMap": true,
18
+ "jsx": "react"
19
+ },
20
+ "include": ["src"]
21
+ }