Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: iamkun/dayjs
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: v1.8.26
Choose a base ref
...
head repository: iamkun/dayjs
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: v1.8.27
Choose a head ref
  • 10 commits
  • 13 files changed
  • 6 contributors

Commits on Apr 30, 2020

  1. Copy the full SHA
    52dfb13 View commit details

Commits on May 3, 2020

  1. fix: Add Turkmen (tk) locale (#893)

    Co-authored-by: Guvanch Nurgeldiyev <guvanch@threadinmotion.com>
    gnurgeldiyev and Guvanch Nurgeldiyev authored May 3, 2020
    Copy the full SHA
    a9ca8dc View commit details

Commits on May 6, 2020

  1. Copy the full SHA
    8035c8a View commit details

Commits on May 13, 2020

  1. Copy the full SHA
    f355235 View commit details

Commits on May 14, 2020

  1. Copy the full SHA
    97856c6 View commit details
  2. Copy the full SHA
    bf347c3 View commit details
  3. Copy the full SHA
    fba621d View commit details
  4. Copy the full SHA
    8593932 View commit details
  5. Merge pull request #909 from iamkun/dev

    D2M
    iamkun authored May 14, 2020
    Copy the full SHA
    04224ae View commit details
  6. chore(release): 1.8.27 [skip ci]

    ## [1.8.27](v1.8.26...v1.8.27) (2020-05-14)
    
    ### Bug Fixes
    
    * Add Kinyarwanda (rw) locale ([#903](#903)) ([f355235](f355235))
    * Add plugin objectSupport ([#887](#887)) ([52dfb13](52dfb13))
    * Add Turkmen (tk) locale ([#893](#893)) ([a9ca8dc](a9ca8dc))
    * Fix CustomParseFormat plugin set locale error ([#896](#896)) ([8035c8a](8035c8a))
    * Fix locale month function bug ([#908](#908)) ([bf347c3](bf347c3))
    * Update CustomParseFormat plugin to support Array formats ([#906](#906)) ([97856c6](97856c6))
    semantic-release-bot committed May 14, 2020
    Copy the full SHA
    9c0523e View commit details
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,15 @@
## [1.8.27](https://github.com/iamkun/dayjs/compare/v1.8.26...v1.8.27) (2020-05-14)


### Bug Fixes

* Add Kinyarwanda (rw) locale ([#903](https://github.com/iamkun/dayjs/issues/903)) ([f355235](https://github.com/iamkun/dayjs/commit/f355235a836540d77880959fb1b614c87e9f7b3e))
* Add plugin objectSupport ([#887](https://github.com/iamkun/dayjs/issues/887)) ([52dfb13](https://github.com/iamkun/dayjs/commit/52dfb13a6b84f0a753cc5761192b92416f440961))
* Add Turkmen (tk) locale ([#893](https://github.com/iamkun/dayjs/issues/893)) ([a9ca8dc](https://github.com/iamkun/dayjs/commit/a9ca8dcbbd0964c5b9abb4e8a2d620c983cf091a))
* Fix CustomParseFormat plugin set locale error ([#896](https://github.com/iamkun/dayjs/issues/896)) ([8035c8a](https://github.com/iamkun/dayjs/commit/8035c8a760549b631252252718db3cdc4ab2f68f))
* Fix locale month function bug ([#908](https://github.com/iamkun/dayjs/issues/908)) ([bf347c3](https://github.com/iamkun/dayjs/commit/bf347c36e401f50727fb5afcc537497b54b90d6b))
* Update CustomParseFormat plugin to support Array formats ([#906](https://github.com/iamkun/dayjs/issues/906)) ([97856c6](https://github.com/iamkun/dayjs/commit/97856c603ef5fbbeb1cf8a42387479e56a77dbe8))

## [1.8.26](https://github.com/iamkun/dayjs/compare/v1.8.25...v1.8.26) (2020-04-30)


2 changes: 1 addition & 1 deletion src/index.js
Original file line number Diff line number Diff line change
@@ -305,7 +305,7 @@ class Dayjs {
M: $M + 1,
MM: Utils.s($M + 1, 2, '0'),
MMM: getShort(locale.monthsShort, $M, months, 3),
MMMM: months[$M] || months(this, str),
MMMM: getShort(months, $M),
D: this.$D,
DD: Utils.s(this.$D, 2, '0'),
d: String(this.$W),
31 changes: 19 additions & 12 deletions src/locale/ru.js
Original file line number Diff line number Diff line change
@@ -27,24 +27,31 @@ function relativeTimeWithPlural(number, withoutSuffix, key) {

return `${number} ${plural(format[key], +number)}`
}
const months = (dayjsInstance, format) => {
if (MONTHS_IN_FORMAT.test(format)) {
return monthFormat[dayjsInstance.month()]
}
return monthStandalone[dayjsInstance.month()]
}
months.s = monthStandalone
months.f = monthFormat

const monthsShort = (dayjsInstance, format) => {
if (MONTHS_IN_FORMAT.test(format)) {
return monthShortFormat[dayjsInstance.month()]
}
return monthShortStandalone[dayjsInstance.month()]
}
monthsShort.s = monthShortStandalone
monthsShort.f = monthShortFormat

const locale = {
name: 'ru',
weekdays: 'воскресенье_понедельник_вторник_среда_четверг_пятница_суббота'.split('_'),
weekdaysShort: 'вск_пнд_втр_срд_чтв_птн_сбт'.split('_'),
weekdaysMin: 'вс_пн_вт_ср_чт_пт_сб'.split('_'),
months: (dayjsInstance, format) => {
if (MONTHS_IN_FORMAT.test(format)) {
return monthFormat[dayjsInstance.month()]
}
return monthStandalone[dayjsInstance.month()]
},
monthsShort: (dayjsInstance, format) => {
if (MONTHS_IN_FORMAT.test(format)) {
return monthShortFormat[dayjsInstance.month()]
}
return monthShortStandalone[dayjsInstance.month()]
},
months,
monthsShort,
weekStart: 1,
formats: {
LT: 'H:mm',
36 changes: 36 additions & 0 deletions src/locale/rw.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
// Kinyarwanda (Rwanda) [rw]
import dayjs from 'dayjs'

const locale = {
name: 'rw',
weekdays: 'Ku Cyumweru_Kuwa Mbere_Kuwa Kabiri_Kuwa Gatatu_Kuwa Kane_Kuwa Gatanu_Kuwa Gatandatu'.split('_'),
months: 'Mutarama_Gashyantare_Werurwe_Mata_Gicurasi_Kamena_Nyakanga_Kanama_Nzeri_Ukwakira_Ugushyingo_Ukuboza'.split('_'),
relativeTime: {
future: 'mu %s',
past: '%s',
s: 'amasegonda',
m: 'Umunota',
mm: '%d iminota',
h: 'isaha',
hh: '%d amasaha',
d: 'Umunsi',
dd: '%d iminsi',
M: 'ukwezi',
MM: '%d amezi',
y: 'umwaka',
yy: '%d imyaka'
},
formats: {
LT: 'HH:mm',
LTS: 'HH:mm:ss',
L: 'DD/MM/YYYY',
LL: 'D MMMM YYYY',
LLL: 'D MMMM YYYY HH:mm',
LLLL: 'dddd, D MMMM YYYY HH:mm'
},
ordinal: n => n
}

dayjs.locale(locale, null, true)

export default locale
40 changes: 40 additions & 0 deletions src/locale/tk.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
// Turkmen [tk]
import dayjs from 'dayjs'

const locale = {
name: 'tk',
weekdays: 'Ýekşenbe_Duşenbe_Sişenbe_Çarşenbe_Penşenbe_Anna_Şenbe'.split('_'),
weekdaysShort: 'Ýek_Duş_Siş_Çar_Pen_Ann_Şen'.split('_'),
weekdaysMin: 'Ýk_Dş_Sş_Çr_Pn_An_Şn'.split('_'),
months: 'Ýanwar_Fewral_Mart_Aprel_Maý_Iýun_Iýul_Awgust_Sentýabr_Oktýabr_Noýabr_Dekabr'.split('_'),
monthsShort: 'Ýan_Few_Mar_Apr_Maý_Iýn_Iýl_Awg_Sen_Okt_Noý_Dek'.split('_'),
weekStart: 1,
formats: {
LT: 'HH:mm',
LTS: 'HH:mm:ss',
L: 'DD.MM.YYYY',
LL: 'D MMMM YYYY',
LLL: 'D MMMM YYYY HH:mm',
LLLL: 'dddd, D MMMM YYYY HH:mm'
},
relativeTime: {
future: '%s soň',
past: '%s öň',
s: 'birnäçe sekunt',
m: 'bir minut',
mm: '%d minut',
h: 'bir sagat',
hh: '%d sagat',
d: 'bir gün',
dd: '%d gün',
M: 'bir aý',
MM: '%d aý',
y: 'bir ýyl',
yy: '%d ýyl'
},
ordinal: n => `${n}.`
}

dayjs.locale(locale, null, true)

export default locale
39 changes: 29 additions & 10 deletions src/plugin/customParseFormat/index.js
Original file line number Diff line number Diff line change
@@ -9,7 +9,7 @@ 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
const matchWord = /\d*[^\s\d-:/()]+/ // Word

let locale

@@ -30,6 +30,13 @@ const zoneExpressions = [matchOffset, function (input) {
zone.offset = offsetFromString(input)
}]

const getLocalePart = (name) => {
const part = locale[name]
return part && (
part.indexOf ? part : part.s.concat(part.f)
)
}

const expressions = {
A: [matchUpperCaseAMPM, function (input) {
this.afternoon = input === 'PM'
@@ -69,22 +76,21 @@ const expressions = {
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)
const months = getLocalePart('months')
const monthsShort = getLocalePart('monthsShort')
const matchIndex = (monthsShort || months.map(_ => _.substr(0, 3))).indexOf(input)
if (matchIndex < 0) {
throw new Error()
}
this.month = matchIndex + 1
this.month = (matchIndex + 1) % 12
}],
MMMM: [matchWord, function (input) {
const { months } = locale
const months = getLocalePart('months')
const matchIndex = months.indexOf(input)
if (matchIndex < 0) {
throw new Error()
}
this.month = matchIndex + 1
this.month = (matchIndex + 1) % 12
}],
Y: [matchSigned, addInput('year')],
YY: [match2, function (input) {
@@ -196,11 +202,24 @@ export default (o, C, d) => {
locale = pl ? d.Ls[pl] : this.$locale()
}
this.$d = parseFormattedInput(date, format, utc)
this.init(cfg)
this.init()
if (pl && pl !== true) this.$L = this.locale(pl).$L
if (isStrict && date !== this.format(format)) {
this.$d = new Date('')
}
if (pl && pl !== true) this.$L = pl
} else if (format instanceof Array) {
const len = format.length
for (let i = 1; i <= len; i += 1) {
args[1] = format[i - 1]
const result = d.apply(this, args)
if (result.isValid()) {
this.$d = result.$d
this.$L = result.$L
this.init()
break
}
if (i === len) this.$d = new Date('')
}
} else {
oldParse.call(this, cfg)
}
10 changes: 5 additions & 5 deletions src/plugin/localeData/index.js
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
export default (o, c, dayjs) => { // locale needed later
const proto = c.prototype
const getLocalePart = part => (part && (part.indexOf ? part : part.s))
const getShort = (ins, target, full, num) => {
const locale = ins.name ? ins : ins.$locale()
if (!locale[target]) {
return locale[full].map(f => f.substr(0, num))
}
return locale[target]
const targetLocale = getLocalePart(locale[target])
const fullLocale = getLocalePart(locale[full])
return targetLocale || fullLocale.map(f => f.substr(0, num))
}
const getDayjsLocaleObject = () => dayjs.Ls[dayjs.locale()]
const localeData = function () {
@@ -38,7 +38,7 @@ export default (o, c, dayjs) => { // locale needed later
}
}

dayjs.months = () => getDayjsLocaleObject().months
dayjs.months = () => getShort(getDayjsLocaleObject(), 'months')

dayjs.monthsShort = () => getShort(getDayjsLocaleObject(), 'monthsShort', 'months', 3)

63 changes: 63 additions & 0 deletions src/plugin/objectSupport/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
export default (o, c) => {
const proto = c.prototype
const isObject = obj => !(obj instanceof Date) && !(obj instanceof Array) && obj instanceof Object
const prettyUnit = (u) => {
const unit = proto.$utils().p(u)
return unit === 'date' ? 'day' : unit
}
const parseDate = (cfg) => {
const { date, utc } = cfg
const $d = {}
if (isObject(date)) {
Object.keys(date).forEach((k) => {
$d[prettyUnit(k)] = date[k]
})
const y = $d.year || 1970
const M = $d.month - 1 || 0
const d = $d.day || 1
const h = $d.hour || 0
const m = $d.minute || 0
const s = $d.second || 0
const ms = $d.millisecond || 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)
}
return date
}

const oldParse = proto.parse
proto.parse = function (cfg) {
cfg.date = parseDate.bind(this)(cfg)
oldParse.bind(this)(cfg)
}

const oldSet = proto.set
const oldAdd = proto.add

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)
}

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.add = function (number, string) {
return callObject.bind(this)(oldAdd, number, string)
}
proto.subtract = function (number, string) {
return callObject.bind(this)(oldAdd, number, string, -1)
}
}
4 changes: 4 additions & 0 deletions test/locale/keys.test.js
Original file line number Diff line number Diff line change
@@ -45,13 +45,17 @@ Locale.forEach((locale) => {
expect(months).toEqual(expect.any(Array))
} else {
expect(months(dayjs(), 'str')).toEqual(expect.any(String))
expect(months.f).toEqual(expect.any(Array))
expect(months.s).toEqual(expect.any(Array))
}
// monthsShort could be a function or array
if (monthsShort) {
if (Array.isArray(monthsShort)) {
expect(monthsShort).toEqual(expect.any(Array))
} else {
expect(monthsShort(dayjs(), 'str')).toEqual(expect.any(String))
expect(monthsShort.f).toEqual(expect.any(Array))
expect(monthsShort.s).toEqual(expect.any(Array))
}
}
// function pass date return string or number or null
34 changes: 34 additions & 0 deletions test/plugin/customParseFormat.test.js
Original file line number Diff line number Diff line change
@@ -4,6 +4,7 @@ import dayjs from '../../src'
import customParseFormat from '../../src/plugin/customParseFormat'
import uk from '../../src/locale/uk'
import '../../src/locale/zh-cn'
import '../../src/locale/ru'

dayjs.extend(customParseFormat)

@@ -233,6 +234,20 @@ it('correctly parse ordinal', () => {
.toBe(momentCN.locale())
})

describe('month function locale', () => {
it('MMMM', () => {
const input = '08 мая 2020'
const input2 = '08 май 2020'
const format = 'DD MMMM YYYY'
expect(dayjs(input, format, 'ru').valueOf()).toBe(moment(input, format, 'ru').valueOf())
expect(dayjs(input2, format, 'ru').valueOf()).toBe(moment(input2, format, 'ru').valueOf())
})
it('MMM', () => {
const input = '08 февр. 2020'
const format = 'DD MMM YYYY'
expect(dayjs(input, format, 'ru').valueOf()).toBe(moment(input, format, 'ru').valueOf())
})
})

describe('Strict mode', () => {
it('without locale', () => {
@@ -248,3 +263,22 @@ describe('Strict mode', () => {
expect(dayjs(input, format, 'zh-cn', true).isValid()).toBe(false)
})
})

describe('Array format support', () => {
it('second ok', () => {
const input = '2012-05-28'
const format = ['YYYY', 'YYYY-MM-DD']
expect(dayjs(input, format).isValid()).toBe(true)
expect(dayjs(input, format, true).format('YYYY-MM-DD')).toBe('2012-05-28')
})
it('all invalid', () => {
const input = '2012-05-28'
const format = ['DD', 'MM-DD']
expect(dayjs(input, format, true).isValid()).toBe(false)
})
it('with locale', () => {
const input = '2018 三月 12'
const format = ['YYYY', 'MM', 'YYYY MMMM DD']
expect(dayjs(input, format, 'zh-cn', true).format('YYYY MMMM DD')).toBe(input)
})
})
12 changes: 12 additions & 0 deletions test/plugin/localeData.test.js
Original file line number Diff line number Diff line change
@@ -5,6 +5,7 @@ import localeData from '../../src/plugin/localeData'
import localizedFormat from '../../src/plugin/localizedFormat'
import '../../src/locale/fr'
import '../../src/locale/zh-cn'
import '../../src/locale/ru'

dayjs.extend(localizedFormat)
dayjs.extend(localeData)
@@ -65,3 +66,14 @@ it('Listing the months and weekdays', () => {
expect(dayjs.weekdaysMin()).toEqual(moment.weekdaysMin())
})
})

it('Month function', () => {
const dayjsLocaleData = dayjs().locale('ru').localeData()
const momentLocaleData = moment().locale('ru').localeData()
expect(dayjsLocaleData.months()).toEqual(momentLocaleData.months())
expect(dayjsLocaleData.monthsShort()).toEqual(momentLocaleData.monthsShort())
dayjs.locale('ru')
moment.locale('ru')
expect(dayjs.months()).toEqual(moment.months())
expect(dayjs.monthsShort()).toEqual(moment.monthsShort())
})
344 changes: 344 additions & 0 deletions test/plugin/objectSupport.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,344 @@
import moment from 'moment'
import MockDate from 'mockdate'
import dayjs from '../../src'
import objectSupport from '../../src/plugin/objectSupport'
import quarterOfYear from '../../src/plugin/quarterOfYear'
import utc from '../../src/plugin/utc'

dayjs.extend(utc)
dayjs.extend(quarterOfYear)
dayjs.extend(objectSupport)

beforeEach(() => {
MockDate.set(new Date())
})

afterEach(() => {
MockDate.reset()
})
const now = new Date()
const fmt = 'YYYY-MM-DD HH:mm:ss.SSS'
const tests = [
[{ year: 2010 }, '2010-01-01 00:00:00.000'],
[{ year: 2010, month: 1 }, '2010-01-01 00:00:00.000'],
[{ year: 2010, month: 1, day: 12 }, '2010-01-12 00:00:00.000'],
[{ year: 2010, month: 1, date: 12 }, '2010-01-12 00:00:00.000'],
[
{
hour: 15, minute: 25, second: 50, millisecond: 125
},
'1970-01-01 15:25:50.125'],
[
{
year: 2010, month: 1, day: 12, hours: 1
},
'2010-01-12 01:00:00.000'
],
[
{
year: 2010, month: 1, date: 12, hours: 1
},
'2010-01-12 01:00:00.000'
],
[
{
year: 2010, month: 1, day: 12, hours: 1, minutes: 1
},
'2010-01-12 01:01:00.000'
],
[
{
year: 2010, month: 1, date: 12, hours: 1, minutes: 1
},
'2010-01-12 01:01:00.000'
],
[
{
year: 2010,
month: 1,
day: 12,
hours: 1,
minutes: 1,
seconds: 1
},
'2010-01-12 01:01:01.000'
],
[
{
year: 2010,
month: 1,
day: 12,
hours: 1,
minutes: 1,
seconds: 1,
milliseconds: 1
},
'2010-01-12 01:01:01.001'
],
[
{
years: 2010,
months: 1,
days: 14,
hours: 15,
minutes: 25,
seconds: 50,
milliseconds: 125
},
'2010-01-14 15:25:50.125'
],
[
{
year: 2010,
month: 1,
day: 14,
hour: 15,
minute: 25,
second: 50,
millisecond: 125
},
'2010-01-14 15:25:50.125'
],
[
{
y: 2010, M: 1, d: 14, h: 15, m: 25, s: 50, ms: 125
},
'2010-01-14 15:25:50.125'
]
]
it('Constructor from Object', () => {
for (let i = 0; i < tests.length; i += 1) {
expect(dayjs(tests[i][0]).format(fmt)).toBe(tests[i][1])
}
})

it('Constructor from Object UTC', () => {
for (let i = 0; i < tests.length; i += 1) {
expect(dayjs.utc(tests[i][0]).format(fmt)).toBe(tests[i][1])
}
})
it('Set from Object', () => {
for (let i = 0; i < tests.length; i += 1) {
expect(dayjs(now).set(tests[i][0]).format(fmt)).toBe(moment(now).set(tests[i][0]).format(fmt))
}
})

it('add short reverse args', () => {
const a = dayjs({
year: 2011,
month: 9,
date: 12,
hour: 6,
minute: 7,
second: 8,
millisecond: 500
})
expect(a.add({ ms: 50 }).millisecond()).toBe(550)
expect(a.add({ s: 1 }).second()).toBe(9)
expect(a.add({ m: 1 }).minute()).toBe(8)
expect(a.add({ h: 1 }).hour()).toBe(7)
expect(a.add({ d: 1 }).date()).toBe(13)
expect(a.add({ w: 1 }).date()).toBe(19)
expect(a.add({ M: 1 }).month()).toBe(9)
expect(a.add({ y: 1 }).year()).toBe(2012)
expect(a.add({ Q: 1 }).month()).toBe(11)

const b = dayjs([2010, 1, 31]).add({ M: 1 })
const c = dayjs([2010, 2, 28]).subtract({ M: 1 })
const d = dayjs([2010, 2, 28]).subtract({ Q: 1 })

expect(b.month()).toBe(1)
expect(b.date()).toBe(28)
expect(c.month()).toBe(0)
expect(c.date()).toBe(28)
expect(d.month()).toBe(10)
expect(d.date()).toBe(28)
expect(d.year()).toBe(2009)
})

it('add long reverse args', () => {
const a = dayjs({
year: 2011,
month: 9,
date: 12,
hour: 6,
minute: 7,
second: 8,
millisecond: 500
})

expect(a.add({ milliseconds: 50 }).millisecond()).toBe(550)
expect(a.add({ seconds: 1 }).second()).toBe(9)
expect(a.add({ minutes: 1 }).minute()).toBe(8)
expect(a.add({ hours: 1 }).hour()).toBe(7)
expect(a.add({ days: 1 }).date()).toBe(13)
expect(a.add({ weeks: 1 }).date()).toBe(19)
expect(a.add({ months: 1 }).month()).toBe(9)
expect(a.add({ years: 1 }).year()).toBe(2012)
expect(a.add({ quarters: 1 }).month()).toBe(11)
})

it('add long singular reverse args', () => {
const a = dayjs({
year: 2011,
month: 9,
date: 12,
hour: 6,
minute: 7,
second: 8,
millisecond: 500
})

expect(a.add({ millisecond: 50 }).millisecond()).toBe(550)
expect(a.add({ second: 1 }).second()).toBe(9)
expect(a.add({ minute: 1 }).minute()).toBe(8)
expect(a.add({ hour: 1 }).hour()).toBe(7)
expect(a.add({ day: 1 }).date()).toBe(13)
expect(a.add({ week: 1 }).date()).toBe(19)
expect(a.add({ month: 1 }).month()).toBe(9)
expect(a.add({ year: 1 }).year()).toBe(2012)
expect(a.add({ quarter: 1 }).month()).toBe(11)
})

it('add string long', () => {
const a = dayjs({
year: 2011,
month: 9,
date: 12,
hour: 6,
minute: 7,
second: 8,
millisecond: 500
})

expect(a.add(50, 'millisecond').millisecond()).toBe(550)
expect(a.add(1, 'second').second()).toBe(9)
expect(a.add(1, 'minute').minute()).toBe(8)
expect(a.add(1, 'hour').hour()).toBe(7)
expect(a.add(1, 'day').date()).toBe(13)
expect(a.add(1, 'week').date()).toBe(19)
expect(a.add(1, 'month').month()).toBe(9)
expect(a.add(1, 'year').year()).toBe(2012)
expect(a.add(1, 'quarter').month()).toBe(11)
})

it('add string long singular', () => {
const a = dayjs({
year: 2011,
month: 9,
date: 12,
hour: 6,
minute: 7,
second: 8,
millisecond: 500
})

expect(a.add(50, 'milliseconds').millisecond()).toBe(550)
expect(a.add(1, 'seconds').second()).toBe(9)
expect(a.add(1, 'minutes').minute()).toBe(8)
expect(a.add(1, 'hours').hour()).toBe(7)
expect(a.add(1, 'days').date()).toBe(13)
expect(a.add(1, 'weeks').date()).toBe(19)
expect(a.add(1, 'months').month()).toBe(9)
expect(a.add(1, 'years').year()).toBe(2012)
expect(a.add(1, 'quarters').month()).toBe(11)
})

it('add string short', () => {
const a = dayjs({
year: 2011,
month: 9,
date: 12,
hour: 6,
minute: 7,
second: 8,
millisecond: 500
})

expect(a.add(50, 'ms').millisecond()).toBe(550)
expect(a.add(1, 's').second()).toBe(9)
expect(a.add(1, 'm').minute()).toBe(8)
expect(a.add(1, 'h').hour()).toBe(7)
expect(a.add(1, 'd').date()).toBe(13)
expect(a.add(1, 'w').date()).toBe(19)
expect(a.add(1, 'M').month()).toBe(9)
expect(a.add(1, 'y').year()).toBe(2012)
expect(a.add(1, 'Q').month()).toBe(11)
})

it('add strings string short', () => {
const a = dayjs({
year: 2011,
month: 9,
date: 12,
hour: 6,
minute: 7,
second: 8,
millisecond: 500
})

expect(a.add('50', 'ms').millisecond()).toBe(550)
expect(a.add('1', 's').second()).toBe(9)
expect(a.add('1', 'm').minute()).toBe(8)
expect(a.add('1', 'h').hour()).toBe(7)
expect(a.add('1', 'd').date()).toBe(13)
expect(a.add('1', 'w').date()).toBe(19)
expect(a.add('1', 'M').month()).toBe(9)
expect(a.add('1', 'y').year()).toBe(2012)
expect(a.add('1', 'Q').month()).toBe(11)
})

it('add no string with milliseconds default', () => {
const a = dayjs({
year: 2011,
month: 9,
date: 12,
hour: 6,
minute: 7,
second: 8,
millisecond: 500
})

expect(a.add(50).millisecond()).toBe(550)
})

it('subtract strings string short', () => {
const a = dayjs({
year: 2011,
month: 9,
date: 12,
hour: 6,
minute: 7,
second: 8,
millisecond: 500
})
expect(a.subtract('50', 'ms').millisecond()).toBe(450)
expect(a.subtract('1', 's').second()).toBe(7)
expect(a.subtract('1', 'm').minute()).toBe(6)
expect(a.subtract('1', 'h').hour()).toBe(5)
expect(a.subtract('1', 'd').date()).toBe(11)
expect(a.subtract('1', 'w').date()).toBe(5)
expect(a.subtract('1', 'M').month()).toBe(7)
expect(a.subtract('1', 'y').year()).toBe(2010)
expect(a.subtract('1', 'Q').month()).toBe(5)
})

it('add decimal values of days and months', () => {
expect(dayjs([2016, 4, 3]).add(1.6, 'days').date()).toBe(5)
expect(dayjs([2016, 4, 3]).add(-1.6, 'days').date()).toBe(1)
expect(dayjs([2016, 4, 1]).add(-1.6, 'days').date()).toBe(30)
expect(dayjs([2016, 4, 3]).add(1.6, 'months').month()).toBe(4)
expect(dayjs([2016, 4, 3]).add(-1.6, 'months').month()).toBe(1)
expect(dayjs([2016, 1, 3]).add(-1.6, 'months').month()).toBe(11)
expect(dayjs([2016, 4, 3]).subtract(1.6, 'days').date()).toBe(1)
expect(dayjs([2016, 4, 2]).subtract(1.6, 'days').date()).toBe(31)
expect(dayjs([2016, 2, 1]).subtract(1.1, 'days').date()).toBe(31)
expect(dayjs([2016, 4, 3]).subtract(-1.6, 'days').date()).toBe(5)
expect(dayjs([2016, 4, 30]).subtract(-1.6, 'days').date()).toBe(2)
expect(dayjs([2016, 4, 3]).subtract(1.6, 'months').month()).toBe(1)
expect(dayjs([2016, 4, 3]).subtract(-1.6, 'months').month()).toBe(4)
expect(dayjs([2016, 12, 31]).subtract(-1.6, 'months').month()).toBe(0)
expect(dayjs([2016, 1, 1]).add(1.6, 'years').format('YYYY-MM-DD')).toBe('2017-01-01')
expect(dayjs([2016, 7, 1]).add(1.6, 'years').format('YYYY-MM-DD')).toBe('2017-07-01')
expect(dayjs([2016, 1, 1]).add(1.1, 'quarters').format('YYYY-MM-DD')).toBe('2016-04-01')
})
12 changes: 12 additions & 0 deletions types/plugin/objectSupport.d.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
import { PluginFunc } from 'dayjs'

declare const plugin: PluginFunc
export = plugin

declare module 'dayjs' {
interface Dayjs {
set(argument: object): Dayjs
add(argument: object): Dayjs
subtract(argument: object): Dayjs
}
}