UNPKG

axiom-react-calendar

Version:

A component for picking dates or date periods for your React application.

519 lines (448 loc) 13.5 kB
/* Simple getters - getting a property of a given point in time */ export const getYear = (date) => { if (date instanceof Date) { return date.getFullYear(); } if (typeof date === 'number') { return date; } const year = parseInt(date, 10); if (typeof date === 'string' && !Number.isNaN(year)) { return year; } throw new Error(`Failed to get year from date: ${date}.`); }; export const getMonth = date => date.getMonth() + 1; export const getMonthIndex = date => date.getMonth(); export const getDay = date => date.getDate(); export const getDayOfWeek = (date, calendarType = 'ISO 8601') => { const weekday = date.getDay(); switch (calendarType) { case 'ISO 8601': // Shifts days of the week so that Monday is 0, Sunday is 6 return (weekday + 6) % 7; case 'US': return weekday; default: throw new Error('Unsupported calendar type.'); } }; /* Complex getters - getting a property somehow related to a given point in time */ export const getBeginOfCenturyYear = (date) => { const year = getYear(date) - 1; return year + (-year % 100) + 1; }; export const getBeginOfCentury = (date) => { const beginOfCenturyYear = getBeginOfCenturyYear(date); return new Date(beginOfCenturyYear, 0, 1); }; export const getEndOfCentury = (date) => { const beginOfCenturyYear = getBeginOfCenturyYear(date); return new Date(beginOfCenturyYear + 100, 0, 1, 0, 0, 0, -1); }; export const getCenturyRange = date => [ getBeginOfCentury(date), getEndOfCentury(date), ]; export const getBeginOfPreviousCentury = (date) => { const previousCenturyYear = getYear(date) - 100; return getBeginOfCentury(previousCenturyYear); }; export const getEndOfPreviousCentury = (date) => { const previousCenturyYear = getYear(date) - 100; return getEndOfCentury(previousCenturyYear); }; export const getBeginOfNextCentury = (date) => { const nextCenturyYear = getYear(date) + 100; return getBeginOfCentury(nextCenturyYear); }; export const getBeginOfDecadeYear = (date) => { const year = getYear(date) - 1; return year + (-year % 10) + 1; }; export const getBeginOfDecade = (date) => { const beginOfDecadeYear = getBeginOfDecadeYear(date); return new Date(beginOfDecadeYear, 0, 1); }; export const getEndOfDecade = (date) => { const beginOfDecadeYear = getBeginOfDecadeYear(date); return new Date(beginOfDecadeYear + 10, 0, 1, 0, 0, 0, -1); }; export const getDecadeRange = date => [ getBeginOfDecade(date), getEndOfDecade(date), ]; export const getBeginOfPreviousDecade = (date, offset = 10) => { const previousDecadeYear = getBeginOfDecadeYear(date) - offset; return getBeginOfDecade(previousDecadeYear); }; export const getEndOfPreviousDecade = (date, offset = 10) => { const previousDecadeYear = getBeginOfDecadeYear(date) - offset; return getEndOfDecade(previousDecadeYear); }; export const getBeginOfNextDecade = (date, offset = 10) => { const nextDecadeYear = getBeginOfDecadeYear(date) + offset; return getBeginOfDecade(nextDecadeYear); }; /** * Returns the beginning of a given year. * * @param {Date} date Date. */ export const getBeginOfYear = (date) => { const year = getYear(date); return new Date(year, 0, 1); }; /** * Returns the end of a given year. * * @param {Date} date Date. */ export const getEndOfYear = (date) => { const year = getYear(date); return new Date(year + 1, 0, 1, 0, 0, 0, -1); }; /** * Returns an array with the beginning and the end of a given year. * * @param {Date} date Date. */ export const getYearRange = date => [ getBeginOfYear(date), getEndOfYear(date), ]; export const getBeginOfPreviousYear = (date, offset = 1) => { const previousYear = getYear(date) - offset; return getBeginOfYear(previousYear); }; export const getEndOfPreviousYear = (date, offset = 1) => { const previousYear = getYear(date) - offset; return getEndOfYear(previousYear); }; export const getBeginOfNextYear = (date, offset = 1) => { const nextYear = getYear(date) + offset; return getBeginOfYear(nextYear); }; /** * Returns the beginning of a given month. * * @param {Date} date Date. */ export const getBeginOfMonth = (date) => { const year = getYear(date); const monthIndex = getMonthIndex(date); return new Date(year, monthIndex, 1); }; /** * Returns the end of a given month. * * @param {Date} date Date. */ export const getEndOfMonth = (date) => { const year = getYear(date); const monthIndex = getMonthIndex(date); return new Date(year, monthIndex + 1, 1, 0, 0, 0, -1); }; /** * Returns the beginning of a given week. * * @param {Date} date Date. * @param {String} calendarType Calendar type. Can be ISO 8601 or US. */ export const getBeginOfWeek = (date, calendarType = 'ISO 8601') => { const year = getYear(date); const monthIndex = getMonthIndex(date); const day = date.getDate() - getDayOfWeek(date, calendarType); return new Date(year, monthIndex, day); }; /** * Returns an array with the beginning and the end of a given month. * * @param {Date} date Date. */ export const getMonthRange = date => [ getBeginOfMonth(date), getEndOfMonth(date), ]; const getDifferentMonth = (date, offset) => { const year = getYear(date); const previousMonthIndex = getMonthIndex(date) + offset; return new Date(year, previousMonthIndex, 1); }; export const getBeginOfPreviousMonth = (date, offset = 1) => { const previousMonth = getDifferentMonth(date, -offset); return getBeginOfMonth(previousMonth); }; export const getEndOfPreviousMonth = (date, offset = 1) => { const previousMonth = getDifferentMonth(date, -offset); return getEndOfMonth(previousMonth); }; export const getBeginOfNextMonth = (date, offset = 1) => { const nextMonth = getDifferentMonth(date, offset); return getBeginOfMonth(nextMonth); }; export const getBeginOfDay = (date) => { const year = getYear(date); const monthIndex = getMonthIndex(date); const day = getDay(date); return new Date(year, monthIndex, day); }; export const getEndOfDay = (date) => { const year = getYear(date); const monthIndex = getMonthIndex(date); const day = getDay(date); return new Date(year, monthIndex, day + 1, 0, 0, 0, -1); }; /** * Returns an array with the beginning and the end of a given day. * * @param {Date} date Date. */ export const getDayRange = date => [ getBeginOfDay(date), getEndOfDay(date), ]; /** * Gets week number according to ISO 8601 or US standard. * In ISO 8601 week 1 is the one with January 4. * In US calendar week 1 is the one with January 1. * * @param {Date} date Date. * @param {String} calendarType Calendar type. Can be ISO 8601 or US. */ export const getWeekNumber = (date, calendarType = 'ISO 8601') => { const beginOfWeek = getBeginOfWeek(date, calendarType); let year = getYear(date) + 1; let dayInWeekOne; let beginOfFirstWeek; // Look for the first week one that does not come after a given date do { dayInWeekOne = new Date(year, 0, calendarType === 'ISO 8601' ? 4 : 1); beginOfFirstWeek = getBeginOfWeek(dayInWeekOne, calendarType); year -= 1; } while (date - beginOfFirstWeek < 0); return Math.round((beginOfWeek - beginOfFirstWeek) / (8.64e7 * 7)) + 1; }; /** * Returns the beginning of a given range. * * @param {String} rangeType Range type (e.g. 'day') * @param {Date} date Date. */ export const getBegin = (rangeType, date) => { switch (rangeType) { case 'century': return getBeginOfCentury(date); case 'decade': return getBeginOfDecade(date); case 'year': return getBeginOfYear(date); case 'month': return getBeginOfMonth(date); case 'day': return getBeginOfDay(date); default: throw new Error(`Invalid rangeType: ${rangeType}`); } }; export const getBeginPrevious = (rangeType, date) => { switch (rangeType) { case 'century': return getBeginOfPreviousCentury(date); case 'decade': return getBeginOfPreviousDecade(date); case 'year': return getBeginOfPreviousYear(date); case 'month': return getBeginOfPreviousMonth(date); default: throw new Error(`Invalid rangeType: ${rangeType}`); } }; export const getBeginNext = (rangeType, date) => { switch (rangeType) { case 'century': return getBeginOfNextCentury(date); case 'decade': return getBeginOfNextDecade(date); case 'year': return getBeginOfNextYear(date); case 'month': return getBeginOfNextMonth(date); default: throw new Error(`Invalid rangeType: ${rangeType}`); } }; export const getBeginPrevious2 = (rangeType, date) => { switch (rangeType) { case 'decade': return getBeginOfPreviousDecade(date, 100); case 'year': return getBeginOfPreviousYear(date, 10); case 'month': return getBeginOfPreviousMonth(date, 12); default: throw new Error(`Invalid rangeType: ${rangeType}`); } }; export const getBeginNext2 = (rangeType, date) => { switch (rangeType) { case 'decade': return getBeginOfNextDecade(date, 100); case 'year': return getBeginOfNextYear(date, 10); case 'month': return getBeginOfNextMonth(date, 12); default: throw new Error(`Invalid rangeType: ${rangeType}`); } }; /** * Returns the end of a given range. * * @param {String} rangeType Range type (e.g. 'day') * @param {Date} date Date. */ export const getEnd = (rangeType, date) => { switch (rangeType) { case 'century': return getEndOfCentury(date); case 'decade': return getEndOfDecade(date); case 'year': return getEndOfYear(date); case 'month': return getEndOfMonth(date); case 'day': return getEndOfDay(date); default: throw new Error(`Invalid rangeType: ${rangeType}`); } }; export const getEndPrevious = (rangeType, date) => { switch (rangeType) { case 'century': return getEndOfPreviousCentury(date); case 'decade': return getEndOfPreviousDecade(date); case 'year': return getEndOfPreviousYear(date); case 'month': return getEndOfPreviousMonth(date); default: throw new Error(`Invalid rangeType: ${rangeType}`); } }; export const getEndPrevious2 = (rangeType, date) => { switch (rangeType) { case 'decade': return getEndOfPreviousDecade(date, 100); case 'year': return getEndOfPreviousYear(date, 10); case 'month': return getEndOfPreviousMonth(date, 12); default: throw new Error(`Invalid rangeType: ${rangeType}`); } }; /** * Returns an array with the beginning and the end of a given range. * * @param {String} rangeType Range type (e.g. 'day') * @param {Date} date Date. */ export const getRange = (rangeType, date) => { switch (rangeType) { case 'century': return getCenturyRange(date); case 'decade': return getDecadeRange(date); case 'year': return getYearRange(date); case 'month': return getMonthRange(date); case 'day': return getDayRange(date); default: throw new Error(`Invalid rangeType: ${rangeType}`); } }; /** * Creates a range out of two values, ensuring they are in order and covering entire period ranges. * * @param {String} rangeType Range type (e.g. 'day') * @param {Date} date1 First date. * @param {Date} date2 Second date. */ export const getValueRange = (rangeType, date1, date2) => { const rawNextValue = [date1, date2].sort((a, b) => a.getTime() > b.getTime()); return [ getBegin(rangeType, rawNextValue[0]), getEnd(rangeType, rawNextValue[1]), ]; }; /** * Returns a number of days in a month of a given date. * * @param {Date} date Date. */ export const getDaysInMonth = (date) => { const year = getYear(date); const monthIndex = getMonthIndex(date); return new Date(year, monthIndex + 1, 0).getDate(); }; const toYearLabel = ([start, end]) => `${getYear(start)}${getYear(end)}`; /** * Returns a string labelling a century of a given date. * For example, for 2017 it will return 2001-2100. * * @param {Date|String|Number} date Date or a year as a string or as a number. */ export const getCenturyLabel = date => toYearLabel(getCenturyRange(date)); /** * Returns a string labelling a century of a given date. * For example, for 2017 it will return 2011-2020. * * @param {Date|String|Number} date Date or a year as a string or as a number. */ export const getDecadeLabel = date => toYearLabel(getDecadeRange(date)); /** * Returns a boolean determining whether a given date is on Saturday or Sunday. * * @param {Date} date Date. */ export const isWeekend = (date) => { const weekday = getDayOfWeek(date); return weekday >= 5; }; /** * Returns local month in ISO-like format (YYYY-MM). */ export const getISOLocalMonth = (value) => { if (!value) { return value; } const date = new Date(value); if (Number.isNaN(date.getTime())) { throw new Error(`Invalid date: ${value}`); } const year = getYear(date); const month = `0${getMonth(date)}`.slice(-2); return `${year}-${month}`; }; /** * Returns local date in ISO-like format (YYYY-MM-DD). */ export const getISOLocalDate = (value) => { if (!value) { return value; } const date = new Date(value); if (Number.isNaN(date.getTime())) { throw new Error(`Invalid date: ${value}`); } const year = getYear(date); const month = `0${getMonth(date)}`.slice(-2); const day = `0${getDay(date)}`.slice(-2); return `${year}-${month}-${day}`; };