UNPKG

@commercetools-uikit/calendar-time-utils

Version:

Utilities to work with time values for a calendar.

231 lines (221 loc) • 9.79 kB
import _slicedToArray from '@babel/runtime-corejs3/helpers/esm/slicedToArray'; import _parseInt from '@babel/runtime-corejs3/core-js-stable/parse-int'; import _sliceInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/slice'; import _mapInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/map'; import _Array$from from '@babel/runtime-corejs3/core-js-stable/array/from'; import _startsWithInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/starts-with'; import _Map from '@babel/runtime-corejs3/core-js-stable/map'; import _Object$entries from '@babel/runtime-corejs3/core-js-stable/object/entries'; import _reduceInstanceProperty from '@babel/runtime-corejs3/core-js-stable/instance/reduce'; import moment from 'moment-timezone'; import { warning, parseTime } from '@commercetools-uikit/utils'; // Reference: https://momentjs.com/docs/#/displaying/format/ const formatToken = { D: 'D', // NUMERIC_SINGLE_DAY DD: 'DD', // NUMERIC_TWO_DIGITS_DAY M: 'M', // NUMERIC_SINGLE_MONTH MM: 'MM', // NUMERIC_TWO_DIGIT_MONTH YY: 'YY', // TWO_DIGITS_YEAR YYYY: 'YYYY', // FOUR_DIGITS_YEAR h: 'h', // HOUR_12_SINGLE hh: 'hh', // HOUR_12_TWO_DIGITS H: 'H', // HOUR_24_SINGLE HH: 'HH', // HOUR_24_TWO_DIGITS m: 'm', // MINUTE_SINGLE mm: 'mm', // MINUTE_TWO_DIGITS A: 'A' // PERIOD - https://unicode.org/reports/tr35/tr35-6.html#Date_Format_Patterns }; // Here is where we translate from the standard characters used in the pattern // (calculated in the moment.js library) to the characters used in the locale // We just need to provide the translation for the characters that are different // For instance, in english we don't need to translate date characters as // they are the same as the pattern characters const DATE_FORMAT_LOCALIZED_MAPPINGS = { en: { // MM/DD/YYYY - h:mm A -> MM/DD/YYYY - HH:mm AM/PM [formatToken.h]: 'HH', [formatToken.A]: 'AM/PM' }, de: { // DD.MM.YYYY - HH:mm -> TT.MM.JJJJ - SS:mm [formatToken.DD]: 'TT', [formatToken.YYYY]: 'JJJJ', [formatToken.HH]: 'SS' }, es: { // DD/MM/YYYY - H:mm -> DD/MM/AAAA - HH:mm [formatToken.H]: 'HH', [formatToken.YYYY]: 'AAAA' }, fr: { // DD/MM/YYYY - HH:mm -> JJ/MM/AAAA - HH:mm [formatToken.DD]: 'JJ', [formatToken.YYYY]: 'AAAA' }, pt: { // DD/MM/YYYY - HH:mm -> DD/MM/AAAA - HH:mm [formatToken.YYYY]: 'AAAA' } }; const getDaysInMonth = (day, timeZone) => moment.tz(day, timeZone).daysInMonth(); const changeDateInMonth = (day, timeZone, dayOfMonth) => moment.tz(day, timeZone).date(dayOfMonth).toISOString(); const changeTime = (dateString, timeZone, parsedTime) => { const date = moment.tz(dateString, timeZone); date.hours(parsedTime.hours); date.minutes(parsedTime.minutes); date.seconds(parsedTime.seconds); date.seconds(parsedTime.seconds); date.milliseconds(parsedTime.milliseconds); return date.toISOString(); }; const getPreviousDay = day => moment(day).subtract(1, 'day').format('YYYY-MM-DD'); const formatDefaultTime = (time, locale) => { const today = moment(); if (moment(time, 'HH:mm', true).isValid()) { const _time$split = time.split(':'), _time$split2 = _slicedToArray(_time$split, 2), hour = _time$split2[0], minute = _time$split2[1]; today.set({ hour: _parseInt(hour, 10), minute: _parseInt(minute, 10) }); return moment(today).locale(locale).format('LT'); // 5:13 PM } else { process.env.NODE_ENV !== "production" ? warning(false, `DataTimeInput: the specified defaultDaySelectionTime '${time}' is not supported. The format should be hh:mm, e.g. 11:10. Using 00:00 as default time.`) : void 0; today.set({ hour: 0, minute: 0 }); return moment(today).locale(locale).format('LT'); // 12:00 AM } }; const formatTime = (day, locale, timeZone) => { const date = moment.tz(day, timeZone).locale(locale); if (date.milliseconds()) return date.format('HH:mm:ss.SSS'); if (date.seconds()) return date.format('LTS'); // 5:13:51 PM return date.format('LT'); // 5:13 PM }; const formatDate = (day, locale, timeZone) => { const date = moment(day, moment.ISO_8601, locale).tz(timeZone).format('L'); const time = formatTime(day, locale, timeZone); return `${date} ${time}`; }; const getDateInMonth = (day, timeZone) => moment.tz(day, timeZone).date(); const getToday = timeZone => moment.tz(timeZone).startOf('day').toISOString(); const changeMonth = (day, timeZone, delta) => moment.tz(day, timeZone).add(delta, 'month').toISOString(); const getPaddingDayCount = (day, locale, timeZone) => { const firstDayOfWeek = moment.localeData(locale).firstDayOfWeek(); const firstDayOfMonth = moment.tz(day, timeZone).startOf('month').day(); // ensure number is always positive return (firstDayOfMonth - firstDayOfWeek + 7) % 7; }; const getWeekdayNames = locale => { const weekDays = moment.localeData(locale).weekdaysMin(); const firstDay = moment.localeData(locale).firstDayOfWeek(); return [..._sliceInstanceProperty(weekDays).call(weekDays, firstDay), ..._sliceInstanceProperty(weekDays).call(weekDays, 0, firstDay)]; }; const getStartOf = (day, timeZone) => moment.tz(day, timeZone).startOf('day').toISOString(); const getMonthCalendarLabel = (day, locale, timeZone) => timeZone ? moment.tz(day, timeZone).locale(locale).format('MMMM') : moment(day, moment.ISO_8601, locale).format('MMMM'); const getYearCalendarLabel = (day, locale, timeZone) => timeZone ? moment.tz(day, timeZone).locale(locale).format('YYYY') : moment(day, moment.ISO_8601, locale).format('YYYY'); const isSameDay = (a, b) => moment(a).isSame(b, 'day'); const getCalendarDayLabel = (day, timeZone) => moment.tz(day, timeZone).format('D'); const createItemDateTimeToString = (locale, timeZone) => item => item ? formatDate(item, locale, timeZone) : ''; const createCalendarItems = (day, timeString, timeZone) => { var _context; const parsedTime = parseTime(timeString); return _mapInstanceProperty(_context = _Array$from({ length: getDaysInMonth(day, timeZone) })).call(_context, (_, i) => { const dayOfMonth = i + 1; let date = changeDateInMonth(day, timeZone, dayOfMonth); if (parsedTime) { date = changeTime(date, timeZone, parsedTime); } return date; }); }; const createSuggestedItems = (inputValue, timeZone) => { if (_startsWithInstanceProperty(inputValue).call(inputValue, 't')) return [getToday(timeZone)]; return []; }; const parseInputText = (text, locale, timeZone) => { const parts = text.split(' '); const dateString = parts[0]; const timeString = _sliceInstanceProperty(parts).call(parts, 1).join(' '); if (!dateString) return ''; const date = moment.tz(dateString, moment.localeData(locale).longDateFormat('L'), timeZone); if (!date.isValid()) return ''; // enable parsing a date only if (!timeString) return date.startOf('day').toISOString(); const parsedTime = parseTime(timeString); if (parsedTime) { date.hours(parsedTime.hours); date.minutes(parsedTime.minutes); date.seconds(parsedTime.seconds); date.seconds(parsedTime.seconds); date.milliseconds(parsedTime.milliseconds); return date.toISOString(); } return ''; }; const localizedDateFormatPatternCache = new _Map(); const getLocalizedDateTimeFormatPattern = function (locale) { let formatType = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'date'; const key = `${locale}::${formatType}`; if (localizedDateFormatPatternCache.has(key)) { return localizedDateFormatPatternCache.get(key); } // References: // https://momentjs.com/docs/#/i18n/locale-data/ // https://momentjs.com/docs/#/displaying/ ("Localized formats" section) const localeData = moment().locale(locale).localeData(); let localizedFormat = ''; switch (formatType) { case 'date': localizedFormat = localeData.longDateFormat('L'); break; case 'time': localizedFormat = localeData.longDateFormat('LT'); break; case 'full': localizedFormat = `${localeData.longDateFormat('L')} - ${localeData.longDateFormat('LT')}`; break; default: throw new Error(`CalendarTime.getLocalizedDateTimeFormatPattern: Unknown format type '${formatType}'`); } // We try to get the localization both with the whole locale (e.g. 'en-GB') // and the generic language code (e.g. 'en'). const _locale$split = locale.split('-'), _locale$split2 = _slicedToArray(_locale$split, 1), languageCode = _locale$split2[0]; const localeMappings = _Object$entries(DATE_FORMAT_LOCALIZED_MAPPINGS[locale] || DATE_FORMAT_LOCALIZED_MAPPINGS[languageCode] || {}); // In case we don't have a translation for the locale, we fallback to the // pattern from the moment locale data. let pattern = localizedFormat; if (localeMappings && localeMappings.length > 0) { pattern = _reduceInstanceProperty(localeMappings).call(localeMappings, (localizedPattern, _ref) => { let _ref2 = _slicedToArray(_ref, 2), token = _ref2[0], mappedValue = _ref2[1]; return localizedPattern.replace(token, mappedValue); }, localizedFormat); } localizedDateFormatPatternCache.set(key, pattern); return pattern; }; // NOTE: This string will be replaced on build time with the package version. var version = "20.2.2"; export { changeDateInMonth, changeMonth, changeTime, createCalendarItems, createItemDateTimeToString, createSuggestedItems, formatDate, formatDefaultTime, formatTime, getCalendarDayLabel, getDateInMonth, getDaysInMonth, getLocalizedDateTimeFormatPattern, getMonthCalendarLabel, getPaddingDayCount, getPreviousDay, getStartOf, getToday, getWeekdayNames, getYearCalendarLabel, isSameDay, parseInputText, version };