1/**
2 * Works with absolute instants, UTC date-times, zoned date-times, and time
3 * zones.
4 *
5 * A `DateTime` always represents an absolute point in time with epoch
6 * milliseconds. It may also carry a `TimeZone` for calendar parts, formatting,
7 * and zone-aware transformations. This module includes constructors, time-zone
8 * helpers, comparisons, date arithmetic, current-time effects, and formatting
9 * functions.
10 *
11 * @since 3.6.0
12 */
13import type { IllegalArgumentError } from "./Cause.ts"
14import * as Context from "./Context.ts"
15import type * as Duration from "./Duration.ts"
16import * as Effect from "./Effect.ts"
17import type * as Equ from "./Equivalence.ts"
18import { dual, flow, type LazyArg } from "./Function.ts"
19import type { Inspectable } from "./Inspectable.ts"
20import * as Internal from "./internal/dateTime.ts"
21import { provideService } from "./internal/effect.ts"
22import * as Layer from "./Layer.ts"
23import type * as Option from "./Option.ts"
24import type * as order from "./Order.ts"
25import type { Pipeable } from "./Pipeable.ts"
26
27const TypeId = Internal.TypeId
28const TimeZoneTypeId = Internal.TimeZoneTypeId
29
30/**
31 * A `DateTime` represents a point in time. It can optionally have a time zone
32 * associated with it.
33 *
34 * @category models
35 * @since 3.6.0
36 */
37export type DateTime = Utc | Zoned
38
39/**
40 * Represents a `DateTime` stored as an absolute UTC instant with no associated
41 * time zone.
42 *
43 * **Details**
44 *
45 * Use `DateTime.isUtc` to narrow a `DateTime` to this variant.
46 *
47 * @category models
48 * @since 3.6.0
49 */
50export interface Utc extends DateTime.Proto {
51 readonly _tag: "Utc"
52 readonly epochMilliseconds: number
53 partsUtc: DateTime.PartsWithWeekday | undefined
54}
55
56/**
57 * Represents a `DateTime` with an associated `TimeZone`.
58 *
59 * **Details**
60 *
61 * A zoned value still represents an absolute instant through
62 * `epochMilliseconds`, while the time zone is used for wall-clock parts,
63 * formatting, and zone-aware transformations.
64 *
65 * @category models
66 * @since 3.6.0
67 */
68export interface Zoned extends DateTime.Proto {
69 readonly _tag: "Zoned"
70 readonly epochMilliseconds: number
71 readonly zone: TimeZone
72 adjustedEpochMilliseconds: number | undefined
73 partsAdjusted: DateTime.PartsWithWeekday | undefined
74 partsUtc: DateTime.PartsWithWeekday | undefined
75}
76
77/**
78 * Companion namespace containing the public helper types used by `DateTime`
79 * constructors, parts APIs, formatting, and date/time arithmetic.
80 *
81 * @since 3.6.0
82 */
83export declare namespace DateTime {
84 /**
85 * Input accepted by `DateTime.make`, `DateTime.makeUnsafe`, and the zoned
86 * constructors.
87 *
88 * **Details**
89 *
90 * Includes existing `DateTime` values, partial date parts, epoch-millisecond
91 * objects, epoch milliseconds, JavaScript `Date` instances, and parseable date
92 * strings.
93 *
94 * @category models
95 * @since 3.6.0
96 */
97 export type Input = DateTime | Partial<Parts> | Instant | InstantWithZone | Date | number | string
98
99 /**
100 * Type-level helper used by constructors to preserve a zoned input.
101 *
102 * **Details**
103 *
104 * When the input type is `DateTime.Zoned`, the result type is
105 * `DateTime.Zoned`; otherwise the result type is `DateTime.Utc`.
106 *
107 * @category models
108 * @since 3.6.0
109 */
110 export type PreserveZone<A extends DateTime.Input> = A extends Zoned ? Zoned : Utc
111
112 /**
113 * Date and time unit name accepted by `DateTime` rounding and arithmetic
114 * APIs.
115 *
116 * **Details**
117 *
118 * Includes both singular units, such as `"day"`, and plural units, such as
119 * `"days"`.
120 *
121 * @category models
122 * @since 3.6.0
123 */
124 export type Unit = UnitSingular | UnitPlural
125
126 /**
127 * Singular date and time unit names used by rounding APIs such as
128 * `DateTime.startOf`, `DateTime.endOf`, and `DateTime.nearest`.
129 *
130 * @category models
131 * @since 3.6.0
132 */
133 export type UnitSingular =
134 | "millisecond"
135 | "second"
136 | "minute"
137 | "hour"
138 | "day"
139 | "week"
140 | "month"
141 | "year"
142
143 /**
144 * Plural date and time unit names used by `DateTime.PartsForMath` for
145 * amount-based arithmetic.
146 *
147 * @category models
148 * @since 3.6.0
149 */
150 export type UnitPlural =
151 | "milliseconds"
152 | "seconds"
153 | "minutes"
154 | "hours"
155 | "days"
156 | "weeks"
157 | "months"
158 | "years"
159
160 /**
161 * Calendar and time components of a `DateTime`, including the weekday.
162 *
163 * **Details**
164 *
165 * `month` is one-based (`1` for January through `12` for December), and
166 * `weekDay` follows JavaScript `Date#getUTCDay` numbering (`0` for Sunday
167 * through `6` for Saturday).
168 *
169 * @category models
170 * @since 3.6.0
171 */
172 export interface PartsWithWeekday {
173 readonly millisecond: number
174 readonly second: number
175 readonly minute: number
176 readonly hour: number
177 readonly day: number
178 readonly weekDay: number
179 readonly month: number
180 readonly year: number
181 }
182
183 /**
184 * Calendar and time components of a `DateTime`, without weekday information.
185 *
186 * **Details**
187 *
188 * `month` is one-based (`1` for January through `12` for December).
189 *
190 * @category models
191 * @since 3.6.0
192 */
193 export interface Parts {
194 readonly millisecond: number
195 readonly second: number
196 readonly minute: number
197 readonly hour: number
198 readonly day: number
199 readonly month: number
200 readonly year: number
201 }
202
203 /**
204 * Plural amount fields accepted by `DateTime.add` and `DateTime.subtract`.
205 *
206 * **Details**
207 *
208 * Each field represents the number of units to add or subtract for that part.
209 *
210 * @category models
211 * @since 3.6.0
212 */
213 export interface PartsForMath {
214 readonly milliseconds: number
215 readonly seconds: number
216 readonly minutes: number
217 readonly hours: number
218 readonly days: number
219 readonly weeks: number
220 readonly months: number
221 readonly years: number
222 }
223
224 /**
225 * Object input representing an absolute instant as milliseconds since the Unix
226 * epoch.
227 *
228 * @category models
229 * @since 4.0.0
230 */
231 export interface Instant {
232 readonly epochMilliseconds: number
233 }
234
235 /**
236 * Object input representing an absolute instant plus a time zone identifier.
237 *
238 * **Details**
239 *
240 * `DateTime.makeZoned` and `DateTime.makeZonedUnsafe` use `timeZoneId` when
241 * no explicit `timeZone` option is supplied.
242 *
243 * @category models
244 * @since 4.0.0
245 */
246 export interface InstantWithZone {
247 readonly timeZoneId: string
248 readonly epochMilliseconds: number
249 }
250
251 /**
252 * Shared protocol implemented by all `DateTime` values.
253 *
254 * **Details**
255 *
256 * Provides the `DateTime` type identifier along with pipe and inspection
257 * support.
258 *
259 * @category models
260 * @since 3.6.0
261 */
262 export interface Proto extends Pipeable, Inspectable {
263 readonly [TypeId]: typeof TypeId
264 }
265}
266
267/**
268 * Represents a time zone used by `DateTime.Zoned`.
269 *
270 * **Details**
271 *
272 * A `TimeZone` is either a fixed offset from UTC or a named IANA time zone.
273 *
274 * @category models
275 * @since 3.6.0
276 */
277export type TimeZone = TimeZone.Offset | TimeZone.Named
278
279/**
280 * Companion namespace containing the public variant and protocol types for
281 * `TimeZone`.
282 *
283 * @since 3.6.0
284 */
285export declare namespace TimeZone {
286 /**
287 * Shared protocol implemented by all `TimeZone` values.
288 *
289 * **Details**
290 *
291 * Provides the `TimeZone` type identifier and inspection support.
292 *
293 * @category models
294 * @since 3.6.0
295 */
296 export interface Proto extends Inspectable {
297 readonly [TimeZoneTypeId]: typeof TimeZoneTypeId
298 }
299
300 /**
301 * Fixed-offset time zone.
302 *
303 * **Details**
304 *
305 * The `offset` is measured in milliseconds from UTC. Positive offsets are
306 * ahead of UTC, and negative offsets are behind UTC.
307 *
308 * @category models
309 * @since 3.6.0
310 */
311 export interface Offset extends Proto {
312 readonly _tag: "Offset"
313 readonly offset: number
314 }
315
316 /**
317 * Named IANA time zone.
318 *
319 * **Details**
320 *
321 * The `id` field contains the resolved time zone identifier, such as
322 * `"Europe/London"` or `"America/New_York"`.
323 *
324 * @category models
325 * @since 3.6.0
326 */
327 export interface Named extends Proto {
328 readonly _tag: "Named"
329 readonly id: string
330 /** @internal */
331 readonly format: Intl.DateTimeFormat
332 }
333}
334
335/**
336 * A `Disambiguation` is used to resolve ambiguities when a `DateTime` is
337 * ambiguous, such as during a daylight saving time transition.
338 *
339 * **Details**
340 *
341 * For more information, see the [Temporal documentation](https://tc39.es/proposal-temporal/docs/timezone.html#ambiguity-due-to-dst-or-other-time-zone-offset-changes)
342 *
343 * - `"compatible"`: (default) Behavior matching Temporal API and legacy JavaScript Date and moment.js.
344 * For repeated times, chooses the earlier occurrence. For gap times, chooses the later interpretation.
345 *
346 * - `"earlier"`: For repeated times, always choose the earlier occurrence.
347 * For gap times, choose the time before the gap.
348 *
349 * - `"later"`: For repeated times, always choose the later occurrence.
350 * For gap times, choose the time after the gap.
351 *
352 * - `"reject"`: Throw an `RangeError` when encountering ambiguous or non-existent times.
353 *
354 * **Example** (Resolving ambiguous local times)
355 *
356 * ```ts import.meta.vitest
357 * import { DateTime, Option } from "effect"
358 *
359 * // Fall-back example: 01:30 on Nov 2, 2025 in New York happens twice
360 * const ambiguousTime = { year: 2025, month: 11, day: 2, hour: 1, minute: 30 }
361 * const timeZone = DateTime.zoneMakeNamedUnsafe("America/New_York")
362 *
363 * const earlier = DateTime.makeZoned(ambiguousTime, {
364 * timeZone,
365 * adjustForTimeZone: true,
366 * disambiguation: "earlier"
367 * })
368 * // Earlier occurrence (DST time): 2025-11-02T05:30:00.000Z
369 *
370 * const later = DateTime.makeZoned(ambiguousTime, {
371 * timeZone,
372 * adjustForTimeZone: true,
373 * disambiguation: "later"
374 * })
375 * // Later occurrence (standard time): 2025-11-02T06:30:00.000Z
376 *
377 * // Gap example: 02:30 on Mar 9, 2025 in New York doesn't exist
378 * const gapTime = { year: 2025, month: 3, day: 9, hour: 2, minute: 30 }
379 *
380 * const beforeGap = DateTime.makeZoned(gapTime, {
381 * timeZone,
382 * adjustForTimeZone: true,
383 * disambiguation: "earlier"
384 * })
385 * // Time before gap: 2025-03-09T06:30:00.000Z (01:30 EST)
386 *
387 * const afterGap = DateTime.makeZoned(gapTime, {
388 * timeZone,
389 * adjustForTimeZone: true,
390 * disambiguation: "later"
391 * })
392 * // Time after gap: 2025-03-09T07:30:00.000Z (03:30 EDT)
393 *
394 * earlier.pipe(Option.getOrThrow, DateTime.formatIso) // => "2025-11-02T05:30:00.000Z"
395 * later.pipe(Option.getOrThrow, DateTime.formatIso) // => "2025-11-02T06:30:00.000Z"
396 * beforeGap.pipe(Option.getOrThrow, DateTime.formatIso) // => "2025-03-09T06:30:00.000Z"
397 * afterGap.pipe(Option.getOrThrow, DateTime.formatIso) // => "2025-03-09T07:30:00.000Z"
398 * ```
399 *
400 * @category models
401 * @since 3.18.0
402 */
403export type Disambiguation = "compatible" | "earlier" | "later" | "reject"
404
405// =============================================================================
406// guards
407// =============================================================================
408
409/**
410 * Checks whether a value is a `DateTime`.
411 *
412 * **When to use**
413 *
414 * Use to narrow an unknown value before treating it as a `DateTime`.
415 *
416 * @see {@link isUtc} for narrowing a known `DateTime` to UTC
417 * @see {@link isZoned} for narrowing a known `DateTime` to zoned
418 *
419 * @category guards
420 * @since 3.6.0
421 */
422export const isDateTime: (u: unknown) => u is DateTime = Internal.isDateTime
423
424/**
425 * Checks whether a value is a `TimeZone`.
426 *
427 * **When to use**
428 *
429 * Use to narrow unknown input to any `TimeZone` before passing it to APIs that
430 * accept either fixed-offset or named time zones.
431 *
432 * @see {@link isTimeZoneOffset} for narrowing to fixed-offset time zones
433 * @see {@link isTimeZoneNamed} for narrowing to named time zones
434 *
435 * @category guards
436 * @since 3.6.0
437 */
438export const isTimeZone: (u: unknown) => u is TimeZone = Internal.isTimeZone
439
440/**
441 * Checks whether a value is an offset-based `TimeZone`.
442 *
443 * **When to use**
444 *
445 * Use when you need to narrow an unknown or union `TimeZone` value to the
446 * fixed-offset variant before reading its offset in milliseconds.
447 *
448 * @see {@link isTimeZone} for checking either time zone variant
449 * @see {@link isTimeZoneNamed} for narrowing to named time zones
450 *
451 * @category guards
452 * @since 3.6.0
453 */
454export const isTimeZoneOffset: (u: unknown) => u is TimeZone.Offset = Internal.isTimeZoneOffset
455
456/**
457 * Checks whether a value is a named `TimeZone` (IANA time zone).
458 *
459 * **When to use**
460 *
461 * Use to narrow an unknown value to the `TimeZone.Named` variant before
462 * reading named-zone fields such as `id`.
463 *
464 * @see {@link isTimeZone} for checking either time zone variant
465 * @see {@link isTimeZoneOffset} for narrowing to fixed-offset time zones
466 *
467 * @category guards
468 * @since 3.6.0
469 */
470export const isTimeZoneNamed: (u: unknown) => u is TimeZone.Named = Internal.isTimeZoneNamed
471
472/**
473 * Checks whether a `DateTime` is a UTC `DateTime` (no time zone information).
474 *
475 * **When to use**
476 *
477 * Use to narrow a `DateTime` before passing it to code that requires a UTC
478 * value without an associated time zone.
479 *
480 * @see {@link isZoned} for narrowing to zoned date-times
481 * @see {@link match} for handling both UTC and zoned cases
482 *
483 * @category guards
484 * @since 3.6.0
485 */
486export const isUtc: (self: DateTime) => self is Utc = Internal.isUtc
487
488/**
489 * Checks whether a `DateTime` is a zoned `DateTime` (has time zone information).
490 *
491 * **When to use**
492 *
493 * Use to narrow a known `DateTime` before reading its zone or passing it to
494 * APIs that require `DateTime.Zoned`.
495 *
496 * @see {@link isUtc} for narrowing to UTC date-times
497 * @see {@link match} for handling both UTC and zoned cases
498 *
499 * @category guards
500 * @since 3.6.0
501 */
502export const isZoned: (self: DateTime) => self is Zoned = Internal.isZoned
503
504// =============================================================================
505// instances
506// =============================================================================
507
508/**
509 * Provides an `Equivalence` for comparing two `DateTime` values for equality.
510 *
511 * **Details**
512 *
513 * Two `DateTime` values are considered equivalent if they represent the same
514 * point in time, regardless of their time zone.
515 *
516 * **Example** (Comparing DateTime values for equivalence)
517 *
518 * ```ts import.meta.vitest
519 * import { DateTime } from "effect"
520 *
521 * const utc = DateTime.makeUnsafe("2024-01-01T12:00:00Z")
522 * const zoned = DateTime.makeZonedUnsafe("2024-01-01T12:00:00Z", {
523 * timeZone: "Europe/London"
524 * })
525 *
526 * DateTime.Equivalence(utc, zoned) // => true
527 * ```
528 *
529 * @category instances
530 * @since 3.6.0
531 */
532export const Equivalence: Equ.Equivalence<DateTime> = Internal.Equivalence
533
534/**
535 * Provides an `Order` for comparing and sorting `DateTime` values.
536 *
537 * **Details**
538 *
539 * `DateTime` values are ordered by their epoch milliseconds, so earlier times
540 * come before later times regardless of time zone.
541 *
542 * **Example** (Sorting DateTime values chronologically)
543 *
544 * ```ts import.meta.vitest
545 * import { Array, DateTime } from "effect"
546 *
547 * const dates = [
548 * DateTime.makeUnsafe("2024-03-01"),
549 * DateTime.makeUnsafe("2024-01-01"),
550 * DateTime.makeUnsafe("2024-02-01")
551 * ]
552 *
553 * Array.sort(dates, DateTime.Order).map(DateTime.formatIsoDateUtc) // => ["2024-01-01", "2024-02-01", "2024-03-01"]
554 * ```
555 *
556 * @category instances
557 * @since 3.6.0
558 */
559export const Order: order.Order<DateTime> = Internal.Order
560
561/**
562 * Returns a `DateTime` constrained between a minimum and maximum value.
563 *
564 * **Details**
565 *
566 * If the `DateTime` is before the minimum, the minimum is returned.
567 * If the `DateTime` is after the maximum, the maximum is returned.
568 * Otherwise, the original `DateTime` is returned.
569 *
570 * **Example** (Clamping DateTime values)
571 *
572 * ```ts import.meta.vitest
573 * import { DateTime } from "effect"
574 *
575 * const min = DateTime.makeUnsafe("2024-01-01")
576 * const max = DateTime.makeUnsafe("2024-12-31")
577 * const date = DateTime.makeUnsafe("2025-06-15")
578 *
579 * DateTime.clamp(date, { minimum: min, maximum: max }) // => DateTime.makeUnsafe("2024-12-31")
580 * ```
581 *
582 * @category ordering
583 * @since 3.6.0
584 */
585export const clamp: {
586 <Min extends DateTime, Max extends DateTime>(
587 options: { readonly minimum: Min; readonly maximum: Max }
588 ): <A extends DateTime>(self: A) => A | Min | Max
589 <A extends DateTime, Min extends DateTime, Max extends DateTime>(
590 self: A,
591 options: { readonly minimum: Min; readonly maximum: Max }
592 ): A | Min | Max
593} = Internal.clamp
594
595// =============================================================================
596// constructors
597// =============================================================================
598
599/**
600 * Create a `DateTime` from a `Date`.
601 *
602 * **Details**
603 *
604 * If the `Date` is invalid, an `IllegalArgumentError` will be thrown.
605 *
606 * **Example** (Creating DateTime values from Dates)
607 *
608 * ```ts import.meta.vitest
609 * import { DateTime } from "effect"
610 *
611 * DateTime.fromDateUnsafe(new Date("2024-01-01T12:00:00Z")) // => DateTime.makeUnsafe("2024-01-01T12:00:00Z")
612 * ```
613 *
614 * @category constructors
615 * @since 4.0.0
616 */
617export const fromDateUnsafe: (date: Date) => Utc = Internal.fromDateUnsafe
618
619/**
620 * Create a `DateTime` from supported input values.
621 *
622 * **When to use**
623 *
624 * Use when creating a `DateTime` from trusted input and construction failures
625 * should throw an `IllegalArgumentError` instead of returning `Option.none`.
626 *
627 * **Details**
628 *
629 * - A `DateTime`
630 * - A `Date` instance (invalid dates will throw an `IllegalArgumentError`)
631 * - The `number` of milliseconds since the Unix epoch
632 * - An object with the parts of a date
633 * - A `string` that can be parsed by `Date.parse`
634 *
635 * **Example** (Creating DateTime values unsafely)
636 *
637 * ```ts import.meta.vitest
638 * import { DateTime } from "effect"
639 *
640 * // from Date
641 * DateTime.makeUnsafe(new Date("2024-01-01T12:00:00Z")) // => DateTime.makeUnsafe("2024-01-01T12:00:00Z")
642 *
643 * // from parts
644 * DateTime.makeUnsafe({ year: 2024 }) // => DateTime.makeUnsafe("2024-01-01T00:00:00Z")
645 *
646 * // from string
647 * DateTime.makeUnsafe("2024-01-01") // => DateTime.makeUnsafe("2024-01-01T00:00:00Z")
648 * ```
649 *
650 * @category constructors
651 * @since 4.0.0
652 */
653export const makeUnsafe: <A extends DateTime.Input>(input: A) => DateTime.PreserveZone<A> = Internal.makeUnsafe
654
655/**
656 * Creates a `DateTime.Utc` from the number of seconds since the Unix epoch.
657 *
658 * **Example** (Creating from epoch seconds)
659 *
660 * ```ts import.meta.vitest
661 * import { DateTime } from "effect"
662 *
663 * DateTime.fromEpochSeconds(1704067200).toJSON() // => "2024-01-01T00:00:00.000Z"
664 * ```
665 *
666 * @category constructors
667 * @since 4.0.0
668 */
669export const fromEpochSeconds: (seconds: number) => Utc = Internal.fromEpochSeconds
670
671/**
672 * Create a `DateTime.Zoned` using `DateTime.makeUnsafe` and a time zone.
673 *
674 * **When to use**
675 *
676 * Use when the date/time input and zone options are trusted and invalid or
677 * rejected ambiguous times should throw instead of returning `Option.none`.
678 *
679 * **Details**
680 *
681 * The input is treated as UTC and then the time zone is attached, unless
682 * `adjustForTimeZone` is set to `true`. In that case, the input is treated as
683 * already in the time zone.
684 *
685 * When `adjustForTimeZone` is true and ambiguous times occur during DST transitions,
686 * the `disambiguation` option controls how to resolve the ambiguity:
687 * - `compatible` (default): Choose earlier time for repeated times, later for gaps
688 * - `earlier`: Always choose the earlier of two possible times
689 * - `later`: Always choose the later of two possible times
690 * - `reject`: Throw an error when ambiguous times are encountered
691 *
692 * **Example** (Creating zoned DateTime values unsafely)
693 *
694 * ```ts import.meta.vitest
695 * import { DateTime } from "effect"
696 *
697 * const zoned = DateTime.makeZonedUnsafe("2024-06-15T14:30:00Z", {
698 * timeZone: "Europe/London"
699 * })
700 *
701 * DateTime.formatIsoZoned(zoned) // => "2024-06-15T15:30:00.000+01:00[Europe/London]"
702 * ```
703 *
704 * @category constructors
705 * @since 4.0.0
706 */
707export const makeZonedUnsafe: (input: DateTime.Input, options?: {
708 readonly timeZone?: number | string | TimeZone | undefined
709 readonly adjustForTimeZone?: boolean | undefined
710 readonly disambiguation?: Disambiguation | undefined
711}) => Zoned = Internal.makeZonedUnsafe
712
713/**
714 * Creates a `DateTime.Zoned` safely from an input and a time zone.
715 *
716 * **Details**
717 *
718 * By default, the input is interpreted as a UTC instant and the time zone is
719 * attached without changing that instant. When `adjustForTimeZone` is `true`,
720 * the input is interpreted as wall-clock time in the target zone.
721 *
722 * When `adjustForTimeZone` is `true`, `disambiguation` controls
723 * daylight-saving gaps and repeated times:
724 *
725 * - `"compatible"` (default): chooses the earlier occurrence for repeated
726 * times and the later interpretation for gaps
727 * - `"earlier"`: chooses the earlier possible instant
728 * - `"later"`: chooses the later possible instant
729 * - `"reject"`: rejects ambiguous or nonexistent wall-clock times
730 *
731 * Returns `Some` when construction succeeds, or `None` when the input, time
732 * zone, or disambiguation cannot be resolved.
733 *
734 * **Example** (Creating optional zoned DateTime values)
735 *
736 * ```ts import.meta.vitest
737 * import { DateTime, Option } from "effect"
738 *
739 * const result = DateTime.makeZoned("2024-06-15T14:30:00Z", {
740 * timeZone: "Europe/London"
741 * })
742 *
743 * result.pipe(Option.map(DateTime.formatIsoZoned)) // => Option.some("2024-06-15T15:30:00.000+01:00[Europe/London]")
744 * ```
745 *
746 * @category constructors
747 * @since 3.6.0
748 */
749export const makeZoned: (
750 input: DateTime.Input,
751 options?: {
752 readonly timeZone?: number | string | TimeZone | undefined
753 readonly adjustForTimeZone?: boolean | undefined
754 readonly disambiguation?: Disambiguation | undefined
755 }
756) => Option.Option<Zoned> = Internal.makeZoned
757
758/**
759 * Creates a `DateTime` safely from supported input values.
760 *
761 * **Details**
762 *
763 * - A `DateTime`
764 * - A JavaScript `Date`
765 * - The number of milliseconds since the Unix epoch
766 * - An object with date and time parts
767 * - A string that can be parsed as a date
768 *
769 * Returns `Some` with the constructed `DateTime` when the input is valid, or
770 * `None` when construction would fail, including invalid `Date` instances or
771 * unparseable strings.
772 *
773 * **Example** (Creating optional DateTime values)
774 *
775 * ```ts import.meta.vitest
776 * import { DateTime, Option } from "effect"
777 *
778 * // from Date
779 * DateTime.make(new Date("2024-01-01T12:00:00Z")) // => Option.some(DateTime.makeUnsafe("2024-01-01T12:00:00Z"))
780 *
781 * // from parts
782 * DateTime.make({ year: 2024 }) // => Option.some(DateTime.makeUnsafe("2024-01-01T00:00:00Z"))
783 *
784 * // from string
785 * DateTime.make("2024-01-01") // => Option.some(DateTime.makeUnsafe("2024-01-01T00:00:00Z"))
786 *
787 * DateTime.make("not a date") // => Option.none()
788 * ```
789 *
790 * @category constructors
791 * @since 3.6.0
792 */
793export const make: <A extends DateTime.Input>(input: A) => Option.Option<DateTime.PreserveZone<A>> = Internal.make
794
795/**
796 * Parses an ISO zoned date-time string into a `DateTime.Zoned` safely.
797 *
798 * **Details**
799 *
800 * Accepts named-zone strings such as
801 * `YYYY-MM-DDTHH:mm:ss.sss+HH:MM[Time/Zone]` and offset-only strings such as
802 * `YYYY-MM-DDTHH:mm:ss.sss+HH:MM`. Returns `None` when the input cannot be
803 * parsed.
804 *
805 * **Example** (Parsing zoned DateTime strings)
806 *
807 * ```ts import.meta.vitest
808 * import { DateTime, Option } from "effect"
809 *
810 * DateTime.makeZonedFromString(
811 * "2024-01-01T12:00:00+02:00[Europe/Berlin]"
812 * ).pipe(Option.map(DateTime.formatIsoZoned)) // => Option.some("2024-01-01T11:00:00.000+01:00[Europe/Berlin]")
813 *
814 * DateTime.makeZonedFromString("2024-01-01T12:00:00Z") // => Option.none()
815 * DateTime.makeZonedFromString("invalid") // => Option.none()
816 * ```
817 *
818 * @category constructors
819 * @since 3.6.0
820 */
821export const makeZonedFromString: (input: string) => Option.Option<Zoned> = Internal.makeZonedFromString
822
823/**
824 * Gets the current time using the `Clock` service and converts it to a `DateTime`.
825 *
826 * **Example** (Getting the current DateTime)
827 *
828 * ```ts import.meta.vitest
829 * import { DateTime, Effect } from "effect"
830 * import { TestClock } from "effect/testing"
831 *
832 * await Effect.runPromise(Effect.map(DateTime.now, DateTime.isDateTime)) // => true
833 * ```
834 *
835 * @category constructors
836 * @since 3.6.0
837 */
838export const now: Effect.Effect<Utc> = Internal.now
839
840/**
841 * Gets the current time from the `Clock` service and returns it as a
842 * JavaScript `Date`.
843 *
844 * **Example** (Getting the current Date)
845 *
846 * ```ts import.meta.vitest
847 * import { DateTime, Effect } from "effect"
848 * import { TestClock } from "effect/testing"
849 *
850 * await Effect.runPromise(Effect.map(DateTime.nowAsDate, (now) => now instanceof Date)) // => true
851 * ```
852 *
853 * @category constructors
854 * @since 3.14.0
855 */
856export const nowAsDate: Effect.Effect<Date> = Internal.nowAsDate
857
858/**
859 * Gets the current time using `Date.now`.
860 *
861 * **When to use**
862 *
863 * Use when synchronous wall-clock access outside an Effect program is
864 * acceptable and testability through the `Clock` service is not needed.
865 *
866 * **Details**
867 *
868 * This is a synchronous version of `now` that directly uses `Date.now()`
869 * instead of the Effect `Clock` service.
870 *
871 * **Example** (Getting the current DateTime unsafely)
872 *
873 * ```ts import.meta.vitest
874 * import { DateTime } from "effect"
875 *
876 * Number.isFinite(DateTime.toEpochMillis(DateTime.nowUnsafe())) // => true
877 * ```
878 *
879 * @category constructors
880 * @since 4.0.0
881 */
882export const nowUnsafe: LazyArg<Utc> = Internal.nowUnsafe
883
884// =============================================================================
885// time zones
886// =============================================================================
887
888/**
889 * Converts a `DateTime` to a UTC `DateTime`.
890 *
891 * **When to use**
892 *
893 * Use to represent the same instant in UTC instead of its current time zone.
894 *
895 * **Details**
896 *
897 * The returned value keeps the same epoch milliseconds and changes only the
898 * `DateTime` representation to UTC.
899 *
900 * **Example** (Converting DateTime values to UTC)
901 *
902 * ```ts import.meta.vitest
903 * import { DateTime } from "effect"
904 *
905 * const now = DateTime.makeZonedUnsafe({ year: 2024 }, {
906 * timeZone: "Europe/London"
907 * })
908 *
909 * // set as UTC
910 * const utc: DateTime.Utc = DateTime.toUtc(now)
911 * utc // => DateTime.makeUnsafe("2024-01-01T00:00:00Z")
912 * ```
913 *
914 * @category converting
915 * @since 3.13.0
916 */
917export const toUtc: (self: DateTime) => Utc = Internal.toUtc
918
919/**
920 * Sets the time zone of a `DateTime`, returning a new `DateTime.Zoned`.
921 *
922 * **Example** (Setting time zones)
923 *
924 * ```ts import.meta.vitest
925 * import { DateTime } from "effect"
926 *
927 * const zone = DateTime.zoneMakeNamedUnsafe("Europe/London")
928 * const zoned: DateTime.Zoned = DateTime.setZone(DateTime.makeUnsafe("2024-01-01"), zone)
929 *
930 * DateTime.isZoned(zoned) // => true
931 * ```
932 *
933 * @category transforming
934 * @since 3.6.0
935 */
936export const setZone: {
937 (zone: TimeZone, options?: {
938 readonly adjustForTimeZone?: boolean | undefined
939 readonly disambiguation?: Disambiguation | undefined
940 }): (self: DateTime) => Zoned
941 (self: DateTime, zone: TimeZone, options?: {
942 readonly adjustForTimeZone?: boolean | undefined
943 readonly disambiguation?: Disambiguation | undefined
944 }): Zoned
945} = Internal.setZone
946
947/**
948 * Adds a fixed offset time zone to a `DateTime`.
949 *
950 * **Details**
951 *
952 * The offset is in milliseconds.
953 *
954 * **Example** (Setting fixed-offset time zones)
955 *
956 * ```ts import.meta.vitest
957 * import { DateTime } from "effect"
958 *
959 * const dateTime = DateTime.makeUnsafe("2024-01-01")
960 * const zoned: DateTime.Zoned = DateTime.setZoneOffset(dateTime, 3 * 60 * 60 * 1000)
961 *
962 * DateTime.zoneToString(zoned.zone) // => "+03:00"
963 * ```
964 *
965 * @category transforming
966 * @since 3.6.0
967 */
968export const setZoneOffset: {
969 (offset: number, options?: {
970 readonly adjustForTimeZone?: boolean | undefined
971 readonly disambiguation?: Disambiguation | undefined
972 }): (self: DateTime) => Zoned
973 (self: DateTime, offset: number, options?: {
974 readonly adjustForTimeZone?: boolean | undefined
975 readonly disambiguation?: Disambiguation | undefined
976 }): Zoned
977} = Internal.setZoneOffset
978
979/**
980 * Attempts to create a named time zone from an IANA time zone identifier.
981 *
982 * **When to use**
983 *
984 * Use when the IANA zone id is trusted and invalid zones should throw instead
985 * of returning `Option.none` or failing in `Effect`.
986 *
987 * **Details**
988 *
989 * If the time zone is invalid, an `IllegalArgumentError` will be thrown.
990 *
991 * **Example** (Creating named time zones unsafely)
992 *
993 * ```ts import.meta.vitest
994 * import { DateTime } from "effect"
995 *
996 * DateTime.zoneToString(DateTime.zoneMakeNamedUnsafe("Europe/London")) // => "Europe/London"
997 * DateTime.zoneToString(DateTime.zoneMakeNamedUnsafe("Asia/Tokyo")) // => "Asia/Tokyo"
998 *
999 * // This would throw an IllegalArgumentError:
1000 * // DateTime.zoneMakeNamedUnsafe("Invalid/Zone")
1001 * ```
1002 *
1003 * @category constructors
1004 * @since 4.0.0
1005 */
1006export const zoneMakeNamedUnsafe: (zoneId: string) => TimeZone.Named = Internal.zoneMakeNamedUnsafe
1007
1008/**
1009 * Create a fixed offset time zone.
1010 *
1011 * **Details**
1012 *
1013 * The offset is specified in milliseconds from UTC. Positive values are
1014 * ahead of UTC, negative values are behind UTC.
1015 *
1016 * **Example** (Creating fixed-offset time zones)
1017 *
1018 * ```ts import.meta.vitest
1019 * import { DateTime } from "effect"
1020 *
1021 * // Create a time zone with +3 hours offset
1022 * const zone = DateTime.zoneMakeOffset(3 * 60 * 60 * 1000)
1023 *
1024 * const dt = DateTime.makeZonedUnsafe("2024-01-01T12:00:00Z", {
1025 * timeZone: zone
1026 * })
1027 * DateTime.formatIsoZoned(dt) // => "2024-01-01T15:00:00.000+03:00"
1028 * ```
1029 *
1030 * @category constructors
1031 * @since 3.6.0
1032 */
1033export const zoneMakeOffset: (offset: number) => TimeZone.Offset = Internal.zoneMakeOffset
1034
1035/**
1036 * Creates a named time zone safely from an IANA time zone identifier.
1037 *
1038 * **Details**
1039 *
1040 * If the time zone is invalid, `None` will be returned.
1041 *
1042 * **Example** (Creating optional named time zones)
1043 *
1044 * ```ts import.meta.vitest
1045 * import { DateTime, Option } from "effect"
1046 *
1047 * DateTime.zoneMakeNamed("Europe/London").pipe(Option.map(DateTime.zoneToString)) // => Option.some("Europe/London")
1048 * DateTime.zoneMakeNamed("Invalid/Zone") // => Option.none()
1049 * ```
1050 *
1051 * @category constructors
1052 * @since 3.6.0
1053 */
1054export const zoneMakeNamed: (zoneId: string) => Option.Option<TimeZone.Named> = Internal.zoneMakeNamed
1055
1056/**
1057 * Creates a named time zone effectfully from an IANA time zone identifier.
1058 *
1059 * **When to use**
1060 *
1061 * Use when invalid IANA zone ids should fail in the Effect error channel
1062 * instead of returning `Option.none` or throwing.
1063 *
1064 * **Example** (Creating named time zones effectfully)
1065 *
1066 * ```ts import.meta.vitest
1067 * import { DateTime, Effect } from "effect"
1068 *
1069 * const program = Effect.gen(function*() {
1070 * const zone = yield* DateTime.zoneMakeNamedEffect("Europe/London")
1071 * const now = yield* DateTime.now
1072 * return DateTime.setZone(now, zone)
1073 * })
1074 *
1075 * DateTime.zoneToString((await Effect.runPromise(program)).zone) // => "Europe/London"
1076 * ```
1077 *
1078 * @category constructors
1079 * @since 3.6.0
1080 */
1081export const zoneMakeNamedEffect: (zoneId: string) => Effect.Effect<TimeZone.Named, IllegalArgumentError> =
1082 Internal.zoneMakeNamedEffect
1083
1084/**
1085 * Create a named time zone from the system's local time zone.
1086 *
1087 * **Details**
1088 *
1089 * This uses the system's configured time zone, which may vary depending
1090 * on the runtime environment.
1091 *
1092 * **Example** (Creating local time zones)
1093 *
1094 * ```ts import.meta.vitest
1095 * import { DateTime } from "effect"
1096 *
1097 * DateTime.isTimeZoneNamed(DateTime.zoneMakeLocal()) // => true
1098 * ```
1099 *
1100 * @category constructors
1101 * @since 3.6.0
1102 */
1103export const zoneMakeLocal: () => TimeZone.Named = Internal.zoneMakeLocal
1104
1105/**
1106 * Tries to parse a `TimeZone` from a string safely.
1107 *
1108 * **Details**
1109 *
1110 * Supports both IANA time zone identifiers and offset formats like "+03:00".
1111 *
1112 * **Example** (Parsing time zones)
1113 *
1114 * ```ts import.meta.vitest
1115 * import { DateTime, Option } from "effect"
1116 *
1117 * DateTime.zoneFromString("Europe/London").pipe(Option.map(DateTime.zoneToString)) // => Option.some("Europe/London")
1118 * DateTime.zoneFromString("+03:00").pipe(Option.map(DateTime.zoneToString)) // => Option.some("+03:00")
1119 * DateTime.zoneFromString("invalid") // => Option.none()
1120 * ```
1121 *
1122 * @category decoding
1123 * @since 3.6.0
1124 */
1125export const zoneFromString: (zone: string) => Option.Option<TimeZone> = Internal.zoneFromString
1126
1127/**
1128 * Formats a `TimeZone` as a string.
1129 *
1130 * **Example** (Formatting time zones)
1131 *
1132 * ```ts import.meta.vitest
1133 * import { DateTime } from "effect"
1134 *
1135 * DateTime.zoneToString(DateTime.zoneMakeOffset(3 * 60 * 60 * 1000)) // => "+03:00"
1136 * DateTime.zoneToString(DateTime.zoneMakeNamedUnsafe("Europe/London")) // => "Europe/London"
1137 * ```
1138 *
1139 * @category encoding
1140 * @since 3.6.0
1141 */
1142export const zoneToString: (self: TimeZone) => string = Internal.zoneToString
1143
1144/**
1145 * Sets the time zone of a `DateTime` safely from an IANA time zone identifier. If the
1146 * time zone is invalid, `None` will be returned.
1147 *
1148 * **Example** (Setting named time zones safely)
1149 *
1150 * ```ts import.meta.vitest
1151 * import { DateTime, Option } from "effect"
1152 *
1153 * const dateTime = DateTime.makeUnsafe("2024-01-01")
1154 * const result = DateTime.setZoneNamed(dateTime, "Europe/London").pipe(Option.map(DateTime.formatIsoZoned))
1155 *
1156 * result // => Option.some("2024-01-01T00:00:00.000+00:00[Europe/London]")
1157 * ```
1158 *
1159 * @category transforming
1160 * @since 3.6.0
1161 */
1162export const setZoneNamed: {
1163 (zoneId: string, options?: {
1164 readonly adjustForTimeZone?: boolean | undefined
1165 readonly disambiguation?: Disambiguation | undefined
1166 }): (self: DateTime) => Option.Option<Zoned>
1167 (self: DateTime, zoneId: string, options?: {
1168 readonly adjustForTimeZone?: boolean | undefined
1169 readonly disambiguation?: Disambiguation | undefined
1170 }): Option.Option<Zoned>
1171} = Internal.setZoneNamed
1172
1173/**
1174 * Sets the time zone of a `DateTime` from an IANA time zone identifier. If the
1175 * time zone is invalid, an `IllegalArgumentError` will be thrown.
1176 *
1177 * **Example** (Setting named time zones unsafely)
1178 *
1179 * ```ts import.meta.vitest
1180 * import { DateTime } from "effect"
1181 *
1182 * const dateTime = DateTime.makeUnsafe("2024-01-01")
1183 * const zoned = DateTime.setZoneNamedUnsafe(dateTime, "Europe/London")
1184 *
1185 * DateTime.zoneToString(zoned.zone) // => "Europe/London"
1186 * ```
1187 *
1188 * @category transforming
1189 * @since 4.0.0
1190 */
1191export const setZoneNamedUnsafe: {
1192 (zoneId: string, options?: {
1193 readonly adjustForTimeZone?: boolean | undefined
1194 readonly disambiguation?: Disambiguation | undefined
1195 }): (self: DateTime) => Zoned
1196 (self: DateTime, zoneId: string, options?: {
1197 readonly adjustForTimeZone?: boolean | undefined
1198 readonly disambiguation?: Disambiguation | undefined
1199 }): Zoned
1200} = Internal.setZoneNamedUnsafe
1201
1202// =============================================================================
1203// comparisons
1204// =============================================================================
1205
1206/**
1207 * Computes the difference between two `DateTime` values, returning a
1208 * `Duration` representing the amount of time between them.
1209 *
1210 * **Details**
1211 *
1212 * If `other` is *after* `self`, the result will be a positive `Duration`. If
1213 * `other` is *before* `self`, the result will be a negative `Duration`. If they
1214 * are equal, the result will be a `Duration` of zero.
1215 *
1216 * **Example** (Measuring distance between DateTime values)
1217 *
1218 * ```ts import.meta.vitest
1219 * import { DateTime, Duration } from "effect"
1220 *
1221 * const start = DateTime.makeUnsafe("2024-01-01T00:00:00Z")
1222 * const end = DateTime.add(start, { minutes: 1 })
1223 *
1224 * DateTime.distance(start, end) // => Duration.minutes(1)
1225 * ```
1226 *
1227 * @category comparisons
1228 * @since 3.6.0
1229 */
1230export const distance: {
1231 (other: DateTime): (self: DateTime) => Duration.Duration
1232 (self: DateTime, other: DateTime): Duration.Duration
1233} = Internal.distance
1234
1235/**
1236 * Returns the earlier of two `DateTime` values.
1237 *
1238 * **Example** (Selecting the earlier DateTime)
1239 *
1240 * ```ts import.meta.vitest
1241 * import { DateTime } from "effect"
1242 *
1243 * const date1 = DateTime.makeUnsafe("2024-01-01")
1244 * const date2 = DateTime.makeUnsafe("2024-02-01")
1245 *
1246 * DateTime.min(date1, date2) // => DateTime.makeUnsafe("2024-01-01")
1247 * ```
1248 *
1249 * @category comparisons
1250 * @since 3.6.0
1251 */
1252export const min: {
1253 <That extends DateTime>(that: That): <Self extends DateTime>(self: Self) => Self | That
1254 <Self extends DateTime, That extends DateTime>(self: Self, that: That): Self | That
1255} = Internal.min
1256
1257/**
1258 * Returns the later of two `DateTime` values.
1259 *
1260 * **Example** (Selecting the later DateTime)
1261 *
1262 * ```ts import.meta.vitest
1263 * import { DateTime } from "effect"
1264 *
1265 * const date1 = DateTime.makeUnsafe("2024-01-01")
1266 * const date2 = DateTime.makeUnsafe("2024-02-01")
1267 *
1268 * DateTime.max(date1, date2) // => DateTime.makeUnsafe("2024-02-01")
1269 * ```
1270 *
1271 * @category comparisons
1272 * @since 3.6.0
1273 */
1274export const max: {
1275 <That extends DateTime>(that: That): <Self extends DateTime>(self: Self) => Self | That
1276 <Self extends DateTime, That extends DateTime>(self: Self, that: That): Self | That
1277} = Internal.max
1278
1279/**
1280 * Checks whether the first `DateTime` is after the second `DateTime`.
1281 *
1282 * **Example** (Checking whether a DateTime is later)
1283 *
1284 * ```ts import.meta.vitest
1285 * import { DateTime } from "effect"
1286 *
1287 * const date1 = DateTime.makeUnsafe("2024-02-01")
1288 * const date2 = DateTime.makeUnsafe("2024-01-01")
1289 *
1290 * DateTime.isGreaterThan(date1, date2) // => true
1291 * DateTime.isGreaterThan(date2, date1) // => false
1292 * ```
1293 *
1294 * @category comparisons
1295 * @since 4.0.0
1296 */
1297export const isGreaterThan: {
1298 (that: DateTime): (self: DateTime) => boolean
1299 (self: DateTime, that: DateTime): boolean
1300} = Internal.isGreaterThan
1301
1302/**
1303 * Checks whether the first `DateTime` is after or equal to the second `DateTime`.
1304 *
1305 * **Example** (Checking whether a DateTime is later or equal)
1306 *
1307 * ```ts import.meta.vitest
1308 * import { DateTime } from "effect"
1309 *
1310 * const date1 = DateTime.makeUnsafe("2024-01-01")
1311 * const date2 = DateTime.makeUnsafe("2024-01-01")
1312 * const date3 = DateTime.makeUnsafe("2024-02-01")
1313 *
1314 * DateTime.isGreaterThanOrEqualTo(date1, date2) // => true
1315 * DateTime.isGreaterThanOrEqualTo(date3, date1) // => true
1316 * DateTime.isGreaterThanOrEqualTo(date1, date3) // => false
1317 * ```
1318 *
1319 * @category comparisons
1320 * @since 4.0.0
1321 */
1322export const isGreaterThanOrEqualTo: {
1323 (that: DateTime): (self: DateTime) => boolean
1324 (self: DateTime, that: DateTime): boolean
1325} = Internal.isGreaterThanOrEqualTo
1326
1327/**
1328 * Checks whether the first `DateTime` is before the second `DateTime`.
1329 *
1330 * **Example** (Checking whether a DateTime is earlier)
1331 *
1332 * ```ts import.meta.vitest
1333 * import { DateTime } from "effect"
1334 *
1335 * const date1 = DateTime.makeUnsafe("2024-01-01")
1336 * const date2 = DateTime.makeUnsafe("2024-02-01")
1337 *
1338 * DateTime.isLessThan(date1, date2) // => true
1339 * DateTime.isLessThan(date2, date1) // => false
1340 * ```
1341 *
1342 * @category comparisons
1343 * @since 4.0.0
1344 */
1345export const isLessThan: {
1346 (that: DateTime): (self: DateTime) => boolean
1347 (self: DateTime, that: DateTime): boolean
1348} = Internal.isLessThan
1349
1350/**
1351 * Checks whether the first `DateTime` is before or equal to the second `DateTime`.
1352 *
1353 * **Example** (Checking whether a DateTime is earlier or equal)
1354 *
1355 * ```ts import.meta.vitest
1356 * import { DateTime } from "effect"
1357 *
1358 * const date1 = DateTime.makeUnsafe("2024-01-01")
1359 * const date2 = DateTime.makeUnsafe("2024-01-01")
1360 * const date3 = DateTime.makeUnsafe("2024-02-01")
1361 *
1362 * DateTime.isLessThanOrEqualTo(date1, date2) // => true
1363 * DateTime.isLessThanOrEqualTo(date1, date3) // => true
1364 * DateTime.isLessThanOrEqualTo(date3, date1) // => false
1365 * ```
1366 *
1367 * @category comparisons
1368 * @since 4.0.0
1369 */
1370export const isLessThanOrEqualTo: {
1371 (that: DateTime): (self: DateTime) => boolean
1372 (self: DateTime, that: DateTime): boolean
1373} = Internal.isLessThanOrEqualTo
1374
1375/**
1376 * Checks whether a `DateTime` is between two other `DateTime` values (inclusive).
1377 *
1378 * **Example** (Checking whether a DateTime is within bounds)
1379 *
1380 * ```ts import.meta.vitest
1381 * import { DateTime } from "effect"
1382 *
1383 * const min = DateTime.makeUnsafe("2024-01-01")
1384 * const max = DateTime.makeUnsafe("2024-12-31")
1385 * const date = DateTime.makeUnsafe("2024-06-15")
1386 *
1387 * DateTime.between(date, { minimum: min, maximum: max }) // => true
1388 * ```
1389 *
1390 * @category comparisons
1391 * @since 3.6.0
1392 */
1393export const between: {
1394 (options: { minimum: DateTime; maximum: DateTime }): (self: DateTime) => boolean
1395 (self: DateTime, options: { minimum: DateTime; maximum: DateTime }): boolean
1396} = Internal.between
1397
1398/**
1399 * Checks effectfully if a `DateTime` is in the future compared to the current time.
1400 *
1401 * **Details**
1402 *
1403 * This is an effectful operation that uses the current time from the `Clock` service.
1404 *
1405 * **Example** (Checking future DateTime values effectfully)
1406 *
1407 * ```ts import.meta.vitest
1408 * import { DateTime, Effect } from "effect"
1409 * import { TestClock } from "effect/testing"
1410 *
1411 * const futureDate = DateTime.makeUnsafe(1)
1412 * await Effect.runPromise(Effect.provide(DateTime.isFuture(futureDate), TestClock.layer())) // => true
1413 * ```
1414 *
1415 * @category comparisons
1416 * @since 3.6.0
1417 */
1418export const isFuture: (self: DateTime) => Effect.Effect<boolean> = Internal.isFuture
1419
1420/**
1421 * Checks synchronously if a `DateTime` is in the future compared to the current time.
1422 *
1423 * **When to use**
1424 *
1425 * Use when checking whether a `DateTime` is in the future with a synchronous
1426 * live-clock read and `Clock`-based testability is not needed.
1427 *
1428 * **Details**
1429 *
1430 * This is a synchronous version that uses `Date.now()` directly.
1431 *
1432 * **Example** (Checking future DateTime values unsafely)
1433 *
1434 * ```ts
1435 * import { DateTime } from "effect"
1436 *
1437 * const oneHourFromNow = DateTime.add(DateTime.nowUnsafe(), { hours: 1 })
1438 * DateTime.isFutureUnsafe(oneHourFromNow)
1439 * ```
1440 *
1441 * @category comparisons
1442 * @since 4.0.0
1443 */
1444export const isFutureUnsafe: (self: DateTime) => boolean = Internal.isFutureUnsafe
1445
1446/**
1447 * Checks effectfully if a `DateTime` is in the past compared to the current time.
1448 *
1449 * **Details**
1450 *
1451 * This is an effectful operation that uses the current time from the `Clock` service.
1452 *
1453 * **Example** (Checking past DateTime values effectfully)
1454 *
1455 * ```ts import.meta.vitest
1456 * import { DateTime, Effect } from "effect"
1457 * import { TestClock } from "effect/testing"
1458 *
1459 * const pastDate = DateTime.makeUnsafe(-1)
1460 * await Effect.runPromise(Effect.provide(DateTime.isPast(pastDate), TestClock.layer())) // => true
1461 * ```
1462 *
1463 * @category comparisons
1464 * @since 3.6.0
1465 */
1466export const isPast: (self: DateTime) => Effect.Effect<boolean> = Internal.isPast
1467
1468/**
1469 * Checks synchronously if a `DateTime` is in the past compared to the current time.
1470 *
1471 * **When to use**
1472 *
1473 * Use when checking whether a `DateTime` is in the past with a synchronous
1474 * live-clock read and `Clock`-based testability is not needed.
1475 *
1476 * **Details**
1477 *
1478 * This is a synchronous version that uses `Date.now()` directly.
1479 *
1480 * **Example** (Checking past DateTime values unsafely)
1481 *
1482 * ```ts
1483 * import { DateTime } from "effect"
1484 *
1485 * const oneHourAgo = DateTime.subtract(DateTime.nowUnsafe(), { hours: 1 })
1486 * DateTime.isPastUnsafe(oneHourAgo)
1487 * ```
1488 *
1489 * @category comparisons
1490 * @since 4.0.0
1491 */
1492export const isPastUnsafe: (self: DateTime) => boolean = Internal.isPastUnsafe
1493
1494// =============================================================================
1495// conversions
1496// =============================================================================
1497
1498/**
1499 * Gets the UTC `Date` of a `DateTime`.
1500 *
1501 * **Details**
1502 *
1503 * This always returns the UTC representation, ignoring any time zone information.
1504 *
1505 * **Example** (Converting DateTime values to UTC Dates)
1506 *
1507 * ```ts import.meta.vitest
1508 * import { DateTime } from "effect"
1509 *
1510 * const dt = DateTime.makeZonedUnsafe("2024-01-01T12:00:00Z", {
1511 * timeZone: "Europe/London"
1512 * })
1513 *
1514 * DateTime.toDateUtc(dt).toISOString() // => "2024-01-01T12:00:00.000Z"
1515 * ```
1516 *
1517 * @category converting
1518 * @since 3.6.0
1519 */
1520export const toDateUtc: (self: DateTime) => Date = Internal.toDateUtc
1521
1522/**
1523 * Converts a `DateTime` to a `Date`, applying the time zone first.
1524 *
1525 * **Details**
1526 *
1527 * For `DateTime.Zoned`, this adjusts for the time zone before converting.
1528 * For `DateTime.Utc`, this is equivalent to `toDateUtc`.
1529 *
1530 * **Example** (Converting DateTime values to Dates)
1531 *
1532 * ```ts import.meta.vitest
1533 * import { DateTime } from "effect"
1534 *
1535 * const utc = DateTime.makeUnsafe("2024-01-01T12:00:00Z")
1536 * const zoned = DateTime.makeZonedUnsafe("2024-01-01T12:00:00Z", {
1537 * timeZone: "Europe/London"
1538 * })
1539 *
1540 * DateTime.toDate(utc).toISOString() // => "2024-01-01T12:00:00.000Z"
1541 * DateTime.toDate(zoned).toISOString() // => "2024-01-01T12:00:00.000Z"
1542 * ```
1543 *
1544 * @category converting
1545 * @since 3.6.0
1546 */
1547export const toDate: (self: DateTime) => Date = Internal.toDate
1548
1549/**
1550 * Computes the time zone offset of a `DateTime.Zoned` in milliseconds.
1551 *
1552 * **Details**
1553 *
1554 * Returns the offset from UTC in milliseconds. Positive values indicate
1555 * time zones ahead of UTC, negative values indicate time zones behind UTC.
1556 *
1557 * **Example** (Reading zoned offsets)
1558 *
1559 * ```ts import.meta.vitest
1560 * import { DateTime } from "effect"
1561 *
1562 * const zoned = DateTime.makeZonedUnsafe("2024-01-01T12:00:00Z", {
1563 * timeZone: "Europe/London"
1564 * })
1565 *
1566 * DateTime.zonedOffset(zoned) // => 0
1567 * ```
1568 *
1569 * @category converting
1570 * @since 3.6.0
1571 */
1572export const zonedOffset: (self: Zoned) => number = Internal.zonedOffset
1573
1574/**
1575 * Formats the time zone offset of a `DateTime.Zoned` as an ISO string.
1576 *
1577 * **Details**
1578 *
1579 * The offset is formatted as "±HH:MM".
1580 *
1581 * **Example** (Formatting zoned offsets)
1582 *
1583 * ```ts import.meta.vitest
1584 * import { DateTime } from "effect"
1585 *
1586 * const zoned = DateTime.makeZonedUnsafe("2024-01-01T12:00:00Z", {
1587 * timeZone: DateTime.zoneMakeOffset(3 * 60 * 60 * 1000) // +3 hours
1588 * })
1589 *
1590 * DateTime.zonedOffsetIso(zoned) // => "+03:00"
1591 * ```
1592 *
1593 * @category converting
1594 * @since 3.6.0
1595 */
1596export const zonedOffsetIso: (self: Zoned) => string = Internal.zonedOffsetIso
1597
1598/**
1599 * Gets the milliseconds since the Unix epoch of a `DateTime`.
1600 *
1601 * **Details**
1602 *
1603 * This returns the UTC timestamp regardless of any time zone information.
1604 *
1605 * **Example** (Reading epoch milliseconds)
1606 *
1607 * ```ts import.meta.vitest
1608 * import { DateTime } from "effect"
1609 *
1610 * const dt = DateTime.makeUnsafe("2024-01-01T00:00:00Z")
1611 * DateTime.toEpochMillis(dt) // => 1704067200000
1612 * ```
1613 *
1614 * @category converting
1615 * @since 3.6.0
1616 */
1617export const toEpochMillis: (self: DateTime) => number = Internal.toEpochMillis
1618
1619/**
1620 * Converts a `DateTime` to the number of seconds since the Unix epoch.
1621 *
1622 * **Details**
1623 *
1624 * This returns the UTC timestamp regardless of any time zone information.
1625 * The result is floored to the nearest second.
1626 *
1627 * **Example** (Reading epoch seconds)
1628 *
1629 * ```ts import.meta.vitest
1630 * import { DateTime } from "effect"
1631 *
1632 * const dt = DateTime.makeUnsafe("2024-01-01T00:00:00Z")
1633 * DateTime.toEpochSeconds(dt) // => 1704067200
1634 * ```
1635 *
1636 * @category converting
1637 * @since 4.0.0
1638 */
1639export const toEpochSeconds: (self: DateTime) => number = Internal.toEpochSeconds
1640
1641/**
1642 * Removes the time aspect of a `DateTime`, first adjusting for the time
1643 * zone. It will return a `DateTime.Utc` only containing the date.
1644 *
1645 * **Example** (Removing time components)
1646 *
1647 * ```ts import.meta.vitest
1648 * import { DateTime } from "effect"
1649 *
1650 * // returns "2024-01-01T00:00:00Z"
1651 * DateTime.makeZonedUnsafe("2024-01-01T05:00:00Z", {
1652 * timeZone: "Pacific/Auckland",
1653 * adjustForTimeZone: true
1654 * }).pipe(
1655 * DateTime.removeTime,
1656 * DateTime.formatIso
1657 * ) // => "2024-01-01T00:00:00.000Z"
1658 * ```
1659 *
1660 * @category converting
1661 * @since 3.6.0
1662 */
1663export const removeTime: (self: DateTime) => Utc = Internal.removeTime
1664
1665// =============================================================================
1666// parts
1667// =============================================================================
1668
1669/**
1670 * Gets the time-zone-adjusted parts of a `DateTime` as an object.
1671 *
1672 * **Details**
1673 *
1674 * The parts will be time zone adjusted if the `DateTime` is zoned.
1675 *
1676 * **Example** (Reading DateTime parts)
1677 *
1678 * ```ts import.meta.vitest
1679 * import { DateTime } from "effect"
1680 *
1681 * const dt = DateTime.makeUnsafe("2024-01-01T12:30:45.123Z")
1682 * const parts = DateTime.toParts(dt)
1683 *
1684 * const selectedParts = [parts.year, parts.month, parts.day, parts.hour] // => [2024, 1, 1, 12]
1685 * ```
1686 *
1687 * @category getters
1688 * @since 3.6.0
1689 */
1690export const toParts: (self: DateTime) => DateTime.PartsWithWeekday = Internal.toParts
1691
1692/**
1693 * Gets the UTC parts of a `DateTime` as an object.
1694 *
1695 * **Details**
1696 *
1697 * The parts will always be in UTC, ignoring any time zone information.
1698 *
1699 * **Example** (Reading UTC DateTime parts)
1700 *
1701 * ```ts import.meta.vitest
1702 * import { DateTime } from "effect"
1703 *
1704 * const zoned = DateTime.makeZonedUnsafe("2024-01-01T12:30:45.123Z", {
1705 * timeZone: "Europe/London"
1706 * })
1707 * const parts = DateTime.toPartsUtc(zoned)
1708 *
1709 * const selectedParts = [parts.year, parts.month, parts.day, parts.hour] // => [2024, 1, 1, 12]
1710 * ```
1711 *
1712 * @category getters
1713 * @since 3.6.0
1714 */
1715export const toPartsUtc: (self: DateTime) => DateTime.PartsWithWeekday = Internal.toPartsUtc
1716
1717/**
1718 * Gets one UTC part of a `DateTime` as a number.
1719 *
1720 * **Details**
1721 *
1722 * The part will be in the UTC time zone.
1723 *
1724 * **Example** (Reading UTC DateTime parts by key)
1725 *
1726 * ```ts import.meta.vitest
1727 * import { DateTime } from "effect"
1728 *
1729 * const dateTime = DateTime.makeUnsafe({ year: 2024 })
1730 * DateTime.getPartUtc(dateTime, "year") // => 2024
1731 * ```
1732 *
1733 * @category getters
1734 * @since 3.6.0
1735 */
1736export const getPartUtc: {
1737 (part: keyof DateTime.PartsWithWeekday): (self: DateTime) => number
1738 (self: DateTime, part: keyof DateTime.PartsWithWeekday): number
1739} = Internal.getPartUtc
1740
1741/**
1742 * Gets one time-zone-adjusted part of a `DateTime` as a number.
1743 *
1744 * **Details**
1745 *
1746 * The part will be time zone adjusted.
1747 *
1748 * **Example** (Reading DateTime parts by key)
1749 *
1750 * ```ts import.meta.vitest
1751 * import { DateTime } from "effect"
1752 *
1753 * const dateTime = DateTime.makeZonedUnsafe({ year: 2024 }, {
1754 * timeZone: "Europe/London"
1755 * })
1756 * DateTime.getPart(dateTime, "year") // => 2024
1757 * ```
1758 *
1759 * @category getters
1760 * @since 3.6.0
1761 */
1762export const getPart: {
1763 (part: keyof DateTime.PartsWithWeekday): (self: DateTime) => number
1764 (self: DateTime, part: keyof DateTime.PartsWithWeekday): number
1765} = Internal.getPart
1766
1767/**
1768 * Sets time-zone-adjusted parts on a `DateTime`.
1769 *
1770 * **Details**
1771 *
1772 * The date will be time zone adjusted for `DateTime.Zoned`.
1773 *
1774 * **Example** (Updating DateTime parts)
1775 *
1776 * ```ts import.meta.vitest
1777 * import { DateTime } from "effect"
1778 *
1779 * const dt = DateTime.makeZonedUnsafe("2024-01-01T12:00:00Z", { timeZone: "UTC" })
1780 * const updated = DateTime.setParts(dt, {
1781 * year: 2025,
1782 * month: 6,
1783 * day: 15
1784 * })
1785 *
1786 * updated // => DateTime.makeZonedUnsafe("2025-06-15T12:00:00Z", { timeZone: "UTC" })
1787 * ```
1788 *
1789 * @category transforming
1790 * @since 3.6.0
1791 */
1792export const setParts: {
1793 (parts: Partial<DateTime.PartsWithWeekday>): <A extends DateTime>(self: A) => A
1794 <A extends DateTime>(self: A, parts: Partial<DateTime.PartsWithWeekday>): A
1795} = Internal.setParts
1796
1797/**
1798 * Sets UTC parts on a `DateTime`.
1799 *
1800 * **Details**
1801 *
1802 * The parts are always interpreted as UTC, ignoring any time zone information.
1803 *
1804 * **Example** (Updating UTC DateTime parts)
1805 *
1806 * ```ts import.meta.vitest
1807 * import { DateTime } from "effect"
1808 *
1809 * const dt = DateTime.makeUnsafe("2024-01-01T12:00:00Z")
1810 * const updated = DateTime.setPartsUtc(dt, {
1811 * year: 2025,
1812 * hour: 18
1813 * })
1814 *
1815 * updated // => DateTime.makeUnsafe("2025-01-01T18:00:00Z")
1816 * ```
1817 *
1818 * @category transforming
1819 * @since 3.6.0
1820 */
1821export const setPartsUtc: {
1822 (parts: Partial<DateTime.PartsWithWeekday>): <A extends DateTime>(self: A) => A
1823 <A extends DateTime>(self: A, parts: Partial<DateTime.PartsWithWeekday>): A
1824} = Internal.setPartsUtc
1825
1826// =============================================================================
1827// current time zone
1828// =============================================================================
1829
1830/**
1831 * Context service that supplies the ambient `TimeZone` for APIs that work in
1832 * the current zone, such as `DateTime.setZoneCurrent` and
1833 * `DateTime.nowInCurrentZone`.
1834 *
1835 * **Details**
1836 *
1837 * Provide it with `DateTime.withCurrentZone`, one of the `withCurrentZone*`
1838 * helpers, or one of the `layerCurrentZone*` layers.
1839 *
1840 * **Example** (Accessing the current time zone service)
1841 *
1842 * ```ts import.meta.vitest
1843 * import { DateTime, Effect } from "effect"
1844 *
1845 * const program = Effect.gen(function*() {
1846 * return DateTime.zoneToString(yield* DateTime.CurrentTimeZone)
1847 * })
1848 *
1849 * // Provide a time zone
1850 * const layer = DateTime.layerCurrentZoneNamed("Europe/London")
1851 * await Effect.runPromise(Effect.provide(program, layer)) // => "Europe/London"
1852 * ```
1853 *
1854 * @category services
1855 * @since 3.11.0
1856 */
1857export class CurrentTimeZone extends Context.Service<CurrentTimeZone, TimeZone>()(
1858 "effect/DateTime/CurrentTimeZone"
1859) {}
1860
1861/**
1862 * Sets the time zone of a `DateTime` to the current time zone, which is
1863 * determined by the `CurrentTimeZone` service.
1864 *
1865 * **Example** (Setting the current time zone)
1866 *
1867 * ```ts import.meta.vitest
1868 * import { DateTime, Effect } from "effect"
1869 *
1870 * await Effect.runPromise(Effect.gen(function*() {
1871 * const zoned = yield* DateTime.setZoneCurrent(DateTime.makeUnsafe("2024-01-01"))
1872 * return DateTime.zoneToString(zoned.zone)
1873 * }).pipe(DateTime.withCurrentZoneNamed("Europe/London"))) // => "Europe/London"
1874 * ```
1875 *
1876 * @category accessors
1877 * @since 3.6.0
1878 */
1879export const setZoneCurrent = (self: DateTime): Effect.Effect<Zoned, never, CurrentTimeZone> =>
1880 Effect.map(CurrentTimeZone, (zone) => setZone(self, zone))
1881
1882/**
1883 * Provides the `CurrentTimeZone` to an effect.
1884 *
1885 * **Example** (Providing the current time zone)
1886 *
1887 * ```ts import.meta.vitest
1888 * import { DateTime, Effect } from "effect"
1889 *
1890 * const zone = DateTime.zoneMakeNamedUnsafe("Europe/London")
1891 *
1892 * await Effect.runPromise(Effect.gen(function*() {
1893 * const zoned = yield* DateTime.setZoneCurrent(DateTime.makeUnsafe("2024-01-01"))
1894 * return DateTime.zoneToString(zoned.zone)
1895 * }).pipe(DateTime.withCurrentZone(zone))) // => "Europe/London"
1896 * ```
1897 *
1898 * @category providing services
1899 * @since 3.6.0
1900 */
1901export const withCurrentZone: {
1902 (value: TimeZone): <A, E, R>(self: Effect.Effect<A, E, R>) => Effect.Effect<A, E, Exclude<R, CurrentTimeZone>>
1903 <A, E, R>(self: Effect.Effect<A, E, R>, value: TimeZone): Effect.Effect<A, E, Exclude<R, CurrentTimeZone>>
1904} = provideService(CurrentTimeZone)
1905
1906/**
1907 * Provides the `CurrentTimeZone` to an effect, using the system's local time
1908 * zone.
1909 *
1910 * **Example** (Providing the local time zone)
1911 *
1912 * ```ts import.meta.vitest
1913 * import { DateTime, Effect } from "effect"
1914 *
1915 * await Effect.runPromise(Effect.gen(function*() {
1916 * return DateTime.isZoned(yield* DateTime.nowInCurrentZone)
1917 * }).pipe(DateTime.withCurrentZoneLocal)) // => true
1918 * ```
1919 *
1920 * @category providing services
1921 * @since 3.6.0
1922 */
1923export const withCurrentZoneLocal = <A, E, R>(
1924 effect: Effect.Effect<A, E, R>
1925): Effect.Effect<A, E, Exclude<R, CurrentTimeZone>> =>
1926 Effect.provideServiceEffect(effect, CurrentTimeZone, Effect.sync(zoneMakeLocal))
1927
1928/**
1929 * Provides the `CurrentTimeZone` to an effect, using an offset.
1930 *
1931 * **Example** (Providing a fixed-offset time zone)
1932 *
1933 * ```ts import.meta.vitest
1934 * import { DateTime, Effect } from "effect"
1935 *
1936 * const program = Effect.gen(function*() {
1937 * return DateTime.zoneToString(yield* DateTime.CurrentTimeZone)
1938 * }).pipe(DateTime.withCurrentZoneOffset(3 * 60 * 60 * 1000))
1939 *
1940 * await Effect.runPromise(program) // => "+03:00"
1941 * ```
1942 *
1943 * @category providing services
1944 * @since 3.6.0
1945 */
1946export const withCurrentZoneOffset: {
1947 (offset: number): <A, E, R>(
1948 effect: Effect.Effect<A, E, R>
1949 ) => Effect.Effect<A, E, Exclude<R, CurrentTimeZone>>
1950 <A, E, R>(effect: Effect.Effect<A, E, R>, offset: number): Effect.Effect<A, E, Exclude<R, CurrentTimeZone>>
1951} = dual(
1952 2,
1953 <A, E, R>(effect: Effect.Effect<A, E, R>, offset: number): Effect.Effect<A, E, Exclude<R, CurrentTimeZone>> =>
1954 Effect.provideService(effect, CurrentTimeZone, zoneMakeOffset(offset))
1955)
1956
1957/**
1958 * Provides the `CurrentTimeZone` to an effect using an IANA time zone
1959 * identifier.
1960 *
1961 * **Details**
1962 *
1963 * If the time zone is invalid, it will fail with an `IllegalArgumentError`.
1964 *
1965 * **Example** (Providing a named time zone)
1966 *
1967 * ```ts import.meta.vitest
1968 * import { DateTime, Effect } from "effect"
1969 *
1970 * await Effect.runPromise(Effect.gen(function*() {
1971 * const zoned = yield* DateTime.setZoneCurrent(DateTime.makeUnsafe("2024-01-01"))
1972 * return DateTime.zoneToString(zoned.zone)
1973 * }).pipe(DateTime.withCurrentZoneNamed("Europe/London"))) // => "Europe/London"
1974 * ```
1975 *
1976 * @category providing services
1977 * @since 3.6.0
1978 */
1979export const withCurrentZoneNamed: {
1980 (zone: string): <A, E, R>(
1981 effect: Effect.Effect<A, E, R>
1982 ) => Effect.Effect<A, E | IllegalArgumentError, Exclude<R, CurrentTimeZone>>
1983 <A, E, R>(
1984 effect: Effect.Effect<A, E, R>,
1985 zone: string
1986 ): Effect.Effect<A, E | IllegalArgumentError, Exclude<R, CurrentTimeZone>>
1987} = dual(
1988 2,
1989 <A, E, R>(
1990 effect: Effect.Effect<A, E, R>,
1991 zone: string
1992 ): Effect.Effect<A, E | IllegalArgumentError, Exclude<R, CurrentTimeZone>> =>
1993 Effect.provideServiceEffect(effect, CurrentTimeZone, zoneMakeNamedEffect(zone))
1994)
1995
1996/**
1997 * Gets the current time as a `DateTime.Zoned`, using the `CurrentTimeZone`.
1998 *
1999 * **Example** (Getting the current time in the current zone)
2000 *
2001 * ```ts import.meta.vitest
2002 * import { DateTime, Effect } from "effect"
2003 *
2004 * await Effect.runPromise(Effect.gen(function*() {
2005 * return DateTime.zoneToString((yield* DateTime.nowInCurrentZone).zone)
2006 * }).pipe(DateTime.withCurrentZoneNamed("Europe/London"))) // => "Europe/London"
2007 * ```
2008 *
2009 * @category accessors
2010 * @since 3.6.0
2011 */
2012export const nowInCurrentZone: Effect.Effect<Zoned, never, CurrentTimeZone> = Effect.flatMap(now, setZoneCurrent)
2013
2014// =============================================================================
2015// mapping
2016// =============================================================================
2017
2018/**
2019 * Modifies a `DateTime` with a mutable local `Date` copy.
2020 *
2021 * **When to use**
2022 *
2023 * Use to adjust calendar fields in the `DateTime`'s own time zone with an
2024 * existing `Date` mutation API.
2025 *
2026 * **Details**
2027 *
2028 * The `Date` will first have the time zone applied if possible, and then be
2029 * converted back to a `DateTime` within the same time zone.
2030 *
2031 * Supports `disambiguation` when the new wall clock time is ambiguous.
2032 *
2033 * **Example** (Mutating DateTime values with Dates)
2034 *
2035 * ```ts import.meta.vitest
2036 * import { DateTime } from "effect"
2037 *
2038 * const dt = DateTime.makeUnsafe("2024-01-01T12:00:00Z")
2039 *
2040 * DateTime.mutate(dt, (date) => {
2041 * date.setHours(15) // Set to 3 PM
2042 * date.setMinutes(30) // Set to 30 minutes
2043 * })
2044 * ```
2045 *
2046 * @category mapping
2047 * @since 3.6.0
2048 */
2049export const mutate: {
2050 (
2051 f: (date: Date) => void,
2052 options?: {
2053 readonly disambiguation?: Disambiguation | undefined
2054 }
2055 ): <A extends DateTime>(self: A) => A
2056 <A extends DateTime>(
2057 self: A,
2058 f: (date: Date) => void,
2059 options?: {
2060 readonly disambiguation?: Disambiguation | undefined
2061 }
2062 ): A
2063} = Internal.mutate
2064
2065/**
2066 * Modifies a `DateTime` with a mutable UTC `Date` copy.
2067 *
2068 * **When to use**
2069 *
2070 * Use to adjust the instant with an existing `Date` mutation API that works on
2071 * UTC calendar fields.
2072 *
2073 * **Example** (Mutating DateTime values with UTC Dates)
2074 *
2075 * ```ts import.meta.vitest
2076 * import { DateTime } from "effect"
2077 *
2078 * const dt = DateTime.makeZonedUnsafe("2024-01-01T12:00:00Z", {
2079 * timeZone: "Europe/London"
2080 * })
2081 *
2082 * const modified = DateTime.mutateUtc(dt, (date) => {
2083 * date.setUTCHours(18) // Set UTC time to 6 PM
2084 * })
2085 *
2086 * modified // => DateTime.makeZonedUnsafe("2024-01-01T18:00:00Z", { timeZone: "Europe/London" })
2087 * ```
2088 *
2089 * @category mapping
2090 * @since 3.6.0
2091 */
2092export const mutateUtc: {
2093 (f: (date: Date) => void): <A extends DateTime>(self: A) => A
2094 <A extends DateTime>(self: A, f: (date: Date) => void): A
2095} = Internal.mutateUtc
2096
2097/**
2098 * Transforms a `DateTime` by applying a function to the number of milliseconds
2099 * since the Unix epoch.
2100 *
2101 * **Example** (Mapping epoch milliseconds)
2102 *
2103 * ```ts import.meta.vitest
2104 * import { DateTime } from "effect"
2105 *
2106 * // add 10 milliseconds
2107 * const result = DateTime.makeUnsafe(0).pipe(
2108 * DateTime.mapEpochMillis((millis) => millis + 10)
2109 * )
2110 * result // => DateTime.makeUnsafe(10)
2111 * ```
2112 *
2113 * @category mapping
2114 * @since 3.6.0
2115 */
2116export const mapEpochMillis: {
2117 (f: (millis: number) => number): <A extends DateTime>(self: A) => A
2118 <A extends DateTime>(self: A, f: (millis: number) => number): A
2119} = Internal.mapEpochMillis
2120
2121/**
2122 * Applies a function to a JavaScript `Date` representing the `DateTime` and
2123 * returns the function's result.
2124 *
2125 * **Details**
2126 *
2127 * The callback receives the time-zone-adjusted wall-clock date for
2128 * `DateTime.Zoned` values. Use `DateTime.withDateUtc` when the callback should
2129 * receive the UTC instant.
2130 *
2131 * **Example** (Applying time zone adjusted Dates)
2132 *
2133 * ```ts import.meta.vitest
2134 * import { DateTime } from "effect"
2135 *
2136 * // get the time zone adjusted date in milliseconds
2137 * DateTime.makeZonedUnsafe(0, { timeZone: "Europe/London" }).pipe(
2138 * DateTime.withDate((date) => date.getTime())
2139 * ) // => 3600000
2140 * ```
2141 *
2142 * @category mapping
2143 * @since 3.6.0
2144 */
2145export const withDate: {
2146 <A>(f: (date: Date) => A): (self: DateTime) => A
2147 <A>(self: DateTime, f: (date: Date) => A): A
2148} = Internal.withDate
2149
2150/**
2151 * Applies a function to a JavaScript `Date` representing the `DateTime`'s UTC
2152 * instant and returns the function's result.
2153 *
2154 * **Details**
2155 *
2156 * This ignores any associated time zone. Use `DateTime.withDate` when the
2157 * callback should receive the time-zone-adjusted wall-clock date.
2158 *
2159 * **Example** (Applying UTC Dates)
2160 *
2161 * ```ts import.meta.vitest
2162 * import { DateTime } from "effect"
2163 *
2164 * // get the date in milliseconds
2165 * DateTime.makeUnsafe(0).pipe(
2166 * DateTime.withDateUtc((date) => date.getTime())
2167 * ) // => 0
2168 * ```
2169 *
2170 * @category mapping
2171 * @since 3.6.0
2172 */
2173export const withDateUtc: {
2174 <A>(f: (date: Date) => A): (self: DateTime) => A
2175 <A>(self: DateTime, f: (date: Date) => A): A
2176} = Internal.withDateUtc
2177
2178/**
2179 * Pattern match on a `DateTime` to handle `Utc` and `Zoned` cases differently.
2180 *
2181 * **Example** (Pattern matching DateTime variants)
2182 *
2183 * ```ts import.meta.vitest
2184 * import { DateTime } from "effect"
2185 *
2186 * const dt1 = DateTime.makeUnsafe("2024-01-01T12:00:00Z") // Utc
2187 * const dt2 = DateTime.makeZonedUnsafe("2024-06-15T14:30:00Z", {
2188 * timeZone: "Europe/London"
2189 * }) // Zoned
2190 *
2191 * const result1 = DateTime.match(dt1, {
2192 * onUtc: (utc) => `UTC: ${DateTime.formatIso(utc)}`,
2193 * onZoned: (zoned) => `Zoned: ${DateTime.formatIsoZoned(zoned)}`
2194 * })
2195 *
2196 * const result2 = DateTime.match(dt2, {
2197 * onUtc: (utc) => `UTC: ${DateTime.formatIso(utc)}`,
2198 * onZoned: (zoned) => `Zoned: ${DateTime.formatIsoZoned(zoned)}`
2199 * })
2200 *
2201 * result1 // => "UTC: 2024-01-01T12:00:00.000Z"
2202 * result2 // => "Zoned: 2024-06-15T15:30:00.000+01:00[Europe/London]"
2203 * ```
2204 *
2205 * @category mapping
2206 * @since 3.6.0
2207 */
2208export const match: {
2209 <A, B>(options: {
2210 readonly onUtc: (_: Utc) => A
2211 readonly onZoned: (_: Zoned) => B
2212 }): (self: DateTime) => A | B
2213 <A, B>(self: DateTime, options: {
2214 readonly onUtc: (_: Utc) => A
2215 readonly onZoned: (_: Zoned) => B
2216 }): A | B
2217} = Internal.match
2218
2219// =============================================================================
2220// math
2221// =============================================================================
2222
2223/**
2224 * Adds the given `Duration` to a `DateTime`.
2225 *
2226 * **When to use**
2227 *
2228 * Use to move a `DateTime` by an elapsed duration such as minutes, seconds, or
2229 * milliseconds.
2230 *
2231 * **Details**
2232 *
2233 * The duration is converted to milliseconds and added to the epoch
2234 * milliseconds. Zoned values keep their original time zone.
2235 *
2236 * **Gotchas**
2237 *
2238 * This is elapsed-time arithmetic, not calendar-aware local date arithmetic.
2239 * Use `add` when adding days, weeks, months, or years should account for the
2240 * date/time zone rules.
2241 *
2242 * **Example** (Adding durations)
2243 *
2244 * ```ts import.meta.vitest
2245 * import { DateTime } from "effect"
2246 *
2247 * // add 5 minutes
2248 * DateTime.makeUnsafe(0).pipe(
2249 * DateTime.addDuration("5 minutes")
2250 * ) // => DateTime.makeUnsafe(300000)
2251 * ```
2252 *
2253 * @see {@link add} for calendar-aware date/time part arithmetic
2254 * @see {@link subtractDuration} for subtracting an elapsed duration
2255 *
2256 * @category math
2257 * @since 3.6.0
2258 */
2259export const addDuration: {
2260 (duration: Duration.Input): <A extends DateTime>(self: A) => A
2261 <A extends DateTime>(self: A, duration: Duration.Input): A
2262} = Internal.addDuration
2263
2264/**
2265 * Subtracts the given `Duration` from a `DateTime`.
2266 *
2267 * **Example** (Subtracting durations)
2268 *
2269 * ```ts import.meta.vitest
2270 * import { DateTime } from "effect"
2271 *
2272 * // subtract 5 minutes
2273 * DateTime.makeUnsafe(0).pipe(
2274 * DateTime.subtractDuration("5 minutes")
2275 * ) // => DateTime.makeUnsafe(-300000)
2276 * ```
2277 *
2278 * @category math
2279 * @since 3.6.0
2280 */
2281export const subtractDuration: {
2282 (duration: Duration.Input): <A extends DateTime>(self: A) => A
2283 <A extends DateTime>(self: A, duration: Duration.Input): A
2284} = Internal.subtractDuration
2285
2286/**
2287 * Adds the given `amount` of `unit` to a `DateTime`.
2288 *
2289 * **Details**
2290 *
2291 * The time zone is taken into account when adding days, weeks, months, and
2292 * years.
2293 *
2294 * **Example** (Adding date and time parts)
2295 *
2296 * ```ts import.meta.vitest
2297 * import { DateTime } from "effect"
2298 *
2299 * // add 5 minutes
2300 * DateTime.makeUnsafe(0).pipe(
2301 * DateTime.add({ minutes: 5 })
2302 * ) // => DateTime.makeUnsafe(300000)
2303 * ```
2304 *
2305 * @category math
2306 * @since 3.6.0
2307 */
2308export const add: {
2309 (parts: Partial<DateTime.PartsForMath>): <A extends DateTime>(self: A) => A
2310 <A extends DateTime>(self: A, parts: Partial<DateTime.PartsForMath>): A
2311} = Internal.add
2312
2313/**
2314 * Subtracts the given `amount` of `unit` from a `DateTime`.
2315 *
2316 * **Example** (Subtracting date and time parts)
2317 *
2318 * ```ts import.meta.vitest
2319 * import { DateTime } from "effect"
2320 *
2321 * // subtract 5 minutes
2322 * DateTime.makeUnsafe(0).pipe(
2323 * DateTime.subtract({ minutes: 5 })
2324 * ) // => DateTime.makeUnsafe(-300000)
2325 * ```
2326 *
2327 * @category math
2328 * @since 3.6.0
2329 */
2330export const subtract: {
2331 (parts: Partial<DateTime.PartsForMath>): <A extends DateTime>(self: A) => A
2332 <A extends DateTime>(self: A, parts: Partial<DateTime.PartsForMath>): A
2333} = Internal.subtract
2334
2335/**
2336 * Converts a `DateTime` to the start of the given `part`.
2337 *
2338 * **Details**
2339 *
2340 * If the part is `week`, the `weekStartsOn` option can be used to specify the
2341 * day of the week that the week starts on. The default is 0 (Sunday).
2342 *
2343 * **Example** (Rounding down DateTime values)
2344 *
2345 * ```ts import.meta.vitest
2346 * import { DateTime } from "effect"
2347 *
2348 * // returns "2024-01-01T00:00:00Z"
2349 * DateTime.makeUnsafe("2024-01-01T12:00:00Z").pipe(
2350 * DateTime.startOf("day"),
2351 * ) // => DateTime.makeUnsafe("2024-01-01T00:00:00Z")
2352 * ```
2353 *
2354 * @category math
2355 * @since 3.6.0
2356 */
2357export const startOf: {
2358 (
2359 part: DateTime.UnitSingular,
2360 options?: { readonly weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | undefined }
2361 ): <A extends DateTime>(self: A) => A
2362 <A extends DateTime>(
2363 self: A,
2364 part: DateTime.UnitSingular,
2365 options?: { readonly weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | undefined }
2366 ): A
2367} = Internal.startOf
2368
2369/**
2370 * Converts a `DateTime` to the end of the given `part`.
2371 *
2372 * **Details**
2373 *
2374 * If the part is `week`, the `weekStartsOn` option can be used to specify the
2375 * day of the week that the week starts on. The default is 0 (Sunday).
2376 *
2377 * **Example** (Rounding up DateTime values)
2378 *
2379 * ```ts import.meta.vitest
2380 * import { DateTime } from "effect"
2381 *
2382 * // returns "2024-01-01T23:59:59.999Z"
2383 * DateTime.makeUnsafe("2024-01-01T12:00:00Z").pipe(
2384 * DateTime.endOf("day"),
2385 * ) // => DateTime.makeUnsafe("2024-01-01T23:59:59.999Z")
2386 * ```
2387 *
2388 * @category math
2389 * @since 3.6.0
2390 */
2391export const endOf: {
2392 (
2393 part: DateTime.UnitSingular,
2394 options?: { readonly weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | undefined }
2395 ): <A extends DateTime>(self: A) => A
2396 <A extends DateTime>(
2397 self: A,
2398 part: DateTime.UnitSingular,
2399 options?: { readonly weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | undefined }
2400 ): A
2401} = Internal.endOf
2402
2403/**
2404 * Converts a `DateTime` to the nearest given `part`.
2405 *
2406 * **Details**
2407 *
2408 * If the part is `week`, the `weekStartsOn` option can be used to specify the
2409 * day of the week that the week starts on. The default is 0 (Sunday).
2410 *
2411 * **Example** (Rounding DateTime values to nearest units)
2412 *
2413 * ```ts import.meta.vitest
2414 * import { DateTime } from "effect"
2415 *
2416 * // returns "2024-01-02T00:00:00Z"
2417 * DateTime.makeUnsafe("2024-01-01T12:01:00Z").pipe(
2418 * DateTime.nearest("day"),
2419 * ) // => DateTime.makeUnsafe("2024-01-02T00:00:00Z")
2420 * ```
2421 *
2422 * @category math
2423 * @since 3.6.0
2424 */
2425export const nearest: {
2426 (
2427 part: DateTime.UnitSingular,
2428 options?: { readonly weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | undefined }
2429 ): <A extends DateTime>(self: A) => A
2430 <A extends DateTime>(
2431 self: A,
2432 part: DateTime.UnitSingular,
2433 options?: { readonly weekStartsOn?: 0 | 1 | 2 | 3 | 4 | 5 | 6 | undefined }
2434 ): A
2435} = Internal.nearest
2436
2437// =============================================================================
2438// formatting
2439// =============================================================================
2440
2441/**
2442 * Formats a `DateTime` with `Intl.DateTimeFormat`.
2443 *
2444 * **Details**
2445 *
2446 * Unless a `timeZone` option is supplied, UTC values are formatted in UTC and
2447 * zoned values are formatted in their named zone or fixed-offset zone.
2448 *
2449 * Fixed-offset zones depend on runtime support for offset `timeZone`
2450 * identifiers. When unsupported, formatting falls back to UTC with the
2451 * `DateTime` adjusted to the offset.
2452 *
2453 * **Example** (Formatting DateTime values with Intl options)
2454 *
2455 * ```ts import.meta.vitest
2456 * import { DateTime } from "effect"
2457 *
2458 * const dt = DateTime.makeZonedUnsafe("2024-06-15T14:30:00Z", {
2459 * timeZone: "Europe/London"
2460 * })
2461 *
2462 * DateTime.format(dt, {
2463 * dateStyle: "full",
2464 * timeStyle: "short",
2465 * locale: "en-US"
2466 * }) // => "Saturday, June 15, 2024 at 3:30 PM"
2467 * ```
2468 *
2469 * @category formatting
2470 * @since 3.6.0
2471 */
2472export const format: {
2473 (
2474 options?:
2475 | Intl.DateTimeFormatOptions & {
2476 readonly locale?: string | undefined
2477 }
2478 | undefined
2479 ): (self: DateTime) => string
2480 (
2481 self: DateTime,
2482 options?:
2483 | Intl.DateTimeFormatOptions & {
2484 readonly locale?: string | undefined
2485 }
2486 | undefined
2487 ): string
2488} = Internal.format
2489
2490/**
2491 * Formats a `DateTime` with `Intl.DateTimeFormat` using the system local time
2492 * zone and locale.
2493 *
2494 * **Example** (Formatting DateTime values locally)
2495 *
2496 * ```ts import.meta.vitest
2497 * import { DateTime } from "effect"
2498 *
2499 * const dt = DateTime.makeUnsafe("2024-06-15T14:30:00Z")
2500 *
2501 * // Uses system local time zone and locale
2502 * DateTime.formatLocal(dt, {
2503 * year: "numeric",
2504 * month: "long",
2505 * day: "numeric",
2506 * hour: "2-digit",
2507 * minute: "2-digit"
2508 * })
2509 * ```
2510 *
2511 * @category formatting
2512 * @since 3.6.0
2513 */
2514export const formatLocal: {
2515 (
2516 options?:
2517 | Intl.DateTimeFormatOptions & {
2518 readonly locale?: string | undefined
2519 }
2520 | undefined
2521 ): (self: DateTime) => string
2522 (
2523 self: DateTime,
2524 options?:
2525 | Intl.DateTimeFormatOptions & {
2526 readonly locale?: string | undefined
2527 }
2528 | undefined
2529 ): string
2530} = Internal.formatLocal
2531
2532/**
2533 * Formats a `DateTime` with `Intl.DateTimeFormat` using the UTC time zone.
2534 *
2535 * **Details**
2536 *
2537 * This forces the time zone to be UTC.
2538 *
2539 * **Example** (Formatting DateTime values in UTC)
2540 *
2541 * ```ts import.meta.vitest
2542 * import { DateTime } from "effect"
2543 *
2544 * const dt = DateTime.makeZonedUnsafe("2024-06-15T14:30:00Z", {
2545 * timeZone: "Europe/London"
2546 * })
2547 *
2548 * // Force UTC formatting regardless of time zone
2549 * DateTime.formatUtc(dt, {
2550 * year: "numeric",
2551 * month: "2-digit",
2552 * day: "2-digit",
2553 * hour: "2-digit",
2554 * minute: "2-digit",
2555 * timeZoneName: "short"
2556 * })
2557 * ```
2558 *
2559 * @category formatting
2560 * @since 3.6.0
2561 */
2562export const formatUtc: {
2563 (
2564 options?:
2565 | Intl.DateTimeFormatOptions & {
2566 readonly locale?: string | undefined
2567 }
2568 | undefined
2569 ): (self: DateTime) => string
2570 (
2571 self: DateTime,
2572 options?:
2573 | Intl.DateTimeFormatOptions & {
2574 readonly locale?: string | undefined
2575 }
2576 | undefined
2577 ): string
2578} = Internal.formatUtc
2579
2580/**
2581 * Formats a `DateTime` as a string using the `Intl.DateTimeFormat` API.
2582 *
2583 * **When to use**
2584 *
2585 * Use when you already have an `Intl.DateTimeFormat` and want it to control the
2586 * locale, time zone, and formatting options.
2587 *
2588 * **Details**
2589 *
2590 * The formatter receives the `DateTime` epoch milliseconds. Any time zone
2591 * conversion comes from the supplied formatter.
2592 *
2593 * **Example** (Formatting DateTime values with custom formatters)
2594 *
2595 * ```ts import.meta.vitest
2596 * import { DateTime } from "effect"
2597 *
2598 * const dt = DateTime.makeUnsafe("2024-06-15T14:30:00Z")
2599 *
2600 * // Create a custom formatter
2601 * const formatter = new Intl.DateTimeFormat("de-DE", {
2602 * year: "numeric",
2603 * month: "long",
2604 * day: "numeric",
2605 * hour: "2-digit",
2606 * minute: "2-digit",
2607 * timeZone: "Europe/Berlin"
2608 * })
2609 *
2610 * DateTime.formatIntl(dt, formatter).length > 0 // => true
2611 * ```
2612 *
2613 * @see {@link formatUtc} for formatting with options forced to UTC
2614 * @see {@link formatIso} for stable ISO formatting
2615 *
2616 * @category formatting
2617 * @since 3.6.0
2618 */
2619export const formatIntl: {
2620 (format: Intl.DateTimeFormat): (self: DateTime) => string
2621 (self: DateTime, format: Intl.DateTimeFormat): string
2622} = Internal.formatIntl
2623
2624/**
2625 * Formats a `DateTime` as a UTC ISO string.
2626 *
2627 * **Details**
2628 *
2629 * Always returns the UTC representation in ISO 8601 format, ignoring any time zone.
2630 *
2631 * **Example** (Formatting DateTime values as ISO strings)
2632 *
2633 * ```ts import.meta.vitest
2634 * import { DateTime } from "effect"
2635 *
2636 * DateTime.formatIso(DateTime.makeUnsafe("2024-01-01T12:30:45.123Z")) // => "2024-01-01T12:30:45.123Z"
2637 *
2638 * const zoned = DateTime.makeZonedUnsafe("2024-01-01T12:30:45.123Z", {
2639 * timeZone: "Europe/London"
2640 * })
2641 * DateTime.formatIso(zoned) // => "2024-01-01T12:30:45.123Z"
2642 * ```
2643 *
2644 * @category formatting
2645 * @since 3.6.0
2646 */
2647export const formatIso: (self: DateTime) => string = Internal.formatIso
2648
2649/**
2650 * Formats a `DateTime` as a time zone adjusted ISO date string.
2651 *
2652 * **Details**
2653 *
2654 * Returns only the date part (YYYY-MM-DD) after applying time zone adjustments.
2655 *
2656 * **Example** (Formatting DateTime values as ISO dates)
2657 *
2658 * ```ts import.meta.vitest
2659 * import { DateTime } from "effect"
2660 *
2661 * const dt = DateTime.makeUnsafe("2024-01-01T23:30:00Z")
2662 * DateTime.formatIsoDate(dt) // => "2024-01-01"
2663 *
2664 * const zoned = DateTime.makeZonedUnsafe("2024-01-01T23:30:00Z", {
2665 * timeZone: "Pacific/Auckland" // UTC+12/13
2666 * })
2667 * DateTime.formatIsoDate(zoned) // => "2024-01-02"
2668 * ```
2669 *
2670 * @category formatting
2671 * @since 3.6.0
2672 */
2673export const formatIsoDate: (self: DateTime) => string = Internal.formatIsoDate
2674
2675/**
2676 * Formats a `DateTime` as a UTC ISO date string.
2677 *
2678 * **Details**
2679 *
2680 * Returns only the date part (YYYY-MM-DD) in UTC, ignoring any time zone.
2681 *
2682 * **Example** (Formatting DateTime values as UTC ISO dates)
2683 *
2684 * ```ts import.meta.vitest
2685 * import { DateTime } from "effect"
2686 *
2687 * const dt = DateTime.makeUnsafe("2024-01-01T23:30:00Z")
2688 * DateTime.formatIsoDateUtc(dt) // => "2024-01-01"
2689 *
2690 * const zoned = DateTime.makeZonedUnsafe("2024-01-01T23:30:00Z", {
2691 * timeZone: "Pacific/Auckland"
2692 * })
2693 * DateTime.formatIsoDateUtc(zoned) // => "2024-01-01"
2694 * ```
2695 *
2696 * @category formatting
2697 * @since 3.6.0
2698 */
2699export const formatIsoDateUtc: (self: DateTime) => string = Internal.formatIsoDateUtc
2700
2701/**
2702 * Formats a `DateTime.Zoned` as an ISO string with an offset.
2703 *
2704 * **Details**
2705 *
2706 * For `DateTime.Utc`, returns the same as `formatIso`. For `DateTime.Zoned`,
2707 * includes the time zone offset in the format.
2708 *
2709 * **Example** (Formatting DateTime values with offsets)
2710 *
2711 * ```ts import.meta.vitest
2712 * import { DateTime } from "effect"
2713 *
2714 * const utc = DateTime.makeUnsafe("2024-01-01T12:00:00Z")
2715 * DateTime.formatIsoOffset(utc) // => "2024-01-01T12:00:00.000Z"
2716 *
2717 * const zoned = DateTime.makeZonedUnsafe("2024-01-01T12:00:00Z", {
2718 * timeZone: DateTime.zoneMakeOffset(3 * 60 * 60 * 1000)
2719 * })
2720 * DateTime.formatIsoOffset(zoned) // => "2024-01-01T15:00:00.000+03:00"
2721 * ```
2722 *
2723 * @category formatting
2724 * @since 3.6.0
2725 */
2726export const formatIsoOffset: (self: DateTime) => string = Internal.formatIsoOffset
2727
2728/**
2729 * Formats a `DateTime.Zoned` as a string.
2730 *
2731 * **Details**
2732 *
2733 * It uses the format: `YYYY-MM-DDTHH:mm:ss.sss+HH:MM[Time/Zone]`.
2734 *
2735 * **Example** (Formatting zoned DateTime values)
2736 *
2737 * ```ts import.meta.vitest
2738 * import { DateTime } from "effect"
2739 *
2740 * const zoned = DateTime.makeZonedUnsafe("2024-06-15T14:30:45.123Z", {
2741 * timeZone: "Europe/London"
2742 * })
2743 *
2744 * DateTime.formatIsoZoned(zoned) // => "2024-06-15T15:30:45.123+01:00[Europe/London]"
2745 *
2746 * const offsetZone = DateTime.makeZonedUnsafe("2024-06-15T14:30:45.123Z", {
2747 * timeZone: DateTime.zoneMakeOffset(3 * 60 * 60 * 1000)
2748 * })
2749 *
2750 * DateTime.formatIsoZoned(offsetZone) // => "2024-06-15T17:30:45.123+03:00"
2751 * ```
2752 *
2753 * @category formatting
2754 * @since 3.6.0
2755 */
2756export const formatIsoZoned: (self: Zoned) => string = Internal.formatIsoZoned
2757
2758/**
2759 * Create a Layer from the given time zone.
2760 *
2761 * **Details**
2762 *
2763 * This layer provides the `CurrentTimeZone` service with the specified time zone.
2764 *
2765 * **Example** (Providing current time zone layers)
2766 *
2767 * ```ts import.meta.vitest
2768 * import { DateTime, Effect } from "effect"
2769 *
2770 * const zone = DateTime.zoneMakeNamedUnsafe("Europe/London")
2771 * const layer = DateTime.layerCurrentZone(zone)
2772 *
2773 * const program = Effect.gen(function*() {
2774 * const now = yield* DateTime.nowInCurrentZone
2775 * return DateTime.zoneToString(now.zone)
2776 * })
2777 *
2778 * // Use the layer to provide the time zone
2779 * await Effect.runPromise(Effect.provide(program, layer)) // => "Europe/London"
2780 * ```
2781 *
2782 * @category layers
2783 * @since 3.6.0
2784 */
2785export const layerCurrentZone: (resource: NoInfer<TimeZone>) => Layer.Layer<CurrentTimeZone> = Layer.succeed(
2786 CurrentTimeZone
2787)
2788
2789/**
2790 * Create a Layer from the given time zone offset.
2791 *
2792 * **Details**
2793 *
2794 * This layer provides the `CurrentTimeZone` service with a fixed offset time zone.
2795 *
2796 * **Example** (Providing fixed-offset time zone layers)
2797 *
2798 * ```ts import.meta.vitest
2799 * import { DateTime, Effect } from "effect"
2800 *
2801 * // Create a layer for UTC+3
2802 * const layer = DateTime.layerCurrentZoneOffset(3 * 60 * 60 * 1000)
2803 *
2804 * const program = Effect.gen(function*() {
2805 * const now = yield* DateTime.nowInCurrentZone
2806 * return DateTime.zoneToString(now.zone)
2807 * })
2808 *
2809 * await Effect.runPromise(Effect.provide(program, layer)) // => "+03:00"
2810 * ```
2811 *
2812 * @category layers
2813 * @since 3.6.0
2814 */
2815export const layerCurrentZoneOffset = (offset: number): Layer.Layer<CurrentTimeZone> =>
2816 Layer.succeed(CurrentTimeZone)(Internal.zoneMakeOffset(offset))
2817
2818/**
2819 * Create a Layer from the given IANA time zone identifier.
2820 *
2821 * **Details**
2822 *
2823 * This layer provides the `CurrentTimeZone` service with a named time zone.
2824 * If the time zone identifier is invalid, the layer will fail.
2825 *
2826 * **Example** (Providing named time zone layers)
2827 *
2828 * ```ts import.meta.vitest
2829 * import { DateTime, Effect } from "effect"
2830 *
2831 * const layer = DateTime.layerCurrentZoneNamed("Europe/London")
2832 *
2833 * const program = Effect.gen(function*() {
2834 * const now = yield* DateTime.nowInCurrentZone
2835 * return DateTime.zoneToString(now.zone)
2836 * })
2837 *
2838 * await Effect.runPromise(Effect.provide(program, layer)) // => "Europe/London"
2839 * ```
2840 *
2841 * @category layers
2842 * @since 3.6.0
2843 */
2844export const layerCurrentZoneNamed: (zoneId: string) => Layer.Layer<
2845 CurrentTimeZone,
2846 IllegalArgumentError
2847> = flow(Internal.zoneMakeNamedEffect, Layer.effect(CurrentTimeZone))
2848
2849/**
2850 * Create a Layer from the system's local time zone.
2851 *
2852 * **Details**
2853 *
2854 * This layer provides the `CurrentTimeZone` service using the system's
2855 * configured local time zone.
2856 *
2857 * **Example** (Providing local time zone layers)
2858 *
2859 * ```ts import.meta.vitest
2860 * import { DateTime, Effect } from "effect"
2861 *
2862 * const program = Effect.gen(function*() {
2863 * const now = yield* DateTime.nowInCurrentZone
2864 * return DateTime.isZoned(now)
2865 * })
2866 *
2867 * // Use the system's local time zone
2868 * await Effect.runPromise(Effect.provide(program, DateTime.layerCurrentZoneLocal)) // => true
2869 * ```
2870 *
2871 * @category layers
2872 * @since 3.6.0
2873 */
2874export const layerCurrentZoneLocal: Layer.Layer<CurrentTimeZone> = Layer.sync(CurrentTimeZone)(zoneMakeLocal)