## Date Adapters
-The time scale requires both a date library and corresponding adapter to be present. By default, Chart.js includes an adapter for Moment.js. You may wish to choose from [other available adapters](https://github.com/chartjs/awesome#adapters) instead.
+The time scale **requires** both a date library and corresponding adapter to be present. Please choose from the [available adapters](https://github.com/chartjs/awesome#adapters).
## Data Sets
});
```
-**Note:** in order to use the time scale, you need to make sure [one of the available date adapters](https://github.com/chartjs/awesome#adapters) and corresponding date library are fully loaded **before** requiring Chart.js. The date adapter for Moment.js is included with Chart.js, but you still need to include Moment.js itself if this is the date adapter you choose to use. You can either use a shim:
+**Note:** in order to use the time scale, you need to make sure [one of the available date adapters](https://github.com/chartjs/awesome#adapters) and corresponding date library are fully loaded **after** requiring Chart.js. For this you can use nested requires:
```javascript
-require.config({
- shim: {
- 'chartjs': {
- deps: ['moment'] // enforce moment to be loaded before chartjs
- }
- },
- paths: {
- 'chartjs': 'path/to/chartjs/dist/Chart.min.js',
- 'moment': 'path/to/moment'
- }
-});
-
require(['chartjs'], function(Chart) {
- new Chart(ctx, {...});
-});
-```
-
-or simply use two nested `require()`:
-
-```javascript
-require(['moment'], function() {
- require(['chartjs'], function(Chart) {
- new Chart(ctx, {...});
+ require(['moment'], function() {
+ require(['chartjs-adapter-moment'], function() {
+ new Chart(ctx, {...});
+ });
});
});
```
### Setup and installation
* Chart.js is no longer providing the `Chart.bundle.js` and `Chart.bundle.min.js`. Please see the [installation](installation.md) and [integration](integration.md) docs for details on the recommended way to setup Chart.js if you were using these builds.
-* `moment` is no longer specified as an npm dependency. If you are using the time scale, you must include one of [the available adapters](https://github.com/chartjs/awesome#adapters) and corresponding date library. If you are using a date library other than moment, you no longer need to exclude moment from your build.
+* `moment` is no longer specified as an npm dependency. If you are using the time scale, you must include one of [the available adapters](https://github.com/chartjs/awesome#adapters) and corresponding date library. You no longer need to exclude moment from your build.
### Ticks
{pattern: 'test/fixtures/**/*.png', included: false},
'node_modules/moment/min/moment.min.js',
'test/index.js',
- 'src/index.js'
+ 'src/index.js',
+ 'node_modules/chartjs-adapter-moment/dist/chartjs-adapter-moment.js'
].concat((args.inputs || 'test/specs/**/*.js').split(';')),
preprocessors: {
"integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
"dev": true
},
+ "chartjs-adapter-moment": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/chartjs-adapter-moment/-/chartjs-adapter-moment-0.1.1.tgz",
+ "integrity": "sha512-lFGCiqpn+0e6CEbEKdG1L3LYR0jnKFqtXsExzmEWXGCxdymTFSqntiWAqWAYDblL/QB3sUk881xVGzhWZdn4kQ==",
+ "dev": true
+ },
"chokidar": {
"version": "2.1.8",
"resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
"@rollup/plugin-node-resolve": "^7.1.1",
"babel-plugin-istanbul": "^6.0.0",
"babel-preset-es2015-rollup": "^3.0.0",
+ "chartjs-adapter-moment": "^0.1.1",
"coveralls": "^3.0.9",
"eslint": "^6.8.0",
"eslint-config-chartjs": "^0.2.0",
const babel = require('rollup-plugin-babel');
const cleanup = require('rollup-plugin-cleanup');
const json = require('@rollup/plugin-json');
-const optional = require('./rollup.plugins').optional;
const resolve = require('@rollup/plugin-node-resolve');
const terser = require('rollup-plugin-terser').terser;
const pkg = require('./package.json');
json(),
resolve(),
babel(),
- optional({
- include: ['moment']
- }),
cleanup({
sourcemap: true
})
banner,
format: 'umd',
indent: false,
- globals: {
- moment: 'moment'
- }
},
- external: [
- 'moment'
- ]
},
{
input,
json(),
resolve(),
babel(),
- optional({
- include: ['moment']
- }),
terser({
output: {
preamble: banner
file: 'dist/Chart.min.js',
format: 'umd',
indent: false,
- globals: {
- moment: 'moment'
- }
},
- external: [
- 'moment'
- ]
},
// ES6 builds
banner,
format: 'esm',
indent: false,
- globals: {
- moment: 'moment'
- }
},
- external: [
- 'moment'
- ]
},
{
input,
file: 'dist/Chart.esm.min.js',
format: 'esm',
indent: false,
- globals: {
- moment: 'moment'
- }
},
- external: [
- 'moment'
- ]
},
];
+++ /dev/null
-/* eslint-disable import/no-commonjs */
-const UMD_WRAPPER_RE = /(\(function \(global, factory\) \{)((?:\s.*?)*)(\}\(this,)/;
-const CJS_FACTORY_RE = /(module.exports = )(factory\(.*?\))( :)/;
-const AMD_FACTORY_RE = /(define\()(.*?, factory)(\) :)/;
-
-function optional(config = {}) {
- return {
- name: 'optional',
- renderChunk(code, chunk, options) {
- if (options.format !== 'umd') {
- this.error('only UMD format is currently supported');
- }
-
- const wrapper = UMD_WRAPPER_RE.exec(code);
- const include = config.include;
- if (!wrapper) {
- this.error('failed to parse the UMD wrapper');
- }
-
- let content = wrapper[2];
- let factory = (CJS_FACTORY_RE.exec(content) || [])[2];
- let updated = false;
-
- for (const lib of chunk.imports) {
- if (!include || include.indexOf(lib) !== -1) {
- const regex = new RegExp(`require\\('${lib}'\\)`);
- if (!regex.test(factory)) {
- this.error(`failed to parse the CJS require for ${lib}`);
- }
-
- // We need to write inline try / catch with explicit require
- // in order to enable statical extraction of dependencies:
- // try { return require('moment'); } catch(e) {}
- const loader = `function() { try { return require('${lib}'); } catch(e) { } }()`;
- factory = factory.replace(regex, loader);
- updated = true;
- }
- }
-
- if (!updated) {
- return;
- }
-
- // Replace the CJS factory by our updated one.
- content = content.replace(CJS_FACTORY_RE, `$1${factory}$3`);
-
- // Replace the AMD factory by our updated one: we need to use the
- // following AMD form in order to be able to try/catch require:
- // define(['require'], function(require) { ... require(...); ... })
- // https://github.com/amdjs/amdjs-api/wiki/AMD#using-require-and-exports
- content = content.replace(AMD_FACTORY_RE, `$1['require'], function(require) { return ${factory}; }$3`);
-
- return code.replace(UMD_WRAPPER_RE, `$1${content}$3`);
- }
- };
-}
-
-module.exports = {
- optional
-};
Chart: true
Samples: true
moment: true
+ luxon: true
randomScalingFactor: true
rules:
<head>
<title>Line Chart</title>
- <script src="https://cdn.jsdelivr.net/npm/moment@2.24.0/moment.min.js"></script>
<script src="../../dist/Chart.min.js"></script>
+ <script src="https://cdn.jsdelivr.net/npm/luxon@1.15.0"></script>
+ <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-luxon@0.2.0"></script>
<script src="../utils.js"></script>
<style>
canvas {
<button id="update">update</button>
<script>
function isFirstUnitOfPeriod(date, unit, period) {
- let first = date.clone().startOf(period);
- while (first.isoWeekday() > 5) {
- first.add(1, 'days');
+ let first = date.startOf(period);
+ while (first.weekday > 5) {
+ first = first.plus({day: 1});
}
if (unit === 'second' || unit === 'minute' || unit === 'hour') {
- first = first.hours(9).minutes(30);
+ first = first.set({hour: 9, minute: 30});
}
- return date.isSame(first);
+ return date === first;
}
// Generate data between the stock market hours of 9:30am - 5pm.
}
function beforeNineThirty(date) {
- return date.hour() < 9 || (date.hour() === 9 && date.minute() < 30);
+ return date.hour < 9 || (date.hour === 9 && date.minute < 30);
}
function after4pm(date) {
- return date.hour() > 16 || (date.hour() === 16 && date.minute() > 0);
+ return date.hour > 16 || (date.hour === 16 && date.minute > 0);
}
// Returns true if outside 9:30am-4pm on a weekday
function outsideMarketHours(date) {
- if (date.isoWeekday() > 5) {
+ if (date.weekday > 5) {
return true;
}
if (unitLessThanDay() && (beforeNineThirty(date) || after4pm(date))) {
const open = randomNumber(lastClose * 0.95, lastClose * 1.05).toFixed(2);
const close = randomNumber(open * 0.95, open * 1.05).toFixed(2);
return {
- t: date.valueOf(),
+ x: date.valueOf(),
y: close
};
}
- let date = moment('Jan 01 1990', 'MMM DD YYYY');
- const now = moment();
+ let date = luxon.DateTime.fromFormat('Jan 01 1990', 'LLL dd yyyy');
+ const now = luxon.DateTime.local();
const data = [];
const lessThanDay = unitLessThanDay();
- for (; data.length < 600 && date.isBefore(now); date = date.clone().add(1, unit).startOf(unit)) {
+ const plus = {};
+ plus[unit] = 1;
+ for (; data.length < 600 && date < now; date = date.plus(plus).startOf(unit)) {
if (outsideMarketHours(date)) {
if (!lessThanDay || !beforeNineThirty(date)) {
- date = date.clone().add(date.isoWeekday() >= 5 ? 8 - date.isoWeekday() : 1, 'day');
+ date = date.plus({day: date.weekday >= 5 ? 8 - date.weekday : 1});
}
if (lessThanDay) {
- date = date.hour(9).minute(30).second(0);
+ date = date.set({hour: 9, minute: 30});
}
}
data.push(randomBar(date, data.length > 0 ? data[data.length - 1].y : 30));
// major ticks
const ticks = scale.ticks;
for (let i = 0; i < ticks.length; i++) {
- ticks[i].major = !majorUnit || isFirstUnitOfPeriod(moment(ticks[i].value), unit, majorUnit);
+ ticks[i].major = !majorUnit || isFirstUnitOfPeriod(luxon.DateTime.fromMillis(ticks[i].value), unit, majorUnit);
}
scale.ticks = ticks;
}
<head>
<title>Line Chart - Combo Time Scale</title>
- <script src="https://cdn.jsdelivr.net/npm/moment@2.24.0/moment.min.js"></script>
<script src="../../../dist/Chart.min.js"></script>
+ <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns@1.0.0/dist/chartjs-adapter-date-fns.bundle.min.js"></script>
<script src="../../utils.js"></script>
<style>
canvas {
<button id="removeData">Remove Data</button>
<script>
function newDate(days) {
- return moment().startOf('day').add(days, 'd').valueOf();
+ var date = new Date();
+ date.setHours(0, 0, 0, 0);
+ date.setDate(date.getDate() + days);
+ return date.valueOf();
}
var labels = [];
<head>
<title>Time Scale Point Data</title>
- <script src="https://cdn.jsdelivr.net/npm/moment@2.24.0/moment.min.js"></script>
<script src="../../../dist/Chart.min.js"></script>
+ <script src="https://cdn.jsdelivr.net/npm/moment@2.24.0"></script>
+ <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment@0.1.1"></script>
<script src="../../utils.js"></script>
<style>
canvas {
<head>
<title>Time Scale Point Data</title>
- <script src="https://cdn.jsdelivr.net/npm/moment@2.24.0/moment.min.js"></script>
<script src="../../../dist/Chart.min.js"></script>
+ <script src="https://cdn.jsdelivr.net/npm/moment@2.24.0"></script>
+ <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment@0.1.1"></script>
<script src="../../utils.js"></script>
<style>
canvas {
<head>
<title>Line Chart</title>
- <script src="https://cdn.jsdelivr.net/npm/moment@2.24.0/moment.min.js"></script>
<script src="../../../dist/Chart.min.js"></script>
+ <script src="https://cdn.jsdelivr.net/npm/moment@2.24.0"></script>
+ <script src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment@0.1.1"></script>
<script src="../../utils.js"></script>
<style>
canvas {
+++ /dev/null
-// TODO v3 - make this adapter external (chartjs-adapter-moment)
-
-import moment from 'moment';
-import adapters from '../core/core.adapters';
-
-const FORMATS = {
- datetime: 'MMM D, YYYY, h:mm:ss a',
- millisecond: 'h:mm:ss.SSS a',
- second: 'h:mm:ss a',
- minute: 'h:mm a',
- hour: 'hA',
- day: 'MMM D',
- week: 'll',
- month: 'MMM YYYY',
- quarter: '[Q]Q - YYYY',
- year: 'YYYY'
-};
-
-adapters._date.override(typeof moment === 'function' ? {
- _id: 'moment', // DEBUG ONLY
-
- formats() {
- return FORMATS;
- },
-
- parse(value, format) {
- if (typeof value === 'string' && typeof format === 'string') {
- value = moment(value, format);
- } else if (!(value instanceof moment)) {
- value = moment(value);
- }
- return value.isValid() ? value.valueOf() : null;
- },
-
- format(time, format) {
- return moment(time).format(format);
- },
-
- add(time, amount, unit) {
- return moment(time).add(amount, unit).valueOf();
- },
-
- diff(max, min, unit) {
- return moment(max).diff(moment(min), unit);
- },
-
- startOf(time, unit, weekday) {
- time = moment(time);
- if (unit === 'isoWeek') {
- return time.isoWeekday(weekday).valueOf();
- }
- return time.startOf(unit).valueOf();
- },
-
- endOf(time, unit) {
- return moment(time).endOf(unit).valueOf();
- }
-} : {});
+++ /dev/null
-// -----------------------------------------------------------------------------
-// IMPORTANT: do NOT submit new adapters to this repository, instead
-// create an external library named `chartjs-adapter-{lib-name}`
-// -----------------------------------------------------------------------------
-
-// Built-in moment adapter that we need to keep for backward compatibility
-// https://github.com/chartjs/Chart.js/issues/5542
-import './adapter.moment';
import * as scales from './scales/index';
Object.keys(scales).forEach(key => Chart.scaleService.registerScale(scales[key]));
-// Load to register built-in adapters (as side effects)
-import './adapters/index';
-
// Loading built-in plugins
import plugins from './plugins/index';
for (const k in plugins) {
adapters: {},
time: {
- parser: false, // false == a pattern string from https://momentjs.com/docs/#/parsing/string-format/ or a custom callback that converts its argument to a moment
+ parser: false, // false == a pattern string from or a custom callback that converts its argument to a timestamp
unit: false, // false == automatic or override with week, month, year, etc.
round: false, // none, or override with week, month, year, etc.
- isoWeekday: false, // override week start day - see https://momentjs.com/docs/#/get-set/iso-weekday/
+ isoWeekday: false, // override week start day
minUnit: 'millisecond',
displayFormats: {}
},