tytanic_core/world_builder/
datetime.rs1use std::sync::Mutex;
2
3use chrono::DateTime;
4use chrono::Datelike;
5use chrono::FixedOffset;
6use chrono::Local;
7use chrono::Utc;
8use typst::foundations::Datetime;
9
10use super::ProvideDatetime;
11
12#[derive(Debug)]
14pub struct SystemDateProvider {
15 today: Mutex<Option<DateTime<Utc>>>,
16}
17
18impl SystemDateProvider {
19 pub fn reset(&self) {
21 *self.today.lock().unwrap() = None;
22 }
23}
24
25impl SystemDateProvider {
26 pub fn today(&self) -> DateTime<Utc> {
28 *self.today.lock().unwrap().get_or_insert_with(Utc::now)
29 }
30}
31
32impl SystemDateProvider {
33 pub fn today_with_offset(&self, offset: Option<i64>) -> Option<Datetime> {
35 with_offset(self.today(), offset)
36 }
37}
38
39impl ProvideDatetime for SystemDateProvider {
40 fn provide_today(&self, offset: Option<i64>) -> Option<Datetime> {
41 self.today_with_offset(offset)
42 }
43
44 fn reset_today(&self) {
45 self.reset();
46 }
47}
48
49#[derive(Debug)]
51pub struct FixedDateProvider {
52 date: DateTime<Utc>,
53}
54
55impl FixedDateProvider {
56 pub fn new(date: DateTime<Utc>) -> Self {
58 Self { date }
59 }
60}
61
62impl FixedDateProvider {
63 pub fn date(&self) -> DateTime<Utc> {
65 self.date
66 }
67}
68
69impl FixedDateProvider {
70 pub fn date_with_offset(&self, offset: Option<i64>) -> Option<Datetime> {
72 with_offset(self.date, offset)
73 }
74}
75
76fn with_offset(today: DateTime<Utc>, offset: Option<i64>) -> Option<Datetime> {
77 let with_offset = match offset {
79 Some(hours) => {
80 let seconds = i32::try_from(hours).ok()?.checked_mul(3600)?;
81 today.with_timezone(&FixedOffset::east_opt(seconds)?)
82 }
83 None => today.with_timezone(&Local).fixed_offset(),
84 };
85
86 Datetime::from_ymd(
87 with_offset.year(),
88 with_offset.month().try_into().ok()?,
89 with_offset.day().try_into().ok()?,
90 )
91}
92
93impl ProvideDatetime for FixedDateProvider {
94 fn provide_today(&self, offset: Option<i64>) -> Option<Datetime> {
95 self.date_with_offset(offset)
96 }
97
98 fn reset_today(&self) {}
99}