export class MyDateConverter { private MONTHNAMES = 'January February March April May June July August September October November December'.split(' '); private MONTHNAMES_LOOKUP = { 'jan': 1, 'feb': 2, 'mar': 3, 'apr': 4, 'may': 5, 'jun': 6, 'jul': 7, 'aug': 8, 'sep': 9, 'oct': 10, 'nov': 11, 'dec': 12 }; /** * @var {Array} Abbreviated names for the months of the year */ private ABBR_MONTHNAMES = 'Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec'.split(' '); /** * @var {Array} Names for the days of the week from Sunday to Saturday */ private DAYNAMES = 'Sunday Monday Tuesday Wednesday Thursday Friday Saturday'.split(' '); private DAYNAMES_LOOKUP = { 'sun': 0, 'mon': 1, 'tue': 2, 'wed': 3, 'thu': 4, 'fri': 5, 'sat': 6 }; /** * @var {Array} Abbreviated names for the days of the week from Sunday to Saturday */ private ABBR_DAYNAMES = 'Sun Mon Tue Wed Thu Fri Sat'.split(' '); regexes = { YEAR: '[1-9]\\d{3}', MONTH: '1[0-2]|0?[1-9]', MONTH2: '1[0-2]|0[1-9]', MONTHNAME: 'jan|january|feb|february|mar|march|apr|april|may|jun|june|jul|july|aug|august|sep|september|oct|october|nov|november|dec|december', DAYNAME: 'mon|monday|tue|tuesday|wed|wednesday|thu|thursday|fri|friday|sat|saturday|sun|sunday', DAY: '3[01]|[12]\\d|0?[1-9]', DAY2: '3[01]|[12]\\d|0[1-9]', TIMEZONE: '[+-][01]\\d\\:?[0-5]\\d', H24: '[01]\\d|2[0-3]', MIN: '[0-5]\\d', SEC: '[0-5]\\d', MS: '\\d{3,}', H12: '0?[1-9]|1[012]', AMPM: 'am|pm', UNIT: 'year|month|week|day|hour|minute|second|millisecond' }; patterns = [ // 2010-03-15 [ 'iso_8601', this.makePattern('^(_YEAR_)-(_MONTH_)-(_DAY_)$'), '$2/$3/$1' ], // 3-15-2010 [ 'us', this.makePattern('^(_MONTH_)([\\/-])(_DAY_)\\2(_YEAR_)$'), '$1/$3/$4' ], // 15.03.2010 [ 'world', this.makePattern('^(_DAY_)([\\/\\.])(_MONTH_)\\2(_YEAR_)$'), '$3/$1/$4' ], // 15-Mar-2010, 8 Dec 2011, "Thu, 8 Dec 2011" [ 'chicago', this.makePattern('^(?:(?:_DAYNAME_),? )?(_DAY_)([ -])(_MONTHNAME_)\\2(_YEAR_)$'), '$3 $1, $4' ], // "March 4, 2012", "Mar 4 2012", "Sun Mar 4 2012" [ 'conversational', this.makePattern('^(?:(?:_DAYNAME_),? )?(_MONTHNAME_) (_DAY_),? (_YEAR_)$'), '$1 $2, $3' ], // Tue Jun 22 17:47:27 +0000 2010 [ 'month_day_time_year', this.makePattern('^(?:_DAYNAME_) (_MONTHNAME_) (_DAY_) ((?:_H24_)\\:(?:_MIN_)(?:\\:_SEC_)?) (_TIMEZONE_) (_YEAR_)$'), (m) => { const month = this.zeroPad(this.getMonthByName(m[1]), 2); const day = this.zeroPad(m[2], 2); const date: any = this.create(m[5] + '-' + month + '-' + day + 'T' + m[3] + m[4]); if (isNaN(date)) { return false; } return date; } ], // @123456789 [ 'unix', /^@(-?\d+)$/, (match) => { return this.create(parseInt(match[1], 10) * 1000); } ], // 24-hour time (This will help catch Date objects that are casted to a string) [ '24_hour', this.makePattern('^(?:(.+?)(?: |T))?(_H24_)\\:(_MIN_)(?:\\:(_SEC_)(?:\\.(_MS_))?)? ?(?:GMT)?(_TIMEZONE_)?(?: \\([A-Z]+\\))?$'), (match) => { let d; if (match[1]) { d = this.create(match[1]); if (isNaN(d)) { return false; } } else { d = Date.now(); d.setMilliseconds(0); } d.setHours(parseFloat(match[2]), parseFloat(match[3]), parseFloat(match[4] || 0)); if (match[5]) { d.setMilliseconds(+String(match[5]).slice(0, 3)); } if (match[6]) { d.setUTCOffsetString(match[6]); } return d; } ], // 12-hour time [ '12_hour', this.makePattern('^(?:(.+) )?(_H12_)(?:\\:(_MIN_)(?:\\:(_SEC_))?)? ?(_AMPM_)$'), (match) => { let d; if (match[1]) { d = this.create(match[1]); if (isNaN(d)) { return false; } } else { d = Date.now(); d.setMilliseconds(0); } let hour = parseFloat(match[2]); hour = match[5].toLowerCase() == 'am' ? (hour == 12 ? 0 : hour) : (hour == 12 ? 12 : hour + 12); d.setHours(hour, parseFloat(match[3] || 0), parseFloat(match[4] || 0)); return d; } ] ]; makePattern(code) { code = code.replace(/_([A-Z][A-Z0-9]+)_/g, ($0, $1) => { return this.regexes[$1]; }); return new RegExp(code, 'i'); } getMonthByName(monthname) { return this.MONTHNAMES_LOOKUP[String(monthname).slice(0, 3).toLowerCase()]; } getWeekdayByName(dayname) { return this.DAYNAMES_LOOKUP[String(dayname).slice(0, 3).toLowerCase()]; } private zeroPad(num, digits) { switch (digits - String(num).length) { case 2: return '00' + num; case 1: return '0' + num; } return num; } create(date) { // 0 arguments or date is undefined if (typeof date == 'undefined') { return Date.now(); } // If the passed value is already a date object, return it if (date instanceof Date) { return date; } const a = arguments; switch (a.length) { case 1: // If the passed value is an integer, interpret it as ms past epoch if (Object.prototype.toString.call(date) == '[object Number]') { return new Date(date); } // trim the date date = String(date).replace(/^\s*(.*)\s*$/, '$1'); // normalize whitespace date = date.replace(/\s{2,}/g, ' '); if (date === '') { return Date.now(); } var i = 0, pattern, ms, obj, match, regex, fn; // try each of our patterns while ((pattern = this.patterns[i++])) { if (typeof pattern[0] == 'string') { // pattern[0] is the name of the pattern regex = pattern[1]; fn = pattern[2]; } else { // backwards compatibility with version 3.1 regex = pattern[0]; fn = pattern[1]; } if (!(match = date.match(regex))) { continue; } if (typeof fn == 'function') { obj = fn(match, date); if (obj instanceof Date) { return obj; } } else { // fn is not a function but a string replace command ms = Date.parse(date.replace(regex, fn)); if (!isNaN(ms)) { return new Date(ms); } } } return NaN; case 2: return new Date(a[0], a[1], 1); case 3: return new Date(a[0], a[1], a[2]); case 4: return new Date(a[0], a[1], a[2], a[3]); case 5: return new Date(a[0], a[1], a[2], a[3], a[4]); case 6: return new Date(a[0], a[1], a[2], a[3], a[4], a[5]); default: return new Date(a[0], a[1], a[2], a[3], a[4], a[5], a[6]); } } }