From b8f412580ca9942a10ec3055bef3b13af4ec7289 Mon Sep 17 00:00:00 2001 From: iamkun Date: Thu, 28 Feb 2019 16:07:13 +0800 Subject: [PATCH 1/4] utc plugin --- package.json | 2 +- src/index.js | 90 ++++++----- src/plugin/advancedFormat/index.js | 2 +- src/plugin/buddhistEra/index.js | 3 +- src/plugin/customParseFormat/index.js | 27 +++- src/plugin/utc/index.js | 59 +++++++ src/utils.js | 19 +-- test/plugin.test.js | 3 +- test/plugin/utc.test.js | 216 ++++++++++++++++++++++++++ test/utils.test.js | 27 ++-- types/index.d.ts | 4 +- types/plugin/utc.d.ts | 17 ++ 12 files changed, 395 insertions(+), 74 deletions(-) create mode 100644 src/plugin/utc/index.js create mode 100644 test/plugin/utc.test.js create mode 100644 types/plugin/utc.d.ts diff --git a/package.json b/package.json index a8a682645..e601a8911 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "build": "cross-env BABEL_ENV=build node build && npm run size", "sauce": "npx karma start karma.sauce.conf.js", "test:sauce": "npm run sauce -- 0 && npm run sauce -- 1 && npm run sauce -- 2 && npm run sauce -- 3", - "size": "size-limit && gzip-size dayjs.min.js" + "size": "size-limit && gzip-size dayjs.min.js && ls -l dayjs.min.js" }, "pre-commit": [ "lint" diff --git a/src/index.js b/src/index.js index 56ce8d6cb..63fbcacf7 100644 --- a/src/index.js +++ b/src/index.js @@ -38,20 +38,25 @@ const dayjs = (date, c, pl) => { return new Dayjs(cfg) // eslint-disable-line no-use-before-define } -const wrapper = (date, instance) => dayjs(date, { locale: instance.$L }) +const wrapper = (date, instance) => dayjs(date, { locale: instance.$L, utc: instance.$u }) const Utils = U // for plugin use -Utils.parseLocale = parseLocale -Utils.isDayjs = isDayjs -Utils.wrapper = wrapper +Utils.l = parseLocale +Utils.i = isDayjs +Utils.w = wrapper -const parseDate = (date) => { +const parseDate = (cfg) => { + const { date, utc } = cfg if (date === null) return new Date(NaN) // null is invalid - if (Utils.isUndefined(date)) return new Date() // today - if (date instanceof Date) return date + if (Utils.u(date)) return new Date() // today + if (date instanceof Date) return new Date(date) if (typeof date === 'string' && !/Z$/i.test(date)) { const d = date.match(C.REGEX_PARSE) if (d) { + if (utc) { + return new Date(Date.UTC(d[1], d[2] - 1, d[3] + || 1, d[4] || 0, d[5] || 0, d[6] || 0, d[7] || 0)) + } return new Date(d[1], d[2] - 1, d[3] || 1, d[4] || 0, d[5] || 0, d[6] || 0, d[7] || 0) } } @@ -66,7 +71,7 @@ class Dayjs { } parse(cfg) { - this.$d = parseDate(cfg.date) + this.$d = parseDate(cfg) this.init() } @@ -146,21 +151,23 @@ class Dayjs { } startOf(units, startOf) { // startOf -> endOf - const isStartOf = !Utils.isUndefined(startOf) ? startOf : true - const unit = Utils.prettyUnit(units) + const isStartOf = !Utils.u(startOf) ? startOf : true + const unit = Utils.p(units) const instanceFactory = (d, m) => { - const ins = Utils.wrapper(new Date(this.$y, m, d), this) + const ins = Utils.w(this.$u ? + Date.UTC(this.$y, m, d) : new Date(this.$y, m, d), this) return isStartOf ? ins : ins.endOf(C.D) } const instanceFactorySet = (method, slice) => { const argumentStart = [0, 0, 0, 0] const argumentEnd = [23, 59, 59, 999] - return Utils.wrapper(this.toDate()[method].apply( // eslint-disable-line prefer-spread + return Utils.w(this.toDate()[method].apply( // eslint-disable-line prefer-spread this.toDate(), (isStartOf ? argumentStart : argumentEnd).slice(slice) ), this) } const { $W, $M, $D } = this + const utcPad = `set${this.$u ? 'UTC' : ''}` switch (unit) { case C.Y: return isStartOf ? instanceFactory(1, 0) : @@ -175,13 +182,13 @@ class Dayjs { } case C.D: case C.DATE: - return instanceFactorySet('setHours', 0) + return instanceFactorySet(`${utcPad}Hours`, 0) case C.H: - return instanceFactorySet('setMinutes', 1) + return instanceFactorySet(`${utcPad}Minutes`, 1) case C.MIN: - return instanceFactorySet('setSeconds', 2) + return instanceFactorySet(`${utcPad}Seconds`, 2) case C.S: - return instanceFactorySet('setMilliseconds', 3) + return instanceFactorySet(`${utcPad}Milliseconds`, 3) default: return this.clone() } @@ -192,16 +199,17 @@ class Dayjs { } $set(units, int) { // private set - const unit = Utils.prettyUnit(units) + const unit = Utils.p(units) + const utcPad = `set${this.$u ? 'UTC' : ''}` const name = { - [C.D]: 'setDate', - [C.DATE]: 'setDate', - [C.M]: 'setMonth', - [C.Y]: 'setFullYear', - [C.H]: 'setHours', - [C.MIN]: 'setMinutes', - [C.S]: 'setSeconds', - [C.MS]: 'setMilliseconds' + [C.D]: `${utcPad}Date`, + [C.DATE]: `${utcPad}Date`, + [C.M]: `${utcPad}Month`, + [C.Y]: `${utcPad}FullYear`, + [C.H]: `${utcPad}Hours`, + [C.MIN]: `${utcPad}Minutes`, // India GMT+5:30 + [C.S]: `${utcPad}Seconds`, + [C.MS]: `${utcPad}Milliseconds` }[unit] const arg = unit === C.D ? this.$D + (int - this.$W) : int @@ -217,7 +225,7 @@ class Dayjs { add(number, units) { number = Number(number) // eslint-disable-line no-param-reassign - const unit = Utils.prettyUnit(units) + const unit = Utils.p(units) const instanceFactory = (u, n) => { const date = this.set(C.DATE, 1).set(u, n + number) return date.set(C.DATE, Math.min(this.$D, date.daysInMonth())) @@ -225,7 +233,7 @@ class Dayjs { const instanceFactorySet = (n) => { const date = new Date(this.$d) date.setDate(date.getDate() + (n * number)) - return Utils.wrapper(date, this) + return Utils.w(date, this) } if (unit === C.M) { return instanceFactory(C.M, this.$M) @@ -246,7 +254,7 @@ class Dayjs { }[unit] || 1 // ms const nextTimeStamp = this.valueOf() + (number * step) - return Utils.wrapper(nextTimeStamp, this) + return Utils.w(nextTimeStamp, this) } subtract(number, string) { @@ -257,7 +265,7 @@ class Dayjs { if (!this.isValid()) return C.INVALID_DATE_STRING const str = formatStr || C.FORMAT_DEFAULT - const zoneStr = Utils.padZoneStr(this.$d.getTimezoneOffset()) + const zoneStr = Utils.z(this) const locale = this.$locale() const { weekdays, months @@ -266,34 +274,34 @@ class Dayjs { (arr && arr[index]) || full[index].substr(0, length) ) const get$H = num => ( - Utils.padStart(this.$H % 12 || 12, num, '0') + Utils.s(this.$H % 12 || 12, num, '0') ) const matches = { YY: String(this.$y).slice(-2), YYYY: String(this.$y), M: String(this.$M + 1), - MM: Utils.padStart(this.$M + 1, 2, '0'), + MM: Utils.s(this.$M + 1, 2, '0'), MMM: getShort(locale.monthsShort, this.$M, months, 3), MMMM: months[this.$M], D: String(this.$D), - DD: Utils.padStart(this.$D, 2, '0'), + DD: Utils.s(this.$D, 2, '0'), d: String(this.$W), dd: getShort(locale.weekdaysMin, this.$W, weekdays, 2), ddd: getShort(locale.weekdaysShort, this.$W, weekdays, 3), dddd: weekdays[this.$W], H: String(this.$H), - HH: Utils.padStart(this.$H, 2, '0'), + HH: Utils.s(this.$H, 2, '0'), h: get$H(1), hh: get$H(2), a: this.$H < 12 ? 'am' : 'pm', A: this.$H < 12 ? 'AM' : 'PM', m: String(this.$m), - mm: Utils.padStart(this.$m, 2, '0'), + mm: Utils.s(this.$m, 2, '0'), s: String(this.$s), - ss: Utils.padStart(this.$s, 2, '0'), - SSS: Utils.padStart(this.$ms, 3, '0'), - Z: zoneStr + ss: Utils.s(this.$s, 2, '0'), + SSS: Utils.s(this.$ms, 3, '0'), + Z: zoneStr // 'ZZ' logic below } return str.replace(C.REGEX_FORMAT, (match) => { @@ -309,11 +317,11 @@ class Dayjs { } diff(input, units, float) { - const unit = Utils.prettyUnit(units) + const unit = Utils.p(units) const that = dayjs(input) const zoneDelta = (that.utcOffset() - this.utcOffset()) * C.MILLISECONDS_A_MINUTE const diff = this - that - let result = Utils.monthDiff(this, that) + let result = Utils.m(this, that) result = { [C.Y]: result / 12, @@ -326,7 +334,7 @@ class Dayjs { [C.S]: diff / C.MILLISECONDS_A_SECOND }[unit] || diff // milliseconds - return float ? result : Utils.absFloor(result) + return float ? result : Utils.a(result) } daysInMonth() { @@ -344,7 +352,7 @@ class Dayjs { } clone() { - return Utils.wrapper(this.toDate(), this) + return Utils.w(this.toDate(), this) } toDate() { diff --git a/src/plugin/advancedFormat/index.js b/src/plugin/advancedFormat/index.js index 1557c76af..854f2b73b 100644 --- a/src/plugin/advancedFormat/index.js +++ b/src/plugin/advancedFormat/index.js @@ -22,7 +22,7 @@ export default (o, c, d) => { // locale needed later } case 'k': case 'kk': - return utils.padStart(String(this.$H === 0 ? 24 : this.$H), match === 'k' ? 1 : 2, '0') + return utils.s(String(this.$H === 0 ? 24 : this.$H), match === 'k' ? 1 : 2, '0') case 'X': return Math.floor(this.$d.getTime() / 1000) default: // 'x' diff --git a/src/plugin/buddhistEra/index.js b/src/plugin/buddhistEra/index.js index e7f3feaa4..3ee0dd520 100644 --- a/src/plugin/buddhistEra/index.js +++ b/src/plugin/buddhistEra/index.js @@ -6,12 +6,11 @@ export default (o, c) => { // locale needed later // extend en locale here proto.format = function (formatStr) { const yearBias = 543 - const { padStart } = this.$utils() const str = formatStr || FORMAT_DEFAULT const result = str.replace(/BBBB|BB/g, (match) => { const year = String(this.$y + yearBias) const args = match === 'BB' ? [year.slice(-2), 2] : [year, 4] - return padStart(...args, '0') + return this.$utils().s(...args, '0') }) return oldFormat.bind(this)(result) } diff --git a/src/plugin/customParseFormat/index.js b/src/plugin/customParseFormat/index.js index 3755b34c8..10273e11f 100644 --- a/src/plugin/customParseFormat/index.js +++ b/src/plugin/customParseFormat/index.js @@ -135,7 +135,7 @@ function makeParser(format) { } } -const parseFormattedInput = (input, format) => { +const parseFormattedInput = (input, format, utc) => { try { const parser = makeParser(format) const { @@ -149,10 +149,17 @@ const parseFormattedInput = (input, format) => { ) + (zone.offset * 60 * 1000)) } const now = new Date() - return new Date( - year || now.getFullYear(), month > 0 ? month - 1 : now.getMonth(), day || now.getDate(), - hours || 0, minutes || 0, seconds || 0, milliseconds || 0 - ) + const y = year || now.getFullYear() + const M = month > 0 ? month - 1 : now.getMonth() + const d = day || now.getDate() + const h = hours || 0 + const m = minutes || 0 + const s = seconds || 0 + const ms = milliseconds || 0 + if (utc) { + return new Date(Date.UTC(y, M, d, h, m, s, ms)) + } + return new Date(y, M, d, h, m, s, ms) } catch (e) { return new Date('') // Invalid Date } @@ -163,10 +170,16 @@ export default (o, C, d) => { const proto = C.prototype const oldParse = proto.parse proto.parse = function (cfg) { - const { date: input, format, pl } = cfg + const { + date: input, + format, + pl, + utc + } = cfg + this.$u = utc if (format) { locale = pl ? d.Ls[pl] : this.$locale() - this.$d = parseFormattedInput(input, format) + this.$d = parseFormattedInput(input, format, utc) this.init(cfg) } else { oldParse.call(this, cfg) diff --git a/src/plugin/utc/index.js b/src/plugin/utc/index.js new file mode 100644 index 000000000..d367c97be --- /dev/null +++ b/src/plugin/utc/index.js @@ -0,0 +1,59 @@ +export default (option, Dayjs, dayjs) => { + const proto = Dayjs.prototype + dayjs.utc = function (date, format) { + const cfg = { date, utc: true, format } + return new Dayjs(cfg) // eslint-disable-line no-use-before-define + } + + proto.utc = function () { + return dayjs(this.toDate(), { locale: this.$L, utc: true }) + } + + proto.local = function () { + return dayjs(this.toDate(), { locale: this.$L, utc: false }) + } + + const oldParse = proto.parse + proto.parse = function (cfg) { + if (cfg.utc) { + this.$u = true + } + oldParse.call(this, cfg) + } + + const oldInit = proto.init + proto.init = function () { + if (this.$u) { + const { $d } = this + this.$y = $d.getUTCFullYear() + this.$M = $d.getUTCMonth() + this.$D = $d.getUTCDate() + this.$W = $d.getUTCDay() + this.$H = $d.getUTCHours() + this.$m = $d.getUTCMinutes() + this.$s = $d.getUTCSeconds() + this.$ms = $d.getUTCMilliseconds() + } else { + oldInit.call(this) + } + } + + const oldUtcOffset = proto.utcOffset + proto.utcOffset = function () { + if (this.$u) { + return 0 + } + return oldUtcOffset.call(this) + } + + const oldFormat = proto.format + const UTC_FORMAT_DEFAULT = 'YYYY-MM-DDTHH:mm:ss[Z]' + proto.format = function (formatStr) { + const str = formatStr || (this.$u ? UTC_FORMAT_DEFAULT : '') + return oldFormat.call(this, str) + } + + proto.isUTC = function () { + return !!this.$u + } +} diff --git a/src/utils.js b/src/utils.js index 4b06043b0..cd98b07cd 100644 --- a/src/utils.js +++ b/src/utils.js @@ -6,7 +6,8 @@ const padStart = (string, length, pad) => { return `${Array((length + 1) - s.length).join(pad)}${string}` } -const padZoneStr = (negMinuts) => { +const padZoneStr = (instance) => { + const negMinuts = -instance.utcOffset() const minutes = Math.abs(negMinuts) const hourOffset = Math.floor(minutes / 60) const minuteOffset = minutes % 60 @@ -16,9 +17,9 @@ const padZoneStr = (negMinuts) => { const monthDiff = (a, b) => { // function from moment.js in order to keep the same result const wholeMonthDiff = ((b.year() - a.year()) * 12) + (b.month() - a.month()) - const anchor = a.clone().add(wholeMonthDiff, 'months') + const anchor = a.clone().add(wholeMonthDiff, C.M) const c = b - anchor < 0 - const anchor2 = a.clone().add(wholeMonthDiff + (c ? -1 : 1), 'months') + const anchor2 = a.clone().add(wholeMonthDiff + (c ? -1 : 1), C.M) return Number(-(wholeMonthDiff + ((b - anchor) / (c ? (anchor - anchor2) : (anchor2 - anchor)))) || 0) } @@ -42,10 +43,10 @@ const prettyUnit = (u) => { const isUndefined = s => s === undefined export default { - padStart, - padZoneStr, - monthDiff, - absFloor, - prettyUnit, - isUndefined + s: padStart, + z: padZoneStr, + m: monthDiff, + a: absFloor, + p: prettyUnit, + u: isUndefined } diff --git a/test/plugin.test.js b/test/plugin.test.js index b223863e0..6e56470c7 100644 --- a/test/plugin.test.js +++ b/test/plugin.test.js @@ -30,5 +30,6 @@ it('Plugin extend dayjs', () => { }) it('Plugin use core utils', () => { - expect(dayjs().$utils().isUndefined).toBeInstanceOf(Function) + // u => isUndefined + expect(dayjs().$utils().u).toBeInstanceOf(Function) }) diff --git a/test/plugin/utc.test.js b/test/plugin/utc.test.js new file mode 100644 index 000000000..9a90adca4 --- /dev/null +++ b/test/plugin/utc.test.js @@ -0,0 +1,216 @@ +import MockDate from 'mockdate' +import moment from 'moment' +import dayjs from '../../src' +import utc from '../../src/plugin/utc' +import customParseFormat from '../../src/plugin/customParseFormat' + +dayjs.extend(utc) + +beforeEach(() => { + MockDate.set(new Date()) +}) + +afterEach(() => { + MockDate.reset() +}) + +describe('UTC Get', () => { + it('UTC Year', () => { + expect(dayjs().utc().year()).toBe(moment().utc().year()) + }) + + it('UTC Month', () => { + expect(dayjs().utc().month()).toBe(moment().utc().month()) + }) + + it('UTC Day of Week', () => { + expect(dayjs().utc().day()).toBe(moment().utc().day()) + }) + + it('UTC Date', () => { + expect(dayjs().utc().date()).toBe(moment().utc().date()) + }) + + it('UTC Hour', () => { + expect(dayjs().utc().hour()).toBe(moment().utc().hour()) + }) + + it('UTC Minute', () => { + expect(dayjs().utc().minute()).toBe(moment().utc().minute()) + }) + + it('UTC Second', () => { + expect(dayjs().utc().second()).toBe(moment().utc().second()) + }) + + it('UTC Millisecond', () => { + expect(dayjs().utc().millisecond()).toBe(moment().utc().millisecond()) + }) +}) + +describe('Parse UTC ', () => { + it('Parse Now', () => { + expect(dayjs.utc().format()).toBe(moment.utc().format()) + expect(dayjs().utc().format()).toBe(moment().utc().format()) + }) + + it('Parse date string without timezome', () => { + const d = '2018-09-06' + const d2 = '2018-09' + expect(dayjs.utc(d).format()).toEqual(moment.utc(d).format()) + expect(dayjs.utc(d).format()).toEqual('2018-09-06T00:00:00Z') + expect(dayjs.utc(d2).format()).toEqual(moment.utc(d2).format()) + expect(dayjs.utc(d2).format()).toEqual('2018-09-01T00:00:00Z') + expect(dayjs(d).utc().format()).toEqual(moment(d).utc().format()) + }) + + it('creating with utc with timezone', () => { + const d = '2011-02-02T03:04:05+00:00' + expect(dayjs.utc(d).format()).toEqual(moment.utc(d).format()) + const d2 = '2012-01-02T08:20:00+09:00' + expect(dayjs.utc(d2).format()).toEqual(moment.utc(d2).format()) + }) + + it('Parse date string without timezome', () => { + 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()) + expect(dayjs(d).utc().format()).toBe(moment(d).utc().format()) + const d2 = '2012-01-02T08:20:00' + expect(dayjs.utc(d2).format()).toEqual(moment.utc(d2).format()) + }) + + it('Parse date string set utc in config', () => { + const d = '2018-09-06T19:34:28Z' + expect(dayjs(d, { utc: true }).format()).toEqual('2018-09-06T19:34:28Z') + expect(dayjs(d, { utc: true }).format()).toEqual(moment(d).utc().format()) + expect(dayjs(d).utc().format()).toEqual('2018-09-06T19:34:28Z') + expect(dayjs(d).utc().format()).toEqual(moment(d).utc().format()) + expect(dayjs.utc(d).format()).toEqual('2018-09-06T19:34:28Z') + expect(dayjs.utc(d).format()).toEqual(moment.utc(d).format()) + }) +}) + +it('Clone retains the UTC mode', () => { + const instance = dayjs('2018-09-06').utc() + const another = instance.clone() + expect(another.$u).toBeTruthy() +}) + +it('UTC mode format tokens', () => { + const d = '2018-09-06T19:34:28.657Z' + const instance = dayjs(d).utc() + const format = 'HH-hh-mm-ss-SSS-Z-ZZ' + expect(instance.format(format)).toBe('19-07-34-28-657-+00:00-+0000') + expect(instance.format(format)).toBe(moment.utc(d).format(format)) +}) + +describe('local', () => { + it('Returns a new instance', () => { + const instance = dayjs.utc('2018-09-06T19:34:28.657Z') + const local = instance.local() + expect(local).not.toBe(instance) + }) + + it('UTC to local', () => { + const d = '2018-09-06' + expect(dayjs.utc(d).local().format()).toEqual(moment.utc(d).local().format()) + }) +}) + +it('StartOf EndOf Year ... in UTC mode', () => { + const testArr = ['year', 'month', 'day', 'date', 'week', 'hour', 'minute', 'second'] + testArr.forEach((d) => { + expect(dayjs().utc().startOf(d).format()).toBe(moment().utc().startOf(d).format()) + expect(dayjs().utc().endOf(d).format()).toBe(moment().utc().endOf(d).format()) + }) +}) + +describe('UTC Set', () => { + it('Set UTC Day', () => { + expect(dayjs().utc().set('date', 30).valueOf()).toBe(moment().utc().set('date', 30).valueOf()) + }) + + it('Set UTC Day of Week', () => { + expect(dayjs().utc().set('day', 0).valueOf()).toBe(moment().utc().set('day', 0).valueOf()) + }) + + it('Set UTC Month', () => { + expect(dayjs().utc().set('month', 11).valueOf()).toBe(moment().utc().set('month', 11).valueOf()) + }) + + it('Set UTC Year', () => { + expect(dayjs().utc().set('year', 2008).valueOf()).toBe(moment().utc().set('year', 2008).valueOf()) + }) + + it('Set UTC Hour', () => { + expect(dayjs().utc().set('hour', 6).valueOf()).toBe(moment().utc().set('hour', 6).valueOf()) + }) + + it('Set UTC Minute', () => { + expect(dayjs().utc().set('minute', 59).valueOf()).toBe(moment().utc().set('minute', 59).valueOf()) + }) + + it('Set UTC Second', () => { + expect(dayjs().utc().set('second', 59).valueOf()).toBe(moment().utc().set('second', 59).valueOf()) + }) + + it('Set UTC Millisecond', () => { + expect(dayjs().utc().set('millisecond', 999).valueOf()).toBe(moment().utc().set('millisecond', 999).valueOf()) + }) +}) + +it('isUTC', () => { + expect(dayjs().isUTC()).toBe(false) + expect(dayjs().utc().isUTC()).toBe(true) + expect(dayjs.utc().isUTC()).toBe(true) +}) + +describe('UTC and local', () => { + const localDay = dayjs(Date.UTC(2011, 1, 2, 3, 4, 5, 6)) + const utcDay = localDay.utc() + + it('utc', () => { + expect(utcDay.date()).toBe(2) + expect(utcDay.day()).toBe(3) + expect(utcDay.hour()).toBe(3) + }) + + const localAnainDay = utcDay.local() + it('local', () => { + if (localAnainDay.utcOffset() < -180) { + expect(localAnainDay.date()).toBe(1) + expect(localAnainDay.day()).toBe(2) + } else { + expect(localAnainDay.date()).toBe(2) + expect(localAnainDay.day()).toBe(3) + } + }) + + const offset = Math.floor(localAnainDay.utcOffset() / 60) + const expected = (24 + 3 + offset) % 24 + it('utcOffset', () => { + expect(localAnainDay.hour()).toBe(expected) + expect(dayjs().utc().utcOffset()).toBe(0) + }) +}) + + +describe('UTC with customParseFormat', () => { + it('Custom Parse Format', () => { + dayjs.extend(customParseFormat) + const instant = dayjs.utc('2011-02-02 03:04:05', 'YYYY-MM-DD HH:mm:ss') + const momentInstant = moment.utc('2011-02-02 03:04:05', 'YYYY-MM-DD HH:mm:ss') + expect(instant.date()).toBe(2) + expect(instant.hour()).toBe(3) + expect(instant.format()).toBe('2011-02-02T03:04:05Z') + expect(instant.format()).toBe(momentInstant.format()) + }) +}) + +describe('UTC Offset', () => { + it('get utcOffset', () => { + expect(dayjs().utcOffset()).toBe(moment().utcOffset()) + expect(dayjs().utc().utcOffset()).toBe(moment().utc().utcOffset()) + }) +}) diff --git a/test/utils.test.js b/test/utils.test.js index 5a4dbaa50..5c07f7796 100644 --- a/test/utils.test.js +++ b/test/utils.test.js @@ -1,10 +1,8 @@ import Utils from '../src/utils' -const { - prettyUnit, - padZoneStr, - padStart -} = Utils +const prettyUnit = Utils.p +const padStart = Utils.s +const padZoneStr = Utils.z it('PrettyUnit', () => { expect(prettyUnit('Days')).toBe('day') @@ -14,12 +12,19 @@ it('PrettyUnit', () => { }) it('PadZoneStr', () => { - expect(padZoneStr(0)).toBe('+00:00') - expect(padZoneStr(1 * 60)).toBe('-01:00') - expect(padZoneStr(-1 * 60)).toBe('+01:00') - expect(padZoneStr(-10 * 60)).toBe('+10:00') - expect(padZoneStr(10 * 60)).toBe('-10:00') - expect(padZoneStr((-5 * 60) - 30)).toBe('+05:30') + const instance = {} + instance.utcOffset = () => 0 * -1 + expect(padZoneStr(instance)).toBe('+00:00') + instance.utcOffset = () => 1 * 60 * -1 + expect(padZoneStr(instance)).toBe('-01:00') + instance.utcOffset = () => -1 * 60 * -1 + expect(padZoneStr(instance)).toBe('+01:00') + instance.utcOffset = () => -10 * 60 * -1 + expect(padZoneStr(instance)).toBe('+10:00') + instance.utcOffset = () => 10 * 60 * -1 + expect(padZoneStr(instance)).toBe('-10:00') + instance.utcOffset = () => ((-5 * 60) - 30) * -1 + expect(padZoneStr(instance)).toBe('+05:30') }) it('PadStart', () => { diff --git a/types/index.d.ts b/types/index.d.ts index c1db5910f..22ea11726 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -4,7 +4,7 @@ declare function dayjs (date?: dayjs.ConfigType, option?: dayjs.OptionType, loca declare namespace dayjs { export type ConfigType = string | number | Date | Dayjs - export type OptionType = { locale?: string, format?: string } | string + export type OptionType = { locale?: string, format?: string, utc?: boolean } | string type UnitTypeShort = 'd' | 'M' | 'y' | 'h' | 'm' | 's' | 'ms' export type UnitType = 'millisecond' | 'second' | 'minute' | 'hour' | 'day' | 'month' | 'quarter' | 'year' | 'date' | UnitTypeShort; @@ -77,6 +77,8 @@ declare namespace dayjs { toString(): string + utcOffset(): number + isBefore(date: ConfigType, unit?: OpUnitType): boolean isSame(date: ConfigType, unit?: OpUnitType): boolean diff --git a/types/plugin/utc.d.ts b/types/plugin/utc.d.ts new file mode 100644 index 000000000..2f14efb22 --- /dev/null +++ b/types/plugin/utc.d.ts @@ -0,0 +1,17 @@ +import { PluginFunc, ConfigType } from 'dayjs' + +declare const plugin: PluginFunc +export = plugin + +declare module 'dayjs' { + interface Dayjs { + + utc(): Dayjs + + local(): Dayjs + + isUTC(): boolean + } + + export function utc(config?: ConfigType, format?: string): Dayjs +} From e953a1a2cdab2805975dceb5564a6826c67980c7 Mon Sep 17 00:00:00 2001 From: iamkun Date: Wed, 6 Mar 2019 16:15:49 +0800 Subject: [PATCH 2/4] rm size ls --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e601a8911..a8a682645 100644 --- a/package.json +++ b/package.json @@ -14,7 +14,7 @@ "build": "cross-env BABEL_ENV=build node build && npm run size", "sauce": "npx karma start karma.sauce.conf.js", "test:sauce": "npm run sauce -- 0 && npm run sauce -- 1 && npm run sauce -- 2 && npm run sauce -- 3", - "size": "size-limit && gzip-size dayjs.min.js && ls -l dayjs.min.js" + "size": "size-limit && gzip-size dayjs.min.js" }, "pre-commit": [ "lint" From 738fa7e494f9453805c4a5c657e8e2fa001f2f1f Mon Sep 17 00:00:00 2001 From: iamkun Date: Wed, 6 Mar 2019 16:16:23 +0800 Subject: [PATCH 3/4] rm comment --- src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index 63fbcacf7..4f96f9c91 100644 --- a/src/index.js +++ b/src/index.js @@ -207,7 +207,7 @@ class Dayjs { [C.M]: `${utcPad}Month`, [C.Y]: `${utcPad}FullYear`, [C.H]: `${utcPad}Hours`, - [C.MIN]: `${utcPad}Minutes`, // India GMT+5:30 + [C.MIN]: `${utcPad}Minutes`, [C.S]: `${utcPad}Seconds`, [C.MS]: `${utcPad}Milliseconds` }[unit] From cd9be33117c0682ec0c8cef41c513bbc26fe09e8 Mon Sep 17 00:00:00 2001 From: iamkun Date: Wed, 6 Mar 2019 16:22:21 +0800 Subject: [PATCH 4/4] refactor --- src/plugin/customParseFormat/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/plugin/customParseFormat/index.js b/src/plugin/customParseFormat/index.js index 10273e11f..ee7bd5cfb 100644 --- a/src/plugin/customParseFormat/index.js +++ b/src/plugin/customParseFormat/index.js @@ -171,7 +171,7 @@ export default (o, C, d) => { const oldParse = proto.parse proto.parse = function (cfg) { const { - date: input, + date, format, pl, utc @@ -179,7 +179,7 @@ export default (o, C, d) => { this.$u = utc if (format) { locale = pl ? d.Ls[pl] : this.$locale() - this.$d = parseFormattedInput(input, format, utc) + this.$d = parseFormattedInput(date, format, utc) this.init(cfg) } else { oldParse.call(this, cfg)