Skip to content

Commit 8f6f63c

Browse files
authored
feat(): add CustomParseFormat plugin and QuarterOfYear plugin (#450)
* refactor: move to single file * refactor: update refactor
1 parent c0ebac0 commit 8f6f63c

File tree

2 files changed

+138
-139
lines changed

2 files changed

+138
-139
lines changed

src/plugin/customParseFormat/index.js

+138-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,141 @@
1-
import parseFormattedInput from './parseFormattedInput'
1+
const formattingTokens = /(\[[^[]*\])|([-:/.()\s]+)|(A|a|YYYY|YY?|MM?|DD?|hh?|HH?|mm?|ss?|S{1,3}|z|ZZ?)/g
2+
3+
const match1 = /\d/ // 0 - 9
4+
const match2 = /\d\d/ // 00 - 99
5+
const match3 = /\d{3}/ // 000 - 999
6+
const match4 = /\d{4}/ // 0000 - 9999
7+
const match1to2 = /\d\d?/ // 0 - 99
8+
const matchUpperCaseAMPM = /[AP]M/
9+
const matchLowerCaseAMPM = /[ap]m/
10+
const matchSigned = /[+-]?\d+/ // -inf - inf
11+
const matchOffset = /[+-]\d\d:?\d\d/ // +00:00 -00:00 +0000 or -0000
12+
13+
function offsetFromString(string) {
14+
const parts = string.match(/([+-]|\d\d)/g)
15+
const minutes = +(parts[1] * 60) + +parts[2]
16+
return minutes === 0 ? 0 : parts[0] === '+' ? -minutes : minutes // eslint-disable-line no-nested-ternary
17+
}
18+
19+
const addInput = function (property) {
20+
return function (input) {
21+
this[property] = +input
22+
}
23+
}
24+
25+
const zoneExpressions = [matchOffset, function (input) {
26+
const zone = this.zone || (this.zone = {})
27+
zone.offset = offsetFromString(input)
28+
}]
29+
30+
const expressions = {
31+
A: [matchUpperCaseAMPM, function (input) {
32+
this.afternoon = input === 'PM'
33+
}],
34+
a: [matchLowerCaseAMPM, function (input) {
35+
this.afternoon = input === 'pm'
36+
}],
37+
S: [match1, function (input) {
38+
this.milliseconds = +input * 100
39+
}],
40+
SS: [match2, function (input) {
41+
this.milliseconds = +input * 10
42+
}],
43+
SSS: [match3, function (input) {
44+
this.milliseconds = +input
45+
}],
46+
s: [match1to2, addInput('seconds')],
47+
ss: [match2, addInput('seconds')],
48+
m: [match1to2, addInput('minutes')],
49+
mm: [match2, addInput('minutes')],
50+
H: [match1to2, addInput('hours')],
51+
h: [match1to2, addInput('hours')],
52+
HH: [match2, addInput('hours')],
53+
hh: [match2, addInput('hours')],
54+
D: [match1to2, addInput('day')],
55+
DD: [match2, addInput('day')],
56+
M: [match1to2, addInput('month')],
57+
MM: [match2, addInput('month')],
58+
Y: [matchSigned, addInput('year')],
59+
YY: [match2, function (input) {
60+
input = +input
61+
this.year = input + (input > 68 ? 1900 : 2000)
62+
}],
63+
YYYY: [match4, addInput('year')],
64+
Z: zoneExpressions,
65+
ZZ: zoneExpressions
66+
}
67+
68+
function correctHours(time) {
69+
const { afternoon } = time
70+
if (afternoon !== undefined) {
71+
const { hours } = time
72+
if (afternoon) {
73+
if (hours < 12) {
74+
time.hours += 12
75+
}
76+
} else if (hours === 12) {
77+
time.hours = 0
78+
}
79+
delete time.afternoon
80+
}
81+
}
82+
83+
function makeParser(format) {
84+
const array = format.match(formattingTokens)
85+
const { length } = array
86+
for (let i = 0; i < length; i += 1) {
87+
const token = array[i]
88+
const parseTo = expressions[token]
89+
const regex = parseTo && parseTo[0]
90+
const parser = parseTo && parseTo[1]
91+
if (parser) {
92+
array[i] = { regex, parser }
93+
} else {
94+
array[i] = token.replace(/^\[|\]$/g, '')
95+
}
96+
}
97+
return function (input) {
98+
const time = {}
99+
for (let i = 0, start = 0; i < length; i += 1) {
100+
const token = array[i]
101+
if (typeof token === 'string') {
102+
start += token.length
103+
} else {
104+
const { regex, parser } = token
105+
const part = input.substr(start)
106+
const match = regex.exec(part)
107+
const value = match[0]
108+
parser.call(time, value)
109+
start += value.length
110+
}
111+
}
112+
correctHours(time)
113+
return time
114+
}
115+
}
116+
117+
const parseFormattedInput = (input, format) => {
118+
try {
119+
const parser = makeParser(format)
120+
const {
121+
year, month, day, hours, minutes, seconds, milliseconds, zone
122+
} = parser(input)
123+
if (zone) {
124+
return new Date(Date.UTC(
125+
year, month - 1, day,
126+
hours || 0,
127+
minutes || 0, seconds || 0, milliseconds || 0
128+
) + (zone.offset * 60 * 1000))
129+
}
130+
return new Date(
131+
year, month - 1, day,
132+
hours || 0, minutes || 0, seconds || 0, milliseconds || 0
133+
)
134+
} catch (e) {
135+
return new Date('') // Invalid Date
136+
}
137+
}
138+
2139

3140
export default (o, C) => {
4141
const proto = C.prototype

src/plugin/customParseFormat/parseFormattedInput.js

-138
This file was deleted.

0 commit comments

Comments
 (0)