@louis.jln/extract-date 3.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/package.json ADDED
@@ -0,0 +1,96 @@
1
+ {
2
+ "author": "Gajus Kuizinas <gajus@gajus.com> (http://gajus.com)",
3
+ "ava": {
4
+ "babel": {
5
+ "compileAsTests": [
6
+ "test/helpers/**/*"
7
+ ]
8
+ },
9
+ "files": [
10
+ "test/extract-date/**/*"
11
+ ],
12
+ "require": [
13
+ "@babel/register"
14
+ ]
15
+ },
16
+ "dependencies": {
17
+ "cartesian": "^1.0.1",
18
+ "date-fns": "^2.9.0",
19
+ "moment": "^2.24.0",
20
+ "moment-timezone": "^0.5.27",
21
+ "relative-date-names": "^1.0.4"
22
+ },
23
+ "description": "Extracts date from an arbitrary text input.",
24
+ "devDependencies": {
25
+ "@ava/babel": "^1.0.0",
26
+ "@babel/cli": "^7.8.4",
27
+ "@babel/core": "^7.8.4",
28
+ "@babel/node": "^7.8.4",
29
+ "@babel/plugin-transform-flow-strip-types": "^7.8.3",
30
+ "@babel/preset-env": "^7.8.4",
31
+ "@babel/register": "^7.8.3",
32
+ "ava": "^3.1.0",
33
+ "babel-plugin-istanbul": "^6.0.0",
34
+ "coveralls": "^3.0.9",
35
+ "esbuild": "^0.24.0",
36
+ "eslint": "^6.8.0",
37
+ "eslint-config-canonical": "^18.1.0",
38
+ "flow-bin": "^0.117.0",
39
+ "flow-copy-source": "^2.0.9",
40
+ "gitdown": "^3.1.2",
41
+ "husky": "^4.2.1",
42
+ "nyc": "^15.0.0",
43
+ "semantic-release": "^17.0.2",
44
+ "sinon": "^8.1.1"
45
+ },
46
+ "engines": {
47
+ "node": ">6"
48
+ },
49
+ "husky": {
50
+ "hooks": {
51
+ "pre-commit": "npm run lint && npm run test && npm run build",
52
+ "pre-push": "gitdown ./.README/README.md --output-file ./README.md --check"
53
+ }
54
+ },
55
+ "keywords": [
56
+ "date",
57
+ "extract",
58
+ "moment",
59
+ "parse"
60
+ ],
61
+ "license": "BSD-3-Clause",
62
+ "main": "./dist/index.js",
63
+ "name": "@louis.jln/extract-date",
64
+ "nyc": {
65
+ "include": [
66
+ "src/**/*.js"
67
+ ],
68
+ "instrument": false,
69
+ "reporter": [
70
+ "text-lcov"
71
+ ],
72
+ "require": [
73
+ "@babel/register"
74
+ ],
75
+ "sourceMap": false
76
+ },
77
+ "repository": {
78
+ "type": "git",
79
+ "url": "git+https://github.com/gajus/extract-date.git"
80
+ },
81
+ "scripts": {
82
+ "build": "rm -fr ./dist && NODE_ENV=production babel ./src --out-dir ./dist --copy-files --source-maps && flow-copy-source src dist",
83
+ "create-readme": "gitdown ./.README/README.md --output-file ./README.md",
84
+ "lint": "eslint ./src ./test && flow",
85
+ "test": "NODE_ENV=test ava --verbose --serial",
86
+ "bundle": "esbuild dist/index.js --bundle --outfile=bundle/extract-date.js --format=esm"
87
+ },
88
+ "version": "3.0.0",
89
+ "directories": {
90
+ "test": "test"
91
+ },
92
+ "bugs": {
93
+ "url": "https://github.com/gajus/extract-date/issues"
94
+ },
95
+ "homepage": "https://github.com/gajus/extract-date#readme"
96
+ }
@@ -0,0 +1,21 @@
1
+ // @flow
2
+
3
+ export default (dateFnsFormat: string): number => {
4
+ let specificity = 0;
5
+
6
+ if (dateFnsFormat.includes('yyyy')) {
7
+ specificity += 40;
8
+ } else if (dateFnsFormat.includes('yy')) {
9
+ specificity += 20;
10
+ }
11
+
12
+ if (dateFnsFormat.includes('M')) {
13
+ specificity += 20;
14
+ }
15
+
16
+ if (/d/.test(dateFnsFormat)) {
17
+ specificity += 20;
18
+ }
19
+
20
+ return specificity + dateFnsFormat.length;
21
+ };
@@ -0,0 +1,373 @@
1
+ // @flow
2
+
3
+ import cartesian from 'cartesian';
4
+ import calculateSpecificity from './calculateSpecificity';
5
+
6
+ const formatCombinaison = (combination) => combination.join(' ').replace(' ,', ',').replace(/ +/, ' ').replace(/ $/, '')
7
+
8
+ export default () => {
9
+ // The reason `yearFirstDashSeparator` and `yearFirstSlashSeparator` formats do not have direction is because
10
+ // there are no known regions that use yyyy-dd-MM format.
11
+ // https://en.wikipedia.org/wiki/Date_format_by_country
12
+ const yearFirstDashSeparator = [
13
+ {
14
+ dateFnsFormat: 'yyyy-MM-dd',
15
+ },
16
+ {
17
+ dateFnsFormat: 'yyyy-M-d',
18
+ },
19
+ ];
20
+
21
+ const yearFirstSlashSeparator = [
22
+ {
23
+ dateFnsFormat: 'yyyy/MM/dd',
24
+ },
25
+ {
26
+ dateFnsFormat: 'yyyy/M/d',
27
+ },
28
+ ];
29
+
30
+ const yearFirstDotSeparator = [
31
+ {
32
+ dateFnsFormat: 'yyyy.MM.dd',
33
+ direction: 'YMD',
34
+ },
35
+ {
36
+ dateFnsFormat: 'yyyy.M.d',
37
+ direction: 'YMD',
38
+ },
39
+ {
40
+ dateFnsFormat: 'yyyy.dd.MM',
41
+ direction: 'YDM',
42
+ },
43
+ {
44
+ dateFnsFormat: 'yyyy.d.M',
45
+ direction: 'YDM',
46
+ },
47
+ ];
48
+
49
+ const yearLastDashSeparator = [
50
+ {
51
+ dateFnsFormat: 'dd-MM-yyyy',
52
+ direction: 'DMY',
53
+ },
54
+ {
55
+ dateFnsFormat: 'd-M-yyyy',
56
+ direction: 'DMY',
57
+ },
58
+ {
59
+ dateFnsFormat: 'MM-dd-yyyy',
60
+ direction: 'MDY',
61
+ },
62
+ {
63
+ dateFnsFormat: 'M-d-yyyy',
64
+ direction: 'MDY',
65
+ },
66
+ ];
67
+
68
+ const yearLastDotSeparator = [
69
+ {
70
+ dateFnsFormat: 'dd.MM.yyyy',
71
+ direction: 'DMY',
72
+ },
73
+ {
74
+ dateFnsFormat: 'd.M.yyyy',
75
+ direction: 'DMY',
76
+ },
77
+ {
78
+ dateFnsFormat: 'MM.dd.yyyy',
79
+ direction: 'MDY',
80
+ },
81
+ {
82
+ dateFnsFormat: 'M.d.yyyy',
83
+ direction: 'MDY',
84
+ },
85
+ {
86
+ dateFnsFormat: 'dd.MM.yy',
87
+ direction: 'DMY',
88
+ },
89
+ {
90
+ dateFnsFormat: 'd.M.yy',
91
+ direction: 'DMY',
92
+ },
93
+ ];
94
+
95
+ const yearLastSlashSeparator = [
96
+ {
97
+ dateFnsFormat: 'dd/MM/yyyy',
98
+ direction: 'DMY',
99
+ },
100
+ {
101
+ dateFnsFormat: 'd/M/yyyy',
102
+ direction: 'DMY',
103
+ },
104
+ {
105
+ dateFnsFormat: 'MM/dd/yyyy',
106
+ direction: 'MDY',
107
+ },
108
+ {
109
+ dateFnsFormat: 'M/d/yyyy',
110
+ direction: 'MDY',
111
+ },
112
+ {
113
+ dateFnsFormat: 'MM/dd/yy',
114
+ direction: 'MDY',
115
+ },
116
+ {
117
+ dateFnsFormat: 'dd/MM/yy',
118
+ direction: 'DMY',
119
+ },
120
+ {
121
+ dateFnsFormat: 'd/M/yy',
122
+ direction: 'DMY',
123
+ },
124
+ {
125
+ dateFnsFormat: 'M/d/yy',
126
+ direction: 'MDY',
127
+ },
128
+ ];
129
+
130
+ const localised = [
131
+ ...cartesian([
132
+ ['MMMM'],
133
+ ['d', 'do'],
134
+ [',', ''],
135
+ ['yyyy'],
136
+ [',', ''],
137
+ ])
138
+ .map((combination) => {
139
+ return {
140
+ dateFnsFormat: formatCombinaison(combination),
141
+ };
142
+ }),
143
+ ...cartesian([
144
+ [
145
+ 'do',
146
+ 'd',
147
+ ],
148
+ [
149
+ 'MMMM',
150
+ 'MMM',
151
+ ],
152
+ [
153
+ 'yyyy',
154
+ ],
155
+ ])
156
+ .map((combination) => {
157
+ return {
158
+ dateFnsFormat: formatCombinaison(combination),
159
+ };
160
+ }),
161
+ ...cartesian([
162
+ [
163
+ 'MMMM',
164
+ 'MMM',
165
+ ],
166
+ [
167
+ 'yyyy',
168
+ ],
169
+ [
170
+ 'do',
171
+ 'd',
172
+ ],
173
+ ])
174
+ .map((combination) => {
175
+ return {
176
+ dateFnsFormat: formatCombinaison(combination),
177
+ };
178
+ }),
179
+ {
180
+ dateFnsFormat: 'MMMM yyyy EEE do',
181
+ },
182
+ {
183
+ dateFnsFormat: 'MMMM yyyy EEE d',
184
+ },
185
+ ];
186
+
187
+ const impliedYearLocalised = [
188
+ ...cartesian([
189
+ [
190
+ 'EEEE',
191
+ 'EEE',
192
+ ],
193
+ [
194
+ '',
195
+ ',',
196
+ ],
197
+ [
198
+ 'MMMM',
199
+ 'MMM',
200
+ ],
201
+ [
202
+ 'dd',
203
+ 'do',
204
+ 'd',
205
+ ],
206
+ ])
207
+ .map((combination) => {
208
+ return {
209
+ dateFnsFormat: formatCombinaison(combination),
210
+ };
211
+ }),
212
+ ...cartesian([
213
+ [
214
+ 'EEEE',
215
+ 'EEE',
216
+ ],
217
+ [
218
+ '',
219
+ ',',
220
+ ],
221
+ [
222
+ 'dd',
223
+ 'do',
224
+ 'd',
225
+ ],
226
+ [
227
+ 'MMMM',
228
+ 'MMM',
229
+ ],
230
+ ])
231
+ .map((combination) => {
232
+ return {
233
+ dateFnsFormat: formatCombinaison(combination),
234
+ };
235
+ }),
236
+ ...cartesian([
237
+ [
238
+ 'MMMM',
239
+ 'MMM',
240
+ ],
241
+ [
242
+ 'dd',
243
+ 'do',
244
+ 'd',
245
+ ],
246
+ [
247
+ ',',
248
+ '',
249
+ ],
250
+ ])
251
+ .map((combination) => {
252
+ return {
253
+ dateFnsFormat: formatCombinaison(combination),
254
+ };
255
+ }),
256
+ ...cartesian([
257
+ [
258
+ 'dd',
259
+ 'do',
260
+ 'd',
261
+ ],
262
+ [
263
+ 'MMMM',
264
+ 'MMM',
265
+ ],
266
+ [
267
+ ',',
268
+ '',
269
+ ],
270
+ ])
271
+ .map((combination) => {
272
+ return {
273
+ dateFnsFormat: formatCombinaison(combination),
274
+ };
275
+ }),
276
+ ];
277
+
278
+ const impliedYear = [
279
+ ...cartesian([
280
+ [
281
+ 'dd',
282
+ 'd',
283
+ ],
284
+ [
285
+ '/',
286
+ '-',
287
+ '.',
288
+ ],
289
+ [
290
+ 'MM',
291
+ 'M',
292
+ ],
293
+ [
294
+ ',',
295
+ '',
296
+ ],
297
+ ])
298
+ .map((combination) => {
299
+ return {
300
+ dateFnsFormat: combination.join('').replace(' ,', ',').replace(/ +/, ' '),
301
+ direction: 'DM',
302
+ };
303
+ }),
304
+ ...cartesian([
305
+ [
306
+ 'MM',
307
+ 'M',
308
+ ],
309
+ [
310
+ '/',
311
+ '-',
312
+ '.',
313
+ ],
314
+ [
315
+ 'dd',
316
+ 'd',
317
+ ],
318
+ [
319
+ ',',
320
+ '',
321
+ ],
322
+ ])
323
+ .map((combination) => {
324
+ return {
325
+ dateFnsFormat: combination.join('').replace(' ,', ',').replace(/ +/, ' '),
326
+ direction: 'MD',
327
+ };
328
+ }),
329
+ ];
330
+
331
+ const relative = [
332
+ {
333
+ dateFnsFormat: 'R',
334
+ test: false,
335
+ }
336
+ ];
337
+
338
+ return [
339
+ {
340
+ dateFnsFormat: 'yyyyMMdd',
341
+ },
342
+ ...yearFirstDashSeparator,
343
+ ...yearFirstDotSeparator,
344
+ ...yearFirstSlashSeparator,
345
+ ...yearLastDashSeparator,
346
+ ...yearLastDotSeparator,
347
+ ...yearLastSlashSeparator,
348
+ ...localised,
349
+ ...impliedYearLocalised,
350
+ ...impliedYear,
351
+ ...relative,
352
+ ]
353
+ .map((format) => {
354
+ return {
355
+ localised: /eee|mmm/i.test(format.dateFnsFormat),
356
+ specificity: calculateSpecificity(format.dateFnsFormat),
357
+ wordCount: format.dateFnsFormat.replace(/[^ ]/g, '').length + 1,
358
+ yearIsExplicit: format.dateFnsFormat.includes('yyyy'),
359
+ ...format,
360
+ };
361
+ })
362
+ .sort((a, b) => {
363
+ if (a.wordCount !== b.wordCount) {
364
+ return b.wordCount - a.wordCount;
365
+ }
366
+
367
+ if (b.specificity === a.specificity) {
368
+ return a.dateFnsFormat.localeCompare(b.dateFnsFormat);
369
+ }
370
+
371
+ return b.specificity - a.specificity;
372
+ });
373
+ };
@@ -0,0 +1,19 @@
1
+ // @flow
2
+
3
+ export default (haystack: $ReadOnlyArray<string>, sliceLength: number): $ReadOnlyArray<$ReadOnlyArray<string>> => {
4
+ const slices = [];
5
+
6
+ let index = 0;
7
+
8
+ while (index < haystack.length) {
9
+ const result = haystack.slice(index, index + sliceLength);
10
+
11
+ if (result.length === sliceLength) {
12
+ slices.push(result);
13
+ }
14
+
15
+ index++;
16
+ }
17
+
18
+ return slices;
19
+ };