Deployed the page to Github Pages.
This commit is contained in:
parent
1d79754e93
commit
2c89899458
62797 changed files with 6551425 additions and 15279 deletions
22
node_modules/fecha/LICENSE
generated
vendored
Normal file
22
node_modules/fecha/LICENSE
generated
vendored
Normal file
|
@ -0,0 +1,22 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Taylor Hakes
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
|
320
node_modules/fecha/README.md
generated
vendored
Normal file
320
node_modules/fecha/README.md
generated
vendored
Normal file
|
@ -0,0 +1,320 @@
|
|||
# fecha [](https://travis-ci.org/taylorhakes/fecha)
|
||||
|
||||
Lightweight date formatting and parsing (~2KB). Meant to replace parsing and formatting functionality of moment.js.
|
||||
|
||||
### NPM
|
||||
```
|
||||
npm install fecha --save
|
||||
```
|
||||
### Yarn
|
||||
```
|
||||
yarn add fecha
|
||||
```
|
||||
|
||||
### Fecha vs Moment
|
||||
<table class="table table-striped table-bordered">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Fecha</th>
|
||||
<th>Moment</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Size (Min. and Gzipped)</b></td>
|
||||
<td>2.1KBs</td>
|
||||
<td>13.1KBs</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Date Parsing</b></td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Date Formatting</b></td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Date Manipulation</b></td>
|
||||
<td></td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>I18n Support</b></td>
|
||||
<td>✓</td>
|
||||
<td>✓</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## Use it
|
||||
|
||||
#### Formatting
|
||||
`format` accepts a Date object (or timestamp) and a string format and returns a formatted string. See below for
|
||||
available format tokens.
|
||||
|
||||
Note: `format` will throw an error when passed invalid parameters
|
||||
```js
|
||||
import { format } from 'fecha';
|
||||
|
||||
type format = (date: Date, format?: string, i18n?: I18nSettings) => str;
|
||||
|
||||
// Custom formats
|
||||
format(new Date(2015, 10, 20), 'dddd MMMM Do, YYYY'); // 'Friday November 20th, 2015'
|
||||
format(new Date(1998, 5, 3, 15, 23, 10, 350), 'YYYY-MM-DD hh:mm:ss.SSS A'); // '1998-06-03 03:23:10.350 PM'
|
||||
|
||||
// Named masks
|
||||
format(new Date(2015, 10, 20), 'isoDate'); // '2015-11-20'
|
||||
format(new Date(2015, 10, 20), 'mediumDate'); // 'Nov 20, 2015'
|
||||
format(new Date(2015, 10, 20, 3, 2, 1), 'isoDateTime'); // '2015-11-20T03:02:01-05:00'
|
||||
format(new Date(2015, 2, 10, 5, 30, 20), 'shortTime'); // '05:30'
|
||||
|
||||
// Literals
|
||||
format(new Date(2001, 2, 5, 6, 7, 2, 5), '[on] MM-DD-YYYY [at] HH:mm'); // 'on 03-05-2001 at 06:07'
|
||||
```
|
||||
|
||||
#### Parsing
|
||||
`parse` accepts a Date string and a string format and returns a Date object. See below for available format tokens.
|
||||
|
||||
*NOTE*: `parse` will throw an error when passed invalid string format or missing format. You MUST specify a format.
|
||||
```js
|
||||
import { parse } from 'fecha';
|
||||
|
||||
type parse = (dateStr: string, format: string, i18n?: I18nSettingsOptional) => Date|null;
|
||||
|
||||
// Custom formats
|
||||
parse('February 3rd, 2014', 'MMMM Do, YYYY'); // new Date(2014, 1, 3)
|
||||
parse('10-12-10 14:11:12', 'YY-MM-DD HH:mm:ss'); // new Date(2010, 11, 10, 14, 11, 12)
|
||||
|
||||
// Named masks
|
||||
parse('5/3/98', 'shortDate'); // new Date(1998, 4, 3)
|
||||
parse('November 4, 2005', 'longDate'); // new Date(2005, 10, 4)
|
||||
parse('2015-11-20T03:02:01-05:00', 'isoDateTime'); // new Date(2015, 10, 20, 3, 2, 1)
|
||||
|
||||
// Override i18n
|
||||
parse('4 de octubre de 1983', 'M de MMMM de YYYY', {
|
||||
monthNames: [
|
||||
'enero',
|
||||
'febrero',
|
||||
'marzo',
|
||||
'abril',
|
||||
'mayo',
|
||||
'junio',
|
||||
'julio',
|
||||
'agosto',
|
||||
'septiembre',
|
||||
'octubre',
|
||||
'noviembre',
|
||||
'diciembre'
|
||||
]
|
||||
}); // new Date(1983, 9, 4)
|
||||
```
|
||||
|
||||
#### i18n Support
|
||||
```js
|
||||
import {setGlobalDateI18n} from 'fecha';
|
||||
|
||||
/*
|
||||
Default I18n Settings
|
||||
{
|
||||
dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat'],
|
||||
dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
|
||||
monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
|
||||
monthNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
|
||||
amPm: ['am', 'pm'],
|
||||
// D is the day of the month, function returns something like... 3rd or 11th
|
||||
DoFn(dayOfMonth) {
|
||||
return dayOfMonth + [ 'th', 'st', 'nd', 'rd' ][ dayOfMonth % 10 > 3 ? 0 : (dayOfMonth - dayOfMonth % 10 !== 10) * dayOfMonth % 10 ];
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
setGlobalDateI18n({
|
||||
dayNamesShort: ['Sun', 'Mon', 'Tue', 'Wed', 'Thur', 'Fri', 'Sat'],
|
||||
dayNames: ['Sunday', 'Monday', 'Tuesday', 'Wednesday', 'Thursday', 'Friday', 'Saturday'],
|
||||
monthNamesShort: ['Jan', 'Feb', 'Mar', 'Apr', 'May', 'Jun', 'Jul', 'Aug', 'Sep', 'Oct', 'Nov', 'Dec'],
|
||||
monthNames: ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'],
|
||||
amPm: ['am', 'pm'],
|
||||
// D is the day of the month, function returns something like... 3rd or 11th
|
||||
DoFn: function (D) {
|
||||
return D + [ 'th', 'st', 'nd', 'rd' ][ D % 10 > 3 ? 0 : (D - D % 10 !== 10) * D % 10 ];
|
||||
}
|
||||
});
|
||||
|
||||
```
|
||||
|
||||
#### Custom Named Masks
|
||||
```js
|
||||
import { format, setGlobalDateMasks } from 'fecha';
|
||||
/*
|
||||
Default global masks
|
||||
{
|
||||
default: 'ddd MMM DD YYYY HH:mm:ss',
|
||||
shortDate: 'M/D/YY',
|
||||
mediumDate: 'MMM D, YYYY',
|
||||
longDate: 'MMMM D, YYYY',
|
||||
fullDate: 'dddd, MMMM D, YYYY',
|
||||
shortTime: 'HH:mm',
|
||||
mediumTime: 'HH:mm:ss',
|
||||
longTime: 'HH:mm:ss.SSS'
|
||||
}
|
||||
*/
|
||||
|
||||
// Create a new mask
|
||||
setGlobalDateMasks({
|
||||
myMask: 'HH:mm:ss YY/MM/DD';
|
||||
});
|
||||
|
||||
// Use it
|
||||
format(new Date(2014, 5, 6, 14, 10, 45), 'myMask'); // '14:10:45 14/06/06'
|
||||
```
|
||||
|
||||
### Formatting Tokens
|
||||
<table class="table table-striped table-bordered">
|
||||
<tbody>
|
||||
<tr>
|
||||
<th></th>
|
||||
<th>Token</th>
|
||||
<th>Output</th>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Month</b></td>
|
||||
<td>M</td>
|
||||
<td>1 2 ... 11 12</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>MM</td>
|
||||
<td>01 02 ... 11 12</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>MMM</td>
|
||||
<td>Jan Feb ... Nov Dec</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>MMMM</td>
|
||||
<td>January February ... November December</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Day of Month</b></td>
|
||||
<td>D</td>
|
||||
<td>1 2 ... 30 31</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>Do</td>
|
||||
<td>1st 2nd ... 30th 31st</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>DD</td>
|
||||
<td>01 02 ... 30 31</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Day of Week</b></td>
|
||||
<td>d</td>
|
||||
<td>0 1 ... 5 6</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>ddd</td>
|
||||
<td>Sun Mon ... Fri Sat</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>dddd</td>
|
||||
<td>Sunday Monday ... Friday Saturday</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Year</b></td>
|
||||
<td>YY</td>
|
||||
<td>70 71 ... 29 30</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>YYYY</td>
|
||||
<td>1970 1971 ... 2029 2030</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>AM/PM</b></td>
|
||||
<td>A</td>
|
||||
<td>AM PM</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>a</td>
|
||||
<td>am pm</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Hour</b></td>
|
||||
<td>H</td>
|
||||
<td>0 1 ... 22 23</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>HH</td>
|
||||
<td>00 01 ... 22 23</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>h</td>
|
||||
<td>1 2 ... 11 12</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>hh</td>
|
||||
<td>01 02 ... 11 12</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Minute</b></td>
|
||||
<td>m</td>
|
||||
<td>0 1 ... 58 59</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>mm</td>
|
||||
<td>00 01 ... 58 59</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Second</b></td>
|
||||
<td>s</td>
|
||||
<td>0 1 ... 58 59</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>ss</td>
|
||||
<td>00 01 ... 58 59</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Fractional Second</b></td>
|
||||
<td>S</td>
|
||||
<td>0 1 ... 8 9</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>SS</td>
|
||||
<td>0 1 ... 98 99</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td></td>
|
||||
<td>SSS</td>
|
||||
<td>0 1 ... 998 999</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b>Timezone</b></td>
|
||||
<td>Z</td>
|
||||
<td>
|
||||
-07:00 -06:00 ... +06:00 +07:00
|
||||
</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><b></b></td>
|
||||
<td>ZZ</td>
|
||||
<td>
|
||||
-0700 -0600 ... +0600 +0700
|
||||
</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
2
node_modules/fecha/dist/fecha.min.js
generated
vendored
Normal file
2
node_modules/fecha/dist/fecha.min.js
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
1
node_modules/fecha/dist/fecha.min.js.map
generated
vendored
Normal file
1
node_modules/fecha/dist/fecha.min.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
52
node_modules/fecha/lib/fecha.d.ts
generated
vendored
Normal file
52
node_modules/fecha/lib/fecha.d.ts
generated
vendored
Normal file
|
@ -0,0 +1,52 @@
|
|||
export declare type I18nSettings = {
|
||||
amPm: [string, string];
|
||||
dayNames: Days;
|
||||
dayNamesShort: Days;
|
||||
monthNames: Months;
|
||||
monthNamesShort: Months;
|
||||
DoFn(dayOfMonth: number): string;
|
||||
};
|
||||
export declare type I18nSettingsOptional = Partial<I18nSettings>;
|
||||
export declare type Days = [string, string, string, string, string, string, string];
|
||||
export declare type Months = [string, string, string, string, string, string, string, string, string, string, string, string];
|
||||
export declare function assign<A>(a: A): A;
|
||||
export declare function assign<A, B>(a: A, b: B): A & B;
|
||||
export declare function assign<A, B, C>(a: A, b: B, c: C): A & B & C;
|
||||
export declare function assign<A, B, C, D>(a: A, b: B, c: C, d: D): A & B & C & D;
|
||||
declare const defaultI18n: I18nSettings;
|
||||
declare const setGlobalDateI18n: (i18n: I18nSettingsOptional) => I18nSettings;
|
||||
declare const setGlobalDateMasks: (masks: {
|
||||
[key: string]: string;
|
||||
}) => {
|
||||
[key: string]: string;
|
||||
};
|
||||
/***
|
||||
* Format a date
|
||||
* @method format
|
||||
* @param {Date|number} dateObj
|
||||
* @param {string} mask Format of the date, i.e. 'mm-dd-yy' or 'shortDate'
|
||||
* @returns {string} Formatted date string
|
||||
*/
|
||||
declare const format: (dateObj: Date, mask?: string, i18n?: I18nSettingsOptional) => string;
|
||||
/**
|
||||
* Parse a date string into a Javascript Date object /
|
||||
* @method parse
|
||||
* @param {string} dateStr Date string
|
||||
* @param {string} format Date parse format
|
||||
* @param {i18n} I18nSettingsOptional Full or subset of I18N settings
|
||||
* @returns {Date|null} Returns Date object. Returns null what date string is invalid or doesn't match format
|
||||
*/
|
||||
declare function parse(dateStr: string, format: string, i18n?: I18nSettingsOptional): Date | null;
|
||||
declare const _default: {
|
||||
format: (dateObj: Date, mask?: string, i18n?: Partial<I18nSettings>) => string;
|
||||
parse: typeof parse;
|
||||
defaultI18n: I18nSettings;
|
||||
setGlobalDateI18n: (i18n: Partial<I18nSettings>) => I18nSettings;
|
||||
setGlobalDateMasks: (masks: {
|
||||
[key: string]: string;
|
||||
}) => {
|
||||
[key: string]: string;
|
||||
};
|
||||
};
|
||||
export default _default;
|
||||
export { format, parse, defaultI18n, setGlobalDateI18n, setGlobalDateMasks };
|
403
node_modules/fecha/lib/fecha.js
generated
vendored
Normal file
403
node_modules/fecha/lib/fecha.js
generated
vendored
Normal file
|
@ -0,0 +1,403 @@
|
|||
var token = /d{1,4}|M{1,4}|YY(?:YY)?|S{1,3}|Do|ZZ|Z|([HhMsDm])\1?|[aA]|"[^"]*"|'[^']*'/g;
|
||||
var twoDigitsOptional = "\\d\\d?";
|
||||
var twoDigits = "\\d\\d";
|
||||
var threeDigits = "\\d{3}";
|
||||
var fourDigits = "\\d{4}";
|
||||
var word = "[^\\s]+";
|
||||
var literal = /\[([^]*?)\]/gm;
|
||||
function shorten(arr, sLen) {
|
||||
var newArr = [];
|
||||
for (var i = 0, len = arr.length; i < len; i++) {
|
||||
newArr.push(arr[i].substr(0, sLen));
|
||||
}
|
||||
return newArr;
|
||||
}
|
||||
var monthUpdate = function (arrName) { return function (v, i18n) {
|
||||
var lowerCaseArr = i18n[arrName].map(function (v) { return v.toLowerCase(); });
|
||||
var index = lowerCaseArr.indexOf(v.toLowerCase());
|
||||
if (index > -1) {
|
||||
return index;
|
||||
}
|
||||
return null;
|
||||
}; };
|
||||
function assign(origObj) {
|
||||
var args = [];
|
||||
for (var _i = 1; _i < arguments.length; _i++) {
|
||||
args[_i - 1] = arguments[_i];
|
||||
}
|
||||
for (var _a = 0, args_1 = args; _a < args_1.length; _a++) {
|
||||
var obj = args_1[_a];
|
||||
for (var key in obj) {
|
||||
// @ts-ignore ex
|
||||
origObj[key] = obj[key];
|
||||
}
|
||||
}
|
||||
return origObj;
|
||||
}
|
||||
var dayNames = [
|
||||
"Sunday",
|
||||
"Monday",
|
||||
"Tuesday",
|
||||
"Wednesday",
|
||||
"Thursday",
|
||||
"Friday",
|
||||
"Saturday"
|
||||
];
|
||||
var monthNames = [
|
||||
"January",
|
||||
"February",
|
||||
"March",
|
||||
"April",
|
||||
"May",
|
||||
"June",
|
||||
"July",
|
||||
"August",
|
||||
"September",
|
||||
"October",
|
||||
"November",
|
||||
"December"
|
||||
];
|
||||
var monthNamesShort = shorten(monthNames, 3);
|
||||
var dayNamesShort = shorten(dayNames, 3);
|
||||
var defaultI18n = {
|
||||
dayNamesShort: dayNamesShort,
|
||||
dayNames: dayNames,
|
||||
monthNamesShort: monthNamesShort,
|
||||
monthNames: monthNames,
|
||||
amPm: ["am", "pm"],
|
||||
DoFn: function (dayOfMonth) {
|
||||
return (dayOfMonth +
|
||||
["th", "st", "nd", "rd"][dayOfMonth % 10 > 3
|
||||
? 0
|
||||
: ((dayOfMonth - (dayOfMonth % 10) !== 10 ? 1 : 0) * dayOfMonth) % 10]);
|
||||
}
|
||||
};
|
||||
var globalI18n = assign({}, defaultI18n);
|
||||
var setGlobalDateI18n = function (i18n) {
|
||||
return (globalI18n = assign(globalI18n, i18n));
|
||||
};
|
||||
var regexEscape = function (str) {
|
||||
return str.replace(/[|\\{()[^$+*?.-]/g, "\\$&");
|
||||
};
|
||||
var pad = function (val, len) {
|
||||
if (len === void 0) { len = 2; }
|
||||
val = String(val);
|
||||
while (val.length < len) {
|
||||
val = "0" + val;
|
||||
}
|
||||
return val;
|
||||
};
|
||||
var formatFlags = {
|
||||
D: function (dateObj) { return String(dateObj.getDate()); },
|
||||
DD: function (dateObj) { return pad(dateObj.getDate()); },
|
||||
Do: function (dateObj, i18n) {
|
||||
return i18n.DoFn(dateObj.getDate());
|
||||
},
|
||||
d: function (dateObj) { return String(dateObj.getDay()); },
|
||||
dd: function (dateObj) { return pad(dateObj.getDay()); },
|
||||
ddd: function (dateObj, i18n) {
|
||||
return i18n.dayNamesShort[dateObj.getDay()];
|
||||
},
|
||||
dddd: function (dateObj, i18n) {
|
||||
return i18n.dayNames[dateObj.getDay()];
|
||||
},
|
||||
M: function (dateObj) { return String(dateObj.getMonth() + 1); },
|
||||
MM: function (dateObj) { return pad(dateObj.getMonth() + 1); },
|
||||
MMM: function (dateObj, i18n) {
|
||||
return i18n.monthNamesShort[dateObj.getMonth()];
|
||||
},
|
||||
MMMM: function (dateObj, i18n) {
|
||||
return i18n.monthNames[dateObj.getMonth()];
|
||||
},
|
||||
YY: function (dateObj) {
|
||||
return pad(String(dateObj.getFullYear()), 4).substr(2);
|
||||
},
|
||||
YYYY: function (dateObj) { return pad(dateObj.getFullYear(), 4); },
|
||||
h: function (dateObj) { return String(dateObj.getHours() % 12 || 12); },
|
||||
hh: function (dateObj) { return pad(dateObj.getHours() % 12 || 12); },
|
||||
H: function (dateObj) { return String(dateObj.getHours()); },
|
||||
HH: function (dateObj) { return pad(dateObj.getHours()); },
|
||||
m: function (dateObj) { return String(dateObj.getMinutes()); },
|
||||
mm: function (dateObj) { return pad(dateObj.getMinutes()); },
|
||||
s: function (dateObj) { return String(dateObj.getSeconds()); },
|
||||
ss: function (dateObj) { return pad(dateObj.getSeconds()); },
|
||||
S: function (dateObj) {
|
||||
return String(Math.round(dateObj.getMilliseconds() / 100));
|
||||
},
|
||||
SS: function (dateObj) {
|
||||
return pad(Math.round(dateObj.getMilliseconds() / 10), 2);
|
||||
},
|
||||
SSS: function (dateObj) { return pad(dateObj.getMilliseconds(), 3); },
|
||||
a: function (dateObj, i18n) {
|
||||
return dateObj.getHours() < 12 ? i18n.amPm[0] : i18n.amPm[1];
|
||||
},
|
||||
A: function (dateObj, i18n) {
|
||||
return dateObj.getHours() < 12
|
||||
? i18n.amPm[0].toUpperCase()
|
||||
: i18n.amPm[1].toUpperCase();
|
||||
},
|
||||
ZZ: function (dateObj) {
|
||||
var offset = dateObj.getTimezoneOffset();
|
||||
return ((offset > 0 ? "-" : "+") +
|
||||
pad(Math.floor(Math.abs(offset) / 60) * 100 + (Math.abs(offset) % 60), 4));
|
||||
},
|
||||
Z: function (dateObj) {
|
||||
var offset = dateObj.getTimezoneOffset();
|
||||
return ((offset > 0 ? "-" : "+") +
|
||||
pad(Math.floor(Math.abs(offset) / 60), 2) +
|
||||
":" +
|
||||
pad(Math.abs(offset) % 60, 2));
|
||||
}
|
||||
};
|
||||
var monthParse = function (v) { return +v - 1; };
|
||||
var emptyDigits = [null, twoDigitsOptional];
|
||||
var emptyWord = [null, word];
|
||||
var amPm = [
|
||||
"isPm",
|
||||
word,
|
||||
function (v, i18n) {
|
||||
var val = v.toLowerCase();
|
||||
if (val === i18n.amPm[0]) {
|
||||
return 0;
|
||||
}
|
||||
else if (val === i18n.amPm[1]) {
|
||||
return 1;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
];
|
||||
var timezoneOffset = [
|
||||
"timezoneOffset",
|
||||
"[^\\s]*?[\\+\\-]\\d\\d:?\\d\\d|[^\\s]*?Z?",
|
||||
function (v) {
|
||||
var parts = (v + "").match(/([+-]|\d\d)/gi);
|
||||
if (parts) {
|
||||
var minutes = +parts[1] * 60 + parseInt(parts[2], 10);
|
||||
return parts[0] === "+" ? minutes : -minutes;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
];
|
||||
var parseFlags = {
|
||||
D: ["day", twoDigitsOptional],
|
||||
DD: ["day", twoDigits],
|
||||
Do: ["day", twoDigitsOptional + word, function (v) { return parseInt(v, 10); }],
|
||||
M: ["month", twoDigitsOptional, monthParse],
|
||||
MM: ["month", twoDigits, monthParse],
|
||||
YY: [
|
||||
"year",
|
||||
twoDigits,
|
||||
function (v) {
|
||||
var now = new Date();
|
||||
var cent = +("" + now.getFullYear()).substr(0, 2);
|
||||
return +("" + (+v > 68 ? cent - 1 : cent) + v);
|
||||
}
|
||||
],
|
||||
h: ["hour", twoDigitsOptional, undefined, "isPm"],
|
||||
hh: ["hour", twoDigits, undefined, "isPm"],
|
||||
H: ["hour", twoDigitsOptional],
|
||||
HH: ["hour", twoDigits],
|
||||
m: ["minute", twoDigitsOptional],
|
||||
mm: ["minute", twoDigits],
|
||||
s: ["second", twoDigitsOptional],
|
||||
ss: ["second", twoDigits],
|
||||
YYYY: ["year", fourDigits],
|
||||
S: ["millisecond", "\\d", function (v) { return +v * 100; }],
|
||||
SS: ["millisecond", twoDigits, function (v) { return +v * 10; }],
|
||||
SSS: ["millisecond", threeDigits],
|
||||
d: emptyDigits,
|
||||
dd: emptyDigits,
|
||||
ddd: emptyWord,
|
||||
dddd: emptyWord,
|
||||
MMM: ["month", word, monthUpdate("monthNamesShort")],
|
||||
MMMM: ["month", word, monthUpdate("monthNames")],
|
||||
a: amPm,
|
||||
A: amPm,
|
||||
ZZ: timezoneOffset,
|
||||
Z: timezoneOffset
|
||||
};
|
||||
// Some common format strings
|
||||
var globalMasks = {
|
||||
default: "ddd MMM DD YYYY HH:mm:ss",
|
||||
shortDate: "M/D/YY",
|
||||
mediumDate: "MMM D, YYYY",
|
||||
longDate: "MMMM D, YYYY",
|
||||
fullDate: "dddd, MMMM D, YYYY",
|
||||
isoDate: "YYYY-MM-DD",
|
||||
isoDateTime: "YYYY-MM-DDTHH:mm:ssZ",
|
||||
shortTime: "HH:mm",
|
||||
mediumTime: "HH:mm:ss",
|
||||
longTime: "HH:mm:ss.SSS"
|
||||
};
|
||||
var setGlobalDateMasks = function (masks) { return assign(globalMasks, masks); };
|
||||
/***
|
||||
* Format a date
|
||||
* @method format
|
||||
* @param {Date|number} dateObj
|
||||
* @param {string} mask Format of the date, i.e. 'mm-dd-yy' or 'shortDate'
|
||||
* @returns {string} Formatted date string
|
||||
*/
|
||||
var format = function (dateObj, mask, i18n) {
|
||||
if (mask === void 0) { mask = globalMasks["default"]; }
|
||||
if (i18n === void 0) { i18n = {}; }
|
||||
if (typeof dateObj === "number") {
|
||||
dateObj = new Date(dateObj);
|
||||
}
|
||||
if (Object.prototype.toString.call(dateObj) !== "[object Date]" ||
|
||||
isNaN(dateObj.getTime())) {
|
||||
throw new Error("Invalid Date pass to format");
|
||||
}
|
||||
mask = globalMasks[mask] || mask;
|
||||
var literals = [];
|
||||
// Make literals inactive by replacing them with @@@
|
||||
mask = mask.replace(literal, function ($0, $1) {
|
||||
literals.push($1);
|
||||
return "@@@";
|
||||
});
|
||||
var combinedI18nSettings = assign(assign({}, globalI18n), i18n);
|
||||
// Apply formatting rules
|
||||
mask = mask.replace(token, function ($0) {
|
||||
return formatFlags[$0](dateObj, combinedI18nSettings);
|
||||
});
|
||||
// Inline literal values back into the formatted value
|
||||
return mask.replace(/@@@/g, function () { return literals.shift(); });
|
||||
};
|
||||
/**
|
||||
* Parse a date string into a Javascript Date object /
|
||||
* @method parse
|
||||
* @param {string} dateStr Date string
|
||||
* @param {string} format Date parse format
|
||||
* @param {i18n} I18nSettingsOptional Full or subset of I18N settings
|
||||
* @returns {Date|null} Returns Date object. Returns null what date string is invalid or doesn't match format
|
||||
*/
|
||||
function parse(dateStr, format, i18n) {
|
||||
if (i18n === void 0) { i18n = {}; }
|
||||
if (typeof format !== "string") {
|
||||
throw new Error("Invalid format in fecha parse");
|
||||
}
|
||||
// Check to see if the format is actually a mask
|
||||
format = globalMasks[format] || format;
|
||||
// Avoid regular expression denial of service, fail early for really long strings
|
||||
// https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS
|
||||
if (dateStr.length > 1000) {
|
||||
return null;
|
||||
}
|
||||
// Default to the beginning of the year.
|
||||
var today = new Date();
|
||||
var dateInfo = {
|
||||
year: today.getFullYear(),
|
||||
month: 0,
|
||||
day: 1,
|
||||
hour: 0,
|
||||
minute: 0,
|
||||
second: 0,
|
||||
millisecond: 0,
|
||||
isPm: null,
|
||||
timezoneOffset: null
|
||||
};
|
||||
var parseInfo = [];
|
||||
var literals = [];
|
||||
// Replace all the literals with @@@. Hopefully a string that won't exist in the format
|
||||
var newFormat = format.replace(literal, function ($0, $1) {
|
||||
literals.push(regexEscape($1));
|
||||
return "@@@";
|
||||
});
|
||||
var specifiedFields = {};
|
||||
var requiredFields = {};
|
||||
// Change every token that we find into the correct regex
|
||||
newFormat = regexEscape(newFormat).replace(token, function ($0) {
|
||||
var info = parseFlags[$0];
|
||||
var field = info[0], regex = info[1], requiredField = info[3];
|
||||
// Check if the person has specified the same field twice. This will lead to confusing results.
|
||||
if (specifiedFields[field]) {
|
||||
throw new Error("Invalid format. " + field + " specified twice in format");
|
||||
}
|
||||
specifiedFields[field] = true;
|
||||
// Check if there are any required fields. For instance, 12 hour time requires AM/PM specified
|
||||
if (requiredField) {
|
||||
requiredFields[requiredField] = true;
|
||||
}
|
||||
parseInfo.push(info);
|
||||
return "(" + regex + ")";
|
||||
});
|
||||
// Check all the required fields are present
|
||||
Object.keys(requiredFields).forEach(function (field) {
|
||||
if (!specifiedFields[field]) {
|
||||
throw new Error("Invalid format. " + field + " is required in specified format");
|
||||
}
|
||||
});
|
||||
// Add back all the literals after
|
||||
newFormat = newFormat.replace(/@@@/g, function () { return literals.shift(); });
|
||||
// Check if the date string matches the format. If it doesn't return null
|
||||
var matches = dateStr.match(new RegExp(newFormat, "i"));
|
||||
if (!matches) {
|
||||
return null;
|
||||
}
|
||||
var combinedI18nSettings = assign(assign({}, globalI18n), i18n);
|
||||
// For each match, call the parser function for that date part
|
||||
for (var i = 1; i < matches.length; i++) {
|
||||
var _a = parseInfo[i - 1], field = _a[0], parser = _a[2];
|
||||
var value = parser
|
||||
? parser(matches[i], combinedI18nSettings)
|
||||
: +matches[i];
|
||||
// If the parser can't make sense of the value, return null
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
dateInfo[field] = value;
|
||||
}
|
||||
if (dateInfo.isPm === 1 && dateInfo.hour != null && +dateInfo.hour !== 12) {
|
||||
dateInfo.hour = +dateInfo.hour + 12;
|
||||
}
|
||||
else if (dateInfo.isPm === 0 && +dateInfo.hour === 12) {
|
||||
dateInfo.hour = 0;
|
||||
}
|
||||
var dateTZ;
|
||||
if (dateInfo.timezoneOffset == null) {
|
||||
dateTZ = new Date(dateInfo.year, dateInfo.month, dateInfo.day, dateInfo.hour, dateInfo.minute, dateInfo.second, dateInfo.millisecond);
|
||||
var validateFields = [
|
||||
["month", "getMonth"],
|
||||
["day", "getDate"],
|
||||
["hour", "getHours"],
|
||||
["minute", "getMinutes"],
|
||||
["second", "getSeconds"]
|
||||
];
|
||||
for (var i = 0, len = validateFields.length; i < len; i++) {
|
||||
// Check to make sure the date field is within the allowed range. Javascript dates allows values
|
||||
// outside the allowed range. If the values don't match the value was invalid
|
||||
if (specifiedFields[validateFields[i][0]] &&
|
||||
dateInfo[validateFields[i][0]] !== dateTZ[validateFields[i][1]]()) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
dateTZ = new Date(Date.UTC(dateInfo.year, dateInfo.month, dateInfo.day, dateInfo.hour, dateInfo.minute - dateInfo.timezoneOffset, dateInfo.second, dateInfo.millisecond));
|
||||
// We can't validate dates in another timezone unfortunately. Do a basic check instead
|
||||
if (dateInfo.month > 11 ||
|
||||
dateInfo.month < 0 ||
|
||||
dateInfo.day > 31 ||
|
||||
dateInfo.day < 1 ||
|
||||
dateInfo.hour > 23 ||
|
||||
dateInfo.hour < 0 ||
|
||||
dateInfo.minute > 59 ||
|
||||
dateInfo.minute < 0 ||
|
||||
dateInfo.second > 59 ||
|
||||
dateInfo.second < 0) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// Don't allow invalid dates
|
||||
return dateTZ;
|
||||
}
|
||||
var fecha = {
|
||||
format: format,
|
||||
parse: parse,
|
||||
defaultI18n: defaultI18n,
|
||||
setGlobalDateI18n: setGlobalDateI18n,
|
||||
setGlobalDateMasks: setGlobalDateMasks
|
||||
};
|
||||
|
||||
export default fecha;
|
||||
export { assign, format, parse, defaultI18n, setGlobalDateI18n, setGlobalDateMasks };
|
||||
//# sourceMappingURL=fecha.js.map
|
1
node_modules/fecha/lib/fecha.js.map
generated
vendored
Normal file
1
node_modules/fecha/lib/fecha.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
418
node_modules/fecha/lib/fecha.umd.js
generated
vendored
Normal file
418
node_modules/fecha/lib/fecha.umd.js
generated
vendored
Normal file
|
@ -0,0 +1,418 @@
|
|||
(function (global, factory) {
|
||||
typeof exports === 'object' && typeof module !== 'undefined' ? factory(exports) :
|
||||
typeof define === 'function' && define.amd ? define(['exports'], factory) :
|
||||
(factory((global.fecha = {})));
|
||||
}(this, (function (exports) { 'use strict';
|
||||
|
||||
var token = /d{1,4}|M{1,4}|YY(?:YY)?|S{1,3}|Do|ZZ|Z|([HhMsDm])\1?|[aA]|"[^"]*"|'[^']*'/g;
|
||||
var twoDigitsOptional = "\\d\\d?";
|
||||
var twoDigits = "\\d\\d";
|
||||
var threeDigits = "\\d{3}";
|
||||
var fourDigits = "\\d{4}";
|
||||
var word = "[^\\s]+";
|
||||
var literal = /\[([^]*?)\]/gm;
|
||||
function shorten(arr, sLen) {
|
||||
var newArr = [];
|
||||
for (var i = 0, len = arr.length; i < len; i++) {
|
||||
newArr.push(arr[i].substr(0, sLen));
|
||||
}
|
||||
return newArr;
|
||||
}
|
||||
var monthUpdate = function (arrName) { return function (v, i18n) {
|
||||
var lowerCaseArr = i18n[arrName].map(function (v) { return v.toLowerCase(); });
|
||||
var index = lowerCaseArr.indexOf(v.toLowerCase());
|
||||
if (index > -1) {
|
||||
return index;
|
||||
}
|
||||
return null;
|
||||
}; };
|
||||
function assign(origObj) {
|
||||
var args = [];
|
||||
for (var _i = 1; _i < arguments.length; _i++) {
|
||||
args[_i - 1] = arguments[_i];
|
||||
}
|
||||
for (var _a = 0, args_1 = args; _a < args_1.length; _a++) {
|
||||
var obj = args_1[_a];
|
||||
for (var key in obj) {
|
||||
// @ts-ignore ex
|
||||
origObj[key] = obj[key];
|
||||
}
|
||||
}
|
||||
return origObj;
|
||||
}
|
||||
var dayNames = [
|
||||
"Sunday",
|
||||
"Monday",
|
||||
"Tuesday",
|
||||
"Wednesday",
|
||||
"Thursday",
|
||||
"Friday",
|
||||
"Saturday"
|
||||
];
|
||||
var monthNames = [
|
||||
"January",
|
||||
"February",
|
||||
"March",
|
||||
"April",
|
||||
"May",
|
||||
"June",
|
||||
"July",
|
||||
"August",
|
||||
"September",
|
||||
"October",
|
||||
"November",
|
||||
"December"
|
||||
];
|
||||
var monthNamesShort = shorten(monthNames, 3);
|
||||
var dayNamesShort = shorten(dayNames, 3);
|
||||
var defaultI18n = {
|
||||
dayNamesShort: dayNamesShort,
|
||||
dayNames: dayNames,
|
||||
monthNamesShort: monthNamesShort,
|
||||
monthNames: monthNames,
|
||||
amPm: ["am", "pm"],
|
||||
DoFn: function (dayOfMonth) {
|
||||
return (dayOfMonth +
|
||||
["th", "st", "nd", "rd"][dayOfMonth % 10 > 3
|
||||
? 0
|
||||
: ((dayOfMonth - (dayOfMonth % 10) !== 10 ? 1 : 0) * dayOfMonth) % 10]);
|
||||
}
|
||||
};
|
||||
var globalI18n = assign({}, defaultI18n);
|
||||
var setGlobalDateI18n = function (i18n) {
|
||||
return (globalI18n = assign(globalI18n, i18n));
|
||||
};
|
||||
var regexEscape = function (str) {
|
||||
return str.replace(/[|\\{()[^$+*?.-]/g, "\\$&");
|
||||
};
|
||||
var pad = function (val, len) {
|
||||
if (len === void 0) { len = 2; }
|
||||
val = String(val);
|
||||
while (val.length < len) {
|
||||
val = "0" + val;
|
||||
}
|
||||
return val;
|
||||
};
|
||||
var formatFlags = {
|
||||
D: function (dateObj) { return String(dateObj.getDate()); },
|
||||
DD: function (dateObj) { return pad(dateObj.getDate()); },
|
||||
Do: function (dateObj, i18n) {
|
||||
return i18n.DoFn(dateObj.getDate());
|
||||
},
|
||||
d: function (dateObj) { return String(dateObj.getDay()); },
|
||||
dd: function (dateObj) { return pad(dateObj.getDay()); },
|
||||
ddd: function (dateObj, i18n) {
|
||||
return i18n.dayNamesShort[dateObj.getDay()];
|
||||
},
|
||||
dddd: function (dateObj, i18n) {
|
||||
return i18n.dayNames[dateObj.getDay()];
|
||||
},
|
||||
M: function (dateObj) { return String(dateObj.getMonth() + 1); },
|
||||
MM: function (dateObj) { return pad(dateObj.getMonth() + 1); },
|
||||
MMM: function (dateObj, i18n) {
|
||||
return i18n.monthNamesShort[dateObj.getMonth()];
|
||||
},
|
||||
MMMM: function (dateObj, i18n) {
|
||||
return i18n.monthNames[dateObj.getMonth()];
|
||||
},
|
||||
YY: function (dateObj) {
|
||||
return pad(String(dateObj.getFullYear()), 4).substr(2);
|
||||
},
|
||||
YYYY: function (dateObj) { return pad(dateObj.getFullYear(), 4); },
|
||||
h: function (dateObj) { return String(dateObj.getHours() % 12 || 12); },
|
||||
hh: function (dateObj) { return pad(dateObj.getHours() % 12 || 12); },
|
||||
H: function (dateObj) { return String(dateObj.getHours()); },
|
||||
HH: function (dateObj) { return pad(dateObj.getHours()); },
|
||||
m: function (dateObj) { return String(dateObj.getMinutes()); },
|
||||
mm: function (dateObj) { return pad(dateObj.getMinutes()); },
|
||||
s: function (dateObj) { return String(dateObj.getSeconds()); },
|
||||
ss: function (dateObj) { return pad(dateObj.getSeconds()); },
|
||||
S: function (dateObj) {
|
||||
return String(Math.round(dateObj.getMilliseconds() / 100));
|
||||
},
|
||||
SS: function (dateObj) {
|
||||
return pad(Math.round(dateObj.getMilliseconds() / 10), 2);
|
||||
},
|
||||
SSS: function (dateObj) { return pad(dateObj.getMilliseconds(), 3); },
|
||||
a: function (dateObj, i18n) {
|
||||
return dateObj.getHours() < 12 ? i18n.amPm[0] : i18n.amPm[1];
|
||||
},
|
||||
A: function (dateObj, i18n) {
|
||||
return dateObj.getHours() < 12
|
||||
? i18n.amPm[0].toUpperCase()
|
||||
: i18n.amPm[1].toUpperCase();
|
||||
},
|
||||
ZZ: function (dateObj) {
|
||||
var offset = dateObj.getTimezoneOffset();
|
||||
return ((offset > 0 ? "-" : "+") +
|
||||
pad(Math.floor(Math.abs(offset) / 60) * 100 + (Math.abs(offset) % 60), 4));
|
||||
},
|
||||
Z: function (dateObj) {
|
||||
var offset = dateObj.getTimezoneOffset();
|
||||
return ((offset > 0 ? "-" : "+") +
|
||||
pad(Math.floor(Math.abs(offset) / 60), 2) +
|
||||
":" +
|
||||
pad(Math.abs(offset) % 60, 2));
|
||||
}
|
||||
};
|
||||
var monthParse = function (v) { return +v - 1; };
|
||||
var emptyDigits = [null, twoDigitsOptional];
|
||||
var emptyWord = [null, word];
|
||||
var amPm = [
|
||||
"isPm",
|
||||
word,
|
||||
function (v, i18n) {
|
||||
var val = v.toLowerCase();
|
||||
if (val === i18n.amPm[0]) {
|
||||
return 0;
|
||||
}
|
||||
else if (val === i18n.amPm[1]) {
|
||||
return 1;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
];
|
||||
var timezoneOffset = [
|
||||
"timezoneOffset",
|
||||
"[^\\s]*?[\\+\\-]\\d\\d:?\\d\\d|[^\\s]*?Z?",
|
||||
function (v) {
|
||||
var parts = (v + "").match(/([+-]|\d\d)/gi);
|
||||
if (parts) {
|
||||
var minutes = +parts[1] * 60 + parseInt(parts[2], 10);
|
||||
return parts[0] === "+" ? minutes : -minutes;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
];
|
||||
var parseFlags = {
|
||||
D: ["day", twoDigitsOptional],
|
||||
DD: ["day", twoDigits],
|
||||
Do: ["day", twoDigitsOptional + word, function (v) { return parseInt(v, 10); }],
|
||||
M: ["month", twoDigitsOptional, monthParse],
|
||||
MM: ["month", twoDigits, monthParse],
|
||||
YY: [
|
||||
"year",
|
||||
twoDigits,
|
||||
function (v) {
|
||||
var now = new Date();
|
||||
var cent = +("" + now.getFullYear()).substr(0, 2);
|
||||
return +("" + (+v > 68 ? cent - 1 : cent) + v);
|
||||
}
|
||||
],
|
||||
h: ["hour", twoDigitsOptional, undefined, "isPm"],
|
||||
hh: ["hour", twoDigits, undefined, "isPm"],
|
||||
H: ["hour", twoDigitsOptional],
|
||||
HH: ["hour", twoDigits],
|
||||
m: ["minute", twoDigitsOptional],
|
||||
mm: ["minute", twoDigits],
|
||||
s: ["second", twoDigitsOptional],
|
||||
ss: ["second", twoDigits],
|
||||
YYYY: ["year", fourDigits],
|
||||
S: ["millisecond", "\\d", function (v) { return +v * 100; }],
|
||||
SS: ["millisecond", twoDigits, function (v) { return +v * 10; }],
|
||||
SSS: ["millisecond", threeDigits],
|
||||
d: emptyDigits,
|
||||
dd: emptyDigits,
|
||||
ddd: emptyWord,
|
||||
dddd: emptyWord,
|
||||
MMM: ["month", word, monthUpdate("monthNamesShort")],
|
||||
MMMM: ["month", word, monthUpdate("monthNames")],
|
||||
a: amPm,
|
||||
A: amPm,
|
||||
ZZ: timezoneOffset,
|
||||
Z: timezoneOffset
|
||||
};
|
||||
// Some common format strings
|
||||
var globalMasks = {
|
||||
default: "ddd MMM DD YYYY HH:mm:ss",
|
||||
shortDate: "M/D/YY",
|
||||
mediumDate: "MMM D, YYYY",
|
||||
longDate: "MMMM D, YYYY",
|
||||
fullDate: "dddd, MMMM D, YYYY",
|
||||
isoDate: "YYYY-MM-DD",
|
||||
isoDateTime: "YYYY-MM-DDTHH:mm:ssZ",
|
||||
shortTime: "HH:mm",
|
||||
mediumTime: "HH:mm:ss",
|
||||
longTime: "HH:mm:ss.SSS"
|
||||
};
|
||||
var setGlobalDateMasks = function (masks) { return assign(globalMasks, masks); };
|
||||
/***
|
||||
* Format a date
|
||||
* @method format
|
||||
* @param {Date|number} dateObj
|
||||
* @param {string} mask Format of the date, i.e. 'mm-dd-yy' or 'shortDate'
|
||||
* @returns {string} Formatted date string
|
||||
*/
|
||||
var format = function (dateObj, mask, i18n) {
|
||||
if (mask === void 0) { mask = globalMasks["default"]; }
|
||||
if (i18n === void 0) { i18n = {}; }
|
||||
if (typeof dateObj === "number") {
|
||||
dateObj = new Date(dateObj);
|
||||
}
|
||||
if (Object.prototype.toString.call(dateObj) !== "[object Date]" ||
|
||||
isNaN(dateObj.getTime())) {
|
||||
throw new Error("Invalid Date pass to format");
|
||||
}
|
||||
mask = globalMasks[mask] || mask;
|
||||
var literals = [];
|
||||
// Make literals inactive by replacing them with @@@
|
||||
mask = mask.replace(literal, function ($0, $1) {
|
||||
literals.push($1);
|
||||
return "@@@";
|
||||
});
|
||||
var combinedI18nSettings = assign(assign({}, globalI18n), i18n);
|
||||
// Apply formatting rules
|
||||
mask = mask.replace(token, function ($0) {
|
||||
return formatFlags[$0](dateObj, combinedI18nSettings);
|
||||
});
|
||||
// Inline literal values back into the formatted value
|
||||
return mask.replace(/@@@/g, function () { return literals.shift(); });
|
||||
};
|
||||
/**
|
||||
* Parse a date string into a Javascript Date object /
|
||||
* @method parse
|
||||
* @param {string} dateStr Date string
|
||||
* @param {string} format Date parse format
|
||||
* @param {i18n} I18nSettingsOptional Full or subset of I18N settings
|
||||
* @returns {Date|null} Returns Date object. Returns null what date string is invalid or doesn't match format
|
||||
*/
|
||||
function parse(dateStr, format, i18n) {
|
||||
if (i18n === void 0) { i18n = {}; }
|
||||
if (typeof format !== "string") {
|
||||
throw new Error("Invalid format in fecha parse");
|
||||
}
|
||||
// Check to see if the format is actually a mask
|
||||
format = globalMasks[format] || format;
|
||||
// Avoid regular expression denial of service, fail early for really long strings
|
||||
// https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS
|
||||
if (dateStr.length > 1000) {
|
||||
return null;
|
||||
}
|
||||
// Default to the beginning of the year.
|
||||
var today = new Date();
|
||||
var dateInfo = {
|
||||
year: today.getFullYear(),
|
||||
month: 0,
|
||||
day: 1,
|
||||
hour: 0,
|
||||
minute: 0,
|
||||
second: 0,
|
||||
millisecond: 0,
|
||||
isPm: null,
|
||||
timezoneOffset: null
|
||||
};
|
||||
var parseInfo = [];
|
||||
var literals = [];
|
||||
// Replace all the literals with @@@. Hopefully a string that won't exist in the format
|
||||
var newFormat = format.replace(literal, function ($0, $1) {
|
||||
literals.push(regexEscape($1));
|
||||
return "@@@";
|
||||
});
|
||||
var specifiedFields = {};
|
||||
var requiredFields = {};
|
||||
// Change every token that we find into the correct regex
|
||||
newFormat = regexEscape(newFormat).replace(token, function ($0) {
|
||||
var info = parseFlags[$0];
|
||||
var field = info[0], regex = info[1], requiredField = info[3];
|
||||
// Check if the person has specified the same field twice. This will lead to confusing results.
|
||||
if (specifiedFields[field]) {
|
||||
throw new Error("Invalid format. " + field + " specified twice in format");
|
||||
}
|
||||
specifiedFields[field] = true;
|
||||
// Check if there are any required fields. For instance, 12 hour time requires AM/PM specified
|
||||
if (requiredField) {
|
||||
requiredFields[requiredField] = true;
|
||||
}
|
||||
parseInfo.push(info);
|
||||
return "(" + regex + ")";
|
||||
});
|
||||
// Check all the required fields are present
|
||||
Object.keys(requiredFields).forEach(function (field) {
|
||||
if (!specifiedFields[field]) {
|
||||
throw new Error("Invalid format. " + field + " is required in specified format");
|
||||
}
|
||||
});
|
||||
// Add back all the literals after
|
||||
newFormat = newFormat.replace(/@@@/g, function () { return literals.shift(); });
|
||||
// Check if the date string matches the format. If it doesn't return null
|
||||
var matches = dateStr.match(new RegExp(newFormat, "i"));
|
||||
if (!matches) {
|
||||
return null;
|
||||
}
|
||||
var combinedI18nSettings = assign(assign({}, globalI18n), i18n);
|
||||
// For each match, call the parser function for that date part
|
||||
for (var i = 1; i < matches.length; i++) {
|
||||
var _a = parseInfo[i - 1], field = _a[0], parser = _a[2];
|
||||
var value = parser
|
||||
? parser(matches[i], combinedI18nSettings)
|
||||
: +matches[i];
|
||||
// If the parser can't make sense of the value, return null
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
dateInfo[field] = value;
|
||||
}
|
||||
if (dateInfo.isPm === 1 && dateInfo.hour != null && +dateInfo.hour !== 12) {
|
||||
dateInfo.hour = +dateInfo.hour + 12;
|
||||
}
|
||||
else if (dateInfo.isPm === 0 && +dateInfo.hour === 12) {
|
||||
dateInfo.hour = 0;
|
||||
}
|
||||
var dateTZ;
|
||||
if (dateInfo.timezoneOffset == null) {
|
||||
dateTZ = new Date(dateInfo.year, dateInfo.month, dateInfo.day, dateInfo.hour, dateInfo.minute, dateInfo.second, dateInfo.millisecond);
|
||||
var validateFields = [
|
||||
["month", "getMonth"],
|
||||
["day", "getDate"],
|
||||
["hour", "getHours"],
|
||||
["minute", "getMinutes"],
|
||||
["second", "getSeconds"]
|
||||
];
|
||||
for (var i = 0, len = validateFields.length; i < len; i++) {
|
||||
// Check to make sure the date field is within the allowed range. Javascript dates allows values
|
||||
// outside the allowed range. If the values don't match the value was invalid
|
||||
if (specifiedFields[validateFields[i][0]] &&
|
||||
dateInfo[validateFields[i][0]] !== dateTZ[validateFields[i][1]]()) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
dateTZ = new Date(Date.UTC(dateInfo.year, dateInfo.month, dateInfo.day, dateInfo.hour, dateInfo.minute - dateInfo.timezoneOffset, dateInfo.second, dateInfo.millisecond));
|
||||
// We can't validate dates in another timezone unfortunately. Do a basic check instead
|
||||
if (dateInfo.month > 11 ||
|
||||
dateInfo.month < 0 ||
|
||||
dateInfo.day > 31 ||
|
||||
dateInfo.day < 1 ||
|
||||
dateInfo.hour > 23 ||
|
||||
dateInfo.hour < 0 ||
|
||||
dateInfo.minute > 59 ||
|
||||
dateInfo.minute < 0 ||
|
||||
dateInfo.second > 59 ||
|
||||
dateInfo.second < 0) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
// Don't allow invalid dates
|
||||
return dateTZ;
|
||||
}
|
||||
var fecha = {
|
||||
format: format,
|
||||
parse: parse,
|
||||
defaultI18n: defaultI18n,
|
||||
setGlobalDateI18n: setGlobalDateI18n,
|
||||
setGlobalDateMasks: setGlobalDateMasks
|
||||
};
|
||||
|
||||
exports.assign = assign;
|
||||
exports.default = fecha;
|
||||
exports.format = format;
|
||||
exports.parse = parse;
|
||||
exports.defaultI18n = defaultI18n;
|
||||
exports.setGlobalDateI18n = setGlobalDateI18n;
|
||||
exports.setGlobalDateMasks = setGlobalDateMasks;
|
||||
|
||||
Object.defineProperty(exports, '__esModule', { value: true });
|
||||
|
||||
})));
|
||||
//# sourceMappingURL=fecha.umd.js.map
|
1
node_modules/fecha/lib/fecha.umd.js.map
generated
vendored
Normal file
1
node_modules/fecha/lib/fecha.umd.js.map
generated
vendored
Normal file
File diff suppressed because one or more lines are too long
55
node_modules/fecha/package.json
generated
vendored
Normal file
55
node_modules/fecha/package.json
generated
vendored
Normal file
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
"name": "fecha",
|
||||
"version": "4.2.3",
|
||||
"description": "Date formatting and parsing",
|
||||
"main": "lib/fecha.umd.js",
|
||||
"module": "lib/fecha.js",
|
||||
"scripts": {
|
||||
"test-only": "ts-node test.js",
|
||||
"test": "prettier --check *.js src/*.ts && eslint --ext .ts src && npm run build && nyc --cache --reporter=text ts-node test.js",
|
||||
"build": "NODE_ENV=production rollup -c --sourcemap && tsc",
|
||||
"format": "prettier --write *.js src/*.ts"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://taylorhakes@github.com/taylorhakes/fecha.git"
|
||||
},
|
||||
"keywords": [
|
||||
"date",
|
||||
"parse",
|
||||
"moment",
|
||||
"format",
|
||||
"fecha",
|
||||
"formatting"
|
||||
],
|
||||
"author": "Taylor Hakes",
|
||||
"license": "MIT",
|
||||
"bugs": {
|
||||
"url": "https://github.com/taylorhakes/fecha/issues"
|
||||
},
|
||||
"homepage": "https://github.com/taylorhakes/fecha",
|
||||
"devDependencies": {
|
||||
"@istanbuljs/nyc-config-typescript": "^1.0.1",
|
||||
"@typescript-eslint/eslint-plugin": "^2.14.0",
|
||||
"@typescript-eslint/parser": "^2.14.0",
|
||||
"eslint": "^7.23.0",
|
||||
"eslint-config-prettier": "^8.1.0",
|
||||
"nyc": "^15.0.0",
|
||||
"painless": "^0.9.7",
|
||||
"prettier": "1.19.1",
|
||||
"rollup": "^0.59.0",
|
||||
"rollup-plugin-sourcemaps": "^0.5.0",
|
||||
"rollup-plugin-typescript": "^1.0.1",
|
||||
"rollup-plugin-uglify": "^3.0.0",
|
||||
"source-map-support": "^0.5.16",
|
||||
"ts-node": "^8.5.4",
|
||||
"tslib": "^1.10.0",
|
||||
"typescript": "^3.7.4"
|
||||
},
|
||||
"files": [
|
||||
"lib",
|
||||
"dist",
|
||||
"src"
|
||||
],
|
||||
"types": "lib/fecha.d.ts"
|
||||
}
|
524
node_modules/fecha/src/fecha.ts
generated
vendored
Normal file
524
node_modules/fecha/src/fecha.ts
generated
vendored
Normal file
|
@ -0,0 +1,524 @@
|
|||
const token = /d{1,4}|M{1,4}|YY(?:YY)?|S{1,3}|Do|ZZ|Z|([HhMsDm])\1?|[aA]|"[^"]*"|'[^']*'/g;
|
||||
const twoDigitsOptional = "\\d\\d?";
|
||||
const twoDigits = "\\d\\d";
|
||||
const threeDigits = "\\d{3}";
|
||||
const fourDigits = "\\d{4}";
|
||||
const word = "[^\\s]+";
|
||||
const literal = /\[([^]*?)\]/gm;
|
||||
|
||||
type DateInfo = {
|
||||
year: number;
|
||||
month: number;
|
||||
day: number;
|
||||
hour: number;
|
||||
minute: number;
|
||||
second: number;
|
||||
millisecond: number;
|
||||
isPm: number | null;
|
||||
timezoneOffset: number | null;
|
||||
};
|
||||
|
||||
export type I18nSettings = {
|
||||
amPm: [string, string];
|
||||
dayNames: Days;
|
||||
dayNamesShort: Days;
|
||||
monthNames: Months;
|
||||
monthNamesShort: Months;
|
||||
DoFn(dayOfMonth: number): string;
|
||||
};
|
||||
|
||||
export type I18nSettingsOptional = Partial<I18nSettings>;
|
||||
|
||||
export type Days = [string, string, string, string, string, string, string];
|
||||
export type Months = [
|
||||
string,
|
||||
string,
|
||||
string,
|
||||
string,
|
||||
string,
|
||||
string,
|
||||
string,
|
||||
string,
|
||||
string,
|
||||
string,
|
||||
string,
|
||||
string
|
||||
];
|
||||
|
||||
function shorten<T extends string[]>(arr: T, sLen: number): string[] {
|
||||
const newArr: string[] = [];
|
||||
for (let i = 0, len = arr.length; i < len; i++) {
|
||||
newArr.push(arr[i].substr(0, sLen));
|
||||
}
|
||||
return newArr;
|
||||
}
|
||||
|
||||
const monthUpdate = (
|
||||
arrName: "monthNames" | "monthNamesShort" | "dayNames" | "dayNamesShort"
|
||||
) => (v: string, i18n: I18nSettings): number | null => {
|
||||
const lowerCaseArr = i18n[arrName].map(v => v.toLowerCase());
|
||||
const index = lowerCaseArr.indexOf(v.toLowerCase());
|
||||
if (index > -1) {
|
||||
return index;
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
export function assign<A>(a: A): A;
|
||||
export function assign<A, B>(a: A, b: B): A & B;
|
||||
export function assign<A, B, C>(a: A, b: B, c: C): A & B & C;
|
||||
export function assign<A, B, C, D>(a: A, b: B, c: C, d: D): A & B & C & D;
|
||||
export function assign(origObj: any, ...args: any[]): any {
|
||||
for (const obj of args) {
|
||||
for (const key in obj) {
|
||||
// @ts-ignore ex
|
||||
origObj[key] = obj[key];
|
||||
}
|
||||
}
|
||||
return origObj;
|
||||
}
|
||||
|
||||
const dayNames: Days = [
|
||||
"Sunday",
|
||||
"Monday",
|
||||
"Tuesday",
|
||||
"Wednesday",
|
||||
"Thursday",
|
||||
"Friday",
|
||||
"Saturday"
|
||||
];
|
||||
const monthNames: Months = [
|
||||
"January",
|
||||
"February",
|
||||
"March",
|
||||
"April",
|
||||
"May",
|
||||
"June",
|
||||
"July",
|
||||
"August",
|
||||
"September",
|
||||
"October",
|
||||
"November",
|
||||
"December"
|
||||
];
|
||||
|
||||
const monthNamesShort: Months = shorten(monthNames, 3) as Months;
|
||||
const dayNamesShort: Days = shorten(dayNames, 3) as Days;
|
||||
|
||||
const defaultI18n: I18nSettings = {
|
||||
dayNamesShort,
|
||||
dayNames,
|
||||
monthNamesShort,
|
||||
monthNames,
|
||||
amPm: ["am", "pm"],
|
||||
DoFn(dayOfMonth: number) {
|
||||
return (
|
||||
dayOfMonth +
|
||||
["th", "st", "nd", "rd"][
|
||||
dayOfMonth % 10 > 3
|
||||
? 0
|
||||
: ((dayOfMonth - (dayOfMonth % 10) !== 10 ? 1 : 0) * dayOfMonth) % 10
|
||||
]
|
||||
);
|
||||
}
|
||||
};
|
||||
let globalI18n = assign({}, defaultI18n);
|
||||
const setGlobalDateI18n = (i18n: I18nSettingsOptional): I18nSettings =>
|
||||
(globalI18n = assign(globalI18n, i18n));
|
||||
|
||||
const regexEscape = (str: string): string =>
|
||||
str.replace(/[|\\{()[^$+*?.-]/g, "\\$&");
|
||||
|
||||
const pad = (val: string | number, len = 2): string => {
|
||||
val = String(val);
|
||||
while (val.length < len) {
|
||||
val = "0" + val;
|
||||
}
|
||||
return val;
|
||||
};
|
||||
|
||||
const formatFlags: Record<
|
||||
string,
|
||||
(dateObj: Date, i18n: I18nSettings) => string
|
||||
> = {
|
||||
D: (dateObj: Date): string => String(dateObj.getDate()),
|
||||
DD: (dateObj: Date): string => pad(dateObj.getDate()),
|
||||
Do: (dateObj: Date, i18n: I18nSettings): string =>
|
||||
i18n.DoFn(dateObj.getDate()),
|
||||
d: (dateObj: Date): string => String(dateObj.getDay()),
|
||||
dd: (dateObj: Date): string => pad(dateObj.getDay()),
|
||||
ddd: (dateObj: Date, i18n: I18nSettings): string =>
|
||||
i18n.dayNamesShort[dateObj.getDay()],
|
||||
dddd: (dateObj: Date, i18n: I18nSettings): string =>
|
||||
i18n.dayNames[dateObj.getDay()],
|
||||
M: (dateObj: Date): string => String(dateObj.getMonth() + 1),
|
||||
MM: (dateObj: Date): string => pad(dateObj.getMonth() + 1),
|
||||
MMM: (dateObj: Date, i18n: I18nSettings): string =>
|
||||
i18n.monthNamesShort[dateObj.getMonth()],
|
||||
MMMM: (dateObj: Date, i18n: I18nSettings): string =>
|
||||
i18n.monthNames[dateObj.getMonth()],
|
||||
YY: (dateObj: Date): string =>
|
||||
pad(String(dateObj.getFullYear()), 4).substr(2),
|
||||
YYYY: (dateObj: Date): string => pad(dateObj.getFullYear(), 4),
|
||||
h: (dateObj: Date): string => String(dateObj.getHours() % 12 || 12),
|
||||
hh: (dateObj: Date): string => pad(dateObj.getHours() % 12 || 12),
|
||||
H: (dateObj: Date): string => String(dateObj.getHours()),
|
||||
HH: (dateObj: Date): string => pad(dateObj.getHours()),
|
||||
m: (dateObj: Date): string => String(dateObj.getMinutes()),
|
||||
mm: (dateObj: Date): string => pad(dateObj.getMinutes()),
|
||||
s: (dateObj: Date): string => String(dateObj.getSeconds()),
|
||||
ss: (dateObj: Date): string => pad(dateObj.getSeconds()),
|
||||
S: (dateObj: Date): string =>
|
||||
String(Math.round(dateObj.getMilliseconds() / 100)),
|
||||
SS: (dateObj: Date): string =>
|
||||
pad(Math.round(dateObj.getMilliseconds() / 10), 2),
|
||||
SSS: (dateObj: Date): string => pad(dateObj.getMilliseconds(), 3),
|
||||
a: (dateObj: Date, i18n: I18nSettings): string =>
|
||||
dateObj.getHours() < 12 ? i18n.amPm[0] : i18n.amPm[1],
|
||||
A: (dateObj: Date, i18n: I18nSettings): string =>
|
||||
dateObj.getHours() < 12
|
||||
? i18n.amPm[0].toUpperCase()
|
||||
: i18n.amPm[1].toUpperCase(),
|
||||
ZZ(dateObj: Date): string {
|
||||
const offset = dateObj.getTimezoneOffset();
|
||||
return (
|
||||
(offset > 0 ? "-" : "+") +
|
||||
pad(Math.floor(Math.abs(offset) / 60) * 100 + (Math.abs(offset) % 60), 4)
|
||||
);
|
||||
},
|
||||
Z(dateObj: Date): string {
|
||||
const offset = dateObj.getTimezoneOffset();
|
||||
return (
|
||||
(offset > 0 ? "-" : "+") +
|
||||
pad(Math.floor(Math.abs(offset) / 60), 2) +
|
||||
":" +
|
||||
pad(Math.abs(offset) % 60, 2)
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
type ParseInfo = [
|
||||
keyof DateInfo,
|
||||
string,
|
||||
((v: string, i18n: I18nSettings) => number | null)?,
|
||||
string?
|
||||
];
|
||||
const monthParse = (v: string): number => +v - 1;
|
||||
const emptyDigits: ParseInfo = [null, twoDigitsOptional];
|
||||
const emptyWord: ParseInfo = [null, word];
|
||||
const amPm: ParseInfo = [
|
||||
"isPm",
|
||||
word,
|
||||
(v: string, i18n: I18nSettings): number | null => {
|
||||
const val = v.toLowerCase();
|
||||
if (val === i18n.amPm[0]) {
|
||||
return 0;
|
||||
} else if (val === i18n.amPm[1]) {
|
||||
return 1;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
];
|
||||
const timezoneOffset: ParseInfo = [
|
||||
"timezoneOffset",
|
||||
"[^\\s]*?[\\+\\-]\\d\\d:?\\d\\d|[^\\s]*?Z?",
|
||||
(v: string): number | null => {
|
||||
const parts = (v + "").match(/([+-]|\d\d)/gi);
|
||||
|
||||
if (parts) {
|
||||
const minutes = +parts[1] * 60 + parseInt(parts[2], 10);
|
||||
return parts[0] === "+" ? minutes : -minutes;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
];
|
||||
const parseFlags: Record<string, ParseInfo> = {
|
||||
D: ["day", twoDigitsOptional],
|
||||
DD: ["day", twoDigits],
|
||||
Do: ["day", twoDigitsOptional + word, (v: string): number => parseInt(v, 10)],
|
||||
M: ["month", twoDigitsOptional, monthParse],
|
||||
MM: ["month", twoDigits, monthParse],
|
||||
YY: [
|
||||
"year",
|
||||
twoDigits,
|
||||
(v: string): number => {
|
||||
const now = new Date();
|
||||
const cent = +("" + now.getFullYear()).substr(0, 2);
|
||||
return +("" + (+v > 68 ? cent - 1 : cent) + v);
|
||||
}
|
||||
],
|
||||
h: ["hour", twoDigitsOptional, undefined, "isPm"],
|
||||
hh: ["hour", twoDigits, undefined, "isPm"],
|
||||
H: ["hour", twoDigitsOptional],
|
||||
HH: ["hour", twoDigits],
|
||||
m: ["minute", twoDigitsOptional],
|
||||
mm: ["minute", twoDigits],
|
||||
s: ["second", twoDigitsOptional],
|
||||
ss: ["second", twoDigits],
|
||||
YYYY: ["year", fourDigits],
|
||||
S: ["millisecond", "\\d", (v: string): number => +v * 100],
|
||||
SS: ["millisecond", twoDigits, (v: string): number => +v * 10],
|
||||
SSS: ["millisecond", threeDigits],
|
||||
d: emptyDigits,
|
||||
dd: emptyDigits,
|
||||
ddd: emptyWord,
|
||||
dddd: emptyWord,
|
||||
MMM: ["month", word, monthUpdate("monthNamesShort")],
|
||||
MMMM: ["month", word, monthUpdate("monthNames")],
|
||||
a: amPm,
|
||||
A: amPm,
|
||||
ZZ: timezoneOffset,
|
||||
Z: timezoneOffset
|
||||
};
|
||||
|
||||
// Some common format strings
|
||||
const globalMasks: { [key: string]: string } = {
|
||||
default: "ddd MMM DD YYYY HH:mm:ss",
|
||||
shortDate: "M/D/YY",
|
||||
mediumDate: "MMM D, YYYY",
|
||||
longDate: "MMMM D, YYYY",
|
||||
fullDate: "dddd, MMMM D, YYYY",
|
||||
isoDate: "YYYY-MM-DD",
|
||||
isoDateTime: "YYYY-MM-DDTHH:mm:ssZ",
|
||||
shortTime: "HH:mm",
|
||||
mediumTime: "HH:mm:ss",
|
||||
longTime: "HH:mm:ss.SSS"
|
||||
};
|
||||
const setGlobalDateMasks = (masks: {
|
||||
[key: string]: string;
|
||||
}): { [key: string]: string } => assign(globalMasks, masks);
|
||||
|
||||
/***
|
||||
* Format a date
|
||||
* @method format
|
||||
* @param {Date|number} dateObj
|
||||
* @param {string} mask Format of the date, i.e. 'mm-dd-yy' or 'shortDate'
|
||||
* @returns {string} Formatted date string
|
||||
*/
|
||||
const format = (
|
||||
dateObj: Date,
|
||||
mask: string = globalMasks["default"],
|
||||
i18n: I18nSettingsOptional = {}
|
||||
): string => {
|
||||
if (typeof dateObj === "number") {
|
||||
dateObj = new Date(dateObj);
|
||||
}
|
||||
|
||||
if (
|
||||
Object.prototype.toString.call(dateObj) !== "[object Date]" ||
|
||||
isNaN(dateObj.getTime())
|
||||
) {
|
||||
throw new Error("Invalid Date pass to format");
|
||||
}
|
||||
|
||||
mask = globalMasks[mask] || mask;
|
||||
|
||||
const literals: string[] = [];
|
||||
|
||||
// Make literals inactive by replacing them with @@@
|
||||
mask = mask.replace(literal, function($0, $1) {
|
||||
literals.push($1);
|
||||
return "@@@";
|
||||
});
|
||||
|
||||
const combinedI18nSettings: I18nSettings = assign(
|
||||
assign({}, globalI18n),
|
||||
i18n
|
||||
);
|
||||
// Apply formatting rules
|
||||
mask = mask.replace(token, $0 =>
|
||||
formatFlags[$0](dateObj, combinedI18nSettings)
|
||||
);
|
||||
// Inline literal values back into the formatted value
|
||||
return mask.replace(/@@@/g, () => literals.shift());
|
||||
};
|
||||
|
||||
/**
|
||||
* Parse a date string into a Javascript Date object /
|
||||
* @method parse
|
||||
* @param {string} dateStr Date string
|
||||
* @param {string} format Date parse format
|
||||
* @param {i18n} I18nSettingsOptional Full or subset of I18N settings
|
||||
* @returns {Date|null} Returns Date object. Returns null what date string is invalid or doesn't match format
|
||||
*/
|
||||
function parse(
|
||||
dateStr: string,
|
||||
format: string,
|
||||
i18n: I18nSettingsOptional = {}
|
||||
): Date | null {
|
||||
if (typeof format !== "string") {
|
||||
throw new Error("Invalid format in fecha parse");
|
||||
}
|
||||
|
||||
// Check to see if the format is actually a mask
|
||||
format = globalMasks[format] || format;
|
||||
|
||||
// Avoid regular expression denial of service, fail early for really long strings
|
||||
// https://www.owasp.org/index.php/Regular_expression_Denial_of_Service_-_ReDoS
|
||||
if (dateStr.length > 1000) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// Default to the beginning of the year.
|
||||
const today = new Date();
|
||||
const dateInfo: DateInfo = {
|
||||
year: today.getFullYear(),
|
||||
month: 0,
|
||||
day: 1,
|
||||
hour: 0,
|
||||
minute: 0,
|
||||
second: 0,
|
||||
millisecond: 0,
|
||||
isPm: null,
|
||||
timezoneOffset: null
|
||||
};
|
||||
const parseInfo: ParseInfo[] = [];
|
||||
const literals: string[] = [];
|
||||
|
||||
// Replace all the literals with @@@. Hopefully a string that won't exist in the format
|
||||
let newFormat = format.replace(literal, ($0, $1) => {
|
||||
literals.push(regexEscape($1));
|
||||
return "@@@";
|
||||
});
|
||||
const specifiedFields: { [field: string]: boolean } = {};
|
||||
const requiredFields: { [field: string]: boolean } = {};
|
||||
|
||||
// Change every token that we find into the correct regex
|
||||
newFormat = regexEscape(newFormat).replace(token, $0 => {
|
||||
const info = parseFlags[$0];
|
||||
const [field, regex, , requiredField] = info;
|
||||
|
||||
// Check if the person has specified the same field twice. This will lead to confusing results.
|
||||
if (specifiedFields[field]) {
|
||||
throw new Error(`Invalid format. ${field} specified twice in format`);
|
||||
}
|
||||
|
||||
specifiedFields[field] = true;
|
||||
|
||||
// Check if there are any required fields. For instance, 12 hour time requires AM/PM specified
|
||||
if (requiredField) {
|
||||
requiredFields[requiredField] = true;
|
||||
}
|
||||
|
||||
parseInfo.push(info);
|
||||
return "(" + regex + ")";
|
||||
});
|
||||
|
||||
// Check all the required fields are present
|
||||
Object.keys(requiredFields).forEach(field => {
|
||||
if (!specifiedFields[field]) {
|
||||
throw new Error(
|
||||
`Invalid format. ${field} is required in specified format`
|
||||
);
|
||||
}
|
||||
});
|
||||
|
||||
// Add back all the literals after
|
||||
newFormat = newFormat.replace(/@@@/g, () => literals.shift());
|
||||
|
||||
// Check if the date string matches the format. If it doesn't return null
|
||||
const matches = dateStr.match(new RegExp(newFormat, "i"));
|
||||
if (!matches) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const combinedI18nSettings: I18nSettings = assign(
|
||||
assign({}, globalI18n),
|
||||
i18n
|
||||
);
|
||||
|
||||
// For each match, call the parser function for that date part
|
||||
for (let i = 1; i < matches.length; i++) {
|
||||
const [field, , parser] = parseInfo[i - 1];
|
||||
const value = parser
|
||||
? parser(matches[i], combinedI18nSettings)
|
||||
: +matches[i];
|
||||
|
||||
// If the parser can't make sense of the value, return null
|
||||
if (value == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
dateInfo[field] = value;
|
||||
}
|
||||
|
||||
if (dateInfo.isPm === 1 && dateInfo.hour != null && +dateInfo.hour !== 12) {
|
||||
dateInfo.hour = +dateInfo.hour + 12;
|
||||
} else if (dateInfo.isPm === 0 && +dateInfo.hour === 12) {
|
||||
dateInfo.hour = 0;
|
||||
}
|
||||
|
||||
let dateTZ: Date;
|
||||
if (dateInfo.timezoneOffset == null) {
|
||||
dateTZ = new Date(
|
||||
dateInfo.year,
|
||||
dateInfo.month,
|
||||
dateInfo.day,
|
||||
dateInfo.hour,
|
||||
dateInfo.minute,
|
||||
dateInfo.second,
|
||||
dateInfo.millisecond
|
||||
);
|
||||
const validateFields: [
|
||||
"month" | "day" | "hour" | "minute" | "second",
|
||||
"getMonth" | "getDate" | "getHours" | "getMinutes" | "getSeconds"
|
||||
][] = [
|
||||
["month", "getMonth"],
|
||||
["day", "getDate"],
|
||||
["hour", "getHours"],
|
||||
["minute", "getMinutes"],
|
||||
["second", "getSeconds"]
|
||||
];
|
||||
for (let i = 0, len = validateFields.length; i < len; i++) {
|
||||
// Check to make sure the date field is within the allowed range. Javascript dates allows values
|
||||
// outside the allowed range. If the values don't match the value was invalid
|
||||
if (
|
||||
specifiedFields[validateFields[i][0]] &&
|
||||
dateInfo[validateFields[i][0]] !== dateTZ[validateFields[i][1]]()
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
dateTZ = new Date(
|
||||
Date.UTC(
|
||||
dateInfo.year,
|
||||
dateInfo.month,
|
||||
dateInfo.day,
|
||||
dateInfo.hour,
|
||||
dateInfo.minute - dateInfo.timezoneOffset,
|
||||
dateInfo.second,
|
||||
dateInfo.millisecond
|
||||
)
|
||||
);
|
||||
|
||||
// We can't validate dates in another timezone unfortunately. Do a basic check instead
|
||||
if (
|
||||
dateInfo.month > 11 ||
|
||||
dateInfo.month < 0 ||
|
||||
dateInfo.day > 31 ||
|
||||
dateInfo.day < 1 ||
|
||||
dateInfo.hour > 23 ||
|
||||
dateInfo.hour < 0 ||
|
||||
dateInfo.minute > 59 ||
|
||||
dateInfo.minute < 0 ||
|
||||
dateInfo.second > 59 ||
|
||||
dateInfo.second < 0
|
||||
) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
// Don't allow invalid dates
|
||||
|
||||
return dateTZ;
|
||||
}
|
||||
export default {
|
||||
format,
|
||||
parse,
|
||||
defaultI18n,
|
||||
setGlobalDateI18n,
|
||||
setGlobalDateMasks
|
||||
};
|
||||
export { format, parse, defaultI18n, setGlobalDateI18n, setGlobalDateMasks };
|
Loading…
Add table
Add a link
Reference in a new issue