@tmlmobilidade/go-utils-dates 20260828.1636.54

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.
@@ -0,0 +1,15 @@
1
+ import { type DateFormat } from '@tmlmobilidade/go-types-shared';
2
+ export interface DateFormatConfig {
3
+ day?: '2-digit' | 'numeric';
4
+ hour?: '2-digit' | 'numeric';
5
+ minute?: '2-digit' | 'numeric';
6
+ month?: '2-digit' | 'long' | 'numeric' | 'short';
7
+ second?: '2-digit' | 'numeric';
8
+ timeZoneName?: 'long' | 'short';
9
+ weekday?: 'long' | 'narrow' | 'short';
10
+ year?: '2-digit' | 'numeric';
11
+ }
12
+ /**
13
+ * A map of date formats to their corresponding config.
14
+ */
15
+ export declare const DateFormatConfigMap: Record<DateFormat, DateFormatConfig>;
@@ -0,0 +1,35 @@
1
+ /* * */
2
+ /**
3
+ * A map of date formats to their corresponding config.
4
+ */
5
+ export const DateFormatConfigMap = {
6
+ full: {
7
+ day: 'numeric',
8
+ month: 'long',
9
+ year: 'numeric',
10
+ },
11
+ iso: {
12
+ day: 'numeric',
13
+ month: 'numeric',
14
+ year: 'numeric',
15
+ },
16
+ only_date: {
17
+ day: 'numeric',
18
+ month: 'numeric',
19
+ year: 'numeric',
20
+ },
21
+ only_time: {
22
+ hour: 'numeric',
23
+ minute: 'numeric',
24
+ },
25
+ only_time_with_seconds: {
26
+ hour: 'numeric',
27
+ minute: 'numeric',
28
+ second: 'numeric',
29
+ },
30
+ short: {
31
+ day: 'numeric',
32
+ month: 'numeric',
33
+ year: 'numeric',
34
+ },
35
+ };
@@ -0,0 +1,161 @@
1
+ import { type CalendarDate, DateFormat, type OperationalDateInt, type TimezoneIdentified, type UnixTimestamp } from '@tmlmobilidade/go-types-shared';
2
+ import { type DateObjectUnits, type DateTimeUnit, type DurationObjectUnits } from 'luxon';
3
+ interface DatesConstructor {
4
+ calendar_date: CalendarDate;
5
+ iso: null | string;
6
+ js_date: Date;
7
+ operational_date_int: OperationalDateInt;
8
+ std_window: {
9
+ end: UnixTimestamp;
10
+ start: UnixTimestamp;
11
+ };
12
+ unix_timestamp: UnixTimestamp;
13
+ }
14
+ export declare class Dates {
15
+ static readonly standardWindowHours = 10;
16
+ static readonly standardWindowMilliseconds: number;
17
+ calendar_date: CalendarDate;
18
+ iso: null | string;
19
+ js_date: Date;
20
+ operational_date_int: OperationalDateInt;
21
+ std_window: {
22
+ end: UnixTimestamp;
23
+ start: UnixTimestamp;
24
+ };
25
+ unix_timestamp: UnixTimestamp;
26
+ constructor(params: DatesConstructor);
27
+ /**
28
+ * Creates a Dates object from a date/time string in a specific format.
29
+ * @param text The date/time string to parse.
30
+ * @param format The format string to use for parsing the date/time.
31
+ * See Luxon documentation for format tokens: https://moment.github.io/luxon/#/formatting?id=table-of-tokens
32
+ * @param timezone The timezone to set for the Dates object.
33
+ * @returns A new Dates object parsed from the string.
34
+ */
35
+ static fromFormat(text: string, format: string, timezone: 'local' | 'utc' | TimezoneIdentified): Dates;
36
+ /**
37
+ * Creates a Dates object from an ISO 8601 date/time string.
38
+ * This method assumes the string has a timezone offset.
39
+ * @param isoText The ISO 8601 date/time string to parse.
40
+ * @returns A new Dates object created from the ISO string.
41
+ */
42
+ static fromISO(isoText: string): Dates;
43
+ /**
44
+ * Creates a Dates object from a JavaScript Date object.
45
+ * @param date The JavaScript Date object to convert. It is assumed that the date is in UTC.
46
+ * @returns A new Dates object created from the JavaScript Date.
47
+ */
48
+ static fromJSDate(date: Date): Dates;
49
+ /**
50
+ * Creates a Dates object from an operational date integer.
51
+ * @param date The operational date integer in 'yyyyMMdd' format.
52
+ * @param timezone The timezone to set for the Dates object.
53
+ * @returns A new Dates object created from the operational date.
54
+ */
55
+ static fromOperationalDateInt(date: OperationalDateInt | string, timezone: 'local' | 'utc' | TimezoneIdentified): Dates;
56
+ /**
57
+ * Creates a Dates object from Unix epoch seconds
58
+ * @param seconds The number of seconds since Unix epoch
59
+ * @returns A new Dates object created from the seconds timestamp
60
+ */
61
+ static fromSeconds(seconds: number): Dates;
62
+ /**
63
+ * Creates a Dates object from Unix epoch in milliseconds.
64
+ * @param millis The number of milliseconds since Unix epoch. Unix timestamp is always in UTC.
65
+ * @returns A new Dates object created from the milliseconds timestamp.
66
+ */
67
+ static fromUnixTimestamp(millis: number | UnixTimestamp): Dates;
68
+ /**
69
+ * Creates a Dates object with the current date and time.
70
+ * @param timezone The timezone to set for the Dates object.
71
+ * @returns A new Dates object with the current date and time in the specified timezone.
72
+ */
73
+ static now(timezone: 'local' | 'utc' | TimezoneIdentified): Dates;
74
+ /**
75
+ * Returns the difference between this date and another date.
76
+ * @param other The other Dates object to compare with
77
+ * @param unit The unit of time to return the difference in (defaults to 'day')
78
+ * @returns The difference as a number in the specified unit
79
+ */
80
+ diff(other: Dates, unit?: DateTimeUnit): number;
81
+ /**
82
+ * Returns a new Dates object with the end of the specified unit.
83
+ * @param unit The unit to set the end of, e.g., 'day', 'month', 'year', etc.
84
+ * @returns A new Dates object with the end of the specified unit.
85
+ */
86
+ endOf(unit: DateTimeUnit): Dates;
87
+ /**
88
+ * Returns a new Dates object with the current date and time minus a duration.
89
+ * @param duration The duration to subtract
90
+ * @returns A new Dates object with the current date and time minus a duration
91
+ */
92
+ minus(duration: DurationObjectUnits): Dates;
93
+ /**
94
+ * Returns a new Dates object with the current date and time plus a duration
95
+ * @param duration The duration to add
96
+ * @returns A new Dates object with the current date and time plus a duration
97
+ */
98
+ plus(duration: DurationObjectUnits): Dates;
99
+ /**
100
+ * Sets the date and time for the Dates object.
101
+ * @param dateOrTime The date or time to set, can be an object with DateObjectUnits or a string in ISO format.
102
+ * @returns The Dates object
103
+ */
104
+ set(dateOrTime: DateObjectUnits): Dates;
105
+ /**
106
+ * Sets the timezone for the Dates object.
107
+ * @param timezone The timezone to set in the format of an IANA timezone.
108
+ * @param method The method to use for updating the timezone information.
109
+ * - `offset_only` Updates only offset setting to the new timezone. The ISO string will show adjusted time components (hour, minutes, etc.) to their equivalent in the new timezone. The UTC value in milliseconds stays the same. The UNIX timestamp is the source of truth.
110
+ * - `rebase_utc` Keeps the individual time components (hour, minutes, etc.) and updates the internal UTC value in milliseconds to reflect the change. The ISO string will show the same time components as before, but the UTC value in milliseconds will be adjusted to match the new timezone. The ISO string is the source of truth.
111
+ * @returns The Dates object
112
+ */
113
+ setZone(timezone: 'local' | 'utc' | TimezoneIdentified, method: 'offset_only' | 'rebase_utc'): Dates;
114
+ /**
115
+ * Returns a new Dates object with the start of the specified unit.
116
+ * @param unit The unit to set the start of, e.g., 'day', 'month', 'year', etc.
117
+ * @returns A new Dates object with the start of the specified unit.
118
+ */
119
+ startOf(unit: DateTimeUnit): Dates;
120
+ /**
121
+ * Returns the time remaining until a given unix_timestamp (in ms) from now,
122
+ * as an object with minutes, hours, and days (all as floats, not rounded).
123
+ * @param unixTimestamp The target timestamp in milliseconds
124
+ * @returns { minutes: number, hours: number, days: number }
125
+ */
126
+ timeUntil(unixTimestamp: UnixTimestamp): {
127
+ days: number;
128
+ hours: number;
129
+ minutes: number;
130
+ };
131
+ /**
132
+ * Returns the date as a string in the specified format.
133
+ * @param format The format string (see Luxon tokens documentation)
134
+ * @param opts Optional formatting options (e.g., { locale: 'pt' })
135
+ * @returns The date as a string in the specified format
136
+ */
137
+ toFormat(format: string, opts?: {
138
+ locale?: string;
139
+ }): string;
140
+ /**
141
+ * Returns the date as a string in the specified format.
142
+ * @param format The format string (see Luxon tokens documentation)
143
+ * @returns The date as a string in the specified format
144
+ */
145
+ toLocaleString(format: DateFormat, locale?: string): string;
146
+ /**
147
+ * Returns the operational date based on the provided timestamp and format.
148
+ * @param isoDate The ISO date string to calculate the operational date.
149
+ * @returns The operational date in the yyyyLLdd format.
150
+ */
151
+ private getOperationalDateInt;
152
+ /**
153
+ * This function returns the start and end of the standard window interval for a given timestamp.
154
+ * The standard window interval is the period in which is possible to receive data for a given ride.
155
+ * Currently, the standard window starts 10 hours before and ends 10 hours after the scheduled ride start.
156
+ * @param isoDate The ISO date string to calculate the standard window interval.
157
+ * @returns An object containing the start and end of the standard window interval.
158
+ */
159
+ private getStandardWindowInterval;
160
+ }
161
+ export {};
package/dist/dates.js ADDED
@@ -0,0 +1,378 @@
1
+ /* eslint-disable @typescript-eslint/naming-convention */
2
+ import { CALENDAR_DATE_FORMAT, OPERATIONAL_DATE_FORMAT } from '@tmlmobilidade/go-types-shared';
3
+ import { DateTime } from 'luxon';
4
+ import { DateFormatConfigMap } from './date-format.js';
5
+ /* * */
6
+ export class Dates {
7
+ //
8
+ static standardWindowHours = 10;
9
+ static standardWindowMilliseconds = this.standardWindowHours * 1000 * 60 * 60;
10
+ calendar_date;
11
+ iso;
12
+ js_date;
13
+ operational_date_int;
14
+ std_window;
15
+ unix_timestamp;
16
+ constructor(params) {
17
+ this.calendar_date = params.calendar_date;
18
+ this.iso = params.iso ?? null;
19
+ this.js_date = params.js_date;
20
+ this.operational_date_int = params.operational_date_int;
21
+ this.std_window = params.std_window;
22
+ this.unix_timestamp = params.unix_timestamp;
23
+ }
24
+ /**
25
+ * Creates a Dates object from a date/time string in a specific format.
26
+ * @param text The date/time string to parse.
27
+ * @param format The format string to use for parsing the date/time.
28
+ * See Luxon documentation for format tokens: https://moment.github.io/luxon/#/formatting?id=table-of-tokens
29
+ * @param timezone The timezone to set for the Dates object.
30
+ * @returns A new Dates object parsed from the string.
31
+ */
32
+ static fromFormat(text, format, timezone) {
33
+ const dateTime = DateTime
34
+ .fromFormat(text, format, { setZone: true })
35
+ .setZone(timezone, { keepLocalTime: true });
36
+ return new Dates({
37
+ calendar_date: dateTime.toFormat(CALENDAR_DATE_FORMAT),
38
+ iso: dateTime.toISO(),
39
+ js_date: dateTime.toJSDate(),
40
+ operational_date_int: this.prototype.getOperationalDateInt(dateTime.toISO()),
41
+ std_window: this.prototype.getStandardWindowInterval(dateTime.toISO()),
42
+ unix_timestamp: dateTime.toMillis(),
43
+ });
44
+ }
45
+ /**
46
+ * Creates a Dates object from an ISO 8601 date/time string.
47
+ * This method assumes the string has a timezone offset.
48
+ * @param isoText The ISO 8601 date/time string to parse.
49
+ * @returns A new Dates object created from the ISO string.
50
+ */
51
+ static fromISO(isoText) {
52
+ const dateTime = DateTime.fromISO(isoText, { setZone: true });
53
+ return new Dates({
54
+ calendar_date: dateTime.toFormat(CALENDAR_DATE_FORMAT),
55
+ iso: dateTime.toISO(),
56
+ js_date: dateTime.toJSDate(),
57
+ operational_date_int: this.prototype.getOperationalDateInt(dateTime.toISO()),
58
+ std_window: this.prototype.getStandardWindowInterval(dateTime.toISO()),
59
+ unix_timestamp: dateTime.toMillis(),
60
+ });
61
+ }
62
+ /**
63
+ * Creates a Dates object from a JavaScript Date object.
64
+ * @param date The JavaScript Date object to convert. It is assumed that the date is in UTC.
65
+ * @returns A new Dates object created from the JavaScript Date.
66
+ */
67
+ static fromJSDate(date) {
68
+ const dateTime = DateTime
69
+ .fromJSDate(date)
70
+ .setZone('utc', { keepLocalTime: false });
71
+ return new Dates({
72
+ calendar_date: dateTime.toFormat(CALENDAR_DATE_FORMAT),
73
+ iso: dateTime.toISO(),
74
+ js_date: dateTime.toJSDate(),
75
+ operational_date_int: this.prototype.getOperationalDateInt(dateTime.toISO()),
76
+ std_window: this.prototype.getStandardWindowInterval(dateTime.toISO()),
77
+ unix_timestamp: dateTime.toMillis(),
78
+ });
79
+ }
80
+ /**
81
+ * Creates a Dates object from an operational date integer.
82
+ * @param date The operational date integer in 'yyyyMMdd' format.
83
+ * @param timezone The timezone to set for the Dates object.
84
+ * @returns A new Dates object created from the operational date.
85
+ */
86
+ static fromOperationalDateInt(date, timezone) {
87
+ const dateTime = DateTime
88
+ .fromFormat(String(date), OPERATIONAL_DATE_FORMAT)
89
+ .setZone(timezone, { keepLocalTime: true })
90
+ .set({ hour: 4, millisecond: 0, minute: 0, second: 0 }); // Start of the operational date
91
+ return new Dates({
92
+ calendar_date: dateTime.toFormat(CALENDAR_DATE_FORMAT),
93
+ iso: dateTime.toISO(),
94
+ js_date: dateTime.toJSDate(),
95
+ operational_date_int: this.prototype.getOperationalDateInt(dateTime.toISO()),
96
+ std_window: this.prototype.getStandardWindowInterval(dateTime.toISO()),
97
+ unix_timestamp: dateTime.toMillis(),
98
+ });
99
+ }
100
+ /**
101
+ * Creates a Dates object from Unix epoch seconds
102
+ * @param seconds The number of seconds since Unix epoch
103
+ * @returns A new Dates object created from the seconds timestamp
104
+ */
105
+ static fromSeconds(seconds) {
106
+ const dateTime = DateTime
107
+ .fromSeconds(seconds)
108
+ .setZone('utc', { keepLocalTime: false });
109
+ return new Dates({
110
+ calendar_date: dateTime.toFormat(CALENDAR_DATE_FORMAT),
111
+ iso: dateTime.toISO(),
112
+ js_date: dateTime.toJSDate(),
113
+ operational_date_int: this.prototype.getOperationalDateInt(dateTime.toISO()),
114
+ std_window: this.prototype.getStandardWindowInterval(dateTime.toISO()),
115
+ unix_timestamp: dateTime.toMillis(),
116
+ });
117
+ }
118
+ /**
119
+ * Creates a Dates object from Unix epoch in milliseconds.
120
+ * @param millis The number of milliseconds since Unix epoch. Unix timestamp is always in UTC.
121
+ * @returns A new Dates object created from the milliseconds timestamp.
122
+ */
123
+ static fromUnixTimestamp(millis) {
124
+ const dateTime = DateTime
125
+ .fromMillis(millis)
126
+ .setZone('utc', { keepLocalTime: false });
127
+ return new Dates({
128
+ calendar_date: dateTime.toFormat(CALENDAR_DATE_FORMAT),
129
+ iso: dateTime.toISO(),
130
+ js_date: dateTime.toJSDate(),
131
+ operational_date_int: this.prototype.getOperationalDateInt(dateTime.toISO()),
132
+ std_window: this.prototype.getStandardWindowInterval(dateTime.toISO()),
133
+ unix_timestamp: dateTime.toMillis(),
134
+ });
135
+ }
136
+ /**
137
+ * Creates a Dates object with the current date and time.
138
+ * @param timezone The timezone to set for the Dates object.
139
+ * @returns A new Dates object with the current date and time in the specified timezone.
140
+ */
141
+ static now(timezone) {
142
+ const dateTime = DateTime
143
+ .now()
144
+ .setZone(timezone, { keepLocalTime: false });
145
+ return new Dates({
146
+ calendar_date: dateTime.toFormat(CALENDAR_DATE_FORMAT),
147
+ iso: dateTime.toISO(),
148
+ js_date: dateTime.toJSDate(),
149
+ operational_date_int: this.prototype.getOperationalDateInt(dateTime.toISO()),
150
+ std_window: this.prototype.getStandardWindowInterval(dateTime.toISO()),
151
+ unix_timestamp: dateTime.toMillis(),
152
+ });
153
+ }
154
+ /**
155
+ * Returns the difference between this date and another date.
156
+ * @param other The other Dates object to compare with
157
+ * @param unit The unit of time to return the difference in (defaults to 'day')
158
+ * @returns The difference as a number in the specified unit
159
+ */
160
+ diff(other, unit = 'day') {
161
+ if (!this.iso || !other.iso)
162
+ throw new Error('ISO date is not set.');
163
+ const thisDateTime = DateTime.fromISO(this.iso, { setZone: true });
164
+ const otherDateTime = DateTime.fromISO(other.iso, { setZone: true });
165
+ return thisDateTime.diff(otherDateTime, unit).as(unit);
166
+ }
167
+ /**
168
+ * Returns a new Dates object with the end of the specified unit.
169
+ * @param unit The unit to set the end of, e.g., 'day', 'month', 'year', etc.
170
+ * @returns A new Dates object with the end of the specified unit.
171
+ */
172
+ endOf(unit) {
173
+ if (!this.iso)
174
+ throw new Error('ISO date is not set.');
175
+ const dateTime = DateTime
176
+ .fromISO(this.iso, { setZone: true })
177
+ .endOf(unit);
178
+ return new Dates({
179
+ calendar_date: dateTime.toFormat(CALENDAR_DATE_FORMAT),
180
+ iso: dateTime.toISO(),
181
+ js_date: dateTime.toJSDate(),
182
+ operational_date_int: this.getOperationalDateInt(dateTime.toISO()),
183
+ std_window: this.getStandardWindowInterval(dateTime.toISO()),
184
+ unix_timestamp: dateTime.toMillis(),
185
+ });
186
+ }
187
+ /**
188
+ * Returns a new Dates object with the current date and time minus a duration.
189
+ * @param duration The duration to subtract
190
+ * @returns A new Dates object with the current date and time minus a duration
191
+ */
192
+ minus(duration) {
193
+ if (!this.iso)
194
+ throw new Error('ISO date is not set.');
195
+ const dateTime = DateTime
196
+ .fromISO(this.iso, { setZone: true })
197
+ .minus(duration);
198
+ return new Dates({
199
+ calendar_date: dateTime.toFormat(CALENDAR_DATE_FORMAT),
200
+ iso: dateTime.toISO(),
201
+ js_date: dateTime.toJSDate(),
202
+ operational_date_int: this.getOperationalDateInt(dateTime.toISO()),
203
+ std_window: this.getStandardWindowInterval(dateTime.toISO()),
204
+ unix_timestamp: dateTime.toMillis(),
205
+ });
206
+ }
207
+ /**
208
+ * Returns a new Dates object with the current date and time plus a duration
209
+ * @param duration The duration to add
210
+ * @returns A new Dates object with the current date and time plus a duration
211
+ */
212
+ plus(duration) {
213
+ if (!this.iso)
214
+ throw new Error('ISO date is not set.');
215
+ const dateTime = DateTime
216
+ .fromISO(this.iso, { setZone: true })
217
+ .plus(duration);
218
+ return new Dates({
219
+ calendar_date: dateTime.toFormat(CALENDAR_DATE_FORMAT),
220
+ iso: dateTime.toISO(),
221
+ js_date: dateTime.toJSDate(),
222
+ operational_date_int: this.getOperationalDateInt(dateTime.toISO()),
223
+ std_window: this.getStandardWindowInterval(dateTime.toISO()),
224
+ unix_timestamp: dateTime.toMillis(),
225
+ });
226
+ }
227
+ /**
228
+ * Sets the date and time for the Dates object.
229
+ * @param dateOrTime The date or time to set, can be an object with DateObjectUnits or a string in ISO format.
230
+ * @returns The Dates object
231
+ */
232
+ set(dateOrTime) {
233
+ if (!this.iso)
234
+ throw new Error('ISO date is not set.');
235
+ const dateTime = DateTime
236
+ .fromISO(this.iso, { setZone: true })
237
+ .set(dateOrTime);
238
+ return new Dates({
239
+ calendar_date: dateTime.toFormat(CALENDAR_DATE_FORMAT),
240
+ iso: dateTime.toISO(),
241
+ js_date: dateTime.toJSDate(),
242
+ operational_date_int: this.getOperationalDateInt(dateTime.toISO()),
243
+ std_window: this.getStandardWindowInterval(dateTime.toISO()),
244
+ unix_timestamp: dateTime.toMillis(),
245
+ });
246
+ }
247
+ /**
248
+ * Sets the timezone for the Dates object.
249
+ * @param timezone The timezone to set in the format of an IANA timezone.
250
+ * @param method The method to use for updating the timezone information.
251
+ * - `offset_only` Updates only offset setting to the new timezone. The ISO string will show adjusted time components (hour, minutes, etc.) to their equivalent in the new timezone. The UTC value in milliseconds stays the same. The UNIX timestamp is the source of truth.
252
+ * - `rebase_utc` Keeps the individual time components (hour, minutes, etc.) and updates the internal UTC value in milliseconds to reflect the change. The ISO string will show the same time components as before, but the UTC value in milliseconds will be adjusted to match the new timezone. The ISO string is the source of truth.
253
+ * @returns The Dates object
254
+ */
255
+ setZone(timezone, method) {
256
+ if (!this.iso)
257
+ throw new Error('ISO date is not set.');
258
+ const dateTime = DateTime
259
+ .fromISO(this.iso, { setZone: true })
260
+ .setZone(timezone, { keepLocalTime: method === 'rebase_utc' });
261
+ return new Dates({
262
+ calendar_date: dateTime.toFormat(CALENDAR_DATE_FORMAT),
263
+ iso: dateTime.toISO(),
264
+ js_date: dateTime.toJSDate(),
265
+ operational_date_int: this.getOperationalDateInt(dateTime.toISO()),
266
+ std_window: this.getStandardWindowInterval(dateTime.toISO()),
267
+ unix_timestamp: dateTime.toMillis(),
268
+ });
269
+ }
270
+ /**
271
+ * Returns a new Dates object with the start of the specified unit.
272
+ * @param unit The unit to set the start of, e.g., 'day', 'month', 'year', etc.
273
+ * @returns A new Dates object with the start of the specified unit.
274
+ */
275
+ startOf(unit) {
276
+ if (!this.iso)
277
+ throw new Error('ISO date is not set.');
278
+ const dateTime = DateTime
279
+ .fromISO(this.iso, { setZone: true })
280
+ .startOf(unit);
281
+ return new Dates({
282
+ calendar_date: dateTime.toFormat(CALENDAR_DATE_FORMAT),
283
+ iso: dateTime.toISO(),
284
+ js_date: dateTime.toJSDate(),
285
+ operational_date_int: this.getOperationalDateInt(dateTime.toISO()),
286
+ std_window: this.getStandardWindowInterval(dateTime.toISO()),
287
+ unix_timestamp: dateTime.toMillis(),
288
+ });
289
+ }
290
+ /**
291
+ * Returns the time remaining until a given unix_timestamp (in ms) from now,
292
+ * as an object with minutes, hours, and days (all as floats, not rounded).
293
+ * @param unixTimestamp The target timestamp in milliseconds
294
+ * @returns { minutes: number, hours: number, days: number }
295
+ */
296
+ timeUntil(unixTimestamp) {
297
+ // Calculate the difference in milliseconds
298
+ const now = Date.now();
299
+ const diffMs = unixTimestamp - now;
300
+ // Calculate the time remaining
301
+ const minutes = diffMs / (1000 * 60);
302
+ const hours = diffMs / (1000 * 60 * 60);
303
+ const days = diffMs / (1000 * 60 * 60 * 24);
304
+ // Return the time components
305
+ return { days, hours, minutes };
306
+ }
307
+ /**
308
+ * Returns the date as a string in the specified format.
309
+ * @param format The format string (see Luxon tokens documentation)
310
+ * @param opts Optional formatting options (e.g., { locale: 'pt' })
311
+ * @returns The date as a string in the specified format
312
+ */
313
+ toFormat(format, opts) {
314
+ if (!this.iso)
315
+ throw new Error('ISO date is not set.');
316
+ const dateTime = DateTime.fromISO(this.iso, { setZone: true });
317
+ return dateTime.setLocale(opts?.locale || 'pt').toFormat(format);
318
+ }
319
+ /**
320
+ * Returns the date as a string in the specified format.
321
+ * @param format The format string (see Luxon tokens documentation)
322
+ * @returns The date as a string in the specified format
323
+ */
324
+ toLocaleString(format, locale) {
325
+ if (!this.iso)
326
+ throw new Error('ISO date is not set.');
327
+ const dateTime = DateTime.fromISO(this.iso, { setZone: true });
328
+ if (locale)
329
+ dateTime.setLocale(locale);
330
+ const dateFormatConfig = DateFormatConfigMap[format];
331
+ if (!dateFormatConfig)
332
+ throw new Error(`Invalid date format: ${format}`);
333
+ return dateTime.toLocaleString(dateFormatConfig, { locale: locale });
334
+ }
335
+ /**
336
+ * Returns the operational date based on the provided timestamp and format.
337
+ * @param isoDate The ISO date string to calculate the operational date.
338
+ * @returns The operational date in the yyyyLLdd format.
339
+ */
340
+ getOperationalDateInt(isoDate) {
341
+ // Skip if the ISO date is not set
342
+ if (!isoDate)
343
+ throw new Error('ISO date is not set.');
344
+ // Get the date object
345
+ const dateObject = DateTime.fromISO(isoDate, { setZone: true });
346
+ // Check if the time is between 00:00 and 03:59.
347
+ // The operational date is between 04:00 and 03:59 of the following day.
348
+ let operationalDate;
349
+ if (dateObject.hour < 4) {
350
+ // If true, unwind the clock by 12 hours to
351
+ // return the previous day in the yyyyLLdd format
352
+ const previousDay = dateObject.minus({ hours: 12 });
353
+ operationalDate = previousDay.toFormat(OPERATIONAL_DATE_FORMAT);
354
+ }
355
+ else {
356
+ // Else, return the current day in the yyyyLLdd format
357
+ operationalDate = dateObject.toFormat(OPERATIONAL_DATE_FORMAT);
358
+ }
359
+ // Return the date as an operational date
360
+ return Number(operationalDate);
361
+ }
362
+ /**
363
+ * This function returns the start and end of the standard window interval for a given timestamp.
364
+ * The standard window interval is the period in which is possible to receive data for a given ride.
365
+ * Currently, the standard window starts 10 hours before and ends 10 hours after the scheduled ride start.
366
+ * @param isoDate The ISO date string to calculate the standard window interval.
367
+ * @returns An object containing the start and end of the standard window interval.
368
+ */
369
+ getStandardWindowInterval(isoDate) {
370
+ if (!isoDate)
371
+ throw new Error('ISO date is not set.');
372
+ const dateTime = DateTime.fromISO(isoDate, { setZone: true });
373
+ return {
374
+ end: dateTime.plus({ hours: Dates.standardWindowHours }).toMillis(),
375
+ start: dateTime.minus({ hours: Dates.standardWindowHours }).toMillis(),
376
+ };
377
+ }
378
+ }
@@ -0,0 +1,8 @@
1
+ import { type OperationalDateInt } from '@tmlmobilidade/go-types-shared';
2
+ /**
3
+ * Returns an array of individual dates from a given range of operational dates.
4
+ * @param start The start date of the range, in OperationalDate format.
5
+ * @param end The end date of the range, in OperationalDate format.
6
+ * @returns An array of OperationalDate objects representing each date in the range.
7
+ */
8
+ export declare function getOperationalDatesFromRange(start: OperationalDateInt, end: OperationalDateInt): OperationalDateInt[];
@@ -0,0 +1,30 @@
1
+ /* * */
2
+ import { Dates } from '../dates.js';
3
+ /**
4
+ * Returns an array of individual dates from a given range of operational dates.
5
+ * @param start The start date of the range, in OperationalDate format.
6
+ * @param end The end date of the range, in OperationalDate format.
7
+ * @returns An array of OperationalDate objects representing each date in the range.
8
+ */
9
+ export function getOperationalDatesFromRange(start, end) {
10
+ //
11
+ //
12
+ // Validate the start and end dates
13
+ if (end < start) {
14
+ throw new Error(`End date "${end}" must be after start date "${start}"`);
15
+ }
16
+ //
17
+ // Parse the start and end dates to ensure they are in the correct format
18
+ const startDate = Dates.fromOperationalDateInt(start, 'Europe/Lisbon');
19
+ const endDate = Dates.fromOperationalDateInt(end, 'Europe/Lisbon');
20
+ //
21
+ // Create an array to hold the individual dates and iterate
22
+ // from the start date to the end date, adding each date to the array
23
+ const dates = [];
24
+ let current = startDate;
25
+ while (current.operational_date_int <= endDate.operational_date_int) {
26
+ dates.push(current.operational_date_int);
27
+ current = current.plus({ days: 1 });
28
+ }
29
+ return dates;
30
+ }
@@ -0,0 +1,2 @@
1
+ export * from './dates-from-range.js';
2
+ export * from './split-time-intervals.js';
@@ -0,0 +1,2 @@
1
+ export * from './dates-from-range.js';
2
+ export * from './split-time-intervals.js';
@@ -0,0 +1,16 @@
1
+ import { type UnixTimestamp } from '@tmlmobilidade/go-types-shared';
2
+ /**
3
+ * Splits a time interval into smaller intervals of a given duration.
4
+ * @param from The start timestamp of the interval.
5
+ * @param to The end timestamp of the interval.
6
+ * @param intervalHrs The duration of the intervals in hours.
7
+ * @returns An array of intervals.
8
+ */
9
+ export declare function splitTimeIntervals(from: UnixTimestamp, to: UnixTimestamp, intervalHrs: number): {
10
+ end: number & {
11
+ __brand: "UnixTimestamp";
12
+ };
13
+ start: number & {
14
+ __brand: "UnixTimestamp";
15
+ };
16
+ }[];
@@ -0,0 +1,47 @@
1
+ /* * */
2
+ import { UnixTimestampSchema } from '@tmlmobilidade/go-types-shared';
3
+ /**
4
+ * Splits a time interval into smaller intervals of a given duration.
5
+ * @param from The start timestamp of the interval.
6
+ * @param to The end timestamp of the interval.
7
+ * @param intervalHrs The duration of the intervals in hours.
8
+ * @returns An array of intervals.
9
+ */
10
+ export function splitTimeIntervals(from, to, intervalHrs) {
11
+ //
12
+ //
13
+ // Validate the input timestamps
14
+ if (from > to)
15
+ throw new Error('The start timestamp must be before the end timestamp');
16
+ //
17
+ // Convert the interval duration in hours to milliseconds,
18
+ // and calculate how much time is left until the next clean interval step.
19
+ // This is so the intervals are allways of the full duration, starting at 00 hours.
20
+ const intervalMs = intervalHrs * 60 * 60 * 1000;
21
+ const remainder = to % intervalMs;
22
+ //
23
+ // Store the intervals in an array and
24
+ // initialize the end timestamp with the most recent timestamp.
25
+ const finalIntervals = [];
26
+ let endTimestamp = to;
27
+ //
28
+ // Handle the first, potentially shorter interval.
29
+ // If there is a remainder, create an interval with the remainder as the duration.
30
+ if (remainder > 0) {
31
+ const startTimestamp = UnixTimestampSchema.parse(Math.max(from, endTimestamp - remainder));
32
+ finalIntervals.push({ end: endTimestamp, start: startTimestamp });
33
+ endTimestamp = startTimestamp;
34
+ }
35
+ //
36
+ // Handle the regular intervals.
37
+ // If the end timestamp is greater than the start timestamp,
38
+ // create an interval with the duration of the interval.
39
+ while (endTimestamp > from) {
40
+ const startTimestamp = UnixTimestampSchema.parse(Math.max(from, endTimestamp - intervalMs));
41
+ finalIntervals.push({ end: endTimestamp, start: startTimestamp });
42
+ endTimestamp = startTimestamp;
43
+ }
44
+ //
45
+ // Return the intervals in reverse order.
46
+ return finalIntervals.reverse();
47
+ }
@@ -0,0 +1,2 @@
1
+ export * from './dates.js';
2
+ export * from './helpers/index.js';
package/dist/index.js ADDED
@@ -0,0 +1,2 @@
1
+ export * from './dates.js';
2
+ export * from './helpers/index.js';
package/package.json ADDED
@@ -0,0 +1,49 @@
1
+ {
2
+ "name": "@tmlmobilidade/go-utils-dates",
3
+ "version": "20260828.1636.54",
4
+ "author": {
5
+ "email": "iso@tmlmobilidade.pt",
6
+ "name": "TML-ISO"
7
+ },
8
+ "license": "AGPL-3.0-or-later",
9
+ "homepage": "https://go.tmlmobilidade.pt",
10
+ "bugs": {
11
+ "url": "https://github.com/tmlmobilidade/go/issues"
12
+ },
13
+ "repository": {
14
+ "type": "git",
15
+ "url": "git+https://github.com/tmlmobilidade/go.git"
16
+ },
17
+ "keywords": [
18
+ "public transit",
19
+ "tml",
20
+ "transportes metropolitanos de lisboa",
21
+ "go"
22
+ ],
23
+ "publishConfig": {
24
+ "access": "public"
25
+ },
26
+ "type": "module",
27
+ "files": [
28
+ "dist"
29
+ ],
30
+ "main": "./dist/index.js",
31
+ "types": "./dist/index.d.ts",
32
+ "scripts": {
33
+ "build": "tsc && resolve-tspaths",
34
+ "lint": "eslint ./src/ && tsc --noEmit",
35
+ "lint:fix": "eslint ./src/ --fix",
36
+ "watch": "tsc-watch --onSuccess 'resolve-tspaths'"
37
+ },
38
+ "dependencies": {
39
+ "@tmlmobilidade/go-types-shared": "*",
40
+ "luxon": "3.7.2"
41
+ },
42
+ "devDependencies": {
43
+ "@tmlmobilidade/go-utils-tsconfig": "*",
44
+ "@types/node": "26.1.2",
45
+ "resolve-tspaths": "0.8.23",
46
+ "tsc-watch": "7.2.1",
47
+ "typescript": "6.0.3"
48
+ }
49
+ }