2005-06-06 Zoltan Varga <vargaz@freemail.hu>
[mono.git] / mcs / class / Microsoft.VisualBasic / Microsoft.VisualBasic / DateAndTime.cs
1 //
2 // DateAndTime.cs
3 //
4 // Author:
5 //   Chris J Breisch (cjbreisch@altavista.net) 
6 //   Pablo Cardona (pcardona37@hotmail.com) CRL Team
7
8 // (C) 2002 Chris J Breisch
9 //
10
11 //
12 // Copyright (c) 2002-2003 Mainsoft Corporation.
13 // Copyright (C) 2004 Novell, Inc (http://www.novell.com)
14 //
15 // Permission is hereby granted, free of charge, to any person obtaining
16 // a copy of this software and associated documentation files (the
17 // "Software"), to deal in the Software without restriction, including
18 // without limitation the rights to use, copy, modify, merge, publish,
19 // distribute, sublicense, and/or sell copies of the Software, and to
20 // permit persons to whom the Software is furnished to do so, subject to
21 // the following conditions:
22 // 
23 // The above copyright notice and this permission notice shall be
24 // included in all copies or substantial portions of the Software.
25 // 
26 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
27 // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
28 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
29 // NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
30 // LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
31 // OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
32 // WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
33 //
34
35 using System;
36 using System.Runtime.InteropServices;
37 using System.ComponentModel;
38 using System.Globalization;
39 using Microsoft.VisualBasic.CompilerServices;
40
41 namespace Microsoft.VisualBasic 
42 {
43         [StandardModule] 
44         sealed public class DateAndTime {
45
46                 private DateAndTime ()
47                 {
48                         //Nobody should see constructor
49                 }
50
51                 public static string DateString {
52                         get { 
53                                 return DateTime.Today.ToString("MM-dd-yyyy");
54                         }
55                         
56                         set { 
57                                 string [] formats = { "M-d-yyyy", "M-d-y", "M/d/yyyy", "M/d/y" };
58
59                                 try {
60                                         DateTime dtToday = DateTime.ParseExact(value, formats,
61                                                 DateTimeFormatInfo.CurrentInfo,
62                                                 DateTimeStyles.None);
63                                 
64                                         Today = dtToday;
65                                 }
66                                 catch {
67                                         throw new InvalidCastException();
68                                 }
69                         } 
70                 }
71                 
72                 [DllImport("libc")]
73                 static extern int stime (ref int t);
74
75                 public static System.DateTime Today {
76                         get { 
77                                 return DateTime.Today; 
78                         }
79                         set { 
80                                 System.DateTime Now = DateTime.Now;
81                                 System.DateTime NewDate = new DateTime(value.Year, value.Month, value.Day,
82                                                                        Now.Hour, Now.Minute, Now.Second, Now.Millisecond);
83                                 System.TimeSpan secondsTimeSpan = NewDate.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0);
84                                 int seconds = (int) secondsTimeSpan.TotalSeconds;
85
86                                 if(stime(ref seconds) == -1)
87                                         throw new UnauthorizedAccessException("The caller is not the super-user.");
88                         }
89  
90                 }
91
92                 public static double Timer {  
93                         get { 
94                                 DateTime DTNow = DateTime.Now;
95
96                                 return DTNow.Hour * 3600 + DTNow.Minute * 60 +
97                                         DTNow.Second + DTNow.Millisecond / 
98                                         1000D;
99                         } 
100                 }
101
102                 public static System.DateTime Now {
103                         get { return DateTime.Now; }
104                 }
105
106                 public static System.DateTime TimeOfDay {  
107                         get { 
108                                 TimeSpan TSpan = DateTime.Now.TimeOfDay;
109
110                                 return new DateTime(1, 1, 1, TSpan.Hours, 
111                                         TSpan.Minutes, TSpan.Seconds, 
112                                         TSpan.Milliseconds); 
113                         }
114                         set {
115                                  Today = DateTime.Now;
116                                  System.DateTime NewTime = new DateTime(Today.Year, Today.Month, Today.Day,
117                                                                         value.Hour,value.Minute,value.Second);
118
119                                  TimeSpan secondsTimeSpan = NewTime.ToUniversalTime() - new DateTime(1970, 1, 1, 0, 0, 0, 0);
120                                  int seconds = (int) secondsTimeSpan.TotalSeconds;
121
122                                  if(stime(ref seconds) == -1)
123                                          throw new UnauthorizedAccessException("The caller is not the super-user.");
124                         }
125  
126                 }
127
128                 public static string TimeString {  
129                         get { return DateTime.Now.ToString("HH:mm:ss"); } 
130                         set { 
131                                 string format = "HH:mm:ss";
132
133                                 try {
134                                         DateTime dtToday = DateTime.ParseExact(value, format,
135                                                 DateTimeFormatInfo.CurrentInfo,
136                                                 DateTimeStyles.None);
137                                 
138                                         TimeOfDay = dtToday;
139                                 }
140                                 catch {
141                                         throw new InvalidCastException();
142                                 } 
143                         } 
144                 }
145         
146                 // Methods
147                 public static System.DateTime DateAdd (DateInterval Interval, 
148                         double Number, System.DateTime DateValue) {
149
150                         switch (Interval) {
151                                 case DateInterval.Year:
152                                         return DateValue.AddYears((int)Number);
153                                 case DateInterval.Quarter:
154                                         return DateValue.AddMonths((int)Number * 3);
155                                 case DateInterval.Month:
156                                         return DateValue.AddMonths((int)Number);
157                                 case DateInterval.WeekOfYear:
158                                         return DateValue.AddDays(Number * 7);
159                                 case DateInterval.Day:
160                                 case DateInterval.DayOfYear:
161                                 case DateInterval.Weekday:
162                                         return DateValue.AddDays(Number);
163                                 case DateInterval.Hour:
164                                         return DateValue.AddHours(Number);
165                                 case DateInterval.Minute:
166                                         return DateValue.AddMinutes(Number);
167                                 case DateInterval.Second:
168                                         return DateValue.AddSeconds(Number);
169                                 default:
170                                         throw new ArgumentException();
171                         }
172                 }
173
174                 private static DayOfWeek GetDayRule(FirstDayOfWeek StartOfWeek, DayOfWeek DayRule) 
175                 {
176                         switch (StartOfWeek) {
177                                 case FirstDayOfWeek.System:
178                                         return DayRule;
179                                 case FirstDayOfWeek.Sunday:
180                                         return DayOfWeek.Sunday;
181                                 case FirstDayOfWeek.Monday:
182                                         return DayOfWeek.Monday;
183                                 case FirstDayOfWeek.Tuesday:
184                                         return DayOfWeek.Tuesday;
185                                 case FirstDayOfWeek.Wednesday:
186                                         return DayOfWeek.Wednesday;
187                                 case FirstDayOfWeek.Thursday:
188                                         return DayOfWeek.Thursday;
189                                 case FirstDayOfWeek.Friday:
190                                         return DayOfWeek.Friday;
191                                 case FirstDayOfWeek.Saturday:
192                                         return DayOfWeek.Saturday;
193                                 default:
194                                         throw new ArgumentException();
195                         }
196                 }
197
198                 private static CalendarWeekRule GetWeekRule(FirstWeekOfYear StartOfYear, CalendarWeekRule WeekRule) 
199                 {
200                         switch (StartOfYear) {
201                                 case FirstWeekOfYear.System:
202                                         return WeekRule;
203                                 case FirstWeekOfYear.FirstFourDays:
204                                         return CalendarWeekRule.FirstFourDayWeek;
205                                 case FirstWeekOfYear.FirstFullWeek:
206                                         return CalendarWeekRule.FirstFullWeek;
207                                 case FirstWeekOfYear.Jan1:
208                                         return CalendarWeekRule.FirstDay;
209                                 default:
210                                         throw new ArgumentException();
211                         }
212                 }
213                 
214                 public static long DateDiff (DateInterval Interval, 
215                         System.DateTime Date1, System.DateTime Date2, 
216                         [Optional, __DefaultArgumentValue((int)FirstDayOfWeek.Sunday)] 
217                         FirstDayOfWeek StartOfWeek, 
218                         [Optional, __DefaultArgumentValue((int)FirstWeekOfYear.Jan1)] 
219                         FirstWeekOfYear StartOfYear) 
220                 {
221                         
222                         int YearMonths;
223                         int YearQuarters;
224                         int YearWeeks;
225                         CalendarWeekRule WeekRule = CalendarWeekRule.FirstDay;
226                         DayOfWeek DayRule = DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek;
227                         Calendar CurCalendar = CultureInfo.CurrentCulture.Calendar;
228
229                         switch (Interval) {
230                                 case DateInterval.Year:
231                                         return Date2.Year - Date1.Year;
232                                 case DateInterval.Quarter:
233                                         YearQuarters = (Date2.Year - Date1.Year) * 4;
234                                         return Date2.Month / 4 - Date1.Month / 4 + YearQuarters;
235                                 case DateInterval.Month:
236                                         YearMonths = (Date2.Year - Date1.Year) * 12;
237                                         return Date2.Month - Date1.Month + YearMonths;
238                                 case DateInterval.WeekOfYear:
239                                         YearWeeks = (Date2.Year - Date1.Year) * 53;
240                                         DayRule = GetDayRule(StartOfWeek, DayRule);
241                                         WeekRule = GetWeekRule(StartOfYear, WeekRule);
242                                         if (CurCalendar == null)
243                                                 throw new NotImplementedException("Looks like CultureInfo.CurrentCulture.Calendar is still returning null");
244                                         return CurCalendar.GetWeekOfYear(Date2, WeekRule, DayRule) -
245                                                 CurCalendar.GetWeekOfYear(Date1,WeekRule, DayRule) + 
246                                                 YearWeeks;
247                                 case DateInterval.Weekday:
248                                         return ((TimeSpan)(Date2.Subtract(Date1))).Days / 7;
249                                 case DateInterval.DayOfYear:
250                                 case DateInterval.Day:
251                                         return ((TimeSpan)(Date2.Subtract(Date1))).Days;
252                                 case DateInterval.Hour:
253                                         return (int)((TimeSpan)(Date2.Subtract(Date1))).TotalHours;
254                                 case DateInterval.Minute:
255                                         return (int)((TimeSpan)(Date2.Subtract(Date1))).TotalMinutes;
256                                 case DateInterval.Second:
257                                         return (int)((TimeSpan)(Date2.Subtract(Date1))).TotalSeconds;
258                                 default:
259                                         throw new ArgumentException();
260                         }
261                 }
262
263                 private static int ConvertWeekDay(DayOfWeek Day, int Offset) 
264                 {
265                         if (Offset == 0)
266                                 return (int)Day+1;
267
268                         int Weekday = (int)Day + 1 - Offset;
269                         if (Weekday < 0)
270                                 Weekday += 7;
271
272                         return Weekday + 1;
273
274                         /*if(Offset >= 7)
275                                 Offset  -= 7;
276
277                         int Weekday = (int)Day + Offset;
278
279                         if (Weekday > 7) {
280                                 Weekday -= 7;
281                         }
282
283                         switch((DayOfWeek)Weekday) {
284                                 case DayOfWeek.Sunday:
285                                         return (int)FirstDayOfWeek.Sunday;
286                                 case DayOfWeek.Monday:
287                                         return (int)FirstDayOfWeek.Monday;
288                                 case DayOfWeek.Tuesday:
289                                         return (int)FirstDayOfWeek.Tuesday;
290                                 case DayOfWeek.Wednesday:
291                                         return (int)FirstDayOfWeek.Wednesday;
292                                 case DayOfWeek.Thursday:
293                                         return (int)FirstDayOfWeek.Thursday;
294                                 case DayOfWeek.Friday:
295                                         return (int)FirstDayOfWeek.Friday;
296                                 case DayOfWeek.Saturday:
297                                         return (int)FirstDayOfWeek.Saturday;
298                                 default:
299                                         throw new ArgumentException();
300                         }*/
301
302                 }
303
304                 public static int DatePart 
305                 (
306                         Microsoft.VisualBasic.DateInterval Interval, 
307                         System.DateTime DateValue, 
308                         [Optional, __DefaultArgumentValue((int)FirstDayOfWeek.Sunday)] 
309                         FirstDayOfWeek StartOfWeek, 
310                         [Optional, __DefaultArgumentValue((int)FirstWeekOfYear.Jan1)] 
311                         FirstWeekOfYear StartOfYear) {
312                 
313                         CalendarWeekRule WeekRule = CalendarWeekRule.FirstDay;
314                         DayOfWeek DayRule = DateTimeFormatInfo.CurrentInfo.FirstDayOfWeek;
315                         Calendar CurCalendar = CultureInfo.CurrentCulture.Calendar;
316
317                         switch (Interval) {
318                                 case DateInterval.Year:
319                                         return DateValue.Year;
320                                 case DateInterval.Quarter:
321                                         return DateValue.Month / 4 + 1;
322                                 case DateInterval.Month:
323                                         return DateValue.Month;
324                                 case DateInterval.WeekOfYear:
325                                         DayRule = GetDayRule(StartOfWeek, DayRule);
326                                         WeekRule = GetWeekRule(StartOfYear, WeekRule);
327                                         return CurCalendar.GetWeekOfYear(DateValue, WeekRule, DayRule);
328                                 case DateInterval.Weekday:
329                                         return ConvertWeekDay(DateValue.DayOfWeek, (int)StartOfWeek);
330                                 case DateInterval.DayOfYear:
331                                         return DateValue.DayOfYear;
332                                 case DateInterval.Day:
333                                         return DateValue.Day;
334                                 case DateInterval.Hour:
335                                         return DateValue.Hour;
336                                 case DateInterval.Minute:
337                                         return DateValue.Minute;
338                                 case DateInterval.Second:
339                                         return DateValue.Second;
340                                 default:
341                                         throw new ArgumentException();
342                         }
343                 }
344
345                 private static DateInterval DateIntervalFromString(string Interval) 
346                 {
347                         switch (Interval) {
348                                 case "yyyy":
349                                         return DateInterval.Year;
350                                 case "q":
351                                         return DateInterval.Quarter;
352                                 case "m":
353                                         return DateInterval.Month;
354                                 case "ww":
355                                         return DateInterval.WeekOfYear;
356                                 case "w":
357                                         return DateInterval.Weekday;
358                                 case "d":
359                                         return DateInterval.Day;
360                                 case "y":
361                                         return DateInterval.DayOfYear;
362                                 case "h":
363                                         return DateInterval.Hour;
364                                 case "n":
365                                         return DateInterval.Minute;
366                                 case "s":
367                                         return DateInterval.Second;
368                         default:
369                                         throw new ArgumentException();
370                         }
371                 }
372
373                 public static System.DateTime DateAdd (string Interval, 
374                         double Number, System.Object DateValue) 
375                 {
376                         if (DateValue == null) {
377                                 throw new ArgumentNullException("DateValue", "Value can not be null.");
378                         }
379                         if (!(DateValue is DateTime)) {
380                                 throw new InvalidCastException();
381                         }
382                         
383                         return DateAdd(DateIntervalFromString(Interval), Number, (DateTime)DateValue);
384                 }
385
386                 public static System.Int64 DateDiff (string Interval, 
387                         System.Object Date1, System.Object Date2, 
388                         [Optional, __DefaultArgumentValue((int)FirstDayOfWeek.Sunday)]
389                         FirstDayOfWeek StartOfWeek, 
390                         [Optional, __DefaultArgumentValue((int)FirstWeekOfYear.Jan1)] 
391                         FirstWeekOfYear StartOfYear) 
392                 {
393                         if (Date1 == null) {
394                                 throw new ArgumentNullException("Date1", "Value can not be null.");
395                         }
396                         if (Date2 == null) {
397                                 throw new ArgumentNullException("Date2", "Value can not be null.");
398                         }
399                         if (!(Date1 is DateTime)) {
400                                 throw new InvalidCastException();
401                         }
402                         if (!(Date2 is DateTime)) {
403                                 throw new InvalidCastException();
404                         }
405                         
406                         return DateDiff(DateIntervalFromString(Interval), (DateTime)Date1, 
407                                 (DateTime)Date2, StartOfWeek, StartOfYear);
408                         
409                 }
410
411                 public static System.Int32 DatePart (string Interval, 
412                         System.Object DateValue, 
413                         [Optional, __DefaultArgumentValue((int)FirstDayOfWeek.Sunday)] 
414                         FirstDayOfWeek StartOfWeek, 
415                         [Optional, __DefaultArgumentValue((int)FirstWeekOfYear.Jan1)] 
416                         FirstWeekOfYear StartOfYear) 
417                 {
418                         if (DateValue == null) {
419                                 throw new ArgumentNullException("DateValue", "Value can not be null.");
420                         }
421                         if (!(DateValue is DateTime)) {
422                                 throw new InvalidCastException();
423                         }
424                         
425                         
426                         return DatePart(DateIntervalFromString(Interval), 
427                                 (DateTime)DateValue, StartOfWeek, StartOfYear);
428                 }
429
430                 public static System.DateTime DateSerial (int Year, int Month, int Day) 
431                 {
432                         DateTime date;
433
434                         if (Year < 0)
435                                 Year = Year + DateTime.Now.Year;
436                         else if (Year >= 0 && Year <= 29)
437                                 Year += 2000;
438                         else if(Year >= 30 && Year <= 99)
439                                 Year += 1900;
440
441                         date = new DateTime(Year, 1, 1); 
442
443                         date = date.AddMonths(Month - 1);
444
445                         date = date.AddDays(Day - 1);
446
447                         return date;
448                 }
449
450                 public static System.DateTime TimeSerial (int Hour, int Minute, int Second) 
451                 {
452                         int day = 1;
453
454                         if (Second < 0) {
455                                 if (Minute == 0 && Hour == 0)
456                                         Second += 60;
457                                 else if (Minute == 0){
458                                         Second += 60;
459                                         Minute = 59;
460                                         Hour--;     
461                                 }
462                                 else {
463                                         Second += 60;
464                                         Minute--;                    
465                                 }                
466                         }
467                         else if(Second > 59){
468                                 Minute += Second/60;
469                                 Second = Second%60;
470                         }
471
472                         if (Minute < 0) {
473                                 if (Hour == 0)
474                                         Minute += 60;
475                                 else {    
476                                         Minute += 60;
477                                         Hour--;
478                                 }        
479                         }
480                         else if (Minute > 59){
481                                 Hour += Minute/60;
482                                 Minute = Minute%60;
483                         }
484
485                         if (Hour < 0)
486                                 Hour += 24;
487                         else if (Hour > 23)     {
488                                 day += Hour/24;
489                                 Hour = Hour%24;
490                         }
491
492                         return new DateTime(1, 1, day, Hour, Minute, Second);
493                 }
494
495                 public static System.DateTime DateValue (string StringDate) 
496                 { 
497                         string[] expectedFormats = {"D", "d", "G", "g", "f" ,"F", "m", "M", "r", "R",
498                                                         "s", "T", "t", "U", "u", "Y", "y",
499                                                         "MMM dd, yy", "MMMM dd, yy", "MMM dd, yyyy", "MMMM dd, yyyy"};
500                         
501                         try {
502                                 return DateTime.ParseExact(StringDate, expectedFormats,
503                                                         System.Globalization.CultureInfo.CurrentCulture.DateTimeFormat,
504                                                         System.Globalization.DateTimeStyles.NoCurrentDateDefault);
505                         } 
506                         catch (FormatException exception) {
507                                 throw new InvalidCastException(null, exception);
508                         }
509                 }
510
511                 public static System.DateTime TimeValue (string StringTime) 
512                 { 
513                         try {
514                                 return DateTime.MinValue + DateTime.Parse(StringTime).TimeOfDay;
515                         } catch (FormatException exception) {
516                                 throw new InvalidCastException(null, exception);
517                         }
518                 }
519
520                 public static int Year (System.DateTime DateValue) 
521                 { 
522                         return DateValue.Year;
523                 }
524
525                 public static int Month (System.DateTime DateValue) 
526                 { 
527                         return DateValue.Month;
528                 }
529
530                 public static int Day (System.DateTime DateValue) 
531                 { 
532                         return DateValue.Day;
533                 }
534
535                 public static int Hour (System.DateTime TimeValue) 
536                 { 
537                         return TimeValue.Hour;
538                 }
539
540                 public static int Minute (System.DateTime TimeValue) 
541                 { 
542                         return TimeValue.Minute;
543                 }
544
545                 public static int Second (System.DateTime TimeValue) 
546                 { 
547                         return TimeValue.Second;
548                 }
549
550                 public static int Weekday (System.DateTime DateValue, 
551                         [Optional, __DefaultArgumentValue((int)FirstDayOfWeek.Sunday)] 
552                         FirstDayOfWeek StartOfWeek) 
553                 { 
554                         return DatePart(DateInterval.Weekday, DateValue, StartOfWeek, FirstWeekOfYear.System);
555                 }
556
557                 public static System.String MonthName (int Month, 
558                         [Optional, __DefaultArgumentValue(false)] bool Abbreviate) 
559                 { 
560                         if (Month < 1 || Month > 13) {
561                                 throw new ArgumentException();
562                         }
563                         if (Abbreviate) {
564                                 return CultureInfo.CurrentCulture.DateTimeFormat.GetAbbreviatedMonthName(Month);
565                         }
566                         else {
567                                 return CultureInfo.CurrentCulture.DateTimeFormat.GetMonthName(Month);
568                         }
569                 }
570                 
571                 public static System.String WeekdayName (int Weekday, 
572                         [Optional, __DefaultArgumentValue(false)] System.Boolean Abbreviate, 
573                         [Optional, __DefaultArgumentValue((int)FirstDayOfWeek.System)] 
574                         FirstDayOfWeek FirstDayOfWeekValue) 
575                 { 
576                         if (Weekday < 1 || Weekday > 7) {
577                                 throw new ArgumentException();
578                         }
579                         Weekday += (int)FirstDayOfWeekValue;
580                         if (Weekday > 7) {
581                                 Weekday -= 7;
582                         }
583                         if (Abbreviate) {
584                                 return CultureInfo.CurrentCulture.DateTimeFormat.GetAbbreviatedDayName((DayOfWeek)Weekday);
585                         }
586                         else {
587                                 return CultureInfo.CurrentCulture.DateTimeFormat.GetDayName((DayOfWeek)Weekday);
588                         }
589                 }
590         }
591 }