@gobrand/tiempo 2.3.4 → 2.3.6

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.
Files changed (2) hide show
  1. package/README.md +23 -978
  2. package/package.json +2 -2
package/README.md CHANGED
@@ -4,998 +4,43 @@
4
4
  [![CI](https://github.com/go-brand/tiempo/actions/workflows/ci.yml/badge.svg)](https://github.com/go-brand/tiempo/actions/workflows/ci.yml)
5
5
  [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
6
6
 
7
- Comprehensive datetime utilities for the [Temporal API](https://tc39.es/proposal-temporal/docs/). Full timezone support, nanosecond precision, and a familiar API.
7
+ ![tiempo clock visualization](./clock-visualization.png)
8
8
 
9
- ## Installation
9
+ **Timezone conversions that don't suck.** Built on the [Temporal API](https://tc39.es/proposal-temporal/docs/).
10
10
 
11
- ```bash
12
- npm install @gobrand/tiempo
13
- # or
14
- pnpm add @gobrand/tiempo
15
- # or
16
- yarn add @gobrand/tiempo
17
- ```
18
-
19
- ## Why tiempo?
20
-
21
- The Temporal API is powerful but requires understanding its various methods and objects. **tiempo** (`@gobrand/tiempo`) provides intuitive utilities for every datetime task:
22
-
23
- - **🌍 Timezone conversions** - Convert between UTC and any timezone effortlessly
24
- - **➕ Complete arithmetic** - Add/subtract any time unit from nanoseconds to years
25
- - **📅 Calendar operations** - Start/end of day, week, month, year with DST handling
26
- - **🔍 Comparisons** - Check if dates are before, after, same day, future, or past
27
- - **📊 Differences** - Calculate precise differences in any time unit
28
- - **🎨 Formatting** - Format dates with date-fns-style tokens or Intl
29
- - **⚡️ Type-safe** - Full TypeScript support with proper Temporal types
30
- - **🎯 Zero config** - Simple, direct function signatures
31
-
32
- **Key features:**
33
- - ✅ Native timezone support with Temporal API
34
- - ✅ DST transitions handled automatically
35
- - ✅ Nanosecond precision (beyond milliseconds)
36
- - ✅ Calendar-aware arithmetic (leap years, month-end dates)
37
- - ✅ Familiar date-fns-style API, built for the future
38
-
39
- **Perfect for:**
40
- - Social media scheduling apps
41
- - Calendar applications
42
- - Booking systems
43
- - Time tracking tools
44
- - Analytics dashboards
45
- - Any app that needs to handle user timezones
46
-
47
- ## Quick Start
48
-
49
- ```typescript
50
- import { toZonedTime, toUtcString, toUtc, toDate } from '@gobrand/tiempo';
51
-
52
- // From ISO string (typical backend API)
53
- const zoned = toZonedTime("2025-01-20T20:00:00.000Z", "America/New_York");
54
- console.log(zoned.hour); // 15 (3 PM in New York)
55
-
56
- // From Date object (e.g., Drizzle ORM)
57
- const date = new Date("2025-01-20T20:00:00.000Z");
58
- const zonedFromDate = toZonedTime(date, "America/New_York");
59
- console.log(zonedFromDate.hour); // 15 (3 PM in New York)
60
-
61
- // Back to ISO string
62
- const utcString = toUtcString(zoned);
63
- console.log(utcString); // "2025-01-20T20:00:00Z"
64
-
65
- // Back to Date object (for Drizzle ORM)
66
- const backToDate = toDate(zoned);
67
- console.log(backToDate.toISOString()); // "2025-01-20T20:00:00.000Z"
68
- ```
69
-
70
- ## API
71
-
72
- ### Core Conversions
73
-
74
- #### `toZonedTime(input, timezone)`
75
-
76
- Convert a UTC ISO string, Date, Instant, or ZonedDateTime to a ZonedDateTime in the specified timezone.
77
-
78
- **Parameters:**
79
- - `input` (string | Date | Temporal.Instant | Temporal.ZonedDateTime): A UTC ISO 8601 string, Date object, Temporal.Instant, or Temporal.ZonedDateTime
80
- - `timezone` (string): An IANA timezone identifier (e.g., `"America/New_York"`, `"Europe/London"`)
81
-
82
- **Returns:** `Temporal.ZonedDateTime` - The same instant in the specified timezone
83
-
84
- **Example:**
85
- ```typescript
86
- import { toZonedTime } from '@gobrand/tiempo';
87
-
88
- // From ISO string
89
- const zoned = toZonedTime("2025-01-20T20:00:00.000Z", "America/New_York");
90
- console.log(zoned.hour); // 15 (3 PM in New York)
91
- console.log(zoned.toString()); // "2025-01-20T15:00:00-05:00[America/New_York]"
92
-
93
- // From Date (e.g., from Drizzle ORM)
94
- const date = new Date("2025-01-20T20:00:00.000Z");
95
- const zoned2 = toZonedTime(date, "America/New_York");
96
- console.log(zoned2.hour); // 15 (3 PM in New York)
97
-
98
- // From Instant
99
- const instant = Temporal.Instant.from("2025-01-20T20:00:00Z");
100
- const zoned3 = toZonedTime(instant, "Asia/Tokyo");
101
-
102
- // From ZonedDateTime (convert to different timezone)
103
- const nyTime = Temporal.ZonedDateTime.from("2025-01-20T15:00:00-05:00[America/New_York]");
104
- const tokyoTime = toZonedTime(nyTime, "Asia/Tokyo");
105
- ```
106
-
107
- #### `toUtc(input)`
108
-
109
- Convert a UTC ISO string, Date, or ZonedDateTime to a Temporal.Instant (UTC).
110
-
111
- **Parameters:**
112
- - `input` (string | Date | Temporal.ZonedDateTime): A UTC ISO 8601 string, Date object, or Temporal.ZonedDateTime
113
-
114
- **Returns:** `Temporal.Instant` - A Temporal.Instant representing the same moment in UTC
115
-
116
- **Example:**
117
- ```typescript
118
- import { toUtc } from '@gobrand/tiempo';
119
-
120
- // From ISO string
121
- const instant = toUtc("2025-01-20T20:00:00.000Z");
122
-
123
- // From Date (e.g., from Drizzle ORM)
124
- const date = new Date("2025-01-20T20:00:00.000Z");
125
- const instant2 = toUtc(date);
126
-
127
- // From ZonedDateTime
128
- const zoned = Temporal.ZonedDateTime.from("2025-01-20T15:00:00-05:00[America/New_York]");
129
- const instant3 = toUtc(zoned);
130
- // All represent the same UTC moment: 2025-01-20T20:00:00Z
131
- ```
132
-
133
- #### `toUtcString(input)`
134
-
135
- Convert a Temporal.Instant or ZonedDateTime to a UTC ISO 8601 string.
136
-
137
- **Parameters:**
138
- - `input` (Temporal.Instant | Temporal.ZonedDateTime): A Temporal.Instant or Temporal.ZonedDateTime
139
-
140
- **Returns:** `string` - A UTC ISO 8601 string representation
141
-
142
- **Example:**
143
- ```typescript
144
- import { toUtcString } from '@gobrand/tiempo';
145
-
146
- // From ZonedDateTime
147
- const zoned = Temporal.ZonedDateTime.from("2025-01-20T15:00:00-05:00[America/New_York]");
148
- const iso = toUtcString(zoned);
149
- console.log(iso); // "2025-01-20T20:00:00Z"
150
-
151
- // From Instant
152
- const instant = Temporal.Instant.from("2025-01-20T20:00:00Z");
153
- const iso2 = toUtcString(instant);
154
- console.log(iso2); // "2025-01-20T20:00:00Z"
155
- ```
156
-
157
- #### `toDate(input)`
158
-
159
- Convert a Temporal.Instant or ZonedDateTime to a Date object.
160
-
161
- **Parameters:**
162
- - `input` (Temporal.Instant | Temporal.ZonedDateTime): A Temporal.Instant or Temporal.ZonedDateTime
163
-
164
- **Returns:** `Date` - A Date object representing the same moment in time
165
-
166
- **Example:**
167
- ```typescript
168
- import { toDate } from '@gobrand/tiempo';
169
-
170
- // From Instant
171
- const instant = Temporal.Instant.from("2025-01-20T20:00:00Z");
172
- const date = toDate(instant);
173
- console.log(date.toISOString()); // "2025-01-20T20:00:00.000Z"
174
-
175
- // From ZonedDateTime
176
- const zoned = Temporal.ZonedDateTime.from("2025-01-20T15:00:00-05:00[America/New_York]");
177
- const date2 = toDate(zoned);
178
- console.log(date2.toISOString()); // "2025-01-20T20:00:00.000Z"
179
-
180
- // Use with Drizzle ORM (for storing back to database)
181
- const instant = Temporal.Instant.from("2025-01-20T20:00:00Z");
182
- const dateForDb = toDate(instant);
183
- await db.update(posts).set({ publishedAt: dateForDb });
184
- ```
185
-
186
- ### Formatting
187
-
188
- #### `intlFormatDistance(laterDate, earlierDate, options?)`
189
-
190
- Format the distance between two dates as a human-readable, internationalized string using `Intl.RelativeTimeFormat`. Automatically selects the most appropriate unit (seconds, minutes, hours, days, weeks, months, years) based on the distance.
191
-
192
- **Parameters:**
193
- - `laterDate` (Temporal.Instant | Temporal.ZonedDateTime): The later date to compare
194
- - `earlierDate` (Temporal.Instant | Temporal.ZonedDateTime): The earlier date to compare with
195
- - `options` (IntlFormatDistanceOptions, optional): Formatting options
196
- - `unit` (Intl.RelativeTimeFormatUnit): Force a specific unit instead of automatic selection
197
- - `locale` (string | string[]): Locale for formatting (default: system locale)
198
- - `numeric` ('always' | 'auto'): Use numeric values always or allow natural language like "tomorrow" (default: 'auto')
199
- - `style` ('long' | 'short' | 'narrow'): Formatting style (default: 'long')
200
- - `localeMatcher` ('best fit' | 'lookup'): Locale matching algorithm
201
-
202
- **Returns:** `string` - Formatted relative time string
203
-
204
- **Automatic unit selection:**
205
- - < 60 seconds → "in X seconds" / "X seconds ago"
206
- - < 60 minutes → "in X minutes" / "X minutes ago"
207
- - < 24 hours → "in X hours" / "X hours ago"
208
- - < 7 days → "tomorrow" / "yesterday" / "in X days" / "X days ago"
209
- - < 4 weeks → "next week" / "last week" / "in X weeks" / "X weeks ago"
210
- - < 12 months → "next month" / "last month" / "in X months" / "X months ago"
211
- - ≥ 12 months → "next year" / "last year" / "in X years" / "X years ago"
212
-
213
- **Example:**
214
- ```typescript
215
- import { intlFormatDistance } from '@gobrand/tiempo';
216
-
217
- const later = Temporal.Instant.from('2025-01-20T12:00:00Z');
218
- const earlier = Temporal.Instant.from('2025-01-20T11:00:00Z');
219
-
220
- // Basic usage
221
- intlFormatDistance(later, earlier);
222
- // => "in 1 hour"
223
-
224
- intlFormatDistance(earlier, later);
225
- // => "1 hour ago"
226
-
227
- // With different locales
228
- intlFormatDistance(later, earlier, { locale: 'es' });
229
- // => "dentro de 1 hora"
230
-
231
- intlFormatDistance(later, earlier, { locale: 'ja' });
232
- // => "1 時間後"
233
-
234
- // Force numeric format
235
- const tomorrow = Temporal.Instant.from('2025-01-21T00:00:00Z');
236
- const today = Temporal.Instant.from('2025-01-20T00:00:00Z');
237
-
238
- intlFormatDistance(tomorrow, today, { numeric: 'auto' });
239
- // => "tomorrow"
240
-
241
- intlFormatDistance(tomorrow, today, { numeric: 'always' });
242
- // => "in 1 day"
243
-
244
- // Different styles
245
- const future = Temporal.Instant.from('2027-01-20T00:00:00Z');
246
- const now = Temporal.Instant.from('2025-01-20T00:00:00Z');
247
-
248
- intlFormatDistance(future, now, { style: 'long' });
249
- // => "in 2 years"
250
-
251
- intlFormatDistance(future, now, { style: 'short' });
252
- // => "in 2 yr."
253
-
254
- intlFormatDistance(future, now, { style: 'narrow' });
255
- // => "in 2y"
256
-
257
- // Force specific units
258
- intlFormatDistance(future, now, { unit: 'quarter' });
259
- // => "in 8 quarters"
260
-
261
- const dayLater = Temporal.Instant.from('2025-01-21T00:00:00Z');
262
- intlFormatDistance(dayLater, today, { unit: 'hour' });
263
- // => "in 24 hours"
264
- ```
265
-
266
- #### `format(input, formatStr, options?)`
267
-
268
- Format a Temporal.Instant or ZonedDateTime using date-fns-like format tokens.
269
-
270
- **Parameters:**
271
- - `input` (Temporal.Instant | Temporal.ZonedDateTime): A Temporal.Instant or Temporal.ZonedDateTime to format
272
- - `formatStr` (string): Format string using date-fns tokens (e.g., "yyyy-MM-dd HH:mm:ss")
273
- - `options` (FormatOptions, optional): Configuration for locale and timezone
274
- - `locale` (string): BCP 47 language tag (default: "en-US")
275
- - `timeZone` (string): IANA timezone identifier to convert to before formatting
276
-
277
- **Returns:** `string` - Formatted date string
278
-
279
- **Supported tokens:**
280
- - **Year**: `yyyy` (2025), `yy` (25), `y` (2025)
281
- - **Month**: `MMMM` (January), `MMM` (Jan), `MM` (01), `M` (1), `Mo` (1st)
282
- - **Day**: `dd` (20), `d` (20), `do` (20th)
283
- - **Weekday**: `EEEE` (Monday), `EEE` (Mon), `EEEEE` (M)
284
- - **Hour**: `HH` (15, 24h), `H` (15), `hh` (03, 12h), `h` (3)
285
- - **Minute**: `mm` (30), `m` (30)
286
- - **Second**: `ss` (45), `s` (45)
287
- - **AM/PM**: `a` (PM), `aa` (PM), `aaa` (pm), `aaaa` (p.m.), `aaaaa` (p)
288
- - **Timezone**: `xxx` (-05:00), `xx` (-0500), `XXX` (Z or -05:00), `zzzz` (Eastern Standard Time)
289
- - **Quarter**: `Q` (1), `QQQ` (Q1), `QQQQ` (1st quarter)
290
- - **Milliseconds**: `SSS` (123)
291
- - **Timestamp**: `T` (milliseconds), `t` (seconds)
292
- - **Escape text**: Use single quotes `'...'`, double single quotes `''` for literal quote
293
-
294
- **Example:**
295
- ```typescript
296
- import { format, toZonedTime, toUtc } from '@gobrand/tiempo';
297
-
298
- // From ISO string to ZonedDateTime, then format
299
- const isoString = "2025-01-20T20:30:45.000Z";
300
- const zoned = toZonedTime(isoString, "America/New_York");
301
-
302
- format(zoned, "yyyy-MM-dd"); // "2025-01-20"
303
- format(zoned, "MMMM d, yyyy"); // "January 20, 2025"
304
- format(zoned, "h:mm a"); // "3:30 PM"
305
- format(zoned, "EEEE, MMMM do, yyyy 'at' h:mm a"); // "Monday, January 20th, 2025 at 3:30 PM"
306
-
307
- // With locale
308
- format(zoned, "MMMM d, yyyy", { locale: "es-ES" }); // "enero 20, 2025"
309
- format(zoned, "EEEE", { locale: "fr-FR" }); // "lundi"
310
-
311
- // From ISO string to Instant (UTC), then format with timezone conversion
312
- const instant = toUtc(isoString);
313
- format(instant, "yyyy-MM-dd HH:mm", { timeZone: "America/New_York" }); // "2025-01-20 15:30"
314
- format(instant, "yyyy-MM-dd HH:mm", { timeZone: "Asia/Tokyo" }); // "2025-01-21 05:30"
315
- ```
316
-
317
- #### `formatPlainDate(date, formatStr, options?)`
318
-
319
- Format a Temporal.PlainDate using date-fns-like format tokens. Only supports date-related tokens (no time or timezone tokens).
320
-
321
- **Parameters:**
322
- - `date` (Temporal.PlainDate): A Temporal.PlainDate to format
323
- - `formatStr` (string): Format string using date-fns tokens (e.g., "yyyy-MM-dd")
324
- - `options` (FormatPlainDateOptions, optional): Configuration for locale
325
- - `locale` (string): BCP 47 language tag (default: "en-US")
326
-
327
- **Returns:** `string` - Formatted date string
328
-
329
- **Supported tokens:**
330
- - **Year**: `yyyy` (2025), `yy` (25), `y` (2025)
331
- - **Month**: `MMMM` (January), `MMM` (Jan), `MM` (01), `M` (1), `Mo` (1st)
332
- - **Day**: `dd` (20), `d` (20), `do` (20th)
333
- - **Weekday**: `EEEE` (Monday), `EEE` (Mon), `EEEEE` (M)
334
- - **Quarter**: `Q` (1), `QQQ` (Q1), `QQQQ` (1st quarter)
335
- - **Era**: `G` (AD), `GGGG` (Anno Domini)
336
- - **Escape text**: Use single quotes `'...'`, double single quotes `''` for literal quote
337
-
338
- **Example:**
339
- ```typescript
340
- import { formatPlainDate, today } from '@gobrand/tiempo';
341
-
342
- const date = Temporal.PlainDate.from("2025-01-20");
343
-
344
- formatPlainDate(date, "yyyy-MM-dd"); // "2025-01-20"
345
- formatPlainDate(date, "MMMM d, yyyy"); // "January 20, 2025"
346
- formatPlainDate(date, "EEEE, MMMM do, yyyy"); // "Monday, January 20th, 2025"
347
- formatPlainDate(date, "MM/dd/yyyy"); // "01/20/2025"
348
-
349
- // With locale
350
- formatPlainDate(date, "MMMM d, yyyy", { locale: "es-ES" }); // "enero 20, 2025"
351
- formatPlainDate(date, "EEEE", { locale: "de-DE" }); // "Montag"
352
-
353
- // Use with today()
354
- const todayFormatted = formatPlainDate(today(), "EEEE, MMMM do");
355
- // "Thursday, January 23rd"
356
- ```
357
-
358
- #### `simpleFormat(input, options?)`
359
-
360
- Format a Temporal date in a human-friendly way: "Dec 23" or "Dec 23, 2020". By default, shows the year only if the date is not in the current year. Optionally includes time in 12-hour or 24-hour format.
361
-
362
- **Parameters:**
363
- - `input` (Temporal.PlainDate | Temporal.ZonedDateTime | Temporal.Instant): The date to format
364
- - `options` (object, optional): Formatting options
365
- - `locale` (string): BCP 47 language tag (default: "en-US")
366
- - `year` ('auto' | 'always' | 'never'): Control year display (default: 'auto')
367
- - `time` ('12h' | '24h'): Include time in output (not available for PlainDate)
368
- - `timeZone` (string): IANA timezone identifier (required for Instant, optional for ZonedDateTime)
369
-
370
- **Returns:** `string` - Human-friendly formatted date string
371
-
372
- **Example:**
373
- ```typescript
374
- import { simpleFormat, today, now } from '@gobrand/tiempo';
375
-
376
- // Assuming current year is 2026
377
- const date2026 = Temporal.ZonedDateTime.from("2026-12-23T15:30:00[America/New_York]");
378
- const date2020 = Temporal.ZonedDateTime.from("2020-12-23T15:30:00[America/New_York]");
379
-
380
- // Basic usage - year shown only for past years
381
- simpleFormat(date2026); // "Dec 23"
382
- simpleFormat(date2020); // "Dec 23, 2020"
383
-
384
- // With time
385
- simpleFormat(date2026, { time: '12h' }); // "Dec 23, 3:30 PM"
386
- simpleFormat(date2026, { time: '24h' }); // "Dec 23, 15:30"
387
-
388
- // Control year display
389
- simpleFormat(date2026, { year: 'always' }); // "Dec 23, 2026"
390
- simpleFormat(date2020, { year: 'never' }); // "Dec 23"
391
-
392
- // With Instant (timeZone required)
393
- const instant = Temporal.Instant.from("2026-12-23T20:30:00Z");
394
- simpleFormat(instant, { timeZone: 'America/New_York' }); // "Dec 23"
395
- simpleFormat(instant, { timeZone: 'America/New_York', time: '12h' }); // "Dec 23, 3:30 PM"
396
-
397
- // With PlainDate (no time option available)
398
- const plain = Temporal.PlainDate.from("2020-12-23");
399
- simpleFormat(plain); // "Dec 23, 2020"
400
-
401
- // Different locales
402
- simpleFormat(date2020, { locale: 'es-ES' }); // "23 dic 2020"
403
- simpleFormat(date2020, { locale: 'de-DE' }); // "23. Dez. 2020"
404
- ```
405
-
406
- ### Start/End Utilities
407
-
408
- #### `today(timezone?)`
409
-
410
- Get today's date in the system's local timezone or a specified timezone.
411
-
412
- **Parameters:**
413
- - `timezone` (string, optional): An IANA timezone identifier (e.g., `"America/New_York"`, `"Europe/Madrid"`) or `"UTC"`. If not provided, uses the system's local timezone.
414
-
415
- **Returns:** `Temporal.PlainDate` - A Temporal.PlainDate representing today's date
416
-
417
- **Example:**
418
- ```typescript
419
- import { today } from '@gobrand/tiempo';
420
-
421
- const date = today(); // 2025-01-20
422
- date.year; // 2025
423
- date.month; // 1
424
- date.day; // 20
425
-
426
- // Get today in a specific timezone
427
- const dateInTokyo = today("Asia/Tokyo"); // 2025-01-21 (next day due to timezone)
428
- ```
429
-
430
- #### `now(timezone?)`
431
-
432
- Get the current date and time in the system's local timezone or a specified timezone.
433
-
434
- **Parameters:**
435
- - `timezone` (string, optional): An IANA timezone identifier (e.g., `"America/New_York"`, `"Europe/Madrid"`) or `"UTC"`. If not provided, uses the system's local timezone.
436
-
437
- **Returns:** `Temporal.ZonedDateTime` - A Temporal.ZonedDateTime representing the current date and time
438
-
439
- **Example:**
440
- ```typescript
441
- import { now } from '@gobrand/tiempo';
442
-
443
- const current = now(); // 2025-01-20T15:30:45.123-05:00[America/New_York]
444
- current.hour; // 15
445
- current.minute; // 30
446
-
447
- // Get current time in a specific timezone
448
- const currentInTokyo = now("Asia/Tokyo"); // 2025-01-21T05:30:45.123+09:00[Asia/Tokyo]
449
- ```
450
-
451
- #### `startOfDay(input)` / `endOfDay(input)`
452
-
453
- Get the start or end of the day for a given datetime.
454
-
455
- ```typescript
456
- import { startOfDay, endOfDay } from '@gobrand/tiempo';
457
-
458
- const zoned = Temporal.ZonedDateTime.from('2025-01-20T15:30:00-05:00[America/New_York]');
459
-
460
- startOfDay(zoned); // 2025-01-20T00:00:00-05:00[America/New_York]
461
- endOfDay(zoned); // 2025-01-20T23:59:59.999999999-05:00[America/New_York]
462
- ```
463
-
464
- #### `startOfWeek(input)` / `endOfWeek(input)`
465
-
466
- Get the start or end of the week. Uses ISO 8601 week definition (Monday to Sunday).
467
-
468
- ```typescript
469
- import { startOfWeek, endOfWeek } from '@gobrand/tiempo';
470
-
471
- const zoned = Temporal.ZonedDateTime.from('2025-01-20T15:30:00-05:00[America/New_York]'); // Monday
472
-
473
- startOfWeek(zoned); // 2025-01-20T00:00:00-05:00[America/New_York] (Monday)
474
- endOfWeek(zoned); // 2025-01-26T23:59:59.999999999-05:00[America/New_York] (Sunday)
475
- ```
476
-
477
- #### `startOfMonth(input)` / `endOfMonth(input)`
478
-
479
- Get the start or end of the month.
480
-
481
- ```typescript
482
- import { startOfMonth, endOfMonth } from '@gobrand/tiempo';
483
-
484
- const zoned = Temporal.ZonedDateTime.from('2025-01-20T15:30:00-05:00[America/New_York]');
485
-
486
- startOfMonth(zoned); // 2025-01-01T00:00:00-05:00[America/New_York]
487
- endOfMonth(zoned); // 2025-01-31T23:59:59.999999999-05:00[America/New_York]
488
- ```
489
-
490
- #### `startOfYear(input)` / `endOfYear(input)`
491
-
492
- Get the start or end of the year.
493
-
494
- ```typescript
495
- import { startOfYear, endOfYear } from '@gobrand/tiempo';
496
-
497
- const zoned = Temporal.ZonedDateTime.from('2025-01-20T15:30:00-05:00[America/New_York]');
498
-
499
- startOfYear(zoned); // 2025-01-01T00:00:00-05:00[America/New_York]
500
- endOfYear(zoned); // 2025-12-31T23:59:59.999999999-05:00[America/New_York]
501
- ```
502
-
503
- ### Addition/Subtraction Utilities
504
-
505
- tiempo provides comprehensive datetime arithmetic functions for all time units, from nanoseconds to years. All functions:
506
- - Accept `Temporal.Instant` or `Temporal.ZonedDateTime` as input
507
- - Return `Temporal.ZonedDateTime` preserving the original timezone
508
- - Properly handle DST transitions, leap years, and month-end edge cases
509
- - Support negative values for subtraction
510
-
511
- #### Addition Functions
512
-
513
- ##### `addYears(input, years)` / `addMonths(input, months)` / `addWeeks(input, weeks)` / `addDays(input, days)`
514
-
515
- Add calendar units (years, months, weeks, or days) to a datetime.
516
-
517
- ```typescript
518
- import { addYears, addMonths, addWeeks, addDays } from '@gobrand/tiempo';
519
-
520
- const date = Temporal.Instant.from('2025-01-20T12:00:00Z');
521
-
522
- addYears(date, 2); // 2027-01-20T12:00:00Z[UTC] (2 years later)
523
- addMonths(date, 3); // 2025-04-20T12:00:00Z[UTC] (3 months later)
524
- addWeeks(date, 2); // 2025-02-03T12:00:00Z[UTC] (2 weeks later)
525
- addDays(date, 5); // 2025-01-25T12:00:00Z[UTC] (5 days later)
526
-
527
- // Handle month-end edge cases automatically
528
- const endOfJan = Temporal.Instant.from('2025-01-31T12:00:00Z');
529
- addMonths(endOfJan, 1); // 2025-02-28T12:00:00Z[UTC] (Jan 31 → Feb 28)
530
-
531
- // Negative values subtract
532
- addMonths(date, -3); // 2024-10-20T12:00:00Z[UTC] (3 months earlier)
533
- ```
534
-
535
- ##### `addHours(input, hours)` / `addMinutes(input, minutes)` / `addSeconds(input, seconds)`
536
-
537
- Add time units (hours, minutes, or seconds) to a datetime.
11
+ 👉 **[Documentation](https://eng.gobrand.app/tiempo)**
538
12
 
539
- ```typescript
540
- import { addHours, addMinutes, addSeconds } from '@gobrand/tiempo';
541
-
542
- const time = Temporal.Instant.from('2025-01-20T12:00:00Z');
543
-
544
- addHours(time, 3); // 2025-01-20T15:00:00Z[UTC] (3 hours later)
545
- addMinutes(time, 30); // 2025-01-20T12:30:00Z[UTC] (30 minutes later)
546
- addSeconds(time, 45); // 2025-01-20T12:00:45Z[UTC] (45 seconds later)
547
-
548
- // Works with ZonedDateTime and preserves timezone
549
- const ny = Temporal.ZonedDateTime.from('2025-01-20T15:00:00-05:00[America/New_York]');
550
- addHours(ny, 2); // 2025-01-20T17:00:00-05:00[America/New_York]
551
- ```
552
-
553
- ##### `addMilliseconds(input, ms)` / `addMicroseconds(input, μs)` / `addNanoseconds(input, ns)`
554
-
555
- Add sub-second precision units (milliseconds, microseconds, or nanoseconds) to a datetime.
556
-
557
- ```typescript
558
- import { addMilliseconds, addMicroseconds, addNanoseconds } from '@gobrand/tiempo';
559
-
560
- const precise = Temporal.Instant.from('2025-01-20T12:00:00Z');
561
-
562
- addMilliseconds(precise, 500); // 2025-01-20T12:00:00.500Z[UTC]
563
- addMicroseconds(precise, 500); // 2025-01-20T12:00:00.000500Z[UTC]
564
- addNanoseconds(precise, 500); // 2025-01-20T12:00:00.000000500Z[UTC]
565
- ```
566
-
567
- #### Subtraction Functions
568
-
569
- All subtraction functions are convenience wrappers that call their corresponding addition functions with negated values.
570
-
571
- ##### `subYears(input, years)` / `subMonths(input, months)` / `subWeeks(input, weeks)` / `subDays(input, days)`
572
-
573
- ```typescript
574
- import { subYears, subMonths, subWeeks, subDays } from '@gobrand/tiempo';
575
-
576
- const date = Temporal.Instant.from('2025-01-20T12:00:00Z');
577
-
578
- subYears(date, 2); // 2023-01-20T12:00:00Z[UTC] (2 years earlier)
579
- subMonths(date, 3); // 2024-10-20T12:00:00Z[UTC] (3 months earlier)
580
- subWeeks(date, 2); // 2025-01-06T12:00:00Z[UTC] (2 weeks earlier)
581
- subDays(date, 5); // 2025-01-15T12:00:00Z[UTC] (5 days earlier)
582
- ```
583
-
584
- ##### `subHours(input, hours)` / `subMinutes(input, minutes)` / `subSeconds(input, seconds)`
585
-
586
- ```typescript
587
- import { subHours, subMinutes, subSeconds } from '@gobrand/tiempo';
588
-
589
- const time = Temporal.Instant.from('2025-01-20T12:00:00Z');
590
-
591
- subHours(time, 3); // 2025-01-20T09:00:00Z[UTC] (3 hours earlier)
592
- subMinutes(time, 30); // 2025-01-20T11:30:00Z[UTC] (30 minutes earlier)
593
- subSeconds(time, 45); // 2025-01-20T11:59:15Z[UTC] (45 seconds earlier)
594
- ```
595
-
596
- ##### `subMilliseconds(input, ms)` / `subMicroseconds(input, μs)` / `subNanoseconds(input, ns)`
597
-
598
- ```typescript
599
- import { subMilliseconds, subMicroseconds, subNanoseconds } from '@gobrand/tiempo';
600
-
601
- const precise = Temporal.Instant.from('2025-01-20T12:00:00.500Z');
602
-
603
- subMilliseconds(precise, 250); // 2025-01-20T12:00:00.250Z[UTC]
604
- subMicroseconds(precise, 250); // 2025-01-20T12:00:00.499750Z[UTC]
605
- subNanoseconds(precise, 250); // 2025-01-20T12:00:00.499999750Z[UTC]
606
- ```
607
-
608
- #### Real-world Example: Meeting Scheduler
609
-
610
- ```typescript
611
- import {
612
- toZonedTime,
613
- addDays,
614
- addMinutes,
615
- format
616
- } from '@gobrand/tiempo';
617
-
618
- // User's current meeting time
619
- const meeting = toZonedTime('2025-01-20T15:00:00Z', 'America/New_York');
620
- // 2025-01-20T10:00:00-05:00[America/New_York] (10 AM in NY)
621
-
622
- // Reschedule to tomorrow, same time
623
- const tomorrow = addDays(meeting, 1);
624
- format(tomorrow, 'EEEE, MMMM do'); // "Tuesday, January 21st"
625
-
626
- // Add 30-minute buffer before the meeting
627
- const arriveBy = subMinutes(tomorrow, 30);
628
- format(arriveBy, 'h:mm a'); // "9:30 AM"
629
-
630
- // Schedule follow-up 2 weeks later
631
- const followUp = addWeeks(tomorrow, 2);
632
- format(followUp, 'MMM d'); // "Feb 4"
633
- ```
634
-
635
- ### Comparison Utilities
636
-
637
- #### `isBefore(date1, date2)` / `isAfter(date1, date2)`
638
-
639
- Check if the first datetime is before or after the second. Compares the underlying instant in time.
640
-
641
- ```typescript
642
- import { isBefore, isAfter } from '@gobrand/tiempo';
643
-
644
- const earlier = Temporal.ZonedDateTime.from('2025-01-20T10:00:00-05:00[America/New_York]');
645
- const later = Temporal.ZonedDateTime.from('2025-01-20T15:00:00-05:00[America/New_York]');
646
-
647
- isBefore(earlier, later); // true
648
- isBefore(later, earlier); // false
649
-
650
- isAfter(later, earlier); // true
651
- isAfter(earlier, later); // false
652
- ```
653
-
654
- ### Difference Utilities
655
-
656
- All difference functions compare the underlying instant in time and return a positive value if laterDate is after earlierDate, negative if before.
657
-
658
- #### Time-based precision (instant comparison)
659
-
660
- ##### `differenceInNanoseconds(laterDate, earlierDate)`
661
-
662
- Returns the difference in nanoseconds as a BigInt. Provides the highest precision available in Temporal.
663
-
664
- ```typescript
665
- import { differenceInNanoseconds } from '@gobrand/tiempo';
666
-
667
- const later = Temporal.Instant.from('2025-01-20T12:30:20.000000500Z');
668
- const earlier = Temporal.Instant.from('2025-01-20T12:30:20.000000000Z');
669
- differenceInNanoseconds(later, earlier); // 500n
670
- ```
671
-
672
- ##### `differenceInMicroseconds(laterDate, earlierDate)`
673
-
674
- Returns the difference in microseconds (1/1,000,000 second).
675
-
676
- ```typescript
677
- import { differenceInMicroseconds } from '@gobrand/tiempo';
678
-
679
- const later = Temporal.Instant.from('2025-01-20T12:30:20.001000Z');
680
- const earlier = Temporal.Instant.from('2025-01-20T12:30:20.000000Z');
681
- differenceInMicroseconds(later, earlier); // 1000
682
- ```
683
-
684
- ##### `differenceInMilliseconds(laterDate, earlierDate)`
685
-
686
- Returns the difference in milliseconds (1/1,000 second).
687
-
688
- ```typescript
689
- import { differenceInMilliseconds } from '@gobrand/tiempo';
690
-
691
- const later = Temporal.Instant.from('2025-01-20T12:30:21.700Z');
692
- const earlier = Temporal.Instant.from('2025-01-20T12:30:20.600Z');
693
- differenceInMilliseconds(later, earlier); // 1100
694
- ```
695
-
696
- ##### `differenceInSeconds(laterDate, earlierDate)`
697
-
698
- Returns the difference in seconds (truncates sub-second precision).
699
-
700
- ```typescript
701
- import { differenceInSeconds } from '@gobrand/tiempo';
702
-
703
- const later = Temporal.Instant.from('2025-01-20T12:30:25Z');
704
- const earlier = Temporal.Instant.from('2025-01-20T12:30:20Z');
705
- differenceInSeconds(later, earlier); // 5
706
- ```
707
-
708
- ##### `differenceInMinutes(laterDate, earlierDate)`
709
-
710
- Returns the difference in minutes (truncates sub-minute precision).
711
-
712
- ```typescript
713
- import { differenceInMinutes } from '@gobrand/tiempo';
714
-
715
- const later = Temporal.Instant.from('2025-01-20T12:45:00Z');
716
- const earlier = Temporal.Instant.from('2025-01-20T12:30:00Z');
717
- differenceInMinutes(later, earlier); // 15
718
- ```
719
-
720
- ##### `differenceInHours(laterDate, earlierDate)`
721
-
722
- Returns the difference in hours (truncates sub-hour precision).
723
-
724
- ```typescript
725
- import { differenceInHours } from '@gobrand/tiempo';
726
-
727
- const later = Temporal.Instant.from('2025-01-20T18:00:00Z');
728
- const earlier = Temporal.Instant.from('2025-01-20T15:00:00Z');
729
- differenceInHours(later, earlier); // 3
730
- ```
731
-
732
- #### Calendar-aware precision
733
-
734
- These functions use Temporal's `until()` method to account for variable-length calendar units.
735
-
736
- ##### `differenceInDays(laterDate, earlierDate)`
737
-
738
- Returns the difference in days. Calendar-aware, so it properly handles DST transitions where days can be 23, 24, or 25 hours.
739
-
740
- ```typescript
741
- import { differenceInDays } from '@gobrand/tiempo';
742
-
743
- const later = Temporal.Instant.from('2025-01-25T12:00:00Z');
744
- const earlier = Temporal.Instant.from('2025-01-20T12:00:00Z');
745
- differenceInDays(later, earlier); // 5
746
-
747
- // Handles DST transitions correctly
748
- const afterDst = Temporal.ZonedDateTime.from('2025-03-10T12:00:00-04:00[America/New_York]');
749
- const beforeDst = Temporal.ZonedDateTime.from('2025-03-08T12:00:00-05:00[America/New_York]');
750
- differenceInDays(afterDst, beforeDst); // 2 (calendar days, not 48 hours)
751
- ```
752
-
753
- ##### `differenceInWeeks(laterDate, earlierDate)`
754
-
755
- Returns the difference in weeks (7-day periods).
756
-
757
- ```typescript
758
- import { differenceInWeeks } from '@gobrand/tiempo';
759
-
760
- const later = Temporal.Instant.from('2025-02-10T12:00:00Z');
761
- const earlier = Temporal.Instant.from('2025-01-20T12:00:00Z');
762
- differenceInWeeks(later, earlier); // 3
763
- ```
764
-
765
- ##### `differenceInMonths(laterDate, earlierDate)`
766
-
767
- Returns the difference in months. Calendar-aware, properly handling months with different numbers of days (28-31).
768
-
769
- ```typescript
770
- import { differenceInMonths } from '@gobrand/tiempo';
771
-
772
- const later = Temporal.Instant.from('2025-04-20T12:00:00Z');
773
- const earlier = Temporal.Instant.from('2025-01-20T12:00:00Z');
774
- differenceInMonths(later, earlier); // 3
775
- ```
776
-
777
- ##### `differenceInYears(laterDate, earlierDate)`
778
-
779
- Returns the difference in years. Calendar-aware, properly handling leap years (366 days) and regular years (365 days).
780
-
781
- ```typescript
782
- import { differenceInYears } from '@gobrand/tiempo';
783
-
784
- const later = Temporal.Instant.from('2028-01-20T12:00:00Z');
785
- const earlier = Temporal.Instant.from('2025-01-20T12:00:00Z');
786
- differenceInYears(later, earlier); // 3
787
-
788
- // Calculate age
789
- const today = Temporal.ZonedDateTime.from('2025-01-20T12:00:00Z[UTC]');
790
- const birthdate = Temporal.ZonedDateTime.from('1990-01-20T12:00:00Z[UTC]');
791
- differenceInYears(today, birthdate); // 35
792
- ```
793
-
794
- #### `isFuture(date)` / `isPast(date)`
795
-
796
- Check if a datetime is in the future or past relative to the current moment. Compares against `Temporal.Now.instant()`.
797
-
798
- ```typescript
799
- import { isFuture, isPast } from '@gobrand/tiempo';
800
-
801
- const tomorrow = Temporal.Now.zonedDateTimeISO().add({ days: 1 });
802
- const yesterday = Temporal.Now.zonedDateTimeISO().subtract({ days: 1 });
803
-
804
- isFuture(tomorrow); // true
805
- isFuture(yesterday); // false
806
-
807
- isPast(yesterday); // true
808
- isPast(tomorrow); // false
809
- ```
810
-
811
- #### `isSameDay(date1, date2)`
812
-
813
- Check if two datetimes fall on the same calendar day. Compares year, month, and day fields directly.
814
-
815
- **Important:** For ZonedDateTime inputs with different timezones, each date is compared in its own timezone. Convert to a common timezone first if you need a specific perspective.
816
-
817
- ```typescript
818
- import { isSameDay } from '@gobrand/tiempo';
819
-
820
- // Same timezone, same day
821
- const morning = Temporal.ZonedDateTime.from('2025-01-20T08:00:00Z[UTC]');
822
- const evening = Temporal.ZonedDateTime.from('2025-01-20T23:00:00Z[UTC]');
823
- isSameDay(morning, evening); // true
824
-
825
- // Different timezones - compares in their respective timezones
826
- const ny = Temporal.ZonedDateTime.from('2025-01-20T23:00:00-05:00[America/New_York]');
827
- const tokyo = Temporal.ZonedDateTime.from('2025-01-21T13:00:00+09:00[Asia/Tokyo]');
828
- isSameDay(ny, tokyo); // false (Jan 20 in NY, Jan 21 in Tokyo)
829
-
830
- // Convert to UTC to compare in UTC timezone
831
- isSameDay(ny.withTimeZone('UTC'), tokyo.withTimeZone('UTC')); // true (both Jan 21 in UTC)
832
-
833
- // Instant inputs are automatically converted to UTC
834
- const instant1 = Temporal.Instant.from('2025-01-20T10:00:00Z');
835
- const instant2 = Temporal.Instant.from('2025-01-20T23:00:00Z');
836
- isSameDay(instant1, instant2); // true (both Jan 20 in UTC)
837
- ```
838
-
839
- ## Drizzle ORM Integration
840
-
841
- tiempo seamlessly integrates with Drizzle ORM for database datetime operations. When using Drizzle with PostgreSQL `timestamptz` columns and `mode: 'date'`, tiempo provides utilities to convert between Date objects and Temporal.
842
-
843
- ```typescript
844
- import { toZonedTime, toUtc, toDate } from '@gobrand/tiempo';
845
-
846
- // 1. Reading from database (Drizzle returns Date with mode: 'date')
847
- const post = await db.query.posts.findFirst();
848
- const publishedAt = post.publishedAt; // Date object
849
-
850
- // 2. Convert to user's timezone for display
851
- const userTimezone = "America/New_York";
852
- const zonedTime = toZonedTime(publishedAt, userTimezone);
853
- console.log(zonedTime.hour); // Local hour in user's timezone
854
-
855
- // 3. User reschedules post to tomorrow at 3 PM their time
856
- const rescheduled = zonedTime.add({ days: 1 }).with({ hour: 15, minute: 0 });
857
-
858
- // 4. Convert back to Date for database storage
859
- const dateForDb = toDate(rescheduled);
860
- await db.update(posts).set({ publishedAt: dateForDb }).where(eq(posts.id, post.id));
861
- ```
862
-
863
- **Why this works:**
864
- - Drizzle's `mode: 'date'` returns JavaScript `Date` objects (timestamps)
865
- - `toZonedTime(date, tz)` converts the Date to a timezone-aware Temporal object
866
- - Work with Temporal's powerful API for date arithmetic and manipulation
867
- - `toDate(temporal)` converts back to Date for Drizzle storage
868
-
869
- ## Real World Examples
870
-
871
- ### Example 1: Social Media Post Scheduler
872
-
873
- This example demonstrates the complete workflow of working with datetimes in a frontend application: receiving a UTC ISO 8601 string from your backend, converting it to a Temporal object in the user's timezone, formatting it for display, manipulating it with tiempo's arithmetic functions, and sending it back to your backend as a UTC ISO 8601 string.
13
+ - **Zero timezone bugs** - Real IANA timezone support, not UTC offset hacks
14
+ - **DST-aware math** - `addDays(1)` means tomorrow, even across clock changes
15
+ - **Nanosecond precision** - When milliseconds aren't enough
16
+ - **Type-safe** - Full TypeScript, catches datetime errors at compile time
17
+ - **Familiar API** - If you've used date-fns, you already know this
874
18
 
875
19
  ```typescript
876
- import {
877
- toZonedTime,
878
- toUtcString,
879
- format,
880
- addDays,
881
- addHours,
882
- subMinutes
883
- } from '@gobrand/tiempo';
884
-
885
- // 1. Receive UTC ISO 8601 string from backend
886
- const scheduledAtUTC = "2025-01-20T20:00:00.000Z";
887
-
888
- // 2. Convert to user's timezone (Temporal.ZonedDateTime)
889
- const userTimezone = "America/New_York";
890
- const zonedDateTime = toZonedTime(scheduledAtUTC, userTimezone);
891
-
892
- // 3. Format for display in the UI
893
- const displayTime = format(zonedDateTime, "EEEE, MMMM do 'at' h:mm a");
894
- console.log(displayTime); // "Monday, January 20th at 3:00 PM"
895
-
896
- // 4. User wants to reschedule to tomorrow, 2 hours later
897
- const tomorrow = addDays(zonedDateTime, 1);
898
- const twoHoursLater = addHours(tomorrow, 2);
899
-
900
- // 5. Format the updated time for confirmation
901
- const confirmTime = format(twoHoursLater, "EEEE 'at' h:mm a");
902
- console.log(`Rescheduled to ${confirmTime}`); // "Tuesday at 5:00 PM"
903
-
904
- // 6. Convert back to UTC ISO 8601 string for backend
905
- const updatedUTC = toUtcString(twoHoursLater);
906
- console.log(updatedUTC); // "2025-01-21T22:00:00Z"
907
- ```
908
-
909
- ### Example 2: Meeting Reminder System
910
-
911
- ```typescript
912
- import {
913
- toZonedTime,
914
- format,
915
- subMinutes,
916
- subHours,
917
- differenceInMinutes,
918
- isFuture
919
- } from '@gobrand/tiempo';
920
-
921
- // Meeting scheduled for 2 PM
922
- const meeting = toZonedTime('2025-01-20T19:00:00Z', 'America/New_York');
923
- // 2025-01-20T14:00:00-05:00[America/New_York]
20
+ import { toZonedTime, addDays, format, toUtcString } from '@gobrand/tiempo';
924
21
 
925
- // Send reminders at multiple intervals
926
- const reminders = [
927
- { time: subMinutes(meeting, 15), label: '15 minutes before' },
928
- { time: subHours(meeting, 1), label: '1 hour before' },
929
- { time: subHours(meeting, 24), label: '1 day before' },
930
- ];
22
+ // Backend sends UTC
23
+ const utc = "2025-03-09T07:00:00Z";
931
24
 
932
- reminders.forEach(({ time, label }) => {
933
- if (isFuture(time)) {
934
- const formatted = format(time, 'MMM d, h:mm a');
935
- console.log(`Send reminder "${label}" at ${formatted}`);
936
- }
937
- });
25
+ // Convert to user's timezone, manipulate, format
26
+ const userTime = toZonedTime(utc, "America/New_York");
27
+ const tomorrow = addDays(userTime, 1); // DST transition handled correctly
28
+ const display = format(tomorrow, "EEEE 'at' h:mm a"); // "Monday at 2:00 AM"
938
29
 
939
- // Calculate time until meeting
940
- const now = Temporal.Now.zonedDateTimeISO('America/New_York');
941
- const minutesUntil = differenceInMinutes(meeting, now);
942
- console.log(`Meeting starts in ${minutesUntil} minutes`);
30
+ // Send back to backend as UTC
31
+ const payload = toUtcString(tomorrow); // "2025-03-10T06:00:00Z"
943
32
  ```
944
33
 
945
- ### PlainDate Comparisons
34
+ ## Install
946
35
 
947
- For comparing calendar dates without time or timezone considerations, tiempo provides dedicated PlainDate comparison functions. These are useful for calendars, date pickers, and scheduling UIs where you work with pure dates.
948
-
949
- #### `isPlainDateBefore(date1, date2)` / `isPlainDateAfter(date1, date2)` / `isPlainDateEqual(date1, date2)`
950
-
951
- Compare two `Temporal.PlainDate` values. Unlike `isBefore`/`isAfter` which compare instants in time, these functions compare pure calendar dates.
952
-
953
- ```typescript
954
- import { isPlainDateBefore, isPlainDateAfter, isPlainDateEqual } from '@gobrand/tiempo';
955
-
956
- const jan20 = Temporal.PlainDate.from('2025-01-20');
957
- const jan25 = Temporal.PlainDate.from('2025-01-25');
958
-
959
- isPlainDateBefore(jan20, jan25); // true
960
- isPlainDateBefore(jan25, jan20); // false
961
-
962
- isPlainDateAfter(jan25, jan20); // true
963
- isPlainDateAfter(jan20, jan25); // false
964
-
965
- isPlainDateEqual(jan20, Temporal.PlainDate.from('2025-01-20')); // true
966
- isPlainDateEqual(jan20, jan25); // false
967
- ```
968
-
969
- **When to use PlainDate vs Instant/ZonedDateTime:**
970
- - Use `isPlainDateBefore`/`isPlainDateAfter` when comparing calendar dates (e.g., "Is January 20th before January 25th?")
971
- - Use `isBefore`/`isAfter` when comparing specific moments in time (e.g., "Did event A happen before event B?")
972
-
973
- ```typescript
974
- // Calendar UI: Disable dates before today
975
- const isDateDisabled = (date: Temporal.PlainDate) =>
976
- isPlainDateBefore(date, today());
977
-
978
- // Booking system: Check if selected date is in the past
979
- const isPastDate = (date: Temporal.PlainDate) =>
980
- isPlainDateBefore(date, today());
981
- ```
982
-
983
- ## Browser Support
984
-
985
- The Temporal API is a Stage 3 TC39 proposal. The polyfill `@js-temporal/polyfill` is included as a dependency, so you're ready to go!
986
-
987
- ```typescript
988
- import { Temporal } from '@js-temporal/polyfill';
36
+ ```bash
37
+ npm install @gobrand/tiempo
989
38
  ```
990
39
 
991
- ## Contributing
40
+ ## Docs
992
41
 
993
- Contributions are welcome! Please feel free to submit a Pull Request.
42
+ **[eng.gobrand.app/tiempo](https://eng.gobrand.app/tiempo)** Full API reference, examples, and guides.
994
43
 
995
44
  ## License
996
45
 
997
- MIT © [Go Brand](https://github.com/go-brand)
998
-
999
- ## Built by Go Brand
1000
-
1001
- tiempo is built and maintained by [Go Brand](https://gobrand.app) - a modern social media management platform.
46
+ MIT © [Ruben Costa](https://x.com/PonziChad) / [Go Brand](https://gobrand.app)
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@gobrand/tiempo",
3
- "version": "2.3.4",
3
+ "version": "2.3.6",
4
4
  "description": "Lightweight utility functions for converting between UTC and timezone-aware datetimes using the Temporal API",
5
5
  "private": false,
6
6
  "publishConfig": {
@@ -28,7 +28,7 @@
28
28
  "bugs": {
29
29
  "url": "https://github.com/go-brand/tiempo/issues"
30
30
  },
31
- "homepage": "https://github.com/go-brand/tiempo#readme",
31
+ "homepage": "https://eng.gobrand.app/tiempo",
32
32
  "scripts": {
33
33
  "build": "tsup && tsc --emitDeclarationOnly",
34
34
  "clean": "git clean -xdf .cache .turbo dist node_modules tsconfig.tsbuildinfo",