typst_library/foundations/
duration.rs1use std::fmt::{self, Debug, Formatter};
2use std::ops::{Add, Div, Mul, Neg, Sub};
3
4use ecow::{eco_format, EcoString};
5use time::ext::NumericalDuration;
6
7use crate::foundations::{func, repr, scope, ty, Repr};
8
9#[ty(scope, cast)]
11#[derive(Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
12pub struct Duration(time::Duration);
13
14impl Duration {
15 pub fn is_zero(&self) -> bool {
17 self.0.is_zero()
18 }
19}
20
21#[scope]
22impl Duration {
23 #[func(constructor)]
36 pub fn construct(
37 #[named]
39 #[default(0)]
40 seconds: i64,
41 #[named]
43 #[default(0)]
44 minutes: i64,
45 #[named]
47 #[default(0)]
48 hours: i64,
49 #[named]
51 #[default(0)]
52 days: i64,
53 #[named]
55 #[default(0)]
56 weeks: i64,
57 ) -> Duration {
58 Duration::from(
59 time::Duration::seconds(seconds)
60 + time::Duration::minutes(minutes)
61 + time::Duration::hours(hours)
62 + time::Duration::days(days)
63 + time::Duration::weeks(weeks),
64 )
65 }
66
67 #[func]
72 pub fn seconds(&self) -> f64 {
73 self.0.as_seconds_f64()
74 }
75
76 #[func]
81 pub fn minutes(&self) -> f64 {
82 self.seconds() / 60.0
83 }
84
85 #[func]
90 pub fn hours(&self) -> f64 {
91 self.seconds() / 3_600.0
92 }
93
94 #[func]
99 pub fn days(&self) -> f64 {
100 self.seconds() / 86_400.0
101 }
102
103 #[func]
108 pub fn weeks(&self) -> f64 {
109 self.seconds() / 604_800.0
110 }
111}
112
113impl Debug for Duration {
114 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
115 self.0.fmt(f)
116 }
117}
118
119impl Repr for Duration {
120 fn repr(&self) -> EcoString {
121 let mut tmp = self.0;
122 let mut vec = Vec::with_capacity(5);
123
124 let weeks = tmp.whole_seconds() / 604_800.0 as i64;
125 if weeks != 0 {
126 vec.push(eco_format!("weeks: {}", weeks.repr()));
127 }
128 tmp -= weeks.weeks();
129
130 let days = tmp.whole_days();
131 if days != 0 {
132 vec.push(eco_format!("days: {}", days.repr()));
133 }
134 tmp -= days.days();
135
136 let hours = tmp.whole_hours();
137 if hours != 0 {
138 vec.push(eco_format!("hours: {}", hours.repr()));
139 }
140 tmp -= hours.hours();
141
142 let minutes = tmp.whole_minutes();
143 if minutes != 0 {
144 vec.push(eco_format!("minutes: {}", minutes.repr()));
145 }
146 tmp -= minutes.minutes();
147
148 let seconds = tmp.whole_seconds();
149 if seconds != 0 {
150 vec.push(eco_format!("seconds: {}", seconds.repr()));
151 }
152
153 eco_format!("duration{}", &repr::pretty_array_like(&vec, false))
154 }
155}
156
157impl From<time::Duration> for Duration {
158 fn from(value: time::Duration) -> Self {
159 Self(value)
160 }
161}
162
163impl From<Duration> for time::Duration {
164 fn from(value: Duration) -> Self {
165 value.0
166 }
167}
168
169impl Add for Duration {
170 type Output = Duration;
171
172 fn add(self, rhs: Self) -> Self::Output {
173 Duration(self.0 + rhs.0)
174 }
175}
176
177impl Sub for Duration {
178 type Output = Duration;
179
180 fn sub(self, rhs: Self) -> Self::Output {
181 Duration(self.0 - rhs.0)
182 }
183}
184
185impl Neg for Duration {
186 type Output = Duration;
187
188 fn neg(self) -> Self::Output {
189 Duration(-self.0)
190 }
191}
192
193impl Mul<f64> for Duration {
194 type Output = Duration;
195
196 fn mul(self, rhs: f64) -> Self::Output {
197 Duration(self.0 * rhs)
198 }
199}
200
201impl Div<f64> for Duration {
202 type Output = Duration;
203
204 fn div(self, rhs: f64) -> Self::Output {
205 Duration(self.0 / rhs)
206 }
207}
208
209impl Div for Duration {
210 type Output = f64;
211
212 fn div(self, rhs: Self) -> Self::Output {
213 self.0 / rhs.0
214 }
215}