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