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