Skip to main content

deep_time/dt/
to.rs

1use crate::{
2    ATTOS_PER_DAY, ATTOS_PER_FS_I128, ATTOS_PER_HOUR, ATTOS_PER_MIN, ATTOS_PER_MS_I128,
3    ATTOS_PER_NS_I128, ATTOS_PER_PS_I128, ATTOS_PER_SEC_I128, ATTOS_PER_SECF, ATTOS_PER_US_I128,
4    Dt, Real, dt,
5};
6
7impl Dt {
8    /// Returns the whole seconds portion of this [`Dt`] using truncation towards zero
9    /// (i.e., the integer part obtained via truncating division, without rounding).
10    ///
11    /// This is equivalent to `self.attos / ATTOS_PER_SEC_I128`.
12    ///
13    /// Unlike
14    /// [`to_sec_floor`](../struct.Dt.html#method.to_sec_floor)
15    /// (which uses Euclidean division, flooring towards
16    /// negative infinity for negative values to keep the fractional part non-negative),
17    /// this version truncates towards zero.
18    ///
19    /// Consequently, for values in `(-1, 0)` seconds (e.g. -0.3 s or -0.8 s),
20    /// both return `0`.
21    ///
22    /// ## Examples
23    ///
24    /// ```rust
25    /// use deep_time::{Dt, dt};
26    ///
27    /// // -0.3 seconds → truncates to 0
28    /// let dt = dt!(-300_000_000_000_000_000);
29    /// assert_eq!(dt.to_sec(), 0);
30    ///
31    /// // -0.8 seconds → truncates to 0
32    /// let dt = dt!(-800_000_000_000_000_000);
33    /// assert_eq!(dt.to_sec(), 0);
34    ///
35    /// // -1.3 seconds → truncates to -1 (while to_sec_floor gives -2)
36    /// let dt = dt!(-1_300_000_000_000_000_000);
37    /// assert_eq!(dt.to_sec(), -1);
38    /// assert_eq!(dt.to_sec_floor(), -2);
39    ///
40    /// // Positive values behave the same as `to_sec_floor`
41    /// let dt = dt!(1_300_000_000_000_000_000);
42    /// assert_eq!(dt.to_sec(), 1);
43    /// assert_eq!(dt.to_sec_floor(), 1);
44    /// ```
45    #[inline(always)]
46    pub const fn to_sec(&self) -> i128 {
47        self.attos / ATTOS_PER_SEC_I128
48    }
49
50    /// Returns the whole seconds portion of this [`Dt`] using truncation towards zero,
51    /// then clamped to an [`i64`].
52    ///
53    /// If the truncated seconds value lies outside the `i64` range, the result
54    /// saturates to [`i64::MAX`] or [`i64::MIN`].
55    ///
56    /// See
57    /// [`to_sec`](../struct.Dt.html#method.to_sec)
58    /// for the truncation semantics
59    /// (towards zero, no rounding).
60    ///
61    /// ## Examples
62    ///
63    /// ```rust
64    /// use deep_time::{Dt, dt};
65    ///
66    /// let dt = dt!(-1_300_000_000_000_000_000);
67    /// assert_eq!(dt.to_sec64(), -1);
68    ///
69    /// let dt = dt!(1_300_000_000_000_000_000);
70    /// assert_eq!(dt.to_sec64_floor(), 1);
71    /// ```
72    #[inline(always)]
73    pub const fn to_sec64(&self) -> i64 {
74        Self::to_i64(self.attos / ATTOS_PER_SEC_I128)
75    }
76
77    /// If this time were turned into [`i128`] seconds and [`u64`] (always
78    /// pushing to the positive) fractional attoseconds, this returns the
79    /// whole seconds part.
80    ///
81    /// To just get seconds rounded to the nearest second use
82    /// [`Dt::to_sec_round`](../struct.Dt.html#method.to_sec_round)
83    /// instead.
84    ///
85    /// ## Examples
86    ///
87    /// ```rust
88    /// use deep_time::{Dt, Scale, dt};
89    ///
90    /// // negative 1.3 seconds
91    /// let dt = dt!(-1_300_000_000_000_000_000);
92    ///
93    /// // becomes positive 700ms
94    /// let frac = dt.to_sec_ufrac();
95    /// assert_eq!(frac, 700_000_000_000_000_000);
96    ///
97    /// // becomes negative 2 seconds
98    /// let sec = dt.to_sec_floor();
99    /// assert_eq!(sec, -2);
100    ///
101    /// let dt = dt!(1_300_000_000_000_000_000);
102    ///
103    /// assert_eq!(dt.to_sec_floor(), 1);
104    /// assert_eq!(dt.to_sec_ufrac(), 300_000_000_000_000_000);
105    ///
106    /// // if you just want rounded seconds
107    /// // use to_sec_round() instead
108    /// let dt = dt!(-1_300_000_000_000_000_000);
109    /// let sec = dt.to_sec_round();
110    /// assert_eq!(sec, -1);
111    /// ```
112    #[inline(always)]
113    pub const fn to_sec_floor(&self) -> i128 {
114        self.attos.div_euclid(ATTOS_PER_SEC_I128)
115    }
116
117    /// If this time were turned into [`i64`] seconds and [`u64`] (always
118    /// pushing to the positive) fractional attoseconds, this returns the
119    /// whole seconds part.
120    ///
121    /// To just get seconds rounded to the nearest second use
122    /// [`Dt::to_sec_round`](../struct.Dt.html#method.to_sec_round)
123    /// instead.
124    ///
125    /// ## Examples
126    ///
127    /// ```rust
128    /// use deep_time::{Dt, Scale, dt};
129    ///
130    /// // negative 1.3 seconds
131    /// let dt = dt!(-1_300_000_000_000_000_000);
132    ///
133    /// // becomes positive 700ms
134    /// let frac = dt.to_sec_ufrac();
135    /// assert_eq!(frac, 700_000_000_000_000_000);
136    ///
137    /// // becomes negative 2 seconds
138    /// let sec = dt.to_sec64_floor();
139    /// assert_eq!(sec, -2);
140    ///
141    /// let dt = dt!(1_300_000_000_000_000_000);
142    ///
143    /// assert_eq!(dt.to_sec64_floor(), 1);
144    /// assert_eq!(dt.to_sec_ufrac(), 300_000_000_000_000_000);
145    ///
146    /// // if you just want rounded seconds
147    /// // use to_sec_round() instead
148    /// let dt = dt!(-1_300_000_000_000_000_000);
149    /// let sec = dt.to_sec_round();
150    /// assert_eq!(sec, -1);
151    /// ```
152    #[inline(always)]
153    pub const fn to_sec64_floor(&self) -> i64 {
154        Self::to_i64(self.attos.div_euclid(ATTOS_PER_SEC_I128))
155    }
156
157    /// Returns this [`Dt`] rounded to the nearest whole second, then
158    /// converted to an [`i128`] number of seconds.
159    ///
160    /// - Exactly halfway cases (e.g. 0.5 s, -0.5 s) round as follows:
161    ///   0.5 becomes 1 and -0.5 becomes -1.
162    /// - Matches the behavior of [`Dt::round`].
163    ///
164    /// ## Examples
165    ///
166    /// ```rust
167    /// use deep_time::{Dt, dt};
168    ///
169    /// // 1.3 seconds → rounds to 1
170    /// assert_eq!(dt!(1_300_000_000_000_000_000).to_sec_round(), 1);
171    ///
172    /// // -1.3 seconds → rounds to -1
173    /// assert_eq!(dt!(-1_300_000_000_000_000_000).to_sec_round(), -1);
174    ///
175    /// // 1.6 seconds → rounds to 2
176    /// assert_eq!(dt!(1_600_000_000_000_000_000).to_sec_round(), 2);
177    ///
178    /// // Halfway cases
179    /// assert_eq!(dt!(500_000_000_000_000_000).to_sec_round(), 1);
180    /// assert_eq!(dt!(-500_000_000_000_000_000).to_sec_round(), -1);
181    /// ```
182    #[inline(always)]
183    pub const fn to_sec_round(&self) -> i128 {
184        self.round_to_sec().to_sec()
185    }
186
187    /// Returns this [`Dt`] rounded to the nearest whole second, then
188    /// converted to an [`i64`] number of seconds.
189    ///
190    /// - Exactly halfway cases round as follows: 0.5 becomes 1 and -0.5 becomes -1,
191    ///   same as
192    ///   [`to_sec_round`](../struct.Dt.html#method.to_sec_round).
193    /// - If the rounded value is outside the representable `i64` range,
194    ///   it saturates to [`i64::MAX`] or [`i64::MIN`].
195    ///
196    /// ## Examples
197    ///
198    /// ```rust
199    /// use deep_time::{Dt, dt};
200    ///
201    /// let dt = dt!(1_300_000_000_000_000_000);
202    /// assert_eq!(dt.to_sec64_round(), 1);
203    ///
204    /// let dt = dt!(-1_300_000_000_000_000_000);
205    /// assert_eq!(dt.to_sec64_round(), -1);
206    /// ```
207    #[inline(always)]
208    pub const fn to_sec64_round(&self) -> i64 {
209        Self::to_i64(self.round_to_sec().to_sec())
210    }
211
212    /// Converts this [`Dt`] to an f64 number of seconds.
213    #[inline(always)]
214    pub const fn to_f64(&self) -> f64 {
215        self.to_sec_f()
216    }
217
218    /// Converts this [`Dt`] to a float number of seconds.
219    pub const fn to_sec_f(&self) -> Real {
220        if self.attos == 0 {
221            return 0.0;
222        }
223        let sec = self.attos.div_euclid(ATTOS_PER_SEC_I128);
224        let rem = self.attos.rem_euclid(ATTOS_PER_SEC_I128); // always in [0, aps)
225
226        if sec < 0 && rem > ATTOS_PER_SEC_I128 / 2 {
227            // original cancellation-avoidance path
228            let small = ATTOS_PER_SEC_I128 - rem;
229            let small_f = f!(small as u64) / ATTOS_PER_SECF;
230            f!(sec) + 1.0 - small_f
231        } else {
232            f!(sec) + f!(rem as u64) / ATTOS_PER_SECF
233        }
234    }
235
236    /// If this time were turned into seconds, this returns the signed fractional
237    /// attoseconds part — the amount left over after removing whole seconds, with the
238    /// same sign as the original value when non-zero.
239    ///
240    /// Pairs with [`from_sec_and_frac`](../struct.Dt.html#method.from_sec_and_frac).
241    #[inline(always)]
242    pub const fn to_sec_frac(&self) -> i64 {
243        (self.attos % ATTOS_PER_SEC_I128) as i64
244    }
245
246    /// If this time were turned into i64 seconds and u64 (always pushing to the positive)
247    /// fractional attoseconds, this returns the fractional attoseconds part.
248    ///
249    /// - Always returns a value in the range `0 ≤ x < ATTOS_PER_SEC`.
250    /// - For negative [`Dt`]s this is **not** simply the decimal part of the time in seconds.
251    ///
252    /// ## Examples
253    ///
254    /// ```rust
255    /// use deep_time::{Dt, Scale, dt};
256    ///
257    /// // negative 1.3 seconds
258    /// let dt = dt!(-1_300_000_000_000_000_000);
259    ///
260    /// // becomes positive 700ms
261    /// let frac = dt.to_sec_ufrac();
262    /// assert_eq!(frac, 700_000_000_000_000_000);
263    ///
264    /// // becomes -2 seconds
265    /// let sec = dt.to_sec64_floor();
266    /// assert_eq!(sec, -2);
267    ///
268    /// let dt = dt!(1_300_000_000_000_000_000);
269    ///
270    /// assert_eq!(dt.to_sec64_floor(), 1);
271    /// assert_eq!(dt.to_sec_ufrac(), 300_000_000_000_000_000);
272    /// ```
273    #[inline(always)]
274    pub const fn to_sec_ufrac(&self) -> u64 {
275        self.attos.rem_euclid(ATTOS_PER_SEC_I128) as u64
276    }
277
278    /// Returns a new [`Dt`] rounded to the nearest second.
279    #[inline(always)]
280    pub const fn round_to_sec(&self) -> Dt {
281        self.round(dt!(ATTOS_PER_SEC_I128))
282    }
283
284    /// Returns the total time in attoseconds.
285    #[inline(always)]
286    pub const fn to_attos(&self) -> i128 {
287        self.attos
288    }
289
290    /// Converts this [`Dt`] into whole femtoseconds and a fractional part within one femtosecond.
291    ///
292    /// - Returns `(whole, frac_attos)` where `frac_attos` is always non-negative.
293    /// - For negative values this does **not** split at the decimal point — see
294    ///   [`to_sec64_floor`](../struct.Dt.html#method.to_sec64_floor) and
295    ///   [`to_sec_ufrac`](../struct.Dt.html#method.to_sec_ufrac).
296    /// - For truncation toward zero, use [`to_fs`](../struct.Dt.html#method.to_fs).
297    #[inline(always)]
298    pub const fn to_fs_floor(&self) -> (i128, i128) {
299        (
300            self.attos.div_euclid(ATTOS_PER_FS_I128),
301            self.attos.rem_euclid(ATTOS_PER_FS_I128),
302        )
303    }
304
305    /// Converts this [`Dt`] into whole picoseconds and a fractional part within one picosecond.
306    ///
307    /// - Returns `(whole, frac_attos)` where `frac_attos` is always non-negative.
308    /// - For negative values this does **not** split at the decimal point — see
309    ///   [`to_sec64_floor`](../struct.Dt.html#method.to_sec64_floor) and
310    ///   [`to_sec_ufrac`](../struct.Dt.html#method.to_sec_ufrac).
311    /// - For truncation toward zero, use [`to_ps`](../struct.Dt.html#method.to_ps).
312    #[inline(always)]
313    pub const fn to_ps_floor(&self) -> (i128, i128) {
314        (
315            self.attos.div_euclid(ATTOS_PER_PS_I128),
316            self.attos.rem_euclid(ATTOS_PER_PS_I128),
317        )
318    }
319
320    /// Converts this [`Dt`] into whole nanoseconds and a fractional part within one nanosecond.
321    ///
322    /// - Returns `(whole, frac_attos)` where `frac_attos` is always non-negative.
323    /// - For negative values this does **not** split at the decimal point — see
324    ///   [`to_sec64_floor`](../struct.Dt.html#method.to_sec64_floor) and
325    ///   [`to_sec_ufrac`](../struct.Dt.html#method.to_sec_ufrac).
326    /// - For truncation toward zero, use [`to_ns`](../struct.Dt.html#method.to_ns).
327    #[inline(always)]
328    pub const fn to_ns_floor(&self) -> (i128, i128) {
329        (
330            self.attos.div_euclid(ATTOS_PER_NS_I128),
331            self.attos.rem_euclid(ATTOS_PER_NS_I128),
332        )
333    }
334
335    /// Converts this [`Dt`] into whole microseconds and a fractional part within one microsecond.
336    ///
337    /// - Returns `(whole, frac_attos)` where `frac_attos` is always non-negative.
338    /// - For negative values this does **not** split at the decimal point — see
339    ///   [`to_sec64_floor`](../struct.Dt.html#method.to_sec64_floor) and
340    ///   [`to_sec_ufrac`](../struct.Dt.html#method.to_sec_ufrac).
341    /// - For truncation toward zero, use [`to_us`](../struct.Dt.html#method.to_us).
342    #[inline(always)]
343    pub const fn to_us_floor(&self) -> (i128, i128) {
344        (
345            self.attos.div_euclid(ATTOS_PER_US_I128),
346            self.attos.rem_euclid(ATTOS_PER_US_I128),
347        )
348    }
349
350    /// Converts this [`Dt`] into whole milliseconds and a fractional part within one millisecond.
351    ///
352    /// - Returns `(whole, frac_attos)` where `frac_attos` is always non-negative.
353    /// - For negative values this does **not** split at the decimal point — see
354    ///   [`to_sec64_floor`](../struct.Dt.html#method.to_sec64_floor) and
355    ///   [`to_sec_ufrac`](../struct.Dt.html#method.to_sec_ufrac).
356    /// - For truncation toward zero, use [`to_ms`](../struct.Dt.html#method.to_ms).
357    #[inline(always)]
358    pub const fn to_ms_floor(&self) -> (i128, i128) {
359        (
360            self.attos.div_euclid(ATTOS_PER_MS_I128),
361            self.attos.rem_euclid(ATTOS_PER_MS_I128),
362        )
363    }
364
365    /// Converts this [`Dt`] into whole minutes and a fractional part within one minute.
366    ///
367    /// - Returns `(whole, frac_attos)` where `frac_attos` is always non-negative.
368    /// - For negative values this does **not** split at the decimal point — see
369    ///   [`to_sec64_floor`](../struct.Dt.html#method.to_sec64_floor) and
370    ///   [`to_sec_ufrac`](../struct.Dt.html#method.to_sec_ufrac).
371    #[inline(always)]
372    pub const fn to_mins_floor(&self) -> (i128, i128) {
373        (
374            self.attos.div_euclid(ATTOS_PER_MIN),
375            self.attos.rem_euclid(ATTOS_PER_MIN),
376        )
377    }
378
379    /// Converts this [`Dt`] to a float number of minutes.
380    ///
381    /// ## Examples
382    ///
383    /// ```rust
384    /// use deep_time::{Dt, from_sec};
385    ///
386    /// assert_eq!(Dt::ZERO.to_mins_f(), 0.0);
387    ///
388    /// let dt = from_sec!(90);
389    /// assert_eq!(dt.to_mins_f(), 1.5);
390    ///
391    /// let dt = from_sec!(-90);
392    /// assert_eq!(dt.to_mins_f(), -1.5);
393    /// ```
394    pub const fn to_mins_f(&self) -> Real {
395        if self.attos == 0 {
396            return 0.0;
397        }
398        let mins = self.attos.div_euclid(ATTOS_PER_MIN);
399        let rem = self.attos.rem_euclid(ATTOS_PER_MIN);
400
401        if mins < 0 && rem > ATTOS_PER_MIN / 2 {
402            let small = ATTOS_PER_MIN - rem;
403            let small_f = f!(small as u128) / f!(ATTOS_PER_MIN);
404            f!(mins) + 1.0 - small_f
405        } else {
406            f!(mins) + f!(rem as u128) / f!(ATTOS_PER_MIN)
407        }
408    }
409
410    /// Converts this [`Dt`] into whole hours and a fractional part within one hour.
411    ///
412    /// - Returns `(whole, frac_attos)` where `frac_attos` is always non-negative.
413    /// - For negative values this does **not** split at the decimal point — see
414    ///   [`to_sec64_floor`](../struct.Dt.html#method.to_sec64_floor) and
415    ///   [`to_sec_ufrac`](../struct.Dt.html#method.to_sec_ufrac).
416    #[inline(always)]
417    pub const fn to_hours_floor(&self) -> (i128, i128) {
418        (
419            self.attos.div_euclid(ATTOS_PER_HOUR),
420            self.attos.rem_euclid(ATTOS_PER_HOUR),
421        )
422    }
423
424    /// Converts this [`Dt`] to a float number of hours.
425    ///
426    /// ## Examples
427    ///
428    /// ```rust
429    /// use deep_time::{Dt, dt, consts::ATTOS_PER_SEC_I128};
430    ///
431    /// assert_eq!(Dt::ZERO.to_hours_f(), 0.0);
432    ///
433    /// let dt = Dt::from_str_iso("2000-01-01 10:30:00 TAI").unwrap();
434    /// assert_eq!(dt.to_hours_f(), -1.5);
435    /// ```
436    pub const fn to_hours_f(&self) -> Real {
437        if self.attos == 0 {
438            return 0.0;
439        }
440        let hours = self.attos.div_euclid(ATTOS_PER_HOUR);
441        let rem = self.attos.rem_euclid(ATTOS_PER_HOUR);
442
443        if hours < 0 && rem > ATTOS_PER_HOUR / 2 {
444            let small = ATTOS_PER_HOUR - rem;
445            let small_f = f!(small as u128) / f!(ATTOS_PER_HOUR);
446            f!(hours) + 1.0 - small_f
447        } else {
448            f!(hours) + f!(rem as u128) / f!(ATTOS_PER_HOUR)
449        }
450    }
451
452    /// Converts this [`Dt`] into whole days and a fractional part within one day,
453    /// truncating toward zero.
454    ///
455    /// Returns `(whole, frac_attos)`. When the value is negative and has a fractional
456    /// part, `frac_attos` is negative too — e.g. `-1.25` days is
457    /// `(-1, -ATTOS_PER_DAY / 4)`.
458    ///
459    /// For a non-negative fractional part, use [`to_days_floor`](#method.to_days_floor).
460    ///
461    /// ## Examples
462    ///
463    /// ```rust
464    /// use deep_time::{Dt, Scale, consts::ATTOS_PER_DAY};
465    ///
466    /// let dt = Dt::from_days_f(1.25, Scale::TAI, Scale::TAI);
467    /// assert_eq!(dt.to_days(), (1, ATTOS_PER_DAY / 4));
468    ///
469    /// let dt = Dt::from_days_f(-1.25, Scale::TAI, Scale::TAI);
470    /// assert_eq!(dt.to_days(), (-1, -ATTOS_PER_DAY / 4));
471    /// ```
472    ///
473    /// ## See also
474    ///
475    /// - [`Dt::to_days_floor`](#method.to_days_floor)
476    /// - [`Dt::from_days`](../struct.Dt.html#method.from_days)
477    #[inline(always)]
478    pub const fn to_days(&self) -> (i128, i128) {
479        (self.attos / ATTOS_PER_DAY, self.attos % ATTOS_PER_DAY)
480    }
481
482    /// Converts this [`Dt`] into whole days and a fractional part within one day.
483    ///
484    /// - Returns `(whole, frac_attos)` where `frac_attos` is always non-negative.
485    /// - For negative values this does **not** split at the decimal point — see
486    ///   [`to_sec64_floor`](../struct.Dt.html#method.to_sec64_floor) and
487    ///   [`to_sec_ufrac`](../struct.Dt.html#method.to_sec_ufrac).
488    ///
489    /// ## Examples
490    ///
491    /// ```rust
492    /// use deep_time::{Dt, Scale, dt};
493    /// use deep_time::consts::ATTOS_PER_HALF_DAY;
494    ///
495    /// // library epoch is 2000-01-01 12:00:00 TAI
496    /// // so result will be negative 2 + half a day
497    /// // effectively -1.5 days
498    /// let dt = Dt::from_ymd(1999, 12, 31, Scale::TAI, 0, 0, 0, 0);
499    /// let (days, attos) = dt.to_days_floor();
500    /// assert_eq!(days, -2);
501    /// assert_eq!(attos, ATTOS_PER_HALF_DAY);
502    /// ```
503    ///
504    /// ## See also
505    ///
506    /// - [`Dt::to_days`](#method.to_days)
507    #[inline(always)]
508    pub const fn to_days_floor(&self) -> (i128, i128) {
509        (
510            self.attos.div_euclid(ATTOS_PER_DAY),
511            self.attos.rem_euclid(ATTOS_PER_DAY),
512        )
513    }
514
515    /// Converts this [`Dt`] to a float number of days.
516    ///
517    /// ## Examples
518    ///
519    /// ```rust
520    /// use deep_time::{Dt, Scale, consts::ATTOS_PER_HALF_DAY_U128};
521    ///
522    /// assert_eq!(Dt::ZERO.to_days_f(), 0.0);
523    ///
524    /// // library epoch is 2000-01-01 12:00:00 TAI
525    /// // so -1.5 days
526    /// let dt = Dt::from_ymd(1999, 12, 31, Scale::TAI, 0, 0, 0, 0);
527    /// assert_eq!(dt.to_days_f(), -1.5);
528    /// ```
529    ///
530    /// ## See also
531    ///
532    /// - [`Dt::from_days_f`](../struct.Dt.html#method.from_days_f)
533    pub const fn to_days_f(&self) -> Real {
534        if self.attos == 0 {
535            return 0.0;
536        }
537        let days = self.attos.div_euclid(ATTOS_PER_DAY);
538        let rem = self.attos.rem_euclid(ATTOS_PER_DAY);
539
540        if days < 0 && rem > ATTOS_PER_DAY / 2 {
541            let small = ATTOS_PER_DAY - rem;
542            let small_f = f!(small as u128) / f!(ATTOS_PER_DAY);
543            f!(days) + 1.0 - small_f
544        } else {
545            f!(days) + f!(rem as u128) / f!(ATTOS_PER_DAY)
546        }
547    }
548
549    /// Converts this [`Dt`] into whole milliseconds and a fractional part within one millisecond,
550    /// truncating toward zero.
551    ///
552    /// Returns `(whole, frac_attos)`. `frac_attos` will be negative when `whole` is negative and
553    /// there is a non-zero fraction. See
554    /// [`to_sec`](../struct.Dt.html#method.to_sec)
555    /// for the same rule in seconds.
556    #[inline(always)]
557    pub const fn to_ms(&self) -> (i128, i128) {
558        (
559            self.attos / ATTOS_PER_MS_I128,
560            self.attos % ATTOS_PER_MS_I128,
561        )
562    }
563
564    /// Converts this [`Dt`] into whole microseconds and a fractional part within one microsecond,
565    /// truncating toward zero.
566    ///
567    /// Returns `(whole, frac_attos)`. `frac_attos` will be negative when `whole` is negative and
568    /// there is a non-zero fraction. See
569    /// [`to_sec`](../struct.Dt.html#method.to_sec)
570    /// for the same rule in seconds.
571    #[inline(always)]
572    pub const fn to_us(&self) -> (i128, i128) {
573        (
574            self.attos / ATTOS_PER_US_I128,
575            self.attos % ATTOS_PER_US_I128,
576        )
577    }
578
579    /// Converts this [`Dt`] into whole nanoseconds and a fractional part within one nanosecond,
580    /// truncating toward zero.
581    ///
582    /// Returns `(whole, frac_attos)`. `frac_attos` will be negative when `whole` is negative and
583    /// there is a non-zero fraction. See
584    /// [`to_sec`](../struct.Dt.html#method.to_sec)
585    /// for the same rule in seconds.
586    #[inline(always)]
587    pub const fn to_ns(&self) -> (i128, i128) {
588        (
589            self.attos / ATTOS_PER_NS_I128,
590            self.attos % ATTOS_PER_NS_I128,
591        )
592    }
593
594    /// Converts this [`Dt`] into whole picoseconds and a fractional part within one picosecond,
595    /// truncating toward zero.
596    ///
597    /// Returns `(whole, frac_attos)`. `frac_attos` will be negative when `whole` is negative and
598    /// there is a non-zero fraction. See
599    /// [`to_sec`](../struct.Dt.html#method.to_sec)
600    /// for the same rule in seconds.
601    #[inline(always)]
602    pub const fn to_ps(&self) -> (i128, i128) {
603        (
604            self.attos / ATTOS_PER_PS_I128,
605            self.attos % ATTOS_PER_PS_I128,
606        )
607    }
608
609    /// Converts this [`Dt`] into whole femtoseconds and a fractional part within one femtosecond,
610    /// truncating toward zero.
611    ///
612    /// Returns `(whole, frac_attos)`. `frac_attos` will be negative when `whole` is negative and
613    /// there is a non-zero fraction. See
614    /// [`to_sec`](../struct.Dt.html#method.to_sec)
615    /// for the same rule in seconds.
616    #[inline(always)]
617    pub const fn to_fs(&self) -> (i128, i128) {
618        (
619            self.attos / ATTOS_PER_FS_I128,
620            self.attos % ATTOS_PER_FS_I128,
621        )
622    }
623}