1 /******************************************************************************
2 
3         copyright:      Copyright (c) 2007 Tango. All rights reserved
4 
5         license:        BSD style: $(LICENSE)
6 
7         version:        mid 2005: Initial release
8                         Apr 2007: heavily reshaped
9                         Dec 2007: moved to tango.time
10 
11         author:         John Chapman, Kris, scheivguy
12 
13 ******************************************************************************/
14 
15 module tango.time.Time;
16 
17 /******************************************************************************
18 
19     This struct represents a length of time.  The underlying representation is
20     in units of 100ns.  This allows the length of time to span to roughly
21     +/- 10000 years.
22     
23     Notably missing from this is a representation of weeks, months and years.
24     This is because weeks, months, and years vary according to local calendars.
25     Use tango.time.chrono.* to deal with these concepts.
26 
27     Note: nobody should change this struct without really good reason as it is
28     required to be a part of some interfaces.  It should be treated as a
29     builtin type. Also note that there is deliberately no opCall constructor
30     here, since it tends to produce too much overhead.   If you wish to build
31     a TimeSpan struct from a ticks value, use D's builtin ability to create a
32     struct with given member values (See the description of ticks() for an
33     example of how to do this).
34 
35     Example:
36     -------------------
37     Time start = Clock.now;
38     Thread.sleep(0.150);
39     Stdout.formatln("slept for {} ms", (Clock.now-start).millis);
40     -------------------
41 
42     See_Also: tango.core.Thread, tango.time.Clock
43 
44 ******************************************************************************/
45 
46 struct TimeSpan
47 {
48         // this is the only member of the struct.
49         package long ticks_;
50 
51         // useful constants.  Shouldn't be used in normal code, use the
52         // static TimeSpan members below instead.  i.e. instead of
53         // TimeSpan.TicksPerSecond, use TimeSpan.second.ticks
54         //
55         enum : long 
56         {
57                 /// basic tick values
58                 NanosecondsPerTick  = 100,
59                 TicksPerMicrosecond = 1000 / NanosecondsPerTick,
60                 TicksPerMillisecond = 1000 * TicksPerMicrosecond,
61                 TicksPerSecond      = 1000 * TicksPerMillisecond,
62                 TicksPerMinute      = 60 * TicksPerSecond,
63                 TicksPerHour        = 60 * TicksPerMinute,
64                 TicksPerDay         = 24 * TicksPerHour,
65 
66                 // millisecond counts
67                 MillisPerSecond     = 1000,
68                 MillisPerMinute     = MillisPerSecond * 60,
69                 MillisPerHour       = MillisPerMinute * 60,
70                 MillisPerDay        = MillisPerHour * 24,
71 
72                 /// day counts
73                 DaysPerYear         = 365,
74                 DaysPer4Years       = DaysPerYear * 4 + 1,
75                 DaysPer100Years     = DaysPer4Years * 25 - 1,
76                 DaysPer400Years     = DaysPer100Years * 4 + 1,
77 
78                 // epoch counts
79                 Epoch1601           = DaysPer400Years * 4 * TicksPerDay,
80                 Epoch1970           = Epoch1601 + TicksPerSecond * 11644473600L,
81         }
82 
83         /**
84          * Minimum TimeSpan
85          */
86         enum TimeSpan min = TimeSpan(long.min);
87 
88         /**
89          * Maximum TimeSpan
90          */
91         enum TimeSpan max = TimeSpan(long.max);
92 
93         /**
94          * Zero TimeSpan.  Useful for comparisons.
95          */
96         enum TimeSpan zero = TimeSpan(0);
97 
98         /**
99          * Get the number of ticks that this timespan represents.  This can be
100          * used to construct another TimeSpan:
101          *
102          * --------
103          * long ticks = myTimeSpan.ticks;
104          * TimeSpan copyOfMyTimeSpan = TimeSpan(ticks);
105          * --------
106          */
107         @property const long ticks()
108         {
109                 return ticks_;
110         }
111 
112         /**
113          * Determines whether two TimeSpan values are equal
114          */
115         const bool opEquals(const(TimeSpan) t)
116         {
117                 return ticks_ is t.ticks_;
118         }
119 
120         /**
121          * Compares this object against another TimeSpan value.
122          */
123         int opCmp(const ref TimeSpan t) const
124         {
125                 if (ticks_ < t.ticks_)
126                     return -1;
127 
128                 if (ticks_ > t.ticks_)
129                     return 1;
130 
131                 return 0;
132         }
133 
134         /* To support manifest constants */
135         int opCmp(const TimeSpan t) const
136         {
137                 return opCmp(t);
138         }
139 
140         /**
141          * Add the TimeSpan given to this TimeSpan returning a new TimeSpan.
142          *
143          * Params: t = A TimeSpan value to add
144          * Returns: A TimeSpan value that is the sum of this instance and t.
145          */
146         const TimeSpan opBinary(immutable(char)[] o : "+")(const(TimeSpan) t)
147         {
148                 return TimeSpan(ticks_ + t.ticks_);
149         }
150 
151         /**
152          * Add the specified TimeSpan to this TimeSpan, assigning the result
153          * to this instance.
154          *
155          * Params: t = A TimeSpan value to add
156          * Returns: a copy of this instance after adding t.
157          */
158         TimeSpan opOpAssign(immutable(char)[] o : "+")(const(TimeSpan) t)
159         {
160                 ticks_ += t.ticks_;
161                 return this;
162         }
163 
164         /**
165          * Subtract the specified TimeSpan from this TimeSpan.
166          *
167          * Params: t = A TimeSpan to subtract
168          * Returns: A new timespan which is the difference between this
169          * instance and t
170          */
171         const TimeSpan opBinary(immutable(char)[] o : "-")(const(TimeSpan) t)
172         {
173                 return TimeSpan(ticks_ - t.ticks_);
174         }
175 
176         /**
177          *
178          * Subtract the specified TimeSpan from this TimeSpan and assign the
179          *
180          * Params: t = A TimeSpan to subtract
181          * Returns: A copy of this instance after subtracting t.
182          */
183         TimeSpan opOpAssign(immutable(char)[] o : "-")(const(TimeSpan) t)
184         {
185                 ticks_ -= t.ticks_;
186                 return this;
187         }
188 
189         /**
190          * Scale the TimeSpan by the specified amount.  This should not be
191          * used to convert to a different unit.  Use the unit accessors
192          * instead.  This should only be used as a scaling mechanism.  For
193          * example, if you have a timeout and you want to sleep for twice the
194          * timeout, you would use timeout * 2.
195          *
196          * Params: v = A multiplier to use for scaling this time span.
197          * Returns: A new TimeSpan that is scaled by v
198          */
199         const TimeSpan opBinary(immutable(char)[] o : "*")(long v)
200         {
201                 return TimeSpan(ticks_ * v);
202         }
203 
204         /**
205          * Scales this TimeSpan and assigns the result to this instance.
206          *
207          * Params: v = A multipler to use for scaling
208          * Returns: A copy of this instance after scaling
209          */
210         TimeSpan opOpAssign(immutable(char)[] o : "*")(long v)
211         {
212                 ticks_ *= v;
213                 return this;
214         }
215 
216         /**
217          * Divide the TimeSpan by the specified amount.  This should not be
218          * used to convert to a different unit.  Use the unit accessors
219          * instead.  This should only be used as a scaling mechanism.  For
220          * example, if you have a timeout and you want to sleep for half the
221          * timeout, you would use timeout / 2.
222          *
223          *
224          * Params: v = A divisor to use for scaling this time span.
225          * Returns: A new TimeSpan that is divided by v
226          */
227         const TimeSpan opBinary(immutable(char)[] o : "/")(long v)
228         {
229                 return TimeSpan(ticks_ / v);
230         }
231 
232         /**
233          * Divides this TimeSpan and assigns the result to this instance.
234          *
235          * Params: v = A multipler to use for dividing
236          * Returns: A copy of this instance after dividing
237          */
238         TimeSpan opOpAssign(immutable(char)[] o : "/")(long v)
239         {
240                 ticks_ /= v;
241                 return this;
242         }
243 
244         /**
245          * Perform integer division with the given time span.
246          *
247          * Params: t = A divisor used for dividing
248          * Returns: The result of integer division between this instance and
249          * t.
250          */
251         const long opBinary(immutable(char)[] o : "/")(const(TimeSpan) t)
252         {
253                 return ticks_ / t.ticks;
254         }
255 
256         /**
257          * Negate a time span
258          *
259          * Returns: The negative equivalent to this time span
260          */
261         const TimeSpan opUnary(immutable(char)[] o : "-")()
262         {
263                 return TimeSpan(-ticks_);
264         }
265 
266         /**
267          * Convert to nanoseconds
268          *
269          * Note: this may incur loss of data because nanoseconds cannot
270          * represent the range of data a TimeSpan can represent.
271          *
272          * Returns: The number of nanoseconds that this TimeSpan represents.
273          */
274         @property const long nanos()
275         {
276                 return ticks_ * NanosecondsPerTick;
277         }
278 
279         /**
280          * Convert to microseconds
281          *
282          * Returns: The number of microseconds that this TimeSpan represents.
283          */
284         @property const long micros()
285         {
286                 return ticks_ / TicksPerMicrosecond;
287         }
288 
289         /**
290          * Convert to milliseconds
291          *
292          * Returns: The number of milliseconds that this TimeSpan represents.
293          */
294         @property const long millis()
295         {
296                 return ticks_ / TicksPerMillisecond;
297         }
298 
299         /**
300          * Convert to seconds
301          *
302          * Returns: The number of seconds that this TimeSpan represents.
303          */
304         @property const long seconds()
305         {
306                 return ticks_ / TicksPerSecond;
307         }
308 
309         /**
310          * Convert to minutes
311          *
312          * Returns: The number of minutes that this TimeSpan represents.
313          */
314         @property const long minutes()
315         {
316                 return ticks_ / TicksPerMinute;
317         }
318 
319         /**
320          * Convert to hours
321          *
322          * Returns: The number of hours that this TimeSpan represents.
323          */
324         @property const long hours()
325         {
326                 return ticks_ / TicksPerHour;
327         }
328 
329         /**
330          * Convert to days
331          *
332          * Returns: The number of days that this TimeSpan represents.
333          */
334         @property const long days()
335         {
336                 return ticks_ / TicksPerDay;
337         }
338 
339         /**
340          * Convert to a floating point interval representing seconds.
341          *
342          * Note: This may cause a loss of precision as a double cannot exactly
343          * represent some fractional values.
344          *
345          * Returns: An interval representing the seconds and fractional
346          * seconds that this TimeSpan represents.
347          */
348         @property const double interval()
349         {
350                 return (cast(double) ticks_) / TicksPerSecond;
351         }
352 
353         /**
354          * Convert to TimeOfDay
355          *
356          * Returns: the TimeOfDay this TimeSpan represents.
357          */
358         @property const TimeOfDay time()
359         {
360                 return TimeOfDay(ticks_);
361         }
362 
363         /**
364          * Construct a TimeSpan from the given number of nanoseconds
365          *
366          * Note: This may cause a loss of data since a TimeSpan's resolution
367          * is in 100ns increments.
368          *
369          * Params: value = The number of nanoseconds.
370          * Returns: A TimeSpan representing the given number of nanoseconds.
371          */
372         static TimeSpan fromNanos(long value)
373         {
374                 return TimeSpan(value / NanosecondsPerTick);
375         }
376 
377         /**
378          * Construct a TimeSpan from the given number of microseconds
379          *
380          * Params: value = The number of microseconds.
381          * Returns: A TimeSpan representing the given number of microseconds.
382          */
383         static TimeSpan fromMicros(long value)
384         {
385                 return TimeSpan(TicksPerMicrosecond * value);
386         }
387 
388         /**
389          * Construct a TimeSpan from the given number of milliseconds
390          *
391          * Params: value = The number of milliseconds.
392          * Returns: A TimeSpan representing the given number of milliseconds.
393          */
394         static TimeSpan fromMillis(long value)
395         {
396                 return TimeSpan(TicksPerMillisecond * value);
397         }
398 
399         /**
400          * Construct a TimeSpan from the given number of seconds
401          *
402          * Params: value = The number of seconds.
403          * Returns: A TimeSpan representing the given number of seconds.
404          */
405         static TimeSpan fromSeconds(long value)
406         {
407                 return TimeSpan(TicksPerSecond * value);
408         }
409 
410         /**
411          * Construct a TimeSpan from the given number of minutes
412          *
413          * Params: value = The number of minutes.
414          * Returns: A TimeSpan representing the given number of minutes.
415          */
416         static TimeSpan fromMinutes(long value)
417         {
418                 return TimeSpan(TicksPerMinute * value);
419         }
420 
421         /**
422          * Construct a TimeSpan from the given number of hours
423          *
424          * Params: value = The number of hours.
425          * Returns: A TimeSpan representing the given number of hours.
426          */
427         static TimeSpan fromHours(long value)
428         {
429                 return TimeSpan(TicksPerHour * value);
430         }
431 
432         /**
433          * Construct a TimeSpan from the given number of days
434          *
435          * Params: value = The number of days.
436          * Returns: A TimeSpan representing the given number of days.
437          */
438         static TimeSpan fromDays(long value)
439         {
440                 return TimeSpan(TicksPerDay * value);
441         }
442 
443         /**
444          * Construct a TimeSpan from the given interval.  The interval
445          * represents seconds as a double.  This allows both whole and
446          * fractional seconds to be passed in.
447          *
448          * Params: value = The interval to convert in seconds.
449          * Returns: A TimeSpan representing the given interval.
450          */
451         static TimeSpan fromInterval(double sec)
452         {
453                 return TimeSpan(cast(long)(sec * TicksPerSecond + .1));
454         }
455 }
456 
457 
458 /******************************************************************************
459 
460         Represents a point in time.
461 
462         Remarks: Time represents dates and times between 12:00:00 
463         midnight on January 1, 10000 BC and 11:59:59 PM on December 31, 
464         9999 AD.
465 
466         Time values are measured in 100-nanosecond intervals, or ticks. 
467         A date value is the number of ticks that have elapsed since 
468         12:00:00 midnight on January 1, 0001 AD in the Gregorian 
469         calendar.
470         
471         Negative Time values are offsets from that same reference point, 
472         but backwards in history.  Time values are not specific to any 
473         calendar, but for an example, the beginning of December 31, 1 BC 
474         in the Gregorian calendar is Time.epoch - TimeSpan.days(1).
475 
476 ******************************************************************************/
477 
478 struct Time 
479 {
480         private long ticks_;
481 
482         private enum : long
483         {
484                 maximum = (TimeSpan.DaysPer400Years * 25 - 366) * TimeSpan.TicksPerDay - 1,
485                 minimum = -((TimeSpan.DaysPer400Years * 25 - 366) * TimeSpan.TicksPerDay - 1),
486         }
487 
488         /// Represents the smallest and largest Time value.
489         enum Time min       = Time(minimum),
490                   max       = Time(maximum);
491 
492         /// Represents the epoch (1/1/0001)
493         enum Time epoch     = Time(0L);
494 
495         /// Represents the epoch of 1/1/1601 (Commonly used in Windows systems)
496         enum Time epoch1601 = Time(TimeSpan.Epoch1601);
497 
498         /// Represents the epoch of 1/1/1970 (Commonly used in Unix systems)
499         enum Time epoch1970 = Time(TimeSpan.Epoch1970);
500 
501         /**********************************************************************
502 
503                 $(I Property.) Retrieves the number of ticks for this Time.
504                 This value can be used to construct another Time struct by
505                 writing:
506 
507                 ---------
508                 long ticks = myTime.ticks;
509                 Time copyOfMyTime = Time(ticks);
510                 ---------
511 
512 
513                 Returns: A long represented by the time of this 
514                          instance.
515 
516         **********************************************************************/
517 
518         @property const long ticks ()
519         {
520                 return ticks_;
521         }
522 
523         /**********************************************************************
524 
525                 Determines whether two Time values are equal.
526 
527                 Params:  value = A Time _value.
528                 Returns: true if both instances are equal; otherwise, false
529 
530         **********************************************************************/
531 
532         const bool opEquals (const(Time) t) 
533         {
534                 return ticks_ is t.ticks_;
535         }
536 
537         /**********************************************************************
538 
539                 Compares two Time values.
540 
541         **********************************************************************/
542 
543         int opCmp (const ref Time t) const
544         {
545                 if (ticks_ < t.ticks_)
546                     return -1;
547 
548                 if (ticks_ > t.ticks_)
549                     return 1;
550 
551                 return 0;
552         }
553 
554         /* To support manifest constants */
555         int opCmp (const Time t) const
556         {
557                 return opCmp(t);
558         }
559 
560         /**********************************************************************
561 
562                 Adds the specified time span to the time, returning a new
563                 time.
564                 
565                 Params:  t = A TimeSpan value.
566                 Returns: A Time that is the sum of this instance and t.
567 
568         **********************************************************************/
569 
570         const Time opBinary(immutable(char)[] o : "+") (const(TimeSpan) t) 
571         {
572                 return Time (ticks_ + t.ticks_);
573         }
574 
575         /**********************************************************************
576 
577                 Adds the specified time span to the time, assigning 
578                 the result to this instance.
579 
580                 Params:  t = A TimeSpan value.
581                 Returns: The current Time instance, with t added to the 
582                          time.
583 
584         **********************************************************************/
585 
586         Time opOpAssign(immutable(char)[] o : "+") (const(TimeSpan) t) 
587         {
588                 ticks_ += t.ticks_;
589                 return this;
590         }
591 
592         /**********************************************************************
593 
594                 Subtracts the specified time span from the time, 
595                 returning a new time.
596 
597                 Params:  t = A TimeSpan value.
598                 Returns: A Time whose value is the value of this instance 
599                          minus the value of t.
600 
601         **********************************************************************/
602 
603         const Time opBinary(immutable(char)[] o : "-") (const(TimeSpan) t) 
604         {
605                 return Time (ticks_ - t.ticks_);
606         }
607 
608         /**********************************************************************
609 
610                 Returns a time span which represents the difference in time
611                 between this and the given Time.
612 
613                 Params:  t = A Time value.
614                 Returns: A TimeSpan which represents the difference between
615                          this and t.
616 
617         **********************************************************************/
618 
619         const TimeSpan opBinary(immutable(char)[] o : "-") (const(Time) t)
620         {
621                 return TimeSpan(ticks_ - t.ticks_);
622         }
623 
624         /**********************************************************************
625 
626                 Subtracts the specified time span from the time, 
627                 assigning the result to this instance.
628 
629                 Params:  t = A TimeSpan value.
630                 Returns: The current Time instance, with t subtracted 
631                          from the time.
632 
633         **********************************************************************/
634 
635         Time opOpAssign(immutable(char)[] o : "-") (const(TimeSpan) t) 
636         {
637                 ticks_ -= t.ticks_;
638                 return this;
639         }
640 
641         /**********************************************************************
642 
643                 $(I Property.) Retrieves the date component.
644 
645                 Returns: A new Time instance with the same date as 
646                          this instance, but with the time truncated.
647 
648         **********************************************************************/
649 
650         @property const Time date () 
651         {
652                 return this - TimeOfDay.modulo24(ticks_);
653         }
654 
655         /**********************************************************************
656 
657                 $(I Property.) Retrieves the time of day.
658 
659                 Returns: A TimeOfDay representing the fraction of the day 
660                          elapsed since midnight.
661 
662         **********************************************************************/
663 
664         @property const TimeOfDay time () 
665         {
666                 return TimeOfDay (ticks_);
667         }
668 
669         /**********************************************************************
670 
671                 $(I Property.) Retrieves the equivalent TimeSpan.
672 
673                 Returns: A TimeSpan representing this Time.
674 
675         **********************************************************************/
676 
677         @property const TimeSpan span () 
678         {
679                 return TimeSpan (ticks_);
680         }
681 
682         /**********************************************************************
683 
684                 $(I Property.) Retrieves a TimeSpan that corresponds to Unix
685                 time (time since 1/1/1970).  Use the TimeSpan accessors to get
686                 the time in seconds, milliseconds, etc.
687 
688                 Returns: A TimeSpan representing this Time as Unix time.
689 
690                 -------------------------------------
691                 auto unixTime = Clock.now.unix.seconds;
692                 auto javaTime = Clock.now.unix.millis;
693                 -------------------------------------
694 
695         **********************************************************************/
696 
697         @property const TimeSpan unix()
698         {
699                 return TimeSpan(ticks_ - epoch1970.ticks_);
700         }
701 }
702 
703 
704 /******************************************************************************
705 
706         Represents a time of day. This is different from TimeSpan in that 
707         each component is represented within the limits of everyday time, 
708         rather than from the start of the Epoch. Effectively, the TimeOfDay
709         epoch is the first second of each day.
710 
711         This is handy for dealing strictly with a 24-hour clock instead of
712         potentially thousands of years. For example:
713         ---
714         auto time = Clock.now.time;
715         assert (time.millis < 1000);
716         assert (time.seconds < 60);
717         assert (time.minutes < 60);
718         assert (time.hours < 24);
719         ---
720 
721         You can create a TimeOfDay from an existing Time or TimeSpan instance
722         via the respective time() method. To convert back to a TimeSpan, use
723         the span() method
724 
725 ******************************************************************************/
726 
727 struct TimeOfDay 
728 {
729         /**
730          * hours component of the time of day.  This should be between 0 and
731          * 23, inclusive.
732          */
733         public uint     hours;
734 
735         /**
736          * minutes component of the time of day.  This should be between 0 and
737          * 59, inclusive.
738          */
739         public uint     minutes;
740 
741         /**
742          * seconds component of the time of day.  This should be between 0 and
743          * 59, inclusive.
744          */
745         public uint     seconds;
746 
747         /**
748          * milliseconds component of the time of day.  This should be between
749          * 0 and 999, inclusive.
750          */
751         public uint     millis;
752 
753         /**
754          * constructor.
755          * Params: hours = number of hours since midnight
756          *         minutes = number of minutes into the hour
757          *         seconds = number of seconds into the minute
758          *         millis = number of milliseconds into the second
759          *
760          * Returns: a TimeOfDay representing the given time fields.
761          *
762          * Note: There is no verification of the range of values, or
763          * normalization made.  So if you pass in larger values than the
764          * maximum value for that field, they will be stored as that value.
765          *
766          * example:
767          * --------------
768          * auto tod = TimeOfDay(100, 100, 100, 10000);
769          * assert(tod.hours == 100);
770          * assert(tod.minutes == 100);
771          * assert(tod.seconds == 100);
772          * assert(tod.millis == 10000);
773          * --------------
774          */
775         static TimeOfDay opCall (uint hours, uint minutes, uint seconds, uint millis=0)
776         {
777                 TimeOfDay t = void;
778                 t.hours   = hours;
779                 t.minutes = minutes;
780                 t.seconds = seconds;
781                 t.millis  = millis;
782                 return t;
783         }
784 
785         /**
786          * constructor.
787          * Params: ticks = ticks representing a Time value.  This is normalized 
788          * so that it represent a time of day (modulo-24 etc)
789          *
790          * Returns: a TimeOfDay value that corresponds to the time of day of
791          * the given number of ticks.
792          */
793         static TimeOfDay opCall (long ticks)
794         {       
795                 TimeOfDay t = void;
796                 ticks = modulo24(ticks).ticks_;
797                 t.millis  = cast(uint) (ticks / TimeSpan.TicksPerMillisecond); 
798                 t.seconds = (t.millis / 1_000) % 60;
799                 t.minutes = (t.millis / 60_000) % 60;
800                 t.hours   = (t.millis / 3_600_000) % 24;
801                 t.millis %= 1000;
802                 return t;
803         }
804 
805         /**
806          * construct a TimeSpan from the current fields
807          *
808          * Returns: a TimeOfDay representing the field values.
809          *
810          * Note: that fields are not checked against a valid range, so
811          * setting 60 for minutes is allowed, and will just add 1 to the hour
812          * component, and set the minute component to 0.  The result is
813          * normalized, so the hours wrap.  If you pass in 25 hours, the
814          * resulting TimeOfDay will have a hour component of 1.
815          */
816         @property const TimeSpan span ()
817         {
818                 return TimeSpan.fromHours(hours) +
819                        TimeSpan.fromMinutes(minutes) + 
820                        TimeSpan.fromSeconds(seconds) + 
821                        TimeSpan.fromMillis(millis);
822         }
823 
824         /**
825          * internal routine to adjust ticks by one day. Also adjusts for
826          * offsets in the BC era
827          */
828         package static TimeSpan modulo24 (long ticks)
829         {
830                 ticks %= TimeSpan.TicksPerDay;
831                 if (ticks < 0)
832                     ticks += TimeSpan.TicksPerDay;
833                 return TimeSpan (ticks);
834         }
835 }
836 
837 /******************************************************************************
838 
839     Generic Date representation
840 
841 ******************************************************************************/
842 
843 struct Date
844 {
845         public uint         era,            /// AD, BC
846                             day,            /// 1 .. 31
847                             year,           /// 0 to 9999
848                             month,          /// 1 .. 12
849                             dow,            /// 0 .. 6
850                             doy;            /// 1 .. 366
851 }
852 
853 
854 /******************************************************************************
855 
856     Combination of a Date and a TimeOfDay
857 
858 ******************************************************************************/
859 
860 struct DateTime
861 {
862         public Date         date;       /// date representation
863         public TimeOfDay    time;       /// time representation
864 }
865 
866 
867 
868 
869 /******************************************************************************
870 
871 ******************************************************************************/
872 
873 debug (UnitTest)
874 {
875         unittest
876         {
877                 assert(TimeSpan.zero > TimeSpan.min);
878                 assert(TimeSpan.max  > TimeSpan.zero);
879                 assert(TimeSpan.max  > TimeSpan.min);
880                 assert(TimeSpan.zero >= TimeSpan.zero);
881                 assert(TimeSpan.zero <= TimeSpan.zero);
882                 assert(TimeSpan.max >= TimeSpan.max);
883                 assert(TimeSpan.max <= TimeSpan.max);
884                 assert(TimeSpan.min >= TimeSpan.min);
885                 assert(TimeSpan.min <= TimeSpan.min);
886 
887                 assert (TimeSpan.fromSeconds(50).seconds is 50);
888                 assert (TimeSpan.fromSeconds(5000).seconds is 5000);
889                 assert (TimeSpan.fromMinutes(50).minutes is 50);
890                 assert (TimeSpan.fromMinutes(5000).minutes is 5000);
891                 assert (TimeSpan.fromHours(23).hours is 23);
892                 assert (TimeSpan.fromHours(5000).hours is 5000);
893                 assert (TimeSpan.fromDays(6).days is 6);
894                 assert (TimeSpan.fromDays(5000).days is 5000);
895 
896                 assert (TimeSpan.fromSeconds(50).time.seconds is 50);
897                 assert (TimeSpan.fromSeconds(5000).time.seconds is 5000 % 60);
898                 assert (TimeSpan.fromMinutes(50).time.minutes is 50);
899                 assert (TimeSpan.fromMinutes(5000).time.minutes is 5000 % 60);
900                 assert (TimeSpan.fromHours(23).time.hours is 23);
901                 assert (TimeSpan.fromHours(5000).time.hours is 5000 % 24);
902 
903                 auto ts = TimeSpan.fromHours(20);
904                 assert (TimeSpan.fromHours(10) + TimeSpan.fromHours(10) == ts);
905                 assert (TimeSpan.fromHours(30) - TimeSpan.fromHours(10) == ts);
906                 auto ts2 = TimeSpan.fromHours(10);
907                 ts2 += TimeSpan.fromHours(10);
908                 assert(ts2 == ts);
909 
910                 auto tod = TimeOfDay (25, 2, 3, 4);
911                 tod = tod.span.time;
912                 assert (tod.hours is 1);
913                 assert (tod.minutes is 2);
914                 assert (tod.seconds is 3);
915                 assert (tod.millis is 4);
916         }
917 }
918 
919 
920 /*******************************************************************************
921 
922 *******************************************************************************/
923 
924 debug (Time)
925 {
926         import tango.io.Stdout;
927         import tango.time.Clock;
928         import tango.time.chrono.Gregorian;
929 
930         Time foo() 
931         {
932                 auto d = Time(10);
933                 auto e = TimeSpan(20);
934 
935                 return d + e;
936         }
937 
938         void main()
939         {
940                 auto c = foo();
941                 Stdout (c.ticks).newline;
942 
943 
944                 auto t = TimeSpan(1);
945                 auto h = t.hours;
946                 auto m = t.time.minutes;
947 
948                 auto now = Clock.now;
949                 auto time = now.time;
950                 auto date = Gregorian.generic.toDate (now);
951                 now = Gregorian.generic.toTime (date, time);
952         }
953 }
954