thisweek_core/calendar/
chinese.rs

1use crate::weekdays::convert_weekday;
2use crate::weekdays::is_weekday_weekend_holiday;
3use crate::{
4    language::{str_to_vec, Language},
5    week_info::{Date, DateView},
6};
7
8use crate::calendar::calendar_names::*;
9use crate::month_names::*;
10use crate::season_names::*;
11use crate::weekday_names::*;
12
13use super::{Calendar, CalendarSpecificDateView, CalendarView, CALENDAR_CHINESE};
14use chinese_lunisolar_calendar::{LunisolarDate, SolarDate};
15use chrono::{DateTime, Datelike, Local};
16use serde::Serialize;
17
18#[derive(Debug, Serialize, Clone, PartialEq)]
19pub struct ChineseCalendar;
20
21impl CalendarSpecificDateView for ChineseCalendar {
22    fn new_date(datetime: DateTime<Local>) -> Date {
23        let year = datetime.year() as u16;
24        let month = datetime.month() as u8;
25        let day = datetime.day() as u8;
26        let solar_date = SolarDate::from_ymd(year, month, day).unwrap();
27        let lunisolar_date = LunisolarDate::from_solar_date(solar_date).unwrap();
28        let month_number = lunisolar_date.to_lunar_month().to_u8() as u32;
29        Date {
30            calendar: Calendar::Chinese(ChineseCalendar),
31            weekday: convert_weekday(datetime.weekday()) as u32,
32            day: lunisolar_date.to_lunar_day() as u32,
33            month: month_number,
34            year: lunisolar_date.to_lunisolar_year().to_u16() as i32,
35        }
36    }
37
38    fn new_date_view(datetime: DateTime<Local>, lang: &Language) -> DateView {
39        let year = datetime.year() as u16;
40        let month = datetime.month() as u8;
41        let day = datetime.day() as u8;
42        let weekday = datetime.weekday();
43        let solar_date = SolarDate::from_ymd(year, month, day).unwrap();
44        let lunisolar_date = LunisolarDate::from_solar_date(solar_date).unwrap();
45        let day = lunisolar_date.to_lunar_day();
46        let month = lunisolar_date.to_lunar_month();
47        let year = lunisolar_date.to_lunisolar_year();
48        let month_index = (lunisolar_date.to_lunar_month().to_u8() - 1) as u32;
49        let day = match lang {
50            Language::Chinese => day.to_string(),
51            _ => day.to_u8().to_string(),
52        };
53        let month = match lang {
54            // format!("{:#}", month), // simplified chinese names
55            Language::Chinese => {
56                if month.is_leap_month() {
57                    format!(
58                        "{}{}",
59                        CHINESE_LEAP_MONTH_PREFIX_ZH, CHINESE_MONTH_NAME_ZH[month_index as usize]
60                    )
61                } else {
62                    CHINESE_MONTH_NAME_ZH[month_index as usize].to_string()
63                }
64            }
65            _ => {
66                if month.is_leap_month() {
67                    format!(
68                        "{}{}",
69                        CHINESE_LEAP_MONTH_PREFIX_EN, CHINESE_MONTH_NAME_EN[month_index as usize]
70                    )
71                } else {
72                    CHINESE_MONTH_NAME_EN[month_index as usize].to_string()
73                }
74            }
75        };
76        let year = match lang {
77            // Language::Chinese => year.to_string(), // this is not very intuitive!
78            Language::Chinese => year.to_u16().to_string(),
79            _ => year.to_u16().to_string(),
80        };
81
82        let weekday = convert_weekday(weekday) as usize;
83        let weekend_holiday = is_weekday_weekend_holiday(weekday.into());
84        let full_format = match lang {
85            Language::Chinese => format!(
86                "{}, {} {} {}",
87                WEEKDAY_NAME_FULL_CN[weekday], day, month, year
88            ),
89            _ => format!(
90                "{}, {} {} {}",
91                WEEKDAY_NAME_FULL_EN[weekday], day, month, year
92            ),
93        }
94        .to_string();
95        let weekday = match lang {
96            Language::Chinese => WEEKDAY_NAME_FULL_CN[weekday],
97            _ => WEEKDAY_NAME_HALF_CAP_EN[weekday],
98        }
99        .to_string();
100
101        DateView {
102            unix_day: 0,
103            day,
104            month,
105            weekday,
106            year,
107            full_format,
108            weekend_holiday,
109        }
110    }
111
112    fn get_calendar_view(lang: &Language) -> CalendarView {
113        let months_names: Vec<String> = match lang {
114            Language::Chinese => str_to_vec(&CHINESE_MONTH_NAME_ZH),
115            _ => str_to_vec(&CHINESE_MONTH_NAME_EN),
116        };
117        let seasons_names: Vec<String> = match lang {
118            Language::Chinese => str_to_vec(&SEASON_NAME_ZH),
119            _ => str_to_vec(&SEASON_NAME_EN),
120        };
121        let calendar_name: String = match lang {
122            // Language::Chinese => "中国农历".into(),
123            Language::Chinese => CHINESE_CALENDAR_NAME_ZH.into(),
124            _ => CHINESE_CALENDAR_NAME_EN.into(),
125        };
126        CalendarView {
127            calendar: CALENDAR_CHINESE,
128            calendar_name,
129            language: lang.clone().into(),
130            direction: lang.default_direction(),
131            months_names,
132            seasons_names,
133        }
134    }
135}