feat: #965 add duration.format()
Heya! This should close #965. Key things to note:
* Is it okay to change REGEX_FORMAT to accept singular Ys? From what I've seen in the code in `src/index.js`, it seems like the original .format() ignores regex matches which are not in the `const matches = { ... }` variable, so this should be safe to do.
* Single Y would be very useful, because you don't often display durations which has double-digit years. So you can do `dayjs.duration(15, 'years').format('Y years has passed') === '15 years has passed'`

Also, difference between the original `dayjs.format()` and this format:
* No 'A'/'a' token (because you can't reason about meridians in durations)
* No 'dddd' token
* No 'ZZ' token

Not sure why commit 6545739 got dragged along as a change in the diff, but doesn't seem like any files are explicitly changed after I resync'd with upstream, so...
I have tried o use this but it does not work 

```
import dayjs from 'dayjs';
import duration from 'dayjs/plugin/duration';
dayjs.extend(duration);
const toTimeFormat = (milliseconds: number) => {
  return dayjs.duration(milliseconds).format('HH:mm:ss')
};
```

How we can format the duration in dayjs.
diff --git a/src/constant.js b/src/constant.js
index a4f034fa2..22c1319e0 100644
--- a/src/constant.js
+++ b/src/constant.js
@@ -27,4 +27,4 @@ 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+)?$/
-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 REGEX_FORMAT = /\[([^\]]+)]|Y{1,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
diff --git a/src/plugin/duration/index.js b/src/plugin/duration/index.js
index 50f660484..02f12bcb4 100644
--- a/src/plugin/duration/index.js
+++ b/src/plugin/duration/index.js
@@ -1,4 +1,4 @@
-import { MILLISECONDS_A_DAY, MILLISECONDS_A_HOUR, MILLISECONDS_A_MINUTE, MILLISECONDS_A_SECOND, MILLISECONDS_A_WEEK } from '../../constant'
+import { MILLISECONDS_A_DAY, MILLISECONDS_A_HOUR, MILLISECONDS_A_MINUTE, MILLISECONDS_A_SECOND, MILLISECONDS_A_WEEK, REGEX_FORMAT } from '../../constant'
 
 const MILLISECONDS_A_YEAR = MILLISECONDS_A_DAY * 365
 const MILLISECONDS_A_MONTH = MILLISECONDS_A_DAY * 30
@@ -105,6 +105,27 @@ class Duration {
     return this.toISOString()
   }
 
+  format(formatStr) {
+    const str = formatStr || 'YYYY-MM-DDTHH:mm:ss'
+    const matches = {
+      Y: this.$d.years,
+      YY: $u.s(this.$d.years, 2, '0'),
+      YYYY: $u.s(this.$d.years, 4, '0'),
+      M: this.$d.months,
+      MM: $u.s(this.$d.months, 2, '0'),
+      D: this.$d.days,
+      DD: $u.s(this.$d.days, 2, '0'),
+      H: this.$d.hours,
+      HH: $u.s(this.$d.hours, 2, '0'),
+      m: this.$d.minutes,
+      mm: $u.s(this.$d.minutes, 2, '0'),
+      s: this.$d.seconds,
+      ss: $u.s(this.$d.seconds, 2, '0'),
+      SSS: $u.s(this.$d.milliseconds, 3, '0')
+    }
+    return str.replace(REGEX_FORMAT, (match, $1) => $1 || String(matches[match]))
+  }
+
   as(unit) {
     return this.$ms / (unitToMS[prettyUnit(unit)])
   }
diff --git a/types/plugin/duration.d.ts b/types/plugin/duration.d.ts
index c09dc9f09..3695eeaaf 100644
--- a/types/plugin/duration.d.ts
+++ b/types/plugin/duration.d.ts
@@ -51,6 +51,8 @@ declare namespace plugin {
 
     toISOString(): string
 
+    format(formatStr?: string): string
+
     locale(locale: string): Duration
   }
 }

diff --git a/test/plugin/duration.test.js b/test/plugin/duration.test.js
index 5e5447658..15e60b925 100644
--- a/test/plugin/duration.test.js
+++ b/test/plugin/duration.test.js
@@ -208,3 +208,27 @@ describe('prettyUnit', () => {
     m: 12
   }).toISOString()).toBe('P12MT12M')
 })
+
+describe('Format', () => {
+  test('no formatStr', () => {
+    const d = dayjs.duration(15, 'seconds')
+      .add(13, 'hours')
+      .add(35, 'minutes')
+      .add(16, 'days')
+      .add(10, 'months')
+      .add(22, 'years')
+    expect(d.format()).toBe('0022-10-16T13:35:15')
+  })
+
+  test('with formatStr for all tokens', () => {
+    const d = dayjs.duration(1, 'seconds')
+      .add(8, 'hours')
+      .add(5, 'minutes')
+      .add(6, 'days')
+      .add(9, 'months')
+      .add(2, 'years')
+      .add(10, 'milliseconds')
+    expect(d.format('Y/YY.YYYYTESTM:MM:D:DD:H:HH:m:mm:s:ss:SSS'))
+      .toBe('2/02.0002TEST9:09:6:06:8:08:5:05:1:01:010')
+  })
+})

{"test/plugin/duration.test.js": {"run": "PASS", "test": "FAIL", "fix": "PASS"}}
{"test/timezone.test.js:Add Time days (DST)": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/locale/de.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/locale/sk.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/advancedFormat.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/weekYear.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/timezone.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/isSameOrBefore.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/pluralGetSet.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/timezone.test.js:Diff (DST)": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/locale/keys.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/utils.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/relativeTime.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/parse.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/localizedFormat.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/updateLocale.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/constructor.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/weekday.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/isLeapYear.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/query.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/localeData.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/timezone.test.js:UTC diff in DST": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/locale/zh.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/declarations.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/timezone.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/locale/ru.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/dayOfYear.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/timezone.test.js:UTC add day in DST": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/manipulate.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/locale/cs.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/locale/en.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/get-set.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/utc.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/quarterOfYear.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/objectSupport.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/locale/fi.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/locale/sv.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/toArray.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/timezone.test.js:Utc Offset": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/utc-utcOffset.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/locale/sr-cyrl.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/locale/br.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/isMoment.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/isYesterday.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/locale/pl.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/toObject.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/locale/sr.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/isSameOrAfter.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/weekOfYear.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/comparison.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/calendar.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/isTomorrow.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/locale/hu.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/locale/et.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/timezone.test.js:UTC and utcOffset": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/arraySupport.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/isToday.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/locale/hr.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/locale.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/badMutable.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/customParseFormat.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/isoWeek.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/minMax.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/isoWeeksInYear.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/buddhistEra.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/locale/uk.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/display.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/locale/lt.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/locale/zh-cn.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/isBetween.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}}
{"test/plugin/duration.test.js": {"run": "PASS", "test": "FAIL", "fix": "PASS"}}
{"passed_count": 71, "failed_count": 0, "skipped_count": 0, "passed_tests": ["test/timezone.test.js:Add Time days (DST)", "test/plugin.test.js", "test/get-set.test.js", "test/locale/de.test.js", "test/plugin/utc.test.js", "test/plugin/quarterOfYear.test.js", "test/plugin/objectSupport.test.js", "test/locale/fi.test.js", "test/locale/sk.test.js", "test/locale/sv.test.js", "test/plugin/advancedFormat.test.js", "test/plugin/toArray.test.js", "test/plugin/weekYear.test.js", "test/timezone.test.js", "test/timezone.test.js:Utc Offset", "test/plugin/isSameOrBefore.test.js", "test/plugin/pluralGetSet.test.js", "test/timezone.test.js:Diff (DST)", "test/plugin/utc-utcOffset.test.js", "test/locale/sr-cyrl.test.js", "test/utils.test.js", "test/locale/br.test.js", "test/plugin/relativeTime.test.js", "test/parse.test.js", "test/locale/keys.test.js", "test/plugin/isMoment.test.js", "test/plugin/isYesterday.test.js", "test/locale/pl.test.js", "test/plugin/toObject.test.js", "test/locale/sr.test.js", "test/plugin/localizedFormat.test.js", "test/plugin/updateLocale.test.js", "test/constructor.test.js", "test/plugin/weekday.test.js", "test/plugin/isSameOrAfter.test.js", "test/plugin/weekOfYear.test.js", "test/plugin/isLeapYear.test.js", "test/comparison.test.js", "test/query.test.js", "test/plugin/localeData.test.js", "test/plugin/calendar.test.js", "test/plugin/isTomorrow.test.js", "test/locale/hu.test.js", "test/timezone.test.js:UTC diff in DST", "test/locale/et.test.js", "test/timezone.test.js:UTC and utcOffset", "test/plugin/arraySupport.test.js", "test/locale/zh.test.js", "test/plugin/isToday.test.js", "test/plugin/declarations.test.js", "test/locale/hr.test.js", "test/plugin/timezone.test.js", "test/locale.test.js", "test/plugin/badMutable.test.js", "test/plugin/customParseFormat.test.js", "test/locale/ru.test.js", "test/plugin/duration.test.js", "test/plugin/isoWeek.test.js", "test/plugin/minMax.test.js", "test/plugin/dayOfYear.test.js", "test/plugin/isoWeeksInYear.test.js", "test/timezone.test.js:UTC add day in DST", "test/manipulate.test.js", "test/plugin/buddhistEra.test.js", "test/locale/uk.test.js", "test/display.test.js", "test/locale/cs.test.js", "test/locale/lt.test.js", "test/locale/zh-cn.test.js", "test/locale/en.test.js", "test/plugin/isBetween.test.js"], "failed_tests": [], "skipped_tests": []}
{"passed_count": 70, "failed_count": 1, "skipped_count": 0, "passed_tests": ["test/timezone.test.js:Add Time days (DST)", "test/locale/de.test.js", "test/plugin.test.js", "test/get-set.test.js", "test/plugin/utc.test.js", "test/plugin/quarterOfYear.test.js", "test/plugin/objectSupport.test.js", "test/locale/fi.test.js", "test/locale/sk.test.js", "test/locale/sv.test.js", "test/plugin/advancedFormat.test.js", "test/plugin/weekYear.test.js", "test/plugin/toArray.test.js", "test/timezone.test.js", "test/timezone.test.js:Utc Offset", "test/plugin/isSameOrBefore.test.js", "test/plugin/pluralGetSet.test.js", "test/timezone.test.js:Diff (DST)", "test/plugin/utc-utcOffset.test.js", "test/locale/sr-cyrl.test.js", "test/utils.test.js", "test/locale/br.test.js", "test/plugin/relativeTime.test.js", "test/parse.test.js", "test/locale/keys.test.js", "test/plugin/isMoment.test.js", "test/plugin/isYesterday.test.js", "test/locale/pl.test.js", "test/plugin/toObject.test.js", "test/locale/sr.test.js", "test/plugin/localizedFormat.test.js", "test/plugin/updateLocale.test.js", "test/constructor.test.js", "test/plugin/weekday.test.js", "test/plugin/isSameOrAfter.test.js", "test/plugin/weekOfYear.test.js", "test/plugin/isLeapYear.test.js", "test/comparison.test.js", "test/query.test.js", "test/plugin/localeData.test.js", "test/locale/et.test.js", "test/locale/hu.test.js", "test/plugin/calendar.test.js", "test/timezone.test.js:UTC diff in DST", "test/plugin/isTomorrow.test.js", "test/timezone.test.js:UTC and utcOffset", "test/plugin/arraySupport.test.js", "test/locale/zh.test.js", "test/plugin/isToday.test.js", "test/plugin/declarations.test.js", "test/locale/hr.test.js", "test/plugin/timezone.test.js", "test/plugin/badMutable.test.js", "test/locale.test.js", "test/plugin/customParseFormat.test.js", "test/locale/ru.test.js", "test/plugin/isoWeek.test.js", "test/plugin/minMax.test.js", "test/plugin/dayOfYear.test.js", "test/plugin/isoWeeksInYear.test.js", "test/timezone.test.js:UTC add day in DST", "test/plugin/buddhistEra.test.js", "test/manipulate.test.js", "test/locale/cs.test.js", "test/locale/uk.test.js", "test/display.test.js", "test/locale/lt.test.js", "test/locale/zh-cn.test.js", "test/locale/en.test.js", "test/plugin/isBetween.test.js"], "failed_tests": ["test/plugin/duration.test.js"], "skipped_tests": []}
{"passed_count": 71, "failed_count": 0, "skipped_count": 0, "passed_tests": ["test/timezone.test.js:Add Time days (DST)", "test/plugin.test.js", "test/locale/de.test.js", "test/get-set.test.js", "test/plugin/utc.test.js", "test/plugin/quarterOfYear.test.js", "test/plugin/objectSupport.test.js", "test/locale/fi.test.js", "test/locale/sk.test.js", "test/locale/sv.test.js", "test/plugin/advancedFormat.test.js", "test/plugin/weekYear.test.js", "test/plugin/toArray.test.js", "test/timezone.test.js", "test/timezone.test.js:Utc Offset", "test/plugin/isSameOrBefore.test.js", "test/plugin/pluralGetSet.test.js", "test/timezone.test.js:Diff (DST)", "test/plugin/utc-utcOffset.test.js", "test/locale/sr-cyrl.test.js", "test/utils.test.js", "test/locale/br.test.js", "test/plugin/relativeTime.test.js", "test/parse.test.js", "test/locale/keys.test.js", "test/plugin/isMoment.test.js", "test/plugin/isYesterday.test.js", "test/locale/pl.test.js", "test/plugin/toObject.test.js", "test/locale/sr.test.js", "test/plugin/localizedFormat.test.js", "test/plugin/updateLocale.test.js", "test/constructor.test.js", "test/plugin/weekday.test.js", "test/plugin/isSameOrAfter.test.js", "test/plugin/weekOfYear.test.js", "test/comparison.test.js", "test/plugin/isLeapYear.test.js", "test/query.test.js", "test/plugin/localeData.test.js", "test/plugin/isTomorrow.test.js", "test/locale/hu.test.js", "test/plugin/calendar.test.js", "test/timezone.test.js:UTC diff in DST", "test/locale/et.test.js", "test/timezone.test.js:UTC and utcOffset", "test/plugin/arraySupport.test.js", "test/locale/zh.test.js", "test/plugin/isToday.test.js", "test/plugin/declarations.test.js", "test/locale/hr.test.js", "test/plugin/timezone.test.js", "test/locale.test.js", "test/plugin/badMutable.test.js", "test/plugin/customParseFormat.test.js", "test/locale/ru.test.js", "test/plugin/duration.test.js", "test/plugin/isoWeek.test.js", "test/plugin/dayOfYear.test.js", "test/plugin/minMax.test.js", "test/plugin/isoWeeksInYear.test.js", "test/timezone.test.js:UTC add day in DST", "test/manipulate.test.js", "test/display.test.js", "test/locale/uk.test.js", "test/plugin/buddhistEra.test.js", "test/locale/cs.test.js", "test/locale/lt.test.js", "test/locale/zh-cn.test.js", "test/locale/en.test.js", "test/plugin/isBetween.test.js"], "failed_tests": [], "skipped_tests": []}