@autometa/datetime 0.1.15 → 1.0.0-rc.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +47 -2
- package/dist/dates/clock.d.ts +5 -0
- package/dist/dates/date-factory.d.ts +20 -0
- package/dist/dates/formatted-date-factory.d.ts +23 -0
- package/dist/dates/iso-date-factory.d.ts +23 -0
- package/dist/dates/object.d.ts +28 -0
- package/dist/dates/time-units.d.ts +6 -0
- package/dist/index.cjs +482 -0
- package/dist/index.cjs.map +1 -0
- package/dist/index.d.ts +6 -219
- package/dist/index.js +349 -481
- package/dist/index.js.map +1 -1
- package/dist/shared/phrases.d.ts +2 -0
- package/dist/time/time-diff.d.ts +12 -0
- package/dist/time/time.d.ts +7 -0
- package/package.json +29 -24
- package/.eslintignore +0 -3
- package/.eslintrc.cjs +0 -4
- package/CHANGELOG.md +0 -132
- package/dist/esm/index.js +0 -573
- package/dist/esm/index.js.map +0 -1
- package/dist/index.d.cts +0 -219
- package/tsup.config.ts +0 -14
package/README.md
CHANGED
|
@@ -1,3 +1,48 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @autometa/datetime
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
Utilities for creating deterministic dates and measuring time differences in
|
|
4
|
+
Autometa tests. The package provides:
|
|
5
|
+
|
|
6
|
+
- `Dates` – convenience shortcuts (yesterday, nextWeek, midnight, etc.), phrase
|
|
7
|
+
parsing (`"2 days from now"`) and explicit time offsets.
|
|
8
|
+
- `Dates.iso` / `Dates.fmt` – ISO string or YYYY-MM-DD formatted variants of the
|
|
9
|
+
same API surface.
|
|
10
|
+
- `Time.diff` – helpers for calculating the difference between two dates in
|
|
11
|
+
milliseconds, seconds, minutes, hours, days, or weeks.
|
|
12
|
+
|
|
13
|
+
```ts
|
|
14
|
+
import { Dates, Time } from "@autometa/datetime";
|
|
15
|
+
|
|
16
|
+
// Shortcut access
|
|
17
|
+
const tomorrow = Dates.tomorrow;
|
|
18
|
+
const nextFortnight = Dates.iso.nextFortnight;
|
|
19
|
+
|
|
20
|
+
// Phrase parsing & offsets
|
|
21
|
+
const launch = Dates.fromPhrase("3 weeks from now");
|
|
22
|
+
const reminder = Dates.make(-2, "days");
|
|
23
|
+
|
|
24
|
+
// Time differences
|
|
25
|
+
const diffInHours = Time.diff.hours(new Date(), reminder);
|
|
26
|
+
```
|
|
27
|
+
|
|
28
|
+
## Custom clocks
|
|
29
|
+
|
|
30
|
+
For deterministic scenarios (e.g. unit tests) you can inject your own clock via
|
|
31
|
+
`createDates`:
|
|
32
|
+
|
|
33
|
+
```ts
|
|
34
|
+
import { createDates } from "@autometa/datetime";
|
|
35
|
+
|
|
36
|
+
const fixed = new Date("2024-01-01T08:00:00Z");
|
|
37
|
+
const clock = { now: () => fixed };
|
|
38
|
+
|
|
39
|
+
const dates = createDates({ clock });
|
|
40
|
+
expect(dates.today.toISOString()).toBe("2024-01-01T08:00:00.000Z");
|
|
41
|
+
```
|
|
42
|
+
|
|
43
|
+
## Migration notes
|
|
44
|
+
|
|
45
|
+
- Singletons (`Dates`, `Time`) remain for convenience but now wrap factories so
|
|
46
|
+
you can create isolated instances with custom clocks.
|
|
47
|
+
- Phrase parsing errors throw `AutomationError` with actionable messaging.
|
|
48
|
+
- All packages enforce >=90% cobertura across statements/branches/functions.
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import type { Clock } from "./clock.js";
|
|
2
|
+
import { type StandardTimeUnit } from "./time-units.js";
|
|
3
|
+
export type DateShortcut = "now" | "beforeYesterday" | "yesterday" | "today" | "tomorrow" | "afterTomorrow" | "midnight" | "lastWeek" | "nextWeek" | "lastFortnight" | "nextFortnight";
|
|
4
|
+
export interface DateFactoryOptions {
|
|
5
|
+
clock?: Clock;
|
|
6
|
+
}
|
|
7
|
+
export declare class DateFactory {
|
|
8
|
+
private readonly clock;
|
|
9
|
+
constructor(options?: DateFactoryOptions);
|
|
10
|
+
find(shortcut: DateShortcut): Date;
|
|
11
|
+
fromPhraseSafe(phrase: unknown): Date;
|
|
12
|
+
fromPhrase(phrase: unknown): Date;
|
|
13
|
+
make(timeOffset: number, timeUnit: string | StandardTimeUnit): Date;
|
|
14
|
+
private currentDate;
|
|
15
|
+
private midnight;
|
|
16
|
+
private parseDate;
|
|
17
|
+
private isDateLike;
|
|
18
|
+
private extractRelative;
|
|
19
|
+
private buildRelativeMatch;
|
|
20
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { DateFactory } from "./date-factory.js";
|
|
2
|
+
import type { StandardTimeUnit } from "./time-units.js";
|
|
3
|
+
export interface FormattedDateFactoryOptions {
|
|
4
|
+
formatter?: (date: Date) => string;
|
|
5
|
+
}
|
|
6
|
+
export declare class FormattedDateFactory {
|
|
7
|
+
private readonly dateFactory;
|
|
8
|
+
private readonly format;
|
|
9
|
+
constructor(dateFactory: DateFactory, options?: FormattedDateFactoryOptions);
|
|
10
|
+
make(offset: number, unit: StandardTimeUnit | string): string;
|
|
11
|
+
fromPhrase(phrase: unknown): string;
|
|
12
|
+
get beforeYesterday(): string;
|
|
13
|
+
get yesterday(): string;
|
|
14
|
+
get today(): string;
|
|
15
|
+
get tomorrow(): string;
|
|
16
|
+
get afterTomorrow(): string;
|
|
17
|
+
get midnight(): string;
|
|
18
|
+
get lastWeek(): string;
|
|
19
|
+
get nextWeek(): string;
|
|
20
|
+
get lastFortnight(): string;
|
|
21
|
+
get nextFortnight(): string;
|
|
22
|
+
private fromShortcut;
|
|
23
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
import type { DateFactory } from "./date-factory.js";
|
|
2
|
+
import type { StandardTimeUnit } from "./time-units.js";
|
|
3
|
+
export interface IsoDateFactoryOptions {
|
|
4
|
+
serializer?: (date: Date) => string;
|
|
5
|
+
}
|
|
6
|
+
export declare class IsoDateFactory {
|
|
7
|
+
private readonly dateFactory;
|
|
8
|
+
private readonly serialise;
|
|
9
|
+
constructor(dateFactory: DateFactory, options?: IsoDateFactoryOptions);
|
|
10
|
+
make(offset: number, unit: StandardTimeUnit | string): string;
|
|
11
|
+
fromPhrase(phrase: unknown): string;
|
|
12
|
+
get beforeYesterday(): string;
|
|
13
|
+
get yesterday(): string;
|
|
14
|
+
get today(): string;
|
|
15
|
+
get tomorrow(): string;
|
|
16
|
+
get afterTomorrow(): string;
|
|
17
|
+
get midnight(): string;
|
|
18
|
+
get lastWeek(): string;
|
|
19
|
+
get nextWeek(): string;
|
|
20
|
+
get lastFortnight(): string;
|
|
21
|
+
get nextFortnight(): string;
|
|
22
|
+
private fromShortcut;
|
|
23
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import { DateFactory, type DateFactoryOptions } from "./date-factory.js";
|
|
2
|
+
import { FormattedDateFactory } from "./formatted-date-factory.js";
|
|
3
|
+
import { IsoDateFactory } from "./iso-date-factory.js";
|
|
4
|
+
import type { StandardTimeUnit } from "./time-units.js";
|
|
5
|
+
export interface DatesOptions extends DateFactoryOptions {
|
|
6
|
+
factory?: DateFactory;
|
|
7
|
+
}
|
|
8
|
+
export interface DatesObject {
|
|
9
|
+
readonly iso: IsoDateFactory;
|
|
10
|
+
readonly fmt: FormattedDateFactory;
|
|
11
|
+
readonly now: Date;
|
|
12
|
+
readonly beforeYesterday: Date;
|
|
13
|
+
readonly yesterday: Date;
|
|
14
|
+
readonly today: Date;
|
|
15
|
+
readonly tomorrow: Date;
|
|
16
|
+
readonly afterTomorrow: Date;
|
|
17
|
+
readonly midnight: Date;
|
|
18
|
+
readonly lastWeek: Date;
|
|
19
|
+
readonly nextWeek: Date;
|
|
20
|
+
readonly lastFortnight: Date;
|
|
21
|
+
readonly nextFortnight: Date;
|
|
22
|
+
fromPhrase(phrase: unknown): Date;
|
|
23
|
+
fromPhraseSafe(phrase: unknown): Date;
|
|
24
|
+
make(offset: number, unit: StandardTimeUnit | string): Date;
|
|
25
|
+
}
|
|
26
|
+
export declare function createDates(options?: DatesOptions): DatesObject;
|
|
27
|
+
export declare const Dates: DatesObject;
|
|
28
|
+
export type { DateFactoryOptions };
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
export type StandardTimeUnit = "milliseconds" | "seconds" | "minutes" | "hours" | "days" | "weeks" | "months" | "years";
|
|
2
|
+
export interface NormalisedTimeUnit {
|
|
3
|
+
unit: StandardTimeUnit;
|
|
4
|
+
scale: number;
|
|
5
|
+
}
|
|
6
|
+
export declare function resolveTimeUnit(input: string): NormalisedTimeUnit;
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,482 @@
|
|
|
1
|
+
'use strict';
|
|
2
|
+
|
|
3
|
+
var errors = require('@autometa/errors');
|
|
4
|
+
var isoDatestringValidator = require('iso-datestring-validator');
|
|
5
|
+
var asserters = require('@autometa/asserters');
|
|
6
|
+
|
|
7
|
+
// src/dates/date-factory.ts
|
|
8
|
+
|
|
9
|
+
// src/dates/clock.ts
|
|
10
|
+
var systemClock = {
|
|
11
|
+
now: () => /* @__PURE__ */ new Date()
|
|
12
|
+
};
|
|
13
|
+
function cloneDate(date) {
|
|
14
|
+
return new Date(date.getTime());
|
|
15
|
+
}
|
|
16
|
+
var UNIT_ALIASES = {
|
|
17
|
+
millisecond: { unit: "milliseconds", scale: 1 },
|
|
18
|
+
milliseconds: { unit: "milliseconds", scale: 1 },
|
|
19
|
+
ms: { unit: "milliseconds", scale: 1 },
|
|
20
|
+
second: { unit: "seconds", scale: 1 },
|
|
21
|
+
seconds: { unit: "seconds", scale: 1 },
|
|
22
|
+
sec: { unit: "seconds", scale: 1 },
|
|
23
|
+
secs: { unit: "seconds", scale: 1 },
|
|
24
|
+
minute: { unit: "minutes", scale: 1 },
|
|
25
|
+
minutes: { unit: "minutes", scale: 1 },
|
|
26
|
+
min: { unit: "minutes", scale: 1 },
|
|
27
|
+
mins: { unit: "minutes", scale: 1 },
|
|
28
|
+
hour: { unit: "hours", scale: 1 },
|
|
29
|
+
hours: { unit: "hours", scale: 1 },
|
|
30
|
+
hr: { unit: "hours", scale: 1 },
|
|
31
|
+
hrs: { unit: "hours", scale: 1 },
|
|
32
|
+
day: { unit: "days", scale: 1 },
|
|
33
|
+
days: { unit: "days", scale: 1 },
|
|
34
|
+
week: { unit: "weeks", scale: 1 },
|
|
35
|
+
weeks: { unit: "weeks", scale: 1 },
|
|
36
|
+
fortnight: { unit: "days", scale: 14 },
|
|
37
|
+
fortnights: { unit: "days", scale: 14 },
|
|
38
|
+
month: { unit: "months", scale: 1 },
|
|
39
|
+
months: { unit: "months", scale: 1 },
|
|
40
|
+
year: { unit: "years", scale: 1 },
|
|
41
|
+
years: { unit: "years", scale: 1 }
|
|
42
|
+
};
|
|
43
|
+
function resolveTimeUnit(input) {
|
|
44
|
+
const key = input.trim().toLowerCase();
|
|
45
|
+
const resolved = UNIT_ALIASES[key];
|
|
46
|
+
if (!resolved) {
|
|
47
|
+
throw new errors.AutomationError(
|
|
48
|
+
`Unsupported time unit '${input}'. Expected one of ${Object.keys(UNIT_ALIASES).sort().join(", ")}.`
|
|
49
|
+
);
|
|
50
|
+
}
|
|
51
|
+
return resolved;
|
|
52
|
+
}
|
|
53
|
+
|
|
54
|
+
// src/shared/phrases.ts
|
|
55
|
+
var SEPARATORS = /[\s_-]+/g;
|
|
56
|
+
function capitalize(word) {
|
|
57
|
+
return word.charAt(0).toUpperCase() + word.slice(1);
|
|
58
|
+
}
|
|
59
|
+
function splitWords(phrase) {
|
|
60
|
+
return phrase.trim().split(SEPARATORS).filter(Boolean).map((word) => word.toLowerCase());
|
|
61
|
+
}
|
|
62
|
+
function toCamelKey(phrase) {
|
|
63
|
+
const words = splitWords(phrase);
|
|
64
|
+
if (words.length === 0) {
|
|
65
|
+
return "";
|
|
66
|
+
}
|
|
67
|
+
const [first, ...rest] = words;
|
|
68
|
+
return first + rest.map(capitalize).join("");
|
|
69
|
+
}
|
|
70
|
+
function normalizeToken(phrase) {
|
|
71
|
+
return splitWords(phrase).join("");
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
// src/dates/date-factory.ts
|
|
75
|
+
var SHORTCUT_LOOKUP = /* @__PURE__ */ new Set([
|
|
76
|
+
"now",
|
|
77
|
+
"beforeYesterday",
|
|
78
|
+
"yesterday",
|
|
79
|
+
"today",
|
|
80
|
+
"tomorrow",
|
|
81
|
+
"afterTomorrow",
|
|
82
|
+
"midnight",
|
|
83
|
+
"lastWeek",
|
|
84
|
+
"nextWeek",
|
|
85
|
+
"lastFortnight",
|
|
86
|
+
"nextFortnight"
|
|
87
|
+
]);
|
|
88
|
+
var FUTURE_PATTERN = /^(\d+)\s+([A-Za-z\s]+?)\s+from\s+now$/i;
|
|
89
|
+
var PAST_PATTERN = /^(\d+)\s+([A-Za-z\s]+?)\s+ago$/i;
|
|
90
|
+
function invalidDate() {
|
|
91
|
+
return new Date(Number.NaN);
|
|
92
|
+
}
|
|
93
|
+
function isDateShortcut(value) {
|
|
94
|
+
return SHORTCUT_LOOKUP.has(value);
|
|
95
|
+
}
|
|
96
|
+
var DateFactory = class {
|
|
97
|
+
constructor(options = {}) {
|
|
98
|
+
this.clock = options.clock ?? systemClock;
|
|
99
|
+
}
|
|
100
|
+
find(shortcut) {
|
|
101
|
+
switch (shortcut) {
|
|
102
|
+
case "now":
|
|
103
|
+
return this.currentDate();
|
|
104
|
+
case "beforeYesterday":
|
|
105
|
+
return this.make(-2, "days");
|
|
106
|
+
case "yesterday":
|
|
107
|
+
return this.make(-1, "days");
|
|
108
|
+
case "today":
|
|
109
|
+
return this.make(0, "days");
|
|
110
|
+
case "tomorrow":
|
|
111
|
+
return this.make(1, "days");
|
|
112
|
+
case "afterTomorrow":
|
|
113
|
+
return this.make(2, "days");
|
|
114
|
+
case "midnight":
|
|
115
|
+
return this.midnight();
|
|
116
|
+
case "lastWeek":
|
|
117
|
+
return this.make(-1, "weeks");
|
|
118
|
+
case "nextWeek":
|
|
119
|
+
return this.make(1, "weeks");
|
|
120
|
+
case "lastFortnight":
|
|
121
|
+
return this.make(-14, "days");
|
|
122
|
+
case "nextFortnight":
|
|
123
|
+
return this.make(14, "days");
|
|
124
|
+
default:
|
|
125
|
+
throw new errors.AutomationError(
|
|
126
|
+
`Unsupported date shortcut '${shortcut}'.`
|
|
127
|
+
);
|
|
128
|
+
}
|
|
129
|
+
}
|
|
130
|
+
fromPhraseSafe(phrase) {
|
|
131
|
+
if (typeof phrase !== "string") {
|
|
132
|
+
return invalidDate();
|
|
133
|
+
}
|
|
134
|
+
const trimmed = phrase.trim();
|
|
135
|
+
if (trimmed.length === 0) {
|
|
136
|
+
return invalidDate();
|
|
137
|
+
}
|
|
138
|
+
const shortcutCandidate = toCamelKey(trimmed);
|
|
139
|
+
if (isDateShortcut(shortcutCandidate)) {
|
|
140
|
+
return this.find(shortcutCandidate);
|
|
141
|
+
}
|
|
142
|
+
const relative = this.extractRelative(trimmed);
|
|
143
|
+
if (relative) {
|
|
144
|
+
return this.make(relative.offset, relative.unit);
|
|
145
|
+
}
|
|
146
|
+
if (this.isDateLike(trimmed)) {
|
|
147
|
+
return this.parseDate(trimmed);
|
|
148
|
+
}
|
|
149
|
+
return invalidDate();
|
|
150
|
+
}
|
|
151
|
+
fromPhrase(phrase) {
|
|
152
|
+
const result = this.fromPhraseSafe(phrase);
|
|
153
|
+
if (Number.isNaN(result.getTime())) {
|
|
154
|
+
throw new errors.AutomationError(
|
|
155
|
+
`Could not parse date from phrase '${String(phrase)}'. Valid shortcuts are: ${[...SHORTCUT_LOOKUP].join(", ")}.`
|
|
156
|
+
);
|
|
157
|
+
}
|
|
158
|
+
return result;
|
|
159
|
+
}
|
|
160
|
+
make(timeOffset, timeUnit) {
|
|
161
|
+
if (!Number.isFinite(timeOffset)) {
|
|
162
|
+
throw new errors.AutomationError(
|
|
163
|
+
`Time offset must be finite. Received '${timeOffset}'.`
|
|
164
|
+
);
|
|
165
|
+
}
|
|
166
|
+
const { unit, scale } = resolveTimeUnit(String(timeUnit));
|
|
167
|
+
const offset = timeOffset * scale;
|
|
168
|
+
const date = this.currentDate();
|
|
169
|
+
switch (unit) {
|
|
170
|
+
case "years":
|
|
171
|
+
date.setFullYear(date.getFullYear() + offset);
|
|
172
|
+
break;
|
|
173
|
+
case "months":
|
|
174
|
+
date.setMonth(date.getMonth() + offset);
|
|
175
|
+
break;
|
|
176
|
+
case "weeks":
|
|
177
|
+
date.setDate(date.getDate() + offset * 7);
|
|
178
|
+
break;
|
|
179
|
+
case "days":
|
|
180
|
+
date.setDate(date.getDate() + offset);
|
|
181
|
+
break;
|
|
182
|
+
case "hours":
|
|
183
|
+
date.setHours(date.getHours() + offset);
|
|
184
|
+
break;
|
|
185
|
+
case "minutes":
|
|
186
|
+
date.setMinutes(date.getMinutes() + offset);
|
|
187
|
+
break;
|
|
188
|
+
case "seconds":
|
|
189
|
+
date.setSeconds(date.getSeconds() + offset);
|
|
190
|
+
break;
|
|
191
|
+
case "milliseconds":
|
|
192
|
+
date.setMilliseconds(date.getMilliseconds() + offset);
|
|
193
|
+
break;
|
|
194
|
+
default:
|
|
195
|
+
throw new errors.AutomationError(`Unsupported time unit '${unit}'.`);
|
|
196
|
+
}
|
|
197
|
+
return date;
|
|
198
|
+
}
|
|
199
|
+
currentDate() {
|
|
200
|
+
return cloneDate(this.clock.now());
|
|
201
|
+
}
|
|
202
|
+
midnight() {
|
|
203
|
+
const date = this.currentDate();
|
|
204
|
+
date.setUTCDate(date.getUTCDate() + 1);
|
|
205
|
+
date.setUTCHours(0, 0, 0, 0);
|
|
206
|
+
return date;
|
|
207
|
+
}
|
|
208
|
+
parseDate(value) {
|
|
209
|
+
const parsed = new Date(value);
|
|
210
|
+
if (!Number.isNaN(parsed.getTime())) {
|
|
211
|
+
return parsed;
|
|
212
|
+
}
|
|
213
|
+
return new Date(Date.parse(value));
|
|
214
|
+
}
|
|
215
|
+
isDateLike(value) {
|
|
216
|
+
if (!Number.isNaN(new Date(value).getTime())) {
|
|
217
|
+
return true;
|
|
218
|
+
}
|
|
219
|
+
return isoDatestringValidator.isValidDate(value) || isoDatestringValidator.isValidISODateString(value) || isoDatestringValidator.isValidTime(value) || isoDatestringValidator.isValidYearMonth(value);
|
|
220
|
+
}
|
|
221
|
+
extractRelative(phrase) {
|
|
222
|
+
const futureMatch = FUTURE_PATTERN.exec(phrase);
|
|
223
|
+
if (futureMatch) {
|
|
224
|
+
return this.buildRelativeMatch(futureMatch, 1);
|
|
225
|
+
}
|
|
226
|
+
const pastMatch = PAST_PATTERN.exec(phrase);
|
|
227
|
+
if (pastMatch) {
|
|
228
|
+
return this.buildRelativeMatch(pastMatch, -1);
|
|
229
|
+
}
|
|
230
|
+
return void 0;
|
|
231
|
+
}
|
|
232
|
+
buildRelativeMatch(match, direction) {
|
|
233
|
+
const value = match[1];
|
|
234
|
+
const unit = match[2];
|
|
235
|
+
if (!value || !unit) {
|
|
236
|
+
return void 0;
|
|
237
|
+
}
|
|
238
|
+
const magnitude = Number.parseInt(value, 10);
|
|
239
|
+
if (!Number.isFinite(magnitude)) {
|
|
240
|
+
return void 0;
|
|
241
|
+
}
|
|
242
|
+
const convertedUnit = normalizeToken(unit);
|
|
243
|
+
const { unit: normalisedUnit, scale } = resolveTimeUnit(convertedUnit);
|
|
244
|
+
const offset = magnitude * scale * direction;
|
|
245
|
+
return {
|
|
246
|
+
offset,
|
|
247
|
+
unit: normalisedUnit
|
|
248
|
+
};
|
|
249
|
+
}
|
|
250
|
+
};
|
|
251
|
+
|
|
252
|
+
// src/dates/formatted-date-factory.ts
|
|
253
|
+
var FormattedDateFactory = class {
|
|
254
|
+
constructor(dateFactory, options = {}) {
|
|
255
|
+
this.dateFactory = dateFactory;
|
|
256
|
+
this.format = options.formatter ?? ((date) => date.toISOString().substring(0, 10));
|
|
257
|
+
}
|
|
258
|
+
make(offset, unit) {
|
|
259
|
+
return this.format(this.dateFactory.make(offset, unit));
|
|
260
|
+
}
|
|
261
|
+
fromPhrase(phrase) {
|
|
262
|
+
return this.format(this.dateFactory.fromPhrase(phrase));
|
|
263
|
+
}
|
|
264
|
+
get beforeYesterday() {
|
|
265
|
+
return this.fromShortcut("beforeYesterday");
|
|
266
|
+
}
|
|
267
|
+
get yesterday() {
|
|
268
|
+
return this.fromShortcut("yesterday");
|
|
269
|
+
}
|
|
270
|
+
get today() {
|
|
271
|
+
return this.fromShortcut("today");
|
|
272
|
+
}
|
|
273
|
+
get tomorrow() {
|
|
274
|
+
return this.fromShortcut("tomorrow");
|
|
275
|
+
}
|
|
276
|
+
get afterTomorrow() {
|
|
277
|
+
return this.fromShortcut("afterTomorrow");
|
|
278
|
+
}
|
|
279
|
+
get midnight() {
|
|
280
|
+
return this.fromShortcut("midnight");
|
|
281
|
+
}
|
|
282
|
+
get lastWeek() {
|
|
283
|
+
return this.fromShortcut("lastWeek");
|
|
284
|
+
}
|
|
285
|
+
get nextWeek() {
|
|
286
|
+
return this.fromShortcut("nextWeek");
|
|
287
|
+
}
|
|
288
|
+
get lastFortnight() {
|
|
289
|
+
return this.fromShortcut("lastFortnight");
|
|
290
|
+
}
|
|
291
|
+
get nextFortnight() {
|
|
292
|
+
return this.fromShortcut("nextFortnight");
|
|
293
|
+
}
|
|
294
|
+
fromShortcut(shortcut) {
|
|
295
|
+
return this.format(this.dateFactory.find(shortcut));
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
|
|
299
|
+
// src/dates/iso-date-factory.ts
|
|
300
|
+
var IsoDateFactory = class {
|
|
301
|
+
constructor(dateFactory, options = {}) {
|
|
302
|
+
this.dateFactory = dateFactory;
|
|
303
|
+
this.serialise = options.serializer ?? ((date) => date.toISOString());
|
|
304
|
+
}
|
|
305
|
+
make(offset, unit) {
|
|
306
|
+
return this.serialise(this.dateFactory.make(offset, unit));
|
|
307
|
+
}
|
|
308
|
+
fromPhrase(phrase) {
|
|
309
|
+
return this.serialise(this.dateFactory.fromPhrase(phrase));
|
|
310
|
+
}
|
|
311
|
+
get beforeYesterday() {
|
|
312
|
+
return this.fromShortcut("beforeYesterday");
|
|
313
|
+
}
|
|
314
|
+
get yesterday() {
|
|
315
|
+
return this.fromShortcut("yesterday");
|
|
316
|
+
}
|
|
317
|
+
get today() {
|
|
318
|
+
return this.fromShortcut("today");
|
|
319
|
+
}
|
|
320
|
+
get tomorrow() {
|
|
321
|
+
return this.fromShortcut("tomorrow");
|
|
322
|
+
}
|
|
323
|
+
get afterTomorrow() {
|
|
324
|
+
return this.fromShortcut("afterTomorrow");
|
|
325
|
+
}
|
|
326
|
+
get midnight() {
|
|
327
|
+
return this.fromShortcut("midnight");
|
|
328
|
+
}
|
|
329
|
+
get lastWeek() {
|
|
330
|
+
return this.fromShortcut("lastWeek");
|
|
331
|
+
}
|
|
332
|
+
get nextWeek() {
|
|
333
|
+
return this.fromShortcut("nextWeek");
|
|
334
|
+
}
|
|
335
|
+
get lastFortnight() {
|
|
336
|
+
return this.fromShortcut("lastFortnight");
|
|
337
|
+
}
|
|
338
|
+
get nextFortnight() {
|
|
339
|
+
return this.fromShortcut("nextFortnight");
|
|
340
|
+
}
|
|
341
|
+
fromShortcut(shortcut) {
|
|
342
|
+
return this.serialise(this.dateFactory.find(shortcut));
|
|
343
|
+
}
|
|
344
|
+
};
|
|
345
|
+
|
|
346
|
+
// src/dates/object.ts
|
|
347
|
+
var DatesFacade = class {
|
|
348
|
+
constructor(factory) {
|
|
349
|
+
this.factory = factory;
|
|
350
|
+
this.iso = new IsoDateFactory(factory);
|
|
351
|
+
this.fmt = new FormattedDateFactory(factory);
|
|
352
|
+
}
|
|
353
|
+
get now() {
|
|
354
|
+
return this.fromShortcut("now");
|
|
355
|
+
}
|
|
356
|
+
get beforeYesterday() {
|
|
357
|
+
return this.fromShortcut("beforeYesterday");
|
|
358
|
+
}
|
|
359
|
+
get yesterday() {
|
|
360
|
+
return this.fromShortcut("yesterday");
|
|
361
|
+
}
|
|
362
|
+
get today() {
|
|
363
|
+
return this.fromShortcut("today");
|
|
364
|
+
}
|
|
365
|
+
get tomorrow() {
|
|
366
|
+
return this.fromShortcut("tomorrow");
|
|
367
|
+
}
|
|
368
|
+
get afterTomorrow() {
|
|
369
|
+
return this.fromShortcut("afterTomorrow");
|
|
370
|
+
}
|
|
371
|
+
get midnight() {
|
|
372
|
+
return this.fromShortcut("midnight");
|
|
373
|
+
}
|
|
374
|
+
get lastWeek() {
|
|
375
|
+
return this.fromShortcut("lastWeek");
|
|
376
|
+
}
|
|
377
|
+
get nextWeek() {
|
|
378
|
+
return this.fromShortcut("nextWeek");
|
|
379
|
+
}
|
|
380
|
+
get lastFortnight() {
|
|
381
|
+
return this.fromShortcut("lastFortnight");
|
|
382
|
+
}
|
|
383
|
+
get nextFortnight() {
|
|
384
|
+
return this.fromShortcut("nextFortnight");
|
|
385
|
+
}
|
|
386
|
+
fromPhrase(phrase) {
|
|
387
|
+
return this.factory.fromPhrase(phrase);
|
|
388
|
+
}
|
|
389
|
+
fromPhraseSafe(phrase) {
|
|
390
|
+
return this.factory.fromPhraseSafe(phrase);
|
|
391
|
+
}
|
|
392
|
+
make(offset, unit) {
|
|
393
|
+
return this.factory.make(offset, unit);
|
|
394
|
+
}
|
|
395
|
+
fromShortcut(shortcut) {
|
|
396
|
+
return this.factory.find(shortcut);
|
|
397
|
+
}
|
|
398
|
+
};
|
|
399
|
+
function createDates(options = {}) {
|
|
400
|
+
const factory = options.factory ?? new DateFactory(options);
|
|
401
|
+
return new DatesFacade(factory);
|
|
402
|
+
}
|
|
403
|
+
var Dates = createDates();
|
|
404
|
+
var SUPPORTED_METHODS = [
|
|
405
|
+
"minutes",
|
|
406
|
+
"seconds",
|
|
407
|
+
"millis",
|
|
408
|
+
"days",
|
|
409
|
+
"hours",
|
|
410
|
+
"weeks"
|
|
411
|
+
];
|
|
412
|
+
function toTime(date) {
|
|
413
|
+
return new Date(date).getTime();
|
|
414
|
+
}
|
|
415
|
+
var TimeDiff = class {
|
|
416
|
+
minutes(start, end) {
|
|
417
|
+
return this.millis(start, end) / 6e4;
|
|
418
|
+
}
|
|
419
|
+
seconds(start, end) {
|
|
420
|
+
return this.millis(start, end) / 1e3;
|
|
421
|
+
}
|
|
422
|
+
millis(start, end) {
|
|
423
|
+
const distance = Math.abs(toTime(end) - toTime(start));
|
|
424
|
+
return Math.round(distance);
|
|
425
|
+
}
|
|
426
|
+
days(start, end) {
|
|
427
|
+
return this.millis(start, end) / 864e5;
|
|
428
|
+
}
|
|
429
|
+
hours(start, end) {
|
|
430
|
+
return this.millis(start, end) / 36e5;
|
|
431
|
+
}
|
|
432
|
+
weeks(start, end) {
|
|
433
|
+
return this.millis(start, end) / 6048e5;
|
|
434
|
+
}
|
|
435
|
+
fromPhrase(phrase) {
|
|
436
|
+
if (typeof phrase !== "string") {
|
|
437
|
+
throw new errors.AutomationError(
|
|
438
|
+
`TimeDiff.fromPhrase expects a string, received '${typeof phrase}'.`
|
|
439
|
+
);
|
|
440
|
+
}
|
|
441
|
+
const key = normalizeToken(phrase);
|
|
442
|
+
if (!this.hasMethod(key)) {
|
|
443
|
+
throw new errors.AutomationError(
|
|
444
|
+
`Unsupported diff unit '${phrase}'. Expected one of ${this.supportedMethods().join(", ")}.`
|
|
445
|
+
);
|
|
446
|
+
}
|
|
447
|
+
asserters.assertKey(this, key, "TimeDiff.fromPhrase");
|
|
448
|
+
const method = this[key];
|
|
449
|
+
if (typeof method !== "function") {
|
|
450
|
+
throw new errors.AutomationError(`Diff method '${key}' is not callable.`);
|
|
451
|
+
}
|
|
452
|
+
return method.bind(this);
|
|
453
|
+
}
|
|
454
|
+
hasMethod(name) {
|
|
455
|
+
return SUPPORTED_METHODS.includes(name);
|
|
456
|
+
}
|
|
457
|
+
supportedMethods() {
|
|
458
|
+
return [...SUPPORTED_METHODS];
|
|
459
|
+
}
|
|
460
|
+
};
|
|
461
|
+
|
|
462
|
+
// src/time/time.ts
|
|
463
|
+
var TimeFacade = class {
|
|
464
|
+
constructor(diff) {
|
|
465
|
+
this.diff = diff;
|
|
466
|
+
}
|
|
467
|
+
};
|
|
468
|
+
function createTime() {
|
|
469
|
+
return new TimeFacade(new TimeDiff());
|
|
470
|
+
}
|
|
471
|
+
var Time = createTime();
|
|
472
|
+
|
|
473
|
+
exports.DateFactory = DateFactory;
|
|
474
|
+
exports.Dates = Dates;
|
|
475
|
+
exports.FormattedDateFactory = FormattedDateFactory;
|
|
476
|
+
exports.IsoDateFactory = IsoDateFactory;
|
|
477
|
+
exports.Time = Time;
|
|
478
|
+
exports.TimeDiff = TimeDiff;
|
|
479
|
+
exports.createDates = createDates;
|
|
480
|
+
exports.createTime = createTime;
|
|
481
|
+
//# sourceMappingURL=out.js.map
|
|
482
|
+
//# sourceMappingURL=index.cjs.map
|