Repository: iamkun/dayjs

Problem statement:
Parsing with Unix Timestamp tokens (X/x) and other visual tokens in strict mode results in Invalid Date
**Describe the bug**
When X/x token is used and there are visual/escaped tokens in strict mode you get `Invalid Date`, best described with this code snippet and log result:
<details><summary>source: </summary> 

```js
const dayjs = require('dayjs');
dayjs.extend(require('dayjs/plugin/customParseFormat'))
dayjs.extend(require('dayjs/plugin/advancedFormat'))

console.log(
  [
    [ 'now format',
      () => dayjs().format('x'),
      () => dayjs().format('X'),
    ],

    [ 'x',
      () => dayjs('/Date(1623787200000)/', '/[Date](x)/').format('/[Date](x)/'),
      () => dayjs('/1623787200000/', '/X/').format('/[Date](X)/'),
      () => dayjs('--1623787200000--', '--X--').format('/[Date](X)/'),
      () => dayjs('1623787200000', 'x').format('x'),
      () => dayjs('1623787200000', 'x').format('YYYY-MM-DD'),
    ],

    [ 'X',
      () => dayjs('/Date(1623787200)/', '/[Date](X)/').format('/[Date](X)/'),
      () => dayjs('/1623787200/', '/X/').format('/[Date](X)/'),
      () => dayjs('--1623787200--', '--X--').format('/[Date](X)/'),
      () => dayjs('1623787200', 'X').format('X'),
      () => dayjs('1623787200', 'X').format('YYYY-MM-DD'),
    ],

    [ 'x STRICT',
      () => dayjs('/Date(1623787200000)/', '/[Date](x)/', true).format('/[Date](x)/'),
      () => dayjs('/1623787200000/', '/x/', true).format('/[Date](x)/'),
      () => dayjs('--1623787200000--', '--x--', true).format('/[Date](x)/'),
      () => dayjs('1623787200000', 'x', true).format('x'),
      () => dayjs('1623787200000', 'x', true).format('YYYY-MM-DD'),
    ],

    [ 'X STRICT',
      () => dayjs('/Date(1623787200)/', '/[Date](X)/', true).format('/[Date](X)/'),
      () => dayjs('/1623787200/', '/X/', true).format('/[Date](X)/'),
      () => dayjs('--1623787200--', '--X--', true).format('/[Date](X)/'),
      () => dayjs('1623787200', 'X', true).format('X'),
      () => dayjs('1623787200', 'X', true).format('YYYY-MM-DD'),
    ],
  ]
    .map(
      ([name, ...cases]) =>
        '\n// ' +
        name +
        '\n' +
        cases.map((f) => `${f.toString().substring(6)} // ${f()}`).join('\n')
    )
    .join('\n')
);
```
</details>

output:
```js
// now format
dayjs().format('x') // 1625563406782
dayjs().format('X') // 1625563406

// x
dayjs('/Date(1623787200000)/', '/[Date](x)/').format('/[Date](x)/') // /Date(1625515200000)/
dayjs('/1623787200000/', '/X/').format('/[Date](X)/') // /Date(1625515200)/
dayjs('--1623787200000--', '--X--').format('/[Date](X)/') // /Date(1625515200)/
dayjs('1623787200000', 'x').format('x') // 1623787200000
dayjs('1623787200000', 'x').format('YYYY-MM-DD') // 2021-06-16

// X
dayjs('/Date(1623787200)/', '/[Date](X)/').format('/[Date](X)/') // /Date(1625515200)/
dayjs('/1623787200/', '/X/').format('/[Date](X)/') // /Date(1625515200)/
dayjs('--1623787200--', '--X--').format('/[Date](X)/') // /Date(1625515200)/
dayjs('1623787200', 'X').format('X') // 1623787200
dayjs('1623787200', 'X').format('YYYY-MM-DD') // 2021-06-16

// x STRICT
dayjs('/Date(1623787200000)/', '/[Date](x)/', true).format('/[Date](x)/') // Invalid Date
dayjs('/1623787200000/', '/x/', true).format('/[Date](x)/') // Invalid Date
dayjs('--1623787200000--', '--x--', true).format('/[Date](x)/') // Invalid Date
dayjs('1623787200000', 'x', true).format('x') // 1623787200000
dayjs('1623787200000', 'x', true).format('YYYY-MM-DD') // 2021-06-16

// X STRICT
dayjs('/Date(1623787200)/', '/[Date](X)/', true).format('/[Date](X)/') // Invalid Date
dayjs('/1623787200/', '/X/', true).format('/[Date](X)/') // Invalid Date
dayjs('--1623787200--', '--X--', true).format('/[Date](X)/') // Invalid Date
dayjs('1623787200', 'X', true).format('X') // 1623787200
dayjs('1623787200', 'X', true).format('YYYY-MM-DD') // 2021-06-16
```
**Expected behavior**
not to get `Invalid Date`

**Information**
 - Day.js Version 1.10.6
 - Node version: 14.17.0
 - Time zone: [e.g. GMT +4:00]


related https://github.com/iamkun/dayjs/issues/1533  #1567


Hints:
I see.

Cause x X format is supported via advancedFormat plugin, you may enable it to use in strict mode 

https://day.js.org/docs/en/plugin/advanced-format
It's enabled. look at the collapsed "source" section of the issue I have this there:
```js
const dayjs = require('dayjs');
dayjs.extend(require('dayjs/plugin/customParseFormat'))
dayjs.extend(require('dayjs/plugin/advancedFormat'))
```

Patch:
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
@@ -232,7 +232,10 @@ export default (o, C, d) => {
       this.$d = parseFormattedInput(date, format, utc)
       this.init()
       if (pl && pl !== true) this.$L = this.locale(pl).$L
-      if (isStrict && date !== this.format(format)) {
+      // use != to treat
+      // input number 1410715640579 and format string '1410715640579' equal
+      // eslint-disable-next-line eqeqeq
+      if (isStrict && date != this.format(format)) {
         this.$d = new Date('')
       }
       // reset global locale to make parallel unit test


Test patch:
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
@@ -5,6 +5,7 @@ import '../../src/locale/ru'
 import uk from '../../src/locale/uk'
 import '../../src/locale/zh-cn'
 import customParseFormat from '../../src/plugin/customParseFormat'
+import advancedFormat from '../../src/plugin/advancedFormat'
 import localizedFormats from '../../src/plugin/localizedFormat'
 
 dayjs.extend(customParseFormat)
@@ -376,4 +377,8 @@ it('parse X x', () => {
   const input2 = '1410715640579'
   const format2 = 'x'
   expect(dayjs(input2, format2).valueOf()).toBe(moment(input2, format2).valueOf())
+
+  // x X starct parse requires advancedFormat plugin
+  dayjs.extend(advancedFormat)
+  expect(dayjs(input2, format2, true).valueOf()).toBe(moment(input2, format2, true).valueOf())
 })