The OpenD Programming Language

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