Repository: iamkun/dayjs (JavaScript)

Issue:
Custom format creating wrong date
Parsing the date `31/01/2019` (pt-br style) using `dayjs_plugin_customParseFormat` is creating a wrong date.

```js
dayjs.extend(dayjs_plugin_customParseFormat);

dayjs('31/01/2019', 'DD/MM/YYYY')
// => 2019-03-03T00:00:00-03:00
```

<https://jsfiddle.net/dpb4hfnk/>


Hints:

Patch:
diff --git a/prettier.config.js b/prettier.config.js
new file mode 100644
--- /dev/null
+++ b/prettier.config.js
@@ -0,0 +1,7 @@
+module.exports = {
+  useTabs: false,
+  printWidth: 80,
+  singleQuote: true,
+  trailingComma: 'none',
+  semi: false
+}
diff --git a/src/constant.js b/src/constant.js
--- a/src/constant.js
+++ b/src/constant.js
@@ -28,9 +28,3 @@ 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_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
-
-export const en = {
-  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('_')
-}
diff --git a/src/index.js b/src/index.js
--- a/src/index.js
+++ b/src/index.js
@@ -1,9 +1,10 @@
 import * as C from './constant'
 import U from './utils'
+import en from './locale/en'
 
 let L = 'en' // global locale
 const Ls = {} // global loaded locale
-Ls[L] = C.en
+Ls[L] = en
 
 const isDayjs = d => d instanceof Dayjs // eslint-disable-line no-use-before-define
 
@@ -163,18 +164,18 @@ class Dayjs {
         (isStartOf ? argumentStart : argumentEnd).slice(slice)
       ), this)
     }
-
+    const { $W, $M, $D } = this
     switch (unit) {
       case C.Y:
         return isStartOf ? instanceFactory(1, 0) :
           instanceFactory(31, 11)
       case C.M:
-        return isStartOf ? instanceFactory(1, this.$M) :
-          instanceFactory(0, this.$M + 1)
+        return isStartOf ? instanceFactory(1, $M) :
+          instanceFactory(0, $M + 1)
       case C.W: {
         const weekStart = this.$locale().weekStart || 0
-        return isStartOf ? instanceFactory(this.$D - (this.$W - weekStart), this.$M) :
-          instanceFactory(this.$D + (6 - (this.$W - weekStart)), this.$M)
+        const gap = ($W < weekStart ? $W + 7 : $W) - weekStart
+        return instanceFactory(isStartOf ? $D - gap : $D + (6 - gap), $M)
       }
       case C.D:
       case C.DATE:
diff --git a/src/locale/ar.js b/src/locale/ar.js
--- a/src/locale/ar.js
+++ b/src/locale/ar.js
@@ -4,6 +4,7 @@ const locale = {
   name: 'ar',
   weekdays: 'الأحد_الإثنين_الثلاثاء_الأربعاء_الخميس_الجمعة_السبت'.split('_'),
   months: 'يناير_فبراير_مارس_أبريل_مايو_يونيو_يوليو_أغسطس_سبتمبر_أكتوبر_نوفمبر_ديسمبر'.split('_'),
+  weekStart: 6,
   relativeTime: {
     future: 'بعد %s',
     past: 'منذ %s',
diff --git a/src/locale/en.js b/src/locale/en.js
new file mode 100644
--- /dev/null
+++ b/src/locale/en.js
@@ -0,0 +1,5 @@
+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('_')
+}
diff --git a/src/locale/fi.js b/src/locale/fi.js
--- a/src/locale/fi.js
+++ b/src/locale/fi.js
@@ -6,7 +6,7 @@ const locale = {
   weekdaysShort: 'su_ma_ti_ke_to_pe_la'.split('_'), // There is no short form of weekdays in Finnish except this 2 letter format so it is used for both 'weekdaysShort' and 'weekdaysMin'
   weekdaysMin: 'su_ma_ti_ke_to_pe_la'.split('_'),
   months: 'tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu'.split('_'), // Note month names are not capitalized in Finnish
-  monthsShort: 'tammikuu_helmikuu_maaliskuu_huhtikuu_toukokuu_kesäkuu_heinäkuu_elokuu_syyskuu_lokakuu_marraskuu_joulukuu'.split('_'), // There is no short form of months in Finnish so just use the regular long form always
+  monthsShort: 'tammi_helmi_maalis_huhti_touko_kesä_heinä_elo_syys_loka_marras_joulu'.split('_'),
   ordinal: n => `${n}.`,
   weekStart: 1,
   /*
diff --git a/src/locale/ms.js b/src/locale/ms.js
new file mode 100644
--- /dev/null
+++ b/src/locale/ms.js
@@ -0,0 +1,36 @@
+import dayjs from 'dayjs'
+
+const locale = {
+  name: 'ms',
+  weekdays: 'Ahad_Isnin_Selasa_Rabu_Khamis_Jumaat_Sabtu'.split('_'),
+  months: 'Januari_Februari_Mac_April_Mei_Jun_Julai_Ogos_September_Oktober_November_Disember'.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: 'dalam %s',
+    past: '%s yang lepas',
+    s: 'beberapa saat',
+    m: 'seminit',
+    mm: '%d minit',
+    h: 'sejam',
+    hh: '%d jam',
+    d: 'sehari',
+    dd: '%d hari',
+    M: 'sebulan',
+    MM: '%d bulan',
+    y: 'setahun',
+    yy: '%d tahun'
+  },
+  ordinal: n => `${n}.`
+}
+
+dayjs.locale(locale, null, true)
+
+export default locale
diff --git a/src/locale/sv.js b/src/locale/sv.js
--- a/src/locale/sv.js
+++ b/src/locale/sv.js
@@ -3,7 +3,10 @@ import dayjs from 'dayjs'
 const locale = {
   name: 'sv',
   weekdays: 'söndag_måndag_tisdag_onsdag_torsdag_fredag_lördag'.split('_'),
+  weekdaysShort: 'sön_mån_tis_ons_tor_fre_lör'.split('_'),
+  weekdaysMin: 'sö_må_ti_on_to_fr_lö'.split('_'),
   months: 'januari_februari_mars_april_maj_juni_juli_augusti_september_oktober_november_december'.split('_'),
+  monthsShort: 'jan_feb_mar_apr_maj_jun_jul_aug_sep_okt_nov_dec'.split('_'),
   weekStart: 1,
   ordinal: (n) => {
     const b = n % 10
diff --git a/src/plugin/customParseFormat/index.js b/src/plugin/customParseFormat/index.js
--- a/src/plugin/customParseFormat/index.js
+++ b/src/plugin/customParseFormat/index.js
@@ -129,7 +129,7 @@ const parseFormattedInput = (input, format) => {
     }
     const now = new Date()
     return new Date(
-      year || now.getFullYear(), month - 1 || now.getMonth(), day || now.getDate(),
+      year || now.getFullYear(), month > 0 ? month - 1 : now.getMonth(), day || now.getDate(),
       hours || 0, minutes || 0, seconds || 0, milliseconds || 0
     )
   } catch (e) {
diff --git a/src/plugin/isBetween/index.js b/src/plugin/isBetween/index.js
--- a/src/plugin/isBetween/index.js
+++ b/src/plugin/isBetween/index.js
@@ -1,9 +1,14 @@
 export default (o, c, d) => {
-  c.prototype.isBetween = function (a, b, u) {
+  c.prototype.isBetween = function (a, b, u, i) {
     const dA = d(a)
     const dB = d(b)
+    i = i || '()'
+    const dAi = i[0] === '('
+    const dBi = i[1] === ')'
 
-    return (this.isAfter(dA, u) && this.isBefore(dB, u))
-        || (this.isBefore(dA, u) && this.isAfter(dB, u))
+    return ((dAi ? this.isAfter(dA, u) : !this.isBefore(dA, u)) &&
+           (dBi ? this.isBefore(dB, u) : !this.isAfter(dB, u)))
+        || ((dAi ? this.isBefore(dA, u) : !this.isAfter(dA, u)) &&
+           (dBi ? this.isAfter(dB, u) : !this.isBefore(dB, u)))
   }
 }


Test patch:
diff --git a/test/locale/keys.test.js b/test/locale/keys.test.js
--- a/test/locale/keys.test.js
+++ b/test/locale/keys.test.js
@@ -36,9 +36,12 @@ it('Locale keys', () => {
 
     expect(months).toEqual(expect.any(Array))
     // function pass date return string or number or null
-    for (let i = 1; i <= 31; i += 1) {
-      expect(ordinal(i)).toEqual(expect.anything())
+    if (name !== 'en') { // en ordinal set in advancedFormat
+      for (let i = 1; i <= 31; i += 1) {
+        expect(ordinal(i)).toEqual(expect.anything())
+      }
     }
+
     expect(dayjs().locale(name).$locale().name).toBe(name)
     if (formats) {
       expect(Object.keys(formats).sort()).toEqual(['L', 'LL', 'LLL', 'LLLL', 'LT', 'LTS'].sort())
diff --git a/test/manipulate.test.js b/test/manipulate.test.js
--- a/test/manipulate.test.js
+++ b/test/manipulate.test.js
@@ -32,10 +32,15 @@ describe('StartOf EndOf', () => {
   })
 
   it('StartOf week with locale', () => {
-    const testArr = ['zh-cn']
-    testArr.forEach((l) => {
-      expect(dayjs().locale(l).startOf('week').date()).toBe(moment().locale(l).startOf('week').date())
-      expect(dayjs().locale(l).endOf('week').date()).toBe(moment().locale(l).endOf('week').date())
+    const testDate = [undefined, '2019-02-10', '2019-02-11', '2019-02-12', '2019-02-13', '2019-02-14', '2019-02-15', '2019-02-16']
+    const testLocale = ['zh-cn', 'ar', 'en']
+    testDate.forEach((d) => {
+      testLocale.forEach((l) => {
+        expect(dayjs(d).locale(l).startOf('week').date())
+          .toBe(moment(d).locale(l).startOf('week').date())
+        expect(dayjs(d).locale(l).endOf('week').date())
+          .toBe(moment(d).locale(l).endOf('week').date())
+      })
     })
   })
 })
diff --git a/test/plugin/customParseFormat.test.js b/test/plugin/customParseFormat.test.js
--- a/test/plugin/customParseFormat.test.js
+++ b/test/plugin/customParseFormat.test.js
@@ -24,6 +24,12 @@ it('parse padded string', () => {
   expect(dayjs(input, format).valueOf()).toBe(moment(input, format).valueOf())
 })
 
+it('parse string January (getMonth() = 0)', () => {
+  const input = '01/01/2019'
+  const format = 'DD/MM/YYYY'
+  expect(dayjs(input, format).valueOf()).toBe(moment(input, format).valueOf())
+})
+
 it('parse unpadded string', () => {
   const input = '2.5.18 1:2:3.4 PM -0100'
   const format = 'D.M.YY H:m:s.S A ZZ'
diff --git a/test/plugin/isBetween.test.js b/test/plugin/isBetween.test.js
--- a/test/plugin/isBetween.test.js
+++ b/test/plugin/isBetween.test.js
@@ -17,6 +17,11 @@ test('bounds can be swapped', () => {
   expect(dayjs('2018-01-01').isBetween(dayjs('2018-01-02'), dayjs('2017-12-31'))).toBeTruthy()
 })
 
+test('bounds can be swapped with inclusivity', () => {
+  expect(dayjs('2018-01-01').isBetween(dayjs('2017-12-31'), dayjs('2018-01-01'), null, '[]')).toBeTruthy()
+  expect(dayjs('2018-01-01').isBetween(dayjs('2018-01-01'), dayjs('2017-12-31'), null, '[]')).toBeTruthy()
+})
+
 test('is between without units', () => {
   const m = dayjs(new Date(2011, 3, 2, 3, 4, 5, 10))
   const mCopy = dayjs(m)
@@ -381,3 +386,303 @@ test('is between millisecond', () => {
   expect(m.isBetween(m, 'millisecond')).toBe(false, 'same moments are not between the same millisecond')
   expect(+m).toEqual(+mCopy, 'isBetween millisecond should not change moment')
 })
+
+test('is between without units inclusivity', () => {
+  const m = dayjs(new Date(2011, 3, 2, 3, 4, 5, 10))
+  const mCopy = dayjs(m)
+
+  expect(m.isBetween(
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2012, 3, 2, 3, 4, 5, 10)),
+    null,
+    '()'
+  )).toBe(false, 'start and end are excluded, start is equal to dayjs')
+
+  expect(m.isBetween(
+    dayjs(new Date(2010, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    null,
+    '()'
+  )).toBe(false, 'start and end are excluded, end is equal to dayjs')
+
+  expect(m.isBetween(
+    dayjs(new Date(2010, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2012, 3, 2, 3, 4, 5, 10)),
+    null,
+    '()'
+  )).toBe(true, 'start and end are excluded, is between')
+
+  expect(m.isBetween(
+    dayjs(new Date(2009, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2010, 3, 2, 3, 4, 5, 10)),
+    null,
+    '()'
+  )).toBe(false, 'start and end are excluded, is not between')
+
+  expect(m.isBetween(
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    null,
+    '()'
+  )).toBe(false, 'start and end are excluded, should fail on same start/end date.')
+
+  expect(m.isBetween(
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2012, 3, 2, 3, 4, 5, 10)),
+    null,
+    '(]'
+  )).toBe(false, 'start is excluded and end is included should fail on same start date')
+
+  expect(m.isBetween(
+    dayjs(new Date(2010, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    null,
+    '(]'
+  )).toBe(true, 'start is excluded and end is included should succeed on end date')
+
+  expect(m.isBetween(
+    dayjs(new Date(2010, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2012, 3, 2, 3, 4, 5, 10)),
+    null,
+    '(]'
+  )).toBe(true, 'start is excluded and end is included, is between')
+
+  expect(m.isBetween(
+    dayjs(new Date(2009, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2010, 3, 2, 3, 4, 5, 10)),
+    null,
+    '(]'
+  )).toBe(false, 'start is excluded and end is included, is not between')
+
+  expect(m.isBetween(
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    null,
+    '(]'
+  )).toBe(false, 'start is excluded and end is included, should fail on same start/end date.')
+
+  expect(m.isBetween(
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2012, 3, 2, 3, 4, 5, 10)),
+    null,
+    '[)'
+  )).toBe(true, 'start is included and end is excluded should succeed on same start date')
+
+  expect(m.isBetween(
+    dayjs(new Date(2010, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    null,
+    '[)'
+  )).toBe(false, 'start is included and end is excluded should fail on same end date')
+
+  expect(m.isBetween(
+    dayjs(new Date(2010, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2012, 3, 2, 3, 4, 5, 10)),
+    null,
+    '[)'
+  )).toBe(true, 'start is included and end is excluded, is between')
+
+  expect(m.isBetween(
+    dayjs(new Date(2009, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2010, 3, 2, 3, 4, 5, 10)),
+    null,
+    '[)'
+  )).toBe(false, 'start is included and end is excluded, is not between')
+
+  expect(m.isBetween(
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    null,
+    '[)'
+  )).toBe(false, 'start is included and end is excluded, should fail on same end and start date')
+
+  expect(m.isBetween(
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2012, 3, 2, 3, 4, 5, 10)),
+    null,
+    '[]'
+  )).toBe(true, 'start and end inclusive should succeed on same start date')
+
+  expect(m.isBetween(
+    dayjs(new Date(2010, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    null,
+    '[]'
+  )).toBe(true, 'start and end inclusive should succeed on same end date')
+
+  expect(m.isBetween(
+    dayjs(new Date(2010, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2012, 3, 2, 3, 4, 5, 10)),
+    null,
+    '[]'
+  )).toBe(true, 'start and end inclusive, is between')
+
+  expect(m.isBetween(
+    dayjs(new Date(2009, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2010, 3, 2, 3, 4, 5, 10)),
+    null,
+    '[]'
+  )).toBe(false, 'start and end inclusive, is not between')
+
+  expect(m.isBetween(
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    null,
+    '[]'
+  )).toBe(true, 'start and end inclusive, should handle same end and start date')
+
+  expect(+m).toEqual(+mCopy, 'isBetween millisecond should not change moment')
+})
+
+test('is between milliseconds inclusivity', () => {
+  const m = dayjs(new Date(2011, 3, 2, 3, 4, 5, 10))
+  const mCopy = dayjs(m)
+
+  expect(m.isBetween(
+    dayjs(new Date(2010, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2012, 3, 2, 3, 4, 5, 10)),
+    'milliseconds'
+  )).toBe(true, 'options, no inclusive')
+
+  expect(m.isBetween(
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2012, 3, 2, 3, 4, 5, 10)),
+    'milliseconds',
+    '()'
+  )).toBe(false, 'start and end are excluded, start is equal to dayjs')
+
+  expect(m.isBetween(
+    dayjs(new Date(2010, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    'milliseconds',
+    '()'
+  )).toBe(false, 'start and end are excluded, end is equal to dayjs')
+
+  expect(m.isBetween(
+    dayjs(new Date(2010, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2012, 3, 2, 3, 4, 5, 10)),
+    'milliseconds',
+    '()'
+  )).toBe(true, 'start and end are excluded, is between')
+
+  expect(m.isBetween(
+    dayjs(new Date(2009, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2010, 3, 2, 3, 4, 5, 10)),
+    'milliseconds',
+    '()'
+  )).toBe(false, 'start and end are excluded, is not between')
+
+  expect(m.isBetween(
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    'milliseconds',
+    '()'
+  )).toBe(false, 'start and end are excluded, should fail on same start/end date.')
+
+  expect(m.isBetween(
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2012, 3, 2, 3, 4, 5, 10)),
+    'milliseconds',
+    '(]'
+  )).toBe(false, 'start is excluded and end is included should fail on same start date')
+
+  expect(m.isBetween(
+    dayjs(new Date(2010, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    'milliseconds',
+    '(]'
+  )).toBe(true, 'start is excluded and end is included should succeed on end date')
+
+  expect(m.isBetween(
+    dayjs(new Date(2010, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2012, 3, 2, 3, 4, 5, 10)),
+    'milliseconds',
+    '(]'
+  )).toBe(true, 'start is excluded and end is included, is between')
+
+  expect(m.isBetween(
+    dayjs(new Date(2009, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2010, 3, 2, 3, 4, 5, 10)),
+    'milliseconds',
+    '(]'
+  )).toBe(false, 'start is excluded and end is included, is not between')
+
+  expect(m.isBetween(
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    'milliseconds',
+    '(]'
+  )).toBe(false, 'start is excluded and end is included, should fail on same start/end date.')
+
+  expect(m.isBetween(
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2012, 3, 2, 3, 4, 5, 10)),
+    'milliseconds',
+    '[)'
+  )).toBe(true, 'start is included and end is excluded should succeed on same start date')
+
+  expect(m.isBetween(
+    dayjs(new Date(2010, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    'milliseconds',
+    '[)'
+  )).toBe(false, 'start is included and end is excluded should fail on same end date')
+
+  expect(m.isBetween(
+    dayjs(new Date(2010, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2012, 3, 2, 3, 4, 5, 10)),
+    'milliseconds',
+    '[)'
+  )).toBe(true, 'start is included and end is excluded, is between')
+
+  expect(m.isBetween(
+    dayjs(new Date(2009, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2010, 3, 2, 3, 4, 5, 10)),
+    'milliseconds',
+    '[)'
+  )).toBe(false, 'start is included and end is excluded, is not between')
+
+  expect(m.isBetween(
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    'milliseconds',
+    '[)'
+  )).toBe(false, 'start is included and end is excluded, should fail on same end and start date')
+
+  expect(m.isBetween(
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2012, 3, 2, 3, 4, 5, 10)),
+    'milliseconds',
+    '[]'
+  )).toBe(true, 'start and end inclusive should succeed on same start date')
+
+  expect(m.isBetween(
+    dayjs(new Date(2010, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    'milliseconds',
+    '[]'
+  )).toBe(true, 'start and end inclusive should succeed on same end date')
+
+  expect(m.isBetween(
+    dayjs(new Date(2010, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2012, 3, 2, 3, 4, 5, 10)),
+    'milliseconds',
+    '[]'
+  )).toBe(true, 'start and end inclusive, is between')
+
+  expect(m.isBetween(
+    dayjs(new Date(2009, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2010, 3, 2, 3, 4, 5, 10)),
+    'milliseconds',
+    '[]'
+  )).toBe(false, 'start and end inclusive, is not between')
+
+  expect(m.isBetween(
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    dayjs(new Date(2011, 3, 2, 3, 4, 5, 10)),
+    'milliseconds',
+    '[]'
+  )).toBe(true, 'start and end inclusive, should handle same end and start date')
+
+  expect(+m).toEqual(+mCopy, 'isBetween second should not change moment')
+})