Download Reference Manual
The Developer's Library for D
About Wiki Forums Source Search Contact

Ticket #671: DateTime.d

File DateTime.d, 23.4 kB (added by schveiguy, 1 year ago)

new DateTime file

Line 
1 /******************************************************************************
2
3         copyright:      Copyright (c) 2005 John Chapman. All rights reserved
4
5         license:        BSD style: $(LICENSE)
6
7         version:        mid 2005: Initial release
8                         Apr 2007: heavily reshaped
9                         Oct 2007: changed to use TimeSpan
10
11         author:         John Chapman, Kris, Steve Schveighoffer
12
13 ******************************************************************************/
14
15 module tango.util.time.DateTime;
16
17 private import  tango.util.time.Clock,
18                 tango.util.time.WallClock;
19
20 public import tango.core.TimeSpan;
21
22 /******************************************************************************
23
24         Represents time expressed as a date and time of day.
25
26         Remarks: DateTime represents dates and times between 12:00:00
27         midnight on January 1, 0001 AD and 11:59:59 PM on December 31,
28         9999 AD.
29
30         Time values are measured in 100-nanosecond intervals, or ticks.
31         A date value is the number of ticks that have elapsed since
32         12:00:00 midnight on January 1, 0001 AD in the Gregorian
33         calendar.
34
35 ******************************************************************************/
36
37 struct DateTime
38 {
39         public long ticks;
40
41         private package enum
42         {
43                 Year,
44                 Month,
45                 Day,
46                 DayOfYear
47         }
48
49         public enum DayOfWeek
50         {
51                 Sunday,    /// Indicates _Sunday.
52                 Monday,    /// Indicates _Monday.
53                 Tuesday,   /// Indicates _Tuesday.
54                 Wednesday, /// Indicates _Wednesday.
55                 Thursday,  /// Indicates _Thursday.
56                 Friday,    /// Indicates _Friday.
57                 Saturday   /// Indicates _Saturday.
58         }
59
60         /// Represents the common epochs used.
61         public static const DateTime    min = {0},
62                                         max = {TimeSpan.DaysTo10000 * TimeSpan.TicksPerDay - 1},
63                                         Epoch1601 = {TimeSpan.DaysTo1601 * TimeSpan.TicksPerDay},
64                                         Epoch1970 = {TimeSpan.DaysTo1601 * TimeSpan.TicksPerDay + TimeSpan.TicksPerSecond * 11644473600L};
65
66         private static final int[] DaysToMonthCommon =
67         [
68                 0,
69                 31,
70                 59,
71                 90,
72                 120,
73                 151,
74                 181,
75                 212,
76                 243,
77                 273,
78                 304,
79                 334,
80                 365
81         ];
82
83         private static final int[] DaysToMonthLeap =
84         [
85                 0,
86                 31,
87                 60,
88                 91,
89                 121,
90                 152,
91                 182,
92                 213,
93                 244,
94                 274,
95                 305,
96                 335,
97                 366
98         ];
99
100         /**********************************************************************
101
102                 $(I Constructor.) Initializes a new instance of the
103                 DateTime struct to the specified number of _ticks.         
104                 
105                 Params: ticks = A date and time expressed in units of
106                 100 nanoseconds.
107
108         **********************************************************************/
109
110         static DateTime opCall (long ticks)
111         {
112                 DateTime d;
113                 d.ticks = ticks;
114                 return d;
115         }
116
117         /**********************************************************************
118
119         **********************************************************************/
120
121         static DateTime opCall (int year, int month, int day)
122         {
123                 return opCall (getDateTicks (year, month, day));
124         }
125
126         /**********************************************************************
127
128                 $(I Property.) Retrieves the current date.
129
130                 Returns: A DateTime instance set to today's date.
131
132         **********************************************************************/
133
134         static DateTime today ()
135         {
136                 return now.date;
137         }
138
139         /**********************************************************************
140
141                 $(I Property.) Retrieves a DateTime instance set to the
142                 current date and time in local time.
143
144                 Returns: A DateTime whose value is the current local date
145                          and time.
146
147         **********************************************************************/
148
149         static DateTime now ()
150         {
151                 return WallClock.now;
152         }
153
154         /**********************************************************************
155
156                 $(I Property.) Retrieves a DateTime instance set to the
157                 current date and time in UTC time.
158
159                 Returns: A DateTime whose value is the current UTC date
160                          and time.
161
162         **********************************************************************/
163
164         // this should probably be deprecated, doesn't add much now that
165         // Clock.now returns a DateTime
166         static DateTime utc ()
167         {
168                 return Clock.now;
169         }
170
171         /**********************************************************************
172
173                 Determines whether two DateTime values are equal.
174
175                 Params:  value = A DateTime _value.
176                 Returns: true if both instances are equal; otherwise, false
177
178         **********************************************************************/
179
180         bool opEquals (DateTime t)
181         {
182                 return ticks is t.ticks;
183         }
184
185         /**********************************************************************
186
187                 Compares two DateTime values.
188
189         **********************************************************************/
190
191         int opCmp (DateTime t)
192         {
193                 if (ticks < t.ticks)
194                     return -1;
195                 else
196                    if (ticks > t.ticks)
197                        return 1;
198                 return 0;
199         }
200
201         /**********************************************************************
202
203                 Adds the specified time span to the date and time,
204                 returning a new date and time.
205                 
206                 Params:  t = A DateTime value.
207                 Returns: A DateTime that is the sum of this instance and t.
208
209         **********************************************************************/
210
211         DateTime opAdd (TimeSpan t)
212         {
213                 return DateTime (ticks + t.ticks);
214         }
215
216         /**********************************************************************
217
218                 Adds the specified time span to the date and time, assigning
219                 the result to this instance.
220
221                 Params:  t = A DateTime value.
222                 Returns: The current DateTime instance, with t added to the
223                          date and time.
224
225         **********************************************************************/
226
227         DateTime opAddAssign (TimeSpan t)
228         {
229                 ticks += t.ticks;
230                 return *this;
231         }
232
233         /**********************************************************************
234
235                 Subtracts the specified date and time from the date and time,
236                 returning a time span value
237
238                 Params:  t = A DateTime value.
239                 Returns: A TimeSpan whose value represents the difference in
240                          time between this date/time and t.
241
242         **********************************************************************/
243
244         TimeSpan opSub (DateTime t)
245         {
246                 return TimeSpan (ticks - t.ticks);
247         }
248
249         /**********************************************************************
250
251                 Subtracts the specified time span from the date and time,
252                 returning a new date and time.
253
254                 Params:  t = A TimeSpan value.
255                 Returns: A DateTime whose value is the value of this instance
256                          minus the value of t.
257
258         **********************************************************************/
259
260         DateTime opSub (TimeSpan t)
261         {
262                 return DateTime(ticks - t.ticks);
263         }
264
265         /**********************************************************************
266
267                 Subtracts the specified time span from the date and time,
268                 assigning the result to this instance.
269
270                 Params:  t = A TimeSpan value.
271                 Returns: The current DateTime instance, with t subtracted
272                          from the date and time.
273
274         **********************************************************************/
275
276         DateTime opSubAssign (TimeSpan t)
277         {
278                 ticks -= t.ticks;
279                 return *this;
280         }
281
282         //
283         // the following functions are no longer useful, you can do the same
284         // thing by doing:
285         //
286         // DateTime.addHours(value) becomes:
287         // t += TimeSpan.fromHours(value);
288
289         /**********************************************************************
290
291                 Adds the specified number of ticks to the _value of this
292                 instance.
293
294                 Params:  value = The number of ticks to add.
295                 Returns: A DateTime whose value is the sum of the date and
296                          time of this instance and the time in value.
297
298         **********************************************************************/
299
300         /*DateTime addTicks (long value)
301         {
302                 return DateTime (ticks + value);
303         }*/
304
305         /**********************************************************************
306                 Adds the specified number of hours to the _value of this
307                 instance.
308
309                 Params:  value = The number of hours to add.
310                 Returns: A DateTime whose value is the sum of the date and
311                          time of this instance and the number of hours in
312                          value.
313
314         **********************************************************************/
315
316         /*DateTime addHours (int value)
317         {
318                 return addMilliseconds (value * Time.MillisPerHour);
319         }*/
320
321         /**********************************************************************
322
323                 Adds the specified number of minutes to the _value of this
324                 instance.
325
326                 Params:  value = The number of minutes to add.
327                 Returns: A DateTime whose value is the sum of the date and
328                          time of this instance and the number of minutes in
329                          value.
330
331         **********************************************************************/
332
333         /*DateTime addMinutes (int value)
334         {
335                 return addMilliseconds (value * Time.MillisPerMinute);
336         }*/
337
338         /**********************************************************************
339
340                 Adds the specified number of seconds to the _value of this
341                 instance.
342
343                 Params:  value = The number of seconds to add.
344                 Returns: A DateTime whose value is the sum of the date and
345                          time of this instance and the number of seconds in
346                          value.
347
348         **********************************************************************/
349
350         /*DateTime addSeconds (int value)
351         {
352                 return addMilliseconds (value * Time.MillisPerSecond);
353         }*/
354
355         /**********************************************************************
356
357                 Adds the specified number of milliseconds to the _value of
358                 this instance.
359
360                 Params:  value = The number of milliseconds to add.
361                 Returns: A DateTime whose value is the sum of the date and
362                          time of this instance and the number of milliseconds
363                          in value.
364
365         **********************************************************************/
366
367         /*DateTime addMilliseconds (long value)
368         {
369                 return addTicks (value * Time.TicksPerMillisecond);
370         }*/
371
372         /**********************************************************************
373
374                 Adds the specified number of days to the _value of this
375                 instance.
376
377                 Params:  value = The number of days to add.
378                 Returns: A DateTime whose value is the sum of the date
379                          and time of this instance and the number of days
380                          in value.
381
382         **********************************************************************/
383
384         /*DateTime addDays (int value)
385         {
386                 return addMilliseconds (value * Time.MillisPerDay);
387         }*/
388
389         /**********************************************************************
390
391                 Adds the specified number of months to the _value of this
392                 instance.
393
394                 Params:  value = The number of months to add.
395                 Returns: A DateTime whose value is the sum of the date and
396                          time of this instance and the number of months in
397                          value.
398
399         **********************************************************************/
400
401         DateTime addMonths (int value)
402         {
403                 int year = this.year;
404                 int month = this.month;
405                 int day = this.day;
406                 int n = month - 1 + value;
407
408                 if (n >= 0)
409                    {
410                    month = n % 12 + 1;
411                    year = year + n / 12;
412                    }
413                 else
414                    {
415                    month = 12 + (n + 1) % 12;
416                    year = year + (n - 11) / 12;
417                    }
418                 int maxDays = daysInMonth (year, month);
419                 if (day > maxDays)
420                     day = maxDays;
421
422                 return DateTime (getDateTicks(year, month, day) + (ticks % TimeSpan.TicksPerDay));
423         }
424
425         /**********************************************************************
426
427                 Adds the specified number of years to the _value of this
428                 instance.
429
430                 Params:  value = The number of years to add.
431                 Returns: A DateTime whose value is the sum of the date
432                          and time of this instance and the number of years
433                          in value.
434
435         **********************************************************************/
436
437         DateTime addYears (int value)
438         {
439                 return addMonths (value * 12);
440         }
441
442         /**********************************************************************
443
444                 $(I Property.) Retrieves the _year component of the date.
445
446                 Returns: The _year.
447
448         **********************************************************************/
449
450         int year ()
451         {
452                 return extractPart (ticks, Year);
453         }
454
455         /**********************************************************************
456
457                 $(I Property.) Retrieves the _month component of the date.
458
459                 Returns: The _month.
460
461         **********************************************************************/
462
463         int month ()
464         {
465                 return extractPart (ticks, Month);
466         }
467
468         /**********************************************************************
469
470                 $(I Property.) Retrieves the _day component of the date.
471
472                 Returns: The _day.
473
474         **********************************************************************/
475
476         int day ()
477         {
478                 return extractPart (ticks, Day);
479         }
480
481         /**********************************************************************
482
483                 $(I Property.) Retrieves the day of the year.
484
485                 Returns: The day of the year.
486
487         **********************************************************************/
488
489         int dayOfYear ()
490         {
491                 return extractPart (ticks, DayOfYear);
492         }
493
494         /**********************************************************************
495
496                 $(I Property.) Retrieves the day of the week.
497
498                 Returns: A DayOfWeek value indicating the day of the week.
499
500         **********************************************************************/
501
502         DayOfWeek dayOfWeek ()
503         {
504                 return cast(DayOfWeek) ((ticks / TimeSpan.TicksPerDay + 1) % 7);
505         }
506
507         /**********************************************************************
508
509                 $(I Property.) Retrieves the _hour component of the date.
510
511                 Returns: The _hour.
512
513         **********************************************************************/
514
515         int hour ()
516         {
517                 return cast(int) ((ticks / TimeSpan.TicksPerHour) % 24);
518         }
519
520         /**********************************************************************
521
522                 $(I Property.) Retrieves the _minute component of the date.
523
524                 Returns: The _minute.
525
526         **********************************************************************/
527
528         int minute ()
529         {
530                 return cast(int) ((ticks / TimeSpan.TicksPerMinute) % 60);
531         }
532
533         /**********************************************************************
534
535                 $(I Property.) Retrieves the _second component of the date.
536
537                 Returns: The _second.
538
539         **********************************************************************/
540
541         int second ()
542         {
543                 return cast(int) ((ticks / TimeSpan.TicksPerSecond) % 60);
544         }
545
546         /**********************************************************************
547
548                 $(I Property.) Retrieves the _millisecond component of the
549                 date.
550
551                 Returns: The _millisecond.
552
553         **********************************************************************/
554
555         int millisecond ()
556         {
557                 return cast(int) ((ticks / TimeSpan.TicksPerMillisecond) % 1000);
558         }
559
560         /**********************************************************************
561
562                 $(I Property.) Retrieves the date component.
563
564                 Returns: A new DateTime instance with the same date as
565                          this instance.
566
567         **********************************************************************/
568
569         DateTime date ()
570         {
571                 auto ticks = this.ticks;
572                 return DateTime (ticks - ticks % TimeSpan.TicksPerDay);
573         }
574
575         /**********************************************************************
576
577                 $(I Property.) Retrieves the time of day.
578
579                 Returns: A DateTime representing the fraction of the day elapsed since midnight.
580
581         **********************************************************************/
582
583         TimeSpan timeOfDay ()
584         {
585                 return TimeSpan (ticks % TimeSpan.TicksPerDay);
586         }
587
588         /**********************************************************************
589
590                 Returns the number of _days in the specified _month.
591
592                 Params:
593                   year = The _year.
594                   month = The _month.
595                 Returns: The number of _days in the specified _month.
596
597         **********************************************************************/
598
599         static int daysInMonth (int year, int month)
600         {
601                 int[] monthDays = isLeapYear(year) ? DaysToMonthLeap
602                                                    : DaysToMonthCommon;
603                 return monthDays[month] - monthDays[month - 1];
604         }
605
606         /**********************************************************************
607
608                 Returns a value indicating whether the specified _year is
609                 a leap _year.
610
611                 Params:  year = The _year.
612                 Returns: true if year is a leap _year; otherwise, false.
613
614         **********************************************************************/
615
616         static bool isLeapYear (int year)
617         {
618                 return (year % 4 == 0 && (year % 100 != 0 || year % 400 == 0));
619         }
620
621         /**********************************************************************
622
623         **********************************************************************/
624
625         private static long getDateTicks (int year, int month, int day)
626         {
627                 int[] monthDays = isLeapYear(year) ? DaysToMonthLeap
628                                                    : DaysToMonthCommon;
629                 --year;
630                 return (year * 365 + year / 4 - year / 100 + year / 400 +
631                         monthDays[month - 1] + day - 1) * TimeSpan.TicksPerDay;
632         }
633
634         /**********************************************************************
635
636         **********************************************************************/
637
638         private static void splitDate (long ticks, out int year, out int month, out int day, out int dayOfYear)
639         {
640                 int numDays = cast(int) (ticks / TimeSpan.TicksPerDay);
641                 int whole400Years = numDays / cast(int) TimeSpan.DaysPer400Years;
642                 numDays -= whole400Years * cast(int) TimeSpan.DaysPer400Years;
643                 int whole100Years = numDays / cast(int) TimeSpan.DaysPer100Years;
644                 if (whole100Years == 4)
645                     whole100Years = 3;
646
647                 numDays -= whole100Years * cast(int) TimeSpan.DaysPer100Years;
648                 int whole4Years = numDays / cast(int) TimeSpan.DaysPer4Years;
649                 numDays -= whole4Years * cast(int) TimeSpan.DaysPer4Years;
650                 int wholeYears = numDays / cast(int) TimeSpan.DaysPerYear;
651                 if (wholeYears == 4)
652                     wholeYears = 3;
653
654                 year = whole400Years * 400 + whole100Years * 100 + whole4Years * 4 + wholeYears + 1;
655                 numDays -= wholeYears * TimeSpan.DaysPerYear;
656                 dayOfYear = numDays + 1;
657
658                 int[] monthDays = (wholeYears == 3 && (whole4Years != 24 || whole100Years == 3)) ? DaysToMonthLeap : DaysToMonthCommon;
659                 month = numDays >> 5 + 1;
660                 while (numDays >= monthDays[month])
661                        month++;
662
663                 day = numDays - monthDays[month - 1] + 1;
664         }
665
666         /**********************************************************************
667
668         **********************************************************************/
669
670         private static int extractPart (long ticks, int part)
671         {
672                 int year, month, day, dayOfYear;
673
674                 splitDate (ticks, year, month, day, dayOfYear);
675
676                 if (part is Year)
677                     return year;
678
679                 if (part is Month)
680                     return month;
681
682                 if (part is DayOfYear)
683                     return dayOfYear;
684
685                 return day;
686         }
687
688 }
689
690 /*******************************************************************************
691
692 *******************************************************************************/
693
694 debug (DateTime)
695 {
696         import tango.io.Stdout;
697
698         DateTime foo()
699         {
700                 auto d = DateTime(10);
701                 auto e = TimeSpan(20);
702
703                 return d + e;
704         }
705
706         void main()
707         {
708                 auto c = foo();
709                 Stdout (c.ticks).newline;
710         }
711 }