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