use std::fmt::Debug; use std::num::NonZero; use rstest::rstest; use time::format_description::modifier::{Hour12, WeekNumberIso}; use time::format_description::{BorrowedFormatItem, Component}; use time::parsing::Parsed; use time::{Month, Time, Weekday, error}; #[rstest] #[case(Parsed::set_year, Parsed::year, 5)] #[case(Parsed::set_year_last_two, Parsed::year_last_two, 5)] #[case(Parsed::set_iso_year, Parsed::iso_year, 5)] #[case(Parsed::set_iso_year_last_two, Parsed::iso_year_last_two, 5)] #[case(Parsed::set_month, Parsed::month, Month::May)] #[case(Parsed::set_sunday_week_number, Parsed::sunday_week_number, 5)] #[case(Parsed::set_monday_week_number, Parsed::monday_week_number, 5)] #[case(Parsed::set_iso_week_number, Parsed::iso_week_number, const { NonZero::new(5).unwrap() })] #[case(Parsed::set_weekday, Parsed::weekday, Weekday::Monday)] #[case(Parsed::set_ordinal, Parsed::ordinal, const { NonZero::new(5).unwrap() })] #[case(Parsed::set_day, Parsed::day, const { NonZero::new(5).unwrap() })] #[case(Parsed::set_hour_24, Parsed::hour_24, 5)] #[case(Parsed::set_hour_12, Parsed::hour_12, const { NonZero::new(5).unwrap() })] #[case(Parsed::set_hour_12_is_pm, Parsed::hour_12_is_pm, true)] #[case(Parsed::set_minute, Parsed::minute, 5)] #[case(Parsed::set_second, Parsed::second, 5)] #[case(Parsed::set_subsecond, Parsed::subsecond, 5)] #[case(Parsed::set_offset_hour, Parsed::offset_hour, 5)] #[expect(deprecated)] #[case(Parsed::set_offset_minute, Parsed::offset_minute, 5)] #[case(Parsed::set_offset_minute_signed, Parsed::offset_minute_signed, -5)] #[expect(deprecated)] #[case(Parsed::set_offset_second, Parsed::offset_second, 5)] #[case(Parsed::set_offset_second_signed, Parsed::offset_second_signed, -5)] fn getters_setters( #[case] setter: fn(&mut Parsed, T) -> Option<()>, #[case] getter: fn(&Parsed) -> Option, #[case] value: T, ) where T: PartialEq + Copy + Debug, { let mut parsed = Parsed::new(); assert!(setter(&mut parsed, value).is_some()); assert_eq!(getter(&parsed), Some(value)); } #[rstest] #[expect(deprecated)] #[case(Parsed::set_offset_minute, Parsed::offset_minute, 200)] #[expect(deprecated)] #[case(Parsed::set_offset_second, Parsed::offset_second, 200)] fn getters_setters_fail( #[case] setter: fn(&mut Parsed, T) -> Option<()>, #[case] getter: fn(&Parsed) -> Option, #[case] value: T, ) { let mut parsed = Parsed::new(); assert!(setter(&mut parsed, value).is_none()); assert!(getter(&parsed).is_none()); } #[rstest] #[case(Parsed::with_year, Parsed::year, 5)] #[case(Parsed::with_year_last_two, Parsed::year_last_two, 5)] #[case(Parsed::with_iso_year, Parsed::iso_year, 5)] #[case(Parsed::with_iso_year_last_two, Parsed::iso_year_last_two, 5)] #[case(Parsed::with_month, Parsed::month, Month::May)] #[case(Parsed::with_sunday_week_number, Parsed::sunday_week_number, 5)] #[case(Parsed::with_monday_week_number, Parsed::monday_week_number, 5)] #[case(Parsed::with_iso_week_number, Parsed::iso_week_number, const { NonZero::new(5).unwrap() })] #[case(Parsed::with_weekday, Parsed::weekday, Weekday::Monday)] #[case(Parsed::with_ordinal, Parsed::ordinal, const { NonZero::new(5).unwrap() })] #[case(Parsed::with_day, Parsed::day, const { NonZero::new(5).unwrap() })] #[case(Parsed::with_hour_24, Parsed::hour_24, 5)] #[case(Parsed::with_hour_12, Parsed::hour_12, const { NonZero::new(5).unwrap() })] #[case(Parsed::with_hour_12_is_pm, Parsed::hour_12_is_pm, true)] #[case(Parsed::with_minute, Parsed::minute, 5)] #[case(Parsed::with_second, Parsed::second, 5)] #[case(Parsed::with_subsecond, Parsed::subsecond, 5)] #[case(Parsed::with_offset_hour, Parsed::offset_hour, 5)] #[expect(deprecated)] #[case(Parsed::with_offset_minute, Parsed::offset_minute, 5)] #[case(Parsed::with_offset_minute_signed, Parsed::offset_minute_signed, -5)] #[expect(deprecated)] #[case(Parsed::with_offset_second, Parsed::offset_second, 5)] #[case(Parsed::with_offset_second_signed, Parsed::offset_second_signed, -5)] fn builder_methods( #[case] builder: fn(Parsed, T) -> Option, #[case] getter: fn(&Parsed) -> Option, #[case] value: T, ) where T: PartialEq + Copy + Debug, { let parsed = builder(Parsed::new(), value).expect("valid value"); assert_eq!(getter(&parsed), Some(value)); } #[rstest] #[expect(deprecated)] #[case(Parsed::with_offset_minute, Parsed::offset_minute, 200)] #[expect(deprecated)] #[case(Parsed::with_offset_second, Parsed::offset_second, 200)] fn builder_methods_fail( #[case] builder: fn(Parsed, T) -> Option, #[case] getter: fn(&Parsed) -> Option, #[case] value: T, ) { assert!(builder(Parsed::new(), value).is_none()); assert!(getter(&Parsed::new()).is_none()); } #[rstest] #[case("a", BorrowedFormatItem::StringLiteral("a"))] #[case("b", BorrowedFormatItem::StringLiteral("a"))] fn single_item_parse(#[case] input: &str, #[case] format_item: BorrowedFormatItem) { assert!(Time::parse(input, &format_item).is_err()); } #[rstest] #[case("day", Component::Day(<_>::default()), b"")] #[case("month", Component::MonthNumerical(<_>::default()), b"")] #[case("ordinal", Component::Ordinal(<_>::default()), b"")] #[case("weekday", Component::WeekdayLong(<_>::default()), b"")] #[case("week number", Component::WeekNumberIso(<_>::default()), b"")] #[case("year", Component::CalendarYearFullExtendedRange(<_>::default()), b"")] #[case("minute", Component::Minute(<_>::default()), b"")] #[case("period", Component::Period(<_>::default()), b"")] #[case("second", Component::Second(<_>::default()), b"")] #[case("subsecond", Component::Subsecond(<_>::default()), b"")] #[case("offset hour", Component::OffsetHour(<_>::default()), b"")] #[case("offset minute", Component::OffsetMinute(<_>::default()), b"")] #[case("offset second", Component::OffsetSecond(<_>::default()), b"")] #[case("unix_timestamp", Component::UnixTimestampSecond(<_>::default()), b"")] #[case( "week number", Component::WeekNumberIso(WeekNumberIso::default()), b"00" )] #[case("hour", Component::Hour12(Hour12::default()), b"00")] fn component_err( #[case] component_name: &'static str, #[case] component: Component, #[case] input: &[u8], ) { let mut parsed = Parsed::new(); assert_eq!( parsed.parse_component(input, component), Err(error::ParseFromDescription::InvalidComponent( component_name )) ); }