/std/datetime.d

http://github.com/AlexeyProkhin/phobos · D · 1381 lines · 750 code · 200 blank · 431 comment · 37 complexity · 71732d420af91f62c6c6187e0ff3bb79 MD5 · raw file

Large files are truncated click here to view the full file

  1. //Written in the D programming language
  2. /++
  3. Module containing Date/Time functionality.
  4. This module provides:
  5. $(UL
  6. $(LI Types to represent points in time: $(D SysTime), $(D Date),
  7. $(D TimeOfDay), and $(D DateTime).)
  8. $(LI Types to represent durations of time.)
  9. $(LI Types to represent intervals of time.)
  10. $(LI Types to represent ranges over intervals of time.)
  11. $(LI Types to represent time zones (used by $(D SysTime)).)
  12. $(LI A platform-independent, high precision stopwatch type:
  13. $(D StopWatch))
  14. $(LI Benchmarking functions.)
  15. $(LI Various helper functions.)
  16. )
  17. Three of the main concepts used in this module are time points, time
  18. durations, and time intervals.
  19. A time point is a specific point in time. e.g. January 5th, 2010
  20. or 5:00.
  21. A time duration is a length of time with units. e.g. 5 days or 231 seconds.
  22. A time interval indicates a period of time associated with a fixed point in
  23. time. So, it is either two time points associated with each other,
  24. indicating the time starting at the first point up to, but not including,
  25. the second point - e.g. [January 5th, 2010 - March 10th, 2010$(RPAREN) - or
  26. it is a time point and a time duration associated with one another. e.g.
  27. January 5th, 2010 and 5 days, indicating [January 5th, 2010 -
  28. January 10th, 2010$(RPAREN).
  29. Various arithmetic operations are supported between time points and
  30. durations (e.g. the difference between two time points is a time duration),
  31. and ranges can be gotten from time intervals, so range-based operations may
  32. be done on a series of time points.
  33. The types that the typical user is most likely to be interested in are
  34. $(D Date) (if they want dates but don't care about time), $(D DateTime)
  35. (if they want dates and times but don't care about time zones), $(D SysTime)
  36. (if they want the date and time from the OS and/or do care about time
  37. zones), and StopWatch (a platform-independent, high precision stop watch).
  38. $(D Date) and $(D DateTime) are optimized for calendar-based operations,
  39. while $(D SysTime) is designed for dealing with time from the OS. Check out
  40. their specific documentation for more details.
  41. To get the current time, use $(D Clock.currTime). It will return the current
  42. time as a $(D SysTime). If you want to print it, $(D toString) is
  43. sufficient, but if you use $(D toISOString), $(D toISOExtendedString), or
  44. $(D toSimpleString), you can use the corresponding $(D fromISOString),
  45. $(D fromISOExtendedString), or $(D fromISOExtendedString) to create a
  46. $(D SysTime) from the string.
  47. --------------------
  48. auto currentTime = Clock.currTime();
  49. auto timeString = currentTime.toISOExtendedString();
  50. auto restoredTime = SysTime.fromISOExtendedString(timeString);
  51. --------------------
  52. Various functions take a string (or strings) to represent a unit of time
  53. (e.g. $(D convert!("days", "hours")(numDays))). The valid strings to use
  54. with such functions are $(D "years"), $(D "months"), $(D "weeks"),
  55. $(D "days"), $(D "hours"), $(D "minutes"), $(D "seconds"),
  56. $(D "msecs") (milliseconds), $(D "usecs") (microseconds),
  57. $(D "hnsecs") (hecto-nanoseconds - i.e. 100 ns) or some subset thereof.
  58. There are a few functions in core.time which take $(D "nsecs"), but because
  59. nothing in std.datetime has precision greater than hnsecs, and very little
  60. in core.time does, no functions in std.datetime accept $(D "nsecs").
  61. Note:
  62. core.time is publicly imported by std.datetime, so if you're using
  63. std.datetime, you don't need to import core.time. Also,
  64. $(D DateTimeException) is an alias for core.time's $(D TimeException),
  65. so you don't need to worry about core.time functions and std.datetime
  66. functions throwing different exception types (except in the rare case
  67. that they throw something other than $(D TimeException) or
  68. $(D DateTimeException)).
  69. See_Also:
  70. $(WEB en.wikipedia.org/wiki/ISO_8601, ISO 8601)
  71. $(WEB en.wikipedia.org/wiki/Tz_database, Wikipedia entry on TZ Database)
  72. $(WEB en.wikipedia.org/wiki/List_of_tz_database_time_zones,
  73. List of Time Zones)
  74. Copyright: Copyright 2010 - 2011
  75. License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
  76. Authors: Jonathan M Davis and Kato Shoichi
  77. Source: $(PHOBOSSRC std/_datetime.d)
  78. +/
  79. module std.datetime;
  80. public import core.time;
  81. import core.exception;
  82. import core.stdc.time;
  83. import std.array;
  84. import std.algorithm;
  85. import std.conv;
  86. import std.ctype;
  87. import std.exception;
  88. import std.file;
  89. import std.functional;
  90. import std.math;
  91. import std.metastrings;
  92. import std.path;
  93. import std.range;
  94. import std.stdio;
  95. import std.string;
  96. import std.system;
  97. import std.traits;
  98. version(Windows)
  99. {
  100. import core.sys.windows.windows;
  101. import std.c.windows.winsock;
  102. //For system call to access the registry.
  103. pragma(lib, "advapi32.lib");
  104. }
  105. else version(Posix)
  106. {
  107. import core.sys.posix.arpa.inet;
  108. import core.sys.posix.stdlib;
  109. import core.sys.posix.time;
  110. import core.sys.posix.sys.time;
  111. //We need to disable many tests because building all of Phobos
  112. //with all of std.datetime's unit tests enables currently causes
  113. //dmd to run out of memory.
  114. //Regardless of that, however, it's also useful to be able to
  115. //easily turn the tests on and off.
  116. version = testStdDateTime;
  117. }
  118. //We should enable at least _some_ of the tests on Windows - especially
  119. //the Windows-specific tests.
  120. version = enableWindowsTest;
  121. version(unittest)
  122. {
  123. import std.c.string;
  124. import std.stdio;
  125. }
  126. version(unittest)
  127. {
  128. bool localTimeIsUTC;
  129. unittest
  130. {
  131. immutable unixTime = core.stdc.time.time(null);
  132. tm* local = core.stdc.time.localtime(&unixTime);
  133. tm* utc = core.stdc.time.gmtime(&unixTime);
  134. localTimeIsUTC = local.tm_sec == utc.tm_sec &&
  135. local.tm_min == utc.tm_min &&
  136. local.tm_hour == utc.tm_hour &&
  137. local.tm_mday == utc.tm_mday &&
  138. local.tm_mon == utc.tm_mon &&
  139. local.tm_year == utc.tm_year &&
  140. local.tm_wday == utc.tm_wday &&
  141. local.tm_yday == utc.tm_yday &&
  142. local.tm_isdst == utc.tm_isdst;
  143. }
  144. }
  145. alias std.string.indexOf indexOf;
  146. unittest
  147. {
  148. //Verify module example.
  149. auto currentTime = Clock.currTime();
  150. auto timeString = currentTime.toISOExtendedString();
  151. auto restoredTime = SysTime.fromISOExtendedString(timeString);
  152. }
  153. //Note: There various functions which void as their return type and ref of the
  154. // struct type which they're in as a commented out return type. Ideally,
  155. // they would return the ref, but there are several dmd bugs which prevent
  156. // that, relating to both ref and invariants. So, I've left the ref return
  157. // types commented out with the idea that those functions can be made to
  158. // return a ref to this once those bugs have been fixed.
  159. //==============================================================================
  160. // Section with public enums and constants.
  161. //==============================================================================
  162. /++
  163. Represents the 12 months of the Gregorian year (January is 1).
  164. +/
  165. enum Month : ubyte { jan = 1, ///
  166. feb, ///
  167. mar, ///
  168. apr, ///
  169. may, ///
  170. jun, ///
  171. jul, ///
  172. aug, ///
  173. sep, ///
  174. oct, ///
  175. nov, ///
  176. dec ///
  177. }
  178. /++
  179. Represents the 7 days of the Gregorian week (Sunday is 0).
  180. +/
  181. enum DayOfWeek : ubyte { sun = 0, ///
  182. mon, ///
  183. tue, ///
  184. wed, ///
  185. thu, ///
  186. fri, ///
  187. sat ///
  188. }
  189. /++
  190. In some date calculations, adding months or years can cause the date to fall
  191. on a day of the month which is not valid (e.g. February 29th 2001 or
  192. June 31st 2000). If overflow is allowed (as is the default), then the month
  193. will be incremented accordingly (so, February 29th 2001 would become
  194. March 1st 2001, and June 31st 2000 would become July 1st 2000). If overflow
  195. is not allowed, then the day will be adjusted to the last valid day in that
  196. month (so, February 29th 2001 would become February 28th 2001 and
  197. June 31st 2000 would become June 30th 2000).
  198. AllowDayOverflow only applies to calculations involving months or years.
  199. +/
  200. enum AllowDayOverflow
  201. {
  202. /// No, don't allow day overflow.
  203. no,
  204. /// Yes, allow day overflow.
  205. yes
  206. }
  207. /++
  208. Indicates a direction in time. One example of its use is $(D Interval)'s
  209. $(D expand) function which uses it to indicate whether the interval should
  210. be expanded backwards (into the past), forwards (into the future), or both.
  211. +/
  212. enum Direction
  213. {
  214. /// Backward.
  215. bwd,
  216. /// Forward.
  217. fwd,
  218. /// Both backward and forward.
  219. both
  220. }
  221. /++
  222. Used to indicate whether $(D popFront) should be called immediately upon
  223. creating a range. The idea is that for some functions used to generate a
  224. range for an interval, $(D front) is not necessarily a time point which
  225. would ever be generated by the range, and if you want the first time point
  226. in the range to match what the function generates, then you use
  227. $(D PopFirst.yes) to indicate that the range should have $(D popFront)
  228. called on it before the range is returned so that $(D front) is a time point
  229. which the function would generate.
  230. For instance, if the function used to generate a range of time points
  231. generated successive Easters (i.e. you're iterating over all of the Easters
  232. within the interval), the initial date probably isn't an Easter. By using
  233. $(D PopFirst.yes), you would be telling the function which returned the
  234. range that you wanted $(D popFront) to be called so that front would then be
  235. an Easter - the next one generated by the function (which if you were
  236. iterating forward, would be the Easter following the original $(D front),
  237. while if you were iterating backward, it would be the Easter prior to the
  238. original $(D front)). If $(D PopFirst.no) were used, then $(D front) would
  239. remain the original time point and it would not necessarily be a time point
  240. which would be generated by the range-generating function (which in many
  241. cases is exactly what you
  242. want - e.g. if you were iterating over every day starting at the beginning
  243. of the interval).
  244. +/
  245. enum PopFirst
  246. {
  247. /// No, don't call popFront() before returning the range.
  248. no,
  249. /// Yes, call popFront() before returning the range.
  250. yes
  251. }
  252. /++
  253. Used by StopWatch to indicate whether it should start immediately upon
  254. construction.
  255. +/
  256. enum AutoStart
  257. {
  258. /// No, don't start the StopWatch when it is constructed.
  259. no,
  260. /// Yes, do start the StopWatch when it is constructed.
  261. yes
  262. }
  263. /++
  264. Array of the strings representing time units, starting with the smallest
  265. unit and going to the largest. It does not include $(D "nsecs").
  266. Includes $(D "hnsecs") (hecto-nanoseconds (100 ns)),
  267. $(D "usecs") (microseconds), $(D "msecs") (milliseconds), $(D "seconds"),
  268. $(D "minutes"), $(D "hours"), $(D "days"), $(D "weeks"), $(D "months"), and
  269. $(D "years")
  270. +/
  271. immutable string[] timeStrings = ["hnsecs", "usecs", "msecs", "seconds", "minutes",
  272. "hours", "days", "weeks", "months", "years"];
  273. //==============================================================================
  274. // Section with other types.
  275. //==============================================================================
  276. /++
  277. Exception type used by std.datetime. It's an alias to TimeException, which
  278. is what core.time uses. So, you can catch either and not worry about which
  279. module it came from.
  280. +/
  281. alias TimeException DateTimeException;
  282. /++
  283. Effectively a namespace to make it clear that the methods it contains are
  284. getting the time from the system clock. It cannot be instantiated.
  285. +/
  286. final class Clock
  287. {
  288. public:
  289. /++
  290. Returns the current time in the given time zone.
  291. Throws:
  292. $(D ErrnoException) (on Posix) or $(D Exception) (on Windows)
  293. if it fails to get the time of day.
  294. +/
  295. static SysTime currTime(immutable TimeZone tz = LocalTime())
  296. {
  297. return SysTime(currStdTime, tz);
  298. }
  299. unittest
  300. {
  301. version(enableWindowsTest)
  302. {
  303. assert(currTime(UTC()).timezone is UTC());
  304. immutable unixTimeD = currTime().toUnixTime();
  305. immutable unixTimeC = core.stdc.time.time(null);
  306. immutable diff = unixTimeC - unixTimeD;
  307. assertPred!">="(diff, -2);
  308. assertPred!"<="(diff, 2);
  309. }
  310. }
  311. /++
  312. Returns the number of hnsecs since midnight, January 1st, 1 A.D. for the
  313. current time.
  314. Throws:
  315. $(D DateTimeException) if it fails to get the time.
  316. +/
  317. @trusted
  318. static @property long currStdTime()
  319. {
  320. version(Windows)
  321. {
  322. //FILETIME represents hnsecs from midnight, January 1st, 1601.
  323. enum hnsecsFrom1601 = 504_911_232_000_000_000L;
  324. FILETIME fileTime;
  325. GetSystemTimeAsFileTime(&fileTime);
  326. ulong tempHNSecs = fileTime.dwHighDateTime;
  327. tempHNSecs <<= 32;
  328. tempHNSecs |= fileTime.dwLowDateTime;
  329. return cast(long)tempHNSecs + hnsecsFrom1601;
  330. }
  331. else version(Posix)
  332. {
  333. enum hnsecsToUnixEpoch = 621_355_968_000_000_000L;
  334. static if(is(typeof(clock_gettime)))
  335. {
  336. timespec ts;
  337. if(clock_gettime(CLOCK_REALTIME, &ts) != 0)
  338. throw new TimeException("Failed in clock_gettime().");
  339. return convert!("seconds", "hnsecs")(ts.tv_sec) +
  340. ts.tv_nsec / 100 +
  341. hnsecsToUnixEpoch;
  342. }
  343. else
  344. {
  345. timeval tv;
  346. if(gettimeofday(&tv, null) != 0)
  347. throw new TimeException("Failed in gettimeofday().");
  348. return convert!("seconds", "hnsecs")(tv.tv_sec) +
  349. convert!("usecs", "hnsecs")(tv.tv_usec) +
  350. hnsecsToUnixEpoch;
  351. }
  352. }
  353. }
  354. /++
  355. The current system tick. The number of ticks per second varies from
  356. system to system. currSystemTick uses a monotonic clock, so it's
  357. intended for precision timing by comparing relative time values, not
  358. for getting the current system time.
  359. Warning:
  360. On some systems, the monotonic clock may stop counting when
  361. the computer goes to sleep or hibernates. So, the monotonic
  362. clock could be off if that occurs. This is known to happen
  363. on Mac OS X. It has not been tested whether it occurs on
  364. either Windows or Linux.
  365. Throws:
  366. $(D DateTimeException) if it fails to get the time.
  367. +/
  368. @safe
  369. static @property TickDuration currSystemTick()
  370. {
  371. return TickDuration.currSystemTick();
  372. }
  373. unittest
  374. {
  375. version(testStdDateTime)
  376. {
  377. auto t = Clock.currSystemTick;
  378. assert(t.length > 0);
  379. }
  380. }
  381. /++
  382. The current number of system ticks since the application started.
  383. The number of ticks per second varies from system to system.
  384. This uses a monotonic clock.
  385. Warning:
  386. On some systems, the monotonic clock may stop counting when
  387. the computer goes to sleep or hibernates. So, the monotonic
  388. clock could be off if that occurs. This is known to happen
  389. on Mac OS X. It has not been tested whether it occurs on
  390. either Windows or on Linux.
  391. Throws:
  392. $(D DateTimeException) if it fails to get the time.
  393. +/
  394. @safe
  395. static @property TickDuration currAppTick()
  396. {
  397. return currSystemTick - TickDuration.appOrigin;
  398. }
  399. unittest
  400. {
  401. version(testStdDateTime)
  402. {
  403. auto a = Clock.currSystemTick;
  404. auto b = Clock.currAppTick;
  405. assert(a.length);
  406. assert(a != b);
  407. }
  408. }
  409. private:
  410. @disable this() {}
  411. }
  412. //==============================================================================
  413. // Section with time points.
  414. //==============================================================================
  415. /++
  416. $(D SysTime) is the type used when you want to get the current time from the
  417. system or if you're doing anything that involves time zones. Unlike
  418. $(D DateTime), the time zone is an integral part of $(D SysTime) (though if
  419. all you care about is local time, you can pretty much ignore time zones, and
  420. it will work, since it defaults to using the local time zone). It holds its
  421. internal time in std time (hnsecs since midnight, January 1st, 1 A.D. UTC),
  422. so it interfaces well with the system time. However, that means that, unlike
  423. $(D DateTime), it is not optimized for calendar-based operations, and
  424. getting individual units from it such as years or days is going to involve
  425. conversions and be less efficient.
  426. Basically, if you care about calendar-based operations and don't
  427. necessarily care about time zones, then $(D DateTime) would be the type to
  428. use. However, if what you care about is the system time, then $(D SysTime)
  429. would be the type to use.
  430. $(D Clock.currTime) will return the current time as a $(D SysTime). If you
  431. want to convert a $(D SysTime) to a $(D Date) or $(D DateTime), simply cast
  432. it. And if you ever want to convert a $(D Date) or $(D DateTime) to a
  433. $(D SysTime), use $(D SysTime)'s constructor, and you can pass in the
  434. intended time zone with it (or don't pass in a $(D TimeZone), and the local
  435. time zone will be used). Be aware, however, that converting from a
  436. $(D DateTime) to a $(D SysTime) will not necessarily be 100% accurate due to
  437. DST (one hour of the year doesn't exist and another occurs twice). So, if
  438. you don't want to risk any conversion errors, keep your times as
  439. $(D SysTime)s. Aside from DST though, there shouldn't be any conversion
  440. problems.
  441. If you care about using time zones other than local time or UTC, you can use
  442. $(D PosixTimeZone) on Posix systems (or on Windows, if you provide the TZ
  443. Database files), and you can use $(D WindowsTimeZone) on Windows systems.
  444. The time in $(D SysTime) is kept internally in hnsecs from midnight,
  445. January 1st, 1 A.D. UTC. So, you never get conversion errors when changing
  446. the time zone of a $(D SysTime). $(D LocalTime) is the $(D TimeZone) class
  447. which represents the local time, and $(D UTC) is the $(D TimeZone) class
  448. which represents UTC. $(D SysTime) uses $(D LocalTime) if no $(D TimeZone)
  449. is provided. For more details on time zones, look at the documentation for
  450. $(D TimeZone), $(D PosixTimeZone), and $(D WindowsTimeZone).
  451. $(D SysTime)'s range is from approximately 29,000 B.C. to approximately
  452. 29,000 A.D.
  453. +/
  454. struct SysTime
  455. {
  456. public:
  457. /++
  458. Params:
  459. dateTime = The $(D DateTime) to use to set this $(D SysTime)'s
  460. internal std time. As $(D DateTime) has no concept of
  461. time zone, tz is used as its time zone.
  462. tz = The $(D TimeZone) to use for this $(D SysTime). If null,
  463. $(D LocalTime) will be used. The given $(D DateTime) is
  464. assumed to be in the given time zone.
  465. +/
  466. this(in DateTime dateTime, immutable TimeZone tz = null) nothrow
  467. {
  468. try
  469. this(dateTime, FracSec.from!"hnsecs"(0), tz);
  470. catch(Exception e)
  471. assert(0, "FracSec's constructor threw when it shouldn't have.");
  472. }
  473. unittest
  474. {
  475. version(testStdDateTime)
  476. {
  477. assertPred!"=="(SysTime(DateTime.init, UTC())._stdTime, 0);
  478. assertPred!"=="(SysTime(DateTime(1, 1, 1, 12, 30, 33), UTC())._stdTime, 450_330_000_000L);
  479. assertPred!"=="(SysTime(DateTime(0, 12, 31, 12, 30, 33), UTC())._stdTime, -413_670_000_000L);
  480. assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0), UTC())._stdTime, 0);
  481. assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 1), UTC())._stdTime, 10_000_000L);
  482. assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), UTC())._stdTime, -10_000_000L);
  483. assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0), new SimpleTimeZone(-60)).stdTime, 36_000_000_000L);
  484. assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0), new SimpleTimeZone(0)).stdTime, 0);
  485. assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0), new SimpleTimeZone(60)).stdTime, -36_000_000_000L);
  486. }
  487. }
  488. /++
  489. Params:
  490. dateTime = The $(D DateTime) to use to set this $(D SysTime)'s
  491. internal std time. As $(D DateTime) has no concept of
  492. time zone, tz is used as its time zone.
  493. fsec = The fractional seconds portion of the time.
  494. tz = The $(D TimeZone) to use for this $(D SysTime). If null,
  495. $(D LocalTime) will be used. The given $(D DateTime) is
  496. assumed to be in the given time zone.
  497. +/
  498. this(in DateTime dateTime, in FracSec fsec, immutable TimeZone tz = null) nothrow
  499. {
  500. if(tz is null)
  501. _timezone = LocalTime();
  502. else
  503. _timezone = tz;
  504. try
  505. {
  506. immutable dateDiff = (dateTime.date - Date(1, 1, 1)).total!"hnsecs";
  507. immutable todDiff = (dateTime.timeOfDay - TimeOfDay(0, 0, 0)).total!"hnsecs";
  508. immutable adjustedTime = dateDiff + todDiff + fsec.hnsecs;
  509. immutable standardTime = _timezone.tzToUTC(adjustedTime);
  510. this(standardTime, _timezone.get);
  511. }
  512. catch(Exception e)
  513. assert(0, "Date, TimeOfDay, or DateTime's constructor threw when it shouldn't have.");
  514. }
  515. unittest
  516. {
  517. version(testStdDateTime)
  518. {
  519. assertPred!"=="(SysTime(DateTime.init, FracSec.init, UTC())._stdTime, 0);
  520. assertPred!"=="(SysTime(DateTime(1, 1, 1, 12, 30, 33), FracSec.init, UTC())._stdTime, 450_330_000_000L);
  521. assertPred!"=="(SysTime(DateTime(0, 12, 31, 12, 30, 33), FracSec.init, UTC())._stdTime, -413_670_000_000L);
  522. assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(1), UTC())._stdTime, 10_000L);
  523. assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"msecs"(999), UTC())._stdTime, -10_000L);
  524. assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999), UTC()).stdTime, -1);
  525. assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1), UTC()).stdTime, -9_999_999);
  526. assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0), UTC()).stdTime, -10_000_000);
  527. }
  528. }
  529. /++
  530. Params:
  531. date = The $(D Date) to use to set this $(D SysTime)'s internal std
  532. time. As $(D Date) has no concept of time zone, tz is used as
  533. its time zone.
  534. tz = The $(D TimeZone) to use for this $(D SysTime). If null,
  535. $(D LocalTime) will be used. The given $(D Date) is assumed
  536. to be in the given time zone.
  537. +/
  538. this(in Date date, immutable TimeZone tz = null) nothrow
  539. {
  540. if(tz is null)
  541. _timezone = LocalTime();
  542. else
  543. _timezone = tz;
  544. try
  545. {
  546. immutable adjustedTime = (date - Date(1, 1, 1)).total!"hnsecs";
  547. immutable standardTime = _timezone.tzToUTC(adjustedTime);
  548. this(standardTime, _timezone.get);
  549. }
  550. catch(Exception e)
  551. assert(0, "Date's constructor through when it shouldn't have");
  552. }
  553. unittest
  554. {
  555. version(testStdDateTime)
  556. {
  557. assertPred!"=="(SysTime(Date.init, UTC())._stdTime, 0);
  558. assertPred!"=="(SysTime(Date(1, 1, 1), UTC())._stdTime, 0);
  559. assertPred!"=="(SysTime(Date(1, 1, 2), UTC())._stdTime, 864000000000);
  560. assertPred!"=="(SysTime(Date(0, 12, 31), UTC())._stdTime, -864000000000);
  561. }
  562. }
  563. /++
  564. Note:
  565. Whereas the other constructors take in the given date/time, assume
  566. that it's in the given time zone, and convert it to hnsecs in UTC
  567. since midnight, January 1st, 1 A.D. UTC - i.e. std time - this
  568. constructor takes a std time, which is specifically already in UTC,
  569. so no conversion takes place. Of course, the various getter
  570. properties and functions will use the given time zone's conversion
  571. function to convert the results to that time zone, but no conversion
  572. of the arguments to this constructor takes place.
  573. Params:
  574. stdTime = The number of hnsecs since midnight, January 1st, 1 A.D. UTC.
  575. tz = The $(D TimeZone) to use for this $(D SysTime). If null,
  576. $(D LocalTime) will be used.
  577. +/
  578. this(long stdTime, immutable TimeZone tz = null) pure nothrow
  579. {
  580. _stdTime = stdTime;
  581. if(tz is null)
  582. _timezone = LocalTime();
  583. else
  584. _timezone = tz;
  585. }
  586. unittest
  587. {
  588. version(testStdDateTime)
  589. {
  590. assertPred!"=="(SysTime(0)._stdTime, 0);
  591. }
  592. }
  593. /++
  594. Params:
  595. rhs = The $(D SysTime) to assign to this one.
  596. +/
  597. ref SysTime opAssign(const ref SysTime rhs) pure nothrow
  598. {
  599. _stdTime = rhs._stdTime;
  600. _timezone = rhs._timezone.get;
  601. return this;
  602. }
  603. /++
  604. Params:
  605. rhs = The $(D SysTime) to assign to this one.
  606. +/
  607. ref SysTime opAssign(SysTime rhs) pure nothrow
  608. {
  609. _stdTime = rhs._stdTime;
  610. _timezone = rhs._timezone.get;
  611. return this;
  612. }
  613. /++
  614. Checks for equality between this $(D SysTime) and the given
  615. $(D SysTime).
  616. Note that the time zone is ignored. Only the internal
  617. std times (which are in UTC) are compared.
  618. +/
  619. bool opEquals(const ref SysTime rhs) const pure nothrow
  620. {
  621. return _stdTime == rhs._stdTime;
  622. }
  623. unittest
  624. {
  625. version(testStdDateTime)
  626. {
  627. auto a = SysTime(DateTime.init, UTC());
  628. auto b = SysTime(0, UTC());
  629. assert(a == b);
  630. assertPred!"=="(a, b);
  631. assertPred!"=="(SysTime(DateTime.init, UTC()), SysTime(0, UTC()));
  632. assertPred!"=="(SysTime(Date.init, UTC()), SysTime(0, UTC()));
  633. assertPred!"=="(SysTime(0), SysTime(0));
  634. assertPred!"=="(SysTime(Date(1999, 1, 1)), SysTime(Date(1999, 1, 1)));
  635. assertPred!"=="(SysTime(Date(1999, 1, 1)), SysTime(Date(1999, 1, 1)));
  636. assertPred!"=="(SysTime(Date(1, 7, 1)), SysTime(Date(1, 7, 1)));
  637. assertPred!"=="(SysTime(Date(1, 1, 6)), SysTime(Date(1, 1, 6)));
  638. assertPred!"=="(SysTime(Date(1999, 7, 1)), SysTime(Date(1999, 7, 1)));
  639. assertPred!"=="(SysTime(Date(1999, 7, 6)), SysTime(Date(1999, 7, 6)));
  640. assertPred!"=="(SysTime(Date(1, 7, 6)), SysTime(Date(1, 7, 6)));
  641. assertPred!"=="(SysTime(DateTime(1999, 1, 1, 0, 0, 0)), SysTime(Date(1999, 1, 1)));
  642. assertPred!"=="(SysTime(Date(1999, 1, 1)), SysTime(DateTime(1999, 1, 1, 0, 0, 0)));
  643. assertPred!"!="(SysTime(DateTime(1999, 1, 1, 11, 30, 20)), SysTime(Date(1999, 1, 1)));
  644. assertPred!"!="(SysTime(Date(1999, 1, 1)), SysTime(DateTime(1999, 1, 1, 11, 30, 20)));
  645. assertPred!"=="(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0))),
  646. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0))));
  647. assertPred!"=="(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 0))),
  648. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 0))));
  649. assertPred!"=="(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 0))),
  650. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 0))));
  651. assertPred!"=="(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33))),
  652. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33))));
  653. assertPred!"=="(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0))),
  654. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0))));
  655. assertPred!"=="(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))),
  656. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))));
  657. assertPred!"=="(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33))),
  658. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33))));
  659. assertPred!"=="(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33))),
  660. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33))));
  661. {
  662. auto sysUTC = SysTime(Date(1999, 1, 1));
  663. sysUTC.timezone = UTC();
  664. auto sysLocal = SysTime(Date(1999, 1, 1));
  665. sysUTC.timezone = LocalTime();
  666. assertPred!"=="(sysUTC, sysLocal);
  667. assertPred!"=="(sysLocal, sysUTC);
  668. if(!localTimeIsUTC)
  669. {
  670. assertPred!"!="(SysTime(Date(1999, 1, 1), UTC()), SysTime(Date(1999, 1, 1), LocalTime()));
  671. assertPred!"!="(SysTime(Date(1999, 7, 1), LocalTime()), SysTime(Date(1999, 7, 1), UTC()));
  672. }
  673. }
  674. {
  675. auto sysUTC = SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)));
  676. sysUTC.timezone = UTC();
  677. auto sysSimple = SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)));
  678. sysSimple.timezone = new SimpleTimeZone(-360);
  679. assertPred!"=="(sysUTC, sysSimple);
  680. assertPred!"=="(sysSimple, sysUTC);
  681. assertPred!"!="(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), UTC()),
  682. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), sysSimple.timezone));
  683. assertPred!"!="(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), sysSimple.timezone),
  684. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), UTC()));
  685. }
  686. {
  687. auto sysUTC = SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), UTC());
  688. auto sysSimple = SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), new SimpleTimeZone(240));
  689. assertPred!"!="(sysUTC, sysSimple);
  690. assertPred!"!="(sysSimple, sysUTC);
  691. sysUTC = SysTime(DateTime(Date(1999, 7, 5), TimeOfDay(20, 0, 0)), UTC());
  692. assertPred!"=="(sysUTC, sysSimple);
  693. assertPred!"=="(sysSimple, sysUTC);
  694. }
  695. auto st = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
  696. const cst = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
  697. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
  698. static assert(__traits(compiles, st == st));
  699. static assert(__traits(compiles, st == cst));
  700. //static assert(__traits(compiles, st == ist));
  701. static assert(__traits(compiles, cst == st));
  702. static assert(__traits(compiles, cst == cst));
  703. //static assert(__traits(compiles, cst == ist));
  704. //static assert(__traits(compiles, ist == st));
  705. //static assert(__traits(compiles, ist == cst));
  706. //static assert(__traits(compiles, ist == ist));
  707. }
  708. }
  709. /++
  710. Compares this $(D SysTime) with the given $(D SysTime).
  711. Time zone is irrelevant when comparing $(D SysTime)s.
  712. Returns:
  713. $(TABLE
  714. $(TR $(TD this &lt; rhs) $(TD &lt; 0))
  715. $(TR $(TD this == rhs) $(TD 0))
  716. $(TR $(TD this &gt; rhs) $(TD &gt; 0))
  717. )
  718. +/
  719. int opCmp(in SysTime rhs) const pure nothrow
  720. {
  721. if(_stdTime < rhs._stdTime)
  722. return -1;
  723. if(_stdTime > rhs._stdTime)
  724. return 1;
  725. return 0;
  726. }
  727. unittest
  728. {
  729. version(testStdDateTime)
  730. {
  731. //Test A.D.
  732. assertPred!("opCmp", "==")(SysTime(DateTime.init, UTC()), SysTime(0));
  733. assertPred!("opCmp", "==")(SysTime(Date.init, UTC()), SysTime(0));
  734. assertPred!("opCmp", "==")(SysTime(Date(1999, 1, 1)), SysTime(Date(1999, 1, 1)));
  735. assertPred!("opCmp", "==")(SysTime(Date(1999, 1, 1)), SysTime(Date(1999, 1, 1)));
  736. assertPred!("opCmp", "==")(SysTime(Date(1, 7, 1)), SysTime(Date(1, 7, 1)));
  737. assertPred!("opCmp", "==")(SysTime(Date(1, 1, 6)), SysTime(Date(1, 1, 6)));
  738. assertPred!("opCmp", "==")(SysTime(Date(1999, 7, 1)), SysTime(Date(1999, 7, 1)));
  739. assertPred!("opCmp", "==")(SysTime(Date(1999, 7, 6)), SysTime(Date(1999, 7, 6)));
  740. assertPred!("opCmp", "==")(SysTime(Date(1, 7, 6)), SysTime(Date(1, 7, 6)));
  741. assertPred!("opCmp", ">")(SysTime(DateTime(1999, 1, 1, 11, 30, 20)), SysTime(Date(1999, 1, 1)));
  742. assertPred!("opCmp", "<")(SysTime(Date(1999, 1, 1)), SysTime(DateTime(1999, 1, 1, 11, 30, 20)));
  743. assertPred!("opCmp", "<")(SysTime(Date(1999, 7, 6)), SysTime(Date(2000, 7, 6)));
  744. assertPred!("opCmp", ">")(SysTime(Date(2000, 7, 6)), SysTime(Date(1999, 7, 6)));
  745. assertPred!("opCmp", "<")(SysTime(Date(1999, 7, 6)), SysTime(Date(1999, 8, 6)));
  746. assertPred!("opCmp", ">")(SysTime(Date(1999, 8, 6)), SysTime(Date(1999, 7, 6)));
  747. assertPred!("opCmp", "<")(SysTime(Date(1999, 7, 6)), SysTime(Date(1999, 7, 7)));
  748. assertPred!("opCmp", ">")(SysTime(Date(1999, 7, 7)), SysTime(Date(1999, 7, 6)));
  749. assertPred!("opCmp", "<")(SysTime(Date(1999, 8, 7)), SysTime(Date(2000, 7, 6)));
  750. assertPred!("opCmp", ">")(SysTime(Date(2000, 8, 6)), SysTime(Date(1999, 7, 7)));
  751. assertPred!("opCmp", "<")(SysTime(Date(1999, 7, 7)), SysTime(Date(2000, 7, 6)));
  752. assertPred!("opCmp", ">")(SysTime(Date(2000, 7, 6)), SysTime(Date(1999, 7, 7)));
  753. assertPred!("opCmp", "<")(SysTime(Date(1999, 7, 7)), SysTime(Date(1999, 8, 6)));
  754. assertPred!("opCmp", ">")(SysTime(Date(1999, 8, 6)), SysTime(Date(1999, 7, 7)));
  755. assertPred!("opCmp", "==")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0))),
  756. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0))));
  757. assertPred!("opCmp", "==")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 0))),
  758. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 0))));
  759. assertPred!("opCmp", "==")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 0))),
  760. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 0)))),
  761. assertPred!("opCmp", "==")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33))),
  762. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33))));
  763. assertPred!("opCmp", "==")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0))),
  764. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0))));
  765. assertPred!("opCmp", "==")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))),
  766. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))));
  767. assertPred!("opCmp", "==")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33))),
  768. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33))));
  769. assertPred!("opCmp", "==")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33))),
  770. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33))));
  771. assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))),
  772. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33))));
  773. assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33))),
  774. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))));
  775. assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))),
  776. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33))));
  777. assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33))),
  778. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))));
  779. assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))),
  780. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34))));
  781. assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34))),
  782. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))));
  783. assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33))),
  784. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34))));
  785. assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34))),
  786. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33))));
  787. assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33))),
  788. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33))));
  789. assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33))),
  790. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33))));
  791. assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33))),
  792. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34))));
  793. assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34))),
  794. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33))));
  795. assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33))),
  796. SysTime(DateTime(Date(2000, 7, 6), TimeOfDay(12, 30, 33))));
  797. assertPred!("opCmp", ">")(SysTime(DateTime(Date(2000, 7, 6), TimeOfDay(12, 30, 33))),
  798. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33))));
  799. assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33))),
  800. SysTime(DateTime(Date(2000, 7, 6), TimeOfDay(12, 30, 33))));
  801. assertPred!("opCmp", ">")(SysTime(DateTime(Date(2000, 7, 6), TimeOfDay(12, 30, 33))),
  802. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33))));
  803. assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34))),
  804. SysTime(DateTime(Date(2000, 7, 6), TimeOfDay(12, 30, 33))));
  805. assertPred!("opCmp", ">")(SysTime(DateTime(Date(2000, 7, 6), TimeOfDay(12, 30, 33))),
  806. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34))));
  807. assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33))),
  808. SysTime(DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33))));
  809. assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33))),
  810. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33))));
  811. assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33))),
  812. SysTime(DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33))));
  813. assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33))),
  814. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33))));
  815. assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34))),
  816. SysTime(DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33))));
  817. assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33))),
  818. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34))));
  819. assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33))),
  820. SysTime(DateTime(Date(1999, 7, 7), TimeOfDay(12, 30, 33))));
  821. assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 7), TimeOfDay(12, 30, 33))),
  822. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33))));
  823. assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33))),
  824. SysTime(DateTime(Date(1999, 7, 7), TimeOfDay(12, 31, 33))));
  825. assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 7), TimeOfDay(12, 30, 33))),
  826. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))));
  827. assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34))),
  828. SysTime(DateTime(Date(1999, 7, 7), TimeOfDay(12, 30, 33))));
  829. assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 7), TimeOfDay(12, 30, 33))),
  830. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34))));
  831. //Test B.C.
  832. assertPred!("opCmp", "==")(SysTime(DateTime(Date(-1, 1, 1), TimeOfDay(12, 30, 33))),
  833. SysTime(DateTime(Date(-1, 1, 1), TimeOfDay(12, 30, 33))));
  834. assertPred!("opCmp", "==")(SysTime(DateTime(Date(-1, 7, 1), TimeOfDay(12, 30, 33))),
  835. SysTime(DateTime(Date(-1, 7, 1), TimeOfDay(12, 30, 33))));
  836. assertPred!("opCmp", "==")(SysTime(DateTime(Date(-1, 1, 6), TimeOfDay(12, 30, 33))),
  837. SysTime(DateTime(Date(-1, 1, 6), TimeOfDay(12, 30, 33))));
  838. assertPred!("opCmp", "==")(SysTime(DateTime(Date(-1999, 7, 1), TimeOfDay(12, 30, 33))),
  839. SysTime(DateTime(Date(-1999, 7, 1), TimeOfDay(12, 30, 33))));
  840. assertPred!("opCmp", "==")(SysTime(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33))),
  841. SysTime(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33))));
  842. assertPred!("opCmp", "==")(SysTime(DateTime(Date(-1, 7, 6), TimeOfDay(12, 30, 33))),
  843. SysTime(DateTime(Date(-1, 7, 6), TimeOfDay(12, 30, 33))));
  844. assertPred!("opCmp", "<")(SysTime(DateTime(Date(-2000, 7, 6), TimeOfDay(12, 30, 33))),
  845. SysTime(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33))));
  846. assertPred!("opCmp", ">")(SysTime(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33))),
  847. SysTime(DateTime(Date(-2000, 7, 6), TimeOfDay(12, 30, 33))));
  848. assertPred!("opCmp", "<")(SysTime(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33))),
  849. SysTime(DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33))));
  850. assertPred!("opCmp", ">")(SysTime(DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33))),
  851. SysTime(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33))));
  852. assertPred!("opCmp", "<")(SysTime(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33))),
  853. SysTime(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33))));
  854. assertPred!("opCmp", ">")(SysTime(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33))),
  855. SysTime(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33))));
  856. assertPred!("opCmp", "<")(SysTime(DateTime(Date(-2000, 8, 6), TimeOfDay(12, 30, 33))),
  857. SysTime(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33))));
  858. assertPred!("opCmp", ">")(SysTime(DateTime(Date(-1999, 8, 7), TimeOfDay(12, 30, 33))),
  859. SysTime(DateTime(Date(-2000, 7, 6), TimeOfDay(12, 30, 33))));
  860. assertPred!("opCmp", "<")(SysTime(DateTime(Date(-2000, 7, 6), TimeOfDay(12, 30, 33))),
  861. SysTime(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33))));
  862. assertPred!("opCmp", ">")(SysTime(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33))),
  863. SysTime(DateTime(Date(-2000, 7, 6), TimeOfDay(12, 30, 33))));
  864. assertPred!("opCmp", "<")(SysTime(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33))),
  865. SysTime(DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33))));
  866. assertPred!("opCmp", ">")(SysTime(DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33))),
  867. SysTime(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33))));
  868. //Test Both
  869. assertPred!("opCmp", "<")(SysTime(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33))),
  870. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))));
  871. assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))),
  872. SysTime(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33))));
  873. assertPred!("opCmp", "<")(SysTime(DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33))),
  874. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))));
  875. assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))),
  876. SysTime(DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33))));
  877. assertPred!("opCmp", "<")(SysTime(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33))),
  878. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))));
  879. assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))),
  880. SysTime(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33))));
  881. assertPred!("opCmp", "<")(SysTime(DateTime(Date(-1999, 8, 7), TimeOfDay(12, 30, 33))),
  882. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))));
  883. assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))),
  884. SysTime(DateTime(Date(-1999, 8, 7), TimeOfDay(12, 30, 33))));
  885. assertPred!("opCmp", "<")(SysTime(DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33))),
  886. SysTime(DateTime(Date(1999, 6, 6), TimeOfDay(12, 30, 33))));
  887. assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 6, 8), TimeOfDay(12, 30, 33))),
  888. SysTime(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33))));
  889. {
  890. auto sysUTC = SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)));
  891. sysUTC.timezone = UTC();
  892. auto sysSimple = SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)));
  893. sysSimple.timezone = new SimpleTimeZone(-360);
  894. assertPred!("opCmp", "==")(sysUTC, sysSimple);
  895. assertPred!("opCmp", "==")(sysSimple, sysUTC);
  896. assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), UTC()),
  897. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), sysSimple.timezone));
  898. assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), sysSimple.timezone),
  899. SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), UTC()));
  900. }
  901. {
  902. auto sysUTC = SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), UTC());
  903. auto sysSimple = SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), new SimpleTimeZone(240));
  904. assertPred!("opCmp", ">")(sysUTC, sysSimple);
  905. assertPred!("opCmp", "<")(sysSimple, sysUTC);
  906. sysUTC = SysTime(DateTime(Date(1999, 7, 5), TimeOfDay(20, 0, 0)), UTC());
  907. assertPred!("opCmp", "==")(sysUTC, sysSimple);
  908. assertPred!("opCmp", "==")(sysSimple, sysUTC);
  909. }
  910. auto st = SysTime(DateTime(1999, 7, 6, 12, 33, 30));