Skip to content

Commit 1a28516

Browse files
Add weekday, month and era getters on FixedCalendarDateTimeNames
1 parent 4259cb6 commit 1a28516

File tree

1 file changed

+196
-2
lines changed

1 file changed

+196
-2
lines changed

components/datetime/src/pattern/names.rs

Lines changed: 196 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ use super::{
1010
use crate::error::ErrorField;
1111
use crate::fieldsets::enums::{CompositeDateTimeFieldSet, CompositeFieldSet};
1212
use crate::provider::fields::{self, FieldLength, FieldSymbol};
13-
use crate::provider::neo::{marker_attrs, *};
13+
use crate::provider::neo::{get_year_name_from_map, marker_attrs, MonthNames, YearNames, *};
1414
use crate::provider::pattern::PatternItem;
1515
use crate::provider::time_zones::tz;
1616
use crate::size_test_macro::size_test;
@@ -19,7 +19,7 @@ use crate::{external_loaders::*, DateTimeFormatterPreferences};
1919
use crate::{scaffold::*, DateTimeFormatter, DateTimeFormatterLoadError};
2020
use core::fmt;
2121
use core::marker::PhantomData;
22-
use icu_calendar::types::{EraYear, MonthCode};
22+
use icu_calendar::types::{EraYear, MonthCode, Weekday};
2323
use icu_calendar::AnyCalendar;
2424
use icu_decimal::options::DecimalFormatterOptions;
2525
use icu_decimal::options::GroupingStrategy;
@@ -2826,6 +2826,200 @@ where
28262826
}
28272827
}
28282828

2829+
impl<C, FSet: DateTimeNamesMarker> FixedCalendarDateTimeNames<C, FSet>
2830+
where
2831+
FSet::WeekdayNames: NamesContainer<
2832+
WeekdayNamesV1,
2833+
WeekdayNameLength,
2834+
Container = DataPayloadWithVariables<WeekdayNamesV1, WeekdayNameLength>,
2835+
>,
2836+
{
2837+
/// Gets the weekday name for the specified length and weekday if the data is loaded.
2838+
///
2839+
/// Returns `Some` if the data for the specified length is loaded, or `None` if not loaded.
2840+
///
2841+
/// # Examples
2842+
///
2843+
/// ```
2844+
/// use icu::calendar::types::Weekday;
2845+
/// use icu::calendar::Gregorian;
2846+
/// use icu::datetime::pattern::{FixedCalendarDateTimeNames, WeekdayNameLength};
2847+
/// use icu::locale::locale;
2848+
///
2849+
/// let mut names =
2850+
/// FixedCalendarDateTimeNames::<Gregorian>::try_new(locale!("en").into())
2851+
/// .unwrap();
2852+
///
2853+
/// // Before loading data, the getter returns None:
2854+
/// assert_eq!(names.get_weekday(Weekday::Monday, WeekdayNameLength::Wide), None);
2855+
///
2856+
/// // Load the weekday names:
2857+
/// names
2858+
/// .include_weekday_names(WeekdayNameLength::Wide)
2859+
/// .unwrap();
2860+
///
2861+
/// // Now we can get the weekday name for the loaded length:
2862+
/// assert_eq!(
2863+
/// names.get_weekday(Weekday::Monday, WeekdayNameLength::Wide),
2864+
/// Some("Monday")
2865+
/// );
2866+
///
2867+
/// // But other lengths are not loaded:
2868+
/// assert_eq!(
2869+
/// names.get_weekday(Weekday::Monday, WeekdayNameLength::Abbreviated),
2870+
/// None
2871+
/// );
2872+
/// ```
2873+
pub fn get_weekday(&self, weekday: Weekday, length: WeekdayNameLength) -> Option<&str> {
2874+
let borrowed = self.inner.as_borrowed();
2875+
borrowed
2876+
.weekday_names
2877+
.get_with_variables(length)
2878+
.and_then(|names| names.names.get((weekday as usize) % 7))
2879+
}
2880+
}
2881+
2882+
impl<C: CldrCalendar, FSet: DateTimeNamesMarker> FixedCalendarDateTimeNames<C, FSet>
2883+
where
2884+
FSet::MonthNames: NamesContainer<
2885+
MonthNamesV1,
2886+
MonthNameLength,
2887+
Container = DataPayloadWithVariables<MonthNamesV1, MonthNameLength>,
2888+
>,
2889+
{
2890+
/// Gets the month name for the specified length and month code if the data is loaded.
2891+
///
2892+
/// Returns `Some` if the data for the specified length is loaded and the month code is valid,
2893+
/// or `None` if not loaded or the month code is invalid.
2894+
///
2895+
/// # Examples
2896+
///
2897+
/// ```
2898+
/// use icu::calendar::types::MonthCode;
2899+
/// use icu::calendar::Gregorian;
2900+
/// use icu::datetime::pattern::{FixedCalendarDateTimeNames, MonthNameLength};
2901+
/// use icu::locale::locale;
2902+
///
2903+
/// let mut names =
2904+
/// FixedCalendarDateTimeNames::<Gregorian>::try_new(locale!("en").into())
2905+
/// .unwrap();
2906+
///
2907+
/// // Before loading data, the getter returns None:
2908+
/// assert_eq!(
2909+
/// names.get_month(MonthCode(tinystr::tinystr!(4, "M01")), MonthNameLength::Wide),
2910+
/// None
2911+
/// );
2912+
///
2913+
/// // Load the month names:
2914+
/// names
2915+
/// .include_month_names(MonthNameLength::Wide)
2916+
/// .unwrap();
2917+
///
2918+
/// // Now we can get the month name for the loaded length:
2919+
/// assert_eq!(
2920+
/// names.get_month(MonthCode(tinystr::tinystr!(4, "M01")), MonthNameLength::Wide),
2921+
/// Some("January")
2922+
/// );
2923+
///
2924+
/// // But other lengths are not loaded:
2925+
/// assert_eq!(
2926+
/// names.get_month(
2927+
/// MonthCode(tinystr::tinystr!(4, "M01")),
2928+
/// MonthNameLength::Abbreviated
2929+
/// ),
2930+
/// None
2931+
/// );
2932+
/// ```
2933+
pub fn get_month(&self, month_code: MonthCode, length: MonthNameLength) -> Option<&str> {
2934+
let borrowed = self.inner.as_borrowed();
2935+
let month_names = borrowed.month_names.get_with_variables(length)?;
2936+
2937+
let (month_number, is_leap) = month_code.parsed()?;
2938+
let month_index = usize::from(month_number.checked_sub(1)?);
2939+
2940+
match month_names {
2941+
MonthNames::Linear(linear) => {
2942+
if is_leap {
2943+
None
2944+
} else {
2945+
linear.get(month_index)
2946+
}
2947+
}
2948+
MonthNames::LeapLinear(leap_linear) => {
2949+
let num_months = leap_linear.len() / 2;
2950+
if is_leap {
2951+
leap_linear.get(month_index + num_months)
2952+
} else if month_index < num_months {
2953+
leap_linear.get(month_index)
2954+
} else {
2955+
None
2956+
}
2957+
}
2958+
MonthNames::LeapNumeric(_) => None,
2959+
}
2960+
}
2961+
}
2962+
2963+
impl<C: CldrCalendar, FSet: DateTimeNamesMarker> FixedCalendarDateTimeNames<C, FSet>
2964+
where
2965+
FSet::YearNames: NamesContainer<
2966+
YearNamesV1,
2967+
YearNameLength,
2968+
Container = DataPayloadWithVariables<YearNamesV1, YearNameLength>,
2969+
>,
2970+
{
2971+
/// Gets the era name for the specified length and era if the data is loaded.
2972+
///
2973+
/// Returns `Some` if the data for the specified length is loaded and the era is valid,
2974+
/// or `None` if not loaded or the era is invalid.
2975+
///
2976+
/// Note: This is a low-level API. The `era_year` parameter is typically obtained from
2977+
/// calendar date operations. Most users should use the formatting APIs instead.
2978+
///
2979+
/// # Examples
2980+
///
2981+
/// ```
2982+
/// use icu::calendar::{Date, Gregorian};
2983+
/// use icu::datetime::pattern::{FixedCalendarDateTimeNames, YearNameLength};
2984+
/// use icu::locale::locale;
2985+
///
2986+
/// let mut names =
2987+
/// FixedCalendarDateTimeNames::<Gregorian>::try_new(locale!("en").into())
2988+
/// .unwrap();
2989+
///
2990+
/// // Get era from a date
2991+
/// let date = Date::try_new_gregorian(2024, 1, 1).unwrap();
2992+
/// let era_year = date.era_year();
2993+
///
2994+
/// // Before loading data, the getter returns None:
2995+
/// assert_eq!(names.get_era(&era_year, YearNameLength::Wide), None);
2996+
///
2997+
/// // Load the year names:
2998+
/// names.include_year_names(YearNameLength::Wide).unwrap();
2999+
///
3000+
/// // Now we can get the era name for the loaded length:
3001+
/// assert_eq!(names.get_era(&era_year, YearNameLength::Wide), Some("Anno Domini"));
3002+
///
3003+
/// // But other lengths are not loaded:
3004+
/// assert_eq!(
3005+
/// names.get_era(&era_year, YearNameLength::Abbreviated),
3006+
/// None
3007+
/// );
3008+
/// ```
3009+
pub fn get_era(&self, era_year: &EraYear, length: YearNameLength) -> Option<&str> {
3010+
let borrowed = self.inner.as_borrowed();
3011+
let year_names = borrowed.year_names.get_with_variables(length)?;
3012+
3013+
match (year_names, era_year.era_index) {
3014+
(YearNames::VariableEras(era_names), None) => {
3015+
get_year_name_from_map(era_names, era_year.era.as_str().into())
3016+
}
3017+
(YearNames::FixedEras(era_names), Some(index)) => era_names.get(index as usize),
3018+
_ => None,
3019+
}
3020+
}
3021+
}
3022+
28293023
impl<FSet: DateTimeNamesMarker> DateTimeNames<FSet> {
28303024
/// Maps a [`FixedCalendarDateTimeNames`] of a specific `FSet` to a more general `FSet`.
28313025
///

0 commit comments

Comments
 (0)