diff --git a/src/plugin/objectSupport/index.js b/src/plugin/objectSupport/index.js index 4344dc402..650166606 100644 --- a/src/plugin/objectSupport/index.js +++ b/src/plugin/objectSupport/index.js @@ -1,6 +1,7 @@ export default (o, c, dayjs) => { const proto = c.prototype - const isObject = obj => !(obj instanceof Date) && !(obj instanceof Array) && obj instanceof Object + const isObject = obj => !(obj instanceof Date) && !(obj instanceof Array) + && !proto.$utils().u(obj) && (obj.constructor.name === 'Object') const prettyUnit = (u) => { const unit = proto.$utils().p(u) return unit === 'date' ? 'day' : unit @@ -39,29 +40,36 @@ export default (o, c, dayjs) => { const oldSet = proto.set const oldAdd = proto.add + const oldSubtract = proto.subtract const callObject = function (call, argument, string, offset = 1) { - if (argument instanceof Object) { - const keys = Object.keys(argument) - let chain = this - keys.forEach((key) => { - chain = call.bind(chain)(argument[key] * offset, key) - }) - return chain - } - return call.bind(this)(argument * offset, string) + const keys = Object.keys(argument) + let chain = this + keys.forEach((key) => { + chain = call.bind(chain)(argument[key] * offset, key) + }) + return chain } - proto.set = function (string, int) { - int = int === undefined ? string : int - return callObject.bind(this)(function (i, s) { - return oldSet.bind(this)(s, i) - }, int, string) + proto.set = function (unit, value) { + value = value === undefined ? unit : value + if (unit.constructor.name === 'Object') { + return callObject.bind(this)(function (i, s) { + return oldSet.bind(this)(s, i) + }, value, unit) + } + return oldSet.bind(this)(unit, value) } - proto.add = function (number, string) { - return callObject.bind(this)(oldAdd, number, string) + proto.add = function (value, unit) { + if (value.constructor.name === 'Object') { + return callObject.bind(this)(oldAdd, value, unit) + } + return oldAdd.bind(this)(value, unit) } - proto.subtract = function (number, string) { - return callObject.bind(this)(oldAdd, number, string, -1) + proto.subtract = function (value, unit) { + if (value.constructor.name === 'Object') { + return callObject.bind(this)(oldAdd, value, unit, -1) + } + return oldSubtract.bind(this)(value, unit) } } diff --git a/test/issues/issue2027.correct-order.test.js b/test/issues/issue2027.correct-order.test.js new file mode 100644 index 000000000..3d9d6300c --- /dev/null +++ b/test/issues/issue2027.correct-order.test.js @@ -0,0 +1,78 @@ +import MockDate from 'mockdate' +import dayjs from '../../src' +import duration from '../../src/plugin/duration' +import objectSupport from '../../src/plugin/objectSupport' + +dayjs.extend(objectSupport) +dayjs.extend(duration) + +beforeEach(() => { + MockDate.set(new Date()) +}) + +afterEach(() => { + MockDate.reset() +}) + +// issue 2027 +describe('issue 2027 - order objectSupport > Duration', () => { + it('add Duration object returns correct date', () => { + const baseDate = dayjs('2022-06-26T14:01:02.003') + const durationToAdd = dayjs.duration(6, 'hours') + const testDate = baseDate.add(durationToAdd) + + expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 20:01:02.003') + }) + it('subtract Duration object returns correct date', () => { + const baseDate = dayjs('2022-06-26T14:01:02.003') + const durationToAdd = dayjs.duration(6, 'hours') + const testDate = baseDate.subtract(durationToAdd) + + expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 08:01:02.003') + }) + + it('add number with unit returns correct date', () => { + const baseDate = dayjs('2022-06-26T14:01:02.003') + const testDate = baseDate.add(6, 'hours') + + expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 20:01:02.003') + }) + it('subtract number with unit returns correct date', () => { + const baseDate = dayjs('2022-06-26T14:01:02.003') + const testDate = baseDate.subtract(6, 'hours') + + expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 08:01:02.003') + }) + + it('parse string returns correct date', () => { + const testDate = dayjs('2022-06-26T14:01:02.003') + + expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 14:01:02.003') + }) + it('parse object returns correct date', () => { + const testDate = dayjs({ + year: '2022', + month: '05', + day: '26', + hour: '14', + minute: '01', + second: '02', + millisecond: '003' + }) + + expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 14:01:02.003') + }) + + it('set hour with number returns correct date', () => { + const baseDate = dayjs('2022-06-26T14:01:02.003') + const testDate = baseDate.hour(10) + + expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 10:01:02.003') + }) + it('set hour with object returns correct date', () => { + const baseDate = dayjs('2022-06-26T14:01:02.003') + const testDate = baseDate.set({ hour: '10' }) + + expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 10:01:02.003') + }) +}) diff --git a/test/issues/issue2027.swapped-order.test.js b/test/issues/issue2027.swapped-order.test.js new file mode 100644 index 000000000..62a969e49 --- /dev/null +++ b/test/issues/issue2027.swapped-order.test.js @@ -0,0 +1,79 @@ +import MockDate from 'mockdate' +import dayjs from '../../src' +import duration from '../../src/plugin/duration' +import objectSupport from '../../src/plugin/objectSupport' + +dayjs.extend(duration) +dayjs.extend(objectSupport) + +beforeEach(() => { + MockDate.set(new Date()) +}) + +afterEach(() => { + MockDate.reset() +}) + +// issue 2027 +describe('issue 2027 - order objectSupport > Duration', () => { + it('add Duration object returns correct date', () => { + const baseDate = dayjs('2022-06-26T14:01:02.003') + const durationToAdd = dayjs.duration(6, 'hours') + const testDate = baseDate.add(durationToAdd) + + expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 20:01:02.003') + }) + + it('subtract Duration object returns correct date', () => { + const baseDate = dayjs('2022-06-26T14:01:02.003') + const durationToAdd = dayjs.duration(6, 'hours') + const testDate = baseDate.subtract(durationToAdd) + + expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 08:01:02.003') + }) + + it('add number with unit returns correct date', () => { + const baseDate = dayjs('2022-06-26T14:01:02.003') + const testDate = baseDate.add(6, 'hours') + + expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 20:01:02.003') + }) + it('subtract number with unit returns correct date', () => { + const baseDate = dayjs('2022-06-26T14:01:02.003') + const testDate = baseDate.subtract(6, 'hours') + + expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 08:01:02.003') + }) + + it('parse string returns correct date', () => { + const testDate = dayjs('2022-06-26T14:01:02.003') + + expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 14:01:02.003') + }) + it('parse object returns correct date', () => { + const testDate = dayjs({ + year: '2022', + month: '05', + day: '26', + hour: '14', + minute: '01', + second: '02', + millisecond: '003' + }) + + expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 14:01:02.003') + }) + + it('set hour with number returns correct date', () => { + const baseDate = dayjs('2022-06-26T14:01:02.003') + const testDate = baseDate.hour(10) + + expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 10:01:02.003') + }) + it('set hour with object returns correct date', () => { + const baseDate = dayjs('2022-06-26T14:01:02.003') + const testDate = baseDate.set({ hour: '10' }) + + expect(testDate.format('YYYY-MM-DD HH:mm:ss.SSS')).toBe('2022-06-26 10:01:02.003') + }) +})