The OpenD Programming Language

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