|  | // Written in the D programming language | 
|  |  | 
|  | /++ | 
|  | Module containing Date/Time functionality. | 
|  |  | 
|  | This module provides: | 
|  | $(UL | 
|  | $(LI Types to represent points in time: | 
|  | $(REF SysTime,std,_datetime,systime), | 
|  | $(REF Date,std,_datetime,date), | 
|  | $(REF TimeOfDay,std,_datetime,date), | 
|  | $(REF DateTime,std,_datetime,date).) | 
|  | $(LI Types to represent intervals of time.) | 
|  | $(LI Types to represent ranges over intervals of time.) | 
|  | $(LI Types to represent time zones (used by | 
|  | $(REF SysTime,std,_datetime,systime)).) | 
|  | $(LI A platform-independent, high precision stopwatch type: | 
|  | $(LREF StopWatch)) | 
|  | $(LI Benchmarking functions.) | 
|  | $(LI Various helper functions.) | 
|  | ) | 
|  |  | 
|  | Closely related to std.datetime is <a href="core_time.html">$(D core.time)</a>, | 
|  | and some of the time types used in std.datetime come from there - such as | 
|  | $(REF Duration, core,time), $(REF TickDuration, core,time), and | 
|  | $(REF FracSec, core,time). | 
|  | core.time is publically imported into std.datetime, it isn't necessary | 
|  | to import it separately. | 
|  |  | 
|  | Three of the main concepts used in this module are time points, time | 
|  | durations, and time intervals. | 
|  |  | 
|  | A time point is a specific point in time. e.g. January 5th, 2010 | 
|  | or 5:00. | 
|  |  | 
|  | A time duration is a length of time with units. e.g. 5 days or 231 seconds. | 
|  |  | 
|  | A time interval indicates a period of time associated with a fixed point in | 
|  | time. It is either two time points associated with each other, | 
|  | indicating the time starting at the first point up to, but not including, | 
|  | the second point - e.g. [January 5th, 2010 - March 10th, 2010$(RPAREN) - or | 
|  | it is a time point and a time duration associated with one another. e.g. | 
|  | January 5th, 2010 and 5 days, indicating [January 5th, 2010 - | 
|  | January 10th, 2010$(RPAREN). | 
|  |  | 
|  | Various arithmetic operations are supported between time points and | 
|  | durations (e.g. the difference between two time points is a time duration), | 
|  | and ranges can be gotten from time intervals, so range-based operations may | 
|  | be done on a series of time points. | 
|  |  | 
|  | The types that the typical user is most likely to be interested in are | 
|  | $(REF Date,std,_datetime,date) (if they want dates but don't care about | 
|  | time), $(REF DateTime,std,_datetime,date) (if they want dates and times | 
|  | but don't care about time zones), $(REF SysTime,std,_datetime,systime) (if | 
|  | they want the date and time from the OS and/or do care about time zones), | 
|  | and StopWatch (a platform-independent, high precision stop watch). | 
|  | $(REF Date,std,_datetime,date) and $(REF DateTime,std,_datetime,date) are | 
|  | optimized for calendar-based operations, while | 
|  | $(REF SysTime,std,_datetime,systime) is designed for dealing with time from | 
|  | the OS. Check out their specific documentation for more details. | 
|  |  | 
|  | To get the current time, use $(REF Clock.currTime,std,_datetime,systime). | 
|  | It will return the current time as a $(REF SysTime,std,_datetime,systime). To | 
|  | print it, $(D toString) is sufficient, but if using $(D toISOString), | 
|  | $(D toISOExtString), or $(D toSimpleString), use the corresponding | 
|  | $(D fromISOString), $(D fromISOExtString), or $(D fromSimpleString) to | 
|  | create a $(REF SysTime,std,_datetime,systime) from the string. | 
|  |  | 
|  | -------------------- | 
|  | auto currentTime = Clock.currTime(); | 
|  | auto timeString = currentTime.toISOExtString(); | 
|  | auto restoredTime = SysTime.fromISOExtString(timeString); | 
|  | -------------------- | 
|  |  | 
|  | Various functions take a string (or strings) to represent a unit of time | 
|  | (e.g. $(D convert!("days", "hours")(numDays))). The valid strings to use | 
|  | with such functions are $(D "years"), $(D "months"), $(D "weeks"), | 
|  | $(D "days"), $(D "hours"), $(D "minutes"), $(D "seconds"), | 
|  | $(D "msecs") (milliseconds), $(D "usecs") (microseconds), | 
|  | $(D "hnsecs") (hecto-nanoseconds - i.e. 100 ns), or some subset thereof. | 
|  | There are a few functions in core.time which take $(D "nsecs"), but because | 
|  | nothing in std.datetime has precision greater than hnsecs, and very little | 
|  | in core.time does, no functions in std.datetime accept $(D "nsecs"). | 
|  | To remember which units are abbreviated and which aren't, | 
|  | all units seconds and greater use their full names, and all | 
|  | sub-second units are abbreviated (since they'd be rather long if they | 
|  | weren't). | 
|  |  | 
|  | Note: | 
|  | $(REF DateTimeException,std,_datetime,date) is an alias for | 
|  | $(REF TimeException, core,time), so you don't need to worry about | 
|  | core.time functions and std.datetime functions throwing different | 
|  | exception types (except in the rare case that they throw something other | 
|  | than $(REF TimeException, core,time) or | 
|  | $(REF DateTimeException,std,_datetime,date)). | 
|  |  | 
|  | See_Also: | 
|  | $(DDLINK intro-to-_datetime, Introduction to std.datetime, | 
|  | Introduction to std._datetime)<br> | 
|  | $(HTTP en.wikipedia.org/wiki/ISO_8601, ISO 8601)<br> | 
|  | $(HTTP en.wikipedia.org/wiki/Tz_database, | 
|  | Wikipedia entry on TZ Database)<br> | 
|  | $(HTTP en.wikipedia.org/wiki/List_of_tz_database_time_zones, | 
|  | List of Time Zones)<br> | 
|  |  | 
|  | License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). | 
|  | Authors:   Jonathan M Davis and Kato Shoichi | 
|  | Source:    $(PHOBOSSRC std/_datetime/package.d) | 
|  | +/ | 
|  | module std.datetime; | 
|  |  | 
|  | public import core.time; | 
|  | public import std.datetime.date; | 
|  | public import std.datetime.interval; | 
|  | public import std.datetime.systime; | 
|  | public import std.datetime.timezone; | 
|  |  | 
|  | import core.exception : AssertError; | 
|  | import std.functional : unaryFun; | 
|  | import std.traits; | 
|  | import std.typecons : Flag, Yes, No; | 
|  |  | 
|  |  | 
|  | // Verify module example. | 
|  | @safe unittest | 
|  | { | 
|  | auto currentTime = Clock.currTime(); | 
|  | auto timeString = currentTime.toISOExtString(); | 
|  | auto restoredTime = SysTime.fromISOExtString(timeString); | 
|  | } | 
|  |  | 
|  | // Verify Examples for core.time.Duration which couldn't be in core.time. | 
|  | @safe unittest | 
|  | { | 
|  | assert(std.datetime.Date(2010, 9, 7) + dur!"days"(5) == | 
|  | std.datetime.Date(2010, 9, 12)); | 
|  |  | 
|  | assert(std.datetime.Date(2010, 9, 7) - std.datetime.Date(2010, 10, 3) == | 
|  | dur!"days"(-26)); | 
|  | } | 
|  |  | 
|  | @safe unittest | 
|  | { | 
|  | import std.traits : hasUnsharedAliasing; | 
|  | /* Issue 6642 */ | 
|  | static assert(!hasUnsharedAliasing!Date); | 
|  | static assert(!hasUnsharedAliasing!TimeOfDay); | 
|  | static assert(!hasUnsharedAliasing!DateTime); | 
|  | static assert(!hasUnsharedAliasing!SysTime); | 
|  | } | 
|  |  | 
|  |  | 
|  | //============================================================================== | 
|  | // Everything after here will be deprecated after we have replacements which | 
|  | // use MonoTime and Duration. | 
|  | //============================================================================== | 
|  |  | 
|  |  | 
|  | /++ | 
|  | Used by StopWatch to indicate whether it should start immediately upon | 
|  | construction. | 
|  |  | 
|  | If set to $(D AutoStart.no), then the stopwatch is not started when it is | 
|  | constructed. | 
|  |  | 
|  | Otherwise, if set to $(D AutoStart.yes), then the stopwatch is started when | 
|  | it is constructed. | 
|  | +/ | 
|  | alias AutoStart = Flag!"autoStart"; | 
|  |  | 
|  |  | 
|  | /++ | 
|  | $(RED This will be deprecated in 2.076. Please use | 
|  | $(REF StopWatch,std,datetime,stopwatch) instead. It uses | 
|  | $(REF Monotime,core,time) and $(REF Duration,core,time) rather | 
|  | than $(REF TickDuration,core,time), which will also be deprecated in | 
|  | 2.076.) | 
|  |  | 
|  | $(D StopWatch) measures time as precisely as possible. | 
|  |  | 
|  | This class uses a high-performance counter. On Windows systems, it uses | 
|  | $(D QueryPerformanceCounter), and on Posix systems, it uses | 
|  | $(D clock_gettime) if available, and $(D gettimeofday) otherwise. | 
|  |  | 
|  | But the precision of $(D StopWatch) differs from system to system. It is | 
|  | impossible to for it to be the same from system to system since the precision | 
|  | of the system clock varies from system to system, and other system-dependent | 
|  | and situation-dependent stuff (such as the overhead of a context switch | 
|  | between threads) can also affect $(D StopWatch)'s accuracy. | 
|  | +/ | 
|  | @safe struct StopWatch | 
|  | { | 
|  | public: | 
|  |  | 
|  | /++ | 
|  | Auto start with constructor. | 
|  | +/ | 
|  | this(AutoStart autostart) @nogc | 
|  | { | 
|  | if (autostart) | 
|  | start(); | 
|  | } | 
|  |  | 
|  | @nogc @safe unittest | 
|  | { | 
|  | auto sw = StopWatch(Yes.autoStart); | 
|  | sw.stop(); | 
|  | } | 
|  |  | 
|  |  | 
|  | /// | 
|  | bool opEquals(const StopWatch rhs) const pure nothrow @nogc | 
|  | { | 
|  | return opEquals(rhs); | 
|  | } | 
|  |  | 
|  | /// ditto | 
|  | bool opEquals(const ref StopWatch rhs) const pure nothrow @nogc | 
|  | { | 
|  | return _timeStart == rhs._timeStart && | 
|  | _timeMeasured == rhs._timeMeasured; | 
|  | } | 
|  |  | 
|  |  | 
|  | /++ | 
|  | Resets the stop watch. | 
|  | +/ | 
|  | void reset() @nogc | 
|  | { | 
|  | if (_flagStarted) | 
|  | { | 
|  | // Set current system time if StopWatch is measuring. | 
|  | _timeStart = TickDuration.currSystemTick; | 
|  | } | 
|  | else | 
|  | { | 
|  | // Set zero if StopWatch is not measuring. | 
|  | _timeStart.length = 0; | 
|  | } | 
|  |  | 
|  | _timeMeasured.length = 0; | 
|  | } | 
|  |  | 
|  | /// | 
|  | @nogc @safe unittest | 
|  | { | 
|  | StopWatch sw; | 
|  | sw.start(); | 
|  | sw.stop(); | 
|  | sw.reset(); | 
|  | assert(sw.peek().to!("seconds", real)() == 0); | 
|  | } | 
|  |  | 
|  |  | 
|  | /++ | 
|  | Starts the stop watch. | 
|  | +/ | 
|  | void start() @nogc | 
|  | { | 
|  | assert(!_flagStarted); | 
|  | _flagStarted = true; | 
|  | _timeStart = TickDuration.currSystemTick; | 
|  | } | 
|  |  | 
|  | @nogc @system unittest | 
|  | { | 
|  | StopWatch sw; | 
|  | sw.start(); | 
|  | auto t1 = sw.peek(); | 
|  | bool doublestart = true; | 
|  | try | 
|  | sw.start(); | 
|  | catch (AssertError e) | 
|  | doublestart = false; | 
|  | assert(!doublestart); | 
|  | sw.stop(); | 
|  | assert((t1 - sw.peek()).to!("seconds", real)() <= 0); | 
|  | } | 
|  |  | 
|  |  | 
|  | /++ | 
|  | Stops the stop watch. | 
|  | +/ | 
|  | void stop() @nogc | 
|  | { | 
|  | assert(_flagStarted); | 
|  | _flagStarted = false; | 
|  | _timeMeasured += TickDuration.currSystemTick - _timeStart; | 
|  | } | 
|  |  | 
|  | @nogc @system unittest | 
|  | { | 
|  | StopWatch sw; | 
|  | sw.start(); | 
|  | sw.stop(); | 
|  | auto t1 = sw.peek(); | 
|  | bool doublestop = true; | 
|  | try | 
|  | sw.stop(); | 
|  | catch (AssertError e) | 
|  | doublestop = false; | 
|  | assert(!doublestop); | 
|  | assert((t1 - sw.peek()).to!("seconds", real)() == 0); | 
|  | } | 
|  |  | 
|  |  | 
|  | /++ | 
|  | Peek at the amount of time which has passed since the stop watch was | 
|  | started. | 
|  | +/ | 
|  | TickDuration peek() const @nogc | 
|  | { | 
|  | if (_flagStarted) | 
|  | return TickDuration.currSystemTick - _timeStart + _timeMeasured; | 
|  |  | 
|  | return _timeMeasured; | 
|  | } | 
|  |  | 
|  | @nogc @safe unittest | 
|  | { | 
|  | StopWatch sw; | 
|  | sw.start(); | 
|  | auto t1 = sw.peek(); | 
|  | sw.stop(); | 
|  | auto t2 = sw.peek(); | 
|  | auto t3 = sw.peek(); | 
|  | assert(t1 <= t2); | 
|  | assert(t2 == t3); | 
|  | } | 
|  |  | 
|  |  | 
|  | /++ | 
|  | Set the amount of time which has been measured since the stop watch was | 
|  | started. | 
|  | +/ | 
|  | void setMeasured(TickDuration d) @nogc | 
|  | { | 
|  | reset(); | 
|  | _timeMeasured = d; | 
|  | } | 
|  |  | 
|  | @nogc @safe unittest | 
|  | { | 
|  | StopWatch sw; | 
|  | TickDuration t0; | 
|  | t0.length = 100; | 
|  | sw.setMeasured(t0); | 
|  | auto t1 = sw.peek(); | 
|  | assert(t0 == t1); | 
|  | } | 
|  |  | 
|  |  | 
|  | /++ | 
|  | Confirm whether this stopwatch is measuring time. | 
|  | +/ | 
|  | bool running() @property const pure nothrow @nogc | 
|  | { | 
|  | return _flagStarted; | 
|  | } | 
|  |  | 
|  | @nogc @safe unittest | 
|  | { | 
|  | StopWatch sw1; | 
|  | assert(!sw1.running); | 
|  | sw1.start(); | 
|  | assert(sw1.running); | 
|  | sw1.stop(); | 
|  | assert(!sw1.running); | 
|  | StopWatch sw2 = Yes.autoStart; | 
|  | assert(sw2.running); | 
|  | sw2.stop(); | 
|  | assert(!sw2.running); | 
|  | sw2.start(); | 
|  | assert(sw2.running); | 
|  | } | 
|  |  | 
|  |  | 
|  |  | 
|  |  | 
|  | private: | 
|  |  | 
|  | // true if observing. | 
|  | bool _flagStarted = false; | 
|  |  | 
|  | // TickDuration at the time of StopWatch starting measurement. | 
|  | TickDuration _timeStart; | 
|  |  | 
|  | // Total time that StopWatch ran. | 
|  | TickDuration _timeMeasured; | 
|  | } | 
|  |  | 
|  | /// | 
|  | @safe unittest | 
|  | { | 
|  | void writeln(S...)(S args){} | 
|  | static void bar() {} | 
|  |  | 
|  | StopWatch sw; | 
|  | enum n = 100; | 
|  | TickDuration[n] times; | 
|  | TickDuration last = TickDuration.from!"seconds"(0); | 
|  | foreach (i; 0 .. n) | 
|  | { | 
|  | sw.start(); //start/resume mesuring. | 
|  | foreach (unused; 0 .. 1_000_000) | 
|  | bar(); | 
|  | sw.stop();  //stop/pause measuring. | 
|  | //Return value of peek() after having stopped are the always same. | 
|  | writeln((i + 1) * 1_000_000, " times done, lap time: ", | 
|  | sw.peek().msecs, "[ms]"); | 
|  | times[i] = sw.peek() - last; | 
|  | last = sw.peek(); | 
|  | } | 
|  | real sum = 0; | 
|  | // To get the number of seconds, | 
|  | // use properties of TickDuration. | 
|  | // (seconds, msecs, usecs, hnsecs) | 
|  | foreach (t; times) | 
|  | sum += t.hnsecs; | 
|  | writeln("Average time: ", sum/n, " hnsecs"); | 
|  | } | 
|  |  | 
|  |  | 
|  | /++ | 
|  | $(RED This will be deprecated in 2.076. Please use | 
|  | $(REF benchmark,std,datetime,stopwatch) instead. It uses | 
|  | $(REF Monotime,core,time) and $(REF Duration,core,time) rather | 
|  | than $(REF TickDuration,core,time), which will also be deprecated in | 
|  | 2.076.) | 
|  |  | 
|  | Benchmarks code for speed assessment and comparison. | 
|  |  | 
|  | Params: | 
|  | fun = aliases of callable objects (e.g. function names). Each should | 
|  | take no arguments. | 
|  | n   = The number of times each function is to be executed. | 
|  |  | 
|  | Returns: | 
|  | The amount of time (as a $(REF TickDuration, core,time)) that it took to | 
|  | call each function $(D n) times. The first value is the length of time | 
|  | that it took to call $(D fun[0]) $(D n) times. The second value is the | 
|  | length of time it took to call $(D fun[1]) $(D n) times. Etc. | 
|  |  | 
|  | Note that casting the TickDurations to $(REF Duration, core,time)s will make | 
|  | the results easier to deal with (and it may change in the future that | 
|  | benchmark will return an array of Durations rather than TickDurations). | 
|  |  | 
|  | See_Also: | 
|  | $(LREF measureTime) | 
|  | +/ | 
|  | TickDuration[fun.length] benchmark(fun...)(uint n) | 
|  | { | 
|  | TickDuration[fun.length] result; | 
|  | StopWatch sw; | 
|  | sw.start(); | 
|  |  | 
|  | foreach (i, unused; fun) | 
|  | { | 
|  | sw.reset(); | 
|  | foreach (j; 0 .. n) | 
|  | fun[i](); | 
|  | result[i] = sw.peek(); | 
|  | } | 
|  |  | 
|  | return result; | 
|  | } | 
|  |  | 
|  | /// | 
|  | @safe unittest | 
|  | { | 
|  | import std.conv : to; | 
|  | int a; | 
|  | void f0() {} | 
|  | void f1() {auto b = a;} | 
|  | void f2() {auto b = to!string(a);} | 
|  | auto r = benchmark!(f0, f1, f2)(10_000); | 
|  | auto f0Result = to!Duration(r[0]); // time f0 took to run 10,000 times | 
|  | auto f1Result = to!Duration(r[1]); // time f1 took to run 10,000 times | 
|  | auto f2Result = to!Duration(r[2]); // time f2 took to run 10,000 times | 
|  | } | 
|  |  | 
|  | @safe unittest | 
|  | { | 
|  | int a; | 
|  | void f0() {} | 
|  | //void f1() {auto b = to!(string)(a);} | 
|  | void f2() {auto b = (a);} | 
|  | auto r = benchmark!(f0, f2)(100); | 
|  | } | 
|  |  | 
|  |  | 
|  | /++ | 
|  | Return value of benchmark with two functions comparing. | 
|  | +/ | 
|  | @safe struct ComparingBenchmarkResult | 
|  | { | 
|  | /++ | 
|  | Evaluation value | 
|  |  | 
|  | This returns the evaluation value of performance as the ratio of | 
|  | baseFunc's time over targetFunc's time. If performance is high, this | 
|  | returns a high value. | 
|  | +/ | 
|  | @property real point() const pure nothrow | 
|  | { | 
|  | return _baseTime.length / cast(const real)_targetTime.length; | 
|  | } | 
|  |  | 
|  |  | 
|  | /++ | 
|  | The time required of the base function | 
|  | +/ | 
|  | @property public TickDuration baseTime() const pure nothrow | 
|  | { | 
|  | return _baseTime; | 
|  | } | 
|  |  | 
|  |  | 
|  | /++ | 
|  | The time required of the target function | 
|  | +/ | 
|  | @property public TickDuration targetTime() const pure nothrow | 
|  | { | 
|  | return _targetTime; | 
|  | } | 
|  |  | 
|  | private: | 
|  |  | 
|  | this(TickDuration baseTime, TickDuration targetTime) pure nothrow | 
|  | { | 
|  | _baseTime = baseTime; | 
|  | _targetTime = targetTime; | 
|  | } | 
|  |  | 
|  | TickDuration _baseTime; | 
|  | TickDuration _targetTime; | 
|  | } | 
|  |  | 
|  |  | 
|  | /++ | 
|  | $(RED This will be deprecated in 2.076. Please use | 
|  | $(REF benchmark,std,datetime,stopwatch) instead. This function has | 
|  | not been ported to $(REF Monotime,core,time) and | 
|  | $(REF Duration,core,time), because it is a trivial wrapper around | 
|  | benchmark.) | 
|  |  | 
|  | Benchmark with two functions comparing. | 
|  |  | 
|  | Params: | 
|  | baseFunc   = The function to become the base of the speed. | 
|  | targetFunc = The function that wants to measure speed. | 
|  | times      = The number of times each function is to be executed. | 
|  | +/ | 
|  | ComparingBenchmarkResult comparingBenchmark(alias baseFunc, | 
|  | alias targetFunc, | 
|  | int times = 0xfff)() | 
|  | { | 
|  | auto t = benchmark!(baseFunc, targetFunc)(times); | 
|  | return ComparingBenchmarkResult(t[0], t[1]); | 
|  | } | 
|  |  | 
|  | /// | 
|  | @safe unittest | 
|  | { | 
|  | void f1x() {} | 
|  | void f2x() {} | 
|  | @safe void f1o() {} | 
|  | @safe void f2o() {} | 
|  | auto b1 = comparingBenchmark!(f1o, f2o, 1)(); // OK | 
|  | //writeln(b1.point); | 
|  | } | 
|  |  | 
|  | //Bug# 8450 | 
|  | @system unittest | 
|  | { | 
|  | @safe    void safeFunc() {} | 
|  | @trusted void trustFunc() {} | 
|  | @system  void sysFunc() {} | 
|  | auto safeResult  = comparingBenchmark!((){safeFunc();}, (){safeFunc();})(); | 
|  | auto trustResult = comparingBenchmark!((){trustFunc();}, (){trustFunc();})(); | 
|  | auto sysResult   = comparingBenchmark!((){sysFunc();}, (){sysFunc();})(); | 
|  | auto mixedResult1  = comparingBenchmark!((){safeFunc();}, (){trustFunc();})(); | 
|  | auto mixedResult2  = comparingBenchmark!((){trustFunc();}, (){sysFunc();})(); | 
|  | auto mixedResult3  = comparingBenchmark!((){safeFunc();}, (){sysFunc();})(); | 
|  | } | 
|  |  | 
|  |  | 
|  | /++ | 
|  | $(RED This will be deprecated in 2.076. Please use | 
|  | $(REF StopWatch,std,datetime,stopwatch) instead. This function has | 
|  | not been ported to $(REF Monotime,core,time) and | 
|  | $(REF Duration,core,time), because it is a trivial wrapper around | 
|  | StopWatch.) | 
|  |  | 
|  | Function for starting to a stop watch time when the function is called | 
|  | and stopping it when its return value goes out of scope and is destroyed. | 
|  |  | 
|  | When the value that is returned by this function is destroyed, | 
|  | $(D func) will run. $(D func) is a unary function that takes a | 
|  | $(REF TickDuration, core,time). | 
|  |  | 
|  | Example: | 
|  | -------------------- | 
|  | { | 
|  | auto mt = measureTime!((TickDuration a) | 
|  | { /+ do something when the scope is exited +/ }); | 
|  | // do something that needs to be timed | 
|  | } | 
|  | -------------------- | 
|  |  | 
|  | which is functionally equivalent to | 
|  |  | 
|  | -------------------- | 
|  | { | 
|  | auto sw = StopWatch(Yes.autoStart); | 
|  | scope(exit) | 
|  | { | 
|  | TickDuration a = sw.peek(); | 
|  | /+ do something when the scope is exited +/ | 
|  | } | 
|  | // do something that needs to be timed | 
|  | } | 
|  | -------------------- | 
|  |  | 
|  | See_Also: | 
|  | $(LREF benchmark) | 
|  | +/ | 
|  | @safe auto measureTime(alias func)() | 
|  | if (isSafe!((){StopWatch sw; unaryFun!func(sw.peek());})) | 
|  | { | 
|  | struct Result | 
|  | { | 
|  | private StopWatch _sw = void; | 
|  | this(AutoStart as) | 
|  | { | 
|  | _sw = StopWatch(as); | 
|  | } | 
|  | ~this() | 
|  | { | 
|  | unaryFun!(func)(_sw.peek()); | 
|  | } | 
|  | } | 
|  | return Result(Yes.autoStart); | 
|  | } | 
|  |  | 
|  | auto measureTime(alias func)() | 
|  | if (!isSafe!((){StopWatch sw; unaryFun!func(sw.peek());})) | 
|  | { | 
|  | struct Result | 
|  | { | 
|  | private StopWatch _sw = void; | 
|  | this(AutoStart as) | 
|  | { | 
|  | _sw = StopWatch(as); | 
|  | } | 
|  | ~this() | 
|  | { | 
|  | unaryFun!(func)(_sw.peek()); | 
|  | } | 
|  | } | 
|  | return Result(Yes.autoStart); | 
|  | } | 
|  |  | 
|  | // Verify Example. | 
|  | @safe unittest | 
|  | { | 
|  | { | 
|  | auto mt = measureTime!((TickDuration a) | 
|  | { /+ do something when the scope is exited +/ }); | 
|  | // do something that needs to be timed | 
|  | } | 
|  |  | 
|  | { | 
|  | auto sw = StopWatch(Yes.autoStart); | 
|  | scope(exit) | 
|  | { | 
|  | TickDuration a = sw.peek(); | 
|  | /+ do something when the scope is exited +/ | 
|  | } | 
|  | // do something that needs to be timed | 
|  | } | 
|  | } | 
|  |  | 
|  | @safe unittest | 
|  | { | 
|  | import std.math : isNaN; | 
|  |  | 
|  | @safe static void func(TickDuration td) | 
|  | { | 
|  | assert(!td.to!("seconds", real)().isNaN()); | 
|  | } | 
|  |  | 
|  | auto mt = measureTime!(func)(); | 
|  |  | 
|  | /+ | 
|  | with (measureTime!((a){assert(a.seconds);})) | 
|  | { | 
|  | // doSomething(); | 
|  | // @@@BUG@@@ doesn't work yet. | 
|  | } | 
|  | +/ | 
|  | } | 
|  |  | 
|  | @safe unittest | 
|  | { | 
|  | import std.math : isNaN; | 
|  |  | 
|  | static void func(TickDuration td) | 
|  | { | 
|  | assert(!td.to!("seconds", real)().isNaN()); | 
|  | } | 
|  |  | 
|  | auto mt = measureTime!(func)(); | 
|  |  | 
|  | /+ | 
|  | with (measureTime!((a){assert(a.seconds);})) | 
|  | { | 
|  | // doSomething(); | 
|  | // @@@BUG@@@ doesn't work yet. | 
|  | } | 
|  | +/ | 
|  | } | 
|  |  | 
|  | //Bug# 8450 | 
|  | @system unittest | 
|  | { | 
|  | @safe    void safeFunc() {} | 
|  | @trusted void trustFunc() {} | 
|  | @system  void sysFunc() {} | 
|  | auto safeResult  = measureTime!((a){safeFunc();})(); | 
|  | auto trustResult = measureTime!((a){trustFunc();})(); | 
|  | auto sysResult   = measureTime!((a){sysFunc();})(); | 
|  | } |