icu_datetime/lib.rs
1// This file is part of ICU4X. For terms of use, please see the file
2// called LICENSE at the top level of the ICU4X source tree
3// (online at: https://github.com/unicode-org/icu4x/blob/main/LICENSE ).
4
5//! Localized formatting of dates, times, and time zones.
6//!
7//! This module is published as its own crate ([`icu_datetime`](https://docs.rs/icu_datetime/latest/icu_datetime/))
8//! and as part of the [`icu`](https://docs.rs/icu/latest/icu/) crate. See the latter for more details on the ICU4X project.
9//!
10//! ICU4X datetime formatting follows the Unicode UTS 35 standard for [Semantic Skeletons](https://unicode.org/reports/tr35/tr35-dates.html#Semantic_Skeletons).
11//! First you choose a _field set_, then you configure the formatting _options_ to your desired context.
12//!
13//! 1. Field Sets: [`icu::datetime::fieldsets`](fieldsets)
14//! 2. Options: [`icu::datetime::options`](options)
15//!
16//! ICU4X supports formatting in over one dozen _calendar systems_, including Gregorian, Buddhist,
17//! Hijri, and more. The calendar system is usually derived from the locale, but it can also be
18//! specified explicitly.
19//!
20//! The main formatter in this crate is [`DateTimeFormatter`], which supports all field sets,
21//! options, and calendar systems. Additional formatter types are available to developers in
22//! resource-constrained environments.
23//!
24//! The formatters accept input types from the [`calendar`](icu_calendar) and
25//! [`timezone`](icu_time) crates (Also reexported from the [`input`] module of this crate):
26//!
27//! 1. [`Date`](icu_calendar::Date)
28//! 2. [`DateTime`](icu_time::DateTime)
29//! 3. [`Time`](icu_time::Time)
30//! 4. [`UtcOffset`](icu_time::zone::UtcOffset)
31//! 5. [`TimeZoneInfo`](icu_time::TimeZoneInfo)
32//! 6. [`ZonedDateTime`](icu_time::ZonedDateTime)
33//!
34//! Not all inputs are valid for all field sets.
35//!
36//! # Examples
37//!
38//! ```
39//! use icu::datetime::fieldsets;
40//! use icu::datetime::input::Date;
41//! use icu::datetime::input::{DateTime, Time};
42//! use icu::datetime::DateTimeFormatter;
43//! use icu::locale::{locale, Locale};
44//! use writeable::assert_writeable_eq;
45//!
46//! // Field set for year, month, day, hour, and minute with a medium length:
47//! let field_set_with_options = fieldsets::YMD::medium().with_time_hm();
48//!
49//! // Create a formatter for Argentinian Spanish:
50//! let locale = locale!("es-AR");
51//! let dtf = DateTimeFormatter::try_new(locale.into(), field_set_with_options)
52//! .unwrap();
53//!
54//! // Format something:
55//! let datetime = DateTime {
56//! date: Date::try_new_iso(2025, 1, 15).unwrap(),
57//! time: Time::try_new(16, 9, 35, 0).unwrap(),
58//! };
59//! let formatted_date = dtf.format(&datetime);
60//!
61//! assert_writeable_eq!(formatted_date, "15 de ene de 2025, 4:09 p. m.");
62//! ```
63//!
64//! # Binary Size Considerations
65//!
66//! ## Avoid linking unnecessary field sets data
67//!
68//! There are two APIs for fieldsets:
69//! * "static" field sets, like [`fieldsets::YMD`], where each field set is a *type*.
70//! * "dynamic" field sets, like [`fieldsets::enums::CompositeFieldSet`], where each field set is a *value*.
71//!
72//! While dynamic fields sets may offer a more powerful API, using them in constructors links data for all
73//! possible values, i.e. all patterns, that the dynamic field set can represent, even if they are
74//! unreachable in code.
75//!
76//! Static field sets on the other hand leverage the type system to let the compiler drop unneeded data.
77//!
78//! ### Example
79//!
80//! ```
81//! use icu::datetime::DateTimeFormatter;
82//! use icu::datetime::fieldsets::YMD;
83//! use icu::datetime::fieldsets::enums::{CompositeFieldSet, DateFieldSet};
84//!
85//! // This constructor only links data required for YMD
86//! let a: DateTimeFormatter<YMD> =
87//! DateTimeFormatter::try_new(Default::default(), YMD::medium()).unwrap();
88//!
89//! // This constructor links data for *all possible field sets*, even though we only use YMD
90//! let b: DateTimeFormatter<CompositeFieldSet> =
91//! DateTimeFormatter::try_new(Default::default(), CompositeFieldSet::Date(DateFieldSet::YMD(YMD::medium()))).unwrap();
92//!
93//! // If a DateTimeFormatter<CompositeFieldSet> is required, cast after construction instead:
94//! let c: DateTimeFormatter<CompositeFieldSet> = a.cast_into_fset::<CompositeFieldSet>();
95//! ```
96//!
97//! ## Avoid linking unnecessary calendar data
98//!
99//! All field sets that contain dates use different data for each calendar system when used with [`DateTimeFormatter`].
100//! This is good i18n practice, as in general the calendar system should be derived from the user locale,
101//! not fixed in code. However, there are legitimate use cases where only one calendar system is supported,
102//! in which case [`DateTimeFormatter`] would link unused data. In this case [`FixedCalendarDateTimeFormatter`]
103//! can be used, which is generic in a calendar type and only links the data for that calendar.
104//!
105//! Using [`FixedCalendarDateTimeFormatter`] also avoids linking code that converts inputs to the user's calendar.
106//! For field sets that don't contain dates, this can also be achieved using [`NoCalendarFormatter`].
107
108// https://github.com/unicode-org/icu4x/blob/main/documents/process/boilerplate.md#library-annotations
109#![cfg_attr(not(any(test, doc)), no_std)]
110#![cfg_attr(
111 not(test),
112 deny(
113 clippy::indexing_slicing,
114 clippy::unwrap_used,
115 clippy::expect_used,
116 clippy::panic,
117 clippy::exhaustive_structs,
118 clippy::exhaustive_enums,
119 clippy::trivially_copy_pass_by_ref,
120 missing_debug_implementations,
121 )
122)]
123#![warn(missing_docs)]
124
125extern crate alloc;
126
127mod combo;
128mod error;
129mod external_loaders;
130pub mod fieldsets;
131mod format;
132mod neo;
133pub mod options;
134pub mod parts;
135pub mod pattern;
136pub mod provider;
137pub(crate) mod raw;
138pub mod scaffold;
139pub(crate) mod size_test_macro;
140pub mod unchecked;
141
142pub use error::{DateTimeFormatterLoadError, MismatchedCalendarError};
143
144pub use neo::DateTimeFormatter;
145pub use neo::DateTimeFormatterPreferences;
146pub use neo::FixedCalendarDateTimeFormatter;
147pub use neo::FormattedDateTime;
148pub use neo::NoCalendarFormatter;
149
150/// Locale preferences used by this crate
151pub mod preferences {
152 /// **This is a reexport of a type in [`icu::locale`](icu_locale_core::preferences::extensions::unicode::keywords)**.
153 #[doc = "\n"] // prevent autoformatting
154 pub use icu_locale_core::preferences::extensions::unicode::keywords::CalendarAlgorithm;
155 /// **This is a reexport of a type in [`icu::locale`](icu_locale_core::preferences::extensions::unicode::keywords)**.
156 #[doc = "\n"] // prevent autoformatting
157 pub use icu_locale_core::preferences::extensions::unicode::keywords::HijriCalendarAlgorithm;
158 /// **This is a reexport of a type in [`icu::locale`](icu_locale_core::preferences::extensions::unicode::keywords)**.
159 #[doc = "\n"] // prevent autoformatting
160 pub use icu_locale_core::preferences::extensions::unicode::keywords::HourCycle;
161 /// **This is a reexport of a type in [`icu::locale`](icu_locale_core::preferences::extensions::unicode::keywords)**.
162 #[doc = "\n"] // prevent autoformatting
163 pub use icu_locale_core::preferences::extensions::unicode::keywords::NumberingSystem;
164}
165
166/// Types that can be fed to [`DateTimeFormatter`]/[`FixedCalendarDateTimeFormatter`].
167///
168/// This module contains re-exports from the [`icu_calendar`] and [`icu_time`] crates.
169pub mod input {
170 pub use icu_calendar::Date;
171 pub use icu_time::zone::UtcOffset;
172 pub use icu_time::DateTime;
173 pub use icu_time::Time;
174 pub use icu_time::TimeZone;
175 pub use icu_time::TimeZoneInfo;
176 pub use icu_time::ZonedDateTime;
177}