2007-12-16 Stephane Delcroix <sdelcroix@novell.com>
[mono.git] / mcs / class / corlib / System / DateTimeOffset.cs
1 /*
2  * System.DateTimeOffset
3  *
4  * Author(s)
5  *      Stephane Delcroix <stephane@delcroix.org>
6  *      Marek Safar (marek.safar@gmail.com)
7  *
8  *  Copyright (C) 2007 Novell, Inc (http://www.novell.com) 
9  *
10  * Permission is hereby granted, free of charge, to any person obtaining
11  * a copy of this software and associated documentation files (the
12  * "Software"), to deal in the Software without restriction, including
13  * without limitation the rights to use, copy, modify, merge, publish,
14  * distribute, sublicense, and/or sell copies of the Software, and to
15  * permit persons to whom the Software is furnished to do so, subject to
16  * the following conditions:
17  * 
18  * The above copyright notice and this permission notice shall be
19  * included in all copies or substantial portions of the Software.
20  * 
21  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
22  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
23  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
24  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
25  * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
26  * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
27  * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
28  */
29
30
31 #if NET_2_0 // Introduced by .NET 3.5 for 2.0 mscorlib
32
33 using System.Globalization;
34 using System.Runtime.InteropServices;
35 using System.Runtime.Serialization;
36
37 namespace System
38 {
39         [Serializable]
40         [StructLayout (LayoutKind.Auto)]
41         public struct DateTimeOffset : IComparable, IFormattable, ISerializable, IDeserializationCallback, IComparable<DateTimeOffset>, IEquatable<DateTimeOffset>
42         {
43                 public static readonly DateTimeOffset MaxValue = new DateTimeOffset (DateTime.MaxValue);
44                 public static readonly DateTimeOffset MinValue = new DateTimeOffset (DateTime.MaxValue);
45                 
46                 DateTime dt;
47                 TimeSpan utc_offset;
48         
49                 public DateTimeOffset (DateTime dateTime)
50                 {
51                         dt = dateTime;
52
53                         if (dateTime.Kind == DateTimeKind.Utc)
54                                 utc_offset = TimeSpan.Zero;
55                         else 
56                                 utc_offset = TimeZone.CurrentTimeZone.GetUtcOffset (dateTime);
57                                 
58                         if (UtcDateTime < DateTime.MinValue || UtcDateTime > DateTime.MaxValue)
59                                 throw new ArgumentOutOfRangeException ("The UTC date and time that results from applying the offset is earlier than MinValue or later than MaxValue.");
60
61                 }
62                 
63                 public DateTimeOffset (DateTime dateTime, TimeSpan offset)
64                 {
65                         if (dateTime.Kind == DateTimeKind.Utc && offset != TimeSpan.Zero)
66                                 throw new ArgumentException ("dateTime.Kind equals Utc and offset does not equal zero.");
67
68                         if (dateTime.Kind == DateTimeKind.Local && offset != TimeZone.CurrentTimeZone.GetUtcOffset (dateTime))
69                                 throw new ArgumentException ("dateTime.Kind equals Local and offset does not equal the offset of the system's local time zone.");
70
71                         if (offset.Ticks % TimeSpan.TicksPerMinute != 0)
72                                 throw new ArgumentException ("offset is not specified in whole minutes.");
73
74                         if (offset < new TimeSpan (-14, 0 ,0) || offset > new TimeSpan (14, 0, 0))
75                                 throw new ArgumentOutOfRangeException ("offset is less than -14 hours or greater than 14 hours.");
76
77                         dt = dateTime;
78                         utc_offset = offset;
79
80                         if (UtcDateTime < DateTime.MinValue || UtcDateTime > DateTime.MaxValue)
81                                 throw new ArgumentOutOfRangeException ("The UtcDateTime property is earlier than MinValue or later than MaxValue.");
82                 }
83
84                 public DateTimeOffset (long ticks, TimeSpan offset) : this (new DateTime (ticks), offset)
85                 {
86                 }
87
88                 public DateTimeOffset (int year, int month, int day, int hour, int minute, int second, TimeSpan offset) : 
89                         this (new DateTime (year, month, day, hour, minute, second), offset)
90                 {
91                 }
92
93                 public DateTimeOffset (int year, int month, int day, int hour, int minute, int second, int millisecond, TimeSpan offset) :
94                         this (new DateTime (year, month, day, hour, minute, second, millisecond), offset)
95                 {
96                 }
97
98                 public DateTimeOffset (int year, int month, int day, int hour, int minute, int second, int millisecond, Calendar calendar, TimeSpan offset) :
99                         this (new DateTime (year, month, day, hour, minute, second, millisecond, calendar), offset)
100                 {
101                 }
102
103                 public DateTimeOffset Add (TimeSpan timeSpan)
104                 {
105                         return new DateTimeOffset (dt.Add (timeSpan), utc_offset);
106                 }
107         
108                 public DateTimeOffset AddDays (double days)
109                 {
110                         return new DateTimeOffset (dt.AddDays (days), utc_offset);      
111                 }
112                 
113                 public DateTimeOffset AddHours (double hours)
114                 {
115                         return new DateTimeOffset (dt.AddHours (hours), utc_offset);
116                 }
117
118                 public static DateTimeOffset operator + (DateTimeOffset dateTimeTz, TimeSpan timeSpan)
119                 {
120                         return dateTimeTz.Add (timeSpan);
121                 }
122
123                 public DateTimeOffset AddMilliseconds (double milliseconds)
124                 {
125                         return new DateTimeOffset (dt.AddMilliseconds (milliseconds), utc_offset);
126                 }
127
128                 public DateTimeOffset AddMinutes (double minutes)
129                 {
130                         return new DateTimeOffset (dt.AddMinutes (minutes), utc_offset);        
131                 }
132
133                 public DateTimeOffset AddMonths (int months)
134                 {
135                         return new DateTimeOffset (dt.AddMonths (months), utc_offset);
136                 }
137
138                 public DateTimeOffset AddSeconds (double seconds)
139                 {
140                         return new DateTimeOffset (dt.AddSeconds (seconds), utc_offset);
141                 }
142
143                 public DateTimeOffset AddTicks (long ticks)
144                 {
145                         return new DateTimeOffset (dt.AddTicks (ticks), utc_offset);    
146                 }
147
148                 public DateTimeOffset AddYears (int years)
149                 {
150                         return new DateTimeOffset (dt.AddYears (years), utc_offset);
151                 }
152
153                 public static int Compare (DateTimeOffset first, DateTimeOffset second)
154                 {
155                         return first.CompareTo (second);        
156                 }
157
158                 public int CompareTo (DateTimeOffset other)
159                 {
160                         return UtcDateTime.CompareTo (other.UtcDateTime);
161                 }
162
163                 public int CompareTo (object other)
164                 {
165                         return UtcDateTime.CompareTo (other);
166                 }
167
168                 public static bool operator == (DateTimeOffset left, DateTimeOffset right)
169                 {
170                         return left.Equals (right);     
171                 }
172
173                 public bool Equals (DateTimeOffset other)
174                 {
175                         return UtcDateTime == other.UtcDateTime;
176                 }
177
178                 public override bool Equals (object other)
179                 {
180                         return UtcDateTime == ((DateTimeOffset) other).UtcDateTime;
181                 }
182
183                 public static bool Equals (DateTimeOffset first, DateTimeOffset second)
184                 {
185                         return first.Equals (second);   
186                 }
187
188                 public bool EqualsExact (DateTimeOffset other)
189                 {
190                         return dt == other.dt && utc_offset == other.utc_offset;        
191                 }
192
193                 public static DateTimeOffset FromFileTime (long fileTime)
194                 {
195                         if (fileTime < 0 || fileTime > MaxValue.Ticks)
196                                 throw new ArgumentOutOfRangeException ("fileTime is less than zero or greater than DateTimeOffset.MaxValue.Ticks.");
197                         
198                         return new DateTimeOffset (DateTime.FromFileTime (fileTime), TimeZone.CurrentTimeZone.GetUtcOffset (DateTime.FromFileTime (fileTime)));
199
200                 }
201
202                 public override int GetHashCode ()
203                 {
204                         return dt.GetHashCode () ^ utc_offset.GetHashCode ();
205                 }
206
207                 void ISerializable.GetObjectData (SerializationInfo info, StreamingContext context)
208                 {
209                         if (info == null)
210                                 throw new ArgumentNullException ("info");
211
212                         info.AddValue ("datetime", dt);
213                         info.AddValue ("offset", utc_offset);
214                 }
215
216                 public static bool operator > (DateTimeOffset left, DateTimeOffset right)
217                 {
218                         return left.UtcDateTime > right.UtcDateTime;
219                 }                       
220
221                 public static bool operator >= (DateTimeOffset left, DateTimeOffset right)
222                 {
223                         return left.UtcDateTime >= right.UtcDateTime;
224                 }                       
225
226                 public static implicit operator DateTimeOffset (DateTime dateTime)
227                 {
228                         return new DateTimeOffset (dateTime);
229                 }
230
231                 public static bool operator != (DateTimeOffset left, DateTimeOffset right)
232                 {
233                         return left.UtcDateTime != right.UtcDateTime;
234                 }
235
236                 public static bool operator < (DateTimeOffset left, DateTimeOffset right)
237                 {
238                         return left.UtcDateTime < right.UtcDateTime;
239                 }
240                 
241                 public static bool operator <= (DateTimeOffset left, DateTimeOffset right)
242                 {
243                         return left.UtcDateTime <= right.UtcDateTime;
244                 }
245         
246                 void IDeserializationCallback.OnDeserialization (object sender)
247                 {
248                 }
249
250                 [MonoTODO]
251                 public static DateTimeOffset Parse (string input)
252                 {
253                         if (input == null)
254                                 throw new ArgumentNullException ("input");
255
256                         throw new NotImplementedException ();
257                 }
258
259                 [MonoTODO]
260                 public static DateTimeOffset Parse (string input, IFormatProvider formatProvider)
261                 {
262                         if (input == null)
263                                 throw new ArgumentNullException ("input");
264
265                         throw new NotImplementedException ();
266                 }
267
268                 [MonoTODO]
269                 public static DateTimeOffset Parse (string input, IFormatProvider formatProvider, DateTimeStyles styles)
270                 {
271                         if (input == null)
272                                 throw new ArgumentNullException ("input");
273
274                         throw new NotImplementedException ();
275                 }
276
277                 [MonoTODO]
278                 public static DateTimeOffset ParseExact (string input, string format, IFormatProvider formatProvider)
279                 {
280                         if (input == null)
281                                 throw new ArgumentNullException ("input");
282                                 
283                         if (format == null)
284                                 throw new ArgumentNullException ("format");
285
286                         if (input == String.Empty)
287                                 throw new FormatException ("input is an empty string");
288
289                         if (format == String.Empty)
290                                 throw new FormatException ("format is an empty string");
291
292                         throw new NotImplementedException ();
293                 }
294
295                 [MonoTODO]
296                 public static DateTimeOffset ParseExact (string input, string format, IFormatProvider formatProvider, DateTimeStyles styles)
297                 {
298                         if (input == null)
299                                 throw new ArgumentNullException ("input");
300                                 
301                         if (format == null)
302                                 throw new ArgumentNullException ("format");
303
304                         if (input == String.Empty)
305                                 throw new FormatException ("input is an empty string");
306
307                         if (format == String.Empty)
308                                 throw new FormatException ("format is an empty string");
309
310                         throw new NotImplementedException ();
311                 }
312
313                 [MonoTODO]
314                 public static DateTimeOffset ParseExact (string input, string[] formats, IFormatProvider formatProvider, DateTimeStyles styles)
315                 {
316                         if (input == null)
317                                 throw new ArgumentNullException ("input");
318                                 
319
320                         if (input == String.Empty)
321                                 throw new FormatException ("input is an empty string");
322
323                         throw new NotImplementedException ();
324                 }
325
326                 public TimeSpan Subtract (DateTimeOffset other)
327                 {
328                         return UtcDateTime - other.UtcDateTime;
329                 }
330
331                 public DateTimeOffset Subtract (TimeSpan timeSpan)
332                 {
333                         return Add (-timeSpan);
334                 }
335
336                 public static TimeSpan operator - (DateTimeOffset left, DateTimeOffset right)
337                 {
338                         return left.Subtract (right);
339                 }
340
341                 public static DateTimeOffset operator - (DateTimeOffset dateTimeTz, TimeSpan timeSpan)
342                 {
343                         return dateTimeTz.Subtract (timeSpan);  
344                 }
345
346                 public long ToFileTime ()
347                 {
348                         return UtcDateTime.ToFileTime ();
349                 }
350
351                 public DateTimeOffset ToLocalTime ()
352                 {
353                         return new DateTimeOffset (UtcDateTime.ToLocalTime (), TimeZone.CurrentTimeZone.GetUtcOffset (UtcDateTime.ToLocalTime ()));
354                 }
355
356                 public DateTimeOffset ToOffset (TimeSpan offset)
357                 {
358                         return new DateTimeOffset (dt - utc_offset + offset, offset);
359                 }
360
361                 [MonoTODO]
362                 public override string ToString ()
363                 {
364                         throw new NotImplementedException ();
365                 }
366
367                 [MonoTODO]
368                 public string ToString (IFormatProvider formatProvider)
369                 {
370                         throw new NotImplementedException ();   
371                 }
372
373                 [MonoTODO]
374                 public string ToString (string format)
375                 {
376                         throw new NotImplementedException ();
377                 }
378
379                 [MonoTODO]
380                 public string ToString (string format, IFormatProvider formatProvider)
381                 {
382                         throw new NotImplementedException ();   
383                 }
384
385                 public DateTimeOffset ToUniversalTime ()
386                 {
387                         return new DateTimeOffset (UtcDateTime, TimeSpan.Zero); 
388                 }
389
390                 public static bool TryParse (string input, out DateTimeOffset result)
391                 {
392                         try {
393                                 result = Parse (input);
394                                 return true;
395                         } catch {
396                                 result = MinValue;
397                                 return false;
398                         }
399                 }
400
401                 public static bool TryParse (string input, IFormatProvider formatProvider, DateTimeStyles styles, out DateTimeOffset result)
402                 {
403                         try {
404                                 result = Parse (input, formatProvider, styles);
405                                 return true;
406                         } catch {
407                                 result = MinValue;
408                                 return false;
409                         }       
410                 }
411
412                 public static bool TryParseExact (string input, string format, IFormatProvider formatProvider, DateTimeStyles styles, out DateTimeOffset result)
413                 {
414                         try {
415                                 result = ParseExact (input, format, formatProvider, styles);
416                                 return true;
417                         } catch {
418                                 result = MinValue;
419                                 return false;
420                         }
421                 }
422
423                 public static bool TryParseExact (string input, string[] formats, IFormatProvider formatProvider, DateTimeStyles styles, out DateTimeOffset result)
424                 {
425                         try {
426                                 result = ParseExact (input, formats, formatProvider, styles);
427                                 return true;
428                         } catch {
429                                 result = MinValue;
430                                 return false;
431                         }
432                 }
433
434                 public DateTime Date {
435                         get { return DateTime.SpecifyKind (dt.Date, DateTimeKind.Unspecified); }
436                 }
437
438                 public DateTime DateTime {
439                         get { return DateTime.SpecifyKind (dt, DateTimeKind.Unspecified); }
440                 }
441
442                 public int Day {
443                         get { return dt.Day; }
444                 }
445
446                 public DayOfWeek DayOfWeek {
447                         get { return dt.DayOfWeek; }
448                 }
449
450                 public int DayOfYear {
451                         get { return dt.DayOfYear; }
452                 }
453
454                 public int Hour {
455                         get { return dt.Hour; }
456                 }
457
458                 public DateTime LocalDateTime {
459                         get { return UtcDateTime.ToLocalTime (); }
460                 }
461
462                 public int Millisecond {
463                         get { return dt.Millisecond; }
464                 }
465
466                 public int Minute {
467                         get { return dt.Minute; }
468                 }
469
470                 public int Month {
471                         get { return dt.Month; }
472                 }
473
474                 public static DateTimeOffset Now {
475                         get { return new DateTimeOffset (DateTime.Now);}
476                 }
477
478                 public TimeSpan Offset {
479                         get { return utc_offset; }      
480                 }
481
482                 public int Second {
483                         get { return dt.Second; }
484                 }
485
486                 public long Ticks {
487                         get { return dt.Ticks; }        
488                 }
489
490                 public TimeSpan TimeOfDay {
491                         get { return dt.TimeOfDay; }
492                 }
493
494                 public DateTime UtcDateTime {
495                         get { return DateTime.SpecifyKind (dt - utc_offset, DateTimeKind.Utc); }        
496                 }
497                 
498                 public static DateTimeOffset UtcNow {
499                         get { return new DateTimeOffset (DateTime.UtcNow); }
500                 }
501
502                 public long UtcTicks {
503                         get { return UtcDateTime.Ticks; }
504                 }
505
506                 public int Year {
507                         get { return dt.Year; }
508                 }
509         }
510 }
511 #endif