Skip to content

Commit dfe93ee

Browse files
himynameistimlifreiksenet
authored andcommitted
feat(gatsby): add support for microsecond and alternative iso datetime formats (#12533)
* Add support for microsecond and alternative iso datetime formats
1 parent 8d8d39b commit dfe93ee

File tree

2 files changed

+428
-0
lines changed

2 files changed

+428
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,383 @@
1+
const { store } = require(`../../../redux`)
2+
const { build } = require(`../..`)
3+
const { isDate } = require(`../date`)
4+
require(`../../../db/__tests__/fixtures/ensure-loki`)()
5+
6+
// Timestamps grabbed from https://github.com/moment/moment/blob/2e2a5b35439665d4b0200143d808a7c26d6cd30f/src/test/moment/is_valid.js
7+
8+
describe(`isDate`, () => {
9+
it.each([
10+
`1970`,
11+
`2019`,
12+
`1970-01`,
13+
`2019-01`,
14+
`1970-01-01`,
15+
`2010-01-01`,
16+
`2010-01-30`,
17+
`19700101`,
18+
`20100101`,
19+
`20100130`,
20+
`2010-01-30T23+00:00`,
21+
`2010-01-30T23:59+00:00`,
22+
`2010-01-30T23:59:59+00:00`,
23+
`2010-01-30T23:59:59.999+00:00`,
24+
`2010-01-30T23:59:59.999-07:00`,
25+
`2010-01-30T00:00:00.000+07:00`,
26+
`2010-01-30T23:59:59.999-07`,
27+
`2010-01-30T00:00:00.000+07`,
28+
`2010-01-30T23Z`,
29+
`2010-01-30T23:59Z`,
30+
`2010-01-30T23:59:59Z`,
31+
`2010-01-30T23:59:59.999Z`,
32+
`2010-01-30T00:00:00.000Z`,
33+
`1970-01-01T00:00:00.000001Z`,
34+
`2012-04-01T00:00:00-05:00`,
35+
`2012-11-12T00:00:00+01:00`,
36+
])(`should return true for valid ISO 8601: %s`, dateString => {
37+
expect(isDate(dateString)).toBeTruthy()
38+
})
39+
40+
it.each([
41+
`2010-01-30 23+00:00`,
42+
`2010-01-30 23:59+00:00`,
43+
`2010-01-30 23:59:59+00:00`,
44+
`2010-01-30 23:59:59.999+00:00`,
45+
`2010-01-30 23:59:59.999-07:00`,
46+
`2010-01-30 00:00:00.000+07:00`,
47+
`2010-01-30 23:59:59.999-07`,
48+
`2010-01-30 00:00:00.000+07`,
49+
`1970-01-01 00:00:00.000Z`,
50+
`2012-04-01 00:00:00-05:00`,
51+
`2012-11-12 00:00:00+01:00`,
52+
`1970-01-01 00:00:00.0000001 Z`,
53+
`1970-01-01 00:00:00.000 Z`,
54+
`1970-01-01 00:00:00 Z`,
55+
`1970-01-01 000000 Z`,
56+
`1970-01-01 00:00 Z`,
57+
`1970-01-01 00 Z`,
58+
])(`should return true for ISO 8601 (no T, extra space): %s`, dateString => {
59+
expect(isDate(dateString)).toBeTruthy()
60+
})
61+
62+
it.each([`1970-W31`, `2006-W01`, `1970W31`, `2009-W53-7`, `2009W537`])(
63+
`should return true for ISO 8601 week dates: %s`,
64+
dateString => {
65+
expect(isDate(dateString)).toBeTruthy()
66+
}
67+
)
68+
69+
it.each([`1970-334`, `1970334`, `2090-001`, `2090001`])(
70+
`should return true for ISO 8601 ordinal dates: %s`,
71+
dateString => {
72+
expect(isDate(dateString)).toBeTruthy()
73+
}
74+
)
75+
76+
it.each([`2018-08-31T23:25:16.019345+02:00`, `2018-08-31T23:25:16.019345Z`])(
77+
`should return true for microsecond precision: %s`,
78+
dateString => {
79+
expect(isDate(dateString)).toBeTruthy()
80+
}
81+
)
82+
83+
it.skip.each([
84+
`2018-08-31T23:25:16.019345123+02:00`,
85+
`2018-08-31T23:25:16.019345123Z`,
86+
])(`should return true for nanosecond precision: %s`, dateString => {
87+
expect(isDate(dateString)).toBeTruthy()
88+
})
89+
90+
it.skip.each([`2018-08-31T23:25:16.012345678901+02:00`])(
91+
`should return false for precision beyond 9 digits: %s`,
92+
dateString => {
93+
expect(isDate(dateString)).toBeFalsy()
94+
}
95+
)
96+
97+
it.each([
98+
`2010-00-00`,
99+
`2010-01-00`,
100+
`2010-01-40`,
101+
`2010-01-01T24:01`, // 24:00:00 is actually valid
102+
`2010-01-01T23:60`,
103+
`2010-01-01T23:59:60`,
104+
`2010-01-40T23:59:59.9999`,
105+
`2010-00-00T+00:00`,
106+
`2010-01-00T+00:00`,
107+
`2010-01-40T+00:00`,
108+
`2010-01-40T24:01+00:00`,
109+
`2010-01-40T23:60+00:00`,
110+
`2010-01-40T23:59:60+00:00`,
111+
`2010-01-40T23:59:59.9999+00:00`,
112+
`2010-01-40T23:59:59,9999+00:00`,
113+
`2012-04-01T00:00:00-5:00`, // should be -05:00
114+
`2012-04-01T00:00:00+1:00`, // should be +01:00
115+
undefined,
116+
`undefined`,
117+
null,
118+
`null`,
119+
[],
120+
{},
121+
``,
122+
` `,
123+
`2012-04-01T00:basketball`,
124+
])(`should return false for invalid ISO 8601: %s`, dateString => {
125+
expect(isDate(dateString)).toBeFalsy()
126+
})
127+
128+
it.skip.each([
129+
1371065286,
130+
1379066897.0,
131+
1379066897.7,
132+
1379066897.0,
133+
1379066897.07,
134+
1379066897.17,
135+
1379066897.0,
136+
1379066897.007,
137+
1379066897.017,
138+
1379066897.157,
139+
`1371065286`,
140+
`1379066897.`,
141+
`1379066897.0`,
142+
`1379066897.7`,
143+
`1379066897.00`,
144+
`1379066897.07`,
145+
`1379066897.17`,
146+
`1379066897.000`,
147+
`1379066897.007`,
148+
`1379066897.017`,
149+
`1379066897.157`,
150+
])(`should return true for unix timestamps: %s`, dateString => {
151+
expect(isDate(dateString)).toBeTruthy()
152+
})
153+
})
154+
155+
const nodes = [
156+
{
157+
id: `id1`,
158+
internal: { type: `Test` },
159+
testDate: new Date(),
160+
explicitValidDate: `2010-01-30T23:59:59.999-07:00`,
161+
inferredValidDate: `1970-01-01T00:00:00.000Z`,
162+
validYYYY: `1970`,
163+
validYYMM: `2019-01`,
164+
validYYMMDD: `2010-01-30`,
165+
validYYMMDDNoDash: `20100101`,
166+
validISO1: `2010-01-30T23:59:59.999+00:00`,
167+
validISO2: `2010-01-30T23:59:59.999-07:00`,
168+
validISO3: `2010-01-30T00:00:00.000+07:00`,
169+
validISO4: `2010-01-30T23:59:59.999-07`,
170+
validISO5: `2010-01-30T00:00:00.000+07`,
171+
validISO6: `2010-01-30 00:00:00.000Z`,
172+
validISO7: `1970-01-01T00:00:00.000Z`,
173+
validISO8: `2012-04-01T00:00:00-05:00`,
174+
validISO9: `2012-11-12T00:00:00+01:00`,
175+
176+
validOrdinal1: `1970-334`,
177+
validOrdinal2: `1970334`,
178+
validOrdinal3: `2090-001`,
179+
validOrdinal4: `2090001`,
180+
181+
validWeek1: `1970-W31`,
182+
validWeek2: `2006-W01`,
183+
validWeek3: `1970W31`,
184+
validWeek4: `2009-W53-7`,
185+
validWeek5: `2009W537`,
186+
187+
validMicrosecond1: `2018-08-31T23:25:16.019345+02:00`,
188+
validMicrosecond2: `2018-08-31T23:25:16.019345Z`,
189+
190+
validNanosecond1: `2018-08-31T23:25:16.019345123+02:00`,
191+
validNanosecond2: `2018-08-31T23:25:16.019345123Z`,
192+
193+
invalidHighPrecision: `2018-08-31T23:25:16.01234567899993+02:00`,
194+
195+
invalidDate1: `2010-00-00`,
196+
invalidDate2: `2010-01-00`,
197+
invalidDate3: `2010-01-40`,
198+
invalidDate4: `2010-01-01T24:01`, // 24:00:00 is actually valid
199+
invalidDate5: `2010-01-01T23:60`,
200+
invalidDate6: `2010-01-01T23:59:60`,
201+
invalidDate7: `2010-01-40T23:59:59.9999`,
202+
203+
invalidDate8: undefined,
204+
invalidDate9: `undefined`,
205+
invalidDate10: null,
206+
invalidDate11: `null`,
207+
invalidDate12: [],
208+
invalidDate13: {},
209+
invalidDate14: ``,
210+
invalidDate15: ` `,
211+
invalidDate16: `2012-04-01T00:basketball`,
212+
},
213+
]
214+
215+
describe(`dateResolver`, () => {
216+
beforeEach(() => {
217+
store.dispatch({ type: `DELETE_CACHE` })
218+
nodes.forEach(node =>
219+
store.dispatch({ type: `CREATE_NODE`, payload: { ...node } })
220+
)
221+
})
222+
223+
const buildTestSchema = async ({
224+
infer = true,
225+
addDefaultResolvers = true,
226+
}) => {
227+
const inferDirective = infer ? `@infer` : `@dontInfer`
228+
const noDefaultResolvers = addDefaultResolvers ? `false` : `true`
229+
const typeDefs = [
230+
`
231+
type Test implements Node ${inferDirective}(noDefaultResolvers: ${noDefaultResolvers}) {
232+
testDate: Date
233+
explicitValidDate: Date
234+
invalidHighPrecision: Date
235+
invalidDate8: Date
236+
invalidDate9: Date
237+
invalidDate10: Date
238+
invalidDate11: Date
239+
invalidDate12: Date
240+
invalidDate13: Date
241+
invalidDate14: Date
242+
invalidDate15: Date
243+
invalidDate16: Date
244+
}`,
245+
]
246+
typeDefs.forEach(def =>
247+
store.dispatch({ type: `CREATE_TYPES`, payload: def })
248+
)
249+
250+
await build({})
251+
return store.getState().schema
252+
}
253+
254+
it(`can properly resolve datetimes`, async () => {
255+
const schema = await buildTestSchema({})
256+
const fields = schema.getType(`Test`).getFields()
257+
258+
expect(fields.testDate.resolve).toBeDefined()
259+
expect(fields.explicitValidDate.resolve).toBeDefined()
260+
expect(fields.inferredValidDate.resolve).toBeDefined()
261+
expect(fields.validYYYY.resolve).toBeDefined()
262+
expect(fields.validYYMM.resolve).toBeDefined()
263+
expect(fields.validYYMMDD.resolve).toBeDefined()
264+
expect(fields.validYYMMDDNoDash.resolve).toBeDefined()
265+
266+
expect(fields.validISO1.resolve).toBeDefined()
267+
expect(fields.validISO2.resolve).toBeDefined()
268+
expect(fields.validISO3.resolve).toBeDefined()
269+
expect(fields.validISO4.resolve).toBeDefined()
270+
expect(fields.validISO5.resolve).toBeDefined()
271+
expect(fields.validISO6.resolve).toBeDefined()
272+
expect(fields.validISO7.resolve).toBeDefined()
273+
expect(fields.validISO8.resolve).toBeDefined()
274+
expect(fields.validISO9.resolve).toBeDefined()
275+
276+
expect(fields.validOrdinal1.resolve).toBeDefined()
277+
expect(fields.validOrdinal2.resolve).toBeDefined()
278+
expect(fields.validOrdinal3.resolve).toBeDefined()
279+
expect(fields.validOrdinal4.resolve).toBeDefined()
280+
281+
expect(fields.validWeek1.resolve).toBeDefined()
282+
expect(fields.validWeek2.resolve).toBeDefined()
283+
expect(fields.validWeek3.resolve).toBeDefined()
284+
expect(fields.validWeek4.resolve).toBeDefined()
285+
expect(fields.validWeek5.resolve).toBeDefined()
286+
287+
expect(fields.validMicrosecond1.resolve).toBeDefined()
288+
expect(fields.validMicrosecond2.resolve).toBeDefined()
289+
290+
expect(fields.validNanosecond1.resolve).toBeDefined()
291+
expect(fields.validNanosecond2.resolve).toBeDefined()
292+
// expect(fields.invalidHighPrecision.resolve).toBeDefined()
293+
expect(fields.invalidDate1.resolve).toBeUndefined()
294+
expect(fields.invalidDate2.resolve).toBeUndefined()
295+
expect(fields.invalidDate3.resolve).toBeUndefined()
296+
expect(fields.invalidDate4.resolve).toBeUndefined()
297+
expect(fields.invalidDate5.resolve).toBeUndefined()
298+
expect(fields.invalidDate6.resolve).toBeUndefined()
299+
expect(fields.invalidDate7.resolve).toBeUndefined()
300+
expect(fields.invalidDate8.resolve).toBeUndefined()
301+
expect(fields.invalidDate9.resolve).toBeUndefined()
302+
expect(fields.invalidDate10.resolve).toBeUndefined()
303+
expect(fields.invalidDate11.resolve).toBeUndefined()
304+
expect(fields.invalidDate12.resolve).toBeUndefined()
305+
expect(fields.invalidDate13.resolve).toBeUndefined()
306+
expect(fields.invalidDate14.resolve).toBeUndefined()
307+
expect(fields.invalidDate15.resolve).toBeUndefined()
308+
expect(fields.invalidDate16.resolve).toBeUndefined()
309+
})
310+
311+
it.each([
312+
`2018-01-28T23:59:59.999-07:00`,
313+
`2018-01-29T00:00:00.000Z`,
314+
`2018-01-29`,
315+
`20180129`,
316+
`2018-01-29T23:59:59.999+00:00`,
317+
`2018-01-28T19:59:59.999-07:00`,
318+
`2018-01-30T06:00:00.001+07:00`,
319+
`2018-01-28 17:00:00.001-07`,
320+
`2018-01-30 04:00:00.001+07`,
321+
`2018-01-29 04:00:00.001Z`,
322+
`2018-01-29 04:00:00.001 Z`,
323+
`2018-01-29 04:00:00 Z`,
324+
`2018-01-29 04:00 Z`,
325+
`2018-01-29 04 Z`,
326+
`2018-01-28T17:00:00.001-07`,
327+
`2018-01-30T04:00:00.001+07`,
328+
`2018-01-29 00:00:00.001Z`,
329+
`2018-01-29T00:00:00.001Z`,
330+
`2018-01-28 23:00:00-05:00`,
331+
`2018-01-29 23:00:00+01:00`,
332+
`2018-01-28T23:00:00-05:00`,
333+
`2018-01-29T23:00:00+01:00`,
334+
`2018-029`,
335+
`2018029`,
336+
`2018-W05`,
337+
`2018W05`,
338+
`2018-W05-1`,
339+
`2018-01-29T23:25:16.019345+02:00`,
340+
`2018-01-29T23:25:16.019345Z`,
341+
// Seems to not require nanosecond definition to not fail
342+
`2018-01-29T23:25:16.019345123+02:00`,
343+
`2018-01-29T23:25:16.019345123Z`,
344+
])(`should return "Jan 29, 2018": %s`, async dateString => {
345+
const schema = await buildTestSchema({})
346+
const fields = schema.getType(`Test`).getFields()
347+
expect(
348+
fields[`testDate`].resolve(
349+
{ date: dateString },
350+
{ formatString: `MMM DD, YYYY` },
351+
{},
352+
{
353+
fieldName: `date`,
354+
}
355+
)
356+
).toEqual(`Jan 29, 2018`)
357+
})
358+
359+
it.each([
360+
`2010-00-00`,
361+
`2010-01-00`,
362+
`2010-01-40`,
363+
`2010-01-01T24:01`,
364+
`2010-01-01T23:60`,
365+
`2010-01-01T23:59:60`,
366+
`2010-01-40T23:59:59.9999`,
367+
// Combine with above statement once we figure out why it passes
368+
// `2018-08-31T23:25:16.01234567899993+02:00`,
369+
])(`should return "Invalid Date": %s`, async dateString => {
370+
const schema = await buildTestSchema({})
371+
const fields = schema.getType(`Test`).getFields()
372+
expect(
373+
fields[`testDate`].resolve(
374+
{ date: dateString },
375+
{ formatString: `MMM DD, YYYY` },
376+
{},
377+
{
378+
fieldName: `date`,
379+
}
380+
)
381+
).toEqual(`Invalid date`)
382+
})
383+
})

0 commit comments

Comments
 (0)