@autometa/datetime
Advanced tools
| export interface Clock { | ||
| now(): Date; | ||
| } | ||
| export declare const systemClock: Clock; | ||
| export declare function cloneDate(date: Date): Date; |
| import type { Clock } from "./clock.js"; | ||
| import { type StandardTimeUnit } from "./time-units.js"; | ||
| export type DateShortcut = "now" | "beforeYesterday" | "yesterday" | "today" | "tomorrow" | "afterTomorrow" | "midnight" | "lastWeek" | "nextWeek" | "lastFortnight" | "nextFortnight"; | ||
| export interface DateFactoryOptions { | ||
| clock?: Clock; | ||
| } | ||
| export declare class DateFactory { | ||
| private readonly clock; | ||
| constructor(options?: DateFactoryOptions); | ||
| find(shortcut: DateShortcut): Date; | ||
| fromPhraseSafe(phrase: unknown): Date; | ||
| fromPhrase(phrase: unknown): Date; | ||
| make(timeOffset: number, timeUnit: string | StandardTimeUnit): Date; | ||
| private currentDate; | ||
| private midnight; | ||
| private parseDate; | ||
| private isDateLike; | ||
| private extractRelative; | ||
| private buildRelativeMatch; | ||
| } |
| import type { DateFactory } from "./date-factory.js"; | ||
| import type { StandardTimeUnit } from "./time-units.js"; | ||
| export interface FormattedDateFactoryOptions { | ||
| formatter?: (date: Date) => string; | ||
| } | ||
| export declare class FormattedDateFactory { | ||
| private readonly dateFactory; | ||
| private readonly format; | ||
| constructor(dateFactory: DateFactory, options?: FormattedDateFactoryOptions); | ||
| make(offset: number, unit: StandardTimeUnit | string): string; | ||
| fromPhrase(phrase: unknown): string; | ||
| get beforeYesterday(): string; | ||
| get yesterday(): string; | ||
| get today(): string; | ||
| get tomorrow(): string; | ||
| get afterTomorrow(): string; | ||
| get midnight(): string; | ||
| get lastWeek(): string; | ||
| get nextWeek(): string; | ||
| get lastFortnight(): string; | ||
| get nextFortnight(): string; | ||
| private fromShortcut; | ||
| } |
| import type { DateFactory } from "./date-factory.js"; | ||
| import type { StandardTimeUnit } from "./time-units.js"; | ||
| export interface IsoDateFactoryOptions { | ||
| serializer?: (date: Date) => string; | ||
| } | ||
| export declare class IsoDateFactory { | ||
| private readonly dateFactory; | ||
| private readonly serialise; | ||
| constructor(dateFactory: DateFactory, options?: IsoDateFactoryOptions); | ||
| make(offset: number, unit: StandardTimeUnit | string): string; | ||
| fromPhrase(phrase: unknown): string; | ||
| get beforeYesterday(): string; | ||
| get yesterday(): string; | ||
| get today(): string; | ||
| get tomorrow(): string; | ||
| get afterTomorrow(): string; | ||
| get midnight(): string; | ||
| get lastWeek(): string; | ||
| get nextWeek(): string; | ||
| get lastFortnight(): string; | ||
| get nextFortnight(): string; | ||
| private fromShortcut; | ||
| } |
| import { DateFactory, type DateFactoryOptions } from "./date-factory.js"; | ||
| import { FormattedDateFactory } from "./formatted-date-factory.js"; | ||
| import { IsoDateFactory } from "./iso-date-factory.js"; | ||
| import type { StandardTimeUnit } from "./time-units.js"; | ||
| export interface DatesOptions extends DateFactoryOptions { | ||
| factory?: DateFactory; | ||
| } | ||
| export interface DatesObject { | ||
| readonly iso: IsoDateFactory; | ||
| readonly fmt: FormattedDateFactory; | ||
| readonly now: Date; | ||
| readonly beforeYesterday: Date; | ||
| readonly yesterday: Date; | ||
| readonly today: Date; | ||
| readonly tomorrow: Date; | ||
| readonly afterTomorrow: Date; | ||
| readonly midnight: Date; | ||
| readonly lastWeek: Date; | ||
| readonly nextWeek: Date; | ||
| readonly lastFortnight: Date; | ||
| readonly nextFortnight: Date; | ||
| fromPhrase(phrase: unknown): Date; | ||
| fromPhraseSafe(phrase: unknown): Date; | ||
| make(offset: number, unit: StandardTimeUnit | string): Date; | ||
| } | ||
| export declare function createDates(options?: DatesOptions): DatesObject; | ||
| export declare const Dates: DatesObject; | ||
| export type { DateFactoryOptions }; |
| export type StandardTimeUnit = "milliseconds" | "seconds" | "minutes" | "hours" | "days" | "weeks" | "months" | "years"; | ||
| export interface NormalisedTimeUnit { | ||
| unit: StandardTimeUnit; | ||
| scale: number; | ||
| } | ||
| export declare function resolveTimeUnit(input: string): NormalisedTimeUnit; |
+482
| 'use strict'; | ||
| var errors = require('@autometa/errors'); | ||
| var isoDatestringValidator = require('iso-datestring-validator'); | ||
| var asserters = require('@autometa/asserters'); | ||
| // src/dates/date-factory.ts | ||
| // src/dates/clock.ts | ||
| var systemClock = { | ||
| now: () => /* @__PURE__ */ new Date() | ||
| }; | ||
| function cloneDate(date) { | ||
| return new Date(date.getTime()); | ||
| } | ||
| var UNIT_ALIASES = { | ||
| millisecond: { unit: "milliseconds", scale: 1 }, | ||
| milliseconds: { unit: "milliseconds", scale: 1 }, | ||
| ms: { unit: "milliseconds", scale: 1 }, | ||
| second: { unit: "seconds", scale: 1 }, | ||
| seconds: { unit: "seconds", scale: 1 }, | ||
| sec: { unit: "seconds", scale: 1 }, | ||
| secs: { unit: "seconds", scale: 1 }, | ||
| minute: { unit: "minutes", scale: 1 }, | ||
| minutes: { unit: "minutes", scale: 1 }, | ||
| min: { unit: "minutes", scale: 1 }, | ||
| mins: { unit: "minutes", scale: 1 }, | ||
| hour: { unit: "hours", scale: 1 }, | ||
| hours: { unit: "hours", scale: 1 }, | ||
| hr: { unit: "hours", scale: 1 }, | ||
| hrs: { unit: "hours", scale: 1 }, | ||
| day: { unit: "days", scale: 1 }, | ||
| days: { unit: "days", scale: 1 }, | ||
| week: { unit: "weeks", scale: 1 }, | ||
| weeks: { unit: "weeks", scale: 1 }, | ||
| fortnight: { unit: "days", scale: 14 }, | ||
| fortnights: { unit: "days", scale: 14 }, | ||
| month: { unit: "months", scale: 1 }, | ||
| months: { unit: "months", scale: 1 }, | ||
| year: { unit: "years", scale: 1 }, | ||
| years: { unit: "years", scale: 1 } | ||
| }; | ||
| function resolveTimeUnit(input) { | ||
| const key = input.trim().toLowerCase(); | ||
| const resolved = UNIT_ALIASES[key]; | ||
| if (!resolved) { | ||
| throw new errors.AutomationError( | ||
| `Unsupported time unit '${input}'. Expected one of ${Object.keys(UNIT_ALIASES).sort().join(", ")}.` | ||
| ); | ||
| } | ||
| return resolved; | ||
| } | ||
| // src/shared/phrases.ts | ||
| var SEPARATORS = /[\s_-]+/g; | ||
| function capitalize(word) { | ||
| return word.charAt(0).toUpperCase() + word.slice(1); | ||
| } | ||
| function splitWords(phrase) { | ||
| return phrase.trim().split(SEPARATORS).filter(Boolean).map((word) => word.toLowerCase()); | ||
| } | ||
| function toCamelKey(phrase) { | ||
| const words = splitWords(phrase); | ||
| if (words.length === 0) { | ||
| return ""; | ||
| } | ||
| const [first, ...rest] = words; | ||
| return first + rest.map(capitalize).join(""); | ||
| } | ||
| function normalizeToken(phrase) { | ||
| return splitWords(phrase).join(""); | ||
| } | ||
| // src/dates/date-factory.ts | ||
| var SHORTCUT_LOOKUP = /* @__PURE__ */ new Set([ | ||
| "now", | ||
| "beforeYesterday", | ||
| "yesterday", | ||
| "today", | ||
| "tomorrow", | ||
| "afterTomorrow", | ||
| "midnight", | ||
| "lastWeek", | ||
| "nextWeek", | ||
| "lastFortnight", | ||
| "nextFortnight" | ||
| ]); | ||
| var FUTURE_PATTERN = /^(\d+)\s+([A-Za-z\s]+?)\s+from\s+now$/i; | ||
| var PAST_PATTERN = /^(\d+)\s+([A-Za-z\s]+?)\s+ago$/i; | ||
| function invalidDate() { | ||
| return new Date(Number.NaN); | ||
| } | ||
| function isDateShortcut(value) { | ||
| return SHORTCUT_LOOKUP.has(value); | ||
| } | ||
| var DateFactory = class { | ||
| constructor(options = {}) { | ||
| this.clock = options.clock ?? systemClock; | ||
| } | ||
| find(shortcut) { | ||
| switch (shortcut) { | ||
| case "now": | ||
| return this.currentDate(); | ||
| case "beforeYesterday": | ||
| return this.make(-2, "days"); | ||
| case "yesterday": | ||
| return this.make(-1, "days"); | ||
| case "today": | ||
| return this.make(0, "days"); | ||
| case "tomorrow": | ||
| return this.make(1, "days"); | ||
| case "afterTomorrow": | ||
| return this.make(2, "days"); | ||
| case "midnight": | ||
| return this.midnight(); | ||
| case "lastWeek": | ||
| return this.make(-1, "weeks"); | ||
| case "nextWeek": | ||
| return this.make(1, "weeks"); | ||
| case "lastFortnight": | ||
| return this.make(-14, "days"); | ||
| case "nextFortnight": | ||
| return this.make(14, "days"); | ||
| default: | ||
| throw new errors.AutomationError( | ||
| `Unsupported date shortcut '${shortcut}'.` | ||
| ); | ||
| } | ||
| } | ||
| fromPhraseSafe(phrase) { | ||
| if (typeof phrase !== "string") { | ||
| return invalidDate(); | ||
| } | ||
| const trimmed = phrase.trim(); | ||
| if (trimmed.length === 0) { | ||
| return invalidDate(); | ||
| } | ||
| const shortcutCandidate = toCamelKey(trimmed); | ||
| if (isDateShortcut(shortcutCandidate)) { | ||
| return this.find(shortcutCandidate); | ||
| } | ||
| const relative = this.extractRelative(trimmed); | ||
| if (relative) { | ||
| return this.make(relative.offset, relative.unit); | ||
| } | ||
| if (this.isDateLike(trimmed)) { | ||
| return this.parseDate(trimmed); | ||
| } | ||
| return invalidDate(); | ||
| } | ||
| fromPhrase(phrase) { | ||
| const result = this.fromPhraseSafe(phrase); | ||
| if (Number.isNaN(result.getTime())) { | ||
| throw new errors.AutomationError( | ||
| `Could not parse date from phrase '${String(phrase)}'. Valid shortcuts are: ${[...SHORTCUT_LOOKUP].join(", ")}.` | ||
| ); | ||
| } | ||
| return result; | ||
| } | ||
| make(timeOffset, timeUnit) { | ||
| if (!Number.isFinite(timeOffset)) { | ||
| throw new errors.AutomationError( | ||
| `Time offset must be finite. Received '${timeOffset}'.` | ||
| ); | ||
| } | ||
| const { unit, scale } = resolveTimeUnit(String(timeUnit)); | ||
| const offset = timeOffset * scale; | ||
| const date = this.currentDate(); | ||
| switch (unit) { | ||
| case "years": | ||
| date.setFullYear(date.getFullYear() + offset); | ||
| break; | ||
| case "months": | ||
| date.setMonth(date.getMonth() + offset); | ||
| break; | ||
| case "weeks": | ||
| date.setDate(date.getDate() + offset * 7); | ||
| break; | ||
| case "days": | ||
| date.setDate(date.getDate() + offset); | ||
| break; | ||
| case "hours": | ||
| date.setHours(date.getHours() + offset); | ||
| break; | ||
| case "minutes": | ||
| date.setMinutes(date.getMinutes() + offset); | ||
| break; | ||
| case "seconds": | ||
| date.setSeconds(date.getSeconds() + offset); | ||
| break; | ||
| case "milliseconds": | ||
| date.setMilliseconds(date.getMilliseconds() + offset); | ||
| break; | ||
| default: | ||
| throw new errors.AutomationError(`Unsupported time unit '${unit}'.`); | ||
| } | ||
| return date; | ||
| } | ||
| currentDate() { | ||
| return cloneDate(this.clock.now()); | ||
| } | ||
| midnight() { | ||
| const date = this.currentDate(); | ||
| date.setUTCDate(date.getUTCDate() + 1); | ||
| date.setUTCHours(0, 0, 0, 0); | ||
| return date; | ||
| } | ||
| parseDate(value) { | ||
| const parsed = new Date(value); | ||
| if (!Number.isNaN(parsed.getTime())) { | ||
| return parsed; | ||
| } | ||
| return new Date(Date.parse(value)); | ||
| } | ||
| isDateLike(value) { | ||
| if (!Number.isNaN(new Date(value).getTime())) { | ||
| return true; | ||
| } | ||
| return isoDatestringValidator.isValidDate(value) || isoDatestringValidator.isValidISODateString(value) || isoDatestringValidator.isValidTime(value) || isoDatestringValidator.isValidYearMonth(value); | ||
| } | ||
| extractRelative(phrase) { | ||
| const futureMatch = FUTURE_PATTERN.exec(phrase); | ||
| if (futureMatch) { | ||
| return this.buildRelativeMatch(futureMatch, 1); | ||
| } | ||
| const pastMatch = PAST_PATTERN.exec(phrase); | ||
| if (pastMatch) { | ||
| return this.buildRelativeMatch(pastMatch, -1); | ||
| } | ||
| return void 0; | ||
| } | ||
| buildRelativeMatch(match, direction) { | ||
| const value = match[1]; | ||
| const unit = match[2]; | ||
| if (!value || !unit) { | ||
| return void 0; | ||
| } | ||
| const magnitude = Number.parseInt(value, 10); | ||
| if (!Number.isFinite(magnitude)) { | ||
| return void 0; | ||
| } | ||
| const convertedUnit = normalizeToken(unit); | ||
| const { unit: normalisedUnit, scale } = resolveTimeUnit(convertedUnit); | ||
| const offset = magnitude * scale * direction; | ||
| return { | ||
| offset, | ||
| unit: normalisedUnit | ||
| }; | ||
| } | ||
| }; | ||
| // src/dates/formatted-date-factory.ts | ||
| var FormattedDateFactory = class { | ||
| constructor(dateFactory, options = {}) { | ||
| this.dateFactory = dateFactory; | ||
| this.format = options.formatter ?? ((date) => date.toISOString().substring(0, 10)); | ||
| } | ||
| make(offset, unit) { | ||
| return this.format(this.dateFactory.make(offset, unit)); | ||
| } | ||
| fromPhrase(phrase) { | ||
| return this.format(this.dateFactory.fromPhrase(phrase)); | ||
| } | ||
| get beforeYesterday() { | ||
| return this.fromShortcut("beforeYesterday"); | ||
| } | ||
| get yesterday() { | ||
| return this.fromShortcut("yesterday"); | ||
| } | ||
| get today() { | ||
| return this.fromShortcut("today"); | ||
| } | ||
| get tomorrow() { | ||
| return this.fromShortcut("tomorrow"); | ||
| } | ||
| get afterTomorrow() { | ||
| return this.fromShortcut("afterTomorrow"); | ||
| } | ||
| get midnight() { | ||
| return this.fromShortcut("midnight"); | ||
| } | ||
| get lastWeek() { | ||
| return this.fromShortcut("lastWeek"); | ||
| } | ||
| get nextWeek() { | ||
| return this.fromShortcut("nextWeek"); | ||
| } | ||
| get lastFortnight() { | ||
| return this.fromShortcut("lastFortnight"); | ||
| } | ||
| get nextFortnight() { | ||
| return this.fromShortcut("nextFortnight"); | ||
| } | ||
| fromShortcut(shortcut) { | ||
| return this.format(this.dateFactory.find(shortcut)); | ||
| } | ||
| }; | ||
| // src/dates/iso-date-factory.ts | ||
| var IsoDateFactory = class { | ||
| constructor(dateFactory, options = {}) { | ||
| this.dateFactory = dateFactory; | ||
| this.serialise = options.serializer ?? ((date) => date.toISOString()); | ||
| } | ||
| make(offset, unit) { | ||
| return this.serialise(this.dateFactory.make(offset, unit)); | ||
| } | ||
| fromPhrase(phrase) { | ||
| return this.serialise(this.dateFactory.fromPhrase(phrase)); | ||
| } | ||
| get beforeYesterday() { | ||
| return this.fromShortcut("beforeYesterday"); | ||
| } | ||
| get yesterday() { | ||
| return this.fromShortcut("yesterday"); | ||
| } | ||
| get today() { | ||
| return this.fromShortcut("today"); | ||
| } | ||
| get tomorrow() { | ||
| return this.fromShortcut("tomorrow"); | ||
| } | ||
| get afterTomorrow() { | ||
| return this.fromShortcut("afterTomorrow"); | ||
| } | ||
| get midnight() { | ||
| return this.fromShortcut("midnight"); | ||
| } | ||
| get lastWeek() { | ||
| return this.fromShortcut("lastWeek"); | ||
| } | ||
| get nextWeek() { | ||
| return this.fromShortcut("nextWeek"); | ||
| } | ||
| get lastFortnight() { | ||
| return this.fromShortcut("lastFortnight"); | ||
| } | ||
| get nextFortnight() { | ||
| return this.fromShortcut("nextFortnight"); | ||
| } | ||
| fromShortcut(shortcut) { | ||
| return this.serialise(this.dateFactory.find(shortcut)); | ||
| } | ||
| }; | ||
| // src/dates/object.ts | ||
| var DatesFacade = class { | ||
| constructor(factory) { | ||
| this.factory = factory; | ||
| this.iso = new IsoDateFactory(factory); | ||
| this.fmt = new FormattedDateFactory(factory); | ||
| } | ||
| get now() { | ||
| return this.fromShortcut("now"); | ||
| } | ||
| get beforeYesterday() { | ||
| return this.fromShortcut("beforeYesterday"); | ||
| } | ||
| get yesterday() { | ||
| return this.fromShortcut("yesterday"); | ||
| } | ||
| get today() { | ||
| return this.fromShortcut("today"); | ||
| } | ||
| get tomorrow() { | ||
| return this.fromShortcut("tomorrow"); | ||
| } | ||
| get afterTomorrow() { | ||
| return this.fromShortcut("afterTomorrow"); | ||
| } | ||
| get midnight() { | ||
| return this.fromShortcut("midnight"); | ||
| } | ||
| get lastWeek() { | ||
| return this.fromShortcut("lastWeek"); | ||
| } | ||
| get nextWeek() { | ||
| return this.fromShortcut("nextWeek"); | ||
| } | ||
| get lastFortnight() { | ||
| return this.fromShortcut("lastFortnight"); | ||
| } | ||
| get nextFortnight() { | ||
| return this.fromShortcut("nextFortnight"); | ||
| } | ||
| fromPhrase(phrase) { | ||
| return this.factory.fromPhrase(phrase); | ||
| } | ||
| fromPhraseSafe(phrase) { | ||
| return this.factory.fromPhraseSafe(phrase); | ||
| } | ||
| make(offset, unit) { | ||
| return this.factory.make(offset, unit); | ||
| } | ||
| fromShortcut(shortcut) { | ||
| return this.factory.find(shortcut); | ||
| } | ||
| }; | ||
| function createDates(options = {}) { | ||
| const factory = options.factory ?? new DateFactory(options); | ||
| return new DatesFacade(factory); | ||
| } | ||
| var Dates = createDates(); | ||
| var SUPPORTED_METHODS = [ | ||
| "minutes", | ||
| "seconds", | ||
| "millis", | ||
| "days", | ||
| "hours", | ||
| "weeks" | ||
| ]; | ||
| function toTime(date) { | ||
| return new Date(date).getTime(); | ||
| } | ||
| var TimeDiff = class { | ||
| minutes(start, end) { | ||
| return this.millis(start, end) / 6e4; | ||
| } | ||
| seconds(start, end) { | ||
| return this.millis(start, end) / 1e3; | ||
| } | ||
| millis(start, end) { | ||
| const distance = Math.abs(toTime(end) - toTime(start)); | ||
| return Math.round(distance); | ||
| } | ||
| days(start, end) { | ||
| return this.millis(start, end) / 864e5; | ||
| } | ||
| hours(start, end) { | ||
| return this.millis(start, end) / 36e5; | ||
| } | ||
| weeks(start, end) { | ||
| return this.millis(start, end) / 6048e5; | ||
| } | ||
| fromPhrase(phrase) { | ||
| if (typeof phrase !== "string") { | ||
| throw new errors.AutomationError( | ||
| `TimeDiff.fromPhrase expects a string, received '${typeof phrase}'.` | ||
| ); | ||
| } | ||
| const key = normalizeToken(phrase); | ||
| if (!this.hasMethod(key)) { | ||
| throw new errors.AutomationError( | ||
| `Unsupported diff unit '${phrase}'. Expected one of ${this.supportedMethods().join(", ")}.` | ||
| ); | ||
| } | ||
| asserters.assertKey(this, key, "TimeDiff.fromPhrase"); | ||
| const method = this[key]; | ||
| if (typeof method !== "function") { | ||
| throw new errors.AutomationError(`Diff method '${key}' is not callable.`); | ||
| } | ||
| return method.bind(this); | ||
| } | ||
| hasMethod(name) { | ||
| return SUPPORTED_METHODS.includes(name); | ||
| } | ||
| supportedMethods() { | ||
| return [...SUPPORTED_METHODS]; | ||
| } | ||
| }; | ||
| // src/time/time.ts | ||
| var TimeFacade = class { | ||
| constructor(diff) { | ||
| this.diff = diff; | ||
| } | ||
| }; | ||
| function createTime() { | ||
| return new TimeFacade(new TimeDiff()); | ||
| } | ||
| var Time = createTime(); | ||
| exports.DateFactory = DateFactory; | ||
| exports.Dates = Dates; | ||
| exports.FormattedDateFactory = FormattedDateFactory; | ||
| exports.IsoDateFactory = IsoDateFactory; | ||
| exports.Time = Time; | ||
| exports.TimeDiff = TimeDiff; | ||
| exports.createDates = createDates; | ||
| exports.createTime = createTime; | ||
| //# sourceMappingURL=out.js.map | ||
| //# sourceMappingURL=index.cjs.map |
| {"version":3,"sources":["../src/dates/date-factory.ts","../src/dates/clock.ts","../src/dates/time-units.ts","../src/shared/phrases.ts","../src/dates/formatted-date-factory.ts","../src/dates/iso-date-factory.ts","../src/dates/object.ts","../src/time/time-diff.ts","../src/time/time.ts"],"names":["AutomationError"],"mappings":"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","sourcesContent":["import { AutomationError } from \"@autometa/errors\";\nimport {\n isValidDate,\n isValidISODateString,\n isValidTime,\n isValidYearMonth,\n} from \"iso-datestring-validator\";\nimport type { Clock } from \"./clock.js\";\nimport { cloneDate, systemClock } from \"./clock.js\";\nimport {\n resolveTimeUnit,\n type StandardTimeUnit,\n} from \"./time-units.js\";\nimport { normalizeToken, toCamelKey } from \"../shared/phrases.js\";\n\nexport type DateShortcut =\n | \"now\"\n | \"beforeYesterday\"\n | \"yesterday\"\n | \"today\"\n | \"tomorrow\"\n | \"afterTomorrow\"\n | \"midnight\"\n | \"lastWeek\"\n | \"nextWeek\"\n | \"lastFortnight\"\n | \"nextFortnight\";\n\nconst SHORTCUT_LOOKUP = new Set<DateShortcut>([\n \"now\",\n \"beforeYesterday\",\n \"yesterday\",\n \"today\",\n \"tomorrow\",\n \"afterTomorrow\",\n \"midnight\",\n \"lastWeek\",\n \"nextWeek\",\n \"lastFortnight\",\n \"nextFortnight\",\n]);\n\nexport interface DateFactoryOptions {\n clock?: Clock;\n}\n\ninterface RelativePhraseMatch {\n offset: number;\n unit: StandardTimeUnit;\n}\n\nconst FUTURE_PATTERN = /^(\\d+)\\s+([A-Za-z\\s]+?)\\s+from\\s+now$/i;\nconst PAST_PATTERN = /^(\\d+)\\s+([A-Za-z\\s]+?)\\s+ago$/i;\n\nfunction invalidDate(): Date {\n return new Date(Number.NaN);\n}\n\nfunction isDateShortcut(value: string): value is DateShortcut {\n return SHORTCUT_LOOKUP.has(value as DateShortcut);\n}\n\nexport class DateFactory {\n private readonly clock: Clock;\n\n constructor(options: DateFactoryOptions = {}) {\n this.clock = options.clock ?? systemClock;\n }\n\n find(shortcut: DateShortcut): Date {\n switch (shortcut) {\n case \"now\":\n return this.currentDate();\n case \"beforeYesterday\":\n return this.make(-2, \"days\");\n case \"yesterday\":\n return this.make(-1, \"days\");\n case \"today\":\n return this.make(0, \"days\");\n case \"tomorrow\":\n return this.make(1, \"days\");\n case \"afterTomorrow\":\n return this.make(2, \"days\");\n case \"midnight\":\n return this.midnight();\n case \"lastWeek\":\n return this.make(-1, \"weeks\");\n case \"nextWeek\":\n return this.make(1, \"weeks\");\n case \"lastFortnight\":\n return this.make(-14, \"days\");\n case \"nextFortnight\":\n return this.make(14, \"days\");\n default:\n throw new AutomationError(\n `Unsupported date shortcut '${shortcut}'.`\n );\n }\n }\n\n fromPhraseSafe(phrase: unknown): Date {\n if (typeof phrase !== \"string\") {\n return invalidDate();\n }\n\n const trimmed = phrase.trim();\n if (trimmed.length === 0) {\n return invalidDate();\n }\n\n const shortcutCandidate = toCamelKey(trimmed);\n if (isDateShortcut(shortcutCandidate)) {\n return this.find(shortcutCandidate);\n }\n\n const relative = this.extractRelative(trimmed);\n if (relative) {\n return this.make(relative.offset, relative.unit);\n }\n\n if (this.isDateLike(trimmed)) {\n return this.parseDate(trimmed);\n }\n\n return invalidDate();\n }\n\n fromPhrase(phrase: unknown): Date {\n const result = this.fromPhraseSafe(phrase);\n if (Number.isNaN(result.getTime())) {\n throw new AutomationError(\n `Could not parse date from phrase '${String(phrase)}'. ` +\n `Valid shortcuts are: ${[...SHORTCUT_LOOKUP].join(\", \")}.`\n );\n }\n return result;\n }\n\n make(timeOffset: number, timeUnit: string | StandardTimeUnit): Date {\n if (!Number.isFinite(timeOffset)) {\n throw new AutomationError(\n `Time offset must be finite. Received '${timeOffset}'.`\n );\n }\n\n const { unit, scale } = resolveTimeUnit(String(timeUnit));\n const offset = timeOffset * scale;\n const date = this.currentDate();\n\n switch (unit) {\n case \"years\":\n date.setFullYear(date.getFullYear() + offset);\n break;\n case \"months\":\n date.setMonth(date.getMonth() + offset);\n break;\n case \"weeks\":\n date.setDate(date.getDate() + offset * 7);\n break;\n case \"days\":\n date.setDate(date.getDate() + offset);\n break;\n case \"hours\":\n date.setHours(date.getHours() + offset);\n break;\n case \"minutes\":\n date.setMinutes(date.getMinutes() + offset);\n break;\n case \"seconds\":\n date.setSeconds(date.getSeconds() + offset);\n break;\n case \"milliseconds\":\n date.setMilliseconds(date.getMilliseconds() + offset);\n break;\n default:\n throw new AutomationError(`Unsupported time unit '${unit}'.`);\n }\n\n return date;\n }\n\n private currentDate(): Date {\n return cloneDate(this.clock.now());\n }\n\n private midnight(): Date {\n const date = this.currentDate();\n date.setUTCDate(date.getUTCDate() + 1);\n date.setUTCHours(0, 0, 0, 0);\n return date;\n }\n\n private parseDate(value: string): Date {\n const parsed = new Date(value);\n if (!Number.isNaN(parsed.getTime())) {\n return parsed;\n }\n return new Date(Date.parse(value));\n }\n\n private isDateLike(value: string): boolean {\n if (!Number.isNaN(new Date(value).getTime())) {\n return true;\n }\n return (\n isValidDate(value) ||\n isValidISODateString(value) ||\n isValidTime(value) ||\n isValidYearMonth(value)\n );\n }\n\n private extractRelative(phrase: string): RelativePhraseMatch | undefined {\n const futureMatch = FUTURE_PATTERN.exec(phrase);\n if (futureMatch) {\n return this.buildRelativeMatch(futureMatch, 1);\n }\n\n const pastMatch = PAST_PATTERN.exec(phrase);\n if (pastMatch) {\n return this.buildRelativeMatch(pastMatch, -1);\n }\n\n return undefined;\n }\n\n private buildRelativeMatch(\n match: RegExpExecArray,\n direction: 1 | -1\n ): RelativePhraseMatch | undefined {\n const value = match[1];\n const unit = match[2];\n if (!value || !unit) {\n return undefined;\n }\n\n const magnitude = Number.parseInt(value, 10);\n if (!Number.isFinite(magnitude)) {\n return undefined;\n }\n\n const convertedUnit = normalizeToken(unit);\n const { unit: normalisedUnit, scale } = resolveTimeUnit(convertedUnit);\n const offset = magnitude * scale * direction;\n return {\n offset,\n unit: normalisedUnit,\n };\n }\n}\n","export interface Clock {\n now(): Date;\n}\n\nexport const systemClock: Clock = {\n now: () => new Date(),\n};\n\nexport function cloneDate(date: Date): Date {\n return new Date(date.getTime());\n}\n","import { AutomationError } from \"@autometa/errors\";\n\nexport type StandardTimeUnit =\n | \"milliseconds\"\n | \"seconds\"\n | \"minutes\"\n | \"hours\"\n | \"days\"\n | \"weeks\"\n | \"months\"\n | \"years\";\n\nexport interface NormalisedTimeUnit {\n unit: StandardTimeUnit;\n scale: number;\n}\n\nconst UNIT_ALIASES: Record<string, NormalisedTimeUnit> = {\n millisecond: { unit: \"milliseconds\", scale: 1 },\n milliseconds: { unit: \"milliseconds\", scale: 1 },\n ms: { unit: \"milliseconds\", scale: 1 },\n second: { unit: \"seconds\", scale: 1 },\n seconds: { unit: \"seconds\", scale: 1 },\n sec: { unit: \"seconds\", scale: 1 },\n secs: { unit: \"seconds\", scale: 1 },\n minute: { unit: \"minutes\", scale: 1 },\n minutes: { unit: \"minutes\", scale: 1 },\n min: { unit: \"minutes\", scale: 1 },\n mins: { unit: \"minutes\", scale: 1 },\n hour: { unit: \"hours\", scale: 1 },\n hours: { unit: \"hours\", scale: 1 },\n hr: { unit: \"hours\", scale: 1 },\n hrs: { unit: \"hours\", scale: 1 },\n day: { unit: \"days\", scale: 1 },\n days: { unit: \"days\", scale: 1 },\n week: { unit: \"weeks\", scale: 1 },\n weeks: { unit: \"weeks\", scale: 1 },\n fortnight: { unit: \"days\", scale: 14 },\n fortnights: { unit: \"days\", scale: 14 },\n month: { unit: \"months\", scale: 1 },\n months: { unit: \"months\", scale: 1 },\n year: { unit: \"years\", scale: 1 },\n years: { unit: \"years\", scale: 1 },\n};\n\nexport function resolveTimeUnit(input: string): NormalisedTimeUnit {\n const key = input.trim().toLowerCase();\n const resolved = UNIT_ALIASES[key];\n if (!resolved) {\n throw new AutomationError(\n `Unsupported time unit '${input}'. Expected one of ${Object.keys(UNIT_ALIASES)\n .sort()\n .join(\", \")}.`\n );\n }\n return resolved;\n}\n","const SEPARATORS = /[\\s_-]+/g;\n\nfunction capitalize(word: string): string {\n return word.charAt(0).toUpperCase() + word.slice(1);\n}\n\nfunction splitWords(phrase: string): string[] {\n return phrase\n .trim()\n .split(SEPARATORS)\n .filter(Boolean)\n .map((word) => word.toLowerCase());\n}\n\nexport function toCamelKey(phrase: string): string {\n const words = splitWords(phrase);\n if (words.length === 0) {\n return \"\";\n }\n const [first, ...rest] = words;\n return first + rest.map(capitalize).join(\"\");\n}\n\nexport function normalizeToken(phrase: string): string {\n return splitWords(phrase).join(\"\");\n}\n","import type { DateFactory, DateShortcut } from \"./date-factory.js\";\nimport type { StandardTimeUnit } from \"./time-units.js\";\n\nexport interface FormattedDateFactoryOptions {\n formatter?: (date: Date) => string;\n}\n\nexport class FormattedDateFactory {\n private readonly format: (date: Date) => string;\n\n constructor(\n private readonly dateFactory: DateFactory,\n options: FormattedDateFactoryOptions = {}\n ) {\n this.format =\n options.formatter ?? ((date) => date.toISOString().substring(0, 10));\n }\n\n make(offset: number, unit: StandardTimeUnit | string): string {\n return this.format(this.dateFactory.make(offset, unit));\n }\n\n fromPhrase(phrase: unknown): string {\n return this.format(this.dateFactory.fromPhrase(phrase));\n }\n\n get beforeYesterday(): string {\n return this.fromShortcut(\"beforeYesterday\");\n }\n\n get yesterday(): string {\n return this.fromShortcut(\"yesterday\");\n }\n\n get today(): string {\n return this.fromShortcut(\"today\");\n }\n\n get tomorrow(): string {\n return this.fromShortcut(\"tomorrow\");\n }\n\n get afterTomorrow(): string {\n return this.fromShortcut(\"afterTomorrow\");\n }\n\n get midnight(): string {\n return this.fromShortcut(\"midnight\");\n }\n\n get lastWeek(): string {\n return this.fromShortcut(\"lastWeek\");\n }\n\n get nextWeek(): string {\n return this.fromShortcut(\"nextWeek\");\n }\n\n get lastFortnight(): string {\n return this.fromShortcut(\"lastFortnight\");\n }\n\n get nextFortnight(): string {\n return this.fromShortcut(\"nextFortnight\");\n }\n\n private fromShortcut(shortcut: DateShortcut): string {\n return this.format(this.dateFactory.find(shortcut));\n }\n}\n","import type { DateFactory, DateShortcut } from \"./date-factory.js\";\nimport type { StandardTimeUnit } from \"./time-units.js\";\n\nexport interface IsoDateFactoryOptions {\n serializer?: (date: Date) => string;\n}\n\nexport class IsoDateFactory {\n private readonly serialise: (date: Date) => string;\n\n constructor(\n private readonly dateFactory: DateFactory,\n options: IsoDateFactoryOptions = {}\n ) {\n this.serialise = options.serializer ?? ((date) => date.toISOString());\n }\n\n make(offset: number, unit: StandardTimeUnit | string): string {\n return this.serialise(this.dateFactory.make(offset, unit));\n }\n\n fromPhrase(phrase: unknown): string {\n return this.serialise(this.dateFactory.fromPhrase(phrase));\n }\n\n get beforeYesterday(): string {\n return this.fromShortcut(\"beforeYesterday\");\n }\n\n get yesterday(): string {\n return this.fromShortcut(\"yesterday\");\n }\n\n get today(): string {\n return this.fromShortcut(\"today\");\n }\n\n get tomorrow(): string {\n return this.fromShortcut(\"tomorrow\");\n }\n\n get afterTomorrow(): string {\n return this.fromShortcut(\"afterTomorrow\");\n }\n\n get midnight(): string {\n return this.fromShortcut(\"midnight\");\n }\n\n get lastWeek(): string {\n return this.fromShortcut(\"lastWeek\");\n }\n\n get nextWeek(): string {\n return this.fromShortcut(\"nextWeek\");\n }\n\n get lastFortnight(): string {\n return this.fromShortcut(\"lastFortnight\");\n }\n\n get nextFortnight(): string {\n return this.fromShortcut(\"nextFortnight\");\n }\n\n private fromShortcut(shortcut: DateShortcut): string {\n return this.serialise(this.dateFactory.find(shortcut));\n }\n}\n","import { DateFactory, type DateFactoryOptions, type DateShortcut } from \"./date-factory.js\";\nimport { FormattedDateFactory } from \"./formatted-date-factory.js\";\nimport { IsoDateFactory } from \"./iso-date-factory.js\";\nimport type { StandardTimeUnit } from \"./time-units.js\";\n\nexport interface DatesOptions extends DateFactoryOptions {\n factory?: DateFactory;\n}\n\nexport interface DatesObject {\n readonly iso: IsoDateFactory;\n readonly fmt: FormattedDateFactory;\n readonly now: Date;\n readonly beforeYesterday: Date;\n readonly yesterday: Date;\n readonly today: Date;\n readonly tomorrow: Date;\n readonly afterTomorrow: Date;\n readonly midnight: Date;\n readonly lastWeek: Date;\n readonly nextWeek: Date;\n readonly lastFortnight: Date;\n readonly nextFortnight: Date;\n fromPhrase(phrase: unknown): Date;\n fromPhraseSafe(phrase: unknown): Date;\n make(offset: number, unit: StandardTimeUnit | string): Date;\n}\n\nclass DatesFacade implements DatesObject {\n readonly iso: IsoDateFactory;\n readonly fmt: FormattedDateFactory;\n\n constructor(private readonly factory: DateFactory) {\n this.iso = new IsoDateFactory(factory);\n this.fmt = new FormattedDateFactory(factory);\n }\n\n get now(): Date {\n return this.fromShortcut(\"now\");\n }\n\n get beforeYesterday(): Date {\n return this.fromShortcut(\"beforeYesterday\");\n }\n\n get yesterday(): Date {\n return this.fromShortcut(\"yesterday\");\n }\n\n get today(): Date {\n return this.fromShortcut(\"today\");\n }\n\n get tomorrow(): Date {\n return this.fromShortcut(\"tomorrow\");\n }\n\n get afterTomorrow(): Date {\n return this.fromShortcut(\"afterTomorrow\");\n }\n\n get midnight(): Date {\n return this.fromShortcut(\"midnight\");\n }\n\n get lastWeek(): Date {\n return this.fromShortcut(\"lastWeek\");\n }\n\n get nextWeek(): Date {\n return this.fromShortcut(\"nextWeek\");\n }\n\n get lastFortnight(): Date {\n return this.fromShortcut(\"lastFortnight\");\n }\n\n get nextFortnight(): Date {\n return this.fromShortcut(\"nextFortnight\");\n }\n\n fromPhrase(phrase: unknown): Date {\n return this.factory.fromPhrase(phrase);\n }\n\n fromPhraseSafe(phrase: unknown): Date {\n return this.factory.fromPhraseSafe(phrase);\n }\n\n make(offset: number, unit: StandardTimeUnit | string): Date {\n return this.factory.make(offset, unit);\n }\n\n private fromShortcut(shortcut: DateShortcut): Date {\n return this.factory.find(shortcut);\n }\n}\n\nexport function createDates(options: DatesOptions = {}): DatesObject {\n const factory = options.factory ?? new DateFactory(options);\n return new DatesFacade(factory);\n}\n\nexport const Dates = createDates();\nexport type { DateFactoryOptions };\n","import { AutomationError } from \"@autometa/errors\";\nimport { assertKey } from \"@autometa/asserters\";\nimport { normalizeToken } from \"../shared/phrases.js\";\n\nexport type TimeDiffFn = (start: Date, end: Date) => number;\n\nconst SUPPORTED_METHODS = [\n \"minutes\",\n \"seconds\",\n \"millis\",\n \"days\",\n \"hours\",\n \"weeks\",\n] as const;\ntype MethodName = (typeof SUPPORTED_METHODS)[number];\n\nfunction toTime(date: Date): number {\n return new Date(date).getTime();\n}\n\nexport class TimeDiff {\n minutes(start: Date, end: Date): number {\n return this.millis(start, end) / 60_000;\n }\n\n seconds(start: Date, end: Date): number {\n return this.millis(start, end) / 1_000;\n }\n\n millis(start: Date, end: Date): number {\n const distance = Math.abs(toTime(end) - toTime(start));\n return Math.round(distance);\n }\n\n days(start: Date, end: Date): number {\n return this.millis(start, end) / 86_400_000;\n }\n\n hours(start: Date, end: Date): number {\n return this.millis(start, end) / 3_600_000;\n }\n\n weeks(start: Date, end: Date): number {\n return this.millis(start, end) / 604_800_000;\n }\n\n fromPhrase(phrase: unknown): TimeDiffFn {\n if (typeof phrase !== \"string\") {\n throw new AutomationError(\n `TimeDiff.fromPhrase expects a string, received '${typeof phrase}'.`\n );\n }\n\n const key = normalizeToken(phrase);\n if (!this.hasMethod(key)) {\n throw new AutomationError(\n `Unsupported diff unit '${phrase}'. Expected one of ${this.supportedMethods().join(\", \")}.`\n );\n }\n\n assertKey(this, key as MethodName, \"TimeDiff.fromPhrase\");\n const method = this[key as MethodName];\n if (typeof method !== \"function\") {\n throw new AutomationError(`Diff method '${key}' is not callable.`);\n }\n return (method as TimeDiffFn).bind(this);\n }\n\n private hasMethod(name: string): boolean {\n return SUPPORTED_METHODS.includes(name as MethodName);\n }\n\n private supportedMethods(): MethodName[] {\n return [...SUPPORTED_METHODS];\n }\n}\n","import { TimeDiff, type TimeDiffFn } from \"./time-diff.js\";\n\nexport interface TimeFactory {\n readonly diff: TimeDiff;\n}\n\nclass TimeFacade implements TimeFactory {\n readonly diff: TimeDiff;\n\n constructor(diff: TimeDiff) {\n this.diff = diff;\n }\n}\n\nexport function createTime(): TimeFactory {\n return new TimeFacade(new TimeDiff());\n}\n\nexport const Time = createTime();\nexport { TimeDiff, type TimeDiffFn };\n"]} |
| export declare function toCamelKey(phrase: string): string; | ||
| export declare function normalizeToken(phrase: string): string; |
| export type TimeDiffFn = (start: Date, end: Date) => number; | ||
| export declare class TimeDiff { | ||
| minutes(start: Date, end: Date): number; | ||
| seconds(start: Date, end: Date): number; | ||
| millis(start: Date, end: Date): number; | ||
| days(start: Date, end: Date): number; | ||
| hours(start: Date, end: Date): number; | ||
| weeks(start: Date, end: Date): number; | ||
| fromPhrase(phrase: unknown): TimeDiffFn; | ||
| private hasMethod; | ||
| private supportedMethods; | ||
| } |
| import { TimeDiff, type TimeDiffFn } from "./time-diff.js"; | ||
| export interface TimeFactory { | ||
| readonly diff: TimeDiff; | ||
| } | ||
| export declare function createTime(): TimeFactory; | ||
| export declare const Time: TimeFactory; | ||
| export { TimeDiff, type TimeDiffFn }; |
+6
-219
@@ -1,219 +0,6 @@ | ||
| import { TimeUnit } from '@autometa/phrases'; | ||
| type TimeShortcut = "now" | "beforeYesterday" | "yesterday" | "today" | "tomorrow" | "afterTomorrow" | "midnight" | "lastWeek" | "nextWeek" | "lastFortnight" | "nextFortnight"; | ||
| declare class DateFactory { | ||
| #private; | ||
| phraseMap: Map<TimeShortcut, () => Date>; | ||
| find(name: TimeShortcut): Date; | ||
| fromPhraseSafe(phrase: string): Date | undefined; | ||
| fromPhrase(phrase: string): Date; | ||
| make(timeOffset: number, timeunit: TimeUnit): Date; | ||
| } | ||
| declare class IsoDateFactory { | ||
| readonly dateFactory: DateFactory; | ||
| constructor(dateFactory: DateFactory); | ||
| phraseMap: Map<string, string>; | ||
| make(daysOffset: number, timeunit: TimeUnit): string; | ||
| /** | ||
| * Attempts to parse a phrase into a date. | ||
| * @param phrase | ||
| * @returns | ||
| */ | ||
| fromPhrase(phrase: string): string; | ||
| /** | ||
| * Returns the date and time of the day before yesterday | ||
| */ | ||
| get beforeYesterday(): string | undefined; | ||
| /** | ||
| * Returns the date and time of yesterday | ||
| */ | ||
| get yesterday(): string | undefined; | ||
| /** | ||
| * Returns the date and time of today | ||
| */ | ||
| get today(): string | undefined; | ||
| /** | ||
| * Returns the date and time of tomorrow | ||
| */ | ||
| get tomorrow(): string | undefined; | ||
| /** | ||
| * Returns the date and time of the day after tomorrow | ||
| */ | ||
| get afterTomorrow(): string | undefined; | ||
| /** | ||
| * Returns the date and time of midnight today | ||
| */ | ||
| get midnight(): string | undefined; | ||
| /** | ||
| * Returns the date and time of today 1 week ago | ||
| */ | ||
| get lastWeek(): string | undefined; | ||
| /** | ||
| * Returns the date and time of today 1 week from now | ||
| */ | ||
| get nextWeek(): string | undefined; | ||
| get lastFortnight(): string | undefined; | ||
| /** | ||
| * Returns the date and time of today 1 fortnight from now | ||
| */ | ||
| get nextFortnight(): string | undefined; | ||
| } | ||
| declare class FmtDateFactory { | ||
| readonly dateFactory: DateFactory; | ||
| constructor(dateFactory: DateFactory); | ||
| phraseMap: Map<string, string>; | ||
| make(daysOffset: number, timeunit: TimeUnit): string; | ||
| /** | ||
| * Attempts to parse a phrase into a date. | ||
| * @param phrase | ||
| * @returns | ||
| */ | ||
| fromPhrase(phrase: string): string; | ||
| /** | ||
| * Returns the date and time of the day before yesterday | ||
| */ | ||
| get beforeYesterday(): string | undefined; | ||
| /** | ||
| * Returns the date and time of yesterday | ||
| */ | ||
| get yesterday(): string | undefined; | ||
| /** | ||
| * Returns the date and time of today | ||
| */ | ||
| get today(): string | undefined; | ||
| /** | ||
| * Returns the date and time of tomorrow | ||
| */ | ||
| get tomorrow(): string | undefined; | ||
| /** | ||
| * Returns the date and time of the day after tomorrow | ||
| */ | ||
| get afterTomorrow(): string | undefined; | ||
| /** | ||
| * Returns the date and time of midnight today | ||
| */ | ||
| get midnight(): string | undefined; | ||
| /** | ||
| * Returns the date and time of today 1 week ago | ||
| */ | ||
| get lastWeek(): string | undefined; | ||
| /** | ||
| * Returns the date and time of today 1 week from now | ||
| */ | ||
| get nextWeek(): string | undefined; | ||
| /** | ||
| * Returns the date and time of today 1 fortnight ago | ||
| */ | ||
| get lastFortnight(): string | undefined; | ||
| /** | ||
| * Returns the date and time of today 1 fortnight from now | ||
| */ | ||
| get nextFortnight(): string | undefined; | ||
| } | ||
| declare class DatesObject { | ||
| #private; | ||
| /** | ||
| * Switches to the ISO factory, which offers an identical interface | ||
| * but returns ISO strings instead of Date objects. | ||
| * | ||
| * Example: `2020-01-01T00:00:00.000Z` | ||
| */ | ||
| get iso(): IsoDateFactory; | ||
| /** | ||
| * Switches to the formatted factory, which offers an identical interface | ||
| * but returns formatted strings instead of Date objects. | ||
| * | ||
| * Example: `2020-01-01` | ||
| */ | ||
| get fmt(): FmtDateFactory; | ||
| /** | ||
| * Returns the current date and time. | ||
| */ | ||
| get now(): Date; | ||
| /** | ||
| * Returns the date and time of the day before yesterday | ||
| */ | ||
| get beforeYesterday(): Date; | ||
| /** | ||
| * Returns the date and time of yesterday | ||
| */ | ||
| get yesterday(): Date; | ||
| /** | ||
| * Returns the date and time of today | ||
| */ | ||
| get today(): Date; | ||
| /** | ||
| * Returns the date and time of tomorrow | ||
| */ | ||
| get tomorrow(): Date; | ||
| /** | ||
| * Returns the date and time of the day after tomorrow | ||
| */ | ||
| get afterTomorrow(): Date; | ||
| /** | ||
| * Returns the date and time of midnight today | ||
| */ | ||
| get midnight(): Date; | ||
| /** | ||
| * Returns the date and time of today 1 week ago | ||
| */ | ||
| get lastWeek(): Date; | ||
| /** | ||
| * Returns the date and time of today 1 week from now | ||
| */ | ||
| get nextWeek(): Date; | ||
| /** | ||
| * Returns the date and time of today 2 weeks ago | ||
| */ | ||
| get lastFortnight(): Date; | ||
| /** | ||
| * Returns the date and time of today 2 weeks from now | ||
| */ | ||
| get nextFortnight(): Date; | ||
| /** | ||
| * Attempts to parse a phrase into a date. | ||
| * @param phrase | ||
| * @returns | ||
| */ | ||
| fromPhrase(phrase: string): Date; | ||
| /** | ||
| * Attempts to parse a phrase into a date. | ||
| * If the phrase is invalid, it will return an invalid date instead of throwing. | ||
| * @param phrase | ||
| * @returns | ||
| */ | ||
| fromPhraseSafe(phrase: string): Date | undefined; | ||
| make(timeOffset: number, timeUnit: TimeUnit): Date; | ||
| } | ||
| /** | ||
| * Date utility option to easily generate common | ||
| * dates around the current date, like 'today', 'midnight', | ||
| * 'tomorrow', 'nextWeek', etc. | ||
| * | ||
| * The Dates utility also supports certain language phrases | ||
| * that might be natural in Cucumber's gherkin syntax, like | ||
| * 'next week', 'last week', 'next fortnight', etc. as well | ||
| * as more dynamic phrases like `1 day ago`, `2 weeks from now`, | ||
| */ | ||
| declare const Dates: DatesObject; | ||
| type TimeDiffFn = (date1: Date, date2: Date) => number; | ||
| declare class TimeDiff { | ||
| minutes(date1: Date, date2: Date): number; | ||
| seconds(date1: Date, date2: Date): number; | ||
| millis(date1: Date, date2: Date): number; | ||
| days(date1: Date, date2: Date): number; | ||
| hours(date1: Date, date2: Date): number; | ||
| weeks(date1: Date, date2: Date): number; | ||
| fromPhrase(phrase: string): TimeDiffFn; | ||
| } | ||
| declare class TimeObject { | ||
| #private; | ||
| get diff(): TimeDiff; | ||
| } | ||
| declare const Time: TimeObject; | ||
| export { DateFactory, Dates, FmtDateFactory, IsoDateFactory, Time, TimeDiff, TimeObject }; | ||
| export type { Clock } from "./dates/clock.js"; | ||
| export { createDates, Dates, type DatesOptions, type DatesObject, } from "./dates/object.js"; | ||
| export { DateFactory, type DateFactoryOptions, } from "./dates/date-factory.js"; | ||
| export { IsoDateFactory, type IsoDateFactoryOptions, } from "./dates/iso-date-factory.js"; | ||
| export { FormattedDateFactory, type FormattedDateFactoryOptions, } from "./dates/formatted-date-factory.js"; | ||
| export { Time, createTime, TimeDiff, type TimeDiffFn, } from "./time/time.js"; |
+342
-474
@@ -1,605 +0,473 @@ | ||
| "use strict"; | ||
| var __defProp = Object.defineProperty; | ||
| var __getOwnPropDesc = Object.getOwnPropertyDescriptor; | ||
| var __getOwnPropNames = Object.getOwnPropertyNames; | ||
| var __hasOwnProp = Object.prototype.hasOwnProperty; | ||
| var __export = (target, all) => { | ||
| for (var name in all) | ||
| __defProp(target, name, { get: all[name], enumerable: true }); | ||
| }; | ||
| var __copyProps = (to, from, except, desc) => { | ||
| if (from && typeof from === "object" || typeof from === "function") { | ||
| for (let key of __getOwnPropNames(from)) | ||
| if (!__hasOwnProp.call(to, key) && key !== except) | ||
| __defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable }); | ||
| } | ||
| return to; | ||
| }; | ||
| var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod); | ||
| var __accessCheck = (obj, member, msg) => { | ||
| if (!member.has(obj)) | ||
| throw TypeError("Cannot " + msg); | ||
| }; | ||
| var __privateGet = (obj, member, getter) => { | ||
| __accessCheck(obj, member, "read from private field"); | ||
| return getter ? getter.call(obj) : member.get(obj); | ||
| }; | ||
| var __privateAdd = (obj, member, value) => { | ||
| if (member.has(obj)) | ||
| throw TypeError("Cannot add the same private member more than once"); | ||
| member instanceof WeakSet ? member.add(obj) : member.set(obj, value); | ||
| }; | ||
| var __privateMethod = (obj, member, method) => { | ||
| __accessCheck(obj, member, "access private method"); | ||
| return method; | ||
| }; | ||
| import { AutomationError } from '@autometa/errors'; | ||
| import { isValidDate, isValidISODateString, isValidTime, isValidYearMonth } from 'iso-datestring-validator'; | ||
| import { assertKey } from '@autometa/asserters'; | ||
| // src/index.ts | ||
| var src_exports = {}; | ||
| __export(src_exports, { | ||
| DateFactory: () => DateFactory, | ||
| Dates: () => Dates, | ||
| FmtDateFactory: () => FmtDateFactory, | ||
| IsoDateFactory: () => IsoDateFactory, | ||
| Time: () => Time, | ||
| TimeDiff: () => TimeDiff, | ||
| TimeObject: () => TimeObject | ||
| }); | ||
| module.exports = __toCommonJS(src_exports); | ||
| // src/dates/date-factory.ts | ||
| var import_phrases = require("@autometa/phrases"); | ||
| // src/dates/midnight.ts | ||
| function midnight() { | ||
| const date = /* @__PURE__ */ new Date(); | ||
| date.setDate(date.getDate() + 1); | ||
| date.setHours(0, 0, 0, 0); | ||
| return date; | ||
| // src/dates/clock.ts | ||
| var systemClock = { | ||
| now: () => /* @__PURE__ */ new Date() | ||
| }; | ||
| function cloneDate(date) { | ||
| return new Date(date.getTime()); | ||
| } | ||
| var UNIT_ALIASES = { | ||
| millisecond: { unit: "milliseconds", scale: 1 }, | ||
| milliseconds: { unit: "milliseconds", scale: 1 }, | ||
| ms: { unit: "milliseconds", scale: 1 }, | ||
| second: { unit: "seconds", scale: 1 }, | ||
| seconds: { unit: "seconds", scale: 1 }, | ||
| sec: { unit: "seconds", scale: 1 }, | ||
| secs: { unit: "seconds", scale: 1 }, | ||
| minute: { unit: "minutes", scale: 1 }, | ||
| minutes: { unit: "minutes", scale: 1 }, | ||
| min: { unit: "minutes", scale: 1 }, | ||
| mins: { unit: "minutes", scale: 1 }, | ||
| hour: { unit: "hours", scale: 1 }, | ||
| hours: { unit: "hours", scale: 1 }, | ||
| hr: { unit: "hours", scale: 1 }, | ||
| hrs: { unit: "hours", scale: 1 }, | ||
| day: { unit: "days", scale: 1 }, | ||
| days: { unit: "days", scale: 1 }, | ||
| week: { unit: "weeks", scale: 1 }, | ||
| weeks: { unit: "weeks", scale: 1 }, | ||
| fortnight: { unit: "days", scale: 14 }, | ||
| fortnights: { unit: "days", scale: 14 }, | ||
| month: { unit: "months", scale: 1 }, | ||
| months: { unit: "months", scale: 1 }, | ||
| year: { unit: "years", scale: 1 }, | ||
| years: { unit: "years", scale: 1 } | ||
| }; | ||
| function resolveTimeUnit(input) { | ||
| const key = input.trim().toLowerCase(); | ||
| const resolved = UNIT_ALIASES[key]; | ||
| if (!resolved) { | ||
| throw new AutomationError( | ||
| `Unsupported time unit '${input}'. Expected one of ${Object.keys(UNIT_ALIASES).sort().join(", ")}.` | ||
| ); | ||
| } | ||
| return resolved; | ||
| } | ||
| // src/dates/date-factory.ts | ||
| var import_errors = require("@autometa/errors"); | ||
| var import_asserters = require("@autometa/asserters"); | ||
| var import_iso_datestring_validator = require("iso-datestring-validator"); | ||
| function isTimeShortcut(text) { | ||
| const converted = (0, import_phrases.convertPhrase)(text, import_phrases.camel); | ||
| const includes = [ | ||
| "now", | ||
| "beforeYesterday", | ||
| "yesterday", | ||
| "today", | ||
| "tomorrow", | ||
| "afterTomorrow", | ||
| "midnight", | ||
| "lastWeek", | ||
| "nextWeek", | ||
| "lastFortnight", | ||
| "nextFortnight" | ||
| ].includes(converted); | ||
| if (!includes) { | ||
| return false; | ||
| // src/shared/phrases.ts | ||
| var SEPARATORS = /[\s_-]+/g; | ||
| function capitalize(word) { | ||
| return word.charAt(0).toUpperCase() + word.slice(1); | ||
| } | ||
| function splitWords(phrase) { | ||
| return phrase.trim().split(SEPARATORS).filter(Boolean).map((word) => word.toLowerCase()); | ||
| } | ||
| function toCamelKey(phrase) { | ||
| const words = splitWords(phrase); | ||
| if (words.length === 0) { | ||
| return ""; | ||
| } | ||
| return true; | ||
| const [first, ...rest] = words; | ||
| return first + rest.map(capitalize).join(""); | ||
| } | ||
| var _extractTimeFromPhrase, extractTimeFromPhrase_fn, _extractFutureFromPhrase, extractFutureFromPhrase_fn, _extractPastFromPhrase, extractPastFromPhrase_fn, _addYears, addYears_fn, _addMonths, addMonths_fn, _addWeeks, addWeeks_fn, _addDays, addDays_fn, _addSeconds, addSeconds_fn, _addMilliseconds, addMilliseconds_fn, _addHours, addHours_fn, _addMinutes, addMinutes_fn; | ||
| function normalizeToken(phrase) { | ||
| return splitWords(phrase).join(""); | ||
| } | ||
| // src/dates/date-factory.ts | ||
| var SHORTCUT_LOOKUP = /* @__PURE__ */ new Set([ | ||
| "now", | ||
| "beforeYesterday", | ||
| "yesterday", | ||
| "today", | ||
| "tomorrow", | ||
| "afterTomorrow", | ||
| "midnight", | ||
| "lastWeek", | ||
| "nextWeek", | ||
| "lastFortnight", | ||
| "nextFortnight" | ||
| ]); | ||
| var FUTURE_PATTERN = /^(\d+)\s+([A-Za-z\s]+?)\s+from\s+now$/i; | ||
| var PAST_PATTERN = /^(\d+)\s+([A-Za-z\s]+?)\s+ago$/i; | ||
| function invalidDate() { | ||
| return new Date(Number.NaN); | ||
| } | ||
| function isDateShortcut(value) { | ||
| return SHORTCUT_LOOKUP.has(value); | ||
| } | ||
| var DateFactory = class { | ||
| constructor() { | ||
| __privateAdd(this, _extractTimeFromPhrase); | ||
| __privateAdd(this, _extractFutureFromPhrase); | ||
| __privateAdd(this, _extractPastFromPhrase); | ||
| __privateAdd(this, _addYears); | ||
| __privateAdd(this, _addMonths); | ||
| __privateAdd(this, _addWeeks); | ||
| __privateAdd(this, _addDays); | ||
| __privateAdd(this, _addSeconds); | ||
| __privateAdd(this, _addMilliseconds); | ||
| __privateAdd(this, _addHours); | ||
| __privateAdd(this, _addMinutes); | ||
| this.phraseMap = /* @__PURE__ */ new Map([ | ||
| ["now", () => this.make(0, "days")], | ||
| ["beforeYesterday", () => this.make(-2, "days")], | ||
| ["yesterday", () => this.make(-1, "days")], | ||
| ["today", () => this.make(0, "days")], | ||
| ["tomorrow", () => this.make(1, "days")], | ||
| ["afterTomorrow", () => this.make(2, "days")], | ||
| ["nextWeek", () => this.make(7, "days")], | ||
| ["lastWeek", () => this.make(-7, "days")], | ||
| ["nextFortnight", () => this.make(14, "days")], | ||
| ["lastFortnight", () => this.make(-14, "days")], | ||
| ["midnight", midnight] | ||
| ]); | ||
| constructor(options = {}) { | ||
| this.clock = options.clock ?? systemClock; | ||
| } | ||
| // eslint-disable-next-line @typescript-eslint/ban-types | ||
| find(name) { | ||
| const result = this.phraseMap.get(name); | ||
| if (result) { | ||
| return result(); | ||
| find(shortcut) { | ||
| switch (shortcut) { | ||
| case "now": | ||
| return this.currentDate(); | ||
| case "beforeYesterday": | ||
| return this.make(-2, "days"); | ||
| case "yesterday": | ||
| return this.make(-1, "days"); | ||
| case "today": | ||
| return this.make(0, "days"); | ||
| case "tomorrow": | ||
| return this.make(1, "days"); | ||
| case "afterTomorrow": | ||
| return this.make(2, "days"); | ||
| case "midnight": | ||
| return this.midnight(); | ||
| case "lastWeek": | ||
| return this.make(-1, "weeks"); | ||
| case "nextWeek": | ||
| return this.make(1, "weeks"); | ||
| case "lastFortnight": | ||
| return this.make(-14, "days"); | ||
| case "nextFortnight": | ||
| return this.make(14, "days"); | ||
| default: | ||
| throw new AutomationError( | ||
| `Unsupported date shortcut '${shortcut}'.` | ||
| ); | ||
| } | ||
| (0, import_errors.raise)( | ||
| `Could not find date shortcut ${name}. Please use a valid date shortcut from the following list: ${Array.from( | ||
| this.phraseMap.keys() | ||
| ).join(", ")}` | ||
| ); | ||
| } | ||
| fromPhraseSafe(phrase) { | ||
| const name = (0, import_phrases.convertPhrase)(phrase, import_phrases.camel); | ||
| if (isTimeShortcut(name)) { | ||
| if (this.phraseMap.has(name)) { | ||
| return this.phraseMap.get(name)?.call(this); | ||
| } | ||
| if (typeof phrase !== "string") { | ||
| return invalidDate(); | ||
| } | ||
| const matchDay = __privateMethod(this, _extractTimeFromPhrase, extractTimeFromPhrase_fn).call(this, phrase); | ||
| if (matchDay) { | ||
| return matchDay; | ||
| const trimmed = phrase.trim(); | ||
| if (trimmed.length === 0) { | ||
| return invalidDate(); | ||
| } | ||
| const first = (0, import_iso_datestring_validator.isValidDate)(phrase); | ||
| const second = (0, import_iso_datestring_validator.isValidISODateString)(phrase); | ||
| const third = (0, import_iso_datestring_validator.isValidTime)(phrase); | ||
| const fourth = (0, import_iso_datestring_validator.isValidYearMonth)(phrase); | ||
| if (!first && !second && !third && !fourth) { | ||
| return /* @__PURE__ */ new Date("null"); | ||
| const shortcutCandidate = toCamelKey(trimmed); | ||
| if (isDateShortcut(shortcutCandidate)) { | ||
| return this.find(shortcutCandidate); | ||
| } | ||
| const parsed = new Date(phrase); | ||
| if (isNaN(parsed.getTime())) { | ||
| return new Date(Date.parse(phrase)); | ||
| const relative = this.extractRelative(trimmed); | ||
| if (relative) { | ||
| return this.make(relative.offset, relative.unit); | ||
| } | ||
| return parsed; | ||
| if (this.isDateLike(trimmed)) { | ||
| return this.parseDate(trimmed); | ||
| } | ||
| return invalidDate(); | ||
| } | ||
| fromPhrase(phrase) { | ||
| const result = this.fromPhraseSafe(phrase); | ||
| if (result) { | ||
| return result; | ||
| if (Number.isNaN(result.getTime())) { | ||
| throw new AutomationError( | ||
| `Could not parse date from phrase '${String(phrase)}'. Valid shortcuts are: ${[...SHORTCUT_LOOKUP].join(", ")}.` | ||
| ); | ||
| } | ||
| (0, import_errors.raise)( | ||
| `Could not parse date from phrase ${phrase}. Please use a valid date string or a phrase from the following list: ${Array.from( | ||
| this.phraseMap.keys() | ||
| ).join(", ")}` | ||
| ); | ||
| return result; | ||
| } | ||
| make(timeOffset, timeunit) { | ||
| const unit = timeunit.endsWith("s") ? timeunit : `${timeunit}s`; | ||
| make(timeOffset, timeUnit) { | ||
| if (!Number.isFinite(timeOffset)) { | ||
| throw new AutomationError( | ||
| `Time offset must be finite. Received '${timeOffset}'.` | ||
| ); | ||
| } | ||
| const { unit, scale } = resolveTimeUnit(String(timeUnit)); | ||
| const offset = timeOffset * scale; | ||
| const date = this.currentDate(); | ||
| switch (unit) { | ||
| case "years": | ||
| return __privateMethod(this, _addYears, addYears_fn).call(this, timeOffset); | ||
| date.setFullYear(date.getFullYear() + offset); | ||
| break; | ||
| case "months": | ||
| return __privateMethod(this, _addMonths, addMonths_fn).call(this, timeOffset); | ||
| date.setMonth(date.getMonth() + offset); | ||
| break; | ||
| case "weeks": | ||
| return __privateMethod(this, _addWeeks, addWeeks_fn).call(this, timeOffset); | ||
| date.setDate(date.getDate() + offset * 7); | ||
| break; | ||
| case "days": | ||
| return __privateMethod(this, _addDays, addDays_fn).call(this, timeOffset); | ||
| date.setDate(date.getDate() + offset); | ||
| break; | ||
| case "hours": | ||
| date.setHours(date.getHours() + offset); | ||
| break; | ||
| case "minutes": | ||
| date.setMinutes(date.getMinutes() + offset); | ||
| break; | ||
| case "seconds": | ||
| return __privateMethod(this, _addSeconds, addSeconds_fn).call(this, timeOffset); | ||
| date.setSeconds(date.getSeconds() + offset); | ||
| break; | ||
| case "milliseconds": | ||
| return __privateMethod(this, _addMilliseconds, addMilliseconds_fn).call(this, timeOffset); | ||
| case "hours": | ||
| return __privateMethod(this, _addHours, addHours_fn).call(this, timeOffset); | ||
| case "minutes": | ||
| return __privateMethod(this, _addMinutes, addMinutes_fn).call(this, timeOffset); | ||
| date.setMilliseconds(date.getMilliseconds() + offset); | ||
| break; | ||
| default: | ||
| throw new import_errors.AutomationError( | ||
| `Invalid timeunit ${timeunit}, options are 'days', 'seconds', 'milliseconds', 'hours', 'minutes'. Non plural equivalents such as 'day' or 'week' are also accepted.` | ||
| ); | ||
| throw new AutomationError(`Unsupported time unit '${unit}'.`); | ||
| } | ||
| return date; | ||
| } | ||
| }; | ||
| _extractTimeFromPhrase = new WeakSet(); | ||
| extractTimeFromPhrase_fn = function(phrase) { | ||
| return __privateMethod(this, _extractFutureFromPhrase, extractFutureFromPhrase_fn).call(this, phrase) ?? __privateMethod(this, _extractPastFromPhrase, extractPastFromPhrase_fn).call(this, phrase); | ||
| }; | ||
| _extractFutureFromPhrase = new WeakSet(); | ||
| extractFutureFromPhrase_fn = function(phrase) { | ||
| const pastPattern = /^(\d+) (.*)s? from now?/; | ||
| const pastMatch = pastPattern.exec(phrase); | ||
| if ((0, import_asserters.ConfirmDefined)(pastMatch) && (0, import_asserters.ConfirmLengthAtLeast)(pastMatch, 3)) { | ||
| const [_, value, unit] = pastMatch; | ||
| const timeunit = (0, import_phrases.convertPhrase)(unit, import_phrases.collapse); | ||
| return this.make(Number(value), timeunit); | ||
| currentDate() { | ||
| return cloneDate(this.clock.now()); | ||
| } | ||
| }; | ||
| _extractPastFromPhrase = new WeakSet(); | ||
| extractPastFromPhrase_fn = function(phrase) { | ||
| const pastPattern = /^(\d+) (.*)(s)? ago?/gm; | ||
| const pastMatch = pastPattern.exec(phrase); | ||
| if ((0, import_asserters.ConfirmDefined)(pastMatch) && (0, import_asserters.ConfirmLengthAtLeast)(pastMatch, 3)) { | ||
| const [_, value, unit] = pastMatch; | ||
| const timeunit = (0, import_phrases.convertPhrase)(unit, import_phrases.camel); | ||
| return this.make(-Number(value), timeunit); | ||
| midnight() { | ||
| const date = this.currentDate(); | ||
| date.setUTCDate(date.getUTCDate() + 1); | ||
| date.setUTCHours(0, 0, 0, 0); | ||
| return date; | ||
| } | ||
| parseDate(value) { | ||
| const parsed = new Date(value); | ||
| if (!Number.isNaN(parsed.getTime())) { | ||
| return parsed; | ||
| } | ||
| return new Date(Date.parse(value)); | ||
| } | ||
| isDateLike(value) { | ||
| if (!Number.isNaN(new Date(value).getTime())) { | ||
| return true; | ||
| } | ||
| return isValidDate(value) || isValidISODateString(value) || isValidTime(value) || isValidYearMonth(value); | ||
| } | ||
| extractRelative(phrase) { | ||
| const futureMatch = FUTURE_PATTERN.exec(phrase); | ||
| if (futureMatch) { | ||
| return this.buildRelativeMatch(futureMatch, 1); | ||
| } | ||
| const pastMatch = PAST_PATTERN.exec(phrase); | ||
| if (pastMatch) { | ||
| return this.buildRelativeMatch(pastMatch, -1); | ||
| } | ||
| return void 0; | ||
| } | ||
| buildRelativeMatch(match, direction) { | ||
| const value = match[1]; | ||
| const unit = match[2]; | ||
| if (!value || !unit) { | ||
| return void 0; | ||
| } | ||
| const magnitude = Number.parseInt(value, 10); | ||
| if (!Number.isFinite(magnitude)) { | ||
| return void 0; | ||
| } | ||
| const convertedUnit = normalizeToken(unit); | ||
| const { unit: normalisedUnit, scale } = resolveTimeUnit(convertedUnit); | ||
| const offset = magnitude * scale * direction; | ||
| return { | ||
| offset, | ||
| unit: normalisedUnit | ||
| }; | ||
| } | ||
| }; | ||
| _addYears = new WeakSet(); | ||
| addYears_fn = function(yearsOffset) { | ||
| const date = /* @__PURE__ */ new Date(); | ||
| date.setFullYear(date.getFullYear() + yearsOffset); | ||
| return date; | ||
| }; | ||
| _addMonths = new WeakSet(); | ||
| addMonths_fn = function(monthOffset) { | ||
| const date = /* @__PURE__ */ new Date(); | ||
| date.setMonth(date.getMonth() + monthOffset); | ||
| return date; | ||
| }; | ||
| _addWeeks = new WeakSet(); | ||
| addWeeks_fn = function(weekOffset) { | ||
| const date = /* @__PURE__ */ new Date(); | ||
| date.setMonth(date.getMonth() + weekOffset / 4); | ||
| return date; | ||
| }; | ||
| _addDays = new WeakSet(); | ||
| addDays_fn = function(daysOffset) { | ||
| const date = /* @__PURE__ */ new Date(); | ||
| date.setDate(date.getDate() + daysOffset); | ||
| return date; | ||
| }; | ||
| _addSeconds = new WeakSet(); | ||
| addSeconds_fn = function(secondsOffset) { | ||
| const date = /* @__PURE__ */ new Date(); | ||
| date.setSeconds(date.getSeconds() + secondsOffset); | ||
| return date; | ||
| }; | ||
| _addMilliseconds = new WeakSet(); | ||
| addMilliseconds_fn = function(millisecondsOffset) { | ||
| const date = /* @__PURE__ */ new Date(); | ||
| date.setMilliseconds(date.getMilliseconds() + millisecondsOffset); | ||
| return date; | ||
| }; | ||
| _addHours = new WeakSet(); | ||
| addHours_fn = function(hoursOffset) { | ||
| const date = /* @__PURE__ */ new Date(); | ||
| date.setHours(date.getHours() + hoursOffset); | ||
| return date; | ||
| }; | ||
| _addMinutes = new WeakSet(); | ||
| addMinutes_fn = function(minutesOffset) { | ||
| const date = /* @__PURE__ */ new Date(); | ||
| date.setMinutes(date.getMinutes() + minutesOffset); | ||
| return date; | ||
| }; | ||
| // src/dates/iso-date-factory.ts | ||
| var IsoDateFactory = class { | ||
| constructor(dateFactory) { | ||
| // src/dates/formatted-date-factory.ts | ||
| var FormattedDateFactory = class { | ||
| constructor(dateFactory, options = {}) { | ||
| this.dateFactory = dateFactory; | ||
| this.phraseMap = /* @__PURE__ */ new Map([ | ||
| ["beforeYesterday", this.make(-2, "days")], | ||
| ["yesterday", this.make(-1, "days")], | ||
| ["today", this.make(0, "days")], | ||
| ["tomorrow", this.make(1, "days")], | ||
| ["afterTomorrow", this.make(2, "days")], | ||
| ["nextWeek", this.make(7, "days")], | ||
| ["lastWeek", this.make(-7, "days")], | ||
| ["nextFortnight", this.make(14, "days")], | ||
| ["lastFortnight", this.make(-14, "days")], | ||
| ["midnight", midnight().toISOString()] | ||
| ]); | ||
| this.format = options.formatter ?? ((date) => date.toISOString().substring(0, 10)); | ||
| } | ||
| make(daysOffset, timeunit) { | ||
| return this.dateFactory.make(daysOffset, timeunit).toISOString(); | ||
| make(offset, unit) { | ||
| return this.format(this.dateFactory.make(offset, unit)); | ||
| } | ||
| /** | ||
| * Attempts to parse a phrase into a date. | ||
| * @param phrase | ||
| * @returns | ||
| */ | ||
| fromPhrase(phrase) { | ||
| return this.dateFactory.fromPhrase(phrase)?.toISOString(); | ||
| return this.format(this.dateFactory.fromPhrase(phrase)); | ||
| } | ||
| /** | ||
| * Returns the date and time of the day before yesterday | ||
| */ | ||
| get beforeYesterday() { | ||
| return this.phraseMap.get("beforeYesterday"); | ||
| return this.fromShortcut("beforeYesterday"); | ||
| } | ||
| /** | ||
| * Returns the date and time of yesterday | ||
| */ | ||
| get yesterday() { | ||
| return this.phraseMap.get("yesterday"); | ||
| return this.fromShortcut("yesterday"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today | ||
| */ | ||
| get today() { | ||
| return this.phraseMap.get("today"); | ||
| return this.fromShortcut("today"); | ||
| } | ||
| /** | ||
| * Returns the date and time of tomorrow | ||
| */ | ||
| get tomorrow() { | ||
| return this.phraseMap.get("tomorrow"); | ||
| return this.fromShortcut("tomorrow"); | ||
| } | ||
| /** | ||
| * Returns the date and time of the day after tomorrow | ||
| */ | ||
| get afterTomorrow() { | ||
| return this.phraseMap.get("afterTomorrow"); | ||
| return this.fromShortcut("afterTomorrow"); | ||
| } | ||
| /** | ||
| * Returns the date and time of midnight today | ||
| */ | ||
| get midnight() { | ||
| return this.phraseMap.get("midnight"); | ||
| return this.fromShortcut("midnight"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today 1 week ago | ||
| */ | ||
| get lastWeek() { | ||
| return this.phraseMap.get("lastWeek"); | ||
| return this.fromShortcut("lastWeek"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today 1 week from now | ||
| */ | ||
| get nextWeek() { | ||
| return this.phraseMap.get("nextWeek"); | ||
| return this.fromShortcut("nextWeek"); | ||
| } | ||
| get lastFortnight() { | ||
| return this.phraseMap.get("lastFortnight"); | ||
| return this.fromShortcut("lastFortnight"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today 1 fortnight from now | ||
| */ | ||
| get nextFortnight() { | ||
| return this.phraseMap.get("nextFortnight"); | ||
| return this.fromShortcut("nextFortnight"); | ||
| } | ||
| fromShortcut(shortcut) { | ||
| return this.format(this.dateFactory.find(shortcut)); | ||
| } | ||
| }; | ||
| // src/dates/formatted-date-factory.ts | ||
| var FmtDateFactory = class { | ||
| constructor(dateFactory) { | ||
| // src/dates/iso-date-factory.ts | ||
| var IsoDateFactory = class { | ||
| constructor(dateFactory, options = {}) { | ||
| this.dateFactory = dateFactory; | ||
| this.phraseMap = /* @__PURE__ */ new Map([ | ||
| ["beforeYesterday", this.make(-2, "days")], | ||
| ["yesterday", this.make(-1, "days")], | ||
| ["today", this.make(0, "days")], | ||
| ["tomorrow", this.make(1, "days")], | ||
| ["afterTomorrow", this.make(2, "days")], | ||
| ["nextWeek", this.make(7, "days")], | ||
| ["lastWeek", this.make(-7, "days")], | ||
| ["nextFortnight", this.make(14, "days")], | ||
| ["lastFortnight", this.make(-14, "days")], | ||
| ["midnight", midnight().toISOString()] | ||
| ]); | ||
| this.serialise = options.serializer ?? ((date) => date.toISOString()); | ||
| } | ||
| make(daysOffset, timeunit) { | ||
| return this.dateFactory.make(daysOffset, timeunit).toISOString().split("T")[0]; | ||
| make(offset, unit) { | ||
| return this.serialise(this.dateFactory.make(offset, unit)); | ||
| } | ||
| /** | ||
| * Attempts to parse a phrase into a date. | ||
| * @param phrase | ||
| * @returns | ||
| */ | ||
| fromPhrase(phrase) { | ||
| return this.dateFactory.fromPhrase(phrase)?.toISOString().split("T")[0]; | ||
| return this.serialise(this.dateFactory.fromPhrase(phrase)); | ||
| } | ||
| /** | ||
| * Returns the date and time of the day before yesterday | ||
| */ | ||
| get beforeYesterday() { | ||
| return this.phraseMap.get("beforeYesterday"); | ||
| return this.fromShortcut("beforeYesterday"); | ||
| } | ||
| /** | ||
| * Returns the date and time of yesterday | ||
| */ | ||
| get yesterday() { | ||
| return this.phraseMap.get("yesterday"); | ||
| return this.fromShortcut("yesterday"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today | ||
| */ | ||
| get today() { | ||
| return this.phraseMap.get("today"); | ||
| return this.fromShortcut("today"); | ||
| } | ||
| /** | ||
| * Returns the date and time of tomorrow | ||
| */ | ||
| get tomorrow() { | ||
| return this.phraseMap.get("tomorrow"); | ||
| return this.fromShortcut("tomorrow"); | ||
| } | ||
| /** | ||
| * Returns the date and time of the day after tomorrow | ||
| */ | ||
| get afterTomorrow() { | ||
| return this.phraseMap.get("afterTomorrow"); | ||
| return this.fromShortcut("afterTomorrow"); | ||
| } | ||
| /** | ||
| * Returns the date and time of midnight today | ||
| */ | ||
| get midnight() { | ||
| return this.phraseMap.get("midnight"); | ||
| return this.fromShortcut("midnight"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today 1 week ago | ||
| */ | ||
| get lastWeek() { | ||
| return this.phraseMap.get("lastWeek"); | ||
| return this.fromShortcut("lastWeek"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today 1 week from now | ||
| */ | ||
| get nextWeek() { | ||
| return this.phraseMap.get("nextWeek"); | ||
| return this.fromShortcut("nextWeek"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today 1 fortnight ago | ||
| */ | ||
| get lastFortnight() { | ||
| return this.phraseMap.get("lastFortnight"); | ||
| return this.fromShortcut("lastFortnight"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today 1 fortnight from now | ||
| */ | ||
| get nextFortnight() { | ||
| return this.phraseMap.get("nextFortnight"); | ||
| return this.fromShortcut("nextFortnight"); | ||
| } | ||
| fromShortcut(shortcut) { | ||
| return this.serialise(this.dateFactory.find(shortcut)); | ||
| } | ||
| }; | ||
| // src/dates/dates.ts | ||
| var _factory, _iso, _fmt; | ||
| var DatesObject = class { | ||
| constructor() { | ||
| __privateAdd(this, _factory, new DateFactory()); | ||
| __privateAdd(this, _iso, new IsoDateFactory(__privateGet(this, _factory))); | ||
| __privateAdd(this, _fmt, new FmtDateFactory(__privateGet(this, _factory))); | ||
| // src/dates/object.ts | ||
| var DatesFacade = class { | ||
| constructor(factory) { | ||
| this.factory = factory; | ||
| this.iso = new IsoDateFactory(factory); | ||
| this.fmt = new FormattedDateFactory(factory); | ||
| } | ||
| /** | ||
| * Switches to the ISO factory, which offers an identical interface | ||
| * but returns ISO strings instead of Date objects. | ||
| * | ||
| * Example: `2020-01-01T00:00:00.000Z` | ||
| */ | ||
| get iso() { | ||
| return __privateGet(this, _iso); | ||
| } | ||
| /** | ||
| * Switches to the formatted factory, which offers an identical interface | ||
| * but returns formatted strings instead of Date objects. | ||
| * | ||
| * Example: `2020-01-01` | ||
| */ | ||
| get fmt() { | ||
| return __privateGet(this, _fmt); | ||
| } | ||
| /** | ||
| * Returns the current date and time. | ||
| */ | ||
| get now() { | ||
| return __privateGet(this, _factory).find("now"); | ||
| return this.fromShortcut("now"); | ||
| } | ||
| /** | ||
| * Returns the date and time of the day before yesterday | ||
| */ | ||
| get beforeYesterday() { | ||
| return __privateGet(this, _factory).find("beforeYesterday"); | ||
| return this.fromShortcut("beforeYesterday"); | ||
| } | ||
| /** | ||
| * Returns the date and time of yesterday | ||
| */ | ||
| get yesterday() { | ||
| return __privateGet(this, _factory).find("yesterday"); | ||
| return this.fromShortcut("yesterday"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today | ||
| */ | ||
| get today() { | ||
| return __privateGet(this, _factory).find("today"); | ||
| return this.fromShortcut("today"); | ||
| } | ||
| /** | ||
| * Returns the date and time of tomorrow | ||
| */ | ||
| get tomorrow() { | ||
| return __privateGet(this, _factory).find("tomorrow"); | ||
| return this.fromShortcut("tomorrow"); | ||
| } | ||
| /** | ||
| * Returns the date and time of the day after tomorrow | ||
| */ | ||
| get afterTomorrow() { | ||
| return __privateGet(this, _factory).find("afterTomorrow"); | ||
| return this.fromShortcut("afterTomorrow"); | ||
| } | ||
| /** | ||
| * Returns the date and time of midnight today | ||
| */ | ||
| get midnight() { | ||
| return __privateGet(this, _factory).find("midnight"); | ||
| return this.fromShortcut("midnight"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today 1 week ago | ||
| */ | ||
| get lastWeek() { | ||
| return __privateGet(this, _factory).find("lastWeek"); | ||
| return this.fromShortcut("lastWeek"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today 1 week from now | ||
| */ | ||
| get nextWeek() { | ||
| return __privateGet(this, _factory).find("nextWeek"); | ||
| return this.fromShortcut("nextWeek"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today 2 weeks ago | ||
| */ | ||
| get lastFortnight() { | ||
| return __privateGet(this, _factory).find("lastFortnight"); | ||
| return this.fromShortcut("lastFortnight"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today 2 weeks from now | ||
| */ | ||
| get nextFortnight() { | ||
| return __privateGet(this, _factory).find("nextFortnight"); | ||
| return this.fromShortcut("nextFortnight"); | ||
| } | ||
| /** | ||
| * Attempts to parse a phrase into a date. | ||
| * @param phrase | ||
| * @returns | ||
| */ | ||
| fromPhrase(phrase) { | ||
| return __privateGet(this, _factory).fromPhrase(phrase); | ||
| return this.factory.fromPhrase(phrase); | ||
| } | ||
| /** | ||
| * Attempts to parse a phrase into a date. | ||
| * If the phrase is invalid, it will return an invalid date instead of throwing. | ||
| * @param phrase | ||
| * @returns | ||
| */ | ||
| fromPhraseSafe(phrase) { | ||
| return __privateGet(this, _factory).fromPhraseSafe(phrase); | ||
| return this.factory.fromPhraseSafe(phrase); | ||
| } | ||
| make(timeOffset, timeUnit) { | ||
| return __privateGet(this, _factory).make(timeOffset, timeUnit); | ||
| make(offset, unit) { | ||
| return this.factory.make(offset, unit); | ||
| } | ||
| fromShortcut(shortcut) { | ||
| return this.factory.find(shortcut); | ||
| } | ||
| }; | ||
| _factory = new WeakMap(); | ||
| _iso = new WeakMap(); | ||
| _fmt = new WeakMap(); | ||
| var Dates = new DatesObject(); | ||
| // src/time/time.ts | ||
| var import_asserters2 = require("@autometa/asserters"); | ||
| var import_phrases2 = require("@autometa/phrases"); | ||
| function createDates(options = {}) { | ||
| const factory = options.factory ?? new DateFactory(options); | ||
| return new DatesFacade(factory); | ||
| } | ||
| var Dates = createDates(); | ||
| var SUPPORTED_METHODS = [ | ||
| "minutes", | ||
| "seconds", | ||
| "millis", | ||
| "days", | ||
| "hours", | ||
| "weeks" | ||
| ]; | ||
| function toTime(date) { | ||
| return new Date(date).getTime(); | ||
| } | ||
| var TimeDiff = class { | ||
| minutes(date1, date2) { | ||
| return this.millis(date1, date2) / 6e4; | ||
| minutes(start, end) { | ||
| return this.millis(start, end) / 6e4; | ||
| } | ||
| seconds(date1, date2) { | ||
| return this.millis(date1, date2) / 1e3; | ||
| seconds(start, end) { | ||
| return this.millis(start, end) / 1e3; | ||
| } | ||
| millis(date1, date2) { | ||
| const d1 = new Date(date1).getTime(); | ||
| const d2 = new Date(date2).getTime(); | ||
| return Math.abs(Math.round(d2 - d1)); | ||
| millis(start, end) { | ||
| const distance = Math.abs(toTime(end) - toTime(start)); | ||
| return Math.round(distance); | ||
| } | ||
| days(date1, date2) { | ||
| return this.millis(date1, date2) / 864e5; | ||
| days(start, end) { | ||
| return this.millis(start, end) / 864e5; | ||
| } | ||
| hours(date1, date2) { | ||
| return this.millis(date1, date2) / 36e5; | ||
| hours(start, end) { | ||
| return this.millis(start, end) / 36e5; | ||
| } | ||
| weeks(date1, date2) { | ||
| return this.millis(date1, date2) / 6048e5; | ||
| weeks(start, end) { | ||
| return this.millis(start, end) / 6048e5; | ||
| } | ||
| fromPhrase(phrase) { | ||
| const propertyKey = (0, import_phrases2.convertPhrase)(phrase, import_phrases2.lower); | ||
| (0, import_asserters2.AssertKey)(this, propertyKey); | ||
| return this[propertyKey].bind(this); | ||
| if (typeof phrase !== "string") { | ||
| throw new AutomationError( | ||
| `TimeDiff.fromPhrase expects a string, received '${typeof phrase}'.` | ||
| ); | ||
| } | ||
| const key = normalizeToken(phrase); | ||
| if (!this.hasMethod(key)) { | ||
| throw new AutomationError( | ||
| `Unsupported diff unit '${phrase}'. Expected one of ${this.supportedMethods().join(", ")}.` | ||
| ); | ||
| } | ||
| assertKey(this, key, "TimeDiff.fromPhrase"); | ||
| const method = this[key]; | ||
| if (typeof method !== "function") { | ||
| throw new AutomationError(`Diff method '${key}' is not callable.`); | ||
| } | ||
| return method.bind(this); | ||
| } | ||
| }; | ||
| var _diff; | ||
| var TimeObject = class { | ||
| constructor() { | ||
| __privateAdd(this, _diff, new TimeDiff()); | ||
| hasMethod(name) { | ||
| return SUPPORTED_METHODS.includes(name); | ||
| } | ||
| get diff() { | ||
| return __privateGet(this, _diff); | ||
| supportedMethods() { | ||
| return [...SUPPORTED_METHODS]; | ||
| } | ||
| }; | ||
| _diff = new WeakMap(); | ||
| var Time = new TimeObject(); | ||
| // Annotate the CommonJS export names for ESM import in node: | ||
| 0 && (module.exports = { | ||
| DateFactory, | ||
| Dates, | ||
| FmtDateFactory, | ||
| IsoDateFactory, | ||
| Time, | ||
| TimeDiff, | ||
| TimeObject | ||
| }); | ||
| // src/time/time.ts | ||
| var TimeFacade = class { | ||
| constructor(diff) { | ||
| this.diff = diff; | ||
| } | ||
| }; | ||
| function createTime() { | ||
| return new TimeFacade(new TimeDiff()); | ||
| } | ||
| var Time = createTime(); | ||
| export { DateFactory, Dates, FormattedDateFactory, IsoDateFactory, Time, TimeDiff, createDates, createTime }; | ||
| //# sourceMappingURL=out.js.map | ||
| //# sourceMappingURL=index.js.map |
@@ -1,1 +0,1 @@ | ||
| {"version":3,"sources":["../src/index.ts","../src/dates/date-factory.ts","../src/dates/midnight.ts","../src/dates/iso-date-factory.ts","../src/dates/formatted-date-factory.ts","../src/dates/dates.ts","../src/time/time.ts"],"sourcesContent":["export * from './dates'\nexport * from './time'","import { TimeUnit, camel, convertPhrase, collapse } from \"@autometa/phrases\";\nimport { midnight } from \"./midnight\";\nimport { AutomationError, raise } from \"@autometa/errors\";\nimport { ConfirmDefined, ConfirmLengthAtLeast } from \"@autometa/asserters\";\nimport { isValidDate, isValidISODateString, isValidTime, isValidYearMonth } from \"iso-datestring-validator\";\ntype TimeShortcut =\n | \"now\"\n | \"beforeYesterday\"\n | \"yesterday\"\n | \"today\"\n | \"tomorrow\"\n | \"afterTomorrow\"\n | \"midnight\"\n | \"lastWeek\"\n | \"nextWeek\"\n | \"lastFortnight\"\n | \"nextFortnight\";\n\nfunction isTimeShortcut(text: string): text is TimeShortcut {\n const converted = convertPhrase(text, camel);\n const includes = [\n \"now\",\n \"beforeYesterday\",\n \"yesterday\",\n \"today\",\n \"tomorrow\",\n \"afterTomorrow\",\n \"midnight\",\n \"lastWeek\",\n \"nextWeek\",\n \"lastFortnight\",\n \"nextFortnight\"\n ].includes(converted);\n if (!includes) {\n return false;\n }\n return true;\n}\nexport class DateFactory {\n phraseMap = new Map<TimeShortcut, () => Date>([\n [\"now\", () => this.make(0, \"days\")],\n [\"beforeYesterday\", () => this.make(-2, \"days\")],\n [\"yesterday\", () => this.make(-1, \"days\")],\n [\"today\", () => this.make(0, \"days\")],\n [\"tomorrow\", () => this.make(1, \"days\")],\n [\"afterTomorrow\", () => this.make(2, \"days\")],\n [\"nextWeek\", () => this.make(7, \"days\")],\n [\"lastWeek\", () => this.make(-7, \"days\")],\n [\"nextFortnight\", () => this.make(14, \"days\")],\n [\"lastFortnight\", () => this.make(-14, \"days\")],\n [\"midnight\", midnight]\n ]);\n\n // eslint-disable-next-line @typescript-eslint/ban-types\n find(name: TimeShortcut): Date {\n const result = this.phraseMap.get(name);\n if (result) {\n return result();\n }\n raise(\n `Could not find date shortcut ${name}. Please use a valid date shortcut from the following list: ${Array.from(\n this.phraseMap.keys()\n ).join(\", \")}`\n );\n }\n\n fromPhraseSafe(phrase: string) {\n const name = convertPhrase(phrase, camel);\n if (isTimeShortcut(name)) {\n if (this.phraseMap.has(name)) {\n return this.phraseMap.get(name)?.call(this);\n }\n }\n \n const matchDay = this.#extractTimeFromPhrase(phrase);\n if (matchDay) {\n return matchDay;\n }\n const first = isValidDate(phrase);\n const second = isValidISODateString(phrase);\n const third = isValidTime(phrase);\n const fourth = isValidYearMonth(phrase);\n if (!first && !second && !third && !fourth) {\n return new Date(\"null\");\n }\n const parsed = new Date(phrase);\n if (isNaN(parsed.getTime())) {\n return new Date(Date.parse(phrase));\n }\n return parsed;\n }\n fromPhrase(phrase: string) {\n const result = this.fromPhraseSafe(phrase);\n if (result) {\n return result;\n }\n raise(\n `Could not parse date from phrase ${phrase}. Please use a valid date string or a phrase from the following list: ${Array.from(\n this.phraseMap.keys()\n ).join(\", \")}`\n );\n }\n make(timeOffset: number, timeunit: TimeUnit) {\n const unit = timeunit.endsWith(\"s\") ? timeunit : `${timeunit}s`;\n switch (unit) {\n case \"years\":\n return this.#addYears(timeOffset);\n case \"months\":\n return this.#addMonths(timeOffset);\n case \"weeks\":\n return this.#addWeeks(timeOffset);\n case \"days\":\n return this.#addDays(timeOffset);\n case \"seconds\":\n return this.#addSeconds(timeOffset);\n case \"milliseconds\":\n return this.#addMilliseconds(timeOffset);\n case \"hours\":\n return this.#addHours(timeOffset);\n case \"minutes\":\n return this.#addMinutes(timeOffset);\n default:\n throw new AutomationError(\n `Invalid timeunit ${timeunit}, options are 'days', 'seconds', 'milliseconds', 'hours', 'minutes'. Non plural equivalents such as 'day' or 'week' are also accepted.`\n );\n }\n }\n #extractTimeFromPhrase(phrase: string) {\n return (\n this.#extractFutureFromPhrase(phrase) ??\n this.#extractPastFromPhrase(phrase)\n );\n }\n #extractFutureFromPhrase(phrase: string) {\n const pastPattern = /^(\\d+) (.*)s? from now?/;\n const pastMatch = pastPattern.exec(phrase);\n\n if (ConfirmDefined(pastMatch) && ConfirmLengthAtLeast(pastMatch, 3)) {\n const [_, value, unit] = pastMatch;\n const timeunit = convertPhrase(unit, collapse) as TimeUnit;\n return this.make(Number(value), timeunit);\n }\n }\n #extractPastFromPhrase(phrase: string) {\n const pastPattern = /^(\\d+) (.*)(s)? ago?/gm;\n const pastMatch = pastPattern.exec(phrase);\n if (ConfirmDefined(pastMatch) && ConfirmLengthAtLeast(pastMatch, 3)) {\n const [_, value, unit] = pastMatch;\n const timeunit = convertPhrase(unit, camel) as TimeUnit;\n return this.make(-Number(value), timeunit);\n }\n }\n #addYears(yearsOffset: number) {\n const date = new Date();\n date.setFullYear(date.getFullYear() + yearsOffset);\n return date;\n }\n #addMonths(monthOffset: number) {\n const date = new Date();\n date.setMonth(date.getMonth() + monthOffset);\n return date;\n }\n #addWeeks(weekOffset: number) {\n const date = new Date();\n date.setMonth(date.getMonth() + weekOffset / 4);\n return date;\n }\n #addDays(daysOffset: number) {\n const date = new Date();\n date.setDate(date.getDate() + daysOffset);\n return date;\n }\n\n #addSeconds(secondsOffset: number) {\n const date = new Date();\n date.setSeconds(date.getSeconds() + secondsOffset);\n return date;\n }\n\n #addMilliseconds(millisecondsOffset: number) {\n const date = new Date();\n date.setMilliseconds(date.getMilliseconds() + millisecondsOffset);\n return date;\n }\n #addHours(hoursOffset: number) {\n const date = new Date();\n date.setHours(date.getHours() + hoursOffset);\n return date;\n }\n #addMinutes(minutesOffset: number) {\n const date = new Date();\n date.setMinutes(date.getMinutes() + minutesOffset);\n return date;\n }\n}\n","\nexport function midnight() {\n const date = new Date();\n date.setDate(date.getDate() + 1);\n date.setHours(0, 0, 0, 0);\n return date;\n}\n","import { TimeUnit } from '@autometa/phrases';\nimport { midnight } from './midnight';\nimport { DateFactory } from './date-factory';\n\n\nexport class IsoDateFactory {\n constructor(readonly dateFactory: DateFactory) { }\n phraseMap = new Map<string, string>([\n ['beforeYesterday', this.make(-2, 'days')],\n ['yesterday', this.make(-1, 'days')],\n ['today', this.make(0, 'days')],\n ['tomorrow', this.make(1, 'days')],\n ['afterTomorrow', this.make(2, 'days')],\n ['nextWeek', this.make(7, 'days')],\n ['lastWeek', this.make(-7, 'days')],\n ['nextFortnight', this.make(14, 'days')],\n ['lastFortnight', this.make(-14, 'days')],\n ['midnight', midnight().toISOString()],\n ]);\n make(daysOffset: number, timeunit: TimeUnit) {\n return this.dateFactory.make(daysOffset, timeunit).toISOString();\n }\n\n /**\n * Attempts to parse a phrase into a date.\n * @param phrase\n * @returns\n */\n fromPhrase(phrase: string) {\n return this.dateFactory.fromPhrase(phrase)?.toISOString();\n }\n\n /**\n * Returns the date and time of the day before yesterday\n */\n get beforeYesterday() {\n return this.phraseMap.get('beforeYesterday');\n }\n\n /**\n * Returns the date and time of yesterday\n */\n get yesterday() {\n return this.phraseMap.get('yesterday');\n }\n\n /**\n * Returns the date and time of today\n */\n get today() {\n return this.phraseMap.get('today');\n }\n\n /**\n * Returns the date and time of tomorrow\n */\n get tomorrow() {\n return this.phraseMap.get('tomorrow');\n }\n\n /**\n * Returns the date and time of the day after tomorrow\n */\n get afterTomorrow() {\n return this.phraseMap.get('afterTomorrow');\n }\n\n /**\n * Returns the date and time of midnight today\n */\n get midnight() {\n return this.phraseMap.get('midnight');\n }\n\n /**\n * Returns the date and time of today 1 week ago\n */\n get lastWeek() {\n return this.phraseMap.get('lastWeek');\n }\n\n /**\n * Returns the date and time of today 1 week from now\n */\n get nextWeek() {\n return this.phraseMap.get('nextWeek');\n }\n get lastFortnight() {\n return this.phraseMap.get('lastFortnight');\n }\n\n /**\n * Returns the date and time of today 1 fortnight from now\n */\n get nextFortnight() {\n return this.phraseMap.get('nextFortnight');\n }\n}\n","import { TimeUnit } from '@autometa/phrases';\nimport { DateFactory } from './date-factory';\nimport { midnight } from './midnight';\n\nexport class FmtDateFactory {\n constructor(readonly dateFactory: DateFactory) { }\n phraseMap = new Map<string, string>([\n ['beforeYesterday', this.make(-2, 'days')],\n ['yesterday', this.make(-1, 'days')],\n ['today', this.make(0, 'days')],\n ['tomorrow', this.make(1, 'days')],\n ['afterTomorrow', this.make(2, 'days')],\n ['nextWeek', this.make(7, 'days')],\n ['lastWeek', this.make(-7, 'days')],\n ['nextFortnight', this.make(14, 'days')],\n ['lastFortnight', this.make(-14, 'days')],\n ['midnight', midnight().toISOString()],\n ]);\n\n make(daysOffset: number, timeunit: TimeUnit) {\n return this.dateFactory\n .make(daysOffset, timeunit)\n .toISOString()\n .split('T')[0];\n }\n \n /**\n * Attempts to parse a phrase into a date.\n * @param phrase\n * @returns\n */\n fromPhrase(phrase: string) {\n return this.dateFactory.fromPhrase(phrase)?.toISOString().split('T')[0];\n }\n\n /**\n * Returns the date and time of the day before yesterday\n */\n get beforeYesterday() {\n return this.phraseMap.get('beforeYesterday');\n }\n\n /**\n * Returns the date and time of yesterday\n */\n get yesterday() {\n return this.phraseMap.get('yesterday');\n }\n\n /**\n * Returns the date and time of today\n */\n get today() {\n return this.phraseMap.get('today');\n }\n\n /**\n * Returns the date and time of tomorrow\n */\n get tomorrow() {\n return this.phraseMap.get('tomorrow');\n }\n\n /**\n * Returns the date and time of the day after tomorrow\n */\n get afterTomorrow() {\n return this.phraseMap.get('afterTomorrow');\n }\n\n /**\n * Returns the date and time of midnight today\n */\n get midnight() {\n return this.phraseMap.get('midnight');\n }\n\n /**\n * Returns the date and time of today 1 week ago\n */\n get lastWeek() {\n return this.phraseMap.get('lastWeek');\n }\n\n /**\n * Returns the date and time of today 1 week from now\n */\n get nextWeek() {\n return this.phraseMap.get('nextWeek');\n }\n\n /**\n * Returns the date and time of today 1 fortnight ago\n */\n get lastFortnight() {\n return this.phraseMap.get('lastFortnight');\n }\n\n /**\n * Returns the date and time of today 1 fortnight from now\n */\n get nextFortnight() {\n return this.phraseMap.get('nextFortnight');\n }\n}\n","import { DateFactory } from \"./date-factory\";\nimport { IsoDateFactory } from \"./iso-date-factory\";\nimport { FmtDateFactory } from \"./formatted-date-factory\";\nimport { TimeUnit } from \"@autometa/phrases\";\n\nexport class DatesObject {\n #factory: DateFactory = new DateFactory();\n #iso = new IsoDateFactory(this.#factory);\n #fmt = new FmtDateFactory(this.#factory);\n /**\n * Switches to the ISO factory, which offers an identical interface\n * but returns ISO strings instead of Date objects.\n * \n * Example: `2020-01-01T00:00:00.000Z`\n */\n get iso() {\n return this.#iso;\n }\n\n /**\n * Switches to the formatted factory, which offers an identical interface\n * but returns formatted strings instead of Date objects.\n * \n * Example: `2020-01-01`\n */\n get fmt() {\n return this.#fmt;\n }\n\n /**\n * Returns the current date and time.\n */\n get now() {\n return this.#factory.find(\"now\");\n }\n\n /**\n * Returns the date and time of the day before yesterday\n */\n get beforeYesterday(): Date {\n return this.#factory.find(\"beforeYesterday\");\n }\n \n /**\n * Returns the date and time of yesterday\n */\n get yesterday(): Date {\n return this.#factory.find(\"yesterday\");\n }\n\n /**\n * Returns the date and time of today\n */\n get today(): Date {\n return this.#factory.find(\"today\");\n }\n\n /**\n * Returns the date and time of tomorrow\n */\n get tomorrow(): Date {\n return this.#factory.find(\"tomorrow\");\n }\n\n /**\n * Returns the date and time of the day after tomorrow\n */\n get afterTomorrow(): Date {\n return this.#factory.find(\"afterTomorrow\");\n }\n\n /**\n * Returns the date and time of midnight today\n */\n get midnight(): Date {\n return this.#factory.find(\"midnight\");\n }\n\n /**\n * Returns the date and time of today 1 week ago\n */\n get lastWeek(): Date {\n return this.#factory.find(\"lastWeek\");\n }\n\n /**\n * Returns the date and time of today 1 week from now\n */\n get nextWeek(): Date {\n return this.#factory.find(\"nextWeek\");\n }\n\n /**\n * Returns the date and time of today 2 weeks ago\n */\n get lastFortnight(): Date {\n return this.#factory.find(\"lastFortnight\");\n }\n\n /**\n * Returns the date and time of today 2 weeks from now\n */\n get nextFortnight(): Date {\n return this.#factory.find(\"nextFortnight\");\n }\n\n /**\n * Attempts to parse a phrase into a date.\n * @param phrase \n * @returns \n */\n fromPhrase(phrase: string) {\n return this.#factory.fromPhrase(phrase);\n }\n\n /**\n * Attempts to parse a phrase into a date.\n * If the phrase is invalid, it will return an invalid date instead of throwing.\n * @param phrase \n * @returns \n */\n fromPhraseSafe(phrase: string) {\n return this.#factory.fromPhraseSafe(phrase);\n }\n\n make(timeOffset: number, timeUnit: TimeUnit) {\n return this.#factory.make(timeOffset, timeUnit);\n }\n}\n\n/**\n * Date utility option to easily generate common\n * dates around the current date, like 'today', 'midnight',\n * 'tomorrow', 'nextWeek', etc.\n * \n * The Dates utility also supports certain language phrases\n * that might be natural in Cucumber's gherkin syntax, like\n * 'next week', 'last week', 'next fortnight', etc. as well\n * as more dynamic phrases like `1 day ago`, `2 weeks from now`,\n */\nexport const Dates = new DatesObject();\n","import { AssertKey } from \"@autometa/asserters\";\nimport { convertPhrase, lower } from \"@autometa/phrases\";\ntype TimeDiffFn = (date1: Date, date2: Date) => number;\n\nexport class TimeDiff {\n minutes(date1: Date, date2: Date) {\n return this.millis(date1, date2) / 60000;\n }\n seconds(date1: Date, date2: Date) {\n return this.millis(date1, date2) / 1000;\n }\n millis(date1: Date, date2: Date) {\n const d1 = new Date(date1).getTime();\n const d2 = new Date(date2).getTime();\n return Math.abs(Math.round(d2 - d1));\n }\n days(date1: Date, date2: Date) {\n return this.millis(date1, date2) / 86400000;\n }\n hours(date1: Date, date2: Date) {\n return this.millis(date1, date2) / 3600000;\n }\n weeks(date1: Date, date2: Date) {\n return this.millis(date1, date2) / 604800000;\n }\n fromPhrase(phrase: string): TimeDiffFn {\n const propertyKey = convertPhrase(phrase, lower);\n AssertKey(this, propertyKey);\n return (this[propertyKey] as TimeDiffFn).bind(this);\n }\n}\n\nexport class TimeObject {\n #diff = new TimeDiff();\n get diff() {\n return this.#diff;\n }\n}\n\nexport const Time = new TimeObject();\n"],"mappings":"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","names":["import_asserters","import_phrases"]} | ||
| {"version":3,"sources":["../src/dates/date-factory.ts","../src/dates/clock.ts","../src/dates/time-units.ts","../src/shared/phrases.ts","../src/dates/formatted-date-factory.ts","../src/dates/iso-date-factory.ts","../src/dates/object.ts","../src/time/time-diff.ts","../src/time/time.ts"],"names":["AutomationError"],"mappings":";AAAA,SAAS,mBAAAA,wBAAuB;AAChC;AAAA,EACE;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,OACK;;;ACFA,IAAM,cAAqB;AAAA,EAChC,KAAK,MAAM,oBAAI,KAAK;AACtB;AAEO,SAAS,UAAU,MAAkB;AAC1C,SAAO,IAAI,KAAK,KAAK,QAAQ,CAAC;AAChC;;;ACVA,SAAS,uBAAuB;AAiBhC,IAAM,eAAmD;AAAA,EACvD,aAAa,EAAE,MAAM,gBAAgB,OAAO,EAAE;AAAA,EAC9C,cAAc,EAAE,MAAM,gBAAgB,OAAO,EAAE;AAAA,EAC/C,IAAI,EAAE,MAAM,gBAAgB,OAAO,EAAE;AAAA,EACrC,QAAQ,EAAE,MAAM,WAAW,OAAO,EAAE;AAAA,EACpC,SAAS,EAAE,MAAM,WAAW,OAAO,EAAE;AAAA,EACrC,KAAK,EAAE,MAAM,WAAW,OAAO,EAAE;AAAA,EACjC,MAAM,EAAE,MAAM,WAAW,OAAO,EAAE;AAAA,EAClC,QAAQ,EAAE,MAAM,WAAW,OAAO,EAAE;AAAA,EACpC,SAAS,EAAE,MAAM,WAAW,OAAO,EAAE;AAAA,EACrC,KAAK,EAAE,MAAM,WAAW,OAAO,EAAE;AAAA,EACjC,MAAM,EAAE,MAAM,WAAW,OAAO,EAAE;AAAA,EAClC,MAAM,EAAE,MAAM,SAAS,OAAO,EAAE;AAAA,EAChC,OAAO,EAAE,MAAM,SAAS,OAAO,EAAE;AAAA,EACjC,IAAI,EAAE,MAAM,SAAS,OAAO,EAAE;AAAA,EAC9B,KAAK,EAAE,MAAM,SAAS,OAAO,EAAE;AAAA,EAC/B,KAAK,EAAE,MAAM,QAAQ,OAAO,EAAE;AAAA,EAC9B,MAAM,EAAE,MAAM,QAAQ,OAAO,EAAE;AAAA,EAC/B,MAAM,EAAE,MAAM,SAAS,OAAO,EAAE;AAAA,EAChC,OAAO,EAAE,MAAM,SAAS,OAAO,EAAE;AAAA,EACjC,WAAW,EAAE,MAAM,QAAQ,OAAO,GAAG;AAAA,EACrC,YAAY,EAAE,MAAM,QAAQ,OAAO,GAAG;AAAA,EACtC,OAAO,EAAE,MAAM,UAAU,OAAO,EAAE;AAAA,EAClC,QAAQ,EAAE,MAAM,UAAU,OAAO,EAAE;AAAA,EACnC,MAAM,EAAE,MAAM,SAAS,OAAO,EAAE;AAAA,EAChC,OAAO,EAAE,MAAM,SAAS,OAAO,EAAE;AACnC;AAEO,SAAS,gBAAgB,OAAmC;AACjE,QAAM,MAAM,MAAM,KAAK,EAAE,YAAY;AACrC,QAAM,WAAW,aAAa,GAAG;AACjC,MAAI,CAAC,UAAU;AACb,UAAM,IAAI;AAAA,MACR,0BAA0B,KAAK,sBAAsB,OAAO,KAAK,YAAY,EAC1E,KAAK,EACL,KAAK,IAAI,CAAC;AAAA,IACf;AAAA,EACF;AACA,SAAO;AACT;;;ACxDA,IAAM,aAAa;AAEnB,SAAS,WAAW,MAAsB;AACxC,SAAO,KAAK,OAAO,CAAC,EAAE,YAAY,IAAI,KAAK,MAAM,CAAC;AACpD;AAEA,SAAS,WAAW,QAA0B;AAC5C,SAAO,OACJ,KAAK,EACL,MAAM,UAAU,EAChB,OAAO,OAAO,EACd,IAAI,CAAC,SAAS,KAAK,YAAY,CAAC;AACrC;AAEO,SAAS,WAAW,QAAwB;AACjD,QAAM,QAAQ,WAAW,MAAM;AAC/B,MAAI,MAAM,WAAW,GAAG;AACtB,WAAO;AAAA,EACT;AACA,QAAM,CAAC,OAAO,GAAG,IAAI,IAAI;AACzB,SAAO,QAAQ,KAAK,IAAI,UAAU,EAAE,KAAK,EAAE;AAC7C;AAEO,SAAS,eAAe,QAAwB;AACrD,SAAO,WAAW,MAAM,EAAE,KAAK,EAAE;AACnC;;;AHGA,IAAM,kBAAkB,oBAAI,IAAkB;AAAA,EAC5C;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF,CAAC;AAWD,IAAM,iBAAiB;AACvB,IAAM,eAAe;AAErB,SAAS,cAAoB;AAC3B,SAAO,IAAI,KAAK,OAAO,GAAG;AAC5B;AAEA,SAAS,eAAe,OAAsC;AAC5D,SAAO,gBAAgB,IAAI,KAAqB;AAClD;AAEO,IAAM,cAAN,MAAkB;AAAA,EAGvB,YAAY,UAA8B,CAAC,GAAG;AAC5C,SAAK,QAAQ,QAAQ,SAAS;AAAA,EAChC;AAAA,EAEA,KAAK,UAA8B;AACjC,YAAQ,UAAU;AAAA,MAChB,KAAK;AACH,eAAO,KAAK,YAAY;AAAA,MAC1B,KAAK;AACH,eAAO,KAAK,KAAK,IAAI,MAAM;AAAA,MAC7B,KAAK;AACH,eAAO,KAAK,KAAK,IAAI,MAAM;AAAA,MAC7B,KAAK;AACH,eAAO,KAAK,KAAK,GAAG,MAAM;AAAA,MAC5B,KAAK;AACH,eAAO,KAAK,KAAK,GAAG,MAAM;AAAA,MAC5B,KAAK;AACH,eAAO,KAAK,KAAK,GAAG,MAAM;AAAA,MAC5B,KAAK;AACH,eAAO,KAAK,SAAS;AAAA,MACvB,KAAK;AACH,eAAO,KAAK,KAAK,IAAI,OAAO;AAAA,MAC9B,KAAK;AACH,eAAO,KAAK,KAAK,GAAG,OAAO;AAAA,MAC7B,KAAK;AACH,eAAO,KAAK,KAAK,KAAK,MAAM;AAAA,MAC9B,KAAK;AACH,eAAO,KAAK,KAAK,IAAI,MAAM;AAAA,MAC7B;AACE,cAAM,IAAIA;AAAA,UACR,8BAA8B,QAAQ;AAAA,QACxC;AAAA,IACJ;AAAA,EACF;AAAA,EAEA,eAAe,QAAuB;AACpC,QAAI,OAAO,WAAW,UAAU;AAC9B,aAAO,YAAY;AAAA,IACrB;AAEA,UAAM,UAAU,OAAO,KAAK;AAC5B,QAAI,QAAQ,WAAW,GAAG;AACxB,aAAO,YAAY;AAAA,IACrB;AAEF,UAAM,oBAAoB,WAAW,OAAO;AAC1C,QAAI,eAAe,iBAAiB,GAAG;AACrC,aAAO,KAAK,KAAK,iBAAiB;AAAA,IACpC;AAEA,UAAM,WAAW,KAAK,gBAAgB,OAAO;AAC7C,QAAI,UAAU;AACZ,aAAO,KAAK,KAAK,SAAS,QAAQ,SAAS,IAAI;AAAA,IACjD;AAEA,QAAI,KAAK,WAAW,OAAO,GAAG;AAC5B,aAAO,KAAK,UAAU,OAAO;AAAA,IAC/B;AAEA,WAAO,YAAY;AAAA,EACrB;AAAA,EAEA,WAAW,QAAuB;AAChC,UAAM,SAAS,KAAK,eAAe,MAAM;AACzC,QAAI,OAAO,MAAM,OAAO,QAAQ,CAAC,GAAG;AAClC,YAAM,IAAIA;AAAA,QACR,qCAAqC,OAAO,MAAM,CAAC,2BACzB,CAAC,GAAG,eAAe,EAAE,KAAK,IAAI,CAAC;AAAA,MAC3D;AAAA,IACF;AACA,WAAO;AAAA,EACT;AAAA,EAEA,KAAK,YAAoB,UAA2C;AAClE,QAAI,CAAC,OAAO,SAAS,UAAU,GAAG;AAChC,YAAM,IAAIA;AAAA,QACR,yCAAyC,UAAU;AAAA,MACrD;AAAA,IACF;AAEA,UAAM,EAAE,MAAM,MAAM,IAAI,gBAAgB,OAAO,QAAQ,CAAC;AACxD,UAAM,SAAS,aAAa;AAC5B,UAAM,OAAO,KAAK,YAAY;AAE9B,YAAQ,MAAM;AAAA,MACZ,KAAK;AACH,aAAK,YAAY,KAAK,YAAY,IAAI,MAAM;AAC5C;AAAA,MACF,KAAK;AACH,aAAK,SAAS,KAAK,SAAS,IAAI,MAAM;AACtC;AAAA,MACF,KAAK;AACH,aAAK,QAAQ,KAAK,QAAQ,IAAI,SAAS,CAAC;AACxC;AAAA,MACF,KAAK;AACH,aAAK,QAAQ,KAAK,QAAQ,IAAI,MAAM;AACpC;AAAA,MACF,KAAK;AACH,aAAK,SAAS,KAAK,SAAS,IAAI,MAAM;AACtC;AAAA,MACF,KAAK;AACH,aAAK,WAAW,KAAK,WAAW,IAAI,MAAM;AAC1C;AAAA,MACF,KAAK;AACH,aAAK,WAAW,KAAK,WAAW,IAAI,MAAM;AAC1C;AAAA,MACF,KAAK;AACH,aAAK,gBAAgB,KAAK,gBAAgB,IAAI,MAAM;AACpD;AAAA,MACF;AACE,cAAM,IAAIA,iBAAgB,0BAA0B,IAAI,IAAI;AAAA,IAChE;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,cAAoB;AAC1B,WAAO,UAAU,KAAK,MAAM,IAAI,CAAC;AAAA,EACnC;AAAA,EAEQ,WAAiB;AACvB,UAAM,OAAO,KAAK,YAAY;AAC9B,SAAK,WAAW,KAAK,WAAW,IAAI,CAAC;AACrC,SAAK,YAAY,GAAG,GAAG,GAAG,CAAC;AAC3B,WAAO;AAAA,EACT;AAAA,EAEQ,UAAU,OAAqB;AACrC,UAAM,SAAS,IAAI,KAAK,KAAK;AAC7B,QAAI,CAAC,OAAO,MAAM,OAAO,QAAQ,CAAC,GAAG;AACnC,aAAO;AAAA,IACT;AACA,WAAO,IAAI,KAAK,KAAK,MAAM,KAAK,CAAC;AAAA,EACnC;AAAA,EAEQ,WAAW,OAAwB;AACzC,QAAI,CAAC,OAAO,MAAM,IAAI,KAAK,KAAK,EAAE,QAAQ,CAAC,GAAG;AAC5C,aAAO;AAAA,IACT;AACA,WACE,YAAY,KAAK,KACjB,qBAAqB,KAAK,KAC1B,YAAY,KAAK,KACjB,iBAAiB,KAAK;AAAA,EAE1B;AAAA,EAEQ,gBAAgB,QAAiD;AACvE,UAAM,cAAc,eAAe,KAAK,MAAM;AAC9C,QAAI,aAAa;AACf,aAAO,KAAK,mBAAmB,aAAa,CAAC;AAAA,IAC/C;AAEA,UAAM,YAAY,aAAa,KAAK,MAAM;AAC1C,QAAI,WAAW;AACb,aAAO,KAAK,mBAAmB,WAAW,EAAE;AAAA,IAC9C;AAEA,WAAO;AAAA,EACT;AAAA,EAEQ,mBACN,OACA,WACiC;AACjC,UAAM,QAAQ,MAAM,CAAC;AACrB,UAAM,OAAO,MAAM,CAAC;AACpB,QAAI,CAAC,SAAS,CAAC,MAAM;AACnB,aAAO;AAAA,IACT;AAEA,UAAM,YAAY,OAAO,SAAS,OAAO,EAAE;AAC3C,QAAI,CAAC,OAAO,SAAS,SAAS,GAAG;AAC/B,aAAO;AAAA,IACT;AAEF,UAAM,gBAAgB,eAAe,IAAI;AACvC,UAAM,EAAE,MAAM,gBAAgB,MAAM,IAAI,gBAAgB,aAAa;AACrE,UAAM,SAAS,YAAY,QAAQ;AACnC,WAAO;AAAA,MACL;AAAA,MACA,MAAM;AAAA,IACR;AAAA,EACF;AACF;;;AIlPO,IAAM,uBAAN,MAA2B;AAAA,EAGhC,YACmB,aACjB,UAAuC,CAAC,GACxC;AAFiB;AAGjB,SAAK,SACH,QAAQ,cAAc,CAAC,SAAS,KAAK,YAAY,EAAE,UAAU,GAAG,EAAE;AAAA,EACtE;AAAA,EAEA,KAAK,QAAgB,MAAyC;AAC5D,WAAO,KAAK,OAAO,KAAK,YAAY,KAAK,QAAQ,IAAI,CAAC;AAAA,EACxD;AAAA,EAEA,WAAW,QAAyB;AAClC,WAAO,KAAK,OAAO,KAAK,YAAY,WAAW,MAAM,CAAC;AAAA,EACxD;AAAA,EAEA,IAAI,kBAA0B;AAC5B,WAAO,KAAK,aAAa,iBAAiB;AAAA,EAC5C;AAAA,EAEA,IAAI,YAAoB;AACtB,WAAO,KAAK,aAAa,WAAW;AAAA,EACtC;AAAA,EAEA,IAAI,QAAgB;AAClB,WAAO,KAAK,aAAa,OAAO;AAAA,EAClC;AAAA,EAEA,IAAI,WAAmB;AACrB,WAAO,KAAK,aAAa,UAAU;AAAA,EACrC;AAAA,EAEA,IAAI,gBAAwB;AAC1B,WAAO,KAAK,aAAa,eAAe;AAAA,EAC1C;AAAA,EAEA,IAAI,WAAmB;AACrB,WAAO,KAAK,aAAa,UAAU;AAAA,EACrC;AAAA,EAEA,IAAI,WAAmB;AACrB,WAAO,KAAK,aAAa,UAAU;AAAA,EACrC;AAAA,EAEA,IAAI,WAAmB;AACrB,WAAO,KAAK,aAAa,UAAU;AAAA,EACrC;AAAA,EAEA,IAAI,gBAAwB;AAC1B,WAAO,KAAK,aAAa,eAAe;AAAA,EAC1C;AAAA,EAEA,IAAI,gBAAwB;AAC1B,WAAO,KAAK,aAAa,eAAe;AAAA,EAC1C;AAAA,EAEQ,aAAa,UAAgC;AACnD,WAAO,KAAK,OAAO,KAAK,YAAY,KAAK,QAAQ,CAAC;AAAA,EACpD;AACF;;;AC9DO,IAAM,iBAAN,MAAqB;AAAA,EAG1B,YACmB,aACjB,UAAiC,CAAC,GAClC;AAFiB;AAGjB,SAAK,YAAY,QAAQ,eAAe,CAAC,SAAS,KAAK,YAAY;AAAA,EACrE;AAAA,EAEA,KAAK,QAAgB,MAAyC;AAC5D,WAAO,KAAK,UAAU,KAAK,YAAY,KAAK,QAAQ,IAAI,CAAC;AAAA,EAC3D;AAAA,EAEA,WAAW,QAAyB;AAClC,WAAO,KAAK,UAAU,KAAK,YAAY,WAAW,MAAM,CAAC;AAAA,EAC3D;AAAA,EAEA,IAAI,kBAA0B;AAC5B,WAAO,KAAK,aAAa,iBAAiB;AAAA,EAC5C;AAAA,EAEA,IAAI,YAAoB;AACtB,WAAO,KAAK,aAAa,WAAW;AAAA,EACtC;AAAA,EAEA,IAAI,QAAgB;AAClB,WAAO,KAAK,aAAa,OAAO;AAAA,EAClC;AAAA,EAEA,IAAI,WAAmB;AACrB,WAAO,KAAK,aAAa,UAAU;AAAA,EACrC;AAAA,EAEA,IAAI,gBAAwB;AAC1B,WAAO,KAAK,aAAa,eAAe;AAAA,EAC1C;AAAA,EAEA,IAAI,WAAmB;AACrB,WAAO,KAAK,aAAa,UAAU;AAAA,EACrC;AAAA,EAEA,IAAI,WAAmB;AACrB,WAAO,KAAK,aAAa,UAAU;AAAA,EACrC;AAAA,EAEA,IAAI,WAAmB;AACrB,WAAO,KAAK,aAAa,UAAU;AAAA,EACrC;AAAA,EAEA,IAAI,gBAAwB;AAC1B,WAAO,KAAK,aAAa,eAAe;AAAA,EAC1C;AAAA,EAEA,IAAI,gBAAwB;AAC1B,WAAO,KAAK,aAAa,eAAe;AAAA,EAC1C;AAAA,EAEQ,aAAa,UAAgC;AACnD,WAAO,KAAK,UAAU,KAAK,YAAY,KAAK,QAAQ,CAAC;AAAA,EACvD;AACF;;;ACxCA,IAAM,cAAN,MAAyC;AAAA,EAIvC,YAA6B,SAAsB;AAAtB;AAC3B,SAAK,MAAM,IAAI,eAAe,OAAO;AACrC,SAAK,MAAM,IAAI,qBAAqB,OAAO;AAAA,EAC7C;AAAA,EAEA,IAAI,MAAY;AACd,WAAO,KAAK,aAAa,KAAK;AAAA,EAChC;AAAA,EAEA,IAAI,kBAAwB;AAC1B,WAAO,KAAK,aAAa,iBAAiB;AAAA,EAC5C;AAAA,EAEA,IAAI,YAAkB;AACpB,WAAO,KAAK,aAAa,WAAW;AAAA,EACtC;AAAA,EAEA,IAAI,QAAc;AAChB,WAAO,KAAK,aAAa,OAAO;AAAA,EAClC;AAAA,EAEA,IAAI,WAAiB;AACnB,WAAO,KAAK,aAAa,UAAU;AAAA,EACrC;AAAA,EAEA,IAAI,gBAAsB;AACxB,WAAO,KAAK,aAAa,eAAe;AAAA,EAC1C;AAAA,EAEA,IAAI,WAAiB;AACnB,WAAO,KAAK,aAAa,UAAU;AAAA,EACrC;AAAA,EAEA,IAAI,WAAiB;AACnB,WAAO,KAAK,aAAa,UAAU;AAAA,EACrC;AAAA,EAEA,IAAI,WAAiB;AACnB,WAAO,KAAK,aAAa,UAAU;AAAA,EACrC;AAAA,EAEA,IAAI,gBAAsB;AACxB,WAAO,KAAK,aAAa,eAAe;AAAA,EAC1C;AAAA,EAEA,IAAI,gBAAsB;AACxB,WAAO,KAAK,aAAa,eAAe;AAAA,EAC1C;AAAA,EAEA,WAAW,QAAuB;AAChC,WAAO,KAAK,QAAQ,WAAW,MAAM;AAAA,EACvC;AAAA,EAEA,eAAe,QAAuB;AACpC,WAAO,KAAK,QAAQ,eAAe,MAAM;AAAA,EAC3C;AAAA,EAEA,KAAK,QAAgB,MAAuC;AAC1D,WAAO,KAAK,QAAQ,KAAK,QAAQ,IAAI;AAAA,EACvC;AAAA,EAEQ,aAAa,UAA8B;AACjD,WAAO,KAAK,QAAQ,KAAK,QAAQ;AAAA,EACnC;AACF;AAEO,SAAS,YAAY,UAAwB,CAAC,GAAgB;AACnE,QAAM,UAAU,QAAQ,WAAW,IAAI,YAAY,OAAO;AAC1D,SAAO,IAAI,YAAY,OAAO;AAChC;AAEO,IAAM,QAAQ,YAAY;;;ACvGjC,SAAS,mBAAAA,wBAAuB;AAChC,SAAS,iBAAiB;AAK1B,IAAM,oBAAoB;AAAA,EACxB;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AAAA,EACA;AACF;AAGA,SAAS,OAAO,MAAoB;AAClC,SAAO,IAAI,KAAK,IAAI,EAAE,QAAQ;AAChC;AAEO,IAAM,WAAN,MAAe;AAAA,EACpB,QAAQ,OAAa,KAAmB;AACtC,WAAO,KAAK,OAAO,OAAO,GAAG,IAAI;AAAA,EACnC;AAAA,EAEA,QAAQ,OAAa,KAAmB;AACtC,WAAO,KAAK,OAAO,OAAO,GAAG,IAAI;AAAA,EACnC;AAAA,EAEA,OAAO,OAAa,KAAmB;AACrC,UAAM,WAAW,KAAK,IAAI,OAAO,GAAG,IAAI,OAAO,KAAK,CAAC;AACrD,WAAO,KAAK,MAAM,QAAQ;AAAA,EAC5B;AAAA,EAEA,KAAK,OAAa,KAAmB;AACnC,WAAO,KAAK,OAAO,OAAO,GAAG,IAAI;AAAA,EACnC;AAAA,EAEA,MAAM,OAAa,KAAmB;AACpC,WAAO,KAAK,OAAO,OAAO,GAAG,IAAI;AAAA,EACnC;AAAA,EAEA,MAAM,OAAa,KAAmB;AACpC,WAAO,KAAK,OAAO,OAAO,GAAG,IAAI;AAAA,EACnC;AAAA,EAEA,WAAW,QAA6B;AACtC,QAAI,OAAO,WAAW,UAAU;AAC9B,YAAM,IAAIA;AAAA,QACR,mDAAmD,OAAO,MAAM;AAAA,MAClE;AAAA,IACF;AAEF,UAAM,MAAM,eAAe,MAAM;AAC/B,QAAI,CAAC,KAAK,UAAU,GAAG,GAAG;AACxB,YAAM,IAAIA;AAAA,QACR,0BAA0B,MAAM,sBAAsB,KAAK,iBAAiB,EAAE,KAAK,IAAI,CAAC;AAAA,MAC1F;AAAA,IACF;AAEF,cAAU,MAAM,KAAmB,qBAAqB;AACxD,UAAM,SAAS,KAAK,GAAiB;AACnC,QAAI,OAAO,WAAW,YAAY;AAChC,YAAM,IAAIA,iBAAgB,gBAAgB,GAAG,oBAAoB;AAAA,IACnE;AACA,WAAQ,OAAsB,KAAK,IAAI;AAAA,EACzC;AAAA,EAEQ,UAAU,MAAuB;AACvC,WAAO,kBAAkB,SAAS,IAAkB;AAAA,EACtD;AAAA,EAEQ,mBAAiC;AACvC,WAAO,CAAC,GAAG,iBAAiB;AAAA,EAC9B;AACF;;;ACrEA,IAAM,aAAN,MAAwC;AAAA,EAGtC,YAAY,MAAgB;AAC1B,SAAK,OAAO;AAAA,EACd;AACF;AAEO,SAAS,aAA0B;AACxC,SAAO,IAAI,WAAW,IAAI,SAAS,CAAC;AACtC;AAEO,IAAM,OAAO,WAAW","sourcesContent":["import { AutomationError } from \"@autometa/errors\";\nimport {\n isValidDate,\n isValidISODateString,\n isValidTime,\n isValidYearMonth,\n} from \"iso-datestring-validator\";\nimport type { Clock } from \"./clock.js\";\nimport { cloneDate, systemClock } from \"./clock.js\";\nimport {\n resolveTimeUnit,\n type StandardTimeUnit,\n} from \"./time-units.js\";\nimport { normalizeToken, toCamelKey } from \"../shared/phrases.js\";\n\nexport type DateShortcut =\n | \"now\"\n | \"beforeYesterday\"\n | \"yesterday\"\n | \"today\"\n | \"tomorrow\"\n | \"afterTomorrow\"\n | \"midnight\"\n | \"lastWeek\"\n | \"nextWeek\"\n | \"lastFortnight\"\n | \"nextFortnight\";\n\nconst SHORTCUT_LOOKUP = new Set<DateShortcut>([\n \"now\",\n \"beforeYesterday\",\n \"yesterday\",\n \"today\",\n \"tomorrow\",\n \"afterTomorrow\",\n \"midnight\",\n \"lastWeek\",\n \"nextWeek\",\n \"lastFortnight\",\n \"nextFortnight\",\n]);\n\nexport interface DateFactoryOptions {\n clock?: Clock;\n}\n\ninterface RelativePhraseMatch {\n offset: number;\n unit: StandardTimeUnit;\n}\n\nconst FUTURE_PATTERN = /^(\\d+)\\s+([A-Za-z\\s]+?)\\s+from\\s+now$/i;\nconst PAST_PATTERN = /^(\\d+)\\s+([A-Za-z\\s]+?)\\s+ago$/i;\n\nfunction invalidDate(): Date {\n return new Date(Number.NaN);\n}\n\nfunction isDateShortcut(value: string): value is DateShortcut {\n return SHORTCUT_LOOKUP.has(value as DateShortcut);\n}\n\nexport class DateFactory {\n private readonly clock: Clock;\n\n constructor(options: DateFactoryOptions = {}) {\n this.clock = options.clock ?? systemClock;\n }\n\n find(shortcut: DateShortcut): Date {\n switch (shortcut) {\n case \"now\":\n return this.currentDate();\n case \"beforeYesterday\":\n return this.make(-2, \"days\");\n case \"yesterday\":\n return this.make(-1, \"days\");\n case \"today\":\n return this.make(0, \"days\");\n case \"tomorrow\":\n return this.make(1, \"days\");\n case \"afterTomorrow\":\n return this.make(2, \"days\");\n case \"midnight\":\n return this.midnight();\n case \"lastWeek\":\n return this.make(-1, \"weeks\");\n case \"nextWeek\":\n return this.make(1, \"weeks\");\n case \"lastFortnight\":\n return this.make(-14, \"days\");\n case \"nextFortnight\":\n return this.make(14, \"days\");\n default:\n throw new AutomationError(\n `Unsupported date shortcut '${shortcut}'.`\n );\n }\n }\n\n fromPhraseSafe(phrase: unknown): Date {\n if (typeof phrase !== \"string\") {\n return invalidDate();\n }\n\n const trimmed = phrase.trim();\n if (trimmed.length === 0) {\n return invalidDate();\n }\n\n const shortcutCandidate = toCamelKey(trimmed);\n if (isDateShortcut(shortcutCandidate)) {\n return this.find(shortcutCandidate);\n }\n\n const relative = this.extractRelative(trimmed);\n if (relative) {\n return this.make(relative.offset, relative.unit);\n }\n\n if (this.isDateLike(trimmed)) {\n return this.parseDate(trimmed);\n }\n\n return invalidDate();\n }\n\n fromPhrase(phrase: unknown): Date {\n const result = this.fromPhraseSafe(phrase);\n if (Number.isNaN(result.getTime())) {\n throw new AutomationError(\n `Could not parse date from phrase '${String(phrase)}'. ` +\n `Valid shortcuts are: ${[...SHORTCUT_LOOKUP].join(\", \")}.`\n );\n }\n return result;\n }\n\n make(timeOffset: number, timeUnit: string | StandardTimeUnit): Date {\n if (!Number.isFinite(timeOffset)) {\n throw new AutomationError(\n `Time offset must be finite. Received '${timeOffset}'.`\n );\n }\n\n const { unit, scale } = resolveTimeUnit(String(timeUnit));\n const offset = timeOffset * scale;\n const date = this.currentDate();\n\n switch (unit) {\n case \"years\":\n date.setFullYear(date.getFullYear() + offset);\n break;\n case \"months\":\n date.setMonth(date.getMonth() + offset);\n break;\n case \"weeks\":\n date.setDate(date.getDate() + offset * 7);\n break;\n case \"days\":\n date.setDate(date.getDate() + offset);\n break;\n case \"hours\":\n date.setHours(date.getHours() + offset);\n break;\n case \"minutes\":\n date.setMinutes(date.getMinutes() + offset);\n break;\n case \"seconds\":\n date.setSeconds(date.getSeconds() + offset);\n break;\n case \"milliseconds\":\n date.setMilliseconds(date.getMilliseconds() + offset);\n break;\n default:\n throw new AutomationError(`Unsupported time unit '${unit}'.`);\n }\n\n return date;\n }\n\n private currentDate(): Date {\n return cloneDate(this.clock.now());\n }\n\n private midnight(): Date {\n const date = this.currentDate();\n date.setUTCDate(date.getUTCDate() + 1);\n date.setUTCHours(0, 0, 0, 0);\n return date;\n }\n\n private parseDate(value: string): Date {\n const parsed = new Date(value);\n if (!Number.isNaN(parsed.getTime())) {\n return parsed;\n }\n return new Date(Date.parse(value));\n }\n\n private isDateLike(value: string): boolean {\n if (!Number.isNaN(new Date(value).getTime())) {\n return true;\n }\n return (\n isValidDate(value) ||\n isValidISODateString(value) ||\n isValidTime(value) ||\n isValidYearMonth(value)\n );\n }\n\n private extractRelative(phrase: string): RelativePhraseMatch | undefined {\n const futureMatch = FUTURE_PATTERN.exec(phrase);\n if (futureMatch) {\n return this.buildRelativeMatch(futureMatch, 1);\n }\n\n const pastMatch = PAST_PATTERN.exec(phrase);\n if (pastMatch) {\n return this.buildRelativeMatch(pastMatch, -1);\n }\n\n return undefined;\n }\n\n private buildRelativeMatch(\n match: RegExpExecArray,\n direction: 1 | -1\n ): RelativePhraseMatch | undefined {\n const value = match[1];\n const unit = match[2];\n if (!value || !unit) {\n return undefined;\n }\n\n const magnitude = Number.parseInt(value, 10);\n if (!Number.isFinite(magnitude)) {\n return undefined;\n }\n\n const convertedUnit = normalizeToken(unit);\n const { unit: normalisedUnit, scale } = resolveTimeUnit(convertedUnit);\n const offset = magnitude * scale * direction;\n return {\n offset,\n unit: normalisedUnit,\n };\n }\n}\n","export interface Clock {\n now(): Date;\n}\n\nexport const systemClock: Clock = {\n now: () => new Date(),\n};\n\nexport function cloneDate(date: Date): Date {\n return new Date(date.getTime());\n}\n","import { AutomationError } from \"@autometa/errors\";\n\nexport type StandardTimeUnit =\n | \"milliseconds\"\n | \"seconds\"\n | \"minutes\"\n | \"hours\"\n | \"days\"\n | \"weeks\"\n | \"months\"\n | \"years\";\n\nexport interface NormalisedTimeUnit {\n unit: StandardTimeUnit;\n scale: number;\n}\n\nconst UNIT_ALIASES: Record<string, NormalisedTimeUnit> = {\n millisecond: { unit: \"milliseconds\", scale: 1 },\n milliseconds: { unit: \"milliseconds\", scale: 1 },\n ms: { unit: \"milliseconds\", scale: 1 },\n second: { unit: \"seconds\", scale: 1 },\n seconds: { unit: \"seconds\", scale: 1 },\n sec: { unit: \"seconds\", scale: 1 },\n secs: { unit: \"seconds\", scale: 1 },\n minute: { unit: \"minutes\", scale: 1 },\n minutes: { unit: \"minutes\", scale: 1 },\n min: { unit: \"minutes\", scale: 1 },\n mins: { unit: \"minutes\", scale: 1 },\n hour: { unit: \"hours\", scale: 1 },\n hours: { unit: \"hours\", scale: 1 },\n hr: { unit: \"hours\", scale: 1 },\n hrs: { unit: \"hours\", scale: 1 },\n day: { unit: \"days\", scale: 1 },\n days: { unit: \"days\", scale: 1 },\n week: { unit: \"weeks\", scale: 1 },\n weeks: { unit: \"weeks\", scale: 1 },\n fortnight: { unit: \"days\", scale: 14 },\n fortnights: { unit: \"days\", scale: 14 },\n month: { unit: \"months\", scale: 1 },\n months: { unit: \"months\", scale: 1 },\n year: { unit: \"years\", scale: 1 },\n years: { unit: \"years\", scale: 1 },\n};\n\nexport function resolveTimeUnit(input: string): NormalisedTimeUnit {\n const key = input.trim().toLowerCase();\n const resolved = UNIT_ALIASES[key];\n if (!resolved) {\n throw new AutomationError(\n `Unsupported time unit '${input}'. Expected one of ${Object.keys(UNIT_ALIASES)\n .sort()\n .join(\", \")}.`\n );\n }\n return resolved;\n}\n","const SEPARATORS = /[\\s_-]+/g;\n\nfunction capitalize(word: string): string {\n return word.charAt(0).toUpperCase() + word.slice(1);\n}\n\nfunction splitWords(phrase: string): string[] {\n return phrase\n .trim()\n .split(SEPARATORS)\n .filter(Boolean)\n .map((word) => word.toLowerCase());\n}\n\nexport function toCamelKey(phrase: string): string {\n const words = splitWords(phrase);\n if (words.length === 0) {\n return \"\";\n }\n const [first, ...rest] = words;\n return first + rest.map(capitalize).join(\"\");\n}\n\nexport function normalizeToken(phrase: string): string {\n return splitWords(phrase).join(\"\");\n}\n","import type { DateFactory, DateShortcut } from \"./date-factory.js\";\nimport type { StandardTimeUnit } from \"./time-units.js\";\n\nexport interface FormattedDateFactoryOptions {\n formatter?: (date: Date) => string;\n}\n\nexport class FormattedDateFactory {\n private readonly format: (date: Date) => string;\n\n constructor(\n private readonly dateFactory: DateFactory,\n options: FormattedDateFactoryOptions = {}\n ) {\n this.format =\n options.formatter ?? ((date) => date.toISOString().substring(0, 10));\n }\n\n make(offset: number, unit: StandardTimeUnit | string): string {\n return this.format(this.dateFactory.make(offset, unit));\n }\n\n fromPhrase(phrase: unknown): string {\n return this.format(this.dateFactory.fromPhrase(phrase));\n }\n\n get beforeYesterday(): string {\n return this.fromShortcut(\"beforeYesterday\");\n }\n\n get yesterday(): string {\n return this.fromShortcut(\"yesterday\");\n }\n\n get today(): string {\n return this.fromShortcut(\"today\");\n }\n\n get tomorrow(): string {\n return this.fromShortcut(\"tomorrow\");\n }\n\n get afterTomorrow(): string {\n return this.fromShortcut(\"afterTomorrow\");\n }\n\n get midnight(): string {\n return this.fromShortcut(\"midnight\");\n }\n\n get lastWeek(): string {\n return this.fromShortcut(\"lastWeek\");\n }\n\n get nextWeek(): string {\n return this.fromShortcut(\"nextWeek\");\n }\n\n get lastFortnight(): string {\n return this.fromShortcut(\"lastFortnight\");\n }\n\n get nextFortnight(): string {\n return this.fromShortcut(\"nextFortnight\");\n }\n\n private fromShortcut(shortcut: DateShortcut): string {\n return this.format(this.dateFactory.find(shortcut));\n }\n}\n","import type { DateFactory, DateShortcut } from \"./date-factory.js\";\nimport type { StandardTimeUnit } from \"./time-units.js\";\n\nexport interface IsoDateFactoryOptions {\n serializer?: (date: Date) => string;\n}\n\nexport class IsoDateFactory {\n private readonly serialise: (date: Date) => string;\n\n constructor(\n private readonly dateFactory: DateFactory,\n options: IsoDateFactoryOptions = {}\n ) {\n this.serialise = options.serializer ?? ((date) => date.toISOString());\n }\n\n make(offset: number, unit: StandardTimeUnit | string): string {\n return this.serialise(this.dateFactory.make(offset, unit));\n }\n\n fromPhrase(phrase: unknown): string {\n return this.serialise(this.dateFactory.fromPhrase(phrase));\n }\n\n get beforeYesterday(): string {\n return this.fromShortcut(\"beforeYesterday\");\n }\n\n get yesterday(): string {\n return this.fromShortcut(\"yesterday\");\n }\n\n get today(): string {\n return this.fromShortcut(\"today\");\n }\n\n get tomorrow(): string {\n return this.fromShortcut(\"tomorrow\");\n }\n\n get afterTomorrow(): string {\n return this.fromShortcut(\"afterTomorrow\");\n }\n\n get midnight(): string {\n return this.fromShortcut(\"midnight\");\n }\n\n get lastWeek(): string {\n return this.fromShortcut(\"lastWeek\");\n }\n\n get nextWeek(): string {\n return this.fromShortcut(\"nextWeek\");\n }\n\n get lastFortnight(): string {\n return this.fromShortcut(\"lastFortnight\");\n }\n\n get nextFortnight(): string {\n return this.fromShortcut(\"nextFortnight\");\n }\n\n private fromShortcut(shortcut: DateShortcut): string {\n return this.serialise(this.dateFactory.find(shortcut));\n }\n}\n","import { DateFactory, type DateFactoryOptions, type DateShortcut } from \"./date-factory.js\";\nimport { FormattedDateFactory } from \"./formatted-date-factory.js\";\nimport { IsoDateFactory } from \"./iso-date-factory.js\";\nimport type { StandardTimeUnit } from \"./time-units.js\";\n\nexport interface DatesOptions extends DateFactoryOptions {\n factory?: DateFactory;\n}\n\nexport interface DatesObject {\n readonly iso: IsoDateFactory;\n readonly fmt: FormattedDateFactory;\n readonly now: Date;\n readonly beforeYesterday: Date;\n readonly yesterday: Date;\n readonly today: Date;\n readonly tomorrow: Date;\n readonly afterTomorrow: Date;\n readonly midnight: Date;\n readonly lastWeek: Date;\n readonly nextWeek: Date;\n readonly lastFortnight: Date;\n readonly nextFortnight: Date;\n fromPhrase(phrase: unknown): Date;\n fromPhraseSafe(phrase: unknown): Date;\n make(offset: number, unit: StandardTimeUnit | string): Date;\n}\n\nclass DatesFacade implements DatesObject {\n readonly iso: IsoDateFactory;\n readonly fmt: FormattedDateFactory;\n\n constructor(private readonly factory: DateFactory) {\n this.iso = new IsoDateFactory(factory);\n this.fmt = new FormattedDateFactory(factory);\n }\n\n get now(): Date {\n return this.fromShortcut(\"now\");\n }\n\n get beforeYesterday(): Date {\n return this.fromShortcut(\"beforeYesterday\");\n }\n\n get yesterday(): Date {\n return this.fromShortcut(\"yesterday\");\n }\n\n get today(): Date {\n return this.fromShortcut(\"today\");\n }\n\n get tomorrow(): Date {\n return this.fromShortcut(\"tomorrow\");\n }\n\n get afterTomorrow(): Date {\n return this.fromShortcut(\"afterTomorrow\");\n }\n\n get midnight(): Date {\n return this.fromShortcut(\"midnight\");\n }\n\n get lastWeek(): Date {\n return this.fromShortcut(\"lastWeek\");\n }\n\n get nextWeek(): Date {\n return this.fromShortcut(\"nextWeek\");\n }\n\n get lastFortnight(): Date {\n return this.fromShortcut(\"lastFortnight\");\n }\n\n get nextFortnight(): Date {\n return this.fromShortcut(\"nextFortnight\");\n }\n\n fromPhrase(phrase: unknown): Date {\n return this.factory.fromPhrase(phrase);\n }\n\n fromPhraseSafe(phrase: unknown): Date {\n return this.factory.fromPhraseSafe(phrase);\n }\n\n make(offset: number, unit: StandardTimeUnit | string): Date {\n return this.factory.make(offset, unit);\n }\n\n private fromShortcut(shortcut: DateShortcut): Date {\n return this.factory.find(shortcut);\n }\n}\n\nexport function createDates(options: DatesOptions = {}): DatesObject {\n const factory = options.factory ?? new DateFactory(options);\n return new DatesFacade(factory);\n}\n\nexport const Dates = createDates();\nexport type { DateFactoryOptions };\n","import { AutomationError } from \"@autometa/errors\";\nimport { assertKey } from \"@autometa/asserters\";\nimport { normalizeToken } from \"../shared/phrases.js\";\n\nexport type TimeDiffFn = (start: Date, end: Date) => number;\n\nconst SUPPORTED_METHODS = [\n \"minutes\",\n \"seconds\",\n \"millis\",\n \"days\",\n \"hours\",\n \"weeks\",\n] as const;\ntype MethodName = (typeof SUPPORTED_METHODS)[number];\n\nfunction toTime(date: Date): number {\n return new Date(date).getTime();\n}\n\nexport class TimeDiff {\n minutes(start: Date, end: Date): number {\n return this.millis(start, end) / 60_000;\n }\n\n seconds(start: Date, end: Date): number {\n return this.millis(start, end) / 1_000;\n }\n\n millis(start: Date, end: Date): number {\n const distance = Math.abs(toTime(end) - toTime(start));\n return Math.round(distance);\n }\n\n days(start: Date, end: Date): number {\n return this.millis(start, end) / 86_400_000;\n }\n\n hours(start: Date, end: Date): number {\n return this.millis(start, end) / 3_600_000;\n }\n\n weeks(start: Date, end: Date): number {\n return this.millis(start, end) / 604_800_000;\n }\n\n fromPhrase(phrase: unknown): TimeDiffFn {\n if (typeof phrase !== \"string\") {\n throw new AutomationError(\n `TimeDiff.fromPhrase expects a string, received '${typeof phrase}'.`\n );\n }\n\n const key = normalizeToken(phrase);\n if (!this.hasMethod(key)) {\n throw new AutomationError(\n `Unsupported diff unit '${phrase}'. Expected one of ${this.supportedMethods().join(\", \")}.`\n );\n }\n\n assertKey(this, key as MethodName, \"TimeDiff.fromPhrase\");\n const method = this[key as MethodName];\n if (typeof method !== \"function\") {\n throw new AutomationError(`Diff method '${key}' is not callable.`);\n }\n return (method as TimeDiffFn).bind(this);\n }\n\n private hasMethod(name: string): boolean {\n return SUPPORTED_METHODS.includes(name as MethodName);\n }\n\n private supportedMethods(): MethodName[] {\n return [...SUPPORTED_METHODS];\n }\n}\n","import { TimeDiff, type TimeDiffFn } from \"./time-diff.js\";\n\nexport interface TimeFactory {\n readonly diff: TimeDiff;\n}\n\nclass TimeFacade implements TimeFactory {\n readonly diff: TimeDiff;\n\n constructor(diff: TimeDiff) {\n this.diff = diff;\n }\n}\n\nexport function createTime(): TimeFactory {\n return new TimeFacade(new TimeDiff());\n}\n\nexport const Time = createTime();\nexport { TimeDiff, type TimeDiffFn };\n"]} |
+29
-24
| { | ||
| "name": "@autometa/datetime", | ||
| "version": "0.1.16", | ||
| "description": "Date and Time utilities for Autometa", | ||
| "version": "1.0.0-rc.0", | ||
| "description": "Date and time utilities for Autometa tests", | ||
| "type": "module", | ||
| "main": "dist/index.js", | ||
| "module": "dist/esm/index.js", | ||
| "main": "dist/index.cjs", | ||
| "module": "dist/index.js", | ||
| "types": "dist/index.d.ts", | ||
| "files": [ | ||
| "dist" | ||
| ], | ||
| "exports": { | ||
| "import": "./dist/esm/index.js", | ||
| "require": "./dist/index.js", | ||
| "default": "./dist/esm/index.js", | ||
| "import": "./dist/index.js", | ||
| "require": "./dist/index.cjs", | ||
| "default": "./dist/index.js", | ||
| "types": "./dist/index.d.ts" | ||
@@ -18,33 +21,35 @@ }, | ||
| "@types/node": "^18.11.18", | ||
| "@types/uuid": "^9.0.5", | ||
| "@typescript-eslint/eslint-plugin": "^5.54.1", | ||
| "@typescript-eslint/parser": "^5.54.1", | ||
| "@vitest/coverage-istanbul": "^0.31.0", | ||
| "eslint": "^8.37.0", | ||
| "eslint-config-custom": "0.6.0", | ||
| "eslint-config-prettier": "^8.3.0", | ||
| "istanbul": "^0.4.5", | ||
| "rimraf": "^4.1.2", | ||
| "tsconfig": " *", | ||
| "tsup": "^7.2.0", | ||
| "typescript": "^4.9.5", | ||
| "vitest": "0.34.6" | ||
| "vitest": "1.4.0", | ||
| "eslint-config-custom": "0.6.0", | ||
| "tsup-config": "0.1.0", | ||
| "tsconfig": "0.7.0" | ||
| }, | ||
| "dependencies": { | ||
| "@autometa/asserters": "^0.1.8", | ||
| "@autometa/errors": "^0.2.2", | ||
| "@autometa/phrases": "^0.1.12", | ||
| "iso-datestring-validator": "^2.2.2" | ||
| "iso-datestring-validator": "^2.2.2", | ||
| "@autometa/errors": "^1.0.0-rc.0", | ||
| "@autometa/asserters": "^1.0.0-rc.0" | ||
| }, | ||
| "scripts": { | ||
| "test": "vitest run --passWithNoTests", | ||
| "type-check": "tsc --noEmit -p tsconfig.dev.json", | ||
| "type-check:watch": "tsc --noEmit --watch -p tsconfig.dev.json", | ||
| "build": "tsup && pnpm run build:types", | ||
| "build:types": "rimraf tsconfig.types.tsbuildinfo && tsc --build tsconfig.types.json", | ||
| "build:watch": "tsup --watch", | ||
| "dev": "tsup --watch", | ||
| "test": "vitest run --coverage", | ||
| "test:watch": "vitest --coverage --watch", | ||
| "test:ui": "vitest --ui --coverage", | ||
| "coverage": "vitest run --coverage", | ||
| "prettify": "prettier --config .prettierrc 'src/**/*.ts' --write", | ||
| "lint": "eslint . --max-warnings 0", | ||
| "lint:fix": "eslint . --fix", | ||
| "clean": "rimraf dist", | ||
| "build": "tsup", | ||
| "build:watch": "tsup --watch" | ||
| }, | ||
| "readme": "# Introduction\n\nThere's nothing here yet" | ||
| "prettify": "prettier --config .prettierrc 'src/**/*.ts' --write", | ||
| "clean": "rimraf dist" | ||
| } | ||
| } |
+47
-2
@@ -1,3 +0,48 @@ | ||
| # Introduction | ||
| # @autometa/datetime | ||
| There's nothing here yet | ||
| Utilities for creating deterministic dates and measuring time differences in | ||
| Autometa tests. The package provides: | ||
| - `Dates` – convenience shortcuts (yesterday, nextWeek, midnight, etc.), phrase | ||
| parsing (`"2 days from now"`) and explicit time offsets. | ||
| - `Dates.iso` / `Dates.fmt` – ISO string or YYYY-MM-DD formatted variants of the | ||
| same API surface. | ||
| - `Time.diff` – helpers for calculating the difference between two dates in | ||
| milliseconds, seconds, minutes, hours, days, or weeks. | ||
| ```ts | ||
| import { Dates, Time } from "@autometa/datetime"; | ||
| // Shortcut access | ||
| const tomorrow = Dates.tomorrow; | ||
| const nextFortnight = Dates.iso.nextFortnight; | ||
| // Phrase parsing & offsets | ||
| const launch = Dates.fromPhrase("3 weeks from now"); | ||
| const reminder = Dates.make(-2, "days"); | ||
| // Time differences | ||
| const diffInHours = Time.diff.hours(new Date(), reminder); | ||
| ``` | ||
| ## Custom clocks | ||
| For deterministic scenarios (e.g. unit tests) you can inject your own clock via | ||
| `createDates`: | ||
| ```ts | ||
| import { createDates } from "@autometa/datetime"; | ||
| const fixed = new Date("2024-01-01T08:00:00Z"); | ||
| const clock = { now: () => fixed }; | ||
| const dates = createDates({ clock }); | ||
| expect(dates.today.toISOString()).toBe("2024-01-01T08:00:00.000Z"); | ||
| ``` | ||
| ## Migration notes | ||
| - Singletons (`Dates`, `Time`) remain for convenience but now wrap factories so | ||
| you can create isolated instances with custom clocks. | ||
| - Phrase parsing errors throw `AutomationError` with actionable messaging. | ||
| - All packages enforce >=90% cobertura across statements/branches/functions. |
Sorry, the diff of this file is not supported yet
| module.exports = { | ||
| root: true, | ||
| extends: ["custom"], | ||
| }; |
-141
| # @autometa/datetime | ||
| ## 0.1.16 | ||
| ### Patch Changes | ||
| - Updated dependencies [3fe2ad4] | ||
| - @autometa/errors@0.2.2 | ||
| - @autometa/asserters@0.1.8 | ||
| - @autometa/phrases@0.1.12 | ||
| ## 0.1.15 | ||
| ### Patch Changes | ||
| - Updated dependencies [3493bb6] | ||
| - @autometa/errors@0.2.1 | ||
| - @autometa/asserters@0.1.7 | ||
| - @autometa/phrases@0.1.11 | ||
| ## 0.1.14 | ||
| ### Patch Changes | ||
| - Updated dependencies [0c070cb] | ||
| - @autometa/asserters@0.1.6 | ||
| - @autometa/phrases@0.1.10 | ||
| ## 0.1.13 | ||
| ### Patch Changes | ||
| - 6fe8f64: docs: improved typedocs on public interface | ||
| ## 0.1.12 | ||
| ### Patch Changes | ||
| - Updated dependencies [b5ce008] | ||
| - @autometa/errors@0.2.0 | ||
| - @autometa/asserters@0.1.5 | ||
| - @autometa/phrases@0.1.9 | ||
| ## 0.1.11 | ||
| ### Patch Changes | ||
| - 04ed85d: feat: added HTP client based on axios | ||
| - Updated dependencies [04ed85d] | ||
| - @autometa/asserters@0.1.4 | ||
| - @autometa/phrases@0.1.8 | ||
| - @autometa/errors@0.1.4 | ||
| ## 0.1.10 | ||
| ### Patch Changes | ||
| - 6dd05a6: Fix: Missing common properties on Dates.fmt | ||
| ## 0.1.9 | ||
| ### Patch Changes | ||
| - Release Bump | ||
| - Updated dependencies | ||
| - @autometa/phrases@0.1.7 | ||
| ## 0.1.8 | ||
| ### Patch Changes | ||
| - Updated dependencies [85050386] | ||
| - @autometa/phrases@0.1.6 | ||
| ## 0.1.7 | ||
| ### Patch Changes | ||
| - 53f958e1: Fix: steps not executing onStepEnded event when an error was thrown | ||
| - Updated dependencies [53f958e1] | ||
| - @autometa/asserters@0.1.3 | ||
| - @autometa/errors@0.1.3 | ||
| - @autometa/phrases@0.1.5 | ||
| ## 0.1.6 | ||
| ### Patch Changes | ||
| - Updated dependencies [12bd4b1e] | ||
| - @autometa/errors@0.1.2 | ||
| - @autometa/asserters@0.1.2 | ||
| - @autometa/phrases@0.1.4 | ||
| ## 0.1.5 | ||
| ### Patch Changes | ||
| - e243e8b4: fix: globally scoped hooks not executing | ||
| ## 0.1.4 | ||
| ### Patch Changes | ||
| - Updated dependencies [0cc7f6aa] | ||
| - @autometa/phrases@0.1.3 | ||
| ## 0.1.3 | ||
| ### Patch Changes | ||
| - Updated dependencies [e8f02f3a] | ||
| - @autometa/phrases@0.1.2 | ||
| - @autometa/errors@0.1.1 | ||
| - @autometa/asserters@0.1.1 | ||
| ## 0.1.2 | ||
| ### Patch Changes | ||
| - a50e99e: Fixed Dates properties returning undefine | ||
| ## 0.1.1 | ||
| ### Patch Changes | ||
| - bf23fc4: Date properties returning functions instead of Dates | ||
| - Updated dependencies [bf23fc4] | ||
| - @autometa/phrases@0.1.1 | ||
| ## 0.1.0 | ||
| ### Minor Changes | ||
| - 554b77e: Releasing packages | ||
| ### Patch Changes | ||
| - Updated dependencies [554b77e] | ||
| - @autometa/asserters@0.1.0 | ||
| - @autometa/errors@0.1.0 | ||
| - @autometa/phrases@0.1.0 |
| var __accessCheck = (obj, member, msg) => { | ||
| if (!member.has(obj)) | ||
| throw TypeError("Cannot " + msg); | ||
| }; | ||
| var __privateGet = (obj, member, getter) => { | ||
| __accessCheck(obj, member, "read from private field"); | ||
| return getter ? getter.call(obj) : member.get(obj); | ||
| }; | ||
| var __privateAdd = (obj, member, value) => { | ||
| if (member.has(obj)) | ||
| throw TypeError("Cannot add the same private member more than once"); | ||
| member instanceof WeakSet ? member.add(obj) : member.set(obj, value); | ||
| }; | ||
| var __privateMethod = (obj, member, method) => { | ||
| __accessCheck(obj, member, "access private method"); | ||
| return method; | ||
| }; | ||
| // src/dates/date-factory.ts | ||
| import { camel, convertPhrase, collapse } from "@autometa/phrases"; | ||
| // src/dates/midnight.ts | ||
| function midnight() { | ||
| const date = /* @__PURE__ */ new Date(); | ||
| date.setDate(date.getDate() + 1); | ||
| date.setHours(0, 0, 0, 0); | ||
| return date; | ||
| } | ||
| // src/dates/date-factory.ts | ||
| import { AutomationError, raise } from "@autometa/errors"; | ||
| import { ConfirmDefined, ConfirmLengthAtLeast } from "@autometa/asserters"; | ||
| import { isValidDate, isValidISODateString, isValidTime, isValidYearMonth } from "iso-datestring-validator"; | ||
| function isTimeShortcut(text) { | ||
| const converted = convertPhrase(text, camel); | ||
| const includes = [ | ||
| "now", | ||
| "beforeYesterday", | ||
| "yesterday", | ||
| "today", | ||
| "tomorrow", | ||
| "afterTomorrow", | ||
| "midnight", | ||
| "lastWeek", | ||
| "nextWeek", | ||
| "lastFortnight", | ||
| "nextFortnight" | ||
| ].includes(converted); | ||
| if (!includes) { | ||
| return false; | ||
| } | ||
| return true; | ||
| } | ||
| var _extractTimeFromPhrase, extractTimeFromPhrase_fn, _extractFutureFromPhrase, extractFutureFromPhrase_fn, _extractPastFromPhrase, extractPastFromPhrase_fn, _addYears, addYears_fn, _addMonths, addMonths_fn, _addWeeks, addWeeks_fn, _addDays, addDays_fn, _addSeconds, addSeconds_fn, _addMilliseconds, addMilliseconds_fn, _addHours, addHours_fn, _addMinutes, addMinutes_fn; | ||
| var DateFactory = class { | ||
| constructor() { | ||
| __privateAdd(this, _extractTimeFromPhrase); | ||
| __privateAdd(this, _extractFutureFromPhrase); | ||
| __privateAdd(this, _extractPastFromPhrase); | ||
| __privateAdd(this, _addYears); | ||
| __privateAdd(this, _addMonths); | ||
| __privateAdd(this, _addWeeks); | ||
| __privateAdd(this, _addDays); | ||
| __privateAdd(this, _addSeconds); | ||
| __privateAdd(this, _addMilliseconds); | ||
| __privateAdd(this, _addHours); | ||
| __privateAdd(this, _addMinutes); | ||
| this.phraseMap = /* @__PURE__ */ new Map([ | ||
| ["now", () => this.make(0, "days")], | ||
| ["beforeYesterday", () => this.make(-2, "days")], | ||
| ["yesterday", () => this.make(-1, "days")], | ||
| ["today", () => this.make(0, "days")], | ||
| ["tomorrow", () => this.make(1, "days")], | ||
| ["afterTomorrow", () => this.make(2, "days")], | ||
| ["nextWeek", () => this.make(7, "days")], | ||
| ["lastWeek", () => this.make(-7, "days")], | ||
| ["nextFortnight", () => this.make(14, "days")], | ||
| ["lastFortnight", () => this.make(-14, "days")], | ||
| ["midnight", midnight] | ||
| ]); | ||
| } | ||
| // eslint-disable-next-line @typescript-eslint/ban-types | ||
| find(name) { | ||
| const result = this.phraseMap.get(name); | ||
| if (result) { | ||
| return result(); | ||
| } | ||
| raise( | ||
| `Could not find date shortcut ${name}. Please use a valid date shortcut from the following list: ${Array.from( | ||
| this.phraseMap.keys() | ||
| ).join(", ")}` | ||
| ); | ||
| } | ||
| fromPhraseSafe(phrase) { | ||
| const name = convertPhrase(phrase, camel); | ||
| if (isTimeShortcut(name)) { | ||
| if (this.phraseMap.has(name)) { | ||
| return this.phraseMap.get(name)?.call(this); | ||
| } | ||
| } | ||
| const matchDay = __privateMethod(this, _extractTimeFromPhrase, extractTimeFromPhrase_fn).call(this, phrase); | ||
| if (matchDay) { | ||
| return matchDay; | ||
| } | ||
| const first = isValidDate(phrase); | ||
| const second = isValidISODateString(phrase); | ||
| const third = isValidTime(phrase); | ||
| const fourth = isValidYearMonth(phrase); | ||
| if (!first && !second && !third && !fourth) { | ||
| return /* @__PURE__ */ new Date("null"); | ||
| } | ||
| const parsed = new Date(phrase); | ||
| if (isNaN(parsed.getTime())) { | ||
| return new Date(Date.parse(phrase)); | ||
| } | ||
| return parsed; | ||
| } | ||
| fromPhrase(phrase) { | ||
| const result = this.fromPhraseSafe(phrase); | ||
| if (result) { | ||
| return result; | ||
| } | ||
| raise( | ||
| `Could not parse date from phrase ${phrase}. Please use a valid date string or a phrase from the following list: ${Array.from( | ||
| this.phraseMap.keys() | ||
| ).join(", ")}` | ||
| ); | ||
| } | ||
| make(timeOffset, timeunit) { | ||
| const unit = timeunit.endsWith("s") ? timeunit : `${timeunit}s`; | ||
| switch (unit) { | ||
| case "years": | ||
| return __privateMethod(this, _addYears, addYears_fn).call(this, timeOffset); | ||
| case "months": | ||
| return __privateMethod(this, _addMonths, addMonths_fn).call(this, timeOffset); | ||
| case "weeks": | ||
| return __privateMethod(this, _addWeeks, addWeeks_fn).call(this, timeOffset); | ||
| case "days": | ||
| return __privateMethod(this, _addDays, addDays_fn).call(this, timeOffset); | ||
| case "seconds": | ||
| return __privateMethod(this, _addSeconds, addSeconds_fn).call(this, timeOffset); | ||
| case "milliseconds": | ||
| return __privateMethod(this, _addMilliseconds, addMilliseconds_fn).call(this, timeOffset); | ||
| case "hours": | ||
| return __privateMethod(this, _addHours, addHours_fn).call(this, timeOffset); | ||
| case "minutes": | ||
| return __privateMethod(this, _addMinutes, addMinutes_fn).call(this, timeOffset); | ||
| default: | ||
| throw new AutomationError( | ||
| `Invalid timeunit ${timeunit}, options are 'days', 'seconds', 'milliseconds', 'hours', 'minutes'. Non plural equivalents such as 'day' or 'week' are also accepted.` | ||
| ); | ||
| } | ||
| } | ||
| }; | ||
| _extractTimeFromPhrase = new WeakSet(); | ||
| extractTimeFromPhrase_fn = function(phrase) { | ||
| return __privateMethod(this, _extractFutureFromPhrase, extractFutureFromPhrase_fn).call(this, phrase) ?? __privateMethod(this, _extractPastFromPhrase, extractPastFromPhrase_fn).call(this, phrase); | ||
| }; | ||
| _extractFutureFromPhrase = new WeakSet(); | ||
| extractFutureFromPhrase_fn = function(phrase) { | ||
| const pastPattern = /^(\d+) (.*)s? from now?/; | ||
| const pastMatch = pastPattern.exec(phrase); | ||
| if (ConfirmDefined(pastMatch) && ConfirmLengthAtLeast(pastMatch, 3)) { | ||
| const [_, value, unit] = pastMatch; | ||
| const timeunit = convertPhrase(unit, collapse); | ||
| return this.make(Number(value), timeunit); | ||
| } | ||
| }; | ||
| _extractPastFromPhrase = new WeakSet(); | ||
| extractPastFromPhrase_fn = function(phrase) { | ||
| const pastPattern = /^(\d+) (.*)(s)? ago?/gm; | ||
| const pastMatch = pastPattern.exec(phrase); | ||
| if (ConfirmDefined(pastMatch) && ConfirmLengthAtLeast(pastMatch, 3)) { | ||
| const [_, value, unit] = pastMatch; | ||
| const timeunit = convertPhrase(unit, camel); | ||
| return this.make(-Number(value), timeunit); | ||
| } | ||
| }; | ||
| _addYears = new WeakSet(); | ||
| addYears_fn = function(yearsOffset) { | ||
| const date = /* @__PURE__ */ new Date(); | ||
| date.setFullYear(date.getFullYear() + yearsOffset); | ||
| return date; | ||
| }; | ||
| _addMonths = new WeakSet(); | ||
| addMonths_fn = function(monthOffset) { | ||
| const date = /* @__PURE__ */ new Date(); | ||
| date.setMonth(date.getMonth() + monthOffset); | ||
| return date; | ||
| }; | ||
| _addWeeks = new WeakSet(); | ||
| addWeeks_fn = function(weekOffset) { | ||
| const date = /* @__PURE__ */ new Date(); | ||
| date.setMonth(date.getMonth() + weekOffset / 4); | ||
| return date; | ||
| }; | ||
| _addDays = new WeakSet(); | ||
| addDays_fn = function(daysOffset) { | ||
| const date = /* @__PURE__ */ new Date(); | ||
| date.setDate(date.getDate() + daysOffset); | ||
| return date; | ||
| }; | ||
| _addSeconds = new WeakSet(); | ||
| addSeconds_fn = function(secondsOffset) { | ||
| const date = /* @__PURE__ */ new Date(); | ||
| date.setSeconds(date.getSeconds() + secondsOffset); | ||
| return date; | ||
| }; | ||
| _addMilliseconds = new WeakSet(); | ||
| addMilliseconds_fn = function(millisecondsOffset) { | ||
| const date = /* @__PURE__ */ new Date(); | ||
| date.setMilliseconds(date.getMilliseconds() + millisecondsOffset); | ||
| return date; | ||
| }; | ||
| _addHours = new WeakSet(); | ||
| addHours_fn = function(hoursOffset) { | ||
| const date = /* @__PURE__ */ new Date(); | ||
| date.setHours(date.getHours() + hoursOffset); | ||
| return date; | ||
| }; | ||
| _addMinutes = new WeakSet(); | ||
| addMinutes_fn = function(minutesOffset) { | ||
| const date = /* @__PURE__ */ new Date(); | ||
| date.setMinutes(date.getMinutes() + minutesOffset); | ||
| return date; | ||
| }; | ||
| // src/dates/iso-date-factory.ts | ||
| var IsoDateFactory = class { | ||
| constructor(dateFactory) { | ||
| this.dateFactory = dateFactory; | ||
| this.phraseMap = /* @__PURE__ */ new Map([ | ||
| ["beforeYesterday", this.make(-2, "days")], | ||
| ["yesterday", this.make(-1, "days")], | ||
| ["today", this.make(0, "days")], | ||
| ["tomorrow", this.make(1, "days")], | ||
| ["afterTomorrow", this.make(2, "days")], | ||
| ["nextWeek", this.make(7, "days")], | ||
| ["lastWeek", this.make(-7, "days")], | ||
| ["nextFortnight", this.make(14, "days")], | ||
| ["lastFortnight", this.make(-14, "days")], | ||
| ["midnight", midnight().toISOString()] | ||
| ]); | ||
| } | ||
| make(daysOffset, timeunit) { | ||
| return this.dateFactory.make(daysOffset, timeunit).toISOString(); | ||
| } | ||
| /** | ||
| * Attempts to parse a phrase into a date. | ||
| * @param phrase | ||
| * @returns | ||
| */ | ||
| fromPhrase(phrase) { | ||
| return this.dateFactory.fromPhrase(phrase)?.toISOString(); | ||
| } | ||
| /** | ||
| * Returns the date and time of the day before yesterday | ||
| */ | ||
| get beforeYesterday() { | ||
| return this.phraseMap.get("beforeYesterday"); | ||
| } | ||
| /** | ||
| * Returns the date and time of yesterday | ||
| */ | ||
| get yesterday() { | ||
| return this.phraseMap.get("yesterday"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today | ||
| */ | ||
| get today() { | ||
| return this.phraseMap.get("today"); | ||
| } | ||
| /** | ||
| * Returns the date and time of tomorrow | ||
| */ | ||
| get tomorrow() { | ||
| return this.phraseMap.get("tomorrow"); | ||
| } | ||
| /** | ||
| * Returns the date and time of the day after tomorrow | ||
| */ | ||
| get afterTomorrow() { | ||
| return this.phraseMap.get("afterTomorrow"); | ||
| } | ||
| /** | ||
| * Returns the date and time of midnight today | ||
| */ | ||
| get midnight() { | ||
| return this.phraseMap.get("midnight"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today 1 week ago | ||
| */ | ||
| get lastWeek() { | ||
| return this.phraseMap.get("lastWeek"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today 1 week from now | ||
| */ | ||
| get nextWeek() { | ||
| return this.phraseMap.get("nextWeek"); | ||
| } | ||
| get lastFortnight() { | ||
| return this.phraseMap.get("lastFortnight"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today 1 fortnight from now | ||
| */ | ||
| get nextFortnight() { | ||
| return this.phraseMap.get("nextFortnight"); | ||
| } | ||
| }; | ||
| // src/dates/formatted-date-factory.ts | ||
| var FmtDateFactory = class { | ||
| constructor(dateFactory) { | ||
| this.dateFactory = dateFactory; | ||
| this.phraseMap = /* @__PURE__ */ new Map([ | ||
| ["beforeYesterday", this.make(-2, "days")], | ||
| ["yesterday", this.make(-1, "days")], | ||
| ["today", this.make(0, "days")], | ||
| ["tomorrow", this.make(1, "days")], | ||
| ["afterTomorrow", this.make(2, "days")], | ||
| ["nextWeek", this.make(7, "days")], | ||
| ["lastWeek", this.make(-7, "days")], | ||
| ["nextFortnight", this.make(14, "days")], | ||
| ["lastFortnight", this.make(-14, "days")], | ||
| ["midnight", midnight().toISOString()] | ||
| ]); | ||
| } | ||
| make(daysOffset, timeunit) { | ||
| return this.dateFactory.make(daysOffset, timeunit).toISOString().split("T")[0]; | ||
| } | ||
| /** | ||
| * Attempts to parse a phrase into a date. | ||
| * @param phrase | ||
| * @returns | ||
| */ | ||
| fromPhrase(phrase) { | ||
| return this.dateFactory.fromPhrase(phrase)?.toISOString().split("T")[0]; | ||
| } | ||
| /** | ||
| * Returns the date and time of the day before yesterday | ||
| */ | ||
| get beforeYesterday() { | ||
| return this.phraseMap.get("beforeYesterday"); | ||
| } | ||
| /** | ||
| * Returns the date and time of yesterday | ||
| */ | ||
| get yesterday() { | ||
| return this.phraseMap.get("yesterday"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today | ||
| */ | ||
| get today() { | ||
| return this.phraseMap.get("today"); | ||
| } | ||
| /** | ||
| * Returns the date and time of tomorrow | ||
| */ | ||
| get tomorrow() { | ||
| return this.phraseMap.get("tomorrow"); | ||
| } | ||
| /** | ||
| * Returns the date and time of the day after tomorrow | ||
| */ | ||
| get afterTomorrow() { | ||
| return this.phraseMap.get("afterTomorrow"); | ||
| } | ||
| /** | ||
| * Returns the date and time of midnight today | ||
| */ | ||
| get midnight() { | ||
| return this.phraseMap.get("midnight"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today 1 week ago | ||
| */ | ||
| get lastWeek() { | ||
| return this.phraseMap.get("lastWeek"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today 1 week from now | ||
| */ | ||
| get nextWeek() { | ||
| return this.phraseMap.get("nextWeek"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today 1 fortnight ago | ||
| */ | ||
| get lastFortnight() { | ||
| return this.phraseMap.get("lastFortnight"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today 1 fortnight from now | ||
| */ | ||
| get nextFortnight() { | ||
| return this.phraseMap.get("nextFortnight"); | ||
| } | ||
| }; | ||
| // src/dates/dates.ts | ||
| var _factory, _iso, _fmt; | ||
| var DatesObject = class { | ||
| constructor() { | ||
| __privateAdd(this, _factory, new DateFactory()); | ||
| __privateAdd(this, _iso, new IsoDateFactory(__privateGet(this, _factory))); | ||
| __privateAdd(this, _fmt, new FmtDateFactory(__privateGet(this, _factory))); | ||
| } | ||
| /** | ||
| * Switches to the ISO factory, which offers an identical interface | ||
| * but returns ISO strings instead of Date objects. | ||
| * | ||
| * Example: `2020-01-01T00:00:00.000Z` | ||
| */ | ||
| get iso() { | ||
| return __privateGet(this, _iso); | ||
| } | ||
| /** | ||
| * Switches to the formatted factory, which offers an identical interface | ||
| * but returns formatted strings instead of Date objects. | ||
| * | ||
| * Example: `2020-01-01` | ||
| */ | ||
| get fmt() { | ||
| return __privateGet(this, _fmt); | ||
| } | ||
| /** | ||
| * Returns the current date and time. | ||
| */ | ||
| get now() { | ||
| return __privateGet(this, _factory).find("now"); | ||
| } | ||
| /** | ||
| * Returns the date and time of the day before yesterday | ||
| */ | ||
| get beforeYesterday() { | ||
| return __privateGet(this, _factory).find("beforeYesterday"); | ||
| } | ||
| /** | ||
| * Returns the date and time of yesterday | ||
| */ | ||
| get yesterday() { | ||
| return __privateGet(this, _factory).find("yesterday"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today | ||
| */ | ||
| get today() { | ||
| return __privateGet(this, _factory).find("today"); | ||
| } | ||
| /** | ||
| * Returns the date and time of tomorrow | ||
| */ | ||
| get tomorrow() { | ||
| return __privateGet(this, _factory).find("tomorrow"); | ||
| } | ||
| /** | ||
| * Returns the date and time of the day after tomorrow | ||
| */ | ||
| get afterTomorrow() { | ||
| return __privateGet(this, _factory).find("afterTomorrow"); | ||
| } | ||
| /** | ||
| * Returns the date and time of midnight today | ||
| */ | ||
| get midnight() { | ||
| return __privateGet(this, _factory).find("midnight"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today 1 week ago | ||
| */ | ||
| get lastWeek() { | ||
| return __privateGet(this, _factory).find("lastWeek"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today 1 week from now | ||
| */ | ||
| get nextWeek() { | ||
| return __privateGet(this, _factory).find("nextWeek"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today 2 weeks ago | ||
| */ | ||
| get lastFortnight() { | ||
| return __privateGet(this, _factory).find("lastFortnight"); | ||
| } | ||
| /** | ||
| * Returns the date and time of today 2 weeks from now | ||
| */ | ||
| get nextFortnight() { | ||
| return __privateGet(this, _factory).find("nextFortnight"); | ||
| } | ||
| /** | ||
| * Attempts to parse a phrase into a date. | ||
| * @param phrase | ||
| * @returns | ||
| */ | ||
| fromPhrase(phrase) { | ||
| return __privateGet(this, _factory).fromPhrase(phrase); | ||
| } | ||
| /** | ||
| * Attempts to parse a phrase into a date. | ||
| * If the phrase is invalid, it will return an invalid date instead of throwing. | ||
| * @param phrase | ||
| * @returns | ||
| */ | ||
| fromPhraseSafe(phrase) { | ||
| return __privateGet(this, _factory).fromPhraseSafe(phrase); | ||
| } | ||
| make(timeOffset, timeUnit) { | ||
| return __privateGet(this, _factory).make(timeOffset, timeUnit); | ||
| } | ||
| }; | ||
| _factory = new WeakMap(); | ||
| _iso = new WeakMap(); | ||
| _fmt = new WeakMap(); | ||
| var Dates = new DatesObject(); | ||
| // src/time/time.ts | ||
| import { AssertKey } from "@autometa/asserters"; | ||
| import { convertPhrase as convertPhrase2, lower } from "@autometa/phrases"; | ||
| var TimeDiff = class { | ||
| minutes(date1, date2) { | ||
| return this.millis(date1, date2) / 6e4; | ||
| } | ||
| seconds(date1, date2) { | ||
| return this.millis(date1, date2) / 1e3; | ||
| } | ||
| millis(date1, date2) { | ||
| const d1 = new Date(date1).getTime(); | ||
| const d2 = new Date(date2).getTime(); | ||
| return Math.abs(Math.round(d2 - d1)); | ||
| } | ||
| days(date1, date2) { | ||
| return this.millis(date1, date2) / 864e5; | ||
| } | ||
| hours(date1, date2) { | ||
| return this.millis(date1, date2) / 36e5; | ||
| } | ||
| weeks(date1, date2) { | ||
| return this.millis(date1, date2) / 6048e5; | ||
| } | ||
| fromPhrase(phrase) { | ||
| const propertyKey = convertPhrase2(phrase, lower); | ||
| AssertKey(this, propertyKey); | ||
| return this[propertyKey].bind(this); | ||
| } | ||
| }; | ||
| var _diff; | ||
| var TimeObject = class { | ||
| constructor() { | ||
| __privateAdd(this, _diff, new TimeDiff()); | ||
| } | ||
| get diff() { | ||
| return __privateGet(this, _diff); | ||
| } | ||
| }; | ||
| _diff = new WeakMap(); | ||
| var Time = new TimeObject(); | ||
| export { | ||
| DateFactory, | ||
| Dates, | ||
| FmtDateFactory, | ||
| IsoDateFactory, | ||
| Time, | ||
| TimeDiff, | ||
| TimeObject | ||
| }; | ||
| //# sourceMappingURL=index.js.map |
| {"version":3,"sources":["../../src/dates/date-factory.ts","../../src/dates/midnight.ts","../../src/dates/iso-date-factory.ts","../../src/dates/formatted-date-factory.ts","../../src/dates/dates.ts","../../src/time/time.ts"],"sourcesContent":["import { TimeUnit, camel, convertPhrase, collapse } from \"@autometa/phrases\";\nimport { midnight } from \"./midnight\";\nimport { AutomationError, raise } from \"@autometa/errors\";\nimport { ConfirmDefined, ConfirmLengthAtLeast } from \"@autometa/asserters\";\nimport { isValidDate, isValidISODateString, isValidTime, isValidYearMonth } from \"iso-datestring-validator\";\ntype TimeShortcut =\n | \"now\"\n | \"beforeYesterday\"\n | \"yesterday\"\n | \"today\"\n | \"tomorrow\"\n | \"afterTomorrow\"\n | \"midnight\"\n | \"lastWeek\"\n | \"nextWeek\"\n | \"lastFortnight\"\n | \"nextFortnight\";\n\nfunction isTimeShortcut(text: string): text is TimeShortcut {\n const converted = convertPhrase(text, camel);\n const includes = [\n \"now\",\n \"beforeYesterday\",\n \"yesterday\",\n \"today\",\n \"tomorrow\",\n \"afterTomorrow\",\n \"midnight\",\n \"lastWeek\",\n \"nextWeek\",\n \"lastFortnight\",\n \"nextFortnight\"\n ].includes(converted);\n if (!includes) {\n return false;\n }\n return true;\n}\nexport class DateFactory {\n phraseMap = new Map<TimeShortcut, () => Date>([\n [\"now\", () => this.make(0, \"days\")],\n [\"beforeYesterday\", () => this.make(-2, \"days\")],\n [\"yesterday\", () => this.make(-1, \"days\")],\n [\"today\", () => this.make(0, \"days\")],\n [\"tomorrow\", () => this.make(1, \"days\")],\n [\"afterTomorrow\", () => this.make(2, \"days\")],\n [\"nextWeek\", () => this.make(7, \"days\")],\n [\"lastWeek\", () => this.make(-7, \"days\")],\n [\"nextFortnight\", () => this.make(14, \"days\")],\n [\"lastFortnight\", () => this.make(-14, \"days\")],\n [\"midnight\", midnight]\n ]);\n\n // eslint-disable-next-line @typescript-eslint/ban-types\n find(name: TimeShortcut): Date {\n const result = this.phraseMap.get(name);\n if (result) {\n return result();\n }\n raise(\n `Could not find date shortcut ${name}. Please use a valid date shortcut from the following list: ${Array.from(\n this.phraseMap.keys()\n ).join(\", \")}`\n );\n }\n\n fromPhraseSafe(phrase: string) {\n const name = convertPhrase(phrase, camel);\n if (isTimeShortcut(name)) {\n if (this.phraseMap.has(name)) {\n return this.phraseMap.get(name)?.call(this);\n }\n }\n \n const matchDay = this.#extractTimeFromPhrase(phrase);\n if (matchDay) {\n return matchDay;\n }\n const first = isValidDate(phrase);\n const second = isValidISODateString(phrase);\n const third = isValidTime(phrase);\n const fourth = isValidYearMonth(phrase);\n if (!first && !second && !third && !fourth) {\n return new Date(\"null\");\n }\n const parsed = new Date(phrase);\n if (isNaN(parsed.getTime())) {\n return new Date(Date.parse(phrase));\n }\n return parsed;\n }\n fromPhrase(phrase: string) {\n const result = this.fromPhraseSafe(phrase);\n if (result) {\n return result;\n }\n raise(\n `Could not parse date from phrase ${phrase}. Please use a valid date string or a phrase from the following list: ${Array.from(\n this.phraseMap.keys()\n ).join(\", \")}`\n );\n }\n make(timeOffset: number, timeunit: TimeUnit) {\n const unit = timeunit.endsWith(\"s\") ? timeunit : `${timeunit}s`;\n switch (unit) {\n case \"years\":\n return this.#addYears(timeOffset);\n case \"months\":\n return this.#addMonths(timeOffset);\n case \"weeks\":\n return this.#addWeeks(timeOffset);\n case \"days\":\n return this.#addDays(timeOffset);\n case \"seconds\":\n return this.#addSeconds(timeOffset);\n case \"milliseconds\":\n return this.#addMilliseconds(timeOffset);\n case \"hours\":\n return this.#addHours(timeOffset);\n case \"minutes\":\n return this.#addMinutes(timeOffset);\n default:\n throw new AutomationError(\n `Invalid timeunit ${timeunit}, options are 'days', 'seconds', 'milliseconds', 'hours', 'minutes'. Non plural equivalents such as 'day' or 'week' are also accepted.`\n );\n }\n }\n #extractTimeFromPhrase(phrase: string) {\n return (\n this.#extractFutureFromPhrase(phrase) ??\n this.#extractPastFromPhrase(phrase)\n );\n }\n #extractFutureFromPhrase(phrase: string) {\n const pastPattern = /^(\\d+) (.*)s? from now?/;\n const pastMatch = pastPattern.exec(phrase);\n\n if (ConfirmDefined(pastMatch) && ConfirmLengthAtLeast(pastMatch, 3)) {\n const [_, value, unit] = pastMatch;\n const timeunit = convertPhrase(unit, collapse) as TimeUnit;\n return this.make(Number(value), timeunit);\n }\n }\n #extractPastFromPhrase(phrase: string) {\n const pastPattern = /^(\\d+) (.*)(s)? ago?/gm;\n const pastMatch = pastPattern.exec(phrase);\n if (ConfirmDefined(pastMatch) && ConfirmLengthAtLeast(pastMatch, 3)) {\n const [_, value, unit] = pastMatch;\n const timeunit = convertPhrase(unit, camel) as TimeUnit;\n return this.make(-Number(value), timeunit);\n }\n }\n #addYears(yearsOffset: number) {\n const date = new Date();\n date.setFullYear(date.getFullYear() + yearsOffset);\n return date;\n }\n #addMonths(monthOffset: number) {\n const date = new Date();\n date.setMonth(date.getMonth() + monthOffset);\n return date;\n }\n #addWeeks(weekOffset: number) {\n const date = new Date();\n date.setMonth(date.getMonth() + weekOffset / 4);\n return date;\n }\n #addDays(daysOffset: number) {\n const date = new Date();\n date.setDate(date.getDate() + daysOffset);\n return date;\n }\n\n #addSeconds(secondsOffset: number) {\n const date = new Date();\n date.setSeconds(date.getSeconds() + secondsOffset);\n return date;\n }\n\n #addMilliseconds(millisecondsOffset: number) {\n const date = new Date();\n date.setMilliseconds(date.getMilliseconds() + millisecondsOffset);\n return date;\n }\n #addHours(hoursOffset: number) {\n const date = new Date();\n date.setHours(date.getHours() + hoursOffset);\n return date;\n }\n #addMinutes(minutesOffset: number) {\n const date = new Date();\n date.setMinutes(date.getMinutes() + minutesOffset);\n return date;\n }\n}\n","\nexport function midnight() {\n const date = new Date();\n date.setDate(date.getDate() + 1);\n date.setHours(0, 0, 0, 0);\n return date;\n}\n","import { TimeUnit } from '@autometa/phrases';\nimport { midnight } from './midnight';\nimport { DateFactory } from './date-factory';\n\n\nexport class IsoDateFactory {\n constructor(readonly dateFactory: DateFactory) { }\n phraseMap = new Map<string, string>([\n ['beforeYesterday', this.make(-2, 'days')],\n ['yesterday', this.make(-1, 'days')],\n ['today', this.make(0, 'days')],\n ['tomorrow', this.make(1, 'days')],\n ['afterTomorrow', this.make(2, 'days')],\n ['nextWeek', this.make(7, 'days')],\n ['lastWeek', this.make(-7, 'days')],\n ['nextFortnight', this.make(14, 'days')],\n ['lastFortnight', this.make(-14, 'days')],\n ['midnight', midnight().toISOString()],\n ]);\n make(daysOffset: number, timeunit: TimeUnit) {\n return this.dateFactory.make(daysOffset, timeunit).toISOString();\n }\n\n /**\n * Attempts to parse a phrase into a date.\n * @param phrase\n * @returns\n */\n fromPhrase(phrase: string) {\n return this.dateFactory.fromPhrase(phrase)?.toISOString();\n }\n\n /**\n * Returns the date and time of the day before yesterday\n */\n get beforeYesterday() {\n return this.phraseMap.get('beforeYesterday');\n }\n\n /**\n * Returns the date and time of yesterday\n */\n get yesterday() {\n return this.phraseMap.get('yesterday');\n }\n\n /**\n * Returns the date and time of today\n */\n get today() {\n return this.phraseMap.get('today');\n }\n\n /**\n * Returns the date and time of tomorrow\n */\n get tomorrow() {\n return this.phraseMap.get('tomorrow');\n }\n\n /**\n * Returns the date and time of the day after tomorrow\n */\n get afterTomorrow() {\n return this.phraseMap.get('afterTomorrow');\n }\n\n /**\n * Returns the date and time of midnight today\n */\n get midnight() {\n return this.phraseMap.get('midnight');\n }\n\n /**\n * Returns the date and time of today 1 week ago\n */\n get lastWeek() {\n return this.phraseMap.get('lastWeek');\n }\n\n /**\n * Returns the date and time of today 1 week from now\n */\n get nextWeek() {\n return this.phraseMap.get('nextWeek');\n }\n get lastFortnight() {\n return this.phraseMap.get('lastFortnight');\n }\n\n /**\n * Returns the date and time of today 1 fortnight from now\n */\n get nextFortnight() {\n return this.phraseMap.get('nextFortnight');\n }\n}\n","import { TimeUnit } from '@autometa/phrases';\nimport { DateFactory } from './date-factory';\nimport { midnight } from './midnight';\n\nexport class FmtDateFactory {\n constructor(readonly dateFactory: DateFactory) { }\n phraseMap = new Map<string, string>([\n ['beforeYesterday', this.make(-2, 'days')],\n ['yesterday', this.make(-1, 'days')],\n ['today', this.make(0, 'days')],\n ['tomorrow', this.make(1, 'days')],\n ['afterTomorrow', this.make(2, 'days')],\n ['nextWeek', this.make(7, 'days')],\n ['lastWeek', this.make(-7, 'days')],\n ['nextFortnight', this.make(14, 'days')],\n ['lastFortnight', this.make(-14, 'days')],\n ['midnight', midnight().toISOString()],\n ]);\n\n make(daysOffset: number, timeunit: TimeUnit) {\n return this.dateFactory\n .make(daysOffset, timeunit)\n .toISOString()\n .split('T')[0];\n }\n \n /**\n * Attempts to parse a phrase into a date.\n * @param phrase\n * @returns\n */\n fromPhrase(phrase: string) {\n return this.dateFactory.fromPhrase(phrase)?.toISOString().split('T')[0];\n }\n\n /**\n * Returns the date and time of the day before yesterday\n */\n get beforeYesterday() {\n return this.phraseMap.get('beforeYesterday');\n }\n\n /**\n * Returns the date and time of yesterday\n */\n get yesterday() {\n return this.phraseMap.get('yesterday');\n }\n\n /**\n * Returns the date and time of today\n */\n get today() {\n return this.phraseMap.get('today');\n }\n\n /**\n * Returns the date and time of tomorrow\n */\n get tomorrow() {\n return this.phraseMap.get('tomorrow');\n }\n\n /**\n * Returns the date and time of the day after tomorrow\n */\n get afterTomorrow() {\n return this.phraseMap.get('afterTomorrow');\n }\n\n /**\n * Returns the date and time of midnight today\n */\n get midnight() {\n return this.phraseMap.get('midnight');\n }\n\n /**\n * Returns the date and time of today 1 week ago\n */\n get lastWeek() {\n return this.phraseMap.get('lastWeek');\n }\n\n /**\n * Returns the date and time of today 1 week from now\n */\n get nextWeek() {\n return this.phraseMap.get('nextWeek');\n }\n\n /**\n * Returns the date and time of today 1 fortnight ago\n */\n get lastFortnight() {\n return this.phraseMap.get('lastFortnight');\n }\n\n /**\n * Returns the date and time of today 1 fortnight from now\n */\n get nextFortnight() {\n return this.phraseMap.get('nextFortnight');\n }\n}\n","import { DateFactory } from \"./date-factory\";\nimport { IsoDateFactory } from \"./iso-date-factory\";\nimport { FmtDateFactory } from \"./formatted-date-factory\";\nimport { TimeUnit } from \"@autometa/phrases\";\n\nexport class DatesObject {\n #factory: DateFactory = new DateFactory();\n #iso = new IsoDateFactory(this.#factory);\n #fmt = new FmtDateFactory(this.#factory);\n /**\n * Switches to the ISO factory, which offers an identical interface\n * but returns ISO strings instead of Date objects.\n * \n * Example: `2020-01-01T00:00:00.000Z`\n */\n get iso() {\n return this.#iso;\n }\n\n /**\n * Switches to the formatted factory, which offers an identical interface\n * but returns formatted strings instead of Date objects.\n * \n * Example: `2020-01-01`\n */\n get fmt() {\n return this.#fmt;\n }\n\n /**\n * Returns the current date and time.\n */\n get now() {\n return this.#factory.find(\"now\");\n }\n\n /**\n * Returns the date and time of the day before yesterday\n */\n get beforeYesterday(): Date {\n return this.#factory.find(\"beforeYesterday\");\n }\n \n /**\n * Returns the date and time of yesterday\n */\n get yesterday(): Date {\n return this.#factory.find(\"yesterday\");\n }\n\n /**\n * Returns the date and time of today\n */\n get today(): Date {\n return this.#factory.find(\"today\");\n }\n\n /**\n * Returns the date and time of tomorrow\n */\n get tomorrow(): Date {\n return this.#factory.find(\"tomorrow\");\n }\n\n /**\n * Returns the date and time of the day after tomorrow\n */\n get afterTomorrow(): Date {\n return this.#factory.find(\"afterTomorrow\");\n }\n\n /**\n * Returns the date and time of midnight today\n */\n get midnight(): Date {\n return this.#factory.find(\"midnight\");\n }\n\n /**\n * Returns the date and time of today 1 week ago\n */\n get lastWeek(): Date {\n return this.#factory.find(\"lastWeek\");\n }\n\n /**\n * Returns the date and time of today 1 week from now\n */\n get nextWeek(): Date {\n return this.#factory.find(\"nextWeek\");\n }\n\n /**\n * Returns the date and time of today 2 weeks ago\n */\n get lastFortnight(): Date {\n return this.#factory.find(\"lastFortnight\");\n }\n\n /**\n * Returns the date and time of today 2 weeks from now\n */\n get nextFortnight(): Date {\n return this.#factory.find(\"nextFortnight\");\n }\n\n /**\n * Attempts to parse a phrase into a date.\n * @param phrase \n * @returns \n */\n fromPhrase(phrase: string) {\n return this.#factory.fromPhrase(phrase);\n }\n\n /**\n * Attempts to parse a phrase into a date.\n * If the phrase is invalid, it will return an invalid date instead of throwing.\n * @param phrase \n * @returns \n */\n fromPhraseSafe(phrase: string) {\n return this.#factory.fromPhraseSafe(phrase);\n }\n\n make(timeOffset: number, timeUnit: TimeUnit) {\n return this.#factory.make(timeOffset, timeUnit);\n }\n}\n\n/**\n * Date utility option to easily generate common\n * dates around the current date, like 'today', 'midnight',\n * 'tomorrow', 'nextWeek', etc.\n * \n * The Dates utility also supports certain language phrases\n * that might be natural in Cucumber's gherkin syntax, like\n * 'next week', 'last week', 'next fortnight', etc. as well\n * as more dynamic phrases like `1 day ago`, `2 weeks from now`,\n */\nexport const Dates = new DatesObject();\n","import { AssertKey } from \"@autometa/asserters\";\nimport { convertPhrase, lower } from \"@autometa/phrases\";\ntype TimeDiffFn = (date1: Date, date2: Date) => number;\n\nexport class TimeDiff {\n minutes(date1: Date, date2: Date) {\n return this.millis(date1, date2) / 60000;\n }\n seconds(date1: Date, date2: Date) {\n return this.millis(date1, date2) / 1000;\n }\n millis(date1: Date, date2: Date) {\n const d1 = new Date(date1).getTime();\n const d2 = new Date(date2).getTime();\n return Math.abs(Math.round(d2 - d1));\n }\n days(date1: Date, date2: Date) {\n return this.millis(date1, date2) / 86400000;\n }\n hours(date1: Date, date2: Date) {\n return this.millis(date1, date2) / 3600000;\n }\n weeks(date1: Date, date2: Date) {\n return this.millis(date1, date2) / 604800000;\n }\n fromPhrase(phrase: string): TimeDiffFn {\n const propertyKey = convertPhrase(phrase, lower);\n AssertKey(this, propertyKey);\n return (this[propertyKey] as TimeDiffFn).bind(this);\n }\n}\n\nexport class TimeObject {\n #diff = new TimeDiff();\n get diff() {\n return this.#diff;\n }\n}\n\nexport const Time = new TimeObject();\n"],"mappings":"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","names":["convertPhrase","convertPhrase"]} |
-219
| import { TimeUnit } from '@autometa/phrases'; | ||
| type TimeShortcut = "now" | "beforeYesterday" | "yesterday" | "today" | "tomorrow" | "afterTomorrow" | "midnight" | "lastWeek" | "nextWeek" | "lastFortnight" | "nextFortnight"; | ||
| declare class DateFactory { | ||
| #private; | ||
| phraseMap: Map<TimeShortcut, () => Date>; | ||
| find(name: TimeShortcut): Date; | ||
| fromPhraseSafe(phrase: string): Date | undefined; | ||
| fromPhrase(phrase: string): Date; | ||
| make(timeOffset: number, timeunit: TimeUnit): Date; | ||
| } | ||
| declare class IsoDateFactory { | ||
| readonly dateFactory: DateFactory; | ||
| constructor(dateFactory: DateFactory); | ||
| phraseMap: Map<string, string>; | ||
| make(daysOffset: number, timeunit: TimeUnit): string; | ||
| /** | ||
| * Attempts to parse a phrase into a date. | ||
| * @param phrase | ||
| * @returns | ||
| */ | ||
| fromPhrase(phrase: string): string; | ||
| /** | ||
| * Returns the date and time of the day before yesterday | ||
| */ | ||
| get beforeYesterday(): string | undefined; | ||
| /** | ||
| * Returns the date and time of yesterday | ||
| */ | ||
| get yesterday(): string | undefined; | ||
| /** | ||
| * Returns the date and time of today | ||
| */ | ||
| get today(): string | undefined; | ||
| /** | ||
| * Returns the date and time of tomorrow | ||
| */ | ||
| get tomorrow(): string | undefined; | ||
| /** | ||
| * Returns the date and time of the day after tomorrow | ||
| */ | ||
| get afterTomorrow(): string | undefined; | ||
| /** | ||
| * Returns the date and time of midnight today | ||
| */ | ||
| get midnight(): string | undefined; | ||
| /** | ||
| * Returns the date and time of today 1 week ago | ||
| */ | ||
| get lastWeek(): string | undefined; | ||
| /** | ||
| * Returns the date and time of today 1 week from now | ||
| */ | ||
| get nextWeek(): string | undefined; | ||
| get lastFortnight(): string | undefined; | ||
| /** | ||
| * Returns the date and time of today 1 fortnight from now | ||
| */ | ||
| get nextFortnight(): string | undefined; | ||
| } | ||
| declare class FmtDateFactory { | ||
| readonly dateFactory: DateFactory; | ||
| constructor(dateFactory: DateFactory); | ||
| phraseMap: Map<string, string>; | ||
| make(daysOffset: number, timeunit: TimeUnit): string; | ||
| /** | ||
| * Attempts to parse a phrase into a date. | ||
| * @param phrase | ||
| * @returns | ||
| */ | ||
| fromPhrase(phrase: string): string; | ||
| /** | ||
| * Returns the date and time of the day before yesterday | ||
| */ | ||
| get beforeYesterday(): string | undefined; | ||
| /** | ||
| * Returns the date and time of yesterday | ||
| */ | ||
| get yesterday(): string | undefined; | ||
| /** | ||
| * Returns the date and time of today | ||
| */ | ||
| get today(): string | undefined; | ||
| /** | ||
| * Returns the date and time of tomorrow | ||
| */ | ||
| get tomorrow(): string | undefined; | ||
| /** | ||
| * Returns the date and time of the day after tomorrow | ||
| */ | ||
| get afterTomorrow(): string | undefined; | ||
| /** | ||
| * Returns the date and time of midnight today | ||
| */ | ||
| get midnight(): string | undefined; | ||
| /** | ||
| * Returns the date and time of today 1 week ago | ||
| */ | ||
| get lastWeek(): string | undefined; | ||
| /** | ||
| * Returns the date and time of today 1 week from now | ||
| */ | ||
| get nextWeek(): string | undefined; | ||
| /** | ||
| * Returns the date and time of today 1 fortnight ago | ||
| */ | ||
| get lastFortnight(): string | undefined; | ||
| /** | ||
| * Returns the date and time of today 1 fortnight from now | ||
| */ | ||
| get nextFortnight(): string | undefined; | ||
| } | ||
| declare class DatesObject { | ||
| #private; | ||
| /** | ||
| * Switches to the ISO factory, which offers an identical interface | ||
| * but returns ISO strings instead of Date objects. | ||
| * | ||
| * Example: `2020-01-01T00:00:00.000Z` | ||
| */ | ||
| get iso(): IsoDateFactory; | ||
| /** | ||
| * Switches to the formatted factory, which offers an identical interface | ||
| * but returns formatted strings instead of Date objects. | ||
| * | ||
| * Example: `2020-01-01` | ||
| */ | ||
| get fmt(): FmtDateFactory; | ||
| /** | ||
| * Returns the current date and time. | ||
| */ | ||
| get now(): Date; | ||
| /** | ||
| * Returns the date and time of the day before yesterday | ||
| */ | ||
| get beforeYesterday(): Date; | ||
| /** | ||
| * Returns the date and time of yesterday | ||
| */ | ||
| get yesterday(): Date; | ||
| /** | ||
| * Returns the date and time of today | ||
| */ | ||
| get today(): Date; | ||
| /** | ||
| * Returns the date and time of tomorrow | ||
| */ | ||
| get tomorrow(): Date; | ||
| /** | ||
| * Returns the date and time of the day after tomorrow | ||
| */ | ||
| get afterTomorrow(): Date; | ||
| /** | ||
| * Returns the date and time of midnight today | ||
| */ | ||
| get midnight(): Date; | ||
| /** | ||
| * Returns the date and time of today 1 week ago | ||
| */ | ||
| get lastWeek(): Date; | ||
| /** | ||
| * Returns the date and time of today 1 week from now | ||
| */ | ||
| get nextWeek(): Date; | ||
| /** | ||
| * Returns the date and time of today 2 weeks ago | ||
| */ | ||
| get lastFortnight(): Date; | ||
| /** | ||
| * Returns the date and time of today 2 weeks from now | ||
| */ | ||
| get nextFortnight(): Date; | ||
| /** | ||
| * Attempts to parse a phrase into a date. | ||
| * @param phrase | ||
| * @returns | ||
| */ | ||
| fromPhrase(phrase: string): Date; | ||
| /** | ||
| * Attempts to parse a phrase into a date. | ||
| * If the phrase is invalid, it will return an invalid date instead of throwing. | ||
| * @param phrase | ||
| * @returns | ||
| */ | ||
| fromPhraseSafe(phrase: string): Date | undefined; | ||
| make(timeOffset: number, timeUnit: TimeUnit): Date; | ||
| } | ||
| /** | ||
| * Date utility option to easily generate common | ||
| * dates around the current date, like 'today', 'midnight', | ||
| * 'tomorrow', 'nextWeek', etc. | ||
| * | ||
| * The Dates utility also supports certain language phrases | ||
| * that might be natural in Cucumber's gherkin syntax, like | ||
| * 'next week', 'last week', 'next fortnight', etc. as well | ||
| * as more dynamic phrases like `1 day ago`, `2 weeks from now`, | ||
| */ | ||
| declare const Dates: DatesObject; | ||
| type TimeDiffFn = (date1: Date, date2: Date) => number; | ||
| declare class TimeDiff { | ||
| minutes(date1: Date, date2: Date): number; | ||
| seconds(date1: Date, date2: Date): number; | ||
| millis(date1: Date, date2: Date): number; | ||
| days(date1: Date, date2: Date): number; | ||
| hours(date1: Date, date2: Date): number; | ||
| weeks(date1: Date, date2: Date): number; | ||
| fromPhrase(phrase: string): TimeDiffFn; | ||
| } | ||
| declare class TimeObject { | ||
| #private; | ||
| get diff(): TimeDiff; | ||
| } | ||
| declare const Time: TimeObject; | ||
| export { DateFactory, Dates, FmtDateFactory, IsoDateFactory, Time, TimeDiff, TimeObject }; |
| import { defineConfig } from "tsup"; | ||
| export default defineConfig({ | ||
| clean: true, // clean up the dist folder | ||
| sourcemap:true, // generate sourcemaps | ||
| format: ["cjs", "esm"], // generate cjs and esm files | ||
| dts: true, | ||
| skipNodeModulesBundle: true, | ||
| entryPoints: ["src/index.ts"], | ||
| target: "es2020", | ||
| outDir: "dist", | ||
| legacyOutput: true, | ||
| external: ["dist"], | ||
| }); |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
3
-25%12
-14.29%17
30.77%48
1500%92217
-12.53%1066
-23.47%1
Infinity%+ Added
+ Added
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
- Removed
Updated