import {isDate, isString} from 'lodash';
import moment from 'moment';
import SHGlobals from 'sh-globals';
const HUMAN_DATE_TIME_FORMAT = 'MMM D, h:mma';
const HUMAN_DATE_MONTHLY_FORMAT = 'MMM D, YYYY';
const HUMAN_TIME_FORMAT = 'h:mma';
const splitTextDate = (date, delimeter) => {
const d = date.split(delimeter);
return new Date(d[2], d[0] - 1, d[1]);
};
const splitMobileDate = date => {
const d = date.split('-');
return new Date(d[0], d[1] - 1, d[2]);
};
/**
* Utilities for working with dates.
* @module DateUtils
*/
const DateUtils = {
/**
* Check whether input type of 'date' is supported in the current browser.
* @static
* @function supportsDateInput
* @example
* DateUtils.supportsDateInput();
* @returns {Boolean} - Whether the input type is supported.
*/
supportsDateInput() {
const fakeValue = 'not-a-date';
const input = document.createElement('input');
input.setAttribute('type', 'date');
input.setAttribute('value', fakeValue);
return (input.value !== fakeValue);
},
/**
* Converts a mobile input date to a string using the specified format.
* @static
* @function convertToDesktop
* @param {String} date - The input value in the format YYYY-MM-DD.
* @param {String} [format='MM/DD/YYYY'] - The output format.
* @example
* DateUtils.convertToDesktop('1983-01-19');
* @returns {String} - The formatted date.
*/
convertToDesktop(date, format = SHGlobals.DESKTOP_DATE_FORMAT) {
if (!isString(date)) {
throw new Error('The supplied date is not a string.');
}
if (date.indexOf('-') !== -1) {
return moment(splitMobileDate(date)).format(format);
} else {
return date;
}
},
/**
* Converts a desktop input date to the native mobile date format.
* @static
* @function convertToMobile
* @param {String} date - The input value in the format MM/DD/YYYY.
* @example
* DateUtils.convertToMobile('01/19/1983');
* @returns {String} - The mobile formatted date.
*/
convertToMobile(date) {
if (!isString(date)) {
throw new Error('The supplied date is not a string.');
}
if (date.indexOf('/') !== -1) {
return moment(splitTextDate(date, '/')).format(SHGlobals.MOBILE_DATE_FORMAT);
} else {
return date;
}
},
/**
* Converts a string date from a text or date input to a date object.
* @static
* @function getAsDate
* @param {String} date - The date in the format MM/DD/YYYY (text input) or YYYY-MM-DD (date input).
* @example
* DateUtils.getAsDate('1983-01-19');
* DateUtils.getAsDate('01/19/1983');
* @returns {Date} - The date object.
*/
getAsDate(date) {
if (!isString(date)) {
throw new Error('The supplied date is not a string.');
}
if (date.indexOf('-') !== -1) {
// date input
return splitMobileDate(date);
} else {
// text input
return splitTextDate(date, '/');
}
},
/**
* Converts a string date from a text or date input to a moment instance.
* @static
* @function getAsMoment
* @param {String} date - The date in the format MM/DD/YYYY (text input) or YYYY-MM-DD (date input).
* @example
* DateUtils.getAsMoment('1983-01-19');
* DateUtils.getAsMoment('01/19/1983');
* @returns {Moment} - The moment instance.
*/
getAsMoment(date) {
if (!isString(date)) {
throw new Error('The supplied date is not a string.');
}
if (date.indexOf('-') !== -1) {
// date input
return moment(splitMobileDate(date));
} else {
// text input
return moment(splitTextDate(date, '/'));
}
},
/**
* Combines a date moment with a time moment to return one moment instance.
* @static
* @function combineDateAndTime
* @param {Moment} date - The date as a moment instance.
* @param {Moment} time - The time as a moment instance.
* @example
* DateUtils.combineDateAndTime(moment(), moment().add(7, 'hours').add(23, 'minutes'));
* @returns {Moment} - The combined moment instance.
*/
combineDateAndTime(date, time) {
if (!moment.isMoment(date) || !moment.isMoment(time)) {
throw new Error('The date and/or time supplied was not an instance of Moment.');
}
return date.hours(time.hours()).minutes(time.minutes());
},
/**
* Checks if one date is before another.
* @static
* @function isBefore
* @param {Date} dateToCheck - The date to check.
* @param {Date} dateToCompare - The date to check against.
* @param {Boolean} [useTime=false] - Whether to use the time in the comparison.
* @example
* DateUtils.isBefore(new Date(2016, 1, 19), new Date(2016, 3, 14));
* @returns {Boolean} - Whether the provided date is before the one being checked against.
*/
isBefore(dateToCheck, dateToCompare, useTime = false) {
if (!isDate(dateToCheck) || !isDate(dateToCompare)) {
throw new Error('The dates supplied must be instances of the Date object.');
}
if (!useTime) {
dateToCheck.setHours(0, 0, 0, 0);
dateToCompare.setHours(0, 0, 0, 0);
}
return dateToCheck < dateToCompare;
},
/**
* Checks if one date is after another.
* @static
* @function isAfter
* @param {Date} dateToCheck - The date to check.
* @param {Date} dateToCompare - The date to check against.
* @param {Boolean} [useTime=false] - Whether to use the time in the comparison.
* @example
* DateUtils.isAfter(new Date(2016, 1, 19), new Date(2016, 3, 14));
* @returns {Boolean} - Whether the provided date is after the one being checked against.
*/
isAfter(dateToCheck, dateToCompare, useTime = false) {
if (!isDate(dateToCheck) || !isDate(dateToCompare)) {
throw new Error('The dates supplied must be instances of the Date object.');
}
if (!useTime) {
dateToCheck.setHours(0, 0, 0, 0);
dateToCompare.setHours(0, 0, 0, 0);
}
return dateToCheck > dateToCompare;
},
/**
* Returns human readable start and end datetime strings from moment objects.
* @static
* @function getHumanDateTimesAsStrings
* @param {Object} data - The data to pass to the function.
* @param {Moment} data.startDateTimeObj - The date as a moment instance.
* @param {Moment} data.endDateTimeObj - The time as a moment instance.
* @param {Boolean} data.isMonthly - Is startDateTimeObj a monthly datetime?
* @example
* DateUtils.getHumanDateTimesAsStrings({
* startDateTimeObj: moment(),
* endDateTimeObj: moment().add(7, 'hours').add(23, 'minutes')
* });
* @returns {Object} - Human readable strings returned for start and end
*/
getHumanDateTimesAsStrings({startDateTimeObj, endDateTimeObj, isMonthly}) {
if (!moment.isMoment(startDateTimeObj) || (!isMonthly && !moment.isMoment(endDateTimeObj))) {
throw new Error('The datetimes supplied are not an instance of Moment.');
}
let startString = null;
let endString = null;
if (startDateTimeObj) {
if (moment().startOf('day').diff(startDateTimeObj.clone().startOf('day')) === 0) {
startString = `Today${(!isMonthly) ? `, ${startDateTimeObj.format(HUMAN_TIME_FORMAT)}` : ''}`;
} else {
if (isMonthly) {
startString = startDateTimeObj.format(HUMAN_DATE_MONTHLY_FORMAT);
} else {
startString = startDateTimeObj.format(HUMAN_DATE_TIME_FORMAT);
}
}
}
if (!isMonthly && endDateTimeObj) {
if (startDateTimeObj.clone().startOf('day').diff(endDateTimeObj.clone().startOf('day')) === 0) {
if (moment().startOf('day').diff(endDateTimeObj.clone().startOf('day')) === 0) {
endString = 'Today, ' + endDateTimeObj.format(HUMAN_TIME_FORMAT);
} else {
endString = endDateTimeObj.format(HUMAN_DATE_TIME_FORMAT);
}
} else {
if (moment().clone().startOf('day').diff(endDateTimeObj.clone().startOf('day'), 'days') === -1) {
endString = `Tomorrow, ${endDateTimeObj.format(HUMAN_TIME_FORMAT)}`;
} else {
endString = endDateTimeObj.format(HUMAN_DATE_TIME_FORMAT);
}
}
}
return {
start: startString,
end: endString
};
}
};
export default DateUtils;