From f4b9ad83c0f20b174996ce0b35af4489fe6a88c5 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sat, 11 Jul 2020 13:46:12 +0200 Subject: [PATCH 01/60] Initial commit Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main From d150d932aa8d2ec206ec1f5d8963fd5505484681 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sat, 11 Jul 2020 14:51:55 +0200 Subject: [PATCH 02/60] Implement locales for format functions --- AUTHORS.txt | 1 + CHANGELOG.md | 2 + Cargo.toml | 4 +- src/format/locales.rs | 58 +++++++++++++++++++++ src/format/mod.rs | 114 +++++++++++++++++++++++++++++------------- src/lib.rs | 3 +- 6 files changed, 144 insertions(+), 38 deletions(-) create mode 100644 src/format/locales.rs diff --git a/AUTHORS.txt b/AUTHORS.txt index 9e738193f8..83395d0d6f 100644 --- a/AUTHORS.txt +++ b/AUTHORS.txt @@ -8,6 +8,7 @@ Ben Boeckel Ben Eills Brandon W Maister Brandon W Maister +Cecile Tonglet Colin Ray Corey Farwell Dan diff --git a/CHANGELOG.md b/CHANGELOG.md index 1159d0790a..3edf7caf6f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,8 @@ Versions with only mechanical changes will be omitted from the following list. ## 0.4.14 (unreleased) +* Added locales. All format functions can now use locales. + ## Improvements * Added MIN and MAX values for `NaiveTime`, `NaiveDateTime` and `DateTime`. diff --git a/Cargo.toml b/Cargo.toml index 1f6d2b83bf..85f6b15ff0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,11 +24,12 @@ appveyor = { repository = "chronotope/chrono" } name = "chrono" [features] -default = ["clock", "std"] +default = ["clock", "std", "locales"] alloc = [] std = [] clock = ["time", "std"] wasmbind = ["wasm-bindgen", "js-sys"] +locales = [] __internal_bench = [] __doctest = [] @@ -38,6 +39,7 @@ num-integer = { version = "0.1.36", default-features = false } num-traits = { version = "0.2", default-features = false } rustc-serialize = { version = "0.3.20", optional = true } serde = { version = "1.0.99", default-features = false, optional = true } +pure-rust-locales = "0.2.1" [target.'cfg(all(target_arch = "wasm32", not(any(target_os = "emscripten", target_os = "wasi"))))'.dependencies] wasm-bindgen = { version = "0.2", optional = true } diff --git a/src/format/locales.rs b/src/format/locales.rs new file mode 100644 index 0000000000..dfd96279d3 --- /dev/null +++ b/src/format/locales.rs @@ -0,0 +1,58 @@ +#[cfg(feature = "locales")] +mod with_locales { + use super::super::{FormatResult, FormatError, FormatErrorKind}; + + macro_rules! locale_match { + ($locale:expr => $($item:ident)::+) => {{ + match $locale { + "en_US" => Ok(pure_rust_locales::en_US::$($item)::+), + "fr_BE" => Ok(pure_rust_locales::fr_BE::$($item)::+), + // TODO: all the locales are available + _ => Err(FormatError(FormatErrorKind::UnknownLocale)), + } + }} + } + + pub(crate) fn short_months(locale: &str) -> FormatResult<&[&'static str]> { + locale_match!(locale => LC_TIME::ABMON) + } + + pub(crate) fn long_months(locale: &str) -> FormatResult<&[&'static str]> { + locale_match!(locale => LC_TIME::MON) + } + + pub(crate) fn short_weekdays(locale: &str) -> FormatResult<&[&'static str]> { + locale_match!(locale => LC_TIME::ABDAY) + } + + pub(crate) fn long_weekdays(locale: &str) -> FormatResult<&[&'static str]> { + locale_match!(locale => LC_TIME::DAY) + } +} + +#[cfg(not(feature = "locales"))] +mod without_locales { + use super::super::FormatResult; + + pub(crate) fn short_months(_locale: &str) -> FormatResult<&[&'static str]> { + Ok(pure_rust_locales::en_US::LC_TIME::ABMON) + } + + pub(crate) fn long_months(_locale: &str) -> FormatResult<&[&'static str]> { + Ok(pure_rust_locales::en_US::LC_TIME::MON) + } + + pub(crate) fn short_weekdays(_locale: &str) -> FormatResult<&[&'static str]> { + Ok(pure_rust_locales::en_US::LC_TIME::ABDAY) + } + + pub(crate) fn long_weekdays(_locale: &str) -> FormatResult<&[&'static str]> { + Ok(pure_rust_locales::en_US::LC_TIME::DAY) + } +} + +#[cfg(feature = "locales")] +pub(crate) use self::with_locales::*; + +#[cfg(not(feature = "locales"))] +pub(crate) use self::without_locales::*; diff --git a/src/format/mod.rs b/src/format/mod.rs index b634b094b0..719068f4a4 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -38,6 +38,8 @@ use offset::{FixedOffset, Offset}; use {Datelike, Timelike}; use {ParseWeekdayError, Weekday}; +mod locales; + pub use self::parse::parse; pub use self::parsed::Parsed; pub use self::strftime::StrftimeItems; @@ -378,6 +380,55 @@ const TOO_SHORT: ParseError = ParseError(ParseErrorKind::TooShort); const TOO_LONG: ParseError = ParseError(ParseErrorKind::TooLong); const BAD_FORMAT: ParseError = ParseError(ParseErrorKind::BadFormat); +/// An error from a "format" function. +#[derive(Debug, Clone, PartialEq, Eq, Copy)] +pub struct FormatError(FormatErrorKind); + +/// The category of format error. +#[derive(Debug, Clone, PartialEq, Eq, Copy)] +enum FormatErrorKind { + /// The locale is unknown or not available. + #[cfg(feature = "locales")] + UnknownLocale, + + /// Format error. + Format, + + /// Insufficient arguments for given format. + InsufficientArguments, + + /// Item error. + Item, +} + +/// Same as `Result`. +pub type FormatResult = Result; + +impl fmt::Display for FormatError { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + match self.0 { + FormatErrorKind::UnknownLocale => write!(f, "the locale is unknown or not available"), + FormatErrorKind::Format => write!(f, "{}", fmt::Error), + FormatErrorKind::InsufficientArguments => write!(f, "insufficient arguments for given format"), + FormatErrorKind::Item => write!(f, "item error"), + } + } +} + +#[cfg(any(feature = "std", test))] +impl Error for FormatError { + #[allow(deprecated)] + fn description(&self) -> &str { + "format error" + } +} + +impl From for FormatError { + fn from(_err: fmt::Error) -> Self { + FormatError(FormatErrorKind::Format) + } +} + /// Formats single formatting item #[cfg(any(feature = "alloc", feature = "std", test))] pub fn format_item<'a>( @@ -386,10 +437,12 @@ pub fn format_item<'a>( time: Option<&NaiveTime>, off: Option<&(String, FixedOffset)>, item: &Item<'a>, -) -> fmt::Result { + locale: &str, +) -> FormatResult<()> { let mut result = String::new(); - format_inner(&mut result, date, time, off, item)?; - w.pad(&result) + format_inner(&mut result, date, time, off, item, locale)?; + w.pad(&result)?; + Ok(()) } #[cfg(any(feature = "alloc", feature = "std", test))] @@ -399,27 +452,13 @@ fn format_inner<'a>( time: Option<&NaiveTime>, off: Option<&(String, FixedOffset)>, item: &Item<'a>, -) -> fmt::Result { + locale: &str, +) -> FormatResult<()> { // full and abbreviated month and weekday names - static SHORT_MONTHS: [&'static str; 12] = - ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; - static LONG_MONTHS: [&'static str; 12] = [ - "January", - "February", - "March", - "April", - "May", - "June", - "July", - "August", - "September", - "October", - "November", - "December", - ]; - static SHORT_WEEKDAYS: [&'static str; 7] = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]; - static LONG_WEEKDAYS: [&'static str; 7] = - ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]; + let short_months = locales::short_months(locale)?; + let long_months = locales::long_months(locale)?; + let short_weekdays = locales::short_weekdays(locale)?; + let long_weekdays = locales::long_weekdays(locale)?; use core::fmt::Write; @@ -489,7 +528,7 @@ fn format_inner<'a>( } }? } else { - return Err(fmt::Error); // insufficient arguments for given format + return Err(FormatError(FormatErrorKind::InsufficientArguments)); } } @@ -521,20 +560,20 @@ fn format_inner<'a>( let ret = match *spec { ShortMonthName => date.map(|d| { - result.push_str(SHORT_MONTHS[d.month0() as usize]); + result.push_str(short_months[d.month0() as usize]); Ok(()) }), LongMonthName => date.map(|d| { - result.push_str(LONG_MONTHS[d.month0() as usize]); + result.push_str(long_months[d.month0() as usize]); Ok(()) }), ShortWeekdayName => date.map(|d| { result - .push_str(SHORT_WEEKDAYS[d.weekday().num_days_from_monday() as usize]); + .push_str(short_weekdays[d.weekday().num_days_from_sunday() as usize]); Ok(()) }), LongWeekdayName => date.map(|d| { - result.push_str(LONG_WEEKDAYS[d.weekday().num_days_from_monday() as usize]); + result.push_str(long_weekdays[d.weekday().num_days_from_sunday() as usize]); Ok(()) }), LowerAmPm => time.map(|t| { @@ -611,9 +650,9 @@ fn format_inner<'a>( write!( result, "{}, {:02} {} {:04} {:02}:{:02}:{:02} ", - SHORT_WEEKDAYS[d.weekday().num_days_from_monday() as usize], + short_weekdays[d.weekday().num_days_from_sunday() as usize], d.day(), - SHORT_MONTHS[d.month0() as usize], + short_months[d.month0() as usize], d.year(), t.hour(), t.minute(), @@ -640,11 +679,11 @@ fn format_inner<'a>( match ret { Some(ret) => ret?, - None => return Err(fmt::Error), // insufficient arguments for given format + None => return Err(FormatError(FormatErrorKind::InsufficientArguments)), } } - Item::Error => return Err(fmt::Error), + Item::Error => return Err(FormatError(FormatErrorKind::Item)), } Ok(()) } @@ -658,16 +697,18 @@ pub fn format<'a, I, B>( time: Option<&NaiveTime>, off: Option<&(String, FixedOffset)>, items: I, -) -> fmt::Result + locale: &str, +) -> FormatResult<()> where I: Iterator + Clone, B: Borrow>, { let mut result = String::new(); for item in items { - format_inner(&mut result, date, time, off, item.borrow())?; + format_inner(&mut result, date, time, off, item.borrow(), locale)?; } - w.pad(&result) + w.pad(&result)?; + Ok(()) } mod parsed; @@ -718,7 +759,8 @@ impl<'a, I: Iterator + Clone, B: Borrow>> DelayedFormat { #[cfg(any(feature = "alloc", feature = "std", test))] impl<'a, I: Iterator + Clone, B: Borrow>> fmt::Display for DelayedFormat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - format(f, self.date.as_ref(), self.time.as_ref(), self.off.as_ref(), self.items.clone()) + format(f, self.date.as_ref(), self.time.as_ref(), self.off.as_ref(), self.items.clone(), "en_US") + .map_err(|_| fmt::Error) } } diff --git a/src/lib.rs b/src/lib.rs index 8bbcdb50e6..482dcce404 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -439,6 +439,7 @@ extern crate js_sys; extern crate test; #[cfg(all(target_arch = "wasm32", not(target_os = "wasi"), feature = "wasmbind"))] extern crate wasm_bindgen; +extern crate pure_rust_locales; #[cfg(feature = "__doctest")] #[cfg_attr(feature = "__doctest", cfg(doctest))] @@ -451,7 +452,7 @@ pub use date::{Date, MAX_DATE, MIN_DATE}; #[cfg(feature = "rustc-serialize")] pub use datetime::rustc_serialize::TsSeconds; pub use datetime::{DateTime, SecondsFormat, MAX_DATETIME, MIN_DATETIME}; -pub use format::{ParseError, ParseResult}; +pub use format::{ParseError, ParseResult, FormatError, FormatResult}; #[doc(no_inline)] pub use naive::{IsoWeek, NaiveDate, NaiveDateTime, NaiveTime}; #[cfg(feature = "clock")] From 330edb6ca72ba7af48b28bcebce5ae48d1319f7f Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 12 Jul 2020 12:20:23 +0200 Subject: [PATCH 03/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/locales.rs | 2 +- src/format/mod.rs | 15 ++++++++++++--- src/lib.rs | 4 ++-- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/src/format/locales.rs b/src/format/locales.rs index dfd96279d3..3420d2d2f8 100644 --- a/src/format/locales.rs +++ b/src/format/locales.rs @@ -1,6 +1,6 @@ #[cfg(feature = "locales")] mod with_locales { - use super::super::{FormatResult, FormatError, FormatErrorKind}; + use super::super::{FormatError, FormatErrorKind, FormatResult}; macro_rules! locale_match { ($locale:expr => $($item:ident)::+) => {{ diff --git a/src/format/mod.rs b/src/format/mod.rs index 719068f4a4..1d4c7cb57e 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -409,7 +409,9 @@ impl fmt::Display for FormatError { match self.0 { FormatErrorKind::UnknownLocale => write!(f, "the locale is unknown or not available"), FormatErrorKind::Format => write!(f, "{}", fmt::Error), - FormatErrorKind::InsufficientArguments => write!(f, "insufficient arguments for given format"), + FormatErrorKind::InsufficientArguments => { + write!(f, "insufficient arguments for given format") + } FormatErrorKind::Item => write!(f, "item error"), } } @@ -759,8 +761,15 @@ impl<'a, I: Iterator + Clone, B: Borrow>> DelayedFormat { #[cfg(any(feature = "alloc", feature = "std", test))] impl<'a, I: Iterator + Clone, B: Borrow>> fmt::Display for DelayedFormat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - format(f, self.date.as_ref(), self.time.as_ref(), self.off.as_ref(), self.items.clone(), "en_US") - .map_err(|_| fmt::Error) + format( + f, + self.date.as_ref(), + self.time.as_ref(), + self.off.as_ref(), + self.items.clone(), + "en_US", + ) + .map_err(|_| fmt::Error) } } diff --git a/src/lib.rs b/src/lib.rs index 482dcce404..b80529f155 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -435,11 +435,11 @@ extern crate serde as serdelib; extern crate doc_comment; #[cfg(all(target_arch = "wasm32", not(target_os = "wasi"), feature = "wasmbind"))] extern crate js_sys; +extern crate pure_rust_locales; #[cfg(feature = "bench")] extern crate test; #[cfg(all(target_arch = "wasm32", not(target_os = "wasi"), feature = "wasmbind"))] extern crate wasm_bindgen; -extern crate pure_rust_locales; #[cfg(feature = "__doctest")] #[cfg_attr(feature = "__doctest", cfg(doctest))] @@ -452,7 +452,7 @@ pub use date::{Date, MAX_DATE, MIN_DATE}; #[cfg(feature = "rustc-serialize")] pub use datetime::rustc_serialize::TsSeconds; pub use datetime::{DateTime, SecondsFormat, MAX_DATETIME, MIN_DATETIME}; -pub use format::{ParseError, ParseResult, FormatError, FormatResult}; +pub use format::{FormatError, FormatResult, ParseError, ParseResult}; #[doc(no_inline)] pub use naive::{IsoWeek, NaiveDate, NaiveDateTime, NaiveTime}; #[cfg(feature = "clock")] From b4296afaaf119ea8551a441a5183d6a6c7e57bbd Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 12 Jul 2020 12:32:09 +0200 Subject: [PATCH 04/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/mod.rs | 7 +++++++ src/lib.rs | 4 +++- 2 files changed, 10 insertions(+), 1 deletion(-) diff --git a/src/format/mod.rs b/src/format/mod.rs index 1d4c7cb57e..ad889c3844 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -38,6 +38,7 @@ use offset::{FixedOffset, Offset}; use {Datelike, Timelike}; use {ParseWeekdayError, Weekday}; +#[cfg(any(feature = "alloc", feature = "std", test))] mod locales; pub use self::parse::parse; @@ -382,9 +383,11 @@ const BAD_FORMAT: ParseError = ParseError(ParseErrorKind::BadFormat); /// An error from a "format" function. #[derive(Debug, Clone, PartialEq, Eq, Copy)] +#[cfg(any(feature = "alloc", feature = "std", test))] pub struct FormatError(FormatErrorKind); /// The category of format error. +#[cfg(any(feature = "alloc", feature = "std", test))] #[derive(Debug, Clone, PartialEq, Eq, Copy)] enum FormatErrorKind { /// The locale is unknown or not available. @@ -402,11 +405,14 @@ enum FormatErrorKind { } /// Same as `Result`. +#[cfg(any(feature = "alloc", feature = "std", test))] pub type FormatResult = Result; +#[cfg(any(feature = "alloc", feature = "std", test))] impl fmt::Display for FormatError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.0 { + #[cfg(feature = "locales")] FormatErrorKind::UnknownLocale => write!(f, "the locale is unknown or not available"), FormatErrorKind::Format => write!(f, "{}", fmt::Error), FormatErrorKind::InsufficientArguments => { @@ -425,6 +431,7 @@ impl Error for FormatError { } } +#[cfg(any(feature = "alloc", feature = "std", test))] impl From for FormatError { fn from(_err: fmt::Error) -> Self { FormatError(FormatErrorKind::Format) diff --git a/src/lib.rs b/src/lib.rs index b80529f155..1020770b00 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -452,7 +452,9 @@ pub use date::{Date, MAX_DATE, MIN_DATE}; #[cfg(feature = "rustc-serialize")] pub use datetime::rustc_serialize::TsSeconds; pub use datetime::{DateTime, SecondsFormat, MAX_DATETIME, MIN_DATETIME}; -pub use format::{FormatError, FormatResult, ParseError, ParseResult}; +#[cfg(any(feature = "alloc", feature = "std", test))] +pub use format::{FormatError, FormatResult}; +pub use format::{ParseError, ParseResult}; #[doc(no_inline)] pub use naive::{IsoWeek, NaiveDate, NaiveDateTime, NaiveTime}; #[cfg(feature = "clock")] From 19f54ab74704adf40382f25b69c4781276cc50c3 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 12 Jul 2020 18:08:52 +0200 Subject: [PATCH 05/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- Cargo.toml | 6 +++--- ci/github.sh | 2 +- src/format/locales.rs | 21 +++++++++++++++++---- src/lib.rs | 1 + 4 files changed, 22 insertions(+), 8 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 85f6b15ff0..9c9e09f669 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -24,12 +24,12 @@ appveyor = { repository = "chronotope/chrono" } name = "chrono" [features] -default = ["clock", "std", "locales"] +default = ["clock", "std"] alloc = [] std = [] clock = ["time", "std"] wasmbind = ["wasm-bindgen", "js-sys"] -locales = [] +locales = ["pure-rust-locales"] __internal_bench = [] __doctest = [] @@ -39,7 +39,7 @@ num-integer = { version = "0.1.36", default-features = false } num-traits = { version = "0.2", default-features = false } rustc-serialize = { version = "0.3.20", optional = true } serde = { version = "1.0.99", default-features = false, optional = true } -pure-rust-locales = "0.2.1" +pure-rust-locales = { version = "0.2.1", optional = true } [target.'cfg(all(target_arch = "wasm32", not(any(target_os = "emscripten", target_os = "wasi"))))'.dependencies] wasm-bindgen = { version = "0.2", optional = true } diff --git a/ci/github.sh b/ci/github.sh index 3c1c873850..681ea03cbf 100755 --- a/ci/github.sh +++ b/ci/github.sh @@ -6,7 +6,7 @@ set -euo pipefail source "${BASH_SOURCE[0]%/*}/_shlib.sh" TEST_TZS=(ACST-9:30 EST4 UTC0 Asia/Katmandu) -FEATURES=(std serde clock "alloc serde") +FEATURES=(std serde clock "alloc serde" locales) RUST_113_FEATURES=(rustc-serialize serde) main() { diff --git a/src/format/locales.rs b/src/format/locales.rs index 3420d2d2f8..9935e82490 100644 --- a/src/format/locales.rs +++ b/src/format/locales.rs @@ -35,19 +35,32 @@ mod without_locales { use super::super::FormatResult; pub(crate) fn short_months(_locale: &str) -> FormatResult<&[&'static str]> { - Ok(pure_rust_locales::en_US::LC_TIME::ABMON) + Ok(&["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]) } pub(crate) fn long_months(_locale: &str) -> FormatResult<&[&'static str]> { - Ok(pure_rust_locales::en_US::LC_TIME::MON) + Ok(&[ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", + ]) } pub(crate) fn short_weekdays(_locale: &str) -> FormatResult<&[&'static str]> { - Ok(pure_rust_locales::en_US::LC_TIME::ABDAY) + Ok(&["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]) } pub(crate) fn long_weekdays(_locale: &str) -> FormatResult<&[&'static str]> { - Ok(pure_rust_locales::en_US::LC_TIME::DAY) + Ok(&["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]) } } diff --git a/src/lib.rs b/src/lib.rs index d013b7ac82..3b6d0abd29 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -435,6 +435,7 @@ extern crate serde as serdelib; extern crate doc_comment; #[cfg(all(target_arch = "wasm32", not(target_os = "wasi"), feature = "wasmbind"))] extern crate js_sys; +#[cfg(feature = "locales")] extern crate pure_rust_locales; #[cfg(feature = "bench")] extern crate test; From 870a7cc8026c898830d7ffbf6c4ada37bfab3459 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 12 Jul 2020 18:22:18 +0200 Subject: [PATCH 06/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/locales.rs | 87 +++++++++++-------------------------------- src/format/mod.rs | 29 ++++++++++++++- 2 files changed, 50 insertions(+), 66 deletions(-) diff --git a/src/format/locales.rs b/src/format/locales.rs index 9935e82490..94fe7a3b37 100644 --- a/src/format/locales.rs +++ b/src/format/locales.rs @@ -1,71 +1,28 @@ -#[cfg(feature = "locales")] -mod with_locales { - use super::super::{FormatError, FormatErrorKind, FormatResult}; - - macro_rules! locale_match { - ($locale:expr => $($item:ident)::+) => {{ - match $locale { - "en_US" => Ok(pure_rust_locales::en_US::$($item)::+), - "fr_BE" => Ok(pure_rust_locales::fr_BE::$($item)::+), - // TODO: all the locales are available - _ => Err(FormatError(FormatErrorKind::UnknownLocale)), - } - }} - } - - pub(crate) fn short_months(locale: &str) -> FormatResult<&[&'static str]> { - locale_match!(locale => LC_TIME::ABMON) - } - - pub(crate) fn long_months(locale: &str) -> FormatResult<&[&'static str]> { - locale_match!(locale => LC_TIME::MON) - } - - pub(crate) fn short_weekdays(locale: &str) -> FormatResult<&[&'static str]> { - locale_match!(locale => LC_TIME::ABDAY) - } - - pub(crate) fn long_weekdays(locale: &str) -> FormatResult<&[&'static str]> { - locale_match!(locale => LC_TIME::DAY) - } +use super::{FormatError, FormatErrorKind, FormatResult}; + +macro_rules! locale_match { + ($locale:expr => $($item:ident)::+) => {{ + match $locale { + "en_US" => Ok(pure_rust_locales::en_US::$($item)::+), + "fr_BE" => Ok(pure_rust_locales::fr_BE::$($item)::+), + // TODO: all the locales are available + _ => Err(FormatError(FormatErrorKind::UnknownLocale)), + } + }} } -#[cfg(not(feature = "locales"))] -mod without_locales { - use super::super::FormatResult; - - pub(crate) fn short_months(_locale: &str) -> FormatResult<&[&'static str]> { - Ok(&["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]) - } - - pub(crate) fn long_months(_locale: &str) -> FormatResult<&[&'static str]> { - Ok(&[ - "January", - "February", - "March", - "April", - "May", - "June", - "July", - "August", - "September", - "October", - "November", - "December", - ]) - } - - pub(crate) fn short_weekdays(_locale: &str) -> FormatResult<&[&'static str]> { - Ok(&["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]) - } +pub(crate) fn short_months(locale: &str) -> FormatResult<&[&'static str]> { + locale_match!(locale => LC_TIME::ABMON) +} - pub(crate) fn long_weekdays(_locale: &str) -> FormatResult<&[&'static str]> { - Ok(&["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]) - } +pub(crate) fn long_months(locale: &str) -> FormatResult<&[&'static str]> { + locale_match!(locale => LC_TIME::MON) } -#[cfg(feature = "locales")] -pub(crate) use self::with_locales::*; +pub(crate) fn short_weekdays(locale: &str) -> FormatResult<&[&'static str]> { + locale_match!(locale => LC_TIME::ABDAY) +} -#[cfg(not(feature = "locales"))] -pub(crate) use self::without_locales::*; +pub(crate) fn long_weekdays(locale: &str) -> FormatResult<&[&'static str]> { + locale_match!(locale => LC_TIME::DAY) +} diff --git a/src/format/mod.rs b/src/format/mod.rs index ad889c3844..9a786f64c6 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -38,7 +38,7 @@ use offset::{FixedOffset, Offset}; use {Datelike, Timelike}; use {ParseWeekdayError, Weekday}; -#[cfg(any(feature = "alloc", feature = "std", test))] +#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] mod locales; pub use self::parse::parse; @@ -464,10 +464,37 @@ fn format_inner<'a>( locale: &str, ) -> FormatResult<()> { // full and abbreviated month and weekday names + #[cfg(feature = "locales")] let short_months = locales::short_months(locale)?; + #[cfg(feature = "locales")] let long_months = locales::long_months(locale)?; + #[cfg(feature = "locales")] let short_weekdays = locales::short_weekdays(locale)?; + #[cfg(feature = "locales")] let long_weekdays = locales::long_weekdays(locale)?; + #[cfg(not(feature = "locales"))] + let short_months = + &["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; + #[cfg(not(feature = "locales"))] + let long_months = &[ + "January", + "February", + "March", + "April", + "May", + "June", + "July", + "August", + "September", + "October", + "November", + "December", + ]; + #[cfg(not(feature = "locales"))] + let short_weekdays = &["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; + #[cfg(not(feature = "locales"))] + let long_weekdays = + &["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; use core::fmt::Write; From f27f6ce0ca0e990c8305b432b196bee8376193c6 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 12 Jul 2020 18:32:26 +0200 Subject: [PATCH 07/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/mod.rs | 336 ++++++++++++++++++++++++++++++++++++++++------ 1 file changed, 298 insertions(+), 38 deletions(-) diff --git a/src/format/mod.rs b/src/format/mod.rs index 9a786f64c6..cedbdd25e9 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -446,10 +446,9 @@ pub fn format_item<'a>( time: Option<&NaiveTime>, off: Option<&(String, FixedOffset)>, item: &Item<'a>, - locale: &str, ) -> FormatResult<()> { let mut result = String::new(); - format_inner(&mut result, date, time, off, item, locale)?; + format_inner(&mut result, date, time, off, item)?; w.pad(&result)?; Ok(()) } @@ -461,22 +460,11 @@ fn format_inner<'a>( time: Option<&NaiveTime>, off: Option<&(String, FixedOffset)>, item: &Item<'a>, - locale: &str, ) -> FormatResult<()> { // full and abbreviated month and weekday names - #[cfg(feature = "locales")] - let short_months = locales::short_months(locale)?; - #[cfg(feature = "locales")] - let long_months = locales::long_months(locale)?; - #[cfg(feature = "locales")] - let short_weekdays = locales::short_weekdays(locale)?; - #[cfg(feature = "locales")] - let long_weekdays = locales::long_weekdays(locale)?; - #[cfg(not(feature = "locales"))] - let short_months = - &["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; - #[cfg(not(feature = "locales"))] - let long_months = &[ + static SHORT_MONTHS: [&'static str; 12] = + ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; + static LONG_MONTHS: [&'static str; 12] = [ "January", "February", "March", @@ -490,11 +478,9 @@ fn format_inner<'a>( "November", "December", ]; - #[cfg(not(feature = "locales"))] - let short_weekdays = &["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; - #[cfg(not(feature = "locales"))] - let long_weekdays = - &["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; + static SHORT_WEEKDAYS: [&'static str; 7] = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]; + static LONG_WEEKDAYS: [&'static str; 7] = + ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]; use core::fmt::Write; @@ -596,20 +582,20 @@ fn format_inner<'a>( let ret = match *spec { ShortMonthName => date.map(|d| { - result.push_str(short_months[d.month0() as usize]); + result.push_str(SHORT_MONTHS[d.month0() as usize]); Ok(()) }), LongMonthName => date.map(|d| { - result.push_str(long_months[d.month0() as usize]); + result.push_str(LONG_MONTHS[d.month0() as usize]); Ok(()) }), ShortWeekdayName => date.map(|d| { result - .push_str(short_weekdays[d.weekday().num_days_from_sunday() as usize]); + .push_str(SHORT_WEEKDAYS[d.weekday().num_days_from_monday() as usize]); Ok(()) }), LongWeekdayName => date.map(|d| { - result.push_str(long_weekdays[d.weekday().num_days_from_sunday() as usize]); + result.push_str(LONG_WEEKDAYS[d.weekday().num_days_from_monday() as usize]); Ok(()) }), LowerAmPm => time.map(|t| { @@ -686,9 +672,9 @@ fn format_inner<'a>( write!( result, "{}, {:02} {} {:04} {:02}:{:02}:{:02} ", - short_weekdays[d.weekday().num_days_from_sunday() as usize], + SHORT_WEEKDAYS[d.weekday().num_days_from_monday() as usize], d.day(), - short_months[d.month0() as usize], + SHORT_MONTHS[d.month0() as usize], d.year(), t.hour(), t.minute(), @@ -733,7 +719,6 @@ pub fn format<'a, I, B>( time: Option<&NaiveTime>, off: Option<&(String, FixedOffset)>, items: I, - locale: &str, ) -> FormatResult<()> where I: Iterator + Clone, @@ -741,7 +726,7 @@ where { let mut result = String::new(); for item in items { - format_inner(&mut result, date, time, off, item.borrow(), locale)?; + format_inner(&mut result, date, time, off, item.borrow())?; } w.pad(&result)?; Ok(()) @@ -795,15 +780,8 @@ impl<'a, I: Iterator + Clone, B: Borrow>> DelayedFormat { #[cfg(any(feature = "alloc", feature = "std", test))] impl<'a, I: Iterator + Clone, B: Borrow>> fmt::Display for DelayedFormat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - format( - f, - self.date.as_ref(), - self.time.as_ref(), - self.off.as_ref(), - self.items.clone(), - "en_US", - ) - .map_err(|_| fmt::Error) + format(f, self.date.as_ref(), self.time.as_ref(), self.off.as_ref(), self.items.clone()) + .map_err(|_| fmt::Error) } } @@ -844,3 +822,285 @@ impl FromStr for Weekday { } } } + +/// Formats single formatting item +#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] +pub fn format_item_localized<'a>( + w: &mut fmt::Formatter, + date: Option<&NaiveDate>, + time: Option<&NaiveTime>, + off: Option<&(String, FixedOffset)>, + item: &Item<'a>, + locale: &str, +) -> FormatResult<()> { + let mut result = String::new(); + format_inner_localized(&mut result, date, time, off, item, locale)?; + w.pad(&result)?; + Ok(()) +} + +#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] +fn format_inner_localized<'a>( + result: &mut String, + date: Option<&NaiveDate>, + time: Option<&NaiveTime>, + off: Option<&(String, FixedOffset)>, + item: &Item<'a>, + locale: &str, +) -> FormatResult<()> { + // full and abbreviated month and weekday names + let short_months = locales::short_months(locale)?; + let long_months = locales::long_months(locale)?; + let short_weekdays = locales::short_weekdays(locale)?; + let long_weekdays = locales::long_weekdays(locale)?; + + use core::fmt::Write; + + match *item { + Item::Literal(s) | Item::Space(s) => result.push_str(s), + #[cfg(any(feature = "alloc", feature = "std", test))] + Item::OwnedLiteral(ref s) | Item::OwnedSpace(ref s) => result.push_str(s), + + Item::Numeric(ref spec, ref pad) => { + use self::Numeric::*; + + let week_from_sun = |d: &NaiveDate| { + (d.ordinal() as i32 - d.weekday().num_days_from_sunday() as i32 + 7) / 7 + }; + let week_from_mon = |d: &NaiveDate| { + (d.ordinal() as i32 - d.weekday().num_days_from_monday() as i32 + 7) / 7 + }; + + let (width, v) = match *spec { + Year => (4, date.map(|d| i64::from(d.year()))), + YearDiv100 => (2, date.map(|d| div_floor(i64::from(d.year()), 100))), + YearMod100 => (2, date.map(|d| mod_floor(i64::from(d.year()), 100))), + IsoYear => (4, date.map(|d| i64::from(d.iso_week().year()))), + IsoYearDiv100 => (2, date.map(|d| div_floor(i64::from(d.iso_week().year()), 100))), + IsoYearMod100 => (2, date.map(|d| mod_floor(i64::from(d.iso_week().year()), 100))), + Month => (2, date.map(|d| i64::from(d.month()))), + Day => (2, date.map(|d| i64::from(d.day()))), + WeekFromSun => (2, date.map(|d| i64::from(week_from_sun(d)))), + WeekFromMon => (2, date.map(|d| i64::from(week_from_mon(d)))), + IsoWeek => (2, date.map(|d| i64::from(d.iso_week().week()))), + NumDaysFromSun => (1, date.map(|d| i64::from(d.weekday().num_days_from_sunday()))), + WeekdayFromMon => (1, date.map(|d| i64::from(d.weekday().number_from_monday()))), + Ordinal => (3, date.map(|d| i64::from(d.ordinal()))), + Hour => (2, time.map(|t| i64::from(t.hour()))), + Hour12 => (2, time.map(|t| i64::from(t.hour12().1))), + Minute => (2, time.map(|t| i64::from(t.minute()))), + Second => (2, time.map(|t| i64::from(t.second() + t.nanosecond() / 1_000_000_000))), + Nanosecond => (9, time.map(|t| i64::from(t.nanosecond() % 1_000_000_000))), + Timestamp => ( + 1, + match (date, time, off) { + (Some(d), Some(t), None) => Some(d.and_time(*t).timestamp()), + (Some(d), Some(t), Some(&(_, off))) => { + Some((d.and_time(*t) - off).timestamp()) + } + (_, _, _) => None, + }, + ), + + // for the future expansion + Internal(ref int) => match int._dummy {}, + }; + + if let Some(v) = v { + if (spec == &Year || spec == &IsoYear) && !(0 <= v && v < 10_000) { + // non-four-digit years require an explicit sign as per ISO 8601 + match *pad { + Pad::None => write!(result, "{:+}", v), + Pad::Zero => write!(result, "{:+01$}", v, width + 1), + Pad::Space => write!(result, "{:+1$}", v, width + 1), + } + } else { + match *pad { + Pad::None => write!(result, "{}", v), + Pad::Zero => write!(result, "{:01$}", v, width), + Pad::Space => write!(result, "{:1$}", v, width), + } + }? + } else { + return Err(FormatError(FormatErrorKind::InsufficientArguments)); + } + } + + Item::Fixed(ref spec) => { + use self::Fixed::*; + + /// Prints an offset from UTC in the format of `+HHMM` or `+HH:MM`. + /// `Z` instead of `+00[:]00` is allowed when `allow_zulu` is true. + fn write_local_minus_utc( + result: &mut String, + off: FixedOffset, + allow_zulu: bool, + use_colon: bool, + ) -> fmt::Result { + let off = off.local_minus_utc(); + if !allow_zulu || off != 0 { + let (sign, off) = if off < 0 { ('-', -off) } else { ('+', off) }; + if use_colon { + write!(result, "{}{:02}:{:02}", sign, off / 3600, off / 60 % 60) + } else { + write!(result, "{}{:02}{:02}", sign, off / 3600, off / 60 % 60) + } + } else { + result.push_str("Z"); + Ok(()) + } + } + + let ret = + match *spec { + ShortMonthName => date.map(|d| { + result.push_str(short_months[d.month0() as usize]); + Ok(()) + }), + LongMonthName => date.map(|d| { + result.push_str(long_months[d.month0() as usize]); + Ok(()) + }), + ShortWeekdayName => date.map(|d| { + result + .push_str(short_weekdays[d.weekday().num_days_from_sunday() as usize]); + Ok(()) + }), + LongWeekdayName => date.map(|d| { + result.push_str(long_weekdays[d.weekday().num_days_from_sunday() as usize]); + Ok(()) + }), + LowerAmPm => time.map(|t| { + result.push_str(if t.hour12().0 { "pm" } else { "am" }); + Ok(()) + }), + UpperAmPm => time.map(|t| { + result.push_str(if t.hour12().0 { "PM" } else { "AM" }); + Ok(()) + }), + Nanosecond => time.map(|t| { + let nano = t.nanosecond() % 1_000_000_000; + if nano == 0 { + Ok(()) + } else if nano % 1_000_000 == 0 { + write!(result, ".{:03}", nano / 1_000_000) + } else if nano % 1_000 == 0 { + write!(result, ".{:06}", nano / 1_000) + } else { + write!(result, ".{:09}", nano) + } + }), + Nanosecond3 => time.map(|t| { + let nano = t.nanosecond() % 1_000_000_000; + write!(result, ".{:03}", nano / 1_000_000) + }), + Nanosecond6 => time.map(|t| { + let nano = t.nanosecond() % 1_000_000_000; + write!(result, ".{:06}", nano / 1_000) + }), + Nanosecond9 => time.map(|t| { + let nano = t.nanosecond() % 1_000_000_000; + write!(result, ".{:09}", nano) + }), + Internal(InternalFixed { val: InternalInternal::Nanosecond3NoDot }) => time + .map(|t| { + let nano = t.nanosecond() % 1_000_000_000; + write!(result, "{:03}", nano / 1_000_000) + }), + Internal(InternalFixed { val: InternalInternal::Nanosecond6NoDot }) => time + .map(|t| { + let nano = t.nanosecond() % 1_000_000_000; + write!(result, "{:06}", nano / 1_000) + }), + Internal(InternalFixed { val: InternalInternal::Nanosecond9NoDot }) => time + .map(|t| { + let nano = t.nanosecond() % 1_000_000_000; + write!(result, "{:09}", nano) + }), + TimezoneName => off.map(|&(ref name, _)| { + result.push_str(name); + Ok(()) + }), + TimezoneOffsetColon => { + off.map(|&(_, off)| write_local_minus_utc(result, off, false, true)) + } + TimezoneOffsetColonZ => { + off.map(|&(_, off)| write_local_minus_utc(result, off, true, true)) + } + TimezoneOffset => { + off.map(|&(_, off)| write_local_minus_utc(result, off, false, false)) + } + TimezoneOffsetZ => { + off.map(|&(_, off)| write_local_minus_utc(result, off, true, false)) + } + Internal(InternalFixed { val: InternalInternal::TimezoneOffsetPermissive }) => { + panic!("Do not try to write %#z it is undefined") + } + RFC2822 => + // same as `%a, %d %b %Y %H:%M:%S %z` + { + if let (Some(d), Some(t), Some(&(_, off))) = (date, time, off) { + let sec = t.second() + t.nanosecond() / 1_000_000_000; + write!( + result, + "{}, {:02} {} {:04} {:02}:{:02}:{:02} ", + short_weekdays[d.weekday().num_days_from_sunday() as usize], + d.day(), + short_months[d.month0() as usize], + d.year(), + t.hour(), + t.minute(), + sec + )?; + Some(write_local_minus_utc(result, off, false, false)) + } else { + None + } + } + RFC3339 => + // same as `%Y-%m-%dT%H:%M:%S%.f%:z` + { + if let (Some(d), Some(t), Some(&(_, off))) = (date, time, off) { + // reuse `Debug` impls which already print ISO 8601 format. + // this is faster in this way. + write!(result, "{:?}T{:?}", d, t)?; + Some(write_local_minus_utc(result, off, false, true)) + } else { + None + } + } + }; + + match ret { + Some(ret) => ret?, + None => return Err(FormatError(FormatErrorKind::InsufficientArguments)), + } + } + + Item::Error => return Err(FormatError(FormatErrorKind::Item)), + } + Ok(()) +} + +/// Tries to format given arguments with given formatting items. +/// Internally used by `DelayedFormat`. +#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] +pub fn format_localized<'a, I, B>( + w: &mut fmt::Formatter, + date: Option<&NaiveDate>, + time: Option<&NaiveTime>, + off: Option<&(String, FixedOffset)>, + items: I, + locale: &str, +) -> FormatResult<()> +where + I: Iterator + Clone, + B: Borrow>, +{ + let mut result = String::new(); + for item in items { + format_inner_localized(&mut result, date, time, off, item.borrow(), locale)?; + } + w.pad(&result)?; + Ok(()) +} From 44e4fb186671c38041a64e497f1bd12bba5e69d5 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 12 Jul 2020 19:01:01 +0200 Subject: [PATCH 08/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/date.rs | 22 ++++++++++++ src/datetime.rs | 28 +++++++++++++++ src/format/mod.rs | 51 ++++++++++++++++++++++++++ src/format/strftime.rs | 82 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 183 insertions(+) diff --git a/src/date.rs b/src/date.rs index 4c573fd9b4..66a9b0973b 100644 --- a/src/date.rs +++ b/src/date.rs @@ -10,6 +10,8 @@ use core::ops::{Add, Sub}; use core::{fmt, hash}; use oldtime::Duration as OldDuration; +#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] +use format::DelayedFormatLocalized; #[cfg(any(feature = "alloc", feature = "std", test))] use format::{DelayedFormat, Item, StrftimeItems}; use naive::{self, IsoWeek, NaiveDate, NaiveTime}; @@ -295,6 +297,26 @@ where pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat> { self.format_with_items(StrftimeItems::new(fmt)) } + + /// Formats the date with the specified formatting items. + #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + #[inline] + pub fn format_localized_with_items<'a, I, B>(&self, items: I) -> DelayedFormatLocalized + where + I: Iterator + Clone, + B: Borrow>, + { + DelayedFormatLocalized::new_with_offset(Some(self.naive_local()), None, &self.offset, items) + } + + /// Formats the date with the specified format string. + /// See the [`format::strftime` module](./format/strftime/index.html) + /// on the supported escape sequences. + #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + #[inline] + pub fn format_localized<'a>(&self, fmt: &'a str) -> DelayedFormatLocalized> { + self.format_localized_with_items(StrftimeItems::new(fmt)) + } } impl Datelike for Date { diff --git a/src/datetime.rs b/src/datetime.rs index c7e6061c47..a6c8c8c16e 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -19,6 +19,8 @@ use std::string::ToString; use core::borrow::Borrow; #[cfg(any(feature = "alloc", feature = "std", test))] use format::DelayedFormat; +#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] +use format::DelayedFormatLocalized; use format::{parse, ParseError, ParseResult, Parsed, StrftimeItems}; use format::{Fixed, Item}; use naive::{self, IsoWeek, NaiveDateTime, NaiveTime}; @@ -493,6 +495,32 @@ where pub fn format<'a>(&self, fmt: &'a str) -> DelayedFormat> { self.format_with_items(StrftimeItems::new(fmt)) } + + /// Formats the combined date and time with the specified formatting items. + #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + #[inline] + pub fn format_localized_with_items<'a, I, B>(&self, items: I) -> DelayedFormatLocalized + where + I: Iterator + Clone, + B: Borrow>, + { + let local = self.naive_local(); + DelayedFormatLocalized::new_with_offset( + Some(local.date()), + Some(local.time()), + &self.offset, + items, + ) + } + + /// Formats the combined date and time with the specified format string. + /// See the [`format::strftime` module](./format/strftime/index.html) + /// on the supported escape sequences. + #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + #[inline] + pub fn format_localized<'a>(&self, fmt: &'a str) -> DelayedFormatLocalized> { + self.format_localized_with_items(StrftimeItems::new(fmt)) + } } impl Datelike for DateTime { diff --git a/src/format/mod.rs b/src/format/mod.rs index cedbdd25e9..1f75ae7fe1 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -785,6 +785,57 @@ impl<'a, I: Iterator + Clone, B: Borrow>> fmt::Display for De } } +/// A *temporary* object which can be used as an argument to `format!` or others. +/// This is normally constructed via `format` methods of each date and time type. +#[cfg(any(feature = "alloc", feature = "std", test))] +#[derive(Debug)] +pub struct DelayedFormatLocalized { + /// The date view, if any. + date: Option, + /// The time view, if any. + time: Option, + /// The name and local-to-UTC difference for the offset (timezone), if any. + off: Option<(String, FixedOffset)>, + /// An iterator returning formatting items. + items: I, +} + +#[cfg(any(feature = "alloc", feature = "std", test))] +impl<'a, I: Iterator + Clone, B: Borrow>> DelayedFormatLocalized { + /// Makes a new `DelayedFormat` value out of local date and time. + pub fn new( + date: Option, + time: Option, + items: I, + ) -> DelayedFormatLocalized { + DelayedFormatLocalized { date: date, time: time, off: None, items: items } + } + + /// Makes a new `DelayedFormat` value out of local date and time and UTC offset. + pub fn new_with_offset( + date: Option, + time: Option, + offset: &Off, + items: I, + ) -> DelayedFormatLocalized + where + Off: Offset + fmt::Display, + { + let name_and_diff = (offset.to_string(), offset.fix()); + DelayedFormatLocalized { date: date, time: time, off: Some(name_and_diff), items: items } + } +} + +#[cfg(any(feature = "alloc", feature = "std", test))] +impl<'a, I: Iterator + Clone, B: Borrow>> fmt::Display + for DelayedFormatLocalized +{ + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + format(f, self.date.as_ref(), self.time.as_ref(), self.off.as_ref(), self.items.clone()) + .map_err(|_| fmt::Error) + } +} + // this implementation is here only because we need some private code from `scan` /// Parsing a `str` into a `Weekday` uses the format [`%W`](./format/strftime/index.html). diff --git a/src/format/strftime.rs b/src/format/strftime.rs index e4918204a7..5b01f2868d 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -518,3 +518,85 @@ fn test_strftime_docs() { assert_eq!(dt.format("%n").to_string(), "\n"); assert_eq!(dt.format("%%").to_string(), "%"); } + +#[cfg(test)] +#[cfg(feature = "locales")] // TODO: remove +#[test] +fn test_strftime_docs_localized() { + use {FixedOffset, TimeZone, Timelike}; + + let dt = FixedOffset::east(34200).ymd(2001, 7, 8).and_hms_nano(0, 34, 59, 1_026_490_708); + + // date specifiers + assert_eq!(dt.format_localized("%Y").to_string(), "2001"); + assert_eq!(dt.format_localized("%C").to_string(), "20"); + assert_eq!(dt.format_localized("%y").to_string(), "01"); + assert_eq!(dt.format_localized("%m").to_string(), "07"); + assert_eq!(dt.format_localized("%b").to_string(), "Jul"); + assert_eq!(dt.format_localized("%B").to_string(), "July"); + assert_eq!(dt.format_localized("%h").to_string(), "Jul"); + assert_eq!(dt.format_localized("%d").to_string(), "08"); + assert_eq!(dt.format_localized("%e").to_string(), " 8"); + assert_eq!(dt.format_localized("%e").to_string(), dt.format_localized("%_d").to_string()); + assert_eq!(dt.format_localized("%a").to_string(), "Sun"); + assert_eq!(dt.format_localized("%A").to_string(), "Sunday"); + assert_eq!(dt.format_localized("%w").to_string(), "0"); + assert_eq!(dt.format_localized("%u").to_string(), "7"); + assert_eq!(dt.format_localized("%U").to_string(), "28"); + assert_eq!(dt.format_localized("%W").to_string(), "27"); + assert_eq!(dt.format_localized("%G").to_string(), "2001"); + assert_eq!(dt.format_localized("%g").to_string(), "01"); + assert_eq!(dt.format_localized("%V").to_string(), "27"); + assert_eq!(dt.format_localized("%j").to_string(), "189"); + assert_eq!(dt.format_localized("%D").to_string(), "07/08/01"); + assert_eq!(dt.format_localized("%x").to_string(), "07/08/01"); + assert_eq!(dt.format_localized("%F").to_string(), "2001-07-08"); + assert_eq!(dt.format_localized("%v").to_string(), " 8-Jul-2001"); + + // time specifiers + assert_eq!(dt.format_localized("%H").to_string(), "00"); + assert_eq!(dt.format_localized("%k").to_string(), " 0"); + assert_eq!(dt.format_localized("%k").to_string(), dt.format_localized("%_H").to_string()); + assert_eq!(dt.format_localized("%I").to_string(), "12"); + assert_eq!(dt.format_localized("%l").to_string(), "12"); + assert_eq!(dt.format_localized("%l").to_string(), dt.format_localized("%_I").to_string()); + assert_eq!(dt.format_localized("%P").to_string(), "am"); + assert_eq!(dt.format_localized("%p").to_string(), "AM"); + assert_eq!(dt.format_localized("%M").to_string(), "34"); + assert_eq!(dt.format_localized("%S").to_string(), "60"); + assert_eq!(dt.format_localized("%f").to_string(), "026490708"); + assert_eq!(dt.format_localized("%.f").to_string(), ".026490708"); + assert_eq!( + dt.with_nanosecond(1_026_490_000).unwrap().format_localized("%.f").to_string(), + ".026490" + ); + assert_eq!(dt.format_localized("%.3f").to_string(), ".026"); + assert_eq!(dt.format_localized("%.6f").to_string(), ".026490"); + assert_eq!(dt.format_localized("%.9f").to_string(), ".026490708"); + assert_eq!(dt.format_localized("%3f").to_string(), "026"); + assert_eq!(dt.format_localized("%6f").to_string(), "026490"); + assert_eq!(dt.format_localized("%9f").to_string(), "026490708"); + assert_eq!(dt.format_localized("%R").to_string(), "00:34"); + assert_eq!(dt.format_localized("%T").to_string(), "00:34:60"); + assert_eq!(dt.format_localized("%X").to_string(), "00:34:60"); + assert_eq!(dt.format_localized("%r").to_string(), "12:34:60 AM"); + + // time zone specifiers + //assert_eq!(dt.format_localized("%Z").to_string(), "ACST"); + assert_eq!(dt.format_localized("%z").to_string(), "+0930"); + assert_eq!(dt.format_localized("%:z").to_string(), "+09:30"); + + // date & time specifiers + assert_eq!(dt.format_localized("%c").to_string(), "Sun Jul 8 00:34:60 2001"); + assert_eq!(dt.format_localized("%+").to_string(), "2001-07-08T00:34:60.026490708+09:30"); + assert_eq!( + dt.with_nanosecond(1_026_490_000).unwrap().format_localized("%+").to_string(), + "2001-07-08T00:34:60.026490+09:30" + ); + assert_eq!(dt.format_localized("%s").to_string(), "994518299"); + + // special specifiers + assert_eq!(dt.format_localized("%t").to_string(), "\t"); + assert_eq!(dt.format_localized("%n").to_string(), "\n"); + assert_eq!(dt.format_localized("%%").to_string(), "%"); +} From 083575acbb1c38aed5b2494ddeea8e8976384501 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 12 Jul 2020 19:08:24 +0200 Subject: [PATCH 09/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/mod.rs | 284 +++++----------------------------------------- 1 file changed, 27 insertions(+), 257 deletions(-) diff --git a/src/format/mod.rs b/src/format/mod.rs index 1f75ae7fe1..2c57528949 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -448,7 +448,7 @@ pub fn format_item<'a>( item: &Item<'a>, ) -> FormatResult<()> { let mut result = String::new(); - format_inner(&mut result, date, time, off, item)?; + format_inner(&mut result, date, time, off, item, "POSIX")?; w.pad(&result)?; Ok(()) } @@ -460,11 +460,22 @@ fn format_inner<'a>( time: Option<&NaiveTime>, off: Option<&(String, FixedOffset)>, item: &Item<'a>, + #[allow(unused_variables)] locale: &str, ) -> FormatResult<()> { // full and abbreviated month and weekday names - static SHORT_MONTHS: [&'static str; 12] = - ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; - static LONG_MONTHS: [&'static str; 12] = [ + #[cfg(feature = "locales")] + let short_months = locales::short_months(locale)?; + #[cfg(feature = "locales")] + let long_months = locales::long_months(locale)?; + #[cfg(feature = "locales")] + let short_weekdays = locales::short_weekdays(locale)?; + #[cfg(feature = "locales")] + let long_weekdays = locales::long_weekdays(locale)?; + #[cfg(not(feature = "locales"))] + let short_months = + &["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; + #[cfg(not(feature = "locales"))] + let long_months = &[ "January", "February", "March", @@ -478,9 +489,11 @@ fn format_inner<'a>( "November", "December", ]; - static SHORT_WEEKDAYS: [&'static str; 7] = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]; - static LONG_WEEKDAYS: [&'static str; 7] = - ["Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"]; + #[cfg(not(feature = "locales"))] + let short_weekdays = &["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; + #[cfg(not(feature = "locales"))] + let long_weekdays = + &["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; use core::fmt::Write; @@ -582,20 +595,20 @@ fn format_inner<'a>( let ret = match *spec { ShortMonthName => date.map(|d| { - result.push_str(SHORT_MONTHS[d.month0() as usize]); + result.push_str(short_months[d.month0() as usize]); Ok(()) }), LongMonthName => date.map(|d| { - result.push_str(LONG_MONTHS[d.month0() as usize]); + result.push_str(long_months[d.month0() as usize]); Ok(()) }), ShortWeekdayName => date.map(|d| { result - .push_str(SHORT_WEEKDAYS[d.weekday().num_days_from_monday() as usize]); + .push_str(short_weekdays[d.weekday().num_days_from_sunday() as usize]); Ok(()) }), LongWeekdayName => date.map(|d| { - result.push_str(LONG_WEEKDAYS[d.weekday().num_days_from_monday() as usize]); + result.push_str(long_weekdays[d.weekday().num_days_from_sunday() as usize]); Ok(()) }), LowerAmPm => time.map(|t| { @@ -672,9 +685,9 @@ fn format_inner<'a>( write!( result, "{}, {:02} {} {:04} {:02}:{:02}:{:02} ", - SHORT_WEEKDAYS[d.weekday().num_days_from_monday() as usize], + short_weekdays[d.weekday().num_days_from_sunday() as usize], d.day(), - SHORT_MONTHS[d.month0() as usize], + short_months[d.month0() as usize], d.year(), t.hour(), t.minute(), @@ -726,7 +739,7 @@ where { let mut result = String::new(); for item in items { - format_inner(&mut result, date, time, off, item.borrow())?; + format_inner(&mut result, date, time, off, item.borrow(), "POSIX")?; } w.pad(&result)?; Ok(()) @@ -890,249 +903,6 @@ pub fn format_item_localized<'a>( Ok(()) } -#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] -fn format_inner_localized<'a>( - result: &mut String, - date: Option<&NaiveDate>, - time: Option<&NaiveTime>, - off: Option<&(String, FixedOffset)>, - item: &Item<'a>, - locale: &str, -) -> FormatResult<()> { - // full and abbreviated month and weekday names - let short_months = locales::short_months(locale)?; - let long_months = locales::long_months(locale)?; - let short_weekdays = locales::short_weekdays(locale)?; - let long_weekdays = locales::long_weekdays(locale)?; - - use core::fmt::Write; - - match *item { - Item::Literal(s) | Item::Space(s) => result.push_str(s), - #[cfg(any(feature = "alloc", feature = "std", test))] - Item::OwnedLiteral(ref s) | Item::OwnedSpace(ref s) => result.push_str(s), - - Item::Numeric(ref spec, ref pad) => { - use self::Numeric::*; - - let week_from_sun = |d: &NaiveDate| { - (d.ordinal() as i32 - d.weekday().num_days_from_sunday() as i32 + 7) / 7 - }; - let week_from_mon = |d: &NaiveDate| { - (d.ordinal() as i32 - d.weekday().num_days_from_monday() as i32 + 7) / 7 - }; - - let (width, v) = match *spec { - Year => (4, date.map(|d| i64::from(d.year()))), - YearDiv100 => (2, date.map(|d| div_floor(i64::from(d.year()), 100))), - YearMod100 => (2, date.map(|d| mod_floor(i64::from(d.year()), 100))), - IsoYear => (4, date.map(|d| i64::from(d.iso_week().year()))), - IsoYearDiv100 => (2, date.map(|d| div_floor(i64::from(d.iso_week().year()), 100))), - IsoYearMod100 => (2, date.map(|d| mod_floor(i64::from(d.iso_week().year()), 100))), - Month => (2, date.map(|d| i64::from(d.month()))), - Day => (2, date.map(|d| i64::from(d.day()))), - WeekFromSun => (2, date.map(|d| i64::from(week_from_sun(d)))), - WeekFromMon => (2, date.map(|d| i64::from(week_from_mon(d)))), - IsoWeek => (2, date.map(|d| i64::from(d.iso_week().week()))), - NumDaysFromSun => (1, date.map(|d| i64::from(d.weekday().num_days_from_sunday()))), - WeekdayFromMon => (1, date.map(|d| i64::from(d.weekday().number_from_monday()))), - Ordinal => (3, date.map(|d| i64::from(d.ordinal()))), - Hour => (2, time.map(|t| i64::from(t.hour()))), - Hour12 => (2, time.map(|t| i64::from(t.hour12().1))), - Minute => (2, time.map(|t| i64::from(t.minute()))), - Second => (2, time.map(|t| i64::from(t.second() + t.nanosecond() / 1_000_000_000))), - Nanosecond => (9, time.map(|t| i64::from(t.nanosecond() % 1_000_000_000))), - Timestamp => ( - 1, - match (date, time, off) { - (Some(d), Some(t), None) => Some(d.and_time(*t).timestamp()), - (Some(d), Some(t), Some(&(_, off))) => { - Some((d.and_time(*t) - off).timestamp()) - } - (_, _, _) => None, - }, - ), - - // for the future expansion - Internal(ref int) => match int._dummy {}, - }; - - if let Some(v) = v { - if (spec == &Year || spec == &IsoYear) && !(0 <= v && v < 10_000) { - // non-four-digit years require an explicit sign as per ISO 8601 - match *pad { - Pad::None => write!(result, "{:+}", v), - Pad::Zero => write!(result, "{:+01$}", v, width + 1), - Pad::Space => write!(result, "{:+1$}", v, width + 1), - } - } else { - match *pad { - Pad::None => write!(result, "{}", v), - Pad::Zero => write!(result, "{:01$}", v, width), - Pad::Space => write!(result, "{:1$}", v, width), - } - }? - } else { - return Err(FormatError(FormatErrorKind::InsufficientArguments)); - } - } - - Item::Fixed(ref spec) => { - use self::Fixed::*; - - /// Prints an offset from UTC in the format of `+HHMM` or `+HH:MM`. - /// `Z` instead of `+00[:]00` is allowed when `allow_zulu` is true. - fn write_local_minus_utc( - result: &mut String, - off: FixedOffset, - allow_zulu: bool, - use_colon: bool, - ) -> fmt::Result { - let off = off.local_minus_utc(); - if !allow_zulu || off != 0 { - let (sign, off) = if off < 0 { ('-', -off) } else { ('+', off) }; - if use_colon { - write!(result, "{}{:02}:{:02}", sign, off / 3600, off / 60 % 60) - } else { - write!(result, "{}{:02}{:02}", sign, off / 3600, off / 60 % 60) - } - } else { - result.push_str("Z"); - Ok(()) - } - } - - let ret = - match *spec { - ShortMonthName => date.map(|d| { - result.push_str(short_months[d.month0() as usize]); - Ok(()) - }), - LongMonthName => date.map(|d| { - result.push_str(long_months[d.month0() as usize]); - Ok(()) - }), - ShortWeekdayName => date.map(|d| { - result - .push_str(short_weekdays[d.weekday().num_days_from_sunday() as usize]); - Ok(()) - }), - LongWeekdayName => date.map(|d| { - result.push_str(long_weekdays[d.weekday().num_days_from_sunday() as usize]); - Ok(()) - }), - LowerAmPm => time.map(|t| { - result.push_str(if t.hour12().0 { "pm" } else { "am" }); - Ok(()) - }), - UpperAmPm => time.map(|t| { - result.push_str(if t.hour12().0 { "PM" } else { "AM" }); - Ok(()) - }), - Nanosecond => time.map(|t| { - let nano = t.nanosecond() % 1_000_000_000; - if nano == 0 { - Ok(()) - } else if nano % 1_000_000 == 0 { - write!(result, ".{:03}", nano / 1_000_000) - } else if nano % 1_000 == 0 { - write!(result, ".{:06}", nano / 1_000) - } else { - write!(result, ".{:09}", nano) - } - }), - Nanosecond3 => time.map(|t| { - let nano = t.nanosecond() % 1_000_000_000; - write!(result, ".{:03}", nano / 1_000_000) - }), - Nanosecond6 => time.map(|t| { - let nano = t.nanosecond() % 1_000_000_000; - write!(result, ".{:06}", nano / 1_000) - }), - Nanosecond9 => time.map(|t| { - let nano = t.nanosecond() % 1_000_000_000; - write!(result, ".{:09}", nano) - }), - Internal(InternalFixed { val: InternalInternal::Nanosecond3NoDot }) => time - .map(|t| { - let nano = t.nanosecond() % 1_000_000_000; - write!(result, "{:03}", nano / 1_000_000) - }), - Internal(InternalFixed { val: InternalInternal::Nanosecond6NoDot }) => time - .map(|t| { - let nano = t.nanosecond() % 1_000_000_000; - write!(result, "{:06}", nano / 1_000) - }), - Internal(InternalFixed { val: InternalInternal::Nanosecond9NoDot }) => time - .map(|t| { - let nano = t.nanosecond() % 1_000_000_000; - write!(result, "{:09}", nano) - }), - TimezoneName => off.map(|&(ref name, _)| { - result.push_str(name); - Ok(()) - }), - TimezoneOffsetColon => { - off.map(|&(_, off)| write_local_minus_utc(result, off, false, true)) - } - TimezoneOffsetColonZ => { - off.map(|&(_, off)| write_local_minus_utc(result, off, true, true)) - } - TimezoneOffset => { - off.map(|&(_, off)| write_local_minus_utc(result, off, false, false)) - } - TimezoneOffsetZ => { - off.map(|&(_, off)| write_local_minus_utc(result, off, true, false)) - } - Internal(InternalFixed { val: InternalInternal::TimezoneOffsetPermissive }) => { - panic!("Do not try to write %#z it is undefined") - } - RFC2822 => - // same as `%a, %d %b %Y %H:%M:%S %z` - { - if let (Some(d), Some(t), Some(&(_, off))) = (date, time, off) { - let sec = t.second() + t.nanosecond() / 1_000_000_000; - write!( - result, - "{}, {:02} {} {:04} {:02}:{:02}:{:02} ", - short_weekdays[d.weekday().num_days_from_sunday() as usize], - d.day(), - short_months[d.month0() as usize], - d.year(), - t.hour(), - t.minute(), - sec - )?; - Some(write_local_minus_utc(result, off, false, false)) - } else { - None - } - } - RFC3339 => - // same as `%Y-%m-%dT%H:%M:%S%.f%:z` - { - if let (Some(d), Some(t), Some(&(_, off))) = (date, time, off) { - // reuse `Debug` impls which already print ISO 8601 format. - // this is faster in this way. - write!(result, "{:?}T{:?}", d, t)?; - Some(write_local_minus_utc(result, off, false, true)) - } else { - None - } - } - }; - - match ret { - Some(ret) => ret?, - None => return Err(FormatError(FormatErrorKind::InsufficientArguments)), - } - } - - Item::Error => return Err(FormatError(FormatErrorKind::Item)), - } - Ok(()) -} - /// Tries to format given arguments with given formatting items. /// Internally used by `DelayedFormat`. #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] From 9b7fd232261e6c4cb0e907c8843e6a85766b4707 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 12 Jul 2020 19:21:30 +0200 Subject: [PATCH 10/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- Cargo.toml | 1 + src/date.rs | 6 +++--- src/datetime.rs | 6 +++--- src/format/locales.rs | 1 + src/format/mod.rs | 30 +++++++++++++++--------------- src/format/strftime.rs | 1 - src/lib.rs | 2 +- 7 files changed, 24 insertions(+), 23 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 9c9e09f669..c3a1206642 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -52,6 +52,7 @@ bincode = { version = "0.8.0" } num-iter = { version = "0.1.35", default-features = false } criterion = { version = "0.3" } doc-comment = { version = "0.3" } +pure-rust-locales = { version = "0.2.1" } [target.'cfg(all(target_arch = "wasm32", not(any(target_os = "emscripten", target_os = "wasi"))))'.dev-dependencies] wasm-bindgen-test = "0.3" diff --git a/src/date.rs b/src/date.rs index 66a9b0973b..7f2bd8b182 100644 --- a/src/date.rs +++ b/src/date.rs @@ -10,7 +10,7 @@ use core::ops::{Add, Sub}; use core::{fmt, hash}; use oldtime::Duration as OldDuration; -#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] +#[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] use format::DelayedFormatLocalized; #[cfg(any(feature = "alloc", feature = "std", test))] use format::{DelayedFormat, Item, StrftimeItems}; @@ -299,7 +299,7 @@ where } /// Formats the date with the specified formatting items. - #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + #[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] #[inline] pub fn format_localized_with_items<'a, I, B>(&self, items: I) -> DelayedFormatLocalized where @@ -312,7 +312,7 @@ where /// Formats the date with the specified format string. /// See the [`format::strftime` module](./format/strftime/index.html) /// on the supported escape sequences. - #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + #[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] #[inline] pub fn format_localized<'a>(&self, fmt: &'a str) -> DelayedFormatLocalized> { self.format_localized_with_items(StrftimeItems::new(fmt)) diff --git a/src/datetime.rs b/src/datetime.rs index a6c8c8c16e..f282bd1e20 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -19,7 +19,7 @@ use std::string::ToString; use core::borrow::Borrow; #[cfg(any(feature = "alloc", feature = "std", test))] use format::DelayedFormat; -#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] +#[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] use format::DelayedFormatLocalized; use format::{parse, ParseError, ParseResult, Parsed, StrftimeItems}; use format::{Fixed, Item}; @@ -497,7 +497,7 @@ where } /// Formats the combined date and time with the specified formatting items. - #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + #[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] #[inline] pub fn format_localized_with_items<'a, I, B>(&self, items: I) -> DelayedFormatLocalized where @@ -516,7 +516,7 @@ where /// Formats the combined date and time with the specified format string. /// See the [`format::strftime` module](./format/strftime/index.html) /// on the supported escape sequences. - #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + #[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] #[inline] pub fn format_localized<'a>(&self, fmt: &'a str) -> DelayedFormatLocalized> { self.format_localized_with_items(StrftimeItems::new(fmt)) diff --git a/src/format/locales.rs b/src/format/locales.rs index 94fe7a3b37..68e85af719 100644 --- a/src/format/locales.rs +++ b/src/format/locales.rs @@ -3,6 +3,7 @@ use super::{FormatError, FormatErrorKind, FormatResult}; macro_rules! locale_match { ($locale:expr => $($item:ident)::+) => {{ match $locale { + "POSIX" => Ok(pure_rust_locales::POSIX::$($item)::+), "en_US" => Ok(pure_rust_locales::en_US::$($item)::+), "fr_BE" => Ok(pure_rust_locales::fr_BE::$($item)::+), // TODO: all the locales are available diff --git a/src/format/mod.rs b/src/format/mod.rs index 2c57528949..36104b78a3 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -38,7 +38,7 @@ use offset::{FixedOffset, Offset}; use {Datelike, Timelike}; use {ParseWeekdayError, Weekday}; -#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] +#[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] mod locales; pub use self::parse::parse; @@ -391,7 +391,7 @@ pub struct FormatError(FormatErrorKind); #[derive(Debug, Clone, PartialEq, Eq, Copy)] enum FormatErrorKind { /// The locale is unknown or not available. - #[cfg(feature = "locales")] + #[cfg(any(feature = "locales", test))] UnknownLocale, /// Format error. @@ -412,7 +412,7 @@ pub type FormatResult = Result; impl fmt::Display for FormatError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.0 { - #[cfg(feature = "locales")] + #[cfg(any(feature = "locales", test))] FormatErrorKind::UnknownLocale => write!(f, "the locale is unknown or not available"), FormatErrorKind::Format => write!(f, "{}", fmt::Error), FormatErrorKind::InsufficientArguments => { @@ -463,18 +463,18 @@ fn format_inner<'a>( #[allow(unused_variables)] locale: &str, ) -> FormatResult<()> { // full and abbreviated month and weekday names - #[cfg(feature = "locales")] + #[cfg(any(feature = "locales", test))] let short_months = locales::short_months(locale)?; - #[cfg(feature = "locales")] + #[cfg(any(feature = "locales", test))] let long_months = locales::long_months(locale)?; - #[cfg(feature = "locales")] + #[cfg(any(feature = "locales", test))] let short_weekdays = locales::short_weekdays(locale)?; - #[cfg(feature = "locales")] + #[cfg(any(feature = "locales", test))] let long_weekdays = locales::long_weekdays(locale)?; - #[cfg(not(feature = "locales"))] + #[cfg(not(any(feature = "locales", test)))] let short_months = &["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; - #[cfg(not(feature = "locales"))] + #[cfg(not(any(feature = "locales", test)))] let long_months = &[ "January", "February", @@ -489,9 +489,9 @@ fn format_inner<'a>( "November", "December", ]; - #[cfg(not(feature = "locales"))] + #[cfg(not(any(feature = "locales", test)))] let short_weekdays = &["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; - #[cfg(not(feature = "locales"))] + #[cfg(not(any(feature = "locales", test)))] let long_weekdays = &["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; @@ -888,7 +888,7 @@ impl FromStr for Weekday { } /// Formats single formatting item -#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] +#[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] pub fn format_item_localized<'a>( w: &mut fmt::Formatter, date: Option<&NaiveDate>, @@ -898,14 +898,14 @@ pub fn format_item_localized<'a>( locale: &str, ) -> FormatResult<()> { let mut result = String::new(); - format_inner_localized(&mut result, date, time, off, item, locale)?; + format_inner(&mut result, date, time, off, item, locale)?; w.pad(&result)?; Ok(()) } /// Tries to format given arguments with given formatting items. /// Internally used by `DelayedFormat`. -#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] +#[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] pub fn format_localized<'a, I, B>( w: &mut fmt::Formatter, date: Option<&NaiveDate>, @@ -920,7 +920,7 @@ where { let mut result = String::new(); for item in items { - format_inner_localized(&mut result, date, time, off, item.borrow(), locale)?; + format_inner(&mut result, date, time, off, item.borrow(), locale)?; } w.pad(&result)?; Ok(()) diff --git a/src/format/strftime.rs b/src/format/strftime.rs index 5b01f2868d..942fd04105 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -520,7 +520,6 @@ fn test_strftime_docs() { } #[cfg(test)] -#[cfg(feature = "locales")] // TODO: remove #[test] fn test_strftime_docs_localized() { use {FixedOffset, TimeZone, Timelike}; diff --git a/src/lib.rs b/src/lib.rs index 3b6d0abd29..a8465f38e8 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -435,7 +435,7 @@ extern crate serde as serdelib; extern crate doc_comment; #[cfg(all(target_arch = "wasm32", not(target_os = "wasi"), feature = "wasmbind"))] extern crate js_sys; -#[cfg(feature = "locales")] +#[cfg(any(feature = "locales", test))] extern crate pure_rust_locales; #[cfg(feature = "bench")] extern crate test; From 61c17d7a9f589353ec3006d7a1897f3997964700 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 12 Jul 2020 21:13:39 +0200 Subject: [PATCH 11/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/mod.rs | 22 +++++++++++----------- src/format/strftime.rs | 2 +- 2 files changed, 12 insertions(+), 12 deletions(-) diff --git a/src/format/mod.rs b/src/format/mod.rs index 36104b78a3..7ec243b9ce 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -38,7 +38,7 @@ use offset::{FixedOffset, Offset}; use {Datelike, Timelike}; use {ParseWeekdayError, Weekday}; -#[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] +#[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std", test))))] mod locales; pub use self::parse::parse; @@ -391,7 +391,7 @@ pub struct FormatError(FormatErrorKind); #[derive(Debug, Clone, PartialEq, Eq, Copy)] enum FormatErrorKind { /// The locale is unknown or not available. - #[cfg(any(feature = "locales", test))] + #[cfg(feature = "locales")] UnknownLocale, /// Format error. @@ -412,7 +412,7 @@ pub type FormatResult = Result; impl fmt::Display for FormatError { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { match self.0 { - #[cfg(any(feature = "locales", test))] + #[cfg(feature = "locales")] FormatErrorKind::UnknownLocale => write!(f, "the locale is unknown or not available"), FormatErrorKind::Format => write!(f, "{}", fmt::Error), FormatErrorKind::InsufficientArguments => { @@ -463,18 +463,18 @@ fn format_inner<'a>( #[allow(unused_variables)] locale: &str, ) -> FormatResult<()> { // full and abbreviated month and weekday names - #[cfg(any(feature = "locales", test))] + #[cfg(feature = "locales")] let short_months = locales::short_months(locale)?; - #[cfg(any(feature = "locales", test))] + #[cfg(feature = "locales")] let long_months = locales::long_months(locale)?; - #[cfg(any(feature = "locales", test))] + #[cfg(feature = "locales")] let short_weekdays = locales::short_weekdays(locale)?; - #[cfg(any(feature = "locales", test))] + #[cfg(feature = "locales")] let long_weekdays = locales::long_weekdays(locale)?; - #[cfg(not(any(feature = "locales", test)))] + #[cfg(not(feature = "locales"))] let short_months = &["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; - #[cfg(not(any(feature = "locales", test)))] + #[cfg(not(feature = "locales"))] let long_months = &[ "January", "February", @@ -489,9 +489,9 @@ fn format_inner<'a>( "November", "December", ]; - #[cfg(not(any(feature = "locales", test)))] + #[cfg(not(feature = "locales"))] let short_weekdays = &["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; - #[cfg(not(any(feature = "locales", test)))] + #[cfg(not(feature = "locales"))] let long_weekdays = &["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; diff --git a/src/format/strftime.rs b/src/format/strftime.rs index 942fd04105..5a5280a893 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -519,7 +519,7 @@ fn test_strftime_docs() { assert_eq!(dt.format("%%").to_string(), "%"); } -#[cfg(test)] +#[cfg(all(feature = "locales", test))] #[test] fn test_strftime_docs_localized() { use {FixedOffset, TimeZone, Timelike}; From 0213867e8ffa4df8f5f02d71c3bd5c603eaf791c Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 12 Jul 2020 21:21:42 +0200 Subject: [PATCH 12/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/mod.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/format/mod.rs b/src/format/mod.rs index 7ec243b9ce..3dea61835b 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -460,8 +460,10 @@ fn format_inner<'a>( time: Option<&NaiveTime>, off: Option<&(String, FixedOffset)>, item: &Item<'a>, - #[allow(unused_variables)] locale: &str, + _locale: &str, ) -> FormatResult<()> { + #[cfg(feature = "locales")] + let locale = _locale; // full and abbreviated month and weekday names #[cfg(feature = "locales")] let short_months = locales::short_months(locale)?; From 1e6c086751348ab05b64c106961b3a4392f6148e Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 17 Jul 2020 18:17:12 +0200 Subject: [PATCH 13/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/date.rs | 8 +-- src/datetime.rs | 7 +-- src/format/mod.rs | 8 ++- src/format/strftime.rs | 114 ++++++++++++++++++++--------------------- 4 files changed, 71 insertions(+), 66 deletions(-) diff --git a/src/date.rs b/src/date.rs index 7f2bd8b182..81fe79bd10 100644 --- a/src/date.rs +++ b/src/date.rs @@ -301,12 +301,12 @@ where /// Formats the date with the specified formatting items. #[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] #[inline] - pub fn format_localized_with_items<'a, I, B>(&self, items: I) -> DelayedFormatLocalized + pub fn format_localized_with_items<'a, I, B>(&self, items: I, locale: impl Into) -> DelayedFormatLocalized where I: Iterator + Clone, B: Borrow>, { - DelayedFormatLocalized::new_with_offset(Some(self.naive_local()), None, &self.offset, items) + DelayedFormatLocalized::new_with_offset(Some(self.naive_local()), None, &self.offset, items, locale) } /// Formats the date with the specified format string. @@ -314,8 +314,8 @@ where /// on the supported escape sequences. #[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] #[inline] - pub fn format_localized<'a>(&self, fmt: &'a str) -> DelayedFormatLocalized> { - self.format_localized_with_items(StrftimeItems::new(fmt)) + pub fn format_localized<'a>(&self, fmt: &'a str, locale: impl Into) -> DelayedFormatLocalized> { + self.format_localized_with_items(StrftimeItems::new(fmt), locale) } } diff --git a/src/datetime.rs b/src/datetime.rs index f282bd1e20..7eb73377cf 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -499,7 +499,7 @@ where /// Formats the combined date and time with the specified formatting items. #[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] #[inline] - pub fn format_localized_with_items<'a, I, B>(&self, items: I) -> DelayedFormatLocalized + pub fn format_localized_with_items<'a, I, B>(&self, items: I, locale: impl Into) -> DelayedFormatLocalized where I: Iterator + Clone, B: Borrow>, @@ -510,6 +510,7 @@ where Some(local.time()), &self.offset, items, + locale, ) } @@ -518,8 +519,8 @@ where /// on the supported escape sequences. #[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] #[inline] - pub fn format_localized<'a>(&self, fmt: &'a str) -> DelayedFormatLocalized> { - self.format_localized_with_items(StrftimeItems::new(fmt)) + pub fn format_localized<'a>(&self, fmt: &'a str, locale: impl Into) -> DelayedFormatLocalized> { + self.format_localized_with_items(StrftimeItems::new(fmt), locale) } } diff --git a/src/format/mod.rs b/src/format/mod.rs index 3dea61835b..68b68fe274 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -813,6 +813,8 @@ pub struct DelayedFormatLocalized { off: Option<(String, FixedOffset)>, /// An iterator returning formatting items. items: I, + /// Locale used for text. + locale: String, } #[cfg(any(feature = "alloc", feature = "std", test))] @@ -822,8 +824,9 @@ impl<'a, I: Iterator + Clone, B: Borrow>> DelayedFormatLocali date: Option, time: Option, items: I, + locale: impl Into, ) -> DelayedFormatLocalized { - DelayedFormatLocalized { date: date, time: time, off: None, items: items } + DelayedFormatLocalized { date: date, time: time, off: None, items: items, locale: locale.into() } } /// Makes a new `DelayedFormat` value out of local date and time and UTC offset. @@ -832,12 +835,13 @@ impl<'a, I: Iterator + Clone, B: Borrow>> DelayedFormatLocali time: Option, offset: &Off, items: I, + locale: impl Into, ) -> DelayedFormatLocalized where Off: Offset + fmt::Display, { let name_and_diff = (offset.to_string(), offset.fix()); - DelayedFormatLocalized { date: date, time: time, off: Some(name_and_diff), items: items } + DelayedFormatLocalized { date: date, time: time, off: Some(name_and_diff), items: items, locale: locale.into() } } } diff --git a/src/format/strftime.rs b/src/format/strftime.rs index 5a5280a893..1c68a0fa6b 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -527,75 +527,75 @@ fn test_strftime_docs_localized() { let dt = FixedOffset::east(34200).ymd(2001, 7, 8).and_hms_nano(0, 34, 59, 1_026_490_708); // date specifiers - assert_eq!(dt.format_localized("%Y").to_string(), "2001"); - assert_eq!(dt.format_localized("%C").to_string(), "20"); - assert_eq!(dt.format_localized("%y").to_string(), "01"); - assert_eq!(dt.format_localized("%m").to_string(), "07"); - assert_eq!(dt.format_localized("%b").to_string(), "Jul"); - assert_eq!(dt.format_localized("%B").to_string(), "July"); - assert_eq!(dt.format_localized("%h").to_string(), "Jul"); - assert_eq!(dt.format_localized("%d").to_string(), "08"); - assert_eq!(dt.format_localized("%e").to_string(), " 8"); - assert_eq!(dt.format_localized("%e").to_string(), dt.format_localized("%_d").to_string()); - assert_eq!(dt.format_localized("%a").to_string(), "Sun"); - assert_eq!(dt.format_localized("%A").to_string(), "Sunday"); - assert_eq!(dt.format_localized("%w").to_string(), "0"); - assert_eq!(dt.format_localized("%u").to_string(), "7"); - assert_eq!(dt.format_localized("%U").to_string(), "28"); - assert_eq!(dt.format_localized("%W").to_string(), "27"); - assert_eq!(dt.format_localized("%G").to_string(), "2001"); - assert_eq!(dt.format_localized("%g").to_string(), "01"); - assert_eq!(dt.format_localized("%V").to_string(), "27"); - assert_eq!(dt.format_localized("%j").to_string(), "189"); - assert_eq!(dt.format_localized("%D").to_string(), "07/08/01"); - assert_eq!(dt.format_localized("%x").to_string(), "07/08/01"); - assert_eq!(dt.format_localized("%F").to_string(), "2001-07-08"); - assert_eq!(dt.format_localized("%v").to_string(), " 8-Jul-2001"); + assert_eq!(dt.format_localized("%Y", "POSIX").to_string(), "2001"); + assert_eq!(dt.format_localized("%C", "POSIX").to_string(), "20"); + assert_eq!(dt.format_localized("%y", "POSIX").to_string(), "01"); + assert_eq!(dt.format_localized("%m", "POSIX").to_string(), "07"); + assert_eq!(dt.format_localized("%b", "POSIX").to_string(), "Jul"); + assert_eq!(dt.format_localized("%B", "POSIX").to_string(), "July"); + assert_eq!(dt.format_localized("%h", "POSIX").to_string(), "Jul"); + assert_eq!(dt.format_localized("%d", "POSIX").to_string(), "08"); + assert_eq!(dt.format_localized("%e", "POSIX").to_string(), " 8"); + assert_eq!(dt.format_localized("%e", "POSIX").to_string(), dt.format_localized("%_d", "POSIX").to_string()); + assert_eq!(dt.format_localized("%a", "POSIX").to_string(), "Sun"); + assert_eq!(dt.format_localized("%A", "POSIX").to_string(), "Sunday"); + assert_eq!(dt.format_localized("%w", "POSIX").to_string(), "0"); + assert_eq!(dt.format_localized("%u", "POSIX").to_string(), "7"); + assert_eq!(dt.format_localized("%U", "POSIX").to_string(), "28"); + assert_eq!(dt.format_localized("%W", "POSIX").to_string(), "27"); + assert_eq!(dt.format_localized("%G", "POSIX").to_string(), "2001"); + assert_eq!(dt.format_localized("%g", "POSIX").to_string(), "01"); + assert_eq!(dt.format_localized("%V", "POSIX").to_string(), "27"); + assert_eq!(dt.format_localized("%j", "POSIX").to_string(), "189"); + assert_eq!(dt.format_localized("%D", "POSIX").to_string(), "07/08/01"); + assert_eq!(dt.format_localized("%x", "POSIX").to_string(), "07/08/01"); + assert_eq!(dt.format_localized("%F", "POSIX").to_string(), "2001-07-08"); + assert_eq!(dt.format_localized("%v", "POSIX").to_string(), " 8-Jul-2001"); // time specifiers - assert_eq!(dt.format_localized("%H").to_string(), "00"); - assert_eq!(dt.format_localized("%k").to_string(), " 0"); - assert_eq!(dt.format_localized("%k").to_string(), dt.format_localized("%_H").to_string()); - assert_eq!(dt.format_localized("%I").to_string(), "12"); - assert_eq!(dt.format_localized("%l").to_string(), "12"); - assert_eq!(dt.format_localized("%l").to_string(), dt.format_localized("%_I").to_string()); - assert_eq!(dt.format_localized("%P").to_string(), "am"); - assert_eq!(dt.format_localized("%p").to_string(), "AM"); - assert_eq!(dt.format_localized("%M").to_string(), "34"); - assert_eq!(dt.format_localized("%S").to_string(), "60"); - assert_eq!(dt.format_localized("%f").to_string(), "026490708"); - assert_eq!(dt.format_localized("%.f").to_string(), ".026490708"); + assert_eq!(dt.format_localized("%H", "POSIX").to_string(), "00"); + assert_eq!(dt.format_localized("%k", "POSIX").to_string(), " 0"); + assert_eq!(dt.format_localized("%k", "POSIX").to_string(), dt.format_localized("%_H", "POSIX").to_string()); + assert_eq!(dt.format_localized("%I", "POSIX").to_string(), "12"); + assert_eq!(dt.format_localized("%l", "POSIX").to_string(), "12"); + assert_eq!(dt.format_localized("%l", "POSIX").to_string(), dt.format_localized("%_I", "POSIX").to_string()); + assert_eq!(dt.format_localized("%P", "POSIX").to_string(), "am"); + assert_eq!(dt.format_localized("%p", "POSIX").to_string(), "AM"); + assert_eq!(dt.format_localized("%M", "POSIX").to_string(), "34"); + assert_eq!(dt.format_localized("%S", "POSIX").to_string(), "60"); + assert_eq!(dt.format_localized("%f", "POSIX").to_string(), "026490708"); + assert_eq!(dt.format_localized("%.f", "POSIX").to_string(), ".026490708"); assert_eq!( - dt.with_nanosecond(1_026_490_000).unwrap().format_localized("%.f").to_string(), + dt.with_nanosecond(1_026_490_000).unwrap().format_localized("%.f", "POSIX").to_string(), ".026490" ); - assert_eq!(dt.format_localized("%.3f").to_string(), ".026"); - assert_eq!(dt.format_localized("%.6f").to_string(), ".026490"); - assert_eq!(dt.format_localized("%.9f").to_string(), ".026490708"); - assert_eq!(dt.format_localized("%3f").to_string(), "026"); - assert_eq!(dt.format_localized("%6f").to_string(), "026490"); - assert_eq!(dt.format_localized("%9f").to_string(), "026490708"); - assert_eq!(dt.format_localized("%R").to_string(), "00:34"); - assert_eq!(dt.format_localized("%T").to_string(), "00:34:60"); - assert_eq!(dt.format_localized("%X").to_string(), "00:34:60"); - assert_eq!(dt.format_localized("%r").to_string(), "12:34:60 AM"); + assert_eq!(dt.format_localized("%.3f", "POSIX").to_string(), ".026"); + assert_eq!(dt.format_localized("%.6f", "POSIX").to_string(), ".026490"); + assert_eq!(dt.format_localized("%.9f", "POSIX").to_string(), ".026490708"); + assert_eq!(dt.format_localized("%3f", "POSIX").to_string(), "026"); + assert_eq!(dt.format_localized("%6f", "POSIX").to_string(), "026490"); + assert_eq!(dt.format_localized("%9f", "POSIX").to_string(), "026490708"); + assert_eq!(dt.format_localized("%R", "POSIX").to_string(), "00:34"); + assert_eq!(dt.format_localized("%T", "POSIX").to_string(), "00:34:60"); + assert_eq!(dt.format_localized("%X", "POSIX").to_string(), "00:34:60"); + assert_eq!(dt.format_localized("%r", "POSIX").to_string(), "12:34:60 AM"); // time zone specifiers - //assert_eq!(dt.format_localized("%Z").to_string(), "ACST"); - assert_eq!(dt.format_localized("%z").to_string(), "+0930"); - assert_eq!(dt.format_localized("%:z").to_string(), "+09:30"); + //assert_eq!(dt.format_localized("%Z", "POSIX").to_string(), "ACST"); + assert_eq!(dt.format_localized("%z", "POSIX").to_string(), "+0930"); + assert_eq!(dt.format_localized("%:z", "POSIX").to_string(), "+09:30"); // date & time specifiers - assert_eq!(dt.format_localized("%c").to_string(), "Sun Jul 8 00:34:60 2001"); - assert_eq!(dt.format_localized("%+").to_string(), "2001-07-08T00:34:60.026490708+09:30"); + assert_eq!(dt.format_localized("%c", "POSIX").to_string(), "Sun Jul 8 00:34:60 2001"); + assert_eq!(dt.format_localized("%+", "POSIX").to_string(), "2001-07-08T00:34:60.026490708+09:30"); assert_eq!( - dt.with_nanosecond(1_026_490_000).unwrap().format_localized("%+").to_string(), + dt.with_nanosecond(1_026_490_000).unwrap().format_localized("%+", "POSIX").to_string(), "2001-07-08T00:34:60.026490+09:30" ); - assert_eq!(dt.format_localized("%s").to_string(), "994518299"); + assert_eq!(dt.format_localized("%s", "POSIX").to_string(), "994518299"); // special specifiers - assert_eq!(dt.format_localized("%t").to_string(), "\t"); - assert_eq!(dt.format_localized("%n").to_string(), "\n"); - assert_eq!(dt.format_localized("%%").to_string(), "%"); + assert_eq!(dt.format_localized("%t", "POSIX").to_string(), "\t"); + assert_eq!(dt.format_localized("%n", "POSIX").to_string(), "\n"); + assert_eq!(dt.format_localized("%%", "POSIX").to_string(), "%"); } From 6de9c1a671d6e02e84afc9857bce0408f4b73820 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 17 Jul 2020 18:31:58 +0200 Subject: [PATCH 14/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/date.rs | 4 ++-- src/datetime.rs | 4 ++-- src/format/mod.rs | 24 ++++++++++++------------ 3 files changed, 16 insertions(+), 16 deletions(-) diff --git a/src/date.rs b/src/date.rs index 81fe79bd10..7dcc49e5c3 100644 --- a/src/date.rs +++ b/src/date.rs @@ -301,7 +301,7 @@ where /// Formats the date with the specified formatting items. #[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] #[inline] - pub fn format_localized_with_items<'a, I, B>(&self, items: I, locale: impl Into) -> DelayedFormatLocalized + pub fn format_localized_with_items<'a, 'b, I, B>(&self, items: I, locale: &'b str) -> DelayedFormatLocalized<'b, I> where I: Iterator + Clone, B: Borrow>, @@ -314,7 +314,7 @@ where /// on the supported escape sequences. #[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] #[inline] - pub fn format_localized<'a>(&self, fmt: &'a str, locale: impl Into) -> DelayedFormatLocalized> { + pub fn format_localized<'a, 'b>(&self, fmt: &'a str, locale: &'b str) -> DelayedFormatLocalized<'b, StrftimeItems<'a>> { self.format_localized_with_items(StrftimeItems::new(fmt), locale) } } diff --git a/src/datetime.rs b/src/datetime.rs index 7eb73377cf..39e5606f76 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -499,7 +499,7 @@ where /// Formats the combined date and time with the specified formatting items. #[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] #[inline] - pub fn format_localized_with_items<'a, I, B>(&self, items: I, locale: impl Into) -> DelayedFormatLocalized + pub fn format_localized_with_items<'a, 'b, I, B>(&self, items: I, locale: &'b str) -> DelayedFormatLocalized<'b, I> where I: Iterator + Clone, B: Borrow>, @@ -519,7 +519,7 @@ where /// on the supported escape sequences. #[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] #[inline] - pub fn format_localized<'a>(&self, fmt: &'a str, locale: impl Into) -> DelayedFormatLocalized> { + pub fn format_localized<'a, 'b>(&self, fmt: &'a str, locale: &'b str) -> DelayedFormatLocalized<'b, StrftimeItems<'a>> { self.format_localized_with_items(StrftimeItems::new(fmt), locale) } } diff --git a/src/format/mod.rs b/src/format/mod.rs index 68b68fe274..e20e1157bb 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -804,7 +804,7 @@ impl<'a, I: Iterator + Clone, B: Borrow>> fmt::Display for De /// This is normally constructed via `format` methods of each date and time type. #[cfg(any(feature = "alloc", feature = "std", test))] #[derive(Debug)] -pub struct DelayedFormatLocalized { +pub struct DelayedFormatLocalized<'a, I> { /// The date view, if any. date: Option, /// The time view, if any. @@ -814,19 +814,19 @@ pub struct DelayedFormatLocalized { /// An iterator returning formatting items. items: I, /// Locale used for text. - locale: String, + locale: &'a str, } #[cfg(any(feature = "alloc", feature = "std", test))] -impl<'a, I: Iterator + Clone, B: Borrow>> DelayedFormatLocalized { +impl<'a, 'b, I: Iterator + Clone, B: Borrow>> DelayedFormatLocalized<'b, I> { /// Makes a new `DelayedFormat` value out of local date and time. pub fn new( date: Option, time: Option, items: I, - locale: impl Into, - ) -> DelayedFormatLocalized { - DelayedFormatLocalized { date: date, time: time, off: None, items: items, locale: locale.into() } + locale: &'b str, + ) -> DelayedFormatLocalized<'b, I> { + DelayedFormatLocalized { date: date, time: time, off: None, items: items, locale: locale.as_ref() } } /// Makes a new `DelayedFormat` value out of local date and time and UTC offset. @@ -835,22 +835,22 @@ impl<'a, I: Iterator + Clone, B: Borrow>> DelayedFormatLocali time: Option, offset: &Off, items: I, - locale: impl Into, - ) -> DelayedFormatLocalized + locale: &'b str, + ) -> DelayedFormatLocalized<'b, I> where Off: Offset + fmt::Display, { let name_and_diff = (offset.to_string(), offset.fix()); - DelayedFormatLocalized { date: date, time: time, off: Some(name_and_diff), items: items, locale: locale.into() } + DelayedFormatLocalized { date: date, time: time, off: Some(name_and_diff), items: items, locale: locale.as_ref() } } } #[cfg(any(feature = "alloc", feature = "std", test))] -impl<'a, I: Iterator + Clone, B: Borrow>> fmt::Display - for DelayedFormatLocalized +impl<'a, 'b, I: Iterator + Clone, B: Borrow>> fmt::Display + for DelayedFormatLocalized<'b, I> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - format(f, self.date.as_ref(), self.time.as_ref(), self.off.as_ref(), self.items.clone()) + format_localized(f, self.date.as_ref(), self.time.as_ref(), self.off.as_ref(), self.items.clone(), self.locale) .map_err(|_| fmt::Error) } } From d10deae75d4933b1936351397a22c29316ea55a7 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 17 Jul 2020 19:02:47 +0200 Subject: [PATCH 15/60] WIP --- src/date.rs | 20 +++++++++++++++++--- src/datetime.rs | 12 ++++++++++-- src/format/mod.rs | 27 +++++++++++++++++++++++---- src/format/strftime.rs | 20 ++++++++++++++++---- 4 files changed, 66 insertions(+), 13 deletions(-) diff --git a/src/date.rs b/src/date.rs index 7dcc49e5c3..fbdd2388fb 100644 --- a/src/date.rs +++ b/src/date.rs @@ -301,12 +301,22 @@ where /// Formats the date with the specified formatting items. #[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] #[inline] - pub fn format_localized_with_items<'a, 'b, I, B>(&self, items: I, locale: &'b str) -> DelayedFormatLocalized<'b, I> + pub fn format_localized_with_items<'a, 'b, I, B>( + &self, + items: I, + locale: &'b str, + ) -> DelayedFormatLocalized<'b, I> where I: Iterator + Clone, B: Borrow>, { - DelayedFormatLocalized::new_with_offset(Some(self.naive_local()), None, &self.offset, items, locale) + DelayedFormatLocalized::new_with_offset( + Some(self.naive_local()), + None, + &self.offset, + items, + locale, + ) } /// Formats the date with the specified format string. @@ -314,7 +324,11 @@ where /// on the supported escape sequences. #[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] #[inline] - pub fn format_localized<'a, 'b>(&self, fmt: &'a str, locale: &'b str) -> DelayedFormatLocalized<'b, StrftimeItems<'a>> { + pub fn format_localized<'a, 'b>( + &self, + fmt: &'a str, + locale: &'b str, + ) -> DelayedFormatLocalized<'b, StrftimeItems<'a>> { self.format_localized_with_items(StrftimeItems::new(fmt), locale) } } diff --git a/src/datetime.rs b/src/datetime.rs index 39e5606f76..9964bb2661 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -499,7 +499,11 @@ where /// Formats the combined date and time with the specified formatting items. #[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] #[inline] - pub fn format_localized_with_items<'a, 'b, I, B>(&self, items: I, locale: &'b str) -> DelayedFormatLocalized<'b, I> + pub fn format_localized_with_items<'a, 'b, I, B>( + &self, + items: I, + locale: &'b str, + ) -> DelayedFormatLocalized<'b, I> where I: Iterator + Clone, B: Borrow>, @@ -519,7 +523,11 @@ where /// on the supported escape sequences. #[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] #[inline] - pub fn format_localized<'a, 'b>(&self, fmt: &'a str, locale: &'b str) -> DelayedFormatLocalized<'b, StrftimeItems<'a>> { + pub fn format_localized<'a, 'b>( + &self, + fmt: &'a str, + locale: &'b str, + ) -> DelayedFormatLocalized<'b, StrftimeItems<'a>> { self.format_localized_with_items(StrftimeItems::new(fmt), locale) } } diff --git a/src/format/mod.rs b/src/format/mod.rs index e20e1157bb..fa84ccf649 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -826,7 +826,13 @@ impl<'a, 'b, I: Iterator + Clone, B: Borrow>> DelayedFormatLo items: I, locale: &'b str, ) -> DelayedFormatLocalized<'b, I> { - DelayedFormatLocalized { date: date, time: time, off: None, items: items, locale: locale.as_ref() } + DelayedFormatLocalized { + date: date, + time: time, + off: None, + items: items, + locale: locale.as_ref(), + } } /// Makes a new `DelayedFormat` value out of local date and time and UTC offset. @@ -841,7 +847,13 @@ impl<'a, 'b, I: Iterator + Clone, B: Borrow>> DelayedFormatLo Off: Offset + fmt::Display, { let name_and_diff = (offset.to_string(), offset.fix()); - DelayedFormatLocalized { date: date, time: time, off: Some(name_and_diff), items: items, locale: locale.as_ref() } + DelayedFormatLocalized { + date: date, + time: time, + off: Some(name_and_diff), + items: items, + locale: locale.as_ref(), + } } } @@ -850,8 +862,15 @@ impl<'a, 'b, I: Iterator + Clone, B: Borrow>> fmt::Display for DelayedFormatLocalized<'b, I> { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - format_localized(f, self.date.as_ref(), self.time.as_ref(), self.off.as_ref(), self.items.clone(), self.locale) - .map_err(|_| fmt::Error) + format_localized( + f, + self.date.as_ref(), + self.time.as_ref(), + self.off.as_ref(), + self.items.clone(), + self.locale, + ) + .map_err(|_| fmt::Error) } } diff --git a/src/format/strftime.rs b/src/format/strftime.rs index 1c68a0fa6b..ddaa1907ca 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -536,7 +536,10 @@ fn test_strftime_docs_localized() { assert_eq!(dt.format_localized("%h", "POSIX").to_string(), "Jul"); assert_eq!(dt.format_localized("%d", "POSIX").to_string(), "08"); assert_eq!(dt.format_localized("%e", "POSIX").to_string(), " 8"); - assert_eq!(dt.format_localized("%e", "POSIX").to_string(), dt.format_localized("%_d", "POSIX").to_string()); + assert_eq!( + dt.format_localized("%e", "POSIX").to_string(), + dt.format_localized("%_d", "POSIX").to_string() + ); assert_eq!(dt.format_localized("%a", "POSIX").to_string(), "Sun"); assert_eq!(dt.format_localized("%A", "POSIX").to_string(), "Sunday"); assert_eq!(dt.format_localized("%w", "POSIX").to_string(), "0"); @@ -555,10 +558,16 @@ fn test_strftime_docs_localized() { // time specifiers assert_eq!(dt.format_localized("%H", "POSIX").to_string(), "00"); assert_eq!(dt.format_localized("%k", "POSIX").to_string(), " 0"); - assert_eq!(dt.format_localized("%k", "POSIX").to_string(), dt.format_localized("%_H", "POSIX").to_string()); + assert_eq!( + dt.format_localized("%k", "POSIX").to_string(), + dt.format_localized("%_H", "POSIX").to_string() + ); assert_eq!(dt.format_localized("%I", "POSIX").to_string(), "12"); assert_eq!(dt.format_localized("%l", "POSIX").to_string(), "12"); - assert_eq!(dt.format_localized("%l", "POSIX").to_string(), dt.format_localized("%_I", "POSIX").to_string()); + assert_eq!( + dt.format_localized("%l", "POSIX").to_string(), + dt.format_localized("%_I", "POSIX").to_string() + ); assert_eq!(dt.format_localized("%P", "POSIX").to_string(), "am"); assert_eq!(dt.format_localized("%p", "POSIX").to_string(), "AM"); assert_eq!(dt.format_localized("%M", "POSIX").to_string(), "34"); @@ -587,7 +596,10 @@ fn test_strftime_docs_localized() { // date & time specifiers assert_eq!(dt.format_localized("%c", "POSIX").to_string(), "Sun Jul 8 00:34:60 2001"); - assert_eq!(dt.format_localized("%+", "POSIX").to_string(), "2001-07-08T00:34:60.026490708+09:30"); + assert_eq!( + dt.format_localized("%+", "POSIX").to_string(), + "2001-07-08T00:34:60.026490708+09:30" + ); assert_eq!( dt.with_nanosecond(1_026_490_000).unwrap().format_localized("%+", "POSIX").to_string(), "2001-07-08T00:34:60.026490+09:30" From 1f9648f3808eb8b056e148f8c18d28fd4fbe5bd0 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 17 Jul 2020 20:34:32 +0200 Subject: [PATCH 16/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- Cargo.toml | 3 +- src/format/locales.rs | 334 +++++++++++++++++++++++++++++++++++++++++- 2 files changed, 334 insertions(+), 3 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index c3a1206642..a5a50bc936 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,7 @@ num-integer = { version = "0.1.36", default-features = false } num-traits = { version = "0.2", default-features = false } rustc-serialize = { version = "0.3.20", optional = true } serde = { version = "1.0.99", default-features = false, optional = true } -pure-rust-locales = { version = "0.2.1", optional = true } +pure-rust-locales = { version = "0.3.0", optional = true } [target.'cfg(all(target_arch = "wasm32", not(any(target_os = "emscripten", target_os = "wasi"))))'.dependencies] wasm-bindgen = { version = "0.2", optional = true } @@ -52,7 +52,6 @@ bincode = { version = "0.8.0" } num-iter = { version = "0.1.35", default-features = false } criterion = { version = "0.3" } doc-comment = { version = "0.3" } -pure-rust-locales = { version = "0.2.1" } [target.'cfg(all(target_arch = "wasm32", not(any(target_os = "emscripten", target_os = "wasi"))))'.dev-dependencies] wasm-bindgen-test = "0.3" diff --git a/src/format/locales.rs b/src/format/locales.rs index 68e85af719..f23cdaee5f 100644 --- a/src/format/locales.rs +++ b/src/format/locales.rs @@ -3,10 +3,342 @@ use super::{FormatError, FormatErrorKind, FormatResult}; macro_rules! locale_match { ($locale:expr => $($item:ident)::+) => {{ match $locale { + "cv_RU" => Ok(pure_rust_locales::cv_RU::$($item)::+), + "so_DJ" => Ok(pure_rust_locales::so_DJ::$($item)::+), + "ln_CD" => Ok(pure_rust_locales::ln_CD::$($item)::+), + "sah_RU" => Ok(pure_rust_locales::sah_RU::$($item)::+), + "ak_GH" => Ok(pure_rust_locales::ak_GH::$($item)::+), + "ber_MA" => Ok(pure_rust_locales::ber_MA::$($item)::+), + "aa_DJ" => Ok(pure_rust_locales::aa_DJ::$($item)::+), + "nl_BE_euro" => Ok(pure_rust_locales::nl_BE_euro::$($item)::+), + "pl_PL" => Ok(pure_rust_locales::pl_PL::$($item)::+), + "ca_AD" => Ok(pure_rust_locales::ca_AD::$($item)::+), + "so_SO" => Ok(pure_rust_locales::so_SO::$($item)::+), + "de_LI" => Ok(pure_rust_locales::de_LI::$($item)::+), + "fur_IT" => Ok(pure_rust_locales::fur_IT::$($item)::+), + "es_VE" => Ok(pure_rust_locales::es_VE::$($item)::+), + "ast_ES" => Ok(pure_rust_locales::ast_ES::$($item)::+), + "sv_FI_euro" => Ok(pure_rust_locales::sv_FI_euro::$($item)::+), + "uz_UZ_cyrillic" => Ok(pure_rust_locales::uz_UZ_cyrillic::$($item)::+), + "it_IT" => Ok(pure_rust_locales::it_IT::$($item)::+), + "ca_ES" => Ok(pure_rust_locales::ca_ES::$($item)::+), + "kk_KZ" => Ok(pure_rust_locales::kk_KZ::$($item)::+), + "ms_MY" => Ok(pure_rust_locales::ms_MY::$($item)::+), + "ig_NG" => Ok(pure_rust_locales::ig_NG::$($item)::+), + "mai_NP" => Ok(pure_rust_locales::mai_NP::$($item)::+), + "eo" => Ok(pure_rust_locales::eo::$($item)::+), + "se_NO" => Ok(pure_rust_locales::se_NO::$($item)::+), + "tr_TR" => Ok(pure_rust_locales::tr_TR::$($item)::+), + "fr_LU_euro" => Ok(pure_rust_locales::fr_LU_euro::$($item)::+), + "pa_IN" => Ok(pure_rust_locales::pa_IN::$($item)::+), + "af_ZA" => Ok(pure_rust_locales::af_ZA::$($item)::+), + "es_US" => Ok(pure_rust_locales::es_US::$($item)::+), + "gv_GB" => Ok(pure_rust_locales::gv_GB::$($item)::+), + "nl_AW" => Ok(pure_rust_locales::nl_AW::$($item)::+), + "ko_KR" => Ok(pure_rust_locales::ko_KR::$($item)::+), + "gez_ER" => Ok(pure_rust_locales::gez_ER::$($item)::+), + "sd_IN_devanagari" => Ok(pure_rust_locales::sd_IN_devanagari::$($item)::+), + "mhr_RU" => Ok(pure_rust_locales::mhr_RU::$($item)::+), + "lv_LV" => Ok(pure_rust_locales::lv_LV::$($item)::+), + "yo_NG" => Ok(pure_rust_locales::yo_NG::$($item)::+), + "agr_PE" => Ok(pure_rust_locales::agr_PE::$($item)::+), + "tn_ZA" => Ok(pure_rust_locales::tn_ZA::$($item)::+), + "st_ZA" => Ok(pure_rust_locales::st_ZA::$($item)::+), + "be_BY_latin" => Ok(pure_rust_locales::be_BY_latin::$($item)::+), + "yue_HK" => Ok(pure_rust_locales::yue_HK::$($item)::+), + "kok_IN" => Ok(pure_rust_locales::kok_IN::$($item)::+), + "ur_PK" => Ok(pure_rust_locales::ur_PK::$($item)::+), + "crh_UA" => Ok(pure_rust_locales::crh_UA::$($item)::+), + "sw_TZ" => Ok(pure_rust_locales::sw_TZ::$($item)::+), + "sv_SE" => Ok(pure_rust_locales::sv_SE::$($item)::+), + "ka_GE" => Ok(pure_rust_locales::ka_GE::$($item)::+), + "ar_EG" => Ok(pure_rust_locales::ar_EG::$($item)::+), + "uk_UA" => Ok(pure_rust_locales::uk_UA::$($item)::+), + "ar_SD" => Ok(pure_rust_locales::ar_SD::$($item)::+), + "en_IN" => Ok(pure_rust_locales::en_IN::$($item)::+), + "bho_NP" => Ok(pure_rust_locales::bho_NP::$($item)::+), + "kw_GB" => Ok(pure_rust_locales::kw_GB::$($item)::+), + "mfe_MU" => Ok(pure_rust_locales::mfe_MU::$($item)::+), + "nl_BE" => Ok(pure_rust_locales::nl_BE::$($item)::+), + "shn_MM" => Ok(pure_rust_locales::shn_MM::$($item)::+), + "ps_AF" => Ok(pure_rust_locales::ps_AF::$($item)::+), + "nr_ZA" => Ok(pure_rust_locales::nr_ZA::$($item)::+), + "el_GR" => Ok(pure_rust_locales::el_GR::$($item)::+), + "nds_NL" => Ok(pure_rust_locales::nds_NL::$($item)::+), + "sl_SI" => Ok(pure_rust_locales::sl_SI::$($item)::+), + "tl_PH" => Ok(pure_rust_locales::tl_PH::$($item)::+), + "or_IN" => Ok(pure_rust_locales::or_IN::$($item)::+), + "mi_NZ" => Ok(pure_rust_locales::mi_NZ::$($item)::+), + "en_AG" => Ok(pure_rust_locales::en_AG::$($item)::+), + "gez_ER_abegede" => Ok(pure_rust_locales::gez_ER_abegede::$($item)::+), + "uz_UZ" => Ok(pure_rust_locales::uz_UZ::$($item)::+), + "ar_SY" => Ok(pure_rust_locales::ar_SY::$($item)::+), + "wa_BE" => Ok(pure_rust_locales::wa_BE::$($item)::+), + "bn_BD" => Ok(pure_rust_locales::bn_BD::$($item)::+), + "bo_CN" => Ok(pure_rust_locales::bo_CN::$($item)::+), + "te_IN" => Ok(pure_rust_locales::te_IN::$($item)::+), + "zh_HK" => Ok(pure_rust_locales::zh_HK::$($item)::+), + "wal_ET" => Ok(pure_rust_locales::wal_ET::$($item)::+), + "ff_SN" => Ok(pure_rust_locales::ff_SN::$($item)::+), + "brx_IN" => Ok(pure_rust_locales::brx_IN::$($item)::+), + "de_AT" => Ok(pure_rust_locales::de_AT::$($item)::+), + "fr_CA" => Ok(pure_rust_locales::fr_CA::$($item)::+), + "hif_FJ" => Ok(pure_rust_locales::hif_FJ::$($item)::+), + "niu_NZ" => Ok(pure_rust_locales::niu_NZ::$($item)::+), "POSIX" => Ok(pure_rust_locales::POSIX::$($item)::+), "en_US" => Ok(pure_rust_locales::en_US::$($item)::+), + "ar_KW" => Ok(pure_rust_locales::ar_KW::$($item)::+), + "bn_IN" => Ok(pure_rust_locales::bn_IN::$($item)::+), + "fi_FI_euro" => Ok(pure_rust_locales::fi_FI_euro::$($item)::+), + "yi_US" => Ok(pure_rust_locales::yi_US::$($item)::+), + "en_ZA" => Ok(pure_rust_locales::en_ZA::$($item)::+), + "sgs_LT" => Ok(pure_rust_locales::sgs_LT::$($item)::+), + "fy_NL" => Ok(pure_rust_locales::fy_NL::$($item)::+), + "nan_TW_latin" => Ok(pure_rust_locales::nan_TW_latin::$($item)::+), + "csb_PL" => Ok(pure_rust_locales::csb_PL::$($item)::+), + "nl_NL" => Ok(pure_rust_locales::nl_NL::$($item)::+), + "en_NZ" => Ok(pure_rust_locales::en_NZ::$($item)::+), + "nn_NO" => Ok(pure_rust_locales::nn_NO::$($item)::+), + "ar_SA" => Ok(pure_rust_locales::ar_SA::$($item)::+), + "bi_VU" => Ok(pure_rust_locales::bi_VU::$($item)::+), + "gl_ES" => Ok(pure_rust_locales::gl_ES::$($item)::+), + "dsb_DE" => Ok(pure_rust_locales::dsb_DE::$($item)::+), + "es_ES" => Ok(pure_rust_locales::es_ES::$($item)::+), + "nhn_MX" => Ok(pure_rust_locales::nhn_MX::$($item)::+), + "es_MX" => Ok(pure_rust_locales::es_MX::$($item)::+), + "miq_NI" => Ok(pure_rust_locales::miq_NI::$($item)::+), + "de_DE_euro" => Ok(pure_rust_locales::de_DE_euro::$($item)::+), + "zh_SG" => Ok(pure_rust_locales::zh_SG::$($item)::+), + "aa_ET" => Ok(pure_rust_locales::aa_ET::$($item)::+), + "tpi_PG" => Ok(pure_rust_locales::tpi_PG::$($item)::+), + "zu_ZA" => Ok(pure_rust_locales::zu_ZA::$($item)::+), + "fil_PH" => Ok(pure_rust_locales::fil_PH::$($item)::+), + "an_ES" => Ok(pure_rust_locales::an_ES::$($item)::+), + "raj_IN" => Ok(pure_rust_locales::raj_IN::$($item)::+), + "ga_IE_euro" => Ok(pure_rust_locales::ga_IE_euro::$($item)::+), + "es_HN" => Ok(pure_rust_locales::es_HN::$($item)::+), + "mai_IN" => Ok(pure_rust_locales::mai_IN::$($item)::+), + "es_NI" => Ok(pure_rust_locales::es_NI::$($item)::+), + "sat_IN" => Ok(pure_rust_locales::sat_IN::$($item)::+), + "km_KH" => Ok(pure_rust_locales::km_KH::$($item)::+), + "as_IN" => Ok(pure_rust_locales::as_IN::$($item)::+), + "en_PH" => Ok(pure_rust_locales::en_PH::$($item)::+), + "ss_ZA" => Ok(pure_rust_locales::ss_ZA::$($item)::+), + "eu_ES" => Ok(pure_rust_locales::eu_ES::$($item)::+), + "es_GT" => Ok(pure_rust_locales::es_GT::$($item)::+), + "sr_ME" => Ok(pure_rust_locales::sr_ME::$($item)::+), + "es_UY" => Ok(pure_rust_locales::es_UY::$($item)::+), + "en_AU" => Ok(pure_rust_locales::en_AU::$($item)::+), + "es_AR" => Ok(pure_rust_locales::es_AR::$($item)::+), + "de_DE" => Ok(pure_rust_locales::de_DE::$($item)::+), + "fo_FO" => Ok(pure_rust_locales::fo_FO::$($item)::+), + "ca_IT" => Ok(pure_rust_locales::ca_IT::$($item)::+), + "aa_ER_saaho" => Ok(pure_rust_locales::aa_ER_saaho::$($item)::+), + "es_PA" => Ok(pure_rust_locales::es_PA::$($item)::+), + "ia_FR" => Ok(pure_rust_locales::ia_FR::$($item)::+), + "ky_KG" => Ok(pure_rust_locales::ky_KG::$($item)::+), + "mk_MK" => Ok(pure_rust_locales::mk_MK::$($item)::+), + "mn_MN" => Ok(pure_rust_locales::mn_MN::$($item)::+), + "ur_IN" => Ok(pure_rust_locales::ur_IN::$($item)::+), + "en_SG" => Ok(pure_rust_locales::en_SG::$($item)::+), + "wa_BE_euro" => Ok(pure_rust_locales::wa_BE_euro::$($item)::+), + "dv_MV" => Ok(pure_rust_locales::dv_MV::$($item)::+), + "de_LU" => Ok(pure_rust_locales::de_LU::$($item)::+), + "ht_HT" => Ok(pure_rust_locales::ht_HT::$($item)::+), + "szl_PL" => Ok(pure_rust_locales::szl_PL::$($item)::+), + "cy_GB" => Ok(pure_rust_locales::cy_GB::$($item)::+), + "to_TO" => Ok(pure_rust_locales::to_TO::$($item)::+), + "es_EC" => Ok(pure_rust_locales::es_EC::$($item)::+), + "ar_LB" => Ok(pure_rust_locales::ar_LB::$($item)::+), + "de_BE_euro" => Ok(pure_rust_locales::de_BE_euro::$($item)::+), + "de_CH" => Ok(pure_rust_locales::de_CH::$($item)::+), + "dz_BT" => Ok(pure_rust_locales::dz_BT::$($item)::+), + "en_HK" => Ok(pure_rust_locales::en_HK::$($item)::+), + "ce_RU" => Ok(pure_rust_locales::ce_RU::$($item)::+), + "gez_ET" => Ok(pure_rust_locales::gez_ET::$($item)::+), + "mag_IN" => Ok(pure_rust_locales::mag_IN::$($item)::+), + "az_AZ" => Ok(pure_rust_locales::az_AZ::$($item)::+), + "es_CL" => Ok(pure_rust_locales::es_CL::$($item)::+), + "sd_IN" => Ok(pure_rust_locales::sd_IN::$($item)::+), + "sr_RS_latin" => Ok(pure_rust_locales::sr_RS_latin::$($item)::+), + "lg_UG" => Ok(pure_rust_locales::lg_UG::$($item)::+), + "fr_BE_euro" => Ok(pure_rust_locales::fr_BE_euro::$($item)::+), + "ca_ES_valencia" => Ok(pure_rust_locales::ca_ES_valencia::$($item)::+), + "el_GR_euro" => Ok(pure_rust_locales::el_GR_euro::$($item)::+), + "pa_PK" => Ok(pure_rust_locales::pa_PK::$($item)::+), + "sa_IN" => Ok(pure_rust_locales::sa_IN::$($item)::+), + "so_ET" => Ok(pure_rust_locales::so_ET::$($item)::+), + "th_TH" => Ok(pure_rust_locales::th_TH::$($item)::+), + "hy_AM" => Ok(pure_rust_locales::hy_AM::$($item)::+), + "wo_SN" => Ok(pure_rust_locales::wo_SN::$($item)::+), + "my_MM" => Ok(pure_rust_locales::my_MM::$($item)::+), + "sk_SK" => Ok(pure_rust_locales::sk_SK::$($item)::+), + "es_SV" => Ok(pure_rust_locales::es_SV::$($item)::+), + "om_KE" => Ok(pure_rust_locales::om_KE::$($item)::+), + "ug_CN" => Ok(pure_rust_locales::ug_CN::$($item)::+), + "ve_ZA" => Ok(pure_rust_locales::ve_ZA::$($item)::+), + "xh_ZA" => Ok(pure_rust_locales::xh_ZA::$($item)::+), "fr_BE" => Ok(pure_rust_locales::fr_BE::$($item)::+), - // TODO: all the locales are available + "rw_RW" => Ok(pure_rust_locales::rw_RW::$($item)::+), + "ar_IN" => Ok(pure_rust_locales::ar_IN::$($item)::+), + "ayc_PE" => Ok(pure_rust_locales::ayc_PE::$($item)::+), + "hu_HU" => Ok(pure_rust_locales::hu_HU::$($item)::+), + "sid_ET" => Ok(pure_rust_locales::sid_ET::$($item)::+), + "de_IT" => Ok(pure_rust_locales::de_IT::$($item)::+), + "aa_ER" => Ok(pure_rust_locales::aa_ER::$($item)::+), + "en_DK" => Ok(pure_rust_locales::en_DK::$($item)::+), + "cmn_TW" => Ok(pure_rust_locales::cmn_TW::$($item)::+), + "ar_LY" => Ok(pure_rust_locales::ar_LY::$($item)::+), + "gd_GB" => Ok(pure_rust_locales::gd_GB::$($item)::+), + "ar_TN" => Ok(pure_rust_locales::ar_TN::$($item)::+), + "be_BY" => Ok(pure_rust_locales::be_BY::$($item)::+), + "de_BE" => Ok(pure_rust_locales::de_BE::$($item)::+), + "ru_RU" => Ok(pure_rust_locales::ru_RU::$($item)::+), + "byn_ER" => Ok(pure_rust_locales::byn_ER::$($item)::+), + "az_IR" => Ok(pure_rust_locales::az_IR::$($item)::+), + "it_IT_euro" => Ok(pure_rust_locales::it_IT_euro::$($item)::+), + "fr_FR" => Ok(pure_rust_locales::fr_FR::$($item)::+), + "ar_BH" => Ok(pure_rust_locales::ar_BH::$($item)::+), + "ha_NG" => Ok(pure_rust_locales::ha_NG::$($item)::+), + "ar_JO" => Ok(pure_rust_locales::ar_JO::$($item)::+), + "wae_CH" => Ok(pure_rust_locales::wae_CH::$($item)::+), + "iu_CA" => Ok(pure_rust_locales::iu_CA::$($item)::+), + "ar_DZ" => Ok(pure_rust_locales::ar_DZ::$($item)::+), + "am_ET" => Ok(pure_rust_locales::am_ET::$($item)::+), + "mni_IN" => Ok(pure_rust_locales::mni_IN::$($item)::+), + "ar_YE" => Ok(pure_rust_locales::ar_YE::$($item)::+), + "sm_WS" => Ok(pure_rust_locales::sm_WS::$($item)::+), + "en_IE_euro" => Ok(pure_rust_locales::en_IE_euro::$($item)::+), + "ber_DZ" => Ok(pure_rust_locales::ber_DZ::$($item)::+), + "es_CR" => Ok(pure_rust_locales::es_CR::$($item)::+), + "ga_IE" => Ok(pure_rust_locales::ga_IE::$($item)::+), + "pap_CW" => Ok(pure_rust_locales::pap_CW::$($item)::+), + "anp_IN" => Ok(pure_rust_locales::anp_IN::$($item)::+), + "es_CO" => Ok(pure_rust_locales::es_CO::$($item)::+), + "fi_FI" => Ok(pure_rust_locales::fi_FI::$($item)::+), + "ta_LK" => Ok(pure_rust_locales::ta_LK::$($item)::+), + "en_SC" => Ok(pure_rust_locales::en_SC::$($item)::+), + "en_ZM" => Ok(pure_rust_locales::en_ZM::$($item)::+), + "the_NP" => Ok(pure_rust_locales::the_NP::$($item)::+), + "sv_FI" => Ok(pure_rust_locales::sv_FI::$($item)::+), + "fy_DE" => Ok(pure_rust_locales::fy_DE::$($item)::+), + "ca_FR" => Ok(pure_rust_locales::ca_FR::$($item)::+), + "gu_IN" => Ok(pure_rust_locales::gu_IN::$($item)::+), + "fr_LU" => Ok(pure_rust_locales::fr_LU::$($item)::+), + "ik_CA" => Ok(pure_rust_locales::ik_CA::$($item)::+), + "ti_ET" => Ok(pure_rust_locales::ti_ET::$($item)::+), + "de_LU_euro" => Ok(pure_rust_locales::de_LU_euro::$($item)::+), + "tcy_IN" => Ok(pure_rust_locales::tcy_IN::$($item)::+), + "tt_RU_iqtelif" => Ok(pure_rust_locales::tt_RU_iqtelif::$($item)::+), + "lij_IT" => Ok(pure_rust_locales::lij_IT::$($item)::+), + "unm_US" => Ok(pure_rust_locales::unm_US::$($item)::+), + "pt_PT_euro" => Ok(pure_rust_locales::pt_PT_euro::$($item)::+), + "sw_KE" => Ok(pure_rust_locales::sw_KE::$($item)::+), + "es_DO" => Ok(pure_rust_locales::es_DO::$($item)::+), + "niu_NU" => Ok(pure_rust_locales::niu_NU::$($item)::+), + "fa_IR" => Ok(pure_rust_locales::fa_IR::$($item)::+), + "es_PE" => Ok(pure_rust_locales::es_PE::$($item)::+), + "es_CU" => Ok(pure_rust_locales::es_CU::$($item)::+), + "gez_ET_abegede" => Ok(pure_rust_locales::gez_ET_abegede::$($item)::+), + "bem_ZM" => Ok(pure_rust_locales::bem_ZM::$($item)::+), + "kl_GL" => Ok(pure_rust_locales::kl_GL::$($item)::+), + "lzh_TW" => Ok(pure_rust_locales::lzh_TW::$($item)::+), + "ts_ZA" => Ok(pure_rust_locales::ts_ZA::$($item)::+), + "li_NL" => Ok(pure_rust_locales::li_NL::$($item)::+), + "cs_CZ" => Ok(pure_rust_locales::cs_CZ::$($item)::+), + "it_CH" => Ok(pure_rust_locales::it_CH::$($item)::+), + "en_ZW" => Ok(pure_rust_locales::en_ZW::$($item)::+), + "hsb_DE" => Ok(pure_rust_locales::hsb_DE::$($item)::+), + "mjw_IN" => Ok(pure_rust_locales::mjw_IN::$($item)::+), + "is_IS" => Ok(pure_rust_locales::is_IS::$($item)::+), + "he_IL" => Ok(pure_rust_locales::he_IL::$($item)::+), + "oc_FR" => Ok(pure_rust_locales::oc_FR::$($item)::+), + "et_EE" => Ok(pure_rust_locales::et_EE::$($item)::+), + "pt_BR" => Ok(pure_rust_locales::pt_BR::$($item)::+), + "os_RU" => Ok(pure_rust_locales::os_RU::$($item)::+), + "br_FR_euro" => Ok(pure_rust_locales::br_FR_euro::$($item)::+), + "es_PY" => Ok(pure_rust_locales::es_PY::$($item)::+), + "ta_IN" => Ok(pure_rust_locales::ta_IN::$($item)::+), + "es_ES_euro" => Ok(pure_rust_locales::es_ES_euro::$($item)::+), + "doi_IN" => Ok(pure_rust_locales::doi_IN::$($item)::+), + "eu_ES_euro" => Ok(pure_rust_locales::eu_ES_euro::$($item)::+), + "sq_MK" => Ok(pure_rust_locales::sq_MK::$($item)::+), + "gl_ES_euro" => Ok(pure_rust_locales::gl_ES_euro::$($item)::+), + "nl_NL_euro" => Ok(pure_rust_locales::nl_NL_euro::$($item)::+), + "ar_SS" => Ok(pure_rust_locales::ar_SS::$($item)::+), + "ca_ES_euro" => Ok(pure_rust_locales::ca_ES_euro::$($item)::+), + "bhb_IN" => Ok(pure_rust_locales::bhb_IN::$($item)::+), + "mnw_MM" => Ok(pure_rust_locales::mnw_MM::$($item)::+), + "mg_MG" => Ok(pure_rust_locales::mg_MG::$($item)::+), + "bg_BG" => Ok(pure_rust_locales::bg_BG::$($item)::+), + "nb_NO" => Ok(pure_rust_locales::nb_NO::$($item)::+), + "ru_UA" => Ok(pure_rust_locales::ru_UA::$($item)::+), + "ar_IQ" => Ok(pure_rust_locales::ar_IQ::$($item)::+), + "bho_IN" => Ok(pure_rust_locales::bho_IN::$($item)::+), + "chr_US" => Ok(pure_rust_locales::chr_US::$($item)::+), + "li_BE" => Ok(pure_rust_locales::li_BE::$($item)::+), + "zh_TW" => Ok(pure_rust_locales::zh_TW::$($item)::+), + "tt_RU" => Ok(pure_rust_locales::tt_RU::$($item)::+), + "mt_MT" => Ok(pure_rust_locales::mt_MT::$($item)::+), + "nds_DE" => Ok(pure_rust_locales::nds_DE::$($item)::+), + "es_BO" => Ok(pure_rust_locales::es_BO::$($item)::+), + "hi_IN" => Ok(pure_rust_locales::hi_IN::$($item)::+), + "ti_ER" => Ok(pure_rust_locales::ti_ER::$($item)::+), + "da_DK" => Ok(pure_rust_locales::da_DK::$($item)::+), + "tr_CY" => Ok(pure_rust_locales::tr_CY::$($item)::+), + "ar_QA" => Ok(pure_rust_locales::ar_QA::$($item)::+), + "lt_LT" => Ok(pure_rust_locales::lt_LT::$($item)::+), + "en_NG" => Ok(pure_rust_locales::en_NG::$($item)::+), + "ks_IN" => Ok(pure_rust_locales::ks_IN::$($item)::+), + "zh_CN" => Ok(pure_rust_locales::zh_CN::$($item)::+), + "mr_IN" => Ok(pure_rust_locales::mr_IN::$($item)::+), + "kab_DZ" => Ok(pure_rust_locales::kab_DZ::$($item)::+), + "si_LK" => Ok(pure_rust_locales::si_LK::$($item)::+), + "pt_PT" => Ok(pure_rust_locales::pt_PT::$($item)::+), + "tig_ER" => Ok(pure_rust_locales::tig_ER::$($item)::+), + "ar_AE" => Ok(pure_rust_locales::ar_AE::$($item)::+), + "yuw_PG" => Ok(pure_rust_locales::yuw_PG::$($item)::+), + "ar_OM" => Ok(pure_rust_locales::ar_OM::$($item)::+), + "en_CA" => Ok(pure_rust_locales::en_CA::$($item)::+), + "fr_FR_euro" => Ok(pure_rust_locales::fr_FR_euro::$($item)::+), + "hak_TW" => Ok(pure_rust_locales::hak_TW::$($item)::+), + "lo_LA" => Ok(pure_rust_locales::lo_LA::$($item)::+), + "sq_AL" => Ok(pure_rust_locales::sq_AL::$($item)::+), + "tg_TJ" => Ok(pure_rust_locales::tg_TJ::$($item)::+), + "bo_IN" => Ok(pure_rust_locales::bo_IN::$($item)::+), + "pap_AW" => Ok(pure_rust_locales::pap_AW::$($item)::+), + "br_FR" => Ok(pure_rust_locales::br_FR::$($item)::+), + "en_GB" => Ok(pure_rust_locales::en_GB::$($item)::+), + "ja_JP" => Ok(pure_rust_locales::ja_JP::$($item)::+), + "sc_IT" => Ok(pure_rust_locales::sc_IT::$($item)::+), + "lb_LU" => Ok(pure_rust_locales::lb_LU::$($item)::+), + "quz_PE" => Ok(pure_rust_locales::quz_PE::$($item)::+), + "ne_NP" => Ok(pure_rust_locales::ne_NP::$($item)::+), + "fr_CH" => Ok(pure_rust_locales::fr_CH::$($item)::+), + "om_ET" => Ok(pure_rust_locales::om_ET::$($item)::+), + "so_KE" => Ok(pure_rust_locales::so_KE::$($item)::+), + "vi_VN" => Ok(pure_rust_locales::vi_VN::$($item)::+), + "kn_IN" => Ok(pure_rust_locales::kn_IN::$($item)::+), + "en_BW" => Ok(pure_rust_locales::en_BW::$($item)::+), + "bs_BA" => Ok(pure_rust_locales::bs_BA::$($item)::+), + "hr_HR" => Ok(pure_rust_locales::hr_HR::$($item)::+), + "ro_RO" => Ok(pure_rust_locales::ro_RO::$($item)::+), + "ks_IN_devanagari" => Ok(pure_rust_locales::ks_IN_devanagari::$($item)::+), + "en_IE" => Ok(pure_rust_locales::en_IE::$($item)::+), + "nso_ZA" => Ok(pure_rust_locales::nso_ZA::$($item)::+), + "hne_IN" => Ok(pure_rust_locales::hne_IN::$($item)::+), + "id_ID" => Ok(pure_rust_locales::id_ID::$($item)::+), + "shs_CA" => Ok(pure_rust_locales::shs_CA::$($item)::+), + "ku_TR" => Ok(pure_rust_locales::ku_TR::$($item)::+), + "el_CY" => Ok(pure_rust_locales::el_CY::$($item)::+), + "tk_TM" => Ok(pure_rust_locales::tk_TM::$($item)::+), + "es_PR" => Ok(pure_rust_locales::es_PR::$($item)::+), + "sr_RS" => Ok(pure_rust_locales::sr_RS::$($item)::+), + "en_IL" => Ok(pure_rust_locales::en_IL::$($item)::+), + "ml_IN" => Ok(pure_rust_locales::ml_IN::$($item)::+), + "ar_MA" => Ok(pure_rust_locales::ar_MA::$($item)::+), + "nan_TW" => Ok(pure_rust_locales::nan_TW::$($item)::+), + "de_AT_euro" => Ok(pure_rust_locales::de_AT_euro::$($item)::+), _ => Err(FormatError(FormatErrorKind::UnknownLocale)), } }} From 26f3c77710132cb7df11d85a6b1bdd4848cb071d Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 17 Jul 2020 20:38:31 +0200 Subject: [PATCH 17/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/mod.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/format/mod.rs b/src/format/mod.rs index fa84ccf649..ee44104a08 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -802,7 +802,7 @@ impl<'a, I: Iterator + Clone, B: Borrow>> fmt::Display for De /// A *temporary* object which can be used as an argument to `format!` or others. /// This is normally constructed via `format` methods of each date and time type. -#[cfg(any(feature = "alloc", feature = "std", test))] +#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] #[derive(Debug)] pub struct DelayedFormatLocalized<'a, I> { /// The date view, if any. @@ -817,9 +817,9 @@ pub struct DelayedFormatLocalized<'a, I> { locale: &'a str, } -#[cfg(any(feature = "alloc", feature = "std", test))] +#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] impl<'a, 'b, I: Iterator + Clone, B: Borrow>> DelayedFormatLocalized<'b, I> { - /// Makes a new `DelayedFormat` value out of local date and time. + /// Makes a new `DelayedFormatLocalized` value out of local date and time. pub fn new( date: Option, time: Option, @@ -835,7 +835,7 @@ impl<'a, 'b, I: Iterator + Clone, B: Borrow>> DelayedFormatLo } } - /// Makes a new `DelayedFormat` value out of local date and time and UTC offset. + /// Makes a new `DelayedFormatLocalized` value out of local date and time and UTC offset. pub fn new_with_offset( date: Option, time: Option, @@ -857,7 +857,7 @@ impl<'a, 'b, I: Iterator + Clone, B: Borrow>> DelayedFormatLo } } -#[cfg(any(feature = "alloc", feature = "std", test))] +#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] impl<'a, 'b, I: Iterator + Clone, B: Borrow>> fmt::Display for DelayedFormatLocalized<'b, I> { @@ -913,7 +913,7 @@ impl FromStr for Weekday { } /// Formats single formatting item -#[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] +#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] pub fn format_item_localized<'a>( w: &mut fmt::Formatter, date: Option<&NaiveDate>, @@ -930,7 +930,7 @@ pub fn format_item_localized<'a>( /// Tries to format given arguments with given formatting items. /// Internally used by `DelayedFormat`. -#[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] +#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] pub fn format_localized<'a, I, B>( w: &mut fmt::Formatter, date: Option<&NaiveDate>, From a65a2b3a8bf244213bcb8d47ba1851477a934235 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 17 Jul 2020 20:43:01 +0200 Subject: [PATCH 18/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/date.rs | 8 ++++---- src/datetime.rs | 8 ++++---- src/lib.rs | 2 +- 3 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/date.rs b/src/date.rs index fbdd2388fb..0486f8fdee 100644 --- a/src/date.rs +++ b/src/date.rs @@ -298,8 +298,8 @@ where self.format_with_items(StrftimeItems::new(fmt)) } - /// Formats the date with the specified formatting items. - #[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] + /// Formats the date with the specified formatting items and locale. + #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] #[inline] pub fn format_localized_with_items<'a, 'b, I, B>( &self, @@ -319,10 +319,10 @@ where ) } - /// Formats the date with the specified format string. + /// Formats the date with the specified format string and locale. /// See the [`format::strftime` module](./format/strftime/index.html) /// on the supported escape sequences. - #[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] + #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] #[inline] pub fn format_localized<'a, 'b>( &self, diff --git a/src/datetime.rs b/src/datetime.rs index 9964bb2661..99b9aa1254 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -496,8 +496,8 @@ where self.format_with_items(StrftimeItems::new(fmt)) } - /// Formats the combined date and time with the specified formatting items. - #[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] + /// Formats the combined date and time with the specified formatting items and locale. + #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] #[inline] pub fn format_localized_with_items<'a, 'b, I, B>( &self, @@ -518,10 +518,10 @@ where ) } - /// Formats the combined date and time with the specified format string. + /// Formats the combined date and time with the specified format string and locale. /// See the [`format::strftime` module](./format/strftime/index.html) /// on the supported escape sequences. - #[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] + #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] #[inline] pub fn format_localized<'a, 'b>( &self, diff --git a/src/lib.rs b/src/lib.rs index a8465f38e8..3b6d0abd29 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -435,7 +435,7 @@ extern crate serde as serdelib; extern crate doc_comment; #[cfg(all(target_arch = "wasm32", not(target_os = "wasi"), feature = "wasmbind"))] extern crate js_sys; -#[cfg(any(feature = "locales", test))] +#[cfg(feature = "locales")] extern crate pure_rust_locales; #[cfg(feature = "bench")] extern crate test; From e4f16d76e74b0f1941ff82a545084db68decd847 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 17 Jul 2020 20:47:17 +0200 Subject: [PATCH 19/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/locales.rs | 66 +++++++++++++++++++++---------------------- 1 file changed, 33 insertions(+), 33 deletions(-) diff --git a/src/format/locales.rs b/src/format/locales.rs index f23cdaee5f..5aae265526 100644 --- a/src/format/locales.rs +++ b/src/format/locales.rs @@ -10,7 +10,7 @@ macro_rules! locale_match { "ak_GH" => Ok(pure_rust_locales::ak_GH::$($item)::+), "ber_MA" => Ok(pure_rust_locales::ber_MA::$($item)::+), "aa_DJ" => Ok(pure_rust_locales::aa_DJ::$($item)::+), - "nl_BE_euro" => Ok(pure_rust_locales::nl_BE_euro::$($item)::+), + "nl_BE@euro" => Ok(pure_rust_locales::nl_BE_euro::$($item)::+), "pl_PL" => Ok(pure_rust_locales::pl_PL::$($item)::+), "ca_AD" => Ok(pure_rust_locales::ca_AD::$($item)::+), "so_SO" => Ok(pure_rust_locales::so_SO::$($item)::+), @@ -18,8 +18,8 @@ macro_rules! locale_match { "fur_IT" => Ok(pure_rust_locales::fur_IT::$($item)::+), "es_VE" => Ok(pure_rust_locales::es_VE::$($item)::+), "ast_ES" => Ok(pure_rust_locales::ast_ES::$($item)::+), - "sv_FI_euro" => Ok(pure_rust_locales::sv_FI_euro::$($item)::+), - "uz_UZ_cyrillic" => Ok(pure_rust_locales::uz_UZ_cyrillic::$($item)::+), + "sv_FI@euro" => Ok(pure_rust_locales::sv_FI_euro::$($item)::+), + "uz_UZ@cyrillic" => Ok(pure_rust_locales::uz_UZ_cyrillic::$($item)::+), "it_IT" => Ok(pure_rust_locales::it_IT::$($item)::+), "ca_ES" => Ok(pure_rust_locales::ca_ES::$($item)::+), "kk_KZ" => Ok(pure_rust_locales::kk_KZ::$($item)::+), @@ -29,7 +29,7 @@ macro_rules! locale_match { "eo" => Ok(pure_rust_locales::eo::$($item)::+), "se_NO" => Ok(pure_rust_locales::se_NO::$($item)::+), "tr_TR" => Ok(pure_rust_locales::tr_TR::$($item)::+), - "fr_LU_euro" => Ok(pure_rust_locales::fr_LU_euro::$($item)::+), + "fr_LU@euro" => Ok(pure_rust_locales::fr_LU_euro::$($item)::+), "pa_IN" => Ok(pure_rust_locales::pa_IN::$($item)::+), "af_ZA" => Ok(pure_rust_locales::af_ZA::$($item)::+), "es_US" => Ok(pure_rust_locales::es_US::$($item)::+), @@ -37,14 +37,14 @@ macro_rules! locale_match { "nl_AW" => Ok(pure_rust_locales::nl_AW::$($item)::+), "ko_KR" => Ok(pure_rust_locales::ko_KR::$($item)::+), "gez_ER" => Ok(pure_rust_locales::gez_ER::$($item)::+), - "sd_IN_devanagari" => Ok(pure_rust_locales::sd_IN_devanagari::$($item)::+), + "sd_IN@devanagari" => Ok(pure_rust_locales::sd_IN_devanagari::$($item)::+), "mhr_RU" => Ok(pure_rust_locales::mhr_RU::$($item)::+), "lv_LV" => Ok(pure_rust_locales::lv_LV::$($item)::+), "yo_NG" => Ok(pure_rust_locales::yo_NG::$($item)::+), "agr_PE" => Ok(pure_rust_locales::agr_PE::$($item)::+), "tn_ZA" => Ok(pure_rust_locales::tn_ZA::$($item)::+), "st_ZA" => Ok(pure_rust_locales::st_ZA::$($item)::+), - "be_BY_latin" => Ok(pure_rust_locales::be_BY_latin::$($item)::+), + "be_BY@latin" => Ok(pure_rust_locales::be_BY_latin::$($item)::+), "yue_HK" => Ok(pure_rust_locales::yue_HK::$($item)::+), "kok_IN" => Ok(pure_rust_locales::kok_IN::$($item)::+), "ur_PK" => Ok(pure_rust_locales::ur_PK::$($item)::+), @@ -70,7 +70,7 @@ macro_rules! locale_match { "or_IN" => Ok(pure_rust_locales::or_IN::$($item)::+), "mi_NZ" => Ok(pure_rust_locales::mi_NZ::$($item)::+), "en_AG" => Ok(pure_rust_locales::en_AG::$($item)::+), - "gez_ER_abegede" => Ok(pure_rust_locales::gez_ER_abegede::$($item)::+), + "gez_ER@abegede" => Ok(pure_rust_locales::gez_ER_abegede::$($item)::+), "uz_UZ" => Ok(pure_rust_locales::uz_UZ::$($item)::+), "ar_SY" => Ok(pure_rust_locales::ar_SY::$($item)::+), "wa_BE" => Ok(pure_rust_locales::wa_BE::$($item)::+), @@ -89,12 +89,12 @@ macro_rules! locale_match { "en_US" => Ok(pure_rust_locales::en_US::$($item)::+), "ar_KW" => Ok(pure_rust_locales::ar_KW::$($item)::+), "bn_IN" => Ok(pure_rust_locales::bn_IN::$($item)::+), - "fi_FI_euro" => Ok(pure_rust_locales::fi_FI_euro::$($item)::+), + "fi_FI@euro" => Ok(pure_rust_locales::fi_FI_euro::$($item)::+), "yi_US" => Ok(pure_rust_locales::yi_US::$($item)::+), "en_ZA" => Ok(pure_rust_locales::en_ZA::$($item)::+), "sgs_LT" => Ok(pure_rust_locales::sgs_LT::$($item)::+), "fy_NL" => Ok(pure_rust_locales::fy_NL::$($item)::+), - "nan_TW_latin" => Ok(pure_rust_locales::nan_TW_latin::$($item)::+), + "nan_TW@latin" => Ok(pure_rust_locales::nan_TW_latin::$($item)::+), "csb_PL" => Ok(pure_rust_locales::csb_PL::$($item)::+), "nl_NL" => Ok(pure_rust_locales::nl_NL::$($item)::+), "en_NZ" => Ok(pure_rust_locales::en_NZ::$($item)::+), @@ -107,7 +107,7 @@ macro_rules! locale_match { "nhn_MX" => Ok(pure_rust_locales::nhn_MX::$($item)::+), "es_MX" => Ok(pure_rust_locales::es_MX::$($item)::+), "miq_NI" => Ok(pure_rust_locales::miq_NI::$($item)::+), - "de_DE_euro" => Ok(pure_rust_locales::de_DE_euro::$($item)::+), + "de_DE@euro" => Ok(pure_rust_locales::de_DE_euro::$($item)::+), "zh_SG" => Ok(pure_rust_locales::zh_SG::$($item)::+), "aa_ET" => Ok(pure_rust_locales::aa_ET::$($item)::+), "tpi_PG" => Ok(pure_rust_locales::tpi_PG::$($item)::+), @@ -115,7 +115,7 @@ macro_rules! locale_match { "fil_PH" => Ok(pure_rust_locales::fil_PH::$($item)::+), "an_ES" => Ok(pure_rust_locales::an_ES::$($item)::+), "raj_IN" => Ok(pure_rust_locales::raj_IN::$($item)::+), - "ga_IE_euro" => Ok(pure_rust_locales::ga_IE_euro::$($item)::+), + "ga_IE@euro" => Ok(pure_rust_locales::ga_IE_euro::$($item)::+), "es_HN" => Ok(pure_rust_locales::es_HN::$($item)::+), "mai_IN" => Ok(pure_rust_locales::mai_IN::$($item)::+), "es_NI" => Ok(pure_rust_locales::es_NI::$($item)::+), @@ -133,7 +133,7 @@ macro_rules! locale_match { "de_DE" => Ok(pure_rust_locales::de_DE::$($item)::+), "fo_FO" => Ok(pure_rust_locales::fo_FO::$($item)::+), "ca_IT" => Ok(pure_rust_locales::ca_IT::$($item)::+), - "aa_ER_saaho" => Ok(pure_rust_locales::aa_ER_saaho::$($item)::+), + "aa_ER@saaho" => Ok(pure_rust_locales::aa_ER_saaho::$($item)::+), "es_PA" => Ok(pure_rust_locales::es_PA::$($item)::+), "ia_FR" => Ok(pure_rust_locales::ia_FR::$($item)::+), "ky_KG" => Ok(pure_rust_locales::ky_KG::$($item)::+), @@ -141,7 +141,7 @@ macro_rules! locale_match { "mn_MN" => Ok(pure_rust_locales::mn_MN::$($item)::+), "ur_IN" => Ok(pure_rust_locales::ur_IN::$($item)::+), "en_SG" => Ok(pure_rust_locales::en_SG::$($item)::+), - "wa_BE_euro" => Ok(pure_rust_locales::wa_BE_euro::$($item)::+), + "wa_BE@euro" => Ok(pure_rust_locales::wa_BE_euro::$($item)::+), "dv_MV" => Ok(pure_rust_locales::dv_MV::$($item)::+), "de_LU" => Ok(pure_rust_locales::de_LU::$($item)::+), "ht_HT" => Ok(pure_rust_locales::ht_HT::$($item)::+), @@ -150,7 +150,7 @@ macro_rules! locale_match { "to_TO" => Ok(pure_rust_locales::to_TO::$($item)::+), "es_EC" => Ok(pure_rust_locales::es_EC::$($item)::+), "ar_LB" => Ok(pure_rust_locales::ar_LB::$($item)::+), - "de_BE_euro" => Ok(pure_rust_locales::de_BE_euro::$($item)::+), + "de_BE@euro" => Ok(pure_rust_locales::de_BE_euro::$($item)::+), "de_CH" => Ok(pure_rust_locales::de_CH::$($item)::+), "dz_BT" => Ok(pure_rust_locales::dz_BT::$($item)::+), "en_HK" => Ok(pure_rust_locales::en_HK::$($item)::+), @@ -160,11 +160,11 @@ macro_rules! locale_match { "az_AZ" => Ok(pure_rust_locales::az_AZ::$($item)::+), "es_CL" => Ok(pure_rust_locales::es_CL::$($item)::+), "sd_IN" => Ok(pure_rust_locales::sd_IN::$($item)::+), - "sr_RS_latin" => Ok(pure_rust_locales::sr_RS_latin::$($item)::+), + "sr_RS@latin" => Ok(pure_rust_locales::sr_RS_latin::$($item)::+), "lg_UG" => Ok(pure_rust_locales::lg_UG::$($item)::+), - "fr_BE_euro" => Ok(pure_rust_locales::fr_BE_euro::$($item)::+), - "ca_ES_valencia" => Ok(pure_rust_locales::ca_ES_valencia::$($item)::+), - "el_GR_euro" => Ok(pure_rust_locales::el_GR_euro::$($item)::+), + "fr_BE@euro" => Ok(pure_rust_locales::fr_BE_euro::$($item)::+), + "ca_ES@valencia" => Ok(pure_rust_locales::ca_ES_valencia::$($item)::+), + "el_GR@euro" => Ok(pure_rust_locales::el_GR_euro::$($item)::+), "pa_PK" => Ok(pure_rust_locales::pa_PK::$($item)::+), "sa_IN" => Ok(pure_rust_locales::sa_IN::$($item)::+), "so_ET" => Ok(pure_rust_locales::so_ET::$($item)::+), @@ -196,7 +196,7 @@ macro_rules! locale_match { "ru_RU" => Ok(pure_rust_locales::ru_RU::$($item)::+), "byn_ER" => Ok(pure_rust_locales::byn_ER::$($item)::+), "az_IR" => Ok(pure_rust_locales::az_IR::$($item)::+), - "it_IT_euro" => Ok(pure_rust_locales::it_IT_euro::$($item)::+), + "it_IT@euro" => Ok(pure_rust_locales::it_IT_euro::$($item)::+), "fr_FR" => Ok(pure_rust_locales::fr_FR::$($item)::+), "ar_BH" => Ok(pure_rust_locales::ar_BH::$($item)::+), "ha_NG" => Ok(pure_rust_locales::ha_NG::$($item)::+), @@ -208,7 +208,7 @@ macro_rules! locale_match { "mni_IN" => Ok(pure_rust_locales::mni_IN::$($item)::+), "ar_YE" => Ok(pure_rust_locales::ar_YE::$($item)::+), "sm_WS" => Ok(pure_rust_locales::sm_WS::$($item)::+), - "en_IE_euro" => Ok(pure_rust_locales::en_IE_euro::$($item)::+), + "en_IE@euro" => Ok(pure_rust_locales::en_IE_euro::$($item)::+), "ber_DZ" => Ok(pure_rust_locales::ber_DZ::$($item)::+), "es_CR" => Ok(pure_rust_locales::es_CR::$($item)::+), "ga_IE" => Ok(pure_rust_locales::ga_IE::$($item)::+), @@ -227,19 +227,19 @@ macro_rules! locale_match { "fr_LU" => Ok(pure_rust_locales::fr_LU::$($item)::+), "ik_CA" => Ok(pure_rust_locales::ik_CA::$($item)::+), "ti_ET" => Ok(pure_rust_locales::ti_ET::$($item)::+), - "de_LU_euro" => Ok(pure_rust_locales::de_LU_euro::$($item)::+), + "de_LU@euro" => Ok(pure_rust_locales::de_LU_euro::$($item)::+), "tcy_IN" => Ok(pure_rust_locales::tcy_IN::$($item)::+), - "tt_RU_iqtelif" => Ok(pure_rust_locales::tt_RU_iqtelif::$($item)::+), + "tt_RU@iqtelif" => Ok(pure_rust_locales::tt_RU_iqtelif::$($item)::+), "lij_IT" => Ok(pure_rust_locales::lij_IT::$($item)::+), "unm_US" => Ok(pure_rust_locales::unm_US::$($item)::+), - "pt_PT_euro" => Ok(pure_rust_locales::pt_PT_euro::$($item)::+), + "pt_PT@euro" => Ok(pure_rust_locales::pt_PT_euro::$($item)::+), "sw_KE" => Ok(pure_rust_locales::sw_KE::$($item)::+), "es_DO" => Ok(pure_rust_locales::es_DO::$($item)::+), "niu_NU" => Ok(pure_rust_locales::niu_NU::$($item)::+), "fa_IR" => Ok(pure_rust_locales::fa_IR::$($item)::+), "es_PE" => Ok(pure_rust_locales::es_PE::$($item)::+), "es_CU" => Ok(pure_rust_locales::es_CU::$($item)::+), - "gez_ET_abegede" => Ok(pure_rust_locales::gez_ET_abegede::$($item)::+), + "gez_ET@abegede" => Ok(pure_rust_locales::gez_ET_abegede::$($item)::+), "bem_ZM" => Ok(pure_rust_locales::bem_ZM::$($item)::+), "kl_GL" => Ok(pure_rust_locales::kl_GL::$($item)::+), "lzh_TW" => Ok(pure_rust_locales::lzh_TW::$($item)::+), @@ -256,17 +256,17 @@ macro_rules! locale_match { "et_EE" => Ok(pure_rust_locales::et_EE::$($item)::+), "pt_BR" => Ok(pure_rust_locales::pt_BR::$($item)::+), "os_RU" => Ok(pure_rust_locales::os_RU::$($item)::+), - "br_FR_euro" => Ok(pure_rust_locales::br_FR_euro::$($item)::+), + "br_FR@euro" => Ok(pure_rust_locales::br_FR_euro::$($item)::+), "es_PY" => Ok(pure_rust_locales::es_PY::$($item)::+), "ta_IN" => Ok(pure_rust_locales::ta_IN::$($item)::+), - "es_ES_euro" => Ok(pure_rust_locales::es_ES_euro::$($item)::+), + "es_ES@euro" => Ok(pure_rust_locales::es_ES_euro::$($item)::+), "doi_IN" => Ok(pure_rust_locales::doi_IN::$($item)::+), - "eu_ES_euro" => Ok(pure_rust_locales::eu_ES_euro::$($item)::+), + "eu_ES@euro" => Ok(pure_rust_locales::eu_ES_euro::$($item)::+), "sq_MK" => Ok(pure_rust_locales::sq_MK::$($item)::+), - "gl_ES_euro" => Ok(pure_rust_locales::gl_ES_euro::$($item)::+), - "nl_NL_euro" => Ok(pure_rust_locales::nl_NL_euro::$($item)::+), + "gl_ES@euro" => Ok(pure_rust_locales::gl_ES_euro::$($item)::+), + "nl_NL@euro" => Ok(pure_rust_locales::nl_NL_euro::$($item)::+), "ar_SS" => Ok(pure_rust_locales::ar_SS::$($item)::+), - "ca_ES_euro" => Ok(pure_rust_locales::ca_ES_euro::$($item)::+), + "ca_ES@euro" => Ok(pure_rust_locales::ca_ES_euro::$($item)::+), "bhb_IN" => Ok(pure_rust_locales::bhb_IN::$($item)::+), "mnw_MM" => Ok(pure_rust_locales::mnw_MM::$($item)::+), "mg_MG" => Ok(pure_rust_locales::mg_MG::$($item)::+), @@ -300,7 +300,7 @@ macro_rules! locale_match { "yuw_PG" => Ok(pure_rust_locales::yuw_PG::$($item)::+), "ar_OM" => Ok(pure_rust_locales::ar_OM::$($item)::+), "en_CA" => Ok(pure_rust_locales::en_CA::$($item)::+), - "fr_FR_euro" => Ok(pure_rust_locales::fr_FR_euro::$($item)::+), + "fr_FR@euro" => Ok(pure_rust_locales::fr_FR_euro::$($item)::+), "hak_TW" => Ok(pure_rust_locales::hak_TW::$($item)::+), "lo_LA" => Ok(pure_rust_locales::lo_LA::$($item)::+), "sq_AL" => Ok(pure_rust_locales::sq_AL::$($item)::+), @@ -323,7 +323,7 @@ macro_rules! locale_match { "bs_BA" => Ok(pure_rust_locales::bs_BA::$($item)::+), "hr_HR" => Ok(pure_rust_locales::hr_HR::$($item)::+), "ro_RO" => Ok(pure_rust_locales::ro_RO::$($item)::+), - "ks_IN_devanagari" => Ok(pure_rust_locales::ks_IN_devanagari::$($item)::+), + "ks_IN@devanagari" => Ok(pure_rust_locales::ks_IN_devanagari::$($item)::+), "en_IE" => Ok(pure_rust_locales::en_IE::$($item)::+), "nso_ZA" => Ok(pure_rust_locales::nso_ZA::$($item)::+), "hne_IN" => Ok(pure_rust_locales::hne_IN::$($item)::+), @@ -338,7 +338,7 @@ macro_rules! locale_match { "ml_IN" => Ok(pure_rust_locales::ml_IN::$($item)::+), "ar_MA" => Ok(pure_rust_locales::ar_MA::$($item)::+), "nan_TW" => Ok(pure_rust_locales::nan_TW::$($item)::+), - "de_AT_euro" => Ok(pure_rust_locales::de_AT_euro::$($item)::+), + "de_AT@euro" => Ok(pure_rust_locales::de_AT_euro::$($item)::+), _ => Err(FormatError(FormatErrorKind::UnknownLocale)), } }} From f32e4f25ae04a8845a949b7ef5c1426038f9f622 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 17 Jul 2020 20:54:16 +0200 Subject: [PATCH 20/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/date.rs | 2 +- src/datetime.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/date.rs b/src/date.rs index 0486f8fdee..c8970d661d 100644 --- a/src/date.rs +++ b/src/date.rs @@ -10,7 +10,7 @@ use core::ops::{Add, Sub}; use core::{fmt, hash}; use oldtime::Duration as OldDuration; -#[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] +#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] use format::DelayedFormatLocalized; #[cfg(any(feature = "alloc", feature = "std", test))] use format::{DelayedFormat, Item, StrftimeItems}; diff --git a/src/datetime.rs b/src/datetime.rs index 99b9aa1254..83c797f4af 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -19,7 +19,7 @@ use std::string::ToString; use core::borrow::Borrow; #[cfg(any(feature = "alloc", feature = "std", test))] use format::DelayedFormat; -#[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std")), test))] +#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] use format::DelayedFormatLocalized; use format::{parse, ParseError, ParseResult, Parsed, StrftimeItems}; use format::{Fixed, Item}; From ee0853bc6a8ae0848e9b1d0439be17e0e5a03f64 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 17 Jul 2020 22:35:10 +0200 Subject: [PATCH 21/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- Cargo.toml | 2 +- src/date.rs | 14 +- src/datetime.rs | 14 +- src/format/locales.rs | 354 +---------------------------------------- src/format/mod.rs | 117 ++++---------- src/format/strftime.rs | 121 +++++++------- src/lib.rs | 2 - 7 files changed, 112 insertions(+), 512 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index a5a50bc936..666990fbec 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -39,7 +39,7 @@ num-integer = { version = "0.1.36", default-features = false } num-traits = { version = "0.2", default-features = false } rustc-serialize = { version = "0.3.20", optional = true } serde = { version = "1.0.99", default-features = false, optional = true } -pure-rust-locales = { version = "0.3.0", optional = true } +pure-rust-locales = { version = "0.5.2", optional = true } [target.'cfg(all(target_arch = "wasm32", not(any(target_os = "emscripten", target_os = "wasi"))))'.dependencies] wasm-bindgen = { version = "0.2", optional = true } diff --git a/src/date.rs b/src/date.rs index c8970d661d..d6d2f544d9 100644 --- a/src/date.rs +++ b/src/date.rs @@ -11,7 +11,7 @@ use core::{fmt, hash}; use oldtime::Duration as OldDuration; #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] -use format::DelayedFormatLocalized; +use format::{DelayedFormatLocalized, Locale}; #[cfg(any(feature = "alloc", feature = "std", test))] use format::{DelayedFormat, Item, StrftimeItems}; use naive::{self, IsoWeek, NaiveDate, NaiveTime}; @@ -301,11 +301,11 @@ where /// Formats the date with the specified formatting items and locale. #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] #[inline] - pub fn format_localized_with_items<'a, 'b, I, B>( + pub fn format_localized_with_items<'a, I, B>( &self, items: I, - locale: &'b str, - ) -> DelayedFormatLocalized<'b, I> + locale: Locale, + ) -> DelayedFormatLocalized where I: Iterator + Clone, B: Borrow>, @@ -324,11 +324,11 @@ where /// on the supported escape sequences. #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] #[inline] - pub fn format_localized<'a, 'b>( + pub fn format_localized<'a>( &self, fmt: &'a str, - locale: &'b str, - ) -> DelayedFormatLocalized<'b, StrftimeItems<'a>> { + locale: Locale, + ) -> DelayedFormatLocalized> { self.format_localized_with_items(StrftimeItems::new(fmt), locale) } } diff --git a/src/datetime.rs b/src/datetime.rs index 83c797f4af..e923d35cb2 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -20,7 +20,7 @@ use core::borrow::Borrow; #[cfg(any(feature = "alloc", feature = "std", test))] use format::DelayedFormat; #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] -use format::DelayedFormatLocalized; +use format::{DelayedFormatLocalized, Locale}; use format::{parse, ParseError, ParseResult, Parsed, StrftimeItems}; use format::{Fixed, Item}; use naive::{self, IsoWeek, NaiveDateTime, NaiveTime}; @@ -499,11 +499,11 @@ where /// Formats the combined date and time with the specified formatting items and locale. #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] #[inline] - pub fn format_localized_with_items<'a, 'b, I, B>( + pub fn format_localized_with_items<'a, I, B>( &self, items: I, - locale: &'b str, - ) -> DelayedFormatLocalized<'b, I> + locale: Locale, + ) -> DelayedFormatLocalized where I: Iterator + Clone, B: Borrow>, @@ -523,11 +523,11 @@ where /// on the supported escape sequences. #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] #[inline] - pub fn format_localized<'a, 'b>( + pub fn format_localized<'a>( &self, fmt: &'a str, - locale: &'b str, - ) -> DelayedFormatLocalized<'b, StrftimeItems<'a>> { + locale: Locale, + ) -> DelayedFormatLocalized> { self.format_localized_with_items(StrftimeItems::new(fmt), locale) } } diff --git a/src/format/locales.rs b/src/format/locales.rs index 5aae265526..cc4910b866 100644 --- a/src/format/locales.rs +++ b/src/format/locales.rs @@ -1,361 +1,17 @@ -use super::{FormatError, FormatErrorKind, FormatResult}; +use pure_rust_locales::{locale_match, Locale}; -macro_rules! locale_match { - ($locale:expr => $($item:ident)::+) => {{ - match $locale { - "cv_RU" => Ok(pure_rust_locales::cv_RU::$($item)::+), - "so_DJ" => Ok(pure_rust_locales::so_DJ::$($item)::+), - "ln_CD" => Ok(pure_rust_locales::ln_CD::$($item)::+), - "sah_RU" => Ok(pure_rust_locales::sah_RU::$($item)::+), - "ak_GH" => Ok(pure_rust_locales::ak_GH::$($item)::+), - "ber_MA" => Ok(pure_rust_locales::ber_MA::$($item)::+), - "aa_DJ" => Ok(pure_rust_locales::aa_DJ::$($item)::+), - "nl_BE@euro" => Ok(pure_rust_locales::nl_BE_euro::$($item)::+), - "pl_PL" => Ok(pure_rust_locales::pl_PL::$($item)::+), - "ca_AD" => Ok(pure_rust_locales::ca_AD::$($item)::+), - "so_SO" => Ok(pure_rust_locales::so_SO::$($item)::+), - "de_LI" => Ok(pure_rust_locales::de_LI::$($item)::+), - "fur_IT" => Ok(pure_rust_locales::fur_IT::$($item)::+), - "es_VE" => Ok(pure_rust_locales::es_VE::$($item)::+), - "ast_ES" => Ok(pure_rust_locales::ast_ES::$($item)::+), - "sv_FI@euro" => Ok(pure_rust_locales::sv_FI_euro::$($item)::+), - "uz_UZ@cyrillic" => Ok(pure_rust_locales::uz_UZ_cyrillic::$($item)::+), - "it_IT" => Ok(pure_rust_locales::it_IT::$($item)::+), - "ca_ES" => Ok(pure_rust_locales::ca_ES::$($item)::+), - "kk_KZ" => Ok(pure_rust_locales::kk_KZ::$($item)::+), - "ms_MY" => Ok(pure_rust_locales::ms_MY::$($item)::+), - "ig_NG" => Ok(pure_rust_locales::ig_NG::$($item)::+), - "mai_NP" => Ok(pure_rust_locales::mai_NP::$($item)::+), - "eo" => Ok(pure_rust_locales::eo::$($item)::+), - "se_NO" => Ok(pure_rust_locales::se_NO::$($item)::+), - "tr_TR" => Ok(pure_rust_locales::tr_TR::$($item)::+), - "fr_LU@euro" => Ok(pure_rust_locales::fr_LU_euro::$($item)::+), - "pa_IN" => Ok(pure_rust_locales::pa_IN::$($item)::+), - "af_ZA" => Ok(pure_rust_locales::af_ZA::$($item)::+), - "es_US" => Ok(pure_rust_locales::es_US::$($item)::+), - "gv_GB" => Ok(pure_rust_locales::gv_GB::$($item)::+), - "nl_AW" => Ok(pure_rust_locales::nl_AW::$($item)::+), - "ko_KR" => Ok(pure_rust_locales::ko_KR::$($item)::+), - "gez_ER" => Ok(pure_rust_locales::gez_ER::$($item)::+), - "sd_IN@devanagari" => Ok(pure_rust_locales::sd_IN_devanagari::$($item)::+), - "mhr_RU" => Ok(pure_rust_locales::mhr_RU::$($item)::+), - "lv_LV" => Ok(pure_rust_locales::lv_LV::$($item)::+), - "yo_NG" => Ok(pure_rust_locales::yo_NG::$($item)::+), - "agr_PE" => Ok(pure_rust_locales::agr_PE::$($item)::+), - "tn_ZA" => Ok(pure_rust_locales::tn_ZA::$($item)::+), - "st_ZA" => Ok(pure_rust_locales::st_ZA::$($item)::+), - "be_BY@latin" => Ok(pure_rust_locales::be_BY_latin::$($item)::+), - "yue_HK" => Ok(pure_rust_locales::yue_HK::$($item)::+), - "kok_IN" => Ok(pure_rust_locales::kok_IN::$($item)::+), - "ur_PK" => Ok(pure_rust_locales::ur_PK::$($item)::+), - "crh_UA" => Ok(pure_rust_locales::crh_UA::$($item)::+), - "sw_TZ" => Ok(pure_rust_locales::sw_TZ::$($item)::+), - "sv_SE" => Ok(pure_rust_locales::sv_SE::$($item)::+), - "ka_GE" => Ok(pure_rust_locales::ka_GE::$($item)::+), - "ar_EG" => Ok(pure_rust_locales::ar_EG::$($item)::+), - "uk_UA" => Ok(pure_rust_locales::uk_UA::$($item)::+), - "ar_SD" => Ok(pure_rust_locales::ar_SD::$($item)::+), - "en_IN" => Ok(pure_rust_locales::en_IN::$($item)::+), - "bho_NP" => Ok(pure_rust_locales::bho_NP::$($item)::+), - "kw_GB" => Ok(pure_rust_locales::kw_GB::$($item)::+), - "mfe_MU" => Ok(pure_rust_locales::mfe_MU::$($item)::+), - "nl_BE" => Ok(pure_rust_locales::nl_BE::$($item)::+), - "shn_MM" => Ok(pure_rust_locales::shn_MM::$($item)::+), - "ps_AF" => Ok(pure_rust_locales::ps_AF::$($item)::+), - "nr_ZA" => Ok(pure_rust_locales::nr_ZA::$($item)::+), - "el_GR" => Ok(pure_rust_locales::el_GR::$($item)::+), - "nds_NL" => Ok(pure_rust_locales::nds_NL::$($item)::+), - "sl_SI" => Ok(pure_rust_locales::sl_SI::$($item)::+), - "tl_PH" => Ok(pure_rust_locales::tl_PH::$($item)::+), - "or_IN" => Ok(pure_rust_locales::or_IN::$($item)::+), - "mi_NZ" => Ok(pure_rust_locales::mi_NZ::$($item)::+), - "en_AG" => Ok(pure_rust_locales::en_AG::$($item)::+), - "gez_ER@abegede" => Ok(pure_rust_locales::gez_ER_abegede::$($item)::+), - "uz_UZ" => Ok(pure_rust_locales::uz_UZ::$($item)::+), - "ar_SY" => Ok(pure_rust_locales::ar_SY::$($item)::+), - "wa_BE" => Ok(pure_rust_locales::wa_BE::$($item)::+), - "bn_BD" => Ok(pure_rust_locales::bn_BD::$($item)::+), - "bo_CN" => Ok(pure_rust_locales::bo_CN::$($item)::+), - "te_IN" => Ok(pure_rust_locales::te_IN::$($item)::+), - "zh_HK" => Ok(pure_rust_locales::zh_HK::$($item)::+), - "wal_ET" => Ok(pure_rust_locales::wal_ET::$($item)::+), - "ff_SN" => Ok(pure_rust_locales::ff_SN::$($item)::+), - "brx_IN" => Ok(pure_rust_locales::brx_IN::$($item)::+), - "de_AT" => Ok(pure_rust_locales::de_AT::$($item)::+), - "fr_CA" => Ok(pure_rust_locales::fr_CA::$($item)::+), - "hif_FJ" => Ok(pure_rust_locales::hif_FJ::$($item)::+), - "niu_NZ" => Ok(pure_rust_locales::niu_NZ::$($item)::+), - "POSIX" => Ok(pure_rust_locales::POSIX::$($item)::+), - "en_US" => Ok(pure_rust_locales::en_US::$($item)::+), - "ar_KW" => Ok(pure_rust_locales::ar_KW::$($item)::+), - "bn_IN" => Ok(pure_rust_locales::bn_IN::$($item)::+), - "fi_FI@euro" => Ok(pure_rust_locales::fi_FI_euro::$($item)::+), - "yi_US" => Ok(pure_rust_locales::yi_US::$($item)::+), - "en_ZA" => Ok(pure_rust_locales::en_ZA::$($item)::+), - "sgs_LT" => Ok(pure_rust_locales::sgs_LT::$($item)::+), - "fy_NL" => Ok(pure_rust_locales::fy_NL::$($item)::+), - "nan_TW@latin" => Ok(pure_rust_locales::nan_TW_latin::$($item)::+), - "csb_PL" => Ok(pure_rust_locales::csb_PL::$($item)::+), - "nl_NL" => Ok(pure_rust_locales::nl_NL::$($item)::+), - "en_NZ" => Ok(pure_rust_locales::en_NZ::$($item)::+), - "nn_NO" => Ok(pure_rust_locales::nn_NO::$($item)::+), - "ar_SA" => Ok(pure_rust_locales::ar_SA::$($item)::+), - "bi_VU" => Ok(pure_rust_locales::bi_VU::$($item)::+), - "gl_ES" => Ok(pure_rust_locales::gl_ES::$($item)::+), - "dsb_DE" => Ok(pure_rust_locales::dsb_DE::$($item)::+), - "es_ES" => Ok(pure_rust_locales::es_ES::$($item)::+), - "nhn_MX" => Ok(pure_rust_locales::nhn_MX::$($item)::+), - "es_MX" => Ok(pure_rust_locales::es_MX::$($item)::+), - "miq_NI" => Ok(pure_rust_locales::miq_NI::$($item)::+), - "de_DE@euro" => Ok(pure_rust_locales::de_DE_euro::$($item)::+), - "zh_SG" => Ok(pure_rust_locales::zh_SG::$($item)::+), - "aa_ET" => Ok(pure_rust_locales::aa_ET::$($item)::+), - "tpi_PG" => Ok(pure_rust_locales::tpi_PG::$($item)::+), - "zu_ZA" => Ok(pure_rust_locales::zu_ZA::$($item)::+), - "fil_PH" => Ok(pure_rust_locales::fil_PH::$($item)::+), - "an_ES" => Ok(pure_rust_locales::an_ES::$($item)::+), - "raj_IN" => Ok(pure_rust_locales::raj_IN::$($item)::+), - "ga_IE@euro" => Ok(pure_rust_locales::ga_IE_euro::$($item)::+), - "es_HN" => Ok(pure_rust_locales::es_HN::$($item)::+), - "mai_IN" => Ok(pure_rust_locales::mai_IN::$($item)::+), - "es_NI" => Ok(pure_rust_locales::es_NI::$($item)::+), - "sat_IN" => Ok(pure_rust_locales::sat_IN::$($item)::+), - "km_KH" => Ok(pure_rust_locales::km_KH::$($item)::+), - "as_IN" => Ok(pure_rust_locales::as_IN::$($item)::+), - "en_PH" => Ok(pure_rust_locales::en_PH::$($item)::+), - "ss_ZA" => Ok(pure_rust_locales::ss_ZA::$($item)::+), - "eu_ES" => Ok(pure_rust_locales::eu_ES::$($item)::+), - "es_GT" => Ok(pure_rust_locales::es_GT::$($item)::+), - "sr_ME" => Ok(pure_rust_locales::sr_ME::$($item)::+), - "es_UY" => Ok(pure_rust_locales::es_UY::$($item)::+), - "en_AU" => Ok(pure_rust_locales::en_AU::$($item)::+), - "es_AR" => Ok(pure_rust_locales::es_AR::$($item)::+), - "de_DE" => Ok(pure_rust_locales::de_DE::$($item)::+), - "fo_FO" => Ok(pure_rust_locales::fo_FO::$($item)::+), - "ca_IT" => Ok(pure_rust_locales::ca_IT::$($item)::+), - "aa_ER@saaho" => Ok(pure_rust_locales::aa_ER_saaho::$($item)::+), - "es_PA" => Ok(pure_rust_locales::es_PA::$($item)::+), - "ia_FR" => Ok(pure_rust_locales::ia_FR::$($item)::+), - "ky_KG" => Ok(pure_rust_locales::ky_KG::$($item)::+), - "mk_MK" => Ok(pure_rust_locales::mk_MK::$($item)::+), - "mn_MN" => Ok(pure_rust_locales::mn_MN::$($item)::+), - "ur_IN" => Ok(pure_rust_locales::ur_IN::$($item)::+), - "en_SG" => Ok(pure_rust_locales::en_SG::$($item)::+), - "wa_BE@euro" => Ok(pure_rust_locales::wa_BE_euro::$($item)::+), - "dv_MV" => Ok(pure_rust_locales::dv_MV::$($item)::+), - "de_LU" => Ok(pure_rust_locales::de_LU::$($item)::+), - "ht_HT" => Ok(pure_rust_locales::ht_HT::$($item)::+), - "szl_PL" => Ok(pure_rust_locales::szl_PL::$($item)::+), - "cy_GB" => Ok(pure_rust_locales::cy_GB::$($item)::+), - "to_TO" => Ok(pure_rust_locales::to_TO::$($item)::+), - "es_EC" => Ok(pure_rust_locales::es_EC::$($item)::+), - "ar_LB" => Ok(pure_rust_locales::ar_LB::$($item)::+), - "de_BE@euro" => Ok(pure_rust_locales::de_BE_euro::$($item)::+), - "de_CH" => Ok(pure_rust_locales::de_CH::$($item)::+), - "dz_BT" => Ok(pure_rust_locales::dz_BT::$($item)::+), - "en_HK" => Ok(pure_rust_locales::en_HK::$($item)::+), - "ce_RU" => Ok(pure_rust_locales::ce_RU::$($item)::+), - "gez_ET" => Ok(pure_rust_locales::gez_ET::$($item)::+), - "mag_IN" => Ok(pure_rust_locales::mag_IN::$($item)::+), - "az_AZ" => Ok(pure_rust_locales::az_AZ::$($item)::+), - "es_CL" => Ok(pure_rust_locales::es_CL::$($item)::+), - "sd_IN" => Ok(pure_rust_locales::sd_IN::$($item)::+), - "sr_RS@latin" => Ok(pure_rust_locales::sr_RS_latin::$($item)::+), - "lg_UG" => Ok(pure_rust_locales::lg_UG::$($item)::+), - "fr_BE@euro" => Ok(pure_rust_locales::fr_BE_euro::$($item)::+), - "ca_ES@valencia" => Ok(pure_rust_locales::ca_ES_valencia::$($item)::+), - "el_GR@euro" => Ok(pure_rust_locales::el_GR_euro::$($item)::+), - "pa_PK" => Ok(pure_rust_locales::pa_PK::$($item)::+), - "sa_IN" => Ok(pure_rust_locales::sa_IN::$($item)::+), - "so_ET" => Ok(pure_rust_locales::so_ET::$($item)::+), - "th_TH" => Ok(pure_rust_locales::th_TH::$($item)::+), - "hy_AM" => Ok(pure_rust_locales::hy_AM::$($item)::+), - "wo_SN" => Ok(pure_rust_locales::wo_SN::$($item)::+), - "my_MM" => Ok(pure_rust_locales::my_MM::$($item)::+), - "sk_SK" => Ok(pure_rust_locales::sk_SK::$($item)::+), - "es_SV" => Ok(pure_rust_locales::es_SV::$($item)::+), - "om_KE" => Ok(pure_rust_locales::om_KE::$($item)::+), - "ug_CN" => Ok(pure_rust_locales::ug_CN::$($item)::+), - "ve_ZA" => Ok(pure_rust_locales::ve_ZA::$($item)::+), - "xh_ZA" => Ok(pure_rust_locales::xh_ZA::$($item)::+), - "fr_BE" => Ok(pure_rust_locales::fr_BE::$($item)::+), - "rw_RW" => Ok(pure_rust_locales::rw_RW::$($item)::+), - "ar_IN" => Ok(pure_rust_locales::ar_IN::$($item)::+), - "ayc_PE" => Ok(pure_rust_locales::ayc_PE::$($item)::+), - "hu_HU" => Ok(pure_rust_locales::hu_HU::$($item)::+), - "sid_ET" => Ok(pure_rust_locales::sid_ET::$($item)::+), - "de_IT" => Ok(pure_rust_locales::de_IT::$($item)::+), - "aa_ER" => Ok(pure_rust_locales::aa_ER::$($item)::+), - "en_DK" => Ok(pure_rust_locales::en_DK::$($item)::+), - "cmn_TW" => Ok(pure_rust_locales::cmn_TW::$($item)::+), - "ar_LY" => Ok(pure_rust_locales::ar_LY::$($item)::+), - "gd_GB" => Ok(pure_rust_locales::gd_GB::$($item)::+), - "ar_TN" => Ok(pure_rust_locales::ar_TN::$($item)::+), - "be_BY" => Ok(pure_rust_locales::be_BY::$($item)::+), - "de_BE" => Ok(pure_rust_locales::de_BE::$($item)::+), - "ru_RU" => Ok(pure_rust_locales::ru_RU::$($item)::+), - "byn_ER" => Ok(pure_rust_locales::byn_ER::$($item)::+), - "az_IR" => Ok(pure_rust_locales::az_IR::$($item)::+), - "it_IT@euro" => Ok(pure_rust_locales::it_IT_euro::$($item)::+), - "fr_FR" => Ok(pure_rust_locales::fr_FR::$($item)::+), - "ar_BH" => Ok(pure_rust_locales::ar_BH::$($item)::+), - "ha_NG" => Ok(pure_rust_locales::ha_NG::$($item)::+), - "ar_JO" => Ok(pure_rust_locales::ar_JO::$($item)::+), - "wae_CH" => Ok(pure_rust_locales::wae_CH::$($item)::+), - "iu_CA" => Ok(pure_rust_locales::iu_CA::$($item)::+), - "ar_DZ" => Ok(pure_rust_locales::ar_DZ::$($item)::+), - "am_ET" => Ok(pure_rust_locales::am_ET::$($item)::+), - "mni_IN" => Ok(pure_rust_locales::mni_IN::$($item)::+), - "ar_YE" => Ok(pure_rust_locales::ar_YE::$($item)::+), - "sm_WS" => Ok(pure_rust_locales::sm_WS::$($item)::+), - "en_IE@euro" => Ok(pure_rust_locales::en_IE_euro::$($item)::+), - "ber_DZ" => Ok(pure_rust_locales::ber_DZ::$($item)::+), - "es_CR" => Ok(pure_rust_locales::es_CR::$($item)::+), - "ga_IE" => Ok(pure_rust_locales::ga_IE::$($item)::+), - "pap_CW" => Ok(pure_rust_locales::pap_CW::$($item)::+), - "anp_IN" => Ok(pure_rust_locales::anp_IN::$($item)::+), - "es_CO" => Ok(pure_rust_locales::es_CO::$($item)::+), - "fi_FI" => Ok(pure_rust_locales::fi_FI::$($item)::+), - "ta_LK" => Ok(pure_rust_locales::ta_LK::$($item)::+), - "en_SC" => Ok(pure_rust_locales::en_SC::$($item)::+), - "en_ZM" => Ok(pure_rust_locales::en_ZM::$($item)::+), - "the_NP" => Ok(pure_rust_locales::the_NP::$($item)::+), - "sv_FI" => Ok(pure_rust_locales::sv_FI::$($item)::+), - "fy_DE" => Ok(pure_rust_locales::fy_DE::$($item)::+), - "ca_FR" => Ok(pure_rust_locales::ca_FR::$($item)::+), - "gu_IN" => Ok(pure_rust_locales::gu_IN::$($item)::+), - "fr_LU" => Ok(pure_rust_locales::fr_LU::$($item)::+), - "ik_CA" => Ok(pure_rust_locales::ik_CA::$($item)::+), - "ti_ET" => Ok(pure_rust_locales::ti_ET::$($item)::+), - "de_LU@euro" => Ok(pure_rust_locales::de_LU_euro::$($item)::+), - "tcy_IN" => Ok(pure_rust_locales::tcy_IN::$($item)::+), - "tt_RU@iqtelif" => Ok(pure_rust_locales::tt_RU_iqtelif::$($item)::+), - "lij_IT" => Ok(pure_rust_locales::lij_IT::$($item)::+), - "unm_US" => Ok(pure_rust_locales::unm_US::$($item)::+), - "pt_PT@euro" => Ok(pure_rust_locales::pt_PT_euro::$($item)::+), - "sw_KE" => Ok(pure_rust_locales::sw_KE::$($item)::+), - "es_DO" => Ok(pure_rust_locales::es_DO::$($item)::+), - "niu_NU" => Ok(pure_rust_locales::niu_NU::$($item)::+), - "fa_IR" => Ok(pure_rust_locales::fa_IR::$($item)::+), - "es_PE" => Ok(pure_rust_locales::es_PE::$($item)::+), - "es_CU" => Ok(pure_rust_locales::es_CU::$($item)::+), - "gez_ET@abegede" => Ok(pure_rust_locales::gez_ET_abegede::$($item)::+), - "bem_ZM" => Ok(pure_rust_locales::bem_ZM::$($item)::+), - "kl_GL" => Ok(pure_rust_locales::kl_GL::$($item)::+), - "lzh_TW" => Ok(pure_rust_locales::lzh_TW::$($item)::+), - "ts_ZA" => Ok(pure_rust_locales::ts_ZA::$($item)::+), - "li_NL" => Ok(pure_rust_locales::li_NL::$($item)::+), - "cs_CZ" => Ok(pure_rust_locales::cs_CZ::$($item)::+), - "it_CH" => Ok(pure_rust_locales::it_CH::$($item)::+), - "en_ZW" => Ok(pure_rust_locales::en_ZW::$($item)::+), - "hsb_DE" => Ok(pure_rust_locales::hsb_DE::$($item)::+), - "mjw_IN" => Ok(pure_rust_locales::mjw_IN::$($item)::+), - "is_IS" => Ok(pure_rust_locales::is_IS::$($item)::+), - "he_IL" => Ok(pure_rust_locales::he_IL::$($item)::+), - "oc_FR" => Ok(pure_rust_locales::oc_FR::$($item)::+), - "et_EE" => Ok(pure_rust_locales::et_EE::$($item)::+), - "pt_BR" => Ok(pure_rust_locales::pt_BR::$($item)::+), - "os_RU" => Ok(pure_rust_locales::os_RU::$($item)::+), - "br_FR@euro" => Ok(pure_rust_locales::br_FR_euro::$($item)::+), - "es_PY" => Ok(pure_rust_locales::es_PY::$($item)::+), - "ta_IN" => Ok(pure_rust_locales::ta_IN::$($item)::+), - "es_ES@euro" => Ok(pure_rust_locales::es_ES_euro::$($item)::+), - "doi_IN" => Ok(pure_rust_locales::doi_IN::$($item)::+), - "eu_ES@euro" => Ok(pure_rust_locales::eu_ES_euro::$($item)::+), - "sq_MK" => Ok(pure_rust_locales::sq_MK::$($item)::+), - "gl_ES@euro" => Ok(pure_rust_locales::gl_ES_euro::$($item)::+), - "nl_NL@euro" => Ok(pure_rust_locales::nl_NL_euro::$($item)::+), - "ar_SS" => Ok(pure_rust_locales::ar_SS::$($item)::+), - "ca_ES@euro" => Ok(pure_rust_locales::ca_ES_euro::$($item)::+), - "bhb_IN" => Ok(pure_rust_locales::bhb_IN::$($item)::+), - "mnw_MM" => Ok(pure_rust_locales::mnw_MM::$($item)::+), - "mg_MG" => Ok(pure_rust_locales::mg_MG::$($item)::+), - "bg_BG" => Ok(pure_rust_locales::bg_BG::$($item)::+), - "nb_NO" => Ok(pure_rust_locales::nb_NO::$($item)::+), - "ru_UA" => Ok(pure_rust_locales::ru_UA::$($item)::+), - "ar_IQ" => Ok(pure_rust_locales::ar_IQ::$($item)::+), - "bho_IN" => Ok(pure_rust_locales::bho_IN::$($item)::+), - "chr_US" => Ok(pure_rust_locales::chr_US::$($item)::+), - "li_BE" => Ok(pure_rust_locales::li_BE::$($item)::+), - "zh_TW" => Ok(pure_rust_locales::zh_TW::$($item)::+), - "tt_RU" => Ok(pure_rust_locales::tt_RU::$($item)::+), - "mt_MT" => Ok(pure_rust_locales::mt_MT::$($item)::+), - "nds_DE" => Ok(pure_rust_locales::nds_DE::$($item)::+), - "es_BO" => Ok(pure_rust_locales::es_BO::$($item)::+), - "hi_IN" => Ok(pure_rust_locales::hi_IN::$($item)::+), - "ti_ER" => Ok(pure_rust_locales::ti_ER::$($item)::+), - "da_DK" => Ok(pure_rust_locales::da_DK::$($item)::+), - "tr_CY" => Ok(pure_rust_locales::tr_CY::$($item)::+), - "ar_QA" => Ok(pure_rust_locales::ar_QA::$($item)::+), - "lt_LT" => Ok(pure_rust_locales::lt_LT::$($item)::+), - "en_NG" => Ok(pure_rust_locales::en_NG::$($item)::+), - "ks_IN" => Ok(pure_rust_locales::ks_IN::$($item)::+), - "zh_CN" => Ok(pure_rust_locales::zh_CN::$($item)::+), - "mr_IN" => Ok(pure_rust_locales::mr_IN::$($item)::+), - "kab_DZ" => Ok(pure_rust_locales::kab_DZ::$($item)::+), - "si_LK" => Ok(pure_rust_locales::si_LK::$($item)::+), - "pt_PT" => Ok(pure_rust_locales::pt_PT::$($item)::+), - "tig_ER" => Ok(pure_rust_locales::tig_ER::$($item)::+), - "ar_AE" => Ok(pure_rust_locales::ar_AE::$($item)::+), - "yuw_PG" => Ok(pure_rust_locales::yuw_PG::$($item)::+), - "ar_OM" => Ok(pure_rust_locales::ar_OM::$($item)::+), - "en_CA" => Ok(pure_rust_locales::en_CA::$($item)::+), - "fr_FR@euro" => Ok(pure_rust_locales::fr_FR_euro::$($item)::+), - "hak_TW" => Ok(pure_rust_locales::hak_TW::$($item)::+), - "lo_LA" => Ok(pure_rust_locales::lo_LA::$($item)::+), - "sq_AL" => Ok(pure_rust_locales::sq_AL::$($item)::+), - "tg_TJ" => Ok(pure_rust_locales::tg_TJ::$($item)::+), - "bo_IN" => Ok(pure_rust_locales::bo_IN::$($item)::+), - "pap_AW" => Ok(pure_rust_locales::pap_AW::$($item)::+), - "br_FR" => Ok(pure_rust_locales::br_FR::$($item)::+), - "en_GB" => Ok(pure_rust_locales::en_GB::$($item)::+), - "ja_JP" => Ok(pure_rust_locales::ja_JP::$($item)::+), - "sc_IT" => Ok(pure_rust_locales::sc_IT::$($item)::+), - "lb_LU" => Ok(pure_rust_locales::lb_LU::$($item)::+), - "quz_PE" => Ok(pure_rust_locales::quz_PE::$($item)::+), - "ne_NP" => Ok(pure_rust_locales::ne_NP::$($item)::+), - "fr_CH" => Ok(pure_rust_locales::fr_CH::$($item)::+), - "om_ET" => Ok(pure_rust_locales::om_ET::$($item)::+), - "so_KE" => Ok(pure_rust_locales::so_KE::$($item)::+), - "vi_VN" => Ok(pure_rust_locales::vi_VN::$($item)::+), - "kn_IN" => Ok(pure_rust_locales::kn_IN::$($item)::+), - "en_BW" => Ok(pure_rust_locales::en_BW::$($item)::+), - "bs_BA" => Ok(pure_rust_locales::bs_BA::$($item)::+), - "hr_HR" => Ok(pure_rust_locales::hr_HR::$($item)::+), - "ro_RO" => Ok(pure_rust_locales::ro_RO::$($item)::+), - "ks_IN@devanagari" => Ok(pure_rust_locales::ks_IN_devanagari::$($item)::+), - "en_IE" => Ok(pure_rust_locales::en_IE::$($item)::+), - "nso_ZA" => Ok(pure_rust_locales::nso_ZA::$($item)::+), - "hne_IN" => Ok(pure_rust_locales::hne_IN::$($item)::+), - "id_ID" => Ok(pure_rust_locales::id_ID::$($item)::+), - "shs_CA" => Ok(pure_rust_locales::shs_CA::$($item)::+), - "ku_TR" => Ok(pure_rust_locales::ku_TR::$($item)::+), - "el_CY" => Ok(pure_rust_locales::el_CY::$($item)::+), - "tk_TM" => Ok(pure_rust_locales::tk_TM::$($item)::+), - "es_PR" => Ok(pure_rust_locales::es_PR::$($item)::+), - "sr_RS" => Ok(pure_rust_locales::sr_RS::$($item)::+), - "en_IL" => Ok(pure_rust_locales::en_IL::$($item)::+), - "ml_IN" => Ok(pure_rust_locales::ml_IN::$($item)::+), - "ar_MA" => Ok(pure_rust_locales::ar_MA::$($item)::+), - "nan_TW" => Ok(pure_rust_locales::nan_TW::$($item)::+), - "de_AT@euro" => Ok(pure_rust_locales::de_AT_euro::$($item)::+), - _ => Err(FormatError(FormatErrorKind::UnknownLocale)), - } - }} -} - -pub(crate) fn short_months(locale: &str) -> FormatResult<&[&'static str]> { +pub(crate) fn short_months(locale: Locale) -> &'static [&'static str] { locale_match!(locale => LC_TIME::ABMON) } -pub(crate) fn long_months(locale: &str) -> FormatResult<&[&'static str]> { +pub(crate) fn long_months(locale: Locale) -> &'static [&'static str] { locale_match!(locale => LC_TIME::MON) } -pub(crate) fn short_weekdays(locale: &str) -> FormatResult<&[&'static str]> { +pub(crate) fn short_weekdays(locale: Locale) -> &'static [&'static str] { locale_match!(locale => LC_TIME::ABDAY) } -pub(crate) fn long_weekdays(locale: &str) -> FormatResult<&[&'static str]> { +pub(crate) fn long_weekdays(locale: Locale) -> &'static [&'static str] { locale_match!(locale => LC_TIME::DAY) } diff --git a/src/format/mod.rs b/src/format/mod.rs index ee44104a08..988a76c79c 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -38,12 +38,14 @@ use offset::{FixedOffset, Offset}; use {Datelike, Timelike}; use {ParseWeekdayError, Weekday}; -#[cfg(any(all(feature = "locales", any(feature = "alloc", feature = "std", test))))] +#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] mod locales; pub use self::parse::parse; pub use self::parsed::Parsed; pub use self::strftime::StrftimeItems; +#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] +pub use pure_rust_locales::Locale; /// An uninhabited type used for `InternalNumeric` and `InternalFixed` below. #[derive(Clone, PartialEq, Eq)] @@ -381,63 +383,6 @@ const TOO_SHORT: ParseError = ParseError(ParseErrorKind::TooShort); const TOO_LONG: ParseError = ParseError(ParseErrorKind::TooLong); const BAD_FORMAT: ParseError = ParseError(ParseErrorKind::BadFormat); -/// An error from a "format" function. -#[derive(Debug, Clone, PartialEq, Eq, Copy)] -#[cfg(any(feature = "alloc", feature = "std", test))] -pub struct FormatError(FormatErrorKind); - -/// The category of format error. -#[cfg(any(feature = "alloc", feature = "std", test))] -#[derive(Debug, Clone, PartialEq, Eq, Copy)] -enum FormatErrorKind { - /// The locale is unknown or not available. - #[cfg(feature = "locales")] - UnknownLocale, - - /// Format error. - Format, - - /// Insufficient arguments for given format. - InsufficientArguments, - - /// Item error. - Item, -} - -/// Same as `Result`. -#[cfg(any(feature = "alloc", feature = "std", test))] -pub type FormatResult = Result; - -#[cfg(any(feature = "alloc", feature = "std", test))] -impl fmt::Display for FormatError { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - match self.0 { - #[cfg(feature = "locales")] - FormatErrorKind::UnknownLocale => write!(f, "the locale is unknown or not available"), - FormatErrorKind::Format => write!(f, "{}", fmt::Error), - FormatErrorKind::InsufficientArguments => { - write!(f, "insufficient arguments for given format") - } - FormatErrorKind::Item => write!(f, "item error"), - } - } -} - -#[cfg(any(feature = "std", test))] -impl Error for FormatError { - #[allow(deprecated)] - fn description(&self) -> &str { - "format error" - } -} - -#[cfg(any(feature = "alloc", feature = "std", test))] -impl From for FormatError { - fn from(_err: fmt::Error) -> Self { - FormatError(FormatErrorKind::Format) - } -} - /// Formats single formatting item #[cfg(any(feature = "alloc", feature = "std", test))] pub fn format_item<'a>( @@ -446,9 +391,9 @@ pub fn format_item<'a>( time: Option<&NaiveTime>, off: Option<&(String, FixedOffset)>, item: &Item<'a>, -) -> FormatResult<()> { +) -> fmt::Result { let mut result = String::new(); - format_inner(&mut result, date, time, off, item, "POSIX")?; + format_inner(&mut result, date, time, off, item, Locale::POSIX)?; w.pad(&result)?; Ok(()) } @@ -460,19 +405,19 @@ fn format_inner<'a>( time: Option<&NaiveTime>, off: Option<&(String, FixedOffset)>, item: &Item<'a>, - _locale: &str, -) -> FormatResult<()> { + _locale: Locale, +) -> fmt::Result { #[cfg(feature = "locales")] let locale = _locale; // full and abbreviated month and weekday names #[cfg(feature = "locales")] - let short_months = locales::short_months(locale)?; + let short_months = locales::short_months(locale); #[cfg(feature = "locales")] - let long_months = locales::long_months(locale)?; + let long_months = locales::long_months(locale); #[cfg(feature = "locales")] - let short_weekdays = locales::short_weekdays(locale)?; + let short_weekdays = locales::short_weekdays(locale); #[cfg(feature = "locales")] - let long_weekdays = locales::long_weekdays(locale)?; + let long_weekdays = locales::long_weekdays(locale); #[cfg(not(feature = "locales"))] let short_months = &["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; @@ -565,7 +510,7 @@ fn format_inner<'a>( } }? } else { - return Err(FormatError(FormatErrorKind::InsufficientArguments)); + return Err(fmt::Error); // insufficient arguments for given format } } @@ -716,11 +661,11 @@ fn format_inner<'a>( match ret { Some(ret) => ret?, - None => return Err(FormatError(FormatErrorKind::InsufficientArguments)), + None => return Err(fmt::Error), // insufficient arguments for given format } } - Item::Error => return Err(FormatError(FormatErrorKind::Item)), + Item::Error => return Err(fmt::Error), } Ok(()) } @@ -734,14 +679,14 @@ pub fn format<'a, I, B>( time: Option<&NaiveTime>, off: Option<&(String, FixedOffset)>, items: I, -) -> FormatResult<()> +) -> fmt::Result where I: Iterator + Clone, B: Borrow>, { let mut result = String::new(); for item in items { - format_inner(&mut result, date, time, off, item.borrow(), "POSIX")?; + format_inner(&mut result, date, time, off, item.borrow(), Locale::POSIX)?; } w.pad(&result)?; Ok(()) @@ -804,7 +749,7 @@ impl<'a, I: Iterator + Clone, B: Borrow>> fmt::Display for De /// This is normally constructed via `format` methods of each date and time type. #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] #[derive(Debug)] -pub struct DelayedFormatLocalized<'a, I> { +pub struct DelayedFormatLocalized { /// The date view, if any. date: Option, /// The time view, if any. @@ -814,24 +759,24 @@ pub struct DelayedFormatLocalized<'a, I> { /// An iterator returning formatting items. items: I, /// Locale used for text. - locale: &'a str, + locale: Locale, } #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] -impl<'a, 'b, I: Iterator + Clone, B: Borrow>> DelayedFormatLocalized<'b, I> { +impl<'a, I: Iterator + Clone, B: Borrow>> DelayedFormatLocalized { /// Makes a new `DelayedFormatLocalized` value out of local date and time. pub fn new( date: Option, time: Option, items: I, - locale: &'b str, - ) -> DelayedFormatLocalized<'b, I> { + locale: Locale, + ) -> DelayedFormatLocalized { DelayedFormatLocalized { date: date, time: time, off: None, items: items, - locale: locale.as_ref(), + locale: locale, } } @@ -841,8 +786,8 @@ impl<'a, 'b, I: Iterator + Clone, B: Borrow>> DelayedFormatLo time: Option, offset: &Off, items: I, - locale: &'b str, - ) -> DelayedFormatLocalized<'b, I> + locale: Locale, + ) -> DelayedFormatLocalized where Off: Offset + fmt::Display, { @@ -852,14 +797,14 @@ impl<'a, 'b, I: Iterator + Clone, B: Borrow>> DelayedFormatLo time: time, off: Some(name_and_diff), items: items, - locale: locale.as_ref(), + locale: locale, } } } #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] -impl<'a, 'b, I: Iterator + Clone, B: Borrow>> fmt::Display - for DelayedFormatLocalized<'b, I> +impl<'a, I: Iterator + Clone, B: Borrow>> fmt::Display + for DelayedFormatLocalized { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { format_localized( @@ -920,8 +865,8 @@ pub fn format_item_localized<'a>( time: Option<&NaiveTime>, off: Option<&(String, FixedOffset)>, item: &Item<'a>, - locale: &str, -) -> FormatResult<()> { + locale: Locale, +) -> fmt::Result { let mut result = String::new(); format_inner(&mut result, date, time, off, item, locale)?; w.pad(&result)?; @@ -937,8 +882,8 @@ pub fn format_localized<'a, I, B>( time: Option<&NaiveTime>, off: Option<&(String, FixedOffset)>, items: I, - locale: &str, -) -> FormatResult<()> + locale: Locale, +) -> fmt::Result where I: Iterator + Clone, B: Borrow>, diff --git a/src/format/strftime.rs b/src/format/strftime.rs index ddaa1907ca..b31cbb0591 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -523,91 +523,92 @@ fn test_strftime_docs() { #[test] fn test_strftime_docs_localized() { use {FixedOffset, TimeZone, Timelike}; + use pure_rust_locales::Locale; let dt = FixedOffset::east(34200).ymd(2001, 7, 8).and_hms_nano(0, 34, 59, 1_026_490_708); // date specifiers - assert_eq!(dt.format_localized("%Y", "POSIX").to_string(), "2001"); - assert_eq!(dt.format_localized("%C", "POSIX").to_string(), "20"); - assert_eq!(dt.format_localized("%y", "POSIX").to_string(), "01"); - assert_eq!(dt.format_localized("%m", "POSIX").to_string(), "07"); - assert_eq!(dt.format_localized("%b", "POSIX").to_string(), "Jul"); - assert_eq!(dt.format_localized("%B", "POSIX").to_string(), "July"); - assert_eq!(dt.format_localized("%h", "POSIX").to_string(), "Jul"); - assert_eq!(dt.format_localized("%d", "POSIX").to_string(), "08"); - assert_eq!(dt.format_localized("%e", "POSIX").to_string(), " 8"); + assert_eq!(dt.format_localized("%Y", Locale::POSIX).to_string(), "2001"); + assert_eq!(dt.format_localized("%C", Locale::POSIX).to_string(), "20"); + assert_eq!(dt.format_localized("%y", Locale::POSIX).to_string(), "01"); + assert_eq!(dt.format_localized("%m", Locale::POSIX).to_string(), "07"); + assert_eq!(dt.format_localized("%b", Locale::POSIX).to_string(), "Jul"); + assert_eq!(dt.format_localized("%B", Locale::POSIX).to_string(), "July"); + assert_eq!(dt.format_localized("%h", Locale::POSIX).to_string(), "Jul"); + assert_eq!(dt.format_localized("%d", Locale::POSIX).to_string(), "08"); + assert_eq!(dt.format_localized("%e", Locale::POSIX).to_string(), " 8"); assert_eq!( - dt.format_localized("%e", "POSIX").to_string(), - dt.format_localized("%_d", "POSIX").to_string() + dt.format_localized("%e", Locale::POSIX).to_string(), + dt.format_localized("%_d", Locale::POSIX).to_string() ); - assert_eq!(dt.format_localized("%a", "POSIX").to_string(), "Sun"); - assert_eq!(dt.format_localized("%A", "POSIX").to_string(), "Sunday"); - assert_eq!(dt.format_localized("%w", "POSIX").to_string(), "0"); - assert_eq!(dt.format_localized("%u", "POSIX").to_string(), "7"); - assert_eq!(dt.format_localized("%U", "POSIX").to_string(), "28"); - assert_eq!(dt.format_localized("%W", "POSIX").to_string(), "27"); - assert_eq!(dt.format_localized("%G", "POSIX").to_string(), "2001"); - assert_eq!(dt.format_localized("%g", "POSIX").to_string(), "01"); - assert_eq!(dt.format_localized("%V", "POSIX").to_string(), "27"); - assert_eq!(dt.format_localized("%j", "POSIX").to_string(), "189"); - assert_eq!(dt.format_localized("%D", "POSIX").to_string(), "07/08/01"); - assert_eq!(dt.format_localized("%x", "POSIX").to_string(), "07/08/01"); - assert_eq!(dt.format_localized("%F", "POSIX").to_string(), "2001-07-08"); - assert_eq!(dt.format_localized("%v", "POSIX").to_string(), " 8-Jul-2001"); + assert_eq!(dt.format_localized("%a", Locale::POSIX).to_string(), "Sun"); + assert_eq!(dt.format_localized("%A", Locale::POSIX).to_string(), "Sunday"); + assert_eq!(dt.format_localized("%w", Locale::POSIX).to_string(), "0"); + assert_eq!(dt.format_localized("%u", Locale::POSIX).to_string(), "7"); + assert_eq!(dt.format_localized("%U", Locale::POSIX).to_string(), "28"); + assert_eq!(dt.format_localized("%W", Locale::POSIX).to_string(), "27"); + assert_eq!(dt.format_localized("%G", Locale::POSIX).to_string(), "2001"); + assert_eq!(dt.format_localized("%g", Locale::POSIX).to_string(), "01"); + assert_eq!(dt.format_localized("%V", Locale::POSIX).to_string(), "27"); + assert_eq!(dt.format_localized("%j", Locale::POSIX).to_string(), "189"); + assert_eq!(dt.format_localized("%D", Locale::POSIX).to_string(), "07/08/01"); + assert_eq!(dt.format_localized("%x", Locale::POSIX).to_string(), "07/08/01"); + assert_eq!(dt.format_localized("%F", Locale::POSIX).to_string(), "2001-07-08"); + assert_eq!(dt.format_localized("%v", Locale::POSIX).to_string(), " 8-Jul-2001"); // time specifiers - assert_eq!(dt.format_localized("%H", "POSIX").to_string(), "00"); - assert_eq!(dt.format_localized("%k", "POSIX").to_string(), " 0"); + assert_eq!(dt.format_localized("%H", Locale::POSIX).to_string(), "00"); + assert_eq!(dt.format_localized("%k", Locale::POSIX).to_string(), " 0"); assert_eq!( - dt.format_localized("%k", "POSIX").to_string(), - dt.format_localized("%_H", "POSIX").to_string() + dt.format_localized("%k", Locale::POSIX).to_string(), + dt.format_localized("%_H", Locale::POSIX).to_string() ); - assert_eq!(dt.format_localized("%I", "POSIX").to_string(), "12"); - assert_eq!(dt.format_localized("%l", "POSIX").to_string(), "12"); + assert_eq!(dt.format_localized("%I", Locale::POSIX).to_string(), "12"); + assert_eq!(dt.format_localized("%l", Locale::POSIX).to_string(), "12"); assert_eq!( - dt.format_localized("%l", "POSIX").to_string(), - dt.format_localized("%_I", "POSIX").to_string() + dt.format_localized("%l", Locale::POSIX).to_string(), + dt.format_localized("%_I", Locale::POSIX).to_string() ); - assert_eq!(dt.format_localized("%P", "POSIX").to_string(), "am"); - assert_eq!(dt.format_localized("%p", "POSIX").to_string(), "AM"); - assert_eq!(dt.format_localized("%M", "POSIX").to_string(), "34"); - assert_eq!(dt.format_localized("%S", "POSIX").to_string(), "60"); - assert_eq!(dt.format_localized("%f", "POSIX").to_string(), "026490708"); - assert_eq!(dt.format_localized("%.f", "POSIX").to_string(), ".026490708"); + assert_eq!(dt.format_localized("%P", Locale::POSIX).to_string(), "am"); + assert_eq!(dt.format_localized("%p", Locale::POSIX).to_string(), "AM"); + assert_eq!(dt.format_localized("%M", Locale::POSIX).to_string(), "34"); + assert_eq!(dt.format_localized("%S", Locale::POSIX).to_string(), "60"); + assert_eq!(dt.format_localized("%f", Locale::POSIX).to_string(), "026490708"); + assert_eq!(dt.format_localized("%.f", Locale::POSIX).to_string(), ".026490708"); assert_eq!( - dt.with_nanosecond(1_026_490_000).unwrap().format_localized("%.f", "POSIX").to_string(), + dt.with_nanosecond(1_026_490_000).unwrap().format_localized("%.f", Locale::POSIX).to_string(), ".026490" ); - assert_eq!(dt.format_localized("%.3f", "POSIX").to_string(), ".026"); - assert_eq!(dt.format_localized("%.6f", "POSIX").to_string(), ".026490"); - assert_eq!(dt.format_localized("%.9f", "POSIX").to_string(), ".026490708"); - assert_eq!(dt.format_localized("%3f", "POSIX").to_string(), "026"); - assert_eq!(dt.format_localized("%6f", "POSIX").to_string(), "026490"); - assert_eq!(dt.format_localized("%9f", "POSIX").to_string(), "026490708"); - assert_eq!(dt.format_localized("%R", "POSIX").to_string(), "00:34"); - assert_eq!(dt.format_localized("%T", "POSIX").to_string(), "00:34:60"); - assert_eq!(dt.format_localized("%X", "POSIX").to_string(), "00:34:60"); - assert_eq!(dt.format_localized("%r", "POSIX").to_string(), "12:34:60 AM"); + assert_eq!(dt.format_localized("%.3f", Locale::POSIX).to_string(), ".026"); + assert_eq!(dt.format_localized("%.6f", Locale::POSIX).to_string(), ".026490"); + assert_eq!(dt.format_localized("%.9f", Locale::POSIX).to_string(), ".026490708"); + assert_eq!(dt.format_localized("%3f", Locale::POSIX).to_string(), "026"); + assert_eq!(dt.format_localized("%6f", Locale::POSIX).to_string(), "026490"); + assert_eq!(dt.format_localized("%9f", Locale::POSIX).to_string(), "026490708"); + assert_eq!(dt.format_localized("%R", Locale::POSIX).to_string(), "00:34"); + assert_eq!(dt.format_localized("%T", Locale::POSIX).to_string(), "00:34:60"); + assert_eq!(dt.format_localized("%X", Locale::POSIX).to_string(), "00:34:60"); + assert_eq!(dt.format_localized("%r", Locale::POSIX).to_string(), "12:34:60 AM"); // time zone specifiers - //assert_eq!(dt.format_localized("%Z", "POSIX").to_string(), "ACST"); - assert_eq!(dt.format_localized("%z", "POSIX").to_string(), "+0930"); - assert_eq!(dt.format_localized("%:z", "POSIX").to_string(), "+09:30"); + //assert_eq!(dt.format_localized("%Z", Locale::POSIX).to_string(), "ACST"); + assert_eq!(dt.format_localized("%z", Locale::POSIX).to_string(), "+0930"); + assert_eq!(dt.format_localized("%:z", Locale::POSIX).to_string(), "+09:30"); // date & time specifiers - assert_eq!(dt.format_localized("%c", "POSIX").to_string(), "Sun Jul 8 00:34:60 2001"); + assert_eq!(dt.format_localized("%c", Locale::POSIX).to_string(), "Sun Jul 8 00:34:60 2001"); assert_eq!( - dt.format_localized("%+", "POSIX").to_string(), + dt.format_localized("%+", Locale::POSIX).to_string(), "2001-07-08T00:34:60.026490708+09:30" ); assert_eq!( - dt.with_nanosecond(1_026_490_000).unwrap().format_localized("%+", "POSIX").to_string(), + dt.with_nanosecond(1_026_490_000).unwrap().format_localized("%+", Locale::POSIX).to_string(), "2001-07-08T00:34:60.026490+09:30" ); - assert_eq!(dt.format_localized("%s", "POSIX").to_string(), "994518299"); + assert_eq!(dt.format_localized("%s", Locale::POSIX).to_string(), "994518299"); // special specifiers - assert_eq!(dt.format_localized("%t", "POSIX").to_string(), "\t"); - assert_eq!(dt.format_localized("%n", "POSIX").to_string(), "\n"); - assert_eq!(dt.format_localized("%%", "POSIX").to_string(), "%"); + assert_eq!(dt.format_localized("%t", Locale::POSIX).to_string(), "\t"); + assert_eq!(dt.format_localized("%n", Locale::POSIX).to_string(), "\n"); + assert_eq!(dt.format_localized("%%", Locale::POSIX).to_string(), "%"); } diff --git a/src/lib.rs b/src/lib.rs index 3b6d0abd29..3374b7ebb5 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -453,8 +453,6 @@ pub use date::{Date, MAX_DATE, MIN_DATE}; #[cfg(feature = "rustc-serialize")] pub use datetime::rustc_serialize::TsSeconds; pub use datetime::{DateTime, SecondsFormat, MAX_DATETIME, MIN_DATETIME}; -#[cfg(any(feature = "alloc", feature = "std", test))] -pub use format::{FormatError, FormatResult}; pub use format::{ParseError, ParseResult}; #[doc(no_inline)] pub use naive::{IsoWeek, NaiveDate, NaiveDateTime, NaiveTime}; From 3f2659edb61a94330988a7ffcb20a5b6a7207d12 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 17 Jul 2020 22:43:16 +0200 Subject: [PATCH 22/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/date.rs | 4 ++-- src/datetime.rs | 2 +- src/format/mod.rs | 8 +------- src/format/strftime.rs | 12 +++++++++--- 4 files changed, 13 insertions(+), 13 deletions(-) diff --git a/src/date.rs b/src/date.rs index d6d2f544d9..3177633e75 100644 --- a/src/date.rs +++ b/src/date.rs @@ -10,10 +10,10 @@ use core::ops::{Add, Sub}; use core::{fmt, hash}; use oldtime::Duration as OldDuration; -#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] -use format::{DelayedFormatLocalized, Locale}; #[cfg(any(feature = "alloc", feature = "std", test))] use format::{DelayedFormat, Item, StrftimeItems}; +#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] +use format::{DelayedFormatLocalized, Locale}; use naive::{self, IsoWeek, NaiveDate, NaiveTime}; use offset::{TimeZone, Utc}; use DateTime; diff --git a/src/datetime.rs b/src/datetime.rs index e923d35cb2..2a80e1a5d1 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -19,9 +19,9 @@ use std::string::ToString; use core::borrow::Borrow; #[cfg(any(feature = "alloc", feature = "std", test))] use format::DelayedFormat; +use format::{parse, ParseError, ParseResult, Parsed, StrftimeItems}; #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] use format::{DelayedFormatLocalized, Locale}; -use format::{parse, ParseError, ParseResult, Parsed, StrftimeItems}; use format::{Fixed, Item}; use naive::{self, IsoWeek, NaiveDateTime, NaiveTime}; #[cfg(feature = "clock")] diff --git a/src/format/mod.rs b/src/format/mod.rs index 988a76c79c..b55c383aa3 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -771,13 +771,7 @@ impl<'a, I: Iterator + Clone, B: Borrow>> DelayedFormatLocali items: I, locale: Locale, ) -> DelayedFormatLocalized { - DelayedFormatLocalized { - date: date, - time: time, - off: None, - items: items, - locale: locale, - } + DelayedFormatLocalized { date: date, time: time, off: None, items: items, locale: locale } } /// Makes a new `DelayedFormatLocalized` value out of local date and time and UTC offset. diff --git a/src/format/strftime.rs b/src/format/strftime.rs index b31cbb0591..d50a460c8a 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -522,8 +522,8 @@ fn test_strftime_docs() { #[cfg(all(feature = "locales", test))] #[test] fn test_strftime_docs_localized() { - use {FixedOffset, TimeZone, Timelike}; use pure_rust_locales::Locale; + use {FixedOffset, TimeZone, Timelike}; let dt = FixedOffset::east(34200).ymd(2001, 7, 8).and_hms_nano(0, 34, 59, 1_026_490_708); @@ -576,7 +576,10 @@ fn test_strftime_docs_localized() { assert_eq!(dt.format_localized("%f", Locale::POSIX).to_string(), "026490708"); assert_eq!(dt.format_localized("%.f", Locale::POSIX).to_string(), ".026490708"); assert_eq!( - dt.with_nanosecond(1_026_490_000).unwrap().format_localized("%.f", Locale::POSIX).to_string(), + dt.with_nanosecond(1_026_490_000) + .unwrap() + .format_localized("%.f", Locale::POSIX) + .to_string(), ".026490" ); assert_eq!(dt.format_localized("%.3f", Locale::POSIX).to_string(), ".026"); @@ -602,7 +605,10 @@ fn test_strftime_docs_localized() { "2001-07-08T00:34:60.026490708+09:30" ); assert_eq!( - dt.with_nanosecond(1_026_490_000).unwrap().format_localized("%+", Locale::POSIX).to_string(), + dt.with_nanosecond(1_026_490_000) + .unwrap() + .format_localized("%+", Locale::POSIX) + .to_string(), "2001-07-08T00:34:60.026490+09:30" ); assert_eq!(dt.format_localized("%s", Locale::POSIX).to_string(), "994518299"); From 9085b05e2061296ea5a0dec64e2c2026ba32ba92 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sat, 18 Jul 2020 14:03:02 +0200 Subject: [PATCH 23/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/date.rs | 10 +++--- src/datetime.rs | 10 +++--- src/format/mod.rs | 92 ++++++++++++++++++----------------------------- 3 files changed, 44 insertions(+), 68 deletions(-) diff --git a/src/date.rs b/src/date.rs index 3177633e75..ca6cfa3bbd 100644 --- a/src/date.rs +++ b/src/date.rs @@ -10,10 +10,10 @@ use core::ops::{Add, Sub}; use core::{fmt, hash}; use oldtime::Duration as OldDuration; +#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] +use format::Locale; #[cfg(any(feature = "alloc", feature = "std", test))] use format::{DelayedFormat, Item, StrftimeItems}; -#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] -use format::{DelayedFormatLocalized, Locale}; use naive::{self, IsoWeek, NaiveDate, NaiveTime}; use offset::{TimeZone, Utc}; use DateTime; @@ -305,12 +305,12 @@ where &self, items: I, locale: Locale, - ) -> DelayedFormatLocalized + ) -> DelayedFormat where I: Iterator + Clone, B: Borrow>, { - DelayedFormatLocalized::new_with_offset( + DelayedFormat::new_with_offset_and_locale( Some(self.naive_local()), None, &self.offset, @@ -328,7 +328,7 @@ where &self, fmt: &'a str, locale: Locale, - ) -> DelayedFormatLocalized> { + ) -> DelayedFormat> { self.format_localized_with_items(StrftimeItems::new(fmt), locale) } } diff --git a/src/datetime.rs b/src/datetime.rs index 2a80e1a5d1..31a765567d 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -19,9 +19,9 @@ use std::string::ToString; use core::borrow::Borrow; #[cfg(any(feature = "alloc", feature = "std", test))] use format::DelayedFormat; -use format::{parse, ParseError, ParseResult, Parsed, StrftimeItems}; #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] -use format::{DelayedFormatLocalized, Locale}; +use format::Locale; +use format::{parse, ParseError, ParseResult, Parsed, StrftimeItems}; use format::{Fixed, Item}; use naive::{self, IsoWeek, NaiveDateTime, NaiveTime}; #[cfg(feature = "clock")] @@ -503,13 +503,13 @@ where &self, items: I, locale: Locale, - ) -> DelayedFormatLocalized + ) -> DelayedFormat where I: Iterator + Clone, B: Borrow>, { let local = self.naive_local(); - DelayedFormatLocalized::new_with_offset( + DelayedFormat::new_with_offset_and_locale( Some(local.date()), Some(local.time()), &self.offset, @@ -527,7 +527,7 @@ where &self, fmt: &'a str, locale: Locale, - ) -> DelayedFormatLocalized> { + ) -> DelayedFormat> { self.format_localized_with_items(StrftimeItems::new(fmt), locale) } } diff --git a/src/format/mod.rs b/src/format/mod.rs index b55c383aa3..59fc7d9b2d 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -47,6 +47,9 @@ pub use self::strftime::StrftimeItems; #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] pub use pure_rust_locales::Locale; +#[cfg(not(feature = "locales"))] +struct Locale; + /// An uninhabited type used for `InternalNumeric` and `InternalFixed` below. #[derive(Clone, PartialEq, Eq)] enum Void {} @@ -393,7 +396,7 @@ pub fn format_item<'a>( item: &Item<'a>, ) -> fmt::Result { let mut result = String::new(); - format_inner(&mut result, date, time, off, item, Locale::POSIX)?; + format_inner(&mut result, date, time, off, item, None)?; w.pad(&result)?; Ok(()) } @@ -405,10 +408,10 @@ fn format_inner<'a>( time: Option<&NaiveTime>, off: Option<&(String, FixedOffset)>, item: &Item<'a>, - _locale: Locale, + _locale: Option, ) -> fmt::Result { #[cfg(feature = "locales")] - let locale = _locale; + let locale = _locale.unwrap_or(Locale::POSIX); // full and abbreviated month and weekday names #[cfg(feature = "locales")] let short_months = locales::short_months(locale); @@ -686,7 +689,7 @@ where { let mut result = String::new(); for item in items { - format_inner(&mut result, date, time, off, item.borrow(), Locale::POSIX)?; + format_inner(&mut result, date, time, off, item.borrow(), None)?; } w.pad(&result)?; Ok(()) @@ -713,13 +716,15 @@ pub struct DelayedFormat { off: Option<(String, FixedOffset)>, /// An iterator returning formatting items. items: I, + /// Locale used for text. + locale: Option, } #[cfg(any(feature = "alloc", feature = "std", test))] impl<'a, I: Iterator + Clone, B: Borrow>> DelayedFormat { /// Makes a new `DelayedFormat` value out of local date and time. pub fn new(date: Option, time: Option, items: I) -> DelayedFormat { - DelayedFormat { date: date, time: time, off: None, items: items } + DelayedFormat { date: date, time: time, off: None, items: items, locale: None } } /// Makes a new `DelayedFormat` value out of local date and time and UTC offset. @@ -733,83 +738,54 @@ impl<'a, I: Iterator + Clone, B: Borrow>> DelayedFormat { Off: Offset + fmt::Display, { let name_and_diff = (offset.to_string(), offset.fix()); - DelayedFormat { date: date, time: time, off: Some(name_and_diff), items: items } - } -} - -#[cfg(any(feature = "alloc", feature = "std", test))] -impl<'a, I: Iterator + Clone, B: Borrow>> fmt::Display for DelayedFormat { - fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - format(f, self.date.as_ref(), self.time.as_ref(), self.off.as_ref(), self.items.clone()) - .map_err(|_| fmt::Error) + DelayedFormat { + date: date, + time: time, + off: Some(name_and_diff), + items: items, + locale: None, + } } -} -/// A *temporary* object which can be used as an argument to `format!` or others. -/// This is normally constructed via `format` methods of each date and time type. -#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] -#[derive(Debug)] -pub struct DelayedFormatLocalized { - /// The date view, if any. - date: Option, - /// The time view, if any. - time: Option, - /// The name and local-to-UTC difference for the offset (timezone), if any. - off: Option<(String, FixedOffset)>, - /// An iterator returning formatting items. - items: I, - /// Locale used for text. - locale: Locale, -} - -#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] -impl<'a, I: Iterator + Clone, B: Borrow>> DelayedFormatLocalized { - /// Makes a new `DelayedFormatLocalized` value out of local date and time. - pub fn new( + /// Makes a new `DelayedFormat` value out of local date and time and locale. + #[cfg(feature = "locales")] + pub fn new_with_locale( date: Option, time: Option, items: I, locale: Locale, - ) -> DelayedFormatLocalized { - DelayedFormatLocalized { date: date, time: time, off: None, items: items, locale: locale } + ) -> DelayedFormat { + DelayedFormat { date: date, time: time, off: None, items: items, locale: Some(locale) } } - /// Makes a new `DelayedFormatLocalized` value out of local date and time and UTC offset. - pub fn new_with_offset( + /// Makes a new `DelayedFormat` value out of local date and time, UTC offset and locale. + #[cfg(feature = "locales")] + pub fn new_with_offset_and_locale( date: Option, time: Option, offset: &Off, items: I, locale: Locale, - ) -> DelayedFormatLocalized + ) -> DelayedFormat where Off: Offset + fmt::Display, { let name_and_diff = (offset.to_string(), offset.fix()); - DelayedFormatLocalized { + DelayedFormat { date: date, time: time, off: Some(name_and_diff), items: items, - locale: locale, + locale: Some(locale), } } } -#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] -impl<'a, I: Iterator + Clone, B: Borrow>> fmt::Display - for DelayedFormatLocalized -{ +#[cfg(any(feature = "alloc", feature = "std", test))] +impl<'a, I: Iterator + Clone, B: Borrow>> fmt::Display for DelayedFormat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - format_localized( - f, - self.date.as_ref(), - self.time.as_ref(), - self.off.as_ref(), - self.items.clone(), - self.locale, - ) - .map_err(|_| fmt::Error) + format(f, self.date.as_ref(), self.time.as_ref(), self.off.as_ref(), self.items.clone()) + .map_err(|_| fmt::Error) } } @@ -862,7 +838,7 @@ pub fn format_item_localized<'a>( locale: Locale, ) -> fmt::Result { let mut result = String::new(); - format_inner(&mut result, date, time, off, item, locale)?; + format_inner(&mut result, date, time, off, item, Some(locale))?; w.pad(&result)?; Ok(()) } @@ -884,7 +860,7 @@ where { let mut result = String::new(); for item in items { - format_inner(&mut result, date, time, off, item.borrow(), locale)?; + format_inner(&mut result, date, time, off, item.borrow(), Some(locale))?; } w.pad(&result)?; Ok(()) From eacc085ee6162e9125157e3feceb6fd8bd43aba7 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sat, 18 Jul 2020 14:12:16 +0200 Subject: [PATCH 24/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/format/mod.rs b/src/format/mod.rs index 59fc7d9b2d..38a5925622 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -48,6 +48,7 @@ pub use self::strftime::StrftimeItems; pub use pure_rust_locales::Locale; #[cfg(not(feature = "locales"))] +#[allow(dead_code)] struct Locale; /// An uninhabited type used for `InternalNumeric` and `InternalFixed` below. From e6d601a9bed54d05fef3838fe56f167c779eeaf5 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sat, 18 Jul 2020 14:17:13 +0200 Subject: [PATCH 25/60] Update src/format/mod.rs --- src/format/mod.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/src/format/mod.rs b/src/format/mod.rs index 38a5925622..d81e2dedd4 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -49,6 +49,7 @@ pub use pure_rust_locales::Locale; #[cfg(not(feature = "locales"))] #[allow(dead_code)] +#[derive(Debug)] struct Locale; /// An uninhabited type used for `InternalNumeric` and `InternalFixed` below. From aef41e938bda75015c28e51ffffc5814d41ee995 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sat, 18 Jul 2020 15:12:36 +0200 Subject: [PATCH 26/60] Update src/format/mod.rs --- src/format/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/format/mod.rs b/src/format/mod.rs index d81e2dedd4..63e8c0621b 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -693,8 +693,7 @@ where for item in items { format_inner(&mut result, date, time, off, item.borrow(), None)?; } - w.pad(&result)?; - Ok(()) + w.pad(&result) } mod parsed; From 08be4234c072e81fc23f2417c70c619a95849a88 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sat, 18 Jul 2020 15:13:01 +0200 Subject: [PATCH 27/60] Update src/format/mod.rs --- src/format/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/format/mod.rs b/src/format/mod.rs index 63e8c0621b..3246f053e3 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -786,7 +786,6 @@ impl<'a, I: Iterator + Clone, B: Borrow>> DelayedFormat { impl<'a, I: Iterator + Clone, B: Borrow>> fmt::Display for DelayedFormat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { format(f, self.date.as_ref(), self.time.as_ref(), self.off.as_ref(), self.items.clone()) - .map_err(|_| fmt::Error) } } From a63d0cf4b33ee501de6264cbfddb2b2e7f891d03 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sat, 18 Jul 2020 15:13:50 +0200 Subject: [PATCH 28/60] Update src/format/mod.rs --- src/format/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/format/mod.rs b/src/format/mod.rs index 3246f053e3..6011df896b 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -839,8 +839,7 @@ pub fn format_item_localized<'a>( ) -> fmt::Result { let mut result = String::new(); format_inner(&mut result, date, time, off, item, Some(locale))?; - w.pad(&result)?; - Ok(()) + w.pad(&result) } /// Tries to format given arguments with given formatting items. From 12ca2c5704e7ebcc801c92f136949f395d19285f Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sat, 18 Jul 2020 15:13:59 +0200 Subject: [PATCH 29/60] Update src/format/mod.rs --- src/format/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/format/mod.rs b/src/format/mod.rs index 6011df896b..b81d5aefa7 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -861,6 +861,5 @@ where for item in items { format_inner(&mut result, date, time, off, item.borrow(), Some(locale))?; } - w.pad(&result)?; - Ok(()) + w.pad(&result) } From 3c02970b6e857877bac82352abe772c1fe6ba82e Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 19 Jul 2020 02:52:18 +0200 Subject: [PATCH 30/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- README.md | 9 +++++++++ src/format/mod.rs | 6 +++++- src/lib.rs | 14 ++++++++++++++ 3 files changed, 28 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 509077fc9a..d3236302ec 100644 --- a/README.md +++ b/README.md @@ -220,12 +220,21 @@ Chrono also provides [`to_rfc2822`](https://docs.rs/chrono/0.4/chrono/struct.Dat [`to_rfc3339`](https://docs.rs/chrono/0.4/chrono/struct.DateTime.html#method.to_rfc3339) methods for well-known formats. +Chrono now also provides date formatting in almost any language without the +help of an additional C library. This functionality is under the feature +`locales`: + +``` +chrono { version = ..., features = ["locales"] +``` + ```rust use chrono::prelude::*; let dt = Utc.ymd(2014, 11, 28).and_hms(12, 0, 9); assert_eq!(dt.format("%Y-%m-%d %H:%M:%S").to_string(), "2014-11-28 12:00:09"); assert_eq!(dt.format("%a %b %e %T %Y").to_string(), "Fri Nov 28 12:00:09 2014"); +assert_eq!(dt.format_localized("%A %e %B %Y, %T", Locale::fr_BE).to_string(), "vendredi 28 novembre 2014, 12:00:09"); assert_eq!(dt.format("%a %b %e %T %Y").to_string(), dt.format("%c").to_string()); assert_eq!(dt.to_string(), "2014-11-28 12:00:09 UTC"); diff --git a/src/format/mod.rs b/src/format/mod.rs index b81d5aefa7..4bf5309d9b 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -785,7 +785,11 @@ impl<'a, I: Iterator + Clone, B: Borrow>> DelayedFormat { #[cfg(any(feature = "alloc", feature = "std", test))] impl<'a, I: Iterator + Clone, B: Borrow>> fmt::Display for DelayedFormat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - format(f, self.date.as_ref(), self.time.as_ref(), self.off.as_ref(), self.items.clone()) + if let Some(locale) = self.locale { + format_localized(f, self.date.as_ref(), self.time.as_ref(), self.off.as_ref(), self.items.clone(), locale) + } else { + format(f, self.date.as_ref(), self.time.as_ref(), self.off.as_ref(), self.items.clone()) + } } } diff --git a/src/lib.rs b/src/lib.rs index 3374b7ebb5..31b9d8b54a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -212,12 +212,21 @@ //! [`to_rfc3339`](./struct.DateTime.html#method.to_rfc3339) methods //! for well-known formats. //! +//! Chrono now also provides date formatting in almost any language without the +//! help of an additional C library. This functionality is under the feature +//! `locales`: +//! +//! ```ignore +//! chrono { version = ..., features = ["locales"] +//! ``` +//! //! ```rust //! use chrono::prelude::*; //! //! let dt = Utc.ymd(2014, 11, 28).and_hms(12, 0, 9); //! assert_eq!(dt.format("%Y-%m-%d %H:%M:%S").to_string(), "2014-11-28 12:00:09"); //! assert_eq!(dt.format("%a %b %e %T %Y").to_string(), "Fri Nov 28 12:00:09 2014"); +//! assert_eq!(dt.format_localized("%A %e %B %Y, %T", Locale::fr_BE).to_string(), "vendredi 28 novembre 2014, 12:00:09"); //! assert_eq!(dt.format("%a %b %e %T %Y").to_string(), dt.format("%c").to_string()); //! //! assert_eq!(dt.to_string(), "2014-11-28 12:00:09 UTC"); @@ -453,6 +462,8 @@ pub use date::{Date, MAX_DATE, MIN_DATE}; #[cfg(feature = "rustc-serialize")] pub use datetime::rustc_serialize::TsSeconds; pub use datetime::{DateTime, SecondsFormat, MAX_DATETIME, MIN_DATETIME}; +#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] +pub use format::Locale; pub use format::{ParseError, ParseResult}; #[doc(no_inline)] pub use naive::{IsoWeek, NaiveDate, NaiveDateTime, NaiveTime}; @@ -482,6 +493,9 @@ pub mod prelude { pub use {NaiveDate, NaiveDateTime, NaiveTime}; #[doc(no_inline)] pub use {Offset, TimeZone}; + #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + #[doc(no_inline)] + pub use Locale; } // useful throughout the codebase From 72c960c096404edc313221ded647aa114c75ca42 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 19 Jul 2020 02:59:48 +0200 Subject: [PATCH 31/60] Update src/format/mod.rs --- src/format/mod.rs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/format/mod.rs b/src/format/mod.rs index 4bf5309d9b..e0e9104a6b 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -399,8 +399,7 @@ pub fn format_item<'a>( ) -> fmt::Result { let mut result = String::new(); format_inner(&mut result, date, time, off, item, None)?; - w.pad(&result)?; - Ok(()) + w.pad(&result) } #[cfg(any(feature = "alloc", feature = "std", test))] From be0cdd35ffc348e38c5338bb1701b76b3bf1c594 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 19 Jul 2020 03:06:37 +0200 Subject: [PATCH 32/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/mod.rs | 9 +++- src/format/strftime.rs | 97 ++++++++---------------------------------- src/lib.rs | 6 +-- 3 files changed, 29 insertions(+), 83 deletions(-) diff --git a/src/format/mod.rs b/src/format/mod.rs index e0e9104a6b..15e9d4f0c4 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -785,7 +785,14 @@ impl<'a, I: Iterator + Clone, B: Borrow>> DelayedFormat { impl<'a, I: Iterator + Clone, B: Borrow>> fmt::Display for DelayedFormat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { if let Some(locale) = self.locale { - format_localized(f, self.date.as_ref(), self.time.as_ref(), self.off.as_ref(), self.items.clone(), locale) + format_localized( + f, + self.date.as_ref(), + self.time.as_ref(), + self.off.as_ref(), + self.items.clone(), + locale, + ) } else { format(f, self.date.as_ref(), self.time.as_ref(), self.off.as_ref(), self.items.clone()) } diff --git a/src/format/strftime.rs b/src/format/strftime.rs index d50a460c8a..e701fc3f8d 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -528,93 +528,32 @@ fn test_strftime_docs_localized() { let dt = FixedOffset::east(34200).ymd(2001, 7, 8).and_hms_nano(0, 34, 59, 1_026_490_708); // date specifiers - assert_eq!(dt.format_localized("%Y", Locale::POSIX).to_string(), "2001"); - assert_eq!(dt.format_localized("%C", Locale::POSIX).to_string(), "20"); - assert_eq!(dt.format_localized("%y", Locale::POSIX).to_string(), "01"); - assert_eq!(dt.format_localized("%m", Locale::POSIX).to_string(), "07"); - assert_eq!(dt.format_localized("%b", Locale::POSIX).to_string(), "Jul"); - assert_eq!(dt.format_localized("%B", Locale::POSIX).to_string(), "July"); - assert_eq!(dt.format_localized("%h", Locale::POSIX).to_string(), "Jul"); - assert_eq!(dt.format_localized("%d", Locale::POSIX).to_string(), "08"); - assert_eq!(dt.format_localized("%e", Locale::POSIX).to_string(), " 8"); - assert_eq!( - dt.format_localized("%e", Locale::POSIX).to_string(), - dt.format_localized("%_d", Locale::POSIX).to_string() - ); - assert_eq!(dt.format_localized("%a", Locale::POSIX).to_string(), "Sun"); - assert_eq!(dt.format_localized("%A", Locale::POSIX).to_string(), "Sunday"); - assert_eq!(dt.format_localized("%w", Locale::POSIX).to_string(), "0"); - assert_eq!(dt.format_localized("%u", Locale::POSIX).to_string(), "7"); - assert_eq!(dt.format_localized("%U", Locale::POSIX).to_string(), "28"); - assert_eq!(dt.format_localized("%W", Locale::POSIX).to_string(), "27"); - assert_eq!(dt.format_localized("%G", Locale::POSIX).to_string(), "2001"); - assert_eq!(dt.format_localized("%g", Locale::POSIX).to_string(), "01"); - assert_eq!(dt.format_localized("%V", Locale::POSIX).to_string(), "27"); - assert_eq!(dt.format_localized("%j", Locale::POSIX).to_string(), "189"); - assert_eq!(dt.format_localized("%D", Locale::POSIX).to_string(), "07/08/01"); - assert_eq!(dt.format_localized("%x", Locale::POSIX).to_string(), "07/08/01"); - assert_eq!(dt.format_localized("%F", Locale::POSIX).to_string(), "2001-07-08"); - assert_eq!(dt.format_localized("%v", Locale::POSIX).to_string(), " 8-Jul-2001"); + assert_eq!(dt.format_localized("%b", Locale::fr_BE).to_string(), "jui"); + assert_eq!(dt.format_localized("%B", Locale::fr_BE).to_string(), "juillet"); + assert_eq!(dt.format_localized("%h", Locale::fr_BE).to_string(), "jui"); + assert_eq!(dt.format_localized("%a", Locale::fr_BE).to_string(), "dim"); + assert_eq!(dt.format_localized("%A", Locale::fr_BE).to_string(), "dimanche"); + assert_eq!(dt.format_localized("%D", Locale::fr_BE).to_string(), "07/08/01"); // TODO + assert_eq!(dt.format_localized("%x", Locale::fr_BE).to_string(), "07/08/01"); // TODO + assert_eq!(dt.format_localized("%F", Locale::fr_BE).to_string(), "2001-07-08"); // TODO + assert_eq!(dt.format_localized("%v", Locale::fr_BE).to_string(), " 8-jui-2001"); // TODO // time specifiers - assert_eq!(dt.format_localized("%H", Locale::POSIX).to_string(), "00"); - assert_eq!(dt.format_localized("%k", Locale::POSIX).to_string(), " 0"); - assert_eq!( - dt.format_localized("%k", Locale::POSIX).to_string(), - dt.format_localized("%_H", Locale::POSIX).to_string() - ); - assert_eq!(dt.format_localized("%I", Locale::POSIX).to_string(), "12"); - assert_eq!(dt.format_localized("%l", Locale::POSIX).to_string(), "12"); - assert_eq!( - dt.format_localized("%l", Locale::POSIX).to_string(), - dt.format_localized("%_I", Locale::POSIX).to_string() - ); - assert_eq!(dt.format_localized("%P", Locale::POSIX).to_string(), "am"); - assert_eq!(dt.format_localized("%p", Locale::POSIX).to_string(), "AM"); - assert_eq!(dt.format_localized("%M", Locale::POSIX).to_string(), "34"); - assert_eq!(dt.format_localized("%S", Locale::POSIX).to_string(), "60"); - assert_eq!(dt.format_localized("%f", Locale::POSIX).to_string(), "026490708"); - assert_eq!(dt.format_localized("%.f", Locale::POSIX).to_string(), ".026490708"); + assert_eq!(dt.format_localized("%P", Locale::fr_BE).to_string(), "am"); // TODO + assert_eq!(dt.format_localized("%p", Locale::fr_BE).to_string(), "AM"); // TODO assert_eq!( dt.with_nanosecond(1_026_490_000) .unwrap() - .format_localized("%.f", Locale::POSIX) + .format_localized("%.f", Locale::fr_BE) .to_string(), ".026490" ); - assert_eq!(dt.format_localized("%.3f", Locale::POSIX).to_string(), ".026"); - assert_eq!(dt.format_localized("%.6f", Locale::POSIX).to_string(), ".026490"); - assert_eq!(dt.format_localized("%.9f", Locale::POSIX).to_string(), ".026490708"); - assert_eq!(dt.format_localized("%3f", Locale::POSIX).to_string(), "026"); - assert_eq!(dt.format_localized("%6f", Locale::POSIX).to_string(), "026490"); - assert_eq!(dt.format_localized("%9f", Locale::POSIX).to_string(), "026490708"); - assert_eq!(dt.format_localized("%R", Locale::POSIX).to_string(), "00:34"); - assert_eq!(dt.format_localized("%T", Locale::POSIX).to_string(), "00:34:60"); - assert_eq!(dt.format_localized("%X", Locale::POSIX).to_string(), "00:34:60"); - assert_eq!(dt.format_localized("%r", Locale::POSIX).to_string(), "12:34:60 AM"); - - // time zone specifiers - //assert_eq!(dt.format_localized("%Z", Locale::POSIX).to_string(), "ACST"); - assert_eq!(dt.format_localized("%z", Locale::POSIX).to_string(), "+0930"); - assert_eq!(dt.format_localized("%:z", Locale::POSIX).to_string(), "+09:30"); + assert_eq!(dt.format_localized("%R", Locale::fr_BE).to_string(), "00:34"); // TODO + assert_eq!(dt.format_localized("%T", Locale::fr_BE).to_string(), "00:34:60"); // TODO + assert_eq!(dt.format_localized("%X", Locale::fr_BE).to_string(), "00:34:60"); // TODO + assert_eq!(dt.format_localized("%r", Locale::fr_BE).to_string(), "12:34:60 AM"); // TODO // date & time specifiers - assert_eq!(dt.format_localized("%c", Locale::POSIX).to_string(), "Sun Jul 8 00:34:60 2001"); - assert_eq!( - dt.format_localized("%+", Locale::POSIX).to_string(), - "2001-07-08T00:34:60.026490708+09:30" - ); - assert_eq!( - dt.with_nanosecond(1_026_490_000) - .unwrap() - .format_localized("%+", Locale::POSIX) - .to_string(), - "2001-07-08T00:34:60.026490+09:30" - ); - assert_eq!(dt.format_localized("%s", Locale::POSIX).to_string(), "994518299"); - - // special specifiers - assert_eq!(dt.format_localized("%t", Locale::POSIX).to_string(), "\t"); - assert_eq!(dt.format_localized("%n", Locale::POSIX).to_string(), "\n"); - assert_eq!(dt.format_localized("%%", Locale::POSIX).to_string(), "%"); + assert_eq!(dt.format_localized("%c", Locale::fr_BE).to_string(), "Sun Jul 8 00:34:60 2001"); + // TODO } diff --git a/src/lib.rs b/src/lib.rs index 31b9d8b54a..1cdb79dfe0 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -481,6 +481,9 @@ pub mod prelude { #[cfg(feature = "clock")] #[doc(no_inline)] pub use Local; + #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + #[doc(no_inline)] + pub use Locale; #[doc(no_inline)] pub use SubsecRound; #[doc(no_inline)] @@ -493,9 +496,6 @@ pub mod prelude { pub use {NaiveDate, NaiveDateTime, NaiveTime}; #[doc(no_inline)] pub use {Offset, TimeZone}; - #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] - #[doc(no_inline)] - pub use Locale; } // useful throughout the codebase From 048b144171b8dca2e7110da1f85f6c054ffa9086 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 19 Jul 2020 03:06:37 +0200 Subject: [PATCH 33/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/strftime.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/format/strftime.rs b/src/format/strftime.rs index e701fc3f8d..1ed3027b90 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -554,6 +554,6 @@ fn test_strftime_docs_localized() { assert_eq!(dt.format_localized("%r", Locale::fr_BE).to_string(), "12:34:60 AM"); // TODO // date & time specifiers - assert_eq!(dt.format_localized("%c", Locale::fr_BE).to_string(), "Sun Jul 8 00:34:60 2001"); + assert_eq!(dt.format_localized("%c", Locale::fr_BE).to_string(), "dim jui 8 00:34:60 2001"); // TODO } From 1acab1d33c86e73f9691f805b67308c30eaa67b9 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 19 Jul 2020 04:18:46 +0200 Subject: [PATCH 34/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/date.rs | 2 +- src/datetime.rs | 2 +- src/format/locales.rs | 16 ++++++ src/format/mod.rs | 18 +++++-- src/format/strftime.rs | 107 +++++++++++++++++++++++++++-------------- 5 files changed, 104 insertions(+), 41 deletions(-) diff --git a/src/date.rs b/src/date.rs index ca6cfa3bbd..ae0f893d11 100644 --- a/src/date.rs +++ b/src/date.rs @@ -329,7 +329,7 @@ where fmt: &'a str, locale: Locale, ) -> DelayedFormat> { - self.format_localized_with_items(StrftimeItems::new(fmt), locale) + self.format_localized_with_items(StrftimeItems::new_with_locale(fmt, locale), locale) } } diff --git a/src/datetime.rs b/src/datetime.rs index 31a765567d..ad7205e8f7 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -528,7 +528,7 @@ where fmt: &'a str, locale: Locale, ) -> DelayedFormat> { - self.format_localized_with_items(StrftimeItems::new(fmt), locale) + self.format_localized_with_items(StrftimeItems::new_with_locale(fmt, locale), locale) } } diff --git a/src/format/locales.rs b/src/format/locales.rs index cc4910b866..f7b4bbde5b 100644 --- a/src/format/locales.rs +++ b/src/format/locales.rs @@ -15,3 +15,19 @@ pub(crate) fn short_weekdays(locale: Locale) -> &'static [&'static str] { pub(crate) fn long_weekdays(locale: Locale) -> &'static [&'static str] { locale_match!(locale => LC_TIME::DAY) } + +pub(crate) fn am_pm(locale: Locale) -> &'static [&'static str] { + locale_match!(locale => LC_TIME::AM_PM) +} + +pub(crate) fn d_fmt(locale: Locale) -> &'static str { + locale_match!(locale => LC_TIME::D_FMT) +} + +pub(crate) fn d_t_fmt(locale: Locale) -> &'static str { + locale_match!(locale => LC_TIME::D_T_FMT) +} + +pub(crate) fn t_fmt(locale: Locale) -> &'static str { + locale_match!(locale => LC_TIME::T_FMT) +} diff --git a/src/format/mod.rs b/src/format/mod.rs index 15e9d4f0c4..ba20fe9944 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -413,7 +413,7 @@ fn format_inner<'a>( ) -> fmt::Result { #[cfg(feature = "locales")] let locale = _locale.unwrap_or(Locale::POSIX); - // full and abbreviated month and weekday names + #[cfg(feature = "locales")] let short_months = locales::short_months(locale); #[cfg(feature = "locales")] @@ -422,6 +422,9 @@ fn format_inner<'a>( let short_weekdays = locales::short_weekdays(locale); #[cfg(feature = "locales")] let long_weekdays = locales::long_weekdays(locale); + #[cfg(feature = "locales")] + let am_pm = locales::am_pm(locale); + #[cfg(not(feature = "locales"))] let short_months = &["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; @@ -445,6 +448,11 @@ fn format_inner<'a>( #[cfg(not(feature = "locales"))] let long_weekdays = &["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; + #[cfg(not(feature = "locales"))] + let am_pm = &["AM", "PM"]; + + let am_pm_lowercase: Vec<_> = am_pm.iter().map(|x| x.to_lowercase()).collect(); + let am_pm_lowercase = &[am_pm_lowercase[0].as_str(), am_pm_lowercase[1].as_str()]; use core::fmt::Write; @@ -563,11 +571,15 @@ fn format_inner<'a>( Ok(()) }), LowerAmPm => time.map(|t| { - result.push_str(if t.hour12().0 { "pm" } else { "am" }); + result.push_str(if t.hour12().0 { + am_pm_lowercase[1] + } else { + am_pm_lowercase[0] + }); Ok(()) }), UpperAmPm => time.map(|t| { - result.push_str(if t.hour12().0 { "PM" } else { "AM" }); + result.push_str(if t.hour12().0 { am_pm[1] } else { am_pm[0] }); Ok(()) }), Nanosecond => time.map(|t| { diff --git a/src/format/strftime.rs b/src/format/strftime.rs index 1ed3027b90..fb66c521ad 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -159,7 +159,7 @@ Notes: */ -use super::{Fixed, InternalFixed, InternalInternal, Item, Numeric, Pad}; +use super::{locales, Fixed, InternalFixed, InternalInternal, Item, Locale, Numeric, Pad}; /// Parsing iterator for `strftime`-like format strings. #[derive(Clone, Debug)] @@ -169,14 +169,55 @@ pub struct StrftimeItems<'a> { /// If the current specifier is composed of multiple formatting items (e.g. `%+`), /// parser refers to the statically reconstructed slice of them. /// If `recons` is not empty they have to be returned earlier than the `remainder`. - recons: &'static [Item<'static>], + recons: Vec>, + /// Date format + d_fmt: Vec>, + /// Date and time format + d_t_fmt: Vec>, + /// Time format + t_fmt: Vec>, } impl<'a> StrftimeItems<'a> { /// Creates a new parsing iterator from the `strftime`-like format string. pub fn new(s: &'a str) -> StrftimeItems<'a> { - static FMT_NONE: [Item<'static>; 0] = []; - StrftimeItems { remainder: s, recons: &FMT_NONE } + static D_FMT: &[Item<'static>] = + &[num0!(Month), lit!("/"), num0!(Day), lit!("/"), num0!(YearMod100)]; + static D_T_FMT: &[Item<'static>] = &[ + fix!(ShortWeekdayName), + sp!(" "), + fix!(ShortMonthName), + sp!(" "), + nums!(Day), + sp!(" "), + num0!(Hour), + lit!(":"), + num0!(Minute), + lit!(":"), + num0!(Second), + sp!(" "), + num0!(Year), + ]; + static T_FMT: &[Item<'static>] = + &[num0!(Hour), lit!(":"), num0!(Minute), lit!(":"), num0!(Second)]; + + StrftimeItems { + remainder: s, + recons: Vec::new(), + d_fmt: D_FMT.to_vec(), + d_t_fmt: D_T_FMT.to_vec(), + t_fmt: T_FMT.to_vec(), + } + } + + /// Creates a new parsing iterator from the `strftime`-like format string. + #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + pub fn new_with_locale(s: &'a str, locale: Locale) -> StrftimeItems<'a> { + let d_fmt = StrftimeItems::new(locales::d_fmt(locale)).collect(); + let d_t_fmt = StrftimeItems::new(locales::d_t_fmt(locale)).collect(); + let t_fmt = StrftimeItems::new(locales::t_fmt(locale)).collect(); + + StrftimeItems { remainder: s, recons: Vec::new(), d_fmt, d_t_fmt, t_fmt } } } @@ -189,7 +230,7 @@ impl<'a> Iterator for StrftimeItems<'a> { // we have some reconstructed items to return if !self.recons.is_empty() { let item = self.recons[0].clone(); - self.recons = &self.recons[1..]; + self.recons = self.recons[1..].to_vec(); return Some(item); } @@ -228,8 +269,7 @@ impl<'a> Iterator for StrftimeItems<'a> { macro_rules! recons { [$head:expr, $($tail:expr),+] => ({ - const RECONS: &'static [Item<'static>] = &[$($tail),+]; - self.recons = RECONS; + self.recons = vec![$($tail),+]; $head }) } @@ -253,26 +293,18 @@ impl<'a> Iterator for StrftimeItems<'a> { 'U' => num0!(WeekFromSun), 'V' => num0!(IsoWeek), 'W' => num0!(WeekFromMon), - 'X' => recons![num0!(Hour), lit!(":"), num0!(Minute), lit!(":"), num0!(Second)], + 'X' => { + self.recons = self.t_fmt[1..].to_vec(); + self.t_fmt[0].clone() + } 'Y' => num0!(Year), 'Z' => fix!(TimezoneName), 'a' => fix!(ShortWeekdayName), 'b' | 'h' => fix!(ShortMonthName), - 'c' => recons![ - fix!(ShortWeekdayName), - sp!(" "), - fix!(ShortMonthName), - sp!(" "), - nums!(Day), - sp!(" "), - num0!(Hour), - lit!(":"), - num0!(Minute), - lit!(":"), - num0!(Second), - sp!(" "), - num0!(Year) - ], + 'c' => { + self.recons = self.d_t_fmt[1..].to_vec(); + self.d_t_fmt[0].clone() + } 'd' => num0!(Day), 'e' => nums!(Day), 'f' => num0!(Nanosecond), @@ -300,7 +332,8 @@ impl<'a> Iterator for StrftimeItems<'a> { } 'w' => num!(NumDaysFromSun), 'x' => { - recons![num0!(Month), lit!("/"), num0!(Day), lit!("/"), num0!(YearMod100)] + self.recons = self.d_fmt[1..].to_vec(); + self.d_fmt[0].clone() } 'y' => num0!(YearMod100), 'z' => { @@ -522,7 +555,6 @@ fn test_strftime_docs() { #[cfg(all(feature = "locales", test))] #[test] fn test_strftime_docs_localized() { - use pure_rust_locales::Locale; use {FixedOffset, TimeZone, Timelike}; let dt = FixedOffset::east(34200).ymd(2001, 7, 8).and_hms_nano(0, 34, 59, 1_026_490_708); @@ -533,14 +565,14 @@ fn test_strftime_docs_localized() { assert_eq!(dt.format_localized("%h", Locale::fr_BE).to_string(), "jui"); assert_eq!(dt.format_localized("%a", Locale::fr_BE).to_string(), "dim"); assert_eq!(dt.format_localized("%A", Locale::fr_BE).to_string(), "dimanche"); - assert_eq!(dt.format_localized("%D", Locale::fr_BE).to_string(), "07/08/01"); // TODO - assert_eq!(dt.format_localized("%x", Locale::fr_BE).to_string(), "07/08/01"); // TODO - assert_eq!(dt.format_localized("%F", Locale::fr_BE).to_string(), "2001-07-08"); // TODO - assert_eq!(dt.format_localized("%v", Locale::fr_BE).to_string(), " 8-jui-2001"); // TODO + assert_eq!(dt.format_localized("%D", Locale::fr_BE).to_string(), "07/08/01"); + assert_eq!(dt.format_localized("%x", Locale::fr_BE).to_string(), "08/07/01"); + assert_eq!(dt.format_localized("%F", Locale::fr_BE).to_string(), "2001-07-08"); + assert_eq!(dt.format_localized("%v", Locale::fr_BE).to_string(), " 8-jui-2001"); // time specifiers - assert_eq!(dt.format_localized("%P", Locale::fr_BE).to_string(), "am"); // TODO - assert_eq!(dt.format_localized("%p", Locale::fr_BE).to_string(), "AM"); // TODO + assert_eq!(dt.format_localized("%P", Locale::fr_BE).to_string(), ""); + assert_eq!(dt.format_localized("%p", Locale::fr_BE).to_string(), ""); assert_eq!( dt.with_nanosecond(1_026_490_000) .unwrap() @@ -548,12 +580,15 @@ fn test_strftime_docs_localized() { .to_string(), ".026490" ); - assert_eq!(dt.format_localized("%R", Locale::fr_BE).to_string(), "00:34"); // TODO - assert_eq!(dt.format_localized("%T", Locale::fr_BE).to_string(), "00:34:60"); // TODO - assert_eq!(dt.format_localized("%X", Locale::fr_BE).to_string(), "00:34:60"); // TODO - assert_eq!(dt.format_localized("%r", Locale::fr_BE).to_string(), "12:34:60 AM"); // TODO + assert_eq!(dt.format_localized("%R", Locale::fr_BE).to_string(), "00:34"); + assert_eq!(dt.format_localized("%T", Locale::fr_BE).to_string(), "00:34:60"); + assert_eq!(dt.format_localized("%X", Locale::fr_BE).to_string(), "00:34:60"); + assert_eq!(dt.format_localized("%r", Locale::fr_BE).to_string(), "12:34:60 "); // date & time specifiers - assert_eq!(dt.format_localized("%c", Locale::fr_BE).to_string(), "dim jui 8 00:34:60 2001"); + assert_eq!( + dt.format_localized("%c", Locale::fr_BE).to_string(), + "dim 08 jui 2001 00:34:60 +09:30" + ); // TODO } From 2052de7c0ec59a8e1fc2b0e9985f2860c43f5dfe Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 19 Jul 2020 04:21:00 +0200 Subject: [PATCH 35/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/strftime.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/format/strftime.rs b/src/format/strftime.rs index fb66c521ad..b753e87535 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -38,7 +38,7 @@ The following specifiers are available both to formatting and parsing. | `%j` | `189` | Day of the year (001--366), zero-padded to 3 digits. | | | | | | `%D` | `07/08/01` | Month-day-year format. Same as `%m/%d/%y`. | -| `%x` | `07/08/01` | Same as `%D`. | +| `%x` | `07/08/01` | Locale's date representation (e.g., 12/31/99). | | `%F` | `2001-07-08` | Year-month-day format (ISO 8601). Same as `%Y-%m-%d`. | | `%v` | ` 8-Jul-2001` | Day-month-year format. Same as `%e-%b-%Y`. | | | | | @@ -64,7 +64,7 @@ The following specifiers are available both to formatting and parsing. | | | | | `%R` | `00:34` | Hour-minute format. Same as `%H:%M`. | | `%T` | `00:34:60` | Hour-minute-second format. Same as `%H:%M:%S`. | -| `%X` | `00:34:60` | Same as `%T`. | +| `%X` | `00:34:60` | Locale's time representation (e.g., 23:13:48). | | `%r` | `12:34:60 AM` | Hour-minute-second format in 12-hour clocks. Same as `%I:%M:%S %p`. | | | | | | | | **TIME ZONE SPECIFIERS:** | @@ -74,7 +74,7 @@ The following specifiers are available both to formatting and parsing. | `%#z` | `+09` | *Parsing only:* Same as `%z` but allows minutes to be missing or present. | | | | | | | | **DATE & TIME SPECIFIERS:** | -|`%c`|`Sun Jul 8 00:34:60 2001`|`ctime` date & time format. Same as `%a %b %e %T %Y` sans `\n`.| +|`%c`|`Sun Jul 8 00:34:60 2001`|Locale's date and time (e.g., Thu Mar 3 23:05:25 2005). | | `%+` | `2001-07-08T00:34:60.026490+09:30` | ISO 8601 / RFC 3339 date & time format. [^6] | | | | | | `%s` | `994518299` | UNIX timestamp, the number of seconds since 1970-01-01 00:00 UTC. [^7]| From 1f2fd4fa611c7d033aa1b1cce307dc5faad994ec Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 19 Jul 2020 04:26:14 +0200 Subject: [PATCH 36/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/strftime.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/format/strftime.rs b/src/format/strftime.rs index b753e87535..2b42a31c9a 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -590,5 +590,4 @@ fn test_strftime_docs_localized() { dt.format_localized("%c", Locale::fr_BE).to_string(), "dim 08 jui 2001 00:34:60 +09:30" ); - // TODO } From d786694e583a306801fe7a6302eb851ecdaea453 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 19 Jul 2020 04:28:23 +0200 Subject: [PATCH 37/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/mod.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/format/mod.rs b/src/format/mod.rs index ba20fe9944..135ec05ac0 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -39,7 +39,7 @@ use {Datelike, Timelike}; use {ParseWeekdayError, Weekday}; #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] -mod locales; +pub(crate) mod locales; pub use self::parse::parse; pub use self::parsed::Parsed; From 1a80aa081f6faa5e9a5a062d9be012d353bb1f03 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 19 Jul 2020 04:30:12 +0200 Subject: [PATCH 38/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/mod.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/format/mod.rs b/src/format/mod.rs index 135ec05ac0..5677668fb4 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -796,6 +796,7 @@ impl<'a, I: Iterator + Clone, B: Borrow>> DelayedFormat { #[cfg(any(feature = "alloc", feature = "std", test))] impl<'a, I: Iterator + Clone, B: Borrow>> fmt::Display for DelayedFormat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + #[cfg(feature = "locales")] if let Some(locale) = self.locale { format_localized( f, @@ -808,6 +809,8 @@ impl<'a, I: Iterator + Clone, B: Borrow>> fmt::Display for De } else { format(f, self.date.as_ref(), self.time.as_ref(), self.off.as_ref(), self.items.clone()) } + #[cfg(not(feature = "locales"))] + format(f, self.date.as_ref(), self.time.as_ref(), self.off.as_ref(), self.items.clone()) } } From 3ef34a0a72085672097f948e7ec189ea4f6def7c Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 19 Jul 2020 04:30:44 +0200 Subject: [PATCH 39/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/mod.rs | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/format/mod.rs b/src/format/mod.rs index 5677668fb4..4a0009362b 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -798,18 +798,16 @@ impl<'a, I: Iterator + Clone, B: Borrow>> fmt::Display for De fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { #[cfg(feature = "locales")] if let Some(locale) = self.locale { - format_localized( + return format_localized( f, self.date.as_ref(), self.time.as_ref(), self.off.as_ref(), self.items.clone(), locale, - ) - } else { - format(f, self.date.as_ref(), self.time.as_ref(), self.off.as_ref(), self.items.clone()) + ); } - #[cfg(not(feature = "locales"))] + format(f, self.date.as_ref(), self.time.as_ref(), self.off.as_ref(), self.items.clone()) } } From 3d5293695f98304e2957ec8cac07c759a8c5f9d4 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 19 Jul 2020 04:32:46 +0200 Subject: [PATCH 40/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/strftime.rs | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/format/strftime.rs b/src/format/strftime.rs index 2b42a31c9a..dfa90769d7 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -159,7 +159,9 @@ Notes: */ -use super::{locales, Fixed, InternalFixed, InternalInternal, Item, Locale, Numeric, Pad}; +#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] +use super::{locales, Locale}; +use super::{Fixed, InternalFixed, InternalInternal, Item, Numeric, Pad}; /// Parsing iterator for `strftime`-like format strings. #[derive(Clone, Debug)] From e07be465c49f017f82c7da09637fb4d90d6365f6 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 19 Jul 2020 04:44:01 +0200 Subject: [PATCH 41/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/strftime.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/format/strftime.rs b/src/format/strftime.rs index dfa90769d7..fdd5f1954e 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -271,7 +271,7 @@ impl<'a> Iterator for StrftimeItems<'a> { macro_rules! recons { [$head:expr, $($tail:expr),+] => ({ - self.recons = vec![$($tail),+]; + self.recons = <[_]>::into_vec(Box::new([$($tail),+])); $head }) } From 5986e3a9889531b06513efb968cfcc34b5403e60 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 19 Jul 2020 04:48:43 +0200 Subject: [PATCH 42/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/strftime.rs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/format/strftime.rs b/src/format/strftime.rs index fdd5f1954e..4421c4ba47 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -171,7 +171,10 @@ pub struct StrftimeItems<'a> { /// If the current specifier is composed of multiple formatting items (e.g. `%+`), /// parser refers to the statically reconstructed slice of them. /// If `recons` is not empty they have to be returned earlier than the `remainder`. + #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] recons: Vec>, + #[cfg(not(all(feature = "locales", any(feature = "alloc", feature = "std", test))))] + recons: &'static [Item<'static>], /// Date format d_fmt: Vec>, /// Date and time format @@ -271,7 +274,7 @@ impl<'a> Iterator for StrftimeItems<'a> { macro_rules! recons { [$head:expr, $($tail:expr),+] => ({ - self.recons = <[_]>::into_vec(Box::new([$($tail),+])); + self.recons = vec![$($tail),+]; $head }) } From a4176284c3ca955864290466d46acca40c16016d Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 19 Jul 2020 05:20:24 +0200 Subject: [PATCH 43/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/mod.rs | 20 +++---- src/format/strftime.rs | 115 +++++++++++++++++++++++++++++++++++------ 2 files changed, 111 insertions(+), 24 deletions(-) diff --git a/src/format/mod.rs b/src/format/mod.rs index 4a0009362b..c642ff01bb 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -797,15 +797,17 @@ impl<'a, I: Iterator + Clone, B: Borrow>> DelayedFormat { impl<'a, I: Iterator + Clone, B: Borrow>> fmt::Display for DelayedFormat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { #[cfg(feature = "locales")] - if let Some(locale) = self.locale { - return format_localized( - f, - self.date.as_ref(), - self.time.as_ref(), - self.off.as_ref(), - self.items.clone(), - locale, - ); + { + if let Some(locale) = self.locale { + return format_localized( + f, + self.date.as_ref(), + self.time.as_ref(), + self.off.as_ref(), + self.items.clone(), + locale, + ); + } } format(f, self.date.as_ref(), self.time.as_ref(), self.off.as_ref(), self.items.clone()) diff --git a/src/format/strftime.rs b/src/format/strftime.rs index 4421c4ba47..e900e3955f 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -176,19 +176,28 @@ pub struct StrftimeItems<'a> { #[cfg(not(all(feature = "locales", any(feature = "alloc", feature = "std", test))))] recons: &'static [Item<'static>], /// Date format + #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] d_fmt: Vec>, + #[cfg(not(all(feature = "locales", any(feature = "alloc", feature = "std", test))))] + d_fmt: &'static [Item<'static>], /// Date and time format + #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] d_t_fmt: Vec>, + #[cfg(not(all(feature = "locales", any(feature = "alloc", feature = "std", test))))] + d_t_fmt: &'static [Item<'static>], /// Time format + #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] t_fmt: Vec>, + #[cfg(not(all(feature = "locales", any(feature = "alloc", feature = "std", test))))] + t_fmt: &'static [Item<'static>], } impl<'a> StrftimeItems<'a> { /// Creates a new parsing iterator from the `strftime`-like format string. pub fn new(s: &'a str) -> StrftimeItems<'a> { - static D_FMT: &[Item<'static>] = + static D_FMT: &'static [Item<'static>] = &[num0!(Month), lit!("/"), num0!(Day), lit!("/"), num0!(YearMod100)]; - static D_T_FMT: &[Item<'static>] = &[ + static D_T_FMT: &'static [Item<'static>] = &[ fix!(ShortWeekdayName), sp!(" "), fix!(ShortMonthName), @@ -203,15 +212,31 @@ impl<'a> StrftimeItems<'a> { sp!(" "), num0!(Year), ]; - static T_FMT: &[Item<'static>] = + static T_FMT: &'static [Item<'static>] = &[num0!(Hour), lit!(":"), num0!(Minute), lit!(":"), num0!(Second)]; + #[cfg(not(all(feature = "locales", any(feature = "alloc", feature = "std", test))))] + static FMT_NONE: &'static [Item<'static>; 0] = &[]; + + #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + { + StrftimeItems { + remainder: s, + recons: Vec::new(), + d_fmt: D_FMT.to_vec(), + d_t_fmt: D_T_FMT.to_vec(), + t_fmt: T_FMT.to_vec(), + } + } - StrftimeItems { - remainder: s, - recons: Vec::new(), - d_fmt: D_FMT.to_vec(), - d_t_fmt: D_T_FMT.to_vec(), - t_fmt: T_FMT.to_vec(), + #[cfg(not(all(feature = "locales", any(feature = "alloc", feature = "std", test))))] + { + StrftimeItems { + remainder: s, + recons: FMT_NONE, + d_fmt: D_FMT, + d_t_fmt: D_T_FMT, + t_fmt: T_FMT, + } } } @@ -222,7 +247,13 @@ impl<'a> StrftimeItems<'a> { let d_t_fmt = StrftimeItems::new(locales::d_t_fmt(locale)).collect(); let t_fmt = StrftimeItems::new(locales::t_fmt(locale)).collect(); - StrftimeItems { remainder: s, recons: Vec::new(), d_fmt, d_t_fmt, t_fmt } + StrftimeItems { + remainder: s, + recons: Vec::new(), + d_fmt: d_fmt, + d_t_fmt: d_t_fmt, + t_fmt: t_fmt, + } } } @@ -235,7 +266,14 @@ impl<'a> Iterator for StrftimeItems<'a> { // we have some reconstructed items to return if !self.recons.is_empty() { let item = self.recons[0].clone(); - self.recons = self.recons[1..].to_vec(); + #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + { + self.recons = self.recons[1..].to_vec(); + } + #[cfg(not(all(feature = "locales", any(feature = "alloc", feature = "std", test))))] + { + self.recons = &self.recons[1..]; + } return Some(item); } @@ -274,7 +312,15 @@ impl<'a> Iterator for StrftimeItems<'a> { macro_rules! recons { [$head:expr, $($tail:expr),+] => ({ - self.recons = vec![$($tail),+]; + #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + { + self.recons = vec![$($tail),+]; + } + #[cfg(not(all(feature = "locales", any(feature = "alloc", feature = "std", test))))] + { + const RECONS: &'static [Item<'static>] = &[$($tail),+]; + self.recons = RECONS; + } $head }) } @@ -299,7 +345,20 @@ impl<'a> Iterator for StrftimeItems<'a> { 'V' => num0!(IsoWeek), 'W' => num0!(WeekFromMon), 'X' => { - self.recons = self.t_fmt[1..].to_vec(); + #[cfg(all( + feature = "locales", + any(feature = "alloc", feature = "std", test) + ))] + { + self.recons = self.t_fmt[1..].to_vec(); + } + #[cfg(not(all( + feature = "locales", + any(feature = "alloc", feature = "std", test) + )))] + { + self.recons = &self.t_fmt[1..]; + } self.t_fmt[0].clone() } 'Y' => num0!(Year), @@ -307,7 +366,20 @@ impl<'a> Iterator for StrftimeItems<'a> { 'a' => fix!(ShortWeekdayName), 'b' | 'h' => fix!(ShortMonthName), 'c' => { - self.recons = self.d_t_fmt[1..].to_vec(); + #[cfg(all( + feature = "locales", + any(feature = "alloc", feature = "std", test) + ))] + { + self.recons = self.d_t_fmt[1..].to_vec(); + } + #[cfg(not(all( + feature = "locales", + any(feature = "alloc", feature = "std", test) + )))] + { + self.recons = &self.d_t_fmt[1..]; + } self.d_t_fmt[0].clone() } 'd' => num0!(Day), @@ -337,7 +409,20 @@ impl<'a> Iterator for StrftimeItems<'a> { } 'w' => num!(NumDaysFromSun), 'x' => { - self.recons = self.d_fmt[1..].to_vec(); + #[cfg(all( + feature = "locales", + any(feature = "alloc", feature = "std", test) + ))] + { + self.recons = self.d_fmt[1..].to_vec(); + } + #[cfg(not(all( + feature = "locales", + any(feature = "alloc", feature = "std", test) + )))] + { + self.recons = &self.d_fmt[1..]; + } self.d_fmt[0].clone() } 'y' => num0!(YearMod100), From 9cb89faa4774fd842c076b98a8b7b97f17881f4d Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 19 Jul 2020 05:28:18 +0200 Subject: [PATCH 44/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- ci/lint.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ci/lint.sh b/ci/lint.sh index bde0392b7d..360d72cd22 100755 --- a/ci/lint.sh +++ b/ci/lint.sh @@ -7,7 +7,7 @@ source "${BASH_SOURCE[0]%/*}/_shlib.sh" main() { # rustflags are present because of: https://github.com/rust-lang/rust-clippy/issues/5749 - runt env RUSTFLAGS="-Dwarnings" cargo clippy --color=always -- -D warnings + runt env RUSTFLAGS="-Dwarnings" cargo clippy --color=always -- -D warnings -A clippy::manual-non-exhaustive runt cargo fmt -- --check --color=always runt make readme runv git diff --exit-code -- README.md From 5d1d9f17102eb49eef6f278da6cd516533429097 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 19 Jul 2020 05:36:17 +0200 Subject: [PATCH 45/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/lib.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/lib.rs b/src/lib.rs index 1cdb79dfe0..6e6ae8c4b1 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -216,7 +216,7 @@ //! help of an additional C library. This functionality is under the feature //! `locales`: //! -//! ```ignore +//! ```text //! chrono { version = ..., features = ["locales"] //! ``` //! From 119c4136d2d8c482bb5af9ee377818e0aadfd927 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 19 Jul 2020 05:42:32 +0200 Subject: [PATCH 46/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- README.md | 2 +- ci/github.sh | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index d3236302ec..b995589e0b 100644 --- a/README.md +++ b/README.md @@ -224,7 +224,7 @@ Chrono now also provides date formatting in almost any language without the help of an additional C library. This functionality is under the feature `locales`: -``` +```text chrono { version = ..., features = ["locales"] ``` diff --git a/ci/github.sh b/ci/github.sh index 681ea03cbf..486fb4457a 100755 --- a/ci/github.sh +++ b/ci/github.sh @@ -56,7 +56,7 @@ test_all_tzs() { test_regular() { tz="$1" && shift - runt env TZ="$tz" cargo test --features __doctest --color=always -- --color=always + runt env TZ="$tz" cargo test --features __doctest,locales --color=always -- --color=always for feature in "${FEATURES[@]}"; do runt env TZ="$tz" cargo test --no-default-features --features "$feature" --lib --color=always -- --color=always done From 790f9d5edf108ea751bdb984fd56dc375d2f8852 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 19 Jul 2020 06:06:01 +0200 Subject: [PATCH 47/60] Small clean-up --- src/format/strftime.rs | 7 ------- 1 file changed, 7 deletions(-) diff --git a/src/format/strftime.rs b/src/format/strftime.rs index e900e3955f..c49a235202 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -663,13 +663,6 @@ fn test_strftime_docs_localized() { // time specifiers assert_eq!(dt.format_localized("%P", Locale::fr_BE).to_string(), ""); assert_eq!(dt.format_localized("%p", Locale::fr_BE).to_string(), ""); - assert_eq!( - dt.with_nanosecond(1_026_490_000) - .unwrap() - .format_localized("%.f", Locale::fr_BE) - .to_string(), - ".026490" - ); assert_eq!(dt.format_localized("%R", Locale::fr_BE).to_string(), "00:34"); assert_eq!(dt.format_localized("%T", Locale::fr_BE).to_string(), "00:34:60"); assert_eq!(dt.format_localized("%X", Locale::fr_BE).to_string(), "00:34:60"); From 87aa146221d86c340fadc226a4be1326e90cfab2 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 24 Jul 2020 20:12:20 +0200 Subject: [PATCH 48/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- Cargo.toml | 2 +- README.md | 4 +++- src/date.rs | 6 +++--- src/datetime.rs | 6 +++--- src/format/mod.rs | 8 ++++---- src/format/strftime.rs | 36 ++++++++++++++++++------------------ src/lib.rs | 8 +++++--- 7 files changed, 37 insertions(+), 33 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 666990fbec..68237a0d8f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,7 @@ alloc = [] std = [] clock = ["time", "std"] wasmbind = ["wasm-bindgen", "js-sys"] -locales = ["pure-rust-locales"] +locales = ["pure-rust-locales", "alloc"] __internal_bench = [] __doctest = [] diff --git a/README.md b/README.md index b995589e0b..cfa87e9ed1 100644 --- a/README.md +++ b/README.md @@ -225,9 +225,11 @@ help of an additional C library. This functionality is under the feature `locales`: ```text -chrono { version = ..., features = ["locales"] +chrono { version = "0.4", features = ["locales"] ``` +The `locales` feature requires and implies at least the `alloc` feature. + ```rust use chrono::prelude::*; diff --git a/src/date.rs b/src/date.rs index ae0f893d11..60a81de725 100644 --- a/src/date.rs +++ b/src/date.rs @@ -10,7 +10,7 @@ use core::ops::{Add, Sub}; use core::{fmt, hash}; use oldtime::Duration as OldDuration; -#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] +#[cfg(feature = "locales")] use format::Locale; #[cfg(any(feature = "alloc", feature = "std", test))] use format::{DelayedFormat, Item, StrftimeItems}; @@ -299,7 +299,7 @@ where } /// Formats the date with the specified formatting items and locale. - #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + #[cfg(feature = "locales")] #[inline] pub fn format_localized_with_items<'a, I, B>( &self, @@ -322,7 +322,7 @@ where /// Formats the date with the specified format string and locale. /// See the [`format::strftime` module](./format/strftime/index.html) /// on the supported escape sequences. - #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + #[cfg(feature = "locales")] #[inline] pub fn format_localized<'a>( &self, diff --git a/src/datetime.rs b/src/datetime.rs index ad7205e8f7..dbca333564 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -19,7 +19,7 @@ use std::string::ToString; use core::borrow::Borrow; #[cfg(any(feature = "alloc", feature = "std", test))] use format::DelayedFormat; -#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] +#[cfg(feature = "locales")] use format::Locale; use format::{parse, ParseError, ParseResult, Parsed, StrftimeItems}; use format::{Fixed, Item}; @@ -497,7 +497,7 @@ where } /// Formats the combined date and time with the specified formatting items and locale. - #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + #[cfg(feature = "locales")] #[inline] pub fn format_localized_with_items<'a, I, B>( &self, @@ -521,7 +521,7 @@ where /// Formats the combined date and time with the specified format string and locale. /// See the [`format::strftime` module](./format/strftime/index.html) /// on the supported escape sequences. - #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + #[cfg(feature = "locales")] #[inline] pub fn format_localized<'a>( &self, diff --git a/src/format/mod.rs b/src/format/mod.rs index c642ff01bb..42fbc746db 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -38,13 +38,13 @@ use offset::{FixedOffset, Offset}; use {Datelike, Timelike}; use {ParseWeekdayError, Weekday}; -#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] +#[cfg(feature = "locales")] pub(crate) mod locales; pub use self::parse::parse; pub use self::parsed::Parsed; pub use self::strftime::StrftimeItems; -#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] +#[cfg(feature = "locales")] pub use pure_rust_locales::Locale; #[cfg(not(feature = "locales"))] @@ -853,7 +853,7 @@ impl FromStr for Weekday { } /// Formats single formatting item -#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] +#[cfg(feature = "locales")] pub fn format_item_localized<'a>( w: &mut fmt::Formatter, date: Option<&NaiveDate>, @@ -869,7 +869,7 @@ pub fn format_item_localized<'a>( /// Tries to format given arguments with given formatting items. /// Internally used by `DelayedFormat`. -#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] +#[cfg(feature = "locales")] pub fn format_localized<'a, I, B>( w: &mut fmt::Formatter, date: Option<&NaiveDate>, diff --git a/src/format/strftime.rs b/src/format/strftime.rs index e900e3955f..bb8b06d3a7 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -159,7 +159,7 @@ Notes: */ -#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] +#[cfg(feature = "locales")] use super::{locales, Locale}; use super::{Fixed, InternalFixed, InternalInternal, Item, Numeric, Pad}; @@ -171,24 +171,24 @@ pub struct StrftimeItems<'a> { /// If the current specifier is composed of multiple formatting items (e.g. `%+`), /// parser refers to the statically reconstructed slice of them. /// If `recons` is not empty they have to be returned earlier than the `remainder`. - #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + #[cfg(feature = "locales")] recons: Vec>, - #[cfg(not(all(feature = "locales", any(feature = "alloc", feature = "std", test))))] + #[cfg(not(feature = "locales"))] recons: &'static [Item<'static>], /// Date format - #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + #[cfg(feature = "locales")] d_fmt: Vec>, - #[cfg(not(all(feature = "locales", any(feature = "alloc", feature = "std", test))))] + #[cfg(not(feature = "locales"))] d_fmt: &'static [Item<'static>], /// Date and time format - #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + #[cfg(feature = "locales")] d_t_fmt: Vec>, - #[cfg(not(all(feature = "locales", any(feature = "alloc", feature = "std", test))))] + #[cfg(not(feature = "locales"))] d_t_fmt: &'static [Item<'static>], /// Time format - #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + #[cfg(feature = "locales")] t_fmt: Vec>, - #[cfg(not(all(feature = "locales", any(feature = "alloc", feature = "std", test))))] + #[cfg(not(feature = "locales"))] t_fmt: &'static [Item<'static>], } @@ -214,10 +214,10 @@ impl<'a> StrftimeItems<'a> { ]; static T_FMT: &'static [Item<'static>] = &[num0!(Hour), lit!(":"), num0!(Minute), lit!(":"), num0!(Second)]; - #[cfg(not(all(feature = "locales", any(feature = "alloc", feature = "std", test))))] + #[cfg(not(feature = "locales"))] static FMT_NONE: &'static [Item<'static>; 0] = &[]; - #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + #[cfg(feature = "locales")] { StrftimeItems { remainder: s, @@ -228,7 +228,7 @@ impl<'a> StrftimeItems<'a> { } } - #[cfg(not(all(feature = "locales", any(feature = "alloc", feature = "std", test))))] + #[cfg(not(feature = "locales"))] { StrftimeItems { remainder: s, @@ -241,7 +241,7 @@ impl<'a> StrftimeItems<'a> { } /// Creates a new parsing iterator from the `strftime`-like format string. - #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + #[cfg(feature = "locales")] pub fn new_with_locale(s: &'a str, locale: Locale) -> StrftimeItems<'a> { let d_fmt = StrftimeItems::new(locales::d_fmt(locale)).collect(); let d_t_fmt = StrftimeItems::new(locales::d_t_fmt(locale)).collect(); @@ -266,11 +266,11 @@ impl<'a> Iterator for StrftimeItems<'a> { // we have some reconstructed items to return if !self.recons.is_empty() { let item = self.recons[0].clone(); - #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + #[cfg(feature = "locales")] { self.recons = self.recons[1..].to_vec(); } - #[cfg(not(all(feature = "locales", any(feature = "alloc", feature = "std", test))))] + #[cfg(not(feature = "locales"))] { self.recons = &self.recons[1..]; } @@ -312,11 +312,11 @@ impl<'a> Iterator for StrftimeItems<'a> { macro_rules! recons { [$head:expr, $($tail:expr),+] => ({ - #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + #[cfg(feature = "locales")] { self.recons = vec![$($tail),+]; } - #[cfg(not(all(feature = "locales", any(feature = "alloc", feature = "std", test))))] + #[cfg(not(feature = "locales"))] { const RECONS: &'static [Item<'static>] = &[$($tail),+]; self.recons = RECONS; @@ -642,7 +642,7 @@ fn test_strftime_docs() { assert_eq!(dt.format("%%").to_string(), "%"); } -#[cfg(all(feature = "locales", test))] +#[cfg(feature = "locales")] #[test] fn test_strftime_docs_localized() { use {FixedOffset, TimeZone, Timelike}; diff --git a/src/lib.rs b/src/lib.rs index 6e6ae8c4b1..a12a79fe36 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -217,9 +217,11 @@ //! `locales`: //! //! ```text -//! chrono { version = ..., features = ["locales"] +//! chrono { version = "0.4", features = ["locales"] //! ``` //! +//! The `locales` feature requires and implies at least the `alloc` feature. +//! //! ```rust //! use chrono::prelude::*; //! @@ -462,7 +464,7 @@ pub use date::{Date, MAX_DATE, MIN_DATE}; #[cfg(feature = "rustc-serialize")] pub use datetime::rustc_serialize::TsSeconds; pub use datetime::{DateTime, SecondsFormat, MAX_DATETIME, MIN_DATETIME}; -#[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] +#[cfg(feature = "locales")] pub use format::Locale; pub use format::{ParseError, ParseResult}; #[doc(no_inline)] @@ -481,7 +483,7 @@ pub mod prelude { #[cfg(feature = "clock")] #[doc(no_inline)] pub use Local; - #[cfg(all(feature = "locales", any(feature = "alloc", feature = "std", test)))] + #[cfg(feature = "locales")] #[doc(no_inline)] pub use Locale; #[doc(no_inline)] From 2d9c1dcd70620f9ecf99eaaea8d0709a9655ea94 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 24 Jul 2020 20:50:07 +0200 Subject: [PATCH 49/60] Remove allow dead_code --- src/format/mod.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/src/format/mod.rs b/src/format/mod.rs index 42fbc746db..ec15c0bc1d 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -48,7 +48,6 @@ pub use self::strftime::StrftimeItems; pub use pure_rust_locales::Locale; #[cfg(not(feature = "locales"))] -#[allow(dead_code)] #[derive(Debug)] struct Locale; From dc66629f179ae664f2bd5fc6700d5dc83ab78138 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 24 Jul 2020 21:10:23 +0200 Subject: [PATCH 50/60] CLEANUP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/strftime.rs | 30 ++++++------------------------ 1 file changed, 6 insertions(+), 24 deletions(-) diff --git a/src/format/strftime.rs b/src/format/strftime.rs index 2326ce4f62..b11d231b94 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -345,17 +345,11 @@ impl<'a> Iterator for StrftimeItems<'a> { 'V' => num0!(IsoWeek), 'W' => num0!(WeekFromMon), 'X' => { - #[cfg(all( - feature = "locales", - any(feature = "alloc", feature = "std", test) - ))] + #[cfg(feature = "locales")] { self.recons = self.t_fmt[1..].to_vec(); } - #[cfg(not(all( - feature = "locales", - any(feature = "alloc", feature = "std", test) - )))] + #[cfg(not(feature = "locales"))] { self.recons = &self.t_fmt[1..]; } @@ -366,17 +360,11 @@ impl<'a> Iterator for StrftimeItems<'a> { 'a' => fix!(ShortWeekdayName), 'b' | 'h' => fix!(ShortMonthName), 'c' => { - #[cfg(all( - feature = "locales", - any(feature = "alloc", feature = "std", test) - ))] + #[cfg(feature = "locales")] { self.recons = self.d_t_fmt[1..].to_vec(); } - #[cfg(not(all( - feature = "locales", - any(feature = "alloc", feature = "std", test) - )))] + #[cfg(not(feature = "locales"))] { self.recons = &self.d_t_fmt[1..]; } @@ -409,17 +397,11 @@ impl<'a> Iterator for StrftimeItems<'a> { } 'w' => num!(NumDaysFromSun), 'x' => { - #[cfg(all( - feature = "locales", - any(feature = "alloc", feature = "std", test) - ))] + #[cfg(feature = "locales")] { self.recons = self.d_fmt[1..].to_vec(); } - #[cfg(not(all( - feature = "locales", - any(feature = "alloc", feature = "std", test) - )))] + #[cfg(not(feature = "locales"))] { self.recons = &self.d_fmt[1..]; } From ab0c06a965f325533055660a260c01682f828653 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 24 Jul 2020 21:45:28 +0200 Subject: [PATCH 51/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/strftime.rs | 70 ++++++++++++++++++++++++++++++++++++------ 1 file changed, 60 insertions(+), 10 deletions(-) diff --git a/src/format/strftime.rs b/src/format/strftime.rs index b11d231b94..e7a33cf2b4 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -257,7 +257,7 @@ impl<'a> StrftimeItems<'a> { } } -const HAVE_ALTERNATES: &'static str = "z"; +const HAVE_ALTERNATES: &'static str = "zxXc"; impl<'a> Iterator for StrftimeItems<'a> { type Item = Item<'a>; @@ -311,7 +311,7 @@ impl<'a> Iterator for StrftimeItems<'a> { } macro_rules! recons { - [$head:expr, $($tail:expr),+] => ({ + [$head:expr, $($tail:expr),+ $(,)?] => ({ #[cfg(feature = "locales")] { self.recons = vec![$($tail),+]; @@ -345,30 +345,64 @@ impl<'a> Iterator for StrftimeItems<'a> { 'V' => num0!(IsoWeek), 'W' => num0!(WeekFromMon), 'X' => { + let head; #[cfg(feature = "locales")] { - self.recons = self.t_fmt[1..].to_vec(); + if is_alternate { + self.recons = self.t_fmt[1..].to_vec(); + head = self.t_fmt[0].clone(); + } else { + head = recons![ + num0!(Hour), + lit!(":"), + num0!(Minute), + lit!(":"), + num0!(Second) + ]; + } } #[cfg(not(feature = "locales"))] { self.recons = &self.t_fmt[1..]; + head = self.t_fmt[0].clone(); } - self.t_fmt[0].clone() + head } 'Y' => num0!(Year), 'Z' => fix!(TimezoneName), 'a' => fix!(ShortWeekdayName), 'b' | 'h' => fix!(ShortMonthName), 'c' => { + let head; #[cfg(feature = "locales")] { - self.recons = self.d_t_fmt[1..].to_vec(); + if is_alternate { + self.recons = self.d_t_fmt[1..].to_vec(); + head = self.d_t_fmt[0].clone(); + } else { + head = recons![ + fix!(ShortWeekdayName), + sp!(" "), + fix!(ShortMonthName), + sp!(" "), + nums!(Day), + sp!(" "), + num0!(Hour), + lit!(":"), + num0!(Minute), + lit!(":"), + num0!(Second), + sp!(" "), + num0!(Year), + ]; + } } #[cfg(not(feature = "locales"))] { self.recons = &self.d_t_fmt[1..]; + head = self.d_t_fmt[0].clone(); } - self.d_t_fmt[0].clone() + head } 'd' => num0!(Day), 'e' => nums!(Day), @@ -397,15 +431,28 @@ impl<'a> Iterator for StrftimeItems<'a> { } 'w' => num!(NumDaysFromSun), 'x' => { + let head; #[cfg(feature = "locales")] { - self.recons = self.d_fmt[1..].to_vec(); + if is_alternate { + self.recons = self.d_fmt[1..].to_vec(); + head = self.d_fmt[0].clone(); + } else { + head = recons![ + num0!(Month), + lit!("/"), + num0!(Day), + lit!("/"), + num0!(YearMod100) + ]; + } } #[cfg(not(feature = "locales"))] { self.recons = &self.d_fmt[1..]; + head = self.d_fmt[0].clone(); } - self.d_fmt[0].clone() + head } 'y' => num0!(YearMod100), 'z' => { @@ -638,7 +685,8 @@ fn test_strftime_docs_localized() { assert_eq!(dt.format_localized("%a", Locale::fr_BE).to_string(), "dim"); assert_eq!(dt.format_localized("%A", Locale::fr_BE).to_string(), "dimanche"); assert_eq!(dt.format_localized("%D", Locale::fr_BE).to_string(), "07/08/01"); - assert_eq!(dt.format_localized("%x", Locale::fr_BE).to_string(), "08/07/01"); + assert_eq!(dt.format_localized("%x", Locale::fr_BE).to_string(), "07/08/01"); + assert_eq!(dt.format_localized("%#x", Locale::fr_BE).to_string(), "08/07/01"); assert_eq!(dt.format_localized("%F", Locale::fr_BE).to_string(), "2001-07-08"); assert_eq!(dt.format_localized("%v", Locale::fr_BE).to_string(), " 8-jui-2001"); @@ -648,11 +696,13 @@ fn test_strftime_docs_localized() { assert_eq!(dt.format_localized("%R", Locale::fr_BE).to_string(), "00:34"); assert_eq!(dt.format_localized("%T", Locale::fr_BE).to_string(), "00:34:60"); assert_eq!(dt.format_localized("%X", Locale::fr_BE).to_string(), "00:34:60"); + assert_eq!(dt.format_localized("%#X", Locale::fr_BE).to_string(), "00:34:60"); assert_eq!(dt.format_localized("%r", Locale::fr_BE).to_string(), "12:34:60 "); // date & time specifiers + assert_eq!(dt.format("%c").to_string(), "Sun Jul 8 00:34:60 2001"); assert_eq!( - dt.format_localized("%c", Locale::fr_BE).to_string(), + dt.format_localized("%#c", Locale::fr_BE).to_string(), "dim 08 jui 2001 00:34:60 +09:30" ); } From c7a491b8bb3ab4803d677cf6343a3c64083f534b Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 24 Jul 2020 21:51:53 +0200 Subject: [PATCH 52/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/strftime.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/format/strftime.rs b/src/format/strftime.rs index e7a33cf2b4..65793099b4 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -311,7 +311,7 @@ impl<'a> Iterator for StrftimeItems<'a> { } macro_rules! recons { - [$head:expr, $($tail:expr),+ $(,)?] => ({ + [$head:expr, $($tail:expr),+ $(,)*] => ({ #[cfg(feature = "locales")] { self.recons = vec![$($tail),+]; From ea3d20e11e5c3e0420a04d9b88578aa6944bf08a Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Fri, 24 Jul 2020 23:12:36 +0200 Subject: [PATCH 53/60] Update doc --- src/format/strftime.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/format/strftime.rs b/src/format/strftime.rs index 65793099b4..b497da3006 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -38,7 +38,8 @@ The following specifiers are available both to formatting and parsing. | `%j` | `189` | Day of the year (001--366), zero-padded to 3 digits. | | | | | | `%D` | `07/08/01` | Month-day-year format. Same as `%m/%d/%y`. | -| `%x` | `07/08/01` | Locale's date representation (e.g., 12/31/99). | +| `%x` | `07/08/01` | Same as `%D`. | +| `%#x` | `07/08/01` | Locale's date representation (e.g., 12/31/99). | | `%F` | `2001-07-08` | Year-month-day format (ISO 8601). Same as `%Y-%m-%d`. | | `%v` | ` 8-Jul-2001` | Day-month-year format. Same as `%e-%b-%Y`. | | | | | @@ -64,7 +65,8 @@ The following specifiers are available both to formatting and parsing. | | | | | `%R` | `00:34` | Hour-minute format. Same as `%H:%M`. | | `%T` | `00:34:60` | Hour-minute-second format. Same as `%H:%M:%S`. | -| `%X` | `00:34:60` | Locale's time representation (e.g., 23:13:48). | +| `%X` | `00:34:60` | Same as `%T`. | +| `%#X` | `00:34:60` | Locale's time representation (e.g., 23:13:48). | | `%r` | `12:34:60 AM` | Hour-minute-second format in 12-hour clocks. Same as `%I:%M:%S %p`. | | | | | | | | **TIME ZONE SPECIFIERS:** | @@ -74,7 +76,8 @@ The following specifiers are available both to formatting and parsing. | `%#z` | `+09` | *Parsing only:* Same as `%z` but allows minutes to be missing or present. | | | | | | | | **DATE & TIME SPECIFIERS:** | -|`%c`|`Sun Jul 8 00:34:60 2001`|Locale's date and time (e.g., Thu Mar 3 23:05:25 2005). | +|`%c`|`Sun Jul 8 00:34:60 2001`|`ctime` date & time format. Same as `%a %b %e %T %Y` sans `\n`.| +|`%#c`|`Sun Jul 8 00:34:60 2001`|Locale's date and time (e.g., Thu Mar 3 23:05:25 2005). | | `%+` | `2001-07-08T00:34:60.026490+09:30` | ISO 8601 / RFC 3339 date & time format. [^6] | | | | | | `%s` | `994518299` | UNIX timestamp, the number of seconds since 1970-01-01 00:00 UTC. [^7]| From f6ecdcb8665dcc491688936b5784b092206ecb17 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 26 Jul 2020 15:36:05 +0200 Subject: [PATCH 54/60] Revert "Update doc" This reverts commit ea3d20e11e5c3e0420a04d9b88578aa6944bf08a. --- src/format/strftime.rs | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/src/format/strftime.rs b/src/format/strftime.rs index b497da3006..65793099b4 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -38,8 +38,7 @@ The following specifiers are available both to formatting and parsing. | `%j` | `189` | Day of the year (001--366), zero-padded to 3 digits. | | | | | | `%D` | `07/08/01` | Month-day-year format. Same as `%m/%d/%y`. | -| `%x` | `07/08/01` | Same as `%D`. | -| `%#x` | `07/08/01` | Locale's date representation (e.g., 12/31/99). | +| `%x` | `07/08/01` | Locale's date representation (e.g., 12/31/99). | | `%F` | `2001-07-08` | Year-month-day format (ISO 8601). Same as `%Y-%m-%d`. | | `%v` | ` 8-Jul-2001` | Day-month-year format. Same as `%e-%b-%Y`. | | | | | @@ -65,8 +64,7 @@ The following specifiers are available both to formatting and parsing. | | | | | `%R` | `00:34` | Hour-minute format. Same as `%H:%M`. | | `%T` | `00:34:60` | Hour-minute-second format. Same as `%H:%M:%S`. | -| `%X` | `00:34:60` | Same as `%T`. | -| `%#X` | `00:34:60` | Locale's time representation (e.g., 23:13:48). | +| `%X` | `00:34:60` | Locale's time representation (e.g., 23:13:48). | | `%r` | `12:34:60 AM` | Hour-minute-second format in 12-hour clocks. Same as `%I:%M:%S %p`. | | | | | | | | **TIME ZONE SPECIFIERS:** | @@ -76,8 +74,7 @@ The following specifiers are available both to formatting and parsing. | `%#z` | `+09` | *Parsing only:* Same as `%z` but allows minutes to be missing or present. | | | | | | | | **DATE & TIME SPECIFIERS:** | -|`%c`|`Sun Jul 8 00:34:60 2001`|`ctime` date & time format. Same as `%a %b %e %T %Y` sans `\n`.| -|`%#c`|`Sun Jul 8 00:34:60 2001`|Locale's date and time (e.g., Thu Mar 3 23:05:25 2005). | +|`%c`|`Sun Jul 8 00:34:60 2001`|Locale's date and time (e.g., Thu Mar 3 23:05:25 2005). | | `%+` | `2001-07-08T00:34:60.026490+09:30` | ISO 8601 / RFC 3339 date & time format. [^6] | | | | | | `%s` | `994518299` | UNIX timestamp, the number of seconds since 1970-01-01 00:00 UTC. [^7]| From 2cdb6d3704b59538379d078e2aa5fd2f1c09f58f Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 26 Jul 2020 15:36:42 +0200 Subject: [PATCH 55/60] Revert "WIP" This reverts commit ab0c06a965f325533055660a260c01682f828653. --- src/format/strftime.rs | 68 ++++++------------------------------------ 1 file changed, 9 insertions(+), 59 deletions(-) diff --git a/src/format/strftime.rs b/src/format/strftime.rs index 65793099b4..4a6ad7fe3a 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -257,7 +257,7 @@ impl<'a> StrftimeItems<'a> { } } -const HAVE_ALTERNATES: &'static str = "zxXc"; +const HAVE_ALTERNATES: &'static str = "z"; impl<'a> Iterator for StrftimeItems<'a> { type Item = Item<'a>; @@ -345,64 +345,30 @@ impl<'a> Iterator for StrftimeItems<'a> { 'V' => num0!(IsoWeek), 'W' => num0!(WeekFromMon), 'X' => { - let head; #[cfg(feature = "locales")] { - if is_alternate { - self.recons = self.t_fmt[1..].to_vec(); - head = self.t_fmt[0].clone(); - } else { - head = recons![ - num0!(Hour), - lit!(":"), - num0!(Minute), - lit!(":"), - num0!(Second) - ]; - } + self.recons = self.t_fmt[1..].to_vec(); } #[cfg(not(feature = "locales"))] { self.recons = &self.t_fmt[1..]; - head = self.t_fmt[0].clone(); } - head + self.t_fmt[0].clone() } 'Y' => num0!(Year), 'Z' => fix!(TimezoneName), 'a' => fix!(ShortWeekdayName), 'b' | 'h' => fix!(ShortMonthName), 'c' => { - let head; #[cfg(feature = "locales")] { - if is_alternate { - self.recons = self.d_t_fmt[1..].to_vec(); - head = self.d_t_fmt[0].clone(); - } else { - head = recons![ - fix!(ShortWeekdayName), - sp!(" "), - fix!(ShortMonthName), - sp!(" "), - nums!(Day), - sp!(" "), - num0!(Hour), - lit!(":"), - num0!(Minute), - lit!(":"), - num0!(Second), - sp!(" "), - num0!(Year), - ]; - } + self.recons = self.d_t_fmt[1..].to_vec(); } #[cfg(not(feature = "locales"))] { self.recons = &self.d_t_fmt[1..]; - head = self.d_t_fmt[0].clone(); } - head + self.d_t_fmt[0].clone() } 'd' => num0!(Day), 'e' => nums!(Day), @@ -431,28 +397,15 @@ impl<'a> Iterator for StrftimeItems<'a> { } 'w' => num!(NumDaysFromSun), 'x' => { - let head; #[cfg(feature = "locales")] { - if is_alternate { - self.recons = self.d_fmt[1..].to_vec(); - head = self.d_fmt[0].clone(); - } else { - head = recons![ - num0!(Month), - lit!("/"), - num0!(Day), - lit!("/"), - num0!(YearMod100) - ]; - } + self.recons = self.d_fmt[1..].to_vec(); } #[cfg(not(feature = "locales"))] { self.recons = &self.d_fmt[1..]; - head = self.d_fmt[0].clone(); } - head + self.d_fmt[0].clone() } 'y' => num0!(YearMod100), 'z' => { @@ -685,8 +638,7 @@ fn test_strftime_docs_localized() { assert_eq!(dt.format_localized("%a", Locale::fr_BE).to_string(), "dim"); assert_eq!(dt.format_localized("%A", Locale::fr_BE).to_string(), "dimanche"); assert_eq!(dt.format_localized("%D", Locale::fr_BE).to_string(), "07/08/01"); - assert_eq!(dt.format_localized("%x", Locale::fr_BE).to_string(), "07/08/01"); - assert_eq!(dt.format_localized("%#x", Locale::fr_BE).to_string(), "08/07/01"); + assert_eq!(dt.format_localized("%x", Locale::fr_BE).to_string(), "08/07/01"); assert_eq!(dt.format_localized("%F", Locale::fr_BE).to_string(), "2001-07-08"); assert_eq!(dt.format_localized("%v", Locale::fr_BE).to_string(), " 8-jui-2001"); @@ -696,13 +648,11 @@ fn test_strftime_docs_localized() { assert_eq!(dt.format_localized("%R", Locale::fr_BE).to_string(), "00:34"); assert_eq!(dt.format_localized("%T", Locale::fr_BE).to_string(), "00:34:60"); assert_eq!(dt.format_localized("%X", Locale::fr_BE).to_string(), "00:34:60"); - assert_eq!(dt.format_localized("%#X", Locale::fr_BE).to_string(), "00:34:60"); assert_eq!(dt.format_localized("%r", Locale::fr_BE).to_string(), "12:34:60 "); // date & time specifiers - assert_eq!(dt.format("%c").to_string(), "Sun Jul 8 00:34:60 2001"); assert_eq!( - dt.format_localized("%#c", Locale::fr_BE).to_string(), + dt.format_localized("%c", Locale::fr_BE).to_string(), "dim 08 jui 2001 00:34:60 +09:30" ); } From 05358aea8ada8b044f8bd0cf5a27dbdc1b9986cc Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 26 Jul 2020 15:58:00 +0200 Subject: [PATCH 56/60] CLEANUP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/strftime.rs | 84 ++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 52 deletions(-) diff --git a/src/format/strftime.rs b/src/format/strftime.rs index 4a6ad7fe3a..b5a53433a8 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -163,6 +163,11 @@ Notes: use super::{locales, Locale}; use super::{Fixed, InternalFixed, InternalInternal, Item, Numeric, Pad}; +#[cfg(feature = "locales")] +type Fmt<'a> = Vec>; +#[cfg(not(feature = "locales"))] +type Fmt<'a> = &'static [Item<'static>]; + /// Parsing iterator for `strftime`-like format strings. #[derive(Clone, Debug)] pub struct StrftimeItems<'a> { @@ -171,25 +176,13 @@ pub struct StrftimeItems<'a> { /// If the current specifier is composed of multiple formatting items (e.g. `%+`), /// parser refers to the statically reconstructed slice of them. /// If `recons` is not empty they have to be returned earlier than the `remainder`. - #[cfg(feature = "locales")] - recons: Vec>, - #[cfg(not(feature = "locales"))] - recons: &'static [Item<'static>], + recons: Fmt<'a>, /// Date format - #[cfg(feature = "locales")] - d_fmt: Vec>, - #[cfg(not(feature = "locales"))] - d_fmt: &'static [Item<'static>], + d_fmt: Fmt<'a>, /// Date and time format - #[cfg(feature = "locales")] - d_t_fmt: Vec>, - #[cfg(not(feature = "locales"))] - d_t_fmt: &'static [Item<'static>], + d_t_fmt: Fmt<'a>, /// Time format - #[cfg(feature = "locales")] - t_fmt: Vec>, - #[cfg(not(feature = "locales"))] - t_fmt: &'static [Item<'static>], + t_fmt: Fmt<'a>, } impl<'a> StrftimeItems<'a> { @@ -265,13 +258,14 @@ impl<'a> Iterator for StrftimeItems<'a> { fn next(&mut self) -> Option> { // we have some reconstructed items to return if !self.recons.is_empty() { - let item = self.recons[0].clone(); + let item; #[cfg(feature = "locales")] { - self.recons = self.recons[1..].to_vec(); + item = self.recons.remove(0); } #[cfg(not(feature = "locales"))] { + item = self.recons[0].clone(); self.recons = &self.recons[1..]; } return Some(item); @@ -314,7 +308,8 @@ impl<'a> Iterator for StrftimeItems<'a> { [$head:expr, $($tail:expr),+ $(,)*] => ({ #[cfg(feature = "locales")] { - self.recons = vec![$($tail),+]; + self.recons.clear(); + $(self.recons.push($tail);)+ } #[cfg(not(feature = "locales"))] { @@ -325,6 +320,21 @@ impl<'a> Iterator for StrftimeItems<'a> { }) } + macro_rules! recons_from_slice { + ($slice:expr) => {{ + #[cfg(feature = "locales")] + { + self.recons.clear(); + self.recons.extend_from_slice(&$slice[1..]); + } + #[cfg(not(feature = "locales"))] + { + self.recons = &$slice[1..]; + } + $slice[0].clone() + }}; + } + let item = match spec { 'A' => fix!(LongWeekdayName), 'B' => fix!(LongMonthName), @@ -344,32 +354,12 @@ impl<'a> Iterator for StrftimeItems<'a> { 'U' => num0!(WeekFromSun), 'V' => num0!(IsoWeek), 'W' => num0!(WeekFromMon), - 'X' => { - #[cfg(feature = "locales")] - { - self.recons = self.t_fmt[1..].to_vec(); - } - #[cfg(not(feature = "locales"))] - { - self.recons = &self.t_fmt[1..]; - } - self.t_fmt[0].clone() - } + 'X' => recons_from_slice!(self.t_fmt), 'Y' => num0!(Year), 'Z' => fix!(TimezoneName), 'a' => fix!(ShortWeekdayName), 'b' | 'h' => fix!(ShortMonthName), - 'c' => { - #[cfg(feature = "locales")] - { - self.recons = self.d_t_fmt[1..].to_vec(); - } - #[cfg(not(feature = "locales"))] - { - self.recons = &self.d_t_fmt[1..]; - } - self.d_t_fmt[0].clone() - } + 'c' => recons_from_slice!(self.d_t_fmt), 'd' => num0!(Day), 'e' => nums!(Day), 'f' => num0!(Nanosecond), @@ -396,17 +386,7 @@ impl<'a> Iterator for StrftimeItems<'a> { recons![nums!(Day), lit!("-"), fix!(ShortMonthName), lit!("-"), num0!(Year)] } 'w' => num!(NumDaysFromSun), - 'x' => { - #[cfg(feature = "locales")] - { - self.recons = self.d_fmt[1..].to_vec(); - } - #[cfg(not(feature = "locales"))] - { - self.recons = &self.d_fmt[1..]; - } - self.d_fmt[0].clone() - } + 'x' => recons_from_slice!(self.d_fmt), 'y' => num0!(YearMod100), 'z' => { if is_alternate { From d1ae67b88431314e290a2634930c087997b0e17f Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 26 Jul 2020 16:07:20 +0200 Subject: [PATCH 57/60] WIP Forked at: aaee91222802471c656480ddb49b6f1e53a69a96 Parent branch: chronotope/main --- src/format/strftime.rs | 88 +++++++++++++++++++++--------------------- 1 file changed, 45 insertions(+), 43 deletions(-) diff --git a/src/format/strftime.rs b/src/format/strftime.rs index b5a53433a8..6aa91192bc 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -168,6 +168,26 @@ type Fmt<'a> = Vec>; #[cfg(not(feature = "locales"))] type Fmt<'a> = &'static [Item<'static>]; +static D_FMT: &'static [Item<'static>] = + &[num0!(Month), lit!("/"), num0!(Day), lit!("/"), num0!(YearMod100)]; +static D_T_FMT: &'static [Item<'static>] = &[ + fix!(ShortWeekdayName), + sp!(" "), + fix!(ShortMonthName), + sp!(" "), + nums!(Day), + sp!(" "), + num0!(Hour), + lit!(":"), + num0!(Minute), + lit!(":"), + num0!(Second), + sp!(" "), + num0!(Year), +]; +static T_FMT: &'static [Item<'static>] = + &[num0!(Hour), lit!(":"), num0!(Minute), lit!(":"), num0!(Second)]; + /// Parsing iterator for `strftime`-like format strings. #[derive(Clone, Debug)] pub struct StrftimeItems<'a> { @@ -188,49 +208,7 @@ pub struct StrftimeItems<'a> { impl<'a> StrftimeItems<'a> { /// Creates a new parsing iterator from the `strftime`-like format string. pub fn new(s: &'a str) -> StrftimeItems<'a> { - static D_FMT: &'static [Item<'static>] = - &[num0!(Month), lit!("/"), num0!(Day), lit!("/"), num0!(YearMod100)]; - static D_T_FMT: &'static [Item<'static>] = &[ - fix!(ShortWeekdayName), - sp!(" "), - fix!(ShortMonthName), - sp!(" "), - nums!(Day), - sp!(" "), - num0!(Hour), - lit!(":"), - num0!(Minute), - lit!(":"), - num0!(Second), - sp!(" "), - num0!(Year), - ]; - static T_FMT: &'static [Item<'static>] = - &[num0!(Hour), lit!(":"), num0!(Minute), lit!(":"), num0!(Second)]; - #[cfg(not(feature = "locales"))] - static FMT_NONE: &'static [Item<'static>; 0] = &[]; - - #[cfg(feature = "locales")] - { - StrftimeItems { - remainder: s, - recons: Vec::new(), - d_fmt: D_FMT.to_vec(), - d_t_fmt: D_T_FMT.to_vec(), - t_fmt: T_FMT.to_vec(), - } - } - - #[cfg(not(feature = "locales"))] - { - StrftimeItems { - remainder: s, - recons: FMT_NONE, - d_fmt: D_FMT, - d_t_fmt: D_T_FMT, - t_fmt: T_FMT, - } - } + Self::with_remainer(s) } /// Creates a new parsing iterator from the `strftime`-like format string. @@ -248,6 +226,30 @@ impl<'a> StrftimeItems<'a> { t_fmt: t_fmt, } } + + #[cfg(not(feature = "locales"))] + fn with_remainer(s: &'a str) -> StrftimeItems<'a> { + static FMT_NONE: &'static [Item<'static>; 0] = &[]; + + StrftimeItems { + remainder: s, + recons: FMT_NONE, + d_fmt: D_FMT, + d_t_fmt: D_T_FMT, + t_fmt: T_FMT, + } + } + + #[cfg(feature = "locales")] + fn with_remainer(s: &'a str) -> StrftimeItems<'a> { + StrftimeItems { + remainder: s, + recons: Vec::new(), + d_fmt: D_FMT.to_vec(), + d_t_fmt: D_T_FMT.to_vec(), + t_fmt: T_FMT.to_vec(), + } + } } const HAVE_ALTERNATES: &'static str = "z"; From 90b3e8e144621afd990812bfd1ba550790dfced3 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 26 Jul 2020 16:20:32 +0200 Subject: [PATCH 58/60] doc --- README.md | 1 + src/lib.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/README.md b/README.md index 407ed5ee26..e642435af2 100644 --- a/README.md +++ b/README.md @@ -62,6 +62,7 @@ Optional features: - `wasmbind`: Enable integration with [wasm-bindgen][] and its `js-sys` project - [`serde`][]: Enable +- `locales`: Enable localization. [`serde`]: https://github.com/serde-rs/serde [wasm-bindgen]: https://github.com/rustwasm/wasm-bindgen diff --git a/src/lib.rs b/src/lib.rs index 2ae72399a7..e2a57fd8ad 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -49,6 +49,7 @@ //! //! - `wasmbind`: Enable integration with [wasm-bindgen][] and its `js-sys` project //! - [`serde`][]: Enable +//! - `locales`: Enable localization. //! //! [`serde`]: https://github.com/serde-rs/serde //! [wasm-bindgen]: https://github.com/rustwasm/wasm-bindgen From b6c53951cd53814ca2b35e0fb7eab8dadf4e9c44 Mon Sep 17 00:00:00 2001 From: Cecile Tonglet Date: Sun, 26 Jul 2020 16:31:19 +0200 Subject: [PATCH 59/60] Doc comments --- src/format/mod.rs | 1 + src/lib.rs | 1 + 2 files changed, 2 insertions(+) diff --git a/src/format/mod.rs b/src/format/mod.rs index ec15c0bc1d..1c28ec53e6 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -44,6 +44,7 @@ pub(crate) mod locales; pub use self::parse::parse; pub use self::parsed::Parsed; pub use self::strftime::StrftimeItems; +/// L10n locales. #[cfg(feature = "locales")] pub use pure_rust_locales::Locale; diff --git a/src/lib.rs b/src/lib.rs index e2a57fd8ad..856c12e70e 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -470,6 +470,7 @@ pub use date::{Date, MAX_DATE, MIN_DATE}; #[cfg(feature = "rustc-serialize")] pub use datetime::rustc_serialize::TsSeconds; pub use datetime::{DateTime, SecondsFormat, MAX_DATETIME, MIN_DATETIME}; +/// L10n locales. #[cfg(feature = "locales")] pub use format::Locale; pub use format::{ParseError, ParseResult}; From bc96105e4b2d700af451bfca54129e0640a549e8 Mon Sep 17 00:00:00 2001 From: Brandon W Maister Date: Fri, 31 Jul 2020 09:46:42 -0400 Subject: [PATCH 60/60] Rename locales feature to "unstable-locales" to make it easier to change --- Cargo.toml | 2 +- README.md | 12 +++++++----- ci/github.sh | 4 ++-- src/date.rs | 6 +++--- src/datetime.rs | 6 +++--- src/format/mod.rs | 38 +++++++++++++++++++------------------- src/format/strftime.rs | 28 ++++++++++++++-------------- src/lib.rs | 18 ++++++++++-------- 8 files changed, 59 insertions(+), 55 deletions(-) diff --git a/Cargo.toml b/Cargo.toml index 68237a0d8f..dd9dbeea97 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -29,7 +29,7 @@ alloc = [] std = [] clock = ["time", "std"] wasmbind = ["wasm-bindgen", "js-sys"] -locales = ["pure-rust-locales", "alloc"] +unstable-locales = ["pure-rust-locales", "alloc"] __internal_bench = [] __doctest = [] diff --git a/README.md b/README.md index e642435af2..2e363f98bb 100644 --- a/README.md +++ b/README.md @@ -61,8 +61,10 @@ Default features: Optional features: - `wasmbind`: Enable integration with [wasm-bindgen][] and its `js-sys` project -- [`serde`][]: Enable -- `locales`: Enable localization. +- [`serde`][]: Enable serialization/deserialization via serde. +- `unstable-locales`: Enable localization. This adds various methods with a + `_localized` suffix. The implementation and API may change or even be + removed in a patch release. Feedback welcome. [`serde`]: https://github.com/serde-rs/serde [wasm-bindgen]: https://github.com/rustwasm/wasm-bindgen @@ -228,13 +230,13 @@ for well-known formats. Chrono now also provides date formatting in almost any language without the help of an additional C library. This functionality is under the feature -`locales`: +`unstable-locales`: ```text -chrono { version = "0.4", features = ["locales"] +chrono { version = "0.4", features = ["unstable-locales"] ``` -The `locales` feature requires and implies at least the `alloc` feature. +The `unstable-locales` feature requires and implies at least the `alloc` feature. ```rust use chrono::prelude::*; diff --git a/ci/github.sh b/ci/github.sh index 486fb4457a..229bd6ee54 100755 --- a/ci/github.sh +++ b/ci/github.sh @@ -6,7 +6,7 @@ set -euo pipefail source "${BASH_SOURCE[0]%/*}/_shlib.sh" TEST_TZS=(ACST-9:30 EST4 UTC0 Asia/Katmandu) -FEATURES=(std serde clock "alloc serde" locales) +FEATURES=(std serde clock "alloc serde" unstable-locales) RUST_113_FEATURES=(rustc-serialize serde) main() { @@ -56,7 +56,7 @@ test_all_tzs() { test_regular() { tz="$1" && shift - runt env TZ="$tz" cargo test --features __doctest,locales --color=always -- --color=always + runt env TZ="$tz" cargo test --features __doctest,unstable-locales --color=always -- --color=always for feature in "${FEATURES[@]}"; do runt env TZ="$tz" cargo test --no-default-features --features "$feature" --lib --color=always -- --color=always done diff --git a/src/date.rs b/src/date.rs index 60a81de725..0012d36049 100644 --- a/src/date.rs +++ b/src/date.rs @@ -10,7 +10,7 @@ use core::ops::{Add, Sub}; use core::{fmt, hash}; use oldtime::Duration as OldDuration; -#[cfg(feature = "locales")] +#[cfg(feature = "unstable-locales")] use format::Locale; #[cfg(any(feature = "alloc", feature = "std", test))] use format::{DelayedFormat, Item, StrftimeItems}; @@ -299,7 +299,7 @@ where } /// Formats the date with the specified formatting items and locale. - #[cfg(feature = "locales")] + #[cfg(feature = "unstable-locales")] #[inline] pub fn format_localized_with_items<'a, I, B>( &self, @@ -322,7 +322,7 @@ where /// Formats the date with the specified format string and locale. /// See the [`format::strftime` module](./format/strftime/index.html) /// on the supported escape sequences. - #[cfg(feature = "locales")] + #[cfg(feature = "unstable-locales")] #[inline] pub fn format_localized<'a>( &self, diff --git a/src/datetime.rs b/src/datetime.rs index dbca333564..f4a0cd13e6 100644 --- a/src/datetime.rs +++ b/src/datetime.rs @@ -19,7 +19,7 @@ use std::string::ToString; use core::borrow::Borrow; #[cfg(any(feature = "alloc", feature = "std", test))] use format::DelayedFormat; -#[cfg(feature = "locales")] +#[cfg(feature = "unstable-locales")] use format::Locale; use format::{parse, ParseError, ParseResult, Parsed, StrftimeItems}; use format::{Fixed, Item}; @@ -497,7 +497,7 @@ where } /// Formats the combined date and time with the specified formatting items and locale. - #[cfg(feature = "locales")] + #[cfg(feature = "unstable-locales")] #[inline] pub fn format_localized_with_items<'a, I, B>( &self, @@ -521,7 +521,7 @@ where /// Formats the combined date and time with the specified format string and locale. /// See the [`format::strftime` module](./format/strftime/index.html) /// on the supported escape sequences. - #[cfg(feature = "locales")] + #[cfg(feature = "unstable-locales")] #[inline] pub fn format_localized<'a>( &self, diff --git a/src/format/mod.rs b/src/format/mod.rs index e8ac705c00..3fbc2dae34 100644 --- a/src/format/mod.rs +++ b/src/format/mod.rs @@ -36,17 +36,17 @@ use offset::{FixedOffset, Offset}; use {Datelike, Timelike}; use {Month, ParseMonthError, ParseWeekdayError, Weekday}; -#[cfg(feature = "locales")] +#[cfg(feature = "unstable-locales")] pub(crate) mod locales; pub use self::parse::parse; pub use self::parsed::Parsed; pub use self::strftime::StrftimeItems; /// L10n locales. -#[cfg(feature = "locales")] +#[cfg(feature = "unstable-locales")] pub use pure_rust_locales::Locale; -#[cfg(not(feature = "locales"))] +#[cfg(not(feature = "unstable-locales"))] #[derive(Debug)] struct Locale; @@ -409,24 +409,24 @@ fn format_inner<'a>( item: &Item<'a>, _locale: Option, ) -> fmt::Result { - #[cfg(feature = "locales")] + #[cfg(feature = "unstable-locales")] let locale = _locale.unwrap_or(Locale::POSIX); - #[cfg(feature = "locales")] + #[cfg(feature = "unstable-locales")] let short_months = locales::short_months(locale); - #[cfg(feature = "locales")] + #[cfg(feature = "unstable-locales")] let long_months = locales::long_months(locale); - #[cfg(feature = "locales")] + #[cfg(feature = "unstable-locales")] let short_weekdays = locales::short_weekdays(locale); - #[cfg(feature = "locales")] + #[cfg(feature = "unstable-locales")] let long_weekdays = locales::long_weekdays(locale); - #[cfg(feature = "locales")] + #[cfg(feature = "unstable-locales")] let am_pm = locales::am_pm(locale); - #[cfg(not(feature = "locales"))] + #[cfg(not(feature = "unstable-locales"))] let short_months = &["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"]; - #[cfg(not(feature = "locales"))] + #[cfg(not(feature = "unstable-locales"))] let long_months = &[ "January", "February", @@ -441,12 +441,12 @@ fn format_inner<'a>( "November", "December", ]; - #[cfg(not(feature = "locales"))] + #[cfg(not(feature = "unstable-locales"))] let short_weekdays = &["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; - #[cfg(not(feature = "locales"))] + #[cfg(not(feature = "unstable-locales"))] let long_weekdays = &["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"]; - #[cfg(not(feature = "locales"))] + #[cfg(not(feature = "unstable-locales"))] let am_pm = &["AM", "PM"]; let am_pm_lowercase: Vec<_> = am_pm.iter().map(|x| x.to_lowercase()).collect(); @@ -759,7 +759,7 @@ impl<'a, I: Iterator + Clone, B: Borrow>> DelayedFormat { } /// Makes a new `DelayedFormat` value out of local date and time and locale. - #[cfg(feature = "locales")] + #[cfg(feature = "unstable-locales")] pub fn new_with_locale( date: Option, time: Option, @@ -770,7 +770,7 @@ impl<'a, I: Iterator + Clone, B: Borrow>> DelayedFormat { } /// Makes a new `DelayedFormat` value out of local date and time, UTC offset and locale. - #[cfg(feature = "locales")] + #[cfg(feature = "unstable-locales")] pub fn new_with_offset_and_locale( date: Option, time: Option, @@ -795,7 +795,7 @@ impl<'a, I: Iterator + Clone, B: Borrow>> DelayedFormat { #[cfg(any(feature = "alloc", feature = "std", test))] impl<'a, I: Iterator + Clone, B: Borrow>> fmt::Display for DelayedFormat { fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { - #[cfg(feature = "locales")] + #[cfg(feature = "unstable-locales")] { if let Some(locale) = self.locale { return format_localized( @@ -852,7 +852,7 @@ impl FromStr for Weekday { } /// Formats single formatting item -#[cfg(feature = "locales")] +#[cfg(feature = "unstable-locales")] pub fn format_item_localized<'a>( w: &mut fmt::Formatter, date: Option<&NaiveDate>, @@ -868,7 +868,7 @@ pub fn format_item_localized<'a>( /// Tries to format given arguments with given formatting items. /// Internally used by `DelayedFormat`. -#[cfg(feature = "locales")] +#[cfg(feature = "unstable-locales")] pub fn format_localized<'a, I, B>( w: &mut fmt::Formatter, date: Option<&NaiveDate>, diff --git a/src/format/strftime.rs b/src/format/strftime.rs index 6aa91192bc..0ca2ca9204 100644 --- a/src/format/strftime.rs +++ b/src/format/strftime.rs @@ -159,13 +159,13 @@ Notes: */ -#[cfg(feature = "locales")] +#[cfg(feature = "unstable-locales")] use super::{locales, Locale}; use super::{Fixed, InternalFixed, InternalInternal, Item, Numeric, Pad}; -#[cfg(feature = "locales")] +#[cfg(feature = "unstable-locales")] type Fmt<'a> = Vec>; -#[cfg(not(feature = "locales"))] +#[cfg(not(feature = "unstable-locales"))] type Fmt<'a> = &'static [Item<'static>]; static D_FMT: &'static [Item<'static>] = @@ -212,7 +212,7 @@ impl<'a> StrftimeItems<'a> { } /// Creates a new parsing iterator from the `strftime`-like format string. - #[cfg(feature = "locales")] + #[cfg(feature = "unstable-locales")] pub fn new_with_locale(s: &'a str, locale: Locale) -> StrftimeItems<'a> { let d_fmt = StrftimeItems::new(locales::d_fmt(locale)).collect(); let d_t_fmt = StrftimeItems::new(locales::d_t_fmt(locale)).collect(); @@ -227,7 +227,7 @@ impl<'a> StrftimeItems<'a> { } } - #[cfg(not(feature = "locales"))] + #[cfg(not(feature = "unstable-locales"))] fn with_remainer(s: &'a str) -> StrftimeItems<'a> { static FMT_NONE: &'static [Item<'static>; 0] = &[]; @@ -240,7 +240,7 @@ impl<'a> StrftimeItems<'a> { } } - #[cfg(feature = "locales")] + #[cfg(feature = "unstable-locales")] fn with_remainer(s: &'a str) -> StrftimeItems<'a> { StrftimeItems { remainder: s, @@ -261,11 +261,11 @@ impl<'a> Iterator for StrftimeItems<'a> { // we have some reconstructed items to return if !self.recons.is_empty() { let item; - #[cfg(feature = "locales")] + #[cfg(feature = "unstable-locales")] { item = self.recons.remove(0); } - #[cfg(not(feature = "locales"))] + #[cfg(not(feature = "unstable-locales"))] { item = self.recons[0].clone(); self.recons = &self.recons[1..]; @@ -308,12 +308,12 @@ impl<'a> Iterator for StrftimeItems<'a> { macro_rules! recons { [$head:expr, $($tail:expr),+ $(,)*] => ({ - #[cfg(feature = "locales")] + #[cfg(feature = "unstable-locales")] { self.recons.clear(); $(self.recons.push($tail);)+ } - #[cfg(not(feature = "locales"))] + #[cfg(not(feature = "unstable-locales"))] { const RECONS: &'static [Item<'static>] = &[$($tail),+]; self.recons = RECONS; @@ -324,12 +324,12 @@ impl<'a> Iterator for StrftimeItems<'a> { macro_rules! recons_from_slice { ($slice:expr) => {{ - #[cfg(feature = "locales")] + #[cfg(feature = "unstable-locales")] { self.recons.clear(); self.recons.extend_from_slice(&$slice[1..]); } - #[cfg(not(feature = "locales"))] + #[cfg(not(feature = "unstable-locales"))] { self.recons = &$slice[1..]; } @@ -606,10 +606,10 @@ fn test_strftime_docs() { assert_eq!(dt.format("%%").to_string(), "%"); } -#[cfg(feature = "locales")] +#[cfg(feature = "unstable-locales")] #[test] fn test_strftime_docs_localized() { - use {FixedOffset, TimeZone, Timelike}; + use {FixedOffset, TimeZone}; let dt = FixedOffset::east(34200).ymd(2001, 7, 8).and_hms_nano(0, 34, 59, 1_026_490_708); diff --git a/src/lib.rs b/src/lib.rs index dd408d856c..89ffd87acd 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -48,8 +48,10 @@ //! Optional features: //! //! - `wasmbind`: Enable integration with [wasm-bindgen][] and its `js-sys` project -//! - [`serde`][]: Enable -//! - `locales`: Enable localization. +//! - [`serde`][]: Enable serialization/deserialization via serde. +//! - `unstable-locales`: Enable localization. This adds various methods with a +//! `_localized` suffix. The implementation and API may change or even be +//! removed in a patch release. Feedback welcome. //! //! [`serde`]: https://github.com/serde-rs/serde //! [wasm-bindgen]: https://github.com/rustwasm/wasm-bindgen @@ -220,13 +222,13 @@ //! //! Chrono now also provides date formatting in almost any language without the //! help of an additional C library. This functionality is under the feature -//! `locales`: +//! `unstable-locales`: //! //! ```text -//! chrono { version = "0.4", features = ["locales"] +//! chrono { version = "0.4", features = ["unstable-locales"] //! ``` //! -//! The `locales` feature requires and implies at least the `alloc` feature. +//! The `unstable-locales` feature requires and implies at least the `alloc` feature. //! //! ```rust //! use chrono::prelude::*; @@ -452,7 +454,7 @@ extern crate serde as serdelib; extern crate doc_comment; #[cfg(all(target_arch = "wasm32", not(target_os = "wasi"), feature = "wasmbind"))] extern crate js_sys; -#[cfg(feature = "locales")] +#[cfg(feature = "unstable-locales")] extern crate pure_rust_locales; #[cfg(feature = "bench")] extern crate test; @@ -471,7 +473,7 @@ pub use date::{Date, MAX_DATE, MIN_DATE}; pub use datetime::rustc_serialize::TsSeconds; pub use datetime::{DateTime, SecondsFormat, MAX_DATETIME, MIN_DATETIME}; /// L10n locales. -#[cfg(feature = "locales")] +#[cfg(feature = "unstable-locales")] pub use format::Locale; pub use format::{ParseError, ParseResult}; #[doc(no_inline)] @@ -490,7 +492,7 @@ pub mod prelude { #[cfg(feature = "clock")] #[doc(no_inline)] pub use Local; - #[cfg(feature = "locales")] + #[cfg(feature = "unstable-locales")] #[doc(no_inline)] pub use Locale; #[doc(no_inline)]