1 // Copyright (c) Microsoft Open Technologies, Inc. All rights reserved. See License.txt in the project root for license information.
2 
3 #if NO_DATETIMEOFFSET
4 
5 /*BDS+*/
6 /*
7  * Copied from Dev11 source tree. Markers used to indicate changes.
8  * Search for BDS- and BDS+ to find additions and removals of code.
9  */
10 /*BDS+*/
11 
12 // ==++==
13 //
14 //   Copyright (c) Microsoft Corporation.  All rights reserved.
15 //
16 // ==--==
17 namespace System {
18 
19     using System;
20     using System.Threading;
21     using System.Globalization;
22     using System.Runtime.InteropServices;
23     using System.Runtime.CompilerServices;
24     using System.Runtime.Serialization;
25     using System.Security.Permissions;
26     /*BDS-*/ //using System.Diagnostics.Contracts;
27 
28     // DateTimeOffset is a value type that consists of a DateTime and a time zone offset,
29     // ie. how far away the time is from GMT. The DateTime is stored whole, and the offset
30     // is stored as an Int16 internally to save space, but presented as a TimeSpan.
31     //
32     // The range is constrained so that both the represented clock time and the represented
33     // UTC time fit within the boundaries of MaxValue. This gives it the same range as DateTime
34     // for actual UTC times, and a slightly constrained range on one end when an offset is
35     // present.
36     //
37     // This class should be substitutable for date time in most cases; so most operations
38     // effectively work on the clock time. However, the underlying UTC time is what counts
39     // for the purposes of identity, sorting and subtracting two instances.
40     //
41     //
42     // There are theoretically two date times stored, the UTC and the relative local representation
43     // or the 'clock' time. It actually does not matter which is stored in m_dateTime, so it is desirable
44     // for most methods to go through the helpers UtcDateTime and ClockDateTime both to abstract this
45     // out and for internal readability.
46 
47     [StructLayout(LayoutKind.Auto)]
48     [Serializable]
49     public struct DateTimeOffset : IComparable, /*BDS-*/ //IFormattable, ISerializable, IDeserializationCallback,
50                                    IComparable<DateTimeOffset>, IEquatable<DateTimeOffset> {
51 
52         // Constants
53         internal const Int64 MaxOffset = TimeSpan.TicksPerHour * 14;
54         internal const Int64 MinOffset = -MaxOffset;
55 
56         // Static Fields
57         /*BDS-*/ //public static readonly DateTimeOffset MinValue = new DateTimeOffset(DateTime.MinTicks, TimeSpan.Zero);
58         /*BDS+*/ public static readonly DateTimeOffset MinValue = new DateTimeOffset(DateTime.MinValue.Ticks, TimeSpan.Zero);
59         /*BDS-*/ //public static readonly DateTimeOffset MaxValue = new DateTimeOffset(DateTime.MaxTicks, TimeSpan.Zero);
60         /*BDS+*/ public static readonly DateTimeOffset MaxValue = new DateTimeOffset(DateTime.MaxValue.Ticks, TimeSpan.Zero);
61 
62         // Instance Fields
63         private DateTime m_dateTime;
64         private Int16 m_offsetMinutes;
65 
66         // Constructors
67 
68         // Constructs a DateTimeOffset from a tick count and offset
DateTimeOffsetSystem.DateTimeOffset69         public DateTimeOffset(long ticks, TimeSpan offset) {
70             m_offsetMinutes = ValidateOffset(offset);
71             // Let the DateTime constructor do the range checks
72             DateTime dateTime = new DateTime(ticks);
73             m_dateTime = ValidateDate(dateTime, offset);
74         }
75 
76         // Constructs a DateTimeOffset from a DateTime. For UTC and Unspecified kinds, creates a
77         // UTC instance with a zero offset. For local, extracts the local offset.
DateTimeOffsetSystem.DateTimeOffset78         public DateTimeOffset(DateTime dateTime) {
79             TimeSpan offset;
80             if (dateTime.Kind != DateTimeKind.Utc) {
81                 // Local and Unspecified are both treated as Local
82                 /*BDS-*/ //offset = TimeZoneInfo.Local.GetUtcOffset(dateTime, TimeZoneInfoOptions.NoThrowOnInvalidTime);
83                 /*BDS+*/ offset = TimeZone.CurrentTimeZone.GetUtcOffset(dateTime);
84             }
85             else {
86                 offset = new TimeSpan(0);
87             }
88             m_offsetMinutes = ValidateOffset(offset);
89             m_dateTime = ValidateDate(dateTime, offset);
90         }
91 
92         // Constructs a DateTimeOffset from a DateTime. And an offset. Always makes the clock time
93         // consistent with the DateTime. For Utc ensures the offset is zero. For local, ensures that
94         // the offset corresponds to the local.
DateTimeOffsetSystem.DateTimeOffset95         public DateTimeOffset(DateTime dateTime, TimeSpan offset) {
96             if (dateTime.Kind == DateTimeKind.Local) {
97                 /*BDS-*/ //if (offset != TimeZoneInfo.Local.GetUtcOffset(dateTime, TimeZoneInfoOptions.NoThrowOnInvalidTime)) {
98                 /*BDS+*/ if (offset != TimeZone.CurrentTimeZone.GetUtcOffset(dateTime)) {
99                     /*BDS-*/ //throw new ArgumentException(Environment.GetResourceString("Argument_OffsetLocalMismatch"), "offset");
100                     /*BDS+*/ throw new ArgumentException("OffsetLocalMismatch", "offset");
101                 }
102             }
103             else if (dateTime.Kind == DateTimeKind.Utc) {
104                 if (offset != TimeSpan.Zero) {
105                     /*BDS-*/ //throw new ArgumentException(Environment.GetResourceString("Argument_OffsetUtcMismatch"), "offset");
106                     /*BDS+*/ throw new ArgumentException("OffsetUtcMismatch", "offset");
107                 }
108             }
109             m_offsetMinutes = ValidateOffset(offset);
110             m_dateTime = ValidateDate(dateTime, offset);
111         }
112 
113         // Constructs a DateTimeOffset from a given year, month, day, hour,
114         // minute, second and offset.
DateTimeOffsetSystem.DateTimeOffset115         public DateTimeOffset(int year, int month, int day, int hour, int minute, int second, TimeSpan offset) {
116             m_offsetMinutes = ValidateOffset(offset);
117             m_dateTime = ValidateDate(new DateTime(year, month, day, hour, minute, second), offset);
118         }
119 
120         // Constructs a DateTimeOffset from a given year, month, day, hour,
121         // minute, second, millsecond and offset
DateTimeOffsetSystem.DateTimeOffset122         public DateTimeOffset(int year, int month, int day, int hour, int minute, int second, int millisecond, TimeSpan offset) {
123             m_offsetMinutes = ValidateOffset(offset);
124             m_dateTime = ValidateDate(new DateTime(year, month, day, hour, minute, second, millisecond), offset);
125         }
126 
127 
128         // Constructs a DateTimeOffset from a given year, month, day, hour,
129         // minute, second, millsecond, Calendar and offset.
DateTimeOffsetSystem.DateTimeOffset130         public DateTimeOffset(int year, int month, int day, int hour, int minute, int second, int millisecond, Calendar calendar, TimeSpan offset) {
131             m_offsetMinutes = ValidateOffset(offset);
132             m_dateTime = ValidateDate(new DateTime(year, month, day, hour, minute, second, millisecond, calendar), offset);
133         }
134 
135         // Returns a DateTimeOffset representing the current date and time. The
136         // resolution of the returned value depends on the system timer. For
137         // Windows NT 3.5 and later the timer resolution is approximately 10ms,
138         // for Windows NT 3.1 it is approximately 16ms, and for Windows 95 and 98
139         // it is approximately 55ms.
140         //
141         public static DateTimeOffset Now {
142             get {
143                 return new DateTimeOffset(DateTime.Now);
144             }
145         }
146 
147         public static DateTimeOffset UtcNow {
148             get {
149                 return new DateTimeOffset(DateTime.UtcNow);
150             }
151         }
152 
153         public DateTime DateTime {
154             get {
155                 return ClockDateTime;
156             }
157         }
158 
159         public DateTime UtcDateTime {
160             /*BDS-*/ //[Pure]
161             get {
162                 /*BDS-*/ //Contract.Ensures(Contract.Result<DateTime>().Kind == DateTimeKind.Utc);
163                 return DateTime.SpecifyKind(m_dateTime, DateTimeKind.Utc);
164             }
165         }
166 
167         public DateTime LocalDateTime {
168             /*BDS-*/ //[Pure]
169             get {
170                 /*BDS-*/ //Contract.Ensures(Contract.Result<DateTime>().Kind == DateTimeKind.Local);
171                 return UtcDateTime.ToLocalTime();
172             }
173         }
174 
175         // Adjust to a given offset with the same UTC time.  Can throw ArgumentException
176         //
ToOffsetSystem.DateTimeOffset177         public DateTimeOffset ToOffset(TimeSpan offset) {
178             return new DateTimeOffset((m_dateTime + offset).Ticks, offset);
179         }
180 
181 
182         // Instance Properties
183 
184         // The clock or visible time represented. This is just a wrapper around the internal date because this is
185         // the chosen storage mechanism. Going through this helper is good for readability and maintainability.
186         // This should be used for display but not identity.
187         private DateTime ClockDateTime {
188             get {
189                 return new DateTime((m_dateTime + Offset).Ticks, DateTimeKind.Unspecified);
190             }
191         }
192 
193         // Returns the date part of this DateTimeOffset. The resulting value
194         // corresponds to this DateTimeOffset with the time-of-day part set to
195         // zero (midnight).
196         //
197         public DateTime Date {
198             get {
199                 return ClockDateTime.Date;
200             }
201         }
202 
203         // Returns the day-of-month part of this DateTimeOffset. The returned
204         // value is an integer between 1 and 31.
205         //
206         public int Day {
207             get {
208                 /*BDS-*/ //Contract.Ensures(Contract.Result<int>() >= 1);
209                 /*BDS-*/ //Contract.Ensures(Contract.Result<int>() <= 31);
210                 return ClockDateTime.Day;
211             }
212         }
213 
214         // Returns the day-of-week part of this DateTimeOffset. The returned value
215         // is an integer between 0 and 6, where 0 indicates Sunday, 1 indicates
216         // Monday, 2 indicates Tuesday, 3 indicates Wednesday, 4 indicates
217         // Thursday, 5 indicates Friday, and 6 indicates Saturday.
218         //
219         public DayOfWeek DayOfWeek {
220             get {
221                 /*BDS-*/ //Contract.Ensures(Contract.Result<DayOfWeek>() >= DayOfWeek.Sunday);
222                 /*BDS-*/ //Contract.Ensures(Contract.Result<DayOfWeek>() <= DayOfWeek.Saturday);
223                 return ClockDateTime.DayOfWeek;
224             }
225         }
226 
227         // Returns the day-of-year part of this DateTimeOffset. The returned value
228         // is an integer between 1 and 366.
229         //
230         public int DayOfYear {
231             get {
232                 /*BDS-*/ //Contract.Ensures(Contract.Result<int>() >= 1);
233                 /*BDS-*/ //Contract.Ensures(Contract.Result<int>() <= 366);  // leap year
234                 return ClockDateTime.DayOfYear;
235             }
236         }
237 
238         // Returns the hour part of this DateTimeOffset. The returned value is an
239         // integer between 0 and 23.
240         //
241         public int Hour {
242             get {
243                 /*BDS-*/ //Contract.Ensures(Contract.Result<int>() >= 0);
244                 /*BDS-*/ //Contract.Ensures(Contract.Result<int>() < 24);
245                 return ClockDateTime.Hour;
246             }
247         }
248 
249 
250         // Returns the millisecond part of this DateTimeOffset. The returned value
251         // is an integer between 0 and 999.
252         //
253         public int Millisecond {
254             get {
255                 /*BDS-*/ //Contract.Ensures(Contract.Result<int>() >= 0);
256                 /*BDS-*/ //Contract.Ensures(Contract.Result<int>() < 1000);
257                 return ClockDateTime.Millisecond;
258             }
259         }
260 
261         // Returns the minute part of this DateTimeOffset. The returned value is
262         // an integer between 0 and 59.
263         //
264         public int Minute {
265             get {
266                 /*BDS-*/ //Contract.Ensures(Contract.Result<int>() >= 0);
267                 /*BDS-*/ //Contract.Ensures(Contract.Result<int>() < 60);
268                 return ClockDateTime.Minute;
269             }
270         }
271 
272         // Returns the month part of this DateTimeOffset. The returned value is an
273         // integer between 1 and 12.
274         //
275         public int Month {
276             get {
277                 /*BDS-*/ //Contract.Ensures(Contract.Result<int>() >= 1);
278                 return ClockDateTime.Month;
279             }
280         }
281 
282         public TimeSpan Offset {
283             get {
284                 return new TimeSpan(0, m_offsetMinutes, 0);
285             }
286         }
287 
288         // Returns the second part of this DateTimeOffset. The returned value is
289         // an integer between 0 and 59.
290         //
291         public int Second {
292             get {
293                 /*BDS-*/ //Contract.Ensures(Contract.Result<int>() >= 0);
294                 /*BDS-*/ //Contract.Ensures(Contract.Result<int>() < 60);
295                 return ClockDateTime.Second;
296             }
297         }
298 
299         // Returns the tick count for this DateTimeOffset. The returned value is
300         // the number of 100-nanosecond intervals that have elapsed since 1/1/0001
301         // 12:00am.
302         //
303         public long Ticks {
304             get {
305                 return ClockDateTime.Ticks;
306             }
307         }
308 
309         public long UtcTicks {
310             get {
311                 return UtcDateTime.Ticks;
312             }
313         }
314 
315         // Returns the time-of-day part of this DateTimeOffset. The returned value
316         // is a TimeSpan that indicates the time elapsed since midnight.
317         //
318         public TimeSpan TimeOfDay {
319             get {
320                 return ClockDateTime.TimeOfDay;
321             }
322         }
323 
324         // Returns the year part of this DateTimeOffset. The returned value is an
325         // integer between 1 and 9999.
326         //
327         public int Year {
328             get {
329                 /*BDS-*/ //Contract.Ensures(Contract.Result<int>() >= 1 && Contract.Result<int>() <= 9999);
330                 return ClockDateTime.Year;
331             }
332         }
333 
334         // Returns the DateTimeOffset resulting from adding the given
335         // TimeSpan to this DateTimeOffset.
336         //
AddSystem.DateTimeOffset337         public DateTimeOffset Add(TimeSpan timeSpan) {
338             return new DateTimeOffset(ClockDateTime.Add(timeSpan), Offset);
339         }
340 
341         // Returns the DateTimeOffset resulting from adding a fractional number of
342         // days to this DateTimeOffset. The result is computed by rounding the
343         // fractional number of days given by value to the nearest
344         // millisecond, and adding that interval to this DateTimeOffset. The
345         // value argument is permitted to be negative.
346         //
AddDaysSystem.DateTimeOffset347         public DateTimeOffset AddDays(double days) {
348             return new DateTimeOffset(ClockDateTime.AddDays(days), Offset);
349         }
350 
351         // Returns the DateTimeOffset resulting from adding a fractional number of
352         // hours to this DateTimeOffset. The result is computed by rounding the
353         // fractional number of hours given by value to the nearest
354         // millisecond, and adding that interval to this DateTimeOffset. The
355         // value argument is permitted to be negative.
356         //
AddHoursSystem.DateTimeOffset357         public DateTimeOffset AddHours(double hours) {
358             return new DateTimeOffset(ClockDateTime.AddHours(hours), Offset);
359         }
360 
361         // Returns the DateTimeOffset resulting from the given number of
362         // milliseconds to this DateTimeOffset. The result is computed by rounding
363         // the number of milliseconds given by value to the nearest integer,
364         // and adding that interval to this DateTimeOffset. The value
365         // argument is permitted to be negative.
366         //
AddMillisecondsSystem.DateTimeOffset367         public DateTimeOffset AddMilliseconds(double milliseconds) {
368             return new DateTimeOffset(ClockDateTime.AddMilliseconds(milliseconds), Offset);
369         }
370 
371         // Returns the DateTimeOffset resulting from adding a fractional number of
372         // minutes to this DateTimeOffset. The result is computed by rounding the
373         // fractional number of minutes given by value to the nearest
374         // millisecond, and adding that interval to this DateTimeOffset. The
375         // value argument is permitted to be negative.
376         //
AddMinutesSystem.DateTimeOffset377         public DateTimeOffset AddMinutes(double minutes) {
378             return new DateTimeOffset(ClockDateTime.AddMinutes(minutes), Offset);
379         }
380 
AddMonthsSystem.DateTimeOffset381         public DateTimeOffset AddMonths(int months) {
382             return new DateTimeOffset(ClockDateTime.AddMonths(months), Offset);
383         }
384 
385         // Returns the DateTimeOffset resulting from adding a fractional number of
386         // seconds to this DateTimeOffset. The result is computed by rounding the
387         // fractional number of seconds given by value to the nearest
388         // millisecond, and adding that interval to this DateTimeOffset. The
389         // value argument is permitted to be negative.
390         //
AddSecondsSystem.DateTimeOffset391         public DateTimeOffset AddSeconds(double seconds) {
392             return new DateTimeOffset(ClockDateTime.AddSeconds(seconds), Offset);
393         }
394 
395         // Returns the DateTimeOffset resulting from adding the given number of
396         // 100-nanosecond ticks to this DateTimeOffset. The value argument
397         // is permitted to be negative.
398         //
AddTicksSystem.DateTimeOffset399         public DateTimeOffset AddTicks(long ticks) {
400             return new DateTimeOffset(ClockDateTime.AddTicks(ticks), Offset);
401         }
402 
403         // Returns the DateTimeOffset resulting from adding the given number of
404         // years to this DateTimeOffset. The result is computed by incrementing
405         // (or decrementing) the year part of this DateTimeOffset by value
406         // years. If the month and day of this DateTimeOffset is 2/29, and if the
407         // resulting year is not a leap year, the month and day of the resulting
408         // DateTimeOffset becomes 2/28. Otherwise, the month, day, and time-of-day
409         // parts of the result are the same as those of this DateTimeOffset.
410         //
AddYearsSystem.DateTimeOffset411         public DateTimeOffset AddYears(int years) {
412             return new DateTimeOffset(ClockDateTime.AddYears(years), Offset);
413         }
414 
415         // Compares two DateTimeOffset values, returning an integer that indicates
416         // their relationship.
417         //
CompareSystem.DateTimeOffset418         public static int Compare(DateTimeOffset first, DateTimeOffset second) {
419             return DateTime.Compare(first.UtcDateTime, second.UtcDateTime);
420         }
421 
422         // Compares this DateTimeOffset to a given object. This method provides an
423         // implementation of the IComparable interface. The object
424         // argument must be another DateTimeOffset, or otherwise an exception
425         // occurs.  Null is considered less than any instance.
426         //
IComparable.CompareToSystem.DateTimeOffset427         int IComparable.CompareTo(Object obj) {
428             if (obj == null) return 1;
429             if (!(obj is DateTimeOffset)) {
430                 /*BDS-*/ //throw new ArgumentException(Environment.GetResourceString("Arg_MustBeDateTimeOffset"));
431                 /*BDS+*/ throw new ArgumentException("MustBeDateTimeOffset");
432             }
433 
434             DateTime objUtc = ((DateTimeOffset)obj).UtcDateTime;
435             DateTime utc = UtcDateTime;
436             if (utc > objUtc) return 1;
437             if (utc < objUtc) return -1;
438             return 0;
439         }
440 
CompareToSystem.DateTimeOffset441         public int CompareTo(DateTimeOffset other) {
442             DateTime otherUtc = other.UtcDateTime;
443             DateTime utc = UtcDateTime;
444             if (utc > otherUtc) return 1;
445             if (utc < otherUtc) return -1;
446             return 0;
447         }
448 
449 
450         // Checks if this DateTimeOffset is equal to a given object. Returns
451         // true if the given object is a boxed DateTimeOffset and its value
452         // is equal to the value of this DateTimeOffset. Returns false
453         // otherwise.
454         //
EqualsSystem.DateTimeOffset455         public override bool Equals(Object obj) {
456             if (obj is DateTimeOffset) {
457                 return UtcDateTime.Equals(((DateTimeOffset)obj).UtcDateTime);
458             }
459             return false;
460         }
461 
EqualsSystem.DateTimeOffset462         public bool Equals(DateTimeOffset other) {
463             return UtcDateTime.Equals(other.UtcDateTime);
464         }
465 
EqualsExactSystem.DateTimeOffset466         public bool EqualsExact(DateTimeOffset other) {
467             //
468             // returns true when the ClockDateTime, Kind, and Offset match
469             //
470             // currently the Kind should always be Unspecified, but there is always the possibility that a future version
471             // of DateTimeOffset overloads the Kind field
472             //
473             return (ClockDateTime == other.ClockDateTime && Offset == other.Offset && ClockDateTime.Kind == other.ClockDateTime.Kind);
474         }
475 
476         // Compares two DateTimeOffset values for equality. Returns true if
477         // the two DateTimeOffset values are equal, or false if they are
478         // not equal.
479         //
EqualsSystem.DateTimeOffset480         public static bool Equals(DateTimeOffset first, DateTimeOffset second) {
481             return DateTime.Equals(first.UtcDateTime, second.UtcDateTime);
482         }
483 
484         // Creates a DateTimeOffset from a Windows filetime. A Windows filetime is
485         // a long representing the date and time as the number of
486         // 100-nanosecond intervals that have elapsed since 1/1/1601 12:00am.
487         //
FromFileTimeSystem.DateTimeOffset488         public static DateTimeOffset FromFileTime(long fileTime) {
489             return new DateTimeOffset(DateTime.FromFileTime(fileTime));
490         }
491 
492 
493         // ----- SECTION: private serialization instance methods  ----------------*
494 
495 #if FEATURE_SERIALIZATION
IDeserializationCallback.OnDeserializationSystem.DateTimeOffset496         void IDeserializationCallback.OnDeserialization(Object sender) {
497             try {
498                 m_offsetMinutes = ValidateOffset(Offset);
499                 m_dateTime      = ValidateDate(ClockDateTime, Offset);
500             }
501             catch (ArgumentException e) {
502                 throw new SerializationException(Environment.GetResourceString("Serialization_InvalidData"), e);
503             }
504         }
505 
506 
507         [System.Security.SecurityCritical]  // auto-generated_required
ISerializable.GetObjectDataSystem.DateTimeOffset508         void ISerializable.GetObjectData(SerializationInfo info, StreamingContext context) {
509             if (info == null) {
510                 throw new ArgumentNullException("info");
511             }
512 
513             Contract.EndContractBlock();
514 
515             info.AddValue("DateTime", m_dateTime);
516             info.AddValue("OffsetMinutes", m_offsetMinutes);
517         }
518 
519 
DateTimeOffsetSystem.DateTimeOffset520         DateTimeOffset(SerializationInfo info, StreamingContext context) {
521             if (info == null) {
522                 throw new ArgumentNullException("info");
523             }
524 
525             m_dateTime      = (DateTime)info.GetValue("DateTime", typeof(DateTime));
526             m_offsetMinutes = (Int16)info.GetValue("OffsetMinutes", typeof(Int16));
527         }
528 #endif
529 
530         // Returns the hash code for this DateTimeOffset.
531         //
GetHashCodeSystem.DateTimeOffset532         public override int GetHashCode() {
533             return UtcDateTime.GetHashCode();
534         }
535 
536 /*BDS-*/ /*
537         // Constructs a DateTimeOffset from a string. The string must specify a
538         // date and optionally a time in a culture-specific or universal format.
539         // Leading and trailing whitespace characters are allowed.
540         //
541         public static DateTimeOffset Parse(String input) {
542             TimeSpan offset;
543             DateTime dateResult = DateTimeParse.Parse(input,
544                                                       DateTimeFormatInfo.CurrentInfo,
545                                                       DateTimeStyles.None,
546                                                       out offset);
547             return new DateTimeOffset(dateResult.Ticks, offset);
548         }
549 
550         // Constructs a DateTimeOffset from a string. The string must specify a
551         // date and optionally a time in a culture-specific or universal format.
552         // Leading and trailing whitespace characters are allowed.
553         //
554         public static DateTimeOffset Parse(String input, IFormatProvider formatProvider) {
555             return Parse(input, formatProvider, DateTimeStyles.None);
556         }
557 
558         public static DateTimeOffset Parse(String input, IFormatProvider formatProvider, DateTimeStyles styles) {
559             styles = ValidateStyles(styles, "styles");
560             TimeSpan offset;
561             DateTime dateResult = DateTimeParse.Parse(input,
562                                                       DateTimeFormatInfo.GetInstance(formatProvider),
563                                                       styles,
564                                                       out offset);
565             return new DateTimeOffset(dateResult.Ticks, offset);
566         }
567 
568         // Constructs a DateTimeOffset from a string. The string must specify a
569         // date and optionally a time in a culture-specific or universal format.
570         // Leading and trailing whitespace characters are allowed.
571         //
572         public static DateTimeOffset ParseExact(String input, String format, IFormatProvider formatProvider) {
573             return ParseExact(input, format, formatProvider, DateTimeStyles.None);
574         }
575 
576         // Constructs a DateTimeOffset from a string. The string must specify a
577         // date and optionally a time in a culture-specific or universal format.
578         // Leading and trailing whitespace characters are allowed.
579         //
580         public static DateTimeOffset ParseExact(String input, String format, IFormatProvider formatProvider, DateTimeStyles styles) {
581             styles = ValidateStyles(styles, "styles");
582             TimeSpan offset;
583             DateTime dateResult = DateTimeParse.ParseExact(input,
584                                                            format,
585                                                            DateTimeFormatInfo.GetInstance(formatProvider),
586                                                            styles,
587                                                            out offset);
588             return new DateTimeOffset(dateResult.Ticks, offset);
589         }
590 
591         public static DateTimeOffset ParseExact(String input, String[] formats, IFormatProvider formatProvider, DateTimeStyles styles) {
592             styles = ValidateStyles(styles, "styles");
593             TimeSpan offset;
594             DateTime dateResult = DateTimeParse.ParseExactMultiple(input,
595                                                                    formats,
596                                                                    DateTimeFormatInfo.GetInstance(formatProvider),
597                                                                    styles,
598                                                                    out offset);
599             return new DateTimeOffset(dateResult.Ticks, offset);
600         }
601 */ /*BDS-*/
602 
SubtractSystem.DateTimeOffset603         public TimeSpan Subtract(DateTimeOffset value) {
604             return UtcDateTime.Subtract(value.UtcDateTime);
605         }
606 
SubtractSystem.DateTimeOffset607         public DateTimeOffset Subtract(TimeSpan value) {
608             return new DateTimeOffset(ClockDateTime.Subtract(value), Offset);
609         }
610 
611 
ToFileTimeSystem.DateTimeOffset612         public long ToFileTime() {
613             return UtcDateTime.ToFileTime();
614         }
615 
ToLocalTimeSystem.DateTimeOffset616         public DateTimeOffset ToLocalTime() {
617             return new DateTimeOffset(UtcDateTime.ToLocalTime());
618         }
619 
620 /*BDS-*/ /*
621         public override String ToString() {
622             Contract.Ensures(Contract.Result<String>() != null);
623             return DateTimeFormat.Format(ClockDateTime, null, DateTimeFormatInfo.CurrentInfo, Offset);
624         }
625 
626         public String ToString(String format) {
627             Contract.Ensures(Contract.Result<String>() != null);
628             return DateTimeFormat.Format(ClockDateTime, format, DateTimeFormatInfo.CurrentInfo, Offset);
629         }
630 
631         public String ToString(IFormatProvider formatProvider) {
632             Contract.Ensures(Contract.Result<String>() != null);
633             return DateTimeFormat.Format(ClockDateTime, null, DateTimeFormatInfo.GetInstance(formatProvider), Offset);
634         }
635 
636         public String ToString(String format, IFormatProvider formatProvider) {
637             Contract.Ensures(Contract.Result<String>() != null);
638             return DateTimeFormat.Format(ClockDateTime, format, DateTimeFormatInfo.GetInstance(formatProvider), Offset);
639         }
640 */ /*BDS-*/
641 
ToUniversalTimeSystem.DateTimeOffset642         public DateTimeOffset ToUniversalTime() {
643             return new DateTimeOffset(UtcDateTime);
644         }
645 
646 /*BDS-*/ /*
647         public static Boolean TryParse(String input, out DateTimeOffset result) {
648             TimeSpan offset;
649             DateTime dateResult;
650             Boolean parsed = DateTimeParse.TryParse(input,
651                                                     DateTimeFormatInfo.CurrentInfo,
652                                                     DateTimeStyles.None,
653                                                     out dateResult,
654                                                     out offset);
655             result = new DateTimeOffset(dateResult.Ticks, offset);
656             return parsed;
657         }
658 
659         public static Boolean TryParse(String input, IFormatProvider formatProvider, DateTimeStyles styles, out DateTimeOffset result) {
660             styles = ValidateStyles(styles, "styles");
661             TimeSpan offset;
662             DateTime dateResult;
663             Boolean parsed = DateTimeParse.TryParse(input,
664                                                     DateTimeFormatInfo.GetInstance(formatProvider),
665                                                     styles,
666                                                     out dateResult,
667                                                     out offset);
668             result = new DateTimeOffset(dateResult.Ticks, offset);
669             return parsed;
670         }
671 
672         public static Boolean TryParseExact(String input, String format, IFormatProvider formatProvider, DateTimeStyles styles,
673                                             out DateTimeOffset result) {
674             styles = ValidateStyles(styles, "styles");
675             TimeSpan offset;
676             DateTime dateResult;
677             Boolean parsed = DateTimeParse.TryParseExact(input,
678                                                          format,
679                                                          DateTimeFormatInfo.GetInstance(formatProvider),
680                                                          styles,
681                                                          out dateResult,
682                                                          out offset);
683             result = new DateTimeOffset(dateResult.Ticks, offset);
684             return parsed;
685         }
686 
687         public static Boolean TryParseExact(String input, String[] formats, IFormatProvider formatProvider, DateTimeStyles styles,
688                                             out DateTimeOffset result) {
689             styles = ValidateStyles(styles, "styles");
690             TimeSpan offset;
691             DateTime dateResult;
692             Boolean parsed = DateTimeParse.TryParseExactMultiple(input,
693                                                                  formats,
694                                                                  DateTimeFormatInfo.GetInstance(formatProvider),
695                                                                  styles,
696                                                                  out dateResult,
697                                                                  out offset);
698             result = new DateTimeOffset(dateResult.Ticks, offset);
699             return parsed;
700         }
701 */ /*BDS-*/
702 
703         // Ensures the TimeSpan is valid to go in a DateTimeOffset.
ValidateOffsetSystem.DateTimeOffset704         private static Int16 ValidateOffset(TimeSpan offset) {
705             Int64 ticks = offset.Ticks;
706             if (ticks % TimeSpan.TicksPerMinute != 0) {
707                 /*BDS-*/ //throw new ArgumentException(Environment.GetResourceString("Argument_OffsetPrecision"), "offset");
708                 /*BDS+*/ throw new ArgumentException("OffsetPrecision", "offset");
709             }
710             if (ticks < MinOffset || ticks > MaxOffset) {
711                 /*BDS-*/ //throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("Argument_OffsetOutOfRange"));
712                 /*BDS+*/ throw new ArgumentOutOfRangeException("offset", "OffsetOutOfRange");
713             }
714             return (Int16)(offset.Ticks / TimeSpan.TicksPerMinute);
715         }
716 
717         // Ensures that the time and offset are in range.
ValidateDateSystem.DateTimeOffset718         private static DateTime ValidateDate(DateTime dateTime, TimeSpan offset) {
719             // The key validation is that both the UTC and clock times fit. The clock time is validated
720             // by the DateTime constructor.
721             /*BDS-*/ //Contract.Assert(offset.Ticks >= MinOffset && offset.Ticks <= MaxOffset, "Offset not validated.");
722             // This operation cannot overflow because offset should have already been validated to be within
723             // 14 hours and the DateTime instance is more than that distance from the boundaries of Int64.
724             Int64 utcTicks = dateTime.Ticks - offset.Ticks;
725             /*BDS-*/ //if (utcTicks < DateTime.MinTicks || utcTicks > DateTime.MaxTicks) {
726             /*BDS+*/ if (utcTicks < DateTime.MinValue.Ticks || utcTicks > DateTime.MaxValue.Ticks) {
727                 /*BDS-*/ //throw new ArgumentOutOfRangeException("offset", Environment.GetResourceString("Argument_UTCOutOfRange"));
728                 /*BDS+*/ throw new ArgumentOutOfRangeException("offset", "UTCOutOfRange");
729             }
730             // make sure the Kind is set to Unspecified
731             //
732             return new DateTime(utcTicks, DateTimeKind.Unspecified);
733         }
734 
ValidateStylesSystem.DateTimeOffset735         private static DateTimeStyles ValidateStyles(DateTimeStyles style, String parameterName) {
736 /*BDS-*/ /*
737             if ((style & DateTimeFormatInfo.InvalidDateTimeStyles) != 0) {
738                 throw new ArgumentException(Environment.GetResourceString("Argument_InvalidDateTimeStyles"), parameterName);
739             }
740 */ /*BDS-*/
741             if (((style & (DateTimeStyles.AssumeLocal)) != 0) && ((style & (DateTimeStyles.AssumeUniversal)) != 0)) {
742                 /*BDS-*/ //throw new ArgumentException(Environment.GetResourceString("Argument_ConflictingDateTimeStyles"), parameterName);
743                 /*BDS+*/ throw new ArgumentException("ConflictingDateTimeStyles", parameterName);
744             }
745             if ((style & DateTimeStyles.NoCurrentDateDefault) != 0) {
746                 /*BDS-*/ //throw new ArgumentException(Environment.GetResourceString("Argument_DateTimeOffsetInvalidDateTimeStyles"), parameterName);
747                 /*BDS+*/ throw new ArgumentException("DateTimeOffsetInvalidDateTimeStyles", parameterName);
748             }
749 
750             /*BDS-*/ //Contract.EndContractBlock();
751             // RoundtripKind does not make sense for DateTimeOffset; ignore this flag for backward compatability with DateTime
752             style &= ~DateTimeStyles.RoundtripKind;
753 
754             // AssumeLocal is also ignored as that is what we do by default with DateTimeOffset.Parse
755             style &= ~DateTimeStyles.AssumeLocal;
756 
757             return style;
758         }
759 
760         // Operators
761 
operator DateTimeOffsetSystem.DateTimeOffset762         public static implicit operator DateTimeOffset (DateTime dateTime) {
763             return new DateTimeOffset(dateTime);
764         }
765 
operator +System.DateTimeOffset766         public static DateTimeOffset operator +(DateTimeOffset dateTimeOffset, TimeSpan timeSpan) {
767             return new DateTimeOffset(dateTimeOffset.ClockDateTime + timeSpan, dateTimeOffset.Offset);
768         }
769 
770 
operator -System.DateTimeOffset771         public static DateTimeOffset operator -(DateTimeOffset dateTimeOffset, TimeSpan timeSpan) {
772             return new DateTimeOffset(dateTimeOffset.ClockDateTime - timeSpan, dateTimeOffset.Offset);
773         }
774 
operator -System.DateTimeOffset775         public static TimeSpan operator -(DateTimeOffset left, DateTimeOffset right) {
776             return left.UtcDateTime - right.UtcDateTime;
777         }
778 
operator ==System.DateTimeOffset779         public static bool operator ==(DateTimeOffset left, DateTimeOffset right) {
780             return left.UtcDateTime == right.UtcDateTime;
781         }
782 
operator !=System.DateTimeOffset783         public static bool operator !=(DateTimeOffset left, DateTimeOffset right) {
784             return left.UtcDateTime != right.UtcDateTime;
785         }
786 
operator <System.DateTimeOffset787         public static bool operator <(DateTimeOffset left, DateTimeOffset right) {
788             return left.UtcDateTime < right.UtcDateTime;
789         }
790 
operator <=System.DateTimeOffset791         public static bool operator <=(DateTimeOffset left, DateTimeOffset right) {
792             return left.UtcDateTime <= right.UtcDateTime;
793         }
794 
operator >System.DateTimeOffset795         public static bool operator >(DateTimeOffset left, DateTimeOffset right) {
796             return left.UtcDateTime > right.UtcDateTime;
797         }
798 
operator >=System.DateTimeOffset799         public static bool operator >=(DateTimeOffset left, DateTimeOffset right) {
800             return left.UtcDateTime >= right.UtcDateTime;
801         }
802 
803     }
804 }
805 #endif