You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

102 lines
3.5 KiB

import pluralize from "pluralize";
import {
addDays, addMonths, addYears,
endOfDay, endOfMonth, endOfWeek, endOfYear,
startOfDay, startOfMonth, startOfWeek, startOfYear
} from "./time";
export interface DateRange {
name: string
calculate(date: Date): [Date, Date]
}
function dateRangeCallback(name: string, calculate: (date: Date) => [Date, Date]): DateRange {
return {name, calculate};
}
export class RelativeDateRange {
private duration: number
private unit: "day" | "month" | "year"
public name: string
constructor(duration: number, unit: "day" | "month" | "year") {
this.duration = duration;
this.unit = unit;
if (this.duration < 0) {
this.name = `Last ${-this.duration} ${pluralize(this.unit, -this.duration)}`;
} else {
this.name = `Next ${this.duration} ${pluralize(this.unit, this.duration)}`;
}
}
calculate(date: Date): [Date, Date] {
switch (this.unit) {
case "day": {
return this.duration < 0
? [ startOfDay(addDays(date, this.duration)), endOfDay(date) ]
: [ startOfDay(date), endOfDay(addDays(date, this.duration)) ];
}
case "month": {
return this.duration < 0
? [ startOfDay(addMonths(date, this.duration)), endOfDay(date) ]
: [ startOfDay(date), endOfDay(addMonths(date, this.duration)) ];
}
case "year": {
return this.duration < 0
? [ startOfDay(addYears(date, this.duration)), endOfDay(date) ]
: [ startOfDay(date), endOfDay(addYears(date, this.duration)) ];
}
}
}
}
export function customDateRange(from: Date, to: Date): DateRange {
return {name: "Specific Dates", calculate: () => [from, to]}
}
const thisWeek = dateRangeCallback("This week", date => [startOfWeek(date), endOfWeek(date)]);
const nextWeek = dateRangeCallback("Next week", date => [startOfWeek(addDays(date, 7)), endOfWeek(addDays(date, 7))]);
const lastWeek = dateRangeCallback("Last week", date => [startOfWeek(addDays(date, -7)), endOfWeek(addDays(date, -7))]);
const thisMonth = dateRangeCallback("This month", date => [startOfMonth(date), endOfMonth(date)]);
const nextMonth = dateRangeCallback("Next month", date => [startOfMonth(addMonths(date, 1)), endOfMonth(addMonths(date, 1))]);
const lastMonth = dateRangeCallback("Last month", date => [startOfMonth(addMonths(date, -1)), endOfMonth(addMonths(date, -1))]);
const thisYear = dateRangeCallback("This year", date => [startOfYear(date), endOfYear(date)]);
const nextYear = dateRangeCallback("Next year", date => [startOfYear(addYears(date, 1)), endOfYear(addYears(date, 1))]);
const lastYear = dateRangeCallback("Last year", date => [startOfYear(addYears(date, -1)), endOfYear(addYears(date, -1))]);
export const allOffsets: DateRange[] = [
thisWeek,
nextWeek,
new RelativeDateRange(7, "day"),
lastWeek,
new RelativeDateRange(-7, "day"),
thisMonth,
nextMonth,
new RelativeDateRange(30, "day"),
new RelativeDateRange(90, "day"),
lastMonth,
new RelativeDateRange(-30, "day"),
new RelativeDateRange(-90, "day"),
thisYear,
nextYear,
new RelativeDateRange(1, "year"),
lastYear,
new RelativeDateRange(-1, "year"),
];
export function rangeFromDates(from: Date, to: Date, options: DateRange[]): DateRange {
for (const option of options) {
const [from2, to2] = option.calculate(new Date());
if (from2.getTime() == from.getTime() && to2.getTime() === to.getTime()) {
return option;
}
}
return customDateRange(from, to);
}
export const pastOffsets: DateRange[] = allOffsets.filter(r => !r.name.startsWith("Next"));