/d/phobos2/std/datetime.d

https://bitbucket.org/alexrp/gdc · D · 33971 lines · 22008 code · 4394 blank · 7569 comment · 1515 complexity · 5de7024b9dda482701bc9e52fc10a811 MD5 · raw 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 intervals of time.)
  9. $(LI Types to represent ranges over intervals of time.)
  10. $(LI Types to represent time zones (used by $(D SysTime)).)
  11. $(LI A platform-independent, high precision stopwatch type:
  12. $(D StopWatch))
  13. $(LI Benchmarking functions.)
  14. $(LI Various helper functions.)
  15. )
  16. Closely related to std.datetime is <a href="core_time.html">$(D core.time)</a>,
  17. and some of the time types used in std.datetime come from there - such as
  18. $(CXREF time, Duration), $(CXREF time, TickDuration), and
  19. $(CXREF time, FracSec). So, you may want to look at its documentation as
  20. well. However, core.time is publically imported into std.datetime, so you
  21. don't have to import it separately.
  22. Three of the main concepts used in this module are time points, time
  23. durations, and time intervals.
  24. A time point is a specific point in time. e.g. January 5th, 2010
  25. or 5:00.
  26. A time duration is a length of time with units. e.g. 5 days or 231 seconds.
  27. A time interval indicates a period of time associated with a fixed point in
  28. time. So, it is either two time points associated with each other,
  29. indicating the time starting at the first point up to, but not including,
  30. the second point - e.g. [January 5th, 2010 - March 10th, 2010$(RPAREN) - or
  31. it is a time point and a time duration associated with one another. e.g.
  32. January 5th, 2010 and 5 days, indicating [January 5th, 2010 -
  33. January 10th, 2010$(RPAREN).
  34. Various arithmetic operations are supported between time points and
  35. durations (e.g. the difference between two time points is a time duration),
  36. and ranges can be gotten from time intervals, so range-based operations may
  37. be done on a series of time points.
  38. The types that the typical user is most likely to be interested in are
  39. $(D Date) (if they want dates but don't care about time), $(D DateTime)
  40. (if they want dates and times but don't care about time zones), $(D SysTime)
  41. (if they want the date and time from the OS and/or do care about time
  42. zones), and StopWatch (a platform-independent, high precision stop watch).
  43. $(D Date) and $(D DateTime) are optimized for calendar-based operations,
  44. while $(D SysTime) is designed for dealing with time from the OS. Check out
  45. their specific documentation for more details.
  46. To get the current time, use $(D Clock.currTime). It will return the current
  47. time as a $(D SysTime). If you want to print it, $(D toString) is
  48. sufficient, but if you use $(D toISOString), $(D toISOExtString), or
  49. $(D toSimpleString), you can use the corresponding $(D fromISOString),
  50. $(D fromISOExtString), or $(D fromISOExtString) to create a
  51. $(D SysTime) from the string.
  52. --------------------
  53. auto currentTime = Clock.currTime();
  54. auto timeString = currentTime.toISOExtString();
  55. auto restoredTime = SysTime.fromISOExtString(timeString);
  56. --------------------
  57. Various functions take a string (or strings) to represent a unit of time
  58. (e.g. $(D convert!("days", "hours")(numDays))). The valid strings to use
  59. with such functions are $(D "years"), $(D "months"), $(D "weeks"),
  60. $(D "days"), $(D "hours"), $(D "minutes"), $(D "seconds"),
  61. $(D "msecs") (milliseconds), $(D "usecs") (microseconds),
  62. $(D "hnsecs") (hecto-nanoseconds - i.e. 100 ns), or some subset thereof.
  63. There are a few functions in core.time which take $(D "nsecs"), but because
  64. nothing in std.datetime has precision greater than hnsecs, and very little
  65. in core.time does, no functions in std.datetime accept $(D "nsecs"). If
  66. you need help remembering which units are abbreviated and which aren't,
  67. notice that all units seconds and greater use their full names, and all
  68. sub-second units are abbreviated (since they'd be rather long if they
  69. weren't).
  70. If you're looking for the definitions of $(D Duration), $(D TickDuration),
  71. or $(D FracSec), they're in core.time.
  72. Note:
  73. $(D DateTimeException) is an alias for core.time's $(D TimeException),
  74. so you don't need to worry about core.time functions and std.datetime
  75. functions throwing different exception types (except in the rare case
  76. that they throw something other than $(D TimeException) or
  77. $(D DateTimeException)).
  78. See_Also:
  79. $(WEB en.wikipedia.org/wiki/ISO_8601, ISO 8601)
  80. $(WEB en.wikipedia.org/wiki/Tz_database, Wikipedia entry on TZ Database)
  81. $(WEB en.wikipedia.org/wiki/List_of_tz_database_time_zones,
  82. List of Time Zones)
  83. Copyright: Copyright 2010 - 2011
  84. License: $(WEB www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
  85. Authors: Jonathan M Davis and Kato Shoichi
  86. Source: $(PHOBOSSRC std/_datetime.d)
  87. +/
  88. module std.datetime;
  89. public import core.time;
  90. import core.exception;
  91. import core.stdc.time;
  92. import std.array;
  93. import std.algorithm;
  94. import std.ascii;
  95. import std.conv;
  96. import std.exception;
  97. import std.file;
  98. import std.functional;
  99. import std.math;
  100. import std.metastrings;
  101. import std.path;
  102. import std.range;
  103. import std.stdio;
  104. import std.string;
  105. import std.system;
  106. import std.traits;
  107. import std.typecons;
  108. version(Windows)
  109. {
  110. import core.sys.windows.windows;
  111. import std.c.windows.winsock;
  112. //For system call to access the registry.
  113. pragma(lib, "advapi32.lib");
  114. }
  115. else version(Posix)
  116. {
  117. import core.sys.posix.arpa.inet;
  118. import core.sys.posix.stdlib;
  119. import core.sys.posix.time;
  120. import core.sys.posix.sys.time;
  121. //We need to disable many tests because building all of Phobos
  122. //with all of std.datetime's unit tests enables currently causes
  123. //dmd to run out of memory.
  124. //Regardless of that, however, it's also useful to be able to
  125. //easily turn the tests on and off.
  126. version = testStdDateTime;
  127. }
  128. version(unittest)
  129. {
  130. import std.c.string;
  131. import std.stdio;
  132. }
  133. //I'd just alias it to indexOf, but
  134. //http://d.puremagic.com/issues/show_bug.cgi?id=6013 would mean that that would
  135. //pollute the global namespace. So, for now, I've created an alias which is
  136. //highly unlikely to conflict with anything that anyone else is doing.
  137. private alias std.string.indexOf stds_indexOf;
  138. //Verify module example.
  139. version(testStdDateTime) unittest
  140. {
  141. auto currentTime = Clock.currTime();
  142. auto timeString = currentTime.toISOExtString();
  143. auto restoredTime = SysTime.fromISOExtString(timeString);
  144. }
  145. //Verify Examples for core.time.Duration which couldn't be in core.time.
  146. unittest
  147. {
  148. assert(std.datetime.Date(2010, 9, 7) + dur!"days"(5) ==
  149. std.datetime.Date(2010, 9, 12));
  150. assert(std.datetime.Date(2010, 9, 7) - std.datetime.Date(2010, 10, 3) ==
  151. dur!"days"(-26));
  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. version(testStdDateTime) unittest
  300. {
  301. assert(currTime(UTC()).timezone is UTC());
  302. //I have no idea why, but for some reason, Windows/Wine likes to get
  303. //time_t wrong when getting it with core.stdc.time.time. On one box
  304. //I have (which has its local time set to UTC), it always gives time_t
  305. //in the real local time (America/Los_Angeles), and after the most recent
  306. //DST switch, every Windows box that I've tried it in is reporting
  307. //time_t as being 1 hour off of where it's supposed to be. So, I really
  308. //don't know what the deal is, but given what I'm seeing, I don't trust
  309. //core.stdc.time.time on Windows, so I'm just going to disable this test
  310. //on Windows.
  311. version(Posix)
  312. {
  313. immutable unixTimeD = currTime().toUnixTime();
  314. immutable unixTimeC = core.stdc.time.time(null);
  315. immutable diff = unixTimeC - unixTimeD;
  316. _assertPred!">="(diff, -2);
  317. _assertPred!"<="(diff, 2);
  318. }
  319. }
  320. /++
  321. Returns the number of hnsecs since midnight, January 1st, 1 A.D. for the
  322. current time.
  323. Throws:
  324. $(D DateTimeException) if it fails to get the time.
  325. +/
  326. @trusted
  327. static @property long currStdTime()
  328. {
  329. version(Windows)
  330. {
  331. //FILETIME represents hnsecs from midnight, January 1st, 1601.
  332. enum hnsecsFrom1601 = 504_911_232_000_000_000L;
  333. FILETIME fileTime;
  334. GetSystemTimeAsFileTime(&fileTime);
  335. ulong tempHNSecs = fileTime.dwHighDateTime;
  336. tempHNSecs <<= 32;
  337. tempHNSecs |= fileTime.dwLowDateTime;
  338. return cast(long)tempHNSecs + hnsecsFrom1601;
  339. }
  340. else version(Posix)
  341. {
  342. enum hnsecsToUnixEpoch = 621_355_968_000_000_000L;
  343. static if(is(typeof(clock_gettime)))
  344. {
  345. timespec ts;
  346. if(clock_gettime(CLOCK_REALTIME, &ts) != 0)
  347. throw new TimeException("Failed in clock_gettime().");
  348. return convert!("seconds", "hnsecs")(ts.tv_sec) +
  349. ts.tv_nsec / 100 +
  350. hnsecsToUnixEpoch;
  351. }
  352. else
  353. {
  354. timeval tv;
  355. if(gettimeofday(&tv, null) != 0)
  356. throw new TimeException("Failed in gettimeofday().");
  357. return convert!("seconds", "hnsecs")(tv.tv_sec) +
  358. convert!("usecs", "hnsecs")(tv.tv_usec) +
  359. hnsecsToUnixEpoch;
  360. }
  361. }
  362. }
  363. /++
  364. The current system tick. The number of ticks per second varies from
  365. system to system. currSystemTick uses a monotonic clock, so it's
  366. intended for precision timing by comparing relative time values, not
  367. for getting the current system time.
  368. Warning:
  369. On some systems, the monotonic clock may stop counting when
  370. the computer goes to sleep or hibernates. So, the monotonic
  371. clock could be off if that occurs. This is known to happen
  372. on Mac OS X. It has not been tested whether it occurs on
  373. either Windows or Linux.
  374. Throws:
  375. $(D DateTimeException) if it fails to get the time.
  376. +/
  377. @safe
  378. static @property TickDuration currSystemTick()
  379. {
  380. return TickDuration.currSystemTick();
  381. }
  382. version(testStdDateTime) unittest
  383. {
  384. assert(Clock.currSystemTick.length > 0);
  385. }
  386. /++
  387. The current number of system ticks since the application started.
  388. The number of ticks per second varies from system to system.
  389. This uses a monotonic clock.
  390. Warning:
  391. On some systems, the monotonic clock may stop counting when
  392. the computer goes to sleep or hibernates. So, the monotonic
  393. clock could be off if that occurs. This is known to happen
  394. on Mac OS X. It has not been tested whether it occurs on
  395. either Windows or on Linux.
  396. Throws:
  397. $(D DateTimeException) if it fails to get the time.
  398. +/
  399. @safe
  400. static @property TickDuration currAppTick()
  401. {
  402. return currSystemTick - TickDuration.appOrigin;
  403. }
  404. version(testStdDateTime) unittest
  405. {
  406. auto a = Clock.currSystemTick;
  407. auto b = Clock.currAppTick;
  408. assert(a.length);
  409. assert(b.length);
  410. assert(a > b);
  411. }
  412. private:
  413. @disable this() {}
  414. }
  415. //==============================================================================
  416. // Section with time points.
  417. //==============================================================================
  418. /++
  419. $(D SysTime) is the type used when you want to get the current time from the
  420. system or if you're doing anything that involves time zones. Unlike
  421. $(D DateTime), the time zone is an integral part of $(D SysTime) (though if
  422. all you care about is local time, you can pretty much ignore time zones, and
  423. it will work, since it defaults to using the local time zone). It holds its
  424. internal time in std time (hnsecs since midnight, January 1st, 1 A.D. UTC),
  425. so it interfaces well with the system time. However, that means that, unlike
  426. $(D DateTime), it is not optimized for calendar-based operations, and
  427. getting individual units from it such as years or days is going to involve
  428. conversions and be less efficient.
  429. Basically, if you care about calendar-based operations and don't
  430. necessarily care about time zones, then $(D DateTime) would be the type to
  431. use. However, if what you care about is the system time, then $(D SysTime)
  432. would be the type to use.
  433. $(D Clock.currTime) will return the current time as a $(D SysTime). If you
  434. want to convert a $(D SysTime) to a $(D Date) or $(D DateTime), simply cast
  435. it. And if you ever want to convert a $(D Date) or $(D DateTime) to a
  436. $(D SysTime), use $(D SysTime)'s constructor, and you can pass in the
  437. intended time zone with it (or don't pass in a $(D TimeZone), and the local
  438. time zone will be used). Be aware, however, that converting from a
  439. $(D DateTime) to a $(D SysTime) will not necessarily be 100% accurate due to
  440. DST (one hour of the year doesn't exist and another occurs twice). So, if
  441. you don't want to risk any conversion errors, keep your times as
  442. $(D SysTime)s. Aside from DST though, there shouldn't be any conversion
  443. problems.
  444. If you care about using time zones other than local time or UTC, you can use
  445. $(D PosixTimeZone) on Posix systems (or on Windows, if you provide the TZ
  446. Database files), and you can use $(D WindowsTimeZone) on Windows systems.
  447. The time in $(D SysTime) is kept internally in hnsecs from midnight,
  448. January 1st, 1 A.D. UTC. So, you never get conversion errors when changing
  449. the time zone of a $(D SysTime). $(D LocalTime) is the $(D TimeZone) class
  450. which represents the local time, and $(D UTC) is the $(D TimeZone) class
  451. which represents UTC. $(D SysTime) uses $(D LocalTime) if no $(D TimeZone)
  452. is provided. For more details on time zones, look at the documentation for
  453. $(D TimeZone), $(D PosixTimeZone), and $(D WindowsTimeZone).
  454. $(D SysTime)'s range is from approximately 29,000 B.C. to approximately
  455. 29,000 A.D.
  456. +/
  457. struct SysTime
  458. {
  459. public:
  460. /++
  461. Params:
  462. dateTime = The $(D DateTime) to use to set this $(D SysTime)'s
  463. internal std time. As $(D DateTime) has no concept of
  464. time zone, tz is used as its time zone.
  465. tz = The $(D TimeZone) to use for this $(D SysTime). If null,
  466. $(D LocalTime) will be used. The given $(D DateTime) is
  467. assumed to be in the given time zone.
  468. +/
  469. this(in DateTime dateTime, immutable TimeZone tz = null) nothrow
  470. {
  471. try
  472. this(dateTime, FracSec.from!"hnsecs"(0), tz);
  473. catch(Exception e)
  474. assert(0, "FracSec's constructor threw when it shouldn't have.");
  475. }
  476. version(testStdDateTime) unittest
  477. {
  478. static void test(DateTime dt, immutable TimeZone tz, long expected)
  479. {
  480. auto sysTime = SysTime(dt, tz);
  481. _assertPred!"=="(sysTime._stdTime, expected);
  482. assert(sysTime._timezone is (tz is null ? LocalTime() : tz),
  483. format("Given DateTime: %s", dt));
  484. }
  485. test(DateTime.init, UTC(), 0);
  486. test(DateTime(1, 1, 1, 12, 30, 33), UTC(), 450_330_000_000L);
  487. test(DateTime(0, 12, 31, 12, 30, 33), UTC(), -413_670_000_000L);
  488. test(DateTime(1, 1, 1, 0, 0, 0), UTC(), 0);
  489. test(DateTime(1, 1, 1, 0, 0, 1), UTC(), 10_000_000L);
  490. test(DateTime(0, 12, 31, 23, 59, 59), UTC(), -10_000_000L);
  491. test(DateTime(1, 1, 1, 0, 0, 0), new SimpleTimeZone(-60),
  492. 36_000_000_000L);
  493. test(DateTime(1, 1, 1, 0, 0, 0), new SimpleTimeZone(0), 0);
  494. test(DateTime(1, 1, 1, 0, 0, 0), new SimpleTimeZone(60),
  495. -36_000_000_000L);
  496. }
  497. /++
  498. Params:
  499. dateTime = The $(D DateTime) to use to set this $(D SysTime)'s
  500. internal std time. As $(D DateTime) has no concept of
  501. time zone, tz is used as its time zone.
  502. fracSec = The fractional seconds portion of the time.
  503. tz = The $(D TimeZone) to use for this $(D SysTime). If null,
  504. $(D LocalTime) will be used. The given $(D DateTime) is
  505. assumed to be in the given time zone.
  506. Throws:
  507. $(D DateTimeException) if $(D fracSec) is negative.
  508. +/
  509. this(in DateTime dateTime, in FracSec fracSec, immutable TimeZone tz = null)
  510. {
  511. immutable fracHNSecs = fracSec.hnsecs;
  512. enforce(fracHNSecs >= 0, new DateTimeException("A SysTime cannot have negative fractional seconds."));
  513. _timezone = tz is null ? LocalTime() : tz;
  514. try
  515. {
  516. immutable dateDiff = (dateTime.date - Date(1, 1, 1)).total!"hnsecs";
  517. immutable todDiff = (dateTime.timeOfDay - TimeOfDay(0, 0, 0)).total!"hnsecs";
  518. immutable adjustedTime = dateDiff + todDiff + fracHNSecs;
  519. immutable standardTime = _timezone.tzToUTC(adjustedTime);
  520. this(standardTime, _timezone);
  521. }
  522. catch(Exception e)
  523. {
  524. assert(0, "Date, TimeOfDay, or DateTime's constructor threw when " ~
  525. "it shouldn't have.");
  526. }
  527. }
  528. version(testStdDateTime) unittest
  529. {
  530. static void test(DateTime dt,
  531. FracSec fracSec,
  532. immutable TimeZone tz,
  533. long expected)
  534. {
  535. auto sysTime = SysTime(dt, fracSec, tz);
  536. _assertPred!"=="(sysTime._stdTime, expected);
  537. assert(sysTime._timezone is (tz is null ? LocalTime() : tz),
  538. format("Given DateTime: %s, Given FracSec: %s", dt, fracSec));
  539. }
  540. test(DateTime.init, FracSec.init, UTC(), 0);
  541. test(DateTime(1, 1, 1, 12, 30, 33), FracSec.init, UTC(), 450_330_000_000L);
  542. test(DateTime(0, 12, 31, 12, 30, 33), FracSec.init, UTC(), -413_670_000_000L);
  543. test(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(1), UTC(), 10_000L);
  544. test(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"msecs"(999), UTC(), -10_000L);
  545. test(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999), UTC(), -1);
  546. test(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1), UTC(), -9_999_999);
  547. test(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0), UTC(), -10_000_000);
  548. assertThrown!DateTimeException(SysTime(DateTime.init, FracSec.from!"hnsecs"(-1), UTC()));
  549. }
  550. /++
  551. Params:
  552. date = The $(D Date) to use to set this $(D SysTime)'s internal std
  553. time. As $(D Date) has no concept of time zone, tz is used as
  554. its time zone.
  555. tz = The $(D TimeZone) to use for this $(D SysTime). If null,
  556. $(D LocalTime) will be used. The given $(D Date) is assumed
  557. to be in the given time zone.
  558. +/
  559. this(in Date date, immutable TimeZone tz = null) nothrow
  560. {
  561. _timezone = tz is null ? LocalTime() : tz;
  562. try
  563. {
  564. immutable adjustedTime = (date - Date(1, 1, 1)).total!"hnsecs";
  565. immutable standardTime = _timezone.tzToUTC(adjustedTime);
  566. this(standardTime, _timezone);
  567. }
  568. catch(Exception e)
  569. assert(0, "Date's constructor through when it shouldn't have.");
  570. }
  571. version(testStdDateTime) unittest
  572. {
  573. static void test(Date d, immutable TimeZone tz, long expected)
  574. {
  575. auto sysTime = SysTime(d, tz);
  576. _assertPred!"=="(sysTime._stdTime, expected);
  577. assert(sysTime._timezone is (tz is null ? LocalTime() : tz),
  578. format("Given Date: %s", d));
  579. }
  580. test(Date.init, UTC(), 0);
  581. test(Date(1, 1, 1), UTC(), 0);
  582. test(Date(1, 1, 2), UTC(), 864000000000);
  583. test(Date(0, 12, 31), UTC(), -864000000000);
  584. }
  585. /++
  586. Note:
  587. Whereas the other constructors take in the given date/time, assume
  588. that it's in the given time zone, and convert it to hnsecs in UTC
  589. since midnight, January 1st, 1 A.D. UTC - i.e. std time - this
  590. constructor takes a std time, which is specifically already in UTC,
  591. so no conversion takes place. Of course, the various getter
  592. properties and functions will use the given time zone's conversion
  593. function to convert the results to that time zone, but no conversion
  594. of the arguments to this constructor takes place.
  595. Params:
  596. stdTime = The number of hnsecs since midnight, January 1st, 1 A.D. UTC.
  597. tz = The $(D TimeZone) to use for this $(D SysTime). If null,
  598. $(D LocalTime) will be used.
  599. +/
  600. this(long stdTime, immutable TimeZone tz = null) pure nothrow
  601. {
  602. _stdTime = stdTime;
  603. _timezone = tz is null ? LocalTime() : tz;
  604. }
  605. version(testStdDateTime) unittest
  606. {
  607. static void test(long stdTime, immutable TimeZone tz)
  608. {
  609. auto sysTime = SysTime(stdTime, tz);
  610. _assertPred!"=="(sysTime._stdTime, stdTime);
  611. assert(sysTime._timezone is (tz is null ? LocalTime() : tz),
  612. format("Given stdTime: %s", stdTime));
  613. }
  614. foreach(stdTime; [-1234567890L, -250, 0, 250, 1235657390L])
  615. {
  616. foreach(tz; testTZs)
  617. test(stdTime, tz);
  618. }
  619. }
  620. /++
  621. Params:
  622. rhs = The $(D SysTime) to assign to this one.
  623. +/
  624. ref SysTime opAssign(const ref SysTime rhs) pure nothrow
  625. {
  626. _stdTime = rhs._stdTime;
  627. _timezone = rhs._timezone;
  628. return this;
  629. }
  630. /++
  631. Params:
  632. rhs = The $(D SysTime) to assign to this one.
  633. +/
  634. ref SysTime opAssign(SysTime rhs) pure nothrow
  635. {
  636. _stdTime = rhs._stdTime;
  637. _timezone = rhs._timezone;
  638. return this;
  639. }
  640. /++
  641. Checks for equality between this $(D SysTime) and the given
  642. $(D SysTime).
  643. Note that the time zone is ignored. Only the internal
  644. std times (which are in UTC) are compared.
  645. +/
  646. bool opEquals(const ref SysTime rhs) const pure nothrow
  647. {
  648. return _stdTime == rhs._stdTime;
  649. }
  650. version(testStdDateTime) unittest
  651. {
  652. _assertPred!"=="(SysTime(DateTime.init, UTC()), SysTime(0, UTC()));
  653. _assertPred!"=="(SysTime(DateTime.init, UTC()), SysTime(0));
  654. _assertPred!"=="(SysTime(Date.init, UTC()), SysTime(0));
  655. _assertPred!"=="(SysTime(0), SysTime(0));
  656. static void test(DateTime dt,
  657. immutable TimeZone tz1,
  658. immutable TimeZone tz2)
  659. {
  660. auto st1 = SysTime(dt);
  661. st1.timezone = tz1;
  662. auto st2 = SysTime(dt);
  663. st2.timezone = tz2;
  664. _assertPred!"=="(st1, st2);
  665. }
  666. foreach(tz1; testTZs)
  667. {
  668. foreach(tz2; testTZs)
  669. {
  670. foreach(dt; chain(testDateTimesBC, testDateTimesAD))
  671. test(dt, tz1, tz2);
  672. }
  673. }
  674. auto st = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
  675. const cst = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
  676. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
  677. static assert(__traits(compiles, st == st));
  678. static assert(__traits(compiles, st == cst));
  679. //static assert(__traits(compiles, st == ist));
  680. static assert(__traits(compiles, cst == st));
  681. static assert(__traits(compiles, cst == cst));
  682. //static assert(__traits(compiles, cst == ist));
  683. //static assert(__traits(compiles, ist == st));
  684. //static assert(__traits(compiles, ist == cst));
  685. //static assert(__traits(compiles, ist == ist));
  686. }
  687. /++
  688. Compares this $(D SysTime) with the given $(D SysTime).
  689. Time zone is irrelevant when comparing $(D SysTime)s.
  690. Returns:
  691. $(BOOKTABLE,
  692. $(TR $(TD this &lt; rhs) $(TD &lt; 0))
  693. $(TR $(TD this == rhs) $(TD 0))
  694. $(TR $(TD this &gt; rhs) $(TD &gt; 0))
  695. )
  696. +/
  697. int opCmp(in SysTime rhs) const pure nothrow
  698. {
  699. if(_stdTime < rhs._stdTime)
  700. return -1;
  701. if(_stdTime > rhs._stdTime)
  702. return 1;
  703. return 0;
  704. }
  705. version(testStdDateTime) unittest
  706. {
  707. _assertPred!("opCmp", "==")(SysTime(DateTime.init, UTC()),
  708. SysTime(0, UTC()));
  709. _assertPred!("opCmp", "==")(SysTime(DateTime.init, UTC()), SysTime(0));
  710. _assertPred!("opCmp", "==")(SysTime(Date.init, UTC()), SysTime(0));
  711. _assertPred!("opCmp", "==")(SysTime(0), SysTime(0));
  712. static void testEqual(DateTime dt,
  713. immutable TimeZone tz1,
  714. immutable TimeZone tz2)
  715. {
  716. auto st1 = SysTime(dt);
  717. st1.timezone = tz1;
  718. auto st2 = SysTime(dt);
  719. st2.timezone = tz2;
  720. _assertPred!("opCmp", "==")(st1, st2);
  721. }
  722. foreach(dt; chain(testDateTimesBC, testDateTimesAD))
  723. {
  724. foreach(tz1; testTZs)
  725. {
  726. foreach(tz2; testTZs)
  727. testEqual(dt, tz1, tz2);
  728. }
  729. }
  730. static void testCmp(DateTime dt1,
  731. immutable TimeZone tz1,
  732. DateTime dt2,
  733. immutable TimeZone tz2)
  734. {
  735. auto st1 = SysTime(dt1);
  736. st1.timezone = tz1;
  737. auto st2 = SysTime(dt2);
  738. st2.timezone = tz2;
  739. _assertPred!("opCmp", "<")(st1, st2);
  740. _assertPred!("opCmp", ">")(st2, st1);
  741. }
  742. auto dts = testDateTimesBC ~ testDateTimesAD;
  743. foreach(tz1; testTZs)
  744. {
  745. foreach(tz2; testTZs)
  746. {
  747. for(size_t i = 0; i < dts.length; ++i)
  748. {
  749. for(size_t j = i + 1; j < dts.length; ++j)
  750. testCmp(dts[i], tz1, dts[j], tz2);
  751. }
  752. }
  753. }
  754. auto st = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
  755. const cst = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
  756. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
  757. static assert(__traits(compiles, st.opCmp(st)));
  758. static assert(__traits(compiles, st.opCmp(cst)));
  759. //static assert(__traits(compiles, st.opCmp(ist)));
  760. static assert(__traits(compiles, cst.opCmp(st)));
  761. static assert(__traits(compiles, cst.opCmp(cst)));
  762. //static assert(__traits(compiles, cst.opCmp(ist)));
  763. //static assert(__traits(compiles, ist.opCmp(st)));
  764. //static assert(__traits(compiles, ist.opCmp(cst)));
  765. //static assert(__traits(compiles, ist.opCmp(ist)));
  766. }
  767. /++
  768. Year of the Gregorian Calendar. Positive numbers are A.D. Non-positive
  769. are B.C.
  770. +/
  771. @property short year() const nothrow
  772. {
  773. return (cast(Date)this).year;
  774. }
  775. version(testStdDateTime) unittest
  776. {
  777. static void test(SysTime sysTime, long expected, size_t line = __LINE__)
  778. {
  779. _assertPred!"=="(sysTime.year, expected,
  780. format("Value given: %s", sysTime), __FILE__, line);
  781. }
  782. test(SysTime(0, UTC()), 1);
  783. test(SysTime(1, UTC()), 1);
  784. test(SysTime(-1, UTC()), 0);
  785. foreach(year; chain(testYearsBC, testYearsAD))
  786. {
  787. foreach(md; testMonthDays)
  788. {
  789. foreach(tod; testTODs)
  790. {
  791. auto dt = DateTime(Date(year, md.month, md.day), tod);
  792. foreach(tz; testTZs)
  793. {
  794. foreach(fs; testFracSecs)
  795. test(SysTime(dt, fs, tz), year);
  796. }
  797. }
  798. }
  799. }
  800. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  801. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  802. static assert(__traits(compiles, cst.year));
  803. //static assert(__traits(compiles, ist.year));
  804. }
  805. /++
  806. Year of the Gregorian Calendar. Positive numbers are A.D. Non-positive
  807. are B.C.
  808. Params:
  809. year = The year to set this $(D SysTime)'s year to.
  810. Throws:
  811. $(D DateTimeException) if the new year is not a leap year and the
  812. resulting date would be on February 29th.
  813. Examples:
  814. --------------------
  815. assert(SysTime(DateTime(1999, 7, 6, 9, 7, 5)).year == 1999);
  816. assert(SysTime(DateTime(2010, 10, 4, 0, 0, 30)).year == 2010);
  817. assert(SysTime(DateTime(-7, 4, 5, 7, 45, 2)).year == -7);
  818. --------------------
  819. +/
  820. @property void year(int year)
  821. {
  822. auto hnsecs = adjTime;
  823. auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
  824. if(hnsecs < 0)
  825. {
  826. hnsecs += convert!("hours", "hnsecs")(24);
  827. --days;
  828. }
  829. auto date = Date(cast(int)days);
  830. date.year = year;
  831. immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
  832. adjTime = newDaysHNSecs + hnsecs;
  833. }
  834. //Verify Examples.
  835. version(testStdDateTime) unittest
  836. {
  837. assert(SysTime(DateTime(1999, 7, 6, 9, 7, 5)).year == 1999);
  838. assert(SysTime(DateTime(2010, 10, 4, 0, 0, 30)).year == 2010);
  839. assert(SysTime(DateTime(-7, 4, 5, 7, 45, 2)).year == -7);
  840. }
  841. version(testStdDateTime) unittest
  842. {
  843. static void test(SysTime st, int year, in SysTime expected, size_t line = __LINE__)
  844. {
  845. st.year = year;
  846. _assertPred!"=="(st, expected, "", __FILE__, line);
  847. }
  848. foreach(st; chain(testSysTimesBC, testSysTimesAD))
  849. {
  850. auto dt = cast(DateTime)st;
  851. foreach(year; chain(testYearsBC, testYearsAD))
  852. {
  853. auto e = SysTime(DateTime(year, dt.month, dt.day, dt.hour, dt.minute, dt.second),
  854. st.fracSec,
  855. st.timezone);
  856. test(st, year, e);
  857. }
  858. }
  859. foreach(fs; testFracSecs)
  860. {
  861. foreach(tz; testTZs)
  862. {
  863. foreach(tod; testTODs)
  864. {
  865. test(SysTime(DateTime(Date(1999, 2, 28), tod), fs, tz), 2000,
  866. SysTime(DateTime(Date(2000, 2, 28), tod), fs, tz));
  867. test(SysTime(DateTime(Date(2000, 2, 28), tod), fs, tz), 1999,
  868. SysTime(DateTime(Date(1999, 2, 28), tod), fs, tz));
  869. }
  870. foreach(tod; testTODsThrown)
  871. {
  872. auto st = SysTime(DateTime(Date(2000, 2, 29), tod), fs, tz);
  873. assertThrown!DateTimeException(st.year = 1999);
  874. }
  875. }
  876. }
  877. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  878. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  879. static assert(!__traits(compiles, cst.year = 7));
  880. //static assert(!__traits(compiles, ist.year = 7));
  881. }
  882. /++
  883. Year B.C. of the Gregorian Calendar counting year 0 as 1 B.C.
  884. Throws:
  885. $(D DateTimeException) if $(D isAD) is true.
  886. Examples:
  887. --------------------
  888. assert(SysTime(DateTime(0, 1, 1, 12, 30, 33)).yearBC == 1);
  889. assert(SysTime(DateTime(-1, 1, 1, 10, 7, 2)).yearBC == 2);
  890. assert(SysTime(DateTime(-100, 1, 1, 4, 59, 0)).yearBC == 101);
  891. --------------------
  892. +/
  893. @property ushort yearBC() const
  894. {
  895. return (cast(Date)this).yearBC;
  896. }
  897. //Verify Examples.
  898. version(testStdDateTime) unittest
  899. {
  900. assert(SysTime(DateTime(0, 1, 1, 12, 30, 33)).yearBC == 1);
  901. assert(SysTime(DateTime(-1, 1, 1, 10, 7, 2)).yearBC == 2);
  902. assert(SysTime(DateTime(-100, 1, 1, 4, 59, 0)).yearBC == 101);
  903. }
  904. version(testStdDateTime) unittest
  905. {
  906. foreach(st; testSysTimesBC)
  907. {
  908. auto msg = format("SysTime: %s", st);
  909. assertNotThrown!DateTimeException(st.yearBC, msg);
  910. _assertPred!"=="(st.yearBC, (st.year * -1) + 1, msg);
  911. }
  912. foreach(st; [testSysTimesAD[0], testSysTimesAD[$/2], testSysTimesAD[$-1]])
  913. assertThrown!DateTimeException(st.yearBC, format("SysTime: %s", st));
  914. auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  915. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  916. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  917. static assert(__traits(compiles, st.year = 12));
  918. static assert(!__traits(compiles, cst.year = 12));
  919. //static assert(!__traits(compiles, ist.year = 12));
  920. }
  921. /++
  922. Year B.C. of the Gregorian Calendar counting year 0 as 1 B.C.
  923. Params:
  924. year = The year B.C. to set this $(D SysTime)'s year to.
  925. Throws:
  926. $(D DateTimeException) if a non-positive value is given.
  927. Examples:
  928. --------------------
  929. auto st = SysTime(DateTime(2010, 1, 1, 7, 30, 0));
  930. st.yearBC = 1;
  931. assert(st == SysTime(DateTime(0, 1, 1, 7, 30, 0)));
  932. st.yearBC = 10;
  933. assert(st == SysTime(DateTime(-9, 1, 1, 7, 30, 0)));
  934. --------------------
  935. +/
  936. @property void yearBC(int year)
  937. {
  938. auto hnsecs = adjTime;
  939. auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
  940. if(hnsecs < 0)
  941. {
  942. hnsecs += convert!("hours", "hnsecs")(24);
  943. --days;
  944. }
  945. auto date = Date(cast(int)days);
  946. date.yearBC = year;
  947. immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
  948. adjTime = newDaysHNSecs + hnsecs;
  949. }
  950. //Verify Examples
  951. version(testStdDateTime) unittest
  952. {
  953. auto st = SysTime(DateTime(2010, 1, 1, 7, 30, 0));
  954. st.yearBC = 1;
  955. assert(st == SysTime(DateTime(0, 1, 1, 7, 30, 0)));
  956. st.yearBC = 10;
  957. assert(st == SysTime(DateTime(-9, 1, 1, 7, 30, 0)));
  958. }
  959. version(testStdDateTime) unittest
  960. {
  961. static void test(SysTime st, int year, in SysTime expected, size_t line = __LINE__)
  962. {
  963. st.yearBC = year;
  964. _assertPred!"=="(st, expected, format("SysTime: %s", st), __FILE__, line);
  965. }
  966. foreach(st; chain(testSysTimesBC, testSysTimesAD))
  967. {
  968. auto dt = cast(DateTime)st;
  969. foreach(year; testYearsBC)
  970. {
  971. auto e = SysTime(DateTime(year, dt.month, dt.day, dt.hour, dt.minute, dt.second),
  972. st.fracSec,
  973. st.timezone);
  974. test(st, (year * -1) + 1, e);
  975. }
  976. }
  977. foreach(st; [testSysTimesBC[0], testSysTimesBC[$ - 1],
  978. testSysTimesAD[0], testSysTimesAD[$ - 1]])
  979. {
  980. foreach(year; testYearsBC)
  981. assertThrown!DateTimeException(st.yearBC = year);
  982. }
  983. foreach(fs; testFracSecs)
  984. {
  985. foreach(tz; testTZs)
  986. {
  987. foreach(tod; testTODs)
  988. {
  989. test(SysTime(DateTime(Date(-1999, 2, 28), tod), fs, tz), 2001,
  990. SysTime(DateTime(Date(-2000, 2, 28), tod), fs, tz));
  991. test(SysTime(DateTime(Date(-2000, 2, 28), tod), fs, tz), 2000,
  992. SysTime(DateTime(Date(-1999, 2, 28), tod), fs, tz));
  993. }
  994. foreach(tod; testTODsThrown)
  995. {
  996. auto st = SysTime(DateTime(Date(-2000, 2, 29), tod), fs, tz);
  997. assertThrown!DateTimeException(st.year = -1999);
  998. }
  999. }
  1000. }
  1001. auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1002. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1003. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1004. static assert(__traits(compiles, st.yearBC = 12));
  1005. static assert(!__traits(compiles, cst.yearBC = 12));
  1006. //static assert(!__traits(compiles, ist.yearBC = 12));
  1007. }
  1008. /++
  1009. Month of a Gregorian Year.
  1010. Examples:
  1011. --------------------
  1012. assert(SysTime(DateTime(1999, 7, 6, 9, 7, 5)).month == 7);
  1013. assert(SysTime(DateTime(2010, 10, 4, 0, 0, 30)).month == 10);
  1014. assert(SysTime(DateTime(-7, 4, 5, 7, 45, 2)).month == 4);
  1015. --------------------
  1016. +/
  1017. @property Month month() const nothrow
  1018. {
  1019. return (cast(Date)this).month;
  1020. }
  1021. //Verify Examples.
  1022. version(testStdDateTime) unittest
  1023. {
  1024. assert(SysTime(DateTime(1999, 7, 6, 9, 7, 5)).month == 7);
  1025. assert(SysTime(DateTime(2010, 10, 4, 0, 0, 30)).month == 10);
  1026. assert(SysTime(DateTime(-7, 4, 5, 7, 45, 2)).month == 4);
  1027. }
  1028. version(testStdDateTime) unittest
  1029. {
  1030. static void test(SysTime sysTime, Month expected, size_t line = __LINE__)
  1031. {
  1032. _assertPred!"=="(sysTime.month, expected,
  1033. format("Value given: %s", sysTime), __FILE__, line);
  1034. }
  1035. test(SysTime(0, UTC()), Month.jan);
  1036. test(SysTime(1, UTC()), Month.jan);
  1037. test(SysTime(-1, UTC()), Month.dec);
  1038. foreach(year; chain(testYearsBC, testYearsAD))
  1039. {
  1040. foreach(md; testMonthDays)
  1041. {
  1042. foreach(tod; testTODs)
  1043. {
  1044. auto dt = DateTime(Date(year, md.month, md.day), tod);
  1045. foreach(fs; testFracSecs)
  1046. {
  1047. foreach(tz; testTZs)
  1048. test(SysTime(dt, fs, tz), md.month);
  1049. }
  1050. }
  1051. }
  1052. }
  1053. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1054. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1055. static assert(__traits(compiles, cst.month));
  1056. //static assert(__traits(compiles, ist.month));
  1057. }
  1058. /++
  1059. Month of a Gregorian Year.
  1060. Params:
  1061. month = The month to set this $(D SysTime)'s month to.
  1062. Throws:
  1063. $(D DateTimeException) if the given month is not a valid month.
  1064. +/
  1065. @property void month(Month month)
  1066. {
  1067. auto hnsecs = adjTime;
  1068. auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
  1069. if(hnsecs < 0)
  1070. {
  1071. hnsecs += convert!("hours", "hnsecs")(24);
  1072. --days;
  1073. }
  1074. auto date = Date(cast(int)days);
  1075. date.month = month;
  1076. immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
  1077. adjTime = newDaysHNSecs + hnsecs;
  1078. }
  1079. version(testStdDateTime) unittest
  1080. {
  1081. static void test(SysTime st, Month month, in SysTime expected, size_t line = __LINE__)
  1082. {
  1083. st.month = cast(Month)month;
  1084. _assertPred!"=="(st, expected, "", __FILE__, line);
  1085. }
  1086. foreach(st; chain(testSysTimesBC, testSysTimesAD))
  1087. {
  1088. auto dt = cast(DateTime)st;
  1089. foreach(md; testMonthDays)
  1090. {
  1091. if(st.day > maxDay(dt.year, md.month))
  1092. continue;
  1093. auto e = SysTime(DateTime(dt.year, md.month, dt.day, dt.hour, dt.minute, dt.second),
  1094. st.fracSec,
  1095. st.timezone);
  1096. test(st, md.month, e);
  1097. }
  1098. }
  1099. foreach(fs; testFracSecs)
  1100. {
  1101. foreach(tz; testTZs)
  1102. {
  1103. foreach(tod; testTODs)
  1104. {
  1105. foreach(year; filter!((a){return yearIsLeapYear(a);})
  1106. (chain(testYearsBC, testYearsAD)))
  1107. {
  1108. test(SysTime(DateTime(Date(year, 1, 29), tod), fs, tz),
  1109. Month.feb,
  1110. SysTime(DateTime(Date(year, 2, 29), tod), fs, tz));
  1111. }
  1112. foreach(year; chain(testYearsBC, testYearsAD))
  1113. {
  1114. test(SysTime(DateTime(Date(year, 1, 28), tod), fs, tz),
  1115. Month.feb,
  1116. SysTime(DateTime(Date(year, 2, 28), tod), fs, tz));
  1117. test(SysTime(DateTime(Date(year, 7, 30), tod), fs, tz),
  1118. Month.jun,
  1119. SysTime(DateTime(Date(year, 6, 30), tod), fs, tz));
  1120. }
  1121. }
  1122. }
  1123. }
  1124. foreach(fs; [testFracSecs[0], testFracSecs[$-1]])
  1125. {
  1126. foreach(tz; testTZs)
  1127. {
  1128. foreach(tod; testTODsThrown)
  1129. {
  1130. foreach(year; [testYearsBC[$-3], testYearsBC[$-2],
  1131. testYearsBC[$-2], testYearsAD[0],
  1132. testYearsAD[$-2], testYearsAD[$-1]])
  1133. {
  1134. auto day = yearIsLeapYear(year) ? 30 : 29;
  1135. auto st1 = SysTime(DateTime(Date(year, 1, day), tod), fs, tz);
  1136. assertThrown!DateTimeException(st1.month = Month.feb);
  1137. auto st2 = SysTime(DateTime(Date(year, 7, 31), tod), fs, tz);
  1138. assertThrown!DateTimeException(st2.month = Month.jun);
  1139. }
  1140. }
  1141. }
  1142. }
  1143. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1144. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1145. static assert(!__traits(compiles, cst.month = 12));
  1146. //static assert(!__traits(compiles, ist.month = 12));
  1147. }
  1148. /++
  1149. Day of a Gregorian Month.
  1150. Examples:
  1151. --------------------
  1152. assert(SysTime(DateTime(1999, 7, 6, 9, 7, 5)).day == 6);
  1153. assert(SysTime(DateTime(2010, 10, 4, 0, 0, 30)).day == 4);
  1154. assert(SysTime(DateTime(-7, 4, 5, 7, 45, 2)).day == 5);
  1155. --------------------
  1156. +/
  1157. @property ubyte day() const nothrow
  1158. {
  1159. return (cast(Date)this).day;
  1160. }
  1161. //Verify Examples.
  1162. version(testStdDateTime) unittest
  1163. {
  1164. assert(SysTime(DateTime(1999, 7, 6, 9, 7, 5)).day == 6);
  1165. assert(SysTime(DateTime(2010, 10, 4, 0, 0, 30)).day == 4);
  1166. assert(SysTime(DateTime(-7, 4, 5, 7, 45, 2)).day == 5);
  1167. }
  1168. version(testStdDateTime) unittest
  1169. {
  1170. static void test(SysTime sysTime, int expected, size_t line = __LINE__)
  1171. {
  1172. _assertPred!"=="(sysTime.day, expected,
  1173. format("Value given: %s", sysTime), __FILE__, line);
  1174. }
  1175. test(SysTime(0, UTC()), 1);
  1176. test(SysTime(1, UTC()), 1);
  1177. test(SysTime(-1, UTC()), 31);
  1178. foreach(year; chain(testYearsBC, testYearsAD))
  1179. {
  1180. foreach(md; testMonthDays)
  1181. {
  1182. foreach(tod; testTODs)
  1183. {
  1184. auto dt = DateTime(Date(year, md.month, md.day), tod);
  1185. foreach(tz; testTZs)
  1186. {
  1187. foreach(fs; testFracSecs)
  1188. test(SysTime(dt, fs, tz), md.day);
  1189. }
  1190. }
  1191. }
  1192. }
  1193. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1194. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1195. static assert(__traits(compiles, cst.day));
  1196. //static assert(__traits(compiles, ist.day));
  1197. }
  1198. /++
  1199. Day of a Gregorian Month.
  1200. Params:
  1201. day = The day of the month to set this $(D SysTime)'s day to.
  1202. Throws:
  1203. $(D DateTimeException) if the given day is not a valid day of the
  1204. current month.
  1205. +/
  1206. @property void day(int day)
  1207. {
  1208. auto hnsecs = adjTime;
  1209. auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
  1210. if(hnsecs < 0)
  1211. {
  1212. hnsecs += convert!("hours", "hnsecs")(24);
  1213. --days;
  1214. }
  1215. auto date = Date(cast(int)days);
  1216. date.day = day;
  1217. immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
  1218. adjTime = newDaysHNSecs + hnsecs;
  1219. }
  1220. version(testStdDateTime) unittest
  1221. {
  1222. static void test(SysTime st, int day, in SysTime expected, size_t line = __LINE__)
  1223. {
  1224. st.day = day;
  1225. _assertPred!"=="(st, expected, "", __FILE__, line);
  1226. }
  1227. foreach(day; chain(testDays))
  1228. {
  1229. foreach(st; chain(testSysTimesBC, testSysTimesAD))
  1230. {
  1231. auto dt = cast(DateTime)st;
  1232. if(day > maxDay(dt.year, dt.month))
  1233. continue;
  1234. auto e = SysTime(DateTime(dt.year, dt.month, day, dt.hour, dt.minute, dt.second),
  1235. st.fracSec,
  1236. st.timezone);
  1237. test(st, day, e);
  1238. }
  1239. }
  1240. foreach(tz; testTZs)
  1241. {
  1242. foreach(tod; testTODs)
  1243. {
  1244. foreach(fs; testFracSecs)
  1245. {
  1246. foreach(year; chain(testYearsBC, testYearsAD))
  1247. {
  1248. foreach(month; EnumMembers!Month)
  1249. {
  1250. auto st = SysTime(DateTime(Date(year, month, 1), tod), fs, tz);
  1251. immutable max = maxDay(year, month);
  1252. test(st, max, SysTime(DateTime(Date(year, month, max), tod), fs, tz));
  1253. }
  1254. }
  1255. }
  1256. }
  1257. }
  1258. foreach(tz; testTZs)
  1259. {
  1260. foreach(tod; testTODsThrown)
  1261. {
  1262. foreach(fs; [testFracSecs[0], testFracSecs[$-1]])
  1263. {
  1264. foreach(year; [testYearsBC[$-3], testYearsBC[$-2],
  1265. testYearsBC[$-2], testYearsAD[0],
  1266. testYearsAD[$-2], testYearsAD[$-1]])
  1267. {
  1268. foreach(month; EnumMembers!Month)
  1269. {
  1270. auto st = SysTime(DateTime(Date(year, month, 1), tod), fs, tz);
  1271. immutable max = maxDay(year, month);
  1272. assertThrown!DateTimeException(st.day = max + 1);
  1273. }
  1274. }
  1275. }
  1276. }
  1277. }
  1278. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1279. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1280. static assert(!__traits(compiles, cst.day = 27));
  1281. //static assert(!__traits(compiles, ist.day = 27));
  1282. }
  1283. /++
  1284. Hours past midnight.
  1285. +/
  1286. @property ubyte hour() const nothrow
  1287. {
  1288. auto hnsecs = adjTime;
  1289. auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
  1290. if(hnsecs < 0)
  1291. {
  1292. hnsecs += convert!("hours", "hnsecs")(24);
  1293. --days;
  1294. }
  1295. return cast(ubyte)getUnitsFromHNSecs!"hours"(hnsecs);
  1296. }
  1297. version(testStdDateTime) unittest
  1298. {
  1299. static void test(SysTime sysTime, int expected, size_t line = __LINE__)
  1300. {
  1301. _assertPred!"=="(sysTime.hour, expected,
  1302. format("Value given: %s", sysTime), __FILE__, line);
  1303. }
  1304. test(SysTime(0, UTC()), 0);
  1305. test(SysTime(1, UTC()), 0);
  1306. test(SysTime(-1, UTC()), 23);
  1307. foreach(tz; testTZs)
  1308. {
  1309. foreach(year; chain(testYearsBC, testYearsAD))
  1310. {
  1311. foreach(md; testMonthDays)
  1312. {
  1313. foreach(hour; testHours)
  1314. {
  1315. foreach(minute; testMinSecs)
  1316. {
  1317. foreach(second; testMinSecs)
  1318. {
  1319. auto dt = DateTime(Date(year, md.month, md.day),
  1320. TimeOfDay(hour, minute, second));
  1321. foreach(fs; testFracSecs)
  1322. test(SysTime(dt, fs, tz), hour);
  1323. }
  1324. }
  1325. }
  1326. }
  1327. }
  1328. }
  1329. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1330. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1331. static assert(__traits(compiles, cst.hour));
  1332. //static assert(__traits(compiles, ist.hour));
  1333. }
  1334. /++
  1335. Hours past midnight.
  1336. Params:
  1337. hour = The hours to set this $(D SysTime)'s hour to.
  1338. Throws:
  1339. $(D DateTimeException) if the given hour are not a valid hour of
  1340. the day.
  1341. +/
  1342. @property void hour(int hour)
  1343. {
  1344. enforceValid!"hours"(hour);
  1345. auto hnsecs = adjTime;
  1346. auto days = splitUnitsFromHNSecs!"days"(hnsecs);
  1347. immutable daysHNSecs = convert!("days", "hnsecs")(days);
  1348. immutable negative = hnsecs < 0;
  1349. if(negative)
  1350. hnsecs += convert!("hours", "hnsecs")(24);
  1351. hnsecs = removeUnitsFromHNSecs!"hours"(hnsecs);
  1352. hnsecs += convert!("hours", "hnsecs")(hour);
  1353. if(negative)
  1354. hnsecs -= convert!("hours", "hnsecs")(24);
  1355. adjTime = daysHNSecs + hnsecs;
  1356. }
  1357. version(testStdDateTime) unittest
  1358. {
  1359. static void test(SysTime st, int hour, in SysTime expected,
  1360. size_t line = __LINE__)
  1361. {
  1362. st.hour = hour;
  1363. _assertPred!"=="(st, expected, "", __FILE__, line);
  1364. }
  1365. foreach(hour; chain(testHours))
  1366. {
  1367. foreach(st; chain(testSysTimesBC, testSysTimesAD))
  1368. {
  1369. auto dt = cast(DateTime)st;
  1370. auto e = SysTime(DateTime(dt.year, dt.month, dt.day, hour, dt.minute, dt.second),
  1371. st.fracSec,
  1372. st.timezone);
  1373. test(st, hour, e);
  1374. }
  1375. }
  1376. auto st = testSysTimesAD[0];
  1377. assertThrown!DateTimeException(st.hour = -1);
  1378. assertThrown!DateTimeException(st.hour = 60);
  1379. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1380. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1381. static assert(!__traits(compiles, cst.hour = 27));
  1382. //static assert(!__traits(compiles, ist.hour = 27));
  1383. }
  1384. /++
  1385. Minutes past the current hour.
  1386. +/
  1387. @property ubyte minute() const nothrow
  1388. {
  1389. auto hnsecs = adjTime;
  1390. auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
  1391. if(hnsecs < 0)
  1392. {
  1393. hnsecs += convert!("hours", "hnsecs")(24);
  1394. --days;
  1395. }
  1396. hnsecs = removeUnitsFromHNSecs!"hours"(hnsecs);
  1397. return cast(ubyte)getUnitsFromHNSecs!"minutes"(hnsecs);
  1398. }
  1399. version(testStdDateTime) unittest
  1400. {
  1401. static void test(SysTime sysTime, int expected, size_t line = __LINE__)
  1402. {
  1403. _assertPred!"=="(sysTime.minute, expected,
  1404. format("Value given: %s", sysTime), __FILE__, line);
  1405. }
  1406. test(SysTime(0, UTC()), 0);
  1407. test(SysTime(1, UTC()), 0);
  1408. test(SysTime(-1, UTC()), 59);
  1409. foreach(tz; testTZs)
  1410. {
  1411. foreach(year; chain(testYearsBC, testYearsAD))
  1412. {
  1413. foreach(md; testMonthDays)
  1414. {
  1415. foreach(hour; testHours)
  1416. {
  1417. foreach(minute; testMinSecs)
  1418. {
  1419. foreach(second; testMinSecs)
  1420. {
  1421. auto dt = DateTime(Date(year, md.month, md.day),
  1422. TimeOfDay(hour, minute, second));
  1423. foreach(fs; testFracSecs)
  1424. test(SysTime(dt, fs, tz), minute);
  1425. }
  1426. }
  1427. }
  1428. }
  1429. }
  1430. }
  1431. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1432. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1433. static assert(__traits(compiles, cst.minute));
  1434. //static assert(__traits(compiles, ist.minute));
  1435. }
  1436. /++
  1437. Minutes past the current hour.
  1438. Params:
  1439. minutes = The minute to set this $(D SysTime)'s minute to.
  1440. Throws:
  1441. $(D DateTimeException) if the given minute are not a valid minute
  1442. of an hour.
  1443. +/
  1444. @property void minute(int minute)
  1445. {
  1446. enforceValid!"minutes"(minute);
  1447. auto hnsecs = adjTime;
  1448. auto days = splitUnitsFromHNSecs!"days"(hnsecs);
  1449. immutable daysHNSecs = convert!("days", "hnsecs")(days);
  1450. immutable negative = hnsecs < 0;
  1451. if(negative)
  1452. hnsecs += convert!("hours", "hnsecs")(24);
  1453. immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
  1454. hnsecs = removeUnitsFromHNSecs!"minutes"(hnsecs);
  1455. hnsecs += convert!("hours", "hnsecs")(hour);
  1456. hnsecs += convert!("minutes", "hnsecs")(minute);
  1457. if(negative)
  1458. hnsecs -= convert!("hours", "hnsecs")(24);
  1459. adjTime = daysHNSecs + hnsecs;
  1460. }
  1461. version(testStdDateTime) unittest
  1462. {
  1463. static void test(SysTime st, int minute, in SysTime expected, size_t line = __LINE__)
  1464. {
  1465. st.minute = minute;
  1466. _assertPred!"=="(st, expected, "", __FILE__, line);
  1467. }
  1468. foreach(minute; testMinSecs)
  1469. {
  1470. foreach(st; chain(testSysTimesBC, testSysTimesAD))
  1471. {
  1472. auto dt = cast(DateTime)st;
  1473. auto e = SysTime(DateTime(dt.year, dt.month, dt.day, dt.hour, minute, dt.second),
  1474. st.fracSec,
  1475. st.timezone);
  1476. test(st, minute, e);
  1477. }
  1478. }
  1479. auto st = testSysTimesAD[0];
  1480. assertThrown!DateTimeException(st.minute = -1);
  1481. assertThrown!DateTimeException(st.minute = 60);
  1482. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1483. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1484. static assert(!__traits(compiles, cst.minute = 27));
  1485. //static assert(!__traits(compiles, ist.minute = 27));
  1486. }
  1487. /++
  1488. Seconds past the current minute.
  1489. +/
  1490. @property ubyte second() const nothrow
  1491. {
  1492. auto hnsecs = adjTime;
  1493. auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
  1494. if(hnsecs < 0)
  1495. {
  1496. hnsecs += convert!("hours", "hnsecs")(24);
  1497. --days;
  1498. }
  1499. hnsecs = removeUnitsFromHNSecs!"hours"(hnsecs);
  1500. hnsecs = removeUnitsFromHNSecs!"minutes"(hnsecs);
  1501. return cast(ubyte)getUnitsFromHNSecs!"seconds"(hnsecs);
  1502. }
  1503. version(testStdDateTime) unittest
  1504. {
  1505. static void test(SysTime sysTime, int expected, size_t line = __LINE__)
  1506. {
  1507. _assertPred!"=="(sysTime.second, expected,
  1508. format("Value given: %s", sysTime), __FILE__, line);
  1509. }
  1510. test(SysTime(0, UTC()), 0);
  1511. test(SysTime(1, UTC()), 0);
  1512. test(SysTime(-1, UTC()), 59);
  1513. foreach(tz; testTZs)
  1514. {
  1515. foreach(year; chain(testYearsBC, testYearsAD))
  1516. {
  1517. foreach(md; testMonthDays)
  1518. {
  1519. foreach(hour; testHours)
  1520. {
  1521. foreach(minute; testMinSecs)
  1522. {
  1523. foreach(second; testMinSecs)
  1524. {
  1525. auto dt = DateTime(Date(year, md.month, md.day),
  1526. TimeOfDay(hour, minute, second));
  1527. foreach(fs; testFracSecs)
  1528. test(SysTime(dt, fs, tz), second);
  1529. }
  1530. }
  1531. }
  1532. }
  1533. }
  1534. }
  1535. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1536. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1537. static assert(__traits(compiles, cst.second));
  1538. //static assert(__traits(compiles, ist.second));
  1539. }
  1540. /++
  1541. Seconds past the current minute.
  1542. Params:
  1543. second = The second to set this $(D SysTime)'s second to.
  1544. Throws:
  1545. $(D DateTimeException) if the given second are not a valid second
  1546. of a minute.
  1547. +/
  1548. @property void second(int second)
  1549. {
  1550. enforceValid!"seconds"(second);
  1551. auto hnsecs = adjTime;
  1552. auto days = splitUnitsFromHNSecs!"days"(hnsecs);
  1553. immutable daysHNSecs = convert!("days", "hnsecs")(days);
  1554. immutable negative = hnsecs < 0;
  1555. if(negative)
  1556. hnsecs += convert!("hours", "hnsecs")(24);
  1557. immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
  1558. immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
  1559. hnsecs = removeUnitsFromHNSecs!"seconds"(hnsecs);
  1560. hnsecs += convert!("hours", "hnsecs")(hour);
  1561. hnsecs += convert!("minutes", "hnsecs")(minute);
  1562. hnsecs += convert!("seconds", "hnsecs")(second);
  1563. if(negative)
  1564. hnsecs -= convert!("hours", "hnsecs")(24);
  1565. adjTime = daysHNSecs + hnsecs;
  1566. }
  1567. version(testStdDateTime) unittest
  1568. {
  1569. static void test(SysTime st, int second, in SysTime expected,
  1570. size_t line = __LINE__)
  1571. {
  1572. st.second = second;
  1573. _assertPred!"=="(st, expected, "", __FILE__, line);
  1574. }
  1575. foreach(second; testMinSecs)
  1576. {
  1577. foreach(st; chain(testSysTimesBC, testSysTimesAD))
  1578. {
  1579. auto dt = cast(DateTime)st;
  1580. auto e = SysTime(DateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute, second),
  1581. st.fracSec,
  1582. st.timezone);
  1583. test(st, second, e);
  1584. }
  1585. }
  1586. auto st = testSysTimesAD[0];
  1587. assertThrown!DateTimeException(st.second = -1);
  1588. assertThrown!DateTimeException(st.second = 60);
  1589. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1590. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1591. static assert(!__traits(compiles, cst.seconds = 27));
  1592. //static assert(!__traits(compiles, ist.seconds = 27));
  1593. }
  1594. /++
  1595. Fractional seconds passed the second.
  1596. +/
  1597. @property FracSec fracSec() const nothrow
  1598. {
  1599. try
  1600. {
  1601. auto hnsecs = removeUnitsFromHNSecs!"days"(adjTime);
  1602. if(hnsecs < 0)
  1603. hnsecs += convert!("hours", "hnsecs")(24);
  1604. hnsecs = removeUnitsFromHNSecs!"seconds"(hnsecs);
  1605. return FracSec.from!"hnsecs"(cast(int)hnsecs);
  1606. }
  1607. catch(Exception e)
  1608. assert(0, "FracSec.from!\"hnsecs\"() threw.");
  1609. }
  1610. version(testStdDateTime) unittest
  1611. {
  1612. static void test(SysTime sysTime, FracSec expected, size_t line = __LINE__)
  1613. {
  1614. _assertPred!"=="(sysTime.fracSec, expected,
  1615. format("Value given: %s", sysTime), __FILE__, line);
  1616. }
  1617. test(SysTime(0, UTC()), FracSec.from!"hnsecs"(0));
  1618. test(SysTime(1, UTC()), FracSec.from!"hnsecs"(1));
  1619. test(SysTime(-1, UTC()), FracSec.from!"hnsecs"(9_999_999));
  1620. foreach(tz; testTZs)
  1621. {
  1622. foreach(year; chain(testYearsBC, testYearsAD))
  1623. {
  1624. foreach(md; testMonthDays)
  1625. {
  1626. foreach(hour; testHours)
  1627. {
  1628. foreach(minute; testMinSecs)
  1629. {
  1630. foreach(second; testMinSecs)
  1631. {
  1632. auto dt = DateTime(Date(year, md.month, md.day),
  1633. TimeOfDay(hour, minute, second));
  1634. foreach(fs; testFracSecs)
  1635. test(SysTime(dt, fs, tz), fs);
  1636. }
  1637. }
  1638. }
  1639. }
  1640. }
  1641. }
  1642. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1643. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1644. static assert(__traits(compiles, cst.fracSec));
  1645. //static assert(__traits(compiles, ist.fracSec));
  1646. }
  1647. /++
  1648. Fractional seconds passed the second.
  1649. Params:
  1650. fracSec = The fractional seconds to set this $(D SysTimes)'s
  1651. fractional seconds to.
  1652. Throws:
  1653. $(D DateTimeException) if $(D fracSec) is negative.
  1654. +/
  1655. @property void fracSec(FracSec fracSec)
  1656. {
  1657. immutable fracHNSecs = fracSec.hnsecs;
  1658. enforce(fracHNSecs >= 0, new DateTimeException("A SysTime cannot have negative fractional seconds."));
  1659. auto hnsecs = adjTime;
  1660. auto days = splitUnitsFromHNSecs!"days"(hnsecs);
  1661. immutable daysHNSecs = convert!("days", "hnsecs")(days);
  1662. immutable negative = hnsecs < 0;
  1663. if(negative)
  1664. hnsecs += convert!("hours", "hnsecs")(24);
  1665. immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
  1666. immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
  1667. immutable second = getUnitsFromHNSecs!"seconds"(hnsecs);
  1668. hnsecs = fracHNSecs;
  1669. hnsecs += convert!("hours", "hnsecs")(hour);
  1670. hnsecs += convert!("minutes", "hnsecs")(minute);
  1671. hnsecs += convert!("seconds", "hnsecs")(second);
  1672. if(negative)
  1673. hnsecs -= convert!("hours", "hnsecs")(24);
  1674. adjTime = daysHNSecs + hnsecs;
  1675. }
  1676. version(testStdDateTime) unittest
  1677. {
  1678. static void test(SysTime st, FracSec fracSec, in SysTime expected, size_t line = __LINE__)
  1679. {
  1680. st.fracSec = fracSec;
  1681. _assertPred!"=="(st, expected, "", __FILE__, line);
  1682. }
  1683. foreach(fracSec; testFracSecs)
  1684. {
  1685. foreach(st; chain(testSysTimesBC, testSysTimesAD))
  1686. {
  1687. auto dt = cast(DateTime)st;
  1688. auto e = SysTime(DateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second),
  1689. fracSec,
  1690. st.timezone);
  1691. test(st, fracSec, e);
  1692. }
  1693. }
  1694. SysTime st = SysTime(DateTime(2011, 7, 11, 2, 51, 27));
  1695. assertThrown!DateTimeException(st.fracSec = FracSec.from!"hnsecs"(-1));
  1696. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1697. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1698. static assert(!__traits(compiles, cst.fracSec = FracSec.from!"msecs"(7)));
  1699. //static assert(!__traits(compiles, ist.fracSec = FracSec.from!"msecs"(7)));
  1700. }
  1701. /++
  1702. The total hnsecs from midnight, January 1st, 1 A.D. UTC. This is the
  1703. internal representation of $(D SysTime).
  1704. +/
  1705. @property long stdTime() const pure nothrow
  1706. {
  1707. return _stdTime;
  1708. }
  1709. version(testStdDateTime) unittest
  1710. {
  1711. _assertPred!"=="(SysTime(0).stdTime, 0);
  1712. _assertPred!"=="(SysTime(1).stdTime, 1);
  1713. _assertPred!"=="(SysTime(-1).stdTime, -1);
  1714. _assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 33), FracSec.from!"hnsecs"(502), UTC()).stdTime,
  1715. 330000502L);
  1716. _assertPred!"=="(SysTime(DateTime(1970, 1, 1, 0, 0, 0), UTC()).stdTime,
  1717. 621355968000000000L);
  1718. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1719. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1720. static assert(__traits(compiles, cst.stdTime));
  1721. //static assert(__traits(compiles, ist.stdTime));
  1722. }
  1723. /++
  1724. The total hnsecs from midnight, January 1st, 1 A.D. UTC. This is the
  1725. internal representation of $(D SysTime).
  1726. Params:
  1727. stdTime = The number of hnsecs since January 1st, 1 A.D. UTC.
  1728. +/
  1729. @property void stdTime(long stdTime) pure nothrow
  1730. {
  1731. _stdTime = stdTime;
  1732. }
  1733. version(testStdDateTime) unittest
  1734. {
  1735. static void test(long stdTime, in SysTime expected, size_t line = __LINE__)
  1736. {
  1737. auto st = SysTime(0, UTC());
  1738. st.stdTime = stdTime;
  1739. _assertPred!"=="(st, expected);
  1740. }
  1741. test(0, SysTime(Date(1, 1, 1), UTC()));
  1742. test(1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1), UTC()));
  1743. test(-1, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999), UTC()));
  1744. test(330_000_502L, SysTime(DateTime(1, 1, 1, 0, 0, 33), FracSec.from!"hnsecs"(502), UTC()));
  1745. test(621_355_968_000_000_000L, SysTime(DateTime(1970, 1, 1, 0, 0, 0), UTC()));
  1746. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1747. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  1748. static assert(!__traits(compiles, cst.stdTime = 27));
  1749. //static assert(!__traits(compiles, ist.stdTime = 27));
  1750. }
  1751. /++
  1752. The current time zone of this $(D SysTime). Its internal time is always
  1753. kept in UTC, so there are no conversion issues between time zones due to
  1754. DST. Functions which return all or part of the time - such as hours -
  1755. adjust the time to this $(D SysTime)'s time zone before returning.
  1756. +/
  1757. @property immutable(TimeZone) timezone() const pure nothrow
  1758. {
  1759. return _timezone;
  1760. }
  1761. /++
  1762. The current time zone of this $(D SysTime). It's internal time is always
  1763. kept in UTC, so there are no conversion issues between time zones due to
  1764. DST. Functions which return all or part of the time - such as hours -
  1765. adjust the time to this $(D SysTime)'s time zone before returning.
  1766. Params:
  1767. tz = The $(D TimeZone) to set this $(D SysTime)'s time zone to.
  1768. +/
  1769. @property void timezone(immutable TimeZone timezone) pure nothrow
  1770. {
  1771. if(timezone is null)
  1772. _timezone = LocalTime();
  1773. else
  1774. _timezone = timezone;
  1775. }
  1776. /++
  1777. Returns whether DST is in effect for this $(D SysTime).
  1778. +/
  1779. @property bool dstInEffect() const nothrow
  1780. {
  1781. return _timezone.dstInEffect(_stdTime);
  1782. //This function's unit testing is done in the time zone classes.
  1783. }
  1784. /++
  1785. Returns a $(D SysTime) with the same std time as this one, but with
  1786. $(D LocalTime) as its time zone.
  1787. +/
  1788. SysTime toLocalTime() const nothrow
  1789. {
  1790. return SysTime(_stdTime, LocalTime());
  1791. }
  1792. unittest
  1793. {
  1794. version(testStdDateTime)
  1795. {
  1796. {
  1797. auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), FracSec.from!"hnsecs"(27));
  1798. _assertPred!"=="(sysTime, sysTime.toLocalTime());
  1799. _assertPred!"=="(sysTime._stdTime, sysTime.toLocalTime()._stdTime);
  1800. assert(sysTime.toLocalTime().timezone is LocalTime());
  1801. assert(sysTime.toLocalTime().timezone is sysTime.timezone);
  1802. assert(sysTime.toLocalTime().timezone !is UTC());
  1803. }
  1804. {
  1805. immutable stz = new SimpleTimeZone(-3 * 60);
  1806. auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), FracSec.from!"hnsecs"(27), stz);
  1807. _assertPred!"=="(sysTime, sysTime.toLocalTime());
  1808. _assertPred!"=="(sysTime._stdTime, sysTime.toLocalTime()._stdTime);
  1809. assert(sysTime.toLocalTime().timezone is LocalTime());
  1810. assert(sysTime.toLocalTime().timezone !is UTC());
  1811. assert(sysTime.toLocalTime().timezone !is stz);
  1812. }
  1813. }
  1814. }
  1815. /++
  1816. Returns a $(D SysTime) with the same std time as this one, but with
  1817. $(D UTC) as its time zone.
  1818. +/
  1819. SysTime toUTC() const pure nothrow
  1820. {
  1821. return SysTime(_stdTime, UTC());
  1822. }
  1823. unittest
  1824. {
  1825. version(testStdDateTime)
  1826. {
  1827. auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), FracSec.from!"hnsecs"(27));
  1828. _assertPred!"=="(sysTime, sysTime.toUTC());
  1829. _assertPred!"=="(sysTime._stdTime, sysTime.toUTC()._stdTime);
  1830. assert(sysTime.toUTC().timezone is UTC());
  1831. assert(sysTime.toUTC().timezone !is LocalTime());
  1832. assert(sysTime.toUTC().timezone !is sysTime.timezone);
  1833. }
  1834. }
  1835. /++
  1836. Returns a $(D SysTime) with the same std time as this one, but with
  1837. given time zone as its time zone.
  1838. +/
  1839. SysTime toOtherTZ(immutable TimeZone tz) const pure nothrow
  1840. {
  1841. if(tz is null)
  1842. return SysTime(_stdTime, LocalTime());
  1843. else
  1844. return SysTime(_stdTime, tz);
  1845. }
  1846. unittest
  1847. {
  1848. version(testStdDateTime)
  1849. {
  1850. immutable stz = new SimpleTimeZone(11 * 60);
  1851. auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), FracSec.from!"hnsecs"(27));
  1852. _assertPred!"=="(sysTime, sysTime.toOtherTZ(stz));
  1853. _assertPred!"=="(sysTime._stdTime, sysTime.toOtherTZ(stz)._stdTime);
  1854. assert(sysTime.toOtherTZ(stz).timezone is stz);
  1855. assert(sysTime.toOtherTZ(stz).timezone !is LocalTime());
  1856. assert(sysTime.toOtherTZ(stz).timezone !is UTC());
  1857. }
  1858. }
  1859. /++
  1860. Returns a $(D time_t) which represents the same time as this
  1861. $(D SysTime).
  1862. Note that like all conversions in std.datetime, this is a truncating
  1863. conversion.
  1864. If $(D time_t) is 32 bits, rather than 64, and the result can't fit in a
  1865. 32-bit value, then the closest value that can be held in 32 bits will be
  1866. used (so $(D time_t.max) if it goes over and $(D time_t.min) if it goes
  1867. under).
  1868. +/
  1869. time_t toUnixTime() const pure nothrow
  1870. {
  1871. return stdTimeToUnixTime(_stdTime);
  1872. }
  1873. unittest
  1874. {
  1875. version(testStdDateTime)
  1876. {
  1877. _assertPred!"=="(SysTime(DateTime(1970, 1, 1), UTC()).toUnixTime, 0);
  1878. _assertPred!"=="(SysTime(DateTime(1970, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1), UTC()).toUnixTime, 0);
  1879. _assertPred!"=="(SysTime(DateTime(1970, 1, 1, 0, 0, 0), FracSec.from!"usecs"(1), UTC()).toUnixTime, 0);
  1880. _assertPred!"=="(SysTime(DateTime(1970, 1, 1, 0, 0, 0), FracSec.from!"msecs"(1), UTC()).toUnixTime, 0);
  1881. _assertPred!"=="(SysTime(DateTime(1970, 1, 1, 0, 0, 1), UTC()).toUnixTime, 1);
  1882. _assertPred!"=="(SysTime(DateTime(1969, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999), UTC()).toUnixTime, 0);
  1883. _assertPred!"=="(SysTime(DateTime(1969, 12, 31, 23, 59, 59), FracSec.from!"usecs"(999_999), UTC()).toUnixTime, 0);
  1884. _assertPred!"=="(SysTime(DateTime(1969, 12, 31, 23, 59, 59), FracSec.from!"msecs"(999), UTC()).toUnixTime, 0);
  1885. _assertPred!"=="(SysTime(DateTime(1969, 12, 31, 23, 59, 59), UTC()).toUnixTime, -1);
  1886. }
  1887. }
  1888. /++
  1889. Returns a $(D timeval) which represents this $(D SysTime).
  1890. Note that like all conversions in std.datetime, this is a truncating
  1891. conversion.
  1892. If $(D time_t) is 32 bits, rather than 64, and the result can't fit in a
  1893. 32-bit value, then the closest value that can be held in 32 bits will be
  1894. used for $(D tv_sec). (so $(D time_t.max) if it goes over and
  1895. $(D time_t.min) if it goes under).
  1896. +/
  1897. timeval toTimeVal() const pure nothrow
  1898. {
  1899. immutable tv_sec = toUnixTime();
  1900. immutable fracHNSecs = removeUnitsFromHNSecs!"seconds"(_stdTime - 621355968000000000L);
  1901. immutable tv_usec = cast(int)convert!("hnsecs", "usecs")(fracHNSecs);
  1902. return timeval(tv_sec, tv_usec);
  1903. }
  1904. unittest
  1905. {
  1906. version(testStdDateTime)
  1907. {
  1908. assert(SysTime(DateTime(1970, 1, 1), UTC()).toTimeVal() == timeval(0, 0));
  1909. assert(SysTime(DateTime(1970, 1, 1), FracSec.from!"hnsecs"(9), UTC()).toTimeVal() == timeval(0, 0));
  1910. assert(SysTime(DateTime(1970, 1, 1), FracSec.from!"hnsecs"(10), UTC()).toTimeVal() == timeval(0, 1));
  1911. assert(SysTime(DateTime(1970, 1, 1), FracSec.from!"usecs"(7), UTC()).toTimeVal() == timeval(0, 7));
  1912. assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), UTC()).toTimeVal() == timeval(1, 0));
  1913. assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), FracSec.from!"hnsecs"(9), UTC()).toTimeVal() == timeval(1, 0));
  1914. assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), FracSec.from!"hnsecs"(10), UTC()).toTimeVal() == timeval(1, 1));
  1915. assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), FracSec.from!"usecs"(7), UTC()).toTimeVal() == timeval(1, 7));
  1916. assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999), UTC()).toTimeVal() ==
  1917. timeval(0, 0));
  1918. assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_990), UTC()).toTimeVal() ==
  1919. timeval(0, -1));
  1920. assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), FracSec.from!"usecs"(999_999), UTC()).toTimeVal() ==
  1921. timeval(0, -1));
  1922. assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), FracSec.from!"usecs"(999), UTC()).toTimeVal() ==
  1923. timeval(0, -999_001));
  1924. assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), FracSec.from!"msecs"(999), UTC()).toTimeVal() ==
  1925. timeval(0, -1000));
  1926. assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), UTC()).toTimeVal() == timeval(-1, 0));
  1927. assert(SysTime(DateTime(1969, 12, 31, 23, 59, 58), FracSec.from!"usecs"(17), UTC()).toTimeVal() ==
  1928. timeval(-1, -999_983));
  1929. }
  1930. }
  1931. /++
  1932. Returns a $(D tm) which represents this $(D SysTime).
  1933. +/
  1934. tm toTM() const nothrow
  1935. {
  1936. try
  1937. {
  1938. auto dateTime = cast(DateTime)this;
  1939. tm timeInfo;
  1940. timeInfo.tm_sec = dateTime.second;
  1941. timeInfo.tm_min = dateTime.minute;
  1942. timeInfo.tm_hour = dateTime.hour;
  1943. timeInfo.tm_mday = dateTime.day;
  1944. timeInfo.tm_mon = dateTime.month - 1;
  1945. timeInfo.tm_year = dateTime.year - 1900;
  1946. timeInfo.tm_wday = dateTime.dayOfWeek;
  1947. timeInfo.tm_yday = dateTime.dayOfYear - 1;
  1948. timeInfo.tm_isdst = _timezone.dstInEffect(_stdTime);
  1949. version(Posix)
  1950. {
  1951. char[] zone = (timeInfo.tm_isdst ? _timezone.dstName : _timezone.stdName).dup;
  1952. zone ~= "\0";
  1953. timeInfo.tm_gmtoff = cast(int)convert!("hnsecs", "seconds")(adjTime - _stdTime);
  1954. timeInfo.tm_zone = zone.ptr;
  1955. }
  1956. return timeInfo;
  1957. }
  1958. catch(Exception e)
  1959. assert(0, "Either DateTime's constructor threw.");
  1960. }
  1961. unittest
  1962. {
  1963. version(testStdDateTime)
  1964. {
  1965. version(Posix)
  1966. {
  1967. scope(exit) clearTZEnvVar();
  1968. setTZEnvVar("America/Los_Angeles");
  1969. }
  1970. {
  1971. auto timeInfo = SysTime(DateTime(1970, 1, 1)).toTM();
  1972. _assertPred!"=="(timeInfo.tm_sec, 0);
  1973. _assertPred!"=="(timeInfo.tm_min, 0);
  1974. _assertPred!"=="(timeInfo.tm_hour, 0);
  1975. _assertPred!"=="(timeInfo.tm_mday, 1);
  1976. _assertPred!"=="(timeInfo.tm_mon, 0);
  1977. _assertPred!"=="(timeInfo.tm_year, 70);
  1978. _assertPred!"=="(timeInfo.tm_wday, 4);
  1979. _assertPred!"=="(timeInfo.tm_yday, 0);
  1980. version(Posix)
  1981. _assertPred!"=="(timeInfo.tm_isdst, 0);
  1982. else version(Windows)
  1983. assert(timeInfo.tm_isdst == 0 || timeInfo.tm_isdst == 1);
  1984. version(Posix)
  1985. {
  1986. _assertPred!"=="(timeInfo.tm_gmtoff, -8 * 60 * 60);
  1987. _assertPred!"=="(to!string(timeInfo.tm_zone), "PST");
  1988. }
  1989. }
  1990. {
  1991. auto timeInfo = SysTime(DateTime(2010, 7, 4, 12, 15, 7), FracSec.from!"hnsecs"(15)).toTM();
  1992. _assertPred!"=="(timeInfo.tm_sec, 7);
  1993. _assertPred!"=="(timeInfo.tm_min, 15);
  1994. _assertPred!"=="(timeInfo.tm_hour, 12);
  1995. _assertPred!"=="(timeInfo.tm_mday, 4);
  1996. _assertPred!"=="(timeInfo.tm_mon, 6);
  1997. _assertPred!"=="(timeInfo.tm_year, 110);
  1998. _assertPred!"=="(timeInfo.tm_wday, 0);
  1999. _assertPred!"=="(timeInfo.tm_yday, 184);
  2000. version(Posix)
  2001. _assertPred!"=="(timeInfo.tm_isdst, 1);
  2002. else version(Windows)
  2003. assert(timeInfo.tm_isdst == 0 || timeInfo.tm_isdst == 1);
  2004. version(Posix)
  2005. {
  2006. _assertPred!"=="(timeInfo.tm_gmtoff, -7 * 60 * 60);
  2007. _assertPred!"=="(to!string(timeInfo.tm_zone), "PDT");
  2008. }
  2009. }
  2010. }
  2011. }
  2012. /++
  2013. Adds the given number of years or months to this $(D SysTime). A
  2014. negative number will subtract.
  2015. Note that if day overflow is allowed, and the date with the adjusted
  2016. year/month overflows the number of days in the new month, then the month
  2017. will be incremented by one, and the day set to the number of days
  2018. overflowed. (e.g. if the day were 31 and the new month were June, then
  2019. the month would be incremented to July, and the new day would be 1). If
  2020. day overflow is not allowed, then the day will be set to the last valid
  2021. day in the month (e.g. June 31st would become June 30th).
  2022. Params:
  2023. units = The type of units to add ("years" or "months").
  2024. value = The number of months or years to add to this
  2025. $(D SysTime).
  2026. allowOverflow = Whether the days should be allowed to overflow,
  2027. causing the month to increment.
  2028. Examples:
  2029. --------------------
  2030. auto st1 = SysTime(DateTime(2010, 1, 1, 12, 30, 33));
  2031. st1.add!"months"(11);
  2032. assert(st1 == SysTime(DateTime(2010, 12, 1, 12, 30, 33)));
  2033. auto st2 = SysTime(DateTime(2010, 1, 1, 12, 30, 33));
  2034. st2.add!"months"(-11);
  2035. assert(st2 == SysTime(DateTime(2009, 2, 1, 12, 30, 33)));
  2036. auto st3 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
  2037. st3.add!"years"(1);
  2038. assert(st3 == SysTime(DateTime(2001, 3, 1, 12, 30, 33)));
  2039. auto st4 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
  2040. st4.add!"years"(1, AllowDayOverflow.no);
  2041. assert(st4 == SysTime(DateTime(2001, 2, 28, 12, 30, 33)));
  2042. --------------------
  2043. +/
  2044. ref SysTime add(string units)(long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) nothrow
  2045. if(units == "years" ||
  2046. units == "months")
  2047. {
  2048. auto hnsecs = adjTime;
  2049. auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
  2050. if(hnsecs < 0)
  2051. {
  2052. hnsecs += convert!("hours", "hnsecs")(24);
  2053. --days;
  2054. }
  2055. auto date = Date(cast(int)days);
  2056. date.add!units(value, allowOverflow);
  2057. days = date.dayOfGregorianCal - 1;
  2058. if(days < 0)
  2059. {
  2060. hnsecs -= convert!("hours", "hnsecs")(24);
  2061. ++days;
  2062. }
  2063. immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
  2064. adjTime = newDaysHNSecs + hnsecs;
  2065. return this;
  2066. }
  2067. //Verify Examples.
  2068. unittest
  2069. {
  2070. version (testStdDateTime)
  2071. {
  2072. auto st1 = SysTime(DateTime(2010, 1, 1, 12, 30, 33));
  2073. st1.add!"months"(11);
  2074. assert(st1 == SysTime(DateTime(2010, 12, 1, 12, 30, 33)));
  2075. auto st2 = SysTime(DateTime(2010, 1, 1, 12, 30, 33));
  2076. st2.add!"months"(-11);
  2077. assert(st2 == SysTime(DateTime(2009, 2, 1, 12, 30, 33)));
  2078. auto st3 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
  2079. st3.add!"years"(1);
  2080. assert(st3 == SysTime(DateTime(2001, 3, 1, 12, 30, 33)));
  2081. auto st4 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
  2082. st4.add!"years"(1, AllowDayOverflow.no);
  2083. assert(st4 == SysTime(DateTime(2001, 2, 28, 12, 30, 33)));
  2084. }
  2085. }
  2086. //Test add!"years"() with AllowDayOverlow.yes
  2087. unittest
  2088. {
  2089. version(testStdDateTime)
  2090. {
  2091. //Test A.D.
  2092. {
  2093. auto sysTime = SysTime(Date(1999, 7, 6));
  2094. sysTime.add!"years"(7);
  2095. _assertPred!"=="(sysTime, SysTime(Date(2006, 7, 6)));
  2096. sysTime.add!"years"(-9);
  2097. _assertPred!"=="(sysTime, SysTime(Date(1997, 7, 6)));
  2098. }
  2099. {
  2100. auto sysTime = SysTime(Date(1999, 2, 28));
  2101. sysTime.add!"years"(1);
  2102. _assertPred!"=="(sysTime, SysTime(Date(2000, 2, 28)));
  2103. }
  2104. {
  2105. auto sysTime = SysTime(Date(2000, 2, 29));
  2106. sysTime.add!"years"(-1);
  2107. _assertPred!"=="(sysTime, SysTime(Date(1999, 3, 1)));
  2108. }
  2109. {
  2110. auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 7, 3), FracSec.from!"msecs"(234));
  2111. sysTime.add!"years"(7);
  2112. _assertPred!"=="(sysTime, SysTime(DateTime(2006, 7, 6, 12, 7, 3), FracSec.from!"msecs"(234)));
  2113. sysTime.add!"years"(-9);
  2114. _assertPred!"=="(sysTime, SysTime(DateTime(1997, 7, 6, 12, 7, 3), FracSec.from!"msecs"(234)));
  2115. }
  2116. {
  2117. auto sysTime = SysTime(DateTime(1999, 2, 28, 0, 7, 2), FracSec.from!"usecs"(1207));
  2118. sysTime.add!"years"(1);
  2119. _assertPred!"=="(sysTime, SysTime(DateTime(2000, 2, 28, 0, 7, 2), FracSec.from!"usecs"(1207)));
  2120. }
  2121. {
  2122. auto sysTime = SysTime(DateTime(2000, 2, 29, 0, 7, 2), FracSec.from!"usecs"(1207));
  2123. sysTime.add!"years"(-1);
  2124. _assertPred!"=="(sysTime, SysTime(DateTime(1999, 3, 1, 0, 7, 2), FracSec.from!"usecs"(1207)));
  2125. }
  2126. //Test B.C.
  2127. {
  2128. auto sysTime = SysTime(Date(-1999, 7, 6));
  2129. sysTime.add!"years"(-7);
  2130. _assertPred!"=="(sysTime, SysTime(Date(-2006, 7, 6)));
  2131. sysTime.add!"years"(9);
  2132. _assertPred!"=="(sysTime, SysTime(Date(-1997, 7, 6)));
  2133. }
  2134. {
  2135. auto sysTime = SysTime(Date(-1999, 2, 28));
  2136. sysTime.add!"years"(-1);
  2137. _assertPred!"=="(sysTime, SysTime(Date(-2000, 2, 28)));
  2138. }
  2139. {
  2140. auto sysTime = SysTime(Date(-2000, 2, 29));
  2141. sysTime.add!"years"(1);
  2142. _assertPred!"=="(sysTime, SysTime(Date(-1999, 3, 1)));
  2143. }
  2144. {
  2145. auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 7, 3), FracSec.from!"msecs"(234));
  2146. sysTime.add!"years"(-7);
  2147. _assertPred!"=="(sysTime, SysTime(DateTime(-2006, 7, 6, 12, 7, 3), FracSec.from!"msecs"(234)));
  2148. sysTime.add!"years"(9);
  2149. _assertPred!"=="(sysTime, SysTime(DateTime(-1997, 7, 6, 12, 7, 3), FracSec.from!"msecs"(234)));
  2150. }
  2151. {
  2152. auto sysTime = SysTime(DateTime(-1999, 2, 28, 3, 3, 3), FracSec.from!"hnsecs"(3));
  2153. sysTime.add!"years"(-1);
  2154. _assertPred!"=="(sysTime, SysTime(DateTime(-2000, 2, 28, 3, 3, 3), FracSec.from!"hnsecs"(3)));
  2155. }
  2156. {
  2157. auto sysTime = SysTime(DateTime(-2000, 2, 29, 3, 3, 3), FracSec.from!"hnsecs"(3));
  2158. sysTime.add!"years"(1);
  2159. _assertPred!"=="(sysTime, SysTime(DateTime(-1999, 3, 1, 3, 3, 3), FracSec.from!"hnsecs"(3)));
  2160. }
  2161. //Test Both
  2162. {
  2163. auto sysTime = SysTime(Date(4, 7, 6));
  2164. sysTime.add!"years"(-5);
  2165. _assertPred!"=="(sysTime, SysTime(Date(-1, 7, 6)));
  2166. sysTime.add!"years"(5);
  2167. _assertPred!"=="(sysTime, SysTime(Date(4, 7, 6)));
  2168. }
  2169. {
  2170. auto sysTime = SysTime(Date(-4, 7, 6));
  2171. sysTime.add!"years"(5);
  2172. _assertPred!"=="(sysTime, SysTime(Date(1, 7, 6)));
  2173. sysTime.add!"years"(-5);
  2174. _assertPred!"=="(sysTime, SysTime(Date(-4, 7, 6)));
  2175. }
  2176. {
  2177. auto sysTime = SysTime(Date(4, 7, 6));
  2178. sysTime.add!"years"(-8);
  2179. _assertPred!"=="(sysTime, SysTime(Date(-4, 7, 6)));
  2180. sysTime.add!"years"(8);
  2181. _assertPred!"=="(sysTime, SysTime(Date(4, 7, 6)));
  2182. }
  2183. {
  2184. auto sysTime = SysTime(Date(-4, 7, 6));
  2185. sysTime.add!"years"(8);
  2186. _assertPred!"=="(sysTime, SysTime(Date(4, 7, 6)));
  2187. sysTime.add!"years"(-8);
  2188. _assertPred!"=="(sysTime, SysTime(Date(-4, 7, 6)));
  2189. }
  2190. {
  2191. auto sysTime = SysTime(Date(-4, 2, 29));
  2192. sysTime.add!"years"(5);
  2193. _assertPred!"=="(sysTime, SysTime(Date(1, 3, 1)));
  2194. }
  2195. {
  2196. auto sysTime = SysTime(Date(4, 2, 29));
  2197. sysTime.add!"years"(-5);
  2198. _assertPred!"=="(sysTime, SysTime(Date(-1, 3, 1)));
  2199. }
  2200. {
  2201. auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
  2202. sysTime.add!"years"(-1);
  2203. _assertPred!"=="(sysTime, SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  2204. sysTime.add!"years"(1);
  2205. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  2206. }
  2207. {
  2208. auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
  2209. sysTime.add!"years"(-1);
  2210. _assertPred!"=="(sysTime, SysTime(DateTime(0, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  2211. sysTime.add!"years"(1);
  2212. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  2213. }
  2214. {
  2215. auto sysTime = SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
  2216. sysTime.add!"years"(1);
  2217. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  2218. sysTime.add!"years"(-1);
  2219. _assertPred!"=="(sysTime, SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  2220. }
  2221. {
  2222. auto sysTime = SysTime(DateTime(0, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
  2223. sysTime.add!"years"(1);
  2224. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  2225. sysTime.add!"years"(-1);
  2226. _assertPred!"=="(sysTime, SysTime(DateTime(0, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  2227. }
  2228. {
  2229. auto sysTime = SysTime(DateTime(4, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329));
  2230. sysTime.add!"years"(-5);
  2231. _assertPred!"=="(sysTime, SysTime(DateTime(-1, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329)));
  2232. sysTime.add!"years"(5);
  2233. _assertPred!"=="(sysTime, SysTime(DateTime(4, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329)));
  2234. }
  2235. {
  2236. auto sysTime = SysTime(DateTime(-4, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329));
  2237. sysTime.add!"years"(5);
  2238. _assertPred!"=="(sysTime, SysTime(DateTime(1, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329)));
  2239. sysTime.add!"years"(-5);
  2240. _assertPred!"=="(sysTime, SysTime(DateTime(-4, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329)));
  2241. }
  2242. {
  2243. auto sysTime = SysTime(DateTime(-4, 2, 29, 5, 5, 5), FracSec.from!"msecs"(555));
  2244. sysTime.add!"years"(5);
  2245. _assertPred!"=="(sysTime, SysTime(DateTime(1, 3, 1, 5, 5, 5), FracSec.from!"msecs"(555)));
  2246. }
  2247. {
  2248. auto sysTime = SysTime(DateTime(4, 2, 29, 5, 5, 5), FracSec.from!"msecs"(555));
  2249. sysTime.add!"years"(-5);
  2250. _assertPred!"=="(sysTime, SysTime(DateTime(-1, 3, 1, 5, 5, 5), FracSec.from!"msecs"(555)));
  2251. }
  2252. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  2253. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  2254. static assert(!__traits(compiles, cst.add!"years"(4)));
  2255. //static assert(!__traits(compiles, ist.add!"years"(4)));
  2256. }
  2257. }
  2258. //Test add!"years"() with AllowDayOverlow.no
  2259. unittest
  2260. {
  2261. version(testStdDateTime)
  2262. {
  2263. //Test A.D.
  2264. {
  2265. auto sysTime = SysTime(Date(1999, 7, 6));
  2266. sysTime.add!"years"(7, AllowDayOverflow.no);
  2267. _assertPred!"=="(sysTime, SysTime(Date(2006, 7, 6)));
  2268. sysTime.add!"years"(-9, AllowDayOverflow.no);
  2269. _assertPred!"=="(sysTime, SysTime(Date(1997, 7, 6)));
  2270. }
  2271. {
  2272. auto sysTime = SysTime(Date(1999, 2, 28));
  2273. sysTime.add!"years"(1, AllowDayOverflow.no);
  2274. _assertPred!"=="(sysTime, SysTime(Date(2000, 2, 28)));
  2275. }
  2276. {
  2277. auto sysTime = SysTime(Date(2000, 2, 29));
  2278. sysTime.add!"years"(-1, AllowDayOverflow.no);
  2279. _assertPred!"=="(sysTime, SysTime(Date(1999, 2, 28)));
  2280. }
  2281. {
  2282. auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 7, 3), FracSec.from!"msecs"(234));
  2283. sysTime.add!"years"(7, AllowDayOverflow.no);
  2284. _assertPred!"=="(sysTime, SysTime(DateTime(2006, 7, 6, 12, 7, 3), FracSec.from!"msecs"(234)));
  2285. sysTime.add!"years"(-9, AllowDayOverflow.no);
  2286. _assertPred!"=="(sysTime, SysTime(DateTime(1997, 7, 6, 12, 7, 3), FracSec.from!"msecs"(234)));
  2287. }
  2288. {
  2289. auto sysTime = SysTime(DateTime(1999, 2, 28, 0, 7, 2), FracSec.from!"usecs"(1207));
  2290. sysTime.add!"years"(1, AllowDayOverflow.no);
  2291. _assertPred!"=="(sysTime, SysTime(DateTime(2000, 2, 28, 0, 7, 2), FracSec.from!"usecs"(1207)));
  2292. }
  2293. {
  2294. auto sysTime = SysTime(DateTime(2000, 2, 29, 0, 7, 2), FracSec.from!"usecs"(1207));
  2295. sysTime.add!"years"(-1, AllowDayOverflow.no);
  2296. _assertPred!"=="(sysTime, SysTime(DateTime(1999, 2, 28, 0, 7, 2), FracSec.from!"usecs"(1207)));
  2297. }
  2298. //Test B.C.
  2299. {
  2300. auto sysTime = SysTime(Date(-1999, 7, 6));
  2301. sysTime.add!"years"(-7, AllowDayOverflow.no);
  2302. _assertPred!"=="(sysTime, SysTime(Date(-2006, 7, 6)));
  2303. sysTime.add!"years"(9, AllowDayOverflow.no);
  2304. _assertPred!"=="(sysTime, SysTime(Date(-1997, 7, 6)));
  2305. }
  2306. {
  2307. auto sysTime = SysTime(Date(-1999, 2, 28));
  2308. sysTime.add!"years"(-1, AllowDayOverflow.no);
  2309. _assertPred!"=="(sysTime, SysTime(Date(-2000, 2, 28)));
  2310. }
  2311. {
  2312. auto sysTime = SysTime(Date(-2000, 2, 29));
  2313. sysTime.add!"years"(1, AllowDayOverflow.no);
  2314. _assertPred!"=="(sysTime, SysTime(Date(-1999, 2, 28)));
  2315. }
  2316. {
  2317. auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 7, 3), FracSec.from!"msecs"(234));
  2318. sysTime.add!"years"(-7, AllowDayOverflow.no);
  2319. _assertPred!"=="(sysTime, SysTime(DateTime(-2006, 7, 6, 12, 7, 3), FracSec.from!"msecs"(234)));
  2320. sysTime.add!"years"(9, AllowDayOverflow.no);
  2321. _assertPred!"=="(sysTime, SysTime(DateTime(-1997, 7, 6, 12, 7, 3), FracSec.from!"msecs"(234)));
  2322. }
  2323. {
  2324. auto sysTime = SysTime(DateTime(-1999, 2, 28, 3, 3, 3), FracSec.from!"hnsecs"(3));
  2325. sysTime.add!"years"(-1, AllowDayOverflow.no);
  2326. _assertPred!"=="(sysTime, SysTime(DateTime(-2000, 2, 28, 3, 3, 3), FracSec.from!"hnsecs"(3)));
  2327. }
  2328. {
  2329. auto sysTime = SysTime(DateTime(-2000, 2, 29, 3, 3, 3), FracSec.from!"hnsecs"(3));
  2330. sysTime.add!"years"(1, AllowDayOverflow.no);
  2331. _assertPred!"=="(sysTime, SysTime(DateTime(-1999, 2, 28, 3, 3, 3), FracSec.from!"hnsecs"(3)));
  2332. }
  2333. //Test Both
  2334. {
  2335. auto sysTime = SysTime(Date(4, 7, 6));
  2336. sysTime.add!"years"(-5, AllowDayOverflow.no);
  2337. _assertPred!"=="(sysTime, SysTime(Date(-1, 7, 6)));
  2338. sysTime.add!"years"(5, AllowDayOverflow.no);
  2339. _assertPred!"=="(sysTime, SysTime(Date(4, 7, 6)));
  2340. }
  2341. {
  2342. auto sysTime = SysTime(Date(-4, 7, 6));
  2343. sysTime.add!"years"(5, AllowDayOverflow.no);
  2344. _assertPred!"=="(sysTime, SysTime(Date(1, 7, 6)));
  2345. sysTime.add!"years"(-5, AllowDayOverflow.no);
  2346. _assertPred!"=="(sysTime, SysTime(Date(-4, 7, 6)));
  2347. }
  2348. {
  2349. auto sysTime = SysTime(Date(4, 7, 6));
  2350. sysTime.add!"years"(-8, AllowDayOverflow.no);
  2351. _assertPred!"=="(sysTime, SysTime(Date(-4, 7, 6)));
  2352. sysTime.add!"years"(8, AllowDayOverflow.no);
  2353. _assertPred!"=="(sysTime, SysTime(Date(4, 7, 6)));
  2354. }
  2355. {
  2356. auto sysTime = SysTime(Date(-4, 7, 6));
  2357. sysTime.add!"years"(8, AllowDayOverflow.no);
  2358. _assertPred!"=="(sysTime, SysTime(Date(4, 7, 6)));
  2359. sysTime.add!"years"(-8, AllowDayOverflow.no);
  2360. _assertPred!"=="(sysTime, SysTime(Date(-4, 7, 6)));
  2361. }
  2362. {
  2363. auto sysTime = SysTime(Date(-4, 2, 29));
  2364. sysTime.add!"years"(5, AllowDayOverflow.no);
  2365. _assertPred!"=="(sysTime, SysTime(Date(1, 2, 28)));
  2366. }
  2367. {
  2368. auto sysTime = SysTime(Date(4, 2, 29));
  2369. sysTime.add!"years"(-5, AllowDayOverflow.no);
  2370. _assertPred!"=="(sysTime, SysTime(Date(-1, 2, 28)));
  2371. }
  2372. {
  2373. auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
  2374. sysTime.add!"years"(-1, AllowDayOverflow.no);
  2375. _assertPred!"=="(sysTime, SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  2376. sysTime.add!"years"(1, AllowDayOverflow.no);
  2377. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  2378. }
  2379. {
  2380. auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
  2381. sysTime.add!"years"(-1, AllowDayOverflow.no);
  2382. _assertPred!"=="(sysTime, SysTime(DateTime(0, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  2383. sysTime.add!"years"(1, AllowDayOverflow.no);
  2384. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  2385. }
  2386. {
  2387. auto sysTime = SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
  2388. sysTime.add!"years"(1, AllowDayOverflow.no);
  2389. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  2390. sysTime.add!"years"(-1, AllowDayOverflow.no);
  2391. _assertPred!"=="(sysTime, SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  2392. }
  2393. {
  2394. auto sysTime = SysTime(DateTime(0, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
  2395. sysTime.add!"years"(1, AllowDayOverflow.no);
  2396. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  2397. sysTime.add!"years"(-1, AllowDayOverflow.no);
  2398. _assertPred!"=="(sysTime, SysTime(DateTime(0, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  2399. }
  2400. {
  2401. auto sysTime = SysTime(DateTime(4, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329));
  2402. sysTime.add!"years"(-5);
  2403. _assertPred!"=="(sysTime, SysTime(DateTime(-1, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329)));
  2404. sysTime.add!"years"(5);
  2405. _assertPred!"=="(sysTime, SysTime(DateTime(4, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329)));
  2406. }
  2407. {
  2408. auto sysTime = SysTime(DateTime(4, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329));
  2409. sysTime.add!"years"(-5, AllowDayOverflow.no);
  2410. _assertPred!"=="(sysTime, SysTime(DateTime(-1, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329)));
  2411. sysTime.add!"years"(5, AllowDayOverflow.no);
  2412. _assertPred!"=="(sysTime, SysTime(DateTime(4, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329)));
  2413. }
  2414. {
  2415. auto sysTime = SysTime(DateTime(-4, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329));
  2416. sysTime.add!"years"(5, AllowDayOverflow.no);
  2417. _assertPred!"=="(sysTime, SysTime(DateTime(1, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329)));
  2418. sysTime.add!"years"(-5, AllowDayOverflow.no);
  2419. _assertPred!"=="(sysTime, SysTime(DateTime(-4, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329)));
  2420. }
  2421. {
  2422. auto sysTime = SysTime(DateTime(-4, 2, 29, 5, 5, 5), FracSec.from!"msecs"(555));
  2423. sysTime.add!"years"(5, AllowDayOverflow.no);
  2424. _assertPred!"=="(sysTime, SysTime(DateTime(1, 2, 28, 5, 5, 5), FracSec.from!"msecs"(555)));
  2425. }
  2426. {
  2427. auto sysTime = SysTime(DateTime(4, 2, 29, 5, 5, 5), FracSec.from!"msecs"(555));
  2428. sysTime.add!"years"(-5, AllowDayOverflow.no);
  2429. _assertPred!"=="(sysTime, SysTime(DateTime(-1, 2, 28, 5, 5, 5), FracSec.from!"msecs"(555)));
  2430. }
  2431. }
  2432. }
  2433. //Test add!"months"() with AllowDayOverlow.yes
  2434. unittest
  2435. {
  2436. version(testStdDateTime)
  2437. {
  2438. //Test A.D.
  2439. {
  2440. auto sysTime = SysTime(Date(1999, 7, 6));
  2441. sysTime.add!"months"(3);
  2442. _assertPred!"=="(sysTime, SysTime(Date(1999, 10, 6)));
  2443. sysTime.add!"months"(-4);
  2444. _assertPred!"=="(sysTime, SysTime(Date(1999, 6, 6)));
  2445. }
  2446. {
  2447. auto sysTime = SysTime(Date(1999, 7, 6));
  2448. sysTime.add!"months"(6);
  2449. _assertPred!"=="(sysTime, SysTime(Date(2000, 1, 6)));
  2450. sysTime.add!"months"(-6);
  2451. _assertPred!"=="(sysTime, SysTime(Date(1999, 7, 6)));
  2452. }
  2453. {
  2454. auto sysTime = SysTime(Date(1999, 7, 6));
  2455. sysTime.add!"months"(27);
  2456. _assertPred!"=="(sysTime, SysTime(Date(2001, 10, 6)));
  2457. sysTime.add!"months"(-28);
  2458. _assertPred!"=="(sysTime, SysTime(Date(1999, 6, 6)));
  2459. }
  2460. {
  2461. auto sysTime = SysTime(Date(1999, 5, 31));
  2462. sysTime.add!"months"(1);
  2463. _assertPred!"=="(sysTime, SysTime(Date(1999, 7, 1)));
  2464. }
  2465. {
  2466. auto sysTime = SysTime(Date(1999, 5, 31));
  2467. sysTime.add!"months"(-1);
  2468. _assertPred!"=="(sysTime, SysTime(Date(1999, 5, 1)));
  2469. }
  2470. {
  2471. auto sysTime = SysTime(Date(1999, 2, 28));
  2472. sysTime.add!"months"(12);
  2473. _assertPred!"=="(sysTime, SysTime(Date(2000, 2, 28)));
  2474. }
  2475. {
  2476. auto sysTime = SysTime(Date(2000, 2, 29));
  2477. sysTime.add!"months"(12);
  2478. _assertPred!"=="(sysTime, SysTime(Date(2001, 3, 1)));
  2479. }
  2480. {
  2481. auto sysTime = SysTime(Date(1999, 7, 31));
  2482. sysTime.add!"months"(1);
  2483. _assertPred!"=="(sysTime, SysTime(Date(1999, 8, 31)));
  2484. sysTime.add!"months"(1);
  2485. _assertPred!"=="(sysTime, SysTime(Date(1999, 10, 1)));
  2486. }
  2487. {
  2488. auto sysTime = SysTime(Date(1998, 8, 31));
  2489. sysTime.add!"months"(13);
  2490. _assertPred!"=="(sysTime, SysTime(Date(1999, 10, 1)));
  2491. sysTime.add!"months"(-13);
  2492. _assertPred!"=="(sysTime, SysTime(Date(1998, 9, 1)));
  2493. }
  2494. {
  2495. auto sysTime = SysTime(Date(1997, 12, 31));
  2496. sysTime.add!"months"(13);
  2497. _assertPred!"=="(sysTime, SysTime(Date(1999, 1, 31)));
  2498. sysTime.add!"months"(-13);
  2499. _assertPred!"=="(sysTime, SysTime(Date(1997, 12, 31)));
  2500. }
  2501. {
  2502. auto sysTime = SysTime(Date(1997, 12, 31));
  2503. sysTime.add!"months"(14);
  2504. _assertPred!"=="(sysTime, SysTime(Date(1999, 3, 3)));
  2505. sysTime.add!"months"(-14);
  2506. _assertPred!"=="(sysTime, SysTime(Date(1998, 1, 3)));
  2507. }
  2508. {
  2509. auto sysTime = SysTime(Date(1998, 12, 31));
  2510. sysTime.add!"months"(14);
  2511. _assertPred!"=="(sysTime, SysTime(Date(2000, 3, 2)));
  2512. sysTime.add!"months"(-14);
  2513. _assertPred!"=="(sysTime, SysTime(Date(1999, 1, 2)));
  2514. }
  2515. {
  2516. auto sysTime = SysTime(Date(1999, 12, 31));
  2517. sysTime.add!"months"(14);
  2518. _assertPred!"=="(sysTime, SysTime(Date(2001, 3, 3)));
  2519. sysTime.add!"months"(-14);
  2520. _assertPred!"=="(sysTime, SysTime(Date(2000, 1, 3)));
  2521. }
  2522. {
  2523. auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), FracSec.from!"usecs"(5007));
  2524. sysTime.add!"months"(3);
  2525. _assertPred!"=="(sysTime, SysTime(DateTime(1999, 10, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
  2526. sysTime.add!"months"(-4);
  2527. _assertPred!"=="(sysTime, SysTime(DateTime(1999, 6, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
  2528. }
  2529. {
  2530. auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
  2531. sysTime.add!"months"(14);
  2532. _assertPred!"=="(sysTime, SysTime(DateTime(2000, 3, 2, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  2533. sysTime.add!"months"(-14);
  2534. _assertPred!"=="(sysTime, SysTime(DateTime(1999, 1, 2, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  2535. }
  2536. {
  2537. auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
  2538. sysTime.add!"months"(14);
  2539. _assertPred!"=="(sysTime, SysTime(DateTime(2001, 3, 3, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  2540. sysTime.add!"months"(-14);
  2541. _assertPred!"=="(sysTime, SysTime(DateTime(2000, 1, 3, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  2542. }
  2543. //Test B.C.
  2544. {
  2545. auto sysTime = SysTime(Date(-1999, 7, 6));
  2546. sysTime.add!"months"(3);
  2547. _assertPred!"=="(sysTime, SysTime(Date(-1999, 10, 6)));
  2548. sysTime.add!"months"(-4);
  2549. _assertPred!"=="(sysTime, SysTime(Date(-1999, 6, 6)));
  2550. }
  2551. {
  2552. auto sysTime = SysTime(Date(-1999, 7, 6));
  2553. sysTime.add!"months"(6);
  2554. _assertPred!"=="(sysTime, SysTime(Date(-1998, 1, 6)));
  2555. sysTime.add!"months"(-6);
  2556. _assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 6)));
  2557. }
  2558. {
  2559. auto sysTime = SysTime(Date(-1999, 7, 6));
  2560. sysTime.add!"months"(-27);
  2561. _assertPred!"=="(sysTime, SysTime(Date(-2001, 4, 6)));
  2562. sysTime.add!"months"(28);
  2563. _assertPred!"=="(sysTime, SysTime(Date(-1999, 8, 6)));
  2564. }
  2565. {
  2566. auto sysTime = SysTime(Date(-1999, 5, 31));
  2567. sysTime.add!"months"(1);
  2568. _assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 1)));
  2569. }
  2570. {
  2571. auto sysTime = SysTime(Date(-1999, 5, 31));
  2572. sysTime.add!"months"(-1);
  2573. _assertPred!"=="(sysTime, SysTime(Date(-1999, 5, 1)));
  2574. }
  2575. {
  2576. auto sysTime = SysTime(Date(-1999, 2, 28));
  2577. sysTime.add!"months"(-12);
  2578. _assertPred!"=="(sysTime, SysTime(Date(-2000, 2, 28)));
  2579. }
  2580. {
  2581. auto sysTime = SysTime(Date(-2000, 2, 29));
  2582. sysTime.add!"months"(-12);
  2583. _assertPred!"=="(sysTime, SysTime(Date(-2001, 3, 1)));
  2584. }
  2585. {
  2586. auto sysTime = SysTime(Date(-1999, 7, 31));
  2587. sysTime.add!"months"(1);
  2588. _assertPred!"=="(sysTime, SysTime(Date(-1999, 8, 31)));
  2589. sysTime.add!"months"(1);
  2590. _assertPred!"=="(sysTime, SysTime(Date(-1999, 10, 1)));
  2591. }
  2592. {
  2593. auto sysTime = SysTime(Date(-1998, 8, 31));
  2594. sysTime.add!"months"(13);
  2595. _assertPred!"=="(sysTime, SysTime(Date(-1997, 10, 1)));
  2596. sysTime.add!"months"(-13);
  2597. _assertPred!"=="(sysTime, SysTime(Date(-1998, 9, 1)));
  2598. }
  2599. {
  2600. auto sysTime = SysTime(Date(-1997, 12, 31));
  2601. sysTime.add!"months"(13);
  2602. _assertPred!"=="(sysTime, SysTime(Date(-1995, 1, 31)));
  2603. sysTime.add!"months"(-13);
  2604. _assertPred!"=="(sysTime, SysTime(Date(-1997, 12, 31)));
  2605. }
  2606. {
  2607. auto sysTime = SysTime(Date(-1997, 12, 31));
  2608. sysTime.add!"months"(14);
  2609. _assertPred!"=="(sysTime, SysTime(Date(-1995, 3, 3)));
  2610. sysTime.add!"months"(-14);
  2611. _assertPred!"=="(sysTime, SysTime(Date(-1996, 1, 3)));
  2612. }
  2613. {
  2614. auto sysTime = SysTime(Date(-2002, 12, 31));
  2615. sysTime.add!"months"(14);
  2616. _assertPred!"=="(sysTime, SysTime(Date(-2000, 3, 2)));
  2617. sysTime.add!"months"(-14);
  2618. _assertPred!"=="(sysTime, SysTime(Date(-2001, 1, 2)));
  2619. }
  2620. {
  2621. auto sysTime = SysTime(Date(-2001, 12, 31));
  2622. sysTime.add!"months"(14);
  2623. _assertPred!"=="(sysTime, SysTime(Date(-1999, 3, 3)));
  2624. sysTime.add!"months"(-14);
  2625. _assertPred!"=="(sysTime, SysTime(Date(-2000, 1, 3)));
  2626. }
  2627. {
  2628. auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), FracSec.from!"usecs"(5007));
  2629. sysTime.add!"months"(3);
  2630. _assertPred!"=="(sysTime, SysTime(DateTime(-1999, 10, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
  2631. sysTime.add!"months"(-4);
  2632. _assertPred!"=="(sysTime, SysTime(DateTime(-1999, 6, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
  2633. }
  2634. {
  2635. auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
  2636. sysTime.add!"months"(14);
  2637. _assertPred!"=="(sysTime, SysTime(DateTime(-2000, 3, 2, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  2638. sysTime.add!"months"(-14);
  2639. _assertPred!"=="(sysTime, SysTime(DateTime(-2001, 1, 2, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  2640. }
  2641. {
  2642. auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
  2643. sysTime.add!"months"(14);
  2644. _assertPred!"=="(sysTime, SysTime(DateTime(-1999, 3, 3, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  2645. sysTime.add!"months"(-14);
  2646. _assertPred!"=="(sysTime, SysTime(DateTime(-2000, 1, 3, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  2647. }
  2648. //Test Both
  2649. {
  2650. auto sysTime = SysTime(Date(1, 1, 1));
  2651. sysTime.add!"months"(-1);
  2652. _assertPred!"=="(sysTime, SysTime(Date(0, 12, 1)));
  2653. sysTime.add!"months"(1);
  2654. _assertPred!"=="(sysTime, SysTime(Date(1, 1, 1)));
  2655. }
  2656. {
  2657. auto sysTime = SysTime(Date(4, 1, 1));
  2658. sysTime.add!"months"(-48);
  2659. _assertPred!"=="(sysTime, SysTime(Date(0, 1, 1)));
  2660. sysTime.add!"months"(48);
  2661. _assertPred!"=="(sysTime, SysTime(Date(4, 1, 1)));
  2662. }
  2663. {
  2664. auto sysTime = SysTime(Date(4, 3, 31));
  2665. sysTime.add!"months"(-49);
  2666. _assertPred!"=="(sysTime, SysTime(Date(0, 3, 2)));
  2667. sysTime.add!"months"(49);
  2668. _assertPred!"=="(sysTime, SysTime(Date(4, 4, 2)));
  2669. }
  2670. {
  2671. auto sysTime = SysTime(Date(4, 3, 31));
  2672. sysTime.add!"months"(-85);
  2673. _assertPred!"=="(sysTime, SysTime(Date(-3, 3, 3)));
  2674. sysTime.add!"months"(85);
  2675. _assertPred!"=="(sysTime, SysTime(Date(4, 4, 3)));
  2676. }
  2677. {
  2678. auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
  2679. sysTime.add!"months"(-1);
  2680. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  2681. sysTime.add!"months"(1);
  2682. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  2683. }
  2684. {
  2685. auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
  2686. sysTime.add!"months"(-1);
  2687. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  2688. sysTime.add!"months"(1);
  2689. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  2690. }
  2691. {
  2692. auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
  2693. sysTime.add!"months"(1);
  2694. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  2695. sysTime.add!"months"(-1);
  2696. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  2697. }
  2698. {
  2699. auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
  2700. sysTime.add!"months"(1);
  2701. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  2702. sysTime.add!"months"(-1);
  2703. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  2704. }
  2705. {
  2706. auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), FracSec.from!"hnsecs"(17));
  2707. sysTime.add!"months"(-1);
  2708. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 0, 7, 9), FracSec.from!"hnsecs"(17)));
  2709. sysTime.add!"months"(1);
  2710. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 7, 9), FracSec.from!"hnsecs"(17)));
  2711. }
  2712. {
  2713. auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), FracSec.from!"msecs"(9));
  2714. sysTime.add!"months"(-85);
  2715. _assertPred!"=="(sysTime, SysTime(DateTime(-3, 3, 3, 12, 11, 10), FracSec.from!"msecs"(9)));
  2716. sysTime.add!"months"(85);
  2717. _assertPred!"=="(sysTime, SysTime(DateTime(4, 4, 3, 12, 11, 10), FracSec.from!"msecs"(9)));
  2718. }
  2719. {
  2720. auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), FracSec.from!"msecs"(9));
  2721. sysTime.add!"months"(85);
  2722. _assertPred!"=="(sysTime, SysTime(DateTime(4, 5, 1, 12, 11, 10), FracSec.from!"msecs"(9)));
  2723. sysTime.add!"months"(-85);
  2724. _assertPred!"=="(sysTime, SysTime(DateTime(-3, 4, 1, 12, 11, 10), FracSec.from!"msecs"(9)));
  2725. }
  2726. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  2727. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  2728. static assert(!__traits(compiles, cst.add!"months"(4)));
  2729. //static assert(!__traits(compiles, ist.add!"months"(4)));
  2730. }
  2731. }
  2732. //Test add!"months"() with AllowDayOverlow.no
  2733. unittest
  2734. {
  2735. version(testStdDateTime)
  2736. {
  2737. //Test A.D.
  2738. {
  2739. auto sysTime = SysTime(Date(1999, 7, 6));
  2740. sysTime.add!"months"(3, AllowDayOverflow.no);
  2741. _assertPred!"=="(sysTime, SysTime(Date(1999, 10, 6)));
  2742. sysTime.add!"months"(-4, AllowDayOverflow.no);
  2743. _assertPred!"=="(sysTime, SysTime(Date(1999, 6, 6)));
  2744. }
  2745. {
  2746. auto sysTime = SysTime(Date(1999, 7, 6));
  2747. sysTime.add!"months"(6, AllowDayOverflow.no);
  2748. _assertPred!"=="(sysTime, SysTime(Date(2000, 1, 6)));
  2749. sysTime.add!"months"(-6, AllowDayOverflow.no);
  2750. _assertPred!"=="(sysTime, SysTime(Date(1999, 7, 6)));
  2751. }
  2752. {
  2753. auto sysTime = SysTime(Date(1999, 7, 6));
  2754. sysTime.add!"months"(27, AllowDayOverflow.no);
  2755. _assertPred!"=="(sysTime, SysTime(Date(2001, 10, 6)));
  2756. sysTime.add!"months"(-28, AllowDayOverflow.no);
  2757. _assertPred!"=="(sysTime, SysTime(Date(1999, 6, 6)));
  2758. }
  2759. {
  2760. auto sysTime = SysTime(Date(1999, 5, 31));
  2761. sysTime.add!"months"(1, AllowDayOverflow.no);
  2762. _assertPred!"=="(sysTime, SysTime(Date(1999, 6, 30)));
  2763. }
  2764. {
  2765. auto sysTime = SysTime(Date(1999, 5, 31));
  2766. sysTime.add!"months"(-1, AllowDayOverflow.no);
  2767. _assertPred!"=="(sysTime, SysTime(Date(1999, 4, 30)));
  2768. }
  2769. {
  2770. auto sysTime = SysTime(Date(1999, 2, 28));
  2771. sysTime.add!"months"(12, AllowDayOverflow.no);
  2772. _assertPred!"=="(sysTime, SysTime(Date(2000, 2, 28)));
  2773. }
  2774. {
  2775. auto sysTime = SysTime(Date(2000, 2, 29));
  2776. sysTime.add!"months"(12, AllowDayOverflow.no);
  2777. _assertPred!"=="(sysTime, SysTime(Date(2001, 2, 28)));
  2778. }
  2779. {
  2780. auto sysTime = SysTime(Date(1999, 7, 31));
  2781. sysTime.add!"months"(1, AllowDayOverflow.no);
  2782. _assertPred!"=="(sysTime, SysTime(Date(1999, 8, 31)));
  2783. sysTime.add!"months"(1, AllowDayOverflow.no);
  2784. _assertPred!"=="(sysTime, SysTime(Date(1999, 9, 30)));
  2785. }
  2786. {
  2787. auto sysTime = SysTime(Date(1998, 8, 31));
  2788. sysTime.add!"months"(13, AllowDayOverflow.no);
  2789. _assertPred!"=="(sysTime, SysTime(Date(1999, 9, 30)));
  2790. sysTime.add!"months"(-13, AllowDayOverflow.no);
  2791. _assertPred!"=="(sysTime, SysTime(Date(1998, 8, 30)));
  2792. }
  2793. {
  2794. auto sysTime = SysTime(Date(1997, 12, 31));
  2795. sysTime.add!"months"(13, AllowDayOverflow.no);
  2796. _assertPred!"=="(sysTime, SysTime(Date(1999, 1, 31)));
  2797. sysTime.add!"months"(-13, AllowDayOverflow.no);
  2798. _assertPred!"=="(sysTime, SysTime(Date(1997, 12, 31)));
  2799. }
  2800. {
  2801. auto sysTime = SysTime(Date(1997, 12, 31));
  2802. sysTime.add!"months"(14, AllowDayOverflow.no);
  2803. _assertPred!"=="(sysTime, SysTime(Date(1999, 2, 28)));
  2804. sysTime.add!"months"(-14, AllowDayOverflow.no);
  2805. _assertPred!"=="(sysTime, SysTime(Date(1997, 12, 28)));
  2806. }
  2807. {
  2808. auto sysTime = SysTime(Date(1998, 12, 31));
  2809. sysTime.add!"months"(14, AllowDayOverflow.no);
  2810. _assertPred!"=="(sysTime, SysTime(Date(2000, 2, 29)));
  2811. sysTime.add!"months"(-14, AllowDayOverflow.no);
  2812. _assertPred!"=="(sysTime, SysTime(Date(1998, 12, 29)));
  2813. }
  2814. {
  2815. auto sysTime = SysTime(Date(1999, 12, 31));
  2816. sysTime.add!"months"(14, AllowDayOverflow.no);
  2817. _assertPred!"=="(sysTime, SysTime(Date(2001, 2, 28)));
  2818. sysTime.add!"months"(-14, AllowDayOverflow.no);
  2819. _assertPred!"=="(sysTime, SysTime(Date(1999, 12, 28)));
  2820. }
  2821. {
  2822. auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), FracSec.from!"usecs"(5007));
  2823. sysTime.add!"months"(3, AllowDayOverflow.no);
  2824. _assertPred!"=="(sysTime, SysTime(DateTime(1999, 10, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
  2825. sysTime.add!"months"(-4, AllowDayOverflow.no);
  2826. _assertPred!"=="(sysTime, SysTime(DateTime(1999, 6, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
  2827. }
  2828. {
  2829. auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
  2830. sysTime.add!"months"(14, AllowDayOverflow.no);
  2831. _assertPred!"=="(sysTime, SysTime(DateTime(2000, 2, 29, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  2832. sysTime.add!"months"(-14, AllowDayOverflow.no);
  2833. _assertPred!"=="(sysTime, SysTime(DateTime(1998, 12, 29, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  2834. }
  2835. {
  2836. auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
  2837. sysTime.add!"months"(14, AllowDayOverflow.no);
  2838. _assertPred!"=="(sysTime, SysTime(DateTime(2001, 2, 28, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  2839. sysTime.add!"months"(-14, AllowDayOverflow.no);
  2840. _assertPred!"=="(sysTime, SysTime(DateTime(1999, 12, 28, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  2841. }
  2842. //Test B.C.
  2843. {
  2844. auto sysTime = SysTime(Date(-1999, 7, 6));
  2845. sysTime.add!"months"(3, AllowDayOverflow.no);
  2846. _assertPred!"=="(sysTime, SysTime(Date(-1999, 10, 6)));
  2847. sysTime.add!"months"(-4, AllowDayOverflow.no);
  2848. _assertPred!"=="(sysTime, SysTime(Date(-1999, 6, 6)));
  2849. }
  2850. {
  2851. auto sysTime = SysTime(Date(-1999, 7, 6));
  2852. sysTime.add!"months"(6, AllowDayOverflow.no);
  2853. _assertPred!"=="(sysTime, SysTime(Date(-1998, 1, 6)));
  2854. sysTime.add!"months"(-6, AllowDayOverflow.no);
  2855. _assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 6)));
  2856. }
  2857. {
  2858. auto sysTime = SysTime(Date(-1999, 7, 6));
  2859. sysTime.add!"months"(-27, AllowDayOverflow.no);
  2860. _assertPred!"=="(sysTime, SysTime(Date(-2001, 4, 6)));
  2861. sysTime.add!"months"(28, AllowDayOverflow.no);
  2862. _assertPred!"=="(sysTime, SysTime(Date(-1999, 8, 6)));
  2863. }
  2864. {
  2865. auto sysTime = SysTime(Date(-1999, 5, 31));
  2866. sysTime.add!"months"(1, AllowDayOverflow.no);
  2867. _assertPred!"=="(sysTime, SysTime(Date(-1999, 6, 30)));
  2868. }
  2869. {
  2870. auto sysTime = SysTime(Date(-1999, 5, 31));
  2871. sysTime.add!"months"(-1, AllowDayOverflow.no);
  2872. _assertPred!"=="(sysTime, SysTime(Date(-1999, 4, 30)));
  2873. }
  2874. {
  2875. auto sysTime = SysTime(Date(-1999, 2, 28));
  2876. sysTime.add!"months"(-12, AllowDayOverflow.no);
  2877. _assertPred!"=="(sysTime, SysTime(Date(-2000, 2, 28)));
  2878. }
  2879. {
  2880. auto sysTime = SysTime(Date(-2000, 2, 29));
  2881. sysTime.add!"months"(-12, AllowDayOverflow.no);
  2882. _assertPred!"=="(sysTime, SysTime(Date(-2001, 2, 28)));
  2883. }
  2884. {
  2885. auto sysTime = SysTime(Date(-1999, 7, 31));
  2886. sysTime.add!"months"(1, AllowDayOverflow.no);
  2887. _assertPred!"=="(sysTime, SysTime(Date(-1999, 8, 31)));
  2888. sysTime.add!"months"(1, AllowDayOverflow.no);
  2889. _assertPred!"=="(sysTime, SysTime(Date(-1999, 9, 30)));
  2890. }
  2891. {
  2892. auto sysTime = SysTime(Date(-1998, 8, 31));
  2893. sysTime.add!"months"(13, AllowDayOverflow.no);
  2894. _assertPred!"=="(sysTime, SysTime(Date(-1997, 9, 30)));
  2895. sysTime.add!"months"(-13, AllowDayOverflow.no);
  2896. _assertPred!"=="(sysTime, SysTime(Date(-1998, 8, 30)));
  2897. }
  2898. {
  2899. auto sysTime = SysTime(Date(-1997, 12, 31));
  2900. sysTime.add!"months"(13, AllowDayOverflow.no);
  2901. _assertPred!"=="(sysTime, SysTime(Date(-1995, 1, 31)));
  2902. sysTime.add!"months"(-13, AllowDayOverflow.no);
  2903. _assertPred!"=="(sysTime, SysTime(Date(-1997, 12, 31)));
  2904. }
  2905. {
  2906. auto sysTime = SysTime(Date(-1997, 12, 31));
  2907. sysTime.add!"months"(14, AllowDayOverflow.no);
  2908. _assertPred!"=="(sysTime, SysTime(Date(-1995, 2, 28)));
  2909. sysTime.add!"months"(-14, AllowDayOverflow.no);
  2910. _assertPred!"=="(sysTime, SysTime(Date(-1997, 12, 28)));
  2911. }
  2912. {
  2913. auto sysTime = SysTime(Date(-2002, 12, 31));
  2914. sysTime.add!"months"(14, AllowDayOverflow.no);
  2915. _assertPred!"=="(sysTime, SysTime(Date(-2000, 2, 29)));
  2916. sysTime.add!"months"(-14, AllowDayOverflow.no);
  2917. _assertPred!"=="(sysTime, SysTime(Date(-2002, 12, 29)));
  2918. }
  2919. {
  2920. auto sysTime = SysTime(Date(-2001, 12, 31));
  2921. sysTime.add!"months"(14, AllowDayOverflow.no);
  2922. _assertPred!"=="(sysTime, SysTime(Date(-1999, 2, 28)));
  2923. sysTime.add!"months"(-14, AllowDayOverflow.no);
  2924. _assertPred!"=="(sysTime, SysTime(Date(-2001, 12, 28)));
  2925. }
  2926. {
  2927. auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), FracSec.from!"usecs"(5007));
  2928. sysTime.add!"months"(3, AllowDayOverflow.no);
  2929. _assertPred!"=="(sysTime, SysTime(DateTime(-1999, 10, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
  2930. sysTime.add!"months"(-4, AllowDayOverflow.no);
  2931. _assertPred!"=="(sysTime, SysTime(DateTime(-1999, 6, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
  2932. }
  2933. {
  2934. auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
  2935. sysTime.add!"months"(14, AllowDayOverflow.no);
  2936. _assertPred!"=="(sysTime, SysTime(DateTime(-2000, 2, 29, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  2937. sysTime.add!"months"(-14, AllowDayOverflow.no);
  2938. _assertPred!"=="(sysTime, SysTime(DateTime(-2002, 12, 29, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  2939. }
  2940. {
  2941. auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
  2942. sysTime.add!"months"(14, AllowDayOverflow.no);
  2943. _assertPred!"=="(sysTime, SysTime(DateTime(-1999, 2, 28, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  2944. sysTime.add!"months"(-14, AllowDayOverflow.no);
  2945. _assertPred!"=="(sysTime, SysTime(DateTime(-2001, 12, 28, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  2946. }
  2947. //Test Both
  2948. {
  2949. auto sysTime = SysTime(Date(1, 1, 1));
  2950. sysTime.add!"months"(-1, AllowDayOverflow.no);
  2951. _assertPred!"=="(sysTime, SysTime(Date(0, 12, 1)));
  2952. sysTime.add!"months"(1, AllowDayOverflow.no);
  2953. _assertPred!"=="(sysTime, SysTime(Date(1, 1, 1)));
  2954. }
  2955. {
  2956. auto sysTime = SysTime(Date(4, 1, 1));
  2957. sysTime.add!"months"(-48, AllowDayOverflow.no);
  2958. _assertPred!"=="(sysTime, SysTime(Date(0, 1, 1)));
  2959. sysTime.add!"months"(48, AllowDayOverflow.no);
  2960. _assertPred!"=="(sysTime, SysTime(Date(4, 1, 1)));
  2961. }
  2962. {
  2963. auto sysTime = SysTime(Date(4, 3, 31));
  2964. sysTime.add!"months"(-49, AllowDayOverflow.no);
  2965. _assertPred!"=="(sysTime, SysTime(Date(0, 2, 29)));
  2966. sysTime.add!"months"(49, AllowDayOverflow.no);
  2967. _assertPred!"=="(sysTime, SysTime(Date(4, 3, 29)));
  2968. }
  2969. {
  2970. auto sysTime = SysTime(Date(4, 3, 31));
  2971. sysTime.add!"months"(-85, AllowDayOverflow.no);
  2972. _assertPred!"=="(sysTime, SysTime(Date(-3, 2, 28)));
  2973. sysTime.add!"months"(85, AllowDayOverflow.no);
  2974. _assertPred!"=="(sysTime, SysTime(Date(4, 3, 28)));
  2975. }
  2976. {
  2977. auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
  2978. sysTime.add!"months"(-1, AllowDayOverflow.no);
  2979. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  2980. sysTime.add!"months"(1, AllowDayOverflow.no);
  2981. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  2982. }
  2983. {
  2984. auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
  2985. sysTime.add!"months"(-1, AllowDayOverflow.no);
  2986. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  2987. sysTime.add!"months"(1, AllowDayOverflow.no);
  2988. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  2989. }
  2990. {
  2991. auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
  2992. sysTime.add!"months"(1, AllowDayOverflow.no);
  2993. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  2994. sysTime.add!"months"(-1, AllowDayOverflow.no);
  2995. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  2996. }
  2997. {
  2998. auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
  2999. sysTime.add!"months"(1, AllowDayOverflow.no);
  3000. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  3001. sysTime.add!"months"(-1, AllowDayOverflow.no);
  3002. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  3003. }
  3004. {
  3005. auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), FracSec.from!"hnsecs"(17));
  3006. sysTime.add!"months"(-1, AllowDayOverflow.no);
  3007. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 0, 7, 9), FracSec.from!"hnsecs"(17)));
  3008. sysTime.add!"months"(1, AllowDayOverflow.no);
  3009. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 7, 9), FracSec.from!"hnsecs"(17)));
  3010. }
  3011. {
  3012. auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), FracSec.from!"msecs"(9));
  3013. sysTime.add!"months"(-85, AllowDayOverflow.no);
  3014. _assertPred!"=="(sysTime, SysTime(DateTime(-3, 2, 28, 12, 11, 10), FracSec.from!"msecs"(9)));
  3015. sysTime.add!"months"(85, AllowDayOverflow.no);
  3016. _assertPred!"=="(sysTime, SysTime(DateTime(4, 3, 28, 12, 11, 10), FracSec.from!"msecs"(9)));
  3017. }
  3018. {
  3019. auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), FracSec.from!"msecs"(9));
  3020. sysTime.add!"months"(85, AllowDayOverflow.no);
  3021. _assertPred!"=="(sysTime, SysTime(DateTime(4, 4, 30, 12, 11, 10), FracSec.from!"msecs"(9)));
  3022. sysTime.add!"months"(-85, AllowDayOverflow.no);
  3023. _assertPred!"=="(sysTime, SysTime(DateTime(-3, 3, 30, 12, 11, 10), FracSec.from!"msecs"(9)));
  3024. }
  3025. }
  3026. }
  3027. /++
  3028. Adds the given number of years or months to this $(D SysTime). A
  3029. negative number will subtract.
  3030. The difference between rolling and adding is that rolling does not
  3031. affect larger units. So, if you roll a $(D SysTime) 12 months, you
  3032. get the exact same $(D SysTime). However, the days can still be affected
  3033. due to the differing number of days in each month.
  3034. Because there are no units larger than years, there is no difference
  3035. between adding and rolling years.
  3036. Params:
  3037. units = The type of units to add ("years" or "months").
  3038. value = The number of months or years to add to this
  3039. $(D SysTime).
  3040. allowOverflow = Whether the days should be allowed to overflow,
  3041. causing the month to increment.
  3042. Examples:
  3043. --------------------
  3044. auto st1 = SysTime(DateTime(2010, 1, 1, 12, 33, 33));
  3045. st1.roll!"months"(1);
  3046. assert(st1 == SysTime(DateTime(2010, 2, 1, 12, 33, 33)));
  3047. auto st2 = SysTime(DateTime(2010, 1, 1, 12, 33, 33));
  3048. st2.roll!"months"(-1);
  3049. assert(st2 == SysTime(DateTime(2010, 12, 1, 12, 33, 33)));
  3050. auto st3 = SysTime(DateTime(1999, 1, 29, 12, 33, 33));
  3051. st3.roll!"months"(1);
  3052. assert(st3 == SysTime(DateTime(1999, 3, 1, 12, 33, 33)));
  3053. auto st4 = SysTime(DateTime(1999, 1, 29, 12, 33, 33));
  3054. st4.roll!"months"(1, AllowDayOverflow.no);
  3055. assert(st4 == SysTime(DateTime(1999, 2, 28, 12, 33, 33)));
  3056. auto st5 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
  3057. st5.roll!"years"(1);
  3058. assert(st5 == SysTime(DateTime(2001, 3, 1, 12, 30, 33)));
  3059. auto st6 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
  3060. st6.roll!"years"(1, AllowDayOverflow.no);
  3061. assert(st6 == SysTime(DateTime(2001, 2, 28, 12, 30, 33)));
  3062. --------------------
  3063. +/
  3064. /+ref SysTime+/ void roll(string units)(long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) nothrow
  3065. if(units == "years")
  3066. {
  3067. add!"years"(value, allowOverflow);
  3068. }
  3069. unittest
  3070. {
  3071. version(testStdDateTime)
  3072. {
  3073. //Verify Examples.
  3074. auto st1 = SysTime(DateTime(2010, 1, 1, 12, 33, 33));
  3075. st1.roll!"months"(1);
  3076. assert(st1 == SysTime(DateTime(2010, 2, 1, 12, 33, 33)));
  3077. auto st2 = SysTime(DateTime(2010, 1, 1, 12, 33, 33));
  3078. st2.roll!"months"(-1);
  3079. assert(st2 == SysTime(DateTime(2010, 12, 1, 12, 33, 33)));
  3080. auto st3 = SysTime(DateTime(1999, 1, 29, 12, 33, 33));
  3081. st3.roll!"months"(1);
  3082. assert(st3 == SysTime(DateTime(1999, 3, 1, 12, 33, 33)));
  3083. auto st4 = SysTime(DateTime(1999, 1, 29, 12, 33, 33));
  3084. st4.roll!"months"(1, AllowDayOverflow.no);
  3085. assert(st4 == SysTime(DateTime(1999, 2, 28, 12, 33, 33)));
  3086. auto st5 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
  3087. st5.roll!"years"(1);
  3088. assert(st5 == SysTime(DateTime(2001, 3, 1, 12, 30, 33)));
  3089. auto st6 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
  3090. st6.roll!"years"(1, AllowDayOverflow.no);
  3091. assert(st6 == SysTime(DateTime(2001, 2, 28, 12, 30, 33)));
  3092. }
  3093. }
  3094. unittest
  3095. {
  3096. version(testStdDateTime)
  3097. {
  3098. auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  3099. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  3100. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  3101. static assert(__traits(compiles, st.roll!"years"(4)));
  3102. static assert(!__traits(compiles, cst.roll!"years"(4)));
  3103. //static assert(!__traits(compiles, ist.roll!"years"(4)));
  3104. }
  3105. }
  3106. //Shares documentation with "years" version.
  3107. /+ref SysTime+/ void roll(string units)(long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) nothrow
  3108. if(units == "months")
  3109. {
  3110. auto hnsecs = adjTime;
  3111. auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
  3112. if(hnsecs < 0)
  3113. {
  3114. hnsecs += convert!("hours", "hnsecs")(24);
  3115. --days;
  3116. }
  3117. auto date = Date(cast(int)days);
  3118. date.roll!"months"(value, allowOverflow);
  3119. days = date.dayOfGregorianCal - 1;
  3120. if(days < 0)
  3121. {
  3122. hnsecs -= convert!("hours", "hnsecs")(24);
  3123. ++days;
  3124. }
  3125. immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
  3126. adjTime = newDaysHNSecs + hnsecs;
  3127. }
  3128. //Test roll!"months"() with AllowDayOverlow.yes
  3129. unittest
  3130. {
  3131. version(testStdDateTime)
  3132. {
  3133. //Test A.D.
  3134. {
  3135. auto sysTime = SysTime(Date(1999, 7, 6));
  3136. sysTime.roll!"months"(3);
  3137. _assertPred!"=="(sysTime, SysTime(Date(1999, 10, 6)));
  3138. sysTime.roll!"months"(-4);
  3139. _assertPred!"=="(sysTime, SysTime(Date(1999, 6, 6)));
  3140. }
  3141. {
  3142. auto sysTime = SysTime(Date(1999, 7, 6));
  3143. sysTime.roll!"months"(6);
  3144. _assertPred!"=="(sysTime, SysTime(Date(1999, 1, 6)));
  3145. sysTime.roll!"months"(-6);
  3146. _assertPred!"=="(sysTime, SysTime(Date(1999, 7, 6)));
  3147. }
  3148. {
  3149. auto sysTime = SysTime(Date(1999, 7, 6));
  3150. sysTime.roll!"months"(27);
  3151. _assertPred!"=="(sysTime, SysTime(Date(1999, 10, 6)));
  3152. sysTime.roll!"months"(-28);
  3153. _assertPred!"=="(sysTime, SysTime(Date(1999, 6, 6)));
  3154. }
  3155. {
  3156. auto sysTime = SysTime(Date(1999, 5, 31));
  3157. sysTime.roll!"months"(1);
  3158. _assertPred!"=="(sysTime, SysTime(Date(1999, 7, 1)));
  3159. }
  3160. {
  3161. auto sysTime = SysTime(Date(1999, 5, 31));
  3162. sysTime.roll!"months"(-1);
  3163. _assertPred!"=="(sysTime, SysTime(Date(1999, 5, 1)));
  3164. }
  3165. {
  3166. auto sysTime = SysTime(Date(1999, 2, 28));
  3167. sysTime.roll!"months"(12);
  3168. _assertPred!"=="(sysTime, SysTime(Date(1999, 2, 28)));
  3169. }
  3170. {
  3171. auto sysTime = SysTime(Date(2000, 2, 29));
  3172. sysTime.roll!"months"(12);
  3173. _assertPred!"=="(sysTime, SysTime(Date(2000, 2, 29)));
  3174. }
  3175. {
  3176. auto sysTime = SysTime(Date(1999, 7, 31));
  3177. sysTime.roll!"months"(1);
  3178. _assertPred!"=="(sysTime, SysTime(Date(1999, 8, 31)));
  3179. sysTime.roll!"months"(1);
  3180. _assertPred!"=="(sysTime, SysTime(Date(1999, 10, 1)));
  3181. }
  3182. {
  3183. auto sysTime = SysTime(Date(1998, 8, 31));
  3184. sysTime.roll!"months"(13);
  3185. _assertPred!"=="(sysTime, SysTime(Date(1998, 10, 1)));
  3186. sysTime.roll!"months"(-13);
  3187. _assertPred!"=="(sysTime, SysTime(Date(1998, 9, 1)));
  3188. }
  3189. {
  3190. auto sysTime = SysTime(Date(1997, 12, 31));
  3191. sysTime.roll!"months"(13);
  3192. _assertPred!"=="(sysTime, SysTime(Date(1997, 1, 31)));
  3193. sysTime.roll!"months"(-13);
  3194. _assertPred!"=="(sysTime, SysTime(Date(1997, 12, 31)));
  3195. }
  3196. {
  3197. auto sysTime = SysTime(Date(1997, 12, 31));
  3198. sysTime.roll!"months"(14);
  3199. _assertPred!"=="(sysTime, SysTime(Date(1997, 3, 3)));
  3200. sysTime.roll!"months"(-14);
  3201. _assertPred!"=="(sysTime, SysTime(Date(1997, 1, 3)));
  3202. }
  3203. {
  3204. auto sysTime = SysTime(Date(1998, 12, 31));
  3205. sysTime.roll!"months"(14);
  3206. _assertPred!"=="(sysTime, SysTime(Date(1998, 3, 3)));
  3207. sysTime.roll!"months"(-14);
  3208. _assertPred!"=="(sysTime, SysTime(Date(1998, 1, 3)));
  3209. }
  3210. {
  3211. auto sysTime = SysTime(Date(1999, 12, 31));
  3212. sysTime.roll!"months"(14);
  3213. _assertPred!"=="(sysTime, SysTime(Date(1999, 3, 3)));
  3214. sysTime.roll!"months"(-14);
  3215. _assertPred!"=="(sysTime, SysTime(Date(1999, 1, 3)));
  3216. }
  3217. {
  3218. auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), FracSec.from!"usecs"(5007));
  3219. sysTime.roll!"months"(3);
  3220. _assertPred!"=="(sysTime, SysTime(DateTime(1999, 10, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
  3221. sysTime.roll!"months"(-4);
  3222. _assertPred!"=="(sysTime, SysTime(DateTime(1999, 6, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
  3223. }
  3224. {
  3225. auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
  3226. sysTime.roll!"months"(14);
  3227. _assertPred!"=="(sysTime, SysTime(DateTime(1998, 3, 3, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  3228. sysTime.roll!"months"(-14);
  3229. _assertPred!"=="(sysTime, SysTime(DateTime(1998, 1, 3, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  3230. }
  3231. {
  3232. auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
  3233. sysTime.roll!"months"(14);
  3234. _assertPred!"=="(sysTime, SysTime(DateTime(1999, 3, 3, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  3235. sysTime.roll!"months"(-14);
  3236. _assertPred!"=="(sysTime, SysTime(DateTime(1999, 1, 3, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  3237. }
  3238. //Test B.C.
  3239. {
  3240. auto sysTime = SysTime(Date(-1999, 7, 6));
  3241. sysTime.roll!"months"(3);
  3242. _assertPred!"=="(sysTime, SysTime(Date(-1999, 10, 6)));
  3243. sysTime.roll!"months"(-4);
  3244. _assertPred!"=="(sysTime, SysTime(Date(-1999, 6, 6)));
  3245. }
  3246. {
  3247. auto sysTime = SysTime(Date(-1999, 7, 6));
  3248. sysTime.roll!"months"(6);
  3249. _assertPred!"=="(sysTime, SysTime(Date(-1999, 1, 6)));
  3250. sysTime.roll!"months"(-6);
  3251. _assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 6)));
  3252. }
  3253. {
  3254. auto sysTime = SysTime(Date(-1999, 7, 6));
  3255. sysTime.roll!"months"(-27);
  3256. _assertPred!"=="(sysTime, SysTime(Date(-1999, 4, 6)));
  3257. sysTime.roll!"months"(28);
  3258. _assertPred!"=="(sysTime, SysTime(Date(-1999, 8, 6)));
  3259. }
  3260. {
  3261. auto sysTime = SysTime(Date(-1999, 5, 31));
  3262. sysTime.roll!"months"(1);
  3263. _assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 1)));
  3264. }
  3265. {
  3266. auto sysTime = SysTime(Date(-1999, 5, 31));
  3267. sysTime.roll!"months"(-1);
  3268. _assertPred!"=="(sysTime, SysTime(Date(-1999, 5, 1)));
  3269. }
  3270. {
  3271. auto sysTime = SysTime(Date(-1999, 2, 28));
  3272. sysTime.roll!"months"(-12);
  3273. _assertPred!"=="(sysTime, SysTime(Date(-1999, 2, 28)));
  3274. }
  3275. {
  3276. auto sysTime = SysTime(Date(-2000, 2, 29));
  3277. sysTime.roll!"months"(-12);
  3278. _assertPred!"=="(sysTime, SysTime(Date(-2000, 2, 29)));
  3279. }
  3280. {
  3281. auto sysTime = SysTime(Date(-1999, 7, 31));
  3282. sysTime.roll!"months"(1);
  3283. _assertPred!"=="(sysTime, SysTime(Date(-1999, 8, 31)));
  3284. sysTime.roll!"months"(1);
  3285. _assertPred!"=="(sysTime, SysTime(Date(-1999, 10, 1)));
  3286. }
  3287. {
  3288. auto sysTime = SysTime(Date(-1998, 8, 31));
  3289. sysTime.roll!"months"(13);
  3290. _assertPred!"=="(sysTime, SysTime(Date(-1998, 10, 1)));
  3291. sysTime.roll!"months"(-13);
  3292. _assertPred!"=="(sysTime, SysTime(Date(-1998, 9, 1)));
  3293. }
  3294. {
  3295. auto sysTime = SysTime(Date(-1997, 12, 31));
  3296. sysTime.roll!"months"(13);
  3297. _assertPred!"=="(sysTime, SysTime(Date(-1997, 1, 31)));
  3298. sysTime.roll!"months"(-13);
  3299. _assertPred!"=="(sysTime, SysTime(Date(-1997, 12, 31)));
  3300. }
  3301. {
  3302. auto sysTime = SysTime(Date(-1997, 12, 31));
  3303. sysTime.roll!"months"(14);
  3304. _assertPred!"=="(sysTime, SysTime(Date(-1997, 3, 3)));
  3305. sysTime.roll!"months"(-14);
  3306. _assertPred!"=="(sysTime, SysTime(Date(-1997, 1, 3)));
  3307. }
  3308. {
  3309. auto sysTime = SysTime(Date(-2002, 12, 31));
  3310. sysTime.roll!"months"(14);
  3311. _assertPred!"=="(sysTime, SysTime(Date(-2002, 3, 3)));
  3312. sysTime.roll!"months"(-14);
  3313. _assertPred!"=="(sysTime, SysTime(Date(-2002, 1, 3)));
  3314. }
  3315. {
  3316. auto sysTime = SysTime(Date(-2001, 12, 31));
  3317. sysTime.roll!"months"(14);
  3318. _assertPred!"=="(sysTime, SysTime(Date(-2001, 3, 3)));
  3319. sysTime.roll!"months"(-14);
  3320. _assertPred!"=="(sysTime, SysTime(Date(-2001, 1, 3)));
  3321. }
  3322. {
  3323. auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
  3324. sysTime.roll!"months"(-1);
  3325. _assertPred!"=="(sysTime, SysTime(DateTime(1, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  3326. sysTime.roll!"months"(1);
  3327. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  3328. }
  3329. {
  3330. auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
  3331. sysTime.roll!"months"(-1);
  3332. _assertPred!"=="(sysTime, SysTime(DateTime(1, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  3333. sysTime.roll!"months"(1);
  3334. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  3335. }
  3336. {
  3337. auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
  3338. sysTime.roll!"months"(1);
  3339. _assertPred!"=="(sysTime, SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  3340. sysTime.roll!"months"(-1);
  3341. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  3342. }
  3343. {
  3344. auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
  3345. sysTime.roll!"months"(1);
  3346. _assertPred!"=="(sysTime, SysTime(DateTime(0, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  3347. sysTime.roll!"months"(-1);
  3348. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  3349. }
  3350. {
  3351. auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), FracSec.from!"hnsecs"(5007));
  3352. sysTime.roll!"months"(3);
  3353. _assertPred!"=="(sysTime, SysTime(DateTime(-1999, 10, 6, 12, 2, 7), FracSec.from!"hnsecs"(5007)));
  3354. sysTime.roll!"months"(-4);
  3355. _assertPred!"=="(sysTime, SysTime(DateTime(-1999, 6, 6, 12, 2, 7), FracSec.from!"hnsecs"(5007)));
  3356. }
  3357. {
  3358. auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
  3359. sysTime.roll!"months"(14);
  3360. _assertPred!"=="(sysTime, SysTime(DateTime(-2002, 3, 3, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  3361. sysTime.roll!"months"(-14);
  3362. _assertPred!"=="(sysTime, SysTime(DateTime(-2002, 1, 3, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  3363. }
  3364. {
  3365. auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
  3366. sysTime.roll!"months"(14);
  3367. _assertPred!"=="(sysTime, SysTime(DateTime(-2001, 3, 3, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  3368. sysTime.roll!"months"(-14);
  3369. _assertPred!"=="(sysTime, SysTime(DateTime(-2001, 1, 3, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  3370. }
  3371. //Test Both
  3372. {
  3373. auto sysTime = SysTime(Date(1, 1, 1));
  3374. sysTime.roll!"months"(-1);
  3375. _assertPred!"=="(sysTime, SysTime(Date(1, 12, 1)));
  3376. sysTime.roll!"months"(1);
  3377. _assertPred!"=="(sysTime, SysTime(Date(1, 1, 1)));
  3378. }
  3379. {
  3380. auto sysTime = SysTime(Date(4, 1, 1));
  3381. sysTime.roll!"months"(-48);
  3382. _assertPred!"=="(sysTime, SysTime(Date(4, 1, 1)));
  3383. sysTime.roll!"months"(48);
  3384. _assertPred!"=="(sysTime, SysTime(Date(4, 1, 1)));
  3385. }
  3386. {
  3387. auto sysTime = SysTime(Date(4, 3, 31));
  3388. sysTime.roll!"months"(-49);
  3389. _assertPred!"=="(sysTime, SysTime(Date(4, 3, 2)));
  3390. sysTime.roll!"months"(49);
  3391. _assertPred!"=="(sysTime, SysTime(Date(4, 4, 2)));
  3392. }
  3393. {
  3394. auto sysTime = SysTime(Date(4, 3, 31));
  3395. sysTime.roll!"months"(-85);
  3396. _assertPred!"=="(sysTime, SysTime(Date(4, 3, 2)));
  3397. sysTime.roll!"months"(85);
  3398. _assertPred!"=="(sysTime, SysTime(Date(4, 4, 2)));
  3399. }
  3400. {
  3401. auto sysTime = SysTime(Date(-1, 1, 1));
  3402. sysTime.roll!"months"(-1);
  3403. _assertPred!"=="(sysTime, SysTime(Date(-1, 12, 1)));
  3404. sysTime.roll!"months"(1);
  3405. _assertPred!"=="(sysTime, SysTime(Date(-1, 1, 1)));
  3406. }
  3407. {
  3408. auto sysTime = SysTime(Date(-4, 1, 1));
  3409. sysTime.roll!"months"(-48);
  3410. _assertPred!"=="(sysTime, SysTime(Date(-4, 1, 1)));
  3411. sysTime.roll!"months"(48);
  3412. _assertPred!"=="(sysTime, SysTime(Date(-4, 1, 1)));
  3413. }
  3414. {
  3415. auto sysTime = SysTime(Date(-4, 3, 31));
  3416. sysTime.roll!"months"(-49);
  3417. _assertPred!"=="(sysTime, SysTime(Date(-4, 3, 2)));
  3418. sysTime.roll!"months"(49);
  3419. _assertPred!"=="(sysTime, SysTime(Date(-4, 4, 2)));
  3420. }
  3421. {
  3422. auto sysTime = SysTime(Date(-4, 3, 31));
  3423. sysTime.roll!"months"(-85);
  3424. _assertPred!"=="(sysTime, SysTime(Date(-4, 3, 2)));
  3425. sysTime.roll!"months"(85);
  3426. _assertPred!"=="(sysTime, SysTime(Date(-4, 4, 2)));
  3427. }
  3428. {
  3429. auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), FracSec.from!"hnsecs"(17));
  3430. sysTime.roll!"months"(-1);
  3431. _assertPred!"=="(sysTime, SysTime(DateTime(1, 12, 1, 0, 7, 9), FracSec.from!"hnsecs"(17)));
  3432. sysTime.roll!"months"(1);
  3433. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 7, 9), FracSec.from!"hnsecs"(17)));
  3434. }
  3435. {
  3436. auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), FracSec.from!"msecs"(9));
  3437. sysTime.roll!"months"(-85);
  3438. _assertPred!"=="(sysTime, SysTime(DateTime(4, 3, 2, 12, 11, 10), FracSec.from!"msecs"(9)));
  3439. sysTime.roll!"months"(85);
  3440. _assertPred!"=="(sysTime, SysTime(DateTime(4, 4, 2, 12, 11, 10), FracSec.from!"msecs"(9)));
  3441. }
  3442. {
  3443. auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), FracSec.from!"msecs"(9));
  3444. sysTime.roll!"months"(85);
  3445. _assertPred!"=="(sysTime, SysTime(DateTime(-3, 5, 1, 12, 11, 10), FracSec.from!"msecs"(9)));
  3446. sysTime.roll!"months"(-85);
  3447. _assertPred!"=="(sysTime, SysTime(DateTime(-3, 4, 1, 12, 11, 10), FracSec.from!"msecs"(9)));
  3448. }
  3449. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  3450. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  3451. static assert(!__traits(compiles, cst.roll!"months"(4)));
  3452. //static assert(!__traits(compiles, ist.roll!"months"(4)));
  3453. //Verify Examples.
  3454. auto st1 = SysTime(DateTime(2010, 1, 1, 12, 33, 33));
  3455. st1.roll!"months"(1);
  3456. assert(st1 == SysTime(DateTime(2010, 2, 1, 12, 33, 33)));
  3457. auto st2 = SysTime(DateTime(2010, 1, 1, 12, 33, 33));
  3458. st2.roll!"months"(-1);
  3459. assert(st2 == SysTime(DateTime(2010, 12, 1, 12, 33, 33)));
  3460. auto st3 = SysTime(DateTime(1999, 1, 29, 12, 33, 33));
  3461. st3.roll!"months"(1);
  3462. assert(st3 == SysTime(DateTime(1999, 3, 1, 12, 33, 33)));
  3463. auto st4 = SysTime(DateTime(1999, 1, 29, 12, 33, 33));
  3464. st4.roll!"months"(1, AllowDayOverflow.no);
  3465. assert(st4 == SysTime(DateTime(1999, 2, 28, 12, 33, 33)));
  3466. }
  3467. }
  3468. //Test roll!"months"() with AllowDayOverlow.no
  3469. unittest
  3470. {
  3471. version(testStdDateTime)
  3472. {
  3473. //Test A.D.
  3474. {
  3475. auto sysTime = SysTime(Date(1999, 7, 6));
  3476. sysTime.roll!"months"(3, AllowDayOverflow.no);
  3477. _assertPred!"=="(sysTime, SysTime(Date(1999, 10, 6)));
  3478. sysTime.roll!"months"(-4, AllowDayOverflow.no);
  3479. _assertPred!"=="(sysTime, SysTime(Date(1999, 6, 6)));
  3480. }
  3481. {
  3482. auto sysTime = SysTime(Date(1999, 7, 6));
  3483. sysTime.roll!"months"(6, AllowDayOverflow.no);
  3484. _assertPred!"=="(sysTime, SysTime(Date(1999, 1, 6)));
  3485. sysTime.roll!"months"(-6, AllowDayOverflow.no);
  3486. _assertPred!"=="(sysTime, SysTime(Date(1999, 7, 6)));
  3487. }
  3488. {
  3489. auto sysTime = SysTime(Date(1999, 7, 6));
  3490. sysTime.roll!"months"(27, AllowDayOverflow.no);
  3491. _assertPred!"=="(sysTime, SysTime(Date(1999, 10, 6)));
  3492. sysTime.roll!"months"(-28, AllowDayOverflow.no);
  3493. _assertPred!"=="(sysTime, SysTime(Date(1999, 6, 6)));
  3494. }
  3495. {
  3496. auto sysTime = SysTime(Date(1999, 5, 31));
  3497. sysTime.roll!"months"(1, AllowDayOverflow.no);
  3498. _assertPred!"=="(sysTime, SysTime(Date(1999, 6, 30)));
  3499. }
  3500. {
  3501. auto sysTime = SysTime(Date(1999, 5, 31));
  3502. sysTime.roll!"months"(-1, AllowDayOverflow.no);
  3503. _assertPred!"=="(sysTime, SysTime(Date(1999, 4, 30)));
  3504. }
  3505. {
  3506. auto sysTime = SysTime(Date(1999, 2, 28));
  3507. sysTime.roll!"months"(12, AllowDayOverflow.no);
  3508. _assertPred!"=="(sysTime, SysTime(Date(1999, 2, 28)));
  3509. }
  3510. {
  3511. auto sysTime = SysTime(Date(2000, 2, 29));
  3512. sysTime.roll!"months"(12, AllowDayOverflow.no);
  3513. _assertPred!"=="(sysTime, SysTime(Date(2000, 2, 29)));
  3514. }
  3515. {
  3516. auto sysTime = SysTime(Date(1999, 7, 31));
  3517. sysTime.roll!"months"(1, AllowDayOverflow.no);
  3518. _assertPred!"=="(sysTime, SysTime(Date(1999, 8, 31)));
  3519. sysTime.roll!"months"(1, AllowDayOverflow.no);
  3520. _assertPred!"=="(sysTime, SysTime(Date(1999, 9, 30)));
  3521. }
  3522. {
  3523. auto sysTime = SysTime(Date(1998, 8, 31));
  3524. sysTime.roll!"months"(13, AllowDayOverflow.no);
  3525. _assertPred!"=="(sysTime, SysTime(Date(1998, 9, 30)));
  3526. sysTime.roll!"months"(-13, AllowDayOverflow.no);
  3527. _assertPred!"=="(sysTime, SysTime(Date(1998, 8, 30)));
  3528. }
  3529. {
  3530. auto sysTime = SysTime(Date(1997, 12, 31));
  3531. sysTime.roll!"months"(13, AllowDayOverflow.no);
  3532. _assertPred!"=="(sysTime, SysTime(Date(1997, 1, 31)));
  3533. sysTime.roll!"months"(-13, AllowDayOverflow.no);
  3534. _assertPred!"=="(sysTime, SysTime(Date(1997, 12, 31)));
  3535. }
  3536. {
  3537. auto sysTime = SysTime(Date(1997, 12, 31));
  3538. sysTime.roll!"months"(14, AllowDayOverflow.no);
  3539. _assertPred!"=="(sysTime, SysTime(Date(1997, 2, 28)));
  3540. sysTime.roll!"months"(-14, AllowDayOverflow.no);
  3541. _assertPred!"=="(sysTime, SysTime(Date(1997, 12, 28)));
  3542. }
  3543. {
  3544. auto sysTime = SysTime(Date(1998, 12, 31));
  3545. sysTime.roll!"months"(14, AllowDayOverflow.no);
  3546. _assertPred!"=="(sysTime, SysTime(Date(1998, 2, 28)));
  3547. sysTime.roll!"months"(-14, AllowDayOverflow.no);
  3548. _assertPred!"=="(sysTime, SysTime(Date(1998, 12, 28)));
  3549. }
  3550. {
  3551. auto sysTime = SysTime(Date(1999, 12, 31));
  3552. sysTime.roll!"months"(14, AllowDayOverflow.no);
  3553. _assertPred!"=="(sysTime, SysTime(Date(1999, 2, 28)));
  3554. sysTime.roll!"months"(-14, AllowDayOverflow.no);
  3555. _assertPred!"=="(sysTime, SysTime(Date(1999, 12, 28)));
  3556. }
  3557. {
  3558. auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), FracSec.from!"usecs"(5007));
  3559. sysTime.roll!"months"(3, AllowDayOverflow.no);
  3560. _assertPred!"=="(sysTime, SysTime(DateTime(1999, 10, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
  3561. sysTime.roll!"months"(-4, AllowDayOverflow.no);
  3562. _assertPred!"=="(sysTime, SysTime(DateTime(1999, 6, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
  3563. }
  3564. {
  3565. auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
  3566. sysTime.roll!"months"(14, AllowDayOverflow.no);
  3567. _assertPred!"=="(sysTime, SysTime(DateTime(1998, 2, 28, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  3568. sysTime.roll!"months"(-14, AllowDayOverflow.no);
  3569. _assertPred!"=="(sysTime, SysTime(DateTime(1998, 12, 28, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  3570. }
  3571. {
  3572. auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
  3573. sysTime.roll!"months"(14, AllowDayOverflow.no);
  3574. _assertPred!"=="(sysTime, SysTime(DateTime(1999, 2, 28, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  3575. sysTime.roll!"months"(-14, AllowDayOverflow.no);
  3576. _assertPred!"=="(sysTime, SysTime(DateTime(1999, 12, 28, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  3577. }
  3578. //Test B.C.
  3579. {
  3580. auto sysTime = SysTime(Date(-1999, 7, 6));
  3581. sysTime.roll!"months"(3, AllowDayOverflow.no);
  3582. _assertPred!"=="(sysTime, SysTime(Date(-1999, 10, 6)));
  3583. sysTime.roll!"months"(-4, AllowDayOverflow.no);
  3584. _assertPred!"=="(sysTime, SysTime(Date(-1999, 6, 6)));
  3585. }
  3586. {
  3587. auto sysTime = SysTime(Date(-1999, 7, 6));
  3588. sysTime.roll!"months"(6, AllowDayOverflow.no);
  3589. _assertPred!"=="(sysTime, SysTime(Date(-1999, 1, 6)));
  3590. sysTime.roll!"months"(-6, AllowDayOverflow.no);
  3591. _assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 6)));
  3592. }
  3593. {
  3594. auto sysTime = SysTime(Date(-1999, 7, 6));
  3595. sysTime.roll!"months"(-27, AllowDayOverflow.no);
  3596. _assertPred!"=="(sysTime, SysTime(Date(-1999, 4, 6)));
  3597. sysTime.roll!"months"(28, AllowDayOverflow.no);
  3598. _assertPred!"=="(sysTime, SysTime(Date(-1999, 8, 6)));
  3599. }
  3600. {
  3601. auto sysTime = SysTime(Date(-1999, 5, 31));
  3602. sysTime.roll!"months"(1, AllowDayOverflow.no);
  3603. _assertPred!"=="(sysTime, SysTime(Date(-1999, 6, 30)));
  3604. }
  3605. {
  3606. auto sysTime = SysTime(Date(-1999, 5, 31));
  3607. sysTime.roll!"months"(-1, AllowDayOverflow.no);
  3608. _assertPred!"=="(sysTime, SysTime(Date(-1999, 4, 30)));
  3609. }
  3610. {
  3611. auto sysTime = SysTime(Date(-1999, 2, 28));
  3612. sysTime.roll!"months"(-12, AllowDayOverflow.no);
  3613. _assertPred!"=="(sysTime, SysTime(Date(-1999, 2, 28)));
  3614. }
  3615. {
  3616. auto sysTime = SysTime(Date(-2000, 2, 29));
  3617. sysTime.roll!"months"(-12, AllowDayOverflow.no);
  3618. _assertPred!"=="(sysTime, SysTime(Date(-2000, 2, 29)));
  3619. }
  3620. {
  3621. auto sysTime = SysTime(Date(-1999, 7, 31));
  3622. sysTime.roll!"months"(1, AllowDayOverflow.no);
  3623. _assertPred!"=="(sysTime, SysTime(Date(-1999, 8, 31)));
  3624. sysTime.roll!"months"(1, AllowDayOverflow.no);
  3625. _assertPred!"=="(sysTime, SysTime(Date(-1999, 9, 30)));
  3626. }
  3627. {
  3628. auto sysTime = SysTime(Date(-1998, 8, 31));
  3629. sysTime.roll!"months"(13, AllowDayOverflow.no);
  3630. _assertPred!"=="(sysTime, SysTime(Date(-1998, 9, 30)));
  3631. sysTime.roll!"months"(-13, AllowDayOverflow.no);
  3632. _assertPred!"=="(sysTime, SysTime(Date(-1998, 8, 30)));
  3633. }
  3634. {
  3635. auto sysTime = SysTime(Date(-1997, 12, 31));
  3636. sysTime.roll!"months"(13, AllowDayOverflow.no);
  3637. _assertPred!"=="(sysTime, SysTime(Date(-1997, 1, 31)));
  3638. sysTime.roll!"months"(-13, AllowDayOverflow.no);
  3639. _assertPred!"=="(sysTime, SysTime(Date(-1997, 12, 31)));
  3640. }
  3641. {
  3642. auto sysTime = SysTime(Date(-1997, 12, 31));
  3643. sysTime.roll!"months"(14, AllowDayOverflow.no);
  3644. _assertPred!"=="(sysTime, SysTime(Date(-1997, 2, 28)));
  3645. sysTime.roll!"months"(-14, AllowDayOverflow.no);
  3646. _assertPred!"=="(sysTime, SysTime(Date(-1997, 12, 28)));
  3647. }
  3648. {
  3649. auto sysTime = SysTime(Date(-2002, 12, 31));
  3650. sysTime.roll!"months"(14, AllowDayOverflow.no);
  3651. _assertPred!"=="(sysTime, SysTime(Date(-2002, 2, 28)));
  3652. sysTime.roll!"months"(-14, AllowDayOverflow.no);
  3653. _assertPred!"=="(sysTime, SysTime(Date(-2002, 12, 28)));
  3654. }
  3655. {
  3656. auto sysTime = SysTime(Date(-2001, 12, 31));
  3657. sysTime.roll!"months"(14, AllowDayOverflow.no);
  3658. _assertPred!"=="(sysTime, SysTime(Date(-2001, 2, 28)));
  3659. sysTime.roll!"months"(-14, AllowDayOverflow.no);
  3660. _assertPred!"=="(sysTime, SysTime(Date(-2001, 12, 28)));
  3661. }
  3662. {
  3663. auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), FracSec.from!"usecs"(5007));
  3664. sysTime.roll!"months"(3, AllowDayOverflow.no);
  3665. _assertPred!"=="(sysTime, SysTime(DateTime(-1999, 10, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
  3666. sysTime.roll!"months"(-4, AllowDayOverflow.no);
  3667. _assertPred!"=="(sysTime, SysTime(DateTime(-1999, 6, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
  3668. }
  3669. {
  3670. auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
  3671. sysTime.roll!"months"(14, AllowDayOverflow.no);
  3672. _assertPred!"=="(sysTime, SysTime(DateTime(-2002, 2, 28, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  3673. sysTime.roll!"months"(-14, AllowDayOverflow.no);
  3674. _assertPred!"=="(sysTime, SysTime(DateTime(-2002, 12, 28, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  3675. }
  3676. {
  3677. auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
  3678. sysTime.roll!"months"(14, AllowDayOverflow.no);
  3679. _assertPred!"=="(sysTime, SysTime(DateTime(-2001, 2, 28, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  3680. sysTime.roll!"months"(-14, AllowDayOverflow.no);
  3681. _assertPred!"=="(sysTime, SysTime(DateTime(-2001, 12, 28, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
  3682. }
  3683. //Test Both
  3684. {
  3685. auto sysTime = SysTime(Date(1, 1, 1));
  3686. sysTime.roll!"months"(-1, AllowDayOverflow.no);
  3687. _assertPred!"=="(sysTime, SysTime(Date(1, 12, 1)));
  3688. sysTime.roll!"months"(1, AllowDayOverflow.no);
  3689. _assertPred!"=="(sysTime, SysTime(Date(1, 1, 1)));
  3690. }
  3691. {
  3692. auto sysTime = SysTime(Date(4, 1, 1));
  3693. sysTime.roll!"months"(-48, AllowDayOverflow.no);
  3694. _assertPred!"=="(sysTime, SysTime(Date(4, 1, 1)));
  3695. sysTime.roll!"months"(48, AllowDayOverflow.no);
  3696. _assertPred!"=="(sysTime, SysTime(Date(4, 1, 1)));
  3697. }
  3698. {
  3699. auto sysTime = SysTime(Date(4, 3, 31));
  3700. sysTime.roll!"months"(-49, AllowDayOverflow.no);
  3701. _assertPred!"=="(sysTime, SysTime(Date(4, 2, 29)));
  3702. sysTime.roll!"months"(49, AllowDayOverflow.no);
  3703. _assertPred!"=="(sysTime, SysTime(Date(4, 3, 29)));
  3704. }
  3705. {
  3706. auto sysTime = SysTime(Date(4, 3, 31));
  3707. sysTime.roll!"months"(-85, AllowDayOverflow.no);
  3708. _assertPred!"=="(sysTime, SysTime(Date(4, 2, 29)));
  3709. sysTime.roll!"months"(85, AllowDayOverflow.no);
  3710. _assertPred!"=="(sysTime, SysTime(Date(4, 3, 29)));
  3711. }
  3712. {
  3713. auto sysTime = SysTime(Date(-1, 1, 1));
  3714. sysTime.roll!"months"(-1, AllowDayOverflow.no);
  3715. _assertPred!"=="(sysTime, SysTime(Date(-1, 12, 1)));
  3716. sysTime.roll!"months"(1, AllowDayOverflow.no);
  3717. _assertPred!"=="(sysTime, SysTime(Date(-1, 1, 1)));
  3718. }
  3719. {
  3720. auto sysTime = SysTime(Date(-4, 1, 1));
  3721. sysTime.roll!"months"(-48, AllowDayOverflow.no);
  3722. _assertPred!"=="(sysTime, SysTime(Date(-4, 1, 1)));
  3723. sysTime.roll!"months"(48, AllowDayOverflow.no);
  3724. _assertPred!"=="(sysTime, SysTime(Date(-4, 1, 1)));
  3725. }
  3726. {
  3727. auto sysTime = SysTime(Date(-4, 3, 31));
  3728. sysTime.roll!"months"(-49, AllowDayOverflow.no);
  3729. _assertPred!"=="(sysTime, SysTime(Date(-4, 2, 29)));
  3730. sysTime.roll!"months"(49, AllowDayOverflow.no);
  3731. _assertPred!"=="(sysTime, SysTime(Date(-4, 3, 29)));
  3732. }
  3733. {
  3734. auto sysTime = SysTime(Date(-4, 3, 31));
  3735. sysTime.roll!"months"(-85, AllowDayOverflow.no);
  3736. _assertPred!"=="(sysTime, SysTime(Date(-4, 2, 29)));
  3737. sysTime.roll!"months"(85, AllowDayOverflow.no);
  3738. _assertPred!"=="(sysTime, SysTime(Date(-4, 3, 29)));
  3739. }
  3740. {
  3741. auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
  3742. sysTime.roll!"months"(-1, AllowDayOverflow.no);
  3743. _assertPred!"=="(sysTime, SysTime(DateTime(1, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  3744. sysTime.roll!"months"(1, AllowDayOverflow.no);
  3745. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  3746. }
  3747. {
  3748. auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
  3749. sysTime.roll!"months"(-1, AllowDayOverflow.no);
  3750. _assertPred!"=="(sysTime, SysTime(DateTime(1, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  3751. sysTime.roll!"months"(1, AllowDayOverflow.no);
  3752. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  3753. }
  3754. {
  3755. auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
  3756. sysTime.roll!"months"(1, AllowDayOverflow.no);
  3757. _assertPred!"=="(sysTime, SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  3758. sysTime.roll!"months"(-1, AllowDayOverflow.no);
  3759. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  3760. }
  3761. {
  3762. auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
  3763. sysTime.roll!"months"(1, AllowDayOverflow.no);
  3764. _assertPred!"=="(sysTime, SysTime(DateTime(0, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  3765. sysTime.roll!"months"(-1, AllowDayOverflow.no);
  3766. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  3767. }
  3768. {
  3769. auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), FracSec.from!"hnsecs"(17));
  3770. sysTime.roll!"months"(-1, AllowDayOverflow.no);
  3771. _assertPred!"=="(sysTime, SysTime(DateTime(1, 12, 1, 0, 7, 9), FracSec.from!"hnsecs"(17)));
  3772. sysTime.roll!"months"(1, AllowDayOverflow.no);
  3773. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 7, 9), FracSec.from!"hnsecs"(17)));
  3774. }
  3775. {
  3776. auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), FracSec.from!"msecs"(9));
  3777. sysTime.roll!"months"(-85, AllowDayOverflow.no);
  3778. _assertPred!"=="(sysTime, SysTime(DateTime(4, 2, 29, 12, 11, 10), FracSec.from!"msecs"(9)));
  3779. sysTime.roll!"months"(85, AllowDayOverflow.no);
  3780. _assertPred!"=="(sysTime, SysTime(DateTime(4, 3, 29, 12, 11, 10), FracSec.from!"msecs"(9)));
  3781. }
  3782. {
  3783. auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), FracSec.from!"msecs"(9));
  3784. sysTime.roll!"months"(85, AllowDayOverflow.no);
  3785. _assertPred!"=="(sysTime, SysTime(DateTime(-3, 4, 30, 12, 11, 10), FracSec.from!"msecs"(9)));
  3786. sysTime.roll!"months"(-85, AllowDayOverflow.no);
  3787. _assertPred!"=="(sysTime, SysTime(DateTime(-3, 3, 30, 12, 11, 10), FracSec.from!"msecs"(9)));
  3788. }
  3789. }
  3790. }
  3791. /++
  3792. Adds the given number of units to this $(D SysTime). A negative number
  3793. will subtract.
  3794. The difference between rolling and adding is that rolling does not
  3795. affect larger units. So, for instance, if you roll a $(D SysTime) one
  3796. year's worth of days, then you get the exact same $(D SysTime).
  3797. Accepted units are $(D "days"), $(D "minutes"), $(D "hours"),
  3798. $(D "minutes"), $(D "seconds"), $(D "msecs"), $(D "usecs"), and
  3799. $(D "hnsecs").
  3800. Note that when rolling msecs, usecs or hnsecs, they all add up to a
  3801. second. So, for example, rolling 1000 msecs is exactly the same as
  3802. rolling 100,000 usecs.
  3803. Params:
  3804. units = The units to add.
  3805. value = The number of $(D_PARAM units) to add to this $(D SysTime).
  3806. Examples:
  3807. --------------------
  3808. auto st1 = SysTime(DateTime(2010, 1, 1, 11, 23, 12));
  3809. st1.roll!"days"(1);
  3810. assert(st1 == SysTime(DateTime(2010, 1, 2, 11, 23, 12)));
  3811. st1.roll!"days"(365);
  3812. assert(st1 == SysTime(DateTime(2010, 1, 26, 11, 23, 12)));
  3813. st1.roll!"days"(-32);
  3814. assert(st1 == SysTime(DateTime(2010, 1, 25, 11, 23, 12)));
  3815. auto st2 = SysTime(DateTime(2010, 7, 4, 12, 0, 0));
  3816. st2.roll!"hours"(1);
  3817. assert(st2 == SysTime(DateTime(2010, 7, 4, 13, 0, 0)));
  3818. auto st3 = SysTime(DateTime(2010, 1, 1, 0, 0, 0));
  3819. st3.roll!"seconds"(-1);
  3820. assert(st3 == SysTime(DateTime(2010, 1, 1, 0, 0, 59)));
  3821. auto st4 = SysTime(DateTime(2010, 1, 1, 0, 0, 0),
  3822. FracSec.from!"usecs"(2_400));
  3823. st4.roll!"usecs"(-1_200_000);
  3824. assert(st4 == SysTime(DateTime(2010, 1, 1, 0, 0, 0),
  3825. FracSec.from!"usecs"(802_400)));
  3826. --------------------
  3827. +/
  3828. /+ref SysTime+/ void roll(string units)(long value) nothrow
  3829. if(units == "days")
  3830. {
  3831. auto hnsecs = adjTime;
  3832. auto gdays = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
  3833. if(hnsecs < 0)
  3834. {
  3835. hnsecs += convert!("hours", "hnsecs")(24);
  3836. --gdays;
  3837. }
  3838. auto date = Date(cast(int)gdays);
  3839. date.roll!"days"(value);
  3840. gdays = date.dayOfGregorianCal - 1;
  3841. if(gdays < 0)
  3842. {
  3843. hnsecs -= convert!("hours", "hnsecs")(24);
  3844. ++gdays;
  3845. }
  3846. immutable newDaysHNSecs = convert!("days", "hnsecs")(gdays);
  3847. adjTime = newDaysHNSecs + hnsecs;
  3848. }
  3849. //Verify Examples.
  3850. unittest
  3851. {
  3852. version(testStdDateTime)
  3853. {
  3854. auto st1 = SysTime(DateTime(2010, 1, 1, 11, 23, 12));
  3855. st1.roll!"days"(1);
  3856. assert(st1 == SysTime(DateTime(2010, 1, 2, 11, 23, 12)));
  3857. st1.roll!"days"(365);
  3858. assert(st1 == SysTime(DateTime(2010, 1, 26, 11, 23, 12)));
  3859. st1.roll!"days"(-32);
  3860. assert(st1 == SysTime(DateTime(2010, 1, 25, 11, 23, 12)));
  3861. auto st2 = SysTime(DateTime(2010, 7, 4, 12, 0, 0));
  3862. st2.roll!"hours"(1);
  3863. assert(st2 == SysTime(DateTime(2010, 7, 4, 13, 0, 0)));
  3864. auto st3 = SysTime(DateTime(2010, 1, 1, 0, 0, 0));
  3865. st3.roll!"seconds"(-1);
  3866. assert(st3 == SysTime(DateTime(2010, 1, 1, 0, 0, 59)));
  3867. auto st4 = SysTime(DateTime(2010, 1, 1, 0, 0, 0),
  3868. FracSec.from!"usecs"(2_400));
  3869. st4.roll!"usecs"(-1_200_000);
  3870. assert(st4 == SysTime(DateTime(2010, 1, 1, 0, 0, 0),
  3871. FracSec.from!"usecs"(802_400)));
  3872. }
  3873. }
  3874. unittest
  3875. {
  3876. version(testStdDateTime)
  3877. {
  3878. //Test A.D.
  3879. {
  3880. auto sysTime = SysTime(Date(1999, 2, 28));
  3881. sysTime.roll!"days"(1);
  3882. _assertPred!"=="(sysTime, SysTime(Date(1999, 2, 1)));
  3883. sysTime.roll!"days"(-1);
  3884. _assertPred!"=="(sysTime, SysTime(Date(1999, 2, 28)));
  3885. }
  3886. {
  3887. auto sysTime = SysTime(Date(2000, 2, 28));
  3888. sysTime.roll!"days"(1);
  3889. _assertPred!"=="(sysTime, SysTime(Date(2000, 2, 29)));
  3890. sysTime.roll!"days"(1);
  3891. _assertPred!"=="(sysTime, SysTime(Date(2000, 2, 1)));
  3892. sysTime.roll!"days"(-1);
  3893. _assertPred!"=="(sysTime, SysTime(Date(2000, 2, 29)));
  3894. }
  3895. {
  3896. auto sysTime = SysTime(Date(1999, 6, 30));
  3897. sysTime.roll!"days"(1);
  3898. _assertPred!"=="(sysTime, SysTime(Date(1999, 6, 1)));
  3899. sysTime.roll!"days"(-1);
  3900. _assertPred!"=="(sysTime, SysTime(Date(1999, 6, 30)));
  3901. }
  3902. {
  3903. auto sysTime = SysTime(Date(1999, 7, 31));
  3904. sysTime.roll!"days"(1);
  3905. _assertPred!"=="(sysTime, SysTime(Date(1999, 7, 1)));
  3906. sysTime.roll!"days"(-1);
  3907. _assertPred!"=="(sysTime, SysTime(Date(1999, 7, 31)));
  3908. }
  3909. {
  3910. auto sysTime = SysTime(Date(1999, 1, 1));
  3911. sysTime.roll!"days"(-1);
  3912. _assertPred!"=="(sysTime, SysTime(Date(1999, 1, 31)));
  3913. sysTime.roll!"days"(1);
  3914. _assertPred!"=="(sysTime, SysTime(Date(1999, 1, 1)));
  3915. }
  3916. {
  3917. auto sysTime = SysTime(Date(1999, 7, 6));
  3918. sysTime.roll!"days"(9);
  3919. _assertPred!"=="(sysTime, SysTime(Date(1999, 7, 15)));
  3920. sysTime.roll!"days"(-11);
  3921. _assertPred!"=="(sysTime, SysTime(Date(1999, 7, 4)));
  3922. sysTime.roll!"days"(30);
  3923. _assertPred!"=="(sysTime, SysTime(Date(1999, 7, 3)));
  3924. sysTime.roll!"days"(-3);
  3925. _assertPred!"=="(sysTime, SysTime(Date(1999, 7, 31)));
  3926. }
  3927. {
  3928. auto sysTime = SysTime(Date(1999, 7, 6));
  3929. sysTime.roll!"days"(365);
  3930. _assertPred!"=="(sysTime, SysTime(Date(1999, 7, 30)));
  3931. sysTime.roll!"days"(-365);
  3932. _assertPred!"=="(sysTime, SysTime(Date(1999, 7, 6)));
  3933. sysTime.roll!"days"(366);
  3934. _assertPred!"=="(sysTime, SysTime(Date(1999, 7, 31)));
  3935. sysTime.roll!"days"(730);
  3936. _assertPred!"=="(sysTime, SysTime(Date(1999, 7, 17)));
  3937. sysTime.roll!"days"(-1096);
  3938. _assertPred!"=="(sysTime, SysTime(Date(1999, 7, 6)));
  3939. }
  3940. {
  3941. auto sysTime = SysTime(Date(1999, 2, 6));
  3942. sysTime.roll!"days"(365);
  3943. _assertPred!"=="(sysTime, SysTime(Date(1999, 2, 7)));
  3944. sysTime.roll!"days"(-365);
  3945. _assertPred!"=="(sysTime, SysTime(Date(1999, 2, 6)));
  3946. sysTime.roll!"days"(366);
  3947. _assertPred!"=="(sysTime, SysTime(Date(1999, 2, 8)));
  3948. sysTime.roll!"days"(730);
  3949. _assertPred!"=="(sysTime, SysTime(Date(1999, 2, 10)));
  3950. sysTime.roll!"days"(-1096);
  3951. _assertPred!"=="(sysTime, SysTime(Date(1999, 2, 6)));
  3952. }
  3953. {
  3954. auto sysTime = SysTime(DateTime(1999, 2, 28, 7, 9, 2), FracSec.from!"usecs"(234578));
  3955. sysTime.roll!"days"(1);
  3956. _assertPred!"=="(sysTime, SysTime(DateTime(1999, 2, 1, 7, 9, 2), FracSec.from!"usecs"(234578)));
  3957. sysTime.roll!"days"(-1);
  3958. _assertPred!"=="(sysTime, SysTime(DateTime(1999, 2, 28, 7, 9, 2), FracSec.from!"usecs"(234578)));
  3959. }
  3960. {
  3961. auto sysTime = SysTime(DateTime(1999, 7, 6, 7, 9, 2), FracSec.from!"usecs"(234578));
  3962. sysTime.roll!"days"(9);
  3963. _assertPred!"=="(sysTime, SysTime(DateTime(1999, 7, 15, 7, 9, 2), FracSec.from!"usecs"(234578)));
  3964. sysTime.roll!"days"(-11);
  3965. _assertPred!"=="(sysTime, SysTime(DateTime(1999, 7, 4, 7, 9, 2), FracSec.from!"usecs"(234578)));
  3966. sysTime.roll!"days"(30);
  3967. _assertPred!"=="(sysTime, SysTime(DateTime(1999, 7, 3, 7, 9, 2), FracSec.from!"usecs"(234578)));
  3968. sysTime.roll!"days"(-3);
  3969. _assertPred!"=="(sysTime, SysTime(DateTime(1999, 7, 31, 7, 9, 2), FracSec.from!"usecs"(234578)));
  3970. }
  3971. //Test B.C.
  3972. {
  3973. auto sysTime = SysTime(Date(-1999, 2, 28));
  3974. sysTime.roll!"days"(1);
  3975. _assertPred!"=="(sysTime, SysTime(Date(-1999, 2, 1)));
  3976. sysTime.roll!"days"(-1);
  3977. _assertPred!"=="(sysTime, SysTime(Date(-1999, 2, 28)));
  3978. }
  3979. {
  3980. auto sysTime = SysTime(Date(-2000, 2, 28));
  3981. sysTime.roll!"days"(1);
  3982. _assertPred!"=="(sysTime, SysTime(Date(-2000, 2, 29)));
  3983. sysTime.roll!"days"(1);
  3984. _assertPred!"=="(sysTime, SysTime(Date(-2000, 2, 1)));
  3985. sysTime.roll!"days"(-1);
  3986. _assertPred!"=="(sysTime, SysTime(Date(-2000, 2, 29)));
  3987. }
  3988. {
  3989. auto sysTime = SysTime(Date(-1999, 6, 30));
  3990. sysTime.roll!"days"(1);
  3991. _assertPred!"=="(sysTime, SysTime(Date(-1999, 6, 1)));
  3992. sysTime.roll!"days"(-1);
  3993. _assertPred!"=="(sysTime, SysTime(Date(-1999, 6, 30)));
  3994. }
  3995. {
  3996. auto sysTime = SysTime(Date(-1999, 7, 31));
  3997. sysTime.roll!"days"(1);
  3998. _assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 1)));
  3999. sysTime.roll!"days"(-1);
  4000. _assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 31)));
  4001. }
  4002. {
  4003. auto sysTime = SysTime(Date(-1999, 1, 1));
  4004. sysTime.roll!"days"(-1);
  4005. _assertPred!"=="(sysTime, SysTime(Date(-1999, 1, 31)));
  4006. sysTime.roll!"days"(1);
  4007. _assertPred!"=="(sysTime, SysTime(Date(-1999, 1, 1)));
  4008. }
  4009. {
  4010. auto sysTime = SysTime(Date(-1999, 7, 6));
  4011. sysTime.roll!"days"(9);
  4012. _assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 15)));
  4013. sysTime.roll!"days"(-11);
  4014. _assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 4)));
  4015. sysTime.roll!"days"(30);
  4016. _assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 3)));
  4017. sysTime.roll!"days"(-3);
  4018. _assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 31)));
  4019. }
  4020. {
  4021. auto sysTime = SysTime(Date(-1999, 7, 6));
  4022. sysTime.roll!"days"(365);
  4023. _assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 30)));
  4024. sysTime.roll!"days"(-365);
  4025. _assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 6)));
  4026. sysTime.roll!"days"(366);
  4027. _assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 31)));
  4028. sysTime.roll!"days"(730);
  4029. _assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 17)));
  4030. sysTime.roll!"days"(-1096);
  4031. _assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 6)));
  4032. }
  4033. {
  4034. auto sysTime = SysTime(DateTime(-1999, 2, 28, 7, 9, 2), FracSec.from!"usecs"(234578));
  4035. sysTime.roll!"days"(1);
  4036. _assertPred!"=="(sysTime, SysTime(DateTime(-1999, 2, 1, 7, 9, 2), FracSec.from!"usecs"(234578)));
  4037. sysTime.roll!"days"(-1);
  4038. _assertPred!"=="(sysTime, SysTime(DateTime(-1999, 2, 28, 7, 9, 2), FracSec.from!"usecs"(234578)));
  4039. }
  4040. {
  4041. auto sysTime = SysTime(DateTime(-1999, 7, 6, 7, 9, 2), FracSec.from!"usecs"(234578));
  4042. sysTime.roll!"days"(9);
  4043. _assertPred!"=="(sysTime, SysTime(DateTime(-1999, 7, 15, 7, 9, 2), FracSec.from!"usecs"(234578)));
  4044. sysTime.roll!"days"(-11);
  4045. _assertPred!"=="(sysTime, SysTime(DateTime(-1999, 7, 4, 7, 9, 2), FracSec.from!"usecs"(234578)));
  4046. sysTime.roll!"days"(30);
  4047. _assertPred!"=="(sysTime, SysTime(DateTime(-1999, 7, 3, 7, 9, 2), FracSec.from!"usecs"(234578)));
  4048. sysTime.roll!"days"(-3);
  4049. }
  4050. //Test Both
  4051. {
  4052. auto sysTime = SysTime(Date(1, 7, 6));
  4053. sysTime.roll!"days"(-365);
  4054. _assertPred!"=="(sysTime, SysTime(Date(1, 7, 13)));
  4055. sysTime.roll!"days"(365);
  4056. _assertPred!"=="(sysTime, SysTime(Date(1, 7, 6)));
  4057. sysTime.roll!"days"(-731);
  4058. _assertPred!"=="(sysTime, SysTime(Date(1, 7, 19)));
  4059. sysTime.roll!"days"(730);
  4060. _assertPred!"=="(sysTime, SysTime(Date(1, 7, 5)));
  4061. }
  4062. {
  4063. auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
  4064. sysTime.roll!"days"(-1);
  4065. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 31, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  4066. sysTime.roll!"days"(1);
  4067. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  4068. }
  4069. {
  4070. auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
  4071. sysTime.roll!"days"(-1);
  4072. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  4073. sysTime.roll!"days"(1);
  4074. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  4075. }
  4076. {
  4077. auto sysTime = SysTime(DateTime(0, 12, 31, 0, 0, 0), FracSec.from!"hnsecs"(0));
  4078. sysTime.roll!"days"(1);
  4079. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  4080. sysTime.roll!"days"(-1);
  4081. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  4082. }
  4083. {
  4084. auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
  4085. sysTime.roll!"days"(1);
  4086. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  4087. sysTime.roll!"days"(-1);
  4088. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  4089. }
  4090. {
  4091. auto sysTime = SysTime(DateTime(1, 7, 6, 13, 13, 9), FracSec.from!"msecs"(22));
  4092. sysTime.roll!"days"(-365);
  4093. _assertPred!"=="(sysTime, SysTime(DateTime(1, 7, 13, 13, 13, 9), FracSec.from!"msecs"(22)));
  4094. sysTime.roll!"days"(365);
  4095. _assertPred!"=="(sysTime, SysTime(DateTime(1, 7, 6, 13, 13, 9), FracSec.from!"msecs"(22)));
  4096. sysTime.roll!"days"(-731);
  4097. _assertPred!"=="(sysTime, SysTime(DateTime(1, 7, 19, 13, 13, 9), FracSec.from!"msecs"(22)));
  4098. sysTime.roll!"days"(730);
  4099. _assertPred!"=="(sysTime, SysTime(DateTime(1, 7, 5, 13, 13, 9), FracSec.from!"msecs"(22)));
  4100. }
  4101. {
  4102. auto sysTime = SysTime(DateTime(0, 7, 6, 13, 13, 9), FracSec.from!"msecs"(22));
  4103. sysTime.roll!"days"(-365);
  4104. _assertPred!"=="(sysTime, SysTime(DateTime(0, 7, 13, 13, 13, 9), FracSec.from!"msecs"(22)));
  4105. sysTime.roll!"days"(365);
  4106. _assertPred!"=="(sysTime, SysTime(DateTime(0, 7, 6, 13, 13, 9), FracSec.from!"msecs"(22)));
  4107. sysTime.roll!"days"(-731);
  4108. _assertPred!"=="(sysTime, SysTime(DateTime(0, 7, 19, 13, 13, 9), FracSec.from!"msecs"(22)));
  4109. sysTime.roll!"days"(730);
  4110. _assertPred!"=="(sysTime, SysTime(DateTime(0, 7, 5, 13, 13, 9), FracSec.from!"msecs"(22)));
  4111. }
  4112. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  4113. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  4114. static assert(!__traits(compiles, cst.roll!"days"(4)));
  4115. //static assert(!__traits(compiles, ist.roll!"days"(4)));
  4116. //Verify Examples.
  4117. auto st = SysTime(DateTime(2010, 1, 1, 11, 23, 12));
  4118. st.roll!"days"(1);
  4119. assert(st == SysTime(DateTime(2010, 1, 2, 11, 23, 12)));
  4120. st.roll!"days"(365);
  4121. assert(st == SysTime(DateTime(2010, 1, 26, 11, 23, 12)));
  4122. st.roll!"days"(-32);
  4123. assert(st == SysTime(DateTime(2010, 1, 25, 11, 23, 12)));
  4124. }
  4125. }
  4126. //Shares documentation with "days" version.
  4127. /+ref SysTime+/ void roll(string units)(long value) nothrow
  4128. if(units == "hours" ||
  4129. units == "minutes" ||
  4130. units == "seconds")
  4131. {
  4132. try
  4133. {
  4134. auto hnsecs = adjTime;
  4135. auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
  4136. if(hnsecs < 0)
  4137. {
  4138. hnsecs += convert!("hours", "hnsecs")(24);
  4139. --days;
  4140. }
  4141. immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
  4142. immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
  4143. immutable second = splitUnitsFromHNSecs!"seconds"(hnsecs);
  4144. auto dateTime = DateTime(Date(cast(int)days), TimeOfDay(cast(int)hour, cast(int)minute, cast(int)second));
  4145. dateTime.roll!units(value);
  4146. --days;
  4147. hnsecs += convert!("hours", "hnsecs")(dateTime.hour);
  4148. hnsecs += convert!("minutes", "hnsecs")(dateTime.minute);
  4149. hnsecs += convert!("seconds", "hnsecs")(dateTime.second);
  4150. if(days < 0)
  4151. {
  4152. hnsecs -= convert!("hours", "hnsecs")(24);
  4153. ++days;
  4154. }
  4155. immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
  4156. adjTime = newDaysHNSecs + hnsecs;
  4157. }
  4158. catch(Exception e)
  4159. assert(0, "Either DateTime's constructor or TimeOfDay's constructor threw.");
  4160. }
  4161. //Test roll!"hours"().
  4162. unittest
  4163. {
  4164. version(testStdDateTime)
  4165. {
  4166. static void TestST(SysTime orig, int hours, in SysTime expected, size_t line = __LINE__)
  4167. {
  4168. orig.roll!"hours"(hours);
  4169. _assertPred!"=="(orig, expected, "", __FILE__, line);
  4170. }
  4171. //Test A.D.
  4172. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)));
  4173. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 1, SysTime(DateTime(1999, 7, 6, 13, 30, 33), FracSec.from!"msecs"(45)));
  4174. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 2, SysTime(DateTime(1999, 7, 6, 14, 30, 33), FracSec.from!"msecs"(45)));
  4175. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 3, SysTime(DateTime(1999, 7, 6, 15, 30, 33), FracSec.from!"msecs"(45)));
  4176. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 4, SysTime(DateTime(1999, 7, 6, 16, 30, 33), FracSec.from!"msecs"(45)));
  4177. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 5, SysTime(DateTime(1999, 7, 6, 17, 30, 33), FracSec.from!"msecs"(45)));
  4178. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 6, SysTime(DateTime(1999, 7, 6, 18, 30, 33), FracSec.from!"msecs"(45)));
  4179. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 7, SysTime(DateTime(1999, 7, 6, 19, 30, 33), FracSec.from!"msecs"(45)));
  4180. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 8, SysTime(DateTime(1999, 7, 6, 20, 30, 33), FracSec.from!"msecs"(45)));
  4181. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 9, SysTime(DateTime(1999, 7, 6, 21, 30, 33), FracSec.from!"msecs"(45)));
  4182. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 10, SysTime(DateTime(1999, 7, 6, 22, 30, 33), FracSec.from!"msecs"(45)));
  4183. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 11, SysTime(DateTime(1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)));
  4184. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 12, SysTime(DateTime(1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)));
  4185. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 13, SysTime(DateTime(1999, 7, 6, 1, 30, 33), FracSec.from!"msecs"(45)));
  4186. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 14, SysTime(DateTime(1999, 7, 6, 2, 30, 33), FracSec.from!"msecs"(45)));
  4187. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 15, SysTime(DateTime(1999, 7, 6, 3, 30, 33), FracSec.from!"msecs"(45)));
  4188. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 16, SysTime(DateTime(1999, 7, 6, 4, 30, 33), FracSec.from!"msecs"(45)));
  4189. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 17, SysTime(DateTime(1999, 7, 6, 5, 30, 33), FracSec.from!"msecs"(45)));
  4190. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 18, SysTime(DateTime(1999, 7, 6, 6, 30, 33), FracSec.from!"msecs"(45)));
  4191. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 19, SysTime(DateTime(1999, 7, 6, 7, 30, 33), FracSec.from!"msecs"(45)));
  4192. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 20, SysTime(DateTime(1999, 7, 6, 8, 30, 33), FracSec.from!"msecs"(45)));
  4193. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 21, SysTime(DateTime(1999, 7, 6, 9, 30, 33), FracSec.from!"msecs"(45)));
  4194. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 22, SysTime(DateTime(1999, 7, 6, 10, 30, 33), FracSec.from!"msecs"(45)));
  4195. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 23, SysTime(DateTime(1999, 7, 6, 11, 30, 33), FracSec.from!"msecs"(45)));
  4196. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 24, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)));
  4197. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 25, SysTime(DateTime(1999, 7, 6, 13, 30, 33), FracSec.from!"msecs"(45)));
  4198. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 50, SysTime(DateTime(1999, 7, 6, 14, 30, 33), FracSec.from!"msecs"(45)));
  4199. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 10_000, SysTime(DateTime(1999, 7, 6, 4, 30, 33), FracSec.from!"msecs"(45)));
  4200. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -1, SysTime(DateTime(1999, 7, 6, 11, 30, 33), FracSec.from!"msecs"(45)));
  4201. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -2, SysTime(DateTime(1999, 7, 6, 10, 30, 33), FracSec.from!"msecs"(45)));
  4202. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -3, SysTime(DateTime(1999, 7, 6, 9, 30, 33), FracSec.from!"msecs"(45)));
  4203. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -4, SysTime(DateTime(1999, 7, 6, 8, 30, 33), FracSec.from!"msecs"(45)));
  4204. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -5, SysTime(DateTime(1999, 7, 6, 7, 30, 33), FracSec.from!"msecs"(45)));
  4205. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -6, SysTime(DateTime(1999, 7, 6, 6, 30, 33), FracSec.from!"msecs"(45)));
  4206. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -7, SysTime(DateTime(1999, 7, 6, 5, 30, 33), FracSec.from!"msecs"(45)));
  4207. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -8, SysTime(DateTime(1999, 7, 6, 4, 30, 33), FracSec.from!"msecs"(45)));
  4208. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -9, SysTime(DateTime(1999, 7, 6, 3, 30, 33), FracSec.from!"msecs"(45)));
  4209. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -10, SysTime(DateTime(1999, 7, 6, 2, 30, 33), FracSec.from!"msecs"(45)));
  4210. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -11, SysTime(DateTime(1999, 7, 6, 1, 30, 33), FracSec.from!"msecs"(45)));
  4211. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -12, SysTime(DateTime(1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)));
  4212. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -13, SysTime(DateTime(1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)));
  4213. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -14, SysTime(DateTime(1999, 7, 6, 22, 30, 33), FracSec.from!"msecs"(45)));
  4214. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -15, SysTime(DateTime(1999, 7, 6, 21, 30, 33), FracSec.from!"msecs"(45)));
  4215. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -16, SysTime(DateTime(1999, 7, 6, 20, 30, 33), FracSec.from!"msecs"(45)));
  4216. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -17, SysTime(DateTime(1999, 7, 6, 19, 30, 33), FracSec.from!"msecs"(45)));
  4217. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -18, SysTime(DateTime(1999, 7, 6, 18, 30, 33), FracSec.from!"msecs"(45)));
  4218. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -19, SysTime(DateTime(1999, 7, 6, 17, 30, 33), FracSec.from!"msecs"(45)));
  4219. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -20, SysTime(DateTime(1999, 7, 6, 16, 30, 33), FracSec.from!"msecs"(45)));
  4220. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -21, SysTime(DateTime(1999, 7, 6, 15, 30, 33), FracSec.from!"msecs"(45)));
  4221. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -22, SysTime(DateTime(1999, 7, 6, 14, 30, 33), FracSec.from!"msecs"(45)));
  4222. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -23, SysTime(DateTime(1999, 7, 6, 13, 30, 33), FracSec.from!"msecs"(45)));
  4223. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -24, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)));
  4224. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -25, SysTime(DateTime(1999, 7, 6, 11, 30, 33), FracSec.from!"msecs"(45)));
  4225. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -50, SysTime(DateTime(1999, 7, 6, 10, 30, 33), FracSec.from!"msecs"(45)));
  4226. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -10_000, SysTime(DateTime(1999, 7, 6, 20, 30, 33), FracSec.from!"msecs"(45)));
  4227. TestST(SysTime(DateTime(1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)), 1, SysTime(DateTime(1999, 7, 6, 1, 30, 33), FracSec.from!"msecs"(45)));
  4228. TestST(SysTime(DateTime(1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)), 0, SysTime(DateTime(1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)));
  4229. TestST(SysTime(DateTime(1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)), -1, SysTime(DateTime(1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)));
  4230. TestST(SysTime(DateTime(1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)), 1, SysTime(DateTime(1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)));
  4231. TestST(SysTime(DateTime(1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)), 0, SysTime(DateTime(1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)));
  4232. TestST(SysTime(DateTime(1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)), -1, SysTime(DateTime(1999, 7, 6, 22, 30, 33), FracSec.from!"msecs"(45)));
  4233. TestST(SysTime(DateTime(1999, 7, 31, 23, 30, 33), FracSec.from!"msecs"(45)), 1, SysTime(DateTime(1999, 7, 31, 0, 30, 33), FracSec.from!"msecs"(45)));
  4234. TestST(SysTime(DateTime(1999, 8, 1, 0, 30, 33), FracSec.from!"msecs"(45)), -1, SysTime(DateTime(1999, 8, 1, 23, 30, 33), FracSec.from!"msecs"(45)));
  4235. TestST(SysTime(DateTime(1999, 12, 31, 23, 30, 33), FracSec.from!"msecs"(45)), 1, SysTime(DateTime(1999, 12, 31, 0, 30, 33), FracSec.from!"msecs"(45)));
  4236. TestST(SysTime(DateTime(2000, 1, 1, 0, 30, 33), FracSec.from!"msecs"(45)), -1, SysTime(DateTime(2000, 1, 1, 23, 30, 33), FracSec.from!"msecs"(45)));
  4237. TestST(SysTime(DateTime(1999, 2, 28, 23, 30, 33), FracSec.from!"msecs"(45)), 25, SysTime(DateTime(1999, 2, 28, 0, 30, 33), FracSec.from!"msecs"(45)));
  4238. TestST(SysTime(DateTime(1999, 3, 2, 0, 30, 33), FracSec.from!"msecs"(45)), -25, SysTime(DateTime(1999, 3, 2, 23, 30, 33), FracSec.from!"msecs"(45)));
  4239. TestST(SysTime(DateTime(2000, 2, 28, 23, 30, 33), FracSec.from!"msecs"(45)), 25, SysTime(DateTime(2000, 2, 28, 0, 30, 33), FracSec.from!"msecs"(45)));
  4240. TestST(SysTime(DateTime(2000, 3, 1, 0, 30, 33), FracSec.from!"msecs"(45)), -25, SysTime(DateTime(2000, 3, 1, 23, 30, 33), FracSec.from!"msecs"(45)));
  4241. //Test B.C.
  4242. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)));
  4243. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 1, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), FracSec.from!"msecs"(45)));
  4244. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 2, SysTime(DateTime(-1999, 7, 6, 14, 30, 33), FracSec.from!"msecs"(45)));
  4245. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 3, SysTime(DateTime(-1999, 7, 6, 15, 30, 33), FracSec.from!"msecs"(45)));
  4246. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 4, SysTime(DateTime(-1999, 7, 6, 16, 30, 33), FracSec.from!"msecs"(45)));
  4247. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 5, SysTime(DateTime(-1999, 7, 6, 17, 30, 33), FracSec.from!"msecs"(45)));
  4248. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 6, SysTime(DateTime(-1999, 7, 6, 18, 30, 33), FracSec.from!"msecs"(45)));
  4249. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 7, SysTime(DateTime(-1999, 7, 6, 19, 30, 33), FracSec.from!"msecs"(45)));
  4250. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 8, SysTime(DateTime(-1999, 7, 6, 20, 30, 33), FracSec.from!"msecs"(45)));
  4251. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 9, SysTime(DateTime(-1999, 7, 6, 21, 30, 33), FracSec.from!"msecs"(45)));
  4252. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 10, SysTime(DateTime(-1999, 7, 6, 22, 30, 33), FracSec.from!"msecs"(45)));
  4253. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 11, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)));
  4254. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 12, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)));
  4255. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 13, SysTime(DateTime(-1999, 7, 6, 1, 30, 33), FracSec.from!"msecs"(45)));
  4256. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 14, SysTime(DateTime(-1999, 7, 6, 2, 30, 33), FracSec.from!"msecs"(45)));
  4257. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 15, SysTime(DateTime(-1999, 7, 6, 3, 30, 33), FracSec.from!"msecs"(45)));
  4258. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 16, SysTime(DateTime(-1999, 7, 6, 4, 30, 33), FracSec.from!"msecs"(45)));
  4259. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 17, SysTime(DateTime(-1999, 7, 6, 5, 30, 33), FracSec.from!"msecs"(45)));
  4260. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 18, SysTime(DateTime(-1999, 7, 6, 6, 30, 33), FracSec.from!"msecs"(45)));
  4261. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 19, SysTime(DateTime(-1999, 7, 6, 7, 30, 33), FracSec.from!"msecs"(45)));
  4262. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 20, SysTime(DateTime(-1999, 7, 6, 8, 30, 33), FracSec.from!"msecs"(45)));
  4263. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 21, SysTime(DateTime(-1999, 7, 6, 9, 30, 33), FracSec.from!"msecs"(45)));
  4264. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 22, SysTime(DateTime(-1999, 7, 6, 10, 30, 33), FracSec.from!"msecs"(45)));
  4265. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 23, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), FracSec.from!"msecs"(45)));
  4266. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 24, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)));
  4267. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 25, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), FracSec.from!"msecs"(45)));
  4268. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 50, SysTime(DateTime(-1999, 7, 6, 14, 30, 33), FracSec.from!"msecs"(45)));
  4269. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 10_000, SysTime(DateTime(-1999, 7, 6, 4, 30, 33), FracSec.from!"msecs"(45)));
  4270. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -1, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), FracSec.from!"msecs"(45)));
  4271. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -2, SysTime(DateTime(-1999, 7, 6, 10, 30, 33), FracSec.from!"msecs"(45)));
  4272. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -3, SysTime(DateTime(-1999, 7, 6, 9, 30, 33), FracSec.from!"msecs"(45)));
  4273. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -4, SysTime(DateTime(-1999, 7, 6, 8, 30, 33), FracSec.from!"msecs"(45)));
  4274. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -5, SysTime(DateTime(-1999, 7, 6, 7, 30, 33), FracSec.from!"msecs"(45)));
  4275. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -6, SysTime(DateTime(-1999, 7, 6, 6, 30, 33), FracSec.from!"msecs"(45)));
  4276. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -7, SysTime(DateTime(-1999, 7, 6, 5, 30, 33), FracSec.from!"msecs"(45)));
  4277. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -8, SysTime(DateTime(-1999, 7, 6, 4, 30, 33), FracSec.from!"msecs"(45)));
  4278. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -9, SysTime(DateTime(-1999, 7, 6, 3, 30, 33), FracSec.from!"msecs"(45)));
  4279. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -10, SysTime(DateTime(-1999, 7, 6, 2, 30, 33), FracSec.from!"msecs"(45)));
  4280. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -11, SysTime(DateTime(-1999, 7, 6, 1, 30, 33), FracSec.from!"msecs"(45)));
  4281. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -12, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)));
  4282. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -13, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)));
  4283. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -14, SysTime(DateTime(-1999, 7, 6, 22, 30, 33), FracSec.from!"msecs"(45)));
  4284. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -15, SysTime(DateTime(-1999, 7, 6, 21, 30, 33), FracSec.from!"msecs"(45)));
  4285. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -16, SysTime(DateTime(-1999, 7, 6, 20, 30, 33), FracSec.from!"msecs"(45)));
  4286. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -17, SysTime(DateTime(-1999, 7, 6, 19, 30, 33), FracSec.from!"msecs"(45)));
  4287. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -18, SysTime(DateTime(-1999, 7, 6, 18, 30, 33), FracSec.from!"msecs"(45)));
  4288. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -19, SysTime(DateTime(-1999, 7, 6, 17, 30, 33), FracSec.from!"msecs"(45)));
  4289. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -20, SysTime(DateTime(-1999, 7, 6, 16, 30, 33), FracSec.from!"msecs"(45)));
  4290. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -21, SysTime(DateTime(-1999, 7, 6, 15, 30, 33), FracSec.from!"msecs"(45)));
  4291. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -22, SysTime(DateTime(-1999, 7, 6, 14, 30, 33), FracSec.from!"msecs"(45)));
  4292. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -23, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), FracSec.from!"msecs"(45)));
  4293. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -24, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)));
  4294. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -25, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), FracSec.from!"msecs"(45)));
  4295. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -50, SysTime(DateTime(-1999, 7, 6, 10, 30, 33), FracSec.from!"msecs"(45)));
  4296. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -10_000, SysTime(DateTime(-1999, 7, 6, 20, 30, 33), FracSec.from!"msecs"(45)));
  4297. TestST(SysTime(DateTime(-1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)), 1, SysTime(DateTime(-1999, 7, 6, 1, 30, 33), FracSec.from!"msecs"(45)));
  4298. TestST(SysTime(DateTime(-1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)), 0, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)));
  4299. TestST(SysTime(DateTime(-1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)), -1, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)));
  4300. TestST(SysTime(DateTime(-1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)), 1, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)));
  4301. TestST(SysTime(DateTime(-1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)), 0, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)));
  4302. TestST(SysTime(DateTime(-1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)), -1, SysTime(DateTime(-1999, 7, 6, 22, 30, 33), FracSec.from!"msecs"(45)));
  4303. TestST(SysTime(DateTime(-1999, 7, 31, 23, 30, 33), FracSec.from!"msecs"(45)), 1, SysTime(DateTime(-1999, 7, 31, 0, 30, 33), FracSec.from!"msecs"(45)));
  4304. TestST(SysTime(DateTime(-1999, 8, 1, 0, 30, 33), FracSec.from!"msecs"(45)), -1, SysTime(DateTime(-1999, 8, 1, 23, 30, 33), FracSec.from!"msecs"(45)));
  4305. TestST(SysTime(DateTime(-2001, 12, 31, 23, 30, 33), FracSec.from!"msecs"(45)), 1, SysTime(DateTime(-2001, 12, 31, 0, 30, 33), FracSec.from!"msecs"(45)));
  4306. TestST(SysTime(DateTime(-2000, 1, 1, 0, 30, 33), FracSec.from!"msecs"(45)), -1, SysTime(DateTime(-2000, 1, 1, 23, 30, 33), FracSec.from!"msecs"(45)));
  4307. TestST(SysTime(DateTime(-2001, 2, 28, 23, 30, 33), FracSec.from!"msecs"(45)), 25, SysTime(DateTime(-2001, 2, 28, 0, 30, 33), FracSec.from!"msecs"(45)));
  4308. TestST(SysTime(DateTime(-2001, 3, 2, 0, 30, 33), FracSec.from!"msecs"(45)), -25, SysTime(DateTime(-2001, 3, 2, 23, 30, 33), FracSec.from!"msecs"(45)));
  4309. TestST(SysTime(DateTime(-2000, 2, 28, 23, 30, 33), FracSec.from!"msecs"(45)), 25, SysTime(DateTime(-2000, 2, 28, 0, 30, 33), FracSec.from!"msecs"(45)));
  4310. TestST(SysTime(DateTime(-2000, 3, 1, 0, 30, 33), FracSec.from!"msecs"(45)), -25, SysTime(DateTime(-2000, 3, 1, 23, 30, 33), FracSec.from!"msecs"(45)));
  4311. //Test Both
  4312. TestST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), FracSec.from!"msecs"(45)), 17_546, SysTime(DateTime(-1, 1, 1, 13, 30, 33), FracSec.from!"msecs"(45)));
  4313. TestST(SysTime(DateTime(1, 1, 1, 13, 30, 33), FracSec.from!"msecs"(45)), -17_546, SysTime(DateTime(1, 1, 1, 11, 30, 33), FracSec.from!"msecs"(45)));
  4314. {
  4315. auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
  4316. sysTime.roll!"hours"(-1);
  4317. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 0, 0), FracSec.from!"hnsecs"(0)));
  4318. sysTime.roll!"hours"(1);
  4319. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  4320. }
  4321. {
  4322. auto sysTime = SysTime(DateTime(1, 1, 1, 0, 59, 59), FracSec.from!"hnsecs"(9_999_999));
  4323. sysTime.roll!"hours"(-1);
  4324. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  4325. sysTime.roll!"hours"(1);
  4326. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  4327. }
  4328. {
  4329. auto sysTime = SysTime(DateTime(0, 12, 31, 23, 0, 0), FracSec.from!"hnsecs"(0));
  4330. sysTime.roll!"hours"(1);
  4331. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  4332. sysTime.roll!"hours"(-1);
  4333. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 23, 0, 0), FracSec.from!"hnsecs"(0)));
  4334. }
  4335. {
  4336. auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
  4337. sysTime.roll!"hours"(1);
  4338. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 0, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  4339. sysTime.roll!"hours"(-1);
  4340. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  4341. }
  4342. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  4343. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  4344. static assert(!__traits(compiles, cst.roll!"hours"(4)));
  4345. //static assert(!__traits(compiles, ist.roll!"hours"(4)));
  4346. //Verify Examples.
  4347. auto st1 = SysTime(DateTime(2010, 7, 4, 12, 0, 0));
  4348. st1.roll!"hours"(1);
  4349. assert(st1 == SysTime(DateTime(2010, 7, 4, 13, 0, 0)));
  4350. auto st2 = SysTime(DateTime(2010, 2, 12, 12, 0, 0));
  4351. st2.roll!"hours"(-1);
  4352. assert(st2 == SysTime(DateTime(2010, 2, 12, 11, 0, 0)));
  4353. auto st3 = SysTime(DateTime(2009, 12, 31, 0, 0, 0));
  4354. st3.roll!"minutes"(1);
  4355. assert(st3 == SysTime(DateTime(2009, 12, 31, 0, 1, 0)));
  4356. auto st4 = SysTime(DateTime(2010, 1, 1, 0, 0, 0));
  4357. st4.roll!"minutes"(-1);
  4358. assert(st4 == SysTime(DateTime(2010, 1, 1, 0, 59, 0)));
  4359. auto st5 = SysTime(DateTime(2009, 12, 31, 0, 0, 0));
  4360. st5.roll!"seconds"(1);
  4361. assert(st5 == SysTime(DateTime(2009, 12, 31, 0, 0, 1)));
  4362. auto st6 = SysTime(DateTime(2010, 1, 1, 0, 0, 0));
  4363. st6.roll!"seconds"(-1);
  4364. assert(st6 == SysTime(DateTime(2010, 1, 1, 0, 0, 59)));
  4365. }
  4366. }
  4367. //Test roll!"minutes"().
  4368. unittest
  4369. {
  4370. version(testStdDateTime)
  4371. {
  4372. static void TestST(SysTime orig, int minutes, in SysTime expected, size_t line = __LINE__)
  4373. {
  4374. orig.roll!"minutes"(minutes);
  4375. _assertPred!"=="(orig, expected, "", __FILE__, line);
  4376. }
  4377. //Test A.D.
  4378. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
  4379. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 1, SysTime(DateTime(1999, 7, 6, 12, 31, 33), FracSec.from!"usecs"(7203)));
  4380. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 2, SysTime(DateTime(1999, 7, 6, 12, 32, 33), FracSec.from!"usecs"(7203)));
  4381. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 3, SysTime(DateTime(1999, 7, 6, 12, 33, 33), FracSec.from!"usecs"(7203)));
  4382. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 4, SysTime(DateTime(1999, 7, 6, 12, 34, 33), FracSec.from!"usecs"(7203)));
  4383. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 5, SysTime(DateTime(1999, 7, 6, 12, 35, 33), FracSec.from!"usecs"(7203)));
  4384. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 10, SysTime(DateTime(1999, 7, 6, 12, 40, 33), FracSec.from!"usecs"(7203)));
  4385. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 15, SysTime(DateTime(1999, 7, 6, 12, 45, 33), FracSec.from!"usecs"(7203)));
  4386. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 29, SysTime(DateTime(1999, 7, 6, 12, 59, 33), FracSec.from!"usecs"(7203)));
  4387. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 30, SysTime(DateTime(1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
  4388. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 45, SysTime(DateTime(1999, 7, 6, 12, 15, 33), FracSec.from!"usecs"(7203)));
  4389. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
  4390. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 75, SysTime(DateTime(1999, 7, 6, 12, 45, 33), FracSec.from!"usecs"(7203)));
  4391. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 90, SysTime(DateTime(1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
  4392. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 100, SysTime(DateTime(1999, 7, 6, 12, 10, 33), FracSec.from!"usecs"(7203)));
  4393. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 689, SysTime(DateTime(1999, 7, 6, 12, 59, 33), FracSec.from!"usecs"(7203)));
  4394. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 690, SysTime(DateTime(1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
  4395. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 691, SysTime(DateTime(1999, 7, 6, 12, 1, 33), FracSec.from!"usecs"(7203)));
  4396. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 960, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
  4397. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 1439, SysTime(DateTime(1999, 7, 6, 12, 29, 33), FracSec.from!"usecs"(7203)));
  4398. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 1440, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
  4399. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 1441, SysTime(DateTime(1999, 7, 6, 12, 31, 33), FracSec.from!"usecs"(7203)));
  4400. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 2880, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
  4401. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -1, SysTime(DateTime(1999, 7, 6, 12, 29, 33), FracSec.from!"usecs"(7203)));
  4402. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -2, SysTime(DateTime(1999, 7, 6, 12, 28, 33), FracSec.from!"usecs"(7203)));
  4403. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -3, SysTime(DateTime(1999, 7, 6, 12, 27, 33), FracSec.from!"usecs"(7203)));
  4404. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -4, SysTime(DateTime(1999, 7, 6, 12, 26, 33), FracSec.from!"usecs"(7203)));
  4405. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -5, SysTime(DateTime(1999, 7, 6, 12, 25, 33), FracSec.from!"usecs"(7203)));
  4406. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -10, SysTime(DateTime(1999, 7, 6, 12, 20, 33), FracSec.from!"usecs"(7203)));
  4407. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -15, SysTime(DateTime(1999, 7, 6, 12, 15, 33), FracSec.from!"usecs"(7203)));
  4408. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -29, SysTime(DateTime(1999, 7, 6, 12, 1, 33), FracSec.from!"usecs"(7203)));
  4409. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -30, SysTime(DateTime(1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
  4410. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -45, SysTime(DateTime(1999, 7, 6, 12, 45, 33), FracSec.from!"usecs"(7203)));
  4411. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
  4412. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -75, SysTime(DateTime(1999, 7, 6, 12, 15, 33), FracSec.from!"usecs"(7203)));
  4413. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -90, SysTime(DateTime(1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
  4414. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -100, SysTime(DateTime(1999, 7, 6, 12, 50, 33), FracSec.from!"usecs"(7203)));
  4415. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -749, SysTime(DateTime(1999, 7, 6, 12, 1, 33), FracSec.from!"usecs"(7203)));
  4416. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -750, SysTime(DateTime(1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
  4417. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -751, SysTime(DateTime(1999, 7, 6, 12, 59, 33), FracSec.from!"usecs"(7203)));
  4418. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -960, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
  4419. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -1439, SysTime(DateTime(1999, 7, 6, 12, 31, 33), FracSec.from!"usecs"(7203)));
  4420. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -1440, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
  4421. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -1441, SysTime(DateTime(1999, 7, 6, 12, 29, 33), FracSec.from!"usecs"(7203)));
  4422. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -2880, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
  4423. TestST(SysTime(DateTime(1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)), 1, SysTime(DateTime(1999, 7, 6, 12, 1, 33), FracSec.from!"usecs"(7203)));
  4424. TestST(SysTime(DateTime(1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)), 0, SysTime(DateTime(1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
  4425. TestST(SysTime(DateTime(1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)), -1, SysTime(DateTime(1999, 7, 6, 12, 59, 33), FracSec.from!"usecs"(7203)));
  4426. TestST(SysTime(DateTime(1999, 7, 6, 11, 59, 33), FracSec.from!"usecs"(7203)), 1, SysTime(DateTime(1999, 7, 6, 11, 0, 33), FracSec.from!"usecs"(7203)));
  4427. TestST(SysTime(DateTime(1999, 7, 6, 11, 59, 33), FracSec.from!"usecs"(7203)), 0, SysTime(DateTime(1999, 7, 6, 11, 59, 33), FracSec.from!"usecs"(7203)));
  4428. TestST(SysTime(DateTime(1999, 7, 6, 11, 59, 33), FracSec.from!"usecs"(7203)), -1, SysTime(DateTime(1999, 7, 6, 11, 58, 33), FracSec.from!"usecs"(7203)));
  4429. TestST(SysTime(DateTime(1999, 7, 6, 0, 0, 33), FracSec.from!"usecs"(7203)), 1, SysTime(DateTime(1999, 7, 6, 0, 1, 33), FracSec.from!"usecs"(7203)));
  4430. TestST(SysTime(DateTime(1999, 7, 6, 0, 0, 33), FracSec.from!"usecs"(7203)), 0, SysTime(DateTime(1999, 7, 6, 0, 0, 33), FracSec.from!"usecs"(7203)));
  4431. TestST(SysTime(DateTime(1999, 7, 6, 0, 0, 33), FracSec.from!"usecs"(7203)), -1, SysTime(DateTime(1999, 7, 6, 0, 59, 33), FracSec.from!"usecs"(7203)));
  4432. TestST(SysTime(DateTime(1999, 7, 5, 23, 59, 33), FracSec.from!"usecs"(7203)), 1, SysTime(DateTime(1999, 7, 5, 23, 0, 33), FracSec.from!"usecs"(7203)));
  4433. TestST(SysTime(DateTime(1999, 7, 5, 23, 59, 33), FracSec.from!"usecs"(7203)), 0, SysTime(DateTime(1999, 7, 5, 23, 59, 33), FracSec.from!"usecs"(7203)));
  4434. TestST(SysTime(DateTime(1999, 7, 5, 23, 59, 33), FracSec.from!"usecs"(7203)), -1, SysTime(DateTime(1999, 7, 5, 23, 58, 33), FracSec.from!"usecs"(7203)));
  4435. TestST(SysTime(DateTime(1998, 12, 31, 23, 59, 33), FracSec.from!"usecs"(7203)), 1, SysTime(DateTime(1998, 12, 31, 23, 0, 33), FracSec.from!"usecs"(7203)));
  4436. TestST(SysTime(DateTime(1998, 12, 31, 23, 59, 33), FracSec.from!"usecs"(7203)), 0, SysTime(DateTime(1998, 12, 31, 23, 59, 33), FracSec.from!"usecs"(7203)));
  4437. TestST(SysTime(DateTime(1998, 12, 31, 23, 59, 33), FracSec.from!"usecs"(7203)), -1, SysTime(DateTime(1998, 12, 31, 23, 58, 33), FracSec.from!"usecs"(7203)));
  4438. //Test B.C.
  4439. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
  4440. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 1, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), FracSec.from!"usecs"(7203)));
  4441. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 2, SysTime(DateTime(-1999, 7, 6, 12, 32, 33), FracSec.from!"usecs"(7203)));
  4442. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 3, SysTime(DateTime(-1999, 7, 6, 12, 33, 33), FracSec.from!"usecs"(7203)));
  4443. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 4, SysTime(DateTime(-1999, 7, 6, 12, 34, 33), FracSec.from!"usecs"(7203)));
  4444. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 5, SysTime(DateTime(-1999, 7, 6, 12, 35, 33), FracSec.from!"usecs"(7203)));
  4445. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 10, SysTime(DateTime(-1999, 7, 6, 12, 40, 33), FracSec.from!"usecs"(7203)));
  4446. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 15, SysTime(DateTime(-1999, 7, 6, 12, 45, 33), FracSec.from!"usecs"(7203)));
  4447. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 29, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), FracSec.from!"usecs"(7203)));
  4448. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 30, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
  4449. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 45, SysTime(DateTime(-1999, 7, 6, 12, 15, 33), FracSec.from!"usecs"(7203)));
  4450. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
  4451. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 75, SysTime(DateTime(-1999, 7, 6, 12, 45, 33), FracSec.from!"usecs"(7203)));
  4452. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 90, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
  4453. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 100, SysTime(DateTime(-1999, 7, 6, 12, 10, 33), FracSec.from!"usecs"(7203)));
  4454. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 689, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), FracSec.from!"usecs"(7203)));
  4455. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 690, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
  4456. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 691, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), FracSec.from!"usecs"(7203)));
  4457. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 960, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
  4458. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 1439, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), FracSec.from!"usecs"(7203)));
  4459. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 1440, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
  4460. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 1441, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), FracSec.from!"usecs"(7203)));
  4461. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 2880, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
  4462. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -1, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), FracSec.from!"usecs"(7203)));
  4463. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -2, SysTime(DateTime(-1999, 7, 6, 12, 28, 33), FracSec.from!"usecs"(7203)));
  4464. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -3, SysTime(DateTime(-1999, 7, 6, 12, 27, 33), FracSec.from!"usecs"(7203)));
  4465. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -4, SysTime(DateTime(-1999, 7, 6, 12, 26, 33), FracSec.from!"usecs"(7203)));
  4466. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -5, SysTime(DateTime(-1999, 7, 6, 12, 25, 33), FracSec.from!"usecs"(7203)));
  4467. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -10, SysTime(DateTime(-1999, 7, 6, 12, 20, 33), FracSec.from!"usecs"(7203)));
  4468. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -15, SysTime(DateTime(-1999, 7, 6, 12, 15, 33), FracSec.from!"usecs"(7203)));
  4469. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -29, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), FracSec.from!"usecs"(7203)));
  4470. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -30, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
  4471. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -45, SysTime(DateTime(-1999, 7, 6, 12, 45, 33), FracSec.from!"usecs"(7203)));
  4472. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
  4473. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -75, SysTime(DateTime(-1999, 7, 6, 12, 15, 33), FracSec.from!"usecs"(7203)));
  4474. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -90, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
  4475. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -100, SysTime(DateTime(-1999, 7, 6, 12, 50, 33), FracSec.from!"usecs"(7203)));
  4476. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -749, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), FracSec.from!"usecs"(7203)));
  4477. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -750, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
  4478. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -751, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), FracSec.from!"usecs"(7203)));
  4479. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -960, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
  4480. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -1439, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), FracSec.from!"usecs"(7203)));
  4481. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -1440, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
  4482. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -1441, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), FracSec.from!"usecs"(7203)));
  4483. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -2880, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
  4484. TestST(SysTime(DateTime(-1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)), 1, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), FracSec.from!"usecs"(7203)));
  4485. TestST(SysTime(DateTime(-1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)), 0, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
  4486. TestST(SysTime(DateTime(-1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)), -1, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), FracSec.from!"usecs"(7203)));
  4487. TestST(SysTime(DateTime(-1999, 7, 6, 11, 59, 33), FracSec.from!"usecs"(7203)), 1, SysTime(DateTime(-1999, 7, 6, 11, 0, 33), FracSec.from!"usecs"(7203)));
  4488. TestST(SysTime(DateTime(-1999, 7, 6, 11, 59, 33), FracSec.from!"usecs"(7203)), 0, SysTime(DateTime(-1999, 7, 6, 11, 59, 33), FracSec.from!"usecs"(7203)));
  4489. TestST(SysTime(DateTime(-1999, 7, 6, 11, 59, 33), FracSec.from!"usecs"(7203)), -1, SysTime(DateTime(-1999, 7, 6, 11, 58, 33), FracSec.from!"usecs"(7203)));
  4490. TestST(SysTime(DateTime(-1999, 7, 6, 0, 0, 33), FracSec.from!"usecs"(7203)), 1, SysTime(DateTime(-1999, 7, 6, 0, 1, 33), FracSec.from!"usecs"(7203)));
  4491. TestST(SysTime(DateTime(-1999, 7, 6, 0, 0, 33), FracSec.from!"usecs"(7203)), 0, SysTime(DateTime(-1999, 7, 6, 0, 0, 33), FracSec.from!"usecs"(7203)));
  4492. TestST(SysTime(DateTime(-1999, 7, 6, 0, 0, 33), FracSec.from!"usecs"(7203)), -1, SysTime(DateTime(-1999, 7, 6, 0, 59, 33), FracSec.from!"usecs"(7203)));
  4493. TestST(SysTime(DateTime(-1999, 7, 5, 23, 59, 33), FracSec.from!"usecs"(7203)), 1, SysTime(DateTime(-1999, 7, 5, 23, 0, 33), FracSec.from!"usecs"(7203)));
  4494. TestST(SysTime(DateTime(-1999, 7, 5, 23, 59, 33), FracSec.from!"usecs"(7203)), 0, SysTime(DateTime(-1999, 7, 5, 23, 59, 33), FracSec.from!"usecs"(7203)));
  4495. TestST(SysTime(DateTime(-1999, 7, 5, 23, 59, 33), FracSec.from!"usecs"(7203)), -1, SysTime(DateTime(-1999, 7, 5, 23, 58, 33), FracSec.from!"usecs"(7203)));
  4496. TestST(SysTime(DateTime(-2000, 12, 31, 23, 59, 33), FracSec.from!"usecs"(7203)), 1, SysTime(DateTime(-2000, 12, 31, 23, 0, 33), FracSec.from!"usecs"(7203)));
  4497. TestST(SysTime(DateTime(-2000, 12, 31, 23, 59, 33), FracSec.from!"usecs"(7203)), 0, SysTime(DateTime(-2000, 12, 31, 23, 59, 33), FracSec.from!"usecs"(7203)));
  4498. TestST(SysTime(DateTime(-2000, 12, 31, 23, 59, 33), FracSec.from!"usecs"(7203)), -1, SysTime(DateTime(-2000, 12, 31, 23, 58, 33), FracSec.from!"usecs"(7203)));
  4499. //Test Both
  4500. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0)), -1, SysTime(DateTime(1, 1, 1, 0, 59, 0)));
  4501. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 0)), 1, SysTime(DateTime(0, 12, 31, 23, 0, 0)));
  4502. TestST(SysTime(DateTime(0, 1, 1, 0, 0, 0)), -1, SysTime(DateTime(0, 1, 1, 0, 59, 0)));
  4503. TestST(SysTime(DateTime(-1, 12, 31, 23, 59, 0)), 1, SysTime(DateTime(-1, 12, 31, 23, 0, 0)));
  4504. TestST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), FracSec.from!"usecs"(7203)), 1_052_760, SysTime(DateTime(-1, 1, 1, 11, 30, 33), FracSec.from!"usecs"(7203)));
  4505. TestST(SysTime(DateTime(1, 1, 1, 13, 30, 33), FracSec.from!"usecs"(7203)), -1_052_760, SysTime(DateTime(1, 1, 1, 13, 30, 33), FracSec.from!"usecs"(7203)));
  4506. TestST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), FracSec.from!"usecs"(7203)), 1_052_782, SysTime(DateTime(-1, 1, 1, 11, 52, 33), FracSec.from!"usecs"(7203)));
  4507. TestST(SysTime(DateTime(1, 1, 1, 13, 52, 33), FracSec.from!"usecs"(7203)), -1_052_782, SysTime(DateTime(1, 1, 1, 13, 30, 33), FracSec.from!"usecs"(7203)));
  4508. {
  4509. auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
  4510. sysTime.roll!"minutes"(-1);
  4511. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 59, 0), FracSec.from!"hnsecs"(0)));
  4512. sysTime.roll!"minutes"(1);
  4513. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  4514. }
  4515. {
  4516. auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 59), FracSec.from!"hnsecs"(9_999_999));
  4517. sysTime.roll!"minutes"(-1);
  4518. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  4519. sysTime.roll!"minutes"(1);
  4520. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 59), FracSec.from!"hnsecs"(9_999_999)));
  4521. }
  4522. {
  4523. auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 0), FracSec.from!"hnsecs"(0));
  4524. sysTime.roll!"minutes"(1);
  4525. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 23, 0, 0), FracSec.from!"hnsecs"(0)));
  4526. sysTime.roll!"minutes"(-1);
  4527. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 23, 59, 0), FracSec.from!"hnsecs"(0)));
  4528. }
  4529. {
  4530. auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
  4531. sysTime.roll!"minutes"(1);
  4532. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 23, 0, 59), FracSec.from!"hnsecs"(9_999_999)));
  4533. sysTime.roll!"minutes"(-1);
  4534. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  4535. }
  4536. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  4537. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  4538. static assert(!__traits(compiles, cst.roll!"minutes"(4)));
  4539. //static assert(!__traits(compiles, ist.roll!"minutes"(4)));
  4540. }
  4541. }
  4542. //Test roll!"seconds"().
  4543. unittest
  4544. {
  4545. version(testStdDateTime)
  4546. {
  4547. static void TestST(SysTime orig, int seconds, in SysTime expected, size_t line = __LINE__)
  4548. {
  4549. orig.roll!"seconds"(seconds);
  4550. _assertPred!"=="(orig, expected, "", __FILE__, line);
  4551. }
  4552. //Test A.D.
  4553. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
  4554. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(1999, 7, 6, 12, 30, 34), FracSec.from!"msecs"(274)));
  4555. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 2, SysTime(DateTime(1999, 7, 6, 12, 30, 35), FracSec.from!"msecs"(274)));
  4556. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 3, SysTime(DateTime(1999, 7, 6, 12, 30, 36), FracSec.from!"msecs"(274)));
  4557. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 4, SysTime(DateTime(1999, 7, 6, 12, 30, 37), FracSec.from!"msecs"(274)));
  4558. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 5, SysTime(DateTime(1999, 7, 6, 12, 30, 38), FracSec.from!"msecs"(274)));
  4559. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 10, SysTime(DateTime(1999, 7, 6, 12, 30, 43), FracSec.from!"msecs"(274)));
  4560. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 15, SysTime(DateTime(1999, 7, 6, 12, 30, 48), FracSec.from!"msecs"(274)));
  4561. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 26, SysTime(DateTime(1999, 7, 6, 12, 30, 59), FracSec.from!"msecs"(274)));
  4562. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 27, SysTime(DateTime(1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)));
  4563. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 30, SysTime(DateTime(1999, 7, 6, 12, 30, 3), FracSec.from!"msecs"(274)));
  4564. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 59, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"msecs"(274)));
  4565. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
  4566. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 61, SysTime(DateTime(1999, 7, 6, 12, 30, 34), FracSec.from!"msecs"(274)));
  4567. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1766, SysTime(DateTime(1999, 7, 6, 12, 30, 59), FracSec.from!"msecs"(274)));
  4568. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1767, SysTime(DateTime(1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)));
  4569. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1768, SysTime(DateTime(1999, 7, 6, 12, 30, 1), FracSec.from!"msecs"(274)));
  4570. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 2007, SysTime(DateTime(1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)));
  4571. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 3599, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"msecs"(274)));
  4572. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 3600, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
  4573. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 3601, SysTime(DateTime(1999, 7, 6, 12, 30, 34), FracSec.from!"msecs"(274)));
  4574. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 7200, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
  4575. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"msecs"(274)));
  4576. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -2, SysTime(DateTime(1999, 7, 6, 12, 30, 31), FracSec.from!"msecs"(274)));
  4577. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -3, SysTime(DateTime(1999, 7, 6, 12, 30, 30), FracSec.from!"msecs"(274)));
  4578. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -4, SysTime(DateTime(1999, 7, 6, 12, 30, 29), FracSec.from!"msecs"(274)));
  4579. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -5, SysTime(DateTime(1999, 7, 6, 12, 30, 28), FracSec.from!"msecs"(274)));
  4580. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -10, SysTime(DateTime(1999, 7, 6, 12, 30, 23), FracSec.from!"msecs"(274)));
  4581. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -15, SysTime(DateTime(1999, 7, 6, 12, 30, 18), FracSec.from!"msecs"(274)));
  4582. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -33, SysTime(DateTime(1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)));
  4583. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -34, SysTime(DateTime(1999, 7, 6, 12, 30, 59), FracSec.from!"msecs"(274)));
  4584. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -35, SysTime(DateTime(1999, 7, 6, 12, 30, 58), FracSec.from!"msecs"(274)));
  4585. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -59, SysTime(DateTime(1999, 7, 6, 12, 30, 34), FracSec.from!"msecs"(274)));
  4586. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
  4587. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -61, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"msecs"(274)));
  4588. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(1999, 7, 6, 12, 30, 1), FracSec.from!"msecs"(274)));
  4589. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)));
  4590. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(1999, 7, 6, 12, 30, 59), FracSec.from!"msecs"(274)));
  4591. TestST(SysTime(DateTime(1999, 7, 6, 12, 0, 0), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(1999, 7, 6, 12, 0, 1), FracSec.from!"msecs"(274)));
  4592. TestST(SysTime(DateTime(1999, 7, 6, 12, 0, 0), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(1999, 7, 6, 12, 0, 0), FracSec.from!"msecs"(274)));
  4593. TestST(SysTime(DateTime(1999, 7, 6, 12, 0, 0), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(1999, 7, 6, 12, 0, 59), FracSec.from!"msecs"(274)));
  4594. TestST(SysTime(DateTime(1999, 7, 6, 0, 0, 0), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(1999, 7, 6, 0, 0, 1), FracSec.from!"msecs"(274)));
  4595. TestST(SysTime(DateTime(1999, 7, 6, 0, 0, 0), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(1999, 7, 6, 0, 0, 0), FracSec.from!"msecs"(274)));
  4596. TestST(SysTime(DateTime(1999, 7, 6, 0, 0, 0), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(1999, 7, 6, 0, 0, 59), FracSec.from!"msecs"(274)));
  4597. TestST(SysTime(DateTime(1999, 7, 5, 23, 59, 59), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(1999, 7, 5, 23, 59, 0), FracSec.from!"msecs"(274)));
  4598. TestST(SysTime(DateTime(1999, 7, 5, 23, 59, 59), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(1999, 7, 5, 23, 59, 59), FracSec.from!"msecs"(274)));
  4599. TestST(SysTime(DateTime(1999, 7, 5, 23, 59, 59), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(1999, 7, 5, 23, 59, 58), FracSec.from!"msecs"(274)));
  4600. TestST(SysTime(DateTime(1998, 12, 31, 23, 59, 59), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(1998, 12, 31, 23, 59, 0), FracSec.from!"msecs"(274)));
  4601. TestST(SysTime(DateTime(1998, 12, 31, 23, 59, 59), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(1998, 12, 31, 23, 59, 59), FracSec.from!"msecs"(274)));
  4602. TestST(SysTime(DateTime(1998, 12, 31, 23, 59, 59), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(1998, 12, 31, 23, 59, 58), FracSec.from!"msecs"(274)));
  4603. //Test B.C.
  4604. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
  4605. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), FracSec.from!"msecs"(274)));
  4606. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 35), FracSec.from!"msecs"(274)));
  4607. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 3, SysTime(DateTime(-1999, 7, 6, 12, 30, 36), FracSec.from!"msecs"(274)));
  4608. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 4, SysTime(DateTime(-1999, 7, 6, 12, 30, 37), FracSec.from!"msecs"(274)));
  4609. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 5, SysTime(DateTime(-1999, 7, 6, 12, 30, 38), FracSec.from!"msecs"(274)));
  4610. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 43), FracSec.from!"msecs"(274)));
  4611. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 15, SysTime(DateTime(-1999, 7, 6, 12, 30, 48), FracSec.from!"msecs"(274)));
  4612. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 26, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), FracSec.from!"msecs"(274)));
  4613. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 27, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)));
  4614. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 30, SysTime(DateTime(-1999, 7, 6, 12, 30, 3), FracSec.from!"msecs"(274)));
  4615. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 59, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"msecs"(274)));
  4616. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
  4617. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 61, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), FracSec.from!"msecs"(274)));
  4618. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1766, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), FracSec.from!"msecs"(274)));
  4619. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1767, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)));
  4620. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1768, SysTime(DateTime(-1999, 7, 6, 12, 30, 1), FracSec.from!"msecs"(274)));
  4621. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 2007, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)));
  4622. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 3599, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"msecs"(274)));
  4623. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 3600, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
  4624. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 3601, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), FracSec.from!"msecs"(274)));
  4625. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 7200, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
  4626. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"msecs"(274)));
  4627. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 31), FracSec.from!"msecs"(274)));
  4628. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -3, SysTime(DateTime(-1999, 7, 6, 12, 30, 30), FracSec.from!"msecs"(274)));
  4629. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -4, SysTime(DateTime(-1999, 7, 6, 12, 30, 29), FracSec.from!"msecs"(274)));
  4630. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -5, SysTime(DateTime(-1999, 7, 6, 12, 30, 28), FracSec.from!"msecs"(274)));
  4631. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 23), FracSec.from!"msecs"(274)));
  4632. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -15, SysTime(DateTime(-1999, 7, 6, 12, 30, 18), FracSec.from!"msecs"(274)));
  4633. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -33, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)));
  4634. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -34, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), FracSec.from!"msecs"(274)));
  4635. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -35, SysTime(DateTime(-1999, 7, 6, 12, 30, 58), FracSec.from!"msecs"(274)));
  4636. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -59, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), FracSec.from!"msecs"(274)));
  4637. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
  4638. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -61, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"msecs"(274)));
  4639. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 1), FracSec.from!"msecs"(274)));
  4640. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)));
  4641. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), FracSec.from!"msecs"(274)));
  4642. TestST(SysTime(DateTime(-1999, 7, 6, 12, 0, 0), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(-1999, 7, 6, 12, 0, 1), FracSec.from!"msecs"(274)));
  4643. TestST(SysTime(DateTime(-1999, 7, 6, 12, 0, 0), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(-1999, 7, 6, 12, 0, 0), FracSec.from!"msecs"(274)));
  4644. TestST(SysTime(DateTime(-1999, 7, 6, 12, 0, 0), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(-1999, 7, 6, 12, 0, 59), FracSec.from!"msecs"(274)));
  4645. TestST(SysTime(DateTime(-1999, 7, 6, 0, 0, 0), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(-1999, 7, 6, 0, 0, 1), FracSec.from!"msecs"(274)));
  4646. TestST(SysTime(DateTime(-1999, 7, 6, 0, 0, 0), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(-1999, 7, 6, 0, 0, 0), FracSec.from!"msecs"(274)));
  4647. TestST(SysTime(DateTime(-1999, 7, 6, 0, 0, 0), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(-1999, 7, 6, 0, 0, 59), FracSec.from!"msecs"(274)));
  4648. TestST(SysTime(DateTime(-1999, 7, 5, 23, 59, 59), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(-1999, 7, 5, 23, 59, 0), FracSec.from!"msecs"(274)));
  4649. TestST(SysTime(DateTime(-1999, 7, 5, 23, 59, 59), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(-1999, 7, 5, 23, 59, 59), FracSec.from!"msecs"(274)));
  4650. TestST(SysTime(DateTime(-1999, 7, 5, 23, 59, 59), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(-1999, 7, 5, 23, 59, 58), FracSec.from!"msecs"(274)));
  4651. TestST(SysTime(DateTime(-2000, 12, 31, 23, 59, 59), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(-2000, 12, 31, 23, 59, 0), FracSec.from!"msecs"(274)));
  4652. TestST(SysTime(DateTime(-2000, 12, 31, 23, 59, 59), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(-2000, 12, 31, 23, 59, 59), FracSec.from!"msecs"(274)));
  4653. TestST(SysTime(DateTime(-2000, 12, 31, 23, 59, 59), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(-2000, 12, 31, 23, 59, 58), FracSec.from!"msecs"(274)));
  4654. //Test Both
  4655. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(1, 1, 1, 0, 0, 59), FracSec.from!"msecs"(274)));
  4656. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(0, 12, 31, 23, 59, 0), FracSec.from!"msecs"(274)));
  4657. TestST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(0, 1, 1, 0, 0, 59), FracSec.from!"msecs"(274)));
  4658. TestST(SysTime(DateTime(-1, 12, 31, 23, 59, 59), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(-1, 12, 31, 23, 59, 0), FracSec.from!"msecs"(274)));
  4659. TestST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), FracSec.from!"msecs"(274)), 63_165_600L, SysTime(DateTime(-1, 1, 1, 11, 30, 33), FracSec.from!"msecs"(274)));
  4660. TestST(SysTime(DateTime(1, 1, 1, 13, 30, 33), FracSec.from!"msecs"(274)), -63_165_600L, SysTime(DateTime(1, 1, 1, 13, 30, 33), FracSec.from!"msecs"(274)));
  4661. TestST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), FracSec.from!"msecs"(274)), 63_165_617L, SysTime(DateTime(-1, 1, 1, 11, 30, 50), FracSec.from!"msecs"(274)));
  4662. TestST(SysTime(DateTime(1, 1, 1, 13, 30, 50), FracSec.from!"msecs"(274)), -63_165_617L, SysTime(DateTime(1, 1, 1, 13, 30, 33), FracSec.from!"msecs"(274)));
  4663. {
  4664. auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
  4665. sysTime.roll!"seconds"(-1);
  4666. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 59), FracSec.from!"hnsecs"(0)));
  4667. sysTime.roll!"seconds"(1);
  4668. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  4669. }
  4670. {
  4671. auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999));
  4672. sysTime.roll!"seconds"(-1);
  4673. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 59), FracSec.from!"hnsecs"(9_999_999)));
  4674. sysTime.roll!"seconds"(1);
  4675. _assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)));
  4676. }
  4677. {
  4678. auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0));
  4679. sysTime.roll!"seconds"(1);
  4680. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 23, 59, 0), FracSec.from!"hnsecs"(0)));
  4681. sysTime.roll!"seconds"(-1);
  4682. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0)));
  4683. }
  4684. {
  4685. auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
  4686. sysTime.roll!"seconds"(1);
  4687. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 23, 59, 0), FracSec.from!"hnsecs"(9_999_999)));
  4688. sysTime.roll!"seconds"(-1);
  4689. _assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  4690. }
  4691. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  4692. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  4693. static assert(!__traits(compiles, cst.roll!"seconds"(4)));
  4694. //static assert(!__traits(compiles, ist.roll!"seconds"(4)));
  4695. }
  4696. }
  4697. //Shares documentation with "days" version.
  4698. /+ref SysTime+/ void roll(string units)(long value) nothrow
  4699. if(units == "msecs" ||
  4700. units == "usecs" ||
  4701. units == "hnsecs")
  4702. {
  4703. auto hnsecs = adjTime;
  4704. immutable days = splitUnitsFromHNSecs!"days"(hnsecs);
  4705. immutable negative = hnsecs < 0;
  4706. if(negative)
  4707. hnsecs += convert!("hours", "hnsecs")(24);
  4708. immutable seconds = splitUnitsFromHNSecs!"seconds"(hnsecs);
  4709. hnsecs += convert!(units, "hnsecs")(value);
  4710. hnsecs %= convert!("seconds", "hnsecs")(1);
  4711. if(hnsecs < 0)
  4712. hnsecs += convert!("seconds", "hnsecs")(1);
  4713. hnsecs += convert!("seconds", "hnsecs")(seconds);
  4714. if(negative)
  4715. hnsecs -= convert!("hours", "hnsecs")(24);
  4716. immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
  4717. adjTime = newDaysHNSecs + hnsecs;
  4718. }
  4719. //Test roll!"msecs"().
  4720. unittest
  4721. {
  4722. version(testStdDateTime)
  4723. {
  4724. static void TestST(SysTime orig, int milliseconds, in SysTime expected, size_t line = __LINE__)
  4725. {
  4726. orig.roll!"msecs"(milliseconds);
  4727. _assertPred!"=="(orig, expected, "", __FILE__, line);
  4728. }
  4729. //Test A.D.
  4730. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
  4731. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(275)));
  4732. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(276)));
  4733. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(284)));
  4734. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(374)));
  4735. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(999)));
  4736. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(0)));
  4737. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
  4738. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(275)));
  4739. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
  4740. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(999)));
  4741. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(0)));
  4742. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(1)));
  4743. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(999)));
  4744. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(0)));
  4745. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(273)));
  4746. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(272)));
  4747. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(264)));
  4748. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(174)));
  4749. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(0)));
  4750. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(999)));
  4751. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
  4752. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(273)));
  4753. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
  4754. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(0)));
  4755. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(999)));
  4756. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(0)));
  4757. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(999)));
  4758. //Test B.C.
  4759. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
  4760. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(275)));
  4761. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(276)));
  4762. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(284)));
  4763. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(374)));
  4764. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(999)));
  4765. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(0)));
  4766. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
  4767. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(275)));
  4768. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
  4769. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(999)));
  4770. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(0)));
  4771. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(1)));
  4772. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(999)));
  4773. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(0)));
  4774. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(273)));
  4775. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(272)));
  4776. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(264)));
  4777. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(174)));
  4778. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(0)));
  4779. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(999)));
  4780. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
  4781. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(273)));
  4782. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
  4783. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(0)));
  4784. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(999)));
  4785. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(0)));
  4786. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(999)));
  4787. //Test Both
  4788. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(0)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(1)));
  4789. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(0)), 0, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(0)));
  4790. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(0)), -1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(999)));
  4791. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(0)), -2, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(998)));
  4792. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(0)), -1000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(0)));
  4793. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(0)), -2000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(0)));
  4794. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(0)), -2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(445)));
  4795. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_989_999)));
  4796. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  4797. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9999)));
  4798. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(19_999)));
  4799. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  4800. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  4801. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(5_549_999)));
  4802. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  4803. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  4804. static assert(!__traits(compiles, cst.addMSecs(4)));
  4805. //static assert(!__traits(compiles, ist.addMSecs(4)));
  4806. }
  4807. }
  4808. //Test roll!"usecs"().
  4809. unittest
  4810. {
  4811. version(testStdDateTime)
  4812. {
  4813. static void TestST(SysTime orig, long microseconds, in SysTime expected, size_t line = __LINE__)
  4814. {
  4815. orig.roll!"usecs"(microseconds);
  4816. _assertPred!"=="(orig, expected, "", __FILE__, line);
  4817. }
  4818. //Test A.D.
  4819. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
  4820. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(275)));
  4821. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(276)));
  4822. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(284)));
  4823. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(374)));
  4824. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(999)));
  4825. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(1000)));
  4826. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(1274)));
  4827. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(1275)));
  4828. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(2274)));
  4829. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(26_999)));
  4830. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(27_000)));
  4831. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(27_001)));
  4832. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(766_999)));
  4833. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(767_000)));
  4834. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
  4835. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
  4836. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
  4837. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(273)));
  4838. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(272)));
  4839. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(264)));
  4840. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(174)));
  4841. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(0)));
  4842. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(999_999)));
  4843. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(999_274)));
  4844. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(999_273)));
  4845. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(998_274)));
  4846. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(967_000)));
  4847. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(966_999)));
  4848. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(167_000)));
  4849. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(166_999)));
  4850. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
  4851. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
  4852. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
  4853. //Test B.C.
  4854. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
  4855. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(275)));
  4856. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(276)));
  4857. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(284)));
  4858. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(374)));
  4859. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(999)));
  4860. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(1000)));
  4861. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(1274)));
  4862. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(1275)));
  4863. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(2274)));
  4864. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(26_999)));
  4865. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(27_000)));
  4866. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(27_001)));
  4867. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(766_999)));
  4868. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(767_000)));
  4869. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
  4870. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
  4871. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
  4872. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(273)));
  4873. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(272)));
  4874. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(264)));
  4875. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(174)));
  4876. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(0)));
  4877. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(999_999)));
  4878. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(999_274)));
  4879. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(999_273)));
  4880. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(998_274)));
  4881. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(967_000)));
  4882. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(966_999)));
  4883. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(167_000)));
  4884. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(166_999)));
  4885. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
  4886. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
  4887. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
  4888. //Test Both
  4889. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(1)));
  4890. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)), 0, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)));
  4891. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)), -1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(999_999)));
  4892. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)), -2, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(999_998)));
  4893. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)), -1000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(999_000)));
  4894. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)), -2000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(998_000)));
  4895. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)), -2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(997_445)));
  4896. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)), -1_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)));
  4897. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)), -2_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)));
  4898. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)), -2_333_333, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(666_667)));
  4899. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_989)));
  4900. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  4901. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9)));
  4902. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(19)));
  4903. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9999)));
  4904. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(19_999)));
  4905. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(25_549)));
  4906. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  4907. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  4908. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2_333_333, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(3_333_329)));
  4909. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  4910. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  4911. static assert(!__traits(compiles, cst.roll!"usecs"(4)));
  4912. //static assert(!__traits(compiles, ist.roll!"usecs"(4)));
  4913. }
  4914. }
  4915. //Test roll!"hnsecs"().
  4916. unittest
  4917. {
  4918. version(testStdDateTime)
  4919. {
  4920. static void TestST(SysTime orig, long hnsecs, in SysTime expected, size_t line = __LINE__)
  4921. {
  4922. orig.roll!"hnsecs"(hnsecs);
  4923. _assertPred!"=="(orig, expected, "", __FILE__, line);
  4924. }
  4925. //Test A.D.
  4926. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
  4927. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(275)));
  4928. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(276)));
  4929. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(284)));
  4930. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(374)));
  4931. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(999)));
  4932. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1000)));
  4933. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1274)));
  4934. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1275)));
  4935. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2274)));
  4936. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(26_999)));
  4937. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(27_000)));
  4938. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(27_001)));
  4939. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_766_999)));
  4940. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_767_000)));
  4941. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_000_274)));
  4942. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
  4943. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
  4944. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
  4945. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 36_000_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
  4946. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(273)));
  4947. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(272)));
  4948. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(264)));
  4949. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(174)));
  4950. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(0)));
  4951. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_999_999)));
  4952. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_999_274)));
  4953. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_999_273)));
  4954. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_998_274)));
  4955. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_967_000)));
  4956. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_966_999)));
  4957. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(8_167_000)));
  4958. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(8_166_999)));
  4959. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_000_274)));
  4960. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
  4961. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
  4962. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
  4963. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -36_000_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
  4964. //Test B.C.
  4965. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
  4966. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(275)));
  4967. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(276)));
  4968. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(284)));
  4969. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(374)));
  4970. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(999)));
  4971. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1000)));
  4972. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1274)));
  4973. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1275)));
  4974. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2274)));
  4975. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(26_999)));
  4976. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(27_000)));
  4977. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(27_001)));
  4978. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_766_999)));
  4979. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_767_000)));
  4980. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_000_274)));
  4981. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
  4982. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
  4983. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
  4984. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
  4985. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(273)));
  4986. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(272)));
  4987. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(264)));
  4988. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(174)));
  4989. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(0)));
  4990. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_999_999)));
  4991. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_999_274)));
  4992. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_999_273)));
  4993. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_998_274)));
  4994. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_967_000)));
  4995. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_966_999)));
  4996. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(8_167_000)));
  4997. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(8_166_999)));
  4998. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_000_274)));
  4999. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
  5000. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
  5001. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
  5002. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
  5003. //Test Both
  5004. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
  5005. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), 0, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  5006. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)));
  5007. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_998)));
  5008. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -1000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_000)));
  5009. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_998_000)));
  5010. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_997_445)));
  5011. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -1_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_000_000)));
  5012. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(8_000_000)));
  5013. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2_333_333, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(7_666_667)));
  5014. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -10_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  5015. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -20_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  5016. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -20_888_888, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_111_112)));
  5017. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_998)));
  5018. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  5019. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0)));
  5020. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)));
  5021. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(999)));
  5022. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1999)));
  5023. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(2554)));
  5024. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(999_999)));
  5025. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1_999_999)));
  5026. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2_333_333, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(2_333_332)));
  5027. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 10_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  5028. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 20_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  5029. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 20_888_888, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(888_887)));
  5030. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5031. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5032. static assert(!__traits(compiles, cst.roll!"hnsecs"(4)));
  5033. //static assert(!__traits(compiles, ist.roll!"hnsecs"(4)));
  5034. }
  5035. }
  5036. /++
  5037. Gives the result of adding or subtracting a duration from this
  5038. $(D SysTime).
  5039. The legal types of arithmetic for $(D SysTime) using this operator are
  5040. $(BOOKTABLE,
  5041. $(TR $(TD SysTime) $(TD +) $(TD duration) $(TD -->) $(TD SysTime))
  5042. $(TR $(TD SysTime) $(TD -) $(TD duration) $(TD -->) $(TD SysTime))
  5043. )
  5044. Params:
  5045. duration = The duration to add to or subtract from this
  5046. $(D SysTime).
  5047. +/
  5048. SysTime opBinary(string op, D)(in D duration) const pure nothrow
  5049. if((op == "+" || op == "-") &&
  5050. (is(Unqual!D == Duration) ||
  5051. is(Unqual!D == TickDuration)))
  5052. {
  5053. SysTime retval = SysTime(this._stdTime, this._timezone);
  5054. static if(is(Unqual!D == Duration))
  5055. immutable hnsecs = duration.total!"hnsecs";
  5056. else static if(is(Unqual!D == TickDuration))
  5057. immutable hnsecs = duration.hnsecs;
  5058. //Ideally, this would just be
  5059. //retval._stdTime += unaryFun!(op ~ "a")(hnsecs);
  5060. //But there isn't currently a pure version of unaryFun!().
  5061. static if(op == "+")
  5062. immutable signedHNSecs = hnsecs;
  5063. else static if(op == "-")
  5064. immutable signedHNSecs = -hnsecs;
  5065. else
  5066. static assert(0);
  5067. retval._stdTime += signedHNSecs;
  5068. return retval;
  5069. }
  5070. unittest
  5071. {
  5072. version(testStdDateTime)
  5073. {
  5074. auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_678));
  5075. _assertPred!"=="(st + dur!"weeks"(7), SysTime(DateTime(1999, 8, 24, 12, 30, 33), FracSec.from!"hnsecs"(2_345_678)));
  5076. _assertPred!"=="(st + dur!"weeks"(-7), SysTime(DateTime(1999, 5, 18, 12, 30, 33), FracSec.from!"hnsecs"(2_345_678)));
  5077. _assertPred!"=="(st + dur!"days"(7), SysTime(DateTime(1999, 7, 13, 12, 30, 33), FracSec.from!"hnsecs"(2_345_678)));
  5078. _assertPred!"=="(st + dur!"days"(-7), SysTime(DateTime(1999, 6, 29, 12, 30, 33), FracSec.from!"hnsecs"(2_345_678)));
  5079. _assertPred!"=="(st + dur!"hours"(7), SysTime(DateTime(1999, 7, 6, 19, 30, 33), FracSec.from!"hnsecs"(2_345_678)));
  5080. _assertPred!"=="(st + dur!"hours"(-7), SysTime(DateTime(1999, 7, 6, 5, 30, 33), FracSec.from!"hnsecs"(2_345_678)));
  5081. _assertPred!"=="(st + dur!"minutes"(7), SysTime(DateTime(1999, 7, 6, 12, 37, 33), FracSec.from!"hnsecs"(2_345_678)));
  5082. _assertPred!"=="(st + dur!"minutes"(-7), SysTime(DateTime(1999, 7, 6, 12, 23, 33), FracSec.from!"hnsecs"(2_345_678)));
  5083. _assertPred!"=="(st + dur!"seconds"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 40), FracSec.from!"hnsecs"(2_345_678)));
  5084. _assertPred!"=="(st + dur!"seconds"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 26), FracSec.from!"hnsecs"(2_345_678)));
  5085. _assertPred!"=="(st + dur!"msecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_415_678)));
  5086. _assertPred!"=="(st + dur!"msecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_275_678)));
  5087. _assertPred!"=="(st + dur!"usecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_748)));
  5088. _assertPred!"=="(st + dur!"usecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_608)));
  5089. _assertPred!"=="(st + dur!"hnsecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_685)));
  5090. _assertPred!"=="(st + dur!"hnsecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_671)));
  5091. //This probably only runs in cases where gettimeofday() is used, but it's
  5092. //hard to do this test correctly with variable ticksPerSec.
  5093. if(TickDuration.ticksPerSec == 1_000_000)
  5094. {
  5095. _assertPred!"=="(st + TickDuration.from!"usecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_748)));
  5096. _assertPred!"=="(st + TickDuration.from!"usecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_608)));
  5097. }
  5098. _assertPred!"=="(st - dur!"weeks"(-7), SysTime(DateTime(1999, 8, 24, 12, 30, 33), FracSec.from!"hnsecs"(2_345_678)));
  5099. _assertPred!"=="(st - dur!"weeks"(7), SysTime(DateTime(1999, 5, 18, 12, 30, 33), FracSec.from!"hnsecs"(2_345_678)));
  5100. _assertPred!"=="(st - dur!"days"(-7), SysTime(DateTime(1999, 7, 13, 12, 30, 33), FracSec.from!"hnsecs"(2_345_678)));
  5101. _assertPred!"=="(st - dur!"days"(7), SysTime(DateTime(1999, 6, 29, 12, 30, 33), FracSec.from!"hnsecs"(2_345_678)));
  5102. _assertPred!"=="(st - dur!"hours"(-7), SysTime(DateTime(1999, 7, 6, 19, 30, 33), FracSec.from!"hnsecs"(2_345_678)));
  5103. _assertPred!"=="(st - dur!"hours"(7), SysTime(DateTime(1999, 7, 6, 5, 30, 33), FracSec.from!"hnsecs"(2_345_678)));
  5104. _assertPred!"=="(st - dur!"minutes"(-7), SysTime(DateTime(1999, 7, 6, 12, 37, 33), FracSec.from!"hnsecs"(2_345_678)));
  5105. _assertPred!"=="(st - dur!"minutes"(7), SysTime(DateTime(1999, 7, 6, 12, 23, 33), FracSec.from!"hnsecs"(2_345_678)));
  5106. _assertPred!"=="(st - dur!"seconds"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 40), FracSec.from!"hnsecs"(2_345_678)));
  5107. _assertPred!"=="(st - dur!"seconds"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 26), FracSec.from!"hnsecs"(2_345_678)));
  5108. _assertPred!"=="(st - dur!"msecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_415_678)));
  5109. _assertPred!"=="(st - dur!"msecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_275_678)));
  5110. _assertPred!"=="(st - dur!"usecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_748)));
  5111. _assertPred!"=="(st - dur!"usecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_608)));
  5112. _assertPred!"=="(st - dur!"hnsecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_685)));
  5113. _assertPred!"=="(st - dur!"hnsecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_671)));
  5114. //This probably only runs in cases where gettimeofday() is used, but it's
  5115. //hard to do this test correctly with variable ticksPerSec.
  5116. if(TickDuration.ticksPerSec == 1_000_000)
  5117. {
  5118. _assertPred!"=="(st - TickDuration.from!"usecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_748)));
  5119. _assertPred!"=="(st - TickDuration.from!"usecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_608)));
  5120. }
  5121. static void TestST(in SysTime orig, long hnsecs, in SysTime expected, size_t line = __LINE__)
  5122. {
  5123. _assertPred!"=="(orig + dur!"hnsecs"(hnsecs), expected, "", __FILE__, line);
  5124. }
  5125. //Test A.D.
  5126. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
  5127. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(275)));
  5128. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(276)));
  5129. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(284)));
  5130. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(374)));
  5131. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(999)));
  5132. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1000)));
  5133. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1274)));
  5134. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1275)));
  5135. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2274)));
  5136. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(26_999)));
  5137. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(27_000)));
  5138. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(27_001)));
  5139. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_766_999)));
  5140. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_767_000)));
  5141. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_000_274)));
  5142. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 39), FracSec.from!"hnsecs"(274)));
  5143. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 36, 33), FracSec.from!"hnsecs"(274)));
  5144. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 31, 33), FracSec.from!"hnsecs"(274)));
  5145. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 36_000_000_000L, SysTime(DateTime(1999, 7, 6, 13, 30, 33), FracSec.from!"hnsecs"(274)));
  5146. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(273)));
  5147. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(272)));
  5148. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(264)));
  5149. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(174)));
  5150. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(0)));
  5151. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_999)));
  5152. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_274)));
  5153. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_273)));
  5154. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_998_274)));
  5155. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_967_000)));
  5156. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_966_999)));
  5157. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(8_167_000)));
  5158. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(8_166_999)));
  5159. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_000_274)));
  5160. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 27), FracSec.from!"hnsecs"(274)));
  5161. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 24, 33), FracSec.from!"hnsecs"(274)));
  5162. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 29, 33), FracSec.from!"hnsecs"(274)));
  5163. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -36_000_000_000L, SysTime(DateTime(1999, 7, 6, 11, 30, 33), FracSec.from!"hnsecs"(274)));
  5164. //Test B.C.
  5165. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
  5166. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(275)));
  5167. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(276)));
  5168. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(284)));
  5169. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(374)));
  5170. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(999)));
  5171. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1000)));
  5172. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1274)));
  5173. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1275)));
  5174. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2274)));
  5175. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(26_999)));
  5176. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(27_000)));
  5177. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(27_001)));
  5178. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_766_999)));
  5179. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_767_000)));
  5180. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_000_274)));
  5181. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 39), FracSec.from!"hnsecs"(274)));
  5182. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 36, 33), FracSec.from!"hnsecs"(274)));
  5183. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), FracSec.from!"hnsecs"(274)));
  5184. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), FracSec.from!"hnsecs"(274)));
  5185. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(273)));
  5186. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(272)));
  5187. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(264)));
  5188. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(174)));
  5189. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(0)));
  5190. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_999)));
  5191. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_274)));
  5192. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_273)));
  5193. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_998_274)));
  5194. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_967_000)));
  5195. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_966_999)));
  5196. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(8_167_000)));
  5197. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(8_166_999)));
  5198. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_000_274)));
  5199. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 27), FracSec.from!"hnsecs"(274)));
  5200. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 24, 33), FracSec.from!"hnsecs"(274)));
  5201. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), FracSec.from!"hnsecs"(274)));
  5202. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), FracSec.from!"hnsecs"(274)));
  5203. //Test Both
  5204. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
  5205. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), 0, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  5206. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  5207. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_998)));
  5208. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_000)));
  5209. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_998_000)));
  5210. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_997_445)));
  5211. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -1_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_000_000)));
  5212. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(8_000_000)));
  5213. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2_333_333, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(7_666_667)));
  5214. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -10_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0)));
  5215. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -20_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 58), FracSec.from!"hnsecs"(0)));
  5216. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -20_888_888, SysTime(DateTime(0, 12, 31, 23, 59, 57), FracSec.from!"hnsecs"(9_111_112)));
  5217. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_998)));
  5218. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  5219. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  5220. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
  5221. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(999)));
  5222. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1999)));
  5223. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(2554)));
  5224. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(999_999)));
  5225. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1_999_999)));
  5226. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2_333_333, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(2_333_332)));
  5227. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 10_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)));
  5228. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 20_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 1), FracSec.from!"hnsecs"(9_999_999)));
  5229. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 20_888_888, SysTime(DateTime(1, 1, 1, 0, 0, 2), FracSec.from!"hnsecs"(888_887)));
  5230. auto duration = dur!"seconds"(12);
  5231. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5232. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5233. static assert(__traits(compiles, cst + duration));
  5234. //static assert(__traits(compiles, ist + duration));
  5235. static assert(__traits(compiles, cst - duration));
  5236. //static assert(__traits(compiles, ist - duration));
  5237. }
  5238. }
  5239. /++
  5240. Gives the result of adding or subtracting a duration from this
  5241. $(D SysTime), as well as assigning the result to this $(D SysTime).
  5242. The legal types of arithmetic for $(D SysTime) using this operator are
  5243. $(BOOKTABLE,
  5244. $(TR $(TD SysTime) $(TD +) $(TD duration) $(TD -->) $(TD SysTime))
  5245. $(TR $(TD SysTime) $(TD -) $(TD duration) $(TD -->) $(TD SysTime))
  5246. )
  5247. Params:
  5248. duration = The duration to add to or subtract from this
  5249. $(D SysTime).
  5250. +/
  5251. /+ref+/ SysTime opOpAssign(string op, D)(in D duration) pure nothrow
  5252. if((op == "+" || op == "-") &&
  5253. (is(Unqual!D == Duration) ||
  5254. is(Unqual!D == TickDuration)))
  5255. {
  5256. static if(is(Unqual!D == Duration))
  5257. auto hnsecs = duration.total!"hnsecs";
  5258. else static if(is(Unqual!D == TickDuration))
  5259. auto hnsecs = duration.hnsecs;
  5260. //Ideally, this would just be
  5261. //_stdTime += unaryFun!(op ~ "a")(hnsecs);
  5262. //But there isn't currently a pure version of unaryFun!().
  5263. static if(op == "+")
  5264. immutable signedHNSecs = hnsecs;
  5265. else static if(op == "-")
  5266. immutable signedHNSecs = -hnsecs;
  5267. else
  5268. static assert(0);
  5269. _stdTime += signedHNSecs;
  5270. return this;
  5271. }
  5272. unittest
  5273. {
  5274. version(testStdDateTime)
  5275. {
  5276. _assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"weeks"(7), SysTime(DateTime(1999, 8, 24, 12, 30, 33)));
  5277. _assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"weeks"(-7), SysTime(DateTime(1999, 5, 18, 12, 30, 33)));
  5278. _assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"days"(7), SysTime(DateTime(1999, 7, 13, 12, 30, 33)));
  5279. _assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"days"(-7), SysTime(DateTime(1999, 6, 29, 12, 30, 33)));
  5280. _assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"hours"(7), SysTime(DateTime(1999, 7, 6, 19, 30, 33)));
  5281. _assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"hours"(-7), SysTime(DateTime(1999, 7, 6, 5, 30, 33)));
  5282. _assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"minutes"(7), SysTime(DateTime(1999, 7, 6, 12, 37, 33)));
  5283. _assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"minutes"(-7), SysTime(DateTime(1999, 7, 6, 12, 23, 33)));
  5284. _assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"seconds"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 40)));
  5285. _assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"seconds"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 26)));
  5286. _assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"msecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(7)));
  5287. _assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"msecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"msecs"(993)));
  5288. _assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"usecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7)));
  5289. _assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"usecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"usecs"(999_993)));
  5290. _assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"hnsecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(7)));
  5291. _assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"hnsecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_993)));
  5292. _assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"weeks"(-7), SysTime(DateTime(1999, 8, 24, 12, 30, 33)));
  5293. _assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"weeks"(7), SysTime(DateTime(1999, 5, 18, 12, 30, 33)));
  5294. _assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"days"(-7), SysTime(DateTime(1999, 7, 13, 12, 30, 33)));
  5295. _assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"days"(7), SysTime(DateTime(1999, 6, 29, 12, 30, 33)));
  5296. _assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"hours"(-7), SysTime(DateTime(1999, 7, 6, 19, 30, 33)));
  5297. _assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"hours"(7), SysTime(DateTime(1999, 7, 6, 5, 30, 33)));
  5298. _assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"minutes"(-7), SysTime(DateTime(1999, 7, 6, 12, 37, 33)));
  5299. _assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"minutes"(7), SysTime(DateTime(1999, 7, 6, 12, 23, 33)));
  5300. _assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"seconds"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 40)));
  5301. _assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"seconds"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 26)));
  5302. _assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"msecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(7)));
  5303. _assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"msecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"msecs"(993)));
  5304. _assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"usecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7)));
  5305. _assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"usecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"usecs"(999_993)));
  5306. _assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"hnsecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(7)));
  5307. _assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"hnsecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_993)));
  5308. static void TestST(SysTime orig, long hnsecs, in SysTime expected, size_t line = __LINE__)
  5309. {
  5310. orig += dur!"hnsecs"(hnsecs);
  5311. _assertPred!"=="(orig, expected, "", __FILE__, line);
  5312. }
  5313. //Test A.D.
  5314. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
  5315. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(275)));
  5316. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(276)));
  5317. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(284)));
  5318. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(374)));
  5319. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(999)));
  5320. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1000)));
  5321. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1274)));
  5322. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1275)));
  5323. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2274)));
  5324. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(26_999)));
  5325. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(27_000)));
  5326. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(27_001)));
  5327. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_766_999)));
  5328. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_767_000)));
  5329. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_000_274)));
  5330. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 39), FracSec.from!"hnsecs"(274)));
  5331. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 36, 33), FracSec.from!"hnsecs"(274)));
  5332. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 31, 33), FracSec.from!"hnsecs"(274)));
  5333. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 36_000_000_000L, SysTime(DateTime(1999, 7, 6, 13, 30, 33), FracSec.from!"hnsecs"(274)));
  5334. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(273)));
  5335. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(272)));
  5336. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(264)));
  5337. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(174)));
  5338. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(0)));
  5339. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_999)));
  5340. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_274)));
  5341. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_273)));
  5342. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_998_274)));
  5343. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_967_000)));
  5344. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_966_999)));
  5345. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(8_167_000)));
  5346. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(8_166_999)));
  5347. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_000_274)));
  5348. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 27), FracSec.from!"hnsecs"(274)));
  5349. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 24, 33), FracSec.from!"hnsecs"(274)));
  5350. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 29, 33), FracSec.from!"hnsecs"(274)));
  5351. TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -36_000_000_000L, SysTime(DateTime(1999, 7, 6, 11, 30, 33), FracSec.from!"hnsecs"(274)));
  5352. //Test B.C.
  5353. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
  5354. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(275)));
  5355. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(276)));
  5356. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(284)));
  5357. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(374)));
  5358. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(999)));
  5359. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1000)));
  5360. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1274)));
  5361. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1275)));
  5362. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2274)));
  5363. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(26_999)));
  5364. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(27_000)));
  5365. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(27_001)));
  5366. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_766_999)));
  5367. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_767_000)));
  5368. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_000_274)));
  5369. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 39), FracSec.from!"hnsecs"(274)));
  5370. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 36, 33), FracSec.from!"hnsecs"(274)));
  5371. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), FracSec.from!"hnsecs"(274)));
  5372. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), FracSec.from!"hnsecs"(274)));
  5373. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(273)));
  5374. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(272)));
  5375. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(264)));
  5376. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(174)));
  5377. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(0)));
  5378. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_999)));
  5379. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_274)));
  5380. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_273)));
  5381. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_998_274)));
  5382. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_967_000)));
  5383. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_966_999)));
  5384. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(8_167_000)));
  5385. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(8_166_999)));
  5386. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_000_274)));
  5387. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 27), FracSec.from!"hnsecs"(274)));
  5388. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 24, 33), FracSec.from!"hnsecs"(274)));
  5389. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), FracSec.from!"hnsecs"(274)));
  5390. TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), FracSec.from!"hnsecs"(274)));
  5391. //Test Both
  5392. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
  5393. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), 0, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  5394. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  5395. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_998)));
  5396. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_000)));
  5397. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_998_000)));
  5398. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_997_445)));
  5399. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -1_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_000_000)));
  5400. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(8_000_000)));
  5401. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2_333_333, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(7_666_667)));
  5402. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -10_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0)));
  5403. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -20_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 58), FracSec.from!"hnsecs"(0)));
  5404. TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -20_888_888, SysTime(DateTime(0, 12, 31, 23, 59, 57), FracSec.from!"hnsecs"(9_111_112)));
  5405. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_998)));
  5406. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  5407. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  5408. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
  5409. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(999)));
  5410. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1999)));
  5411. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(2554)));
  5412. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(999_999)));
  5413. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1_999_999)));
  5414. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2_333_333, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(2_333_332)));
  5415. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 10_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)));
  5416. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 20_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 1), FracSec.from!"hnsecs"(9_999_999)));
  5417. TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 20_888_888, SysTime(DateTime(1, 1, 1, 0, 0, 2), FracSec.from!"hnsecs"(888_887)));
  5418. auto duration = dur!"seconds"(12);
  5419. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5420. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5421. static assert(!__traits(compiles, cst += duration));
  5422. //static assert(!__traits(compiles, ist += duration));
  5423. static assert(!__traits(compiles, cst -= duration));
  5424. //static assert(!__traits(compiles, ist -= duration));
  5425. }
  5426. }
  5427. /++
  5428. Gives the difference between two $(D SysTime)s.
  5429. The legal types of arithmetic for $(D SysTime) using this operator are
  5430. $(BOOKTABLE,
  5431. $(TR $(TD SysTime) $(TD -) $(TD SysTime) $(TD -->) $(TD duration))
  5432. )
  5433. +/
  5434. Duration opBinary(string op)(in SysTime rhs) const pure nothrow
  5435. if(op == "-")
  5436. {
  5437. return dur!"hnsecs"(_stdTime - rhs._stdTime);
  5438. }
  5439. unittest
  5440. {
  5441. version(testStdDateTime)
  5442. {
  5443. _assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1998, 7, 6, 12, 30, 33)),
  5444. dur!"seconds"(31_536_000));
  5445. _assertPred!"=="(SysTime(DateTime(1998, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)),
  5446. dur!"seconds"(-31_536_000));
  5447. _assertPred!"=="(SysTime(DateTime(1999, 8, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)),
  5448. dur!"seconds"(26_78_400));
  5449. _assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 8, 6, 12, 30, 33)),
  5450. dur!"seconds"(-26_78_400));
  5451. _assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 5, 12, 30, 33)),
  5452. dur!"seconds"(86_400));
  5453. _assertPred!"=="(SysTime(DateTime(1999, 7, 5, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)),
  5454. dur!"seconds"(-86_400));
  5455. _assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 11, 30, 33)),
  5456. dur!"seconds"(3600));
  5457. _assertPred!"=="(SysTime(DateTime(1999, 7, 6, 11, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)),
  5458. dur!"seconds"(-3600));
  5459. _assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 31, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)),
  5460. dur!"seconds"(60));
  5461. _assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 31, 33)),
  5462. dur!"seconds"(-60));
  5463. _assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 34)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)),
  5464. dur!"seconds"(1));
  5465. _assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 34)),
  5466. dur!"seconds"(-1));
  5467. _assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(532)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)),
  5468. dur!"msecs"(532));
  5469. _assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(532)),
  5470. dur!"msecs"(-532));
  5471. _assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(333_347)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)),
  5472. dur!"usecs"(333_347));
  5473. _assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(333_347)),
  5474. dur!"usecs"(-333_347));
  5475. _assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_234_567)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)),
  5476. dur!"hnsecs"(1_234_567));
  5477. _assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_234_567)),
  5478. dur!"hnsecs"(-1_234_567));
  5479. _assertPred!"=="(SysTime(DateTime(1, 1, 1, 12, 30, 33)) - SysTime(DateTime(1, 1, 1, 0, 0, 0)), dur!"seconds"(45033));
  5480. _assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0)) - SysTime(DateTime(1, 1, 1, 12, 30, 33)), dur!"seconds"(-45033));
  5481. _assertPred!"=="(SysTime(DateTime(0, 12, 31, 12, 30, 33)) - SysTime(DateTime(1, 1, 1, 0, 0, 0)), dur!"seconds"(-41367));
  5482. _assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0)) - SysTime(DateTime(0, 12, 31, 12, 30, 33)), dur!"seconds"(41367));
  5483. _assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0)) - SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)),
  5484. dur!"hnsecs"(1));
  5485. _assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)) - SysTime(DateTime(1, 1, 1, 0, 0, 0)),
  5486. dur!"hnsecs"(-1));
  5487. auto tz = TimeZone.getTimeZone("America/Los_Angeles");
  5488. _assertPred!"=="(SysTime(DateTime(2011, 1, 13, 8, 17, 2), FracSec.from!"msecs"(296), tz) -
  5489. SysTime(DateTime(2011, 1, 13, 8, 17, 2), FracSec.from!"msecs"(296), tz),
  5490. dur!"hnsecs"(0));
  5491. _assertPred!"=="(SysTime(DateTime(2011, 1, 13, 8, 17, 2), FracSec.from!"msecs"(296), tz) -
  5492. SysTime(DateTime(2011, 1, 13, 8, 17, 2), FracSec.from!"msecs"(296), UTC()),
  5493. dur!"hours"(8));
  5494. _assertPred!"=="(SysTime(DateTime(2011, 1, 13, 8, 17, 2), FracSec.from!"msecs"(296), UTC()) -
  5495. SysTime(DateTime(2011, 1, 13, 8, 17, 2), FracSec.from!"msecs"(296), tz),
  5496. dur!"hours"(-8));
  5497. auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5498. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5499. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5500. static assert(__traits(compiles, st - st));
  5501. static assert(__traits(compiles, cst - st));
  5502. //static assert(__traits(compiles, ist - st));
  5503. static assert(__traits(compiles, st - cst));
  5504. static assert(__traits(compiles, cst - cst));
  5505. //static assert(__traits(compiles, ist - cst));
  5506. //static assert(__traits(compiles, st - ist));
  5507. //static assert(__traits(compiles, cst - ist));
  5508. //static assert(__traits(compiles, ist - ist));
  5509. }
  5510. }
  5511. /++
  5512. Returns the difference between the two $(D SysTime)s in months.
  5513. You can get the difference in years by subtracting the year property
  5514. of two $(D SysTime)s, and you can get the difference in days or weeks by
  5515. subtracting the $(D SysTime)s themselves and using the $(D Duration)
  5516. that results, but because you cannot convert between months and smaller
  5517. units without a specific date (which $(D Duration)s don't have), you
  5518. cannot get the difference in months without doing some math using both
  5519. the year and month properties, so this is a convenience function for
  5520. getting the difference in months.
  5521. Note that the number of days in the months or how far into the month
  5522. either date is is irrelevant. It is the difference in the month property
  5523. combined with the difference in years * 12. So, for instance,
  5524. December 31st and January 1st are one month apart just as December 1st
  5525. and January 31st are one month apart.
  5526. Params:
  5527. rhs = The $(D SysTime) to subtract from this one.
  5528. Examples:
  5529. --------------------
  5530. assert(SysTime(Date(1999, 2, 1)).diffMonths(SysTime(Date(1999, 1, 31))) == 1);
  5531. assert(SysTime(Date(1999, 1, 31)).diffMonths(SysTime(Date(1999, 2, 1))) == -1);
  5532. assert(SysTime(Date(1999, 3, 1)).diffMonths(SysTime(Date(1999, 1, 1))) == 2);
  5533. assert(SysTime(Date(1999, 1, 1)).diffMonths(SysTime(Date(1999, 3, 31))) == -2);
  5534. --------------------
  5535. +/
  5536. int diffMonths(in SysTime rhs) const nothrow
  5537. {
  5538. return (cast(Date)this).diffMonths(cast(Date)rhs);
  5539. }
  5540. unittest
  5541. {
  5542. version(testStdDateTime)
  5543. {
  5544. auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5545. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5546. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5547. static assert(__traits(compiles, st.diffMonths(st)));
  5548. static assert(__traits(compiles, cst.diffMonths(st)));
  5549. //static assert(__traits(compiles, ist.diffMonths(st)));
  5550. static assert(__traits(compiles, st.diffMonths(cst)));
  5551. static assert(__traits(compiles, cst.diffMonths(cst)));
  5552. //static assert(__traits(compiles, ist.diffMonths(cst)));
  5553. //static assert(__traits(compiles, st.diffMonths(ist)));
  5554. //static assert(__traits(compiles, cst.diffMonths(ist)));
  5555. //static assert(__traits(compiles, ist.diffMonths(ist)));
  5556. //Verify Examples.
  5557. assert(SysTime(Date(1999, 2, 1)).diffMonths(SysTime(Date(1999, 1, 31))) == 1);
  5558. assert(SysTime(Date(1999, 1, 31)).diffMonths(SysTime(Date(1999, 2, 1))) == -1);
  5559. assert(SysTime(Date(1999, 3, 1)).diffMonths(SysTime(Date(1999, 1, 1))) == 2);
  5560. assert(SysTime(Date(1999, 1, 1)).diffMonths(SysTime(Date(1999, 3, 31))) == -2);
  5561. }
  5562. }
  5563. /++
  5564. Whether this $(D SysTime) is in a leap year.
  5565. +/
  5566. @property bool isLeapYear() const nothrow
  5567. {
  5568. return (cast(Date)this).isLeapYear;
  5569. }
  5570. unittest
  5571. {
  5572. version(testStdDateTime)
  5573. {
  5574. auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5575. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5576. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5577. static assert(__traits(compiles, st.isLeapYear));
  5578. static assert(__traits(compiles, cst.isLeapYear));
  5579. //static assert(__traits(compiles, ist.isLeapYear));
  5580. }
  5581. }
  5582. /++
  5583. Day of the week this $(D SysTime) is on.
  5584. +/
  5585. @property DayOfWeek dayOfWeek() const nothrow
  5586. {
  5587. return getDayOfWeek(dayOfGregorianCal);
  5588. }
  5589. unittest
  5590. {
  5591. version(testStdDateTime)
  5592. {
  5593. auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5594. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5595. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5596. static assert(__traits(compiles, st.dayOfWeek));
  5597. static assert(__traits(compiles, cst.dayOfWeek));
  5598. //static assert(__traits(compiles, ist.dayOfWeek));
  5599. }
  5600. }
  5601. /++
  5602. Day of the year this $(D SysTime) is on.
  5603. Examples:
  5604. --------------------
  5605. assert(SysTime(DateTime(1999, 1, 1, 12, 22, 7)).dayOfYear == 1);
  5606. assert(SysTime(DateTime(1999, 12, 31, 7, 2, 59)).dayOfYear == 365);
  5607. assert(SysTime(DateTime(2000, 12, 31, 21, 20, 0)).dayOfYear == 366);
  5608. --------------------
  5609. +/
  5610. @property ushort dayOfYear() const nothrow
  5611. {
  5612. return (cast(Date)this).dayOfYear;
  5613. }
  5614. unittest
  5615. {
  5616. version(testStdDateTime)
  5617. {
  5618. auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5619. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5620. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5621. static assert(__traits(compiles, st.dayOfYear));
  5622. static assert(__traits(compiles, cst.dayOfYear));
  5623. //static assert(__traits(compiles, ist.dayOfYear));
  5624. //Verify Examples.
  5625. assert(SysTime(DateTime(1999, 1, 1, 12, 22, 7)).dayOfYear == 1);
  5626. assert(SysTime(DateTime(1999, 12, 31, 7, 2, 59)).dayOfYear == 365);
  5627. assert(SysTime(DateTime(2000, 12, 31, 21, 20, 0)).dayOfYear == 366);
  5628. }
  5629. }
  5630. /++
  5631. Day of the year.
  5632. Params:
  5633. day = The day of the year to set which day of the year this
  5634. $(D SysTime) is on.
  5635. +/
  5636. @property void dayOfYear(int day)
  5637. {
  5638. immutable hnsecs = adjTime;
  5639. immutable days = convert!("hnsecs", "days")(hnsecs);
  5640. immutable theRest = hnsecs - convert!("days", "hnsecs")(days);
  5641. auto date = Date(cast(int)days);
  5642. date.dayOfYear = day;
  5643. immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
  5644. adjTime = newDaysHNSecs + theRest;
  5645. }
  5646. unittest
  5647. {
  5648. version(testStdDateTime)
  5649. {
  5650. auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5651. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5652. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5653. static assert(__traits(compiles, st.dayOfYear = 12));
  5654. static assert(!__traits(compiles, cst.dayOfYear = 12));
  5655. //static assert(!__traits(compiles, ist.dayOfYear = 12));
  5656. }
  5657. }
  5658. /++
  5659. The Xth day of the Gregorian Calendar that this $(D SysTime) is on.
  5660. Examples:
  5661. --------------------
  5662. assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).dayOfGregorianCal == 1);
  5663. assert(SysTime(DateTime(1, 12, 31, 23, 59, 59)).dayOfGregorianCal == 365);
  5664. assert(SysTime(DateTime(2, 1, 1, 2, 2, 2)).dayOfGregorianCal == 366);
  5665. assert(SysTime(DateTime(0, 12, 31, 7, 7, 7)).dayOfGregorianCal == 0);
  5666. assert(SysTime(DateTime(0, 1, 1, 19, 30, 0)).dayOfGregorianCal == -365);
  5667. assert(SysTime(DateTime(-1, 12, 31, 4, 7, 0)).dayOfGregorianCal == -366);
  5668. assert(SysTime(DateTime(2000, 1, 1, 9, 30, 20)).dayOfGregorianCal == 730_120);
  5669. assert(SysTime(DateTime(2010, 12, 31, 15, 45, 50)).dayOfGregorianCal == 734_137);
  5670. --------------------
  5671. +/
  5672. @property int dayOfGregorianCal() const nothrow
  5673. {
  5674. immutable adjustedTime = adjTime;
  5675. //We have to add one because 0 would be midnight, January 1st, 1 A.D.,
  5676. //which would be the 1st day of the Gregorian Calendar, not the 0th. So,
  5677. //simply casting to days is one day off.
  5678. if(adjustedTime > 0)
  5679. return cast(int)getUnitsFromHNSecs!"days"(adjustedTime) + 1;
  5680. auto hnsecs = adjustedTime;
  5681. immutable days = cast(int)splitUnitsFromHNSecs!"days"(hnsecs);
  5682. return hnsecs == 0 ? days + 1 : days;
  5683. }
  5684. unittest
  5685. {
  5686. version(testStdDateTime)
  5687. {
  5688. //Test A.D.
  5689. _assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal, 1);
  5690. _assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)).dayOfGregorianCal, 1);
  5691. _assertPred!"=="(SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal, 1);
  5692. _assertPred!"=="(SysTime(DateTime(1, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 1);
  5693. _assertPred!"=="(SysTime(DateTime(1, 1, 2, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 2);
  5694. _assertPred!"=="(SysTime(DateTime(1, 2, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 32);
  5695. _assertPred!"=="(SysTime(DateTime(2, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 366);
  5696. _assertPred!"=="(SysTime(DateTime(3, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 731);
  5697. _assertPred!"=="(SysTime(DateTime(4, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 1096);
  5698. _assertPred!"=="(SysTime(DateTime(5, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 1462);
  5699. _assertPred!"=="(SysTime(DateTime(50, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 17_898);
  5700. _assertPred!"=="(SysTime(DateTime(97, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 35_065);
  5701. _assertPred!"=="(SysTime(DateTime(100, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 36_160);
  5702. _assertPred!"=="(SysTime(DateTime(101, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 36_525);
  5703. _assertPred!"=="(SysTime(DateTime(105, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 37_986);
  5704. _assertPred!"=="(SysTime(DateTime(200, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 72_684);
  5705. _assertPred!"=="(SysTime(DateTime(201, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 73_049);
  5706. _assertPred!"=="(SysTime(DateTime(300, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 109_208);
  5707. _assertPred!"=="(SysTime(DateTime(301, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 109_573);
  5708. _assertPred!"=="(SysTime(DateTime(400, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 145_732);
  5709. _assertPred!"=="(SysTime(DateTime(401, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 146_098);
  5710. _assertPred!"=="(SysTime(DateTime(500, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 182_257);
  5711. _assertPred!"=="(SysTime(DateTime(501, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 182_622);
  5712. _assertPred!"=="(SysTime(DateTime(1000, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 364_878);
  5713. _assertPred!"=="(SysTime(DateTime(1001, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 365_243);
  5714. _assertPred!"=="(SysTime(DateTime(1600, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 584_023);
  5715. _assertPred!"=="(SysTime(DateTime(1601, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 584_389);
  5716. _assertPred!"=="(SysTime(DateTime(1900, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 693_596);
  5717. _assertPred!"=="(SysTime(DateTime(1901, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 693_961);
  5718. _assertPred!"=="(SysTime(DateTime(1945, 11, 12, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 710_347);
  5719. _assertPred!"=="(SysTime(DateTime(1999, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 729_755);
  5720. _assertPred!"=="(SysTime(DateTime(2000, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 730_120);
  5721. _assertPred!"=="(SysTime(DateTime(2001, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 730_486);
  5722. _assertPred!"=="(SysTime(DateTime(2010, 1, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_773);
  5723. _assertPred!"=="(SysTime(DateTime(2010, 1, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_803);
  5724. _assertPred!"=="(SysTime(DateTime(2010, 2, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_804);
  5725. _assertPred!"=="(SysTime(DateTime(2010, 2, 28, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_831);
  5726. _assertPred!"=="(SysTime(DateTime(2010, 3, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_832);
  5727. _assertPred!"=="(SysTime(DateTime(2010, 3, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_862);
  5728. _assertPred!"=="(SysTime(DateTime(2010, 4, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_863);
  5729. _assertPred!"=="(SysTime(DateTime(2010, 4, 30, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_892);
  5730. _assertPred!"=="(SysTime(DateTime(2010, 5, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_893);
  5731. _assertPred!"=="(SysTime(DateTime(2010, 5, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_923);
  5732. _assertPred!"=="(SysTime(DateTime(2010, 6, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_924);
  5733. _assertPred!"=="(SysTime(DateTime(2010, 6, 30, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_953);
  5734. _assertPred!"=="(SysTime(DateTime(2010, 7, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_954);
  5735. _assertPred!"=="(SysTime(DateTime(2010, 7, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_984);
  5736. _assertPred!"=="(SysTime(DateTime(2010, 8, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_985);
  5737. _assertPred!"=="(SysTime(DateTime(2010, 8, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 734_015);
  5738. _assertPred!"=="(SysTime(DateTime(2010, 9, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 734_016);
  5739. _assertPred!"=="(SysTime(DateTime(2010, 9, 30, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 734_045);
  5740. _assertPred!"=="(SysTime(DateTime(2010, 10, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 734_046);
  5741. _assertPred!"=="(SysTime(DateTime(2010, 10, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 734_076);
  5742. _assertPred!"=="(SysTime(DateTime(2010, 11, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 734_077);
  5743. _assertPred!"=="(SysTime(DateTime(2010, 11, 30, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 734_106);
  5744. _assertPred!"=="(SysTime(DateTime(2010, 12, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 734_107);
  5745. _assertPred!"=="(SysTime(DateTime(2010, 12, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 734_137);
  5746. _assertPred!"=="(SysTime(DateTime(2012, 2, 1, 0, 0, 0), FracSec.from!"msecs"(0)).dayOfGregorianCal, 734_534);
  5747. _assertPred!"=="(SysTime(DateTime(2012, 2, 28, 0, 0, 0), FracSec.from!"msecs"(0)).dayOfGregorianCal, 734_561);
  5748. _assertPred!"=="(SysTime(DateTime(2012, 2, 29, 0, 0, 0), FracSec.from!"msecs"(0)).dayOfGregorianCal, 734_562);
  5749. _assertPred!"=="(SysTime(DateTime(2012, 3, 1, 0, 0, 0), FracSec.from!"msecs"(0)).dayOfGregorianCal, 734_563);
  5750. //Test B.C.
  5751. _assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal, 0);
  5752. _assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_998)).dayOfGregorianCal, 0);
  5753. _assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0)).dayOfGregorianCal, 0);
  5754. _assertPred!"=="(SysTime(DateTime(0, 12, 31, 0, 0, 0), FracSec.from!"hnsecs"(1)).dayOfGregorianCal, 0);
  5755. _assertPred!"=="(SysTime(DateTime(0, 12, 31, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal, 0);
  5756. _assertPred!"=="(SysTime(DateTime(-1, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal, -366);
  5757. _assertPred!"=="(SysTime(DateTime(-1, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_998)).dayOfGregorianCal, -366);
  5758. _assertPred!"=="(SysTime(DateTime(-1, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0)).dayOfGregorianCal, -366);
  5759. _assertPred!"=="(SysTime(DateTime(-1, 12, 31, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal, -366);
  5760. _assertPred!"=="(SysTime(DateTime(0, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 0);
  5761. _assertPred!"=="(SysTime(DateTime(0, 12, 30, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -1);
  5762. _assertPred!"=="(SysTime(DateTime(0, 12, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -30);
  5763. _assertPred!"=="(SysTime(DateTime(0, 11, 30, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -31);
  5764. _assertPred!"=="(SysTime(DateTime(-1, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -366);
  5765. _assertPred!"=="(SysTime(DateTime(-1, 12, 30, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -367);
  5766. _assertPred!"=="(SysTime(DateTime(-1, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -730);
  5767. _assertPred!"=="(SysTime(DateTime(-2, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -731);
  5768. _assertPred!"=="(SysTime(DateTime(-2, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -1095);
  5769. _assertPred!"=="(SysTime(DateTime(-3, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -1096);
  5770. _assertPred!"=="(SysTime(DateTime(-3, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -1460);
  5771. _assertPred!"=="(SysTime(DateTime(-4, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -1461);
  5772. _assertPred!"=="(SysTime(DateTime(-4, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -1826);
  5773. _assertPred!"=="(SysTime(DateTime(-5, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -1827);
  5774. _assertPred!"=="(SysTime(DateTime(-5, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -2191);
  5775. _assertPred!"=="(SysTime(DateTime(-9, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -3652);
  5776. _assertPred!"=="(SysTime(DateTime(-49, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -18_262);
  5777. _assertPred!"=="(SysTime(DateTime(-50, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -18_627);
  5778. _assertPred!"=="(SysTime(DateTime(-97, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -35_794);
  5779. _assertPred!"=="(SysTime(DateTime(-99, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -36_160);
  5780. _assertPred!"=="(SysTime(DateTime(-99, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -36_524);
  5781. _assertPred!"=="(SysTime(DateTime(-100, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -36_889);
  5782. _assertPred!"=="(SysTime(DateTime(-101, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -37_254);
  5783. _assertPred!"=="(SysTime(DateTime(-105, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -38_715);
  5784. _assertPred!"=="(SysTime(DateTime(-200, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -73_413);
  5785. _assertPred!"=="(SysTime(DateTime(-201, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -73_778);
  5786. _assertPred!"=="(SysTime(DateTime(-300, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -109_937);
  5787. _assertPred!"=="(SysTime(DateTime(-301, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -110_302);
  5788. _assertPred!"=="(SysTime(DateTime(-400, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -146_097);
  5789. _assertPred!"=="(SysTime(DateTime(-400, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -146_462);
  5790. _assertPred!"=="(SysTime(DateTime(-401, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -146_827);
  5791. _assertPred!"=="(SysTime(DateTime(-499, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -182_621);
  5792. _assertPred!"=="(SysTime(DateTime(-500, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -182_986);
  5793. _assertPred!"=="(SysTime(DateTime(-501, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -183_351);
  5794. _assertPred!"=="(SysTime(DateTime(-1000, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -365_607);
  5795. _assertPred!"=="(SysTime(DateTime(-1001, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -365_972);
  5796. _assertPred!"=="(SysTime(DateTime(-1599, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -584_387);
  5797. _assertPred!"=="(SysTime(DateTime(-1600, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -584_388);
  5798. _assertPred!"=="(SysTime(DateTime(-1600, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -584_753);
  5799. _assertPred!"=="(SysTime(DateTime(-1601, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -585_118);
  5800. _assertPred!"=="(SysTime(DateTime(-1900, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -694_325);
  5801. _assertPred!"=="(SysTime(DateTime(-1901, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -694_690);
  5802. _assertPred!"=="(SysTime(DateTime(-1999, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -730_484);
  5803. _assertPred!"=="(SysTime(DateTime(-2000, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -730_485);
  5804. _assertPred!"=="(SysTime(DateTime(-2000, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -730_850);
  5805. _assertPred!"=="(SysTime(DateTime(-2001, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -731_215);
  5806. _assertPred!"=="(SysTime(DateTime(-2010, 1, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_502);
  5807. _assertPred!"=="(SysTime(DateTime(-2010, 1, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_472);
  5808. _assertPred!"=="(SysTime(DateTime(-2010, 2, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_471);
  5809. _assertPred!"=="(SysTime(DateTime(-2010, 2, 28, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_444);
  5810. _assertPred!"=="(SysTime(DateTime(-2010, 3, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_443);
  5811. _assertPred!"=="(SysTime(DateTime(-2010, 3, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_413);
  5812. _assertPred!"=="(SysTime(DateTime(-2010, 4, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_412);
  5813. _assertPred!"=="(SysTime(DateTime(-2010, 4, 30, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_383);
  5814. _assertPred!"=="(SysTime(DateTime(-2010, 5, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_382);
  5815. _assertPred!"=="(SysTime(DateTime(-2010, 5, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_352);
  5816. _assertPred!"=="(SysTime(DateTime(-2010, 6, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_351);
  5817. _assertPred!"=="(SysTime(DateTime(-2010, 6, 30, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_322);
  5818. _assertPred!"=="(SysTime(DateTime(-2010, 7, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_321);
  5819. _assertPred!"=="(SysTime(DateTime(-2010, 7, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_291);
  5820. _assertPred!"=="(SysTime(DateTime(-2010, 8, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_290);
  5821. _assertPred!"=="(SysTime(DateTime(-2010, 8, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_260);
  5822. _assertPred!"=="(SysTime(DateTime(-2010, 9, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_259);
  5823. _assertPred!"=="(SysTime(DateTime(-2010, 9, 30, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_230);
  5824. _assertPred!"=="(SysTime(DateTime(-2010, 10, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_229);
  5825. _assertPred!"=="(SysTime(DateTime(-2010, 10, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_199);
  5826. _assertPred!"=="(SysTime(DateTime(-2010, 11, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_198);
  5827. _assertPred!"=="(SysTime(DateTime(-2010, 11, 30, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_169);
  5828. _assertPred!"=="(SysTime(DateTime(-2010, 12, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_168);
  5829. _assertPred!"=="(SysTime(DateTime(-2010, 12, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_138);
  5830. _assertPred!"=="(SysTime(DateTime(-2012, 2, 1, 0, 0, 0), FracSec.from!"msecs"(0)).dayOfGregorianCal, -735_202);
  5831. _assertPred!"=="(SysTime(DateTime(-2012, 2, 28, 0, 0, 0), FracSec.from!"msecs"(0)).dayOfGregorianCal, -735_175);
  5832. _assertPred!"=="(SysTime(DateTime(-2012, 2, 29, 0, 0, 0), FracSec.from!"msecs"(0)).dayOfGregorianCal, -735_174);
  5833. _assertPred!"=="(SysTime(DateTime(-2012, 3, 1, 0, 0, 0), FracSec.from!"msecs"(0)).dayOfGregorianCal, -735_173);
  5834. _assertPred!"=="(SysTime(DateTime(-3760, 9, 7, 0, 0, 0), FracSec.from!"msecs"(0)).dayOfGregorianCal, -1_373_427); //Start of Hebrew Calendar
  5835. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5836. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  5837. static assert(__traits(compiles, cst.dayOfGregorianCal));
  5838. //static assert(__traits(compiles, ist.dayOfGregorianCal));
  5839. //Verify Examples.
  5840. assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).dayOfGregorianCal == 1);
  5841. assert(SysTime(DateTime(1, 12, 31, 23, 59, 59)).dayOfGregorianCal == 365);
  5842. assert(SysTime(DateTime(2, 1, 1, 2, 2, 2)).dayOfGregorianCal == 366);
  5843. assert(SysTime(DateTime(0, 12, 31, 7, 7, 7)).dayOfGregorianCal == 0);
  5844. assert(SysTime(DateTime(0, 1, 1, 19, 30, 0)).dayOfGregorianCal == -365);
  5845. assert(SysTime(DateTime(-1, 12, 31, 4, 7, 0)).dayOfGregorianCal == -366);
  5846. assert(SysTime(DateTime(2000, 1, 1, 9, 30, 20)).dayOfGregorianCal == 730_120);
  5847. assert(SysTime(DateTime(2010, 12, 31, 15, 45, 50)).dayOfGregorianCal == 734_137);
  5848. }
  5849. }
  5850. //Test that the logic for the day of the Gregorian Calendar is consistent
  5851. //between Date and SysTime.
  5852. unittest
  5853. {
  5854. version(testStdDateTime)
  5855. {
  5856. //Test A.D.
  5857. _assertPred!"=="(Date(1, 1, 1).dayOfGregorianCal, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5858. _assertPred!"=="(Date(1, 1, 2).dayOfGregorianCal, SysTime(DateTime(1, 1, 2, 0, 0, 0), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5859. _assertPred!"=="(Date(1, 2, 1).dayOfGregorianCal, SysTime(DateTime(1, 2, 1, 0, 0, 0), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5860. _assertPred!"=="(Date(2, 1, 1).dayOfGregorianCal, SysTime(DateTime(2, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5861. _assertPred!"=="(Date(3, 1, 1).dayOfGregorianCal, SysTime(DateTime(3, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5862. _assertPred!"=="(Date(4, 1, 1).dayOfGregorianCal, SysTime(DateTime(4, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5863. _assertPred!"=="(Date(5, 1, 1).dayOfGregorianCal, SysTime(DateTime(5, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5864. _assertPred!"=="(Date(50, 1, 1).dayOfGregorianCal, SysTime(DateTime(50, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5865. _assertPred!"=="(Date(97, 1, 1).dayOfGregorianCal, SysTime(DateTime(97, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5866. _assertPred!"=="(Date(100, 1, 1).dayOfGregorianCal, SysTime(DateTime(100, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5867. _assertPred!"=="(Date(101, 1, 1).dayOfGregorianCal, SysTime(DateTime(101, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5868. _assertPred!"=="(Date(105, 1, 1).dayOfGregorianCal, SysTime(DateTime(105, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5869. _assertPred!"=="(Date(200, 1, 1).dayOfGregorianCal, SysTime(DateTime(200, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5870. _assertPred!"=="(Date(201, 1, 1).dayOfGregorianCal, SysTime(DateTime(201, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5871. _assertPred!"=="(Date(300, 1, 1).dayOfGregorianCal, SysTime(DateTime(300, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5872. _assertPred!"=="(Date(301, 1, 1).dayOfGregorianCal, SysTime(DateTime(301, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5873. _assertPred!"=="(Date(400, 1, 1).dayOfGregorianCal, SysTime(DateTime(400, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5874. _assertPred!"=="(Date(401, 1, 1).dayOfGregorianCal, SysTime(DateTime(401, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5875. _assertPred!"=="(Date(500, 1, 1).dayOfGregorianCal, SysTime(DateTime(500, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5876. _assertPred!"=="(Date(501, 1, 1).dayOfGregorianCal, SysTime(DateTime(501, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5877. _assertPred!"=="(Date(1000, 1, 1).dayOfGregorianCal, SysTime(DateTime(1000, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5878. _assertPred!"=="(Date(1001, 1, 1).dayOfGregorianCal, SysTime(DateTime(1001, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5879. _assertPred!"=="(Date(1600, 1, 1).dayOfGregorianCal, SysTime(DateTime(1600, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5880. _assertPred!"=="(Date(1601, 1, 1).dayOfGregorianCal, SysTime(DateTime(1601, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5881. _assertPred!"=="(Date(1900, 1, 1).dayOfGregorianCal, SysTime(DateTime(1900, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5882. _assertPred!"=="(Date(1901, 1, 1).dayOfGregorianCal, SysTime(DateTime(1901, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5883. _assertPred!"=="(Date(1945, 11, 12).dayOfGregorianCal, SysTime(DateTime(1945, 11, 12, 0, 0, 0), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5884. _assertPred!"=="(Date(1999, 1, 1).dayOfGregorianCal, SysTime(DateTime(1999, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5885. _assertPred!"=="(Date(1999, 7, 6).dayOfGregorianCal, SysTime(DateTime(1999, 7, 6, 12, 13, 14), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5886. _assertPred!"=="(Date(2000, 1, 1).dayOfGregorianCal, SysTime(DateTime(2000, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5887. _assertPred!"=="(Date(2001, 1, 1).dayOfGregorianCal, SysTime(DateTime(2001, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5888. _assertPred!"=="(Date(2010, 1, 1).dayOfGregorianCal, SysTime(DateTime(2010, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5889. _assertPred!"=="(Date(2010, 1, 31).dayOfGregorianCal, SysTime(DateTime(2010, 1, 31, 23, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5890. _assertPred!"=="(Date(2010, 2, 1).dayOfGregorianCal, SysTime(DateTime(2010, 2, 1, 23, 59, 59), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5891. _assertPred!"=="(Date(2010, 2, 28).dayOfGregorianCal, SysTime(DateTime(2010, 2, 28, 23, 59, 59), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5892. _assertPred!"=="(Date(2010, 3, 1).dayOfGregorianCal, SysTime(DateTime(2010, 3, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5893. _assertPred!"=="(Date(2010, 3, 31).dayOfGregorianCal, SysTime(DateTime(2010, 3, 31, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5894. _assertPred!"=="(Date(2010, 4, 1).dayOfGregorianCal, SysTime(DateTime(2010, 4, 1, 0, 0, 0), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5895. _assertPred!"=="(Date(2010, 4, 30).dayOfGregorianCal, SysTime(DateTime(2010, 4, 30, 0, 0, 0), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5896. _assertPred!"=="(Date(2010, 5, 1).dayOfGregorianCal, SysTime(DateTime(2010, 5, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5897. _assertPred!"=="(Date(2010, 5, 31).dayOfGregorianCal, SysTime(DateTime(2010, 5, 31, 12, 13, 14), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5898. _assertPred!"=="(Date(2010, 6, 1).dayOfGregorianCal, SysTime(DateTime(2010, 6, 1, 12, 13, 14), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5899. _assertPred!"=="(Date(2010, 6, 30).dayOfGregorianCal, SysTime(DateTime(2010, 6, 30, 12, 13, 14), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5900. _assertPred!"=="(Date(2010, 7, 1).dayOfGregorianCal, SysTime(DateTime(2010, 7, 1, 12, 13, 14), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5901. _assertPred!"=="(Date(2010, 7, 31).dayOfGregorianCal, SysTime(DateTime(2010, 7, 31, 23, 59, 59), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5902. _assertPred!"=="(Date(2010, 8, 1).dayOfGregorianCal, SysTime(DateTime(2010, 8, 1, 23, 59, 59), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5903. _assertPred!"=="(Date(2010, 8, 31).dayOfGregorianCal, SysTime(DateTime(2010, 8, 31, 23, 59, 59), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5904. _assertPred!"=="(Date(2010, 9, 1).dayOfGregorianCal, SysTime(DateTime(2010, 9, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5905. _assertPred!"=="(Date(2010, 9, 30).dayOfGregorianCal, SysTime(DateTime(2010, 9, 30, 12, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5906. _assertPred!"=="(Date(2010, 10, 1).dayOfGregorianCal, SysTime(DateTime(2010, 10, 1, 0, 12, 0), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5907. _assertPred!"=="(Date(2010, 10, 31).dayOfGregorianCal, SysTime(DateTime(2010, 10, 31, 0, 0, 12), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5908. _assertPred!"=="(Date(2010, 11, 1).dayOfGregorianCal, SysTime(DateTime(2010, 11, 1, 23, 0, 0), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5909. _assertPred!"=="(Date(2010, 11, 30).dayOfGregorianCal, SysTime(DateTime(2010, 11, 30, 0, 59, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5910. _assertPred!"=="(Date(2010, 12, 1).dayOfGregorianCal, SysTime(DateTime(2010, 12, 1, 0, 0, 59), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5911. _assertPred!"=="(Date(2010, 12, 31).dayOfGregorianCal, SysTime(DateTime(2010, 12, 31, 0, 59, 59), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5912. _assertPred!"=="(Date(2012, 2, 1).dayOfGregorianCal, SysTime(DateTime(2012, 2, 1, 23, 0, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5913. _assertPred!"=="(Date(2012, 2, 28).dayOfGregorianCal, SysTime(DateTime(2012, 2, 28, 23, 59, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5914. _assertPred!"=="(Date(2012, 2, 29).dayOfGregorianCal, SysTime(DateTime(2012, 2, 29, 7, 7, 7), FracSec.from!"hnsecs"(7)).dayOfGregorianCal);
  5915. _assertPred!"=="(Date(2012, 3, 1).dayOfGregorianCal, SysTime(DateTime(2012, 3, 1, 7, 7, 7), FracSec.from!"hnsecs"(7)).dayOfGregorianCal);
  5916. //Test B.C.
  5917. _assertPred!"=="(Date(0, 12, 31).dayOfGregorianCal, SysTime(DateTime(0, 12, 31, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5918. _assertPred!"=="(Date(0, 12, 30).dayOfGregorianCal, SysTime(DateTime(0, 12, 30, 0, 0, 0), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5919. _assertPred!"=="(Date(0, 12, 1).dayOfGregorianCal, SysTime(DateTime(0, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5920. _assertPred!"=="(Date(0, 11, 30).dayOfGregorianCal, SysTime(DateTime(0, 11, 30, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5921. _assertPred!"=="(Date(-1, 12, 31).dayOfGregorianCal, SysTime(DateTime(-1, 12, 31, 12, 13, 14), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5922. _assertPred!"=="(Date(-1, 12, 30).dayOfGregorianCal, SysTime(DateTime(-1, 12, 30, 12, 13, 14), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5923. _assertPred!"=="(Date(-1, 1, 1).dayOfGregorianCal, SysTime(DateTime(-1, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5924. _assertPred!"=="(Date(-2, 12, 31).dayOfGregorianCal, SysTime(DateTime(-2, 12, 31, 12, 13, 14), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5925. _assertPred!"=="(Date(-2, 1, 1).dayOfGregorianCal, SysTime(DateTime(-2, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5926. _assertPred!"=="(Date(-3, 12, 31).dayOfGregorianCal, SysTime(DateTime(-3, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5927. _assertPred!"=="(Date(-3, 1, 1).dayOfGregorianCal, SysTime(DateTime(-3, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5928. _assertPred!"=="(Date(-4, 12, 31).dayOfGregorianCal, SysTime(DateTime(-4, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5929. _assertPred!"=="(Date(-4, 1, 1).dayOfGregorianCal, SysTime(DateTime(-4, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5930. _assertPred!"=="(Date(-5, 12, 31).dayOfGregorianCal, SysTime(DateTime(-5, 12, 31, 0, 0, 0), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5931. _assertPred!"=="(Date(-5, 1, 1).dayOfGregorianCal, SysTime(DateTime(-5, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5932. _assertPred!"=="(Date(-9, 1, 1).dayOfGregorianCal, SysTime(DateTime(-9, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5933. _assertPred!"=="(Date(-49, 1, 1).dayOfGregorianCal, SysTime(DateTime(-49, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5934. _assertPred!"=="(Date(-50, 1, 1).dayOfGregorianCal, SysTime(DateTime(-50, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5935. _assertPred!"=="(Date(-97, 1, 1).dayOfGregorianCal, SysTime(DateTime(-97, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5936. _assertPred!"=="(Date(-99, 12, 31).dayOfGregorianCal, SysTime(DateTime(-99, 12, 31, 12, 13, 14), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5937. _assertPred!"=="(Date(-99, 1, 1).dayOfGregorianCal, SysTime(DateTime(-99, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5938. _assertPred!"=="(Date(-100, 1, 1).dayOfGregorianCal, SysTime(DateTime(-100, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5939. _assertPred!"=="(Date(-101, 1, 1).dayOfGregorianCal, SysTime(DateTime(-101, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5940. _assertPred!"=="(Date(-105, 1, 1).dayOfGregorianCal, SysTime(DateTime(-105, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5941. _assertPred!"=="(Date(-200, 1, 1).dayOfGregorianCal, SysTime(DateTime(-200, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5942. _assertPred!"=="(Date(-201, 1, 1).dayOfGregorianCal, SysTime(DateTime(-201, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5943. _assertPred!"=="(Date(-300, 1, 1).dayOfGregorianCal, SysTime(DateTime(-300, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5944. _assertPred!"=="(Date(-301, 1, 1).dayOfGregorianCal, SysTime(DateTime(-301, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5945. _assertPred!"=="(Date(-400, 12, 31).dayOfGregorianCal, SysTime(DateTime(-400, 12, 31, 12, 13, 14), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5946. _assertPred!"=="(Date(-400, 1, 1).dayOfGregorianCal, SysTime(DateTime(-400, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5947. _assertPred!"=="(Date(-401, 1, 1).dayOfGregorianCal, SysTime(DateTime(-401, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5948. _assertPred!"=="(Date(-499, 1, 1).dayOfGregorianCal, SysTime(DateTime(-499, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5949. _assertPred!"=="(Date(-500, 1, 1).dayOfGregorianCal, SysTime(DateTime(-500, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5950. _assertPred!"=="(Date(-501, 1, 1).dayOfGregorianCal, SysTime(DateTime(-501, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5951. _assertPred!"=="(Date(-1000, 1, 1).dayOfGregorianCal, SysTime(DateTime(-1000, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5952. _assertPred!"=="(Date(-1001, 1, 1).dayOfGregorianCal, SysTime(DateTime(-1001, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5953. _assertPred!"=="(Date(-1599, 1, 1).dayOfGregorianCal, SysTime(DateTime(-1599, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5954. _assertPred!"=="(Date(-1600, 12, 31).dayOfGregorianCal, SysTime(DateTime(-1600, 12, 31, 0, 0, 0), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5955. _assertPred!"=="(Date(-1600, 1, 1).dayOfGregorianCal, SysTime(DateTime(-1600, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5956. _assertPred!"=="(Date(-1601, 1, 1).dayOfGregorianCal, SysTime(DateTime(-1601, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5957. _assertPred!"=="(Date(-1900, 1, 1).dayOfGregorianCal, SysTime(DateTime(-1900, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5958. _assertPred!"=="(Date(-1901, 1, 1).dayOfGregorianCal, SysTime(DateTime(-1901, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5959. _assertPred!"=="(Date(-1999, 1, 1).dayOfGregorianCal, SysTime(DateTime(-1999, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5960. _assertPred!"=="(Date(-1999, 7, 6).dayOfGregorianCal, SysTime(DateTime(-1999, 7, 6, 12, 13, 14), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5961. _assertPred!"=="(Date(-2000, 12, 31).dayOfGregorianCal, SysTime(DateTime(-2000, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5962. _assertPred!"=="(Date(-2000, 1, 1).dayOfGregorianCal, SysTime(DateTime(-2000, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5963. _assertPred!"=="(Date(-2001, 1, 1).dayOfGregorianCal, SysTime(DateTime(-2001, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5964. _assertPred!"=="(Date(-2010, 1, 1).dayOfGregorianCal, SysTime(DateTime(-2010, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5965. _assertPred!"=="(Date(-2010, 1, 31).dayOfGregorianCal, SysTime(DateTime(-2010, 1, 31, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5966. _assertPred!"=="(Date(-2010, 2, 1).dayOfGregorianCal, SysTime(DateTime(-2010, 2, 1, 0, 0, 0), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5967. _assertPred!"=="(Date(-2010, 2, 28).dayOfGregorianCal, SysTime(DateTime(-2010, 2, 28, 0, 0, 0), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5968. _assertPred!"=="(Date(-2010, 3, 1).dayOfGregorianCal, SysTime(DateTime(-2010, 3, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5969. _assertPred!"=="(Date(-2010, 3, 31).dayOfGregorianCal, SysTime(DateTime(-2010, 3, 31, 12, 13, 14), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5970. _assertPred!"=="(Date(-2010, 4, 1).dayOfGregorianCal, SysTime(DateTime(-2010, 4, 1, 12, 13, 14), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5971. _assertPred!"=="(Date(-2010, 4, 30).dayOfGregorianCal, SysTime(DateTime(-2010, 4, 30, 12, 13, 14), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5972. _assertPred!"=="(Date(-2010, 5, 1).dayOfGregorianCal, SysTime(DateTime(-2010, 5, 1, 12, 13, 14), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5973. _assertPred!"=="(Date(-2010, 5, 31).dayOfGregorianCal, SysTime(DateTime(-2010, 5, 31, 23, 59, 59), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5974. _assertPred!"=="(Date(-2010, 6, 1).dayOfGregorianCal, SysTime(DateTime(-2010, 6, 1, 23, 59, 59), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5975. _assertPred!"=="(Date(-2010, 6, 30).dayOfGregorianCal, SysTime(DateTime(-2010, 6, 30, 23, 59, 59), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5976. _assertPred!"=="(Date(-2010, 7, 1).dayOfGregorianCal, SysTime(DateTime(-2010, 7, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5977. _assertPred!"=="(Date(-2010, 7, 31).dayOfGregorianCal, SysTime(DateTime(-2010, 7, 31, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5978. _assertPred!"=="(Date(-2010, 8, 1).dayOfGregorianCal, SysTime(DateTime(-2010, 8, 1, 0, 0, 0), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5979. _assertPred!"=="(Date(-2010, 8, 31).dayOfGregorianCal, SysTime(DateTime(-2010, 8, 31, 0, 0, 0), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5980. _assertPred!"=="(Date(-2010, 9, 1).dayOfGregorianCal, SysTime(DateTime(-2010, 9, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5981. _assertPred!"=="(Date(-2010, 9, 30).dayOfGregorianCal, SysTime(DateTime(-2010, 9, 30, 12, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5982. _assertPred!"=="(Date(-2010, 10, 1).dayOfGregorianCal, SysTime(DateTime(-2010, 10, 1, 0, 12, 0), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5983. _assertPred!"=="(Date(-2010, 10, 31).dayOfGregorianCal, SysTime(DateTime(-2010, 10, 31, 0, 0, 12), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5984. _assertPred!"=="(Date(-2010, 11, 1).dayOfGregorianCal, SysTime(DateTime(-2010, 11, 1, 23, 0, 0), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5985. _assertPred!"=="(Date(-2010, 11, 30).dayOfGregorianCal, SysTime(DateTime(-2010, 11, 30, 0, 59, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5986. _assertPred!"=="(Date(-2010, 12, 1).dayOfGregorianCal, SysTime(DateTime(-2010, 12, 1, 0, 0, 59), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
  5987. _assertPred!"=="(Date(-2010, 12, 31).dayOfGregorianCal, SysTime(DateTime(-2010, 12, 31, 0, 59, 59), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
  5988. _assertPred!"=="(Date(-2012, 2, 1).dayOfGregorianCal, SysTime(DateTime(-2012, 2, 1, 23, 0, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
  5989. _assertPred!"=="(Date(-2012, 2, 28).dayOfGregorianCal, SysTime(DateTime(-2012, 2, 28, 23, 59, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5990. _assertPred!"=="(Date(-2012, 2, 29).dayOfGregorianCal, SysTime(DateTime(-2012, 2, 29, 7, 7, 7), FracSec.from!"hnsecs"(7)).dayOfGregorianCal);
  5991. _assertPred!"=="(Date(-2012, 3, 1).dayOfGregorianCal, SysTime(DateTime(-2012, 3, 1, 7, 7, 7), FracSec.from!"hnsecs"(7)).dayOfGregorianCal);
  5992. _assertPred!"=="(Date(-3760, 9, 7).dayOfGregorianCal, SysTime(DateTime(-3760, 9, 7, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
  5993. }
  5994. }
  5995. /++
  5996. The Xth day of the Gregorian Calendar that this $(D SysTime) is on.
  5997. Setting this property does not affect the time portion of $(D SysTime).
  5998. Params:
  5999. days = The day of the Gregorian Calendar to set this $(D SysTime)
  6000. to.
  6001. Examples:
  6002. --------------------
  6003. auto st = SysTime(DateTime(0, 0, 0, 12, 0, 0));
  6004. st.dayOfGregorianCal = 1;
  6005. assert(st == SysTime(DateTime(1, 1, 1, 12, 0, 0)));
  6006. st.dayOfGregorianCal = 365;
  6007. assert(st == SysTime(DateTime(1, 12, 31, 12, 0, 0)));
  6008. st.dayOfGregorianCal = 366;
  6009. assert(st == SysTime(DateTime(2, 1, 1, 12, 0, 0)));
  6010. st.dayOfGregorianCal = 0;
  6011. assert(st == SysTime(DateTime(0, 12, 31, 12, 0, 0)));
  6012. st.dayOfGregorianCal = -365;
  6013. assert(st == SysTime(DateTime(-0, 1, 1, 12, 0, 0)));
  6014. st.dayOfGregorianCal = -366;
  6015. assert(st == SysTime(DateTime(-1, 12, 31, 12, 0, 0)));
  6016. st.dayOfGregorianCal = 730_120;
  6017. assert(st == SysTime(DateTime(2000, 1, 1, 12, 0, 0)));
  6018. st.dayOfGregorianCal = 734_137;
  6019. assert(st == SysTime(DateTime(2010, 12, 31, 12, 0, 0)));
  6020. --------------------
  6021. +/
  6022. @property void dayOfGregorianCal(int days) nothrow
  6023. {
  6024. auto hnsecs = adjTime;
  6025. hnsecs = removeUnitsFromHNSecs!"days"(hnsecs);
  6026. if(hnsecs < 0)
  6027. hnsecs += convert!("hours", "hnsecs")(24);
  6028. if(--days < 0)
  6029. {
  6030. hnsecs -= convert!("hours", "hnsecs")(24);
  6031. ++days;
  6032. }
  6033. immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
  6034. adjTime = newDaysHNSecs + hnsecs;
  6035. }
  6036. unittest
  6037. {
  6038. version(testStdDateTime)
  6039. {
  6040. void testST(SysTime orig, int day, in SysTime expected, size_t line = __LINE__)
  6041. {
  6042. orig.dayOfGregorianCal = day;
  6043. _assertPred!"=="(orig, expected, "", __FILE__, line);
  6044. }
  6045. //Test A.D.
  6046. testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  6047. testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
  6048. testST(SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6049. //Test B.C.
  6050. testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), 0, SysTime(DateTime(0, 12, 31, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  6051. testST(SysTime(DateTime(0, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6052. testST(SysTime(DateTime(0, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(1)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)));
  6053. testST(SysTime(DateTime(0, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(0)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0)));
  6054. //Test Both.
  6055. testST(SysTime(DateTime(-512, 7, 20, 0, 0, 0), FracSec.from!"hnsecs"(0)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  6056. testST(SysTime(DateTime(-513, 6, 6, 0, 0, 0), FracSec.from!"hnsecs"(1)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
  6057. testST(SysTime(DateTime(-511, 5, 7, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6058. testST(SysTime(DateTime(1607, 4, 8, 0, 0, 0), FracSec.from!"hnsecs"(0)), 0, SysTime(DateTime(0, 12, 31, 0, 0, 0), FracSec.from!"hnsecs"(0)));
  6059. testST(SysTime(DateTime(1500, 3, 9, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6060. testST(SysTime(DateTime(999, 2, 10, 23, 59, 59), FracSec.from!"hnsecs"(1)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)));
  6061. testST(SysTime(DateTime(2007, 12, 11, 23, 59, 59), FracSec.from!"hnsecs"(0)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0)));
  6062. auto sysTime = SysTime(DateTime(1, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212));
  6063. void testST2(int day, in SysTime expected, size_t line = __LINE__)
  6064. {
  6065. sysTime.dayOfGregorianCal = day;
  6066. _assertPred!"=="(sysTime, expected, "", __FILE__, line);
  6067. }
  6068. //Test A.D.
  6069. testST2(1, SysTime(DateTime(1, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6070. testST2(2, SysTime(DateTime(1, 1, 2, 12, 2, 9), FracSec.from!"msecs"(212)));
  6071. testST2(32, SysTime(DateTime(1, 2, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6072. testST2(366, SysTime(DateTime(2, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6073. testST2(731, SysTime(DateTime(3, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6074. testST2(1096, SysTime(DateTime(4, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6075. testST2(1462, SysTime(DateTime(5, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6076. testST2(17_898, SysTime(DateTime(50, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6077. testST2(35_065, SysTime(DateTime(97, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6078. testST2(36_160, SysTime(DateTime(100, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6079. testST2(36_525, SysTime(DateTime(101, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6080. testST2(37_986, SysTime(DateTime(105, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6081. testST2(72_684, SysTime(DateTime(200, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6082. testST2(73_049, SysTime(DateTime(201, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6083. testST2(109_208, SysTime(DateTime(300, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6084. testST2(109_573, SysTime(DateTime(301, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6085. testST2(145_732, SysTime(DateTime(400, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6086. testST2(146_098, SysTime(DateTime(401, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6087. testST2(182_257, SysTime(DateTime(500, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6088. testST2(182_622, SysTime(DateTime(501, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6089. testST2(364_878, SysTime(DateTime(1000, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6090. testST2(365_243, SysTime(DateTime(1001, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6091. testST2(584_023, SysTime(DateTime(1600, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6092. testST2(584_389, SysTime(DateTime(1601, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6093. testST2(693_596, SysTime(DateTime(1900, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6094. testST2(693_961, SysTime(DateTime(1901, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6095. testST2(729_755, SysTime(DateTime(1999, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6096. testST2(730_120, SysTime(DateTime(2000, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6097. testST2(730_486, SysTime(DateTime(2001, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6098. testST2(733_773, SysTime(DateTime(2010, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6099. testST2(733_803, SysTime(DateTime(2010, 1, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
  6100. testST2(733_804, SysTime(DateTime(2010, 2, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6101. testST2(733_831, SysTime(DateTime(2010, 2, 28, 12, 2, 9), FracSec.from!"msecs"(212)));
  6102. testST2(733_832, SysTime(DateTime(2010, 3, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6103. testST2(733_862, SysTime(DateTime(2010, 3, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
  6104. testST2(733_863, SysTime(DateTime(2010, 4, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6105. testST2(733_892, SysTime(DateTime(2010, 4, 30, 12, 2, 9), FracSec.from!"msecs"(212)));
  6106. testST2(733_893, SysTime(DateTime(2010, 5, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6107. testST2(733_923, SysTime(DateTime(2010, 5, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
  6108. testST2(733_924, SysTime(DateTime(2010, 6, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6109. testST2(733_953, SysTime(DateTime(2010, 6, 30, 12, 2, 9), FracSec.from!"msecs"(212)));
  6110. testST2(733_954, SysTime(DateTime(2010, 7, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6111. testST2(733_984, SysTime(DateTime(2010, 7, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
  6112. testST2(733_985, SysTime(DateTime(2010, 8, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6113. testST2(734_015, SysTime(DateTime(2010, 8, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
  6114. testST2(734_016, SysTime(DateTime(2010, 9, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6115. testST2(734_045, SysTime(DateTime(2010, 9, 30, 12, 2, 9), FracSec.from!"msecs"(212)));
  6116. testST2(734_046, SysTime(DateTime(2010, 10, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6117. testST2(734_076, SysTime(DateTime(2010, 10, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
  6118. testST2(734_077, SysTime(DateTime(2010, 11, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6119. testST2(734_106, SysTime(DateTime(2010, 11, 30, 12, 2, 9), FracSec.from!"msecs"(212)));
  6120. testST2(734_107, SysTime(DateTime(2010, 12, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6121. testST2(734_137, SysTime(DateTime(2010, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
  6122. testST2(734_534, SysTime(DateTime(2012, 2, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6123. testST2(734_561, SysTime(DateTime(2012, 2, 28, 12, 2, 9), FracSec.from!"msecs"(212)));
  6124. testST2(734_562, SysTime(DateTime(2012, 2, 29, 12, 2, 9), FracSec.from!"msecs"(212)));
  6125. testST2(734_563, SysTime(DateTime(2012, 3, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6126. testST2(734_534, SysTime(DateTime(2012, 2, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6127. testST2(734_561, SysTime(DateTime(2012, 2, 28, 12, 2, 9), FracSec.from!"msecs"(212)));
  6128. testST2(734_562, SysTime(DateTime(2012, 2, 29, 12, 2, 9), FracSec.from!"msecs"(212)));
  6129. testST2(734_563, SysTime(DateTime(2012, 3, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6130. //Test B.C.
  6131. testST2(0, SysTime(DateTime(0, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
  6132. testST2(-1, SysTime(DateTime(0, 12, 30, 12, 2, 9), FracSec.from!"msecs"(212)));
  6133. testST2(-30, SysTime(DateTime(0, 12, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6134. testST2(-31, SysTime(DateTime(0, 11, 30, 12, 2, 9), FracSec.from!"msecs"(212)));
  6135. testST2(-366, SysTime(DateTime(-1, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
  6136. testST2(-367, SysTime(DateTime(-1, 12, 30, 12, 2, 9), FracSec.from!"msecs"(212)));
  6137. testST2(-730, SysTime(DateTime(-1, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6138. testST2(-731, SysTime(DateTime(-2, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
  6139. testST2(-1095, SysTime(DateTime(-2, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6140. testST2(-1096, SysTime(DateTime(-3, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
  6141. testST2(-1460, SysTime(DateTime(-3, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6142. testST2(-1461, SysTime(DateTime(-4, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
  6143. testST2(-1826, SysTime(DateTime(-4, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6144. testST2(-1827, SysTime(DateTime(-5, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
  6145. testST2(-2191, SysTime(DateTime(-5, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6146. testST2(-3652, SysTime(DateTime(-9, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6147. testST2(-18_262, SysTime(DateTime(-49, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6148. testST2(-18_627, SysTime(DateTime(-50, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6149. testST2(-35_794, SysTime(DateTime(-97, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6150. testST2(-36_160, SysTime(DateTime(-99, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
  6151. testST2(-36_524, SysTime(DateTime(-99, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6152. testST2(-36_889, SysTime(DateTime(-100, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6153. testST2(-37_254, SysTime(DateTime(-101, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6154. testST2(-38_715, SysTime(DateTime(-105, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6155. testST2(-73_413, SysTime(DateTime(-200, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6156. testST2(-73_778, SysTime(DateTime(-201, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6157. testST2(-109_937, SysTime(DateTime(-300, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6158. testST2(-110_302, SysTime(DateTime(-301, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6159. testST2(-146_097, SysTime(DateTime(-400, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
  6160. testST2(-146_462, SysTime(DateTime(-400, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6161. testST2(-146_827, SysTime(DateTime(-401, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6162. testST2(-182_621, SysTime(DateTime(-499, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6163. testST2(-182_986, SysTime(DateTime(-500, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6164. testST2(-183_351, SysTime(DateTime(-501, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6165. testST2(-365_607, SysTime(DateTime(-1000, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6166. testST2(-365_972, SysTime(DateTime(-1001, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6167. testST2(-584_387, SysTime(DateTime(-1599, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6168. testST2(-584_388, SysTime(DateTime(-1600, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
  6169. testST2(-584_753, SysTime(DateTime(-1600, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6170. testST2(-585_118, SysTime(DateTime(-1601, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6171. testST2(-694_325, SysTime(DateTime(-1900, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6172. testST2(-694_690, SysTime(DateTime(-1901, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6173. testST2(-730_484, SysTime(DateTime(-1999, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6174. testST2(-730_485, SysTime(DateTime(-2000, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
  6175. testST2(-730_850, SysTime(DateTime(-2000, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6176. testST2(-731_215, SysTime(DateTime(-2001, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6177. testST2(-734_502, SysTime(DateTime(-2010, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6178. testST2(-734_472, SysTime(DateTime(-2010, 1, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
  6179. testST2(-734_471, SysTime(DateTime(-2010, 2, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6180. testST2(-734_444, SysTime(DateTime(-2010, 2, 28, 12, 2, 9), FracSec.from!"msecs"(212)));
  6181. testST2(-734_443, SysTime(DateTime(-2010, 3, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6182. testST2(-734_413, SysTime(DateTime(-2010, 3, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
  6183. testST2(-734_412, SysTime(DateTime(-2010, 4, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6184. testST2(-734_383, SysTime(DateTime(-2010, 4, 30, 12, 2, 9), FracSec.from!"msecs"(212)));
  6185. testST2(-734_382, SysTime(DateTime(-2010, 5, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6186. testST2(-734_352, SysTime(DateTime(-2010, 5, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
  6187. testST2(-734_351, SysTime(DateTime(-2010, 6, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6188. testST2(-734_322, SysTime(DateTime(-2010, 6, 30, 12, 2, 9), FracSec.from!"msecs"(212)));
  6189. testST2(-734_321, SysTime(DateTime(-2010, 7, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6190. testST2(-734_291, SysTime(DateTime(-2010, 7, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
  6191. testST2(-734_290, SysTime(DateTime(-2010, 8, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6192. testST2(-734_260, SysTime(DateTime(-2010, 8, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
  6193. testST2(-734_259, SysTime(DateTime(-2010, 9, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6194. testST2(-734_230, SysTime(DateTime(-2010, 9, 30, 12, 2, 9), FracSec.from!"msecs"(212)));
  6195. testST2(-734_229, SysTime(DateTime(-2010, 10, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6196. testST2(-734_199, SysTime(DateTime(-2010, 10, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
  6197. testST2(-734_198, SysTime(DateTime(-2010, 11, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6198. testST2(-734_169, SysTime(DateTime(-2010, 11, 30, 12, 2, 9), FracSec.from!"msecs"(212)));
  6199. testST2(-734_168, SysTime(DateTime(-2010, 12, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6200. testST2(-734_138, SysTime(DateTime(-2010, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
  6201. testST2(-735_202, SysTime(DateTime(-2012, 2, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6202. testST2(-735_175, SysTime(DateTime(-2012, 2, 28, 12, 2, 9), FracSec.from!"msecs"(212)));
  6203. testST2(-735_174, SysTime(DateTime(-2012, 2, 29, 12, 2, 9), FracSec.from!"msecs"(212)));
  6204. testST2(-735_173, SysTime(DateTime(-2012, 3, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
  6205. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6206. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6207. static assert(!__traits(compiles, cst.dayOfGregorianCal = 7));
  6208. //static assert(!__traits(compiles, ist.dayOfGregorianCal = 7));
  6209. //Verify Examples.
  6210. auto st = SysTime(DateTime(0, 1, 1, 12, 0, 0));
  6211. st.dayOfGregorianCal = 1;
  6212. assert(st == SysTime(DateTime(1, 1, 1, 12, 0, 0)));
  6213. st.dayOfGregorianCal = 365;
  6214. assert(st == SysTime(DateTime(1, 12, 31, 12, 0, 0)));
  6215. st.dayOfGregorianCal = 366;
  6216. assert(st == SysTime(DateTime(2, 1, 1, 12, 0, 0)));
  6217. st.dayOfGregorianCal = 0;
  6218. assert(st == SysTime(DateTime(0, 12, 31, 12, 0, 0)));
  6219. st.dayOfGregorianCal = -365;
  6220. assert(st == SysTime(DateTime(-0, 1, 1, 12, 0, 0)));
  6221. st.dayOfGregorianCal = -366;
  6222. assert(st == SysTime(DateTime(-1, 12, 31, 12, 0, 0)));
  6223. st.dayOfGregorianCal = 730_120;
  6224. assert(st == SysTime(DateTime(2000, 1, 1, 12, 0, 0)));
  6225. st.dayOfGregorianCal = 734_137;
  6226. assert(st == SysTime(DateTime(2010, 12, 31, 12, 0, 0)));
  6227. }
  6228. }
  6229. /++
  6230. The ISO 8601 week of the year that this $(D SysTime) is in.
  6231. See_Also:
  6232. $(WEB en.wikipedia.org/wiki/ISO_week_date, ISO Week Date).
  6233. +/
  6234. @property ubyte isoWeek() const nothrow
  6235. {
  6236. return (cast(Date)this).isoWeek;
  6237. }
  6238. unittest
  6239. {
  6240. version(testStdDateTime)
  6241. {
  6242. auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6243. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6244. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6245. static assert(__traits(compiles, st.isoWeek));
  6246. static assert(__traits(compiles, cst.isoWeek));
  6247. //static assert(__traits(compiles, ist.isoWeek));
  6248. }
  6249. }
  6250. /++
  6251. $(D SysTime) for the last day in the month that this Date is in.
  6252. The time portion of endOfMonth is always 23:59:59.9999999.
  6253. Examples:
  6254. --------------------
  6255. assert(SysTime(DateTime(1999, 1, 6, 0, 0, 0)).endOfMonth ==
  6256. SysTime(DateTime(1999, 1, 31, 23, 59, 59),
  6257. FracSec.from!"hnsecs"(9_999_999)));
  6258. assert(SysTime(DateTime(1999, 2, 7, 19, 30, 0),
  6259. FracSec.from!"msecs"(24)).endOfMonth ==
  6260. SysTime(DateTime(1999, 2, 28, 23, 59, 59),
  6261. FracSec.from!"hnsecs"(9_999_999)));
  6262. assert(SysTime(DateTime(2000, 2, 7, 5, 12, 27),
  6263. FracSec.from!"usecs"(5203)).endOfMonth ==
  6264. SysTime(DateTime(2000, 2, 29, 23, 59, 59),
  6265. FracSec.from!"hnsecs"(9_999_999)));
  6266. assert(SysTime(DateTime(2000, 6, 4, 12, 22, 9),
  6267. FracSec.from!"hnsecs"(12345)).endOfMonth ==
  6268. SysTime(DateTime(2000, 6, 30, 23, 59, 59),
  6269. FracSec.from!"hnsecs"(9_999_999)));
  6270. --------------------
  6271. +/
  6272. @property SysTime endOfMonth() const nothrow
  6273. {
  6274. immutable hnsecs = adjTime;
  6275. immutable days = getUnitsFromHNSecs!"days"(hnsecs);
  6276. auto date = Date(cast(int)days + 1).endOfMonth;
  6277. auto newDays = date.dayOfGregorianCal - 1;
  6278. long theTimeHNSecs;
  6279. if(newDays < 0)
  6280. {
  6281. theTimeHNSecs = -1;
  6282. ++newDays;
  6283. }
  6284. else
  6285. theTimeHNSecs = convert!("days", "hnsecs")(1) - 1;
  6286. immutable newDaysHNSecs = convert!("days", "hnsecs")(newDays);
  6287. auto retval = SysTime(this._stdTime, this._timezone);
  6288. retval.adjTime = newDaysHNSecs + theTimeHNSecs;
  6289. return retval;
  6290. }
  6291. unittest
  6292. {
  6293. version(testStdDateTime)
  6294. {
  6295. //Test A.D.
  6296. _assertPred!"=="(SysTime(Date(1999, 1, 1)).endOfMonth, SysTime(DateTime(1999, 1, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6297. _assertPred!"=="(SysTime(Date(1999, 2, 1)).endOfMonth, SysTime(DateTime(1999, 2, 28, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6298. _assertPred!"=="(SysTime(Date(2000, 2, 1)).endOfMonth, SysTime(DateTime(2000, 2, 29, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6299. _assertPred!"=="(SysTime(Date(1999, 3, 1)).endOfMonth, SysTime(DateTime(1999, 3, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6300. _assertPred!"=="(SysTime(Date(1999, 4, 1)).endOfMonth, SysTime(DateTime(1999, 4, 30, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6301. _assertPred!"=="(SysTime(Date(1999, 5, 1)).endOfMonth, SysTime(DateTime(1999, 5, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6302. _assertPred!"=="(SysTime(Date(1999, 6, 1)).endOfMonth, SysTime(DateTime(1999, 6, 30, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6303. _assertPred!"=="(SysTime(Date(1999, 7, 1)).endOfMonth, SysTime(DateTime(1999, 7, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6304. _assertPred!"=="(SysTime(Date(1999, 8, 1)).endOfMonth, SysTime(DateTime(1999, 8, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6305. _assertPred!"=="(SysTime(Date(1999, 9, 1)).endOfMonth, SysTime(DateTime(1999, 9, 30, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6306. _assertPred!"=="(SysTime(Date(1999, 10, 1)).endOfMonth, SysTime(DateTime(1999, 10, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6307. _assertPred!"=="(SysTime(Date(1999, 11, 1)).endOfMonth, SysTime(DateTime(1999, 11, 30, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6308. _assertPred!"=="(SysTime(Date(1999, 12, 1)).endOfMonth, SysTime(DateTime(1999, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6309. //Test B.C.
  6310. _assertPred!"=="(SysTime(Date(-1999, 1, 1)).endOfMonth, SysTime(DateTime(-1999, 1, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6311. _assertPred!"=="(SysTime(Date(-1999, 2, 1)).endOfMonth, SysTime(DateTime(-1999, 2, 28, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6312. _assertPred!"=="(SysTime(Date(-2000, 2, 1)).endOfMonth, SysTime(DateTime(-2000, 2, 29, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6313. _assertPred!"=="(SysTime(Date(-1999, 3, 1)).endOfMonth, SysTime(DateTime(-1999, 3, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6314. _assertPred!"=="(SysTime(Date(-1999, 4, 1)).endOfMonth, SysTime(DateTime(-1999, 4, 30, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6315. _assertPred!"=="(SysTime(Date(-1999, 5, 1)).endOfMonth, SysTime(DateTime(-1999, 5, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6316. _assertPred!"=="(SysTime(Date(-1999, 6, 1)).endOfMonth, SysTime(DateTime(-1999, 6, 30, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6317. _assertPred!"=="(SysTime(Date(-1999, 7, 1)).endOfMonth, SysTime(DateTime(-1999, 7, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6318. _assertPred!"=="(SysTime(Date(-1999, 8, 1)).endOfMonth, SysTime(DateTime(-1999, 8, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6319. _assertPred!"=="(SysTime(Date(-1999, 9, 1)).endOfMonth, SysTime(DateTime(-1999, 9, 30, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6320. _assertPred!"=="(SysTime(Date(-1999, 10, 1)).endOfMonth, SysTime(DateTime(-1999, 10, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6321. _assertPred!"=="(SysTime(Date(-1999, 11, 1)).endOfMonth, SysTime(DateTime(-1999, 11, 30, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6322. _assertPred!"=="(SysTime(Date(-1999, 12, 1)).endOfMonth, SysTime(DateTime(-1999, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6323. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6324. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6325. static assert(__traits(compiles, cst.endOfMonth));
  6326. //static assert(__traits(compiles, ist.endOfMonth));
  6327. //Verify Examples.
  6328. assert(SysTime(DateTime(1999, 1, 6, 0, 0, 0)).endOfMonth == SysTime(DateTime(1999, 1, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6329. assert(SysTime(DateTime(1999, 2, 7, 19, 30, 0), FracSec.from!"msecs"(24)).endOfMonth == SysTime(DateTime(1999, 2, 28, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6330. assert(SysTime(DateTime(2000, 2, 7, 5, 12, 27), FracSec.from!"usecs"(5203)).endOfMonth == SysTime(DateTime(2000, 2, 29, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6331. assert(SysTime(DateTime(2000, 6, 4, 12, 22, 9), FracSec.from!"hnsecs"(12345)).endOfMonth == SysTime(DateTime(2000, 6, 30, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
  6332. }
  6333. }
  6334. /++
  6335. The last day in the month that this $(D SysTime) is in.
  6336. Examples:
  6337. --------------------
  6338. assert(SysTime(DateTime(1999, 1, 6, 0, 0, 0)).daysInMonth == 31);
  6339. assert(SysTime(DateTime(1999, 2, 7, 19, 30, 0)).daysInMonth == 28);
  6340. assert(SysTime(DateTime(2000, 2, 7, 5, 12, 27)).daysInMonth == 29);
  6341. assert(SysTime(DateTime(2000, 6, 4, 12, 22, 9)).daysInMonth == 30);
  6342. --------------------
  6343. +/
  6344. @property ubyte daysInMonth() const nothrow
  6345. {
  6346. return Date(dayOfGregorianCal).daysInMonth;
  6347. }
  6348. /++
  6349. $(RED Scheduled for deprecation in January 2012.
  6350. Please use daysInMonth instead.)
  6351. +/
  6352. alias daysInMonth endofMonthDay;
  6353. unittest
  6354. {
  6355. version(testStdDateTime)
  6356. {
  6357. //Test A.D.
  6358. _assertPred!"=="(SysTime(DateTime(1999, 1, 1, 12, 1, 13)).daysInMonth, 31);
  6359. _assertPred!"=="(SysTime(DateTime(1999, 2, 1, 17, 13, 12)).daysInMonth, 28);
  6360. _assertPred!"=="(SysTime(DateTime(2000, 2, 1, 13, 2, 12)).daysInMonth, 29);
  6361. _assertPred!"=="(SysTime(DateTime(1999, 3, 1, 12, 13, 12)).daysInMonth, 31);
  6362. _assertPred!"=="(SysTime(DateTime(1999, 4, 1, 12, 6, 13)).daysInMonth, 30);
  6363. _assertPred!"=="(SysTime(DateTime(1999, 5, 1, 15, 13, 12)).daysInMonth, 31);
  6364. _assertPred!"=="(SysTime(DateTime(1999, 6, 1, 13, 7, 12)).daysInMonth, 30);
  6365. _assertPred!"=="(SysTime(DateTime(1999, 7, 1, 12, 13, 17)).daysInMonth, 31);
  6366. _assertPred!"=="(SysTime(DateTime(1999, 8, 1, 12, 3, 13)).daysInMonth, 31);
  6367. _assertPred!"=="(SysTime(DateTime(1999, 9, 1, 12, 13, 12)).daysInMonth, 30);
  6368. _assertPred!"=="(SysTime(DateTime(1999, 10, 1, 13, 19, 12)).daysInMonth, 31);
  6369. _assertPred!"=="(SysTime(DateTime(1999, 11, 1, 12, 13, 17)).daysInMonth, 30);
  6370. _assertPred!"=="(SysTime(DateTime(1999, 12, 1, 12, 52, 13)).daysInMonth, 31);
  6371. //Test B.C.
  6372. _assertPred!"=="(SysTime(DateTime(-1999, 1, 1, 12, 1, 13)).daysInMonth, 31);
  6373. _assertPred!"=="(SysTime(DateTime(-1999, 2, 1, 7, 13, 12)).daysInMonth, 28);
  6374. _assertPred!"=="(SysTime(DateTime(-2000, 2, 1, 13, 2, 12)).daysInMonth, 29);
  6375. _assertPred!"=="(SysTime(DateTime(-1999, 3, 1, 12, 13, 12)).daysInMonth, 31);
  6376. _assertPred!"=="(SysTime(DateTime(-1999, 4, 1, 12, 6, 13)).daysInMonth, 30);
  6377. _assertPred!"=="(SysTime(DateTime(-1999, 5, 1, 5, 13, 12)).daysInMonth, 31);
  6378. _assertPred!"=="(SysTime(DateTime(-1999, 6, 1, 13, 7, 12)).daysInMonth, 30);
  6379. _assertPred!"=="(SysTime(DateTime(-1999, 7, 1, 12, 13, 17)).daysInMonth, 31);
  6380. _assertPred!"=="(SysTime(DateTime(-1999, 8, 1, 12, 3, 13)).daysInMonth, 31);
  6381. _assertPred!"=="(SysTime(DateTime(-1999, 9, 1, 12, 13, 12)).daysInMonth, 30);
  6382. _assertPred!"=="(SysTime(DateTime(-1999, 10, 1, 13, 19, 12)).daysInMonth, 31);
  6383. _assertPred!"=="(SysTime(DateTime(-1999, 11, 1, 12, 13, 17)).daysInMonth, 30);
  6384. _assertPred!"=="(SysTime(DateTime(-1999, 12, 1, 12, 52, 13)).daysInMonth, 31);
  6385. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6386. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6387. static assert(__traits(compiles, cst.daysInMonth));
  6388. //static assert(__traits(compiles, ist.daysInMonth));
  6389. //Verify Examples.
  6390. assert(SysTime(DateTime(1999, 1, 6, 0, 0, 0)).daysInMonth == 31);
  6391. assert(SysTime(DateTime(1999, 2, 7, 19, 30, 0)).daysInMonth == 28);
  6392. assert(SysTime(DateTime(2000, 2, 7, 5, 12, 27)).daysInMonth == 29);
  6393. assert(SysTime(DateTime(2000, 6, 4, 12, 22, 9)).daysInMonth == 30);
  6394. }
  6395. }
  6396. /++
  6397. Whether the current year is a date in A.D.
  6398. Examples:
  6399. --------------------
  6400. assert(SysTime(DateTime(1, 1, 1, 12, 7, 0)).isAD);
  6401. assert(SysTime(DateTime(2010, 12, 31, 0, 0, 0)).isAD);
  6402. assert(!SysTime(DateTime(0, 12, 31, 23, 59, 59)).isAD);
  6403. assert(!SysTime(DateTime(-2010, 1, 1, 2, 2, 2)).isAD);
  6404. --------------------
  6405. +/
  6406. @property bool isAD() const nothrow
  6407. {
  6408. return adjTime >= 0;
  6409. }
  6410. unittest
  6411. {
  6412. version(testStdDateTime)
  6413. {
  6414. assert(SysTime(DateTime(2010, 7, 4, 12, 0, 9)).isAD);
  6415. assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).isAD);
  6416. assert(!SysTime(DateTime(0, 12, 31, 23, 59, 59)).isAD);
  6417. assert(!SysTime(DateTime(0, 1, 1, 23, 59, 59)).isAD);
  6418. assert(!SysTime(DateTime(-1, 1, 1, 23 ,59 ,59)).isAD);
  6419. assert(!SysTime(DateTime(-2010, 7, 4, 12, 2, 2)).isAD);
  6420. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6421. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6422. static assert(__traits(compiles, cst.isAD));
  6423. //static assert(__traits(compiles, ist.isAD));
  6424. //Verify Examples.
  6425. assert(SysTime(DateTime(1, 1, 1, 12, 7, 0)).isAD);
  6426. assert(SysTime(DateTime(2010, 12, 31, 0, 0, 0)).isAD);
  6427. assert(!SysTime(DateTime(0, 12, 31, 23, 59, 59)).isAD);
  6428. assert(!SysTime(DateTime(-2010, 1, 1, 2, 2, 2)).isAD);
  6429. }
  6430. }
  6431. /++
  6432. The julian day for this $(D SysTime) at the given time. For example,
  6433. prior to noon, 1996-03-31 would be the julian day number 2_450_173, so
  6434. this function returns 2_450_173, while from noon onward, the julian
  6435. day number would be 2_450_174, so this function returns 2_450_174.
  6436. +/
  6437. @property long julianDay() const nothrow
  6438. {
  6439. immutable jd = dayOfGregorianCal + 1_721_425;
  6440. return hour < 12 ? jd - 1 : jd;
  6441. }
  6442. unittest
  6443. {
  6444. version(testStdDateTime)
  6445. {
  6446. _assertPred!"=="(SysTime(DateTime(-4713, 11, 24, 0, 0, 0)).julianDay, -1);
  6447. _assertPred!"=="(SysTime(DateTime(-4713, 11, 24, 12, 0, 0)).julianDay, 0);
  6448. _assertPred!"=="(SysTime(DateTime(0, 12, 31, 0, 0, 0)).julianDay, 1_721_424);
  6449. _assertPred!"=="(SysTime(DateTime(0, 12, 31, 12, 0, 0)).julianDay, 1_721_425);
  6450. _assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0)).julianDay, 1_721_425);
  6451. _assertPred!"=="(SysTime(DateTime(1, 1, 1, 12, 0, 0)).julianDay, 1_721_426);
  6452. _assertPred!"=="(SysTime(DateTime(1582, 10, 15, 0, 0, 0)).julianDay, 2_299_160);
  6453. _assertPred!"=="(SysTime(DateTime(1582, 10, 15, 12, 0, 0)).julianDay, 2_299_161);
  6454. _assertPred!"=="(SysTime(DateTime(1858, 11, 17, 0, 0, 0)).julianDay, 2_400_000);
  6455. _assertPred!"=="(SysTime(DateTime(1858, 11, 17, 12, 0, 0)).julianDay, 2_400_001);
  6456. _assertPred!"=="(SysTime(DateTime(1982, 1, 4, 0, 0, 0)).julianDay, 2_444_973);
  6457. _assertPred!"=="(SysTime(DateTime(1982, 1, 4, 12, 0, 0)).julianDay, 2_444_974);
  6458. _assertPred!"=="(SysTime(DateTime(1996, 3, 31, 0, 0, 0)).julianDay, 2_450_173);
  6459. _assertPred!"=="(SysTime(DateTime(1996, 3, 31, 12, 0, 0)).julianDay, 2_450_174);
  6460. _assertPred!"=="(SysTime(DateTime(2010, 8, 24, 0, 0, 0)).julianDay, 2_455_432);
  6461. _assertPred!"=="(SysTime(DateTime(2010, 8, 24, 12, 0, 0)).julianDay, 2_455_433);
  6462. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6463. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6464. static assert(__traits(compiles, cst.julianDay));
  6465. //static assert(__traits(compiles, ist.julianDay));
  6466. }
  6467. }
  6468. /++
  6469. The modified julian day for any time on this date (since, the modified
  6470. julian day changes at midnight).
  6471. +/
  6472. @property long modJulianDay() const nothrow
  6473. {
  6474. return (dayOfGregorianCal + 1_721_425) - 2_400_001;
  6475. }
  6476. unittest
  6477. {
  6478. version(testStdDateTime)
  6479. {
  6480. _assertPred!"=="(SysTime(DateTime(1858, 11, 17, 0, 0, 0)).modJulianDay, 0);
  6481. _assertPred!"=="(SysTime(DateTime(1858, 11, 17, 12, 0, 0)).modJulianDay, 0);
  6482. _assertPred!"=="(SysTime(DateTime(2010, 8, 24, 0, 0, 0)).modJulianDay, 55_432);
  6483. _assertPred!"=="(SysTime(DateTime(2010, 8, 24, 12, 0, 0)).modJulianDay, 55_432);
  6484. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6485. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6486. static assert(__traits(compiles, cst.modJulianDay));
  6487. //static assert(__traits(compiles, ist.modJulianDay));
  6488. }
  6489. }
  6490. /++
  6491. Returns a $(D Date) equivalent to this $(D SysTime).
  6492. +/
  6493. Date opCast(T)() const nothrow
  6494. if(is(Unqual!T == Date))
  6495. {
  6496. return Date(dayOfGregorianCal);
  6497. }
  6498. unittest
  6499. {
  6500. version(testStdDateTime)
  6501. {
  6502. _assertPred!"=="(cast(Date)SysTime(Date(1999, 7, 6)), Date(1999, 7, 6));
  6503. _assertPred!"=="(cast(Date)SysTime(Date(2000, 12, 31)), Date(2000, 12, 31));
  6504. _assertPred!"=="(cast(Date)SysTime(Date(2001, 1, 1)), Date(2001, 1, 1));
  6505. _assertPred!"=="(cast(Date)SysTime(DateTime(1999, 7, 6, 12, 10, 9)), Date(1999, 7, 6));
  6506. _assertPred!"=="(cast(Date)SysTime(DateTime(2000, 12, 31, 13, 11, 10)), Date(2000, 12, 31));
  6507. _assertPred!"=="(cast(Date)SysTime(DateTime(2001, 1, 1, 14, 12, 11)), Date(2001, 1, 1));
  6508. _assertPred!"=="(cast(Date)SysTime(Date(-1999, 7, 6)), Date(-1999, 7, 6));
  6509. _assertPred!"=="(cast(Date)SysTime(Date(-2000, 12, 31)), Date(-2000, 12, 31));
  6510. _assertPred!"=="(cast(Date)SysTime(Date(-2001, 1, 1)), Date(-2001, 1, 1));
  6511. _assertPred!"=="(cast(Date)SysTime(DateTime(-1999, 7, 6, 12, 10, 9)), Date(-1999, 7, 6));
  6512. _assertPred!"=="(cast(Date)SysTime(DateTime(-2000, 12, 31, 13, 11, 10)), Date(-2000, 12, 31));
  6513. _assertPred!"=="(cast(Date)SysTime(DateTime(-2001, 1, 1, 14, 12, 11)), Date(-2001, 1, 1));
  6514. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6515. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6516. static assert(__traits(compiles, cast(Date)cst));
  6517. //static assert(__traits(compiles, cast(Date)ist));
  6518. }
  6519. }
  6520. /++
  6521. Returns a $(D DateTime) equivalent to this $(D SysTime).
  6522. +/
  6523. DateTime opCast(T)() const nothrow
  6524. if(is(Unqual!T == DateTime))
  6525. {
  6526. try
  6527. {
  6528. auto hnsecs = adjTime;
  6529. auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
  6530. if(hnsecs < 0)
  6531. {
  6532. hnsecs += convert!("hours", "hnsecs")(24);
  6533. --days;
  6534. }
  6535. immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
  6536. immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
  6537. immutable second = getUnitsFromHNSecs!"seconds"(hnsecs);
  6538. return DateTime(Date(cast(int)days), TimeOfDay(cast(int)hour, cast(int)minute, cast(int)second));
  6539. }
  6540. catch(Exception e)
  6541. assert(0, "Either DateTime's constructor or TimeOfDay's constructor threw.");
  6542. }
  6543. unittest
  6544. {
  6545. version(testStdDateTime)
  6546. {
  6547. _assertPred!"=="(cast(DateTime)SysTime(DateTime(1, 1, 6, 7, 12, 22)), DateTime(1, 1, 6, 7, 12, 22));
  6548. _assertPred!"=="(cast(DateTime)SysTime(DateTime(1, 1, 6, 7, 12, 22), FracSec.from!"msecs"(22)), DateTime(1, 1, 6, 7, 12, 22));
  6549. _assertPred!"=="(cast(DateTime)SysTime(Date(1999, 7, 6)), DateTime(1999, 7, 6, 0, 0, 0));
  6550. _assertPred!"=="(cast(DateTime)SysTime(Date(2000, 12, 31)), DateTime(2000, 12, 31, 0, 0, 0));
  6551. _assertPred!"=="(cast(DateTime)SysTime(Date(2001, 1, 1)), DateTime(2001, 1, 1, 0, 0, 0));
  6552. _assertPred!"=="(cast(DateTime)SysTime(DateTime(1999, 7, 6, 12, 10, 9)), DateTime(1999, 7, 6, 12, 10, 9));
  6553. _assertPred!"=="(cast(DateTime)SysTime(DateTime(2000, 12, 31, 13, 11, 10)), DateTime(2000, 12, 31, 13, 11, 10));
  6554. _assertPred!"=="(cast(DateTime)SysTime(DateTime(2001, 1, 1, 14, 12, 11)), DateTime(2001, 1, 1, 14, 12, 11));
  6555. _assertPred!"=="(cast(DateTime)SysTime(DateTime(-1, 1, 6, 7, 12, 22)), DateTime(-1, 1, 6, 7, 12, 22));
  6556. _assertPred!"=="(cast(DateTime)SysTime(DateTime(-1, 1, 6, 7, 12, 22), FracSec.from!"msecs"(22)), DateTime(-1, 1, 6, 7, 12, 22));
  6557. _assertPred!"=="(cast(DateTime)SysTime(Date(-1999, 7, 6)), DateTime(-1999, 7, 6, 0, 0, 0));
  6558. _assertPred!"=="(cast(DateTime)SysTime(Date(-2000, 12, 31)), DateTime(-2000, 12, 31, 0, 0, 0));
  6559. _assertPred!"=="(cast(DateTime)SysTime(Date(-2001, 1, 1)), DateTime(-2001, 1, 1, 0, 0, 0));
  6560. _assertPred!"=="(cast(DateTime)SysTime(DateTime(-1999, 7, 6, 12, 10, 9)), DateTime(-1999, 7, 6, 12, 10, 9));
  6561. _assertPred!"=="(cast(DateTime)SysTime(DateTime(-2000, 12, 31, 13, 11, 10)), DateTime(-2000, 12, 31, 13, 11, 10));
  6562. _assertPred!"=="(cast(DateTime)SysTime(DateTime(-2001, 1, 1, 14, 12, 11)), DateTime(-2001, 1, 1, 14, 12, 11));
  6563. _assertPred!"=="(cast(DateTime)SysTime(DateTime(2011, 1, 13, 8, 17, 2), FracSec.from!"msecs"(296), LocalTime()),
  6564. DateTime(2011, 1, 13, 8, 17, 2));
  6565. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6566. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6567. static assert(__traits(compiles, cast(DateTime)cst));
  6568. //static assert(__traits(compiles, cast(DateTime)ist));
  6569. }
  6570. }
  6571. /++
  6572. Returns a $(D TimeOfDay) equivalent to this $(D SysTime).
  6573. +/
  6574. TimeOfDay opCast(T)() const nothrow
  6575. if(is(Unqual!T == TimeOfDay))
  6576. {
  6577. try
  6578. {
  6579. auto hnsecs = adjTime;
  6580. hnsecs = removeUnitsFromHNSecs!"days"(hnsecs);
  6581. if(hnsecs < 0)
  6582. hnsecs += convert!("hours", "hnsecs")(24);
  6583. immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
  6584. immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
  6585. immutable second = getUnitsFromHNSecs!"seconds"(hnsecs);
  6586. return TimeOfDay(cast(int)hour, cast(int)minute, cast(int)second);
  6587. }
  6588. catch(Exception e)
  6589. assert(0, "TimeOfDay's constructor threw.");
  6590. }
  6591. unittest
  6592. {
  6593. version(testStdDateTime)
  6594. {
  6595. _assertPred!"=="(cast(TimeOfDay)SysTime(Date(1999, 7, 6)), TimeOfDay(0, 0, 0));
  6596. _assertPred!"=="(cast(TimeOfDay)SysTime(Date(2000, 12, 31)), TimeOfDay(0, 0, 0));
  6597. _assertPred!"=="(cast(TimeOfDay)SysTime(Date(2001, 1, 1)), TimeOfDay(0, 0, 0));
  6598. _assertPred!"=="(cast(TimeOfDay)SysTime(DateTime(1999, 7, 6, 12, 10, 9)), TimeOfDay(12, 10, 9));
  6599. _assertPred!"=="(cast(TimeOfDay)SysTime(DateTime(2000, 12, 31, 13, 11, 10)), TimeOfDay(13, 11, 10));
  6600. _assertPred!"=="(cast(TimeOfDay)SysTime(DateTime(2001, 1, 1, 14, 12, 11)), TimeOfDay(14, 12, 11));
  6601. _assertPred!"=="(cast(TimeOfDay)SysTime(Date(-1999, 7, 6)), TimeOfDay(0, 0, 0));
  6602. _assertPred!"=="(cast(TimeOfDay)SysTime(Date(-2000, 12, 31)), TimeOfDay(0, 0, 0));
  6603. _assertPred!"=="(cast(TimeOfDay)SysTime(Date(-2001, 1, 1)), TimeOfDay(0, 0, 0));
  6604. _assertPred!"=="(cast(TimeOfDay)SysTime(DateTime(-1999, 7, 6, 12, 10, 9)), TimeOfDay(12, 10, 9));
  6605. _assertPred!"=="(cast(TimeOfDay)SysTime(DateTime(-2000, 12, 31, 13, 11, 10)), TimeOfDay(13, 11, 10));
  6606. _assertPred!"=="(cast(TimeOfDay)SysTime(DateTime(-2001, 1, 1, 14, 12, 11)), TimeOfDay(14, 12, 11));
  6607. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6608. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6609. static assert(__traits(compiles, cast(TimeOfDay)cst));
  6610. //static assert(__traits(compiles, cast(TimeOfDay)ist));
  6611. }
  6612. }
  6613. //Temporary hack until bug http://d.puremagic.com/issues/show_bug.cgi?id=4867 is fixed.
  6614. //This allows assignment from const(SysTime) to SysTime.
  6615. //It may be a good idea to keep it though, since casting from a type to itself
  6616. //should be allowed, and it doesn't work without this opCast() since opCast()
  6617. //has already been defined for other types.
  6618. SysTime opCast(T)() const pure nothrow
  6619. if(is(Unqual!T == SysTime))
  6620. {
  6621. return SysTime(_stdTime, _timezone);
  6622. }
  6623. /++
  6624. Converts this $(D SysTime) to a string with the format
  6625. YYYYMMDDTHHMMSS.FFFFFFFTZ (where F is fractional seconds and TZ is time
  6626. zone).
  6627. Note that the number of digits in the fractional seconds varies with the
  6628. number of fractional seconds. It's a maximum of 7 (which would be
  6629. hnsecs), but only has as many as are necessary to hold the correct value
  6630. (so no trailing zeroes), and if there are no fractional seconds, then
  6631. there is no decimal point.
  6632. If this $(D SysTime)'s time zone is $(D LocalTime), then TZ is empty.
  6633. If its time zone is $(D UTC), then it is "Z". Otherwise, it is the
  6634. offset from UTC (e.g. +1:00 or -7:00). Note that the offset from UTC
  6635. is $(I not) enough to uniquely identify the time zone.
  6636. Time zone offsets will be in the form +HH:MM or -HH:MM.
  6637. Examples:
  6638. --------------------
  6639. assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toISOString() ==
  6640. "20100704T070612");
  6641. assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0),
  6642. FracSec.from!"msecs"(24)).toISOString() ==
  6643. "19981225T021500.024");
  6644. assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toISOString() ==
  6645. "00000105T230959");
  6646. assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2),
  6647. FracSec.from!"hnsecs"(520_920)).toISOString() ==
  6648. "-00040105T000002.052092");
  6649. --------------------
  6650. +/
  6651. string toISOString() const nothrow
  6652. {
  6653. try
  6654. {
  6655. immutable adjustedTime = adjTime;
  6656. long hnsecs = adjustedTime;
  6657. auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
  6658. if(hnsecs < 0)
  6659. {
  6660. hnsecs += convert!("hours", "hnsecs")(24);
  6661. --days;
  6662. }
  6663. auto hour = splitUnitsFromHNSecs!"hours"(hnsecs);
  6664. auto minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
  6665. auto second = splitUnitsFromHNSecs!"seconds"(hnsecs);
  6666. auto dateTime = DateTime(Date(cast(int)days), TimeOfDay(cast(int)hour, cast(int)minute, cast(int)second));
  6667. auto fracSecStr = fracSecToISOString(cast(int)hnsecs);
  6668. if(_timezone is LocalTime())
  6669. return dateTime.toISOString() ~ fracSecToISOString(cast(int)hnsecs);
  6670. if(_timezone is UTC())
  6671. return dateTime.toISOString() ~ fracSecToISOString(cast(int)hnsecs) ~ "Z";
  6672. immutable utcOffset = cast(int)convert!("hnsecs", "minutes")(adjustedTime - stdTime);
  6673. return dateTime.toISOString() ~ fracSecToISOString(cast(int)hnsecs) ~ SimpleTimeZone.toISOString(utcOffset);
  6674. }
  6675. catch(Exception e)
  6676. assert(0, "format() threw.");
  6677. }
  6678. unittest
  6679. {
  6680. version(testStdDateTime)
  6681. {
  6682. //Test A.D.
  6683. _assertPred!"=="(SysTime(DateTime.init, UTC()).toISOString(), "00010101T000000Z");
  6684. _assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1), UTC()).toISOString(), "00010101T000000.0000001Z");
  6685. _assertPred!"=="(SysTime(DateTime(9, 12, 4, 0, 0, 0)).toISOString(), "00091204T000000");
  6686. _assertPred!"=="(SysTime(DateTime(99, 12, 4, 5, 6, 12)).toISOString(), "00991204T050612");
  6687. _assertPred!"=="(SysTime(DateTime(999, 12, 4, 13, 44, 59)).toISOString(), "09991204T134459");
  6688. _assertPred!"=="(SysTime(DateTime(9999, 7, 4, 23, 59, 59)).toISOString(), "99990704T235959");
  6689. _assertPred!"=="(SysTime(DateTime(10000, 10, 20, 1, 1, 1)).toISOString(), "+100001020T010101");
  6690. _assertPred!"=="(SysTime(DateTime(9, 12, 4, 0, 0, 0), FracSec.from!"msecs"(42)).toISOString(), "00091204T000000.042");
  6691. _assertPred!"=="(SysTime(DateTime(99, 12, 4, 5, 6, 12), FracSec.from!"msecs"(100)).toISOString(), "00991204T050612.1");
  6692. _assertPred!"=="(SysTime(DateTime(999, 12, 4, 13, 44, 59), FracSec.from!"usecs"(45020)).toISOString(), "09991204T134459.04502");
  6693. _assertPred!"=="(SysTime(DateTime(9999, 7, 4, 23, 59, 59), FracSec.from!"hnsecs"(12)).toISOString(), "99990704T235959.0000012");
  6694. _assertPred!"=="(SysTime(DateTime(10000, 10, 20, 1, 1, 1), FracSec.from!"hnsecs"(507890)).toISOString(), "+100001020T010101.050789");
  6695. _assertPred!"=="(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
  6696. new SimpleTimeZone(-360)).toISOString(),
  6697. "20121221T121212-06:00");
  6698. _assertPred!"=="(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
  6699. new SimpleTimeZone(420)).toISOString(),
  6700. "20121221T121212+07:00");
  6701. //Test B.C.
  6702. _assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999), UTC()).toISOString(), "00001231T235959.9999999Z");
  6703. _assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1), UTC()).toISOString(), "00001231T235959.0000001Z");
  6704. _assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), UTC()).toISOString(), "00001231T235959Z");
  6705. _assertPred!"=="(SysTime(DateTime(0, 12, 4, 0, 12, 4)).toISOString(), "00001204T001204");
  6706. _assertPred!"=="(SysTime(DateTime(-9, 12, 4, 0, 0, 0)).toISOString(), "-00091204T000000");
  6707. _assertPred!"=="(SysTime(DateTime(-99, 12, 4, 5, 6, 12)).toISOString(), "-00991204T050612");
  6708. _assertPred!"=="(SysTime(DateTime(-999, 12, 4, 13, 44, 59)).toISOString(), "-09991204T134459");
  6709. _assertPred!"=="(SysTime(DateTime(-9999, 7, 4, 23, 59, 59)).toISOString(), "-99990704T235959");
  6710. _assertPred!"=="(SysTime(DateTime(-10000, 10, 20, 1, 1, 1)).toISOString(), "-100001020T010101");
  6711. _assertPred!"=="(SysTime(DateTime(0, 12, 4, 0, 0, 0), FracSec.from!"msecs"(7)).toISOString(), "00001204T000000.007");
  6712. _assertPred!"=="(SysTime(DateTime(-9, 12, 4, 0, 0, 0), FracSec.from!"msecs"(42)).toISOString(), "-00091204T000000.042");
  6713. _assertPred!"=="(SysTime(DateTime(-99, 12, 4, 5, 6, 12), FracSec.from!"msecs"(100)).toISOString(), "-00991204T050612.1");
  6714. _assertPred!"=="(SysTime(DateTime(-999, 12, 4, 13, 44, 59), FracSec.from!"usecs"(45020)).toISOString(), "-09991204T134459.04502");
  6715. _assertPred!"=="(SysTime(DateTime(-9999, 7, 4, 23, 59, 59), FracSec.from!"hnsecs"(12)).toISOString(), "-99990704T235959.0000012");
  6716. _assertPred!"=="(SysTime(DateTime(-10000, 10, 20, 1, 1, 1), FracSec.from!"hnsecs"(507890)).toISOString(), "-100001020T010101.050789");
  6717. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6718. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6719. static assert(__traits(compiles, cast(TimeOfDay)cst));
  6720. //static assert(__traits(compiles, cast(TimeOfDay)ist));
  6721. //Verify Examples.
  6722. assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toISOString() ==
  6723. "20100704T070612");
  6724. assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0),
  6725. FracSec.from!"msecs"(24)).toISOString() ==
  6726. "19981225T021500.024");
  6727. assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toISOString() ==
  6728. "00000105T230959");
  6729. assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2),
  6730. FracSec.from!"hnsecs"(520_920)).toISOString() ==
  6731. "-00040105T000002.052092");
  6732. }
  6733. }
  6734. /++
  6735. Converts this $(D SysTime) to a string with the format
  6736. YYYY-MM-DDTHH:MM:SS.FFFFFFFTZ (where F is fractional seconds and TZ
  6737. is the time zone).
  6738. Note that the number of digits in the fractional seconds varies with the
  6739. number of fractional seconds. It's a maximum of 7 (which would be
  6740. hnsecs), but only has as many as are necessary to hold the correct value
  6741. (so no trailing zeroes), and if there are no fractional seconds, then
  6742. there is no decimal point.
  6743. If this $(D SysTime)'s time zone is $(D LocalTime), then TZ is empty. If
  6744. its time zone is $(D UTC), then it is "Z". Otherwise, it is the offset
  6745. from UTC (e.g. +1:00 or -7:00). Note that the offset from UTC is
  6746. $(I not) enough to uniquely identify the time zone.
  6747. Time zone offsets will be in the form +HH:MM or -HH:MM.
  6748. Examples:
  6749. --------------------
  6750. assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toISOExtString() ==
  6751. "2010-07-04T07:06:12");
  6752. assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0),
  6753. FracSec.from!"msecs"(24)).toISOExtString() ==
  6754. "1998-12-25T02:15:00.024");
  6755. assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toISOExtString() ==
  6756. "0000-01-05T23:09:59");
  6757. assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2),
  6758. FracSec.from!"hnsecs"(520_920)).toISOExtString() ==
  6759. "-0004-01-05T00:00:02.052092");
  6760. --------------------
  6761. +/
  6762. string toISOExtString() const nothrow
  6763. {
  6764. try
  6765. {
  6766. immutable adjustedTime = adjTime;
  6767. long hnsecs = adjustedTime;
  6768. auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
  6769. if(hnsecs < 0)
  6770. {
  6771. hnsecs += convert!("hours", "hnsecs")(24);
  6772. --days;
  6773. }
  6774. auto hour = splitUnitsFromHNSecs!"hours"(hnsecs);
  6775. auto minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
  6776. auto second = splitUnitsFromHNSecs!"seconds"(hnsecs);
  6777. auto dateTime = DateTime(Date(cast(int)days), TimeOfDay(cast(int)hour, cast(int)minute, cast(int)second));
  6778. auto fracSecStr = fracSecToISOString(cast(int)hnsecs);
  6779. if(_timezone is LocalTime())
  6780. return dateTime.toISOExtString() ~ fracSecToISOString(cast(int)hnsecs);
  6781. if(_timezone is UTC())
  6782. return dateTime.toISOExtString() ~ fracSecToISOString(cast(int)hnsecs) ~ "Z";
  6783. immutable utcOffset = cast(int)convert!("hnsecs", "minutes")(adjustedTime - stdTime);
  6784. return dateTime.toISOExtString() ~ fracSecToISOString(cast(int)hnsecs) ~ SimpleTimeZone.toISOString(utcOffset);
  6785. }
  6786. catch(Exception e)
  6787. assert(0, "format() threw.");
  6788. }
  6789. /++
  6790. $(RED Scheduled for deprecation in November 2011.
  6791. Please use toISOExtString instead.)
  6792. +/
  6793. alias toISOExtString toISOExtendedString;
  6794. unittest
  6795. {
  6796. version(testStdDateTime)
  6797. {
  6798. //Test A.D.
  6799. _assertPred!"=="(SysTime(DateTime.init, UTC()).toISOExtString(), "0001-01-01T00:00:00Z");
  6800. _assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1), UTC()).toISOExtString(), "0001-01-01T00:00:00.0000001Z");
  6801. _assertPred!"=="(SysTime(DateTime(9, 12, 4, 0, 0, 0)).toISOExtString(), "0009-12-04T00:00:00");
  6802. _assertPred!"=="(SysTime(DateTime(99, 12, 4, 5, 6, 12)).toISOExtString(), "0099-12-04T05:06:12");
  6803. _assertPred!"=="(SysTime(DateTime(999, 12, 4, 13, 44, 59)).toISOExtString(), "0999-12-04T13:44:59");
  6804. _assertPred!"=="(SysTime(DateTime(9999, 7, 4, 23, 59, 59)).toISOExtString(), "9999-07-04T23:59:59");
  6805. _assertPred!"=="(SysTime(DateTime(10000, 10, 20, 1, 1, 1)).toISOExtString(), "+10000-10-20T01:01:01");
  6806. _assertPred!"=="(SysTime(DateTime(9, 12, 4, 0, 0, 0), FracSec.from!"msecs"(42)).toISOExtString(), "0009-12-04T00:00:00.042");
  6807. _assertPred!"=="(SysTime(DateTime(99, 12, 4, 5, 6, 12), FracSec.from!"msecs"(100)).toISOExtString(), "0099-12-04T05:06:12.1");
  6808. _assertPred!"=="(SysTime(DateTime(999, 12, 4, 13, 44, 59), FracSec.from!"usecs"(45020)).toISOExtString(), "0999-12-04T13:44:59.04502");
  6809. _assertPred!"=="(SysTime(DateTime(9999, 7, 4, 23, 59, 59), FracSec.from!"hnsecs"(12)).toISOExtString(), "9999-07-04T23:59:59.0000012");
  6810. _assertPred!"=="(SysTime(DateTime(10000, 10, 20, 1, 1, 1), FracSec.from!"hnsecs"(507890)).toISOExtString(), "+10000-10-20T01:01:01.050789");
  6811. _assertPred!"=="(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
  6812. new SimpleTimeZone(-360)).toISOExtString(),
  6813. "2012-12-21T12:12:12-06:00");
  6814. _assertPred!"=="(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
  6815. new SimpleTimeZone(420)).toISOExtString(),
  6816. "2012-12-21T12:12:12+07:00");
  6817. //Test B.C.
  6818. _assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999), UTC()).toISOExtString(), "0000-12-31T23:59:59.9999999Z");
  6819. _assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1), UTC()).toISOExtString(), "0000-12-31T23:59:59.0000001Z");
  6820. _assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), UTC()).toISOExtString(), "0000-12-31T23:59:59Z");
  6821. _assertPred!"=="(SysTime(DateTime(0, 12, 4, 0, 12, 4)).toISOExtString(), "0000-12-04T00:12:04");
  6822. _assertPred!"=="(SysTime(DateTime(-9, 12, 4, 0, 0, 0)).toISOExtString(), "-0009-12-04T00:00:00");
  6823. _assertPred!"=="(SysTime(DateTime(-99, 12, 4, 5, 6, 12)).toISOExtString(), "-0099-12-04T05:06:12");
  6824. _assertPred!"=="(SysTime(DateTime(-999, 12, 4, 13, 44, 59)).toISOExtString(), "-0999-12-04T13:44:59");
  6825. _assertPred!"=="(SysTime(DateTime(-9999, 7, 4, 23, 59, 59)).toISOExtString(), "-9999-07-04T23:59:59");
  6826. _assertPred!"=="(SysTime(DateTime(-10000, 10, 20, 1, 1, 1)).toISOExtString(), "-10000-10-20T01:01:01");
  6827. _assertPred!"=="(SysTime(DateTime(0, 12, 4, 0, 0, 0), FracSec.from!"msecs"(7)).toISOExtString(), "0000-12-04T00:00:00.007");
  6828. _assertPred!"=="(SysTime(DateTime(-9, 12, 4, 0, 0, 0), FracSec.from!"msecs"(42)).toISOExtString(), "-0009-12-04T00:00:00.042");
  6829. _assertPred!"=="(SysTime(DateTime(-99, 12, 4, 5, 6, 12), FracSec.from!"msecs"(100)).toISOExtString(), "-0099-12-04T05:06:12.1");
  6830. _assertPred!"=="(SysTime(DateTime(-999, 12, 4, 13, 44, 59), FracSec.from!"usecs"(45020)).toISOExtString(), "-0999-12-04T13:44:59.04502");
  6831. _assertPred!"=="(SysTime(DateTime(-9999, 7, 4, 23, 59, 59), FracSec.from!"hnsecs"(12)).toISOExtString(), "-9999-07-04T23:59:59.0000012");
  6832. _assertPred!"=="(SysTime(DateTime(-10000, 10, 20, 1, 1, 1), FracSec.from!"hnsecs"(507890)).toISOExtString(), "-10000-10-20T01:01:01.050789");
  6833. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6834. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6835. static assert(__traits(compiles, cast(TimeOfDay)cst));
  6836. //static assert(__traits(compiles, cast(TimeOfDay)ist));
  6837. //Verify Examples.
  6838. assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toISOExtString() ==
  6839. "2010-07-04T07:06:12");
  6840. assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0),
  6841. FracSec.from!"msecs"(24)).toISOExtString() ==
  6842. "1998-12-25T02:15:00.024");
  6843. assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toISOExtString() ==
  6844. "0000-01-05T23:09:59");
  6845. assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2),
  6846. FracSec.from!"hnsecs"(520_920)).toISOExtString() ==
  6847. "-0004-01-05T00:00:02.052092");
  6848. }
  6849. }
  6850. /++
  6851. Converts this $(D SysTime) to a string with the format
  6852. YYYY-Mon-DD HH:MM:SS.FFFFFFFTZ (where F is fractional seconds and TZ
  6853. is the time zone).
  6854. Note that the number of digits in the fractional seconds varies with the
  6855. number of fractional seconds. It's a maximum of 7 (which would be
  6856. hnsecs), but only has as many as are necessary to hold the correct value
  6857. (so no trailing zeroes), and if there are no fractional seconds, then
  6858. there is no decimal point.
  6859. If this $(D SysTime)'s time zone is $(D LocalTime), then TZ is empty. If
  6860. its time zone is $(D UTC), then it is "Z". Otherwise, it is the offset
  6861. from UTC (e.g. +1:00 or -7:00). Note that the offset from UTC is
  6862. $(I not) enough to uniquely identify the time zone.
  6863. Time zone offsets will be in the form +HH:MM or -HH:MM.
  6864. Examples:
  6865. --------------------
  6866. assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toSimpleString() ==
  6867. "2010-Jul-04 07:06:12");
  6868. assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0),
  6869. FracSec.from!"msecs"(24)).toSimpleString() ==
  6870. "1998-Dec-25 02:15:00.024");
  6871. assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toSimpleString() ==
  6872. "0000-Jan-05 23:09:59");
  6873. assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2),
  6874. FracSec.from!"hnsecs"(520_920)).toSimpleString() ==
  6875. "-0004-Jan-05 00:00:02.052092");
  6876. --------------------
  6877. +/
  6878. string toSimpleString() const nothrow
  6879. {
  6880. try
  6881. {
  6882. immutable adjustedTime = adjTime;
  6883. long hnsecs = adjustedTime;
  6884. auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
  6885. if(hnsecs < 0)
  6886. {
  6887. hnsecs += convert!("hours", "hnsecs")(24);
  6888. --days;
  6889. }
  6890. auto hour = splitUnitsFromHNSecs!"hours"(hnsecs);
  6891. auto minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
  6892. auto second = splitUnitsFromHNSecs!"seconds"(hnsecs);
  6893. auto dateTime = DateTime(Date(cast(int)days), TimeOfDay(cast(int)hour, cast(int)minute, cast(int)second));
  6894. auto fracSecStr = fracSecToISOString(cast(int)hnsecs);
  6895. if(_timezone is LocalTime())
  6896. return dateTime.toSimpleString() ~ fracSecToISOString(cast(int)hnsecs);
  6897. if(_timezone is UTC())
  6898. return dateTime.toSimpleString() ~ fracSecToISOString(cast(int)hnsecs) ~ "Z";
  6899. immutable utcOffset = cast(int)convert!("hnsecs", "minutes")(adjustedTime - stdTime);
  6900. return dateTime.toSimpleString() ~ fracSecToISOString(cast(int)hnsecs) ~ SimpleTimeZone.toISOString(utcOffset);
  6901. }
  6902. catch(Exception e)
  6903. assert(0, "format() threw.");
  6904. }
  6905. unittest
  6906. {
  6907. version(testStdDateTime)
  6908. {
  6909. //Test A.D.
  6910. _assertPred!"=="(SysTime(DateTime.init, UTC()).toString(), "0001-Jan-01 00:00:00Z");
  6911. _assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1), UTC()).toString(), "0001-Jan-01 00:00:00.0000001Z");
  6912. _assertPred!"=="(SysTime(DateTime(9, 12, 4, 0, 0, 0)).toSimpleString(), "0009-Dec-04 00:00:00");
  6913. _assertPred!"=="(SysTime(DateTime(99, 12, 4, 5, 6, 12)).toSimpleString(), "0099-Dec-04 05:06:12");
  6914. _assertPred!"=="(SysTime(DateTime(999, 12, 4, 13, 44, 59)).toSimpleString(), "0999-Dec-04 13:44:59");
  6915. _assertPred!"=="(SysTime(DateTime(9999, 7, 4, 23, 59, 59)).toSimpleString(), "9999-Jul-04 23:59:59");
  6916. _assertPred!"=="(SysTime(DateTime(10000, 10, 20, 1, 1, 1)).toSimpleString(), "+10000-Oct-20 01:01:01");
  6917. _assertPred!"=="(SysTime(DateTime(9, 12, 4, 0, 0, 0), FracSec.from!"msecs"(42)).toSimpleString(), "0009-Dec-04 00:00:00.042");
  6918. _assertPred!"=="(SysTime(DateTime(99, 12, 4, 5, 6, 12), FracSec.from!"msecs"(100)).toSimpleString(), "0099-Dec-04 05:06:12.1");
  6919. _assertPred!"=="(SysTime(DateTime(999, 12, 4, 13, 44, 59), FracSec.from!"usecs"(45020)).toSimpleString(), "0999-Dec-04 13:44:59.04502");
  6920. _assertPred!"=="(SysTime(DateTime(9999, 7, 4, 23, 59, 59), FracSec.from!"hnsecs"(12)).toSimpleString(), "9999-Jul-04 23:59:59.0000012");
  6921. _assertPred!"=="(SysTime(DateTime(10000, 10, 20, 1, 1, 1), FracSec.from!"hnsecs"(507890)).toSimpleString(), "+10000-Oct-20 01:01:01.050789");
  6922. _assertPred!"=="(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
  6923. new SimpleTimeZone(-360)).toSimpleString(),
  6924. "2012-Dec-21 12:12:12-06:00");
  6925. _assertPred!"=="(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
  6926. new SimpleTimeZone(420)).toSimpleString(),
  6927. "2012-Dec-21 12:12:12+07:00");
  6928. //Test B.C.
  6929. _assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999), UTC()).toSimpleString(), "0000-Dec-31 23:59:59.9999999Z");
  6930. _assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1), UTC()).toSimpleString(), "0000-Dec-31 23:59:59.0000001Z");
  6931. _assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), UTC()).toSimpleString(), "0000-Dec-31 23:59:59Z");
  6932. _assertPred!"=="(SysTime(DateTime(0, 12, 4, 0, 12, 4)).toSimpleString(), "0000-Dec-04 00:12:04");
  6933. _assertPred!"=="(SysTime(DateTime(-9, 12, 4, 0, 0, 0)).toSimpleString(), "-0009-Dec-04 00:00:00");
  6934. _assertPred!"=="(SysTime(DateTime(-99, 12, 4, 5, 6, 12)).toSimpleString(), "-0099-Dec-04 05:06:12");
  6935. _assertPred!"=="(SysTime(DateTime(-999, 12, 4, 13, 44, 59)).toSimpleString(), "-0999-Dec-04 13:44:59");
  6936. _assertPred!"=="(SysTime(DateTime(-9999, 7, 4, 23, 59, 59)).toSimpleString(), "-9999-Jul-04 23:59:59");
  6937. _assertPred!"=="(SysTime(DateTime(-10000, 10, 20, 1, 1, 1)).toSimpleString(), "-10000-Oct-20 01:01:01");
  6938. _assertPred!"=="(SysTime(DateTime(0, 12, 4, 0, 0, 0), FracSec.from!"msecs"(7)).toSimpleString(), "0000-Dec-04 00:00:00.007");
  6939. _assertPred!"=="(SysTime(DateTime(-9, 12, 4, 0, 0, 0), FracSec.from!"msecs"(42)).toSimpleString(), "-0009-Dec-04 00:00:00.042");
  6940. _assertPred!"=="(SysTime(DateTime(-99, 12, 4, 5, 6, 12), FracSec.from!"msecs"(100)).toSimpleString(), "-0099-Dec-04 05:06:12.1");
  6941. _assertPred!"=="(SysTime(DateTime(-999, 12, 4, 13, 44, 59), FracSec.from!"usecs"(45020)).toSimpleString(), "-0999-Dec-04 13:44:59.04502");
  6942. _assertPred!"=="(SysTime(DateTime(-9999, 7, 4, 23, 59, 59), FracSec.from!"hnsecs"(12)).toSimpleString(), "-9999-Jul-04 23:59:59.0000012");
  6943. _assertPred!"=="(SysTime(DateTime(-10000, 10, 20, 1, 1, 1), FracSec.from!"hnsecs"(507890)).toSimpleString(), "-10000-Oct-20 01:01:01.050789");
  6944. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6945. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6946. static assert(__traits(compiles, cast(TimeOfDay)cst));
  6947. //static assert(__traits(compiles, cast(TimeOfDay)ist));
  6948. //Verify Examples.
  6949. assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toSimpleString() ==
  6950. "2010-Jul-04 07:06:12");
  6951. assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0),
  6952. FracSec.from!"msecs"(24)).toSimpleString() ==
  6953. "1998-Dec-25 02:15:00.024");
  6954. assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toSimpleString() ==
  6955. "0000-Jan-05 23:09:59");
  6956. assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2),
  6957. FracSec.from!"hnsecs"(520_920)).toSimpleString() ==
  6958. "-0004-Jan-05 00:00:02.052092");
  6959. }
  6960. }
  6961. /+
  6962. Converts this $(D SysTime) to a string.
  6963. +/
  6964. //Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
  6965. //have versions of toString() with extra modifiers, so we define one version
  6966. //with modifiers and one without.
  6967. string toString()
  6968. {
  6969. return toSimpleString();
  6970. }
  6971. /++
  6972. Converts this $(D SysTime) to a string.
  6973. +/
  6974. //Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
  6975. //have versions of toString() with extra modifiers, so we define one version
  6976. //with modifiers and one without.
  6977. string toString() const nothrow
  6978. {
  6979. return toSimpleString();
  6980. }
  6981. unittest
  6982. {
  6983. version(testStdDateTime)
  6984. {
  6985. auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6986. const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6987. //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
  6988. static assert(__traits(compiles, st.toString()));
  6989. static assert(__traits(compiles, cst.toString()));
  6990. //static assert(__traits(compiles, ist.toString()));
  6991. }
  6992. }
  6993. /++
  6994. Creates a $(D SysTime) from a string with the format
  6995. YYYYMMDDTHHMMSS.FFFFFFFTZ (where F is fractional seconds is the time
  6996. zone). Whitespace is stripped from the given string.
  6997. The exact format is exactly as described in $(D toISOString) except that
  6998. trailing zeroes are permitted - including having fractional seconds with
  6999. all zeroes. However, a decimal point with nothing following it is
  7000. invalid.
  7001. If there is no time zone in the string, then $(D LocalTime) is used. If
  7002. the time zone is "Z", then $(D UTC) is used. Otherwise, a
  7003. $(D SimpleTimeZone) which corresponds to the given offset from UTC is
  7004. used. If you wish the returned $(D SysTime) to be a particular time
  7005. zone, then pass in that time zone and the $(D SysTime) to be returned
  7006. will be converted to that time zone (though it will still be read in as
  7007. whatever time zone is in its string).
  7008. The accepted formats for time zone offsets
  7009. are +H, -H, +HH, -HH, +H:MM, -H:MM, +HH:MM, and -HH:MM.
  7010. Params:
  7011. isoString = A string formatted in the ISO format for dates and times.
  7012. tz = The time zone to convert the given time to (no
  7013. conversion occurs if null).
  7014. Throws:
  7015. $(D DateTimeException) if the given string is not in the ISO format
  7016. or if the resulting $(D SysTime) would not be valid.
  7017. Examples:
  7018. --------------------
  7019. assert(SysTime.fromISOString("20100704T070612") ==
  7020. SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
  7021. assert(SysTime.fromISOString("19981225T021500.007") ==
  7022. SysTime(DateTime(1998, 12, 25, 2, 15, 0), FracSec.from!"msecs"(7)));
  7023. assert(SysTime.fromISOString("00000105T230959.00002") ==
  7024. SysTime(DateTime(0, 1, 5, 23, 9, 59), FracSec.from!"usecs"(20)));
  7025. assert(SysTime.fromISOString("-00040105T000002") ==
  7026. SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
  7027. assert(SysTime.fromISOString(" 20100704T070612 ") ==
  7028. SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
  7029. assert(SysTime.fromISOString("20100704T070612Z") ==
  7030. SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
  7031. assert(SysTime.fromISOString("20100704T070612-8:00") ==
  7032. SysTime(DateTime(2010, 7, 4, 7, 6, 12), new SimpleTimeZone(-480)));
  7033. assert(SysTime.fromISOString("20100704T070612+8:00") ==
  7034. SysTime(DateTime(2010, 7, 3, 7, 6, 12), new SimpleTimeZone(480)));
  7035. --------------------
  7036. +/
  7037. static SysTime fromISOString(S)(in S isoString, immutable TimeZone tz = null)
  7038. if(isSomeString!S)
  7039. {
  7040. auto dstr = to!dstring(strip(isoString));
  7041. immutable skipFirst = dstr.startsWith("+", "-") != 0;
  7042. auto found = (skipFirst ? dstr[1..$] : dstr).find(".", "Z", "+", "-");
  7043. auto dateTimeStr = dstr[0 .. $ - found[0].length];
  7044. dstring fracSecStr;
  7045. dstring zoneStr;
  7046. if(found[1] != 0)
  7047. {
  7048. if(found[1] == 1)
  7049. {
  7050. auto foundTZ = found[0].find("Z", "+", "-");
  7051. if(foundTZ[1] != 0)
  7052. {
  7053. fracSecStr = found[0][0 .. $ - foundTZ[0].length];
  7054. zoneStr = foundTZ[0];
  7055. }
  7056. else
  7057. fracSecStr = found[0];
  7058. }
  7059. else
  7060. zoneStr = found[0];
  7061. }
  7062. try
  7063. {
  7064. auto dateTime = DateTime.fromISOString(dateTimeStr);
  7065. auto fracSec = fracSecFromISOString(fracSecStr);
  7066. Rebindable!(immutable TimeZone) parsedZone;
  7067. if(zoneStr.empty)
  7068. parsedZone = LocalTime();
  7069. else if(zoneStr == "Z")
  7070. parsedZone = UTC();
  7071. else
  7072. parsedZone = SimpleTimeZone.fromISOString(zoneStr);
  7073. auto retval = SysTime(dateTime, fracSec, parsedZone);
  7074. if(tz !is null)
  7075. retval.timezone = tz;
  7076. return retval;
  7077. }
  7078. catch(DateTimeException dte)
  7079. throw new DateTimeException(format("Invalid ISO String: %s", isoString));
  7080. }
  7081. unittest
  7082. {
  7083. version(testStdDateTime)
  7084. {
  7085. assertThrown!DateTimeException(SysTime.fromISOString(""));
  7086. assertThrown!DateTimeException(SysTime.fromISOString("20100704000000"));
  7087. assertThrown!DateTimeException(SysTime.fromISOString("20100704 000000"));
  7088. assertThrown!DateTimeException(SysTime.fromISOString("20100704t000000"));
  7089. assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000."));
  7090. assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000.A"));
  7091. assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000.Z"));
  7092. assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000.00000000"));
  7093. assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000.00000000"));
  7094. assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000+"));
  7095. assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000-"));
  7096. assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000:"));
  7097. assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000-:"));
  7098. assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000+:"));
  7099. assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000-1:"));
  7100. assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000+1:"));
  7101. assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000+1:0"));
  7102. assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000-24.00"));
  7103. assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000+24.00"));
  7104. assertThrown!DateTimeException(SysTime.fromISOString("2010-07-0400:00:00"));
  7105. assertThrown!DateTimeException(SysTime.fromISOString("2010-07-04 00:00:00"));
  7106. assertThrown!DateTimeException(SysTime.fromISOString("2010-07-04t00:00:00"));
  7107. assertThrown!DateTimeException(SysTime.fromISOString("2010-07-04T00:00:00."));
  7108. assertThrown!DateTimeException(SysTime.fromISOString("2010-Jul-0400:00:00"));
  7109. assertThrown!DateTimeException(SysTime.fromISOString("2010-Jul-04 00:00:00"));
  7110. assertThrown!DateTimeException(SysTime.fromISOString("2010-Jul-04t00:00:00"));
  7111. assertThrown!DateTimeException(SysTime.fromISOString("2010-Jul-04T00:00:00"));
  7112. assertThrown!DateTimeException(SysTime.fromISOString("2010-Jul-04 00:00:00."));
  7113. assertThrown!DateTimeException(SysTime.fromISOString("2010-12-22T172201"));
  7114. assertThrown!DateTimeException(SysTime.fromISOString("2010-Dec-22 17:22:01"));
  7115. _assertPred!"=="(SysTime.fromISOString("20101222T172201"), SysTime(DateTime(2010, 12, 22, 17, 22, 01)));
  7116. _assertPred!"=="(SysTime.fromISOString("19990706T123033"), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
  7117. _assertPred!"=="(SysTime.fromISOString("-19990706T123033"), SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
  7118. _assertPred!"=="(SysTime.fromISOString("+019990706T123033"), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
  7119. _assertPred!"=="(SysTime.fromISOString("19990706T123033 "), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
  7120. _assertPred!"=="(SysTime.fromISOString(" 19990706T123033"), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
  7121. _assertPred!"=="(SysTime.fromISOString(" 19990706T123033 "), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
  7122. _assertPred!"=="(SysTime.fromISOString("19070707T121212.0"), SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
  7123. _assertPred!"=="(SysTime.fromISOString("19070707T121212.0000000"), SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
  7124. _assertPred!"=="(SysTime.fromISOString("19070707T121212.0000001"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"hnsecs"(1)));
  7125. _assertPred!"=="(SysTime.fromISOString("19070707T121212.000001"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"usecs"(1)));
  7126. _assertPred!"=="(SysTime.fromISOString("19070707T121212.0000010"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"usecs"(1)));
  7127. _assertPred!"=="(SysTime.fromISOString("19070707T121212.001"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"msecs"(1)));
  7128. _assertPred!"=="(SysTime.fromISOString("19070707T121212.0010000"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"msecs"(1)));
  7129. _assertPred!"=="(SysTime.fromISOString("20101222T172201Z"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), UTC()));
  7130. _assertPred!"=="(SysTime.fromISOString("20101222T172201-1:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(-60)));
  7131. _assertPred!"=="(SysTime.fromISOString("20101222T172201-1"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(-60)));
  7132. _assertPred!"=="(SysTime.fromISOString("20101222T172201-1:30"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(-90)));
  7133. _assertPred!"=="(SysTime.fromISOString("20101222T172201-8:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(-480)));
  7134. _assertPred!"=="(SysTime.fromISOString("20101222T172201+1:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(60)));
  7135. _assertPred!"=="(SysTime.fromISOString("20101222T172201+1"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(60)));
  7136. _assertPred!"=="(SysTime.fromISOString("20101222T172201+1:30"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(90)));
  7137. _assertPred!"=="(SysTime.fromISOString("20101222T172201+8:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(480)));
  7138. _assertPred!"=="(SysTime.fromISOString("20101103T065106.57159Z"), SysTime(DateTime(2010, 11, 3, 6, 51, 6), FracSec.from!"hnsecs"(5715900), UTC()));
  7139. _assertPred!"=="(SysTime.fromISOString("20101222T172201.23412Z"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(2_341_200), UTC()));
  7140. _assertPred!"=="(SysTime.fromISOString("20101222T172201.23112-1:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(2_311_200), new SimpleTimeZone(-60)));
  7141. _assertPred!"=="(SysTime.fromISOString("20101222T172201.45-1"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(4_500_000), new SimpleTimeZone(-60)));
  7142. _assertPred!"=="(SysTime.fromISOString("20101222T172201.1-1:30"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(1_000_000), new SimpleTimeZone(-90)));
  7143. _assertPred!"=="(SysTime.fromISOString("20101222T172201.55-8:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(5_500_000), new SimpleTimeZone(-480)));
  7144. _assertPred!"=="(SysTime.fromISOString("20101222T172201.1234567+1:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(1_234_567), new SimpleTimeZone(60)));
  7145. _assertPred!"=="(SysTime.fromISOString("20101222T172201.0+1"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(0), new SimpleTimeZone(60)));
  7146. _assertPred!"=="(SysTime.fromISOString("20101222T172201.0000000+1:30"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(0), new SimpleTimeZone(90)));
  7147. _assertPred!"=="(SysTime.fromISOString("20101222T172201.45+8:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(4_500_000), new SimpleTimeZone(480)));
  7148. //Verify Examples.
  7149. assert(SysTime.fromISOString("20100704T070612") == SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
  7150. assert(SysTime.fromISOString("19981225T021500.007") == SysTime(DateTime(1998, 12, 25, 2, 15, 0), FracSec.from!"msecs"(7)));
  7151. assert(SysTime.fromISOString("00000105T230959.00002") == SysTime(DateTime(0, 1, 5, 23, 9, 59), FracSec.from!"usecs"(20)));
  7152. assert(SysTime.fromISOString("-00040105T000002") == SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
  7153. assert(SysTime.fromISOString(" 20100704T070612 ") == SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
  7154. assert(SysTime.fromISOString("20100704T070612Z") == SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
  7155. assert(SysTime.fromISOString("20100704T070612-8:00") == SysTime(DateTime(2010, 7, 4, 7, 6, 12), new SimpleTimeZone(-480)));
  7156. assert(SysTime.fromISOString("20100704T070612+8:00") == SysTime(DateTime(2010, 7, 4, 7, 6, 12), new SimpleTimeZone(480)));
  7157. }
  7158. }
  7159. /++
  7160. Creates a $(D SysTime) from a string with the format
  7161. YYYY-MM-DDTHH:MM:SS.FFFFFFFTZ (where F is fractional seconds is the
  7162. time zone). Whitespace is stripped from the given string.
  7163. The exact format is exactly as described in $(D toISOExtString)
  7164. except that trailing zeroes are permitted - including having fractional
  7165. seconds with all zeroes. However, a decimal point with nothing following
  7166. it is invalid.
  7167. If there is no time zone in the string, then $(D LocalTime) is used. If
  7168. the time zone is "Z", then $(D UTC) is used. Otherwise, a
  7169. $(D SimpleTimeZone) which corresponds to the given offset from UTC is
  7170. used. If you wish the returned $(D SysTime) to be a particular time
  7171. zone, then pass in that time zone and the $(D SysTime) to be returned
  7172. will be converted to that time zone (though it will still be read in as
  7173. whatever time zone is in its string).
  7174. The accepted formats for time zone offsets
  7175. are +H, -H, +HH, -HH, +H:MM, -H:MM, +HH:MM, and -HH:MM.
  7176. Params:
  7177. isoString = A string formatted in the ISO Extended format for dates
  7178. and times.
  7179. tz = The time zone to convert the given time to (no
  7180. conversion occurs if null).
  7181. Throws:
  7182. $(D DateTimeException) if the given string is not in the ISO format
  7183. or if the resulting $(D SysTime) would not be valid.
  7184. Examples:
  7185. --------------------
  7186. assert(SysTime.fromISOExtString("2010-07-04T07:06:12") ==
  7187. SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
  7188. assert(SysTime.fromISOExtString("1998-12-25T02:15:00.007") ==
  7189. SysTime(DateTime(1998, 12, 25, 2, 15, 0), FracSec.from!"msecs"(7)));
  7190. assert(SysTime.fromISOExtString("0000-01-05T23:09:59.00002") ==
  7191. SysTime(DateTime(0, 1, 5, 23, 9, 59), FracSec.from!"usecs"(20)));
  7192. assert(SysTime.fromISOExtString("-0004-01-05T00:00:02") ==
  7193. SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
  7194. assert(SysTime.fromISOExtString(" 2010-07-04T07:06:12 ") ==
  7195. SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
  7196. assert(SysTime.fromISOExtString("2010-07-04T07:06:12Z") ==
  7197. SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
  7198. assert(SysTime.fromISOExtString("2010-07-04T07:06:12-8:00") ==
  7199. SysTime(DateTime(2010, 7, 4, 7, 6, 12), new SimpleTimeZone(-480)));
  7200. assert(SysTime.fromISOExtString("2010-07-04T07:06:12+8:00") ==
  7201. SysTime(DateTime(2010, 7, 4, 7, 6, 12), new SimpleTimeZone(480)));
  7202. --------------------
  7203. +/
  7204. static SysTime fromISOExtString(S)(in S isoExtString, immutable TimeZone tz = null)
  7205. if(isSomeString!(S))
  7206. {
  7207. auto dstr = to!dstring(strip(isoExtString));
  7208. auto tIndex = dstr.stds_indexOf("T");
  7209. enforce(tIndex != -1, new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
  7210. auto found = dstr[tIndex + 1 .. $].find(".", "Z", "+", "-");
  7211. auto dateTimeStr = dstr[0 .. $ - found[0].length];
  7212. dstring fracSecStr;
  7213. dstring zoneStr;
  7214. if(found[1] != 0)
  7215. {
  7216. if(found[1] == 1)
  7217. {
  7218. auto foundTZ = found[0].find("Z", "+", "-");
  7219. if(foundTZ[1] != 0)
  7220. {
  7221. fracSecStr = found[0][0 .. $ - foundTZ[0].length];
  7222. zoneStr = foundTZ[0];
  7223. }
  7224. else
  7225. fracSecStr = found[0];
  7226. }
  7227. else
  7228. zoneStr = found[0];
  7229. }
  7230. try
  7231. {
  7232. auto dateTime = DateTime.fromISOExtString(dateTimeStr);
  7233. auto fracSec = fracSecFromISOString(fracSecStr);
  7234. Rebindable!(immutable TimeZone) parsedZone;
  7235. if(zoneStr.empty)
  7236. parsedZone = LocalTime();
  7237. else if(zoneStr == "Z")
  7238. parsedZone = UTC();
  7239. else
  7240. parsedZone = SimpleTimeZone.fromISOString(zoneStr);
  7241. auto retval = SysTime(dateTime, fracSec, parsedZone);
  7242. if(tz !is null)
  7243. retval.timezone = tz;
  7244. return retval;
  7245. }
  7246. catch(DateTimeException dte)
  7247. throw new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString));
  7248. }
  7249. /++
  7250. $(RED Scheduled for deprecation in November 2011.
  7251. Please use fromISOExtString instead.)
  7252. +/
  7253. static SysTime fromISOExtendedString(S)(in S isoExtString, immutable TimeZone tz = null)
  7254. if(isSomeString!(S))
  7255. {
  7256. pragma(msg, softDeprec!("2.053", "November 2011", "fromISOExtendedString", "fromISOExtString"));
  7257. return fromISOExtString!string(isoExtString, tz);
  7258. }
  7259. unittest
  7260. {
  7261. version(testStdDateTime)
  7262. {
  7263. assertThrown!DateTimeException(SysTime.fromISOExtString(""));
  7264. assertThrown!DateTimeException(SysTime.fromISOExtString("20100704000000"));
  7265. assertThrown!DateTimeException(SysTime.fromISOExtString("20100704 000000"));
  7266. assertThrown!DateTimeException(SysTime.fromISOExtString("20100704t000000"));
  7267. assertThrown!DateTimeException(SysTime.fromISOExtString("20100704T000000."));
  7268. assertThrown!DateTimeException(SysTime.fromISOExtString("20100704T000000.0"));
  7269. assertThrown!DateTimeException(SysTime.fromISOExtString("2010-07:0400:00:00"));
  7270. assertThrown!DateTimeException(SysTime.fromISOExtString("2010-07-04 00:00:00"));
  7271. assertThrown!DateTimeException(SysTime.fromISOExtString("2010-07-04 00:00:00"));
  7272. assertThrown!DateTimeException(SysTime.fromISOExtString("2010-07-04t00:00:00"));
  7273. assertThrown!DateTimeException(SysTime.fromISOExtString("2010-07-04T00:00:00."));
  7274. assertThrown!DateTimeException(SysTime.fromISOExtString("2010-07-04T00:00:00.A"));
  7275. assertThrown!DateTimeException(SysTime.fromISOExtString("2010-07-04T00:00:00.Z"));
  7276. assertThrown!DateTimeException(SysTime.fromISOExtString("2010-07-04T00:00:00.00000000"));
  7277. assertThrown!DateTimeException(SysTime.fromISOExtString("2010-07-04T00:00:00.00000000"));
  7278. assertThrown!DateTimeException(SysTime.fromISOExtString("2010-07-04T00:00:00+"));
  7279. assertThrown!DateTimeException(SysTime.fromISOExtString("2010-07-04T00:00:00-"));
  7280. assertThrown!DateTimeException(SysTime.fromISOExtString("2010-07-04T00:00:00:"));
  7281. assertThrown!DateTimeException(SysTime.fromISOExtString("2010-07-04T00:00:00-:"));
  7282. assertThrown!DateTimeException(SysTime.fromISOExtString("2010-07-04T00:00:00+:"));
  7283. assertThrown!DateTimeException(SysTime.fromISOExtString("2010-07-04T00:00:00-1:"));
  7284. assertThrown!DateTimeException(SysTime.fromISOExtString("2010-07-04T00:00:00+1:"));
  7285. assertThrown!DateTimeException(SysTime.fromISOExtString("2010-07-04T00:00:00+1:0"));
  7286. assertThrown!DateTimeException(SysTime.fromISOExtString("2010-07-04T00:00:00-24.00"));
  7287. assertThrown!DateTimeException(SysTime.fromISOExtString("2010-07-04T00:00:00+24.00"));
  7288. assertThrown!DateTimeException(SysTime.fromISOExtString("2010-Jul-0400:00:00"));
  7289. assertThrown!DateTimeException(SysTime.fromISOExtString("2010-Jul-04t00:00:00"));
  7290. assertThrown!DateTimeException(SysTime.fromISOExtString("2010-Jul-04 00:00:00."));
  7291. assertThrown!DateTimeException(SysTime.fromISOExtString("2010-Jul-04 00:00:00.0"));
  7292. assertThrown!DateTimeException(SysTime.fromISOExtString("20101222T172201"));
  7293. assertThrown!DateTimeException(SysTime.fromISOExtString("2010-Dec-22 17:22:01"));
  7294. _assertPred!"=="(SysTime.fromISOExtString("2010-12-22T17:22:01"), SysTime(DateTime(2010, 12, 22, 17, 22, 01)));
  7295. _assertPred!"=="(SysTime.fromISOExtString("1999-07-06T12:30:33"), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
  7296. _assertPred!"=="(SysTime.fromISOExtString("-1999-07-06T12:30:33"), SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
  7297. _assertPred!"=="(SysTime.fromISOExtString("+01999-07-06T12:30:33"), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
  7298. _assertPred!"=="(SysTime.fromISOExtString("1999-07-06T12:30:33 "), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
  7299. _assertPred!"=="(SysTime.fromISOExtString(" 1999-07-06T12:30:33"), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
  7300. _assertPred!"=="(SysTime.fromISOExtString(" 1999-07-06T12:30:33 "), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
  7301. _assertPred!"=="(SysTime.fromISOExtString("1907-07-07T12:12:12.0"), SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
  7302. _assertPred!"=="(SysTime.fromISOExtString("1907-07-07T12:12:12.0000000"), SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
  7303. _assertPred!"=="(SysTime.fromISOExtString("1907-07-07T12:12:12.0000001"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"hnsecs"(1)));
  7304. _assertPred!"=="(SysTime.fromISOExtString("1907-07-07T12:12:12.000001"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"usecs"(1)));
  7305. _assertPred!"=="(SysTime.fromISOExtString("1907-07-07T12:12:12.0000010"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"usecs"(1)));
  7306. _assertPred!"=="(SysTime.fromISOExtString("1907-07-07T12:12:12.001"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"msecs"(1)));
  7307. _assertPred!"=="(SysTime.fromISOExtString("1907-07-07T12:12:12.0010000"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"msecs"(1)));
  7308. _assertPred!"=="(SysTime.fromISOExtString("2010-12-22T17:22:01Z"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), UTC()));
  7309. _assertPred!"=="(SysTime.fromISOExtString("2010-12-22T17:22:01-1:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(-60)));
  7310. _assertPred!"=="(SysTime.fromISOExtString("2010-12-22T17:22:01-1"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(-60)));
  7311. _assertPred!"=="(SysTime.fromISOExtString("2010-12-22T17:22:01-1:30"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(-90)));
  7312. _assertPred!"=="(SysTime.fromISOExtString("2010-12-22T17:22:01-8:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(-480)));
  7313. _assertPred!"=="(SysTime.fromISOExtString("2010-12-22T17:22:01+1:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(60)));
  7314. _assertPred!"=="(SysTime.fromISOExtString("2010-12-22T17:22:01+1"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(60)));
  7315. _assertPred!"=="(SysTime.fromISOExtString("2010-12-22T17:22:01+1:30"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(90)));
  7316. _assertPred!"=="(SysTime.fromISOExtString("2010-12-22T17:22:01+8:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(480)));
  7317. _assertPred!"=="(SysTime.fromISOExtString("2010-11-03T06:51:06.57159Z"), SysTime(DateTime(2010, 11, 3, 6, 51, 6), FracSec.from!"hnsecs"(5715900), UTC()));
  7318. _assertPred!"=="(SysTime.fromISOExtString("2010-12-22T17:22:01.23412Z"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(2_341_200), UTC()));
  7319. _assertPred!"=="(SysTime.fromISOExtString("2010-12-22T17:22:01.23112-1:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(2_311_200), new SimpleTimeZone(-60)));
  7320. _assertPred!"=="(SysTime.fromISOExtString("2010-12-22T17:22:01.45-1"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(4_500_000), new SimpleTimeZone(-60)));
  7321. _assertPred!"=="(SysTime.fromISOExtString("2010-12-22T17:22:01.1-1:30"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(1_000_000), new SimpleTimeZone(-90)));
  7322. _assertPred!"=="(SysTime.fromISOExtString("2010-12-22T17:22:01.55-8:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(5_500_000), new SimpleTimeZone(-480)));
  7323. _assertPred!"=="(SysTime.fromISOExtString("2010-12-22T17:22:01.1234567+1:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(1_234_567), new SimpleTimeZone(60)));
  7324. _assertPred!"=="(SysTime.fromISOExtString("2010-12-22T17:22:01.0+1"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(0), new SimpleTimeZone(60)));
  7325. _assertPred!"=="(SysTime.fromISOExtString("2010-12-22T17:22:01.0000000+1:30"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(0), new SimpleTimeZone(90)));
  7326. _assertPred!"=="(SysTime.fromISOExtString("2010-12-22T17:22:01.45+8:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(4_500_000), new SimpleTimeZone(480)));
  7327. //Verify Examples.
  7328. assert(SysTime.fromISOExtString("2010-07-04T07:06:12") == SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
  7329. assert(SysTime.fromISOExtString("1998-12-25T02:15:00.007") == SysTime(DateTime(1998, 12, 25, 2, 15, 0), FracSec.from!"msecs"(7)));
  7330. assert(SysTime.fromISOExtString("0000-01-05T23:09:59.00002") == SysTime(DateTime(0, 1, 5, 23, 9, 59), FracSec.from!"usecs"(20)));
  7331. assert(SysTime.fromISOExtString("-0004-01-05T00:00:02") == SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
  7332. assert(SysTime.fromISOExtString(" 2010-07-04T07:06:12 ") == SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
  7333. assert(SysTime.fromISOExtString("2010-07-04T07:06:12Z") == SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
  7334. assert(SysTime.fromISOExtString("2010-07-04T07:06:12-8:00") == SysTime(DateTime(2010, 7, 4, 7, 6, 12), new SimpleTimeZone(-480)));
  7335. assert(SysTime.fromISOExtString("2010-07-04T07:06:12+8:00") == SysTime(DateTime(2010, 7, 4, 7, 6, 12), new SimpleTimeZone(480)));
  7336. }
  7337. }
  7338. /++
  7339. Creates a $(D SysTime) from a string with the format
  7340. YYYY-MM-DD HH:MM:SS.FFFFFFFTZ (where F is fractional seconds is the
  7341. time zone). Whitespace is stripped from the given string.
  7342. The exact format is exactly as described in $(D toSimpleString) except
  7343. that trailing zeroes are permitted - including having fractional seconds
  7344. with all zeroes. However, a decimal point with nothing following it is
  7345. invalid.
  7346. If there is no time zone in the string, then $(D LocalTime) is used. If
  7347. the time zone is "Z", then $(D UTC) is used. Otherwise, a
  7348. $(D SimpleTimeZone) which corresponds to the given offset from UTC is
  7349. used. If you wish the returned $(D SysTime) to be a particular time
  7350. zone, then pass in that time zone and the $(D SysTime) to be returned
  7351. will be converted to that time zone (though it will still be read in as
  7352. whatever time zone is in its string).
  7353. The accepted formats for time zone offsets
  7354. are +H, -H, +HH, -HH, +H:MM, -H:MM, +HH:MM, and -HH:MM.
  7355. Params:
  7356. simpleString = A string formatted in the way that
  7357. $(D toSimpleString) formats dates and times.
  7358. tz = The time zone to convert the given time to (no
  7359. conversion occurs if null).
  7360. Throws:
  7361. $(D DateTimeException) if the given string is not in the ISO format
  7362. or if the resulting $(D SysTime) would not be valid.
  7363. Examples:
  7364. --------------------
  7365. assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12") ==
  7366. SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
  7367. assert(SysTime.fromSimpleString("1998-Dec-25 02:15:00.007") ==
  7368. SysTime(DateTime(1998, 12, 25, 2, 15, 0), FracSec.from!"msecs"(7)));
  7369. assert(SysTime.fromSimpleString("0000-Jan-05 23:09:59.00002") ==
  7370. SysTime(DateTime(0, 1, 5, 23, 9, 59), FracSec.from!"usecs"(20)));
  7371. assert(SysTime.fromSimpleString("-0004-Jan-05 00:00:02") ==
  7372. SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
  7373. assert(SysTime.fromSimpleString(" 2010-Jul-04 07:06:12 ") ==
  7374. SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
  7375. assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12Z") ==
  7376. SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
  7377. assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12-8:00") ==
  7378. SysTime(DateTime(2010, 7, 4, 7, 6, 12), new SimpleTimeZone(-480)));
  7379. assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12+8:00") ==
  7380. SysTime(DateTime(2010, 7, 4, 7, 6, 12), new SimpleTimeZone(480)));
  7381. --------------------
  7382. +/
  7383. static SysTime fromSimpleString(S)(in S simpleString, immutable TimeZone tz = null)
  7384. if(isSomeString!(S))
  7385. {
  7386. auto dstr = to!dstring(strip(simpleString));
  7387. auto spaceIndex = dstr.stds_indexOf(" ");
  7388. enforce(spaceIndex != -1, new DateTimeException(format("Invalid Simple String: %s", simpleString)));
  7389. auto found = dstr[spaceIndex + 1 .. $].find(".", "Z", "+", "-");
  7390. auto dateTimeStr = dstr[0 .. $ - found[0].length];
  7391. dstring fracSecStr;
  7392. dstring zoneStr;
  7393. if(found[1] != 0)
  7394. {
  7395. if(found[1] == 1)
  7396. {
  7397. auto foundTZ = found[0].find("Z", "+", "-");
  7398. if(foundTZ[1] != 0)
  7399. {
  7400. fracSecStr = found[0][0 .. $ - foundTZ[0].length];
  7401. zoneStr = foundTZ[0];
  7402. }
  7403. else
  7404. fracSecStr = found[0];
  7405. }
  7406. else
  7407. zoneStr = found[0];
  7408. }
  7409. try
  7410. {
  7411. auto dateTime = DateTime.fromSimpleString(dateTimeStr);
  7412. auto fracSec = fracSecFromISOString(fracSecStr);
  7413. Rebindable!(immutable TimeZone) parsedZone;
  7414. if(zoneStr.empty)
  7415. parsedZone = LocalTime();
  7416. else if(zoneStr == "Z")
  7417. parsedZone = UTC();
  7418. else
  7419. parsedZone = SimpleTimeZone.fromISOString(zoneStr);
  7420. auto retval = SysTime(dateTime, fracSec, parsedZone);
  7421. if(tz !is null)
  7422. retval.timezone = tz;
  7423. return retval;
  7424. }
  7425. catch(DateTimeException dte)
  7426. throw new DateTimeException(format("Invalid Simple String: %s", simpleString));
  7427. }
  7428. unittest
  7429. {
  7430. version(testStdDateTime)
  7431. {
  7432. assertThrown!DateTimeException(SysTime.fromSimpleString(""));
  7433. assertThrown!DateTimeException(SysTime.fromSimpleString("20100704000000"));
  7434. assertThrown!DateTimeException(SysTime.fromSimpleString("20100704 000000"));
  7435. assertThrown!DateTimeException(SysTime.fromSimpleString("20100704t000000"));
  7436. assertThrown!DateTimeException(SysTime.fromSimpleString("20100704T000000."));
  7437. assertThrown!DateTimeException(SysTime.fromSimpleString("20100704T000000.0"));
  7438. assertThrown!DateTimeException(SysTime.fromSimpleString("2010-07-0400:00:00"));
  7439. assertThrown!DateTimeException(SysTime.fromSimpleString("2010-07-04 00:00:00"));
  7440. assertThrown!DateTimeException(SysTime.fromSimpleString("2010-07-04t00:00:00"));
  7441. assertThrown!DateTimeException(SysTime.fromSimpleString("2010-07-04T00:00:00."));
  7442. assertThrown!DateTimeException(SysTime.fromSimpleString("2010-07-04T00:00:00.0"));
  7443. assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-0400:00:00"));
  7444. assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04t00:00:00"));
  7445. assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04T00:00:00"));
  7446. assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00."));
  7447. assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00.A"));
  7448. assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00.Z"));
  7449. assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00.00000000"));
  7450. assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00.00000000"));
  7451. assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00+"));
  7452. assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00-"));
  7453. assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00:"));
  7454. assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00-:"));
  7455. assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00+:"));
  7456. assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00-1:"));
  7457. assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00+1:"));
  7458. assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00+1:0"));
  7459. assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00-24.00"));
  7460. assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00+24.00"));
  7461. assertThrown!DateTimeException(SysTime.fromSimpleString("20101222T172201"));
  7462. assertThrown!DateTimeException(SysTime.fromSimpleString("2010-12-22T172201"));
  7463. _assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01"), SysTime(DateTime(2010, 12, 22, 17, 22, 01)));
  7464. _assertPred!"=="(SysTime.fromSimpleString("1999-Jul-06 12:30:33"), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
  7465. _assertPred!"=="(SysTime.fromSimpleString("-1999-Jul-06 12:30:33"), SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
  7466. _assertPred!"=="(SysTime.fromSimpleString("+01999-Jul-06 12:30:33"), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
  7467. _assertPred!"=="(SysTime.fromSimpleString("1999-Jul-06 12:30:33 "), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
  7468. _assertPred!"=="(SysTime.fromSimpleString(" 1999-Jul-06 12:30:33"), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
  7469. _assertPred!"=="(SysTime.fromSimpleString(" 1999-Jul-06 12:30:33 "), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
  7470. _assertPred!"=="(SysTime.fromSimpleString("1907-Jul-07 12:12:12.0"), SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
  7471. _assertPred!"=="(SysTime.fromSimpleString("1907-Jul-07 12:12:12.0000000"), SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
  7472. _assertPred!"=="(SysTime.fromSimpleString("1907-Jul-07 12:12:12.0000001"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"hnsecs"(1)));
  7473. _assertPred!"=="(SysTime.fromSimpleString("1907-Jul-07 12:12:12.000001"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"usecs"(1)));
  7474. _assertPred!"=="(SysTime.fromSimpleString("1907-Jul-07 12:12:12.0000010"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"usecs"(1)));
  7475. _assertPred!"=="(SysTime.fromSimpleString("1907-Jul-07 12:12:12.001"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"msecs"(1)));
  7476. _assertPred!"=="(SysTime.fromSimpleString("1907-Jul-07 12:12:12.0010000"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"msecs"(1)));
  7477. _assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01Z"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), UTC()));
  7478. _assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01-1:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(-60)));
  7479. _assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01-1"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(-60)));
  7480. _assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01-1:30"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(-90)));
  7481. _assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01-8:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(-480)));
  7482. _assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01+1:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(60)));
  7483. _assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01+1"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(60)));
  7484. _assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01+1:30"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(90)));
  7485. _assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01+8:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(480)));
  7486. _assertPred!"=="(SysTime.fromSimpleString("2010-Nov-03 06:51:06.57159Z"), SysTime(DateTime(2010, 11, 3, 6, 51, 6), FracSec.from!"hnsecs"(5715900), UTC()));
  7487. _assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01.23412Z"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(2_341_200), UTC()));
  7488. _assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01.23112-1:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(2_311_200), new SimpleTimeZone(-60)));
  7489. _assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01.45-1"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(4_500_000), new SimpleTimeZone(-60)));
  7490. _assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01.1-1:30"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(1_000_000), new SimpleTimeZone(-90)));
  7491. _assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01.55-8:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(5_500_000), new SimpleTimeZone(-480)));
  7492. _assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01.1234567+1:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(1_234_567), new SimpleTimeZone(60)));
  7493. _assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01.0+1"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(0), new SimpleTimeZone(60)));
  7494. _assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01.0000000+1:30"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(0), new SimpleTimeZone(90)));
  7495. _assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01.45+8:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(4_500_000), new SimpleTimeZone(480)));
  7496. //Verify Examples.
  7497. assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12") == SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
  7498. assert(SysTime.fromSimpleString("1998-Dec-25 02:15:00.007") == SysTime(DateTime(1998, 12, 25, 2, 15, 0), FracSec.from!"msecs"(7)));
  7499. assert(SysTime.fromSimpleString("0000-Jan-05 23:09:59.00002") == SysTime(DateTime(0, 1, 5, 23, 9, 59), FracSec.from!"usecs"(20)));
  7500. assert(SysTime.fromSimpleString("-0004-Jan-05 00:00:02") == SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
  7501. assert(SysTime.fromSimpleString(" 2010-Jul-04 07:06:12 ") == SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
  7502. assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12Z") == SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
  7503. assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12-8:00") == SysTime(DateTime(2010, 7, 4, 7, 6, 12), new SimpleTimeZone(-480)));
  7504. assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12+8:00") == SysTime(DateTime(2010, 7, 4, 7, 6, 12), new SimpleTimeZone(480)));
  7505. }
  7506. }
  7507. //TODO Add function which takes a user-specified time format and produces a SysTime
  7508. //TODO Add function which takes pretty much any time-string and produces a SysTime.
  7509. // Obviously, it will be less efficient, and it probably won't manage _every_
  7510. // possible date format, but a smart conversion function would be nice.
  7511. /++
  7512. Returns the $(D SysTime) farthest in the past which is representable
  7513. by $(D SysTime).
  7514. The $(D SysTime) which is returned is in UTC.
  7515. +/
  7516. @property static SysTime min() pure nothrow
  7517. {
  7518. return SysTime(long.min, UTC());
  7519. }
  7520. unittest
  7521. {
  7522. version(testStdDateTime)
  7523. {
  7524. assert(SysTime.min.year < 0);
  7525. assert(SysTime.min < SysTime.max);
  7526. }
  7527. }
  7528. /++
  7529. Returns the $(D SysTime) farthest in the future which is representable
  7530. by $(D SysTime).
  7531. The $(D SysTime) which is returned is in UTC.
  7532. +/
  7533. @property static SysTime max() pure nothrow
  7534. {
  7535. return SysTime(long.max, UTC());
  7536. }
  7537. unittest
  7538. {
  7539. version(testStdDateTime)
  7540. {
  7541. assert(SysTime.max.year > 0);
  7542. assert(SysTime.max > SysTime.min);
  7543. }
  7544. }
  7545. private:
  7546. /+
  7547. Returns $(D stdTime) converted to $(D SysTime)'s time zone.
  7548. +/
  7549. @property long adjTime() const nothrow
  7550. {
  7551. return _timezone.utcToTZ(_stdTime);
  7552. }
  7553. /+
  7554. Converts the given hnsecs from $(D SysTime)'s time zone to std time.
  7555. +/
  7556. @property void adjTime(long adjTime) nothrow
  7557. {
  7558. _stdTime = _timezone.tzToUTC(adjTime);
  7559. }
  7560. //Commented out due to bug http://d.puremagic.com/issues/show_bug.cgi?id=5058
  7561. /+
  7562. invariant()
  7563. {
  7564. assert(_timezone !is null, "Invariant Failure: timezone is null. Were you foolish enough to use SysTime.init? (since timezone for SysTime.init can't be set at compile time).");
  7565. }
  7566. +/
  7567. long _stdTime;
  7568. Rebindable!(immutable TimeZone) _timezone;
  7569. }
  7570. /++
  7571. Represents a date in the Proleptic Gregorian Calendar ranging from
  7572. 32,768 B.C. to 32,767 A.D. Positive years are A.D. Non-positive years are
  7573. B.C.
  7574. Year, month, and day are kept separately internally so that $(D Date) is
  7575. optimized for calendar-based operations.
  7576. $(D Date) uses the Proleptic Gregorian Calendar, so it assumes the Gregorian
  7577. leap year calculations for its entire length. And, as per
  7578. $(WEB en.wikipedia.org/wiki/ISO_8601, ISO 8601), it also treats 1 B.C. as
  7579. year 0. So, 1 B.C. is 0, 2 B.C. is -1, etc. Use $(D yearBC) if want B.C. as
  7580. a positive integer with 1 B.C. being the year prior to 1 A.D.
  7581. Year 0 is a leap year.
  7582. +/
  7583. struct Date
  7584. {
  7585. public:
  7586. /++
  7587. Throws:
  7588. $(D DateTimeException) if the resulting $(D Date) would not be valid.
  7589. Params:
  7590. year = Year of the Gregorian Calendar. Positive values are A.D.
  7591. Non-positive values are B.C. with year 0 being the year
  7592. prior to 1 A.D.
  7593. month = Month of the year.
  7594. day = Day of the month.
  7595. +/
  7596. this(int year, int month, int day) pure
  7597. {
  7598. enforceValid!"months"(cast(Month)month);
  7599. enforceValid!"days"(year, cast(Month)month, day);
  7600. _year = cast(short)year;
  7601. _month = cast(Month)month;
  7602. _day = cast(ubyte)day;
  7603. }
  7604. unittest
  7605. {
  7606. version(testStdDateTime)
  7607. {
  7608. _assertPred!"=="(Date(1, 1, 1), Date.init);
  7609. static void testDate(in Date date, int year, int month, int day, size_t line = __LINE__)
  7610. {
  7611. _assertPred!"=="(date._year, year, "", __FILE__, line);
  7612. _assertPred!"=="(date._month, month, "", __FILE__, line);
  7613. _assertPred!"=="(date._day, day, "", __FILE__, line);
  7614. }
  7615. testDate(Date(1999, 1 , 1), 1999, Month.jan, 1);
  7616. testDate(Date(1999, 7 , 1), 1999, Month.jul, 1);
  7617. testDate(Date(1999, 7 , 6), 1999, Month.jul, 6);
  7618. //Test A.D.
  7619. assertThrown!DateTimeException(Date(1, 0, 1));
  7620. assertThrown!DateTimeException(Date(1, 1, 0));
  7621. assertThrown!DateTimeException(Date(1999, 13, 1));
  7622. assertThrown!DateTimeException(Date(1999, 1, 32));
  7623. assertThrown!DateTimeException(Date(1999, 2, 29));
  7624. assertThrown!DateTimeException(Date(2000, 2, 30));
  7625. assertThrown!DateTimeException(Date(1999, 3, 32));
  7626. assertThrown!DateTimeException(Date(1999, 4, 31));
  7627. assertThrown!DateTimeException(Date(1999, 5, 32));
  7628. assertThrown!DateTimeException(Date(1999, 6, 31));
  7629. assertThrown!DateTimeException(Date(1999, 7, 32));
  7630. assertThrown!DateTimeException(Date(1999, 8, 32));
  7631. assertThrown!DateTimeException(Date(1999, 9, 31));
  7632. assertThrown!DateTimeException(Date(1999, 10, 32));
  7633. assertThrown!DateTimeException(Date(1999, 11, 31));
  7634. assertThrown!DateTimeException(Date(1999, 12, 32));
  7635. assertNotThrown!DateTimeException(Date(1999, 1, 31));
  7636. assertNotThrown!DateTimeException(Date(1999, 2, 28));
  7637. assertNotThrown!DateTimeException(Date(2000, 2, 29));
  7638. assertNotThrown!DateTimeException(Date(1999, 3, 31));
  7639. assertNotThrown!DateTimeException(Date(1999, 4, 30));
  7640. assertNotThrown!DateTimeException(Date(1999, 5, 31));
  7641. assertNotThrown!DateTimeException(Date(1999, 6, 30));
  7642. assertNotThrown!DateTimeException(Date(1999, 7, 31));
  7643. assertNotThrown!DateTimeException(Date(1999, 8, 31));
  7644. assertNotThrown!DateTimeException(Date(1999, 9, 30));
  7645. assertNotThrown!DateTimeException(Date(1999, 10, 31));
  7646. assertNotThrown!DateTimeException(Date(1999, 11, 30));
  7647. assertNotThrown!DateTimeException(Date(1999, 12, 31));
  7648. //Test B.C.
  7649. assertNotThrown!DateTimeException(Date(0, 1, 1));
  7650. assertNotThrown!DateTimeException(Date(-1, 1, 1));
  7651. assertNotThrown!DateTimeException(Date(-1, 12, 31));
  7652. assertNotThrown!DateTimeException(Date(-1, 2, 28));
  7653. assertNotThrown!DateTimeException(Date(-4, 2, 29));
  7654. assertThrown!DateTimeException(Date(-1, 2, 29));
  7655. assertThrown!DateTimeException(Date(-2, 2, 29));
  7656. assertThrown!DateTimeException(Date(-3, 2, 29));
  7657. }
  7658. }
  7659. /++
  7660. Params:
  7661. day = The Xth day of the Gregorian Calendar that the constructed
  7662. $(D Date) will be for.
  7663. +/
  7664. this(int day) pure nothrow
  7665. {
  7666. if(day > 0)
  7667. {
  7668. int years = (day / daysIn400Years) * 400 + 1;
  7669. day %= daysIn400Years;
  7670. {
  7671. immutable tempYears = day / daysIn100Years;
  7672. if(tempYears == 4)
  7673. {
  7674. years += 300;
  7675. day -= daysIn100Years * 3;
  7676. }
  7677. else
  7678. {
  7679. years += tempYears * 100;
  7680. day %= daysIn100Years;
  7681. }
  7682. }
  7683. years += (day / daysIn4Years) * 4;
  7684. day %= daysIn4Years;
  7685. {
  7686. immutable tempYears = day / daysInYear;
  7687. if(tempYears == 4)
  7688. {
  7689. years += 3;
  7690. day -= daysInYear * 3;
  7691. }
  7692. else
  7693. {
  7694. years += tempYears;
  7695. day %= daysInYear;
  7696. }
  7697. }
  7698. if(day == 0)
  7699. {
  7700. _year = cast(short)(years - 1);
  7701. _month = Month.dec;
  7702. _day = 31;
  7703. }
  7704. else
  7705. {
  7706. _year = cast(short)years;
  7707. try
  7708. dayOfYear = day;
  7709. catch(Exception e)
  7710. assert(0, "dayOfYear assignment threw.");
  7711. }
  7712. }
  7713. else if(day <= 0 && -day < daysInLeapYear)
  7714. {
  7715. _year = 0;
  7716. try
  7717. dayOfYear = (daysInLeapYear + day);
  7718. catch(Exception e)
  7719. assert(0, "dayOfYear assignment threw.");
  7720. }
  7721. else
  7722. {
  7723. day += daysInLeapYear - 1;
  7724. int years = (day / daysIn400Years) * 400 - 1;
  7725. day %= daysIn400Years;
  7726. {
  7727. immutable tempYears = day / daysIn100Years;
  7728. if(tempYears == -4)
  7729. {
  7730. years -= 300;
  7731. day += daysIn100Years * 3;
  7732. }
  7733. else
  7734. {
  7735. years += tempYears * 100;
  7736. day %= daysIn100Years;
  7737. }
  7738. }
  7739. years += (day / daysIn4Years) * 4;
  7740. day %= daysIn4Years;
  7741. {
  7742. immutable tempYears = day / daysInYear;
  7743. if(tempYears == -4)
  7744. {
  7745. years -= 3;
  7746. day += daysInYear * 3;
  7747. }
  7748. else
  7749. {
  7750. years += tempYears;
  7751. day %= daysInYear;
  7752. }
  7753. }
  7754. if(day == 0)
  7755. {
  7756. _year = cast(short)(years + 1);
  7757. _month = Month.jan;
  7758. _day = 1;
  7759. }
  7760. else
  7761. {
  7762. _year = cast(short)years;
  7763. immutable newDoY = (yearIsLeapYear(_year) ? daysInLeapYear : daysInYear) + day + 1;
  7764. try
  7765. dayOfYear = newDoY;
  7766. catch(Exception e)
  7767. assert(0, "dayOfYear assignment threw.");
  7768. }
  7769. }
  7770. }
  7771. version(testStdDateTime) unittest
  7772. {
  7773. //Test A.D.
  7774. foreach(gd; chain(testGregDaysBC, testGregDaysAD))
  7775. _assertPred!"=="(Date(gd.day), gd.date);
  7776. }
  7777. /++
  7778. Compares this $(D Date) with the given $(D Date).
  7779. Returns:
  7780. $(BOOKTABLE,
  7781. $(TR $(TD this &lt; rhs) $(TD &lt; 0))
  7782. $(TR $(TD this == rhs) $(TD 0))
  7783. $(TR $(TD this &gt; rhs) $(TD &gt; 0))
  7784. )
  7785. +/
  7786. int opCmp(in Date rhs) const pure nothrow
  7787. {
  7788. if(_year < rhs._year)
  7789. return -1;
  7790. if(_year > rhs._year)
  7791. return 1;
  7792. if(_month < rhs._month)
  7793. return -1;
  7794. if(_month > rhs._month)
  7795. return 1;
  7796. if(_day < rhs._day)
  7797. return -1;
  7798. if(_day > rhs._day)
  7799. return 1;
  7800. return 0;
  7801. }
  7802. unittest
  7803. {
  7804. version(testStdDateTime)
  7805. {
  7806. //Test A.D.
  7807. _assertPred!("opCmp", "==")(Date(1, 1, 1), Date.init);
  7808. _assertPred!("opCmp", "==")(Date(1999, 1, 1), Date(1999, 1, 1));
  7809. _assertPred!("opCmp", "==")(Date(1, 7, 1), Date(1, 7, 1));
  7810. _assertPred!("opCmp", "==")(Date(1, 1, 6), Date(1, 1, 6));
  7811. _assertPred!("opCmp", "==")(Date(1999, 7, 1), Date(1999, 7, 1));
  7812. _assertPred!("opCmp", "==")(Date(1999, 7, 6), Date(1999, 7, 6));
  7813. _assertPred!("opCmp", "==")(Date(1, 7, 6), Date(1, 7, 6));
  7814. _assertPred!("opCmp", "<")(Date(1999, 7, 6), Date(2000, 7, 6));
  7815. _assertPred!("opCmp", ">")(Date(2000, 7, 6), Date(1999, 7, 6));
  7816. _assertPred!("opCmp", "<")(Date(1999, 7, 6), Date(1999, 8, 6));
  7817. _assertPred!("opCmp", ">")(Date(1999, 8, 6), Date(1999, 7, 6));
  7818. _assertPred!("opCmp", "<")(Date(1999, 7, 6), Date(1999, 7, 7));
  7819. _assertPred!("opCmp", ">")(Date(1999, 7, 7), Date(1999, 7, 6));
  7820. _assertPred!("opCmp", "<")(Date(1999, 8, 7), Date(2000, 7, 6));
  7821. _assertPred!("opCmp", ">")(Date(2000, 8, 6), Date(1999, 7, 7));
  7822. _assertPred!("opCmp", "<")(Date(1999, 7, 7), Date(2000, 7, 6));
  7823. _assertPred!("opCmp", ">")(Date(2000, 7, 6), Date(1999, 7, 7));
  7824. _assertPred!("opCmp", "<")(Date(1999, 7, 7), Date(1999, 8, 6));
  7825. _assertPred!("opCmp", ">")(Date(1999, 8, 6), Date(1999, 7, 7));
  7826. //Test B.C.
  7827. _assertPred!("opCmp", "==")(Date(0, 1, 1), Date(0, 1, 1));
  7828. _assertPred!("opCmp", "==")(Date(-1, 1, 1), Date(-1, 1, 1));
  7829. _assertPred!("opCmp", "==")(Date(-1, 7, 1), Date(-1, 7, 1));
  7830. _assertPred!("opCmp", "==")(Date(-1, 1, 6), Date(-1, 1, 6));
  7831. _assertPred!("opCmp", "==")(Date(-1999, 7, 1), Date(-1999, 7, 1));
  7832. _assertPred!("opCmp", "==")(Date(-1999, 7, 6), Date(-1999, 7, 6));
  7833. _assertPred!("opCmp", "==")(Date(-1, 7, 6), Date(-1, 7, 6));
  7834. _assertPred!("opCmp", "<")(Date(-2000, 7, 6), Date(-1999, 7, 6));
  7835. _assertPred!("opCmp", ">")(Date(-1999, 7, 6), Date(-2000, 7, 6));
  7836. _assertPred!("opCmp", "<")(Date(-1999, 7, 6), Date(-1999, 8, 6));
  7837. _assertPred!("opCmp", ">")(Date(-1999, 8, 6), Date(-1999, 7, 6));
  7838. _assertPred!("opCmp", "<")(Date(-1999, 7, 6), Date(-1999, 7, 7));
  7839. _assertPred!("opCmp", ">")(Date(-1999, 7, 7), Date(-1999, 7, 6));
  7840. _assertPred!("opCmp", "<")(Date(-2000, 8, 6), Date(-1999, 7, 7));
  7841. _assertPred!("opCmp", ">")(Date(-1999, 8, 7), Date(-2000, 7, 6));
  7842. _assertPred!("opCmp", "<")(Date(-2000, 7, 6), Date(-1999, 7, 7));
  7843. _assertPred!("opCmp", ">")(Date(-1999, 7, 7), Date(-2000, 7, 6));
  7844. _assertPred!("opCmp", "<")(Date(-1999, 7, 7), Date(-1999, 8, 6));
  7845. _assertPred!("opCmp", ">")(Date(-1999, 8, 6), Date(-1999, 7, 7));
  7846. //Test Both
  7847. _assertPred!("opCmp", "<")(Date(-1999, 7, 6), Date(1999, 7, 6));
  7848. _assertPred!("opCmp", ">")(Date(1999, 7, 6), Date(-1999, 7, 6));
  7849. _assertPred!("opCmp", "<")(Date(-1999, 8, 6), Date(1999, 7, 6));
  7850. _assertPred!("opCmp", ">")(Date(1999, 7, 6), Date(-1999, 8, 6));
  7851. _assertPred!("opCmp", "<")(Date(-1999, 7, 7), Date(1999, 7, 6));
  7852. _assertPred!("opCmp", ">")(Date(1999, 7, 6), Date(-1999, 7, 7));
  7853. _assertPred!("opCmp", "<")(Date(-1999, 8, 7), Date(1999, 7, 6));
  7854. _assertPred!("opCmp", ">")(Date(1999, 7, 6), Date(-1999, 8, 7));
  7855. _assertPred!("opCmp", "<")(Date(-1999, 8, 6), Date(1999, 6, 6));
  7856. _assertPred!("opCmp", ">")(Date(1999, 6, 8), Date(-1999, 7, 6));
  7857. auto date = Date(1999, 7, 6);
  7858. const cdate = Date(1999, 7, 6);
  7859. immutable idate = Date(1999, 7, 6);
  7860. static assert(__traits(compiles, date.opCmp(date)));
  7861. static assert(__traits(compiles, date.opCmp(cdate)));
  7862. static assert(__traits(compiles, date.opCmp(idate)));
  7863. static assert(__traits(compiles, cdate.opCmp(date)));
  7864. static assert(__traits(compiles, cdate.opCmp(cdate)));
  7865. static assert(__traits(compiles, cdate.opCmp(idate)));
  7866. static assert(__traits(compiles, idate.opCmp(date)));
  7867. static assert(__traits(compiles, idate.opCmp(cdate)));
  7868. static assert(__traits(compiles, idate.opCmp(idate)));
  7869. }
  7870. }
  7871. /++
  7872. Year of the Gregorian Calendar. Positive numbers are A.D. Non-positive
  7873. are B.C.
  7874. Examples:
  7875. --------------------
  7876. assert(Date(1999, 7, 6).year == 1999);
  7877. assert(Date(2010, 10, 4).year == 2010);
  7878. assert(Date(-7, 4, 5).year == -7);
  7879. --------------------
  7880. +/
  7881. @property short year() const pure nothrow
  7882. {
  7883. return _year;
  7884. }
  7885. unittest
  7886. {
  7887. version(testStdDateTime)
  7888. {
  7889. _assertPred!"=="(Date.init.year, 1);
  7890. _assertPred!"=="(Date(1999, 7, 6).year, 1999);
  7891. _assertPred!"=="(Date(-1999, 7, 6).year, -1999);
  7892. const cdate = Date(1999, 7, 6);
  7893. immutable idate = Date(1999, 7, 6);
  7894. static assert(__traits(compiles, cdate.year == 1999));
  7895. static assert(__traits(compiles, idate.year == 1999));
  7896. //Verify Examples.
  7897. assert(Date(1999, 7, 6).year == 1999);
  7898. assert(Date(2010, 10, 4).year == 2010);
  7899. assert(Date(-7, 4, 5).year == -7);
  7900. }
  7901. }
  7902. /++
  7903. Year of the Gregorian Calendar. Positive numbers are A.D. Non-positive
  7904. are B.C.
  7905. Params:
  7906. year = The year to set this Date's year to.
  7907. Throws:
  7908. $(D DateTimeException) if the new year is not a leap year and the
  7909. resulting date would be on February 29th.
  7910. +/
  7911. @property void year(int year) pure
  7912. {
  7913. enforceValid!"days"(year, _month, _day);
  7914. _year = cast(short)year;
  7915. }
  7916. unittest
  7917. {
  7918. version(testStdDateTime)
  7919. {
  7920. static void testDateInvalid(Date date, int year)
  7921. {
  7922. date.year = year;
  7923. }
  7924. static void testDate(Date date, int year, in Date expected, size_t line = __LINE__)
  7925. {
  7926. date.year = year;
  7927. _assertPred!"=="(date, expected, "", __FILE__, line);
  7928. }
  7929. assertThrown!DateTimeException(testDateInvalid(Date(4, 2, 29), 1));
  7930. testDate(Date(1, 1, 1), 1999, Date(1999, 1, 1));
  7931. testDate(Date(1, 1, 1), 0, Date(0, 1, 1));
  7932. testDate(Date(1, 1, 1), -1999, Date(-1999, 1, 1));
  7933. const cdate = Date(1999, 7, 6);
  7934. immutable idate = Date(1999, 7, 6);
  7935. static assert(!__traits(compiles, cdate.year = 1999));
  7936. static assert(!__traits(compiles, idate.year = 1999));
  7937. //Verify Examples.
  7938. assert(Date(1999, 7, 6).year == 1999);
  7939. assert(Date(2010, 10, 4).year == 2010);
  7940. assert(Date(-7, 4, 5).year == -7);
  7941. }
  7942. }
  7943. /++
  7944. Year B.C. of the Gregorian Calendar counting year 0 as 1 B.C.
  7945. Throws:
  7946. $(D DateTimeException) if $(D isAD) is true.
  7947. Examples:
  7948. --------------------
  7949. assert(Date(0, 1, 1).yearBC == 1);
  7950. assert(Date(-1, 1, 1).yearBC == 2);
  7951. assert(Date(-100, 1, 1).yearBC == 101);
  7952. --------------------
  7953. +/
  7954. @property ushort yearBC() const pure
  7955. {
  7956. if(isAD)
  7957. throw new DateTimeException("Year " ~ numToString(_year) ~ " is A.D.");
  7958. //Once format is pure, this would be a better error message.
  7959. //throw new DateTimeException(format("%s is A.D.", this));
  7960. return cast(ushort)((_year * -1) + 1);
  7961. }
  7962. unittest
  7963. {
  7964. version(testStdDateTime)
  7965. {
  7966. assertThrown!DateTimeException((in Date date){date.yearBC;}(Date(1, 1, 1)));
  7967. auto date = Date(0, 7, 6);
  7968. const cdate = Date(0, 7, 6);
  7969. immutable idate = Date(0, 7, 6);
  7970. static assert(__traits(compiles, date.yearBC));
  7971. static assert(__traits(compiles, cdate.yearBC));
  7972. static assert(__traits(compiles, idate.yearBC));
  7973. //Verify Examples.
  7974. assert(Date(0, 1, 1).yearBC == 1);
  7975. assert(Date(-1, 1, 1).yearBC == 2);
  7976. assert(Date(-100, 1, 1).yearBC == 101);
  7977. }
  7978. }
  7979. /++
  7980. Year B.C. of the Gregorian Calendar counting year 0 as 1 B.C.
  7981. Params:
  7982. year = The year B.C. to set this $(D Date)'s year to.
  7983. Throws:
  7984. $(D DateTimeException) if a non-positive value is given.
  7985. Examples:
  7986. --------------------
  7987. auto date = Date(2010, 1, 1);
  7988. date.yearBC = 1;
  7989. assert(date == Date(0, 1, 1));
  7990. date.yearBC = 10;
  7991. assert(date == Date(-9, 1, 1));
  7992. --------------------
  7993. +/
  7994. @property void yearBC(int year) pure
  7995. {
  7996. if(year <= 0)
  7997. throw new DateTimeException("The given year is not a year B.C.");
  7998. _year = cast(short)((year - 1) * -1);
  7999. }
  8000. unittest
  8001. {
  8002. version(testStdDateTime)
  8003. {
  8004. assertThrown!DateTimeException((Date date){date.yearBC = -1;}(Date(1, 1, 1)));
  8005. {
  8006. auto date = Date(0, 7, 6);
  8007. const cdate = Date(0, 7, 6);
  8008. immutable idate = Date(0, 7, 6);
  8009. static assert(__traits(compiles, date.yearBC = 7));
  8010. static assert(!__traits(compiles, cdate.yearBC = 7));
  8011. static assert(!__traits(compiles, idate.yearBC = 7));
  8012. }
  8013. //Verify Examples.
  8014. {
  8015. auto date = Date(2010, 1, 1);
  8016. date.yearBC = 1;
  8017. assert(date == Date(0, 1, 1));
  8018. date.yearBC = 10;
  8019. assert(date == Date(-9, 1, 1));
  8020. }
  8021. }
  8022. }
  8023. /++
  8024. Month of a Gregorian Year.
  8025. Examples:
  8026. --------------------
  8027. assert(Date(1999, 7, 6).month == 7);
  8028. assert(Date(2010, 10, 4).month == 10);
  8029. assert(Date(-7, 4, 5).month == 4);
  8030. --------------------
  8031. +/
  8032. @property Month month() const pure nothrow
  8033. {
  8034. return _month;
  8035. }
  8036. unittest
  8037. {
  8038. version(testStdDateTime)
  8039. {
  8040. _assertPred!"=="(Date.init.month, 1);
  8041. _assertPred!"=="(Date(1999, 7, 6).month, 7);
  8042. _assertPred!"=="(Date(-1999, 7, 6).month, 7);
  8043. const cdate = Date(1999, 7, 6);
  8044. immutable idate = Date(1999, 7, 6);
  8045. static assert(__traits(compiles, cdate.month == 7));
  8046. static assert(__traits(compiles, idate.month == 7));
  8047. //Verify Examples.
  8048. assert(Date(1999, 7, 6).month == 7);
  8049. assert(Date(2010, 10, 4).month == 10);
  8050. assert(Date(-7, 4, 5).month == 4);
  8051. }
  8052. }
  8053. /++
  8054. Month of a Gregorian Year.
  8055. Params:
  8056. month = The month to set this $(D Date)'s month to.
  8057. Throws:
  8058. $(D DateTimeException) if the given month is not a valid month or if
  8059. the current day would not be valid in the given month.
  8060. +/
  8061. @property void month(Month month) pure
  8062. {
  8063. enforceValid!"months"(month);
  8064. enforceValid!"days"(_year, month, _day);
  8065. _month = cast(Month)month;
  8066. }
  8067. unittest
  8068. {
  8069. version(testStdDateTime)
  8070. {
  8071. static void testDate(Date date, Month month, in Date expected = Date.init, size_t line = __LINE__)
  8072. {
  8073. date.month = month;
  8074. assert(expected != Date.init);
  8075. _assertPred!"=="(date, expected, "", __FILE__, line);
  8076. }
  8077. assertThrown!DateTimeException(testDate(Date(1, 1, 1), cast(Month)0));
  8078. assertThrown!DateTimeException(testDate(Date(1, 1, 1), cast(Month)13));
  8079. assertThrown!DateTimeException(testDate(Date(1, 1, 29), cast(Month)2));
  8080. assertThrown!DateTimeException(testDate(Date(0, 1, 30), cast(Month)2));
  8081. testDate(Date(1, 1, 1), cast(Month)7, Date(1, 7, 1));
  8082. testDate(Date(-1, 1, 1), cast(Month)7, Date(-1, 7, 1));
  8083. const cdate = Date(1999, 7, 6);
  8084. immutable idate = Date(1999, 7, 6);
  8085. static assert(!__traits(compiles, cdate.month = 7));
  8086. static assert(!__traits(compiles, idate.month = 7));
  8087. }
  8088. }
  8089. /++
  8090. Day of a Gregorian Month.
  8091. Examples:
  8092. --------------------
  8093. assert(Date(1999, 7, 6).day == 6);
  8094. assert(Date(2010, 10, 4).day == 4);
  8095. assert(Date(-7, 4, 5).day == 5);
  8096. --------------------
  8097. +/
  8098. @property ubyte day() const pure nothrow
  8099. {
  8100. return _day;
  8101. }
  8102. //Verify Examples.
  8103. version(testStdDateTime) unittest
  8104. {
  8105. assert(Date(1999, 7, 6).day == 6);
  8106. assert(Date(2010, 10, 4).day == 4);
  8107. assert(Date(-7, 4, 5).day == 5);
  8108. }
  8109. version(testStdDateTime) unittest
  8110. {
  8111. static void test(Date date, int expected, size_t line = __LINE__)
  8112. {
  8113. _assertPred!"=="(date.day, expected,
  8114. format("Value given: %s", date), __FILE__, line);
  8115. }
  8116. foreach(year; chain(testYearsBC, testYearsAD))
  8117. {
  8118. foreach(md; testMonthDays)
  8119. test(Date(year, md.month, md.day), md.day);
  8120. }
  8121. const cdate = Date(1999, 7, 6);
  8122. immutable idate = Date(1999, 7, 6);
  8123. static assert(__traits(compiles, cdate.day == 6));
  8124. static assert(__traits(compiles, idate.day == 6));
  8125. }
  8126. /++
  8127. Day of a Gregorian Month.
  8128. Params:
  8129. day = The day of the month to set this $(D Date)'s day to.
  8130. Throws:
  8131. $(D DateTimeException) if the given day is not a valid day of the
  8132. current month.
  8133. +/
  8134. @property void day(int day) pure
  8135. {
  8136. enforceValid!"days"(_year, _month, day);
  8137. _day = cast(ubyte)day;
  8138. }
  8139. unittest
  8140. {
  8141. version(testStdDateTime)
  8142. {
  8143. static void testDate(Date date, int day)
  8144. {
  8145. date.day = day;
  8146. }
  8147. //Test A.D.
  8148. assertThrown!DateTimeException(testDate(Date(1, 1, 1), 0));
  8149. assertThrown!DateTimeException(testDate(Date(1, 1, 1), 32));
  8150. assertThrown!DateTimeException(testDate(Date(1, 2, 1), 29));
  8151. assertThrown!DateTimeException(testDate(Date(4, 2, 1), 30));
  8152. assertThrown!DateTimeException(testDate(Date(1, 3, 1), 32));
  8153. assertThrown!DateTimeException(testDate(Date(1, 4, 1), 31));
  8154. assertThrown!DateTimeException(testDate(Date(1, 5, 1), 32));
  8155. assertThrown!DateTimeException(testDate(Date(1, 6, 1), 31));
  8156. assertThrown!DateTimeException(testDate(Date(1, 7, 1), 32));
  8157. assertThrown!DateTimeException(testDate(Date(1, 8, 1), 32));
  8158. assertThrown!DateTimeException(testDate(Date(1, 9, 1), 31));
  8159. assertThrown!DateTimeException(testDate(Date(1, 10, 1), 32));
  8160. assertThrown!DateTimeException(testDate(Date(1, 11, 1), 31));
  8161. assertThrown!DateTimeException(testDate(Date(1, 12, 1), 32));
  8162. assertNotThrown!DateTimeException(testDate(Date(1, 1, 1), 31));
  8163. assertNotThrown!DateTimeException(testDate(Date(1, 2, 1), 28));
  8164. assertNotThrown!DateTimeException(testDate(Date(4, 2, 1), 29));
  8165. assertNotThrown!DateTimeException(testDate(Date(1, 3, 1), 31));
  8166. assertNotThrown!DateTimeException(testDate(Date(1, 4, 1), 30));
  8167. assertNotThrown!DateTimeException(testDate(Date(1, 5, 1), 31));
  8168. assertNotThrown!DateTimeException(testDate(Date(1, 6, 1), 30));
  8169. assertNotThrown!DateTimeException(testDate(Date(1, 7, 1), 31));
  8170. assertNotThrown!DateTimeException(testDate(Date(1, 8, 1), 31));
  8171. assertNotThrown!DateTimeException(testDate(Date(1, 9, 1), 30));
  8172. assertNotThrown!DateTimeException(testDate(Date(1, 10, 1), 31));
  8173. assertNotThrown!DateTimeException(testDate(Date(1, 11, 1), 30));
  8174. assertNotThrown!DateTimeException(testDate(Date(1, 12, 1), 31));
  8175. {
  8176. auto date = Date(1, 1, 1);
  8177. date.day = 6;
  8178. _assertPred!"=="(date, Date(1, 1, 6));
  8179. }
  8180. //Test B.C.
  8181. assertThrown!DateTimeException(testDate(Date(-1, 1, 1), 0));
  8182. assertThrown!DateTimeException(testDate(Date(-1, 1, 1), 32));
  8183. assertThrown!DateTimeException(testDate(Date(-1, 2, 1), 29));
  8184. assertThrown!DateTimeException(testDate(Date(0, 2, 1), 30));
  8185. assertThrown!DateTimeException(testDate(Date(-1, 3, 1), 32));
  8186. assertThrown!DateTimeException(testDate(Date(-1, 4, 1), 31));
  8187. assertThrown!DateTimeException(testDate(Date(-1, 5, 1), 32));
  8188. assertThrown!DateTimeException(testDate(Date(-1, 6, 1), 31));
  8189. assertThrown!DateTimeException(testDate(Date(-1, 7, 1), 32));
  8190. assertThrown!DateTimeException(testDate(Date(-1, 8, 1), 32));
  8191. assertThrown!DateTimeException(testDate(Date(-1, 9, 1), 31));
  8192. assertThrown!DateTimeException(testDate(Date(-1, 10, 1), 32));
  8193. assertThrown!DateTimeException(testDate(Date(-1, 11, 1), 31));
  8194. assertThrown!DateTimeException(testDate(Date(-1, 12, 1), 32));
  8195. assertNotThrown!DateTimeException(testDate(Date(-1, 1, 1), 31));
  8196. assertNotThrown!DateTimeException(testDate(Date(-1, 2, 1), 28));
  8197. assertNotThrown!DateTimeException(testDate(Date(0, 2, 1), 29));
  8198. assertNotThrown!DateTimeException(testDate(Date(-1, 3, 1), 31));
  8199. assertNotThrown!DateTimeException(testDate(Date(-1, 4, 1), 30));
  8200. assertNotThrown!DateTimeException(testDate(Date(-1, 5, 1), 31));
  8201. assertNotThrown!DateTimeException(testDate(Date(-1, 6, 1), 30));
  8202. assertNotThrown!DateTimeException(testDate(Date(-1, 7, 1), 31));
  8203. assertNotThrown!DateTimeException(testDate(Date(-1, 8, 1), 31));
  8204. assertNotThrown!DateTimeException(testDate(Date(-1, 9, 1), 30));
  8205. assertNotThrown!DateTimeException(testDate(Date(-1, 10, 1), 31));
  8206. assertNotThrown!DateTimeException(testDate(Date(-1, 11, 1), 30));
  8207. assertNotThrown!DateTimeException(testDate(Date(-1, 12, 1), 31));
  8208. {
  8209. auto date = Date(-1, 1, 1);
  8210. date.day = 6;
  8211. _assertPred!"=="(date, Date(-1, 1, 6));
  8212. }
  8213. const cdate = Date(1999, 7, 6);
  8214. immutable idate = Date(1999, 7, 6);
  8215. static assert(!__traits(compiles, cdate.day = 6));
  8216. static assert(!__traits(compiles, idate.day = 6));
  8217. }
  8218. }
  8219. /++
  8220. Adds the given number of years or months to this $(D Date). A negative
  8221. number will subtract.
  8222. Note that if day overflow is allowed, and the date with the adjusted
  8223. year/month overflows the number of days in the new month, then the month
  8224. will be incremented by one, and the day set to the number of days
  8225. overflowed. (e.g. if the day were 31 and the new month were June, then
  8226. the month would be incremented to July, and the new day would be 1). If
  8227. day overflow is not allowed, then the day will be set to the last valid
  8228. day in the month (e.g. June 31st would become June 30th).
  8229. Params:
  8230. units = The type of units to add ("years" or "months").
  8231. value = The number of months or years to add to this
  8232. $(D Date).
  8233. allowOverflow = Whether the day should be allowed to overflow,
  8234. causing the month to increment.
  8235. Examples:
  8236. --------------------
  8237. auto d1 = Date(2010, 1, 1);
  8238. d1.add!"months"(11);
  8239. assert(d1 == Date(2010, 12, 1));
  8240. auto d2 = Date(2010, 1, 1);
  8241. d2.add!"months"(-11);
  8242. assert(d2 == Date(2009, 2, 1));
  8243. auto d3 = Date(2000, 2, 29);
  8244. d3.add!"years"(1);
  8245. assert(d3 == Date(2001, 3, 1));
  8246. auto d4 = Date(2000, 2, 29);
  8247. d4.add!"years"(1, AllowDayOverflow.no);
  8248. assert(d4 == Date(2001, 2, 28));
  8249. --------------------
  8250. +/
  8251. /+ref Date+/ void add(string units)(long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) pure nothrow
  8252. if(units == "years")
  8253. {
  8254. immutable newYear = _year + value;
  8255. _year += value;
  8256. if(_month == Month.feb && _day == 29 && !yearIsLeapYear(_year))
  8257. {
  8258. if(allowOverflow == AllowDayOverflow.yes)
  8259. {
  8260. _month = Month.mar;
  8261. _day = 1;
  8262. }
  8263. else
  8264. _day = 28;
  8265. }
  8266. }
  8267. //Verify Examples.
  8268. unittest
  8269. {
  8270. version(stdStdDateTime)
  8271. {
  8272. auto d1 = Date(2010, 1, 1);
  8273. d1.add!"months"(11);
  8274. assert(d1 == Date(2010, 12, 1));
  8275. auto d2 = Date(2010, 1, 1);
  8276. d2.add!"months"(-11);
  8277. assert(d2 == Date(2009, 2, 1));
  8278. auto d3 = Date(2000, 2, 29);
  8279. d3.add!"years"(1);
  8280. assert(d3 == Date(2001, 3, 1));
  8281. auto d4 = Date(2000, 2, 29);
  8282. d4.add!"years"(1, AllowDayOverflow.no);
  8283. assert(d4 == Date(2001, 2, 28));
  8284. }
  8285. }
  8286. //Test add!"years"() with AllowDayOverlow.yes
  8287. unittest
  8288. {
  8289. version(testStdDateTime)
  8290. {
  8291. //Test A.D.
  8292. {
  8293. auto date = Date(1999, 7, 6);
  8294. date.add!"years"(7);
  8295. _assertPred!"=="(date, Date(2006, 7, 6));
  8296. date.add!"years"(-9);
  8297. _assertPred!"=="(date, Date(1997, 7, 6));
  8298. }
  8299. {
  8300. auto date = Date(1999, 2, 28);
  8301. date.add!"years"(1);
  8302. _assertPred!"=="(date, Date(2000, 2, 28));
  8303. }
  8304. {
  8305. auto date = Date(2000, 2, 29);
  8306. date.add!"years"(-1);
  8307. _assertPred!"=="(date, Date(1999, 3, 1));
  8308. }
  8309. //Test B.C.
  8310. {
  8311. auto date = Date(-1999, 7, 6);
  8312. date.add!"years"(-7);
  8313. _assertPred!"=="(date, Date(-2006, 7, 6));
  8314. date.add!"years"(9);
  8315. _assertPred!"=="(date, Date(-1997, 7, 6));
  8316. }
  8317. {
  8318. auto date = Date(-1999, 2, 28);
  8319. date.add!"years"(-1);
  8320. _assertPred!"=="(date, Date(-2000, 2, 28));
  8321. }
  8322. {
  8323. auto date = Date(-2000, 2, 29);
  8324. date.add!"years"(1);
  8325. _assertPred!"=="(date, Date(-1999, 3, 1));
  8326. }
  8327. //Test Both
  8328. {
  8329. auto date = Date(4, 7, 6);
  8330. date.add!"years"(-5);
  8331. _assertPred!"=="(date, Date(-1, 7, 6));
  8332. date.add!"years"(5);
  8333. _assertPred!"=="(date, Date(4, 7, 6));
  8334. }
  8335. {
  8336. auto date = Date(-4, 7, 6);
  8337. date.add!"years"(5);
  8338. _assertPred!"=="(date, Date(1, 7, 6));
  8339. date.add!"years"(-5);
  8340. _assertPred!"=="(date, Date(-4, 7, 6));
  8341. }
  8342. {
  8343. auto date = Date(4, 7, 6);
  8344. date.add!"years"(-8);
  8345. _assertPred!"=="(date, Date(-4, 7, 6));
  8346. date.add!"years"(8);
  8347. _assertPred!"=="(date, Date(4, 7, 6));
  8348. }
  8349. {
  8350. auto date = Date(-4, 7, 6);
  8351. date.add!"years"(8);
  8352. _assertPred!"=="(date, Date(4, 7, 6));
  8353. date.add!"years"(-8);
  8354. _assertPred!"=="(date, Date(-4, 7, 6));
  8355. }
  8356. {
  8357. auto date = Date(-4, 2, 29);
  8358. date.add!"years"(5);
  8359. _assertPred!"=="(date, Date(1, 3, 1));
  8360. }
  8361. {
  8362. auto date = Date(4, 2, 29);
  8363. date.add!"years"(-5);
  8364. _assertPred!"=="(date, Date(-1, 3, 1));
  8365. }
  8366. const cdate = Date(1999, 7, 6);
  8367. immutable idate = Date(1999, 7, 6);
  8368. static assert(!__traits(compiles, cdate.add!"years"(7)));
  8369. static assert(!__traits(compiles, idate.add!"years"(7)));
  8370. }
  8371. }
  8372. //Test add!"years"() with AllowDayOverlow.no
  8373. unittest
  8374. {
  8375. version(testStdDateTime)
  8376. {
  8377. //Test A.D.
  8378. {
  8379. auto date = Date(1999, 7, 6);
  8380. date.add!"years"(7, AllowDayOverflow.no);
  8381. _assertPred!"=="(date, Date(2006, 7, 6));
  8382. date.add!"years"(-9, AllowDayOverflow.no);
  8383. _assertPred!"=="(date, Date(1997, 7, 6));
  8384. }
  8385. {
  8386. auto date = Date(1999, 2, 28);
  8387. date.add!"years"(1, AllowDayOverflow.no);
  8388. _assertPred!"=="(date, Date(2000, 2, 28));
  8389. }
  8390. {
  8391. auto date = Date(2000, 2, 29);
  8392. date.add!"years"(-1, AllowDayOverflow.no);
  8393. _assertPred!"=="(date, Date(1999, 2, 28));
  8394. }
  8395. //Test B.C.
  8396. {
  8397. auto date = Date(-1999, 7, 6);
  8398. date.add!"years"(-7, AllowDayOverflow.no);
  8399. _assertPred!"=="(date, Date(-2006, 7, 6));
  8400. date.add!"years"(9, AllowDayOverflow.no);
  8401. _assertPred!"=="(date, Date(-1997, 7, 6));
  8402. }
  8403. {
  8404. auto date = Date(-1999, 2, 28);
  8405. date.add!"years"(-1, AllowDayOverflow.no);
  8406. _assertPred!"=="(date, Date(-2000, 2, 28));
  8407. }
  8408. {
  8409. auto date = Date(-2000, 2, 29);
  8410. date.add!"years"(1, AllowDayOverflow.no);
  8411. _assertPred!"=="(date, Date(-1999, 2, 28));
  8412. }
  8413. //Test Both
  8414. {
  8415. auto date = Date(4, 7, 6);
  8416. date.add!"years"(-5, AllowDayOverflow.no);
  8417. _assertPred!"=="(date, Date(-1, 7, 6));
  8418. date.add!"years"(5, AllowDayOverflow.no);
  8419. _assertPred!"=="(date, Date(4, 7, 6));
  8420. }
  8421. {
  8422. auto date = Date(-4, 7, 6);
  8423. date.add!"years"(5, AllowDayOverflow.no);
  8424. _assertPred!"=="(date, Date(1, 7, 6));
  8425. date.add!"years"(-5, AllowDayOverflow.no);
  8426. _assertPred!"=="(date, Date(-4, 7, 6));
  8427. }
  8428. {
  8429. auto date = Date(4, 7, 6);
  8430. date.add!"years"(-8, AllowDayOverflow.no);
  8431. _assertPred!"=="(date, Date(-4, 7, 6));
  8432. date.add!"years"(8, AllowDayOverflow.no);
  8433. _assertPred!"=="(date, Date(4, 7, 6));
  8434. }
  8435. {
  8436. auto date = Date(-4, 7, 6);
  8437. date.add!"years"(8, AllowDayOverflow.no);
  8438. _assertPred!"=="(date, Date(4, 7, 6));
  8439. date.add!"years"(-8, AllowDayOverflow.no);
  8440. _assertPred!"=="(date, Date(-4, 7, 6));
  8441. }
  8442. {
  8443. auto date = Date(-4, 2, 29);
  8444. date.add!"years"(5, AllowDayOverflow.no);
  8445. _assertPred!"=="(date, Date(1, 2, 28));
  8446. }
  8447. {
  8448. auto date = Date(4, 2, 29);
  8449. date.add!"years"(-5, AllowDayOverflow.no);
  8450. _assertPred!"=="(date, Date(-1, 2, 28));
  8451. }
  8452. }
  8453. }
  8454. //Shares documentation with "years" version.
  8455. /+ref Date+/ void add(string units)(long months, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) pure nothrow
  8456. if(units == "months")
  8457. {
  8458. auto years = months / 12;
  8459. months %= 12;
  8460. auto newMonth = _month + months;
  8461. if(months < 0)
  8462. {
  8463. if(newMonth < 1)
  8464. {
  8465. newMonth += 12;
  8466. --years;
  8467. }
  8468. }
  8469. else if(newMonth > 12)
  8470. {
  8471. newMonth -= 12;
  8472. ++years;
  8473. }
  8474. _year += years;
  8475. _month = cast(Month)newMonth;
  8476. immutable currMaxDay = maxDay(_year, _month);
  8477. immutable overflow = _day - currMaxDay;
  8478. if(overflow > 0)
  8479. {
  8480. if(allowOverflow == AllowDayOverflow.yes)
  8481. {
  8482. ++_month;
  8483. _day = cast(ubyte)overflow;
  8484. }
  8485. else
  8486. _day = cast(ubyte)currMaxDay;
  8487. }
  8488. }
  8489. //Test add!"months"() with AllowDayOverlow.yes
  8490. unittest
  8491. {
  8492. version(testStdDateTime)
  8493. {
  8494. //Test A.D.
  8495. {
  8496. auto date = Date(1999, 7, 6);
  8497. date.add!"months"(3);
  8498. _assertPred!"=="(date, Date(1999, 10, 6));
  8499. date.add!"months"(-4);
  8500. _assertPred!"=="(date, Date(1999, 6, 6));
  8501. }
  8502. {
  8503. auto date = Date(1999, 7, 6);
  8504. date.add!"months"(6);
  8505. _assertPred!"=="(date, Date(2000, 1, 6));
  8506. date.add!"months"(-6);
  8507. _assertPred!"=="(date, Date(1999, 7, 6));
  8508. }
  8509. {
  8510. auto date = Date(1999, 7, 6);
  8511. date.add!"months"(27);
  8512. _assertPred!"=="(date, Date(2001, 10, 6));
  8513. date.add!"months"(-28);
  8514. _assertPred!"=="(date, Date(1999, 6, 6));
  8515. }
  8516. {
  8517. auto date = Date(1999, 5, 31);
  8518. date.add!"months"(1);
  8519. _assertPred!"=="(date, Date(1999, 7, 1));
  8520. }
  8521. {
  8522. auto date = Date(1999, 5, 31);
  8523. date.add!"months"(-1);
  8524. _assertPred!"=="(date, Date(1999, 5, 1));
  8525. }
  8526. {
  8527. auto date = Date(1999, 2, 28);
  8528. date.add!"months"(12);
  8529. _assertPred!"=="(date, Date(2000, 2, 28));
  8530. }
  8531. {
  8532. auto date = Date(2000, 2, 29);
  8533. date.add!"months"(12);
  8534. _assertPred!"=="(date, Date(2001, 3, 1));
  8535. }
  8536. {
  8537. auto date = Date(1999, 7, 31);
  8538. date.add!"months"(1);
  8539. _assertPred!"=="(date, Date(1999, 8, 31));
  8540. date.add!"months"(1);
  8541. _assertPred!"=="(date, Date(1999, 10, 1));
  8542. }
  8543. {
  8544. auto date = Date(1998, 8, 31);
  8545. date.add!"months"(13);
  8546. _assertPred!"=="(date, Date(1999, 10, 1));
  8547. date.add!"months"(-13);
  8548. _assertPred!"=="(date, Date(1998, 9, 1));
  8549. }
  8550. {
  8551. auto date = Date(1997, 12, 31);
  8552. date.add!"months"(13);
  8553. _assertPred!"=="(date, Date(1999, 1, 31));
  8554. date.add!"months"(-13);
  8555. _assertPred!"=="(date, Date(1997, 12, 31));
  8556. }
  8557. {
  8558. auto date = Date(1997, 12, 31);
  8559. date.add!"months"(14);
  8560. _assertPred!"=="(date, Date(1999, 3, 3));
  8561. date.add!"months"(-14);
  8562. _assertPred!"=="(date, Date(1998, 1, 3));
  8563. }
  8564. {
  8565. auto date = Date(1998, 12, 31);
  8566. date.add!"months"(14);
  8567. _assertPred!"=="(date, Date(2000, 3, 2));
  8568. date.add!"months"(-14);
  8569. _assertPred!"=="(date, Date(1999, 1, 2));
  8570. }
  8571. {
  8572. auto date = Date(1999, 12, 31);
  8573. date.add!"months"(14);
  8574. _assertPred!"=="(date, Date(2001, 3, 3));
  8575. date.add!"months"(-14);
  8576. _assertPred!"=="(date, Date(2000, 1, 3));
  8577. }
  8578. //Test B.C.
  8579. {
  8580. auto date = Date(-1999, 7, 6);
  8581. date.add!"months"(3);
  8582. _assertPred!"=="(date, Date(-1999, 10, 6));
  8583. date.add!"months"(-4);
  8584. _assertPred!"=="(date, Date(-1999, 6, 6));
  8585. }
  8586. {
  8587. auto date = Date(-1999, 7, 6);
  8588. date.add!"months"(6);
  8589. _assertPred!"=="(date, Date(-1998, 1, 6));
  8590. date.add!"months"(-6);
  8591. _assertPred!"=="(date, Date(-1999, 7, 6));
  8592. }
  8593. {
  8594. auto date = Date(-1999, 7, 6);
  8595. date.add!"months"(-27);
  8596. _assertPred!"=="(date, Date(-2001, 4, 6));
  8597. date.add!"months"(28);
  8598. _assertPred!"=="(date, Date(-1999, 8, 6));
  8599. }
  8600. {
  8601. auto date = Date(-1999, 5, 31);
  8602. date.add!"months"(1);
  8603. _assertPred!"=="(date, Date(-1999, 7, 1));
  8604. }
  8605. {
  8606. auto date = Date(-1999, 5, 31);
  8607. date.add!"months"(-1);
  8608. _assertPred!"=="(date, Date(-1999, 5, 1));
  8609. }
  8610. {
  8611. auto date = Date(-1999, 2, 28);
  8612. date.add!"months"(-12);
  8613. _assertPred!"=="(date, Date(-2000, 2, 28));
  8614. }
  8615. {
  8616. auto date = Date(-2000, 2, 29);
  8617. date.add!"months"(-12);
  8618. _assertPred!"=="(date, Date(-2001, 3, 1));
  8619. }
  8620. {
  8621. auto date = Date(-1999, 7, 31);
  8622. date.add!"months"(1);
  8623. _assertPred!"=="(date, Date(-1999, 8, 31));
  8624. date.add!"months"(1);
  8625. _assertPred!"=="(date, Date(-1999, 10, 1));
  8626. }
  8627. {
  8628. auto date = Date(-1998, 8, 31);
  8629. date.add!"months"(13);
  8630. _assertPred!"=="(date, Date(-1997, 10, 1));
  8631. date.add!"months"(-13);
  8632. _assertPred!"=="(date, Date(-1998, 9, 1));
  8633. }
  8634. {
  8635. auto date = Date(-1997, 12, 31);
  8636. date.add!"months"(13);
  8637. _assertPred!"=="(date, Date(-1995, 1, 31));
  8638. date.add!"months"(-13);
  8639. _assertPred!"=="(date, Date(-1997, 12, 31));
  8640. }
  8641. {
  8642. auto date = Date(-1997, 12, 31);
  8643. date.add!"months"(14);
  8644. _assertPred!"=="(date, Date(-1995, 3, 3));
  8645. date.add!"months"(-14);
  8646. _assertPred!"=="(date, Date(-1996, 1, 3));
  8647. }
  8648. {
  8649. auto date = Date(-2002, 12, 31);
  8650. date.add!"months"(14);
  8651. _assertPred!"=="(date, Date(-2000, 3, 2));
  8652. date.add!"months"(-14);
  8653. _assertPred!"=="(date, Date(-2001, 1, 2));
  8654. }
  8655. {
  8656. auto date = Date(-2001, 12, 31);
  8657. date.add!"months"(14);
  8658. _assertPred!"=="(date, Date(-1999, 3, 3));
  8659. date.add!"months"(-14);
  8660. _assertPred!"=="(date, Date(-2000, 1, 3));
  8661. }
  8662. //Test Both
  8663. {
  8664. auto date = Date(1, 1, 1);
  8665. date.add!"months"(-1);
  8666. _assertPred!"=="(date, Date(0, 12, 1));
  8667. date.add!"months"(1);
  8668. _assertPred!"=="(date, Date(1, 1, 1));
  8669. }
  8670. {
  8671. auto date = Date(4, 1, 1);
  8672. date.add!"months"(-48);
  8673. _assertPred!"=="(date, Date(0, 1, 1));
  8674. date.add!"months"(48);
  8675. _assertPred!"=="(date, Date(4, 1, 1));
  8676. }
  8677. {
  8678. auto date = Date(4, 3, 31);
  8679. date.add!"months"(-49);
  8680. _assertPred!"=="(date, Date(0, 3, 2));
  8681. date.add!"months"(49);
  8682. _assertPred!"=="(date, Date(4, 4, 2));
  8683. }
  8684. {
  8685. auto date = Date(4, 3, 31);
  8686. date.add!"months"(-85);
  8687. _assertPred!"=="(date, Date(-3, 3, 3));
  8688. date.add!"months"(85);
  8689. _assertPred!"=="(date, Date(4, 4, 3));
  8690. }
  8691. const cdate = Date(1999, 7, 6);
  8692. immutable idate = Date(1999, 7, 6);
  8693. static assert(!__traits(compiles, cdate.add!"months"(3)));
  8694. static assert(!__traits(compiles, idate.add!"months"(3)));
  8695. }
  8696. }
  8697. //Test add!"months"() with AllowDayOverlow.no
  8698. unittest
  8699. {
  8700. version(testStdDateTime)
  8701. {
  8702. //Test A.D.
  8703. {
  8704. auto date = Date(1999, 7, 6);
  8705. date.add!"months"(3, AllowDayOverflow.no);
  8706. _assertPred!"=="(date, Date(1999, 10, 6));
  8707. date.add!"months"(-4, AllowDayOverflow.no);
  8708. _assertPred!"=="(date, Date(1999, 6, 6));
  8709. }
  8710. {
  8711. auto date = Date(1999, 7, 6);
  8712. date.add!"months"(6, AllowDayOverflow.no);
  8713. _assertPred!"=="(date, Date(2000, 1, 6));
  8714. date.add!"months"(-6, AllowDayOverflow.no);
  8715. _assertPred!"=="(date, Date(1999, 7, 6));
  8716. }
  8717. {
  8718. auto date = Date(1999, 7, 6);
  8719. date.add!"months"(27, AllowDayOverflow.no);
  8720. _assertPred!"=="(date, Date(2001, 10, 6));
  8721. date.add!"months"(-28, AllowDayOverflow.no);
  8722. _assertPred!"=="(date, Date(1999, 6, 6));
  8723. }
  8724. {
  8725. auto date = Date(1999, 5, 31);
  8726. date.add!"months"(1, AllowDayOverflow.no);
  8727. _assertPred!"=="(date, Date(1999, 6, 30));
  8728. }
  8729. {
  8730. auto date = Date(1999, 5, 31);
  8731. date.add!"months"(-1, AllowDayOverflow.no);
  8732. _assertPred!"=="(date, Date(1999, 4, 30));
  8733. }
  8734. {
  8735. auto date = Date(1999, 2, 28);
  8736. date.add!"months"(12, AllowDayOverflow.no);
  8737. _assertPred!"=="(date, Date(2000, 2, 28));
  8738. }
  8739. {
  8740. auto date = Date(2000, 2, 29);
  8741. date.add!"months"(12, AllowDayOverflow.no);
  8742. _assertPred!"=="(date, Date(2001, 2, 28));
  8743. }
  8744. {
  8745. auto date = Date(1999, 7, 31);
  8746. date.add!"months"(1, AllowDayOverflow.no);
  8747. _assertPred!"=="(date, Date(1999, 8, 31));
  8748. date.add!"months"(1, AllowDayOverflow.no);
  8749. _assertPred!"=="(date, Date(1999, 9, 30));
  8750. }
  8751. {
  8752. auto date = Date(1998, 8, 31);
  8753. date.add!"months"(13, AllowDayOverflow.no);
  8754. _assertPred!"=="(date, Date(1999, 9, 30));
  8755. date.add!"months"(-13, AllowDayOverflow.no);
  8756. _assertPred!"=="(date, Date(1998, 8, 30));
  8757. }
  8758. {
  8759. auto date = Date(1997, 12, 31);
  8760. date.add!"months"(13, AllowDayOverflow.no);
  8761. _assertPred!"=="(date, Date(1999, 1, 31));
  8762. date.add!"months"(-13, AllowDayOverflow.no);
  8763. _assertPred!"=="(date, Date(1997, 12, 31));
  8764. }
  8765. {
  8766. auto date = Date(1997, 12, 31);
  8767. date.add!"months"(14, AllowDayOverflow.no);
  8768. _assertPred!"=="(date, Date(1999, 2, 28));
  8769. date.add!"months"(-14, AllowDayOverflow.no);
  8770. _assertPred!"=="(date, Date(1997, 12, 28));
  8771. }
  8772. {
  8773. auto date = Date(1998, 12, 31);
  8774. date.add!"months"(14, AllowDayOverflow.no);
  8775. _assertPred!"=="(date, Date(2000, 2, 29));
  8776. date.add!"months"(-14, AllowDayOverflow.no);
  8777. _assertPred!"=="(date, Date(1998, 12, 29));
  8778. }
  8779. {
  8780. auto date = Date(1999, 12, 31);
  8781. date.add!"months"(14, AllowDayOverflow.no);
  8782. _assertPred!"=="(date, Date(2001, 2, 28));
  8783. date.add!"months"(-14, AllowDayOverflow.no);
  8784. _assertPred!"=="(date, Date(1999, 12, 28));
  8785. }
  8786. //Test B.C.
  8787. {
  8788. auto date = Date(-1999, 7, 6);
  8789. date.add!"months"(3, AllowDayOverflow.no);
  8790. _assertPred!"=="(date, Date(-1999, 10, 6));
  8791. date.add!"months"(-4, AllowDayOverflow.no);
  8792. _assertPred!"=="(date, Date(-1999, 6, 6));
  8793. }
  8794. {
  8795. auto date = Date(-1999, 7, 6);
  8796. date.add!"months"(6, AllowDayOverflow.no);
  8797. _assertPred!"=="(date, Date(-1998, 1, 6));
  8798. date.add!"months"(-6, AllowDayOverflow.no);
  8799. _assertPred!"=="(date, Date(-1999, 7, 6));
  8800. }
  8801. {
  8802. auto date = Date(-1999, 7, 6);
  8803. date.add!"months"(-27, AllowDayOverflow.no);
  8804. _assertPred!"=="(date, Date(-2001, 4, 6));
  8805. date.add!"months"(28, AllowDayOverflow.no);
  8806. _assertPred!"=="(date, Date(-1999, 8, 6));
  8807. }
  8808. {
  8809. auto date = Date(-1999, 5, 31);
  8810. date.add!"months"(1, AllowDayOverflow.no);
  8811. _assertPred!"=="(date, Date(-1999, 6, 30));
  8812. }
  8813. {
  8814. auto date = Date(-1999, 5, 31);
  8815. date.add!"months"(-1, AllowDayOverflow.no);
  8816. _assertPred!"=="(date, Date(-1999, 4, 30));
  8817. }
  8818. {
  8819. auto date = Date(-1999, 2, 28);
  8820. date.add!"months"(-12, AllowDayOverflow.no);
  8821. _assertPred!"=="(date, Date(-2000, 2, 28));
  8822. }
  8823. {
  8824. auto date = Date(-2000, 2, 29);
  8825. date.add!"months"(-12, AllowDayOverflow.no);
  8826. _assertPred!"=="(date, Date(-2001, 2, 28));
  8827. }
  8828. {
  8829. auto date = Date(-1999, 7, 31);
  8830. date.add!"months"(1, AllowDayOverflow.no);
  8831. _assertPred!"=="(date, Date(-1999, 8, 31));
  8832. date.add!"months"(1, AllowDayOverflow.no);
  8833. _assertPred!"=="(date, Date(-1999, 9, 30));
  8834. }
  8835. {
  8836. auto date = Date(-1998, 8, 31);
  8837. date.add!"months"(13, AllowDayOverflow.no);
  8838. _assertPred!"=="(date, Date(-1997, 9, 30));
  8839. date.add!"months"(-13, AllowDayOverflow.no);
  8840. _assertPred!"=="(date, Date(-1998, 8, 30));
  8841. }
  8842. {
  8843. auto date = Date(-1997, 12, 31);
  8844. date.add!"months"(13, AllowDayOverflow.no);
  8845. _assertPred!"=="(date, Date(-1995, 1, 31));
  8846. date.add!"months"(-13, AllowDayOverflow.no);
  8847. _assertPred!"=="(date, Date(-1997, 12, 31));
  8848. }
  8849. {
  8850. auto date = Date(-1997, 12, 31);
  8851. date.add!"months"(14, AllowDayOverflow.no);
  8852. _assertPred!"=="(date, Date(-1995, 2, 28));
  8853. date.add!"months"(-14, AllowDayOverflow.no);
  8854. _assertPred!"=="(date, Date(-1997, 12, 28));
  8855. }
  8856. {
  8857. auto date = Date(-2002, 12, 31);
  8858. date.add!"months"(14, AllowDayOverflow.no);
  8859. _assertPred!"=="(date, Date(-2000, 2, 29));
  8860. date.add!"months"(-14, AllowDayOverflow.no);
  8861. _assertPred!"=="(date, Date(-2002, 12, 29));
  8862. }
  8863. {
  8864. auto date = Date(-2001, 12, 31);
  8865. date.add!"months"(14, AllowDayOverflow.no);
  8866. _assertPred!"=="(date, Date(-1999, 2, 28));
  8867. date.add!"months"(-14, AllowDayOverflow.no);
  8868. _assertPred!"=="(date, Date(-2001, 12, 28));
  8869. }
  8870. //Test Both
  8871. {
  8872. auto date = Date(1, 1, 1);
  8873. date.add!"months"(-1, AllowDayOverflow.no);
  8874. _assertPred!"=="(date, Date(0, 12, 1));
  8875. date.add!"months"(1, AllowDayOverflow.no);
  8876. _assertPred!"=="(date, Date(1, 1, 1));
  8877. }
  8878. {
  8879. auto date = Date(4, 1, 1);
  8880. date.add!"months"(-48, AllowDayOverflow.no);
  8881. _assertPred!"=="(date, Date(0, 1, 1));
  8882. date.add!"months"(48, AllowDayOverflow.no);
  8883. _assertPred!"=="(date, Date(4, 1, 1));
  8884. }
  8885. {
  8886. auto date = Date(4, 3, 31);
  8887. date.add!"months"(-49, AllowDayOverflow.no);
  8888. _assertPred!"=="(date, Date(0, 2, 29));
  8889. date.add!"months"(49, AllowDayOverflow.no);
  8890. _assertPred!"=="(date, Date(4, 3, 29));
  8891. }
  8892. {
  8893. auto date = Date(4, 3, 31);
  8894. date.add!"months"(-85, AllowDayOverflow.no);
  8895. _assertPred!"=="(date, Date(-3, 2, 28));
  8896. date.add!"months"(85, AllowDayOverflow.no);
  8897. _assertPred!"=="(date, Date(4, 3, 28));
  8898. }
  8899. }
  8900. }
  8901. /++
  8902. Adds the given number of years or months to this $(D Date). A negative
  8903. number will subtract.
  8904. The difference between rolling and adding is that rolling does not
  8905. affect larger units. So, if you roll a $(D Date) 12 months, you get
  8906. the exact same $(D Date). However, the days can still be affected due to
  8907. the differing number of days in each month.
  8908. Because there are no units larger than years, there is no difference
  8909. between adding and rolling years.
  8910. Params:
  8911. units = The type of units to add ("years" or "months").
  8912. value = The number of months or years to add to this
  8913. $(D Date).
  8914. Examples:
  8915. --------------------
  8916. auto d1 = Date(2010, 1, 1);
  8917. d1.roll!"months"(1);
  8918. assert(d1 == Date(2010, 2, 1));
  8919. auto d2 = Date(2010, 1, 1);
  8920. d2.roll!"months"(-1);
  8921. assert(d2 == Date(2010, 12, 1));
  8922. auto d3 = Date(1999, 1, 29);
  8923. d3.roll!"months"(1);
  8924. assert(d3 == Date(1999, 3, 1));
  8925. auto d4 = Date(1999, 1, 29);
  8926. d4.roll!"months"(1, AllowDayOverflow.no);
  8927. assert(d4 == Date(1999, 2, 28));
  8928. auto d5 = Date(2000, 2, 29);
  8929. d5.roll!"years"(1);
  8930. assert(d5 == Date(2001, 3, 1));
  8931. auto d6 = Date(2000, 2, 29);
  8932. d6.roll!"years"(1, AllowDayOverflow.no);
  8933. assert(d6 == Date(2001, 2, 28));
  8934. --------------------
  8935. +/
  8936. /+ref Date+/ void roll(string units)(long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) pure nothrow
  8937. if(units == "years")
  8938. {
  8939. add!"years"(value, allowOverflow);
  8940. }
  8941. //Verify Examples.
  8942. unittest
  8943. {
  8944. version(testStdDateTime)
  8945. {
  8946. auto d1 = Date(2010, 1, 1);
  8947. d1.roll!"months"(1);
  8948. assert(d1 == Date(2010, 2, 1));
  8949. auto d2 = Date(2010, 1, 1);
  8950. d2.roll!"months"(-1);
  8951. assert(d2 == Date(2010, 12, 1));
  8952. auto d3 = Date(1999, 1, 29);
  8953. d3.roll!"months"(1);
  8954. assert(d3 == Date(1999, 3, 1));
  8955. auto d4 = Date(1999, 1, 29);
  8956. d4.roll!"months"(1, AllowDayOverflow.no);
  8957. assert(d4 == Date(1999, 2, 28));
  8958. auto d5 = Date(2000, 2, 29);
  8959. d5.roll!"years"(1);
  8960. assert(d5 == Date(2001, 3, 1));
  8961. auto d6 = Date(2000, 2, 29);
  8962. d6.roll!"years"(1, AllowDayOverflow.no);
  8963. assert(d6 == Date(2001, 2, 28));
  8964. }
  8965. }
  8966. unittest
  8967. {
  8968. version(testStdDateTime)
  8969. {
  8970. const cdate = Date(1999, 7, 6);
  8971. immutable idate = Date(1999, 7, 6);
  8972. static assert(!__traits(compiles, cdate.roll!"years"(3)));
  8973. static assert(!__traits(compiles, idate.rolYears(3)));
  8974. }
  8975. }
  8976. //Shares documentation with "years" version.
  8977. /+ref Date+/ void roll(string units)(long months, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) pure nothrow
  8978. if(units == "months")
  8979. {
  8980. months %= 12;
  8981. auto newMonth = _month + months;
  8982. if(months < 0)
  8983. {
  8984. if(newMonth < 1)
  8985. newMonth += 12;
  8986. }
  8987. else
  8988. {
  8989. if(newMonth > 12)
  8990. newMonth -= 12;
  8991. }
  8992. _month = cast(Month)newMonth;
  8993. immutable currMaxDay = maxDay(_year, _month);
  8994. immutable overflow = _day - currMaxDay;
  8995. if(overflow > 0)
  8996. {
  8997. if(allowOverflow == AllowDayOverflow.yes)
  8998. {
  8999. ++_month;
  9000. _day = cast(ubyte)overflow;
  9001. }
  9002. else
  9003. _day = cast(ubyte)currMaxDay;
  9004. }
  9005. }
  9006. //Test roll!"months"() with AllowDayOverlow.yes
  9007. unittest
  9008. {
  9009. version(testStdDateTime)
  9010. {
  9011. //Test A.D.
  9012. {
  9013. auto date = Date(1999, 7, 6);
  9014. date.roll!"months"(3);
  9015. _assertPred!"=="(date, Date(1999, 10, 6));
  9016. date.roll!"months"(-4);
  9017. _assertPred!"=="(date, Date(1999, 6, 6));
  9018. }
  9019. {
  9020. auto date = Date(1999, 7, 6);
  9021. date.roll!"months"(6);
  9022. _assertPred!"=="(date, Date(1999, 1, 6));
  9023. date.roll!"months"(-6);
  9024. _assertPred!"=="(date, Date(1999, 7, 6));
  9025. }
  9026. {
  9027. auto date = Date(1999, 7, 6);
  9028. date.roll!"months"(27);
  9029. _assertPred!"=="(date, Date(1999, 10, 6));
  9030. date.roll!"months"(-28);
  9031. _assertPred!"=="(date, Date(1999, 6, 6));
  9032. }
  9033. {
  9034. auto date = Date(1999, 5, 31);
  9035. date.roll!"months"(1);
  9036. _assertPred!"=="(date, Date(1999, 7, 1));
  9037. }
  9038. {
  9039. auto date = Date(1999, 5, 31);
  9040. date.roll!"months"(-1);
  9041. _assertPred!"=="(date, Date(1999, 5, 1));
  9042. }
  9043. {
  9044. auto date = Date(1999, 2, 28);
  9045. date.roll!"months"(12);
  9046. _assertPred!"=="(date, Date(1999, 2, 28));
  9047. }
  9048. {
  9049. auto date = Date(2000, 2, 29);
  9050. date.roll!"months"(12);
  9051. _assertPred!"=="(date, Date(2000, 2, 29));
  9052. }
  9053. {
  9054. auto date = Date(1999, 7, 31);
  9055. date.roll!"months"(1);
  9056. _assertPred!"=="(date, Date(1999, 8, 31));
  9057. date.roll!"months"(1);
  9058. _assertPred!"=="(date, Date(1999, 10, 1));
  9059. }
  9060. {
  9061. auto date = Date(1998, 8, 31);
  9062. date.roll!"months"(13);
  9063. _assertPred!"=="(date, Date(1998, 10, 1));
  9064. date.roll!"months"(-13);
  9065. _assertPred!"=="(date, Date(1998, 9, 1));
  9066. }
  9067. {
  9068. auto date = Date(1997, 12, 31);
  9069. date.roll!"months"(13);
  9070. _assertPred!"=="(date, Date(1997, 1, 31));
  9071. date.roll!"months"(-13);
  9072. _assertPred!"=="(date, Date(1997, 12, 31));
  9073. }
  9074. {
  9075. auto date = Date(1997, 12, 31);
  9076. date.roll!"months"(14);
  9077. _assertPred!"=="(date, Date(1997, 3, 3));
  9078. date.roll!"months"(-14);
  9079. _assertPred!"=="(date, Date(1997, 1, 3));
  9080. }
  9081. {
  9082. auto date = Date(1998, 12, 31);
  9083. date.roll!"months"(14);
  9084. _assertPred!"=="(date, Date(1998, 3, 3));
  9085. date.roll!"months"(-14);
  9086. _assertPred!"=="(date, Date(1998, 1, 3));
  9087. }
  9088. {
  9089. auto date = Date(1999, 12, 31);
  9090. date.roll!"months"(14);
  9091. _assertPred!"=="(date, Date(1999, 3, 3));
  9092. date.roll!"months"(-14);
  9093. _assertPred!"=="(date, Date(1999, 1, 3));
  9094. }
  9095. //Test B.C.
  9096. {
  9097. auto date = Date(-1999, 7, 6);
  9098. date.roll!"months"(3);
  9099. _assertPred!"=="(date, Date(-1999, 10, 6));
  9100. date.roll!"months"(-4);
  9101. _assertPred!"=="(date, Date(-1999, 6, 6));
  9102. }
  9103. {
  9104. auto date = Date(-1999, 7, 6);
  9105. date.roll!"months"(6);
  9106. _assertPred!"=="(date, Date(-1999, 1, 6));
  9107. date.roll!"months"(-6);
  9108. _assertPred!"=="(date, Date(-1999, 7, 6));
  9109. }
  9110. {
  9111. auto date = Date(-1999, 7, 6);
  9112. date.roll!"months"(-27);
  9113. _assertPred!"=="(date, Date(-1999, 4, 6));
  9114. date.roll!"months"(28);
  9115. _assertPred!"=="(date, Date(-1999, 8, 6));
  9116. }
  9117. {
  9118. auto date = Date(-1999, 5, 31);
  9119. date.roll!"months"(1);
  9120. _assertPred!"=="(date, Date(-1999, 7, 1));
  9121. }
  9122. {
  9123. auto date = Date(-1999, 5, 31);
  9124. date.roll!"months"(-1);
  9125. _assertPred!"=="(date, Date(-1999, 5, 1));
  9126. }
  9127. {
  9128. auto date = Date(-1999, 2, 28);
  9129. date.roll!"months"(-12);
  9130. _assertPred!"=="(date, Date(-1999, 2, 28));
  9131. }
  9132. {
  9133. auto date = Date(-2000, 2, 29);
  9134. date.roll!"months"(-12);
  9135. _assertPred!"=="(date, Date(-2000, 2, 29));
  9136. }
  9137. {
  9138. auto date = Date(-1999, 7, 31);
  9139. date.roll!"months"(1);
  9140. _assertPred!"=="(date, Date(-1999, 8, 31));
  9141. date.roll!"months"(1);
  9142. _assertPred!"=="(date, Date(-1999, 10, 1));
  9143. }
  9144. {
  9145. auto date = Date(-1998, 8, 31);
  9146. date.roll!"months"(13);
  9147. _assertPred!"=="(date, Date(-1998, 10, 1));
  9148. date.roll!"months"(-13);
  9149. _assertPred!"=="(date, Date(-1998, 9, 1));
  9150. }
  9151. {
  9152. auto date = Date(-1997, 12, 31);
  9153. date.roll!"months"(13);
  9154. _assertPred!"=="(date, Date(-1997, 1, 31));
  9155. date.roll!"months"(-13);
  9156. _assertPred!"=="(date, Date(-1997, 12, 31));
  9157. }
  9158. {
  9159. auto date = Date(-1997, 12, 31);
  9160. date.roll!"months"(14);
  9161. _assertPred!"=="(date, Date(-1997, 3, 3));
  9162. date.roll!"months"(-14);
  9163. _assertPred!"=="(date, Date(-1997, 1, 3));
  9164. }
  9165. {
  9166. auto date = Date(-2002, 12, 31);
  9167. date.roll!"months"(14);
  9168. _assertPred!"=="(date, Date(-2002, 3, 3));
  9169. date.roll!"months"(-14);
  9170. _assertPred!"=="(date, Date(-2002, 1, 3));
  9171. }
  9172. {
  9173. auto date = Date(-2001, 12, 31);
  9174. date.roll!"months"(14);
  9175. _assertPred!"=="(date, Date(-2001, 3, 3));
  9176. date.roll!"months"(-14);
  9177. _assertPred!"=="(date, Date(-2001, 1, 3));
  9178. }
  9179. //Test Both
  9180. {
  9181. auto date = Date(1, 1, 1);
  9182. date.roll!"months"(-1);
  9183. _assertPred!"=="(date, Date(1, 12, 1));
  9184. date.roll!"months"(1);
  9185. _assertPred!"=="(date, Date(1, 1, 1));
  9186. }
  9187. {
  9188. auto date = Date(4, 1, 1);
  9189. date.roll!"months"(-48);
  9190. _assertPred!"=="(date, Date(4, 1, 1));
  9191. date.roll!"months"(48);
  9192. _assertPred!"=="(date, Date(4, 1, 1));
  9193. }
  9194. {
  9195. auto date = Date(4, 3, 31);
  9196. date.roll!"months"(-49);
  9197. _assertPred!"=="(date, Date(4, 3, 2));
  9198. date.roll!"months"(49);
  9199. _assertPred!"=="(date, Date(4, 4, 2));
  9200. }
  9201. {
  9202. auto date = Date(4, 3, 31);
  9203. date.roll!"months"(-85);
  9204. _assertPred!"=="(date, Date(4, 3, 2));
  9205. date.roll!"months"(85);
  9206. _assertPred!"=="(date, Date(4, 4, 2));
  9207. }
  9208. {
  9209. auto date = Date(-1, 1, 1);
  9210. date.roll!"months"(-1);
  9211. _assertPred!"=="(date, Date(-1, 12, 1));
  9212. date.roll!"months"(1);
  9213. _assertPred!"=="(date, Date(-1, 1, 1));
  9214. }
  9215. {
  9216. auto date = Date(-4, 1, 1);
  9217. date.roll!"months"(-48);
  9218. _assertPred!"=="(date, Date(-4, 1, 1));
  9219. date.roll!"months"(48);
  9220. _assertPred!"=="(date, Date(-4, 1, 1));
  9221. }
  9222. {
  9223. auto date = Date(-4, 3, 31);
  9224. date.roll!"months"(-49);
  9225. _assertPred!"=="(date, Date(-4, 3, 2));
  9226. date.roll!"months"(49);
  9227. _assertPred!"=="(date, Date(-4, 4, 2));
  9228. }
  9229. {
  9230. auto date = Date(-4, 3, 31);
  9231. date.roll!"months"(-85);
  9232. _assertPred!"=="(date, Date(-4, 3, 2));
  9233. date.roll!"months"(85);
  9234. _assertPred!"=="(date, Date(-4, 4, 2));
  9235. }
  9236. const cdate = Date(1999, 7, 6);
  9237. immutable idate = Date(1999, 7, 6);
  9238. static assert(!__traits(compiles, cdate.roll!"months"(3)));
  9239. static assert(!__traits(compiles, idate.roll!"months"(3)));
  9240. //Verify Examples.
  9241. auto date1 = Date(2010, 1, 1);
  9242. date1.roll!"months"(1);
  9243. assert(date1 == Date(2010, 2, 1));
  9244. auto date2 = Date(2010, 1, 1);
  9245. date2.roll!"months"(-1);
  9246. assert(date2 == Date(2010, 12, 1));
  9247. auto date3 = Date(1999, 1, 29);
  9248. date3.roll!"months"(1);
  9249. assert(date3 == Date(1999, 3, 1));
  9250. auto date4 = Date(1999, 1, 29);
  9251. date4.roll!"months"(1, AllowDayOverflow.no);
  9252. assert(date4 == Date(1999, 2, 28));
  9253. }
  9254. }
  9255. //Test roll!"months"() with AllowDayOverlow.no
  9256. unittest
  9257. {
  9258. version(testStdDateTime)
  9259. {
  9260. //Test A.D.
  9261. {
  9262. auto date = Date(1999, 7, 6);
  9263. date.roll!"months"(3, AllowDayOverflow.no);
  9264. _assertPred!"=="(date, Date(1999, 10, 6));
  9265. date.roll!"months"(-4, AllowDayOverflow.no);
  9266. _assertPred!"=="(date, Date(1999, 6, 6));
  9267. }
  9268. {
  9269. auto date = Date(1999, 7, 6);
  9270. date.roll!"months"(6, AllowDayOverflow.no);
  9271. _assertPred!"=="(date, Date(1999, 1, 6));
  9272. date.roll!"months"(-6, AllowDayOverflow.no);
  9273. _assertPred!"=="(date, Date(1999, 7, 6));
  9274. }
  9275. {
  9276. auto date = Date(1999, 7, 6);
  9277. date.roll!"months"(27, AllowDayOverflow.no);
  9278. _assertPred!"=="(date, Date(1999, 10, 6));
  9279. date.roll!"months"(-28, AllowDayOverflow.no);
  9280. _assertPred!"=="(date, Date(1999, 6, 6));
  9281. }
  9282. {
  9283. auto date = Date(1999, 5, 31);
  9284. date.roll!"months"(1, AllowDayOverflow.no);
  9285. _assertPred!"=="(date, Date(1999, 6, 30));
  9286. }
  9287. {
  9288. auto date = Date(1999, 5, 31);
  9289. date.roll!"months"(-1, AllowDayOverflow.no);
  9290. _assertPred!"=="(date, Date(1999, 4, 30));
  9291. }
  9292. {
  9293. auto date = Date(1999, 2, 28);
  9294. date.roll!"months"(12, AllowDayOverflow.no);
  9295. _assertPred!"=="(date, Date(1999, 2, 28));
  9296. }
  9297. {
  9298. auto date = Date(2000, 2, 29);
  9299. date.roll!"months"(12, AllowDayOverflow.no);
  9300. _assertPred!"=="(date, Date(2000, 2, 29));
  9301. }
  9302. {
  9303. auto date = Date(1999, 7, 31);
  9304. date.roll!"months"(1, AllowDayOverflow.no);
  9305. _assertPred!"=="(date, Date(1999, 8, 31));
  9306. date.roll!"months"(1, AllowDayOverflow.no);
  9307. _assertPred!"=="(date, Date(1999, 9, 30));
  9308. }
  9309. {
  9310. auto date = Date(1998, 8, 31);
  9311. date.roll!"months"(13, AllowDayOverflow.no);
  9312. _assertPred!"=="(date, Date(1998, 9, 30));
  9313. date.roll!"months"(-13, AllowDayOverflow.no);
  9314. _assertPred!"=="(date, Date(1998, 8, 30));
  9315. }
  9316. {
  9317. auto date = Date(1997, 12, 31);
  9318. date.roll!"months"(13, AllowDayOverflow.no);
  9319. _assertPred!"=="(date, Date(1997, 1, 31));
  9320. date.roll!"months"(-13, AllowDayOverflow.no);
  9321. _assertPred!"=="(date, Date(1997, 12, 31));
  9322. }
  9323. {
  9324. auto date = Date(1997, 12, 31);
  9325. date.roll!"months"(14, AllowDayOverflow.no);
  9326. _assertPred!"=="(date, Date(1997, 2, 28));
  9327. date.roll!"months"(-14, AllowDayOverflow.no);
  9328. _assertPred!"=="(date, Date(1997, 12, 28));
  9329. }
  9330. {
  9331. auto date = Date(1998, 12, 31);
  9332. date.roll!"months"(14, AllowDayOverflow.no);
  9333. _assertPred!"=="(date, Date(1998, 2, 28));
  9334. date.roll!"months"(-14, AllowDayOverflow.no);
  9335. _assertPred!"=="(date, Date(1998, 12, 28));
  9336. }
  9337. {
  9338. auto date = Date(1999, 12, 31);
  9339. date.roll!"months"(14, AllowDayOverflow.no);
  9340. _assertPred!"=="(date, Date(1999, 2, 28));
  9341. date.roll!"months"(-14, AllowDayOverflow.no);
  9342. _assertPred!"=="(date, Date(1999, 12, 28));
  9343. }
  9344. //Test B.C.
  9345. {
  9346. auto date = Date(-1999, 7, 6);
  9347. date.roll!"months"(3, AllowDayOverflow.no);
  9348. _assertPred!"=="(date, Date(-1999, 10, 6));
  9349. date.roll!"months"(-4, AllowDayOverflow.no);
  9350. _assertPred!"=="(date, Date(-1999, 6, 6));
  9351. }
  9352. {
  9353. auto date = Date(-1999, 7, 6);
  9354. date.roll!"months"(6, AllowDayOverflow.no);
  9355. _assertPred!"=="(date, Date(-1999, 1, 6));
  9356. date.roll!"months"(-6, AllowDayOverflow.no);
  9357. _assertPred!"=="(date, Date(-1999, 7, 6));
  9358. }
  9359. {
  9360. auto date = Date(-1999, 7, 6);
  9361. date.roll!"months"(-27, AllowDayOverflow.no);
  9362. _assertPred!"=="(date, Date(-1999, 4, 6));
  9363. date.roll!"months"(28, AllowDayOverflow.no);
  9364. _assertPred!"=="(date, Date(-1999, 8, 6));
  9365. }
  9366. {
  9367. auto date = Date(-1999, 5, 31);
  9368. date.roll!"months"(1, AllowDayOverflow.no);
  9369. _assertPred!"=="(date, Date(-1999, 6, 30));
  9370. }
  9371. {
  9372. auto date = Date(-1999, 5, 31);
  9373. date.roll!"months"(-1, AllowDayOverflow.no);
  9374. _assertPred!"=="(date, Date(-1999, 4, 30));
  9375. }
  9376. {
  9377. auto date = Date(-1999, 2, 28);
  9378. date.roll!"months"(-12, AllowDayOverflow.no);
  9379. _assertPred!"=="(date, Date(-1999, 2, 28));
  9380. }
  9381. {
  9382. auto date = Date(-2000, 2, 29);
  9383. date.roll!"months"(-12, AllowDayOverflow.no);
  9384. _assertPred!"=="(date, Date(-2000, 2, 29));
  9385. }
  9386. {
  9387. auto date = Date(-1999, 7, 31);
  9388. date.roll!"months"(1, AllowDayOverflow.no);
  9389. _assertPred!"=="(date, Date(-1999, 8, 31));
  9390. date.roll!"months"(1, AllowDayOverflow.no);
  9391. _assertPred!"=="(date, Date(-1999, 9, 30));
  9392. }
  9393. {
  9394. auto date = Date(-1998, 8, 31);
  9395. date.roll!"months"(13, AllowDayOverflow.no);
  9396. _assertPred!"=="(date, Date(-1998, 9, 30));
  9397. date.roll!"months"(-13, AllowDayOverflow.no);
  9398. _assertPred!"=="(date, Date(-1998, 8, 30));
  9399. }
  9400. {
  9401. auto date = Date(-1997, 12, 31);
  9402. date.roll!"months"(13, AllowDayOverflow.no);
  9403. _assertPred!"=="(date, Date(-1997, 1, 31));
  9404. date.roll!"months"(-13, AllowDayOverflow.no);
  9405. _assertPred!"=="(date, Date(-1997, 12, 31));
  9406. }
  9407. {
  9408. auto date = Date(-1997, 12, 31);
  9409. date.roll!"months"(14, AllowDayOverflow.no);
  9410. _assertPred!"=="(date, Date(-1997, 2, 28));
  9411. date.roll!"months"(-14, AllowDayOverflow.no);
  9412. _assertPred!"=="(date, Date(-1997, 12, 28));
  9413. }
  9414. {
  9415. auto date = Date(-2002, 12, 31);
  9416. date.roll!"months"(14, AllowDayOverflow.no);
  9417. _assertPred!"=="(date, Date(-2002, 2, 28));
  9418. date.roll!"months"(-14, AllowDayOverflow.no);
  9419. _assertPred!"=="(date, Date(-2002, 12, 28));
  9420. }
  9421. {
  9422. auto date = Date(-2001, 12, 31);
  9423. date.roll!"months"(14, AllowDayOverflow.no);
  9424. _assertPred!"=="(date, Date(-2001, 2, 28));
  9425. date.roll!"months"(-14, AllowDayOverflow.no);
  9426. _assertPred!"=="(date, Date(-2001, 12, 28));
  9427. }
  9428. //Test Both
  9429. {
  9430. auto date = Date(1, 1, 1);
  9431. date.roll!"months"(-1, AllowDayOverflow.no);
  9432. _assertPred!"=="(date, Date(1, 12, 1));
  9433. date.roll!"months"(1, AllowDayOverflow.no);
  9434. _assertPred!"=="(date, Date(1, 1, 1));
  9435. }
  9436. {
  9437. auto date = Date(4, 1, 1);
  9438. date.roll!"months"(-48, AllowDayOverflow.no);
  9439. _assertPred!"=="(date, Date(4, 1, 1));
  9440. date.roll!"months"(48, AllowDayOverflow.no);
  9441. _assertPred!"=="(date, Date(4, 1, 1));
  9442. }
  9443. {
  9444. auto date = Date(4, 3, 31);
  9445. date.roll!"months"(-49, AllowDayOverflow.no);
  9446. _assertPred!"=="(date, Date(4, 2, 29));
  9447. date.roll!"months"(49, AllowDayOverflow.no);
  9448. _assertPred!"=="(date, Date(4, 3, 29));
  9449. }
  9450. {
  9451. auto date = Date(4, 3, 31);
  9452. date.roll!"months"(-85, AllowDayOverflow.no);
  9453. _assertPred!"=="(date, Date(4, 2, 29));
  9454. date.roll!"months"(85, AllowDayOverflow.no);
  9455. _assertPred!"=="(date, Date(4, 3, 29));
  9456. }
  9457. {
  9458. auto date = Date(-1, 1, 1);
  9459. date.roll!"months"(-1, AllowDayOverflow.no);
  9460. _assertPred!"=="(date, Date(-1, 12, 1));
  9461. date.roll!"months"(1, AllowDayOverflow.no);
  9462. _assertPred!"=="(date, Date(-1, 1, 1));
  9463. }
  9464. {
  9465. auto date = Date(-4, 1, 1);
  9466. date.roll!"months"(-48, AllowDayOverflow.no);
  9467. _assertPred!"=="(date, Date(-4, 1, 1));
  9468. date.roll!"months"(48, AllowDayOverflow.no);
  9469. _assertPred!"=="(date, Date(-4, 1, 1));
  9470. }
  9471. {
  9472. auto date = Date(-4, 3, 31);
  9473. date.roll!"months"(-49, AllowDayOverflow.no);
  9474. _assertPred!"=="(date, Date(-4, 2, 29));
  9475. date.roll!"months"(49, AllowDayOverflow.no);
  9476. _assertPred!"=="(date, Date(-4, 3, 29));
  9477. }
  9478. {
  9479. auto date = Date(-4, 3, 31);
  9480. date.roll!"months"(-85, AllowDayOverflow.no);
  9481. _assertPred!"=="(date, Date(-4, 2, 29));
  9482. date.roll!"months"(85, AllowDayOverflow.no);
  9483. _assertPred!"=="(date, Date(-4, 3, 29));
  9484. }
  9485. }
  9486. }
  9487. /++
  9488. Adds the given number of units to this $(D Date). A negative number will
  9489. subtract.
  9490. The difference between rolling and adding is that rolling does not
  9491. affect larger units. So, for instance, if you roll a $(D Date) one
  9492. year's worth of days, then you get the exact same $(D Date).
  9493. The only accepted units are $(D "days").
  9494. Params:
  9495. units = The units to add. Must be $(D "days").
  9496. value = The number of days to add to this $(D Date).
  9497. Examples:
  9498. --------------------
  9499. auto d = Date(2010, 1, 1);
  9500. d.roll!"days"(1);
  9501. assert(d == Date(2010, 1, 2));
  9502. d.roll!"days"(365);
  9503. assert(d == Date(2010, 1, 26));
  9504. d.roll!"days"(-32);
  9505. assert(d == Date(2010, 1, 25));
  9506. --------------------
  9507. +/
  9508. /+ref Date+/ void roll(string units)(long days) pure nothrow
  9509. if(units == "days")
  9510. {
  9511. immutable limit = maxDay(_year, _month);
  9512. days %= limit;
  9513. auto newDay = _day + days;
  9514. if(days < 0)
  9515. {
  9516. if(newDay < 1)
  9517. newDay += limit;
  9518. }
  9519. else if(newDay > limit)
  9520. newDay -= limit;
  9521. _day = cast(ubyte)newDay;
  9522. }
  9523. //Verify Examples.
  9524. unittest
  9525. {
  9526. version(testStdDateTime)
  9527. {
  9528. auto d = Date(2010, 1, 1);
  9529. d.roll!"days"(1);
  9530. assert(d == Date(2010, 1, 2));
  9531. d.roll!"days"(365);
  9532. assert(d == Date(2010, 1, 26));
  9533. d.roll!"days"(-32);
  9534. assert(d == Date(2010, 1, 25));
  9535. }
  9536. }
  9537. unittest
  9538. {
  9539. version(testStdDateTime)
  9540. {
  9541. //Test A.D.
  9542. {
  9543. auto date = Date(1999, 2, 28);
  9544. date.roll!"days"(1);
  9545. _assertPred!"=="(date, Date(1999, 2, 1));
  9546. date.roll!"days"(-1);
  9547. _assertPred!"=="(date, Date(1999, 2, 28));
  9548. }
  9549. {
  9550. auto date = Date(2000, 2, 28);
  9551. date.roll!"days"(1);
  9552. _assertPred!"=="(date, Date(2000, 2, 29));
  9553. date.roll!"days"(1);
  9554. _assertPred!"=="(date, Date(2000, 2, 1));
  9555. date.roll!"days"(-1);
  9556. _assertPred!"=="(date, Date(2000, 2, 29));
  9557. }
  9558. {
  9559. auto date = Date(1999, 6, 30);
  9560. date.roll!"days"(1);
  9561. _assertPred!"=="(date, Date(1999, 6, 1));
  9562. date.roll!"days"(-1);
  9563. _assertPred!"=="(date, Date(1999, 6, 30));
  9564. }
  9565. {
  9566. auto date = Date(1999, 7, 31);
  9567. date.roll!"days"(1);
  9568. _assertPred!"=="(date, Date(1999, 7, 1));
  9569. date.roll!"days"(-1);
  9570. _assertPred!"=="(date, Date(1999, 7, 31));
  9571. }
  9572. {
  9573. auto date = Date(1999, 1, 1);
  9574. date.roll!"days"(-1);
  9575. _assertPred!"=="(date, Date(1999, 1, 31));
  9576. date.roll!"days"(1);
  9577. _assertPred!"=="(date, Date(1999, 1, 1));
  9578. }
  9579. {
  9580. auto date = Date(1999, 7, 6);
  9581. date.roll!"days"(9);
  9582. _assertPred!"=="(date, Date(1999, 7, 15));
  9583. date.roll!"days"(-11);
  9584. _assertPred!"=="(date, Date(1999, 7, 4));
  9585. date.roll!"days"(30);
  9586. _assertPred!"=="(date, Date(1999, 7, 3));
  9587. date.roll!"days"(-3);
  9588. _assertPred!"=="(date, Date(1999, 7, 31));
  9589. }
  9590. {
  9591. auto date = Date(1999, 7, 6);
  9592. date.roll!"days"(365);
  9593. _assertPred!"=="(date, Date(1999, 7, 30));
  9594. date.roll!"days"(-365);
  9595. _assertPred!"=="(date, Date(1999, 7, 6));
  9596. date.roll!"days"(366);
  9597. _assertPred!"=="(date, Date(1999, 7, 31));
  9598. date.roll!"days"(730);
  9599. _assertPred!"=="(date, Date(1999, 7, 17));
  9600. date.roll!"days"(-1096);
  9601. _assertPred!"=="(date, Date(1999, 7, 6));
  9602. }
  9603. {
  9604. auto date = Date(1999, 2, 6);
  9605. date.roll!"days"(365);
  9606. _assertPred!"=="(date, Date(1999, 2, 7));
  9607. date.roll!"days"(-365);
  9608. _assertPred!"=="(date, Date(1999, 2, 6));
  9609. date.roll!"days"(366);
  9610. _assertPred!"=="(date, Date(1999, 2, 8));
  9611. date.roll!"days"(730);
  9612. _assertPred!"=="(date, Date(1999, 2, 10));
  9613. date.roll!"days"(-1096);
  9614. _assertPred!"=="(date, Date(1999, 2, 6));
  9615. }
  9616. //Test B.C.
  9617. {
  9618. auto date = Date(-1999, 2, 28);
  9619. date.roll!"days"(1);
  9620. _assertPred!"=="(date, Date(-1999, 2, 1));
  9621. date.roll!"days"(-1);
  9622. _assertPred!"=="(date, Date(-1999, 2, 28));
  9623. }
  9624. {
  9625. auto date = Date(-2000, 2, 28);
  9626. date.roll!"days"(1);
  9627. _assertPred!"=="(date, Date(-2000, 2, 29));
  9628. date.roll!"days"(1);
  9629. _assertPred!"=="(date, Date(-2000, 2, 1));
  9630. date.roll!"days"(-1);
  9631. _assertPred!"=="(date, Date(-2000, 2, 29));
  9632. }
  9633. {
  9634. auto date = Date(-1999, 6, 30);
  9635. date.roll!"days"(1);
  9636. _assertPred!"=="(date, Date(-1999, 6, 1));
  9637. date.roll!"days"(-1);
  9638. _assertPred!"=="(date, Date(-1999, 6, 30));
  9639. }
  9640. {
  9641. auto date = Date(-1999, 7, 31);
  9642. date.roll!"days"(1);
  9643. _assertPred!"=="(date, Date(-1999, 7, 1));
  9644. date.roll!"days"(-1);
  9645. _assertPred!"=="(date, Date(-1999, 7, 31));
  9646. }
  9647. {
  9648. auto date = Date(-1999, 1, 1);
  9649. date.roll!"days"(-1);
  9650. _assertPred!"=="(date, Date(-1999, 1, 31));
  9651. date.roll!"days"(1);
  9652. _assertPred!"=="(date, Date(-1999, 1, 1));
  9653. }
  9654. {
  9655. auto date = Date(-1999, 7, 6);
  9656. date.roll!"days"(9);
  9657. _assertPred!"=="(date, Date(-1999, 7, 15));
  9658. date.roll!"days"(-11);
  9659. _assertPred!"=="(date, Date(-1999, 7, 4));
  9660. date.roll!"days"(30);
  9661. _assertPred!"=="(date, Date(-1999, 7, 3));
  9662. date.roll!"days"(-3);
  9663. _assertPred!"=="(date, Date(-1999, 7, 31));
  9664. }
  9665. {
  9666. auto date = Date(-1999, 7, 6);
  9667. date.roll!"days"(365);
  9668. _assertPred!"=="(date, Date(-1999, 7, 30));
  9669. date.roll!"days"(-365);
  9670. _assertPred!"=="(date, Date(-1999, 7, 6));
  9671. date.roll!"days"(366);
  9672. _assertPred!"=="(date, Date(-1999, 7, 31));
  9673. date.roll!"days"(730);
  9674. _assertPred!"=="(date, Date(-1999, 7, 17));
  9675. date.roll!"days"(-1096);
  9676. _assertPred!"=="(date, Date(-1999, 7, 6));
  9677. }
  9678. //Test Both
  9679. {
  9680. auto date = Date(1, 7, 6);
  9681. date.roll!"days"(-365);
  9682. _assertPred!"=="(date, Date(1, 7, 13));
  9683. date.roll!"days"(365);
  9684. _assertPred!"=="(date, Date(1, 7, 6));
  9685. date.roll!"days"(-731);
  9686. _assertPred!"=="(date, Date(1, 7, 19));
  9687. date.roll!"days"(730);
  9688. _assertPred!"=="(date, Date(1, 7, 5));
  9689. }
  9690. {
  9691. auto date = Date(0, 7, 6);
  9692. date.roll!"days"(-365);
  9693. _assertPred!"=="(date, Date(0, 7, 13));
  9694. date.roll!"days"(365);
  9695. _assertPred!"=="(date, Date(0, 7, 6));
  9696. date.roll!"days"(-731);
  9697. _assertPred!"=="(date, Date(0, 7, 19));
  9698. date.roll!"days"(730);
  9699. _assertPred!"=="(date, Date(0, 7, 5));
  9700. }
  9701. const cdate = Date(1999, 7, 6);
  9702. immutable idate = Date(1999, 7, 6);
  9703. static assert(!__traits(compiles, cdate.roll!"days"(12)));
  9704. static assert(!__traits(compiles, idate.roll!"days"(12)));
  9705. //Verify Examples.
  9706. auto date = Date(2010, 1, 1);
  9707. date.roll!"days"(1);
  9708. assert(date == Date(2010, 1, 2));
  9709. date.roll!"days"(365);
  9710. assert(date == Date(2010, 1, 26));
  9711. date.roll!"days"(-32);
  9712. assert(date == Date(2010, 1, 25));
  9713. }
  9714. }
  9715. /++
  9716. Gives the result of adding or subtracting a duration from this
  9717. $(D Date).
  9718. The legal types of arithmetic for Date using this operator are
  9719. $(BOOKTABLE,
  9720. $(TR $(TD Date) $(TD +) $(TD duration) $(TD -->) $(TD Date))
  9721. $(TR $(TD Date) $(TD -) $(TD duration) $(TD -->) $(TD Date))
  9722. )
  9723. Params:
  9724. duration = The duration to add to or subtract from this $(D Date).
  9725. +/
  9726. Date opBinary(string op, D)(in D duration) const pure nothrow
  9727. if((op == "+" || op == "-") &&
  9728. (is(Unqual!D == Duration) ||
  9729. is(Unqual!D == TickDuration)))
  9730. {
  9731. Date retval = this;
  9732. static if(is(Unqual!D == Duration))
  9733. immutable days = duration.total!"days";
  9734. else static if(is(Unqual!D == TickDuration))
  9735. immutable days = convert!("hnsecs", "days")(duration.hnsecs);
  9736. //Ideally, this would just be
  9737. //return retval.addDays(unaryFun!(op ~ "a")(days));
  9738. //But there isn't currently a pure version of unaryFun!().
  9739. static if(op == "+")
  9740. immutable signedDays = days;
  9741. else static if(op == "-")
  9742. immutable signedDays = -days;
  9743. else
  9744. static assert(0);
  9745. return retval.addDays(signedDays);
  9746. }
  9747. unittest
  9748. {
  9749. version(testStdDateTime)
  9750. {
  9751. auto date = Date(1999, 7, 6);
  9752. _assertPred!"=="(date + dur!"weeks"(7), Date(1999, 8, 24));
  9753. _assertPred!"=="(date + dur!"weeks"(-7), Date(1999, 5, 18));
  9754. _assertPred!"=="(date + dur!"days"(7), Date(1999, 7, 13));
  9755. _assertPred!"=="(date + dur!"days"(-7), Date(1999, 6, 29));
  9756. _assertPred!"=="(date + dur!"hours"(24), Date(1999, 7, 7));
  9757. _assertPred!"=="(date + dur!"hours"(-24), Date(1999, 7, 5));
  9758. _assertPred!"=="(date + dur!"minutes"(1440), Date(1999, 7, 7));
  9759. _assertPred!"=="(date + dur!"minutes"(-1440), Date(1999, 7, 5));
  9760. _assertPred!"=="(date + dur!"seconds"(86_400), Date(1999, 7, 7));
  9761. _assertPred!"=="(date + dur!"seconds"(-86_400), Date(1999, 7, 5));
  9762. _assertPred!"=="(date + dur!"msecs"(86_400_000), Date(1999, 7, 7));
  9763. _assertPred!"=="(date + dur!"msecs"(-86_400_000), Date(1999, 7, 5));
  9764. _assertPred!"=="(date + dur!"usecs"(86_400_000_000), Date(1999, 7, 7));
  9765. _assertPred!"=="(date + dur!"usecs"(-86_400_000_000), Date(1999, 7, 5));
  9766. _assertPred!"=="(date + dur!"hnsecs"(864_000_000_000), Date(1999, 7, 7));
  9767. _assertPred!"=="(date + dur!"hnsecs"(-864_000_000_000), Date(1999, 7, 5));
  9768. //This probably only runs in cases where gettimeofday() is used, but it's
  9769. //hard to do this test correctly with variable ticksPerSec.
  9770. if(TickDuration.ticksPerSec == 1_000_000)
  9771. {
  9772. _assertPred!"=="(date + TickDuration.from!"usecs"(86_400_000_000), Date(1999, 7, 7));
  9773. _assertPred!"=="(date + TickDuration.from!"usecs"(-86_400_000_000), Date(1999, 7, 5));
  9774. }
  9775. _assertPred!"=="(date - dur!"weeks"(-7), Date(1999, 8, 24));
  9776. _assertPred!"=="(date - dur!"weeks"(7), Date(1999, 5, 18));
  9777. _assertPred!"=="(date - dur!"days"(-7), Date(1999, 7, 13));
  9778. _assertPred!"=="(date - dur!"days"(7), Date(1999, 6, 29));
  9779. _assertPred!"=="(date - dur!"hours"(-24), Date(1999, 7, 7));
  9780. _assertPred!"=="(date - dur!"hours"(24), Date(1999, 7, 5));
  9781. _assertPred!"=="(date - dur!"minutes"(-1440), Date(1999, 7, 7));
  9782. _assertPred!"=="(date - dur!"minutes"(1440), Date(1999, 7, 5));
  9783. _assertPred!"=="(date - dur!"seconds"(-86_400), Date(1999, 7, 7));
  9784. _assertPred!"=="(date - dur!"seconds"(86_400), Date(1999, 7, 5));
  9785. _assertPred!"=="(date - dur!"msecs"(-86_400_000), Date(1999, 7, 7));
  9786. _assertPred!"=="(date - dur!"msecs"(86_400_000), Date(1999, 7, 5));
  9787. _assertPred!"=="(date - dur!"usecs"(-86_400_000_000), Date(1999, 7, 7));
  9788. _assertPred!"=="(date - dur!"usecs"(86_400_000_000), Date(1999, 7, 5));
  9789. _assertPred!"=="(date - dur!"hnsecs"(-864_000_000_000), Date(1999, 7, 7));
  9790. _assertPred!"=="(date - dur!"hnsecs"(864_000_000_000), Date(1999, 7, 5));
  9791. //This probably only runs in cases where gettimeofday() is used, but it's
  9792. //hard to do this test correctly with variable ticksPerSec.
  9793. if(TickDuration.ticksPerSec == 1_000_000)
  9794. {
  9795. _assertPred!"=="(date - TickDuration.from!"usecs"(-86_400_000_000), Date(1999, 7, 7));
  9796. _assertPred!"=="(date - TickDuration.from!"usecs"(86_400_000_000), Date(1999, 7, 5));
  9797. }
  9798. auto duration = dur!"days"(12);
  9799. const cdate = Date(1999, 7, 6);
  9800. immutable idate = Date(1999, 7, 6);
  9801. static assert(__traits(compiles, date + duration));
  9802. static assert(__traits(compiles, cdate + duration));
  9803. static assert(__traits(compiles, idate + duration));
  9804. static assert(__traits(compiles, date - duration));
  9805. static assert(__traits(compiles, cdate - duration));
  9806. static assert(__traits(compiles, idate - duration));
  9807. }
  9808. }
  9809. /++
  9810. Gives the result of adding or subtracting a duration from this
  9811. $(D Date), as well as assigning the result to this $(D Date).
  9812. The legal types of arithmetic for $(D Date) using this operator are
  9813. $(BOOKTABLE,
  9814. $(TR $(TD Date) $(TD +) $(TD duration) $(TD -->) $(TD Date))
  9815. $(TR $(TD Date) $(TD -) $(TD duration) $(TD -->) $(TD Date))
  9816. )
  9817. Params:
  9818. duration = The duration to add to or subtract from this $(D Date).
  9819. +/
  9820. /+ref+/ Date opOpAssign(string op, D)(in D duration) pure nothrow
  9821. if((op == "+" || op == "-") &&
  9822. (is(Unqual!D == Duration) ||
  9823. is(Unqual!D == TickDuration)))
  9824. {
  9825. static if(is(Unqual!D == Duration))
  9826. immutable days = duration.total!"days";
  9827. else static if(is(Unqual!D == TickDuration))
  9828. immutable days = convert!("hnsecs", "days")(duration.hnsecs);
  9829. //Ideally, this would just be
  9830. //return addDays(unaryFun!(op ~ "a")(days));
  9831. //But there isn't currently a pure version of unaryFun!().
  9832. static if(op == "+")
  9833. immutable signedDays = days;
  9834. else static if(op == "-")
  9835. immutable signedDays = -days;
  9836. else
  9837. static assert(0);
  9838. return addDays(signedDays);
  9839. }
  9840. unittest
  9841. {
  9842. version(testStdDateTime)
  9843. {
  9844. _assertPred!"+="(Date(1999, 7, 6), dur!"weeks"(7), Date(1999, 8, 24));
  9845. _assertPred!"+="(Date(1999, 7, 6), dur!"weeks"(-7), Date(1999, 5, 18));
  9846. _assertPred!"+="(Date(1999, 7, 6), dur!"days"(7), Date(1999, 7, 13));
  9847. _assertPred!"+="(Date(1999, 7, 6), dur!"days"(-7), Date(1999, 6, 29));
  9848. _assertPred!"+="(Date(1999, 7, 6), dur!"hours"(24), Date(1999, 7, 7));
  9849. _assertPred!"+="(Date(1999, 7, 6), dur!"hours"(-24), Date(1999, 7, 5));
  9850. _assertPred!"+="(Date(1999, 7, 6), dur!"minutes"(1440), Date(1999, 7, 7));
  9851. _assertPred!"+="(Date(1999, 7, 6), dur!"minutes"(-1440), Date(1999, 7, 5));
  9852. _assertPred!"+="(Date(1999, 7, 6), dur!"seconds"(86_400), Date(1999, 7, 7));
  9853. _assertPred!"+="(Date(1999, 7, 6), dur!"seconds"(-86_400), Date(1999, 7, 5));
  9854. _assertPred!"+="(Date(1999, 7, 6), dur!"msecs"(86_400_000), Date(1999, 7, 7));
  9855. _assertPred!"+="(Date(1999, 7, 6), dur!"msecs"(-86_400_000), Date(1999, 7, 5));
  9856. _assertPred!"+="(Date(1999, 7, 6), dur!"usecs"(86_400_000_000), Date(1999, 7, 7));
  9857. _assertPred!"+="(Date(1999, 7, 6), dur!"usecs"(-86_400_000_000), Date(1999, 7, 5));
  9858. _assertPred!"+="(Date(1999, 7, 6), dur!"hnsecs"(864_000_000_000), Date(1999, 7, 7));
  9859. _assertPred!"+="(Date(1999, 7, 6), dur!"hnsecs"(-864_000_000_000), Date(1999, 7, 5));
  9860. _assertPred!"-="(Date(1999, 7, 6), dur!"weeks"(-7), Date(1999, 8, 24));
  9861. _assertPred!"-="(Date(1999, 7, 6), dur!"weeks"(7), Date(1999, 5, 18));
  9862. _assertPred!"-="(Date(1999, 7, 6), dur!"days"(-7), Date(1999, 7, 13));
  9863. _assertPred!"-="(Date(1999, 7, 6), dur!"days"(7), Date(1999, 6, 29));
  9864. _assertPred!"-="(Date(1999, 7, 6), dur!"hours"(-24), Date(1999, 7, 7));
  9865. _assertPred!"-="(Date(1999, 7, 6), dur!"hours"(24), Date(1999, 7, 5));
  9866. _assertPred!"-="(Date(1999, 7, 6), dur!"minutes"(-1440), Date(1999, 7, 7));
  9867. _assertPred!"-="(Date(1999, 7, 6), dur!"minutes"(1440), Date(1999, 7, 5));
  9868. _assertPred!"-="(Date(1999, 7, 6), dur!"seconds"(-86_400), Date(1999, 7, 7));
  9869. _assertPred!"-="(Date(1999, 7, 6), dur!"seconds"(86_400), Date(1999, 7, 5));
  9870. _assertPred!"-="(Date(1999, 7, 6), dur!"msecs"(-86_400_000), Date(1999, 7, 7));
  9871. _assertPred!"-="(Date(1999, 7, 6), dur!"msecs"(86_400_000), Date(1999, 7, 5));
  9872. _assertPred!"-="(Date(1999, 7, 6), dur!"usecs"(-86_400_000_000), Date(1999, 7, 7));
  9873. _assertPred!"-="(Date(1999, 7, 6), dur!"usecs"(86_400_000_000), Date(1999, 7, 5));
  9874. _assertPred!"-="(Date(1999, 7, 6), dur!"hnsecs"(-864_000_000_000), Date(1999, 7, 7));
  9875. _assertPred!"-="(Date(1999, 7, 6), dur!"hnsecs"(864_000_000_000), Date(1999, 7, 5));
  9876. auto duration = dur!"days"(12);
  9877. auto date = Date(1999, 7, 6);
  9878. const cdate = Date(1999, 7, 6);
  9879. immutable idate = Date(1999, 7, 6);
  9880. static assert(__traits(compiles, date += duration));
  9881. static assert(!__traits(compiles, cdate += duration));
  9882. static assert(!__traits(compiles, idate += duration));
  9883. static assert(__traits(compiles, date -= duration));
  9884. static assert(!__traits(compiles, cdate -= duration));
  9885. static assert(!__traits(compiles, idate -= duration));
  9886. }
  9887. }
  9888. /++
  9889. Gives the difference between two $(D Date)s.
  9890. The legal types of arithmetic for Date using this operator are
  9891. $(BOOKTABLE,
  9892. $(TR $(TD Date) $(TD -) $(TD Date) $(TD -->) $(TD duration))
  9893. )
  9894. +/
  9895. Duration opBinary(string op)(in Date rhs) const pure nothrow
  9896. if(op == "-")
  9897. {
  9898. return dur!"days"(this.dayOfGregorianCal - rhs.dayOfGregorianCal);
  9899. }
  9900. unittest
  9901. {
  9902. version(testStdDateTime)
  9903. {
  9904. auto date = Date(1999, 7, 6);
  9905. _assertPred!"=="(Date(1999, 7, 6) - Date(1998, 7, 6), dur!"days"(365));
  9906. _assertPred!"=="(Date(1998, 7, 6) - Date(1999, 7, 6), dur!"days"(-365));
  9907. _assertPred!"=="(Date(1999, 6, 6) - Date(1999, 5, 6), dur!"days"(31));
  9908. _assertPred!"=="(Date(1999, 5, 6) - Date(1999, 6, 6), dur!"days"(-31));
  9909. _assertPred!"=="(Date(1999, 1, 1) - Date(1998, 12, 31), dur!"days"(1));
  9910. _assertPred!"=="(Date(1998, 12, 31) - Date(1999, 1, 1), dur!"days"(-1));
  9911. const cdate = Date(1999, 7, 6);
  9912. immutable idate = Date(1999, 7, 6);
  9913. static assert(__traits(compiles, date - date));
  9914. static assert(__traits(compiles, cdate - date));
  9915. static assert(__traits(compiles, idate - date));
  9916. static assert(__traits(compiles, date - cdate));
  9917. static assert(__traits(compiles, cdate - cdate));
  9918. static assert(__traits(compiles, idate - cdate));
  9919. static assert(__traits(compiles, date - idate));
  9920. static assert(__traits(compiles, cdate - idate));
  9921. static assert(__traits(compiles, idate - idate));
  9922. }
  9923. }
  9924. /++
  9925. Returns the difference between the two $(D Date)s in months.
  9926. You can get the difference in years by subtracting the year property
  9927. of two $(D Date)s, and you can get the difference in days or weeks by
  9928. subtracting the $(D Date)s themselves and using the $(D Duration) that
  9929. results, but because you cannot convert between months and smaller units
  9930. without a specific date (which $(D Duration)s don't have), you cannot
  9931. get the difference in months without doing some math using both the year
  9932. and month properties, so this is a convenience function for getting the
  9933. difference in months.
  9934. Note that the number of days in the months or how far into the month
  9935. either $(D Date) is is irrelevant. It is the difference in the month
  9936. property combined with the difference in years * 12. So, for instance,
  9937. December 31st and January 1st are one month apart just as December 1st
  9938. and January 31st are one month apart.
  9939. Params:
  9940. rhs = The $(D Date) to subtract from this one.
  9941. Examples:
  9942. --------------------
  9943. assert(Date(1999, 2, 1).diffMonths(Date(1999, 1, 31)) == 1);
  9944. assert(Date(1999, 1, 31).diffMonths(Date(1999, 2, 1)) == -1);
  9945. assert(Date(1999, 3, 1).diffMonths(Date(1999, 1, 1)) == 2);
  9946. assert(Date(1999, 1, 1).diffMonths(Date(1999, 3, 31)) == -2);
  9947. --------------------
  9948. +/
  9949. int diffMonths(in Date rhs) const pure nothrow
  9950. {
  9951. immutable yearDiff = _year - rhs._year;
  9952. immutable monthDiff = _month - rhs._month;
  9953. return yearDiff * 12 + monthDiff;
  9954. }
  9955. unittest
  9956. {
  9957. version(testStdDateTime)
  9958. {
  9959. auto date = Date(1999, 7, 6);
  9960. //Test A.D.
  9961. _assertPred!"=="(date.diffMonths(Date(1998, 6, 5)), 13);
  9962. _assertPred!"=="(date.diffMonths(Date(1998, 7, 5)), 12);
  9963. _assertPred!"=="(date.diffMonths(Date(1998, 8, 5)), 11);
  9964. _assertPred!"=="(date.diffMonths(Date(1998, 9, 5)), 10);
  9965. _assertPred!"=="(date.diffMonths(Date(1998, 10, 5)), 9);
  9966. _assertPred!"=="(date.diffMonths(Date(1998, 11, 5)), 8);
  9967. _assertPred!"=="(date.diffMonths(Date(1998, 12, 5)), 7);
  9968. _assertPred!"=="(date.diffMonths(Date(1999, 1, 5)), 6);
  9969. _assertPred!"=="(date.diffMonths(Date(1999, 2, 6)), 5);
  9970. _assertPred!"=="(date.diffMonths(Date(1999, 3, 6)), 4);
  9971. _assertPred!"=="(date.diffMonths(Date(1999, 4, 6)), 3);
  9972. _assertPred!"=="(date.diffMonths(Date(1999, 5, 6)), 2);
  9973. _assertPred!"=="(date.diffMonths(Date(1999, 6, 6)), 1);
  9974. _assertPred!"=="(date.diffMonths(date), 0);
  9975. _assertPred!"=="(date.diffMonths(Date(1999, 8, 6)), -1);
  9976. _assertPred!"=="(date.diffMonths(Date(1999, 9, 6)), -2);
  9977. _assertPred!"=="(date.diffMonths(Date(1999, 10, 6)), -3);
  9978. _assertPred!"=="(date.diffMonths(Date(1999, 11, 6)), -4);
  9979. _assertPred!"=="(date.diffMonths(Date(1999, 12, 6)), -5);
  9980. _assertPred!"=="(date.diffMonths(Date(2000, 1, 6)), -6);
  9981. _assertPred!"=="(date.diffMonths(Date(2000, 2, 6)), -7);
  9982. _assertPred!"=="(date.diffMonths(Date(2000, 3, 6)), -8);
  9983. _assertPred!"=="(date.diffMonths(Date(2000, 4, 6)), -9);
  9984. _assertPred!"=="(date.diffMonths(Date(2000, 5, 6)), -10);
  9985. _assertPred!"=="(date.diffMonths(Date(2000, 6, 6)), -11);
  9986. _assertPred!"=="(date.diffMonths(Date(2000, 7, 6)), -12);
  9987. _assertPred!"=="(date.diffMonths(Date(2000, 8, 6)), -13);
  9988. _assertPred!"=="(Date(1998, 6, 5).diffMonths(date), -13);
  9989. _assertPred!"=="(Date(1998, 7, 5).diffMonths(date), -12);
  9990. _assertPred!"=="(Date(1998, 8, 5).diffMonths(date), -11);
  9991. _assertPred!"=="(Date(1998, 9, 5).diffMonths(date), -10);
  9992. _assertPred!"=="(Date(1998, 10, 5).diffMonths(date), -9);
  9993. _assertPred!"=="(Date(1998, 11, 5).diffMonths(date), -8);
  9994. _assertPred!"=="(Date(1998, 12, 5).diffMonths(date), -7);
  9995. _assertPred!"=="(Date(1999, 1, 5).diffMonths(date), -6);
  9996. _assertPred!"=="(Date(1999, 2, 6).diffMonths(date), -5);
  9997. _assertPred!"=="(Date(1999, 3, 6).diffMonths(date), -4);
  9998. _assertPred!"=="(Date(1999, 4, 6).diffMonths(date), -3);
  9999. _assertPred!"=="(Date(1999, 5, 6).diffMonths(date), -2);
  10000. _assertPred!"=="(Date(1999, 6, 6).diffMonths(date), -1);
  10001. _assertPred!"=="(Date(1999, 8, 6).diffMonths(date), 1);
  10002. _assertPred!"=="(Date(1999, 9, 6).diffMonths(date), 2);
  10003. _assertPred!"=="(Date(1999, 10, 6).diffMonths(date), 3);
  10004. _assertPred!"=="(Date(1999, 11, 6).diffMonths(date), 4);
  10005. _assertPred!"=="(Date(1999, 12, 6).diffMonths(date), 5);
  10006. _assertPred!"=="(Date(2000, 1, 6).diffMonths(date), 6);
  10007. _assertPred!"=="(Date(2000, 2, 6).diffMonths(date), 7);
  10008. _assertPred!"=="(Date(2000, 3, 6).diffMonths(date), 8);
  10009. _assertPred!"=="(Date(2000, 4, 6).diffMonths(date), 9);
  10010. _assertPred!"=="(Date(2000, 5, 6).diffMonths(date), 10);
  10011. _assertPred!"=="(Date(2000, 6, 6).diffMonths(date), 11);
  10012. _assertPred!"=="(Date(2000, 7, 6).diffMonths(date), 12);
  10013. _assertPred!"=="(Date(2000, 8, 6).diffMonths(date), 13);
  10014. _assertPred!"=="(date.diffMonths(Date(1999, 6, 30)), 1);
  10015. _assertPred!"=="(date.diffMonths(Date(1999, 7, 1)), 0);
  10016. _assertPred!"=="(date.diffMonths(Date(1999, 7, 6)), 0);
  10017. _assertPred!"=="(date.diffMonths(Date(1999, 7, 11)), 0);
  10018. _assertPred!"=="(date.diffMonths(Date(1999, 7, 16)), 0);
  10019. _assertPred!"=="(date.diffMonths(Date(1999, 7, 21)), 0);
  10020. _assertPred!"=="(date.diffMonths(Date(1999, 7, 26)), 0);
  10021. _assertPred!"=="(date.diffMonths(Date(1999, 7, 31)), 0);
  10022. _assertPred!"=="(date.diffMonths(Date(1999, 8, 1)), -1);
  10023. _assertPred!"=="(date.diffMonths(Date(1990, 6, 30)), 109);
  10024. _assertPred!"=="(date.diffMonths(Date(1990, 7, 1)), 108);
  10025. _assertPred!"=="(date.diffMonths(Date(1990, 7, 6)), 108);
  10026. _assertPred!"=="(date.diffMonths(Date(1990, 7, 11)), 108);
  10027. _assertPred!"=="(date.diffMonths(Date(1990, 7, 16)), 108);
  10028. _assertPred!"=="(date.diffMonths(Date(1990, 7, 21)), 108);
  10029. _assertPred!"=="(date.diffMonths(Date(1990, 7, 26)), 108);
  10030. _assertPred!"=="(date.diffMonths(Date(1990, 7, 31)), 108);
  10031. _assertPred!"=="(date.diffMonths(Date(1990, 8, 1)), 107);
  10032. _assertPred!"=="(Date(1999, 6, 30).diffMonths(date), -1);
  10033. _assertPred!"=="(Date(1999, 7, 1).diffMonths(date), 0);
  10034. _assertPred!"=="(Date(1999, 7, 6).diffMonths(date), 0);
  10035. _assertPred!"=="(Date(1999, 7, 11).diffMonths(date), 0);
  10036. _assertPred!"=="(Date(1999, 7, 16).diffMonths(date), 0);
  10037. _assertPred!"=="(Date(1999, 7, 21).diffMonths(date), 0);
  10038. _assertPred!"=="(Date(1999, 7, 26).diffMonths(date), 0);
  10039. _assertPred!"=="(Date(1999, 7, 31).diffMonths(date), 0);
  10040. _assertPred!"=="(Date(1999, 8, 1).diffMonths(date), 1);
  10041. _assertPred!"=="(Date(1990, 6, 30).diffMonths(date), -109);
  10042. _assertPred!"=="(Date(1990, 7, 1).diffMonths(date), -108);
  10043. _assertPred!"=="(Date(1990, 7, 6).diffMonths(date), -108);
  10044. _assertPred!"=="(Date(1990, 7, 11).diffMonths(date), -108);
  10045. _assertPred!"=="(Date(1990, 7, 16).diffMonths(date), -108);
  10046. _assertPred!"=="(Date(1990, 7, 21).diffMonths(date), -108);
  10047. _assertPred!"=="(Date(1990, 7, 26).diffMonths(date), -108);
  10048. _assertPred!"=="(Date(1990, 7, 31).diffMonths(date), -108);
  10049. _assertPred!"=="(Date(1990, 8, 1).diffMonths(date), -107);
  10050. //Test B.C.
  10051. auto dateBC = Date(-1999, 7, 6);
  10052. _assertPred!"=="(dateBC.diffMonths(Date(-2000, 6, 5)), 13);
  10053. _assertPred!"=="(dateBC.diffMonths(Date(-2000, 7, 5)), 12);
  10054. _assertPred!"=="(dateBC.diffMonths(Date(-2000, 8, 5)), 11);
  10055. _assertPred!"=="(dateBC.diffMonths(Date(-2000, 9, 5)), 10);
  10056. _assertPred!"=="(dateBC.diffMonths(Date(-2000, 10, 5)), 9);
  10057. _assertPred!"=="(dateBC.diffMonths(Date(-2000, 11, 5)), 8);
  10058. _assertPred!"=="(dateBC.diffMonths(Date(-2000, 12, 5)), 7);
  10059. _assertPred!"=="(dateBC.diffMonths(Date(-1999, 1, 5)), 6);
  10060. _assertPred!"=="(dateBC.diffMonths(Date(-1999, 2, 6)), 5);
  10061. _assertPred!"=="(dateBC.diffMonths(Date(-1999, 3, 6)), 4);
  10062. _assertPred!"=="(dateBC.diffMonths(Date(-1999, 4, 6)), 3);
  10063. _assertPred!"=="(dateBC.diffMonths(Date(-1999, 5, 6)), 2);
  10064. _assertPred!"=="(dateBC.diffMonths(Date(-1999, 6, 6)), 1);
  10065. _assertPred!"=="(dateBC.diffMonths(dateBC), 0);
  10066. _assertPred!"=="(dateBC.diffMonths(Date(-1999, 8, 6)), -1);
  10067. _assertPred!"=="(dateBC.diffMonths(Date(-1999, 9, 6)), -2);
  10068. _assertPred!"=="(dateBC.diffMonths(Date(-1999, 10, 6)), -3);
  10069. _assertPred!"=="(dateBC.diffMonths(Date(-1999, 11, 6)), -4);
  10070. _assertPred!"=="(dateBC.diffMonths(Date(-1999, 12, 6)), -5);
  10071. _assertPred!"=="(dateBC.diffMonths(Date(-1998, 1, 6)), -6);
  10072. _assertPred!"=="(dateBC.diffMonths(Date(-1998, 2, 6)), -7);
  10073. _assertPred!"=="(dateBC.diffMonths(Date(-1998, 3, 6)), -8);
  10074. _assertPred!"=="(dateBC.diffMonths(Date(-1998, 4, 6)), -9);
  10075. _assertPred!"=="(dateBC.diffMonths(Date(-1998, 5, 6)), -10);
  10076. _assertPred!"=="(dateBC.diffMonths(Date(-1998, 6, 6)), -11);
  10077. _assertPred!"=="(dateBC.diffMonths(Date(-1998, 7, 6)), -12);
  10078. _assertPred!"=="(dateBC.diffMonths(Date(-1998, 8, 6)), -13);
  10079. _assertPred!"=="(Date(-2000, 6, 5).diffMonths(dateBC), -13);
  10080. _assertPred!"=="(Date(-2000, 7, 5).diffMonths(dateBC), -12);
  10081. _assertPred!"=="(Date(-2000, 8, 5).diffMonths(dateBC), -11);
  10082. _assertPred!"=="(Date(-2000, 9, 5).diffMonths(dateBC), -10);
  10083. _assertPred!"=="(Date(-2000, 10, 5).diffMonths(dateBC), -9);
  10084. _assertPred!"=="(Date(-2000, 11, 5).diffMonths(dateBC), -8);
  10085. _assertPred!"=="(Date(-2000, 12, 5).diffMonths(dateBC), -7);
  10086. _assertPred!"=="(Date(-1999, 1, 5).diffMonths(dateBC), -6);
  10087. _assertPred!"=="(Date(-1999, 2, 6).diffMonths(dateBC), -5);
  10088. _assertPred!"=="(Date(-1999, 3, 6).diffMonths(dateBC), -4);
  10089. _assertPred!"=="(Date(-1999, 4, 6).diffMonths(dateBC), -3);
  10090. _assertPred!"=="(Date(-1999, 5, 6).diffMonths(dateBC), -2);
  10091. _assertPred!"=="(Date(-1999, 6, 6).diffMonths(dateBC), -1);
  10092. _assertPred!"=="(Date(-1999, 8, 6).diffMonths(dateBC), 1);
  10093. _assertPred!"=="(Date(-1999, 9, 6).diffMonths(dateBC), 2);
  10094. _assertPred!"=="(Date(-1999, 10, 6).diffMonths(dateBC), 3);
  10095. _assertPred!"=="(Date(-1999, 11, 6).diffMonths(dateBC), 4);
  10096. _assertPred!"=="(Date(-1999, 12, 6).diffMonths(dateBC), 5);
  10097. _assertPred!"=="(Date(-1998, 1, 6).diffMonths(dateBC), 6);
  10098. _assertPred!"=="(Date(-1998, 2, 6).diffMonths(dateBC), 7);
  10099. _assertPred!"=="(Date(-1998, 3, 6).diffMonths(dateBC), 8);
  10100. _assertPred!"=="(Date(-1998, 4, 6).diffMonths(dateBC), 9);
  10101. _assertPred!"=="(Date(-1998, 5, 6).diffMonths(dateBC), 10);
  10102. _assertPred!"=="(Date(-1998, 6, 6).diffMonths(dateBC), 11);
  10103. _assertPred!"=="(Date(-1998, 7, 6).diffMonths(dateBC), 12);
  10104. _assertPred!"=="(Date(-1998, 8, 6).diffMonths(dateBC), 13);
  10105. _assertPred!"=="(dateBC.diffMonths(Date(-1999, 6, 30)), 1);
  10106. _assertPred!"=="(dateBC.diffMonths(Date(-1999, 7, 1)), 0);
  10107. _assertPred!"=="(dateBC.diffMonths(Date(-1999, 7, 6)), 0);
  10108. _assertPred!"=="(dateBC.diffMonths(Date(-1999, 7, 11)), 0);
  10109. _assertPred!"=="(dateBC.diffMonths(Date(-1999, 7, 16)), 0);
  10110. _assertPred!"=="(dateBC.diffMonths(Date(-1999, 7, 21)), 0);
  10111. _assertPred!"=="(dateBC.diffMonths(Date(-1999, 7, 26)), 0);
  10112. _assertPred!"=="(dateBC.diffMonths(Date(-1999, 7, 31)), 0);
  10113. _assertPred!"=="(dateBC.diffMonths(Date(-1999, 8, 1)), -1);
  10114. _assertPred!"=="(dateBC.diffMonths(Date(-2008, 6, 30)), 109);
  10115. _assertPred!"=="(dateBC.diffMonths(Date(-2008, 7, 1)), 108);
  10116. _assertPred!"=="(dateBC.diffMonths(Date(-2008, 7, 6)), 108);
  10117. _assertPred!"=="(dateBC.diffMonths(Date(-2008, 7, 11)), 108);
  10118. _assertPred!"=="(dateBC.diffMonths(Date(-2008, 7, 16)), 108);
  10119. _assertPred!"=="(dateBC.diffMonths(Date(-2008, 7, 21)), 108);
  10120. _assertPred!"=="(dateBC.diffMonths(Date(-2008, 7, 26)), 108);
  10121. _assertPred!"=="(dateBC.diffMonths(Date(-2008, 7, 31)), 108);
  10122. _assertPred!"=="(dateBC.diffMonths(Date(-2008, 8, 1)), 107);
  10123. _assertPred!"=="(Date(-1999, 6, 30).diffMonths(dateBC), -1);
  10124. _assertPred!"=="(Date(-1999, 7, 1).diffMonths(dateBC), 0);
  10125. _assertPred!"=="(Date(-1999, 7, 6).diffMonths(dateBC), 0);
  10126. _assertPred!"=="(Date(-1999, 7, 11).diffMonths(dateBC), 0);
  10127. _assertPred!"=="(Date(-1999, 7, 16).diffMonths(dateBC), 0);
  10128. _assertPred!"=="(Date(-1999, 7, 21).diffMonths(dateBC), 0);
  10129. _assertPred!"=="(Date(-1999, 7, 26).diffMonths(dateBC), 0);
  10130. _assertPred!"=="(Date(-1999, 7, 31).diffMonths(dateBC), 0);
  10131. _assertPred!"=="(Date(-1999, 8, 1).diffMonths(dateBC), 1);
  10132. _assertPred!"=="(Date(-2008, 6, 30).diffMonths(dateBC), -109);
  10133. _assertPred!"=="(Date(-2008, 7, 1).diffMonths(dateBC), -108);
  10134. _assertPred!"=="(Date(-2008, 7, 6).diffMonths(dateBC), -108);
  10135. _assertPred!"=="(Date(-2008, 7, 11).diffMonths(dateBC), -108);
  10136. _assertPred!"=="(Date(-2008, 7, 16).diffMonths(dateBC), -108);
  10137. _assertPred!"=="(Date(-2008, 7, 21).diffMonths(dateBC), -108);
  10138. _assertPred!"=="(Date(-2008, 7, 26).diffMonths(dateBC), -108);
  10139. _assertPred!"=="(Date(-2008, 7, 31).diffMonths(dateBC), -108);
  10140. _assertPred!"=="(Date(-2008, 8, 1).diffMonths(dateBC), -107);
  10141. //Test Both
  10142. _assertPred!"=="(Date(3, 3, 3).diffMonths(Date(-5, 5, 5)), 94);
  10143. _assertPred!"=="(Date(-5, 5, 5).diffMonths(Date(3, 3, 3)), -94);
  10144. const cdate = Date(1999, 7, 6);
  10145. immutable idate = Date(1999, 7, 6);
  10146. static assert(__traits(compiles, date.diffMonths(date)));
  10147. static assert(__traits(compiles, cdate.diffMonths(date)));
  10148. static assert(__traits(compiles, idate.diffMonths(date)));
  10149. static assert(__traits(compiles, date.diffMonths(cdate)));
  10150. static assert(__traits(compiles, cdate.diffMonths(cdate)));
  10151. static assert(__traits(compiles, idate.diffMonths(cdate)));
  10152. static assert(__traits(compiles, date.diffMonths(idate)));
  10153. static assert(__traits(compiles, cdate.diffMonths(idate)));
  10154. static assert(__traits(compiles, idate.diffMonths(idate)));
  10155. //Verify Examples.
  10156. assert(Date(1999, 2, 1).diffMonths(Date(1999, 1, 31)) == 1);
  10157. assert(Date(1999, 1, 31).diffMonths(Date(1999, 2, 1)) == -1);
  10158. assert(Date(1999, 3, 1).diffMonths(Date(1999, 1, 1)) == 2);
  10159. assert(Date(1999, 1, 1).diffMonths(Date(1999, 3, 31)) == -2);
  10160. }
  10161. }
  10162. /++
  10163. Whether this $(D Date) is in a leap year.
  10164. +/
  10165. @property bool isLeapYear() const pure nothrow
  10166. {
  10167. return yearIsLeapYear(_year);
  10168. }
  10169. unittest
  10170. {
  10171. version(testStdDateTime)
  10172. {
  10173. auto date = Date(1999, 7, 6);
  10174. const cdate = Date(1999, 7, 6);
  10175. immutable idate = Date(1999, 7, 6);
  10176. static assert(!__traits(compiles, date.isLeapYear = true));
  10177. static assert(!__traits(compiles, cdate.isLeapYear = true));
  10178. static assert(!__traits(compiles, idate.isLeapYear = true));
  10179. }
  10180. }
  10181. /++
  10182. Day of the week this $(D Date) is on.
  10183. +/
  10184. @property DayOfWeek dayOfWeek() const pure nothrow
  10185. {
  10186. return getDayOfWeek(dayOfGregorianCal);
  10187. }
  10188. unittest
  10189. {
  10190. version(testStdDateTime)
  10191. {
  10192. const cdate = Date(1999, 7, 6);
  10193. immutable idate = Date(1999, 7, 6);
  10194. static assert(__traits(compiles, cdate.dayOfWeek == DayOfWeek.sun));
  10195. static assert(!__traits(compiles, cdate.dayOfWeek = DayOfWeek.sun));
  10196. static assert(__traits(compiles, idate.dayOfWeek == DayOfWeek.sun));
  10197. static assert(!__traits(compiles, idate.dayOfWeek = DayOfWeek.sun));
  10198. }
  10199. }
  10200. /++
  10201. Day of the year this $(D Date) is on.
  10202. Examples:
  10203. --------------------
  10204. assert(Date(1999, 1, 1).dayOfYear == 1);
  10205. assert(Date(1999, 12, 31).dayOfYear == 365);
  10206. assert(Date(2000, 12, 31).dayOfYear == 366);
  10207. --------------------
  10208. +/
  10209. @property ushort dayOfYear() const pure nothrow
  10210. {
  10211. switch(_month)
  10212. {
  10213. case Month.jan:
  10214. return _day;
  10215. case Month.feb:
  10216. return cast(ushort)(31 + _day);
  10217. case Month.mar:
  10218. return cast(ushort)((isLeapYear ? 60 : 59) + _day);
  10219. case Month.apr:
  10220. return cast(ushort)((isLeapYear ? 91 : 90) + _day);
  10221. case Month.may:
  10222. return cast(ushort)((isLeapYear ? 121 : 120) + _day);
  10223. case Month.jun:
  10224. return cast(ushort)((isLeapYear ? 152 : 151) + _day);
  10225. case Month.jul:
  10226. return cast(ushort)((isLeapYear ? 182 : 181) + _day);
  10227. case Month.aug:
  10228. return cast(ushort)((isLeapYear ? 213 : 212) + _day);
  10229. case Month.sep:
  10230. return cast(ushort)((isLeapYear ? 244 : 243) + _day);
  10231. case Month.oct:
  10232. return cast(ushort)((isLeapYear ? 274 : 273) + _day);
  10233. case Month.nov:
  10234. return cast(ushort)((isLeapYear ? 305 : 304) + _day);
  10235. case Month.dec:
  10236. return cast(ushort)((isLeapYear ? 335 : 334) + _day);
  10237. default:
  10238. assert(0, "Invalid month.");
  10239. }
  10240. }
  10241. //Verify Examples.
  10242. version(testStdDateTime) unittest
  10243. {
  10244. assert(Date(1999, 1, 1).dayOfYear == 1);
  10245. assert(Date(1999, 12, 31).dayOfYear == 365);
  10246. assert(Date(2000, 12, 31).dayOfYear == 366);
  10247. }
  10248. version(testStdDateTime) unittest
  10249. {
  10250. foreach(year; filter!((a){return !yearIsLeapYear(a);})
  10251. (chain(testYearsBC, testYearsAD)))
  10252. {
  10253. foreach(doy; testDaysOfYear)
  10254. {
  10255. _assertPred!"=="(Date(year, doy.md.month, doy.md.day).dayOfYear,
  10256. doy.day);
  10257. }
  10258. }
  10259. foreach(year; filter!((a){return yearIsLeapYear(a);})
  10260. (chain(testYearsBC, testYearsAD)))
  10261. {
  10262. foreach(doy; testDaysOfLeapYear)
  10263. {
  10264. _assertPred!"=="(Date(year, doy.md.month, doy.md.day).dayOfYear,
  10265. doy.day);
  10266. }
  10267. }
  10268. const cdate = Date(1999, 7, 6);
  10269. immutable idate = Date(1999, 7, 6);
  10270. static assert(__traits(compiles, cdate.dayOfYear == 187));
  10271. static assert(__traits(compiles, idate.dayOfYear == 187));
  10272. }
  10273. /++
  10274. Day of the year.
  10275. Params:
  10276. day = The day of the year to set which day of the year this
  10277. $(D Date) is on.
  10278. Throws:
  10279. $(D DateTimeException) if the given day is an invalid day of the
  10280. year.
  10281. +/
  10282. @property void dayOfYear(int day) pure
  10283. {
  10284. if(isLeapYear)
  10285. {
  10286. if(day <= 0 || day > daysInLeapYear)
  10287. throw new DateTimeException("Invalid day of the year.");
  10288. switch(day)
  10289. {
  10290. case 1: .. case 31:
  10291. {
  10292. _month = Month.jan;
  10293. _day = cast(ubyte)day;
  10294. break;
  10295. }
  10296. case 32: .. case 60:
  10297. {
  10298. _month = Month.feb;
  10299. _day = cast(ubyte)(day - 31);
  10300. break;
  10301. }
  10302. case 61: .. case 91:
  10303. {
  10304. _month = Month.mar;
  10305. _day = cast(ubyte)(day - 60);
  10306. break;
  10307. }
  10308. case 92: .. case 121:
  10309. {
  10310. _month = Month.apr;
  10311. _day = cast(ubyte)(day - 91);
  10312. break;
  10313. }
  10314. case 122: .. case 152:
  10315. {
  10316. _month = Month.may;
  10317. _day = cast(ubyte)(day - 121);
  10318. break;
  10319. }
  10320. case 153: .. case 182:
  10321. {
  10322. _month = Month.jun;
  10323. _day = cast(ubyte)(day - 152);
  10324. break;
  10325. }
  10326. case 183: .. case 213:
  10327. {
  10328. _month = Month.jul;
  10329. _day = cast(ubyte)(day - 182);
  10330. break;
  10331. }
  10332. case 214: .. case 244:
  10333. {
  10334. _month = Month.aug;
  10335. _day = cast(ubyte)(day - 213);
  10336. break;
  10337. }
  10338. case 245: .. case 274:
  10339. {
  10340. _month = Month.sep;
  10341. _day = cast(ubyte)(day - 244);
  10342. break;
  10343. }
  10344. case 275: .. case 305:
  10345. {
  10346. _month = Month.oct;
  10347. _day = cast(ubyte)(day - 274);
  10348. break;
  10349. }
  10350. case 306: .. case 335:
  10351. {
  10352. _month = Month.nov;
  10353. _day = cast(ubyte)(day - 305);
  10354. break;
  10355. }
  10356. case 336: .. case 366:
  10357. {
  10358. _month = Month.dec;
  10359. _day = cast(ubyte)(day - 335);
  10360. break;
  10361. }
  10362. default:
  10363. assert(0, "Invalid day of the year.");
  10364. }
  10365. }
  10366. else
  10367. {
  10368. if(day <= 0 || day > daysInYear)
  10369. throw new DateTimeException("Invalid day of the year.");
  10370. switch(day)
  10371. {
  10372. case 1: .. case 31:
  10373. {
  10374. _month = Month.jan;
  10375. _day = cast(ubyte)day;
  10376. break;
  10377. }
  10378. case 32: .. case 59:
  10379. {
  10380. _month = Month.feb;
  10381. _day = cast(ubyte)(day - 31);
  10382. break;
  10383. }
  10384. case 60: .. case 90:
  10385. {
  10386. _month = Month.mar;
  10387. _day = cast(ubyte)(day - 59);
  10388. break;
  10389. }
  10390. case 91: .. case 120:
  10391. {
  10392. _month = Month.apr;
  10393. _day = cast(ubyte)(day - 90);
  10394. break;
  10395. }
  10396. case 121: .. case 151:
  10397. {
  10398. _month = Month.may;
  10399. _day = cast(ubyte)(day - 120);
  10400. break;
  10401. }
  10402. case 152: .. case 181:
  10403. {
  10404. _month = Month.jun;
  10405. _day = cast(ubyte)(day - 151);
  10406. break;
  10407. }
  10408. case 182: .. case 212:
  10409. {
  10410. _month = Month.jul;
  10411. _day = cast(ubyte)(day - 181);
  10412. break;
  10413. }
  10414. case 213: .. case 243:
  10415. {
  10416. _month = Month.aug;
  10417. _day = cast(ubyte)(day - 212);
  10418. break;
  10419. }
  10420. case 244: .. case 273:
  10421. {
  10422. _month = Month.sep;
  10423. _day = cast(ubyte)(day - 243);
  10424. break;
  10425. }
  10426. case 274: .. case 304:
  10427. {
  10428. _month = Month.oct;
  10429. _day = cast(ubyte)(day - 273);
  10430. break;
  10431. }
  10432. case 305: .. case 334:
  10433. {
  10434. _month = Month.nov;
  10435. _day = cast(ubyte)(day - 304);
  10436. break;
  10437. }
  10438. case 335: .. case 365:
  10439. {
  10440. _month = Month.dec;
  10441. _day = cast(ubyte)(day - 334);
  10442. break;
  10443. }
  10444. default:
  10445. assert(0, "Invalid day of the year.");
  10446. }
  10447. }
  10448. }
  10449. version(testStdDateTime) unittest
  10450. {
  10451. static void test(Date date, int day, MonthDay expected, size_t line = __LINE__)
  10452. {
  10453. date.dayOfYear = day;
  10454. _assertPred!"=="(date.month, expected.month, "", __FILE__, line);
  10455. _assertPred!"=="(date.day, expected.day, "", __FILE__, line);
  10456. }
  10457. foreach(doy; testDaysOfYear)
  10458. {
  10459. test(Date(1999, 1, 1), doy.day, doy.md);
  10460. test(Date(-1, 1, 1), doy.day, doy.md);
  10461. }
  10462. foreach(doy; testDaysOfLeapYear)
  10463. {
  10464. test(Date(2000, 1, 1), doy.day, doy.md);
  10465. test(Date(-4, 1, 1), doy.day, doy.md);
  10466. }
  10467. const cdate = Date(1999, 7, 6);
  10468. immutable idate = Date(1999, 7, 6);
  10469. static assert(!__traits(compiles, cdate.dayOfYear = 187));
  10470. static assert(!__traits(compiles, idate.dayOfYear = 187));
  10471. }
  10472. /++
  10473. The Xth day of the Gregorian Calendar that this $(D Date) is on.
  10474. Examples:
  10475. --------------------
  10476. assert(Date(1, 1, 1).dayOfGregorianCal == 1);
  10477. assert(Date(1, 12, 31).dayOfGregorianCal == 365);
  10478. assert(Date(2, 1, 1).dayOfGregorianCal == 366);
  10479. assert(Date(0, 12, 31).dayOfGregorianCal == 0);
  10480. assert(Date(0, 1, 1).dayOfGregorianCal == -365);
  10481. assert(Date(-1, 12, 31).dayOfGregorianCal == -366);
  10482. assert(Date(2000, 1, 1).dayOfGregorianCal == 730_120);
  10483. assert(Date(2010, 12, 31).dayOfGregorianCal == 734_137);
  10484. --------------------
  10485. +/
  10486. @property int dayOfGregorianCal() const pure nothrow
  10487. {
  10488. if(isAD)
  10489. {
  10490. if(_year == 1)
  10491. return dayOfYear;
  10492. int years = _year - 1;
  10493. auto days = (years / 400) * daysIn400Years;
  10494. years %= 400;
  10495. days += (years / 100) * daysIn100Years;
  10496. years %= 100;
  10497. days += (years / 4) * daysIn4Years;
  10498. years %= 4;
  10499. days += years * daysInYear;
  10500. days += dayOfYear;
  10501. return days;
  10502. }
  10503. else if(_year == 0)
  10504. return dayOfYear - daysInLeapYear;
  10505. else
  10506. {
  10507. int years = _year;
  10508. auto days = (years / 400) * daysIn400Years;
  10509. years %= 400;
  10510. days += (years / 100) * daysIn100Years;
  10511. years %= 100;
  10512. days += (years / 4) * daysIn4Years;
  10513. years %= 4;
  10514. if(years < 0)
  10515. {
  10516. days -= daysInLeapYear;
  10517. ++years;
  10518. days += years * daysInYear;
  10519. days -= daysInYear - dayOfYear;
  10520. }
  10521. else
  10522. days -= daysInLeapYear - dayOfYear;
  10523. return days;
  10524. }
  10525. }
  10526. //Verify Examples.
  10527. version(testStdDateTime) unittest
  10528. {
  10529. assert(Date(1, 1, 1).dayOfGregorianCal == 1);
  10530. assert(Date(1, 12, 31).dayOfGregorianCal == 365);
  10531. assert(Date(2, 1, 1).dayOfGregorianCal == 366);
  10532. assert(Date(0, 12, 31).dayOfGregorianCal == 0);
  10533. assert(Date(0, 1, 1).dayOfGregorianCal == -365);
  10534. assert(Date(-1, 12, 31).dayOfGregorianCal == -366);
  10535. assert(Date(2000, 1, 1).dayOfGregorianCal == 730_120);
  10536. assert(Date(2010, 12, 31).dayOfGregorianCal == 734_137);
  10537. }
  10538. version(testStdDateTime) unittest
  10539. {
  10540. foreach(gd; chain(testGregDaysBC, testGregDaysAD))
  10541. _assertPred!"=="(gd.date.dayOfGregorianCal, gd.day);
  10542. auto date = Date(1999, 7, 6);
  10543. const cdate = Date(1999, 7, 6);
  10544. immutable idate = Date(1999, 7, 6);
  10545. static assert(__traits(compiles, date.dayOfGregorianCal));
  10546. static assert(__traits(compiles, cdate.dayOfGregorianCal));
  10547. static assert(__traits(compiles, idate.dayOfGregorianCal));
  10548. }
  10549. /++
  10550. The Xth day of the Gregorian Calendar that this $(D Date) is on.
  10551. Params:
  10552. day = The day of the Gregorian Calendar to set this $(D Date) to.
  10553. Examples:
  10554. --------------------
  10555. auto date = Date.init;
  10556. date.dayOfGregorianCal = 1;
  10557. assert(date == Date(1, 1, 1));
  10558. date.dayOfGregorianCal = 365;
  10559. assert(date == Date(1, 12, 31));
  10560. date.dayOfGregorianCal = 366;
  10561. assert(date == Date(2, 1, 1));
  10562. date.dayOfGregorianCal = 0;
  10563. assert(date == Date(0, 12, 31));
  10564. date.dayOfGregorianCal = -365;
  10565. assert(date == Date(-0, 1, 1));
  10566. date.dayOfGregorianCal = -366;
  10567. assert(date == Date(-1, 12, 31));
  10568. date.dayOfGregorianCal = 730_120;
  10569. assert(date == Date(2000, 1, 1));
  10570. date.dayOfGregorianCal = 734_137;
  10571. assert(date == Date(2010, 12, 31));
  10572. --------------------
  10573. +/
  10574. @property void dayOfGregorianCal(int day) pure nothrow
  10575. {
  10576. this = Date(day);
  10577. }
  10578. unittest
  10579. {
  10580. version(testStdDateTime)
  10581. {
  10582. {
  10583. auto date = Date(1999, 7, 6);
  10584. const cdate = Date(1999, 7, 6);
  10585. immutable idate = Date(1999, 7, 6);
  10586. static assert(__traits(compiles, date.dayOfGregorianCal = 187));
  10587. static assert(!__traits(compiles, cdate.dayOfGregorianCal = 187));
  10588. static assert(!__traits(compiles, idate.dayOfGregorianCal = 187));
  10589. }
  10590. //Verify Examples.
  10591. {
  10592. auto date = Date.init;
  10593. date.dayOfGregorianCal = 1;
  10594. assert(date == Date(1, 1, 1));
  10595. date.dayOfGregorianCal = 365;
  10596. assert(date == Date(1, 12, 31));
  10597. date.dayOfGregorianCal = 366;
  10598. assert(date == Date(2, 1, 1));
  10599. date.dayOfGregorianCal = 0;
  10600. assert(date == Date(0, 12, 31));
  10601. date.dayOfGregorianCal = -365;
  10602. assert(date == Date(-0, 1, 1));
  10603. date.dayOfGregorianCal = -366;
  10604. assert(date == Date(-1, 12, 31));
  10605. date.dayOfGregorianCal = 730_120;
  10606. assert(date == Date(2000, 1, 1));
  10607. date.dayOfGregorianCal = 734_137;
  10608. assert(date == Date(2010, 12, 31));
  10609. }
  10610. }
  10611. }
  10612. /++
  10613. The ISO 8601 week of the year that this $(D Date) is in.
  10614. See_Also:
  10615. $(WEB en.wikipedia.org/wiki/ISO_week_date, ISO Week Date)
  10616. +/
  10617. @property ubyte isoWeek() const pure nothrow
  10618. {
  10619. immutable weekday = dayOfWeek;
  10620. immutable adjustedWeekday = weekday == DayOfWeek.sun ? 7 : weekday;
  10621. immutable week = (dayOfYear - adjustedWeekday + 10) / 7;
  10622. try
  10623. {
  10624. if(week == 53)
  10625. {
  10626. switch(Date(_year + 1, 1, 1).dayOfWeek)
  10627. {
  10628. case DayOfWeek.mon:
  10629. case DayOfWeek.tue:
  10630. case DayOfWeek.wed:
  10631. case DayOfWeek.thu:
  10632. return 1;
  10633. case DayOfWeek.fri:
  10634. case DayOfWeek.sat:
  10635. case DayOfWeek.sun:
  10636. return 53;
  10637. default:
  10638. assert(0, "Invalid ISO Week");
  10639. }
  10640. }
  10641. else if(week > 0)
  10642. return cast(ubyte)week;
  10643. else
  10644. return Date(_year - 1, 12, 31).isoWeek;
  10645. }
  10646. catch(Exception e)
  10647. assert(0, "Date's constructor threw.");
  10648. }
  10649. unittest
  10650. {
  10651. version(testStdDateTime)
  10652. {
  10653. //Test A.D.
  10654. _assertPred!"=="(Date(2009, 12, 28).isoWeek, 53);
  10655. _assertPred!"=="(Date(2009, 12, 29).isoWeek, 53);
  10656. _assertPred!"=="(Date(2009, 12, 30).isoWeek, 53);
  10657. _assertPred!"=="(Date(2009, 12, 31).isoWeek, 53);
  10658. _assertPred!"=="(Date(2010, 1, 1).isoWeek, 53);
  10659. _assertPred!"=="(Date(2010, 1, 2).isoWeek, 53);
  10660. _assertPred!"=="(Date(2010, 1, 3).isoWeek, 53);
  10661. _assertPred!"=="(Date(2010, 1, 4).isoWeek, 1);
  10662. _assertPred!"=="(Date(2010, 1, 5).isoWeek, 1);
  10663. _assertPred!"=="(Date(2010, 1, 6).isoWeek, 1);
  10664. _assertPred!"=="(Date(2010, 1, 7).isoWeek, 1);
  10665. _assertPred!"=="(Date(2010, 1, 8).isoWeek, 1);
  10666. _assertPred!"=="(Date(2010, 1, 9).isoWeek, 1);
  10667. _assertPred!"=="(Date(2010, 1, 10).isoWeek, 1);
  10668. _assertPred!"=="(Date(2010, 1, 11).isoWeek, 2);
  10669. _assertPred!"=="(Date(2010, 12, 31).isoWeek, 52);
  10670. _assertPred!"=="(Date(2004, 12, 26).isoWeek, 52);
  10671. _assertPred!"=="(Date(2004, 12, 27).isoWeek, 53);
  10672. _assertPred!"=="(Date(2004, 12, 28).isoWeek, 53);
  10673. _assertPred!"=="(Date(2004, 12, 29).isoWeek, 53);
  10674. _assertPred!"=="(Date(2004, 12, 30).isoWeek, 53);
  10675. _assertPred!"=="(Date(2004, 12, 31).isoWeek, 53);
  10676. _assertPred!"=="(Date(2005, 1, 1).isoWeek, 53);
  10677. _assertPred!"=="(Date(2005, 1, 2).isoWeek, 53);
  10678. _assertPred!"=="(Date(2005, 12, 31).isoWeek, 52);
  10679. _assertPred!"=="(Date(2007, 1, 1).isoWeek, 1);
  10680. _assertPred!"=="(Date(2007, 12, 30).isoWeek, 52);
  10681. _assertPred!"=="(Date(2007, 12, 31).isoWeek, 1);
  10682. _assertPred!"=="(Date(2008, 1, 1).isoWeek, 1);
  10683. _assertPred!"=="(Date(2008, 12, 28).isoWeek, 52);
  10684. _assertPred!"=="(Date(2008, 12, 29).isoWeek, 1);
  10685. _assertPred!"=="(Date(2008, 12, 30).isoWeek, 1);
  10686. _assertPred!"=="(Date(2008, 12, 31).isoWeek, 1);
  10687. _assertPred!"=="(Date(2009, 1, 1).isoWeek, 1);
  10688. _assertPred!"=="(Date(2009, 1, 2).isoWeek, 1);
  10689. _assertPred!"=="(Date(2009, 1, 3).isoWeek, 1);
  10690. _assertPred!"=="(Date(2009, 1, 4).isoWeek, 1);
  10691. //Test B.C.
  10692. //The algorithm should work identically for both A.D. and B.C. since
  10693. //it doesn't really take the year into account, so B.C. testing
  10694. //probably isn't really needed.
  10695. _assertPred!"=="(Date(0, 12, 31).isoWeek, 52);
  10696. _assertPred!"=="(Date(0, 1, 4).isoWeek, 1);
  10697. _assertPred!"=="(Date(0, 1, 1).isoWeek, 52);
  10698. const cdate = Date(1999, 7, 6);
  10699. immutable idate = Date(1999, 7, 6);
  10700. static assert(__traits(compiles, cdate.isoWeek == 3));
  10701. static assert(!__traits(compiles, cdate.isoWeek = 3));
  10702. static assert(__traits(compiles, idate.isoWeek == 3));
  10703. static assert(!__traits(compiles, idate.isoWeek = 3));
  10704. }
  10705. }
  10706. /++
  10707. $(D Date) for the last day in the month that this $(D Date) is in.
  10708. Examples:
  10709. --------------------
  10710. assert(Date(1999, 1, 6).endOfMonth == Date(1999, 1, 31));
  10711. assert(Date(1999, 2, 7).endOfMonth == Date(1999, 2, 28));
  10712. assert(Date(2000, 2, 7).endOfMonth == Date(1999, 2, 29));
  10713. assert(Date(2000, 6, 4).endOfMonth == Date(1999, 6, 30));
  10714. --------------------
  10715. +/
  10716. @property Date endOfMonth() const pure nothrow
  10717. {
  10718. try
  10719. return Date(_year, _month, maxDay(_year, _month));
  10720. catch(Exception e)
  10721. assert(0, "Date's constructor threw.");
  10722. }
  10723. unittest
  10724. {
  10725. version(testStdDateTime)
  10726. {
  10727. //Test A.D.
  10728. _assertPred!"=="(Date(1999, 1, 1).endOfMonth, Date(1999, 1, 31));
  10729. _assertPred!"=="(Date(1999, 2, 1).endOfMonth, Date(1999, 2, 28));
  10730. _assertPred!"=="(Date(2000, 2, 1).endOfMonth, Date(2000, 2, 29));
  10731. _assertPred!"=="(Date(1999, 3, 1).endOfMonth, Date(1999, 3, 31));
  10732. _assertPred!"=="(Date(1999, 4, 1).endOfMonth, Date(1999, 4, 30));
  10733. _assertPred!"=="(Date(1999, 5, 1).endOfMonth, Date(1999, 5, 31));
  10734. _assertPred!"=="(Date(1999, 6, 1).endOfMonth, Date(1999, 6, 30));
  10735. _assertPred!"=="(Date(1999, 7, 1).endOfMonth, Date(1999, 7, 31));
  10736. _assertPred!"=="(Date(1999, 8, 1).endOfMonth, Date(1999, 8, 31));
  10737. _assertPred!"=="(Date(1999, 9, 1).endOfMonth, Date(1999, 9, 30));
  10738. _assertPred!"=="(Date(1999, 10, 1).endOfMonth, Date(1999, 10, 31));
  10739. _assertPred!"=="(Date(1999, 11, 1).endOfMonth, Date(1999, 11, 30));
  10740. _assertPred!"=="(Date(1999, 12, 1).endOfMonth, Date(1999, 12, 31));
  10741. //Test B.C.
  10742. _assertPred!"=="(Date(-1999, 1, 1).endOfMonth, Date(-1999, 1, 31));
  10743. _assertPred!"=="(Date(-1999, 2, 1).endOfMonth, Date(-1999, 2, 28));
  10744. _assertPred!"=="(Date(-2000, 2, 1).endOfMonth, Date(-2000, 2, 29));
  10745. _assertPred!"=="(Date(-1999, 3, 1).endOfMonth, Date(-1999, 3, 31));
  10746. _assertPred!"=="(Date(-1999, 4, 1).endOfMonth, Date(-1999, 4, 30));
  10747. _assertPred!"=="(Date(-1999, 5, 1).endOfMonth, Date(-1999, 5, 31));
  10748. _assertPred!"=="(Date(-1999, 6, 1).endOfMonth, Date(-1999, 6, 30));
  10749. _assertPred!"=="(Date(-1999, 7, 1).endOfMonth, Date(-1999, 7, 31));
  10750. _assertPred!"=="(Date(-1999, 8, 1).endOfMonth, Date(-1999, 8, 31));
  10751. _assertPred!"=="(Date(-1999, 9, 1).endOfMonth, Date(-1999, 9, 30));
  10752. _assertPred!"=="(Date(-1999, 10, 1).endOfMonth, Date(-1999, 10, 31));
  10753. _assertPred!"=="(Date(-1999, 11, 1).endOfMonth, Date(-1999, 11, 30));
  10754. _assertPred!"=="(Date(-1999, 12, 1).endOfMonth, Date(-1999, 12, 31));
  10755. const cdate = Date(1999, 7, 6);
  10756. immutable idate = Date(1999, 7, 6);
  10757. static assert(!__traits(compiles, cdate.endOfMonth = Date(1999, 7, 30)));
  10758. static assert(!__traits(compiles, idate.endOfMonth = Date(1999, 7, 30)));
  10759. //Verify Examples.
  10760. assert(Date(1999, 1, 6).endOfMonth == Date(1999, 1, 31));
  10761. assert(Date(1999, 2, 7).endOfMonth == Date(1999, 2, 28));
  10762. assert(Date(2000, 2, 7).endOfMonth == Date(2000, 2, 29));
  10763. assert(Date(2000, 6, 4).endOfMonth == Date(2000, 6, 30));
  10764. }
  10765. }
  10766. /++
  10767. The last day in the month that this $(D Date) is in.
  10768. Examples:
  10769. --------------------
  10770. assert(Date(1999, 1, 6).daysInMonth == 31);
  10771. assert(Date(1999, 2, 7).daysInMonth == 28);
  10772. assert(Date(2000, 2, 7).daysInMonth == 29);
  10773. assert(Date(2000, 6, 4).daysInMonth == 30);
  10774. --------------------
  10775. +/
  10776. @property ubyte daysInMonth() const pure nothrow
  10777. {
  10778. return maxDay(_year, _month);
  10779. }
  10780. /++
  10781. $(RED Scheduled for deprecation in January 2012.
  10782. Please use daysInMonth instead.)
  10783. +/
  10784. alias daysInMonth endofMonthDay;
  10785. unittest
  10786. {
  10787. version(testStdDateTime)
  10788. {
  10789. //Test A.D.
  10790. _assertPred!"=="(Date(1999, 1, 1).daysInMonth, 31);
  10791. _assertPred!"=="(Date(1999, 2, 1).daysInMonth, 28);
  10792. _assertPred!"=="(Date(2000, 2, 1).daysInMonth, 29);
  10793. _assertPred!"=="(Date(1999, 3, 1).daysInMonth, 31);
  10794. _assertPred!"=="(Date(1999, 4, 1).daysInMonth, 30);
  10795. _assertPred!"=="(Date(1999, 5, 1).daysInMonth, 31);
  10796. _assertPred!"=="(Date(1999, 6, 1).daysInMonth, 30);
  10797. _assertPred!"=="(Date(1999, 7, 1).daysInMonth, 31);
  10798. _assertPred!"=="(Date(1999, 8, 1).daysInMonth, 31);
  10799. _assertPred!"=="(Date(1999, 9, 1).daysInMonth, 30);
  10800. _assertPred!"=="(Date(1999, 10, 1).daysInMonth, 31);
  10801. _assertPred!"=="(Date(1999, 11, 1).daysInMonth, 30);
  10802. _assertPred!"=="(Date(1999, 12, 1).daysInMonth, 31);
  10803. //Test B.C.
  10804. _assertPred!"=="(Date(-1999, 1, 1).daysInMonth, 31);
  10805. _assertPred!"=="(Date(-1999, 2, 1).daysInMonth, 28);
  10806. _assertPred!"=="(Date(-2000, 2, 1).daysInMonth, 29);
  10807. _assertPred!"=="(Date(-1999, 3, 1).daysInMonth, 31);
  10808. _assertPred!"=="(Date(-1999, 4, 1).daysInMonth, 30);
  10809. _assertPred!"=="(Date(-1999, 5, 1).daysInMonth, 31);
  10810. _assertPred!"=="(Date(-1999, 6, 1).daysInMonth, 30);
  10811. _assertPred!"=="(Date(-1999, 7, 1).daysInMonth, 31);
  10812. _assertPred!"=="(Date(-1999, 8, 1).daysInMonth, 31);
  10813. _assertPred!"=="(Date(-1999, 9, 1).daysInMonth, 30);
  10814. _assertPred!"=="(Date(-1999, 10, 1).daysInMonth, 31);
  10815. _assertPred!"=="(Date(-1999, 11, 1).daysInMonth, 30);
  10816. _assertPred!"=="(Date(-1999, 12, 1).daysInMonth, 31);
  10817. const cdate = Date(1999, 7, 6);
  10818. immutable idate = Date(1999, 7, 6);
  10819. static assert(!__traits(compiles, cdate.daysInMonth = 30));
  10820. static assert(!__traits(compiles, idate.daysInMonth = 30));
  10821. //Verify Examples.
  10822. assert(Date(1999, 1, 6).daysInMonth == 31);
  10823. assert(Date(1999, 2, 7).daysInMonth == 28);
  10824. assert(Date(2000, 2, 7).daysInMonth == 29);
  10825. assert(Date(2000, 6, 4).daysInMonth == 30);
  10826. }
  10827. }
  10828. /++
  10829. Whether the current year is a date in A.D.
  10830. Examples:
  10831. --------------------
  10832. assert(Date(1, 1, 1).isAD);
  10833. assert(Date(2010, 12, 31).isAD);
  10834. assert(!Date(0, 12, 31).isAD);
  10835. assert(!Date(-2010, 1, 1).isAD);
  10836. --------------------
  10837. +/
  10838. @property bool isAD() const pure nothrow
  10839. {
  10840. return _year > 0;
  10841. }
  10842. unittest
  10843. {
  10844. version(testStdDateTime)
  10845. {
  10846. assert(Date(2010, 7, 4).isAD);
  10847. assert(Date(1, 1, 1).isAD);
  10848. assert(!Date(0, 1, 1).isAD);
  10849. assert(!Date(-1, 1, 1).isAD);
  10850. assert(!Date(-2010, 7, 4).isAD);
  10851. const cdate = Date(1999, 7, 6);
  10852. immutable idate = Date(1999, 7, 6);
  10853. static assert(__traits(compiles, cdate.isAD));
  10854. static assert(__traits(compiles, idate.isAD));
  10855. //Verify Examples.
  10856. assert(Date(1, 1, 1).isAD);
  10857. assert(Date(2010, 12, 31).isAD);
  10858. assert(!Date(0, 12, 31).isAD);
  10859. assert(!Date(-2010, 1, 1).isAD);
  10860. }
  10861. }
  10862. /++
  10863. The julian day for this $(D Date) at noon (since the julian day changes
  10864. at noon).
  10865. +/
  10866. @property long julianDay() const pure nothrow
  10867. {
  10868. return dayOfGregorianCal + 1_721_425;
  10869. }
  10870. unittest
  10871. {
  10872. version(testStdDateTime)
  10873. {
  10874. _assertPred!"=="(Date(-4713, 11, 24).julianDay, 0);
  10875. _assertPred!"=="(Date(0, 12, 31).julianDay, 1_721_425);
  10876. _assertPred!"=="(Date(1, 1, 1).julianDay, 1_721_426);
  10877. _assertPred!"=="(Date(1582, 10, 15).julianDay, 2_299_161);
  10878. _assertPred!"=="(Date(1858, 11, 17).julianDay, 2_400_001);
  10879. _assertPred!"=="(Date(1982, 1, 4).julianDay, 2_444_974);
  10880. _assertPred!"=="(Date(1996, 3, 31).julianDay, 2_450_174);
  10881. _assertPred!"=="(Date(2010, 8, 24).julianDay, 2_455_433);
  10882. const cdate = Date(1999, 7, 6);
  10883. immutable idate = Date(1999, 7, 6);
  10884. static assert(__traits(compiles, cdate.julianDay));
  10885. static assert(__traits(compiles, idate.julianDay));
  10886. }
  10887. }
  10888. /++
  10889. The modified julian day for any time on this date (since, the modified
  10890. julian day changes at midnight).
  10891. +/
  10892. @property long modJulianDay() const pure nothrow
  10893. {
  10894. return julianDay - 2_400_001;
  10895. }
  10896. unittest
  10897. {
  10898. version(testStdDateTime)
  10899. {
  10900. _assertPred!"=="(Date(1858, 11, 17).modJulianDay, 0);
  10901. _assertPred!"=="(Date(2010, 8, 24).modJulianDay, 55_432);
  10902. const cdate = Date(1999, 7, 6);
  10903. immutable idate = Date(1999, 7, 6);
  10904. static assert(__traits(compiles, cdate.modJulianDay));
  10905. static assert(__traits(compiles, idate.modJulianDay));
  10906. }
  10907. }
  10908. /++
  10909. Converts this $(D Date) to a string with the format YYYYMMDD.
  10910. Examples:
  10911. --------------------
  10912. assert(Date(2010, 7, 4).toISOString() == "20100704");
  10913. assert(Date(1998, 12, 25).toISOString() == "19981225");
  10914. assert(Date(0, 1, 5).toISOString() == "00000105");
  10915. assert(Date(-4, 1, 5).toISOString() == "-00040105");
  10916. --------------------
  10917. +/
  10918. string toISOString() const nothrow
  10919. {
  10920. try
  10921. {
  10922. if(_year >= 0)
  10923. {
  10924. if(_year < 10_000)
  10925. return format("%04d%02d%02d", _year, _month, _day);
  10926. else
  10927. return format("+%05d%02d%02d", _year, _month, _day);
  10928. }
  10929. else if(_year > -10_000)
  10930. return format("%05d%02d%02d", _year, _month, _day);
  10931. else
  10932. return format("%06d%02d%02d", _year, _month, _day);
  10933. }
  10934. catch(Exception e)
  10935. assert(0, "format() threw.");
  10936. }
  10937. unittest
  10938. {
  10939. version(testStdDateTime)
  10940. {
  10941. //Test A.D.
  10942. _assertPred!"=="(Date(9, 12, 4).toISOString(), "00091204");
  10943. _assertPred!"=="(Date(99, 12, 4).toISOString(), "00991204");
  10944. _assertPred!"=="(Date(999, 12, 4).toISOString(), "09991204");
  10945. _assertPred!"=="(Date(9999, 7, 4).toISOString(), "99990704");
  10946. _assertPred!"=="(Date(10000, 10, 20).toISOString(), "+100001020");
  10947. //Test B.C.
  10948. _assertPred!"=="(Date(0, 12, 4).toISOString(), "00001204");
  10949. _assertPred!"=="(Date(-9, 12, 4).toISOString(), "-00091204");
  10950. _assertPred!"=="(Date(-99, 12, 4).toISOString(), "-00991204");
  10951. _assertPred!"=="(Date(-999, 12, 4).toISOString(), "-09991204");
  10952. _assertPred!"=="(Date(-9999, 7, 4).toISOString(), "-99990704");
  10953. _assertPred!"=="(Date(-10000, 10, 20).toISOString(), "-100001020");
  10954. const cdate = Date(1999, 7, 6);
  10955. immutable idate = Date(1999, 7, 6);
  10956. static assert(__traits(compiles, cdate.toISOString()));
  10957. static assert(__traits(compiles, idate.toISOString()));
  10958. //Verify Examples.
  10959. assert(Date(2010, 7, 4).toISOString() == "20100704");
  10960. assert(Date(1998, 12, 25).toISOString() == "19981225");
  10961. assert(Date(0, 1, 5).toISOString() == "00000105");
  10962. assert(Date(-4, 1, 5).toISOString() == "-00040105");
  10963. }
  10964. }
  10965. /++
  10966. Converts this $(D Date) to a string with the format YYYY-MM-DD.
  10967. Examples:
  10968. --------------------
  10969. assert(Date(2010, 7, 4).toISOExtString() == "2010-07-04");
  10970. assert(Date(1998, 12, 25).toISOExtString() == "1998-12-25");
  10971. assert(Date(0, 1, 5).toISOExtString() == "0000-01-05");
  10972. assert(Date(-4, 1, 5).toISOExtString() == "-0004-01-05");
  10973. --------------------
  10974. +/
  10975. string toISOExtString() const nothrow
  10976. {
  10977. try
  10978. {
  10979. if(_year >= 0)
  10980. {
  10981. if(_year < 10_000)
  10982. return format("%04d-%02d-%02d", _year, _month, _day);
  10983. else
  10984. return format("+%05d-%02d-%02d", _year, _month, _day);
  10985. }
  10986. else if(_year > -10_000)
  10987. return format("%05d-%02d-%02d", _year, _month, _day);
  10988. else
  10989. return format("%06d-%02d-%02d", _year, _month, _day);
  10990. }
  10991. catch(Exception e)
  10992. assert(0, "format() threw.");
  10993. }
  10994. /++
  10995. $(RED Scheduled for deprecation in November 2011.
  10996. Please use toISOExtString instead.)
  10997. +/
  10998. alias toISOExtString toISOExtendedString;
  10999. unittest
  11000. {
  11001. version(testStdDateTime)
  11002. {
  11003. //Test A.D.
  11004. _assertPred!"=="(Date(9, 12, 4).toISOExtString(), "0009-12-04");
  11005. _assertPred!"=="(Date(99, 12, 4).toISOExtString(), "0099-12-04");
  11006. _assertPred!"=="(Date(999, 12, 4).toISOExtString(), "0999-12-04");
  11007. _assertPred!"=="(Date(9999, 7, 4).toISOExtString(), "9999-07-04");
  11008. _assertPred!"=="(Date(10000, 10, 20).toISOExtString(), "+10000-10-20");
  11009. //Test B.C.
  11010. _assertPred!"=="(Date(0, 12, 4).toISOExtString(), "0000-12-04");
  11011. _assertPred!"=="(Date(-9, 12, 4).toISOExtString(), "-0009-12-04");
  11012. _assertPred!"=="(Date(-99, 12, 4).toISOExtString(), "-0099-12-04");
  11013. _assertPred!"=="(Date(-999, 12, 4).toISOExtString(), "-0999-12-04");
  11014. _assertPred!"=="(Date(-9999, 7, 4).toISOExtString(), "-9999-07-04");
  11015. _assertPred!"=="(Date(-10000, 10, 20).toISOExtString(), "-10000-10-20");
  11016. const cdate = Date(1999, 7, 6);
  11017. immutable idate = Date(1999, 7, 6);
  11018. static assert(__traits(compiles, cdate.toISOExtString()));
  11019. static assert(__traits(compiles, idate.toISOExtString()));
  11020. //Verify Examples.
  11021. assert(Date(2010, 7, 4).toISOExtString() == "2010-07-04");
  11022. assert(Date(1998, 12, 25).toISOExtString() == "1998-12-25");
  11023. assert(Date(0, 1, 5).toISOExtString() == "0000-01-05");
  11024. assert(Date(-4, 1, 5).toISOExtString() == "-0004-01-05");
  11025. }
  11026. }
  11027. /++
  11028. Converts this $(D Date) to a string with the format YYYY-Mon-DD.
  11029. Examples:
  11030. --------------------
  11031. assert(Date(2010, 7, 4).toSimpleString() == "2010-Jul-04");
  11032. assert(Date(1998, 12, 25).toSimpleString() == "1998-Dec-25");
  11033. assert(Date(0, 1, 5).toSimpleString() == "0000-Jan-05");
  11034. assert(Date(-4, 1, 5).toSimpleString() == "-0004-Jan-05");
  11035. --------------------
  11036. +/
  11037. string toSimpleString() const nothrow
  11038. {
  11039. try
  11040. {
  11041. if(_year >= 0)
  11042. {
  11043. if(_year < 10_000)
  11044. return format("%04d-%s-%02d", _year, monthToString(_month, false), _day);
  11045. else
  11046. return format("+%05d-%s-%02d", _year, monthToString(_month, false), _day);
  11047. }
  11048. else if(_year > -10_000)
  11049. return format("%05d-%s-%02d", _year, monthToString(_month, false), _day);
  11050. else
  11051. return format("%06d-%s-%02d", _year, monthToString(_month, false), _day);
  11052. }
  11053. catch(Exception e)
  11054. assert(0, "format() threw.");
  11055. }
  11056. unittest
  11057. {
  11058. version(testStdDateTime)
  11059. {
  11060. //Test A.D.
  11061. _assertPred!"=="(Date(9, 12, 4).toSimpleString(), "0009-Dec-04");
  11062. _assertPred!"=="(Date(99, 12, 4).toSimpleString(), "0099-Dec-04");
  11063. _assertPred!"=="(Date(999, 12, 4).toSimpleString(), "0999-Dec-04");
  11064. _assertPred!"=="(Date(9999, 7, 4).toSimpleString(), "9999-Jul-04");
  11065. _assertPred!"=="(Date(10000, 10, 20).toSimpleString(), "+10000-Oct-20");
  11066. //Test B.C.
  11067. _assertPred!"=="(Date(0, 12, 4).toSimpleString(), "0000-Dec-04");
  11068. _assertPred!"=="(Date(-9, 12, 4).toSimpleString(), "-0009-Dec-04");
  11069. _assertPred!"=="(Date(-99, 12, 4).toSimpleString(), "-0099-Dec-04");
  11070. _assertPred!"=="(Date(-999, 12, 4).toSimpleString(), "-0999-Dec-04");
  11071. _assertPred!"=="(Date(-9999, 7, 4).toSimpleString(), "-9999-Jul-04");
  11072. _assertPred!"=="(Date(-10000, 10, 20).toSimpleString(), "-10000-Oct-20");
  11073. const cdate = Date(1999, 7, 6);
  11074. immutable idate = Date(1999, 7, 6);
  11075. static assert(__traits(compiles, cdate.toSimpleString()));
  11076. static assert(__traits(compiles, idate.toSimpleString()));
  11077. //Verify Examples.
  11078. assert(Date(2010, 7, 4).toSimpleString() == "2010-Jul-04");
  11079. assert(Date(1998, 12, 25).toSimpleString() == "1998-Dec-25");
  11080. assert(Date(0, 1, 5).toSimpleString() == "0000-Jan-05");
  11081. assert(Date(-4, 1, 5).toSimpleString() == "-0004-Jan-05");
  11082. }
  11083. }
  11084. //TODO Add a function which returns a string in a user-specified format.
  11085. /+
  11086. Converts this $(D Date) to a string.
  11087. +/
  11088. //Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
  11089. //have versions of toString() with extra modifiers, so we define one version
  11090. //with modifiers and one without.
  11091. string toString()
  11092. {
  11093. return toSimpleString();
  11094. }
  11095. /++
  11096. Converts this $(D Date) to a string.
  11097. +/
  11098. //Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
  11099. //have versions of toString() with extra modifiers, so we define one version
  11100. //with modifiers and one without.
  11101. string toString() const nothrow
  11102. {
  11103. return toSimpleString();
  11104. }
  11105. unittest
  11106. {
  11107. version(testStdDateTime)
  11108. {
  11109. auto date = Date(1999, 7, 6);
  11110. const cdate = Date(1999, 7, 6);
  11111. immutable idate = Date(1999, 7, 6);
  11112. static assert(__traits(compiles, date.toString()));
  11113. static assert(__traits(compiles, cdate.toString()));
  11114. static assert(__traits(compiles, idate.toString()));
  11115. }
  11116. }
  11117. /++
  11118. Creates a $(D Date) from a string with the format YYYYMMDD. Whitespace
  11119. is stripped from the given string.
  11120. Params:
  11121. isoString = A string formatted in the ISO format for dates.
  11122. Throws:
  11123. $(D DateTimeException) if the given string is not in the ISO format
  11124. or if the resulting $(D Date) would not be valid.
  11125. Examples:
  11126. --------------------
  11127. assert(Date.fromISOString("20100704") == Date(2010, 7, 4));
  11128. assert(Date.fromISOString("19981225") == Date(1998, 12, 25));
  11129. assert(Date.fromISOString("00000105") == Date(0, 1, 5));
  11130. assert(Date.fromISOString("-00040105") == Date(-4, 1, 5));
  11131. assert(Date.fromISOString(" 20100704 ") == Date(2010, 7, 4));
  11132. --------------------
  11133. +/
  11134. static Date fromISOString(S)(in S isoString)
  11135. if(isSomeString!S)
  11136. {
  11137. auto dstr = to!dstring(strip(isoString));
  11138. enforce(dstr.length >= 8, new DateTimeException(format("Invalid ISO String: %s", isoString)));
  11139. auto day = dstr[$-2 .. $];
  11140. auto month = dstr[$-4 .. $-2];
  11141. auto year = dstr[0 .. $-4];
  11142. enforce(!canFind!(not!isDigit)(day), new DateTimeException(format("Invalid ISO String: %s", isoString)));
  11143. enforce(!canFind!(not!isDigit)(month), new DateTimeException(format("Invalid ISO String: %s", isoString)));
  11144. if(year.length > 4)
  11145. {
  11146. enforce(year.startsWith("-") || year.startsWith("+"),
  11147. new DateTimeException(format("Invalid ISO String: %s", isoString)));
  11148. enforce(!canFind!(not!isDigit)(year[1..$]),
  11149. new DateTimeException(format("Invalid ISO String: %s", isoString)));
  11150. }
  11151. else
  11152. enforce(!canFind!(not!isDigit)(year), new DateTimeException(format("Invalid ISO String: %s", isoString)));
  11153. return Date(to!short(year), to!ubyte(month), to!ubyte(day));
  11154. }
  11155. unittest
  11156. {
  11157. version(testStdDateTime)
  11158. {
  11159. assertThrown!DateTimeException(Date.fromISOString(""));
  11160. assertThrown!DateTimeException(Date.fromISOString("990704"));
  11161. assertThrown!DateTimeException(Date.fromISOString("0100704"));
  11162. assertThrown!DateTimeException(Date.fromISOString("2010070"));
  11163. assertThrown!DateTimeException(Date.fromISOString("2010070 "));
  11164. assertThrown!DateTimeException(Date.fromISOString("120100704"));
  11165. assertThrown!DateTimeException(Date.fromISOString("-0100704"));
  11166. assertThrown!DateTimeException(Date.fromISOString("+0100704"));
  11167. assertThrown!DateTimeException(Date.fromISOString("2010070a"));
  11168. assertThrown!DateTimeException(Date.fromISOString("20100a04"));
  11169. assertThrown!DateTimeException(Date.fromISOString("2010a704"));
  11170. assertThrown!DateTimeException(Date.fromISOString("99-07-04"));
  11171. assertThrown!DateTimeException(Date.fromISOString("010-07-04"));
  11172. assertThrown!DateTimeException(Date.fromISOString("2010-07-0"));
  11173. assertThrown!DateTimeException(Date.fromISOString("2010-07-0 "));
  11174. assertThrown!DateTimeException(Date.fromISOString("12010-07-04"));
  11175. assertThrown!DateTimeException(Date.fromISOString("-010-07-04"));
  11176. assertThrown!DateTimeException(Date.fromISOString("+010-07-04"));
  11177. assertThrown!DateTimeException(Date.fromISOString("2010-07-0a"));
  11178. assertThrown!DateTimeException(Date.fromISOString("2010-0a-04"));
  11179. assertThrown!DateTimeException(Date.fromISOString("2010-a7-04"));
  11180. assertThrown!DateTimeException(Date.fromISOString("2010/07/04"));
  11181. assertThrown!DateTimeException(Date.fromISOString("2010/7/04"));
  11182. assertThrown!DateTimeException(Date.fromISOString("2010/7/4"));
  11183. assertThrown!DateTimeException(Date.fromISOString("2010/07/4"));
  11184. assertThrown!DateTimeException(Date.fromISOString("2010-7-04"));
  11185. assertThrown!DateTimeException(Date.fromISOString("2010-7-4"));
  11186. assertThrown!DateTimeException(Date.fromISOString("2010-07-4"));
  11187. assertThrown!DateTimeException(Date.fromISOString("99Jul04"));
  11188. assertThrown!DateTimeException(Date.fromISOString("010Jul04"));
  11189. assertThrown!DateTimeException(Date.fromISOString("2010Jul0"));
  11190. assertThrown!DateTimeException(Date.fromISOString("2010Jul0 "));
  11191. assertThrown!DateTimeException(Date.fromISOString("12010Jul04"));
  11192. assertThrown!DateTimeException(Date.fromISOString("-010Jul04"));
  11193. assertThrown!DateTimeException(Date.fromISOString("+010Jul04"));
  11194. assertThrown!DateTimeException(Date.fromISOString("2010Jul0a"));
  11195. assertThrown!DateTimeException(Date.fromISOString("2010Jua04"));
  11196. assertThrown!DateTimeException(Date.fromISOString("2010aul04"));
  11197. assertThrown!DateTimeException(Date.fromISOString("99-Jul-04"));
  11198. assertThrown!DateTimeException(Date.fromISOString("010-Jul-04"));
  11199. assertThrown!DateTimeException(Date.fromISOString("2010-Jul-0"));
  11200. assertThrown!DateTimeException(Date.fromISOString("2010-Jul-0 "));
  11201. assertThrown!DateTimeException(Date.fromISOString("12010-Jul-04"));
  11202. assertThrown!DateTimeException(Date.fromISOString("-010-Jul-04"));
  11203. assertThrown!DateTimeException(Date.fromISOString("+010-Jul-04"));
  11204. assertThrown!DateTimeException(Date.fromISOString("2010-Jul-0a"));
  11205. assertThrown!DateTimeException(Date.fromISOString("2010-Jua-04"));
  11206. assertThrown!DateTimeException(Date.fromISOString("2010-Jal-04"));
  11207. assertThrown!DateTimeException(Date.fromISOString("2010-aul-04"));
  11208. assertThrown!DateTimeException(Date.fromISOString("2010-07-04"));
  11209. assertThrown!DateTimeException(Date.fromISOString("2010-Jul-04"));
  11210. _assertPred!"=="(Date.fromISOString("19990706"), Date(1999, 7, 6));
  11211. _assertPred!"=="(Date.fromISOString("-19990706"), Date(-1999, 7, 6));
  11212. _assertPred!"=="(Date.fromISOString("+019990706"), Date(1999, 7, 6));
  11213. _assertPred!"=="(Date.fromISOString("19990706 "), Date(1999, 7, 6));
  11214. _assertPred!"=="(Date.fromISOString(" 19990706"), Date(1999, 7, 6));
  11215. _assertPred!"=="(Date.fromISOString(" 19990706 "), Date(1999, 7, 6));
  11216. //Verify Examples.
  11217. assert(Date.fromISOString("20100704") == Date(2010, 7, 4));
  11218. assert(Date.fromISOString("19981225") == Date(1998, 12, 25));
  11219. assert(Date.fromISOString("00000105") == Date(0, 1, 5));
  11220. assert(Date.fromISOString("-00040105") == Date(-4, 1, 5));
  11221. assert(Date.fromISOString(" 20100704 ") == Date(2010, 7, 4));
  11222. }
  11223. }
  11224. /++
  11225. Creates a $(D Date) from a string with the format YYYY-MM-DD. Whitespace
  11226. is stripped from the given string.
  11227. Params:
  11228. isoExtString = A string formatted in the ISO Extended format for
  11229. dates.
  11230. Throws:
  11231. $(D DateTimeException) if the given string is not in the ISO
  11232. Extended format or if the resulting $(D Date) would not be valid.
  11233. Examples:
  11234. --------------------
  11235. assert(Date.fromISOExtString("2010-07-04") == Date(2010, 7, 4));
  11236. assert(Date.fromISOExtString("1998-12-25") == Date(1998, 12, 25));
  11237. assert(Date.fromISOExtString("0000-01-05") == Date(0, 1, 5));
  11238. assert(Date.fromISOExtString("-0004-01-05") == Date(-4, 1, 5));
  11239. assert(Date.fromISOExtString(" 2010-07-04 ") == Date(2010, 7, 4));
  11240. --------------------
  11241. +/
  11242. static Date fromISOExtString(S)(in S isoExtString)
  11243. if(isSomeString!(S))
  11244. {
  11245. auto dstr = to!dstring(strip(isoExtString));
  11246. enforce(dstr.length >= 10, new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
  11247. auto day = dstr[$-2 .. $];
  11248. auto month = dstr[$-5 .. $-3];
  11249. auto year = dstr[0 .. $-6];
  11250. enforce(dstr[$-3] == '-', new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
  11251. enforce(dstr[$-6] == '-', new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
  11252. enforce(!canFind!(not!isDigit)(day),
  11253. new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
  11254. enforce(!canFind!(not!isDigit)(month),
  11255. new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
  11256. if(year.length > 4)
  11257. {
  11258. enforce(year.startsWith("-") || year.startsWith("+"),
  11259. new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
  11260. enforce(!canFind!(not!isDigit)(year[1..$]),
  11261. new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
  11262. }
  11263. else
  11264. enforce(!canFind!(not!isDigit)(year),
  11265. new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
  11266. return Date(to!short(year), to!ubyte(month), to!ubyte(day));
  11267. }
  11268. /++
  11269. $(RED Scheduled for deprecation in November 2011.
  11270. Please use fromISOExtString instead.)
  11271. +/
  11272. static Date fromISOExtendedString(S)(in S isoExtString)
  11273. if(isSomeString!(S))
  11274. {
  11275. pragma(msg, softDeprec!("2.053", "November 2011", "fromISOExtendedString", "fromISOExtString"));
  11276. return fromISOExtString!string(isoExtString);
  11277. }
  11278. unittest
  11279. {
  11280. version(testStdDateTime)
  11281. {
  11282. assertThrown!DateTimeException(Date.fromISOExtString(""));
  11283. assertThrown!DateTimeException(Date.fromISOExtString("990704"));
  11284. assertThrown!DateTimeException(Date.fromISOExtString("0100704"));
  11285. assertThrown!DateTimeException(Date.fromISOExtString("2010070"));
  11286. assertThrown!DateTimeException(Date.fromISOExtString("2010070 "));
  11287. assertThrown!DateTimeException(Date.fromISOExtString("120100704"));
  11288. assertThrown!DateTimeException(Date.fromISOExtString("-0100704"));
  11289. assertThrown!DateTimeException(Date.fromISOExtString("+0100704"));
  11290. assertThrown!DateTimeException(Date.fromISOExtString("2010070a"));
  11291. assertThrown!DateTimeException(Date.fromISOExtString("20100a04"));
  11292. assertThrown!DateTimeException(Date.fromISOExtString("2010a704"));
  11293. assertThrown!DateTimeException(Date.fromISOExtString("99-07-04"));
  11294. assertThrown!DateTimeException(Date.fromISOExtString("010-07-04"));
  11295. assertThrown!DateTimeException(Date.fromISOExtString("2010-07-0"));
  11296. assertThrown!DateTimeException(Date.fromISOExtString("2010-07-0 "));
  11297. assertThrown!DateTimeException(Date.fromISOExtString("12010-07-04"));
  11298. assertThrown!DateTimeException(Date.fromISOExtString("-010-07-04"));
  11299. assertThrown!DateTimeException(Date.fromISOExtString("+010-07-04"));
  11300. assertThrown!DateTimeException(Date.fromISOExtString("2010-07-0a"));
  11301. assertThrown!DateTimeException(Date.fromISOExtString("2010-0a-04"));
  11302. assertThrown!DateTimeException(Date.fromISOExtString("2010-a7-04"));
  11303. assertThrown!DateTimeException(Date.fromISOExtString("2010/07/04"));
  11304. assertThrown!DateTimeException(Date.fromISOExtString("2010/7/04"));
  11305. assertThrown!DateTimeException(Date.fromISOExtString("2010/7/4"));
  11306. assertThrown!DateTimeException(Date.fromISOExtString("2010/07/4"));
  11307. assertThrown!DateTimeException(Date.fromISOExtString("2010-7-04"));
  11308. assertThrown!DateTimeException(Date.fromISOExtString("2010-7-4"));
  11309. assertThrown!DateTimeException(Date.fromISOExtString("2010-07-4"));
  11310. assertThrown!DateTimeException(Date.fromISOExtString("99Jul04"));
  11311. assertThrown!DateTimeException(Date.fromISOExtString("010Jul04"));
  11312. assertThrown!DateTimeException(Date.fromISOExtString("2010Jul0"));
  11313. assertThrown!DateTimeException(Date.fromISOExtString("2010-Jul-0 "));
  11314. assertThrown!DateTimeException(Date.fromISOExtString("12010Jul04"));
  11315. assertThrown!DateTimeException(Date.fromISOExtString("-010Jul04"));
  11316. assertThrown!DateTimeException(Date.fromISOExtString("+010Jul04"));
  11317. assertThrown!DateTimeException(Date.fromISOExtString("2010Jul0a"));
  11318. assertThrown!DateTimeException(Date.fromISOExtString("2010Jua04"));
  11319. assertThrown!DateTimeException(Date.fromISOExtString("2010aul04"));
  11320. assertThrown!DateTimeException(Date.fromISOExtString("99-Jul-04"));
  11321. assertThrown!DateTimeException(Date.fromISOExtString("010-Jul-04"));
  11322. assertThrown!DateTimeException(Date.fromISOExtString("2010-Jul-0"));
  11323. assertThrown!DateTimeException(Date.fromISOExtString("2010Jul0 "));
  11324. assertThrown!DateTimeException(Date.fromISOExtString("12010-Jul-04"));
  11325. assertThrown!DateTimeException(Date.fromISOExtString("-010-Jul-04"));
  11326. assertThrown!DateTimeException(Date.fromISOExtString("+010-Jul-04"));
  11327. assertThrown!DateTimeException(Date.fromISOExtString("2010-Jul-0a"));
  11328. assertThrown!DateTimeException(Date.fromISOExtString("2010-Jua-04"));
  11329. assertThrown!DateTimeException(Date.fromISOExtString("2010-Jal-04"));
  11330. assertThrown!DateTimeException(Date.fromISOExtString("2010-aul-04"));
  11331. assertThrown!DateTimeException(Date.fromISOExtString("20100704"));
  11332. assertThrown!DateTimeException(Date.fromISOExtString("2010-Jul-04"));
  11333. _assertPred!"=="(Date.fromISOExtString("1999-07-06"), Date(1999, 7, 6));
  11334. _assertPred!"=="(Date.fromISOExtString("-1999-07-06"), Date(-1999, 7, 6));
  11335. _assertPred!"=="(Date.fromISOExtString("+01999-07-06"), Date(1999, 7, 6));
  11336. _assertPred!"=="(Date.fromISOExtString("1999-07-06 "), Date(1999, 7, 6));
  11337. _assertPred!"=="(Date.fromISOExtString(" 1999-07-06"), Date(1999, 7, 6));
  11338. _assertPred!"=="(Date.fromISOExtString(" 1999-07-06 "), Date(1999, 7, 6));
  11339. //Verify Examples.
  11340. assert(Date.fromISOExtString("2010-07-04") == Date(2010, 7, 4));
  11341. assert(Date.fromISOExtString("1998-12-25") == Date(1998, 12, 25));
  11342. assert(Date.fromISOExtString("0000-01-05") == Date(0, 1, 5));
  11343. assert(Date.fromISOExtString("-0004-01-05") == Date(-4, 1, 5));
  11344. assert(Date.fromISOExtString(" 2010-07-04 ") == Date(2010, 7, 4));
  11345. }
  11346. }
  11347. /++
  11348. Creates a $(D Date) from a string with the format YYYY-Mon-DD.
  11349. Whitespace is stripped from the given string.
  11350. Params:
  11351. simpleString = A string formatted in the way that toSimpleString
  11352. formats dates.
  11353. Throws:
  11354. $(D DateTimeException) if the given string is not in the correct
  11355. format or if the resulting $(D Date) would not be valid.
  11356. Examples:
  11357. --------------------
  11358. assert(Date.fromSimpleString("2010-Jul-04") == Date(2010, 7, 4));
  11359. assert(Date.fromSimpleString("1998-Dec-25") == Date(1998, 12, 25));
  11360. assert(Date.fromSimpleString("0000-Jan-05") == Date(0, 1, 5));
  11361. assert(Date.fromSimpleString("-0004-Jan-05") == Date(-4, 1, 5));
  11362. assert(Date.fromSimpleString(" 2010-Jul-04 ") == Date(2010, 7, 4));
  11363. --------------------
  11364. +/
  11365. static Date fromSimpleString(S)(in S simpleString)
  11366. if(isSomeString!(S))
  11367. {
  11368. auto dstr = to!dstring(strip(simpleString));
  11369. enforce(dstr.length >= 11, new DateTimeException(format("Invalid string format: %s", simpleString)));
  11370. auto day = dstr[$-2 .. $];
  11371. auto month = monthFromString(to!string(dstr[$-6 .. $-3]));
  11372. auto year = dstr[0 .. $-7];
  11373. enforce(dstr[$-3] == '-', new DateTimeException(format("Invalid string format: %s", simpleString)));
  11374. enforce(dstr[$-7] == '-', new DateTimeException(format("Invalid string format: %s", simpleString)));
  11375. enforce(!canFind!(not!isDigit)(day), new DateTimeException(format("Invalid string format: %s", simpleString)));
  11376. if(year.length > 4)
  11377. {
  11378. enforce(year.startsWith("-") || year.startsWith("+"),
  11379. new DateTimeException(format("Invalid string format: %s", simpleString)));
  11380. enforce(!canFind!(not!isDigit)(year[1..$]),
  11381. new DateTimeException(format("Invalid string format: %s", simpleString)));
  11382. }
  11383. else
  11384. enforce(!canFind!(not!isDigit)(year),
  11385. new DateTimeException(format("Invalid string format: %s", simpleString)));
  11386. return Date(to!short(year), month, to!ubyte(day));
  11387. }
  11388. unittest
  11389. {
  11390. version(testStdDateTime)
  11391. {
  11392. assertThrown!DateTimeException(Date.fromSimpleString(""));
  11393. assertThrown!DateTimeException(Date.fromSimpleString("990704"));
  11394. assertThrown!DateTimeException(Date.fromSimpleString("0100704"));
  11395. assertThrown!DateTimeException(Date.fromSimpleString("2010070"));
  11396. assertThrown!DateTimeException(Date.fromSimpleString("2010070 "));
  11397. assertThrown!DateTimeException(Date.fromSimpleString("120100704"));
  11398. assertThrown!DateTimeException(Date.fromSimpleString("-0100704"));
  11399. assertThrown!DateTimeException(Date.fromSimpleString("+0100704"));
  11400. assertThrown!DateTimeException(Date.fromSimpleString("2010070a"));
  11401. assertThrown!DateTimeException(Date.fromSimpleString("20100a04"));
  11402. assertThrown!DateTimeException(Date.fromSimpleString("2010a704"));
  11403. assertThrown!DateTimeException(Date.fromSimpleString("99-07-04"));
  11404. assertThrown!DateTimeException(Date.fromSimpleString("010-07-04"));
  11405. assertThrown!DateTimeException(Date.fromSimpleString("2010-07-0"));
  11406. assertThrown!DateTimeException(Date.fromSimpleString("2010-07-0 "));
  11407. assertThrown!DateTimeException(Date.fromSimpleString("12010-07-04"));
  11408. assertThrown!DateTimeException(Date.fromSimpleString("-010-07-04"));
  11409. assertThrown!DateTimeException(Date.fromSimpleString("+010-07-04"));
  11410. assertThrown!DateTimeException(Date.fromSimpleString("2010-07-0a"));
  11411. assertThrown!DateTimeException(Date.fromSimpleString("2010-0a-04"));
  11412. assertThrown!DateTimeException(Date.fromSimpleString("2010-a7-04"));
  11413. assertThrown!DateTimeException(Date.fromSimpleString("2010/07/04"));
  11414. assertThrown!DateTimeException(Date.fromSimpleString("2010/7/04"));
  11415. assertThrown!DateTimeException(Date.fromSimpleString("2010/7/4"));
  11416. assertThrown!DateTimeException(Date.fromSimpleString("2010/07/4"));
  11417. assertThrown!DateTimeException(Date.fromSimpleString("2010-7-04"));
  11418. assertThrown!DateTimeException(Date.fromSimpleString("2010-7-4"));
  11419. assertThrown!DateTimeException(Date.fromSimpleString("2010-07-4"));
  11420. assertThrown!DateTimeException(Date.fromSimpleString("99Jul04"));
  11421. assertThrown!DateTimeException(Date.fromSimpleString("010Jul04"));
  11422. assertThrown!DateTimeException(Date.fromSimpleString("2010Jul0"));
  11423. assertThrown!DateTimeException(Date.fromSimpleString("2010Jul0 "));
  11424. assertThrown!DateTimeException(Date.fromSimpleString("12010Jul04"));
  11425. assertThrown!DateTimeException(Date.fromSimpleString("-010Jul04"));
  11426. assertThrown!DateTimeException(Date.fromSimpleString("+010Jul04"));
  11427. assertThrown!DateTimeException(Date.fromSimpleString("2010Jul0a"));
  11428. assertThrown!DateTimeException(Date.fromSimpleString("2010Jua04"));
  11429. assertThrown!DateTimeException(Date.fromSimpleString("2010aul04"));
  11430. assertThrown!DateTimeException(Date.fromSimpleString("99-Jul-04"));
  11431. assertThrown!DateTimeException(Date.fromSimpleString("010-Jul-04"));
  11432. assertThrown!DateTimeException(Date.fromSimpleString("2010-Jul-0"));
  11433. assertThrown!DateTimeException(Date.fromSimpleString("2010-Jul-0 "));
  11434. assertThrown!DateTimeException(Date.fromSimpleString("12010-Jul-04"));
  11435. assertThrown!DateTimeException(Date.fromSimpleString("-010-Jul-04"));
  11436. assertThrown!DateTimeException(Date.fromSimpleString("+010-Jul-04"));
  11437. assertThrown!DateTimeException(Date.fromSimpleString("2010-Jul-0a"));
  11438. assertThrown!DateTimeException(Date.fromSimpleString("2010-Jua-04"));
  11439. assertThrown!DateTimeException(Date.fromSimpleString("2010-Jal-04"));
  11440. assertThrown!DateTimeException(Date.fromSimpleString("2010-aul-04"));
  11441. assertThrown!DateTimeException(Date.fromSimpleString("20100704"));
  11442. assertThrown!DateTimeException(Date.fromSimpleString("2010-07-04"));
  11443. _assertPred!"=="(Date.fromSimpleString("1999-Jul-06"), Date(1999, 7, 6));
  11444. _assertPred!"=="(Date.fromSimpleString("-1999-Jul-06"), Date(-1999, 7, 6));
  11445. _assertPred!"=="(Date.fromSimpleString("+01999-Jul-06"), Date(1999, 7, 6));
  11446. _assertPred!"=="(Date.fromSimpleString("1999-Jul-06 "), Date(1999, 7, 6));
  11447. _assertPred!"=="(Date.fromSimpleString(" 1999-Jul-06"), Date(1999, 7, 6));
  11448. _assertPred!"=="(Date.fromSimpleString(" 1999-Jul-06 "), Date(1999, 7, 6));
  11449. //Verify Examples.
  11450. assert(Date.fromSimpleString("2010-Jul-04") == Date(2010, 7, 4));
  11451. assert(Date.fromSimpleString("1998-Dec-25") == Date(1998, 12, 25));
  11452. assert(Date.fromSimpleString("0000-Jan-05") == Date(0, 1, 5));
  11453. assert(Date.fromSimpleString("-0004-Jan-05") == Date(-4, 1, 5));
  11454. assert(Date.fromSimpleString(" 2010-Jul-04 ") == Date(2010, 7, 4));
  11455. }
  11456. }
  11457. //TODO Add function which takes a user-specified time format and produces a Date
  11458. //TODO Add function which takes pretty much any time-string and produces a Date
  11459. // Obviously, it will be less efficient, and it probably won't manage _every_
  11460. // possible date format, but a smart conversion function would be nice.
  11461. /++
  11462. Returns the $(D Date) farthest in the past which is representable by
  11463. $(D Date).
  11464. +/
  11465. @property static Date min() pure nothrow
  11466. {
  11467. auto date = Date.init;
  11468. date._year = short.min;
  11469. date._month = Month.jan;
  11470. date._day = 1;
  11471. return date;
  11472. }
  11473. unittest
  11474. {
  11475. version(testStdDateTime)
  11476. {
  11477. assert(Date.min.year < 0);
  11478. assert(Date.min < Date.max);
  11479. }
  11480. }
  11481. /++
  11482. Returns the $(D Date) farthest in the future which is representable by
  11483. $(D Date).
  11484. +/
  11485. @property static Date max() pure nothrow
  11486. {
  11487. auto date = Date.init;
  11488. date._year = short.max;
  11489. date._month = Month.dec;
  11490. date._day = 31;
  11491. return date;
  11492. }
  11493. unittest
  11494. {
  11495. version(testStdDateTime)
  11496. {
  11497. assert(Date.max.year > 0);
  11498. assert(Date.max > Date.min);
  11499. }
  11500. }
  11501. private:
  11502. /+
  11503. Whether the given values form a valid date.
  11504. Params:
  11505. year = The year to test.
  11506. month = The month of the Gregorian Calendar to test.
  11507. day = The day of the month to test.
  11508. +/
  11509. static bool _valid(int year, int month, int day) pure nothrow
  11510. {
  11511. if(!valid!"months"(month))
  11512. return false;
  11513. return valid!"days"(year, month, day);
  11514. }
  11515. /+
  11516. Adds the given number of days to this $(D Date). A negative number will
  11517. subtract.
  11518. The month will be adjusted along with the day if the number of days
  11519. added (or subtracted) would overflow (or underflow) the current month.
  11520. The year will be adjusted along with the month if the increase (or
  11521. decrease) to the month would cause it to overflow (or underflow) the
  11522. current year.
  11523. $(D addDays(numDays)) is effectively equivalent to
  11524. $(D date.dayOfGregorianCal = date.dayOfGregorianCal + days).
  11525. Params:
  11526. days = The number of days to add to this Date.
  11527. +/
  11528. ref Date addDays(long days) pure nothrow
  11529. {
  11530. dayOfGregorianCal = cast(int)(dayOfGregorianCal + days);
  11531. return this;
  11532. }
  11533. unittest
  11534. {
  11535. version(testStdDateTime)
  11536. {
  11537. //Test A.D.
  11538. {
  11539. auto date = Date(1999, 2, 28);
  11540. date.addDays(1);
  11541. _assertPred!"=="(date, Date(1999, 3, 1));
  11542. date.addDays(-1);
  11543. _assertPred!"=="(date, Date(1999, 2, 28));
  11544. }
  11545. {
  11546. auto date = Date(2000, 2, 28);
  11547. date.addDays(1);
  11548. _assertPred!"=="(date, Date(2000, 2, 29));
  11549. date.addDays(1);
  11550. _assertPred!"=="(date, Date(2000, 3, 1));
  11551. date.addDays(-1);
  11552. _assertPred!"=="(date, Date(2000, 2, 29));
  11553. }
  11554. {
  11555. auto date = Date(1999, 6, 30);
  11556. date.addDays(1);
  11557. _assertPred!"=="(date, Date(1999, 7, 1));
  11558. date.addDays(-1);
  11559. _assertPred!"=="(date, Date(1999, 6, 30));
  11560. }
  11561. {
  11562. auto date = Date(1999, 7, 31);
  11563. date.addDays(1);
  11564. _assertPred!"=="(date, Date(1999, 8, 1));
  11565. date.addDays(-1);
  11566. _assertPred!"=="(date, Date(1999, 7, 31));
  11567. }
  11568. {
  11569. auto date = Date(1999, 1, 1);
  11570. date.addDays(-1);
  11571. _assertPred!"=="(date, Date(1998, 12, 31));
  11572. date.addDays(1);
  11573. _assertPred!"=="(date, Date(1999, 1, 1));
  11574. }
  11575. {
  11576. auto date = Date(1999, 7, 6);
  11577. date.addDays(9);
  11578. _assertPred!"=="(date, Date(1999, 7, 15));
  11579. date.addDays(-11);
  11580. _assertPred!"=="(date, Date(1999, 7, 4));
  11581. date.addDays(30);
  11582. _assertPred!"=="(date, Date(1999, 8, 3));
  11583. date.addDays(-3);
  11584. _assertPred!"=="(date, Date(1999, 7, 31));
  11585. }
  11586. {
  11587. auto date = Date(1999, 7, 6);
  11588. date.addDays(365);
  11589. _assertPred!"=="(date, Date(2000, 7, 5));
  11590. date.addDays(-365);
  11591. _assertPred!"=="(date, Date(1999, 7, 6));
  11592. date.addDays(366);
  11593. _assertPred!"=="(date, Date(2000, 7, 6));
  11594. date.addDays(730);
  11595. _assertPred!"=="(date, Date(2002, 7, 6));
  11596. date.addDays(-1096);
  11597. _assertPred!"=="(date, Date(1999, 7, 6));
  11598. }
  11599. //Test B.C.
  11600. {
  11601. auto date = Date(-1999, 2, 28);
  11602. date.addDays(1);
  11603. _assertPred!"=="(date, Date(-1999, 3, 1));
  11604. date.addDays(-1);
  11605. _assertPred!"=="(date, Date(-1999, 2, 28));
  11606. }
  11607. {
  11608. auto date = Date(-2000, 2, 28);
  11609. date.addDays(1);
  11610. _assertPred!"=="(date, Date(-2000, 2, 29));
  11611. date.addDays(1);
  11612. _assertPred!"=="(date, Date(-2000, 3, 1));
  11613. date.addDays(-1);
  11614. _assertPred!"=="(date, Date(-2000, 2, 29));
  11615. }
  11616. {
  11617. auto date = Date(-1999, 6, 30);
  11618. date.addDays(1);
  11619. _assertPred!"=="(date, Date(-1999, 7, 1));
  11620. date.addDays(-1);
  11621. _assertPred!"=="(date, Date(-1999, 6, 30));
  11622. }
  11623. {
  11624. auto date = Date(-1999, 7, 31);
  11625. date.addDays(1);
  11626. _assertPred!"=="(date, Date(-1999, 8, 1));
  11627. date.addDays(-1);
  11628. _assertPred!"=="(date, Date(-1999, 7, 31));
  11629. }
  11630. {
  11631. auto date = Date(-1999, 1, 1);
  11632. date.addDays(-1);
  11633. _assertPred!"=="(date, Date(-2000, 12, 31));
  11634. date.addDays(1);
  11635. _assertPred!"=="(date, Date(-1999, 1, 1));
  11636. }
  11637. {
  11638. auto date = Date(-1999, 7, 6);
  11639. date.addDays(9);
  11640. _assertPred!"=="(date, Date(-1999, 7, 15));
  11641. date.addDays(-11);
  11642. _assertPred!"=="(date, Date(-1999, 7, 4));
  11643. date.addDays(30);
  11644. _assertPred!"=="(date, Date(-1999, 8, 3));
  11645. date.addDays(-3);
  11646. }
  11647. {
  11648. auto date = Date(-1999, 7, 6);
  11649. date.addDays(365);
  11650. _assertPred!"=="(date, Date(-1998, 7, 6));
  11651. date.addDays(-365);
  11652. _assertPred!"=="(date, Date(-1999, 7, 6));
  11653. date.addDays(366);
  11654. _assertPred!"=="(date, Date(-1998, 7, 7));
  11655. date.addDays(730);
  11656. _assertPred!"=="(date, Date(-1996, 7, 6));
  11657. date.addDays(-1096);
  11658. _assertPred!"=="(date, Date(-1999, 7, 6));
  11659. }
  11660. //Test Both
  11661. {
  11662. auto date = Date(1, 7, 6);
  11663. date.addDays(-365);
  11664. _assertPred!"=="(date, Date(0, 7, 6));
  11665. date.addDays(365);
  11666. _assertPred!"=="(date, Date(1, 7, 6));
  11667. date.addDays(-731);
  11668. _assertPred!"=="(date, Date(-1, 7, 6));
  11669. date.addDays(730);
  11670. _assertPred!"=="(date, Date(1, 7, 5));
  11671. }
  11672. const cdate = Date(1999, 7, 6);
  11673. immutable idate = Date(1999, 7, 6);
  11674. static assert(!__traits(compiles, cdate.addDays(12)));
  11675. static assert(!__traits(compiles, idate.addDays(12)));
  11676. }
  11677. }
  11678. pure invariant()
  11679. {
  11680. assert(valid!"months"(_month), "Invariant Failure: year [" ~
  11681. numToString(_year) ~
  11682. "] month [" ~
  11683. numToString(_month) ~
  11684. "] day [" ~
  11685. numToString(_day) ~
  11686. "]");
  11687. assert(valid!"days"(_year, _month, _day), "Invariant Failure: year [" ~
  11688. numToString(_year) ~
  11689. "] month [" ~
  11690. numToString(_month) ~
  11691. "] day [" ~
  11692. numToString(_day) ~
  11693. "]");
  11694. }
  11695. short _year = 1;
  11696. Month _month = Month.jan;
  11697. ubyte _day = 1;
  11698. }
  11699. /++
  11700. Represents a time of day with hours, minutes, and seconds. It uses 24 hour
  11701. time.
  11702. +/
  11703. struct TimeOfDay
  11704. {
  11705. public:
  11706. /++
  11707. Params:
  11708. hour = Hour of the day [0 - 24$(RPAREN).
  11709. minute = Minute of the hour [0 - 60$(RPAREN).
  11710. second = Second of the minute [0 - 60$(RPAREN).
  11711. Throws:
  11712. $(D DateTimeException) if the resulting $(D TimeOfDay) would be not
  11713. be valid.
  11714. +/
  11715. this(int hour, int minute, int second = 0) pure
  11716. {
  11717. enforceValid!"hours"(hour);
  11718. enforceValid!"minutes"(minute);
  11719. enforceValid!"seconds"(second);
  11720. _hour = cast(ubyte)hour;
  11721. _minute = cast(ubyte)minute;
  11722. _second = cast(ubyte)second;
  11723. }
  11724. unittest
  11725. {
  11726. version(testStdDateTime)
  11727. {
  11728. assert(TimeOfDay(0, 0) == TimeOfDay.init);
  11729. {
  11730. auto tod = TimeOfDay(0, 0);
  11731. _assertPred!"=="(tod._hour, 0);
  11732. _assertPred!"=="(tod._minute, 0);
  11733. _assertPred!"=="(tod._second, 0);
  11734. }
  11735. {
  11736. auto tod = TimeOfDay(12, 30, 33);
  11737. _assertPred!"=="(tod._hour, 12);
  11738. _assertPred!"=="(tod._minute, 30);
  11739. _assertPred!"=="(tod._second, 33);
  11740. }
  11741. {
  11742. auto tod = TimeOfDay(23, 59, 59);
  11743. _assertPred!"=="(tod._hour, 23);
  11744. _assertPred!"=="(tod._minute, 59);
  11745. _assertPred!"=="(tod._second, 59);
  11746. }
  11747. assertThrown!DateTimeException(TimeOfDay(24, 0, 0));
  11748. assertThrown!DateTimeException(TimeOfDay(0, 60, 0));
  11749. assertThrown!DateTimeException(TimeOfDay(0, 0, 60));
  11750. }
  11751. }
  11752. /++
  11753. Compares this $(D TimeOfDay) with the given $(D TimeOfDay).
  11754. Returns:
  11755. $(BOOKTABLE,
  11756. $(TR $(TD this &lt; rhs) $(TD &lt; 0))
  11757. $(TR $(TD this == rhs) $(TD 0))
  11758. $(TR $(TD this &gt; rhs) $(TD &gt; 0))
  11759. )
  11760. +/
  11761. int opCmp(in TimeOfDay rhs) const pure nothrow
  11762. {
  11763. if(_hour < rhs._hour)
  11764. return -1;
  11765. if(_hour > rhs._hour)
  11766. return 1;
  11767. if(_minute < rhs._minute)
  11768. return -1;
  11769. if(_minute > rhs._minute)
  11770. return 1;
  11771. if(_second < rhs._second)
  11772. return -1;
  11773. if(_second > rhs._second)
  11774. return 1;
  11775. return 0;
  11776. }
  11777. unittest
  11778. {
  11779. version(testStdDateTime)
  11780. {
  11781. _assertPred!("opCmp", "==")(TimeOfDay(0, 0, 0), TimeOfDay.init);
  11782. _assertPred!("opCmp", "==")(TimeOfDay(0, 0, 0), TimeOfDay(0, 0, 0));
  11783. _assertPred!("opCmp", "==")(TimeOfDay(12, 0, 0), TimeOfDay(12, 0, 0));
  11784. _assertPred!("opCmp", "==")(TimeOfDay(0, 30, 0), TimeOfDay(0, 30, 0));
  11785. _assertPred!("opCmp", "==")(TimeOfDay(0, 0, 33), TimeOfDay(0, 0, 33));
  11786. _assertPred!("opCmp", "==")(TimeOfDay(12, 30, 0), TimeOfDay(12, 30, 0));
  11787. _assertPred!("opCmp", "==")(TimeOfDay(12, 30, 33), TimeOfDay(12, 30, 33));
  11788. _assertPred!("opCmp", "==")(TimeOfDay(0, 30, 33), TimeOfDay(0, 30, 33));
  11789. _assertPred!("opCmp", "==")(TimeOfDay(0, 0, 33), TimeOfDay(0, 0, 33));
  11790. _assertPred!("opCmp", "<")(TimeOfDay(12, 30, 33), TimeOfDay(13, 30, 33));
  11791. _assertPred!("opCmp", ">")(TimeOfDay(13, 30, 33), TimeOfDay(12, 30, 33));
  11792. _assertPred!("opCmp", "<")(TimeOfDay(12, 30, 33), TimeOfDay(12, 31, 33));
  11793. _assertPred!("opCmp", ">")(TimeOfDay(12, 31, 33), TimeOfDay(12, 30, 33));
  11794. _assertPred!("opCmp", "<")(TimeOfDay(12, 30, 33), TimeOfDay(12, 30, 34));
  11795. _assertPred!("opCmp", ">")(TimeOfDay(12, 30, 34), TimeOfDay(12, 30, 33));
  11796. _assertPred!("opCmp", ">")(TimeOfDay(13, 30, 33), TimeOfDay(12, 30, 34));
  11797. _assertPred!("opCmp", "<")(TimeOfDay(12, 30, 34), TimeOfDay(13, 30, 33));
  11798. _assertPred!("opCmp", ">")(TimeOfDay(13, 30, 33), TimeOfDay(12, 31, 33));
  11799. _assertPred!("opCmp", "<")(TimeOfDay(12, 31, 33), TimeOfDay(13, 30, 33));
  11800. _assertPred!("opCmp", ">")(TimeOfDay(12, 31, 33), TimeOfDay(12, 30, 34));
  11801. _assertPred!("opCmp", "<")(TimeOfDay(12, 30, 34), TimeOfDay(12, 31, 33));
  11802. const ctod = TimeOfDay(12, 30, 33);
  11803. immutable itod = TimeOfDay(12, 30, 33);
  11804. static assert(__traits(compiles, ctod.opCmp(itod)));
  11805. static assert(__traits(compiles, itod.opCmp(ctod)));
  11806. }
  11807. }
  11808. /++
  11809. Hours passed midnight.
  11810. +/
  11811. @property ubyte hour() const pure nothrow
  11812. {
  11813. return _hour;
  11814. }
  11815. unittest
  11816. {
  11817. version(testStdDateTime)
  11818. {
  11819. _assertPred!"=="(TimeOfDay.init.hour, 0);
  11820. _assertPred!"=="(TimeOfDay(12, 0, 0).hour, 12);
  11821. const ctod = TimeOfDay(12, 0, 0);
  11822. immutable itod = TimeOfDay(12, 0, 0);
  11823. static assert(__traits(compiles, ctod.hour == 12));
  11824. static assert(__traits(compiles, itod.hour == 12));
  11825. }
  11826. }
  11827. /++
  11828. Hours passed midnight.
  11829. Params:
  11830. hour = The hour of the day to set this $(D TimeOfDay)'s hour to.
  11831. Throws:
  11832. $(D DateTimeException) if the given hour would result in an invalid
  11833. $(D TimeOfDay).
  11834. +/
  11835. @property void hour(int hour) pure
  11836. {
  11837. enforceValid!"hours"(hour);
  11838. _hour = cast(ubyte)hour;
  11839. }
  11840. unittest
  11841. {
  11842. version(testStdDateTime)
  11843. {
  11844. assertThrown!DateTimeException((){TimeOfDay(0, 0, 0).hour = 24;}());
  11845. auto tod = TimeOfDay(0, 0, 0);
  11846. tod.hour = 12;
  11847. _assertPred!"=="(tod, TimeOfDay(12, 0, 0));
  11848. const ctod = TimeOfDay(0, 0, 0);
  11849. immutable itod = TimeOfDay(0, 0, 0);
  11850. static assert(!__traits(compiles, ctod.hour = 12));
  11851. static assert(!__traits(compiles, itod.hour = 12));
  11852. }
  11853. }
  11854. /++
  11855. Minutes passed the hour.
  11856. +/
  11857. @property ubyte minute() const pure nothrow
  11858. {
  11859. return _minute;
  11860. }
  11861. unittest
  11862. {
  11863. version(testStdDateTime)
  11864. {
  11865. _assertPred!"=="(TimeOfDay.init.minute, 0);
  11866. _assertPred!"=="(TimeOfDay(0, 30, 0).minute, 30);
  11867. const ctod = TimeOfDay(0, 30, 0);
  11868. immutable itod = TimeOfDay(0, 30, 0);
  11869. static assert(__traits(compiles, ctod.minute == 30));
  11870. static assert(__traits(compiles, itod.minute == 30));
  11871. }
  11872. }
  11873. /++
  11874. Minutes passed the hour.
  11875. Params:
  11876. minute = The minute to set this $(D TimeOfDay)'s minute to.
  11877. Throws:
  11878. $(D DateTimeException) if the given minute would result in an
  11879. invalid $(D TimeOfDay).
  11880. +/
  11881. @property void minute(int minute) pure
  11882. {
  11883. enforceValid!"minutes"(minute);
  11884. _minute = cast(ubyte)minute;
  11885. }
  11886. unittest
  11887. {
  11888. version(testStdDateTime)
  11889. {
  11890. assertThrown!DateTimeException((){TimeOfDay(0, 0, 0).minute = 60;}());
  11891. auto tod = TimeOfDay(0, 0, 0);
  11892. tod.minute = 30;
  11893. _assertPred!"=="(tod, TimeOfDay(0, 30, 0));
  11894. const ctod = TimeOfDay(0, 0, 0);
  11895. immutable itod = TimeOfDay(0, 0, 0);
  11896. static assert(!__traits(compiles, ctod.minute = 30));
  11897. static assert(!__traits(compiles, itod.minute = 30));
  11898. }
  11899. }
  11900. /++
  11901. Seconds passed the minute.
  11902. +/
  11903. @property ubyte second() const pure nothrow
  11904. {
  11905. return _second;
  11906. }
  11907. unittest
  11908. {
  11909. version(testStdDateTime)
  11910. {
  11911. _assertPred!"=="(TimeOfDay.init.second, 0);
  11912. _assertPred!"=="(TimeOfDay(0, 0, 33).second, 33);
  11913. const ctod = TimeOfDay(0, 0, 33);
  11914. immutable itod = TimeOfDay(0, 0, 33);
  11915. static assert(__traits(compiles, ctod.second == 33));
  11916. static assert(__traits(compiles, itod.second == 33));
  11917. }
  11918. }
  11919. /++
  11920. Seconds passed the minute.
  11921. Params:
  11922. second = The second to set this $(D TimeOfDay)'s second to.
  11923. Throws:
  11924. $(D DateTimeException) if the given second would result in an
  11925. invalid $(D TimeOfDay).
  11926. +/
  11927. @property void second(int second) pure
  11928. {
  11929. enforceValid!"seconds"(second);
  11930. _second = cast(ubyte)second;
  11931. }
  11932. unittest
  11933. {
  11934. version(testStdDateTime)
  11935. {
  11936. assertThrown!DateTimeException((){TimeOfDay(0, 0, 0).second = 60;}());
  11937. auto tod = TimeOfDay(0, 0, 0);
  11938. tod.second = 33;
  11939. _assertPred!"=="(tod, TimeOfDay(0, 0, 33));
  11940. const ctod = TimeOfDay(0, 0, 0);
  11941. immutable itod = TimeOfDay(0, 0, 0);
  11942. static assert(!__traits(compiles, ctod.second = 33));
  11943. static assert(!__traits(compiles, itod.second = 33));
  11944. }
  11945. }
  11946. /++
  11947. Adds the given number of units to this $(D TimeOfDay). A negative number
  11948. will subtract.
  11949. The difference between rolling and adding is that rolling does not
  11950. affect larger units. So, for instance, if you roll a $(D TimeOfDay)
  11951. one hours's worth of minutes, then you get the exact same
  11952. $(D TimeOfDay).
  11953. Accepted units are $(D "hours"), $(D "minutes"), and $(D "seconds").
  11954. Params:
  11955. units = The units to add.
  11956. value = The number of $(D_PARAM units) to add to this
  11957. $(D TimeOfDay).
  11958. Examples:
  11959. --------------------
  11960. auto tod1 = TimeOfDay(7, 12, 0);
  11961. tod1.roll!"hours"(1);
  11962. assert(tod1 == TimeOfDay(8, 12, 0));
  11963. auto tod2 = TimeOfDay(7, 12, 0);
  11964. tod2.roll!"hours"(-1);
  11965. assert(tod2 == TimeOfDay(6, 12, 0));
  11966. auto tod3 = TimeOfDay(23, 59, 0);
  11967. tod3.roll!"minutes"(1);
  11968. assert(tod3 == TimeOfDay(23, 0, 0));
  11969. auto tod4 = TimeOfDay(0, 0, 0);
  11970. tod4.roll!"minutes"(-1);
  11971. assert(tod4 == TimeOfDay(0, 59, 0));
  11972. auto tod5 = TimeOfDay(23, 59, 59);
  11973. tod5.roll!"seconds"(1);
  11974. assert(tod5 == TimeOfDay(23, 59, 0));
  11975. auto tod6 = TimeOfDay(0, 0, 0);
  11976. tod6.roll!"seconds"(-1);
  11977. assert(tod6 == TimeOfDay(0, 0, 59));
  11978. --------------------
  11979. +/
  11980. /+ref TimeOfDay+/ void roll(string units)(long value) pure nothrow
  11981. if(units == "hours")
  11982. {
  11983. this += dur!"hours"(value);
  11984. }
  11985. //Verify Examples.
  11986. unittest
  11987. {
  11988. version(testStdDateTime)
  11989. {
  11990. auto tod1 = TimeOfDay(7, 12, 0);
  11991. tod1.roll!"hours"(1);
  11992. assert(tod1 == TimeOfDay(8, 12, 0));
  11993. auto tod2 = TimeOfDay(7, 12, 0);
  11994. tod2.roll!"hours"(-1);
  11995. assert(tod2 == TimeOfDay(6, 12, 0));
  11996. auto tod3 = TimeOfDay(23, 59, 0);
  11997. tod3.roll!"minutes"(1);
  11998. assert(tod3 == TimeOfDay(23, 0, 0));
  11999. auto tod4 = TimeOfDay(0, 0, 0);
  12000. tod4.roll!"minutes"(-1);
  12001. assert(tod4 == TimeOfDay(0, 59, 0));
  12002. auto tod5 = TimeOfDay(23, 59, 59);
  12003. tod5.roll!"seconds"(1);
  12004. assert(tod5 == TimeOfDay(23, 59, 0));
  12005. auto tod6 = TimeOfDay(0, 0, 0);
  12006. tod6.roll!"seconds"(-1);
  12007. assert(tod6 == TimeOfDay(0, 0, 59));
  12008. }
  12009. }
  12010. unittest
  12011. {
  12012. version(testStdDateTime)
  12013. {
  12014. const ctod = TimeOfDay(0, 0, 0);
  12015. immutable itod = TimeOfDay(0, 0, 0);
  12016. static assert(!__traits(compiles, ctod.roll!"hours"(53)));
  12017. static assert(!__traits(compiles, itod.roll!"hours"(53)));
  12018. }
  12019. }
  12020. //Shares documentation with "hours" version.
  12021. /+ref TimeOfDay+/ void roll(string units)(long value) pure nothrow
  12022. if(units == "minutes" ||
  12023. units == "seconds")
  12024. {
  12025. static if(units == "minutes")
  12026. enum memberVarStr = "minute";
  12027. else static if(units == "seconds")
  12028. enum memberVarStr = "second";
  12029. else
  12030. static assert(0);
  12031. value %= 60;
  12032. mixin("auto newVal = cast(ubyte)(_" ~ memberVarStr ~ ") + value;");
  12033. if(value < 0)
  12034. {
  12035. if(newVal < 0)
  12036. newVal += 60;
  12037. }
  12038. else if(newVal >= 60)
  12039. newVal -= 60;
  12040. mixin("_" ~ memberVarStr ~ " = cast(ubyte)newVal;");
  12041. }
  12042. //Test roll!"minutes"().
  12043. unittest
  12044. {
  12045. version(testStdDateTime)
  12046. {
  12047. static void testTOD(TimeOfDay orig, int minutes, in TimeOfDay expected, size_t line = __LINE__)
  12048. {
  12049. orig.roll!"minutes"(minutes);
  12050. _assertPred!"=="(orig, expected, "", __FILE__, line);
  12051. }
  12052. testTOD(TimeOfDay(12, 30, 33), 0, TimeOfDay(12, 30, 33));
  12053. testTOD(TimeOfDay(12, 30, 33), 1, TimeOfDay(12, 31, 33));
  12054. testTOD(TimeOfDay(12, 30, 33), 2, TimeOfDay(12, 32, 33));
  12055. testTOD(TimeOfDay(12, 30, 33), 3, TimeOfDay(12, 33, 33));
  12056. testTOD(TimeOfDay(12, 30, 33), 4, TimeOfDay(12, 34, 33));
  12057. testTOD(TimeOfDay(12, 30, 33), 5, TimeOfDay(12, 35, 33));
  12058. testTOD(TimeOfDay(12, 30, 33), 10, TimeOfDay(12, 40, 33));
  12059. testTOD(TimeOfDay(12, 30, 33), 15, TimeOfDay(12, 45, 33));
  12060. testTOD(TimeOfDay(12, 30, 33), 29, TimeOfDay(12, 59, 33));
  12061. testTOD(TimeOfDay(12, 30, 33), 30, TimeOfDay(12, 0, 33));
  12062. testTOD(TimeOfDay(12, 30, 33), 45, TimeOfDay(12, 15, 33));
  12063. testTOD(TimeOfDay(12, 30, 33), 60, TimeOfDay(12, 30, 33));
  12064. testTOD(TimeOfDay(12, 30, 33), 75, TimeOfDay(12, 45, 33));
  12065. testTOD(TimeOfDay(12, 30, 33), 90, TimeOfDay(12, 0, 33));
  12066. testTOD(TimeOfDay(12, 30, 33), 100, TimeOfDay(12, 10, 33));
  12067. testTOD(TimeOfDay(12, 30, 33), 689, TimeOfDay(12, 59, 33));
  12068. testTOD(TimeOfDay(12, 30, 33), 690, TimeOfDay(12, 0, 33));
  12069. testTOD(TimeOfDay(12, 30, 33), 691, TimeOfDay(12, 1, 33));
  12070. testTOD(TimeOfDay(12, 30, 33), 960, TimeOfDay(12, 30, 33));
  12071. testTOD(TimeOfDay(12, 30, 33), 1439, TimeOfDay(12, 29, 33));
  12072. testTOD(TimeOfDay(12, 30, 33), 1440, TimeOfDay(12, 30, 33));
  12073. testTOD(TimeOfDay(12, 30, 33), 1441, TimeOfDay(12, 31, 33));
  12074. testTOD(TimeOfDay(12, 30, 33), 2880, TimeOfDay(12, 30, 33));
  12075. testTOD(TimeOfDay(12, 30, 33), -1, TimeOfDay(12, 29, 33));
  12076. testTOD(TimeOfDay(12, 30, 33), -2, TimeOfDay(12, 28, 33));
  12077. testTOD(TimeOfDay(12, 30, 33), -3, TimeOfDay(12, 27, 33));
  12078. testTOD(TimeOfDay(12, 30, 33), -4, TimeOfDay(12, 26, 33));
  12079. testTOD(TimeOfDay(12, 30, 33), -5, TimeOfDay(12, 25, 33));
  12080. testTOD(TimeOfDay(12, 30, 33), -10, TimeOfDay(12, 20, 33));
  12081. testTOD(TimeOfDay(12, 30, 33), -15, TimeOfDay(12, 15, 33));
  12082. testTOD(TimeOfDay(12, 30, 33), -29, TimeOfDay(12, 1, 33));
  12083. testTOD(TimeOfDay(12, 30, 33), -30, TimeOfDay(12, 0, 33));
  12084. testTOD(TimeOfDay(12, 30, 33), -45, TimeOfDay(12, 45, 33));
  12085. testTOD(TimeOfDay(12, 30, 33), -60, TimeOfDay(12, 30, 33));
  12086. testTOD(TimeOfDay(12, 30, 33), -75, TimeOfDay(12, 15, 33));
  12087. testTOD(TimeOfDay(12, 30, 33), -90, TimeOfDay(12, 0, 33));
  12088. testTOD(TimeOfDay(12, 30, 33), -100, TimeOfDay(12, 50, 33));
  12089. testTOD(TimeOfDay(12, 30, 33), -749, TimeOfDay(12, 1, 33));
  12090. testTOD(TimeOfDay(12, 30, 33), -750, TimeOfDay(12, 0, 33));
  12091. testTOD(TimeOfDay(12, 30, 33), -751, TimeOfDay(12, 59, 33));
  12092. testTOD(TimeOfDay(12, 30, 33), -960, TimeOfDay(12, 30, 33));
  12093. testTOD(TimeOfDay(12, 30, 33), -1439, TimeOfDay(12, 31, 33));
  12094. testTOD(TimeOfDay(12, 30, 33), -1440, TimeOfDay(12, 30, 33));
  12095. testTOD(TimeOfDay(12, 30, 33), -1441, TimeOfDay(12, 29, 33));
  12096. testTOD(TimeOfDay(12, 30, 33), -2880, TimeOfDay(12, 30, 33));
  12097. testTOD(TimeOfDay(12, 0, 33), 1, TimeOfDay(12, 1, 33));
  12098. testTOD(TimeOfDay(12, 0, 33), 0, TimeOfDay(12, 0, 33));
  12099. testTOD(TimeOfDay(12, 0, 33), -1, TimeOfDay(12, 59, 33));
  12100. testTOD(TimeOfDay(11, 59, 33), 1, TimeOfDay(11, 0, 33));
  12101. testTOD(TimeOfDay(11, 59, 33), 0, TimeOfDay(11, 59, 33));
  12102. testTOD(TimeOfDay(11, 59, 33), -1, TimeOfDay(11, 58, 33));
  12103. testTOD(TimeOfDay(0, 0, 33), 1, TimeOfDay(0, 1, 33));
  12104. testTOD(TimeOfDay(0, 0, 33), 0, TimeOfDay(0, 0, 33));
  12105. testTOD(TimeOfDay(0, 0, 33), -1, TimeOfDay(0, 59, 33));
  12106. testTOD(TimeOfDay(23, 59, 33), 1, TimeOfDay(23, 0, 33));
  12107. testTOD(TimeOfDay(23, 59, 33), 0, TimeOfDay(23, 59, 33));
  12108. testTOD(TimeOfDay(23, 59, 33), -1, TimeOfDay(23, 58, 33));
  12109. const ctod = TimeOfDay(0, 0, 0);
  12110. immutable itod = TimeOfDay(0, 0, 0);
  12111. static assert(!__traits(compiles, ctod.roll!"minutes"(7)));
  12112. static assert(!__traits(compiles, itod.roll!"minutes"(7)));
  12113. //Verify Examples.
  12114. auto tod1 = TimeOfDay(7, 12, 0);
  12115. tod1.roll!"minutes"(1);
  12116. assert(tod1 == TimeOfDay(7, 13, 0));
  12117. auto tod2 = TimeOfDay(7, 12, 0);
  12118. tod2.roll!"minutes"(-1);
  12119. assert(tod2 == TimeOfDay(7, 11, 0));
  12120. auto tod3 = TimeOfDay(23, 59, 0);
  12121. tod3.roll!"minutes"(1);
  12122. assert(tod3 == TimeOfDay(23, 0, 0));
  12123. auto tod4 = TimeOfDay(0, 0, 0);
  12124. tod4.roll!"minutes"(-1);
  12125. assert(tod4 == TimeOfDay(0, 59, 0));
  12126. auto tod5 = TimeOfDay(7, 32, 12);
  12127. tod5.roll!"seconds"(1);
  12128. assert(tod5 == TimeOfDay(7, 32, 13));
  12129. auto tod6 = TimeOfDay(7, 32, 12);
  12130. tod6.roll!"seconds"(-1);
  12131. assert(tod6 == TimeOfDay(7, 32, 11));
  12132. auto tod7 = TimeOfDay(23, 59, 59);
  12133. tod7.roll!"seconds"(1);
  12134. assert(tod7 == TimeOfDay(23, 59, 0));
  12135. auto tod8 = TimeOfDay(0, 0, 0);
  12136. tod8.roll!"seconds"(-1);
  12137. assert(tod8 == TimeOfDay(0, 0, 59));
  12138. }
  12139. }
  12140. //Test roll!"seconds"().
  12141. unittest
  12142. {
  12143. version(testStdDateTime)
  12144. {
  12145. static void testTOD(TimeOfDay orig, int seconds, in TimeOfDay expected, size_t line = __LINE__)
  12146. {
  12147. orig.roll!"seconds"(seconds);
  12148. _assertPred!"=="(orig, expected, "", __FILE__, line);
  12149. }
  12150. testTOD(TimeOfDay(12, 30, 33), 0, TimeOfDay(12, 30, 33));
  12151. testTOD(TimeOfDay(12, 30, 33), 1, TimeOfDay(12, 30, 34));
  12152. testTOD(TimeOfDay(12, 30, 33), 2, TimeOfDay(12, 30, 35));
  12153. testTOD(TimeOfDay(12, 30, 33), 3, TimeOfDay(12, 30, 36));
  12154. testTOD(TimeOfDay(12, 30, 33), 4, TimeOfDay(12, 30, 37));
  12155. testTOD(TimeOfDay(12, 30, 33), 5, TimeOfDay(12, 30, 38));
  12156. testTOD(TimeOfDay(12, 30, 33), 10, TimeOfDay(12, 30, 43));
  12157. testTOD(TimeOfDay(12, 30, 33), 15, TimeOfDay(12, 30, 48));
  12158. testTOD(TimeOfDay(12, 30, 33), 26, TimeOfDay(12, 30, 59));
  12159. testTOD(TimeOfDay(12, 30, 33), 27, TimeOfDay(12, 30, 0));
  12160. testTOD(TimeOfDay(12, 30, 33), 30, TimeOfDay(12, 30, 3));
  12161. testTOD(TimeOfDay(12, 30, 33), 59, TimeOfDay(12, 30, 32));
  12162. testTOD(TimeOfDay(12, 30, 33), 60, TimeOfDay(12, 30, 33));
  12163. testTOD(TimeOfDay(12, 30, 33), 61, TimeOfDay(12, 30, 34));
  12164. testTOD(TimeOfDay(12, 30, 33), 1766, TimeOfDay(12, 30, 59));
  12165. testTOD(TimeOfDay(12, 30, 33), 1767, TimeOfDay(12, 30, 0));
  12166. testTOD(TimeOfDay(12, 30, 33), 1768, TimeOfDay(12, 30, 1));
  12167. testTOD(TimeOfDay(12, 30, 33), 2007, TimeOfDay(12, 30, 0));
  12168. testTOD(TimeOfDay(12, 30, 33), 3599, TimeOfDay(12, 30, 32));
  12169. testTOD(TimeOfDay(12, 30, 33), 3600, TimeOfDay(12, 30, 33));
  12170. testTOD(TimeOfDay(12, 30, 33), 3601, TimeOfDay(12, 30, 34));
  12171. testTOD(TimeOfDay(12, 30, 33), 7200, TimeOfDay(12, 30, 33));
  12172. testTOD(TimeOfDay(12, 30, 33), -1, TimeOfDay(12, 30, 32));
  12173. testTOD(TimeOfDay(12, 30, 33), -2, TimeOfDay(12, 30, 31));
  12174. testTOD(TimeOfDay(12, 30, 33), -3, TimeOfDay(12, 30, 30));
  12175. testTOD(TimeOfDay(12, 30, 33), -4, TimeOfDay(12, 30, 29));
  12176. testTOD(TimeOfDay(12, 30, 33), -5, TimeOfDay(12, 30, 28));
  12177. testTOD(TimeOfDay(12, 30, 33), -10, TimeOfDay(12, 30, 23));
  12178. testTOD(TimeOfDay(12, 30, 33), -15, TimeOfDay(12, 30, 18));
  12179. testTOD(TimeOfDay(12, 30, 33), -33, TimeOfDay(12, 30, 0));
  12180. testTOD(TimeOfDay(12, 30, 33), -34, TimeOfDay(12, 30, 59));
  12181. testTOD(TimeOfDay(12, 30, 33), -35, TimeOfDay(12, 30, 58));
  12182. testTOD(TimeOfDay(12, 30, 33), -59, TimeOfDay(12, 30, 34));
  12183. testTOD(TimeOfDay(12, 30, 33), -60, TimeOfDay(12, 30, 33));
  12184. testTOD(TimeOfDay(12, 30, 33), -61, TimeOfDay(12, 30, 32));
  12185. testTOD(TimeOfDay(12, 30, 0), 1, TimeOfDay(12, 30, 1));
  12186. testTOD(TimeOfDay(12, 30, 0), 0, TimeOfDay(12, 30, 0));
  12187. testTOD(TimeOfDay(12, 30, 0), -1, TimeOfDay(12, 30, 59));
  12188. testTOD(TimeOfDay(12, 0, 0), 1, TimeOfDay(12, 0, 1));
  12189. testTOD(TimeOfDay(12, 0, 0), 0, TimeOfDay(12, 0, 0));
  12190. testTOD(TimeOfDay(12, 0, 0), -1, TimeOfDay(12, 0, 59));
  12191. testTOD(TimeOfDay(0, 0, 0), 1, TimeOfDay(0, 0, 1));
  12192. testTOD(TimeOfDay(0, 0, 0), 0, TimeOfDay(0, 0, 0));
  12193. testTOD(TimeOfDay(0, 0, 0), -1, TimeOfDay(0, 0, 59));
  12194. testTOD(TimeOfDay(23, 59, 59), 1, TimeOfDay(23, 59, 0));
  12195. testTOD(TimeOfDay(23, 59, 59), 0, TimeOfDay(23, 59, 59));
  12196. testTOD(TimeOfDay(23, 59, 59), -1, TimeOfDay(23, 59, 58));
  12197. const ctod = TimeOfDay(0, 0, 0);
  12198. immutable itod = TimeOfDay(0, 0, 0);
  12199. static assert(!__traits(compiles, ctod.roll!"seconds"(7)));
  12200. static assert(!__traits(compiles, itod.roll!"seconds"(7)));
  12201. }
  12202. }
  12203. /++
  12204. Gives the result of adding or subtracting a duration from this
  12205. $(D TimeOfDay).
  12206. The legal types of arithmetic for $(D TimeOfDay) using this operator are
  12207. $(BOOKTABLE,
  12208. $(TR $(TD TimeOfDay) $(TD +) $(TD duration) $(TD -->) $(TD TimeOfDay))
  12209. $(TR $(TD TimeOfDay) $(TD -) $(TD duration) $(TD -->) $(TD TimeOfDay))
  12210. )
  12211. Params:
  12212. duration = The duration to add to or subtract from this
  12213. $(D TimeOfDay).
  12214. +/
  12215. TimeOfDay opBinary(string op, D)(in D duration) const pure nothrow
  12216. if((op == "+" || op == "-") &&
  12217. (is(Unqual!D == Duration) ||
  12218. is(Unqual!D == TickDuration)))
  12219. {
  12220. TimeOfDay retval = this;
  12221. static if(is(Unqual!D == Duration))
  12222. immutable hnsecs = duration.total!"hnsecs";
  12223. else static if(is(Unqual!D == TickDuration))
  12224. immutable hnsecs = duration.hnsecs;
  12225. //Ideally, this would just be
  12226. //return retval.addSeconds(convert!("hnsecs", "seconds")(unaryFun!(op ~ "a")(hnsecs)));
  12227. //But there isn't currently a pure version of unaryFun!().
  12228. static if(op == "+")
  12229. immutable signedHNSecs = hnsecs;
  12230. else static if(op == "-")
  12231. immutable signedHNSecs = -hnsecs;
  12232. else
  12233. static assert(0);
  12234. return retval.addSeconds(convert!("hnsecs", "seconds")(signedHNSecs));
  12235. }
  12236. unittest
  12237. {
  12238. version(testStdDateTime)
  12239. {
  12240. auto tod = TimeOfDay(12, 30, 33);
  12241. _assertPred!"=="(tod + dur!"hours"(7), TimeOfDay(19, 30, 33));
  12242. _assertPred!"=="(tod + dur!"hours"(-7), TimeOfDay(5, 30, 33));
  12243. _assertPred!"=="(tod + dur!"minutes"(7), TimeOfDay(12, 37, 33));
  12244. _assertPred!"=="(tod + dur!"minutes"(-7), TimeOfDay(12, 23, 33));
  12245. _assertPred!"=="(tod + dur!"seconds"(7), TimeOfDay(12, 30, 40));
  12246. _assertPred!"=="(tod + dur!"seconds"(-7), TimeOfDay(12, 30, 26));
  12247. _assertPred!"=="(tod + dur!"msecs"(7000), TimeOfDay(12, 30, 40));
  12248. _assertPred!"=="(tod + dur!"msecs"(-7000), TimeOfDay(12, 30, 26));
  12249. _assertPred!"=="(tod + dur!"usecs"(7_000_000), TimeOfDay(12, 30, 40));
  12250. _assertPred!"=="(tod + dur!"usecs"(-7_000_000), TimeOfDay(12, 30, 26));
  12251. _assertPred!"=="(tod + dur!"hnsecs"(70_000_000), TimeOfDay(12, 30, 40));
  12252. _assertPred!"=="(tod + dur!"hnsecs"(-70_000_000), TimeOfDay(12, 30, 26));
  12253. //This probably only runs in cases where gettimeofday() is used, but it's
  12254. //hard to do this test correctly with variable ticksPerSec.
  12255. if(TickDuration.ticksPerSec == 1_000_000)
  12256. {
  12257. _assertPred!"=="(tod + TickDuration.from!"usecs"(7_000_000), TimeOfDay(12, 30, 40));
  12258. _assertPred!"=="(tod + TickDuration.from!"usecs"(-7_000_000), TimeOfDay(12, 30, 26));
  12259. }
  12260. _assertPred!"=="(tod - dur!"hours"(-7), TimeOfDay(19, 30, 33));
  12261. _assertPred!"=="(tod - dur!"hours"(7), TimeOfDay(5, 30, 33));
  12262. _assertPred!"=="(tod - dur!"minutes"(-7), TimeOfDay(12, 37, 33));
  12263. _assertPred!"=="(tod - dur!"minutes"(7), TimeOfDay(12, 23, 33));
  12264. _assertPred!"=="(tod - dur!"seconds"(-7), TimeOfDay(12, 30, 40));
  12265. _assertPred!"=="(tod - dur!"seconds"(7), TimeOfDay(12, 30, 26));
  12266. _assertPred!"=="(tod - dur!"msecs"(-7000), TimeOfDay(12, 30, 40));
  12267. _assertPred!"=="(tod - dur!"msecs"(7000), TimeOfDay(12, 30, 26));
  12268. _assertPred!"=="(tod - dur!"usecs"(-7_000_000), TimeOfDay(12, 30, 40));
  12269. _assertPred!"=="(tod - dur!"usecs"(7_000_000), TimeOfDay(12, 30, 26));
  12270. _assertPred!"=="(tod - dur!"hnsecs"(-70_000_000), TimeOfDay(12, 30, 40));
  12271. _assertPred!"=="(tod - dur!"hnsecs"(70_000_000), TimeOfDay(12, 30, 26));
  12272. //This probably only runs in cases where gettimeofday() is used, but it's
  12273. //hard to do this test correctly with variable ticksPerSec.
  12274. if(TickDuration.ticksPerSec == 1_000_000)
  12275. {
  12276. _assertPred!"=="(tod - TickDuration.from!"usecs"(-7_000_000), TimeOfDay(12, 30, 40));
  12277. _assertPred!"=="(tod - TickDuration.from!"usecs"(7_000_000), TimeOfDay(12, 30, 26));
  12278. }
  12279. auto duration = dur!"hours"(11);
  12280. const ctod = TimeOfDay(12, 33, 30);
  12281. immutable itod = TimeOfDay(12, 33, 30);
  12282. static assert(__traits(compiles, tod + duration));
  12283. static assert(__traits(compiles, ctod + duration));
  12284. static assert(__traits(compiles, itod + duration));
  12285. static assert(__traits(compiles, tod - duration));
  12286. static assert(__traits(compiles, ctod - duration));
  12287. static assert(__traits(compiles, itod - duration));
  12288. }
  12289. }
  12290. /++
  12291. Gives the result of adding or subtracting a duration from this
  12292. $(D TimeOfDay), as well as assigning the result to this
  12293. $(D TimeOfDay).
  12294. The legal types of arithmetic for $(D TimeOfDay) using this operator are
  12295. $(BOOKTABLE,
  12296. $(TR $(TD TimeOfDay) $(TD +) $(TD duration) $(TD -->) $(TD TimeOfDay))
  12297. $(TR $(TD TimeOfDay) $(TD -) $(TD duration) $(TD -->) $(TD TimeOfDay))
  12298. )
  12299. Params:
  12300. duration = The duration to add to or subtract from this
  12301. $(D TimeOfDay).
  12302. +/
  12303. /+ref+/ TimeOfDay opOpAssign(string op, D)(in D duration) pure nothrow
  12304. if((op == "+" || op == "-") &&
  12305. (is(Unqual!D == Duration) ||
  12306. is(Unqual!D == TickDuration)))
  12307. {
  12308. static if(is(Unqual!D == Duration))
  12309. immutable hnsecs = duration.total!"hnsecs";
  12310. else static if(is(Unqual!D == TickDuration))
  12311. immutable hnsecs = duration.hnsecs;
  12312. //Ideally, this would just be
  12313. //return addSeconds(convert!("hnsecs", "seconds")(unaryFun!(op ~ "a")(hnsecs)));
  12314. //But there isn't currently a pure version of unaryFun!().
  12315. static if(op == "+")
  12316. immutable signedHNSecs = hnsecs;
  12317. else static if(op == "-")
  12318. immutable signedHNSecs = -hnsecs;
  12319. else
  12320. static assert(0);
  12321. return addSeconds(convert!("hnsecs", "seconds")(signedHNSecs));
  12322. }
  12323. unittest
  12324. {
  12325. version(testStdDateTime)
  12326. {
  12327. auto duration = dur!"hours"(12);
  12328. _assertPred!"+="(TimeOfDay(12, 30, 33), dur!"hours"(7), TimeOfDay(19, 30, 33));
  12329. _assertPred!"+="(TimeOfDay(12, 30, 33), dur!"hours"(-7), TimeOfDay(5, 30, 33));
  12330. _assertPred!"+="(TimeOfDay(12, 30, 33), dur!"minutes"(7), TimeOfDay(12, 37, 33));
  12331. _assertPred!"+="(TimeOfDay(12, 30, 33), dur!"minutes"(-7), TimeOfDay(12, 23, 33));
  12332. _assertPred!"+="(TimeOfDay(12, 30, 33), dur!"seconds"(7), TimeOfDay(12, 30, 40));
  12333. _assertPred!"+="(TimeOfDay(12, 30, 33), dur!"seconds"(-7), TimeOfDay(12, 30, 26));
  12334. _assertPred!"+="(TimeOfDay(12, 30, 33), dur!"msecs"(7000), TimeOfDay(12, 30, 40));
  12335. _assertPred!"+="(TimeOfDay(12, 30, 33), dur!"msecs"(-7000), TimeOfDay(12, 30, 26));
  12336. _assertPred!"+="(TimeOfDay(12, 30, 33), dur!"usecs"(7_000_000), TimeOfDay(12, 30, 40));
  12337. _assertPred!"+="(TimeOfDay(12, 30, 33), dur!"usecs"(-7_000_000), TimeOfDay(12, 30, 26));
  12338. _assertPred!"+="(TimeOfDay(12, 30, 33), dur!"hnsecs"(70_000_000), TimeOfDay(12, 30, 40));
  12339. _assertPred!"+="(TimeOfDay(12, 30, 33), dur!"hnsecs"(-70_000_000), TimeOfDay(12, 30, 26));
  12340. _assertPred!"-="(TimeOfDay(12, 30, 33), dur!"hours"(-7), TimeOfDay(19, 30, 33));
  12341. _assertPred!"-="(TimeOfDay(12, 30, 33), dur!"hours"(7), TimeOfDay(5, 30, 33));
  12342. _assertPred!"-="(TimeOfDay(12, 30, 33), dur!"minutes"(-7), TimeOfDay(12, 37, 33));
  12343. _assertPred!"-="(TimeOfDay(12, 30, 33), dur!"minutes"(7), TimeOfDay(12, 23, 33));
  12344. _assertPred!"-="(TimeOfDay(12, 30, 33), dur!"seconds"(-7), TimeOfDay(12, 30, 40));
  12345. _assertPred!"-="(TimeOfDay(12, 30, 33), dur!"seconds"(7), TimeOfDay(12, 30, 26));
  12346. _assertPred!"-="(TimeOfDay(12, 30, 33), dur!"msecs"(-7000), TimeOfDay(12, 30, 40));
  12347. _assertPred!"-="(TimeOfDay(12, 30, 33), dur!"msecs"(7000), TimeOfDay(12, 30, 26));
  12348. _assertPred!"-="(TimeOfDay(12, 30, 33), dur!"usecs"(-7_000_000), TimeOfDay(12, 30, 40));
  12349. _assertPred!"-="(TimeOfDay(12, 30, 33), dur!"usecs"(7_000_000), TimeOfDay(12, 30, 26));
  12350. _assertPred!"-="(TimeOfDay(12, 30, 33), dur!"hnsecs"(-70_000_000), TimeOfDay(12, 30, 40));
  12351. _assertPred!"-="(TimeOfDay(12, 30, 33), dur!"hnsecs"(70_000_000), TimeOfDay(12, 30, 26));
  12352. const ctod = TimeOfDay(12, 33, 30);
  12353. immutable itod = TimeOfDay(12, 33, 30);
  12354. static assert(!__traits(compiles, ctod += duration));
  12355. static assert(!__traits(compiles, itod += duration));
  12356. static assert(!__traits(compiles, ctod -= duration));
  12357. static assert(!__traits(compiles, itod -= duration));
  12358. }
  12359. }
  12360. /++
  12361. Gives the difference between two $(D TimeOfDay)s.
  12362. The legal types of arithmetic for $(D TimeOfDay) using this operator are
  12363. $(BOOKTABLE,
  12364. $(TR $(TD TimeOfDay) $(TD -) $(TD TimeOfDay) $(TD -->) $(TD duration))
  12365. )
  12366. Params:
  12367. rhs = The $(D TimeOfDay) to subtract from this one.
  12368. +/
  12369. Duration opBinary(string op)(in TimeOfDay rhs) const pure nothrow
  12370. if(op == "-")
  12371. {
  12372. immutable lhsSec = _hour * 3600 + _minute * 60 + _second;
  12373. immutable rhsSec = rhs._hour * 3600 + rhs._minute * 60 + rhs._second;
  12374. return dur!"seconds"(lhsSec - rhsSec);
  12375. }
  12376. unittest
  12377. {
  12378. version(testStdDateTime)
  12379. {
  12380. auto tod = TimeOfDay(12, 30, 33);
  12381. _assertPred!"=="(TimeOfDay(7, 12, 52) - TimeOfDay(12, 30, 33), dur!"seconds"(-19_061));
  12382. _assertPred!"=="(TimeOfDay(12, 30, 33) - TimeOfDay(7, 12, 52), dur!"seconds"(19_061));
  12383. _assertPred!"=="(TimeOfDay(12, 30, 33) - TimeOfDay(14, 30, 33), dur!"seconds"(-7200));
  12384. _assertPred!"=="(TimeOfDay(14, 30, 33) - TimeOfDay(12, 30, 33), dur!"seconds"(7200));
  12385. _assertPred!"=="(TimeOfDay(12, 30, 33) - TimeOfDay(12, 34, 33), dur!"seconds"(-240));
  12386. _assertPred!"=="(TimeOfDay(12, 34, 33) - TimeOfDay(12, 30, 33), dur!"seconds"(240));
  12387. _assertPred!"=="(TimeOfDay(12, 30, 33) - TimeOfDay(12, 30, 34), dur!"seconds"(-1));
  12388. _assertPred!"=="(TimeOfDay(12, 30, 34) - TimeOfDay(12, 30, 33), dur!"seconds"(1));
  12389. const ctod = TimeOfDay(12, 30, 33);
  12390. immutable itod = TimeOfDay(12, 30, 33);
  12391. static assert(__traits(compiles, tod - tod));
  12392. static assert(__traits(compiles, ctod - tod));
  12393. static assert(__traits(compiles, itod - tod));
  12394. static assert(__traits(compiles, tod - ctod));
  12395. static assert(__traits(compiles, ctod - ctod));
  12396. static assert(__traits(compiles, itod - ctod));
  12397. static assert(__traits(compiles, tod - itod));
  12398. static assert(__traits(compiles, ctod - itod));
  12399. static assert(__traits(compiles, itod - itod));
  12400. }
  12401. }
  12402. /++
  12403. Converts this $(D TimeOfDay) to a string with the format HHMMSS.
  12404. Examples:
  12405. --------------------
  12406. assert(TimeOfDay(0, 0, 0).toISOString() == "000000");
  12407. assert(TimeOfDay(12, 30, 33).toISOString() == "123033");
  12408. --------------------
  12409. +/
  12410. string toISOString() const nothrow
  12411. {
  12412. try
  12413. return format("%02d%02d%02d", _hour, _minute, _second);
  12414. catch(Exception e)
  12415. assert(0, "format() threw.");
  12416. }
  12417. unittest
  12418. {
  12419. version(testStdDateTime)
  12420. {
  12421. auto tod = TimeOfDay(12, 30, 33);
  12422. const ctod = TimeOfDay(12, 30, 33);
  12423. immutable itod = TimeOfDay(12, 30, 33);
  12424. static assert(__traits(compiles, tod.toISOString()));
  12425. static assert(__traits(compiles, ctod.toISOString()));
  12426. static assert(__traits(compiles, itod.toISOString()));
  12427. //Verify Examples.
  12428. assert(TimeOfDay(0, 0, 0).toISOString() == "000000");
  12429. assert(TimeOfDay(12, 30, 33).toISOString() == "123033");
  12430. }
  12431. }
  12432. /++
  12433. Converts this $(D TimeOfDay) to a string with the format HH:MM:SS.
  12434. Examples:
  12435. --------------------
  12436. assert(TimeOfDay(0, 0, 0).toISOExtString() == "000000");
  12437. assert(TimeOfDay(12, 30, 33).toISOExtString() == "123033");
  12438. --------------------
  12439. +/
  12440. string toISOExtString() const nothrow
  12441. {
  12442. try
  12443. return format("%02d:%02d:%02d", _hour, _minute, _second);
  12444. catch(Exception e)
  12445. assert(0, "format() threw.");
  12446. }
  12447. /++
  12448. $(RED Scheduled for deprecation in November 2011.
  12449. Please use toISOExtString instead.)
  12450. +/
  12451. alias toISOExtString toISOExtendedString;
  12452. unittest
  12453. {
  12454. version(testStdDateTime)
  12455. {
  12456. auto tod = TimeOfDay(12, 30, 33);
  12457. const ctod = TimeOfDay(12, 30, 33);
  12458. immutable itod = TimeOfDay(12, 30, 33);
  12459. static assert(__traits(compiles, tod.toISOExtString()));
  12460. static assert(__traits(compiles, ctod.toISOExtString()));
  12461. static assert(__traits(compiles, itod.toISOExtString()));
  12462. //Verify Examples.
  12463. assert(TimeOfDay(0, 0, 0).toISOExtString() == "00:00:00");
  12464. assert(TimeOfDay(12, 30, 33).toISOExtString() == "12:30:33");
  12465. }
  12466. }
  12467. /+
  12468. Converts this $(D TimeOfDay) to a string.
  12469. +/
  12470. //Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
  12471. //have versions of toString() with extra modifiers, so we define one version
  12472. //with modifiers and one without.
  12473. string toString()
  12474. {
  12475. return toISOExtString();
  12476. }
  12477. /++
  12478. Converts this TimeOfDay to a string.
  12479. +/
  12480. //Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
  12481. //have versions of toString() with extra modifiers, so we define one version
  12482. //with modifiers and one without.
  12483. string toString() const nothrow
  12484. {
  12485. return toISOExtString();
  12486. }
  12487. unittest
  12488. {
  12489. version(testStdDateTime)
  12490. {
  12491. auto tod = TimeOfDay(12, 30, 33);
  12492. const ctod = TimeOfDay(12, 30, 33);
  12493. immutable itod = TimeOfDay(12, 30, 33);
  12494. static assert(__traits(compiles, tod.toString()));
  12495. static assert(__traits(compiles, ctod.toString()));
  12496. static assert(__traits(compiles, itod.toString()));
  12497. }
  12498. }
  12499. //TODO Add a function which returns a string in a user-specified format.
  12500. /++
  12501. Creates a $(D TimeOfDay) from a string with the format HHMMSS.
  12502. Whitespace is stripped from the given string.
  12503. Params:
  12504. isoString = A string formatted in the ISO format for times.
  12505. Throws:
  12506. $(D DateTimeException) if the given string is not in the ISO format
  12507. or if the resulting $(D TimeOfDay) would not be valid.
  12508. Examples:
  12509. --------------------
  12510. assert(TimeOfDay.fromISOString("000000") == TimeOfDay(0, 0, 0));
  12511. assert(TimeOfDay.fromISOString("123033") == TimeOfDay(12, 30, 33));
  12512. assert(TimeOfDay.fromISOString(" 123033 ") == TimeOfDay(12, 30, 33));
  12513. --------------------
  12514. +/
  12515. static TimeOfDay fromISOString(S)(in S isoString)
  12516. if(isSomeString!S)
  12517. {
  12518. auto dstr = to!dstring(strip(isoString));
  12519. enforce(dstr.length == 6, new DateTimeException(format("Invalid ISO String: %s", isoString)));
  12520. auto hours = dstr[0 .. 2];
  12521. auto minutes = dstr[2 .. 4];
  12522. auto seconds = dstr[4 .. $];
  12523. enforce(!canFind!(not!isDigit)(hours), new DateTimeException(format("Invalid ISO String: %s", isoString)));
  12524. enforce(!canFind!(not!isDigit)(minutes), new DateTimeException(format("Invalid ISO String: %s", isoString)));
  12525. enforce(!canFind!(not!isDigit)(seconds), new DateTimeException(format("Invalid ISO String: %s", isoString)));
  12526. return TimeOfDay(to!int(hours), to!int(minutes), to!int(seconds));
  12527. }
  12528. unittest
  12529. {
  12530. version(testStdDateTime)
  12531. {
  12532. assertThrown!DateTimeException(TimeOfDay.fromISOString(""));
  12533. assertThrown!DateTimeException(TimeOfDay.fromISOString("0"));
  12534. assertThrown!DateTimeException(TimeOfDay.fromISOString("00"));
  12535. assertThrown!DateTimeException(TimeOfDay.fromISOString("000"));
  12536. assertThrown!DateTimeException(TimeOfDay.fromISOString("0000"));
  12537. assertThrown!DateTimeException(TimeOfDay.fromISOString("00000"));
  12538. assertThrown!DateTimeException(TimeOfDay.fromISOString("13033"));
  12539. assertThrown!DateTimeException(TimeOfDay.fromISOString("1277"));
  12540. assertThrown!DateTimeException(TimeOfDay.fromISOString("12707"));
  12541. assertThrown!DateTimeException(TimeOfDay.fromISOString("12070"));
  12542. assertThrown!DateTimeException(TimeOfDay.fromISOString("12303a"));
  12543. assertThrown!DateTimeException(TimeOfDay.fromISOString("1230a3"));
  12544. assertThrown!DateTimeException(TimeOfDay.fromISOString("123a33"));
  12545. assertThrown!DateTimeException(TimeOfDay.fromISOString("12a033"));
  12546. assertThrown!DateTimeException(TimeOfDay.fromISOString("1a0033"));
  12547. assertThrown!DateTimeException(TimeOfDay.fromISOString("a20033"));
  12548. assertThrown!DateTimeException(TimeOfDay.fromISOString("1200330"));
  12549. assertThrown!DateTimeException(TimeOfDay.fromISOString("0120033"));
  12550. assertThrown!DateTimeException(TimeOfDay.fromISOString("-120033"));
  12551. assertThrown!DateTimeException(TimeOfDay.fromISOString("+120033"));
  12552. assertThrown!DateTimeException(TimeOfDay.fromISOString("120033am"));
  12553. assertThrown!DateTimeException(TimeOfDay.fromISOString("120033pm"));
  12554. assertThrown!DateTimeException(TimeOfDay.fromISOString("0::"));
  12555. assertThrown!DateTimeException(TimeOfDay.fromISOString(":0:"));
  12556. assertThrown!DateTimeException(TimeOfDay.fromISOString("::0"));
  12557. assertThrown!DateTimeException(TimeOfDay.fromISOString("0:0:0"));
  12558. assertThrown!DateTimeException(TimeOfDay.fromISOString("0:0:00"));
  12559. assertThrown!DateTimeException(TimeOfDay.fromISOString("0:00:0"));
  12560. assertThrown!DateTimeException(TimeOfDay.fromISOString("00:0:0"));
  12561. assertThrown!DateTimeException(TimeOfDay.fromISOString("00:00:0"));
  12562. assertThrown!DateTimeException(TimeOfDay.fromISOString("00:0:00"));
  12563. assertThrown!DateTimeException(TimeOfDay.fromISOString("13:0:33"));
  12564. assertThrown!DateTimeException(TimeOfDay.fromISOString("12:7:7"));
  12565. assertThrown!DateTimeException(TimeOfDay.fromISOString("12:7:07"));
  12566. assertThrown!DateTimeException(TimeOfDay.fromISOString("12:07:0"));
  12567. assertThrown!DateTimeException(TimeOfDay.fromISOString("12:30:3a"));
  12568. assertThrown!DateTimeException(TimeOfDay.fromISOString("12:30:a3"));
  12569. assertThrown!DateTimeException(TimeOfDay.fromISOString("12:3a:33"));
  12570. assertThrown!DateTimeException(TimeOfDay.fromISOString("12:a0:33"));
  12571. assertThrown!DateTimeException(TimeOfDay.fromISOString("1a:00:33"));
  12572. assertThrown!DateTimeException(TimeOfDay.fromISOString("a2:00:33"));
  12573. assertThrown!DateTimeException(TimeOfDay.fromISOString("12:003:30"));
  12574. assertThrown!DateTimeException(TimeOfDay.fromISOString("120:03:30"));
  12575. assertThrown!DateTimeException(TimeOfDay.fromISOString("012:00:33"));
  12576. assertThrown!DateTimeException(TimeOfDay.fromISOString("01:200:33"));
  12577. assertThrown!DateTimeException(TimeOfDay.fromISOString("-12:00:33"));
  12578. assertThrown!DateTimeException(TimeOfDay.fromISOString("+12:00:33"));
  12579. assertThrown!DateTimeException(TimeOfDay.fromISOString("12:00:33am"));
  12580. assertThrown!DateTimeException(TimeOfDay.fromISOString("12:00:33pm"));
  12581. assertThrown!DateTimeException(TimeOfDay.fromISOString("12:00:33"));
  12582. _assertPred!"=="(TimeOfDay.fromISOString("011217"), TimeOfDay(1, 12, 17));
  12583. _assertPred!"=="(TimeOfDay.fromISOString("001412"), TimeOfDay(0, 14, 12));
  12584. _assertPred!"=="(TimeOfDay.fromISOString("000007"), TimeOfDay(0, 0, 7));
  12585. _assertPred!"=="(TimeOfDay.fromISOString("011217 "), TimeOfDay(1, 12, 17));
  12586. _assertPred!"=="(TimeOfDay.fromISOString(" 011217"), TimeOfDay(1, 12, 17));
  12587. _assertPred!"=="(TimeOfDay.fromISOString(" 011217 "), TimeOfDay(1, 12, 17));
  12588. //Verify Examples.
  12589. assert(TimeOfDay.fromISOString("000000") == TimeOfDay(0, 0, 0));
  12590. assert(TimeOfDay.fromISOString("123033") == TimeOfDay(12, 30, 33));
  12591. assert(TimeOfDay.fromISOString(" 123033 ") == TimeOfDay(12, 30, 33));
  12592. }
  12593. }
  12594. /++
  12595. Creates a $(D TimeOfDay) from a string with the format HH:MM:SS.
  12596. Whitespace is stripped from the given string.
  12597. Params:
  12598. isoString = A string formatted in the ISO Extended format for times.
  12599. Throws:
  12600. $(D DateTimeException) if the given string is not in the ISO
  12601. Extended format or if the resulting $(D TimeOfDay) would not be
  12602. valid.
  12603. Examples:
  12604. --------------------
  12605. assert(TimeOfDay.fromISOExtString("00:00:00") == TimeOfDay(0, 0, 0));
  12606. assert(TimeOfDay.fromISOExtString("12:30:33") == TimeOfDay(12, 30, 33));
  12607. assert(TimeOfDay.fromISOExtString(" 12:30:33 ") == TimeOfDay(12, 30, 33));
  12608. --------------------
  12609. +/
  12610. static TimeOfDay fromISOExtString(S)(in S isoExtString)
  12611. if(isSomeString!S)
  12612. {
  12613. auto dstr = to!dstring(strip(isoExtString));
  12614. enforce(dstr.length == 8, new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
  12615. auto hours = dstr[0 .. 2];
  12616. auto minutes = dstr[3 .. 5];
  12617. auto seconds = dstr[6 .. $];
  12618. enforce(dstr[2] == ':', new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
  12619. enforce(dstr[5] == ':', new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
  12620. enforce(!canFind!(not!isDigit)(hours),
  12621. new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
  12622. enforce(!canFind!(not!isDigit)(minutes),
  12623. new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
  12624. enforce(!canFind!(not!isDigit)(seconds),
  12625. new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
  12626. return TimeOfDay(to!int(hours), to!int(minutes), to!int(seconds));
  12627. }
  12628. /++
  12629. $(RED Scheduled for deprecation in November 2011.
  12630. Please use fromISOExtString instead.)
  12631. +/
  12632. static TimeOfDay fromISOExtendedString(S)(in S isoExtString)
  12633. if(isSomeString!(S))
  12634. {
  12635. pragma(msg, softDeprec!("2.053", "November 2011", "fromISOExtendedString", "fromISOExtString"));
  12636. return fromISOExtString!string(isoExtString);
  12637. }
  12638. unittest
  12639. {
  12640. version(testStdDateTime)
  12641. {
  12642. assertThrown!DateTimeException(TimeOfDay.fromISOExtString(""));
  12643. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("0"));
  12644. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("00"));
  12645. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("000"));
  12646. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("0000"));
  12647. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("00000"));
  12648. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("13033"));
  12649. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("1277"));
  12650. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("12707"));
  12651. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("12070"));
  12652. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("12303a"));
  12653. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("1230a3"));
  12654. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("123a33"));
  12655. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("12a033"));
  12656. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("1a0033"));
  12657. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("a20033"));
  12658. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("1200330"));
  12659. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("0120033"));
  12660. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("-120033"));
  12661. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("+120033"));
  12662. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("120033am"));
  12663. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("120033pm"));
  12664. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("0::"));
  12665. assertThrown!DateTimeException(TimeOfDay.fromISOExtString(":0:"));
  12666. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("::0"));
  12667. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("0:0:0"));
  12668. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("0:0:00"));
  12669. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("0:00:0"));
  12670. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("00:0:0"));
  12671. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("00:00:0"));
  12672. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("00:0:00"));
  12673. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("13:0:33"));
  12674. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("12:7:7"));
  12675. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("12:7:07"));
  12676. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("12:07:0"));
  12677. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("12:30:3a"));
  12678. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("12:30:a3"));
  12679. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("12:3a:33"));
  12680. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("12:a0:33"));
  12681. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("1a:00:33"));
  12682. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("a2:00:33"));
  12683. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("12:003:30"));
  12684. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("120:03:30"));
  12685. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("012:00:33"));
  12686. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("01:200:33"));
  12687. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("-12:00:33"));
  12688. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("+12:00:33"));
  12689. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("12:00:33am"));
  12690. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("12:00:33pm"));
  12691. assertThrown!DateTimeException(TimeOfDay.fromISOExtString("120033"));
  12692. _assertPred!"=="(TimeOfDay.fromISOExtString("01:12:17"), TimeOfDay(1, 12, 17));
  12693. _assertPred!"=="(TimeOfDay.fromISOExtString("00:14:12"), TimeOfDay(0, 14, 12));
  12694. _assertPred!"=="(TimeOfDay.fromISOExtString("00:00:07"), TimeOfDay(0, 0, 7));
  12695. _assertPred!"=="(TimeOfDay.fromISOExtString("01:12:17 "), TimeOfDay(1, 12, 17));
  12696. _assertPred!"=="(TimeOfDay.fromISOExtString(" 01:12:17"), TimeOfDay(1, 12, 17));
  12697. _assertPred!"=="(TimeOfDay.fromISOExtString(" 01:12:17 "), TimeOfDay(1, 12, 17));
  12698. //Verify Examples.
  12699. assert(TimeOfDay.fromISOExtString("00:00:00") == TimeOfDay(0, 0, 0));
  12700. assert(TimeOfDay.fromISOExtString("12:30:33") == TimeOfDay(12, 30, 33));
  12701. assert(TimeOfDay.fromISOExtString(" 12:30:33 ") == TimeOfDay(12, 30, 33));
  12702. }
  12703. }
  12704. //TODO Add function which takes a user-specified time format and produces a TimeOfDay
  12705. //TODO Add function which takes pretty much any time-string and produces a TimeOfDay
  12706. // Obviously, it will be less efficient, and it probably won't manage _every_
  12707. // possible date format, but a smart conversion function would be nice.
  12708. /++
  12709. Returns midnight.
  12710. +/
  12711. @property static TimeOfDay min() pure nothrow
  12712. {
  12713. return TimeOfDay.init;
  12714. }
  12715. unittest
  12716. {
  12717. version(testStdDateTime)
  12718. {
  12719. assert(TimeOfDay.min.hour == 0);
  12720. assert(TimeOfDay.min.minute == 0);
  12721. assert(TimeOfDay.min.second == 0);
  12722. assert(TimeOfDay.min < TimeOfDay.max);
  12723. }
  12724. }
  12725. /++
  12726. Returns one second short of midnight.
  12727. +/
  12728. @property static TimeOfDay max() pure nothrow
  12729. {
  12730. auto tod = TimeOfDay.init;
  12731. tod._hour = maxHour;
  12732. tod._minute = maxMinute;
  12733. tod._second = maxSecond;
  12734. return tod;
  12735. }
  12736. unittest
  12737. {
  12738. version(testStdDateTime)
  12739. {
  12740. assert(TimeOfDay.max.hour == 23);
  12741. assert(TimeOfDay.max.minute == 59);
  12742. assert(TimeOfDay.max.second == 59);
  12743. assert(TimeOfDay.max > TimeOfDay.min);
  12744. }
  12745. }
  12746. private:
  12747. /+
  12748. Add seconds to the time of day. Negative values will subtract. If the
  12749. number of seconds overflows (or underflows), then the seconds will wrap,
  12750. increasing (or decreasing) the number of minutes accordingly. If the
  12751. number of minutes overflows (or underflows), then the minutes will wrap.
  12752. If the number of minutes overflows(or underflows), then the hour will
  12753. wrap. (e.g. adding 90 seconds to 23:59:00 would result in 00:00:30).
  12754. Params:
  12755. seconds = The number of seconds to add to this TimeOfDay.
  12756. +/
  12757. ref TimeOfDay addSeconds(long seconds) pure nothrow
  12758. {
  12759. long hnsecs = convert!("seconds", "hnsecs")(seconds);
  12760. hnsecs += convert!("hours", "hnsecs")(_hour);
  12761. hnsecs += convert!("minutes", "hnsecs")(_minute);
  12762. hnsecs += convert!("seconds", "hnsecs")(_second);
  12763. hnsecs %= convert!("days", "hnsecs")(1);
  12764. if(hnsecs < 0)
  12765. hnsecs += convert!("days", "hnsecs")(1);
  12766. immutable newHours = splitUnitsFromHNSecs!"hours"(hnsecs);
  12767. immutable newMinutes = splitUnitsFromHNSecs!"minutes"(hnsecs);
  12768. immutable newSeconds = splitUnitsFromHNSecs!"seconds"(hnsecs);
  12769. _hour = cast(ubyte)newHours;
  12770. _minute = cast(ubyte)newMinutes;
  12771. _second = cast(ubyte)newSeconds;
  12772. return this;
  12773. }
  12774. unittest
  12775. {
  12776. version(testStdDateTime)
  12777. {
  12778. static void testTOD(TimeOfDay orig, int seconds, in TimeOfDay expected, size_t line = __LINE__)
  12779. {
  12780. orig.addSeconds(seconds);
  12781. _assertPred!"=="(orig, expected, "", __FILE__, line);
  12782. }
  12783. testTOD(TimeOfDay(12, 30, 33), 0, TimeOfDay(12, 30, 33));
  12784. testTOD(TimeOfDay(12, 30, 33), 1, TimeOfDay(12, 30, 34));
  12785. testTOD(TimeOfDay(12, 30, 33), 2, TimeOfDay(12, 30, 35));
  12786. testTOD(TimeOfDay(12, 30, 33), 3, TimeOfDay(12, 30, 36));
  12787. testTOD(TimeOfDay(12, 30, 33), 4, TimeOfDay(12, 30, 37));
  12788. testTOD(TimeOfDay(12, 30, 33), 5, TimeOfDay(12, 30, 38));
  12789. testTOD(TimeOfDay(12, 30, 33), 10, TimeOfDay(12, 30, 43));
  12790. testTOD(TimeOfDay(12, 30, 33), 15, TimeOfDay(12, 30, 48));
  12791. testTOD(TimeOfDay(12, 30, 33), 26, TimeOfDay(12, 30, 59));
  12792. testTOD(TimeOfDay(12, 30, 33), 27, TimeOfDay(12, 31, 0));
  12793. testTOD(TimeOfDay(12, 30, 33), 30, TimeOfDay(12, 31, 3));
  12794. testTOD(TimeOfDay(12, 30, 33), 59, TimeOfDay(12, 31, 32));
  12795. testTOD(TimeOfDay(12, 30, 33), 60, TimeOfDay(12, 31, 33));
  12796. testTOD(TimeOfDay(12, 30, 33), 61, TimeOfDay(12, 31, 34));
  12797. testTOD(TimeOfDay(12, 30, 33), 1766, TimeOfDay(12, 59, 59));
  12798. testTOD(TimeOfDay(12, 30, 33), 1767, TimeOfDay(13, 0, 0));
  12799. testTOD(TimeOfDay(12, 30, 33), 1768, TimeOfDay(13, 0, 1));
  12800. testTOD(TimeOfDay(12, 30, 33), 2007, TimeOfDay(13, 4, 0));
  12801. testTOD(TimeOfDay(12, 30, 33), 3599, TimeOfDay(13, 30, 32));
  12802. testTOD(TimeOfDay(12, 30, 33), 3600, TimeOfDay(13, 30, 33));
  12803. testTOD(TimeOfDay(12, 30, 33), 3601, TimeOfDay(13, 30, 34));
  12804. testTOD(TimeOfDay(12, 30, 33), 7200, TimeOfDay(14, 30, 33));
  12805. testTOD(TimeOfDay(12, 30, 33), -1, TimeOfDay(12, 30, 32));
  12806. testTOD(TimeOfDay(12, 30, 33), -2, TimeOfDay(12, 30, 31));
  12807. testTOD(TimeOfDay(12, 30, 33), -3, TimeOfDay(12, 30, 30));
  12808. testTOD(TimeOfDay(12, 30, 33), -4, TimeOfDay(12, 30, 29));
  12809. testTOD(TimeOfDay(12, 30, 33), -5, TimeOfDay(12, 30, 28));
  12810. testTOD(TimeOfDay(12, 30, 33), -10, TimeOfDay(12, 30, 23));
  12811. testTOD(TimeOfDay(12, 30, 33), -15, TimeOfDay(12, 30, 18));
  12812. testTOD(TimeOfDay(12, 30, 33), -33, TimeOfDay(12, 30, 0));
  12813. testTOD(TimeOfDay(12, 30, 33), -34, TimeOfDay(12, 29, 59));
  12814. testTOD(TimeOfDay(12, 30, 33), -35, TimeOfDay(12, 29, 58));
  12815. testTOD(TimeOfDay(12, 30, 33), -59, TimeOfDay(12, 29, 34));
  12816. testTOD(TimeOfDay(12, 30, 33), -60, TimeOfDay(12, 29, 33));
  12817. testTOD(TimeOfDay(12, 30, 33), -61, TimeOfDay(12, 29, 32));
  12818. testTOD(TimeOfDay(12, 30, 33), -1833, TimeOfDay(12, 0, 0));
  12819. testTOD(TimeOfDay(12, 30, 33), -1834, TimeOfDay(11, 59, 59));
  12820. testTOD(TimeOfDay(12, 30, 33), -3600, TimeOfDay(11, 30, 33));
  12821. testTOD(TimeOfDay(12, 30, 33), -3601, TimeOfDay(11, 30, 32));
  12822. testTOD(TimeOfDay(12, 30, 33), -5134, TimeOfDay(11, 4, 59));
  12823. testTOD(TimeOfDay(12, 30, 33), -7200, TimeOfDay(10, 30, 33));
  12824. testTOD(TimeOfDay(12, 30, 0), 1, TimeOfDay(12, 30, 1));
  12825. testTOD(TimeOfDay(12, 30, 0), 0, TimeOfDay(12, 30, 0));
  12826. testTOD(TimeOfDay(12, 30, 0), -1, TimeOfDay(12, 29, 59));
  12827. testTOD(TimeOfDay(12, 0, 0), 1, TimeOfDay(12, 0, 1));
  12828. testTOD(TimeOfDay(12, 0, 0), 0, TimeOfDay(12, 0, 0));
  12829. testTOD(TimeOfDay(12, 0, 0), -1, TimeOfDay(11, 59, 59));
  12830. testTOD(TimeOfDay(0, 0, 0), 1, TimeOfDay(0, 0, 1));
  12831. testTOD(TimeOfDay(0, 0, 0), 0, TimeOfDay(0, 0, 0));
  12832. testTOD(TimeOfDay(0, 0, 0), -1, TimeOfDay(23, 59, 59));
  12833. testTOD(TimeOfDay(23, 59, 59), 1, TimeOfDay(0, 0, 0));
  12834. testTOD(TimeOfDay(23, 59, 59), 0, TimeOfDay(23, 59, 59));
  12835. testTOD(TimeOfDay(23, 59, 59), -1, TimeOfDay(23, 59, 58));
  12836. const ctod = TimeOfDay(0, 0, 0);
  12837. immutable itod = TimeOfDay(0, 0, 0);
  12838. static assert(!__traits(compiles, ctod.addSeconds(7)));
  12839. static assert(!__traits(compiles, itod.addSeconds(7)));
  12840. }
  12841. }
  12842. /+
  12843. Whether the given values form a valid $(D TimeOfDay).
  12844. +/
  12845. static bool _valid(int hour, int minute, int second) pure nothrow
  12846. {
  12847. return valid!"hours"(hour) && valid!"minutes"(minute) && valid!"seconds"(second);
  12848. }
  12849. pure invariant()
  12850. {
  12851. assert(_valid(_hour, _minute, _second),
  12852. "Invariant Failure: hour [" ~
  12853. numToString(_hour) ~
  12854. "] minute [" ~
  12855. numToString(_minute) ~
  12856. "] second [" ~
  12857. numToString(_second) ~
  12858. "]");
  12859. }
  12860. ubyte _hour;
  12861. ubyte _minute;
  12862. ubyte _second;
  12863. enum ubyte maxHour = 24 - 1;
  12864. enum ubyte maxMinute = 60 - 1;
  12865. enum ubyte maxSecond = 60 - 1;
  12866. }
  12867. /++
  12868. Combines the $(D Date) and $(D TimeOfDay) structs to give you an object
  12869. which holds both the date and the time. It is optimized for calendar-based
  12870. operations and has no concept of time zone. If you want an object which is
  12871. optimized for time operations based on the system time, then use
  12872. $(D SysTime). $(D SysTime) has a concept of time zone and has much higher
  12873. precision (hnsecs). $(D DateTime) is intended primarily for calendar-based
  12874. uses rather than precise time operations.
  12875. +/
  12876. struct DateTime
  12877. {
  12878. public:
  12879. /++
  12880. Params:
  12881. date = The date portion of $(D DateTime).
  12882. tod = The time portion of $(D DateTime).
  12883. +/
  12884. this(in Date date, in TimeOfDay tod = TimeOfDay.init) pure nothrow
  12885. {
  12886. _date = date;
  12887. _tod = tod;
  12888. }
  12889. unittest
  12890. {
  12891. version(testStdDateTime)
  12892. {
  12893. {
  12894. auto dt = DateTime.init;
  12895. _assertPred!"=="(dt._date, Date.init);
  12896. _assertPred!"=="(dt._tod, TimeOfDay.init);
  12897. }
  12898. {
  12899. auto dt = DateTime(Date(1999, 7 ,6));
  12900. _assertPred!"=="(dt._date, Date(1999, 7, 6));
  12901. _assertPred!"=="(dt._tod, TimeOfDay.init);
  12902. }
  12903. {
  12904. auto dt = DateTime(Date(1999, 7 ,6), TimeOfDay(12, 30, 33));
  12905. _assertPred!"=="(dt._date, Date(1999, 7, 6));
  12906. _assertPred!"=="(dt._tod, TimeOfDay(12, 30, 33));
  12907. }
  12908. }
  12909. }
  12910. /++
  12911. Params:
  12912. year = The year portion of the date.
  12913. month = The month portion of the date.
  12914. day = The day portion of the date.
  12915. hour = The hour portion of the time;
  12916. minute = The minute portion of the time;
  12917. second = The second portion of the time;
  12918. +/
  12919. this(int year, int month, int day,
  12920. int hour = 0, int minute = 0, int second = 0) pure
  12921. {
  12922. _date = Date(year, month, day);
  12923. _tod = TimeOfDay(hour, minute, second);
  12924. }
  12925. unittest
  12926. {
  12927. version(testStdDateTime)
  12928. {
  12929. {
  12930. auto dt = DateTime(1999, 7 ,6);
  12931. _assertPred!"=="(dt._date, Date(1999, 7, 6));
  12932. _assertPred!"=="(dt._tod, TimeOfDay.init);
  12933. }
  12934. {
  12935. auto dt = DateTime(1999, 7 ,6, 12, 30, 33);
  12936. _assertPred!"=="(dt._date, Date(1999, 7, 6));
  12937. _assertPred!"=="(dt._tod, TimeOfDay(12, 30, 33));
  12938. }
  12939. }
  12940. }
  12941. /++
  12942. Compares this $(D DateTime) with the given $(D DateTime.).
  12943. Returns:
  12944. $(BOOKTABLE,
  12945. $(TR $(TD this &lt; rhs) $(TD &lt; 0))
  12946. $(TR $(TD this == rhs) $(TD 0))
  12947. $(TR $(TD this &gt; rhs) $(TD &gt; 0))
  12948. )
  12949. +/
  12950. int opCmp(in DateTime rhs) const pure nothrow
  12951. {
  12952. immutable dateResult = _date.opCmp(rhs._date);
  12953. if(dateResult != 0)
  12954. return dateResult;
  12955. return _tod.opCmp(rhs._tod);
  12956. }
  12957. unittest
  12958. {
  12959. version(testStdDateTime)
  12960. {
  12961. //Test A.D.
  12962. _assertPred!("opCmp", "==")(DateTime(Date.init, TimeOfDay.init), DateTime.init);
  12963. _assertPred!("opCmp", "==")(DateTime(Date(1999, 1, 1)), DateTime(Date(1999, 1, 1)));
  12964. _assertPred!("opCmp", "==")(DateTime(Date(1, 7, 1)), DateTime(Date(1, 7, 1)));
  12965. _assertPred!("opCmp", "==")(DateTime(Date(1, 1, 6)), DateTime(Date(1, 1, 6)));
  12966. _assertPred!("opCmp", "==")(DateTime(Date(1999, 7, 1)), DateTime(Date(1999, 7, 1)));
  12967. _assertPred!("opCmp", "==")(DateTime(Date(1999, 7, 6)), DateTime(Date(1999, 7, 6)));
  12968. _assertPred!("opCmp", "==")(DateTime(Date(1, 7, 6)), DateTime(Date(1, 7, 6)));
  12969. _assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6)), DateTime(Date(2000, 7, 6)));
  12970. _assertPred!("opCmp", ">")(DateTime(Date(2000, 7, 6)), DateTime(Date(1999, 7, 6)));
  12971. _assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6)), DateTime(Date(1999, 8, 6)));
  12972. _assertPred!("opCmp", ">")(DateTime(Date(1999, 8, 6)), DateTime(Date(1999, 7, 6)));
  12973. _assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6)), DateTime(Date(1999, 7, 7)));
  12974. _assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 7)), DateTime(Date(1999, 7, 6)));
  12975. _assertPred!("opCmp", "<")(DateTime(Date(1999, 8, 7)), DateTime(Date(2000, 7, 6)));
  12976. _assertPred!("opCmp", ">")(DateTime(Date(2000, 8, 6)), DateTime(Date(1999, 7, 7)));
  12977. _assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 7)), DateTime(Date(2000, 7, 6)));
  12978. _assertPred!("opCmp", ">")(DateTime(Date(2000, 7, 6)), DateTime(Date(1999, 7, 7)));
  12979. _assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 7)), DateTime(Date(1999, 8, 6)));
  12980. _assertPred!("opCmp", ">")(DateTime(Date(1999, 8, 6)), DateTime(Date(1999, 7, 7)));
  12981. _assertPred!("opCmp", "==")(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)),
  12982. DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)));
  12983. _assertPred!("opCmp", "==")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 0)),
  12984. DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 0)));
  12985. _assertPred!("opCmp", "==")(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 0)),
  12986. DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 0)));
  12987. _assertPred!("opCmp", "==")(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33)),
  12988. DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33)));
  12989. _assertPred!("opCmp", "==")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0)),
  12990. DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0)));
  12991. _assertPred!("opCmp", "==")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
  12992. DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  12993. _assertPred!("opCmp", "==")(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33)),
  12994. DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33)));
  12995. _assertPred!("opCmp", "==")(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33)),
  12996. DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33)));
  12997. _assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
  12998. DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)));
  12999. _assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)),
  13000. DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  13001. _assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
  13002. DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)));
  13003. _assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)),
  13004. DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  13005. _assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
  13006. DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)));
  13007. _assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)),
  13008. DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  13009. _assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)),
  13010. DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)));
  13011. _assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)),
  13012. DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)));
  13013. _assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)),
  13014. DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)));
  13015. _assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)),
  13016. DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)));
  13017. _assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)),
  13018. DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)));
  13019. _assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)),
  13020. DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)));
  13021. _assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)),
  13022. DateTime(Date(2000, 7, 6), TimeOfDay(12, 30, 33)));
  13023. _assertPred!("opCmp", ">")(DateTime(Date(2000, 7, 6), TimeOfDay(12, 30, 33)),
  13024. DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)));
  13025. _assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)),
  13026. DateTime(Date(2000, 7, 6), TimeOfDay(12, 30, 33)));
  13027. _assertPred!("opCmp", ">")(DateTime(Date(2000, 7, 6), TimeOfDay(12, 30, 33)),
  13028. DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)));
  13029. _assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)),
  13030. DateTime(Date(2000, 7, 6), TimeOfDay(12, 30, 33)));
  13031. _assertPred!("opCmp", ">")(DateTime(Date(2000, 7, 6), TimeOfDay(12, 30, 33)),
  13032. DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)));
  13033. _assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)),
  13034. DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33)));
  13035. _assertPred!("opCmp", ">")(DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33)),
  13036. DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)));
  13037. _assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)),
  13038. DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33)));
  13039. _assertPred!("opCmp", ">")(DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33)),
  13040. DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)));
  13041. _assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)),
  13042. DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33)));
  13043. _assertPred!("opCmp", ">")(DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33)),
  13044. DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)));
  13045. _assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)),
  13046. DateTime(Date(1999, 7, 7), TimeOfDay(12, 30, 33)));
  13047. _assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 7), TimeOfDay(12, 30, 33)),
  13048. DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)));
  13049. _assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)),
  13050. DateTime(Date(1999, 7, 7), TimeOfDay(12, 31, 33)));
  13051. _assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 7), TimeOfDay(12, 30, 33)),
  13052. DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  13053. _assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)),
  13054. DateTime(Date(1999, 7, 7), TimeOfDay(12, 30, 33)));
  13055. _assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 7), TimeOfDay(12, 30, 33)),
  13056. DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)));
  13057. //Test B.C.
  13058. _assertPred!("opCmp", "==")(DateTime(Date(-1, 1, 1), TimeOfDay(12, 30, 33)),
  13059. DateTime(Date(-1, 1, 1), TimeOfDay(12, 30, 33)));
  13060. _assertPred!("opCmp", "==")(DateTime(Date(-1, 7, 1), TimeOfDay(12, 30, 33)),
  13061. DateTime(Date(-1, 7, 1), TimeOfDay(12, 30, 33)));
  13062. _assertPred!("opCmp", "==")(DateTime(Date(-1, 1, 6), TimeOfDay(12, 30, 33)),
  13063. DateTime(Date(-1, 1, 6), TimeOfDay(12, 30, 33)));
  13064. _assertPred!("opCmp", "==")(DateTime(Date(-1999, 7, 1), TimeOfDay(12, 30, 33)),
  13065. DateTime(Date(-1999, 7, 1), TimeOfDay(12, 30, 33)));
  13066. _assertPred!("opCmp", "==")(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)),
  13067. DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  13068. _assertPred!("opCmp", "==")(DateTime(Date(-1, 7, 6), TimeOfDay(12, 30, 33)),
  13069. DateTime(Date(-1, 7, 6), TimeOfDay(12, 30, 33)));
  13070. _assertPred!("opCmp", "<")(DateTime(Date(-2000, 7, 6), TimeOfDay(12, 30, 33)),
  13071. DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  13072. _assertPred!("opCmp", ">")(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)),
  13073. DateTime(Date(-2000, 7, 6), TimeOfDay(12, 30, 33)));
  13074. _assertPred!("opCmp", "<")(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)),
  13075. DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33)));
  13076. _assertPred!("opCmp", ">")(DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33)),
  13077. DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  13078. _assertPred!("opCmp", "<")(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)),
  13079. DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33)));
  13080. _assertPred!("opCmp", ">")(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33)),
  13081. DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  13082. _assertPred!("opCmp", "<")(DateTime(Date(-2000, 8, 6), TimeOfDay(12, 30, 33)),
  13083. DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33)));
  13084. _assertPred!("opCmp", ">")(DateTime(Date(-1999, 8, 7), TimeOfDay(12, 30, 33)),
  13085. DateTime(Date(-2000, 7, 6), TimeOfDay(12, 30, 33)));
  13086. _assertPred!("opCmp", "<")(DateTime(Date(-2000, 7, 6), TimeOfDay(12, 30, 33)),
  13087. DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33)));
  13088. _assertPred!("opCmp", ">")(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33)),
  13089. DateTime(Date(-2000, 7, 6), TimeOfDay(12, 30, 33)));
  13090. _assertPred!("opCmp", "<")(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33)),
  13091. DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33)));
  13092. _assertPred!("opCmp", ">")(DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33)),
  13093. DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33)));
  13094. //Test Both
  13095. _assertPred!("opCmp", "<")(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)),
  13096. DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  13097. _assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
  13098. DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  13099. _assertPred!("opCmp", "<")(DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33)),
  13100. DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  13101. _assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
  13102. DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33)));
  13103. _assertPred!("opCmp", "<")(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33)),
  13104. DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  13105. _assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
  13106. DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33)));
  13107. _assertPred!("opCmp", "<")(DateTime(Date(-1999, 8, 7), TimeOfDay(12, 30, 33)),
  13108. DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  13109. _assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
  13110. DateTime(Date(-1999, 8, 7), TimeOfDay(12, 30, 33)));
  13111. _assertPred!("opCmp", "<")(DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33)),
  13112. DateTime(Date(1999, 6, 6), TimeOfDay(12, 30, 33)));
  13113. _assertPred!("opCmp", ">")(DateTime(Date(1999, 6, 8), TimeOfDay(12, 30, 33)),
  13114. DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  13115. auto dt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 33, 30));
  13116. const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 33, 30));
  13117. immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 33, 30));
  13118. static assert(__traits(compiles, dt.opCmp(dt)));
  13119. static assert(__traits(compiles, dt.opCmp(cdt)));
  13120. static assert(__traits(compiles, dt.opCmp(idt)));
  13121. static assert(__traits(compiles, cdt.opCmp(dt)));
  13122. static assert(__traits(compiles, cdt.opCmp(cdt)));
  13123. static assert(__traits(compiles, cdt.opCmp(idt)));
  13124. static assert(__traits(compiles, idt.opCmp(dt)));
  13125. static assert(__traits(compiles, idt.opCmp(cdt)));
  13126. static assert(__traits(compiles, idt.opCmp(idt)));
  13127. }
  13128. }
  13129. /++
  13130. The date portion of $(D DateTime).
  13131. +/
  13132. @property Date date() const pure nothrow
  13133. {
  13134. return _date;
  13135. }
  13136. unittest
  13137. {
  13138. version(testStdDateTime)
  13139. {
  13140. {
  13141. auto dt = DateTime.init;
  13142. _assertPred!"=="(dt.date, Date.init);
  13143. }
  13144. {
  13145. auto dt = DateTime(Date(1999, 7, 6));
  13146. _assertPred!"=="(dt.date, Date(1999, 7, 6));
  13147. }
  13148. const cdt = DateTime(1999, 7, 6);
  13149. immutable idt = DateTime(1999, 7, 6);
  13150. static assert(__traits(compiles, cdt.date == Date(2010, 1, 1)));
  13151. static assert(__traits(compiles, idt.date == Date(2010, 1, 1)));
  13152. }
  13153. }
  13154. /++
  13155. The date portion of $(D DateTime).
  13156. Params:
  13157. date = The Date to set this $(D DateTime)'s date portion to.
  13158. +/
  13159. @property void date(in Date date) pure nothrow
  13160. {
  13161. _date = date;
  13162. }
  13163. unittest
  13164. {
  13165. version(testStdDateTime)
  13166. {
  13167. auto dt = DateTime.init;
  13168. dt.date = Date(1999, 7, 6);
  13169. _assertPred!"=="(dt._date, Date(1999, 7, 6));
  13170. _assertPred!"=="(dt._tod, TimeOfDay.init);
  13171. const cdt = DateTime(1999, 7, 6);
  13172. immutable idt = DateTime(1999, 7, 6);
  13173. static assert(!__traits(compiles, cdt.date = Date(2010, 1, 1)));
  13174. static assert(!__traits(compiles, idt.date = Date(2010, 1, 1)));
  13175. }
  13176. }
  13177. /++
  13178. The time portion of $(D DateTime).
  13179. +/
  13180. @property TimeOfDay timeOfDay() const pure nothrow
  13181. {
  13182. return _tod;
  13183. }
  13184. unittest
  13185. {
  13186. version(testStdDateTime)
  13187. {
  13188. {
  13189. auto dt = DateTime.init;
  13190. _assertPred!"=="(dt.timeOfDay, TimeOfDay.init);
  13191. }
  13192. {
  13193. auto dt = DateTime(Date.init, TimeOfDay(12, 30, 33));
  13194. _assertPred!"=="(dt.timeOfDay, TimeOfDay(12, 30, 33));
  13195. }
  13196. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  13197. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  13198. static assert(__traits(compiles, cdt.timeOfDay == TimeOfDay(12, 30, 33)));
  13199. static assert(__traits(compiles, idt.timeOfDay == TimeOfDay(12, 30, 33)));
  13200. }
  13201. }
  13202. /++
  13203. The time portion of $(D DateTime).
  13204. Params:
  13205. tod = The $(D TimeOfDay) to set this $(D DateTime)'s time portion
  13206. to.
  13207. +/
  13208. @property void timeOfDay(in TimeOfDay tod) pure nothrow
  13209. {
  13210. _tod = tod;
  13211. }
  13212. unittest
  13213. {
  13214. version(testStdDateTime)
  13215. {
  13216. auto dt = DateTime.init;
  13217. dt.timeOfDay = TimeOfDay(12, 30, 33);
  13218. _assertPred!"=="(dt._date, date.init);
  13219. _assertPred!"=="(dt._tod, TimeOfDay(12, 30, 33));
  13220. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  13221. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  13222. static assert(!__traits(compiles, cdt.timeOfDay = TimeOfDay(12, 30, 33)));
  13223. static assert(!__traits(compiles, idt.timeOfDay = TimeOfDay(12, 30, 33)));
  13224. }
  13225. }
  13226. /++
  13227. Year of the Gregorian Calendar. Positive numbers are A.D. Non-positive
  13228. are B.C.
  13229. +/
  13230. @property short year() const pure nothrow
  13231. {
  13232. return _date.year;
  13233. }
  13234. unittest
  13235. {
  13236. version(testStdDateTime)
  13237. {
  13238. _assertPred!"=="(Date.init.year, 1);
  13239. _assertPred!"=="(Date(1999, 7, 6).year, 1999);
  13240. _assertPred!"=="(Date(-1999, 7, 6).year, -1999);
  13241. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  13242. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  13243. static assert(__traits(compiles, idt.year));
  13244. static assert(__traits(compiles, idt.year));
  13245. }
  13246. }
  13247. /++
  13248. Year of the Gregorian Calendar. Positive numbers are A.D. Non-positive
  13249. are B.C.
  13250. Params:
  13251. year = The year to set this $(D DateTime)'s year to.
  13252. Throws:
  13253. $(D DateTimeException) if the new year is not a leap year and if the
  13254. resulting date would be on February 29th.
  13255. Examples:
  13256. --------------------
  13257. assert(DateTime(Date(1999, 7, 6), TimeOfDay(9, 7, 5)).year == 1999);
  13258. assert(DateTime(Date(2010, 10, 4), TimeOfDay(0, 0, 30)).year == 2010);
  13259. assert(DateTime(Date(-7, 4, 5), TimeOfDay(7, 45, 2)).year == -7);
  13260. --------------------
  13261. +/
  13262. @property void year(int year) pure
  13263. {
  13264. _date.year = year;
  13265. }
  13266. unittest
  13267. {
  13268. version(testStdDateTime)
  13269. {
  13270. static void testDT(DateTime dt, int year, in DateTime expected, size_t line = __LINE__)
  13271. {
  13272. dt.year = year;
  13273. _assertPred!"=="(dt, expected, "", __FILE__, line);
  13274. }
  13275. testDT(DateTime(Date(1, 1, 1), TimeOfDay(12, 30, 33)), 1999, DateTime(Date(1999, 1, 1), TimeOfDay(12, 30, 33)));
  13276. testDT(DateTime(Date(1, 1, 1), TimeOfDay(12, 30, 33)), 0, DateTime(Date(0, 1, 1), TimeOfDay(12, 30, 33)));
  13277. testDT(DateTime(Date(1, 1, 1), TimeOfDay(12, 30, 33)), -1999, DateTime(Date(-1999, 1, 1), TimeOfDay(12, 30, 33)));
  13278. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  13279. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  13280. static assert(!__traits(compiles, cdt.year = 7));
  13281. static assert(!__traits(compiles, idt.year = 7));
  13282. //Verify Examples.
  13283. assert(DateTime(Date(1999, 7, 6), TimeOfDay(9, 7, 5)).year == 1999);
  13284. assert(DateTime(Date(2010, 10, 4), TimeOfDay(0, 0, 30)).year == 2010);
  13285. assert(DateTime(Date(-7, 4, 5), TimeOfDay(7, 45, 2)).year == -7);
  13286. }
  13287. }
  13288. /++
  13289. Year B.C. of the Gregorian Calendar counting year 0 as 1 B.C.
  13290. Throws:
  13291. $(D DateTimeException) if $(D isAD) is true.
  13292. Examples:
  13293. --------------------
  13294. assert(DateTime(Date(0, 1, 1), TimeOfDay(12, 30, 33)).yearBC == 1);
  13295. assert(DateTime(Date(-1, 1, 1), TimeOfDay(10, 7, 2)).yearBC == 2);
  13296. assert(DateTime(Date(-100, 1, 1), TimeOfDay(4, 59, 0)).yearBC == 101);
  13297. --------------------
  13298. +/
  13299. @property short yearBC() const pure
  13300. {
  13301. return _date.yearBC;
  13302. }
  13303. unittest
  13304. {
  13305. version(testStdDateTime)
  13306. {
  13307. assertThrown!DateTimeException((in DateTime dt){dt.yearBC;}(DateTime(Date(1, 1, 1))));
  13308. auto dt = DateTime(1999, 7, 6, 12, 30, 33);
  13309. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  13310. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  13311. static assert(__traits(compiles, dt.yearBC = 12));
  13312. static assert(!__traits(compiles, cdt.yearBC = 12));
  13313. static assert(!__traits(compiles, idt.yearBC = 12));
  13314. //Verify Examples.
  13315. assert(DateTime(Date(0, 1, 1), TimeOfDay(12, 30, 33)).yearBC == 1);
  13316. assert(DateTime(Date(-1, 1, 1), TimeOfDay(10, 7, 2)).yearBC == 2);
  13317. assert(DateTime(Date(-100, 1, 1), TimeOfDay(4, 59, 0)).yearBC == 101);
  13318. }
  13319. }
  13320. /++
  13321. Year B.C. of the Gregorian Calendar counting year 0 as 1 B.C.
  13322. Params:
  13323. year = The year B.C. to set this $(D DateTime)'s year to.
  13324. Throws:
  13325. $(D DateTimeException) if a non-positive value is given.
  13326. Examples:
  13327. --------------------
  13328. auto dt = DateTime(Date(2010, 1, 1), TimeOfDay(7, 30, 0));
  13329. dt.yearBC = 1;
  13330. assert(dt == DateTime(Date(0, 1, 1), TimeOfDay(7, 30, 0)));
  13331. dt.yearBC = 10;
  13332. assert(dt == DateTime(Date(-9, 1, 1), TimeOfDay(7, 30, 0)));
  13333. --------------------
  13334. +/
  13335. @property void yearBC(int year) pure
  13336. {
  13337. _date.yearBC = year;
  13338. }
  13339. unittest
  13340. {
  13341. version(testStdDateTime)
  13342. {
  13343. assertThrown!DateTimeException((DateTime dt){dt.yearBC = -1;}(DateTime(Date(1, 1, 1))));
  13344. {
  13345. auto dt = DateTime(1999, 7, 6, 12, 30, 33);
  13346. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  13347. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  13348. static assert(__traits(compiles, dt.yearBC = 12));
  13349. static assert(!__traits(compiles, cdt.yearBC = 12));
  13350. static assert(!__traits(compiles, idt.yearBC = 12));
  13351. }
  13352. //Verify Examples.
  13353. {
  13354. auto dt = DateTime(Date(2010, 1, 1), TimeOfDay(7, 30, 0));
  13355. dt.yearBC = 1;
  13356. assert(dt == DateTime(Date(0, 1, 1), TimeOfDay(7, 30, 0)));
  13357. dt.yearBC = 10;
  13358. assert(dt == DateTime(Date(-9, 1, 1), TimeOfDay(7, 30, 0)));
  13359. }
  13360. }
  13361. }
  13362. /++
  13363. Month of a Gregorian Year.
  13364. Examples:
  13365. --------------------
  13366. assert(DateTime(Date(1999, 7, 6), TimeOfDay(9, 7, 5)).month == 7);
  13367. assert(DateTime(Date(2010, 10, 4), TimeOfDay(0, 0, 30)).month == 10);
  13368. assert(DateTime(Date(-7, 4, 5), TimeOfDay(7, 45, 2)).month == 4);
  13369. --------------------
  13370. +/
  13371. @property Month month() const pure nothrow
  13372. {
  13373. return _date.month;
  13374. }
  13375. unittest
  13376. {
  13377. version(testStdDateTime)
  13378. {
  13379. _assertPred!"=="(DateTime.init.month, 1);
  13380. _assertPred!"=="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)).month, 7);
  13381. _assertPred!"=="(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)).month, 7);
  13382. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  13383. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  13384. static assert(__traits(compiles, cdt.month));
  13385. static assert(__traits(compiles, idt.month));
  13386. //Verify Examples.
  13387. assert(DateTime(Date(1999, 7, 6), TimeOfDay(9, 7, 5)).month == 7);
  13388. assert(DateTime(Date(2010, 10, 4), TimeOfDay(0, 0, 30)).month == 10);
  13389. assert(DateTime(Date(-7, 4, 5), TimeOfDay(7, 45, 2)).month == 4);
  13390. }
  13391. }
  13392. /++
  13393. Month of a Gregorian Year.
  13394. Params:
  13395. month = The month to set this $(D DateTime)'s month to.
  13396. Throws:
  13397. $(D DateTimeException) if the given month is not a valid month.
  13398. +/
  13399. @property void month(Month month) pure
  13400. {
  13401. _date.month = month;
  13402. }
  13403. unittest
  13404. {
  13405. version(testStdDateTime)
  13406. {
  13407. static void testDT(DateTime dt, Month month, in DateTime expected = DateTime.init, size_t line = __LINE__)
  13408. {
  13409. dt.month = month;
  13410. assert(expected != DateTime.init);
  13411. _assertPred!"=="(dt, expected, "", __FILE__, line);
  13412. }
  13413. assertThrown!DateTimeException(testDT(DateTime(Date(1, 1, 1), TimeOfDay(12, 30, 33)), cast(Month)0));
  13414. assertThrown!DateTimeException(testDT(DateTime(Date(1, 1, 1), TimeOfDay(12, 30, 33)), cast(Month)13));
  13415. testDT(DateTime(Date(1, 1, 1), TimeOfDay(12, 30, 33)), cast(Month)7, DateTime(Date(1, 7, 1), TimeOfDay(12, 30, 33)));
  13416. testDT(DateTime(Date(-1, 1, 1), TimeOfDay(12, 30, 33)), cast(Month)7, DateTime(Date(-1, 7, 1), TimeOfDay(12, 30, 33)));
  13417. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  13418. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  13419. static assert(!__traits(compiles, cdt.month = 12));
  13420. static assert(!__traits(compiles, idt.month = 12));
  13421. }
  13422. }
  13423. /++
  13424. Day of a Gregorian Month.
  13425. Examples:
  13426. --------------------
  13427. assert(DateTime(Date(1999, 7, 6), TimeOfDay(9, 7, 5)).day == 6);
  13428. assert(DateTime(Date(2010, 10, 4), TimeOfDay(0, 0, 30)).day == 4);
  13429. assert(DateTime(Date(-7, 4, 5), TimeOfDay(7, 45, 2)).day == 5);
  13430. --------------------
  13431. +/
  13432. @property ubyte day() const pure nothrow
  13433. {
  13434. return _date.day;
  13435. }
  13436. //Verify Examples.
  13437. version(testStdDateTime) unittest
  13438. {
  13439. assert(DateTime(Date(1999, 7, 6), TimeOfDay(9, 7, 5)).day == 6);
  13440. assert(DateTime(Date(2010, 10, 4), TimeOfDay(0, 0, 30)).day == 4);
  13441. assert(DateTime(Date(-7, 4, 5), TimeOfDay(7, 45, 2)).day == 5);
  13442. }
  13443. version(testStdDateTime) unittest
  13444. {
  13445. static void test(DateTime dateTime, int expected, size_t line = __LINE__)
  13446. {
  13447. _assertPred!"=="(dateTime.day, expected,
  13448. format("Value given: %s", dateTime), __FILE__, line);
  13449. }
  13450. foreach(year; chain(testYearsBC, testYearsAD))
  13451. {
  13452. foreach(md; testMonthDays)
  13453. {
  13454. foreach(tod; testTODs)
  13455. test(DateTime(Date(year, md.month, md.day), tod), md.day);
  13456. }
  13457. }
  13458. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  13459. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  13460. static assert(__traits(compiles, cdt.day));
  13461. static assert(__traits(compiles, idt.day));
  13462. }
  13463. /++
  13464. Day of a Gregorian Month.
  13465. Params:
  13466. day = The day of the month to set this $(D DateTime)'s day to.
  13467. Throws:
  13468. $(D DateTimeException) if the given day is not a valid day of the
  13469. current month.
  13470. +/
  13471. @property void day(int day) pure
  13472. {
  13473. _date.day = day;
  13474. }
  13475. unittest
  13476. {
  13477. version(testStdDateTime)
  13478. {
  13479. static void testDT(DateTime dt, int day)
  13480. {
  13481. dt.day = day;
  13482. }
  13483. //Test A.D.
  13484. assertThrown!DateTimeException(testDT(DateTime(Date(1, 1, 1)), 0));
  13485. assertThrown!DateTimeException(testDT(DateTime(Date(1, 1, 1)), 32));
  13486. assertThrown!DateTimeException(testDT(DateTime(Date(1, 2, 1)), 29));
  13487. assertThrown!DateTimeException(testDT(DateTime(Date(4, 2, 1)), 30));
  13488. assertThrown!DateTimeException(testDT(DateTime(Date(1, 3, 1)), 32));
  13489. assertThrown!DateTimeException(testDT(DateTime(Date(1, 4, 1)), 31));
  13490. assertThrown!DateTimeException(testDT(DateTime(Date(1, 5, 1)), 32));
  13491. assertThrown!DateTimeException(testDT(DateTime(Date(1, 6, 1)), 31));
  13492. assertThrown!DateTimeException(testDT(DateTime(Date(1, 7, 1)), 32));
  13493. assertThrown!DateTimeException(testDT(DateTime(Date(1, 8, 1)), 32));
  13494. assertThrown!DateTimeException(testDT(DateTime(Date(1, 9, 1)), 31));
  13495. assertThrown!DateTimeException(testDT(DateTime(Date(1, 10, 1)), 32));
  13496. assertThrown!DateTimeException(testDT(DateTime(Date(1, 11, 1)), 31));
  13497. assertThrown!DateTimeException(testDT(DateTime(Date(1, 12, 1)), 32));
  13498. assertNotThrown!DateTimeException(testDT(DateTime(Date(1, 1, 1)), 31));
  13499. assertNotThrown!DateTimeException(testDT(DateTime(Date(1, 2, 1)), 28));
  13500. assertNotThrown!DateTimeException(testDT(DateTime(Date(4, 2, 1)), 29));
  13501. assertNotThrown!DateTimeException(testDT(DateTime(Date(1, 3, 1)), 31));
  13502. assertNotThrown!DateTimeException(testDT(DateTime(Date(1, 4, 1)), 30));
  13503. assertNotThrown!DateTimeException(testDT(DateTime(Date(1, 5, 1)), 31));
  13504. assertNotThrown!DateTimeException(testDT(DateTime(Date(1, 6, 1)), 30));
  13505. assertNotThrown!DateTimeException(testDT(DateTime(Date(1, 7, 1)), 31));
  13506. assertNotThrown!DateTimeException(testDT(DateTime(Date(1, 8, 1)), 31));
  13507. assertNotThrown!DateTimeException(testDT(DateTime(Date(1, 9, 1)), 30));
  13508. assertNotThrown!DateTimeException(testDT(DateTime(Date(1, 10, 1)), 31));
  13509. assertNotThrown!DateTimeException(testDT(DateTime(Date(1, 11, 1)), 30));
  13510. assertNotThrown!DateTimeException(testDT(DateTime(Date(1, 12, 1)), 31));
  13511. {
  13512. auto dt = DateTime(Date(1, 1, 1), TimeOfDay(7, 12, 22));
  13513. dt.day = 6;
  13514. _assertPred!"=="(dt, DateTime(Date(1, 1, 6), TimeOfDay(7, 12, 22)));
  13515. }
  13516. //Test B.C.
  13517. assertThrown!DateTimeException(testDT(DateTime(Date(-1, 1, 1)), 0));
  13518. assertThrown!DateTimeException(testDT(DateTime(Date(-1, 1, 1)), 32));
  13519. assertThrown!DateTimeException(testDT(DateTime(Date(-1, 2, 1)), 29));
  13520. assertThrown!DateTimeException(testDT(DateTime(Date(0, 2, 1)), 30));
  13521. assertThrown!DateTimeException(testDT(DateTime(Date(-1, 3, 1)), 32));
  13522. assertThrown!DateTimeException(testDT(DateTime(Date(-1, 4, 1)), 31));
  13523. assertThrown!DateTimeException(testDT(DateTime(Date(-1, 5, 1)), 32));
  13524. assertThrown!DateTimeException(testDT(DateTime(Date(-1, 6, 1)), 31));
  13525. assertThrown!DateTimeException(testDT(DateTime(Date(-1, 7, 1)), 32));
  13526. assertThrown!DateTimeException(testDT(DateTime(Date(-1, 8, 1)), 32));
  13527. assertThrown!DateTimeException(testDT(DateTime(Date(-1, 9, 1)), 31));
  13528. assertThrown!DateTimeException(testDT(DateTime(Date(-1, 10, 1)), 32));
  13529. assertThrown!DateTimeException(testDT(DateTime(Date(-1, 11, 1)), 31));
  13530. assertThrown!DateTimeException(testDT(DateTime(Date(-1, 12, 1)), 32));
  13531. assertNotThrown!DateTimeException(testDT(DateTime(Date(-1, 1, 1)), 31));
  13532. assertNotThrown!DateTimeException(testDT(DateTime(Date(-1, 2, 1)), 28));
  13533. assertNotThrown!DateTimeException(testDT(DateTime(Date(0, 2, 1)), 29));
  13534. assertNotThrown!DateTimeException(testDT(DateTime(Date(-1, 3, 1)), 31));
  13535. assertNotThrown!DateTimeException(testDT(DateTime(Date(-1, 4, 1)), 30));
  13536. assertNotThrown!DateTimeException(testDT(DateTime(Date(-1, 5, 1)), 31));
  13537. assertNotThrown!DateTimeException(testDT(DateTime(Date(-1, 6, 1)), 30));
  13538. assertNotThrown!DateTimeException(testDT(DateTime(Date(-1, 7, 1)), 31));
  13539. assertNotThrown!DateTimeException(testDT(DateTime(Date(-1, 8, 1)), 31));
  13540. assertNotThrown!DateTimeException(testDT(DateTime(Date(-1, 9, 1)), 30));
  13541. assertNotThrown!DateTimeException(testDT(DateTime(Date(-1, 10, 1)), 31));
  13542. assertNotThrown!DateTimeException(testDT(DateTime(Date(-1, 11, 1)), 30));
  13543. assertNotThrown!DateTimeException(testDT(DateTime(Date(-1, 12, 1)), 31));
  13544. auto dt = DateTime(Date(-1, 1, 1), TimeOfDay(7, 12, 22));
  13545. dt.day = 6;
  13546. _assertPred!"=="(dt, DateTime(Date(-1, 1, 6), TimeOfDay(7, 12, 22)));
  13547. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  13548. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  13549. static assert(!__traits(compiles, cdt.day = 27));
  13550. static assert(!__traits(compiles, idt.day = 27));
  13551. }
  13552. }
  13553. /++
  13554. Hours passed midnight.
  13555. +/
  13556. @property ubyte hour() const pure nothrow
  13557. {
  13558. return _tod.hour;
  13559. }
  13560. unittest
  13561. {
  13562. version(testStdDateTime)
  13563. {
  13564. _assertPred!"=="(DateTime.init.hour, 0);
  13565. _assertPred!"=="(DateTime(Date.init, TimeOfDay(12, 0, 0)).hour, 12);
  13566. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  13567. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  13568. static assert(__traits(compiles, cdt.hour));
  13569. static assert(__traits(compiles, idt.hour));
  13570. }
  13571. }
  13572. /++
  13573. Hours passed midnight.
  13574. Params:
  13575. hour = The hour of the day to set this $(D DateTime)'s hour to.
  13576. Throws:
  13577. $(D DateTimeException) if the given hour would result in an invalid
  13578. $(D DateTime).
  13579. +/
  13580. @property void hour(int hour) pure
  13581. {
  13582. _tod.hour = hour;
  13583. }
  13584. unittest
  13585. {
  13586. version(testStdDateTime)
  13587. {
  13588. assertThrown!DateTimeException((){DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)).hour = 24;}());
  13589. auto dt = DateTime.init;
  13590. dt.hour = 12;
  13591. _assertPred!"=="(dt, DateTime(1, 1, 1, 12, 0, 0));
  13592. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  13593. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  13594. static assert(!__traits(compiles, cdt.hour = 27));
  13595. static assert(!__traits(compiles, idt.hour = 27));
  13596. }
  13597. }
  13598. /++
  13599. Minutes passed the hour.
  13600. +/
  13601. @property ubyte minute() const pure nothrow
  13602. {
  13603. return _tod.minute;
  13604. }
  13605. unittest
  13606. {
  13607. version(testStdDateTime)
  13608. {
  13609. _assertPred!"=="(DateTime.init.minute, 0);
  13610. _assertPred!"=="(DateTime(1, 1, 1, 0, 30, 0).minute, 30);
  13611. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  13612. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  13613. static assert(__traits(compiles, cdt.minute));
  13614. static assert(__traits(compiles, idt.minute));
  13615. }
  13616. }
  13617. /++
  13618. Minutes passed the hour.
  13619. Params:
  13620. minute = The minute to set this $(D DateTime)'s minute to.
  13621. Throws:
  13622. $(D DateTimeException) if the given minute would result in an
  13623. invalid $(D DateTime).
  13624. +/
  13625. @property void minute(int minute) pure
  13626. {
  13627. _tod.minute = minute;
  13628. }
  13629. unittest
  13630. {
  13631. version(testStdDateTime)
  13632. {
  13633. assertThrown!DateTimeException((){DateTime.init.minute = 60;}());
  13634. auto dt = DateTime.init;
  13635. dt.minute = 30;
  13636. _assertPred!"=="(dt, DateTime(1, 1, 1, 0, 30, 0));
  13637. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  13638. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  13639. static assert(!__traits(compiles, cdt.minute = 27));
  13640. static assert(!__traits(compiles, idt.minute = 27));
  13641. }
  13642. }
  13643. /++
  13644. Seconds passed the minute.
  13645. +/
  13646. @property ubyte second() const pure nothrow
  13647. {
  13648. return _tod.second;
  13649. }
  13650. unittest
  13651. {
  13652. version(testStdDateTime)
  13653. {
  13654. _assertPred!"=="(DateTime.init.second, 0);
  13655. _assertPred!"=="(DateTime(1, 1, 1, 0, 0, 33).second, 33);
  13656. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  13657. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  13658. static assert(__traits(compiles, cdt.second));
  13659. static assert(__traits(compiles, idt.second));
  13660. }
  13661. }
  13662. /++
  13663. Seconds passed the minute.
  13664. Params:
  13665. second = The second to set this $(D DateTime)'s second to.
  13666. Throws:
  13667. $(D DateTimeException) if the given seconds would result in an
  13668. invalid $(D DateTime).
  13669. +/
  13670. @property void second(int second) pure
  13671. {
  13672. _tod.second = second;
  13673. }
  13674. unittest
  13675. {
  13676. version(testStdDateTime)
  13677. {
  13678. assertThrown!DateTimeException((){DateTime.init.second = 60;}());
  13679. auto dt = DateTime.init;
  13680. dt.second = 33;
  13681. _assertPred!"=="(dt, DateTime(1, 1, 1, 0, 0, 33));
  13682. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  13683. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  13684. static assert(!__traits(compiles, cdt.second = 27));
  13685. static assert(!__traits(compiles, idt.second = 27));
  13686. }
  13687. }
  13688. /++
  13689. Adds the given number of years or months to this $(D DateTime). A
  13690. negative number will subtract.
  13691. Note that if day overflow is allowed, and the date with the adjusted
  13692. year/month overflows the number of days in the new month, then the month
  13693. will be incremented by one, and the day set to the number of days
  13694. overflowed. (e.g. if the day were 31 and the new month were June, then
  13695. the month would be incremented to July, and the new day would be 1). If
  13696. day overflow is not allowed, then the day will be set to the last valid
  13697. day in the month (e.g. June 31st would become June 30th).
  13698. Params:
  13699. units = The type of units to add ("years" or "months").
  13700. value = The number of months or years to add to this
  13701. $(D DateTime).
  13702. allowOverflow = Whether the days should be allowed to overflow,
  13703. causing the month to increment.
  13704. Examples:
  13705. --------------------
  13706. auto dt1 = DateTime(2010, 1, 1, 12, 30, 33);
  13707. dt1.add!"months"(11);
  13708. assert(dt1 == DateTime(2010, 12, 1, 12, 30, 33));
  13709. auto dt2 = DateTime(2010, 1, 1, 12, 30, 33);
  13710. dt2.add!"months"(-11);
  13711. assert(dt2 == DateTime(2009, 2, 1, 12, 30, 33));
  13712. auto dt3 = DateTime(2000, 2, 29, 12, 30, 33);
  13713. dt3.add!"years"(1);
  13714. assert(dt3 == DateTime(2001, 3, 1, 12, 30, 33));
  13715. auto dt4 = DateTime(2000, 2, 29, 12, 30, 33);
  13716. dt4.add!"years"(1, AllowDayOverflow.no);
  13717. assert(dt4 == DateTime(2001, 2, 28, 12, 30, 33));
  13718. --------------------
  13719. +/
  13720. /+ref DateTime+/ void add(string units)(long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) pure nothrow
  13721. if(units == "years" ||
  13722. units == "months")
  13723. {
  13724. _date.add!units(value, allowOverflow);
  13725. }
  13726. //Verify Examples.
  13727. unittest
  13728. {
  13729. version(testStdDateTime)
  13730. {
  13731. auto dt1 = DateTime(2010, 1, 1, 12, 30, 33);
  13732. dt1.add!"months"(11);
  13733. assert(dt1 == DateTime(2010, 12, 1, 12, 30, 33));
  13734. auto dt2 = DateTime(2010, 1, 1, 12, 30, 33);
  13735. dt2.add!"months"(-11);
  13736. assert(dt2 == DateTime(2009, 2, 1, 12, 30, 33));
  13737. auto dt3 = DateTime(2000, 2, 29, 12, 30, 33);
  13738. dt3.add!"years"(1);
  13739. assert(dt3 == DateTime(2001, 3, 1, 12, 30, 33));
  13740. auto dt4 = DateTime(2000, 2, 29, 12, 30, 33);
  13741. dt4.add!"years"(1, AllowDayOverflow.no);
  13742. assert(dt4 == DateTime(2001, 2, 28, 12, 30, 33));
  13743. }
  13744. }
  13745. unittest
  13746. {
  13747. version(testStdDateTime)
  13748. {
  13749. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  13750. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  13751. static assert(!__traits(compiles, cdt.add!"years"(4)));
  13752. static assert(!__traits(compiles, idt.add!"years"(4)));
  13753. static assert(!__traits(compiles, cdt.add!"months"(4)));
  13754. static assert(!__traits(compiles, idt.add!"months"(4)));
  13755. }
  13756. }
  13757. /++
  13758. Adds the given number of years or months to this $(D DateTime). A
  13759. negative number will subtract.
  13760. The difference between rolling and adding is that rolling does not
  13761. affect larger units. So, if you roll a $(D DateTime) 12 months, you
  13762. get the exact same $(D DateTime). However, the days can still be
  13763. affected due to the differing number of days in each month.
  13764. Because there are no units larger than years, there is no difference
  13765. between adding and rolling years.
  13766. Params:
  13767. units = The type of units to add ("years" or "months").
  13768. value = The number of months or years to add to this
  13769. $(D DateTime).
  13770. allowOverflow = Whether the days should be allowed to overflow,
  13771. causing the month to increment.
  13772. Examples:
  13773. --------------------
  13774. auto dt1 = DateTime(2010, 1, 1, 12, 33, 33);
  13775. dt1.roll!"months"(1);
  13776. assert(dt1 == DateTime(2010, 2, 1, 12, 33, 33));
  13777. auto dt2 = DateTime(2010, 1, 1, 12, 33, 33);
  13778. dt2.roll!"months"(-1);
  13779. assert(dt2 == DateTime(2010, 12, 1, 12, 33, 33));
  13780. auto dt3 = DateTime(1999, 1, 29, 12, 33, 33);
  13781. dt3.roll!"months"(1);
  13782. assert(dt3 == DateTime(1999, 3, 1, 12, 33, 33));
  13783. auto dt4 = DateTime(1999, 1, 29, 12, 33, 33);
  13784. dt4.roll!"months"(1, AllowDayOverflow.no);
  13785. assert(dt4 == DateTime(1999, 2, 28, 12, 33, 33));
  13786. auto dt5 = DateTime(2000, 2, 29, 12, 30, 33);
  13787. dt5.roll!"years"(1);
  13788. assert(dt5 == DateTime(2001, 3, 1, 12, 30, 33));
  13789. auto dt6 = DateTime(2000, 2, 29, 12, 30, 33);
  13790. dt6.roll!"years"(1, AllowDayOverflow.no);
  13791. assert(dt6 == DateTime(2001, 2, 28, 12, 30, 33));
  13792. --------------------
  13793. +/
  13794. /+ref DateTime+/ void roll(string units)(long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) pure nothrow
  13795. if(units == "years" ||
  13796. units == "months")
  13797. {
  13798. _date.roll!units(value, allowOverflow);
  13799. }
  13800. //Verify Examples.
  13801. unittest
  13802. {
  13803. version(testdStdDateTime)
  13804. {
  13805. auto dt1 = DateTime(2010, 1, 1, 12, 33, 33);
  13806. dt1.roll!"months"(1);
  13807. assert(dt1 == DateTime(2010, 2, 1, 12, 33, 33));
  13808. auto dt2 = DateTime(2010, 1, 1, 12, 33, 33);
  13809. dt2.roll!"months"(-1);
  13810. assert(dt2 == DateTime(2010, 12, 1, 12, 33, 33));
  13811. auto dt3 = DateTime(1999, 1, 29, 12, 33, 33);
  13812. dt3.roll!"months"(1);
  13813. assert(dt3 == DateTime(1999, 3, 1, 12, 33, 33));
  13814. auto dt4 = DateTime(1999, 1, 29, 12, 33, 33);
  13815. dt4.roll!"months"(1, AllowDayOverflow.no);
  13816. assert(dt4 == DateTime(1999, 2, 28, 12, 33, 33));
  13817. auto dt5 = DateTime(2000, 2, 29, 12, 30, 33);
  13818. dt5.roll!"years"(1);
  13819. assert(dt5 == DateTime(2001, 3, 1, 12, 30, 33));
  13820. auto dt6 = DateTime(2000, 2, 29, 12, 30, 33);
  13821. dt6.roll!"years"(1, AllowDayOverflow.no);
  13822. assert(dt6 == DateTime(2001, 2, 28, 12, 30, 33));
  13823. }
  13824. }
  13825. unittest
  13826. {
  13827. version(testStdDateTime)
  13828. {
  13829. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  13830. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  13831. static assert(!__traits(compiles, cdt.roll!"years"(4)));
  13832. static assert(!__traits(compiles, idt.roll!"years"(4)));
  13833. static assert(!__traits(compiles, cdt.roll!"months"(4)));
  13834. static assert(!__traits(compiles, idt.roll!"months"(4)));
  13835. static assert(!__traits(compiles, cdt.roll!"days"(4)));
  13836. static assert(!__traits(compiles, idt.roll!"days"(4)));
  13837. }
  13838. }
  13839. /++
  13840. Adds the given number of units to this $(D DateTime). A negative number
  13841. will subtract.
  13842. The difference between rolling and adding is that rolling does not
  13843. affect larger units. So, for instance, if you roll a $(D DateTime) one
  13844. year's worth of days, then you get the exact same $(D DateTime).
  13845. Accepted units are $(D "days"), $(D "minutes"), $(D "hours"),
  13846. $(D "minutes"), and $(D "seconds").
  13847. Params:
  13848. units = The units to add.
  13849. value = The number of $(D_PARAM units) to add to this $(D DateTime).
  13850. Examples:
  13851. --------------------
  13852. auto dt1 = DateTime(2010, 1, 1, 11, 23, 12);
  13853. dt1.roll!"days"(1);
  13854. assert(dt1 == DateTime(2010, 1, 2, 11, 23, 12));
  13855. dt1.roll!"days"(365);
  13856. assert(dt1 == DateTime(2010, 1, 26, 11, 23, 12));
  13857. dt1.roll!"days"(-32);
  13858. assert(dt1 == DateTime(2010, 1, 25, 11, 23, 12));
  13859. auto dt2 = DateTime(2010, 7, 4, 12, 0, 0);
  13860. dt2.roll!"hours"(1);
  13861. assert(dt2 == DateTime(2010, 7, 4, 13, 0, 0));
  13862. auto dt3 = DateTime(2010, 1, 1, 0, 0, 0);
  13863. dt3.roll!"seconds"(-1);
  13864. assert(dt3 == DateTime(2010, 1, 1, 0, 0, 59));
  13865. --------------------
  13866. +/
  13867. /+ref DateTime+/ void roll(string units)(long days) pure nothrow
  13868. if(units == "days")
  13869. {
  13870. _date.roll!"days"(days);
  13871. }
  13872. //Verify Examples.
  13873. unittest
  13874. {
  13875. version(testStdDateTime)
  13876. {
  13877. auto dt1 = DateTime(2010, 1, 1, 11, 23, 12);
  13878. dt1.roll!"days"(1);
  13879. assert(dt1 == DateTime(2010, 1, 2, 11, 23, 12));
  13880. dt1.roll!"days"(365);
  13881. assert(dt1 == DateTime(2010, 1, 26, 11, 23, 12));
  13882. dt1.roll!"days"(-32);
  13883. assert(dt1 == DateTime(2010, 1, 25, 11, 23, 12));
  13884. auto dt2 = DateTime(2010, 7, 4, 12, 0, 0);
  13885. dt2.roll!"hours"(1);
  13886. assert(dt2 == DateTime(2010, 7, 4, 13, 0, 0));
  13887. auto dt3 = DateTime(2010, 1, 1, 0, 0, 0);
  13888. dt3.roll!"seconds"(-1);
  13889. assert(dt3 == DateTime(2010, 1, 1, 0, 0, 59));
  13890. }
  13891. }
  13892. unittest
  13893. {
  13894. version(testStdDateTime)
  13895. {
  13896. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  13897. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  13898. static assert(!__traits(compiles, cdt.roll!"days"(4)));
  13899. static assert(!__traits(compiles, idt.roll!"days"(4)));
  13900. }
  13901. }
  13902. //Shares documentation with "days" version.
  13903. /+ref DateTime+/ void roll(string units)(long value) pure nothrow
  13904. if(units == "hours" ||
  13905. units == "minutes" ||
  13906. units == "seconds")
  13907. {
  13908. _tod.roll!units(value);
  13909. }
  13910. //Test roll!"hours"().
  13911. unittest
  13912. {
  13913. version(testStdDateTime)
  13914. {
  13915. static void testDT(DateTime orig, int hours, in DateTime expected, size_t line = __LINE__)
  13916. {
  13917. orig.roll!"hours"(hours);
  13918. _assertPred!"=="(orig, expected, "", __FILE__, line);
  13919. }
  13920. //Test A.D.
  13921. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 0, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  13922. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 1, DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)));
  13923. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 2, DateTime(Date(1999, 7, 6), TimeOfDay(14, 30, 33)));
  13924. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 3, DateTime(Date(1999, 7, 6), TimeOfDay(15, 30, 33)));
  13925. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 4, DateTime(Date(1999, 7, 6), TimeOfDay(16, 30, 33)));
  13926. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 5, DateTime(Date(1999, 7, 6), TimeOfDay(17, 30, 33)));
  13927. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 6, DateTime(Date(1999, 7, 6), TimeOfDay(18, 30, 33)));
  13928. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 7, DateTime(Date(1999, 7, 6), TimeOfDay(19, 30, 33)));
  13929. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 8, DateTime(Date(1999, 7, 6), TimeOfDay(20, 30, 33)));
  13930. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 9, DateTime(Date(1999, 7, 6), TimeOfDay(21, 30, 33)));
  13931. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 10, DateTime(Date(1999, 7, 6), TimeOfDay(22, 30, 33)));
  13932. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 11, DateTime(Date(1999, 7, 6), TimeOfDay(23, 30, 33)));
  13933. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 12, DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33)));
  13934. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 13, DateTime(Date(1999, 7, 6), TimeOfDay(1, 30, 33)));
  13935. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 14, DateTime(Date(1999, 7, 6), TimeOfDay(2, 30, 33)));
  13936. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 15, DateTime(Date(1999, 7, 6), TimeOfDay(3, 30, 33)));
  13937. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 16, DateTime(Date(1999, 7, 6), TimeOfDay(4, 30, 33)));
  13938. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 17, DateTime(Date(1999, 7, 6), TimeOfDay(5, 30, 33)));
  13939. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 18, DateTime(Date(1999, 7, 6), TimeOfDay(6, 30, 33)));
  13940. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 19, DateTime(Date(1999, 7, 6), TimeOfDay(7, 30, 33)));
  13941. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 20, DateTime(Date(1999, 7, 6), TimeOfDay(8, 30, 33)));
  13942. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 21, DateTime(Date(1999, 7, 6), TimeOfDay(9, 30, 33)));
  13943. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 22, DateTime(Date(1999, 7, 6), TimeOfDay(10, 30, 33)));
  13944. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 23, DateTime(Date(1999, 7, 6), TimeOfDay(11, 30, 33)));
  13945. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 24, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  13946. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 25, DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)));
  13947. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -1, DateTime(Date(1999, 7, 6), TimeOfDay(11, 30, 33)));
  13948. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -2, DateTime(Date(1999, 7, 6), TimeOfDay(10, 30, 33)));
  13949. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -3, DateTime(Date(1999, 7, 6), TimeOfDay(9, 30, 33)));
  13950. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -4, DateTime(Date(1999, 7, 6), TimeOfDay(8, 30, 33)));
  13951. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -5, DateTime(Date(1999, 7, 6), TimeOfDay(7, 30, 33)));
  13952. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -6, DateTime(Date(1999, 7, 6), TimeOfDay(6, 30, 33)));
  13953. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -7, DateTime(Date(1999, 7, 6), TimeOfDay(5, 30, 33)));
  13954. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -8, DateTime(Date(1999, 7, 6), TimeOfDay(4, 30, 33)));
  13955. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -9, DateTime(Date(1999, 7, 6), TimeOfDay(3, 30, 33)));
  13956. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -10, DateTime(Date(1999, 7, 6), TimeOfDay(2, 30, 33)));
  13957. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -11, DateTime(Date(1999, 7, 6), TimeOfDay(1, 30, 33)));
  13958. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -12, DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33)));
  13959. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -13, DateTime(Date(1999, 7, 6), TimeOfDay(23, 30, 33)));
  13960. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -14, DateTime(Date(1999, 7, 6), TimeOfDay(22, 30, 33)));
  13961. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -15, DateTime(Date(1999, 7, 6), TimeOfDay(21, 30, 33)));
  13962. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -16, DateTime(Date(1999, 7, 6), TimeOfDay(20, 30, 33)));
  13963. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -17, DateTime(Date(1999, 7, 6), TimeOfDay(19, 30, 33)));
  13964. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -18, DateTime(Date(1999, 7, 6), TimeOfDay(18, 30, 33)));
  13965. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -19, DateTime(Date(1999, 7, 6), TimeOfDay(17, 30, 33)));
  13966. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -20, DateTime(Date(1999, 7, 6), TimeOfDay(16, 30, 33)));
  13967. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -21, DateTime(Date(1999, 7, 6), TimeOfDay(15, 30, 33)));
  13968. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -22, DateTime(Date(1999, 7, 6), TimeOfDay(14, 30, 33)));
  13969. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -23, DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)));
  13970. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -24, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  13971. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -25, DateTime(Date(1999, 7, 6), TimeOfDay(11, 30, 33)));
  13972. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33)), 1, DateTime(Date(1999, 7, 6), TimeOfDay(1, 30, 33)));
  13973. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33)), 0, DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33)));
  13974. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33)), -1, DateTime(Date(1999, 7, 6), TimeOfDay(23, 30, 33)));
  13975. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(23, 30, 33)), 1, DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33)));
  13976. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(23, 30, 33)), 0, DateTime(Date(1999, 7, 6), TimeOfDay(23, 30, 33)));
  13977. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(23, 30, 33)), -1, DateTime(Date(1999, 7, 6), TimeOfDay(22, 30, 33)));
  13978. testDT(DateTime(Date(1999, 7, 31), TimeOfDay(23, 30, 33)), 1, DateTime(Date(1999, 7, 31), TimeOfDay(0, 30, 33)));
  13979. testDT(DateTime(Date(1999, 8, 1), TimeOfDay(0, 30, 33)), -1, DateTime(Date(1999, 8, 1), TimeOfDay(23, 30, 33)));
  13980. testDT(DateTime(Date(1999, 12, 31), TimeOfDay(23, 30, 33)), 1, DateTime(Date(1999, 12, 31), TimeOfDay(0, 30, 33)));
  13981. testDT(DateTime(Date(2000, 1, 1), TimeOfDay(0, 30, 33)), -1, DateTime(Date(2000, 1, 1), TimeOfDay(23, 30, 33)));
  13982. testDT(DateTime(Date(1999, 2, 28), TimeOfDay(23, 30, 33)), 25, DateTime(Date(1999, 2, 28), TimeOfDay(0, 30, 33)));
  13983. testDT(DateTime(Date(1999, 3, 2), TimeOfDay(0, 30, 33)), -25, DateTime(Date(1999, 3, 2), TimeOfDay(23, 30, 33)));
  13984. testDT(DateTime(Date(2000, 2, 28), TimeOfDay(23, 30, 33)), 25, DateTime(Date(2000, 2, 28), TimeOfDay(0, 30, 33)));
  13985. testDT(DateTime(Date(2000, 3, 1), TimeOfDay(0, 30, 33)), -25, DateTime(Date(2000, 3, 1), TimeOfDay(23, 30, 33)));
  13986. //Test B.C.
  13987. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 0, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  13988. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 1, DateTime(Date(-1999, 7, 6), TimeOfDay(13, 30, 33)));
  13989. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 2, DateTime(Date(-1999, 7, 6), TimeOfDay(14, 30, 33)));
  13990. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 3, DateTime(Date(-1999, 7, 6), TimeOfDay(15, 30, 33)));
  13991. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 4, DateTime(Date(-1999, 7, 6), TimeOfDay(16, 30, 33)));
  13992. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 5, DateTime(Date(-1999, 7, 6), TimeOfDay(17, 30, 33)));
  13993. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 6, DateTime(Date(-1999, 7, 6), TimeOfDay(18, 30, 33)));
  13994. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 7, DateTime(Date(-1999, 7, 6), TimeOfDay(19, 30, 33)));
  13995. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 8, DateTime(Date(-1999, 7, 6), TimeOfDay(20, 30, 33)));
  13996. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 9, DateTime(Date(-1999, 7, 6), TimeOfDay(21, 30, 33)));
  13997. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 10, DateTime(Date(-1999, 7, 6), TimeOfDay(22, 30, 33)));
  13998. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 11, DateTime(Date(-1999, 7, 6), TimeOfDay(23, 30, 33)));
  13999. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 12, DateTime(Date(-1999, 7, 6), TimeOfDay(0, 30, 33)));
  14000. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 13, DateTime(Date(-1999, 7, 6), TimeOfDay(1, 30, 33)));
  14001. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 14, DateTime(Date(-1999, 7, 6), TimeOfDay(2, 30, 33)));
  14002. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 15, DateTime(Date(-1999, 7, 6), TimeOfDay(3, 30, 33)));
  14003. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 16, DateTime(Date(-1999, 7, 6), TimeOfDay(4, 30, 33)));
  14004. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 17, DateTime(Date(-1999, 7, 6), TimeOfDay(5, 30, 33)));
  14005. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 18, DateTime(Date(-1999, 7, 6), TimeOfDay(6, 30, 33)));
  14006. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 19, DateTime(Date(-1999, 7, 6), TimeOfDay(7, 30, 33)));
  14007. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 20, DateTime(Date(-1999, 7, 6), TimeOfDay(8, 30, 33)));
  14008. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 21, DateTime(Date(-1999, 7, 6), TimeOfDay(9, 30, 33)));
  14009. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 22, DateTime(Date(-1999, 7, 6), TimeOfDay(10, 30, 33)));
  14010. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 23, DateTime(Date(-1999, 7, 6), TimeOfDay(11, 30, 33)));
  14011. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 24, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  14012. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 25, DateTime(Date(-1999, 7, 6), TimeOfDay(13, 30, 33)));
  14013. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -1, DateTime(Date(-1999, 7, 6), TimeOfDay(11, 30, 33)));
  14014. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -2, DateTime(Date(-1999, 7, 6), TimeOfDay(10, 30, 33)));
  14015. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -3, DateTime(Date(-1999, 7, 6), TimeOfDay(9, 30, 33)));
  14016. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -4, DateTime(Date(-1999, 7, 6), TimeOfDay(8, 30, 33)));
  14017. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -5, DateTime(Date(-1999, 7, 6), TimeOfDay(7, 30, 33)));
  14018. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -6, DateTime(Date(-1999, 7, 6), TimeOfDay(6, 30, 33)));
  14019. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -7, DateTime(Date(-1999, 7, 6), TimeOfDay(5, 30, 33)));
  14020. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -8, DateTime(Date(-1999, 7, 6), TimeOfDay(4, 30, 33)));
  14021. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -9, DateTime(Date(-1999, 7, 6), TimeOfDay(3, 30, 33)));
  14022. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -10, DateTime(Date(-1999, 7, 6), TimeOfDay(2, 30, 33)));
  14023. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -11, DateTime(Date(-1999, 7, 6), TimeOfDay(1, 30, 33)));
  14024. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -12, DateTime(Date(-1999, 7, 6), TimeOfDay(0, 30, 33)));
  14025. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -13, DateTime(Date(-1999, 7, 6), TimeOfDay(23, 30, 33)));
  14026. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -14, DateTime(Date(-1999, 7, 6), TimeOfDay(22, 30, 33)));
  14027. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -15, DateTime(Date(-1999, 7, 6), TimeOfDay(21, 30, 33)));
  14028. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -16, DateTime(Date(-1999, 7, 6), TimeOfDay(20, 30, 33)));
  14029. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -17, DateTime(Date(-1999, 7, 6), TimeOfDay(19, 30, 33)));
  14030. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -18, DateTime(Date(-1999, 7, 6), TimeOfDay(18, 30, 33)));
  14031. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -19, DateTime(Date(-1999, 7, 6), TimeOfDay(17, 30, 33)));
  14032. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -20, DateTime(Date(-1999, 7, 6), TimeOfDay(16, 30, 33)));
  14033. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -21, DateTime(Date(-1999, 7, 6), TimeOfDay(15, 30, 33)));
  14034. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -22, DateTime(Date(-1999, 7, 6), TimeOfDay(14, 30, 33)));
  14035. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -23, DateTime(Date(-1999, 7, 6), TimeOfDay(13, 30, 33)));
  14036. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -24, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  14037. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -25, DateTime(Date(-1999, 7, 6), TimeOfDay(11, 30, 33)));
  14038. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(0, 30, 33)), 1, DateTime(Date(-1999, 7, 6), TimeOfDay(1, 30, 33)));
  14039. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(0, 30, 33)), 0, DateTime(Date(-1999, 7, 6), TimeOfDay(0, 30, 33)));
  14040. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(0, 30, 33)), -1, DateTime(Date(-1999, 7, 6), TimeOfDay(23, 30, 33)));
  14041. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(23, 30, 33)), 1, DateTime(Date(-1999, 7, 6), TimeOfDay(0, 30, 33)));
  14042. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(23, 30, 33)), 0, DateTime(Date(-1999, 7, 6), TimeOfDay(23, 30, 33)));
  14043. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(23, 30, 33)), -1, DateTime(Date(-1999, 7, 6), TimeOfDay(22, 30, 33)));
  14044. testDT(DateTime(Date(-1999, 7, 31), TimeOfDay(23, 30, 33)), 1, DateTime(Date(-1999, 7, 31), TimeOfDay(0, 30, 33)));
  14045. testDT(DateTime(Date(-1999, 8, 1), TimeOfDay(0, 30, 33)), -1, DateTime(Date(-1999, 8, 1), TimeOfDay(23, 30, 33)));
  14046. testDT(DateTime(Date(-2001, 12, 31), TimeOfDay(23, 30, 33)), 1, DateTime(Date(-2001, 12, 31), TimeOfDay(0, 30, 33)));
  14047. testDT(DateTime(Date(-2000, 1, 1), TimeOfDay(0, 30, 33)), -1, DateTime(Date(-2000, 1, 1), TimeOfDay(23, 30, 33)));
  14048. testDT(DateTime(Date(-2001, 2, 28), TimeOfDay(23, 30, 33)), 25, DateTime(Date(-2001, 2, 28), TimeOfDay(0, 30, 33)));
  14049. testDT(DateTime(Date(-2001, 3, 2), TimeOfDay(0, 30, 33)), -25, DateTime(Date(-2001, 3, 2), TimeOfDay(23, 30, 33)));
  14050. testDT(DateTime(Date(-2000, 2, 28), TimeOfDay(23, 30, 33)), 25, DateTime(Date(-2000, 2, 28), TimeOfDay(0, 30, 33)));
  14051. testDT(DateTime(Date(-2000, 3, 1), TimeOfDay(0, 30, 33)), -25, DateTime(Date(-2000, 3, 1), TimeOfDay(23, 30, 33)));
  14052. //Test Both
  14053. testDT(DateTime(Date(-1, 1, 1), TimeOfDay(11, 30, 33)), 17_546, DateTime(Date(-1, 1, 1), TimeOfDay(13, 30, 33)));
  14054. testDT(DateTime(Date(1, 1, 1), TimeOfDay(13, 30, 33)), -17_546, DateTime(Date(1, 1, 1), TimeOfDay(11, 30, 33)));
  14055. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  14056. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  14057. static assert(!__traits(compiles, cdt.roll!"hours"(4)));
  14058. static assert(!__traits(compiles, idt.roll!"hours"(4)));
  14059. //Verify Examples.
  14060. auto dt1 = DateTime(Date(2010, 7, 4), TimeOfDay(12, 0, 0));
  14061. dt1.roll!"hours"(1);
  14062. assert(dt1 == DateTime(Date(2010, 7, 4), TimeOfDay(13, 0, 0)));
  14063. auto dt2 = DateTime(Date(2010, 2, 12), TimeOfDay(12, 0, 0));
  14064. dt2.roll!"hours"(-1);
  14065. assert(dt2 == DateTime(Date(2010, 2, 12), TimeOfDay(11, 0, 0)));
  14066. auto dt3 = DateTime(Date(2009, 12, 31), TimeOfDay(23, 0, 0));
  14067. dt3.roll!"hours"(1);
  14068. assert(dt3 == DateTime(Date(2009, 12, 31), TimeOfDay(0, 0, 0)));
  14069. auto dt4 = DateTime(Date(2010, 1, 1), TimeOfDay(0, 0, 0));
  14070. dt4.roll!"hours"(-1);
  14071. assert(dt4 == DateTime(Date(2010, 1, 1), TimeOfDay(23, 0, 0)));
  14072. }
  14073. }
  14074. //Test roll!"minutes"().
  14075. unittest
  14076. {
  14077. version(testStdDateTime)
  14078. {
  14079. static void testDT(DateTime orig, int minutes, in DateTime expected, size_t line = __LINE__)
  14080. {
  14081. orig.roll!"minutes"(minutes);
  14082. _assertPred!"=="(orig, expected, "", __FILE__, line);
  14083. }
  14084. //Test A.D.
  14085. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 0, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  14086. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 1, DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)));
  14087. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 2, DateTime(Date(1999, 7, 6), TimeOfDay(12, 32, 33)));
  14088. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 3, DateTime(Date(1999, 7, 6), TimeOfDay(12, 33, 33)));
  14089. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 4, DateTime(Date(1999, 7, 6), TimeOfDay(12, 34, 33)));
  14090. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 5, DateTime(Date(1999, 7, 6), TimeOfDay(12, 35, 33)));
  14091. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 10, DateTime(Date(1999, 7, 6), TimeOfDay(12, 40, 33)));
  14092. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 15, DateTime(Date(1999, 7, 6), TimeOfDay(12, 45, 33)));
  14093. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 29, DateTime(Date(1999, 7, 6), TimeOfDay(12, 59, 33)));
  14094. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 30, DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 33)));
  14095. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 45, DateTime(Date(1999, 7, 6), TimeOfDay(12, 15, 33)));
  14096. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 60, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  14097. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 75, DateTime(Date(1999, 7, 6), TimeOfDay(12, 45, 33)));
  14098. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 90, DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 33)));
  14099. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 100, DateTime(Date(1999, 7, 6), TimeOfDay(12, 10, 33)));
  14100. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 689, DateTime(Date(1999, 7, 6), TimeOfDay(12, 59, 33)));
  14101. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 690, DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 33)));
  14102. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 691, DateTime(Date(1999, 7, 6), TimeOfDay(12, 1, 33)));
  14103. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 960, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  14104. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 1439, DateTime(Date(1999, 7, 6), TimeOfDay(12, 29, 33)));
  14105. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 1440, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  14106. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 1441, DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)));
  14107. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 2880, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  14108. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -1, DateTime(Date(1999, 7, 6), TimeOfDay(12, 29, 33)));
  14109. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -2, DateTime(Date(1999, 7, 6), TimeOfDay(12, 28, 33)));
  14110. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -3, DateTime(Date(1999, 7, 6), TimeOfDay(12, 27, 33)));
  14111. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -4, DateTime(Date(1999, 7, 6), TimeOfDay(12, 26, 33)));
  14112. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -5, DateTime(Date(1999, 7, 6), TimeOfDay(12, 25, 33)));
  14113. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -10, DateTime(Date(1999, 7, 6), TimeOfDay(12, 20, 33)));
  14114. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -15, DateTime(Date(1999, 7, 6), TimeOfDay(12, 15, 33)));
  14115. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -29, DateTime(Date(1999, 7, 6), TimeOfDay(12, 1, 33)));
  14116. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -30, DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 33)));
  14117. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -45, DateTime(Date(1999, 7, 6), TimeOfDay(12, 45, 33)));
  14118. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -60, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  14119. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -75, DateTime(Date(1999, 7, 6), TimeOfDay(12, 15, 33)));
  14120. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -90, DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 33)));
  14121. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -100, DateTime(Date(1999, 7, 6), TimeOfDay(12, 50, 33)));
  14122. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -749, DateTime(Date(1999, 7, 6), TimeOfDay(12, 1, 33)));
  14123. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -750, DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 33)));
  14124. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -751, DateTime(Date(1999, 7, 6), TimeOfDay(12, 59, 33)));
  14125. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -960, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  14126. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -1439, DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)));
  14127. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -1440, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  14128. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -1441, DateTime(Date(1999, 7, 6), TimeOfDay(12, 29, 33)));
  14129. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -2880, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  14130. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 33)), 1, DateTime(Date(1999, 7, 6), TimeOfDay(12, 1, 33)));
  14131. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 33)), 0, DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 33)));
  14132. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 33)), -1, DateTime(Date(1999, 7, 6), TimeOfDay(12, 59, 33)));
  14133. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(11, 59, 33)), 1, DateTime(Date(1999, 7, 6), TimeOfDay(11, 0, 33)));
  14134. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(11, 59, 33)), 0, DateTime(Date(1999, 7, 6), TimeOfDay(11, 59, 33)));
  14135. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(11, 59, 33)), -1, DateTime(Date(1999, 7, 6), TimeOfDay(11, 58, 33)));
  14136. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33)), 1, DateTime(Date(1999, 7, 6), TimeOfDay(0, 1, 33)));
  14137. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33)), 0, DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33)));
  14138. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33)), -1, DateTime(Date(1999, 7, 6), TimeOfDay(0, 59, 33)));
  14139. testDT(DateTime(Date(1999, 7, 5), TimeOfDay(23, 59, 33)), 1, DateTime(Date(1999, 7, 5), TimeOfDay(23, 0, 33)));
  14140. testDT(DateTime(Date(1999, 7, 5), TimeOfDay(23, 59, 33)), 0, DateTime(Date(1999, 7, 5), TimeOfDay(23, 59, 33)));
  14141. testDT(DateTime(Date(1999, 7, 5), TimeOfDay(23, 59, 33)), -1, DateTime(Date(1999, 7, 5), TimeOfDay(23, 58, 33)));
  14142. testDT(DateTime(Date(1998, 12, 31), TimeOfDay(23, 59, 33)), 1, DateTime(Date(1998, 12, 31), TimeOfDay(23, 0, 33)));
  14143. testDT(DateTime(Date(1998, 12, 31), TimeOfDay(23, 59, 33)), 0, DateTime(Date(1998, 12, 31), TimeOfDay(23, 59, 33)));
  14144. testDT(DateTime(Date(1998, 12, 31), TimeOfDay(23, 59, 33)), -1, DateTime(Date(1998, 12, 31), TimeOfDay(23, 58, 33)));
  14145. //Test B.C.
  14146. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 0, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  14147. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 1, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 31, 33)));
  14148. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 2, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 32, 33)));
  14149. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 3, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 33, 33)));
  14150. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 4, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 34, 33)));
  14151. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 5, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 35, 33)));
  14152. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 10, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 40, 33)));
  14153. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 15, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 45, 33)));
  14154. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 29, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 59, 33)));
  14155. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 30, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 33)));
  14156. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 45, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 15, 33)));
  14157. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 60, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  14158. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 75, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 45, 33)));
  14159. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 90, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 33)));
  14160. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 100, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 10, 33)));
  14161. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 689, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 59, 33)));
  14162. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 690, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 33)));
  14163. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 691, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 1, 33)));
  14164. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 960, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  14165. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 1439, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 29, 33)));
  14166. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 1440, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  14167. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 1441, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 31, 33)));
  14168. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 2880, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  14169. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -1, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 29, 33)));
  14170. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -2, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 28, 33)));
  14171. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -3, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 27, 33)));
  14172. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -4, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 26, 33)));
  14173. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -5, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 25, 33)));
  14174. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -10, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 20, 33)));
  14175. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -15, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 15, 33)));
  14176. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -29, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 1, 33)));
  14177. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -30, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 33)));
  14178. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -45, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 45, 33)));
  14179. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -60, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  14180. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -75, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 15, 33)));
  14181. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -90, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 33)));
  14182. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -100, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 50, 33)));
  14183. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -749, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 1, 33)));
  14184. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -750, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 33)));
  14185. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -751, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 59, 33)));
  14186. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -960, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  14187. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -1439, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 31, 33)));
  14188. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -1440, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  14189. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -1441, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 29, 33)));
  14190. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -2880, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  14191. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 33)), 1, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 1, 33)));
  14192. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 33)), 0, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 33)));
  14193. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 33)), -1, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 59, 33)));
  14194. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(11, 59, 33)), 1, DateTime(Date(-1999, 7, 6), TimeOfDay(11, 0, 33)));
  14195. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(11, 59, 33)), 0, DateTime(Date(-1999, 7, 6), TimeOfDay(11, 59, 33)));
  14196. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(11, 59, 33)), -1, DateTime(Date(-1999, 7, 6), TimeOfDay(11, 58, 33)));
  14197. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(0, 0, 33)), 1, DateTime(Date(-1999, 7, 6), TimeOfDay(0, 1, 33)));
  14198. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(0, 0, 33)), 0, DateTime(Date(-1999, 7, 6), TimeOfDay(0, 0, 33)));
  14199. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(0, 0, 33)), -1, DateTime(Date(-1999, 7, 6), TimeOfDay(0, 59, 33)));
  14200. testDT(DateTime(Date(-1999, 7, 5), TimeOfDay(23, 59, 33)), 1, DateTime(Date(-1999, 7, 5), TimeOfDay(23, 0, 33)));
  14201. testDT(DateTime(Date(-1999, 7, 5), TimeOfDay(23, 59, 33)), 0, DateTime(Date(-1999, 7, 5), TimeOfDay(23, 59, 33)));
  14202. testDT(DateTime(Date(-1999, 7, 5), TimeOfDay(23, 59, 33)), -1, DateTime(Date(-1999, 7, 5), TimeOfDay(23, 58, 33)));
  14203. testDT(DateTime(Date(-2000, 12, 31), TimeOfDay(23, 59, 33)), 1, DateTime(Date(-2000, 12, 31), TimeOfDay(23, 0, 33)));
  14204. testDT(DateTime(Date(-2000, 12, 31), TimeOfDay(23, 59, 33)), 0, DateTime(Date(-2000, 12, 31), TimeOfDay(23, 59, 33)));
  14205. testDT(DateTime(Date(-2000, 12, 31), TimeOfDay(23, 59, 33)), -1, DateTime(Date(-2000, 12, 31), TimeOfDay(23, 58, 33)));
  14206. //Test Both
  14207. testDT(DateTime(Date(1, 1, 1), TimeOfDay(0, 0, 0)), -1, DateTime(Date(1, 1, 1), TimeOfDay(0, 59, 0)));
  14208. testDT(DateTime(Date(0, 12, 31), TimeOfDay(23, 59, 0)), 1, DateTime(Date(0, 12, 31), TimeOfDay(23, 0, 0)));
  14209. testDT(DateTime(Date(0, 1, 1), TimeOfDay(0, 0, 0)), -1, DateTime(Date(0, 1, 1), TimeOfDay(0, 59, 0)));
  14210. testDT(DateTime(Date(-1, 12, 31), TimeOfDay(23, 59, 0)), 1, DateTime(Date(-1, 12, 31), TimeOfDay(23, 0, 0)));
  14211. testDT(DateTime(Date(-1, 1, 1), TimeOfDay(11, 30, 33)), 1_052_760, DateTime(Date(-1, 1, 1), TimeOfDay(11, 30, 33)));
  14212. testDT(DateTime(Date(1, 1, 1), TimeOfDay(13, 30, 33)), -1_052_760, DateTime(Date(1, 1, 1), TimeOfDay(13, 30, 33)));
  14213. testDT(DateTime(Date(-1, 1, 1), TimeOfDay(11, 30, 33)), 1_052_782, DateTime(Date(-1, 1, 1), TimeOfDay(11, 52, 33)));
  14214. testDT(DateTime(Date(1, 1, 1), TimeOfDay(13, 52, 33)), -1_052_782, DateTime(Date(1, 1, 1), TimeOfDay(13, 30, 33)));
  14215. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  14216. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  14217. static assert(!__traits(compiles, cdt.roll!"minutes"(4)));
  14218. static assert(!__traits(compiles, idt.roll!"minutes"(4)));
  14219. }
  14220. }
  14221. //Test roll!"seconds"().
  14222. unittest
  14223. {
  14224. version(testStdDateTime)
  14225. {
  14226. static void testDT(DateTime orig, int seconds, in DateTime expected, size_t line = __LINE__)
  14227. {
  14228. orig.roll!"seconds"(seconds);
  14229. _assertPred!"=="(orig, expected, "", __FILE__, line);
  14230. }
  14231. //Test A.D.
  14232. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 0, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  14233. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 1, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)));
  14234. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 2, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 35)));
  14235. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 3, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 36)));
  14236. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 4, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 37)));
  14237. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 5, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 38)));
  14238. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 10, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 43)));
  14239. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 15, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 48)));
  14240. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 26, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 59)));
  14241. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 27, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0)));
  14242. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 30, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 3)));
  14243. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 59, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 32)));
  14244. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 60, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  14245. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 61, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)));
  14246. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 1766, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 59)));
  14247. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 1767, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0)));
  14248. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 1768, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 1)));
  14249. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 2007, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0)));
  14250. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 3599, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 32)));
  14251. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 3600, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  14252. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 3601, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)));
  14253. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 7200, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  14254. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -1, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 32)));
  14255. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -2, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 31)));
  14256. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -3, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 30)));
  14257. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -4, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 29)));
  14258. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -5, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 28)));
  14259. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -10, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 23)));
  14260. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -15, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 18)));
  14261. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -33, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0)));
  14262. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -34, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 59)));
  14263. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -35, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 58)));
  14264. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -59, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)));
  14265. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -60, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  14266. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -61, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 32)));
  14267. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0)), 1, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 1)));
  14268. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0)), 0, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0)));
  14269. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0)), -1, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 59)));
  14270. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 0)), 1, DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 1)));
  14271. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 0)), 0, DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 0)));
  14272. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 0)), -1, DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 59)));
  14273. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), 1, DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 1)));
  14274. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), 0, DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)));
  14275. testDT(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), -1, DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 59)));
  14276. testDT(DateTime(Date(1999, 7, 5), TimeOfDay(23, 59, 59)), 1, DateTime(Date(1999, 7, 5), TimeOfDay(23, 59, 0)));
  14277. testDT(DateTime(Date(1999, 7, 5), TimeOfDay(23, 59, 59)), 0, DateTime(Date(1999, 7, 5), TimeOfDay(23, 59, 59)));
  14278. testDT(DateTime(Date(1999, 7, 5), TimeOfDay(23, 59, 59)), -1, DateTime(Date(1999, 7, 5), TimeOfDay(23, 59, 58)));
  14279. testDT(DateTime(Date(1998, 12, 31), TimeOfDay(23, 59, 59)), 1, DateTime(Date(1998, 12, 31), TimeOfDay(23, 59, 0)));
  14280. testDT(DateTime(Date(1998, 12, 31), TimeOfDay(23, 59, 59)), 0, DateTime(Date(1998, 12, 31), TimeOfDay(23, 59, 59)));
  14281. testDT(DateTime(Date(1998, 12, 31), TimeOfDay(23, 59, 59)), -1, DateTime(Date(1998, 12, 31), TimeOfDay(23, 59, 58)));
  14282. //Test B.C.
  14283. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 0, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  14284. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 1, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 34)));
  14285. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 2, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 35)));
  14286. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 3, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 36)));
  14287. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 4, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 37)));
  14288. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 5, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 38)));
  14289. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 10, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 43)));
  14290. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 15, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 48)));
  14291. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 26, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 59)));
  14292. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 27, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 0)));
  14293. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 30, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 3)));
  14294. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 59, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 32)));
  14295. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 60, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  14296. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 61, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 34)));
  14297. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 1766, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 59)));
  14298. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 1767, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 0)));
  14299. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 1768, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 1)));
  14300. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 2007, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 0)));
  14301. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 3599, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 32)));
  14302. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 3600, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  14303. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 3601, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 34)));
  14304. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 7200, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  14305. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -1, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 32)));
  14306. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -2, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 31)));
  14307. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -3, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 30)));
  14308. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -4, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 29)));
  14309. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -5, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 28)));
  14310. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -10, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 23)));
  14311. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -15, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 18)));
  14312. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -33, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 0)));
  14313. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -34, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 59)));
  14314. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -35, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 58)));
  14315. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -59, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 34)));
  14316. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -60, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  14317. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -61, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 32)));
  14318. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 0)), 1, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 1)));
  14319. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 0)), 0, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 0)));
  14320. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 0)), -1, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 59)));
  14321. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 0)), 1, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 1)));
  14322. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 0)), 0, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 0)));
  14323. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 0)), -1, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 59)));
  14324. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(0, 0, 0)), 1, DateTime(Date(-1999, 7, 6), TimeOfDay(0, 0, 1)));
  14325. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(0, 0, 0)), 0, DateTime(Date(-1999, 7, 6), TimeOfDay(0, 0, 0)));
  14326. testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(0, 0, 0)), -1, DateTime(Date(-1999, 7, 6), TimeOfDay(0, 0, 59)));
  14327. testDT(DateTime(Date(-1999, 7, 5), TimeOfDay(23, 59, 59)), 1, DateTime(Date(-1999, 7, 5), TimeOfDay(23, 59, 0)));
  14328. testDT(DateTime(Date(-1999, 7, 5), TimeOfDay(23, 59, 59)), 0, DateTime(Date(-1999, 7, 5), TimeOfDay(23, 59, 59)));
  14329. testDT(DateTime(Date(-1999, 7, 5), TimeOfDay(23, 59, 59)), -1, DateTime(Date(-1999, 7, 5), TimeOfDay(23, 59, 58)));
  14330. testDT(DateTime(Date(-2000, 12, 31), TimeOfDay(23, 59, 59)), 1, DateTime(Date(-2000, 12, 31), TimeOfDay(23, 59, 0)));
  14331. testDT(DateTime(Date(-2000, 12, 31), TimeOfDay(23, 59, 59)), 0, DateTime(Date(-2000, 12, 31), TimeOfDay(23, 59, 59)));
  14332. testDT(DateTime(Date(-2000, 12, 31), TimeOfDay(23, 59, 59)), -1, DateTime(Date(-2000, 12, 31), TimeOfDay(23, 59, 58)));
  14333. //Test Both
  14334. testDT(DateTime(Date(1, 1, 1), TimeOfDay(0, 0, 0)), -1, DateTime(Date(1, 1, 1), TimeOfDay(0, 0, 59)));
  14335. testDT(DateTime(Date(0, 12, 31), TimeOfDay(23, 59, 59)), 1, DateTime(Date(0, 12, 31), TimeOfDay(23, 59, 0)));
  14336. testDT(DateTime(Date(0, 1, 1), TimeOfDay(0, 0, 0)), -1, DateTime(Date(0, 1, 1), TimeOfDay(0, 0, 59)));
  14337. testDT(DateTime(Date(-1, 12, 31), TimeOfDay(23, 59, 59)), 1, DateTime(Date(-1, 12, 31), TimeOfDay(23, 59, 0)));
  14338. testDT(DateTime(Date(-1, 1, 1), TimeOfDay(11, 30, 33)), 63_165_600L, DateTime(Date(-1, 1, 1), TimeOfDay(11, 30, 33)));
  14339. testDT(DateTime(Date(1, 1, 1), TimeOfDay(13, 30, 33)), -63_165_600L, DateTime(Date(1, 1, 1), TimeOfDay(13, 30, 33)));
  14340. testDT(DateTime(Date(-1, 1, 1), TimeOfDay(11, 30, 33)), 63_165_617L, DateTime(Date(-1, 1, 1), TimeOfDay(11, 30, 50)));
  14341. testDT(DateTime(Date(1, 1, 1), TimeOfDay(13, 30, 50)), -63_165_617L, DateTime(Date(1, 1, 1), TimeOfDay(13, 30, 33)));
  14342. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  14343. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  14344. static assert(!__traits(compiles, cdt.roll!"seconds"(4)));
  14345. static assert(!__traits(compiles, idt.roll!"seconds"(4)));
  14346. }
  14347. }
  14348. /++
  14349. Gives the result of adding or subtracting a duration from this
  14350. $(D DateTime).
  14351. The legal types of arithmetic for $(D DateTime) using this operator are
  14352. $(BOOKTABLE,
  14353. $(TR $(TD DateTime) $(TD +) $(TD duration) $(TD -->) $(TD DateTime))
  14354. $(TR $(TD DateTime) $(TD -) $(TD duration) $(TD -->) $(TD DateTime))
  14355. )
  14356. Params:
  14357. duration = The duration to add to or subtract from this
  14358. $(D DateTime).
  14359. +/
  14360. DateTime opBinary(string op, D)(in D duration) const pure nothrow
  14361. if((op == "+" || op == "-") &&
  14362. (is(Unqual!D == Duration) ||
  14363. is(Unqual!D == TickDuration)))
  14364. {
  14365. DateTime retval = this;
  14366. static if(is(Unqual!D == Duration))
  14367. immutable hnsecs = duration.total!"hnsecs";
  14368. else static if(is(Unqual!D == TickDuration))
  14369. immutable hnsecs = duration.hnsecs;
  14370. //Ideally, this would just be
  14371. //return retval.addSeconds(convert!("hnsecs", "seconds")(unaryFun!(op ~ "a")(hnsecs)));
  14372. //But there isn't currently a pure version of unaryFun!().
  14373. static if(op == "+")
  14374. immutable signedHNSecs = hnsecs;
  14375. else static if(op == "-")
  14376. immutable signedHNSecs = -hnsecs;
  14377. else
  14378. static assert(0);
  14379. return retval.addSeconds(convert!("hnsecs", "seconds")(signedHNSecs));
  14380. }
  14381. unittest
  14382. {
  14383. version(testStdDateTime)
  14384. {
  14385. auto dt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14386. _assertPred!"=="(dt + dur!"weeks"(7), DateTime(Date(1999, 8, 24), TimeOfDay(12, 30, 33)));
  14387. _assertPred!"=="(dt + dur!"weeks"(-7), DateTime(Date(1999, 5, 18), TimeOfDay(12, 30, 33)));
  14388. _assertPred!"=="(dt + dur!"days"(7), DateTime(Date(1999, 7, 13), TimeOfDay(12, 30, 33)));
  14389. _assertPred!"=="(dt + dur!"days"(-7), DateTime(Date(1999, 6, 29), TimeOfDay(12, 30, 33)));
  14390. _assertPred!"=="(dt + dur!"hours"(7), DateTime(Date(1999, 7, 6), TimeOfDay(19, 30, 33)));
  14391. _assertPred!"=="(dt + dur!"hours"(-7), DateTime(Date(1999, 7, 6), TimeOfDay(5, 30, 33)));
  14392. _assertPred!"=="(dt + dur!"minutes"(7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 37, 33)));
  14393. _assertPred!"=="(dt + dur!"minutes"(-7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 23, 33)));
  14394. _assertPred!"=="(dt + dur!"seconds"(7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
  14395. _assertPred!"=="(dt + dur!"seconds"(-7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
  14396. _assertPred!"=="(dt + dur!"msecs"(7_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
  14397. _assertPred!"=="(dt + dur!"msecs"(-7_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
  14398. _assertPred!"=="(dt + dur!"usecs"(7_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
  14399. _assertPred!"=="(dt + dur!"usecs"(-7_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
  14400. _assertPred!"=="(dt + dur!"hnsecs"(70_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
  14401. _assertPred!"=="(dt + dur!"hnsecs"(-70_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
  14402. //This probably only runs in cases where gettimeofday() is used, but it's
  14403. //hard to do this test correctly with variable ticksPerSec.
  14404. if(TickDuration.ticksPerSec == 1_000_000)
  14405. {
  14406. _assertPred!"=="(dt + TickDuration.from!"usecs"(7_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
  14407. _assertPred!"=="(dt + TickDuration.from!"usecs"(-7_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
  14408. }
  14409. _assertPred!"=="(dt - dur!"weeks"(-7), DateTime(Date(1999, 8, 24), TimeOfDay(12, 30, 33)));
  14410. _assertPred!"=="(dt - dur!"weeks"(7), DateTime(Date(1999, 5, 18), TimeOfDay(12, 30, 33)));
  14411. _assertPred!"=="(dt - dur!"days"(-7), DateTime(Date(1999, 7, 13), TimeOfDay(12, 30, 33)));
  14412. _assertPred!"=="(dt - dur!"days"(7), DateTime(Date(1999, 6, 29), TimeOfDay(12, 30, 33)));
  14413. _assertPred!"=="(dt - dur!"hours"(-7), DateTime(Date(1999, 7, 6), TimeOfDay(19, 30, 33)));
  14414. _assertPred!"=="(dt - dur!"hours"(7), DateTime(Date(1999, 7, 6), TimeOfDay(5, 30, 33)));
  14415. _assertPred!"=="(dt - dur!"minutes"(-7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 37, 33)));
  14416. _assertPred!"=="(dt - dur!"minutes"(7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 23, 33)));
  14417. _assertPred!"=="(dt - dur!"seconds"(-7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
  14418. _assertPred!"=="(dt - dur!"seconds"(7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
  14419. _assertPred!"=="(dt - dur!"msecs"(-7_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
  14420. _assertPred!"=="(dt - dur!"msecs"(7_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
  14421. _assertPred!"=="(dt - dur!"usecs"(-7_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
  14422. _assertPred!"=="(dt - dur!"usecs"(7_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
  14423. _assertPred!"=="(dt - dur!"hnsecs"(-70_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
  14424. _assertPred!"=="(dt - dur!"hnsecs"(70_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
  14425. //This probably only runs in cases where gettimeofday() is used, but it's
  14426. //hard to do this test correctly with variable ticksPerSec.
  14427. if(TickDuration.ticksPerSec == 1_000_000)
  14428. {
  14429. _assertPred!"=="(dt - TickDuration.from!"usecs"(-7_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
  14430. _assertPred!"=="(dt - TickDuration.from!"usecs"(7_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
  14431. }
  14432. auto duration = dur!"seconds"(12);
  14433. const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14434. immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14435. static assert(__traits(compiles, cdt + duration));
  14436. static assert(__traits(compiles, idt + duration));
  14437. static assert(__traits(compiles, cdt - duration));
  14438. static assert(__traits(compiles, idt - duration));
  14439. }
  14440. }
  14441. /++
  14442. Gives the result of adding or subtracting a duration from this
  14443. $(D DateTime), as well as assigning the result to this $(D DateTime).
  14444. The legal types of arithmetic for $(D DateTime) using this operator are
  14445. $(BOOKTABLE,
  14446. $(TR $(TD DateTime) $(TD +) $(TD duration) $(TD -->) $(TD DateTime))
  14447. $(TR $(TD DateTime) $(TD -) $(TD duration) $(TD -->) $(TD DateTime))
  14448. )
  14449. Params:
  14450. duration = The duration to add to or subtract from this
  14451. $(D DateTime).
  14452. +/
  14453. /+ref+/ DateTime opOpAssign(string op, D)(in D duration) pure nothrow
  14454. if((op == "+" || op == "-") &&
  14455. (is(Unqual!D == Duration) ||
  14456. is(Unqual!D == TickDuration)))
  14457. {
  14458. DateTime retval = this;
  14459. static if(is(Unqual!D == Duration))
  14460. immutable hnsecs = duration.total!"hnsecs";
  14461. else static if(is(Unqual!D == TickDuration))
  14462. immutable hnsecs = duration.hnsecs;
  14463. //Ideally, this would just be
  14464. //return addSeconds(convert!("hnsecs", "seconds")(unaryFun!(op ~ "a")(hnsecs)));
  14465. //But there isn't currently a pure version of unaryFun!().
  14466. static if(op == "+")
  14467. immutable signedHNSecs = hnsecs;
  14468. else static if(op == "-")
  14469. immutable signedHNSecs = -hnsecs;
  14470. else
  14471. static assert(0);
  14472. return addSeconds(convert!("hnsecs", "seconds")(signedHNSecs));
  14473. }
  14474. unittest
  14475. {
  14476. version(testStdDateTime)
  14477. {
  14478. _assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"weeks"(7), DateTime(Date(1999, 8, 24), TimeOfDay(12, 30, 33)));
  14479. _assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"weeks"(-7), DateTime(Date(1999, 5, 18), TimeOfDay(12, 30, 33)));
  14480. _assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"days"(7), DateTime(Date(1999, 7, 13), TimeOfDay(12, 30, 33)));
  14481. _assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"days"(-7), DateTime(Date(1999, 6, 29), TimeOfDay(12, 30, 33)));
  14482. _assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"hours"(7), DateTime(Date(1999, 7, 6), TimeOfDay(19, 30, 33)));
  14483. _assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"hours"(-7), DateTime(Date(1999, 7, 6), TimeOfDay(5, 30, 33)));
  14484. _assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"minutes"(7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 37, 33)));
  14485. _assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"minutes"(-7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 23, 33)));
  14486. _assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"seconds"(7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
  14487. _assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"seconds"(-7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
  14488. _assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"msecs"(7_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
  14489. _assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"msecs"(-7_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
  14490. _assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"usecs"(7_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
  14491. _assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"usecs"(-7_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
  14492. _assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"hnsecs"(70_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
  14493. _assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"hnsecs"(-70_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
  14494. _assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"weeks"(-7), DateTime(Date(1999, 8, 24), TimeOfDay(12, 30, 33)));
  14495. _assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"weeks"(7), DateTime(Date(1999, 5, 18), TimeOfDay(12, 30, 33)));
  14496. _assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"days"(-7), DateTime(Date(1999, 7, 13), TimeOfDay(12, 30, 33)));
  14497. _assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"days"(7), DateTime(Date(1999, 6, 29), TimeOfDay(12, 30, 33)));
  14498. _assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"hours"(-7), DateTime(Date(1999, 7, 6), TimeOfDay(19, 30, 33)));
  14499. _assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"hours"(7), DateTime(Date(1999, 7, 6), TimeOfDay(5, 30, 33)));
  14500. _assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"minutes"(-7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 37, 33)));
  14501. _assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"minutes"(7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 23, 33)));
  14502. _assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"seconds"(-7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
  14503. _assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"seconds"(7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
  14504. _assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"msecs"(-7_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
  14505. _assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"msecs"(7_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
  14506. _assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"usecs"(-7_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
  14507. _assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"usecs"(7_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
  14508. _assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"hnsecs"(-70_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
  14509. _assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"hnsecs"(70_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
  14510. auto duration = dur!"seconds"(12);
  14511. const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14512. immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14513. static assert(!__traits(compiles, cdt += duration));
  14514. static assert(!__traits(compiles, idt += duration));
  14515. static assert(!__traits(compiles, cdt -= duration));
  14516. static assert(!__traits(compiles, idt -= duration));
  14517. }
  14518. }
  14519. /++
  14520. Gives the difference between two $(D DateTime)s.
  14521. The legal types of arithmetic for $(D DateTime) using this operator are
  14522. $(BOOKTABLE,
  14523. $(TR $(TD DateTime) $(TD -) $(TD DateTime) $(TD -->) $(TD duration))
  14524. )
  14525. +/
  14526. Duration opBinary(string op)(in DateTime rhs) const pure nothrow
  14527. if(op == "-")
  14528. {
  14529. immutable dateResult = _date - rhs.date;
  14530. immutable todResult = _tod - rhs._tod;
  14531. return dur!"hnsecs"(dateResult.total!"hnsecs" + todResult.total!"hnsecs");
  14532. }
  14533. unittest
  14534. {
  14535. version(testStdDateTime)
  14536. {
  14537. auto dt = DateTime(1999, 7, 6, 12, 30, 33);
  14538. _assertPred!"=="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)) -
  14539. DateTime(Date(1998, 7, 6), TimeOfDay(12, 30, 33)),
  14540. dur!"seconds"(31_536_000));
  14541. _assertPred!"=="(DateTime(Date(1998, 7, 6), TimeOfDay(12, 30, 33)) -
  14542. DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
  14543. dur!"seconds"(-31_536_000));
  14544. _assertPred!"=="(DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33)) -
  14545. DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
  14546. dur!"seconds"(26_78_400));
  14547. _assertPred!"=="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)) -
  14548. DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33)),
  14549. dur!"seconds"(-26_78_400));
  14550. _assertPred!"=="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)) -
  14551. DateTime(Date(1999, 7, 5), TimeOfDay(12, 30, 33)),
  14552. dur!"seconds"(86_400));
  14553. _assertPred!"=="(DateTime(Date(1999, 7, 5), TimeOfDay(12, 30, 33)) -
  14554. DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
  14555. dur!"seconds"(-86_400));
  14556. _assertPred!"=="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)) -
  14557. DateTime(Date(1999, 7, 6), TimeOfDay(11, 30, 33)),
  14558. dur!"seconds"(3600));
  14559. _assertPred!"=="(DateTime(Date(1999, 7, 6), TimeOfDay(11, 30, 33)) -
  14560. DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
  14561. dur!"seconds"(-3600));
  14562. _assertPred!"=="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)) -
  14563. DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
  14564. dur!"seconds"(60));
  14565. _assertPred!"=="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)) -
  14566. DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)),
  14567. dur!"seconds"(-60));
  14568. _assertPred!"=="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)) -
  14569. DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
  14570. dur!"seconds"(1));
  14571. _assertPred!"=="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)) -
  14572. DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)),
  14573. dur!"seconds"(-1));
  14574. _assertPred!"=="(DateTime(1, 1, 1, 12, 30, 33) - DateTime(1, 1, 1, 0, 0, 0), dur!"seconds"(45033));
  14575. _assertPred!"=="(DateTime(1, 1, 1, 0, 0, 0) - DateTime(1, 1, 1, 12, 30, 33), dur!"seconds"(-45033));
  14576. _assertPred!"=="(DateTime(0, 12, 31, 12, 30, 33) - DateTime(1, 1, 1, 0, 0, 0), dur!"seconds"(-41367));
  14577. _assertPred!"=="(DateTime(1, 1, 1, 0, 0, 0) - DateTime(0, 12, 31, 12, 30, 33), dur!"seconds"(41367));
  14578. const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14579. immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14580. static assert(__traits(compiles, dt - dt));
  14581. static assert(__traits(compiles, cdt - dt));
  14582. static assert(__traits(compiles, idt - dt));
  14583. static assert(__traits(compiles, dt - cdt));
  14584. static assert(__traits(compiles, cdt - cdt));
  14585. static assert(__traits(compiles, idt - cdt));
  14586. static assert(__traits(compiles, dt - idt));
  14587. static assert(__traits(compiles, cdt - idt));
  14588. static assert(__traits(compiles, idt - idt));
  14589. }
  14590. }
  14591. /++
  14592. Returns the difference between the two $(D DateTime)s in months.
  14593. You can get the difference in years by subtracting the year property
  14594. of two $(D DateTime)s, and you can get the difference in days or weeks
  14595. by subtracting the $(D DateTime)s themselves and using the Duration that
  14596. results, but because you cannot convert between months and smaller units
  14597. without a specific date (which $(D Duration)s don't have), you cannot
  14598. get the difference in months without doing some math using both the year
  14599. and month properties, so this is a convenience function for getting the
  14600. difference in months.
  14601. Note that the number of days in the months or how far into the month
  14602. either date is is irrelevant. It is the difference in the month property
  14603. combined with the difference in years * 12. So, for instance,
  14604. December 31st and January 1st are one month apart just as December 1st
  14605. and January 31st are one month apart.
  14606. Params:
  14607. rhs = The $(D DateTime) to subtract from this one.
  14608. Examples:
  14609. --------------------
  14610. assert(DateTime(1999, 2, 1, 12, 2, 3).diffMonths(
  14611. DateTime(1999, 1, 31, 23, 59, 59)) == 1);
  14612. assert(DateTime(1999, 1, 31, 0, 0, 0).diffMonths(
  14613. DateTime(1999, 2, 1, 12, 3, 42)) == -1);
  14614. assert(DateTime(1999, 3, 1, 5, 30, 0).diffMonths(
  14615. DateTime(1999, 1, 1, 2, 4, 7)) == 2);
  14616. assert(DateTime(1999, 1, 1, 7, 2, 4).diffMonths(
  14617. DateTime(1999, 3, 31, 0, 30, 58)) == -2);
  14618. --------------------
  14619. +/
  14620. int diffMonths(in DateTime rhs) const pure nothrow
  14621. {
  14622. return _date.diffMonths(rhs._date);
  14623. }
  14624. unittest
  14625. {
  14626. version(testStdDateTime)
  14627. {
  14628. auto dt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14629. const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14630. immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14631. static assert(__traits(compiles, dt.diffMonths(dt)));
  14632. static assert(__traits(compiles, cdt.diffMonths(dt)));
  14633. static assert(__traits(compiles, idt.diffMonths(dt)));
  14634. static assert(__traits(compiles, dt.diffMonths(cdt)));
  14635. static assert(__traits(compiles, cdt.diffMonths(cdt)));
  14636. static assert(__traits(compiles, idt.diffMonths(cdt)));
  14637. static assert(__traits(compiles, dt.diffMonths(idt)));
  14638. static assert(__traits(compiles, cdt.diffMonths(idt)));
  14639. static assert(__traits(compiles, idt.diffMonths(idt)));
  14640. //Verify Examples.
  14641. assert(DateTime(1999, 2, 1, 12, 2, 3).diffMonths(DateTime(1999, 1, 31, 23, 59, 59)) == 1);
  14642. assert(DateTime(1999, 1, 31, 0, 0, 0).diffMonths(DateTime(1999, 2, 1, 12, 3, 42)) == -1);
  14643. assert(DateTime(1999, 3, 1, 5, 30, 0).diffMonths(DateTime(1999, 1, 1, 2, 4, 7)) == 2);
  14644. assert(DateTime(1999, 1, 1, 7, 2, 4).diffMonths(DateTime(1999, 3, 31, 0, 30, 58)) == -2);
  14645. }
  14646. }
  14647. /++
  14648. Whether this $(D DateTime) is in a leap year.
  14649. +/
  14650. @property bool isLeapYear() const pure nothrow
  14651. {
  14652. return _date.isLeapYear;
  14653. }
  14654. unittest
  14655. {
  14656. version(testStdDateTime)
  14657. {
  14658. auto dt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14659. const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14660. immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14661. static assert(__traits(compiles, dt.isLeapYear));
  14662. static assert(__traits(compiles, cdt.isLeapYear));
  14663. static assert(__traits(compiles, idt.isLeapYear));
  14664. }
  14665. }
  14666. /++
  14667. Day of the week this $(D DateTime) is on.
  14668. +/
  14669. @property DayOfWeek dayOfWeek() const pure nothrow
  14670. {
  14671. return _date.dayOfWeek;
  14672. }
  14673. unittest
  14674. {
  14675. version(testStdDateTime)
  14676. {
  14677. auto dt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14678. const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14679. immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14680. static assert(__traits(compiles, dt.dayOfWeek));
  14681. static assert(__traits(compiles, cdt.dayOfWeek));
  14682. static assert(__traits(compiles, idt.dayOfWeek));
  14683. }
  14684. }
  14685. /++
  14686. Day of the year this $(D DateTime) is on.
  14687. Examples:
  14688. --------------------
  14689. assert(DateTime(Date(1999, 1, 1), TimeOfDay(12, 22, 7)).dayOfYear == 1);
  14690. assert(DateTime(Date(1999, 12, 31), TimeOfDay(7, 2, 59)).dayOfYear == 365);
  14691. assert(DateTime(Date(2000, 12, 31), TimeOfDay(21, 20, 0)).dayOfYear == 366);
  14692. --------------------
  14693. +/
  14694. @property ushort dayOfYear() const pure nothrow
  14695. {
  14696. return _date.dayOfYear;
  14697. }
  14698. unittest
  14699. {
  14700. version(testStdDateTime)
  14701. {
  14702. auto dt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14703. const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14704. immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14705. static assert(__traits(compiles, dt.dayOfYear));
  14706. static assert(__traits(compiles, cdt.dayOfYear));
  14707. static assert(__traits(compiles, idt.dayOfYear));
  14708. //Verify Examples.
  14709. assert(DateTime(Date(1999, 1, 1), TimeOfDay(12, 22, 7)).dayOfYear == 1);
  14710. assert(DateTime(Date(1999, 12, 31), TimeOfDay(7, 2, 59)).dayOfYear == 365);
  14711. assert(DateTime(Date(2000, 12, 31), TimeOfDay(21, 20, 0)).dayOfYear == 366);
  14712. }
  14713. }
  14714. /++
  14715. Day of the year.
  14716. Params:
  14717. day = The day of the year to set which day of the year this
  14718. $(D DateTime) is on.
  14719. +/
  14720. @property void dayOfYear(int day) pure
  14721. {
  14722. _date.dayOfYear = day;
  14723. }
  14724. unittest
  14725. {
  14726. version(testStdDateTime)
  14727. {
  14728. auto dt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14729. const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14730. immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14731. static assert(__traits(compiles, dt.dayOfYear = 12));
  14732. static assert(!__traits(compiles, cdt.dayOfYear = 12));
  14733. static assert(!__traits(compiles, idt.dayOfYear = 12));
  14734. }
  14735. }
  14736. /++
  14737. The Xth day of the Gregorian Calendar that this $(D DateTime) is on.
  14738. Examples:
  14739. --------------------
  14740. assert(DateTime(Date(1, 1, 1), TimeOfDay(0, 0, 0)).dayOfGregorianCal ==
  14741. 1);
  14742. assert(DateTime(Date(1, 12, 31), TimeOfDay(23, 59, 59)).dayOfGregorianCal ==
  14743. 365);
  14744. assert(DateTime(Date(2, 1, 1), TimeOfDay(2, 2, 2)).dayOfGregorianCal ==
  14745. 366);
  14746. assert(DateTime(Date(0, 12, 31), TimeOfDay(7, 7, 7)).dayOfGregorianCal ==
  14747. 0);
  14748. assert(DateTime(Date(0, 1, 1), TimeOfDay(19, 30, 0)).dayOfGregorianCal ==
  14749. -365);
  14750. assert(DateTime(Date(-1, 12, 31), TimeOfDay(4, 7, 0)).dayOfGregorianCal ==
  14751. -366);
  14752. assert(DateTime(Date(2000, 1, 1), TimeOfDay(9, 30, 20)).dayOfGregorianCal ==
  14753. 730_120);
  14754. assert(DateTime(Date(2010, 12, 31), TimeOfDay(15, 45, 50)).dayOfGregorianCal ==
  14755. 734_137);
  14756. --------------------
  14757. +/
  14758. @property int dayOfGregorianCal() const pure nothrow
  14759. {
  14760. return _date.dayOfGregorianCal;
  14761. }
  14762. unittest
  14763. {
  14764. version(testStdDateTime)
  14765. {
  14766. const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14767. immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14768. static assert(__traits(compiles, cdt.dayOfGregorianCal));
  14769. static assert(__traits(compiles, idt.dayOfGregorianCal));
  14770. //Verify Examples.
  14771. assert(DateTime(Date(1, 1, 1), TimeOfDay(0, 0, 0)).dayOfGregorianCal == 1);
  14772. assert(DateTime(Date(1, 12, 31), TimeOfDay(23, 59, 59)).dayOfGregorianCal == 365);
  14773. assert(DateTime(Date(2, 1, 1), TimeOfDay(2, 2, 2)).dayOfGregorianCal == 366);
  14774. assert(DateTime(Date(0, 12, 31), TimeOfDay(7, 7, 7)).dayOfGregorianCal == 0);
  14775. assert(DateTime(Date(0, 1, 1), TimeOfDay(19, 30, 0)).dayOfGregorianCal == -365);
  14776. assert(DateTime(Date(-1, 12, 31), TimeOfDay(4, 7, 0)).dayOfGregorianCal == -366);
  14777. assert(DateTime(Date(2000, 1, 1), TimeOfDay(9, 30, 20)).dayOfGregorianCal == 730_120);
  14778. assert(DateTime(Date(2010, 12, 31), TimeOfDay(15, 45, 50)).dayOfGregorianCal == 734_137);
  14779. }
  14780. }
  14781. /++
  14782. The Xth day of the Gregorian Calendar that this $(D DateTime) is on.
  14783. Setting this property does not affect the time portion of
  14784. $(D DateTime).
  14785. Params:
  14786. days = The day of the Gregorian Calendar to set this $(D DateTime)
  14787. to.
  14788. Examples:
  14789. --------------------
  14790. auto dt = DateTime(Date.init, TimeOfDay(12, 0, 0));
  14791. dt.dayOfGregorianCal = 1;
  14792. assert(dt == DateTime(Date(1, 1, 1), TimeOfDay(12, 0, 0)));
  14793. dt.dayOfGregorianCal = 365;
  14794. assert(dt == DateTime(Date(1, 12, 31), TimeOfDay(12, 0, 0)));
  14795. dt.dayOfGregorianCal = 366;
  14796. assert(dt == DateTime(Date(2, 1, 1), TimeOfDay(12, 0, 0)));
  14797. dt.dayOfGregorianCal = 0;
  14798. assert(dt == DateTime(Date(0, 12, 31), TimeOfDay(12, 0, 0)));
  14799. dt.dayOfGregorianCal = -365;
  14800. assert(dt == DateTime(Date(-0, 1, 1), TimeOfDay(12, 0, 0)));
  14801. dt.dayOfGregorianCal = -366;
  14802. assert(dt == DateTime(Date(-1, 12, 31), TimeOfDay(12, 0, 0)));
  14803. dt.dayOfGregorianCal = 730_120;
  14804. assert(dt == DateTime(Date(2000, 1, 1), TimeOfDay(12, 0, 0)));
  14805. dt.dayOfGregorianCal = 734_137;
  14806. assert(dt == DateTime(Date(2010, 12, 31), TimeOfDay(12, 0, 0)));
  14807. --------------------
  14808. +/
  14809. @property void dayOfGregorianCal(int days) pure nothrow
  14810. {
  14811. _date.dayOfGregorianCal = days;
  14812. }
  14813. unittest
  14814. {
  14815. version(testStdDateTime)
  14816. {
  14817. const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14818. immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14819. static assert(!__traits(compiles, cdt.dayOfGregorianCal = 7));
  14820. static assert(!__traits(compiles, idt.dayOfGregorianCal = 7));
  14821. //Verify Examples.
  14822. auto dt = DateTime(Date.init, TimeOfDay(12, 0, 0));
  14823. dt.dayOfGregorianCal = 1;
  14824. assert(dt == DateTime(Date(1, 1, 1), TimeOfDay(12, 0, 0)));
  14825. dt.dayOfGregorianCal = 365;
  14826. assert(dt == DateTime(Date(1, 12, 31), TimeOfDay(12, 0, 0)));
  14827. dt.dayOfGregorianCal = 366;
  14828. assert(dt == DateTime(Date(2, 1, 1), TimeOfDay(12, 0, 0)));
  14829. dt.dayOfGregorianCal = 0;
  14830. assert(dt == DateTime(Date(0, 12, 31), TimeOfDay(12, 0, 0)));
  14831. dt.dayOfGregorianCal = -365;
  14832. assert(dt == DateTime(Date(-0, 1, 1), TimeOfDay(12, 0, 0)));
  14833. dt.dayOfGregorianCal = -366;
  14834. assert(dt == DateTime(Date(-1, 12, 31), TimeOfDay(12, 0, 0)));
  14835. dt.dayOfGregorianCal = 730_120;
  14836. assert(dt == DateTime(Date(2000, 1, 1), TimeOfDay(12, 0, 0)));
  14837. dt.dayOfGregorianCal = 734_137;
  14838. assert(dt == DateTime(Date(2010, 12, 31), TimeOfDay(12, 0, 0)));
  14839. }
  14840. }
  14841. /++
  14842. The ISO 8601 week of the year that this $(D DateTime) is in.
  14843. See_Also:
  14844. $(WEB en.wikipedia.org/wiki/ISO_week_date, ISO Week Date)
  14845. +/
  14846. @property ubyte isoWeek() const pure nothrow
  14847. {
  14848. return _date.isoWeek;
  14849. }
  14850. unittest
  14851. {
  14852. version(testStdDateTime)
  14853. {
  14854. auto dt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14855. const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14856. immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14857. static assert(__traits(compiles, dt.isoWeek));
  14858. static assert(__traits(compiles, cdt.isoWeek));
  14859. static assert(__traits(compiles, idt.isoWeek));
  14860. }
  14861. }
  14862. /++
  14863. $(D DateTime) for the last day in the month that this $(D DateTime) is
  14864. in. The time portion of endOfMonth is always 23:59:59.
  14865. Examples:
  14866. --------------------
  14867. assert(DateTime(Date(1999, 1, 6), TimeOfDay(0, 0, 0)).endOfMonth ==
  14868. DateTime(Date(1999, 1, 31), TimeOfDay(23, 59, 59)));
  14869. assert(DateTime(Date(1999, 2, 7), TimeOfDay(19, 30, 0)).endOfMonth ==
  14870. DateTime(Date(1999, 2, 28), TimeOfDay(23, 59, 59)));
  14871. assert(DateTime(Date(2000, 2, 7), TimeOfDay(5, 12, 27)).endOfMonth ==
  14872. DateTime(Date(2000, 2, 29), TimeOfDay(23, 59, 59)));
  14873. assert(DateTime(Date(2000, 6, 4), TimeOfDay(12, 22, 9)).endOfMonth ==
  14874. DateTime(Date(2000, 6, 30), TimeOfDay(23, 59, 59)));
  14875. --------------------
  14876. +/
  14877. @property DateTime endOfMonth() const pure nothrow
  14878. {
  14879. try
  14880. return DateTime(_date.endOfMonth, TimeOfDay(23, 59, 59));
  14881. catch(Exception e)
  14882. assert(0, "DateTime constructor threw.");
  14883. }
  14884. unittest
  14885. {
  14886. version(testStdDateTime)
  14887. {
  14888. //Test A.D.
  14889. _assertPred!"=="(DateTime(1999, 1, 1, 0, 13, 26).endOfMonth, DateTime(1999, 1, 31, 23, 59, 59));
  14890. _assertPred!"=="(DateTime(1999, 2, 1, 1, 14, 27).endOfMonth, DateTime(1999, 2, 28, 23, 59, 59));
  14891. _assertPred!"=="(DateTime(2000, 2, 1, 2, 15, 28).endOfMonth, DateTime(2000, 2, 29, 23, 59, 59));
  14892. _assertPred!"=="(DateTime(1999, 3, 1, 3, 16, 29).endOfMonth, DateTime(1999, 3, 31, 23, 59, 59));
  14893. _assertPred!"=="(DateTime(1999, 4, 1, 4, 17, 30).endOfMonth, DateTime(1999, 4, 30, 23, 59, 59));
  14894. _assertPred!"=="(DateTime(1999, 5, 1, 5, 18, 31).endOfMonth, DateTime(1999, 5, 31, 23, 59, 59));
  14895. _assertPred!"=="(DateTime(1999, 6, 1, 6, 19, 32).endOfMonth, DateTime(1999, 6, 30, 23, 59, 59));
  14896. _assertPred!"=="(DateTime(1999, 7, 1, 7, 20, 33).endOfMonth, DateTime(1999, 7, 31, 23, 59, 59));
  14897. _assertPred!"=="(DateTime(1999, 8, 1, 8, 21, 34).endOfMonth, DateTime(1999, 8, 31, 23, 59, 59));
  14898. _assertPred!"=="(DateTime(1999, 9, 1, 9, 22, 35).endOfMonth, DateTime(1999, 9, 30, 23, 59, 59));
  14899. _assertPred!"=="(DateTime(1999, 10, 1, 10, 23, 36).endOfMonth, DateTime(1999, 10, 31, 23, 59, 59));
  14900. _assertPred!"=="(DateTime(1999, 11, 1, 11, 24, 37).endOfMonth, DateTime(1999, 11, 30, 23, 59, 59));
  14901. _assertPred!"=="(DateTime(1999, 12, 1, 12, 25, 38).endOfMonth, DateTime(1999, 12, 31, 23, 59, 59));
  14902. //Test B.C.
  14903. _assertPred!"=="(DateTime(-1999, 1, 1, 0, 13, 26).endOfMonth, DateTime(-1999, 1, 31, 23, 59, 59));
  14904. _assertPred!"=="(DateTime(-1999, 2, 1, 1, 14, 27).endOfMonth, DateTime(-1999, 2, 28, 23, 59, 59));
  14905. _assertPred!"=="(DateTime(-2000, 2, 1, 2, 15, 28).endOfMonth, DateTime(-2000, 2, 29, 23, 59, 59));
  14906. _assertPred!"=="(DateTime(-1999, 3, 1, 3, 16, 29).endOfMonth, DateTime(-1999, 3, 31, 23, 59, 59));
  14907. _assertPred!"=="(DateTime(-1999, 4, 1, 4, 17, 30).endOfMonth, DateTime(-1999, 4, 30, 23, 59, 59));
  14908. _assertPred!"=="(DateTime(-1999, 5, 1, 5, 18, 31).endOfMonth, DateTime(-1999, 5, 31, 23, 59, 59));
  14909. _assertPred!"=="(DateTime(-1999, 6, 1, 6, 19, 32).endOfMonth, DateTime(-1999, 6, 30, 23, 59, 59));
  14910. _assertPred!"=="(DateTime(-1999, 7, 1, 7, 20, 33).endOfMonth, DateTime(-1999, 7, 31, 23, 59, 59));
  14911. _assertPred!"=="(DateTime(-1999, 8, 1, 8, 21, 34).endOfMonth, DateTime(-1999, 8, 31, 23, 59, 59));
  14912. _assertPred!"=="(DateTime(-1999, 9, 1, 9, 22, 35).endOfMonth, DateTime(-1999, 9, 30, 23, 59, 59));
  14913. _assertPred!"=="(DateTime(-1999, 10, 1, 10, 23, 36).endOfMonth, DateTime(-1999, 10, 31, 23, 59, 59));
  14914. _assertPred!"=="(DateTime(-1999, 11, 1, 11, 24, 37).endOfMonth, DateTime(-1999, 11, 30, 23, 59, 59));
  14915. _assertPred!"=="(DateTime(-1999, 12, 1, 12, 25, 38).endOfMonth, DateTime(-1999, 12, 31, 23, 59, 59));
  14916. const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14917. immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14918. static assert(__traits(compiles, cdt.endOfMonth));
  14919. static assert(__traits(compiles, idt.endOfMonth));
  14920. //Verify Examples.
  14921. assert(DateTime(Date(1999, 1, 6), TimeOfDay(0, 0, 0)).endOfMonth == DateTime(Date(1999, 1, 31), TimeOfDay(23, 59, 59)));
  14922. assert(DateTime(Date(1999, 2, 7), TimeOfDay(19, 30, 0)).endOfMonth == DateTime(Date(1999, 2, 28), TimeOfDay(23, 59, 59)));
  14923. assert(DateTime(Date(2000, 2, 7), TimeOfDay(5, 12, 27)).endOfMonth == DateTime(Date(2000, 2, 29), TimeOfDay(23, 59, 59)));
  14924. assert(DateTime(Date(2000, 6, 4), TimeOfDay(12, 22, 9)).endOfMonth == DateTime(Date(2000, 6, 30), TimeOfDay(23, 59, 59)));
  14925. }
  14926. }
  14927. /++
  14928. The last day in the month that this $(D DateTime) is in.
  14929. Examples:
  14930. --------------------
  14931. assert(DateTime(Date(1999, 1, 6), TimeOfDay(0, 0, 0)).daysInMonth == 31);
  14932. assert(DateTime(Date(1999, 2, 7), TimeOfDay(19, 30, 0)).daysInMonth == 28);
  14933. assert(DateTime(Date(2000, 2, 7), TimeOfDay(5, 12, 27)).daysInMonth == 29);
  14934. assert(DateTime(Date(2000, 6, 4), TimeOfDay(12, 22, 9)).daysInMonth == 30);
  14935. --------------------
  14936. +/
  14937. @property ubyte daysInMonth() const pure nothrow
  14938. {
  14939. return _date.daysInMonth;
  14940. }
  14941. /++
  14942. $(RED Scheduled for deprecation in January 2012.
  14943. Please use daysInMonth instead.)
  14944. +/
  14945. alias daysInMonth endofMonthDay;
  14946. unittest
  14947. {
  14948. version(testStdDateTime)
  14949. {
  14950. const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14951. immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14952. static assert(__traits(compiles, cdt.daysInMonth));
  14953. static assert(__traits(compiles, idt.daysInMonth));
  14954. //Verify Examples.
  14955. assert(DateTime(Date(1999, 1, 6), TimeOfDay(0, 0, 0)).daysInMonth == 31);
  14956. assert(DateTime(Date(1999, 2, 7), TimeOfDay(19, 30, 0)).daysInMonth == 28);
  14957. assert(DateTime(Date(2000, 2, 7), TimeOfDay(5, 12, 27)).daysInMonth == 29);
  14958. assert(DateTime(Date(2000, 6, 4), TimeOfDay(12, 22, 9)).daysInMonth == 30);
  14959. }
  14960. }
  14961. /++
  14962. Whether the current year is a date in A.D.
  14963. Examples:
  14964. --------------------
  14965. assert(DateTime(Date(1, 1, 1), TimeOfDay(12, 7, 0)).isAD);
  14966. assert(DateTime(Date(2010, 12, 31), TimeOfDay(0, 0, 0)).isAD);
  14967. assert(!DateTime(Date(0, 12, 31), TimeOfDay(23, 59, 59)).isAD);
  14968. assert(!DateTime(Date(-2010, 1, 1), TimeOfDay(2, 2, 2)).isAD);
  14969. --------------------
  14970. +/
  14971. @property bool isAD() const pure nothrow
  14972. {
  14973. return _date.isAD;
  14974. }
  14975. unittest
  14976. {
  14977. version(testStdDateTime)
  14978. {
  14979. const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14980. immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  14981. static assert(__traits(compiles, cdt.isAD));
  14982. static assert(__traits(compiles, idt.isAD));
  14983. //Verify Examples.
  14984. assert(DateTime(Date(1, 1, 1), TimeOfDay(12, 7, 0)).isAD);
  14985. assert(DateTime(Date(2010, 12, 31), TimeOfDay(0, 0, 0)).isAD);
  14986. assert(!DateTime(Date(0, 12, 31), TimeOfDay(23, 59, 59)).isAD);
  14987. assert(!DateTime(Date(-2010, 1, 1), TimeOfDay(2, 2, 2)).isAD);
  14988. }
  14989. }
  14990. /++
  14991. The julian day for this $(D DateTime) at the given time. For example,
  14992. prior to noon, 1996-03-31 would be the julian day number 2_450_173, so
  14993. this function returns 2_450_173, while from noon onward, the julian
  14994. day number would be 2_450_174, so this function returns 2_450_174.
  14995. +/
  14996. @property long julianDay() const pure nothrow
  14997. {
  14998. if(_tod._hour < 12)
  14999. return _date.julianDay - 1;
  15000. else
  15001. return _date.julianDay;
  15002. }
  15003. unittest
  15004. {
  15005. version(testStdDateTime)
  15006. {
  15007. _assertPred!"=="(DateTime(Date(-4713, 11, 24), TimeOfDay(0, 0, 0)).julianDay, -1);
  15008. _assertPred!"=="(DateTime(Date(-4713, 11, 24), TimeOfDay(12, 0, 0)).julianDay, 0);
  15009. _assertPred!"=="(DateTime(Date(0, 12, 31), TimeOfDay(0, 0, 0)).julianDay, 1_721_424);
  15010. _assertPred!"=="(DateTime(Date(0, 12, 31), TimeOfDay(12, 0, 0)).julianDay, 1_721_425);
  15011. _assertPred!"=="(DateTime(Date(1, 1, 1), TimeOfDay(0, 0, 0)).julianDay, 1_721_425);
  15012. _assertPred!"=="(DateTime(Date(1, 1, 1), TimeOfDay(12, 0, 0)).julianDay, 1_721_426);
  15013. _assertPred!"=="(DateTime(Date(1582, 10, 15), TimeOfDay(0, 0, 0)).julianDay, 2_299_160);
  15014. _assertPred!"=="(DateTime(Date(1582, 10, 15), TimeOfDay(12, 0, 0)).julianDay, 2_299_161);
  15015. _assertPred!"=="(DateTime(Date(1858, 11, 17), TimeOfDay(0, 0, 0)).julianDay, 2_400_000);
  15016. _assertPred!"=="(DateTime(Date(1858, 11, 17), TimeOfDay(12, 0, 0)).julianDay, 2_400_001);
  15017. _assertPred!"=="(DateTime(Date(1982, 1, 4), TimeOfDay(0, 0, 0)).julianDay, 2_444_973);
  15018. _assertPred!"=="(DateTime(Date(1982, 1, 4), TimeOfDay(12, 0, 0)).julianDay, 2_444_974);
  15019. _assertPred!"=="(DateTime(Date(1996, 3, 31), TimeOfDay(0, 0, 0)).julianDay, 2_450_173);
  15020. _assertPred!"=="(DateTime(Date(1996, 3, 31), TimeOfDay(12, 0, 0)).julianDay, 2_450_174);
  15021. _assertPred!"=="(DateTime(Date(2010, 8, 24), TimeOfDay(0, 0, 0)).julianDay, 2_455_432);
  15022. _assertPred!"=="(DateTime(Date(2010, 8, 24), TimeOfDay(12, 0, 0)).julianDay, 2_455_433);
  15023. const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  15024. immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  15025. static assert(__traits(compiles, cdt.julianDay));
  15026. static assert(__traits(compiles, idt.julianDay));
  15027. }
  15028. }
  15029. /++
  15030. The modified julian day for any time on this date (since, the modified
  15031. julian day changes at midnight).
  15032. +/
  15033. @property long modJulianDay() const pure nothrow
  15034. {
  15035. return _date.modJulianDay;
  15036. }
  15037. unittest
  15038. {
  15039. version(testStdDateTime)
  15040. {
  15041. _assertPred!"=="(DateTime(Date(1858, 11, 17), TimeOfDay(0, 0, 0)).modJulianDay, 0);
  15042. _assertPred!"=="(DateTime(Date(1858, 11, 17), TimeOfDay(12, 0, 0)).modJulianDay, 0);
  15043. _assertPred!"=="(DateTime(Date(2010, 8, 24), TimeOfDay(0, 0, 0)).modJulianDay, 55_432);
  15044. _assertPred!"=="(DateTime(Date(2010, 8, 24), TimeOfDay(12, 0, 0)).modJulianDay, 55_432);
  15045. const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  15046. immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  15047. static assert(__traits(compiles, cdt.modJulianDay));
  15048. static assert(__traits(compiles, idt.modJulianDay));
  15049. }
  15050. }
  15051. /++
  15052. Converts this $(D DateTime) to a string with the format YYYYMMDDTHHMMSS.
  15053. Examples:
  15054. --------------------
  15055. assert(DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)).toISOString() ==
  15056. "20100704T070612");
  15057. assert(DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)).toISOString() ==
  15058. "19981225T021500");
  15059. assert(DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)).toISOString() ==
  15060. "00000105T230959");
  15061. assert(DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)).toISOString() ==
  15062. "-00040105T000002");
  15063. --------------------
  15064. +/
  15065. string toISOString() const nothrow
  15066. {
  15067. try
  15068. return format("%sT%s", _date.toISOString(), _tod.toISOString());
  15069. catch(Exception e)
  15070. assert(0, "format() threw.");
  15071. }
  15072. unittest
  15073. {
  15074. version(testStdDateTime)
  15075. {
  15076. //Test A.D.
  15077. _assertPred!"=="(DateTime(Date(9, 12, 4), TimeOfDay(0, 0, 0)).toISOString(), "00091204T000000");
  15078. _assertPred!"=="(DateTime(Date(99, 12, 4), TimeOfDay(5, 6, 12)).toISOString(), "00991204T050612");
  15079. _assertPred!"=="(DateTime(Date(999, 12, 4), TimeOfDay(13, 44, 59)).toISOString(), "09991204T134459");
  15080. _assertPred!"=="(DateTime(Date(9999, 7, 4), TimeOfDay(23, 59, 59)).toISOString(), "99990704T235959");
  15081. _assertPred!"=="(DateTime(Date(10000, 10, 20), TimeOfDay(1, 1, 1)).toISOString(), "+100001020T010101");
  15082. //Test B.C.
  15083. _assertPred!"=="(DateTime(Date(0, 12, 4), TimeOfDay(0, 12, 4)).toISOString(), "00001204T001204");
  15084. _assertPred!"=="(DateTime(Date(-9, 12, 4), TimeOfDay(0, 0, 0)).toISOString(), "-00091204T000000");
  15085. _assertPred!"=="(DateTime(Date(-99, 12, 4), TimeOfDay(5, 6, 12)).toISOString(), "-00991204T050612");
  15086. _assertPred!"=="(DateTime(Date(-999, 12, 4), TimeOfDay(13, 44, 59)).toISOString(), "-09991204T134459");
  15087. _assertPred!"=="(DateTime(Date(-9999, 7, 4), TimeOfDay(23, 59, 59)).toISOString(), "-99990704T235959");
  15088. _assertPred!"=="(DateTime(Date(-10000, 10, 20), TimeOfDay(1, 1, 1)).toISOString(), "-100001020T010101");
  15089. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  15090. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  15091. static assert(__traits(compiles, cdt.toISOString()));
  15092. static assert(__traits(compiles, idt.toISOString()));
  15093. //Verify Examples.
  15094. assert(DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)).toISOString() == "20100704T070612");
  15095. assert(DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)).toISOString() == "19981225T021500");
  15096. assert(DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)).toISOString() == "00000105T230959");
  15097. assert(DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)).toISOString() == "-00040105T000002");
  15098. }
  15099. }
  15100. /++
  15101. Converts this $(D DateTime) to a string with the format
  15102. YYYY-MM-DDTHH:MM:SS.
  15103. Examples:
  15104. --------------------
  15105. assert(DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)).toISOExtString() ==
  15106. "2010-07-04T07:06:12");
  15107. assert(DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)).toISOExtString() ==
  15108. "1998-12-25T02:15:00");
  15109. assert(DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)).toISOExtString() ==
  15110. "0000-01-05T23:09:59");
  15111. assert(DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)).toISOExtString() ==
  15112. "-0004-01-05T00:00:02");
  15113. --------------------
  15114. +/
  15115. string toISOExtString() const nothrow
  15116. {
  15117. try
  15118. return format("%sT%s", _date.toISOExtString(), _tod.toISOExtString());
  15119. catch(Exception e)
  15120. assert(0, "format() threw.");
  15121. }
  15122. /++
  15123. $(RED Scheduled for deprecation in November 2011.
  15124. Please use toISOExtString instead.)
  15125. +/
  15126. alias toISOExtString toISOExtendedString;
  15127. unittest
  15128. {
  15129. version(testStdDateTime)
  15130. {
  15131. //Test A.D.
  15132. _assertPred!"=="(DateTime(Date(9, 12, 4), TimeOfDay(0, 0, 0)).toISOExtString(), "0009-12-04T00:00:00");
  15133. _assertPred!"=="(DateTime(Date(99, 12, 4), TimeOfDay(5, 6, 12)).toISOExtString(), "0099-12-04T05:06:12");
  15134. _assertPred!"=="(DateTime(Date(999, 12, 4), TimeOfDay(13, 44, 59)).toISOExtString(), "0999-12-04T13:44:59");
  15135. _assertPred!"=="(DateTime(Date(9999, 7, 4), TimeOfDay(23, 59, 59)).toISOExtString(), "9999-07-04T23:59:59");
  15136. _assertPred!"=="(DateTime(Date(10000, 10, 20), TimeOfDay(1, 1, 1)).toISOExtString(), "+10000-10-20T01:01:01");
  15137. //Test B.C.
  15138. _assertPred!"=="(DateTime(Date(0, 12, 4), TimeOfDay(0, 12, 4)).toISOExtString(), "0000-12-04T00:12:04");
  15139. _assertPred!"=="(DateTime(Date(-9, 12, 4), TimeOfDay(0, 0, 0)).toISOExtString(), "-0009-12-04T00:00:00");
  15140. _assertPred!"=="(DateTime(Date(-99, 12, 4), TimeOfDay(5, 6, 12)).toISOExtString(), "-0099-12-04T05:06:12");
  15141. _assertPred!"=="(DateTime(Date(-999, 12, 4), TimeOfDay(13, 44, 59)).toISOExtString(), "-0999-12-04T13:44:59");
  15142. _assertPred!"=="(DateTime(Date(-9999, 7, 4), TimeOfDay(23, 59, 59)).toISOExtString(), "-9999-07-04T23:59:59");
  15143. _assertPred!"=="(DateTime(Date(-10000, 10, 20), TimeOfDay(1, 1, 1)).toISOExtString(), "-10000-10-20T01:01:01");
  15144. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  15145. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  15146. static assert(__traits(compiles, cdt.toISOExtString()));
  15147. static assert(__traits(compiles, idt.toISOExtString()));
  15148. //Verify Examples.
  15149. assert(DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)).toISOExtString() == "2010-07-04T07:06:12");
  15150. assert(DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)).toISOExtString() == "1998-12-25T02:15:00");
  15151. assert(DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)).toISOExtString() == "0000-01-05T23:09:59");
  15152. assert(DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)).toISOExtString() == "-0004-01-05T00:00:02");
  15153. }
  15154. }
  15155. /++
  15156. Converts this $(D DateTime) to a string with the format
  15157. YYYY-Mon-DD HH:MM:SS.
  15158. Examples:
  15159. --------------------
  15160. assert(DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)).toSimpleString() ==
  15161. "2010-Jul-04 07:06:12");
  15162. assert(DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)).toSimpleString() ==
  15163. "1998-Dec-25 02:15:00");
  15164. assert(DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)).toSimpleString() ==
  15165. "0000-Jan-05 23:09:59");
  15166. assert(DateTime(Dte(-4, 1, 5), TimeOfDay(0, 0, 2)).toSimpleString() ==
  15167. "-0004-Jan-05 00:00:02");
  15168. --------------------
  15169. +/
  15170. string toSimpleString() const nothrow
  15171. {
  15172. try
  15173. return format("%s %s", _date.toSimpleString(), _tod.toString());
  15174. catch(Exception e)
  15175. assert(0, "format() threw.");
  15176. }
  15177. unittest
  15178. {
  15179. version(testStdDateTime)
  15180. {
  15181. //Test A.D.
  15182. _assertPred!"=="(DateTime(Date(9, 12, 4), TimeOfDay(0, 0, 0)).toSimpleString(), "0009-Dec-04 00:00:00");
  15183. _assertPred!"=="(DateTime(Date(99, 12, 4), TimeOfDay(5, 6, 12)).toSimpleString(), "0099-Dec-04 05:06:12");
  15184. _assertPred!"=="(DateTime(Date(999, 12, 4), TimeOfDay(13, 44, 59)).toSimpleString(), "0999-Dec-04 13:44:59");
  15185. _assertPred!"=="(DateTime(Date(9999, 7, 4), TimeOfDay(23, 59, 59)).toSimpleString(), "9999-Jul-04 23:59:59");
  15186. _assertPred!"=="(DateTime(Date(10000, 10, 20), TimeOfDay(1, 1, 1)).toSimpleString(), "+10000-Oct-20 01:01:01");
  15187. //Test B.C.
  15188. _assertPred!"=="(DateTime(Date(0, 12, 4), TimeOfDay(0, 12, 4)).toSimpleString(), "0000-Dec-04 00:12:04");
  15189. _assertPred!"=="(DateTime(Date(-9, 12, 4), TimeOfDay(0, 0, 0)).toSimpleString(), "-0009-Dec-04 00:00:00");
  15190. _assertPred!"=="(DateTime(Date(-99, 12, 4), TimeOfDay(5, 6, 12)).toSimpleString(), "-0099-Dec-04 05:06:12");
  15191. _assertPred!"=="(DateTime(Date(-999, 12, 4), TimeOfDay(13, 44, 59)).toSimpleString(), "-0999-Dec-04 13:44:59");
  15192. _assertPred!"=="(DateTime(Date(-9999, 7, 4), TimeOfDay(23, 59, 59)).toSimpleString(), "-9999-Jul-04 23:59:59");
  15193. _assertPred!"=="(DateTime(Date(-10000, 10, 20), TimeOfDay(1, 1, 1)).toSimpleString(), "-10000-Oct-20 01:01:01");
  15194. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  15195. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  15196. static assert(__traits(compiles, cdt.toSimpleString()));
  15197. static assert(__traits(compiles, idt.toSimpleString()));
  15198. //Verify Examples.
  15199. assert(DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)).toSimpleString() == "2010-Jul-04 07:06:12");
  15200. assert(DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)).toSimpleString() == "1998-Dec-25 02:15:00");
  15201. assert(DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)).toSimpleString() == "0000-Jan-05 23:09:59");
  15202. assert(DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)).toSimpleString() == "-0004-Jan-05 00:00:02");
  15203. }
  15204. }
  15205. /+
  15206. Converts this $(D DateTime) to a string.
  15207. +/
  15208. //Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
  15209. //have versions of toString() with extra modifiers, so we define one version
  15210. //with modifiers and one without.
  15211. string toString()
  15212. {
  15213. return toSimpleString();
  15214. }
  15215. /++
  15216. Converts this $(D DateTime) to a string.
  15217. +/
  15218. //Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
  15219. //have versions of toString() with extra modifiers, so we define one version
  15220. //with modifiers and one without.
  15221. string toString() const nothrow
  15222. {
  15223. return toSimpleString();
  15224. }
  15225. unittest
  15226. {
  15227. version(testStdDateTime)
  15228. {
  15229. auto dt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  15230. const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  15231. immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
  15232. static assert(__traits(compiles, dt.toString()));
  15233. static assert(__traits(compiles, cdt.toString()));
  15234. static assert(__traits(compiles, idt.toString()));
  15235. }
  15236. }
  15237. /++
  15238. Creates a $(D DateTime) from a string with the format YYYYMMDDTHHMMSS.
  15239. Whitespace is stripped from the given string.
  15240. Params:
  15241. isoString = A string formatted in the ISO format for dates and times.
  15242. Throws:
  15243. $(D DateTimeException) if the given string is not in the ISO format
  15244. or if the resulting $(D DateTime) would not be valid.
  15245. Examples:
  15246. --------------------
  15247. assert(DateTime.fromISOString("20100704T070612") ==
  15248. DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
  15249. assert(DateTime.fromISOString("19981225T021500") ==
  15250. DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)));
  15251. assert(DateTime.fromISOString("00000105T230959") ==
  15252. DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)));
  15253. assert(DateTime.fromISOString("-00040105T000002") ==
  15254. DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)));
  15255. assert(DateTime.fromISOString(" 20100704T070612 ") ==
  15256. DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
  15257. --------------------
  15258. +/
  15259. static DateTime fromISOString(S)(in S isoString)
  15260. if(isSomeString!S)
  15261. {
  15262. immutable dstr = to!dstring(strip(isoString));
  15263. enforce(dstr.length >= 15, new DateTimeException(format("Invalid ISO String: %s", isoString)));
  15264. auto t = dstr.stds_indexOf('T');
  15265. enforce(t != -1, new DateTimeException(format("Invalid ISO String: %s", isoString)));
  15266. immutable date = Date.fromISOString(dstr[0..t]);
  15267. immutable tod = TimeOfDay.fromISOString(dstr[t+1 .. $]);
  15268. return DateTime(date, tod);
  15269. }
  15270. unittest
  15271. {
  15272. version(testStdDateTime)
  15273. {
  15274. assertThrown!DateTimeException(DateTime.fromISOString(""));
  15275. assertThrown!DateTimeException(DateTime.fromISOString("20100704000000"));
  15276. assertThrown!DateTimeException(DateTime.fromISOString("20100704 000000"));
  15277. assertThrown!DateTimeException(DateTime.fromISOString("20100704t000000"));
  15278. assertThrown!DateTimeException(DateTime.fromISOString("20100704T000000."));
  15279. assertThrown!DateTimeException(DateTime.fromISOString("20100704T000000.0"));
  15280. assertThrown!DateTimeException(DateTime.fromISOString("2010-07-0400:00:00"));
  15281. assertThrown!DateTimeException(DateTime.fromISOString("2010-07-04 00:00:00"));
  15282. assertThrown!DateTimeException(DateTime.fromISOString("2010-07-04t00:00:00"));
  15283. assertThrown!DateTimeException(DateTime.fromISOString("2010-07-04T00:00:00."));
  15284. assertThrown!DateTimeException(DateTime.fromISOString("2010-07-04T00:00:00.0"));
  15285. assertThrown!DateTimeException(DateTime.fromISOString("2010-Jul-0400:00:00"));
  15286. assertThrown!DateTimeException(DateTime.fromISOString("2010-Jul-04 00:00:00"));
  15287. assertThrown!DateTimeException(DateTime.fromISOString("2010-Jul-04t00:00:00"));
  15288. assertThrown!DateTimeException(DateTime.fromISOString("2010-Jul-04T00:00:00"));
  15289. assertThrown!DateTimeException(DateTime.fromISOString("2010-Jul-04 00:00:00."));
  15290. assertThrown!DateTimeException(DateTime.fromISOString("2010-Jul-04 00:00:00.0"));
  15291. assertThrown!DateTimeException(DateTime.fromISOString("2010-12-22T172201"));
  15292. assertThrown!DateTimeException(DateTime.fromISOString("2010-Dec-22 17:22:01"));
  15293. _assertPred!"=="(DateTime.fromISOString("20101222T172201"), DateTime(Date(2010, 12, 22), TimeOfDay(17, 22, 01)));
  15294. _assertPred!"=="(DateTime.fromISOString("19990706T123033"), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  15295. _assertPred!"=="(DateTime.fromISOString("-19990706T123033"), DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  15296. _assertPred!"=="(DateTime.fromISOString("+019990706T123033"), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  15297. _assertPred!"=="(DateTime.fromISOString("19990706T123033 "), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  15298. _assertPred!"=="(DateTime.fromISOString(" 19990706T123033"), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  15299. _assertPred!"=="(DateTime.fromISOString(" 19990706T123033 "), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  15300. //Verify Examples.
  15301. assert(DateTime.fromISOString("20100704T070612") == DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
  15302. assert(DateTime.fromISOString("19981225T021500") == DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)));
  15303. assert(DateTime.fromISOString("00000105T230959") == DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)));
  15304. assert(DateTime.fromISOString("-00040105T000002") == DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)));
  15305. assert(DateTime.fromISOString(" 20100704T070612 ") == DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
  15306. }
  15307. }
  15308. /++
  15309. Creates a $(D DateTime) from a string with the format
  15310. YYYY-MM-DDTHH:MM:SS. Whitespace is stripped from the given string.
  15311. Params:
  15312. isoString = A string formatted in the ISO Extended format for dates
  15313. and times.
  15314. Throws:
  15315. $(D DateTimeException) if the given string is not in the ISO
  15316. Extended format or if the resulting $(D DateTime) would not be
  15317. valid.
  15318. Examples:
  15319. --------------------
  15320. assert(DateTime.fromISOExtString("2010-07-04T07:06:12") ==
  15321. DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
  15322. assert(DateTime.fromISOExtString("1998-12-25T02:15:00") ==
  15323. DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)));
  15324. assert(DateTime.fromISOExtString("0000-01-05T23:09:59") ==
  15325. DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)));
  15326. assert(DateTime.fromISOExtString("-0004-01-05T00:00:02") ==
  15327. DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)));
  15328. assert(DateTime.fromISOExtString(" 2010-07-04T07:06:12 ") ==
  15329. DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
  15330. --------------------
  15331. +/
  15332. static DateTime fromISOExtString(S)(in S isoExtString)
  15333. if(isSomeString!(S))
  15334. {
  15335. immutable dstr = to!dstring(strip(isoExtString));
  15336. enforce(dstr.length >= 15, new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
  15337. auto t = dstr.stds_indexOf('T');
  15338. enforce(t != -1, new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
  15339. immutable date = Date.fromISOExtString(dstr[0..t]);
  15340. immutable tod = TimeOfDay.fromISOExtString(dstr[t+1 .. $]);
  15341. return DateTime(date, tod);
  15342. }
  15343. /++
  15344. $(RED Scheduled for deprecation in November 2011.
  15345. Please use fromISOExtString instead.)
  15346. +/
  15347. static DateTime fromISOExtendedString(S)(in S isoExtString)
  15348. if(isSomeString!(S))
  15349. {
  15350. pragma(msg, softDeprec!("2.053", "November 2011", "fromISOExtendedString", "fromISOExtString"));
  15351. return fromISOExtString!string(isoExtString);
  15352. }
  15353. unittest
  15354. {
  15355. version(testStdDateTime)
  15356. {
  15357. assertThrown!DateTimeException(DateTime.fromISOExtString(""));
  15358. assertThrown!DateTimeException(DateTime.fromISOExtString("20100704000000"));
  15359. assertThrown!DateTimeException(DateTime.fromISOExtString("20100704 000000"));
  15360. assertThrown!DateTimeException(DateTime.fromISOExtString("20100704t000000"));
  15361. assertThrown!DateTimeException(DateTime.fromISOExtString("20100704T000000."));
  15362. assertThrown!DateTimeException(DateTime.fromISOExtString("20100704T000000.0"));
  15363. assertThrown!DateTimeException(DateTime.fromISOExtString("2010-07:0400:00:00"));
  15364. assertThrown!DateTimeException(DateTime.fromISOExtString("2010-07-04 00:00:00"));
  15365. assertThrown!DateTimeException(DateTime.fromISOExtString("2010-07-04 00:00:00"));
  15366. assertThrown!DateTimeException(DateTime.fromISOExtString("2010-07-04t00:00:00"));
  15367. assertThrown!DateTimeException(DateTime.fromISOExtString("2010-07-04T00:00:00."));
  15368. assertThrown!DateTimeException(DateTime.fromISOExtString("2010-07-04T00:00:00.0"));
  15369. assertThrown!DateTimeException(DateTime.fromISOExtString("2010-Jul-0400:00:00"));
  15370. assertThrown!DateTimeException(DateTime.fromISOExtString("2010-Jul-04t00:00:00"));
  15371. assertThrown!DateTimeException(DateTime.fromISOExtString("2010-Jul-04 00:00:00."));
  15372. assertThrown!DateTimeException(DateTime.fromISOExtString("2010-Jul-04 00:00:00.0"));
  15373. assertThrown!DateTimeException(DateTime.fromISOExtString("20101222T172201"));
  15374. assertThrown!DateTimeException(DateTime.fromISOExtString("2010-Dec-22 17:22:01"));
  15375. _assertPred!"=="(DateTime.fromISOExtString("2010-12-22T17:22:01"), DateTime(Date(2010, 12, 22), TimeOfDay(17, 22, 01)));
  15376. _assertPred!"=="(DateTime.fromISOExtString("1999-07-06T12:30:33"), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  15377. _assertPred!"=="(DateTime.fromISOExtString("-1999-07-06T12:30:33"), DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  15378. _assertPred!"=="(DateTime.fromISOExtString("+01999-07-06T12:30:33"), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  15379. _assertPred!"=="(DateTime.fromISOExtString("1999-07-06T12:30:33 "), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  15380. _assertPred!"=="(DateTime.fromISOExtString(" 1999-07-06T12:30:33"), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  15381. _assertPred!"=="(DateTime.fromISOExtString(" 1999-07-06T12:30:33 "), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  15382. //Verify Examples.
  15383. assert(DateTime.fromISOExtString("2010-07-04T07:06:12") == DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
  15384. assert(DateTime.fromISOExtString("1998-12-25T02:15:00") == DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)));
  15385. assert(DateTime.fromISOExtString("0000-01-05T23:09:59") == DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)));
  15386. assert(DateTime.fromISOExtString("-0004-01-05T00:00:02") == DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)));
  15387. assert(DateTime.fromISOExtString(" 2010-07-04T07:06:12 ") == DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
  15388. }
  15389. }
  15390. /++
  15391. Creates a $(D DateTime) from a string with the format
  15392. YYYY-Mon-DD HH:MM:SS. Whitespace is stripped from the given string.
  15393. Params:
  15394. simpleString = A string formatted in the way that toSimpleString
  15395. formats dates and times.
  15396. Throws:
  15397. $(D DateTimeException) if the given string is not in the correct
  15398. format or if the resulting $(D DateTime) would not be valid.
  15399. Examples:
  15400. --------------------
  15401. assert(DateTime.fromSimpleString("2010-Jul-04 07:06:12") ==
  15402. DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
  15403. assert(DateTime.fromSimpleString("1998-Dec-25 02:15:00") ==
  15404. DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)));
  15405. assert(DateTime.fromSimpleString("0000-Jan-05 23:09:59") ==
  15406. DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)));
  15407. assert(DateTime.fromSimpleString("-0004-Jan-05 00:00:02") ==
  15408. DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)));
  15409. assert(DateTime.fromSimpleString(" 2010-Jul-04 07:06:12 ") ==
  15410. DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
  15411. --------------------
  15412. +/
  15413. static DateTime fromSimpleString(S)(in S simpleString)
  15414. if(isSomeString!(S))
  15415. {
  15416. immutable dstr = to!dstring(strip(simpleString));
  15417. enforce(dstr.length >= 15, new DateTimeException(format("Invalid string format: %s", simpleString)));
  15418. auto t = dstr.stds_indexOf(' ');
  15419. enforce(t != -1, new DateTimeException(format("Invalid string format: %s", simpleString)));
  15420. immutable date = Date.fromSimpleString(dstr[0..t]);
  15421. immutable tod = TimeOfDay.fromISOExtString(dstr[t+1 .. $]);
  15422. return DateTime(date, tod);
  15423. }
  15424. unittest
  15425. {
  15426. version(testStdDateTime)
  15427. {
  15428. assertThrown!DateTimeException(DateTime.fromISOString(""));
  15429. assertThrown!DateTimeException(DateTime.fromISOString("20100704000000"));
  15430. assertThrown!DateTimeException(DateTime.fromISOString("20100704 000000"));
  15431. assertThrown!DateTimeException(DateTime.fromISOString("20100704t000000"));
  15432. assertThrown!DateTimeException(DateTime.fromISOString("20100704T000000."));
  15433. assertThrown!DateTimeException(DateTime.fromISOString("20100704T000000.0"));
  15434. assertThrown!DateTimeException(DateTime.fromISOString("2010-07-0400:00:00"));
  15435. assertThrown!DateTimeException(DateTime.fromISOString("2010-07-04 00:00:00"));
  15436. assertThrown!DateTimeException(DateTime.fromISOString("2010-07-04t00:00:00"));
  15437. assertThrown!DateTimeException(DateTime.fromISOString("2010-07-04T00:00:00."));
  15438. assertThrown!DateTimeException(DateTime.fromISOString("2010-07-04T00:00:00.0"));
  15439. assertThrown!DateTimeException(DateTime.fromISOString("2010-Jul-0400:00:00"));
  15440. assertThrown!DateTimeException(DateTime.fromISOString("2010-Jul-04 00:00:00"));
  15441. assertThrown!DateTimeException(DateTime.fromISOString("2010-Jul-04t00:00:00"));
  15442. assertThrown!DateTimeException(DateTime.fromISOString("2010-Jul-04T00:00:00"));
  15443. assertThrown!DateTimeException(DateTime.fromISOString("2010-Jul-04 00:00:00."));
  15444. assertThrown!DateTimeException(DateTime.fromISOString("2010-Jul-04 00:00:00.0"));
  15445. assertThrown!DateTimeException(DateTime.fromSimpleString("20101222T172201"));
  15446. assertThrown!DateTimeException(DateTime.fromSimpleString("2010-12-22T172201"));
  15447. _assertPred!"=="(DateTime.fromSimpleString("2010-Dec-22 17:22:01"), DateTime(Date(2010, 12, 22), TimeOfDay(17, 22, 01)));
  15448. _assertPred!"=="(DateTime.fromSimpleString("1999-Jul-06 12:30:33"), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  15449. _assertPred!"=="(DateTime.fromSimpleString("-1999-Jul-06 12:30:33"), DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
  15450. _assertPred!"=="(DateTime.fromSimpleString("+01999-Jul-06 12:30:33"), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  15451. _assertPred!"=="(DateTime.fromSimpleString("1999-Jul-06 12:30:33 "), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  15452. _assertPred!"=="(DateTime.fromSimpleString(" 1999-Jul-06 12:30:33"), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  15453. _assertPred!"=="(DateTime.fromSimpleString(" 1999-Jul-06 12:30:33 "), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
  15454. //Verify Examples.
  15455. assert(DateTime.fromSimpleString("2010-Jul-04 07:06:12") == DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
  15456. assert(DateTime.fromSimpleString("1998-Dec-25 02:15:00") == DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)));
  15457. assert(DateTime.fromSimpleString("0000-Jan-05 23:09:59") == DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)));
  15458. assert(DateTime.fromSimpleString("-0004-Jan-05 00:00:02") == DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)));
  15459. assert(DateTime.fromSimpleString(" 2010-Jul-04 07:06:12 ") == DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
  15460. }
  15461. }
  15462. //TODO Add function which takes a user-specified time format and produces a DateTime
  15463. //TODO Add function which takes pretty much any time-string and produces a DateTime
  15464. // Obviously, it will be less efficient, and it probably won't manage _every_
  15465. // possible date format, but a smart conversion function would be nice.
  15466. /++
  15467. Returns the $(D DateTime) farthest in the past which is representable by
  15468. $(D DateTime).
  15469. +/
  15470. @property static DateTime min() pure nothrow
  15471. out(result)
  15472. {
  15473. assert(result._date == Date.min);
  15474. assert(result._tod == TimeOfDay.min);
  15475. }
  15476. body
  15477. {
  15478. auto dt = DateTime.init;
  15479. dt._date._year = short.min;
  15480. dt._date._month = Month.jan;
  15481. dt._date._day = 1;
  15482. return dt;
  15483. }
  15484. unittest
  15485. {
  15486. version(testStdDateTime)
  15487. {
  15488. assert(DateTime.min.year < 0);
  15489. assert(DateTime.min < DateTime.max);
  15490. }
  15491. }
  15492. /++
  15493. Returns the $(D DateTime) farthest in the future which is representable
  15494. by $(D DateTime).
  15495. +/
  15496. @property static DateTime max() pure nothrow
  15497. out(result)
  15498. {
  15499. assert(result._date == Date.max);
  15500. assert(result._tod == TimeOfDay.max);
  15501. }
  15502. body
  15503. {
  15504. auto dt = DateTime.init;
  15505. dt._date._year = short.max;
  15506. dt._date._month = Month.dec;
  15507. dt._date._day = 31;
  15508. dt._tod._hour = TimeOfDay.maxHour;
  15509. dt._tod._minute = TimeOfDay.maxMinute;
  15510. dt._tod._second = TimeOfDay.maxSecond;
  15511. return dt;
  15512. }
  15513. unittest
  15514. {
  15515. version(testStdDateTime)
  15516. {
  15517. assert(DateTime.max.year > 0);
  15518. assert(DateTime.max > DateTime.min);
  15519. }
  15520. }
  15521. private:
  15522. /+
  15523. Add seconds to the time of day. Negative values will subtract. If the
  15524. number of seconds overflows (or underflows), then the seconds will wrap,
  15525. increasing (or decreasing) the number of minutes accordingly. The
  15526. same goes for any larger units.
  15527. Params:
  15528. seconds = The number of seconds to add to this $(D DateTime).
  15529. +/
  15530. ref DateTime addSeconds(long seconds) pure nothrow
  15531. {
  15532. long hnsecs = convert!("seconds", "hnsecs")(seconds);
  15533. hnsecs += convert!("hours", "hnsecs")(_tod._hour);
  15534. hnsecs += convert!("minutes", "hnsecs")(_tod._minute);
  15535. hnsecs += convert!("seconds", "hnsecs")(_tod._second);
  15536. auto days = splitUnitsFromHNSecs!"days"(hnsecs);
  15537. if(hnsecs < 0)
  15538. {
  15539. hnsecs += convert!("days", "hnsecs")(1);
  15540. --days;
  15541. }
  15542. _date.addDays(days);
  15543. immutable newHours = splitUnitsFromHNSecs!"hours"(hnsecs);
  15544. immutable newMinutes = splitUnitsFromHNSecs!"minutes"(hnsecs);
  15545. immutable newSeconds = splitUnitsFromHNSecs!"seconds"(hnsecs);
  15546. _tod._hour = cast(ubyte)newHours;
  15547. _tod._minute = cast(ubyte)newMinutes;
  15548. _tod._second = cast(ubyte)newSeconds;
  15549. return this;
  15550. }
  15551. unittest
  15552. {
  15553. version(testStdDateTime)
  15554. {
  15555. static void testDT(DateTime orig, int seconds, in DateTime expected, size_t line = __LINE__)
  15556. {
  15557. orig.addSeconds(seconds);
  15558. _assertPred!"=="(orig, expected, "", __FILE__, line);
  15559. }
  15560. //Test A.D.
  15561. testDT(DateTime(1999, 7, 6, 12, 30, 33), 0, DateTime(1999, 7, 6, 12, 30, 33));
  15562. testDT(DateTime(1999, 7, 6, 12, 30, 33), 1, DateTime(1999, 7, 6, 12, 30, 34));
  15563. testDT(DateTime(1999, 7, 6, 12, 30, 33), 2, DateTime(1999, 7, 6, 12, 30, 35));
  15564. testDT(DateTime(1999, 7, 6, 12, 30, 33), 3, DateTime(1999, 7, 6, 12, 30, 36));
  15565. testDT(DateTime(1999, 7, 6, 12, 30, 33), 4, DateTime(1999, 7, 6, 12, 30, 37));
  15566. testDT(DateTime(1999, 7, 6, 12, 30, 33), 5, DateTime(1999, 7, 6, 12, 30, 38));
  15567. testDT(DateTime(1999, 7, 6, 12, 30, 33), 10, DateTime(1999, 7, 6, 12, 30, 43));
  15568. testDT(DateTime(1999, 7, 6, 12, 30, 33), 15, DateTime(1999, 7, 6, 12, 30, 48));
  15569. testDT(DateTime(1999, 7, 6, 12, 30, 33), 26, DateTime(1999, 7, 6, 12, 30, 59));
  15570. testDT(DateTime(1999, 7, 6, 12, 30, 33), 27, DateTime(1999, 7, 6, 12, 31, 0));
  15571. testDT(DateTime(1999, 7, 6, 12, 30, 33), 30, DateTime(1999, 7, 6, 12, 31, 3));
  15572. testDT(DateTime(1999, 7, 6, 12, 30, 33), 59, DateTime(1999, 7, 6, 12, 31, 32));
  15573. testDT(DateTime(1999, 7, 6, 12, 30, 33), 60, DateTime(1999, 7, 6, 12, 31, 33));
  15574. testDT(DateTime(1999, 7, 6, 12, 30, 33), 61, DateTime(1999, 7, 6, 12, 31, 34));
  15575. testDT(DateTime(1999, 7, 6, 12, 30, 33), 1766, DateTime(1999, 7, 6, 12, 59, 59));
  15576. testDT(DateTime(1999, 7, 6, 12, 30, 33), 1767, DateTime(1999, 7, 6, 13, 0, 0));
  15577. testDT(DateTime(1999, 7, 6, 12, 30, 33), 1768, DateTime(1999, 7, 6, 13, 0, 1));
  15578. testDT(DateTime(1999, 7, 6, 12, 30, 33), 2007, DateTime(1999, 7, 6, 13, 4, 0));
  15579. testDT(DateTime(1999, 7, 6, 12, 30, 33), 3599, DateTime(1999, 7, 6, 13, 30, 32));
  15580. testDT(DateTime(1999, 7, 6, 12, 30, 33), 3600, DateTime(1999, 7, 6, 13, 30, 33));
  15581. testDT(DateTime(1999, 7, 6, 12, 30, 33), 3601, DateTime(1999, 7, 6, 13, 30, 34));
  15582. testDT(DateTime(1999, 7, 6, 12, 30, 33), 7200, DateTime(1999, 7, 6, 14, 30, 33));
  15583. testDT(DateTime(1999, 7, 6, 23, 0, 0), 432_123, DateTime(1999, 7, 11, 23, 2, 3));
  15584. testDT(DateTime(1999, 7, 6, 12, 30, 33), -1, DateTime(1999, 7, 6, 12, 30, 32));
  15585. testDT(DateTime(1999, 7, 6, 12, 30, 33), -2, DateTime(1999, 7, 6, 12, 30, 31));
  15586. testDT(DateTime(1999, 7, 6, 12, 30, 33), -3, DateTime(1999, 7, 6, 12, 30, 30));
  15587. testDT(DateTime(1999, 7, 6, 12, 30, 33), -4, DateTime(1999, 7, 6, 12, 30, 29));
  15588. testDT(DateTime(1999, 7, 6, 12, 30, 33), -5, DateTime(1999, 7, 6, 12, 30, 28));
  15589. testDT(DateTime(1999, 7, 6, 12, 30, 33), -10, DateTime(1999, 7, 6, 12, 30, 23));
  15590. testDT(DateTime(1999, 7, 6, 12, 30, 33), -15, DateTime(1999, 7, 6, 12, 30, 18));
  15591. testDT(DateTime(1999, 7, 6, 12, 30, 33), -33, DateTime(1999, 7, 6, 12, 30, 0));
  15592. testDT(DateTime(1999, 7, 6, 12, 30, 33), -34, DateTime(1999, 7, 6, 12, 29, 59));
  15593. testDT(DateTime(1999, 7, 6, 12, 30, 33), -35, DateTime(1999, 7, 6, 12, 29, 58));
  15594. testDT(DateTime(1999, 7, 6, 12, 30, 33), -59, DateTime(1999, 7, 6, 12, 29, 34));
  15595. testDT(DateTime(1999, 7, 6, 12, 30, 33), -60, DateTime(1999, 7, 6, 12, 29, 33));
  15596. testDT(DateTime(1999, 7, 6, 12, 30, 33), -61, DateTime(1999, 7, 6, 12, 29, 32));
  15597. testDT(DateTime(1999, 7, 6, 12, 30, 33), -1833, DateTime(1999, 7, 6, 12, 0, 0));
  15598. testDT(DateTime(1999, 7, 6, 12, 30, 33), -1834, DateTime(1999, 7, 6, 11, 59, 59));
  15599. testDT(DateTime(1999, 7, 6, 12, 30, 33), -3600, DateTime(1999, 7, 6, 11, 30, 33));
  15600. testDT(DateTime(1999, 7, 6, 12, 30, 33), -3601, DateTime(1999, 7, 6, 11, 30, 32));
  15601. testDT(DateTime(1999, 7, 6, 12, 30, 33), -5134, DateTime(1999, 7, 6, 11, 4, 59));
  15602. testDT(DateTime(1999, 7, 6, 23, 0, 0), -432_123, DateTime(1999, 7, 1, 22, 57, 57));
  15603. testDT(DateTime(1999, 7, 6, 12, 30, 0), 1, DateTime(1999, 7, 6, 12, 30, 1));
  15604. testDT(DateTime(1999, 7, 6, 12, 30, 0), 0, DateTime(1999, 7, 6, 12, 30, 0));
  15605. testDT(DateTime(1999, 7, 6, 12, 30, 0), -1, DateTime(1999, 7, 6, 12, 29, 59));
  15606. testDT(DateTime(1999, 7, 6, 12, 0, 0), 1, DateTime(1999, 7, 6, 12, 0, 1));
  15607. testDT(DateTime(1999, 7, 6, 12, 0, 0), 0, DateTime(1999, 7, 6, 12, 0, 0));
  15608. testDT(DateTime(1999, 7, 6, 12, 0, 0), -1, DateTime(1999, 7, 6, 11, 59, 59));
  15609. testDT(DateTime(1999, 7, 6, 0, 0, 0), 1, DateTime(1999, 7, 6, 0, 0, 1));
  15610. testDT(DateTime(1999, 7, 6, 0, 0, 0), 0, DateTime(1999, 7, 6, 0, 0, 0));
  15611. testDT(DateTime(1999, 7, 6, 0, 0, 0), -1, DateTime(1999, 7, 5, 23, 59, 59));
  15612. testDT(DateTime(1999, 7, 5, 23, 59, 59), 1, DateTime(1999, 7, 6, 0, 0, 0));
  15613. testDT(DateTime(1999, 7, 5, 23, 59, 59), 0, DateTime(1999, 7, 5, 23, 59, 59));
  15614. testDT(DateTime(1999, 7, 5, 23, 59, 59), -1, DateTime(1999, 7, 5, 23, 59, 58));
  15615. testDT(DateTime(1998, 12, 31, 23, 59, 59), 1, DateTime(1999, 1, 1, 0, 0, 0));
  15616. testDT(DateTime(1998, 12, 31, 23, 59, 59), 0, DateTime(1998, 12, 31, 23, 59, 59));
  15617. testDT(DateTime(1998, 12, 31, 23, 59, 59), -1, DateTime(1998, 12, 31, 23, 59, 58));
  15618. testDT(DateTime(1998, 1, 1, 0, 0, 0), 1, DateTime(1998, 1, 1, 0, 0, 1));
  15619. testDT(DateTime(1998, 1, 1, 0, 0, 0), 0, DateTime(1998, 1, 1, 0, 0, 0));
  15620. testDT(DateTime(1998, 1, 1, 0, 0, 0), -1, DateTime(1997, 12, 31, 23, 59, 59));
  15621. //Test B.C.
  15622. testDT(DateTime(-1999, 7, 6, 12, 30, 33), 0, DateTime(-1999, 7, 6, 12, 30, 33));
  15623. testDT(DateTime(-1999, 7, 6, 12, 30, 33), 1, DateTime(-1999, 7, 6, 12, 30, 34));
  15624. testDT(DateTime(-1999, 7, 6, 12, 30, 33), 2, DateTime(-1999, 7, 6, 12, 30, 35));
  15625. testDT(DateTime(-1999, 7, 6, 12, 30, 33), 3, DateTime(-1999, 7, 6, 12, 30, 36));
  15626. testDT(DateTime(-1999, 7, 6, 12, 30, 33), 4, DateTime(-1999, 7, 6, 12, 30, 37));
  15627. testDT(DateTime(-1999, 7, 6, 12, 30, 33), 5, DateTime(-1999, 7, 6, 12, 30, 38));
  15628. testDT(DateTime(-1999, 7, 6, 12, 30, 33), 10, DateTime(-1999, 7, 6, 12, 30, 43));
  15629. testDT(DateTime(-1999, 7, 6, 12, 30, 33), 15, DateTime(-1999, 7, 6, 12, 30, 48));
  15630. testDT(DateTime(-1999, 7, 6, 12, 30, 33), 26, DateTime(-1999, 7, 6, 12, 30, 59));
  15631. testDT(DateTime(-1999, 7, 6, 12, 30, 33), 27, DateTime(-1999, 7, 6, 12, 31, 0));
  15632. testDT(DateTime(-1999, 7, 6, 12, 30, 33), 30, DateTime(-1999, 7, 6, 12, 31, 3));
  15633. testDT(DateTime(-1999, 7, 6, 12, 30, 33), 59, DateTime(-1999, 7, 6, 12, 31, 32));
  15634. testDT(DateTime(-1999, 7, 6, 12, 30, 33), 60, DateTime(-1999, 7, 6, 12, 31, 33));
  15635. testDT(DateTime(-1999, 7, 6, 12, 30, 33), 61, DateTime(-1999, 7, 6, 12, 31, 34));
  15636. testDT(DateTime(-1999, 7, 6, 12, 30, 33), 1766, DateTime(-1999, 7, 6, 12, 59, 59));
  15637. testDT(DateTime(-1999, 7, 6, 12, 30, 33), 1767, DateTime(-1999, 7, 6, 13, 0, 0));
  15638. testDT(DateTime(-1999, 7, 6, 12, 30, 33), 1768, DateTime(-1999, 7, 6, 13, 0, 1));
  15639. testDT(DateTime(-1999, 7, 6, 12, 30, 33), 2007, DateTime(-1999, 7, 6, 13, 4, 0));
  15640. testDT(DateTime(-1999, 7, 6, 12, 30, 33), 3599, DateTime(-1999, 7, 6, 13, 30, 32));
  15641. testDT(DateTime(-1999, 7, 6, 12, 30, 33), 3600, DateTime(-1999, 7, 6, 13, 30, 33));
  15642. testDT(DateTime(-1999, 7, 6, 12, 30, 33), 3601, DateTime(-1999, 7, 6, 13, 30, 34));
  15643. testDT(DateTime(-1999, 7, 6, 12, 30, 33), 7200, DateTime(-1999, 7, 6, 14, 30, 33));
  15644. testDT(DateTime(-1999, 7, 6, 23, 0, 0), 432_123, DateTime(-1999, 7, 11, 23, 2, 3));
  15645. testDT(DateTime(-1999, 7, 6, 12, 30, 33), -1, DateTime(-1999, 7, 6, 12, 30, 32));
  15646. testDT(DateTime(-1999, 7, 6, 12, 30, 33), -2, DateTime(-1999, 7, 6, 12, 30, 31));
  15647. testDT(DateTime(-1999, 7, 6, 12, 30, 33), -3, DateTime(-1999, 7, 6, 12, 30, 30));
  15648. testDT(DateTime(-1999, 7, 6, 12, 30, 33), -4, DateTime(-1999, 7, 6, 12, 30, 29));
  15649. testDT(DateTime(-1999, 7, 6, 12, 30, 33), -5, DateTime(-1999, 7, 6, 12, 30, 28));
  15650. testDT(DateTime(-1999, 7, 6, 12, 30, 33), -10, DateTime(-1999, 7, 6, 12, 30, 23));
  15651. testDT(DateTime(-1999, 7, 6, 12, 30, 33), -15, DateTime(-1999, 7, 6, 12, 30, 18));
  15652. testDT(DateTime(-1999, 7, 6, 12, 30, 33), -33, DateTime(-1999, 7, 6, 12, 30, 0));
  15653. testDT(DateTime(-1999, 7, 6, 12, 30, 33), -34, DateTime(-1999, 7, 6, 12, 29, 59));
  15654. testDT(DateTime(-1999, 7, 6, 12, 30, 33), -35, DateTime(-1999, 7, 6, 12, 29, 58));
  15655. testDT(DateTime(-1999, 7, 6, 12, 30, 33), -59, DateTime(-1999, 7, 6, 12, 29, 34));
  15656. testDT(DateTime(-1999, 7, 6, 12, 30, 33), -60, DateTime(-1999, 7, 6, 12, 29, 33));
  15657. testDT(DateTime(-1999, 7, 6, 12, 30, 33), -61, DateTime(-1999, 7, 6, 12, 29, 32));
  15658. testDT(DateTime(-1999, 7, 6, 12, 30, 33), -1833, DateTime(-1999, 7, 6, 12, 0, 0));
  15659. testDT(DateTime(-1999, 7, 6, 12, 30, 33), -1834, DateTime(-1999, 7, 6, 11, 59, 59));
  15660. testDT(DateTime(-1999, 7, 6, 12, 30, 33), -3600, DateTime(-1999, 7, 6, 11, 30, 33));
  15661. testDT(DateTime(-1999, 7, 6, 12, 30, 33), -3601, DateTime(-1999, 7, 6, 11, 30, 32));
  15662. testDT(DateTime(-1999, 7, 6, 12, 30, 33), -5134, DateTime(-1999, 7, 6, 11, 4, 59));
  15663. testDT(DateTime(-1999, 7, 6, 12, 30, 33), -7200, DateTime(-1999, 7, 6, 10, 30, 33));
  15664. testDT(DateTime(-1999, 7, 6, 23, 0, 0), -432_123, DateTime(-1999, 7, 1, 22, 57, 57));
  15665. testDT(DateTime(-1999, 7, 6, 12, 30, 0), 1, DateTime(-1999, 7, 6, 12, 30, 1));
  15666. testDT(DateTime(-1999, 7, 6, 12, 30, 0), 0, DateTime(-1999, 7, 6, 12, 30, 0));
  15667. testDT(DateTime(-1999, 7, 6, 12, 30, 0), -1, DateTime(-1999, 7, 6, 12, 29, 59));
  15668. testDT(DateTime(-1999, 7, 6, 12, 0, 0), 1, DateTime(-1999, 7, 6, 12, 0, 1));
  15669. testDT(DateTime(-1999, 7, 6, 12, 0, 0), 0, DateTime(-1999, 7, 6, 12, 0, 0));
  15670. testDT(DateTime(-1999, 7, 6, 12, 0, 0), -1, DateTime(-1999, 7, 6, 11, 59, 59));
  15671. testDT(DateTime(-1999, 7, 6, 0, 0, 0), 1, DateTime(-1999, 7, 6, 0, 0, 1));
  15672. testDT(DateTime(-1999, 7, 6, 0, 0, 0), 0, DateTime(-1999, 7, 6, 0, 0, 0));
  15673. testDT(DateTime(-1999, 7, 6, 0, 0, 0), -1, DateTime(-1999, 7, 5, 23, 59, 59));
  15674. testDT(DateTime(-1999, 7, 5, 23, 59, 59), 1, DateTime(-1999, 7, 6, 0, 0, 0));
  15675. testDT(DateTime(-1999, 7, 5, 23, 59, 59), 0, DateTime(-1999, 7, 5, 23, 59, 59));
  15676. testDT(DateTime(-1999, 7, 5, 23, 59, 59), -1, DateTime(-1999, 7, 5, 23, 59, 58));
  15677. testDT(DateTime(-2000, 12, 31, 23, 59, 59), 1, DateTime(-1999, 1, 1, 0, 0, 0));
  15678. testDT(DateTime(-2000, 12, 31, 23, 59, 59), 0, DateTime(-2000, 12, 31, 23, 59, 59));
  15679. testDT(DateTime(-2000, 12, 31, 23, 59, 59), -1, DateTime(-2000, 12, 31, 23, 59, 58));
  15680. testDT(DateTime(-2000, 1, 1, 0, 0, 0), 1, DateTime(-2000, 1, 1, 0, 0, 1));
  15681. testDT(DateTime(-2000, 1, 1, 0, 0, 0), 0, DateTime(-2000, 1, 1, 0, 0, 0));
  15682. testDT(DateTime(-2000, 1, 1, 0, 0, 0), -1, DateTime(-2001, 12, 31, 23, 59, 59));
  15683. //Test Both
  15684. testDT(DateTime(1, 1, 1, 0, 0, 0), -1, DateTime(0, 12, 31, 23, 59, 59));
  15685. testDT(DateTime(0, 12, 31, 23, 59, 59), 1, DateTime(1, 1, 1, 0, 0, 0));
  15686. testDT(DateTime(0, 1, 1, 0, 0, 0), -1, DateTime(-1, 12, 31, 23, 59, 59));
  15687. testDT(DateTime(-1, 12, 31, 23, 59, 59), 1, DateTime(0, 1, 1, 0, 0, 0));
  15688. testDT(DateTime(-1, 1, 1, 11, 30, 33), 63_165_600L, DateTime(1, 1, 1, 13, 30, 33));
  15689. testDT(DateTime(1, 1, 1, 13, 30, 33), -63_165_600L, DateTime(-1, 1, 1, 11, 30, 33));
  15690. testDT(DateTime(-1, 1, 1, 11, 30, 33), 63_165_617L, DateTime(1, 1, 1, 13, 30, 50));
  15691. testDT(DateTime(1, 1, 1, 13, 30, 50), -63_165_617L, DateTime(-1, 1, 1, 11, 30, 33));
  15692. const cdt = DateTime(1999, 7, 6, 12, 30, 33);
  15693. immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
  15694. static assert(!__traits(compiles, cdt.addSeconds(4)));
  15695. static assert(!__traits(compiles, idt.addSeconds(4)));
  15696. }
  15697. }
  15698. Date _date;
  15699. TimeOfDay _tod;
  15700. }
  15701. //==============================================================================
  15702. // Section with intervals.
  15703. //==============================================================================
  15704. /++
  15705. Represents an interval of time.
  15706. An $(D Interval) has a starting point and an end point. The interval of time
  15707. is therefore the time starting at the starting point up to, but not
  15708. including, the end point. e.g.
  15709. $(BOOKTABLE,
  15710. $(TR $(TD [January 5th, 2010 - March 10th, 2010$(RPAREN)))
  15711. $(TR $(TD [05:00:30 - 12:00:00$(RPAREN)))
  15712. $(TR $(TD [1982-01-04T08:59:00 - 2010-07-04T12:00:00$(RPAREN)))
  15713. )
  15714. A range can be obtained from an $(D Interval), allowing you to iterate over
  15715. that interval, with the exact time points which are iterated over depending
  15716. on the function which generates the range.
  15717. +/
  15718. struct Interval(TP)
  15719. {
  15720. public:
  15721. /++
  15722. Params:
  15723. begin = The time point which begins the interval.
  15724. end = The time point which ends (but is not included in) the
  15725. interval.
  15726. Throws:
  15727. $(D DateTimeException) if $(D_PARAM end) is before $(D_PARAM begin).
  15728. Examples:
  15729. --------------------
  15730. Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
  15731. --------------------
  15732. +/
  15733. this(U)(in TP begin, in U end) pure
  15734. if(is(Unqual!TP == Unqual!U))
  15735. {
  15736. if(!_valid(begin, end))
  15737. throw new DateTimeException("Arguments would result in an invalid Interval.");
  15738. _begin = cast(TP)begin;
  15739. _end = cast(TP)end;
  15740. }
  15741. /++
  15742. Params:
  15743. begin = The time point which begins the interval.
  15744. duration = The duration from the starting point to the end point.
  15745. Throws:
  15746. $(D DateTimeException) if the resulting $(D end) is before
  15747. $(D begin).
  15748. Examples:
  15749. --------------------
  15750. assert(Interval!Date(Date(1996, 1, 2), Dur.years(3)) ==
  15751. Interval!Date(Date(1996, 1, 2), Date(1999, 1, 2)));
  15752. --------------------
  15753. +/
  15754. this(D)(in TP begin, in D duration) pure
  15755. if(__traits(compiles, begin + duration))
  15756. {
  15757. _begin = cast(TP)begin;
  15758. _end = begin + duration;
  15759. if(!_valid(_begin, _end))
  15760. throw new DateTimeException("Arguments would result in an invalid Interval.");
  15761. }
  15762. /++
  15763. Params:
  15764. rhs = The $(D Interval) to assign to this one.
  15765. +/
  15766. /+ref+/ Interval opAssign(const ref Interval rhs) pure nothrow
  15767. {
  15768. _begin = cast(TP)rhs._begin;
  15769. _end = cast(TP)rhs._end;
  15770. return this;
  15771. }
  15772. /++
  15773. Params:
  15774. rhs = The $(D Interval) to assign to this one.
  15775. +/
  15776. /+ref+/ Interval opAssign(Interval rhs) pure nothrow
  15777. {
  15778. _begin = cast(TP)rhs._begin;
  15779. _end = cast(TP)rhs._end;
  15780. return this;
  15781. }
  15782. /++
  15783. The starting point of the interval. It is included in the interval.
  15784. Examples:
  15785. --------------------
  15786. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).begin ==
  15787. Date(1996, 1, 2));
  15788. --------------------
  15789. +/
  15790. @property TP begin() const pure nothrow
  15791. {
  15792. return cast(TP)_begin;
  15793. }
  15794. /++
  15795. The starting point of the interval. It is included in the interval.
  15796. Params:
  15797. timePoint = The time point to set $(D begin) to.
  15798. Throws:
  15799. $(D DateTimeException) if the resulting interval would be invalid.
  15800. +/
  15801. @property void begin(TP timePoint) pure
  15802. {
  15803. if(!_valid(timePoint, _end))
  15804. throw new DateTimeException("Arguments would result in an invalid Interval.");
  15805. _begin = timePoint;
  15806. }
  15807. /++
  15808. The end point of the interval. It is excluded from the interval.
  15809. Examples:
  15810. --------------------
  15811. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).end ==
  15812. Date(2012, 3, 1));
  15813. --------------------
  15814. +/
  15815. @property TP end() const pure nothrow
  15816. {
  15817. return cast(TP)_end;
  15818. }
  15819. /++
  15820. The end point of the interval. It is excluded from the interval.
  15821. Params:
  15822. timePoint = The time point to set end to.
  15823. Throws:
  15824. $(D DateTimeException) if the resulting interval would be invalid.
  15825. +/
  15826. @property void end(TP timePoint) pure
  15827. {
  15828. if(!_valid(_begin, timePoint))
  15829. throw new DateTimeException("Arguments would result in an invalid Interval.");
  15830. _end = timePoint;
  15831. }
  15832. /++
  15833. Returns the duration between $(D begin) and $(D end).
  15834. Examples:
  15835. --------------------
  15836. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).length ==
  15837. dur!"days"(5903));
  15838. --------------------
  15839. +/
  15840. @property typeof(end - begin) length() const pure nothrow
  15841. {
  15842. return _end - _begin;
  15843. }
  15844. /++
  15845. Whether the interval's length is 0, that is, whether $(D begin == end).
  15846. Examples:
  15847. --------------------
  15848. assert(Interval!Date(Date(1996, 1, 2), Date(1996, 1, 2)).empty);
  15849. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).empty);
  15850. --------------------
  15851. +/
  15852. @property bool empty() const pure nothrow
  15853. {
  15854. return _begin == _end;
  15855. }
  15856. /++
  15857. Whether the given time point is within this interval.
  15858. Params:
  15859. timePoint = The time point to check for inclusion in this interval.
  15860. Throws:
  15861. $(D DateTimeException) if this interval is empty.
  15862. Examples:
  15863. --------------------
  15864. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
  15865. Date(1994, 12, 24)));
  15866. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
  15867. Date(2000, 1, 5)));
  15868. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
  15869. Date(2012, 3, 1)));
  15870. --------------------
  15871. +/
  15872. bool contains(in TP timePoint) const pure
  15873. {
  15874. _enforceNotEmpty();
  15875. return timePoint >= _begin && timePoint < _end;
  15876. }
  15877. /++
  15878. Whether the given interval is completely within this interval.
  15879. Params:
  15880. interval = The interval to check for inclusion in this interval.
  15881. Throws:
  15882. $(D DateTimeException) if either interval is empty.
  15883. Examples:
  15884. --------------------
  15885. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
  15886. Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  15887. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
  15888. Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  15889. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
  15890. Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
  15891. --------------------
  15892. +/
  15893. bool contains(in Interval interval) const pure
  15894. {
  15895. _enforceNotEmpty();
  15896. interval._enforceNotEmpty();
  15897. return interval._begin >= _begin &&
  15898. interval._begin < _end &&
  15899. interval._end <= _end;
  15900. }
  15901. /++
  15902. Whether the given interval is completely within this interval.
  15903. Always returns false (unless this interval is empty), because an
  15904. interval going to positive infinity can never be contained in a finite
  15905. interval.
  15906. Params:
  15907. interval = The interval to check for inclusion in this interval.
  15908. Throws:
  15909. $(D DateTimeException) if this interval is empty.
  15910. Examples:
  15911. --------------------
  15912. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
  15913. PosInfInterval!Date(Date(1999, 5, 4))));
  15914. --------------------
  15915. +/
  15916. bool contains(in PosInfInterval!TP interval) const pure
  15917. {
  15918. _enforceNotEmpty();
  15919. return false;
  15920. }
  15921. /++
  15922. Whether the given interval is completely within this interval.
  15923. Always returns false (unless this interval is empty), because an
  15924. interval beginning at negative infinity can never be contained in a
  15925. finite interval.
  15926. Params:
  15927. interval = The interval to check for inclusion in this interval.
  15928. Throws:
  15929. $(D DateTimeException) if this interval is empty.
  15930. Examples:
  15931. --------------------
  15932. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(
  15933. NegInfInterval!Date(Date(1996, 5, 4))));
  15934. --------------------
  15935. +/
  15936. bool contains(in NegInfInterval!TP interval) const pure
  15937. {
  15938. _enforceNotEmpty();
  15939. return false;
  15940. }
  15941. /++
  15942. Whether this interval is before the given time point.
  15943. Params:
  15944. timePoint = The time point to check whether this interval is before
  15945. it.
  15946. Throws:
  15947. $(D DateTimeException) if this interval is empty.
  15948. Examples:
  15949. --------------------
  15950. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
  15951. Date(1994, 12, 24)));
  15952. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
  15953. Date(2000, 1, 5)));
  15954. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
  15955. Date(2012, 3, 1)));
  15956. --------------------
  15957. +/
  15958. bool isBefore(in TP timePoint) const pure
  15959. {
  15960. _enforceNotEmpty();
  15961. return _end <= timePoint;
  15962. }
  15963. /++
  15964. Whether this interval is before the given interval and does not
  15965. intersect with it.
  15966. Params:
  15967. interval = The interval to check for against this interval.
  15968. Throws:
  15969. $(D DateTimeException) if either interval is empty.
  15970. Examples:
  15971. --------------------
  15972. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
  15973. Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  15974. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
  15975. Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  15976. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
  15977. Interval!Date(Date(2012, 3, 1), Date(2013, 5, 1))));
  15978. --------------------
  15979. +/
  15980. bool isBefore(in Interval interval) const pure
  15981. {
  15982. _enforceNotEmpty();
  15983. interval._enforceNotEmpty();
  15984. return _end <= interval._begin;
  15985. }
  15986. /++
  15987. Whether this interval is before the given interval and does not
  15988. intersect with it.
  15989. Params:
  15990. interval = The interval to check for against this interval.
  15991. Throws:
  15992. $(D DateTimeException) if this interval is empty.
  15993. Examples:
  15994. --------------------
  15995. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
  15996. PosInfInterval!Date(Date(1999, 5, 4))));
  15997. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
  15998. PosInfInterval!Date(Date(2013, 3, 7))));
  15999. --------------------
  16000. +/
  16001. bool isBefore(in PosInfInterval!TP interval) const pure
  16002. {
  16003. _enforceNotEmpty();
  16004. return _end <= interval._begin;
  16005. }
  16006. /++
  16007. Whether this interval is before the given interval and does not
  16008. intersect with it.
  16009. Always returns false (unless this interval is empty) because a finite
  16010. interval can never be before an interval beginning at negative infinity.
  16011. Params:
  16012. interval = The interval to check for against this interval.
  16013. Throws:
  16014. $(D DateTimeException) if this interval is empty.
  16015. Examples:
  16016. --------------------
  16017. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(
  16018. NegInfInterval!Date(Date(1996, 5, 4))));
  16019. --------------------
  16020. +/
  16021. bool isBefore(in NegInfInterval!TP interval) const pure
  16022. {
  16023. _enforceNotEmpty();
  16024. return false;
  16025. }
  16026. /++
  16027. Whether this interval is after the given time point.
  16028. Params:
  16029. timePoint = The time point to check whether this interval is after
  16030. it.
  16031. Throws:
  16032. $(D DateTimeException) if this interval is empty.
  16033. Examples:
  16034. --------------------
  16035. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
  16036. Date(1994, 12, 24)));
  16037. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
  16038. Date(2000, 1, 5)));
  16039. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
  16040. Date(2012, 3, 1)));
  16041. --------------------
  16042. +/
  16043. bool isAfter(in TP timePoint) const pure
  16044. {
  16045. _enforceNotEmpty();
  16046. return timePoint < _begin;
  16047. }
  16048. /++
  16049. Whether this interval is after the given interval and does not intersect
  16050. it.
  16051. Params:
  16052. interval = The interval to check against this interval.
  16053. Throws:
  16054. $(D DateTimeException) if either interval is empty.
  16055. Examples:
  16056. --------------------
  16057. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
  16058. Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  16059. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
  16060. Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  16061. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
  16062. Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
  16063. --------------------
  16064. +/
  16065. bool isAfter(in Interval interval) const pure
  16066. {
  16067. _enforceNotEmpty();
  16068. interval._enforceNotEmpty();
  16069. return _begin >= interval._end;
  16070. }
  16071. /++
  16072. Whether this interval is after the given interval and does not intersect
  16073. it.
  16074. Always returns false (unless this interval is empty) because a finite
  16075. interval can never be after an interval going to positive infinity.
  16076. Params:
  16077. interval = The interval to check against this interval.
  16078. Throws:
  16079. $(D DateTimeException) if this interval is empty.
  16080. Examples:
  16081. --------------------
  16082. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
  16083. PosInfInterval!Date(Date(1999, 5, 4))));
  16084. --------------------
  16085. +/
  16086. bool isAfter(in PosInfInterval!TP interval) const pure
  16087. {
  16088. _enforceNotEmpty();
  16089. return false;
  16090. }
  16091. /++
  16092. Whether this interval is after the given interval and does not intersect
  16093. it.
  16094. Params:
  16095. interval = The interval to check against this interval.
  16096. Throws:
  16097. $(D DateTimeException) if this interval is empty.
  16098. Examples:
  16099. --------------------
  16100. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(
  16101. NegInfInterval!Date(Date(1996, 1, 2))));
  16102. --------------------
  16103. +/
  16104. bool isAfter(in NegInfInterval!TP interval) const pure
  16105. {
  16106. _enforceNotEmpty();
  16107. return _begin >= interval._end;
  16108. }
  16109. /++
  16110. Whether the given interval overlaps this interval.
  16111. Params:
  16112. interval = The interval to check for intersection with this interval.
  16113. Throws:
  16114. $(D DateTimeException) if either interval is empty.
  16115. Examples:
  16116. --------------------
  16117. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
  16118. Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  16119. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
  16120. Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  16121. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
  16122. Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
  16123. --------------------
  16124. +/
  16125. bool intersects(in Interval interval) const pure
  16126. {
  16127. _enforceNotEmpty();
  16128. interval._enforceNotEmpty();
  16129. return interval._begin < _end && interval._end > _begin;
  16130. }
  16131. /++
  16132. Whether the given interval overlaps this interval.
  16133. Params:
  16134. interval = The interval to check for intersection with this interval.
  16135. Throws:
  16136. $(D DateTimeException) if this interval is empty.
  16137. Examples:
  16138. --------------------
  16139. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
  16140. PosInfInterval!Date(Date(1999, 5, 4))));
  16141. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
  16142. PosInfInterval!Date(Date(2012, 3, 1))));
  16143. --------------------
  16144. +/
  16145. bool intersects(in PosInfInterval!TP interval) const pure
  16146. {
  16147. _enforceNotEmpty();
  16148. return _end > interval._begin;
  16149. }
  16150. /++
  16151. Whether the given interval overlaps this interval.
  16152. Params:
  16153. interval = The interval to check for intersection with this interval.
  16154. Throws:
  16155. $(D DateTimeException) if this interval is empty.
  16156. Examples:
  16157. --------------------
  16158. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
  16159. NegInfInterval!Date(Date(1996, 1, 2))));
  16160. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(
  16161. NegInfInterval!Date(Date(2000, 1, 2))));
  16162. --------------------
  16163. +/
  16164. bool intersects(in NegInfInterval!TP interval) const pure
  16165. {
  16166. _enforceNotEmpty();
  16167. return _begin < interval._end;
  16168. }
  16169. /++
  16170. Returns the intersection of two intervals
  16171. Params:
  16172. interval = The interval to intersect with this interval.
  16173. Throws:
  16174. $(D DateTimeException) if the two intervals do not intersect or if
  16175. either interval is empty.
  16176. Examples:
  16177. --------------------
  16178. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
  16179. Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
  16180. Interval!Date(Date(1996, 1 , 2), Date(2000, 8, 2)));
  16181. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
  16182. Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) ==
  16183. Interval!Date(Date(1999, 1 , 12), Date(2011, 9, 17)));
  16184. --------------------
  16185. +/
  16186. Interval intersection(in Interval interval) const
  16187. {
  16188. enforce(this.intersects(interval), new DateTimeException(format("%s and %s do not intersect.", this, interval)));
  16189. auto begin = _begin > interval._begin ? _begin : interval._begin;
  16190. auto end = _end < interval._end ? _end : interval._end;
  16191. return Interval(begin, end);
  16192. }
  16193. /++
  16194. Returns the intersection of two intervals
  16195. Params:
  16196. interval = The interval to intersect with this interval.
  16197. Throws:
  16198. $(D DateTimeException) if the two intervals do not intersect or if
  16199. this interval is empty.
  16200. Examples:
  16201. --------------------
  16202. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
  16203. PosInfInterval!Date(Date(1990, 7, 6))) ==
  16204. Interval!Date(Date(1996, 1 , 2), Date(2012, 3, 1)));
  16205. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
  16206. PosInfInterval!Date(Date(1999, 1, 12))) ==
  16207. Interval!Date(Date(1999, 1 , 12), Date(2012, 3, 1)));
  16208. --------------------
  16209. +/
  16210. Interval intersection(in PosInfInterval!TP interval) const
  16211. {
  16212. enforce(this.intersects(interval), new DateTimeException(format("%s and %s do not intersect.", this, interval)));
  16213. return Interval(_begin > interval._begin ? _begin : interval._begin, _end);
  16214. }
  16215. /++
  16216. Returns the intersection of two intervals
  16217. Params:
  16218. interval = The interval to intersect with this interval.
  16219. Throws:
  16220. $(D DateTimeException) if the two intervals do not intersect or if
  16221. this interval is empty.
  16222. Examples:
  16223. --------------------
  16224. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
  16225. NegInfInterval!Date(Date(1999, 7, 6))) ==
  16226. Interval!Date(Date(1996, 1 , 2), Date(1999, 7, 6)));
  16227. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(
  16228. NegInfInterval!Date(Date(2013, 1, 12))) ==
  16229. Interval!Date(Date(1996, 1 , 2), Date(2012, 3, 1)));
  16230. --------------------
  16231. +/
  16232. Interval intersection(in NegInfInterval!TP interval) const
  16233. {
  16234. enforce(this.intersects(interval), new DateTimeException(format("%s and %s do not intersect.", this, interval)));
  16235. return Interval(_begin, _end < interval._end ? _end : interval._end);
  16236. }
  16237. /++
  16238. Whether the given interval is adjacent to this interval.
  16239. Params:
  16240. interval = The interval to check whether its adjecent to this
  16241. interval.
  16242. Throws:
  16243. $(D DateTimeException) if either interval is empty.
  16244. Examples:
  16245. --------------------
  16246. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
  16247. Interval!Date(Date(1990, 7, 6), Date(1996, 1, 2))));
  16248. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
  16249. Interval!Date(Date(2012, 3, 1), Date(2013, 9, 17))));
  16250. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
  16251. Interval!Date(Date(1989, 3, 1), Date(2012, 3, 1))));
  16252. --------------------
  16253. +/
  16254. bool isAdjacent(in Interval interval) const pure
  16255. {
  16256. _enforceNotEmpty();
  16257. interval._enforceNotEmpty();
  16258. return _begin == interval._end || _end == interval._begin;
  16259. }
  16260. /++
  16261. Whether the given interval is adjacent to this interval.
  16262. Params:
  16263. interval = The interval to check whether its adjecent to this
  16264. interval.
  16265. Throws:
  16266. $(D DateTimeException) if this interval is empty.
  16267. Examples:
  16268. --------------------
  16269. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
  16270. PosInfInterval!Date(Date(1999, 5, 4))));
  16271. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
  16272. PosInfInterval!Date(Date(2012, 3, 1))));
  16273. --------------------
  16274. +/
  16275. bool isAdjacent(in PosInfInterval!TP interval) const pure
  16276. {
  16277. _enforceNotEmpty();
  16278. return _end == interval._begin;
  16279. }
  16280. /++
  16281. Whether the given interval is adjacent to this interval.
  16282. Params:
  16283. interval = The interval to check whether its adjecent to this
  16284. interval.
  16285. Throws:
  16286. $(D DateTimeException) if this interval is empty.
  16287. Examples:
  16288. --------------------
  16289. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
  16290. NegInfInterval!Date(Date(1996, 1, 2))));
  16291. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(
  16292. NegInfInterval!Date(Date(2000, 1, 2))));
  16293. --------------------
  16294. +/
  16295. bool isAdjacent(in NegInfInterval!TP interval) const pure
  16296. {
  16297. _enforceNotEmpty();
  16298. return _begin == interval._end;
  16299. }
  16300. /++
  16301. Returns the union of two intervals
  16302. Params:
  16303. interval = The interval to merge with this interval.
  16304. Throws:
  16305. $(D DateTimeException) if the two intervals do not intersect and are
  16306. not adjacent or if either interval is empty.
  16307. Examples:
  16308. --------------------
  16309. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(
  16310. Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
  16311. Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
  16312. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(
  16313. Interval!Date(Date(2012, 3, 1), Date(2013, 5, 7))) ==
  16314. Interval!Date(Date(1996, 1 , 2), Date(2013, 5, 7)));
  16315. --------------------
  16316. +/
  16317. Interval merge(in Interval interval) const
  16318. {
  16319. enforce(this.isAdjacent(interval) || this.intersects(interval),
  16320. new DateTimeException(format("%s and %s are not adjacent and do not intersect.", this, interval)));
  16321. auto begin = _begin < interval._begin ? _begin : interval._begin;
  16322. auto end = _end > interval._end ? _end : interval._end;
  16323. return Interval(begin, end);
  16324. }
  16325. /++
  16326. Returns the union of two intervals
  16327. Params:
  16328. interval = The interval to merge with this interval.
  16329. Throws:
  16330. $(D DateTimeException) if the two intervals do not intersect and are
  16331. not adjacent or if this interval is empty.
  16332. Examples:
  16333. --------------------
  16334. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(
  16335. PosInfInterval!Date(Date(1990, 7, 6))) ==
  16336. PosInfInterval!Date(Date(1990, 7 , 6)));
  16337. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(
  16338. PosInfInterval!Date(Date(2012, 3, 1))) ==
  16339. PosInfInterval!Date(Date(1996, 1 , 2)));
  16340. --------------------
  16341. +/
  16342. PosInfInterval!TP merge(in PosInfInterval!TP interval) const
  16343. {
  16344. enforce(this.isAdjacent(interval) || this.intersects(interval),
  16345. new DateTimeException(format("%s and %s are not adjacent and do not intersect.", this, interval)));
  16346. return PosInfInterval!TP(_begin < interval._begin ? _begin : interval._begin);
  16347. }
  16348. /++
  16349. Returns the union of two intervals
  16350. Params:
  16351. interval = The interval to merge with this interval.
  16352. Throws:
  16353. $(D DateTimeException) if the two intervals do not intersect and are not
  16354. adjacent or if this interval is empty.
  16355. Examples:
  16356. --------------------
  16357. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(
  16358. NegInfInterval!Date(Date(1996, 1, 2))) ==
  16359. NegInfInterval!Date(Date(2012, 3 , 1)));
  16360. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(
  16361. NegInfInterval!Date(Date(2013, 1, 12))) ==
  16362. NegInfInterval!Date(Date(2013, 1 , 12)));
  16363. --------------------
  16364. +/
  16365. NegInfInterval!TP merge(in NegInfInterval!TP interval) const
  16366. {
  16367. enforce(this.isAdjacent(interval) || this.intersects(interval),
  16368. new DateTimeException(format("%s and %s are not adjacent and do not intersect.", this, interval)));
  16369. return NegInfInterval!TP(_end > interval._end ? _end : interval._end);
  16370. }
  16371. /++
  16372. Returns an interval that covers from the earliest time point of two
  16373. intervals up to (but not including) the latest time point of two
  16374. intervals.
  16375. Params:
  16376. interval = The interval to create a span together with this interval.
  16377. Throws:
  16378. $(D DateTimeException) if either interval is empty.
  16379. Examples:
  16380. --------------------
  16381. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(
  16382. Interval!Date(Date(1990, 7, 6), Date(1991, 1, 8))) ==
  16383. Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
  16384. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(
  16385. Interval!Date(Date(2012, 3, 1), Date(2013, 5, 7))) ==
  16386. Interval!Date(Date(1996, 1 , 2), Date(2013, 5, 7)));
  16387. --------------------
  16388. +/
  16389. Interval span(in Interval interval) const pure
  16390. {
  16391. _enforceNotEmpty();
  16392. interval._enforceNotEmpty();
  16393. auto begin = _begin < interval._begin ? _begin : interval._begin;
  16394. auto end = _end > interval._end ? _end : interval._end;
  16395. return Interval(begin, end);
  16396. }
  16397. /++
  16398. Returns an interval that covers from the earliest time point of two
  16399. intervals up to (but not including) the latest time point of two
  16400. intervals.
  16401. Params:
  16402. interval = The interval to create a span together with this interval.
  16403. Throws:
  16404. $(D DateTimeException) if this interval is empty.
  16405. Examples:
  16406. --------------------
  16407. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(
  16408. PosInfInterval!Date(Date(1990, 7, 6))) ==
  16409. PosInfInterval!Date(Date(1990, 7 , 6)));
  16410. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(
  16411. PosInfInterval!Date(Date(2050, 1, 1))) ==
  16412. PosInfInterval!Date(Date(1996, 1 , 2)));
  16413. --------------------
  16414. +/
  16415. PosInfInterval!TP span(in PosInfInterval!TP interval) const pure
  16416. {
  16417. _enforceNotEmpty();
  16418. return PosInfInterval!TP(_begin < interval._begin ? _begin : interval._begin);
  16419. }
  16420. /++
  16421. Returns an interval that covers from the earliest time point of two
  16422. intervals up to (but not including) the latest time point of two
  16423. intervals.
  16424. Params:
  16425. interval = The interval to create a span together with this interval.
  16426. Throws:
  16427. $(D DateTimeException) if this interval is empty.
  16428. Examples:
  16429. --------------------
  16430. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(
  16431. NegInfInterval!Date(Date(1602, 5, 21))) ==
  16432. NegInfInterval!Date(Date(2012, 3 , 1)));
  16433. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(
  16434. NegInfInterval!Date(Date(2013, 1, 12))) ==
  16435. NegInfInterval!Date(Date(2013, 1 , 12)));
  16436. --------------------
  16437. +/
  16438. NegInfInterval!TP span(in NegInfInterval!TP interval) const pure
  16439. {
  16440. _enforceNotEmpty();
  16441. return NegInfInterval!TP(_end > interval._end ? _end : interval._end);
  16442. }
  16443. /++
  16444. Shifts the interval forward or backwards in time by the given duration
  16445. (a positive duration shifts the interval forward; a negative duration
  16446. shifts it backward). Effectively, it does $(D begin += duration) and
  16447. $(D end += duration).
  16448. Params:
  16449. duration = The duration to shift the interval by.
  16450. Throws:
  16451. $(D DateTimeException) this interval is empty or if the resulting
  16452. interval would be invalid.
  16453. Examples:
  16454. --------------------
  16455. auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 4, 5));
  16456. auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 4, 5));
  16457. interval1.shift(dur!"days"(50));
  16458. assert(interval1 == Interval!Date(Date(1996, 2, 21), Date(2012, 5, 25)));
  16459. interval2.shift(dur!"days"(-50));
  16460. assert(interval2 == Interval!Date(Date(1995, 11, 13), Date(2012, 2, 15)));
  16461. --------------------
  16462. +/
  16463. void shift(D)(D duration) pure
  16464. if(__traits(compiles, begin + duration))
  16465. {
  16466. _enforceNotEmpty();
  16467. auto begin = _begin + duration;
  16468. auto end = _end + duration;
  16469. if(!_valid(begin, end))
  16470. throw new DateTimeException("Argument would result in an invalid Interval.");
  16471. _begin = begin;
  16472. _end = end;
  16473. }
  16474. static if(__traits(compiles, begin.add!"months"(1)) &&
  16475. __traits(compiles, begin.add!"years"(1)))
  16476. {
  16477. /++
  16478. Shifts the interval forward or backwards in time by the given number
  16479. of years and/or months (a positive number of years and months shifts
  16480. the interval forward; a negative number shifts it backward).
  16481. It adds the years the given years and months to both begin and end.
  16482. It effectively calls $(D add!"years"()) and then $(D add!"months"())
  16483. on begin and end with the given number of years and months.
  16484. Params:
  16485. years = The number of years to shift the interval by.
  16486. months = The number of months to shift the interval by.
  16487. allowOverflow = Whether the days should be allowed to overflow
  16488. on $(D begin) and $(D end), causing their month
  16489. to increment.
  16490. Throws:
  16491. $(D DateTimeException) if this interval is empty or if the
  16492. resulting interval would be invalid.
  16493. Examples:
  16494. --------------------
  16495. auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
  16496. auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
  16497. interval1.shift(2);
  16498. assert(interval1 == Interval!Date(Date(1998, 1, 2), Date(2014, 3, 1)));
  16499. interval2.shift(-2);
  16500. assert(interval2 == Interval!Date(Date(1994, 1, 2), Date(2010, 3, 1)));
  16501. --------------------
  16502. +/
  16503. void shift(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
  16504. if(isIntegral!T)
  16505. {
  16506. _enforceNotEmpty();
  16507. auto begin = _begin;
  16508. auto end = _end;
  16509. begin.add!"years"(years, allowOverflow);
  16510. begin.add!"months"(months, allowOverflow);
  16511. end.add!"years"(years, allowOverflow);
  16512. end.add!"months"(months, allowOverflow);
  16513. enforce(_valid(begin, end), new DateTimeException("Argument would result in an invalid Interval."));
  16514. _begin = begin;
  16515. _end = end;
  16516. }
  16517. }
  16518. /++
  16519. Expands the interval forwards and/or backwards in time. Effectively,
  16520. it does $(D begin -= duration) and/or $(D end += duration). Whether
  16521. it expands forwards and/or backwards in time is determined by
  16522. $(D_PARAM dir).
  16523. Params:
  16524. duration = The duration to expand the interval by.
  16525. dir = The direction in time to expand the interval.
  16526. Throws:
  16527. $(D DateTimeException) this interval is empty or if the resulting
  16528. interval would be invalid.
  16529. Examples:
  16530. --------------------
  16531. auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
  16532. auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
  16533. interval1.expand(2);
  16534. assert(interval1 == Interval!Date(Date(1994, 1, 2), Date(2014, 3, 1)));
  16535. interval2.expand(-2);
  16536. assert(interval2 == Interval!Date(Date(1998, 1, 2), Date(2010, 3, 1)));
  16537. --------------------
  16538. +/
  16539. void expand(D)(D duration, Direction dir = Direction.both) pure
  16540. if(__traits(compiles, begin + duration))
  16541. {
  16542. _enforceNotEmpty();
  16543. switch(dir)
  16544. {
  16545. case Direction.both:
  16546. {
  16547. auto begin = _begin - duration;
  16548. auto end = _end + duration;
  16549. if(!_valid(begin, end))
  16550. throw new DateTimeException("Argument would result in an invalid Interval.");
  16551. _begin = begin;
  16552. _end = end;
  16553. return;
  16554. }
  16555. case Direction.fwd:
  16556. {
  16557. auto end = _end + duration;
  16558. if(!_valid(_begin, end))
  16559. throw new DateTimeException("Argument would result in an invalid Interval.");
  16560. _end = end;
  16561. return;
  16562. }
  16563. case Direction.bwd:
  16564. {
  16565. auto begin = _begin - duration;
  16566. if(!_valid(begin, _end))
  16567. throw new DateTimeException("Argument would result in an invalid Interval.");
  16568. _begin = begin;
  16569. return;
  16570. }
  16571. default:
  16572. assert(0, "Invalid Direction.");
  16573. }
  16574. }
  16575. static if(__traits(compiles, begin.add!"months"(1)) &&
  16576. __traits(compiles, begin.add!"years"(1)))
  16577. {
  16578. /++
  16579. Expands the interval forwards and/or backwards in time. Effectively,
  16580. it subtracts the given number of months/years from $(D begin) and
  16581. adds them to $(D end). Whether it expands forwards and/or backwards
  16582. in time is determined by $(D_PARAM dir).
  16583. Params:
  16584. years = The number of years to expand the interval by.
  16585. months = The number of months to expand the interval by.
  16586. allowOverflow = Whether the days should be allowed to overflow
  16587. on $(D begin) and $(D end), causing their month
  16588. to increment.
  16589. Throws:
  16590. $(D DateTimeException) if this interval is empty or if the
  16591. resulting interval would be invalid.
  16592. Examples:
  16593. --------------------
  16594. auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
  16595. auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
  16596. interval1.expand(2);
  16597. assert(interval1 == Interval!Date(Date(1994, 1, 2), Date(2014, 3, 1)));
  16598. interval2.expand(-2);
  16599. assert(interval2 == Interval!Date(Date(1998, 1, 2), Date(2010, 3, 1)));
  16600. --------------------
  16601. +/
  16602. void expand(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes, Direction dir = Direction.both)
  16603. if(isIntegral!T)
  16604. {
  16605. _enforceNotEmpty();
  16606. switch(dir)
  16607. {
  16608. case Direction.both:
  16609. {
  16610. auto begin = _begin;
  16611. auto end = _end;
  16612. begin.add!"years"(-years, allowOverflow);
  16613. begin.add!"months"(-months, allowOverflow);
  16614. end.add!"years"(years, allowOverflow);
  16615. end.add!"months"(months, allowOverflow);
  16616. enforce(_valid(begin, end), new DateTimeException("Argument would result in an invalid Interval."));
  16617. _begin = begin;
  16618. _end = end;
  16619. return;
  16620. }
  16621. case Direction.fwd:
  16622. {
  16623. auto end = _end;
  16624. end.add!"years"(years, allowOverflow);
  16625. end.add!"months"(months, allowOverflow);
  16626. enforce(_valid(_begin, end), new DateTimeException("Argument would result in an invalid Interval."));
  16627. _end = end;
  16628. return;
  16629. }
  16630. case Direction.bwd:
  16631. {
  16632. auto begin = _begin;
  16633. begin.add!"years"(-years, allowOverflow);
  16634. begin.add!"months"(-months, allowOverflow);
  16635. enforce(_valid(begin, _end), new DateTimeException("Argument would result in an invalid Interval."));
  16636. _begin = begin;
  16637. return;
  16638. }
  16639. default:
  16640. assert(0, "Invalid Direction.");
  16641. }
  16642. }
  16643. }
  16644. /++
  16645. Returns a range which iterates forward over the interval, starting
  16646. at $(D begin), using $(D_PARAM func) to generate each successive time
  16647. point.
  16648. The range's $(D front) is the interval's $(D begin). $(D_PARAM func) is
  16649. used to generate the next $(D front) when $(D popFront) is called. If
  16650. $(D_PARAM popFirst) is $(D PopFirst.yes), then $(D popFront) is called
  16651. before the range is returned (so that $(D front) is a time point which
  16652. $(D_PARAM func) would generate).
  16653. If $(D_PARAM func) ever generates a time point less than or equal to the
  16654. current $(D front) of the range, then a $(D DateTimeException) will be
  16655. thrown. The range will be empty and iteration complete when
  16656. $(D_PARAM func) generates a time point equal to or beyond the $(D end)
  16657. of the interval.
  16658. There are helper functions in this module which generate common
  16659. delegates to pass to $(D fwdRange). Their documentation starts with
  16660. "Range-generating function," so you can easily search for them.
  16661. Params:
  16662. func = The function used to generate the time points of the
  16663. range over the interval.
  16664. popFirst = Whether $(D popFront) should be called on the range
  16665. before returning it.
  16666. Throws:
  16667. $(D DateTimeException) if this interval is empty.
  16668. Warning:
  16669. $(D_PARAM func) must be logically pure. Ideally, $(D_PARAM func)
  16670. would be a function pointer to a pure function, but forcing
  16671. $(D_PARAM func) to be pure is far too restrictive to be useful, and
  16672. in order to have the ease of use of having functions which generate
  16673. functions to pass to $(D fwdRange), $(D_PARAM func) must be a
  16674. delegate.
  16675. If $(D_PARAM func) retains state which changes as it is called, then
  16676. some algorithms will not work correctly, because the range's
  16677. $(D save) will have failed to have really saved the range's state.
  16678. So, if you want to avoid such bugs, don't pass a delegate which is
  16679. not logically pure to $(D fwdRange). If $(D_PARAM func) is given the
  16680. same time point with two different calls, it must return the same
  16681. result both times.
  16682. Of course, none of the functions in this module have this problem,
  16683. so it's only relevant if you're creating your own delegate.
  16684. Examples:
  16685. --------------------
  16686. auto interval = Interval!Date(Date(2010, 9, 1), Date(2010, 9, 9));
  16687. auto func = (in Date date) //For iterating over even-numbered days.
  16688. {
  16689. if((date.day & 1) == 0)
  16690. return date + dur!"days"(2);
  16691. return date + dur!"days"(1);
  16692. };
  16693. auto range = interval.fwdRange(func);
  16694. //An odd day. Using PopFirst.yes would have made this Date(2010, 9, 2).
  16695. assert(range.front == Date(2010, 9, 1));
  16696. range.popFront();
  16697. assert(range.front == Date(2010, 9, 2));
  16698. range.popFront();
  16699. assert(range.front == Date(2010, 9, 4));
  16700. range.popFront();
  16701. assert(range.front == Date(2010, 9, 6));
  16702. range.popFront();
  16703. assert(range.front == Date(2010, 9, 8));
  16704. range.popFront();
  16705. assert(range.empty);
  16706. --------------------
  16707. +/
  16708. IntervalRange!(TP, Direction.fwd) fwdRange(TP delegate(in TP) func, PopFirst popFirst = PopFirst.no) const
  16709. {
  16710. _enforceNotEmpty();
  16711. auto range = IntervalRange!(TP, Direction.fwd)(this, func);
  16712. if(popFirst == PopFirst.yes)
  16713. range.popFront();
  16714. return range;
  16715. }
  16716. /++
  16717. Returns a range which iterates backwards over the interval, starting
  16718. at $(D end), using $(D_PARAM func) to generate each successive time
  16719. point.
  16720. The range's $(D front) is the interval's $(D end). $(D_PARAM func) is
  16721. used to generate the next $(D front) when $(D popFront) is called. If
  16722. $(D_PARAM popFirst) is $(D PopFirst.yes), then $(D popFront) is called
  16723. before the range is returned (so that $(D front) is a time point which
  16724. $(D_PARAM func) would generate).
  16725. If $(D_PARAM func) ever generates a time point greater than or equal to
  16726. the current $(D front) of the range, then a $(D DateTimeException) will
  16727. be thrown. The range will be empty and iteration complete when
  16728. $(D_PARAM func) generates a time point equal to or less than the
  16729. $(D begin) of the interval.
  16730. There are helper functions in this module which generate common
  16731. delegates to pass to $(D bwdRange). Their documentation starts with
  16732. "Range-generating function," so you can easily search for them.
  16733. Params:
  16734. func = The function used to generate the time points of the
  16735. range over the interval.
  16736. popFirst = Whether $(D popFront) should be called on the range
  16737. before returning it.
  16738. Throws:
  16739. $(D DateTimeException) if this interval is empty.
  16740. Warning:
  16741. $(D_PARAM func) must be logically pure. Ideally, $(D_PARAM func)
  16742. would be a function pointer to a pure function, but forcing
  16743. $(D_PARAM func) to be pure is far too restrictive to be useful, and
  16744. in order to have the ease of use of having functions which generate
  16745. functions to pass to $(D fwdRange), $(D_PARAM func) must be a
  16746. delegate.
  16747. If $(D_PARAM func) retains state which changes as it is called, then
  16748. some algorithms will not work correctly, because the range's
  16749. $(D save) will have failed to have really saved the range's state.
  16750. So, if you want to avoid such bugs, don't pass a delegate which is
  16751. not logically pure to $(D fwdRange). If $(D_PARAM func) is given the
  16752. same time point with two different calls, it must return the same
  16753. result both times.
  16754. Of course, none of the functions in this module have this problem,
  16755. so it's only relevant if you're creating your own delegate.
  16756. Examples:
  16757. --------------------
  16758. auto interval = Interval!Date(Date(2010, 9, 1), Date(2010, 9, 9));
  16759. auto func = (in Date date) //For iterating over even-numbered days.
  16760. {
  16761. if((date.day & 1) == 0)
  16762. return date - dur!"days"(2);
  16763. return date - dur!"days"(1);
  16764. };
  16765. auto range = interval.bwdRange(func);
  16766. //An odd day. Using PopFirst.yes would have made this Date(2010, 9, 8).
  16767. assert(range.front == Date(2010, 9, 9));
  16768. range.popFront();
  16769. assert(range.front == Date(2010, 9, 8));
  16770. range.popFront();
  16771. assert(range.front == Date(2010, 9, 6));
  16772. range.popFront();
  16773. assert(range.front == Date(2010, 9, 4));
  16774. range.popFront();
  16775. assert(range.front == Date(2010, 9, 2));
  16776. range.popFront();
  16777. assert(range.empty);
  16778. --------------------
  16779. +/
  16780. IntervalRange!(TP, Direction.bwd) bwdRange(TP delegate(in TP) func, PopFirst popFirst = PopFirst.no) const
  16781. {
  16782. _enforceNotEmpty();
  16783. auto range = IntervalRange!(TP, Direction.bwd)(this, func);
  16784. if(popFirst == PopFirst.yes)
  16785. range.popFront();
  16786. return range;
  16787. }
  16788. /+
  16789. Converts this interval to a string.
  16790. +/
  16791. //Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
  16792. //have versions of toString() with extra modifiers, so we define one version
  16793. //with modifiers and one without.
  16794. string toString()
  16795. {
  16796. return _toStringImpl();
  16797. }
  16798. /++
  16799. Converts this interval to a string.
  16800. +/
  16801. //Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
  16802. //have versions of toString() with extra modifiers, so we define one version
  16803. //with modifiers and one without.
  16804. string toString() const nothrow
  16805. {
  16806. return _toStringImpl();
  16807. }
  16808. private:
  16809. /+
  16810. Since we have two versions of toString, we have _toStringImpl
  16811. so that they can share implementations.
  16812. +/
  16813. string _toStringImpl() const nothrow
  16814. {
  16815. try
  16816. return format("[%s - %s)", _begin, _end);
  16817. catch(Exception e)
  16818. assert(0, "format() threw.");
  16819. }
  16820. /+
  16821. Throws:
  16822. $(D DateTimeException) if this interval is empty.
  16823. +/
  16824. void _enforceNotEmpty(size_t line = __LINE__) const pure
  16825. {
  16826. if(empty)
  16827. throw new DateTimeException("Invalid operation for an empty Interval.", __FILE__, line);
  16828. }
  16829. /+
  16830. Whether the given values form a valid time interval.
  16831. Params:
  16832. begin = The starting point of the interval.
  16833. end = The end point of the interval.
  16834. +/
  16835. static bool _valid(in TP begin, in TP end) pure nothrow
  16836. {
  16837. return begin <= end;
  16838. }
  16839. pure invariant()
  16840. {
  16841. assert(_valid(_begin, _end), "Invariant Failure: begin is not before or equal to end.");
  16842. }
  16843. TP _begin;
  16844. TP _end;
  16845. }
  16846. //Test Interval's constructors.
  16847. unittest
  16848. {
  16849. version(testStdDateTime)
  16850. {
  16851. assertThrown!DateTimeException(Interval!Date(Date(2010, 1, 1), Date(1, 1, 1)));
  16852. Interval!Date(Date.init, Date.init);
  16853. Interval!TimeOfDay(TimeOfDay.init, TimeOfDay.init);
  16854. Interval!DateTime(DateTime.init, DateTime.init);
  16855. Interval!SysTime(SysTime(0), SysTime(0));
  16856. Interval!DateTime(DateTime.init, dur!"days"(7));
  16857. //Verify Examples.
  16858. Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
  16859. assert(Interval!Date(Date(1996, 1, 2), dur!"weeks"(3)) == Interval!Date(Date(1996, 1, 2), Date(1996, 1, 23)));
  16860. assert(Interval!Date(Date(1996, 1, 2), dur!"days"(3)) == Interval!Date(Date(1996, 1, 2), Date(1996, 1, 5)));
  16861. assert(Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), dur!"hours"(3)) == Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), DateTime(1996, 1, 2, 15, 0, 0)));
  16862. assert(Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), dur!"minutes"(3)) == Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), DateTime(1996, 1, 2, 12, 3, 0)));
  16863. assert(Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), dur!"seconds"(3)) == Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), DateTime(1996, 1, 2, 12, 0, 3)));
  16864. assert(Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), dur!"msecs"(3000)) == Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), DateTime(1996, 1, 2, 12, 0, 3)));
  16865. }
  16866. }
  16867. //Test Interval's begin.
  16868. unittest
  16869. {
  16870. version(testStdDateTime)
  16871. {
  16872. _assertPred!"=="(Interval!Date(Date(1, 1, 1), Date(2010, 1, 1)).begin, Date(1, 1, 1));
  16873. _assertPred!"=="(Interval!Date(Date(2010, 1, 1), Date(2010, 1, 1)).begin, Date(2010, 1, 1));
  16874. _assertPred!"=="(Interval!Date(Date(1997, 12, 31), Date(1998, 1, 1)).begin, Date(1997, 12, 31));
  16875. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  16876. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  16877. static assert(__traits(compiles, cInterval.begin));
  16878. static assert(__traits(compiles, iInterval.begin));
  16879. //Verify Examples.
  16880. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).begin == Date(1996, 1, 2));
  16881. }
  16882. }
  16883. //Test Interval's end.
  16884. unittest
  16885. {
  16886. version(testStdDateTime)
  16887. {
  16888. _assertPred!"=="(Interval!Date(Date(1, 1, 1), Date(2010, 1, 1)).end, Date(2010, 1, 1));
  16889. _assertPred!"=="(Interval!Date(Date(2010, 1, 1), Date(2010, 1, 1)).end, Date(2010, 1, 1));
  16890. _assertPred!"=="(Interval!Date(Date(1997, 12, 31), Date(1998, 1, 1)).end, Date(1998, 1, 1));
  16891. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  16892. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  16893. static assert(__traits(compiles, cInterval.end));
  16894. static assert(__traits(compiles, iInterval.end));
  16895. //Verify Examples.
  16896. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).end == Date(2012, 3, 1));
  16897. }
  16898. }
  16899. //Test Interval's length.
  16900. unittest
  16901. {
  16902. version(testStdDateTime)
  16903. {
  16904. _assertPred!"=="(Interval!Date(Date(2010, 1, 1), Date(2010, 1, 1)).length, dur!"days"(0));
  16905. _assertPred!"=="(Interval!Date(Date(2010, 1, 1), Date(2010, 4, 1)).length, dur!"days"(90));
  16906. _assertPred!"=="(Interval!TimeOfDay(TimeOfDay(0, 30, 0), TimeOfDay(12, 22, 7)).length, dur!"seconds"(42_727));
  16907. _assertPred!"=="(Interval!DateTime(DateTime(2010, 1, 1, 0, 30, 0), DateTime(2010, 1, 2, 12, 22, 7)).length, dur!"seconds"(129_127));
  16908. _assertPred!"=="(Interval!SysTime(SysTime(DateTime(2010, 1, 1, 0, 30, 0)), SysTime(DateTime(2010, 1, 2, 12, 22, 7))).length, dur!"seconds"(129_127));
  16909. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  16910. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  16911. static assert(__traits(compiles, cInterval.length));
  16912. static assert(__traits(compiles, iInterval.length));
  16913. //Verify Examples.
  16914. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).length == dur!"days"(5903));
  16915. }
  16916. }
  16917. //Test Interval's empty.
  16918. unittest
  16919. {
  16920. version(testStdDateTime)
  16921. {
  16922. assert(Interval!Date(Date(2010, 1, 1), Date(2010, 1, 1)).empty);
  16923. assert(!Interval!Date(Date(2010, 1, 1), Date(2010, 4, 1)).empty);
  16924. assert(!Interval!TimeOfDay(TimeOfDay(0, 30, 0), TimeOfDay(12, 22, 7)).empty);
  16925. assert(!Interval!DateTime(DateTime(2010, 1, 1, 0, 30, 0), DateTime(2010, 1, 2, 12, 22, 7)).empty);
  16926. assert(!Interval!SysTime(SysTime(DateTime(2010, 1, 1, 0, 30, 0)), SysTime(DateTime(2010, 1, 2, 12, 22, 7))).empty);
  16927. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  16928. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  16929. static assert(__traits(compiles, cInterval.empty));
  16930. static assert(__traits(compiles, iInterval.empty));
  16931. //Verify Examples.
  16932. assert(Interval!Date(Date(1996, 1, 2), Date(1996, 1, 2)).empty);
  16933. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).empty);
  16934. }
  16935. }
  16936. //Test Interval's contains(time point).
  16937. unittest
  16938. {
  16939. version(testStdDateTime)
  16940. {
  16941. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  16942. assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).contains(Date(2010, 7, 4)));
  16943. assert(!interval.contains(Date(2009, 7, 4)));
  16944. assert(!interval.contains(Date(2010, 7, 3)));
  16945. assert(interval.contains(Date(2010, 7, 4)));
  16946. assert(interval.contains(Date(2010, 7, 5)));
  16947. assert(interval.contains(Date(2011, 7, 1)));
  16948. assert(interval.contains(Date(2012, 1, 6)));
  16949. assert(!interval.contains(Date(2012, 1, 7)));
  16950. assert(!interval.contains(Date(2012, 1, 8)));
  16951. assert(!interval.contains(Date(2013, 1, 7)));
  16952. const cdate = Date(2010, 7, 6);
  16953. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  16954. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  16955. static assert(__traits(compiles, interval.contains(cdate)));
  16956. static assert(__traits(compiles, cInterval.contains(cdate)));
  16957. static assert(__traits(compiles, iInterval.contains(cdate)));
  16958. //Verify Examples.
  16959. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Date(1994, 12, 24)));
  16960. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Date(2000, 1, 5)));
  16961. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Date(2012, 3, 1)));
  16962. }
  16963. }
  16964. //Test Interval's contains(Interval).
  16965. unittest
  16966. {
  16967. version(testStdDateTime)
  16968. {
  16969. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  16970. assertThrown!DateTimeException(interval.contains(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  16971. assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).contains(interval));
  16972. assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).contains(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  16973. assert(interval.contains(interval));
  16974. assert(!interval.contains(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
  16975. assert(!interval.contains(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
  16976. assert(!interval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
  16977. assert(!interval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
  16978. assert(!interval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
  16979. assert(!interval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
  16980. assert(interval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
  16981. assert(interval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
  16982. assert(interval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
  16983. assert(!interval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
  16984. assert(!interval.contains(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
  16985. assert(!interval.contains(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
  16986. assert(!Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).contains(interval));
  16987. assert(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).contains(interval));
  16988. assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).contains(interval));
  16989. assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).contains(interval));
  16990. assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).contains(interval));
  16991. assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).contains(interval));
  16992. assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).contains(interval));
  16993. assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).contains(interval));
  16994. assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).contains(interval));
  16995. assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).contains(interval));
  16996. assert(!Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).contains(interval));
  16997. assert(!Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).contains(interval));
  16998. assert(!interval.contains(PosInfInterval!Date(Date(2010, 7, 3))));
  16999. assert(!interval.contains(PosInfInterval!Date(Date(2010, 7, 4))));
  17000. assert(!interval.contains(PosInfInterval!Date(Date(2010, 7, 5))));
  17001. assert(!interval.contains(PosInfInterval!Date(Date(2012, 1, 6))));
  17002. assert(!interval.contains(PosInfInterval!Date(Date(2012, 1, 7))));
  17003. assert(!interval.contains(PosInfInterval!Date(Date(2012, 1, 8))));
  17004. assert(!interval.contains(NegInfInterval!Date(Date(2010, 7, 3))));
  17005. assert(!interval.contains(NegInfInterval!Date(Date(2010, 7, 4))));
  17006. assert(!interval.contains(NegInfInterval!Date(Date(2010, 7, 5))));
  17007. assert(!interval.contains(NegInfInterval!Date(Date(2012, 1, 6))));
  17008. assert(!interval.contains(NegInfInterval!Date(Date(2012, 1, 7))));
  17009. assert(!interval.contains(NegInfInterval!Date(Date(2012, 1, 8))));
  17010. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17011. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17012. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  17013. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  17014. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  17015. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  17016. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  17017. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  17018. static assert(__traits(compiles, interval.contains(interval)));
  17019. static assert(__traits(compiles, interval.contains(cInterval)));
  17020. static assert(__traits(compiles, interval.contains(iInterval)));
  17021. static assert(__traits(compiles, interval.contains(posInfInterval)));
  17022. static assert(__traits(compiles, interval.contains(cPosInfInterval)));
  17023. static assert(__traits(compiles, interval.contains(iPosInfInterval)));
  17024. static assert(__traits(compiles, interval.contains(negInfInterval)));
  17025. static assert(__traits(compiles, interval.contains(cNegInfInterval)));
  17026. static assert(__traits(compiles, interval.contains(iNegInfInterval)));
  17027. static assert(__traits(compiles, cInterval.contains(interval)));
  17028. static assert(__traits(compiles, cInterval.contains(cInterval)));
  17029. static assert(__traits(compiles, cInterval.contains(iInterval)));
  17030. static assert(__traits(compiles, cInterval.contains(posInfInterval)));
  17031. static assert(__traits(compiles, cInterval.contains(cPosInfInterval)));
  17032. static assert(__traits(compiles, cInterval.contains(iPosInfInterval)));
  17033. static assert(__traits(compiles, cInterval.contains(negInfInterval)));
  17034. static assert(__traits(compiles, cInterval.contains(cNegInfInterval)));
  17035. static assert(__traits(compiles, cInterval.contains(iNegInfInterval)));
  17036. static assert(__traits(compiles, iInterval.contains(interval)));
  17037. static assert(__traits(compiles, iInterval.contains(cInterval)));
  17038. static assert(__traits(compiles, iInterval.contains(iInterval)));
  17039. static assert(__traits(compiles, iInterval.contains(posInfInterval)));
  17040. static assert(__traits(compiles, iInterval.contains(cPosInfInterval)));
  17041. static assert(__traits(compiles, iInterval.contains(iPosInfInterval)));
  17042. static assert(__traits(compiles, iInterval.contains(negInfInterval)));
  17043. static assert(__traits(compiles, iInterval.contains(cNegInfInterval)));
  17044. static assert(__traits(compiles, iInterval.contains(iNegInfInterval)));
  17045. //Verify Examples.
  17046. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  17047. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  17048. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
  17049. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(PosInfInterval!Date(Date(1999, 5, 4))));
  17050. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(NegInfInterval!Date(Date(1996, 5, 4))));
  17051. }
  17052. }
  17053. //Test Interval's isBefore(time point).
  17054. unittest
  17055. {
  17056. version(testStdDateTime)
  17057. {
  17058. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17059. assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isBefore(Date(2010, 7, 4)));
  17060. assert(!interval.isBefore(Date(2009, 7, 3)));
  17061. assert(!interval.isBefore(Date(2010, 7, 3)));
  17062. assert(!interval.isBefore(Date(2010, 7, 4)));
  17063. assert(!interval.isBefore(Date(2010, 7, 5)));
  17064. assert(!interval.isBefore(Date(2011, 7, 1)));
  17065. assert(!interval.isBefore(Date(2012, 1, 6)));
  17066. assert(interval.isBefore(Date(2012, 1, 7)));
  17067. assert(interval.isBefore(Date(2012, 1, 8)));
  17068. assert(interval.isBefore(Date(2013, 1, 7)));
  17069. const cdate = Date(2010, 7, 6);
  17070. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17071. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17072. static assert(__traits(compiles, interval.isBefore(cdate)));
  17073. static assert(__traits(compiles, cInterval.isBefore(cdate)));
  17074. static assert(__traits(compiles, iInterval.isBefore(cdate)));
  17075. //Verify Examples.
  17076. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Date(1994, 12, 24)));
  17077. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Date(2000, 1, 5)));
  17078. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Date(2012, 3, 1)));
  17079. }
  17080. }
  17081. //Test Interval's isBefore(Interval).
  17082. unittest
  17083. {
  17084. version(testStdDateTime)
  17085. {
  17086. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17087. assertThrown!DateTimeException(interval.isBefore(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  17088. assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isBefore(interval));
  17089. assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isBefore(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  17090. assert(!interval.isBefore(interval));
  17091. assert(!interval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
  17092. assert(!interval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
  17093. assert(!interval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
  17094. assert(!interval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
  17095. assert(!interval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
  17096. assert(!interval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
  17097. assert(!interval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
  17098. assert(!interval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
  17099. assert(!interval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
  17100. assert(!interval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
  17101. assert(interval.isBefore(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
  17102. assert(interval.isBefore(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
  17103. assert(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).isBefore(interval));
  17104. assert(!Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).isBefore(interval));
  17105. assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).isBefore(interval));
  17106. assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).isBefore(interval));
  17107. assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).isBefore(interval));
  17108. assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).isBefore(interval));
  17109. assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).isBefore(interval));
  17110. assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).isBefore(interval));
  17111. assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).isBefore(interval));
  17112. assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).isBefore(interval));
  17113. assert(!Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).isBefore(interval));
  17114. assert(!Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).isBefore(interval));
  17115. assert(!interval.isBefore(PosInfInterval!Date(Date(2010, 7, 3))));
  17116. assert(!interval.isBefore(PosInfInterval!Date(Date(2010, 7, 4))));
  17117. assert(!interval.isBefore(PosInfInterval!Date(Date(2010, 7, 5))));
  17118. assert(!interval.isBefore(PosInfInterval!Date(Date(2012, 1, 6))));
  17119. assert(interval.isBefore(PosInfInterval!Date(Date(2012, 1, 7))));
  17120. assert(interval.isBefore(PosInfInterval!Date(Date(2012, 1, 8))));
  17121. assert(!interval.isBefore(NegInfInterval!Date(Date(2010, 7, 3))));
  17122. assert(!interval.isBefore(NegInfInterval!Date(Date(2010, 7, 4))));
  17123. assert(!interval.isBefore(NegInfInterval!Date(Date(2010, 7, 5))));
  17124. assert(!interval.isBefore(NegInfInterval!Date(Date(2012, 1, 6))));
  17125. assert(!interval.isBefore(NegInfInterval!Date(Date(2012, 1, 7))));
  17126. assert(!interval.isBefore(NegInfInterval!Date(Date(2012, 1, 8))));
  17127. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17128. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17129. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  17130. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  17131. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  17132. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  17133. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  17134. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  17135. static assert(__traits(compiles, interval.isBefore(interval)));
  17136. static assert(__traits(compiles, interval.isBefore(cInterval)));
  17137. static assert(__traits(compiles, interval.isBefore(iInterval)));
  17138. static assert(__traits(compiles, interval.isBefore(posInfInterval)));
  17139. static assert(__traits(compiles, interval.isBefore(cPosInfInterval)));
  17140. static assert(__traits(compiles, interval.isBefore(iPosInfInterval)));
  17141. static assert(__traits(compiles, interval.isBefore(negInfInterval)));
  17142. static assert(__traits(compiles, interval.isBefore(cNegInfInterval)));
  17143. static assert(__traits(compiles, interval.isBefore(iNegInfInterval)));
  17144. static assert(__traits(compiles, cInterval.isBefore(interval)));
  17145. static assert(__traits(compiles, cInterval.isBefore(cInterval)));
  17146. static assert(__traits(compiles, cInterval.isBefore(iInterval)));
  17147. static assert(__traits(compiles, cInterval.isBefore(posInfInterval)));
  17148. static assert(__traits(compiles, cInterval.isBefore(cPosInfInterval)));
  17149. static assert(__traits(compiles, cInterval.isBefore(iPosInfInterval)));
  17150. static assert(__traits(compiles, cInterval.isBefore(negInfInterval)));
  17151. static assert(__traits(compiles, cInterval.isBefore(cNegInfInterval)));
  17152. static assert(__traits(compiles, cInterval.isBefore(iNegInfInterval)));
  17153. static assert(__traits(compiles, iInterval.isBefore(interval)));
  17154. static assert(__traits(compiles, iInterval.isBefore(cInterval)));
  17155. static assert(__traits(compiles, iInterval.isBefore(iInterval)));
  17156. static assert(__traits(compiles, iInterval.isBefore(posInfInterval)));
  17157. static assert(__traits(compiles, iInterval.isBefore(cPosInfInterval)));
  17158. static assert(__traits(compiles, iInterval.isBefore(iPosInfInterval)));
  17159. static assert(__traits(compiles, iInterval.isBefore(negInfInterval)));
  17160. static assert(__traits(compiles, iInterval.isBefore(cNegInfInterval)));
  17161. static assert(__traits(compiles, iInterval.isBefore(iNegInfInterval)));
  17162. //Verify Examples.
  17163. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  17164. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  17165. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Interval!Date(Date(2012, 3, 1), Date(2013, 5, 1))));
  17166. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(PosInfInterval!Date(Date(1999, 5, 4))));
  17167. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(PosInfInterval!Date(Date(2013, 3, 7))));
  17168. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(NegInfInterval!Date(Date(1996, 5, 4))));
  17169. }
  17170. }
  17171. //Test Interval's isAfter(time point).
  17172. unittest
  17173. {
  17174. version(testStdDateTime)
  17175. {
  17176. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17177. assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isAfter(Date(2010, 7, 4)));
  17178. assert(interval.isAfter(Date(2009, 7, 4)));
  17179. assert(interval.isAfter(Date(2010, 7, 3)));
  17180. assert(!interval.isAfter(Date(2010, 7, 4)));
  17181. assert(!interval.isAfter(Date(2010, 7, 5)));
  17182. assert(!interval.isAfter(Date(2011, 7, 1)));
  17183. assert(!interval.isAfter(Date(2012, 1, 6)));
  17184. assert(!interval.isAfter(Date(2012, 1, 7)));
  17185. assert(!interval.isAfter(Date(2012, 1, 8)));
  17186. assert(!interval.isAfter(Date(2013, 1, 7)));
  17187. const cdate = Date(2010, 7, 6);
  17188. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17189. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17190. static assert(__traits(compiles, interval.isAfter(cdate)));
  17191. static assert(__traits(compiles, cInterval.isAfter(cdate)));
  17192. static assert(__traits(compiles, iInterval.isAfter(cdate)));
  17193. //Verify Examples.
  17194. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Date(1994, 12, 24)));
  17195. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Date(2000, 1, 5)));
  17196. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Date(2012, 3, 1)));
  17197. }
  17198. }
  17199. //Test Interval's isAfter(Interval).
  17200. unittest
  17201. {
  17202. version(testStdDateTime)
  17203. {
  17204. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17205. assertThrown!DateTimeException(interval.isAfter(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  17206. assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isAfter(interval));
  17207. assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isAfter(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  17208. assert(!interval.isAfter(interval));
  17209. assert(interval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
  17210. assert(!interval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
  17211. assert(interval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
  17212. assert(!interval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
  17213. assert(!interval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
  17214. assert(!interval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
  17215. assert(!interval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
  17216. assert(!interval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
  17217. assert(!interval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
  17218. assert(!interval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
  17219. assert(!interval.isAfter(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
  17220. assert(!interval.isAfter(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
  17221. assert(!Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).isAfter(interval));
  17222. assert(!Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).isAfter(interval));
  17223. assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).isAfter(interval));
  17224. assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).isAfter(interval));
  17225. assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).isAfter(interval));
  17226. assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).isAfter(interval));
  17227. assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).isAfter(interval));
  17228. assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).isAfter(interval));
  17229. assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).isAfter(interval));
  17230. assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).isAfter(interval));
  17231. assert(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).isAfter(interval));
  17232. assert(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).isAfter(interval));
  17233. assert(!interval.isAfter(PosInfInterval!Date(Date(2010, 7, 3))));
  17234. assert(!interval.isAfter(PosInfInterval!Date(Date(2010, 7, 4))));
  17235. assert(!interval.isAfter(PosInfInterval!Date(Date(2010, 7, 5))));
  17236. assert(!interval.isAfter(PosInfInterval!Date(Date(2012, 1, 6))));
  17237. assert(!interval.isAfter(PosInfInterval!Date(Date(2012, 1, 7))));
  17238. assert(!interval.isAfter(PosInfInterval!Date(Date(2012, 1, 8))));
  17239. assert(interval.isAfter(NegInfInterval!Date(Date(2010, 7, 3))));
  17240. assert(interval.isAfter(NegInfInterval!Date(Date(2010, 7, 4))));
  17241. assert(!interval.isAfter(NegInfInterval!Date(Date(2010, 7, 5))));
  17242. assert(!interval.isAfter(NegInfInterval!Date(Date(2012, 1, 6))));
  17243. assert(!interval.isAfter(NegInfInterval!Date(Date(2012, 1, 7))));
  17244. assert(!interval.isAfter(NegInfInterval!Date(Date(2012, 1, 8))));
  17245. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17246. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17247. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  17248. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  17249. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  17250. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  17251. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  17252. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  17253. static assert(__traits(compiles, interval.isAfter(interval)));
  17254. static assert(__traits(compiles, interval.isAfter(cInterval)));
  17255. static assert(__traits(compiles, interval.isAfter(iInterval)));
  17256. static assert(__traits(compiles, interval.isAfter(posInfInterval)));
  17257. static assert(__traits(compiles, interval.isAfter(cPosInfInterval)));
  17258. static assert(__traits(compiles, interval.isAfter(iPosInfInterval)));
  17259. static assert(__traits(compiles, interval.isAfter(negInfInterval)));
  17260. static assert(__traits(compiles, interval.isAfter(cNegInfInterval)));
  17261. static assert(__traits(compiles, interval.isAfter(iNegInfInterval)));
  17262. static assert(__traits(compiles, cInterval.isAfter(interval)));
  17263. static assert(__traits(compiles, cInterval.isAfter(cInterval)));
  17264. static assert(__traits(compiles, cInterval.isAfter(iInterval)));
  17265. static assert(__traits(compiles, cInterval.isAfter(posInfInterval)));
  17266. static assert(__traits(compiles, cInterval.isAfter(cPosInfInterval)));
  17267. static assert(__traits(compiles, cInterval.isAfter(iPosInfInterval)));
  17268. static assert(__traits(compiles, cInterval.isAfter(negInfInterval)));
  17269. static assert(__traits(compiles, cInterval.isAfter(cNegInfInterval)));
  17270. static assert(__traits(compiles, cInterval.isAfter(iNegInfInterval)));
  17271. static assert(__traits(compiles, iInterval.isAfter(interval)));
  17272. static assert(__traits(compiles, iInterval.isAfter(cInterval)));
  17273. static assert(__traits(compiles, iInterval.isAfter(iInterval)));
  17274. static assert(__traits(compiles, iInterval.isAfter(posInfInterval)));
  17275. static assert(__traits(compiles, iInterval.isAfter(cPosInfInterval)));
  17276. static assert(__traits(compiles, iInterval.isAfter(iPosInfInterval)));
  17277. static assert(__traits(compiles, iInterval.isAfter(negInfInterval)));
  17278. static assert(__traits(compiles, iInterval.isAfter(cNegInfInterval)));
  17279. static assert(__traits(compiles, iInterval.isAfter(iNegInfInterval)));
  17280. //Verify Examples.
  17281. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  17282. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  17283. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
  17284. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(PosInfInterval!Date(Date(1999, 5, 4))));
  17285. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(NegInfInterval!Date(Date(1996, 1, 2))));
  17286. }
  17287. }
  17288. //Test Interval's intersects().
  17289. unittest
  17290. {
  17291. version(testStdDateTime)
  17292. {
  17293. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17294. assertThrown!DateTimeException(interval.intersects(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  17295. assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).intersects(interval));
  17296. assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).intersects(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  17297. assert(interval.intersects(interval));
  17298. assert(!interval.intersects(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
  17299. assert(interval.intersects(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
  17300. assert(!interval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
  17301. assert(interval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
  17302. assert(interval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
  17303. assert(interval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
  17304. assert(interval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
  17305. assert(interval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
  17306. assert(interval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
  17307. assert(interval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
  17308. assert(!interval.intersects(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
  17309. assert(!interval.intersects(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
  17310. assert(!Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).intersects(interval));
  17311. assert(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).intersects(interval));
  17312. assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).intersects(interval));
  17313. assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).intersects(interval));
  17314. assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).intersects(interval));
  17315. assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).intersects(interval));
  17316. assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).intersects(interval));
  17317. assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).intersects(interval));
  17318. assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).intersects(interval));
  17319. assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).intersects(interval));
  17320. assert(!Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).intersects(interval));
  17321. assert(!Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).intersects(interval));
  17322. assert(interval.intersects(PosInfInterval!Date(Date(2010, 7, 3))));
  17323. assert(interval.intersects(PosInfInterval!Date(Date(2010, 7, 4))));
  17324. assert(interval.intersects(PosInfInterval!Date(Date(2010, 7, 5))));
  17325. assert(interval.intersects(PosInfInterval!Date(Date(2012, 1, 6))));
  17326. assert(!interval.intersects(PosInfInterval!Date(Date(2012, 1, 7))));
  17327. assert(!interval.intersects(PosInfInterval!Date(Date(2012, 1, 8))));
  17328. assert(!interval.intersects(NegInfInterval!Date(Date(2010, 7, 3))));
  17329. assert(!interval.intersects(NegInfInterval!Date(Date(2010, 7, 4))));
  17330. assert(interval.intersects(NegInfInterval!Date(Date(2010, 7, 5))));
  17331. assert(interval.intersects(NegInfInterval!Date(Date(2012, 1, 6))));
  17332. assert(interval.intersects(NegInfInterval!Date(Date(2012, 1, 7))));
  17333. assert(interval.intersects(NegInfInterval!Date(Date(2012, 1, 8))));
  17334. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17335. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17336. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  17337. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  17338. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  17339. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  17340. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  17341. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  17342. static assert(__traits(compiles, interval.intersects(interval)));
  17343. static assert(__traits(compiles, interval.intersects(cInterval)));
  17344. static assert(__traits(compiles, interval.intersects(iInterval)));
  17345. static assert(__traits(compiles, interval.intersects(posInfInterval)));
  17346. static assert(__traits(compiles, interval.intersects(cPosInfInterval)));
  17347. static assert(__traits(compiles, interval.intersects(iPosInfInterval)));
  17348. static assert(__traits(compiles, interval.intersects(negInfInterval)));
  17349. static assert(__traits(compiles, interval.intersects(cNegInfInterval)));
  17350. static assert(__traits(compiles, interval.intersects(iNegInfInterval)));
  17351. static assert(__traits(compiles, cInterval.intersects(interval)));
  17352. static assert(__traits(compiles, cInterval.intersects(cInterval)));
  17353. static assert(__traits(compiles, cInterval.intersects(iInterval)));
  17354. static assert(__traits(compiles, cInterval.intersects(posInfInterval)));
  17355. static assert(__traits(compiles, cInterval.intersects(cPosInfInterval)));
  17356. static assert(__traits(compiles, cInterval.intersects(iPosInfInterval)));
  17357. static assert(__traits(compiles, cInterval.intersects(negInfInterval)));
  17358. static assert(__traits(compiles, cInterval.intersects(cNegInfInterval)));
  17359. static assert(__traits(compiles, cInterval.intersects(iNegInfInterval)));
  17360. static assert(__traits(compiles, iInterval.intersects(interval)));
  17361. static assert(__traits(compiles, iInterval.intersects(cInterval)));
  17362. static assert(__traits(compiles, iInterval.intersects(iInterval)));
  17363. static assert(__traits(compiles, iInterval.intersects(posInfInterval)));
  17364. static assert(__traits(compiles, iInterval.intersects(cPosInfInterval)));
  17365. static assert(__traits(compiles, iInterval.intersects(iPosInfInterval)));
  17366. static assert(__traits(compiles, iInterval.intersects(negInfInterval)));
  17367. static assert(__traits(compiles, iInterval.intersects(cNegInfInterval)));
  17368. static assert(__traits(compiles, iInterval.intersects(iNegInfInterval)));
  17369. //Verify Examples.
  17370. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  17371. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  17372. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
  17373. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(PosInfInterval!Date(Date(1999, 5, 4))));
  17374. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(PosInfInterval!Date(Date(2012, 3, 1))));
  17375. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(NegInfInterval!Date(Date(1996, 1, 2))));
  17376. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(NegInfInterval!Date(Date(2000, 1, 2))));
  17377. }
  17378. }
  17379. //Test Interval's intersection().
  17380. unittest
  17381. {
  17382. version(testStdDateTime)
  17383. {
  17384. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17385. assertThrown!DateTimeException(interval.intersection(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  17386. assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).intersection(interval));
  17387. assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).intersection(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  17388. assertThrown!DateTimeException(interval.intersection(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
  17389. assertThrown!DateTimeException(interval.intersection(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
  17390. assertThrown!DateTimeException(interval.intersection(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
  17391. assertThrown!DateTimeException(interval.intersection(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
  17392. assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).intersection(interval));
  17393. assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).intersection(interval));
  17394. assertThrown!DateTimeException(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).intersection(interval));
  17395. assertThrown!DateTimeException(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).intersection(interval));
  17396. assertThrown!DateTimeException(interval.intersection(PosInfInterval!Date(Date(2012, 1, 7))));
  17397. assertThrown!DateTimeException(interval.intersection(PosInfInterval!Date(Date(2012, 1, 8))));
  17398. assertThrown!DateTimeException(interval.intersection(NegInfInterval!Date(Date(2010, 7, 3))));
  17399. assertThrown!DateTimeException(interval.intersection(NegInfInterval!Date(Date(2010, 7, 4))));
  17400. _assertPred!"=="(interval.intersection(interval), interval);
  17401. _assertPred!"=="(interval.intersection(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))),
  17402. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
  17403. _assertPred!"=="(interval.intersection(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))),
  17404. Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)));
  17405. _assertPred!"=="(interval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))),
  17406. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
  17407. _assertPred!"=="(interval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))),
  17408. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
  17409. _assertPred!"=="(interval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))),
  17410. Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)));
  17411. _assertPred!"=="(interval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))),
  17412. Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)));
  17413. _assertPred!"=="(interval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))),
  17414. Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
  17415. _assertPred!"=="(interval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))),
  17416. Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
  17417. _assertPred!"=="(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).intersection(interval),
  17418. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
  17419. _assertPred!"=="(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).intersection(interval),
  17420. Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)));
  17421. _assertPred!"=="(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).intersection(interval),
  17422. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
  17423. _assertPred!"=="(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).intersection(interval),
  17424. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
  17425. _assertPred!"=="(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).intersection(interval),
  17426. Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)));
  17427. _assertPred!"=="(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).intersection(interval),
  17428. Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)));
  17429. _assertPred!"=="(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).intersection(interval),
  17430. Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
  17431. _assertPred!"=="(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).intersection(interval),
  17432. Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
  17433. _assertPred!"=="(interval.intersection(PosInfInterval!Date(Date(2010, 7, 3))),
  17434. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
  17435. _assertPred!"=="(interval.intersection(PosInfInterval!Date(Date(2010, 7, 4))),
  17436. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
  17437. _assertPred!"=="(interval.intersection(PosInfInterval!Date(Date(2010, 7, 5))),
  17438. Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)));
  17439. _assertPred!"=="(interval.intersection(PosInfInterval!Date(Date(2012, 1, 6))),
  17440. Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
  17441. _assertPred!"=="(interval.intersection(NegInfInterval!Date(Date(2010, 7, 5))),
  17442. Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)));
  17443. _assertPred!"=="(interval.intersection(NegInfInterval!Date(Date(2012, 1, 6))),
  17444. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 6)));
  17445. _assertPred!"=="(interval.intersection(NegInfInterval!Date(Date(2012, 1, 7))),
  17446. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
  17447. _assertPred!"=="(interval.intersection(NegInfInterval!Date(Date(2012, 1, 8))),
  17448. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
  17449. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17450. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17451. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  17452. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  17453. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  17454. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  17455. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  17456. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  17457. static assert(__traits(compiles, interval.intersection(interval)));
  17458. static assert(__traits(compiles, interval.intersection(cInterval)));
  17459. static assert(__traits(compiles, interval.intersection(iInterval)));
  17460. static assert(__traits(compiles, interval.intersection(posInfInterval)));
  17461. static assert(__traits(compiles, interval.intersection(cPosInfInterval)));
  17462. static assert(__traits(compiles, interval.intersection(iPosInfInterval)));
  17463. static assert(__traits(compiles, interval.intersection(negInfInterval)));
  17464. static assert(__traits(compiles, interval.intersection(cNegInfInterval)));
  17465. static assert(__traits(compiles, interval.intersection(iNegInfInterval)));
  17466. static assert(__traits(compiles, cInterval.intersection(interval)));
  17467. static assert(__traits(compiles, cInterval.intersection(cInterval)));
  17468. static assert(__traits(compiles, cInterval.intersection(iInterval)));
  17469. static assert(__traits(compiles, cInterval.intersection(posInfInterval)));
  17470. static assert(__traits(compiles, cInterval.intersection(cPosInfInterval)));
  17471. static assert(__traits(compiles, cInterval.intersection(iPosInfInterval)));
  17472. static assert(__traits(compiles, cInterval.intersection(negInfInterval)));
  17473. static assert(__traits(compiles, cInterval.intersection(cNegInfInterval)));
  17474. static assert(__traits(compiles, cInterval.intersection(iNegInfInterval)));
  17475. static assert(__traits(compiles, iInterval.intersection(interval)));
  17476. static assert(__traits(compiles, iInterval.intersection(cInterval)));
  17477. static assert(__traits(compiles, iInterval.intersection(iInterval)));
  17478. static assert(__traits(compiles, iInterval.intersection(posInfInterval)));
  17479. static assert(__traits(compiles, iInterval.intersection(cPosInfInterval)));
  17480. static assert(__traits(compiles, iInterval.intersection(iPosInfInterval)));
  17481. static assert(__traits(compiles, iInterval.intersection(negInfInterval)));
  17482. static assert(__traits(compiles, iInterval.intersection(cNegInfInterval)));
  17483. static assert(__traits(compiles, iInterval.intersection(iNegInfInterval)));
  17484. //Verify Examples.
  17485. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) == Interval!Date(Date(1996, 1 , 2), Date(2000, 8, 2)));
  17486. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) == Interval!Date(Date(1999, 1 , 12), Date(2011, 9, 17)));
  17487. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(PosInfInterval!Date(Date(1990, 7, 6))) == Interval!Date(Date(1996, 1 , 2), Date(2012, 3, 1)));
  17488. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(PosInfInterval!Date(Date(1999, 1, 12))) == Interval!Date(Date(1999, 1 , 12), Date(2012, 3, 1)));
  17489. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(NegInfInterval!Date(Date(1999, 7, 6))) == Interval!Date(Date(1996, 1 , 2), Date(1999, 7, 6)));
  17490. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(NegInfInterval!Date(Date(2013, 1, 12))) == Interval!Date(Date(1996, 1 , 2), Date(2012, 3, 1)));
  17491. }
  17492. }
  17493. //Test Interval's isAdjacent().
  17494. unittest
  17495. {
  17496. version(testStdDateTime)
  17497. {
  17498. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17499. static void testInterval(in Interval!Date interval1, in Interval!Date interval2)
  17500. {
  17501. interval1.isAdjacent(interval2);
  17502. }
  17503. assertThrown!DateTimeException(testInterval(interval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  17504. assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), interval));
  17505. assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  17506. assert(!interval.isAdjacent(interval));
  17507. assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
  17508. assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
  17509. assert(interval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
  17510. assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
  17511. assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
  17512. assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
  17513. assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
  17514. assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
  17515. assert(!interval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
  17516. assert(!interval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
  17517. assert(interval.isAdjacent(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
  17518. assert(!interval.isAdjacent(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
  17519. assert(!Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).isAdjacent(interval));
  17520. assert(!Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).isAdjacent(interval));
  17521. assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).isAdjacent(interval));
  17522. assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).isAdjacent(interval));
  17523. assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).isAdjacent(interval));
  17524. assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).isAdjacent(interval));
  17525. assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).isAdjacent(interval));
  17526. assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).isAdjacent(interval));
  17527. assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).isAdjacent(interval));
  17528. assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).isAdjacent(interval));
  17529. assert(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).isAdjacent(interval));
  17530. assert(!Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).isAdjacent(interval));
  17531. assert(!interval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 3))));
  17532. assert(!interval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 4))));
  17533. assert(!interval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 5))));
  17534. assert(!interval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 6))));
  17535. assert(interval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 7))));
  17536. assert(!interval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 8))));
  17537. assert(!interval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 3))));
  17538. assert(interval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 4))));
  17539. assert(!interval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 5))));
  17540. assert(!interval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 6))));
  17541. assert(!interval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 7))));
  17542. assert(!interval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 8))));
  17543. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17544. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17545. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  17546. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  17547. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  17548. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  17549. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  17550. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  17551. static assert(__traits(compiles, interval.isAdjacent(interval)));
  17552. static assert(__traits(compiles, interval.isAdjacent(cInterval)));
  17553. static assert(__traits(compiles, interval.isAdjacent(iInterval)));
  17554. static assert(__traits(compiles, interval.isAdjacent(posInfInterval)));
  17555. static assert(__traits(compiles, interval.isAdjacent(cPosInfInterval)));
  17556. static assert(__traits(compiles, interval.isAdjacent(iPosInfInterval)));
  17557. static assert(__traits(compiles, interval.isAdjacent(negInfInterval)));
  17558. static assert(__traits(compiles, interval.isAdjacent(cNegInfInterval)));
  17559. static assert(__traits(compiles, interval.isAdjacent(iNegInfInterval)));
  17560. static assert(__traits(compiles, cInterval.isAdjacent(interval)));
  17561. static assert(__traits(compiles, cInterval.isAdjacent(cInterval)));
  17562. static assert(__traits(compiles, cInterval.isAdjacent(iInterval)));
  17563. static assert(__traits(compiles, cInterval.isAdjacent(posInfInterval)));
  17564. static assert(__traits(compiles, cInterval.isAdjacent(cPosInfInterval)));
  17565. static assert(__traits(compiles, cInterval.isAdjacent(iPosInfInterval)));
  17566. static assert(__traits(compiles, cInterval.isAdjacent(negInfInterval)));
  17567. static assert(__traits(compiles, cInterval.isAdjacent(cNegInfInterval)));
  17568. static assert(__traits(compiles, cInterval.isAdjacent(iNegInfInterval)));
  17569. static assert(__traits(compiles, iInterval.isAdjacent(interval)));
  17570. static assert(__traits(compiles, iInterval.isAdjacent(cInterval)));
  17571. static assert(__traits(compiles, iInterval.isAdjacent(iInterval)));
  17572. static assert(__traits(compiles, iInterval.isAdjacent(posInfInterval)));
  17573. static assert(__traits(compiles, iInterval.isAdjacent(cPosInfInterval)));
  17574. static assert(__traits(compiles, iInterval.isAdjacent(iPosInfInterval)));
  17575. static assert(__traits(compiles, iInterval.isAdjacent(negInfInterval)));
  17576. static assert(__traits(compiles, iInterval.isAdjacent(cNegInfInterval)));
  17577. static assert(__traits(compiles, iInterval.isAdjacent(iNegInfInterval)));
  17578. //Verify Examples.
  17579. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(1990, 7, 6), Date(1996, 1, 2))));
  17580. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(2012, 3, 1), Date(2013, 9, 17))));
  17581. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(1989, 3, 1), Date(2012, 3, 1))));
  17582. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(PosInfInterval!Date(Date(1999, 5, 4))));
  17583. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(PosInfInterval!Date(Date(2012, 3, 1))));
  17584. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(NegInfInterval!Date(Date(1996, 1, 2))));
  17585. assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(NegInfInterval!Date(Date(2000, 1, 2))));
  17586. }
  17587. }
  17588. //Test Interval's merge().
  17589. unittest
  17590. {
  17591. version(testStdDateTime)
  17592. {
  17593. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17594. static void testInterval(I)(in Interval!Date interval1, in I interval2)
  17595. {
  17596. interval1.merge(interval2);
  17597. }
  17598. assertThrown!DateTimeException(testInterval(interval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  17599. assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), interval));
  17600. assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  17601. assertThrown!DateTimeException(testInterval(interval, Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
  17602. assertThrown!DateTimeException(testInterval(interval, Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
  17603. assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)), interval));
  17604. assertThrown!DateTimeException(testInterval(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)), interval));
  17605. assertThrown!DateTimeException(testInterval(interval, PosInfInterval!Date(Date(2012, 1, 8))));
  17606. assertThrown!DateTimeException(testInterval(interval, NegInfInterval!Date(Date(2010, 7, 3))));
  17607. _assertPred!"=="(interval.merge(interval), interval);
  17608. _assertPred!"=="(interval.merge(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))),
  17609. Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)));
  17610. _assertPred!"=="(interval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))),
  17611. Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
  17612. _assertPred!"=="(interval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))),
  17613. Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
  17614. _assertPred!"=="(interval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))),
  17615. Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
  17616. _assertPred!"=="(interval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))),
  17617. Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)));
  17618. _assertPred!"=="(interval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))),
  17619. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
  17620. _assertPred!"=="(interval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))),
  17621. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
  17622. _assertPred!"=="(interval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))),
  17623. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
  17624. _assertPred!"=="(interval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))),
  17625. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
  17626. _assertPred!"=="(interval.merge(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))),
  17627. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
  17628. _assertPred!"=="(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).merge(interval),
  17629. Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)));
  17630. _assertPred!"=="(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).merge(interval),
  17631. Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
  17632. _assertPred!"=="(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).merge(interval),
  17633. Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
  17634. _assertPred!"=="(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).merge(interval),
  17635. Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
  17636. _assertPred!"=="(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).merge(interval),
  17637. Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)));
  17638. _assertPred!"=="(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).merge(interval),
  17639. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
  17640. _assertPred!"=="(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).merge(interval),
  17641. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
  17642. _assertPred!"=="(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).merge(interval),
  17643. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
  17644. _assertPred!"=="(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).merge(interval),
  17645. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
  17646. _assertPred!"=="(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).merge(interval),
  17647. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
  17648. _assertPred!"=="(interval.merge(PosInfInterval!Date(Date(2010, 7, 3))),
  17649. PosInfInterval!Date(Date(2010, 7, 3)));
  17650. _assertPred!"=="(interval.merge(PosInfInterval!Date(Date(2010, 7, 4))),
  17651. PosInfInterval!Date(Date(2010, 7, 4)));
  17652. _assertPred!"=="(interval.merge(PosInfInterval!Date(Date(2010, 7, 5))),
  17653. PosInfInterval!Date(Date(2010, 7, 4)));
  17654. _assertPred!"=="(interval.merge(PosInfInterval!Date(Date(2012, 1, 6))),
  17655. PosInfInterval!Date(Date(2010, 7, 4)));
  17656. _assertPred!"=="(interval.merge(PosInfInterval!Date(Date(2012, 1, 7))),
  17657. PosInfInterval!Date(Date(2010, 7, 4)));
  17658. _assertPred!"=="(interval.merge(NegInfInterval!Date(Date(2010, 7, 4))),
  17659. NegInfInterval!Date(Date(2012, 1, 7)));
  17660. _assertPred!"=="(interval.merge(NegInfInterval!Date(Date(2010, 7, 5))),
  17661. NegInfInterval!Date(Date(2012, 1, 7)));
  17662. _assertPred!"=="(interval.merge(NegInfInterval!Date(Date(2012, 1, 6))),
  17663. NegInfInterval!Date(Date(2012, 1, 7)));
  17664. _assertPred!"=="(interval.merge(NegInfInterval!Date(Date(2012, 1, 7))),
  17665. NegInfInterval!Date(Date(2012, 1, 7)));
  17666. _assertPred!"=="(interval.merge(NegInfInterval!Date(Date(2012, 1, 8))),
  17667. NegInfInterval!Date(Date(2012, 1, 8)));
  17668. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17669. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17670. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  17671. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  17672. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  17673. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  17674. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  17675. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  17676. static assert(__traits(compiles, interval.merge(interval)));
  17677. static assert(__traits(compiles, interval.merge(cInterval)));
  17678. static assert(__traits(compiles, interval.merge(iInterval)));
  17679. static assert(__traits(compiles, interval.merge(posInfInterval)));
  17680. static assert(__traits(compiles, interval.merge(cPosInfInterval)));
  17681. static assert(__traits(compiles, interval.merge(iPosInfInterval)));
  17682. static assert(__traits(compiles, interval.merge(negInfInterval)));
  17683. static assert(__traits(compiles, interval.merge(cNegInfInterval)));
  17684. static assert(__traits(compiles, interval.merge(iNegInfInterval)));
  17685. static assert(__traits(compiles, cInterval.merge(interval)));
  17686. static assert(__traits(compiles, cInterval.merge(cInterval)));
  17687. static assert(__traits(compiles, cInterval.merge(iInterval)));
  17688. static assert(__traits(compiles, cInterval.merge(posInfInterval)));
  17689. static assert(__traits(compiles, cInterval.merge(cPosInfInterval)));
  17690. static assert(__traits(compiles, cInterval.merge(iPosInfInterval)));
  17691. static assert(__traits(compiles, cInterval.merge(negInfInterval)));
  17692. static assert(__traits(compiles, cInterval.merge(cNegInfInterval)));
  17693. static assert(__traits(compiles, cInterval.merge(iNegInfInterval)));
  17694. static assert(__traits(compiles, iInterval.merge(interval)));
  17695. static assert(__traits(compiles, iInterval.merge(cInterval)));
  17696. static assert(__traits(compiles, iInterval.merge(iInterval)));
  17697. static assert(__traits(compiles, iInterval.merge(posInfInterval)));
  17698. static assert(__traits(compiles, iInterval.merge(cPosInfInterval)));
  17699. static assert(__traits(compiles, iInterval.merge(iPosInfInterval)));
  17700. static assert(__traits(compiles, iInterval.merge(negInfInterval)));
  17701. static assert(__traits(compiles, iInterval.merge(cNegInfInterval)));
  17702. static assert(__traits(compiles, iInterval.merge(iNegInfInterval)));
  17703. //Verify Examples.
  17704. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) == Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
  17705. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(Interval!Date(Date(2012, 3, 1), Date(2013, 5, 7))) == Interval!Date(Date(1996, 1 , 2), Date(2013, 5, 7)));
  17706. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(PosInfInterval!Date(Date(1990, 7, 6))) == PosInfInterval!Date(Date(1990, 7 , 6)));
  17707. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(PosInfInterval!Date(Date(2012, 3, 1))) == PosInfInterval!Date(Date(1996, 1 , 2)));
  17708. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(NegInfInterval!Date(Date(1996, 1, 2))) == NegInfInterval!Date(Date(2012, 3 , 1)));
  17709. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(NegInfInterval!Date(Date(2013, 1, 12))) == NegInfInterval!Date(Date(2013, 1 , 12)));
  17710. }
  17711. }
  17712. //Test Interval's span().
  17713. unittest
  17714. {
  17715. version(testStdDateTime)
  17716. {
  17717. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17718. static void testInterval(in Interval!Date interval1, in Interval!Date interval2)
  17719. {
  17720. interval1.span(interval2);
  17721. }
  17722. assertThrown!DateTimeException(testInterval(interval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  17723. assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), interval));
  17724. assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  17725. _assertPred!"=="(interval.span(interval), interval);
  17726. _assertPred!"=="(interval.span(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))),
  17727. Interval!Date(Date(2010, 7, 1), Date(2012, 1, 7)));
  17728. _assertPred!"=="(interval.span(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))),
  17729. Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)));
  17730. _assertPred!"=="(interval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))),
  17731. Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
  17732. _assertPred!"=="(interval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))),
  17733. Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
  17734. _assertPred!"=="(interval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))),
  17735. Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
  17736. _assertPred!"=="(interval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))),
  17737. Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)));
  17738. _assertPred!"=="(interval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))),
  17739. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
  17740. _assertPred!"=="(interval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))),
  17741. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
  17742. _assertPred!"=="(interval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))),
  17743. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
  17744. _assertPred!"=="(interval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))),
  17745. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
  17746. _assertPred!"=="(interval.span(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))),
  17747. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
  17748. _assertPred!"=="(interval.span(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))),
  17749. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 9)));
  17750. _assertPred!"=="(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).span(interval),
  17751. Interval!Date(Date(2010, 7, 1), Date(2012, 1, 7)));
  17752. _assertPred!"=="(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).span(interval),
  17753. Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)));
  17754. _assertPred!"=="(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).span(interval),
  17755. Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
  17756. _assertPred!"=="(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).span(interval),
  17757. Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
  17758. _assertPred!"=="(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).span(interval),
  17759. Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
  17760. _assertPred!"=="(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).span(interval),
  17761. Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)));
  17762. _assertPred!"=="(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).span(interval),
  17763. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
  17764. _assertPred!"=="(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).span(interval),
  17765. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
  17766. _assertPred!"=="(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).span(interval),
  17767. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
  17768. _assertPred!"=="(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).span(interval),
  17769. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
  17770. _assertPred!"=="(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).span(interval),
  17771. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
  17772. _assertPred!"=="(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).span(interval),
  17773. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 9)));
  17774. _assertPred!"=="(interval.span(PosInfInterval!Date(Date(2010, 7, 3))),
  17775. PosInfInterval!Date(Date(2010, 7, 3)));
  17776. _assertPred!"=="(interval.span(PosInfInterval!Date(Date(2010, 7, 4))),
  17777. PosInfInterval!Date(Date(2010, 7, 4)));
  17778. _assertPred!"=="(interval.span(PosInfInterval!Date(Date(2010, 7, 5))),
  17779. PosInfInterval!Date(Date(2010, 7, 4)));
  17780. _assertPred!"=="(interval.span(PosInfInterval!Date(Date(2012, 1, 6))),
  17781. PosInfInterval!Date(Date(2010, 7, 4)));
  17782. _assertPred!"=="(interval.span(PosInfInterval!Date(Date(2012, 1, 7))),
  17783. PosInfInterval!Date(Date(2010, 7, 4)));
  17784. _assertPred!"=="(interval.span(PosInfInterval!Date(Date(2012, 1, 8))),
  17785. PosInfInterval!Date(Date(2010, 7, 4)));
  17786. _assertPred!"=="(interval.span(NegInfInterval!Date(Date(2010, 7, 3))),
  17787. NegInfInterval!Date(Date(2012, 1, 7)));
  17788. _assertPred!"=="(interval.span(NegInfInterval!Date(Date(2010, 7, 4))),
  17789. NegInfInterval!Date(Date(2012, 1, 7)));
  17790. _assertPred!"=="(interval.span(NegInfInterval!Date(Date(2010, 7, 5))),
  17791. NegInfInterval!Date(Date(2012, 1, 7)));
  17792. _assertPred!"=="(interval.span(NegInfInterval!Date(Date(2012, 1, 6))),
  17793. NegInfInterval!Date(Date(2012, 1, 7)));
  17794. _assertPred!"=="(interval.span(NegInfInterval!Date(Date(2012, 1, 7))),
  17795. NegInfInterval!Date(Date(2012, 1, 7)));
  17796. _assertPred!"=="(interval.span(NegInfInterval!Date(Date(2012, 1, 8))),
  17797. NegInfInterval!Date(Date(2012, 1, 8)));
  17798. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17799. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17800. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  17801. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  17802. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  17803. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  17804. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  17805. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  17806. static assert(__traits(compiles, interval.span(interval)));
  17807. static assert(__traits(compiles, interval.span(cInterval)));
  17808. static assert(__traits(compiles, interval.span(iInterval)));
  17809. static assert(__traits(compiles, interval.span(posInfInterval)));
  17810. static assert(__traits(compiles, interval.span(cPosInfInterval)));
  17811. static assert(__traits(compiles, interval.span(iPosInfInterval)));
  17812. static assert(__traits(compiles, interval.span(negInfInterval)));
  17813. static assert(__traits(compiles, interval.span(cNegInfInterval)));
  17814. static assert(__traits(compiles, interval.span(iNegInfInterval)));
  17815. static assert(__traits(compiles, cInterval.span(interval)));
  17816. static assert(__traits(compiles, cInterval.span(cInterval)));
  17817. static assert(__traits(compiles, cInterval.span(iInterval)));
  17818. static assert(__traits(compiles, cInterval.span(posInfInterval)));
  17819. static assert(__traits(compiles, cInterval.span(cPosInfInterval)));
  17820. static assert(__traits(compiles, cInterval.span(iPosInfInterval)));
  17821. static assert(__traits(compiles, cInterval.span(negInfInterval)));
  17822. static assert(__traits(compiles, cInterval.span(cNegInfInterval)));
  17823. static assert(__traits(compiles, cInterval.span(iNegInfInterval)));
  17824. static assert(__traits(compiles, iInterval.span(interval)));
  17825. static assert(__traits(compiles, iInterval.span(cInterval)));
  17826. static assert(__traits(compiles, iInterval.span(iInterval)));
  17827. static assert(__traits(compiles, iInterval.span(posInfInterval)));
  17828. static assert(__traits(compiles, iInterval.span(cPosInfInterval)));
  17829. static assert(__traits(compiles, iInterval.span(iPosInfInterval)));
  17830. static assert(__traits(compiles, iInterval.span(negInfInterval)));
  17831. static assert(__traits(compiles, iInterval.span(cNegInfInterval)));
  17832. static assert(__traits(compiles, iInterval.span(iNegInfInterval)));
  17833. //Verify Examples.
  17834. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(Interval!Date(Date(1990, 7, 6), Date(1991, 1, 8))) == Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
  17835. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(Interval!Date(Date(2012, 3, 1), Date(2013, 5, 7))) == Interval!Date(Date(1996, 1 , 2), Date(2013, 5, 7)));
  17836. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(PosInfInterval!Date(Date(1990, 7, 6))) == PosInfInterval!Date(Date(1990, 7 , 6)));
  17837. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(PosInfInterval!Date(Date(2050, 1, 1))) == PosInfInterval!Date(Date(1996, 1 , 2)));
  17838. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(NegInfInterval!Date(Date(1602, 5, 21))) == NegInfInterval!Date(Date(2012, 3 , 1)));
  17839. assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(NegInfInterval!Date(Date(2013, 1, 12))) == NegInfInterval!Date(Date(2013, 1 , 12)));
  17840. }
  17841. }
  17842. //Test Interval's shift(duration).
  17843. unittest
  17844. {
  17845. version(testStdDateTime)
  17846. {
  17847. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17848. static void testIntervalFail(Interval!Date interval, in Duration duration)
  17849. {
  17850. interval.shift(duration);
  17851. }
  17852. assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), dur!"days"(1)));
  17853. static void testInterval(I)(I interval, in Duration duration, in I expected, size_t line = __LINE__)
  17854. {
  17855. interval.shift(duration);
  17856. _assertPred!"=="(interval, expected, "", __FILE__, line);
  17857. }
  17858. testInterval(interval, dur!"days"(22), Interval!Date(Date(2010, 7, 26), Date(2012, 1, 29)));
  17859. testInterval(interval, dur!"days"(-22), Interval!Date(Date(2010, 6, 12), Date(2011, 12, 16)));
  17860. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17861. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17862. static assert(!__traits(compiles, cInterval.shift(dur!"days"(5))));
  17863. static assert(!__traits(compiles, iInterval.shift(dur!"days"(5))));
  17864. //Verify Examples.
  17865. auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 4, 5));
  17866. auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 4, 5));
  17867. interval1.shift(dur!"days"(50));
  17868. assert(interval1 == Interval!Date(Date(1996, 2, 21), Date(2012, 5, 25)));
  17869. interval2.shift(dur!"days"(-50));
  17870. assert(interval2 == Interval!Date(Date(1995, 11, 13), Date(2012, 2, 15)));
  17871. }
  17872. }
  17873. //Test Interval's shift(int, int, AllowDayOverflow).
  17874. unittest
  17875. {
  17876. version(testStdDateTime)
  17877. {
  17878. {
  17879. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17880. static void testIntervalFail(Interval!Date interval, int years, int months)
  17881. {
  17882. interval.shift(years, months);
  17883. }
  17884. assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), 1, 0));
  17885. static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow, in I expected, size_t line = __LINE__)
  17886. {
  17887. interval.shift(years, months, allow);
  17888. _assertPred!"=="(interval, expected, "", __FILE__, line);
  17889. }
  17890. testInterval(interval, 5, 0, AllowDayOverflow.yes, Interval!Date(Date(2015, 7, 4), Date(2017, 1, 7)));
  17891. testInterval(interval, -5, 0, AllowDayOverflow.yes, Interval!Date(Date(2005, 7, 4), Date(2007, 1, 7)));
  17892. auto interval2 = Interval!Date(Date(2000, 1, 29), Date(2010, 5, 31));
  17893. testInterval(interval2, 1, 1, AllowDayOverflow.yes, Interval!Date(Date(2001, 3, 1), Date(2011, 7, 1)));
  17894. testInterval(interval2, 1, -1, AllowDayOverflow.yes, Interval!Date(Date(2000, 12, 29), Date(2011, 5, 1)));
  17895. testInterval(interval2, -1, -1, AllowDayOverflow.yes, Interval!Date(Date(1998, 12, 29), Date(2009, 5, 1)));
  17896. testInterval(interval2, -1, 1, AllowDayOverflow.yes, Interval!Date(Date(1999, 3, 1), Date(2009, 7, 1)));
  17897. testInterval(interval2, 1, 1, AllowDayOverflow.no, Interval!Date(Date(2001, 2, 28), Date(2011, 6, 30)));
  17898. testInterval(interval2, 1, -1, AllowDayOverflow.no, Interval!Date(Date(2000, 12, 29), Date(2011, 4, 30)));
  17899. testInterval(interval2, -1, -1, AllowDayOverflow.no, Interval!Date(Date(1998, 12, 29), Date(2009, 4, 30)));
  17900. testInterval(interval2, -1, 1, AllowDayOverflow.no, Interval!Date(Date(1999, 2, 28), Date(2009, 6, 30)));
  17901. }
  17902. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17903. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17904. static assert(!__traits(compiles, cInterval.shift(5)));
  17905. static assert(!__traits(compiles, iInterval.shift(5)));
  17906. //Verify Examples.
  17907. auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
  17908. auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
  17909. interval1.shift(2);
  17910. assert(interval1 == Interval!Date(Date(1998, 1, 2), Date(2014, 3, 1)));
  17911. interval2.shift(-2);
  17912. assert(interval2 == Interval!Date(Date(1994, 1, 2), Date(2010, 3, 1)));
  17913. }
  17914. }
  17915. //Test Interval's expand(Duration).
  17916. unittest
  17917. {
  17918. version(testStdDateTime)
  17919. {
  17920. auto interval = Interval!Date(Date(2000, 7, 4), Date(2012, 1, 7));
  17921. static void testIntervalFail(I)(I interval, in Duration duration)
  17922. {
  17923. interval.expand(duration);
  17924. }
  17925. assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), dur!"days"(1)));
  17926. assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)), dur!"days"(-5)));
  17927. static void testInterval(I)(I interval, in Duration duration, in I expected, size_t line = __LINE__)
  17928. {
  17929. interval.expand(duration);
  17930. _assertPred!"=="(interval, expected, "", __FILE__, line);
  17931. }
  17932. testInterval(interval, dur!"days"(22), Interval!Date(Date(2000, 6, 12), Date(2012, 1, 29)));
  17933. testInterval(interval, dur!"days"(-22), Interval!Date(Date(2000, 7, 26), Date(2011, 12, 16)));
  17934. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17935. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17936. static assert(!__traits(compiles, cInterval.expand(dur!"days"(5))));
  17937. static assert(!__traits(compiles, iInterval.expand(dur!"days"(5))));
  17938. //Verify Examples.
  17939. auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
  17940. auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
  17941. interval1.expand(dur!"days"(2));
  17942. assert(interval1 == Interval!Date(Date(1995, 12, 31), Date(2012, 3, 3)));
  17943. interval2.expand(dur!"days"(-2));
  17944. assert(interval2 == Interval!Date(Date(1996, 1, 4), Date(2012, 2, 28)));
  17945. }
  17946. }
  17947. //Test Interval's expand(int, int, AllowDayOverflow, Direction)
  17948. unittest
  17949. {
  17950. version(testStdDateTime)
  17951. {
  17952. {
  17953. auto interval = Interval!Date(Date(2000, 7, 4), Date(2012, 1, 7));
  17954. static void testIntervalFail(Interval!Date interval, int years, int months)
  17955. {
  17956. interval.expand(years, months);
  17957. }
  17958. assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), 1, 0));
  17959. assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)), -5, 0));
  17960. static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow, Direction dir, in I expected, size_t line = __LINE__)
  17961. {
  17962. interval.expand(years, months, allow, dir);
  17963. _assertPred!"=="(interval, expected, "", __FILE__, line);
  17964. }
  17965. testInterval(interval, 5, 0, AllowDayOverflow.yes, Direction.both, Interval!Date(Date(1995, 7, 4), Date(2017, 1, 7)));
  17966. testInterval(interval, -5, 0, AllowDayOverflow.yes, Direction.both, Interval!Date(Date(2005, 7, 4), Date(2007, 1, 7)));
  17967. testInterval(interval, 5, 0, AllowDayOverflow.yes, Direction.fwd, Interval!Date(Date(2000, 7, 4), Date(2017, 1, 7)));
  17968. testInterval(interval, -5, 0, AllowDayOverflow.yes, Direction.fwd, Interval!Date(Date(2000, 7, 4), Date(2007, 1, 7)));
  17969. testInterval(interval, 5, 0, AllowDayOverflow.yes, Direction.bwd, Interval!Date(Date(1995, 7, 4), Date(2012, 1, 7)));
  17970. testInterval(interval, -5, 0, AllowDayOverflow.yes, Direction.bwd, Interval!Date(Date(2005, 7, 4), Date(2012, 1, 7)));
  17971. auto interval2 = Interval!Date(Date(2000, 1, 29), Date(2010, 5, 31));
  17972. testInterval(interval2, 1, 1, AllowDayOverflow.yes, Direction.both, Interval!Date(Date(1998, 12, 29), Date(2011, 7, 1)));
  17973. testInterval(interval2, 1, -1, AllowDayOverflow.yes, Direction.both, Interval!Date(Date(1999, 3, 1), Date(2011, 5, 1)));
  17974. testInterval(interval2, -1, -1, AllowDayOverflow.yes, Direction.both, Interval!Date(Date(2001, 3, 1), Date(2009, 5, 1)));
  17975. testInterval(interval2, -1, 1, AllowDayOverflow.yes, Direction.both, Interval!Date(Date(2000, 12, 29), Date(2009, 7, 1)));
  17976. testInterval(interval2, 1, 1, AllowDayOverflow.no, Direction.both, Interval!Date(Date(1998, 12, 29), Date(2011, 6, 30)));
  17977. testInterval(interval2, 1, -1, AllowDayOverflow.no, Direction.both, Interval!Date(Date(1999, 2, 28), Date(2011, 4, 30)));
  17978. testInterval(interval2, -1, -1, AllowDayOverflow.no, Direction.both, Interval!Date(Date(2001, 2, 28), Date(2009, 4, 30)));
  17979. testInterval(interval2, -1, 1, AllowDayOverflow.no, Direction.both, Interval!Date(Date(2000, 12, 29), Date(2009, 6, 30)));
  17980. testInterval(interval2, 1, 1, AllowDayOverflow.yes, Direction.fwd, Interval!Date(Date(2000, 1, 29), Date(2011, 7, 1)));
  17981. testInterval(interval2, 1, -1, AllowDayOverflow.yes, Direction.fwd, Interval!Date(Date(2000, 1, 29), Date(2011, 5, 1)));
  17982. testInterval(interval2, -1, -1, AllowDayOverflow.yes, Direction.fwd, Interval!Date(Date(2000, 1, 29), Date(2009, 5, 1)));
  17983. testInterval(interval2, -1, 1, AllowDayOverflow.yes, Direction.fwd, Interval!Date(Date(2000, 1, 29), Date(2009, 7, 1)));
  17984. testInterval(interval2, 1, 1, AllowDayOverflow.no, Direction.fwd, Interval!Date(Date(2000, 1, 29), Date(2011, 6, 30)));
  17985. testInterval(interval2, 1, -1, AllowDayOverflow.no, Direction.fwd, Interval!Date(Date(2000, 1, 29), Date(2011, 4, 30)));
  17986. testInterval(interval2, -1, -1, AllowDayOverflow.no, Direction.fwd, Interval!Date(Date(2000, 1, 29), Date(2009, 4, 30)));
  17987. testInterval(interval2, -1, 1, AllowDayOverflow.no, Direction.fwd, Interval!Date(Date(2000, 1, 29), Date(2009, 6, 30)));
  17988. testInterval(interval2, 1, 1, AllowDayOverflow.yes, Direction.bwd, Interval!Date(Date(1998, 12, 29), Date(2010, 5, 31)));
  17989. testInterval(interval2, 1, -1, AllowDayOverflow.yes, Direction.bwd, Interval!Date(Date(1999, 3, 1), Date(2010, 5, 31)));
  17990. testInterval(interval2, -1, -1, AllowDayOverflow.yes, Direction.bwd, Interval!Date(Date(2001, 3, 1), Date(2010, 5, 31)));
  17991. testInterval(interval2, -1, 1, AllowDayOverflow.yes, Direction.bwd, Interval!Date(Date(2000, 12, 29), Date(2010, 5, 31)));
  17992. testInterval(interval2, 1, 1, AllowDayOverflow.no, Direction.bwd, Interval!Date(Date(1998, 12, 29), Date(2010, 5, 31)));
  17993. testInterval(interval2, 1, -1, AllowDayOverflow.no, Direction.bwd, Interval!Date(Date(1999, 2, 28), Date(2010, 5, 31)));
  17994. testInterval(interval2, -1, -1, AllowDayOverflow.no, Direction.bwd, Interval!Date(Date(2001, 2, 28), Date(2010, 5, 31)));
  17995. testInterval(interval2, -1, 1, AllowDayOverflow.no, Direction.bwd, Interval!Date(Date(2000, 12, 29), Date(2010, 5, 31)));
  17996. }
  17997. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17998. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  17999. static assert(!__traits(compiles, cInterval.expand(5)));
  18000. static assert(!__traits(compiles, iInterval.expand(5)));
  18001. //Verify Examples.
  18002. auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
  18003. auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
  18004. interval1.expand(2);
  18005. assert(interval1 == Interval!Date(Date(1994, 1, 2), Date(2014, 3, 1)));
  18006. interval2.expand(-2);
  18007. assert(interval2 == Interval!Date(Date(1998, 1, 2), Date(2010, 3, 1)));
  18008. }
  18009. }
  18010. //Test Interval's fwdRange.
  18011. unittest
  18012. {
  18013. version(testStdDateTime)
  18014. {
  18015. {
  18016. auto interval = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 21));
  18017. static void testInterval1(Interval!Date interval)
  18018. {
  18019. interval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
  18020. }
  18021. assertThrown!DateTimeException(testInterval1(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  18022. static void testInterval2(Interval!Date interval)
  18023. {
  18024. interval.fwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).popFront();
  18025. }
  18026. assertThrown!DateTimeException(testInterval2(interval));
  18027. assert(!interval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).empty);
  18028. assert(interval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri), PopFirst.yes).empty);
  18029. _assertPred!"=="(Interval!Date(Date(2010, 9, 12), Date(2010, 10, 1)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).front,
  18030. Date(2010, 9, 12));
  18031. _assertPred!"=="(Interval!Date(Date(2010, 9, 12), Date(2010, 10, 1)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri), PopFirst.yes).front,
  18032. Date(2010, 9, 17));
  18033. }
  18034. //Verify Examples.
  18035. {
  18036. auto interval = Interval!Date(Date(2010, 9, 1), Date(2010, 9, 9));
  18037. auto func = (in Date date)
  18038. {
  18039. if((date.day & 1) == 0)
  18040. return date + dur!"days"(2);
  18041. return date + dur!"days"(1);
  18042. };
  18043. auto range = interval.fwdRange(func);
  18044. assert(range.front == Date(2010, 9, 1)); //An odd day. Using PopFirst.yes would have made this Date(2010, 9, 2).
  18045. range.popFront();
  18046. assert(range.front == Date(2010, 9, 2));
  18047. range.popFront();
  18048. assert(range.front == Date(2010, 9, 4));
  18049. range.popFront();
  18050. assert(range.front == Date(2010, 9, 6));
  18051. range.popFront();
  18052. assert(range.front == Date(2010, 9, 8));
  18053. range.popFront();
  18054. assert(range.empty);
  18055. }
  18056. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  18057. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  18058. static assert(__traits(compiles, cInterval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri))));
  18059. static assert(__traits(compiles, iInterval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri))));
  18060. }
  18061. }
  18062. //Test Interval's bwdRange.
  18063. unittest
  18064. {
  18065. version(testStdDateTime)
  18066. {
  18067. {
  18068. auto interval = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 21));
  18069. static void testInterval1(Interval!Date interval)
  18070. {
  18071. interval.bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
  18072. }
  18073. assertThrown!DateTimeException(testInterval1(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  18074. static void testInterval2(Interval!Date interval)
  18075. {
  18076. interval.bwdRange(everyDayOfWeek!(Date, Direction.fwd)(DayOfWeek.fri)).popFront();
  18077. }
  18078. assertThrown!DateTimeException(testInterval2(interval));
  18079. assert(!interval.bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).empty);
  18080. assert(interval.bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri), PopFirst.yes).empty);
  18081. _assertPred!"=="(Interval!Date(Date(2010, 9, 19), Date(2010, 10, 1)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).front,
  18082. Date(2010, 10, 1));
  18083. _assertPred!"=="(Interval!Date(Date(2010, 9, 19), Date(2010, 10, 1)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri), PopFirst.yes).front,
  18084. Date(2010, 9, 24));
  18085. }
  18086. //Verify Examples.
  18087. {
  18088. auto interval = Interval!Date(Date(2010, 9, 1), Date(2010, 9, 9));
  18089. auto func = (in Date date)
  18090. {
  18091. if((date.day & 1) == 0)
  18092. return date - dur!"days"(2);
  18093. return date - dur!"days"(1);
  18094. };
  18095. auto range = interval.bwdRange(func);
  18096. assert(range.front == Date(2010, 9, 9)); //An odd day. Using PopFirst.yes would have made this Date(2010, 9, 8).
  18097. range.popFront();
  18098. assert(range.front == Date(2010, 9, 8));
  18099. range.popFront();
  18100. assert(range.front == Date(2010, 9, 6));
  18101. range.popFront();
  18102. assert(range.front == Date(2010, 9, 4));
  18103. range.popFront();
  18104. assert(range.front == Date(2010, 9, 2));
  18105. range.popFront();
  18106. assert(range.empty);
  18107. }
  18108. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  18109. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  18110. static assert(__traits(compiles, cInterval.bwdRange(everyDayOfWeek!Date(DayOfWeek.fri))));
  18111. static assert(__traits(compiles, iInterval.bwdRange(everyDayOfWeek!Date(DayOfWeek.fri))));
  18112. }
  18113. }
  18114. //Test Interval's toString().
  18115. unittest
  18116. {
  18117. version(testStdDateTime)
  18118. {
  18119. _assertPred!"=="(Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).toString(), "[2010-Jul-04 - 2012-Jan-07)");
  18120. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  18121. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  18122. static assert(__traits(compiles, cInterval.toString()));
  18123. static assert(__traits(compiles, iInterval.toString()));
  18124. }
  18125. }
  18126. /++
  18127. Represents an interval of time which has positive infinity as its end point.
  18128. Any ranges which iterate over a $(D PosInfInterval) are infinite. So, the
  18129. main purpose of using $(D PosInfInterval) is to create an infinite range
  18130. which starts at a fixed point in time and goes to positive infinity.
  18131. +/
  18132. struct PosInfInterval(TP)
  18133. {
  18134. public:
  18135. /++
  18136. Params:
  18137. begin = The time point which begins the interval.
  18138. Examples:
  18139. --------------------
  18140. auto interval = PosInfInterval!Date(Date(1996, 1, 2));
  18141. --------------------
  18142. +/
  18143. this(in TP begin) pure nothrow
  18144. {
  18145. _begin = cast(TP)begin;
  18146. }
  18147. /++
  18148. Params:
  18149. rhs = The $(D PosInfInterval) to assign to this one.
  18150. +/
  18151. /+ref+/ PosInfInterval opAssign(const ref PosInfInterval rhs) pure nothrow
  18152. {
  18153. _begin = cast(TP)rhs._begin;
  18154. return this;
  18155. }
  18156. /++
  18157. Params:
  18158. rhs = The $(D PosInfInterval) to assign to this one.
  18159. +/
  18160. /+ref+/ PosInfInterval opAssign(PosInfInterval rhs) pure nothrow
  18161. {
  18162. _begin = cast(TP)rhs._begin;
  18163. return this;
  18164. }
  18165. /++
  18166. The starting point of the interval. It is included in the interval.
  18167. Examples:
  18168. --------------------
  18169. assert(PosInfInterval!Date(Date(1996, 1, 2)).begin == Date(1996, 1, 2));
  18170. --------------------
  18171. +/
  18172. @property TP begin() const pure nothrow
  18173. {
  18174. return cast(TP)_begin;
  18175. }
  18176. /++
  18177. The starting point of the interval. It is included in the interval.
  18178. Params:
  18179. timePoint = The time point to set $(D begin) to.
  18180. +/
  18181. @property void begin(TP timePoint) pure nothrow
  18182. {
  18183. _begin = timePoint;
  18184. }
  18185. /++
  18186. Whether the interval's length is 0. Always returns false.
  18187. Examples:
  18188. --------------------
  18189. assert(!PosInfInterval!Date(Date(1996, 1, 2)).empty);
  18190. --------------------
  18191. +/
  18192. @property bool empty() const pure nothrow
  18193. {
  18194. return false;
  18195. }
  18196. /++
  18197. Whether the given time point is within this interval.
  18198. Params:
  18199. timePoint = The time point to check for inclusion in this interval.
  18200. Examples:
  18201. --------------------
  18202. assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(Date(1994, 12, 24)));
  18203. assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(Date(2000, 1, 5)));
  18204. --------------------
  18205. +/
  18206. bool contains(TP timePoint) const pure nothrow
  18207. {
  18208. return timePoint >= _begin;
  18209. }
  18210. /++
  18211. Whether the given interval is completely within this interval.
  18212. Params:
  18213. interval = The interval to check for inclusion in this interval.
  18214. Throws:
  18215. $(D DateTimeException) if the given interval is empty.
  18216. Examples:
  18217. --------------------
  18218. assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(
  18219. Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  18220. assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(
  18221. Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  18222. assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(
  18223. Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
  18224. --------------------
  18225. +/
  18226. bool contains(in Interval!TP interval) const pure
  18227. {
  18228. interval._enforceNotEmpty();
  18229. return interval._begin >= _begin;
  18230. }
  18231. /++
  18232. Whether the given interval is completely within this interval.
  18233. Params:
  18234. interval = The interval to check for inclusion in this interval.
  18235. Examples:
  18236. --------------------
  18237. assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(
  18238. PosInfInterval!Date(Date(1999, 5, 4))));
  18239. assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(
  18240. PosInfInterval!Date(Date(1995, 7, 2))));
  18241. --------------------
  18242. +/
  18243. bool contains(in PosInfInterval interval) const pure nothrow
  18244. {
  18245. return interval._begin >= _begin;
  18246. }
  18247. /++
  18248. Whether the given interval is completely within this interval.
  18249. Always returns false because an interval going to positive infinity
  18250. can never contain an interval beginning at negative infinity.
  18251. Params:
  18252. interval = The interval to check for inclusion in this interval.
  18253. Examples:
  18254. --------------------
  18255. assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(
  18256. NegInfInterval!Date(Date(1996, 5, 4))));
  18257. --------------------
  18258. +/
  18259. bool contains(in NegInfInterval!TP interval) const pure nothrow
  18260. {
  18261. return false;
  18262. }
  18263. /++
  18264. Whether this interval is before the given time point.
  18265. Always returns false because an interval going to positive infinity
  18266. can never be before any time point.
  18267. Params:
  18268. timePoint = The time point to check whether this interval is before
  18269. it.
  18270. Examples:
  18271. --------------------
  18272. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Date(1994, 12, 24)));
  18273. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Date(2000, 1, 5)));
  18274. --------------------
  18275. +/
  18276. bool isBefore(in TP timePoint) const pure nothrow
  18277. {
  18278. return false;
  18279. }
  18280. /++
  18281. Whether this interval is before the given interval and does not
  18282. intersect it.
  18283. Always returns false (unless the given interval is empty) because an
  18284. interval going to positive infinity can never be before any other
  18285. interval.
  18286. Params:
  18287. interval = The interval to check for against this interval.
  18288. Throws:
  18289. $(D DateTimeException) if the given interval is empty.
  18290. Examples:
  18291. --------------------
  18292. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(
  18293. Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  18294. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(
  18295. Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  18296. --------------------
  18297. +/
  18298. bool isBefore(in Interval!TP interval) const pure
  18299. {
  18300. interval._enforceNotEmpty();
  18301. return false;
  18302. }
  18303. /++
  18304. Whether this interval is before the given interval and does not
  18305. intersect it.
  18306. Always returns false because an interval going to positive infinity can
  18307. never be before any other interval.
  18308. Params:
  18309. interval = The interval to check for against this interval.
  18310. Examples:
  18311. --------------------
  18312. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(
  18313. PosInfInterval!Date(Date(1992, 5, 4))));
  18314. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(
  18315. PosInfInterval!Date(Date(2013, 3, 7))));
  18316. --------------------
  18317. +/
  18318. bool isBefore(in PosInfInterval interval) const pure nothrow
  18319. {
  18320. return false;
  18321. }
  18322. /++
  18323. Whether this interval is before the given interval and does not
  18324. intersect it.
  18325. Always returns false because an interval going to positive infinity can
  18326. never be before any other interval.
  18327. Params:
  18328. interval = The interval to check for against this interval.
  18329. Examples:
  18330. --------------------
  18331. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(
  18332. NegInfInterval!Date(Date(1996, 5, 4))));
  18333. --------------------
  18334. +/
  18335. bool isBefore(in NegInfInterval!TP interval) const pure nothrow
  18336. {
  18337. return false;
  18338. }
  18339. /++
  18340. Whether this interval is after the given time point.
  18341. Params:
  18342. timePoint = The time point to check whether this interval is after
  18343. it.
  18344. Examples:
  18345. --------------------
  18346. assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Date(1994, 12, 24)));
  18347. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Date(2000, 1, 5)));
  18348. --------------------
  18349. +/
  18350. bool isAfter(in TP timePoint) const pure nothrow
  18351. {
  18352. return timePoint < _begin;
  18353. }
  18354. /++
  18355. Whether this interval is after the given interval and does not intersect
  18356. it.
  18357. Params:
  18358. interval = The interval to check against this interval.
  18359. Throws:
  18360. $(D DateTimeException) if the given interval is empty.
  18361. Examples:
  18362. --------------------
  18363. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
  18364. Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  18365. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
  18366. Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  18367. assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
  18368. Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
  18369. --------------------
  18370. +/
  18371. bool isAfter(in Interval!TP interval) const pure
  18372. {
  18373. interval._enforceNotEmpty();
  18374. return _begin >= interval._end;
  18375. }
  18376. /++
  18377. Whether this interval is after the given interval and does not intersect
  18378. it.
  18379. Always returns false because an interval going to positive infinity can
  18380. never be after another interval going to positive infinity.
  18381. Params:
  18382. interval = The interval to check against this interval.
  18383. Examples:
  18384. --------------------
  18385. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
  18386. PosInfInterval!Date(Date(1990, 1, 7))));
  18387. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
  18388. PosInfInterval!Date(Date(1999, 5, 4))));
  18389. --------------------
  18390. +/
  18391. bool isAfter(in PosInfInterval interval) const pure nothrow
  18392. {
  18393. return false;
  18394. }
  18395. /++
  18396. Whether this interval is after the given interval and does not intersect
  18397. it.
  18398. Params:
  18399. interval = The interval to check against this interval.
  18400. Examples:
  18401. --------------------
  18402. assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
  18403. NegInfInterval!Date(Date(1996, 1, 2))));
  18404. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(
  18405. NegInfInterval!Date(Date(2000, 7, 1))));
  18406. --------------------
  18407. +/
  18408. bool isAfter(in NegInfInterval!TP interval) const pure nothrow
  18409. {
  18410. return _begin >= interval._end;
  18411. }
  18412. /++
  18413. Whether the given interval overlaps this interval.
  18414. Params:
  18415. interval = The interval to check for intersection with this interval.
  18416. Throws:
  18417. $(D DateTimeException) if the given interval is empty.
  18418. Examples:
  18419. --------------------
  18420. assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(
  18421. Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  18422. assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(
  18423. Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  18424. assert(!PosInfInterval!Date(Date(1996, 1, 2)).intersects(
  18425. Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
  18426. --------------------
  18427. +/
  18428. bool intersects(in Interval!TP interval) const pure
  18429. {
  18430. interval._enforceNotEmpty();
  18431. return interval._end > _begin;
  18432. }
  18433. /++
  18434. Whether the given interval overlaps this interval.
  18435. Always returns true because two intervals going to positive infinity
  18436. always overlap.
  18437. Params:
  18438. interval = The interval to check for intersection with this
  18439. interval.
  18440. Examples:
  18441. --------------------
  18442. assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(
  18443. PosInfInterval!Date(Date(1990, 1, 7))));
  18444. assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(
  18445. PosInfInterval!Date(Date(1999, 5, 4))));
  18446. --------------------
  18447. +/
  18448. bool intersects(in PosInfInterval interval) const pure nothrow
  18449. {
  18450. return true;
  18451. }
  18452. /++
  18453. Whether the given interval overlaps this interval.
  18454. Params:
  18455. interval = The interval to check for intersection with this
  18456. interval.
  18457. Examples:
  18458. --------------------
  18459. assert(!PosInfInterval!Date(Date(1996, 1, 2)).intersects(
  18460. NegInfInterval!Date(Date(1996, 1, 2))));
  18461. assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(
  18462. NegInfInterval!Date(Date(2000, 7, 1))));
  18463. --------------------
  18464. +/
  18465. bool intersects(in NegInfInterval!TP interval) const pure nothrow
  18466. {
  18467. return _begin < interval._end;
  18468. }
  18469. /++
  18470. Returns the intersection of two intervals
  18471. Params:
  18472. interval = The interval to intersect with this interval.
  18473. Throws:
  18474. $(D DateTimeException) if the two intervals do not intersect or if
  18475. the given interval is empty.
  18476. Examples:
  18477. --------------------
  18478. assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(
  18479. Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
  18480. Interval!Date(Date(1996, 1 , 2), Date(2000, 8, 2)));
  18481. assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(
  18482. Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) ==
  18483. Interval!Date(Date(1999, 1 , 12), Date(2011, 9, 17)));
  18484. --------------------
  18485. +/
  18486. Interval!TP intersection(in Interval!TP interval) const
  18487. {
  18488. enforce(this.intersects(interval), new DateTimeException(format("%s and %s do not intersect.", this, interval)));
  18489. auto begin = _begin > interval._begin ? _begin : interval._begin;
  18490. return Interval!TP(begin, interval._end);
  18491. }
  18492. /++
  18493. Returns the intersection of two intervals
  18494. Params:
  18495. interval = The interval to intersect with this interval.
  18496. Examples:
  18497. --------------------
  18498. assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(
  18499. PosInfInterval!Date(Date(1990, 7, 6))) ==
  18500. PosInfInterval!Date(Date(1996, 1 , 2)));
  18501. assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(
  18502. PosInfInterval!Date(Date(1999, 1, 12))) ==
  18503. PosInfInterval!Date(Date(1999, 1 , 12)));
  18504. --------------------
  18505. +/
  18506. PosInfInterval intersection(in PosInfInterval interval) const pure nothrow
  18507. {
  18508. return PosInfInterval(_begin < interval._begin ? interval._begin : _begin);
  18509. }
  18510. /++
  18511. Returns the intersection of two intervals
  18512. Params:
  18513. interval = The interval to intersect with this interval.
  18514. Throws:
  18515. $(D DateTimeException) if the two intervals do not intersect.
  18516. Examples:
  18517. --------------------
  18518. assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(
  18519. NegInfInterval!Date(Date(1999, 7, 6))) ==
  18520. Interval!Date(Date(1996, 1 , 2), Date(1999, 7, 6)));
  18521. assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(
  18522. NegInfInterval!Date(Date(2013, 1, 12))) ==
  18523. Interval!Date(Date(1996, 1 , 2), Date(2013, 1, 12)));
  18524. --------------------
  18525. +/
  18526. Interval!TP intersection(in NegInfInterval!TP interval) const
  18527. {
  18528. enforce(this.intersects(interval), new DateTimeException(format("%s and %s do not intersect.", this, interval)));
  18529. return Interval!TP(_begin, interval._end);
  18530. }
  18531. /++
  18532. Whether the given interval is adjacent to this interval.
  18533. Params:
  18534. interval = The interval to check whether its adjecent to this
  18535. interval.
  18536. Throws:
  18537. $(D DateTimeException) if the given interval is empty.
  18538. Examples:
  18539. --------------------
  18540. assert(PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(
  18541. Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
  18542. assert(!PosInfInterval!Date(Date(1999, 1, 12)).isAdjacent(
  18543. Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  18544. --------------------
  18545. +/
  18546. bool isAdjacent(in Interval!TP interval) const pure
  18547. {
  18548. interval._enforceNotEmpty();
  18549. return _begin == interval._end;
  18550. }
  18551. /++
  18552. Whether the given interval is adjacent to this interval.
  18553. Always returns false because two intervals going to positive infinity
  18554. can never be adjacent to one another.
  18555. Params:
  18556. interval = The interval to check whether its adjecent to this
  18557. interval.
  18558. Examples:
  18559. --------------------
  18560. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(
  18561. PosInfInterval!Date(Date(1990, 1, 7))));
  18562. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(
  18563. PosInfInterval!Date(Date(1996, 1, 2))));
  18564. --------------------
  18565. +/
  18566. bool isAdjacent(in PosInfInterval interval) const pure nothrow
  18567. {
  18568. return false;
  18569. }
  18570. /++
  18571. Whether the given interval is adjacent to this interval.
  18572. Params:
  18573. interval = The interval to check whether its adjecent to this
  18574. interval.
  18575. Examples:
  18576. --------------------
  18577. assert(PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(
  18578. NegInfInterval!Date(Date(1996, 1, 2))));
  18579. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(
  18580. NegInfInterval!Date(Date(2000, 7, 1))));
  18581. --------------------
  18582. +/
  18583. bool isAdjacent(in NegInfInterval!TP interval) const pure nothrow
  18584. {
  18585. return _begin == interval._end;
  18586. }
  18587. /++
  18588. Returns the union of two intervals
  18589. Params:
  18590. interval = The interval to merge with this interval.
  18591. Throws:
  18592. $(D DateTimeException) if the two intervals do not intersect and are
  18593. not adjacent or if the given interval is empty.
  18594. Note:
  18595. There is no overload for $(D merge) which takes a
  18596. $(D NegInfInterval). This is because you can't have an interval
  18597. which goes from negative infinity to positive infinity.
  18598. Examples:
  18599. --------------------
  18600. assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(
  18601. Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
  18602. PosInfInterval!Date(Date(1990, 7 , 6)));
  18603. assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(
  18604. Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) ==
  18605. PosInfInterval!Date(Date(1996, 1 , 2)));
  18606. --------------------
  18607. +/
  18608. PosInfInterval merge(in Interval!TP interval) const
  18609. {
  18610. enforce(this.isAdjacent(interval) || this.intersects(interval),
  18611. new DateTimeException(format("%s and %s are not adjacent and do not intersect.", this, interval)));
  18612. return PosInfInterval(_begin < interval._begin ? _begin : interval._begin);
  18613. }
  18614. /++
  18615. Returns the union of two intervals
  18616. Params:
  18617. interval = The interval to merge with this interval.
  18618. Note:
  18619. There is no overload for $(D merge) which takes a
  18620. $(D NegInfInterval). This is because you can't have an interval
  18621. which goes from negative infinity to positive infinity.
  18622. Examples:
  18623. --------------------
  18624. assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(
  18625. PosInfInterval!Date(Date(1990, 7, 6))) ==
  18626. PosInfInterval!Date(Date(1990, 7 , 6)));
  18627. assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(
  18628. PosInfInterval!Date(Date(1999, 1, 12))) ==
  18629. PosInfInterval!Date(Date(1996, 1 , 2)));
  18630. --------------------
  18631. +/
  18632. PosInfInterval merge(in PosInfInterval interval) const pure nothrow
  18633. {
  18634. return PosInfInterval(_begin < interval._begin ? _begin : interval._begin);
  18635. }
  18636. /++
  18637. Returns an interval that covers from the earliest time point of two
  18638. intervals up to (but not including) the latest time point of two
  18639. intervals.
  18640. Params:
  18641. interval = The interval to create a span together with this
  18642. interval.
  18643. Throws:
  18644. $(D DateTimeException) if the given interval is empty.
  18645. Note:
  18646. There is no overload for $(D span) which takes a
  18647. $(D NegInfInterval). This is because you can't have an interval
  18648. which goes from negative infinity to positive infinity.
  18649. Examples:
  18650. --------------------
  18651. assert(PosInfInterval!Date(Date(1996, 1, 2)).span(
  18652. Interval!Date(Date(500, 8, 9), Date(1602, 1, 31))) ==
  18653. PosInfInterval!Date(Date(500, 8, 9)));
  18654. assert(PosInfInterval!Date(Date(1996, 1, 2)).span(
  18655. Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
  18656. PosInfInterval!Date(Date(1990, 7 , 6)));
  18657. assert(PosInfInterval!Date(Date(1996, 1, 2)).span(
  18658. Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) ==
  18659. PosInfInterval!Date(Date(1996, 1 , 2)));
  18660. --------------------
  18661. +/
  18662. PosInfInterval span(in Interval!TP interval) const pure
  18663. {
  18664. interval._enforceNotEmpty();
  18665. return PosInfInterval(_begin < interval._begin ? _begin : interval._begin);
  18666. }
  18667. /++
  18668. Returns an interval that covers from the earliest time point of two
  18669. intervals up to (but not including) the latest time point of two
  18670. intervals.
  18671. Params:
  18672. interval = The interval to create a span together with this
  18673. interval.
  18674. Note:
  18675. There is no overload for $(D span) which takes a
  18676. $(D NegInfInterval). This is because you can't have an interval
  18677. which goes from negative infinity to positive infinity.
  18678. Examples:
  18679. --------------------
  18680. assert(PosInfInterval!Date(Date(1996, 1, 2)).span(
  18681. PosInfInterval!Date(Date(1990, 7, 6))) ==
  18682. PosInfInterval!Date(Date(1990, 7 , 6)));
  18683. assert(PosInfInterval!Date(Date(1996, 1, 2)).span(
  18684. PosInfInterval!Date(Date(1999, 1, 12))) ==
  18685. PosInfInterval!Date(Date(1996, 1 , 2)));
  18686. --------------------
  18687. +/
  18688. PosInfInterval span(in PosInfInterval interval) const pure nothrow
  18689. {
  18690. return PosInfInterval(_begin < interval._begin ? _begin : interval._begin);
  18691. }
  18692. /++
  18693. Shifts the $(D begin) of this interval forward or backwards in time by
  18694. the given duration (a positive duration shifts the interval forward; a
  18695. negative duration shifts it backward). Effectively, it does
  18696. $(D begin += duration).
  18697. Params:
  18698. duration = The duration to shift the interval by.
  18699. Examples:
  18700. --------------------
  18701. auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
  18702. auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
  18703. interval1.shift(dur!"days"(50));
  18704. assert(interval1 == PosInfInterval!Date(Date(1996, 2, 21)));
  18705. interval2.shift(dur!"days"(-50));
  18706. assert(interval2 == PosInfInterval!Date(Date(1995, 11, 13)));
  18707. --------------------
  18708. +/
  18709. void shift(D)(D duration) pure nothrow
  18710. if(__traits(compiles, begin + duration))
  18711. {
  18712. _begin += duration;
  18713. }
  18714. static if(__traits(compiles, begin.add!"months"(1)) &&
  18715. __traits(compiles, begin.add!"years"(1)))
  18716. {
  18717. /++
  18718. Shifts the $(D begin) of this interval forward or backwards in time
  18719. by the given number of years and/or months (a positive number of years
  18720. and months shifts the interval forward; a negative number shifts it
  18721. backward). It adds the years the given years and months to
  18722. $(D begin). It effectively calls $(D add!"years"()) and then
  18723. $(D add!"months"()) on $(D begin) with the given number of years and
  18724. months.
  18725. Params:
  18726. years = The number of years to shift the interval by.
  18727. months = The number of months to shift the interval by.
  18728. allowOverflow = Whether the days should be allowed to overflow
  18729. on $(D begin), causing its month to increment.
  18730. Throws:
  18731. $(D DateTimeException) if this interval is empty or if the
  18732. resulting interval would be invalid.
  18733. Examples:
  18734. --------------------
  18735. auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
  18736. auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
  18737. interval1.shift(dur!"days"(50));
  18738. assert(interval1 == PosInfInterval!Date(Date(1996, 2, 21)));
  18739. interval2.shift(dur!"days"(-50));
  18740. assert(interval2 == PosInfInterval!Date(Date(1995, 11, 13)));
  18741. --------------------
  18742. +/
  18743. void shift(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
  18744. if(isIntegral!T)
  18745. {
  18746. auto begin = _begin;
  18747. begin.add!"years"(years, allowOverflow);
  18748. begin.add!"months"(months, allowOverflow);
  18749. _begin = begin;
  18750. }
  18751. }
  18752. /++
  18753. Expands the interval backwards in time. Effectively, it does
  18754. $(D begin -= duration).
  18755. Params:
  18756. duration = The duration to expand the interval by.
  18757. dir = The direction in time to expand the interval.
  18758. Examples:
  18759. --------------------
  18760. auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
  18761. auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
  18762. interval1.expand(dur!"days"(2));
  18763. assert(interval1 == PosInfInterval!Date(Date(1995, 12, 31)));
  18764. interval2.expand(dur!"days"(-2));
  18765. assert(interval2 == PosInfInterval!Date(Date(1996, 1, 4)));
  18766. --------------------
  18767. +/
  18768. void expand(D)(D duration) pure nothrow
  18769. if(__traits(compiles, begin + duration))
  18770. {
  18771. _begin -= duration;
  18772. }
  18773. static if(__traits(compiles, begin.add!"months"(1)) &&
  18774. __traits(compiles, begin.add!"years"(1)))
  18775. {
  18776. /++
  18777. Expands the interval forwards and/or backwards in time. Effectively,
  18778. it subtracts the given number of months/years from $(D begin).
  18779. Params:
  18780. years = The number of years to expand the interval by.
  18781. months = The number of months to expand the interval by.
  18782. allowOverflow = Whether the days should be allowed to overflow
  18783. on $(D begin), causing its month to increment.
  18784. Throws:
  18785. $(D DateTimeException) if this interval is empty or if the
  18786. resulting interval would be invalid.
  18787. Examples:
  18788. --------------------
  18789. auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
  18790. auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
  18791. interval1.expand(2);
  18792. assert(interval1 == PosInfInterval!Date(Date(1994, 1, 2)));
  18793. interval2.expand(-2);
  18794. assert(interval2 == PosInfInterval!Date(Date(1998, 1, 2)));
  18795. --------------------
  18796. +/
  18797. void expand(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
  18798. if(isIntegral!T)
  18799. {
  18800. auto begin = _begin;
  18801. begin.add!"years"(-years, allowOverflow);
  18802. begin.add!"months"(-months, allowOverflow);
  18803. _begin = begin;
  18804. return;
  18805. }
  18806. }
  18807. /++
  18808. Returns a range which iterates forward over the interval, starting
  18809. at $(D begin), using $(D_PARAM func) to generate each successive time
  18810. point.
  18811. The range's $(D front) is the interval's $(D begin). $(D_PARAM func) is
  18812. used to generate the next $(D front) when $(D popFront) is called. If
  18813. $(D_PARAM popFirst) is $(D PopFirst.yes), then $(D popFront) is called
  18814. before the range is returned (so that $(D front) is a time point which
  18815. $(D_PARAM func) would generate).
  18816. If $(D_PARAM func) ever generates a time point less than or equal to the
  18817. current $(D front) of the range, then a $(D DateTimeException) will be
  18818. thrown.
  18819. There are helper functions in this module which generate common
  18820. delegates to pass to $(D fwdRange). Their documentation starts with
  18821. "Range-generating function," so you can easily search for them.
  18822. Params:
  18823. func = The function used to generate the time points of the
  18824. range over the interval.
  18825. popFirst = Whether $(D popFront) should be called on the range
  18826. before returning it.
  18827. Throws:
  18828. $(D DateTimeException) if this interval is empty.
  18829. Warning:
  18830. $(D_PARAM func) must be logically pure. Ideally, $(D_PARAM func)
  18831. would be a function pointer to a pure function, but forcing
  18832. $(D_PARAM func) to be pure is far too restrictive to be useful, and
  18833. in order to have the ease of use of having functions which generate
  18834. functions to pass to $(D fwdRange), $(D_PARAM func) must be a
  18835. delegate.
  18836. If $(D_PARAM func) retains state which changes as it is called, then
  18837. some algorithms will not work correctly, because the range's
  18838. $(D save) will have failed to have really saved the range's state.
  18839. So, if you want to avoid such bugs, don't pass a delegate which is
  18840. not logically pure to $(D fwdRange). If $(D_PARAM func) is given the
  18841. same time point with two different calls, it must return the same
  18842. result both times.
  18843. Of course, none of the functions in this module have this problem,
  18844. so it's only relevant if you're creating your own delegate.
  18845. Examples:
  18846. --------------------
  18847. auto interval = PosInfInterval!Date(Date(2010, 9, 1));
  18848. auto func = (in Date date) //For iterating over even-numbered days.
  18849. {
  18850. if((date.day & 1) == 0)
  18851. return date + dur!"days"(2);
  18852. return date + dur!"days"(1);
  18853. };
  18854. auto range = interval.fwdRange(func);
  18855. //An odd day. Using PopFirst.yes would have made this Date(2010, 9, 2).
  18856. assert(range.front == Date(2010, 9, 1));
  18857. range.popFront();
  18858. assert(range.front == Date(2010, 9, 2));
  18859. range.popFront();
  18860. assert(range.front == Date(2010, 9, 4));
  18861. range.popFront();
  18862. assert(range.front == Date(2010, 9, 6));
  18863. range.popFront();
  18864. assert(range.front == Date(2010, 9, 8));
  18865. range.popFront();
  18866. assert(!range.empty);
  18867. --------------------
  18868. +/
  18869. PosInfIntervalRange!(TP) fwdRange(TP delegate(in TP) func, PopFirst popFirst = PopFirst.no) const
  18870. {
  18871. auto range = PosInfIntervalRange!(TP)(this, func);
  18872. if(popFirst == PopFirst.yes)
  18873. range.popFront();
  18874. return range;
  18875. }
  18876. /+
  18877. Converts this interval to a string.
  18878. +/
  18879. //Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
  18880. //have versions of toString() with extra modifiers, so we define one version
  18881. //with modifiers and one without.
  18882. string toString()
  18883. {
  18884. return _toStringImpl();
  18885. }
  18886. /++
  18887. Converts this interval to a string.
  18888. +/
  18889. //Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
  18890. //have versions of toString() with extra modifiers, so we define one version
  18891. //with modifiers and one without.
  18892. string toString() const nothrow
  18893. {
  18894. return _toStringImpl();
  18895. }
  18896. private:
  18897. /+
  18898. Since we have two versions of toString(), we have _toStringImpl()
  18899. so that they can share implementations.
  18900. +/
  18901. string _toStringImpl() const nothrow
  18902. {
  18903. try
  18904. return format("[%s - ∞)", _begin);
  18905. catch(Exception e)
  18906. assert(0, "format() threw.");
  18907. }
  18908. TP _begin;
  18909. }
  18910. //Test PosInfInterval's constructor.
  18911. unittest
  18912. {
  18913. version(testStdDateTime)
  18914. {
  18915. PosInfInterval!Date(Date.init);
  18916. PosInfInterval!TimeOfDay(TimeOfDay.init);
  18917. PosInfInterval!DateTime(DateTime.init);
  18918. PosInfInterval!SysTime(SysTime(0));
  18919. //Verify Examples.
  18920. auto interval = PosInfInterval!Date(Date(1996, 1, 2));
  18921. }
  18922. }
  18923. //Test PosInfInterval's begin.
  18924. unittest
  18925. {
  18926. version(testStdDateTime)
  18927. {
  18928. _assertPred!"=="(PosInfInterval!Date(Date(1, 1, 1)).begin, Date(1, 1, 1));
  18929. _assertPred!"=="(PosInfInterval!Date(Date(2010, 1, 1)).begin, Date(2010, 1, 1));
  18930. _assertPred!"=="(PosInfInterval!Date(Date(1997, 12, 31)).begin, Date(1997, 12, 31));
  18931. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  18932. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  18933. static assert(__traits(compiles, cPosInfInterval.begin));
  18934. static assert(__traits(compiles, iPosInfInterval.begin));
  18935. //Verify Examples.
  18936. assert(PosInfInterval!Date(Date(1996, 1, 2)).begin == Date(1996, 1, 2));
  18937. }
  18938. }
  18939. //Test PosInfInterval's empty.
  18940. unittest
  18941. {
  18942. version(testStdDateTime)
  18943. {
  18944. assert(!PosInfInterval!Date(Date(2010, 1, 1)).empty);
  18945. assert(!PosInfInterval!TimeOfDay(TimeOfDay(0, 30, 0)).empty);
  18946. assert(!PosInfInterval!DateTime(DateTime(2010, 1, 1, 0, 30, 0)).empty);
  18947. assert(!PosInfInterval!SysTime(SysTime(DateTime(2010, 1, 1, 0, 30, 0))).empty);
  18948. const cPosInfInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  18949. immutable iPosInfInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  18950. static assert(__traits(compiles, cPosInfInterval.empty));
  18951. static assert(__traits(compiles, iPosInfInterval.empty));
  18952. //Verify Examples.
  18953. assert(!PosInfInterval!Date(Date(1996, 1, 2)).empty);
  18954. }
  18955. }
  18956. //Test PosInfInterval's contains(time point).
  18957. unittest
  18958. {
  18959. version(testStdDateTime)
  18960. {
  18961. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  18962. assert(!posInfInterval.contains(Date(2009, 7, 4)));
  18963. assert(!posInfInterval.contains(Date(2010, 7, 3)));
  18964. assert(posInfInterval.contains(Date(2010, 7, 4)));
  18965. assert(posInfInterval.contains(Date(2010, 7, 5)));
  18966. assert(posInfInterval.contains(Date(2011, 7, 1)));
  18967. assert(posInfInterval.contains(Date(2012, 1, 6)));
  18968. assert(posInfInterval.contains(Date(2012, 1, 7)));
  18969. assert(posInfInterval.contains(Date(2012, 1, 8)));
  18970. assert(posInfInterval.contains(Date(2013, 1, 7)));
  18971. const cdate = Date(2010, 7, 6);
  18972. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  18973. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  18974. static assert(__traits(compiles, posInfInterval.contains(cdate)));
  18975. static assert(__traits(compiles, cPosInfInterval.contains(cdate)));
  18976. static assert(__traits(compiles, iPosInfInterval.contains(cdate)));
  18977. //Verify Examples.
  18978. assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(Date(1994, 12, 24)));
  18979. assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(Date(2000, 1, 5)));
  18980. }
  18981. }
  18982. //Test PosInfInterval's contains(Interval).
  18983. unittest
  18984. {
  18985. version(testStdDateTime)
  18986. {
  18987. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  18988. static void testInterval(in PosInfInterval!Date posInfInterval, in Interval!Date interval)
  18989. {
  18990. posInfInterval.contains(interval);
  18991. }
  18992. assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  18993. assert(posInfInterval.contains(posInfInterval));
  18994. assert(!posInfInterval.contains(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
  18995. assert(!posInfInterval.contains(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
  18996. assert(!posInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
  18997. assert(!posInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
  18998. assert(!posInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
  18999. assert(!posInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
  19000. assert(posInfInterval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
  19001. assert(posInfInterval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
  19002. assert(posInfInterval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
  19003. assert(posInfInterval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
  19004. assert(posInfInterval.contains(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
  19005. assert(posInfInterval.contains(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
  19006. assert(!posInfInterval.contains(PosInfInterval!Date(Date(2010, 7, 3))));
  19007. assert(posInfInterval.contains(PosInfInterval!Date(Date(2010, 7, 4))));
  19008. assert(posInfInterval.contains(PosInfInterval!Date(Date(2010, 7, 5))));
  19009. assert(posInfInterval.contains(PosInfInterval!Date(Date(2012, 1, 6))));
  19010. assert(posInfInterval.contains(PosInfInterval!Date(Date(2012, 1, 7))));
  19011. assert(posInfInterval.contains(PosInfInterval!Date(Date(2012, 1, 8))));
  19012. assert(PosInfInterval!Date(Date(2010, 7, 3)).contains(posInfInterval));
  19013. assert(PosInfInterval!Date(Date(2010, 7, 4)).contains(posInfInterval));
  19014. assert(!PosInfInterval!Date(Date(2010, 7, 5)).contains(posInfInterval));
  19015. assert(!PosInfInterval!Date(Date(2012, 1, 6)).contains(posInfInterval));
  19016. assert(!PosInfInterval!Date(Date(2012, 1, 7)).contains(posInfInterval));
  19017. assert(!PosInfInterval!Date(Date(2012, 1, 8)).contains(posInfInterval));
  19018. assert(!posInfInterval.contains(NegInfInterval!Date(Date(2010, 7, 3))));
  19019. assert(!posInfInterval.contains(NegInfInterval!Date(Date(2010, 7, 4))));
  19020. assert(!posInfInterval.contains(NegInfInterval!Date(Date(2010, 7, 5))));
  19021. assert(!posInfInterval.contains(NegInfInterval!Date(Date(2012, 1, 6))));
  19022. assert(!posInfInterval.contains(NegInfInterval!Date(Date(2012, 1, 7))));
  19023. assert(!posInfInterval.contains(NegInfInterval!Date(Date(2012, 1, 8))));
  19024. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  19025. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  19026. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  19027. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19028. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19029. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  19030. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  19031. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  19032. static assert(__traits(compiles, posInfInterval.contains(interval)));
  19033. static assert(__traits(compiles, posInfInterval.contains(cInterval)));
  19034. static assert(__traits(compiles, posInfInterval.contains(iInterval)));
  19035. static assert(__traits(compiles, posInfInterval.contains(posInfInterval)));
  19036. static assert(__traits(compiles, posInfInterval.contains(cPosInfInterval)));
  19037. static assert(__traits(compiles, posInfInterval.contains(iPosInfInterval)));
  19038. static assert(__traits(compiles, posInfInterval.contains(negInfInterval)));
  19039. static assert(__traits(compiles, posInfInterval.contains(cNegInfInterval)));
  19040. static assert(__traits(compiles, posInfInterval.contains(iNegInfInterval)));
  19041. static assert(__traits(compiles, cPosInfInterval.contains(interval)));
  19042. static assert(__traits(compiles, cPosInfInterval.contains(cInterval)));
  19043. static assert(__traits(compiles, cPosInfInterval.contains(iInterval)));
  19044. static assert(__traits(compiles, cPosInfInterval.contains(posInfInterval)));
  19045. static assert(__traits(compiles, cPosInfInterval.contains(cPosInfInterval)));
  19046. static assert(__traits(compiles, cPosInfInterval.contains(iPosInfInterval)));
  19047. static assert(__traits(compiles, cPosInfInterval.contains(negInfInterval)));
  19048. static assert(__traits(compiles, cPosInfInterval.contains(cNegInfInterval)));
  19049. static assert(__traits(compiles, cPosInfInterval.contains(iNegInfInterval)));
  19050. static assert(__traits(compiles, iPosInfInterval.contains(interval)));
  19051. static assert(__traits(compiles, iPosInfInterval.contains(cInterval)));
  19052. static assert(__traits(compiles, iPosInfInterval.contains(iInterval)));
  19053. static assert(__traits(compiles, iPosInfInterval.contains(posInfInterval)));
  19054. static assert(__traits(compiles, iPosInfInterval.contains(cPosInfInterval)));
  19055. static assert(__traits(compiles, iPosInfInterval.contains(iPosInfInterval)));
  19056. static assert(__traits(compiles, iPosInfInterval.contains(negInfInterval)));
  19057. static assert(__traits(compiles, iPosInfInterval.contains(cNegInfInterval)));
  19058. static assert(__traits(compiles, iPosInfInterval.contains(iNegInfInterval)));
  19059. //Verify Examples.
  19060. assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  19061. assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  19062. assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
  19063. assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(PosInfInterval!Date(Date(1999, 5, 4))));
  19064. assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(PosInfInterval!Date(Date(1995, 7, 2))));
  19065. assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(NegInfInterval!Date(Date(1996, 5, 4))));
  19066. }
  19067. }
  19068. //Test PosInfInterval's isBefore(time point).
  19069. unittest
  19070. {
  19071. version(testStdDateTime)
  19072. {
  19073. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19074. assert(!posInfInterval.isBefore(Date(2009, 7, 3)));
  19075. assert(!posInfInterval.isBefore(Date(2010, 7, 3)));
  19076. assert(!posInfInterval.isBefore(Date(2010, 7, 4)));
  19077. assert(!posInfInterval.isBefore(Date(2010, 7, 5)));
  19078. assert(!posInfInterval.isBefore(Date(2011, 7, 1)));
  19079. assert(!posInfInterval.isBefore(Date(2012, 1, 6)));
  19080. assert(!posInfInterval.isBefore(Date(2012, 1, 7)));
  19081. assert(!posInfInterval.isBefore(Date(2012, 1, 8)));
  19082. assert(!posInfInterval.isBefore(Date(2013, 1, 7)));
  19083. const cdate = Date(2010, 7, 6);
  19084. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19085. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19086. static assert(__traits(compiles, posInfInterval.isBefore(cdate)));
  19087. static assert(__traits(compiles, cPosInfInterval.isBefore(cdate)));
  19088. static assert(__traits(compiles, iPosInfInterval.isBefore(cdate)));
  19089. //Verify Examples.
  19090. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Date(1994, 12, 24)));
  19091. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Date(2000, 1, 5)));
  19092. }
  19093. }
  19094. //Test PosInfInterval's isBefore(Interval).
  19095. unittest
  19096. {
  19097. version(testStdDateTime)
  19098. {
  19099. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19100. static void testInterval(in PosInfInterval!Date posInfInterval, in Interval!Date interval)
  19101. {
  19102. posInfInterval.isBefore(interval);
  19103. }
  19104. assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  19105. assert(!posInfInterval.isBefore(posInfInterval));
  19106. assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
  19107. assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
  19108. assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
  19109. assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
  19110. assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
  19111. assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
  19112. assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
  19113. assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
  19114. assert(!posInfInterval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
  19115. assert(!posInfInterval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
  19116. assert(!posInfInterval.isBefore(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
  19117. assert(!posInfInterval.isBefore(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
  19118. assert(!posInfInterval.isBefore(PosInfInterval!Date(Date(2010, 7, 3))));
  19119. assert(!posInfInterval.isBefore(PosInfInterval!Date(Date(2010, 7, 4))));
  19120. assert(!posInfInterval.isBefore(PosInfInterval!Date(Date(2010, 7, 5))));
  19121. assert(!posInfInterval.isBefore(PosInfInterval!Date(Date(2012, 1, 6))));
  19122. assert(!posInfInterval.isBefore(PosInfInterval!Date(Date(2012, 1, 7))));
  19123. assert(!posInfInterval.isBefore(PosInfInterval!Date(Date(2012, 1, 8))));
  19124. assert(!PosInfInterval!Date(Date(2010, 7, 3)).isBefore(posInfInterval));
  19125. assert(!PosInfInterval!Date(Date(2010, 7, 4)).isBefore(posInfInterval));
  19126. assert(!PosInfInterval!Date(Date(2010, 7, 5)).isBefore(posInfInterval));
  19127. assert(!PosInfInterval!Date(Date(2012, 1, 6)).isBefore(posInfInterval));
  19128. assert(!PosInfInterval!Date(Date(2012, 1, 7)).isBefore(posInfInterval));
  19129. assert(!PosInfInterval!Date(Date(2012, 1, 8)).isBefore(posInfInterval));
  19130. assert(!posInfInterval.isBefore(NegInfInterval!Date(Date(2010, 7, 3))));
  19131. assert(!posInfInterval.isBefore(NegInfInterval!Date(Date(2010, 7, 4))));
  19132. assert(!posInfInterval.isBefore(NegInfInterval!Date(Date(2010, 7, 5))));
  19133. assert(!posInfInterval.isBefore(NegInfInterval!Date(Date(2012, 1, 6))));
  19134. assert(!posInfInterval.isBefore(NegInfInterval!Date(Date(2012, 1, 7))));
  19135. assert(!posInfInterval.isBefore(NegInfInterval!Date(Date(2012, 1, 8))));
  19136. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  19137. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  19138. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  19139. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19140. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19141. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  19142. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  19143. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  19144. static assert(__traits(compiles, posInfInterval.isBefore(interval)));
  19145. static assert(__traits(compiles, posInfInterval.isBefore(cInterval)));
  19146. static assert(__traits(compiles, posInfInterval.isBefore(iInterval)));
  19147. static assert(__traits(compiles, posInfInterval.isBefore(posInfInterval)));
  19148. static assert(__traits(compiles, posInfInterval.isBefore(cPosInfInterval)));
  19149. static assert(__traits(compiles, posInfInterval.isBefore(iPosInfInterval)));
  19150. static assert(__traits(compiles, posInfInterval.isBefore(negInfInterval)));
  19151. static assert(__traits(compiles, posInfInterval.isBefore(cNegInfInterval)));
  19152. static assert(__traits(compiles, posInfInterval.isBefore(iNegInfInterval)));
  19153. static assert(__traits(compiles, cPosInfInterval.isBefore(interval)));
  19154. static assert(__traits(compiles, cPosInfInterval.isBefore(cInterval)));
  19155. static assert(__traits(compiles, cPosInfInterval.isBefore(iInterval)));
  19156. static assert(__traits(compiles, cPosInfInterval.isBefore(posInfInterval)));
  19157. static assert(__traits(compiles, cPosInfInterval.isBefore(cPosInfInterval)));
  19158. static assert(__traits(compiles, cPosInfInterval.isBefore(iPosInfInterval)));
  19159. static assert(__traits(compiles, cPosInfInterval.isBefore(negInfInterval)));
  19160. static assert(__traits(compiles, cPosInfInterval.isBefore(cNegInfInterval)));
  19161. static assert(__traits(compiles, cPosInfInterval.isBefore(iNegInfInterval)));
  19162. static assert(__traits(compiles, iPosInfInterval.isBefore(interval)));
  19163. static assert(__traits(compiles, iPosInfInterval.isBefore(cInterval)));
  19164. static assert(__traits(compiles, iPosInfInterval.isBefore(iInterval)));
  19165. static assert(__traits(compiles, iPosInfInterval.isBefore(posInfInterval)));
  19166. static assert(__traits(compiles, iPosInfInterval.isBefore(cPosInfInterval)));
  19167. static assert(__traits(compiles, iPosInfInterval.isBefore(iPosInfInterval)));
  19168. static assert(__traits(compiles, iPosInfInterval.isBefore(negInfInterval)));
  19169. static assert(__traits(compiles, iPosInfInterval.isBefore(cNegInfInterval)));
  19170. static assert(__traits(compiles, iPosInfInterval.isBefore(iNegInfInterval)));
  19171. //Verify Examples.
  19172. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  19173. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  19174. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(PosInfInterval!Date(Date(1992, 5, 4))));
  19175. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(PosInfInterval!Date(Date(2013, 3, 7))));
  19176. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(NegInfInterval!Date(Date(1996, 5, 4))));
  19177. }
  19178. }
  19179. //Test PosInfInterval's isAfter(time point).
  19180. unittest
  19181. {
  19182. version(testStdDateTime)
  19183. {
  19184. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19185. assert(posInfInterval.isAfter(Date(2009, 7, 3)));
  19186. assert(posInfInterval.isAfter(Date(2010, 7, 3)));
  19187. assert(!posInfInterval.isAfter(Date(2010, 7, 4)));
  19188. assert(!posInfInterval.isAfter(Date(2010, 7, 5)));
  19189. assert(!posInfInterval.isAfter(Date(2011, 7, 1)));
  19190. assert(!posInfInterval.isAfter(Date(2012, 1, 6)));
  19191. assert(!posInfInterval.isAfter(Date(2012, 1, 7)));
  19192. assert(!posInfInterval.isAfter(Date(2012, 1, 8)));
  19193. assert(!posInfInterval.isAfter(Date(2013, 1, 7)));
  19194. const cdate = Date(2010, 7, 6);
  19195. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19196. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19197. static assert(__traits(compiles, posInfInterval.isAfter(cdate)));
  19198. static assert(__traits(compiles, cPosInfInterval.isAfter(cdate)));
  19199. static assert(__traits(compiles, iPosInfInterval.isAfter(cdate)));
  19200. //Verify Examples.
  19201. assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Date(1994, 12, 24)));
  19202. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Date(2000, 1, 5)));
  19203. }
  19204. }
  19205. //Test PosInfInterval's isAfter(Interval).
  19206. unittest
  19207. {
  19208. version(testStdDateTime)
  19209. {
  19210. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19211. static void testInterval(in PosInfInterval!Date posInfInterval, in Interval!Date interval)
  19212. {
  19213. posInfInterval.isAfter(interval);
  19214. }
  19215. assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  19216. assert(!posInfInterval.isAfter(posInfInterval));
  19217. assert(posInfInterval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
  19218. assert(!posInfInterval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
  19219. assert(posInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
  19220. assert(!posInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
  19221. assert(!posInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
  19222. assert(!posInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
  19223. assert(!posInfInterval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
  19224. assert(!posInfInterval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
  19225. assert(!posInfInterval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
  19226. assert(!posInfInterval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
  19227. assert(!posInfInterval.isAfter(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
  19228. assert(!posInfInterval.isAfter(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
  19229. assert(!posInfInterval.isAfter(PosInfInterval!Date(Date(2010, 7, 3))));
  19230. assert(!posInfInterval.isAfter(PosInfInterval!Date(Date(2010, 7, 4))));
  19231. assert(!posInfInterval.isAfter(PosInfInterval!Date(Date(2010, 7, 5))));
  19232. assert(!posInfInterval.isAfter(PosInfInterval!Date(Date(2012, 1, 6))));
  19233. assert(!posInfInterval.isAfter(PosInfInterval!Date(Date(2012, 1, 7))));
  19234. assert(!posInfInterval.isAfter(PosInfInterval!Date(Date(2012, 1, 8))));
  19235. assert(!PosInfInterval!Date(Date(2010, 7, 3)).isAfter(posInfInterval));
  19236. assert(!PosInfInterval!Date(Date(2010, 7, 4)).isAfter(posInfInterval));
  19237. assert(!PosInfInterval!Date(Date(2010, 7, 5)).isAfter(posInfInterval));
  19238. assert(!PosInfInterval!Date(Date(2012, 1, 6)).isAfter(posInfInterval));
  19239. assert(!PosInfInterval!Date(Date(2012, 1, 7)).isAfter(posInfInterval));
  19240. assert(!PosInfInterval!Date(Date(2012, 1, 8)).isAfter(posInfInterval));
  19241. assert(posInfInterval.isAfter(NegInfInterval!Date(Date(2010, 7, 3))));
  19242. assert(posInfInterval.isAfter(NegInfInterval!Date(Date(2010, 7, 4))));
  19243. assert(!posInfInterval.isAfter(NegInfInterval!Date(Date(2010, 7, 5))));
  19244. assert(!posInfInterval.isAfter(NegInfInterval!Date(Date(2012, 1, 6))));
  19245. assert(!posInfInterval.isAfter(NegInfInterval!Date(Date(2012, 1, 7))));
  19246. assert(!posInfInterval.isAfter(NegInfInterval!Date(Date(2012, 1, 8))));
  19247. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  19248. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  19249. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  19250. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19251. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19252. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  19253. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  19254. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  19255. static assert(__traits(compiles, posInfInterval.isAfter(interval)));
  19256. static assert(__traits(compiles, posInfInterval.isAfter(cInterval)));
  19257. static assert(__traits(compiles, posInfInterval.isAfter(iInterval)));
  19258. static assert(__traits(compiles, posInfInterval.isAfter(posInfInterval)));
  19259. static assert(__traits(compiles, posInfInterval.isAfter(cPosInfInterval)));
  19260. static assert(__traits(compiles, posInfInterval.isAfter(iPosInfInterval)));
  19261. static assert(__traits(compiles, posInfInterval.isAfter(negInfInterval)));
  19262. static assert(__traits(compiles, posInfInterval.isAfter(cNegInfInterval)));
  19263. static assert(__traits(compiles, posInfInterval.isAfter(iNegInfInterval)));
  19264. static assert(__traits(compiles, cPosInfInterval.isAfter(interval)));
  19265. static assert(__traits(compiles, cPosInfInterval.isAfter(cInterval)));
  19266. static assert(__traits(compiles, cPosInfInterval.isAfter(iInterval)));
  19267. static assert(__traits(compiles, cPosInfInterval.isAfter(posInfInterval)));
  19268. static assert(__traits(compiles, cPosInfInterval.isAfter(cPosInfInterval)));
  19269. static assert(__traits(compiles, cPosInfInterval.isAfter(iPosInfInterval)));
  19270. static assert(__traits(compiles, cPosInfInterval.isAfter(negInfInterval)));
  19271. static assert(__traits(compiles, cPosInfInterval.isAfter(cNegInfInterval)));
  19272. static assert(__traits(compiles, cPosInfInterval.isAfter(iNegInfInterval)));
  19273. static assert(__traits(compiles, iPosInfInterval.isAfter(interval)));
  19274. static assert(__traits(compiles, iPosInfInterval.isAfter(cInterval)));
  19275. static assert(__traits(compiles, iPosInfInterval.isAfter(iInterval)));
  19276. static assert(__traits(compiles, iPosInfInterval.isAfter(posInfInterval)));
  19277. static assert(__traits(compiles, iPosInfInterval.isAfter(cPosInfInterval)));
  19278. static assert(__traits(compiles, iPosInfInterval.isAfter(iPosInfInterval)));
  19279. static assert(__traits(compiles, iPosInfInterval.isAfter(negInfInterval)));
  19280. static assert(__traits(compiles, iPosInfInterval.isAfter(cNegInfInterval)));
  19281. static assert(__traits(compiles, iPosInfInterval.isAfter(iNegInfInterval)));
  19282. //Verify Examples.
  19283. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  19284. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  19285. assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
  19286. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(PosInfInterval!Date(Date(1990, 1, 7))));
  19287. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(PosInfInterval!Date(Date(1999, 5, 4))));
  19288. assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(NegInfInterval!Date(Date(1996, 1, 2))));
  19289. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(NegInfInterval!Date(Date(2000, 7, 1))));
  19290. }
  19291. }
  19292. //Test PosInfInterval's intersects().
  19293. unittest
  19294. {
  19295. version(testStdDateTime)
  19296. {
  19297. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19298. static void testInterval(in PosInfInterval!Date posInfInterval, in Interval!Date interval)
  19299. {
  19300. posInfInterval.intersects(interval);
  19301. }
  19302. assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  19303. assert(posInfInterval.intersects(posInfInterval));
  19304. assert(!posInfInterval.intersects(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
  19305. assert(posInfInterval.intersects(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
  19306. assert(!posInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
  19307. assert(posInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
  19308. assert(posInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
  19309. assert(posInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
  19310. assert(posInfInterval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
  19311. assert(posInfInterval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
  19312. assert(posInfInterval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
  19313. assert(posInfInterval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
  19314. assert(posInfInterval.intersects(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
  19315. assert(posInfInterval.intersects(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
  19316. assert(posInfInterval.intersects(PosInfInterval!Date(Date(2010, 7, 3))));
  19317. assert(posInfInterval.intersects(PosInfInterval!Date(Date(2010, 7, 4))));
  19318. assert(posInfInterval.intersects(PosInfInterval!Date(Date(2010, 7, 5))));
  19319. assert(posInfInterval.intersects(PosInfInterval!Date(Date(2012, 1, 6))));
  19320. assert(posInfInterval.intersects(PosInfInterval!Date(Date(2012, 1, 7))));
  19321. assert(posInfInterval.intersects(PosInfInterval!Date(Date(2012, 1, 8))));
  19322. assert(PosInfInterval!Date(Date(2010, 7, 3)).intersects(posInfInterval));
  19323. assert(PosInfInterval!Date(Date(2010, 7, 4)).intersects(posInfInterval));
  19324. assert(PosInfInterval!Date(Date(2010, 7, 5)).intersects(posInfInterval));
  19325. assert(PosInfInterval!Date(Date(2012, 1, 6)).intersects(posInfInterval));
  19326. assert(PosInfInterval!Date(Date(2012, 1, 7)).intersects(posInfInterval));
  19327. assert(PosInfInterval!Date(Date(2012, 1, 8)).intersects(posInfInterval));
  19328. assert(!posInfInterval.intersects(NegInfInterval!Date(Date(2010, 7, 3))));
  19329. assert(!posInfInterval.intersects(NegInfInterval!Date(Date(2010, 7, 4))));
  19330. assert(posInfInterval.intersects(NegInfInterval!Date(Date(2010, 7, 5))));
  19331. assert(posInfInterval.intersects(NegInfInterval!Date(Date(2012, 1, 6))));
  19332. assert(posInfInterval.intersects(NegInfInterval!Date(Date(2012, 1, 7))));
  19333. assert(posInfInterval.intersects(NegInfInterval!Date(Date(2012, 1, 8))));
  19334. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  19335. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  19336. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  19337. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19338. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19339. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  19340. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  19341. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  19342. static assert(__traits(compiles, posInfInterval.intersects(interval)));
  19343. static assert(__traits(compiles, posInfInterval.intersects(cInterval)));
  19344. static assert(__traits(compiles, posInfInterval.intersects(iInterval)));
  19345. static assert(__traits(compiles, posInfInterval.intersects(posInfInterval)));
  19346. static assert(__traits(compiles, posInfInterval.intersects(cPosInfInterval)));
  19347. static assert(__traits(compiles, posInfInterval.intersects(iPosInfInterval)));
  19348. static assert(__traits(compiles, posInfInterval.intersects(negInfInterval)));
  19349. static assert(__traits(compiles, posInfInterval.intersects(cNegInfInterval)));
  19350. static assert(__traits(compiles, posInfInterval.intersects(iNegInfInterval)));
  19351. static assert(__traits(compiles, cPosInfInterval.intersects(interval)));
  19352. static assert(__traits(compiles, cPosInfInterval.intersects(cInterval)));
  19353. static assert(__traits(compiles, cPosInfInterval.intersects(iInterval)));
  19354. static assert(__traits(compiles, cPosInfInterval.intersects(posInfInterval)));
  19355. static assert(__traits(compiles, cPosInfInterval.intersects(cPosInfInterval)));
  19356. static assert(__traits(compiles, cPosInfInterval.intersects(iPosInfInterval)));
  19357. static assert(__traits(compiles, cPosInfInterval.intersects(negInfInterval)));
  19358. static assert(__traits(compiles, cPosInfInterval.intersects(cNegInfInterval)));
  19359. static assert(__traits(compiles, cPosInfInterval.intersects(iNegInfInterval)));
  19360. static assert(__traits(compiles, iPosInfInterval.intersects(interval)));
  19361. static assert(__traits(compiles, iPosInfInterval.intersects(cInterval)));
  19362. static assert(__traits(compiles, iPosInfInterval.intersects(iInterval)));
  19363. static assert(__traits(compiles, iPosInfInterval.intersects(posInfInterval)));
  19364. static assert(__traits(compiles, iPosInfInterval.intersects(cPosInfInterval)));
  19365. static assert(__traits(compiles, iPosInfInterval.intersects(iPosInfInterval)));
  19366. static assert(__traits(compiles, iPosInfInterval.intersects(negInfInterval)));
  19367. static assert(__traits(compiles, iPosInfInterval.intersects(cNegInfInterval)));
  19368. static assert(__traits(compiles, iPosInfInterval.intersects(iNegInfInterval)));
  19369. //Verify Examples.
  19370. assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  19371. assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  19372. assert(!PosInfInterval!Date(Date(1996, 1, 2)).intersects(Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
  19373. assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(PosInfInterval!Date(Date(1990, 1, 7))));
  19374. assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(PosInfInterval!Date(Date(1999, 5, 4))));
  19375. assert(!PosInfInterval!Date(Date(1996, 1, 2)).intersects(NegInfInterval!Date(Date(1996, 1, 2))));
  19376. assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(NegInfInterval!Date(Date(2000, 7, 1))));
  19377. }
  19378. }
  19379. //Test PosInfInterval's intersection().
  19380. unittest
  19381. {
  19382. version(testStdDateTime)
  19383. {
  19384. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19385. static void testInterval(I, J)(in I interval1, in J interval2)
  19386. {
  19387. interval1.intersection(interval2);
  19388. }
  19389. assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  19390. assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
  19391. assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
  19392. assertThrown!DateTimeException(testInterval(posInfInterval, NegInfInterval!Date(Date(2010, 7, 3))));
  19393. assertThrown!DateTimeException(testInterval(posInfInterval, NegInfInterval!Date(Date(2010, 7, 4))));
  19394. _assertPred!"=="(posInfInterval.intersection(posInfInterval),
  19395. posInfInterval);
  19396. _assertPred!"=="(posInfInterval.intersection(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))),
  19397. Interval!Date(Date(2010, 7, 4), Date(2013, 7, 3)));
  19398. _assertPred!"=="(posInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))),
  19399. Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)));
  19400. _assertPred!"=="(posInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))),
  19401. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
  19402. _assertPred!"=="(posInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))),
  19403. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
  19404. _assertPred!"=="(posInfInterval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))),
  19405. Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)));
  19406. _assertPred!"=="(posInfInterval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))),
  19407. Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)));
  19408. _assertPred!"=="(posInfInterval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))),
  19409. Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
  19410. _assertPred!"=="(posInfInterval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))),
  19411. Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)));
  19412. _assertPred!"=="(posInfInterval.intersection(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))),
  19413. Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)));
  19414. _assertPred!"=="(posInfInterval.intersection(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))),
  19415. Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)));
  19416. _assertPred!"=="(posInfInterval.intersection(PosInfInterval!Date(Date(2010, 7, 3))),
  19417. PosInfInterval!Date(Date(2010, 7, 4)));
  19418. _assertPred!"=="(posInfInterval.intersection(PosInfInterval!Date(Date(2010, 7, 4))),
  19419. PosInfInterval!Date(Date(2010, 7, 4)));
  19420. _assertPred!"=="(posInfInterval.intersection(PosInfInterval!Date(Date(2010, 7, 5))),
  19421. PosInfInterval!Date(Date(2010, 7, 5)));
  19422. _assertPred!"=="(posInfInterval.intersection(PosInfInterval!Date(Date(2012, 1, 6))),
  19423. PosInfInterval!Date(Date(2012, 1, 6)));
  19424. _assertPred!"=="(posInfInterval.intersection(PosInfInterval!Date(Date(2012, 1, 7))),
  19425. PosInfInterval!Date(Date(2012, 1, 7)));
  19426. _assertPred!"=="(posInfInterval.intersection(PosInfInterval!Date(Date(2012, 1, 8))),
  19427. PosInfInterval!Date(Date(2012, 1, 8)));
  19428. _assertPred!"=="(PosInfInterval!Date(Date(2010, 7, 3)).intersection(posInfInterval),
  19429. PosInfInterval!Date(Date(2010, 7, 4)));
  19430. _assertPred!"=="(PosInfInterval!Date(Date(2010, 7, 4)).intersection(posInfInterval),
  19431. PosInfInterval!Date(Date(2010, 7, 4)));
  19432. _assertPred!"=="(PosInfInterval!Date(Date(2010, 7, 5)).intersection(posInfInterval),
  19433. PosInfInterval!Date(Date(2010, 7, 5)));
  19434. _assertPred!"=="(PosInfInterval!Date(Date(2012, 1, 6)).intersection(posInfInterval),
  19435. PosInfInterval!Date(Date(2012, 1, 6)));
  19436. _assertPred!"=="(PosInfInterval!Date(Date(2012, 1, 7)).intersection(posInfInterval),
  19437. PosInfInterval!Date(Date(2012, 1, 7)));
  19438. _assertPred!"=="(PosInfInterval!Date(Date(2012, 1, 8)).intersection(posInfInterval),
  19439. PosInfInterval!Date(Date(2012, 1, 8)));
  19440. _assertPred!"=="(posInfInterval.intersection(NegInfInterval!Date(Date(2010, 7, 5))),
  19441. Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)));
  19442. _assertPred!"=="(posInfInterval.intersection(NegInfInterval!Date(Date(2012, 1, 6))),
  19443. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 6)));
  19444. _assertPred!"=="(posInfInterval.intersection(NegInfInterval!Date(Date(2012, 1, 7))),
  19445. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
  19446. _assertPred!"=="(posInfInterval.intersection(NegInfInterval!Date(Date(2012, 1, 8))),
  19447. Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
  19448. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  19449. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  19450. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  19451. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19452. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19453. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  19454. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  19455. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  19456. static assert(__traits(compiles, posInfInterval.intersection(interval)));
  19457. static assert(__traits(compiles, posInfInterval.intersection(cInterval)));
  19458. static assert(__traits(compiles, posInfInterval.intersection(iInterval)));
  19459. static assert(__traits(compiles, posInfInterval.intersection(posInfInterval)));
  19460. static assert(__traits(compiles, posInfInterval.intersection(cPosInfInterval)));
  19461. static assert(__traits(compiles, posInfInterval.intersection(iPosInfInterval)));
  19462. static assert(__traits(compiles, posInfInterval.intersection(negInfInterval)));
  19463. static assert(__traits(compiles, posInfInterval.intersection(cNegInfInterval)));
  19464. static assert(__traits(compiles, posInfInterval.intersection(iNegInfInterval)));
  19465. static assert(__traits(compiles, cPosInfInterval.intersection(interval)));
  19466. static assert(__traits(compiles, cPosInfInterval.intersection(cInterval)));
  19467. static assert(__traits(compiles, cPosInfInterval.intersection(iInterval)));
  19468. static assert(__traits(compiles, cPosInfInterval.intersection(posInfInterval)));
  19469. static assert(__traits(compiles, cPosInfInterval.intersection(cPosInfInterval)));
  19470. static assert(__traits(compiles, cPosInfInterval.intersection(iPosInfInterval)));
  19471. static assert(__traits(compiles, cPosInfInterval.intersection(negInfInterval)));
  19472. static assert(__traits(compiles, cPosInfInterval.intersection(cNegInfInterval)));
  19473. static assert(__traits(compiles, cPosInfInterval.intersection(iNegInfInterval)));
  19474. static assert(__traits(compiles, iPosInfInterval.intersection(interval)));
  19475. static assert(__traits(compiles, iPosInfInterval.intersection(cInterval)));
  19476. static assert(__traits(compiles, iPosInfInterval.intersection(iInterval)));
  19477. static assert(__traits(compiles, iPosInfInterval.intersection(posInfInterval)));
  19478. static assert(__traits(compiles, iPosInfInterval.intersection(cPosInfInterval)));
  19479. static assert(__traits(compiles, iPosInfInterval.intersection(iPosInfInterval)));
  19480. static assert(__traits(compiles, iPosInfInterval.intersection(negInfInterval)));
  19481. static assert(__traits(compiles, iPosInfInterval.intersection(cNegInfInterval)));
  19482. static assert(__traits(compiles, iPosInfInterval.intersection(iNegInfInterval)));
  19483. //Verify Examples.
  19484. assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) == Interval!Date(Date(1996, 1 , 2), Date(2000, 8, 2)));
  19485. assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) == Interval!Date(Date(1999, 1 , 12), Date(2011, 9, 17)));
  19486. assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(PosInfInterval!Date(Date(1990, 7, 6))) == PosInfInterval!Date(Date(1996, 1 , 2)));
  19487. assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(PosInfInterval!Date(Date(1999, 1, 12))) == PosInfInterval!Date(Date(1999, 1 , 12)));
  19488. assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(NegInfInterval!Date(Date(1999, 7, 6))) == Interval!Date(Date(1996, 1 , 2), Date(1999, 7, 6)));
  19489. assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(NegInfInterval!Date(Date(2013, 1, 12))) == Interval!Date(Date(1996, 1 , 2), Date(2013, 1, 12)));
  19490. }
  19491. }
  19492. //Test PosInfInterval's isAdjacent().
  19493. unittest
  19494. {
  19495. version(testStdDateTime)
  19496. {
  19497. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19498. static void testInterval(in PosInfInterval!Date posInfInterval, in Interval!Date interval)
  19499. {
  19500. posInfInterval.isAdjacent(interval);
  19501. }
  19502. assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  19503. assert(!posInfInterval.isAdjacent(posInfInterval));
  19504. assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
  19505. assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
  19506. assert(posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
  19507. assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
  19508. assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
  19509. assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
  19510. assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
  19511. assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
  19512. assert(!posInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
  19513. assert(!posInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
  19514. assert(!posInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
  19515. assert(!posInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
  19516. assert(!posInfInterval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 3))));
  19517. assert(!posInfInterval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 4))));
  19518. assert(!posInfInterval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 5))));
  19519. assert(!posInfInterval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 6))));
  19520. assert(!posInfInterval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 7))));
  19521. assert(!posInfInterval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 8))));
  19522. assert(!PosInfInterval!Date(Date(2010, 7, 3)).isAdjacent(posInfInterval));
  19523. assert(!PosInfInterval!Date(Date(2010, 7, 4)).isAdjacent(posInfInterval));
  19524. assert(!PosInfInterval!Date(Date(2010, 7, 5)).isAdjacent(posInfInterval));
  19525. assert(!PosInfInterval!Date(Date(2012, 1, 6)).isAdjacent(posInfInterval));
  19526. assert(!PosInfInterval!Date(Date(2012, 1, 7)).isAdjacent(posInfInterval));
  19527. assert(!PosInfInterval!Date(Date(2012, 1, 8)).isAdjacent(posInfInterval));
  19528. assert(!posInfInterval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 3))));
  19529. assert(posInfInterval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 4))));
  19530. assert(!posInfInterval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 5))));
  19531. assert(!posInfInterval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 6))));
  19532. assert(!posInfInterval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 7))));
  19533. assert(!posInfInterval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 8))));
  19534. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  19535. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  19536. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  19537. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19538. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19539. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  19540. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  19541. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  19542. static assert(__traits(compiles, posInfInterval.isAdjacent(interval)));
  19543. static assert(__traits(compiles, posInfInterval.isAdjacent(cInterval)));
  19544. static assert(__traits(compiles, posInfInterval.isAdjacent(iInterval)));
  19545. static assert(__traits(compiles, posInfInterval.isAdjacent(posInfInterval)));
  19546. static assert(__traits(compiles, posInfInterval.isAdjacent(cPosInfInterval)));
  19547. static assert(__traits(compiles, posInfInterval.isAdjacent(iPosInfInterval)));
  19548. static assert(__traits(compiles, posInfInterval.isAdjacent(negInfInterval)));
  19549. static assert(__traits(compiles, posInfInterval.isAdjacent(cNegInfInterval)));
  19550. static assert(__traits(compiles, posInfInterval.isAdjacent(iNegInfInterval)));
  19551. static assert(__traits(compiles, cPosInfInterval.isAdjacent(interval)));
  19552. static assert(__traits(compiles, cPosInfInterval.isAdjacent(cInterval)));
  19553. static assert(__traits(compiles, cPosInfInterval.isAdjacent(iInterval)));
  19554. static assert(__traits(compiles, cPosInfInterval.isAdjacent(posInfInterval)));
  19555. static assert(__traits(compiles, cPosInfInterval.isAdjacent(cPosInfInterval)));
  19556. static assert(__traits(compiles, cPosInfInterval.isAdjacent(iPosInfInterval)));
  19557. static assert(__traits(compiles, cPosInfInterval.isAdjacent(negInfInterval)));
  19558. static assert(__traits(compiles, cPosInfInterval.isAdjacent(cNegInfInterval)));
  19559. static assert(__traits(compiles, cPosInfInterval.isAdjacent(iNegInfInterval)));
  19560. static assert(__traits(compiles, iPosInfInterval.isAdjacent(interval)));
  19561. static assert(__traits(compiles, iPosInfInterval.isAdjacent(cInterval)));
  19562. static assert(__traits(compiles, iPosInfInterval.isAdjacent(iInterval)));
  19563. static assert(__traits(compiles, iPosInfInterval.isAdjacent(posInfInterval)));
  19564. static assert(__traits(compiles, iPosInfInterval.isAdjacent(cPosInfInterval)));
  19565. static assert(__traits(compiles, iPosInfInterval.isAdjacent(iPosInfInterval)));
  19566. static assert(__traits(compiles, iPosInfInterval.isAdjacent(negInfInterval)));
  19567. static assert(__traits(compiles, iPosInfInterval.isAdjacent(cNegInfInterval)));
  19568. static assert(__traits(compiles, iPosInfInterval.isAdjacent(iNegInfInterval)));
  19569. //Verify Examples.
  19570. assert(PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
  19571. assert(!PosInfInterval!Date(Date(1999, 1, 12)).isAdjacent(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  19572. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(PosInfInterval!Date(Date(1990, 1, 7))));
  19573. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(PosInfInterval!Date(Date(1996, 1, 2))));
  19574. assert(PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(NegInfInterval!Date(Date(1996, 1, 2))));
  19575. assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(NegInfInterval!Date(Date(2000, 7, 1))));
  19576. }
  19577. }
  19578. //Test PosInfInterval's merge().
  19579. unittest
  19580. {
  19581. version(testStdDateTime)
  19582. {
  19583. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19584. static void testInterval(in PosInfInterval!Date posInfInterval, in Interval!Date interval)
  19585. {
  19586. posInfInterval.merge(interval);
  19587. }
  19588. assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  19589. assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
  19590. _assertPred!"=="(posInfInterval.merge(posInfInterval),
  19591. posInfInterval);
  19592. _assertPred!"=="(posInfInterval.merge(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))),
  19593. PosInfInterval!Date(Date(2010, 7, 1)));
  19594. _assertPred!"=="(posInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))),
  19595. PosInfInterval!Date(Date(2010, 7, 3)));
  19596. _assertPred!"=="(posInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))),
  19597. PosInfInterval!Date(Date(2010, 7, 3)));
  19598. _assertPred!"=="(posInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))),
  19599. PosInfInterval!Date(Date(2010, 7, 3)));
  19600. _assertPred!"=="(posInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))),
  19601. PosInfInterval!Date(Date(2010, 7, 3)));
  19602. _assertPred!"=="(posInfInterval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))),
  19603. PosInfInterval!Date(Date(2010, 7, 4)));
  19604. _assertPred!"=="(posInfInterval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))),
  19605. PosInfInterval!Date(Date(2010, 7, 4)));
  19606. _assertPred!"=="(posInfInterval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))),
  19607. PosInfInterval!Date(Date(2010, 7, 4)));
  19608. _assertPred!"=="(posInfInterval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))),
  19609. PosInfInterval!Date(Date(2010, 7, 4)));
  19610. _assertPred!"=="(posInfInterval.merge(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))),
  19611. PosInfInterval!Date(Date(2010, 7, 4)));
  19612. _assertPred!"=="(posInfInterval.merge(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))),
  19613. PosInfInterval!Date(Date(2010, 7, 4)));
  19614. _assertPred!"=="(posInfInterval.merge(PosInfInterval!Date(Date(2010, 7, 3))),
  19615. PosInfInterval!Date(Date(2010, 7, 3)));
  19616. _assertPred!"=="(posInfInterval.merge(PosInfInterval!Date(Date(2010, 7, 4))),
  19617. PosInfInterval!Date(Date(2010, 7, 4)));
  19618. _assertPred!"=="(posInfInterval.merge(PosInfInterval!Date(Date(2010, 7, 5))),
  19619. PosInfInterval!Date(Date(2010, 7, 4)));
  19620. _assertPred!"=="(posInfInterval.merge(PosInfInterval!Date(Date(2012, 1, 6))),
  19621. PosInfInterval!Date(Date(2010, 7, 4)));
  19622. _assertPred!"=="(posInfInterval.merge(PosInfInterval!Date(Date(2012, 1, 7))),
  19623. PosInfInterval!Date(Date(2010, 7, 4)));
  19624. _assertPred!"=="(posInfInterval.merge(PosInfInterval!Date(Date(2012, 1, 8))),
  19625. PosInfInterval!Date(Date(2010, 7, 4)));
  19626. _assertPred!"=="(PosInfInterval!Date(Date(2010, 7, 3)).merge(posInfInterval),
  19627. PosInfInterval!Date(Date(2010, 7, 3)));
  19628. _assertPred!"=="(PosInfInterval!Date(Date(2010, 7, 4)).merge(posInfInterval),
  19629. PosInfInterval!Date(Date(2010, 7, 4)));
  19630. _assertPred!"=="(PosInfInterval!Date(Date(2010, 7, 5)).merge(posInfInterval),
  19631. PosInfInterval!Date(Date(2010, 7, 4)));
  19632. _assertPred!"=="(PosInfInterval!Date(Date(2012, 1, 6)).merge(posInfInterval),
  19633. PosInfInterval!Date(Date(2010, 7, 4)));
  19634. _assertPred!"=="(PosInfInterval!Date(Date(2012, 1, 7)).merge(posInfInterval),
  19635. PosInfInterval!Date(Date(2010, 7, 4)));
  19636. _assertPred!"=="(PosInfInterval!Date(Date(2012, 1, 8)).merge(posInfInterval),
  19637. PosInfInterval!Date(Date(2010, 7, 4)));
  19638. static assert(!__traits(compiles, posInfInterval.merge(NegInfInterval!Date(Date(2010, 7, 3)))));
  19639. static assert(!__traits(compiles, posInfInterval.merge(NegInfInterval!Date(Date(2010, 7, 4)))));
  19640. static assert(!__traits(compiles, posInfInterval.merge(NegInfInterval!Date(Date(2010, 7, 5)))));
  19641. static assert(!__traits(compiles, posInfInterval.merge(NegInfInterval!Date(Date(2012, 1, 6)))));
  19642. static assert(!__traits(compiles, posInfInterval.merge(NegInfInterval!Date(Date(2012, 1, 7)))));
  19643. static assert(!__traits(compiles, posInfInterval.merge(NegInfInterval!Date(Date(2012, 1, 8)))));
  19644. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  19645. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  19646. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  19647. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19648. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19649. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  19650. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  19651. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  19652. static assert(__traits(compiles, posInfInterval.merge(interval)));
  19653. static assert(__traits(compiles, posInfInterval.merge(cInterval)));
  19654. static assert(__traits(compiles, posInfInterval.merge(iInterval)));
  19655. static assert(__traits(compiles, posInfInterval.merge(posInfInterval)));
  19656. static assert(__traits(compiles, posInfInterval.merge(cPosInfInterval)));
  19657. static assert(__traits(compiles, posInfInterval.merge(iPosInfInterval)));
  19658. static assert(!__traits(compiles, posInfInterval.merge(negInfInterval)));
  19659. static assert(!__traits(compiles, posInfInterval.merge(cNegInfInterval)));
  19660. static assert(!__traits(compiles, posInfInterval.merge(iNegInfInterval)));
  19661. static assert(__traits(compiles, cPosInfInterval.merge(interval)));
  19662. static assert(__traits(compiles, cPosInfInterval.merge(cInterval)));
  19663. static assert(__traits(compiles, cPosInfInterval.merge(iInterval)));
  19664. static assert(__traits(compiles, cPosInfInterval.merge(posInfInterval)));
  19665. static assert(__traits(compiles, cPosInfInterval.merge(cPosInfInterval)));
  19666. static assert(__traits(compiles, cPosInfInterval.merge(iPosInfInterval)));
  19667. static assert(!__traits(compiles, cPosInfInterval.merge(negInfInterval)));
  19668. static assert(!__traits(compiles, cPosInfInterval.merge(cNegInfInterval)));
  19669. static assert(!__traits(compiles, cPosInfInterval.merge(iNegInfInterval)));
  19670. static assert(__traits(compiles, iPosInfInterval.merge(interval)));
  19671. static assert(__traits(compiles, iPosInfInterval.merge(cInterval)));
  19672. static assert(__traits(compiles, iPosInfInterval.merge(iInterval)));
  19673. static assert(__traits(compiles, iPosInfInterval.merge(posInfInterval)));
  19674. static assert(__traits(compiles, iPosInfInterval.merge(cPosInfInterval)));
  19675. static assert(__traits(compiles, iPosInfInterval.merge(iPosInfInterval)));
  19676. static assert(!__traits(compiles, iPosInfInterval.merge(negInfInterval)));
  19677. static assert(!__traits(compiles, iPosInfInterval.merge(cNegInfInterval)));
  19678. static assert(!__traits(compiles, iPosInfInterval.merge(iNegInfInterval)));
  19679. //Verify Examples.
  19680. assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) == PosInfInterval!Date(Date(1990, 7 , 6)));
  19681. assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) == PosInfInterval!Date(Date(1996, 1 , 2)));
  19682. assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(PosInfInterval!Date(Date(1990, 7, 6))) == PosInfInterval!Date(Date(1990, 7 , 6)));
  19683. assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(PosInfInterval!Date(Date(1999, 1, 12))) == PosInfInterval!Date(Date(1996, 1 , 2)));
  19684. }
  19685. }
  19686. //Test PosInfInterval's span().
  19687. unittest
  19688. {
  19689. version(testStdDateTime)
  19690. {
  19691. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19692. static void testInterval(in PosInfInterval!Date posInfInterval, in Interval!Date interval)
  19693. {
  19694. posInfInterval.span(interval);
  19695. }
  19696. assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  19697. _assertPred!"=="(posInfInterval.span(posInfInterval),
  19698. posInfInterval);
  19699. _assertPred!"=="(posInfInterval.span(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))),
  19700. PosInfInterval!Date(Date(2010, 7, 1)));
  19701. _assertPred!"=="(posInfInterval.span(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))),
  19702. PosInfInterval!Date(Date(2010, 7, 1)));
  19703. _assertPred!"=="(posInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))),
  19704. PosInfInterval!Date(Date(2010, 7, 3)));
  19705. _assertPred!"=="(posInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))),
  19706. PosInfInterval!Date(Date(2010, 7, 3)));
  19707. _assertPred!"=="(posInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))),
  19708. PosInfInterval!Date(Date(2010, 7, 3)));
  19709. _assertPred!"=="(posInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))),
  19710. PosInfInterval!Date(Date(2010, 7, 3)));
  19711. _assertPred!"=="(posInfInterval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))),
  19712. PosInfInterval!Date(Date(2010, 7, 4)));
  19713. _assertPred!"=="(posInfInterval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))),
  19714. PosInfInterval!Date(Date(2010, 7, 4)));
  19715. _assertPred!"=="(posInfInterval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))),
  19716. PosInfInterval!Date(Date(2010, 7, 4)));
  19717. _assertPred!"=="(posInfInterval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))),
  19718. PosInfInterval!Date(Date(2010, 7, 4)));
  19719. _assertPred!"=="(posInfInterval.span(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))),
  19720. PosInfInterval!Date(Date(2010, 7, 4)));
  19721. _assertPred!"=="(posInfInterval.span(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))),
  19722. PosInfInterval!Date(Date(2010, 7, 4)));
  19723. _assertPred!"=="(posInfInterval.span(PosInfInterval!Date(Date(2010, 7, 3))),
  19724. PosInfInterval!Date(Date(2010, 7, 3)));
  19725. _assertPred!"=="(posInfInterval.span(PosInfInterval!Date(Date(2010, 7, 4))),
  19726. PosInfInterval!Date(Date(2010, 7, 4)));
  19727. _assertPred!"=="(posInfInterval.span(PosInfInterval!Date(Date(2010, 7, 5))),
  19728. PosInfInterval!Date(Date(2010, 7, 4)));
  19729. _assertPred!"=="(posInfInterval.span(PosInfInterval!Date(Date(2012, 1, 6))),
  19730. PosInfInterval!Date(Date(2010, 7, 4)));
  19731. _assertPred!"=="(posInfInterval.span(PosInfInterval!Date(Date(2012, 1, 7))),
  19732. PosInfInterval!Date(Date(2010, 7, 4)));
  19733. _assertPred!"=="(posInfInterval.span(PosInfInterval!Date(Date(2012, 1, 8))),
  19734. PosInfInterval!Date(Date(2010, 7, 4)));
  19735. _assertPred!"=="(PosInfInterval!Date(Date(2010, 7, 3)).span(posInfInterval),
  19736. PosInfInterval!Date(Date(2010, 7, 3)));
  19737. _assertPred!"=="(PosInfInterval!Date(Date(2010, 7, 4)).span(posInfInterval),
  19738. PosInfInterval!Date(Date(2010, 7, 4)));
  19739. _assertPred!"=="(PosInfInterval!Date(Date(2010, 7, 5)).span(posInfInterval),
  19740. PosInfInterval!Date(Date(2010, 7, 4)));
  19741. _assertPred!"=="(PosInfInterval!Date(Date(2012, 1, 6)).span(posInfInterval),
  19742. PosInfInterval!Date(Date(2010, 7, 4)));
  19743. _assertPred!"=="(PosInfInterval!Date(Date(2012, 1, 7)).span(posInfInterval),
  19744. PosInfInterval!Date(Date(2010, 7, 4)));
  19745. _assertPred!"=="(PosInfInterval!Date(Date(2012, 1, 8)).span(posInfInterval),
  19746. PosInfInterval!Date(Date(2010, 7, 4)));
  19747. static assert(!__traits(compiles, posInfInterval.span(NegInfInterval!Date(Date(2010, 7, 3)))));
  19748. static assert(!__traits(compiles, posInfInterval.span(NegInfInterval!Date(Date(2010, 7, 4)))));
  19749. static assert(!__traits(compiles, posInfInterval.span(NegInfInterval!Date(Date(2010, 7, 5)))));
  19750. static assert(!__traits(compiles, posInfInterval.span(NegInfInterval!Date(Date(2012, 1, 6)))));
  19751. static assert(!__traits(compiles, posInfInterval.span(NegInfInterval!Date(Date(2012, 1, 7)))));
  19752. static assert(!__traits(compiles, posInfInterval.span(NegInfInterval!Date(Date(2012, 1, 8)))));
  19753. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  19754. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  19755. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  19756. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19757. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19758. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  19759. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  19760. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  19761. static assert(__traits(compiles, posInfInterval.span(interval)));
  19762. static assert(__traits(compiles, posInfInterval.span(cInterval)));
  19763. static assert(__traits(compiles, posInfInterval.span(iInterval)));
  19764. static assert(__traits(compiles, posInfInterval.span(posInfInterval)));
  19765. static assert(__traits(compiles, posInfInterval.span(cPosInfInterval)));
  19766. static assert(__traits(compiles, posInfInterval.span(iPosInfInterval)));
  19767. static assert(!__traits(compiles, posInfInterval.span(negInfInterval)));
  19768. static assert(!__traits(compiles, posInfInterval.span(cNegInfInterval)));
  19769. static assert(!__traits(compiles, posInfInterval.span(iNegInfInterval)));
  19770. static assert(__traits(compiles, cPosInfInterval.span(interval)));
  19771. static assert(__traits(compiles, cPosInfInterval.span(cInterval)));
  19772. static assert(__traits(compiles, cPosInfInterval.span(iInterval)));
  19773. static assert(__traits(compiles, cPosInfInterval.span(posInfInterval)));
  19774. static assert(__traits(compiles, cPosInfInterval.span(cPosInfInterval)));
  19775. static assert(__traits(compiles, cPosInfInterval.span(iPosInfInterval)));
  19776. static assert(!__traits(compiles, cPosInfInterval.span(negInfInterval)));
  19777. static assert(!__traits(compiles, cPosInfInterval.span(cNegInfInterval)));
  19778. static assert(!__traits(compiles, cPosInfInterval.span(iNegInfInterval)));
  19779. static assert(__traits(compiles, iPosInfInterval.span(interval)));
  19780. static assert(__traits(compiles, iPosInfInterval.span(cInterval)));
  19781. static assert(__traits(compiles, iPosInfInterval.span(iInterval)));
  19782. static assert(__traits(compiles, iPosInfInterval.span(posInfInterval)));
  19783. static assert(__traits(compiles, iPosInfInterval.span(cPosInfInterval)));
  19784. static assert(__traits(compiles, iPosInfInterval.span(iPosInfInterval)));
  19785. static assert(!__traits(compiles, iPosInfInterval.span(negInfInterval)));
  19786. static assert(!__traits(compiles, iPosInfInterval.span(cNegInfInterval)));
  19787. static assert(!__traits(compiles, iPosInfInterval.span(iNegInfInterval)));
  19788. //Verify Examples.
  19789. assert(PosInfInterval!Date(Date(1996, 1, 2)).span(Interval!Date(Date(500, 8, 9), Date(1602, 1, 31))) == PosInfInterval!Date(Date(500, 8, 9)));
  19790. assert(PosInfInterval!Date(Date(1996, 1, 2)).span(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) == PosInfInterval!Date(Date(1990, 7 , 6)));
  19791. assert(PosInfInterval!Date(Date(1996, 1, 2)).span(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) == PosInfInterval!Date(Date(1996, 1 , 2)));
  19792. assert(PosInfInterval!Date(Date(1996, 1, 2)).span(PosInfInterval!Date(Date(1990, 7, 6))) == PosInfInterval!Date(Date(1990, 7 , 6)));
  19793. assert(PosInfInterval!Date(Date(1996, 1, 2)).span(PosInfInterval!Date(Date(1999, 1, 12))) == PosInfInterval!Date(Date(1996, 1 , 2)));
  19794. }
  19795. }
  19796. //Test PosInfInterval's shift().
  19797. unittest
  19798. {
  19799. version(testStdDateTime)
  19800. {
  19801. auto interval = PosInfInterval!Date(Date(2010, 7, 4));
  19802. static void testInterval(I)(I interval, in Duration duration, in I expected, size_t line = __LINE__)
  19803. {
  19804. interval.shift(duration);
  19805. _assertPred!"=="(interval, expected, "", __FILE__, line);
  19806. }
  19807. testInterval(interval, dur!"days"(22), PosInfInterval!Date(Date(2010, 7, 26)));
  19808. testInterval(interval, dur!"days"(-22), PosInfInterval!Date(Date(2010, 6, 12)));
  19809. const cInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19810. immutable iInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19811. static assert(!__traits(compiles, cInterval.shift(dur!"days"(5))));
  19812. static assert(!__traits(compiles, iInterval.shift(dur!"days"(5))));
  19813. //Verify Examples.
  19814. auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
  19815. auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
  19816. interval1.shift(dur!"days"(50));
  19817. assert(interval1 == PosInfInterval!Date(Date(1996, 2, 21)));
  19818. interval2.shift(dur!"days"(-50));
  19819. assert(interval2 == PosInfInterval!Date(Date(1995, 11, 13)));
  19820. }
  19821. }
  19822. //Test PosInfInterval's shift(int, int, AllowDayOverflow).
  19823. unittest
  19824. {
  19825. version(testStdDateTime)
  19826. {
  19827. {
  19828. auto interval = PosInfInterval!Date(Date(2010, 7, 4));
  19829. static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow, in I expected, size_t line = __LINE__)
  19830. {
  19831. interval.shift(years, months, allow);
  19832. _assertPred!"=="(interval, expected, "", __FILE__, line);
  19833. }
  19834. testInterval(interval, 5, 0, AllowDayOverflow.yes, PosInfInterval!Date(Date(2015, 7, 4)));
  19835. testInterval(interval, -5, 0, AllowDayOverflow.yes, PosInfInterval!Date(Date(2005, 7, 4)));
  19836. auto interval2 = PosInfInterval!Date(Date(2000, 1, 29));
  19837. testInterval(interval2, 1, 1, AllowDayOverflow.yes, PosInfInterval!Date(Date(2001, 3, 1)));
  19838. testInterval(interval2, 1, -1, AllowDayOverflow.yes, PosInfInterval!Date(Date(2000, 12, 29)));
  19839. testInterval(interval2, -1, -1, AllowDayOverflow.yes, PosInfInterval!Date(Date(1998, 12, 29)));
  19840. testInterval(interval2, -1, 1, AllowDayOverflow.yes, PosInfInterval!Date(Date(1999, 3, 1)));
  19841. testInterval(interval2, 1, 1, AllowDayOverflow.no, PosInfInterval!Date(Date(2001, 2, 28)));
  19842. testInterval(interval2, 1, -1, AllowDayOverflow.no, PosInfInterval!Date(Date(2000, 12, 29)));
  19843. testInterval(interval2, -1, -1, AllowDayOverflow.no, PosInfInterval!Date(Date(1998, 12, 29)));
  19844. testInterval(interval2, -1, 1, AllowDayOverflow.no, PosInfInterval!Date(Date(1999, 2, 28)));
  19845. }
  19846. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19847. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19848. static assert(!__traits(compiles, cPosInfInterval.shift(1)));
  19849. static assert(!__traits(compiles, iPosInfInterval.shift(1)));
  19850. //Verify Examples.
  19851. auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
  19852. auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
  19853. interval1.shift(2);
  19854. assert(interval1 == PosInfInterval!Date(Date(1998, 1, 2)));
  19855. interval2.shift(-2);
  19856. assert(interval2 == PosInfInterval!Date(Date(1994, 1, 2)));
  19857. }
  19858. }
  19859. //Test PosInfInterval's expand().
  19860. unittest
  19861. {
  19862. version(testStdDateTime)
  19863. {
  19864. auto interval = PosInfInterval!Date(Date(2000, 7, 4));
  19865. static void testInterval(I)(I interval, in Duration duration, in I expected, size_t line = __LINE__)
  19866. {
  19867. interval.expand(duration);
  19868. _assertPred!"=="(interval, expected, "", __FILE__, line);
  19869. }
  19870. testInterval(interval, dur!"days"(22), PosInfInterval!Date(Date(2000, 6, 12)));
  19871. testInterval(interval, dur!"days"(-22), PosInfInterval!Date(Date(2000, 7, 26)));
  19872. const cInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19873. immutable iInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19874. static assert(!__traits(compiles, cInterval.expand(dur!"days"(5))));
  19875. static assert(!__traits(compiles, iInterval.expand(dur!"days"(5))));
  19876. //Verify Examples.
  19877. auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
  19878. auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
  19879. interval1.expand(dur!"days"(2));
  19880. assert(interval1 == PosInfInterval!Date(Date(1995, 12, 31)));
  19881. interval2.expand(dur!"days"(-2));
  19882. assert(interval2 == PosInfInterval!Date(Date(1996, 1, 4)));
  19883. }
  19884. }
  19885. //Test PosInfInterval's expand(int, int, AllowDayOverflow).
  19886. unittest
  19887. {
  19888. version(testStdDateTime)
  19889. {
  19890. {
  19891. auto interval = PosInfInterval!Date(Date(2000, 7, 4));
  19892. static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow, in I expected, size_t line = __LINE__)
  19893. {
  19894. interval.expand(years, months, allow);
  19895. _assertPred!"=="(interval, expected, "", __FILE__, line);
  19896. }
  19897. testInterval(interval, 5, 0, AllowDayOverflow.yes, PosInfInterval!Date(Date(1995, 7, 4)));
  19898. testInterval(interval, -5, 0, AllowDayOverflow.yes, PosInfInterval!Date(Date(2005, 7, 4)));
  19899. auto interval2 = PosInfInterval!Date(Date(2000, 1, 29));
  19900. testInterval(interval2, 1, 1, AllowDayOverflow.yes, PosInfInterval!Date(Date(1998, 12, 29)));
  19901. testInterval(interval2, 1, -1, AllowDayOverflow.yes, PosInfInterval!Date(Date(1999, 3, 1)));
  19902. testInterval(interval2, -1, -1, AllowDayOverflow.yes, PosInfInterval!Date(Date(2001, 3, 1)));
  19903. testInterval(interval2, -1, 1, AllowDayOverflow.yes, PosInfInterval!Date(Date(2000, 12, 29)));
  19904. testInterval(interval2, 1, 1, AllowDayOverflow.no, PosInfInterval!Date(Date(1998, 12, 29)));
  19905. testInterval(interval2, 1, -1, AllowDayOverflow.no, PosInfInterval!Date(Date(1999, 2, 28)));
  19906. testInterval(interval2, -1, -1, AllowDayOverflow.no, PosInfInterval!Date(Date(2001, 2, 28)));
  19907. testInterval(interval2, -1, 1, AllowDayOverflow.no, PosInfInterval!Date(Date(2000, 12, 29)));
  19908. }
  19909. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19910. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19911. static assert(!__traits(compiles, cPosInfInterval.expand(1)));
  19912. static assert(!__traits(compiles, iPosInfInterval.expand(1)));
  19913. //Verify Examples.
  19914. auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
  19915. auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
  19916. interval1.expand(2);
  19917. assert(interval1 == PosInfInterval!Date(Date(1994, 1, 2)));
  19918. interval2.expand(-2);
  19919. assert(interval2 == PosInfInterval!Date(Date(1998, 1, 2)));
  19920. }
  19921. }
  19922. //Test PosInfInterval's fwdRange().
  19923. unittest
  19924. {
  19925. version(testStdDateTime)
  19926. {
  19927. auto posInfInterval = PosInfInterval!Date(Date(2010, 9, 19));
  19928. static void testInterval(PosInfInterval!Date posInfInterval)
  19929. {
  19930. posInfInterval.fwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).popFront();
  19931. }
  19932. assertThrown!DateTimeException(testInterval(posInfInterval));
  19933. _assertPred!"=="(PosInfInterval!Date(Date(2010, 9, 12)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).front,
  19934. Date(2010, 9, 12));
  19935. _assertPred!"=="(PosInfInterval!Date(Date(2010, 9, 12)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri), PopFirst.yes).front,
  19936. Date(2010, 9, 17));
  19937. //Verify Examples.
  19938. auto interval = PosInfInterval!Date(Date(2010, 9, 1));
  19939. auto func = (in Date date)
  19940. {
  19941. if((date.day & 1) == 0)
  19942. return date + dur!"days"(2);
  19943. return date + dur!"days"(1);
  19944. };
  19945. auto range = interval.fwdRange(func);
  19946. assert(range.front == Date(2010, 9, 1)); //An odd day. Using PopFirst.yes would have made this Date(2010, 9, 2).
  19947. range.popFront();
  19948. assert(range.front == Date(2010, 9, 2));
  19949. range.popFront();
  19950. assert(range.front == Date(2010, 9, 4));
  19951. range.popFront();
  19952. assert(range.front == Date(2010, 9, 6));
  19953. range.popFront();
  19954. assert(range.front == Date(2010, 9, 8));
  19955. range.popFront();
  19956. assert(!range.empty);
  19957. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19958. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19959. static assert(__traits(compiles, cPosInfInterval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri))));
  19960. static assert(__traits(compiles, iPosInfInterval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri))));
  19961. }
  19962. }
  19963. //Test PosInfInterval's toString().
  19964. unittest
  19965. {
  19966. version(testStdDateTime)
  19967. {
  19968. _assertPred!"=="(PosInfInterval!Date(Date(2010, 7, 4)).toString(), "[2010-Jul-04 - ∞)");
  19969. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19970. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  19971. static assert(__traits(compiles, cPosInfInterval.toString()));
  19972. static assert(__traits(compiles, iPosInfInterval.toString()));
  19973. }
  19974. }
  19975. /++
  19976. Represents an interval of time which has negative infinity as its starting
  19977. point.
  19978. Any ranges which iterate over a $(D NegInfInterval) are infinite. So, the
  19979. main purpose of using $(D NegInfInterval) is to create an infinite range
  19980. which starts at negative infinity and goes to a fixed end point. You would
  19981. then iterate over it in reverse.
  19982. +/
  19983. struct NegInfInterval(TP)
  19984. {
  19985. public:
  19986. /++
  19987. Params:
  19988. begin = The time point which begins the interval.
  19989. Examples:
  19990. --------------------
  19991. auto interval = PosInfInterval!Date(Date(1996, 1, 2));
  19992. --------------------
  19993. +/
  19994. this(in TP end) pure nothrow
  19995. {
  19996. _end = cast(TP)end;
  19997. }
  19998. /++
  19999. Params:
  20000. rhs = The $(D NegInfInterval) to assign to this one.
  20001. +/
  20002. /+ref+/ NegInfInterval opAssign(const ref NegInfInterval rhs) pure nothrow
  20003. {
  20004. _end = cast(TP)rhs._end;
  20005. return this;
  20006. }
  20007. /++
  20008. Params:
  20009. rhs = The $(D NegInfInterval) to assign to this one.
  20010. +/
  20011. /+ref+/ NegInfInterval opAssign(NegInfInterval rhs) pure nothrow
  20012. {
  20013. _end = cast(TP)rhs._end;
  20014. return this;
  20015. }
  20016. /++
  20017. The end point of the interval. It is excluded from the interval.
  20018. Examples:
  20019. --------------------
  20020. assert(NegInfInterval!Date(Date(2012, 3, 1)).end == Date(2012, 3, 1));
  20021. --------------------
  20022. +/
  20023. @property TP end() const pure nothrow
  20024. {
  20025. return cast(TP)_end;
  20026. }
  20027. /++
  20028. The end point of the interval. It is excluded from the interval.
  20029. Params:
  20030. timePoint = The time point to set end to.
  20031. +/
  20032. @property void end(TP timePoint) pure nothrow
  20033. {
  20034. _end = timePoint;
  20035. }
  20036. /++
  20037. Whether the interval's length is 0. Always returns false.
  20038. Examples:
  20039. --------------------
  20040. assert(!NegInfInterval!Date(Date(1996, 1, 2)).empty);
  20041. --------------------
  20042. +/
  20043. @property bool empty() const pure nothrow
  20044. {
  20045. return false;
  20046. }
  20047. /++
  20048. Whether the given time point is within this interval.
  20049. Params:
  20050. timePoint = The time point to check for inclusion in this interval.
  20051. Examples:
  20052. --------------------
  20053. assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Date(1994, 12, 24)));
  20054. assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Date(2000, 1, 5)));
  20055. assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(Date(2012, 3, 1)));
  20056. --------------------
  20057. +/
  20058. bool contains(TP timePoint) const pure nothrow
  20059. {
  20060. return timePoint < _end;
  20061. }
  20062. /++
  20063. Whether the given interval is completely within this interval.
  20064. Params:
  20065. interval = The interval to check for inclusion in this interval.
  20066. Throws:
  20067. $(D DateTimeException) if the given interval is empty.
  20068. Examples:
  20069. --------------------
  20070. assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(
  20071. Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  20072. assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(
  20073. Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  20074. assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(
  20075. Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
  20076. --------------------
  20077. +/
  20078. bool contains(in Interval!TP interval) const pure
  20079. {
  20080. interval._enforceNotEmpty();
  20081. return interval._end <= _end;
  20082. }
  20083. /++
  20084. Whether the given interval is completely within this interval.
  20085. Always returns false because an interval beginning at negative
  20086. infinity can never contain an interval going to positive infinity.
  20087. Params:
  20088. interval = The interval to check for inclusion in this interval.
  20089. Examples:
  20090. --------------------
  20091. assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(
  20092. PosInfInterval!Date(Date(1999, 5, 4))));
  20093. --------------------
  20094. +/
  20095. bool contains(in PosInfInterval!TP interval) const pure nothrow
  20096. {
  20097. return false;
  20098. }
  20099. /++
  20100. Whether the given interval is completely within this interval.
  20101. Params:
  20102. interval = The interval to check for inclusion in this interval.
  20103. Examples:
  20104. --------------------
  20105. assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(
  20106. NegInfInterval!Date(Date(1996, 5, 4))));
  20107. assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(
  20108. NegInfInterval!Date(Date(2013, 7, 9))));
  20109. --------------------
  20110. +/
  20111. bool contains(in NegInfInterval interval) const pure nothrow
  20112. {
  20113. return interval._end <= _end;
  20114. }
  20115. /++
  20116. Whether this interval is before the given time point.
  20117. Params:
  20118. timePoint = The time point to check whether this interval is
  20119. before it.
  20120. Examples:
  20121. --------------------
  20122. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Date(1994, 12, 24)));
  20123. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Date(2000, 1, 5)));
  20124. assert(NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Date(2012, 3, 1)));
  20125. --------------------
  20126. +/
  20127. bool isBefore(in TP timePoint) const pure nothrow
  20128. {
  20129. return timePoint >= _end;
  20130. }
  20131. /++
  20132. Whether this interval is before the given interval and does not
  20133. intersect it.
  20134. Params:
  20135. interval = The interval to check for against this interval.
  20136. Throws:
  20137. $(D DateTimeException) if the given interval is empty
  20138. Examples:
  20139. --------------------
  20140. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(
  20141. Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  20142. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(
  20143. Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  20144. assert(NegInfInterval!Date(Date(2012, 3, 1)).isBefore(
  20145. Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
  20146. --------------------
  20147. +/
  20148. bool isBefore(in Interval!TP interval) const pure
  20149. {
  20150. interval._enforceNotEmpty();
  20151. return _end <= interval._begin;
  20152. }
  20153. /++
  20154. Whether this interval is before the given interval and does not
  20155. intersect it.
  20156. Params:
  20157. interval = The interval to check for against this interval.
  20158. Examples:
  20159. --------------------
  20160. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(
  20161. PosInfInterval!Date(Date(1999, 5, 4))));
  20162. assert(NegInfInterval!Date(Date(2012, 3, 1)).isBefore(
  20163. PosInfInterval!Date(Date(2012, 3, 1))));
  20164. --------------------
  20165. +/
  20166. bool isBefore(in PosInfInterval!TP interval) const pure nothrow
  20167. {
  20168. return _end <= interval._begin;
  20169. }
  20170. /++
  20171. Whether this interval is before the given interval and does not
  20172. intersect it.
  20173. Always returns false because an interval beginning at negative
  20174. infinity can never be before another interval beginning at negative
  20175. infinity.
  20176. Params:
  20177. interval = The interval to check for against this interval.
  20178. Examples:
  20179. --------------------
  20180. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(
  20181. NegInfInterval!Date(Date(1996, 5, 4))));
  20182. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(
  20183. NegInfInterval!Date(Date(2013, 7, 9))));
  20184. --------------------
  20185. +/
  20186. bool isBefore(in NegInfInterval interval) const pure nothrow
  20187. {
  20188. return false;
  20189. }
  20190. /++
  20191. Whether this interval is after the given time point.
  20192. Always returns false because an interval beginning at negative infinity
  20193. can never be after any time point.
  20194. Params:
  20195. timePoint = The time point to check whether this interval is after
  20196. it.
  20197. Examples:
  20198. --------------------
  20199. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Date(1994, 12, 24)));
  20200. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Date(2000, 1, 5)));
  20201. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Date(2012, 3, 1)));
  20202. --------------------
  20203. +/
  20204. bool isAfter(in TP timePoint) const pure nothrow
  20205. {
  20206. return false;
  20207. }
  20208. /++
  20209. Whether this interval is after the given interval and does not
  20210. intersect it.
  20211. Always returns false (unless the given interval is empty) because an
  20212. interval beginning at negative infinity can never be after any other
  20213. interval.
  20214. Params:
  20215. interval = The interval to check against this interval.
  20216. Throws:
  20217. $(D DateTimeException) if the given interval is empty.
  20218. Examples:
  20219. --------------------
  20220. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(
  20221. Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  20222. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(
  20223. Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  20224. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(
  20225. Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
  20226. --------------------
  20227. +/
  20228. bool isAfter(in Interval!TP interval) const pure
  20229. {
  20230. interval._enforceNotEmpty();
  20231. return false;
  20232. }
  20233. /++
  20234. Whether this interval is after the given interval and does not intersect
  20235. it.
  20236. Always returns false because an interval beginning at negative infinity
  20237. can never be after any other interval.
  20238. Params:
  20239. interval = The interval to check against this interval.
  20240. Examples:
  20241. --------------------
  20242. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(
  20243. PosInfInterval!Date(Date(1999, 5, 4))));
  20244. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(
  20245. PosInfInterval!Date(Date(2012, 3, 1))));
  20246. --------------------
  20247. +/
  20248. bool isAfter(in PosInfInterval!TP interval) const pure nothrow
  20249. {
  20250. return false;
  20251. }
  20252. /++
  20253. Whether this interval is after the given interval and does not intersect
  20254. it.
  20255. Always returns false because an interval beginning at negative infinity
  20256. can never be after any other interval.
  20257. Params:
  20258. interval = The interval to check against this interval.
  20259. Examples:
  20260. --------------------
  20261. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(
  20262. NegInfInterval!Date(Date(1996, 5, 4))));
  20263. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(
  20264. NegInfInterval!Date(Date(2013, 7, 9))));
  20265. --------------------
  20266. +/
  20267. bool isAfter(in NegInfInterval interval) const pure nothrow
  20268. {
  20269. return false;
  20270. }
  20271. /++
  20272. Whether the given interval overlaps this interval.
  20273. Params:
  20274. interval = The interval to check for intersection with this interval.
  20275. Throws:
  20276. $(D DateTimeException) if the given interval is empty.
  20277. Examples:
  20278. --------------------
  20279. assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(
  20280. Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  20281. assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(
  20282. Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  20283. assert(!NegInfInterval!Date(Date(2012, 3, 1)).intersects(
  20284. Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
  20285. --------------------
  20286. +/
  20287. bool intersects(in Interval!TP interval) const pure
  20288. {
  20289. interval._enforceNotEmpty();
  20290. return interval._begin < _end;
  20291. }
  20292. /++
  20293. Whether the given interval overlaps this interval.
  20294. Params:
  20295. interval = The interval to check for intersection with this
  20296. interval.
  20297. Examples:
  20298. --------------------
  20299. assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(
  20300. PosInfInterval!Date(Date(1999, 5, 4))));
  20301. assert(!NegInfInterval!Date(Date(2012, 3, 1)).intersects(
  20302. PosInfInterval!Date(Date(2012, 3, 1))));
  20303. --------------------
  20304. +/
  20305. bool intersects(in PosInfInterval!TP interval) const pure nothrow
  20306. {
  20307. return interval._begin < _end;
  20308. }
  20309. /++
  20310. Whether the given interval overlaps this interval.
  20311. Always returns true because two intervals beginning at negative infinity
  20312. always overlap.
  20313. Params:
  20314. interval = The interval to check for intersection with this interval.
  20315. Examples:
  20316. --------------------
  20317. assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(
  20318. NegInfInterval!Date(Date(1996, 5, 4))));
  20319. assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(
  20320. NegInfInterval!Date(Date(2013, 7, 9))));
  20321. --------------------
  20322. +/
  20323. bool intersects(in NegInfInterval!TP interval) const pure nothrow
  20324. {
  20325. return true;
  20326. }
  20327. /++
  20328. Returns the intersection of two intervals
  20329. Params:
  20330. interval = The interval to intersect with this interval.
  20331. Throws:
  20332. $(D DateTimeException) if the two intervals do not intersect or if
  20333. the given interval is empty.
  20334. Examples:
  20335. --------------------
  20336. assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(
  20337. Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
  20338. Interval!Date(Date(1990, 7 , 6), Date(2000, 8, 2)));
  20339. assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(
  20340. Interval!Date(Date(1999, 1, 12), Date(2015, 9, 2))) ==
  20341. Interval!Date(Date(1999, 1 , 12), Date(2012, 3, 1)));
  20342. --------------------
  20343. +/
  20344. Interval!TP intersection(in Interval!TP interval) const
  20345. {
  20346. enforce(this.intersects(interval), new DateTimeException(format("%s and %s do not intersect.", this, interval)));
  20347. auto end = _end < interval._end ? _end : interval._end;
  20348. return Interval!TP(interval._begin, end);
  20349. }
  20350. /++
  20351. Returns the intersection of two intervals
  20352. Params:
  20353. interval = The interval to intersect with this interval.
  20354. Throws:
  20355. $(D DateTimeException) if the two intervals do not intersect.
  20356. Examples:
  20357. --------------------
  20358. assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(
  20359. PosInfInterval!Date(Date(1990, 7, 6))) ==
  20360. Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
  20361. assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(
  20362. PosInfInterval!Date(Date(1999, 1, 12))) ==
  20363. Interval!Date(Date(1999, 1 , 12), Date(2012, 3, 1)));
  20364. --------------------
  20365. +/
  20366. Interval!TP intersection(in PosInfInterval!TP interval) const
  20367. {
  20368. enforce(this.intersects(interval), new DateTimeException(format("%s and %s do not intersect.", this, interval)));
  20369. return Interval!TP(interval._begin, _end);
  20370. }
  20371. /++
  20372. Returns the intersection of two intervals
  20373. Params:
  20374. interval = The interval to intersect with this interval.
  20375. Examples:
  20376. --------------------
  20377. assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(
  20378. NegInfInterval!Date(Date(1999, 7, 6))) ==
  20379. NegInfInterval!Date(Date(1999, 7 , 6)));
  20380. assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(
  20381. NegInfInterval!Date(Date(2013, 1, 12))) ==
  20382. NegInfInterval!Date(Date(2012, 3 , 1)));
  20383. --------------------
  20384. +/
  20385. NegInfInterval intersection(in NegInfInterval interval) const nothrow
  20386. {
  20387. return NegInfInterval(_end < interval._end ? _end : interval._end);
  20388. }
  20389. /++
  20390. Whether the given interval is adjacent to this interval.
  20391. Params:
  20392. interval = The interval to check whether its adjecent to this
  20393. interval.
  20394. Throws:
  20395. $(D DateTimeException) if the given interval is empty.
  20396. Examples:
  20397. --------------------
  20398. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(
  20399. Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  20400. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(
  20401. Interval!Date(Date(1999, 1, 12), Date(2012, 3, 1))));
  20402. assert(NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(
  20403. Interval!Date(Date(2012, 3, 1), Date(2019, 2, 2))));
  20404. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(
  20405. Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
  20406. --------------------
  20407. +/
  20408. bool isAdjacent(in Interval!TP interval) const pure
  20409. {
  20410. interval._enforceNotEmpty();
  20411. return interval._begin == _end;
  20412. }
  20413. /++
  20414. Whether the given interval is adjacent to this interval.
  20415. Params:
  20416. interval = The interval to check whether its adjecent to this
  20417. interval.
  20418. Examples:
  20419. --------------------
  20420. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(
  20421. PosInfInterval!Date(Date(1999, 5, 4))));
  20422. assert(NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(
  20423. PosInfInterval!Date(Date(2012, 3, 1))));
  20424. --------------------
  20425. +/
  20426. bool isAdjacent(in PosInfInterval!TP interval) const pure nothrow
  20427. {
  20428. return interval._begin == _end;
  20429. }
  20430. /++
  20431. Whether the given interval is adjacent to this interval.
  20432. Always returns false because two intervals beginning at negative
  20433. infinity can never be adjacent to one another.
  20434. Params:
  20435. interval = The interval to check whether its adjecent to this
  20436. interval.
  20437. Examples:
  20438. --------------------
  20439. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(
  20440. NegInfInterval!Date(Date(1996, 5, 4))));
  20441. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(
  20442. NegInfInterval!Date(Date(2012, 3, 1))));
  20443. --------------------
  20444. +/
  20445. bool isAdjacent(in NegInfInterval interval) const pure nothrow
  20446. {
  20447. return false;
  20448. }
  20449. /++
  20450. Returns the union of two intervals
  20451. Params:
  20452. interval = The interval to merge with this interval.
  20453. Throws:
  20454. $(D DateTimeException) if the two intervals do not intersect and are
  20455. not adjacent or if the given interval is empty.
  20456. Note:
  20457. There is no overload for $(D merge) which takes a
  20458. $(D PosInfInterval). This is because you can't have an interval
  20459. which goes from negative infinity to positive infinity.
  20460. Examples:
  20461. --------------------
  20462. assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(
  20463. Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
  20464. NegInfInterval!Date(Date(2012, 3 , 1)));
  20465. assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(
  20466. Interval!Date(Date(1999, 1, 12), Date(2015, 9, 2))) ==
  20467. NegInfInterval!Date(Date(2015, 9 , 2)));
  20468. --------------------
  20469. +/
  20470. NegInfInterval merge(in Interval!TP interval) const
  20471. {
  20472. enforce(this.isAdjacent(interval) || this.intersects(interval),
  20473. new DateTimeException(format("%s and %s are not adjacent and do not intersect.", this, interval)));
  20474. return NegInfInterval(_end > interval._end ? _end : interval._end);
  20475. }
  20476. /++
  20477. Returns the union of two intervals
  20478. Params:
  20479. interval = The interval to merge with this interval.
  20480. Note:
  20481. There is no overload for $(D merge) which takes a
  20482. $(D PosInfInterval). This is because you can't have an interval
  20483. which goes from negative infinity to positive infinity.
  20484. Examples:
  20485. --------------------
  20486. assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(
  20487. NegInfInterval!Date(Date(1999, 7, 6))) ==
  20488. NegInfInterval!Date(Date(2012, 3 , 1)));
  20489. assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(
  20490. NegInfInterval!Date(Date(2013, 1, 12))) ==
  20491. NegInfInterval!Date(Date(2013, 1 , 12)));
  20492. --------------------
  20493. +/
  20494. NegInfInterval merge(in NegInfInterval interval) const pure nothrow
  20495. {
  20496. return NegInfInterval(_end > interval._end ? _end : interval._end);
  20497. }
  20498. /++
  20499. Returns an interval that covers from the earliest time point of two
  20500. intervals up to (but not including) the latest time point of two
  20501. intervals.
  20502. Params:
  20503. interval = The interval to create a span together with this
  20504. interval.
  20505. Throws:
  20506. $(D DateTimeException) if the given interval is empty.
  20507. Note:
  20508. There is no overload for $(D span) which takes a
  20509. $(D PosInfInterval). This is because you can't have an interval
  20510. which goes from negative infinity to positive infinity.
  20511. Examples:
  20512. --------------------
  20513. assert(NegInfInterval!Date(Date(2012, 3, 1)).span(
  20514. Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) ==
  20515. NegInfInterval!Date(Date(2012, 3 , 1)));
  20516. assert(NegInfInterval!Date(Date(2012, 3, 1)).span(
  20517. Interval!Date(Date(1999, 1, 12), Date(2015, 9, 2))) ==
  20518. NegInfInterval!Date(Date(2015, 9 , 2)));
  20519. assert(NegInfInterval!Date(Date(1600, 1, 7)).span(
  20520. Interval!Date(Date(2012, 3, 11), Date(2017, 7, 1))) ==
  20521. NegInfInterval!Date(Date(2017, 7 , 1)));
  20522. --------------------
  20523. +/
  20524. NegInfInterval span(in Interval!TP interval) const pure
  20525. {
  20526. interval._enforceNotEmpty();
  20527. return NegInfInterval(_end > interval._end ? _end : interval._end);
  20528. }
  20529. /++
  20530. Returns an interval that covers from the earliest time point of two
  20531. intervals up to (but not including) the latest time point of two
  20532. intervals.
  20533. Params:
  20534. interval = The interval to create a span together with this
  20535. interval.
  20536. Note:
  20537. There is no overload for $(D span) which takes a
  20538. $(D PosInfInterval). This is because you can't have an interval
  20539. which goes from negative infinity to positive infinity.
  20540. Examples:
  20541. --------------------
  20542. assert(NegInfInterval!Date(Date(2012, 3, 1)).span(
  20543. NegInfInterval!Date(Date(1999, 7, 6))) ==
  20544. NegInfInterval!Date(Date(2012, 3 , 1)));
  20545. assert(NegInfInterval!Date(Date(2012, 3, 1)).span(
  20546. NegInfInterval!Date(Date(2013, 1, 12))) ==
  20547. NegInfInterval!Date(Date(2013, 1 , 12)));
  20548. --------------------
  20549. +/
  20550. NegInfInterval span(in NegInfInterval interval) const pure nothrow
  20551. {
  20552. return NegInfInterval(_end > interval._end ? _end : interval._end);
  20553. }
  20554. /++
  20555. Shifts the $(D end) of this interval forward or backwards in time by the
  20556. given duration (a positive duration shifts the interval forward; a
  20557. negative duration shifts it backward). Effectively, it does
  20558. $(D end += duration).
  20559. Params:
  20560. duration = The duration to shift the interval by.
  20561. Examples:
  20562. --------------------
  20563. auto interval1 = NegInfInterval!Date(Date(2012, 4, 5));
  20564. auto interval2 = NegInfInterval!Date(Date(2012, 4, 5));
  20565. interval1.shift(dur!"days"(50));
  20566. assert(interval1 == NegInfInterval!Date(Date(2012, 5, 25)));
  20567. interval2.shift(dur!"days"(-50));
  20568. assert(interval2 == NegInfInterval!Date( Date(2012, 2, 15)));
  20569. --------------------
  20570. +/
  20571. void shift(D)(D duration) pure nothrow
  20572. if(__traits(compiles, end + duration))
  20573. {
  20574. _end += duration;
  20575. }
  20576. static if(__traits(compiles, end.add!"months"(1)) &&
  20577. __traits(compiles, end.add!"years"(1)))
  20578. {
  20579. /++
  20580. Shifts the $(D end) of this interval forward or backwards in time by
  20581. the given number of years and/or months (a positive number of years
  20582. and months shifts the interval forward; a negative number shifts it
  20583. backward). It adds the years the given years and months to end. It
  20584. effectively calls $(D add!"years"()) and then $(D add!"months"())
  20585. on end with the given number of years and months.
  20586. Params:
  20587. years = The number of years to shift the interval by.
  20588. months = The number of months to shift the interval by.
  20589. allowOverflow = Whether the days should be allowed to overflow
  20590. on $(D end), causing its month to increment.
  20591. Throws:
  20592. $(D DateTimeException) if empty is true or if the resulting
  20593. interval would be invalid.
  20594. Examples:
  20595. --------------------
  20596. auto interval1 = NegInfInterval!Date(Date(2012, 3, 1));
  20597. auto interval2 = NegInfInterval!Date(Date(2012, 3, 1));
  20598. interval1.shift(2);
  20599. assert(interval1 == NegInfInterval!Date(Date(2014, 3, 1)));
  20600. interval2.shift(-2);
  20601. assert(interval2 == NegInfInterval!Date(Date(2010, 3, 1)));
  20602. --------------------
  20603. +/
  20604. void shift(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
  20605. if(isIntegral!T)
  20606. {
  20607. auto end = _end;
  20608. end.add!"years"(years, allowOverflow);
  20609. end.add!"months"(months, allowOverflow);
  20610. _end = end;
  20611. }
  20612. }
  20613. /++
  20614. Expands the interval forwards in time. Effectively, it does
  20615. $(D end += duration).
  20616. Params:
  20617. duration = The duration to expand the interval by.
  20618. dir = The direction in time to expand the interval.
  20619. Examples:
  20620. --------------------
  20621. auto interval1 = NegInfInterval!Date(Date(2012, 3, 1));
  20622. auto interval2 = NegInfInterval!Date(Date(2012, 3, 1));
  20623. interval1.expand(dur!"days"(2));
  20624. assert(interval1 == NegInfInterval!Date(Date(2012, 3, 3)));
  20625. interval2.expand(dur!"days"(-2));
  20626. assert(interval2 == NegInfInterval!Date(Date(2012, 2, 28)));
  20627. --------------------
  20628. +/
  20629. void expand(D)(D duration) pure nothrow
  20630. if(__traits(compiles, end + duration))
  20631. {
  20632. _end += duration;
  20633. }
  20634. static if(__traits(compiles, end.add!"months"(1)) &&
  20635. __traits(compiles, end.add!"years"(1)))
  20636. {
  20637. /++
  20638. Expands the interval forwards and/or backwards in time. Effectively,
  20639. it adds the given number of months/years to end.
  20640. Params:
  20641. years = The number of years to expand the interval by.
  20642. months = The number of months to expand the interval by.
  20643. allowOverflow = Whether the days should be allowed to overflow
  20644. on $(D end), causing their month to increment.
  20645. Throws:
  20646. $(D DateTimeException) if empty is true or if the resulting
  20647. interval would be invalid.
  20648. Examples:
  20649. --------------------
  20650. auto interval1 = NegInfInterval!Date(Date(2012, 3, 1));
  20651. auto interval2 = NegInfInterval!Date(Date(2012, 3, 1));
  20652. interval1.expand(2);
  20653. assert(interval1 == NegInfInterval!Date(Date(2014, 3, 1)));
  20654. interval2.expand(-2);
  20655. assert(interval2 == NegInfInterval!Date(Date(2010, 3, 1)));
  20656. --------------------
  20657. +/
  20658. void expand(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
  20659. if(isIntegral!T)
  20660. {
  20661. auto end = _end;
  20662. end.add!"years"(years, allowOverflow);
  20663. end.add!"months"(months, allowOverflow);
  20664. _end = end;
  20665. return;
  20666. }
  20667. }
  20668. /++
  20669. Returns a range which iterates backwards over the interval, starting
  20670. at $(D end), using $(D_PARAM func) to generate each successive time
  20671. point.
  20672. The range's $(D front) is the interval's $(D end). $(D_PARAM func) is
  20673. used to generate the next $(D front) when $(D popFront) is called. If
  20674. $(D_PARAM popFirst) is $(D PopFirst.yes), then $(D popFront) is called
  20675. before the range is returned (so that $(D front) is a time point which
  20676. $(D_PARAM func) would generate).
  20677. If $(D_PARAM func) ever generates a time point greater than or equal to
  20678. the current $(D front) of the range, then a $(D DateTimeException) will
  20679. be thrown.
  20680. There are helper functions in this module which generate common
  20681. delegates to pass to $(D bwdRange). Their documentation starts with
  20682. "Range-generating function," so you can easily search for them.
  20683. Params:
  20684. func = The function used to generate the time points of the
  20685. range over the interval.
  20686. popFirst = Whether $(D popFront) should be called on the range
  20687. before returning it.
  20688. Throws:
  20689. $(D DateTimeException) if this interval is empty.
  20690. Warning:
  20691. $(D_PARAM func) must be logically pure. Ideally, $(D_PARAM func)
  20692. would be a function pointer to a pure function, but forcing
  20693. $(D_PARAM func) to be pure is far too restrictive to be useful, and
  20694. in order to have the ease of use of having functions which generate
  20695. functions to pass to $(D fwdRange), $(D_PARAM func) must be a
  20696. delegate.
  20697. If $(D_PARAM func) retains state which changes as it is called, then
  20698. some algorithms will not work correctly, because the range's
  20699. $(D save) will have failed to have really saved the range's state.
  20700. So, if you want to avoid such bugs, don't pass a delegate which is
  20701. not logically pure to $(D fwdRange). If $(D_PARAM func) is given the
  20702. same time point with two different calls, it must return the same
  20703. result both times.
  20704. Of course, none of the functions in this module have this problem,
  20705. so it's only relevant if you're creating your own delegate.
  20706. Examples:
  20707. --------------------
  20708. auto interval = NegInfInterval!Date(Date(2010, 9, 9));
  20709. auto func = (in Date date) //For iterating over even-numbered days.
  20710. {
  20711. if((date.day & 1) == 0)
  20712. return date - dur!"days"(2);
  20713. return date - dur!"days"(1);
  20714. };
  20715. auto range = interval.bwdRange(func);
  20716. assert(range.front == Date(2010, 9, 9)); //An odd day. Using PopFirst.yes would have made this Date(2010, 9, 8).
  20717. range.popFront();
  20718. assert(range.front == Date(2010, 9, 8));
  20719. range.popFront();
  20720. assert(range.front == Date(2010, 9, 6));
  20721. range.popFront();
  20722. assert(range.front == Date(2010, 9, 4));
  20723. range.popFront();
  20724. assert(range.front == Date(2010, 9, 2));
  20725. range.popFront();
  20726. assert(!range.empty);
  20727. --------------------
  20728. +/
  20729. NegInfIntervalRange!(TP) bwdRange(TP delegate(in TP) func, PopFirst popFirst = PopFirst.no) const
  20730. {
  20731. auto range = NegInfIntervalRange!(TP)(this, func);
  20732. if(popFirst == PopFirst.yes)
  20733. range.popFront();
  20734. return range;
  20735. }
  20736. /+
  20737. Converts this interval to a string.
  20738. +/
  20739. //Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
  20740. //have versions of toString() with extra modifiers, so we define one version
  20741. //with modifiers and one without.
  20742. string toString()
  20743. {
  20744. return _toStringImpl();
  20745. }
  20746. /++
  20747. Converts this interval to a string.
  20748. +/
  20749. //Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
  20750. //have versions of toString() with extra modifiers, so we define one version
  20751. //with modifiers and one without.
  20752. string toString() const nothrow
  20753. {
  20754. return _toStringImpl();
  20755. }
  20756. private:
  20757. /+
  20758. Since we have two versions of toString(), we have _toStringImpl()
  20759. so that they can share implementations.
  20760. +/
  20761. string _toStringImpl() const nothrow
  20762. {
  20763. try
  20764. return format("[-∞ - %s)", _end);
  20765. catch(Exception e)
  20766. assert(0, "format() threw.");
  20767. }
  20768. TP _end;
  20769. }
  20770. //Test NegInfInterval's constructor.
  20771. unittest
  20772. {
  20773. version(testStdDateTime)
  20774. {
  20775. NegInfInterval!Date(Date.init);
  20776. NegInfInterval!TimeOfDay(TimeOfDay.init);
  20777. NegInfInterval!DateTime(DateTime.init);
  20778. NegInfInterval!SysTime(SysTime(0));
  20779. }
  20780. }
  20781. //Test NegInfInterval's end.
  20782. unittest
  20783. {
  20784. version(testStdDateTime)
  20785. {
  20786. _assertPred!"=="(NegInfInterval!Date(Date(2010, 1, 1)).end, Date(2010, 1, 1));
  20787. _assertPred!"=="(NegInfInterval!Date(Date(2010, 1, 1)).end, Date(2010, 1, 1));
  20788. _assertPred!"=="(NegInfInterval!Date(Date(1998, 1, 1)).end, Date(1998, 1, 1));
  20789. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  20790. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  20791. static assert(__traits(compiles, cNegInfInterval.end));
  20792. static assert(__traits(compiles, iNegInfInterval.end));
  20793. //Verify Examples.
  20794. assert(NegInfInterval!Date(Date(2012, 3, 1)).end == Date(2012, 3, 1));
  20795. }
  20796. }
  20797. //Test NegInfInterval's empty.
  20798. unittest
  20799. {
  20800. version(testStdDateTime)
  20801. {
  20802. assert(!NegInfInterval!Date(Date(2010, 1, 1)).empty);
  20803. assert(!NegInfInterval!TimeOfDay(TimeOfDay(0, 30, 0)).empty);
  20804. assert(!NegInfInterval!DateTime(DateTime(2010, 1, 1, 0, 30, 0)).empty);
  20805. assert(!NegInfInterval!SysTime(SysTime(DateTime(2010, 1, 1, 0, 30, 0))).empty);
  20806. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  20807. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  20808. static assert(__traits(compiles, cNegInfInterval.empty));
  20809. static assert(__traits(compiles, iNegInfInterval.empty));
  20810. //Verify Examples.
  20811. assert(!NegInfInterval!Date(Date(1996, 1, 2)).empty);
  20812. }
  20813. }
  20814. //Test NegInfInterval's contains(time point).
  20815. unittest
  20816. {
  20817. version(testStdDateTime)
  20818. {
  20819. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  20820. assert(negInfInterval.contains(Date(2009, 7, 4)));
  20821. assert(negInfInterval.contains(Date(2010, 7, 3)));
  20822. assert(negInfInterval.contains(Date(2010, 7, 4)));
  20823. assert(negInfInterval.contains(Date(2010, 7, 5)));
  20824. assert(negInfInterval.contains(Date(2011, 7, 1)));
  20825. assert(negInfInterval.contains(Date(2012, 1, 6)));
  20826. assert(!negInfInterval.contains(Date(2012, 1, 7)));
  20827. assert(!negInfInterval.contains(Date(2012, 1, 8)));
  20828. assert(!negInfInterval.contains(Date(2013, 1, 7)));
  20829. const cdate = Date(2010, 7, 6);
  20830. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  20831. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  20832. static assert(__traits(compiles, negInfInterval.contains(cdate)));
  20833. static assert(__traits(compiles, cNegInfInterval.contains(cdate)));
  20834. static assert(__traits(compiles, iNegInfInterval.contains(cdate)));
  20835. //Verify Examples.
  20836. assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Date(1994, 12, 24)));
  20837. assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Date(2000, 1, 5)));
  20838. assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(Date(2012, 3, 1)));
  20839. }
  20840. }
  20841. //Test NegInfInterval's contains(Interval).
  20842. unittest
  20843. {
  20844. version(testStdDateTime)
  20845. {
  20846. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  20847. static void testInterval(in NegInfInterval!Date negInfInterval, in Interval!Date interval)
  20848. {
  20849. negInfInterval.contains(interval);
  20850. }
  20851. assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  20852. assert(negInfInterval.contains(negInfInterval));
  20853. assert(negInfInterval.contains(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
  20854. assert(!negInfInterval.contains(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
  20855. assert(negInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
  20856. assert(negInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
  20857. assert(negInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
  20858. assert(!negInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
  20859. assert(negInfInterval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
  20860. assert(negInfInterval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
  20861. assert(negInfInterval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
  20862. assert(!negInfInterval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
  20863. assert(!negInfInterval.contains(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
  20864. assert(!negInfInterval.contains(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
  20865. assert(negInfInterval.contains(NegInfInterval!Date(Date(2010, 7, 3))));
  20866. assert(negInfInterval.contains(NegInfInterval!Date(Date(2010, 7, 4))));
  20867. assert(negInfInterval.contains(NegInfInterval!Date(Date(2010, 7, 5))));
  20868. assert(negInfInterval.contains(NegInfInterval!Date(Date(2012, 1, 6))));
  20869. assert(negInfInterval.contains(NegInfInterval!Date(Date(2012, 1, 7))));
  20870. assert(!negInfInterval.contains(NegInfInterval!Date(Date(2012, 1, 8))));
  20871. assert(!NegInfInterval!Date(Date(2010, 7, 3)).contains(negInfInterval));
  20872. assert(!NegInfInterval!Date(Date(2010, 7, 4)).contains(negInfInterval));
  20873. assert(!NegInfInterval!Date(Date(2010, 7, 5)).contains(negInfInterval));
  20874. assert(!NegInfInterval!Date(Date(2012, 1, 6)).contains(negInfInterval));
  20875. assert(NegInfInterval!Date(Date(2012, 1, 7)).contains(negInfInterval));
  20876. assert(NegInfInterval!Date(Date(2012, 1, 8)).contains(negInfInterval));
  20877. assert(!negInfInterval.contains(PosInfInterval!Date(Date(2010, 7, 3))));
  20878. assert(!negInfInterval.contains(PosInfInterval!Date(Date(2010, 7, 4))));
  20879. assert(!negInfInterval.contains(PosInfInterval!Date(Date(2010, 7, 5))));
  20880. assert(!negInfInterval.contains(PosInfInterval!Date(Date(2012, 1, 6))));
  20881. assert(!negInfInterval.contains(PosInfInterval!Date(Date(2012, 1, 7))));
  20882. assert(!negInfInterval.contains(PosInfInterval!Date(Date(2012, 1, 8))));
  20883. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  20884. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  20885. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  20886. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  20887. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  20888. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  20889. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  20890. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  20891. static assert(__traits(compiles, negInfInterval.contains(interval)));
  20892. static assert(__traits(compiles, negInfInterval.contains(cInterval)));
  20893. static assert(__traits(compiles, negInfInterval.contains(iInterval)));
  20894. static assert(__traits(compiles, negInfInterval.contains(posInfInterval)));
  20895. static assert(__traits(compiles, negInfInterval.contains(cPosInfInterval)));
  20896. static assert(__traits(compiles, negInfInterval.contains(iPosInfInterval)));
  20897. static assert(__traits(compiles, negInfInterval.contains(negInfInterval)));
  20898. static assert(__traits(compiles, negInfInterval.contains(cNegInfInterval)));
  20899. static assert(__traits(compiles, negInfInterval.contains(iNegInfInterval)));
  20900. static assert(__traits(compiles, cNegInfInterval.contains(interval)));
  20901. static assert(__traits(compiles, cNegInfInterval.contains(cInterval)));
  20902. static assert(__traits(compiles, cNegInfInterval.contains(iInterval)));
  20903. static assert(__traits(compiles, cNegInfInterval.contains(posInfInterval)));
  20904. static assert(__traits(compiles, cNegInfInterval.contains(cPosInfInterval)));
  20905. static assert(__traits(compiles, cNegInfInterval.contains(iPosInfInterval)));
  20906. static assert(__traits(compiles, cNegInfInterval.contains(negInfInterval)));
  20907. static assert(__traits(compiles, cNegInfInterval.contains(cNegInfInterval)));
  20908. static assert(__traits(compiles, cNegInfInterval.contains(iNegInfInterval)));
  20909. static assert(__traits(compiles, iNegInfInterval.contains(interval)));
  20910. static assert(__traits(compiles, iNegInfInterval.contains(cInterval)));
  20911. static assert(__traits(compiles, iNegInfInterval.contains(iInterval)));
  20912. static assert(__traits(compiles, iNegInfInterval.contains(posInfInterval)));
  20913. static assert(__traits(compiles, iNegInfInterval.contains(cPosInfInterval)));
  20914. static assert(__traits(compiles, iNegInfInterval.contains(iPosInfInterval)));
  20915. static assert(__traits(compiles, iNegInfInterval.contains(negInfInterval)));
  20916. static assert(__traits(compiles, iNegInfInterval.contains(cNegInfInterval)));
  20917. static assert(__traits(compiles, iNegInfInterval.contains(iNegInfInterval)));
  20918. //Verify Examples.
  20919. assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  20920. assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  20921. assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
  20922. assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(PosInfInterval!Date(Date(1999, 5, 4))));
  20923. assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(NegInfInterval!Date(Date(1996, 5, 4))));
  20924. assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(NegInfInterval!Date(Date(2013, 7, 9))));
  20925. }
  20926. }
  20927. //Test NegInfInterval's isBefore(time point).
  20928. unittest
  20929. {
  20930. version(testStdDateTime)
  20931. {
  20932. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  20933. assert(!negInfInterval.isBefore(Date(2009, 7, 4)));
  20934. assert(!negInfInterval.isBefore(Date(2010, 7, 3)));
  20935. assert(!negInfInterval.isBefore(Date(2010, 7, 4)));
  20936. assert(!negInfInterval.isBefore(Date(2010, 7, 5)));
  20937. assert(!negInfInterval.isBefore(Date(2011, 7, 1)));
  20938. assert(!negInfInterval.isBefore(Date(2012, 1, 6)));
  20939. assert(negInfInterval.isBefore(Date(2012, 1, 7)));
  20940. assert(negInfInterval.isBefore(Date(2012, 1, 8)));
  20941. assert(negInfInterval.isBefore(Date(2013, 1, 7)));
  20942. const cdate = Date(2010, 7, 6);
  20943. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  20944. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  20945. static assert(__traits(compiles, negInfInterval.isBefore(cdate)));
  20946. static assert(__traits(compiles, cNegInfInterval.isBefore(cdate)));
  20947. static assert(__traits(compiles, iNegInfInterval.isBefore(cdate)));
  20948. //Verify Examples.
  20949. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Date(1994, 12, 24)));
  20950. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Date(2000, 1, 5)));
  20951. assert(NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Date(2012, 3, 1)));
  20952. }
  20953. }
  20954. //Test NegInfInterval's isBefore(Interval).
  20955. unittest
  20956. {
  20957. version(testStdDateTime)
  20958. {
  20959. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  20960. static void testInterval(in NegInfInterval!Date negInfInterval, in Interval!Date interval)
  20961. {
  20962. negInfInterval.isBefore(interval);
  20963. }
  20964. assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  20965. assert(!negInfInterval.isBefore(negInfInterval));
  20966. assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
  20967. assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
  20968. assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
  20969. assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
  20970. assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
  20971. assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
  20972. assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
  20973. assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
  20974. assert(!negInfInterval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
  20975. assert(!negInfInterval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
  20976. assert(negInfInterval.isBefore(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
  20977. assert(negInfInterval.isBefore(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
  20978. assert(!negInfInterval.isBefore(NegInfInterval!Date(Date(2010, 7, 3))));
  20979. assert(!negInfInterval.isBefore(NegInfInterval!Date(Date(2010, 7, 4))));
  20980. assert(!negInfInterval.isBefore(NegInfInterval!Date(Date(2010, 7, 5))));
  20981. assert(!negInfInterval.isBefore(NegInfInterval!Date(Date(2012, 1, 6))));
  20982. assert(!negInfInterval.isBefore(NegInfInterval!Date(Date(2012, 1, 7))));
  20983. assert(!negInfInterval.isBefore(NegInfInterval!Date(Date(2012, 1, 8))));
  20984. assert(!NegInfInterval!Date(Date(2010, 7, 3)).isBefore(negInfInterval));
  20985. assert(!NegInfInterval!Date(Date(2010, 7, 4)).isBefore(negInfInterval));
  20986. assert(!NegInfInterval!Date(Date(2010, 7, 5)).isBefore(negInfInterval));
  20987. assert(!NegInfInterval!Date(Date(2012, 1, 6)).isBefore(negInfInterval));
  20988. assert(!NegInfInterval!Date(Date(2012, 1, 7)).isBefore(negInfInterval));
  20989. assert(!NegInfInterval!Date(Date(2012, 1, 8)).isBefore(negInfInterval));
  20990. assert(!negInfInterval.isBefore(PosInfInterval!Date(Date(2010, 7, 3))));
  20991. assert(!negInfInterval.isBefore(PosInfInterval!Date(Date(2010, 7, 4))));
  20992. assert(!negInfInterval.isBefore(PosInfInterval!Date(Date(2010, 7, 5))));
  20993. assert(!negInfInterval.isBefore(PosInfInterval!Date(Date(2012, 1, 6))));
  20994. assert(negInfInterval.isBefore(PosInfInterval!Date(Date(2012, 1, 7))));
  20995. assert(negInfInterval.isBefore(PosInfInterval!Date(Date(2012, 1, 8))));
  20996. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  20997. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  20998. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  20999. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  21000. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  21001. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  21002. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21003. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21004. static assert(__traits(compiles, negInfInterval.isBefore(interval)));
  21005. static assert(__traits(compiles, negInfInterval.isBefore(cInterval)));
  21006. static assert(__traits(compiles, negInfInterval.isBefore(iInterval)));
  21007. static assert(__traits(compiles, negInfInterval.isBefore(posInfInterval)));
  21008. static assert(__traits(compiles, negInfInterval.isBefore(cPosInfInterval)));
  21009. static assert(__traits(compiles, negInfInterval.isBefore(iPosInfInterval)));
  21010. static assert(__traits(compiles, negInfInterval.isBefore(negInfInterval)));
  21011. static assert(__traits(compiles, negInfInterval.isBefore(cNegInfInterval)));
  21012. static assert(__traits(compiles, negInfInterval.isBefore(iNegInfInterval)));
  21013. static assert(__traits(compiles, cNegInfInterval.isBefore(interval)));
  21014. static assert(__traits(compiles, cNegInfInterval.isBefore(cInterval)));
  21015. static assert(__traits(compiles, cNegInfInterval.isBefore(iInterval)));
  21016. static assert(__traits(compiles, cNegInfInterval.isBefore(posInfInterval)));
  21017. static assert(__traits(compiles, cNegInfInterval.isBefore(cPosInfInterval)));
  21018. static assert(__traits(compiles, cNegInfInterval.isBefore(iPosInfInterval)));
  21019. static assert(__traits(compiles, cNegInfInterval.isBefore(negInfInterval)));
  21020. static assert(__traits(compiles, cNegInfInterval.isBefore(cNegInfInterval)));
  21021. static assert(__traits(compiles, cNegInfInterval.isBefore(iNegInfInterval)));
  21022. static assert(__traits(compiles, iNegInfInterval.isBefore(interval)));
  21023. static assert(__traits(compiles, iNegInfInterval.isBefore(cInterval)));
  21024. static assert(__traits(compiles, iNegInfInterval.isBefore(iInterval)));
  21025. static assert(__traits(compiles, iNegInfInterval.isBefore(posInfInterval)));
  21026. static assert(__traits(compiles, iNegInfInterval.isBefore(cPosInfInterval)));
  21027. static assert(__traits(compiles, iNegInfInterval.isBefore(iPosInfInterval)));
  21028. static assert(__traits(compiles, iNegInfInterval.isBefore(negInfInterval)));
  21029. static assert(__traits(compiles, iNegInfInterval.isBefore(cNegInfInterval)));
  21030. static assert(__traits(compiles, iNegInfInterval.isBefore(iNegInfInterval)));
  21031. //Verify Examples.
  21032. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  21033. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  21034. assert(NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
  21035. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(PosInfInterval!Date(Date(1999, 5, 4))));
  21036. assert(NegInfInterval!Date(Date(2012, 3, 1)).isBefore(PosInfInterval!Date(Date(2012, 3, 1))));
  21037. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(NegInfInterval!Date(Date(1996, 5, 4))));
  21038. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(NegInfInterval!Date(Date(2013, 7, 9))));
  21039. }
  21040. }
  21041. //Test NegInfInterval's isAfter(time point).
  21042. unittest
  21043. {
  21044. version(testStdDateTime)
  21045. {
  21046. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21047. assert(!negInfInterval.isAfter(Date(2009, 7, 4)));
  21048. assert(!negInfInterval.isAfter(Date(2010, 7, 3)));
  21049. assert(!negInfInterval.isAfter(Date(2010, 7, 4)));
  21050. assert(!negInfInterval.isAfter(Date(2010, 7, 5)));
  21051. assert(!negInfInterval.isAfter(Date(2011, 7, 1)));
  21052. assert(!negInfInterval.isAfter(Date(2012, 1, 6)));
  21053. assert(!negInfInterval.isAfter(Date(2012, 1, 7)));
  21054. assert(!negInfInterval.isAfter(Date(2012, 1, 8)));
  21055. assert(!negInfInterval.isAfter(Date(2013, 1, 7)));
  21056. const cdate = Date(2010, 7, 6);
  21057. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21058. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21059. static assert(__traits(compiles, negInfInterval.isAfter(cdate)));
  21060. static assert(__traits(compiles, cNegInfInterval.isAfter(cdate)));
  21061. static assert(__traits(compiles, iNegInfInterval.isAfter(cdate)));
  21062. }
  21063. }
  21064. //Test NegInfInterval's isAfter(Interval).
  21065. unittest
  21066. {
  21067. version(testStdDateTime)
  21068. {
  21069. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21070. static void testInterval(in NegInfInterval!Date negInfInterval, in Interval!Date interval)
  21071. {
  21072. negInfInterval.isAfter(interval);
  21073. }
  21074. assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  21075. assert(!negInfInterval.isAfter(negInfInterval));
  21076. assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
  21077. assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
  21078. assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
  21079. assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
  21080. assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
  21081. assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
  21082. assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
  21083. assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
  21084. assert(!negInfInterval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
  21085. assert(!negInfInterval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
  21086. assert(!negInfInterval.isAfter(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
  21087. assert(!negInfInterval.isAfter(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
  21088. assert(!negInfInterval.isAfter(NegInfInterval!Date(Date(2010, 7, 3))));
  21089. assert(!negInfInterval.isAfter(NegInfInterval!Date(Date(2010, 7, 4))));
  21090. assert(!negInfInterval.isAfter(NegInfInterval!Date(Date(2010, 7, 5))));
  21091. assert(!negInfInterval.isAfter(NegInfInterval!Date(Date(2012, 1, 6))));
  21092. assert(!negInfInterval.isAfter(NegInfInterval!Date(Date(2012, 1, 7))));
  21093. assert(!negInfInterval.isAfter(NegInfInterval!Date(Date(2012, 1, 8))));
  21094. assert(!NegInfInterval!Date(Date(2010, 7, 3)).isAfter(negInfInterval));
  21095. assert(!NegInfInterval!Date(Date(2010, 7, 4)).isAfter(negInfInterval));
  21096. assert(!NegInfInterval!Date(Date(2010, 7, 5)).isAfter(negInfInterval));
  21097. assert(!NegInfInterval!Date(Date(2012, 1, 6)).isAfter(negInfInterval));
  21098. assert(!NegInfInterval!Date(Date(2012, 1, 7)).isAfter(negInfInterval));
  21099. assert(!NegInfInterval!Date(Date(2012, 1, 8)).isAfter(negInfInterval));
  21100. assert(!negInfInterval.isAfter(PosInfInterval!Date(Date(2010, 7, 3))));
  21101. assert(!negInfInterval.isAfter(PosInfInterval!Date(Date(2010, 7, 4))));
  21102. assert(!negInfInterval.isAfter(PosInfInterval!Date(Date(2010, 7, 5))));
  21103. assert(!negInfInterval.isAfter(PosInfInterval!Date(Date(2012, 1, 6))));
  21104. assert(!negInfInterval.isAfter(PosInfInterval!Date(Date(2012, 1, 7))));
  21105. assert(!negInfInterval.isAfter(PosInfInterval!Date(Date(2012, 1, 8))));
  21106. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  21107. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  21108. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  21109. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  21110. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  21111. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  21112. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21113. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21114. static assert(__traits(compiles, negInfInterval.isAfter(interval)));
  21115. static assert(__traits(compiles, negInfInterval.isAfter(cInterval)));
  21116. static assert(__traits(compiles, negInfInterval.isAfter(iInterval)));
  21117. static assert(__traits(compiles, negInfInterval.isAfter(posInfInterval)));
  21118. static assert(__traits(compiles, negInfInterval.isAfter(cPosInfInterval)));
  21119. static assert(__traits(compiles, negInfInterval.isAfter(iPosInfInterval)));
  21120. static assert(__traits(compiles, negInfInterval.isAfter(negInfInterval)));
  21121. static assert(__traits(compiles, negInfInterval.isAfter(cNegInfInterval)));
  21122. static assert(__traits(compiles, negInfInterval.isAfter(iNegInfInterval)));
  21123. static assert(__traits(compiles, cNegInfInterval.isAfter(interval)));
  21124. static assert(__traits(compiles, cNegInfInterval.isAfter(cInterval)));
  21125. static assert(__traits(compiles, cNegInfInterval.isAfter(iInterval)));
  21126. static assert(__traits(compiles, cNegInfInterval.isAfter(posInfInterval)));
  21127. static assert(__traits(compiles, cNegInfInterval.isAfter(cPosInfInterval)));
  21128. static assert(__traits(compiles, cNegInfInterval.isAfter(iPosInfInterval)));
  21129. static assert(__traits(compiles, cNegInfInterval.isAfter(negInfInterval)));
  21130. static assert(__traits(compiles, cNegInfInterval.isAfter(cNegInfInterval)));
  21131. static assert(__traits(compiles, cNegInfInterval.isAfter(iNegInfInterval)));
  21132. static assert(__traits(compiles, iNegInfInterval.isAfter(interval)));
  21133. static assert(__traits(compiles, iNegInfInterval.isAfter(cInterval)));
  21134. static assert(__traits(compiles, iNegInfInterval.isAfter(iInterval)));
  21135. static assert(__traits(compiles, iNegInfInterval.isAfter(posInfInterval)));
  21136. static assert(__traits(compiles, iNegInfInterval.isAfter(cPosInfInterval)));
  21137. static assert(__traits(compiles, iNegInfInterval.isAfter(iPosInfInterval)));
  21138. static assert(__traits(compiles, iNegInfInterval.isAfter(negInfInterval)));
  21139. static assert(__traits(compiles, iNegInfInterval.isAfter(cNegInfInterval)));
  21140. static assert(__traits(compiles, iNegInfInterval.isAfter(iNegInfInterval)));
  21141. //Verify Examples.
  21142. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Date(1994, 12, 24)));
  21143. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Date(2000, 1, 5)));
  21144. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Date(2012, 3, 1)));
  21145. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  21146. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  21147. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
  21148. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(PosInfInterval!Date(Date(1999, 5, 4))));
  21149. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(PosInfInterval!Date(Date(2012, 3, 1))));
  21150. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(NegInfInterval!Date(Date(1996, 5, 4))));
  21151. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(NegInfInterval!Date(Date(2013, 7, 9))));
  21152. }
  21153. }
  21154. //Test NegInfInterval's intersects().
  21155. unittest
  21156. {
  21157. version(testStdDateTime)
  21158. {
  21159. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21160. static void testInterval(in NegInfInterval!Date negInfInterval, in Interval!Date interval)
  21161. {
  21162. negInfInterval.intersects(interval);
  21163. }
  21164. assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  21165. assert(negInfInterval.intersects(negInfInterval));
  21166. assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
  21167. assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
  21168. assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
  21169. assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
  21170. assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
  21171. assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
  21172. assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
  21173. assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
  21174. assert(negInfInterval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
  21175. assert(negInfInterval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
  21176. assert(!negInfInterval.intersects(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
  21177. assert(!negInfInterval.intersects(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
  21178. assert(negInfInterval.intersects(NegInfInterval!Date(Date(2010, 7, 3))));
  21179. assert(negInfInterval.intersects(NegInfInterval!Date(Date(2010, 7, 4))));
  21180. assert(negInfInterval.intersects(NegInfInterval!Date(Date(2010, 7, 5))));
  21181. assert(negInfInterval.intersects(NegInfInterval!Date(Date(2012, 1, 6))));
  21182. assert(negInfInterval.intersects(NegInfInterval!Date(Date(2012, 1, 7))));
  21183. assert(negInfInterval.intersects(NegInfInterval!Date(Date(2012, 1, 8))));
  21184. assert(NegInfInterval!Date(Date(2010, 7, 3)).intersects(negInfInterval));
  21185. assert(NegInfInterval!Date(Date(2010, 7, 4)).intersects(negInfInterval));
  21186. assert(NegInfInterval!Date(Date(2010, 7, 5)).intersects(negInfInterval));
  21187. assert(NegInfInterval!Date(Date(2012, 1, 6)).intersects(negInfInterval));
  21188. assert(NegInfInterval!Date(Date(2012, 1, 7)).intersects(negInfInterval));
  21189. assert(NegInfInterval!Date(Date(2012, 1, 8)).intersects(negInfInterval));
  21190. assert(negInfInterval.intersects(PosInfInterval!Date(Date(2010, 7, 3))));
  21191. assert(negInfInterval.intersects(PosInfInterval!Date(Date(2010, 7, 4))));
  21192. assert(negInfInterval.intersects(PosInfInterval!Date(Date(2010, 7, 5))));
  21193. assert(negInfInterval.intersects(PosInfInterval!Date(Date(2012, 1, 6))));
  21194. assert(!negInfInterval.intersects(PosInfInterval!Date(Date(2012, 1, 7))));
  21195. assert(!negInfInterval.intersects(PosInfInterval!Date(Date(2012, 1, 8))));
  21196. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  21197. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  21198. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  21199. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  21200. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  21201. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  21202. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21203. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21204. static assert(__traits(compiles, negInfInterval.intersects(interval)));
  21205. static assert(__traits(compiles, negInfInterval.intersects(cInterval)));
  21206. static assert(__traits(compiles, negInfInterval.intersects(iInterval)));
  21207. static assert(__traits(compiles, negInfInterval.intersects(posInfInterval)));
  21208. static assert(__traits(compiles, negInfInterval.intersects(cPosInfInterval)));
  21209. static assert(__traits(compiles, negInfInterval.intersects(iPosInfInterval)));
  21210. static assert(__traits(compiles, negInfInterval.intersects(negInfInterval)));
  21211. static assert(__traits(compiles, negInfInterval.intersects(cNegInfInterval)));
  21212. static assert(__traits(compiles, negInfInterval.intersects(iNegInfInterval)));
  21213. static assert(__traits(compiles, cNegInfInterval.intersects(interval)));
  21214. static assert(__traits(compiles, cNegInfInterval.intersects(cInterval)));
  21215. static assert(__traits(compiles, cNegInfInterval.intersects(iInterval)));
  21216. static assert(__traits(compiles, cNegInfInterval.intersects(posInfInterval)));
  21217. static assert(__traits(compiles, cNegInfInterval.intersects(cPosInfInterval)));
  21218. static assert(__traits(compiles, cNegInfInterval.intersects(iPosInfInterval)));
  21219. static assert(__traits(compiles, cNegInfInterval.intersects(negInfInterval)));
  21220. static assert(__traits(compiles, cNegInfInterval.intersects(cNegInfInterval)));
  21221. static assert(__traits(compiles, cNegInfInterval.intersects(iNegInfInterval)));
  21222. static assert(__traits(compiles, iNegInfInterval.intersects(interval)));
  21223. static assert(__traits(compiles, iNegInfInterval.intersects(cInterval)));
  21224. static assert(__traits(compiles, iNegInfInterval.intersects(iInterval)));
  21225. static assert(__traits(compiles, iNegInfInterval.intersects(posInfInterval)));
  21226. static assert(__traits(compiles, iNegInfInterval.intersects(cPosInfInterval)));
  21227. static assert(__traits(compiles, iNegInfInterval.intersects(iPosInfInterval)));
  21228. static assert(__traits(compiles, iNegInfInterval.intersects(negInfInterval)));
  21229. static assert(__traits(compiles, iNegInfInterval.intersects(cNegInfInterval)));
  21230. static assert(__traits(compiles, iNegInfInterval.intersects(iNegInfInterval)));
  21231. //Verify Examples.
  21232. assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  21233. assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
  21234. assert(!NegInfInterval!Date(Date(2012, 3, 1)).intersects(Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
  21235. assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(PosInfInterval!Date(Date(1999, 5, 4))));
  21236. assert(!NegInfInterval!Date(Date(2012, 3, 1)).intersects(PosInfInterval!Date(Date(2012, 3, 1))));
  21237. assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(NegInfInterval!Date(Date(1996, 5, 4))));
  21238. assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(NegInfInterval!Date(Date(2013, 7, 9))));
  21239. }
  21240. }
  21241. //Test NegInfInterval's intersection().
  21242. unittest
  21243. {
  21244. version(testStdDateTime)
  21245. {
  21246. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21247. static void testInterval(I, J)(in I interval1, in J interval2)
  21248. {
  21249. interval1.intersection(interval2);
  21250. }
  21251. assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  21252. assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
  21253. assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
  21254. assertThrown!DateTimeException(testInterval(negInfInterval, PosInfInterval!Date(Date(2012, 1, 7))));
  21255. assertThrown!DateTimeException(testInterval(negInfInterval, PosInfInterval!Date(Date(2012, 1, 8))));
  21256. _assertPred!"=="(negInfInterval.intersection(negInfInterval),
  21257. negInfInterval);
  21258. _assertPred!"=="(negInfInterval.intersection(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))),
  21259. Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)));
  21260. _assertPred!"=="(negInfInterval.intersection(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))),
  21261. Interval!Date(Date(2010, 7, 1), Date(2012, 1, 7)));
  21262. _assertPred!"=="(negInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))),
  21263. Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)));
  21264. _assertPred!"=="(negInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))),
  21265. Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)));
  21266. _assertPred!"=="(negInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))),
  21267. Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
  21268. _assertPred!"=="(negInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))),
  21269. Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
  21270. _assertPred!"=="(negInfInterval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))),
  21271. Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)));
  21272. _assertPred!"=="(negInfInterval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))),
  21273. Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)));
  21274. _assertPred!"=="(negInfInterval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))),
  21275. Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
  21276. _assertPred!"=="(negInfInterval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))),
  21277. Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
  21278. _assertPred!"=="(negInfInterval.intersection(NegInfInterval!Date(Date(2010, 7, 3))),
  21279. NegInfInterval!Date(Date(2010, 7, 3)));
  21280. _assertPred!"=="(negInfInterval.intersection(NegInfInterval!Date(Date(2010, 7, 4))),
  21281. NegInfInterval!Date(Date(2010, 7, 4)));
  21282. _assertPred!"=="(negInfInterval.intersection(NegInfInterval!Date(Date(2010, 7, 5))),
  21283. NegInfInterval!Date(Date(2010, 7, 5)));
  21284. _assertPred!"=="(negInfInterval.intersection(NegInfInterval!Date(Date(2012, 1, 6))),
  21285. NegInfInterval!Date(Date(2012, 1, 6)));
  21286. _assertPred!"=="(negInfInterval.intersection(NegInfInterval!Date(Date(2012, 1, 7))),
  21287. NegInfInterval!Date(Date(2012, 1, 7)));
  21288. _assertPred!"=="(negInfInterval.intersection(NegInfInterval!Date(Date(2012, 1, 8))),
  21289. NegInfInterval!Date(Date(2012, 1, 7)));
  21290. _assertPred!"=="(NegInfInterval!Date(Date(2010, 7, 3)).intersection(negInfInterval),
  21291. NegInfInterval!Date(Date(2010, 7, 3)));
  21292. _assertPred!"=="(NegInfInterval!Date(Date(2010, 7, 4)).intersection(negInfInterval),
  21293. NegInfInterval!Date(Date(2010, 7, 4)));
  21294. _assertPred!"=="(NegInfInterval!Date(Date(2010, 7, 5)).intersection(negInfInterval),
  21295. NegInfInterval!Date(Date(2010, 7, 5)));
  21296. _assertPred!"=="(NegInfInterval!Date(Date(2012, 1, 6)).intersection(negInfInterval),
  21297. NegInfInterval!Date(Date(2012, 1, 6)));
  21298. _assertPred!"=="(NegInfInterval!Date(Date(2012, 1, 7)).intersection(negInfInterval),
  21299. NegInfInterval!Date(Date(2012, 1, 7)));
  21300. _assertPred!"=="(NegInfInterval!Date(Date(2012, 1, 8)).intersection(negInfInterval),
  21301. NegInfInterval!Date(Date(2012, 1, 7)));
  21302. _assertPred!"=="(negInfInterval.intersection(PosInfInterval!Date(Date(2010, 7, 3))),
  21303. Interval!Date(Date(2010, 7, 3), Date(2012, 1 ,7)));
  21304. _assertPred!"=="(negInfInterval.intersection(PosInfInterval!Date(Date(2010, 7, 4))),
  21305. Interval!Date(Date(2010, 7, 4), Date(2012, 1 ,7)));
  21306. _assertPred!"=="(negInfInterval.intersection(PosInfInterval!Date(Date(2010, 7, 5))),
  21307. Interval!Date(Date(2010, 7, 5), Date(2012, 1 ,7)));
  21308. _assertPred!"=="(negInfInterval.intersection(PosInfInterval!Date(Date(2012, 1, 6))),
  21309. Interval!Date(Date(2012, 1, 6), Date(2012, 1 ,7)));
  21310. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  21311. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  21312. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  21313. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  21314. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  21315. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  21316. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21317. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21318. static assert(__traits(compiles, negInfInterval.intersection(interval)));
  21319. static assert(__traits(compiles, negInfInterval.intersection(cInterval)));
  21320. static assert(__traits(compiles, negInfInterval.intersection(iInterval)));
  21321. static assert(__traits(compiles, negInfInterval.intersection(posInfInterval)));
  21322. static assert(__traits(compiles, negInfInterval.intersection(cPosInfInterval)));
  21323. static assert(__traits(compiles, negInfInterval.intersection(iPosInfInterval)));
  21324. static assert(__traits(compiles, negInfInterval.intersection(negInfInterval)));
  21325. static assert(__traits(compiles, negInfInterval.intersection(cNegInfInterval)));
  21326. static assert(__traits(compiles, negInfInterval.intersection(iNegInfInterval)));
  21327. static assert(__traits(compiles, cNegInfInterval.intersection(interval)));
  21328. static assert(__traits(compiles, cNegInfInterval.intersection(cInterval)));
  21329. static assert(__traits(compiles, cNegInfInterval.intersection(iInterval)));
  21330. static assert(__traits(compiles, cNegInfInterval.intersection(posInfInterval)));
  21331. static assert(__traits(compiles, cNegInfInterval.intersection(cPosInfInterval)));
  21332. static assert(__traits(compiles, cNegInfInterval.intersection(iPosInfInterval)));
  21333. static assert(__traits(compiles, cNegInfInterval.intersection(negInfInterval)));
  21334. static assert(__traits(compiles, cNegInfInterval.intersection(cNegInfInterval)));
  21335. static assert(__traits(compiles, cNegInfInterval.intersection(iNegInfInterval)));
  21336. static assert(__traits(compiles, iNegInfInterval.intersection(interval)));
  21337. static assert(__traits(compiles, iNegInfInterval.intersection(cInterval)));
  21338. static assert(__traits(compiles, iNegInfInterval.intersection(iInterval)));
  21339. static assert(__traits(compiles, iNegInfInterval.intersection(posInfInterval)));
  21340. static assert(__traits(compiles, iNegInfInterval.intersection(cPosInfInterval)));
  21341. static assert(__traits(compiles, iNegInfInterval.intersection(iPosInfInterval)));
  21342. static assert(__traits(compiles, iNegInfInterval.intersection(negInfInterval)));
  21343. static assert(__traits(compiles, iNegInfInterval.intersection(cNegInfInterval)));
  21344. static assert(__traits(compiles, iNegInfInterval.intersection(iNegInfInterval)));
  21345. //Verify Examples.
  21346. assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) == Interval!Date(Date(1990, 7 , 6), Date(2000, 8, 2)));
  21347. assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(Interval!Date(Date(1999, 1, 12), Date(2015, 9, 2))) == Interval!Date(Date(1999, 1 , 12), Date(2012, 3, 1)));
  21348. assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(PosInfInterval!Date(Date(1990, 7, 6))) == Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
  21349. assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(PosInfInterval!Date(Date(1999, 1, 12))) == Interval!Date(Date(1999, 1 , 12), Date(2012, 3, 1)));
  21350. assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(NegInfInterval!Date(Date(1999, 7, 6))) == NegInfInterval!Date(Date(1999, 7 , 6)));
  21351. assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(NegInfInterval!Date(Date(2013, 1, 12))) == NegInfInterval!Date(Date(2012, 3 , 1)));
  21352. }
  21353. }
  21354. //Test NegInfInterval's isAdjacent().
  21355. unittest
  21356. {
  21357. version(testStdDateTime)
  21358. {
  21359. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21360. static void testInterval(in NegInfInterval!Date negInfInterval, in Interval!Date interval)
  21361. {
  21362. negInfInterval.isAdjacent(interval);
  21363. }
  21364. assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  21365. assert(!negInfInterval.isAdjacent(negInfInterval));
  21366. assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
  21367. assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
  21368. assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
  21369. assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
  21370. assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
  21371. assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
  21372. assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
  21373. assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
  21374. assert(!negInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
  21375. assert(!negInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
  21376. assert(negInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
  21377. assert(!negInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
  21378. assert(!negInfInterval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 3))));
  21379. assert(!negInfInterval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 4))));
  21380. assert(!negInfInterval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 5))));
  21381. assert(!negInfInterval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 6))));
  21382. assert(!negInfInterval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 7))));
  21383. assert(!negInfInterval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 8))));
  21384. assert(!NegInfInterval!Date(Date(2010, 7, 3)).isAdjacent(negInfInterval));
  21385. assert(!NegInfInterval!Date(Date(2010, 7, 4)).isAdjacent(negInfInterval));
  21386. assert(!NegInfInterval!Date(Date(2010, 7, 5)).isAdjacent(negInfInterval));
  21387. assert(!NegInfInterval!Date(Date(2012, 1, 6)).isAdjacent(negInfInterval));
  21388. assert(!NegInfInterval!Date(Date(2012, 1, 7)).isAdjacent(negInfInterval));
  21389. assert(!NegInfInterval!Date(Date(2012, 1, 8)).isAdjacent(negInfInterval));
  21390. assert(!negInfInterval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 3))));
  21391. assert(!negInfInterval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 4))));
  21392. assert(!negInfInterval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 5))));
  21393. assert(!negInfInterval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 6))));
  21394. assert(negInfInterval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 7))));
  21395. assert(!negInfInterval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 8))));
  21396. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  21397. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  21398. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  21399. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  21400. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  21401. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  21402. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21403. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21404. static assert(__traits(compiles, negInfInterval.isAdjacent(interval)));
  21405. static assert(__traits(compiles, negInfInterval.isAdjacent(cInterval)));
  21406. static assert(__traits(compiles, negInfInterval.isAdjacent(iInterval)));
  21407. static assert(__traits(compiles, negInfInterval.isAdjacent(posInfInterval)));
  21408. static assert(__traits(compiles, negInfInterval.isAdjacent(cPosInfInterval)));
  21409. static assert(__traits(compiles, negInfInterval.isAdjacent(iPosInfInterval)));
  21410. static assert(__traits(compiles, negInfInterval.isAdjacent(negInfInterval)));
  21411. static assert(__traits(compiles, negInfInterval.isAdjacent(cNegInfInterval)));
  21412. static assert(__traits(compiles, negInfInterval.isAdjacent(iNegInfInterval)));
  21413. static assert(__traits(compiles, cNegInfInterval.isAdjacent(interval)));
  21414. static assert(__traits(compiles, cNegInfInterval.isAdjacent(cInterval)));
  21415. static assert(__traits(compiles, cNegInfInterval.isAdjacent(iInterval)));
  21416. static assert(__traits(compiles, cNegInfInterval.isAdjacent(posInfInterval)));
  21417. static assert(__traits(compiles, cNegInfInterval.isAdjacent(cPosInfInterval)));
  21418. static assert(__traits(compiles, cNegInfInterval.isAdjacent(iPosInfInterval)));
  21419. static assert(__traits(compiles, cNegInfInterval.isAdjacent(negInfInterval)));
  21420. static assert(__traits(compiles, cNegInfInterval.isAdjacent(cNegInfInterval)));
  21421. static assert(__traits(compiles, cNegInfInterval.isAdjacent(iNegInfInterval)));
  21422. static assert(__traits(compiles, iNegInfInterval.isAdjacent(interval)));
  21423. static assert(__traits(compiles, iNegInfInterval.isAdjacent(cInterval)));
  21424. static assert(__traits(compiles, iNegInfInterval.isAdjacent(iInterval)));
  21425. static assert(__traits(compiles, iNegInfInterval.isAdjacent(posInfInterval)));
  21426. static assert(__traits(compiles, iNegInfInterval.isAdjacent(cPosInfInterval)));
  21427. static assert(__traits(compiles, iNegInfInterval.isAdjacent(iPosInfInterval)));
  21428. static assert(__traits(compiles, iNegInfInterval.isAdjacent(negInfInterval)));
  21429. static assert(__traits(compiles, iNegInfInterval.isAdjacent(cNegInfInterval)));
  21430. static assert(__traits(compiles, iNegInfInterval.isAdjacent(iNegInfInterval)));
  21431. //Verify Examples.
  21432. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
  21433. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(1999, 1, 12), Date(2012, 3, 1))));
  21434. assert(NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(2012, 3, 1), Date(2019, 2, 2))));
  21435. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
  21436. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(PosInfInterval!Date(Date(1999, 5, 4))));
  21437. assert(NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(PosInfInterval!Date(Date(2012, 3, 1))));
  21438. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(NegInfInterval!Date(Date(1996, 5, 4))));
  21439. assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(NegInfInterval!Date(Date(2012, 3, 1))));
  21440. }
  21441. }
  21442. //Test NegInfInterval's merge().
  21443. unittest
  21444. {
  21445. version(testStdDateTime)
  21446. {
  21447. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21448. static void testInterval(I, J)(in I interval1, in J interval2)
  21449. {
  21450. interval1.merge(interval2);
  21451. }
  21452. assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  21453. assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
  21454. _assertPred!"=="(negInfInterval.merge(negInfInterval),
  21455. negInfInterval);
  21456. _assertPred!"=="(negInfInterval.merge(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))),
  21457. NegInfInterval!Date(Date(2012, 1, 7)));
  21458. _assertPred!"=="(negInfInterval.merge(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))),
  21459. NegInfInterval!Date(Date(2013, 7, 3)));
  21460. _assertPred!"=="(negInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))),
  21461. NegInfInterval!Date(Date(2012, 1, 7)));
  21462. _assertPred!"=="(negInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))),
  21463. NegInfInterval!Date(Date(2012, 1, 7)));
  21464. _assertPred!"=="(negInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))),
  21465. NegInfInterval!Date(Date(2012, 1, 7)));
  21466. _assertPred!"=="(negInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))),
  21467. NegInfInterval!Date(Date(2012, 1, 8)));
  21468. _assertPred!"=="(negInfInterval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))),
  21469. NegInfInterval!Date(Date(2012, 1, 7)));
  21470. _assertPred!"=="(negInfInterval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))),
  21471. NegInfInterval!Date(Date(2012, 1, 7)));
  21472. _assertPred!"=="(negInfInterval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))),
  21473. NegInfInterval!Date(Date(2012, 1, 7)));
  21474. _assertPred!"=="(negInfInterval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))),
  21475. NegInfInterval!Date(Date(2012, 1, 8)));
  21476. _assertPred!"=="(negInfInterval.merge(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))),
  21477. NegInfInterval!Date(Date(2012, 1, 8)));
  21478. _assertPred!"=="(negInfInterval.merge(NegInfInterval!Date(Date(2010, 7, 3))),
  21479. NegInfInterval!Date(Date(2012, 1, 7)));
  21480. _assertPred!"=="(negInfInterval.merge(NegInfInterval!Date(Date(2010, 7, 4))),
  21481. NegInfInterval!Date(Date(2012, 1, 7)));
  21482. _assertPred!"=="(negInfInterval.merge(NegInfInterval!Date(Date(2010, 7, 5))),
  21483. NegInfInterval!Date(Date(2012, 1, 7)));
  21484. _assertPred!"=="(negInfInterval.merge(NegInfInterval!Date(Date(2012, 1, 6))),
  21485. NegInfInterval!Date(Date(2012, 1, 7)));
  21486. _assertPred!"=="(negInfInterval.merge(NegInfInterval!Date(Date(2012, 1, 7))),
  21487. NegInfInterval!Date(Date(2012, 1, 7)));
  21488. _assertPred!"=="(negInfInterval.merge(NegInfInterval!Date(Date(2012, 1, 8))),
  21489. NegInfInterval!Date(Date(2012, 1, 8)));
  21490. _assertPred!"=="(NegInfInterval!Date(Date(2010, 7, 3)).merge(negInfInterval),
  21491. NegInfInterval!Date(Date(2012, 1, 7)));
  21492. _assertPred!"=="(NegInfInterval!Date(Date(2010, 7, 4)).merge(negInfInterval),
  21493. NegInfInterval!Date(Date(2012, 1, 7)));
  21494. _assertPred!"=="(NegInfInterval!Date(Date(2010, 7, 5)).merge(negInfInterval),
  21495. NegInfInterval!Date(Date(2012, 1, 7)));
  21496. _assertPred!"=="(NegInfInterval!Date(Date(2012, 1, 6)).merge(negInfInterval),
  21497. NegInfInterval!Date(Date(2012, 1, 7)));
  21498. _assertPred!"=="(NegInfInterval!Date(Date(2012, 1, 7)).merge(negInfInterval),
  21499. NegInfInterval!Date(Date(2012, 1, 7)));
  21500. _assertPred!"=="(NegInfInterval!Date(Date(2012, 1, 8)).merge(negInfInterval),
  21501. NegInfInterval!Date(Date(2012, 1, 8)));
  21502. static assert(!__traits(compiles, negInfInterval.merge(PosInfInterval!Date(Date(2010, 7, 3)))));
  21503. static assert(!__traits(compiles, negInfInterval.merge(PosInfInterval!Date(Date(2010, 7, 4)))));
  21504. static assert(!__traits(compiles, negInfInterval.merge(PosInfInterval!Date(Date(2010, 7, 5)))));
  21505. static assert(!__traits(compiles, negInfInterval.merge(PosInfInterval!Date(Date(2012, 1, 6)))));
  21506. static assert(!__traits(compiles, negInfInterval.merge(PosInfInterval!Date(Date(2012, 1, 7)))));
  21507. static assert(!__traits(compiles, negInfInterval.merge(PosInfInterval!Date(Date(2012, 1, 8)))));
  21508. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  21509. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  21510. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  21511. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  21512. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  21513. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  21514. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21515. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21516. static assert(__traits(compiles, negInfInterval.merge(interval)));
  21517. static assert(__traits(compiles, negInfInterval.merge(cInterval)));
  21518. static assert(__traits(compiles, negInfInterval.merge(iInterval)));
  21519. static assert(!__traits(compiles, negInfInterval.merge(posInfInterval)));
  21520. static assert(!__traits(compiles, negInfInterval.merge(cPosInfInterval)));
  21521. static assert(!__traits(compiles, negInfInterval.merge(iPosInfInterval)));
  21522. static assert(__traits(compiles, negInfInterval.merge(negInfInterval)));
  21523. static assert(__traits(compiles, negInfInterval.merge(cNegInfInterval)));
  21524. static assert(__traits(compiles, negInfInterval.merge(iNegInfInterval)));
  21525. static assert(__traits(compiles, cNegInfInterval.merge(interval)));
  21526. static assert(__traits(compiles, cNegInfInterval.merge(cInterval)));
  21527. static assert(__traits(compiles, cNegInfInterval.merge(iInterval)));
  21528. static assert(!__traits(compiles, cNegInfInterval.merge(posInfInterval)));
  21529. static assert(!__traits(compiles, cNegInfInterval.merge(cPosInfInterval)));
  21530. static assert(!__traits(compiles, cNegInfInterval.merge(iPosInfInterval)));
  21531. static assert(__traits(compiles, cNegInfInterval.merge(negInfInterval)));
  21532. static assert(__traits(compiles, cNegInfInterval.merge(cNegInfInterval)));
  21533. static assert(__traits(compiles, cNegInfInterval.merge(iNegInfInterval)));
  21534. static assert(__traits(compiles, iNegInfInterval.merge(interval)));
  21535. static assert(__traits(compiles, iNegInfInterval.merge(cInterval)));
  21536. static assert(__traits(compiles, iNegInfInterval.merge(iInterval)));
  21537. static assert(!__traits(compiles, iNegInfInterval.merge(posInfInterval)));
  21538. static assert(!__traits(compiles, iNegInfInterval.merge(cPosInfInterval)));
  21539. static assert(!__traits(compiles, iNegInfInterval.merge(iPosInfInterval)));
  21540. static assert(__traits(compiles, iNegInfInterval.merge(negInfInterval)));
  21541. static assert(__traits(compiles, iNegInfInterval.merge(cNegInfInterval)));
  21542. static assert(__traits(compiles, iNegInfInterval.merge(iNegInfInterval)));
  21543. //Verify Examples.
  21544. assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) == NegInfInterval!Date(Date(2012, 3 , 1)));
  21545. assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(Interval!Date(Date(1999, 1, 12), Date(2015, 9, 2))) == NegInfInterval!Date(Date(2015, 9 , 2)));
  21546. assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(NegInfInterval!Date(Date(1999, 7, 6))) == NegInfInterval!Date(Date(2012, 3 , 1)));
  21547. assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(NegInfInterval!Date(Date(2013, 1, 12))) == NegInfInterval!Date(Date(2013, 1 , 12)));
  21548. }
  21549. }
  21550. //Test NegInfInterval's span().
  21551. unittest
  21552. {
  21553. version(testStdDateTime)
  21554. {
  21555. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21556. static void testInterval(I, J)(in I interval1, in J interval2)
  21557. {
  21558. interval1.span(interval2);
  21559. }
  21560. assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
  21561. _assertPred!"=="(negInfInterval.span(negInfInterval),
  21562. negInfInterval);
  21563. _assertPred!"=="(negInfInterval.span(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))),
  21564. NegInfInterval!Date(Date(2012, 1, 7)));
  21565. _assertPred!"=="(negInfInterval.span(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))),
  21566. NegInfInterval!Date(Date(2013, 7, 3)));
  21567. _assertPred!"=="(negInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))),
  21568. NegInfInterval!Date(Date(2012, 1, 7)));
  21569. _assertPred!"=="(negInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))),
  21570. NegInfInterval!Date(Date(2012, 1, 7)));
  21571. _assertPred!"=="(negInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))),
  21572. NegInfInterval!Date(Date(2012, 1, 7)));
  21573. _assertPred!"=="(negInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))),
  21574. NegInfInterval!Date(Date(2012, 1, 8)));
  21575. _assertPred!"=="(negInfInterval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))),
  21576. NegInfInterval!Date(Date(2012, 1, 7)));
  21577. _assertPred!"=="(negInfInterval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))),
  21578. NegInfInterval!Date(Date(2012, 1, 7)));
  21579. _assertPred!"=="(negInfInterval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))),
  21580. NegInfInterval!Date(Date(2012, 1, 7)));
  21581. _assertPred!"=="(negInfInterval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))),
  21582. NegInfInterval!Date(Date(2012, 1, 8)));
  21583. _assertPred!"=="(negInfInterval.span(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))),
  21584. NegInfInterval!Date(Date(2012, 1, 8)));
  21585. _assertPred!"=="(negInfInterval.span(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))),
  21586. NegInfInterval!Date(Date(2012, 1, 9)));
  21587. _assertPred!"=="(negInfInterval.span(NegInfInterval!Date(Date(2010, 7, 3))),
  21588. NegInfInterval!Date(Date(2012, 1, 7)));
  21589. _assertPred!"=="(negInfInterval.span(NegInfInterval!Date(Date(2010, 7, 4))),
  21590. NegInfInterval!Date(Date(2012, 1, 7)));
  21591. _assertPred!"=="(negInfInterval.span(NegInfInterval!Date(Date(2010, 7, 5))),
  21592. NegInfInterval!Date(Date(2012, 1, 7)));
  21593. _assertPred!"=="(negInfInterval.span(NegInfInterval!Date(Date(2012, 1, 6))),
  21594. NegInfInterval!Date(Date(2012, 1, 7)));
  21595. _assertPred!"=="(negInfInterval.span(NegInfInterval!Date(Date(2012, 1, 7))),
  21596. NegInfInterval!Date(Date(2012, 1, 7)));
  21597. _assertPred!"=="(negInfInterval.span(NegInfInterval!Date(Date(2012, 1, 8))),
  21598. NegInfInterval!Date(Date(2012, 1, 8)));
  21599. _assertPred!"=="(NegInfInterval!Date(Date(2010, 7, 3)).span(negInfInterval),
  21600. NegInfInterval!Date(Date(2012, 1, 7)));
  21601. _assertPred!"=="(NegInfInterval!Date(Date(2010, 7, 4)).span(negInfInterval),
  21602. NegInfInterval!Date(Date(2012, 1, 7)));
  21603. _assertPred!"=="(NegInfInterval!Date(Date(2010, 7, 5)).span(negInfInterval),
  21604. NegInfInterval!Date(Date(2012, 1, 7)));
  21605. _assertPred!"=="(NegInfInterval!Date(Date(2012, 1, 6)).span(negInfInterval),
  21606. NegInfInterval!Date(Date(2012, 1, 7)));
  21607. _assertPred!"=="(NegInfInterval!Date(Date(2012, 1, 7)).span(negInfInterval),
  21608. NegInfInterval!Date(Date(2012, 1, 7)));
  21609. _assertPred!"=="(NegInfInterval!Date(Date(2012, 1, 8)).span(negInfInterval),
  21610. NegInfInterval!Date(Date(2012, 1, 8)));
  21611. static assert(!__traits(compiles, negInfInterval.span(PosInfInterval!Date(Date(2010, 7, 3)))));
  21612. static assert(!__traits(compiles, negInfInterval.span(PosInfInterval!Date(Date(2010, 7, 4)))));
  21613. static assert(!__traits(compiles, negInfInterval.span(PosInfInterval!Date(Date(2010, 7, 5)))));
  21614. static assert(!__traits(compiles, negInfInterval.span(PosInfInterval!Date(Date(2012, 1, 6)))));
  21615. static assert(!__traits(compiles, negInfInterval.span(PosInfInterval!Date(Date(2012, 1, 7)))));
  21616. static assert(!__traits(compiles, negInfInterval.span(PosInfInterval!Date(Date(2012, 1, 8)))));
  21617. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  21618. const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  21619. immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  21620. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  21621. const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  21622. immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  21623. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21624. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21625. static assert(__traits(compiles, negInfInterval.span(interval)));
  21626. static assert(__traits(compiles, negInfInterval.span(cInterval)));
  21627. static assert(__traits(compiles, negInfInterval.span(iInterval)));
  21628. static assert(!__traits(compiles, negInfInterval.span(posInfInterval)));
  21629. static assert(!__traits(compiles, negInfInterval.span(cPosInfInterval)));
  21630. static assert(!__traits(compiles, negInfInterval.span(iPosInfInterval)));
  21631. static assert(__traits(compiles, negInfInterval.span(negInfInterval)));
  21632. static assert(__traits(compiles, negInfInterval.span(cNegInfInterval)));
  21633. static assert(__traits(compiles, negInfInterval.span(iNegInfInterval)));
  21634. static assert(__traits(compiles, cNegInfInterval.span(interval)));
  21635. static assert(__traits(compiles, cNegInfInterval.span(cInterval)));
  21636. static assert(__traits(compiles, cNegInfInterval.span(iInterval)));
  21637. static assert(!__traits(compiles, cNegInfInterval.span(posInfInterval)));
  21638. static assert(!__traits(compiles, cNegInfInterval.span(cPosInfInterval)));
  21639. static assert(!__traits(compiles, cNegInfInterval.span(iPosInfInterval)));
  21640. static assert(__traits(compiles, cNegInfInterval.span(negInfInterval)));
  21641. static assert(__traits(compiles, cNegInfInterval.span(cNegInfInterval)));
  21642. static assert(__traits(compiles, cNegInfInterval.span(iNegInfInterval)));
  21643. static assert(__traits(compiles, iNegInfInterval.span(interval)));
  21644. static assert(__traits(compiles, iNegInfInterval.span(cInterval)));
  21645. static assert(__traits(compiles, iNegInfInterval.span(iInterval)));
  21646. static assert(!__traits(compiles, iNegInfInterval.span(posInfInterval)));
  21647. static assert(!__traits(compiles, iNegInfInterval.span(cPosInfInterval)));
  21648. static assert(!__traits(compiles, iNegInfInterval.span(iPosInfInterval)));
  21649. static assert(__traits(compiles, iNegInfInterval.span(negInfInterval)));
  21650. static assert(__traits(compiles, iNegInfInterval.span(cNegInfInterval)));
  21651. static assert(__traits(compiles, iNegInfInterval.span(iNegInfInterval)));
  21652. //Verify Examples.
  21653. assert(NegInfInterval!Date(Date(2012, 3, 1)).span(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) == NegInfInterval!Date(Date(2012, 3 , 1)));
  21654. assert(NegInfInterval!Date(Date(2012, 3, 1)).span(Interval!Date(Date(1999, 1, 12), Date(2015, 9, 2))) == NegInfInterval!Date(Date(2015, 9 , 2)));
  21655. assert(NegInfInterval!Date(Date(1600, 1, 7)).span(Interval!Date(Date(2012, 3, 11), Date(2017, 7, 1))) == NegInfInterval!Date(Date(2017, 7 , 1)));
  21656. assert(NegInfInterval!Date(Date(2012, 3, 1)).span(NegInfInterval!Date(Date(1999, 7, 6))) == NegInfInterval!Date(Date(2012, 3 , 1)));
  21657. assert(NegInfInterval!Date(Date(2012, 3, 1)).span(NegInfInterval!Date(Date(2013, 1, 12))) == NegInfInterval!Date(Date(2013, 1 , 12)));
  21658. }
  21659. }
  21660. //Test NegInfInterval's shift().
  21661. unittest
  21662. {
  21663. version(testStdDateTime)
  21664. {
  21665. auto interval = NegInfInterval!Date(Date(2012, 1, 7));
  21666. static void testInterval(I)(I interval, in Duration duration, in I expected, size_t line = __LINE__)
  21667. {
  21668. interval.shift(duration);
  21669. _assertPred!"=="(interval, expected, "", __FILE__, line);
  21670. }
  21671. testInterval(interval, dur!"days"(22), NegInfInterval!Date(Date(2012, 1, 29)));
  21672. testInterval(interval, dur!"days"(-22), NegInfInterval!Date(Date(2011, 12, 16)));
  21673. const cInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21674. immutable iInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21675. static assert(!__traits(compiles, cInterval.shift(dur!"days"(5))));
  21676. static assert(!__traits(compiles, iInterval.shift(dur!"days"(5))));
  21677. //Verify Examples.
  21678. auto interval1 = NegInfInterval!Date(Date(2012, 4, 5));
  21679. auto interval2 = NegInfInterval!Date(Date(2012, 4, 5));
  21680. interval1.shift(dur!"days"(50));
  21681. assert(interval1 == NegInfInterval!Date(Date(2012, 5, 25)));
  21682. interval2.shift(dur!"days"(-50));
  21683. assert(interval2 == NegInfInterval!Date( Date(2012, 2, 15)));
  21684. }
  21685. }
  21686. //Test NegInfInterval's shift(int, int, AllowDayOverflow).
  21687. unittest
  21688. {
  21689. version(testStdDateTime)
  21690. {
  21691. {
  21692. auto interval = NegInfInterval!Date(Date(2012, 1, 7));
  21693. static void testIntervalFail(I)(I interval, int years, int months)
  21694. {
  21695. interval.shift(years, months);
  21696. }
  21697. static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow, in I expected, size_t line = __LINE__)
  21698. {
  21699. interval.shift(years, months, allow);
  21700. _assertPred!"=="(interval, expected, "", __FILE__, line);
  21701. }
  21702. testInterval(interval, 5, 0, AllowDayOverflow.yes, NegInfInterval!Date(Date(2017, 1, 7)));
  21703. testInterval(interval, -5, 0, AllowDayOverflow.yes, NegInfInterval!Date(Date(2007, 1, 7)));
  21704. auto interval2 = NegInfInterval!Date(Date(2010, 5, 31));
  21705. testInterval(interval2, 1, 1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2011, 7, 1)));
  21706. testInterval(interval2, 1, -1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2011, 5, 1)));
  21707. testInterval(interval2, -1, -1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2009, 5, 1)));
  21708. testInterval(interval2, -1, 1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2009, 7, 1)));
  21709. testInterval(interval2, 1, 1, AllowDayOverflow.no, NegInfInterval!Date(Date(2011, 6, 30)));
  21710. testInterval(interval2, 1, -1, AllowDayOverflow.no, NegInfInterval!Date(Date(2011, 4, 30)));
  21711. testInterval(interval2, -1, -1, AllowDayOverflow.no, NegInfInterval!Date(Date(2009, 4, 30)));
  21712. testInterval(interval2, -1, 1, AllowDayOverflow.no, NegInfInterval!Date(Date(2009, 6, 30)));
  21713. }
  21714. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21715. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21716. static assert(!__traits(compiles, cNegInfInterval.shift(1)));
  21717. static assert(!__traits(compiles, iNegInfInterval.shift(1)));
  21718. //Verify Examples.
  21719. auto interval1 = NegInfInterval!Date(Date(2012, 3, 1));
  21720. auto interval2 = NegInfInterval!Date(Date(2012, 3, 1));
  21721. interval1.shift(2);
  21722. assert(interval1 == NegInfInterval!Date(Date(2014, 3, 1)));
  21723. interval2.shift(-2);
  21724. assert(interval2 == NegInfInterval!Date(Date(2010, 3, 1)));
  21725. }
  21726. }
  21727. //Test NegInfInterval's expand().
  21728. unittest
  21729. {
  21730. version(testStdDateTime)
  21731. {
  21732. auto interval = NegInfInterval!Date(Date(2012, 1, 7));
  21733. static void testInterval(I)(I interval, in Duration duration, in I expected, size_t line = __LINE__)
  21734. {
  21735. interval.expand(duration);
  21736. _assertPred!"=="(interval, expected, "", __FILE__, line);
  21737. }
  21738. testInterval(interval, dur!"days"(22), NegInfInterval!Date(Date(2012, 1, 29)));
  21739. testInterval(interval, dur!"days"(-22), NegInfInterval!Date(Date(2011, 12, 16)));
  21740. const cInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21741. immutable iInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21742. static assert(!__traits(compiles, cInterval.expand(dur!"days"(5))));
  21743. static assert(!__traits(compiles, iInterval.expand(dur!"days"(5))));
  21744. //Verify Examples.
  21745. auto interval1 = NegInfInterval!Date(Date(2012, 3, 1));
  21746. auto interval2 = NegInfInterval!Date(Date(2012, 3, 1));
  21747. interval1.expand(dur!"days"(2));
  21748. assert(interval1 == NegInfInterval!Date(Date(2012, 3, 3)));
  21749. interval2.expand(dur!"days"(-2));
  21750. assert(interval2 == NegInfInterval!Date(Date(2012, 2, 28)));
  21751. }
  21752. }
  21753. //Test NegInfInterval's expand(int, int, AllowDayOverflow).
  21754. unittest
  21755. {
  21756. version(testStdDateTime)
  21757. {
  21758. {
  21759. auto interval = NegInfInterval!Date(Date(2012, 1, 7));
  21760. static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow, in I expected, size_t line = __LINE__)
  21761. {
  21762. interval.expand(years, months, allow);
  21763. _assertPred!"=="(interval, expected, "", __FILE__, line);
  21764. }
  21765. testInterval(interval, 5, 0, AllowDayOverflow.yes, NegInfInterval!Date(Date(2017, 1, 7)));
  21766. testInterval(interval, -5, 0, AllowDayOverflow.yes, NegInfInterval!Date(Date(2007, 1, 7)));
  21767. auto interval2 = NegInfInterval!Date(Date(2010, 5, 31));
  21768. testInterval(interval2, 1, 1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2011, 7, 1)));
  21769. testInterval(interval2, 1, -1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2011, 5, 1)));
  21770. testInterval(interval2, -1, -1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2009, 5, 1)));
  21771. testInterval(interval2, -1, 1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2009, 7, 1)));
  21772. testInterval(interval2, 1, 1, AllowDayOverflow.no, NegInfInterval!Date(Date(2011, 6, 30)));
  21773. testInterval(interval2, 1, -1, AllowDayOverflow.no, NegInfInterval!Date(Date(2011, 4, 30)));
  21774. testInterval(interval2, -1, -1, AllowDayOverflow.no, NegInfInterval!Date(Date(2009, 4, 30)));
  21775. testInterval(interval2, -1, 1, AllowDayOverflow.no, NegInfInterval!Date( Date(2009, 6, 30)));
  21776. }
  21777. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21778. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21779. static assert(!__traits(compiles, cNegInfInterval.expand(1)));
  21780. static assert(!__traits(compiles, iNegInfInterval.expand(1)));
  21781. //Verify Examples.
  21782. auto interval1 = NegInfInterval!Date(Date(2012, 3, 1));
  21783. auto interval2 = NegInfInterval!Date(Date(2012, 3, 1));
  21784. interval1.expand(2);
  21785. assert(interval1 == NegInfInterval!Date(Date(2014, 3, 1)));
  21786. interval2.expand(-2);
  21787. assert(interval2 == NegInfInterval!Date(Date(2010, 3, 1)));
  21788. }
  21789. }
  21790. //Test NegInfInterval's bwdRange().
  21791. unittest
  21792. {
  21793. version(testStdDateTime)
  21794. {
  21795. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21796. static void testInterval(NegInfInterval!Date negInfInterval)
  21797. {
  21798. negInfInterval.bwdRange(everyDayOfWeek!(Date, Direction.fwd)(DayOfWeek.fri)).popFront();
  21799. }
  21800. assertThrown!DateTimeException(testInterval(negInfInterval));
  21801. _assertPred!"=="(NegInfInterval!Date(Date(2010, 10, 1)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).front,
  21802. Date(2010, 10, 1));
  21803. _assertPred!"=="(NegInfInterval!Date(Date(2010, 10, 1)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri), PopFirst.yes).front,
  21804. Date(2010, 9, 24));
  21805. //Verify Examples.
  21806. auto interval = NegInfInterval!Date(Date(2010, 9, 9));
  21807. auto func = (in Date date)
  21808. {
  21809. if((date.day & 1) == 0)
  21810. return date - dur!"days"(2);
  21811. return date - dur!"days"(1);
  21812. };
  21813. auto range = interval.bwdRange(func);
  21814. //An odd day. Using PopFirst.yes would have made this Date(2010, 9, 8).
  21815. assert(range.front == Date(2010, 9, 9));
  21816. range.popFront();
  21817. assert(range.front == Date(2010, 9, 8));
  21818. range.popFront();
  21819. assert(range.front == Date(2010, 9, 6));
  21820. range.popFront();
  21821. assert(range.front == Date(2010, 9, 4));
  21822. range.popFront();
  21823. assert(range.front == Date(2010, 9, 2));
  21824. range.popFront();
  21825. assert(!range.empty);
  21826. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21827. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21828. static assert(__traits(compiles, cNegInfInterval.bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri))));
  21829. static assert(__traits(compiles, iNegInfInterval.bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri))));
  21830. }
  21831. }
  21832. //Test NegInfInterval's toString().
  21833. unittest
  21834. {
  21835. version(testStdDateTime)
  21836. {
  21837. _assertPred!"=="(NegInfInterval!Date(Date(2012, 1, 7)).toString(), "[-∞ - 2012-Jan-07)");
  21838. const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21839. immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  21840. static assert(__traits(compiles, cNegInfInterval.toString()));
  21841. static assert(__traits(compiles, iNegInfInterval.toString()));
  21842. }
  21843. }
  21844. /++
  21845. Range-generating function.
  21846. Returns a delegate which returns the next time point with the given
  21847. $(D DayOfWeek) in a range.
  21848. Using this delegate allows you to iterate over successive time points which
  21849. are all the same day of the week. e.g. passing $(D DayOfWeek.mon) to
  21850. $(D everyDayOfWeek) would result in a delegate which could be used to
  21851. iterate over all of the Mondays in a range.
  21852. Params:
  21853. dir = The direction to iterate in. If passing the return value to
  21854. $(D fwdRange), use $(D Direction.fwd). If passing it to
  21855. $(D bwdRange), use $(D Direction.bwd).
  21856. dayOfWeek = The week that each time point in the range will be.
  21857. Examples:
  21858. --------------------
  21859. auto interval = Interval!Date(Date(2010, 9, 2), Date(2010, 9, 27));
  21860. auto func = everyDayOfWeek!Date(DayOfWeek.mon);
  21861. auto range = interval.fwdRange(func);
  21862. //A Thursday. Using PopFirst.yes would have made this Date(2010, 9, 6).
  21863. assert(range.front == Date(2010, 9, 2));
  21864. range.popFront();
  21865. assert(range.front == Date(2010, 9, 6));
  21866. range.popFront();
  21867. assert(range.front == Date(2010, 9, 13));
  21868. range.popFront();
  21869. assert(range.front == Date(2010, 9, 20));
  21870. range.popFront();
  21871. assert(range.empty);
  21872. --------------------
  21873. +/
  21874. static TP delegate(in TP) everyDayOfWeek(TP, Direction dir = Direction.fwd)(DayOfWeek dayOfWeek) nothrow
  21875. if(isTimePoint!TP &&
  21876. (dir == Direction.fwd || dir == Direction.bwd) &&
  21877. __traits(hasMember, TP, "dayOfWeek") &&
  21878. !__traits(isStaticFunction, TP.dayOfWeek) &&
  21879. is(ReturnType!(TP.dayOfWeek) == DayOfWeek) &&
  21880. (functionAttributes!(TP.dayOfWeek) & FunctionAttribute.property) &&
  21881. (functionAttributes!(TP.dayOfWeek) & FunctionAttribute.nothrow_))
  21882. {
  21883. TP func(in TP tp)
  21884. {
  21885. TP retval = cast(TP)tp;
  21886. immutable days = daysToDayOfWeek(retval.dayOfWeek, dayOfWeek);
  21887. static if(dir == Direction.fwd)
  21888. immutable adjustedDays = days == 0 ? 7 : days;
  21889. else
  21890. immutable adjustedDays = days == 0 ? -7 : days - 7;
  21891. return retval += dur!"days"(adjustedDays);
  21892. }
  21893. return &func;
  21894. }
  21895. unittest
  21896. {
  21897. version(testStdDateTime)
  21898. {
  21899. auto funcFwd = everyDayOfWeek!Date(DayOfWeek.mon);
  21900. auto funcBwd = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.mon);
  21901. _assertPred!"=="(funcFwd(Date(2010, 8, 28)), Date(2010, 8, 30));
  21902. _assertPred!"=="(funcFwd(Date(2010, 8, 29)), Date(2010, 8, 30));
  21903. _assertPred!"=="(funcFwd(Date(2010, 8, 30)), Date(2010, 9, 6));
  21904. _assertPred!"=="(funcFwd(Date(2010, 8, 31)), Date(2010, 9, 6));
  21905. _assertPred!"=="(funcFwd(Date(2010, 9, 1)), Date(2010, 9, 6));
  21906. _assertPred!"=="(funcFwd(Date(2010, 9, 2)), Date(2010, 9, 6));
  21907. _assertPred!"=="(funcFwd(Date(2010, 9, 3)), Date(2010, 9, 6));
  21908. _assertPred!"=="(funcFwd(Date(2010, 9, 4)), Date(2010, 9, 6));
  21909. _assertPred!"=="(funcFwd(Date(2010, 9, 5)), Date(2010, 9, 6));
  21910. _assertPred!"=="(funcFwd(Date(2010, 9, 6)), Date(2010, 9, 13));
  21911. _assertPred!"=="(funcFwd(Date(2010, 9, 7)), Date(2010, 9, 13));
  21912. _assertPred!"=="(funcBwd(Date(2010, 8, 28)), Date(2010, 8, 23));
  21913. _assertPred!"=="(funcBwd(Date(2010, 8, 29)), Date(2010, 8, 23));
  21914. _assertPred!"=="(funcBwd(Date(2010, 8, 30)), Date(2010, 8, 23));
  21915. _assertPred!"=="(funcBwd(Date(2010, 8, 31)), Date(2010, 8, 30));
  21916. _assertPred!"=="(funcBwd(Date(2010, 9, 1)), Date(2010, 8, 30));
  21917. _assertPred!"=="(funcBwd(Date(2010, 9, 2)), Date(2010, 8, 30));
  21918. _assertPred!"=="(funcBwd(Date(2010, 9, 3)), Date(2010, 8, 30));
  21919. _assertPred!"=="(funcBwd(Date(2010, 9, 4)), Date(2010, 8, 30));
  21920. _assertPred!"=="(funcBwd(Date(2010, 9, 5)), Date(2010, 8, 30));
  21921. _assertPred!"=="(funcBwd(Date(2010, 9, 6)), Date(2010, 8, 30));
  21922. _assertPred!"=="(funcBwd(Date(2010, 9, 7)), Date(2010, 9, 6));
  21923. static assert(!__traits(compiles, everyDayOfWeek!(TimeOfDay)(DayOfWeek.mon)));
  21924. static assert(__traits(compiles, everyDayOfWeek!(DateTime)(DayOfWeek.mon)));
  21925. static assert(__traits(compiles, everyDayOfWeek!(SysTime)(DayOfWeek.mon)));
  21926. //Verify Examples.
  21927. auto interval = Interval!Date(Date(2010, 9, 2), Date(2010, 9, 27));
  21928. auto func = everyDayOfWeek!Date(DayOfWeek.mon);
  21929. auto range = interval.fwdRange(func);
  21930. //A Thursday. Using PopFirst.yes would have made this Date(2010, 9, 6).
  21931. assert(range.front == Date(2010, 9, 2));
  21932. range.popFront();
  21933. assert(range.front == Date(2010, 9, 6));
  21934. range.popFront();
  21935. assert(range.front == Date(2010, 9, 13));
  21936. range.popFront();
  21937. assert(range.front == Date(2010, 9, 20));
  21938. range.popFront();
  21939. assert(range.empty);
  21940. }
  21941. }
  21942. /++
  21943. Range-generating function.
  21944. Returns a delegate which returns the next time point with the given month
  21945. which would be reached by adding months to the given time point.
  21946. So, using this delegate allows you to iterate over successive time points
  21947. which are in the same month but different years. For example, you could
  21948. iterate over each successive December 25th in an interval by starting with a
  21949. date which had the 25th as its day and passed $(D Month.dec) to
  21950. $(D everyMonth) to create the delegate.
  21951. Since it wouldn't really make sense to be iterating over a specific month
  21952. and end up with some of the time points in the succeeding month or two years
  21953. after the previous time point, $(D AllowDayOverflow.no) is always used when
  21954. calculating the next time point.
  21955. Params:
  21956. dir = The direction to iterate in. If passing the return value to
  21957. $(D fwdRange), use $(D Direction.fwd). If passing it to
  21958. $(D bwdRange), use $(D Direction.bwd).
  21959. month = The month that each time point in the range will be in.
  21960. Examples:
  21961. --------------------
  21962. auto interval = Interval!Date(Date(2000, 1, 30), Date(2004, 8, 5));
  21963. auto func = everyMonth!(Date)(Month.feb);
  21964. auto range = interval.fwdRange(func);
  21965. //Using PopFirst.yes would have made this Date(2010, 2, 29).
  21966. assert(range.front == Date(2000, 1, 30));
  21967. range.popFront();
  21968. assert(range.front == Date(2000, 2, 29));
  21969. range.popFront();
  21970. assert(range.front == Date(2001, 2, 28));
  21971. range.popFront();
  21972. assert(range.front == Date(2002, 2, 28));
  21973. range.popFront();
  21974. assert(range.front == Date(2003, 2, 28));
  21975. range.popFront();
  21976. assert(range.front == Date(2004, 2, 28));
  21977. range.popFront();
  21978. assert(range.empty);
  21979. --------------------
  21980. +/
  21981. static TP delegate(in TP) everyMonth(TP, Direction dir = Direction.fwd)(int month)
  21982. if(isTimePoint!TP &&
  21983. (dir == Direction.fwd || dir == Direction.bwd) &&
  21984. __traits(hasMember, TP, "month") &&
  21985. !__traits(isStaticFunction, TP.month) &&
  21986. is(ReturnType!(TP.month) == Month) &&
  21987. (functionAttributes!(TP.month) & FunctionAttribute.property) &&
  21988. (functionAttributes!(TP.month) & FunctionAttribute.nothrow_))
  21989. {
  21990. enforceValid!"months"(month);
  21991. TP func(in TP tp)
  21992. {
  21993. TP retval = cast(TP)tp;
  21994. immutable months = monthsToMonth(retval.month, month);
  21995. static if(dir == Direction.fwd)
  21996. immutable adjustedMonths = months == 0 ? 12 : months;
  21997. else
  21998. immutable adjustedMonths = months == 0 ? -12 : months - 12;
  21999. retval.add!"months"(adjustedMonths, AllowDayOverflow.no);
  22000. if(retval.month != month)
  22001. {
  22002. retval.add!"months"(-1);
  22003. assert(retval.month == month);
  22004. }
  22005. return retval;
  22006. }
  22007. return &func;
  22008. }
  22009. unittest
  22010. {
  22011. version(testStdDateTime)
  22012. {
  22013. auto funcFwd = everyMonth!Date(Month.jun);
  22014. auto funcBwd = everyMonth!(Date, Direction.bwd)(Month.jun);
  22015. _assertPred!"=="(funcFwd(Date(2010, 5, 31)), Date(2010, 6, 30));
  22016. _assertPred!"=="(funcFwd(Date(2010, 6, 30)), Date(2011, 6, 30));
  22017. _assertPred!"=="(funcFwd(Date(2010, 7, 31)), Date(2011, 6, 30));
  22018. _assertPred!"=="(funcFwd(Date(2010, 8, 31)), Date(2011, 6, 30));
  22019. _assertPred!"=="(funcFwd(Date(2010, 9, 30)), Date(2011, 6, 30));
  22020. _assertPred!"=="(funcFwd(Date(2010, 10, 31)), Date(2011, 6, 30));
  22021. _assertPred!"=="(funcFwd(Date(2010, 11, 30)), Date(2011, 6, 30));
  22022. _assertPred!"=="(funcFwd(Date(2010, 12, 31)), Date(2011, 6, 30));
  22023. _assertPred!"=="(funcFwd(Date(2011, 1, 31)), Date(2011, 6, 30));
  22024. _assertPred!"=="(funcFwd(Date(2011, 2, 28)), Date(2011, 6, 28));
  22025. _assertPred!"=="(funcFwd(Date(2011, 3, 31)), Date(2011, 6, 30));
  22026. _assertPred!"=="(funcFwd(Date(2011, 4, 30)), Date(2011, 6, 30));
  22027. _assertPred!"=="(funcFwd(Date(2011, 5, 31)), Date(2011, 6, 30));
  22028. _assertPred!"=="(funcFwd(Date(2011, 6, 30)), Date(2012, 6, 30));
  22029. _assertPred!"=="(funcFwd(Date(2011, 7, 31)), Date(2012, 6, 30));
  22030. _assertPred!"=="(funcBwd(Date(2010, 5, 31)), Date(2009, 6, 30));
  22031. _assertPred!"=="(funcBwd(Date(2010, 6, 30)), Date(2009, 6, 30));
  22032. _assertPred!"=="(funcBwd(Date(2010, 7, 31)), Date(2010, 6, 30));
  22033. _assertPred!"=="(funcBwd(Date(2010, 8, 31)), Date(2010, 6, 30));
  22034. _assertPred!"=="(funcBwd(Date(2010, 9, 30)), Date(2010, 6, 30));
  22035. _assertPred!"=="(funcBwd(Date(2010, 10, 31)), Date(2010, 6, 30));
  22036. _assertPred!"=="(funcBwd(Date(2010, 11, 30)), Date(2010, 6, 30));
  22037. _assertPred!"=="(funcBwd(Date(2010, 12, 31)), Date(2010, 6, 30));
  22038. _assertPred!"=="(funcBwd(Date(2011, 1, 31)), Date(2010, 6, 30));
  22039. _assertPred!"=="(funcBwd(Date(2011, 2, 28)), Date(2010, 6, 28));
  22040. _assertPred!"=="(funcBwd(Date(2011, 3, 31)), Date(2010, 6, 30));
  22041. _assertPred!"=="(funcBwd(Date(2011, 4, 30)), Date(2010, 6, 30));
  22042. _assertPred!"=="(funcBwd(Date(2011, 5, 31)), Date(2010, 6, 30));
  22043. _assertPred!"=="(funcBwd(Date(2011, 6, 30)), Date(2010, 6, 30));
  22044. _assertPred!"=="(funcBwd(Date(2011, 7, 30)), Date(2011, 6, 30));
  22045. static assert(!__traits(compiles, everyMonth!(TimeOfDay)(Month.jan)));
  22046. static assert(__traits(compiles, everyMonth!(DateTime)(Month.jan)));
  22047. static assert(__traits(compiles, everyMonth!(SysTime)(Month.jan)));
  22048. //Verify Examples.
  22049. auto interval = Interval!Date(Date(2000, 1, 30), Date(2004, 8, 5));
  22050. auto func = everyMonth!(Date)(Month.feb);
  22051. auto range = interval.fwdRange(func);
  22052. //Using PopFirst.yes would have made this Date(2010, 2, 29).
  22053. assert(range.front == Date(2000, 1, 30));
  22054. range.popFront();
  22055. assert(range.front == Date(2000, 2, 29));
  22056. range.popFront();
  22057. assert(range.front == Date(2001, 2, 28));
  22058. range.popFront();
  22059. assert(range.front == Date(2002, 2, 28));
  22060. range.popFront();
  22061. assert(range.front == Date(2003, 2, 28));
  22062. range.popFront();
  22063. assert(range.front == Date(2004, 2, 28));
  22064. range.popFront();
  22065. assert(range.empty);
  22066. }
  22067. }
  22068. /++
  22069. Range-generating function.
  22070. Returns a delegate which returns the next time point which is the given
  22071. duration later.
  22072. Using this delegate allows you to iterate over successive time points which
  22073. are apart by the given duration e.g. passing $(D dur!"days"(3)) to
  22074. $(D everyDuration) would result in a delegate which could be used to iterate
  22075. over a range of days which are each 3 days apart.
  22076. Params:
  22077. dir = The direction to iterate in. If passing the return value to
  22078. $(D fwdRange), use $(D Direction.fwd). If passing it to
  22079. $(D bwdRange), use $(D Direction.bwd).
  22080. duration = The duration which separates each successive time point in
  22081. the range.
  22082. Examples:
  22083. --------------------
  22084. auto interval = Interval!Date(Date(2010, 9, 2), Date(2010, 9, 27));
  22085. auto func = everyDuration!Date(dur!"days"(8));
  22086. auto range = interval.fwdRange(func);
  22087. //Using PopFirst.yes would have made this Date(2010, 9, 10).
  22088. assert(range.front == Date(2010, 9, 2));
  22089. range.popFront();
  22090. assert(range.front == Date(2010, 9, 10));
  22091. range.popFront();
  22092. assert(range.front == Date(2010, 9, 18));
  22093. range.popFront();
  22094. assert(range.front == Date(2010, 9, 26));
  22095. range.popFront();
  22096. assert(range.empty);
  22097. --------------------
  22098. +/
  22099. static TP delegate(in TP) everyDuration(TP, Direction dir = Direction.fwd, D)
  22100. (D duration) nothrow
  22101. if(isTimePoint!TP &&
  22102. __traits(compiles, TP.init + duration) &&
  22103. (dir == Direction.fwd || dir == Direction.bwd))
  22104. {
  22105. TP func(in TP tp)
  22106. {
  22107. static if(dir == Direction.fwd)
  22108. return tp + duration;
  22109. else
  22110. return tp - duration;
  22111. }
  22112. return &func;
  22113. }
  22114. unittest
  22115. {
  22116. version(testStdDateTime)
  22117. {
  22118. auto funcFwd = everyDuration!Date(dur!"days"(27));
  22119. auto funcBwd = everyDuration!(Date, Direction.bwd)(dur!"days"(27));
  22120. _assertPred!"=="(funcFwd(Date(2009, 12, 25)), Date(2010, 1, 21));
  22121. _assertPred!"=="(funcFwd(Date(2009, 12, 26)), Date(2010, 1, 22));
  22122. _assertPred!"=="(funcFwd(Date(2009, 12, 27)), Date(2010, 1, 23));
  22123. _assertPred!"=="(funcFwd(Date(2009, 12, 28)), Date(2010, 1, 24));
  22124. _assertPred!"=="(funcBwd(Date(2010, 1, 21)), Date(2009, 12, 25));
  22125. _assertPred!"=="(funcBwd(Date(2010, 1, 22)), Date(2009, 12, 26));
  22126. _assertPred!"=="(funcBwd(Date(2010, 1, 23)), Date(2009, 12, 27));
  22127. _assertPred!"=="(funcBwd(Date(2010, 1, 24)), Date(2009, 12, 28));
  22128. static assert(__traits(compiles, everyDuration!Date(dur!"hnsecs"(1))));
  22129. static assert(__traits(compiles, everyDuration!TimeOfDay(dur!"hnsecs"(1))));
  22130. static assert(__traits(compiles, everyDuration!DateTime(dur!"hnsecs"(1))));
  22131. static assert(__traits(compiles, everyDuration!SysTime(dur!"hnsecs"(1))));
  22132. //Verify Examples.
  22133. auto interval = Interval!Date(Date(2010, 9, 2), Date(2010, 9, 27));
  22134. auto func = everyDuration!Date(dur!"days"(8));
  22135. auto range = interval.fwdRange(func);
  22136. //Using PopFirst.yes would have made this Date(2010, 9, 10).
  22137. assert(range.front == Date(2010, 9, 2));
  22138. range.popFront();
  22139. assert(range.front == Date(2010, 9, 10));
  22140. range.popFront();
  22141. assert(range.front == Date(2010, 9, 18));
  22142. range.popFront();
  22143. assert(range.front == Date(2010, 9, 26));
  22144. range.popFront();
  22145. assert(range.empty);
  22146. }
  22147. }
  22148. /++
  22149. Range-generating function.
  22150. Returns a delegate which returns the next time point which is the given
  22151. number of years, month, and duration later.
  22152. The difference between this version of $(D everyDuration) and the version
  22153. which just takes a $(D Duration) is that this one also takes the number of
  22154. years and months (along with an $(D AllowDayOverflow) to indicate whether
  22155. adding years and months should allow the days to overflow).
  22156. Note that if iterating forward, $(D add!"years"()) is called on the given
  22157. time point, then $(D add!"months"()), and finally the duration is added
  22158. to it. However, if iterating backwards, the duration is added first, then
  22159. $(D add!"months"()) is called, and finally $(D add!"years"()) is called.
  22160. That way, going backwards generates close to the same time points that
  22161. iterating forward does, but since adding years and months is not entirely
  22162. reversible (due to possible day overflow, regardless of whether
  22163. $(D AllowDayOverflow.yes) or $(D AllowDayOverflow.no) is used), it can't be
  22164. guaranteed that iterating backwards will give you the same time points as
  22165. iterating forward would have (even assuming that the end of the range is a
  22166. time point which would be returned by the delegate when iterating forward
  22167. from $(D begin)).
  22168. Params:
  22169. dir = The direction to iterate in. If passing the return
  22170. value to $(D fwdRange), use $(D Direction.fwd). If
  22171. passing it to $(D bwdRange), use $(D Direction.bwd).
  22172. years = The number of years to add to the time point passed to
  22173. the delegate.
  22174. months = The number of months to add to the time point passed to
  22175. the delegate.
  22176. allowOverflow = Whether the days should be allowed to overflow on
  22177. $(D begin) and $(D end), causing their month to
  22178. increment.
  22179. duration = The duration to add to the time point passed to the
  22180. delegate.
  22181. Examples:
  22182. --------------------
  22183. auto interval = Interval!Date(Date(2010, 9, 2), Date(2025, 9, 27));
  22184. auto func = everyDuration!Date(4, 1, AllowDayOverflow.yes, dur!"days"(2));
  22185. auto range = interval.fwdRange(func);
  22186. //Using PopFirst.yes would have made this Date(2014, 10, 12).
  22187. assert(range.front == Date(2010, 9, 2));
  22188. range.popFront();
  22189. assert(range.front == Date(2014, 10, 4));
  22190. range.popFront();
  22191. assert(range.front == Date(2018, 11, 6));
  22192. range.popFront();
  22193. assert(range.front == Date(2022, 12, 8));
  22194. range.popFront();
  22195. assert(range.empty);
  22196. --------------------
  22197. +/
  22198. static TP delegate(in TP) everyDuration(TP, Direction dir = Direction.fwd, D)
  22199. (int years,
  22200. int months = 0,
  22201. AllowDayOverflow allowOverflow = AllowDayOverflow.yes,
  22202. D duration = dur!"days"(0)) nothrow
  22203. if(isTimePoint!TP &&
  22204. __traits(compiles, TP.init + duration) &&
  22205. __traits(compiles, TP.init.add!"years"(years)) &&
  22206. __traits(compiles, TP.init.add!"months"(months)) &&
  22207. (dir == Direction.fwd || dir == Direction.bwd))
  22208. {
  22209. TP func(in TP tp)
  22210. {
  22211. static if(dir == Direction.fwd)
  22212. {
  22213. TP retval = cast(TP)tp;
  22214. retval.add!"years"(years, allowOverflow);
  22215. retval.add!"months"(months, allowOverflow);
  22216. return retval + duration;
  22217. }
  22218. else
  22219. {
  22220. TP retval = tp - duration;
  22221. retval.add!"months"(-months, allowOverflow);
  22222. retval.add!"years"(-years, allowOverflow);
  22223. return retval;
  22224. }
  22225. }
  22226. return &func;
  22227. }
  22228. unittest
  22229. {
  22230. version(testStdDateTime)
  22231. {
  22232. {
  22233. auto funcFwd = everyDuration!Date(1, 2, AllowDayOverflow.yes, dur!"days"(3));
  22234. auto funcBwd = everyDuration!(Date, Direction.bwd)(1, 2, AllowDayOverflow.yes, dur!"days"(3));
  22235. _assertPred!"=="(funcFwd(Date(2009, 12, 25)), Date(2011, 2, 28));
  22236. _assertPred!"=="(funcFwd(Date(2009, 12, 26)), Date(2011, 3, 1));
  22237. _assertPred!"=="(funcFwd(Date(2009, 12, 27)), Date(2011, 3, 2));
  22238. _assertPred!"=="(funcFwd(Date(2009, 12, 28)), Date(2011, 3, 3));
  22239. _assertPred!"=="(funcFwd(Date(2009, 12, 29)), Date(2011, 3, 4));
  22240. _assertPred!"=="(funcBwd(Date(2011, 2, 28)), Date(2009, 12, 25));
  22241. _assertPred!"=="(funcBwd(Date(2011, 3, 1)), Date(2009, 12, 26));
  22242. _assertPred!"=="(funcBwd(Date(2011, 3, 2)), Date(2009, 12, 27));
  22243. _assertPred!"=="(funcBwd(Date(2011, 3, 3)), Date(2009, 12, 28));
  22244. _assertPred!"=="(funcBwd(Date(2011, 3, 4)), Date(2010, 1, 1));
  22245. }
  22246. {
  22247. auto funcFwd = everyDuration!Date(1, 2, AllowDayOverflow.no, dur!"days"(3));
  22248. auto funcBwd = everyDuration!(Date, Direction.bwd)(1, 2, AllowDayOverflow.yes, dur!"days"(3));
  22249. _assertPred!"=="(funcFwd(Date(2009, 12, 25)), Date(2011, 2, 28));
  22250. _assertPred!"=="(funcFwd(Date(2009, 12, 26)), Date(2011, 3, 1));
  22251. _assertPred!"=="(funcFwd(Date(2009, 12, 27)), Date(2011, 3, 2));
  22252. _assertPred!"=="(funcFwd(Date(2009, 12, 28)), Date(2011, 3, 3));
  22253. _assertPred!"=="(funcFwd(Date(2009, 12, 29)), Date(2011, 3, 3));
  22254. _assertPred!"=="(funcBwd(Date(2011, 2, 28)), Date(2009, 12, 25));
  22255. _assertPred!"=="(funcBwd(Date(2011, 3, 1)), Date(2009, 12, 26));
  22256. _assertPred!"=="(funcBwd(Date(2011, 3, 2)), Date(2009, 12, 27));
  22257. _assertPred!"=="(funcBwd(Date(2011, 3, 3)), Date(2009, 12, 28));
  22258. _assertPred!"=="(funcBwd(Date(2011, 3, 4)), Date(2010, 1, 1));
  22259. }
  22260. static assert(__traits(compiles, everyDuration!Date(1, 2, AllowDayOverflow.yes, dur!"hnsecs"(1))));
  22261. static assert(!__traits(compiles, everyDuration!TimeOfDay(1, 2, AllowDayOverflow.yes, dur!"hnsecs"(1))));
  22262. static assert(__traits(compiles, everyDuration!DateTime(1, 2, AllowDayOverflow.yes, dur!"hnsecs"(1))));
  22263. static assert(__traits(compiles, everyDuration!SysTime(1, 2, AllowDayOverflow.yes, dur!"hnsecs"(1))));
  22264. //Verify Examples.
  22265. auto interval = Interval!Date(Date(2010, 9, 2), Date(2025, 9, 27));
  22266. auto func = everyDuration!Date(4, 1, AllowDayOverflow.yes, dur!"days"(2));
  22267. auto range = interval.fwdRange(func);
  22268. //Using PopFirst.yes would have made this Date(2014, 10, 12).
  22269. assert(range.front == Date(2010, 9, 2));
  22270. range.popFront();
  22271. assert(range.front == Date(2014, 10, 4));
  22272. range.popFront();
  22273. assert(range.front == Date(2018, 11, 6));
  22274. range.popFront();
  22275. assert(range.front == Date(2022, 12, 8));
  22276. range.popFront();
  22277. assert(range.empty);
  22278. }
  22279. }
  22280. //TODO Add function to create a range generating function based on a date recurrence pattern string.
  22281. // This may or may not involve creating a date recurrence pattern class of some sort - probably
  22282. // yes if we want to make it easy to build them. However, there is a standard recurrence
  22283. // pattern string format which we'd want to support with a range generator (though if we have
  22284. // the class/struct, we'd probably want a version of the range generating function which took
  22285. // that rather than a string).
  22286. //==============================================================================
  22287. // Section with ranges.
  22288. //==============================================================================
  22289. /++
  22290. A range over an $(D Interval).
  22291. $(D IntervalRange) is only ever constructed by $(D Interval). However, when
  22292. it is constructed, it is given a function, $(D func), which is used to
  22293. generate the time points which are iterated over. $(D func) takes a time
  22294. point and returns a time point of the same type. So, for instance, if you
  22295. had an $(D Interval!Date), and you wanted to iterate over all of the days in
  22296. that interval, you would pass a function to $(D Interval)'s $(D fwdRange)
  22297. where that function took a $(D Date) and returned a $(D Date) which was one
  22298. day later. That function would then be used by $(D IntervalRange)'s
  22299. $(D popFront) to iterate over the $(D Date)s in the interval.
  22300. If $(D dir == Direction.fwd), then a range iterates forward in time, whereas
  22301. if $(D dir == Direction.bwd), then it iterates backwards in time. So, if
  22302. $(D dir == Direction.fwd) then $(D front == interval.begin), whereas if
  22303. $(D dir == Direction.bwd) then $(D front == interval.end). $(D func) must
  22304. generate a time point going in the proper direction of iteration, or a
  22305. $(D DateTimeException) will be thrown. So, if you're iterating forward in
  22306. time, the time point that $(D func) generates must be later in time than the
  22307. one passed to it. If it's either identical or earlier in time, then a
  22308. $(D DateTimeException) will be thrown. If you're iterating backwards, then
  22309. the generated time point must be before the time point which was passed in.
  22310. If the generated time point is ever passed the edge of the range in the
  22311. proper direction, then the edge of that range will be used instead. So, if
  22312. iterating forward, and the generated time point is past the interval's
  22313. $(D end), then $(D front) becomes $(D end). If iterating backwards, and the
  22314. generated time point is before $(D begin), then $(D front) becomes
  22315. $(D begin). In either case, the range would then be empty.
  22316. Also note that while normally the $(D begin) of an interval is included in
  22317. it and its $(D end) is excluded from it, if $(D dir == Direction.bwd), then
  22318. $(D begin) is treated as excluded and $(D end) is treated as included. This
  22319. allows for the same behavior in both directions. This works because none of
  22320. $(D Interval)'s functions which care about whether $(D begin) or $(D end) is
  22321. included or excluded are ever called by $(D IntervalRange). $(D interval)
  22322. returns a normal interval, regardless of whether $(D dir == Direction.fwd)
  22323. or if $(D dir == Direction.bwd), so any $(D Interval) functions which are
  22324. called on it which care about whether $(D begin) or $(D end) are included or
  22325. excluded will treat $(D begin) as included and $(D end) as excluded.
  22326. +/
  22327. struct IntervalRange(TP, Direction dir)
  22328. if(isTimePoint!TP && dir != Direction.both)
  22329. {
  22330. public:
  22331. /++
  22332. Params:
  22333. rhs = The $(D IntervalRange) to assign to this one.
  22334. +/
  22335. /+ref+/ IntervalRange opAssign(ref IntervalRange rhs) pure nothrow
  22336. {
  22337. _interval = rhs._interval;
  22338. _func = rhs._func;
  22339. return this;
  22340. }
  22341. /++
  22342. Whether this $(D IntervalRange) is empty.
  22343. +/
  22344. @property bool empty() const pure nothrow
  22345. {
  22346. return _interval.empty;
  22347. }
  22348. /++
  22349. The first time point in the range.
  22350. Throws:
  22351. $(D DateTimeException) if the range is empty.
  22352. +/
  22353. @property TP front() const pure
  22354. {
  22355. _enforceNotEmpty();
  22356. static if(dir == Direction.fwd)
  22357. return _interval.begin;
  22358. else
  22359. return _interval.end;
  22360. }
  22361. /++
  22362. Pops $(D front) from the range, using $(D func) to generate the next
  22363. time point in the range. If the generated time point is beyond the edge
  22364. of the range, then $(D front) is set to that edge, and the range is then
  22365. empty. So, if iterating forwards, and the generated time point is
  22366. greater than the interval's $(D end), then $(D front) is set to
  22367. $(D end). If iterating backwards, and the generated time point is less
  22368. than the interval's $(D begin), then $(D front) is set to $(D begin).
  22369. Throws:
  22370. $(D DateTimeException) if the range is empty or if the generated
  22371. time point is in the wrong direction (i.e. if you're iterating
  22372. forward and the generated time point is before $(D front), or if
  22373. you're iterating backwards, and the generated time point is after
  22374. $(D front)).
  22375. +/
  22376. void popFront()
  22377. {
  22378. _enforceNotEmpty();
  22379. static if(dir == Direction.fwd)
  22380. {
  22381. auto begin = _func(_interval.begin);
  22382. if(begin > _interval.end)
  22383. begin = _interval.end;
  22384. _enforceCorrectDirection(begin);
  22385. _interval.begin = begin;
  22386. }
  22387. else
  22388. {
  22389. auto end = _func(_interval.end);
  22390. if(end < _interval.begin)
  22391. end = _interval.begin;
  22392. _enforceCorrectDirection(end);
  22393. _interval.end = end;
  22394. }
  22395. }
  22396. /++
  22397. Returns a copy of $(D this).
  22398. +/
  22399. @property IntervalRange save() pure nothrow
  22400. {
  22401. return this;
  22402. }
  22403. /++
  22404. The interval that this $(D IntervalRange) currently covers.
  22405. +/
  22406. @property Interval!TP interval() const pure nothrow
  22407. {
  22408. return cast(Interval!TP)_interval;
  22409. }
  22410. /++
  22411. The function used to generate the next time point in the range.
  22412. +/
  22413. TP delegate(in TP) func() pure nothrow @property
  22414. {
  22415. return _func;
  22416. }
  22417. /++
  22418. The $(D Direction) that this range iterates in.
  22419. +/
  22420. @property Direction direction() const pure nothrow
  22421. {
  22422. return dir;
  22423. }
  22424. private:
  22425. /+
  22426. Params:
  22427. interval = The interval that this range covers.
  22428. func = The function used to generate the time points which are
  22429. iterated over.
  22430. +/
  22431. this(in Interval!TP interval, TP delegate(in TP) func) pure nothrow
  22432. {
  22433. _func = func;
  22434. _interval = interval;
  22435. }
  22436. /+
  22437. Throws:
  22438. $(D DateTimeException) if this interval is empty.
  22439. +/
  22440. void _enforceNotEmpty(size_t line = __LINE__) const pure
  22441. {
  22442. if(empty)
  22443. throw new DateTimeException("Invalid operation for an empty IntervalRange.", __FILE__, line);
  22444. }
  22445. /+
  22446. Throws:
  22447. $(D DateTimeException) if $(D_PARAM newTP) is in the wrong
  22448. direction.
  22449. +/
  22450. void _enforceCorrectDirection(in TP newTP, size_t line = __LINE__) const
  22451. {
  22452. static if(dir == Direction.fwd)
  22453. {
  22454. enforce(newTP > _interval._begin,
  22455. new DateTimeException(format("Generated time point is before previous begin: prev [%s] new [%s]",
  22456. interval._begin,
  22457. newTP),
  22458. __FILE__,
  22459. line));
  22460. }
  22461. else
  22462. {
  22463. enforce(newTP < _interval._end,
  22464. new DateTimeException(format("Generated time point is after previous end: prev [%s] new [%s]",
  22465. interval._end,
  22466. newTP),
  22467. __FILE__,
  22468. line));
  22469. }
  22470. }
  22471. Interval!TP _interval;
  22472. TP delegate(in TP) _func;
  22473. }
  22474. //Test that IntervalRange satisfies the range predicates that it's supposed to satisfy.
  22475. unittest
  22476. {
  22477. version(testStdDateTime)
  22478. {
  22479. static assert(isInputRange!(IntervalRange!(Date, Direction.fwd)));
  22480. static assert(isForwardRange!(IntervalRange!(Date, Direction.fwd)));
  22481. //Commented out due to bug http://d.puremagic.com/issues/show_bug.cgi?id=4895
  22482. //static assert(!isOutputRange!(IntervalRange!(Date, Direction.fwd), Date));
  22483. static assert(!isBidirectionalRange!(IntervalRange!(Date, Direction.fwd)));
  22484. static assert(!isRandomAccessRange!(IntervalRange!(Date, Direction.fwd)));
  22485. static assert(!hasSwappableElements!(IntervalRange!(Date, Direction.fwd)));
  22486. static assert(!hasAssignableElements!(IntervalRange!(Date, Direction.fwd)));
  22487. static assert(!hasLength!(IntervalRange!(Date, Direction.fwd)));
  22488. static assert(!isInfinite!(IntervalRange!(Date, Direction.fwd)));
  22489. static assert(!hasSlicing!(IntervalRange!(Date, Direction.fwd)));
  22490. static assert(is(ElementType!(IntervalRange!(Date, Direction.fwd)) == Date));
  22491. static assert(is(ElementType!(IntervalRange!(TimeOfDay, Direction.fwd)) == TimeOfDay));
  22492. static assert(is(ElementType!(IntervalRange!(DateTime, Direction.fwd)) == DateTime));
  22493. static assert(is(ElementType!(IntervalRange!(SysTime, Direction.fwd)) == SysTime));
  22494. }
  22495. }
  22496. //Test construction of IntervalRange.
  22497. unittest
  22498. {
  22499. version(testStdDateTime)
  22500. {
  22501. {
  22502. Date dateFunc(in Date date)
  22503. {
  22504. return date;
  22505. }
  22506. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  22507. auto ir = IntervalRange!(Date, Direction.fwd)(interval, &dateFunc);
  22508. }
  22509. {
  22510. TimeOfDay todFunc(in TimeOfDay tod)
  22511. {
  22512. return tod;
  22513. }
  22514. auto interval = Interval!TimeOfDay(TimeOfDay(12, 1, 7), TimeOfDay(14, 0, 0));
  22515. auto ir = IntervalRange!(TimeOfDay, Direction.fwd)(interval, &todFunc);
  22516. }
  22517. {
  22518. DateTime dtFunc(in DateTime dt)
  22519. {
  22520. return dt;
  22521. }
  22522. auto interval = Interval!DateTime(DateTime(2010, 7, 4, 12, 1, 7), DateTime(2012, 1, 7, 14, 0, 0));
  22523. auto ir = IntervalRange!(DateTime, Direction.fwd)(interval, &dtFunc);
  22524. }
  22525. {
  22526. SysTime stFunc(in SysTime st)
  22527. {
  22528. return cast(SysTime)st;
  22529. }
  22530. auto interval = Interval!SysTime(SysTime(DateTime(2010, 7, 4, 12, 1, 7)), SysTime(DateTime(2012, 1, 7, 14, 0, 0)));
  22531. auto ir = IntervalRange!(SysTime, Direction.fwd)(interval, &stFunc);
  22532. }
  22533. }
  22534. }
  22535. //Test IntervalRange's empty().
  22536. unittest
  22537. {
  22538. version(testStdDateTime)
  22539. {
  22540. //fwd
  22541. {
  22542. auto range = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 21)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
  22543. assert(!range.empty);
  22544. range.popFront();
  22545. assert(range.empty);
  22546. const cRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
  22547. static assert(__traits(compiles, cRange.empty));
  22548. //Apparently, creating an immutable IntervalRange!Date doesn't work, so we can't test if
  22549. //empty works with it. However, since an immutable range is pretty useless, it's no great loss.
  22550. }
  22551. //bwd
  22552. {
  22553. auto range = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 21)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
  22554. assert(!range.empty);
  22555. range.popFront();
  22556. assert(range.empty);
  22557. const cRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
  22558. static assert(__traits(compiles, cRange.empty));
  22559. //Apparently, creating an immutable IntervalRange!Date doesn't work, so we can't test if
  22560. //empty works with it. However, since an immutable range is pretty useless, it's no great loss.
  22561. }
  22562. }
  22563. }
  22564. //Test IntervalRange's front.
  22565. unittest
  22566. {
  22567. version(testStdDateTime)
  22568. {
  22569. //fwd
  22570. {
  22571. auto emptyRange = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 20)).fwdRange(everyDayOfWeek!Date(DayOfWeek.wed), PopFirst.yes);
  22572. assertThrown!DateTimeException((in IntervalRange!(Date, Direction.fwd) range){range.front;}(emptyRange));
  22573. auto range = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).fwdRange(everyDayOfWeek!Date(DayOfWeek.wed));
  22574. _assertPred!"=="(range.front, Date(2010, 7, 4));
  22575. auto poppedRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).fwdRange(everyDayOfWeek!Date(DayOfWeek.wed), PopFirst.yes);
  22576. _assertPred!"=="(poppedRange.front, Date(2010, 7, 7));
  22577. const cRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
  22578. static assert(__traits(compiles, cRange.front));
  22579. }
  22580. //bwd
  22581. {
  22582. auto emptyRange = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 20)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed), PopFirst.yes);
  22583. assertThrown!DateTimeException((in IntervalRange!(Date, Direction.bwd) range){range.front;}(emptyRange));
  22584. auto range = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed));
  22585. _assertPred!"=="(range.front, Date(2012, 1, 7));
  22586. auto poppedRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed), PopFirst.yes);
  22587. _assertPred!"=="(poppedRange.front, Date(2012, 1, 4));
  22588. const cRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
  22589. static assert(__traits(compiles, cRange.front));
  22590. }
  22591. }
  22592. }
  22593. //Test IntervalRange's popFront().
  22594. unittest
  22595. {
  22596. version(testStdDateTime)
  22597. {
  22598. //fwd
  22599. {
  22600. auto emptyRange = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 20)).fwdRange(everyDayOfWeek!Date(DayOfWeek.wed), PopFirst.yes);
  22601. assertThrown!DateTimeException((IntervalRange!(Date, Direction.fwd) range){range.popFront();}(emptyRange));
  22602. auto range = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).fwdRange(everyDayOfWeek!Date(DayOfWeek.wed), PopFirst.yes);
  22603. auto expected = range.front;
  22604. foreach(date; range)
  22605. {
  22606. _assertPred!"=="(date, expected);
  22607. expected += dur!"days"(7);
  22608. }
  22609. _assertPred!"=="(walkLength(range), 79);
  22610. const cRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
  22611. static assert(__traits(compiles, cRange.front));
  22612. }
  22613. //bwd
  22614. {
  22615. auto emptyRange = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 20)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed), PopFirst.yes);
  22616. assertThrown!DateTimeException((IntervalRange!(Date, Direction.bwd) range){range.popFront();}(emptyRange));
  22617. auto range = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed), PopFirst.yes);
  22618. auto expected = range.front;
  22619. foreach(date; range)
  22620. {
  22621. _assertPred!"=="(date, expected);
  22622. expected += dur!"days"(-7);
  22623. }
  22624. _assertPred!"=="(walkLength(range), 79);
  22625. const cRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
  22626. static assert(!__traits(compiles, cRange.popFront()));
  22627. }
  22628. }
  22629. }
  22630. //Test IntervalRange's save.
  22631. unittest
  22632. {
  22633. version(testStdDateTime)
  22634. {
  22635. //fwd
  22636. {
  22637. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  22638. auto func = everyDayOfWeek!Date(DayOfWeek.fri);
  22639. auto range = interval.fwdRange(func);
  22640. assert(range.save == range);
  22641. }
  22642. //bwd
  22643. {
  22644. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  22645. auto func = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri);
  22646. auto range = interval.bwdRange(func);
  22647. assert(range.save == range);
  22648. }
  22649. }
  22650. }
  22651. //Test IntervalRange's interval.
  22652. unittest
  22653. {
  22654. version(testStdDateTime)
  22655. {
  22656. //fwd
  22657. {
  22658. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  22659. auto func = everyDayOfWeek!Date(DayOfWeek.fri);
  22660. auto range = interval.fwdRange(func);
  22661. assert(range.interval == interval);
  22662. const cRange = range;
  22663. static assert(__traits(compiles, cRange.interval));
  22664. }
  22665. //bwd
  22666. {
  22667. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  22668. auto func = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri);
  22669. auto range = interval.bwdRange(func);
  22670. assert(range.interval == interval);
  22671. const cRange = range;
  22672. static assert(__traits(compiles, cRange.interval));
  22673. }
  22674. }
  22675. }
  22676. //Test IntervalRange's func.
  22677. unittest
  22678. {
  22679. version(testStdDateTime)
  22680. {
  22681. //fwd
  22682. {
  22683. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  22684. auto func = everyDayOfWeek!Date(DayOfWeek.fri);
  22685. auto range = interval.fwdRange(func);
  22686. assert(range.func == func);
  22687. }
  22688. //bwd
  22689. {
  22690. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  22691. auto func = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri);
  22692. auto range = interval.bwdRange(func);
  22693. assert(range.func == func);
  22694. }
  22695. }
  22696. }
  22697. //Test IntervalRange's direction.
  22698. unittest
  22699. {
  22700. version(testStdDateTime)
  22701. {
  22702. //fwd
  22703. {
  22704. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  22705. auto func = everyDayOfWeek!Date(DayOfWeek.fri);
  22706. auto range = interval.fwdRange(func);
  22707. assert(range.direction == Direction.fwd);
  22708. const cRange = range;
  22709. static assert(__traits(compiles, cRange.direction));
  22710. }
  22711. //bwd
  22712. {
  22713. auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
  22714. auto func = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri);
  22715. auto range = interval.bwdRange(func);
  22716. assert(range.direction == Direction.bwd);
  22717. const cRange = range;
  22718. static assert(__traits(compiles, cRange.direction));
  22719. }
  22720. }
  22721. }
  22722. /++
  22723. A range over a $(D PosInfInterval). It is an infinite range.
  22724. $(D PosInfIntervalRange) is only ever constructed by $(D PosInfInterval).
  22725. However, when it is constructed, it is given a function, $(D func), which
  22726. is used to generate the time points which are iterated over. $(D func)
  22727. takes a time point and returns a time point of the same type. So, for
  22728. instance, if you had a $(D PosInfInterval!Date), and you wanted to iterate
  22729. over all of the days in that interval, you would pass a function to
  22730. $(D PosInfInterval)'s $(D fwdRange) where that function took a $(D Date) and
  22731. returned a $(D Date) which was one day later. That function would then be
  22732. used by $(D PosInfIntervalRange)'s $(D popFront) to iterate over the
  22733. $(D Date)s in the interval - though obviously, since the range is infinite,
  22734. you would use a function such as $(D std.range.take) with it rather than
  22735. iterating over $(I all) of the dates.
  22736. As the interval goes to positive infinity, the range is always iterated over
  22737. forwards, never backwards. $(D func) must generate a time point going in
  22738. the proper direction of iteration, or a $(D DateTimeException) will be
  22739. thrown. So, the time points that $(D func) generates must be later in time
  22740. than the one passed to it. If it's either identical or earlier in time, then
  22741. a $(D DateTimeException) will be thrown.
  22742. +/
  22743. struct PosInfIntervalRange(TP)
  22744. if(isTimePoint!TP)
  22745. {
  22746. public:
  22747. /++
  22748. Params:
  22749. rhs = The $(D PosInfIntervalRange) to assign to this one.
  22750. +/
  22751. /+ref+/ PosInfIntervalRange opAssign(ref PosInfIntervalRange rhs) pure nothrow
  22752. {
  22753. _interval = rhs._interval;
  22754. _func = rhs._func;
  22755. return this;
  22756. }
  22757. /++
  22758. This is an infinite range, so it is never empty.
  22759. +/
  22760. enum bool empty = false;
  22761. /++
  22762. The first time point in the range.
  22763. +/
  22764. @property TP front() const pure nothrow
  22765. {
  22766. return _interval.begin;
  22767. }
  22768. /++
  22769. Pops $(D front) from the range, using $(D func) to generate the next
  22770. time point in the range.
  22771. Throws:
  22772. $(D DateTimeException) if the generated time point is less than
  22773. $(D front).
  22774. +/
  22775. void popFront()
  22776. {
  22777. auto begin = _func(_interval.begin);
  22778. _enforceCorrectDirection(begin);
  22779. _interval.begin = begin;
  22780. }
  22781. /++
  22782. Returns a copy of $(D this).
  22783. +/
  22784. @property PosInfIntervalRange save() pure nothrow
  22785. {
  22786. return this;
  22787. }
  22788. /++
  22789. The interval that this range currently covers.
  22790. +/
  22791. @property PosInfInterval!TP interval() const pure nothrow
  22792. {
  22793. return cast(PosInfInterval!TP)_interval;
  22794. }
  22795. /++
  22796. The function used to generate the next time point in the range.
  22797. +/
  22798. TP delegate(in TP) func() pure nothrow @property
  22799. {
  22800. return _func;
  22801. }
  22802. private:
  22803. /+
  22804. Params:
  22805. interval = The interval that this range covers.
  22806. func = The function used to generate the time points which are
  22807. iterated over.
  22808. +/
  22809. this(in PosInfInterval!TP interval, TP delegate(in TP) func) pure nothrow
  22810. {
  22811. _func = func;
  22812. _interval = interval;
  22813. }
  22814. /+
  22815. Throws:
  22816. $(D DateTimeException) if $(D_PARAME newTP) is in the wrong
  22817. direction.
  22818. +/
  22819. void _enforceCorrectDirection(in TP newTP, size_t line = __LINE__) const
  22820. {
  22821. enforce(newTP > _interval._begin,
  22822. new DateTimeException(format("Generated time point is before previous begin: prev [%s] new [%s]",
  22823. interval._begin,
  22824. newTP),
  22825. __FILE__,
  22826. line));
  22827. }
  22828. PosInfInterval!TP _interval;
  22829. TP delegate(in TP) _func;
  22830. }
  22831. //Test that PosInfIntervalRange satisfies the range predicates that it's supposed to satisfy.
  22832. unittest
  22833. {
  22834. version(testStdDateTime)
  22835. {
  22836. static assert(isInputRange!(PosInfIntervalRange!Date));
  22837. static assert(isForwardRange!(PosInfIntervalRange!Date));
  22838. static assert(isInfinite!(PosInfIntervalRange!Date));
  22839. //Commented out due to bug http://d.puremagic.com/issues/show_bug.cgi?id=4895
  22840. //static assert(!isOutputRange!(PosInfIntervalRange!Date, Date));
  22841. static assert(!isBidirectionalRange!(PosInfIntervalRange!Date));
  22842. static assert(!isRandomAccessRange!(PosInfIntervalRange!Date));
  22843. static assert(!hasSwappableElements!(PosInfIntervalRange!Date));
  22844. static assert(!hasAssignableElements!(PosInfIntervalRange!Date));
  22845. static assert(!hasLength!(PosInfIntervalRange!Date));
  22846. static assert(!hasSlicing!(PosInfIntervalRange!Date));
  22847. static assert(is(ElementType!(PosInfIntervalRange!Date) == Date));
  22848. static assert(is(ElementType!(PosInfIntervalRange!TimeOfDay) == TimeOfDay));
  22849. static assert(is(ElementType!(PosInfIntervalRange!DateTime) == DateTime));
  22850. static assert(is(ElementType!(PosInfIntervalRange!SysTime) == SysTime));
  22851. }
  22852. }
  22853. //Test construction of PosInfIntervalRange.
  22854. unittest
  22855. {
  22856. version(testStdDateTime)
  22857. {
  22858. {
  22859. Date dateFunc(in Date date)
  22860. {
  22861. return date;
  22862. }
  22863. auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
  22864. auto ir = PosInfIntervalRange!Date(posInfInterval, &dateFunc);
  22865. }
  22866. {
  22867. TimeOfDay todFunc(in TimeOfDay tod)
  22868. {
  22869. return tod;
  22870. }
  22871. auto posInfInterval = PosInfInterval!TimeOfDay(TimeOfDay(12, 1, 7));
  22872. auto ir = PosInfIntervalRange!(TimeOfDay)(posInfInterval, &todFunc);
  22873. }
  22874. {
  22875. DateTime dtFunc(in DateTime dt)
  22876. {
  22877. return dt;
  22878. }
  22879. auto posInfInterval = PosInfInterval!DateTime(DateTime(2010, 7, 4, 12, 1, 7));
  22880. auto ir = PosInfIntervalRange!(DateTime)(posInfInterval, &dtFunc);
  22881. }
  22882. {
  22883. SysTime stFunc(in SysTime st)
  22884. {
  22885. return cast(SysTime)st;
  22886. }
  22887. auto posInfInterval = PosInfInterval!SysTime(SysTime(DateTime(2010, 7, 4, 12, 1, 7)));
  22888. auto ir = PosInfIntervalRange!(SysTime)(posInfInterval, &stFunc);
  22889. }
  22890. }
  22891. }
  22892. //Test PosInfIntervalRange's front.
  22893. unittest
  22894. {
  22895. version(testStdDateTime)
  22896. {
  22897. auto range = PosInfInterval!Date(Date(2010, 7, 4)).fwdRange(everyDayOfWeek!Date(DayOfWeek.wed));
  22898. _assertPred!"=="(range.front, Date(2010, 7, 4));
  22899. auto poppedRange = PosInfInterval!Date(Date(2010, 7, 4)).fwdRange(everyDayOfWeek!Date(DayOfWeek.wed), PopFirst.yes);
  22900. _assertPred!"=="(poppedRange.front, Date(2010, 7, 7));
  22901. const cRange = PosInfInterval!Date(Date(2010, 7, 4)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
  22902. static assert(__traits(compiles, cRange.front));
  22903. }
  22904. }
  22905. //Test PosInfIntervalRange's popFront().
  22906. unittest
  22907. {
  22908. version(testStdDateTime)
  22909. {
  22910. auto range = PosInfInterval!Date(Date(2010, 7, 4)).fwdRange(everyDayOfWeek!Date(DayOfWeek.wed), PopFirst.yes);
  22911. auto expected = range.front;
  22912. foreach(date; take(range, 79))
  22913. {
  22914. _assertPred!"=="(date, expected);
  22915. expected += dur!"days"(7);
  22916. }
  22917. const cRange = PosInfInterval!Date(Date(2010, 7, 4)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
  22918. static assert(!__traits(compiles, cRange.popFront()));
  22919. }
  22920. }
  22921. //Test PosInfIntervalRange's save.
  22922. unittest
  22923. {
  22924. version(testStdDateTime)
  22925. {
  22926. auto interval = PosInfInterval!Date(Date(2010, 7, 4));
  22927. auto func = everyDayOfWeek!Date(DayOfWeek.fri);
  22928. auto range = interval.fwdRange(func);
  22929. assert(range.save == range);
  22930. }
  22931. }
  22932. //Test PosInfIntervalRange's interval.
  22933. unittest
  22934. {
  22935. version(testStdDateTime)
  22936. {
  22937. auto interval = PosInfInterval!Date(Date(2010, 7, 4));
  22938. auto func = everyDayOfWeek!Date(DayOfWeek.fri);
  22939. auto range = interval.fwdRange(func);
  22940. assert(range.interval == interval);
  22941. const cRange = range;
  22942. static assert(__traits(compiles, cRange.interval));
  22943. }
  22944. }
  22945. //Test PosInfIntervalRange's func.
  22946. unittest
  22947. {
  22948. version(testStdDateTime)
  22949. {
  22950. auto interval = PosInfInterval!Date(Date(2010, 7, 4));
  22951. auto func = everyDayOfWeek!Date(DayOfWeek.fri);
  22952. auto range = interval.fwdRange(func);
  22953. assert(range.func == func);
  22954. }
  22955. }
  22956. /++
  22957. A range over a $(D NegInfInterval). It is an infinite range.
  22958. $(D NegInfIntervalRange) is only ever constructed by $(D NegInfInterval).
  22959. However, when it is constructed, it is given a function, $(D func), which
  22960. is used to generate the time points which are iterated over. $(D func)
  22961. takes a time point and returns a time point of the same type. So, for
  22962. instance, if you had a $(D NegInfInterval!Date), and you wanted to iterate
  22963. over all of the days in that interval, you would pass a function to
  22964. $(D NegInfInterval)'s $(D bwdRange) where that function took a $(D Date) and
  22965. returned a $(D Date) which was one day earlier. That function would then be
  22966. used by $(D NegInfIntervalRange)'s $(D popFront) to iterate over the
  22967. $(D Date)s in the interval - though obviously, since the range is infinite,
  22968. you would use a function such as $(D std.range.take) with it rather than
  22969. iterating over $(I all) of the dates.
  22970. As the interval goes to negative infinity, the range is always iterated over
  22971. backwards, never forwards. $(D func) must generate a time point going in
  22972. the proper direction of iteration, or a $(D DateTimeException) will be
  22973. thrown. So, the time points that $(D func) generates must be earlier in time
  22974. than the one passed to it. If it's either identical or later in time, then a
  22975. $(D DateTimeException) will be thrown.
  22976. Also note that while normally the $(D end) of an interval is excluded from
  22977. it, $(D NegInfIntervalRange) treats it as if it were included. This allows
  22978. for the same behavior as you get with $(D PosInfIntervalRange). This works
  22979. because none of $(D NegInfInterval)'s functions which care about whether
  22980. $(D end) is included or excluded are ever called by
  22981. $(D NegInfIntervalRange). $(D interval) returns a normal interval, so any
  22982. $(D NegInfInterval) functions which are called on it which care about
  22983. whether $(D end) is included or excluded will treat $(D end) as excluded.
  22984. +/
  22985. struct NegInfIntervalRange(TP)
  22986. if(isTimePoint!TP)
  22987. {
  22988. public:
  22989. /++
  22990. Params:
  22991. rhs = The $(D NegInfIntervalRange) to assign to this one.
  22992. +/
  22993. /+ref+/ NegInfIntervalRange opAssign(ref NegInfIntervalRange rhs) pure nothrow
  22994. {
  22995. _interval = rhs._interval;
  22996. _func = rhs._func;
  22997. return this;
  22998. }
  22999. /++
  23000. This is an infinite range, so it is never empty.
  23001. +/
  23002. enum bool empty = false;
  23003. /++
  23004. The first time point in the range.
  23005. +/
  23006. @property TP front() const pure nothrow
  23007. {
  23008. return _interval.end;
  23009. }
  23010. /++
  23011. Pops $(D front) from the range, using $(D func) to generate the next
  23012. time point in the range.
  23013. Throws:
  23014. $(D DateTimeException) if the generated time point is greater than
  23015. $(D front).
  23016. +/
  23017. void popFront()
  23018. {
  23019. auto end = _func(_interval.end);
  23020. _enforceCorrectDirection(end);
  23021. _interval.end = end;
  23022. }
  23023. /++
  23024. Returns a copy of $(D this).
  23025. +/
  23026. @property NegInfIntervalRange save() pure nothrow
  23027. {
  23028. return this;
  23029. }
  23030. /++
  23031. The interval that this range currently covers.
  23032. +/
  23033. @property NegInfInterval!TP interval() const pure nothrow
  23034. {
  23035. return cast(NegInfInterval!TP)_interval;
  23036. }
  23037. /++
  23038. The function used to generate the next time point in the range.
  23039. +/
  23040. TP delegate(in TP) func() pure nothrow @property
  23041. {
  23042. return _func;
  23043. }
  23044. private:
  23045. /+
  23046. Params:
  23047. interval = The interval that this range covers.
  23048. func = The function used to generate the time points which are
  23049. iterated over.
  23050. +/
  23051. this(in NegInfInterval!TP interval, TP delegate(in TP) func) pure nothrow
  23052. {
  23053. _func = func;
  23054. _interval = interval;
  23055. }
  23056. /+
  23057. Throws:
  23058. $(D DateTimeException) if $(D_PARAM newTP) is in the wrong
  23059. direction.
  23060. +/
  23061. void _enforceCorrectDirection(in TP newTP, size_t line = __LINE__) const
  23062. {
  23063. enforce(newTP < _interval._end,
  23064. new DateTimeException(format("Generated time point is before previous end: prev [%s] new [%s]",
  23065. interval._end,
  23066. newTP),
  23067. __FILE__,
  23068. line));
  23069. }
  23070. NegInfInterval!TP _interval;
  23071. TP delegate(in TP) _func;
  23072. }
  23073. //Test that NegInfIntervalRange satisfies the range predicates that it's supposed to satisfy.
  23074. unittest
  23075. {
  23076. version(testStdDateTime)
  23077. {
  23078. static assert(isInputRange!(NegInfIntervalRange!Date));
  23079. static assert(isForwardRange!(NegInfIntervalRange!Date));
  23080. static assert(isInfinite!(NegInfIntervalRange!Date));
  23081. //Commented out due to bug http://d.puremagic.com/issues/show_bug.cgi?id=4895
  23082. //static assert(!isOutputRange!(NegInfIntervalRange!Date, Date));
  23083. static assert(!isBidirectionalRange!(NegInfIntervalRange!Date));
  23084. static assert(!isRandomAccessRange!(NegInfIntervalRange!Date));
  23085. static assert(!hasSwappableElements!(NegInfIntervalRange!Date));
  23086. static assert(!hasAssignableElements!(NegInfIntervalRange!Date));
  23087. static assert(!hasLength!(NegInfIntervalRange!Date));
  23088. static assert(!hasSlicing!(NegInfIntervalRange!Date));
  23089. static assert(is(ElementType!(NegInfIntervalRange!Date) == Date));
  23090. static assert(is(ElementType!(NegInfIntervalRange!TimeOfDay) == TimeOfDay));
  23091. static assert(is(ElementType!(NegInfIntervalRange!DateTime) == DateTime));
  23092. }
  23093. }
  23094. //Test construction of NegInfIntervalRange.
  23095. unittest
  23096. {
  23097. version(testStdDateTime)
  23098. {
  23099. {
  23100. Date dateFunc(in Date date)
  23101. {
  23102. return date;
  23103. }
  23104. auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
  23105. auto ir = NegInfIntervalRange!Date(negInfInterval, &dateFunc);
  23106. }
  23107. {
  23108. TimeOfDay todFunc(in TimeOfDay tod)
  23109. {
  23110. return tod;
  23111. }
  23112. auto negInfInterval = NegInfInterval!TimeOfDay(TimeOfDay(14, 0, 0));
  23113. auto ir = NegInfIntervalRange!(TimeOfDay)(negInfInterval, &todFunc);
  23114. }
  23115. {
  23116. DateTime dtFunc(in DateTime dt)
  23117. {
  23118. return dt;
  23119. }
  23120. auto negInfInterval = NegInfInterval!DateTime(DateTime(2012, 1, 7, 14, 0, 0));
  23121. auto ir = NegInfIntervalRange!(DateTime)(negInfInterval, &dtFunc);
  23122. }
  23123. {
  23124. SysTime stFunc(in SysTime st)
  23125. {
  23126. return cast(SysTime)(st);
  23127. }
  23128. auto negInfInterval = NegInfInterval!SysTime(SysTime(DateTime(2012, 1, 7, 14, 0, 0)));
  23129. auto ir = NegInfIntervalRange!(SysTime)(negInfInterval, &stFunc);
  23130. }
  23131. }
  23132. }
  23133. //Test NegInfIntervalRange's front.
  23134. unittest
  23135. {
  23136. version(testStdDateTime)
  23137. {
  23138. auto range = NegInfInterval!Date(Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed));
  23139. _assertPred!"=="(range.front, Date(2012, 1, 7));
  23140. auto poppedRange = NegInfInterval!Date(Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed), PopFirst.yes);
  23141. _assertPred!"=="(poppedRange.front, Date(2012, 1, 4));
  23142. const cRange = NegInfInterval!Date(Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
  23143. static assert(__traits(compiles, cRange.front));
  23144. }
  23145. }
  23146. //Test NegInfIntervalRange's popFront().
  23147. unittest
  23148. {
  23149. version(testStdDateTime)
  23150. {
  23151. auto range = NegInfInterval!Date(Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed), PopFirst.yes);
  23152. auto expected = range.front;
  23153. foreach(date; take(range, 79))
  23154. {
  23155. _assertPred!"=="(date, expected);
  23156. expected += dur!"days"(-7);
  23157. }
  23158. const cRange = NegInfInterval!Date(Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
  23159. static assert(!__traits(compiles, cRange.popFront()));
  23160. }
  23161. }
  23162. //Test NegInfIntervalRange's save.
  23163. unittest
  23164. {
  23165. version(testStdDateTime)
  23166. {
  23167. auto interval = NegInfInterval!Date(Date(2012, 1, 7));
  23168. auto func = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri);
  23169. auto range = interval.bwdRange(func);
  23170. assert(range.save == range);
  23171. }
  23172. }
  23173. //Test NegInfIntervalRange's interval.
  23174. unittest
  23175. {
  23176. version(testStdDateTime)
  23177. {
  23178. auto interval = NegInfInterval!Date(Date(2012, 1, 7));
  23179. auto func = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri);
  23180. auto range = interval.bwdRange(func);
  23181. assert(range.interval == interval);
  23182. const cRange = range;
  23183. static assert(__traits(compiles, cRange.interval));
  23184. }
  23185. }
  23186. //Test NegInfIntervalRange's func.
  23187. unittest
  23188. {
  23189. version(testStdDateTime)
  23190. {
  23191. auto interval = NegInfInterval!Date(Date(2012, 1, 7));
  23192. auto func = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri);
  23193. auto range = interval.bwdRange(func);
  23194. assert(range.func == func);
  23195. }
  23196. }
  23197. //==============================================================================
  23198. // Section with time zones.
  23199. //==============================================================================
  23200. /++
  23201. Represents a time zone. It is used with $(D SysTime) to indicate the time
  23202. zone of a $(D SysTime).
  23203. +/
  23204. abstract class TimeZone
  23205. {
  23206. public:
  23207. /++
  23208. The name of the time zone per the TZ Database. This is the name used to
  23209. get a $(D TimeZone) by name with $(D TimeZone.getTimeZone).
  23210. See_Also:
  23211. $(WEB en.wikipedia.org/wiki/Tz_database, Wikipedia entry on TZ
  23212. Database)
  23213. $(WEB en.wikipedia.org/wiki/List_of_tz_database_time_zones, List of
  23214. Time Zones)
  23215. +/
  23216. @property string name() const nothrow
  23217. {
  23218. return _name;
  23219. }
  23220. /++
  23221. Typically, the abbreviation (generally 3 or 4 letters) for the time zone
  23222. when DST is $(I not) in effect (e.g. PST). It is not necessarily unique.
  23223. However, on Windows, it may be the unabbreviated name (e.g. Pacific
  23224. Standard Time). Regardless, it is not the same as name.
  23225. +/
  23226. @property string stdName() const nothrow
  23227. {
  23228. return _stdName;
  23229. }
  23230. /++
  23231. Typically, the abbreviation (generally 3 or 4 letters) for the time zone
  23232. when DST $(I is) in effect (e.g. PDT). It is not necessarily unique.
  23233. However, on Windows, it may be the unabbreviated name (e.g. Pacific
  23234. Daylight Time). Regardless, it is not the same as name.
  23235. +/
  23236. @property string dstName() const nothrow
  23237. {
  23238. return _dstName;
  23239. }
  23240. /++
  23241. Whether this time zone has Daylight Savings Time at any point in time.
  23242. Note that for some time zone types it may not have DST for current dates
  23243. but will still return true for $(D hasDST) because the time zone did at
  23244. some point have DST.
  23245. +/
  23246. @property abstract bool hasDST() const nothrow;
  23247. /++
  23248. Takes the number of hnsecs (100 ns) since midnight, January 1st, 1 A.D.
  23249. in UTC time (i.e. std time) and returns whether DST is effect in this
  23250. time zone at the given point in time.
  23251. Params:
  23252. stdTime = The UTC time that needs to be checked for DST in this time
  23253. zone.
  23254. +/
  23255. abstract bool dstInEffect(long stdTime) const nothrow;
  23256. /++
  23257. Takes the number of hnsecs (100 ns) since midnight, January 1st, 1 A.D.
  23258. in UTC time (i.e. std time) and converts it to this time zone's time.
  23259. Params:
  23260. stdTime = The UTC time that needs to be adjusted to this time zone's
  23261. time.
  23262. +/
  23263. abstract long utcToTZ(long stdTime) const nothrow;
  23264. /++
  23265. Takes the number of hnsecs (100 ns) since midnight, January 1st, 1 A.D.
  23266. in this time zone's time and converts it to UTC (i.e. std time).
  23267. Params:
  23268. adjTime = The time in this time zone that needs to be adjusted to
  23269. UTC time.
  23270. +/
  23271. abstract long tzToUTC(long adjTime) const nothrow;
  23272. /++
  23273. Returns a $(D TimeZone) with the give name per the TZ Database.
  23274. This returns a $(D PosixTimeZone) on Posix systems and a
  23275. $(D WindowsTimeZone) on Windows systems. If you want a
  23276. $(D PosixTimeZone) on Windows, then call $(D PosixTimeZone.getTimeZone)
  23277. directly and give it the location of the TZ Database time zone files on
  23278. disk.
  23279. On Windows, the given TZ Database name is converted to the corresponding
  23280. time zone name on Windows prior to calling
  23281. $(D WindowsTimeZone.getTimeZone). So, this function allows you to use
  23282. the same time zone names on both Windows and Posix systems.
  23283. See_Also:
  23284. $(WEB en.wikipedia.org/wiki/Tz_database, Wikipedia entry on TZ
  23285. Database)
  23286. $(WEB en.wikipedia.org/wiki/List_of_tz_database_time_zones, List of
  23287. Time Zones)
  23288. $(WEB unicode.org/repos/cldr-tmp/trunk/diff/supplemental/zone_tzid.html,
  23289. Windows <-> TZ Database Name Conversion Table)
  23290. Params:
  23291. name = The TZ Database name of the time zone that you're looking for.
  23292. Throws:
  23293. $(D DateTimeException) if the given time zone could not be found.
  23294. Examples:
  23295. --------------------
  23296. auto tz = TimeZone.getTimeZone("America/Los_Angeles");
  23297. --------------------
  23298. +/
  23299. static immutable(TimeZone) getTimeZone(string name)
  23300. {
  23301. version(Posix)
  23302. return PosixTimeZone.getTimeZone(name);
  23303. else version(Windows)
  23304. return WindowsTimeZone.getTimeZone(tzDatabaseNameToWindowsTZName(name));
  23305. }
  23306. //Since reading in the time zone files could be expensive, most unit tests
  23307. //are consolidated into this one unittest block which minimizes how often it
  23308. //reads a time zone file.
  23309. version(testStdDateTime) unittest
  23310. {
  23311. version(Posix) scope(exit) clearTZEnvVar();
  23312. static void testTZ(string tzName,
  23313. string stdName,
  23314. string dstName,
  23315. int utcOffset,
  23316. int dstOffset,
  23317. bool north = true)
  23318. {
  23319. scope(failure) writefln("Failed time zone: %s", tzName);
  23320. immutable tz = TimeZone.getTimeZone(tzName);
  23321. immutable hasDST = dstOffset != 0;
  23322. version(Posix)
  23323. _assertPred!"=="(tz.name, tzName);
  23324. else version(Windows)
  23325. _assertPred!"=="(tz.name, stdName);
  23326. _assertPred!"=="(tz.stdName, stdName);
  23327. _assertPred!"=="(tz.dstName, dstName);
  23328. _assertPred!"=="(tz.hasDST, hasDST);
  23329. immutable stdDate = DateTime(2010, north ? 1 : 7, 1, 6, 0, 0);
  23330. immutable dstDate = DateTime(2010, north ? 7 : 1, 1, 6, 0, 0);
  23331. auto std = SysTime(stdDate, tz);
  23332. auto dst = SysTime(dstDate, tz);
  23333. auto stdUTC = SysTime(stdDate - dur!"minutes"(utcOffset), UTC());
  23334. auto dstUTC = SysTime(stdDate - dur!"minutes"(utcOffset + dstOffset), UTC());
  23335. assert(!std.dstInEffect);
  23336. _assertPred!"=="(dst.dstInEffect, hasDST);
  23337. _assertPred!"=="(cast(DateTime)std, stdDate);
  23338. _assertPred!"=="(cast(DateTime)dst, dstDate);
  23339. _assertPred!"=="(std, stdUTC);
  23340. version(Posix)
  23341. {
  23342. setTZEnvVar(tzName);
  23343. static void testTM(in SysTime st)
  23344. {
  23345. time_t unixTime = st.toUnixTime();
  23346. tm* osTimeInfo = localtime(&unixTime);
  23347. tm ourTimeInfo = st.toTM();
  23348. _assertPred!"=="(ourTimeInfo.tm_sec, osTimeInfo.tm_sec);
  23349. _assertPred!"=="(ourTimeInfo.tm_min, osTimeInfo.tm_min);
  23350. _assertPred!"=="(ourTimeInfo.tm_hour, osTimeInfo.tm_hour);
  23351. _assertPred!"=="(ourTimeInfo.tm_min, osTimeInfo.tm_min);
  23352. _assertPred!"=="(ourTimeInfo.tm_mday, osTimeInfo.tm_mday);
  23353. _assertPred!"=="(ourTimeInfo.tm_mon, osTimeInfo.tm_mon);
  23354. _assertPred!"=="(ourTimeInfo.tm_year, osTimeInfo.tm_year);
  23355. _assertPred!"=="(ourTimeInfo.tm_wday, osTimeInfo.tm_wday);
  23356. _assertPred!"=="(ourTimeInfo.tm_yday, osTimeInfo.tm_yday);
  23357. _assertPred!"=="(ourTimeInfo.tm_isdst, osTimeInfo.tm_isdst);
  23358. _assertPred!"=="(ourTimeInfo.tm_gmtoff, osTimeInfo.tm_gmtoff);
  23359. _assertPred!"=="(to!string(ourTimeInfo.tm_zone),
  23360. to!string(osTimeInfo.tm_zone));
  23361. }
  23362. testTM(std);
  23363. testTM(dst);
  23364. //Apparently, right/ does not exist on Mac OS X. I don't know
  23365. //whether or not it exists on FreeBSD. It's rather pointless
  23366. //normally, since the Posix standard requires that leap seconds
  23367. //be ignored, so it does make some sense that right/ wouldn't
  23368. //be there, but since PosixTimeZone _does_ use leap seconds if
  23369. //the time zone file does, we'll test that functionality if the
  23370. //appropriate files exist.
  23371. if((PosixTimeZone.defaultTZDatabaseDir ~ "right/" ~ tzName).exists())
  23372. {
  23373. auto leapTZ = PosixTimeZone.getTimeZone("right/" ~ tzName);
  23374. assert(leapTZ.name == "right/" ~ tzName);
  23375. assert(leapTZ.stdName == stdName);
  23376. assert(leapTZ.dstName == dstName);
  23377. assert(leapTZ.hasDST == hasDST);
  23378. auto leapSTD = SysTime(std.stdTime, leapTZ);
  23379. auto leapDST = SysTime(dst.stdTime, leapTZ);
  23380. assert(!leapSTD.dstInEffect);
  23381. assert(leapDST.dstInEffect == hasDST);
  23382. _assertPred!"=="(leapSTD.stdTime, std.stdTime);
  23383. _assertPred!"=="(leapDST.stdTime, dst.stdTime);
  23384. //Whenever a leap second is added/removed,
  23385. //this will have to be adjusted.
  23386. enum leapDiff = convert!("seconds", "hnsecs")(24);
  23387. _assertPred!"=="(leapSTD.adjTime - leapDiff, std.adjTime);
  23388. _assertPred!"=="(leapDST.adjTime - leapDiff, dst.adjTime);
  23389. }
  23390. }
  23391. }
  23392. version(Posix)
  23393. {
  23394. version(FreeBSD) enum utcZone = "Etc/UTC";
  23395. version(linux) enum utcZone = "UTC";
  23396. version(OSX) enum utcZone = "UTC";
  23397. testTZ("America/Los_Angeles", "PST", "PDT", -8 * 60, 60);
  23398. testTZ("America/New_York", "EST", "EDT", -5 * 60, 60);
  23399. testTZ(utcZone, "UTC", "UTC", 0, 0);
  23400. testTZ("Europe/Paris", "CET", "CEST", 60, 60);
  23401. testTZ("Australia/Adelaide", "CST", "CST", 9 * 60 + 30, 60, false);
  23402. assertThrown!DateTimeException(PosixTimeZone.getTimeZone("hello_world"));
  23403. }
  23404. version(Windows)
  23405. {
  23406. testTZ("America/Los_Angeles", "Pacific Standard Time",
  23407. "Pacific Daylight Time", -8 * 60, 60);
  23408. testTZ("America/New_York", "Eastern Standard Time",
  23409. "Eastern Daylight Time", -5 * 60, 60);
  23410. testTZ("Atlantic/Reykjavik", "Greenwich Standard Time",
  23411. "Greenwich Daylight Time", 0, 0);
  23412. testTZ("Europe/Paris", "Romance Standard Time",
  23413. "Romance Daylight Time", 60, 60);
  23414. testTZ("Australia/Adelaide", "Cen. Australia Standard Time",
  23415. "Cen. Australia Daylight Time", 9 * 60 + 30, 60, false);
  23416. assertThrown!DateTimeException(WindowsTimeZone.getTimeZone("hello_world"));
  23417. }
  23418. }
  23419. /++
  23420. Returns a list of the names of the time zones installed on the system.
  23421. You can provide a sub-name to narrow down the list of time zones (which
  23422. will likely be in the thousands if you get them all). For example,
  23423. if you pass in "America" as the sub-name, then only the time zones which
  23424. begin with "America" will be returned.
  23425. On Windows, this function will convert the Windows time zone names to
  23426. the corresponding TZ Database names with
  23427. $(D windowsTZNameToTZDatabaseName). If you want the actual Windows time
  23428. zone names, use $(D WindowsTimeZone.getInstalledTZNames) directly.
  23429. Params:
  23430. subName = The first part of the time zones that you want.
  23431. Throws:
  23432. $(D FileException) on Posix systems if it fails to read from disk.
  23433. $(D DateTimeException) on Windows systems if it fails to read the
  23434. registry.
  23435. +/
  23436. static string[] getInstalledTZNames(string subName = "")
  23437. {
  23438. version(Posix)
  23439. return PosixTimeZone.getInstalledTZNames(subName);
  23440. else version(Windows)
  23441. {
  23442. auto windowsNames = WindowsTimeZone.getInstalledTZNames();
  23443. auto retval = appender!(string[])();
  23444. foreach(winName; windowsNames)
  23445. {
  23446. auto tzName = windowsTZNameToTZDatabaseName(winName);
  23447. if(tzName.startsWith(subName))
  23448. retval.put(tzName);
  23449. }
  23450. sort(retval.data);
  23451. return retval.data;
  23452. }
  23453. }
  23454. unittest
  23455. {
  23456. version(testStdDateTime)
  23457. {
  23458. static void testPZSuccess(string tzName)
  23459. {
  23460. scope(failure) writefln("TZName which threw: %s", tzName);
  23461. TimeZone.getTimeZone(tzName);
  23462. }
  23463. auto tzNames = getInstalledTZNames();
  23464. foreach(tzName; tzNames)
  23465. assertNotThrown!DateTimeException(testPZSuccess(tzName));
  23466. }
  23467. }
  23468. private:
  23469. /+
  23470. Params:
  23471. name = The TZ Database name for the time zone.
  23472. stdName = The abbreviation for the time zone during std time.
  23473. dstName = The abbreviation for the time zone during DST.
  23474. +/
  23475. this(string name, string stdName, string dstName) immutable pure
  23476. {
  23477. _name = name;
  23478. _stdName = stdName;
  23479. _dstName = dstName;
  23480. }
  23481. immutable string _name;
  23482. immutable string _stdName;
  23483. immutable string _dstName;
  23484. }
  23485. /++
  23486. A TimeZone which represents the current local time zone on
  23487. the system running your program.
  23488. This uses the underlying C calls to adjust the time rather than using
  23489. specific D code based off of system settings to calculate the time such as
  23490. $(D PosixTimeZone) and $(D WindowsTimeZone) do. That also means that it will
  23491. use whatever the current time zone is on the system, even if the system's
  23492. time zone changes while the program is running.
  23493. +/
  23494. final class LocalTime : TimeZone
  23495. {
  23496. public:
  23497. /++
  23498. $(D LocalTime) is a singleton class. $(D LocalTime) returns its only
  23499. instance.
  23500. +/
  23501. static immutable(LocalTime) opCall() pure nothrow
  23502. {
  23503. return _localTime;
  23504. }
  23505. version(StdDdoc)
  23506. {
  23507. /++
  23508. The name of the time zone per the TZ Database. This is the name used to
  23509. get a $(D TimeZone) by name with $(D TimeZone.getTimeZone).
  23510. Note that this always returns the empty string. This is because time
  23511. zones cannot be uniquely identified by the attributes given by the
  23512. OS (such as the $(D stdName) and $(D dstName)), and neither Posix
  23513. systems nor Windows systems provide an easy way to get the TZ
  23514. Database name of the local time zone.
  23515. See_Also:
  23516. $(WEB en.wikipedia.org/wiki/Tz_database, Wikipedia entry on TZ
  23517. Database)
  23518. $(WEB en.wikipedia.org/wiki/List_of_tz_database_time_zones, List
  23519. of Time Zones)
  23520. +/
  23521. @property override string name() const nothrow;
  23522. }
  23523. /++
  23524. Typically, the abbreviation (generally 3 or 4 letters) for the time zone
  23525. when DST is $(I not) in effect (e.g. PST). It is not necessarily unique.
  23526. However, on Windows, it may be the unabbreviated name (e.g. Pacific
  23527. Standard Time). Regardless, it is not the same as name.
  23528. This property is overridden because the local time of the system could
  23529. change while the program is running and we need to determine it
  23530. dynamically rather than it being fixed like it would be with most time
  23531. zones.
  23532. +/
  23533. @property override string stdName() const nothrow
  23534. {
  23535. version(Posix)
  23536. {
  23537. try
  23538. return to!string(tzname[0]);
  23539. catch(Exception e)
  23540. assert(0, "to!string(tzname[0]) failed.");
  23541. }
  23542. else version(Windows)
  23543. {
  23544. try
  23545. {
  23546. TIME_ZONE_INFORMATION tzInfo;
  23547. GetTimeZoneInformation(&tzInfo);
  23548. //Cannot use to!string() like this should, probably due to bug http://d.puremagic.com/issues/show_bug.cgi?id=5016
  23549. //return to!string(tzInfo.StandardName);
  23550. wchar[32] str;
  23551. foreach(i, ref wchar c; str)
  23552. c = tzInfo.StandardName[i];
  23553. string retval;
  23554. foreach(dchar c; str)
  23555. {
  23556. if(c == '\0')
  23557. break;
  23558. retval ~= c;
  23559. }
  23560. return retval;
  23561. }
  23562. catch(Exception e)
  23563. assert(0, "GetTimeZoneInformation() threw.");
  23564. }
  23565. }
  23566. unittest
  23567. {
  23568. version(testStdDateTime)
  23569. {
  23570. assert(LocalTime().stdName !is null);
  23571. version(Posix)
  23572. {
  23573. scope(exit) clearTZEnvVar();
  23574. setTZEnvVar("America/Los_Angeles");
  23575. _assertPred!"=="(LocalTime().stdName, "PST");
  23576. setTZEnvVar("America/New_York");
  23577. _assertPred!"=="(LocalTime().stdName, "EST");
  23578. }
  23579. }
  23580. }
  23581. /++
  23582. Typically, the abbreviation (generally 3 or 4 letters) for the time zone
  23583. when DST $(I is) in effect (e.g. PDT). It is not necessarily unique.
  23584. However, on Windows, it may be the unabbreviated name (e.g. Pacific
  23585. Daylight Time). Regardless, it is not the same as name.
  23586. This property is overridden because the local time of the system could
  23587. change while the program is running and we need to determine it
  23588. dynamically rather than it being fixed like it would be with most time
  23589. zones.
  23590. +/
  23591. @property override string dstName() const nothrow
  23592. {
  23593. version(Posix)
  23594. {
  23595. try
  23596. return to!string(tzname[1]);
  23597. catch(Exception e)
  23598. assert(0, "to!string(tzname[1]) failed.");
  23599. }
  23600. else version(Windows)
  23601. {
  23602. try
  23603. {
  23604. TIME_ZONE_INFORMATION tzInfo;
  23605. GetTimeZoneInformation(&tzInfo);
  23606. //Cannot use to!string() like this should, probably due to bug http://d.puremagic.com/issues/show_bug.cgi?id=5016
  23607. //return to!string(tzInfo.DaylightName);
  23608. wchar[32] str;
  23609. foreach(i, ref wchar c; str)
  23610. c = tzInfo.DaylightName[i];
  23611. string retval;
  23612. foreach(dchar c; str)
  23613. {
  23614. if(c == '\0')
  23615. break;
  23616. retval ~= c;
  23617. }
  23618. return retval;
  23619. }
  23620. catch(Exception e)
  23621. assert(0, "GetTimeZoneInformation() threw.");
  23622. }
  23623. }
  23624. unittest
  23625. {
  23626. version(testStdDateTime)
  23627. {
  23628. assert(LocalTime().dstName !is null);
  23629. version(Posix)
  23630. {
  23631. scope(exit) clearTZEnvVar();
  23632. setTZEnvVar("America/Los_Angeles");
  23633. _assertPred!"=="(LocalTime().dstName, "PDT");
  23634. setTZEnvVar("America/New_York");
  23635. _assertPred!"=="(LocalTime().dstName, "EDT");
  23636. }
  23637. }
  23638. }
  23639. /++
  23640. Whether this time zone has Daylight Savings Time at any point in time.
  23641. Note that for some time zone types it may not have DST for current
  23642. dates but will still return true for $(D hasDST) because the time zone
  23643. did at some point have DST.
  23644. +/
  23645. @property override bool hasDST() const nothrow
  23646. {
  23647. version(Posix)
  23648. {
  23649. static if(is(typeof(daylight)))
  23650. return cast(bool)(daylight);
  23651. else
  23652. {
  23653. try
  23654. {
  23655. auto currYear = (cast(Date)Clock.currTime()).year;
  23656. auto janOffset = SysTime(Date(currYear, 1, 4), this).stdTime -
  23657. SysTime(Date(currYear, 1, 4), UTC()).stdTime;
  23658. auto julyOffset = SysTime(Date(currYear, 7, 4), this).stdTime -
  23659. SysTime(Date(currYear, 7, 4), UTC()).stdTime;
  23660. return janOffset != julyOffset;
  23661. }
  23662. catch(Exception e)
  23663. assert(0, "Clock.currTime() threw.");
  23664. }
  23665. }
  23666. else version(Windows)
  23667. {
  23668. try
  23669. {
  23670. TIME_ZONE_INFORMATION tzInfo;
  23671. GetTimeZoneInformation(&tzInfo);
  23672. return tzInfo.DaylightDate.wMonth != 0;
  23673. }
  23674. catch(Exception e)
  23675. assert(0, "GetTimeZoneInformation() threw.");
  23676. }
  23677. }
  23678. unittest
  23679. {
  23680. version(testStdDateTime)
  23681. {
  23682. LocalTime().hasDST;
  23683. version(Posix)
  23684. {
  23685. scope(exit) clearTZEnvVar();
  23686. setTZEnvVar("America/Los_Angeles");
  23687. assert(LocalTime().hasDST);
  23688. setTZEnvVar("America/New_York");
  23689. assert(LocalTime().hasDST);
  23690. setTZEnvVar("UTC");
  23691. assert(!LocalTime().hasDST);
  23692. }
  23693. }
  23694. }
  23695. /++
  23696. Takes the number of hnsecs (100 ns) since midnight, January 1st, 1 A.D.
  23697. in UTC time (i.e. std time) and returns whether DST is in effect in this
  23698. time zone at the given point in time.
  23699. Params:
  23700. stdTime = The UTC time that needs to be checked for DST in this time
  23701. zone.
  23702. +/
  23703. override bool dstInEffect(long stdTime) const nothrow
  23704. {
  23705. time_t unixTime = stdTimeToUnixTime(stdTime);
  23706. version(Posix)
  23707. {
  23708. tm* timeInfo = localtime(&unixTime);
  23709. return cast(bool)(timeInfo.tm_isdst);
  23710. }
  23711. else version(Windows)
  23712. {
  23713. //Apparently Windows isn't smart enough to deal with negative time_t.
  23714. if(unixTime >= 0)
  23715. {
  23716. tm* timeInfo = localtime(&unixTime);
  23717. if(timeInfo)
  23718. return cast(bool)(timeInfo.tm_isdst);
  23719. }
  23720. TIME_ZONE_INFORMATION tzInfo;
  23721. try
  23722. GetTimeZoneInformation(&tzInfo);
  23723. catch(Exception e)
  23724. assert(0, "The impossible happened. GetTimeZoneInformation() threw.");
  23725. return WindowsTimeZone._dstInEffect(&tzInfo, stdTime);
  23726. }
  23727. }
  23728. unittest
  23729. {
  23730. version(testStdDateTime)
  23731. {
  23732. auto currTime = Clock.currStdTime;
  23733. LocalTime().dstInEffect(currTime);
  23734. version(Posix)
  23735. {
  23736. scope(exit) clearTZEnvVar();
  23737. auto std = SysTime(DateTime(2010, 1, 1, 12, 0, 0), LocalTime());
  23738. auto dst = SysTime(DateTime(2010, 7, 1, 12, 0, 0), LocalTime());
  23739. setTZEnvVar("America/Los_Angeles");
  23740. assert(!LocalTime().dstInEffect(std.stdTime));
  23741. assert(LocalTime().dstInEffect(dst.stdTime));
  23742. assert(!std.dstInEffect);
  23743. assert(dst.dstInEffect);
  23744. setTZEnvVar("America/New_York");
  23745. assert(!LocalTime().dstInEffect(std.stdTime));
  23746. assert(LocalTime().dstInEffect(dst.stdTime));
  23747. assert(!std.dstInEffect);
  23748. assert(dst.dstInEffect);
  23749. }
  23750. }
  23751. }
  23752. /++
  23753. Returns hnsecs in the local time zone using the standard C function
  23754. calls on Posix systems and the standard Windows system calls on Windows
  23755. systems to adjust the time to the appropriate time zone from std time.
  23756. Params:
  23757. stdTime = The UTC time that needs to be adjusted to this time zone's
  23758. time.
  23759. See_Also:
  23760. $(D TimeZone.utcToTZ)
  23761. +/
  23762. override long utcToTZ(long stdTime) const nothrow
  23763. {
  23764. version(Posix)
  23765. {
  23766. time_t unixTime = stdTimeToUnixTime(stdTime);
  23767. tm* timeInfo = localtime(&unixTime);
  23768. return stdTime + convert!("seconds", "hnsecs")(timeInfo.tm_gmtoff);
  23769. }
  23770. else version(Windows)
  23771. {
  23772. TIME_ZONE_INFORMATION tzInfo;
  23773. try
  23774. GetTimeZoneInformation(&tzInfo);
  23775. catch(Exception e)
  23776. assert(0, "GetTimeZoneInformation() threw.");
  23777. return WindowsTimeZone._utcToTZ(&tzInfo, stdTime, hasDST);
  23778. }
  23779. }
  23780. unittest
  23781. {
  23782. version(testStdDateTime)
  23783. {
  23784. LocalTime().utcToTZ(0);
  23785. version(Posix)
  23786. {
  23787. scope(exit) clearTZEnvVar();
  23788. {
  23789. setTZEnvVar("America/Los_Angeles");
  23790. auto std = SysTime(Date(2010, 1, 1));
  23791. auto dst = SysTime(Date(2010, 7, 1));
  23792. _assertPred!"=="(LocalTime().utcToTZ(std.stdTime), SysTime(DateTime(2009, 12, 31, 16, 0, 0)).stdTime);
  23793. _assertPred!"=="(LocalTime().utcToTZ(dst.stdTime), SysTime(DateTime(2010, 6, 30, 17, 0, 0)).stdTime);
  23794. }
  23795. {
  23796. setTZEnvVar("America/New_York");
  23797. auto std = SysTime(Date(2010, 1, 1));
  23798. auto dst = SysTime(Date(2010, 7, 1));
  23799. _assertPred!"=="(LocalTime().utcToTZ(std.stdTime), SysTime(DateTime(2009, 12, 31, 19, 0, 0)).stdTime);
  23800. _assertPred!"=="(LocalTime().utcToTZ(dst.stdTime), SysTime(DateTime(2010, 6, 30, 20, 0, 0)).stdTime);
  23801. }
  23802. }
  23803. }
  23804. }
  23805. /++
  23806. Returns std time using the standard C function calls on Posix systems
  23807. and the standard Windows system calls on Windows systems to adjust the
  23808. time to UTC from the appropriate time zone.
  23809. See_Also:
  23810. $(D TimeZone.tzToUTC)
  23811. Params:
  23812. adjTime = The time in this time zone that needs to be adjusted to
  23813. UTC time.
  23814. +/
  23815. override long tzToUTC(long adjTime) const nothrow
  23816. {
  23817. version(Posix)
  23818. {
  23819. time_t unixTime = stdTimeToUnixTime(adjTime);
  23820. tm* timeInfo = localtime(&unixTime);
  23821. return adjTime - convert!("seconds", "hnsecs")(timeInfo.tm_gmtoff);
  23822. }
  23823. else version(Windows)
  23824. {
  23825. TIME_ZONE_INFORMATION tzInfo;
  23826. try
  23827. GetTimeZoneInformation(&tzInfo);
  23828. catch(Exception e)
  23829. assert(0, "GetTimeZoneInformation() threw.");
  23830. return WindowsTimeZone._tzToUTC(&tzInfo, adjTime, hasDST);
  23831. }
  23832. }
  23833. unittest
  23834. {
  23835. version(testStdDateTime)
  23836. {
  23837. LocalTime().tzToUTC(0);
  23838. _assertPred!"=="(LocalTime().tzToUTC(LocalTime().utcToTZ(0)), 0);
  23839. _assertPred!"=="(LocalTime().utcToTZ(LocalTime().tzToUTC(0)), 0);
  23840. version(Posix)
  23841. {
  23842. scope(exit) clearTZEnvVar();
  23843. {
  23844. setTZEnvVar("America/Los_Angeles");
  23845. auto std = SysTime(DateTime(2009, 12, 31, 16, 0, 0));
  23846. auto dst = SysTime(DateTime(2010, 6, 30, 17, 0, 0));
  23847. _assertPred!"=="(LocalTime().tzToUTC(std.stdTime), SysTime(Date(2010, 1, 1)).stdTime);
  23848. _assertPred!"=="(LocalTime().tzToUTC(dst.stdTime), SysTime(Date(2010, 7, 1)).stdTime);
  23849. }
  23850. {
  23851. setTZEnvVar("America/New_York");
  23852. auto std = SysTime(DateTime(2009, 12, 31, 19, 0, 0));
  23853. auto dst = SysTime(DateTime(2010, 6, 30, 20, 0, 0));
  23854. _assertPred!"=="(LocalTime().tzToUTC(std.stdTime), SysTime(Date(2010, 1, 1)).stdTime);
  23855. _assertPred!"=="(LocalTime().tzToUTC(dst.stdTime), SysTime(Date(2010, 7, 1)).stdTime);
  23856. }
  23857. }
  23858. }
  23859. }
  23860. private:
  23861. this() immutable pure
  23862. {
  23863. super("", "", "");
  23864. }
  23865. static immutable LocalTime _localTime;
  23866. shared static this()
  23867. {
  23868. tzset();
  23869. _localTime = new immutable(LocalTime)();
  23870. }
  23871. }
  23872. /++
  23873. A $(D TimeZone) which represents UTC.
  23874. +/
  23875. final class UTC : TimeZone
  23876. {
  23877. public:
  23878. /++
  23879. $(D UTC) is a singleton class. $(D UTC) returns its only instance.
  23880. +/
  23881. static immutable(UTC) opCall() pure nothrow
  23882. {
  23883. return _utc;
  23884. }
  23885. /++
  23886. Always returns false.
  23887. +/
  23888. @property override bool hasDST() const nothrow
  23889. {
  23890. return false;
  23891. }
  23892. /++
  23893. Always returns false.
  23894. +/
  23895. override bool dstInEffect(long stdTime) const nothrow
  23896. {
  23897. return false;
  23898. }
  23899. /++
  23900. Returns the given hnsecs without changing them at all.
  23901. Params:
  23902. stdTime = The UTC time that needs to be adjusted to this time zone's
  23903. time.
  23904. See_Also:
  23905. $(D TimeZone.utcToTZ)
  23906. +/
  23907. override long utcToTZ(long stdTime) const nothrow
  23908. {
  23909. return stdTime;
  23910. }
  23911. unittest
  23912. {
  23913. version(testStdDateTime)
  23914. {
  23915. _assertPred!"=="(UTC().utcToTZ(0), 0);
  23916. version(Posix)
  23917. {
  23918. scope(exit) clearTZEnvVar();
  23919. setTZEnvVar("UTC");
  23920. auto std = SysTime(Date(2010, 1, 1));
  23921. auto dst = SysTime(Date(2010, 7, 1));
  23922. _assertPred!"=="(UTC().utcToTZ(std.stdTime), std.stdTime);
  23923. _assertPred!"=="(UTC().utcToTZ(dst.stdTime), dst.stdTime);
  23924. }
  23925. }
  23926. }
  23927. /++
  23928. Returns the given hnsecs without changing them at all.
  23929. See_Also:
  23930. $(D TimeZone.tzToUTC)
  23931. Params:
  23932. adjTime = The time in this time zone that needs to be adjusted to
  23933. UTC time.
  23934. +/
  23935. override long tzToUTC(long adjTime) const nothrow
  23936. {
  23937. return adjTime;
  23938. }
  23939. unittest
  23940. {
  23941. version(testStdDateTime)
  23942. {
  23943. _assertPred!"=="(UTC().tzToUTC(0), 0);
  23944. version(Posix)
  23945. {
  23946. scope(exit) clearTZEnvVar();
  23947. setTZEnvVar("UTC");
  23948. auto std = SysTime(Date(2010, 1, 1));
  23949. auto dst = SysTime(Date(2010, 7, 1));
  23950. _assertPred!"=="(UTC().tzToUTC(std.stdTime), std.stdTime);
  23951. _assertPred!"=="(UTC().tzToUTC(dst.stdTime), dst.stdTime);
  23952. }
  23953. }
  23954. }
  23955. private:
  23956. this() immutable pure
  23957. {
  23958. super("UTC", "UTC", "UTC");
  23959. }
  23960. static immutable UTC _utc;
  23961. shared static this()
  23962. {
  23963. _utc = new immutable(UTC)();
  23964. }
  23965. }
  23966. /++
  23967. Represents a time zone with an offset (in minutes, west is negative) from
  23968. UTC but no DST.
  23969. It's primarily used as the time zone in the result of $(D SysTime)'s
  23970. $(D fromISOString), $(D fromISOExtString), and $(D fromSimpleString).
  23971. $(D name) and $(D dstName) are always the empty string since this time zone
  23972. has no DST, and while it may be meant to represent a time zone which is in
  23973. the TZ Database, obviously it's not likely to be following the exact rules
  23974. of any of the time zones in the TZ Database, so it makes no sense to set it.
  23975. +/
  23976. final class SimpleTimeZone : TimeZone
  23977. {
  23978. public:
  23979. /++
  23980. Always returns false.
  23981. +/
  23982. @property override bool hasDST() const nothrow
  23983. {
  23984. return false;
  23985. }
  23986. /++
  23987. Always returns false.
  23988. +/
  23989. override bool dstInEffect(long stdTime) const nothrow
  23990. {
  23991. return false;
  23992. }
  23993. /++
  23994. Takes the number of hnsecs (100 ns) since midnight, January 1st, 1 A.D.
  23995. in UTC time (i.e. std time) and converts it to this time zone's time.
  23996. Params:
  23997. stdTime = The UTC time that needs to be adjusted to this time zone's
  23998. time.
  23999. +/
  24000. override long utcToTZ(long stdTime) const nothrow
  24001. {
  24002. return stdTime + convert!("minutes", "hnsecs")(utcOffset);
  24003. }
  24004. unittest
  24005. {
  24006. version(testStdDateTime)
  24007. {
  24008. _assertPred!"=="((new SimpleTimeZone(-8 * 60)).utcToTZ(0), -288_000_000_000L);
  24009. _assertPred!"=="((new SimpleTimeZone(8 * 60)).utcToTZ(0), 288_000_000_000L);
  24010. _assertPred!"=="((new SimpleTimeZone(-8 * 60)).utcToTZ(54_321_234_567_890L), 54_033_234_567_890L);
  24011. auto stz = new SimpleTimeZone(-8 * 60);
  24012. const cstz = new SimpleTimeZone(-8 * 60);
  24013. static assert(__traits(compiles, stz.utcToTZ(50002)));
  24014. static assert(__traits(compiles, cstz.utcToTZ(50002)));
  24015. }
  24016. }
  24017. /++
  24018. Takes the number of hnsecs (100 ns) since midnight, January 1st, 1 A.D.
  24019. in this time zone's time and converts it to UTC (i.e. std time).
  24020. Params:
  24021. adjTime = The time in this time zone that needs to be adjusted to
  24022. UTC time.
  24023. +/
  24024. override long tzToUTC(long adjTime) const nothrow
  24025. {
  24026. return adjTime - convert!("minutes", "hnsecs")(utcOffset);
  24027. }
  24028. unittest
  24029. {
  24030. version(testStdDateTime)
  24031. {
  24032. _assertPred!"=="((new SimpleTimeZone(-8 * 60)).tzToUTC(-288_000_000_000L), 0);
  24033. _assertPred!"=="((new SimpleTimeZone(8 * 60)).tzToUTC(288_000_000_000L), 0);
  24034. _assertPred!"=="((new SimpleTimeZone(-8 * 60)).tzToUTC(54_033_234_567_890L), 54_321_234_567_890L);
  24035. auto stz = new SimpleTimeZone(-8 * 60);
  24036. const cstz = new SimpleTimeZone(-8 * 60);
  24037. static assert(__traits(compiles, stz.tzToUTC(20005)));
  24038. static assert(__traits(compiles, cstz.tzToUTC(20005)));
  24039. }
  24040. }
  24041. /++
  24042. Params:
  24043. utcOffset = This time zone's offset from UTC in minutes with west of
  24044. UTC being negative (it is added to UTC to get the
  24045. adjusted time).
  24046. stdName = The $(D stdName) for this time zone.
  24047. +/
  24048. this(int utcOffset, string stdName = "") immutable
  24049. {
  24050. //FIXME This probably needs to be changed to something like (-12 - 13).
  24051. enforce(std.math.abs(utcOffset) < 1440, new DateTimeException("Offset from UTC must be within range (-24:00 - 24:00)."));
  24052. super("", stdName, "");
  24053. this.utcOffset = utcOffset;
  24054. }
  24055. unittest
  24056. {
  24057. version(testStdDateTime)
  24058. {
  24059. auto stz = new SimpleTimeZone(-8 * 60, "PST");
  24060. _assertPred!"=="(stz.name, "");
  24061. _assertPred!"=="(stz.stdName, "PST");
  24062. _assertPred!"=="(stz.dstName, "");
  24063. _assertPred!"=="(stz.utcOffset, -8 * 60);
  24064. }
  24065. }
  24066. /++
  24067. The number of minutes the offset from UTC is (negative is west of UTC,
  24068. positive is east).
  24069. +/
  24070. immutable int utcOffset;
  24071. private:
  24072. /+
  24073. Returns a time zone as a string with an offset from UTC.
  24074. Time zone offsets will be in the form +HH:MM or -HH:MM.
  24075. Params:
  24076. utcOffset = The number of minutes offset from UTC (negative means
  24077. west).
  24078. +/
  24079. static string toISOString(int utcOffset)
  24080. {
  24081. immutable absOffset = std.math.abs(utcOffset);
  24082. enforce(absOffset < 1440, new DateTimeException("Offset from UTC must be within range (-24:00 - 24:00)."));
  24083. immutable hours = convert!("minutes", "hours")(absOffset);
  24084. immutable minutes = absOffset - convert!("hours", "minutes")(hours);
  24085. if(utcOffset < 0)
  24086. return format("-%02d:%02d", hours, minutes);
  24087. return format("+%02d:%02d", hours, minutes);
  24088. }
  24089. unittest
  24090. {
  24091. version(testStdDateTime)
  24092. {
  24093. static string testSTZInvalid(int offset)
  24094. {
  24095. return SimpleTimeZone.toISOString(offset);
  24096. }
  24097. assertThrown!DateTimeException(testSTZInvalid(1440));
  24098. assertThrown!DateTimeException(testSTZInvalid(-1440));
  24099. _assertPred!"=="(toISOString(0), "+00:00");
  24100. _assertPred!"=="(toISOString(1), "+00:01");
  24101. _assertPred!"=="(toISOString(10), "+00:10");
  24102. _assertPred!"=="(toISOString(59), "+00:59");
  24103. _assertPred!"=="(toISOString(60), "+01:00");
  24104. _assertPred!"=="(toISOString(90), "+01:30");
  24105. _assertPred!"=="(toISOString(120), "+02:00");
  24106. _assertPred!"=="(toISOString(480), "+08:00");
  24107. _assertPred!"=="(toISOString(1439), "+23:59");
  24108. _assertPred!"=="(toISOString(-1), "-00:01");
  24109. _assertPred!"=="(toISOString(-10), "-00:10");
  24110. _assertPred!"=="(toISOString(-59), "-00:59");
  24111. _assertPred!"=="(toISOString(-60), "-01:00");
  24112. _assertPred!"=="(toISOString(-90), "-01:30");
  24113. _assertPred!"=="(toISOString(-120), "-02:00");
  24114. _assertPred!"=="(toISOString(-480), "-08:00");
  24115. _assertPred!"=="(toISOString(-1439), "-23:59");
  24116. }
  24117. }
  24118. /+
  24119. Takes a time zone as a string with an offset from UTC and returns a
  24120. $(D SimpleTimeZone) which matches.
  24121. The accepted formats for time zone offsets
  24122. are +H, -H, +HH, -HH, +H:MM, -H:MM, +HH:MM, and -HH:MM.
  24123. Params:
  24124. isoString = A string which represents a time zone in the ISO format.
  24125. +/
  24126. static immutable(SimpleTimeZone) fromISOString(S)(S isoString)
  24127. if(isSomeString!(S))
  24128. {
  24129. auto dstr = to!dstring(strip(isoString));
  24130. enforce(dstr.startsWith("-") || dstr.startsWith("+"), new DateTimeException("Invalid ISO String"));
  24131. auto sign = dstr.startsWith("-") ? -1 : 1;
  24132. dstr.popFront();
  24133. enforce(!dstr.empty, new DateTimeException("Invalid ISO String"));
  24134. immutable colon = dstr.stds_indexOf(":");
  24135. dstring hoursStr;
  24136. dstring minutesStr;
  24137. if(colon != -1)
  24138. {
  24139. hoursStr = dstr[0 .. colon];
  24140. minutesStr = dstr[colon + 1 .. $];
  24141. enforce(minutesStr.length == 2, new DateTimeException(format("Invalid ISO String: %s", dstr)));
  24142. }
  24143. else
  24144. hoursStr = dstr;
  24145. enforce(!canFind!(not!isDigit)(hoursStr), new DateTimeException(format("Invalid ISO String: %s", dstr)));
  24146. enforce(!canFind!(not!isDigit)(minutesStr), new DateTimeException(format("Invalid ISO String: %s", dstr)));
  24147. immutable hours = to!int(hoursStr);
  24148. immutable minutes = minutesStr.empty ? 0 : to!int(minutesStr);
  24149. return new SimpleTimeZone(sign * cast(int)(convert!("hours", "minutes")(hours) + minutes));
  24150. }
  24151. unittest
  24152. {
  24153. version(testStdDateTime)
  24154. {
  24155. assertThrown!DateTimeException(SimpleTimeZone.fromISOString(""));
  24156. assertThrown!DateTimeException(SimpleTimeZone.fromISOString("Z"));
  24157. assertThrown!DateTimeException(SimpleTimeZone.fromISOString("-"));
  24158. assertThrown!DateTimeException(SimpleTimeZone.fromISOString("+"));
  24159. assertThrown!DateTimeException(SimpleTimeZone.fromISOString("-:"));
  24160. assertThrown!DateTimeException(SimpleTimeZone.fromISOString("+:"));
  24161. assertThrown!DateTimeException(SimpleTimeZone.fromISOString("-1:"));
  24162. assertThrown!DateTimeException(SimpleTimeZone.fromISOString("+1:"));
  24163. assertThrown!DateTimeException(SimpleTimeZone.fromISOString("1"));
  24164. assertThrown!DateTimeException(SimpleTimeZone.fromISOString("-24:00"));
  24165. assertThrown!DateTimeException(SimpleTimeZone.fromISOString("+24:00"));
  24166. assertThrown!DateTimeException(SimpleTimeZone.fromISOString("+1:0"));
  24167. _assertPred!"=="(SimpleTimeZone.fromISOString("+00:00").utcOffset, (new SimpleTimeZone(0)).utcOffset);
  24168. _assertPred!"=="(SimpleTimeZone.fromISOString("+00:01").utcOffset, (new SimpleTimeZone(1)).utcOffset);
  24169. _assertPred!"=="(SimpleTimeZone.fromISOString("+00:10").utcOffset, (new SimpleTimeZone(10)).utcOffset);
  24170. _assertPred!"=="(SimpleTimeZone.fromISOString("+00:59").utcOffset, (new SimpleTimeZone(59)).utcOffset);
  24171. _assertPred!"=="(SimpleTimeZone.fromISOString("+01:00").utcOffset, (new SimpleTimeZone(60)).utcOffset);
  24172. _assertPred!"=="(SimpleTimeZone.fromISOString("+01:30").utcOffset, (new SimpleTimeZone(90)).utcOffset);
  24173. _assertPred!"=="(SimpleTimeZone.fromISOString("+02:00").utcOffset, (new SimpleTimeZone(120)).utcOffset);
  24174. _assertPred!"=="(SimpleTimeZone.fromISOString("+08:00").utcOffset, (new SimpleTimeZone(480)).utcOffset);
  24175. _assertPred!"=="(SimpleTimeZone.fromISOString("+23:59").utcOffset, (new SimpleTimeZone(1439)).utcOffset);
  24176. _assertPred!"=="(SimpleTimeZone.fromISOString("-00:01").utcOffset, (new SimpleTimeZone(-1)).utcOffset);
  24177. _assertPred!"=="(SimpleTimeZone.fromISOString("-00:10").utcOffset, (new SimpleTimeZone(-10)).utcOffset);
  24178. _assertPred!"=="(SimpleTimeZone.fromISOString("-00:59").utcOffset, (new SimpleTimeZone(-59)).utcOffset);
  24179. _assertPred!"=="(SimpleTimeZone.fromISOString("-01:00").utcOffset, (new SimpleTimeZone(-60)).utcOffset);
  24180. _assertPred!"=="(SimpleTimeZone.fromISOString("-01:30").utcOffset, (new SimpleTimeZone(-90)).utcOffset);
  24181. _assertPred!"=="(SimpleTimeZone.fromISOString("-02:00").utcOffset, (new SimpleTimeZone(-120)).utcOffset);
  24182. _assertPred!"=="(SimpleTimeZone.fromISOString("-08:00").utcOffset, (new SimpleTimeZone(-480)).utcOffset);
  24183. _assertPred!"=="(SimpleTimeZone.fromISOString("-23:59").utcOffset, (new SimpleTimeZone(-1439)).utcOffset);
  24184. _assertPred!"=="(SimpleTimeZone.fromISOString("+0").utcOffset, (new SimpleTimeZone(0)).utcOffset);
  24185. _assertPred!"=="(SimpleTimeZone.fromISOString("+1").utcOffset, (new SimpleTimeZone(60)).utcOffset);
  24186. _assertPred!"=="(SimpleTimeZone.fromISOString("+2").utcOffset, (new SimpleTimeZone(120)).utcOffset);
  24187. _assertPred!"=="(SimpleTimeZone.fromISOString("+23").utcOffset, (new SimpleTimeZone(1380)).utcOffset);
  24188. _assertPred!"=="(SimpleTimeZone.fromISOString("+2").utcOffset, (new SimpleTimeZone(120)).utcOffset);
  24189. _assertPred!"=="(SimpleTimeZone.fromISOString("+0").utcOffset, (new SimpleTimeZone(0)).utcOffset);
  24190. _assertPred!"=="(SimpleTimeZone.fromISOString("+1").utcOffset, (new SimpleTimeZone(60)).utcOffset);
  24191. _assertPred!"=="(SimpleTimeZone.fromISOString("+2").utcOffset, (new SimpleTimeZone(120)).utcOffset);
  24192. _assertPred!"=="(SimpleTimeZone.fromISOString("+23").utcOffset, (new SimpleTimeZone(1380)).utcOffset);
  24193. _assertPred!"=="(SimpleTimeZone.fromISOString("+1:00").utcOffset, (new SimpleTimeZone(60)).utcOffset);
  24194. _assertPred!"=="(SimpleTimeZone.fromISOString("+1:01").utcOffset, (new SimpleTimeZone(61)).utcOffset);
  24195. _assertPred!"=="(SimpleTimeZone.fromISOString("-0").utcOffset, (new SimpleTimeZone(0)).utcOffset);
  24196. _assertPred!"=="(SimpleTimeZone.fromISOString("-1").utcOffset, (new SimpleTimeZone(-60)).utcOffset);
  24197. _assertPred!"=="(SimpleTimeZone.fromISOString("-2").utcOffset, (new SimpleTimeZone(-120)).utcOffset);
  24198. _assertPred!"=="(SimpleTimeZone.fromISOString("-23").utcOffset, (new SimpleTimeZone(-1380)).utcOffset);
  24199. _assertPred!"=="(SimpleTimeZone.fromISOString("-1:00").utcOffset, (new SimpleTimeZone(-60)).utcOffset);
  24200. _assertPred!"=="(SimpleTimeZone.fromISOString("-1:01").utcOffset, (new SimpleTimeZone(-61)).utcOffset);
  24201. }
  24202. }
  24203. //Test that converting from an ISO string to a SimpleTimeZone to an ISO String works properly.
  24204. unittest
  24205. {
  24206. version(testStdDateTime)
  24207. {
  24208. static void testSTZ(in string isoString, int expectedOffset, size_t line = __LINE__)
  24209. {
  24210. auto stz = SimpleTimeZone.fromISOString(isoString);
  24211. _assertPred!"=="(stz.utcOffset, expectedOffset, "", __FILE__, line);
  24212. auto result = SimpleTimeZone.toISOString(stz.utcOffset);
  24213. _assertPred!"=="(result, isoString, "", __FILE__, line);
  24214. }
  24215. testSTZ("+00:00", 0);
  24216. testSTZ("+00:01", 1);
  24217. testSTZ("+00:10", 10);
  24218. testSTZ("+00:59", 59);
  24219. testSTZ("+01:00", 60);
  24220. testSTZ("+01:30", 90);
  24221. testSTZ("+02:00", 120);
  24222. testSTZ("+08:00", 480);
  24223. testSTZ("+08:00", 480);
  24224. testSTZ("+23:59", 1439);
  24225. testSTZ("-00:01", -1);
  24226. testSTZ("-00:10", -10);
  24227. testSTZ("-00:59", -59);
  24228. testSTZ("-01:00", -60);
  24229. testSTZ("-01:30", -90);
  24230. testSTZ("-02:00", -120);
  24231. testSTZ("-08:00", -480);
  24232. testSTZ("-08:00", -480);
  24233. testSTZ("-23:59", -1439);
  24234. }
  24235. }
  24236. }
  24237. /++
  24238. Represents a time zone from a TZ Database time zone file. Files from the TZ
  24239. database are how Posix systems hold their time zone information.
  24240. Unfortunately, Windows does not use the TZ Database. You can, however, use
  24241. $(D PosixTimeZone) (which reads its information from the TZ Database files
  24242. on disk) on Windows if you provide the TZ Database files
  24243. ( $(WEB elsie.nci.nih.gov/pub/, Repository with the TZ Database files (tzdata)) )
  24244. yourself and tell $(D PosixTimeZone.getTimeZone) where the directory holding
  24245. them is.
  24246. To get a $(D PosixTimeZone), either call $(D PosixTimeZone.getTimeZone)
  24247. (which will allow you to specify the location the time zone files) or call
  24248. $(D TimeZone.getTimeZone) (which will give you a $(D PosixTimeZone) on Posix
  24249. systems and a $(D WindowsTimeZone) on Windows systems).
  24250. Note:
  24251. Unless your system's local time zone deals with leap seconds (which is
  24252. highly unlikely), then only way that you will get a time zone which
  24253. takes leap seconds into account is if you use $(D PosixTimeZone) with a
  24254. time zone whose name starts with "right/". Those time zone files do
  24255. include leap seconds, and $(D PosixTimeZone) will take them into account
  24256. (though posix systems which use a "right/" time zone as their local time
  24257. zone will $(I not) take leap seconds into account even though they're
  24258. in the file).
  24259. See_Also:
  24260. $(WEB en.wikipedia.org/wiki/Tz_database, Wikipedia entry on TZ Database)
  24261. $(WEB en.wikipedia.org/wiki/List_of_tz_database_time_zones, List of Time
  24262. Zones)
  24263. +/
  24264. final class PosixTimeZone : TimeZone
  24265. {
  24266. public:
  24267. /++
  24268. Whether this time zone has Daylight Savings Time at any point in time.
  24269. Note that for some time zone types it may not have DST for current
  24270. dates but will still return true for $(D hasDST) because the time zone
  24271. did at some point have DST.
  24272. +/
  24273. @property override bool hasDST() const nothrow
  24274. {
  24275. return _hasDST;
  24276. }
  24277. /++
  24278. Takes the number of hnsecs (100 ns) since midnight, January 1st, 1 A.D.
  24279. in UTC time (i.e. std time) and returns whether DST is in effect in this
  24280. time zone at the given point in time.
  24281. Params:
  24282. stdTime = The UTC time that needs to be checked for DST in this time
  24283. zone.
  24284. +/
  24285. override bool dstInEffect(long stdTime) const nothrow
  24286. {
  24287. assert(!_transitions.empty);
  24288. try
  24289. {
  24290. immutable unixTime = stdTimeToUnixTime(stdTime);
  24291. if(_transitions.front.timeT >= unixTime)
  24292. return _transitions.front.ttInfo.isDST;
  24293. auto found = std.algorithm.countUntil!"b < a.timeT"(cast(Transition[])_transitions, unixTime);
  24294. if(found == -1)
  24295. return _transitions.back.ttInfo.isDST;
  24296. auto transition = found == 0 ? _transitions[0] : _transitions[found - 1];
  24297. return transition.ttInfo.isDST;
  24298. }
  24299. catch(Exception e)
  24300. assert(0, format("Nothing in calculateLeapSeconds() should be throwing. Caught Exception: %s", e));
  24301. }
  24302. /++
  24303. Takes the number of hnsecs (100 ns) since midnight, January 1st, 1 A.D.
  24304. in UTC time (i.e. std time) and converts it to this time zone's time.
  24305. Params:
  24306. stdTime = The UTC time that needs to be adjusted to this time zone's
  24307. time.
  24308. +/
  24309. override long utcToTZ(long stdTime) const nothrow
  24310. {
  24311. assert(!_transitions.empty);
  24312. try
  24313. {
  24314. immutable leapSecs = calculateLeapSeconds(stdTime);
  24315. immutable unixTime = stdTimeToUnixTime(stdTime);
  24316. if(_transitions.front.timeT >= unixTime)
  24317. return stdTime + convert!("seconds", "hnsecs")(_transitions.front.ttInfo.utcOffset + leapSecs);
  24318. auto found = std.algorithm.countUntil!"b < a.timeT"(cast(Transition[])_transitions, unixTime);
  24319. if(found == -1)
  24320. return stdTime + convert!("seconds", "hnsecs")(_transitions.back.ttInfo.utcOffset + leapSecs);
  24321. auto transition = found == 0 ? _transitions[0] : _transitions[found - 1];
  24322. return stdTime + convert!("seconds", "hnsecs")(transition.ttInfo.utcOffset + leapSecs);
  24323. }
  24324. catch(Exception e)
  24325. assert(0, format("Nothing in calculateLeapSeconds() should be throwing. Caught Exception: %s", e));
  24326. }
  24327. /++
  24328. Takes the number of hnsecs (100 ns) since midnight, January 1st, 1 A.D.
  24329. in this time zone's time and converts it to UTC (i.e. std time).
  24330. Params:
  24331. adjTime = The time in this time zone that needs to be adjusted to
  24332. UTC time.
  24333. +/
  24334. override long tzToUTC(long adjTime) const nothrow
  24335. {
  24336. assert(!_transitions.empty);
  24337. try
  24338. {
  24339. immutable leapSecs = calculateLeapSeconds(adjTime);
  24340. immutable unixTime = stdTimeToUnixTime(adjTime);
  24341. if(_transitions.front.timeT >= unixTime)
  24342. return adjTime - convert!("seconds", "hnsecs")(_transitions.front.ttInfo.utcOffset + leapSecs);
  24343. //Okay, casting is a hack, but countUntil shouldn't be changing it,
  24344. //and it would be too inefficient to have to keep duping it every
  24345. //time we have to calculate the time. Hopefully, countUntil will
  24346. //properly support immutable ranges at some point.
  24347. auto found = std.algorithm.countUntil!"b < a.timeT"(cast(Transition[])_transitions, unixTime);
  24348. if(found == -1)
  24349. return adjTime - convert!("seconds", "hnsecs")(_transitions.back.ttInfo.utcOffset + leapSecs);
  24350. auto transition = found == 0 ? _transitions[0] : _transitions[found - 1];
  24351. return adjTime - convert!("seconds", "hnsecs")(transition.ttInfo.utcOffset + leapSecs);
  24352. }
  24353. catch(Exception e)
  24354. assert(0, format("Nothing in calculateLeapSeconds() should be throwing. Caught Exception: %s", e));
  24355. }
  24356. version(Posix)
  24357. {
  24358. /++
  24359. The default directory where the TZ Database files are. It's empty
  24360. for Windows, since Windows doesn't have them.
  24361. +/
  24362. enum defaultTZDatabaseDir = "/usr/share/zoneinfo/";
  24363. }
  24364. else version(Windows)
  24365. {
  24366. /++ The default directory where the TZ Database files are. It's empty
  24367. for Windows, since Windows doesn't have them.
  24368. +/
  24369. enum defaultTZDatabaseDir = "";
  24370. }
  24371. /++
  24372. Returns a $(D TimeZone) with the give name per the TZ Database. The time
  24373. zone information is fetched from the TZ Database time zone files in the
  24374. given directory.
  24375. See_Also:
  24376. $(WEB en.wikipedia.org/wiki/Tz_database, Wikipedia entry on TZ
  24377. Database)
  24378. $(WEB en.wikipedia.org/wiki/List_of_tz_database_time_zones, List of
  24379. Time Zones)
  24380. Params:
  24381. name = The TZ Database name of the time zone that you're
  24382. looking for.
  24383. tzDatabaseDir = The directory where the TZ Database files are
  24384. located. Because these files are not located on
  24385. Windows systems, you will need to provide them
  24386. yourself and give their location here if you wish to
  24387. use $(D PosixTimeZone)s.
  24388. Throws:
  24389. $(D DateTimeException) if the given time zone could not be found or
  24390. $(D FileException) if the TZ Database file could not be opened.
  24391. Examples:
  24392. --------------------
  24393. auto tz = PosixTimeZone.getTimeZone("America/Los_Angeles");
  24394. assert(tz.name == "America/Los_Angeles");
  24395. assert(tz.stdName == "PST");
  24396. assert(tz.dstName == "PDT");
  24397. --------------------
  24398. +/
  24399. //TODO make it possible for tzDatabaseDir to be gzipped tar file rather than an uncompressed
  24400. // directory.
  24401. static immutable(PosixTimeZone) getTimeZone(string name, string tzDatabaseDir = defaultTZDatabaseDir)
  24402. {
  24403. name = strip(name);
  24404. enforce(tzDatabaseDir.exists, new DateTimeException(format("Directory %s does not exist.", tzDatabaseDir)));
  24405. enforce(tzDatabaseDir.isDir, new DateTimeException(format("%s is not a directory.", tzDatabaseDir)));
  24406. version(Posix)
  24407. auto file = tzDatabaseDir ~ name;
  24408. else version(Windows)
  24409. auto file = tzDatabaseDir ~ replace(strip(name), "/", sep);
  24410. enforce(file.exists, new DateTimeException(format("File %s does not exist.", file)));
  24411. enforce(file.isFile, new DateTimeException(format("%s is not a file.", file)));
  24412. auto tzFile = File(file);
  24413. immutable gmtZone = file.canFind("GMT");
  24414. try
  24415. {
  24416. _enforceValidTZFile(readVal!(char[])(tzFile, 4) == "TZif");
  24417. immutable char tzFileVersion = readVal!char(tzFile);
  24418. _enforceValidTZFile(tzFileVersion == '\0' || tzFileVersion == '2');
  24419. {
  24420. auto zeroBlock = readVal!(ubyte[])(tzFile, 15);
  24421. bool allZeroes = true;
  24422. foreach(val; zeroBlock)
  24423. {
  24424. if(val != 0)
  24425. {
  24426. allZeroes = false;
  24427. break;
  24428. }
  24429. }
  24430. _enforceValidTZFile(allZeroes);
  24431. }
  24432. //The number of UTC/local indicators stored in the file.
  24433. auto tzh_ttisgmtcnt = readVal!int(tzFile);
  24434. //The number of standard/wall indicators stored in the file.
  24435. auto tzh_ttisstdcnt = readVal!int(tzFile);
  24436. //The number of leap seconds for which data is stored in the file.
  24437. auto tzh_leapcnt = readVal!int(tzFile);
  24438. //The number of "transition times" for which data is stored in the file.
  24439. auto tzh_timecnt = readVal!int(tzFile);
  24440. //The number of "local time types" for which data is stored in the file (must not be zero).
  24441. auto tzh_typecnt = readVal!int(tzFile);
  24442. _enforceValidTZFile(tzh_typecnt != 0);
  24443. //The number of characters of "timezone abbreviation strings" stored in the file.
  24444. auto tzh_charcnt = readVal!int(tzFile);
  24445. //time_ts where DST transitions occur.
  24446. auto transitionTimeTs = new long[](tzh_timecnt);
  24447. foreach(ref transition; transitionTimeTs)
  24448. transition = readVal!int(tzFile);
  24449. //Indices into ttinfo structs indicating the changes
  24450. //to be made at the corresponding DST transition.
  24451. auto ttInfoIndices = new ubyte[](tzh_timecnt);
  24452. foreach(ref ttInfoIndex; ttInfoIndices)
  24453. ttInfoIndex = readVal!ubyte(tzFile);
  24454. //ttinfos which give info on DST transitions.
  24455. auto tempTTInfos = new TempTTInfo[](tzh_typecnt);
  24456. foreach(ref ttInfo; tempTTInfos)
  24457. ttInfo = readVal!TempTTInfo(tzFile);
  24458. //The array of time zone abbreviation characters.
  24459. auto tzAbbrevChars = readVal!(char[])(tzFile, tzh_charcnt);
  24460. auto leapSeconds = new LeapSecond[](tzh_leapcnt);
  24461. foreach(ref leapSecond; leapSeconds)
  24462. {
  24463. //The time_t when the leap second occurs.
  24464. auto timeT = readVal!int(tzFile);
  24465. //The total number of leap seconds to be applied after
  24466. //the corresponding leap second.
  24467. auto total = readVal!int(tzFile);
  24468. leapSecond = LeapSecond(timeT, total);
  24469. }
  24470. //Indicate whether each corresponding DST transition were specified
  24471. //in standard time or wall clock time.
  24472. auto transitionIsStd = new bool[](tzh_ttisstdcnt);
  24473. foreach(ref isStd; transitionIsStd)
  24474. isStd = readVal!bool(tzFile);
  24475. //Indicate whether each corresponding DST transition associated with
  24476. //local time types are specified in UTC or local time.
  24477. auto transitionInUTC = new bool[](tzh_ttisgmtcnt);
  24478. foreach(ref inUTC; transitionInUTC)
  24479. inUTC = readVal!bool(tzFile);
  24480. _enforceValidTZFile(!tzFile.eof());
  24481. //If version 2, the information is duplicated in 64-bit.
  24482. if(tzFileVersion == '2')
  24483. {
  24484. _enforceValidTZFile(readVal!(char[])(tzFile, 4) == "TZif");
  24485. _enforceValidTZFile(readVal!(char)(tzFile) == '2');
  24486. {
  24487. auto zeroBlock = readVal!(ubyte[])(tzFile, 15);
  24488. bool allZeroes = true;
  24489. foreach(val; zeroBlock)
  24490. {
  24491. if(val != 0)
  24492. {
  24493. allZeroes = false;
  24494. break;
  24495. }
  24496. }
  24497. _enforceValidTZFile(allZeroes);
  24498. }
  24499. //The number of UTC/local indicators stored in the file.
  24500. tzh_ttisgmtcnt = readVal!int(tzFile);
  24501. //The number of standard/wall indicators stored in the file.
  24502. tzh_ttisstdcnt = readVal!int(tzFile);
  24503. //The number of leap seconds for which data is stored in the file.
  24504. tzh_leapcnt = readVal!int(tzFile);
  24505. //The number of "transition times" for which data is stored in the file.
  24506. tzh_timecnt = readVal!int(tzFile);
  24507. //The number of "local time types" for which data is stored in the file (must not be zero).
  24508. tzh_typecnt = readVal!int(tzFile);
  24509. _enforceValidTZFile(tzh_typecnt != 0);
  24510. //The number of characters of "timezone abbreviation strings" stored in the file.
  24511. tzh_charcnt = readVal!int(tzFile);
  24512. //time_ts where DST transitions occur.
  24513. transitionTimeTs = new long[](tzh_timecnt);
  24514. foreach(ref transition; transitionTimeTs)
  24515. transition = readVal!long(tzFile);
  24516. //Indices into ttinfo structs indicating the changes
  24517. //to be made at the corresponding DST transition.
  24518. ttInfoIndices = new ubyte[](tzh_timecnt);
  24519. foreach(ref ttInfoIndex; ttInfoIndices)
  24520. ttInfoIndex = readVal!ubyte(tzFile);
  24521. //ttinfos which give info on DST transitions.
  24522. tempTTInfos = new TempTTInfo[](tzh_typecnt);
  24523. foreach(ref ttInfo; tempTTInfos)
  24524. ttInfo = readVal!TempTTInfo(tzFile);
  24525. //The array of time zone abbreviation characters.
  24526. tzAbbrevChars = readVal!(char[])(tzFile, tzh_charcnt);
  24527. leapSeconds = new LeapSecond[](tzh_leapcnt);
  24528. foreach(ref leapSecond; leapSeconds)
  24529. {
  24530. //The time_t when the leap second occurs.
  24531. auto timeT = readVal!long(tzFile);
  24532. //The total number of leap seconds to be applied after
  24533. //the corresponding leap second.
  24534. auto total = readVal!int(tzFile);
  24535. leapSecond = LeapSecond(timeT, total);
  24536. }
  24537. //Indicate whether each corresponding DST transition were specified
  24538. //in standard time or wall clock time.
  24539. transitionIsStd = new bool[](tzh_ttisstdcnt);
  24540. foreach(ref isStd; transitionIsStd)
  24541. isStd = readVal!bool(tzFile);
  24542. //Indicate whether each corresponding DST transition associated with
  24543. //local time types are specified in UTC or local time.
  24544. transitionInUTC = new bool[](tzh_ttisgmtcnt);
  24545. foreach(ref inUTC; transitionInUTC)
  24546. inUTC = readVal!bool(tzFile);
  24547. }
  24548. _enforceValidTZFile(tzFile.readln().strip().empty());
  24549. auto posixEnvStr = tzFile.readln().strip();
  24550. _enforceValidTZFile(tzFile.readln().strip().empty());
  24551. _enforceValidTZFile(tzFile.eof());
  24552. auto transitionTypes = new TransitionType*[](tempTTInfos.length);
  24553. foreach(i, ref ttype; transitionTypes)
  24554. {
  24555. bool isStd = false;
  24556. if(i < transitionIsStd.length && !transitionIsStd.empty)
  24557. isStd = transitionIsStd[i];
  24558. bool inUTC = false;
  24559. if(i < transitionInUTC.length && !transitionInUTC.empty)
  24560. inUTC = transitionInUTC[i];
  24561. ttype = new TransitionType(isStd, inUTC);
  24562. }
  24563. auto ttInfos = new immutable(TTInfo)*[](tempTTInfos.length);
  24564. foreach(i, ref ttInfo; ttInfos)
  24565. {
  24566. auto tempTTInfo = tempTTInfos[i];
  24567. if(gmtZone)
  24568. tempTTInfo.tt_gmtoff = -tempTTInfo.tt_gmtoff;
  24569. auto abbrevChars = tzAbbrevChars[tempTTInfo.tt_abbrind .. $];
  24570. string abbrev = abbrevChars[0 .. abbrevChars.stds_indexOf("\0")].idup;
  24571. ttInfo = new immutable(TTInfo)(tempTTInfos[i], abbrev);
  24572. }
  24573. auto tempTransitions = new TempTransition[](transitionTimeTs.length);
  24574. foreach(i, ref tempTransition; tempTransitions)
  24575. {
  24576. immutable ttiIndex = ttInfoIndices[i];
  24577. auto transitionTimeT = transitionTimeTs[i];
  24578. auto ttype = transitionTypes[ttiIndex];
  24579. auto ttInfo = ttInfos[ttiIndex];
  24580. tempTransition = TempTransition(transitionTimeT, ttInfo, ttype);
  24581. }
  24582. if(tempTransitions.empty)
  24583. {
  24584. _enforceValidTZFile(ttInfos.length == 1 && transitionTypes.length == 1);
  24585. tempTransitions ~= TempTransition(0, ttInfos[0], transitionTypes[0]);
  24586. }
  24587. sort!"a.timeT < b.timeT"(tempTransitions);
  24588. sort!"a.timeT < b.timeT"(leapSeconds);
  24589. auto transitions = new Transition[](tempTransitions.length);
  24590. foreach(i, ref transition; transitions)
  24591. {
  24592. auto tempTransition = tempTransitions[i];
  24593. auto transitionTimeT = tempTransition.timeT;
  24594. auto ttInfo = tempTransition.ttInfo;
  24595. auto ttype = tempTransition.ttype;
  24596. _enforceValidTZFile(i == 0 || transitionTimeT > tempTransitions[i - 1].timeT);
  24597. transition = Transition(transitionTimeT, ttInfo);
  24598. }
  24599. string stdName;
  24600. string dstName;
  24601. bool hasDST = false;
  24602. foreach(transition; retro(transitions))
  24603. {
  24604. auto ttInfo = transition.ttInfo;
  24605. if(ttInfo.isDST)
  24606. {
  24607. if(dstName.empty)
  24608. dstName = ttInfo.abbrev;
  24609. hasDST = true;
  24610. }
  24611. else
  24612. {
  24613. if(stdName.empty)
  24614. stdName = ttInfo.abbrev;
  24615. }
  24616. if(!stdName.empty && !dstName.empty)
  24617. break;
  24618. }
  24619. return new PosixTimeZone(transitions.idup, leapSeconds.idup, name, stdName, dstName, hasDST);
  24620. }
  24621. catch(DateTimeException dte)
  24622. throw dte;
  24623. catch(Exception e)
  24624. throw new DateTimeException("Not a valid TZ data file", __FILE__, __LINE__, e);
  24625. }
  24626. /++
  24627. Returns a list of the names of the time zones installed on the system.
  24628. You can provide a sub-name to narrow down the list of time zones (which
  24629. will likely be in the thousands if you get them all). For example,
  24630. if you pass in "America" as the sub-name, then only the time zones which
  24631. begin with "America" will be returned.
  24632. Params:
  24633. subName = The first part of the time zones that you want.
  24634. Throws:
  24635. $(D FileException) if it fails to read from disk.
  24636. +/
  24637. static string[] getInstalledTZNames(string subName = "", string tzDatabaseDir = defaultTZDatabaseDir)
  24638. {
  24639. version(Posix)
  24640. subName = strip(subName);
  24641. else version(Windows)
  24642. subName = replace(strip(subName), "/", sep);
  24643. if(!tzDatabaseDir.endsWith(sep))
  24644. tzDatabaseDir ~= sep;
  24645. enforce(tzDatabaseDir.exists, new DateTimeException(format("Directory %s does not exist.", tzDatabaseDir)));
  24646. enforce(tzDatabaseDir.isDir, new DateTimeException(format("%s is not a directory.", tzDatabaseDir)));
  24647. auto timezones = appender!(string[])();
  24648. foreach(DirEntry dentry; dirEntries(tzDatabaseDir, SpanMode.depth))
  24649. {
  24650. if(dentry.isFile)
  24651. {
  24652. auto tzName = dentry.name[tzDatabaseDir.length .. $];
  24653. if(!tzName.extension().empty() ||
  24654. !tzName.startsWith(subName) ||
  24655. tzName == "+VERSION")
  24656. {
  24657. continue;
  24658. }
  24659. timezones.put(tzName);
  24660. }
  24661. }
  24662. sort(timezones.data);
  24663. return timezones.data;
  24664. }
  24665. unittest
  24666. {
  24667. version(testStdDateTime)
  24668. {
  24669. version(Posix)
  24670. {
  24671. static void testPTZSuccess(string tzName)
  24672. {
  24673. scope(failure) writefln("TZName which threw: %s", tzName);
  24674. PosixTimeZone.getTimeZone(tzName);
  24675. }
  24676. static void testPTZFailure(string tzName)
  24677. {
  24678. scope(success) writefln("TZName which was supposed to throw: %s", tzName);
  24679. PosixTimeZone.getTimeZone(tzName);
  24680. }
  24681. auto tzNames = getInstalledTZNames();
  24682. foreach(tzName; tzNames)
  24683. assertNotThrown!DateTimeException(testPTZSuccess(tzName));
  24684. foreach(DirEntry dentry; dirEntries(defaultTZDatabaseDir, SpanMode.depth))
  24685. {
  24686. if(dentry.isFile)
  24687. {
  24688. auto tzName = dentry.name[defaultTZDatabaseDir.length .. $];
  24689. if(!canFind(tzNames, tzName))
  24690. assertThrown!DateTimeException(testPTZFailure(tzName));
  24691. }
  24692. }
  24693. }
  24694. }
  24695. }
  24696. private:
  24697. /+
  24698. Holds information on when a time transition occures (usually a
  24699. transition to or from DST) as well as a pointer to the $(D TTInfo) which
  24700. holds information on the utc offset passed the transition.
  24701. +/
  24702. struct Transition
  24703. {
  24704. this(long timeT, immutable (TTInfo)* ttInfo)
  24705. {
  24706. this.timeT = timeT;
  24707. this.ttInfo = ttInfo;
  24708. }
  24709. long timeT;
  24710. immutable (TTInfo)* ttInfo;
  24711. }
  24712. /+
  24713. Holds information on when a leap second occurs.
  24714. +/
  24715. struct LeapSecond
  24716. {
  24717. this(long timeT, int total)
  24718. {
  24719. this.timeT = timeT;
  24720. this.total = total;
  24721. }
  24722. long timeT;
  24723. int total;
  24724. }
  24725. /+
  24726. Holds information on the utc offset after a transition as well as
  24727. whether DST is in effect after that transition.
  24728. +/
  24729. struct TTInfo
  24730. {
  24731. this(in TempTTInfo tempTTInfo, string abbrev) immutable
  24732. {
  24733. utcOffset = tempTTInfo.tt_gmtoff;
  24734. isDST = tempTTInfo.tt_isdst;
  24735. this.abbrev = abbrev;
  24736. }
  24737. immutable int utcOffset; /// Offset from UTC.
  24738. immutable bool isDST; /// Whether DST is in effect.
  24739. immutable string abbrev; /// The current abbreviation for the time zone.
  24740. }
  24741. /+
  24742. Struct used to hold information relating to $(D TTInfo) while organizing
  24743. the time zone information prior to putting it in its final form.
  24744. +/
  24745. struct TempTTInfo
  24746. {
  24747. this(int gmtOff, bool isDST, ubyte abbrInd)
  24748. {
  24749. tt_gmtoff = gmtOff;
  24750. tt_isdst = isDST;
  24751. tt_abbrind = abbrInd;
  24752. }
  24753. int tt_gmtoff;
  24754. bool tt_isdst;
  24755. ubyte tt_abbrind;
  24756. }
  24757. /+
  24758. Struct used to hold information relating to $(D Transition) while
  24759. organizing the time zone information prior to putting it in its final
  24760. form.
  24761. +/
  24762. struct TempTransition
  24763. {
  24764. this(long timeT, immutable (TTInfo)* ttInfo, TransitionType* ttype)
  24765. {
  24766. this.timeT = timeT;
  24767. this.ttInfo = ttInfo;
  24768. this.ttype = ttype;
  24769. }
  24770. long timeT;
  24771. immutable (TTInfo)* ttInfo;
  24772. TransitionType* ttype;
  24773. }
  24774. /+
  24775. Struct used to hold information relating to $(D Transition) and
  24776. $(D TTInfo) while organizing the time zone information prior to putting
  24777. it in its final form.
  24778. +/
  24779. struct TransitionType
  24780. {
  24781. this(bool isStd, bool inUTC)
  24782. {
  24783. this.isStd = isStd;
  24784. this.inUTC = inUTC;
  24785. }
  24786. /// Whether the transition is in std time (as opposed to wall clock time).
  24787. bool isStd;
  24788. /// Whether the transition is in UTC (as opposed to local time).
  24789. bool inUTC;
  24790. }
  24791. /+
  24792. Reads an int from a TZ file.
  24793. +/
  24794. static T readVal(T)(ref File tzFile)
  24795. if((isIntegral!T || isSomeChar!T) || is(Unqual!T == bool))
  24796. {
  24797. import std.bitmanip;
  24798. T[1] buff;
  24799. _enforceValidTZFile(!tzFile.eof());
  24800. tzFile.rawRead(buff);
  24801. // @@@BUG@@@ 4414 forces us to save the result rather than use it directly.
  24802. auto bigEndian = cast(ubyte[T.sizeof])buff;
  24803. return bigEndianToNative!T(bigEndian);
  24804. }
  24805. /+
  24806. Reads an array of values from a TZ file.
  24807. +/
  24808. static T readVal(T)(ref File tzFile, size_t length)
  24809. if(isArray!T)
  24810. {
  24811. auto buff = new T(length);
  24812. _enforceValidTZFile(!tzFile.eof());
  24813. tzFile.rawRead(buff);
  24814. return buff;
  24815. }
  24816. /+
  24817. Reads a $(D TempTTInfo) from a TZ file.
  24818. +/
  24819. static T readVal(T)(ref File tzFile)
  24820. if(is(T == TempTTInfo))
  24821. {
  24822. return TempTTInfo(readVal!int(tzFile),
  24823. readVal!bool(tzFile),
  24824. readVal!ubyte(tzFile));
  24825. }
  24826. /+
  24827. Throws:
  24828. $(D DateTimeException) if $(D result) is false.
  24829. +/
  24830. static void _enforceValidTZFile(bool result, size_t line = __LINE__)
  24831. {
  24832. if(!result)
  24833. throw new DateTimeException("Not a valid tzdata file.", __FILE__, line);
  24834. }
  24835. int calculateLeapSeconds(long stdTime) const nothrow
  24836. {
  24837. try
  24838. {
  24839. if(_leapSeconds.empty)
  24840. return 0;
  24841. immutable unixTime = stdTimeToUnixTime(stdTime);
  24842. if(_leapSeconds.front.timeT >= unixTime)
  24843. return 0;
  24844. //Okay, casting is a hack, but countUntil shouldn't be changing it,
  24845. //and it would be too inefficient to have to keep duping it every
  24846. //time we have to calculate the time. Hopefully, countUntil will
  24847. //properly support immutable ranges at some point.
  24848. auto found = std.algorithm.countUntil!"b < a.timeT"(cast(LeapSecond[])_leapSeconds, unixTime);
  24849. if(found == -1)
  24850. return _leapSeconds.back.total;
  24851. auto leapSecond = found == 0 ? _leapSeconds[0] : _leapSeconds[found - 1];
  24852. return leapSecond.total;
  24853. }
  24854. catch(Exception e)
  24855. assert(0, format("Nothing in calculateLeapSeconds() should be throwing. Caught Exception: %s", e));
  24856. }
  24857. this(immutable Transition[] transitions,
  24858. immutable LeapSecond[] leapSeconds,
  24859. string name,
  24860. string stdName,
  24861. string dstName,
  24862. bool hasDST) immutable
  24863. {
  24864. if(dstName.empty && !stdName.empty)
  24865. dstName = stdName;
  24866. else if(stdName.empty && !dstName.empty)
  24867. stdName = dstName;
  24868. super(name, stdName, dstName);
  24869. if(!transitions.empty)
  24870. {
  24871. foreach(i, transition; transitions[0 .. $-1])
  24872. _enforceValidTZFile(transition.timeT < transitions[i + 1].timeT);
  24873. }
  24874. foreach(i, leapSecond; leapSeconds)
  24875. _enforceValidTZFile(i == leapSeconds.length - 1 || leapSecond.timeT < leapSeconds[i + 1].timeT);
  24876. _transitions = transitions;
  24877. _leapSeconds = leapSeconds;
  24878. _hasDST = hasDST;
  24879. }
  24880. /// List of times when the utc offset changes.
  24881. immutable Transition[] _transitions;
  24882. /// List of leap second occurrences.
  24883. immutable LeapSecond[] _leapSeconds;
  24884. /// Whether DST is in effect for this time zone at any point in time.
  24885. immutable bool _hasDST;
  24886. }
  24887. version(StdDdoc)
  24888. {
  24889. /++
  24890. $(BLUE This class is Windows-Only.)
  24891. Represents a time zone from the Windows registry. Unfortunately, Windows
  24892. does not use the TZ Database. You can, however, use $(D PosixTimeZone)
  24893. (which reads its information from the TZ Database files on disk) on
  24894. Windows if you provide the TZ Database files
  24895. ( $(WEB ftp://elsie.nci.nih.gov/pub/,
  24896. Repository with the TZ Database files (tzdata)) )
  24897. yourself and tell $(D PosixTimeZone.getTimeZone) where the directory
  24898. holding them is.
  24899. The TZ Dabatase files and Windows are not likely to always match,
  24900. particularly for historical dates, so if you want complete consistency
  24901. between Posix and Windows, then you should provide the appropriate
  24902. TZ Database files on Windows and use $(D PosixTimeZone). But as
  24903. $(D WindowsTimeZone) uses the Windows functions, $(D WindowsTimeZone)
  24904. is more likely to match the behavior of other Windows programs.
  24905. $(D WindowsTimeZone) should be fine for most programs.
  24906. $(D WindowsTimeZone) does not exist on Posix systems.
  24907. To get a $(D WindowsTimeZone), either call
  24908. $(D WindowsTimeZone.getTimeZone) or call $(D TimeZone.getTimeZone)
  24909. (which will give you a $(D PosixTimeZone) on Posix systems and a
  24910. $(D WindowsTimeZone) on Windows systems).
  24911. +/
  24912. final class WindowsTimeZone : TimeZone
  24913. {
  24914. public:
  24915. /++
  24916. Whether this time zone has Daylight Savings Time at any point in
  24917. time. Note that for some time zone types it may not have DST for
  24918. current dates but will still return true for $(D hasDST) because the
  24919. time zone did at some point have DST.
  24920. +/
  24921. @property override bool hasDST() const nothrow;
  24922. /++
  24923. Takes the number of hnsecs (100 ns) since midnight, January 1st,
  24924. 1 A.D. in UTC time (i.e. std time) and returns whether DST is in
  24925. effect in this time zone at the given point in time.
  24926. Params:
  24927. stdTime = The UTC time that needs to be checked for DST in this
  24928. time zone.
  24929. +/
  24930. override bool dstInEffect(long stdTime) const nothrow;
  24931. /++
  24932. Takes the number of hnsecs (100 ns) since midnight, January 1st,
  24933. 1 A.D. in UTC time (i.e. std time) and converts it to this time
  24934. zone's time.
  24935. Params:
  24936. stdTime = The UTC time that needs to be adjusted to this time
  24937. zone's time.
  24938. +/
  24939. override long utcToTZ(long stdTime) const nothrow;
  24940. /++
  24941. Takes the number of hnsecs (100 ns) since midnight, January 1st,
  24942. 1 A.D. in this time zone's time and converts it to UTC (i.e. std
  24943. time).
  24944. Params:
  24945. adjTime = The time in this time zone that needs to be adjusted
  24946. to UTC time.
  24947. +/
  24948. override long tzToUTC(long adjTime) const nothrow;
  24949. /++
  24950. Returns a $(D TimeZone) with the given name per the Windows time
  24951. zone names. The time zone information is fetched from the Windows
  24952. registry.
  24953. See_Also:
  24954. $(WEB en.wikipedia.org/wiki/Tz_database, Wikipedia entry on TZ
  24955. Database)
  24956. $(WEB en.wikipedia.org/wiki/List_of_tz_database_time_zones, List
  24957. of Time Zones)
  24958. Params:
  24959. name = The TZ Database name of the time zone that you're looking
  24960. for.
  24961. Throws:
  24962. $(D DateTimeException) if the given time zone could not be
  24963. found.
  24964. Examples:
  24965. --------------------
  24966. auto tz = TimeZone.getTimeZone("America/Los_Angeles");
  24967. --------------------
  24968. +/
  24969. static immutable(WindowsTimeZone) getTimeZone(string name);
  24970. /++
  24971. Returns a list of the names of the time zones installed on the
  24972. system.
  24973. +/
  24974. static string[] getInstalledTZNames();
  24975. private:
  24976. version(Windows) {}
  24977. else
  24978. alias void* TIME_ZONE_INFORMATION;
  24979. static bool _dstInEffect(const TIME_ZONE_INFORMATION* tzInfo, long stdTime) nothrow;
  24980. static long _utcToTZ(const TIME_ZONE_INFORMATION* tzInfo, long stdTime, bool hasDST) nothrow;
  24981. static long _tzToUTC(const TIME_ZONE_INFORMATION* tzInfo, long adjTime, bool hasDST) nothrow;
  24982. this() immutable pure
  24983. {
  24984. super("", "", "");
  24985. }
  24986. }
  24987. }
  24988. else version(Windows)
  24989. {
  24990. //Should be in core.sys.windows.windows, but for some reason it isn't.
  24991. extern(Windows)
  24992. {
  24993. export LONG RegQueryValueExA(HKEY hKey, LPCSTR name, LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count);
  24994. struct REG_TZI_FORMAT
  24995. {
  24996. LONG Bias;
  24997. LONG StandardBias;
  24998. LONG DaylightBias;
  24999. SYSTEMTIME StandardDate;
  25000. SYSTEMTIME DaylightDate;
  25001. }
  25002. }
  25003. final class WindowsTimeZone : TimeZone
  25004. {
  25005. public:
  25006. @property override bool hasDST() const nothrow
  25007. {
  25008. return _tzInfo.DaylightDate.wMonth != 0;
  25009. }
  25010. override bool dstInEffect(long stdTime) const nothrow
  25011. {
  25012. return _dstInEffect(&_tzInfo, stdTime);
  25013. }
  25014. override long utcToTZ(long stdTime) const nothrow
  25015. {
  25016. return _utcToTZ(&_tzInfo, stdTime, hasDST);
  25017. }
  25018. override long tzToUTC(long adjTime) const nothrow
  25019. {
  25020. return _tzToUTC(&_tzInfo, adjTime, hasDST);
  25021. }
  25022. static immutable(WindowsTimeZone) getTimeZone(string name)
  25023. {
  25024. auto keyStr = "Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\0";
  25025. HKEY baseKey;
  25026. {
  25027. auto result = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keyStr.ptr, 0, KEY_READ, &baseKey);
  25028. if(result != ERROR_SUCCESS)
  25029. throw new DateTimeException(format("Failed to open registry. Error: %s", result));
  25030. }
  25031. scope(exit) RegCloseKey(baseKey);
  25032. char[1024] keyName;
  25033. auto nameLen = to!DWORD(keyName.length);
  25034. int result;
  25035. for(DWORD index = 0;
  25036. (result = RegEnumKeyExA(baseKey, index, keyName.ptr, &nameLen, null, null, null, null)) != ERROR_NO_MORE_ITEMS;
  25037. ++index, nameLen = keyName.length)
  25038. {
  25039. if(result == ERROR_SUCCESS)
  25040. {
  25041. HKEY tzKey;
  25042. if(RegOpenKeyExA(baseKey, keyName.ptr, 0, KEY_READ, &tzKey) == ERROR_SUCCESS)
  25043. {
  25044. scope(exit) RegCloseKey(tzKey);
  25045. char[1024] strVal;
  25046. auto strValLen = to!DWORD(strVal.length);
  25047. bool queryStringValue(string name, size_t lineNum = __LINE__)
  25048. {
  25049. strValLen = strVal.length;
  25050. return RegQueryValueExA(tzKey, name.ptr, null, null, cast(ubyte*)strVal.ptr, &strValLen) == ERROR_SUCCESS;
  25051. }
  25052. if(to!string(keyName.ptr) == name)
  25053. {
  25054. if(queryStringValue("Std\0"))
  25055. {
  25056. //Cannot use to!wstring(char*), probably due to bug http://d.puremagic.com/issues/show_bug.cgi?id=5016
  25057. static wstring conv(char* cstr, size_t strValLen)
  25058. {
  25059. cstr[strValLen - 1] = '\0';
  25060. string retval;
  25061. for(;; ++cstr)
  25062. {
  25063. if(*cstr == '\0')
  25064. break;
  25065. retval ~= *cstr;
  25066. }
  25067. return to!wstring(retval);
  25068. }
  25069. //auto stdName = to!wstring(strVal.ptr);
  25070. auto stdName = conv(strVal.ptr, strValLen);
  25071. if(queryStringValue("Dlt\0"))
  25072. {
  25073. //auto dstName = to!wstring(strVal.ptr);
  25074. auto dstName = conv(strVal.ptr, strValLen);
  25075. enum tzi = "TZI\0";
  25076. REG_TZI_FORMAT binVal;
  25077. auto binValLen = to!DWORD(REG_TZI_FORMAT.sizeof);
  25078. if(RegQueryValueExA(tzKey, tzi.ptr, null, null, cast(ubyte*)&binVal, &binValLen) == ERROR_SUCCESS)
  25079. {
  25080. TIME_ZONE_INFORMATION tzInfo;
  25081. auto stdNameLen = stdName.length > 32 ? 32 : stdName.length;
  25082. auto dstNameLen = dstName.length > 32 ? 32 : dstName.length;
  25083. tzInfo.Bias = binVal.Bias;
  25084. tzInfo.StandardName[0 .. stdNameLen] = stdName[0 .. stdNameLen];
  25085. tzInfo.StandardName[stdNameLen .. $] = '\0';
  25086. tzInfo.StandardDate = binVal.StandardDate;
  25087. tzInfo.StandardBias = binVal.StandardBias;
  25088. tzInfo.DaylightName[0 .. dstNameLen] = dstName[0 .. dstNameLen];
  25089. tzInfo.DaylightName[dstNameLen .. $] = '\0';
  25090. tzInfo.DaylightDate = binVal.DaylightDate;
  25091. tzInfo.DaylightBias = binVal.DaylightBias;
  25092. return new WindowsTimeZone(name, tzInfo);
  25093. }
  25094. }
  25095. }
  25096. }
  25097. }
  25098. }
  25099. }
  25100. throw new DateTimeException(format("Failed to find time zone: %s", name));
  25101. }
  25102. static string[] getInstalledTZNames()
  25103. {
  25104. auto timezones = appender!(string[])();
  25105. auto keyStr = "Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones";
  25106. HKEY baseKey;
  25107. {
  25108. auto result = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keyStr.ptr, 0, KEY_READ, &baseKey);
  25109. if(result != ERROR_SUCCESS)
  25110. throw new DateTimeException(format("Failed to open registry. Error: %s", result));
  25111. }
  25112. scope(exit) RegCloseKey(baseKey);
  25113. char[1024] keyName;
  25114. auto nameLen = to!DWORD(keyName.length);
  25115. int result;
  25116. for(DWORD index = 0;
  25117. (result = RegEnumKeyExA(baseKey, index, keyName.ptr, &nameLen, null, null, null, null)) != ERROR_NO_MORE_ITEMS;
  25118. ++index, nameLen = keyName.length)
  25119. {
  25120. if(result == ERROR_SUCCESS)
  25121. timezones.put(to!string(keyName.ptr));
  25122. }
  25123. sort(timezones.data);
  25124. return timezones.data;
  25125. }
  25126. unittest
  25127. {
  25128. version(testStdDateTime)
  25129. {
  25130. static void testWTZSuccess(string tzName)
  25131. {
  25132. scope(failure) writefln("TZName which threw: %s", tzName);
  25133. WindowsTimeZone.getTimeZone(tzName);
  25134. }
  25135. auto tzNames = getInstalledTZNames();
  25136. foreach(tzName; tzNames)
  25137. assertNotThrown!DateTimeException(testWTZSuccess(tzName));
  25138. }
  25139. }
  25140. private:
  25141. static bool _dstInEffect(const TIME_ZONE_INFORMATION* tzInfo, long stdTime) nothrow
  25142. {
  25143. try
  25144. {
  25145. if(tzInfo.DaylightDate.wMonth == 0)
  25146. return false;
  25147. auto utcDateTime = cast(DateTime)SysTime(stdTime, UTC());
  25148. //The limits of what SystemTimeToTZSpecificLocalTime will accept.
  25149. if(utcDateTime.year < 1601)
  25150. {
  25151. if(utcDateTime.month == Month.feb && utcDateTime.day == 29)
  25152. utcDateTime.day = 28;
  25153. utcDateTime.year = 1601;
  25154. }
  25155. else if(utcDateTime.year > 30_827)
  25156. {
  25157. if(utcDateTime.month == Month.feb && utcDateTime.day == 29)
  25158. utcDateTime.day = 28;
  25159. utcDateTime.year = 30_827;
  25160. }
  25161. //SystemTimeToTZSpecificLocalTime doesn't act correctly at the
  25162. //beginning or end of the year (bleh). Unless some bizarre time
  25163. //zone changes DST on January 1st or December 31st, this should
  25164. //fix the problem.
  25165. if(utcDateTime.month == Month.jan)
  25166. {
  25167. if(utcDateTime.day == 1)
  25168. utcDateTime.day = 2;
  25169. }
  25170. else if(utcDateTime.month == Month.dec && utcDateTime.day == 31)
  25171. utcDateTime.day = 30;
  25172. SYSTEMTIME utcTime = void;
  25173. SYSTEMTIME otherTime = void;
  25174. utcTime.wYear = utcDateTime.year;
  25175. utcTime.wMonth = utcDateTime.month;
  25176. utcTime.wDay = utcDateTime.day;
  25177. utcTime.wHour = utcDateTime.hour;
  25178. utcTime.wMinute = utcDateTime.minute;
  25179. utcTime.wSecond = utcDateTime.second;
  25180. utcTime.wMilliseconds = 0;
  25181. immutable result = SystemTimeToTzSpecificLocalTime(cast(TIME_ZONE_INFORMATION*)tzInfo,
  25182. &utcTime,
  25183. &otherTime);
  25184. assert(result);
  25185. immutable otherDateTime = DateTime(otherTime.wYear,
  25186. otherTime.wMonth,
  25187. otherTime.wDay,
  25188. otherTime.wHour,
  25189. otherTime.wMinute,
  25190. otherTime.wSecond);
  25191. immutable diff = utcDateTime - otherDateTime;
  25192. immutable minutes = diff.total!"minutes"() - tzInfo.Bias;
  25193. if(minutes == tzInfo.DaylightBias)
  25194. return true;
  25195. assert(minutes == tzInfo.StandardBias);
  25196. return false;
  25197. }
  25198. catch(Exception e)
  25199. assert(0, "DateTime's constructor threw.");
  25200. }
  25201. version(testStdDateTime) unittest
  25202. {
  25203. TIME_ZONE_INFORMATION tzInfo;
  25204. GetTimeZoneInformation(&tzInfo);
  25205. foreach(year; [1600, 1601, 30_827, 30_828])
  25206. WindowsTimeZone._dstInEffect(&tzInfo, SysTime(DateTime(year, 1, 1)).stdTime);
  25207. }
  25208. static long _utcToTZ(const TIME_ZONE_INFORMATION* tzInfo, long stdTime, bool hasDST) nothrow
  25209. {
  25210. if(hasDST && WindowsTimeZone._dstInEffect(tzInfo, stdTime))
  25211. return stdTime - convert!("minutes", "hnsecs")(tzInfo.Bias + tzInfo.DaylightBias);
  25212. return stdTime - convert!("minutes", "hnsecs")(tzInfo.Bias + tzInfo.StandardBias);
  25213. }
  25214. static long _tzToUTC(const TIME_ZONE_INFORMATION* tzInfo, long adjTime, bool hasDST) nothrow
  25215. {
  25216. if(hasDST)
  25217. {
  25218. try
  25219. {
  25220. bool dstInEffectForLocalDateTime(DateTime localDateTime)
  25221. {
  25222. //The limits of what SystemTimeToTZSpecificLocalTime will accept.
  25223. if(localDateTime.year < 1601)
  25224. {
  25225. if(localDateTime.month == Month.feb && localDateTime.day == 29)
  25226. localDateTime.day = 28;
  25227. localDateTime.year = 1601;
  25228. }
  25229. else if(localDateTime.year > 30_827)
  25230. {
  25231. if(localDateTime.month == Month.feb && localDateTime.day == 29)
  25232. localDateTime.day = 28;
  25233. localDateTime.year = 30_827;
  25234. }
  25235. //SystemTimeToTZSpecificLocalTime doesn't act correctly at the
  25236. //beginning or end of the year (bleh). Unless some bizarre time
  25237. //zone changes DST on January 1st or December 31st, this should
  25238. //fix the problem.
  25239. if(localDateTime.month == Month.jan)
  25240. {
  25241. if(localDateTime.day == 1)
  25242. localDateTime.day = 2;
  25243. }
  25244. else if(localDateTime.month == Month.dec && localDateTime.day == 31)
  25245. localDateTime.day = 30;
  25246. SYSTEMTIME utcTime = void;
  25247. SYSTEMTIME localTime = void;
  25248. localTime.wYear = localDateTime.year;
  25249. localTime.wMonth = localDateTime.month;
  25250. localTime.wDay = localDateTime.day;
  25251. localTime.wHour = localDateTime.hour;
  25252. localTime.wMinute = localDateTime.minute;
  25253. localTime.wSecond = localDateTime.second;
  25254. localTime.wMilliseconds = 0;
  25255. immutable result = SystemTimeToTzSpecificLocalTime(cast(TIME_ZONE_INFORMATION*)tzInfo,
  25256. &localTime,
  25257. &utcTime);
  25258. assert(result);
  25259. immutable utcDateTime = DateTime(utcTime.wYear,
  25260. utcTime.wMonth,
  25261. utcTime.wDay,
  25262. utcTime.wHour,
  25263. utcTime.wMinute,
  25264. utcTime.wSecond);
  25265. immutable diff = localDateTime - utcDateTime;
  25266. immutable minutes = diff.total!"minutes"() - tzInfo.Bias;
  25267. if(minutes == tzInfo.DaylightBias)
  25268. return true;
  25269. assert(minutes == tzInfo.StandardBias);
  25270. return false;
  25271. }
  25272. auto localDateTime = cast(DateTime)SysTime(adjTime, UTC());
  25273. auto localDateTimeBefore = localDateTime - dur!"hours"(1);
  25274. auto localDateTimeAfter = localDateTime + dur!"hours"(1);
  25275. auto dstInEffectNow = dstInEffectForLocalDateTime(localDateTime);
  25276. auto dstInEffectBefore = dstInEffectForLocalDateTime(localDateTimeBefore);
  25277. auto dstInEffectAfter = dstInEffectForLocalDateTime(localDateTimeAfter);
  25278. bool isDST;
  25279. if(dstInEffectBefore && dstInEffectNow && dstInEffectAfter)
  25280. isDST = true;
  25281. else if(!dstInEffectBefore && !dstInEffectNow && !dstInEffectAfter)
  25282. isDST = false;
  25283. else if((!dstInEffectBefore && dstInEffectAfter) ||
  25284. (dstInEffectBefore && !dstInEffectAfter))
  25285. {
  25286. isDST = dstInEffectNow;
  25287. }
  25288. else
  25289. assert(0, "Bad Logic.");
  25290. if(isDST)
  25291. return adjTime + convert!("minutes", "hnsecs")(tzInfo.Bias + tzInfo.DaylightBias);
  25292. }
  25293. catch(Exception e)
  25294. assert(0, "SysTime's constructor threw.");
  25295. }
  25296. return adjTime + convert!("minutes", "hnsecs")(tzInfo.Bias + tzInfo.StandardBias);
  25297. }
  25298. this(string name, TIME_ZONE_INFORMATION tzInfo) immutable
  25299. {
  25300. //Cannot use to!string(wchar*), probably due to bug http://d.puremagic.com/issues/show_bug.cgi?id=5016
  25301. static string conv(wchar* wcstr)
  25302. {
  25303. wcstr[31] = '\0';
  25304. wstring retval;
  25305. for(;; ++wcstr)
  25306. {
  25307. if(*wcstr == '\0')
  25308. break;
  25309. retval ~= *wcstr;
  25310. }
  25311. return to!string(retval);
  25312. }
  25313. //super(name, to!string(tzInfo.StandardName.ptr), to!string(tzInfo.DaylightName.ptr));
  25314. super(name, conv(tzInfo.StandardName.ptr), conv(tzInfo.DaylightName.ptr));
  25315. _tzInfo = tzInfo;
  25316. }
  25317. TIME_ZONE_INFORMATION _tzInfo;
  25318. }
  25319. }
  25320. version(StdDdoc)
  25321. {
  25322. /++
  25323. $(BLUE This function is Posix-Only.)
  25324. Allows you to set the local time zone on Posix systems with the TZ
  25325. database name by setting the TZ environment variable.
  25326. Unfortunately, there is no way to do it on Windows using the TZ
  25327. database name, so this function only exists on Posix systems.
  25328. +/
  25329. void setTZEnvVar(string tzDatabaseName);
  25330. /++
  25331. $(BLUE This function is Posix-Only.)
  25332. Clears the TZ environment variable.
  25333. +/
  25334. void clearTZEnvVar();
  25335. }
  25336. else version(Posix)
  25337. {
  25338. void setTZEnvVar(string tzDatabaseName) nothrow
  25339. {
  25340. try
  25341. {
  25342. auto value = PosixTimeZone.defaultTZDatabaseDir ~ tzDatabaseName ~ "\0";
  25343. setenv("TZ", value.ptr, 1);
  25344. tzset();
  25345. }
  25346. catch(Exception e)
  25347. assert(0, "The impossible happened. setenv or tzset threw.");
  25348. }
  25349. void clearTZEnvVar() nothrow
  25350. {
  25351. try
  25352. {
  25353. unsetenv("TZ");
  25354. tzset();
  25355. }
  25356. catch(Exception e)
  25357. assert(0, "The impossible happened. unsetenv or tzset threw.");
  25358. }
  25359. }
  25360. /++
  25361. Converts the given TZ Database name to the corresponding Windows time zone
  25362. name.
  25363. Note that in a few cases, a TZ Dabatase name corresponds to two different
  25364. Windows time zone names. So, while in most cases converting from one to the
  25365. other and back again will result in the same time zone name that you started
  25366. with, in a few cases, you will get a different name.
  25367. Also, there are far more TZ Database names than Windows time zones, so some
  25368. of the more exotic TZ Database names don't have corresponding Windows time
  25369. zone names.
  25370. See_Also:
  25371. $(WEB unicode.org/repos/cldr-tmp/trunk/diff/supplemental/zone_tzid.html,
  25372. Windows <-> TZ Database Name Conversion Table)
  25373. Params:
  25374. tzName = The TZ Database name to convert.
  25375. Throws:
  25376. $(D DateTimeException) if the given $(D_PARAM tzName) cannot be
  25377. converted.
  25378. +/
  25379. string tzDatabaseNameToWindowsTZName(string tzName)
  25380. {
  25381. switch(tzName)
  25382. {
  25383. case "Africa/Cairo": return "Egypt Standard Time";
  25384. case "Africa/Casablanca": return "Morocco Standard Time";
  25385. case "Africa/Johannesburg": return "South Africa Standard Time";
  25386. case "Africa/Lagos": return "W. Central Africa Standard Time";
  25387. case "Africa/Nairobi": return "E. Africa Standard Time";
  25388. case "Africa/Windhoek": return "Namibia Standard Time";
  25389. case "America/Anchorage": return "Alaskan Standard Time";
  25390. case "America/Asuncion": return "Paraguay Standard Time";
  25391. case "America/Bogota": return "SA Pacific Standard Time";
  25392. case "America/Buenos_Aires": return "Argentina Standard Time";
  25393. case "America/Caracas": return "Venezuela Standard Time";
  25394. case "America/Cayenne": return "SA Eastern Standard Time";
  25395. case "America/Chicago": return "Central Standard Time";
  25396. case "America/Chihuahua": return "Mountain Standard Time (Mexico)";
  25397. case "America/Cuiaba": return "Central Brazilian Standard Time";
  25398. case "America/Denver": return "Mountain Standard Time";
  25399. case "America/Godthab": return "Greenland Standard Time";
  25400. case "America/Guatemala": return "Central America Standard Time";
  25401. case "America/Halifax": return "Atlantic Standard Time";
  25402. case "America/La_Paz": return "SA Western Standard Time";
  25403. case "America/Los_Angeles": return "Pacific Standard Time";
  25404. case "America/Mexico_City": return "Central Standard Time (Mexico)";
  25405. case "America/Montevideo": return "Montevideo Standard Time";
  25406. case "America/New_York": return "Eastern Standard Time";
  25407. case "America/Phoenix": return "US Mountain Standard Time";
  25408. case "America/Regina": return "Canada Central Standard Time";
  25409. case "America/Santa_Isabel": return "Pacific Standard Time (Mexico)";
  25410. case "America/Santiago": return "Pacific SA Standard Time";
  25411. case "America/Sao_Paulo": return "E. South America Standard Time";
  25412. case "America/St_Johns": return "Newfoundland Standard Time";
  25413. case "Asia/Almaty": return "Central Asia Standard Time";
  25414. case "Asia/Amman": return "Jordan Standard Time";
  25415. case "Asia/Baghdad": return "Arabic Standard Time";
  25416. case "Asia/Baku": return "Azerbaijan Standard Time";
  25417. case "Asia/Bangkok": return "SE Asia Standard Time";
  25418. case "Asia/Beirut": return "Middle East Standard Time";
  25419. case "Asia/Calcutta": return "India Standard Time";
  25420. case "Asia/Colombo": return "Sri Lanka Standard Time";
  25421. case "Asia/Damascus": return "Syria Standard Time";
  25422. case "Asia/Dhaka": return "Bangladesh Standard Time";
  25423. case "Asia/Dubai": return "Arabian Standard Time";
  25424. case "Asia/Irkutsk": return "North Asia East Standard Time";
  25425. case "Asia/Jerusalem": return "Israel Standard Time";
  25426. case "Asia/Kabul": return "Afghanistan Standard Time";
  25427. case "Asia/Kamchatka": return "Kamchatka Standard Time";
  25428. case "Asia/Karachi": return "Pakistan Standard Time";
  25429. case "Asia/Katmandu": return "Nepal Standard Time";
  25430. case "Asia/Krasnoyarsk": return "North Asia Standard Time";
  25431. case "Asia/Magadan": return "Magadan Standard Time";
  25432. case "Asia/Novosibirsk": return "N. Central Asia Standard Time";
  25433. case "Asia/Rangoon": return "Myanmar Standard Time";
  25434. case "Asia/Riyadh": return "Arab Standard Time";
  25435. case "Asia/Seoul": return "Korea Standard Time";
  25436. case "Asia/Shanghai": return "China Standard Time";
  25437. case "Asia/Singapore": return "Singapore Standard Time";
  25438. case "Asia/Taipei": return "Taipei Standard Time";
  25439. case "Asia/Tashkent": return "West Asia Standard Time";
  25440. case "Asia/Tbilisi": return "Georgian Standard Time";
  25441. case "Asia/Tehran": return "Iran Standard Time";
  25442. case "Asia/Tokyo": return "Tokyo Standard Time";
  25443. case "Asia/Ulaanbaatar": return "Ulaanbaatar Standard Time";
  25444. case "Asia/Vladivostok": return "Vladivostok Standard Time";
  25445. case "Asia/Yakutsk": return "Yakutsk Standard Time";
  25446. case "Asia/Yekaterinburg": return "Ekaterinburg Standard Time";
  25447. case "Asia/Yerevan": return "Caucasus Standard Time";
  25448. case "Atlantic/Azores": return "Azores Standard Time";
  25449. case "Atlantic/Cape_Verde": return "Cape Verde Standard Time";
  25450. case "Atlantic/Reykjavik": return "Greenwich Standard Time";
  25451. case "Australia/Adelaide": return "Cen. Australia Standard Time";
  25452. case "Australia/Brisbane": return "E. Australia Standard Time";
  25453. case "Australia/Darwin": return "AUS Central Standard Time";
  25454. case "Australia/Hobart": return "Tasmania Standard Time";
  25455. case "Australia/Perth": return "W. Australia Standard Time";
  25456. case "Australia/Sydney": return "AUS Eastern Standard Time";
  25457. case "Etc/GMT-12": return "UTC+12";
  25458. case "Etc/GMT": return "UTC";
  25459. case "Etc/GMT+11": return "UTC-11";
  25460. case "Etc/GMT+12": return "Dateline Standard Time";
  25461. case "Etc/GMT+2": return "Mid-Atlantic Standard Time";
  25462. case "Etc/GMT+5": return "US Eastern Standard Time";
  25463. case "Europe/Berlin": return "W. Europe Standard Time";
  25464. case "Europe/Budapest": return "Central Europe Standard Time";
  25465. case "Europe/Istanbul": return "GTB Standard Time";
  25466. case "Europe/Kiev": return "FLE Standard Time";
  25467. case "Europe/London": return "GMT Standard Time";
  25468. case "Europe/Minsk": return "E. Europe Standard Time";
  25469. case "Europe/Moscow": return "Russian Standard Time";
  25470. case "Europe/Paris": return "Romance Standard Time";
  25471. case "Europe/Warsaw": return "Central European Standard Time";
  25472. case "Indian/Mauritius": return "Mauritius Standard Time";
  25473. case "Pacific/Apia": return "Samoa Standard Time";
  25474. case "Pacific/Auckland": return "New Zealand Standard Time";
  25475. case "Pacific/Fiji": return "Fiji Standard Time";
  25476. case "Pacific/Guadalcanal": return "Central Pacific Standard Time";
  25477. case "Pacific/Honolulu": return "Hawaiian Standard Time";
  25478. case "Pacific/Port_Moresby": return "West Pacific Standard Time";
  25479. case "Pacific/Tongatapu": return "Tonga Standard Time";
  25480. default:
  25481. throw new DateTimeException(format("Could not find Windows time zone name for: %s.", tzName));
  25482. }
  25483. }
  25484. unittest
  25485. {
  25486. version(testStdDateTime)
  25487. {
  25488. version(Windows)
  25489. {
  25490. static void testTZSuccess(string tzName)
  25491. {
  25492. scope(failure) writefln("TZName which threw: %s", tzName);
  25493. tzDatabaseNameToWindowsTZName(tzName);
  25494. }
  25495. auto timeZones = TimeZone.getInstalledTZNames();
  25496. foreach(tzname; timeZones)
  25497. assertNotThrown!DateTimeException(testTZSuccess(tzname));
  25498. }
  25499. }
  25500. }
  25501. /++
  25502. Converts the given Windows time zone name to a corresponding TZ Database
  25503. name.
  25504. See_Also:
  25505. $(WEB unicode.org/repos/cldr-tmp/trunk/diff/supplemental/zone_tzid.html,
  25506. Windows <-> TZ Database Name Conversion Table)
  25507. Params:
  25508. tzName = The TZ Database name to convert.
  25509. Throws:
  25510. $(D DateTimeException) if the given $(D_PARAM tzName) cannot be
  25511. converted.
  25512. +/
  25513. string windowsTZNameToTZDatabaseName(string tzName)
  25514. {
  25515. switch(tzName)
  25516. {
  25517. case "AUS Central Standard Time": return "Australia/Darwin";
  25518. case "AUS Eastern Standard Time": return "Australia/Sydney";
  25519. case "Afghanistan Standard Time": return "Asia/Kabul";
  25520. case "Alaskan Standard Time": return "America/Anchorage";
  25521. case "Arab Standard Time": return "Asia/Riyadh";
  25522. case "Arabian Standard Time": return "Asia/Dubai";
  25523. case "Arabic Standard Time": return "Asia/Baghdad";
  25524. case "Argentina Standard Time": return "America/Buenos_Aires";
  25525. case "Armenian Standard Time": return "Asia/Yerevan";
  25526. case "Atlantic Standard Time": return "America/Halifax";
  25527. case "Azerbaijan Standard Time": return "Asia/Baku";
  25528. case "Azores Standard Time": return "Atlantic/Azores";
  25529. case "Bangladesh Standard Time": return "Asia/Dhaka";
  25530. case "Canada Central Standard Time": return "America/Regina";
  25531. case "Cape Verde Standard Time": return "Atlantic/Cape_Verde";
  25532. case "Caucasus Standard Time": return "Asia/Yerevan";
  25533. case "Cen. Australia Standard Time": return "Australia/Adelaide";
  25534. case "Central America Standard Time": return "America/Guatemala";
  25535. case "Central Asia Standard Time": return "Asia/Almaty";
  25536. case "Central Brazilian Standard Time": return "America/Cuiaba";
  25537. case "Central Europe Standard Time": return "Europe/Budapest";
  25538. case "Central European Standard Time": return "Europe/Warsaw";
  25539. case "Central Pacific Standard Time": return "Pacific/Guadalcanal";
  25540. case "Central Standard Time": return "America/Chicago";
  25541. case "Central Standard Time (Mexico)": return "America/Mexico_City";
  25542. case "China Standard Time": return "Asia/Shanghai";
  25543. case "Dateline Standard Time": return "Etc/GMT+12";
  25544. case "E. Africa Standard Time": return "Africa/Nairobi";
  25545. case "E. Australia Standard Time": return "Australia/Brisbane";
  25546. case "E. Europe Standard Time": return "Europe/Minsk";
  25547. case "E. South America Standard Time": return "America/Sao_Paulo";
  25548. case "Eastern Standard Time": return "America/New_York";
  25549. case "Egypt Standard Time": return "Africa/Cairo";
  25550. case "Ekaterinburg Standard Time": return "Asia/Yekaterinburg";
  25551. case "FLE Standard Time": return "Europe/Kiev";
  25552. case "Fiji Standard Time": return "Pacific/Fiji";
  25553. case "GMT Standard Time": return "Europe/London";
  25554. case "GTB Standard Time": return "Europe/Istanbul";
  25555. case "Georgian Standard Time": return "Asia/Tbilisi";
  25556. case "Greenland Standard Time": return "America/Godthab";
  25557. case "Greenwich Standard Time": return "Atlantic/Reykjavik";
  25558. case "Hawaiian Standard Time": return "Pacific/Honolulu";
  25559. case "India Standard Time": return "Asia/Calcutta";
  25560. case "Iran Standard Time": return "Asia/Tehran";
  25561. case "Israel Standard Time": return "Asia/Jerusalem";
  25562. case "Jordan Standard Time": return "Asia/Amman";
  25563. case "Kamchatka Standard Time": return "Asia/Kamchatka";
  25564. case "Korea Standard Time": return "Asia/Seoul";
  25565. case "Magadan Standard Time": return "Asia/Magadan";
  25566. case "Mauritius Standard Time": return "Indian/Mauritius";
  25567. case "Mexico Standard Time": return "America/Mexico_City";
  25568. case "Mexico Standard Time 2": return "America/Chihuahua";
  25569. case "Mid-Atlantic Standard Time": return "Etc/GMT+2";
  25570. case "Middle East Standard Time": return "Asia/Beirut";
  25571. case "Montevideo Standard Time": return "America/Montevideo";
  25572. case "Morocco Standard Time": return "Africa/Casablanca";
  25573. case "Mountain Standard Time": return "America/Denver";
  25574. case "Mountain Standard Time (Mexico)": return "America/Chihuahua";
  25575. case "Myanmar Standard Time": return "Asia/Rangoon";
  25576. case "N. Central Asia Standard Time": return "Asia/Novosibirsk";
  25577. case "Namibia Standard Time": return "Africa/Windhoek";
  25578. case "Nepal Standard Time": return "Asia/Katmandu";
  25579. case "New Zealand Standard Time": return "Pacific/Auckland";
  25580. case "Newfoundland Standard Time": return "America/St_Johns";
  25581. case "North Asia East Standard Time": return "Asia/Irkutsk";
  25582. case "North Asia Standard Time": return "Asia/Krasnoyarsk";
  25583. case "Pacific SA Standard Time": return "America/Santiago";
  25584. case "Pacific Standard Time": return "America/Los_Angeles";
  25585. case "Pacific Standard Time (Mexico)": return "America/Santa_Isabel";
  25586. case "Pakistan Standard Time": return "Asia/Karachi";
  25587. case "Paraguay Standard Time": return "America/Asuncion";
  25588. case "Romance Standard Time": return "Europe/Paris";
  25589. case "Russian Standard Time": return "Europe/Moscow";
  25590. case "SA Eastern Standard Time": return "America/Cayenne";
  25591. case "SA Pacific Standard Time": return "America/Bogota";
  25592. case "SA Western Standard Time": return "America/La_Paz";
  25593. case "SE Asia Standard Time": return "Asia/Bangkok";
  25594. case "Samoa Standard Time": return "Pacific/Apia";
  25595. case "Singapore Standard Time": return "Asia/Singapore";
  25596. case "South Africa Standard Time": return "Africa/Johannesburg";
  25597. case "Sri Lanka Standard Time": return "Asia/Colombo";
  25598. case "Syria Standard Time": return "Asia/Damascus";
  25599. case "Taipei Standard Time": return "Asia/Taipei";
  25600. case "Tasmania Standard Time": return "Australia/Hobart";
  25601. case "Tokyo Standard Time": return "Asia/Tokyo";
  25602. case "Tonga Standard Time": return "Pacific/Tongatapu";
  25603. case "US Eastern Standard Time": return "Etc/GMT+5";
  25604. case "US Mountain Standard Time": return "America/Phoenix";
  25605. case "UTC": return "Etc/GMT";
  25606. case "UTC+12": return "Etc/GMT-12";
  25607. case "UTC-02": return "Etc/GMT+2";
  25608. case "UTC-11": return "Etc/GMT+11";
  25609. case "Ulaanbaatar Standard Time": return "Asia/Ulaanbaatar";
  25610. case "Venezuela Standard Time": return "America/Caracas";
  25611. case "Vladivostok Standard Time": return "Asia/Vladivostok";
  25612. case "W. Australia Standard Time": return "Australia/Perth";
  25613. case "W. Central Africa Standard Time": return "Africa/Lagos";
  25614. case "W. Europe Standard Time": return "Europe/Berlin";
  25615. case "West Asia Standard Time": return "Asia/Tashkent";
  25616. case "West Pacific Standard Time": return "Pacific/Port_Moresby";
  25617. case "Yakutsk Standard Time": return "Asia/Yakutsk";
  25618. default:
  25619. throw new DateTimeException(format("Could not find TZ Database name for: %s.", tzName));
  25620. }
  25621. }
  25622. unittest
  25623. {
  25624. version(testStdDateTime)
  25625. {
  25626. version(Windows)
  25627. {
  25628. static void testTZSuccess(string tzName)
  25629. {
  25630. scope(failure) writefln("TZName which threw: %s", tzName);
  25631. windowsTZNameToTZDatabaseName(tzName);
  25632. }
  25633. auto timeZones = WindowsTimeZone.getInstalledTZNames();
  25634. foreach(tzname; timeZones)
  25635. assertNotThrown!DateTimeException(testTZSuccess(tzname));
  25636. }
  25637. }
  25638. }
  25639. //==============================================================================
  25640. // Section with StopWatch and Benchmark Code.
  25641. //==============================================================================
  25642. /++
  25643. $(D StopWatch) measures time as precisely as possible.
  25644. This class uses a high-performance counter. On Windows systems, it uses
  25645. $(D QueryPerformanceCounter), and on Posix systems, it uses
  25646. $(D clock_gettime) if available, and $(D gettimeofday) otherwise.
  25647. But the precision of $(D StopWatch) differs from system to system. It is
  25648. impossible to for it to be the same from system to system since the precision
  25649. of the system clock varies from system to system, and other system-dependent
  25650. and situation-dependent stuff (such as the overhead of a context switch
  25651. between threads) can also affect $(D StopWatch)'s accuracy.
  25652. Examples:
  25653. --------------------
  25654. void foo()
  25655. {
  25656. StopWatch sw;
  25657. enum n = 100;
  25658. TickDuration[n] times;
  25659. TickDuration last = TickDuration.from!"seconds"(0);
  25660. foreach(i; 0..n)
  25661. {
  25662. sw.start(); //start/resume mesuring.
  25663. foreach(unused; 0..1_000_000)
  25664. bar();
  25665. sw.stop(); //stop/pause measuring.
  25666. //Return value of peek() after having stopped are the always same.
  25667. writeln((i + 1) * 1_000_000, " times done, lap time: ",
  25668. sw.peek().msecs, "[ms]");
  25669. times[i] = sw.peek() - last;
  25670. last = sw.peek();
  25671. }
  25672. real sum = 0;
  25673. // When you want to know the number of seconds,
  25674. // you can use properties of TickDuration.
  25675. // (seconds, mseconds, useconds, hnsecs)
  25676. foreach(t; times)
  25677. sum += t.hnsecs;
  25678. writeln("Average time: ", sum/n, " hnsecs");
  25679. }
  25680. --------------------
  25681. +/
  25682. @safe struct StopWatch
  25683. {
  25684. public:
  25685. //Verify Example
  25686. @safe unittest
  25687. {
  25688. void writeln(S...)(S args){}
  25689. static void bar() {}
  25690. StopWatch sw;
  25691. enum n = 100;
  25692. TickDuration[n] times;
  25693. TickDuration last = TickDuration.from!"seconds"(0);
  25694. foreach(i; 0..n)
  25695. {
  25696. sw.start(); //start/resume mesuring.
  25697. foreach(unused; 0..1_000_000)
  25698. bar();
  25699. sw.stop(); //stop/pause measuring.
  25700. //Return value of peek() after having stopped are the always same.
  25701. writeln((i + 1) * 1_000_000, " times done, lap time: ",
  25702. sw.peek().msecs, "[ms]");
  25703. times[i] = sw.peek() - last;
  25704. last = sw.peek();
  25705. }
  25706. real sum = 0;
  25707. // When you want to know the number of seconds,
  25708. // you can use properties of TickDuration.
  25709. // (seconds, mseconds, useconds, hnsecs)
  25710. foreach(t; times)
  25711. sum += t.hnsecs;
  25712. writeln("Average time: ", sum/n, " hnsecs");
  25713. }
  25714. /++
  25715. Auto start with constructor.
  25716. +/
  25717. this(AutoStart autostart)
  25718. {
  25719. if(autostart)
  25720. start();
  25721. }
  25722. version(testStdDateTime) @safe unittest
  25723. {
  25724. auto sw = StopWatch(AutoStart.yes);
  25725. sw.stop();
  25726. }
  25727. ///
  25728. bool opEquals(const ref StopWatch rhs) const pure nothrow
  25729. {
  25730. return _timeStart == rhs._timeStart &&
  25731. _timeMeasured == rhs._timeMeasured;
  25732. }
  25733. /++
  25734. Resets the stop watch.
  25735. +/
  25736. void reset()
  25737. {
  25738. if(_flagStarted)
  25739. {
  25740. // Set current system time if StopWatch is measuring.
  25741. _timeStart = Clock.currSystemTick;
  25742. }
  25743. else
  25744. {
  25745. // Set zero if StopWatch is not measuring.
  25746. _timeStart.length = 0;
  25747. }
  25748. _timeMeasured.length = 0;
  25749. }
  25750. version(testStdDateTime) @safe unittest
  25751. {
  25752. StopWatch sw;
  25753. sw.start();
  25754. sw.stop();
  25755. sw.reset();
  25756. assert(sw.peek().to!("seconds", real) == 0);
  25757. }
  25758. /++
  25759. Starts the stop watch.
  25760. +/
  25761. void start()
  25762. {
  25763. assert(!_flagStarted);
  25764. StopWatch sw;
  25765. _flagStarted = true;
  25766. _timeStart = Clock.currSystemTick;
  25767. }
  25768. version(testStdDateTime) @trusted unittest
  25769. {
  25770. StopWatch sw;
  25771. sw.start();
  25772. auto t1 = sw.peek();
  25773. bool doublestart = true;
  25774. try
  25775. sw.start();
  25776. catch(AssertError e)
  25777. doublestart = false;
  25778. assert(!doublestart);
  25779. sw.stop();
  25780. assert((t1 - sw.peek()).to!("seconds", real) <= 0);
  25781. }
  25782. /++
  25783. Stops the stop watch.
  25784. +/
  25785. void stop()
  25786. {
  25787. assert(_flagStarted);
  25788. _flagStarted = false;
  25789. _timeMeasured += Clock.currSystemTick - _timeStart;
  25790. }
  25791. version(testStdDateTime) @trusted unittest
  25792. {
  25793. StopWatch sw;
  25794. sw.start();
  25795. sw.stop();
  25796. auto t1 = sw.peek();
  25797. bool doublestop = true;
  25798. try
  25799. sw.stop();
  25800. catch(AssertError e)
  25801. doublestop = false;
  25802. assert(!doublestop);
  25803. assert((t1 - sw.peek()).to!("seconds", real) == 0);
  25804. }
  25805. /++
  25806. Peek at the amount of time which has passed since the stop watch was
  25807. started.
  25808. +/
  25809. TickDuration peek() const
  25810. {
  25811. if(_flagStarted)
  25812. return Clock.currSystemTick - _timeStart + _timeMeasured;
  25813. return _timeMeasured;
  25814. }
  25815. version(testStdDateTime) @safe unittest
  25816. {
  25817. StopWatch sw;
  25818. sw.start();
  25819. auto t1 = sw.peek();
  25820. sw.stop();
  25821. auto t2 = sw.peek();
  25822. auto t3 = sw.peek();
  25823. assert(t1 <= t2);
  25824. assert(t2 == t3);
  25825. }
  25826. private:
  25827. // true if observing.
  25828. bool _flagStarted = false;
  25829. // TickDuration at the time of StopWatch starting measurement.
  25830. TickDuration _timeStart;
  25831. // Total time that StopWatch ran.
  25832. TickDuration _timeMeasured;
  25833. }
  25834. // workaround for bug4886
  25835. @safe size_t lengthof(aliases...)() pure nothrow
  25836. {
  25837. return aliases.length;
  25838. }
  25839. /++
  25840. Benchmarks code for speed assessment and comparison.
  25841. Params:
  25842. fun = aliases of callable objects (e.g. function names). Each should
  25843. take no arguments.
  25844. n = The number of times each function is to be executed.
  25845. Returns:
  25846. The amount of time (as a $(CXREF time, TickDuration)) that it took to
  25847. call each function $(D n) times. The first value is the length of time
  25848. that it took to call $(D fun[0]) $(D n) times. The second value is the
  25849. length of time it took to call $(D fun[1]) $(D n) times. Etc.
  25850. Examples:
  25851. --------------------
  25852. int a;
  25853. void f0() {}
  25854. void f1() {auto b = a;}
  25855. void f2() {auto b = to!(string)(a);}
  25856. auto r = benchmark!(f0, f1, f2)(10_000_000);
  25857. writefln("Milliseconds to call fun[0] n times: %s", r[0].to!("msecs", int));
  25858. --------------------
  25859. +/
  25860. @safe TickDuration[lengthof!(fun)()] benchmark(fun...)(uint n)
  25861. if(areAllSafe!fun)
  25862. {
  25863. TickDuration[lengthof!(fun)()] result;
  25864. StopWatch sw;
  25865. sw.start();
  25866. foreach(i, unused; fun)
  25867. {
  25868. sw.reset();
  25869. foreach(j; 0 .. n)
  25870. fun[i]();
  25871. result[i] = sw.peek();
  25872. }
  25873. return result;
  25874. }
  25875. /++ Ditto +/
  25876. TickDuration[lengthof!(fun)()] benchmark(fun...)(uint times)
  25877. if(!areAllSafe!fun)
  25878. {
  25879. TickDuration[lengthof!(fun)()] result;
  25880. StopWatch sw;
  25881. sw.start();
  25882. foreach(i, unused; fun)
  25883. {
  25884. sw.reset();
  25885. foreach(j; 0 .. times)
  25886. fun[i]();
  25887. result[i] = sw.peek();
  25888. }
  25889. return result;
  25890. }
  25891. //Verify Examples.
  25892. version(testStdDateTime) unittest
  25893. {
  25894. void writefln(S...)(S args){}
  25895. int a;
  25896. void f0() {}
  25897. void f1() {auto b = a;}
  25898. void f2() {auto b = to!(string)(a);}
  25899. auto r = benchmark!(f0, f1, f2)(10_000_000);
  25900. writefln("Milliseconds to call fun[0] n times: %s", r[0].to!("msecs", int));
  25901. }
  25902. version(testStdDateTime) @safe unittest
  25903. {
  25904. int a;
  25905. void f0() {}
  25906. //void f1() {auto b = to!(string)(a);}
  25907. void f2() {auto b = (a);}
  25908. auto r = benchmark!(f0, f2)(100);
  25909. }
  25910. /++
  25911. Return value of benchmark with two functions comparing.
  25912. +/
  25913. @safe struct ComparingBenchmarkResult
  25914. {
  25915. /++
  25916. Evaluation value
  25917. This returns the evaluation value of performance as the ratio of
  25918. baseFunc's time over targetFunc's time. If performance is high, this
  25919. returns a high value.
  25920. +/
  25921. @property real point() const pure nothrow
  25922. {
  25923. return _baseTime.length / cast(const real)_targetTime.length;
  25924. }
  25925. /++
  25926. The time required of the base function
  25927. +/
  25928. @property public TickDuration baseTime() const pure nothrow
  25929. {
  25930. return _baseTime;
  25931. }
  25932. /++
  25933. The time required of the target function
  25934. +/
  25935. @property public TickDuration targetTime() const pure nothrow
  25936. {
  25937. return _targetTime;
  25938. }
  25939. private:
  25940. this(TickDuration baseTime, TickDuration targetTime) pure nothrow
  25941. {
  25942. _baseTime = baseTime;
  25943. _targetTime = targetTime;
  25944. }
  25945. TickDuration _baseTime;
  25946. TickDuration _targetTime;
  25947. }
  25948. /++
  25949. Benchmark with two functions comparing.
  25950. Params:
  25951. baseFunc = The function to become the base of the speed.
  25952. targetFunc = The function that wants to measure speed.
  25953. times = The number of times each function is to be executed.
  25954. Examples:
  25955. --------------------
  25956. void f1() {
  25957. // ...
  25958. }
  25959. void f2() {
  25960. // ...
  25961. }
  25962. void main() {
  25963. auto b = comparingBenchmark!(f1, f2, 0x80);
  25964. writeln(b.point);
  25965. }
  25966. --------------------
  25967. +/
  25968. @safe ComparingBenchmarkResult comparingBenchmark(alias baseFunc,
  25969. alias targetFunc,
  25970. int times = 0xfff)()
  25971. if(isSafe!baseFunc && isSafe!targetFunc)
  25972. {
  25973. auto t = benchmark!(baseFunc, targetFunc)(times);
  25974. return ComparingBenchmarkResult(t[0], t[1]);
  25975. }
  25976. /++ Ditto +/
  25977. ComparingBenchmarkResult comparingBenchmark(alias baseFunc,
  25978. alias targetFunc,
  25979. int times = 0xfff)()
  25980. if(!isSafe!baseFunc || !isSafe!targetFunc)
  25981. {
  25982. auto t = benchmark!(baseFunc, targetFunc)(times);
  25983. return ComparingBenchmarkResult(t[0], t[1]);
  25984. }
  25985. version(testStdDateTime) @safe unittest
  25986. {
  25987. void f1x() {}
  25988. void f2x() {}
  25989. @safe void f1o() {}
  25990. @safe void f2o() {}
  25991. auto b1 = comparingBenchmark!(f1o, f2o, 1); // OK
  25992. //static auto b2 = comparingBenchmark!(f1x, f2x, 1); // NG
  25993. }
  25994. version(testStdDateTime) unittest
  25995. {
  25996. void f1x() {}
  25997. void f2x() {}
  25998. @safe void f1o() {}
  25999. @safe void f2o() {}
  26000. auto b1 = comparingBenchmark!(f1o, f2o, 1); // OK
  26001. auto b2 = comparingBenchmark!(f1x, f2x, 1); // OK
  26002. }
  26003. //==============================================================================
  26004. // Section with public helper functions and templates.
  26005. //==============================================================================
  26006. /++
  26007. $(RED Deprecated. It will be removed in February 2012. This is only here to
  26008. help transition code which uses std.date to using std.datetime.)
  26009. Returns a $(D d_time) for the given $(D SysTime).
  26010. +/
  26011. deprecated long sysTimeToDTime(in SysTime sysTime)
  26012. {
  26013. return convert!("hnsecs", "msecs")(sysTime.stdTime - 621355968000000000L);
  26014. }
  26015. version(testStdDateTime) unittest
  26016. {
  26017. _assertPred!"=="(sysTimeToDTime(SysTime(DateTime(1970, 1, 1), UTC())),
  26018. 0);
  26019. _assertPred!"=="(sysTimeToDTime(SysTime(DateTime(1970, 1, 1), FracSec.from!"msecs"(1), UTC())),
  26020. 1);
  26021. _assertPred!"=="(sysTimeToDTime(SysTime(DateTime(1969, 12, 31, 23, 59, 59), FracSec.from!"msecs"(999), UTC())),
  26022. -1);
  26023. _assertPred!"=="(sysTimeToDTime(SysTime(DateTime(1970, 1, 2), UTC())),
  26024. 86_400_000);
  26025. _assertPred!"=="(sysTimeToDTime(SysTime(DateTime(1969, 12, 31), UTC())),
  26026. -86_400_000);
  26027. }
  26028. /++
  26029. $(RED Deprecated. It will be removed in February 2012. This is only here to
  26030. help transition code which uses std.date to using std.datetime.)
  26031. Returns a $(D SysTime) for the given $(D d_time).
  26032. +/
  26033. deprecated SysTime dTimeToSysTime(long dTime, immutable TimeZone tz = null)
  26034. {
  26035. immutable hnsecs = convert!("msecs", "hnsecs")(dTime) + 621355968000000000L;
  26036. return SysTime(hnsecs, tz);
  26037. }
  26038. version(testStdDateTime) unittest
  26039. {
  26040. _assertPred!"=="(dTimeToSysTime(0),
  26041. SysTime(DateTime(1970, 1, 1), UTC()));
  26042. _assertPred!"=="(dTimeToSysTime(1),
  26043. SysTime(DateTime(1970, 1, 1), FracSec.from!"msecs"(1), UTC()));
  26044. _assertPred!"=="(dTimeToSysTime(-1),
  26045. SysTime(DateTime(1969, 12, 31, 23, 59, 59), FracSec.from!"msecs"(999), UTC()));
  26046. _assertPred!"=="(dTimeToSysTime(86_400_000),
  26047. SysTime(DateTime(1970, 1, 2), UTC()));
  26048. _assertPred!"=="(dTimeToSysTime(-86_400_000),
  26049. SysTime(DateTime(1969, 12, 31), UTC()));
  26050. }
  26051. /++
  26052. Returns the absolute value of a duration.
  26053. +/
  26054. D abs(D)(D duration)
  26055. if(is(Unqual!D == Duration) ||
  26056. is(Unqual!D == TickDuration))
  26057. {
  26058. static if(is(Unqual!D == Duration))
  26059. return dur!"hnsecs"(std.math.abs(duration.total!"hnsecs"()));
  26060. else static if(is(Unqual!D == TickDuration))
  26061. return TickDuration(std.math.abs(duration.length));
  26062. else
  26063. static assert(0);
  26064. }
  26065. unittest
  26066. {
  26067. version(testStdDateTime)
  26068. {
  26069. _assertPred!"=="(abs(dur!"msecs"(5)), dur!"msecs"(5));
  26070. _assertPred!"=="(abs(dur!"msecs"(-5)), dur!"msecs"(5));
  26071. _assertPred!"=="(abs(TickDuration(17)), TickDuration(17));
  26072. _assertPred!"=="(abs(TickDuration(-17)), TickDuration(17));
  26073. }
  26074. }
  26075. /++
  26076. Whether the given type defines all of the necessary functions for it to
  26077. function as a time point.
  26078. +/
  26079. template isTimePoint(T)
  26080. {
  26081. enum isTimePoint = hasMin!T &&
  26082. hasMax!T &&
  26083. hasOverloadedOpBinaryWithDuration!T &&
  26084. hasOverloadedOpAssignWithDuration!T &&
  26085. hasOverloadedOpBinaryWithSelf!T;
  26086. }
  26087. unittest
  26088. {
  26089. version(testStdDateTime)
  26090. {
  26091. static assert(isTimePoint!(Date));
  26092. static assert(isTimePoint!(DateTime));
  26093. static assert(isTimePoint!(TimeOfDay));
  26094. static assert(isTimePoint!(SysTime));
  26095. static assert(isTimePoint!(const Date));
  26096. static assert(isTimePoint!(const DateTime));
  26097. static assert(isTimePoint!(const TimeOfDay));
  26098. static assert(isTimePoint!(const SysTime));
  26099. static assert(isTimePoint!(immutable Date));
  26100. static assert(isTimePoint!(immutable DateTime));
  26101. static assert(isTimePoint!(immutable TimeOfDay));
  26102. static assert(isTimePoint!(immutable SysTime));
  26103. }
  26104. }
  26105. /++
  26106. Whether the given Gregorian Year is a leap year.
  26107. Params:
  26108. year = The year to to be tested.
  26109. +/
  26110. static bool yearIsLeapYear(int year) pure nothrow
  26111. {
  26112. if(year % 400 == 0)
  26113. return true;
  26114. if(year % 100 == 0)
  26115. return false;
  26116. return year % 4 == 0;
  26117. }
  26118. version(testStdDateTime) unittest
  26119. {
  26120. foreach(year; [1, 2, 3, 5, 6, 7, 100, 200, 300, 500, 600, 700, 1998, 1999,
  26121. 2001, 2002, 2003, 2005, 2006, 2007, 2009, 2010, 2011])
  26122. {
  26123. assert(!yearIsLeapYear(year), format("year: %s.", year));
  26124. assert(!yearIsLeapYear(-year), format("year: %s.", year));
  26125. }
  26126. foreach(year; [0, 4, 8, 400, 800, 1600, 1996, 2000, 2004, 2008, 2012])
  26127. {
  26128. assert(yearIsLeapYear(year), format("year: %s.", year));
  26129. assert(yearIsLeapYear(-year), format("year: %s.", year));
  26130. }
  26131. }
  26132. /++
  26133. Converts a $(D time_t) (which uses midnight, January 1st, 1970 UTC as its
  26134. epoch and seconds as its units) to std time (which uses midnight,
  26135. January 1st, 1 A.D. UTC and hnsecs as its units).
  26136. Params:
  26137. unixTime = The $(D time_t) to convert.
  26138. +/
  26139. long unixTimeToStdTime(time_t unixTime) pure nothrow
  26140. {
  26141. return 621_355_968_000_000_000L + convert!("seconds", "hnsecs")(unixTime);
  26142. }
  26143. unittest
  26144. {
  26145. version(testStdDateTime)
  26146. {
  26147. _assertPred!"=="(unixTimeToStdTime(0), 621_355_968_000_000_000L); //Midnight, January 1st, 1970
  26148. _assertPred!"=="(unixTimeToStdTime(86_400), 621_355_968_000_000_000L + 864_000_000_000L); //Midnight, January 2nd, 1970
  26149. _assertPred!"=="(unixTimeToStdTime(-86_400), 621_355_968_000_000_000L - 864_000_000_000L); //Midnight, December 31st, 1969
  26150. _assertPred!"=="(unixTimeToStdTime(0), (Date(1970, 1, 1) - Date(1, 1, 1)).total!"hnsecs");
  26151. _assertPred!"=="(unixTimeToStdTime(0), (DateTime(1970, 1, 1) - DateTime(1, 1, 1)).total!"hnsecs");
  26152. }
  26153. }
  26154. /++
  26155. Converts std time (which uses midnight, January 1st, 1 A.D. UTC as its epoch
  26156. and hnsecs as its units) to $(D time_t) (which uses midnight, January 1st,
  26157. 1970 UTC as its epoch and seconds as its units). If $(D time_t) is 32 bits,
  26158. rather than 64, and the result can't fit in a 32-bit value, then the closest
  26159. value that can be held in 32 bits will be used (so $(D time_t.max) if it
  26160. goes over and $(D time_t.min) if it goes under).
  26161. Note:
  26162. While Windows systems require that $(D time_t) be non-negative (in spite
  26163. of $(D time_t) being signed), this function still returns negative
  26164. numbers on Windows, since it's more flexible to allow negative time_t
  26165. for those who need it. So, if you're on Windows and are using the
  26166. standard C functions or Win32 API functions which take a $(D time_t),
  26167. you may want to check whether the return value of
  26168. $(D stdTimeToUnixTime) is non-negative.
  26169. Params:
  26170. stdTime = The std time to convert.
  26171. +/
  26172. time_t stdTimeToUnixTime(long stdTime) pure nothrow
  26173. {
  26174. immutable unixTime = convert!("hnsecs", "seconds")(stdTime - 621_355_968_000_000_000L);
  26175. static if(time_t.sizeof >= long.sizeof)
  26176. return cast(time_t)unixTime;
  26177. else
  26178. {
  26179. if(unixTime > 0)
  26180. {
  26181. if(unixTime > time_t.max)
  26182. return time_t.max;
  26183. return cast(time_t)unixTime;
  26184. }
  26185. if(unixTime < time_t.min)
  26186. return time_t.min;
  26187. return cast(time_t)unixTime;
  26188. }
  26189. }
  26190. unittest
  26191. {
  26192. version(testStdDateTime)
  26193. {
  26194. _assertPred!"=="(stdTimeToUnixTime(621_355_968_000_000_000L), 0); //Midnight, January 1st, 1970
  26195. _assertPred!"=="(stdTimeToUnixTime(621_355_968_000_000_000L + 864_000_000_000L), 86_400); //Midnight, January 2nd, 1970
  26196. _assertPred!"=="(stdTimeToUnixTime(621_355_968_000_000_000L - 864_000_000_000L), -86_400); //Midnight, December 31st, 1969
  26197. _assertPred!"=="(stdTimeToUnixTime((Date(1970, 1, 1) - Date(1, 1, 1)).total!"hnsecs"), 0);
  26198. _assertPred!"=="(stdTimeToUnixTime((DateTime(1970, 1, 1) - DateTime(1, 1, 1)).total!"hnsecs"), 0);
  26199. }
  26200. }
  26201. version(StdDdoc)
  26202. {
  26203. version(Windows) {}
  26204. else
  26205. {
  26206. alias void* SYSTEMTIME;
  26207. alias void* FILETIME;
  26208. }
  26209. /++
  26210. $(BLUE This function is Windows-Only.)
  26211. Converts a $(D SYSTEMTIME) struct to a $(D SysTime).
  26212. Params:
  26213. st = The $(D SYSTEMTIME) struct to convert.
  26214. tz = The time zone that the time in the $(D SYSTEMTIME) struct is
  26215. assumed to be (if the $(D SYSTEMTIME) was supplied by a Windows
  26216. system call, the $(D SYSTEMTIME) will either be in local time
  26217. or UTC, depending on the call).
  26218. Throws:
  26219. $(D DateTimeException) if the given $(D SYSTEMTIME) will not fit in
  26220. a $(D SysTime), which is highly unlikely to happen given that
  26221. $(D SysTime.max) is in 29,228 A.D. and the maximum $(D SYSTEMTIME)
  26222. is in 30,827 A.D.
  26223. +/
  26224. SysTime SYSTEMTIMEToSysTime(const SYSTEMTIME* st, immutable TimeZone tz = LocalTime());
  26225. /++
  26226. $(BLUE This function is Windows-Only.)
  26227. Converts a $(D SysTime) to a $(D SYSTEMTIME) struct.
  26228. The $(D SYSTEMTIME) which is returned will be set using the given
  26229. $(D SysTime)'s time zone, so if you want the $(D SYSTEMTIME) to be in
  26230. UTC, set the $(D SysTime)'s time zone to UTC.
  26231. Params:
  26232. sysTime = The $(D SysTime) to convert.
  26233. Throws:
  26234. $(D DateTimeException) if the given $(D SysTime) will not fit in a
  26235. $(D SYSTEMTIME). This will only happen if the $(D SysTime)'s date is
  26236. prior to 1601 A.D.
  26237. +/
  26238. SYSTEMTIME SysTimeToSYSTEMTIME(in SysTime sysTime);
  26239. /++
  26240. $(BLUE This function is Windows-Only.)
  26241. Converts a $(D FILETIME) struct to a $(D SysTime).
  26242. Params:
  26243. ft = The $(D FILETIME) struct to convert.
  26244. tz = The time zone that the $(D SysTime) will be in ($(D FILETIME)s
  26245. are in UTC).
  26246. Throws:
  26247. $(D DateTimeException) if the given $(D FILETIME) will not fit in a
  26248. $(D SysTime) or if the $(D FILETIME) cannot be converted to a
  26249. $(D SYSTEMTIME).
  26250. +/
  26251. SysTime FILETIMEToSysTime(const FILETIME* ft, immutable TimeZone tz = LocalTime());
  26252. /++
  26253. $(BLUE This function is Windows-Only.)
  26254. Converts a $(D SysTime) to a $(D FILETIME) struct.
  26255. $(D FILETIME)s are always in UTC.
  26256. Params:
  26257. sysTime = The $(D SysTime) to convert.
  26258. Throws:
  26259. $(D DateTimeException) if the given $(D SysTime) will not fit in a
  26260. $(D FILETIME).
  26261. +/
  26262. FILETIME SysTimeToFILETIME(SysTime sysTime);
  26263. }
  26264. else version(Windows)
  26265. {
  26266. SysTime SYSTEMTIMEToSysTime(const SYSTEMTIME* st, immutable TimeZone tz = LocalTime())
  26267. {
  26268. const max = SysTime.max;
  26269. static void throwLaterThanMax()
  26270. {
  26271. throw new DateTimeException("The given SYSTEMTIME is for a date greater than SysTime.max.");
  26272. }
  26273. if(st.wYear > max.year)
  26274. throwLaterThanMax();
  26275. else if(st.wYear == max.year)
  26276. {
  26277. if(st.wMonth > max.month)
  26278. throwLaterThanMax();
  26279. else if(st.wMonth == max.month)
  26280. {
  26281. if(st.wDay > max.day)
  26282. throwLaterThanMax();
  26283. else if(st.wDay == max.day)
  26284. {
  26285. if(st.wHour > max.hour)
  26286. throwLaterThanMax();
  26287. else if(st.wHour == max.hour)
  26288. {
  26289. if(st.wMinute > max.minute)
  26290. throwLaterThanMax();
  26291. else if(st.wMinute == max.minute)
  26292. {
  26293. if(st.wSecond > max.second)
  26294. throwLaterThanMax();
  26295. else if(st.wSecond == max.second)
  26296. {
  26297. if(st.wMilliseconds > max.fracSec.msecs)
  26298. throwLaterThanMax();
  26299. }
  26300. }
  26301. }
  26302. }
  26303. }
  26304. }
  26305. auto dt = DateTime(st.wYear, st.wMonth, st.wDay,
  26306. st.wHour, st.wMinute, st.wSecond);
  26307. return SysTime(dt, FracSec.from!"msecs"(st.wMilliseconds), tz);
  26308. }
  26309. unittest
  26310. {
  26311. version(testStdDateTime)
  26312. {
  26313. auto sysTime = Clock.currTime(UTC());
  26314. SYSTEMTIME st = void;
  26315. GetSystemTime(&st);
  26316. auto converted = SYSTEMTIMEToSysTime(&st, UTC());
  26317. _assertPred!"<="(abs((converted - sysTime)),
  26318. dur!"seconds"(2));
  26319. }
  26320. }
  26321. SYSTEMTIME SysTimeToSYSTEMTIME(in SysTime sysTime)
  26322. {
  26323. immutable dt = cast(DateTime)sysTime;
  26324. if(dt.year < 1601)
  26325. throw new DateTimeException("SYSTEMTIME cannot hold dates prior to the year 1601.");
  26326. SYSTEMTIME st;
  26327. st.wYear = dt.year;
  26328. st.wMonth = dt.month;
  26329. st.wDayOfWeek = dt.dayOfWeek;
  26330. st.wDay = dt.day;
  26331. st.wHour = dt.hour;
  26332. st.wMinute = dt.minute;
  26333. st.wSecond = dt.second;
  26334. st.wMilliseconds = cast(ushort)sysTime.fracSec.msecs;
  26335. return st;
  26336. }
  26337. unittest
  26338. {
  26339. version(testStdDateTime)
  26340. {
  26341. SYSTEMTIME st = void;
  26342. GetSystemTime(&st);
  26343. auto sysTime = SYSTEMTIMEToSysTime(&st, UTC());
  26344. SYSTEMTIME result = SysTimeToSYSTEMTIME(sysTime);
  26345. _assertPred!"=="(st.wYear, result.wYear);
  26346. _assertPred!"=="(st.wMonth, result.wMonth);
  26347. _assertPred!"=="(st.wDayOfWeek, result.wDayOfWeek);
  26348. _assertPred!"=="(st.wDay, result.wDay);
  26349. _assertPred!"=="(st.wHour, result.wHour);
  26350. _assertPred!"=="(st.wMinute, result.wMinute);
  26351. _assertPred!"=="(st.wSecond, result.wSecond);
  26352. _assertPred!"=="(st.wMilliseconds, result.wMilliseconds);
  26353. }
  26354. }
  26355. SysTime FILETIMEToSysTime(const FILETIME* ft, immutable TimeZone tz = LocalTime())
  26356. {
  26357. SYSTEMTIME st = void;
  26358. if(!FileTimeToSystemTime(ft, &st))
  26359. throw new DateTimeException("FileTimeToSystemTime() failed.");
  26360. auto sysTime = SYSTEMTIMEToSysTime(&st, UTC());
  26361. sysTime.timezone = tz;
  26362. return sysTime;
  26363. }
  26364. unittest
  26365. {
  26366. version(testStdDateTime)
  26367. {
  26368. auto sysTime = Clock.currTime(UTC());
  26369. SYSTEMTIME st = void;
  26370. GetSystemTime(&st);
  26371. FILETIME ft = void;
  26372. SystemTimeToFileTime(&st, &ft);
  26373. auto converted = FILETIMEToSysTime(&ft);
  26374. _assertPred!"<="(abs((converted - sysTime)),
  26375. dur!"seconds"(2));
  26376. }
  26377. }
  26378. FILETIME SysTimeToFILETIME(SysTime sysTime)
  26379. {
  26380. SYSTEMTIME st = SysTimeToSYSTEMTIME(sysTime.toUTC());
  26381. FILETIME ft = void;
  26382. SystemTimeToFileTime(&st, &ft);
  26383. return ft;
  26384. }
  26385. unittest
  26386. {
  26387. version(testStdDateTime)
  26388. {
  26389. SYSTEMTIME st = void;
  26390. GetSystemTime(&st);
  26391. FILETIME ft = void;
  26392. SystemTimeToFileTime(&st, &ft);
  26393. auto sysTime = FILETIMEToSysTime(&ft, UTC());
  26394. FILETIME result = SysTimeToFILETIME(sysTime);
  26395. _assertPred!"=="(ft.dwLowDateTime, result.dwLowDateTime);
  26396. _assertPred!"=="(ft.dwHighDateTime, result.dwHighDateTime);
  26397. }
  26398. }
  26399. }
  26400. /++
  26401. Type representing the DOS file date/time format.
  26402. +/
  26403. alias uint DosFileTime;
  26404. /++
  26405. Converts from DOS file date/time to $(D SysTime).
  26406. Params:
  26407. dft = The DOS file time to convert.
  26408. tz = The time zone which the DOS file time is assumed to be in.
  26409. Throws:
  26410. $(D DateTimeException) if the $(D DosFileTime) is invalid.
  26411. +/
  26412. SysTime DosFileTimeToSysTime(DosFileTime dft, immutable TimeZone tz = LocalTime())
  26413. {
  26414. uint dt = cast(uint)dft;
  26415. if(dt == 0)
  26416. throw new DateTimeException("Invalid DosFileTime.");
  26417. int year = ((dt >> 25) & 0x7F) + 1980;
  26418. int month = ((dt >> 21) & 0x0F); // 1..12
  26419. int dayOfMonth = ((dt >> 16) & 0x1F); // 1..31
  26420. int hour = (dt >> 11) & 0x1F; // 0..23
  26421. int minute = (dt >> 5) & 0x3F; // 0..59
  26422. int second = (dt << 1) & 0x3E; // 0..58 (in 2 second increments)
  26423. SysTime sysTime = void;
  26424. try
  26425. return SysTime(DateTime(year, month, dayOfMonth, hour, minute, second), tz);
  26426. catch(DateTimeException dte)
  26427. throw new DateTimeException("Invalid DosFileTime", __FILE__, __LINE__, dte);
  26428. }
  26429. unittest
  26430. {
  26431. version(testStdDateTime)
  26432. {
  26433. _assertPred!"=="(DosFileTimeToSysTime(0b00000000001000010000000000000000),
  26434. SysTime(DateTime(1980, 1, 1, 0, 0, 0)));
  26435. _assertPred!"=="(DosFileTimeToSysTime(0b11111111100111111011111101111101),
  26436. SysTime(DateTime(2107, 12, 31, 23, 59, 58)));
  26437. _assertPred!"=="(DosFileTimeToSysTime(0x3E3F8456),
  26438. SysTime(DateTime(2011, 1, 31, 16, 34, 44)));
  26439. }
  26440. }
  26441. /++
  26442. Converts from $(D SysTime) to DOS file date/time.
  26443. Params:
  26444. sysTime = The $(D SysTime) to convert.
  26445. Throws:
  26446. $(D DateTimeException) if the given $(D SysTime) cannot be converted to
  26447. a $(D DosFileTime).
  26448. +/
  26449. DosFileTime SysTimeToDosFileTime(SysTime sysTime)
  26450. {
  26451. auto dateTime = cast(DateTime)sysTime;
  26452. if(dateTime.year < 1980)
  26453. throw new DateTimeException("DOS File Times cannot hold dates prior to 1980.");
  26454. if(dateTime.year > 2107)
  26455. throw new DateTimeException("DOS File Times cannot hold dates passed 2107.");
  26456. uint retval = 0;
  26457. retval = (dateTime.year - 1980) << 25;
  26458. retval |= (dateTime.month & 0x0F) << 21;
  26459. retval |= (dateTime.day & 0x1F) << 16;
  26460. retval |= (dateTime.hour & 0x1F) << 11;
  26461. retval |= (dateTime.minute & 0x3F) << 5;
  26462. retval |= (dateTime.second >> 1) & 0x1F;
  26463. return cast(DosFileTime)retval;
  26464. }
  26465. unittest
  26466. {
  26467. version(testStdDateTime)
  26468. {
  26469. _assertPred!"=="(SysTimeToDosFileTime(SysTime(DateTime(1980, 1, 1, 0, 0, 0))),
  26470. 0b00000000001000010000000000000000);
  26471. _assertPred!"=="(SysTimeToDosFileTime(SysTime(DateTime(2107, 12, 31, 23, 59, 58))),
  26472. 0b11111111100111111011111101111101);
  26473. _assertPred!"=="(SysTimeToDosFileTime(SysTime(DateTime(2011, 1, 31, 16, 34, 44))),
  26474. 0x3E3F8456);
  26475. }
  26476. }
  26477. /++
  26478. Whether all of the given strings are valid units of time.
  26479. $(D "nsecs") is not considered a valid unit of time. Nothing in std.datetime
  26480. can handle precision greater than hnsecs, and the few functions in core.time
  26481. which deal with "nsecs" deal with it explicitly.
  26482. +/
  26483. bool validTimeUnits(string[] units...)
  26484. {
  26485. foreach(str; units)
  26486. {
  26487. if(!canFind(timeStrings.dup, str))
  26488. return false;
  26489. }
  26490. return true;
  26491. }
  26492. /++
  26493. Compares two time unit strings. $(D "years") are the largest units and
  26494. $(D "hnsecs") are the smallest.
  26495. Returns:
  26496. $(BOOKTABLE,
  26497. $(TR $(TD this &lt; rhs) $(TD &lt; 0))
  26498. $(TR $(TD this == rhs) $(TD 0))
  26499. $(TR $(TD this &gt; rhs) $(TD &gt; 0))
  26500. )
  26501. Throws:
  26502. $(D DateTimeException) if either of the given strings is not a valid
  26503. time unit string.
  26504. +/
  26505. int cmpTimeUnits(string lhs, string rhs)
  26506. {
  26507. auto tstrings = timeStrings.dup;
  26508. immutable indexOfLHS = std.algorithm.countUntil(tstrings, lhs);
  26509. immutable indexOfRHS = std.algorithm.countUntil(tstrings, rhs);
  26510. enforce(indexOfLHS != -1, format("%s is not a valid TimeString", lhs));
  26511. enforce(indexOfRHS != -1, format("%s is not a valid TimeString", rhs));
  26512. if(indexOfLHS < indexOfRHS)
  26513. return -1;
  26514. if(indexOfLHS > indexOfRHS)
  26515. return 1;
  26516. return 0;
  26517. }
  26518. unittest
  26519. {
  26520. version(testStdDateTime)
  26521. {
  26522. foreach(i, outerUnits; timeStrings)
  26523. {
  26524. _assertPred!"=="(cmpTimeUnits(outerUnits, outerUnits), 0);
  26525. //For some reason, $ won't compile.
  26526. foreach(innerUnits; timeStrings[i+1 .. timeStrings.length])
  26527. _assertPred!"=="(cmpTimeUnits(outerUnits, innerUnits), -1);
  26528. }
  26529. foreach(i, outerUnits; timeStrings)
  26530. {
  26531. foreach(innerUnits; timeStrings[0 .. i])
  26532. _assertPred!"=="(cmpTimeUnits(outerUnits, innerUnits), 1);
  26533. }
  26534. }
  26535. }
  26536. /++
  26537. Compares two time unit strings at compile time. $(D "years") are the largest
  26538. units and $(D "hnsecs") are the smallest.
  26539. This template is used instead of $(D cmpTimeUnits) because exceptions
  26540. can't be thrown at compile time and $(D cmpTimeUnits) must enforce that
  26541. the strings it's given are valid time unit strings. This template uses a
  26542. template constraint instead.
  26543. Returns:
  26544. $(BOOKTABLE,
  26545. $(TR $(TD this &lt; rhs) $(TD &lt; 0))
  26546. $(TR $(TD this == rhs) $(TD 0))
  26547. $(TR $(TD this &gt; rhs) $(TD &gt; 0))
  26548. )
  26549. +/
  26550. template CmpTimeUnits(string lhs, string rhs)
  26551. if(validTimeUnits(lhs, rhs))
  26552. {
  26553. enum CmpTimeUnits = cmpTimeUnitsCTFE(lhs, rhs);
  26554. }
  26555. /+
  26556. Helper function for $(D CmpTimeUnits).
  26557. +/
  26558. private int cmpTimeUnitsCTFE(string lhs, string rhs)
  26559. {
  26560. auto tstrings = timeStrings.dup;
  26561. immutable indexOfLHS = std.algorithm.countUntil(tstrings, lhs);
  26562. immutable indexOfRHS = std.algorithm.countUntil(tstrings, rhs);
  26563. if(indexOfLHS < indexOfRHS)
  26564. return -1;
  26565. if(indexOfLHS > indexOfRHS)
  26566. return 1;
  26567. return 0;
  26568. }
  26569. unittest
  26570. {
  26571. version(testStdDateTime)
  26572. {
  26573. static string genTest(size_t index)
  26574. {
  26575. auto currUnits = timeStrings[index];
  26576. auto test = `_assertPred!"=="(CmpTimeUnits!("` ~ currUnits ~ `", "` ~ currUnits ~ `"), 0); `;
  26577. //For some reason, $ won't compile.
  26578. foreach(units; timeStrings[index + 1 .. timeStrings.length])
  26579. test ~= `_assertPred!"=="(CmpTimeUnits!("` ~ currUnits ~ `", "` ~ units ~ `"), -1); `;
  26580. foreach(units; timeStrings[0 .. index])
  26581. test ~= `_assertPred!"=="(CmpTimeUnits!("` ~ currUnits ~ `", "` ~ units ~ `"), 1); `;
  26582. return test;
  26583. }
  26584. mixin(genTest(0));
  26585. mixin(genTest(1));
  26586. mixin(genTest(2));
  26587. mixin(genTest(3));
  26588. mixin(genTest(4));
  26589. mixin(genTest(5));
  26590. mixin(genTest(6));
  26591. mixin(genTest(7));
  26592. mixin(genTest(8));
  26593. mixin(genTest(9));
  26594. }
  26595. }
  26596. /++
  26597. Returns whether the given value is valid for the given unit type when in a
  26598. time point. Naturally, a duration is not held to a particular range, but
  26599. the values in a time point are (e.g. a month must be in the range of
  26600. 1 - 12 inclusive).
  26601. Params:
  26602. units = The units of time to validate.
  26603. value = The number to validate.
  26604. Examples:
  26605. --------------------
  26606. assert(valid!"hours"(12));
  26607. assert(!valid!"hours"(32));
  26608. assert(valid!"months"(12));
  26609. assert(!valid!"months"(13));
  26610. --------------------
  26611. +/
  26612. bool valid(string units)(int value) pure nothrow
  26613. if(units == "months" ||
  26614. units == "hours" ||
  26615. units == "minutes" ||
  26616. units == "seconds")
  26617. {
  26618. static if(units == "months")
  26619. return value >= Month.jan && value <= Month.dec;
  26620. else static if(units == "hours")
  26621. return value >= 0 && value <= TimeOfDay.maxHour;
  26622. else static if(units == "minutes")
  26623. return value >= 0 && value <= TimeOfDay.maxMinute;
  26624. else static if(units == "seconds")
  26625. return value >= 0 && value <= TimeOfDay.maxSecond;
  26626. }
  26627. unittest
  26628. {
  26629. version(testStdDateTime)
  26630. {
  26631. //Verify Examples.
  26632. assert(valid!"hours"(12));
  26633. assert(!valid!"hours"(32));
  26634. assert(valid!"months"(12));
  26635. assert(!valid!"months"(13));
  26636. }
  26637. }
  26638. /++
  26639. Returns whether the given day is valid for the given year and month.
  26640. Params:
  26641. units = The units of time to validate.
  26642. year = The year of the day to validate.
  26643. month = The month of the day to validate.
  26644. day = The day to validate.
  26645. +/
  26646. bool valid(string units)(int year, int month, int day) pure nothrow
  26647. if(units == "days")
  26648. {
  26649. return day > 0 && day <= maxDay(year, month);
  26650. }
  26651. /++
  26652. Params:
  26653. units = The units of time to validate.
  26654. value = The number to validate.
  26655. file = The file that the $(D DateTimeException) will list if thrown.
  26656. line = The line number that the $(D DateTimeException) will list if
  26657. thrown.
  26658. Throws:
  26659. $(D DateTimeException) if $(D valid!units(value)) is false.
  26660. +/
  26661. void enforceValid(string units)(int value, string file = __FILE__, size_t line = __LINE__) pure
  26662. if(units == "months" ||
  26663. units == "hours" ||
  26664. units == "minutes" ||
  26665. units == "seconds")
  26666. {
  26667. static if(units == "months")
  26668. {
  26669. if(!valid!units(value))
  26670. throw new DateTimeException(numToString(value) ~ " is not a valid month of the year.", file, line);
  26671. }
  26672. else static if(units == "hours")
  26673. {
  26674. if(!valid!units(value))
  26675. throw new DateTimeException(numToString(value) ~ " is not a valid hour of the day.", file, line);
  26676. }
  26677. else static if(units == "minutes")
  26678. {
  26679. if(!valid!units(value))
  26680. throw new DateTimeException(numToString(value) ~ " is not a valid minute of an hour.", file, line);
  26681. }
  26682. else static if(units == "seconds")
  26683. {
  26684. if(!valid!units(value))
  26685. throw new DateTimeException(numToString(value) ~ " is not a valid second of a minute.", file, line);
  26686. }
  26687. }
  26688. /++
  26689. Params:
  26690. units = The units of time to validate.
  26691. year = The year of the day to validate.
  26692. month = The month of the day to validate.
  26693. day = The day to validate.
  26694. file = The file that the $(D DateTimeException) will list if thrown.
  26695. line = The line number that the $(D DateTimeException) will list if
  26696. thrown.
  26697. Throws:
  26698. $(D DateTimeException) if $(D valid!"days"(year, month, day)) is false.
  26699. +/
  26700. void enforceValid(string units)(int year, Month month, int day, string file = __FILE__, size_t line = __LINE__) pure
  26701. if(units == "days")
  26702. {
  26703. if(!valid!"days"(year, month, day))
  26704. {
  26705. throw new DateTimeException(numToString(day) ~
  26706. " is not a valid day in " ~
  26707. monthToString(month) ~
  26708. " in " ~
  26709. numToString(year), file, line);
  26710. }
  26711. }
  26712. /++
  26713. Returns the number of months from the current months of the year to the
  26714. given month of the year. If they are the same, then the result is 0.
  26715. Params:
  26716. currMonth = The current month of the year.
  26717. month = The month of the year to get the number of months to.
  26718. +/
  26719. static int monthsToMonth(int currMonth, int month) pure
  26720. {
  26721. enforceValid!"months"(currMonth);
  26722. enforceValid!"months"(month);
  26723. if(currMonth == month)
  26724. return 0;
  26725. if(currMonth < month)
  26726. return month - currMonth;
  26727. return (Month.dec - currMonth) + month;
  26728. }
  26729. unittest
  26730. {
  26731. version(testStdDateTime)
  26732. {
  26733. _assertPred!"=="(monthsToMonth(Month.jan, Month.jan), 0);
  26734. _assertPred!"=="(monthsToMonth(Month.jan, Month.feb), 1);
  26735. _assertPred!"=="(monthsToMonth(Month.jan, Month.mar), 2);
  26736. _assertPred!"=="(monthsToMonth(Month.jan, Month.apr), 3);
  26737. _assertPred!"=="(monthsToMonth(Month.jan, Month.may), 4);
  26738. _assertPred!"=="(monthsToMonth(Month.jan, Month.jun), 5);
  26739. _assertPred!"=="(monthsToMonth(Month.jan, Month.jul), 6);
  26740. _assertPred!"=="(monthsToMonth(Month.jan, Month.aug), 7);
  26741. _assertPred!"=="(monthsToMonth(Month.jan, Month.sep), 8);
  26742. _assertPred!"=="(monthsToMonth(Month.jan, Month.oct), 9);
  26743. _assertPred!"=="(monthsToMonth(Month.jan, Month.nov), 10);
  26744. _assertPred!"=="(monthsToMonth(Month.jan, Month.dec), 11);
  26745. _assertPred!"=="(monthsToMonth(Month.may, Month.jan), 8);
  26746. _assertPred!"=="(monthsToMonth(Month.may, Month.feb), 9);
  26747. _assertPred!"=="(monthsToMonth(Month.may, Month.mar), 10);
  26748. _assertPred!"=="(monthsToMonth(Month.may, Month.apr), 11);
  26749. _assertPred!"=="(monthsToMonth(Month.may, Month.may), 0);
  26750. _assertPred!"=="(monthsToMonth(Month.may, Month.jun), 1);
  26751. _assertPred!"=="(monthsToMonth(Month.may, Month.jul), 2);
  26752. _assertPred!"=="(monthsToMonth(Month.may, Month.aug), 3);
  26753. _assertPred!"=="(monthsToMonth(Month.may, Month.sep), 4);
  26754. _assertPred!"=="(monthsToMonth(Month.may, Month.oct), 5);
  26755. _assertPred!"=="(monthsToMonth(Month.may, Month.nov), 6);
  26756. _assertPred!"=="(monthsToMonth(Month.may, Month.dec), 7);
  26757. _assertPred!"=="(monthsToMonth(Month.oct, Month.jan), 3);
  26758. _assertPred!"=="(monthsToMonth(Month.oct, Month.feb), 4);
  26759. _assertPred!"=="(monthsToMonth(Month.oct, Month.mar), 5);
  26760. _assertPred!"=="(monthsToMonth(Month.oct, Month.apr), 6);
  26761. _assertPred!"=="(monthsToMonth(Month.oct, Month.may), 7);
  26762. _assertPred!"=="(monthsToMonth(Month.oct, Month.jun), 8);
  26763. _assertPred!"=="(monthsToMonth(Month.oct, Month.jul), 9);
  26764. _assertPred!"=="(monthsToMonth(Month.oct, Month.aug), 10);
  26765. _assertPred!"=="(monthsToMonth(Month.oct, Month.sep), 11);
  26766. _assertPred!"=="(monthsToMonth(Month.oct, Month.oct), 0);
  26767. _assertPred!"=="(monthsToMonth(Month.oct, Month.nov), 1);
  26768. _assertPred!"=="(monthsToMonth(Month.oct, Month.dec), 2);
  26769. _assertPred!"=="(monthsToMonth(Month.dec, Month.jan), 1);
  26770. _assertPred!"=="(monthsToMonth(Month.dec, Month.feb), 2);
  26771. _assertPred!"=="(monthsToMonth(Month.dec, Month.mar), 3);
  26772. _assertPred!"=="(monthsToMonth(Month.dec, Month.apr), 4);
  26773. _assertPred!"=="(monthsToMonth(Month.dec, Month.may), 5);
  26774. _assertPred!"=="(monthsToMonth(Month.dec, Month.jun), 6);
  26775. _assertPred!"=="(monthsToMonth(Month.dec, Month.jul), 7);
  26776. _assertPred!"=="(monthsToMonth(Month.dec, Month.aug), 8);
  26777. _assertPred!"=="(monthsToMonth(Month.dec, Month.sep), 9);
  26778. _assertPred!"=="(monthsToMonth(Month.dec, Month.oct), 10);
  26779. _assertPred!"=="(monthsToMonth(Month.dec, Month.nov), 11);
  26780. _assertPred!"=="(monthsToMonth(Month.dec, Month.dec), 0);
  26781. }
  26782. }
  26783. /++
  26784. Returns the number of days from the current day of the week to the given
  26785. day of the week. If they are the same, then the result is 0.
  26786. Params:
  26787. currDoW = The current day of the week.
  26788. dow = The day of the week to get the number of days to.
  26789. +/
  26790. static int daysToDayOfWeek(DayOfWeek currDoW, DayOfWeek dow) pure nothrow
  26791. {
  26792. if(currDoW == dow)
  26793. return 0;
  26794. if(currDoW < dow)
  26795. return dow - currDoW;
  26796. return (DayOfWeek.sat - currDoW) + dow + 1;
  26797. }
  26798. unittest
  26799. {
  26800. version(testStdDateTime)
  26801. {
  26802. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.sun), 0);
  26803. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.mon), 1);
  26804. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.tue), 2);
  26805. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.wed), 3);
  26806. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.thu), 4);
  26807. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.fri), 5);
  26808. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.sat), 6);
  26809. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.sun), 6);
  26810. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.mon), 0);
  26811. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.tue), 1);
  26812. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.wed), 2);
  26813. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.thu), 3);
  26814. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.fri), 4);
  26815. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.sat), 5);
  26816. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.sun), 5);
  26817. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.mon), 6);
  26818. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.tue), 0);
  26819. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.wed), 1);
  26820. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.thu), 2);
  26821. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.fri), 3);
  26822. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.sat), 4);
  26823. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.sun), 4);
  26824. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.mon), 5);
  26825. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.tue), 6);
  26826. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.wed), 0);
  26827. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.thu), 1);
  26828. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.fri), 2);
  26829. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.sat), 3);
  26830. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.sun), 3);
  26831. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.mon), 4);
  26832. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.tue), 5);
  26833. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.wed), 6);
  26834. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.thu), 0);
  26835. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.fri), 1);
  26836. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.sat), 2);
  26837. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.sun), 2);
  26838. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.mon), 3);
  26839. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.tue), 4);
  26840. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.wed), 5);
  26841. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.thu), 6);
  26842. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.fri), 0);
  26843. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.sat), 1);
  26844. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.sun), 1);
  26845. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.mon), 2);
  26846. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.tue), 3);
  26847. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.wed), 4);
  26848. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.thu), 5);
  26849. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.fri), 6);
  26850. _assertPred!"=="(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.sat), 0);
  26851. }
  26852. }
  26853. version(StdDdoc)
  26854. {
  26855. /++
  26856. Function for starting to a stop watch time when the function is called
  26857. and stopping it when its return value goes out of scope and is destroyed.
  26858. When the value that is returned by this function is destroyed,
  26859. $(D func) will run. $(D func) is a unary function that takes a
  26860. $(CXREF TickDuration).
  26861. Examples:
  26862. --------------------
  26863. writeln("benchmark start!");
  26864. {
  26865. auto mt = measureTime!((a){assert(a.seconds);});
  26866. doSomething();
  26867. }
  26868. writeln("benchmark end!");
  26869. --------------------
  26870. +/
  26871. auto measureTime(alias func)();
  26872. }
  26873. else
  26874. {
  26875. @safe auto measureTime(alias func)()
  26876. if(isSafe!func)
  26877. {
  26878. struct Result
  26879. {
  26880. private StopWatch _sw = void;
  26881. this(AutoStart as)
  26882. {
  26883. _sw = StopWatch(as);
  26884. }
  26885. ~this()
  26886. {
  26887. unaryFun!(func)(_sw.peek());
  26888. }
  26889. }
  26890. return Result(AutoStart.yes);
  26891. }
  26892. auto measureTime(alias func)()
  26893. if(!isSafe!func)
  26894. {
  26895. struct Result
  26896. {
  26897. private StopWatch _sw = void;
  26898. this(AutoStart as)
  26899. {
  26900. _sw = StopWatch(as);
  26901. }
  26902. ~this()
  26903. {
  26904. unaryFun!(func)(_sw.peek());
  26905. }
  26906. }
  26907. return Result(AutoStart.yes);
  26908. }
  26909. }
  26910. version(testStdDateTime) @safe unittest
  26911. {
  26912. @safe static void func(TickDuration td)
  26913. {
  26914. assert(td.to!("seconds", real) <>= 0);
  26915. }
  26916. auto mt = measureTime!(func)();
  26917. /+
  26918. with (measureTime!((a){assert(a.seconds);}))
  26919. {
  26920. // doSomething();
  26921. // @@@BUG@@@ doesn't work yet.
  26922. }
  26923. +/
  26924. }
  26925. version(testStdDateTime) unittest
  26926. {
  26927. static void func(TickDuration td)
  26928. {
  26929. assert(td.to!("seconds", real) <>= 0);
  26930. }
  26931. auto mt = measureTime!(func)();
  26932. /+
  26933. with (measureTime!((a){assert(a.seconds);}))
  26934. {
  26935. // doSomething();
  26936. // @@@BUG@@@ doesn't work yet.
  26937. }
  26938. +/
  26939. }
  26940. //==============================================================================
  26941. // Private Section.
  26942. //==============================================================================
  26943. private:
  26944. //==============================================================================
  26945. // Section with private enums and constants.
  26946. //==============================================================================
  26947. enum daysInYear = 365; /// The number of days in a non-leap year.
  26948. enum daysInLeapYear = 366; /// The numbef or days in a leap year.
  26949. enum daysIn4Years = daysInYear * 3 + daysInLeapYear; /// Number of days in 4 years.
  26950. enum daysIn100Years = daysIn4Years * 25 - 1; /// The number of days in 100 years.
  26951. enum daysIn400Years = daysIn100Years * 4 + 1; /// The number of days in 400 years.
  26952. //==============================================================================
  26953. // Section with private helper functions and templates.
  26954. //==============================================================================
  26955. /+
  26956. Template to help with converting between time units.
  26957. +/
  26958. template hnsecsPer(string units)
  26959. if(CmpTimeUnits!(units, "months") < 0)
  26960. {
  26961. static if(units == "hnsecs")
  26962. enum hnsecsPer = 1L;
  26963. else static if(units == "usecs")
  26964. enum hnsecsPer = 10L;
  26965. else static if(units == "msecs")
  26966. enum hnsecsPer = 1000 * hnsecsPer!"usecs";
  26967. else static if(units == "seconds")
  26968. enum hnsecsPer = 1000 * hnsecsPer!"msecs";
  26969. else static if(units == "minutes")
  26970. enum hnsecsPer = 60 * hnsecsPer!"seconds";
  26971. else static if(units == "hours")
  26972. enum hnsecsPer = 60 * hnsecsPer!"minutes";
  26973. else static if(units == "days")
  26974. enum hnsecsPer = 24 * hnsecsPer!"hours";
  26975. else static if(units == "weeks")
  26976. enum hnsecsPer = 7 * hnsecsPer!"days";
  26977. }
  26978. /+
  26979. Splits out a particular unit from hnsecs and gives you the value for that
  26980. unit and the remaining hnsecs. It really shouldn't be used unless unless
  26981. all units larger than the given units have already been split out.
  26982. Params:
  26983. units = The units to split out.
  26984. hnsecs = The current total hnsecs. Upon returning, it is the hnsecs left
  26985. after splitting out the given units.
  26986. Returns:
  26987. The number of the given units from converting hnsecs to those units.
  26988. Examples:
  26989. --------------------
  26990. auto hnsecs = 2595000000007L;
  26991. immutable days = splitUnitsFromHNSecs!"days"(hnsecs);
  26992. assert(days == 3);
  26993. assert(hnsecs == 3000000007);
  26994. immutable minutes = splitUnitsFromHNSecs!"minutes"(hnsecs);
  26995. assert(minutes == 5);
  26996. assert(hnsecs == 7);
  26997. --------------------
  26998. +/
  26999. long splitUnitsFromHNSecs(string units)(ref long hnsecs) pure nothrow
  27000. if(validTimeUnits(units) &&
  27001. CmpTimeUnits!(units, "months") < 0)
  27002. {
  27003. immutable value = convert!("hnsecs", units)(hnsecs);
  27004. hnsecs -= convert!(units, "hnsecs")(value);
  27005. return value;
  27006. }
  27007. unittest
  27008. {
  27009. version(testStdDateTime)
  27010. {
  27011. //Verify Example.
  27012. auto hnsecs = 2595000000007L;
  27013. immutable days = splitUnitsFromHNSecs!"days"(hnsecs);
  27014. assert(days == 3);
  27015. assert(hnsecs == 3000000007);
  27016. immutable minutes = splitUnitsFromHNSecs!"minutes"(hnsecs);
  27017. assert(minutes == 5);
  27018. assert(hnsecs == 7);
  27019. }
  27020. }
  27021. /+
  27022. This function is used to split out the units without getting the remaining
  27023. hnsecs.
  27024. See_Also:
  27025. splitUnitsFromHNSecs()
  27026. Params:
  27027. units = The units to split out.
  27028. hnsecs = The current total hnsecs.
  27029. Returns:
  27030. The split out value.
  27031. Examples:
  27032. --------------------
  27033. auto hnsecs = 2595000000007L;
  27034. immutable days = getUnitsFromHNSecs!"days"(hnsecs);
  27035. assert(days == 3);
  27036. assert(hnsecs == 2595000000007L);
  27037. --------------------
  27038. +/
  27039. long getUnitsFromHNSecs(string units)(long hnsecs) pure nothrow
  27040. if(validTimeUnits(units) &&
  27041. CmpTimeUnits!(units, "months") < 0)
  27042. {
  27043. return convert!("hnsecs", units)(hnsecs);
  27044. }
  27045. unittest
  27046. {
  27047. version(testStdDateTime)
  27048. {
  27049. //Verify Example.
  27050. auto hnsecs = 2595000000007L;
  27051. immutable days = getUnitsFromHNSecs!"days"(hnsecs);
  27052. assert(days == 3);
  27053. assert(hnsecs == 2595000000007L);
  27054. }
  27055. }
  27056. /+
  27057. This function is used to split out the units without getting the units but
  27058. just the remaining hnsecs.
  27059. See_Also:
  27060. splitUnitsFromHNSecs()
  27061. Params:
  27062. units = The units to split out.
  27063. hnsecs = The current total hnsecs.
  27064. Returns:
  27065. The remaining hnsecs.
  27066. Examples:
  27067. --------------------
  27068. auto hnsecs = 2595000000007L;
  27069. auto returned = removeUnitsFromHNSecs!"days"(hnsecs);
  27070. assert(returned == 3000000007);
  27071. assert(hnsecs == 2595000000007L);
  27072. --------------------
  27073. +/
  27074. long removeUnitsFromHNSecs(string units)(long hnsecs) pure nothrow
  27075. if(validTimeUnits(units) &&
  27076. CmpTimeUnits!(units, "months") < 0)
  27077. {
  27078. immutable value = convert!("hnsecs", units)(hnsecs);
  27079. return hnsecs - convert!(units, "hnsecs")(value);
  27080. }
  27081. unittest
  27082. {
  27083. version(testStdDateTime)
  27084. {
  27085. //Verify Example.
  27086. auto hnsecs = 2595000000007L;
  27087. auto returned = removeUnitsFromHNSecs!"days"(hnsecs);
  27088. assert(returned == 3000000007);
  27089. assert(hnsecs == 2595000000007L);
  27090. }
  27091. }
  27092. /+
  27093. The maximum valid Day in the given month in the given year.
  27094. Params:
  27095. year = The year to get the day for.
  27096. month = The month of the Gregorian Calendar to get the day for.
  27097. +/
  27098. static ubyte maxDay(int year, int month) pure nothrow
  27099. in
  27100. {
  27101. assert(valid!"months"(month));
  27102. }
  27103. body
  27104. {
  27105. switch(month)
  27106. {
  27107. case Month.jan, Month.mar, Month.may, Month.jul, Month.aug, Month.oct, Month.dec:
  27108. return 31;
  27109. case Month.feb:
  27110. return yearIsLeapYear(year) ? 29 : 28;
  27111. case Month.apr, Month.jun, Month.sep, Month.nov:
  27112. return 30;
  27113. default:
  27114. assert(0, "Invalid month.");
  27115. }
  27116. }
  27117. unittest
  27118. {
  27119. version(testStdDateTime)
  27120. {
  27121. //Test A.D.
  27122. _assertPred!"=="(maxDay(1999, 1), 31);
  27123. _assertPred!"=="(maxDay(1999, 2), 28);
  27124. _assertPred!"=="(maxDay(1999, 3), 31);
  27125. _assertPred!"=="(maxDay(1999, 4), 30);
  27126. _assertPred!"=="(maxDay(1999, 5), 31);
  27127. _assertPred!"=="(maxDay(1999, 6), 30);
  27128. _assertPred!"=="(maxDay(1999, 7), 31);
  27129. _assertPred!"=="(maxDay(1999, 8), 31);
  27130. _assertPred!"=="(maxDay(1999, 9), 30);
  27131. _assertPred!"=="(maxDay(1999, 10), 31);
  27132. _assertPred!"=="(maxDay(1999, 11), 30);
  27133. _assertPred!"=="(maxDay(1999, 12), 31);
  27134. _assertPred!"=="(maxDay(2000, 1), 31);
  27135. _assertPred!"=="(maxDay(2000, 2), 29);
  27136. _assertPred!"=="(maxDay(2000, 3), 31);
  27137. _assertPred!"=="(maxDay(2000, 4), 30);
  27138. _assertPred!"=="(maxDay(2000, 5), 31);
  27139. _assertPred!"=="(maxDay(2000, 6), 30);
  27140. _assertPred!"=="(maxDay(2000, 7), 31);
  27141. _assertPred!"=="(maxDay(2000, 8), 31);
  27142. _assertPred!"=="(maxDay(2000, 9), 30);
  27143. _assertPred!"=="(maxDay(2000, 10), 31);
  27144. _assertPred!"=="(maxDay(2000, 11), 30);
  27145. _assertPred!"=="(maxDay(2000, 12), 31);
  27146. //Test B.C.
  27147. _assertPred!"=="(maxDay(-1999, 1), 31);
  27148. _assertPred!"=="(maxDay(-1999, 2), 28);
  27149. _assertPred!"=="(maxDay(-1999, 3), 31);
  27150. _assertPred!"=="(maxDay(-1999, 4), 30);
  27151. _assertPred!"=="(maxDay(-1999, 5), 31);
  27152. _assertPred!"=="(maxDay(-1999, 6), 30);
  27153. _assertPred!"=="(maxDay(-1999, 7), 31);
  27154. _assertPred!"=="(maxDay(-1999, 8), 31);
  27155. _assertPred!"=="(maxDay(-1999, 9), 30);
  27156. _assertPred!"=="(maxDay(-1999, 10), 31);
  27157. _assertPred!"=="(maxDay(-1999, 11), 30);
  27158. _assertPred!"=="(maxDay(-1999, 12), 31);
  27159. _assertPred!"=="(maxDay(-2000, 1), 31);
  27160. _assertPred!"=="(maxDay(-2000, 2), 29);
  27161. _assertPred!"=="(maxDay(-2000, 3), 31);
  27162. _assertPred!"=="(maxDay(-2000, 4), 30);
  27163. _assertPred!"=="(maxDay(-2000, 5), 31);
  27164. _assertPred!"=="(maxDay(-2000, 6), 30);
  27165. _assertPred!"=="(maxDay(-2000, 7), 31);
  27166. _assertPred!"=="(maxDay(-2000, 8), 31);
  27167. _assertPred!"=="(maxDay(-2000, 9), 30);
  27168. _assertPred!"=="(maxDay(-2000, 10), 31);
  27169. _assertPred!"=="(maxDay(-2000, 11), 30);
  27170. _assertPred!"=="(maxDay(-2000, 12), 31);
  27171. }
  27172. }
  27173. /+
  27174. Returns the day of the week for the given day of the Gregorian Calendar.
  27175. Params:
  27176. day = The day of the Gregorian Calendar for which to get the day of
  27177. the week.
  27178. +/
  27179. DayOfWeek getDayOfWeek(int day) pure nothrow
  27180. {
  27181. //January 1st, 1 A.D. was a Monday
  27182. if(day >= 0)
  27183. return cast(DayOfWeek)(day % 7);
  27184. else
  27185. {
  27186. immutable dow = cast(DayOfWeek)((day % 7) + 7);
  27187. if(dow == 7)
  27188. return DayOfWeek.sun;
  27189. else
  27190. return dow;
  27191. }
  27192. }
  27193. unittest
  27194. {
  27195. version(testStdDateTime)
  27196. {
  27197. //Test A.D.
  27198. _assertPred!"=="(getDayOfWeek(SysTime(Date(1, 1, 1)).dayOfGregorianCal), DayOfWeek.mon);
  27199. _assertPred!"=="(getDayOfWeek(SysTime(Date(1, 1, 2)).dayOfGregorianCal), DayOfWeek.tue);
  27200. _assertPred!"=="(getDayOfWeek(SysTime(Date(1, 1, 3)).dayOfGregorianCal), DayOfWeek.wed);
  27201. _assertPred!"=="(getDayOfWeek(SysTime(Date(1, 1, 4)).dayOfGregorianCal), DayOfWeek.thu);
  27202. _assertPred!"=="(getDayOfWeek(SysTime(Date(1, 1, 5)).dayOfGregorianCal), DayOfWeek.fri);
  27203. _assertPred!"=="(getDayOfWeek(SysTime(Date(1, 1, 6)).dayOfGregorianCal), DayOfWeek.sat);
  27204. _assertPred!"=="(getDayOfWeek(SysTime(Date(1, 1, 7)).dayOfGregorianCal), DayOfWeek.sun);
  27205. _assertPred!"=="(getDayOfWeek(SysTime(Date(1, 1, 8)).dayOfGregorianCal), DayOfWeek.mon);
  27206. _assertPred!"=="(getDayOfWeek(SysTime(Date(1, 1, 9)).dayOfGregorianCal), DayOfWeek.tue);
  27207. _assertPred!"=="(getDayOfWeek(SysTime(Date(2, 1, 1)).dayOfGregorianCal), DayOfWeek.tue);
  27208. _assertPred!"=="(getDayOfWeek(SysTime(Date(3, 1, 1)).dayOfGregorianCal), DayOfWeek.wed);
  27209. _assertPred!"=="(getDayOfWeek(SysTime(Date(4, 1, 1)).dayOfGregorianCal), DayOfWeek.thu);
  27210. _assertPred!"=="(getDayOfWeek(SysTime(Date(5, 1, 1)).dayOfGregorianCal), DayOfWeek.sat);
  27211. _assertPred!"=="(getDayOfWeek(SysTime(Date(2000, 1, 1)).dayOfGregorianCal), DayOfWeek.sat);
  27212. _assertPred!"=="(getDayOfWeek(SysTime(Date(2010, 8, 22)).dayOfGregorianCal), DayOfWeek.sun);
  27213. _assertPred!"=="(getDayOfWeek(SysTime(Date(2010, 8, 23)).dayOfGregorianCal), DayOfWeek.mon);
  27214. _assertPred!"=="(getDayOfWeek(SysTime(Date(2010, 8, 24)).dayOfGregorianCal), DayOfWeek.tue);
  27215. _assertPred!"=="(getDayOfWeek(SysTime(Date(2010, 8, 25)).dayOfGregorianCal), DayOfWeek.wed);
  27216. _assertPred!"=="(getDayOfWeek(SysTime(Date(2010, 8, 26)).dayOfGregorianCal), DayOfWeek.thu);
  27217. _assertPred!"=="(getDayOfWeek(SysTime(Date(2010, 8, 27)).dayOfGregorianCal), DayOfWeek.fri);
  27218. _assertPred!"=="(getDayOfWeek(SysTime(Date(2010, 8, 28)).dayOfGregorianCal), DayOfWeek.sat);
  27219. _assertPred!"=="(getDayOfWeek(SysTime(Date(2010, 8, 29)).dayOfGregorianCal), DayOfWeek.sun);
  27220. //Test B.C.
  27221. _assertPred!"=="(getDayOfWeek(SysTime(Date(0, 12, 31)).dayOfGregorianCal), DayOfWeek.sun);
  27222. _assertPred!"=="(getDayOfWeek(SysTime(Date(0, 12, 30)).dayOfGregorianCal), DayOfWeek.sat);
  27223. _assertPred!"=="(getDayOfWeek(SysTime(Date(0, 12, 29)).dayOfGregorianCal), DayOfWeek.fri);
  27224. _assertPred!"=="(getDayOfWeek(SysTime(Date(0, 12, 28)).dayOfGregorianCal), DayOfWeek.thu);
  27225. _assertPred!"=="(getDayOfWeek(SysTime(Date(0, 12, 27)).dayOfGregorianCal), DayOfWeek.wed);
  27226. _assertPred!"=="(getDayOfWeek(SysTime(Date(0, 12, 26)).dayOfGregorianCal), DayOfWeek.tue);
  27227. _assertPred!"=="(getDayOfWeek(SysTime(Date(0, 12, 25)).dayOfGregorianCal), DayOfWeek.mon);
  27228. _assertPred!"=="(getDayOfWeek(SysTime(Date(0, 12, 24)).dayOfGregorianCal), DayOfWeek.sun);
  27229. _assertPred!"=="(getDayOfWeek(SysTime(Date(0, 12, 23)).dayOfGregorianCal), DayOfWeek.sat);
  27230. }
  27231. }
  27232. /+
  27233. Returns the string representation of the given month.
  27234. Params:
  27235. useLongName = Whether the long or short version of the month name should
  27236. be used.
  27237. plural = Whether the string should be plural or not.
  27238. Throws:
  27239. $(D DateTimeException) if the given month is not a valid month.
  27240. +/
  27241. string monthToString(Month month, bool useLongName = true) pure
  27242. {
  27243. if(useLongName == true)
  27244. {
  27245. switch(month)
  27246. {
  27247. case Month.jan:
  27248. return "January";
  27249. case Month.feb:
  27250. return "February";
  27251. case Month.mar:
  27252. return "March";
  27253. case Month.apr:
  27254. return "April";
  27255. case Month.may:
  27256. return "May";
  27257. case Month.jun:
  27258. return "June";
  27259. case Month.jul:
  27260. return "July";
  27261. case Month.aug:
  27262. return "August";
  27263. case Month.sep:
  27264. return "September";
  27265. case Month.oct:
  27266. return "October";
  27267. case Month.nov:
  27268. return "November";
  27269. case Month.dec:
  27270. return "December";
  27271. default:
  27272. throw new DateTimeException("Invalid month: " ~ numToString(month));
  27273. }
  27274. }
  27275. else
  27276. {
  27277. switch(month)
  27278. {
  27279. case Month.jan:
  27280. return "Jan";
  27281. case Month.feb:
  27282. return "Feb";
  27283. case Month.mar:
  27284. return "Mar";
  27285. case Month.apr:
  27286. return "Apr";
  27287. case Month.may:
  27288. return "May";
  27289. case Month.jun:
  27290. return "Jun";
  27291. case Month.jul:
  27292. return "Jul";
  27293. case Month.aug:
  27294. return "Aug";
  27295. case Month.sep:
  27296. return "Sep";
  27297. case Month.oct:
  27298. return "Oct";
  27299. case Month.nov:
  27300. return "Nov";
  27301. case Month.dec:
  27302. return "Dec";
  27303. default:
  27304. throw new DateTimeException("Invalid month: " ~ numToString(month));
  27305. }
  27306. }
  27307. }
  27308. unittest
  27309. {
  27310. version(testStdDateTime)
  27311. {
  27312. static void testMTSInvalid(Month month, bool useLongName)
  27313. {
  27314. monthToString(month, useLongName);
  27315. }
  27316. assertThrown!DateTimeException(testMTSInvalid(cast(Month)0, true));
  27317. assertThrown!DateTimeException(testMTSInvalid(cast(Month)0, false));
  27318. assertThrown!DateTimeException(testMTSInvalid(cast(Month)13, true));
  27319. assertThrown!DateTimeException(testMTSInvalid(cast(Month)13, false));
  27320. _assertPred!"=="(monthToString(Month.jan), "January");
  27321. _assertPred!"=="(monthToString(Month.feb), "February");
  27322. _assertPred!"=="(monthToString(Month.mar), "March");
  27323. _assertPred!"=="(monthToString(Month.apr), "April");
  27324. _assertPred!"=="(monthToString(Month.may), "May");
  27325. _assertPred!"=="(monthToString(Month.jun), "June");
  27326. _assertPred!"=="(monthToString(Month.jul), "July");
  27327. _assertPred!"=="(monthToString(Month.aug), "August");
  27328. _assertPred!"=="(monthToString(Month.sep), "September");
  27329. _assertPred!"=="(monthToString(Month.oct), "October");
  27330. _assertPred!"=="(monthToString(Month.nov), "November");
  27331. _assertPred!"=="(monthToString(Month.dec), "December");
  27332. _assertPred!"=="(monthToString(Month.jan, false), "Jan");
  27333. _assertPred!"=="(monthToString(Month.feb, false), "Feb");
  27334. _assertPred!"=="(monthToString(Month.mar, false), "Mar");
  27335. _assertPred!"=="(monthToString(Month.apr, false), "Apr");
  27336. _assertPred!"=="(monthToString(Month.may, false), "May");
  27337. _assertPred!"=="(monthToString(Month.jun, false), "Jun");
  27338. _assertPred!"=="(monthToString(Month.jul, false), "Jul");
  27339. _assertPred!"=="(monthToString(Month.aug, false), "Aug");
  27340. _assertPred!"=="(monthToString(Month.sep, false), "Sep");
  27341. _assertPred!"=="(monthToString(Month.oct, false), "Oct");
  27342. _assertPred!"=="(monthToString(Month.nov, false), "Nov");
  27343. _assertPred!"=="(monthToString(Month.dec, false), "Dec");
  27344. }
  27345. }
  27346. /+
  27347. Returns the Month corresponding to the given string. Casing is ignored.
  27348. Params:
  27349. monthStr = The string representation of the month to get the Month for.
  27350. Throws:
  27351. $(D DateTimeException) if the given month is not a valid month string.
  27352. +/
  27353. Month monthFromString(string monthStr)
  27354. {
  27355. switch(toLower(monthStr))
  27356. {
  27357. case "january":
  27358. case "jan":
  27359. return Month.jan;
  27360. case "february":
  27361. case "feb":
  27362. return Month.feb;
  27363. case "march":
  27364. case "mar":
  27365. return Month.mar;
  27366. case "april":
  27367. case "apr":
  27368. return Month.apr;
  27369. case "may":
  27370. return Month.may;
  27371. case "june":
  27372. case "jun":
  27373. return Month.jun;
  27374. case "july":
  27375. case "jul":
  27376. return Month.jul;
  27377. case "august":
  27378. case "aug":
  27379. return Month.aug;
  27380. case "september":
  27381. case "sep":
  27382. return Month.sep;
  27383. case "october":
  27384. case "oct":
  27385. return Month.oct;
  27386. case "november":
  27387. case "nov":
  27388. return Month.nov;
  27389. case "december":
  27390. case "dec":
  27391. return Month.dec;
  27392. default:
  27393. throw new DateTimeException(format("Invalid month %s", monthStr));
  27394. }
  27395. }
  27396. unittest
  27397. {
  27398. version(testStdDateTime)
  27399. {
  27400. static void testMFSInvalid(string monthStr)
  27401. {
  27402. monthFromString(monthStr);
  27403. }
  27404. assertThrown!DateTimeException(testMFSInvalid("Ja"));
  27405. assertThrown!DateTimeException(testMFSInvalid("Janu"));
  27406. assertThrown!DateTimeException(testMFSInvalid("Januar"));
  27407. assertThrown!DateTimeException(testMFSInvalid("Januarys"));
  27408. assertThrown!DateTimeException(testMFSInvalid("JJanuary"));
  27409. _assertPred!"=="(monthFromString(monthToString(Month.jan)), Month.jan);
  27410. _assertPred!"=="(monthFromString(monthToString(Month.feb)), Month.feb);
  27411. _assertPred!"=="(monthFromString(monthToString(Month.mar)), Month.mar);
  27412. _assertPred!"=="(monthFromString(monthToString(Month.apr)), Month.apr);
  27413. _assertPred!"=="(monthFromString(monthToString(Month.may)), Month.may);
  27414. _assertPred!"=="(monthFromString(monthToString(Month.jun)), Month.jun);
  27415. _assertPred!"=="(monthFromString(monthToString(Month.jul)), Month.jul);
  27416. _assertPred!"=="(monthFromString(monthToString(Month.aug)), Month.aug);
  27417. _assertPred!"=="(monthFromString(monthToString(Month.sep)), Month.sep);
  27418. _assertPred!"=="(monthFromString(monthToString(Month.oct)), Month.oct);
  27419. _assertPred!"=="(monthFromString(monthToString(Month.nov)), Month.nov);
  27420. _assertPred!"=="(monthFromString(monthToString(Month.dec)), Month.dec);
  27421. _assertPred!"=="(monthFromString(monthToString(Month.jan, false)), Month.jan);
  27422. _assertPred!"=="(monthFromString(monthToString(Month.feb, false)), Month.feb);
  27423. _assertPred!"=="(monthFromString(monthToString(Month.mar, false)), Month.mar);
  27424. _assertPred!"=="(monthFromString(monthToString(Month.apr, false)), Month.apr);
  27425. _assertPred!"=="(monthFromString(monthToString(Month.may, false)), Month.may);
  27426. _assertPred!"=="(monthFromString(monthToString(Month.jun, false)), Month.jun);
  27427. _assertPred!"=="(monthFromString(monthToString(Month.jul, false)), Month.jul);
  27428. _assertPred!"=="(monthFromString(monthToString(Month.aug, false)), Month.aug);
  27429. _assertPred!"=="(monthFromString(monthToString(Month.sep, false)), Month.sep);
  27430. _assertPred!"=="(monthFromString(monthToString(Month.oct, false)), Month.oct);
  27431. _assertPred!"=="(monthFromString(monthToString(Month.nov, false)), Month.nov);
  27432. _assertPred!"=="(monthFromString(monthToString(Month.dec, false)), Month.dec);
  27433. _assertPred!"=="(monthFromString("JANUARY"), Month.jan);
  27434. _assertPred!"=="(monthFromString("JAN"), Month.jan);
  27435. _assertPred!"=="(monthFromString("january"), Month.jan);
  27436. _assertPred!"=="(monthFromString("jan"), Month.jan);
  27437. _assertPred!"=="(monthFromString("jaNuary"), Month.jan);
  27438. _assertPred!"=="(monthFromString("jaN"), Month.jan);
  27439. _assertPred!"=="(monthFromString("jaNuaRy"), Month.jan);
  27440. _assertPred!"=="(monthFromString("jAn"), Month.jan);
  27441. }
  27442. }
  27443. /+
  27444. The time units which are one step smaller than the given units.
  27445. Examples:
  27446. --------------------
  27447. assert(nextSmallerTimeUnits!"years" == "months");
  27448. assert(nextSmallerTimeUnits!"usecs" == "hnsecs");
  27449. --------------------
  27450. +/
  27451. template nextSmallerTimeUnits(string units)
  27452. if(validTimeUnits(units) &&
  27453. timeStrings.front != units)
  27454. {
  27455. enum nextSmallerTimeUnits = timeStrings[std.algorithm.countUntil(timeStrings.dup, units) - 1];
  27456. }
  27457. unittest
  27458. {
  27459. version(testStdDateTime)
  27460. {
  27461. _assertPred!"=="(nextSmallerTimeUnits!"months", "weeks");
  27462. _assertPred!"=="(nextSmallerTimeUnits!"weeks", "days");
  27463. _assertPred!"=="(nextSmallerTimeUnits!"days", "hours");
  27464. _assertPred!"=="(nextSmallerTimeUnits!"hours", "minutes");
  27465. _assertPred!"=="(nextSmallerTimeUnits!"minutes", "seconds");
  27466. _assertPred!"=="(nextSmallerTimeUnits!"seconds", "msecs");
  27467. _assertPred!"=="(nextSmallerTimeUnits!"msecs", "usecs");
  27468. static assert(!__traits(compiles, nextSmallerTimeUnits!"hnsecs"));
  27469. //Verify Examples.
  27470. assert(nextSmallerTimeUnits!"years" == "months");
  27471. assert(nextSmallerTimeUnits!"usecs" == "hnsecs");
  27472. }
  27473. }
  27474. /+
  27475. The time units which are one step larger than the given units.
  27476. Examples:
  27477. --------------------
  27478. assert(nextLargerTimeUnits!"months" == "years");
  27479. assert(nextLargerTimeUnits!"hnsecs" == "usecs");
  27480. --------------------
  27481. +/
  27482. template nextLargerTimeUnits(string units)
  27483. if(validTimeUnits(units) &&
  27484. timeStrings.back != units)
  27485. {
  27486. enum nextLargerTimeUnits = timeStrings[std.algorithm.countUntil(timeStrings.dup, units) + 1];
  27487. }
  27488. unittest
  27489. {
  27490. version(testStdDateTime)
  27491. {
  27492. _assertPred!"=="(nextLargerTimeUnits!"usecs", "msecs");
  27493. _assertPred!"=="(nextLargerTimeUnits!"msecs", "seconds");
  27494. _assertPred!"=="(nextLargerTimeUnits!"seconds", "minutes");
  27495. _assertPred!"=="(nextLargerTimeUnits!"minutes", "hours");
  27496. _assertPred!"=="(nextLargerTimeUnits!"hours", "days");
  27497. _assertPred!"=="(nextLargerTimeUnits!"days", "weeks");
  27498. _assertPred!"=="(nextLargerTimeUnits!"weeks", "months");
  27499. static assert(!__traits(compiles, nextLargerTimeUnits!"years"));
  27500. //Verify Examples.
  27501. assert(nextLargerTimeUnits!"months" == "years");
  27502. assert(nextLargerTimeUnits!"hnsecs" == "usecs");
  27503. }
  27504. }
  27505. /+
  27506. Returns the given hnsecs as an ISO string of fractional seconds.
  27507. +/
  27508. static string fracSecToISOString(int hnsecs) nothrow
  27509. in
  27510. {
  27511. assert(hnsecs >= 0);
  27512. }
  27513. body
  27514. {
  27515. try
  27516. {
  27517. string isoString = format(".%07d", hnsecs);
  27518. while(isoString.endsWith("0"))
  27519. isoString.popBack();
  27520. if(isoString.length == 1)
  27521. return "";
  27522. return isoString;
  27523. }
  27524. catch(Exception e)
  27525. assert(0, "format() threw.");
  27526. }
  27527. unittest
  27528. {
  27529. version(testStdDateTime)
  27530. {
  27531. _assertPred!"=="(fracSecToISOString(0), "");
  27532. _assertPred!"=="(fracSecToISOString(1), ".0000001");
  27533. _assertPred!"=="(fracSecToISOString(10), ".000001");
  27534. _assertPred!"=="(fracSecToISOString(100), ".00001");
  27535. _assertPred!"=="(fracSecToISOString(1000), ".0001");
  27536. _assertPred!"=="(fracSecToISOString(10_000), ".001");
  27537. _assertPred!"=="(fracSecToISOString(100_000), ".01");
  27538. _assertPred!"=="(fracSecToISOString(1_000_000), ".1");
  27539. _assertPred!"=="(fracSecToISOString(1_000_001), ".1000001");
  27540. _assertPred!"=="(fracSecToISOString(1_001_001), ".1001001");
  27541. _assertPred!"=="(fracSecToISOString(1_071_601), ".1071601");
  27542. _assertPred!"=="(fracSecToISOString(1_271_641), ".1271641");
  27543. _assertPred!"=="(fracSecToISOString(9_999_999), ".9999999");
  27544. _assertPred!"=="(fracSecToISOString(9_999_990), ".999999");
  27545. _assertPred!"=="(fracSecToISOString(9_999_900), ".99999");
  27546. _assertPred!"=="(fracSecToISOString(9_999_000), ".9999");
  27547. _assertPred!"=="(fracSecToISOString(9_990_000), ".999");
  27548. _assertPred!"=="(fracSecToISOString(9_900_000), ".99");
  27549. _assertPred!"=="(fracSecToISOString(9_000_000), ".9");
  27550. _assertPred!"=="(fracSecToISOString(999), ".0000999");
  27551. _assertPred!"=="(fracSecToISOString(9990), ".000999");
  27552. _assertPred!"=="(fracSecToISOString(99_900), ".00999");
  27553. _assertPred!"=="(fracSecToISOString(999_000), ".0999");
  27554. }
  27555. }
  27556. /+
  27557. Returns a FracSec corresponding to to the given ISO string of
  27558. fractional seconds.
  27559. +/
  27560. static FracSec fracSecFromISOString(S)(in S isoString)
  27561. if(isSomeString!S)
  27562. {
  27563. if(isoString.empty)
  27564. return FracSec.from!"hnsecs"(0);
  27565. auto dstr = to!dstring(isoString);
  27566. enforce(dstr.startsWith("."), new DateTimeException("Invalid ISO String"));
  27567. dstr.popFront();
  27568. enforce(!dstr.empty && dstr.length <= 7, new DateTimeException("Invalid ISO String"));
  27569. enforce(!canFind!(not!isDigit)(dstr), new DateTimeException("Invalid ISO String"));
  27570. dchar[7] fullISOString;
  27571. foreach(i, ref dchar c; fullISOString)
  27572. {
  27573. if(i < dstr.length)
  27574. c = dstr[i];
  27575. else
  27576. c = '0';
  27577. }
  27578. return FracSec.from!"hnsecs"(to!int(fullISOString[]));
  27579. }
  27580. unittest
  27581. {
  27582. version(testStdDateTime)
  27583. {
  27584. static void testFSInvalid(string isoString)
  27585. {
  27586. fracSecFromISOString(isoString);
  27587. }
  27588. assertThrown!DateTimeException(testFSInvalid("."));
  27589. assertThrown!DateTimeException(testFSInvalid("0."));
  27590. assertThrown!DateTimeException(testFSInvalid("0"));
  27591. assertThrown!DateTimeException(testFSInvalid("0000000"));
  27592. assertThrown!DateTimeException(testFSInvalid(".00000000"));
  27593. assertThrown!DateTimeException(testFSInvalid(".00000001"));
  27594. assertThrown!DateTimeException(testFSInvalid("T"));
  27595. assertThrown!DateTimeException(testFSInvalid("T."));
  27596. assertThrown!DateTimeException(testFSInvalid(".T"));
  27597. _assertPred!"=="(fracSecFromISOString(""), FracSec.from!"hnsecs"(0));
  27598. _assertPred!"=="(fracSecFromISOString(".0000001"), FracSec.from!"hnsecs"(1));
  27599. _assertPred!"=="(fracSecFromISOString(".000001"), FracSec.from!"hnsecs"(10));
  27600. _assertPred!"=="(fracSecFromISOString(".00001"), FracSec.from!"hnsecs"(100));
  27601. _assertPred!"=="(fracSecFromISOString(".0001"), FracSec.from!"hnsecs"(1000));
  27602. _assertPred!"=="(fracSecFromISOString(".001"), FracSec.from!"hnsecs"(10_000));
  27603. _assertPred!"=="(fracSecFromISOString(".01"), FracSec.from!"hnsecs"(100_000));
  27604. _assertPred!"=="(fracSecFromISOString(".1"), FracSec.from!"hnsecs"(1_000_000));
  27605. _assertPred!"=="(fracSecFromISOString(".1000001"), FracSec.from!"hnsecs"(1_000_001));
  27606. _assertPred!"=="(fracSecFromISOString(".1001001"), FracSec.from!"hnsecs"(1_001_001));
  27607. _assertPred!"=="(fracSecFromISOString(".1071601"), FracSec.from!"hnsecs"(1_071_601));
  27608. _assertPred!"=="(fracSecFromISOString(".1271641"), FracSec.from!"hnsecs"(1_271_641));
  27609. _assertPred!"=="(fracSecFromISOString(".9999999"), FracSec.from!"hnsecs"(9_999_999));
  27610. _assertPred!"=="(fracSecFromISOString(".9999990"), FracSec.from!"hnsecs"(9_999_990));
  27611. _assertPred!"=="(fracSecFromISOString(".999999"), FracSec.from!"hnsecs"(9_999_990));
  27612. _assertPred!"=="(fracSecFromISOString(".9999900"), FracSec.from!"hnsecs"(9_999_900));
  27613. _assertPred!"=="(fracSecFromISOString(".99999"), FracSec.from!"hnsecs"(9_999_900));
  27614. _assertPred!"=="(fracSecFromISOString(".9999000"), FracSec.from!"hnsecs"(9_999_000));
  27615. _assertPred!"=="(fracSecFromISOString(".9999"), FracSec.from!"hnsecs"(9_999_000));
  27616. _assertPred!"=="(fracSecFromISOString(".9990000"), FracSec.from!"hnsecs"(9_990_000));
  27617. _assertPred!"=="(fracSecFromISOString(".999"), FracSec.from!"hnsecs"(9_990_000));
  27618. _assertPred!"=="(fracSecFromISOString(".9900000"), FracSec.from!"hnsecs"(9_900_000));
  27619. _assertPred!"=="(fracSecFromISOString(".9900"), FracSec.from!"hnsecs"(9_900_000));
  27620. _assertPred!"=="(fracSecFromISOString(".99"), FracSec.from!"hnsecs"(9_900_000));
  27621. _assertPred!"=="(fracSecFromISOString(".9000000"), FracSec.from!"hnsecs"(9_000_000));
  27622. _assertPred!"=="(fracSecFromISOString(".9"), FracSec.from!"hnsecs"(9_000_000));
  27623. _assertPred!"=="(fracSecFromISOString(".0000999"), FracSec.from!"hnsecs"(999));
  27624. _assertPred!"=="(fracSecFromISOString(".0009990"), FracSec.from!"hnsecs"(9990));
  27625. _assertPred!"=="(fracSecFromISOString(".000999"), FracSec.from!"hnsecs"(9990));
  27626. _assertPred!"=="(fracSecFromISOString(".0099900"), FracSec.from!"hnsecs"(99_900));
  27627. _assertPred!"=="(fracSecFromISOString(".00999"), FracSec.from!"hnsecs"(99_900));
  27628. _assertPred!"=="(fracSecFromISOString(".0999000"), FracSec.from!"hnsecs"(999_000));
  27629. _assertPred!"=="(fracSecFromISOString(".0999"), FracSec.from!"hnsecs"(999_000));
  27630. }
  27631. }
  27632. /+
  27633. Whether the given type defines the static property min which returns the
  27634. minimum value for the type.
  27635. +/
  27636. template hasMin(T)
  27637. {
  27638. enum hasMin = __traits(hasMember, T, "min") &&
  27639. __traits(isStaticFunction, T.min) &&
  27640. is(ReturnType!(T.min) == Unqual!T) &&
  27641. (functionAttributes!(T.min) & FunctionAttribute.property) &&
  27642. (functionAttributes!(T.min) & FunctionAttribute.nothrow_);
  27643. //(functionAttributes!(T.min) & FunctionAttribute.pure_); //Ideally this would be the case, but SysTime's min() can't currently be pure.
  27644. }
  27645. unittest
  27646. {
  27647. version(testStdDateTime)
  27648. {
  27649. static assert(hasMin!(Date));
  27650. static assert(hasMin!(TimeOfDay));
  27651. static assert(hasMin!(DateTime));
  27652. static assert(hasMin!(SysTime));
  27653. static assert(hasMin!(const Date));
  27654. static assert(hasMin!(const TimeOfDay));
  27655. static assert(hasMin!(const DateTime));
  27656. static assert(hasMin!(const SysTime));
  27657. static assert(hasMin!(immutable Date));
  27658. static assert(hasMin!(immutable TimeOfDay));
  27659. static assert(hasMin!(immutable SysTime));
  27660. }
  27661. }
  27662. /+
  27663. Whether the given type defines the static property max which returns the
  27664. maximum value for the type.
  27665. +/
  27666. template hasMax(T)
  27667. {
  27668. enum hasMax = __traits(hasMember, T, "max") &&
  27669. __traits(isStaticFunction, T.max) &&
  27670. is(ReturnType!(T.max) == Unqual!T) &&
  27671. (functionAttributes!(T.max) & FunctionAttribute.property) &&
  27672. (functionAttributes!(T.max) & FunctionAttribute.nothrow_);
  27673. //(functionAttributes!(T.max) & FunctionAttribute.pure_); //Ideally this would be the case, but SysTime's max() can't currently be pure.
  27674. }
  27675. unittest
  27676. {
  27677. version(testStdDateTime)
  27678. {
  27679. static assert(hasMax!(Date));
  27680. static assert(hasMax!(TimeOfDay));
  27681. static assert(hasMax!(DateTime));
  27682. static assert(hasMax!(SysTime));
  27683. static assert(hasMax!(const Date));
  27684. static assert(hasMax!(const TimeOfDay));
  27685. static assert(hasMax!(const DateTime));
  27686. static assert(hasMax!(const SysTime));
  27687. static assert(hasMax!(immutable Date));
  27688. static assert(hasMax!(immutable TimeOfDay));
  27689. static assert(hasMax!(immutable DateTime));
  27690. static assert(hasMax!(immutable SysTime));
  27691. }
  27692. }
  27693. /+
  27694. Whether the given type defines the overloaded opBinary operators that a time
  27695. point is supposed to define which work with time durations. Namely:
  27696. $(BOOKTABLE,
  27697. $(TR $(TD TimePoint opBinary"+"(duration)))
  27698. $(TR $(TD TimePoint opBinary"-"(duration)))
  27699. )
  27700. +/
  27701. template hasOverloadedOpBinaryWithDuration(T)
  27702. {
  27703. enum hasOverloadedOpBinaryWithDuration = __traits(compiles, T.init + dur!"days"(5)) &&
  27704. is(typeof(T.init + dur!"days"(5)) == Unqual!T) &&
  27705. __traits(compiles, T.init - dur!"days"(5)) &&
  27706. is(typeof(T.init - dur!"days"(5)) == Unqual!T) &&
  27707. __traits(compiles, T.init + TickDuration.from!"hnsecs"(5)) &&
  27708. is(typeof(T.init + TickDuration.from!"hnsecs"(5)) == Unqual!T) &&
  27709. __traits(compiles, T.init - TickDuration.from!"hnsecs"(5)) &&
  27710. is(typeof(T.init - TickDuration.from!"hnsecs"(5)) == Unqual!T);
  27711. }
  27712. unittest
  27713. {
  27714. version(testStdDateTime)
  27715. {
  27716. static assert(hasOverloadedOpBinaryWithDuration!(Date));
  27717. static assert(hasOverloadedOpBinaryWithDuration!(TimeOfDay));
  27718. static assert(hasOverloadedOpBinaryWithDuration!(DateTime));
  27719. static assert(hasOverloadedOpBinaryWithDuration!(SysTime));
  27720. static assert(hasOverloadedOpBinaryWithDuration!(const Date));
  27721. static assert(hasOverloadedOpBinaryWithDuration!(const TimeOfDay));
  27722. static assert(hasOverloadedOpBinaryWithDuration!(const DateTime));
  27723. static assert(hasOverloadedOpBinaryWithDuration!(const SysTime));
  27724. static assert(hasOverloadedOpBinaryWithDuration!(immutable Date));
  27725. static assert(hasOverloadedOpBinaryWithDuration!(immutable TimeOfDay));
  27726. static assert(hasOverloadedOpBinaryWithDuration!(immutable DateTime));
  27727. static assert(hasOverloadedOpBinaryWithDuration!(immutable SysTime));
  27728. }
  27729. }
  27730. /+
  27731. Whether the given type defines the overloaded opOpAssign operators that a time point is supposed
  27732. to define. Namely:
  27733. $(BOOKTABLE,
  27734. $(TR $(TD TimePoint opOpAssign"+"(duration)))
  27735. $(TR $(TD TimePoint opOpAssign"-"(duration)))
  27736. )
  27737. +/
  27738. template hasOverloadedOpAssignWithDuration(T)
  27739. {
  27740. enum hasOverloadedOpAssignWithDuration = __traits(compiles, T.init += dur!"days"(5)) &&
  27741. is(typeof(T.init += dur!"days"(5)) == Unqual!T) &&
  27742. __traits(compiles, T.init -= dur!"days"(5)) &&
  27743. is(typeof(T.init -= dur!"days"(5)) == Unqual!T) &&
  27744. __traits(compiles, T.init += TickDuration.from!"hnsecs"(5)) &&
  27745. is(typeof(T.init += TickDuration.from!"hnsecs"(5)) == Unqual!T) &&
  27746. __traits(compiles, T.init -= TickDuration.from!"hnsecs"(5)) &&
  27747. is(typeof(T.init -= TickDuration.from!"hnsecs"(5)) == Unqual!T);
  27748. }
  27749. unittest
  27750. {
  27751. version(testStdDateTime)
  27752. {
  27753. static assert(hasOverloadedOpAssignWithDuration!(Date));
  27754. static assert(hasOverloadedOpAssignWithDuration!(TimeOfDay));
  27755. static assert(hasOverloadedOpAssignWithDuration!(DateTime));
  27756. static assert(hasOverloadedOpAssignWithDuration!(SysTime));
  27757. static assert(hasOverloadedOpAssignWithDuration!(const Date));
  27758. static assert(hasOverloadedOpAssignWithDuration!(const TimeOfDay));
  27759. static assert(hasOverloadedOpAssignWithDuration!(const DateTime));
  27760. static assert(hasOverloadedOpAssignWithDuration!(const SysTime));
  27761. static assert(hasOverloadedOpAssignWithDuration!(immutable Date));
  27762. static assert(hasOverloadedOpAssignWithDuration!(immutable TimeOfDay));
  27763. static assert(hasOverloadedOpAssignWithDuration!(immutable DateTime));
  27764. static assert(hasOverloadedOpAssignWithDuration!(immutable SysTime));
  27765. }
  27766. }
  27767. /+
  27768. Whether the given type defines the overloaded opBinary operator that a time point is supposed
  27769. to define which works with itself. Namely:
  27770. $(BOOKTABLE,
  27771. $(TR $(TD duration opBinary"-"(Date)))
  27772. )
  27773. +/
  27774. template hasOverloadedOpBinaryWithSelf(T)
  27775. {
  27776. enum hasOverloadedOpBinaryWithSelf = __traits(compiles, T.init - T.init) &&
  27777. is(Unqual!(typeof(T.init - T.init)) == Duration);
  27778. }
  27779. unittest
  27780. {
  27781. version(testStdDateTime)
  27782. {
  27783. static assert(hasOverloadedOpBinaryWithSelf!(Date));
  27784. static assert(hasOverloadedOpBinaryWithSelf!(TimeOfDay));
  27785. static assert(hasOverloadedOpBinaryWithSelf!(DateTime));
  27786. static assert(hasOverloadedOpBinaryWithSelf!(SysTime));
  27787. static assert(hasOverloadedOpBinaryWithSelf!(const Date));
  27788. static assert(hasOverloadedOpBinaryWithSelf!(const TimeOfDay));
  27789. static assert(hasOverloadedOpBinaryWithSelf!(const DateTime));
  27790. static assert(hasOverloadedOpBinaryWithSelf!(const SysTime));
  27791. static assert(hasOverloadedOpBinaryWithSelf!(immutable Date));
  27792. static assert(hasOverloadedOpBinaryWithSelf!(immutable TimeOfDay));
  27793. static assert(hasOverloadedOpBinaryWithSelf!(immutable DateTime));
  27794. static assert(hasOverloadedOpBinaryWithSelf!(immutable SysTime));
  27795. }
  27796. }
  27797. /+
  27798. Unfortunately, to!string() is not pure, so here's a way to convert
  27799. a number to a string which is. Once to!string() is properly pure
  27800. (like it hopefully will be at some point), this function should
  27801. be removed in favor of using to!string().
  27802. +/
  27803. string numToString(long value) pure nothrow
  27804. {
  27805. try
  27806. {
  27807. immutable negative = value < 0;
  27808. char[25] str;
  27809. size_t i = str.length;
  27810. if(negative)
  27811. value = -value;
  27812. while(1)
  27813. {
  27814. char digit = cast(char)('0' + value % 10);
  27815. value /= 10;
  27816. str[--i] = digit;
  27817. assert(i > 0);
  27818. if(value == 0)
  27819. break;
  27820. }
  27821. if(negative)
  27822. return "-" ~ str[i .. $].idup;
  27823. else
  27824. return str[i .. $].idup;
  27825. }
  27826. catch(Exception e)
  27827. assert(0, "Something threw when nothing can throw.");
  27828. }
  27829. version(unittest)
  27830. {
  27831. //Variables to help in testing.
  27832. Duration currLocalDiffFromUTC;
  27833. immutable (TimeZone)[] testTZs;
  27834. //All of these helper arrays are sorted in ascending order.
  27835. auto testYearsBC = [-1999, -1200, -600, -4, -1, 0];
  27836. auto testYearsAD = [1, 4, 1000, 1999, 2000, 2012];
  27837. //I'd use a Tuple, but I get forward reference errors if I try.
  27838. struct MonthDay
  27839. {
  27840. Month month;
  27841. short day;
  27842. this(int m, short d)
  27843. {
  27844. month = cast(Month)m;
  27845. day = d;
  27846. }
  27847. }
  27848. MonthDay[] testMonthDays = [MonthDay(1, 1),
  27849. MonthDay(1, 2),
  27850. MonthDay(3, 17),
  27851. MonthDay(7, 4),
  27852. MonthDay(10, 27),
  27853. MonthDay(12, 30),
  27854. MonthDay(12, 31)];
  27855. auto testDays = [1, 2, 9, 10, 16, 20, 25, 28, 29, 30, 31];
  27856. auto testTODs = [TimeOfDay(0, 0, 0),
  27857. TimeOfDay(0, 0, 1),
  27858. TimeOfDay(0, 1, 0),
  27859. TimeOfDay(1, 0, 0),
  27860. TimeOfDay(13, 13, 13),
  27861. TimeOfDay(23, 59, 59)];
  27862. auto testHours = [0, 1, 12, 22, 23];
  27863. auto testMinSecs = [0, 1, 30, 58, 59];
  27864. //Throwing exceptions is incredibly expensive, so we want to use a smaller
  27865. //set of values for tests using assertThrown.
  27866. auto testTODsThrown = [TimeOfDay(0, 0, 0),
  27867. TimeOfDay(13, 13, 13),
  27868. TimeOfDay(23, 59, 59)];
  27869. Date[] testDatesBC;
  27870. Date[] testDatesAD;
  27871. DateTime[] testDateTimesBC;
  27872. DateTime[] testDateTimesAD;
  27873. FracSec[] testFracSecs;
  27874. SysTime[] testSysTimesBC;
  27875. SysTime[] testSysTimesAD;
  27876. //I'd use a Tuple, but I get forward reference errors if I try.
  27877. struct GregDay { int day; Date date; }
  27878. auto testGregDaysBC = [GregDay(-1_373_427, Date(-3760, 9, 7)), //Start of the Hebrew Calendar
  27879. GregDay(-735_233, Date(-2012, 1, 1)),
  27880. GregDay(-735_202, Date(-2012, 2, 1)),
  27881. GregDay(-735_175, Date(-2012, 2, 28)),
  27882. GregDay(-735_174, Date(-2012, 2, 29)),
  27883. GregDay(-735_173, Date(-2012, 3, 1)),
  27884. GregDay(-734_502, Date(-2010, 1, 1)),
  27885. GregDay(-734_472, Date(-2010, 1, 31)),
  27886. GregDay(-734_471, Date(-2010, 2, 1)),
  27887. GregDay(-734_444, Date(-2010, 2, 28)),
  27888. GregDay(-734_443, Date(-2010, 3, 1)),
  27889. GregDay(-734_413, Date(-2010, 3, 31)),
  27890. GregDay(-734_412, Date(-2010, 4, 1)),
  27891. GregDay(-734_383, Date(-2010, 4, 30)),
  27892. GregDay(-734_382, Date(-2010, 5, 1)),
  27893. GregDay(-734_352, Date(-2010, 5, 31)),
  27894. GregDay(-734_351, Date(-2010, 6, 1)),
  27895. GregDay(-734_322, Date(-2010, 6, 30)),
  27896. GregDay(-734_321, Date(-2010, 7, 1)),
  27897. GregDay(-734_291, Date(-2010, 7, 31)),
  27898. GregDay(-734_290, Date(-2010, 8, 1)),
  27899. GregDay(-734_260, Date(-2010, 8, 31)),
  27900. GregDay(-734_259, Date(-2010, 9, 1)),
  27901. GregDay(-734_230, Date(-2010, 9, 30)),
  27902. GregDay(-734_229, Date(-2010, 10, 1)),
  27903. GregDay(-734_199, Date(-2010, 10, 31)),
  27904. GregDay(-734_198, Date(-2010, 11, 1)),
  27905. GregDay(-734_169, Date(-2010, 11, 30)),
  27906. GregDay(-734_168, Date(-2010, 12, 1)),
  27907. GregDay(-734_139, Date(-2010, 12, 30)),
  27908. GregDay(-734_138, Date(-2010, 12, 31)),
  27909. GregDay(-731_215, Date(-2001, 1, 1)),
  27910. GregDay(-730_850, Date(-2000, 1, 1)),
  27911. GregDay(-730_849, Date(-2000, 1, 2)),
  27912. GregDay(-730_486, Date(-2000, 12, 30)),
  27913. GregDay(-730_485, Date(-2000, 12, 31)),
  27914. GregDay(-730_484, Date(-1999, 1, 1)),
  27915. GregDay(-694_690, Date(-1901, 1, 1)),
  27916. GregDay(-694_325, Date(-1900, 1, 1)),
  27917. GregDay(-585_118, Date(-1601, 1, 1)),
  27918. GregDay(-584_753, Date(-1600, 1, 1)),
  27919. GregDay(-584_388, Date(-1600, 12, 31)),
  27920. GregDay(-584_387, Date(-1599, 1, 1)),
  27921. GregDay(-365_972, Date(-1001, 1, 1)),
  27922. GregDay(-365_607, Date(-1000, 1, 1)),
  27923. GregDay(-183_351, Date(-501, 1, 1)),
  27924. GregDay(-182_986, Date(-500, 1, 1)),
  27925. GregDay(-182_621, Date(-499, 1, 1)),
  27926. GregDay(-146_827, Date(-401, 1, 1)),
  27927. GregDay(-146_462, Date(-400, 1, 1)),
  27928. GregDay(-146_097, Date(-400, 12, 31)),
  27929. GregDay(-110_302, Date(-301, 1, 1)),
  27930. GregDay(-109_937, Date(-300, 1, 1)),
  27931. GregDay(-73_778, Date(-201, 1, 1)),
  27932. GregDay(-73_413, Date(-200, 1, 1)),
  27933. GregDay(-38_715, Date(-105, 1, 1)),
  27934. GregDay(-37_254, Date(-101, 1, 1)),
  27935. GregDay(-36_889, Date(-100, 1, 1)),
  27936. GregDay(-36_524, Date(-99, 1, 1)),
  27937. GregDay(-36_160, Date(-99, 12, 31)),
  27938. GregDay(-35_794, Date(-97, 1, 1)),
  27939. GregDay(-18_627, Date(-50, 1, 1)),
  27940. GregDay(-18_262, Date(-49, 1, 1)),
  27941. GregDay(-3652, Date(-9, 1, 1)),
  27942. GregDay(-2191, Date(-5, 1, 1)),
  27943. GregDay(-1827, Date(-5, 12, 31)),
  27944. GregDay(-1826, Date(-4, 1, 1)),
  27945. GregDay(-1825, Date(-4, 1, 2)),
  27946. GregDay(-1462, Date(-4, 12, 30)),
  27947. GregDay(-1461, Date(-4, 12, 31)),
  27948. GregDay(-1460, Date(-3, 1, 1)),
  27949. GregDay(-1096, Date(-3, 12, 31)),
  27950. GregDay(-1095, Date(-2, 1, 1)),
  27951. GregDay(-731, Date(-2, 12, 31)),
  27952. GregDay(-730, Date(-1, 1, 1)),
  27953. GregDay(-367, Date(-1, 12, 30)),
  27954. GregDay(-366, Date(-1, 12, 31)),
  27955. GregDay(-365, Date(0, 1, 1)),
  27956. GregDay(-31, Date(0, 11, 30)),
  27957. GregDay(-30, Date(0, 12, 1)),
  27958. GregDay(-1, Date(0, 12, 30)),
  27959. GregDay(0, Date(0, 12, 31))];
  27960. auto testGregDaysAD = [GregDay(1, Date(1, 1, 1)),
  27961. GregDay(2, Date(1, 1, 2)),
  27962. GregDay(32, Date(1, 2, 1)),
  27963. GregDay(365, Date(1, 12, 31)),
  27964. GregDay(366, Date(2, 1, 1)),
  27965. GregDay(731, Date(3, 1, 1)),
  27966. GregDay(1096, Date(4, 1, 1)),
  27967. GregDay(1097, Date(4, 1, 2)),
  27968. GregDay(1460, Date(4, 12, 30)),
  27969. GregDay(1461, Date(4, 12, 31)),
  27970. GregDay(1462, Date(5, 1, 1)),
  27971. GregDay(17_898, Date(50, 1, 1)),
  27972. GregDay(35_065, Date(97, 1, 1)),
  27973. GregDay(36_160, Date(100, 1, 1)),
  27974. GregDay(36_525, Date(101, 1, 1)),
  27975. GregDay(37_986, Date(105, 1, 1)),
  27976. GregDay(72_684, Date(200, 1, 1)),
  27977. GregDay(73_049, Date(201, 1, 1)),
  27978. GregDay(109_208, Date(300, 1, 1)),
  27979. GregDay(109_573, Date(301, 1, 1)),
  27980. GregDay(145_732, Date(400, 1, 1)),
  27981. GregDay(146_098, Date(401, 1, 1)),
  27982. GregDay(182_257, Date(500, 1, 1)),
  27983. GregDay(182_622, Date(501, 1, 1)),
  27984. GregDay(364_878, Date(1000, 1, 1)),
  27985. GregDay(365_243, Date(1001, 1, 1)),
  27986. GregDay(584_023, Date(1600, 1, 1)),
  27987. GregDay(584_389, Date(1601, 1, 1)),
  27988. GregDay(693_596, Date(1900, 1, 1)),
  27989. GregDay(693_961, Date(1901, 1, 1)),
  27990. GregDay(729_755, Date(1999, 1, 1)),
  27991. GregDay(730_120, Date(2000, 1, 1)),
  27992. GregDay(730_121, Date(2000, 1, 2)),
  27993. GregDay(730_484, Date(2000, 12, 30)),
  27994. GregDay(730_485, Date(2000, 12, 31)),
  27995. GregDay(730_486, Date(2001, 1, 1)),
  27996. GregDay(733_773, Date(2010, 1, 1)),
  27997. GregDay(733_774, Date(2010, 1, 2)),
  27998. GregDay(733_803, Date(2010, 1, 31)),
  27999. GregDay(733_804, Date(2010, 2, 1)),
  28000. GregDay(733_831, Date(2010, 2, 28)),
  28001. GregDay(733_832, Date(2010, 3, 1)),
  28002. GregDay(733_862, Date(2010, 3, 31)),
  28003. GregDay(733_863, Date(2010, 4, 1)),
  28004. GregDay(733_892, Date(2010, 4, 30)),
  28005. GregDay(733_893, Date(2010, 5, 1)),
  28006. GregDay(733_923, Date(2010, 5, 31)),
  28007. GregDay(733_924, Date(2010, 6, 1)),
  28008. GregDay(733_953, Date(2010, 6, 30)),
  28009. GregDay(733_954, Date(2010, 7, 1)),
  28010. GregDay(733_984, Date(2010, 7, 31)),
  28011. GregDay(733_985, Date(2010, 8, 1)),
  28012. GregDay(734_015, Date(2010, 8, 31)),
  28013. GregDay(734_016, Date(2010, 9, 1)),
  28014. GregDay(734_045, Date(2010, 9, 30)),
  28015. GregDay(734_046, Date(2010, 10, 1)),
  28016. GregDay(734_076, Date(2010, 10, 31)),
  28017. GregDay(734_077, Date(2010, 11, 1)),
  28018. GregDay(734_106, Date(2010, 11, 30)),
  28019. GregDay(734_107, Date(2010, 12, 1)),
  28020. GregDay(734_136, Date(2010, 12, 30)),
  28021. GregDay(734_137, Date(2010, 12, 31)),
  28022. GregDay(734_503, Date(2012, 1, 1)),
  28023. GregDay(734_534, Date(2012, 2, 1)),
  28024. GregDay(734_561, Date(2012, 2, 28)),
  28025. GregDay(734_562, Date(2012, 2, 29)),
  28026. GregDay(734_563, Date(2012, 3, 1)),
  28027. GregDay(734_858, Date(2012, 12, 21))];
  28028. //I'd use a Tuple, but I get forward reference errors if I try.
  28029. struct DayOfYear { int day; MonthDay md; }
  28030. auto testDaysOfYear = [DayOfYear(1, MonthDay(1, 1)),
  28031. DayOfYear(2, MonthDay(1, 2)),
  28032. DayOfYear(3, MonthDay(1, 3)),
  28033. DayOfYear(31, MonthDay(1, 31)),
  28034. DayOfYear(32, MonthDay(2, 1)),
  28035. DayOfYear(59, MonthDay(2, 28)),
  28036. DayOfYear(60, MonthDay(3, 1)),
  28037. DayOfYear(90, MonthDay(3, 31)),
  28038. DayOfYear(91, MonthDay(4, 1)),
  28039. DayOfYear(120, MonthDay(4, 30)),
  28040. DayOfYear(121, MonthDay(5, 1)),
  28041. DayOfYear(151, MonthDay(5, 31)),
  28042. DayOfYear(152, MonthDay(6, 1)),
  28043. DayOfYear(181, MonthDay(6, 30)),
  28044. DayOfYear(182, MonthDay(7, 1)),
  28045. DayOfYear(212, MonthDay(7, 31)),
  28046. DayOfYear(213, MonthDay(8, 1)),
  28047. DayOfYear(243, MonthDay(8, 31)),
  28048. DayOfYear(244, MonthDay(9, 1)),
  28049. DayOfYear(273, MonthDay(9, 30)),
  28050. DayOfYear(274, MonthDay(10, 1)),
  28051. DayOfYear(304, MonthDay(10, 31)),
  28052. DayOfYear(305, MonthDay(11, 1)),
  28053. DayOfYear(334, MonthDay(11, 30)),
  28054. DayOfYear(335, MonthDay(12, 1)),
  28055. DayOfYear(363, MonthDay(12, 29)),
  28056. DayOfYear(364, MonthDay(12, 30)),
  28057. DayOfYear(365, MonthDay(12, 31))];
  28058. auto testDaysOfLeapYear = [DayOfYear(1, MonthDay(1, 1)),
  28059. DayOfYear(2, MonthDay(1, 2)),
  28060. DayOfYear(3, MonthDay(1, 3)),
  28061. DayOfYear(31, MonthDay(1, 31)),
  28062. DayOfYear(32, MonthDay(2, 1)),
  28063. DayOfYear(59, MonthDay(2, 28)),
  28064. DayOfYear(60, MonthDay(2, 29)),
  28065. DayOfYear(61, MonthDay(3, 1)),
  28066. DayOfYear(91, MonthDay(3, 31)),
  28067. DayOfYear(92, MonthDay(4, 1)),
  28068. DayOfYear(121, MonthDay(4, 30)),
  28069. DayOfYear(122, MonthDay(5, 1)),
  28070. DayOfYear(152, MonthDay(5, 31)),
  28071. DayOfYear(153, MonthDay(6, 1)),
  28072. DayOfYear(182, MonthDay(6, 30)),
  28073. DayOfYear(183, MonthDay(7, 1)),
  28074. DayOfYear(213, MonthDay(7, 31)),
  28075. DayOfYear(214, MonthDay(8, 1)),
  28076. DayOfYear(244, MonthDay(8, 31)),
  28077. DayOfYear(245, MonthDay(9, 1)),
  28078. DayOfYear(274, MonthDay(9, 30)),
  28079. DayOfYear(275, MonthDay(10, 1)),
  28080. DayOfYear(305, MonthDay(10, 31)),
  28081. DayOfYear(306, MonthDay(11, 1)),
  28082. DayOfYear(335, MonthDay(11, 30)),
  28083. DayOfYear(336, MonthDay(12, 1)),
  28084. DayOfYear(364, MonthDay(12, 29)),
  28085. DayOfYear(365, MonthDay(12, 30)),
  28086. DayOfYear(366, MonthDay(12, 31))];
  28087. static this()
  28088. {
  28089. currLocalDiffFromUTC = Clock.currTime(UTC()) -
  28090. Clock.currTime(LocalTime());
  28091. immutable simpleTZ = new SimpleTimeZone(cast(int)
  28092. (currLocalDiffFromUTC + dur!"hours"(2)).total!"minutes"());
  28093. immutable lt = LocalTime().utcToTZ(0);
  28094. immutable st = simpleTZ.utcToTZ(0);
  28095. auto diffs = [0, lt, st];
  28096. auto diffAA = [0 : cast(immutable TimeZone)UTC(),
  28097. lt : cast(immutable TimeZone)LocalTime(),
  28098. st : cast(immutable TimeZone)simpleTZ];
  28099. sort(diffs);
  28100. testTZs = [diffAA[diffs[0]], diffAA[diffs[1]], diffAA[diffs[2]]];
  28101. testFracSecs = [FracSec.from!"hnsecs"(0),
  28102. FracSec.from!"hnsecs"(1),
  28103. FracSec.from!"hnsecs"(5007),
  28104. FracSec.from!"hnsecs"(9999999)];
  28105. foreach(year; testYearsBC)
  28106. {
  28107. foreach(md; testMonthDays)
  28108. testDatesBC ~= Date(year, md.month, md.day);
  28109. }
  28110. foreach(year; testYearsAD)
  28111. {
  28112. foreach(md; testMonthDays)
  28113. testDatesAD ~= Date(year, md.month, md.day);
  28114. }
  28115. foreach(dt; testDatesBC)
  28116. {
  28117. foreach(tod; testTODs)
  28118. testDateTimesBC ~= DateTime(dt, tod);
  28119. }
  28120. foreach(dt; testDatesAD)
  28121. {
  28122. foreach(tod; testTODs)
  28123. testDateTimesAD ~= DateTime(dt, tod);
  28124. }
  28125. foreach(dt; testDateTimesBC)
  28126. {
  28127. foreach(tz; testTZs)
  28128. {
  28129. foreach(fs; testFracSecs)
  28130. testSysTimesBC ~= SysTime(dt, fs, tz);
  28131. }
  28132. }
  28133. foreach(dt; testDateTimesAD)
  28134. {
  28135. foreach(tz; testTZs)
  28136. {
  28137. foreach(fs; testFracSecs)
  28138. testSysTimesAD ~= SysTime(dt, fs, tz);
  28139. }
  28140. }
  28141. }
  28142. }
  28143. //==============================================================================
  28144. // Unit testing functions.
  28145. //==============================================================================
  28146. void _assertPred(string op, L, R)
  28147. (L lhs, R rhs, lazy string msg = null, string file = __FILE__, size_t line = __LINE__)
  28148. if((op == "<" ||
  28149. op == "<=" ||
  28150. op == "==" ||
  28151. op == "!=" ||
  28152. op == ">=" ||
  28153. op == ">") &&
  28154. __traits(compiles, mixin("lhs " ~ op ~ " rhs")) &&
  28155. _isPrintable!L &&
  28156. _isPrintable!R)
  28157. {
  28158. immutable result = mixin("lhs " ~ op ~ " rhs");
  28159. if(!result)
  28160. {
  28161. if(msg.empty)
  28162. throw new AssertError(format(`_assertPred!"%s" failed: [%s] is not %s [%s].`, op, lhs, op, rhs), file, line);
  28163. else
  28164. throw new AssertError(format(`_assertPred!"%s" failed: [%s] is not %s [%s]: %s`, op, lhs, op, rhs, msg), file, line);
  28165. }
  28166. }
  28167. unittest
  28168. {
  28169. version(testStdDateTime)
  28170. {
  28171. struct IntWrapper
  28172. {
  28173. int value;
  28174. this(int value)
  28175. {
  28176. this.value = value;
  28177. }
  28178. string toString()
  28179. {
  28180. return to!string(value);
  28181. }
  28182. }
  28183. //Test ==.
  28184. assertNotThrown!AssertError(_assertPred!"=="(6, 6));
  28185. assertNotThrown!AssertError(_assertPred!"=="(6, 6.0));
  28186. assertNotThrown!AssertError(_assertPred!"=="(IntWrapper(6), IntWrapper(6)));
  28187. assertThrown!AssertError(_assertPred!"=="(6, 7));
  28188. assertThrown!AssertError(_assertPred!"=="(6, 6.1));
  28189. assertThrown!AssertError(_assertPred!"=="(IntWrapper(6), IntWrapper(7)));
  28190. assertThrown!AssertError(_assertPred!"=="(IntWrapper(7), IntWrapper(6)));
  28191. _assertPred!"=="(collectExceptionMsg!AssertError(_assertPred!"=="(6, 7)),
  28192. `_assertPred!"==" failed: [6] is not == [7].`);
  28193. _assertPred!"=="(collectExceptionMsg!AssertError(_assertPred!"=="(6, 7, "It failed!")),
  28194. `_assertPred!"==" failed: [6] is not == [7]: It failed!`);
  28195. //Test !=.
  28196. assertNotThrown!AssertError(_assertPred!"!="(6, 7));
  28197. assertNotThrown!AssertError(_assertPred!"!="(6, 6.1));
  28198. assertNotThrown!AssertError(_assertPred!"!="(IntWrapper(6), IntWrapper(7)));
  28199. assertNotThrown!AssertError(_assertPred!"!="(IntWrapper(7), IntWrapper(6)));
  28200. assertThrown!AssertError(_assertPred!"!="(6, 6));
  28201. assertThrown!AssertError(_assertPred!"!="(6, 6.0));
  28202. assertThrown!AssertError(_assertPred!"!="(IntWrapper(6), IntWrapper(6)));
  28203. _assertPred!"=="(collectExceptionMsg!AssertError(_assertPred!"!="(6, 6)),
  28204. `_assertPred!"!=" failed: [6] is not != [6].`);
  28205. _assertPred!"=="(collectExceptionMsg!AssertError(_assertPred!"!="(6, 6, "It failed!")),
  28206. `_assertPred!"!=" failed: [6] is not != [6]: It failed!`);
  28207. //Test <, <=, >=, >.
  28208. assertNotThrown!AssertError(_assertPred!"<"(5, 7));
  28209. assertNotThrown!AssertError(_assertPred!"<="(5, 7));
  28210. assertNotThrown!AssertError(_assertPred!"<="(5, 5));
  28211. assertNotThrown!AssertError(_assertPred!">="(7, 7));
  28212. assertNotThrown!AssertError(_assertPred!">="(7, 5));
  28213. assertNotThrown!AssertError(_assertPred!">"(7, 5));
  28214. assertThrown!AssertError(_assertPred!"<"(7, 5));
  28215. assertThrown!AssertError(_assertPred!"<="(7, 5));
  28216. assertThrown!AssertError(_assertPred!">="(5, 7));
  28217. assertThrown!AssertError(_assertPred!">"(5, 7));
  28218. _assertPred!"=="(collectExceptionMsg!AssertError(_assertPred!"<"(7, 5)),
  28219. `_assertPred!"<" failed: [7] is not < [5].`);
  28220. _assertPred!"=="(collectExceptionMsg!AssertError(_assertPred!"<"(7, 5, "It failed!")),
  28221. `_assertPred!"<" failed: [7] is not < [5]: It failed!`);
  28222. //Verify Examples.
  28223. //Equivalent to assert(5 / 2 + 4 < 27);
  28224. _assertPred!"<"(5 / 2 + 4, 27);
  28225. //Equivalent to assert(4 <= 5);
  28226. _assertPred!"<="(4, 5);
  28227. //Equivalent to assert(1 * 2.1 == 2.1);
  28228. _assertPred!"=="(1 * 2.1, 2.1);
  28229. //Equivalent to assert("hello " ~ "world" != "goodbye world");
  28230. _assertPred!"!="("hello " ~ "world", "goodbye world");
  28231. //Equivalent to assert(14.2 >= 14);
  28232. _assertPred!">="(14.2, 14);
  28233. //Equivalent to assert(15 > 2 + 1);
  28234. _assertPred!">"(15, 2 + 1);
  28235. assert(collectExceptionMsg!AssertError(_assertPred!"=="("hello", "goodbye")) ==
  28236. `_assertPred!"==" failed: [hello] is not == [goodbye].`);
  28237. assert(collectExceptionMsg!AssertError(_assertPred!"<"(5, 2, "My test failed!")) ==
  28238. `_assertPred!"<" failed: [5] is not < [2]: My test failed!`);
  28239. }
  28240. }
  28241. void _assertPred(string func, string expected, L, R)
  28242. (L lhs, R rhs, lazy string msg = null, string file = __FILE__, size_t line = __LINE__)
  28243. if(func == "opCmp" &&
  28244. (expected == "<" ||
  28245. expected == "==" ||
  28246. expected == ">") &&
  28247. __traits(compiles, lhs.opCmp(rhs)) &&
  28248. _isPrintable!L &&
  28249. _isPrintable!R)
  28250. {
  28251. immutable result = lhs.opCmp(rhs);
  28252. static if(expected == "<")
  28253. {
  28254. if(result < 0)
  28255. return;
  28256. if(result == 0)
  28257. {
  28258. if(msg.empty)
  28259. throw new AssertError(format(`_assertPred!("opCmp", "<") failed: [%s] == [%s].`, lhs, rhs), file, line);
  28260. else
  28261. throw new AssertError(format(`_assertPred!("opCmp", "<") failed: [%s] == [%s]: %s`, lhs, rhs, msg), file, line);
  28262. }
  28263. else
  28264. {
  28265. if(msg.empty)
  28266. throw new AssertError(format(`_assertPred!("opCmp", "<") failed: [%s] > [%s].`, lhs, rhs), file, line);
  28267. else
  28268. throw new AssertError(format(`_assertPred!("opCmp", "<") failed: [%s] > [%s]: %s`, lhs, rhs, msg), file, line);
  28269. }
  28270. }
  28271. else static if(expected == "==")
  28272. {
  28273. if(result == 0)
  28274. return;
  28275. if(result < 0)
  28276. {
  28277. if(msg.empty)
  28278. throw new AssertError(format(`_assertPred!("opCmp", "==") failed: [%s] < [%s].`, lhs, rhs), file, line);
  28279. else
  28280. throw new AssertError(format(`_assertPred!("opCmp", "==") failed: [%s] < [%s]: %s`, lhs, rhs, msg), file, line);
  28281. }
  28282. else
  28283. {
  28284. if(msg.empty)
  28285. throw new AssertError(format(`_assertPred!("opCmp", "==") failed: [%s] > [%s].`, lhs, rhs), file, line);
  28286. else
  28287. throw new AssertError(format(`_assertPred!("opCmp", "==") failed: [%s] > [%s]: %s`, lhs, rhs, msg), file, line);
  28288. }
  28289. }
  28290. else static if(expected == ">")
  28291. {
  28292. if(result > 0)
  28293. return;
  28294. if(result < 0)
  28295. {
  28296. if(msg.empty)
  28297. throw new AssertError(format(`_assertPred!("opCmp", ">") failed: [%s] < [%s].`, lhs, rhs), file, line);
  28298. else
  28299. throw new AssertError(format(`_assertPred!("opCmp", ">") failed: [%s] < [%s]: %s`, lhs, rhs, msg), file, line);
  28300. }
  28301. else
  28302. {
  28303. if(msg.empty)
  28304. throw new AssertError(format(`_assertPred!("opCmp", ">") failed: [%s] == [%s].`, lhs, rhs), file, line);
  28305. else
  28306. throw new AssertError(format(`_assertPred!("opCmp", ">") failed: [%s] == [%s]: %s`, lhs, rhs, msg), file, line);
  28307. }
  28308. }
  28309. else
  28310. static assert(0);
  28311. }
  28312. void _assertPred(string op, L, R, E)
  28313. (L lhs, R rhs, E expected, lazy string msg = null, string file = __FILE__, size_t line = __LINE__)
  28314. if((op == "+=" ||
  28315. op == "-=" ||
  28316. op == "*=" ||
  28317. op == "/=" ||
  28318. op == "%=" ||
  28319. op == "^^=" ||
  28320. op == "&=" ||
  28321. op == "|=" ||
  28322. op == "^=" ||
  28323. op == "<<=" ||
  28324. op == ">>=" ||
  28325. op == ">>>=" ||
  28326. op == "~=") &&
  28327. __traits(compiles, mixin("lhs " ~ op ~ " rhs")) &&
  28328. __traits(compiles, mixin("(lhs " ~ op ~ " rhs) == expected")) &&
  28329. _isPrintable!L &&
  28330. _isPrintable!R)
  28331. {
  28332. immutable origLHSStr = to!string(lhs);
  28333. const result = mixin("lhs " ~ op ~ " rhs");
  28334. if(lhs != expected)
  28335. {
  28336. if(msg.empty)
  28337. {
  28338. throw new AssertError(format(`_assertPred!"%s" failed: After [%s] %s [%s], lhs was assigned to [%s] instead of [%s].`,
  28339. op,
  28340. origLHSStr,
  28341. op,
  28342. rhs,
  28343. lhs,
  28344. expected),
  28345. file,
  28346. line);
  28347. }
  28348. else
  28349. {
  28350. throw new AssertError(format(`_assertPred!"%s" failed: After [%s] %s [%s], lhs was assigned to [%s] instead of [%s]: %s`,
  28351. op,
  28352. origLHSStr,
  28353. op,
  28354. rhs,
  28355. lhs,
  28356. expected,
  28357. msg),
  28358. file,
  28359. line);
  28360. }
  28361. }
  28362. if(result != expected)
  28363. {
  28364. if(msg.empty)
  28365. {
  28366. throw new AssertError(format(`_assertPred!"%s" failed: Return value of [%s] %s [%s] was [%s] instead of [%s].`,
  28367. op,
  28368. origLHSStr,
  28369. op,
  28370. rhs,
  28371. result,
  28372. expected),
  28373. file,
  28374. line);
  28375. }
  28376. else
  28377. {
  28378. throw new AssertError(format(`_assertPred!"%s" failed: Return value of [%s] %s [%s] was [%s] instead of [%s]: %s`,
  28379. op,
  28380. origLHSStr,
  28381. op,
  28382. rhs,
  28383. result,
  28384. expected,
  28385. msg),
  28386. file,
  28387. line);
  28388. }
  28389. }
  28390. }
  28391. unittest
  28392. {
  28393. version(testStdDateTime)
  28394. {
  28395. assertNotThrown!AssertError(_assertPred!"+="(7, 5, 12));
  28396. assertNotThrown!AssertError(_assertPred!"-="(7, 5, 2));
  28397. assertNotThrown!AssertError(_assertPred!"*="(7, 5, 35));
  28398. assertNotThrown!AssertError(_assertPred!"/="(7, 5, 1));
  28399. assertNotThrown!AssertError(_assertPred!"%="(7, 5, 2));
  28400. assertNotThrown!AssertError(_assertPred!"^^="(7, 5, 16_807));
  28401. assertNotThrown!AssertError(_assertPred!"&="(7, 5, 5));
  28402. assertNotThrown!AssertError(_assertPred!"|="(7, 5, 7));
  28403. assertNotThrown!AssertError(_assertPred!"^="(7, 5, 2));
  28404. assertNotThrown!AssertError(_assertPred!"<<="(7, 1, 14));
  28405. assertNotThrown!AssertError(_assertPred!">>="(7, 1, 3));
  28406. assertNotThrown!AssertError(_assertPred!">>>="(-7, 1, 2_147_483_644));
  28407. assertNotThrown!AssertError(_assertPred!"~="("hello ", "world", "hello world"));
  28408. assertThrown!AssertError(_assertPred!"+="(7, 5, 0));
  28409. assertThrown!AssertError(_assertPred!"-="(7, 5, 0));
  28410. assertThrown!AssertError(_assertPred!"*="(7, 5, 0));
  28411. assertThrown!AssertError(_assertPred!"/="(7, 5, 0));
  28412. assertThrown!AssertError(_assertPred!"%="(7, 5, 0));
  28413. assertThrown!AssertError(_assertPred!"^^="(7, 5, 0));
  28414. assertThrown!AssertError(_assertPred!"&="(7, 5, 0));
  28415. assertThrown!AssertError(_assertPred!"|="(7, 5, 0));
  28416. assertThrown!AssertError(_assertPred!"^="(7, 5, 0));
  28417. assertThrown!AssertError(_assertPred!"<<="(7, 1, 0));
  28418. assertThrown!AssertError(_assertPred!">>="(7, 1, 0));
  28419. assertThrown!AssertError(_assertPred!">>>="(-7, 1, 0));
  28420. assertThrown!AssertError(_assertPred!"~="("hello ", "world", "goodbye world"));
  28421. _assertPred!"=="(collectExceptionMsg!AssertError(_assertPred!"+="(7, 5, 11)),
  28422. `_assertPred!"+=" failed: After [7] += [5], lhs was assigned to [12] instead of [11].`);
  28423. _assertPred!"=="(collectExceptionMsg!AssertError(_assertPred!"+="(7, 5, 11, "It failed!")),
  28424. `_assertPred!"+=" failed: After [7] += [5], lhs was assigned to [12] instead of [11]: It failed!`);
  28425. _assertPred!"=="(collectExceptionMsg!AssertError(_assertPred!"^^="(7, 5, 42)),
  28426. `_assertPred!"^^=" failed: After [7] ^^= [5], lhs was assigned to [16807] instead of [42].`);
  28427. _assertPred!"=="(collectExceptionMsg!AssertError(_assertPred!"^^="(7, 5, 42, "It failed!")),
  28428. `_assertPred!"^^=" failed: After [7] ^^= [5], lhs was assigned to [16807] instead of [42]: It failed!`);
  28429. _assertPred!"=="(collectExceptionMsg!AssertError(_assertPred!"~="("hello ", "world", "goodbye world")),
  28430. `_assertPred!"~=" failed: After [hello ] ~= [world], lhs was assigned to [hello world] instead of [goodbye world].`);
  28431. _assertPred!"=="(collectExceptionMsg!AssertError(_assertPred!"~="("hello ", "world", "goodbye world", "It failed!")),
  28432. `_assertPred!"~=" failed: After [hello ] ~= [world], lhs was assigned to [hello world] instead of [goodbye world]: It failed!`);
  28433. struct IntWrapper
  28434. {
  28435. int value;
  28436. this(int value)
  28437. {
  28438. this.value = value;
  28439. }
  28440. IntWrapper opOpAssign(string op)(IntWrapper rhs)
  28441. {
  28442. mixin("this.value " ~ op ~ "= rhs.value;");
  28443. return this;
  28444. }
  28445. string toString()
  28446. {
  28447. return to!string(value);
  28448. }
  28449. }
  28450. struct IntWrapper_BadAssign
  28451. {
  28452. int value;
  28453. this(int value)
  28454. {
  28455. this.value = value;
  28456. }
  28457. IntWrapper_BadAssign opOpAssign(string op)(IntWrapper_BadAssign rhs)
  28458. {
  28459. auto old = this.value;
  28460. mixin("this.value " ~ op ~ "= -rhs.value;");
  28461. return IntWrapper_BadAssign(mixin("old " ~ op ~ " rhs.value"));
  28462. }
  28463. string toString()
  28464. {
  28465. return to!string(value);
  28466. }
  28467. }
  28468. struct IntWrapper_BadReturn
  28469. {
  28470. int value;
  28471. this(int value)
  28472. {
  28473. this.value = value;
  28474. }
  28475. IntWrapper_BadReturn opOpAssign(string op)(IntWrapper_BadReturn rhs)
  28476. {
  28477. mixin("this.value " ~ op ~ "= rhs.value;");
  28478. return IntWrapper_BadReturn(rhs.value);
  28479. }
  28480. string toString()
  28481. {
  28482. return to!string(value);
  28483. }
  28484. }
  28485. assertNotThrown!AssertError(_assertPred!"+="(IntWrapper(5), IntWrapper(2), IntWrapper(7)));
  28486. assertNotThrown!AssertError(_assertPred!"*="(IntWrapper(5), IntWrapper(2), IntWrapper(10)));
  28487. assertThrown!AssertError(_assertPred!"+="(IntWrapper_BadAssign(5), IntWrapper_BadAssign(2), IntWrapper_BadAssign(7)));
  28488. assertThrown!AssertError(_assertPred!"+="(IntWrapper_BadReturn(5), IntWrapper_BadReturn(2), IntWrapper_BadReturn(7)));
  28489. assertThrown!AssertError(_assertPred!"*="(IntWrapper_BadAssign(5), IntWrapper_BadAssign(2), IntWrapper_BadAssign(10)));
  28490. assertThrown!AssertError(_assertPred!"*="(IntWrapper_BadReturn(5), IntWrapper_BadReturn(2), IntWrapper_BadReturn(10)));
  28491. _assertPred!"=="(collectExceptionMsg!AssertError(_assertPred!"+="(IntWrapper_BadAssign(5), IntWrapper_BadAssign(2), IntWrapper_BadAssign(7))),
  28492. `_assertPred!"+=" failed: After [5] += [2], lhs was assigned to [3] instead of [7].`);
  28493. _assertPred!"=="(collectExceptionMsg!AssertError(_assertPred!"+="(IntWrapper_BadAssign(5), IntWrapper_BadAssign(2), IntWrapper_BadAssign(7), "It failed!")),
  28494. `_assertPred!"+=" failed: After [5] += [2], lhs was assigned to [3] instead of [7]: It failed!`);
  28495. _assertPred!"=="(collectExceptionMsg!AssertError(_assertPred!"+="(IntWrapper_BadReturn(5), IntWrapper_BadReturn(2), IntWrapper_BadReturn(7))),
  28496. `_assertPred!"+=" failed: Return value of [5] += [2] was [2] instead of [7].`);
  28497. _assertPred!"=="(collectExceptionMsg!AssertError(_assertPred!"+="(IntWrapper_BadReturn(5), IntWrapper_BadReturn(2), IntWrapper_BadReturn(7), "It failed!")),
  28498. `_assertPred!"+=" failed: Return value of [5] += [2] was [2] instead of [7]: It failed!`);
  28499. _assertPred!"=="(collectExceptionMsg!AssertError(_assertPred!"*="(IntWrapper_BadAssign(5), IntWrapper_BadAssign(2), IntWrapper_BadAssign(10))),
  28500. `_assertPred!"*=" failed: After [5] *= [2], lhs was assigned to [-10] instead of [10].`);
  28501. _assertPred!"=="(collectExceptionMsg!AssertError(_assertPred!"*="(IntWrapper_BadAssign(5), IntWrapper_BadAssign(2), IntWrapper_BadAssign(10), "It failed!")),
  28502. `_assertPred!"*=" failed: After [5] *= [2], lhs was assigned to [-10] instead of [10]: It failed!`);
  28503. _assertPred!"=="(collectExceptionMsg!AssertError(_assertPred!"*="(IntWrapper_BadReturn(5), IntWrapper_BadReturn(2), IntWrapper_BadReturn(10))),
  28504. `_assertPred!"*=" failed: Return value of [5] *= [2] was [2] instead of [10].`);
  28505. _assertPred!"=="(collectExceptionMsg!AssertError(_assertPred!"*="(IntWrapper_BadReturn(5), IntWrapper_BadReturn(2), IntWrapper_BadReturn(10), "It failed!")),
  28506. `_assertPred!"*=" failed: Return value of [5] *= [2] was [2] instead of [10]: It failed!`);
  28507. }
  28508. }
  28509. template _isPrintable(T...)
  28510. {
  28511. static if(T.length == 0)
  28512. enum _isPrintable = true;
  28513. else static if(T.length == 1)
  28514. {
  28515. enum _isPrintable = (!isArray!(T[0]) && __traits(compiles, to!string(T[0].init))) ||
  28516. (isArray!(T[0]) && __traits(compiles, to!string(T[0].init[0])));
  28517. }
  28518. else
  28519. {
  28520. enum _isPrintable = _isPrintable!(T[0]) && _isPrintable!(T[1 .. $]);
  28521. }
  28522. }
  28523. template softDeprec(string vers, string date, string oldFunc, string newFunc)
  28524. {
  28525. enum softDeprec = Format!("Notice: As of Phobos %s, std.datetime.%s has been scheduled " ~
  28526. "for deprecation in %s. Please use std.datetime.%s instead.",
  28527. vers, oldFunc, date, newFunc);
  28528. }