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.
116 lines
3.7 KiB
116 lines
3.7 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 class CustomDateRange {
|
|
private from: Date;
|
|
private to: Date;
|
|
|
|
constructor(from: Date, to: Date) {
|
|
this.from = from;
|
|
this.to = to;
|
|
}
|
|
|
|
get name() {
|
|
return "Specific Dates"
|
|
}
|
|
|
|
calculate(_: Date): [Date, Date] {
|
|
return [this.from, this.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 new CustomDateRange(from, to);
|
|
}
|
|
|
|
export const pastOffsets: DateRange[] = allOffsets.filter(r => !r.name.startsWith("Next"));
|