"Fossies" - the Fresh Open Source Software Archive

Member "dmd2/src/druntime/src/core/time.d" (20 Nov 2020, 148017 Bytes) of package /linux/misc/dmd.2.094.2.linux.tar.xz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) D source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file.

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