intldate
Date formatting for gleam_time following the JavaScript Intl.DateTimeFormat() API.
This module provides a type-safe wrapper around the Intl.DateTimeFormat API,
allowing you to format dates and times according to locale-specific conventions.
Works on both the JavaScript and Erlang runtimes. On JavaScript it delegates to
the native Intl.DateTimeFormat(), while on Erlang it uses a pure Gleam
reimplementation that mirrors the same behaviour, so the output stays consistent
whichever target you compile to.
Error handling
format never fails: if the time zone, locale, or calendar cannot be resolved, it
returns a human-readable, English-only message describing the error (via
describe_error), regardless of the requested locale.
If you’d rather handle the error yourself, use try_format, which returns a
Result(String, IntlError).
Types
The calendar system to use for date formatting.
CalendarBuddhist: Buddhist calendarCalendarChinese: Chinese calendarCalendarCoptic: Coptic calendarCalendarDangi: Dangi calendar (Korean)CalendarEthioaa: Ethiopic Amete Alem calendarCalendarEthiopic: Ethiopic calendarCalendarGregory: Gregorian calendarCalendarHebrew: Hebrew calendarCalendarIndian: Indian national calendarCalendarIslamic: Islamic calendarCalendarIslamicUmalqura: Islamic calendar (Umm al-Qura)CalendarIslamicTbla: Islamic calendar (tabular, astronomical epoch)CalendarIslamicCivil: Islamic calendar (tabular, civil epoch)CalendarIslamicRgsa: Islamic calendar (Saudi Arabia sighting)CalendarIso8601: ISO 8601 calendar (Gregorian with ISO week numbering)CalendarJapanese: Japanese imperial calendarCalendarPersian: Persian calendarCalendarRoc: Republic of China calendar
pub type Calendar {
CalendarBuddhist
CalendarChinese
CalendarCoptic
CalendarDangi
CalendarEthioaa
CalendarEthiopic
CalendarGregory
CalendarHebrew
CalendarIndian
CalendarIslamic
CalendarIslamicUmalqura
CalendarIslamicTbla
CalendarIslamicCivil
CalendarIslamicRgsa
CalendarIso8601
CalendarJapanese
CalendarPersian
CalendarRoc
}
Constructors
-
CalendarBuddhist -
CalendarChinese -
CalendarCoptic -
CalendarDangi -
CalendarEthioaa -
CalendarEthiopic -
CalendarGregory -
CalendarHebrew -
CalendarIndian -
CalendarIslamic -
CalendarIslamicUmalqura -
CalendarIslamicTbla -
CalendarIslamicCivil -
CalendarIslamicRgsa -
CalendarIso8601 -
CalendarJapanese -
CalendarPersian -
CalendarRoc
Configuration for date/time formatting.
This type allows you to specify which date and time components to include in the formatted output and how they should be represented.
Create a new configuration with new() and customize it with the various
with_* functions.
pub type DateTimeFormatConfig {
DateTimeFormatConfig(
locale_matcher: option.Option(LocaleMatcher),
calendar: option.Option(Calendar),
weekday: option.Option(Weekday),
era: option.Option(Era),
year: option.Option(Year),
month: option.Option(Month),
day: option.Option(Day),
hour: option.Option(Hour),
minute: option.Option(Minute),
second: option.Option(Second),
time_zone_name: option.Option(TimeZoneName),
format_matcher: option.Option(FormatMatcher),
hour12: option.Option(Bool),
)
}
Constructors
-
DateTimeFormatConfig( locale_matcher: option.Option(LocaleMatcher), calendar: option.Option(Calendar), weekday: option.Option(Weekday), era: option.Option(Era), year: option.Option(Year), month: option.Option(Month), day: option.Option(Day), hour: option.Option(Hour), minute: option.Option(Minute), second: option.Option(Second), time_zone_name: option.Option(TimeZoneName), format_matcher: option.Option(FormatMatcher), hour12: option.Option(Bool), )
One structured part of a formatted date/time string.
pub type DateTimeFormatPart {
DateTimeFormatPart(
kind: DateTimePartKind,
value: String,
source: DateTimePartSource,
)
}
Constructors
-
DateTimeFormatPart( kind: DateTimePartKind, value: String, source: DateTimePartSource, )
A part type returned by format_to_parts and format_range_to_parts.
pub type DateTimePartKind {
DateTimePartLiteral
DateTimePartWeekday
DateTimePartEra
DateTimePartYear
DateTimePartRelatedYear
DateTimePartYearName
DateTimePartMonth
DateTimePartDay
DateTimePartDayPeriod
DateTimePartHour
DateTimePartMinute
DateTimePartSecond
DateTimePartFractionalSecond
DateTimePartTimeZoneName
DateTimePartUnknown(inner: String)
}
Constructors
-
DateTimePartLiteral -
DateTimePartWeekday -
DateTimePartEra -
DateTimePartYear -
DateTimePartRelatedYear -
DateTimePartYearName -
DateTimePartMonth -
DateTimePartDay -
DateTimePartDayPeriod -
DateTimePartHour -
DateTimePartMinute -
DateTimePartSecond -
DateTimePartFractionalSecond -
DateTimePartTimeZoneName -
DateTimePartUnknown(inner: String)
Where a range part came from.
pub type DateTimePartSource {
DateTimePartSourceNone
DateTimePartSourceStartRange
DateTimePartSourceShared
DateTimePartSourceEndRange
}
Constructors
-
DateTimePartSourceNone -
DateTimePartSourceStartRange -
DateTimePartSourceShared -
DateTimePartSourceEndRange
Options resolved by a date/time formatter.
pub type DateTimeResolvedOptions {
DateTimeResolvedOptions(
locale: String,
calendar: String,
numbering_system: String,
time_zone: String,
hour_cycle: option.Option(String),
hour12: option.Option(Bool),
weekday: option.Option(String),
era: option.Option(String),
year: option.Option(String),
month: option.Option(String),
day: option.Option(String),
hour: option.Option(String),
minute: option.Option(String),
second: option.Option(String),
time_zone_name: option.Option(String),
)
}
Constructors
-
DateTimeResolvedOptions( locale: String, calendar: String, numbering_system: String, time_zone: String, hour_cycle: option.Option(String), hour12: option.Option(Bool), weekday: option.Option(String), era: option.Option(String), year: option.Option(String), month: option.Option(String), day: option.Option(String), hour: option.Option(String), minute: option.Option(String), second: option.Option(String), time_zone_name: option.Option(String), )
The representation of the day.
DayNumeric: Numeric representation (e.g., “5”)Day2Digit: Two-digit numeric representation (e.g., “05”)
pub type Day {
DayNumeric
Day2Digit
}
Constructors
-
DayNumeric -
Day2Digit
The representation of the era.
EraLong: Full era name (e.g., “Anno Domini”, “après Jésus-Christ”)EraShort: Abbreviated era name (e.g., “AD”, “ap. J.-C.”)EraNarrow: Narrow era name (e.g., “A”, “ap. J.-C.”)
pub type Era {
EraLong
EraShort
EraNarrow
}
Constructors
-
EraLong -
EraShort -
EraNarrow
The format matching algorithm to use.
FormatMatcherBestFit: The runtime is allowed to choose the best format based on the requested components and the locale.FormatMatcherBasic: Use a basic algorithm that prioritizes matching the requested components in order.
pub type FormatMatcher {
FormatMatcherBestFit
FormatMatcherBasic
}
Constructors
-
FormatMatcherBestFit -
FormatMatcherBasic
The representation of the hour.
HourNumeric: Numeric representation (e.g., “5”)Hour2Digit: Two-digit numeric representation (e.g., “05”)
pub type Hour {
HourNumeric
Hour2Digit
}
Constructors
-
HourNumeric -
Hour2Digit
pub type IntlError {
FailedToLoadTimeZone(inner: String)
FailedToLoadLocale(inner: String)
FailedToLoadCalendar(inner: String)
FailedToLoadData(inner: String)
SystemTimeZoneUnavailable
Unknown(inner: String)
}
Constructors
-
FailedToLoadTimeZone(inner: String)The requested time zone could not be loaded or resolved.
-
FailedToLoadLocale(inner: String)The requested locale could not be loaded or resolved.
-
FailedToLoadCalendar(inner: String)The requested calendar could not be loaded or resolved.
-
FailedToLoadData(inner: String)The bundled locale data could not be loaded or validated.
-
SystemTimeZoneUnavailableThe system local time zone could not be detected.
-
Unknown(inner: String)Any error not accounted for by this type.
The locale matching algorithm to use.
LocaleMatcherBestFit: The runtime is allowed to choose the best matching locale, potentially considering extension keys and other options.LocaleMatcherLookup: Use the BCP 47 lookup algorithm to find the best matching locale.
pub type LocaleMatcher {
LocaleMatcherBestFit
LocaleMatcherLookup
}
Constructors
-
LocaleMatcherBestFit -
LocaleMatcherLookup
The representation of the minute.
MinuteNumeric: Numeric representation (e.g., “8”)Minute2Digit: Two-digit numeric representation (e.g., “08”)
pub type Minute {
MinuteNumeric
Minute2Digit
}
Constructors
-
MinuteNumeric -
Minute2Digit
The representation of the month.
MonthNumeric: Numeric representation (e.g., “2”)Month2Digit: Two-digit numeric representation (e.g., “02”)MonthLong: Full month name (e.g., “February”, “février”)MonthShort: Abbreviated month name (e.g., “Feb”, “févr.”)MonthNarrow: Narrow month name (e.g., “F”, “F”)
pub type Month {
MonthNumeric
Month2Digit
MonthLong
MonthShort
MonthNarrow
}
Constructors
-
MonthNumeric -
Month2Digit -
MonthLong -
MonthShort -
MonthNarrow
The representation of the second.
SecondNumeric: Numeric representation (e.g., “3”)Second2Digit: Two-digit numeric representation (e.g., “03”)
pub type Second {
SecondNumeric
Second2Digit
}
Constructors
-
SecondNumeric -
Second2Digit
The localized representation of the time zone name.
TimeZoneNameShort: Short time zone name (e.g., “EST”, “PST”)TimeZoneNameLong: Long time zone name (e.g., “Eastern Standard Time”)TimeZoneNameShortOffset: Short GMT offset (e.g., “GMT+9”)TimeZoneNameLongOffset: Long GMT offset (e.g., “GMT+09:00”)TimeZoneNameShortGeneric: Short generic non-location format (e.g., “ET”, “PT”)TimeZoneNameLongGeneric: Long generic non-location format (e.g., “Eastern Time”)
pub type TimeZoneName {
TimeZoneNameShort
TimeZoneNameLong
TimeZoneNameShortOffset
TimeZoneNameLongOffset
TimeZoneNameShortGeneric
TimeZoneNameLongGeneric
}
Constructors
-
TimeZoneNameShort -
TimeZoneNameLong -
TimeZoneNameShortOffset -
TimeZoneNameLongOffset -
TimeZoneNameShortGeneric -
TimeZoneNameLongGeneric
The representation of the weekday.
WeekdayLong: Full weekday name (e.g., “Monday”, “lundi”)WeekdayShort: Abbreviated weekday name (e.g., “Mon”, “lun”)WeekdayNarrow: Narrow weekday name (e.g., “M”, “L”)
pub type Weekday {
WeekdayLong
WeekdayShort
WeekdayNarrow
}
Constructors
-
WeekdayLong -
WeekdayShort -
WeekdayNarrow
Values
pub fn describe_error(error: IntlError) -> String
Convert an error into a human-readable description.
Example
let assert "Failed to load time zone: Invalid/TimeZone" =
describe_error(FailedToLoadTimeZone("Invalid/TimeZone"))
pub fn format(
date date: timestamp.Timestamp,
time_zone time_zone: option.Option(String),
locale locale: option.Option(String),
config config: DateTimeFormatConfig,
) -> String
Format a timestamp according to the specified locale and configuration.
Parameters
date: The timestamp to formattime_zone: The time zone to use (IANA time zone name like “America/New_York”). IfNone, uses the system’s local time zone.locale: The locale to use for formatting (BCP 47 language tag like “en-US”, “fr-FR”). IfNone, uses the system’s default locale.config: The configuration object specifying which date/time components to include
Why Timestamp Instead of Calendar?
This function depends directly on the timestamp module and not calendar from gleam_time because Calendar
represents a day and time separately without any timezone information, and the built-in timestamp to calendar
conversion in gleam_time does not have complete support for time zones as described by IANA. Therefore, it can
only represent time zones as offsets and does not take countries with daylight saving time into account. Since the
Intl.DateTimeFormat model works directly with a date in UTC and resolves the time zone display from the IANA
database, it is more logical to use a timestamp for this purpose.
Example
import gleam/option
import gleam/time/timestamp
import intldate
let assert Ok(date) = timestamp.parse_rfc3339("2026-02-24T17:48:22+04:00")
intldate.format(
date:,
time_zone: option.Some("Indian/Reunion"),
locale: option.Some("fr-FR"),
config: intldate.new()
|> intldate.with_weekday(intldate.WeekdayLong)
|> intldate.with_year(intldate.YearNumeric)
|> intldate.with_month(intldate.MonthLong)
|> intldate.with_day(intldate.DayNumeric)
|> intldate.with_hour(intldate.HourNumeric)
|> intldate.with_minute(intldate.MinuteNumeric),
)
// -> "mardi 24 février 2026 à 17:48"
pub fn format_range(
date_start date_start: timestamp.Timestamp,
date_end date_end: timestamp.Timestamp,
time_zone time_zone: option.Option(String),
locale locale: option.Option(String),
config config: DateTimeFormatConfig,
) -> String
Format a range between two timestamps according to the specified locale and
configuration, using the same options as format.
This mirrors the Intl.DateTimeFormat.prototype.formatRange API: it renders
the two dates together, collapsing the parts they have in common.
Parameters
date_start: The timestamp marking the start of the rangedate_end: The timestamp marking the end of the rangetime_zone: The time zone to use (IANA time zone name like “America/New_York”). IfNone, uses the system’s local time zone.locale: The locale to use for formatting (BCP 47 language tag like “en-US”, “fr-FR”). IfNone, uses the system’s default locale.config: The configuration object specifying which date/time components to include
Like format, this never fails: if the time zone, locale, or calendar cannot
be resolved, it returns a human-readable, English-only message describing the
error (via describe_error).
Example
import gleam/option
import gleam/time/timestamp
import intldate
let assert Ok(start) = timestamp.parse_rfc3339("2026-02-24T17:48:22+04:00")
let assert Ok(end) = timestamp.parse_rfc3339("2026-02-27T17:48:22+04:00")
intldate.format_range(
date_start: start,
date_end: end,
time_zone: option.Some("Indian/Reunion"),
locale: option.Some("fr-FR"),
config: intldate.new()
|> intldate.with_year(intldate.YearNumeric)
|> intldate.with_month(intldate.MonthLong)
|> intldate.with_day(intldate.DayNumeric),
)
// -> "24–27 février 2026"
pub fn format_range_to_parts(
date_start date_start: timestamp.Timestamp,
date_end date_end: timestamp.Timestamp,
time_zone time_zone: option.Option(String),
locale locale: option.Option(String),
config config: DateTimeFormatConfig,
) -> List(DateTimeFormatPart)
Format a range and return the structured parts of the formatted output.
This mirrors Intl.DateTimeFormat.prototype.formatRangeToParts. Parts that
come from the start date, end date, or shared range text are marked with
source.
pub fn format_to_parts(
date date: timestamp.Timestamp,
time_zone time_zone: option.Option(String),
locale locale: option.Option(String),
config config: DateTimeFormatConfig,
) -> List(DateTimeFormatPart)
Format a timestamp and return the structured parts of the formatted output.
This mirrors Intl.DateTimeFormat.prototype.formatToParts.
pub fn new() -> DateTimeFormatConfig
Create a new date/time format configuration with all options unset.
Use the various with_* functions to customize the configuration.
Example
intldate.new()
|> intldate.with_year(intldate.YearNumeric)
|> intldate.with_month(intldate.MonthLong)
|> intldate.with_day(intldate.DayNumeric)
pub fn resolved_options(
time_zone time_zone: option.Option(String),
locale locale: option.Option(String),
config config: DateTimeFormatConfig,
) -> Result(DateTimeResolvedOptions, IntlError)
Return the options resolved by the date/time formatter.
This mirrors Intl.DateTimeFormat.prototype.resolvedOptions.
pub fn try_format(
date date: timestamp.Timestamp,
time_zone time_zone: option.Option(String),
locale locale: option.Option(String),
config config: DateTimeFormatConfig,
) -> Result(String, IntlError)
Format a timestamp according to the specified locale and configuration,
returning a Result instead of falling back to an error message.
This is identical to format, except it lets you handle the IntlError
yourself instead of getting a human-readable string when resolution fails.
Example
import gleam/option
import gleam/time/timestamp
import intldate
let assert Ok(date) = timestamp.parse_rfc3339("2026-02-24T17:48:22+04:00")
intldate.try_format(
date:,
time_zone: option.Some("Invalid/TimeZone"),
locale: option.Some("fr-FR"),
config: intldate.new()
|> intldate.with_year(intldate.YearNumeric)
|> intldate.with_month(intldate.MonthLong)
|> intldate.with_day(intldate.DayNumeric),
)
// -> Error(intldate.FailedToLoadTimeZone("Invalid/TimeZone"))
pub fn try_format_range(
date_start date_start: timestamp.Timestamp,
date_end date_end: timestamp.Timestamp,
time_zone time_zone: option.Option(String),
locale locale: option.Option(String),
config config: DateTimeFormatConfig,
) -> Result(String, IntlError)
Format a range between two timestamps according to the specified locale and
configuration, returning a Result instead of falling back to an error
message.
This is identical to format_range, except it lets you handle the
IntlError yourself instead of getting a human-readable string when
resolution fails.
pub fn try_format_range_to_parts(
date_start date_start: timestamp.Timestamp,
date_end date_end: timestamp.Timestamp,
time_zone time_zone: option.Option(String),
locale locale: option.Option(String),
config config: DateTimeFormatConfig,
) -> Result(List(DateTimeFormatPart), IntlError)
Format a range to parts, returning a Result.
pub fn try_format_to_parts(
date date: timestamp.Timestamp,
time_zone time_zone: option.Option(String),
locale locale: option.Option(String),
config config: DateTimeFormatConfig,
) -> Result(List(DateTimeFormatPart), IntlError)
Format a timestamp to parts, returning a Result.
pub fn with_calendar(
config: DateTimeFormatConfig,
calendar: Calendar,
) -> DateTimeFormatConfig
Set the calendar system to use for date formatting.
pub fn with_day(
config: DateTimeFormatConfig,
day: Day,
) -> DateTimeFormatConfig
Set the representation of the day.
pub fn with_era(
config: DateTimeFormatConfig,
era: Era,
) -> DateTimeFormatConfig
Set the representation of the era.
pub fn with_format_matcher(
config: DateTimeFormatConfig,
format_matcher: FormatMatcher,
) -> DateTimeFormatConfig
Set the format matching algorithm.
The format matcher determines how the runtime selects the best format pattern based on the requested components and the locale.
pub fn with_hour(
config: DateTimeFormatConfig,
hour: Hour,
) -> DateTimeFormatConfig
Set the representation of the hour.
pub fn with_hour12(
config: DateTimeFormatConfig,
hour12: Bool,
) -> DateTimeFormatConfig
Set whether to use 12-hour time format.
True: Use 12-hour format with AM/PM (e.g., “5:48 PM”)False: Use 24-hour format (e.g., “17:48”)
If not set, the hour format is determined by the locale.
pub fn with_locale_matcher(
config: DateTimeFormatConfig,
locale_matcher: LocaleMatcher,
) -> DateTimeFormatConfig
Set the locale matching algorithm.
The locale matcher determines how the runtime selects the best matching locale when the exact locale you requested isn’t available.
pub fn with_minute(
config: DateTimeFormatConfig,
minute: Minute,
) -> DateTimeFormatConfig
Set the representation of the minute.
pub fn with_month(
config: DateTimeFormatConfig,
month: Month,
) -> DateTimeFormatConfig
Set the representation of the month.
pub fn with_second(
config: DateTimeFormatConfig,
second: Second,
) -> DateTimeFormatConfig
Set the representation of the second.
pub fn with_time_zone_name(
config: DateTimeFormatConfig,
time_zone_name: TimeZoneName,
) -> DateTimeFormatConfig
Set the localized representation of the time zone name.
pub fn with_weekday(
config: DateTimeFormatConfig,
weekday: Weekday,
) -> DateTimeFormatConfig
Set the representation of the weekday.
pub fn with_year(
config: DateTimeFormatConfig,
year: Year,
) -> DateTimeFormatConfig
Set the representation of the year.