@commercetools-uikit/calendar-time-utils
Version:
Utilities to work with time values for a calendar.
231 lines (221 loc) • 9.79 kB
JavaScript
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 };