Repository: iamkun/dayjs
Pull request #2088 (2022-10-21 00:36:54)

D2M


Patch:
diff --git a/src/locale/en.js b/src/locale/en.js
index 71c2f22..2913d57 100644
--- a/src/locale/en.js
+++ b/src/locale/en.js
@@ -3,5 +3,10 @@
 export default {
   name: 'en',
   weekdays: 'Sunday_Monday_Tuesday_Wednesday_Thursday_Friday_Saturday'.split('_'),
-  months: 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_')
+  months: 'January_February_March_April_May_June_July_August_September_October_November_December'.split('_'),
+  ordinal: (n) => {
+    const s = ['th', 'st', 'nd', 'rd']
+    const v = n % 100
+    return `[${n}${(s[(v - 20) % 10] || s[v] || s[0])}]`
+  }
 }
diff --git a/src/plugin/advancedFormat/index.js b/src/plugin/advancedFormat/index.js
index a78296f..7794af9 100644
--- a/src/plugin/advancedFormat/index.js
+++ b/src/plugin/advancedFormat/index.js
@@ -1,14 +1,8 @@
 import { FORMAT_DEFAULT } from '../../constant'
 
-export default (o, c, d) => { // locale needed later
+export default (o, c) => { // locale needed later
   const proto = c.prototype
   const oldFormat = proto.format
-  d.en.ordinal = (number) => {
-    const s = ['th', 'st', 'nd', 'rd']
-    const v = number % 100
-    return `[${number}${(s[(v - 20) % 10] || s[v] || s[0])}]`
-  }
-  // extend en locale here
   proto.format = function (formatStr) {
     const locale = this.$locale()
 
diff --git a/src/plugin/bigIntSupport/index.js b/src/plugin/bigIntSupport/index.js
new file mode 100644
index 0000000..a90bae1
--- /dev/null
+++ b/src/plugin/bigIntSupport/index.js
@@ -0,0 +1,25 @@
+// eslint-disable-next-line valid-typeof
+const isBigInt = num => typeof num === 'bigint'
+export default (o, c, dayjs) => {
+  const proto = c.prototype
+  const parseDate = (cfg) => {
+    const { date } = cfg
+    if (isBigInt(date)) {
+      return Number(date)
+    }
+    return date
+  }
+
+  const oldParse = proto.parse
+  proto.parse = function (cfg) {
+    cfg.date = parseDate.bind(this)(cfg)
+    oldParse.bind(this)(cfg)
+  }
+
+
+  const oldUnix = dayjs.unix
+  dayjs.unix = function (timestamp) {
+    const ts = isBigInt(timestamp) ? Number(timestamp) : timestamp
+    return oldUnix(ts)
+  }
+}
diff --git a/src/plugin/objectSupport/index.js b/src/plugin/objectSupport/index.js
index 4344dc4..6501666 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/types/plugin/bigIntSupport.d.ts b/types/plugin/bigIntSupport.d.ts
new file mode 100644
index 0000000..d9f2f39
--- /dev/null
+++ b/types/plugin/bigIntSupport.d.ts
@@ -0,0 +1,11 @@
+import { PluginFunc } from 'dayjs'
+
+declare module 'dayjs' {
+  interface ConfigTypeMap {
+    bigIntSupport: BigInt
+  }
+  export function unix(t: BigInt): Dayjs
+}
+
+declare const plugin: PluginFunc
+export = plugin


Test patch:
diff --git a/test/issues/issue2027.correct-order.test.js b/test/issues/issue2027.correct-order.test.js
new file mode 100644
index 0000000..3d9d630
--- /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 0000000..62a969e
--- /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')
+  })
+})
diff --git a/test/plugin/bigIntSupport.test.js b/test/plugin/bigIntSupport.test.js
new file mode 100644
index 0000000..b2e7086
--- /dev/null
+++ b/test/plugin/bigIntSupport.test.js
@@ -0,0 +1,30 @@
+import MockDate from 'mockdate'
+import moment from 'moment'
+import dayjs from '../../src'
+import bigIntSupport from '../../src/plugin/bigIntSupport'
+
+dayjs.extend(bigIntSupport)
+
+beforeEach(() => {
+  MockDate.set(new Date())
+})
+
+afterEach(() => {
+  MockDate.reset()
+})
+
+/* global BigInt */
+
+it('Parse BigInt ts and tsms', () => {
+  const tsms = 1666310421101
+  const tsmsBig = BigInt(tsms)
+  const ts = 1666311003
+  const tsBig = BigInt(ts)
+  const momentTsms = moment(tsms)
+  const momentTs = moment.unix(ts)
+  expect(dayjs(tsms).valueOf()).toBe(momentTsms.valueOf())
+  expect(dayjs(tsms).valueOf()).toBe(dayjs(tsmsBig).valueOf())
+  expect(dayjs.unix(ts).valueOf()).toBe(momentTs.valueOf())
+  expect(dayjs.unix(tsBig).valueOf()).toBe(dayjs.unix(tsBig).valueOf())
+})
+