svelte-ux
Version:
- Increment version in `package.json` and commit as `Version bump to x.y.z` - `npm run publish`
527 lines (526 loc) • 20.6 kB
JavaScript
import { format, startOfDay, endOfDay, startOfWeek, endOfWeek, startOfMonth, endOfMonth, startOfQuarter, endOfQuarter, startOfYear, endOfYear, min, max, addMonths, addDays, differenceInDays, differenceInWeeks, differenceInMonths, differenceInQuarters, differenceInYears, addWeeks, addQuarters, addYears, isSameDay, isSameWeek, isSameMonth, isSameQuarter, isSameYear, parseISO, formatISO, } from 'date-fns';
import { timeDays } from 'd3-time';
import { hasKeyOf } from '../types/typeGuards';
import { chunk } from './array';
export var PeriodType;
(function (PeriodType) {
PeriodType[PeriodType["Day"] = 10] = "Day";
PeriodType[PeriodType["WeekSun"] = 20] = "WeekSun";
PeriodType[PeriodType["WeekMon"] = 21] = "WeekMon";
PeriodType[PeriodType["WeekTue"] = 22] = "WeekTue";
PeriodType[PeriodType["WeekWed"] = 23] = "WeekWed";
PeriodType[PeriodType["WeekThu"] = 24] = "WeekThu";
PeriodType[PeriodType["WeekFri"] = 25] = "WeekFri";
PeriodType[PeriodType["WeekSat"] = 26] = "WeekSat";
PeriodType[PeriodType["Month"] = 30] = "Month";
PeriodType[PeriodType["Quarter"] = 40] = "Quarter";
PeriodType[PeriodType["CalendarYear"] = 50] = "CalendarYear";
PeriodType[PeriodType["FiscalYearOctober"] = 60] = "FiscalYearOctober";
PeriodType[PeriodType["BiWeek1Sun"] = 70] = "BiWeek1Sun";
PeriodType[PeriodType["BiWeek1Mon"] = 71] = "BiWeek1Mon";
PeriodType[PeriodType["BiWeek1Tue"] = 72] = "BiWeek1Tue";
PeriodType[PeriodType["BiWeek1Wed"] = 73] = "BiWeek1Wed";
PeriodType[PeriodType["BiWeek1Thu"] = 74] = "BiWeek1Thu";
PeriodType[PeriodType["BiWeek1Fri"] = 75] = "BiWeek1Fri";
PeriodType[PeriodType["BiWeek1Sat"] = 76] = "BiWeek1Sat";
PeriodType[PeriodType["BiWeek2Sun"] = 80] = "BiWeek2Sun";
PeriodType[PeriodType["BiWeek2Mon"] = 81] = "BiWeek2Mon";
PeriodType[PeriodType["BiWeek2Tue"] = 82] = "BiWeek2Tue";
PeriodType[PeriodType["BiWeek2Wed"] = 83] = "BiWeek2Wed";
PeriodType[PeriodType["BiWeek2Thu"] = 84] = "BiWeek2Thu";
PeriodType[PeriodType["BiWeek2Fri"] = 85] = "BiWeek2Fri";
PeriodType[PeriodType["BiWeek2Sat"] = 86] = "BiWeek2Sat";
})(PeriodType || (PeriodType = {}));
export var DayOfWeek;
(function (DayOfWeek) {
DayOfWeek[DayOfWeek["SUN"] = 0] = "SUN";
DayOfWeek[DayOfWeek["MON"] = 1] = "MON";
DayOfWeek[DayOfWeek["TUE"] = 2] = "TUE";
DayOfWeek[DayOfWeek["WED"] = 3] = "WED";
DayOfWeek[DayOfWeek["THU"] = 4] = "THU";
DayOfWeek[DayOfWeek["FRI"] = 5] = "FRI";
DayOfWeek[DayOfWeek["SAT"] = 6] = "SAT";
})(DayOfWeek || (DayOfWeek = {}));
export function getPeriodTypeName(periodType) {
switch (periodType) {
case PeriodType.Day:
return 'Day';
case PeriodType.WeekSun:
return 'Week (Sun)';
case PeriodType.WeekMon:
return 'Week (Mon)';
case PeriodType.WeekTue:
return 'Week (Tue)';
case PeriodType.WeekWed:
return 'Week (Wed)';
case PeriodType.WeekThu:
return 'Week (Thu)';
case PeriodType.WeekFri:
return 'Week (Fri)';
case PeriodType.WeekSat:
return 'Week (Sat)';
case PeriodType.Month:
return 'Month';
case PeriodType.Quarter:
return 'Quarter';
case PeriodType.CalendarYear:
return 'Calendar Year';
case PeriodType.FiscalYearOctober:
return 'Fiscal Year (Oct)';
case PeriodType.BiWeek1Sun:
return 'Bi-Week (Sun)';
case PeriodType.BiWeek1Mon:
return 'Bi-Week (Mon)';
case PeriodType.BiWeek1Tue:
return 'Bi-Week (Tue)';
case PeriodType.BiWeek1Wed:
return 'Bi-Week (Wed)';
case PeriodType.BiWeek1Thu:
return 'Bi-Week (Thu)';
case PeriodType.BiWeek1Fri:
return 'Bi-Week (Fri)';
case PeriodType.BiWeek1Sat:
return 'Bi-Week (Sat)';
case PeriodType.BiWeek2Sun:
return 'Bi-Week 2 (Sun)';
case PeriodType.BiWeek2Mon:
return 'Bi-Week 2 (Mon)';
case PeriodType.BiWeek2Tue:
return 'Bi-Week 2 (Tue)';
case PeriodType.BiWeek2Wed:
return 'Bi-Week 2 (Wed)';
case PeriodType.BiWeek2Thu:
return 'Bi-Week 2 (Thu)';
case PeriodType.BiWeek2Fri:
return 'Bi-Week 2 (Fri)';
case PeriodType.BiWeek2Sat:
return 'Bi-Week 2 (Sat)';
default:
return 'Unknown';
}
}
export function getPeriodTypeCode(periodType) {
switch (periodType) {
case PeriodType.Day:
return 'DAY';
case PeriodType.WeekSun:
return 'WEEK-SUN';
case PeriodType.WeekMon:
return 'WEEK-MON';
case PeriodType.WeekTue:
return 'WEEK-TUE';
case PeriodType.WeekWed:
return 'WEEK-WED';
case PeriodType.WeekThu:
return 'WEEK-THU';
case PeriodType.WeekFri:
return 'WEEK-FRI';
case PeriodType.WeekSat:
return 'WEEK-SAT';
case PeriodType.Month:
return 'MTH';
case PeriodType.Quarter:
return 'QTR';
case PeriodType.CalendarYear:
return 'CY';
case PeriodType.FiscalYearOctober:
return 'FY-OCT';
case PeriodType.BiWeek1Sun:
return 'BIWEEK1-SUN';
case PeriodType.BiWeek1Mon:
return 'BIWEEK1-MON';
case PeriodType.BiWeek1Tue:
return 'BIWEEK1-TUE';
case PeriodType.BiWeek1Wed:
return 'BIWEEK1-WED';
case PeriodType.BiWeek1Thu:
return 'BIWEEK1-THU';
case PeriodType.BiWeek1Fri:
return 'BIWEEK1-FRI';
case PeriodType.BiWeek1Sat:
return 'BIWEEK1-SAT';
case PeriodType.BiWeek2Sun:
return 'BIWEEK2-SUN';
case PeriodType.BiWeek2Mon:
return 'BIWEEK2-MON';
case PeriodType.BiWeek2Tue:
return 'BIWEEK2-TUE';
case PeriodType.BiWeek2Wed:
return 'BIWEEK2-WED';
case PeriodType.BiWeek2Thu:
return 'BIWEEK2-THU';
case PeriodType.BiWeek2Fri:
return 'BIWEEK2-FRI';
case PeriodType.BiWeek2Sat:
return 'BIWEEK2-SAT';
default:
return 'UNK';
}
}
export function getPeriodTypeByCode(code) {
switch (code) {
case 'DAY':
return PeriodType.Day;
case 'WEEK-SUN':
return PeriodType.WeekSun;
case 'WEEK-MON':
return PeriodType.WeekMon;
case 'WEEK-TUE':
return PeriodType.WeekTue;
case 'WEEK-WED':
return PeriodType.WeekWed;
case 'WEEK-THU':
return PeriodType.WeekThu;
case 'WEEK-FRI':
return PeriodType.WeekFri;
case 'WEEK-SAT':
return PeriodType.WeekSat;
case 'MTH':
return PeriodType.Month;
case 'QTR':
return PeriodType.Quarter;
case 'CY':
return PeriodType.CalendarYear;
case 'FY-OCT':
return PeriodType.FiscalYearOctober;
case 'BIWEEK1-SUN':
return PeriodType.BiWeek1Sun;
case 'BIWEEK1-MON':
return PeriodType.BiWeek1Mon;
case 'BIWEEK1-TUE':
return PeriodType.BiWeek1Tue;
case 'BIWEEK1-WED':
return PeriodType.BiWeek1Wed;
case 'BIWEEK1-THU':
return PeriodType.BiWeek1Thu;
case 'BIWEEK1-FRI':
return PeriodType.BiWeek1Fri;
case 'BIWEEK1-SAT':
return PeriodType.BiWeek1Sat;
default:
return null;
}
}
export function getDayOfWeek(periodType) {
const periodTypeCode = getPeriodTypeCode(periodType);
const matches = periodTypeCode.match(/\-(SUN|MON|TUE|WED|THU|FRI|SAT)/);
if (matches) {
return DayOfWeek[matches[1]];
}
else {
return null;
}
}
export function replaceDayOfWeek(periodType, dayOfWeek) {
const periodTypeCode = getPeriodTypeCode(periodType);
const dayOfWeekName = DayOfWeek[dayOfWeek];
// Replace everything after `-` with new dayOfWeek
const newPeriodTypeCode = periodTypeCode.replace(/\-(.*)/, `-${dayOfWeekName}`);
return getPeriodTypeByCode(newPeriodTypeCode);
}
export function hasDayOfWeek(periodType) {
const periodTypeCode = getPeriodTypeCode(periodType);
return /\-(SUN|MON|TUE|WED|THU|FRI|SAT)/.test(periodTypeCode);
}
export function getMonths(year = new Date().getFullYear()) {
return Array.from({ length: 12 }, (_, i) => new Date(year, i, 1));
}
export function getMonthDaysByWeek(startOfMonth) {
const startOfFirstWeek = startOfWeek(startOfMonth);
const endOfLastWeek = endOfWeek(endOfMonth(startOfMonth));
const monthDaysByWeek = chunk(timeDays(startOfFirstWeek, endOfLastWeek), 7);
return monthDaysByWeek;
}
export function getMinSelectedDate(date) {
if (date instanceof Date) {
return date;
}
else if (date instanceof Array) {
return min(date);
}
else if (hasKeyOf(date, 'from')) {
return date.from;
}
else {
return null;
}
}
export function getMaxSelectedDate(date) {
if (date instanceof Date) {
return date;
}
else if (date instanceof Array) {
return max(date);
}
else if (hasKeyOf(date, 'to')) {
return date.to;
}
else {
return null;
}
}
/*
* Fiscal Year
*/
export function getFiscalYear(date = new Date(), options) {
if (date === null) {
// null explicitly passed in (default value overridden)
return NaN;
}
const startMonth = (options && options.startMonth) || 10;
return date.getMonth() >= startMonth - 1 ? date.getFullYear() + 1 : date.getFullYear();
}
export function getFiscalYearRange(date = new Date(), options) {
const fiscalYear = getFiscalYear(date, options);
const startMonth = (options && options.startMonth) || 10;
const numberOfMonths = (options && options.numberOfMonths) || 12;
const startDate = new Date((fiscalYear || 0) - 1, startMonth - 1, 1);
const endDate = endOfMonth(addMonths(startDate, numberOfMonths - 1));
return { startDate, endDate };
}
export function startOfFiscalYear(date, options) {
return getFiscalYearRange(date, options).startDate;
}
export function endOfFiscalYear(date, options) {
return getFiscalYearRange(date, options).endDate;
}
export function isSameFiscalYear(dateLeft, dateRight) {
return getFiscalYear(dateLeft) === getFiscalYear(dateRight);
}
/*
* Bi-Weekly
*/
const biweekBaseDates = [new Date('1799-12-22T00:00'), new Date('1799-12-15T00:00')];
export function startOfBiWeek(date, week, startOfWeek) {
var weekBaseDate = biweekBaseDates[week - 1];
var baseDate = addDays(weekBaseDate, startOfWeek);
var periodsSince = Math.floor(differenceInDays(date, baseDate) / 14);
return addDays(baseDate, periodsSince * 14);
}
export function endOfBiWeek(date, week, startOfWeek) {
return addDays(startOfBiWeek(date, week, startOfWeek), 13);
}
export function getDateFuncsByPeriodType(periodType) {
switch (periodType) {
case PeriodType.Day:
return {
start: startOfDay,
end: endOfDay,
add: addDays,
difference: differenceInDays,
isSame: isSameDay,
};
case PeriodType.WeekSun:
return {
start: startOfWeek,
end: endOfWeek,
add: addWeeks,
difference: differenceInWeeks,
isSame: isSameWeek,
};
case PeriodType.WeekMon:
return {
start: (date) => startOfWeek(date, { weekStartsOn: 1 }),
end: (date) => endOfWeek(date, { weekStartsOn: 1 }),
add: addWeeks,
difference: differenceInWeeks,
isSame: (dateLeft, dateRight) => isSameWeek(dateLeft, dateRight, { weekStartsOn: 1 }),
};
case PeriodType.WeekTue:
return {
start: (date) => startOfWeek(date, { weekStartsOn: 2 }),
end: (date) => endOfWeek(date, { weekStartsOn: 2 }),
add: addWeeks,
difference: differenceInWeeks,
isSame: (dateLeft, dateRight) => isSameWeek(dateLeft, dateRight, { weekStartsOn: 2 }),
};
case PeriodType.WeekWed:
return {
start: (date) => startOfWeek(date, { weekStartsOn: 3 }),
end: (date) => endOfWeek(date, { weekStartsOn: 3 }),
add: addWeeks,
difference: differenceInWeeks,
isSame: (dateLeft, dateRight) => isSameWeek(dateLeft, dateRight, { weekStartsOn: 3 }),
};
case PeriodType.WeekThu:
return {
start: (date) => startOfWeek(date, { weekStartsOn: 4 }),
end: (date) => endOfWeek(date, { weekStartsOn: 4 }),
add: addWeeks,
difference: differenceInWeeks,
isSame: (dateLeft, dateRight) => isSameWeek(dateLeft, dateRight, { weekStartsOn: 4 }),
};
case PeriodType.WeekFri:
return {
start: (date) => startOfWeek(date, { weekStartsOn: 5 }),
end: (date) => endOfWeek(date, { weekStartsOn: 5 }),
add: addWeeks,
difference: differenceInWeeks,
isSame: (dateLeft, dateRight) => isSameWeek(dateLeft, dateRight, { weekStartsOn: 5 }),
};
case PeriodType.WeekSat:
return {
start: (date) => startOfWeek(date, { weekStartsOn: 6 }),
end: (date) => endOfWeek(date, { weekStartsOn: 6 }),
add: addWeeks,
difference: differenceInWeeks,
isSame: (dateLeft, dateRight) => isSameWeek(dateLeft, dateRight, { weekStartsOn: 6 }),
};
case PeriodType.Month:
return {
start: startOfMonth,
end: endOfMonth,
add: addMonths,
difference: differenceInMonths,
isSame: isSameMonth,
};
case PeriodType.Quarter:
return {
start: startOfQuarter,
end: endOfQuarter,
add: addQuarters,
difference: differenceInQuarters,
isSame: isSameQuarter,
};
case PeriodType.CalendarYear:
return {
start: startOfYear,
end: endOfYear,
add: addYears,
difference: differenceInYears,
isSame: isSameYear,
};
case PeriodType.FiscalYearOctober:
return {
start: startOfFiscalYear,
end: endOfFiscalYear,
add: addYears,
difference: differenceInYears,
isSame: isSameFiscalYear,
};
// BiWeek 1
case PeriodType.BiWeek1Sun:
case PeriodType.BiWeek1Mon:
case PeriodType.BiWeek1Tue:
case PeriodType.BiWeek1Wed:
case PeriodType.BiWeek1Thu:
case PeriodType.BiWeek1Fri:
case PeriodType.BiWeek1Sat:
// BiWeek 2
case PeriodType.BiWeek2Sun:
case PeriodType.BiWeek2Mon:
case PeriodType.BiWeek2Tue:
case PeriodType.BiWeek2Wed:
case PeriodType.BiWeek2Thu:
case PeriodType.BiWeek2Fri:
case PeriodType.BiWeek2Sat: {
const week = getPeriodTypeCode(periodType).startsWith('BIWEEK1') ? 1 : 2;
const dayOfWeek = getDayOfWeek(periodType);
return {
start: (date) => startOfBiWeek(date, week, dayOfWeek),
end: (date) => endOfBiWeek(date, week, dayOfWeek),
add: (date, amount) => addWeeks(date, amount * 2),
difference: (dateLeft, dateRight) => {
return differenceInWeeks(dateLeft, dateRight) / 2;
},
isSame: (dateLeft, dateRight) => {
return isSameDay(startOfBiWeek(dateLeft, week, dayOfWeek), startOfBiWeek(dateRight, week, dayOfWeek));
},
};
}
default:
// Default to end of day if periodType == null, etc
return {
start: startOfDay,
end: endOfDay,
add: addDays,
difference: differenceInDays,
isSame: isSameDay,
};
}
}
export function formatISODate(date, representation = 'complete') {
if (date == null) {
return '';
}
if (typeof date === 'string') {
date = parseISO(date);
}
return formatISO(date, { representation });
}
export function formatDate(date, periodType, variant // TODO: Support x-long, etc (maybe call it sm, md, lg, xl, etc)
) {
if (typeof date === 'string') {
date = parseISO(date);
}
// Handle 'Invalid Date'
// @ts-ignore - Date is a number (see: https://stackoverflow.com/questions/1353684/detecting-an-invalid-date-date-instance-in-javascript)
if (date == null || isNaN(date)) {
return '';
}
switch (periodType) {
case PeriodType.Day:
return variant === 'short' ? format(date, 'M/d') : format(date, 'MMM d, yyyy');
case PeriodType.WeekSun:
case PeriodType.WeekMon:
case PeriodType.WeekTue:
case PeriodType.WeekWed:
case PeriodType.WeekThu:
case PeriodType.WeekFri:
case PeriodType.WeekSat:
return variant === 'short'
? format(date, 'M/d') + ' - ' + format(addDays(date, 6), 'M/d')
: format(date, 'M/d/yyyy') + ' - ' + format(addDays(date, 6), 'M/d/yyyy');
case PeriodType.Month:
return variant === 'short' ? format(date, 'MMM yyyy') : format(date, 'MMMM yyyy');
case PeriodType.Quarter:
return variant === 'short'
? format(date, 'MMM') + ' - ' + format(addMonths(date, 2), 'MMM yyyy')
: format(date, 'MMMM') + ' - ' + format(addMonths(date, 2), 'MMMM yyyy');
case PeriodType.CalendarYear:
return variant === 'short' ? format(date, 'yy') : format(date, 'yyyy');
case PeriodType.FiscalYearOctober:
return variant === 'short' ? `${getFiscalYear(date)}`.substring(2) : `${getFiscalYear(date)}`;
case PeriodType.BiWeek1Sun:
case PeriodType.BiWeek1Mon:
case PeriodType.BiWeek1Tue:
case PeriodType.BiWeek1Wed:
case PeriodType.BiWeek1Thu:
case PeriodType.BiWeek1Fri:
case PeriodType.BiWeek1Sat:
case PeriodType.BiWeek2Sun:
case PeriodType.BiWeek2Mon:
case PeriodType.BiWeek2Tue:
case PeriodType.BiWeek2Wed:
case PeriodType.BiWeek2Thu:
case PeriodType.BiWeek2Fri:
case PeriodType.BiWeek2Sat:
return variant === 'short'
? format(date, 'M/d') + ' - ' + format(addDays(date, 13), 'M/d')
: format(date, 'M/d/yyyy') + ' - ' + format(addDays(date, 13), 'M/d/yyyy');
default:
return formatISO(date);
}
}
/**
* Return new Date using UTC date/time as local date/time
*/
export function utcToLocalDate(date) {
date = date instanceof Date ? date : typeof date === 'string' ? new Date(date) : new Date();
// https://github.com/date-fns/date-fns/issues/376#issuecomment-454163253
// return new Date(date.getTime() + date.getTimezoneOffset() * 60 * 1000);
// This approach seems to work more reliably with dates before 11/18/1883 @ 12:00
// https://github.com/d3/d3-time/issues/29#issuecomment-396415951
const d = new Date(date.getUTCFullYear(), date.getUTCMonth(), date.getUTCDate(), date.getUTCHours(), date.getUTCMinutes(), date.getUTCSeconds());
d.setUTCFullYear(date.getUTCFullYear());
return d;
}
/**
* Return new Date using local date/time as UTC date/time
*/
export function localToUtcDate(date) {
date = date instanceof Date ? date : typeof date === 'string' ? new Date(date) : new Date();
// return new Date(date.getTime() - date.getTimezoneOffset() * 60 * 1000);
const d = new Date(Date.UTC(date.getFullYear(), date.getMonth(), date.getDate(), date.getHours(), date.getMinutes(), date.getSeconds()));
return d;
}