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._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