UNPKG

@busy-web/ember-date-time

Version:

Date time & and range picker for ember addon

316 lines (288 loc) 6.95 kB
/** * @module Utils/Time * */ import moment from 'moment'; import { isNone } from '@ember/utils'; import { assert } from '@ember/debug'; import { YEAR_FLAG, MONTH_FLAG, WEEKDAY_FLAG, DAY_FLAG, HOUR_FLAG, MINUTE_FLAG, MERIDIAN_FLAG } from '@busy-web/ember-date-time/utils/constant'; /** * Time utils for working with dates that will not * convert using timezones. Dates will remain the same * for input and output * * @class Time */ class Time extends moment.fn.constructor { constructor(...args) { super(...args); } timestamp() { return this.valueOf(); } addFormatted(value, format) { let type = convertType(format); if (type) { if (type === 'ampm') { type = 'h'; value = value * 12; } this.add(value, type); } else { throw new Error('Format not found for ' + type); } return this; } subFormatted(value, format) { let type = convertType(format); if (type) { if (type === 'ampm') { type = 'h'; value = value * 12; } this.subtract(value, type); } else { throw new Error('Format not found for ' + type); } return this; } } function _time(...args) { const m = moment.apply(this, args); return new Time(m); } _time.unix = time => new Time(moment.unix(time)); _time.utc = time => new Time(moment.utc(time)); _time.localeData = () => moment.localeData(); _time.locale = () => moment.locale(); _time.duration = (time, type) => moment.duration(time, type); // _time.daysApart = (start, end) => Math.floor(moment.duration(end - start, 'ms').asDays()); _time.daysApart = (start, end) => moment(end).diff(moment(start), 'days'); _time.hoursApart = (start, end) => Math.floor(moment.duration(end - start, 'ms').asHours()); _time.utcToLocal = function(time) { const m = moment.utc(time) .subtract(moment.utc(time).local().utcOffset(), 'minutes'); return new Time(m); }; _time.utcFromLocal = function(time) { const m = moment(time) .add(moment(time).utcOffset(), 'minutes'); return new Time(m); }; _time.round = function(time, round=1) { let date = moment(time); let minute = date.minute(); let dist = minute % round; let low = round - dist; if (low > dist) { minute -= dist; } else { minute += low; } date.minute(minute).seconds(0); return date.valueOf(); }; _time.standardFormatTypes = function() { return { YYYY: /Y{1,4}/, MM: /M(o|M)?/, DD: /D(o|D)?/, HH: /(HH?|hh?)/, mm: /mm?/, ss: /ss?/ }; }; _time.formatStringType = function(fmt) { if (/^D(o|D)?$/.test(fmt)) { return DAY_FLAG; } else if (/^d(o|d|dd|ddd)?$/.test(fmt)) { return WEEKDAY_FLAG; } else if (/^M(o|M|MM|MMM)?$/.test(fmt)) { return MONTH_FLAG; } else if (/^Y{1,4}$/.test(fmt)) { return YEAR_FLAG; } else if (/^hh?$/.test(fmt)) { return HOUR_FLAG; } else if (/^HH?$/.test(fmt)) { return 'm-hours'; } else if (/^mm?$/.test(fmt)) { return MINUTE_FLAG; } else if (/^ss?$/.test(fmt)) { return 'seconds'; } else if (/^A|a$/.test(fmt)) { return MERIDIAN_FLAG; } else { return null; } }; _time.typeExp = function(type) { if (type === DAY_FLAG) { return /D(o|D)?/; } else if (type === WEEKDAY_FLAG) { return /d(o|d|dd|ddd)?/; } else if (type === MONTH_FLAG) { return /M(o|M|MM|MMM)?/; } else if (type === YEAR_FLAG) { return /Y{1,4}/; } else if (type === HOUR_FLAG) { return /hh?/; } else if (type === 'm-hours') { return /HH?/; } else if (type === MINUTE_FLAG) { return /mm?/; } else if (type === 'seconds') { return /ss?/; } else if (type === MERIDIAN_FLAG) { return /A|a/; } }; /** * validates a moment date object * * @public * @method isValidDate * @param date {Moment} * @return {boolean} */ _time.isValidDate = function(date) { return !isNone(date) && typeof date === 'object' && moment.isMoment(date) && date.isValid(); }; /** * validates a timestamp or unix timestamp * * @public * @method isValidTimestamp * @param timestamp {number} * @return {boolean} */ _time.isValidTimestamp = function(timestamp) { let isValid = false; if (typeof timestamp === 'number' && !isNaN(timestamp)) { const date = _time(timestamp); isValid = _time.isValidDate(date); } return isValid; }; _time.isDateBefore = function(date, minDate) { let isBefore = false; if (!isNone(minDate)) { if (typeof minDate === 'number' && !isNaN(minDate)) { minDate = _time(minDate); } if (typeof date === 'number' && !isNaN(date)) { date = _time(date); } if (typeof minDate === 'object' && _time.isValidDate(minDate)) { isBefore = date.isBefore(minDate); } else { assert('Invalid minDate passed to isDateInBounds'); } } return isBefore; }; _time.isDateAfter = function(date, maxDate) { let isAfter = false; if (!isNone(maxDate)) { if (typeof maxDate === 'number' && !isNaN(maxDate)) { maxDate = _time(maxDate); } if (typeof date === 'number' && !isNaN(date)) { date = _time(date); } if (typeof maxDate === 'object' && _time.isValidDate(maxDate)) { isAfter = date.isAfter(maxDate); } else { assert('Invalid maxDate passed to isDateInBounds'); } } return isAfter; }; /** * checks if a timestamp is within the min and max dates * * returns an object with isBefore and isAfter boolean values * * @public * @method isDateInBounds * @param date {moment} moment date object * @param minDate {number|Moment} * @param maxDate {number|Moment} * @return {object|} {isBefore: boolean, isAfter: boolean} */ _time.isDateInBounds = function(date, minDate, maxDate) { const isBefore = _time.isDateBefore(date, minDate); const isAfter = _time.isDateAfter(date, maxDate); return { isBefore, isAfter }; }; function convertType(type) { let map = { '^(Y{1,4}|(gg){1,2}|(GG){1,2})$': 'y', '^M(o?|M{0,3})$': 'M', '^W(o|W)?$': 'w', '^Qo?$': 'Q', '^w(o|w)?$': 'w', '^D(o|DDo?|DD?D?)?$': 'd', '^d(o?|d{0,3})$': 'd', '^(HH?|hh?)$': 'h', '^mm?$': 'm', '^ss?$': 's', '^(A|a)$': 'ampm' }; let res; Object.keys(map).forEach(key => { if (res === undefined) { let reg = new RegExp(key); if (reg.test(type)) { res = map[key]; } } }); return res; } export default _time; const LOCALE_DATA = { "en": { this_day: 'Today', next_day: 'Tomorrow', last_day: 'Yesterday', this_week: 'This Week', next_week: 'Next Week', last_week: 'Last Week', this_month: 'This Month', next_month: 'Next Month', last_month: 'Last Month' }, "en-us": { this_day: 'Today', next_day: 'Tomorrow', last_day: 'Yesterday', this_week: 'This Week', next_week: 'Next Week', last_week: 'Last Week', this_month: 'This Month', next_month: 'Next Month', last_month: 'Last Month' }, "es": { this_day: 'Hoy', next_day: 'Mañana', last_day: 'Ayer', this_week: 'Esta Semana', next_week: 'La Próxima Semana', last_week: 'La Semana Pasada', this_month: 'Este Mes', next_month: 'Próximo Mes', last_month: 'El Mes Pasado' } }; export function i18n(key) { return LOCALE_DATA[_time.locale()][key]; }