| // 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();})(); | |
| } |