Abstraction over common javascript date management libraries
Installations
npm install @date-io/dayjs
Developer
dmtrKovalenko
Developer Guide
Module System
CommonJS
Min. Node Version
Typescript Support
No
Node Version
19.9.0
NPM Version
lerna/3.22.1/node@v19.9.0+arm64 (darwin)
Statistics
727 Stars
708 Commits
90 Forks
3 Watching
35 Branches
45 Contributors
Updated on 26 Nov 2024
Languages
TypeScript (97.07%)
JavaScript (2.93%)
Total Downloads
Cumulative downloads
Total Downloads
127,528,110
Last day
-4.1%
133,041
Compared to previous day
Last week
1.1%
678,850
Compared to previous week
Last month
8.9%
2,894,239
Compared to previous month
Last year
-26.9%
37,071,653
Compared to previous year
Daily Downloads
Weekly Downloads
Monthly Downloads
Yearly Downloads
date-io
Abstraction over common JavaScript date management libraries.
The project exposes an abstraction interface over luxon, date-fns v3, dayjs and moment. It allows you to build any UI date or time components while utilizing the same date management library in use within your user's project.
It simplifies timezone management, allows your code to return the exact same type that your user expects and works with specific calendar systems (e.g. Jalali calendar)
Projects
Library | Downloads |
---|---|
@date-io/date-fns | |
@date-io/moment | |
@date-io/luxon | |
@date-io/dayjs | |
@date-io/js-joda | |
@date-io/date-fns-jalali | |
@date-io/jalaali | |
@date-io/hijri |
Usage example
1import LuxonAdapter from "@date-io/luxon"; 2import DateFnsAdapter from "@date-io/date-fns"; 3 4const dateFns = new DateFnsAdapter(); 5const luxon = new LuxonAdapter({ locale: "fr" }); // pass french locale 6 7const initialLuxonDate = luxon.date("2018-10-28T11:44:00.000Z"); 8const initialDateFnsDate = dateFns.date("2018-10-28T11:44:00.000Z"); 9 10const updatedLuxonDate = luxon.addDays(initialLuxonDate, 2); 11const updatedDateFnsDate = dateFns.addDays(initialDateFnsDate, 2); 12 13luxon.format(updatedLuxonDate, "fullDateTime24h"); // "2018, octobre 30 11:44" 14dateFns.format(updatedLuxonDate, "fullDateTime24h"); // "2018, October 30th 11:44"
Interface
The implemented interface. If you cannot find the method you require, please let us know, and we will add it!
Localized output will of course vary based on the locale and date library used. Inline examples here are based on using
moment
with the en-US
locale.
1export interface DateIOFormats<TLibFormatToken = string> {
2 /** Localized full date @example "Jan 1, 2019" */
3 fullDate: TLibFormatToken;
4 /** Partially localized full date with weekday, useful for text-to-speech accessibility @example "Tuesday, January 1, 2019" */
5 fullDateWithWeekday: TLibFormatToken;
6 /** Date format string with month and day of month @example "1 January" */
7 normalDate: TLibFormatToken;
8 /** Date format string with weekday, month and day of month @example "Wed, Jan 1" */
9 normalDateWithWeekday: TLibFormatToken;
10 /** Shorter day format @example "Jan 1" */
11 shortDate: TLibFormatToken;
12 /** Year format string @example "2019" */
13 year: TLibFormatToken;
14 /** Month format string @example "January" */
15 month: TLibFormatToken;
16 /** Short month format string @example "Jan" */
17 monthShort: TLibFormatToken;
18 /** Month with year format string @example "January 2018" */
19 monthAndYear: TLibFormatToken;
20 /** Month with date format string @example "January 1" */
21 monthAndDate: TLibFormatToken;
22 /** Weekday format string @example "Wednesday" */
23 weekday: TLibFormatToken;
24 /** Short weekday format string @example "Wed" */
25 weekdayShort: TLibFormatToken;
26 /** Day format string @example "1" */
27 dayOfMonth: TLibFormatToken;
28 /** Hours format string @example "11" */
29 hours12h: TLibFormatToken;
30 /** Hours format string @example "23" */
31 hours24h: TLibFormatToken;
32 /** Minutes format string @example "44" */
33 minutes: TLibFormatToken;
34 /** Seconds format string @example "00" */
35 seconds: TLibFormatToken;
36 /** Full time localized format string @example "11:44 PM" for US, "23:44" for Europe */
37 fullTime: TLibFormatToken;
38 /** Not localized full time format string @example "11:44 PM" */
39 fullTime12h: TLibFormatToken;
40 /** Not localized full time format string @example "23:44" */
41 fullTime24h: TLibFormatToken;
42 /** Date & time format string with localized time @example "Jan 1, 2018 11:44 PM" */
43 fullDateTime: TLibFormatToken;
44 /** Not localized date & Time format 12h @example "Jan 1, 2018 11:44 PM" */
45 fullDateTime12h: TLibFormatToken;
46 /** Not localized date & Time format 24h @example "Jan 1, 2018 23:44" */
47 fullDateTime24h: TLibFormatToken;
48 /** Localized keyboard input friendly date format @example "02/13/2020 */
49 keyboardDate: TLibFormatToken;
50 /** Localized keyboard input friendly date/time format @example "02/13/2020 23:44" */
51 keyboardDateTime: TLibFormatToken;
52 /** Partially localized keyboard input friendly date/time 12h format @example "02/13/2020 11:44 PM" */
53 keyboardDateTime12h: TLibFormatToken;
54 /** Partially localized keyboard input friendly date/time 24h format @example "02/13/2020 23:44" */
55 keyboardDateTime24h: TLibFormatToken;
56}
57
58export type Unit =
59 | "years"
60 | "quarters"
61 | "months"
62 | "weeks"
63 | "days"
64 | "hours"
65 | "minutes"
66 | "seconds"
67 | "milliseconds";
68
69export interface IUtils<TDate> {
70 formats: DateIOFormats<any>;
71 locale?: any;
72 moment?: any;
73 dayjs?: any;
74 /** Name of the library that is used right now */
75 lib: string;
76
77 // constructor (options?: { formats?: DateIOFormats, locale?: any, instance?: any });
78
79 date(value?: any): TDate | null;
80 toJsDate(value: TDate): Date;
81 parseISO(isString: string): TDate;
82 toISO(value: TDate): string;
83 parse(value: string, format: string): TDate | null;
84
85 getCurrentLocaleCode(): string;
86 is12HourCycleInCurrentLocale(): boolean;
87 /** Returns user readable format (taking into account localized format tokens), useful to render helper text for input (e.g. placeholder). For luxon always returns empty string. */
88 getFormatHelperText(format: string): string;
89
90 isNull(value: TDate | null): boolean;
91 isValid(value: any): boolean;
92 getDiff(value: TDate, comparing: TDate | string, unit?: Unit): number;
93 isEqual(value: any, comparing: any): boolean;
94
95 isSameDay(value: TDate, comparing: TDate): boolean;
96 isSameMonth(value: TDate, comparing: TDate): boolean;
97 isSameYear(value: TDate, comparing: TDate): boolean;
98 isSameHour(value: TDate, comparing: TDate): boolean;
99
100 isAfter(value: TDate, comparing: TDate): boolean;
101 isAfterDay(value: TDate, comparing: TDate): boolean;
102 isAfterYear(value: TDate, comparing: TDate): boolean;
103
104 isBeforeDay(value: TDate, comparing: TDate): boolean;
105 isBeforeYear(value: TDate, comparing: TDate): boolean;
106 isBefore(value: TDate, comparing: TDate): boolean;
107
108 isWithinRange(value: TDate, range: [TDate, TDate]): boolean;
109
110 startOfYear(value: TDate): TDate;
111 endOfYear(value: TDate): TDate;
112 startOfMonth(value: TDate): TDate;
113 endOfMonth(value: TDate): TDate;
114 startOfWeek(value: TDate): TDate;
115 endOfWeek(value: TDate): TDate;
116
117 addSeconds(value: TDate, count: number): TDate;
118 addMinutes(value: TDate, count: number): TDate;
119 addHours(value: TDate, count: number): TDate;
120 addDays(value: TDate, count: number): TDate;
121 addWeeks(value: TDate, count: number): TDate;
122 addMonths(value: TDate, count: number): TDate;
123 addYears(value: TDate, count: number): TDate;
124
125 startOfDay(value: TDate): TDate;
126 endOfDay(value: TDate): TDate;
127
128 format(value: TDate, formatKey: keyof DateIOFormats): string;
129 formatByString(value: TDate, formatString: string): string;
130 formatNumber(numberToFormat: string): string;
131
132 getHours(value: TDate): number;
133 setHours(value: TDate, count: number): TDate;
134
135 getMinutes(value: TDate): number;
136 setMinutes(value: TDate, count: number): TDate;
137
138 getSeconds(value: TDate): number;
139 setSeconds(value: TDate, count: number): TDate;
140
141 getDate(value: TDate): number;
142 setDate(value: TDate, count: number): TDate;
143
144 getMonth(value: TDate): number;
145 getDaysInMonth(value: TDate): number;
146 setMonth(value: TDate, count: number): TDate;
147 getNextMonth(value: TDate): TDate;
148 getPreviousMonth(value: TDate): TDate;
149
150 getMonthArray(value: TDate): TDate[];
151
152 getYear(value: TDate): number;
153 setYear(value: TDate, count: number): TDate;
154
155 mergeDateAndTime(date: TDate, time: TDate): TDate;
156
157 getWeekdays(): string[];
158 getWeekArray(date: TDate): TDate[][];
159 getYearRange(start: TDate, end: TDate): TDate[];
160
161 /** Allow to customize displaying "am/pm" strings */
162 getMeridiemText(ampm: "am" | "pm"): string;
163}
For library authors
If you are a library author that exposes date/time management utils or controls you may want to use date-io to interop with the most popular libraries. Here are some instructions on how to use date-fns as an adapter.
1. Install the bindings
First of all, it is required to provide the adapters for your users. We do not recommend installing the date-io directly by the end users, cause it may be easy to mismatch the version. The better way will be to reexport them.
Firstly install all the adapters you want to support and lock the version.
Yes, you will install all of them as dependencies. But every adapter is 50kb unpacked npm module and relieas to the library as for optional peer dependency. It won't be included in user bundle until user will choose which library he want's to use.
1{ 2 "dependencies": { 3 "@date-io/date-fns": "x.x.x", 4 "@date-io/dayjs": "x.x.x", 5 "@date-io/luxon": "x.x.x", 6 "@date-io/date-fns-jalali": "x.x.x", 7 "@date-io/jalaali": "x.x.x" 8 } 9}
2. Reexport the bindings
1// you-awesome-lib/adapters/date-fns 2export { default } from "@date-io/date-fns";
3. Use it for date-time management
Register it using your library context. It may be react context, dependency injection container or any other tool that allows the user to register the used library 1 time.
1// react example 2import { createMyAdapter } from "your-awesome-lib/adapters/date-fns"; 3 4<DateLibProvider adapter={createMyAdapter({ locale: "fr" })}> 5 {/* ... */} 6</DateLibProvider>;
And use the interface of date-io (or your custom interface).
1import { IUtils } from "@date-io/core/IUtils"; 2 3function myFunctionInLibrary<TDate>(date: TDate, adapter: IUtils<TDate>) { 4 // ... 5 const weekArray = adapter.getWeekArray(Date); 6 // ... 7}
Overriding behavior
It is possible to change or extend the behavior of any adapter by simply inheriting and overriding the base class of utils while saving the same interface.
Let's say you want to override getYear
to always return 2007 and getWeekdays
to contain only 2 weekends (let's admit that this is what we all desire) you can do the following:
1class CustomDateTime extends DayjsUtils implements IUtils<Dayjs> { 2 getWeekdays = () => { 3 const start = this.dayjs().startOf("week"); 4 return [0, 1].map((diff) => this.formatByString(start.add(diff, "day"), "dd")); 5 }; 6}
Note: that you will need to do this with every adapter you want to support to be in sync.
Extending behavior
It is possible also to add custom functionality to the adapter, in case the author of date-io doesn't want to add it. To do this create your custom interface that extends IUtils and inherit your adapters both from the base adapter and your custom interface.
1// your-awesome-lib/adapters/CustomAdapter 2import { IUtils } from "@date-io/core/IUtils"; 3import DateIODateFnsAdapter from "@date-io/date-fns"; 4 5interface CustomUtils<TDate> extends IUtils<TDate> { 6 getDayOfYear(day: TDate): number; 7} 8 9interface CustomDateFnsUtils extends DateIODateFnsAdapter implements CustomUtils<Date> { 10 getDayOfYear(day: Date): number { 11 return getDayOfYear(day); 12 } 13}
Build system
In some build systems (hello babel) it may be impossible to extend the methods because they are defined as class properties. While it should be standardized already there are still some issues with it. In this case you can use the following workaround:
1// you-awesome-lib/adapters/date-fns 2import { CustomUtils } from "../CustomUtils"; 3import getDayOfYear from "date-fns/getDayOfYear"; 4import DateIODateFnsAdapter from "@date-io/date-fns"; 5 6export const createMyAdapter(options) { 7 const dateFns = new DateFnsUtils(options) 8 9 const adapter = { 10 ...dateFns, 11 12 getWeekArray() { 13 const startDate = endOfWeek(adapter.endOfMonth(date), { locale: adapter.locale }) 14 const extraWeek = adapter.getWeekdays().map((day, index) => adapter.addDays(startDate, index + 1)) 15 return [...dateFns.getWeekArray(date), extraWeek] 16 }, 17 18 // ... 19 } 20 21 return adapter 22}
No vulnerabilities found.
Reason
no dangerous workflow patterns detected
Reason
no binaries found in the repo
Reason
license file detected
Details
- Info: project has a license file: LICENSE:0
- Info: FSF or OSI recognized license: MIT License: LICENSE:0
Reason
Found 13/29 approved changesets -- score normalized to 4
Reason
0 commit(s) and 1 issue activity found in the last 90 days -- score normalized to 0
Reason
detected GitHub workflow tokens with excessive permissions
Details
- Warn: no topLevel permission defined: .github/workflows/build.yml:1
- Info: no jobLevel write permissions found
Reason
dependency not pinned by hash detected -- score normalized to 0
Details
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:10: update your workflow using https://app.stepsecurity.io/secureworkflow/dmtrKovalenko/date-io/build.yml/master?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:11: update your workflow using https://app.stepsecurity.io/secureworkflow/dmtrKovalenko/date-io/build.yml/master?enable=pin
- Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/build.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/dmtrKovalenko/date-io/build.yml/master?enable=pin
- Info: 0 out of 3 GitHub-owned GitHubAction dependencies pinned
Reason
no effort to earn an OpenSSF best practices badge detected
Reason
security policy file not detected
Details
- Warn: no security policy file detected
- Warn: no security file to analyze
- Warn: no security file to analyze
- Warn: no security file to analyze
Reason
project is not fuzzed
Details
- Warn: no fuzzer integrations found
Reason
branch protection not enabled on development/release branches
Details
- Warn: branch protection not enabled for branch 'master'
Reason
SAST tool is not run on all commits -- score normalized to 0
Details
- Warn: 0 commits out of 21 are checked with a SAST tool
Reason
44 existing vulnerabilities detected
Details
- Warn: Project is vulnerable to: GHSA-67hx-6x53-jw92
- Warn: Project is vulnerable to: GHSA-v88g-cgmw-v5xw
- Warn: Project is vulnerable to: GHSA-93q8-gq69-wqmw
- Warn: Project is vulnerable to: GHSA-wf5p-g6vw-rhxx
- Warn: Project is vulnerable to: GHSA-grv7-fg5c-xmjg
- Warn: Project is vulnerable to: GHSA-3xgq-45jj-v275
- Warn: Project is vulnerable to: GHSA-gxpj-cx7g-858c
- Warn: Project is vulnerable to: GHSA-w573-4hg7-7wgq
- Warn: Project is vulnerable to: GHSA-ff7x-qrg7-qggm
- Warn: Project is vulnerable to: GHSA-jchw-25xp-jwwc
- Warn: Project is vulnerable to: GHSA-cxjh-pqwp-8mfp
- Warn: Project is vulnerable to: GHSA-ww39-953v-wcq6
- Warn: Project is vulnerable to: GHSA-43f8-2h32-f4cj
- Warn: Project is vulnerable to: GHSA-rc47-6667-2j5j
- Warn: Project is vulnerable to: GHSA-78xj-cgh5-2h22
- Warn: Project is vulnerable to: GHSA-2p57-rm9w-gvfp
- Warn: Project is vulnerable to: GHSA-6c8f-qphg-qjgp
- Warn: Project is vulnerable to: GHSA-p6mc-m468-83gw
- Warn: Project is vulnerable to: GHSA-35jh-r3h4-6jhm
- Warn: Project is vulnerable to: GHSA-952p-6rrq-rcjv
- Warn: Project is vulnerable to: GHSA-f8q6-p94x-37v3
- Warn: Project is vulnerable to: GHSA-xvch-5gv4-984h
- Warn: Project is vulnerable to: GHSA-56x4-j7p9-fcf9
- Warn: Project is vulnerable to: GHSA-v78c-4p63-2j6c
- Warn: Project is vulnerable to: GHSA-r683-j2x4-v87g
- Warn: Project is vulnerable to: GHSA-3j8f-xvm3-ffx4
- Warn: Project is vulnerable to: GHSA-4p35-cfcx-8653
- Warn: Project is vulnerable to: GHSA-7f3x-x4pr-wqhj
- Warn: Project is vulnerable to: GHSA-jpp7-7chh-cf67
- Warn: Project is vulnerable to: GHSA-q6wq-5p59-983w
- Warn: Project is vulnerable to: GHSA-j9fq-vwqv-2fm2
- Warn: Project is vulnerable to: GHSA-pqw5-jmp5-px4v
- Warn: Project is vulnerable to: GHSA-hj48-42vr-x3v9
- Warn: Project is vulnerable to: GHSA-hrpp-h998-j3pp
- Warn: Project is vulnerable to: GHSA-p8p7-x288-28g6
- Warn: Project is vulnerable to: GHSA-gcx4-mw62-g8wm
- Warn: Project is vulnerable to: GHSA-c2qf-rxjj-qqgw
- Warn: Project is vulnerable to: GHSA-f5x3-32g6-xq36
- Warn: Project is vulnerable to: GHSA-29xr-v42j-r956
- Warn: Project is vulnerable to: GHSA-72xf-g2v4-qvf3
- Warn: Project is vulnerable to: GHSA-7p7h-4mm5-852v
- Warn: Project is vulnerable to: GHSA-38fc-wpqx-33j7
- Warn: Project is vulnerable to: GHSA-c4w7-xm78-47vh
- Warn: Project is vulnerable to: GHSA-p9pc-299p-vxgp
Score
2.9
/10
Last Scanned on 2024-11-25
The Open Source Security Foundation is a cross-industry collaboration to improve the security of open source software (OSS). The Scorecard provides security health metrics for open source projects.
Learn MoreOther packages similar to @date-io/dayjs
dayjs
2KB immutable date time library alternative to Moment.js with the same modern API
@date-io/core
Abstraction over common javascript date management libraries
@mui/x-date-pickers
The community edition of the Date and Time Picker components (MUI X).
@date-io/date-fns
Abstraction over common javascript date management libraries