import globalize from 'globalize'; /* eslint-disable indent */ export function parseISO8601Date(s, toLocal) { // parenthese matches: // year month day hours minutes seconds // dotmilliseconds // tzstring plusminus hours minutes const re = /(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(\.\d+)?(Z|([+-])(\d{2}):(\d{2}))?/; const d = s.match(re); // "2010-12-07T11:00:00.000-09:00" parses to: // ["2010-12-07T11:00:00.000-09:00", "2010", "12", "07", "11", // "00", "00", ".000", "-09:00", "-", "09", "00"] // "2010-12-07T11:00:00.000Z" parses to: // ["2010-12-07T11:00:00.000Z", "2010", "12", "07", "11", // "00", "00", ".000", "Z", undefined, undefined, undefined] if (!d) { throw "Couldn't parse ISO 8601 date string '" + s + "'"; } // parse strings, leading zeros into proper ints const a = [1, 2, 3, 4, 5, 6, 10, 11]; for (const i in a) { d[a[i]] = parseInt(d[a[i]], 10); } d[7] = parseFloat(d[7]); // Date.UTC(year, month[, date[, hrs[, min[, sec[, ms]]]]]) // note that month is 0-11, not 1-12 // see https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/UTC let ms = Date.UTC(d[1], d[2] - 1, d[3], d[4], d[5], d[6]); // if there are milliseconds, add them if (d[7] > 0) { ms += Math.round(d[7] * 1000); } // if there's a timezone, calculate it if (d[8] !== 'Z' && d[10]) { let offset = d[10] * 60 * 60 * 1000; if (d[11]) { offset += d[11] * 60 * 1000; } if (d[9] === '-') { ms -= offset; } else { ms += offset; } } else if (toLocal === false) { ms += new Date().getTimezoneOffset() * 60000; } return new Date(ms); } export function getDisplayRunningTime(ticks) { const ticksPerHour = 36000000000; const ticksPerMinute = 600000000; const ticksPerSecond = 10000000; const parts = []; let hours = ticks / ticksPerHour; hours = Math.floor(hours); if (hours) { parts.push(hours); } ticks -= (hours * ticksPerHour); let minutes = ticks / ticksPerMinute; minutes = Math.floor(minutes); ticks -= (minutes * ticksPerMinute); if (minutes < 10 && hours) { minutes = '0' + minutes; } parts.push(minutes); let seconds = ticks / ticksPerSecond; seconds = Math.floor(seconds); if (seconds < 10) { seconds = '0' + seconds; } parts.push(seconds); return parts.join(':'); } const toLocaleTimeStringSupportsLocales = function () { try { new Date().toLocaleTimeString('i'); } catch (e) { return e.name === 'RangeError'; } return false; }(); function getOptionList(options) { const list = []; for (const i in options) { list.push({ name: i, value: options[i] }); } return list; } export function toLocaleString(date, options) { if (!date) { throw new Error('date cannot be null'); } options = options || {}; if (toLocaleTimeStringSupportsLocales) { const currentLocale = globalize.getCurrentDateTimeLocale(); if (currentLocale) { return date.toLocaleString(currentLocale, options); } } return date.toLocaleString(); } export function toLocaleDateString(date, options) { if (!date) { throw new Error('date cannot be null'); } options = options || {}; if (toLocaleTimeStringSupportsLocales) { const currentLocale = globalize.getCurrentDateTimeLocale(); if (currentLocale) { return date.toLocaleDateString(currentLocale, options); } } // This is essentially a hard-coded polyfill const optionList = getOptionList(options); if (optionList.length === 1 && optionList[0].name === 'weekday') { const weekday = []; weekday[0] = 'Sun'; weekday[1] = 'Mon'; weekday[2] = 'Tue'; weekday[3] = 'Wed'; weekday[4] = 'Thu'; weekday[5] = 'Fri'; weekday[6] = 'Sat'; return weekday[date.getDay()]; } return date.toLocaleDateString(); } export function toLocaleTimeString(date, options) { if (!date) { throw new Error('date cannot be null'); } options = options || {}; if (toLocaleTimeStringSupportsLocales) { const currentLocale = globalize.getCurrentDateTimeLocale(); if (currentLocale) { return date.toLocaleTimeString(currentLocale, options); } } return date.toLocaleTimeString(); } export function getDisplayTime(date) { if (!date) { throw new Error('date cannot be null'); } if ((typeof date).toString().toLowerCase() === 'string') { try { date = parseISO8601Date(date, true); } catch (err) { return date; } } if (toLocaleTimeStringSupportsLocales) { return toLocaleTimeString(date, { hour: 'numeric', minute: '2-digit' }); } let time = toLocaleTimeString(date); const timeLower = time.toLowerCase(); if (timeLower.indexOf('am') !== -1 || timeLower.indexOf('pm') !== -1) { time = timeLower; let hour = date.getHours() % 12; const suffix = date.getHours() > 11 ? 'pm' : 'am'; if (!hour) { hour = 12; } let minutes = date.getMinutes(); if (minutes < 10) { minutes = '0' + minutes; } minutes = ':' + minutes; time = hour + minutes + suffix; } else { const timeParts = time.split(':'); // Trim off seconds if (timeParts.length > 2) { // setting to 2 also handles '21:00:28 GMT+9:30' timeParts.length = 2; time = timeParts.join(':'); } } return time; } export function isRelativeDay(date, offsetInDays) { if (!date) { throw new Error('date cannot be null'); } const yesterday = new Date(); const day = yesterday.getDate() + offsetInDays; yesterday.setDate(day); // automatically adjusts month/year appropriately return date.getFullYear() === yesterday.getFullYear() && date.getMonth() === yesterday.getMonth() && date.getDate() === day; } export default { parseISO8601Date: parseISO8601Date, getDisplayRunningTime: getDisplayRunningTime, toLocaleDateString: toLocaleDateString, toLocaleString: toLocaleString, getDisplayTime: getDisplayTime, isRelativeDay: isRelativeDay, toLocaleTimeString: toLocaleTimeString, supportsLocalization: function () { return toLocaleTimeStringSupportsLocales; } }; /* eslint-enable indent */