PageRenderTime 76ms CodeModel.GetById 34ms RepoModel.GetById 1ms app.codeStats 3ms

/d/phobos2/std/datetime.d

https://bitbucket.org/alexrp/gdc
D | 8509 lines | 6008 code | 1083 blank | 1418 comment | 252 complexity | 5de7024b9dda482701bc9e52fc10a811 MD5 | raw file
Possible License(s): GPL-2.0, AGPL-1.0

Large files files are truncated, but you can click here to view the full file

  1. //Written in the D programming language
  2. /++
  3. Module containing Date/Time functionality.
  4. This module provides:
  5. $(UL
  6. $(LI Types to represent points in time: $(D SysTime), $(D Date),
  7. $(D TimeOfDay), and $(D DateTime).)
  8. $(LI Types to represent 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(…

Large files files are truncated, but you can click here to view the full file