UNPKG

chartjs-adapter-date-std

Version:

Chart.js adapter using browser standard Intl API for time functionalities

406 lines (403 loc) 15.8 kB
/*! * chartjs-adapter-date-std v0.1.13 * https://github.com/gcollin/chartjs-adapter-date-std/blob/master/README.md * (c) 2023 chartjs-adapter-date-std Contributors * Released under the MIT license */ (function (factory) { typeof define === 'function' && define.amd ? define(factory) : factory(); }((function () { 'use strict'; exports.__esModule = true; exports.StdDateAdapter = void 0; var chart_js_1 = require("chart.js"); /* * An adaptor for the chartjs library enabling usage of time series without dependencies to any 3rd party libraries. * Based on the work of: https://github.com/mnlipp/jgrapes-webconsole/blob/master/org.jgrapes.webconsole.provider.chartjs/resources/org/jgrapes/webconsole/provider/chartjs/chart.js/adapters/chartjs-adapter-simple.js * Simple time axes adapter for chart.js. * * * Handles Date and numeric data (as from Date.toTime()) only. * * * Parsing simply calls the constructor of Date. * * * Supported displayFormats are "datetime", "milliseconds", ... * (i.e. key is passed through). Formatting is done with * Intl.DateTimeFormat. Locale may be changed between calls to * update. * * * "weeks" and "quarters" is not supported by Intl.DateTimeFormat, * the date is output instead. * * * The helper functions (add, diff, etc.) have not really been tested. * * * Superficial testing gives better performance results than moment * when using firefox as runtime. */ var StdDateAdapter = /** @class */ (function () { function StdDateAdapter(locale) { var _a; this.formatLabels = ["datetime", "millisecond", "second", "minute", "hour", "day", "week", "month", "quarter", "year"]; this.FORMATS = {}; this.intlFormats = { 'datetime': { year: "numeric", month: "short", day: "numeric", 'hour': "numeric", minute: "numeric", second: "numeric" }, 'millisecond': { hour: "numeric", minute: "numeric", second: "numeric", // eslint-disable-next-line @typescript-eslint/ban-ts-comment //@ts-ignore fractionalSecondDigits: 3 }, 'second': { hour: "numeric", minute: "numeric", second: "numeric" }, 'minute': { hour: "numeric", minute: "numeric" }, 'hour': { hour: 'numeric' }, 'day': { day: 'numeric', month: 'short' }, 'week': { day: 'numeric', month: 'short', year: 'numeric' }, 'month': { month: 'short', year: 'numeric' }, 'year': { year: 'numeric' } }; this.formatters = {}; this.configuredLocale = ""; this.updateLocale(locale || ((_a = globalThis === null || globalThis === void 0 ? void 0 : globalThis.window) === null || _a === void 0 ? void 0 : _a.navigator.language) || "en-US"); for (var _i = 0, _b = this.formatLabels; _i < _b.length; _i++) { var label = _b[_i]; (this.FORMATS)[label] = label; } } /** * Creates an object from this StdAdaptorClass that can be used in Object.assign (...). * Needed for Chart.js */ StdDateAdapter.chartJsStandardAdapter = function () { console.log("Registering GraphJs Standard Date Adaptor"); return { _id: "StdDataAdapter", delegate: new StdDateAdapter(), override: function (members) { return this.delegate.override(members); }, init: function (chartOptions) { return this.delegate.init(chartOptions); }, formats: function () { return this.delegate.formats(); }, parse: function (value, fmt) { return this.delegate.parse(value, fmt); }, format: function (time, fmt) { return this.delegate.format(time, fmt); }, add: function (time, amount, unit) { return this.delegate.add(time, amount, unit); }, diff: function (max, min, unit) { return this.delegate.diff(max, min, unit); }, startOf: function (time, unit, weekday) { return this.delegate.startOf(time, unit, weekday); }, endOf: function (time, unit) { return this.delegate.endOf(time, unit); } }; }; StdDateAdapter.prototype.updateLocale = function (locale) { if (locale && locale != this.configuredLocale) { for (var _i = 0, _a = this.formatLabels; _i < _a.length; _i++) { var label = _a[_i]; this.formatters[label] = new Intl.DateTimeFormat(locale, (this.intlFormats)[label]); } this.configuredLocale = locale; } }; StdDateAdapter.prototype.override = function (members) { //throw new Error("Method not implemented."); }; StdDateAdapter.prototype.init = function (chartOptions) { //throw new Error("Method not implemented."); }; StdDateAdapter.prototype.toInteger = function (dirtyNumber) { if (dirtyNumber === null || dirtyNumber === true || dirtyNumber === false) { return NaN; } var number = Number(dirtyNumber); if (isNaN(number)) { return number; } return number < 0 ? Math.ceil(number) : Math.floor(number); }; StdDateAdapter.prototype.toDate = function (value) { if (value == null) { return null; } if (value instanceof Date) { return value; } if (typeof value === 'number') { return new Date(value); } else if (typeof value === 'string') { var number = Date.parse(value); if (isNaN(number)) { // Check if it's a trimester var val = value.toUpperCase().trim(); var trimester = -1; // Brut force stuff var trimesterPos = val.indexOf("Q1"); if (trimesterPos != -1) trimester = 1; else { trimesterPos = val.indexOf("Q2"); if (trimesterPos != -1) trimester = 2; else { trimesterPos = val.indexOf("Q3"); if (trimesterPos != -1) trimester = 3; else { trimesterPos = val.indexOf("Q4"); if (trimesterPos != -1) trimester = 4; else return null; } } } var year = NaN; var yearIndex = val.substring(trimesterPos).lastIndexOf(" "); if (yearIndex != -1) year = Number.parseInt(val.substring(trimesterPos + yearIndex)); if (isNaN(year)) year = new Date().getFullYear(); // console.log ("Trimester = "+trimester.toString()+" value = "+((trimester-1)*3+1)); return new Date(year, ((trimester - 1) * 3 + 1)); } else { return new Date(number); } } return null; }; StdDateAdapter.prototype.addMonths = function (date, amount) { var newDate = new Date(date.getTime()); newDate.setMonth(date.getMonth() + amount); if (newDate.getMonth() != (date.getMonth() + amount) % 12) { newDate.setDate(0); } return newDate.getTime(); }; StdDateAdapter.prototype.diffInMonths = function (max, min) { var diff = (max.getFullYear() - min.getFullYear()) * 12; diff += max.getMonth() - min.getMonth(); // Make sure that we have full months if (this.addMonths(min, diff) > max.getTime()) { diff -= 1; } return diff; }; StdDateAdapter.prototype.formats = function () { return this.FORMATS; }; StdDateAdapter.prototype.parse = function (value, fmt) { var _a; // console.log("parsing ", value); var ret = (_a = this.toDate(value)) === null || _a === void 0 ? void 0 : _a.getTime(); if (ret == null) return null; else return ret; }; StdDateAdapter.prototype.format = function (time, fmt) { if (fmt === 'quarter') { // Special case var curDate = new Date(time); // console.log ("Format quarter of ", curDate); return "Q" + Math.floor(curDate.getMonth() / 3 + 1).toString() + " - " + curDate.getFullYear().toString(); } if (!this.formatLabels.includes(fmt)) { return "Unknown"; } return (this.formatters)[fmt].format(time); }; StdDateAdapter.prototype.add = function (time, amount, unit) { amount = this.toInteger(amount); if (isNaN(amount)) { return amount; } var date = this.toDate(time); if ((!amount) || (date == null)) { return NaN; } switch (unit) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore // eslint-disable-next-line no-fallthrough case 'week': amount *= 7; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore // eslint-disable-next-line no-fallthrough case 'day': amount *= 24; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore // eslint-disable-next-line no-fallthrough case 'hour': amount *= 60; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore // eslint-disable-next-line no-fallthrough case 'minute': amount *= 60; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore // eslint-disable-next-line no-fallthrough case 'second': amount *= 1000; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore // eslint-disable-next-line no-fallthrough case 'millisecond': break; case 'year': return this.addMonths(date, amount * 12); case 'quarter': return this.addMonths(date, amount * 3); case 'month': return this.addMonths(date, amount); default: return time; } return time + amount; }; StdDateAdapter.prototype.diff = function (max, min, unit) { var maxDate = this.toDate(max); var minDate = this.toDate(min); if ((maxDate == null) || (minDate == null)) return NaN; var diff = maxDate.getTime() - minDate.getTime(); switch (unit) { // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore // eslint-disable-next-line no-fallthrough case 'week': diff /= 7; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore // eslint-disable-next-line no-fallthrough case 'day': diff /= 24; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore // eslint-disable-next-line no-fallthrough case 'hour': diff /= 60; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore // eslint-disable-next-line no-fallthrough case 'minute': diff /= 60; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore // eslint-disable-next-line no-fallthrough case 'second': diff /= 1000; // eslint-disable-next-line @typescript-eslint/ban-ts-comment // @ts-ignore // eslint-disable-next-line no-fallthrough case 'millisecond': break; case 'month': return this.diffInMonths(maxDate, minDate); case 'quarter': return this.diffInMonths(maxDate, minDate) / 3; case 'year': return this.diffInMonths(maxDate, minDate) / 12; default: return 0; } if (diff < 0) { return Math.ceil(diff); } return Math.floor(diff); }; StdDateAdapter.prototype.startOf = function (time, unit, weekday) { var date = this.toDate(time); if (date == null) return NaN; switch (unit) { case 'second': date.setMilliseconds(0); break; case 'minute': date.setSeconds(0, 0); break; case 'hour': date.setMinutes(0, 0, 0); break; case 'quarter': { var cur = date.getMonth(); date.setMonth(cur - (cur % 3)); } break; case 'month': date.setDate(1); break; case 'day': date.setHours(0, 0, 0, 0); break; case 'isoWeek': case 'week': { // Monday --> 0 var cur = (date.getDay() + 6) % 7; date.setDate(date.getDate() - cur); date.setHours(0, 0, 0, 0); break; } case 'year': { var newDate = new Date(0); newDate.setFullYear(date.getFullYear(), 0, 1); newDate.setHours(0, 0, 0, 0); return newDate.getTime(); } default: return date.getTime(); } return date.getTime(); }; StdDateAdapter.prototype.endOf = function (time, unit) { var date = this.toDate(time); if (date == null) return NaN; switch (unit) { case 'second': date.setMilliseconds(999); break; case 'minute': date.setSeconds(59, 999); break; case 'hour': date.setMinutes(59, 59, 999); break; case 'day': date.setHours(23, 59, 59, 999); break; case 'isoWeek': case 'week': { // Monday --> 0 var cur = (date.getDay() + 6) % 7; date.setDate(date.getDate() + 6 - cur); date.setHours(23, 59, 59, 999); break; } case 'month': { var month = date.getMonth(); date.setFullYear(date.getFullYear(), month + 1, 0); date.setHours(23, 59, 59, 999); break; } case 'quarter': { var curMonth = date.getMonth(); date.setMonth(curMonth - (curMonth % 3) + 3, 0); date.setHours(23, 59, 59, 999); break; } case 'year': { var year = date.getFullYear(); date.setFullYear(year + 1, 0, 0); date.setHours(23, 59, 59, 999); break; } default: return time; } return date.getTime(); }; return StdDateAdapter; }()); exports.StdDateAdapter = StdDateAdapter; // Automatically register the adapter chart_js_1._adapters._date.override(StdDateAdapter.chartJsStandardAdapter()); })));