UNPKG

3.54 kBJavaScriptView Raw
1/*
2 * Licensed under the Apache License, Version 2.0 (the "License");
3 * you may not use this file except in compliance with the License.
4 * You may obtain a copy of the License at
5 *
6 * http://www.apache.org/licenses/LICENSE-2.0
7 *
8 * Unless required by applicable law or agreed to in writing, software
9 * distributed under the License is distributed on an "AS IS" BASIS,
10 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11 * See the License for the specific language governing permissions and
12 * limitations under the License.
13 */
14'use strict';
15
16const crypto = require('crypto');
17/**
18 * Parses a date/time format string
19 * @class
20 * @public
21 */
22
23
24class DateTimeFormatParser {
25 /**
26 * Given a format field (like HH or D) this method returns
27 * a logical name for the field. Note the logical names
28 * have been picked to align with the moment constructor that takes an object.
29 * @param {string} field - the input format field
30 * @returns {string} the field designator
31 */
32 static parseDateTimeFormatField(field) {
33 switch (field) {
34 case 'D':
35 case 'DD':
36 return 'days';
37
38 case 'M':
39 case 'MM':
40 case 'MMM':
41 case 'MMMM':
42 return 'months';
43
44 case 'YYYY':
45 return 'years';
46
47 case 'H':
48 case 'HH':
49 return 'hours';
50
51 case 'mm':
52 return 'minutes';
53
54 case 'ss':
55 return 'seconds';
56
57 case 'SSS':
58 return 'milliseconds';
59
60 case 'Z':
61 return 'timezone';
62
63 default:
64 return null;
65 }
66 }
67 /**
68 * Converts a format string to a Nearley action
69 * @param {string} formatString - the input format string
70 * @returns {{tokens: String, action: String, name: String }} the tokens and action and name to use for the Nearley rule
71 */
72
73
74 static buildDateTimeFormatRule(formatString) {
75 // strip quotes
76 let input = formatString.substr(1, formatString.length - 2);
77 const lastCharacter = input.charAt(input.length - 1);
78 let hasTimeZone = DateTimeFormatParser.parseDateTimeFormatField(lastCharacter) === 'timezone';
79
80 if (hasTimeZone) {
81 // strip Z
82 input = input.substr(0, input.length - 1);
83 }
84
85 const fields = input.split(/(DD|D|MMMM|MMM|MM|M|YYYY|HH|H|mm|ss|SSS)+/); // remove the first and last (empty) items
86
87 fields.shift();
88 fields.pop();
89 let tokens = '';
90 let parsedDateTime = '{"$class" : "ParsedDateTime",';
91 let fieldNames = [];
92 fields.forEach((field, index) => {
93 const fieldName = DateTimeFormatParser.parseDateTimeFormatField(field);
94
95 if (fieldName) {
96 if (fieldNames.indexOf(fieldName) >= 0) {
97 throw new Error("Duplicate ".concat(fieldName, " field in date time format string: ").concat(formatString));
98 } else {
99 parsedDateTime += " \"".concat(fieldName, "\": d[").concat(index, "]");
100
101 if (index < fields.length - 1) {
102 parsedDateTime += ',';
103 }
104
105 tokens += field + ' ';
106 fieldNames.push(fieldName);
107 }
108 } else {
109 tokens += " \"".concat(field, "\" ");
110 }
111 });
112
113 if (hasTimeZone) {
114 tokens += 'Z';
115 parsedDateTime += ", \"timezone\": d[".concat(fields.length, "]");
116 }
117
118 parsedDateTime += '}';
119 const action = "{% (d) => {return ".concat(parsedDateTime, ";}%}");
120 const name = 'DateTime_' + crypto.createHash('md5').update(formatString).digest('hex');
121 return {
122 tokens,
123 name,
124 action
125 };
126 }
127
128}
129
130module.exports = DateTimeFormatParser;
\No newline at end of file