use crate::Error;
use crate::format::Digits;
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, Default)]
pub enum Lang {
#[default]
En,
Ne,
}
impl Lang {
#[must_use]
pub const fn digits(self, n: u32, min_width: u8) -> Digits {
Digits::new(n, min_width, self)
}
}
#[repr(u8)]
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
pub enum Month {
Baishakh = 1,
Jestha,
Ashad,
Shrawan,
Bhadra,
Ashoj,
Kartik,
Mangsir,
Poush,
Magh,
Falgun,
Chaitra,
}
const MONTH_EN: [&str; 12] = [
"Baishakh", "Jestha", "Ashad", "Shrawan", "Bhadra", "Ashoj", "Kartik", "Mangsir", "Poush",
"Magh", "Falgun", "Chaitra",
];
const MONTH_EN_SHORT: [&str; 12] = [
"Bai", "Jes", "Asa", "Shr", "Bha", "Aso", "Kar", "Man", "Pou", "Mag", "Fal", "Cha",
];
const MONTH_NE: [&str; 12] = [
"बैशाख",
"जेठ",
"असार",
"साउन",
"भदौ",
"असोज",
"कार्तिक",
"मंसिर",
"पुष",
"माघ",
"फागुन",
"चैत",
];
impl Month {
pub const ALL: [Month; 12] = [
Month::Baishakh,
Month::Jestha,
Month::Ashad,
Month::Shrawan,
Month::Bhadra,
Month::Ashoj,
Month::Kartik,
Month::Mangsir,
Month::Poush,
Month::Magh,
Month::Falgun,
Month::Chaitra,
];
#[must_use]
pub const fn number(self) -> u8 {
self as u8
}
pub(crate) const fn from_number(m: u8) -> Option<Month> {
match m {
1 => Some(Month::Baishakh),
2 => Some(Month::Jestha),
3 => Some(Month::Ashad),
4 => Some(Month::Shrawan),
5 => Some(Month::Bhadra),
6 => Some(Month::Ashoj),
7 => Some(Month::Kartik),
8 => Some(Month::Mangsir),
9 => Some(Month::Poush),
10 => Some(Month::Magh),
11 => Some(Month::Falgun),
12 => Some(Month::Chaitra),
_ => None,
}
}
const fn index(self) -> usize {
self as usize - 1
}
#[must_use]
#[allow(clippy::indexing_slicing)] pub fn name(self, lang: Lang) -> &'static str {
match lang {
Lang::En => MONTH_EN[self.index()],
Lang::Ne => MONTH_NE[self.index()],
}
}
#[must_use]
#[allow(clippy::indexing_slicing)] pub fn short_name(self, lang: Lang) -> &'static str {
match lang {
Lang::En => MONTH_EN_SHORT[self.index()],
Lang::Ne => MONTH_NE[self.index()],
}
}
#[must_use]
#[allow(clippy::indexing_slicing)] pub fn next(self) -> Month {
Month::ALL[usize::from(self.number() % 12)]
}
#[must_use]
#[allow(clippy::indexing_slicing)] pub fn prev(self) -> Month {
Month::ALL[usize::from((self.number() + 10) % 12)]
}
}
impl TryFrom<u8> for Month {
type Error = Error;
fn try_from(m: u8) -> Result<Self, Error> {
Month::from_number(m).ok_or(Error::InvalidMonth(m))
}
}
#[repr(u8)]
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
pub enum Weekday {
Sunday = 0,
Monday,
Tuesday,
Wednesday,
Thursday,
Friday,
Saturday,
}
const WEEKDAY_EN: [&str; 7] = [
"Sunday",
"Monday",
"Tuesday",
"Wednesday",
"Thursday",
"Friday",
"Saturday",
];
const WEEKDAY_EN_SHORT: [&str; 7] = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
const WEEKDAY_NE: [&str; 7] = [
"आइतवार",
"सोमवार",
"मङ्गलवार",
"बुधवार",
"बिहिवार",
"शुक्रवार",
"शनिवार",
];
const WEEKDAY_NE_SHORT: [&str; 7] = ["आइत", "सोम", "मङ्गल", "बुध", "बिहि", "शुक्र", "शनि"];
impl Weekday {
pub const ALL: [Weekday; 7] = [
Weekday::Sunday,
Weekday::Monday,
Weekday::Tuesday,
Weekday::Wednesday,
Weekday::Thursday,
Weekday::Friday,
Weekday::Saturday,
];
#[must_use]
pub const fn index_from_sunday(self) -> u8 {
self as u8
}
#[must_use]
#[allow(clippy::indexing_slicing)] pub fn name(self, lang: Lang) -> &'static str {
let i = usize::from(self.index_from_sunday());
match lang {
Lang::En => WEEKDAY_EN[i],
Lang::Ne => WEEKDAY_NE[i],
}
}
#[must_use]
#[allow(clippy::indexing_slicing)] pub fn short_name(self, lang: Lang) -> &'static str {
let i = usize::from(self.index_from_sunday());
match lang {
Lang::En => WEEKDAY_EN_SHORT[i],
Lang::Ne => WEEKDAY_NE_SHORT[i],
}
}
}
#[cfg(test)]
mod tests {
use super::*;
fn nepali_ok(s: &str) {
assert!(!s.is_empty());
assert!(!s.bytes().any(|b| b.is_ascii()), "{s} contains ASCII");
}
#[test]
fn nepali_names_have_no_ascii() {
for m in Month::ALL {
nepali_ok(m.name(Lang::Ne));
nepali_ok(m.short_name(Lang::Ne));
}
for w in Weekday::ALL {
nepali_ok(w.name(Lang::Ne));
nepali_ok(w.short_name(Lang::Ne));
}
}
#[test]
fn month_numbers_round_trip() {
for (i, m) in Month::ALL.into_iter().enumerate() {
let n = u8::try_from(i + 1).unwrap_or(0);
assert_eq!(m.number(), n);
assert_eq!(Month::try_from(n), Ok(m));
assert_eq!(m.next().prev(), m);
}
assert_eq!(Month::try_from(0), Err(Error::InvalidMonth(0)));
assert_eq!(Month::try_from(13), Err(Error::InvalidMonth(13)));
}
#[test]
fn english_names() {
assert_eq!(Month::Ashoj.short_name(Lang::En), "Aso");
assert_eq!(Month::Baishakh.name(Lang::En), "Baishakh");
assert_eq!(Weekday::Sunday.name(Lang::En), "Sunday");
}
}