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//! Formatting date and time.
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//! [`TypedDateTimeFormatter`] and [`DateTimeFormatter`] are the main types of the component. They accepts a set of arguments which
11//! allow it to collect necessary data from the [data provider], and once instantiated, can be
12//! used to quickly format any date and time provided. There are variants of these types that can format greater or fewer components,
13//! including [`TypedDateFormatter`] & [`DateFormatter`], [`TypedZonedDateTimeFormatter`] & [`ZonedDateTimeFormatter`], [`TimeFormatter`],
14//! and [`TimeZoneFormatter`]
15//!
16//! These formatters work with types from the [`calendar`] module, like [`Date`], [`DateTime`], and [`Time`],
17//! and [`timezone::CustomTimeZone`], however other types may be used provided they implement the traits from the [`input`] module.
18//!
19//! Each instance of a date-related formatter (i.e. not [`TimeFormatter`] or [`TimeZoneFormatter`]
20//! is associated with a particular [`Calendar`].
21//! The "Typed" vs untyped formatter distinction is to help with this. For example, if you know at compile time that you
22//! will only be formatting Gregorian dates, you can use [`TypedDateTimeFormatter<Gregorian>`](TypedDateTimeFormatter) and the
23//! APIs will make sure that only Gregorian [`DateTime`]s are used with the calendar. On the other hand, if you want to be able to select
24//! the calendar at runtime, you can use [`DateTimeFormatter`] with the calendar specified in the locale, and use it with
25//! [`DateTime`],[`AnyCalendar`]. These formatters still require dates associated
26//! with the appropriate calendar (though they will convert ISO dates to the calendar if provided), they just do not force the
27//! programmer to pick the calendar at compile time.
28//!
29//!
30//! # Examples
31//!
32//! ```
33//! use icu::calendar::{DateTime, Gregorian};
34//! use icu::datetime::{
35//!     options::length, DateTimeFormatter, DateTimeFormatterOptions,
36//!     TypedDateTimeFormatter,
37//! };
38//! use icu::locid::{locale, Locale};
39//! use std::str::FromStr;
40//! use writeable::assert_writeable_eq;
41//!
42//! // See the next code example for a more ergonomic example with .into().
43//! let options =
44//!     DateTimeFormatterOptions::Length(length::Bag::from_date_time_style(
45//!         length::Date::Medium,
46//!         length::Time::Short,
47//!     ));
48//!
49//! // You can work with a formatter that can select the calendar at runtime:
50//! let locale = Locale::from_str("en-u-ca-gregory").unwrap();
51//! let dtf = DateTimeFormatter::try_new(&locale.into(), options.clone())
52//!     .expect("Failed to create DateTimeFormatter instance.");
53//!
54//! // Or one that selects a calendar at compile time:
55//! let typed_dtf = TypedDateTimeFormatter::<Gregorian>::try_new(
56//!     &locale!("en").into(),
57//!     options,
58//! )
59//! .expect("Failed to create TypedDateTimeFormatter instance.");
60//!
61//! let typed_date =
62//!     DateTime::try_new_gregorian_datetime(2020, 9, 12, 12, 34, 28).unwrap();
63//! // prefer using ISO dates with DateTimeFormatter
64//! let date = typed_date.to_iso().to_any();
65//!
66//! let formatted_date = dtf.format(&date).expect("Calendars should match");
67//! let typed_formatted_date = typed_dtf.format(&typed_date);
68//!
69//! assert_writeable_eq!(formatted_date, "Sep 12, 2020, 12:34 PM");
70//! assert_writeable_eq!(typed_formatted_date, "Sep 12, 2020, 12:34 PM");
71//!
72//! let formatted_date_string =
73//!     dtf.format_to_string(&date).expect("Calendars should match");
74//! let typed_formatted_date_string = typed_dtf.format_to_string(&typed_date);
75//!
76//! assert_eq!(formatted_date_string, "Sep 12, 2020, 12:34 PM");
77//! assert_eq!(typed_formatted_date_string, "Sep 12, 2020, 12:34 PM");
78//! ```
79//!
80//! The options can be created more ergonomically using the `Into` trait to automatically
81//! convert a [`options::length::Bag`] into a [`DateTimeFormatterOptions::Length`].
82//!
83//! ```
84//! use icu::calendar::Gregorian;
85//! use icu::datetime::{
86//!     options::length, DateTimeFormatterOptions, TypedDateTimeFormatter,
87//! };
88//! use icu::locid::locale;
89//! let options = length::Bag::from_date_time_style(
90//!     length::Date::Medium,
91//!     length::Time::Short,
92//! )
93//! .into();
94//!
95//! let dtf = TypedDateTimeFormatter::<Gregorian>::try_new(
96//!     &locale!("en").into(),
97//!     options,
98//! );
99//! ```
100//!
101//! At the moment, the crate provides only options using the [`Length`] bag, but in the future,
102//! we expect to add more ways to customize the output, like skeletons, and components.
103//!
104//! [data provider]: icu_provider
105//! [`ICU4X`]: ../icu/index.html
106//! [`Length`]: options::length
107//! [`DateTime`]: calendar::{DateTime}
108//! [`Date`]: calendar::{Date}
109//! [`Time`]: calendar::types::{Time}
110//! [`Calendar`]: calendar::{Calendar}
111//! [`AnyCalendar`]: calendar::any_calendar::{AnyCalendar}
112//! [`timezone::CustomTimeZone`]: icu::timezone::{CustomTimeZone}
113//! [`TimeZoneFormatter`]: time_zone::TimeZoneFormatter
114
115// https://github.com/unicode-org/icu4x/blob/main/documents/process/boilerplate.md#library-annotations
116#![cfg_attr(not(any(test, feature = "std")), no_std)]
117#![cfg_attr(
118    not(test),
119    deny(
120        clippy::indexing_slicing,
121        clippy::unwrap_used,
122        clippy::expect_used,
123        clippy::panic,
124        clippy::exhaustive_structs,
125        clippy::exhaustive_enums,
126        missing_debug_implementations,
127    )
128)]
129#![warn(missing_docs)]
130
131extern crate alloc;
132
133mod any;
134mod calendar;
135mod datetime;
136mod error;
137#[cfg(feature = "experimental")]
138mod external_loaders;
139pub mod fields;
140mod format;
141#[macro_use]
142pub(crate) mod helpers;
143pub mod input;
144#[cfg(feature = "experimental")]
145pub mod neo;
146#[cfg(feature = "experimental")]
147pub mod neo_marker;
148#[cfg(feature = "experimental")]
149pub mod neo_pattern;
150#[cfg(any(feature = "datagen", feature = "experimental"))]
151pub mod neo_skeleton;
152pub mod options;
153#[doc(hidden)]
154pub mod pattern;
155pub mod provider;
156pub(crate) mod raw;
157#[doc(hidden)]
158#[allow(clippy::exhaustive_structs, clippy::exhaustive_enums)] // private-ish module
159#[cfg(any(feature = "datagen", feature = "experimental"))]
160pub mod skeleton;
161pub mod time_zone;
162mod zoned_datetime;
163
164pub use any::{DateFormatter, DateTimeFormatter, ZonedDateTimeFormatter};
165pub use calendar::CldrCalendar;
166#[cfg(feature = "experimental")]
167pub use calendar::{InternalCldrCalendar, NeverCalendar};
168pub use datetime::{TimeFormatter, TypedDateFormatter, TypedDateTimeFormatter};
169pub use error::DateTimeError;
170pub use error::MismatchedCalendarError;
171#[cfg(feature = "experimental")]
172pub use format::datetime::DateTimeWriteError;
173pub use format::datetime::FormattedDateTime;
174#[cfg(feature = "experimental")]
175pub use format::neo::{FormattedDateTimePattern, LoadError, SingleLoadError, TypedDateTimeNames};
176pub use format::time_zone::FormattedTimeZone;
177pub use format::zoned_datetime::FormattedZonedDateTime;
178pub use options::DateTimeFormatterOptions;
179pub use zoned_datetime::TypedZonedDateTimeFormatter;
180
181#[doc(no_inline)]
182pub use DateTimeError as Error;