UNPKG

3.57 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 * @memberof module:cicero-core
22 */
23
24
25class DateTimeFormatParser {
26 /**
27 * Given a format field (like HH or D) this method returns
28 * a logical name for the field. Note the logical names
29 * have been picked to align with the moment constructor that takes an object.
30 * @param {string} field - the input format field
31 * @returns {string} the field designator
32 */
33 static parseDateTimeFormatField(field) {
34 switch (field) {
35 case 'D':
36 case 'DD':
37 return 'days';
38
39 case 'M':
40 case 'MM':
41 case 'MMM':
42 case 'MMMM':
43 return 'months';
44
45 case 'YYYY':
46 return 'years';
47
48 case 'H':
49 case 'HH':
50 return 'hours';
51
52 case 'mm':
53 return 'minutes';
54
55 case 'ss':
56 return 'seconds';
57
58 case 'SSS':
59 return 'milliseconds';
60
61 case 'Z':
62 return 'timezone';
63
64 default:
65 return null;
66 }
67 }
68 /**
69 * Converts a format string to a Nearley action
70 * @param {string} formatString - the input format string
71 * @returns {{tokens: String, action: String, name: String }} the tokens and action and name to use for the Nearley rule
72 */
73
74
75 static buildDateTimeFormatRule(formatString) {
76 // strip quotes
77 let input = formatString.substr(1, formatString.length - 2);
78 const lastCharacter = input.charAt(input.length - 1);
79 let hasTimeZone = DateTimeFormatParser.parseDateTimeFormatField(lastCharacter) === 'timezone';
80
81 if (hasTimeZone) {
82 // strip Z
83 input = input.substr(0, input.length - 1);
84 }
85
86 const fields = input.split(/(DD|D|MMMM|MMM|MM|M|YYYY|HH|H|mm|ss|SSS)+/); // remove the first and last (empty) items
87
88 fields.shift();
89 fields.pop();
90 let tokens = '';
91 let parsedDateTime = '{"$class" : "ParsedDateTime",';
92 let fieldNames = [];
93 fields.forEach((field, index) => {
94 const fieldName = DateTimeFormatParser.parseDateTimeFormatField(field);
95
96 if (fieldName) {
97 if (fieldNames.indexOf(fieldName) >= 0) {
98 throw new Error("Duplicate ".concat(fieldName, " field in date time format string: ").concat(formatString));
99 } else {
100 parsedDateTime += " \"".concat(fieldName, "\": d[").concat(index, "]");
101
102 if (index < fields.length - 1) {
103 parsedDateTime += ',';
104 }
105
106 tokens += field + ' ';
107 fieldNames.push(fieldName);
108 }
109 } else {
110 tokens += " \"".concat(field, "\" ");
111 }
112 });
113
114 if (hasTimeZone) {
115 tokens += 'Z';
116 parsedDateTime += ", \"timezone\": d[".concat(fields.length, "]");
117 }
118
119 parsedDateTime += '}';
120 const action = "{% (d) => {return ".concat(parsedDateTime, ";}%}");
121 const name = 'DateTime_' + crypto.createHash('md5').update(formatString).digest('hex');
122 return {
123 tokens,
124 name,
125 action
126 };
127 }
128
129}
130
131module.exports = DateTimeFormatParser;
\No newline at end of file