thisweek_core/calendar/
persian.rs1use crate::language::str_to_vec;
2use crate::weekdays::convert_weekday;
3use crate::weekdays::is_weekday_weekend_holiday;
4use crate::{language::Language, week_info::Date, week_info::DateView};
5use chrono::{DateTime, Datelike, Local};
6use serde::Serialize;
7
8use crate::calendar::{Calendar, CalendarSpecificDateView, CalendarView, CALENDAR_PERSIAN};
9
10use crate::calendar::calendar_names::*;
11use crate::month_names::*;
12use crate::season_names::*;
13use crate::weekday_names::*;
14
15#[derive(Debug, Serialize, Clone, PartialEq)]
16pub struct PersianCalendar;
17
18impl CalendarSpecificDateView for PersianCalendar {
33 fn new_date(datetime: DateTime<Local>) -> Date {
34 let (gy, gm, gd) = (datetime.year(), datetime.month(), datetime.day());
35 let (year, month, day) = Self::gregorian_to_jalali(gy, gm, gd);
36 let weekday = convert_weekday(datetime.weekday()) as u32;
37 Date {
38 calendar: Calendar::Persian(PersianCalendar),
39 day,
40 month,
41 weekday,
42 year,
43 }
44 }
45
46 fn new_date_view(datetime: DateTime<Local>, lang: &Language) -> DateView {
47 let (gy, gm, gd) = (datetime.year(), datetime.month(), datetime.day());
48 let (year, month, day) = Self::gregorian_to_jalali(gy, gm, gd);
49 let day = lang.change_numbers_language(&day.to_string());
50 let month = (month - 1) as usize;
51 let month = match lang {
52 Language::Farsi => PERSIAN_MONTH_NAME_FA[month],
53 _ => PERSIAN_MONTH_NAME_EN[month],
54 };
55 let month = month.to_string();
56 let year = lang.change_numbers_language(&year.to_string());
57 let weekday = convert_weekday(datetime.weekday()) as usize;
58 let weekend_holiday = is_weekday_weekend_holiday(weekday.into());
59 let full_format = match lang {
60 Language::Farsi => format!(
61 "{}، {} {} {}",
62 WEEKDAY_NAME_FULL_FA[weekday], day, month, year
63 ),
64 _ => format!(
65 "{}, {} {} {}",
66 WEEKDAY_NAME_FULL_EN[weekday], day, month, year
67 ),
68 }
69 .to_string();
70 let weekday = match lang {
71 Language::Farsi => WEEKDAY_NAME_FULL_FA[weekday],
72 _ => WEEKDAY_NAME_HALF_CAP_EN[weekday],
73 }
74 .to_string();
75 DateView {
76 unix_day: 0,
77 day,
78 month,
79 weekday,
80 year,
81 full_format,
82 weekend_holiday,
83 }
84 }
85
86 fn get_calendar_view(lang: &Language) -> CalendarView {
87 let months_names: Vec<String> = match lang {
88 Language::Farsi => str_to_vec(&PERSIAN_MONTH_NAME_FA),
89 _ => str_to_vec(&PERSIAN_MONTH_NAME_EN),
90 };
91 let seasons_names: Vec<String> = match lang {
92 Language::Farsi => str_to_vec(&SEASON_NAME_FA),
93 _ => str_to_vec(&SEASON_NAME_EN),
94 };
95 let calendar_name: String = match lang {
96 Language::Farsi => PERSIAN_CALENDAR_NAME_FA.into(),
97 _ => PERSIAN_CALENDAR_NAME_EN.into(),
98 };
99 CalendarView {
100 calendar: CALENDAR_PERSIAN,
101 calendar_name,
102 language: lang.clone().into(),
103 direction: lang.default_direction(),
104 months_names,
105 seasons_names,
106 }
107 }
108}
109
110impl PersianCalendar {
111 fn gregorian_to_jalali(gy: i32, gm: u32, gd: u32) -> (i32, u32, u32) {
118 const G_D_M: [i32; 12] = [0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334];
119 let gy2 = if gm > 2 { gy + 1 } else { gy };
120
121 let mut days = 355666 + (365 * gy) + ((gy2 + 3) / 4) - ((gy2 + 99) / 100)
122 + ((gy2 + 399) / 400)
123 + gd as i32
124 + G_D_M[(gm - 1) as usize];
125
126 let mut jy = -1595 + (33 * (days / 12053));
127 days %= 12053;
128 jy += 4 * (days / 1461);
129 days %= 1461;
130
131 if days > 365 {
132 jy += (days - 1) / 365;
133 days = (days - 1) % 365;
134 }
135
136 let jm = if days < 186 {
137 1 + (days / 31)
138 } else {
139 7 + ((days - 186) / 30)
140 };
141
142 let jd = if days < 186 {
143 1 + (days % 31)
144 } else {
145 1 + ((days - 186) % 30)
146 };
147
148 (jy, jm as u32, jd as u32)
149 }
150}