///|
/// A month and a day with no year, such as a recurring anniversary.
///
/// A reference year is kept internally so the pair names a concrete date;
/// 1972 is used because it is a leap year, so February 29 survives the round
/// trip.
///
/// Reference:
pub struct PlainMonthDay {
iso : IsoDate
calendar : Calendar
} derive(Eq)
///|
pub impl Show for PlainMonthDay with fn output(self, logger) {
logger.write_string(self.to_string_with_options(DisplayCalendar::default()))
}
///|
pub impl Debug for PlainMonthDay with fn to_repr(self) {
Repr::Repr(self.to_string())
}
///|
/// The reference year the specification uses for a bare month-day.
pub const MONTH_DAY_REFERENCE_YEAR : Int = 1972
///|
/// Creates a month-day.
///
/// ```mbt check
/// test {
/// inspect(@temporal.PlainMonthDay::try_new(2, 29), content="02-29")
/// }
/// ```
pub fn PlainMonthDay::try_new(
month : Int,
day : Int,
reference_year? : Int = MONTH_DAY_REFERENCE_YEAR,
overflow? : Overflow = Reject,
calendar? : Calendar = Calendar::ISO,
) -> PlainMonthDay raise TemporalError {
let iso = IsoDate::new_with_overflow(reference_year, month, day, overflow)
{ iso, calendar }
}
///|
/// Returns the month, 1-based.
pub fn PlainMonthDay::month(self : PlainMonthDay) -> Int {
self.iso.month
}
///|
/// Returns the calendar-independent month code.
pub fn PlainMonthDay::month_code(self : PlainMonthDay) -> String {
month_code_of(self.iso.month)
}
///|
/// Returns the day of the month.
pub fn PlainMonthDay::day(self : PlainMonthDay) -> Int {
self.iso.day
}
///|
/// Returns the calendar.
pub fn PlainMonthDay::calendar(self : PlainMonthDay) -> Calendar {
self.calendar
}
///|
/// Returns the internal reference year.
pub fn PlainMonthDay::reference_year(self : PlainMonthDay) -> Int {
self.iso.year
}
///|
/// Returns whether both name the same month and day in the same calendar.
pub fn PlainMonthDay::equals(
self : PlainMonthDay,
other : PlainMonthDay,
) -> Bool {
self.iso == other.iso && self.calendar == other.calendar
}
///|
/// Returns a copy with the month or day replaced.
pub fn PlainMonthDay::with_fields(
self : PlainMonthDay,
month? : Int,
day? : Int,
overflow? : Overflow = Constrain,
) -> PlainMonthDay raise TemporalError {
PlainMonthDay::try_new(
month.unwrap_or(self.iso.month),
day.unwrap_or(self.iso.day),
reference_year=self.iso.year,
overflow~,
calendar=self.calendar,
)
}
///|
/// Combines this month-day with a year to produce a `PlainDate`.
///
/// ```mbt check
/// test {
/// let leap_day = @temporal.PlainMonthDay::try_new(2, 29)
/// // 2023 is not a leap year, so the day is constrained to the 28th.
/// inspect(leap_day.to_plain_date(2023), content="2023-02-28")
/// }
/// ```
pub fn PlainMonthDay::to_plain_date(
self : PlainMonthDay,
year : Int,
overflow? : Overflow = Constrain,
) -> PlainDate raise TemporalError {
PlainDate::new_with_overflow(
year,
self.iso.month,
self.iso.day,
overflow,
self.calendar,
)
}
///|
/// Parses a month-day from an RFC 9557 string.
///
/// ```mbt check
/// test {
/// inspect(@temporal.PlainMonthDay::of_string("--02-29"), content="02-29")
/// inspect(@temporal.PlainMonthDay::of_string("2024-02-29"), content="02-29")
/// }
/// ```
pub fn PlainMonthDay::of_string(
source : String,
) -> PlainMonthDay raise TemporalError {
let record = parse_month_day_string(source)
let date = temporal_unwrap(record.date, "date component")
// The reference year is always 1972, whether or not the string named one:
// a month-day has no year of its own, and 1972 is a leap year so that
// February 29 survives.
PlainMonthDay::try_new(
date.month,
date.day,
reference_year=MONTH_DAY_REFERENCE_YEAR,
calendar=calendar_of(record),
)
}
///|
/// Renders the month-day as `MM-DD`.
///
/// The reference year is included when a calendar annotation is present,
/// since a non-ISO calendar needs it to reconstruct the same day.
pub fn PlainMonthDay::to_string_with_options(
self : PlainMonthDay,
display_calendar : DisplayCalendar,
) -> String {
let buf = StringBuilder::new()
if display_calendar is (Always | Critical) || self.calendar != Calendar::ISO {
write_year(buf, self.iso.year)
buf.write_string("-")
}
write_padded_2(buf, self.iso.month)
buf.write_string("-")
write_padded_2(buf, self.iso.day)
write_calendar_annotation(buf, self.calendar, display_calendar)
buf.to_string()
}
///|
/// Renders the month-day as `MM-DD`.
pub fn PlainMonthDay::to_string(self : PlainMonthDay) -> String {
self.to_string_with_options(DisplayCalendar::default())
}