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.
118 lines
4.4 KiB
118 lines
4.4 KiB
import type { TimeInterval } from "../models/common";
|
|
import { addDays, addMonths, addYears, formatDate, startOfDay, startOfMonth, startOfWeek, startOfYear } from "./date";
|
|
|
|
export default function parseInterval(s: string, date: Date): TimeInterval<Date> {
|
|
const [verb, args] = s.split(":")
|
|
|
|
switch (verb) {
|
|
case "":
|
|
case "all_time":
|
|
return null;
|
|
case "next": {
|
|
const [amount, unit] = unitNumber(args);
|
|
switch (unit) {
|
|
case "d": case "days":
|
|
return {display: "days", min: startOfDay(date), max: startOfDay(addDays(date, amount))}
|
|
case "w": case "weeks":
|
|
return {display: "days", min: startOfDay(date), max: startOfDay(addDays(date, amount * 7))}
|
|
case "m": case "months":
|
|
return {display: "days", min: startOfDay(date), max: startOfDay(addMonths(date, amount))}
|
|
case "y": case "years":
|
|
return {display: "none", min: startOfDay(date), max: startOfDay(addYears(date, amount))}
|
|
}
|
|
}
|
|
case "last": {
|
|
const [amount, unit] = unitNumber(args);
|
|
switch (unit) {
|
|
case "d": case "days":
|
|
return {display: "days", min: startOfDay(addDays(date, -amount)), max: startOfDay(addDays(date, 1))}
|
|
case "w": case "weeks":
|
|
return {display: "weeks", min: startOfDay(addDays(date, -amount * 7)), max: startOfDay(addDays(date, 1))}
|
|
case "m": case "months":
|
|
return {display: "days", min: startOfDay(addMonths(date, -amount)), max: startOfDay(addDays(date, 1))}
|
|
case "y": case "years":
|
|
return {display: "none", min: startOfDay(addYears(date, -amount)), max: startOfDay(addDays(date, 1))}
|
|
}
|
|
}
|
|
case "today":
|
|
return {display: "none", min: startOfDay(date), max: startOfDay(addDays(date, 1))}
|
|
case "next_week":
|
|
return {display: "weeks", min: startOfWeek(addDays(date, 7)), max: startOfWeek(addDays(date, 14))}
|
|
case "this_week":
|
|
return {display: "weeks", min: startOfWeek(date), max: startOfWeek(addDays(date, 7))}
|
|
case "last_week":
|
|
return {display: "weeks", min: startOfWeek(addDays(date, -7)), max: startOfWeek(date)}
|
|
case "next_month":
|
|
return {display: "month", min: startOfMonth(addMonths(date, 1)), max: startOfMonth(addMonths(date, 2))}
|
|
case "this_month":
|
|
return {display: "month", min: startOfMonth(date), max: startOfMonth(addMonths(date, 1))}
|
|
case "last_month":
|
|
return {display: "month", min: startOfMonth(addMonths(date, -1)), max: startOfMonth(date)}
|
|
case "next_year":
|
|
return {display: "year", min: startOfYear(addYears(date, 1)), max: startOfYear(addYears(date, 2))}
|
|
case "this_year":
|
|
return {display: "year", min: startOfYear(date), max: startOfYear(addYears(date, 1))}
|
|
case "last_year":
|
|
return {display: "year", min: startOfYear(addYears(date, -1)), max: startOfYear(date)}
|
|
}
|
|
}
|
|
|
|
export function intervalLabel(s: string): string {
|
|
const [verb, args] = s.split(":")
|
|
|
|
switch (verb) {
|
|
case "":
|
|
return "All time";
|
|
case "next":
|
|
case "last": {
|
|
const [amount, unit] = unitNumber(args);
|
|
switch (unit) {
|
|
case "d": case "days":
|
|
return `${capitalize(verb)} ${amount} ${amount !== 1 ? "days" : "day"}`
|
|
case "w": case "weeks":
|
|
return `${capitalize(verb)} ${amount} ${amount !== 1 ? "weeks" : "week"}`
|
|
case "m": case "months":
|
|
return `${capitalize(verb)} ${amount} ${amount !== 1 ? "months" : "month"}`
|
|
case "y": case "years":
|
|
return `${capitalize(verb)} ${amount} ${amount !== 1 ? "years" : "year"}`
|
|
}
|
|
}
|
|
case "today":
|
|
return verb;
|
|
case "all_time":
|
|
case "next_week":
|
|
case "this_week":
|
|
case "last_week":
|
|
case "next_month":
|
|
case "this_month":
|
|
case "last_month":
|
|
case "next_year":
|
|
case "this_year":
|
|
case "last_year":
|
|
return capitalize(verb.replace("_", " "));
|
|
}
|
|
}
|
|
|
|
export function datesOf(interval: TimeInterval<string | Date>): TimeInterval<string> {
|
|
if (interval == null) {
|
|
return void(0)
|
|
}
|
|
|
|
return {min: formatDate(interval.min), max: formatDate(interval.max)}
|
|
}
|
|
|
|
function capitalize(s: string) {
|
|
return `${s.charAt(0).toLocaleUpperCase()}${s.slice(1)}`
|
|
}
|
|
|
|
function unitNumber(s: string): [number, string] {
|
|
for (let i = 0; i < s.length; ++i) {
|
|
const ch = s.charAt(i);
|
|
|
|
if (ch < '0' || ch > '9') {
|
|
return [parseInt(s.slice(0, i)), s.slice(i)]
|
|
}
|
|
}
|
|
|
|
return [parseInt(s), ""];
|
|
}
|