DateTimeOffset.cs 36 KB

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