typst_library/foundations/
duration.rs1use std::fmt::{self, Debug, Formatter};
2use std::ops::{Add, Div, Mul, Neg, Sub};
3
4use ecow::{EcoString, eco_format};
5use time::ext::NumericalDuration;
6
7use crate::foundations::{Repr, func, repr, scope, ty};
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 pub fn decompose(&self) -> [i64; 5] {
22 let mut tmp = self.0;
23 let weeks = tmp.whole_weeks();
24 tmp -= weeks.weeks();
25 let days = tmp.whole_days();
26 tmp -= days.days();
27 let hours = tmp.whole_hours();
28 tmp -= hours.hours();
29 let minutes = tmp.whole_minutes();
30 tmp -= minutes.minutes();
31 let seconds = tmp.whole_seconds();
32 [weeks, days, hours, minutes, seconds]
33 }
34}
35
36#[scope]
37impl Duration {
38 #[func(constructor)]
51 pub fn construct(
52 #[named]
54 #[default(0)]
55 seconds: i64,
56 #[named]
58 #[default(0)]
59 minutes: i64,
60 #[named]
62 #[default(0)]
63 hours: i64,
64 #[named]
66 #[default(0)]
67 days: i64,
68 #[named]
70 #[default(0)]
71 weeks: i64,
72 ) -> Duration {
73 Duration::from(
74 time::Duration::seconds(seconds)
75 + time::Duration::minutes(minutes)
76 + time::Duration::hours(hours)
77 + time::Duration::days(days)
78 + time::Duration::weeks(weeks),
79 )
80 }
81
82 #[func]
88 pub fn seconds(&self) -> f64 {
89 self.0.as_seconds_f64()
90 }
91
92 #[func]
98 pub fn minutes(&self) -> f64 {
99 self.seconds() / 60.0
100 }
101
102 #[func]
107 pub fn hours(&self) -> f64 {
108 self.seconds() / 3_600.0
109 }
110
111 #[func]
116 pub fn days(&self) -> f64 {
117 self.seconds() / 86_400.0
118 }
119
120 #[func]
125 pub fn weeks(&self) -> f64 {
126 self.seconds() / 604_800.0
127 }
128}
129
130impl Debug for Duration {
131 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
132 self.0.fmt(f)
133 }
134}
135
136impl Repr for Duration {
137 fn repr(&self) -> EcoString {
138 let [weeks, days, hours, minutes, seconds] = self.decompose();
139 let mut vec = Vec::with_capacity(5);
140
141 if weeks != 0 {
142 vec.push(eco_format!("weeks: {}", weeks.repr()));
143 }
144
145 if days != 0 {
146 vec.push(eco_format!("days: {}", days.repr()));
147 }
148
149 if hours != 0 {
150 vec.push(eco_format!("hours: {}", hours.repr()));
151 }
152
153 if minutes != 0 {
154 vec.push(eco_format!("minutes: {}", minutes.repr()));
155 }
156
157 if seconds != 0 {
158 vec.push(eco_format!("seconds: {}", seconds.repr()));
159 }
160
161 eco_format!("duration{}", &repr::pretty_array_like(&vec, false))
162 }
163}
164
165impl From<time::Duration> for Duration {
166 fn from(value: time::Duration) -> Self {
167 Self(value)
168 }
169}
170
171impl From<Duration> for time::Duration {
172 fn from(value: Duration) -> Self {
173 value.0
174 }
175}
176
177impl Add for Duration {
178 type Output = Duration;
179
180 fn add(self, rhs: Self) -> Self::Output {
181 Duration(self.0 + rhs.0)
182 }
183}
184
185impl Sub for Duration {
186 type Output = Duration;
187
188 fn sub(self, rhs: Self) -> Self::Output {
189 Duration(self.0 - rhs.0)
190 }
191}
192
193impl Neg for Duration {
194 type Output = Duration;
195
196 fn neg(self) -> Self::Output {
197 Duration(-self.0)
198 }
199}
200
201impl Mul<f64> for Duration {
202 type Output = Duration;
203
204 fn mul(self, rhs: f64) -> Self::Output {
205 Duration(self.0 * rhs)
206 }
207}
208
209impl Div<f64> for Duration {
210 type Output = Duration;
211
212 fn div(self, rhs: f64) -> Self::Output {
213 Duration(self.0 / rhs)
214 }
215}
216
217impl Div for Duration {
218 type Output = f64;
219
220 fn div(self, rhs: Self) -> Self::Output {
221 self.0 / rhs.0
222 }
223}