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]
87 pub fn seconds(&self) -> f64 {
88 self.0.as_seconds_f64()
89 }
90
91 #[func]
96 pub fn minutes(&self) -> f64 {
97 self.seconds() / 60.0
98 }
99
100 #[func]
105 pub fn hours(&self) -> f64 {
106 self.seconds() / 3_600.0
107 }
108
109 #[func]
114 pub fn days(&self) -> f64 {
115 self.seconds() / 86_400.0
116 }
117
118 #[func]
123 pub fn weeks(&self) -> f64 {
124 self.seconds() / 604_800.0
125 }
126}
127
128impl Debug for Duration {
129 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
130 self.0.fmt(f)
131 }
132}
133
134impl Repr for Duration {
135 fn repr(&self) -> EcoString {
136 let [weeks, days, hours, minutes, seconds] = self.decompose();
137 let mut vec = Vec::with_capacity(5);
138
139 if weeks != 0 {
140 vec.push(eco_format!("weeks: {}", weeks.repr()));
141 }
142
143 if days != 0 {
144 vec.push(eco_format!("days: {}", days.repr()));
145 }
146
147 if hours != 0 {
148 vec.push(eco_format!("hours: {}", hours.repr()));
149 }
150
151 if minutes != 0 {
152 vec.push(eco_format!("minutes: {}", minutes.repr()));
153 }
154
155 if seconds != 0 {
156 vec.push(eco_format!("seconds: {}", seconds.repr()));
157 }
158
159 eco_format!("duration{}", &repr::pretty_array_like(&vec, false))
160 }
161}
162
163impl From<time::Duration> for Duration {
164 fn from(value: time::Duration) -> Self {
165 Self(value)
166 }
167}
168
169impl From<Duration> for time::Duration {
170 fn from(value: Duration) -> Self {
171 value.0
172 }
173}
174
175impl Add for Duration {
176 type Output = Duration;
177
178 fn add(self, rhs: Self) -> Self::Output {
179 Duration(self.0 + rhs.0)
180 }
181}
182
183impl Sub for Duration {
184 type Output = Duration;
185
186 fn sub(self, rhs: Self) -> Self::Output {
187 Duration(self.0 - rhs.0)
188 }
189}
190
191impl Neg for Duration {
192 type Output = Duration;
193
194 fn neg(self) -> Self::Output {
195 Duration(-self.0)
196 }
197}
198
199impl Mul<f64> for Duration {
200 type Output = Duration;
201
202 fn mul(self, rhs: f64) -> Self::Output {
203 Duration(self.0 * rhs)
204 }
205}
206
207impl Div<f64> for Duration {
208 type Output = Duration;
209
210 fn div(self, rhs: f64) -> Self::Output {
211 Duration(self.0 / rhs)
212 }
213}
214
215impl Div for Duration {
216 type Output = f64;
217
218 fn div(self, rhs: Self) -> Self::Output {
219 self.0 / rhs.0
220 }
221}