1 //Written in the D programming language
2 
3 /++
4     Module containing core time functionality, such as $(LREF Duration) (which
5     represents a duration of time) or $(LREF MonoTime) (which represents a
6     timestamp of the system's monotonic clock).
7 
8     Various functions take a string (or strings) to represent a unit of time
9     (e.g. $(D convert!("days", "hours")(numDays))). The valid strings to use
10     with such functions are "years", "months", "weeks", "days", "hours",
11     "minutes", "seconds", "msecs" (milliseconds), "usecs" (microseconds),
12     "hnsecs" (hecto-nanoseconds - i.e. 100 ns) or some subset thereof. There
13     are a few functions that also allow "nsecs", but very little actually
14     has precision greater than hnsecs.
15 
16     $(BOOKTABLE Cheat Sheet,
17     $(TR $(TH Symbol) $(TH Description))
18     $(LEADINGROW Types)
19     $(TR $(TDNW $(LREF Duration)) $(TD Represents a duration of time of weeks
20     or less (kept internally as hnsecs). (e.g. 22 days or 700 seconds).))
21     $(TR $(TDNW $(LREF TickDuration)) $(TD $(RED DEPRECATED) Represents a duration of time in
22     system clock ticks, using the highest precision that the system provides.))
23     $(TR $(TDNW $(LREF MonoTime)) $(TD Represents a monotonic timestamp in
24     system clock ticks, using the highest precision that the system provides.))
25     $(LEADINGROW Functions)
26     $(TR $(TDNW $(LREF convert)) $(TD Generic way of converting between two time
27     units.))
28     $(TR $(TDNW $(LREF dur)) $(TD Allows constructing a $(LREF Duration) from
29     the given time units with the given length.))
30     $(TR $(TDNW $(LREF weeks)$(NBSP)$(LREF days)$(NBSP)$(LREF hours)$(BR)
31     $(LREF minutes)$(NBSP)$(LREF seconds)$(NBSP)$(LREF msecs)$(BR)
32     $(LREF usecs)$(NBSP)$(LREF hnsecs)$(NBSP)$(LREF nsecs))
33     $(TD Convenience aliases for $(LREF dur).))
34     $(TR $(TDNW $(LREF abs)) $(TD Returns the absolute value of a duration.))
35     )
36 
37     $(BOOKTABLE Conversions,
38     $(TR $(TH )
39      $(TH From $(LREF Duration))
40      $(TH From $(LREF TickDuration))
41      $(TH From units)
42     )
43     $(TR $(TD $(B To $(LREF Duration)))
44      $(TD -)
45      $(TD $(D tickDuration.)$(REF_SHORT to, std,conv)$(D !Duration()))
46      $(TD $(D dur!"msecs"(5)) or $(D 5.msecs()))
47     )
48     $(TR $(TD $(B To $(LREF TickDuration)))
49      $(TD $(D duration.)$(REF_SHORT to, std,conv)$(D !TickDuration()))
50      $(TD -)
51      $(TD $(D TickDuration.from!"msecs"(msecs)))
52     )
53     $(TR $(TD $(B To units))
54      $(TD $(D duration.total!"days"))
55      $(TD $(D tickDuration.msecs))
56      $(TD $(D convert!("days", "msecs")(msecs)))
57     ))
58 
59     Copyright: Copyright 2010 - 2012
60     License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
61     Authors:   $(HTTP jmdavisprog.com, Jonathan M Davis) and Kato Shoichi
62     Source:    $(DRUNTIMESRC core/_time.d)
63     Macros:
64     NBSP= 
65  +/
66 module core.time;
67 
68 import core.exception;
69 import core.stdc.time;
70 import core.stdc.stdio;
71 import core.internal.string;
72 
73 version (Windows)
74 {
75 import core.sys.windows.winbase /+: QueryPerformanceCounter, QueryPerformanceFrequency+/;
76 }
77 else version (Posix)
78 {
79 import core.sys.posix.time;
80 import core.sys.posix.sys.time;
81 } else version (WASI) 
82 {
83 import core.sys.wasi.time;
84 }
85 
86 version (OSX)
87     version = Darwin;
88 else version (iOS)
89     version = Darwin;
90 else version (TVOS)
91     version = Darwin;
92 else version (WatchOS)
93     version = Darwin;
94 
95 //This probably should be moved somewhere else in druntime which
96 //is Darwin-specific.
97 version (Darwin)
98 {
99 
100 public import core.sys.darwin.mach.kern_return;
101 
102 extern(C) nothrow @nogc
103 {
104 
105 struct mach_timebase_info_data_t
106 {
107     uint numer;
108     uint denom;
109 }
110 
111 alias mach_timebase_info_data_t* mach_timebase_info_t;
112 
113 kern_return_t mach_timebase_info(mach_timebase_info_t);
114 
115 ulong mach_absolute_time();
116 
117 }
118 
119 }
120 
121 /++
122     What type of clock to use with $(LREF MonoTime) / $(LREF MonoTimeImpl) or
123     $(D std.datetime.Clock.currTime). They default to $(D ClockType.normal),
124     and most programs do not need to ever deal with the others.
125 
126     The other $(D ClockType)s are provided so that other clocks provided by the
127     underlying C, system calls can be used with $(LREF MonoTimeImpl) or
128     $(D std.datetime.Clock.currTime) without having to use the C API directly.
129 
130     In the case of the monotonic time, $(LREF MonoTimeImpl) is templatized on
131     $(D ClockType), whereas with $(D std.datetime.Clock.currTime), its a runtime
132     argument, since in the case of the monotonic time, the type of the clock
133     affects the resolution of a $(LREF MonoTimeImpl) object, whereas with
134     $(REF SysTime, std,datetime), its resolution is always hecto-nanoseconds
135     regardless of the source of the time.
136 
137     $(D ClockType.normal), $(D ClockType.coarse), and $(D ClockType.precise)
138     work with both $(D Clock.currTime) and $(LREF MonoTimeImpl).
139     $(D ClockType.second) only works with $(D Clock.currTime). The others only
140     work with $(LREF MonoTimeImpl).
141   +/
142 version (CoreDdoc) enum ClockType
143 {
144     /++
145         Use the normal clock.
146       +/
147     normal = 0,
148 
149     /++
150         $(BLUE Linux,OpenBSD-Only)
151 
152         Uses $(D CLOCK_BOOTTIME).
153       +/
154     bootTime = 1,
155 
156     /++
157         Use the coarse clock, not the normal one (e.g. on Linux, that would be
158         $(D CLOCK_REALTIME_COARSE) instead of $(D CLOCK_REALTIME) for
159         $(D clock_gettime) if a function is using the realtime clock). It's
160         generally faster to get the time with the coarse clock than the normal
161         clock, but it's less precise (e.g. 1 msec instead of 1 usec or 1 nsec).
162         Howeover, it $(I is) guaranteed to still have sub-second precision
163         (just not as high as with $(D ClockType.normal)).
164 
165         On systems which do not support a coarser clock,
166         $(D MonoTimeImpl!(ClockType.coarse)) will internally use the same clock
167         as $(D MonoTime) does, and $(D Clock.currTime!(ClockType.coarse)) will
168         use the same clock as $(D Clock.currTime). This is because the coarse
169         clock is doing the same thing as the normal clock (just at lower
170         precision), whereas some of the other clock types
171         (e.g. $(D ClockType.processCPUTime)) mean something fundamentally
172         different. So, treating those as $(D ClockType.normal) on systems where
173         they weren't natively supported would give misleading results.
174 
175         Most programs should not use the coarse clock, exactly because it's
176         less precise, and most programs don't need to get the time often
177         enough to care, but for those rare programs that need to get the time
178         extremely frequently (e.g. hundreds of thousands of times a second) but
179         don't care about high precision, the coarse clock might be appropriate.
180 
181         Currently, only Linux and FreeBSD/DragonFlyBSD support a coarser clock, and on other
182         platforms, it's treated as $(D ClockType.normal).
183       +/
184     coarse = 2,
185 
186     /++
187         Uses a more precise clock than the normal one (which is already very
188         precise), but it takes longer to get the time. Similarly to
189         $(D ClockType.coarse), if it's used on a system that does not support a
190         more precise clock than the normal one, it's treated as equivalent to
191         $(D ClockType.normal).
192 
193         Currently, only FreeBSD/DragonFlyBSD supports a more precise clock, where it uses
194         $(D CLOCK_MONOTONIC_PRECISE) for the monotonic time and
195         $(D CLOCK_REALTIME_PRECISE) for the wall clock time.
196       +/
197     precise = 3,
198 
199     /++
200         $(BLUE Linux,OpenBSD,Solaris-Only)
201 
202         Uses $(D CLOCK_PROCESS_CPUTIME_ID).
203       +/
204     processCPUTime = 4,
205 
206     /++
207         $(BLUE Linux-Only)
208 
209         Uses $(D CLOCK_MONOTONIC_RAW).
210       +/
211     raw = 5,
212 
213     /++
214         Uses a clock that has a precision of one second (contrast to the coarse
215         clock, which has sub-second precision like the normal clock does).
216 
217         FreeBSD/DragonFlyBSD are the only systems which specifically have a clock set up for
218         this (it has $(D CLOCK_SECOND) to use with $(D clock_gettime) which
219         takes advantage of an in-kernel cached value), but on other systems, the
220         fastest function available will be used, and the resulting $(D SysTime)
221         will be rounded down to the second if the clock that was used gave the
222         time at a more precise resolution. So, it's guaranteed that the time
223         will be given at a precision of one second and it's likely the case that
224         will be faster than $(D ClockType.normal), since there tend to be
225         several options on a system to get the time at low resolutions, and they
226         tend to be faster than getting the time at high resolutions.
227 
228         So, the primary difference between $(D ClockType.coarse) and
229         $(D ClockType.second) is that $(D ClockType.coarse) sacrifices some
230         precision in order to get speed but is still fairly precise, whereas
231         $(D ClockType.second) tries to be as fast as possible at the expense of
232         all sub-second precision.
233       +/
234     second = 6,
235 
236     /++
237         $(BLUE Linux,OpenBSD,Solaris-Only)
238 
239         Uses $(D CLOCK_THREAD_CPUTIME_ID).
240       +/
241     threadCPUTime = 7,
242 
243     /++
244         $(BLUE DragonFlyBSD,FreeBSD,OpenBSD-Only)
245 
246         Uses $(D CLOCK_UPTIME).
247       +/
248     uptime = 8,
249 
250     /++
251         $(BLUE FreeBSD-Only)
252 
253         Uses $(D CLOCK_UPTIME_FAST).
254       +/
255     uptimeCoarse = 9,
256 
257     /++
258         $(BLUE FreeBSD-Only)
259 
260         Uses $(D CLOCK_UPTIME_PRECISE).
261       +/
262     uptimePrecise = 10,
263 }
264 else version (Windows) enum ClockType
265 {
266     normal = 0,
267     coarse = 2,
268     precise = 3,
269     second = 6,
270 }
271 else version (Darwin) enum ClockType
272 {
273     normal = 0,
274     coarse = 2,
275     precise = 3,
276     second = 6,
277 }
278 else version (linux) enum ClockType
279 {
280     normal = 0,
281     bootTime = 1,
282     coarse = 2,
283     precise = 3,
284     processCPUTime = 4,
285     raw = 5,
286     second = 6,
287     threadCPUTime = 7,
288 }
289 else version (FreeBSD) enum ClockType
290 {
291     normal = 0,
292     coarse = 2,
293     precise = 3,
294     second = 6,
295     uptime = 8,
296     uptimeCoarse = 9,
297     uptimePrecise = 10,
298 }
299 else version (NetBSD) enum ClockType
300 {
301     normal = 0,
302     coarse = 2,
303     precise = 3,
304     second = 6,
305 }
306 else version (OpenBSD) enum ClockType
307 {
308     normal = 0,
309     bootTime = 1,
310     coarse = 2,
311     precise = 3,
312     processCPUTime = 4,
313     second = 6,
314     threadCPUTime = 7,
315     uptime = 8,
316 }
317 else version (DragonFlyBSD) enum ClockType
318 {
319     normal = 0,
320     coarse = 2,
321     precise = 3,
322     second = 6,
323     uptime = 8,
324     uptimeCoarse = 9,
325     uptimePrecise = 10,
326 }
327 else version (Solaris) enum ClockType
328 {
329     normal = 0,
330     coarse = 2,
331     precise = 3,
332     processCPUTime = 4,
333     second = 6,
334     threadCPUTime = 7,
335 } else version (WASI) enum ClockType
336 {
337     normal = 0,
338     raw = 1,
339     processCPUTime = 2,
340     threadCPUTime = 3
341 }
342 else
343 {
344     // It needs to be decided (and implemented in an appropriate version branch
345     // here) which clock types new platforms are going to support. At minimum,
346     // the ones _not_ marked with $(D Blue Foo-Only) should be supported.
347     static assert(0, "What are the clock types supported by this system?");
348 }
349 
350 // private, used to translate clock type to proper argument to clock_xxx
351 // functions on posix systems
352 version (CoreDdoc)
353     private int _posixClock(ClockType clockType) { return 0; }
354 else
355 version (Posix)
356 {
357     private auto _posixClock(ClockType clockType)
358     {
359         version (linux)
360         {
361             import core.sys.linux.time;
362             with(ClockType) final switch (clockType)
363             {
364             case bootTime: return CLOCK_BOOTTIME;
365             case coarse: return CLOCK_MONOTONIC_COARSE;
366             case normal: return CLOCK_MONOTONIC;
367             case precise: return CLOCK_MONOTONIC;
368             case processCPUTime: return CLOCK_PROCESS_CPUTIME_ID;
369             case raw: return CLOCK_MONOTONIC_RAW;
370             case threadCPUTime: return CLOCK_THREAD_CPUTIME_ID;
371             case second: assert(0);
372             }
373         }
374         else version (FreeBSD)
375         {
376             import core.sys.freebsd.time;
377             with(ClockType) final switch (clockType)
378             {
379             case coarse: return CLOCK_MONOTONIC_FAST;
380             case normal: return CLOCK_MONOTONIC;
381             case precise: return CLOCK_MONOTONIC_PRECISE;
382             case uptime: return CLOCK_UPTIME;
383             case uptimeCoarse: return CLOCK_UPTIME_FAST;
384             case uptimePrecise: return CLOCK_UPTIME_PRECISE;
385             case second: assert(0);
386             }
387         }
388         else version (NetBSD)
389         {
390             import core.sys.netbsd.time;
391             with(ClockType) final switch (clockType)
392             {
393             case coarse: return CLOCK_MONOTONIC;
394             case normal: return CLOCK_MONOTONIC;
395             case precise: return CLOCK_MONOTONIC;
396             case second: assert(0);
397             }
398         }
399         else version (OpenBSD)
400         {
401             import core.sys.openbsd.time;
402             with(ClockType) final switch (clockType)
403             {
404             case bootTime: return CLOCK_BOOTTIME;
405             case coarse: return CLOCK_MONOTONIC;
406             case normal: return CLOCK_MONOTONIC;
407             case precise: return CLOCK_MONOTONIC;
408             case processCPUTime: return CLOCK_PROCESS_CPUTIME_ID;
409             case threadCPUTime: return CLOCK_THREAD_CPUTIME_ID;
410             case uptime: return CLOCK_UPTIME;
411             case second: assert(0);
412             }
413         }
414         else version (DragonFlyBSD)
415         {
416             import core.sys.dragonflybsd.time;
417             with(ClockType) final switch (clockType)
418             {
419             case coarse: return CLOCK_MONOTONIC_FAST;
420             case normal: return CLOCK_MONOTONIC;
421             case precise: return CLOCK_MONOTONIC_PRECISE;
422             case uptime: return CLOCK_UPTIME;
423             case uptimeCoarse: return CLOCK_UPTIME_FAST;
424             case uptimePrecise: return CLOCK_UPTIME_PRECISE;
425             case second: assert(0);
426             }
427         }
428         else version (Solaris)
429         {
430             import core.sys.solaris.time;
431             with(ClockType) final switch (clockType)
432             {
433             case coarse: return CLOCK_MONOTONIC;
434             case normal: return CLOCK_MONOTONIC;
435             case precise: return CLOCK_MONOTONIC;
436             case processCPUTime: return CLOCK_PROCESS_CPUTIME_ID;
437             case threadCPUTime: return CLOCK_THREAD_CPUTIME_ID;
438             case second: assert(0);
439             }
440         }
441         else
442             // It needs to be decided (and implemented in an appropriate
443             // version branch here) which clock types new platforms are going
444             // to support. Also, ClockType's documentation should be updated to
445             // mention it if a new platform uses anything that's not supported
446             // on all platforms..
447             assert(0, "What are the monotonic clock types supported by this system?");
448     }
449 }
450 
451 unittest
452 {
453     // Make sure that the values are the same across platforms.
454     static if (is(typeof(ClockType.normal)))         static assert(ClockType.normal == 0);
455     static if (is(typeof(ClockType.bootTime)))       static assert(ClockType.bootTime == 1);
456     static if (is(typeof(ClockType.coarse)))         static assert(ClockType.coarse == 2);
457     static if (is(typeof(ClockType.precise)))        static assert(ClockType.precise == 3);
458     static if (is(typeof(ClockType.processCPUTime))) static assert(ClockType.processCPUTime == 4);
459     static if (is(typeof(ClockType.raw)))            static assert(ClockType.raw == 5);
460     static if (is(typeof(ClockType.second)))         static assert(ClockType.second == 6);
461     static if (is(typeof(ClockType.threadCPUTime)))  static assert(ClockType.threadCPUTime == 7);
462     static if (is(typeof(ClockType.uptime)))         static assert(ClockType.uptime == 8);
463     static if (is(typeof(ClockType.uptimeCoarse)))   static assert(ClockType.uptimeCoarse == 9);
464     static if (is(typeof(ClockType.uptimePrecise)))  static assert(ClockType.uptimePrecise == 10);
465 }
466 
467 
468 /++
469     Represents a duration of time of weeks or less (kept internally as hnsecs).
470     (e.g. 22 days or 700 seconds).
471 
472     It is used when representing a duration of time - such as how long to
473     sleep with $(REF Thread.sleep, core,thread).
474 
475     In std.datetime, it is also used as the result of various arithmetic
476     operations on time points.
477 
478     Use the $(LREF dur) function or one of its non-generic aliases to create
479     $(D Duration)s.
480 
481     It's not possible to create a Duration of months or years, because the
482     variable number of days in a month or year makes it impossible to convert
483     between months or years and smaller units without a specific date. So,
484     nothing uses $(D Duration)s when dealing with months or years. Rather,
485     functions specific to months and years are defined. For instance,
486     $(REF Date, std,datetime) has $(D add!"years") and $(D add!"months") for adding
487     years and months rather than creating a Duration of years or months and
488     adding that to a $(REF Date, std,datetime). But Duration is used when dealing
489     with weeks or smaller.
490 
491     Examples:
492 --------------------
493 import std.datetime;
494 
495 assert(dur!"days"(12) == dur!"hnsecs"(10_368_000_000_000L));
496 assert(dur!"hnsecs"(27) == dur!"hnsecs"(27));
497 assert(std.datetime.Date(2010, 9, 7) + dur!"days"(5) ==
498        std.datetime.Date(2010, 9, 12));
499 
500 assert(days(-12) == dur!"hnsecs"(-10_368_000_000_000L));
501 assert(hnsecs(-27) == dur!"hnsecs"(-27));
502 assert(std.datetime.Date(2010, 9, 7) - std.datetime.Date(2010, 10, 3) ==
503        days(-26));
504 --------------------
505  +/
506 struct Duration
507 {
508     /++
509         Converts this `Duration` to a `string`.
510 
511         The string is meant to be human readable, not machine parseable (e.g.
512         whether there is an `'s'` on the end of the unit name usually depends on
513         whether it's plural or not, and empty units are not included unless the
514         Duration is `zero`). Any code needing a specific string format should
515         use `total` or `split` to get the units needed to create the desired
516         string format and create the string itself.
517 
518         The format returned by toString may or may not change in the future.
519 
520         Params:
521           sink = A sink object, expected to be a delegate or aggregate
522                  implementing `opCall` that accepts a `scope const(char)[]`
523                  as argument.
524       +/
525     void toString (SinkT) (scope SinkT sink) const scope
526     {
527         static immutable units = [
528             "weeks", "days", "hours", "minutes", "seconds", "msecs", "usecs"
529         ];
530 
531         static void appListSep(SinkT sink, uint pos, bool last)
532         {
533             if (pos == 0)
534                 return;
535             if (!last)
536                 sink(", ");
537             else
538                 sink(pos == 1 ? " and " : ", and ");
539         }
540 
541         static void appUnitVal(string units)(SinkT sink, long val)
542         {
543             immutable plural = val != 1;
544             string unit;
545             static if (units == "seconds")
546                 unit = plural ? "secs" : "sec";
547             else static if (units == "msecs")
548                 unit = "ms";
549             else static if (units == "usecs")
550                 unit = "μs";
551             else
552                 unit = plural ? units : units[0 .. $-1];
553             sink(signedToTempString(val));
554             sink(" ");
555             sink(unit);
556         }
557 
558         if (_hnsecs == 0)
559         {
560             sink("0 hnsecs");
561             return;
562         }
563 
564         long hnsecs = _hnsecs;
565         uint pos;
566         static foreach (unit; units)
567         {
568             if (auto val = splitUnitsFromHNSecs!unit(hnsecs))
569             {
570                 appListSep(sink, pos++, hnsecs == 0);
571                 appUnitVal!unit(sink, val);
572             }
573             if (hnsecs == 0)
574                 return;
575         }
576         if (hnsecs != 0)
577         {
578             appListSep(sink, pos++, true);
579             appUnitVal!"hnsecs"(sink, hnsecs);
580         }
581     }
582 
583 @safe pure:
584 
585 public:
586 
587     /++
588         A $(D Duration) of $(D 0). It's shorter than doing something like
589         $(D dur!"seconds"(0)) and more explicit than $(D Duration.init).
590       +/
591     static @property nothrow @nogc Duration zero() { return Duration(0); }
592 
593     /++
594         Largest $(D Duration) possible.
595       +/
596     static @property nothrow @nogc Duration max() { return Duration(long.max); }
597 
598     /++
599         Most negative $(D Duration) possible.
600       +/
601     static @property nothrow @nogc Duration min() { return Duration(long.min); }
602 
603     version (CoreUnittest) unittest
604     {
605         assert(zero == dur!"seconds"(0));
606         assert(Duration.max == Duration(long.max));
607         assert(Duration.min == Duration(long.min));
608         assert(Duration.min < Duration.zero);
609         assert(Duration.zero < Duration.max);
610         assert(Duration.min < Duration.max);
611         assert(Duration.min - dur!"hnsecs"(1) == Duration.max);
612         assert(Duration.max + dur!"hnsecs"(1) == Duration.min);
613     }
614 
615 
616     /++
617         Compares this $(D Duration) with the given $(D Duration).
618 
619         Returns:
620             $(TABLE
621             $(TR $(TD this &lt; rhs) $(TD &lt; 0))
622             $(TR $(TD this == rhs) $(TD 0))
623             $(TR $(TD this &gt; rhs) $(TD &gt; 0))
624             )
625      +/
626     int opCmp(Duration rhs) const nothrow @nogc
627     {
628         return (_hnsecs > rhs._hnsecs) - (_hnsecs < rhs._hnsecs);
629     }
630 
631     version (CoreUnittest) unittest
632     {
633         import core.internal.traits : rvalueOf;
634         foreach (T; AliasSeq!(Duration, const Duration, immutable Duration))
635         {
636             foreach (U; AliasSeq!(Duration, const Duration, immutable Duration))
637             {
638                 T t = 42;
639                 // workaround https://issues.dlang.org/show_bug.cgi?id=18296
640                 version (D_Coverage)
641                     U u = T(t._hnsecs);
642                 else
643                     U u = t;
644                 assert(t == u);
645                 assert(rvalueOf(t) == u);
646                 assert(t == rvalueOf(u));
647             }
648         }
649 
650         foreach (D; AliasSeq!(Duration, const Duration, immutable Duration))
651         {
652             foreach (E; AliasSeq!(Duration, const Duration, immutable Duration))
653             {
654                 assert((cast(D)Duration(12)).opCmp(cast(E)Duration(12)) == 0);
655                 assert((cast(D)Duration(-12)).opCmp(cast(E)Duration(-12)) == 0);
656 
657                 assert((cast(D)Duration(10)).opCmp(cast(E)Duration(12)) < 0);
658                 assert((cast(D)Duration(-12)).opCmp(cast(E)Duration(12)) < 0);
659 
660                 assert((cast(D)Duration(12)).opCmp(cast(E)Duration(10)) > 0);
661                 assert((cast(D)Duration(12)).opCmp(cast(E)Duration(-12)) > 0);
662 
663                 assert(rvalueOf(cast(D)Duration(12)).opCmp(cast(E)Duration(12)) == 0);
664                 assert(rvalueOf(cast(D)Duration(-12)).opCmp(cast(E)Duration(-12)) == 0);
665 
666                 assert(rvalueOf(cast(D)Duration(10)).opCmp(cast(E)Duration(12)) < 0);
667                 assert(rvalueOf(cast(D)Duration(-12)).opCmp(cast(E)Duration(12)) < 0);
668 
669                 assert(rvalueOf(cast(D)Duration(12)).opCmp(cast(E)Duration(10)) > 0);
670                 assert(rvalueOf(cast(D)Duration(12)).opCmp(cast(E)Duration(-12)) > 0);
671 
672                 assert((cast(D)Duration(12)).opCmp(rvalueOf(cast(E)Duration(12))) == 0);
673                 assert((cast(D)Duration(-12)).opCmp(rvalueOf(cast(E)Duration(-12))) == 0);
674 
675                 assert((cast(D)Duration(10)).opCmp(rvalueOf(cast(E)Duration(12))) < 0);
676                 assert((cast(D)Duration(-12)).opCmp(rvalueOf(cast(E)Duration(12))) < 0);
677 
678                 assert((cast(D)Duration(12)).opCmp(rvalueOf(cast(E)Duration(10))) > 0);
679                 assert((cast(D)Duration(12)).opCmp(rvalueOf(cast(E)Duration(-12))) > 0);
680             }
681         }
682     }
683 
684 
685     /++
686         Adds, subtracts or calculates the modulo of two durations.
687 
688         The legal types of arithmetic for $(D Duration) using this operator are
689 
690         $(TABLE
691         $(TR $(TD Duration) $(TD +) $(TD Duration) $(TD -->) $(TD Duration))
692         $(TR $(TD Duration) $(TD -) $(TD Duration) $(TD -->) $(TD Duration))
693         $(TR $(TD Duration) $(TD %) $(TD Duration) $(TD -->) $(TD Duration))
694         )
695 
696         Params:
697             rhs = The duration to add to or subtract from this $(D Duration).
698       +/
699     Duration opBinary(string op)(const Duration rhs) const nothrow @nogc
700         if (op == "+" || op == "-" || op == "%")
701     {
702         return Duration(mixin("_hnsecs " ~ op ~ " rhs._hnsecs"));
703     }
704 
705     deprecated Duration opBinary(string op)(const TickDuration rhs) const nothrow @nogc
706         if (op == "+" || op == "-")
707     {
708         return Duration(mixin("_hnsecs " ~ op ~ " rhs.hnsecs"));
709     }
710 
711     version (CoreUnittest) unittest
712     {
713         foreach (D; AliasSeq!(Duration, const Duration, immutable Duration))
714         {
715             foreach (E; AliasSeq!(Duration, const Duration, immutable Duration))
716             {
717                 assert((cast(D)Duration(5)) + (cast(E)Duration(7)) == Duration(12));
718                 assert((cast(D)Duration(5)) - (cast(E)Duration(7)) == Duration(-2));
719                 assert((cast(D)Duration(5)) % (cast(E)Duration(7)) == Duration(5));
720                 assert((cast(D)Duration(7)) + (cast(E)Duration(5)) == Duration(12));
721                 assert((cast(D)Duration(7)) - (cast(E)Duration(5)) == Duration(2));
722                 assert((cast(D)Duration(7)) % (cast(E)Duration(5)) == Duration(2));
723 
724                 assert((cast(D)Duration(5)) + (cast(E)Duration(-7)) == Duration(-2));
725                 assert((cast(D)Duration(5)) - (cast(E)Duration(-7)) == Duration(12));
726                 assert((cast(D)Duration(5)) % (cast(E)Duration(-7)) == Duration(5));
727                 assert((cast(D)Duration(7)) + (cast(E)Duration(-5)) == Duration(2));
728                 assert((cast(D)Duration(7)) - (cast(E)Duration(-5)) == Duration(12));
729                 assert((cast(D)Duration(7)) % (cast(E)Duration(-5)) == Duration(2));
730 
731                 assert((cast(D)Duration(-5)) + (cast(E)Duration(7)) == Duration(2));
732                 assert((cast(D)Duration(-5)) - (cast(E)Duration(7)) == Duration(-12));
733                 assert((cast(D)Duration(-5)) % (cast(E)Duration(7)) == Duration(-5));
734                 assert((cast(D)Duration(-7)) + (cast(E)Duration(5)) == Duration(-2));
735                 assert((cast(D)Duration(-7)) - (cast(E)Duration(5)) == Duration(-12));
736                 assert((cast(D)Duration(-7)) % (cast(E)Duration(5)) == Duration(-2));
737 
738                 assert((cast(D)Duration(-5)) + (cast(E)Duration(-7)) == Duration(-12));
739                 assert((cast(D)Duration(-5)) - (cast(E)Duration(-7)) == Duration(2));
740                 assert((cast(D)Duration(-5)) % (cast(E)Duration(7)) == Duration(-5));
741                 assert((cast(D)Duration(-7)) + (cast(E)Duration(-5)) == Duration(-12));
742                 assert((cast(D)Duration(-7)) - (cast(E)Duration(-5)) == Duration(-2));
743                 assert((cast(D)Duration(-7)) % (cast(E)Duration(5)) == Duration(-2));
744             }
745         }
746     }
747 
748     version (CoreUnittest) deprecated unittest
749     {
750         foreach (D; AliasSeq!(Duration, const Duration, immutable Duration))
751         {
752             foreach (T; AliasSeq!(TickDuration, const TickDuration, immutable TickDuration))
753             {
754                 assertApprox((cast(D)Duration(5)) + cast(T)TickDuration.from!"usecs"(7), Duration(70), Duration(80));
755                 assertApprox((cast(D)Duration(5)) - cast(T)TickDuration.from!"usecs"(7), Duration(-70), Duration(-60));
756                 assertApprox((cast(D)Duration(7)) + cast(T)TickDuration.from!"usecs"(5), Duration(52), Duration(62));
757                 assertApprox((cast(D)Duration(7)) - cast(T)TickDuration.from!"usecs"(5), Duration(-48), Duration(-38));
758 
759                 assertApprox((cast(D)Duration(5)) + cast(T)TickDuration.from!"usecs"(-7), Duration(-70), Duration(-60));
760                 assertApprox((cast(D)Duration(5)) - cast(T)TickDuration.from!"usecs"(-7), Duration(70), Duration(80));
761                 assertApprox((cast(D)Duration(7)) + cast(T)TickDuration.from!"usecs"(-5), Duration(-48), Duration(-38));
762                 assertApprox((cast(D)Duration(7)) - cast(T)TickDuration.from!"usecs"(-5), Duration(52), Duration(62));
763 
764                 assertApprox((cast(D)Duration(-5)) + cast(T)TickDuration.from!"usecs"(7), Duration(60), Duration(70));
765                 assertApprox((cast(D)Duration(-5)) - cast(T)TickDuration.from!"usecs"(7), Duration(-80), Duration(-70));
766                 assertApprox((cast(D)Duration(-7)) + cast(T)TickDuration.from!"usecs"(5), Duration(38), Duration(48));
767                 assertApprox((cast(D)Duration(-7)) - cast(T)TickDuration.from!"usecs"(5), Duration(-62), Duration(-52));
768 
769                 assertApprox((cast(D)Duration(-5)) + cast(T)TickDuration.from!"usecs"(-7), Duration(-80), Duration(-70));
770                 assertApprox((cast(D)Duration(-5)) - cast(T)TickDuration.from!"usecs"(-7), Duration(60), Duration(70));
771                 assertApprox((cast(D)Duration(-7)) + cast(T)TickDuration.from!"usecs"(-5), Duration(-62), Duration(-52));
772                 assertApprox((cast(D)Duration(-7)) - cast(T)TickDuration.from!"usecs"(-5), Duration(38), Duration(48));
773             }
774         }
775     }
776 
777 
778     /++
779         $(RED TickDuration is Deprecated)
780 
781         Adds or subtracts two durations.
782 
783         The legal types of arithmetic for $(D Duration) using this operator are
784 
785         $(TABLE
786         $(TR $(TD TickDuration) $(TD +) $(TD Duration) $(TD -->) $(TD Duration))
787         $(TR $(TD TickDuration) $(TD -) $(TD Duration) $(TD -->) $(TD Duration))
788         )
789 
790         Params:
791             lhs = The $(D TickDuration) to add to this $(D Duration) or to
792                   subtract this $(D Duration) from.
793       +/
794     deprecated Duration opBinaryRight(string op, D)(D lhs) const nothrow @nogc
795         if ((op == "+" || op == "-") &&
796             is(immutable D == immutable TickDuration))
797     {
798         return Duration(mixin("lhs.hnsecs " ~ op ~ " _hnsecs"));
799     }
800 
801     version (CoreUnittest) deprecated unittest
802     {
803         foreach (D; AliasSeq!(Duration, const Duration, immutable Duration))
804         {
805             foreach (T; AliasSeq!(TickDuration, const TickDuration, immutable TickDuration))
806             {
807                 assertApprox((cast(T)TickDuration.from!"usecs"(7)) + cast(D)Duration(5), Duration(70), Duration(80));
808                 assertApprox((cast(T)TickDuration.from!"usecs"(7)) - cast(D)Duration(5), Duration(60), Duration(70));
809                 assertApprox((cast(T)TickDuration.from!"usecs"(5)) + cast(D)Duration(7), Duration(52), Duration(62));
810                 assertApprox((cast(T)TickDuration.from!"usecs"(5)) - cast(D)Duration(7), Duration(38), Duration(48));
811 
812                 assertApprox((cast(T)TickDuration.from!"usecs"(-7)) + cast(D)Duration(5), Duration(-70), Duration(-60));
813                 assertApprox((cast(T)TickDuration.from!"usecs"(-7)) - cast(D)Duration(5), Duration(-80), Duration(-70));
814                 assertApprox((cast(T)TickDuration.from!"usecs"(-5)) + cast(D)Duration(7), Duration(-48), Duration(-38));
815                 assertApprox((cast(T)TickDuration.from!"usecs"(-5)) - cast(D)Duration(7), Duration(-62), Duration(-52));
816 
817                 assertApprox((cast(T)TickDuration.from!"usecs"(7)) + (cast(D)Duration(-5)), Duration(60), Duration(70));
818                 assertApprox((cast(T)TickDuration.from!"usecs"(7)) - (cast(D)Duration(-5)), Duration(70), Duration(80));
819                 assertApprox((cast(T)TickDuration.from!"usecs"(5)) + (cast(D)Duration(-7)), Duration(38), Duration(48));
820                 assertApprox((cast(T)TickDuration.from!"usecs"(5)) - (cast(D)Duration(-7)), Duration(52), Duration(62));
821 
822                 assertApprox((cast(T)TickDuration.from!"usecs"(-7)) + cast(D)Duration(-5), Duration(-80), Duration(-70));
823                 assertApprox((cast(T)TickDuration.from!"usecs"(-7)) - cast(D)Duration(-5), Duration(-70), Duration(-60));
824                 assertApprox((cast(T)TickDuration.from!"usecs"(-5)) + cast(D)Duration(-7), Duration(-62), Duration(-52));
825                 assertApprox((cast(T)TickDuration.from!"usecs"(-5)) - cast(D)Duration(-7), Duration(-48), Duration(-38));
826             }
827         }
828     }
829 
830 
831     /++
832         Adds, subtracts or calculates the modulo of two durations as well as
833         assigning the result to this $(D Duration).
834 
835         The legal types of arithmetic for $(D Duration) using this operator are
836 
837         $(TABLE
838         $(TR $(TD Duration) $(TD +) $(TD Duration) $(TD -->) $(TD Duration))
839         $(TR $(TD Duration) $(TD -) $(TD Duration) $(TD -->) $(TD Duration))
840         $(TR $(TD Duration) $(TD %) $(TD Duration) $(TD -->) $(TD Duration))
841         )
842 
843         Params:
844             rhs = The duration to add to or subtract from this $(D Duration).
845       +/
846     ref Duration opOpAssign(string op)(const Duration rhs) nothrow @nogc
847         if (op == "+" || op == "-" || op == "%")
848     {
849         mixin("_hnsecs " ~ op ~ "= rhs._hnsecs;");
850         return this;
851     }
852 
853     deprecated ref Duration opOpAssign(string op)(const TickDuration rhs) nothrow @nogc
854         if (op == "+" || op == "-")
855     {
856         mixin("_hnsecs " ~ op ~ "= rhs.hnsecs;");
857         return this;
858     }
859 
860     version (CoreUnittest) unittest
861     {
862         static void test1(string op, E)(Duration actual, in E rhs, Duration expected, size_t line = __LINE__)
863         {
864             if (mixin("actual " ~ op ~ " rhs") != expected)
865                 throw new AssertError("op failed", __FILE__, line);
866 
867             if (actual != expected)
868                 throw new AssertError("op assign failed", __FILE__, line);
869         }
870 
871         foreach (E; AliasSeq!(Duration, const Duration, immutable Duration))
872         {
873             test1!"+="(Duration(5), (cast(E)Duration(7)), Duration(12));
874             test1!"-="(Duration(5), (cast(E)Duration(7)), Duration(-2));
875             test1!"%="(Duration(5), (cast(E)Duration(7)), Duration(5));
876             test1!"+="(Duration(7), (cast(E)Duration(5)), Duration(12));
877             test1!"-="(Duration(7), (cast(E)Duration(5)), Duration(2));
878             test1!"%="(Duration(7), (cast(E)Duration(5)), Duration(2));
879 
880             test1!"+="(Duration(5), (cast(E)Duration(-7)), Duration(-2));
881             test1!"-="(Duration(5), (cast(E)Duration(-7)), Duration(12));
882             test1!"%="(Duration(5), (cast(E)Duration(-7)), Duration(5));
883             test1!"+="(Duration(7), (cast(E)Duration(-5)), Duration(2));
884             test1!"-="(Duration(7), (cast(E)Duration(-5)), Duration(12));
885             test1!"%="(Duration(7), (cast(E)Duration(-5)), Duration(2));
886 
887             test1!"+="(Duration(-5), (cast(E)Duration(7)), Duration(2));
888             test1!"-="(Duration(-5), (cast(E)Duration(7)), Duration(-12));
889             test1!"%="(Duration(-5), (cast(E)Duration(7)), Duration(-5));
890             test1!"+="(Duration(-7), (cast(E)Duration(5)), Duration(-2));
891             test1!"-="(Duration(-7), (cast(E)Duration(5)), Duration(-12));
892             test1!"%="(Duration(-7), (cast(E)Duration(5)), Duration(-2));
893 
894             test1!"+="(Duration(-5), (cast(E)Duration(-7)), Duration(-12));
895             test1!"-="(Duration(-5), (cast(E)Duration(-7)), Duration(2));
896             test1!"%="(Duration(-5), (cast(E)Duration(-7)), Duration(-5));
897             test1!"+="(Duration(-7), (cast(E)Duration(-5)), Duration(-12));
898             test1!"-="(Duration(-7), (cast(E)Duration(-5)), Duration(-2));
899             test1!"%="(Duration(-7), (cast(E)Duration(-5)), Duration(-2));
900         }
901 
902         foreach (D; AliasSeq!(const Duration, immutable Duration))
903         {
904             foreach (E; AliasSeq!(Duration, const Duration, immutable Duration))
905             {
906                 D lhs = D(120);
907                 E rhs = E(120);
908                 static assert(!__traits(compiles, lhs += rhs), D.stringof ~ " " ~ E.stringof);
909             }
910         }
911     }
912 
913     version (CoreUnittest) deprecated unittest
914     {
915         static void test2(string op, E)
916                          (Duration actual, in E rhs, Duration lower, Duration upper, size_t line = __LINE__)
917         {
918             assertApprox(mixin("actual " ~ op ~ " rhs"), lower, upper, "op failed", line);
919             assertApprox(actual, lower, upper, "op assign failed", line);
920         }
921 
922         foreach (T; AliasSeq!(TickDuration, const TickDuration, immutable TickDuration))
923         {
924             test2!"+="(Duration(5), cast(T)TickDuration.from!"usecs"(7), Duration(70), Duration(80));
925             test2!"-="(Duration(5), cast(T)TickDuration.from!"usecs"(7), Duration(-70), Duration(-60));
926             test2!"+="(Duration(7), cast(T)TickDuration.from!"usecs"(5), Duration(52), Duration(62));
927             test2!"-="(Duration(7), cast(T)TickDuration.from!"usecs"(5), Duration(-48), Duration(-38));
928 
929             test2!"+="(Duration(5), cast(T)TickDuration.from!"usecs"(-7), Duration(-70), Duration(-60));
930             test2!"-="(Duration(5), cast(T)TickDuration.from!"usecs"(-7), Duration(70), Duration(80));
931             test2!"+="(Duration(7), cast(T)TickDuration.from!"usecs"(-5), Duration(-48), Duration(-38));
932             test2!"-="(Duration(7), cast(T)TickDuration.from!"usecs"(-5), Duration(52), Duration(62));
933 
934             test2!"+="(Duration(-5), cast(T)TickDuration.from!"usecs"(7), Duration(60), Duration(70));
935             test2!"-="(Duration(-5), cast(T)TickDuration.from!"usecs"(7), Duration(-80), Duration(-70));
936             test2!"+="(Duration(-7), cast(T)TickDuration.from!"usecs"(5), Duration(38), Duration(48));
937             test2!"-="(Duration(-7), cast(T)TickDuration.from!"usecs"(5), Duration(-62), Duration(-52));
938 
939             test2!"+="(Duration(-5), cast(T)TickDuration.from!"usecs"(-7), Duration(-80), Duration(-70));
940             test2!"-="(Duration(-5), cast(T)TickDuration.from!"usecs"(-7), Duration(60), Duration(70));
941             test2!"+="(Duration(-7), cast(T)TickDuration.from!"usecs"(-5), Duration(-62), Duration(-52));
942             test2!"-="(Duration(-7), cast(T)TickDuration.from!"usecs"(-5), Duration(38), Duration(48));
943         }
944 
945         foreach (D; AliasSeq!(const Duration, immutable Duration))
946         {
947             foreach (E; AliasSeq!(TickDuration, const TickDuration, immutable TickDuration))
948             {
949                 D lhs = D(120);
950                 E rhs = E(120);
951                 static assert(!__traits(compiles, lhs += rhs), D.stringof ~ " " ~ E.stringof);
952             }
953         }
954     }
955 
956 
957     /++
958         Multiplies or divides the duration by an integer value.
959 
960         The legal types of arithmetic for $(D Duration) using this operator
961         overload are
962 
963         $(TABLE
964         $(TR $(TD Duration) $(TD *) $(TD long) $(TD -->) $(TD Duration))
965         $(TR $(TD Duration) $(TD /) $(TD long) $(TD -->) $(TD Duration))
966         )
967 
968         Params:
969             value = The value to multiply this $(D Duration) by.
970       +/
971     Duration opBinary(string op)(long value) const nothrow @nogc
972         if (op == "*" || op == "/")
973     {
974         mixin("return Duration(_hnsecs " ~ op ~ " value);");
975     }
976 
977     version (CoreUnittest) unittest
978     {
979         foreach (D; AliasSeq!(Duration, const Duration, immutable Duration))
980         {
981             assert((cast(D)Duration(5)) * 7 == Duration(35));
982             assert((cast(D)Duration(7)) * 5 == Duration(35));
983 
984             assert((cast(D)Duration(5)) * -7 == Duration(-35));
985             assert((cast(D)Duration(7)) * -5 == Duration(-35));
986 
987             assert((cast(D)Duration(-5)) * 7 == Duration(-35));
988             assert((cast(D)Duration(-7)) * 5 == Duration(-35));
989 
990             assert((cast(D)Duration(-5)) * -7 == Duration(35));
991             assert((cast(D)Duration(-7)) * -5 == Duration(35));
992 
993             assert((cast(D)Duration(5)) * 0 == Duration(0));
994             assert((cast(D)Duration(-5)) * 0 == Duration(0));
995         }
996     }
997 
998     version (CoreUnittest) unittest
999     {
1000         foreach (D; AliasSeq!(Duration, const Duration, immutable Duration))
1001         {
1002             assert((cast(D)Duration(5)) / 7 == Duration(0));
1003             assert((cast(D)Duration(7)) / 5 == Duration(1));
1004 
1005             assert((cast(D)Duration(5)) / -7 == Duration(0));
1006             assert((cast(D)Duration(7)) / -5 == Duration(-1));
1007 
1008             assert((cast(D)Duration(-5)) / 7 == Duration(0));
1009             assert((cast(D)Duration(-7)) / 5 == Duration(-1));
1010 
1011             assert((cast(D)Duration(-5)) / -7 == Duration(0));
1012             assert((cast(D)Duration(-7)) / -5 == Duration(1));
1013         }
1014     }
1015 
1016 
1017     /++
1018         Multiplies/Divides the duration by an integer value as well as
1019         assigning the result to this $(D Duration).
1020 
1021         The legal types of arithmetic for $(D Duration) using this operator
1022         overload are
1023 
1024         $(TABLE
1025         $(TR $(TD Duration) $(TD *) $(TD long) $(TD -->) $(TD Duration))
1026         $(TR $(TD Duration) $(TD /) $(TD long) $(TD -->) $(TD Duration))
1027         )
1028 
1029         Params:
1030             value = The value to multiply/divide this $(D Duration) by.
1031       +/
1032     ref Duration opOpAssign(string op)(long value) nothrow @nogc
1033         if (op == "*" || op == "/")
1034     {
1035         mixin("_hnsecs " ~ op ~ "= value;");
1036         return this;
1037     }
1038 
1039     version (CoreUnittest) unittest
1040     {
1041         static void test(D)(D actual, long value, Duration expected, size_t line = __LINE__)
1042         {
1043             if ((actual *= value) != expected)
1044                 throw new AssertError("op failed", __FILE__, line);
1045 
1046             if (actual != expected)
1047                 throw new AssertError("op assign failed", __FILE__, line);
1048         }
1049 
1050         test(Duration(5), 7, Duration(35));
1051         test(Duration(7), 5, Duration(35));
1052 
1053         test(Duration(5), -7, Duration(-35));
1054         test(Duration(7), -5, Duration(-35));
1055 
1056         test(Duration(-5), 7, Duration(-35));
1057         test(Duration(-7), 5, Duration(-35));
1058 
1059         test(Duration(-5), -7, Duration(35));
1060         test(Duration(-7), -5, Duration(35));
1061 
1062         test(Duration(5), 0, Duration(0));
1063         test(Duration(-5), 0, Duration(0));
1064 
1065         const cdur = Duration(12);
1066         immutable idur = Duration(12);
1067         static assert(!__traits(compiles, cdur *= 12));
1068         static assert(!__traits(compiles, idur *= 12));
1069     }
1070 
1071     version (CoreUnittest) unittest
1072     {
1073         static void test(Duration actual, long value, Duration expected, size_t line = __LINE__)
1074         {
1075             if ((actual /= value) != expected)
1076                 throw new AssertError("op failed", __FILE__, line);
1077 
1078             if (actual != expected)
1079                 throw new AssertError("op assign failed", __FILE__, line);
1080         }
1081 
1082         test(Duration(5), 7, Duration(0));
1083         test(Duration(7), 5, Duration(1));
1084 
1085         test(Duration(5), -7, Duration(0));
1086         test(Duration(7), -5, Duration(-1));
1087 
1088         test(Duration(-5), 7, Duration(0));
1089         test(Duration(-7), 5, Duration(-1));
1090 
1091         test(Duration(-5), -7, Duration(0));
1092         test(Duration(-7), -5, Duration(1));
1093 
1094         const cdur = Duration(12);
1095         immutable idur = Duration(12);
1096         static assert(!__traits(compiles, cdur /= 12));
1097         static assert(!__traits(compiles, idur /= 12));
1098     }
1099 
1100 
1101     /++
1102         Divides two durations.
1103 
1104         The legal types of arithmetic for $(D Duration) using this operator are
1105 
1106         $(TABLE
1107         $(TR $(TD Duration) $(TD /) $(TD Duration) $(TD -->) $(TD long))
1108         )
1109 
1110         Params:
1111             rhs = The duration to divide this $(D Duration) by.
1112       +/
1113     long opBinary(string op)(Duration rhs) const nothrow @nogc
1114         if (op == "/")
1115     {
1116         return _hnsecs / rhs._hnsecs;
1117     }
1118 
1119     version (CoreUnittest) unittest
1120     {
1121         assert(Duration(5) / Duration(7) == 0);
1122         assert(Duration(7) / Duration(5) == 1);
1123         assert(Duration(8) / Duration(4) == 2);
1124 
1125         assert(Duration(5) / Duration(-7) == 0);
1126         assert(Duration(7) / Duration(-5) == -1);
1127         assert(Duration(8) / Duration(-4) == -2);
1128 
1129         assert(Duration(-5) / Duration(7) == 0);
1130         assert(Duration(-7) / Duration(5) == -1);
1131         assert(Duration(-8) / Duration(4) == -2);
1132 
1133         assert(Duration(-5) / Duration(-7) == 0);
1134         assert(Duration(-7) / Duration(-5) == 1);
1135         assert(Duration(-8) / Duration(-4) == 2);
1136     }
1137 
1138 
1139     /++
1140         Multiplies an integral value and a $(D Duration).
1141 
1142         The legal types of arithmetic for $(D Duration) using this operator
1143         overload are
1144 
1145         $(TABLE
1146         $(TR $(TD long) $(TD *) $(TD Duration) $(TD -->) $(TD Duration))
1147         )
1148 
1149         Params:
1150             value = The number of units to multiply this $(D Duration) by.
1151       +/
1152     Duration opBinaryRight(string op)(long value) const nothrow @nogc
1153         if (op == "*")
1154     {
1155         return opBinary!op(value);
1156     }
1157 
1158     version (CoreUnittest) unittest
1159     {
1160         foreach (D; AliasSeq!(Duration, const Duration, immutable Duration))
1161         {
1162             assert(5 * cast(D)Duration(7) == Duration(35));
1163             assert(7 * cast(D)Duration(5) == Duration(35));
1164 
1165             assert(5 * cast(D)Duration(-7) == Duration(-35));
1166             assert(7 * cast(D)Duration(-5) == Duration(-35));
1167 
1168             assert(-5 * cast(D)Duration(7) == Duration(-35));
1169             assert(-7 * cast(D)Duration(5) == Duration(-35));
1170 
1171             assert(-5 * cast(D)Duration(-7) == Duration(35));
1172             assert(-7 * cast(D)Duration(-5) == Duration(35));
1173 
1174             assert(0 * cast(D)Duration(-5) == Duration(0));
1175             assert(0 * cast(D)Duration(5) == Duration(0));
1176         }
1177     }
1178 
1179 
1180     /++
1181         Returns the negation of this $(D Duration).
1182       +/
1183     Duration opUnary(string op)() const nothrow @nogc
1184         if (op == "-")
1185     {
1186         return Duration(-_hnsecs);
1187     }
1188 
1189     version (CoreUnittest) unittest
1190     {
1191         foreach (D; AliasSeq!(Duration, const Duration, immutable Duration))
1192         {
1193             assert(-(cast(D)Duration(7)) == Duration(-7));
1194             assert(-(cast(D)Duration(5)) == Duration(-5));
1195             assert(-(cast(D)Duration(-7)) == Duration(7));
1196             assert(-(cast(D)Duration(-5)) == Duration(5));
1197             assert(-(cast(D)Duration(0)) == Duration(0));
1198         }
1199     }
1200 
1201 
1202     /++
1203         $(RED TickDuration is Deprecated)
1204 
1205         Returns a $(LREF TickDuration) with the same number of hnsecs as this
1206         $(D Duration).
1207         Note that the conventional way to convert between $(D Duration) and
1208         $(D TickDuration) is using $(REF to, std,conv), e.g.:
1209         $(D duration.to!TickDuration())
1210       +/
1211     deprecated TickDuration opCast(T)() const nothrow @nogc
1212         if (is(immutable T == immutable TickDuration))
1213     {
1214         return TickDuration.from!"hnsecs"(_hnsecs);
1215     }
1216 
1217     version (CoreUnittest) deprecated unittest
1218     {
1219         foreach (D; AliasSeq!(Duration, const Duration, immutable Duration))
1220         {
1221             foreach (units; AliasSeq!("seconds", "msecs", "usecs", "hnsecs"))
1222             {
1223                 enum unitsPerSec = convert!("seconds", units)(1);
1224 
1225                 if (TickDuration.ticksPerSec >= unitsPerSec)
1226                 {
1227                     foreach (T; AliasSeq!(TickDuration, const TickDuration, immutable TickDuration))
1228                     {
1229                         auto t = TickDuration.from!units(1);
1230                         assertApprox(cast(T)cast(D)dur!units(1), t - TickDuration(1), t + TickDuration(1), units);
1231                         t = TickDuration.from!units(2);
1232                         assertApprox(cast(T)cast(D)dur!units(2), t - TickDuration(1), t + TickDuration(1), units);
1233                     }
1234                 }
1235                 else
1236                 {
1237                     auto t = TickDuration.from!units(1);
1238                     assert(t.to!(units, long)() == 0, units);
1239                     t = TickDuration.from!units(1_000_000);
1240                     assert(t.to!(units, long)() >= 900_000, units);
1241                     assert(t.to!(units, long)() <= 1_100_000, units);
1242                 }
1243             }
1244         }
1245     }
1246 
1247     /++
1248         Allow Duration to be used as a boolean.
1249         Returns: `true` if this duration is non-zero.
1250       +/
1251     bool opCast(T : bool)() const nothrow @nogc
1252     {
1253         return _hnsecs != 0;
1254     }
1255 
1256     version (CoreUnittest) unittest
1257     {
1258         auto d = 10.minutes;
1259         assert(d);
1260         assert(!(d - d));
1261         assert(d + d);
1262     }
1263 
1264     //Temporary hack until bug http://d.puremagic.com/issues/show_bug.cgi?id=5747 is fixed.
1265     Duration opCast(T)() const nothrow @nogc
1266         if (is(immutable T == immutable Duration))
1267     {
1268         return this;
1269     }
1270 
1271 
1272     /++
1273         Splits out the Duration into the given units.
1274 
1275         split takes the list of time units to split out as template arguments.
1276         The time unit strings must be given in decreasing order. How it returns
1277         the values for those units depends on the overload used.
1278 
1279         The overload which accepts function arguments takes integral types in
1280         the order that the time unit strings were given, and those integers are
1281         passed by $(D ref). split assigns the values for the units to each
1282         corresponding integer. Any integral type may be used, but no attempt is
1283         made to prevent integer overflow, so don't use small integral types in
1284         circumstances where the values for those units aren't likely to fit in
1285         an integral type that small.
1286 
1287         The overload with no arguments returns the values for the units in a
1288         struct with members whose names are the same as the given time unit
1289         strings. The members are all $(D long)s. This overload will also work
1290         with no time strings being given, in which case $(I all) of the time
1291         units from weeks through hnsecs will be provided (but no nsecs, since it
1292         would always be $(D 0)).
1293 
1294         For both overloads, the entire value of the Duration is split among the
1295         units (rather than splitting the Duration across all units and then only
1296         providing the values for the requested units), so if only one unit is
1297         given, the result is equivalent to $(LREF total).
1298 
1299         $(D "nsecs") is accepted by split, but $(D "years") and $(D "months")
1300         are not.
1301 
1302         For negative durations, all of the split values will be negative.
1303       +/
1304     template split(units...)
1305         if (allAreAcceptedUnits!("weeks", "days", "hours", "minutes", "seconds",
1306                                 "msecs", "usecs", "hnsecs", "nsecs")([units]) &&
1307            unitsAreInDescendingOrder([units]))
1308     {
1309         /++ Ditto +/
1310         void split(Args...)(out Args args) const nothrow @nogc
1311             if (units.length != 0 && args.length == units.length && allAreMutableIntegralTypes!Args)
1312         {
1313             long hnsecs = _hnsecs;
1314             foreach (i, unit; units)
1315             {
1316                 static if (unit == "nsecs")
1317                     args[i] = cast(Args[i])convert!("hnsecs", "nsecs")(hnsecs);
1318                 else
1319                     args[i] = cast(Args[i])splitUnitsFromHNSecs!unit(hnsecs);
1320             }
1321         }
1322 
1323         /++ Ditto +/
1324         auto split() const nothrow @nogc
1325         {
1326             static if (units.length == 0)
1327                 return split!("weeks", "days", "hours", "minutes", "seconds", "msecs", "usecs", "hnsecs")();
1328             else
1329             {
1330                 static string genMemberDecls()
1331                 {
1332                     string retval;
1333                     foreach (unit; units)
1334                     {
1335                         retval ~= "long ";
1336                         retval ~= unit;
1337                         retval ~= "; ";
1338                     }
1339                     return retval;
1340                 }
1341 
1342                 static struct SplitUnits
1343                 {
1344                     mixin(genMemberDecls());
1345                 }
1346 
1347                 static string genSplitCall()
1348                 {
1349                     auto retval = "split(";
1350                     foreach (i, unit; units)
1351                     {
1352                         retval ~= "su.";
1353                         retval ~= unit;
1354                         if (i < units.length - 1)
1355                             retval ~= ", ";
1356                         else
1357                             retval ~= ");";
1358                     }
1359                     return retval;
1360                 }
1361 
1362                 SplitUnits su = void;
1363                 mixin(genSplitCall());
1364                 return su;
1365             }
1366         }
1367 
1368         /+
1369             Whether all of the given arguments are integral types.
1370           +/
1371         private template allAreMutableIntegralTypes(Args...)
1372         {
1373             static if (Args.length == 0)
1374                 enum allAreMutableIntegralTypes = true;
1375             else static if (!is(Args[0] == long) &&
1376                            !is(Args[0] == int) &&
1377                            !is(Args[0] == short) &&
1378                            !is(Args[0] == byte) &&
1379                            !is(Args[0] == ulong) &&
1380                            !is(Args[0] == uint) &&
1381                            !is(Args[0] == ushort) &&
1382                            !is(Args[0] == ubyte))
1383             {
1384                 enum allAreMutableIntegralTypes = false;
1385             }
1386             else
1387                 enum allAreMutableIntegralTypes = allAreMutableIntegralTypes!(Args[1 .. $]);
1388         }
1389 
1390         version (CoreUnittest) unittest
1391         {
1392             foreach (T; AliasSeq!(long, int, short, byte, ulong, uint, ushort, ubyte))
1393                 static assert(allAreMutableIntegralTypes!T);
1394             foreach (T; AliasSeq!(long, int, short, byte, ulong, uint, ushort, ubyte))
1395                 static assert(!allAreMutableIntegralTypes!(const T));
1396             foreach (T; AliasSeq!(char, wchar, dchar, float, double, real, string))
1397                 static assert(!allAreMutableIntegralTypes!T);
1398             static assert(allAreMutableIntegralTypes!(long, int, short, byte));
1399             static assert(!allAreMutableIntegralTypes!(long, int, short, char, byte));
1400             static assert(!allAreMutableIntegralTypes!(long, int*, short));
1401         }
1402     }
1403 
1404     ///
1405     unittest
1406     {
1407         {
1408             auto d = dur!"days"(12) + dur!"minutes"(7) + dur!"usecs"(501223);
1409             long days;
1410             int seconds;
1411             short msecs;
1412             d.split!("days", "seconds", "msecs")(days, seconds, msecs);
1413             assert(days == 12);
1414             assert(seconds == 7 * 60);
1415             assert(msecs == 501);
1416 
1417             auto splitStruct = d.split!("days", "seconds", "msecs")();
1418             assert(splitStruct.days == 12);
1419             assert(splitStruct.seconds == 7 * 60);
1420             assert(splitStruct.msecs == 501);
1421 
1422             auto fullSplitStruct = d.split();
1423             assert(fullSplitStruct.weeks == 1);
1424             assert(fullSplitStruct.days == 5);
1425             assert(fullSplitStruct.hours == 0);
1426             assert(fullSplitStruct.minutes == 7);
1427             assert(fullSplitStruct.seconds == 0);
1428             assert(fullSplitStruct.msecs == 501);
1429             assert(fullSplitStruct.usecs == 223);
1430             assert(fullSplitStruct.hnsecs == 0);
1431 
1432             assert(d.split!"minutes"().minutes == d.total!"minutes");
1433         }
1434 
1435         {
1436             auto d = dur!"days"(12);
1437             assert(d.split!"weeks"().weeks == 1);
1438             assert(d.split!"days"().days == 12);
1439 
1440             assert(d.split().weeks == 1);
1441             assert(d.split().days == 5);
1442         }
1443 
1444         {
1445             auto d = dur!"days"(7) + dur!"hnsecs"(42);
1446             assert(d.split!("seconds", "nsecs")().nsecs == 4200);
1447         }
1448 
1449         {
1450             auto d = dur!"days"(-7) + dur!"hours"(-9);
1451             auto result = d.split!("days", "hours")();
1452             assert(result.days == -7);
1453             assert(result.hours == -9);
1454         }
1455     }
1456 
1457     version (CoreUnittest) pure nothrow unittest
1458     {
1459         foreach (D; AliasSeq!(const Duration, immutable Duration))
1460         {
1461             D d = dur!"weeks"(3) + dur!"days"(5) + dur!"hours"(19) + dur!"minutes"(7) +
1462                   dur!"seconds"(2) + dur!"hnsecs"(1234567);
1463             byte weeks;
1464             ubyte days;
1465             short hours;
1466             ushort minutes;
1467             int seconds;
1468             uint msecs;
1469             long usecs;
1470             ulong hnsecs;
1471             long nsecs;
1472 
1473             d.split!("weeks", "days", "hours", "minutes", "seconds", "msecs", "usecs", "hnsecs", "nsecs")
1474                     (weeks, days, hours, minutes, seconds, msecs, usecs, hnsecs, nsecs);
1475             assert(weeks == 3);
1476             assert(days == 5);
1477             assert(hours == 19);
1478             assert(minutes == 7);
1479             assert(seconds == 2);
1480             assert(msecs == 123);
1481             assert(usecs == 456);
1482             assert(hnsecs == 7);
1483             assert(nsecs == 0);
1484 
1485             d.split!("weeks", "days", "hours", "seconds", "usecs")(weeks, days, hours, seconds, usecs);
1486             assert(weeks == 3);
1487             assert(days == 5);
1488             assert(hours == 19);
1489             assert(seconds == 422);
1490             assert(usecs == 123456);
1491 
1492             d.split!("days", "minutes", "seconds", "nsecs")(days, minutes, seconds, nsecs);
1493             assert(days == 26);
1494             assert(minutes == 1147);
1495             assert(seconds == 2);
1496             assert(nsecs == 123456700);
1497 
1498             d.split!("minutes", "msecs", "usecs", "hnsecs")(minutes, msecs, usecs, hnsecs);
1499             assert(minutes == 38587);
1500             assert(msecs == 2123);
1501             assert(usecs == 456);
1502             assert(hnsecs == 7);
1503 
1504             {
1505                 auto result = d.split!("weeks", "days", "hours", "minutes", "seconds",
1506                                        "msecs", "usecs", "hnsecs", "nsecs");
1507                 assert(result.weeks == 3);
1508                 assert(result.days == 5);
1509                 assert(result.hours == 19);
1510                 assert(result.minutes == 7);
1511                 assert(result.seconds == 2);
1512                 assert(result.msecs == 123);
1513                 assert(result.usecs == 456);
1514                 assert(result.hnsecs == 7);
1515                 assert(result.nsecs == 0);
1516             }
1517 
1518             {
1519                 auto result = d.split!("weeks", "days", "hours", "seconds", "usecs");
1520                 assert(result.weeks == 3);
1521                 assert(result.days == 5);
1522                 assert(result.hours == 19);
1523                 assert(result.seconds == 422);
1524                 assert(result.usecs == 123456);
1525             }
1526 
1527             {
1528                 auto result = d.split!("days", "minutes", "seconds", "nsecs")();
1529                 assert(result.days == 26);
1530                 assert(result.minutes == 1147);
1531                 assert(result.seconds == 2);
1532                 assert(result.nsecs == 123456700);
1533             }
1534 
1535             {
1536                 auto result = d.split!("minutes", "msecs", "usecs", "hnsecs")();
1537                 assert(result.minutes == 38587);
1538                 assert(result.msecs == 2123);
1539                 assert(result.usecs == 456);
1540                 assert(result.hnsecs == 7);
1541             }
1542 
1543             {
1544                 auto result = d.split();
1545                 assert(result.weeks == 3);
1546                 assert(result.days == 5);
1547                 assert(result.hours == 19);
1548                 assert(result.minutes == 7);
1549                 assert(result.seconds == 2);
1550                 assert(result.msecs == 123);
1551                 assert(result.usecs == 456);
1552                 assert(result.hnsecs == 7);
1553                 static assert(!is(typeof(result.nsecs)));
1554             }
1555 
1556             static assert(!is(typeof(d.split("seconds", "hnsecs")(seconds))));
1557             static assert(!is(typeof(d.split("hnsecs", "seconds", "minutes")(hnsecs, seconds, minutes))));
1558             static assert(!is(typeof(d.split("hnsecs", "seconds", "msecs")(hnsecs, seconds, msecs))));
1559             static assert(!is(typeof(d.split("seconds", "hnecs", "msecs")(seconds, hnsecs, msecs))));
1560             static assert(!is(typeof(d.split("seconds", "msecs", "msecs")(seconds, msecs, msecs))));
1561             static assert(!is(typeof(d.split("hnsecs", "seconds", "minutes")())));
1562             static assert(!is(typeof(d.split("hnsecs", "seconds", "msecs")())));
1563             static assert(!is(typeof(d.split("seconds", "hnecs", "msecs")())));
1564             static assert(!is(typeof(d.split("seconds", "msecs", "msecs")())));
1565             alias AliasSeq!("nsecs", "hnsecs", "usecs", "msecs", "seconds",
1566                               "minutes", "hours", "days", "weeks") timeStrs;
1567             foreach (i, str; timeStrs[1 .. $])
1568                 static assert(!is(typeof(d.split!(timeStrs[i - 1], str)())));
1569 
1570             D nd = -d;
1571 
1572             {
1573                 auto result = nd.split();
1574                 assert(result.weeks == -3);
1575                 assert(result.days == -5);
1576                 assert(result.hours == -19);
1577                 assert(result.minutes == -7);
1578                 assert(result.seconds == -2);
1579                 assert(result.msecs == -123);
1580                 assert(result.usecs == -456);
1581                 assert(result.hnsecs == -7);
1582             }
1583 
1584             {
1585                 auto result = nd.split!("weeks", "days", "hours", "minutes", "seconds", "nsecs")();
1586                 assert(result.weeks == -3);
1587                 assert(result.days == -5);
1588                 assert(result.hours == -19);
1589                 assert(result.minutes == -7);
1590                 assert(result.seconds == -2);
1591                 assert(result.nsecs == -123456700);
1592             }
1593         }
1594     }
1595 
1596 
1597     /++
1598         Returns the total number of the given units in this $(D Duration).
1599         So, unlike $(D split), it does not strip out the larger units.
1600       +/
1601     @property long total(string units)() const nothrow @nogc
1602         if (units == "weeks" ||
1603            units == "days" ||
1604            units == "hours" ||
1605            units == "minutes" ||
1606            units == "seconds" ||
1607            units == "msecs" ||
1608            units == "usecs" ||
1609            units == "hnsecs" ||
1610            units == "nsecs")
1611     {
1612         return convert!("hnsecs", units)(_hnsecs);
1613     }
1614 
1615     ///
1616     unittest
1617     {
1618         assert(dur!"weeks"(12).total!"weeks" == 12);
1619         assert(dur!"weeks"(12).total!"days" == 84);
1620 
1621         assert(dur!"days"(13).total!"weeks" == 1);
1622         assert(dur!"days"(13).total!"days" == 13);
1623 
1624         assert(dur!"hours"(49).total!"days" == 2);
1625         assert(dur!"hours"(49).total!"hours" == 49);
1626 
1627         assert(dur!"nsecs"(2007).total!"hnsecs" == 20);
1628         assert(dur!"nsecs"(2007).total!"nsecs" == 2000);
1629     }
1630 
1631     version (CoreUnittest) unittest
1632     {
1633         foreach (D; AliasSeq!(const Duration, immutable Duration))
1634         {
1635             assert((cast(D)dur!"weeks"(12)).total!"weeks" == 12);
1636             assert((cast(D)dur!"weeks"(12)).total!"days" == 84);
1637 
1638             assert((cast(D)dur!"days"(13)).total!"weeks" == 1);
1639             assert((cast(D)dur!"days"(13)).total!"days" == 13);
1640 
1641             assert((cast(D)dur!"hours"(49)).total!"days" == 2);
1642             assert((cast(D)dur!"hours"(49)).total!"hours" == 49);
1643 
1644             assert((cast(D)dur!"nsecs"(2007)).total!"hnsecs" == 20);
1645             assert((cast(D)dur!"nsecs"(2007)).total!"nsecs" == 2000);
1646         }
1647     }
1648 
1649     /// Ditto
1650     string toString() const scope nothrow
1651     {
1652         string result;
1653         this.toString((in char[] data) { result ~= data; });
1654         return result;
1655     }
1656 
1657     ///
1658     unittest
1659     {
1660         assert(Duration.zero.toString() == "0 hnsecs");
1661         assert(weeks(5).toString() == "5 weeks");
1662         assert(days(2).toString() == "2 days");
1663         assert(hours(1).toString() == "1 hour");
1664         assert(minutes(19).toString() == "19 minutes");
1665         assert(seconds(42).toString() == "42 secs");
1666         assert(msecs(42).toString() == "42 ms");
1667         assert(usecs(27).toString() == "27 μs");
1668         assert(hnsecs(5).toString() == "5 hnsecs");
1669 
1670         assert(seconds(121).toString() == "2 minutes and 1 sec");
1671         assert((minutes(5) + seconds(3) + usecs(4)).toString() ==
1672                "5 minutes, 3 secs, and 4 μs");
1673 
1674         assert(seconds(-42).toString() == "-42 secs");
1675         assert(usecs(-5239492).toString() == "-5 secs, -239 ms, and -492 μs");
1676     }
1677 
1678     version (CoreUnittest) unittest
1679     {
1680         foreach (D; AliasSeq!(Duration, const Duration, immutable Duration))
1681         {
1682             assert((cast(D)Duration(0)).toString() == "0 hnsecs");
1683             assert((cast(D)Duration(1)).toString() == "1 hnsec");
1684             assert((cast(D)Duration(7)).toString() == "7 hnsecs");
1685             assert((cast(D)Duration(10)).toString() == "1 μs");
1686             assert((cast(D)Duration(20)).toString() == "2 μs");
1687             assert((cast(D)Duration(10_000)).toString() == "1 ms");
1688             assert((cast(D)Duration(20_000)).toString() == "2 ms");
1689             assert((cast(D)Duration(10_000_000)).toString() == "1 sec");
1690             assert((cast(D)Duration(20_000_000)).toString() == "2 secs");
1691             assert((cast(D)Duration(600_000_000)).toString() == "1 minute");
1692             assert((cast(D)Duration(1_200_000_000)).toString() == "2 minutes");
1693             assert((cast(D)Duration(36_000_000_000)).toString() == "1 hour");
1694             assert((cast(D)Duration(72_000_000_000)).toString() == "2 hours");
1695             assert((cast(D)Duration(864_000_000_000)).toString() == "1 day");
1696             assert((cast(D)Duration(1_728_000_000_000)).toString() == "2 days");
1697             assert((cast(D)Duration(6_048_000_000_000)).toString() == "1 week");
1698             assert((cast(D)Duration(12_096_000_000_000)).toString() == "2 weeks");
1699 
1700             assert((cast(D)Duration(12)).toString() == "1 μs and 2 hnsecs");
1701             assert((cast(D)Duration(120_795)).toString() == "12 ms, 79 μs, and 5 hnsecs");
1702             assert((cast(D)Duration(12_096_020_900_003)).toString() == "2 weeks, 2 secs, 90 ms, and 3 hnsecs");
1703 
1704             assert((cast(D)Duration(-1)).toString() == "-1 hnsecs");
1705             assert((cast(D)Duration(-7)).toString() == "-7 hnsecs");
1706             assert((cast(D)Duration(-10)).toString() == "-1 μs");
1707             assert((cast(D)Duration(-20)).toString() == "-2 μs");
1708             assert((cast(D)Duration(-10_000)).toString() == "-1 ms");
1709             assert((cast(D)Duration(-20_000)).toString() == "-2 ms");
1710             assert((cast(D)Duration(-10_000_000)).toString() == "-1 secs");
1711             assert((cast(D)Duration(-20_000_000)).toString() == "-2 secs");
1712             assert((cast(D)Duration(-600_000_000)).toString() == "-1 minutes");
1713             assert((cast(D)Duration(-1_200_000_000)).toString() == "-2 minutes");
1714             assert((cast(D)Duration(-36_000_000_000)).toString() == "-1 hours");
1715             assert((cast(D)Duration(-72_000_000_000)).toString() == "-2 hours");
1716             assert((cast(D)Duration(-864_000_000_000)).toString() == "-1 days");
1717             assert((cast(D)Duration(-1_728_000_000_000)).toString() == "-2 days");
1718             assert((cast(D)Duration(-6_048_000_000_000)).toString() == "-1 weeks");
1719             assert((cast(D)Duration(-12_096_000_000_000)).toString() == "-2 weeks");
1720 
1721             assert((cast(D)Duration(-12)).toString() == "-1 μs and -2 hnsecs");
1722             assert((cast(D)Duration(-120_795)).toString() == "-12 ms, -79 μs, and -5 hnsecs");
1723             assert((cast(D)Duration(-12_096_020_900_003)).toString() == "-2 weeks, -2 secs, -90 ms, and -3 hnsecs");
1724         }
1725     }
1726 
1727 
1728     /++
1729         Returns whether this $(D Duration) is negative.
1730       +/
1731     @property bool isNegative() const nothrow @nogc
1732     {
1733         return _hnsecs < 0;
1734     }
1735 
1736     version (CoreUnittest) unittest
1737     {
1738         foreach (D; AliasSeq!(Duration, const Duration, immutable Duration))
1739         {
1740             assert(!(cast(D)Duration(100)).isNegative);
1741             assert(!(cast(D)Duration(1)).isNegative);
1742             assert(!(cast(D)Duration(0)).isNegative);
1743             assert((cast(D)Duration(-1)).isNegative);
1744             assert((cast(D)Duration(-100)).isNegative);
1745         }
1746     }
1747 
1748 
1749 private:
1750 
1751     /+
1752         Params:
1753             hnsecs = The total number of hecto-nanoseconds in this $(D Duration).
1754       +/
1755     this(long hnsecs) nothrow @nogc
1756     {
1757         _hnsecs = hnsecs;
1758     }
1759 
1760 
1761     long _hnsecs;
1762 }
1763 
1764 ///
1765 unittest
1766 {
1767     import core.time;
1768 
1769     // using the dur template
1770     auto numDays = dur!"days"(12);
1771 
1772     // using the days function
1773     numDays = days(12);
1774 
1775     // alternatively using UFCS syntax
1776     numDays = 12.days;
1777 
1778     auto myTime = 100.msecs + 20_000.usecs + 30_000.hnsecs;
1779     assert(myTime == 123.msecs);
1780 }
1781 
1782 // Ensure `toString` doesn't allocate if the sink doesn't
1783 version (CoreUnittest) @safe pure nothrow @nogc unittest
1784 {
1785     char[256] buffer; size_t len;
1786     scope sink = (in char[] data) {
1787         assert(data.length + len <= buffer.length);
1788         buffer[len .. len + data.length] = data[];
1789         len += data.length;
1790     };
1791     auto dur = Duration(-12_096_020_900_003);
1792     dur.toString(sink);
1793     assert(buffer[0 .. len] == "-2 weeks, -2 secs, -90 ms, and -3 hnsecs");
1794 }
1795 
1796 /++
1797     $(RED TickDuration is DEPRECATED)
1798 
1799     Converts a $(D TickDuration) to the given units as either an integral
1800     value or a floating point value.
1801 
1802     Params:
1803         units = The units to convert to. Accepts $(D "seconds") and smaller
1804                 only.
1805         T     = The type to convert to (either an integral type or a
1806                 floating point type).
1807 
1808         td    = The TickDuration to convert
1809   +/
1810 deprecated("TickDuration has been deprecated, please use Duration or MonoTime instead")
1811 T to(string units, T, D)(D td) @safe pure nothrow @nogc
1812     if (is(immutable D == immutable TickDuration) &&
1813        (units == "seconds" ||
1814         units == "msecs" ||
1815         units == "usecs" ||
1816         units == "hnsecs" ||
1817         units == "nsecs"))
1818 {
1819     static if (__traits(isIntegral, T) && T.sizeof >= 4)
1820     {
1821         enum unitsPerSec = convert!("seconds", units)(1);
1822 
1823         return cast(T) (td.length / (TickDuration.ticksPerSec / cast(real) unitsPerSec));
1824     }
1825     else static if (__traits(isFloating, T))
1826     {
1827         static if (units == "seconds")
1828             return td.length / cast(T)TickDuration.ticksPerSec;
1829         else
1830         {
1831             enum unitsPerSec = convert!("seconds", units)(1);
1832 
1833             return cast(T) (td.length /
1834                 (TickDuration.ticksPerSec / cast(real) unitsPerSec));
1835         }
1836     }
1837     else
1838         static assert(0, "Incorrect template constraint.");
1839 }
1840 
1841 ///
1842 deprecated unittest
1843 {
1844     auto t = TickDuration.from!"seconds"(1000);
1845 
1846     long tl = to!("seconds",long)(t);
1847     assert(tl == 1000);
1848 
1849     import core.stdc.math : fabs;
1850     double td = to!("seconds",double)(t);
1851     assert(fabs(td - 1000) < 0.001);
1852 }
1853 
1854 deprecated unittest
1855 {
1856     void testFun(string U)() {
1857         auto t1v = 1000;
1858         auto t2v = 333;
1859 
1860         auto t1 = TickDuration.from!U(t1v);
1861         auto t2 = TickDuration.from!U(t2v);
1862 
1863         auto _str(F)(F val)
1864         {
1865             static if (is(F == int) || is(F == long))
1866                 return signedToTempString(val);
1867             else
1868                 return unsignedToTempString(val);
1869         }
1870 
1871         foreach (F; AliasSeq!(int,uint,long,ulong,float,double,real))
1872         {
1873             F t1f = to!(U,F)(t1);
1874             F t2f = to!(U,F)(t2);
1875             auto t12d = t1 / t2v;
1876             auto t12m = t1 - t2;
1877             F t3f = to!(U,F)(t12d);
1878             F t4f = to!(U,F)(t12m);
1879 
1880 
1881             static if (is(F == float) || is(F == double) || is(F == real))
1882             {
1883                 assert((t1f - cast(F)t1v) <= 3.0,
1884                     F.stringof ~ " " ~ U ~ " " ~ doubleToString(t1f) ~ " " ~
1885                     doubleToString(cast(F)t1v)
1886                 );
1887                 assert((t2f - cast(F)t2v) <= 3.0,
1888                     F.stringof ~ " " ~ U ~ " " ~ doubleToString(t2f) ~ " " ~
1889                     doubleToString(cast(F)t2v)
1890                 );
1891                 assert(t3f - (cast(F)t1v) / (cast(F)t2v) <= 3.0,
1892                     F.stringof ~ " " ~ U ~ " " ~ doubleToString(t3f) ~ " " ~
1893                     doubleToString((cast(F)t1v)/(cast(F)t2v))
1894                 );
1895                 assert(t4f - (cast(F)(t1v - t2v)) <= 3.0,
1896                     F.stringof ~ " " ~ U ~ " " ~ doubleToString(t4f) ~ " " ~
1897                     doubleToString(cast(F)(t1v - t2v))
1898                 );
1899             }
1900             else
1901             {
1902                 // even though this should be exact math it is not as internal
1903                 // in "to" floating point is used
1904                 assert(_abs(t1f) - _abs(cast(F)t1v) <= 3,
1905                     F.stringof ~ " " ~ U ~ " " ~ _str(t1f) ~ " " ~
1906                     _str(cast(F)t1v)
1907                 );
1908                 assert(_abs(t2f) - _abs(cast(F)t2v) <= 3,
1909                     F.stringof ~ " " ~ U ~ " " ~ _str(t2f) ~ " " ~
1910                     _str(cast(F)t2v)
1911                 );
1912                 assert(_abs(t3f) - _abs((cast(F)t1v) / (cast(F)t2v)) <= 3,
1913                     F.stringof ~ " " ~ U ~ " " ~ _str(t3f) ~ " " ~
1914                     _str((cast(F)t1v) / (cast(F)t2v))
1915                 );
1916                 assert(_abs(t4f) - _abs((cast(F)t1v) - (cast(F)t2v)) <= 3,
1917                     F.stringof ~ " " ~ U ~ " " ~ _str(t4f) ~ " " ~
1918                     _str((cast(F)t1v) - (cast(F)t2v))
1919                 );
1920             }
1921         }
1922     }
1923 
1924     testFun!"seconds"();
1925     testFun!"msecs"();
1926     testFun!"usecs"();
1927 }
1928 
1929 /++
1930     These allow you to construct a $(D Duration) from the given time units
1931     with the given length.
1932 
1933     You can either use the generic function $(D dur) and give it the units as
1934     a $(D string) or use the named aliases.
1935 
1936     The possible values for units are $(D "weeks"), $(D "days"), $(D "hours"),
1937     $(D "minutes"), $(D "seconds"), $(D "msecs") (milliseconds), $(D "usecs"),
1938     (microseconds), $(D "hnsecs") (hecto-nanoseconds, i.e. 100 ns), and
1939     $(D "nsecs").
1940 
1941     Params:
1942         units  = The time units of the $(D Duration) (e.g. $(D "days")).
1943         length = The number of units in the $(D Duration).
1944   +/
1945 Duration dur(string units)(long length) @safe pure nothrow @nogc
1946     if (units == "weeks" ||
1947        units == "days" ||
1948        units == "hours" ||
1949        units == "minutes" ||
1950        units == "seconds" ||
1951        units == "msecs" ||
1952        units == "usecs" ||
1953        units == "hnsecs" ||
1954        units == "nsecs")
1955 {
1956     return Duration(convert!(units, "hnsecs")(length));
1957 }
1958 
1959 alias weeks   = dur!"weeks";   /// Ditto
1960 alias days    = dur!"days";    /// Ditto
1961 alias hours   = dur!"hours";   /// Ditto
1962 alias minutes = dur!"minutes"; /// Ditto
1963 alias seconds = dur!"seconds"; /// Ditto
1964 alias msecs   = dur!"msecs";   /// Ditto
1965 alias usecs   = dur!"usecs";   /// Ditto
1966 alias hnsecs  = dur!"hnsecs";  /// Ditto
1967 alias nsecs   = dur!"nsecs";   /// Ditto
1968 
1969 ///
1970 unittest
1971 {
1972     // Generic
1973     assert(dur!"weeks"(142).total!"weeks" == 142);
1974     assert(dur!"days"(142).total!"days" == 142);
1975     assert(dur!"hours"(142).total!"hours" == 142);
1976     assert(dur!"minutes"(142).total!"minutes" == 142);
1977     assert(dur!"seconds"(142).total!"seconds" == 142);
1978     assert(dur!"msecs"(142).total!"msecs" == 142);
1979     assert(dur!"usecs"(142).total!"usecs" == 142);
1980     assert(dur!"hnsecs"(142).total!"hnsecs" == 142);
1981     assert(dur!"nsecs"(142).total!"nsecs" == 100);
1982 
1983     // Non-generic
1984     assert(weeks(142).total!"weeks" == 142);
1985     assert(days(142).total!"days" == 142);
1986     assert(hours(142).total!"hours" == 142);
1987     assert(minutes(142).total!"minutes" == 142);
1988     assert(seconds(142).total!"seconds" == 142);
1989     assert(msecs(142).total!"msecs" == 142);
1990     assert(usecs(142).total!"usecs" == 142);
1991     assert(hnsecs(142).total!"hnsecs" == 142);
1992     assert(nsecs(142).total!"nsecs" == 100);
1993 }
1994 
1995 unittest
1996 {
1997     foreach (D; AliasSeq!(Duration, const Duration, immutable Duration))
1998     {
1999         assert(dur!"weeks"(7).total!"weeks" == 7);
2000         assert(dur!"days"(7).total!"days" == 7);
2001         assert(dur!"hours"(7).total!"hours" == 7);
2002         assert(dur!"minutes"(7).total!"minutes" == 7);
2003         assert(dur!"seconds"(7).total!"seconds" == 7);
2004         assert(dur!"msecs"(7).total!"msecs" == 7);
2005         assert(dur!"usecs"(7).total!"usecs" == 7);
2006         assert(dur!"hnsecs"(7).total!"hnsecs" == 7);
2007         assert(dur!"nsecs"(7).total!"nsecs" == 0);
2008 
2009         assert(dur!"weeks"(1007) == weeks(1007));
2010         assert(dur!"days"(1007) == days(1007));
2011         assert(dur!"hours"(1007) == hours(1007));
2012         assert(dur!"minutes"(1007) == minutes(1007));
2013         assert(dur!"seconds"(1007) == seconds(1007));
2014         assert(dur!"msecs"(1007) == msecs(1007));
2015         assert(dur!"usecs"(1007) == usecs(1007));
2016         assert(dur!"hnsecs"(1007) == hnsecs(1007));
2017         assert(dur!"nsecs"(10) == nsecs(10));
2018     }
2019 }
2020 
2021 // used in MonoTimeImpl
2022 private string _clockTypeName(ClockType clockType)
2023 {
2024     final switch (clockType)
2025     {
2026         foreach (name; __traits(allMembers, ClockType))
2027         {
2028         case __traits(getMember, ClockType, name):
2029             return name;
2030         }
2031     }
2032     assert(0);
2033 }
2034 
2035 // used in MonoTimeImpl
2036 private size_t _clockTypeIdx(ClockType clockType)
2037 {
2038     final switch (clockType)
2039     {
2040         foreach (i, name; __traits(allMembers, ClockType))
2041         {
2042         case __traits(getMember, ClockType, name):
2043             return i;
2044         }
2045     }
2046     assert(0);
2047 }
2048 
2049 
2050 /++
2051     alias for $(D MonoTimeImpl) instantiated with $(D ClockType.normal). This is
2052     what most programs should use. It's also what much of $(D MonoTimeImpl) uses
2053     in its documentation (particularly in the examples), because that's what's
2054     going to be used in most code.
2055   +/
2056 alias MonoTime = MonoTimeImpl!(ClockType.normal);
2057 
2058 /++
2059     Represents a timestamp of the system's monotonic clock.
2060 
2061     A monotonic clock is one which always goes forward and never moves
2062     backwards, unlike the system's wall clock time (as represented by
2063     $(REF SysTime, std,datetime)). The system's wall clock time can be adjusted
2064     by the user or by the system itself via services such as NTP, so it is
2065     unreliable to use the wall clock time for timing. Timers which use the wall
2066     clock time could easily end up never going off due to changes made to the
2067     wall clock time or otherwise waiting for a different period of time than
2068     that specified by the programmer. However, because the monotonic clock
2069     always increases at a fixed rate and is not affected by adjustments to the
2070     wall clock time, it is ideal for use with timers or anything which requires
2071     high precision timing.
2072 
2073     So, MonoTime should be used for anything involving timers and timing,
2074     whereas $(REF SysTime, std,datetime) should be used when the wall clock time
2075     is required.
2076 
2077     The monotonic clock has no relation to wall clock time. Rather, it holds
2078     its time as the number of ticks of the clock which have occurred since the
2079     clock started (typically when the system booted up). So, to determine how
2080     much time has passed between two points in time, one monotonic time is
2081     subtracted from the other to determine the number of ticks which occurred
2082     between the two points of time, and those ticks are divided by the number of
2083     ticks that occur every second (as represented by MonoTime.ticksPerSecond)
2084     to get a meaningful duration of time. Normally, MonoTime does these
2085     calculations for the programmer, but the $(D ticks) and $(D ticksPerSecond)
2086     properties are provided for those who require direct access to the system
2087     ticks. The normal way that MonoTime would be used is
2088 
2089 --------------------
2090     MonoTime before = MonoTime.currTime;
2091     // do stuff...
2092     MonoTime after = MonoTime.currTime;
2093     Duration timeElapsed = after - before;
2094 --------------------
2095 
2096     $(LREF MonoTime) is an alias to $(D MonoTimeImpl!(ClockType.normal)) and is
2097     what most programs should use for the monotonic clock, so that's what is
2098     used in most of $(D MonoTimeImpl)'s documentation. But $(D MonoTimeImpl)
2099     can be instantiated with other clock types for those rare programs that need
2100     it.
2101 
2102     See_Also:
2103         $(LREF ClockType)
2104   +/
2105 struct MonoTimeImpl(ClockType clockType)
2106 {
2107     private enum _clockIdx = _clockTypeIdx(clockType);
2108     private enum _clockName = _clockTypeName(clockType);
2109 
2110 @safe:
2111 
2112     version (Windows)
2113     {
2114         static if (clockType != ClockType.coarse &&
2115                   clockType != ClockType.normal &&
2116                   clockType != ClockType.precise)
2117         {
2118             static assert(0, "ClockType." ~ _clockName ~
2119                              " is not supported by MonoTimeImpl on this system.");
2120         }
2121     }
2122     else version (Darwin)
2123     {
2124         static if (clockType != ClockType.coarse &&
2125                   clockType != ClockType.normal &&
2126                   clockType != ClockType.precise)
2127         {
2128             static assert(0, "ClockType." ~ _clockName ~
2129                              " is not supported by MonoTimeImpl on this system.");
2130         }
2131     }
2132     else version (Posix)
2133     {
2134         enum clockArg = _posixClock(clockType);
2135     }
2136     else version (WASI)
2137     {
2138         static if (clockType != ClockType.normal &&
2139                   clockType != ClockType.raw)
2140         {
2141             static assert(0, "ClockType." ~ _clockName ~
2142                              " is not supported by MonoTimeImpl on this system.");
2143         }
2144     }
2145     else static assert(0, "Unsupported platform");
2146 
2147     // POD value, test mutable/const/immutable conversion
2148     version (CoreUnittest) unittest
2149     {
2150         MonoTimeImpl m;
2151         const MonoTimeImpl cm = m;
2152         immutable MonoTimeImpl im = m;
2153         m = cm;
2154         m = im;
2155     }
2156 
2157     /++
2158         The current time of the system's monotonic clock. This has no relation
2159         to the wall clock time, as the wall clock time can be adjusted (e.g.
2160         by NTP), whereas the monotonic clock always moves forward. The source
2161         of the monotonic time is system-specific.
2162 
2163         On Windows, $(D QueryPerformanceCounter) is used. On Mac OS X,
2164         $(D mach_absolute_time) is used, while on other POSIX systems,
2165         $(D clock_gettime) is used.
2166 
2167         $(RED Warning): On some systems, the monotonic clock may stop counting
2168                         when the computer goes to sleep or hibernates. So, the
2169                         monotonic clock may indicate less time than has actually
2170                         passed if that occurs. This is known to happen on
2171                         Mac OS X. It has not been tested whether it occurs on
2172                         either Windows or Linux.
2173       +/
2174     static @property MonoTimeImpl currTime() @trusted nothrow @nogc
2175     {
2176         if (ticksPerSecond == 0)
2177         {
2178             import core.internal.abort : abort;
2179             abort("MonoTimeImpl!(ClockType." ~ _clockName ~
2180                       ") failed to get the frequency of the system's monotonic clock.");
2181         }
2182 
2183         version (Windows)
2184         {
2185             long ticks = void;
2186             QueryPerformanceCounter(&ticks);
2187             return MonoTimeImpl(ticks);
2188         }
2189         else version (Darwin)
2190             return MonoTimeImpl(mach_absolute_time());
2191         else version (Posix)
2192         {
2193             timespec ts = void;
2194             immutable error = clock_gettime(clockArg, &ts);
2195             // clockArg is supported and if tv_sec is long or larger
2196             // overflow won't happen before 292 billion years A.D.
2197             static if (ts.tv_sec.max < long.max)
2198             {
2199                 if (error)
2200                 {
2201                     import core.internal.abort : abort;
2202                     abort("Call to clock_gettime failed.");
2203                 }
2204             }
2205             return MonoTimeImpl(convClockFreq(ts.tv_sec * 1_000_000_000L + ts.tv_nsec,
2206                                               1_000_000_000L,
2207                                               ticksPerSecond));
2208         } else version (WASI) {
2209             time_result_t timestamp_res = clock_time_get(CLOCK_REALTIME, -1);
2210             if (timestamp_res.errno)
2211             {
2212                 import core.internal.abort : abort;
2213                 abort("Call to clock_time_get failed.");
2214             }
2215             return MonoTimeImpl(timestamp_res.timestamp);
2216         }
2217     }
2218 
2219 
2220     static @property pure nothrow @nogc
2221     {
2222     /++
2223         A $(D MonoTime) of $(D 0) ticks. It's provided to be consistent with
2224         $(D Duration.zero), and it's more explicit than $(D MonoTime.init).
2225       +/
2226     MonoTimeImpl zero() { return MonoTimeImpl(0); }
2227 
2228     /++
2229         Largest $(D MonoTime) possible.
2230       +/
2231     MonoTimeImpl max() { return MonoTimeImpl(long.max); }
2232 
2233     /++
2234         Most negative $(D MonoTime) possible.
2235       +/
2236     MonoTimeImpl min() { return MonoTimeImpl(long.min); }
2237     }
2238 
2239     version (CoreUnittest) unittest
2240     {
2241         assert(MonoTimeImpl.zero == MonoTimeImpl(0));
2242         assert(MonoTimeImpl.max == MonoTimeImpl(long.max));
2243         assert(MonoTimeImpl.min == MonoTimeImpl(long.min));
2244         assert(MonoTimeImpl.min < MonoTimeImpl.zero);
2245         assert(MonoTimeImpl.zero < MonoTimeImpl.max);
2246         assert(MonoTimeImpl.min < MonoTimeImpl.max);
2247     }
2248 
2249 
2250     /++
2251         Compares this MonoTime with the given MonoTime.
2252 
2253         Returns:
2254             $(BOOKTABLE,
2255                 $(TR $(TD this &lt; rhs) $(TD &lt; 0))
2256                 $(TR $(TD this == rhs) $(TD 0))
2257                 $(TR $(TD this &gt; rhs) $(TD &gt; 0))
2258             )
2259      +/
2260     int opCmp(MonoTimeImpl rhs) const pure nothrow @nogc
2261     {
2262         return (_ticks > rhs._ticks) - (_ticks < rhs._ticks);
2263     }
2264 
2265     version (CoreUnittest) unittest
2266     {
2267         import core.internal.traits : rvalueOf;
2268         const t = MonoTimeImpl.currTime;
2269         assert(t == rvalueOf(t));
2270     }
2271 
2272     version (CoreUnittest) unittest
2273     {
2274         import core.internal.traits : rvalueOf;
2275         const before = MonoTimeImpl.currTime;
2276         auto after = MonoTimeImpl(before._ticks + 42);
2277         assert(before < after);
2278         assert(rvalueOf(before) <= before);
2279         assert(rvalueOf(after) > before);
2280         assert(after >= rvalueOf(after));
2281     }
2282 
2283     version (CoreUnittest) unittest
2284     {
2285         const currTime = MonoTimeImpl.currTime;
2286         assert(MonoTimeImpl(long.max) > MonoTimeImpl(0));
2287         assert(MonoTimeImpl(0) > MonoTimeImpl(long.min));
2288         assert(MonoTimeImpl(long.max) > currTime);
2289         assert(currTime > MonoTimeImpl(0));
2290         assert(MonoTimeImpl(0) < currTime);
2291         assert(MonoTimeImpl(0) < MonoTimeImpl(long.max));
2292         assert(MonoTimeImpl(long.min) < MonoTimeImpl(0));
2293     }
2294 
2295 
2296     /++
2297         Subtracting two MonoTimes results in a $(LREF Duration) representing
2298         the amount of time which elapsed between them.
2299 
2300         The primary way that programs should time how long something takes is to
2301         do
2302 --------------------
2303 MonoTime before = MonoTime.currTime;
2304 // do stuff
2305 MonoTime after = MonoTime.currTime;
2306 
2307 // How long it took.
2308 Duration timeElapsed = after - before;
2309 --------------------
2310         or to use a wrapper (such as a stop watch type) which does that.
2311 
2312         $(RED Warning):
2313             Because $(LREF Duration) is in hnsecs, whereas MonoTime is in system
2314             ticks, it's usually the case that this assertion will fail
2315 --------------------
2316 auto before = MonoTime.currTime;
2317 // do stuff
2318 auto after = MonoTime.currTime;
2319 auto timeElapsed = after - before;
2320 assert(before + timeElapsed == after);
2321 --------------------
2322 
2323             This is generally fine, and by its very nature, converting from
2324             system ticks to any type of seconds (hnsecs, nsecs, etc.) will
2325             introduce rounding errors, but if code needs to avoid any of the
2326             small rounding errors introduced by conversion, then it needs to use
2327             MonoTime's $(D ticks) property and keep all calculations in ticks
2328             rather than using $(LREF Duration).
2329       +/
2330     Duration opBinary(string op)(MonoTimeImpl rhs) const pure nothrow @nogc
2331         if (op == "-")
2332     {
2333         immutable diff = _ticks - rhs._ticks;
2334         return Duration(convClockFreq(diff , ticksPerSecond, hnsecsPer!"seconds"));
2335     }
2336 
2337     version (CoreUnittest) unittest
2338     {
2339         import core.internal.traits : rvalueOf;
2340         const t = MonoTimeImpl.currTime;
2341         assert(t - rvalueOf(t) == Duration.zero);
2342         static assert(!__traits(compiles, t + t));
2343     }
2344 
2345     version (CoreUnittest) unittest
2346     {
2347         static void test(const scope MonoTimeImpl before, const scope MonoTimeImpl after, const scope Duration min)
2348         {
2349             immutable diff = after - before;
2350             assert(diff >= min);
2351             auto calcAfter = before + diff;
2352             assertApprox(calcAfter, calcAfter - Duration(1), calcAfter + Duration(1));
2353             assert(before - after == -diff);
2354         }
2355 
2356         const before = MonoTimeImpl.currTime;
2357         test(before, MonoTimeImpl(before._ticks + 4202), Duration.zero);
2358         test(before, MonoTimeImpl.currTime, Duration.zero);
2359 
2360         const durLargerUnits = dur!"minutes"(7) + dur!"seconds"(22);
2361         test(before, before + durLargerUnits + dur!"msecs"(33) + dur!"hnsecs"(571), durLargerUnits);
2362     }
2363 
2364 
2365     /++
2366         Adding or subtracting a $(LREF Duration) to/from a MonoTime results in
2367         a MonoTime which is adjusted by that amount.
2368       +/
2369     MonoTimeImpl opBinary(string op)(Duration rhs) const pure nothrow @nogc
2370         if (op == "+" || op == "-")
2371     {
2372         immutable rhsConverted = convClockFreq(rhs._hnsecs, hnsecsPer!"seconds", ticksPerSecond);
2373         mixin("return MonoTimeImpl(_ticks " ~ op ~ " rhsConverted);");
2374     }
2375 
2376     version (CoreUnittest) unittest
2377     {
2378         const t = MonoTimeImpl.currTime;
2379         assert(t + Duration(0) == t);
2380         assert(t - Duration(0) == t);
2381     }
2382 
2383     version (CoreUnittest) unittest
2384     {
2385         const t = MonoTimeImpl.currTime;
2386 
2387         // We reassign ticks in order to get the same rounding errors
2388         // that we should be getting with Duration (e.g. MonoTimeImpl may be
2389         // at a higher precision than hnsecs, meaning that 7333 would be
2390         // truncated when converting to hnsecs).
2391         long ticks = 7333;
2392         auto hnsecs = convClockFreq(ticks, ticksPerSecond, hnsecsPer!"seconds");
2393         ticks = convClockFreq(hnsecs, hnsecsPer!"seconds", ticksPerSecond);
2394 
2395         assert(t - Duration(hnsecs) == MonoTimeImpl(t._ticks - ticks));
2396         assert(t + Duration(hnsecs) == MonoTimeImpl(t._ticks + ticks));
2397     }
2398 
2399 
2400     /++ Ditto +/
2401     ref MonoTimeImpl opOpAssign(string op)(Duration rhs) pure nothrow @nogc
2402         if (op == "+" || op == "-")
2403     {
2404         immutable rhsConverted = convClockFreq(rhs._hnsecs, hnsecsPer!"seconds", ticksPerSecond);
2405         mixin("_ticks " ~ op ~ "= rhsConverted;");
2406         return this;
2407     }
2408 
2409     version (CoreUnittest) unittest
2410     {
2411         auto mt = MonoTimeImpl.currTime;
2412         const initial = mt;
2413         mt += Duration(0);
2414         assert(mt == initial);
2415         mt -= Duration(0);
2416         assert(mt == initial);
2417 
2418         // We reassign ticks in order to get the same rounding errors
2419         // that we should be getting with Duration (e.g. MonoTimeImpl may be
2420         // at a higher precision than hnsecs, meaning that 7333 would be
2421         // truncated when converting to hnsecs).
2422         long ticks = 7333;
2423         auto hnsecs = convClockFreq(ticks, ticksPerSecond, hnsecsPer!"seconds");
2424         ticks = convClockFreq(hnsecs, hnsecsPer!"seconds", ticksPerSecond);
2425         auto before = MonoTimeImpl(initial._ticks - ticks);
2426 
2427         assert((mt -= Duration(hnsecs)) == before);
2428         assert(mt  == before);
2429         assert((mt += Duration(hnsecs)) == initial);
2430         assert(mt  == initial);
2431     }
2432 
2433 
2434     /++
2435         The number of ticks in the monotonic time.
2436 
2437         Most programs should not use this directly, but it's exposed for those
2438         few programs that need it.
2439 
2440         The main reasons that a program might need to use ticks directly is if
2441         the system clock has higher precision than hnsecs, and the program needs
2442         that higher precision, or if the program needs to avoid the rounding
2443         errors caused by converting to hnsecs.
2444       +/
2445     @property long ticks() const pure nothrow @nogc
2446     {
2447         return _ticks;
2448     }
2449 
2450     version (CoreUnittest) unittest
2451     {
2452         const mt = MonoTimeImpl.currTime;
2453         assert(mt.ticks == mt._ticks);
2454     }
2455 
2456 
2457     /++
2458         The number of ticks that MonoTime has per second - i.e. the resolution
2459         or frequency of the system's monotonic clock.
2460 
2461         e.g. if the system clock had a resolution of microseconds, then
2462         ticksPerSecond would be $(D 1_000_000).
2463       +/
2464     static @property long ticksPerSecond() pure nothrow @nogc
2465     {
2466         return _ticksPerSecond[_clockIdx];
2467     }
2468 
2469     version (CoreUnittest) unittest
2470     {
2471         assert(MonoTimeImpl.ticksPerSecond == _ticksPerSecond[_clockIdx]);
2472     }
2473 
2474 
2475     ///
2476     string toString() const pure nothrow
2477     {
2478         static if (clockType == ClockType.normal)
2479             return "MonoTime(" ~ signedToTempString(_ticks) ~ " ticks, " ~ signedToTempString(ticksPerSecond) ~ " ticks per second)";
2480         else
2481             return "MonoTimeImpl!(ClockType." ~ _clockName ~ ")(" ~ signedToTempString(_ticks) ~ " ticks, " ~
2482                    signedToTempString(ticksPerSecond) ~ " ticks per second)";
2483     }
2484 
2485     version (CoreUnittest) unittest
2486     {
2487         import core.internal.util.math : min;
2488 
2489         static void eat(ref string s, const(char)[] exp)
2490         {
2491             assert(s[0 .. min($, exp.length)] == exp, s~" != "~exp);
2492             s = s[exp.length .. $];
2493         }
2494 
2495         immutable mt = MonoTimeImpl.currTime;
2496         auto str = mt.toString();
2497         static if (is(typeof(this) == MonoTime))
2498             eat(str, "MonoTime(");
2499         else
2500             eat(str, "MonoTimeImpl!(ClockType."~_clockName~")(");
2501 
2502         eat(str, signedToTempString(mt._ticks));
2503         eat(str, " ticks, ");
2504         eat(str, signedToTempString(ticksPerSecond));
2505         eat(str, " ticks per second)");
2506     }
2507 
2508 private:
2509 
2510     // static immutable long _ticksPerSecond;
2511 
2512     version (CoreUnittest) unittest
2513     {
2514         assert(_ticksPerSecond[_clockIdx]);
2515     }
2516 
2517 
2518     long _ticks;
2519 }
2520 
2521 // This is supposed to be a static variable in MonoTimeImpl with the static
2522 // constructor being in there, but https://issues.dlang.org/show_bug.cgi?id=14517
2523 // prevents that from working. However, moving it back to a static ctor will
2524 // reraise issues with other systems using MonoTime, so we should leave this
2525 // here even when that bug is fixed.
2526 private immutable long[__traits(allMembers, ClockType).length] _ticksPerSecond;
2527 
2528 // This is called directly from the runtime initilization function (rt_init),
2529 // instead of using a static constructor. Other subsystems inside the runtime
2530 // (namely, the GC) may need time functionality, but cannot wait until the
2531 // static ctors have run. Therefore, we initialize these specially. Because
2532 // it's a normal function, we need to do some dangerous casting PLEASE take
2533 // care when modifying this function, and it should NOT be called except from
2534 // the runtime init.
2535 //
2536 // NOTE: the code below SPECIFICALLY does not assert when it cannot initialize
2537 // the ticks per second array. This allows cases where a clock is never used on
2538 // a system that doesn't support it. See bugzilla issue
2539 // https://issues.dlang.org/show_bug.cgi?id=14863
2540 // The assert will occur when someone attempts to use _ticksPerSecond for that
2541 // value.
2542 extern(C) void _d_initMonoTime() @nogc nothrow
2543 {
2544     // We need a mutable pointer to the ticksPerSecond array. Although this
2545     // would appear to break immutability, it is logically the same as a static
2546     // ctor. So we should ONLY write these values once (we will check for 0
2547     // values when setting to ensure this is truly only called once).
2548     auto tps = cast(long[])_ticksPerSecond[];
2549 
2550     // If we try to do anything with ClockType in the documentation build, it'll
2551     // trigger the static assertions related to ClockType, since the
2552     // documentation build defines all of the possible ClockTypes, which won't
2553     // work when they're used in the static ifs, because no system supports them
2554     // all.
2555     version (CoreDdoc)
2556     {}
2557     else version (Windows)
2558     {
2559         long ticksPerSecond;
2560         if (QueryPerformanceFrequency(&ticksPerSecond) != 0)
2561         {
2562             foreach (i, typeStr; __traits(allMembers, ClockType))
2563             {
2564                 // ensure we are only writing immutable data once
2565                 if (tps[i] != 0)
2566                     // should only be called once
2567                     assert(0);
2568                 tps[i] = ticksPerSecond;
2569             }
2570         }
2571     }
2572     else version (Darwin)
2573     {
2574         immutable long ticksPerSecond = machTicksPerSecond();
2575         foreach (i, typeStr; __traits(allMembers, ClockType))
2576         {
2577             // ensure we are only writing immutable data once
2578             if (tps[i] != 0)
2579                 // should only be called once
2580                 assert(0);
2581             tps[i] = ticksPerSecond;
2582         }
2583     }
2584     else version (Posix)
2585     {
2586         timespec ts;
2587         foreach (i, typeStr; __traits(allMembers, ClockType))
2588         {
2589             static if (typeStr != "second")
2590             {
2591                 enum clockArg = _posixClock(__traits(getMember, ClockType, typeStr));
2592                 if (clock_getres(clockArg, &ts) == 0)
2593                 {
2594                     // ensure we are only writing immutable data once
2595                     if (tps[i] != 0)
2596                         // should only be called once
2597                         assert(0);
2598 
2599                     // For some reason, on some systems, clock_getres returns
2600                     // a resolution which is clearly wrong:
2601                     //  - it's a millisecond or worse, but the time is updated
2602                     //    much more frequently than that.
2603                     //  - it's negative
2604                     //  - it's zero
2605                     // In such cases, we'll just use nanosecond resolution.
2606                     tps[i] = ts.tv_sec != 0 || ts.tv_nsec <= 0 || ts.tv_nsec >= 1000
2607                         ? 1_000_000_000L : 1_000_000_000L / ts.tv_nsec;
2608                 }
2609             }
2610         }
2611     }
2612 }
2613 
2614 
2615 // Tests for MonoTimeImpl.currTime. It has to be outside, because MonoTimeImpl
2616 // is a template. This unittest block also makes sure that MonoTimeImpl actually
2617 // is instantiated with all of the various ClockTypes so that those types and
2618 // their tests are compiled and run.
2619 unittest
2620 {
2621     // This test is separate so that it can be tested with MonoTime and not just
2622     // MonoTimeImpl.
2623     auto norm1 = MonoTime.currTime;
2624     auto norm2 = MonoTimeImpl!(ClockType.normal).currTime;
2625     assert(norm1 <= norm2);
2626 
2627     static bool clockSupported(ClockType c)
2628     {
2629         // Skip unsupported clocks on older linux kernels, assume that only
2630         // CLOCK_MONOTONIC and CLOCK_REALTIME exist, as that is the lowest
2631         // common denominator supported by all versions of Linux pre-2.6.12.
2632         version (Linux_Pre_2639)
2633             return c == ClockType.normal || c == ClockType.precise;
2634         else
2635             return c != ClockType.second; // second doesn't work with MonoTimeImpl
2636 
2637     }
2638 
2639     foreach (typeStr; __traits(allMembers, ClockType))
2640     {
2641         mixin("alias type = ClockType." ~ typeStr ~ ";");
2642         static if (clockSupported(type))
2643         {
2644             auto v1 = MonoTimeImpl!type.currTime;
2645             auto v2 = MonoTimeImpl!type.currTime;
2646             scope(failure)
2647             {
2648                 printf("%s: v1 %s, v2 %s, tps %s\n",
2649                        (type.stringof ~ "\0").ptr,
2650                        numToStringz(v1._ticks),
2651                        numToStringz(v2._ticks),
2652                        numToStringz(typeof(v1).ticksPerSecond));
2653             }
2654             assert(v1 <= v2);
2655 
2656             foreach (otherStr; __traits(allMembers, ClockType))
2657             {
2658                 mixin("alias other = ClockType." ~ otherStr ~ ";");
2659                 static if (clockSupported(other))
2660                 {
2661                     static assert(is(typeof({auto o1 = MonTimeImpl!other.currTime; auto b = v1 <= o1;})) ==
2662                                   is(type == other));
2663                 }
2664             }
2665         }
2666     }
2667 }
2668 
2669 
2670 /++
2671     Converts the given time from one clock frequency/resolution to another.
2672 
2673     See_Also:
2674         $(LREF ticksToNSecs)
2675   +/
2676 long convClockFreq(long ticks, long srcTicksPerSecond, long dstTicksPerSecond) @safe pure nothrow @nogc
2677 {
2678     // This would be more straightforward with floating point arithmetic,
2679     // but we avoid it here in order to avoid the rounding errors that that
2680     // introduces. Also, by splitting out the units in this way, we're able
2681     // to deal with much larger values before running into problems with
2682     // integer overflow.
2683     return ticks / srcTicksPerSecond * dstTicksPerSecond +
2684            ticks % srcTicksPerSecond * dstTicksPerSecond / srcTicksPerSecond;
2685 }
2686 
2687 ///
2688 unittest
2689 {
2690     // one tick is one second -> one tick is a hecto-nanosecond
2691     assert(convClockFreq(45, 1, 10_000_000) == 450_000_000);
2692 
2693     // one tick is one microsecond -> one tick is a millisecond
2694     assert(convClockFreq(9029, 1_000_000, 1_000) == 9);
2695 
2696     // one tick is 1/3_515_654 of a second -> 1/1_001_010 of a second
2697     assert(convClockFreq(912_319, 3_515_654, 1_001_010) == 259_764);
2698 
2699     // one tick is 1/MonoTime.ticksPerSecond -> one tick is a nanosecond
2700     // Equivalent to ticksToNSecs
2701     auto nsecs = convClockFreq(1982, MonoTime.ticksPerSecond, 1_000_000_000);
2702 }
2703 
2704 unittest
2705 {
2706     assert(convClockFreq(99, 43, 57) == 131);
2707     assert(convClockFreq(131, 57, 43) == 98);
2708     assert(convClockFreq(1234567890, 10_000_000, 1_000_000_000) == 123456789000);
2709     assert(convClockFreq(1234567890, 1_000_000_000, 10_000_000) == 12345678);
2710     assert(convClockFreq(123456789000, 1_000_000_000, 10_000_000) == 1234567890);
2711     assert(convClockFreq(12345678, 10_000_000, 1_000_000_000) == 1234567800);
2712     assert(convClockFreq(13131, 3_515_654, 10_000_000) == 37350);
2713     assert(convClockFreq(37350, 10_000_000, 3_515_654) == 13130);
2714     assert(convClockFreq(37350, 3_515_654, 10_000_000) == 106239);
2715     assert(convClockFreq(106239, 10_000_000, 3_515_654) == 37349);
2716 
2717     // It would be too expensive to cover a large range of possible values for
2718     // ticks, so we use random values in an attempt to get reasonable coverage.
2719     import core.stdc.stdlib;
2720     immutable seed = cast(int)time(null);
2721     srand(seed);
2722     scope(failure) printf("seed %d\n", seed);
2723     enum freq1 = 5_527_551L;
2724     enum freq2 = 10_000_000L;
2725     enum freq3 = 1_000_000_000L;
2726     enum freq4 = 98_123_320L;
2727     immutable freq5 = MonoTime.ticksPerSecond;
2728 
2729     // This makes it so that freq6 is the first multiple of 10 which is greater
2730     // than or equal to freq5, which at one point was considered for MonoTime's
2731     // ticksPerSecond rather than using the system's actual clock frequency, so
2732     // it seemed like a good test case to have.
2733     import core.stdc.math;
2734     immutable numDigitsMinus1 = cast(int)floor(log10(freq5));
2735     auto freq6 = cast(long)pow(10, numDigitsMinus1);
2736     if (freq5 > freq6)
2737         freq6 *= 10;
2738 
2739     foreach (_; 0 .. 10_000)
2740     {
2741         long[2] values = [rand(), cast(long)rand() * (rand() % 16)];
2742         foreach (i; values)
2743         {
2744             scope(failure) printf("i %s\n", numToStringz(i));
2745             assertApprox(convClockFreq(convClockFreq(i, freq1, freq2), freq2, freq1), i - 10, i + 10);
2746             assertApprox(convClockFreq(convClockFreq(i, freq2, freq1), freq1, freq2), i - 10, i + 10);
2747 
2748             assertApprox(convClockFreq(convClockFreq(i, freq3, freq4), freq4, freq3), i - 100, i + 100);
2749             assertApprox(convClockFreq(convClockFreq(i, freq4, freq3), freq3, freq4), i - 100, i + 100);
2750 
2751             scope(failure) printf("sys %s mt %s\n", numToStringz(freq5), numToStringz(freq6));
2752             assertApprox(convClockFreq(convClockFreq(i, freq5, freq6), freq6, freq5), i - 10, i + 10);
2753             assertApprox(convClockFreq(convClockFreq(i, freq6, freq5), freq5, freq6), i - 10, i + 10);
2754 
2755             // This is here rather than in a unittest block immediately after
2756             // ticksToNSecs in order to avoid code duplication in the unit tests.
2757             assert(convClockFreq(i, MonoTime.ticksPerSecond, 1_000_000_000) == ticksToNSecs(i));
2758         }
2759     }
2760 }
2761 
2762 
2763 /++
2764     Convenience wrapper around $(LREF convClockFreq) which converts ticks at
2765     a clock frequency of $(D MonoTime.ticksPerSecond) to nanoseconds.
2766 
2767     It's primarily of use when $(D MonoTime.ticksPerSecond) is greater than
2768     hecto-nanosecond resolution, and an application needs a higher precision
2769     than hecto-nanoceconds.
2770 
2771     See_Also:
2772         $(LREF convClockFreq)
2773   +/
2774 long ticksToNSecs(long ticks) @safe pure nothrow @nogc
2775 {
2776     return convClockFreq(ticks, MonoTime.ticksPerSecond, 1_000_000_000);
2777 }
2778 
2779 ///
2780 unittest
2781 {
2782     auto before = MonoTime.currTime;
2783     // do stuff
2784     auto after = MonoTime.currTime;
2785     auto diffInTicks = after.ticks - before.ticks;
2786     auto diffInNSecs = ticksToNSecs(diffInTicks);
2787     assert(diffInNSecs == convClockFreq(diffInTicks, MonoTime.ticksPerSecond, 1_000_000_000));
2788 }
2789 
2790 
2791 /++
2792     The reverse of $(LREF ticksToNSecs).
2793   +/
2794 long nsecsToTicks(long ticks) @safe pure nothrow @nogc
2795 {
2796     return convClockFreq(ticks, 1_000_000_000, MonoTime.ticksPerSecond);
2797 }
2798 
2799 unittest
2800 {
2801     long ticks = 123409832717333;
2802     auto nsecs = convClockFreq(ticks, MonoTime.ticksPerSecond, 1_000_000_000);
2803     ticks = convClockFreq(nsecs, 1_000_000_000, MonoTime.ticksPerSecond);
2804     assert(nsecsToTicks(nsecs) == ticks);
2805 }
2806 
2807 
2808 
2809 /++
2810    $(RED Warning: TickDuration is deprecated. Please use
2811           $(LREF MonoTime) for the cases where a monotonic timestamp is needed
2812           and $(LREF Duration) when a duration is needed, rather than using
2813           TickDuration.)
2814 
2815    Represents a duration of time in system clock ticks.
2816 
2817    The system clock ticks are the ticks of the system clock at the highest
2818    precision that the system provides.
2819   +/
2820 deprecated("TickDuration has been deprecated, please use Duration or MonoTime instead")
2821 struct TickDuration
2822 {
2823 deprecated:
2824     private static TickDuration TDRvalueOf(TickDuration td)
2825     {
2826         return td;
2827     }
2828     /++
2829        The number of ticks that the system clock has in one second.
2830 
2831        If $(D ticksPerSec) is $(D 0), then then $(D TickDuration) failed to
2832        get the value of $(D ticksPerSec) on the current system, and
2833        $(D TickDuration) is not going to work. That would be highly abnormal
2834        though.
2835       +/
2836     static immutable long ticksPerSec;
2837 
2838 
2839     /++
2840         The tick of the system clock (as a $(D TickDuration)) when the
2841         application started.
2842       +/
2843     static immutable TickDuration appOrigin;
2844 
2845 
2846     static @property @safe pure nothrow @nogc
2847     {
2848     /++
2849         It's the same as $(D TickDuration(0)), but it's provided to be
2850         consistent with $(D Duration), which provides a $(D zero) property.
2851       +/
2852     TickDuration zero() { return TickDuration(0); }
2853 
2854     /++
2855         Largest $(D TickDuration) possible.
2856       +/
2857     TickDuration max() { return TickDuration(long.max); }
2858 
2859     /++
2860         Most negative $(D TickDuration) possible.
2861       +/
2862     TickDuration min() { return TickDuration(long.min); }
2863     }
2864 
2865     version (CoreUnittest) unittest
2866     {
2867         assert((zero == TickDuration(0)) == true);
2868         assert((TickDuration.max == TickDuration(long.max)) == true);
2869         assert((TickDuration.min == TickDuration(long.min)) == true);
2870         assert((TickDuration.min < TickDuration.zero) == true);
2871         assert((TickDuration.zero < TickDuration.max) == true);
2872         assert((TickDuration.min < TickDuration.max) == true);
2873         assert((TickDuration.min - TickDuration(1) == TickDuration.max) == true);
2874         assert((TickDuration.max + TickDuration(1) == TickDuration.min) == true);
2875     }
2876 
2877 
2878     static pragma(crt_constructor) void time_initializer()
2879     {
2880         version (Windows)
2881         {
2882             if (QueryPerformanceFrequency(cast(long*)&ticksPerSec) == 0)
2883                 ticksPerSec = 0;
2884         }
2885         else version (Darwin)
2886         {
2887             ticksPerSec = machTicksPerSecond();
2888         }
2889         else version (Posix)
2890         {
2891             static if (is(typeof(clock_gettime)))
2892             {
2893                 timespec ts;
2894 
2895                 if (clock_getres(CLOCK_MONOTONIC, &ts) != 0)
2896                     ticksPerSec = 0;
2897                 else
2898                 {
2899                     //For some reason, on some systems, clock_getres returns
2900                     //a resolution which is clearly wrong (it's a millisecond
2901                     //or worse, but the time is updated much more frequently
2902                     //than that). In such cases, we'll just use nanosecond
2903                     //resolution.
2904                     ticksPerSec = ts.tv_nsec >= 1000 ? 1_000_000_000
2905                                                      : 1_000_000_000 / ts.tv_nsec;
2906                 }
2907             }
2908             else
2909                 ticksPerSec = 1_000_000;
2910         }
2911 
2912         if (ticksPerSec != 0)
2913             appOrigin = TickDuration.currSystemTick;
2914     }
2915 
2916     version (CoreUnittest) unittest
2917     {
2918         assert(ticksPerSec);
2919     }
2920 
2921 
2922     /++
2923        The number of system ticks in this $(D TickDuration).
2924 
2925        You can convert this $(D length) into the number of seconds by dividing
2926        it by $(D ticksPerSec) (or using one the appropriate property function
2927        to do it).
2928       +/
2929     long length;
2930 
2931     /++
2932         Returns the total number of seconds in this $(D TickDuration).
2933       +/
2934     @property long seconds() @safe const pure nothrow @nogc
2935     {
2936         return this.to!("seconds", long)();
2937     }
2938 
2939     version (CoreUnittest) unittest
2940     {
2941         foreach (T; AliasSeq!(TickDuration, const TickDuration, immutable TickDuration))
2942         {
2943             assert((cast(T)TickDuration(ticksPerSec)).seconds == 1);
2944             assert((cast(T)TickDuration(ticksPerSec - 1)).seconds == 0);
2945             assert((cast(T)TickDuration(ticksPerSec * 2)).seconds == 2);
2946             assert((cast(T)TickDuration(ticksPerSec * 2 - 1)).seconds == 1);
2947             assert((cast(T)TickDuration(-1)).seconds == 0);
2948             assert((cast(T)TickDuration(-ticksPerSec - 1)).seconds == -1);
2949             assert((cast(T)TickDuration(-ticksPerSec)).seconds == -1);
2950         }
2951     }
2952 
2953 
2954     /++
2955         Returns the total number of milliseconds in this $(D TickDuration).
2956       +/
2957     @property long msecs() @safe const pure nothrow @nogc
2958     {
2959         return this.to!("msecs", long)();
2960     }
2961 
2962 
2963     /++
2964         Returns the total number of microseconds in this $(D TickDuration).
2965       +/
2966     @property long usecs() @safe const pure nothrow @nogc
2967     {
2968         return this.to!("usecs", long)();
2969     }
2970 
2971 
2972     /++
2973         Returns the total number of hecto-nanoseconds in this $(D TickDuration).
2974       +/
2975     @property long hnsecs() @safe const pure nothrow @nogc
2976     {
2977         return this.to!("hnsecs", long)();
2978     }
2979 
2980 
2981     /++
2982         Returns the total number of nanoseconds in this $(D TickDuration).
2983       +/
2984     @property long nsecs() @safe const pure nothrow @nogc
2985     {
2986         return this.to!("nsecs", long)();
2987     }
2988 
2989 
2990     /++
2991         This allows you to construct a $(D TickDuration) from the given time
2992         units with the given length.
2993 
2994         Params:
2995             units  = The time units of the $(D TickDuration) (e.g. $(D "msecs")).
2996             length = The number of units in the $(D TickDuration).
2997       +/
2998     static TickDuration from(string units)(long length) @safe pure nothrow @nogc
2999         if (units == "seconds" ||
3000            units == "msecs" ||
3001            units == "usecs" ||
3002            units == "hnsecs" ||
3003            units == "nsecs")
3004     {
3005         enum unitsPerSec = convert!("seconds", units)(1);
3006 
3007         return TickDuration(cast(long)(length * (ticksPerSec / cast(real)unitsPerSec)));
3008     }
3009 
3010     version (CoreUnittest) unittest
3011     {
3012         foreach (units; AliasSeq!("seconds", "msecs", "usecs", "nsecs"))
3013         {
3014             foreach (T; AliasSeq!(TickDuration, const TickDuration, immutable TickDuration))
3015             {
3016                 assertApprox((cast(T)TickDuration.from!units(1000)).to!(units, long)(),
3017                              500, 1500, units);
3018                 assertApprox((cast(T)TickDuration.from!units(1_000_000)).to!(units, long)(),
3019                              900_000, 1_100_000, units);
3020                 assertApprox((cast(T)TickDuration.from!units(2_000_000)).to!(units, long)(),
3021                              1_900_000, 2_100_000, units);
3022             }
3023         }
3024     }
3025 
3026 
3027     /++
3028         Returns a $(LREF Duration) with the same number of hnsecs as this
3029         $(D TickDuration).
3030         Note that the conventional way to convert between $(D TickDuration)
3031         and $(D Duration) is using $(REF to, std,conv), e.g.:
3032         $(D tickDuration.to!Duration())
3033       +/
3034     Duration opCast(T)() @safe const pure nothrow @nogc
3035         if (is(immutable T == immutable Duration))
3036     {
3037         return Duration(hnsecs);
3038     }
3039 
3040     version (CoreUnittest) unittest
3041     {
3042         foreach (D; AliasSeq!(Duration, const Duration, immutable Duration))
3043         {
3044             foreach (T; AliasSeq!(TickDuration, const TickDuration, immutable TickDuration))
3045             {
3046                 auto expected = dur!"seconds"(1);
3047                 assert(cast(D)cast(T)TickDuration.from!"seconds"(1) == expected);
3048 
3049                 foreach (units; AliasSeq!("msecs", "usecs", "hnsecs"))
3050                 {
3051                     D actual = cast(D)cast(T)TickDuration.from!units(1_000_000);
3052                     assertApprox(actual, dur!units(900_000), dur!units(1_100_000));
3053                 }
3054             }
3055         }
3056     }
3057 
3058 
3059     //Temporary hack until bug http://d.puremagic.com/issues/show_bug.cgi?id=5747 is fixed.
3060     TickDuration opCast(T)() @safe const pure nothrow @nogc
3061         if (is(immutable T == immutable TickDuration))
3062     {
3063         return this;
3064     }
3065 
3066 
3067     /++
3068         Adds or subtracts two $(D TickDuration)s as well as assigning the result
3069         to this $(D TickDuration).
3070 
3071         The legal types of arithmetic for $(D TickDuration) using this operator
3072         are
3073 
3074         $(TABLE
3075         $(TR $(TD TickDuration) $(TD +=) $(TD TickDuration) $(TD -->) $(TD TickDuration))
3076         $(TR $(TD TickDuration) $(TD -=) $(TD TickDuration) $(TD -->) $(TD TickDuration))
3077         )
3078 
3079         Params:
3080             rhs = The $(D TickDuration) to add to or subtract from this
3081                   $(D $(D TickDuration)).
3082       +/
3083     ref TickDuration opOpAssign(string op)(TickDuration rhs) @safe pure nothrow @nogc
3084         if (op == "+" || op == "-")
3085     {
3086         mixin("length " ~ op ~ "= rhs.length;");
3087         return this;
3088     }
3089 
3090     version (CoreUnittest) unittest
3091     {
3092         foreach (T; AliasSeq!(TickDuration, const TickDuration, immutable TickDuration))
3093         {
3094             auto a = TickDuration.currSystemTick;
3095             auto result = a += cast(T)TickDuration.currSystemTick;
3096             assert((a == result) == true);
3097             assert(a.to!("seconds", real)() >= 0);
3098 
3099             auto b = TickDuration.currSystemTick;
3100             result = b -= cast(T)TickDuration.currSystemTick;
3101             assert((b == result) == true);
3102             assert(b.to!("seconds", real)() <= 0);
3103 
3104             foreach (U; AliasSeq!(const TickDuration, immutable TickDuration))
3105             {
3106                 U u = TickDuration(12);
3107                 static assert(!__traits(compiles, u += cast(T)TickDuration.currSystemTick));
3108                 static assert(!__traits(compiles, u -= cast(T)TickDuration.currSystemTick));
3109             }
3110         }
3111     }
3112 
3113 
3114     /++
3115         Adds or subtracts two $(D TickDuration)s.
3116 
3117         The legal types of arithmetic for $(D TickDuration) using this operator
3118         are
3119 
3120         $(TABLE
3121         $(TR $(TD TickDuration) $(TD +) $(TD TickDuration) $(TD -->) $(TD TickDuration))
3122         $(TR $(TD TickDuration) $(TD -) $(TD TickDuration) $(TD -->) $(TD TickDuration))
3123         )
3124 
3125         Params:
3126             rhs = The $(D TickDuration) to add to or subtract from this
3127                   $(D TickDuration).
3128       +/
3129     TickDuration opBinary(string op)(TickDuration rhs) @safe const pure nothrow @nogc
3130         if (op == "+" || op == "-")
3131     {
3132         return TickDuration(mixin("length " ~ op ~ " rhs.length"));
3133     }
3134 
3135     version (CoreUnittest) unittest
3136     {
3137         foreach (T; AliasSeq!(TickDuration, const TickDuration, immutable TickDuration))
3138         {
3139             T a = TickDuration.currSystemTick;
3140             T b = TickDuration.currSystemTick;
3141             assert((a + b).usecs > 0);
3142             assert((a - b).seconds <= 0);
3143         }
3144     }
3145 
3146 
3147     /++
3148         Returns the negation of this $(D TickDuration).
3149       +/
3150     TickDuration opUnary(string op)() @safe const pure nothrow @nogc
3151         if (op == "-")
3152     {
3153         return TickDuration(-length);
3154     }
3155 
3156     version (CoreUnittest) unittest
3157     {
3158         foreach (T; AliasSeq!(TickDuration, const TickDuration, immutable TickDuration))
3159         {
3160             assert((-(cast(T)TickDuration(7)) == TickDuration(-7)) == true);
3161             assert((-(cast(T)TickDuration(5)) == TickDuration(-5)) == true);
3162             assert((-(cast(T)TickDuration(-7)) == TickDuration(7)) == true);
3163             assert((-(cast(T)TickDuration(-5)) == TickDuration(5)) == true);
3164             assert((-(cast(T)TickDuration(0)) == TickDuration(0)) == true);
3165         }
3166     }
3167 
3168 
3169     /++
3170        operator overloading "<, >, <=, >="
3171       +/
3172     int opCmp(TickDuration rhs) @safe const pure nothrow @nogc
3173     {
3174         return (length > rhs.length) - (length < rhs.length);
3175     }
3176 
3177     version (CoreUnittest) unittest
3178     {
3179         import core.internal.traits : rvalueOf;
3180         foreach (T; AliasSeq!(TickDuration, const TickDuration, immutable TickDuration))
3181         {
3182             foreach (U; AliasSeq!(TickDuration, const TickDuration, immutable TickDuration))
3183             {
3184                 T t = TickDuration.currSystemTick;
3185                 U u = t;
3186                 assert((t == u) == true);
3187                 assert((TDRvalueOf(t) == u) == true);
3188                 assert((t == TDRvalueOf(u)) == true);
3189             }
3190         }
3191 
3192         foreach (T; AliasSeq!(TickDuration, const TickDuration, immutable TickDuration))
3193         {
3194             foreach (U; AliasSeq!(TickDuration, const TickDuration, immutable TickDuration))
3195             {
3196                 T t = TickDuration.currSystemTick;
3197                 U u = t + t;
3198                 assert((t < u) == true);
3199                 assert((t <= t) == true);
3200                 assert((u > t) == true);
3201                 assert((u >= u) == true);
3202 
3203                 assert((TDRvalueOf(t) < u) == true);
3204                 assert((TDRvalueOf(t) <= t) == true);
3205                 assert((TDRvalueOf(u) > t) == true);
3206                 assert((TDRvalueOf(u) >= u) == true);
3207 
3208                 assert((t < TDRvalueOf(u)) == true);
3209                 assert((t <= TDRvalueOf(t)) == true);
3210                 assert((u > TDRvalueOf(t)) == true);
3211                 assert((u >= TDRvalueOf(u)) == true);
3212             }
3213         }
3214     }
3215 
3216 
3217     /++
3218         The legal types of arithmetic for $(D TickDuration) using this operator
3219         overload are
3220 
3221         $(TABLE
3222         $(TR $(TD TickDuration) $(TD *) $(TD long) $(TD -->) $(TD TickDuration))
3223         $(TR $(TD TickDuration) $(TD *) $(TD floating point) $(TD -->) $(TD TickDuration))
3224         )
3225 
3226         Params:
3227             value = The value to divide from this duration.
3228       +/
3229     void opOpAssign(string op, T)(T value) @safe pure nothrow @nogc
3230         if (op == "*" &&
3231            (__traits(isIntegral, T) || __traits(isFloating, T)))
3232     {
3233         length = cast(long)(length * value);
3234     }
3235 
3236     version (CoreUnittest) unittest
3237     {
3238         immutable curr = TickDuration.currSystemTick;
3239         TickDuration t1 = curr;
3240         immutable t2 = curr + curr;
3241         t1 *= 2;
3242         assert((t1 == t2) == true);
3243 
3244         t1 = curr;
3245         t1 *= 2.0;
3246         immutable tol = TickDuration(cast(long)(_abs(t1.length) * double.epsilon * 2.0));
3247         assertApprox(t1, t2 - tol, t2 + tol);
3248 
3249         t1 = curr;
3250         t1 *= 2.1;
3251         assert((t1 > t2) == true);
3252 
3253         foreach (T; AliasSeq!(const TickDuration, immutable TickDuration))
3254         {
3255             T t = TickDuration.currSystemTick;
3256             assert(!__traits(compiles, t *= 12));
3257             assert(!__traits(compiles, t *= 12.0));
3258         }
3259     }
3260 
3261 
3262     /++
3263         The legal types of arithmetic for $(D TickDuration) using this operator
3264         overload are
3265 
3266         $(TABLE
3267         $(TR $(TD TickDuration) $(TD /) $(TD long) $(TD -->) $(TD TickDuration))
3268         $(TR $(TD TickDuration) $(TD /) $(TD floating point) $(TD -->) $(TD TickDuration))
3269         )
3270 
3271         Params:
3272             value = The value to divide from this $(D TickDuration).
3273 
3274         Throws:
3275             $(D TimeException) if an attempt to divide by $(D 0) is made.
3276       +/
3277     void opOpAssign(string op, T)(T value) @safe pure
3278         if (op == "/" &&
3279            (__traits(isIntegral, T) || __traits(isFloating, T)))
3280     {
3281         if (value == 0)
3282             throw new TimeException("Attempted division by 0.");
3283 
3284         length = cast(long)(length / value);
3285     }
3286 
3287     version (CoreUnittest) unittest
3288     {
3289         immutable curr = TickDuration.currSystemTick;
3290         immutable t1 = curr;
3291         TickDuration t2 = curr + curr;
3292         t2 /= 2;
3293         assert((t1 == t2) == true);
3294 
3295         t2 = curr + curr;
3296         t2 /= 2.0;
3297         immutable tol = TickDuration(cast(long)(_abs(t2.length) * double.epsilon / 2.0));
3298         assertApprox(t1, t2 - tol, t2 + tol);
3299 
3300         t2 = curr + curr;
3301         t2 /= 2.1;
3302         assert((t1 > t2) == true);
3303 
3304         _assertThrown!TimeException(t2 /= 0);
3305 
3306         foreach (T; AliasSeq!(const TickDuration, immutable TickDuration))
3307         {
3308             T t = TickDuration.currSystemTick;
3309             assert(!__traits(compiles, t /= 12));
3310             assert(!__traits(compiles, t /= 12.0));
3311         }
3312     }
3313 
3314 
3315     /++
3316         The legal types of arithmetic for $(D TickDuration) using this operator
3317         overload are
3318 
3319         $(TABLE
3320         $(TR $(TD TickDuration) $(TD *) $(TD long) $(TD -->) $(TD TickDuration))
3321         $(TR $(TD TickDuration) $(TD *) $(TD floating point) $(TD -->) $(TD TickDuration))
3322         )
3323 
3324         Params:
3325             value = The value to divide from this $(D TickDuration).
3326       +/
3327     TickDuration opBinary(string op, T)(T value) @safe const pure nothrow @nogc
3328         if (op == "*" &&
3329            (__traits(isIntegral, T) || __traits(isFloating, T)))
3330     {
3331         return TickDuration(cast(long)(length * value));
3332     }
3333 
3334     version (CoreUnittest) unittest
3335     {
3336         foreach (T; AliasSeq!(TickDuration, const TickDuration, immutable TickDuration))
3337         {
3338             T t1 = TickDuration.currSystemTick;
3339             T t2 = t1 + t1;
3340             assert((t1 * 2 == t2) == true);
3341             immutable tol = TickDuration(cast(long)(_abs(t1.length) * double.epsilon * 2.0));
3342             assertApprox(t1 * 2.0, t2 - tol, t2 + tol);
3343             assert((t1 * 2.1 > t2) == true);
3344         }
3345     }
3346 
3347 
3348     /++
3349         The legal types of arithmetic for $(D TickDuration) using this operator
3350         overload are
3351 
3352         $(TABLE
3353         $(TR $(TD TickDuration) $(TD /) $(TD long) $(TD -->) $(TD TickDuration))
3354         $(TR $(TD TickDuration) $(TD /) $(TD floating point) $(TD -->) $(TD TickDuration))
3355         )
3356 
3357         Params:
3358             value = The value to divide from this $(D TickDuration).
3359 
3360         Throws:
3361             $(D TimeException) if an attempt to divide by $(D 0) is made.
3362       +/
3363     TickDuration opBinary(string op, T)(T value) @safe const pure
3364         if (op == "/" &&
3365            (__traits(isIntegral, T) || __traits(isFloating, T)))
3366     {
3367         if (value == 0)
3368             throw new TimeException("Attempted division by 0.");
3369 
3370         return TickDuration(cast(long)(length / value));
3371     }
3372 
3373     version (CoreUnittest) unittest
3374     {
3375         foreach (T; AliasSeq!(TickDuration, const TickDuration, immutable TickDuration))
3376         {
3377             T t1 = TickDuration.currSystemTick;
3378             T t2 = t1 + t1;
3379             assert((t2 / 2 == t1) == true);
3380             immutable tol = TickDuration(cast(long)(_abs(t2.length) * double.epsilon / 2.0));
3381             assertApprox(t2 / 2.0, t1 - tol, t1 + tol);
3382             assert((t2 / 2.1 < t1) == true);
3383 
3384             _assertThrownDep!TimeException(t2 / 0);
3385         }
3386     }
3387 
3388 
3389     /++
3390         Params:
3391             ticks = The number of ticks in the TickDuration.
3392       +/
3393     @safe pure nothrow @nogc this(long ticks)
3394     {
3395         this.length = ticks;
3396     }
3397 
3398     version (CoreUnittest) unittest
3399     {
3400         foreach (i; [-42, 0, 42])
3401             assert(TickDuration(i).length == i);
3402     }
3403 
3404 
3405     /++
3406         The current system tick. The number of ticks per second varies from
3407         system to system. $(D currSystemTick) uses a monotonic clock, so it's
3408         intended for precision timing by comparing relative time values, not for
3409         getting the current system time.
3410 
3411         On Windows, $(D QueryPerformanceCounter) is used. On Mac OS X,
3412         $(D mach_absolute_time) is used, while on other Posix systems,
3413         $(D clock_gettime) is used. If $(D mach_absolute_time) or
3414         $(D clock_gettime) is unavailable, then Posix systems use
3415         $(D gettimeofday) (the decision is made when $(D TickDuration) is
3416         compiled), which unfortunately, is not monotonic, but if
3417         $(D mach_absolute_time) and $(D clock_gettime) aren't available, then
3418         $(D gettimeofday) is the best that there is.
3419 
3420         $(RED Warning):
3421             On some systems, the monotonic clock may stop counting when
3422             the computer goes to sleep or hibernates. So, the monotonic
3423             clock could be off if that occurs. This is known to happen
3424             on Mac OS X. It has not been tested whether it occurs on
3425             either Windows or on Linux.
3426 
3427         Throws:
3428             $(D TimeException) if it fails to get the time.
3429       +/
3430     static @property TickDuration currSystemTick() @trusted nothrow @nogc
3431     {
3432         import core.internal.abort : abort;
3433         version (WASI) {
3434             time_result_t timestamp_res = clock_time_get(CLOCK_REALTIME, -1);
3435             if (timestamp_res.errno)
3436             {
3437                 import core.internal.abort : abort;
3438                 abort("Call to clock_time_get failed.");
3439             }
3440             return TickDuration(timestamp_res.timestamp);
3441         }
3442         else version (Windows)
3443         {
3444             ulong ticks = void;
3445             QueryPerformanceCounter(cast(long*)&ticks);
3446             return TickDuration(ticks);
3447         }
3448         else version (Darwin)
3449         {
3450             static if (is(typeof(mach_absolute_time)))
3451                 return TickDuration(cast(long)mach_absolute_time());
3452             else
3453             {
3454                 timeval tv = void;
3455                 gettimeofday(&tv, null);
3456                 return TickDuration(tv.tv_sec * TickDuration.ticksPerSec +
3457                                     tv.tv_usec * TickDuration.ticksPerSec / 1000 / 1000);
3458             }
3459         }
3460         else version (Posix)
3461         {
3462             static if (is(typeof(clock_gettime)))
3463             {
3464                 timespec ts = void;
3465                 immutable error = clock_gettime(CLOCK_MONOTONIC, &ts);
3466                 // CLOCK_MONOTONIC is supported and if tv_sec is long or larger
3467                 // overflow won't happen before 292 billion years A.D.
3468                 static if (ts.tv_sec.max < long.max)
3469                 {
3470                     if (error)
3471                     {
3472                         import core.internal.abort : abort;
3473                         abort("Call to clock_gettime failed.");
3474                     }
3475                 }
3476                 return TickDuration(ts.tv_sec * TickDuration.ticksPerSec +
3477                                     ts.tv_nsec * TickDuration.ticksPerSec / 1000 / 1000 / 1000);
3478             }
3479             else
3480             {
3481                 timeval tv = void;
3482                 gettimeofday(&tv, null);
3483                 return TickDuration(tv.tv_sec * TickDuration.ticksPerSec +
3484                                     tv.tv_usec * TickDuration.ticksPerSec / 1000 / 1000);
3485             }
3486         }
3487     }
3488 
3489     version (CoreUnittest) @safe nothrow unittest
3490     {
3491         assert(TickDuration.currSystemTick.length > 0);
3492     }
3493 }
3494 
3495 /++
3496     Generic way of converting between two time units. Conversions to smaller
3497     units use truncating division. Years and months can be converted to each
3498     other, small units can be converted to each other, but years and months
3499     cannot be converted to or from smaller units (due to the varying number
3500     of days in a month or year).
3501 
3502     Params:
3503         from  = The units of time to convert from.
3504         to    = The units of time to convert to.
3505         value = The value to convert.
3506   +/
3507 long convert(string from, string to)(long value) @safe pure nothrow @nogc
3508     if (((from == "weeks" ||
3509          from == "days" ||
3510          from == "hours" ||
3511          from == "minutes" ||
3512          from == "seconds" ||
3513          from == "msecs" ||
3514          from == "usecs" ||
3515          from == "hnsecs" ||
3516          from == "nsecs") &&
3517         (to == "weeks" ||
3518          to == "days" ||
3519          to == "hours" ||
3520          to == "minutes" ||
3521          to == "seconds" ||
3522          to == "msecs" ||
3523          to == "usecs" ||
3524          to == "hnsecs" ||
3525          to == "nsecs")) ||
3526        ((from == "years" || from == "months") && (to == "years" || to == "months")))
3527 {
3528     static if (from == "years")
3529     {
3530         static if (to == "years")
3531             return value;
3532         else static if (to == "months")
3533             return value * 12;
3534         else
3535             static assert(0, "A generic month or year cannot be converted to or from smaller units.");
3536     }
3537     else static if (from == "months")
3538     {
3539         static if (to == "years")
3540             return value / 12;
3541         else static if (to == "months")
3542             return value;
3543         else
3544             static assert(0, "A generic month or year cannot be converted to or from smaller units.");
3545     }
3546     else static if (from == "nsecs" && to == "nsecs")
3547         return value;
3548     else static if (from == "nsecs")
3549         return convert!("hnsecs", to)(value / 100);
3550     else static if (to == "nsecs")
3551         return convert!(from, "hnsecs")(value) * 100;
3552     else
3553         return (hnsecsPer!from * value) / hnsecsPer!to;
3554 }
3555 
3556 ///
3557 unittest
3558 {
3559     assert(convert!("years", "months")(1) == 12);
3560     assert(convert!("months", "years")(12) == 1);
3561 
3562     assert(convert!("weeks", "days")(1) == 7);
3563     assert(convert!("hours", "seconds")(1) == 3600);
3564     assert(convert!("seconds", "days")(1) == 0);
3565     assert(convert!("seconds", "days")(86_400) == 1);
3566 
3567     assert(convert!("nsecs", "nsecs")(1) == 1);
3568     assert(convert!("nsecs", "hnsecs")(1) == 0);
3569     assert(convert!("hnsecs", "nsecs")(1) == 100);
3570     assert(convert!("nsecs", "seconds")(1) == 0);
3571     assert(convert!("seconds", "nsecs")(1) == 1_000_000_000);
3572 }
3573 
3574 unittest
3575 {
3576     foreach (units; AliasSeq!("weeks", "days", "hours", "seconds", "msecs", "usecs", "hnsecs", "nsecs"))
3577     {
3578         static assert(!__traits(compiles, convert!("years", units)(12)), units);
3579         static assert(!__traits(compiles, convert!(units, "years")(12)), units);
3580     }
3581 
3582     foreach (units; AliasSeq!("years", "months", "weeks", "days",
3583                                "hours", "seconds", "msecs", "usecs", "hnsecs", "nsecs"))
3584     {
3585         assert(convert!(units, units)(12) == 12);
3586     }
3587 
3588     assert(convert!("weeks", "hnsecs")(1) == 6_048_000_000_000L);
3589     assert(convert!("days", "hnsecs")(1) == 864_000_000_000L);
3590     assert(convert!("hours", "hnsecs")(1) == 36_000_000_000L);
3591     assert(convert!("minutes", "hnsecs")(1) == 600_000_000L);
3592     assert(convert!("seconds", "hnsecs")(1) == 10_000_000L);
3593     assert(convert!("msecs", "hnsecs")(1) == 10_000);
3594     assert(convert!("usecs", "hnsecs")(1) == 10);
3595 
3596     assert(convert!("hnsecs", "weeks")(6_048_000_000_000L) == 1);
3597     assert(convert!("hnsecs", "days")(864_000_000_000L) == 1);
3598     assert(convert!("hnsecs", "hours")(36_000_000_000L) == 1);
3599     assert(convert!("hnsecs", "minutes")(600_000_000L) == 1);
3600     assert(convert!("hnsecs", "seconds")(10_000_000L) == 1);
3601     assert(convert!("hnsecs", "msecs")(10_000) == 1);
3602     assert(convert!("hnsecs", "usecs")(10) == 1);
3603 
3604     assert(convert!("weeks", "days")(1) == 7);
3605     assert(convert!("days", "weeks")(7) == 1);
3606 
3607     assert(convert!("days", "hours")(1) == 24);
3608     assert(convert!("hours", "days")(24) == 1);
3609 
3610     assert(convert!("hours", "minutes")(1) == 60);
3611     assert(convert!("minutes", "hours")(60) == 1);
3612 
3613     assert(convert!("minutes", "seconds")(1) == 60);
3614     assert(convert!("seconds", "minutes")(60) == 1);
3615 
3616     assert(convert!("seconds", "msecs")(1) == 1000);
3617     assert(convert!("msecs", "seconds")(1000) == 1);
3618 
3619     assert(convert!("msecs", "usecs")(1) == 1000);
3620     assert(convert!("usecs", "msecs")(1000) == 1);
3621 
3622     assert(convert!("usecs", "hnsecs")(1) == 10);
3623     assert(convert!("hnsecs", "usecs")(10) == 1);
3624 
3625     assert(convert!("weeks", "nsecs")(1) == 604_800_000_000_000L);
3626     assert(convert!("days", "nsecs")(1) == 86_400_000_000_000L);
3627     assert(convert!("hours", "nsecs")(1) == 3_600_000_000_000L);
3628     assert(convert!("minutes", "nsecs")(1) == 60_000_000_000L);
3629     assert(convert!("seconds", "nsecs")(1) == 1_000_000_000L);
3630     assert(convert!("msecs", "nsecs")(1) == 1_000_000);
3631     assert(convert!("usecs", "nsecs")(1) == 1000);
3632     assert(convert!("hnsecs", "nsecs")(1) == 100);
3633 
3634     assert(convert!("nsecs", "weeks")(604_800_000_000_000L) == 1);
3635     assert(convert!("nsecs", "days")(86_400_000_000_000L) == 1);
3636     assert(convert!("nsecs", "hours")(3_600_000_000_000L) == 1);
3637     assert(convert!("nsecs", "minutes")(60_000_000_000L) == 1);
3638     assert(convert!("nsecs", "seconds")(1_000_000_000L) == 1);
3639     assert(convert!("nsecs", "msecs")(1_000_000) == 1);
3640     assert(convert!("nsecs", "usecs")(1000) == 1);
3641     assert(convert!("nsecs", "hnsecs")(100) == 1);
3642 }
3643 
3644 /++
3645     Exception type used by core.time.
3646   +/
3647 class TimeException : Exception
3648 {
3649     /++
3650         Params:
3651             msg  = The message for the exception.
3652             file = The file where the exception occurred.
3653             line = The line number where the exception occurred.
3654             next = The previous exception in the chain of exceptions, if any.
3655       +/
3656     this(string msg, string file = __FILE__, size_t line = __LINE__, Throwable next = null) @safe pure nothrow
3657     {
3658         super(msg, file, line, next);
3659     }
3660 
3661     /++
3662         Params:
3663             msg  = The message for the exception.
3664             next = The previous exception in the chain of exceptions.
3665             file = The file where the exception occurred.
3666             line = The line number where the exception occurred.
3667       +/
3668     this(string msg, Throwable next, string file = __FILE__, size_t line = __LINE__) @safe pure nothrow
3669     {
3670         super(msg, file, line, next);
3671     }
3672 }
3673 
3674 unittest
3675 {
3676     {
3677         auto e = new TimeException("hello");
3678         assert(e.msg == "hello");
3679         assert(e.file == __FILE__);
3680         assert(e.line == __LINE__ - 3);
3681         assert(e.next is null);
3682     }
3683 
3684     {
3685         auto next = new Exception("foo");
3686         auto e = new TimeException("goodbye", next);
3687         assert(e.msg == "goodbye");
3688         assert(e.file == __FILE__);
3689         assert(e.line == __LINE__ - 3);
3690         assert(e.next is next);
3691     }
3692 }
3693 
3694 
3695 
3696 /++
3697     Returns the absolute value of a duration.
3698   +/
3699 Duration abs(Duration duration) @safe pure nothrow @nogc
3700 {
3701     return Duration(_abs(duration._hnsecs));
3702 }
3703 
3704 /++ Ditto +/
3705 deprecated("TickDuration has been deprecated, please use Duration or MonoTime instead")
3706 TickDuration abs(TickDuration duration) @safe pure nothrow @nogc
3707 {
3708     return TickDuration(_abs(duration.length));
3709 }
3710 
3711 unittest
3712 {
3713     assert(abs(dur!"msecs"(5)) == dur!"msecs"(5));
3714     assert(abs(dur!"msecs"(-5)) == dur!"msecs"(5));
3715 }
3716 
3717 deprecated unittest
3718 {
3719     assert((abs(TickDuration(17)) == TickDuration(17)) == true);
3720     assert((abs(TickDuration(-17)) == TickDuration(17)) == true);
3721 }
3722 
3723 
3724 //==============================================================================
3725 // Private Section.
3726 //
3727 // Much of this is a copy or simplified copy of what's in std.datetime.
3728 //==============================================================================
3729 private:
3730 
3731 
3732 /+
3733     Template to help with converting between time units.
3734  +/
3735 template hnsecsPer(string units)
3736     if (units == "weeks" ||
3737        units == "days" ||
3738        units == "hours" ||
3739        units == "minutes" ||
3740        units == "seconds" ||
3741        units == "msecs" ||
3742        units == "usecs" ||
3743        units == "hnsecs")
3744 {
3745     static if (units == "hnsecs")
3746         enum hnsecsPer = 1L;
3747     else static if (units == "usecs")
3748         enum hnsecsPer = 10L;
3749     else static if (units == "msecs")
3750         enum hnsecsPer = 1000 * hnsecsPer!"usecs";
3751     else static if (units == "seconds")
3752         enum hnsecsPer = 1000 * hnsecsPer!"msecs";
3753     else static if (units == "minutes")
3754         enum hnsecsPer = 60 * hnsecsPer!"seconds";
3755     else static if (units == "hours")
3756         enum hnsecsPer = 60 * hnsecsPer!"minutes";
3757     else static if (units == "days")
3758         enum hnsecsPer = 24 * hnsecsPer!"hours";
3759     else static if (units == "weeks")
3760         enum hnsecsPer = 7 * hnsecsPer!"days";
3761 }
3762 
3763 /+
3764     Splits out a particular unit from hnsecs and gives you the value for that
3765     unit and the remaining hnsecs. It really shouldn't be used unless all units
3766     larger than the given units have already been split out.
3767 
3768     Params:
3769         units  = The units to split out.
3770         hnsecs = The current total hnsecs. Upon returning, it is the hnsecs left
3771                  after splitting out the given units.
3772 
3773     Returns:
3774         The number of the given units from converting hnsecs to those units.
3775   +/
3776 long splitUnitsFromHNSecs(string units)(ref long hnsecs) @safe pure nothrow @nogc
3777     if (units == "weeks" ||
3778        units == "days" ||
3779        units == "hours" ||
3780        units == "minutes" ||
3781        units == "seconds" ||
3782        units == "msecs" ||
3783        units == "usecs" ||
3784        units == "hnsecs")
3785 {
3786     immutable value = convert!("hnsecs", units)(hnsecs);
3787     hnsecs -= convert!(units, "hnsecs")(value);
3788 
3789     return value;
3790 }
3791 
3792 unittest
3793 {
3794     auto hnsecs = 2595000000007L;
3795     immutable days = splitUnitsFromHNSecs!"days"(hnsecs);
3796     assert(days == 3);
3797     assert(hnsecs == 3000000007);
3798 
3799     immutable minutes = splitUnitsFromHNSecs!"minutes"(hnsecs);
3800     assert(minutes == 5);
3801     assert(hnsecs == 7);
3802 }
3803 
3804 /+
3805     Whether all of the given strings are among the accepted strings.
3806   +/
3807 bool allAreAcceptedUnits(acceptedUnits...)(scope string[] units)
3808 {
3809     foreach (unit; units)
3810     {
3811         bool found = false;
3812         foreach (acceptedUnit; acceptedUnits)
3813         {
3814             if (unit == acceptedUnit)
3815             {
3816                 found = true;
3817                 break;
3818             }
3819         }
3820         if (!found)
3821             return false;
3822     }
3823     return true;
3824 }
3825 
3826 unittest
3827 {
3828     assert(allAreAcceptedUnits!("hours", "seconds")(["seconds", "hours"]));
3829     assert(!allAreAcceptedUnits!("hours", "seconds")(["minutes", "hours"]));
3830     assert(!allAreAcceptedUnits!("hours", "seconds")(["seconds", "minutes"]));
3831     assert(allAreAcceptedUnits!("days", "hours", "minutes", "seconds", "msecs")(["minutes"]));
3832     assert(!allAreAcceptedUnits!("days", "hours", "minutes", "seconds", "msecs")(["usecs"]));
3833     assert(!allAreAcceptedUnits!("days", "hours", "minutes", "seconds", "msecs")(["secs"]));
3834 }
3835 
3836 
3837 /+
3838     Whether the given time unit strings are arranged in order from largest to
3839     smallest.
3840   +/
3841 bool unitsAreInDescendingOrder(scope string[] units)
3842 {
3843     if (units.length <= 1)
3844         return true;
3845 
3846     immutable string[] timeStrings = ["nsecs", "hnsecs", "usecs", "msecs", "seconds",
3847                                       "minutes", "hours", "days", "weeks", "months", "years"];
3848     size_t currIndex = 42;
3849     foreach (i, timeStr; timeStrings)
3850     {
3851         if (units[0] == timeStr)
3852         {
3853             currIndex = i;
3854             break;
3855         }
3856     }
3857     assert(currIndex != 42);
3858 
3859     foreach (unit; units[1 .. $])
3860     {
3861         size_t nextIndex = 42;
3862         foreach (i, timeStr; timeStrings)
3863         {
3864             if (unit == timeStr)
3865             {
3866                 nextIndex = i;
3867                 break;
3868             }
3869         }
3870         assert(nextIndex != 42);
3871 
3872         if (currIndex <= nextIndex)
3873             return false;
3874         currIndex = nextIndex;
3875     }
3876     return true;
3877 }
3878 
3879 unittest
3880 {
3881     assert(unitsAreInDescendingOrder(["years", "months", "weeks", "days", "hours", "minutes",
3882                                      "seconds", "msecs", "usecs", "hnsecs", "nsecs"]));
3883     assert(unitsAreInDescendingOrder(["weeks", "hours", "msecs"]));
3884     assert(unitsAreInDescendingOrder(["days", "hours", "minutes"]));
3885     assert(unitsAreInDescendingOrder(["hnsecs"]));
3886     assert(!unitsAreInDescendingOrder(["days", "hours", "hours"]));
3887     assert(!unitsAreInDescendingOrder(["days", "hours", "days"]));
3888 }
3889 
3890 version (Darwin)
3891 long machTicksPerSecond() @nogc nothrow
3892 {
3893     // Be optimistic that ticksPerSecond (1e9*denom/numer) is integral. So far
3894     // so good on Darwin based platforms OS X, iOS.
3895     import core.internal.abort : abort;
3896     mach_timebase_info_data_t info;
3897     if (mach_timebase_info(&info) != 0)
3898         abort("Failed in mach_timebase_info().");
3899 
3900     long scaledDenom = 1_000_000_000L * info.denom;
3901     if (scaledDenom % info.numer != 0)
3902         abort("Non integral ticksPerSecond from mach_timebase_info.");
3903     return scaledDenom / info.numer;
3904 }
3905 
3906 /+
3907     Local version of abs, since std.math.abs is in Phobos, not druntime.
3908   +/
3909 long _abs(long val) @safe pure nothrow @nogc
3910 {
3911     return val >= 0 ? val : -val;
3912 }
3913 
3914 double _abs(double val) @safe pure nothrow @nogc
3915 {
3916     return val >= 0.0 ? val : -val;
3917 }
3918 
3919 
3920 version (CoreUnittest)
3921 string doubleToString(double value) @safe pure nothrow
3922 {
3923     string result;
3924     if (value < 0 && cast(long)value == 0)
3925         result = "-0";
3926     else
3927         result = signedToTempString(cast(long)value).idup;
3928     result ~= '.';
3929     result ~= unsignedToTempString(cast(ulong)(_abs((value - cast(long)value) * 1_000_000) + .5));
3930 
3931     while (result[$-1] == '0')
3932         result = result[0 .. $-1];
3933     return result;
3934 }
3935 
3936 unittest
3937 {
3938     auto a = 1.337;
3939     auto aStr = doubleToString(a);
3940     assert(aStr == "1.337", aStr);
3941 
3942     a = 0.337;
3943     aStr = doubleToString(a);
3944     assert(aStr == "0.337", aStr);
3945 
3946     a = -0.337;
3947     aStr = doubleToString(a);
3948     assert(aStr == "-0.337", aStr);
3949 }
3950 
3951 version (CoreUnittest) const(char)* numToStringz()(long value) @trusted pure nothrow
3952 {
3953     return (signedToTempString(value) ~ "\0").ptr;
3954 }
3955 
3956 
3957 import core.internal.traits : AliasSeq;
3958 
3959 
3960 /+ An adjusted copy of std.exception.assertThrown. +/
3961 version (CoreUnittest) void _assertThrown(T : Throwable = Exception, E)
3962                                     (lazy E expression,
3963                                      string msg = null,
3964                                      string file = __FILE__,
3965                                      size_t line = __LINE__)
3966 {
3967     bool thrown = false;
3968 
3969     try
3970         expression();
3971     catch (T t)
3972         thrown = true;
3973 
3974     if (!thrown)
3975     {
3976         immutable tail = msg.length == 0 ? "." : ": " ~ msg;
3977 
3978         throw new AssertError("assertThrown() failed: No " ~ T.stringof ~ " was thrown" ~ tail, file, line);
3979     }
3980 }
3981 
3982 unittest
3983 {
3984 
3985     void throwEx(Throwable t)
3986     {
3987         throw t;
3988     }
3989 
3990     void nothrowEx()
3991     {}
3992 
3993     try
3994         _assertThrown!Exception(throwEx(new Exception("It's an Exception")));
3995     catch (AssertError)
3996         assert(0);
3997 
3998     try
3999         _assertThrown!Exception(throwEx(new Exception("It's an Exception")), "It's a message");
4000     catch (AssertError)
4001         assert(0);
4002 
4003     try
4004         _assertThrown!AssertError(throwEx(new AssertError("It's an AssertError", __FILE__, __LINE__)));
4005     catch (AssertError)
4006         assert(0);
4007 
4008     try
4009         _assertThrown!AssertError(throwEx(new AssertError("It's an AssertError", __FILE__, __LINE__)), "It's a message");
4010     catch (AssertError)
4011         assert(0);
4012 
4013 
4014     {
4015         bool thrown = false;
4016         try
4017             _assertThrown!Exception(nothrowEx());
4018         catch (AssertError)
4019             thrown = true;
4020 
4021         assert(thrown);
4022     }
4023 
4024     {
4025         bool thrown = false;
4026         try
4027             _assertThrown!Exception(nothrowEx(), "It's a message");
4028         catch (AssertError)
4029             thrown = true;
4030 
4031         assert(thrown);
4032     }
4033 
4034     {
4035         bool thrown = false;
4036         try
4037             _assertThrown!AssertError(nothrowEx());
4038         catch (AssertError)
4039             thrown = true;
4040 
4041         assert(thrown);
4042     }
4043 
4044     {
4045         bool thrown = false;
4046         try
4047             _assertThrown!AssertError(nothrowEx(), "It's a message");
4048         catch (AssertError)
4049             thrown = true;
4050 
4051         assert(thrown);
4052     }
4053 }
4054 
4055 version (CoreUnittest) deprecated void _assertThrownDep(T : Throwable = Exception, E)
4056                                     (lazy E expression,
4057                                      string msg = null,
4058                                      string file = __FILE__,
4059                                      size_t line = __LINE__)
4060 {
4061     bool thrown = false;
4062 
4063     try
4064         expression();
4065     catch (T t)
4066         thrown = true;
4067 
4068     if (!thrown)
4069     {
4070         immutable tail = msg.length == 0 ? "." : ": " ~ msg;
4071 
4072         throw new AssertError("assertThrown() failed: No " ~ T.stringof ~ " was thrown" ~ tail, file, line);
4073     }
4074 }
4075 
4076 
4077 
4078 version (CoreUnittest) void assertApprox(D, E)(D actual,
4079                                           E lower,
4080                                           E upper,
4081                                           string msg = "unittest failure",
4082                                           size_t line = __LINE__)
4083     if (is(D : const Duration) && is(E : const Duration))
4084 {
4085     if (actual < lower)
4086         throw new AssertError(msg ~ ": lower: " ~ actual.toString(), __FILE__, line);
4087     if (actual > upper)
4088         throw new AssertError(msg ~ ": upper: " ~ actual.toString(), __FILE__, line);
4089 }
4090 
4091 version (CoreUnittest) deprecated void assertApprox(D, E)(D actual,
4092                                           E lower,
4093                                           E upper,
4094                                           string msg = "unittest failure",
4095                                           size_t line = __LINE__)
4096     if (is(D : const TickDuration) && is(E : const TickDuration))
4097 {
4098     if (actual.length < lower.length || actual.length > upper.length)
4099     {
4100         throw new AssertError(msg ~ (": [" ~ signedToTempString(lower.length) ~ "] [" ~
4101                               signedToTempString(actual.length) ~ "] [" ~
4102                               signedToTempString(upper.length) ~ "]").idup,
4103                               __FILE__, line);
4104     }
4105 }
4106 
4107 version (CoreUnittest) void assertApprox(MT)(MT actual,
4108                                         MT lower,
4109                                         MT upper,
4110                                         string msg = "unittest failure",
4111                                         size_t line = __LINE__)
4112     if (is(MT == MonoTimeImpl!type, ClockType type))
4113 {
4114     assertApprox(actual._ticks, lower._ticks, upper._ticks, msg, line);
4115 }
4116 
4117 version (CoreUnittest) void assertApprox()(long actual,
4118                                       long lower,
4119                                       long upper,
4120                                       string msg = "unittest failure",
4121                                       size_t line = __LINE__)
4122 {
4123     if (actual < lower)
4124         throw new AssertError(msg ~ ": lower: " ~ signedToTempString(actual).idup, __FILE__, line);
4125     if (actual > upper)
4126         throw new AssertError(msg ~ ": upper: " ~ signedToTempString(actual).idup, __FILE__, line);
4127 }