diff --git a/src/constant.js b/src/constant.js index 6cab7bee5..a4f034fa2 100644 --- a/src/constant.js +++ b/src/constant.js @@ -26,5 +26,5 @@ export const FORMAT_DEFAULT = 'YYYY-MM-DDTHH:mm:ssZ' export const INVALID_DATE_STRING = 'Invalid Date' // regex -export const REGEX_PARSE = /^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[^0-9]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?.?(\d{1,3})?$/ +export const REGEX_PARSE = /^(\d{4})[-/]?(\d{1,2})?[-/]?(\d{0,2})[^0-9]*(\d{1,2})?:?(\d{1,2})?:?(\d{1,2})?.?(\d+)?$/ export const REGEX_FORMAT = /\[([^\]]+)]|Y{2,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g diff --git a/src/index.js b/src/index.js index f8517ac38..af7aae3a4 100644 --- a/src/index.js +++ b/src/index.js @@ -60,12 +60,13 @@ const parseDate = (cfg) => { const d = date.match(C.REGEX_PARSE) if (d) { const m = d[2] - 1 || 0 + const ms = (d[7] || '0').substring(0, 3) if (utc) { return new Date(Date.UTC(d[1], m, d[3] - || 1, d[4] || 0, d[5] || 0, d[6] || 0, d[7] || 0)) + || 1, d[4] || 0, d[5] || 0, d[6] || 0, ms)) } return new Date(d[1], m, d[3] - || 1, d[4] || 0, d[5] || 0, d[6] || 0, d[7] || 0) + || 1, d[4] || 0, d[5] || 0, d[6] || 0, ms) } } diff --git a/src/plugin/duration/index.js b/src/plugin/duration/index.js index 31ab68572..dad125f11 100644 --- a/src/plugin/duration/index.js +++ b/src/plugin/duration/index.js @@ -28,7 +28,7 @@ const prettyUnit = unit => `${$u.p(unit)}s` class Duration { constructor(input, unit, locale) { this.$d = {} - this.$l = locale || 'en' + this.$l = locale if (unit) { return wrapper(input * unitToMS[prettyUnit(unit)], this) } @@ -172,7 +172,8 @@ export default (option, Dayjs, dayjs) => { $d = dayjs $u = dayjs().$utils() dayjs.duration = function (input, unit) { - return wrapper(input, {}, unit) + const $l = dayjs.locale() + return wrapper(input, { $l }, unit) } dayjs.isDuration = isDuration } diff --git a/src/plugin/timezone/index.js b/src/plugin/timezone/index.js index b9703b2de..0c248c607 100644 --- a/src/plugin/timezone/index.js +++ b/src/plugin/timezone/index.js @@ -7,6 +7,8 @@ const typeToPos = { second: 5 } +const ms = 'ms' + export default (o, c, d) => { const localUtcOffset = d().utcOffset() const tzOffset = (timestamp, timezone) => { @@ -55,7 +57,7 @@ export default (o, c, d) => { proto.tz = function (timezone) { const target = this.toDate().toLocaleString('en-US', { timeZone: timezone }) const diff = Math.round((this.toDate() - new Date(target)) / 1000 / 60) - return d(target).utcOffset(localUtcOffset - diff, true) + return d(target).utcOffset(localUtcOffset - diff, true).$set(ms, this.$ms) } d.tz = function (input, timezone) { const previousOffset = tzOffset(+d(), timezone) diff --git a/test/parse.test.js b/test/parse.test.js index 6302d8942..aecbaa898 100644 --- a/test/parse.test.js +++ b/test/parse.test.js @@ -81,6 +81,14 @@ describe('Parse', () => { expect(normalized.toISOString()).toEqual(expected) }) + it('parses unlimited millisecond', () => { + const date = '2019-03-25T06:41:00.999999999' + const ds = dayjs(date) + const ms = moment(date) + expect(ds.valueOf()).toEqual(ms.valueOf()) + expect(ds.millisecond()).toEqual(ms.millisecond()) + }) + it('String Other, Null and isValid', () => { global.console.warn = jest.genMockFunction()// moment.js otherString will throw warn expect(dayjs('otherString').toString().toLowerCase()).toBe(moment('otherString').toString().toLowerCase()) @@ -134,4 +142,10 @@ describe('REGEX_PARSE', () => { expect(dayjs(date).valueOf()).toBe(moment(date).valueOf()) expect(d.join('-')).toBe('2020/9/30-2020-9-30----') }) + it('2019-03-25T06:41:00.999999999', () => { + const date = '2019-03-25T06:41:00.999999999' + const d = date.match(REGEX_PARSE) + expect(dayjs(date).valueOf()).toBe(moment(date).valueOf()) + expect(d.join('-')).toBe('2019-03-25T06:41:00.999999999-2019-03-25-06-41-00-999999999') + }) }) diff --git a/test/plugin/duration.test.js b/test/plugin/duration.test.js index d2e4abe6c..d153da43a 100644 --- a/test/plugin/duration.test.js +++ b/test/plugin/duration.test.js @@ -101,6 +101,15 @@ describe('Humanize', () => { expect(dayjs.duration(1, 'minutes').locale('fr').humanize(true)).toBe('dans une minute') expect(dayjs.duration(1, 'minutes').locale('es').humanize(true)).toBe('en un minuto') }) + it('Global Locale', () => { + dayjs.locale('en') + expect(dayjs.duration(1, 'minutes').humanize(true)).toBe('in a minute') + dayjs.locale('fr') + expect(dayjs.duration(1, 'minutes').humanize(true)).toBe('dans une minute') + dayjs.locale('es') + expect(dayjs.duration(1, 'minutes').humanize(true)).toBe('en un minuto') + dayjs.locale('en') + }) }) describe('Clone', () => { diff --git a/test/plugin/timezone.test.js b/test/plugin/timezone.test.js index 21bb08f9d..ca807aa4f 100644 --- a/test/plugin/timezone.test.js +++ b/test/plugin/timezone.test.js @@ -56,6 +56,14 @@ describe('Parse', () => { expect(newYork.tz('America/Los_Angeles').format()).toBe('2014-06-01T09:00:00-07:00') expect(newYork.tz('Europe/London').format()).toBe('2014-06-01T17:00:00+01:00') }) + + it('preserve milliseconds', () => { + const d = dayjs(1596735327399) + const oldMs = d.millisecond() + const dTz = d.tz('America/New_York') + const newMs = dTz.millisecond() + expect(oldMs).toEqual(newMs) + }) }) describe('Convert', () => { diff --git a/test/plugin/utc.test.js b/test/plugin/utc.test.js index d8fd7da27..a02e8c143 100644 --- a/test/plugin/utc.test.js +++ b/test/plugin/utc.test.js @@ -54,7 +54,7 @@ describe('Parse UTC ', () => { expect(dayjs().utc().format()).toBe(moment().utc().format()) }) - it('Parse date string without timezome', () => { + it('Parse date string without timezone', () => { const d = '2018-09-06' expect(dayjs.utc(d).format()).toEqual(moment.utc(d).format()) expect(dayjs.utc(d).format()).toEqual('2018-09-06T00:00:00Z') @@ -76,7 +76,7 @@ describe('Parse UTC ', () => { expect(dayjs.utc(d2).format()).toEqual(moment.utc(d2).format()) }) - it('Parse date string without timezome', () => { + it('Parse date string without timezone', () => { const d = '2017-04-22 19:50:16' expect(dayjs.utc(d).format()).toEqual('2017-04-22T19:50:16Z') expect(dayjs.utc(d).format()).toEqual(moment.utc(d).format()) @@ -94,6 +94,14 @@ describe('Parse UTC ', () => { expect(dayjs.utc(d).format()).toEqual('2018-09-06T19:34:28Z') expect(dayjs.utc(d).format()).toEqual(moment.utc(d).format()) }) + + it('parses unlimited millisecond in utc', () => { + const date = '2019-03-25T06:41:00.999999999' + const ds = dayjs.utc(date) + const ms = moment.utc(date) + expect(ds.valueOf()).toEqual(ms.valueOf()) + expect(ds.millisecond()).toEqual(ms.millisecond()) + }) }) it('Clone retains the UTC mode', () => {