xref: /netbsd-src/external/gpl3/gcc.old/dist/libphobos/src/std/datetime/package.d (revision 627f7eb200a4419d89b531d55fccd2ee3ffdcde0)
1 // Written in the D programming language
2 
3 /++
4     Module containing Date/Time functionality.
5 
6     This module provides:
7     $(UL
8         $(LI Types to represent points in time:
9              $(REF SysTime,std,_datetime,systime),
10              $(REF Date,std,_datetime,date),
11              $(REF TimeOfDay,std,_datetime,date),
12              $(REF DateTime,std,_datetime,date).)
13         $(LI Types to represent intervals of time.)
14         $(LI Types to represent ranges over intervals of time.)
15         $(LI Types to represent time zones (used by
16              $(REF SysTime,std,_datetime,systime)).)
17         $(LI A platform-independent, high precision stopwatch type:
18              $(LREF StopWatch))
19         $(LI Benchmarking functions.)
20         $(LI Various helper functions.)
21     )
22 
23     Closely related to std.datetime is <a href="core_time.html">$(D core.time)</a>,
24     and some of the time types used in std.datetime come from there - such as
25     $(REF Duration, core,time), $(REF TickDuration, core,time), and
26     $(REF FracSec, core,time).
27     core.time is publically imported into std.datetime, it isn't necessary
28     to import it separately.
29 
30     Three of the main concepts used in this module are time points, time
31     durations, and time intervals.
32 
33     A time point is a specific point in time. e.g. January 5th, 2010
34     or 5:00.
35 
36     A time duration is a length of time with units. e.g. 5 days or 231 seconds.
37 
38     A time interval indicates a period of time associated with a fixed point in
39     time. It is either two time points associated with each other,
40     indicating the time starting at the first point up to, but not including,
41     the second point - e.g. [January 5th, 2010 - March 10th, 2010$(RPAREN) - or
42     it is a time point and a time duration associated with one another. e.g.
43     January 5th, 2010 and 5 days, indicating [January 5th, 2010 -
44     January 10th, 2010$(RPAREN).
45 
46     Various arithmetic operations are supported between time points and
47     durations (e.g. the difference between two time points is a time duration),
48     and ranges can be gotten from time intervals, so range-based operations may
49     be done on a series of time points.
50 
51     The types that the typical user is most likely to be interested in are
52     $(REF Date,std,_datetime,date) (if they want dates but don't care about
53     time), $(REF DateTime,std,_datetime,date) (if they want dates and times
54     but don't care about time zones), $(REF SysTime,std,_datetime,systime) (if
55     they want the date and time from the OS and/or do care about time zones),
56     and StopWatch (a platform-independent, high precision stop watch).
57     $(REF Date,std,_datetime,date) and $(REF DateTime,std,_datetime,date) are
58     optimized for calendar-based operations, while
59     $(REF SysTime,std,_datetime,systime) is designed for dealing with time from
60     the OS. Check out their specific documentation for more details.
61 
62     To get the current time, use $(REF Clock.currTime,std,_datetime,systime).
63     It will return the current time as a $(REF SysTime,std,_datetime,systime). To
64     print it, $(D toString) is sufficient, but if using $(D toISOString),
65     $(D toISOExtString), or $(D toSimpleString), use the corresponding
66     $(D fromISOString), $(D fromISOExtString), or $(D fromSimpleString) to
67     create a $(REF SysTime,std,_datetime,systime) from the string.
68 
69 --------------------
70 auto currentTime = Clock.currTime();
71 auto timeString = currentTime.toISOExtString();
72 auto restoredTime = SysTime.fromISOExtString(timeString);
73 --------------------
74 
75     Various functions take a string (or strings) to represent a unit of time
76     (e.g. $(D convert!("days", "hours")(numDays))). The valid strings to use
77     with such functions are $(D "years"), $(D "months"), $(D "weeks"),
78     $(D "days"), $(D "hours"), $(D "minutes"), $(D "seconds"),
79     $(D "msecs") (milliseconds), $(D "usecs") (microseconds),
80     $(D "hnsecs") (hecto-nanoseconds - i.e. 100 ns), or some subset thereof.
81     There are a few functions in core.time which take $(D "nsecs"), but because
82     nothing in std.datetime has precision greater than hnsecs, and very little
83     in core.time does, no functions in std.datetime accept $(D "nsecs").
84     To remember which units are abbreviated and which aren't,
85     all units seconds and greater use their full names, and all
86     sub-second units are abbreviated (since they'd be rather long if they
87     weren't).
88 
89     Note:
90         $(REF DateTimeException,std,_datetime,date) is an alias for
91         $(REF TimeException, core,time), so you don't need to worry about
92         core.time functions and std.datetime functions throwing different
93         exception types (except in the rare case that they throw something other
94         than $(REF TimeException, core,time) or
95         $(REF DateTimeException,std,_datetime,date)).
96 
97     See_Also:
98         $(DDLINK intro-to-_datetime, Introduction to std.datetime,
99                  Introduction to std&#46;_datetime)<br>
100         $(HTTP en.wikipedia.org/wiki/ISO_8601, ISO 8601)<br>
101         $(HTTP en.wikipedia.org/wiki/Tz_database,
102               Wikipedia entry on TZ Database)<br>
103         $(HTTP en.wikipedia.org/wiki/List_of_tz_database_time_zones,
104               List of Time Zones)<br>
105 
106     License:   $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
107     Authors:   Jonathan M Davis and Kato Shoichi
108     Source:    $(PHOBOSSRC std/_datetime/package.d)
109 +/
110 module std.datetime;
111 
112 public import core.time;
113 public import std.datetime.date;
114 public import std.datetime.interval;
115 public import std.datetime.systime;
116 public import std.datetime.timezone;
117 
118 import core.exception : AssertError;
119 import std.functional : unaryFun;
120 import std.traits;
121 import std.typecons : Flag, Yes, No;
122 
123 
124 // Verify module example.
125 @safe unittest
126 {
127     auto currentTime = Clock.currTime();
128     auto timeString = currentTime.toISOExtString();
129     auto restoredTime = SysTime.fromISOExtString(timeString);
130 }
131 
132 // Verify Examples for core.time.Duration which couldn't be in core.time.
133 @safe unittest
134 {
135     assert(std.datetime.Date(2010, 9, 7) + dur!"days"(5) ==
136            std.datetime.Date(2010, 9, 12));
137 
138     assert(std.datetime.Date(2010, 9, 7) - std.datetime.Date(2010, 10, 3) ==
139            dur!"days"(-26));
140 }
141 
142 @safe unittest
143 {
144     import std.traits : hasUnsharedAliasing;
145     /* Issue 6642 */
146     static assert(!hasUnsharedAliasing!Date);
147     static assert(!hasUnsharedAliasing!TimeOfDay);
148     static assert(!hasUnsharedAliasing!DateTime);
149     static assert(!hasUnsharedAliasing!SysTime);
150 }
151 
152 
153 //==============================================================================
154 // Everything after here will be deprecated after we have replacements which
155 // use MonoTime and Duration.
156 //==============================================================================
157 
158 
159 /++
160    Used by StopWatch to indicate whether it should start immediately upon
161    construction.
162 
163    If set to $(D AutoStart.no), then the stopwatch is not started when it is
164    constructed.
165 
166    Otherwise, if set to $(D AutoStart.yes), then the stopwatch is started when
167    it is constructed.
168   +/
169 alias AutoStart = Flag!"autoStart";
170 
171 
172 /++
173     $(RED This will be deprecated in 2.076. Please use
174           $(REF StopWatch,std,datetime,stopwatch) instead. It uses
175           $(REF Monotime,core,time) and $(REF Duration,core,time) rather
176           than $(REF TickDuration,core,time), which will also be deprecated in
177           2.076.)
178 
179    $(D StopWatch) measures time as precisely as possible.
180 
181    This class uses a high-performance counter. On Windows systems, it uses
182    $(D QueryPerformanceCounter), and on Posix systems, it uses
183    $(D clock_gettime) if available, and $(D gettimeofday) otherwise.
184 
185    But the precision of $(D StopWatch) differs from system to system. It is
186    impossible to for it to be the same from system to system since the precision
187    of the system clock varies from system to system, and other system-dependent
188    and situation-dependent stuff (such as the overhead of a context switch
189    between threads) can also affect $(D StopWatch)'s accuracy.
190   +/
191 @safe struct StopWatch
192 {
193 public:
194 
195     /++
196        Auto start with constructor.
197       +/
thisStopWatch198     this(AutoStart autostart) @nogc
199     {
200         if (autostart)
201             start();
202     }
203 
204     @nogc @safe unittest
205     {
206         auto sw = StopWatch(Yes.autoStart);
207         sw.stop();
208     }
209 
210 
211     ///
212     bool opEquals(const StopWatch rhs) const pure nothrow @nogc
213     {
214         return opEquals(rhs);
215     }
216 
217     /// ditto
218     bool opEquals(const ref StopWatch rhs) const pure nothrow @nogc
219     {
220         return _timeStart == rhs._timeStart &&
221                _timeMeasured == rhs._timeMeasured;
222     }
223 
224 
225     /++
226        Resets the stop watch.
227       +/
228     void reset() @nogc
229     {
230         if (_flagStarted)
231         {
232             // Set current system time if StopWatch is measuring.
233             _timeStart = TickDuration.currSystemTick;
234         }
235         else
236         {
237             // Set zero if StopWatch is not measuring.
238             _timeStart.length = 0;
239         }
240 
241         _timeMeasured.length = 0;
242     }
243 
244     ///
245     @nogc @safe unittest
246     {
247         StopWatch sw;
248         sw.start();
249         sw.stop();
250         sw.reset();
251         assert(sw.peek().to!("seconds", real)() == 0);
252     }
253 
254 
255     /++
256        Starts the stop watch.
257       +/
258     void start() @nogc
259     {
260         assert(!_flagStarted);
261         _flagStarted = true;
262         _timeStart = TickDuration.currSystemTick;
263     }
264 
265     @nogc @system unittest
266     {
267         StopWatch sw;
268         sw.start();
269         auto t1 = sw.peek();
270         bool doublestart = true;
271         try
272             sw.start();
273         catch (AssertError e)
274             doublestart = false;
275         assert(!doublestart);
276         sw.stop();
277         assert((t1 - sw.peek()).to!("seconds", real)() <= 0);
278     }
279 
280 
281     /++
282        Stops the stop watch.
283       +/
284     void stop() @nogc
285     {
286         assert(_flagStarted);
287         _flagStarted = false;
288         _timeMeasured += TickDuration.currSystemTick - _timeStart;
289     }
290 
291     @nogc @system unittest
292     {
293         StopWatch sw;
294         sw.start();
295         sw.stop();
296         auto t1 = sw.peek();
297         bool doublestop = true;
298         try
299             sw.stop();
300         catch (AssertError e)
301             doublestop = false;
302         assert(!doublestop);
303         assert((t1 - sw.peek()).to!("seconds", real)() == 0);
304     }
305 
306 
307     /++
308        Peek at the amount of time which has passed since the stop watch was
309        started.
310       +/
311     TickDuration peek() const @nogc
312     {
313         if (_flagStarted)
314             return TickDuration.currSystemTick - _timeStart + _timeMeasured;
315 
316         return _timeMeasured;
317     }
318 
319     @nogc @safe unittest
320     {
321         StopWatch sw;
322         sw.start();
323         auto t1 = sw.peek();
324         sw.stop();
325         auto t2 = sw.peek();
326         auto t3 = sw.peek();
327         assert(t1 <= t2);
328         assert(t2 == t3);
329     }
330 
331 
332     /++
333        Set the amount of time which has been measured since the stop watch was
334        started.
335       +/
336     void setMeasured(TickDuration d) @nogc
337     {
338         reset();
339         _timeMeasured = d;
340     }
341 
342     @nogc @safe unittest
343     {
344         StopWatch sw;
345         TickDuration t0;
346         t0.length = 100;
347         sw.setMeasured(t0);
348         auto t1 = sw.peek();
349         assert(t0 == t1);
350     }
351 
352 
353     /++
354        Confirm whether this stopwatch is measuring time.
355       +/
356     bool running() @property const pure nothrow @nogc
357     {
358         return _flagStarted;
359     }
360 
361     @nogc @safe unittest
362     {
363         StopWatch sw1;
364         assert(!sw1.running);
365         sw1.start();
366         assert(sw1.running);
367         sw1.stop();
368         assert(!sw1.running);
369         StopWatch sw2 = Yes.autoStart;
370         assert(sw2.running);
371         sw2.stop();
372         assert(!sw2.running);
373         sw2.start();
374         assert(sw2.running);
375     }
376 
377 
378 
379 
380 private:
381 
382     // true if observing.
383     bool _flagStarted = false;
384 
385     // TickDuration at the time of StopWatch starting measurement.
386     TickDuration _timeStart;
387 
388     // Total time that StopWatch ran.
389     TickDuration _timeMeasured;
390 }
391 
392 ///
393 @safe unittest
394 {
395     void writeln(S...)(S args){}
396     static void bar() {}
397 
398     StopWatch sw;
399     enum n = 100;
400     TickDuration[n] times;
401     TickDuration last = TickDuration.from!"seconds"(0);
402     foreach (i; 0 .. n)
403     {
404        sw.start(); //start/resume mesuring.
405        foreach (unused; 0 .. 1_000_000)
406            bar();
407        sw.stop();  //stop/pause measuring.
408        //Return value of peek() after having stopped are the always same.
409        writeln((i + 1) * 1_000_000, " times done, lap time: ",
410                sw.peek().msecs, "[ms]");
411        times[i] = sw.peek() - last;
412        last = sw.peek();
413     }
414     real sum = 0;
415     // To get the number of seconds,
416     // use properties of TickDuration.
417     // (seconds, msecs, usecs, hnsecs)
418     foreach (t; times)
419        sum += t.hnsecs;
420     writeln("Average time: ", sum/n, " hnsecs");
421 }
422 
423 
424 /++
425     $(RED This will be deprecated in 2.076. Please use
426           $(REF benchmark,std,datetime,stopwatch) instead. It uses
427           $(REF Monotime,core,time) and $(REF Duration,core,time) rather
428           than $(REF TickDuration,core,time), which will also be deprecated in
429           2.076.)
430 
431     Benchmarks code for speed assessment and comparison.
432 
433     Params:
434         fun = aliases of callable objects (e.g. function names). Each should
435               take no arguments.
436         n   = The number of times each function is to be executed.
437 
438     Returns:
439         The amount of time (as a $(REF TickDuration, core,time)) that it took to
440         call each function $(D n) times. The first value is the length of time
441         that it took to call $(D fun[0]) $(D n) times. The second value is the
442         length of time it took to call $(D fun[1]) $(D n) times. Etc.
443 
444     Note that casting the TickDurations to $(REF Duration, core,time)s will make
445     the results easier to deal with (and it may change in the future that
446     benchmark will return an array of Durations rather than TickDurations).
447 
448     See_Also:
449         $(LREF measureTime)
450   +/
451 TickDuration[fun.length] benchmark(fun...)(uint n)
452 {
453     TickDuration[fun.length] result;
454     StopWatch sw;
455     sw.start();
456 
457     foreach (i, unused; fun)
458     {
459         sw.reset();
460         foreach (j; 0 .. n)
461             fun[i]();
462         result[i] = sw.peek();
463     }
464 
465     return result;
466 }
467 
468 ///
469 @safe unittest
470 {
471     import std.conv : to;
472     int a;
473     void f0() {}
474     void f1() {auto b = a;}
475     void f2() {auto b = to!string(a);}
476     auto r = benchmark!(f0, f1, f2)(10_000);
477     auto f0Result = to!Duration(r[0]); // time f0 took to run 10,000 times
478     auto f1Result = to!Duration(r[1]); // time f1 took to run 10,000 times
479     auto f2Result = to!Duration(r[2]); // time f2 took to run 10,000 times
480 }
481 
482 @safe unittest
483 {
484     int a;
485     void f0() {}
486     //void f1() {auto b = to!(string)(a);}
487     void f2() {auto b = (a);}
488     auto r = benchmark!(f0, f2)(100);
489 }
490 
491 
492 /++
493    Return value of benchmark with two functions comparing.
494   +/
495 @safe struct ComparingBenchmarkResult
496 {
497     /++
498        Evaluation value
499 
500        This returns the evaluation value of performance as the ratio of
501        baseFunc's time over targetFunc's time. If performance is high, this
502        returns a high value.
503       +/
504     @property real point() const pure nothrow
505     {
506         return _baseTime.length / cast(const real)_targetTime.length;
507     }
508 
509 
510     /++
511        The time required of the base function
512       +/
513     @property public TickDuration baseTime() const pure nothrow
514     {
515         return _baseTime;
516     }
517 
518 
519     /++
520        The time required of the target function
521       +/
522     @property public TickDuration targetTime() const pure nothrow
523     {
524         return _targetTime;
525     }
526 
527 private:
528 
529     this(TickDuration baseTime, TickDuration targetTime) pure nothrow
530     {
531         _baseTime = baseTime;
532         _targetTime = targetTime;
533     }
534 
535     TickDuration _baseTime;
536     TickDuration _targetTime;
537 }
538 
539 
540 /++
541     $(RED This will be deprecated in 2.076. Please use
542           $(REF benchmark,std,datetime,stopwatch) instead. This function has
543           not been ported to $(REF Monotime,core,time) and
544           $(REF Duration,core,time), because it is a trivial wrapper around
545           benchmark.)
546 
547    Benchmark with two functions comparing.
548 
549    Params:
550        baseFunc   = The function to become the base of the speed.
551        targetFunc = The function that wants to measure speed.
552        times      = The number of times each function is to be executed.
553   +/
554 ComparingBenchmarkResult comparingBenchmark(alias baseFunc,
555                                             alias targetFunc,
556                                             int times = 0xfff)()
557 {
558     auto t = benchmark!(baseFunc, targetFunc)(times);
559     return ComparingBenchmarkResult(t[0], t[1]);
560 }
561 
562 ///
563 @safe unittest
564 {
565     void f1x() {}
566     void f2x() {}
567     @safe void f1o() {}
568     @safe void f2o() {}
569     auto b1 = comparingBenchmark!(f1o, f2o, 1)(); // OK
570     //writeln(b1.point);
571 }
572 
573 //Bug# 8450
574 @system unittest
575 {
576     @safe    void safeFunc() {}
577     @trusted void trustFunc() {}
578     @system  void sysFunc() {}
579     auto safeResult  = comparingBenchmark!((){safeFunc();}, (){safeFunc();})();
580     auto trustResult = comparingBenchmark!((){trustFunc();}, (){trustFunc();})();
581     auto sysResult   = comparingBenchmark!((){sysFunc();}, (){sysFunc();})();
582     auto mixedResult1  = comparingBenchmark!((){safeFunc();}, (){trustFunc();})();
583     auto mixedResult2  = comparingBenchmark!((){trustFunc();}, (){sysFunc();})();
584     auto mixedResult3  = comparingBenchmark!((){safeFunc();}, (){sysFunc();})();
585 }
586 
587 
588 /++
589     $(RED This will be deprecated in 2.076. Please use
590           $(REF StopWatch,std,datetime,stopwatch) instead. This function has
591           not been ported to $(REF Monotime,core,time) and
592           $(REF Duration,core,time), because it is a trivial wrapper around
593           StopWatch.)
594 
595     Function for starting to a stop watch time when the function is called
596     and stopping it when its return value goes out of scope and is destroyed.
597 
598     When the value that is returned by this function is destroyed,
599     $(D func) will run. $(D func) is a unary function that takes a
600     $(REF TickDuration, core,time).
601 
602     Example:
603 --------------------
604 {
605     auto mt = measureTime!((TickDuration a)
606         { /+ do something when the scope is exited +/ });
607     // do something that needs to be timed
608 }
609 --------------------
610 
611     which is functionally equivalent to
612 
613 --------------------
614 {
615     auto sw = StopWatch(Yes.autoStart);
616     scope(exit)
617     {
618         TickDuration a = sw.peek();
619         /+ do something when the scope is exited +/
620     }
621     // do something that needs to be timed
622 }
623 --------------------
624 
625     See_Also:
626         $(LREF benchmark)
627 +/
628 @safe auto measureTime(alias func)()
629 if (isSafe!((){StopWatch sw; unaryFun!func(sw.peek());}))
630 {
631     struct Result
632     {
633         private StopWatch _sw = void;
634         this(AutoStart as)
635         {
636             _sw = StopWatch(as);
637         }
638         ~this()
639         {
640             unaryFun!(func)(_sw.peek());
641         }
642     }
643     return Result(Yes.autoStart);
644 }
645 
646 auto measureTime(alias func)()
647 if (!isSafe!((){StopWatch sw; unaryFun!func(sw.peek());}))
648 {
649     struct Result
650     {
651         private StopWatch _sw = void;
652         this(AutoStart as)
653         {
654             _sw = StopWatch(as);
655         }
656         ~this()
657         {
658             unaryFun!(func)(_sw.peek());
659         }
660     }
661     return Result(Yes.autoStart);
662 }
663 
664 // Verify Example.
665 @safe unittest
666 {
667     {
668         auto mt = measureTime!((TickDuration a)
669             { /+ do something when the scope is exited +/ });
670         // do something that needs to be timed
671     }
672 
673     {
674         auto sw = StopWatch(Yes.autoStart);
675         scope(exit)
676         {
677             TickDuration a = sw.peek();
678             /+ do something when the scope is exited +/
679         }
680         // do something that needs to be timed
681     }
682 }
683 
684 @safe unittest
685 {
686     import std.math : isNaN;
687 
688     @safe static void func(TickDuration td)
689     {
690         assert(!td.to!("seconds", real)().isNaN());
691     }
692 
693     auto mt = measureTime!(func)();
694 
695     /+
696     with (measureTime!((a){assert(a.seconds);}))
697     {
698         // doSomething();
699         // @@@BUG@@@ doesn't work yet.
700     }
701     +/
702 }
703 
704 @safe unittest
705 {
706     import std.math : isNaN;
707 
708     static void func(TickDuration td)
709     {
710         assert(!td.to!("seconds", real)().isNaN());
711     }
712 
713     auto mt = measureTime!(func)();
714 
715     /+
716     with (measureTime!((a){assert(a.seconds);}))
717     {
718         // doSomething();
719         // @@@BUG@@@ doesn't work yet.
720     }
721     +/
722 }
723 
724 //Bug# 8450
725 @system unittest
726 {
727     @safe    void safeFunc() {}
728     @trusted void trustFunc() {}
729     @system  void sysFunc() {}
730     auto safeResult  = measureTime!((a){safeFunc();})();
731     auto trustResult = measureTime!((a){trustFunc();})();
732     auto sysResult   = measureTime!((a){sysFunc();})();
733 }
734