UNPKG

11 kBJavaScriptView Raw
1/* Modified from https://github.com/taylorhakes/fecha
2 *
3 * The MIT License (MIT)
4 *
5 * Copyright (c) 2015 Taylor Hakes
6 *
7 * Permission is hereby granted, free of charge, to any person obtaining a copy
8 * of this software and associated documentation files (the "Software"), to deal
9 * in the Software without restriction, including without limitation the rights
10 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 * copies of the Software, and to permit persons to whom the Software is
12 * furnished to do so, subject to the following conditions:
13 *
14 * The above copyright notice and this permission notice shall be included in all
15 * copies or substantial portions of the Software.
16 *
17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
23 * SOFTWARE.
24 */
25
26/*eslint-disable*/
27// 把 YYYY-MM-DD 改成了 yyyy-MM-dd
28(function (main) {
29 'use strict';
30
31 /**
32 * Parse or format dates
33 * @class fecha
34 */
35 var fecha = {};
36 var token = /d{1,4}|M{1,4}|yy(?:yy)?|S{1,3}|Do|ZZ|([HhMsDm])\1?|[aA]|"[^"]*"|'[^']*'/g;
37 var twoDigits = '\\d\\d?';
38 var threeDigits = '\\d{3}';
39 var fourDigits = '\\d{4}';
40 var word = '[^\\s]+';
41 var literal = /\[([^]*?)\]/gm;
42 var noop = function () {
43 };
44
45 function regexEscape(str) {
46 return str.replace( /[|\\{()[^$+*?.-]/g, '\\$&');
47 }
48
49 function shorten(arr, sLen) {
50 var newArr = [];
51 for (var i = 0, len = arr.length; i < len; i++) {
52 newArr.push(arr[i].substr(0, sLen));
53 }
54 return newArr;
55 }
56
57 function monthUpdate(arrName) {
58 return function (d, v, i18n) {
59 var index = i18n[arrName].indexOf(v.charAt(0).toUpperCase() + v.substr(1).toLowerCase());
60 if (~index) {
61 d.month = index;
62 }
63 };
64 }
65
66 function pad(val, len) {
67 val = String(val);
68 len = len || 2;
69 while (val.length < len) {
70 val = '0' + val;
71 }
72 return val;
73 }
74
75 var dayNames = ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'];
76 var monthNames = ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'];
77 var monthNamesShort = shorten(monthNames, 3);
78 var dayNamesShort = shorten(dayNames, 3);
79 fecha.i18n = {
80 dayNamesShort: dayNamesShort,
81 dayNames: dayNames,
82 monthNamesShort: monthNamesShort,
83 monthNames: monthNames,
84 amPm: ['am', 'pm'],
85 DoFn: function DoFn(D) {
86 return D + ['th', 'st', 'nd', 'rd'][D % 10 > 3 ? 0 : (D - D % 10 !== 10) * D % 10];
87 }
88 };
89
90 var formatFlags = {
91 D: function(dateObj) {
92 return dateObj.getDay();
93 },
94 DD: function(dateObj) {
95 return pad(dateObj.getDay());
96 },
97 Do: function(dateObj, i18n) {
98 return i18n.DoFn(dateObj.getDate());
99 },
100 d: function(dateObj) {
101 return dateObj.getDate();
102 },
103 dd: function(dateObj) {
104 return pad(dateObj.getDate());
105 },
106 ddd: function(dateObj, i18n) {
107 return i18n.dayNamesShort[dateObj.getDay()];
108 },
109 dddd: function(dateObj, i18n) {
110 return i18n.dayNames[dateObj.getDay()];
111 },
112 M: function(dateObj) {
113 return dateObj.getMonth() + 1;
114 },
115 MM: function(dateObj) {
116 return pad(dateObj.getMonth() + 1);
117 },
118 MMM: function(dateObj, i18n) {
119 return i18n.monthNamesShort[dateObj.getMonth()];
120 },
121 MMMM: function(dateObj, i18n) {
122 return i18n.monthNames[dateObj.getMonth()];
123 },
124 yy: function(dateObj) {
125 return pad(String(dateObj.getFullYear()), 4).substr(2);
126 },
127 yyyy: function(dateObj) {
128 return pad(dateObj.getFullYear(), 4);
129 },
130 h: function(dateObj) {
131 return dateObj.getHours() % 12 || 12;
132 },
133 hh: function(dateObj) {
134 return pad(dateObj.getHours() % 12 || 12);
135 },
136 H: function(dateObj) {
137 return dateObj.getHours();
138 },
139 HH: function(dateObj) {
140 return pad(dateObj.getHours());
141 },
142 m: function(dateObj) {
143 return dateObj.getMinutes();
144 },
145 mm: function(dateObj) {
146 return pad(dateObj.getMinutes());
147 },
148 s: function(dateObj) {
149 return dateObj.getSeconds();
150 },
151 ss: function(dateObj) {
152 return pad(dateObj.getSeconds());
153 },
154 S: function(dateObj) {
155 return Math.round(dateObj.getMilliseconds() / 100);
156 },
157 SS: function(dateObj) {
158 return pad(Math.round(dateObj.getMilliseconds() / 10), 2);
159 },
160 SSS: function(dateObj) {
161 return pad(dateObj.getMilliseconds(), 3);
162 },
163 a: function(dateObj, i18n) {
164 return dateObj.getHours() < 12 ? i18n.amPm[0] : i18n.amPm[1];
165 },
166 A: function(dateObj, i18n) {
167 return dateObj.getHours() < 12 ? i18n.amPm[0].toUpperCase() : i18n.amPm[1].toUpperCase();
168 },
169 ZZ: function(dateObj) {
170 var o = dateObj.getTimezoneOffset();
171 return (o > 0 ? '-' : '+') + pad(Math.floor(Math.abs(o) / 60) * 100 + Math.abs(o) % 60, 4);
172 }
173 };
174
175 var parseFlags = {
176 d: [twoDigits, function (d, v) {
177 d.day = v;
178 }],
179 Do: [twoDigits + word, function (d, v) {
180 d.day = parseInt(v, 10);
181 }],
182 M: [twoDigits, function (d, v) {
183 d.month = v - 1;
184 }],
185 yy: [twoDigits, function (d, v) {
186 var da = new Date(), cent = +('' + da.getFullYear()).substr(0, 2);
187 d.year = '' + (v > 68 ? cent - 1 : cent) + v;
188 }],
189 h: [twoDigits, function (d, v) {
190 d.hour = v;
191 }],
192 m: [twoDigits, function (d, v) {
193 d.minute = v;
194 }],
195 s: [twoDigits, function (d, v) {
196 d.second = v;
197 }],
198 yyyy: [fourDigits, function (d, v) {
199 d.year = v;
200 }],
201 S: ['\\d', function (d, v) {
202 d.millisecond = v * 100;
203 }],
204 SS: ['\\d{2}', function (d, v) {
205 d.millisecond = v * 10;
206 }],
207 SSS: [threeDigits, function (d, v) {
208 d.millisecond = v;
209 }],
210 D: [twoDigits, noop],
211 ddd: [word, noop],
212 MMM: [word, monthUpdate('monthNamesShort')],
213 MMMM: [word, monthUpdate('monthNames')],
214 a: [word, function (d, v, i18n) {
215 var val = v.toLowerCase();
216 if (val === i18n.amPm[0]) {
217 d.isPm = false;
218 } else if (val === i18n.amPm[1]) {
219 d.isPm = true;
220 }
221 }],
222 ZZ: ['[^\\s]*?[\\+\\-]\\d\\d:?\\d\\d|[^\\s]*?Z', function (d, v) {
223 var parts = (v + '').match(/([+-]|\d\d)/gi), minutes;
224
225 if (parts) {
226 minutes = +(parts[1] * 60) + parseInt(parts[2], 10);
227 d.timezoneOffset = parts[0] === '+' ? minutes : -minutes;
228 }
229 }]
230 };
231 parseFlags.dd = parseFlags.d;
232 parseFlags.dddd = parseFlags.ddd;
233 parseFlags.DD = parseFlags.D;
234 parseFlags.mm = parseFlags.m;
235 parseFlags.hh = parseFlags.H = parseFlags.HH = parseFlags.h;
236 parseFlags.MM = parseFlags.M;
237 parseFlags.ss = parseFlags.s;
238 parseFlags.A = parseFlags.a;
239
240
241 // Some common format strings
242 fecha.masks = {
243 default: 'ddd MMM dd yyyy HH:mm:ss',
244 shortDate: 'M/D/yy',
245 mediumDate: 'MMM d, yyyy',
246 longDate: 'MMMM d, yyyy',
247 fullDate: 'dddd, MMMM d, yyyy',
248 shortTime: 'HH:mm',
249 mediumTime: 'HH:mm:ss',
250 longTime: 'HH:mm:ss.SSS'
251 };
252
253 /***
254 * Format a date
255 * @method format
256 * @param {Date|number} dateObj
257 * @param {string} mask Format of the date, i.e. 'mm-dd-yy' or 'shortDate'
258 */
259 fecha.format = function (dateObj, mask, i18nSettings) {
260 var i18n = i18nSettings || fecha.i18n;
261
262 if (typeof dateObj === 'number') {
263 dateObj = new Date(dateObj);
264 }
265
266 if (Object.prototype.toString.call(dateObj) !== '[object Date]' || isNaN(dateObj.getTime())) {
267 throw new Error('Invalid Date in fecha.format');
268 }
269
270 mask = fecha.masks[mask] || mask || fecha.masks['default'];
271
272 var literals = [];
273
274 // Make literals inactive by replacing them with ??
275 mask = mask.replace(literal, function($0, $1) {
276 literals.push($1);
277 return '@@@';
278 });
279 // Apply formatting rules
280 mask = mask.replace(token, function ($0) {
281 return $0 in formatFlags ? formatFlags[$0](dateObj, i18n) : $0.slice(1, $0.length - 1);
282 });
283 // Inline literal values back into the formatted value
284 return mask.replace(/@@@/g, function() {
285 return literals.shift();
286 });
287 };
288
289 /**
290 * Parse a date string into an object, changes - into /
291 * @method parse
292 * @param {string} dateStr Date string
293 * @param {string} format Date parse format
294 * @returns {Date|boolean}
295 */
296 fecha.parse = function (dateStr, format, i18nSettings) {
297 var i18n = i18nSettings || fecha.i18n;
298
299 if (typeof format !== 'string') {
300 throw new Error('Invalid format in fecha.parse');
301 }
302
303 format = fecha.masks[format] || format;
304
305 // Avoid regular expression denial of service, fail early for really long strings
306 // https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS
307 if (dateStr.length > 1000) {
308 return null;
309 }
310
311 var dateInfo = {};
312 var parseInfo = [];
313 var literals = [];
314 format = format.replace(literal, function($0, $1) {
315 literals.push($1);
316 return '@@@';
317 });
318 var newFormat = regexEscape(format).replace(token, function ($0) {
319 if (parseFlags[$0]) {
320 var info = parseFlags[$0];
321 parseInfo.push(info[1]);
322 return '(' + info[0] + ')';
323 }
324
325 return $0;
326 });
327 newFormat = newFormat.replace(/@@@/g, function() {
328 return literals.shift();
329 });
330 var matches = dateStr.match(new RegExp(newFormat, 'i'));
331 if (!matches) {
332 return null;
333 }
334
335 for (var i = 1; i < matches.length; i++) {
336 parseInfo[i - 1](dateInfo, matches[i], i18n);
337 }
338
339 var today = new Date();
340 if (dateInfo.isPm === true && dateInfo.hour != null && +dateInfo.hour !== 12) {
341 dateInfo.hour = +dateInfo.hour + 12;
342 } else if (dateInfo.isPm === false && +dateInfo.hour === 12) {
343 dateInfo.hour = 0;
344 }
345
346 var date;
347 if (dateInfo.timezoneOffset != null) {
348 dateInfo.minute = +(dateInfo.minute || 0) - +dateInfo.timezoneOffset;
349 date = new Date(Date.UTC(dateInfo.year || today.getFullYear(), dateInfo.month || 0, dateInfo.day || 1,
350 dateInfo.hour || 0, dateInfo.minute || 0, dateInfo.second || 0, dateInfo.millisecond || 0));
351 } else {
352 date = new Date(dateInfo.year || today.getFullYear(), dateInfo.month || 0, dateInfo.day || 1,
353 dateInfo.hour || 0, dateInfo.minute || 0, dateInfo.second || 0, dateInfo.millisecond || 0);
354 }
355 return date;
356 };
357
358 /* istanbul ignore next */
359 if (typeof module !== 'undefined' && module.exports) {
360 module.exports = fecha;
361 } else if (typeof define === 'function' && define.amd) {
362 define(function () {
363 return fecha;
364 });
365 } else {
366 main.fecha = fecha;
367 }
368})(this);