1
0

DateTimeOffset.cs 36 KB

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