diff --git a/.babelrc b/babel.config.js similarity index 87% rename from .babelrc rename to babel.config.js index 6ae4011d2..a0291dac6 100644 --- a/.babelrc +++ b/babel.config.js @@ -1,20 +1,20 @@ -{ - "env": { - "test": { - "presets": [ - "@babel/preset-env" - ] - }, - "build": { - "presets": [ - [ - "@babel/preset-env", - { - "modules": false, - "loose": true - } - ] - ] - } - } -} +module.exports = { + "env": { + "test": { + "presets": [ + "@babel/preset-env" + ] + }, + "build": { + "presets": [ + [ + "@babel/preset-env", + { + "modules": false, + "loose": true + } + ] + ] + } + } +}; \ No newline at end of file diff --git a/docs/en/Plugin.md b/docs/en/Plugin.md index 7df564c7e..ea00de436 100644 --- a/docs/en/Plugin.md +++ b/docs/en/Plugin.md @@ -260,6 +260,9 @@ dayjs.extend(customParseFormat) dayjs('05/02/69 1:02:03 PM -05:00', 'MM/DD/YY H:mm:ss A Z') // Returns an instance containing '1969-05-02T18:02:03.000Z' + +dayjs('2018 Enero 15', { format: 'YYYY MMMM DD', locale: es }) +// Returns an instance containing '2018-01-15T00:00:00.000Z' ``` #### List of all available format tokens diff --git a/docs/es-es/Plugin.md b/docs/es-es/Plugin.md index aede05fd1..5668155b9 100644 --- a/docs/es-es/Plugin.md +++ b/docs/es-es/Plugin.md @@ -247,6 +247,23 @@ dayjs.extend(quarterOfYear) dayjs('2010-04-01').quarter() // 2 ``` +### CustomParseFormat + - CustomParseFormat extends `dayjs()` constructor to support custom formats of input strings. + +To escape characters, wrap them in square brackets (e.g. `[G]`). Punctuation symbols (-:/.()) do not need to be wrapped. + +```javascript +import customParseFormat from 'dayjs/plugin/customParseFormat' + +dayjs.extend(customParseFormat) + +dayjs('05/02/69 1:02:03 PM -05:00', 'MM/DD/YY H:mm:ss A Z') +// Returns an instance containing '1969-05-02T18:02:03.000Z' + +dayjs('2018 Enero 15', { format: 'YYYY MMMM DD', locale: es }) +// Returns an instance containing '2018-01-15T00:00:00.000Z' +``` + #### List of all available format tokens | Format | Output | Description | diff --git a/docs/ja/Plugin.md b/docs/ja/Plugin.md index 4be8f2e4f..981a29e27 100644 --- a/docs/ja/Plugin.md +++ b/docs/ja/Plugin.md @@ -269,6 +269,9 @@ dayjs.extend(customParseFormat) dayjs('05/02/69 1:02:03 PM -05:00', 'MM/DD/YY H:mm:ss A Z') // Returns an instance containing '1969-05-02T18:02:03.000Z' + +dayjs('2018 5月 15', { format: 'YYYY MMMM DD', locale: ja }) +// Returns an instance containing '2018-05-15T00:00:00.000Z' ``` #### List of all available format tokens diff --git a/docs/ko/Plugin.md b/docs/ko/Plugin.md index cd96ff2d8..e203c811c 100644 --- a/docs/ko/Plugin.md +++ b/docs/ko/Plugin.md @@ -261,6 +261,9 @@ dayjs.extend(customParseFormat) dayjs('05/02/69 1:02:03 PM -05:00', 'MM/DD/YY H:mm:ss A Z') // Returns an instance containing '1969-05-02T18:02:03.000Z' + +dayjs('2018 5월 15', { format: 'YYYY MMMM DD', locale: ko }) +// Returns an instance containing '2018-05-15T00:00:00.000Z' ``` #### List of all available format tokens diff --git a/docs/pt-br/Plugin.md b/docs/pt-br/Plugin.md index 0d6000488..04581f34c 100644 --- a/docs/pt-br/Plugin.md +++ b/docs/pt-br/Plugin.md @@ -260,6 +260,9 @@ dayjs.extend(customParseFormat) dayjs('05/02/69 1:02:03 PM -05:00', 'MM/DD/YY H:mm:ss A Z') // Returns an instance containing '1969-05-02T18:02:03.000Z' + +dayjs('2018 Fevereiro 15', { format: 'YYYY MMMM DD', locale: pt_br }) +// Returns an instance containing '2018-02-15T00:00:00.000Z' ``` #### List of all available format tokens diff --git a/docs/zh-cn/Plugin.md b/docs/zh-cn/Plugin.md index 3ce2cd1c2..02938ab3e 100644 --- a/docs/zh-cn/Plugin.md +++ b/docs/zh-cn/Plugin.md @@ -260,6 +260,9 @@ dayjs.extend(customParseFormat) dayjs('05/02/69 1:02:03 PM -05:00', 'MM/DD/YY H:mm:ss A Z') // Returns an instance containing '1969-05-02T18:02:03.000Z' + +dayjs('2018 五月 15', { format: 'YYYY MMMM DD', locale: zh_cn }) +// Returns an instance containing '2018-05-15T00:00:00.000Z' ``` #### List of all available format tokens diff --git a/src/index.js b/src/index.js index 2e2cdbdbc..e33a80a05 100644 --- a/src/index.js +++ b/src/index.js @@ -61,15 +61,16 @@ const parseDate = (date) => { class Dayjs { constructor(cfg) { + this.$L = this.$L || parseLocale(cfg.locale, null, true) || L this.parse(cfg) // for plugin } parse(cfg) { this.$d = parseDate(cfg.date) - this.init(cfg) + this.init() } - init(cfg) { + init() { const { $d } = this this.$y = $d.getFullYear() this.$M = $d.getMonth() @@ -79,7 +80,6 @@ class Dayjs { this.$m = $d.getMinutes() this.$s = $d.getSeconds() this.$ms = $d.getMilliseconds() - this.$L = this.$L || parseLocale(cfg.locale, null, true) || L } // eslint-disable-next-line class-methods-use-this diff --git a/src/plugin/customParseFormat/index.js b/src/plugin/customParseFormat/index.js index ad639beb1..0d8e0acb0 100644 --- a/src/plugin/customParseFormat/index.js +++ b/src/plugin/customParseFormat/index.js @@ -1,4 +1,4 @@ -const formattingTokens = /(\[[^[]*\])|([-:/.()\s]+)|(A|a|YYYY|YY?|MM?|DD?|hh?|HH?|mm?|ss?|S{1,3}|z|ZZ?)/g +const formattingTokens = /(\[[^[]*\])|([-:/.()\s]+)|(A|a|YYYY|YY?|MM?M?M?|DD?|hh?|HH?|mm?|ss?|S{1,3}|z|ZZ?)/g const match1 = /\d/ // 0 - 9 const match2 = /\d\d/ // 00 - 99 @@ -9,6 +9,9 @@ const matchUpperCaseAMPM = /[AP]M/ const matchLowerCaseAMPM = /[ap]m/ const matchSigned = /[+-]?\d+/ // -inf - inf const matchOffset = /[+-]\d\d:?\d\d/ // +00:00 -00:00 +0000 or -0000 +const matchWord = /\d*[^\s\d]+/ // Word + +let locale function offsetFromString(string) { const parts = string.match(/([+-]|\d\d)/g) @@ -55,6 +58,24 @@ const expressions = { DD: [match2, addInput('day')], M: [match1to2, addInput('month')], MM: [match2, addInput('month')], + MMM: [matchWord, function (input) { + const { months, monthsShort } = locale + const matchIndex = monthsShort + ? monthsShort.findIndex(month => month === input) + : months.findIndex(month => month.substr(0, 3) === input) + if (matchIndex < 0) { + throw new Error() + } + this.month = matchIndex + 1 + }], + MMMM: [matchWord, function (input) { + const { months } = locale + const matchIndex = months.indexOf(input) + if (matchIndex < 0) { + throw new Error() + } + this.month = matchIndex + 1 + }], Y: [matchSigned, addInput('year')], YY: [match2, function (input) { input = +input @@ -144,6 +165,7 @@ export default (o, C) => { proto.parse = function (cfg) { const { date: input, format } = cfg if (format) { + locale = this.$locale() this.$d = parseFormattedInput(input, format) this.init(cfg) } else { diff --git a/test/plugin/customParseFormat.test.js b/test/plugin/customParseFormat.test.js index e26cbea30..b278462f9 100644 --- a/test/plugin/customParseFormat.test.js +++ b/test/plugin/customParseFormat.test.js @@ -2,6 +2,7 @@ import MockDate from 'mockdate' import moment from 'moment' import dayjs from '../../src' import customParseFormat from '../../src/plugin/customParseFormat' +import uk from '../../src/locale/uk' dayjs.extend(customParseFormat) @@ -84,3 +85,56 @@ it('fails with an invalid format', () => { expect(dayjs(input, format).format().toLowerCase()) .toBe(moment(input, format).format().toLowerCase()) }) + +it('parse month from string', () => { + const input = '2018 February 03' + const format = 'YYYY MMMM DD' + expect(dayjs(input, format).valueOf()).toBe(moment(input, format).valueOf()) +}) + +it('parse month from short string', () => { + const input = '2018 Feb 03' + const format = 'YYYY MMM DD' + expect(dayjs(input, format).valueOf()).toBe(moment(input, format).valueOf()) +}) + +it('parse month from string with locale in config', () => { + const input = '2018 лютий 03' + const format = 'YYYY MMMM DD' + + expect(dayjs(input, { format, locale: uk }).valueOf()).toBe(moment(input, format, 'uk').valueOf()) +}) + +it('parse month from short string with locale in config', () => { + const input = '2018 трав 03' + const format = 'YYYY MMM DD' + expect(dayjs(input, { format, locale: uk }).valueOf()).toBe(moment(input, format, 'uk').valueOf()) +}) + +it('return Invalid Date when parse corrupt string', () => { + const input = '2018 Turnip 03' + const format = 'YYYY MMMM DD' + expect(dayjs(input, format).format()).toBe('Invalid Date') +}) + +it('return Invalid Date when parse corrupt short string', () => { + const input = '2018 Dog 03' + const format = 'YYYY MMM DD' + expect(dayjs(input, format).format()).toBe('Invalid Date') +}) + +it('correctly parse month from string after changing locale globally', () => { + const input = '2018 лютий 03' + const format = 'YYYY MMMM DD' + + const dayjsLocale = dayjs().$locale() + const momentLocale = moment.locale() + try { + dayjs.locale(uk) + moment.locale('uk') + expect(dayjs(input, format).valueOf()).toBe(moment(input, format).valueOf()) + } finally { + dayjs.locale(dayjsLocale) + moment.locale(momentLocale) + } +})