deep_time/macros.rs
1//! Macros for easy unit conversion and
2//! [`Dt`](../struct.Dt.html) construction.
3//!
4//! Each macro expands to a call on an equivalent [`Dt`](../struct.Dt.html)
5//! method.
6//!
7//! ## Overview
8//!
9//! ### Unit → attoseconds
10//!
11//! Returns total attoseconds as `i128`.
12//!
13//! - [`fs!`]
14//! - [`ps!`]
15//! - [`ns!`]
16//! - [`us!`]
17//! - [`ms!`]
18//! - [`sec!`]
19//! - [`sec_f!`]
20//! - [`mins!`]
21//! - [`hours!`]
22//! - [`days!`]
23//! - [`days_f!`]
24//! - [`weeks!`]
25//!
26//! ### Attoseconds → unit
27//!
28//! Returns a whole-unit count as `i128`, or a lossy
29//! [`Real`](../type.Real.html) for the `_f` forms.
30//!
31//! - [`as_fs!`]
32//! - [`as_ps!`]
33//! - [`as_ns!`]
34//! - [`as_us!`]
35//! - [`as_ms!`]
36//! - [`as_sec!`]
37//! - [`as_sec_f!`]
38//! - [`as_mins!`]
39//! - [`as_hours!`]
40//! - [`as_days!`]
41//! - [`as_days_f!`]
42//! - [`as_weeks!`]
43//!
44//! ### Instant / duration
45//!
46//! Returns a [`Dt`](../struct.Dt.html).
47//!
48//! - [`dt!`]
49//! - [`from_sec!`]
50//! - [`from_sec_f!`]
51//! - [`from_ms!`]
52//! - [`from_us!`]
53//! - [`from_ns!`]
54//! - [`from_ps!`]
55//! - [`from_fs!`]
56//! - [`from_days_f!`]
57//! - [`from_ymd!`]
58//! - [`from_jd!`]
59//! - [`from_jd_f!`]
60//! - [`from_mjd!`]
61//! - [`from_mjd_f!`]
62//!
63//! ## Import paths
64//!
65//! Prefer importing macros from this module:
66//!
67//! ```
68//! use deep_time::macros::{from_ns, ms, sec};
69//! ```
70//!
71//! `use deep_time::macros::*` brings in every macro listed above.
72//! Prefer explicit imports to avoid short-name clashes.
73//!
74//! ## How they work
75//!
76//! - **Attosecond storage unit.** Forward converters such as [`ms!`] and
77//! [`sec!`] return total attoseconds as `i128`. Reverse converters such as
78//! [`as_ms!`] and [`as_sec!`] take total attoseconds and return a count in
79//! the named unit.
80//! - **Truncation toward zero.** Integer reverse converters use ordinary
81//! `i128` division (`attos / unit`). Any leftover below one whole unit is
82//! dropped, and the result moves toward zero—not toward −∞. For example,
83//! −0.5 s as whole seconds is `0`, and −1.5 s is `-1`. The floating reverse
84//! converters ([`as_sec_f!`], [`as_days_f!`]) are lossy
85//! [`Real`](crate::Real) casts instead.
86//! - **Signed remainders on constructors.** Macros such as [`from_sec!`] and
87//! [`from_ns!`] accept an optional fractional remainder in **attoseconds**.
88//! Both signs of the remainder are valid; the total is
89//! `whole × unit + frac` (with saturating arithmetic on the underlying
90//! method). The same total can often be written with a signed remainder or
91//! as a floor-style split with a non-negative remainder.
92//! - **Scale labels vs conversion.** Most `from_*` macros only set the
93//! returned [`Dt`](../struct.Dt.html)'s `scale` / `target` fields; they do
94//! **not** convert the attosecond count between time scales. [`from_ymd!`],
95//! [`from_jd!`], [`from_jd_f!`], [`from_mjd!`], and [`from_mjd_f!`] are the
96//! exceptions: they build a [`Dt`](../struct.Dt.html) on TAI (converting
97//! from the `on=` scale when needed) and set `target` from `on=`, as
98//! documented on each macro.
99//! - **`const` contexts.** Expansions call `const` methods on
100//! [`Dt`](../struct.Dt.html), so these macros work in `const` contexts where
101//! the underlying method does.
102//!
103//! ## Examples
104//!
105//! ```
106//! use deep_time::{Dt, Scale};
107//! use deep_time::macros::{as_sec, dt, from_sec, from_ymd, ms, ns, sec};
108//!
109//! // Unit helpers avoid hand-counting zeros in attosecond literals.
110//! assert_eq!(ms!(300), Dt::ms_to_attos(300));
111//! assert_eq!(ns!(1), 1_000_000_000);
112//!
113//! // Whole seconds + sub-second remainder (remainder is attoseconds).
114//! let a = from_sec!(1, ms!(300));
115//! assert_eq!(a, dt!(1_300_000_000_000_000_000));
116//!
117//! // Reverse conversion truncates toward zero.
118//! assert_eq!(as_sec!(sec!(1) + ms!(900)), 1);
119//! assert_eq!(as_sec!(-ms!(500)), 0);
120//! assert_eq!(as_sec!(-sec!(1) - ms!(500)), -1);
121//!
122//! // Calendar construction: builds a Dt, converting civil time to TAI.
123//! assert_eq!(from_ymd!(2000, 1, 1; 12, on=Scale::TAI), Dt::ZERO);
124//! ```
125//!
126//! See each macro's own documentation for accepted forms, defaults, and
127//! links to the corresponding [`Dt`](../struct.Dt.html) methods.
128
129/// Converts whole femtoseconds (`i128`) to total attoseconds (`i128`).
130///
131/// Equivalent to [`Dt::fs_to_attos`](../struct.Dt.html#method.fs_to_attos).
132///
133/// ## Examples
134///
135/// ```rust
136/// use deep_time::Dt;
137/// use deep_time::macros::fs;
138///
139/// assert_eq!(fs!(1), Dt::fs_to_attos(1));
140/// ```
141#[macro_export]
142macro_rules! fs {
143 ($x:expr) => {
144 $crate::Dt::fs_to_attos($x)
145 };
146}
147
148/// Converts whole picoseconds (`i128`) to total attoseconds (`i128`).
149///
150/// Equivalent to [`Dt::ps_to_attos`](../struct.Dt.html#method.ps_to_attos).
151///
152/// ## Examples
153///
154/// ```rust
155/// use deep_time::Dt;
156/// use deep_time::macros::ps;
157///
158/// assert_eq!(ps!(1), Dt::ps_to_attos(1));
159/// ```
160#[macro_export]
161macro_rules! ps {
162 ($x:expr) => {
163 $crate::Dt::ps_to_attos($x)
164 };
165}
166
167/// Converts whole nanoseconds (`i128`) to total attoseconds (`i128`).
168///
169/// Equivalent to [`Dt::ns_to_attos`](../struct.Dt.html#method.ns_to_attos).
170///
171/// ## Examples
172///
173/// ```rust
174/// use deep_time::Dt;
175/// use deep_time::macros::ns;
176///
177/// assert_eq!(ns!(1), Dt::ns_to_attos(1));
178/// ```
179#[macro_export]
180macro_rules! ns {
181 ($x:expr) => {
182 $crate::Dt::ns_to_attos($x)
183 };
184}
185
186/// Converts whole microseconds (`i128`) to total attoseconds (`i128`).
187///
188/// Equivalent to [`Dt::us_to_attos`](../struct.Dt.html#method.us_to_attos).
189///
190/// ## Examples
191///
192/// ```rust
193/// use deep_time::Dt;
194/// use deep_time::macros::us;
195///
196/// assert_eq!(us!(1), Dt::us_to_attos(1));
197/// ```
198#[macro_export]
199macro_rules! us {
200 ($x:expr) => {
201 $crate::Dt::us_to_attos($x)
202 };
203}
204
205/// Converts whole milliseconds (`i128`) to total attoseconds (`i128`).
206///
207/// Equivalent to [`Dt::ms_to_attos`](../struct.Dt.html#method.ms_to_attos).
208///
209/// ## Examples
210///
211/// ```rust
212/// use deep_time::Dt;
213/// use deep_time::macros::ms;
214///
215/// assert_eq!(ms!(1), Dt::ms_to_attos(1));
216/// ```
217#[macro_export]
218macro_rules! ms {
219 ($x:expr) => {
220 $crate::Dt::ms_to_attos($x)
221 };
222}
223
224/// Converts whole seconds (`i128`) to total attoseconds (`i128`).
225///
226/// Equivalent to [`Dt::sec_to_attos`](../struct.Dt.html#method.sec_to_attos).
227///
228/// ## Examples
229///
230/// ```rust
231/// use deep_time::Dt;
232/// use deep_time::macros::sec;
233///
234/// assert_eq!(sec!(1), Dt::sec_to_attos(1));
235/// ```
236#[macro_export]
237macro_rules! sec {
238 ($x:expr) => {
239 $crate::Dt::sec_to_attos($x)
240 };
241}
242
243/// Converts a floating-point second count ([`Real`](crate::Real)) to
244/// total attoseconds (`i128`).
245///
246/// Equivalent to [`Dt::sec_f_to_attos`](../struct.Dt.html#method.sec_f_to_attos).
247///
248/// ## Examples
249///
250/// ```rust
251/// use deep_time::Dt;
252/// use deep_time::macros::sec_f;
253///
254/// assert_eq!(sec_f!(1.5), Dt::sec_f_to_attos(1.5));
255/// ```
256#[macro_export]
257macro_rules! sec_f {
258 ($x:expr) => {
259 $crate::Dt::sec_f_to_attos($x)
260 };
261}
262
263/// Converts whole minutes (`i128`) to total attoseconds (`i128`).
264///
265/// Equivalent to [`Dt::mins_to_attos`](../struct.Dt.html#method.mins_to_attos).
266///
267/// ## Examples
268///
269/// ```rust
270/// use deep_time::Dt;
271/// use deep_time::macros::mins;
272///
273/// assert_eq!(mins!(1), Dt::mins_to_attos(1));
274/// ```
275#[macro_export]
276macro_rules! mins {
277 ($x:expr) => {
278 $crate::Dt::mins_to_attos($x)
279 };
280}
281
282/// Converts whole hours (`i128`) to total attoseconds (`i128`).
283///
284/// Equivalent to [`Dt::hours_to_attos`](../struct.Dt.html#method.hours_to_attos).
285///
286/// ## Examples
287///
288/// ```rust
289/// use deep_time::Dt;
290/// use deep_time::macros::hours;
291///
292/// assert_eq!(hours!(1), Dt::hours_to_attos(1));
293/// ```
294#[macro_export]
295macro_rules! hours {
296 ($x:expr) => {
297 $crate::Dt::hours_to_attos($x)
298 };
299}
300
301/// Converts whole days (`i128`) to total attoseconds (`i128`).
302///
303/// Equivalent to [`Dt::days_to_attos`](../struct.Dt.html#method.days_to_attos).
304///
305/// ## Examples
306///
307/// ```rust
308/// use deep_time::Dt;
309/// use deep_time::macros::days;
310///
311/// assert_eq!(days!(1), Dt::days_to_attos(1));
312/// ```
313#[macro_export]
314macro_rules! days {
315 ($x:expr) => {
316 $crate::Dt::days_to_attos($x)
317 };
318}
319
320/// Converts a floating-point day count ([`Real`](crate::Real)) to total attoseconds (`i128`).
321///
322/// Equivalent to [`Dt::days_f_to_attos`](../struct.Dt.html#method.days_f_to_attos).
323///
324/// ## Examples
325///
326/// ```rust
327/// use deep_time::Dt;
328/// use deep_time::macros::days_f;
329///
330/// assert_eq!(days_f!(0.25), Dt::days_f_to_attos(0.25));
331/// ```
332#[macro_export]
333macro_rules! days_f {
334 ($x:expr) => {
335 $crate::Dt::days_f_to_attos($x)
336 };
337}
338
339/// Converts whole weeks (`i128`) to total attoseconds (`i128`).
340///
341/// Equivalent to [`Dt::weeks_to_attos`](../struct.Dt.html#method.weeks_to_attos).
342///
343/// ## Examples
344///
345/// ```rust
346/// use deep_time::Dt;
347/// use deep_time::macros::weeks;
348///
349/// assert_eq!(weeks!(1), Dt::weeks_to_attos(1));
350/// ```
351#[macro_export]
352macro_rules! weeks {
353 ($x:expr) => {
354 $crate::Dt::weeks_to_attos($x)
355 };
356}
357
358/// Converts total attoseconds (`i128`) → whole femtoseconds (`i128`).
359///
360/// Equivalent to [`Dt::attos_to_fs`](../struct.Dt.html#method.attos_to_fs).
361///
362/// Truncates toward zero.
363///
364/// Half a femtosecond is `500` attoseconds (no smaller named unit macro).
365///
366/// ## Examples
367///
368/// Example shows attos inputs being built with macros rather than counting
369/// attosecond zeros by hand.
370///
371/// ```rust
372/// use deep_time::macros::{as_fs, fs};
373///
374/// // an amount of attoseconds that is equal to
375/// // −1.5 fs becomes −1 femtoseconds
376/// assert_eq!(as_fs!(-fs!(1) - 500), -1);
377/// ```
378#[macro_export]
379macro_rules! as_fs {
380 ($x:expr) => {
381 $crate::Dt::attos_to_fs($x)
382 };
383}
384
385/// Converts total attoseconds (`i128`) → whole picoseconds (`i128`).
386///
387/// Equivalent to [`Dt::attos_to_ps`](../struct.Dt.html#method.attos_to_ps).
388///
389/// Truncates toward zero.
390///
391/// ## Examples
392///
393/// Example shows attos inputs being built with macros rather than counting
394/// attosecond zeros by hand.
395///
396/// ```rust
397/// use deep_time::macros::{as_ps, fs, ps};
398///
399/// // an amount of attoseconds that is equal to
400/// // −1.5 ps becomes −1 picoseconds
401/// assert_eq!(as_ps!(-ps!(1) - fs!(500)), -1);
402/// ```
403#[macro_export]
404macro_rules! as_ps {
405 ($x:expr) => {
406 $crate::Dt::attos_to_ps($x)
407 };
408}
409
410/// Converts total attoseconds (`i128`) → whole nanoseconds (`i128`).
411///
412/// Equivalent to [`Dt::attos_to_ns`](../struct.Dt.html#method.attos_to_ns).
413///
414/// Truncates toward zero.
415///
416/// ## Examples
417///
418/// Example shows attos inputs being built with macros rather than counting
419/// attosecond zeros by hand.
420///
421/// ```rust
422/// use deep_time::macros::{as_ns, ns, ps};
423///
424/// // an amount of attoseconds that is equal to
425/// // −1.5 ns becomes −1 nanoseconds
426/// assert_eq!(as_ns!(-ns!(1) - ps!(500)), -1);
427/// ```
428#[macro_export]
429macro_rules! as_ns {
430 ($x:expr) => {
431 $crate::Dt::attos_to_ns($x)
432 };
433}
434
435/// Converts total attoseconds (`i128`) → whole microseconds (`i128`).
436///
437/// Equivalent to [`Dt::attos_to_us`](../struct.Dt.html#method.attos_to_us).
438///
439/// Truncates toward zero.
440///
441/// ## Examples
442///
443/// Example shows attos inputs being built with macros rather than counting
444/// attosecond zeros by hand.
445///
446/// ```rust
447/// use deep_time::macros::{as_us, ns, us};
448///
449/// // an amount of attoseconds that is equal to
450/// // −1.5 µs becomes −1 microseconds
451/// assert_eq!(as_us!(-us!(1) - ns!(500)), -1);
452/// ```
453#[macro_export]
454macro_rules! as_us {
455 ($x:expr) => {
456 $crate::Dt::attos_to_us($x)
457 };
458}
459
460/// Converts total attoseconds (`i128`) → whole milliseconds (`i128`).
461///
462/// Equivalent to [`Dt::attos_to_ms`](../struct.Dt.html#method.attos_to_ms).
463///
464/// Truncates toward zero.
465///
466/// ## Examples
467///
468/// Example shows attos inputs being built with macros rather than counting
469/// attosecond zeros by hand.
470///
471/// ```rust
472/// use deep_time::macros::{as_ms, ms, us};
473///
474/// // an amount of attoseconds that is equal to
475/// // −1.5 ms becomes −1 milliseconds
476/// assert_eq!(as_ms!(-ms!(1) - us!(500)), -1);
477/// ```
478#[macro_export]
479macro_rules! as_ms {
480 ($x:expr) => {
481 $crate::Dt::attos_to_ms($x)
482 };
483}
484
485/// Converts total attoseconds (`i128`) → whole seconds (`i128`).
486///
487/// Equivalent to [`Dt::attos_to_sec`](../struct.Dt.html#method.attos_to_sec).
488///
489/// Truncates toward zero.
490///
491/// ## Examples
492///
493/// Example shows attos inputs being built with macros rather than counting
494/// attosecond zeros by hand.
495///
496/// ```rust
497/// use deep_time::macros::{as_sec, ms, sec};
498///
499/// // an amount of attoseconds that is equal to
500/// // −1.5 s becomes −1 seconds
501/// assert_eq!(as_sec!(-sec!(1) - ms!(500)), -1);
502/// ```
503#[macro_export]
504macro_rules! as_sec {
505 ($x:expr) => {
506 $crate::Dt::attos_to_sec($x)
507 };
508}
509
510/// Converts total attoseconds (`i128`) → lossy float seconds ([`Real`](crate::Real)).
511///
512/// Equivalent to [`Dt::attos_to_sec_f`](../struct.Dt.html#method.attos_to_sec_f).
513///
514/// ## Examples
515///
516/// Example shows attos inputs being built with macros rather than counting
517/// attosecond zeros by hand.
518///
519/// ```rust
520/// use deep_time::macros::{as_sec_f, ms, sec};
521///
522/// // an amount of attoseconds that is equal to
523/// // −1.5 s becomes -1.5 seconds
524/// assert_eq!(as_sec_f!(-sec!(1) - ms!(500)), -1.5);
525/// ```
526#[macro_export]
527macro_rules! as_sec_f {
528 ($x:expr) => {
529 $crate::Dt::attos_to_sec_f($x)
530 };
531}
532
533/// Converts total attoseconds (`i128`) → whole minutes (`i128`).
534///
535/// Equivalent to [`Dt::attos_to_mins`](../struct.Dt.html#method.attos_to_mins).
536///
537/// Truncates toward zero.
538///
539/// ## Examples
540///
541/// Example shows attos inputs being built with macros rather than counting
542/// attosecond zeros by hand.
543///
544/// ```rust
545/// use deep_time::macros::{as_mins, mins, sec};
546///
547/// // an amount of attoseconds that is equal to
548/// // −1.5 min becomes −1 minutes
549/// assert_eq!(as_mins!(-mins!(1) - sec!(30)), -1);
550/// ```
551#[macro_export]
552macro_rules! as_mins {
553 ($x:expr) => {
554 $crate::Dt::attos_to_mins($x)
555 };
556}
557
558/// Converts total attoseconds (`i128`) → whole hours (`i128`).
559///
560/// Equivalent to [`Dt::attos_to_hours`](../struct.Dt.html#method.attos_to_hours).
561///
562/// Truncates toward zero.
563///
564/// ## Examples
565///
566/// Example shows attos inputs being built with macros rather than counting
567/// attosecond zeros by hand.
568///
569/// ```rust
570/// use deep_time::macros::{as_hours, hours, mins};
571///
572/// // an amount of attoseconds that is equal to
573/// // −1.5 h becomes −1 hours
574/// assert_eq!(as_hours!(-hours!(1) - mins!(30)), -1);
575/// ```
576#[macro_export]
577macro_rules! as_hours {
578 ($x:expr) => {
579 $crate::Dt::attos_to_hours($x)
580 };
581}
582
583/// Converts total attoseconds (`i128`) → whole days (`i128`).
584///
585/// Equivalent to [`Dt::attos_to_days`](../struct.Dt.html#method.attos_to_days).
586///
587/// Truncates toward zero.
588///
589/// ## Examples
590///
591/// Example shows attos inputs being built with macros rather than counting
592/// attosecond zeros by hand.
593///
594/// ```rust
595/// use deep_time::macros::{as_days, days, hours};
596///
597/// // an amount of attoseconds that is equal to
598/// // −1.5 d becomes −1 days
599/// assert_eq!(as_days!(-days!(1) - hours!(12)), -1);
600/// ```
601#[macro_export]
602macro_rules! as_days {
603 ($x:expr) => {
604 $crate::Dt::attos_to_days($x)
605 };
606}
607
608/// Converts total attoseconds (`i128`) → lossy float days ([`Real`](crate::Real)).
609///
610/// Equivalent to [`Dt::attos_to_days_f`](../struct.Dt.html#method.attos_to_days_f).
611///
612/// ## Examples
613///
614/// Example shows attos inputs being built with macros rather than counting
615/// attosecond zeros by hand.
616///
617/// ```rust
618/// use deep_time::macros::{as_days_f, days, hours};
619///
620/// // an amount of attoseconds that is equal to
621/// // −1.5 d becomes -1.5 days
622/// assert_eq!(as_days_f!(-days!(1) - hours!(12)), -1.5);
623/// ```
624#[macro_export]
625macro_rules! as_days_f {
626 ($x:expr) => {
627 $crate::Dt::attos_to_days_f($x)
628 };
629}
630
631/// Converts total attoseconds (`i128`) → whole weeks (`i128`).
632///
633/// Equivalent to [`Dt::attos_to_weeks`](../struct.Dt.html#method.attos_to_weeks).
634///
635/// Truncates toward zero.
636///
637/// ## Examples
638///
639/// Example shows attos inputs being built with macros rather than counting
640/// attosecond zeros by hand.
641///
642/// ```rust
643/// use deep_time::macros::{as_weeks, days, hours, weeks};
644///
645/// // an amount of attoseconds that is equal to
646/// // −1.5 wk becomes −1 weeks
647/// assert_eq!(as_weeks!(-weeks!(1) - days!(3) - hours!(12)), -1);
648/// ```
649#[macro_export]
650macro_rules! as_weeks {
651 ($x:expr) => {
652 $crate::Dt::attos_to_weeks($x)
653 };
654}
655
656/// Builds a [`Dt`](../struct.Dt.html) from total attoseconds with optional scale labels.
657///
658/// - Equivalent to [`Dt::new`](../struct.Dt.html#method.new).
659/// - Does **not** perform time-scale conversion.
660///
661/// ## Defaults
662///
663/// | Omitted | Default |
664/// |---------|---------|
665/// | `on` and `target` | both [`Scale::TAI`](crate::Scale::TAI) |
666/// | only `on=s` | `target=s` |
667/// | only `target=t` | `on=TAI` |
668///
669/// ## Forms
670///
671/// | Form | Meaning |
672/// |------|---------|
673/// | `dt!(attos)` | both scales TAI |
674/// | `dt!(attos, on=s)` | scale and target `s` |
675/// | `dt!(attos, target=t)` | scale TAI, target `t` |
676/// | `dt!(attos, on=s, target=t)` | either order |
677/// | `dt!(attos, target=t, on=s)` | either order |
678///
679/// ## Examples
680///
681/// ```rust
682/// use deep_time::{Dt, Scale};
683/// use deep_time::macros::dt;
684///
685/// let a = dt!(Dt::sec_to_attos(1));
686/// let b = dt!(0, on=Scale::UTC);
687/// let c = dt!(0, on=Scale::TAI, target=Scale::UTC);
688/// let d = dt!(0, target=Scale::UTC, on=Scale::TAI);
689/// let e = dt!(0, target=Scale::UTC);
690///
691/// assert_eq!(a, Dt::new(Dt::sec_to_attos(1), Scale::TAI, Scale::TAI));
692/// assert_eq!(b, Dt::new(0, Scale::UTC, Scale::UTC));
693/// assert_eq!(c, Dt::new(0, Scale::TAI, Scale::UTC));
694/// assert_eq!(d, c);
695/// assert_eq!(e, Dt::new(0, Scale::TAI, Scale::UTC));
696/// ```
697#[macro_export]
698macro_rules! dt {
699 ($attos:expr, on=$scale:expr, target=$target:expr) => {
700 $crate::Dt::new($attos, $scale, $target)
701 };
702 ($attos:expr, target=$target:expr, on=$scale:expr) => {
703 $crate::Dt::new($attos, $scale, $target)
704 };
705 ($attos:expr, on=$scale:expr) => {
706 $crate::Dt::new($attos, $scale, $scale)
707 };
708 ($attos:expr, target=$target:expr) => {
709 $crate::Dt::new($attos, $crate::Scale::TAI, $target)
710 };
711 ($attos:expr) => {
712 $crate::Dt::new($attos, $crate::Scale::TAI, $crate::Scale::TAI)
713 };
714}
715
716/// Builds a [`Dt`](../struct.Dt.html) from whole seconds and an optional signed
717/// sub-second remainder (attoseconds).
718///
719/// - Equivalent to [`Dt::from_sec_and_frac`](../struct.Dt.html#method.from_sec_and_frac).
720/// - Does **not** perform time-scale conversion.
721///
722/// The fractional remainder is in **attoseconds** — use
723/// [`ms!`](../macro.ms.html) (or another `*_to_attos`
724/// helper) instead of writing the attosecond literal by hand.
725///
726/// ## Defaults
727///
728/// | Omitted | Default |
729/// |---------|---------|
730/// | fraction | `0` |
731/// | `on` and `target` | both [`Scale::TAI`](crate::Scale::TAI) |
732/// | only `on=s` | `target=s` |
733/// | only `target=t` | `on=TAI` |
734///
735/// ## Forms
736///
737/// ```text
738/// from_sec!(sec)
739/// from_sec!(sec, frac)
740/// from_sec!(sec, on=s)
741/// from_sec!(sec, target=t)
742/// from_sec!(sec, on=s, target=t)
743/// from_sec!(sec, target=t, on=s)
744/// from_sec!(sec, frac, on=s)
745/// from_sec!(sec, frac, target=t)
746/// from_sec!(sec, frac, on=s, target=t)
747/// from_sec!(sec, frac, target=t, on=s)
748/// ```
749///
750/// ## Examples
751///
752/// ```
753/// use deep_time::{Dt, Scale};
754/// use deep_time::macros::{from_sec, ms};
755///
756/// // 1.3 s → whole seconds + 300 ms remainder
757/// let a = from_sec!(1);
758/// let b = from_sec!(1, ms!(300));
759/// let c = from_sec!(-1, ms!(-300), on=Scale::TAI);
760/// let d = from_sec!(0, on=Scale::UTC);
761/// let e = from_sec!(1, on=Scale::TAI, target=Scale::UTC);
762/// let f = from_sec!(1, target=Scale::UTC, on=Scale::TAI);
763///
764/// assert_eq!(a, Dt::from_sec_and_frac(1, 0, Scale::TAI, Scale::TAI));
765/// assert_eq!(b, Dt::from_sec_and_frac(1, ms!(300), Scale::TAI, Scale::TAI));
766/// assert_eq!(c, Dt::from_sec_and_frac(-1, ms!(-300), Scale::TAI, Scale::TAI));
767/// assert_eq!(d, Dt::from_sec_and_frac(0, 0, Scale::UTC, Scale::UTC));
768/// assert_eq!(e, Dt::from_sec_and_frac(1, 0, Scale::TAI, Scale::UTC));
769/// assert_eq!(f, e);
770///
771/// let signed = from_sec!(-1, ms!(-300));
772/// let floored = from_sec!(-2, ms!(700));
773/// assert_eq!(signed, floored);
774/// assert_eq!(signed, Dt::from_sec_and_frac(-1, ms!(-300), Scale::TAI, Scale::TAI));
775/// ```
776#[macro_export]
777macro_rules! from_sec {
778 ($sec:expr, $frac:expr, on=$scale:expr, target=$target:expr) => {
779 $crate::Dt::from_sec_and_frac($sec, $frac, $scale, $target)
780 };
781 ($sec:expr, $frac:expr, target=$target:expr, on=$scale:expr) => {
782 $crate::Dt::from_sec_and_frac($sec, $frac, $scale, $target)
783 };
784 ($sec:expr, on=$scale:expr, target=$target:expr) => {
785 $crate::Dt::from_sec_and_frac($sec, 0, $scale, $target)
786 };
787 ($sec:expr, target=$target:expr, on=$scale:expr) => {
788 $crate::Dt::from_sec_and_frac($sec, 0, $scale, $target)
789 };
790 ($sec:expr, $frac:expr, on=$scale:expr) => {
791 $crate::Dt::from_sec_and_frac($sec, $frac, $scale, $scale)
792 };
793 ($sec:expr, $frac:expr, target=$target:expr) => {
794 $crate::Dt::from_sec_and_frac($sec, $frac, $crate::Scale::TAI, $target)
795 };
796 ($sec:expr, on=$scale:expr) => {
797 $crate::Dt::from_sec_and_frac($sec, 0, $scale, $scale)
798 };
799 ($sec:expr, target=$target:expr) => {
800 $crate::Dt::from_sec_and_frac($sec, 0, $crate::Scale::TAI, $target)
801 };
802 ($sec:expr, $frac:expr) => {
803 $crate::Dt::from_sec_and_frac($sec, $frac, $crate::Scale::TAI, $crate::Scale::TAI)
804 };
805 ($sec:expr) => {
806 $crate::Dt::from_sec_and_frac($sec, 0, $crate::Scale::TAI, $crate::Scale::TAI)
807 };
808}
809
810/// Builds a [`Dt`](../struct.Dt.html) from a floating-point seconds count with optional
811/// scale labels.
812///
813/// - Equivalent to [`Dt::from_sec_f`](../struct.Dt.html#method.from_sec_f).
814/// - Does **not** perform time-scale conversion.
815///
816/// ## Defaults
817///
818/// | Omitted | Default |
819/// |---------|---------|
820/// | `on` and `target` | both [`Scale::TAI`](crate::Scale::TAI) |
821/// | only `on=s` | `target=s` |
822/// | only `target=t` | `on=TAI` |
823///
824/// ## Forms
825///
826/// | Form | Meaning |
827/// |------|---------|
828/// | `from_sec_f!(sec)` | both scales TAI |
829/// | `from_sec_f!(sec, on=s)` | scale and target `s` |
830/// | `from_sec_f!(sec, target=t)` | scale TAI, target `t` |
831/// | `from_sec_f!(sec, on=s, target=t)` | either order |
832/// | `from_sec_f!(sec, target=t, on=s)` | either order |
833///
834/// ## Examples
835///
836/// ```
837/// use deep_time::Scale;
838/// use deep_time::macros::from_sec_f;
839///
840/// let a = from_sec_f!(5.5);
841/// let b = from_sec_f!(0.0, on=Scale::UTC);
842/// let c = from_sec_f!(1.0, on=Scale::TAI, target=Scale::UTC);
843/// let d = from_sec_f!(1.0, target=Scale::UTC, on=Scale::TAI);
844///
845/// assert_eq!(a, deep_time::Dt::from_sec_f(5.5, Scale::TAI, Scale::TAI));
846/// assert_eq!(b, deep_time::Dt::from_sec_f(0.0, Scale::UTC, Scale::UTC));
847/// assert_eq!(c, deep_time::Dt::from_sec_f(1.0, Scale::TAI, Scale::UTC));
848/// assert_eq!(d, c);
849/// ```
850#[macro_export]
851macro_rules! from_sec_f {
852 ($sec:expr, on=$scale:expr, target=$target:expr) => {
853 $crate::Dt::from_sec_f($sec, $scale, $target)
854 };
855 ($sec:expr, target=$target:expr, on=$scale:expr) => {
856 $crate::Dt::from_sec_f($sec, $scale, $target)
857 };
858 ($sec:expr, on=$scale:expr) => {
859 $crate::Dt::from_sec_f($sec, $scale, $scale)
860 };
861 ($sec:expr, target=$target:expr) => {
862 $crate::Dt::from_sec_f($sec, $crate::Scale::TAI, $target)
863 };
864 ($sec:expr) => {
865 $crate::Dt::from_sec_f($sec, $crate::Scale::TAI, $crate::Scale::TAI)
866 };
867}
868
869/// Builds a [`Dt`](../struct.Dt.html) from a floating-point day count with optional
870/// scale labels.
871///
872/// - Equivalent to [`Dt::from_days_f`](../struct.Dt.html#method.from_days_f).
873/// - Does **not** perform time-scale conversion.
874///
875/// ## Defaults
876///
877/// | Omitted | Default |
878/// |---------|---------|
879/// | `on` and `target` | both [`Scale::TAI`](crate::Scale::TAI) |
880/// | only `on=s` | `target=s` |
881/// | only `target=t` | `on=TAI` |
882///
883/// ## Forms
884///
885/// | Form | Meaning |
886/// |------|---------|
887/// | `from_days_f!(days)` | both scales TAI |
888/// | `from_days_f!(days, on=s)` | scale and target `s` |
889/// | `from_days_f!(days, target=t)` | scale TAI, target `t` |
890/// | `from_days_f!(days, on=s, target=t)` | either order |
891/// | `from_days_f!(days, target=t, on=s)` | either order |
892///
893/// ## Examples
894///
895/// ```
896/// use deep_time::Scale;
897/// use deep_time::macros::from_days_f;
898///
899/// let a = from_days_f!(1.25);
900/// let b = from_days_f!(0.0, on=Scale::UTC);
901/// let c = from_days_f!(1.0, on=Scale::TAI, target=Scale::UTC);
902///
903/// assert_eq!(a, deep_time::Dt::from_days_f(1.25, Scale::TAI, Scale::TAI));
904/// assert_eq!(b, deep_time::Dt::from_days_f(0.0, Scale::UTC, Scale::UTC));
905/// assert_eq!(c, deep_time::Dt::from_days_f(1.0, Scale::TAI, Scale::UTC));
906/// ```
907#[macro_export]
908macro_rules! from_days_f {
909 ($days:expr, on=$scale:expr, target=$target:expr) => {
910 $crate::Dt::from_days_f($days, $scale, $target)
911 };
912 ($days:expr, target=$target:expr, on=$scale:expr) => {
913 $crate::Dt::from_days_f($days, $scale, $target)
914 };
915 ($days:expr, on=$scale:expr) => {
916 $crate::Dt::from_days_f($days, $scale, $scale)
917 };
918 ($days:expr, target=$target:expr) => {
919 $crate::Dt::from_days_f($days, $crate::Scale::TAI, $target)
920 };
921 ($days:expr) => {
922 $crate::Dt::from_days_f($days, $crate::Scale::TAI, $crate::Scale::TAI)
923 };
924}
925
926/// Builds a [`Dt`](../struct.Dt.html) from whole nanoseconds and an optional signed
927/// fractional remainder in attoseconds.
928///
929/// - Equivalent to [`Dt::from_ns`](../struct.Dt.html#method.from_ns).
930/// - Does **not** perform time-scale conversion.
931///
932/// The fractional remainder is in **attoseconds** — use
933/// [`ps!`](macro.ps.html) (or another `*_to_attos`
934/// helper) instead of writing the attosecond literal by hand.
935///
936/// ## Defaults
937///
938/// | Omitted | Default |
939/// |---------|---------|
940/// | fraction | `0` |
941/// | `on` and `target` | both [`Scale::TAI`](crate::Scale::TAI) |
942/// | only `on=s` | `target=s` |
943/// | only `target=t` | `on=TAI` |
944///
945/// ## Forms
946///
947/// ```text
948/// from_ns!(ns)
949/// from_ns!(ns, frac)
950/// from_ns!(ns, on=s)
951/// from_ns!(ns, target=t)
952/// from_ns!(ns, on=s, target=t)
953/// from_ns!(ns, target=t, on=s)
954/// from_ns!(ns, frac, on=s)
955/// from_ns!(ns, frac, target=t)
956/// from_ns!(ns, frac, on=s, target=t)
957/// from_ns!(ns, frac, target=t, on=s)
958/// ```
959///
960/// ## Examples
961///
962/// ```
963/// use deep_time::{Dt, Scale};
964/// use deep_time::macros::{from_ns, ps};
965///
966/// // 1.3 ns → whole nanoseconds + 300 ps remainder
967/// let a = from_ns!(1);
968/// let b = from_ns!(1, ps!(300));
969/// let c = from_ns!(-1, ps!(-300), on=Scale::TAI);
970/// let d = from_ns!(0, on=Scale::UTC);
971/// let e = from_ns!(1, on=Scale::TAI, target=Scale::UTC);
972/// let f = from_ns!(1, target=Scale::UTC);
973///
974/// assert_eq!(a, Dt::from_ns(1, 0, Scale::TAI, Scale::TAI));
975/// assert_eq!(b, Dt::from_ns(1, ps!(300), Scale::TAI, Scale::TAI));
976/// assert_eq!(c, Dt::from_ns(-1, ps!(-300), Scale::TAI, Scale::TAI));
977/// assert_eq!(d, Dt::from_ns(0, 0, Scale::UTC, Scale::UTC));
978/// assert_eq!(e, Dt::from_ns(1, 0, Scale::TAI, Scale::UTC));
979/// assert_eq!(f, e);
980///
981/// let signed = from_ns!(-1, ps!(-300));
982/// let floor = from_ns!(-2, ps!(700));
983/// assert_eq!(signed, floor);
984/// assert_eq!(signed, Dt::from_ns(-1, ps!(-300), Scale::TAI, Scale::TAI));
985/// ```
986#[macro_export]
987macro_rules! from_ns {
988 ($ns:expr, $frac:expr, on=$scale:expr, target=$target:expr) => {
989 $crate::Dt::from_ns($ns, $frac, $scale, $target)
990 };
991 ($ns:expr, $frac:expr, target=$target:expr, on=$scale:expr) => {
992 $crate::Dt::from_ns($ns, $frac, $scale, $target)
993 };
994 ($ns:expr, on=$scale:expr, target=$target:expr) => {
995 $crate::Dt::from_ns($ns, 0, $scale, $target)
996 };
997 ($ns:expr, target=$target:expr, on=$scale:expr) => {
998 $crate::Dt::from_ns($ns, 0, $scale, $target)
999 };
1000 ($ns:expr, $frac:expr, on=$scale:expr) => {
1001 $crate::Dt::from_ns($ns, $frac, $scale, $scale)
1002 };
1003 ($ns:expr, $frac:expr, target=$target:expr) => {
1004 $crate::Dt::from_ns($ns, $frac, $crate::Scale::TAI, $target)
1005 };
1006 ($ns:expr, on=$scale:expr) => {
1007 $crate::Dt::from_ns($ns, 0, $scale, $scale)
1008 };
1009 ($ns:expr, target=$target:expr) => {
1010 $crate::Dt::from_ns($ns, 0, $crate::Scale::TAI, $target)
1011 };
1012 ($ns:expr, $frac:expr) => {
1013 $crate::Dt::from_ns($ns, $frac, $crate::Scale::TAI, $crate::Scale::TAI)
1014 };
1015 ($ns:expr) => {
1016 $crate::Dt::from_ns($ns, 0, $crate::Scale::TAI, $crate::Scale::TAI)
1017 };
1018}
1019
1020/// Builds a [`Dt`](../struct.Dt.html) from whole milliseconds and an optional signed
1021/// fractional remainder in attoseconds.
1022///
1023/// - Equivalent to [`Dt::from_ms`](../struct.Dt.html#method.from_ms).
1024/// - Does **not** perform time-scale conversion.
1025///
1026/// The fractional remainder is in **attoseconds** — use
1027/// [`us!`](macro.us.html) (or another `*_to_attos`
1028/// helper) instead of writing the attosecond literal by hand.
1029///
1030/// ## Defaults
1031///
1032/// | Omitted | Default |
1033/// |---------|---------|
1034/// | fraction | `0` |
1035/// | `on` and `target` | both [`Scale::TAI`](crate::Scale::TAI) |
1036/// | only `on=s` | `target=s` |
1037/// | only `target=t` | `on=TAI` |
1038///
1039/// ## Forms
1040///
1041/// ```text
1042/// from_ms!(ms)
1043/// from_ms!(ms, frac)
1044/// from_ms!(ms, on=s)
1045/// from_ms!(ms, target=t)
1046/// from_ms!(ms, on=s, target=t)
1047/// from_ms!(ms, target=t, on=s)
1048/// from_ms!(ms, frac, on=s)
1049/// from_ms!(ms, frac, target=t)
1050/// from_ms!(ms, frac, on=s, target=t)
1051/// from_ms!(ms, frac, target=t, on=s)
1052/// ```
1053///
1054/// ## Examples
1055///
1056/// ```
1057/// use deep_time::{Dt, Scale};
1058/// use deep_time::macros::{from_ms, us};
1059///
1060/// // 1.3 ms → whole milliseconds + 300 µs remainder
1061/// let a = from_ms!(1);
1062/// let b = from_ms!(1, us!(300));
1063/// let c = from_ms!(-1, us!(-300), on=Scale::TAI);
1064/// let d = from_ms!(0, on=Scale::UTC);
1065/// let e = from_ms!(1, on=Scale::TAI, target=Scale::UTC);
1066/// let f = from_ms!(1, target=Scale::UTC);
1067///
1068/// assert_eq!(a, Dt::from_ms(1, 0, Scale::TAI, Scale::TAI));
1069/// assert_eq!(b, Dt::from_ms(1, us!(300), Scale::TAI, Scale::TAI));
1070/// assert_eq!(c, Dt::from_ms(-1, us!(-300), Scale::TAI, Scale::TAI));
1071/// assert_eq!(d, Dt::from_ms(0, 0, Scale::UTC, Scale::UTC));
1072/// assert_eq!(e, Dt::from_ms(1, 0, Scale::TAI, Scale::UTC));
1073/// assert_eq!(f, e);
1074///
1075/// let signed = from_ms!(-1, us!(-300));
1076/// let floor = from_ms!(-2, us!(700));
1077/// assert_eq!(signed, floor);
1078/// assert_eq!(signed, Dt::from_ms(-1, us!(-300), Scale::TAI, Scale::TAI));
1079/// ```
1080#[macro_export]
1081macro_rules! from_ms {
1082 ($ms:expr, $frac:expr, on=$scale:expr, target=$target:expr) => {
1083 $crate::Dt::from_ms($ms, $frac, $scale, $target)
1084 };
1085 ($ms:expr, $frac:expr, target=$target:expr, on=$scale:expr) => {
1086 $crate::Dt::from_ms($ms, $frac, $scale, $target)
1087 };
1088 ($ms:expr, on=$scale:expr, target=$target:expr) => {
1089 $crate::Dt::from_ms($ms, 0, $scale, $target)
1090 };
1091 ($ms:expr, target=$target:expr, on=$scale:expr) => {
1092 $crate::Dt::from_ms($ms, 0, $scale, $target)
1093 };
1094 ($ms:expr, $frac:expr, on=$scale:expr) => {
1095 $crate::Dt::from_ms($ms, $frac, $scale, $scale)
1096 };
1097 ($ms:expr, $frac:expr, target=$target:expr) => {
1098 $crate::Dt::from_ms($ms, $frac, $crate::Scale::TAI, $target)
1099 };
1100 ($ms:expr, on=$scale:expr) => {
1101 $crate::Dt::from_ms($ms, 0, $scale, $scale)
1102 };
1103 ($ms:expr, target=$target:expr) => {
1104 $crate::Dt::from_ms($ms, 0, $crate::Scale::TAI, $target)
1105 };
1106 ($ms:expr, $frac:expr) => {
1107 $crate::Dt::from_ms($ms, $frac, $crate::Scale::TAI, $crate::Scale::TAI)
1108 };
1109 ($ms:expr) => {
1110 $crate::Dt::from_ms($ms, 0, $crate::Scale::TAI, $crate::Scale::TAI)
1111 };
1112}
1113
1114/// Builds a [`Dt`](../struct.Dt.html) from whole microseconds and an optional signed
1115/// fractional remainder in attoseconds.
1116///
1117/// - Equivalent to [`Dt::from_us`](../struct.Dt.html#method.from_us).
1118/// - Does **not** perform time-scale conversion.
1119///
1120/// The fractional remainder is in **attoseconds** — use
1121/// [`ns!`](../macro.ns.html) (or another `*_to_attos`
1122/// helper) instead of writing the attosecond literal by hand.
1123///
1124/// ## Defaults
1125///
1126/// | Omitted | Default |
1127/// |---------|---------|
1128/// | fraction | `0` |
1129/// | `on` and `target` | both [`Scale::TAI`](crate::Scale::TAI) |
1130/// | only `on=s` | `target=s` |
1131/// | only `target=t` | `on=TAI` |
1132///
1133/// ## Forms
1134///
1135/// ```text
1136/// from_us!(us)
1137/// from_us!(us, frac)
1138/// from_us!(us, on=s)
1139/// from_us!(us, target=t)
1140/// from_us!(us, on=s, target=t)
1141/// from_us!(us, target=t, on=s)
1142/// from_us!(us, frac, on=s)
1143/// from_us!(us, frac, target=t)
1144/// from_us!(us, frac, on=s, target=t)
1145/// from_us!(us, frac, target=t, on=s)
1146/// ```
1147///
1148/// ## Examples
1149///
1150/// ```
1151/// use deep_time::{Dt, Scale};
1152/// use deep_time::macros::{from_us, ns};
1153///
1154/// // 1.3 µs → whole microseconds + 300 ns remainder
1155/// let a = from_us!(1);
1156/// let b = from_us!(1, ns!(300));
1157/// let c = from_us!(-1, ns!(-300), on=Scale::TAI);
1158/// let d = from_us!(0, on=Scale::UTC);
1159/// let e = from_us!(1, on=Scale::TAI, target=Scale::UTC);
1160/// let f = from_us!(1, target=Scale::UTC);
1161///
1162/// assert_eq!(a, Dt::from_us(1, 0, Scale::TAI, Scale::TAI));
1163/// assert_eq!(b, Dt::from_us(1, ns!(300), Scale::TAI, Scale::TAI));
1164/// assert_eq!(c, Dt::from_us(-1, ns!(-300), Scale::TAI, Scale::TAI));
1165/// assert_eq!(d, Dt::from_us(0, 0, Scale::UTC, Scale::UTC));
1166/// assert_eq!(e, Dt::from_us(1, 0, Scale::TAI, Scale::UTC));
1167/// assert_eq!(f, e);
1168///
1169/// let signed = from_us!(-1, ns!(-300));
1170/// let floor = from_us!(-2, ns!(700));
1171/// assert_eq!(signed, floor);
1172/// assert_eq!(signed, Dt::from_us(-1, ns!(-300), Scale::TAI, Scale::TAI));
1173/// ```
1174#[macro_export]
1175macro_rules! from_us {
1176 ($us:expr, $frac:expr, on=$scale:expr, target=$target:expr) => {
1177 $crate::Dt::from_us($us, $frac, $scale, $target)
1178 };
1179 ($us:expr, $frac:expr, target=$target:expr, on=$scale:expr) => {
1180 $crate::Dt::from_us($us, $frac, $scale, $target)
1181 };
1182 ($us:expr, on=$scale:expr, target=$target:expr) => {
1183 $crate::Dt::from_us($us, 0, $scale, $target)
1184 };
1185 ($us:expr, target=$target:expr, on=$scale:expr) => {
1186 $crate::Dt::from_us($us, 0, $scale, $target)
1187 };
1188 ($us:expr, $frac:expr, on=$scale:expr) => {
1189 $crate::Dt::from_us($us, $frac, $scale, $scale)
1190 };
1191 ($us:expr, $frac:expr, target=$target:expr) => {
1192 $crate::Dt::from_us($us, $frac, $crate::Scale::TAI, $target)
1193 };
1194 ($us:expr, on=$scale:expr) => {
1195 $crate::Dt::from_us($us, 0, $scale, $scale)
1196 };
1197 ($us:expr, target=$target:expr) => {
1198 $crate::Dt::from_us($us, 0, $crate::Scale::TAI, $target)
1199 };
1200 ($us:expr, $frac:expr) => {
1201 $crate::Dt::from_us($us, $frac, $crate::Scale::TAI, $crate::Scale::TAI)
1202 };
1203 ($us:expr) => {
1204 $crate::Dt::from_us($us, 0, $crate::Scale::TAI, $crate::Scale::TAI)
1205 };
1206}
1207
1208/// Builds a [`Dt`](../struct.Dt.html) from whole picoseconds and an optional signed
1209/// fractional remainder in attoseconds.
1210///
1211/// - Equivalent to [`Dt::from_ps`](../struct.Dt.html#method.from_ps).
1212/// - Does **not** perform time-scale conversion.
1213///
1214/// The fractional remainder is in **attoseconds** — use
1215/// [`fs!`](macro.fs.html) (or another `*_to_attos`
1216/// helper) instead of writing the attosecond literal by hand.
1217///
1218/// ## Defaults
1219///
1220/// | Omitted | Default |
1221/// |---------|---------|
1222/// | fraction | `0` |
1223/// | `on` and `target` | both [`Scale::TAI`](crate::Scale::TAI) |
1224/// | only `on=s` | `target=s` |
1225/// | only `target=t` | `on=TAI` |
1226///
1227/// ## Forms
1228///
1229/// ```text
1230/// from_ps!(ps)
1231/// from_ps!(ps, frac)
1232/// from_ps!(ps, on=s)
1233/// from_ps!(ps, target=t)
1234/// from_ps!(ps, on=s, target=t)
1235/// from_ps!(ps, target=t, on=s)
1236/// from_ps!(ps, frac, on=s)
1237/// from_ps!(ps, frac, target=t)
1238/// from_ps!(ps, frac, on=s, target=t)
1239/// from_ps!(ps, frac, target=t, on=s)
1240/// ```
1241///
1242/// ## Examples
1243///
1244/// ```
1245/// use deep_time::{Dt, Scale};
1246/// use deep_time::macros::{from_ps, fs};
1247///
1248/// // 1.3 ps → whole picoseconds + 300 fs remainder
1249/// let a = from_ps!(1);
1250/// let b = from_ps!(1, fs!(300));
1251/// let c = from_ps!(-1, fs!(-300), on=Scale::TAI);
1252/// let d = from_ps!(0, on=Scale::UTC);
1253/// let e = from_ps!(1, on=Scale::TAI, target=Scale::UTC);
1254/// let f = from_ps!(1, target=Scale::UTC);
1255///
1256/// assert_eq!(a, Dt::from_ps(1, 0, Scale::TAI, Scale::TAI));
1257/// assert_eq!(b, Dt::from_ps(1, fs!(300), Scale::TAI, Scale::TAI));
1258/// assert_eq!(c, Dt::from_ps(-1, fs!(-300), Scale::TAI, Scale::TAI));
1259/// assert_eq!(d, Dt::from_ps(0, 0, Scale::UTC, Scale::UTC));
1260/// assert_eq!(e, Dt::from_ps(1, 0, Scale::TAI, Scale::UTC));
1261/// assert_eq!(f, e);
1262///
1263/// let signed = from_ps!(-1, fs!(-300));
1264/// let floor = from_ps!(-2, fs!(700));
1265/// assert_eq!(signed, floor);
1266/// assert_eq!(signed, Dt::from_ps(-1, fs!(-300), Scale::TAI, Scale::TAI));
1267/// ```
1268#[macro_export]
1269macro_rules! from_ps {
1270 ($ps:expr, $frac:expr, on=$scale:expr, target=$target:expr) => {
1271 $crate::Dt::from_ps($ps, $frac, $scale, $target)
1272 };
1273 ($ps:expr, $frac:expr, target=$target:expr, on=$scale:expr) => {
1274 $crate::Dt::from_ps($ps, $frac, $scale, $target)
1275 };
1276 ($ps:expr, on=$scale:expr, target=$target:expr) => {
1277 $crate::Dt::from_ps($ps, 0, $scale, $target)
1278 };
1279 ($ps:expr, target=$target:expr, on=$scale:expr) => {
1280 $crate::Dt::from_ps($ps, 0, $scale, $target)
1281 };
1282 ($ps:expr, $frac:expr, on=$scale:expr) => {
1283 $crate::Dt::from_ps($ps, $frac, $scale, $scale)
1284 };
1285 ($ps:expr, $frac:expr, target=$target:expr) => {
1286 $crate::Dt::from_ps($ps, $frac, $crate::Scale::TAI, $target)
1287 };
1288 ($ps:expr, on=$scale:expr) => {
1289 $crate::Dt::from_ps($ps, 0, $scale, $scale)
1290 };
1291 ($ps:expr, target=$target:expr) => {
1292 $crate::Dt::from_ps($ps, 0, $crate::Scale::TAI, $target)
1293 };
1294 ($ps:expr, $frac:expr) => {
1295 $crate::Dt::from_ps($ps, $frac, $crate::Scale::TAI, $crate::Scale::TAI)
1296 };
1297 ($ps:expr) => {
1298 $crate::Dt::from_ps($ps, 0, $crate::Scale::TAI, $crate::Scale::TAI)
1299 };
1300}
1301
1302/// Builds a [`Dt`](../struct.Dt.html) from whole femtoseconds and an optional signed
1303/// fractional remainder in attoseconds.
1304///
1305/// - Equivalent to [`Dt::from_fs`](../struct.Dt.html#method.from_fs).
1306/// - Does **not** perform time-scale conversion.
1307///
1308/// The fractional remainder is already in **attoseconds** (one femtosecond is
1309/// 1000 attoseconds) — there is no smaller named unit macro.
1310///
1311/// ## Defaults
1312///
1313/// | Omitted | Default |
1314/// |---------|---------|
1315/// | fraction | `0` |
1316/// | `on` and `target` | both [`Scale::TAI`](crate::Scale::TAI) |
1317/// | only `on=s` | `target=s` |
1318/// | only `target=t` | `on=TAI` |
1319///
1320/// ## Forms
1321///
1322/// ```text
1323/// from_fs!(fs)
1324/// from_fs!(fs, frac)
1325/// from_fs!(fs, on=s)
1326/// from_fs!(fs, target=t)
1327/// from_fs!(fs, on=s, target=t)
1328/// from_fs!(fs, target=t, on=s)
1329/// from_fs!(fs, frac, on=s)
1330/// from_fs!(fs, frac, target=t)
1331/// from_fs!(fs, frac, on=s, target=t)
1332/// from_fs!(fs, frac, target=t, on=s)
1333/// ```
1334///
1335/// ## Examples
1336///
1337/// ```
1338/// use deep_time::{Dt, Scale};
1339/// use deep_time::macros::from_fs;
1340///
1341/// // 1.3 fs → whole femtoseconds + 300 attoseconds remainder
1342/// let a = from_fs!(1);
1343/// let b = from_fs!(1, 300);
1344/// let c = from_fs!(-1, -300, on=Scale::TAI);
1345/// let d = from_fs!(0, on=Scale::UTC);
1346/// let e = from_fs!(1, on=Scale::TAI, target=Scale::UTC);
1347/// let f = from_fs!(1, target=Scale::UTC);
1348///
1349/// assert_eq!(a, Dt::from_fs(1, 0, Scale::TAI, Scale::TAI));
1350/// assert_eq!(b, Dt::from_fs(1, 300, Scale::TAI, Scale::TAI));
1351/// assert_eq!(c, Dt::from_fs(-1, -300, Scale::TAI, Scale::TAI));
1352/// assert_eq!(d, Dt::from_fs(0, 0, Scale::UTC, Scale::UTC));
1353/// assert_eq!(e, Dt::from_fs(1, 0, Scale::TAI, Scale::UTC));
1354/// assert_eq!(f, e);
1355///
1356/// let signed = from_fs!(-1, -300);
1357/// let floor = from_fs!(-2, 700);
1358/// assert_eq!(signed, floor);
1359/// assert_eq!(signed, Dt::from_fs(-1, -300, Scale::TAI, Scale::TAI));
1360/// ```
1361#[macro_export]
1362macro_rules! from_fs {
1363 ($fs:expr, $frac:expr, on=$scale:expr, target=$target:expr) => {
1364 $crate::Dt::from_fs($fs, $frac, $scale, $target)
1365 };
1366 ($fs:expr, $frac:expr, target=$target:expr, on=$scale:expr) => {
1367 $crate::Dt::from_fs($fs, $frac, $scale, $target)
1368 };
1369 ($fs:expr, on=$scale:expr, target=$target:expr) => {
1370 $crate::Dt::from_fs($fs, 0, $scale, $target)
1371 };
1372 ($fs:expr, target=$target:expr, on=$scale:expr) => {
1373 $crate::Dt::from_fs($fs, 0, $scale, $target)
1374 };
1375 ($fs:expr, $frac:expr, on=$scale:expr) => {
1376 $crate::Dt::from_fs($fs, $frac, $scale, $scale)
1377 };
1378 ($fs:expr, $frac:expr, target=$target:expr) => {
1379 $crate::Dt::from_fs($fs, $frac, $crate::Scale::TAI, $target)
1380 };
1381 ($fs:expr, on=$scale:expr) => {
1382 $crate::Dt::from_fs($fs, 0, $scale, $scale)
1383 };
1384 ($fs:expr, target=$target:expr) => {
1385 $crate::Dt::from_fs($fs, 0, $crate::Scale::TAI, $target)
1386 };
1387 ($fs:expr, $frac:expr) => {
1388 $crate::Dt::from_fs($fs, $frac, $crate::Scale::TAI, $crate::Scale::TAI)
1389 };
1390 ($fs:expr) => {
1391 $crate::Dt::from_fs($fs, 0, $crate::Scale::TAI, $crate::Scale::TAI)
1392 };
1393}
1394
1395/// Builds a **TAI** [`Dt`](../struct.Dt.html) from a Julian Date (whole days plus
1396/// optional attosecond remainder).
1397///
1398/// Equivalent to [`Dt::from_jd`](../struct.Dt.html#method.from_jd).
1399///
1400/// When an `on` arg is provided and it's not [`Scale::TAI`](crate::Scale::TAI)
1401/// then a time scale conversion is performed equivalent to `on` ->
1402/// [`Scale::TAI`](crate::Scale::TAI).
1403///
1404/// There is no `target=` on this macro — the returned [`Dt`](../struct.Dt.html)'s
1405/// `target` is set from `on` (or TAI when omitted), as
1406/// [`from_jd`](../struct.Dt.html#method.from_jd) does. Chain
1407/// [`.target(…)`](../struct.Dt.html#method.target) if needed.
1408///
1409/// The fractional remainder is in **attoseconds** — use a `*_to_attos` helper
1410/// (e.g. a day fraction built from [`days_f!`](../macro.days_f.html))
1411/// instead of hand-counting zeros when convenient.
1412///
1413/// ## Defaults
1414///
1415/// | Omitted | Default |
1416/// |---------|---------|
1417/// | fraction | `0` |
1418/// | `on` | [`Scale::TAI`](crate::Scale::TAI) |
1419///
1420/// ## Forms
1421///
1422/// ```text
1423/// from_jd!(jd_days)
1424/// from_jd!(jd_days, frac)
1425/// from_jd!(jd_days, on=s)
1426/// from_jd!(jd_days, frac, on=s)
1427/// ```
1428///
1429/// ## Examples
1430///
1431/// ```
1432/// use deep_time::{Dt, Scale};
1433/// use deep_time::macros::{days_f, from_jd};
1434///
1435/// // 2_460_782.25
1436/// let a = from_jd!(2_460_782);
1437/// let b = from_jd!(2_460_782, days_f!(0.25));
1438/// let c = from_jd!(2_460_782, days_f!(0.25), on=Scale::TAI);
1439/// let d = from_jd!(2_460_782, on=Scale::UTC);
1440///
1441/// assert_eq!(a, Dt::from_jd(2_460_782, 0, Scale::TAI));
1442/// assert_eq!(b, Dt::from_jd(2_460_782, days_f!(0.25), Scale::TAI));
1443/// assert_eq!(c, b);
1444/// assert_eq!(d, Dt::from_jd(2_460_782, 0, Scale::UTC));
1445///
1446/// // -1_000.25 (signed remainder)
1447/// let neg = from_jd!(-1_000, -days_f!(0.25));
1448/// assert_eq!(neg, Dt::from_jd(-1_000, -days_f!(0.25), Scale::TAI));
1449/// assert_eq!(neg.to_jd(), (-1_000, -days_f!(0.25)));
1450///
1451/// // or with floor style
1452/// assert_eq!(neg, from_jd!(-1_001, days_f!(0.75)));
1453/// ```
1454#[macro_export]
1455macro_rules! from_jd {
1456 // `on=` arms before bare `$frac:expr` so `on=…` is not taken as an expr.
1457 ($jd_days:expr, $frac:expr, on=$scale:expr) => {
1458 $crate::Dt::from_jd($jd_days, $frac, $scale)
1459 };
1460 ($jd_days:expr, on=$scale:expr) => {
1461 $crate::Dt::from_jd($jd_days, 0, $scale)
1462 };
1463 ($jd_days:expr, $frac:expr) => {
1464 $crate::Dt::from_jd($jd_days, $frac, $crate::Scale::TAI)
1465 };
1466 ($jd_days:expr) => {
1467 $crate::Dt::from_jd($jd_days, 0, $crate::Scale::TAI)
1468 };
1469}
1470
1471/// Builds a **TAI** [`Dt`](../struct.Dt.html) from a floating-point Julian Date.
1472///
1473/// Equivalent to [`Dt::from_jd_f`](../struct.Dt.html#method.from_jd_f).
1474///
1475/// When an `on` arg is provided and it's not [`Scale::TAI`](crate::Scale::TAI)
1476/// then a time scale conversion is performed equivalent to `on` ->
1477/// [`Scale::TAI`](crate::Scale::TAI).
1478///
1479/// There is no `target=` on this macro — the returned [`Dt`](../struct.Dt.html)'s
1480/// `target` is set from `on` (or TAI when omitted), as
1481/// [`from_jd_f`](../struct.Dt.html#method.from_jd_f) does. Chain
1482/// [`.target(…)`](../struct.Dt.html#method.target) if needed.
1483///
1484/// ## Defaults
1485///
1486/// | Omitted | Default |
1487/// |---------|---------|
1488/// | `on` | [`Scale::TAI`](crate::Scale::TAI) |
1489///
1490/// ## Forms
1491///
1492/// ```text
1493/// from_jd_f!(jd)
1494/// from_jd_f!(jd, on=s)
1495/// ```
1496///
1497/// ## Examples
1498///
1499/// ```
1500/// use deep_time::{Dt, Scale};
1501/// use deep_time::macros::{days_f, from_jd_f};
1502///
1503/// // 2_460_782.25
1504/// let a = from_jd_f!(2_460_782.25);
1505/// let b = from_jd_f!(2_460_782.25, on=Scale::TAI);
1506/// let c = from_jd_f!(2_460_782.0, on=Scale::UTC);
1507///
1508/// assert_eq!(a, Dt::from_jd_f(2_460_782.25, Scale::TAI));
1509/// assert_eq!(b, a);
1510/// assert_eq!(c, Dt::from_jd_f(2_460_782.0, Scale::UTC));
1511/// assert_eq!(a.to_jd(), (2_460_782, days_f!(0.25)));
1512///
1513/// // -1_000.25 (signed remainder)
1514/// let neg = from_jd_f!(-1_000.25);
1515/// assert_eq!(neg, Dt::from_jd_f(-1_000.25, Scale::TAI));
1516/// assert_eq!(neg.to_jd(), (-1_000, -days_f!(0.25)));
1517/// ```
1518#[macro_export]
1519macro_rules! from_jd_f {
1520 ($jd:expr, on=$scale:expr) => {
1521 $crate::Dt::from_jd_f($jd, $scale)
1522 };
1523 ($jd:expr) => {
1524 $crate::Dt::from_jd_f($jd, $crate::Scale::TAI)
1525 };
1526}
1527
1528/// Builds a **TAI** [`Dt`](../struct.Dt.html) from a Modified Julian Date (whole days
1529/// plus optional attosecond remainder).
1530///
1531/// Equivalent to [`Dt::from_mjd`](../struct.Dt.html#method.from_mjd).
1532///
1533/// When an `on` arg is provided and it's not [`Scale::TAI`](crate::Scale::TAI)
1534/// then a time scale conversion is performed equivalent to `on` ->
1535/// [`Scale::TAI`](crate::Scale::TAI).
1536///
1537/// There is no `target=` on this macro — the returned [`Dt`](../struct.Dt.html)'s
1538/// `target` is set from `on` (or TAI when omitted), as
1539/// [`from_mjd`](../struct.Dt.html#method.from_mjd) does. Chain
1540/// [`.target(…)`](../struct.Dt.html#method.target) if needed.
1541///
1542/// MJD and JD relate by `JD = MJD + 2_400_000.5`.
1543///
1544/// The fractional remainder is in **attoseconds** — use a `*_to_attos` helper
1545/// (e.g. a day fraction built from [`days_f!`](../macro.days_f.html))
1546/// instead of hand-counting zeros when convenient.
1547///
1548/// ## Defaults
1549///
1550/// | Omitted | Default |
1551/// |---------|---------|
1552/// | fraction | `0` |
1553/// | `on` | [`Scale::TAI`](crate::Scale::TAI) |
1554///
1555/// ## Forms
1556///
1557/// ```text
1558/// from_mjd!(mjd_days)
1559/// from_mjd!(mjd_days, frac)
1560/// from_mjd!(mjd_days, on=s)
1561/// from_mjd!(mjd_days, frac, on=s)
1562/// ```
1563///
1564/// ## Examples
1565///
1566/// ```
1567/// use deep_time::{Dt, Scale};
1568/// use deep_time::macros::{days_f, from_mjd};
1569///
1570/// // J2000.0 → MJD 51_544.5
1571/// let a = from_mjd!(51_544);
1572/// let b = from_mjd!(51_544, days_f!(0.5));
1573/// let c = from_mjd!(51_544, days_f!(0.5), on=Scale::TAI);
1574/// let d = from_mjd!(51_544, on=Scale::UTC);
1575///
1576/// assert_eq!(a, Dt::from_mjd(51_544, 0, Scale::TAI));
1577/// assert_eq!(b, Dt::from_mjd(51_544, days_f!(0.5), Scale::TAI));
1578/// assert_eq!(c, b);
1579/// assert_eq!(d, Dt::from_mjd(51_544, 0, Scale::UTC));
1580/// assert_eq!(b.to_mjd(), (51_544, days_f!(0.5)));
1581///
1582/// // -1_000.25 (signed truncating remainder)
1583/// let neg = from_mjd!(-1_000, -days_f!(0.25));
1584/// assert_eq!(neg, Dt::from_mjd(-1_000, -days_f!(0.25), Scale::TAI));
1585/// assert_eq!(neg.to_mjd(), (-1_000, -days_f!(0.25)));
1586///
1587/// // or with floor style
1588/// assert_eq!(neg, from_mjd!(-1_001, days_f!(0.75)));
1589/// ```
1590#[macro_export]
1591macro_rules! from_mjd {
1592 // `on=` arms before bare `$frac:expr` so `on=…` is not taken as an expr.
1593 ($mjd_days:expr, $frac:expr, on=$scale:expr) => {
1594 $crate::Dt::from_mjd($mjd_days, $frac, $scale)
1595 };
1596 ($mjd_days:expr, on=$scale:expr) => {
1597 $crate::Dt::from_mjd($mjd_days, 0, $scale)
1598 };
1599 ($mjd_days:expr, $frac:expr) => {
1600 $crate::Dt::from_mjd($mjd_days, $frac, $crate::Scale::TAI)
1601 };
1602 ($mjd_days:expr) => {
1603 $crate::Dt::from_mjd($mjd_days, 0, $crate::Scale::TAI)
1604 };
1605}
1606
1607/// Builds a **TAI** [`Dt`](../struct.Dt.html) from a floating-point Modified Julian Date.
1608///
1609/// Equivalent to [`Dt::from_mjd_f`](../struct.Dt.html#method.from_mjd_f).
1610///
1611/// When an `on` arg is provided and it's not [`Scale::TAI`](crate::Scale::TAI)
1612/// then a time scale conversion is performed equivalent to `on` ->
1613/// [`Scale::TAI`](crate::Scale::TAI).
1614///
1615/// There is no `target=` on this macro — the returned [`Dt`](../struct.Dt.html)'s
1616/// `target` is set from `on` (or TAI when omitted), as
1617/// [`from_mjd_f`](../struct.Dt.html#method.from_mjd_f) does. Chain
1618/// [`.target(…)`](../struct.Dt.html#method.target) if needed.
1619///
1620/// MJD and JD relate by `JD = MJD + 2_400_000.5`.
1621///
1622/// ## Defaults
1623///
1624/// | Omitted | Default |
1625/// |---------|---------|
1626/// | `on` | [`Scale::TAI`](crate::Scale::TAI) |
1627///
1628/// ## Forms
1629///
1630/// ```text
1631/// from_mjd_f!(mjd)
1632/// from_mjd_f!(mjd, on=s)
1633/// ```
1634///
1635/// ## Examples
1636///
1637/// ```
1638/// use deep_time::{Dt, Scale};
1639/// use deep_time::macros::{days_f, from_mjd_f};
1640///
1641/// // 60_961.25
1642/// let a = from_mjd_f!(60_961.25);
1643/// let b = from_mjd_f!(60_961.25, on=Scale::TAI);
1644/// let c = from_mjd_f!(60_961.0, on=Scale::UTC);
1645///
1646/// assert_eq!(a, Dt::from_mjd_f(60_961.25, Scale::TAI));
1647/// assert_eq!(b, a);
1648/// assert_eq!(c, Dt::from_mjd_f(60_961.0, Scale::UTC));
1649/// assert_eq!(a.to_mjd_floor(), (60_961, days_f!(0.25)));
1650///
1651/// // -1_000.25 as -1_001 + 0.75 day
1652/// let neg = from_mjd_f!(-1_000.25);
1653/// assert_eq!(neg, Dt::from_mjd_f(-1_000.25, Scale::TAI));
1654/// assert_eq!(neg.to_mjd_floor(), (-1_001, days_f!(0.75)));
1655/// ```
1656#[macro_export]
1657macro_rules! from_mjd_f {
1658 ($mjd:expr, on=$scale:expr) => {
1659 $crate::Dt::from_mjd_f($mjd, $scale)
1660 };
1661 ($mjd:expr) => {
1662 $crate::Dt::from_mjd_f($mjd, $crate::Scale::TAI)
1663 };
1664}
1665
1666/// Builds a [`Dt`](../struct.Dt.html) from a Gregorian calendar date and optional time.
1667///
1668/// Equivalent to [`Dt::from_ymd`](../struct.Dt.html#method.from_ymd).
1669///
1670/// Date fields are positional (`y`, `m`, `d`). Time is optional: put a
1671/// **semicolon after the day**, then hour (required if `;` is present), then
1672/// optional minute, second, and attoseconds. An optional `on=` civil scale may
1673/// follow.
1674///
1675/// A time scale conversion is performed from the `on` arg ->
1676/// [`Scale::TAI`](crate::Scale::TAI).
1677///
1678/// When no `on` arg is used the time scale is assumed to be
1679/// [`Scale::UTC`](crate::Scale::UTC).
1680///
1681/// | Omitted field | Default |
1682/// |---------------|---------|
1683/// | month | `1` |
1684/// | day | `1` |
1685/// | time (no `;`) | `0, 0, 0, 0` |
1686/// | minute / second / attos after `; h` | `0` |
1687/// | `on` | [`Scale::UTC`](crate::Scale::UTC) |
1688///
1689/// The resulting [`Dt`](../struct.Dt.html)'s `target` field is set from that civil
1690/// scale (the `on=` value, or UTC when omitted), as
1691/// [`Dt::from_ymd`](../struct.Dt.html#method.from_ymd) does. There is no `target=` on
1692/// this macro — chain [`.target(…)`](../struct.Dt.html#method.target) if needed.
1693///
1694/// ## Forms
1695///
1696/// ```text
1697/// from_ymd!(y)
1698/// from_ymd!(y, m)
1699/// from_ymd!(y, m, d)
1700/// from_ymd!(y, m, d, on=Scale::TAI)
1701/// from_ymd!(y, m, d; h)
1702/// from_ymd!(y, m, d; h, min)
1703/// from_ymd!(y, m, d; h, min, sec)
1704/// from_ymd!(y, m, d; h, min, sec, attos)
1705/// from_ymd!(y, m, d; h, min, sec, attos, on=Scale::UTC)
1706/// ```
1707///
1708/// ## Examples
1709///
1710/// ```
1711/// use deep_time::Scale;
1712/// use deep_time::macros::from_ymd;
1713///
1714/// assert_eq!(
1715/// from_ymd!(1970),
1716/// deep_time::Dt::UNIX_EPOCH,
1717/// );
1718/// assert_eq!(
1719/// from_ymd!(2026, 6, 16),
1720/// deep_time::Dt::from_ymd(2026, 6, 16, Scale::UTC, 0, 0, 0, 0),
1721/// );
1722/// assert_eq!(
1723/// from_ymd!(2000, 1, 1; 12, on=Scale::TAI),
1724/// deep_time::Dt::ZERO,
1725/// );
1726/// assert_eq!(
1727/// from_ymd!(2000, 1, 1; 12, 0, 0, 123_456_789, on=Scale::UTC),
1728/// deep_time::Dt::from_ymd(2000, 1, 1, Scale::UTC, 12, 0, 0, 123_456_789),
1729/// );
1730///
1731/// // different target field after construction
1732/// let _ = from_ymd!(2020, 1, 1, on=Scale::UTC).target(Scale::TAI);
1733/// ```
1734#[macro_export]
1735macro_rules! from_ymd {
1736 // Time section: `d; h …` — `on=` arms before bare so `on=…` is not an `:expr`.
1737 ($y:expr, $m:expr, $d:expr; $h:expr, $min:expr, $s:expr, $attos:expr, on=$scale:expr) => {
1738 $crate::Dt::from_ymd($y, $m, $d, $scale, $h, $min, $s, $attos)
1739 };
1740 ($y:expr, $m:expr, $d:expr; $h:expr, $min:expr, $s:expr, on=$scale:expr) => {
1741 $crate::Dt::from_ymd($y, $m, $d, $scale, $h, $min, $s, 0)
1742 };
1743 ($y:expr, $m:expr, $d:expr; $h:expr, $min:expr, on=$scale:expr) => {
1744 $crate::Dt::from_ymd($y, $m, $d, $scale, $h, $min, 0, 0)
1745 };
1746 ($y:expr, $m:expr, $d:expr; $h:expr, on=$scale:expr) => {
1747 $crate::Dt::from_ymd($y, $m, $d, $scale, $h, 0, 0, 0)
1748 };
1749 ($y:expr, $m:expr, $d:expr; $h:expr, $min:expr, $s:expr, $attos:expr) => {
1750 $crate::Dt::from_ymd($y, $m, $d, $crate::Scale::UTC, $h, $min, $s, $attos)
1751 };
1752 ($y:expr, $m:expr, $d:expr; $h:expr, $min:expr, $s:expr) => {
1753 $crate::Dt::from_ymd($y, $m, $d, $crate::Scale::UTC, $h, $min, $s, 0)
1754 };
1755 ($y:expr, $m:expr, $d:expr; $h:expr, $min:expr) => {
1756 $crate::Dt::from_ymd($y, $m, $d, $crate::Scale::UTC, $h, $min, 0, 0)
1757 };
1758 ($y:expr, $m:expr, $d:expr; $h:expr) => {
1759 $crate::Dt::from_ymd($y, $m, $d, $crate::Scale::UTC, $h, 0, 0, 0)
1760 };
1761
1762 // Date only (+ optional on=)
1763 ($y:expr, $m:expr, $d:expr, on=$scale:expr) => {
1764 $crate::Dt::from_ymd($y, $m, $d, $scale, 0, 0, 0, 0)
1765 };
1766 ($y:expr, $m:expr, on=$scale:expr) => {
1767 $crate::Dt::from_ymd($y, $m, 1, $scale, 0, 0, 0, 0)
1768 };
1769 ($y:expr, on=$scale:expr) => {
1770 $crate::Dt::from_ymd($y, 1, 1, $scale, 0, 0, 0, 0)
1771 };
1772 ($y:expr, $m:expr, $d:expr) => {
1773 $crate::Dt::from_ymd($y, $m, $d, $crate::Scale::UTC, 0, 0, 0, 0)
1774 };
1775 ($y:expr, $m:expr) => {
1776 $crate::Dt::from_ymd($y, $m, 1, $crate::Scale::UTC, 0, 0, 0, 0)
1777 };
1778 ($y:expr) => {
1779 $crate::Dt::from_ymd($y, 1, 1, $crate::Scale::UTC, 0, 0, 0, 0)
1780 };
1781}
1782
1783#[doc(inline)]
1784pub use crate::{
1785 // attoseconds → unit
1786 as_days,
1787 as_days_f,
1788 as_fs,
1789 as_hours,
1790 as_mins,
1791 as_ms,
1792 as_ns,
1793 as_ps,
1794 as_sec,
1795 as_sec_f,
1796 as_us,
1797 as_weeks,
1798 // unit → attoseconds
1799 days,
1800 days_f,
1801 // constructors
1802 dt,
1803 from_days_f,
1804 from_fs,
1805 from_jd,
1806 from_jd_f,
1807 from_mjd,
1808 from_mjd_f,
1809 from_ms,
1810 from_ns,
1811 from_ps,
1812 from_sec,
1813 from_sec_f,
1814 from_us,
1815 from_ymd,
1816 fs,
1817 hours,
1818 mins,
1819 ms,
1820 ns,
1821 ps,
1822 sec,
1823 sec_f,
1824 us,
1825 weeks,
1826};