xref: /aosp_15_r20/external/cronet/third_party/rust/chromium_crates_io/vendor/fend-core-1.4.6/src/date.rs (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 use std::{fmt, io};
2 
3 mod day;
4 mod day_of_week;
5 mod month;
6 mod parser;
7 mod year;
8 
9 use day::Day;
10 pub(crate) use day_of_week::DayOfWeek;
11 pub(crate) use month::Month;
12 use year::Year;
13 
14 use crate::{error::FendError, ident::Ident, result::FResult, value::Value, Interrupt};
15 
16 #[derive(Copy, Clone, Eq, PartialEq)]
17 pub(crate) struct Date {
18 	year: Year,
19 	month: Month,
20 	day: Day,
21 }
22 
23 impl Date {
today(context: &crate::Context) -> FResult<Self>24 	pub(crate) fn today(context: &crate::Context) -> FResult<Self> {
25 		let Some(current_time_info) = &context.current_time else {
26 			return Err(FendError::UnableToGetCurrentDate);
27 		};
28 		let mut ms_since_epoch: i64 = current_time_info.elapsed_unix_time_ms.try_into().unwrap();
29 		ms_since_epoch -= current_time_info.timezone_offset_secs * 1000;
30 		let mut days = ms_since_epoch / 86_400_000; // no leap seconds
31 		let mut year = Year::new(1970);
32 		while days >= year.number_of_days().into() {
33 			year = year.next();
34 			days -= i64::from(year.number_of_days());
35 		}
36 		let mut month = Month::January;
37 		while days >= month.number_of_days(year).into() {
38 			month = month.next();
39 			days -= i64::from(month.number_of_days(year));
40 		}
41 		Ok(Self {
42 			year,
43 			month,
44 			day: Day::new(days.try_into().unwrap()),
45 		})
46 	}
47 
day_of_week(self) -> DayOfWeek48 	fn day_of_week(self) -> DayOfWeek {
49 		let d1 = (1
50 			+ 5 * ((self.year.value() - 1) % 4)
51 			+ 4 * ((self.year.value() - 1) % 100)
52 			+ 6 * ((self.year.value() - 1) % 400))
53 			% 7;
54 		let ms = match self.month {
55 			Month::January => (0, 0),
56 			Month::February => (3, 3),
57 			Month::March | Month::November => (3, 4),
58 			Month::April | Month::July => (6, 0),
59 			Month::May => (1, 2),
60 			Month::June => (4, 5),
61 			Month::August => (2, 3),
62 			Month::September | Month::December => (5, 6),
63 			Month::October => (0, 1),
64 		};
65 		let m = if self.year.is_leap_year() { ms.1 } else { ms.0 };
66 		match (d1 + m + i32::from(self.day.value() - 1)) % 7 {
67 			0 => DayOfWeek::Sunday,
68 			1 => DayOfWeek::Monday,
69 			2 => DayOfWeek::Tuesday,
70 			3 => DayOfWeek::Wednesday,
71 			4 => DayOfWeek::Thursday,
72 			5 => DayOfWeek::Friday,
73 			6 => DayOfWeek::Saturday,
74 			_ => unreachable!(),
75 		}
76 	}
77 
next(self) -> Self78 	pub(crate) fn next(self) -> Self {
79 		if self.day.value() < Month::number_of_days(self.month, self.year) {
80 			Self {
81 				day: Day::new(self.day.value() + 1),
82 				month: self.month,
83 				year: self.year,
84 			}
85 		} else if self.month == Month::December {
86 			Self {
87 				day: Day::new(1),
88 				month: Month::January,
89 				year: self.year.next(),
90 			}
91 		} else {
92 			Self {
93 				day: Day::new(1),
94 				month: self.month.next(),
95 				year: self.year,
96 			}
97 		}
98 	}
99 
prev(self) -> Self100 	pub(crate) fn prev(self) -> Self {
101 		if self.day.value() > 1 {
102 			Self {
103 				day: Day::new(self.day.value() - 1),
104 				month: self.month,
105 				year: self.year,
106 			}
107 		} else if self.month == Month::January {
108 			Self {
109 				day: Day::new(31),
110 				month: Month::December,
111 				year: self.year.prev(),
112 			}
113 		} else {
114 			let month = self.month.prev();
115 			Self {
116 				day: Day::new(Month::number_of_days(month, self.year)),
117 				month,
118 				year: self.year,
119 			}
120 		}
121 	}
122 
diff_months(self, mut months: i64) -> FResult<Self>123 	pub(crate) fn diff_months(self, mut months: i64) -> FResult<Self> {
124 		let mut result = self;
125 		while months >= 12 {
126 			result.year = result.year.next();
127 			months -= 12;
128 		}
129 		while months <= -12 {
130 			result.year = result.year.prev();
131 			months += 12;
132 		}
133 		while months > 0 {
134 			if result.month == Month::December {
135 				result.month = Month::January;
136 				result.year = result.year.next();
137 			} else {
138 				result.month = result.month.next();
139 			}
140 			months -= 1;
141 		}
142 		while months < 0 {
143 			if result.month == Month::January {
144 				result.month = Month::December;
145 				result.year = result.year.prev();
146 			} else {
147 				result.month = result.month.prev();
148 			}
149 			months += 1;
150 		}
151 		if result.day.value() > Month::number_of_days(result.month, result.year) {
152 			let mut before = result;
153 			before.day = Day::new(Month::number_of_days(before.month, before.year));
154 			let mut after = result;
155 			if after.month == Month::December {
156 				after.month = Month::January;
157 				after.year = after.year.next();
158 			} else {
159 				after.month = after.month.next();
160 			}
161 			after.day = Day::new(1);
162 			return Err(FendError::NonExistentDate {
163 				year: result.year.value(),
164 				month: result.month,
165 				expected_day: result.day.value(),
166 				before,
167 				after,
168 			});
169 		}
170 		Ok(result)
171 	}
172 
parse(s: &str) -> FResult<Self>173 	pub(crate) fn parse(s: &str) -> FResult<Self> {
174 		parser::parse_date(s)
175 	}
176 
serialize(self, write: &mut impl io::Write) -> FResult<()>177 	pub(crate) fn serialize(self, write: &mut impl io::Write) -> FResult<()> {
178 		self.year.serialize(write)?;
179 		self.month.serialize(write)?;
180 		self.day.serialize(write)?;
181 		Ok(())
182 	}
183 
deserialize(read: &mut impl io::Read) -> FResult<Self>184 	pub(crate) fn deserialize(read: &mut impl io::Read) -> FResult<Self> {
185 		Ok(Self {
186 			year: Year::deserialize(read)?,
187 			month: Month::deserialize(read)?,
188 			day: Day::deserialize(read)?,
189 		})
190 	}
191 
get_object_member(self, key: &Ident) -> FResult<crate::value::Value>192 	pub(crate) fn get_object_member(self, key: &Ident) -> FResult<crate::value::Value> {
193 		Ok(match key.as_str() {
194 			"month" => Value::Month(self.month),
195 			"day_of_week" => Value::DayOfWeek(self.day_of_week()),
196 			_ => return Err(FendError::CouldNotFindKey(key.to_string())),
197 		})
198 	}
199 
add<I: Interrupt>(self, rhs: Value, int: &I) -> FResult<Value>200 	pub(crate) fn add<I: Interrupt>(self, rhs: Value, int: &I) -> FResult<Value> {
201 		let rhs = rhs.expect_num()?;
202 		if rhs.unit_equal_to("day", int)? {
203 			let num_days = rhs.try_as_usize_unit(int)?;
204 			let mut result = self;
205 			for _ in 0..num_days {
206 				result = result.next();
207 			}
208 			Ok(Value::Date(result))
209 		} else {
210 			Err(FendError::ExpectedANumber)
211 		}
212 	}
213 
sub<I: Interrupt>(self, rhs: Value, int: &I) -> FResult<Value>214 	pub(crate) fn sub<I: Interrupt>(self, rhs: Value, int: &I) -> FResult<Value> {
215 		let rhs = rhs.expect_num()?;
216 
217 		if rhs.unit_equal_to("day", int)? {
218 			let num_days = rhs.try_as_usize_unit(int)?;
219 			let mut result = self;
220 			for _ in 0..num_days {
221 				result = result.prev();
222 			}
223 			Ok(Value::Date(result))
224 		} else if rhs.unit_equal_to("week", int)? {
225 			let num_weeks = rhs.try_as_usize_unit(int)?;
226 			let mut result = self;
227 			for _ in 0..num_weeks {
228 				for _ in 0..7 {
229 					result = result.prev();
230 				}
231 			}
232 			Ok(Value::Date(result))
233 		} else if rhs.unit_equal_to("month", int)? {
234 			let num_months = rhs.try_as_usize_unit(int)?;
235 			let result = self
236 				.diff_months(-i64::try_from(num_months).map_err(|_| FendError::ValueTooLarge)?)?;
237 			Ok(Value::Date(result))
238 		} else if rhs.unit_equal_to("year", int)? {
239 			let num_years = rhs.try_as_usize_unit(int)?;
240 			let num_months = num_years * 12;
241 			let result = self
242 				.diff_months(-i64::try_from(num_months).map_err(|_| FendError::ValueTooLarge)?)?;
243 			Ok(Value::Date(result))
244 		} else {
245 			Err(FendError::ExpectedANumber)
246 		}
247 	}
248 }
249 
250 impl fmt::Debug for Date {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result251 	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
252 		write!(
253 			f,
254 			"{}, {} {} {}",
255 			self.day_of_week(),
256 			self.day,
257 			self.month,
258 			self.year
259 		)
260 	}
261 }
262 
263 impl fmt::Display for Date {
fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result264 	fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
265 		write!(f, "{self:?}")
266 	}
267 }
268