Skip to content

Commit f343206

Browse files
Kreozotiamkun
authored andcommitted
fix: Parse month string 'MMMM MMM (February, Feb)' in customParseFormat (#457)
1 parent 44e9680 commit f343206

File tree

10 files changed

+132
-24
lines changed

10 files changed

+132
-24
lines changed

.babelrc babel.config.js

+20-20
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,20 @@
1-
{
2-
"env": {
3-
"test": {
4-
"presets": [
5-
"@babel/preset-env"
6-
]
7-
},
8-
"build": {
9-
"presets": [
10-
[
11-
"@babel/preset-env",
12-
{
13-
"modules": false,
14-
"loose": true
15-
}
16-
]
17-
]
18-
}
19-
}
20-
}
1+
module.exports = {
2+
"env": {
3+
"test": {
4+
"presets": [
5+
"@babel/preset-env"
6+
]
7+
},
8+
"build": {
9+
"presets": [
10+
[
11+
"@babel/preset-env",
12+
{
13+
"modules": false,
14+
"loose": true
15+
}
16+
]
17+
]
18+
}
19+
}
20+
};

docs/en/Plugin.md

+3
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,9 @@ dayjs.extend(customParseFormat)
260260

261261
dayjs('05/02/69 1:02:03 PM -05:00', 'MM/DD/YY H:mm:ss A Z')
262262
// Returns an instance containing '1969-05-02T18:02:03.000Z'
263+
264+
dayjs('2018 Enero 15', { format: 'YYYY MMMM DD', locale: es })
265+
// Returns an instance containing '2018-01-15T00:00:00.000Z'
263266
```
264267

265268
#### List of all available format tokens

docs/es-es/Plugin.md

+17
Original file line numberDiff line numberDiff line change
@@ -247,6 +247,23 @@ dayjs.extend(quarterOfYear)
247247
dayjs('2010-04-01').quarter() // 2
248248
```
249249

250+
### CustomParseFormat
251+
- CustomParseFormat extends `dayjs()` constructor to support custom formats of input strings.
252+
253+
To escape characters, wrap them in square brackets (e.g. `[G]`). Punctuation symbols (-:/.()) do not need to be wrapped.
254+
255+
```javascript
256+
import customParseFormat from 'dayjs/plugin/customParseFormat'
257+
258+
dayjs.extend(customParseFormat)
259+
260+
dayjs('05/02/69 1:02:03 PM -05:00', 'MM/DD/YY H:mm:ss A Z')
261+
// Returns an instance containing '1969-05-02T18:02:03.000Z'
262+
263+
dayjs('2018 Enero 15', { format: 'YYYY MMMM DD', locale: es })
264+
// Returns an instance containing '2018-01-15T00:00:00.000Z'
265+
```
266+
250267
#### List of all available format tokens
251268

252269
| Format | Output | Description |

docs/ja/Plugin.md

+3
Original file line numberDiff line numberDiff line change
@@ -269,6 +269,9 @@ dayjs.extend(customParseFormat)
269269

270270
dayjs('05/02/69 1:02:03 PM -05:00', 'MM/DD/YY H:mm:ss A Z')
271271
// Returns an instance containing '1969-05-02T18:02:03.000Z'
272+
273+
dayjs('2018 5月 15', { format: 'YYYY MMMM DD', locale: ja })
274+
// Returns an instance containing '2018-05-15T00:00:00.000Z'
272275
```
273276

274277
#### List of all available format tokens

docs/ko/Plugin.md

+3
Original file line numberDiff line numberDiff line change
@@ -261,6 +261,9 @@ dayjs.extend(customParseFormat)
261261

262262
dayjs('05/02/69 1:02:03 PM -05:00', 'MM/DD/YY H:mm:ss A Z')
263263
// Returns an instance containing '1969-05-02T18:02:03.000Z'
264+
265+
dayjs('2018 5월 15', { format: 'YYYY MMMM DD', locale: ko })
266+
// Returns an instance containing '2018-05-15T00:00:00.000Z'
264267
```
265268

266269
#### List of all available format tokens

docs/pt-br/Plugin.md

+3
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,9 @@ dayjs.extend(customParseFormat)
260260

261261
dayjs('05/02/69 1:02:03 PM -05:00', 'MM/DD/YY H:mm:ss A Z')
262262
// Returns an instance containing '1969-05-02T18:02:03.000Z'
263+
264+
dayjs('2018 Fevereiro 15', { format: 'YYYY MMMM DD', locale: pt_br })
265+
// Returns an instance containing '2018-02-15T00:00:00.000Z'
263266
```
264267

265268
#### List of all available format tokens

docs/zh-cn/Plugin.md

+3
Original file line numberDiff line numberDiff line change
@@ -260,6 +260,9 @@ dayjs.extend(customParseFormat)
260260

261261
dayjs('05/02/69 1:02:03 PM -05:00', 'MM/DD/YY H:mm:ss A Z')
262262
// Returns an instance containing '1969-05-02T18:02:03.000Z'
263+
264+
dayjs('2018 五月 15', { format: 'YYYY MMMM DD', locale: zh_cn })
265+
// Returns an instance containing '2018-05-15T00:00:00.000Z'
263266
```
264267

265268
#### List of all available format tokens

src/index.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -61,15 +61,16 @@ const parseDate = (date) => {
6161

6262
class Dayjs {
6363
constructor(cfg) {
64+
this.$L = this.$L || parseLocale(cfg.locale, null, true) || L
6465
this.parse(cfg) // for plugin
6566
}
6667

6768
parse(cfg) {
6869
this.$d = parseDate(cfg.date)
69-
this.init(cfg)
70+
this.init()
7071
}
7172

72-
init(cfg) {
73+
init() {
7374
const { $d } = this
7475
this.$y = $d.getFullYear()
7576
this.$M = $d.getMonth()
@@ -79,7 +80,6 @@ class Dayjs {
7980
this.$m = $d.getMinutes()
8081
this.$s = $d.getSeconds()
8182
this.$ms = $d.getMilliseconds()
82-
this.$L = this.$L || parseLocale(cfg.locale, null, true) || L
8383
}
8484

8585
// eslint-disable-next-line class-methods-use-this

src/plugin/customParseFormat/index.js

+23-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
const formattingTokens = /(\[[^[]*\])|([-:/.()\s]+)|(A|a|YYYY|YY?|MM?|DD?|hh?|HH?|mm?|ss?|S{1,3}|z|ZZ?)/g
1+
const formattingTokens = /(\[[^[]*\])|([-:/.()\s]+)|(A|a|YYYY|YY?|MM?M?M?|DD?|hh?|HH?|mm?|ss?|S{1,3}|z|ZZ?)/g
22

33
const match1 = /\d/ // 0 - 9
44
const match2 = /\d\d/ // 00 - 99
@@ -9,6 +9,9 @@ const matchUpperCaseAMPM = /[AP]M/
99
const matchLowerCaseAMPM = /[ap]m/
1010
const matchSigned = /[+-]?\d+/ // -inf - inf
1111
const matchOffset = /[+-]\d\d:?\d\d/ // +00:00 -00:00 +0000 or -0000
12+
const matchWord = /\d*[^\s\d]+/ // Word
13+
14+
let locale
1215

1316
function offsetFromString(string) {
1417
const parts = string.match(/([+-]|\d\d)/g)
@@ -55,6 +58,24 @@ const expressions = {
5558
DD: [match2, addInput('day')],
5659
M: [match1to2, addInput('month')],
5760
MM: [match2, addInput('month')],
61+
MMM: [matchWord, function (input) {
62+
const { months, monthsShort } = locale
63+
const matchIndex = monthsShort
64+
? monthsShort.findIndex(month => month === input)
65+
: months.findIndex(month => month.substr(0, 3) === input)
66+
if (matchIndex < 0) {
67+
throw new Error()
68+
}
69+
this.month = matchIndex + 1
70+
}],
71+
MMMM: [matchWord, function (input) {
72+
const { months } = locale
73+
const matchIndex = months.indexOf(input)
74+
if (matchIndex < 0) {
75+
throw new Error()
76+
}
77+
this.month = matchIndex + 1
78+
}],
5879
Y: [matchSigned, addInput('year')],
5980
YY: [match2, function (input) {
6081
input = +input
@@ -144,6 +165,7 @@ export default (o, C) => {
144165
proto.parse = function (cfg) {
145166
const { date: input, format } = cfg
146167
if (format) {
168+
locale = this.$locale()
147169
this.$d = parseFormattedInput(input, format)
148170
this.init(cfg)
149171
} else {

test/plugin/customParseFormat.test.js

+54
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ import MockDate from 'mockdate'
22
import moment from 'moment'
33
import dayjs from '../../src'
44
import customParseFormat from '../../src/plugin/customParseFormat'
5+
import uk from '../../src/locale/uk'
56

67
dayjs.extend(customParseFormat)
78

@@ -84,3 +85,56 @@ it('fails with an invalid format', () => {
8485
expect(dayjs(input, format).format().toLowerCase())
8586
.toBe(moment(input, format).format().toLowerCase())
8687
})
88+
89+
it('parse month from string', () => {
90+
const input = '2018 February 03'
91+
const format = 'YYYY MMMM DD'
92+
expect(dayjs(input, format).valueOf()).toBe(moment(input, format).valueOf())
93+
})
94+
95+
it('parse month from short string', () => {
96+
const input = '2018 Feb 03'
97+
const format = 'YYYY MMM DD'
98+
expect(dayjs(input, format).valueOf()).toBe(moment(input, format).valueOf())
99+
})
100+
101+
it('parse month from string with locale in config', () => {
102+
const input = '2018 лютий 03'
103+
const format = 'YYYY MMMM DD'
104+
105+
expect(dayjs(input, { format, locale: uk }).valueOf()).toBe(moment(input, format, 'uk').valueOf())
106+
})
107+
108+
it('parse month from short string with locale in config', () => {
109+
const input = '2018 трав 03'
110+
const format = 'YYYY MMM DD'
111+
expect(dayjs(input, { format, locale: uk }).valueOf()).toBe(moment(input, format, 'uk').valueOf())
112+
})
113+
114+
it('return Invalid Date when parse corrupt string', () => {
115+
const input = '2018 Turnip 03'
116+
const format = 'YYYY MMMM DD'
117+
expect(dayjs(input, format).format()).toBe('Invalid Date')
118+
})
119+
120+
it('return Invalid Date when parse corrupt short string', () => {
121+
const input = '2018 Dog 03'
122+
const format = 'YYYY MMM DD'
123+
expect(dayjs(input, format).format()).toBe('Invalid Date')
124+
})
125+
126+
it('correctly parse month from string after changing locale globally', () => {
127+
const input = '2018 лютий 03'
128+
const format = 'YYYY MMMM DD'
129+
130+
const dayjsLocale = dayjs().$locale()
131+
const momentLocale = moment.locale()
132+
try {
133+
dayjs.locale(uk)
134+
moment.locale('uk')
135+
expect(dayjs(input, format).valueOf()).toBe(moment(input, format).valueOf())
136+
} finally {
137+
dayjs.locale(dayjsLocale)
138+
moment.locale(momentLocale)
139+
}
140+
})

0 commit comments

Comments
 (0)