├── .editorconfig ├── .eslintignore ├── .eslintrc.yml ├── .github ├── release-drafter.yml └── workflows │ ├── ci.yml │ ├── compressed-size.yml │ ├── npmpublish.yml │ └── release-drafter.yml ├── .gitignore ├── LICENSE.md ├── README.md ├── karma.conf.cjs ├── package-lock.json ├── package.json ├── rollup.config.js ├── src └── index.js └── test ├── .eslintrc.yml ├── index.js └── specs └── adapter.spec.js /.editorconfig: -------------------------------------------------------------------------------- 1 | # https://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | indent_style = space 6 | indent_size = 2 7 | end_of_line = lf 8 | charset = utf-8 9 | trim_trailing_whitespace = true 10 | insert_final_newline = true 11 | 12 | [*.html] 13 | indent_style = tab 14 | indent_size = 4 15 | -------------------------------------------------------------------------------- /.eslintignore: -------------------------------------------------------------------------------- 1 | **/*{.,-}min.js 2 | dist/**/* 3 | -------------------------------------------------------------------------------- /.eslintrc.yml: -------------------------------------------------------------------------------- 1 | extends: 2 | - chartjs 3 | - plugin:es/no-new-in-es2019 4 | 5 | env: 6 | es6: true 7 | browser: true 8 | node: true 9 | 10 | parserOptions: 11 | ecmaVersion: 2022 12 | sourceType: module 13 | ecmaFeatures: 14 | impliedStrict: true 15 | modules: true 16 | 17 | plugins: ['es'] 18 | -------------------------------------------------------------------------------- /.github/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name-template: 'v$RESOLVED_VERSION' 2 | tag-template: 'v$RESOLVED_VERSION' 3 | categories: 4 | - title: 'Breaking Changes' 5 | labels: 6 | - 'breaking change' 7 | - title: 'Enhancements' 8 | labels: 9 | - 'enhancement' 10 | - title: 'Bugs Fixed' 11 | labels: 12 | - 'bug' 13 | - title: 'Types' 14 | labels: 15 | - 'types' 16 | - title: 'Documentation' 17 | labels: 18 | - 'documentation' 19 | - title: 'Development' 20 | labels: 21 | - 'chore' 22 | exclude-labels: 23 | - 'infrastructure' 24 | change-template: '- #$NUMBER $TITLE' 25 | change-title-escapes: '\<*_&`#@' 26 | version-resolver: 27 | major: 28 | labels: 29 | - 'breaking change' 30 | minor: 31 | labels: 32 | - 'enhancement' 33 | patch: 34 | labels: 35 | - 'bug' 36 | - 'chore' 37 | - 'types' 38 | default: patch 39 | template: | 40 | # Essential Links 41 | 42 | * [npm](https://www.npmjs.com/package/chartjs-adapter-date-fns) 43 | 44 | $CHANGES 45 | 46 | Thanks to $CONTRIBUTORS 47 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: Node.js CI 2 | 3 | on: 4 | push: 5 | branches: [ master, next ] 6 | pull_request: 7 | branches: [ master, next ] 8 | 9 | jobs: 10 | build: 11 | 12 | runs-on: ${{ matrix.os }} 13 | 14 | strategy: 15 | matrix: 16 | os: [ubuntu-latest, windows-latest] 17 | fail-fast: false 18 | 19 | steps: 20 | - uses: actions/checkout@v3 21 | - uses: actions/setup-node@v3 22 | with: 23 | cache: npm 24 | - run: | 25 | npm ci 26 | npm run build 27 | if [ "${{ runner.os }}" == "Windows" ]; then 28 | npm test 29 | else 30 | xvfb-run --auto-servernum npm test 31 | fi 32 | shell: bash 33 | - name: Coveralls Parallel - Chrome 34 | uses: coverallsapp/github-action@master 35 | with: 36 | github-token: ${{ secrets.github_token }} 37 | path-to-lcov: './coverage/chrome/lcov.info' 38 | flag-name: ${{ matrix.os }}-chrome 39 | parallel: true 40 | - name: Coveralls Parallel - Firefox 41 | uses: coverallsapp/github-action@master 42 | with: 43 | github-token: ${{ secrets.github_token }} 44 | path-to-lcov: './coverage/firefox/lcov.info' 45 | flag-name: ${{ matrix.os }}-firefox 46 | parallel: true 47 | 48 | finish: 49 | needs: build 50 | runs-on: ubuntu-latest 51 | steps: 52 | - name: Coveralls Finished 53 | uses: coverallsapp/github-action@master 54 | with: 55 | github-token: ${{ secrets.github_token }} 56 | parallel-finished: true 57 | -------------------------------------------------------------------------------- /.github/workflows/compressed-size.yml: -------------------------------------------------------------------------------- 1 | 2 | name: Compressed Size 3 | 4 | on: [pull_request] 5 | 6 | jobs: 7 | build: 8 | 9 | runs-on: ubuntu-latest 10 | 11 | steps: 12 | - uses: actions/checkout@v3 13 | - uses: preactjs/compressed-size-action@v2 14 | with: 15 | repo-token: "${{ secrets.GITHUB_TOKEN }}" 16 | -------------------------------------------------------------------------------- /.github/workflows/npmpublish.yml: -------------------------------------------------------------------------------- 1 | name: Node.js Package 2 | 3 | on: 4 | release: 5 | types: [published] 6 | 7 | jobs: 8 | setup: 9 | runs-on: ubuntu-latest 10 | outputs: 11 | version: ${{ steps.trim.outputs.version }} 12 | steps: 13 | - id: trim 14 | run: echo "::set-output name=version::${TAG:1}" 15 | env: 16 | TAG: ${{ github.event.release.tag_name }} 17 | 18 | test: 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: actions/checkout@v3 22 | - uses: actions/setup-node@v3 23 | with: 24 | cache: npm 25 | - name: Test 26 | run: | 27 | npm ci 28 | xvfb-run --auto-servernum npm test 29 | publish-npm: 30 | needs: [test, setup] 31 | runs-on: ubuntu-latest 32 | steps: 33 | - uses: actions/checkout@v3 34 | - uses: actions/setup-node@v3 35 | with: 36 | cache: npm 37 | registry-url: https://registry.npmjs.org/ 38 | - name: Setup and build 39 | run: | 40 | npm ci 41 | npm install -g json 42 | json -I -f package.json -e "this.version=\"$VERSION\"" 43 | json -I -f package-lock.json -e "this.version=\"$VERSION\"" 44 | npm run build 45 | npm pack 46 | env: 47 | VERSION: ${{ needs.setup.outputs.version }} 48 | - name: Publish @next 49 | run: npm publish --tag next 50 | if: "github.event.release.prerelease" 51 | env: 52 | NODE_AUTH_TOKEN: ${{secrets.NPM_AUTH_TOKEN}} 53 | - name: Publish @latest 54 | run: npm publish --tag latest 55 | if: "!github.event.release.prerelease" 56 | env: 57 | NODE_AUTH_TOKEN: ${{secrets.NPM_AUTH_TOKEN}} 58 | -------------------------------------------------------------------------------- /.github/workflows/release-drafter.yml: -------------------------------------------------------------------------------- 1 | name: Release Drafter 2 | 3 | on: 4 | push: 5 | branches: 6 | - master 7 | - next 8 | 9 | jobs: 10 | correct_repository: 11 | runs-on: ubuntu-latest 12 | steps: 13 | - name: fail on fork 14 | if: github.repository_owner != 'chartjs' 15 | run: exit 1 16 | 17 | update_release_draft: 18 | needs: correct_repository 19 | runs-on: ubuntu-latest 20 | steps: 21 | - uses: release-drafter/release-drafter@v5 22 | env: 23 | GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} 24 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .vscode/ 2 | coverage/ 3 | dist/ 4 | node_modules/ 5 | *.stackdump 6 | .DS_Store 7 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2019 Chart.js Contributors 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: 6 | 7 | The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. 8 | 9 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # chartjs-adapter-date-fns 2 | 3 | [![release](https://img.shields.io/github/release/chartjs/chartjs-adapter-date-fns.svg?style=flat-square)](https://github.com/chartjs/chartjs-adapter-date-fns/releases/latest) [![travis](https://img.shields.io/travis/chartjs/chartjs-adapter-date-fns.svg?style=flat-square&maxAge=60)](https://travis-ci.org/chartjs/chartjs-adapter-date-fns) [![awesome](https://awesome.re/badge-flat2.svg)](https://github.com/chartjs/awesome) 4 | 5 | ## Overview 6 | 7 | This adapter allows the use of date-fns with Chart.js. 8 | 9 | Requires [Chart.js](https://github.com/chartjs/Chart.js/releases) **2.8.0** or later and [date-fns](https://date-fns.org/) **2.0.0** or later. 10 | 11 | **Note:** once loaded, this adapter overrides the default date-adapter provided in Chart.js (as a side-effect). 12 | 13 | ## Installation 14 | 15 | ### npm 16 | 17 | ```bash 18 | npm install date-fns chartjs-adapter-date-fns --save 19 | ``` 20 | 21 | ```javascript 22 | import { Chart } from 'chart.js'; 23 | import 'chartjs-adapter-date-fns'; 24 | ``` 25 | 26 | ### CDN 27 | 28 | By default, `https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns` returns the latest (minified) version, however it's [highly recommended](https://www.jsdelivr.com/features) to always specify a version in order to avoid breaking changes. This can be achieved by appending `@{version}` to the url: 29 | 30 | ```html 31 | 32 | 33 | ``` 34 | 35 | Read more about jsDeliver versioning on their [website](http://www.jsdelivr.com/). 36 | 37 | ## Configuration 38 | 39 | ### Locale support via scale options 40 | 41 | date-fns requires a date-fns locale object to be tagged on to each `format()` call, which requires the locale to be explicitly set via the `adapters.date` option: [Chart.js documentation on adapters.date](https://www.chartjs.org/docs/next/axes/cartesian/time#date-adapters) 42 | 43 | For example: 44 | 45 | ```javascript 46 | // import date-fns locale: 47 | import {de} from 'date-fns/locale'; 48 | 49 | 50 | // scale options: 51 | { 52 | adapters: { 53 | date: { 54 | locale: de 55 | } 56 | } 57 | } 58 | ``` 59 | 60 | Further, read the [Chart.js documentation](https://www.chartjs.org/docs/next) for other possible date/time related options. For example, the time scale [`time.*` options](https://www.chartjs.org/docs/next/axes/cartesian/time#configuration-options) can be overridden using the [date-fns tokens](https://date-fns.org/docs/format). 61 | 62 | ## Development 63 | 64 | You first need to install node dependencies (requires [Node.js](https://nodejs.org/)): 65 | 66 | ```bash 67 | > npm install 68 | ``` 69 | 70 | The following commands will then be available from the repository root: 71 | 72 | ```bash 73 | > npm run build // build dist files 74 | > npm run lint // perform code linting 75 | ``` 76 | 77 | ## License 78 | 79 | `chartjs-adapter-date-fns` is available under the [MIT license](LICENSE.md). 80 | -------------------------------------------------------------------------------- /karma.conf.cjs: -------------------------------------------------------------------------------- 1 | const istanbul = require('rollup-plugin-istanbul'); 2 | const resolve = require('@rollup/plugin-node-resolve').default; 3 | const yargs = require('yargs'); 4 | const env = process.env.NODE_ENV; 5 | 6 | module.exports = async function(karma) { 7 | const builds = (await import('./rollup.config.js')).default; 8 | const args = yargs 9 | .option('verbose', {default: false}) 10 | .argv; 11 | 12 | // Use the same rollup config as our dist files: when debugging (npm run dev), 13 | // we will prefer the unminified build which is easier to browse and works 14 | // better with source mapping. In other cases, pick the minified build to 15 | // make sure that the minification process (terser) doesn't break anything. 16 | const regex = karma.autoWatch ? /chartjs-adapter-date-fns\.bundle\.js$/ : /chartjs-adapter-date-fns\.bundle\.min\.js$/; 17 | const build = builds.filter(v => v.output.file && v.output.file.match(regex))[0]; 18 | 19 | if (env === 'test') { 20 | build.plugins = [ 21 | resolve(), 22 | istanbul({exclude: ['node_modules/**/*.js', 'package.json']}) 23 | ]; 24 | } 25 | 26 | karma.set({ 27 | frameworks: ['jasmine'], 28 | reporters: ['progress', 'kjhtml'], 29 | browsers: (args.browsers || 'chrome,firefox').split(','), 30 | logLevel: karma.LOG_INFO, 31 | 32 | client: { 33 | jasmine: { 34 | failFast: !!karma.autoWatch 35 | } 36 | }, 37 | 38 | // Explicitly disable hardware acceleration to make image 39 | // diff more stable when ran on Travis and dev machine. 40 | // https://github.com/chartjs/Chart.js/pull/5629 41 | customLaunchers: { 42 | chrome: { 43 | base: 'Chrome', 44 | flags: [ 45 | '--disable-accelerated-2d-canvas' 46 | ] 47 | }, 48 | firefox: { 49 | base: 'Firefox', 50 | prefs: { 51 | 'layers.acceleration.disabled': true 52 | } 53 | } 54 | }, 55 | 56 | files: [ 57 | {pattern: 'node_modules/chart.js/dist/chart.umd.js'}, 58 | {pattern: 'src/index.js', watched: false}, 59 | {pattern: 'test/index.js'}, 60 | {pattern: 'test/specs/**/**.js'} 61 | ], 62 | 63 | preprocessors: { 64 | 'src/index.js': ['sources'], 65 | 'test/index.js': ['rollup'], 66 | 'test/specs/**/*.js': ['rollup'], 67 | }, 68 | 69 | rollupPreprocessor: { 70 | plugins: [ 71 | resolve(), 72 | ], 73 | output: { 74 | name: 'test', 75 | format: 'umd', 76 | sourcemap: karma.autoWatch ? 'inline' : false 77 | } 78 | }, 79 | 80 | customPreprocessors: { 81 | sources: { 82 | base: 'rollup', 83 | options: build 84 | } 85 | }, 86 | 87 | // These settings deal with browser disconnects. We had seen test flakiness from Firefox 88 | // [Firefox 56.0.0 (Linux 0.0.0)]: Disconnected (1 times), because no message in 10000 ms. 89 | // https://github.com/jasmine/jasmine/issues/1327#issuecomment-332939551 90 | browserDisconnectTolerance: 3 91 | }); 92 | 93 | if (env === 'test') { 94 | karma.reporters.push('coverage'); 95 | karma.coverageReporter = { 96 | dir: 'coverage/', 97 | reporters: [ 98 | {type: 'html', subdir: 'html'}, 99 | {type: 'lcovonly', subdir: (browser) => browser.toLowerCase().split(/[ /-]/)[0]} 100 | ] 101 | }; 102 | } 103 | }; 104 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "chartjs-adapter-date-fns", 3 | "homepage": "https://www.chartjs.org", 4 | "description": "Chart.js adapter to use date-fns for time functionalities", 5 | "version": "3.0.0", 6 | "license": "MIT", 7 | "type": "module", 8 | "main": "dist/chartjs-adapter-date-fns.esm.js", 9 | "jsdelivr": "dist/chartjs-adapter-date-fns.bundle.min.js", 10 | "unpkg": "dist/chartjs-adapter-date-fns.bundle.min.js", 11 | "exports": { 12 | "import": "./dist/chartjs-adapter-date-fns.esm.js", 13 | "require": "./dist/chartjs-adapter-date-fns.min.js" 14 | }, 15 | "repository": { 16 | "type": "git", 17 | "url": "https://github.com/chartjs/chartjs-adapter-date-fns.git" 18 | }, 19 | "scripts": { 20 | "build": "rollup -c", 21 | "dev": "karma start ./karma.conf.cjs --auto-watch --no-single-run --browsers chrome", 22 | "lint": "eslint test/**/*.js src/**/*.js", 23 | "test": "cross-env NODE_ENV=test concurrently \"npm:test-*\"", 24 | "test-lint": "npm run lint", 25 | "test-karma": "karma start ./karma.conf.cjs --auto-watch --single-run" 26 | }, 27 | "keywords": [ 28 | "chart.js", 29 | "date", 30 | "date-fns", 31 | "time" 32 | ], 33 | "files": [ 34 | "dist/*.js" 35 | ], 36 | "devDependencies": { 37 | "@rollup/plugin-node-resolve": "^15.0.1", 38 | "@rollup/plugin-terser": "^0.1.0", 39 | "chart.js": "^4.0.1", 40 | "chartjs-test-utils": "^0.5.0", 41 | "concurrently": "^7.6.0", 42 | "cross-env": "^7.0.3", 43 | "date-fns": "2.19", 44 | "eslint": "^8.29.0", 45 | "eslint-config-chartjs": "^0.3.0", 46 | "eslint-plugin-es": "^4.1.0", 47 | "karma": "^6.1.1", 48 | "karma-chrome-launcher": "^3.1.0", 49 | "karma-coverage": "^2.0.3", 50 | "karma-firefox-launcher": "^2.1.0", 51 | "karma-jasmine": "^5.1.0", 52 | "karma-jasmine-html-reporter": "^2.0.0", 53 | "karma-rollup-preprocessor": "7.0.7", 54 | "rollup": "^3.7.2", 55 | "rollup-plugin-istanbul": "^4.0.0" 56 | }, 57 | "peerDependencies": { 58 | "chart.js": ">=2.8.0", 59 | "date-fns": ">=2.0.0" 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /rollup.config.js: -------------------------------------------------------------------------------- 1 | import resolve from '@rollup/plugin-node-resolve'; 2 | import terser from '@rollup/plugin-terser'; 3 | import {readFileSync} from 'fs'; 4 | 5 | const {name, version, homepage, main, license} = JSON.parse(readFileSync('./package.json')); 6 | 7 | const banner = `/*! 8 | * ${name} v${version} 9 | * ${homepage} 10 | * (c) ${new Date().getFullYear()} chartjs-adapter-date-fns Contributors 11 | * Released under the ${license} license 12 | */`; 13 | 14 | const input = 'src/index.js'; 15 | const external = [ 16 | 'chart.js', 17 | 'date-fns' 18 | ]; 19 | const globals = { 20 | 'chart.js': 'Chart', 21 | 'date-fns': 'dateFns' 22 | }; 23 | 24 | export default [ 25 | { 26 | input, 27 | output: { 28 | file: main, 29 | banner: banner, 30 | format: 'esm', 31 | indent: false, 32 | globals 33 | }, 34 | external 35 | }, 36 | { 37 | input, 38 | output: { 39 | file: main.replace('.esm.js', '.js'), 40 | banner: banner, 41 | format: 'umd', 42 | indent: false, 43 | globals 44 | }, 45 | external 46 | }, 47 | { 48 | input, 49 | output: { 50 | file: main.replace('.esm.js', '.min.js'), 51 | format: 'umd', 52 | indent: false, 53 | globals 54 | }, 55 | plugins: [ 56 | terser({ 57 | output: { 58 | preamble: banner 59 | } 60 | }) 61 | ], 62 | external 63 | }, 64 | { 65 | input, 66 | output: { 67 | file: main.replace('.esm.js', '.bundle.js'), 68 | format: 'umd', 69 | indent: false, 70 | globals: { 71 | 'chart.js': 'Chart' 72 | } 73 | }, 74 | plugins: [ 75 | resolve(), 76 | ], 77 | external: [ 78 | 'chart.js' 79 | ] 80 | }, 81 | { 82 | input, 83 | output: { 84 | file: main.replace('.esm.js', '.bundle.min.js'), 85 | format: 'umd', 86 | indent: false, 87 | globals: { 88 | 'chart.js': 'Chart' 89 | } 90 | }, 91 | plugins: [ 92 | resolve(), 93 | terser({ 94 | output: { 95 | preamble: banner 96 | } 97 | }) 98 | ], 99 | external: [ 100 | 'chart.js' 101 | ] 102 | } 103 | ]; 104 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | import {_adapters} from 'chart.js'; 2 | import { 3 | parse, parseISO, toDate, isValid, format, 4 | startOfSecond, startOfMinute, startOfHour, startOfDay, 5 | startOfWeek, startOfMonth, startOfQuarter, startOfYear, 6 | addMilliseconds, addSeconds, addMinutes, addHours, 7 | addDays, addWeeks, addMonths, addQuarters, addYears, 8 | differenceInMilliseconds, differenceInSeconds, differenceInMinutes, 9 | differenceInHours, differenceInDays, differenceInWeeks, 10 | differenceInMonths, differenceInQuarters, differenceInYears, 11 | endOfSecond, endOfMinute, endOfHour, endOfDay, 12 | endOfWeek, endOfMonth, endOfQuarter, endOfYear 13 | } from 'date-fns'; 14 | 15 | const FORMATS = { 16 | datetime: 'MMM d, yyyy, h:mm:ss aaaa', 17 | millisecond: 'h:mm:ss.SSS aaaa', 18 | second: 'h:mm:ss aaaa', 19 | minute: 'h:mm aaaa', 20 | hour: 'ha', 21 | day: 'MMM d', 22 | week: 'PP', 23 | month: 'MMM yyyy', 24 | quarter: 'qqq - yyyy', 25 | year: 'yyyy' 26 | }; 27 | 28 | _adapters._date.override({ 29 | _id: 'date-fns', // DEBUG 30 | 31 | formats: function() { 32 | return FORMATS; 33 | }, 34 | 35 | parse: function(value, fmt) { 36 | if (value === null || typeof value === 'undefined') { 37 | return null; 38 | } 39 | const type = typeof value; 40 | if (type === 'number' || value instanceof Date) { 41 | value = toDate(value); 42 | } else if (type === 'string') { 43 | if (typeof fmt === 'string') { 44 | value = parse(value, fmt, new Date(), this.options); 45 | } else { 46 | value = parseISO(value, this.options); 47 | } 48 | } 49 | return isValid(value) ? value.getTime() : null; 50 | }, 51 | 52 | format: function(time, fmt) { 53 | return format(time, fmt, this.options); 54 | }, 55 | 56 | add: function(time, amount, unit) { 57 | switch (unit) { 58 | case 'millisecond': return addMilliseconds(time, amount); 59 | case 'second': return addSeconds(time, amount); 60 | case 'minute': return addMinutes(time, amount); 61 | case 'hour': return addHours(time, amount); 62 | case 'day': return addDays(time, amount); 63 | case 'week': return addWeeks(time, amount); 64 | case 'month': return addMonths(time, amount); 65 | case 'quarter': return addQuarters(time, amount); 66 | case 'year': return addYears(time, amount); 67 | default: return time; 68 | } 69 | }, 70 | 71 | diff: function(max, min, unit) { 72 | switch (unit) { 73 | case 'millisecond': return differenceInMilliseconds(max, min); 74 | case 'second': return differenceInSeconds(max, min); 75 | case 'minute': return differenceInMinutes(max, min); 76 | case 'hour': return differenceInHours(max, min); 77 | case 'day': return differenceInDays(max, min); 78 | case 'week': return differenceInWeeks(max, min); 79 | case 'month': return differenceInMonths(max, min); 80 | case 'quarter': return differenceInQuarters(max, min); 81 | case 'year': return differenceInYears(max, min); 82 | default: return 0; 83 | } 84 | }, 85 | 86 | startOf: function(time, unit, weekday) { 87 | switch (unit) { 88 | case 'second': return startOfSecond(time); 89 | case 'minute': return startOfMinute(time); 90 | case 'hour': return startOfHour(time); 91 | case 'day': return startOfDay(time); 92 | case 'week': return startOfWeek(time); 93 | case 'isoWeek': return startOfWeek(time, {weekStartsOn: +weekday}); 94 | case 'month': return startOfMonth(time); 95 | case 'quarter': return startOfQuarter(time); 96 | case 'year': return startOfYear(time); 97 | default: return time; 98 | } 99 | }, 100 | 101 | endOf: function(time, unit) { 102 | switch (unit) { 103 | case 'second': return endOfSecond(time); 104 | case 'minute': return endOfMinute(time); 105 | case 'hour': return endOfHour(time); 106 | case 'day': return endOfDay(time); 107 | case 'week': return endOfWeek(time); 108 | case 'month': return endOfMonth(time); 109 | case 'quarter': return endOfQuarter(time); 110 | case 'year': return endOfYear(time); 111 | default: return time; 112 | } 113 | } 114 | }); 115 | -------------------------------------------------------------------------------- /test/.eslintrc.yml: -------------------------------------------------------------------------------- 1 | env: 2 | jasmine: true 3 | 4 | globals: 5 | acquireChart: true 6 | afterEvent: true 7 | Chart: true 8 | createMockContext: true 9 | __karma__: true 10 | releaseChart: true 11 | waitForResize: true 12 | dateFns: true 13 | -------------------------------------------------------------------------------- /test/index.js: -------------------------------------------------------------------------------- 1 | import {acquireChart, addMatchers, releaseCharts, specsFromFixtures, triggerMouseEvent, afterEvent} from 'chartjs-test-utils'; 2 | 3 | window.devicePixelRatio = 1; 4 | window.acquireChart = acquireChart; 5 | window.afterEvent = afterEvent; 6 | window.triggerMouseEvent = triggerMouseEvent; 7 | 8 | jasmine.fixtures = specsFromFixtures; 9 | 10 | beforeEach(function() { 11 | addMatchers(); 12 | }); 13 | 14 | afterEach(function() { 15 | releaseCharts(); 16 | }); 17 | -------------------------------------------------------------------------------- /test/specs/adapter.spec.js: -------------------------------------------------------------------------------- 1 | describe('date-fns adapter', function() { 2 | it('should format correctly using format presets', function() { 3 | const adapter = new Chart._adapters._date({timeZone: 'UTC'}); 4 | expect(adapter).toBeDefined(); 5 | 6 | const formats = adapter.formats(); 7 | expect(formats).toEqual({ 8 | datetime: 'MMM d, yyyy, h:mm:ss aaaa', 9 | millisecond: 'h:mm:ss.SSS aaaa', 10 | second: 'h:mm:ss aaaa', 11 | minute: 'h:mm aaaa', 12 | hour: 'ha', 13 | day: 'MMM d', 14 | week: 'PP', 15 | month: 'MMM yyyy', 16 | quarter: 'qqq - yyyy', 17 | year: 'yyyy' 18 | }); 19 | 20 | const timestamp = adapter.parse('2019-05-28T15:10:27.000'); 21 | expect(adapter.format(timestamp, formats.year)).toEqual('2019'); 22 | expect(adapter.format(timestamp, formats.quarter)).toEqual('Q2 - 2019'); 23 | expect(adapter.format(timestamp, formats.month)).toEqual('May 2019'); 24 | expect(adapter.format(timestamp, formats.week)).toEqual('May 28, 2019'); 25 | expect(adapter.format(timestamp, formats.day)).toEqual('May 28'); 26 | expect(adapter.format(timestamp, formats.hour)).toEqual('3PM'); 27 | expect(adapter.format(timestamp, formats.minute)).toEqual('3:10 p.m.'); 28 | expect(adapter.format(timestamp, formats.second)).toEqual('3:10:27 p.m.'); 29 | expect(adapter.format(timestamp, formats.millisecond)).toEqual('3:10:27.000 p.m.'); 30 | expect(adapter.format(timestamp, formats.datetime)).toEqual('May 28, 2019, 3:10:27 p.m.'); 31 | }); 32 | }); 33 | --------------------------------------------------------------------------------