1 // Written in the D programming language
2
3 /++
4 License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
5 Authors: Jonathan M Davis
6 Source: $(PHOBOSSRC std/datetime/_systime.d)
7 +/
8 module std.datetime.systime;
9
10 import core.time;
11 import std.datetime.date;
12 import std.datetime.timezone;
13 import std.exception : enforce;
14 import std.format : format;
15 import std.range.primitives;
16 import std.traits : isIntegral, isSigned, isSomeString, Unqual;
17
version(Windows)18 version (Windows)
19 {
20 import core.stdc.time : time_t;
21 import core.sys.windows.windows;
22 import core.sys.windows.winsock2;
23 }
version(Posix)24 else version (Posix)
25 {
26 import core.sys.posix.signal : timespec;
27 import core.sys.posix.sys.types : time_t;
28 }
29
version(unittest)30 version (unittest)
31 {
32 import core.exception : AssertError;
33 import std.exception : assertThrown;
34 }
35
36
37 @safe unittest
38 {
39 initializeTests();
40 }
41
42
43 /++
44 Effectively a namespace to make it clear that the methods it contains are
45 getting the time from the system clock. It cannot be instantiated.
46 +/
47 final class Clock
48 {
49 public:
50
51 /++
52 Returns the current time in the given time zone.
53
54 Params:
55 clockType = The $(REF ClockType, core,time) indicates which system
56 clock to use to get the current time. Very few programs
57 need to use anything other than the default.
58 tz = The time zone for the SysTime that's returned.
59
60 Throws:
61 $(REF DateTimeException,std,datetime,date) if it fails to get the
62 time.
63 +/
64 static SysTime currTime(ClockType clockType = ClockType.normal)(immutable TimeZone tz = LocalTime()) @safe
65 {
66 return SysTime(currStdTime!clockType, tz);
67 }
68
69 @safe unittest
70 {
71 import std.format : format;
72 import std.stdio : writefln;
73 assert(currTime().timezone is LocalTime());
74 assert(currTime(UTC()).timezone is UTC());
75
76 // core.stdc.time.time does not always use unix time on Windows systems.
77 // In particular, dmc does not use unix time. If we can guarantee that
78 // the MS runtime uses unix time, then we may be able run this test
79 // then, but for now, we're just not going to run this test on Windows.
version(Posix)80 version (Posix)
81 {
82 static import core.stdc.time;
83 static import std.math;
84 immutable unixTimeD = currTime().toUnixTime();
85 immutable unixTimeC = core.stdc.time.time(null);
86 assert(std.math.abs(unixTimeC - unixTimeD) <= 2);
87 }
88
89 auto norm1 = Clock.currTime;
90 auto norm2 = Clock.currTime(UTC());
91 assert(norm1 <= norm2, format("%s %s", norm1, norm2));
92 assert(abs(norm1 - norm2) <= seconds(2));
93
94 import std.meta : AliasSeq;
95 foreach (ct; AliasSeq!(ClockType.coarse, ClockType.precise, ClockType.second))
96 {
97 scope(failure) writefln("ClockType.%s", ct);
98 auto value1 = Clock.currTime!ct;
99 auto value2 = Clock.currTime!ct(UTC());
100 assert(value1 <= value2, format("%s %s", value1, value2));
101 assert(abs(value1 - value2) <= seconds(2));
102 }
103 }
104
105
106 /++
107 Returns the number of hnsecs since midnight, January 1st, 1 A.D. for the
108 current time.
109
110 Params:
111 clockType = The $(REF ClockType, core,time) indicates which system
112 clock to use to get the current time. Very few programs
113 need to use anything other than the default.
114
115 Throws:
116 $(REF DateTimeException,std,datetime,date) if it fails to get the
117 time.
118 +/
119 static @property long currStdTime(ClockType clockType = ClockType.normal)() @trusted
120 {
121 static if (clockType != ClockType.coarse &&
122 clockType != ClockType.normal &&
123 clockType != ClockType.precise &&
124 clockType != ClockType.second)
125 {
126 static assert(0, format("ClockType.%s is not supported by Clock.currTime or Clock.currStdTime", clockType));
127 }
128
version(Windows)129 version (Windows)
130 {
131 FILETIME fileTime;
132 GetSystemTimeAsFileTime(&fileTime);
133 immutable result = FILETIMEToStdTime(&fileTime);
134 static if (clockType == ClockType.second)
135 {
136 // Ideally, this would use core.std.time.time, but the C runtime
137 // has to be using unix time for that to work, and that's not
138 // guaranteed on Windows. Digital Mars does not use unix time.
139 // MS may or may not. If it does, then this can be made to use
140 // core.stdc.time for MS, but for now, we'll leave it like this.
141 return convert!("seconds", "hnsecs")(convert!("hnsecs", "seconds")(result));
142 }
143 else
144 return result;
145 }
version(Posix)146 else version (Posix)
147 {
148 static import core.stdc.time;
149 enum hnsecsToUnixEpoch = unixTimeToStdTime(0);
150
151 version (OSX)
152 {
153 static if (clockType == ClockType.second)
154 return unixTimeToStdTime(core.stdc.time.time(null));
155 else
156 {
157 import core.sys.posix.sys.time : gettimeofday, timeval;
158 timeval tv;
159 if (gettimeofday(&tv, null) != 0)
160 throw new TimeException("Call to gettimeofday() failed");
161 return convert!("seconds", "hnsecs")(tv.tv_sec) +
162 convert!("usecs", "hnsecs")(tv.tv_usec) +
163 hnsecsToUnixEpoch;
164 }
165 }
166 else version (linux)
167 {
168 static if (clockType == ClockType.second)
169 return unixTimeToStdTime(core.stdc.time.time(null));
170 else
171 {
172 import core.sys.linux.time : CLOCK_REALTIME_COARSE;
173 import core.sys.posix.time : clock_gettime, CLOCK_REALTIME;
174 static if (clockType == ClockType.coarse) alias clockArg = CLOCK_REALTIME_COARSE;
175 else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME;
176 else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME;
177 else static assert(0, "Previous static if is wrong.");
178 timespec ts;
179 if (clock_gettime(clockArg, &ts) != 0)
180 throw new TimeException("Call to clock_gettime() failed");
181 return convert!("seconds", "hnsecs")(ts.tv_sec) +
182 ts.tv_nsec / 100 +
183 hnsecsToUnixEpoch;
184 }
185 }
186 else version (FreeBSD)
187 {
188 import core.sys.freebsd.time : clock_gettime, CLOCK_REALTIME,
189 CLOCK_REALTIME_FAST, CLOCK_REALTIME_PRECISE, CLOCK_SECOND;
190 static if (clockType == ClockType.coarse) alias clockArg = CLOCK_REALTIME_FAST;
191 else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME;
192 else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME_PRECISE;
193 else static if (clockType == ClockType.second) alias clockArg = CLOCK_SECOND;
194 else static assert(0, "Previous static if is wrong.");
195 timespec ts;
196 if (clock_gettime(clockArg, &ts) != 0)
197 throw new TimeException("Call to clock_gettime() failed");
198 return convert!("seconds", "hnsecs")(ts.tv_sec) +
199 ts.tv_nsec / 100 +
200 hnsecsToUnixEpoch;
201 }
202 else version (NetBSD)
203 {
204 static if (clockType == ClockType.second)
205 return unixTimeToStdTime(core.stdc.time.time(null));
206 else
207 {
208 import core.sys.posix.sys.time : gettimeofday, timeval;
209 timeval tv;
210 if (gettimeofday(&tv, null) != 0)
211 throw new TimeException("Call to gettimeofday() failed");
212 return convert!("seconds", "hnsecs")(tv.tv_sec) +
213 convert!("usecs", "hnsecs")(tv.tv_usec) +
214 hnsecsToUnixEpoch;
215 }
216 }
217 else version (DragonFlyBSD)
218 {
219 import core.sys.dragonflybsd.time : clock_gettime, CLOCK_REALTIME,
220 CLOCK_REALTIME_FAST, CLOCK_REALTIME_PRECISE, CLOCK_SECOND;
221 static if (clockType == ClockType.coarse) alias clockArg = CLOCK_REALTIME_FAST;
222 else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME;
223 else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME_PRECISE;
224 else static if (clockType == ClockType.second) alias clockArg = CLOCK_SECOND;
225 else static assert(0, "Previous static if is wrong.");
226 timespec ts;
227 if (clock_gettime(clockArg, &ts) != 0)
228 throw new TimeException("Call to clock_gettime() failed");
229 return convert!("seconds", "hnsecs")(ts.tv_sec) +
230 ts.tv_nsec / 100 +
231 hnsecsToUnixEpoch;
232 }
233 else version (Solaris)
234 {
235 static if (clockType == ClockType.second)
236 return unixTimeToStdTime(core.stdc.time.time(null));
237 else
238 {
239 import core.sys.solaris.time : clock_gettime, CLOCK_REALTIME;
240 static if (clockType == ClockType.coarse) alias clockArg = CLOCK_REALTIME;
241 else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME;
242 else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME;
243 else static assert(0, "Previous static if is wrong.");
244 timespec ts;
245 if (clock_gettime(clockArg, &ts) != 0)
246 throw new TimeException("Call to clock_gettime() failed");
247 return convert!("seconds", "hnsecs")(ts.tv_sec) +
248 ts.tv_nsec / 100 +
249 hnsecsToUnixEpoch;
250 }
251 }
252 else static assert(0, "Unsupported OS");
253 }
254 else static assert(0, "Unsupported OS");
255 }
256
257 @safe unittest
258 {
259 import std.format : format;
260 import std.math : abs;
261 import std.meta : AliasSeq;
262 import std.stdio : writefln;
263 enum limit = convert!("seconds", "hnsecs")(2);
264
265 auto norm1 = Clock.currStdTime;
266 auto norm2 = Clock.currStdTime;
267 assert(norm1 <= norm2, format("%s %s", norm1, norm2));
268 assert(abs(norm1 - norm2) <= limit);
269
270 foreach (ct; AliasSeq!(ClockType.coarse, ClockType.precise, ClockType.second))
271 {
272 scope(failure) writefln("ClockType.%s", ct);
273 auto value1 = Clock.currStdTime!ct;
274 auto value2 = Clock.currStdTime!ct;
275 assert(value1 <= value2, format("%s %s", value1, value2));
276 assert(abs(value1 - value2) <= limit);
277 }
278 }
279
280
281 private:
282
this()283 @disable this() {}
284 }
285
286
287 /++
288 $(D SysTime) is the type used to get the current time from the
289 system or doing anything that involves time zones. Unlike
290 $(REF DateTime,std,datetime,date), the time zone is an integral part of
291 $(D SysTime) (though for local time applications, time zones can be ignored
292 and it will work, since it defaults to using the local time zone). It holds
293 its internal time in std time (hnsecs since midnight, January 1st, 1 A.D.
294 UTC), so it interfaces well with the system time. However, that means that,
295 unlike $(REF DateTime,std,datetime,date), it is not optimized for
296 calendar-based operations, and getting individual units from it such as
297 years or days is going to involve conversions and be less efficient.
298
299 For calendar-based operations that don't
300 care about time zones, then $(REF DateTime,std,datetime,date) would be
301 the type to use. For system time, use $(D SysTime).
302
303 $(LREF Clock.currTime) will return the current time as a $(D SysTime).
304 To convert a $(D SysTime) to a $(REF Date,std,datetime,date) or
305 $(REF DateTime,std,datetime,date), simply cast it. To convert a
306 $(REF Date,std,datetime,date) or $(REF DateTime,std,datetime,date) to a
307 $(D SysTime), use $(D SysTime)'s constructor, and pass in the ntended time
308 zone with it (or don't pass in a $(REF TimeZone,std,datetime,timezone), and
309 the local time zone will be used). Be aware, however, that converting from a
310 $(REF DateTime,std,datetime,date) to a $(D SysTime) will not necessarily
311 be 100% accurate due to DST (one hour of the year doesn't exist and another
312 occurs twice). To not risk any conversion errors, keep times as
313 $(D SysTime)s. Aside from DST though, there shouldn't be any conversion
314 problems.
315
316 For using time zones other than local time or UTC, use
317 $(REF PosixTimeZone,std,datetime,timezone) on Posix systems (or on Windows,
318 if providing the TZ Database files), and use
319 $(REF WindowsTimeZone,std,datetime,timezone) on Windows systems. The time in
320 $(D SysTime) is kept internally in hnsecs from midnight, January 1st, 1 A.D.
321 UTC. Conversion error cannot happen when changing the time zone of a
322 $(D SysTime). $(REF LocalTime,std,datetime,timezone) is the
323 $(REF TimeZone,std,datetime,timezone) class which represents the local time,
324 and $(D UTC) is the $(REF TimeZone,std,datetime,timezone) class which
325 represents UTC. $(D SysTime) uses $(REF LocalTime,std,datetime,timezone) if
326 no $(REF TimeZone,std,datetime,timezone) is provided. For more details on
327 time zones, see the documentation for $(REF TimeZone,std,datetime,timezone),
328 $(REF PosixTimeZone,std,datetime,timezone), and
329 $(REF WindowsTimeZone,std,datetime,timezone).
330
331 $(D SysTime)'s range is from approximately 29,000 B.C. to approximately
332 29,000 A.D.
333 +/
334 struct SysTime
335 {
336 import core.stdc.time : tm;
337 version (Posix) import core.sys.posix.sys.time : timeval;
338 import std.typecons : Rebindable;
339
340 public:
341
342 /++
343 Params:
344 dateTime = The $(REF DateTime,std,datetime,date) to use to set
345 this $(LREF SysTime)'s internal std time. As
346 $(REF DateTime,std,datetime,date) has no concept of
347 time zone, tz is used as its time zone.
348 tz = The $(REF TimeZone,std,datetime,timezone) to use for this
349 $(LREF SysTime). If null,
350 $(REF LocalTime,std,datetime,timezone) will be used. The
351 given $(REF DateTime,std,datetime,date) is assumed to
352 be in the given time zone.
353 +/
354 this(in DateTime dateTime, immutable TimeZone tz = null) @safe nothrow
355 {
356 try
357 this(dateTime, Duration.zero, tz);
358 catch (Exception e)
359 assert(0, "SysTime's constructor threw when it shouldn't have.");
360 }
361
362 @safe unittest
363 {
testSysTime364 static void test(DateTime dt, immutable TimeZone tz, long expected)
365 {
366 auto sysTime = SysTime(dt, tz);
367 assert(sysTime._stdTime == expected);
368 assert(sysTime._timezone is (tz is null ? LocalTime() : tz), format("Given DateTime: %s", dt));
369 }
370
371 test(DateTime.init, UTC(), 0);
372 test(DateTime(1, 1, 1, 12, 30, 33), UTC(), 450_330_000_000L);
373 test(DateTime(0, 12, 31, 12, 30, 33), UTC(), -413_670_000_000L);
374 test(DateTime(1, 1, 1, 0, 0, 0), UTC(), 0);
375 test(DateTime(1, 1, 1, 0, 0, 1), UTC(), 10_000_000L);
376 test(DateTime(0, 12, 31, 23, 59, 59), UTC(), -10_000_000L);
377
378 test(DateTime(1, 1, 1, 0, 0, 0), new immutable SimpleTimeZone(dur!"minutes"(-60)), 36_000_000_000L);
379 test(DateTime(1, 1, 1, 0, 0, 0), new immutable SimpleTimeZone(Duration.zero), 0);
380 test(DateTime(1, 1, 1, 0, 0, 0), new immutable SimpleTimeZone(dur!"minutes"(60)), -36_000_000_000L);
381 }
382
383 /++
384 Params:
385 dateTime = The $(REF DateTime,std,datetime,date) to use to set
386 this $(LREF SysTime)'s internal std time. As
387 $(REF DateTime,std,datetime,date) has no concept of
388 time zone, tz is used as its time zone.
389 fracSecs = The fractional seconds portion of the time.
390 tz = The $(REF TimeZone,std,datetime,timezone) to use for this
391 $(LREF SysTime). If null,
392 $(REF LocalTime,std,datetime,timezone) will be used. The
393 given $(REF DateTime,std,datetime,date) is assumed to
394 be in the given time zone.
395
396 Throws:
397 $(REF DateTimeException,std,datetime,date) if $(D fracSecs) is negative or if it's
398 greater than or equal to one second.
399 +/
400 this(in DateTime dateTime, in Duration fracSecs, immutable TimeZone tz = null) @safe
401 {
402 enforce(fracSecs >= Duration.zero, new DateTimeException("A SysTime cannot have negative fractional seconds."));
403 enforce(fracSecs < seconds(1), new DateTimeException("Fractional seconds must be less than one second."));
404 auto nonNullTZ = tz is null ? LocalTime() : tz;
405
406 immutable dateDiff = dateTime.date - Date.init;
407 immutable todDiff = dateTime.timeOfDay - TimeOfDay.init;
408
409 immutable adjustedTime = dateDiff + todDiff + fracSecs;
410 immutable standardTime = nonNullTZ.tzToUTC(adjustedTime.total!"hnsecs");
411
412 this(standardTime, nonNullTZ);
413 }
414
415 @safe unittest
416 {
417 static void test(DateTime dt, Duration fracSecs, immutable TimeZone tz, long expected)
418 {
419 auto sysTime = SysTime(dt, fracSecs, tz);
420 assert(sysTime._stdTime == expected);
421 assert(sysTime._timezone is (tz is null ? LocalTime() : tz),
422 format("Given DateTime: %s, Given Duration: %s", dt, fracSecs));
423 }
424
425 test(DateTime.init, Duration.zero, UTC(), 0);
426 test(DateTime(1, 1, 1, 12, 30, 33), Duration.zero, UTC(), 450_330_000_000L);
427 test(DateTime(0, 12, 31, 12, 30, 33), Duration.zero, UTC(), -413_670_000_000L);
428 test(DateTime(1, 1, 1, 0, 0, 0), msecs(1), UTC(), 10_000L);
429 test(DateTime(0, 12, 31, 23, 59, 59), msecs(999), UTC(), -10_000L);
430
431 test(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC(), -1);
432 test(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1), UTC(), -9_999_999);
433 test(DateTime(0, 12, 31, 23, 59, 59), Duration.zero, UTC(), -10_000_000);
434
435 assertThrown!DateTimeException(SysTime(DateTime.init, hnsecs(-1), UTC()));
436 assertThrown!DateTimeException(SysTime(DateTime.init, seconds(1), UTC()));
437 }
438
439 /++
440 Params:
441 date = The $(REF Date,std,datetime,date) to use to set this
442 $(LREF SysTime)'s internal std time. As
443 $(REF Date,std,datetime,date) has no concept of time zone, tz
444 is used as its time zone.
445 tz = The $(REF TimeZone,std,datetime,timezone) to use for this
446 $(LREF SysTime). If null,
447 $(REF LocalTime,std,datetime,timezone) will be used. The
448 given $(REF Date,std,datetime,date) is assumed to be in the
449 given time zone.
450 +/
451 this(in Date date, immutable TimeZone tz = null) @safe nothrow
452 {
453 _timezone = tz is null ? LocalTime() : tz;
454
455 try
456 {
457 immutable adjustedTime = (date - Date(1, 1, 1)).total!"hnsecs";
458 immutable standardTime = _timezone.tzToUTC(adjustedTime);
459
460 this(standardTime, _timezone);
461 }
462 catch (Exception e)
463 assert(0, "Date's constructor through when it shouldn't have.");
464 }
465
466 @safe unittest
467 {
testSysTime468 static void test(Date d, immutable TimeZone tz, long expected)
469 {
470 auto sysTime = SysTime(d, tz);
471 assert(sysTime._stdTime == expected);
472 assert(sysTime._timezone is (tz is null ? LocalTime() : tz), format("Given Date: %s", d));
473 }
474
475 test(Date.init, UTC(), 0);
476 test(Date(1, 1, 1), UTC(), 0);
477 test(Date(1, 1, 2), UTC(), 864000000000);
478 test(Date(0, 12, 31), UTC(), -864000000000);
479 }
480
481 /++
482 Note:
483 Whereas the other constructors take in the given date/time, assume
484 that it's in the given time zone, and convert it to hnsecs in UTC
485 since midnight, January 1st, 1 A.D. UTC - i.e. std time - this
486 constructor takes a std time, which is specifically already in UTC,
487 so no conversion takes place. Of course, the various getter
488 properties and functions will use the given time zone's conversion
489 function to convert the results to that time zone, but no conversion
490 of the arguments to this constructor takes place.
491
492 Params:
493 stdTime = The number of hnsecs since midnight, January 1st, 1 A.D.
494 UTC.
495 tz = The $(REF TimeZone,std,datetime,timezone) to use for this
496 $(LREF SysTime). If null,
497 $(REF LocalTime,std,datetime,timezone) will be used.
498 +/
499 this(long stdTime, immutable TimeZone tz = null) @safe pure nothrow
500 {
501 _stdTime = stdTime;
502 _timezone = tz is null ? LocalTime() : tz;
503 }
504
505 @safe unittest
506 {
testSysTime507 static void test(long stdTime, immutable TimeZone tz)
508 {
509 auto sysTime = SysTime(stdTime, tz);
510 assert(sysTime._stdTime == stdTime);
511 assert(sysTime._timezone is (tz is null ? LocalTime() : tz), format("Given stdTime: %s", stdTime));
512 }
513
foreachSysTime514 foreach (stdTime; [-1234567890L, -250, 0, 250, 1235657390L])
515 {
516 foreach (tz; testTZs)
517 test(stdTime, tz);
518 }
519 }
520
521 /++
522 Params:
523 rhs = The $(LREF SysTime) to assign to this one.
524 +/
525 ref SysTime opAssign(const ref SysTime rhs) return @safe pure nothrow
526 {
527 _stdTime = rhs._stdTime;
528 _timezone = rhs._timezone;
529 return this;
530 }
531
532 /++
533 Params:
534 rhs = The $(LREF SysTime) to assign to this one.
535 +/
536 ref SysTime opAssign(SysTime rhs) scope return @safe pure nothrow
537 {
538 _stdTime = rhs._stdTime;
539 _timezone = rhs._timezone;
540 return this;
541 }
542
543 /++
544 Checks for equality between this $(LREF SysTime) and the given
545 $(LREF SysTime).
546
547 Note that the time zone is ignored. Only the internal
548 std times (which are in UTC) are compared.
549 +/
550 bool opEquals(const SysTime rhs) @safe const pure nothrow
551 {
552 return opEquals(rhs);
553 }
554
555 /// ditto
556 bool opEquals(const ref SysTime rhs) @safe const pure nothrow
557 {
558 return _stdTime == rhs._stdTime;
559 }
560
561 @safe unittest
562 {
563 import std.range : chain;
564
565 assert(SysTime(DateTime.init, UTC()) == SysTime(0, UTC()));
566 assert(SysTime(DateTime.init, UTC()) == SysTime(0));
567 assert(SysTime(Date.init, UTC()) == SysTime(0));
568 assert(SysTime(0) == SysTime(0));
569
570 static void test(DateTime dt, immutable TimeZone tz1, immutable TimeZone tz2)
571 {
572 auto st1 = SysTime(dt);
573 st1.timezone = tz1;
574
575 auto st2 = SysTime(dt);
576 st2.timezone = tz2;
577
578 assert(st1 == st2);
579 }
580
581 foreach (tz1; testTZs)
582 {
583 foreach (tz2; testTZs)
584 {
585 foreach (dt; chain(testDateTimesBC, testDateTimesAD))
586 test(dt, tz1, tz2);
587 }
588 }
589
590 auto st = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
591 const cst = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
592 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
593 assert(st == st);
594 assert(st == cst);
595 //assert(st == ist);
596 assert(cst == st);
597 assert(cst == cst);
598 //assert(cst == ist);
599 //assert(ist == st);
600 //assert(ist == cst);
601 //assert(ist == ist);
602 }
603
604 /++
605 Compares this $(LREF SysTime) with the given $(LREF SysTime).
606
607 Time zone is irrelevant when comparing $(LREF SysTime)s.
608
609 Returns:
610 $(BOOKTABLE,
611 $(TR $(TD this < rhs) $(TD < 0))
612 $(TR $(TD this == rhs) $(TD 0))
613 $(TR $(TD this > rhs) $(TD > 0))
614 )
615 +/
616 int opCmp(in SysTime rhs) @safe const pure nothrow
617 {
618 if (_stdTime < rhs._stdTime)
619 return -1;
620 if (_stdTime > rhs._stdTime)
621 return 1;
622 return 0;
623 }
624
625 @safe unittest
626 {
627 import std.algorithm.iteration : map;
628 import std.array : array;
629 import std.range : chain;
630
631 assert(SysTime(DateTime.init, UTC()).opCmp(SysTime(0, UTC())) == 0);
632 assert(SysTime(DateTime.init, UTC()).opCmp(SysTime(0)) == 0);
633 assert(SysTime(Date.init, UTC()).opCmp(SysTime(0)) == 0);
634 assert(SysTime(0).opCmp(SysTime(0)) == 0);
635
636 static void testEqual(SysTime st, immutable TimeZone tz1, immutable TimeZone tz2)
637 {
638 auto st1 = st;
639 st1.timezone = tz1;
640
641 auto st2 = st;
642 st2.timezone = tz2;
643
644 assert(st1.opCmp(st2) == 0);
645 }
646
647 auto sts = array(map!SysTime(chain(testDateTimesBC, testDateTimesAD)));
648
649 foreach (st; sts)
650 {
651 foreach (tz1; testTZs)
652 {
653 foreach (tz2; testTZs)
654 testEqual(st, tz1, tz2);
655 }
656 }
657
658 static void testCmp(SysTime st1, immutable TimeZone tz1, SysTime st2, immutable TimeZone tz2)
659 {
660 st1.timezone = tz1;
661 st2.timezone = tz2;
662 assert(st1.opCmp(st2) < 0);
663 assert(st2.opCmp(st1) > 0);
664 }
665
666 foreach (si, st1; sts)
667 {
668 foreach (st2; sts[si + 1 .. $])
669 {
670 foreach (tz1; testTZs)
671 {
672 foreach (tz2; testTZs)
673 testCmp(st1, tz1, st2, tz2);
674 }
675 }
676 }
677
678 auto st = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
679 const cst = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
680 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
681 assert(st.opCmp(st) == 0);
682 assert(st.opCmp(cst) == 0);
683 //assert(st.opCmp(ist) == 0);
684 assert(cst.opCmp(st) == 0);
685 assert(cst.opCmp(cst) == 0);
686 //assert(cst.opCmp(ist) == 0);
687 //assert(ist.opCmp(st) == 0);
688 //assert(ist.opCmp(cst) == 0);
689 //assert(ist.opCmp(ist) == 0);
690 }
691
692 /**
693 * Returns: A hash of the $(LREF SysTime)
694 */
695 size_t toHash() const @nogc pure nothrow @safe
696 {
697 static if (is(size_t == ulong))
698 return _stdTime;
699 else
700 {
701 // MurmurHash2
702 enum ulong m = 0xc6a4a7935bd1e995UL;
703 enum ulong n = m * 16;
704 enum uint r = 47;
705
706 ulong k = _stdTime;
707 k *= m;
708 k ^= k >> r;
709 k *= m;
710
711 ulong h = n;
712 h ^= k;
713 h *= m;
714
715 return cast(size_t) h;
716 }
717 }
718
719 @safe unittest
720 {
721 assert(SysTime(0).toHash == SysTime(0).toHash);
722 assert(SysTime(DateTime(2000, 1, 1)).toHash == SysTime(DateTime(2000, 1, 1)).toHash);
723 assert(SysTime(DateTime(2000, 1, 1)).toHash != SysTime(DateTime(2000, 1, 2)).toHash);
724
725 // test that timezones aren't taken into account
726 assert(SysTime(0, LocalTime()).toHash == SysTime(0, LocalTime()).toHash);
727 assert(SysTime(0, LocalTime()).toHash == SysTime(0, UTC()).toHash);
728 assert(SysTime(DateTime(2000, 1, 1), LocalTime()).toHash == SysTime(DateTime(2000, 1, 1), LocalTime()).toHash);
729 immutable zone = new SimpleTimeZone(dur!"minutes"(60));
730 assert(SysTime(DateTime(2000, 1, 1, 1), zone).toHash == SysTime(DateTime(2000, 1, 1), UTC()).toHash);
731 assert(SysTime(DateTime(2000, 1, 1), zone).toHash != SysTime(DateTime(2000, 1, 1), UTC()).toHash);
732 }
733
734 /++
735 Year of the Gregorian Calendar. Positive numbers are A.D. Non-positive
736 are B.C.
737 +/
738 @property short year() @safe const nothrow
739 {
740 return (cast(Date) this).year;
741 }
742
743 @safe unittest
744 {
745 import std.range : chain;
746 static void test(SysTime sysTime, long expected)
747 {
748 assert(sysTime.year == expected, format("Value given: %s", sysTime));
749 }
750
751 test(SysTime(0, UTC()), 1);
752 test(SysTime(1, UTC()), 1);
753 test(SysTime(-1, UTC()), 0);
754
755 foreach (year; chain(testYearsBC, testYearsAD))
756 {
757 foreach (md; testMonthDays)
758 {
759 foreach (tod; testTODs)
760 {
761 auto dt = DateTime(Date(year, md.month, md.day), tod);
762 foreach (tz; testTZs)
763 {
764 foreach (fs; testFracSecs)
765 test(SysTime(dt, fs, tz), year);
766 }
767 }
768 }
769 }
770
771 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
772 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
773 assert(cst.year == 1999);
774 //assert(ist.year == 1999);
775 }
776
777 /++
778 Year of the Gregorian Calendar. Positive numbers are A.D. Non-positive
779 are B.C.
780
781 Params:
782 year = The year to set this $(LREF SysTime)'s year to.
783
784 Throws:
785 $(REF DateTimeException,std,datetime,date) if the new year is not
786 a leap year and the resulting date would be on February 29th.
787 +/
788 @property void year(int year) @safe
789 {
790 auto hnsecs = adjTime;
791 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
792
793 if (hnsecs < 0)
794 {
795 hnsecs += convert!("hours", "hnsecs")(24);
796 --days;
797 }
798
799 auto date = Date(cast(int) days);
800 date.year = year;
801
802 immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
803 adjTime = newDaysHNSecs + hnsecs;
804 }
805
806 ///
807 @safe unittest
808 {
809 import std.datetime.date : DateTime;
810
811 assert(SysTime(DateTime(1999, 7, 6, 9, 7, 5)).year == 1999);
812 assert(SysTime(DateTime(2010, 10, 4, 0, 0, 30)).year == 2010);
813 assert(SysTime(DateTime(-7, 4, 5, 7, 45, 2)).year == -7);
814 }
815
816 @safe unittest
817 {
818 import std.range : chain;
819
820 static void test(SysTime st, int year, in SysTime expected)
821 {
822 st.year = year;
823 assert(st == expected);
824 }
825
826 foreach (st; chain(testSysTimesBC, testSysTimesAD))
827 {
828 auto dt = cast(DateTime) st;
829
830 foreach (year; chain(testYearsBC, testYearsAD))
831 {
832 auto e = SysTime(DateTime(year, dt.month, dt.day, dt.hour, dt.minute, dt.second),
833 st.fracSecs,
834 st.timezone);
835 test(st, year, e);
836 }
837 }
838
839 foreach (fs; testFracSecs)
840 {
841 foreach (tz; testTZs)
842 {
843 foreach (tod; testTODs)
844 {
845 test(SysTime(DateTime(Date(1999, 2, 28), tod), fs, tz), 2000,
846 SysTime(DateTime(Date(2000, 2, 28), tod), fs, tz));
847 test(SysTime(DateTime(Date(2000, 2, 28), tod), fs, tz), 1999,
848 SysTime(DateTime(Date(1999, 2, 28), tod), fs, tz));
849 }
850
851 foreach (tod; testTODsThrown)
852 {
853 auto st = SysTime(DateTime(Date(2000, 2, 29), tod), fs, tz);
854 assertThrown!DateTimeException(st.year = 1999);
855 }
856 }
857 }
858
859 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
860 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
861 static assert(!__traits(compiles, cst.year = 7));
862 //static assert(!__traits(compiles, ist.year = 7));
863 }
864
865 /++
866 Year B.C. of the Gregorian Calendar counting year 0 as 1 B.C.
867
868 Throws:
869 $(REF DateTimeException,std,datetime,date) if $(D isAD) is true.
870 +/
871 @property ushort yearBC() @safe const
872 {
873 return (cast(Date) this).yearBC;
874 }
875
876 ///
877 @safe unittest
878 {
879 import std.datetime.date : DateTime;
880
881 assert(SysTime(DateTime(0, 1, 1, 12, 30, 33)).yearBC == 1);
882 assert(SysTime(DateTime(-1, 1, 1, 10, 7, 2)).yearBC == 2);
883 assert(SysTime(DateTime(-100, 1, 1, 4, 59, 0)).yearBC == 101);
884 }
885
886 @safe unittest
887 {
888 import std.exception : assertNotThrown;
889 foreach (st; testSysTimesBC)
890 {
891 auto msg = format("SysTime: %s", st);
892 assertNotThrown!DateTimeException(st.yearBC, msg);
893 assert(st.yearBC == (st.year * -1) + 1, msg);
894 }
895
896 foreach (st; [testSysTimesAD[0], testSysTimesAD[$/2], testSysTimesAD[$-1]])
897 assertThrown!DateTimeException(st.yearBC, format("SysTime: %s", st));
898
899 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
900 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
901 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
902 st.year = 12;
903 assert(st.year == 12);
904 static assert(!__traits(compiles, cst.year = 12));
905 //static assert(!__traits(compiles, ist.year = 12));
906 }
907
908
909 /++
910 Year B.C. of the Gregorian Calendar counting year 0 as 1 B.C.
911
912 Params:
913 year = The year B.C. to set this $(LREF SysTime)'s year to.
914
915 Throws:
916 $(REF DateTimeException,std,datetime,date) if a non-positive value
917 is given.
918 +/
919 @property void yearBC(int year) @safe
920 {
921 auto hnsecs = adjTime;
922 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
923
924 if (hnsecs < 0)
925 {
926 hnsecs += convert!("hours", "hnsecs")(24);
927 --days;
928 }
929
930 auto date = Date(cast(int) days);
931 date.yearBC = year;
932
933 immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
934 adjTime = newDaysHNSecs + hnsecs;
935 }
936
937 @safe unittest
938 {
939 auto st = SysTime(DateTime(2010, 1, 1, 7, 30, 0));
940 st.yearBC = 1;
941 assert(st == SysTime(DateTime(0, 1, 1, 7, 30, 0)));
942
943 st.yearBC = 10;
944 assert(st == SysTime(DateTime(-9, 1, 1, 7, 30, 0)));
945 }
946
947 @safe unittest
948 {
949 import std.range : chain;
950 static void test(SysTime st, int year, in SysTime expected)
951 {
952 st.yearBC = year;
953 assert(st == expected, format("SysTime: %s", st));
954 }
955
956 foreach (st; chain(testSysTimesBC, testSysTimesAD))
957 {
958 auto dt = cast(DateTime) st;
959
960 foreach (year; testYearsBC)
961 {
962 auto e = SysTime(DateTime(year, dt.month, dt.day, dt.hour, dt.minute, dt.second),
963 st.fracSecs,
964 st.timezone);
965 test(st, (year * -1) + 1, e);
966 }
967 }
968
969 foreach (st; [testSysTimesBC[0], testSysTimesBC[$ - 1], testSysTimesAD[0], testSysTimesAD[$ - 1]])
970 {
971 foreach (year; testYearsBC)
972 assertThrown!DateTimeException(st.yearBC = year);
973 }
974
975 foreach (fs; testFracSecs)
976 {
977 foreach (tz; testTZs)
978 {
979 foreach (tod; testTODs)
980 {
981 test(SysTime(DateTime(Date(-1999, 2, 28), tod), fs, tz), 2001,
982 SysTime(DateTime(Date(-2000, 2, 28), tod), fs, tz));
983 test(SysTime(DateTime(Date(-2000, 2, 28), tod), fs, tz), 2000,
984 SysTime(DateTime(Date(-1999, 2, 28), tod), fs, tz));
985 }
986
987 foreach (tod; testTODsThrown)
988 {
989 auto st = SysTime(DateTime(Date(-2000, 2, 29), tod), fs, tz);
990 assertThrown!DateTimeException(st.year = -1999);
991 }
992 }
993 }
994
995 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
996 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
997 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
998 st.yearBC = 12;
999 assert(st.yearBC == 12);
1000 static assert(!__traits(compiles, cst.yearBC = 12));
1001 //static assert(!__traits(compiles, ist.yearBC = 12));
1002 }
1003
1004 /++
1005 Month of a Gregorian Year.
1006 +/
1007 @property Month month() @safe const nothrow
1008 {
1009 return (cast(Date) this).month;
1010 }
1011
1012 ///
1013 @safe unittest
1014 {
1015 import std.datetime.date : DateTime;
1016
1017 assert(SysTime(DateTime(1999, 7, 6, 9, 7, 5)).month == 7);
1018 assert(SysTime(DateTime(2010, 10, 4, 0, 0, 30)).month == 10);
1019 assert(SysTime(DateTime(-7, 4, 5, 7, 45, 2)).month == 4);
1020 }
1021
1022 @safe unittest
1023 {
1024 import std.range : chain;
1025
1026 static void test(SysTime sysTime, Month expected)
1027 {
1028 assert(sysTime.month == expected, format("Value given: %s", sysTime));
1029 }
1030
1031 test(SysTime(0, UTC()), Month.jan);
1032 test(SysTime(1, UTC()), Month.jan);
1033 test(SysTime(-1, UTC()), Month.dec);
1034
1035 foreach (year; chain(testYearsBC, testYearsAD))
1036 {
1037 foreach (md; testMonthDays)
1038 {
1039 foreach (tod; testTODs)
1040 {
1041 auto dt = DateTime(Date(year, md.month, md.day), tod);
1042 foreach (fs; testFracSecs)
1043 {
1044 foreach (tz; testTZs)
1045 test(SysTime(dt, fs, tz), md.month);
1046 }
1047 }
1048 }
1049 }
1050
1051 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1052 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1053 assert(cst.month == 7);
1054 //assert(ist.month == 7);
1055 }
1056
1057
1058 /++
1059 Month of a Gregorian Year.
1060
1061 Params:
1062 month = The month to set this $(LREF SysTime)'s month to.
1063
1064 Throws:
1065 $(REF DateTimeException,std,datetime,date) if the given month is
1066 not a valid month.
1067 +/
1068 @property void month(Month month) @safe
1069 {
1070 auto hnsecs = adjTime;
1071 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
1072
1073 if (hnsecs < 0)
1074 {
1075 hnsecs += convert!("hours", "hnsecs")(24);
1076 --days;
1077 }
1078
1079 auto date = Date(cast(int) days);
1080 date.month = month;
1081
1082 immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
1083 adjTime = newDaysHNSecs + hnsecs;
1084 }
1085
1086 @safe unittest
1087 {
1088 import std.algorithm.iteration : filter;
1089 import std.range : chain;
1090
1091 static void test(SysTime st, Month month, in SysTime expected)
1092 {
1093 st.month = cast(Month) month;
1094 assert(st == expected);
1095 }
1096
1097 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1098 {
1099 auto dt = cast(DateTime) st;
1100
1101 foreach (md; testMonthDays)
1102 {
1103 if (st.day > maxDay(dt.year, md.month))
1104 continue;
1105 auto e = SysTime(DateTime(dt.year, md.month, dt.day, dt.hour, dt.minute, dt.second),
1106 st.fracSecs,
1107 st.timezone);
1108 test(st, md.month, e);
1109 }
1110 }
1111
1112 foreach (fs; testFracSecs)
1113 {
1114 foreach (tz; testTZs)
1115 {
1116 foreach (tod; testTODs)
1117 {
1118 foreach (year; filter!((a){return yearIsLeapYear(a);}) (chain(testYearsBC, testYearsAD)))
1119 {
1120 test(SysTime(DateTime(Date(year, 1, 29), tod), fs, tz),
1121 Month.feb,
1122 SysTime(DateTime(Date(year, 2, 29), tod), fs, tz));
1123 }
1124
1125 foreach (year; chain(testYearsBC, testYearsAD))
1126 {
1127 test(SysTime(DateTime(Date(year, 1, 28), tod), fs, tz),
1128 Month.feb,
1129 SysTime(DateTime(Date(year, 2, 28), tod), fs, tz));
1130 test(SysTime(DateTime(Date(year, 7, 30), tod), fs, tz),
1131 Month.jun,
1132 SysTime(DateTime(Date(year, 6, 30), tod), fs, tz));
1133 }
1134 }
1135 }
1136 }
1137
1138 foreach (fs; [testFracSecs[0], testFracSecs[$-1]])
1139 {
1140 foreach (tz; testTZs)
1141 {
1142 foreach (tod; testTODsThrown)
1143 {
1144 foreach (year; [testYearsBC[$-3], testYearsBC[$-2],
1145 testYearsBC[$-2], testYearsAD[0],
1146 testYearsAD[$-2], testYearsAD[$-1]])
1147 {
1148 auto day = yearIsLeapYear(year) ? 30 : 29;
1149 auto st1 = SysTime(DateTime(Date(year, 1, day), tod), fs, tz);
1150 assertThrown!DateTimeException(st1.month = Month.feb);
1151
1152 auto st2 = SysTime(DateTime(Date(year, 7, 31), tod), fs, tz);
1153 assertThrown!DateTimeException(st2.month = Month.jun);
1154 }
1155 }
1156 }
1157 }
1158
1159 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1160 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1161 static assert(!__traits(compiles, cst.month = 12));
1162 //static assert(!__traits(compiles, ist.month = 12));
1163 }
1164
1165 /++
1166 Day of a Gregorian Month.
1167 +/
1168 @property ubyte day() @safe const nothrow
1169 {
1170 return (cast(Date) this).day;
1171 }
1172
1173 ///
1174 @safe unittest
1175 {
1176 import std.datetime.date : DateTime;
1177
1178 assert(SysTime(DateTime(1999, 7, 6, 9, 7, 5)).day == 6);
1179 assert(SysTime(DateTime(2010, 10, 4, 0, 0, 30)).day == 4);
1180 assert(SysTime(DateTime(-7, 4, 5, 7, 45, 2)).day == 5);
1181 }
1182
1183 @safe unittest
1184 {
1185 import std.range : chain;
1186
1187 static void test(SysTime sysTime, int expected)
1188 {
1189 assert(sysTime.day == expected, format("Value given: %s", sysTime));
1190 }
1191
1192 test(SysTime(0, UTC()), 1);
1193 test(SysTime(1, UTC()), 1);
1194 test(SysTime(-1, UTC()), 31);
1195
1196 foreach (year; chain(testYearsBC, testYearsAD))
1197 {
1198 foreach (md; testMonthDays)
1199 {
1200 foreach (tod; testTODs)
1201 {
1202 auto dt = DateTime(Date(year, md.month, md.day), tod);
1203
1204 foreach (tz; testTZs)
1205 {
1206 foreach (fs; testFracSecs)
1207 test(SysTime(dt, fs, tz), md.day);
1208 }
1209 }
1210 }
1211 }
1212
1213 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1214 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1215 assert(cst.day == 6);
1216 //assert(ist.day == 6);
1217 }
1218
1219
1220 /++
1221 Day of a Gregorian Month.
1222
1223 Params:
1224 day = The day of the month to set this $(LREF SysTime)'s day to.
1225
1226 Throws:
1227 $(REF DateTimeException,std,datetime,date) if the given day is not
1228 a valid day of the current month.
1229 +/
1230 @property void day(int day) @safe
1231 {
1232 auto hnsecs = adjTime;
1233 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
1234
1235 if (hnsecs < 0)
1236 {
1237 hnsecs += convert!("hours", "hnsecs")(24);
1238 --days;
1239 }
1240
1241 auto date = Date(cast(int) days);
1242 date.day = day;
1243
1244 immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
1245 adjTime = newDaysHNSecs + hnsecs;
1246 }
1247
1248 @safe unittest
1249 {
1250 import std.range : chain;
1251 import std.traits : EnumMembers;
1252
1253 foreach (day; chain(testDays))
1254 {
1255 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1256 {
1257 auto dt = cast(DateTime) st;
1258
1259 if (day > maxDay(dt.year, dt.month))
1260 continue;
1261 auto expected = SysTime(DateTime(dt.year, dt.month, day, dt.hour, dt.minute, dt.second),
1262 st.fracSecs,
1263 st.timezone);
1264 st.day = day;
1265 assert(st == expected, format("[%s] [%s]", st, expected));
1266 }
1267 }
1268
1269 foreach (tz; testTZs)
1270 {
1271 foreach (tod; testTODs)
1272 {
1273 foreach (fs; testFracSecs)
1274 {
1275 foreach (year; chain(testYearsBC, testYearsAD))
1276 {
1277 foreach (month; EnumMembers!Month)
1278 {
1279 auto st = SysTime(DateTime(Date(year, month, 1), tod), fs, tz);
1280 immutable max = maxDay(year, month);
1281 auto expected = SysTime(DateTime(Date(year, month, max), tod), fs, tz);
1282
1283 st.day = max;
1284 assert(st == expected, format("[%s] [%s]", st, expected));
1285 }
1286 }
1287 }
1288 }
1289 }
1290
1291 foreach (tz; testTZs)
1292 {
1293 foreach (tod; testTODsThrown)
1294 {
1295 foreach (fs; [testFracSecs[0], testFracSecs[$-1]])
1296 {
1297 foreach (year; [testYearsBC[$-3], testYearsBC[$-2],
1298 testYearsBC[$-2], testYearsAD[0],
1299 testYearsAD[$-2], testYearsAD[$-1]])
1300 {
1301 foreach (month; EnumMembers!Month)
1302 {
1303 auto st = SysTime(DateTime(Date(year, month, 1), tod), fs, tz);
1304 immutable max = maxDay(year, month);
1305
1306 assertThrown!DateTimeException(st.day = max + 1);
1307 }
1308 }
1309 }
1310 }
1311 }
1312
1313 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1314 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1315 static assert(!__traits(compiles, cst.day = 27));
1316 //static assert(!__traits(compiles, ist.day = 27));
1317 }
1318
1319
1320 /++
1321 Hours past midnight.
1322 +/
1323 @property ubyte hour() @safe const nothrow
1324 {
1325 auto hnsecs = adjTime;
1326 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
1327
1328 if (hnsecs < 0)
1329 {
1330 hnsecs += convert!("hours", "hnsecs")(24);
1331 --days;
1332 }
1333
1334 return cast(ubyte) getUnitsFromHNSecs!"hours"(hnsecs);
1335 }
1336
1337 @safe unittest
1338 {
1339 import std.range : chain;
1340
1341 static void test(SysTime sysTime, int expected)
1342 {
1343 assert(sysTime.hour == expected, format("Value given: %s", sysTime));
1344 }
1345
1346 test(SysTime(0, UTC()), 0);
1347 test(SysTime(1, UTC()), 0);
1348 test(SysTime(-1, UTC()), 23);
1349
1350 foreach (tz; testTZs)
1351 {
1352 foreach (year; chain(testYearsBC, testYearsAD))
1353 {
1354 foreach (md; testMonthDays)
1355 {
1356 foreach (hour; testHours)
1357 {
1358 foreach (minute; testMinSecs)
1359 {
1360 foreach (second; testMinSecs)
1361 {
1362 auto dt = DateTime(Date(year, md.month, md.day), TimeOfDay(hour, minute, second));
1363 foreach (fs; testFracSecs)
1364 test(SysTime(dt, fs, tz), hour);
1365 }
1366 }
1367 }
1368 }
1369 }
1370 }
1371
1372 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1373 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1374 assert(cst.hour == 12);
1375 //assert(ist.hour == 12);
1376 }
1377
1378
1379 /++
1380 Hours past midnight.
1381
1382 Params:
1383 hour = The hours to set this $(LREF SysTime)'s hour to.
1384
1385 Throws:
1386 $(REF DateTimeException,std,datetime,date) if the given hour are
1387 not a valid hour of the day.
1388 +/
1389 @property void hour(int hour) @safe
1390 {
1391 enforceValid!"hours"(hour);
1392
1393 auto hnsecs = adjTime;
1394 auto days = splitUnitsFromHNSecs!"days"(hnsecs);
1395 immutable daysHNSecs = convert!("days", "hnsecs")(days);
1396 immutable negative = hnsecs < 0;
1397
1398 if (negative)
1399 hnsecs += convert!("hours", "hnsecs")(24);
1400
1401 hnsecs = removeUnitsFromHNSecs!"hours"(hnsecs);
1402 hnsecs += convert!("hours", "hnsecs")(hour);
1403
1404 if (negative)
1405 hnsecs -= convert!("hours", "hnsecs")(24);
1406
1407 adjTime = daysHNSecs + hnsecs;
1408 }
1409
1410 @safe unittest
1411 {
1412 import std.range : chain;
1413
1414 foreach (hour; chain(testHours))
1415 {
1416 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1417 {
1418 auto dt = cast(DateTime) st;
1419 auto expected = SysTime(DateTime(dt.year, dt.month, dt.day, hour, dt.minute, dt.second),
1420 st.fracSecs,
1421 st.timezone);
1422 st.hour = hour;
1423 assert(st == expected, format("[%s] [%s]", st, expected));
1424 }
1425 }
1426
1427 auto st = testSysTimesAD[0];
1428 assertThrown!DateTimeException(st.hour = -1);
1429 assertThrown!DateTimeException(st.hour = 60);
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.hour = 27));
1434 //static assert(!__traits(compiles, ist.hour = 27));
1435 }
1436
1437
1438 /++
1439 Minutes past the current hour.
1440 +/
1441 @property ubyte minute() @safe const nothrow
1442 {
1443 auto hnsecs = adjTime;
1444 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
1445
1446 if (hnsecs < 0)
1447 {
1448 hnsecs += convert!("hours", "hnsecs")(24);
1449 --days;
1450 }
1451
1452 hnsecs = removeUnitsFromHNSecs!"hours"(hnsecs);
1453
1454 return cast(ubyte) getUnitsFromHNSecs!"minutes"(hnsecs);
1455 }
1456
1457 @safe unittest
1458 {
1459 import std.range : chain;
1460
1461 static void test(SysTime sysTime, int expected)
1462 {
1463 assert(sysTime.minute == expected, format("Value given: %s", sysTime));
1464 }
1465
1466 test(SysTime(0, UTC()), 0);
1467 test(SysTime(1, UTC()), 0);
1468 test(SysTime(-1, UTC()), 59);
1469
1470 foreach (tz; testTZs)
1471 {
1472 foreach (year; chain(testYearsBC, testYearsAD))
1473 {
1474 foreach (md; testMonthDays)
1475 {
1476 foreach (hour; testHours)
1477 {
1478 foreach (minute; testMinSecs)
1479 {
1480 foreach (second; testMinSecs)
1481 {
1482 auto dt = DateTime(Date(year, md.month, md.day), TimeOfDay(hour, minute, second));
1483 foreach (fs; testFracSecs)
1484 test(SysTime(dt, fs, tz), minute);
1485 }
1486 }
1487 }
1488 }
1489 }
1490 }
1491
1492 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1493 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1494 assert(cst.minute == 30);
1495 //assert(ist.minute == 30);
1496 }
1497
1498
1499 /++
1500 Minutes past the current hour.
1501
1502 Params:
1503 minute = The minute to set this $(LREF SysTime)'s minute to.
1504
1505 Throws:
1506 $(REF DateTimeException,std,datetime,date) if the given minute are
1507 not a valid minute of an hour.
1508 +/
1509 @property void minute(int minute) @safe
1510 {
1511 enforceValid!"minutes"(minute);
1512
1513 auto hnsecs = adjTime;
1514 auto days = splitUnitsFromHNSecs!"days"(hnsecs);
1515 immutable daysHNSecs = convert!("days", "hnsecs")(days);
1516 immutable negative = hnsecs < 0;
1517
1518 if (negative)
1519 hnsecs += convert!("hours", "hnsecs")(24);
1520
1521 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
1522 hnsecs = removeUnitsFromHNSecs!"minutes"(hnsecs);
1523
1524 hnsecs += convert!("hours", "hnsecs")(hour);
1525 hnsecs += convert!("minutes", "hnsecs")(minute);
1526
1527 if (negative)
1528 hnsecs -= convert!("hours", "hnsecs")(24);
1529
1530 adjTime = daysHNSecs + hnsecs;
1531 }
1532
1533 @safe unittest
1534 {
1535 import std.range : chain;
1536
1537 foreach (minute; testMinSecs)
1538 {
1539 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1540 {
1541 auto dt = cast(DateTime) st;
1542 auto expected = SysTime(DateTime(dt.year, dt.month, dt.day, dt.hour, minute, dt.second),
1543 st.fracSecs,
1544 st.timezone);
1545 st.minute = minute;
1546 assert(st == expected, format("[%s] [%s]", st, expected));
1547 }
1548 }
1549
1550 auto st = testSysTimesAD[0];
1551 assertThrown!DateTimeException(st.minute = -1);
1552 assertThrown!DateTimeException(st.minute = 60);
1553
1554 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1555 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1556 static assert(!__traits(compiles, cst.minute = 27));
1557 //static assert(!__traits(compiles, ist.minute = 27));
1558 }
1559
1560
1561 /++
1562 Seconds past the current minute.
1563 +/
1564 @property ubyte second() @safe const nothrow
1565 {
1566 auto hnsecs = adjTime;
1567 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
1568
1569 if (hnsecs < 0)
1570 {
1571 hnsecs += convert!("hours", "hnsecs")(24);
1572 --days;
1573 }
1574
1575 hnsecs = removeUnitsFromHNSecs!"hours"(hnsecs);
1576 hnsecs = removeUnitsFromHNSecs!"minutes"(hnsecs);
1577
1578 return cast(ubyte) getUnitsFromHNSecs!"seconds"(hnsecs);
1579 }
1580
1581 @safe unittest
1582 {
1583 import std.range : chain;
1584
1585 static void test(SysTime sysTime, int expected)
1586 {
1587 assert(sysTime.second == expected, format("Value given: %s", sysTime));
1588 }
1589
1590 test(SysTime(0, UTC()), 0);
1591 test(SysTime(1, UTC()), 0);
1592 test(SysTime(-1, UTC()), 59);
1593
1594 foreach (tz; testTZs)
1595 {
1596 foreach (year; chain(testYearsBC, testYearsAD))
1597 {
1598 foreach (md; testMonthDays)
1599 {
1600 foreach (hour; testHours)
1601 {
1602 foreach (minute; testMinSecs)
1603 {
1604 foreach (second; testMinSecs)
1605 {
1606 auto dt = DateTime(Date(year, md.month, md.day), TimeOfDay(hour, minute, second));
1607 foreach (fs; testFracSecs)
1608 test(SysTime(dt, fs, tz), second);
1609 }
1610 }
1611 }
1612 }
1613 }
1614 }
1615
1616 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1617 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1618 assert(cst.second == 33);
1619 //assert(ist.second == 33);
1620 }
1621
1622
1623 /++
1624 Seconds past the current minute.
1625
1626 Params:
1627 second = The second to set this $(LREF SysTime)'s second to.
1628
1629 Throws:
1630 $(REF DateTimeException,std,datetime,date) if the given second are
1631 not a valid second of a minute.
1632 +/
1633 @property void second(int second) @safe
1634 {
1635 enforceValid!"seconds"(second);
1636
1637 auto hnsecs = adjTime;
1638 auto days = splitUnitsFromHNSecs!"days"(hnsecs);
1639 immutable daysHNSecs = convert!("days", "hnsecs")(days);
1640 immutable negative = hnsecs < 0;
1641
1642 if (negative)
1643 hnsecs += convert!("hours", "hnsecs")(24);
1644
1645 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
1646 immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
1647 hnsecs = removeUnitsFromHNSecs!"seconds"(hnsecs);
1648
1649 hnsecs += convert!("hours", "hnsecs")(hour);
1650 hnsecs += convert!("minutes", "hnsecs")(minute);
1651 hnsecs += convert!("seconds", "hnsecs")(second);
1652
1653 if (negative)
1654 hnsecs -= convert!("hours", "hnsecs")(24);
1655
1656 adjTime = daysHNSecs + hnsecs;
1657 }
1658
1659 @safe unittest
1660 {
1661 import std.range : chain;
1662
1663 foreach (second; testMinSecs)
1664 {
1665 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1666 {
1667 auto dt = cast(DateTime) st;
1668 auto expected = SysTime(DateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute, second),
1669 st.fracSecs,
1670 st.timezone);
1671 st.second = second;
1672 assert(st == expected, format("[%s] [%s]", st, expected));
1673 }
1674 }
1675
1676 auto st = testSysTimesAD[0];
1677 assertThrown!DateTimeException(st.second = -1);
1678 assertThrown!DateTimeException(st.second = 60);
1679
1680 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1681 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1682 static assert(!__traits(compiles, cst.seconds = 27));
1683 //static assert(!__traits(compiles, ist.seconds = 27));
1684 }
1685
1686
1687 /++
1688 Fractional seconds past the second (i.e. the portion of a
1689 $(LREF SysTime) which is less than a second).
1690 +/
1691 @property Duration fracSecs() @safe const nothrow
1692 {
1693 auto hnsecs = removeUnitsFromHNSecs!"days"(adjTime);
1694
1695 if (hnsecs < 0)
1696 hnsecs += convert!("hours", "hnsecs")(24);
1697
1698 return dur!"hnsecs"(removeUnitsFromHNSecs!"seconds"(hnsecs));
1699 }
1700
1701 ///
1702 @safe unittest
1703 {
1704 import core.time : msecs, usecs, hnsecs, nsecs;
1705 import std.datetime.date : DateTime;
1706
1707 auto dt = DateTime(1982, 4, 1, 20, 59, 22);
1708 assert(SysTime(dt, msecs(213)).fracSecs == msecs(213));
1709 assert(SysTime(dt, usecs(5202)).fracSecs == usecs(5202));
1710 assert(SysTime(dt, hnsecs(1234567)).fracSecs == hnsecs(1234567));
1711
1712 // SysTime and Duration both have a precision of hnsecs (100 ns),
1713 // so nsecs are going to be truncated.
1714 assert(SysTime(dt, nsecs(123456789)).fracSecs == nsecs(123456700));
1715 }
1716
1717 @safe unittest
1718 {
1719 import std.range : chain;
1720
1721 assert(SysTime(0, UTC()).fracSecs == Duration.zero);
1722 assert(SysTime(1, UTC()).fracSecs == hnsecs(1));
1723 assert(SysTime(-1, UTC()).fracSecs == hnsecs(9_999_999));
1724
1725 foreach (tz; testTZs)
1726 {
1727 foreach (year; chain(testYearsBC, testYearsAD))
1728 {
1729 foreach (md; testMonthDays)
1730 {
1731 foreach (hour; testHours)
1732 {
1733 foreach (minute; testMinSecs)
1734 {
1735 foreach (second; testMinSecs)
1736 {
1737 auto dt = DateTime(Date(year, md.month, md.day), TimeOfDay(hour, minute, second));
1738 foreach (fs; testFracSecs)
1739 assert(SysTime(dt, fs, tz).fracSecs == fs);
1740 }
1741 }
1742 }
1743 }
1744 }
1745 }
1746
1747 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1748 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1749 assert(cst.fracSecs == Duration.zero);
1750 //assert(ist.fracSecs == Duration.zero);
1751 }
1752
1753
1754 /++
1755 Fractional seconds past the second (i.e. the portion of a
1756 $(LREF SysTime) which is less than a second).
1757
1758 Params:
1759 fracSecs = The duration to set this $(LREF SysTime)'s fractional
1760 seconds to.
1761
1762 Throws:
1763 $(REF DateTimeException,std,datetime,date) if the given duration
1764 is negative or if it's greater than or equal to one second.
1765 +/
1766 @property void fracSecs(Duration fracSecs) @safe
1767 {
1768 enforce(fracSecs >= Duration.zero, new DateTimeException("A SysTime cannot have negative fractional seconds."));
1769 enforce(fracSecs < seconds(1), new DateTimeException("Fractional seconds must be less than one second."));
1770
1771 auto oldHNSecs = adjTime;
1772 auto days = splitUnitsFromHNSecs!"days"(oldHNSecs);
1773 immutable daysHNSecs = convert!("days", "hnsecs")(days);
1774 immutable negative = oldHNSecs < 0;
1775
1776 if (negative)
1777 oldHNSecs += convert!("hours", "hnsecs")(24);
1778
1779 immutable seconds = splitUnitsFromHNSecs!"seconds"(oldHNSecs);
1780 immutable secondsHNSecs = convert!("seconds", "hnsecs")(seconds);
1781 auto newHNSecs = fracSecs.total!"hnsecs" + secondsHNSecs;
1782
1783 if (negative)
1784 newHNSecs -= convert!("hours", "hnsecs")(24);
1785
1786 adjTime = daysHNSecs + newHNSecs;
1787 }
1788
1789 ///
1790 @safe unittest
1791 {
1792 import core.time : Duration, msecs, hnsecs, nsecs;
1793 import std.datetime.date : DateTime;
1794
1795 auto st = SysTime(DateTime(1982, 4, 1, 20, 59, 22));
1796 assert(st.fracSecs == Duration.zero);
1797
1798 st.fracSecs = msecs(213);
1799 assert(st.fracSecs == msecs(213));
1800
1801 st.fracSecs = hnsecs(1234567);
1802 assert(st.fracSecs == hnsecs(1234567));
1803
1804 // SysTime has a precision of hnsecs (100 ns), so nsecs are
1805 // going to be truncated.
1806 st.fracSecs = nsecs(123456789);
1807 assert(st.fracSecs == hnsecs(1234567));
1808 }
1809
1810 @safe unittest
1811 {
1812 import std.range : chain;
1813
1814 foreach (fracSec; testFracSecs)
1815 {
1816 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1817 {
1818 auto dt = cast(DateTime) st;
1819 auto expected = SysTime(dt, fracSec, st.timezone);
1820 st.fracSecs = fracSec;
1821 assert(st == expected, format("[%s] [%s]", st, expected));
1822 }
1823 }
1824
1825 auto st = testSysTimesAD[0];
1826 assertThrown!DateTimeException(st.fracSecs = hnsecs(-1));
1827 assertThrown!DateTimeException(st.fracSecs = seconds(1));
1828
1829 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1830 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1831 static assert(!__traits(compiles, cst.fracSecs = msecs(7)));
1832 //static assert(!__traits(compiles, ist.fracSecs = msecs(7)));
1833 }
1834
1835
1836 /++
1837 The total hnsecs from midnight, January 1st, 1 A.D. UTC. This is the
1838 internal representation of $(LREF SysTime).
1839 +/
1840 @property long stdTime() @safe const pure nothrow
1841 {
1842 return _stdTime;
1843 }
1844
1845 @safe unittest
1846 {
1847 assert(SysTime(0).stdTime == 0);
1848 assert(SysTime(1).stdTime == 1);
1849 assert(SysTime(-1).stdTime == -1);
1850 assert(SysTime(DateTime(1, 1, 1, 0, 0, 33), hnsecs(502), UTC()).stdTime == 330_000_502L);
1851 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 0), UTC()).stdTime == 621_355_968_000_000_000L);
1852
1853 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1854 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1855 assert(cst.stdTime > 0);
1856 //assert(ist.stdTime > 0);
1857 }
1858
1859
1860 /++
1861 The total hnsecs from midnight, January 1st, 1 A.D. UTC. This is the
1862 internal representation of $(LREF SysTime).
1863
1864 Params:
1865 stdTime = The number of hnsecs since January 1st, 1 A.D. UTC.
1866 +/
1867 @property void stdTime(long stdTime) @safe pure nothrow
1868 {
1869 _stdTime = stdTime;
1870 }
1871
1872 @safe unittest
1873 {
1874 static void test(long stdTime, in SysTime expected, size_t line = __LINE__)
1875 {
1876 auto st = SysTime(0, UTC());
1877 st.stdTime = stdTime;
1878 assert(st == expected);
1879 }
1880
1881 test(0, SysTime(Date(1, 1, 1), UTC()));
1882 test(1, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1), UTC()));
1883 test(-1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()));
1884 test(330_000_502L, SysTime(DateTime(1, 1, 1, 0, 0, 33), hnsecs(502), UTC()));
1885 test(621_355_968_000_000_000L, SysTime(DateTime(1970, 1, 1, 0, 0, 0), UTC()));
1886
1887 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1888 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1889 static assert(!__traits(compiles, cst.stdTime = 27));
1890 //static assert(!__traits(compiles, ist.stdTime = 27));
1891 }
1892
1893
1894 /++
1895 The current time zone of this $(LREF SysTime). Its internal time is
1896 always kept in UTC, so there are no conversion issues between time zones
1897 due to DST. Functions which return all or part of the time - such as
1898 hours - adjust the time to this $(LREF SysTime)'s time zone before
1899 returning.
1900 +/
1901 @property immutable(TimeZone) timezone() @safe const pure nothrow
1902 {
1903 return _timezone;
1904 }
1905
1906
1907 /++
1908 The current time zone of this $(LREF SysTime). It's internal time is
1909 always kept in UTC, so there are no conversion issues between time zones
1910 due to DST. Functions which return all or part of the time - such as
1911 hours - adjust the time to this $(LREF SysTime)'s time zone before
1912 returning.
1913
1914 Params:
1915 timezone = The $(REF _TimeZone,std,datetime,_timezone) to set this
1916 $(LREF SysTime)'s time zone to.
1917 +/
1918 @property void timezone(immutable TimeZone timezone) @safe pure nothrow
1919 {
1920 if (timezone is null)
1921 _timezone = LocalTime();
1922 else
1923 _timezone = timezone;
1924 }
1925
1926
1927 /++
1928 Returns whether DST is in effect for this $(LREF SysTime).
1929 +/
1930 @property bool dstInEffect() @safe const nothrow
1931 {
1932 return _timezone.dstInEffect(_stdTime);
1933 // This function's unit testing is done in the time zone classes.
1934 }
1935
1936
1937 /++
1938 Returns what the offset from UTC is for this $(LREF SysTime).
1939 It includes the DST offset in effect at that time (if any).
1940 +/
1941 @property Duration utcOffset() @safe const nothrow
1942 {
1943 return _timezone.utcOffsetAt(_stdTime);
1944 }
1945
1946
1947 /++
1948 Returns a $(LREF SysTime) with the same std time as this one, but with
1949 $(REF LocalTime,std,datetime,timezone) as its time zone.
1950 +/
1951 SysTime toLocalTime() @safe const pure nothrow
1952 {
1953 return SysTime(_stdTime, LocalTime());
1954 }
1955
1956 @safe unittest
1957 {
1958 {
1959 auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), hnsecs(27));
1960 assert(sysTime == sysTime.toLocalTime());
1961 assert(sysTime._stdTime == sysTime.toLocalTime()._stdTime);
1962 assert(sysTime.toLocalTime().timezone is LocalTime());
1963 assert(sysTime.toLocalTime().timezone is sysTime.timezone);
1964 assert(sysTime.toLocalTime().timezone !is UTC());
1965 }
1966
1967 {
1968 auto stz = new immutable SimpleTimeZone(dur!"minutes"(-3 * 60));
1969 auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), hnsecs(27), stz);
1970 assert(sysTime == sysTime.toLocalTime());
1971 assert(sysTime._stdTime == sysTime.toLocalTime()._stdTime);
1972 assert(sysTime.toLocalTime().timezone is LocalTime());
1973 assert(sysTime.toLocalTime().timezone !is UTC());
1974 assert(sysTime.toLocalTime().timezone !is stz);
1975 }
1976 }
1977
1978
1979 /++
1980 Returns a $(LREF SysTime) with the same std time as this one, but with
1981 $(D UTC) as its time zone.
1982 +/
1983 SysTime toUTC() @safe const pure nothrow
1984 {
1985 return SysTime(_stdTime, UTC());
1986 }
1987
1988 @safe unittest
1989 {
1990 auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), hnsecs(27));
1991 assert(sysTime == sysTime.toUTC());
1992 assert(sysTime._stdTime == sysTime.toUTC()._stdTime);
1993 assert(sysTime.toUTC().timezone is UTC());
1994 assert(sysTime.toUTC().timezone !is LocalTime());
1995 assert(sysTime.toUTC().timezone !is sysTime.timezone);
1996 }
1997
1998
1999 /++
2000 Returns a $(LREF SysTime) with the same std time as this one, but with
2001 given time zone as its time zone.
2002 +/
2003 SysTime toOtherTZ(immutable TimeZone tz) @safe const pure nothrow
2004 {
2005 if (tz is null)
2006 return SysTime(_stdTime, LocalTime());
2007 else
2008 return SysTime(_stdTime, tz);
2009 }
2010
2011 @safe unittest
2012 {
2013 auto stz = new immutable SimpleTimeZone(dur!"minutes"(11 * 60));
2014 auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), hnsecs(27));
2015 assert(sysTime == sysTime.toOtherTZ(stz));
2016 assert(sysTime._stdTime == sysTime.toOtherTZ(stz)._stdTime);
2017 assert(sysTime.toOtherTZ(stz).timezone is stz);
2018 assert(sysTime.toOtherTZ(stz).timezone !is LocalTime());
2019 assert(sysTime.toOtherTZ(stz).timezone !is UTC());
2020 }
2021
2022
2023 /++
2024 Converts this $(LREF SysTime) to unix time (i.e. seconds from midnight,
2025 January 1st, 1970 in UTC).
2026
2027 The C standard does not specify the representation of time_t, so it is
2028 implementation defined. On POSIX systems, unix time is equivalent to
2029 time_t, but that's not necessarily true on other systems (e.g. it is
2030 not true for the Digital Mars C runtime). So, be careful when using unix
2031 time with C functions on non-POSIX systems.
2032
2033 By default, the return type is time_t (which is normally an alias for
2034 int on 32-bit systems and long on 64-bit systems), but if a different
2035 size is required than either int or long can be passed as a template
2036 argument to get the desired size.
2037
2038 If the return type is int, and the result can't fit in an int, then the
2039 closest value that can be held in 32 bits will be used (so $(D int.max)
2040 if it goes over and $(D int.min) if it goes under). However, no attempt
2041 is made to deal with integer overflow if the return type is long.
2042
2043 Params:
2044 T = The return type (int or long). It defaults to time_t, which is
2045 normally 32 bits on a 32-bit system and 64 bits on a 64-bit
2046 system.
2047
2048 Returns:
2049 A signed integer representing the unix time which is equivalent to
2050 this SysTime.
2051 +/
2052 T toUnixTime(T = time_t)() @safe const pure nothrow
2053 if (is(T == int) || is(T == long))
2054 {
2055 return stdTimeToUnixTime!T(_stdTime);
2056 }
2057
2058 ///
2059 @safe unittest
2060 {
2061 import core.time : hours;
2062 import std.datetime.date : DateTime;
2063 import std.datetime.timezone : SimpleTimeZone, UTC;
2064
2065 assert(SysTime(DateTime(1970, 1, 1), UTC()).toUnixTime() == 0);
2066
2067 auto pst = new immutable SimpleTimeZone(hours(-8));
2068 assert(SysTime(DateTime(1970, 1, 1), pst).toUnixTime() == 28800);
2069
2070 auto utc = SysTime(DateTime(2007, 12, 22, 8, 14, 45), UTC());
2071 assert(utc.toUnixTime() == 1_198_311_285);
2072
2073 auto ca = SysTime(DateTime(2007, 12, 22, 8, 14, 45), pst);
2074 assert(ca.toUnixTime() == 1_198_340_085);
2075 }
2076
2077 @safe unittest
2078 {
2079 import std.meta : AliasSeq;
2080 assert(SysTime(DateTime(1970, 1, 1), UTC()).toUnixTime() == 0);
2081 foreach (units; AliasSeq!("hnsecs", "usecs", "msecs"))
2082 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 0), dur!units(1), UTC()).toUnixTime() == 0);
2083 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), UTC()).toUnixTime() == 1);
2084 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toUnixTime() == 0);
2085 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), usecs(999_999), UTC()).toUnixTime() == 0);
2086 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), msecs(999), UTC()).toUnixTime() == 0);
2087 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), UTC()).toUnixTime() == -1);
2088 }
2089
2090
2091 /++
2092 Converts from unix time (i.e. seconds from midnight, January 1st, 1970
2093 in UTC) to a $(LREF SysTime).
2094
2095 The C standard does not specify the representation of time_t, so it is
2096 implementation defined. On POSIX systems, unix time is equivalent to
2097 time_t, but that's not necessarily true on other systems (e.g. it is
2098 not true for the Digital Mars C runtime). So, be careful when using unix
2099 time with C functions on non-POSIX systems.
2100
2101 Params:
2102 unixTime = Seconds from midnight, January 1st, 1970 in UTC.
2103 tz = The time zone for the SysTime that's returned.
2104 +/
2105 static SysTime fromUnixTime(long unixTime, immutable TimeZone tz = LocalTime()) @safe pure nothrow
2106 {
2107 return SysTime(unixTimeToStdTime(unixTime), tz);
2108 }
2109
2110 ///
2111 @safe unittest
2112 {
2113 import core.time : hours;
2114 import std.datetime.date : DateTime;
2115 import std.datetime.timezone : SimpleTimeZone, UTC;
2116
2117 assert(SysTime.fromUnixTime(0) ==
2118 SysTime(DateTime(1970, 1, 1), UTC()));
2119
2120 auto pst = new immutable SimpleTimeZone(hours(-8));
2121 assert(SysTime.fromUnixTime(28800) ==
2122 SysTime(DateTime(1970, 1, 1), pst));
2123
2124 auto st1 = SysTime.fromUnixTime(1_198_311_285, UTC());
2125 assert(st1 == SysTime(DateTime(2007, 12, 22, 8, 14, 45), UTC()));
2126 assert(st1.timezone is UTC());
2127 assert(st1 == SysTime(DateTime(2007, 12, 22, 0, 14, 45), pst));
2128
2129 auto st2 = SysTime.fromUnixTime(1_198_311_285, pst);
2130 assert(st2 == SysTime(DateTime(2007, 12, 22, 8, 14, 45), UTC()));
2131 assert(st2.timezone is pst);
2132 assert(st2 == SysTime(DateTime(2007, 12, 22, 0, 14, 45), pst));
2133 }
2134
2135 @safe unittest
2136 {
2137 assert(SysTime.fromUnixTime(0) == SysTime(DateTime(1970, 1, 1), UTC()));
2138 assert(SysTime.fromUnixTime(1) == SysTime(DateTime(1970, 1, 1, 0, 0, 1), UTC()));
2139 assert(SysTime.fromUnixTime(-1) == SysTime(DateTime(1969, 12, 31, 23, 59, 59), UTC()));
2140
2141 auto st = SysTime.fromUnixTime(0);
2142 auto dt = cast(DateTime) st;
2143 assert(dt <= DateTime(1970, 2, 1) && dt >= DateTime(1969, 12, 31));
2144 assert(st.timezone is LocalTime());
2145
2146 auto aest = new immutable SimpleTimeZone(hours(10));
2147 assert(SysTime.fromUnixTime(-36000) == SysTime(DateTime(1970, 1, 1), aest));
2148 }
2149
2150
2151 /++
2152 Returns a $(D timeval) which represents this $(LREF SysTime).
2153
2154 Note that like all conversions in std.datetime, this is a truncating
2155 conversion.
2156
2157 If $(D timeval.tv_sec) is int, and the result can't fit in an int, then
2158 the closest value that can be held in 32 bits will be used for
2159 $(D tv_sec). (so $(D int.max) if it goes over and $(D int.min) if it
2160 goes under).
2161 +/
2162 timeval toTimeVal() @safe const pure nothrow
2163 {
2164 immutable tv_sec = toUnixTime!(typeof(timeval.tv_sec))();
2165 immutable fracHNSecs = removeUnitsFromHNSecs!"seconds"(_stdTime - 621_355_968_000_000_000L);
2166 immutable tv_usec = cast(typeof(timeval.tv_usec))convert!("hnsecs", "usecs")(fracHNSecs);
2167 return timeval(tv_sec, tv_usec);
2168 }
2169
2170 @safe unittest
2171 {
2172 assert(SysTime(DateTime(1970, 1, 1), UTC()).toTimeVal() == timeval(0, 0));
2173 assert(SysTime(DateTime(1970, 1, 1), hnsecs(9), UTC()).toTimeVal() == timeval(0, 0));
2174 assert(SysTime(DateTime(1970, 1, 1), hnsecs(10), UTC()).toTimeVal() == timeval(0, 1));
2175 assert(SysTime(DateTime(1970, 1, 1), usecs(7), UTC()).toTimeVal() == timeval(0, 7));
2176
2177 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), UTC()).toTimeVal() == timeval(1, 0));
2178 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), hnsecs(9), UTC()).toTimeVal() == timeval(1, 0));
2179 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), hnsecs(10), UTC()).toTimeVal() == timeval(1, 1));
2180 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), usecs(7), UTC()).toTimeVal() == timeval(1, 7));
2181
2182 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toTimeVal() == timeval(0, 0));
2183 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), hnsecs(9_999_990), UTC()).toTimeVal() == timeval(0, -1));
2184
2185 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), usecs(999_999), UTC()).toTimeVal() == timeval(0, -1));
2186 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), usecs(999), UTC()).toTimeVal() == timeval(0, -999_001));
2187 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), msecs(999), UTC()).toTimeVal() == timeval(0, -1000));
2188 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), UTC()).toTimeVal() == timeval(-1, 0));
2189 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 58), usecs(17), UTC()).toTimeVal() == timeval(-1, -999_983));
2190 }
2191
2192
2193 version (StdDdoc)
2194 {
2195 private struct timespec {}
2196 /++
2197 Returns a $(D timespec) which represents this $(LREF SysTime).
2198
2199 $(BLUE This function is Posix-Only.)
2200 +/
2201 timespec toTimeSpec() @safe const pure nothrow;
2202 }
2203 else version (Posix)
2204 {
2205 timespec toTimeSpec() @safe const pure nothrow
2206 {
2207 immutable tv_sec = toUnixTime!(typeof(timespec.tv_sec))();
2208 immutable fracHNSecs = removeUnitsFromHNSecs!"seconds"(_stdTime - 621_355_968_000_000_000L);
2209 immutable tv_nsec = cast(typeof(timespec.tv_nsec))convert!("hnsecs", "nsecs")(fracHNSecs);
2210 return timespec(tv_sec, tv_nsec);
2211 }
2212
2213 @safe unittest
2214 {
2215 assert(SysTime(DateTime(1970, 1, 1), UTC()).toTimeSpec() == timespec(0, 0));
2216 assert(SysTime(DateTime(1970, 1, 1), hnsecs(9), UTC()).toTimeSpec() == timespec(0, 900));
2217 assert(SysTime(DateTime(1970, 1, 1), hnsecs(10), UTC()).toTimeSpec() == timespec(0, 1000));
2218 assert(SysTime(DateTime(1970, 1, 1), usecs(7), UTC()).toTimeSpec() == timespec(0, 7000));
2219
2220 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), UTC()).toTimeSpec() == timespec(1, 0));
2221 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), hnsecs(9), UTC()).toTimeSpec() == timespec(1, 900));
2222 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), hnsecs(10), UTC()).toTimeSpec() == timespec(1, 1000));
2223 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), usecs(7), UTC()).toTimeSpec() == timespec(1, 7000));
2224
2225 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toTimeSpec() ==
2226 timespec(0, -100));
2227 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), hnsecs(9_999_990), UTC()).toTimeSpec() ==
2228 timespec(0, -1000));
2229
2230 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), usecs(999_999), UTC()).toTimeSpec() ==
2231 timespec(0, -1_000));
2232 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), usecs(999), UTC()).toTimeSpec() ==
2233 timespec(0, -999_001_000));
2234 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), msecs(999), UTC()).toTimeSpec() ==
2235 timespec(0, -1_000_000));
2236 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), UTC()).toTimeSpec() ==
2237 timespec(-1, 0));
2238 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 58), usecs(17), UTC()).toTimeSpec() ==
2239 timespec(-1, -999_983_000));
2240 }
2241 }
2242
2243 /++
2244 Returns a $(D tm) which represents this $(LREF SysTime).
2245 +/
2246 tm toTM() @safe const nothrow
2247 {
2248 auto dateTime = cast(DateTime) this;
2249 tm timeInfo;
2250
2251 timeInfo.tm_sec = dateTime.second;
2252 timeInfo.tm_min = dateTime.minute;
2253 timeInfo.tm_hour = dateTime.hour;
2254 timeInfo.tm_mday = dateTime.day;
2255 timeInfo.tm_mon = dateTime.month - 1;
2256 timeInfo.tm_year = dateTime.year - 1900;
2257 timeInfo.tm_wday = dateTime.dayOfWeek;
2258 timeInfo.tm_yday = dateTime.dayOfYear - 1;
2259 timeInfo.tm_isdst = _timezone.dstInEffect(_stdTime);
2260
2261 version (Posix)
2262 {
2263 import std.utf : toUTFz;
2264 timeInfo.tm_gmtoff = cast(int) convert!("hnsecs", "seconds")(adjTime - _stdTime);
2265 auto zone = (timeInfo.tm_isdst ? _timezone.dstName : _timezone.stdName);
2266 timeInfo.tm_zone = zone.toUTFz!(char*)();
2267 }
2268
2269 return timeInfo;
2270 }
2271
2272 @system unittest
2273 {
2274 import std.conv : to;
2275
2276 version (Posix)
2277 {
2278 scope(exit) clearTZEnvVar();
2279 setTZEnvVar("America/Los_Angeles");
2280 }
2281
2282 {
2283 auto timeInfo = SysTime(DateTime(1970, 1, 1)).toTM();
2284
2285 assert(timeInfo.tm_sec == 0);
2286 assert(timeInfo.tm_min == 0);
2287 assert(timeInfo.tm_hour == 0);
2288 assert(timeInfo.tm_mday == 1);
2289 assert(timeInfo.tm_mon == 0);
2290 assert(timeInfo.tm_year == 70);
2291 assert(timeInfo.tm_wday == 4);
2292 assert(timeInfo.tm_yday == 0);
2293
2294 version (Posix)
2295 assert(timeInfo.tm_isdst == 0);
2296 else version (Windows)
2297 assert(timeInfo.tm_isdst == 0 || timeInfo.tm_isdst == 1);
2298
2299 version (Posix)
2300 {
2301 assert(timeInfo.tm_gmtoff == -8 * 60 * 60);
2302 assert(to!string(timeInfo.tm_zone) == "PST");
2303 }
2304 }
2305
2306 {
2307 auto timeInfo = SysTime(DateTime(2010, 7, 4, 12, 15, 7), hnsecs(15)).toTM();
2308
2309 assert(timeInfo.tm_sec == 7);
2310 assert(timeInfo.tm_min == 15);
2311 assert(timeInfo.tm_hour == 12);
2312 assert(timeInfo.tm_mday == 4);
2313 assert(timeInfo.tm_mon == 6);
2314 assert(timeInfo.tm_year == 110);
2315 assert(timeInfo.tm_wday == 0);
2316 assert(timeInfo.tm_yday == 184);
2317
2318 version (Posix)
2319 assert(timeInfo.tm_isdst == 1);
2320 else version (Windows)
2321 assert(timeInfo.tm_isdst == 0 || timeInfo.tm_isdst == 1);
2322
2323 version (Posix)
2324 {
2325 assert(timeInfo.tm_gmtoff == -7 * 60 * 60);
2326 assert(to!string(timeInfo.tm_zone) == "PDT");
2327 }
2328 }
2329 }
2330
2331
2332 /++
2333 Adds the given number of years or months to this $(LREF SysTime). A
2334 negative number will subtract.
2335
2336 Note that if day overflow is allowed, and the date with the adjusted
2337 year/month overflows the number of days in the new month, then the month
2338 will be incremented by one, and the day set to the number of days
2339 overflowed. (e.g. if the day were 31 and the new month were June, then
2340 the month would be incremented to July, and the new day would be 1). If
2341 day overflow is not allowed, then the day will be set to the last valid
2342 day in the month (e.g. June 31st would become June 30th).
2343
2344 Params:
2345 units = The type of units to add ("years" or "months").
2346 value = The number of months or years to add to this
2347 $(LREF SysTime).
2348 allowOverflow = Whether the days should be allowed to overflow,
2349 causing the month to increment.
2350 +/
2351 ref SysTime add(string units)(long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) @safe nothrow
2352 if (units == "years" || units == "months")
2353 {
2354 auto hnsecs = adjTime;
2355 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
2356
2357 if (hnsecs < 0)
2358 {
2359 hnsecs += convert!("hours", "hnsecs")(24);
2360 --days;
2361 }
2362
2363 auto date = Date(cast(int) days);
2364 date.add!units(value, allowOverflow);
2365 days = date.dayOfGregorianCal - 1;
2366
2367 if (days < 0)
2368 {
2369 hnsecs -= convert!("hours", "hnsecs")(24);
2370 ++days;
2371 }
2372
2373 immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
2374
2375 adjTime = newDaysHNSecs + hnsecs;
2376
2377 return this;
2378 }
2379
2380 @safe unittest
2381 {
2382 auto st1 = SysTime(DateTime(2010, 1, 1, 12, 30, 33));
2383 st1.add!"months"(11);
2384 assert(st1 == SysTime(DateTime(2010, 12, 1, 12, 30, 33)));
2385
2386 auto st2 = SysTime(DateTime(2010, 1, 1, 12, 30, 33));
2387 st2.add!"months"(-11);
2388 assert(st2 == SysTime(DateTime(2009, 2, 1, 12, 30, 33)));
2389
2390 auto st3 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
2391 st3.add!"years"(1);
2392 assert(st3 == SysTime(DateTime(2001, 3, 1, 12, 30, 33)));
2393
2394 auto st4 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
2395 st4.add!"years"(1, AllowDayOverflow.no);
2396 assert(st4 == SysTime(DateTime(2001, 2, 28, 12, 30, 33)));
2397 }
2398
2399 // Test add!"years"() with AllowDayOverflow.yes
2400 @safe unittest
2401 {
2402 // Test A.D.
2403 {
2404 auto sysTime = SysTime(Date(1999, 7, 6));
2405 sysTime.add!"years"(7);
2406 assert(sysTime == SysTime(Date(2006, 7, 6)));
2407 sysTime.add!"years"(-9);
2408 assert(sysTime == SysTime(Date(1997, 7, 6)));
2409 }
2410
2411 {
2412 auto sysTime = SysTime(Date(1999, 2, 28));
2413 sysTime.add!"years"(1);
2414 assert(sysTime == SysTime(Date(2000, 2, 28)));
2415 }
2416
2417 {
2418 auto sysTime = SysTime(Date(2000, 2, 29));
2419 sysTime.add!"years"(-1);
2420 assert(sysTime == SysTime(Date(1999, 3, 1)));
2421 }
2422
2423 {
2424 auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 7, 3), msecs(234));
2425 sysTime.add!"years"(7);
2426 assert(sysTime == SysTime(DateTime(2006, 7, 6, 12, 7, 3), msecs(234)));
2427 sysTime.add!"years"(-9);
2428 assert(sysTime == SysTime(DateTime(1997, 7, 6, 12, 7, 3), msecs(234)));
2429 }
2430
2431 {
2432 auto sysTime = SysTime(DateTime(1999, 2, 28, 0, 7, 2), usecs(1207));
2433 sysTime.add!"years"(1);
2434 assert(sysTime == SysTime(DateTime(2000, 2, 28, 0, 7, 2), usecs(1207)));
2435 }
2436
2437 {
2438 auto sysTime = SysTime(DateTime(2000, 2, 29, 0, 7, 2), usecs(1207));
2439 sysTime.add!"years"(-1);
2440 assert(sysTime == SysTime(DateTime(1999, 3, 1, 0, 7, 2), usecs(1207)));
2441 }
2442
2443 // Test B.C.
2444 {
2445 auto sysTime = SysTime(Date(-1999, 7, 6));
2446 sysTime.add!"years"(-7);
2447 assert(sysTime == SysTime(Date(-2006, 7, 6)));
2448 sysTime.add!"years"(9);
2449 assert(sysTime == SysTime(Date(-1997, 7, 6)));
2450 }
2451
2452 {
2453 auto sysTime = SysTime(Date(-1999, 2, 28));
2454 sysTime.add!"years"(-1);
2455 assert(sysTime == SysTime(Date(-2000, 2, 28)));
2456 }
2457
2458 {
2459 auto sysTime = SysTime(Date(-2000, 2, 29));
2460 sysTime.add!"years"(1);
2461 assert(sysTime == SysTime(Date(-1999, 3, 1)));
2462 }
2463
2464 {
2465 auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 7, 3), msecs(234));
2466 sysTime.add!"years"(-7);
2467 assert(sysTime == SysTime(DateTime(-2006, 7, 6, 12, 7, 3), msecs(234)));
2468 sysTime.add!"years"(9);
2469 assert(sysTime == SysTime(DateTime(-1997, 7, 6, 12, 7, 3), msecs(234)));
2470 }
2471
2472 {
2473 auto sysTime = SysTime(DateTime(-1999, 2, 28, 3, 3, 3), hnsecs(3));
2474 sysTime.add!"years"(-1);
2475 assert(sysTime == SysTime(DateTime(-2000, 2, 28, 3, 3, 3), hnsecs(3)));
2476 }
2477
2478 {
2479 auto sysTime = SysTime(DateTime(-2000, 2, 29, 3, 3, 3), hnsecs(3));
2480 sysTime.add!"years"(1);
2481 assert(sysTime == SysTime(DateTime(-1999, 3, 1, 3, 3, 3), hnsecs(3)));
2482 }
2483
2484 // Test Both
2485 {
2486 auto sysTime = SysTime(Date(4, 7, 6));
2487 sysTime.add!"years"(-5);
2488 assert(sysTime == SysTime(Date(-1, 7, 6)));
2489 sysTime.add!"years"(5);
2490 assert(sysTime == SysTime(Date(4, 7, 6)));
2491 }
2492
2493 {
2494 auto sysTime = SysTime(Date(-4, 7, 6));
2495 sysTime.add!"years"(5);
2496 assert(sysTime == SysTime(Date(1, 7, 6)));
2497 sysTime.add!"years"(-5);
2498 assert(sysTime == SysTime(Date(-4, 7, 6)));
2499 }
2500
2501 {
2502 auto sysTime = SysTime(Date(4, 7, 6));
2503 sysTime.add!"years"(-8);
2504 assert(sysTime == SysTime(Date(-4, 7, 6)));
2505 sysTime.add!"years"(8);
2506 assert(sysTime == SysTime(Date(4, 7, 6)));
2507 }
2508
2509 {
2510 auto sysTime = SysTime(Date(-4, 7, 6));
2511 sysTime.add!"years"(8);
2512 assert(sysTime == SysTime(Date(4, 7, 6)));
2513 sysTime.add!"years"(-8);
2514 assert(sysTime == SysTime(Date(-4, 7, 6)));
2515 }
2516
2517 {
2518 auto sysTime = SysTime(Date(-4, 2, 29));
2519 sysTime.add!"years"(5);
2520 assert(sysTime == SysTime(Date(1, 3, 1)));
2521 }
2522
2523 {
2524 auto sysTime = SysTime(Date(4, 2, 29));
2525 sysTime.add!"years"(-5);
2526 assert(sysTime == SysTime(Date(-1, 3, 1)));
2527 }
2528
2529 {
2530 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
2531 sysTime.add!"years"(-1);
2532 assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0)));
2533 sysTime.add!"years"(1);
2534 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
2535 }
2536
2537 {
2538 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
2539 sysTime.add!"years"(-1);
2540 assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
2541 sysTime.add!"years"(1);
2542 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
2543 }
2544
2545 {
2546 auto sysTime = SysTime(DateTime(0, 1, 1, 0, 0, 0));
2547 sysTime.add!"years"(1);
2548 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
2549 sysTime.add!"years"(-1);
2550 assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0)));
2551 }
2552
2553 {
2554 auto sysTime = SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999));
2555 sysTime.add!"years"(1);
2556 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
2557 sysTime.add!"years"(-1);
2558 assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
2559 }
2560
2561 {
2562 auto sysTime = SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329));
2563 sysTime.add!"years"(-5);
2564 assert(sysTime == SysTime(DateTime(-1, 7, 6, 14, 7, 1), usecs(54329)));
2565 sysTime.add!"years"(5);
2566 assert(sysTime == SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329)));
2567 }
2568
2569 {
2570 auto sysTime = SysTime(DateTime(-4, 7, 6, 14, 7, 1), usecs(54329));
2571 sysTime.add!"years"(5);
2572 assert(sysTime == SysTime(DateTime(1, 7, 6, 14, 7, 1), usecs(54329)));
2573 sysTime.add!"years"(-5);
2574 assert(sysTime == SysTime(DateTime(-4, 7, 6, 14, 7, 1), usecs(54329)));
2575 }
2576
2577 {
2578 auto sysTime = SysTime(DateTime(-4, 2, 29, 5, 5, 5), msecs(555));
2579 sysTime.add!"years"(5);
2580 assert(sysTime == SysTime(DateTime(1, 3, 1, 5, 5, 5), msecs(555)));
2581 }
2582
2583 {
2584 auto sysTime = SysTime(DateTime(4, 2, 29, 5, 5, 5), msecs(555));
2585 sysTime.add!"years"(-5);
2586 assert(sysTime == SysTime(DateTime(-1, 3, 1, 5, 5, 5), msecs(555)));
2587 }
2588
2589 {
2590 auto sysTime = SysTime(DateTime(4, 2, 29, 5, 5, 5), msecs(555));
2591 sysTime.add!"years"(-5).add!"years"(7);
2592 assert(sysTime == SysTime(DateTime(6, 3, 1, 5, 5, 5), msecs(555)));
2593 }
2594
2595 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
2596 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
2597 static assert(!__traits(compiles, cst.add!"years"(4)));
2598 //static assert(!__traits(compiles, ist.add!"years"(4)));
2599 }
2600
2601 // Test add!"years"() with AllowDayOverflow.no
2602 @safe unittest
2603 {
2604 // Test A.D.
2605 {
2606 auto sysTime = SysTime(Date(1999, 7, 6));
2607 sysTime.add!"years"(7, AllowDayOverflow.no);
2608 assert(sysTime == SysTime(Date(2006, 7, 6)));
2609 sysTime.add!"years"(-9, AllowDayOverflow.no);
2610 assert(sysTime == SysTime(Date(1997, 7, 6)));
2611 }
2612
2613 {
2614 auto sysTime = SysTime(Date(1999, 2, 28));
2615 sysTime.add!"years"(1, AllowDayOverflow.no);
2616 assert(sysTime == SysTime(Date(2000, 2, 28)));
2617 }
2618
2619 {
2620 auto sysTime = SysTime(Date(2000, 2, 29));
2621 sysTime.add!"years"(-1, AllowDayOverflow.no);
2622 assert(sysTime == SysTime(Date(1999, 2, 28)));
2623 }
2624
2625 {
2626 auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 7, 3), msecs(234));
2627 sysTime.add!"years"(7, AllowDayOverflow.no);
2628 assert(sysTime == SysTime(DateTime(2006, 7, 6, 12, 7, 3), msecs(234)));
2629 sysTime.add!"years"(-9, AllowDayOverflow.no);
2630 assert(sysTime == SysTime(DateTime(1997, 7, 6, 12, 7, 3), msecs(234)));
2631 }
2632
2633 {
2634 auto sysTime = SysTime(DateTime(1999, 2, 28, 0, 7, 2), usecs(1207));
2635 sysTime.add!"years"(1, AllowDayOverflow.no);
2636 assert(sysTime == SysTime(DateTime(2000, 2, 28, 0, 7, 2), usecs(1207)));
2637 }
2638
2639 {
2640 auto sysTime = SysTime(DateTime(2000, 2, 29, 0, 7, 2), usecs(1207));
2641 sysTime.add!"years"(-1, AllowDayOverflow.no);
2642 assert(sysTime == SysTime(DateTime(1999, 2, 28, 0, 7, 2), usecs(1207)));
2643 }
2644
2645 // Test B.C.
2646 {
2647 auto sysTime = SysTime(Date(-1999, 7, 6));
2648 sysTime.add!"years"(-7, AllowDayOverflow.no);
2649 assert(sysTime == SysTime(Date(-2006, 7, 6)));
2650 sysTime.add!"years"(9, AllowDayOverflow.no);
2651 assert(sysTime == SysTime(Date(-1997, 7, 6)));
2652 }
2653
2654 {
2655 auto sysTime = SysTime(Date(-1999, 2, 28));
2656 sysTime.add!"years"(-1, AllowDayOverflow.no);
2657 assert(sysTime == SysTime(Date(-2000, 2, 28)));
2658 }
2659
2660 {
2661 auto sysTime = SysTime(Date(-2000, 2, 29));
2662 sysTime.add!"years"(1, AllowDayOverflow.no);
2663 assert(sysTime == SysTime(Date(-1999, 2, 28)));
2664 }
2665
2666 {
2667 auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 7, 3), msecs(234));
2668 sysTime.add!"years"(-7, AllowDayOverflow.no);
2669 assert(sysTime == SysTime(DateTime(-2006, 7, 6, 12, 7, 3), msecs(234)));
2670 sysTime.add!"years"(9, AllowDayOverflow.no);
2671 assert(sysTime == SysTime(DateTime(-1997, 7, 6, 12, 7, 3), msecs(234)));
2672 }
2673
2674 {
2675 auto sysTime = SysTime(DateTime(-1999, 2, 28, 3, 3, 3), hnsecs(3));
2676 sysTime.add!"years"(-1, AllowDayOverflow.no);
2677 assert(sysTime == SysTime(DateTime(-2000, 2, 28, 3, 3, 3), hnsecs(3)));
2678 }
2679
2680 {
2681 auto sysTime = SysTime(DateTime(-2000, 2, 29, 3, 3, 3), hnsecs(3));
2682 sysTime.add!"years"(1, AllowDayOverflow.no);
2683 assert(sysTime == SysTime(DateTime(-1999, 2, 28, 3, 3, 3), hnsecs(3)));
2684 }
2685
2686 // Test Both
2687 {
2688 auto sysTime = SysTime(Date(4, 7, 6));
2689 sysTime.add!"years"(-5, AllowDayOverflow.no);
2690 assert(sysTime == SysTime(Date(-1, 7, 6)));
2691 sysTime.add!"years"(5, AllowDayOverflow.no);
2692 assert(sysTime == SysTime(Date(4, 7, 6)));
2693 }
2694
2695 {
2696 auto sysTime = SysTime(Date(-4, 7, 6));
2697 sysTime.add!"years"(5, AllowDayOverflow.no);
2698 assert(sysTime == SysTime(Date(1, 7, 6)));
2699 sysTime.add!"years"(-5, AllowDayOverflow.no);
2700 assert(sysTime == SysTime(Date(-4, 7, 6)));
2701 }
2702
2703 {
2704 auto sysTime = SysTime(Date(4, 7, 6));
2705 sysTime.add!"years"(-8, AllowDayOverflow.no);
2706 assert(sysTime == SysTime(Date(-4, 7, 6)));
2707 sysTime.add!"years"(8, AllowDayOverflow.no);
2708 assert(sysTime == SysTime(Date(4, 7, 6)));
2709 }
2710
2711 {
2712 auto sysTime = SysTime(Date(-4, 7, 6));
2713 sysTime.add!"years"(8, AllowDayOverflow.no);
2714 assert(sysTime == SysTime(Date(4, 7, 6)));
2715 sysTime.add!"years"(-8, AllowDayOverflow.no);
2716 assert(sysTime == SysTime(Date(-4, 7, 6)));
2717 }
2718
2719 {
2720 auto sysTime = SysTime(Date(-4, 2, 29));
2721 sysTime.add!"years"(5, AllowDayOverflow.no);
2722 assert(sysTime == SysTime(Date(1, 2, 28)));
2723 }
2724
2725 {
2726 auto sysTime = SysTime(Date(4, 2, 29));
2727 sysTime.add!"years"(-5, AllowDayOverflow.no);
2728 assert(sysTime == SysTime(Date(-1, 2, 28)));
2729 }
2730
2731 {
2732 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
2733 sysTime.add!"years"(-1, AllowDayOverflow.no);
2734 assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0)));
2735 sysTime.add!"years"(1, AllowDayOverflow.no);
2736 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
2737 }
2738
2739 {
2740 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
2741 sysTime.add!"years"(-1, AllowDayOverflow.no);
2742 assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
2743 sysTime.add!"years"(1, AllowDayOverflow.no);
2744 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
2745 }
2746
2747 {
2748 auto sysTime = SysTime(DateTime(0, 1, 1, 0, 0, 0));
2749 sysTime.add!"years"(1, AllowDayOverflow.no);
2750 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
2751 sysTime.add!"years"(-1, AllowDayOverflow.no);
2752 assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0)));
2753 }
2754
2755 {
2756 auto sysTime = SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999));
2757 sysTime.add!"years"(1, AllowDayOverflow.no);
2758 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
2759 sysTime.add!"years"(-1, AllowDayOverflow.no);
2760 assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
2761 }
2762
2763 {
2764 auto sysTime = SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329));
2765 sysTime.add!"years"(-5);
2766 assert(sysTime == SysTime(DateTime(-1, 7, 6, 14, 7, 1), usecs(54329)));
2767 sysTime.add!"years"(5);
2768 assert(sysTime == SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329)));
2769 }
2770
2771 {
2772 auto sysTime = SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329));
2773 sysTime.add!"years"(-5, AllowDayOverflow.no);
2774 assert(sysTime == SysTime(DateTime(-1, 7, 6, 14, 7, 1), usecs(54329)));
2775 sysTime.add!"years"(5, AllowDayOverflow.no);
2776 assert(sysTime == SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329)));
2777 }
2778
2779 {
2780 auto sysTime = SysTime(DateTime(-4, 7, 6, 14, 7, 1), usecs(54329));
2781 sysTime.add!"years"(5, AllowDayOverflow.no);
2782 assert(sysTime == SysTime(DateTime(1, 7, 6, 14, 7, 1), usecs(54329)));
2783 sysTime.add!"years"(-5, AllowDayOverflow.no);
2784 assert(sysTime == SysTime(DateTime(-4, 7, 6, 14, 7, 1), usecs(54329)));
2785 }
2786
2787 {
2788 auto sysTime = SysTime(DateTime(-4, 2, 29, 5, 5, 5), msecs(555));
2789 sysTime.add!"years"(5, AllowDayOverflow.no);
2790 assert(sysTime == SysTime(DateTime(1, 2, 28, 5, 5, 5), msecs(555)));
2791 }
2792
2793 {
2794 auto sysTime = SysTime(DateTime(4, 2, 29, 5, 5, 5), msecs(555));
2795 sysTime.add!"years"(-5, AllowDayOverflow.no);
2796 assert(sysTime == SysTime(DateTime(-1, 2, 28, 5, 5, 5), msecs(555)));
2797 }
2798
2799 {
2800 auto sysTime = SysTime(DateTime(4, 2, 29, 5, 5, 5), msecs(555));
2801 sysTime.add!"years"(-5, AllowDayOverflow.no).add!"years"(7, AllowDayOverflow.no);
2802 assert(sysTime == SysTime(DateTime(6, 2, 28, 5, 5, 5), msecs(555)));
2803 }
2804 }
2805
2806 // Test add!"months"() with AllowDayOverflow.yes
2807 @safe unittest
2808 {
2809 // Test A.D.
2810 {
2811 auto sysTime = SysTime(Date(1999, 7, 6));
2812 sysTime.add!"months"(3);
2813 assert(sysTime == SysTime(Date(1999, 10, 6)));
2814 sysTime.add!"months"(-4);
2815 assert(sysTime == SysTime(Date(1999, 6, 6)));
2816 }
2817
2818 {
2819 auto sysTime = SysTime(Date(1999, 7, 6));
2820 sysTime.add!"months"(6);
2821 assert(sysTime == SysTime(Date(2000, 1, 6)));
2822 sysTime.add!"months"(-6);
2823 assert(sysTime == SysTime(Date(1999, 7, 6)));
2824 }
2825
2826 {
2827 auto sysTime = SysTime(Date(1999, 7, 6));
2828 sysTime.add!"months"(27);
2829 assert(sysTime == SysTime(Date(2001, 10, 6)));
2830 sysTime.add!"months"(-28);
2831 assert(sysTime == SysTime(Date(1999, 6, 6)));
2832 }
2833
2834 {
2835 auto sysTime = SysTime(Date(1999, 5, 31));
2836 sysTime.add!"months"(1);
2837 assert(sysTime == SysTime(Date(1999, 7, 1)));
2838 }
2839
2840 {
2841 auto sysTime = SysTime(Date(1999, 5, 31));
2842 sysTime.add!"months"(-1);
2843 assert(sysTime == SysTime(Date(1999, 5, 1)));
2844 }
2845
2846 {
2847 auto sysTime = SysTime(Date(1999, 2, 28));
2848 sysTime.add!"months"(12);
2849 assert(sysTime == SysTime(Date(2000, 2, 28)));
2850 }
2851
2852 {
2853 auto sysTime = SysTime(Date(2000, 2, 29));
2854 sysTime.add!"months"(12);
2855 assert(sysTime == SysTime(Date(2001, 3, 1)));
2856 }
2857
2858 {
2859 auto sysTime = SysTime(Date(1999, 7, 31));
2860 sysTime.add!"months"(1);
2861 assert(sysTime == SysTime(Date(1999, 8, 31)));
2862 sysTime.add!"months"(1);
2863 assert(sysTime == SysTime(Date(1999, 10, 1)));
2864 }
2865
2866 {
2867 auto sysTime = SysTime(Date(1998, 8, 31));
2868 sysTime.add!"months"(13);
2869 assert(sysTime == SysTime(Date(1999, 10, 1)));
2870 sysTime.add!"months"(-13);
2871 assert(sysTime == SysTime(Date(1998, 9, 1)));
2872 }
2873
2874 {
2875 auto sysTime = SysTime(Date(1997, 12, 31));
2876 sysTime.add!"months"(13);
2877 assert(sysTime == SysTime(Date(1999, 1, 31)));
2878 sysTime.add!"months"(-13);
2879 assert(sysTime == SysTime(Date(1997, 12, 31)));
2880 }
2881
2882 {
2883 auto sysTime = SysTime(Date(1997, 12, 31));
2884 sysTime.add!"months"(14);
2885 assert(sysTime == SysTime(Date(1999, 3, 3)));
2886 sysTime.add!"months"(-14);
2887 assert(sysTime == SysTime(Date(1998, 1, 3)));
2888 }
2889
2890 {
2891 auto sysTime = SysTime(Date(1998, 12, 31));
2892 sysTime.add!"months"(14);
2893 assert(sysTime == SysTime(Date(2000, 3, 2)));
2894 sysTime.add!"months"(-14);
2895 assert(sysTime == SysTime(Date(1999, 1, 2)));
2896 }
2897
2898 {
2899 auto sysTime = SysTime(Date(1999, 12, 31));
2900 sysTime.add!"months"(14);
2901 assert(sysTime == SysTime(Date(2001, 3, 3)));
2902 sysTime.add!"months"(-14);
2903 assert(sysTime == SysTime(Date(2000, 1, 3)));
2904 }
2905
2906 {
2907 auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), usecs(5007));
2908 sysTime.add!"months"(3);
2909 assert(sysTime == SysTime(DateTime(1999, 10, 6, 12, 2, 7), usecs(5007)));
2910 sysTime.add!"months"(-4);
2911 assert(sysTime == SysTime(DateTime(1999, 6, 6, 12, 2, 7), usecs(5007)));
2912 }
2913
2914 {
2915 auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), hnsecs(422202));
2916 sysTime.add!"months"(14);
2917 assert(sysTime == SysTime(DateTime(2000, 3, 2, 7, 7, 7), hnsecs(422202)));
2918 sysTime.add!"months"(-14);
2919 assert(sysTime == SysTime(DateTime(1999, 1, 2, 7, 7, 7), hnsecs(422202)));
2920 }
2921
2922 {
2923 auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), hnsecs(422202));
2924 sysTime.add!"months"(14);
2925 assert(sysTime == SysTime(DateTime(2001, 3, 3, 7, 7, 7), hnsecs(422202)));
2926 sysTime.add!"months"(-14);
2927 assert(sysTime == SysTime(DateTime(2000, 1, 3, 7, 7, 7), hnsecs(422202)));
2928 }
2929
2930 // Test B.C.
2931 {
2932 auto sysTime = SysTime(Date(-1999, 7, 6));
2933 sysTime.add!"months"(3);
2934 assert(sysTime == SysTime(Date(-1999, 10, 6)));
2935 sysTime.add!"months"(-4);
2936 assert(sysTime == SysTime(Date(-1999, 6, 6)));
2937 }
2938
2939 {
2940 auto sysTime = SysTime(Date(-1999, 7, 6));
2941 sysTime.add!"months"(6);
2942 assert(sysTime == SysTime(Date(-1998, 1, 6)));
2943 sysTime.add!"months"(-6);
2944 assert(sysTime == SysTime(Date(-1999, 7, 6)));
2945 }
2946
2947 {
2948 auto sysTime = SysTime(Date(-1999, 7, 6));
2949 sysTime.add!"months"(-27);
2950 assert(sysTime == SysTime(Date(-2001, 4, 6)));
2951 sysTime.add!"months"(28);
2952 assert(sysTime == SysTime(Date(-1999, 8, 6)));
2953 }
2954
2955 {
2956 auto sysTime = SysTime(Date(-1999, 5, 31));
2957 sysTime.add!"months"(1);
2958 assert(sysTime == SysTime(Date(-1999, 7, 1)));
2959 }
2960
2961 {
2962 auto sysTime = SysTime(Date(-1999, 5, 31));
2963 sysTime.add!"months"(-1);
2964 assert(sysTime == SysTime(Date(-1999, 5, 1)));
2965 }
2966
2967 {
2968 auto sysTime = SysTime(Date(-1999, 2, 28));
2969 sysTime.add!"months"(-12);
2970 assert(sysTime == SysTime(Date(-2000, 2, 28)));
2971 }
2972
2973 {
2974 auto sysTime = SysTime(Date(-2000, 2, 29));
2975 sysTime.add!"months"(-12);
2976 assert(sysTime == SysTime(Date(-2001, 3, 1)));
2977 }
2978
2979 {
2980 auto sysTime = SysTime(Date(-1999, 7, 31));
2981 sysTime.add!"months"(1);
2982 assert(sysTime == SysTime(Date(-1999, 8, 31)));
2983 sysTime.add!"months"(1);
2984 assert(sysTime == SysTime(Date(-1999, 10, 1)));
2985 }
2986
2987 {
2988 auto sysTime = SysTime(Date(-1998, 8, 31));
2989 sysTime.add!"months"(13);
2990 assert(sysTime == SysTime(Date(-1997, 10, 1)));
2991 sysTime.add!"months"(-13);
2992 assert(sysTime == SysTime(Date(-1998, 9, 1)));
2993 }
2994
2995 {
2996 auto sysTime = SysTime(Date(-1997, 12, 31));
2997 sysTime.add!"months"(13);
2998 assert(sysTime == SysTime(Date(-1995, 1, 31)));
2999 sysTime.add!"months"(-13);
3000 assert(sysTime == SysTime(Date(-1997, 12, 31)));
3001 }
3002
3003 {
3004 auto sysTime = SysTime(Date(-1997, 12, 31));
3005 sysTime.add!"months"(14);
3006 assert(sysTime == SysTime(Date(-1995, 3, 3)));
3007 sysTime.add!"months"(-14);
3008 assert(sysTime == SysTime(Date(-1996, 1, 3)));
3009 }
3010
3011 {
3012 auto sysTime = SysTime(Date(-2002, 12, 31));
3013 sysTime.add!"months"(14);
3014 assert(sysTime == SysTime(Date(-2000, 3, 2)));
3015 sysTime.add!"months"(-14);
3016 assert(sysTime == SysTime(Date(-2001, 1, 2)));
3017 }
3018
3019 {
3020 auto sysTime = SysTime(Date(-2001, 12, 31));
3021 sysTime.add!"months"(14);
3022 assert(sysTime == SysTime(Date(-1999, 3, 3)));
3023 sysTime.add!"months"(-14);
3024 assert(sysTime == SysTime(Date(-2000, 1, 3)));
3025 }
3026
3027 {
3028 auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), usecs(5007));
3029 sysTime.add!"months"(3);
3030 assert(sysTime == SysTime(DateTime(-1999, 10, 6, 12, 2, 7), usecs(5007)));
3031 sysTime.add!"months"(-4);
3032 assert(sysTime == SysTime(DateTime(-1999, 6, 6, 12, 2, 7), usecs(5007)));
3033 }
3034
3035 {
3036 auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), hnsecs(422202));
3037 sysTime.add!"months"(14);
3038 assert(sysTime == SysTime(DateTime(-2000, 3, 2, 7, 7, 7), hnsecs(422202)));
3039 sysTime.add!"months"(-14);
3040 assert(sysTime == SysTime(DateTime(-2001, 1, 2, 7, 7, 7), hnsecs(422202)));
3041 }
3042
3043 {
3044 auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), hnsecs(422202));
3045 sysTime.add!"months"(14);
3046 assert(sysTime == SysTime(DateTime(-1999, 3, 3, 7, 7, 7), hnsecs(422202)));
3047 sysTime.add!"months"(-14);
3048 assert(sysTime == SysTime(DateTime(-2000, 1, 3, 7, 7, 7), hnsecs(422202)));
3049 }
3050
3051 // Test Both
3052 {
3053 auto sysTime = SysTime(Date(1, 1, 1));
3054 sysTime.add!"months"(-1);
3055 assert(sysTime == SysTime(Date(0, 12, 1)));
3056 sysTime.add!"months"(1);
3057 assert(sysTime == SysTime(Date(1, 1, 1)));
3058 }
3059
3060 {
3061 auto sysTime = SysTime(Date(4, 1, 1));
3062 sysTime.add!"months"(-48);
3063 assert(sysTime == SysTime(Date(0, 1, 1)));
3064 sysTime.add!"months"(48);
3065 assert(sysTime == SysTime(Date(4, 1, 1)));
3066 }
3067
3068 {
3069 auto sysTime = SysTime(Date(4, 3, 31));
3070 sysTime.add!"months"(-49);
3071 assert(sysTime == SysTime(Date(0, 3, 2)));
3072 sysTime.add!"months"(49);
3073 assert(sysTime == SysTime(Date(4, 4, 2)));
3074 }
3075
3076 {
3077 auto sysTime = SysTime(Date(4, 3, 31));
3078 sysTime.add!"months"(-85);
3079 assert(sysTime == SysTime(Date(-3, 3, 3)));
3080 sysTime.add!"months"(85);
3081 assert(sysTime == SysTime(Date(4, 4, 3)));
3082 }
3083
3084 {
3085 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
3086 sysTime.add!"months"(-1);
3087 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
3088 sysTime.add!"months"(1);
3089 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
3090 }
3091
3092 {
3093 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
3094 sysTime.add!"months"(-1);
3095 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
3096 sysTime.add!"months"(1);
3097 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3098 }
3099
3100 {
3101 auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0));
3102 sysTime.add!"months"(1);
3103 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
3104 sysTime.add!"months"(-1);
3105 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
3106 }
3107
3108 {
3109 auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999));
3110 sysTime.add!"months"(1);
3111 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3112 sysTime.add!"months"(-1);
3113 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
3114 }
3115
3116 {
3117 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17));
3118 sysTime.add!"months"(-1);
3119 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 7, 9), hnsecs(17)));
3120 sysTime.add!"months"(1);
3121 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17)));
3122 }
3123
3124 {
3125 auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), msecs(9));
3126 sysTime.add!"months"(-85);
3127 assert(sysTime == SysTime(DateTime(-3, 3, 3, 12, 11, 10), msecs(9)));
3128 sysTime.add!"months"(85);
3129 assert(sysTime == SysTime(DateTime(4, 4, 3, 12, 11, 10), msecs(9)));
3130 }
3131
3132 {
3133 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
3134 sysTime.add!"months"(85);
3135 assert(sysTime == SysTime(DateTime(4, 5, 1, 12, 11, 10), msecs(9)));
3136 sysTime.add!"months"(-85);
3137 assert(sysTime == SysTime(DateTime(-3, 4, 1, 12, 11, 10), msecs(9)));
3138 }
3139
3140 {
3141 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
3142 sysTime.add!"months"(85).add!"months"(-83);
3143 assert(sysTime == SysTime(DateTime(-3, 6, 1, 12, 11, 10), msecs(9)));
3144 }
3145
3146 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
3147 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
3148 static assert(!__traits(compiles, cst.add!"months"(4)));
3149 //static assert(!__traits(compiles, ist.add!"months"(4)));
3150 }
3151
3152 // Test add!"months"() with AllowDayOverflow.no
3153 @safe unittest
3154 {
3155 // Test A.D.
3156 {
3157 auto sysTime = SysTime(Date(1999, 7, 6));
3158 sysTime.add!"months"(3, AllowDayOverflow.no);
3159 assert(sysTime == SysTime(Date(1999, 10, 6)));
3160 sysTime.add!"months"(-4, AllowDayOverflow.no);
3161 assert(sysTime == SysTime(Date(1999, 6, 6)));
3162 }
3163
3164 {
3165 auto sysTime = SysTime(Date(1999, 7, 6));
3166 sysTime.add!"months"(6, AllowDayOverflow.no);
3167 assert(sysTime == SysTime(Date(2000, 1, 6)));
3168 sysTime.add!"months"(-6, AllowDayOverflow.no);
3169 assert(sysTime == SysTime(Date(1999, 7, 6)));
3170 }
3171
3172 {
3173 auto sysTime = SysTime(Date(1999, 7, 6));
3174 sysTime.add!"months"(27, AllowDayOverflow.no);
3175 assert(sysTime == SysTime(Date(2001, 10, 6)));
3176 sysTime.add!"months"(-28, AllowDayOverflow.no);
3177 assert(sysTime == SysTime(Date(1999, 6, 6)));
3178 }
3179
3180 {
3181 auto sysTime = SysTime(Date(1999, 5, 31));
3182 sysTime.add!"months"(1, AllowDayOverflow.no);
3183 assert(sysTime == SysTime(Date(1999, 6, 30)));
3184 }
3185
3186 {
3187 auto sysTime = SysTime(Date(1999, 5, 31));
3188 sysTime.add!"months"(-1, AllowDayOverflow.no);
3189 assert(sysTime == SysTime(Date(1999, 4, 30)));
3190 }
3191
3192 {
3193 auto sysTime = SysTime(Date(1999, 2, 28));
3194 sysTime.add!"months"(12, AllowDayOverflow.no);
3195 assert(sysTime == SysTime(Date(2000, 2, 28)));
3196 }
3197
3198 {
3199 auto sysTime = SysTime(Date(2000, 2, 29));
3200 sysTime.add!"months"(12, AllowDayOverflow.no);
3201 assert(sysTime == SysTime(Date(2001, 2, 28)));
3202 }
3203
3204 {
3205 auto sysTime = SysTime(Date(1999, 7, 31));
3206 sysTime.add!"months"(1, AllowDayOverflow.no);
3207 assert(sysTime == SysTime(Date(1999, 8, 31)));
3208 sysTime.add!"months"(1, AllowDayOverflow.no);
3209 assert(sysTime == SysTime(Date(1999, 9, 30)));
3210 }
3211
3212 {
3213 auto sysTime = SysTime(Date(1998, 8, 31));
3214 sysTime.add!"months"(13, AllowDayOverflow.no);
3215 assert(sysTime == SysTime(Date(1999, 9, 30)));
3216 sysTime.add!"months"(-13, AllowDayOverflow.no);
3217 assert(sysTime == SysTime(Date(1998, 8, 30)));
3218 }
3219
3220 {
3221 auto sysTime = SysTime(Date(1997, 12, 31));
3222 sysTime.add!"months"(13, AllowDayOverflow.no);
3223 assert(sysTime == SysTime(Date(1999, 1, 31)));
3224 sysTime.add!"months"(-13, AllowDayOverflow.no);
3225 assert(sysTime == SysTime(Date(1997, 12, 31)));
3226 }
3227
3228 {
3229 auto sysTime = SysTime(Date(1997, 12, 31));
3230 sysTime.add!"months"(14, AllowDayOverflow.no);
3231 assert(sysTime == SysTime(Date(1999, 2, 28)));
3232 sysTime.add!"months"(-14, AllowDayOverflow.no);
3233 assert(sysTime == SysTime(Date(1997, 12, 28)));
3234 }
3235
3236 {
3237 auto sysTime = SysTime(Date(1998, 12, 31));
3238 sysTime.add!"months"(14, AllowDayOverflow.no);
3239 assert(sysTime == SysTime(Date(2000, 2, 29)));
3240 sysTime.add!"months"(-14, AllowDayOverflow.no);
3241 assert(sysTime == SysTime(Date(1998, 12, 29)));
3242 }
3243
3244 {
3245 auto sysTime = SysTime(Date(1999, 12, 31));
3246 sysTime.add!"months"(14, AllowDayOverflow.no);
3247 assert(sysTime == SysTime(Date(2001, 2, 28)));
3248 sysTime.add!"months"(-14, AllowDayOverflow.no);
3249 assert(sysTime == SysTime(Date(1999, 12, 28)));
3250 }
3251
3252 {
3253 auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), usecs(5007));
3254 sysTime.add!"months"(3, AllowDayOverflow.no);
3255 assert(sysTime == SysTime(DateTime(1999, 10, 6, 12, 2, 7), usecs(5007)));
3256 sysTime.add!"months"(-4, AllowDayOverflow.no);
3257 assert(sysTime == SysTime(DateTime(1999, 6, 6, 12, 2, 7), usecs(5007)));
3258 }
3259
3260 {
3261 auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), hnsecs(422202));
3262 sysTime.add!"months"(14, AllowDayOverflow.no);
3263 assert(sysTime == SysTime(DateTime(2000, 2, 29, 7, 7, 7), hnsecs(422202)));
3264 sysTime.add!"months"(-14, AllowDayOverflow.no);
3265 assert(sysTime == SysTime(DateTime(1998, 12, 29, 7, 7, 7), hnsecs(422202)));
3266 }
3267
3268 {
3269 auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), hnsecs(422202));
3270 sysTime.add!"months"(14, AllowDayOverflow.no);
3271 assert(sysTime == SysTime(DateTime(2001, 2, 28, 7, 7, 7), hnsecs(422202)));
3272 sysTime.add!"months"(-14, AllowDayOverflow.no);
3273 assert(sysTime == SysTime(DateTime(1999, 12, 28, 7, 7, 7), hnsecs(422202)));
3274 }
3275
3276 // Test B.C.
3277 {
3278 auto sysTime = SysTime(Date(-1999, 7, 6));
3279 sysTime.add!"months"(3, AllowDayOverflow.no);
3280 assert(sysTime == SysTime(Date(-1999, 10, 6)));
3281 sysTime.add!"months"(-4, AllowDayOverflow.no);
3282 assert(sysTime == SysTime(Date(-1999, 6, 6)));
3283 }
3284
3285 {
3286 auto sysTime = SysTime(Date(-1999, 7, 6));
3287 sysTime.add!"months"(6, AllowDayOverflow.no);
3288 assert(sysTime == SysTime(Date(-1998, 1, 6)));
3289 sysTime.add!"months"(-6, AllowDayOverflow.no);
3290 assert(sysTime == SysTime(Date(-1999, 7, 6)));
3291 }
3292
3293 {
3294 auto sysTime = SysTime(Date(-1999, 7, 6));
3295 sysTime.add!"months"(-27, AllowDayOverflow.no);
3296 assert(sysTime == SysTime(Date(-2001, 4, 6)));
3297 sysTime.add!"months"(28, AllowDayOverflow.no);
3298 assert(sysTime == SysTime(Date(-1999, 8, 6)));
3299 }
3300
3301 {
3302 auto sysTime = SysTime(Date(-1999, 5, 31));
3303 sysTime.add!"months"(1, AllowDayOverflow.no);
3304 assert(sysTime == SysTime(Date(-1999, 6, 30)));
3305 }
3306
3307 {
3308 auto sysTime = SysTime(Date(-1999, 5, 31));
3309 sysTime.add!"months"(-1, AllowDayOverflow.no);
3310 assert(sysTime == SysTime(Date(-1999, 4, 30)));
3311 }
3312
3313 {
3314 auto sysTime = SysTime(Date(-1999, 2, 28));
3315 sysTime.add!"months"(-12, AllowDayOverflow.no);
3316 assert(sysTime == SysTime(Date(-2000, 2, 28)));
3317 }
3318
3319 {
3320 auto sysTime = SysTime(Date(-2000, 2, 29));
3321 sysTime.add!"months"(-12, AllowDayOverflow.no);
3322 assert(sysTime == SysTime(Date(-2001, 2, 28)));
3323 }
3324
3325 {
3326 auto sysTime = SysTime(Date(-1999, 7, 31));
3327 sysTime.add!"months"(1, AllowDayOverflow.no);
3328 assert(sysTime == SysTime(Date(-1999, 8, 31)));
3329 sysTime.add!"months"(1, AllowDayOverflow.no);
3330 assert(sysTime == SysTime(Date(-1999, 9, 30)));
3331 }
3332
3333 {
3334 auto sysTime = SysTime(Date(-1998, 8, 31));
3335 sysTime.add!"months"(13, AllowDayOverflow.no);
3336 assert(sysTime == SysTime(Date(-1997, 9, 30)));
3337 sysTime.add!"months"(-13, AllowDayOverflow.no);
3338 assert(sysTime == SysTime(Date(-1998, 8, 30)));
3339 }
3340
3341 {
3342 auto sysTime = SysTime(Date(-1997, 12, 31));
3343 sysTime.add!"months"(13, AllowDayOverflow.no);
3344 assert(sysTime == SysTime(Date(-1995, 1, 31)));
3345 sysTime.add!"months"(-13, AllowDayOverflow.no);
3346 assert(sysTime == SysTime(Date(-1997, 12, 31)));
3347 }
3348
3349 {
3350 auto sysTime = SysTime(Date(-1997, 12, 31));
3351 sysTime.add!"months"(14, AllowDayOverflow.no);
3352 assert(sysTime == SysTime(Date(-1995, 2, 28)));
3353 sysTime.add!"months"(-14, AllowDayOverflow.no);
3354 assert(sysTime == SysTime(Date(-1997, 12, 28)));
3355 }
3356
3357 {
3358 auto sysTime = SysTime(Date(-2002, 12, 31));
3359 sysTime.add!"months"(14, AllowDayOverflow.no);
3360 assert(sysTime == SysTime(Date(-2000, 2, 29)));
3361 sysTime.add!"months"(-14, AllowDayOverflow.no);
3362 assert(sysTime == SysTime(Date(-2002, 12, 29)));
3363 }
3364
3365 {
3366 auto sysTime = SysTime(Date(-2001, 12, 31));
3367 sysTime.add!"months"(14, AllowDayOverflow.no);
3368 assert(sysTime == SysTime(Date(-1999, 2, 28)));
3369 sysTime.add!"months"(-14, AllowDayOverflow.no);
3370 assert(sysTime == SysTime(Date(-2001, 12, 28)));
3371 }
3372
3373 {
3374 auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), usecs(5007));
3375 sysTime.add!"months"(3, AllowDayOverflow.no);
3376 assert(sysTime == SysTime(DateTime(-1999, 10, 6, 12, 2, 7), usecs(5007)));
3377 sysTime.add!"months"(-4, AllowDayOverflow.no);
3378 assert(sysTime == SysTime(DateTime(-1999, 6, 6, 12, 2, 7), usecs(5007)));
3379 }
3380
3381 {
3382 auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), hnsecs(422202));
3383 sysTime.add!"months"(14, AllowDayOverflow.no);
3384 assert(sysTime == SysTime(DateTime(-2000, 2, 29, 7, 7, 7), hnsecs(422202)));
3385 sysTime.add!"months"(-14, AllowDayOverflow.no);
3386 assert(sysTime == SysTime(DateTime(-2002, 12, 29, 7, 7, 7), hnsecs(422202)));
3387 }
3388
3389 {
3390 auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), hnsecs(422202));
3391 sysTime.add!"months"(14, AllowDayOverflow.no);
3392 assert(sysTime == SysTime(DateTime(-1999, 2, 28, 7, 7, 7), hnsecs(422202)));
3393 sysTime.add!"months"(-14, AllowDayOverflow.no);
3394 assert(sysTime == SysTime(DateTime(-2001, 12, 28, 7, 7, 7), hnsecs(422202)));
3395 }
3396
3397 // Test Both
3398 {
3399 auto sysTime = SysTime(Date(1, 1, 1));
3400 sysTime.add!"months"(-1, AllowDayOverflow.no);
3401 assert(sysTime == SysTime(Date(0, 12, 1)));
3402 sysTime.add!"months"(1, AllowDayOverflow.no);
3403 assert(sysTime == SysTime(Date(1, 1, 1)));
3404 }
3405
3406 {
3407 auto sysTime = SysTime(Date(4, 1, 1));
3408 sysTime.add!"months"(-48, AllowDayOverflow.no);
3409 assert(sysTime == SysTime(Date(0, 1, 1)));
3410 sysTime.add!"months"(48, AllowDayOverflow.no);
3411 assert(sysTime == SysTime(Date(4, 1, 1)));
3412 }
3413
3414 {
3415 auto sysTime = SysTime(Date(4, 3, 31));
3416 sysTime.add!"months"(-49, AllowDayOverflow.no);
3417 assert(sysTime == SysTime(Date(0, 2, 29)));
3418 sysTime.add!"months"(49, AllowDayOverflow.no);
3419 assert(sysTime == SysTime(Date(4, 3, 29)));
3420 }
3421
3422 {
3423 auto sysTime = SysTime(Date(4, 3, 31));
3424 sysTime.add!"months"(-85, AllowDayOverflow.no);
3425 assert(sysTime == SysTime(Date(-3, 2, 28)));
3426 sysTime.add!"months"(85, AllowDayOverflow.no);
3427 assert(sysTime == SysTime(Date(4, 3, 28)));
3428 }
3429
3430 {
3431 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
3432 sysTime.add!"months"(-1, AllowDayOverflow.no);
3433 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
3434 sysTime.add!"months"(1, AllowDayOverflow.no);
3435 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
3436 }
3437
3438 {
3439 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
3440 sysTime.add!"months"(-1, AllowDayOverflow.no);
3441 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
3442 sysTime.add!"months"(1, AllowDayOverflow.no);
3443 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3444 }
3445
3446 {
3447 auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0));
3448 sysTime.add!"months"(1, AllowDayOverflow.no);
3449 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
3450 sysTime.add!"months"(-1, AllowDayOverflow.no);
3451 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
3452 }
3453
3454 {
3455 auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999));
3456 sysTime.add!"months"(1, AllowDayOverflow.no);
3457 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3458 sysTime.add!"months"(-1, AllowDayOverflow.no);
3459 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
3460 }
3461
3462 {
3463 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17));
3464 sysTime.add!"months"(-1, AllowDayOverflow.no);
3465 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 7, 9), hnsecs(17)));
3466 sysTime.add!"months"(1, AllowDayOverflow.no);
3467 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17)));
3468 }
3469
3470 {
3471 auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), msecs(9));
3472 sysTime.add!"months"(-85, AllowDayOverflow.no);
3473 assert(sysTime == SysTime(DateTime(-3, 2, 28, 12, 11, 10), msecs(9)));
3474 sysTime.add!"months"(85, AllowDayOverflow.no);
3475 assert(sysTime == SysTime(DateTime(4, 3, 28, 12, 11, 10), msecs(9)));
3476 }
3477
3478 {
3479 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
3480 sysTime.add!"months"(85, AllowDayOverflow.no);
3481 assert(sysTime == SysTime(DateTime(4, 4, 30, 12, 11, 10), msecs(9)));
3482 sysTime.add!"months"(-85, AllowDayOverflow.no);
3483 assert(sysTime == SysTime(DateTime(-3, 3, 30, 12, 11, 10), msecs(9)));
3484 }
3485
3486 {
3487 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
3488 sysTime.add!"months"(85, AllowDayOverflow.no).add!"months"(-83, AllowDayOverflow.no);
3489 assert(sysTime == SysTime(DateTime(-3, 5, 30, 12, 11, 10), msecs(9)));
3490 }
3491 }
3492
3493
3494 /++
3495 Adds the given number of years or months to this $(LREF SysTime). A
3496 negative number will subtract.
3497
3498 The difference between rolling and adding is that rolling does not
3499 affect larger units. Rolling a $(LREF SysTime) 12 months
3500 gets the exact same $(LREF SysTime). However, the days can still be
3501 affected due to the differing number of days in each month.
3502
3503 Because there are no units larger than years, there is no difference
3504 between adding and rolling years.
3505
3506 Params:
3507 units = The type of units to add ("years" or "months").
3508 value = The number of months or years to add to this
3509 $(LREF SysTime).
3510 allowOverflow = Whether the days should be allowed to overflow,
3511 causing the month to increment.
3512 +/
3513 ref SysTime roll(string units)(long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) @safe nothrow
3514 if (units == "years")
3515 {
3516 return add!"years"(value, allowOverflow);
3517 }
3518
3519 ///
3520 @safe unittest
3521 {
3522 import std.datetime.date : AllowDayOverflow, DateTime;
3523
3524 auto st1 = SysTime(DateTime(2010, 1, 1, 12, 33, 33));
3525 st1.roll!"months"(1);
3526 assert(st1 == SysTime(DateTime(2010, 2, 1, 12, 33, 33)));
3527
3528 auto st2 = SysTime(DateTime(2010, 1, 1, 12, 33, 33));
3529 st2.roll!"months"(-1);
3530 assert(st2 == SysTime(DateTime(2010, 12, 1, 12, 33, 33)));
3531
3532 auto st3 = SysTime(DateTime(1999, 1, 29, 12, 33, 33));
3533 st3.roll!"months"(1);
3534 assert(st3 == SysTime(DateTime(1999, 3, 1, 12, 33, 33)));
3535
3536 auto st4 = SysTime(DateTime(1999, 1, 29, 12, 33, 33));
3537 st4.roll!"months"(1, AllowDayOverflow.no);
3538 assert(st4 == SysTime(DateTime(1999, 2, 28, 12, 33, 33)));
3539
3540 auto st5 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
3541 st5.roll!"years"(1);
3542 assert(st5 == SysTime(DateTime(2001, 3, 1, 12, 30, 33)));
3543
3544 auto st6 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
3545 st6.roll!"years"(1, AllowDayOverflow.no);
3546 assert(st6 == SysTime(DateTime(2001, 2, 28, 12, 30, 33)));
3547 }
3548
3549 @safe unittest
3550 {
3551 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
3552 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
3553 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
3554 st.roll!"years"(4);
3555 static assert(!__traits(compiles, cst.roll!"years"(4)));
3556 //static assert(!__traits(compiles, ist.roll!"years"(4)));
3557 }
3558
3559
3560 // Shares documentation with "years" overload.
3561 ref SysTime roll(string units)(long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) @safe nothrow
3562 if (units == "months")
3563 {
3564 auto hnsecs = adjTime;
3565 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
3566
3567 if (hnsecs < 0)
3568 {
3569 hnsecs += convert!("hours", "hnsecs")(24);
3570 --days;
3571 }
3572
3573 auto date = Date(cast(int) days);
3574 date.roll!"months"(value, allowOverflow);
3575 days = date.dayOfGregorianCal - 1;
3576
3577 if (days < 0)
3578 {
3579 hnsecs -= convert!("hours", "hnsecs")(24);
3580 ++days;
3581 }
3582
3583 immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
3584 adjTime = newDaysHNSecs + hnsecs;
3585 return this;
3586 }
3587
3588 // Test roll!"months"() with AllowDayOverflow.yes
3589 @safe unittest
3590 {
3591 // Test A.D.
3592 {
3593 auto sysTime = SysTime(Date(1999, 7, 6));
3594 sysTime.roll!"months"(3);
3595 assert(sysTime == SysTime(Date(1999, 10, 6)));
3596 sysTime.roll!"months"(-4);
3597 assert(sysTime == SysTime(Date(1999, 6, 6)));
3598 }
3599
3600 {
3601 auto sysTime = SysTime(Date(1999, 7, 6));
3602 sysTime.roll!"months"(6);
3603 assert(sysTime == SysTime(Date(1999, 1, 6)));
3604 sysTime.roll!"months"(-6);
3605 assert(sysTime == SysTime(Date(1999, 7, 6)));
3606 }
3607
3608 {
3609 auto sysTime = SysTime(Date(1999, 7, 6));
3610 sysTime.roll!"months"(27);
3611 assert(sysTime == SysTime(Date(1999, 10, 6)));
3612 sysTime.roll!"months"(-28);
3613 assert(sysTime == SysTime(Date(1999, 6, 6)));
3614 }
3615
3616 {
3617 auto sysTime = SysTime(Date(1999, 5, 31));
3618 sysTime.roll!"months"(1);
3619 assert(sysTime == SysTime(Date(1999, 7, 1)));
3620 }
3621
3622 {
3623 auto sysTime = SysTime(Date(1999, 5, 31));
3624 sysTime.roll!"months"(-1);
3625 assert(sysTime == SysTime(Date(1999, 5, 1)));
3626 }
3627
3628 {
3629 auto sysTime = SysTime(Date(1999, 2, 28));
3630 sysTime.roll!"months"(12);
3631 assert(sysTime == SysTime(Date(1999, 2, 28)));
3632 }
3633
3634 {
3635 auto sysTime = SysTime(Date(2000, 2, 29));
3636 sysTime.roll!"months"(12);
3637 assert(sysTime == SysTime(Date(2000, 2, 29)));
3638 }
3639
3640 {
3641 auto sysTime = SysTime(Date(1999, 7, 31));
3642 sysTime.roll!"months"(1);
3643 assert(sysTime == SysTime(Date(1999, 8, 31)));
3644 sysTime.roll!"months"(1);
3645 assert(sysTime == SysTime(Date(1999, 10, 1)));
3646 }
3647
3648 {
3649 auto sysTime = SysTime(Date(1998, 8, 31));
3650 sysTime.roll!"months"(13);
3651 assert(sysTime == SysTime(Date(1998, 10, 1)));
3652 sysTime.roll!"months"(-13);
3653 assert(sysTime == SysTime(Date(1998, 9, 1)));
3654 }
3655
3656 {
3657 auto sysTime = SysTime(Date(1997, 12, 31));
3658 sysTime.roll!"months"(13);
3659 assert(sysTime == SysTime(Date(1997, 1, 31)));
3660 sysTime.roll!"months"(-13);
3661 assert(sysTime == SysTime(Date(1997, 12, 31)));
3662 }
3663
3664 {
3665 auto sysTime = SysTime(Date(1997, 12, 31));
3666 sysTime.roll!"months"(14);
3667 assert(sysTime == SysTime(Date(1997, 3, 3)));
3668 sysTime.roll!"months"(-14);
3669 assert(sysTime == SysTime(Date(1997, 1, 3)));
3670 }
3671
3672 {
3673 auto sysTime = SysTime(Date(1998, 12, 31));
3674 sysTime.roll!"months"(14);
3675 assert(sysTime == SysTime(Date(1998, 3, 3)));
3676 sysTime.roll!"months"(-14);
3677 assert(sysTime == SysTime(Date(1998, 1, 3)));
3678 }
3679
3680 {
3681 auto sysTime = SysTime(Date(1999, 12, 31));
3682 sysTime.roll!"months"(14);
3683 assert(sysTime == SysTime(Date(1999, 3, 3)));
3684 sysTime.roll!"months"(-14);
3685 assert(sysTime == SysTime(Date(1999, 1, 3)));
3686 }
3687
3688 {
3689 auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), usecs(5007));
3690 sysTime.roll!"months"(3);
3691 assert(sysTime == SysTime(DateTime(1999, 10, 6, 12, 2, 7), usecs(5007)));
3692 sysTime.roll!"months"(-4);
3693 assert(sysTime == SysTime(DateTime(1999, 6, 6, 12, 2, 7), usecs(5007)));
3694 }
3695
3696 {
3697 auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), hnsecs(422202));
3698 sysTime.roll!"months"(14);
3699 assert(sysTime == SysTime(DateTime(1998, 3, 3, 7, 7, 7), hnsecs(422202)));
3700 sysTime.roll!"months"(-14);
3701 assert(sysTime == SysTime(DateTime(1998, 1, 3, 7, 7, 7), hnsecs(422202)));
3702 }
3703
3704 {
3705 auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), hnsecs(422202));
3706 sysTime.roll!"months"(14);
3707 assert(sysTime == SysTime(DateTime(1999, 3, 3, 7, 7, 7), hnsecs(422202)));
3708 sysTime.roll!"months"(-14);
3709 assert(sysTime == SysTime(DateTime(1999, 1, 3, 7, 7, 7), hnsecs(422202)));
3710 }
3711
3712 // Test B.C.
3713 {
3714 auto sysTime = SysTime(Date(-1999, 7, 6));
3715 sysTime.roll!"months"(3);
3716 assert(sysTime == SysTime(Date(-1999, 10, 6)));
3717 sysTime.roll!"months"(-4);
3718 assert(sysTime == SysTime(Date(-1999, 6, 6)));
3719 }
3720
3721 {
3722 auto sysTime = SysTime(Date(-1999, 7, 6));
3723 sysTime.roll!"months"(6);
3724 assert(sysTime == SysTime(Date(-1999, 1, 6)));
3725 sysTime.roll!"months"(-6);
3726 assert(sysTime == SysTime(Date(-1999, 7, 6)));
3727 }
3728
3729 {
3730 auto sysTime = SysTime(Date(-1999, 7, 6));
3731 sysTime.roll!"months"(-27);
3732 assert(sysTime == SysTime(Date(-1999, 4, 6)));
3733 sysTime.roll!"months"(28);
3734 assert(sysTime == SysTime(Date(-1999, 8, 6)));
3735 }
3736
3737 {
3738 auto sysTime = SysTime(Date(-1999, 5, 31));
3739 sysTime.roll!"months"(1);
3740 assert(sysTime == SysTime(Date(-1999, 7, 1)));
3741 }
3742
3743 {
3744 auto sysTime = SysTime(Date(-1999, 5, 31));
3745 sysTime.roll!"months"(-1);
3746 assert(sysTime == SysTime(Date(-1999, 5, 1)));
3747 }
3748
3749 {
3750 auto sysTime = SysTime(Date(-1999, 2, 28));
3751 sysTime.roll!"months"(-12);
3752 assert(sysTime == SysTime(Date(-1999, 2, 28)));
3753 }
3754
3755 {
3756 auto sysTime = SysTime(Date(-2000, 2, 29));
3757 sysTime.roll!"months"(-12);
3758 assert(sysTime == SysTime(Date(-2000, 2, 29)));
3759 }
3760
3761 {
3762 auto sysTime = SysTime(Date(-1999, 7, 31));
3763 sysTime.roll!"months"(1);
3764 assert(sysTime == SysTime(Date(-1999, 8, 31)));
3765 sysTime.roll!"months"(1);
3766 assert(sysTime == SysTime(Date(-1999, 10, 1)));
3767 }
3768
3769 {
3770 auto sysTime = SysTime(Date(-1998, 8, 31));
3771 sysTime.roll!"months"(13);
3772 assert(sysTime == SysTime(Date(-1998, 10, 1)));
3773 sysTime.roll!"months"(-13);
3774 assert(sysTime == SysTime(Date(-1998, 9, 1)));
3775 }
3776
3777 {
3778 auto sysTime = SysTime(Date(-1997, 12, 31));
3779 sysTime.roll!"months"(13);
3780 assert(sysTime == SysTime(Date(-1997, 1, 31)));
3781 sysTime.roll!"months"(-13);
3782 assert(sysTime == SysTime(Date(-1997, 12, 31)));
3783 }
3784
3785 {
3786 auto sysTime = SysTime(Date(-1997, 12, 31));
3787 sysTime.roll!"months"(14);
3788 assert(sysTime == SysTime(Date(-1997, 3, 3)));
3789 sysTime.roll!"months"(-14);
3790 assert(sysTime == SysTime(Date(-1997, 1, 3)));
3791 }
3792
3793 {
3794 auto sysTime = SysTime(Date(-2002, 12, 31));
3795 sysTime.roll!"months"(14);
3796 assert(sysTime == SysTime(Date(-2002, 3, 3)));
3797 sysTime.roll!"months"(-14);
3798 assert(sysTime == SysTime(Date(-2002, 1, 3)));
3799 }
3800
3801 {
3802 auto sysTime = SysTime(Date(-2001, 12, 31));
3803 sysTime.roll!"months"(14);
3804 assert(sysTime == SysTime(Date(-2001, 3, 3)));
3805 sysTime.roll!"months"(-14);
3806 assert(sysTime == SysTime(Date(-2001, 1, 3)));
3807 }
3808
3809 {
3810 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
3811 sysTime.roll!"months"(-1);
3812 assert(sysTime == SysTime(DateTime(1, 12, 1, 0, 0, 0)));
3813 sysTime.roll!"months"(1);
3814 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
3815 }
3816
3817 {
3818 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
3819 sysTime.roll!"months"(-1);
3820 assert(sysTime == SysTime(DateTime(1, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
3821 sysTime.roll!"months"(1);
3822 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3823 }
3824
3825 {
3826 auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0));
3827 sysTime.roll!"months"(1);
3828 assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0)));
3829 sysTime.roll!"months"(-1);
3830 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
3831 }
3832
3833 {
3834 auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999));
3835 sysTime.roll!"months"(1);
3836 assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3837 sysTime.roll!"months"(-1);
3838 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
3839 }
3840
3841 {
3842 auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), hnsecs(5007));
3843 sysTime.roll!"months"(3);
3844 assert(sysTime == SysTime(DateTime(-1999, 10, 6, 12, 2, 7), hnsecs(5007)));
3845 sysTime.roll!"months"(-4);
3846 assert(sysTime == SysTime(DateTime(-1999, 6, 6, 12, 2, 7), hnsecs(5007)));
3847 }
3848
3849 {
3850 auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), hnsecs(422202));
3851 sysTime.roll!"months"(14);
3852 assert(sysTime == SysTime(DateTime(-2002, 3, 3, 7, 7, 7), hnsecs(422202)));
3853 sysTime.roll!"months"(-14);
3854 assert(sysTime == SysTime(DateTime(-2002, 1, 3, 7, 7, 7), hnsecs(422202)));
3855 }
3856
3857 {
3858 auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), hnsecs(422202));
3859 sysTime.roll!"months"(14);
3860 assert(sysTime == SysTime(DateTime(-2001, 3, 3, 7, 7, 7), hnsecs(422202)));
3861 sysTime.roll!"months"(-14);
3862 assert(sysTime == SysTime(DateTime(-2001, 1, 3, 7, 7, 7), hnsecs(422202)));
3863 }
3864
3865 // Test Both
3866 {
3867 auto sysTime = SysTime(Date(1, 1, 1));
3868 sysTime.roll!"months"(-1);
3869 assert(sysTime == SysTime(Date(1, 12, 1)));
3870 sysTime.roll!"months"(1);
3871 assert(sysTime == SysTime(Date(1, 1, 1)));
3872 }
3873
3874 {
3875 auto sysTime = SysTime(Date(4, 1, 1));
3876 sysTime.roll!"months"(-48);
3877 assert(sysTime == SysTime(Date(4, 1, 1)));
3878 sysTime.roll!"months"(48);
3879 assert(sysTime == SysTime(Date(4, 1, 1)));
3880 }
3881
3882 {
3883 auto sysTime = SysTime(Date(4, 3, 31));
3884 sysTime.roll!"months"(-49);
3885 assert(sysTime == SysTime(Date(4, 3, 2)));
3886 sysTime.roll!"months"(49);
3887 assert(sysTime == SysTime(Date(4, 4, 2)));
3888 }
3889
3890 {
3891 auto sysTime = SysTime(Date(4, 3, 31));
3892 sysTime.roll!"months"(-85);
3893 assert(sysTime == SysTime(Date(4, 3, 2)));
3894 sysTime.roll!"months"(85);
3895 assert(sysTime == SysTime(Date(4, 4, 2)));
3896 }
3897
3898 {
3899 auto sysTime = SysTime(Date(-1, 1, 1));
3900 sysTime.roll!"months"(-1);
3901 assert(sysTime == SysTime(Date(-1, 12, 1)));
3902 sysTime.roll!"months"(1);
3903 assert(sysTime == SysTime(Date(-1, 1, 1)));
3904 }
3905
3906 {
3907 auto sysTime = SysTime(Date(-4, 1, 1));
3908 sysTime.roll!"months"(-48);
3909 assert(sysTime == SysTime(Date(-4, 1, 1)));
3910 sysTime.roll!"months"(48);
3911 assert(sysTime == SysTime(Date(-4, 1, 1)));
3912 }
3913
3914 {
3915 auto sysTime = SysTime(Date(-4, 3, 31));
3916 sysTime.roll!"months"(-49);
3917 assert(sysTime == SysTime(Date(-4, 3, 2)));
3918 sysTime.roll!"months"(49);
3919 assert(sysTime == SysTime(Date(-4, 4, 2)));
3920 }
3921
3922 {
3923 auto sysTime = SysTime(Date(-4, 3, 31));
3924 sysTime.roll!"months"(-85);
3925 assert(sysTime == SysTime(Date(-4, 3, 2)));
3926 sysTime.roll!"months"(85);
3927 assert(sysTime == SysTime(Date(-4, 4, 2)));
3928 }
3929
3930 {
3931 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17));
3932 sysTime.roll!"months"(-1);
3933 assert(sysTime == SysTime(DateTime(1, 12, 1, 0, 7, 9), hnsecs(17)));
3934 sysTime.roll!"months"(1);
3935 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17)));
3936 }
3937
3938 {
3939 auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), msecs(9));
3940 sysTime.roll!"months"(-85);
3941 assert(sysTime == SysTime(DateTime(4, 3, 2, 12, 11, 10), msecs(9)));
3942 sysTime.roll!"months"(85);
3943 assert(sysTime == SysTime(DateTime(4, 4, 2, 12, 11, 10), msecs(9)));
3944 }
3945
3946 {
3947 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
3948 sysTime.roll!"months"(85);
3949 assert(sysTime == SysTime(DateTime(-3, 5, 1, 12, 11, 10), msecs(9)));
3950 sysTime.roll!"months"(-85);
3951 assert(sysTime == SysTime(DateTime(-3, 4, 1, 12, 11, 10), msecs(9)));
3952 }
3953
3954 {
3955 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
3956 sysTime.roll!"months"(85).roll!"months"(-83);
3957 assert(sysTime == SysTime(DateTime(-3, 6, 1, 12, 11, 10), msecs(9)));
3958 }
3959
3960 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
3961 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
3962 static assert(!__traits(compiles, cst.roll!"months"(4)));
3963 //static assert(!__traits(compiles, ist.roll!"months"(4)));
3964 }
3965
3966 // Test roll!"months"() with AllowDayOverflow.no
3967 @safe unittest
3968 {
3969 // Test A.D.
3970 {
3971 auto sysTime = SysTime(Date(1999, 7, 6));
3972 sysTime.roll!"months"(3, AllowDayOverflow.no);
3973 assert(sysTime == SysTime(Date(1999, 10, 6)));
3974 sysTime.roll!"months"(-4, AllowDayOverflow.no);
3975 assert(sysTime == SysTime(Date(1999, 6, 6)));
3976 }
3977
3978 {
3979 auto sysTime = SysTime(Date(1999, 7, 6));
3980 sysTime.roll!"months"(6, AllowDayOverflow.no);
3981 assert(sysTime == SysTime(Date(1999, 1, 6)));
3982 sysTime.roll!"months"(-6, AllowDayOverflow.no);
3983 assert(sysTime == SysTime(Date(1999, 7, 6)));
3984 }
3985
3986 {
3987 auto sysTime = SysTime(Date(1999, 7, 6));
3988 sysTime.roll!"months"(27, AllowDayOverflow.no);
3989 assert(sysTime == SysTime(Date(1999, 10, 6)));
3990 sysTime.roll!"months"(-28, AllowDayOverflow.no);
3991 assert(sysTime == SysTime(Date(1999, 6, 6)));
3992 }
3993
3994 {
3995 auto sysTime = SysTime(Date(1999, 5, 31));
3996 sysTime.roll!"months"(1, AllowDayOverflow.no);
3997 assert(sysTime == SysTime(Date(1999, 6, 30)));
3998 }
3999
4000 {
4001 auto sysTime = SysTime(Date(1999, 5, 31));
4002 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4003 assert(sysTime == SysTime(Date(1999, 4, 30)));
4004 }
4005
4006 {
4007 auto sysTime = SysTime(Date(1999, 2, 28));
4008 sysTime.roll!"months"(12, AllowDayOverflow.no);
4009 assert(sysTime == SysTime(Date(1999, 2, 28)));
4010 }
4011
4012 {
4013 auto sysTime = SysTime(Date(2000, 2, 29));
4014 sysTime.roll!"months"(12, AllowDayOverflow.no);
4015 assert(sysTime == SysTime(Date(2000, 2, 29)));
4016 }
4017
4018 {
4019 auto sysTime = SysTime(Date(1999, 7, 31));
4020 sysTime.roll!"months"(1, AllowDayOverflow.no);
4021 assert(sysTime == SysTime(Date(1999, 8, 31)));
4022 sysTime.roll!"months"(1, AllowDayOverflow.no);
4023 assert(sysTime == SysTime(Date(1999, 9, 30)));
4024 }
4025
4026 {
4027 auto sysTime = SysTime(Date(1998, 8, 31));
4028 sysTime.roll!"months"(13, AllowDayOverflow.no);
4029 assert(sysTime == SysTime(Date(1998, 9, 30)));
4030 sysTime.roll!"months"(-13, AllowDayOverflow.no);
4031 assert(sysTime == SysTime(Date(1998, 8, 30)));
4032 }
4033
4034 {
4035 auto sysTime = SysTime(Date(1997, 12, 31));
4036 sysTime.roll!"months"(13, AllowDayOverflow.no);
4037 assert(sysTime == SysTime(Date(1997, 1, 31)));
4038 sysTime.roll!"months"(-13, AllowDayOverflow.no);
4039 assert(sysTime == SysTime(Date(1997, 12, 31)));
4040 }
4041
4042 {
4043 auto sysTime = SysTime(Date(1997, 12, 31));
4044 sysTime.roll!"months"(14, AllowDayOverflow.no);
4045 assert(sysTime == SysTime(Date(1997, 2, 28)));
4046 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4047 assert(sysTime == SysTime(Date(1997, 12, 28)));
4048 }
4049
4050 {
4051 auto sysTime = SysTime(Date(1998, 12, 31));
4052 sysTime.roll!"months"(14, AllowDayOverflow.no);
4053 assert(sysTime == SysTime(Date(1998, 2, 28)));
4054 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4055 assert(sysTime == SysTime(Date(1998, 12, 28)));
4056 }
4057
4058 {
4059 auto sysTime = SysTime(Date(1999, 12, 31));
4060 sysTime.roll!"months"(14, AllowDayOverflow.no);
4061 assert(sysTime == SysTime(Date(1999, 2, 28)));
4062 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4063 assert(sysTime == SysTime(Date(1999, 12, 28)));
4064 }
4065
4066 {
4067 auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), usecs(5007));
4068 sysTime.roll!"months"(3, AllowDayOverflow.no);
4069 assert(sysTime == SysTime(DateTime(1999, 10, 6, 12, 2, 7), usecs(5007)));
4070 sysTime.roll!"months"(-4, AllowDayOverflow.no);
4071 assert(sysTime == SysTime(DateTime(1999, 6, 6, 12, 2, 7), usecs(5007)));
4072 }
4073
4074 {
4075 auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), hnsecs(422202));
4076 sysTime.roll!"months"(14, AllowDayOverflow.no);
4077 assert(sysTime == SysTime(DateTime(1998, 2, 28, 7, 7, 7), hnsecs(422202)));
4078 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4079 assert(sysTime == SysTime(DateTime(1998, 12, 28, 7, 7, 7), hnsecs(422202)));
4080 }
4081
4082 {
4083 auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), hnsecs(422202));
4084 sysTime.roll!"months"(14, AllowDayOverflow.no);
4085 assert(sysTime == SysTime(DateTime(1999, 2, 28, 7, 7, 7), hnsecs(422202)));
4086 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4087 assert(sysTime == SysTime(DateTime(1999, 12, 28, 7, 7, 7), hnsecs(422202)));
4088 }
4089
4090 // Test B.C.
4091 {
4092 auto sysTime = SysTime(Date(-1999, 7, 6));
4093 sysTime.roll!"months"(3, AllowDayOverflow.no);
4094 assert(sysTime == SysTime(Date(-1999, 10, 6)));
4095 sysTime.roll!"months"(-4, AllowDayOverflow.no);
4096 assert(sysTime == SysTime(Date(-1999, 6, 6)));
4097 }
4098
4099 {
4100 auto sysTime = SysTime(Date(-1999, 7, 6));
4101 sysTime.roll!"months"(6, AllowDayOverflow.no);
4102 assert(sysTime == SysTime(Date(-1999, 1, 6)));
4103 sysTime.roll!"months"(-6, AllowDayOverflow.no);
4104 assert(sysTime == SysTime(Date(-1999, 7, 6)));
4105 }
4106
4107 {
4108 auto sysTime = SysTime(Date(-1999, 7, 6));
4109 sysTime.roll!"months"(-27, AllowDayOverflow.no);
4110 assert(sysTime == SysTime(Date(-1999, 4, 6)));
4111 sysTime.roll!"months"(28, AllowDayOverflow.no);
4112 assert(sysTime == SysTime(Date(-1999, 8, 6)));
4113 }
4114
4115 {
4116 auto sysTime = SysTime(Date(-1999, 5, 31));
4117 sysTime.roll!"months"(1, AllowDayOverflow.no);
4118 assert(sysTime == SysTime(Date(-1999, 6, 30)));
4119 }
4120
4121 {
4122 auto sysTime = SysTime(Date(-1999, 5, 31));
4123 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4124 assert(sysTime == SysTime(Date(-1999, 4, 30)));
4125 }
4126
4127 {
4128 auto sysTime = SysTime(Date(-1999, 2, 28));
4129 sysTime.roll!"months"(-12, AllowDayOverflow.no);
4130 assert(sysTime == SysTime(Date(-1999, 2, 28)));
4131 }
4132
4133 {
4134 auto sysTime = SysTime(Date(-2000, 2, 29));
4135 sysTime.roll!"months"(-12, AllowDayOverflow.no);
4136 assert(sysTime == SysTime(Date(-2000, 2, 29)));
4137 }
4138
4139 {
4140 auto sysTime = SysTime(Date(-1999, 7, 31));
4141 sysTime.roll!"months"(1, AllowDayOverflow.no);
4142 assert(sysTime == SysTime(Date(-1999, 8, 31)));
4143 sysTime.roll!"months"(1, AllowDayOverflow.no);
4144 assert(sysTime == SysTime(Date(-1999, 9, 30)));
4145 }
4146
4147 {
4148 auto sysTime = SysTime(Date(-1998, 8, 31));
4149 sysTime.roll!"months"(13, AllowDayOverflow.no);
4150 assert(sysTime == SysTime(Date(-1998, 9, 30)));
4151 sysTime.roll!"months"(-13, AllowDayOverflow.no);
4152 assert(sysTime == SysTime(Date(-1998, 8, 30)));
4153 }
4154
4155 {
4156 auto sysTime = SysTime(Date(-1997, 12, 31));
4157 sysTime.roll!"months"(13, AllowDayOverflow.no);
4158 assert(sysTime == SysTime(Date(-1997, 1, 31)));
4159 sysTime.roll!"months"(-13, AllowDayOverflow.no);
4160 assert(sysTime == SysTime(Date(-1997, 12, 31)));
4161 }
4162
4163 {
4164 auto sysTime = SysTime(Date(-1997, 12, 31));
4165 sysTime.roll!"months"(14, AllowDayOverflow.no);
4166 assert(sysTime == SysTime(Date(-1997, 2, 28)));
4167 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4168 assert(sysTime == SysTime(Date(-1997, 12, 28)));
4169 }
4170
4171 {
4172 auto sysTime = SysTime(Date(-2002, 12, 31));
4173 sysTime.roll!"months"(14, AllowDayOverflow.no);
4174 assert(sysTime == SysTime(Date(-2002, 2, 28)));
4175 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4176 assert(sysTime == SysTime(Date(-2002, 12, 28)));
4177 }
4178
4179 {
4180 auto sysTime = SysTime(Date(-2001, 12, 31));
4181 sysTime.roll!"months"(14, AllowDayOverflow.no);
4182 assert(sysTime == SysTime(Date(-2001, 2, 28)));
4183 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4184 assert(sysTime == SysTime(Date(-2001, 12, 28)));
4185 }
4186
4187 {
4188 auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), usecs(5007));
4189 sysTime.roll!"months"(3, AllowDayOverflow.no);
4190 assert(sysTime == SysTime(DateTime(-1999, 10, 6, 12, 2, 7), usecs(5007)));
4191 sysTime.roll!"months"(-4, AllowDayOverflow.no);
4192 assert(sysTime == SysTime(DateTime(-1999, 6, 6, 12, 2, 7), usecs(5007)));
4193 }
4194
4195 {
4196 auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), hnsecs(422202));
4197 sysTime.roll!"months"(14, AllowDayOverflow.no);
4198 assert(sysTime == SysTime(DateTime(-2002, 2, 28, 7, 7, 7), hnsecs(422202)));
4199 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4200 assert(sysTime == SysTime(DateTime(-2002, 12, 28, 7, 7, 7), hnsecs(422202)));
4201 }
4202
4203 {
4204 auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), hnsecs(422202));
4205 sysTime.roll!"months"(14, AllowDayOverflow.no);
4206 assert(sysTime == SysTime(DateTime(-2001, 2, 28, 7, 7, 7), hnsecs(422202)));
4207 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4208 assert(sysTime == SysTime(DateTime(-2001, 12, 28, 7, 7, 7), hnsecs(422202)));
4209 }
4210
4211 // Test Both
4212 {
4213 auto sysTime = SysTime(Date(1, 1, 1));
4214 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4215 assert(sysTime == SysTime(Date(1, 12, 1)));
4216 sysTime.roll!"months"(1, AllowDayOverflow.no);
4217 assert(sysTime == SysTime(Date(1, 1, 1)));
4218 }
4219
4220 {
4221 auto sysTime = SysTime(Date(4, 1, 1));
4222 sysTime.roll!"months"(-48, AllowDayOverflow.no);
4223 assert(sysTime == SysTime(Date(4, 1, 1)));
4224 sysTime.roll!"months"(48, AllowDayOverflow.no);
4225 assert(sysTime == SysTime(Date(4, 1, 1)));
4226 }
4227
4228 {
4229 auto sysTime = SysTime(Date(4, 3, 31));
4230 sysTime.roll!"months"(-49, AllowDayOverflow.no);
4231 assert(sysTime == SysTime(Date(4, 2, 29)));
4232 sysTime.roll!"months"(49, AllowDayOverflow.no);
4233 assert(sysTime == SysTime(Date(4, 3, 29)));
4234 }
4235
4236 {
4237 auto sysTime = SysTime(Date(4, 3, 31));
4238 sysTime.roll!"months"(-85, AllowDayOverflow.no);
4239 assert(sysTime == SysTime(Date(4, 2, 29)));
4240 sysTime.roll!"months"(85, AllowDayOverflow.no);
4241 assert(sysTime == SysTime(Date(4, 3, 29)));
4242 }
4243
4244 {
4245 auto sysTime = SysTime(Date(-1, 1, 1));
4246 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4247 assert(sysTime == SysTime(Date(-1, 12, 1)));
4248 sysTime.roll!"months"(1, AllowDayOverflow.no);
4249 assert(sysTime == SysTime(Date(-1, 1, 1)));
4250 }
4251
4252 {
4253 auto sysTime = SysTime(Date(-4, 1, 1));
4254 sysTime.roll!"months"(-48, AllowDayOverflow.no);
4255 assert(sysTime == SysTime(Date(-4, 1, 1)));
4256 sysTime.roll!"months"(48, AllowDayOverflow.no);
4257 assert(sysTime == SysTime(Date(-4, 1, 1)));
4258 }
4259
4260 {
4261 auto sysTime = SysTime(Date(-4, 3, 31));
4262 sysTime.roll!"months"(-49, AllowDayOverflow.no);
4263 assert(sysTime == SysTime(Date(-4, 2, 29)));
4264 sysTime.roll!"months"(49, AllowDayOverflow.no);
4265 assert(sysTime == SysTime(Date(-4, 3, 29)));
4266 }
4267
4268 {
4269 auto sysTime = SysTime(Date(-4, 3, 31));
4270 sysTime.roll!"months"(-85, AllowDayOverflow.no);
4271 assert(sysTime == SysTime(Date(-4, 2, 29)));
4272 sysTime.roll!"months"(85, AllowDayOverflow.no);
4273 assert(sysTime == SysTime(Date(-4, 3, 29)));
4274 }
4275
4276 {
4277 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
4278 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4279 assert(sysTime == SysTime(DateTime(1, 12, 1, 0, 0, 0)));
4280 sysTime.roll!"months"(1, AllowDayOverflow.no);
4281 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
4282 }
4283
4284 {
4285 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
4286 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4287 assert(sysTime == SysTime(DateTime(1, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
4288 sysTime.roll!"months"(1, AllowDayOverflow.no);
4289 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
4290 }
4291
4292 {
4293 auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0));
4294 sysTime.roll!"months"(1, AllowDayOverflow.no);
4295 assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0)));
4296 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4297 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
4298 }
4299
4300 {
4301 auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999));
4302 sysTime.roll!"months"(1, AllowDayOverflow.no);
4303 assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
4304 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4305 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
4306 }
4307
4308 {
4309 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17));
4310 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4311 assert(sysTime == SysTime(DateTime(1, 12, 1, 0, 7, 9), hnsecs(17)));
4312 sysTime.roll!"months"(1, AllowDayOverflow.no);
4313 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17)));
4314 }
4315
4316 {
4317 auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), msecs(9));
4318 sysTime.roll!"months"(-85, AllowDayOverflow.no);
4319 assert(sysTime == SysTime(DateTime(4, 2, 29, 12, 11, 10), msecs(9)));
4320 sysTime.roll!"months"(85, AllowDayOverflow.no);
4321 assert(sysTime == SysTime(DateTime(4, 3, 29, 12, 11, 10), msecs(9)));
4322 }
4323
4324 {
4325 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
4326 sysTime.roll!"months"(85, AllowDayOverflow.no);
4327 assert(sysTime == SysTime(DateTime(-3, 4, 30, 12, 11, 10), msecs(9)));
4328 sysTime.roll!"months"(-85, AllowDayOverflow.no);
4329 assert(sysTime == SysTime(DateTime(-3, 3, 30, 12, 11, 10), msecs(9)));
4330 }
4331
4332 {
4333 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
4334 sysTime.roll!"months"(85, AllowDayOverflow.no).roll!"months"(-83, AllowDayOverflow.no);
4335 assert(sysTime == SysTime(DateTime(-3, 5, 30, 12, 11, 10), msecs(9)));
4336 }
4337 }
4338
4339
4340 /++
4341 Adds the given number of units to this $(LREF SysTime). A negative number
4342 will subtract.
4343
4344 The difference between rolling and adding is that rolling does not
4345 affect larger units. For instance, rolling a $(LREF SysTime) one
4346 year's worth of days gets the exact same $(LREF SysTime).
4347
4348 Accepted units are $(D "days"), $(D "minutes"), $(D "hours"),
4349 $(D "minutes"), $(D "seconds"), $(D "msecs"), $(D "usecs"), and
4350 $(D "hnsecs").
4351
4352 Note that when rolling msecs, usecs or hnsecs, they all add up to a
4353 second. So, for example, rolling 1000 msecs is exactly the same as
4354 rolling 100,000 usecs.
4355
4356 Params:
4357 units = The units to add.
4358 value = The number of $(D_PARAM units) to add to this
4359 $(LREF SysTime).
4360 +/
4361 ref SysTime roll(string units)(long value) @safe nothrow
4362 if (units == "days")
4363 {
4364 auto hnsecs = adjTime;
4365 auto gdays = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
4366
4367 if (hnsecs < 0)
4368 {
4369 hnsecs += convert!("hours", "hnsecs")(24);
4370 --gdays;
4371 }
4372
4373 auto date = Date(cast(int) gdays);
4374 date.roll!"days"(value);
4375 gdays = date.dayOfGregorianCal - 1;
4376
4377 if (gdays < 0)
4378 {
4379 hnsecs -= convert!("hours", "hnsecs")(24);
4380 ++gdays;
4381 }
4382
4383 immutable newDaysHNSecs = convert!("days", "hnsecs")(gdays);
4384 adjTime = newDaysHNSecs + hnsecs;
4385 return this;
4386 }
4387
4388 ///
4389 @safe unittest
4390 {
4391 import core.time : msecs, hnsecs;
4392 import std.datetime.date : DateTime;
4393
4394 auto st1 = SysTime(DateTime(2010, 1, 1, 11, 23, 12));
4395 st1.roll!"days"(1);
4396 assert(st1 == SysTime(DateTime(2010, 1, 2, 11, 23, 12)));
4397 st1.roll!"days"(365);
4398 assert(st1 == SysTime(DateTime(2010, 1, 26, 11, 23, 12)));
4399 st1.roll!"days"(-32);
4400 assert(st1 == SysTime(DateTime(2010, 1, 25, 11, 23, 12)));
4401
4402 auto st2 = SysTime(DateTime(2010, 7, 4, 12, 0, 0));
4403 st2.roll!"hours"(1);
4404 assert(st2 == SysTime(DateTime(2010, 7, 4, 13, 0, 0)));
4405
4406 auto st3 = SysTime(DateTime(2010, 2, 12, 12, 0, 0));
4407 st3.roll!"hours"(-1);
4408 assert(st3 == SysTime(DateTime(2010, 2, 12, 11, 0, 0)));
4409
4410 auto st4 = SysTime(DateTime(2009, 12, 31, 0, 0, 0));
4411 st4.roll!"minutes"(1);
4412 assert(st4 == SysTime(DateTime(2009, 12, 31, 0, 1, 0)));
4413
4414 auto st5 = SysTime(DateTime(2010, 1, 1, 0, 0, 0));
4415 st5.roll!"minutes"(-1);
4416 assert(st5 == SysTime(DateTime(2010, 1, 1, 0, 59, 0)));
4417
4418 auto st6 = SysTime(DateTime(2009, 12, 31, 0, 0, 0));
4419 st6.roll!"seconds"(1);
4420 assert(st6 == SysTime(DateTime(2009, 12, 31, 0, 0, 1)));
4421
4422 auto st7 = SysTime(DateTime(2010, 1, 1, 0, 0, 0));
4423 st7.roll!"seconds"(-1);
4424 assert(st7 == SysTime(DateTime(2010, 1, 1, 0, 0, 59)));
4425
4426 auto dt = DateTime(2010, 1, 1, 0, 0, 0);
4427 auto st8 = SysTime(dt);
4428 st8.roll!"msecs"(1);
4429 assert(st8 == SysTime(dt, msecs(1)));
4430
4431 auto st9 = SysTime(dt);
4432 st9.roll!"msecs"(-1);
4433 assert(st9 == SysTime(dt, msecs(999)));
4434
4435 auto st10 = SysTime(dt);
4436 st10.roll!"hnsecs"(1);
4437 assert(st10 == SysTime(dt, hnsecs(1)));
4438
4439 auto st11 = SysTime(dt);
4440 st11.roll!"hnsecs"(-1);
4441 assert(st11 == SysTime(dt, hnsecs(9_999_999)));
4442 }
4443
4444 @safe unittest
4445 {
4446 // Test A.D.
4447 {
4448 auto sysTime = SysTime(Date(1999, 2, 28));
4449 sysTime.roll!"days"(1);
4450 assert(sysTime == SysTime(Date(1999, 2, 1)));
4451 sysTime.roll!"days"(-1);
4452 assert(sysTime == SysTime(Date(1999, 2, 28)));
4453 }
4454
4455 {
4456 auto sysTime = SysTime(Date(2000, 2, 28));
4457 sysTime.roll!"days"(1);
4458 assert(sysTime == SysTime(Date(2000, 2, 29)));
4459 sysTime.roll!"days"(1);
4460 assert(sysTime == SysTime(Date(2000, 2, 1)));
4461 sysTime.roll!"days"(-1);
4462 assert(sysTime == SysTime(Date(2000, 2, 29)));
4463 }
4464
4465 {
4466 auto sysTime = SysTime(Date(1999, 6, 30));
4467 sysTime.roll!"days"(1);
4468 assert(sysTime == SysTime(Date(1999, 6, 1)));
4469 sysTime.roll!"days"(-1);
4470 assert(sysTime == SysTime(Date(1999, 6, 30)));
4471 }
4472
4473 {
4474 auto sysTime = SysTime(Date(1999, 7, 31));
4475 sysTime.roll!"days"(1);
4476 assert(sysTime == SysTime(Date(1999, 7, 1)));
4477 sysTime.roll!"days"(-1);
4478 assert(sysTime == SysTime(Date(1999, 7, 31)));
4479 }
4480
4481 {
4482 auto sysTime = SysTime(Date(1999, 1, 1));
4483 sysTime.roll!"days"(-1);
4484 assert(sysTime == SysTime(Date(1999, 1, 31)));
4485 sysTime.roll!"days"(1);
4486 assert(sysTime == SysTime(Date(1999, 1, 1)));
4487 }
4488
4489 {
4490 auto sysTime = SysTime(Date(1999, 7, 6));
4491 sysTime.roll!"days"(9);
4492 assert(sysTime == SysTime(Date(1999, 7, 15)));
4493 sysTime.roll!"days"(-11);
4494 assert(sysTime == SysTime(Date(1999, 7, 4)));
4495 sysTime.roll!"days"(30);
4496 assert(sysTime == SysTime(Date(1999, 7, 3)));
4497 sysTime.roll!"days"(-3);
4498 assert(sysTime == SysTime(Date(1999, 7, 31)));
4499 }
4500
4501 {
4502 auto sysTime = SysTime(Date(1999, 7, 6));
4503 sysTime.roll!"days"(365);
4504 assert(sysTime == SysTime(Date(1999, 7, 30)));
4505 sysTime.roll!"days"(-365);
4506 assert(sysTime == SysTime(Date(1999, 7, 6)));
4507 sysTime.roll!"days"(366);
4508 assert(sysTime == SysTime(Date(1999, 7, 31)));
4509 sysTime.roll!"days"(730);
4510 assert(sysTime == SysTime(Date(1999, 7, 17)));
4511 sysTime.roll!"days"(-1096);
4512 assert(sysTime == SysTime(Date(1999, 7, 6)));
4513 }
4514
4515 {
4516 auto sysTime = SysTime(Date(1999, 2, 6));
4517 sysTime.roll!"days"(365);
4518 assert(sysTime == SysTime(Date(1999, 2, 7)));
4519 sysTime.roll!"days"(-365);
4520 assert(sysTime == SysTime(Date(1999, 2, 6)));
4521 sysTime.roll!"days"(366);
4522 assert(sysTime == SysTime(Date(1999, 2, 8)));
4523 sysTime.roll!"days"(730);
4524 assert(sysTime == SysTime(Date(1999, 2, 10)));
4525 sysTime.roll!"days"(-1096);
4526 assert(sysTime == SysTime(Date(1999, 2, 6)));
4527 }
4528
4529 {
4530 auto sysTime = SysTime(DateTime(1999, 2, 28, 7, 9, 2), usecs(234578));
4531 sysTime.roll!"days"(1);
4532 assert(sysTime == SysTime(DateTime(1999, 2, 1, 7, 9, 2), usecs(234578)));
4533 sysTime.roll!"days"(-1);
4534 assert(sysTime == SysTime(DateTime(1999, 2, 28, 7, 9, 2), usecs(234578)));
4535 }
4536
4537 {
4538 auto sysTime = SysTime(DateTime(1999, 7, 6, 7, 9, 2), usecs(234578));
4539 sysTime.roll!"days"(9);
4540 assert(sysTime == SysTime(DateTime(1999, 7, 15, 7, 9, 2), usecs(234578)));
4541 sysTime.roll!"days"(-11);
4542 assert(sysTime == SysTime(DateTime(1999, 7, 4, 7, 9, 2), usecs(234578)));
4543 sysTime.roll!"days"(30);
4544 assert(sysTime == SysTime(DateTime(1999, 7, 3, 7, 9, 2), usecs(234578)));
4545 sysTime.roll!"days"(-3);
4546 assert(sysTime == SysTime(DateTime(1999, 7, 31, 7, 9, 2), usecs(234578)));
4547 }
4548
4549 // Test B.C.
4550 {
4551 auto sysTime = SysTime(Date(-1999, 2, 28));
4552 sysTime.roll!"days"(1);
4553 assert(sysTime == SysTime(Date(-1999, 2, 1)));
4554 sysTime.roll!"days"(-1);
4555 assert(sysTime == SysTime(Date(-1999, 2, 28)));
4556 }
4557
4558 {
4559 auto sysTime = SysTime(Date(-2000, 2, 28));
4560 sysTime.roll!"days"(1);
4561 assert(sysTime == SysTime(Date(-2000, 2, 29)));
4562 sysTime.roll!"days"(1);
4563 assert(sysTime == SysTime(Date(-2000, 2, 1)));
4564 sysTime.roll!"days"(-1);
4565 assert(sysTime == SysTime(Date(-2000, 2, 29)));
4566 }
4567
4568 {
4569 auto sysTime = SysTime(Date(-1999, 6, 30));
4570 sysTime.roll!"days"(1);
4571 assert(sysTime == SysTime(Date(-1999, 6, 1)));
4572 sysTime.roll!"days"(-1);
4573 assert(sysTime == SysTime(Date(-1999, 6, 30)));
4574 }
4575
4576 {
4577 auto sysTime = SysTime(Date(-1999, 7, 31));
4578 sysTime.roll!"days"(1);
4579 assert(sysTime == SysTime(Date(-1999, 7, 1)));
4580 sysTime.roll!"days"(-1);
4581 assert(sysTime == SysTime(Date(-1999, 7, 31)));
4582 }
4583
4584 {
4585 auto sysTime = SysTime(Date(-1999, 1, 1));
4586 sysTime.roll!"days"(-1);
4587 assert(sysTime == SysTime(Date(-1999, 1, 31)));
4588 sysTime.roll!"days"(1);
4589 assert(sysTime == SysTime(Date(-1999, 1, 1)));
4590 }
4591
4592 {
4593 auto sysTime = SysTime(Date(-1999, 7, 6));
4594 sysTime.roll!"days"(9);
4595 assert(sysTime == SysTime(Date(-1999, 7, 15)));
4596 sysTime.roll!"days"(-11);
4597 assert(sysTime == SysTime(Date(-1999, 7, 4)));
4598 sysTime.roll!"days"(30);
4599 assert(sysTime == SysTime(Date(-1999, 7, 3)));
4600 sysTime.roll!"days"(-3);
4601 assert(sysTime == SysTime(Date(-1999, 7, 31)));
4602 }
4603
4604 {
4605 auto sysTime = SysTime(Date(-1999, 7, 6));
4606 sysTime.roll!"days"(365);
4607 assert(sysTime == SysTime(Date(-1999, 7, 30)));
4608 sysTime.roll!"days"(-365);
4609 assert(sysTime == SysTime(Date(-1999, 7, 6)));
4610 sysTime.roll!"days"(366);
4611 assert(sysTime == SysTime(Date(-1999, 7, 31)));
4612 sysTime.roll!"days"(730);
4613 assert(sysTime == SysTime(Date(-1999, 7, 17)));
4614 sysTime.roll!"days"(-1096);
4615 assert(sysTime == SysTime(Date(-1999, 7, 6)));
4616 }
4617
4618 {
4619 auto sysTime = SysTime(DateTime(-1999, 2, 28, 7, 9, 2), usecs(234578));
4620 sysTime.roll!"days"(1);
4621 assert(sysTime == SysTime(DateTime(-1999, 2, 1, 7, 9, 2), usecs(234578)));
4622 sysTime.roll!"days"(-1);
4623 assert(sysTime == SysTime(DateTime(-1999, 2, 28, 7, 9, 2), usecs(234578)));
4624 }
4625
4626 {
4627 auto sysTime = SysTime(DateTime(-1999, 7, 6, 7, 9, 2), usecs(234578));
4628 sysTime.roll!"days"(9);
4629 assert(sysTime == SysTime(DateTime(-1999, 7, 15, 7, 9, 2), usecs(234578)));
4630 sysTime.roll!"days"(-11);
4631 assert(sysTime == SysTime(DateTime(-1999, 7, 4, 7, 9, 2), usecs(234578)));
4632 sysTime.roll!"days"(30);
4633 assert(sysTime == SysTime(DateTime(-1999, 7, 3, 7, 9, 2), usecs(234578)));
4634 sysTime.roll!"days"(-3);
4635 }
4636
4637 // Test Both
4638 {
4639 auto sysTime = SysTime(Date(1, 7, 6));
4640 sysTime.roll!"days"(-365);
4641 assert(sysTime == SysTime(Date(1, 7, 13)));
4642 sysTime.roll!"days"(365);
4643 assert(sysTime == SysTime(Date(1, 7, 6)));
4644 sysTime.roll!"days"(-731);
4645 assert(sysTime == SysTime(Date(1, 7, 19)));
4646 sysTime.roll!"days"(730);
4647 assert(sysTime == SysTime(Date(1, 7, 5)));
4648 }
4649
4650 {
4651 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
4652 sysTime.roll!"days"(-1);
4653 assert(sysTime == SysTime(DateTime(1, 1, 31, 0, 0, 0)));
4654 sysTime.roll!"days"(1);
4655 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
4656 }
4657
4658 {
4659 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
4660 sysTime.roll!"days"(-1);
4661 assert(sysTime == SysTime(DateTime(1, 1, 31, 23, 59, 59), hnsecs(9_999_999)));
4662 sysTime.roll!"days"(1);
4663 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
4664 }
4665
4666 {
4667 auto sysTime = SysTime(DateTime(0, 12, 31, 0, 0, 0));
4668 sysTime.roll!"days"(1);
4669 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
4670 sysTime.roll!"days"(-1);
4671 assert(sysTime == SysTime(DateTime(0, 12, 31, 0, 0, 0)));
4672 }
4673
4674 {
4675 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
4676 sysTime.roll!"days"(1);
4677 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
4678 sysTime.roll!"days"(-1);
4679 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
4680 }
4681
4682 {
4683 auto sysTime = SysTime(DateTime(1, 7, 6, 13, 13, 9), msecs(22));
4684 sysTime.roll!"days"(-365);
4685 assert(sysTime == SysTime(DateTime(1, 7, 13, 13, 13, 9), msecs(22)));
4686 sysTime.roll!"days"(365);
4687 assert(sysTime == SysTime(DateTime(1, 7, 6, 13, 13, 9), msecs(22)));
4688 sysTime.roll!"days"(-731);
4689 assert(sysTime == SysTime(DateTime(1, 7, 19, 13, 13, 9), msecs(22)));
4690 sysTime.roll!"days"(730);
4691 assert(sysTime == SysTime(DateTime(1, 7, 5, 13, 13, 9), msecs(22)));
4692 }
4693
4694 {
4695 auto sysTime = SysTime(DateTime(0, 7, 6, 13, 13, 9), msecs(22));
4696 sysTime.roll!"days"(-365);
4697 assert(sysTime == SysTime(DateTime(0, 7, 13, 13, 13, 9), msecs(22)));
4698 sysTime.roll!"days"(365);
4699 assert(sysTime == SysTime(DateTime(0, 7, 6, 13, 13, 9), msecs(22)));
4700 sysTime.roll!"days"(-731);
4701 assert(sysTime == SysTime(DateTime(0, 7, 19, 13, 13, 9), msecs(22)));
4702 sysTime.roll!"days"(730);
4703 assert(sysTime == SysTime(DateTime(0, 7, 5, 13, 13, 9), msecs(22)));
4704 }
4705
4706 {
4707 auto sysTime = SysTime(DateTime(0, 7, 6, 13, 13, 9), msecs(22));
4708 sysTime.roll!"days"(-365).roll!"days"(362).roll!"days"(-12).roll!"days"(730);
4709 assert(sysTime == SysTime(DateTime(0, 7, 8, 13, 13, 9), msecs(22)));
4710 }
4711
4712 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
4713 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
4714 static assert(!__traits(compiles, cst.roll!"days"(4)));
4715 //static assert(!__traits(compiles, ist.roll!"days"(4)));
4716 }
4717
4718
4719 // Shares documentation with "days" version.
4720 ref SysTime roll(string units)(long value) @safe nothrow
4721 if (units == "hours" || units == "minutes" || units == "seconds")
4722 {
4723 try
4724 {
4725 auto hnsecs = adjTime;
4726 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
4727
4728 if (hnsecs < 0)
4729 {
4730 hnsecs += convert!("hours", "hnsecs")(24);
4731 --days;
4732 }
4733
4734 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
4735 immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
4736 immutable second = splitUnitsFromHNSecs!"seconds"(hnsecs);
4737
4738 auto dateTime = DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour,
4739 cast(int) minute, cast(int) second));
4740 dateTime.roll!units(value);
4741 --days;
4742
4743 hnsecs += convert!("hours", "hnsecs")(dateTime.hour);
4744 hnsecs += convert!("minutes", "hnsecs")(dateTime.minute);
4745 hnsecs += convert!("seconds", "hnsecs")(dateTime.second);
4746
4747 if (days < 0)
4748 {
4749 hnsecs -= convert!("hours", "hnsecs")(24);
4750 ++days;
4751 }
4752
4753 immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
4754 adjTime = newDaysHNSecs + hnsecs;
4755 return this;
4756 }
4757 catch (Exception e)
4758 assert(0, "Either DateTime's constructor or TimeOfDay's constructor threw.");
4759 }
4760
4761 // Test roll!"hours"().
4762 @safe unittest
4763 {
4764 static void testST(SysTime orig, int hours, in SysTime expected, size_t line = __LINE__)
4765 {
4766 orig.roll!"hours"(hours);
4767 if (orig != expected)
4768 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
4769 }
4770
4771 // Test A.D.
4772 immutable d = msecs(45);
4773 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), d);
4774 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
4775 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 13, 30, 33), d));
4776 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 14, 30, 33), d));
4777 testST(beforeAD, 3, SysTime(DateTime(1999, 7, 6, 15, 30, 33), d));
4778 testST(beforeAD, 4, SysTime(DateTime(1999, 7, 6, 16, 30, 33), d));
4779 testST(beforeAD, 5, SysTime(DateTime(1999, 7, 6, 17, 30, 33), d));
4780 testST(beforeAD, 6, SysTime(DateTime(1999, 7, 6, 18, 30, 33), d));
4781 testST(beforeAD, 7, SysTime(DateTime(1999, 7, 6, 19, 30, 33), d));
4782 testST(beforeAD, 8, SysTime(DateTime(1999, 7, 6, 20, 30, 33), d));
4783 testST(beforeAD, 9, SysTime(DateTime(1999, 7, 6, 21, 30, 33), d));
4784 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 22, 30, 33), d));
4785 testST(beforeAD, 11, SysTime(DateTime(1999, 7, 6, 23, 30, 33), d));
4786 testST(beforeAD, 12, SysTime(DateTime(1999, 7, 6, 0, 30, 33), d));
4787 testST(beforeAD, 13, SysTime(DateTime(1999, 7, 6, 1, 30, 33), d));
4788 testST(beforeAD, 14, SysTime(DateTime(1999, 7, 6, 2, 30, 33), d));
4789 testST(beforeAD, 15, SysTime(DateTime(1999, 7, 6, 3, 30, 33), d));
4790 testST(beforeAD, 16, SysTime(DateTime(1999, 7, 6, 4, 30, 33), d));
4791 testST(beforeAD, 17, SysTime(DateTime(1999, 7, 6, 5, 30, 33), d));
4792 testST(beforeAD, 18, SysTime(DateTime(1999, 7, 6, 6, 30, 33), d));
4793 testST(beforeAD, 19, SysTime(DateTime(1999, 7, 6, 7, 30, 33), d));
4794 testST(beforeAD, 20, SysTime(DateTime(1999, 7, 6, 8, 30, 33), d));
4795 testST(beforeAD, 21, SysTime(DateTime(1999, 7, 6, 9, 30, 33), d));
4796 testST(beforeAD, 22, SysTime(DateTime(1999, 7, 6, 10, 30, 33), d));
4797 testST(beforeAD, 23, SysTime(DateTime(1999, 7, 6, 11, 30, 33), d));
4798 testST(beforeAD, 24, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
4799 testST(beforeAD, 25, SysTime(DateTime(1999, 7, 6, 13, 30, 33), d));
4800 testST(beforeAD, 50, SysTime(DateTime(1999, 7, 6, 14, 30, 33), d));
4801 testST(beforeAD, 10_000, SysTime(DateTime(1999, 7, 6, 4, 30, 33), d));
4802
4803 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 11, 30, 33), d));
4804 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 10, 30, 33), d));
4805 testST(beforeAD, -3, SysTime(DateTime(1999, 7, 6, 9, 30, 33), d));
4806 testST(beforeAD, -4, SysTime(DateTime(1999, 7, 6, 8, 30, 33), d));
4807 testST(beforeAD, -5, SysTime(DateTime(1999, 7, 6, 7, 30, 33), d));
4808 testST(beforeAD, -6, SysTime(DateTime(1999, 7, 6, 6, 30, 33), d));
4809 testST(beforeAD, -7, SysTime(DateTime(1999, 7, 6, 5, 30, 33), d));
4810 testST(beforeAD, -8, SysTime(DateTime(1999, 7, 6, 4, 30, 33), d));
4811 testST(beforeAD, -9, SysTime(DateTime(1999, 7, 6, 3, 30, 33), d));
4812 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 2, 30, 33), d));
4813 testST(beforeAD, -11, SysTime(DateTime(1999, 7, 6, 1, 30, 33), d));
4814 testST(beforeAD, -12, SysTime(DateTime(1999, 7, 6, 0, 30, 33), d));
4815 testST(beforeAD, -13, SysTime(DateTime(1999, 7, 6, 23, 30, 33), d));
4816 testST(beforeAD, -14, SysTime(DateTime(1999, 7, 6, 22, 30, 33), d));
4817 testST(beforeAD, -15, SysTime(DateTime(1999, 7, 6, 21, 30, 33), d));
4818 testST(beforeAD, -16, SysTime(DateTime(1999, 7, 6, 20, 30, 33), d));
4819 testST(beforeAD, -17, SysTime(DateTime(1999, 7, 6, 19, 30, 33), d));
4820 testST(beforeAD, -18, SysTime(DateTime(1999, 7, 6, 18, 30, 33), d));
4821 testST(beforeAD, -19, SysTime(DateTime(1999, 7, 6, 17, 30, 33), d));
4822 testST(beforeAD, -20, SysTime(DateTime(1999, 7, 6, 16, 30, 33), d));
4823 testST(beforeAD, -21, SysTime(DateTime(1999, 7, 6, 15, 30, 33), d));
4824 testST(beforeAD, -22, SysTime(DateTime(1999, 7, 6, 14, 30, 33), d));
4825 testST(beforeAD, -23, SysTime(DateTime(1999, 7, 6, 13, 30, 33), d));
4826 testST(beforeAD, -24, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
4827 testST(beforeAD, -25, SysTime(DateTime(1999, 7, 6, 11, 30, 33), d));
4828 testST(beforeAD, -50, SysTime(DateTime(1999, 7, 6, 10, 30, 33), d));
4829 testST(beforeAD, -10_000, SysTime(DateTime(1999, 7, 6, 20, 30, 33), d));
4830
4831 testST(SysTime(DateTime(1999, 7, 6, 0, 30, 33), d), 1, SysTime(DateTime(1999, 7, 6, 1, 30, 33), d));
4832 testST(SysTime(DateTime(1999, 7, 6, 0, 30, 33), d), 0, SysTime(DateTime(1999, 7, 6, 0, 30, 33), d));
4833 testST(SysTime(DateTime(1999, 7, 6, 0, 30, 33), d), -1, SysTime(DateTime(1999, 7, 6, 23, 30, 33), d));
4834
4835 testST(SysTime(DateTime(1999, 7, 6, 23, 30, 33), d), 1, SysTime(DateTime(1999, 7, 6, 0, 30, 33), d));
4836 testST(SysTime(DateTime(1999, 7, 6, 23, 30, 33), d), 0, SysTime(DateTime(1999, 7, 6, 23, 30, 33), d));
4837 testST(SysTime(DateTime(1999, 7, 6, 23, 30, 33), d), -1, SysTime(DateTime(1999, 7, 6, 22, 30, 33), d));
4838
4839 testST(SysTime(DateTime(1999, 7, 31, 23, 30, 33), d), 1, SysTime(DateTime(1999, 7, 31, 0, 30, 33), d));
4840 testST(SysTime(DateTime(1999, 8, 1, 0, 30, 33), d), -1, SysTime(DateTime(1999, 8, 1, 23, 30, 33), d));
4841
4842 testST(SysTime(DateTime(1999, 12, 31, 23, 30, 33), d), 1, SysTime(DateTime(1999, 12, 31, 0, 30, 33), d));
4843 testST(SysTime(DateTime(2000, 1, 1, 0, 30, 33), d), -1, SysTime(DateTime(2000, 1, 1, 23, 30, 33), d));
4844
4845 testST(SysTime(DateTime(1999, 2, 28, 23, 30, 33), d), 25, SysTime(DateTime(1999, 2, 28, 0, 30, 33), d));
4846 testST(SysTime(DateTime(1999, 3, 2, 0, 30, 33), d), -25, SysTime(DateTime(1999, 3, 2, 23, 30, 33), d));
4847
4848 testST(SysTime(DateTime(2000, 2, 28, 23, 30, 33), d), 25, SysTime(DateTime(2000, 2, 28, 0, 30, 33), d));
4849 testST(SysTime(DateTime(2000, 3, 1, 0, 30, 33), d), -25, SysTime(DateTime(2000, 3, 1, 23, 30, 33), d));
4850
4851 // Test B.C.
4852 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d);
4853 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
4854 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), d));
4855 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 14, 30, 33), d));
4856 testST(beforeBC, 3, SysTime(DateTime(-1999, 7, 6, 15, 30, 33), d));
4857 testST(beforeBC, 4, SysTime(DateTime(-1999, 7, 6, 16, 30, 33), d));
4858 testST(beforeBC, 5, SysTime(DateTime(-1999, 7, 6, 17, 30, 33), d));
4859 testST(beforeBC, 6, SysTime(DateTime(-1999, 7, 6, 18, 30, 33), d));
4860 testST(beforeBC, 7, SysTime(DateTime(-1999, 7, 6, 19, 30, 33), d));
4861 testST(beforeBC, 8, SysTime(DateTime(-1999, 7, 6, 20, 30, 33), d));
4862 testST(beforeBC, 9, SysTime(DateTime(-1999, 7, 6, 21, 30, 33), d));
4863 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 22, 30, 33), d));
4864 testST(beforeBC, 11, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d));
4865 testST(beforeBC, 12, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d));
4866 testST(beforeBC, 13, SysTime(DateTime(-1999, 7, 6, 1, 30, 33), d));
4867 testST(beforeBC, 14, SysTime(DateTime(-1999, 7, 6, 2, 30, 33), d));
4868 testST(beforeBC, 15, SysTime(DateTime(-1999, 7, 6, 3, 30, 33), d));
4869 testST(beforeBC, 16, SysTime(DateTime(-1999, 7, 6, 4, 30, 33), d));
4870 testST(beforeBC, 17, SysTime(DateTime(-1999, 7, 6, 5, 30, 33), d));
4871 testST(beforeBC, 18, SysTime(DateTime(-1999, 7, 6, 6, 30, 33), d));
4872 testST(beforeBC, 19, SysTime(DateTime(-1999, 7, 6, 7, 30, 33), d));
4873 testST(beforeBC, 20, SysTime(DateTime(-1999, 7, 6, 8, 30, 33), d));
4874 testST(beforeBC, 21, SysTime(DateTime(-1999, 7, 6, 9, 30, 33), d));
4875 testST(beforeBC, 22, SysTime(DateTime(-1999, 7, 6, 10, 30, 33), d));
4876 testST(beforeBC, 23, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), d));
4877 testST(beforeBC, 24, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
4878 testST(beforeBC, 25, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), d));
4879 testST(beforeBC, 50, SysTime(DateTime(-1999, 7, 6, 14, 30, 33), d));
4880 testST(beforeBC, 10_000, SysTime(DateTime(-1999, 7, 6, 4, 30, 33), d));
4881
4882 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), d));
4883 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 10, 30, 33), d));
4884 testST(beforeBC, -3, SysTime(DateTime(-1999, 7, 6, 9, 30, 33), d));
4885 testST(beforeBC, -4, SysTime(DateTime(-1999, 7, 6, 8, 30, 33), d));
4886 testST(beforeBC, -5, SysTime(DateTime(-1999, 7, 6, 7, 30, 33), d));
4887 testST(beforeBC, -6, SysTime(DateTime(-1999, 7, 6, 6, 30, 33), d));
4888 testST(beforeBC, -7, SysTime(DateTime(-1999, 7, 6, 5, 30, 33), d));
4889 testST(beforeBC, -8, SysTime(DateTime(-1999, 7, 6, 4, 30, 33), d));
4890 testST(beforeBC, -9, SysTime(DateTime(-1999, 7, 6, 3, 30, 33), d));
4891 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 2, 30, 33), d));
4892 testST(beforeBC, -11, SysTime(DateTime(-1999, 7, 6, 1, 30, 33), d));
4893 testST(beforeBC, -12, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d));
4894 testST(beforeBC, -13, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d));
4895 testST(beforeBC, -14, SysTime(DateTime(-1999, 7, 6, 22, 30, 33), d));
4896 testST(beforeBC, -15, SysTime(DateTime(-1999, 7, 6, 21, 30, 33), d));
4897 testST(beforeBC, -16, SysTime(DateTime(-1999, 7, 6, 20, 30, 33), d));
4898 testST(beforeBC, -17, SysTime(DateTime(-1999, 7, 6, 19, 30, 33), d));
4899 testST(beforeBC, -18, SysTime(DateTime(-1999, 7, 6, 18, 30, 33), d));
4900 testST(beforeBC, -19, SysTime(DateTime(-1999, 7, 6, 17, 30, 33), d));
4901 testST(beforeBC, -20, SysTime(DateTime(-1999, 7, 6, 16, 30, 33), d));
4902 testST(beforeBC, -21, SysTime(DateTime(-1999, 7, 6, 15, 30, 33), d));
4903 testST(beforeBC, -22, SysTime(DateTime(-1999, 7, 6, 14, 30, 33), d));
4904 testST(beforeBC, -23, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), d));
4905 testST(beforeBC, -24, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
4906 testST(beforeBC, -25, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), d));
4907 testST(beforeBC, -50, SysTime(DateTime(-1999, 7, 6, 10, 30, 33), d));
4908 testST(beforeBC, -10_000, SysTime(DateTime(-1999, 7, 6, 20, 30, 33), d));
4909
4910 testST(SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d), 1, SysTime(DateTime(-1999, 7, 6, 1, 30, 33), d));
4911 testST(SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d), 0, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d));
4912 testST(SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d), -1, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d));
4913
4914 testST(SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d), 1, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d));
4915 testST(SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d), 0, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d));
4916 testST(SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d), -1, SysTime(DateTime(-1999, 7, 6, 22, 30, 33), d));
4917
4918 testST(SysTime(DateTime(-1999, 7, 31, 23, 30, 33), d), 1, SysTime(DateTime(-1999, 7, 31, 0, 30, 33), d));
4919 testST(SysTime(DateTime(-1999, 8, 1, 0, 30, 33), d), -1, SysTime(DateTime(-1999, 8, 1, 23, 30, 33), d));
4920
4921 testST(SysTime(DateTime(-2001, 12, 31, 23, 30, 33), d), 1, SysTime(DateTime(-2001, 12, 31, 0, 30, 33), d));
4922 testST(SysTime(DateTime(-2000, 1, 1, 0, 30, 33), d), -1, SysTime(DateTime(-2000, 1, 1, 23, 30, 33), d));
4923
4924 testST(SysTime(DateTime(-2001, 2, 28, 23, 30, 33), d), 25, SysTime(DateTime(-2001, 2, 28, 0, 30, 33), d));
4925 testST(SysTime(DateTime(-2001, 3, 2, 0, 30, 33), d), -25, SysTime(DateTime(-2001, 3, 2, 23, 30, 33), d));
4926
4927 testST(SysTime(DateTime(-2000, 2, 28, 23, 30, 33), d), 25, SysTime(DateTime(-2000, 2, 28, 0, 30, 33), d));
4928 testST(SysTime(DateTime(-2000, 3, 1, 0, 30, 33), d), -25, SysTime(DateTime(-2000, 3, 1, 23, 30, 33), d));
4929
4930 // Test Both
4931 testST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), d), 17_546, SysTime(DateTime(-1, 1, 1, 13, 30, 33), d));
4932 testST(SysTime(DateTime(1, 1, 1, 13, 30, 33), d), -17_546, SysTime(DateTime(1, 1, 1, 11, 30, 33), d));
4933
4934 {
4935 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
4936 sysTime.roll!"hours"(-1);
4937 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 0, 0)));
4938 sysTime.roll!"hours"(1);
4939 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
4940 }
4941
4942 {
4943 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 59, 59), hnsecs(9_999_999));
4944 sysTime.roll!"hours"(-1);
4945 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
4946 sysTime.roll!"hours"(1);
4947 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 59, 59), hnsecs(9_999_999)));
4948 }
4949
4950 {
4951 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 0, 0));
4952 sysTime.roll!"hours"(1);
4953 assert(sysTime == SysTime(DateTime(0, 12, 31, 0, 0, 0)));
4954 sysTime.roll!"hours"(-1);
4955 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 0, 0)));
4956 }
4957
4958 {
4959 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
4960 sysTime.roll!"hours"(1);
4961 assert(sysTime == SysTime(DateTime(0, 12, 31, 0, 59, 59), hnsecs(9_999_999)));
4962 sysTime.roll!"hours"(-1);
4963 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
4964 }
4965
4966 {
4967 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
4968 sysTime.roll!"hours"(1).roll!"hours"(-67);
4969 assert(sysTime == SysTime(DateTime(0, 12, 31, 5, 59, 59), hnsecs(9_999_999)));
4970 }
4971
4972 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
4973 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
4974 static assert(!__traits(compiles, cst.roll!"hours"(4)));
4975 //static assert(!__traits(compiles, ist.roll!"hours"(4)));
4976 }
4977
4978 // Test roll!"minutes"().
4979 @safe unittest
4980 {
4981 static void testST(SysTime orig, int minutes, in SysTime expected, size_t line = __LINE__)
4982 {
4983 orig.roll!"minutes"(minutes);
4984 if (orig != expected)
4985 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
4986 }
4987
4988 // Test A.D.
4989 immutable d = usecs(7203);
4990 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), d);
4991 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
4992 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 31, 33), d));
4993 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 32, 33), d));
4994 testST(beforeAD, 3, SysTime(DateTime(1999, 7, 6, 12, 33, 33), d));
4995 testST(beforeAD, 4, SysTime(DateTime(1999, 7, 6, 12, 34, 33), d));
4996 testST(beforeAD, 5, SysTime(DateTime(1999, 7, 6, 12, 35, 33), d));
4997 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 40, 33), d));
4998 testST(beforeAD, 15, SysTime(DateTime(1999, 7, 6, 12, 45, 33), d));
4999 testST(beforeAD, 29, SysTime(DateTime(1999, 7, 6, 12, 59, 33), d));
5000 testST(beforeAD, 30, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5001 testST(beforeAD, 45, SysTime(DateTime(1999, 7, 6, 12, 15, 33), d));
5002 testST(beforeAD, 60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5003 testST(beforeAD, 75, SysTime(DateTime(1999, 7, 6, 12, 45, 33), d));
5004 testST(beforeAD, 90, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5005 testST(beforeAD, 100, SysTime(DateTime(1999, 7, 6, 12, 10, 33), d));
5006
5007 testST(beforeAD, 689, SysTime(DateTime(1999, 7, 6, 12, 59, 33), d));
5008 testST(beforeAD, 690, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5009 testST(beforeAD, 691, SysTime(DateTime(1999, 7, 6, 12, 1, 33), d));
5010 testST(beforeAD, 960, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5011 testST(beforeAD, 1439, SysTime(DateTime(1999, 7, 6, 12, 29, 33), d));
5012 testST(beforeAD, 1440, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5013 testST(beforeAD, 1441, SysTime(DateTime(1999, 7, 6, 12, 31, 33), d));
5014 testST(beforeAD, 2880, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5015
5016 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 29, 33), d));
5017 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 28, 33), d));
5018 testST(beforeAD, -3, SysTime(DateTime(1999, 7, 6, 12, 27, 33), d));
5019 testST(beforeAD, -4, SysTime(DateTime(1999, 7, 6, 12, 26, 33), d));
5020 testST(beforeAD, -5, SysTime(DateTime(1999, 7, 6, 12, 25, 33), d));
5021 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 20, 33), d));
5022 testST(beforeAD, -15, SysTime(DateTime(1999, 7, 6, 12, 15, 33), d));
5023 testST(beforeAD, -29, SysTime(DateTime(1999, 7, 6, 12, 1, 33), d));
5024 testST(beforeAD, -30, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5025 testST(beforeAD, -45, SysTime(DateTime(1999, 7, 6, 12, 45, 33), d));
5026 testST(beforeAD, -60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5027 testST(beforeAD, -75, SysTime(DateTime(1999, 7, 6, 12, 15, 33), d));
5028 testST(beforeAD, -90, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5029 testST(beforeAD, -100, SysTime(DateTime(1999, 7, 6, 12, 50, 33), d));
5030
5031 testST(beforeAD, -749, SysTime(DateTime(1999, 7, 6, 12, 1, 33), d));
5032 testST(beforeAD, -750, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5033 testST(beforeAD, -751, SysTime(DateTime(1999, 7, 6, 12, 59, 33), d));
5034 testST(beforeAD, -960, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5035 testST(beforeAD, -1439, SysTime(DateTime(1999, 7, 6, 12, 31, 33), d));
5036 testST(beforeAD, -1440, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5037 testST(beforeAD, -1441, SysTime(DateTime(1999, 7, 6, 12, 29, 33), d));
5038 testST(beforeAD, -2880, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5039
5040 testST(SysTime(DateTime(1999, 7, 6, 12, 0, 33), d), 1, SysTime(DateTime(1999, 7, 6, 12, 1, 33), d));
5041 testST(SysTime(DateTime(1999, 7, 6, 12, 0, 33), d), 0, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5042 testST(SysTime(DateTime(1999, 7, 6, 12, 0, 33), d), -1, SysTime(DateTime(1999, 7, 6, 12, 59, 33), d));
5043
5044 testST(SysTime(DateTime(1999, 7, 6, 11, 59, 33), d), 1, SysTime(DateTime(1999, 7, 6, 11, 0, 33), d));
5045 testST(SysTime(DateTime(1999, 7, 6, 11, 59, 33), d), 0, SysTime(DateTime(1999, 7, 6, 11, 59, 33), d));
5046 testST(SysTime(DateTime(1999, 7, 6, 11, 59, 33), d), -1, SysTime(DateTime(1999, 7, 6, 11, 58, 33), d));
5047
5048 testST(SysTime(DateTime(1999, 7, 6, 0, 0, 33), d), 1, SysTime(DateTime(1999, 7, 6, 0, 1, 33), d));
5049 testST(SysTime(DateTime(1999, 7, 6, 0, 0, 33), d), 0, SysTime(DateTime(1999, 7, 6, 0, 0, 33), d));
5050 testST(SysTime(DateTime(1999, 7, 6, 0, 0, 33), d), -1, SysTime(DateTime(1999, 7, 6, 0, 59, 33), d));
5051
5052 testST(SysTime(DateTime(1999, 7, 5, 23, 59, 33), d), 1, SysTime(DateTime(1999, 7, 5, 23, 0, 33), d));
5053 testST(SysTime(DateTime(1999, 7, 5, 23, 59, 33), d), 0, SysTime(DateTime(1999, 7, 5, 23, 59, 33), d));
5054 testST(SysTime(DateTime(1999, 7, 5, 23, 59, 33), d), -1, SysTime(DateTime(1999, 7, 5, 23, 58, 33), d));
5055
5056 testST(SysTime(DateTime(1998, 12, 31, 23, 59, 33), d), 1, SysTime(DateTime(1998, 12, 31, 23, 0, 33), d));
5057 testST(SysTime(DateTime(1998, 12, 31, 23, 59, 33), d), 0, SysTime(DateTime(1998, 12, 31, 23, 59, 33), d));
5058 testST(SysTime(DateTime(1998, 12, 31, 23, 59, 33), d), -1, SysTime(DateTime(1998, 12, 31, 23, 58, 33), d));
5059
5060 // Test B.C.
5061 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d);
5062 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5063 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), d));
5064 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 32, 33), d));
5065 testST(beforeBC, 3, SysTime(DateTime(-1999, 7, 6, 12, 33, 33), d));
5066 testST(beforeBC, 4, SysTime(DateTime(-1999, 7, 6, 12, 34, 33), d));
5067 testST(beforeBC, 5, SysTime(DateTime(-1999, 7, 6, 12, 35, 33), d));
5068 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 40, 33), d));
5069 testST(beforeBC, 15, SysTime(DateTime(-1999, 7, 6, 12, 45, 33), d));
5070 testST(beforeBC, 29, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), d));
5071 testST(beforeBC, 30, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5072 testST(beforeBC, 45, SysTime(DateTime(-1999, 7, 6, 12, 15, 33), d));
5073 testST(beforeBC, 60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5074 testST(beforeBC, 75, SysTime(DateTime(-1999, 7, 6, 12, 45, 33), d));
5075 testST(beforeBC, 90, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5076 testST(beforeBC, 100, SysTime(DateTime(-1999, 7, 6, 12, 10, 33), d));
5077
5078 testST(beforeBC, 689, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), d));
5079 testST(beforeBC, 690, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5080 testST(beforeBC, 691, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), d));
5081 testST(beforeBC, 960, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5082 testST(beforeBC, 1439, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), d));
5083 testST(beforeBC, 1440, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5084 testST(beforeBC, 1441, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), d));
5085 testST(beforeBC, 2880, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5086
5087 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), d));
5088 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 28, 33), d));
5089 testST(beforeBC, -3, SysTime(DateTime(-1999, 7, 6, 12, 27, 33), d));
5090 testST(beforeBC, -4, SysTime(DateTime(-1999, 7, 6, 12, 26, 33), d));
5091 testST(beforeBC, -5, SysTime(DateTime(-1999, 7, 6, 12, 25, 33), d));
5092 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 20, 33), d));
5093 testST(beforeBC, -15, SysTime(DateTime(-1999, 7, 6, 12, 15, 33), d));
5094 testST(beforeBC, -29, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), d));
5095 testST(beforeBC, -30, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5096 testST(beforeBC, -45, SysTime(DateTime(-1999, 7, 6, 12, 45, 33), d));
5097 testST(beforeBC, -60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5098 testST(beforeBC, -75, SysTime(DateTime(-1999, 7, 6, 12, 15, 33), d));
5099 testST(beforeBC, -90, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5100 testST(beforeBC, -100, SysTime(DateTime(-1999, 7, 6, 12, 50, 33), d));
5101
5102 testST(beforeBC, -749, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), d));
5103 testST(beforeBC, -750, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5104 testST(beforeBC, -751, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), d));
5105 testST(beforeBC, -960, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5106 testST(beforeBC, -1439, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), d));
5107 testST(beforeBC, -1440, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5108 testST(beforeBC, -1441, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), d));
5109 testST(beforeBC, -2880, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5110
5111 testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d), 1, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), d));
5112 testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d), 0, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5113 testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d), -1, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), d));
5114
5115 testST(SysTime(DateTime(-1999, 7, 6, 11, 59, 33), d), 1, SysTime(DateTime(-1999, 7, 6, 11, 0, 33), d));
5116 testST(SysTime(DateTime(-1999, 7, 6, 11, 59, 33), d), 0, SysTime(DateTime(-1999, 7, 6, 11, 59, 33), d));
5117 testST(SysTime(DateTime(-1999, 7, 6, 11, 59, 33), d), -1, SysTime(DateTime(-1999, 7, 6, 11, 58, 33), d));
5118
5119 testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 33), d), 1, SysTime(DateTime(-1999, 7, 6, 0, 1, 33), d));
5120 testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 33), d), 0, SysTime(DateTime(-1999, 7, 6, 0, 0, 33), d));
5121 testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 33), d), -1, SysTime(DateTime(-1999, 7, 6, 0, 59, 33), d));
5122
5123 testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 33), d), 1, SysTime(DateTime(-1999, 7, 5, 23, 0, 33), d));
5124 testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 33), d), 0, SysTime(DateTime(-1999, 7, 5, 23, 59, 33), d));
5125 testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 33), d), -1, SysTime(DateTime(-1999, 7, 5, 23, 58, 33), d));
5126
5127 testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 33), d), 1, SysTime(DateTime(-2000, 12, 31, 23, 0, 33), d));
5128 testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 33), d), 0, SysTime(DateTime(-2000, 12, 31, 23, 59, 33), d));
5129 testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 33), d), -1, SysTime(DateTime(-2000, 12, 31, 23, 58, 33), d));
5130
5131 // Test Both
5132 testST(SysTime(DateTime(1, 1, 1, 0, 0, 0)), -1, SysTime(DateTime(1, 1, 1, 0, 59, 0)));
5133 testST(SysTime(DateTime(0, 12, 31, 23, 59, 0)), 1, SysTime(DateTime(0, 12, 31, 23, 0, 0)));
5134
5135 testST(SysTime(DateTime(0, 1, 1, 0, 0, 0)), -1, SysTime(DateTime(0, 1, 1, 0, 59, 0)));
5136 testST(SysTime(DateTime(-1, 12, 31, 23, 59, 0)), 1, SysTime(DateTime(-1, 12, 31, 23, 0, 0)));
5137
5138 testST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), d), 1_052_760, SysTime(DateTime(-1, 1, 1, 11, 30, 33), d));
5139 testST(SysTime(DateTime(1, 1, 1, 13, 30, 33), d), -1_052_760, SysTime(DateTime(1, 1, 1, 13, 30, 33), d));
5140
5141 testST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), d), 1_052_782, SysTime(DateTime(-1, 1, 1, 11, 52, 33), d));
5142 testST(SysTime(DateTime(1, 1, 1, 13, 52, 33), d), -1_052_782, SysTime(DateTime(1, 1, 1, 13, 30, 33), d));
5143
5144 {
5145 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
5146 sysTime.roll!"minutes"(-1);
5147 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 59, 0)));
5148 sysTime.roll!"minutes"(1);
5149 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5150 }
5151
5152 {
5153 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 59), hnsecs(9_999_999));
5154 sysTime.roll!"minutes"(-1);
5155 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 59, 59), hnsecs(9_999_999)));
5156 sysTime.roll!"minutes"(1);
5157 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 59), hnsecs(9_999_999)));
5158 }
5159
5160 {
5161 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 0));
5162 sysTime.roll!"minutes"(1);
5163 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 0, 0)));
5164 sysTime.roll!"minutes"(-1);
5165 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 0)));
5166 }
5167
5168 {
5169 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5170 sysTime.roll!"minutes"(1);
5171 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 0, 59), hnsecs(9_999_999)));
5172 sysTime.roll!"minutes"(-1);
5173 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5174 }
5175
5176 {
5177 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5178 sysTime.roll!"minutes"(1).roll!"minutes"(-79);
5179 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 41, 59), hnsecs(9_999_999)));
5180 }
5181
5182 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5183 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5184 static assert(!__traits(compiles, cst.roll!"minutes"(4)));
5185 //static assert(!__traits(compiles, ist.roll!"minutes"(4)));
5186 }
5187
5188 // Test roll!"seconds"().
5189 @safe unittest
5190 {
5191 static void testST(SysTime orig, int seconds, in SysTime expected, size_t line = __LINE__)
5192 {
5193 orig.roll!"seconds"(seconds);
5194 if (orig != expected)
5195 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
5196 }
5197
5198 // Test A.D.
5199 immutable d = msecs(274);
5200 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), d);
5201 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5202 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 30, 34), d));
5203 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 30, 35), d));
5204 testST(beforeAD, 3, SysTime(DateTime(1999, 7, 6, 12, 30, 36), d));
5205 testST(beforeAD, 4, SysTime(DateTime(1999, 7, 6, 12, 30, 37), d));
5206 testST(beforeAD, 5, SysTime(DateTime(1999, 7, 6, 12, 30, 38), d));
5207 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 30, 43), d));
5208 testST(beforeAD, 15, SysTime(DateTime(1999, 7, 6, 12, 30, 48), d));
5209 testST(beforeAD, 26, SysTime(DateTime(1999, 7, 6, 12, 30, 59), d));
5210 testST(beforeAD, 27, SysTime(DateTime(1999, 7, 6, 12, 30, 0), d));
5211 testST(beforeAD, 30, SysTime(DateTime(1999, 7, 6, 12, 30, 3), d));
5212 testST(beforeAD, 59, SysTime(DateTime(1999, 7, 6, 12, 30, 32), d));
5213 testST(beforeAD, 60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5214 testST(beforeAD, 61, SysTime(DateTime(1999, 7, 6, 12, 30, 34), d));
5215
5216 testST(beforeAD, 1766, SysTime(DateTime(1999, 7, 6, 12, 30, 59), d));
5217 testST(beforeAD, 1767, SysTime(DateTime(1999, 7, 6, 12, 30, 0), d));
5218 testST(beforeAD, 1768, SysTime(DateTime(1999, 7, 6, 12, 30, 1), d));
5219 testST(beforeAD, 2007, SysTime(DateTime(1999, 7, 6, 12, 30, 0), d));
5220 testST(beforeAD, 3599, SysTime(DateTime(1999, 7, 6, 12, 30, 32), d));
5221 testST(beforeAD, 3600, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5222 testST(beforeAD, 3601, SysTime(DateTime(1999, 7, 6, 12, 30, 34), d));
5223 testST(beforeAD, 7200, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5224
5225 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 30, 32), d));
5226 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 30, 31), d));
5227 testST(beforeAD, -3, SysTime(DateTime(1999, 7, 6, 12, 30, 30), d));
5228 testST(beforeAD, -4, SysTime(DateTime(1999, 7, 6, 12, 30, 29), d));
5229 testST(beforeAD, -5, SysTime(DateTime(1999, 7, 6, 12, 30, 28), d));
5230 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 30, 23), d));
5231 testST(beforeAD, -15, SysTime(DateTime(1999, 7, 6, 12, 30, 18), d));
5232 testST(beforeAD, -33, SysTime(DateTime(1999, 7, 6, 12, 30, 0), d));
5233 testST(beforeAD, -34, SysTime(DateTime(1999, 7, 6, 12, 30, 59), d));
5234 testST(beforeAD, -35, SysTime(DateTime(1999, 7, 6, 12, 30, 58), d));
5235 testST(beforeAD, -59, SysTime(DateTime(1999, 7, 6, 12, 30, 34), d));
5236 testST(beforeAD, -60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5237 testST(beforeAD, -61, SysTime(DateTime(1999, 7, 6, 12, 30, 32), d));
5238
5239 testST(SysTime(DateTime(1999, 7, 6, 12, 30, 0), d), 1, SysTime(DateTime(1999, 7, 6, 12, 30, 1), d));
5240 testST(SysTime(DateTime(1999, 7, 6, 12, 30, 0), d), 0, SysTime(DateTime(1999, 7, 6, 12, 30, 0), d));
5241 testST(SysTime(DateTime(1999, 7, 6, 12, 30, 0), d), -1, SysTime(DateTime(1999, 7, 6, 12, 30, 59), d));
5242
5243 testST(SysTime(DateTime(1999, 7, 6, 12, 0, 0), d), 1, SysTime(DateTime(1999, 7, 6, 12, 0, 1), d));
5244 testST(SysTime(DateTime(1999, 7, 6, 12, 0, 0), d), 0, SysTime(DateTime(1999, 7, 6, 12, 0, 0), d));
5245 testST(SysTime(DateTime(1999, 7, 6, 12, 0, 0), d), -1, SysTime(DateTime(1999, 7, 6, 12, 0, 59), d));
5246
5247 testST(SysTime(DateTime(1999, 7, 6, 0, 0, 0), d), 1, SysTime(DateTime(1999, 7, 6, 0, 0, 1), d));
5248 testST(SysTime(DateTime(1999, 7, 6, 0, 0, 0), d), 0, SysTime(DateTime(1999, 7, 6, 0, 0, 0), d));
5249 testST(SysTime(DateTime(1999, 7, 6, 0, 0, 0), d), -1, SysTime(DateTime(1999, 7, 6, 0, 0, 59), d));
5250
5251 testST(SysTime(DateTime(1999, 7, 5, 23, 59, 59), d), 1, SysTime(DateTime(1999, 7, 5, 23, 59, 0), d));
5252 testST(SysTime(DateTime(1999, 7, 5, 23, 59, 59), d), 0, SysTime(DateTime(1999, 7, 5, 23, 59, 59), d));
5253 testST(SysTime(DateTime(1999, 7, 5, 23, 59, 59), d), -1, SysTime(DateTime(1999, 7, 5, 23, 59, 58), d));
5254
5255 testST(SysTime(DateTime(1998, 12, 31, 23, 59, 59), d), 1, SysTime(DateTime(1998, 12, 31, 23, 59, 0), d));
5256 testST(SysTime(DateTime(1998, 12, 31, 23, 59, 59), d), 0, SysTime(DateTime(1998, 12, 31, 23, 59, 59), d));
5257 testST(SysTime(DateTime(1998, 12, 31, 23, 59, 59), d), -1, SysTime(DateTime(1998, 12, 31, 23, 59, 58), d));
5258
5259 // Test B.C.
5260 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d);
5261 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5262 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), d));
5263 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 35), d));
5264 testST(beforeBC, 3, SysTime(DateTime(-1999, 7, 6, 12, 30, 36), d));
5265 testST(beforeBC, 4, SysTime(DateTime(-1999, 7, 6, 12, 30, 37), d));
5266 testST(beforeBC, 5, SysTime(DateTime(-1999, 7, 6, 12, 30, 38), d));
5267 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 43), d));
5268 testST(beforeBC, 15, SysTime(DateTime(-1999, 7, 6, 12, 30, 48), d));
5269 testST(beforeBC, 26, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), d));
5270 testST(beforeBC, 27, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d));
5271 testST(beforeBC, 30, SysTime(DateTime(-1999, 7, 6, 12, 30, 3), d));
5272 testST(beforeBC, 59, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), d));
5273 testST(beforeBC, 60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5274 testST(beforeBC, 61, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), d));
5275
5276 testST(beforeBC, 1766, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), d));
5277 testST(beforeBC, 1767, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d));
5278 testST(beforeBC, 1768, SysTime(DateTime(-1999, 7, 6, 12, 30, 1), d));
5279 testST(beforeBC, 2007, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d));
5280 testST(beforeBC, 3599, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), d));
5281 testST(beforeBC, 3600, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5282 testST(beforeBC, 3601, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), d));
5283 testST(beforeBC, 7200, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5284
5285 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), d));
5286 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 31), d));
5287 testST(beforeBC, -3, SysTime(DateTime(-1999, 7, 6, 12, 30, 30), d));
5288 testST(beforeBC, -4, SysTime(DateTime(-1999, 7, 6, 12, 30, 29), d));
5289 testST(beforeBC, -5, SysTime(DateTime(-1999, 7, 6, 12, 30, 28), d));
5290 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 23), d));
5291 testST(beforeBC, -15, SysTime(DateTime(-1999, 7, 6, 12, 30, 18), d));
5292 testST(beforeBC, -33, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d));
5293 testST(beforeBC, -34, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), d));
5294 testST(beforeBC, -35, SysTime(DateTime(-1999, 7, 6, 12, 30, 58), d));
5295 testST(beforeBC, -59, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), d));
5296 testST(beforeBC, -60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5297 testST(beforeBC, -61, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), d));
5298
5299 testST(SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d), 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 1), d));
5300 testST(SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d), 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d));
5301 testST(SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d), -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), d));
5302
5303 testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 0), d), 1, SysTime(DateTime(-1999, 7, 6, 12, 0, 1), d));
5304 testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 0), d), 0, SysTime(DateTime(-1999, 7, 6, 12, 0, 0), d));
5305 testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 0), d), -1, SysTime(DateTime(-1999, 7, 6, 12, 0, 59), d));
5306
5307 testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 0), d), 1, SysTime(DateTime(-1999, 7, 6, 0, 0, 1), d));
5308 testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 0), d), 0, SysTime(DateTime(-1999, 7, 6, 0, 0, 0), d));
5309 testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 0), d), -1, SysTime(DateTime(-1999, 7, 6, 0, 0, 59), d));
5310
5311 testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 59), d), 1, SysTime(DateTime(-1999, 7, 5, 23, 59, 0), d));
5312 testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 59), d), 0, SysTime(DateTime(-1999, 7, 5, 23, 59, 59), d));
5313 testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 59), d), -1, SysTime(DateTime(-1999, 7, 5, 23, 59, 58), d));
5314
5315 testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 59), d), 1, SysTime(DateTime(-2000, 12, 31, 23, 59, 0), d));
5316 testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 59), d), 0, SysTime(DateTime(-2000, 12, 31, 23, 59, 59), d));
5317 testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 59), d), -1, SysTime(DateTime(-2000, 12, 31, 23, 59, 58), d));
5318
5319 // Test Both
5320 testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), d), -1, SysTime(DateTime(1, 1, 1, 0, 0, 59), d));
5321 testST(SysTime(DateTime(0, 12, 31, 23, 59, 59), d), 1, SysTime(DateTime(0, 12, 31, 23, 59, 0), d));
5322
5323 testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), d), -1, SysTime(DateTime(0, 1, 1, 0, 0, 59), d));
5324 testST(SysTime(DateTime(-1, 12, 31, 23, 59, 59), d), 1, SysTime(DateTime(-1, 12, 31, 23, 59, 0), d));
5325
5326 testST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), d), 63_165_600L, SysTime(DateTime(-1, 1, 1, 11, 30, 33), d));
5327 testST(SysTime(DateTime(1, 1, 1, 13, 30, 33), d), -63_165_600L, SysTime(DateTime(1, 1, 1, 13, 30, 33), d));
5328
5329 testST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), d), 63_165_617L, SysTime(DateTime(-1, 1, 1, 11, 30, 50), d));
5330 testST(SysTime(DateTime(1, 1, 1, 13, 30, 50), d), -63_165_617L, SysTime(DateTime(1, 1, 1, 13, 30, 33), d));
5331
5332 {
5333 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
5334 sysTime.roll!"seconds"(-1);
5335 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 59)));
5336 sysTime.roll!"seconds"(1);
5337 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5338 }
5339
5340 {
5341 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(9_999_999));
5342 sysTime.roll!"seconds"(-1);
5343 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 59), hnsecs(9_999_999)));
5344 sysTime.roll!"seconds"(1);
5345 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
5346 }
5347
5348 {
5349 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59));
5350 sysTime.roll!"seconds"(1);
5351 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 0)));
5352 sysTime.roll!"seconds"(-1);
5353 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 59)));
5354 }
5355
5356 {
5357 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5358 sysTime.roll!"seconds"(1);
5359 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 0), hnsecs(9_999_999)));
5360 sysTime.roll!"seconds"(-1);
5361 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5362 }
5363
5364 {
5365 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5366 sysTime.roll!"seconds"(1).roll!"seconds"(-102);
5367 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 18), hnsecs(9_999_999)));
5368 }
5369
5370 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5371 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5372 static assert(!__traits(compiles, cst.roll!"seconds"(4)));
5373 //static assert(!__traits(compiles, ist.roll!"seconds"(4)));
5374 }
5375
5376
5377 // Shares documentation with "days" version.
5378 ref SysTime roll(string units)(long value) @safe nothrow
5379 if (units == "msecs" || units == "usecs" || units == "hnsecs")
5380 {
5381 auto hnsecs = adjTime;
5382 immutable days = splitUnitsFromHNSecs!"days"(hnsecs);
5383 immutable negative = hnsecs < 0;
5384
5385 if (negative)
5386 hnsecs += convert!("hours", "hnsecs")(24);
5387
5388 immutable seconds = splitUnitsFromHNSecs!"seconds"(hnsecs);
5389 hnsecs += convert!(units, "hnsecs")(value);
5390 hnsecs %= convert!("seconds", "hnsecs")(1);
5391
5392 if (hnsecs < 0)
5393 hnsecs += convert!("seconds", "hnsecs")(1);
5394 hnsecs += convert!("seconds", "hnsecs")(seconds);
5395
5396 if (negative)
5397 hnsecs -= convert!("hours", "hnsecs")(24);
5398
5399 immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
5400 adjTime = newDaysHNSecs + hnsecs;
5401 return this;
5402 }
5403
5404
5405 // Test roll!"msecs"().
5406 @safe unittest
5407 {
5408 static void testST(SysTime orig, int milliseconds, in SysTime expected, size_t line = __LINE__)
5409 {
5410 orig.roll!"msecs"(milliseconds);
5411 if (orig != expected)
5412 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
5413 }
5414
5415 // Test A.D.
5416 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274));
5417 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274)));
5418 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(275)));
5419 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(276)));
5420 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(284)));
5421 testST(beforeAD, 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(374)));
5422 testST(beforeAD, 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999)));
5423 testST(beforeAD, 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5424 testST(beforeAD, 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274)));
5425 testST(beforeAD, 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(275)));
5426 testST(beforeAD, 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274)));
5427 testST(beforeAD, 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999)));
5428 testST(beforeAD, 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5429 testST(beforeAD, 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(1)));
5430 testST(beforeAD, 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999)));
5431 testST(beforeAD, 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5432
5433 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(273)));
5434 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(272)));
5435 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(264)));
5436 testST(beforeAD, -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(174)));
5437 testST(beforeAD, -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5438 testST(beforeAD, -275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999)));
5439 testST(beforeAD, -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274)));
5440 testST(beforeAD, -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(273)));
5441 testST(beforeAD, -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274)));
5442 testST(beforeAD, -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5443 testST(beforeAD, -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999)));
5444 testST(beforeAD, -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5445 testST(beforeAD, -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999)));
5446
5447 // Test B.C.
5448 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274));
5449 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274)));
5450 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(275)));
5451 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(276)));
5452 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(284)));
5453 testST(beforeBC, 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(374)));
5454 testST(beforeBC, 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999)));
5455 testST(beforeBC, 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5456 testST(beforeBC, 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274)));
5457 testST(beforeBC, 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(275)));
5458 testST(beforeBC, 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274)));
5459 testST(beforeBC, 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999)));
5460 testST(beforeBC, 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5461 testST(beforeBC, 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(1)));
5462 testST(beforeBC, 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999)));
5463 testST(beforeBC, 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5464
5465 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(273)));
5466 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(272)));
5467 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(264)));
5468 testST(beforeBC, -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(174)));
5469 testST(beforeBC, -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5470 testST(beforeBC, -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999)));
5471 testST(beforeBC, -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274)));
5472 testST(beforeBC, -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(273)));
5473 testST(beforeBC, -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274)));
5474 testST(beforeBC, -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5475 testST(beforeBC, -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999)));
5476 testST(beforeBC, -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5477 testST(beforeBC, -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999)));
5478
5479 // Test Both
5480 auto beforeBoth1 = SysTime(DateTime(1, 1, 1, 0, 0, 0));
5481 testST(beforeBoth1, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), msecs(1)));
5482 testST(beforeBoth1, 0, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5483 testST(beforeBoth1, -1, SysTime(DateTime(1, 1, 1, 0, 0, 0), msecs(999)));
5484 testST(beforeBoth1, -2, SysTime(DateTime(1, 1, 1, 0, 0, 0), msecs(998)));
5485 testST(beforeBoth1, -1000, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5486 testST(beforeBoth1, -2000, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5487 testST(beforeBoth1, -2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), msecs(445)));
5488
5489 auto beforeBoth2 = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5490 testST(beforeBoth2, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_989_999)));
5491 testST(beforeBoth2, 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5492 testST(beforeBoth2, 1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9999)));
5493 testST(beforeBoth2, 2, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(19_999)));
5494 testST(beforeBoth2, 1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5495 testST(beforeBoth2, 2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5496 testST(beforeBoth2, 2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(5_549_999)));
5497
5498 {
5499 auto st = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5500 st.roll!"msecs"(1202).roll!"msecs"(-703);
5501 assert(st == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(4_989_999)));
5502 }
5503
5504 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5505 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5506 static assert(!__traits(compiles, cst.addMSecs(4)));
5507 //static assert(!__traits(compiles, ist.addMSecs(4)));
5508 }
5509
5510 // Test roll!"usecs"().
5511 @safe unittest
5512 {
5513 static void testST(SysTime orig, long microseconds, in SysTime expected, size_t line = __LINE__)
5514 {
5515 orig.roll!"usecs"(microseconds);
5516 if (orig != expected)
5517 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
5518 }
5519
5520 // Test A.D.
5521 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274));
5522 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
5523 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(275)));
5524 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(276)));
5525 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(284)));
5526 testST(beforeAD, 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(374)));
5527 testST(beforeAD, 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(999)));
5528 testST(beforeAD, 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(1000)));
5529 testST(beforeAD, 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(1274)));
5530 testST(beforeAD, 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(1275)));
5531 testST(beforeAD, 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(2274)));
5532 testST(beforeAD, 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(26_999)));
5533 testST(beforeAD, 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(27_000)));
5534 testST(beforeAD, 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(27_001)));
5535 testST(beforeAD, 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(766_999)));
5536 testST(beforeAD, 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(767_000)));
5537 testST(beforeAD, 1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
5538 testST(beforeAD, 60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
5539 testST(beforeAD, 3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
5540
5541 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(273)));
5542 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(272)));
5543 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(264)));
5544 testST(beforeAD, -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(174)));
5545 testST(beforeAD, -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5546 testST(beforeAD, -275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(999_999)));
5547 testST(beforeAD, -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(999_274)));
5548 testST(beforeAD, -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(999_273)));
5549 testST(beforeAD, -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(998_274)));
5550 testST(beforeAD, -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(967_000)));
5551 testST(beforeAD, -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(966_999)));
5552 testST(beforeAD, -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(167_000)));
5553 testST(beforeAD, -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(166_999)));
5554 testST(beforeAD, -1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
5555 testST(beforeAD, -60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
5556 testST(beforeAD, -3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
5557
5558 // Test B.C.
5559 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274));
5560 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
5561 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(275)));
5562 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(276)));
5563 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(284)));
5564 testST(beforeBC, 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(374)));
5565 testST(beforeBC, 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(999)));
5566 testST(beforeBC, 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(1000)));
5567 testST(beforeBC, 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(1274)));
5568 testST(beforeBC, 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(1275)));
5569 testST(beforeBC, 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(2274)));
5570 testST(beforeBC, 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(26_999)));
5571 testST(beforeBC, 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(27_000)));
5572 testST(beforeBC, 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(27_001)));
5573 testST(beforeBC, 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(766_999)));
5574 testST(beforeBC, 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(767_000)));
5575 testST(beforeBC, 1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
5576 testST(beforeBC, 60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
5577 testST(beforeBC, 3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
5578
5579 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(273)));
5580 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(272)));
5581 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(264)));
5582 testST(beforeBC, -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(174)));
5583 testST(beforeBC, -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5584 testST(beforeBC, -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(999_999)));
5585 testST(beforeBC, -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(999_274)));
5586 testST(beforeBC, -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(999_273)));
5587 testST(beforeBC, -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(998_274)));
5588 testST(beforeBC, -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(967_000)));
5589 testST(beforeBC, -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(966_999)));
5590 testST(beforeBC, -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(167_000)));
5591 testST(beforeBC, -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(166_999)));
5592 testST(beforeBC, -1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
5593 testST(beforeBC, -60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
5594 testST(beforeBC, -3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
5595
5596 // Test Both
5597 auto beforeBoth1 = SysTime(DateTime(1, 1, 1, 0, 0, 0));
5598 testST(beforeBoth1, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(1)));
5599 testST(beforeBoth1, 0, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5600 testST(beforeBoth1, -1, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(999_999)));
5601 testST(beforeBoth1, -2, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(999_998)));
5602 testST(beforeBoth1, -1000, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(999_000)));
5603 testST(beforeBoth1, -2000, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(998_000)));
5604 testST(beforeBoth1, -2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(997_445)));
5605 testST(beforeBoth1, -1_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5606 testST(beforeBoth1, -2_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5607 testST(beforeBoth1, -2_333_333, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(666_667)));
5608
5609 auto beforeBoth2 = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5610 testST(beforeBoth2, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_989)));
5611 testST(beforeBoth2, 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5612 testST(beforeBoth2, 1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9)));
5613 testST(beforeBoth2, 2, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(19)));
5614 testST(beforeBoth2, 1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9999)));
5615 testST(beforeBoth2, 2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(19_999)));
5616 testST(beforeBoth2, 2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(25_549)));
5617 testST(beforeBoth2, 1_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5618 testST(beforeBoth2, 2_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5619 testST(beforeBoth2, 2_333_333, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(3_333_329)));
5620
5621 {
5622 auto st = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5623 st.roll!"usecs"(9_020_027);
5624 assert(st == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(200_269)));
5625 }
5626
5627 {
5628 auto st = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5629 st.roll!"usecs"(9_020_027).roll!"usecs"(-70_034);
5630 assert(st == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_499_929)));
5631 }
5632
5633 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5634 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5635 static assert(!__traits(compiles, cst.roll!"usecs"(4)));
5636 //static assert(!__traits(compiles, ist.roll!"usecs"(4)));
5637 }
5638
5639 // Test roll!"hnsecs"().
5640 @safe unittest
5641 {
5642 static void testST(SysTime orig, long hnsecs, in SysTime expected, size_t line = __LINE__)
5643 {
5644 orig.roll!"hnsecs"(hnsecs);
5645 if (orig != expected)
5646 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
5647 }
5648
5649 // Test A.D.
5650 auto dtAD = DateTime(1999, 7, 6, 12, 30, 33);
5651 auto beforeAD = SysTime(dtAD, hnsecs(274));
5652 testST(beforeAD, 0, SysTime(dtAD, hnsecs(274)));
5653 testST(beforeAD, 1, SysTime(dtAD, hnsecs(275)));
5654 testST(beforeAD, 2, SysTime(dtAD, hnsecs(276)));
5655 testST(beforeAD, 10, SysTime(dtAD, hnsecs(284)));
5656 testST(beforeAD, 100, SysTime(dtAD, hnsecs(374)));
5657 testST(beforeAD, 725, SysTime(dtAD, hnsecs(999)));
5658 testST(beforeAD, 726, SysTime(dtAD, hnsecs(1000)));
5659 testST(beforeAD, 1000, SysTime(dtAD, hnsecs(1274)));
5660 testST(beforeAD, 1001, SysTime(dtAD, hnsecs(1275)));
5661 testST(beforeAD, 2000, SysTime(dtAD, hnsecs(2274)));
5662 testST(beforeAD, 26_725, SysTime(dtAD, hnsecs(26_999)));
5663 testST(beforeAD, 26_726, SysTime(dtAD, hnsecs(27_000)));
5664 testST(beforeAD, 26_727, SysTime(dtAD, hnsecs(27_001)));
5665 testST(beforeAD, 1_766_725, SysTime(dtAD, hnsecs(1_766_999)));
5666 testST(beforeAD, 1_766_726, SysTime(dtAD, hnsecs(1_767_000)));
5667 testST(beforeAD, 1_000_000, SysTime(dtAD, hnsecs(1_000_274)));
5668 testST(beforeAD, 60_000_000L, SysTime(dtAD, hnsecs(274)));
5669 testST(beforeAD, 3_600_000_000L, SysTime(dtAD, hnsecs(274)));
5670 testST(beforeAD, 600_000_000L, SysTime(dtAD, hnsecs(274)));
5671 testST(beforeAD, 36_000_000_000L, SysTime(dtAD, hnsecs(274)));
5672
5673 testST(beforeAD, -1, SysTime(dtAD, hnsecs(273)));
5674 testST(beforeAD, -2, SysTime(dtAD, hnsecs(272)));
5675 testST(beforeAD, -10, SysTime(dtAD, hnsecs(264)));
5676 testST(beforeAD, -100, SysTime(dtAD, hnsecs(174)));
5677 testST(beforeAD, -274, SysTime(dtAD));
5678 testST(beforeAD, -275, SysTime(dtAD, hnsecs(9_999_999)));
5679 testST(beforeAD, -1000, SysTime(dtAD, hnsecs(9_999_274)));
5680 testST(beforeAD, -1001, SysTime(dtAD, hnsecs(9_999_273)));
5681 testST(beforeAD, -2000, SysTime(dtAD, hnsecs(9_998_274)));
5682 testST(beforeAD, -33_274, SysTime(dtAD, hnsecs(9_967_000)));
5683 testST(beforeAD, -33_275, SysTime(dtAD, hnsecs(9_966_999)));
5684 testST(beforeAD, -1_833_274, SysTime(dtAD, hnsecs(8_167_000)));
5685 testST(beforeAD, -1_833_275, SysTime(dtAD, hnsecs(8_166_999)));
5686 testST(beforeAD, -1_000_000, SysTime(dtAD, hnsecs(9_000_274)));
5687 testST(beforeAD, -60_000_000L, SysTime(dtAD, hnsecs(274)));
5688 testST(beforeAD, -3_600_000_000L, SysTime(dtAD, hnsecs(274)));
5689 testST(beforeAD, -600_000_000L, SysTime(dtAD, hnsecs(274)));
5690 testST(beforeAD, -36_000_000_000L, SysTime(dtAD, hnsecs(274)));
5691
5692 // Test B.C.
5693 auto dtBC = DateTime(-1999, 7, 6, 12, 30, 33);
5694 auto beforeBC = SysTime(dtBC, hnsecs(274));
5695 testST(beforeBC, 0, SysTime(dtBC, hnsecs(274)));
5696 testST(beforeBC, 1, SysTime(dtBC, hnsecs(275)));
5697 testST(beforeBC, 2, SysTime(dtBC, hnsecs(276)));
5698 testST(beforeBC, 10, SysTime(dtBC, hnsecs(284)));
5699 testST(beforeBC, 100, SysTime(dtBC, hnsecs(374)));
5700 testST(beforeBC, 725, SysTime(dtBC, hnsecs(999)));
5701 testST(beforeBC, 726, SysTime(dtBC, hnsecs(1000)));
5702 testST(beforeBC, 1000, SysTime(dtBC, hnsecs(1274)));
5703 testST(beforeBC, 1001, SysTime(dtBC, hnsecs(1275)));
5704 testST(beforeBC, 2000, SysTime(dtBC, hnsecs(2274)));
5705 testST(beforeBC, 26_725, SysTime(dtBC, hnsecs(26_999)));
5706 testST(beforeBC, 26_726, SysTime(dtBC, hnsecs(27_000)));
5707 testST(beforeBC, 26_727, SysTime(dtBC, hnsecs(27_001)));
5708 testST(beforeBC, 1_766_725, SysTime(dtBC, hnsecs(1_766_999)));
5709 testST(beforeBC, 1_766_726, SysTime(dtBC, hnsecs(1_767_000)));
5710 testST(beforeBC, 1_000_000, SysTime(dtBC, hnsecs(1_000_274)));
5711 testST(beforeBC, 60_000_000L, SysTime(dtBC, hnsecs(274)));
5712 testST(beforeBC, 3_600_000_000L, SysTime(dtBC, hnsecs(274)));
5713 testST(beforeBC, 600_000_000L, SysTime(dtBC, hnsecs(274)));
5714 testST(beforeBC, 36_000_000_000L, SysTime(dtBC, hnsecs(274)));
5715
5716 testST(beforeBC, -1, SysTime(dtBC, hnsecs(273)));
5717 testST(beforeBC, -2, SysTime(dtBC, hnsecs(272)));
5718 testST(beforeBC, -10, SysTime(dtBC, hnsecs(264)));
5719 testST(beforeBC, -100, SysTime(dtBC, hnsecs(174)));
5720 testST(beforeBC, -274, SysTime(dtBC));
5721 testST(beforeBC, -275, SysTime(dtBC, hnsecs(9_999_999)));
5722 testST(beforeBC, -1000, SysTime(dtBC, hnsecs(9_999_274)));
5723 testST(beforeBC, -1001, SysTime(dtBC, hnsecs(9_999_273)));
5724 testST(beforeBC, -2000, SysTime(dtBC, hnsecs(9_998_274)));
5725 testST(beforeBC, -33_274, SysTime(dtBC, hnsecs(9_967_000)));
5726 testST(beforeBC, -33_275, SysTime(dtBC, hnsecs(9_966_999)));
5727 testST(beforeBC, -1_833_274, SysTime(dtBC, hnsecs(8_167_000)));
5728 testST(beforeBC, -1_833_275, SysTime(dtBC, hnsecs(8_166_999)));
5729 testST(beforeBC, -1_000_000, SysTime(dtBC, hnsecs(9_000_274)));
5730 testST(beforeBC, -60_000_000L, SysTime(dtBC, hnsecs(274)));
5731 testST(beforeBC, -3_600_000_000L, SysTime(dtBC, hnsecs(274)));
5732 testST(beforeBC, -600_000_000L, SysTime(dtBC, hnsecs(274)));
5733 testST(beforeBC, -36_000_000_000L, SysTime(dtBC, hnsecs(274)));
5734
5735 // Test Both
5736 auto dtBoth1 = DateTime(1, 1, 1, 0, 0, 0);
5737 auto beforeBoth1 = SysTime(dtBoth1);
5738 testST(beforeBoth1, 1, SysTime(dtBoth1, hnsecs(1)));
5739 testST(beforeBoth1, 0, SysTime(dtBoth1));
5740 testST(beforeBoth1, -1, SysTime(dtBoth1, hnsecs(9_999_999)));
5741 testST(beforeBoth1, -2, SysTime(dtBoth1, hnsecs(9_999_998)));
5742 testST(beforeBoth1, -1000, SysTime(dtBoth1, hnsecs(9_999_000)));
5743 testST(beforeBoth1, -2000, SysTime(dtBoth1, hnsecs(9_998_000)));
5744 testST(beforeBoth1, -2555, SysTime(dtBoth1, hnsecs(9_997_445)));
5745 testST(beforeBoth1, -1_000_000, SysTime(dtBoth1, hnsecs(9_000_000)));
5746 testST(beforeBoth1, -2_000_000, SysTime(dtBoth1, hnsecs(8_000_000)));
5747 testST(beforeBoth1, -2_333_333, SysTime(dtBoth1, hnsecs(7_666_667)));
5748 testST(beforeBoth1, -10_000_000, SysTime(dtBoth1));
5749 testST(beforeBoth1, -20_000_000, SysTime(dtBoth1));
5750 testST(beforeBoth1, -20_888_888, SysTime(dtBoth1, hnsecs(9_111_112)));
5751
5752 auto dtBoth2 = DateTime(0, 12, 31, 23, 59, 59);
5753 auto beforeBoth2 = SysTime(dtBoth2, hnsecs(9_999_999));
5754 testST(beforeBoth2, -1, SysTime(dtBoth2, hnsecs(9_999_998)));
5755 testST(beforeBoth2, 0, SysTime(dtBoth2, hnsecs(9_999_999)));
5756 testST(beforeBoth2, 1, SysTime(dtBoth2));
5757 testST(beforeBoth2, 2, SysTime(dtBoth2, hnsecs(1)));
5758 testST(beforeBoth2, 1000, SysTime(dtBoth2, hnsecs(999)));
5759 testST(beforeBoth2, 2000, SysTime(dtBoth2, hnsecs(1999)));
5760 testST(beforeBoth2, 2555, SysTime(dtBoth2, hnsecs(2554)));
5761 testST(beforeBoth2, 1_000_000, SysTime(dtBoth2, hnsecs(999_999)));
5762 testST(beforeBoth2, 2_000_000, SysTime(dtBoth2, hnsecs(1_999_999)));
5763 testST(beforeBoth2, 2_333_333, SysTime(dtBoth2, hnsecs(2_333_332)));
5764 testST(beforeBoth2, 10_000_000, SysTime(dtBoth2, hnsecs(9_999_999)));
5765 testST(beforeBoth2, 20_000_000, SysTime(dtBoth2, hnsecs(9_999_999)));
5766 testST(beforeBoth2, 20_888_888, SysTime(dtBoth2, hnsecs(888_887)));
5767
5768 {
5769 auto st = SysTime(dtBoth2, hnsecs(9_999_999));
5770 st.roll!"hnsecs"(70_777_222).roll!"hnsecs"(-222_555_292);
5771 assert(st == SysTime(dtBoth2, hnsecs(8_221_929)));
5772 }
5773
5774 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5775 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5776 static assert(!__traits(compiles, cst.roll!"hnsecs"(4)));
5777 //static assert(!__traits(compiles, ist.roll!"hnsecs"(4)));
5778 }
5779
5780
5781 /++
5782 Gives the result of adding or subtracting a $(REF Duration, core,time)
5783 from this $(LREF SysTime).
5784
5785 The legal types of arithmetic for $(LREF SysTime) using this operator
5786 are
5787
5788 $(BOOKTABLE,
5789 $(TR $(TD SysTime) $(TD +) $(TD Duration) $(TD -->) $(TD SysTime))
5790 $(TR $(TD SysTime) $(TD -) $(TD Duration) $(TD -->) $(TD SysTime))
5791 )
5792
5793 Params:
5794 duration = The $(REF Duration, core,time) to add to or subtract from
5795 this $(LREF SysTime).
5796 +/
5797 SysTime opBinary(string op)(Duration duration) @safe const pure nothrow
5798 if (op == "+" || op == "-")
5799 {
5800 SysTime retval = SysTime(this._stdTime, this._timezone);
5801 immutable hnsecs = duration.total!"hnsecs";
5802 mixin("retval._stdTime " ~ op ~ "= hnsecs;");
5803 return retval;
5804 }
5805
5806 ///
5807 @safe unittest
5808 {
5809 import core.time : hours, seconds;
5810 import std.datetime.date : DateTime;
5811
5812 assert(SysTime(DateTime(2015, 12, 31, 23, 59, 59)) + seconds(1) ==
5813 SysTime(DateTime(2016, 1, 1, 0, 0, 0)));
5814
5815 assert(SysTime(DateTime(2015, 12, 31, 23, 59, 59)) + hours(1) ==
5816 SysTime(DateTime(2016, 1, 1, 0, 59, 59)));
5817
5818 assert(SysTime(DateTime(2016, 1, 1, 0, 0, 0)) - seconds(1) ==
5819 SysTime(DateTime(2015, 12, 31, 23, 59, 59)));
5820
5821 assert(SysTime(DateTime(2016, 1, 1, 0, 59, 59)) - hours(1) ==
5822 SysTime(DateTime(2015, 12, 31, 23, 59, 59)));
5823 }
5824
5825 @safe unittest
5826 {
5827 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_678));
5828
5829 assert(st + dur!"weeks"(7) == SysTime(DateTime(1999, 8, 24, 12, 30, 33), hnsecs(2_345_678)));
5830 assert(st + dur!"weeks"(-7) == SysTime(DateTime(1999, 5, 18, 12, 30, 33), hnsecs(2_345_678)));
5831 assert(st + dur!"days"(7) == SysTime(DateTime(1999, 7, 13, 12, 30, 33), hnsecs(2_345_678)));
5832 assert(st + dur!"days"(-7) == SysTime(DateTime(1999, 6, 29, 12, 30, 33), hnsecs(2_345_678)));
5833 assert(st + dur!"hours"(7) == SysTime(DateTime(1999, 7, 6, 19, 30, 33), hnsecs(2_345_678)));
5834 assert(st + dur!"hours"(-7) == SysTime(DateTime(1999, 7, 6, 5, 30, 33), hnsecs(2_345_678)));
5835 assert(st + dur!"minutes"(7) == SysTime(DateTime(1999, 7, 6, 12, 37, 33), hnsecs(2_345_678)));
5836 assert(st + dur!"minutes"(-7) == SysTime(DateTime(1999, 7, 6, 12, 23, 33), hnsecs(2_345_678)));
5837 assert(st + dur!"seconds"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 40), hnsecs(2_345_678)));
5838 assert(st + dur!"seconds"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 26), hnsecs(2_345_678)));
5839 assert(st + dur!"msecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_415_678)));
5840 assert(st + dur!"msecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_275_678)));
5841 assert(st + dur!"usecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_748)));
5842 assert(st + dur!"usecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_608)));
5843 assert(st + dur!"hnsecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_685)));
5844 assert(st + dur!"hnsecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_671)));
5845
5846 assert(st - dur!"weeks"(-7) == SysTime(DateTime(1999, 8, 24, 12, 30, 33), hnsecs(2_345_678)));
5847 assert(st - dur!"weeks"(7) == SysTime(DateTime(1999, 5, 18, 12, 30, 33), hnsecs(2_345_678)));
5848 assert(st - dur!"days"(-7) == SysTime(DateTime(1999, 7, 13, 12, 30, 33), hnsecs(2_345_678)));
5849 assert(st - dur!"days"(7) == SysTime(DateTime(1999, 6, 29, 12, 30, 33), hnsecs(2_345_678)));
5850 assert(st - dur!"hours"(-7) == SysTime(DateTime(1999, 7, 6, 19, 30, 33), hnsecs(2_345_678)));
5851 assert(st - dur!"hours"(7) == SysTime(DateTime(1999, 7, 6, 5, 30, 33), hnsecs(2_345_678)));
5852 assert(st - dur!"minutes"(-7) == SysTime(DateTime(1999, 7, 6, 12, 37, 33), hnsecs(2_345_678)));
5853 assert(st - dur!"minutes"(7) == SysTime(DateTime(1999, 7, 6, 12, 23, 33), hnsecs(2_345_678)));
5854 assert(st - dur!"seconds"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 40), hnsecs(2_345_678)));
5855 assert(st - dur!"seconds"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 26), hnsecs(2_345_678)));
5856 assert(st - dur!"msecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_415_678)));
5857 assert(st - dur!"msecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_275_678)));
5858 assert(st - dur!"usecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_748)));
5859 assert(st - dur!"usecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_608)));
5860 assert(st - dur!"hnsecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_685)));
5861 assert(st - dur!"hnsecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_671)));
5862
5863 static void testST(in SysTime orig, long hnsecs, in SysTime expected, size_t line = __LINE__)
5864 {
5865 auto result = orig + dur!"hnsecs"(hnsecs);
5866 if (result != expected)
5867 throw new AssertError(format("Failed. actual [%s] != expected [%s]", result, expected), __FILE__, line);
5868 }
5869
5870 // Test A.D.
5871 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(274));
5872 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(274)));
5873 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(275)));
5874 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(276)));
5875 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(284)));
5876 testST(beforeAD, 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(374)));
5877 testST(beforeAD, 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(999)));
5878 testST(beforeAD, 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1000)));
5879 testST(beforeAD, 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1274)));
5880 testST(beforeAD, 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1275)));
5881 testST(beforeAD, 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2274)));
5882 testST(beforeAD, 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(26_999)));
5883 testST(beforeAD, 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(27_000)));
5884 testST(beforeAD, 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(27_001)));
5885 testST(beforeAD, 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_766_999)));
5886 testST(beforeAD, 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_767_000)));
5887 testST(beforeAD, 1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_000_274)));
5888 testST(beforeAD, 60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 39), hnsecs(274)));
5889 testST(beforeAD, 3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 36, 33), hnsecs(274)));
5890 testST(beforeAD, 600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 31, 33), hnsecs(274)));
5891 testST(beforeAD, 36_000_000_000L, SysTime(DateTime(1999, 7, 6, 13, 30, 33), hnsecs(274)));
5892
5893 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(273)));
5894 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(272)));
5895 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(264)));
5896 testST(beforeAD, -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(174)));
5897 testST(beforeAD, -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5898 testST(beforeAD, -275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_999)));
5899 testST(beforeAD, -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_274)));
5900 testST(beforeAD, -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_273)));
5901 testST(beforeAD, -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_998_274)));
5902 testST(beforeAD, -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_967_000)));
5903 testST(beforeAD, -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_966_999)));
5904 testST(beforeAD, -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(8_167_000)));
5905 testST(beforeAD, -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(8_166_999)));
5906 testST(beforeAD, -1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_000_274)));
5907 testST(beforeAD, -60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 27), hnsecs(274)));
5908 testST(beforeAD, -3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 24, 33), hnsecs(274)));
5909 testST(beforeAD, -600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 29, 33), hnsecs(274)));
5910 testST(beforeAD, -36_000_000_000L, SysTime(DateTime(1999, 7, 6, 11, 30, 33), hnsecs(274)));
5911
5912 // Test B.C.
5913 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(274));
5914 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(274)));
5915 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(275)));
5916 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(276)));
5917 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(284)));
5918 testST(beforeBC, 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(374)));
5919 testST(beforeBC, 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(999)));
5920 testST(beforeBC, 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1000)));
5921 testST(beforeBC, 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1274)));
5922 testST(beforeBC, 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1275)));
5923 testST(beforeBC, 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(2274)));
5924 testST(beforeBC, 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(26_999)));
5925 testST(beforeBC, 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(27_000)));
5926 testST(beforeBC, 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(27_001)));
5927 testST(beforeBC, 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_766_999)));
5928 testST(beforeBC, 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_767_000)));
5929 testST(beforeBC, 1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_000_274)));
5930 testST(beforeBC, 60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 39), hnsecs(274)));
5931 testST(beforeBC, 3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 36, 33), hnsecs(274)));
5932 testST(beforeBC, 600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), hnsecs(274)));
5933 testST(beforeBC, 36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), hnsecs(274)));
5934
5935 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(273)));
5936 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(272)));
5937 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(264)));
5938 testST(beforeBC, -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(174)));
5939 testST(beforeBC, -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5940 testST(beforeBC, -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_999)));
5941 testST(beforeBC, -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_274)));
5942 testST(beforeBC, -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_273)));
5943 testST(beforeBC, -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_998_274)));
5944 testST(beforeBC, -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_967_000)));
5945 testST(beforeBC, -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_966_999)));
5946 testST(beforeBC, -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(8_167_000)));
5947 testST(beforeBC, -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(8_166_999)));
5948 testST(beforeBC, -1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_000_274)));
5949 testST(beforeBC, -60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 27), hnsecs(274)));
5950 testST(beforeBC, -3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 24, 33), hnsecs(274)));
5951 testST(beforeBC, -600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), hnsecs(274)));
5952 testST(beforeBC, -36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), hnsecs(274)));
5953
5954 // Test Both
5955 auto beforeBoth1 = SysTime(DateTime(1, 1, 1, 0, 0, 0));
5956 testST(beforeBoth1, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)));
5957 testST(beforeBoth1, 0, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5958 testST(beforeBoth1, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5959 testST(beforeBoth1, -2, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_998)));
5960 testST(beforeBoth1, -1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_000)));
5961 testST(beforeBoth1, -2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_998_000)));
5962 testST(beforeBoth1, -2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_997_445)));
5963 testST(beforeBoth1, -1_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_000_000)));
5964 testST(beforeBoth1, -2_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(8_000_000)));
5965 testST(beforeBoth1, -2_333_333, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(7_666_667)));
5966 testST(beforeBoth1, -10_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59)));
5967 testST(beforeBoth1, -20_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 58)));
5968 testST(beforeBoth1, -20_888_888, SysTime(DateTime(0, 12, 31, 23, 59, 57), hnsecs(9_111_112)));
5969
5970 auto beforeBoth2 = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5971 testST(beforeBoth2, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_998)));
5972 testST(beforeBoth2, 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5973 testST(beforeBoth2, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5974 testST(beforeBoth2, 2, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)));
5975 testST(beforeBoth2, 1000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(999)));
5976 testST(beforeBoth2, 2000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1999)));
5977 testST(beforeBoth2, 2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(2554)));
5978 testST(beforeBoth2, 1_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(999_999)));
5979 testST(beforeBoth2, 2_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1_999_999)));
5980 testST(beforeBoth2, 2_333_333, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(2_333_332)));
5981 testST(beforeBoth2, 10_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
5982 testST(beforeBoth2, 20_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 1), hnsecs(9_999_999)));
5983 testST(beforeBoth2, 20_888_888, SysTime(DateTime(1, 1, 1, 0, 0, 2), hnsecs(888_887)));
5984
5985 auto duration = dur!"seconds"(12);
5986 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5987 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5988 assert(cst + duration == SysTime(DateTime(1999, 7, 6, 12, 30, 45)));
5989 //assert(ist + duration == SysTime(DateTime(1999, 7, 6, 12, 30, 45)));
5990 assert(cst - duration == SysTime(DateTime(1999, 7, 6, 12, 30, 21)));
5991 //assert(ist - duration == SysTime(DateTime(1999, 7, 6, 12, 30, 21)));
5992 }
5993
5994
5995 /++
5996 Gives the result of adding or subtracting a $(REF Duration, core,time) from
5997 this $(LREF SysTime), as well as assigning the result to this
5998 $(LREF SysTime).
5999
6000 The legal types of arithmetic for $(LREF SysTime) using this operator are
6001
6002 $(BOOKTABLE,
6003 $(TR $(TD SysTime) $(TD +) $(TD Duration) $(TD -->) $(TD SysTime))
6004 $(TR $(TD SysTime) $(TD -) $(TD Duration) $(TD -->) $(TD SysTime))
6005 )
6006
6007 Params:
6008 duration = The $(REF Duration, core,time) to add to or subtract from
6009 this $(LREF SysTime).
6010 +/
6011 ref SysTime opOpAssign(string op)(Duration duration) @safe pure nothrow
6012 if (op == "+" || op == "-")
6013 {
6014 immutable hnsecs = duration.total!"hnsecs";
6015 mixin("_stdTime " ~ op ~ "= hnsecs;");
6016 return this;
6017 }
6018
6019 @safe unittest
6020 {
6021 auto before = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6022 assert(before + dur!"weeks"(7) == SysTime(DateTime(1999, 8, 24, 12, 30, 33)));
6023 assert(before + dur!"weeks"(-7) == SysTime(DateTime(1999, 5, 18, 12, 30, 33)));
6024 assert(before + dur!"days"(7) == SysTime(DateTime(1999, 7, 13, 12, 30, 33)));
6025 assert(before + dur!"days"(-7) == SysTime(DateTime(1999, 6, 29, 12, 30, 33)));
6026
6027 assert(before + dur!"hours"(7) == SysTime(DateTime(1999, 7, 6, 19, 30, 33)));
6028 assert(before + dur!"hours"(-7) == SysTime(DateTime(1999, 7, 6, 5, 30, 33)));
6029 assert(before + dur!"minutes"(7) == SysTime(DateTime(1999, 7, 6, 12, 37, 33)));
6030 assert(before + dur!"minutes"(-7) == SysTime(DateTime(1999, 7, 6, 12, 23, 33)));
6031 assert(before + dur!"seconds"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 40)));
6032 assert(before + dur!"seconds"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 26)));
6033 assert(before + dur!"msecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(7)));
6034 assert(before + dur!"msecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), msecs(993)));
6035 assert(before + dur!"usecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(7)));
6036 assert(before + dur!"usecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), usecs(999_993)));
6037 assert(before + dur!"hnsecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(7)));
6038 assert(before + dur!"hnsecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_993)));
6039
6040 assert(before - dur!"weeks"(-7) == SysTime(DateTime(1999, 8, 24, 12, 30, 33)));
6041 assert(before - dur!"weeks"(7) == SysTime(DateTime(1999, 5, 18, 12, 30, 33)));
6042 assert(before - dur!"days"(-7) == SysTime(DateTime(1999, 7, 13, 12, 30, 33)));
6043 assert(before - dur!"days"(7) == SysTime(DateTime(1999, 6, 29, 12, 30, 33)));
6044
6045 assert(before - dur!"hours"(-7) == SysTime(DateTime(1999, 7, 6, 19, 30, 33)));
6046 assert(before - dur!"hours"(7) == SysTime(DateTime(1999, 7, 6, 5, 30, 33)));
6047 assert(before - dur!"minutes"(-7) == SysTime(DateTime(1999, 7, 6, 12, 37, 33)));
6048 assert(before - dur!"minutes"(7) == SysTime(DateTime(1999, 7, 6, 12, 23, 33)));
6049 assert(before - dur!"seconds"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 40)));
6050 assert(before - dur!"seconds"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 26)));
6051 assert(before - dur!"msecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(7)));
6052 assert(before - dur!"msecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), msecs(993)));
6053 assert(before - dur!"usecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(7)));
6054 assert(before - dur!"usecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), usecs(999_993)));
6055 assert(before - dur!"hnsecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(7)));
6056 assert(before - dur!"hnsecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_993)));
6057
6058 static void testST(SysTime orig, long hnsecs, in SysTime expected, size_t line = __LINE__)
6059 {
6060 auto r = orig += dur!"hnsecs"(hnsecs);
6061 if (orig != expected)
6062 throw new AssertError(format("Failed 1. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
6063 if (r != expected)
6064 throw new AssertError(format("Failed 2. actual [%s] != expected [%s]", r, expected), __FILE__, line);
6065 }
6066
6067 // Test A.D.
6068 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(274));
6069 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(274)));
6070 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(275)));
6071 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(276)));
6072 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(284)));
6073 testST(beforeAD, 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(374)));
6074 testST(beforeAD, 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(999)));
6075 testST(beforeAD, 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1000)));
6076 testST(beforeAD, 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1274)));
6077 testST(beforeAD, 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1275)));
6078 testST(beforeAD, 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2274)));
6079 testST(beforeAD, 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(26_999)));
6080 testST(beforeAD, 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(27_000)));
6081 testST(beforeAD, 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(27_001)));
6082 testST(beforeAD, 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_766_999)));
6083 testST(beforeAD, 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_767_000)));
6084 testST(beforeAD, 1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_000_274)));
6085 testST(beforeAD, 60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 39), hnsecs(274)));
6086 testST(beforeAD, 3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 36, 33), hnsecs(274)));
6087 testST(beforeAD, 600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 31, 33), hnsecs(274)));
6088 testST(beforeAD, 36_000_000_000L, SysTime(DateTime(1999, 7, 6, 13, 30, 33), hnsecs(274)));
6089
6090 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(273)));
6091 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(272)));
6092 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(264)));
6093 testST(beforeAD, -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(174)));
6094 testST(beforeAD, -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
6095 testST(beforeAD, -275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_999)));
6096 testST(beforeAD, -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_274)));
6097 testST(beforeAD, -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_273)));
6098 testST(beforeAD, -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_998_274)));
6099 testST(beforeAD, -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_967_000)));
6100 testST(beforeAD, -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_966_999)));
6101 testST(beforeAD, -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(8_167_000)));
6102 testST(beforeAD, -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(8_166_999)));
6103 testST(beforeAD, -1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_000_274)));
6104 testST(beforeAD, -60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 27), hnsecs(274)));
6105 testST(beforeAD, -3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 24, 33), hnsecs(274)));
6106 testST(beforeAD, -600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 29, 33), hnsecs(274)));
6107 testST(beforeAD, -36_000_000_000L, SysTime(DateTime(1999, 7, 6, 11, 30, 33), hnsecs(274)));
6108
6109 // Test B.C.
6110 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(274));
6111 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(274)));
6112 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(275)));
6113 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(276)));
6114 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(284)));
6115 testST(beforeBC, 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(374)));
6116 testST(beforeBC, 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(999)));
6117 testST(beforeBC, 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1000)));
6118 testST(beforeBC, 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1274)));
6119 testST(beforeBC, 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1275)));
6120 testST(beforeBC, 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(2274)));
6121 testST(beforeBC, 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(26_999)));
6122 testST(beforeBC, 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(27_000)));
6123 testST(beforeBC, 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(27_001)));
6124 testST(beforeBC, 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_766_999)));
6125 testST(beforeBC, 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_767_000)));
6126 testST(beforeBC, 1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_000_274)));
6127 testST(beforeBC, 60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 39), hnsecs(274)));
6128 testST(beforeBC, 3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 36, 33), hnsecs(274)));
6129 testST(beforeBC, 600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), hnsecs(274)));
6130 testST(beforeBC, 36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), hnsecs(274)));
6131
6132 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(273)));
6133 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(272)));
6134 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(264)));
6135 testST(beforeBC, -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(174)));
6136 testST(beforeBC, -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
6137 testST(beforeBC, -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_999)));
6138 testST(beforeBC, -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_274)));
6139 testST(beforeBC, -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_273)));
6140 testST(beforeBC, -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_998_274)));
6141 testST(beforeBC, -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_967_000)));
6142 testST(beforeBC, -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_966_999)));
6143 testST(beforeBC, -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(8_167_000)));
6144 testST(beforeBC, -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(8_166_999)));
6145 testST(beforeBC, -1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_000_274)));
6146 testST(beforeBC, -60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 27), hnsecs(274)));
6147 testST(beforeBC, -3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 24, 33), hnsecs(274)));
6148 testST(beforeBC, -600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), hnsecs(274)));
6149 testST(beforeBC, -36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), hnsecs(274)));
6150
6151 // Test Both
6152 auto beforeBoth1 = SysTime(DateTime(1, 1, 1, 0, 0, 0));
6153 testST(beforeBoth1, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)));
6154 testST(beforeBoth1, 0, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6155 testST(beforeBoth1, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6156 testST(beforeBoth1, -2, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_998)));
6157 testST(beforeBoth1, -1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_000)));
6158 testST(beforeBoth1, -2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_998_000)));
6159 testST(beforeBoth1, -2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_997_445)));
6160 testST(beforeBoth1, -1_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_000_000)));
6161 testST(beforeBoth1, -2_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(8_000_000)));
6162 testST(beforeBoth1, -2_333_333, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(7_666_667)));
6163 testST(beforeBoth1, -10_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59)));
6164 testST(beforeBoth1, -20_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 58)));
6165 testST(beforeBoth1, -20_888_888, SysTime(DateTime(0, 12, 31, 23, 59, 57), hnsecs(9_111_112)));
6166
6167 auto beforeBoth2 = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
6168 testST(beforeBoth2, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_998)));
6169 testST(beforeBoth2, 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6170 testST(beforeBoth2, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6171 testST(beforeBoth2, 2, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)));
6172 testST(beforeBoth2, 1000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(999)));
6173 testST(beforeBoth2, 2000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1999)));
6174 testST(beforeBoth2, 2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(2554)));
6175 testST(beforeBoth2, 1_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(999_999)));
6176 testST(beforeBoth2, 2_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1_999_999)));
6177 testST(beforeBoth2, 2_333_333, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(2_333_332)));
6178 testST(beforeBoth2, 10_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
6179 testST(beforeBoth2, 20_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 1), hnsecs(9_999_999)));
6180 testST(beforeBoth2, 20_888_888, SysTime(DateTime(1, 1, 1, 0, 0, 2), hnsecs(888_887)));
6181
6182 {
6183 auto st = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
6184 (st += dur!"hnsecs"(52)) += dur!"seconds"(-907);
6185 assert(st == SysTime(DateTime(0, 12, 31, 23, 44, 53), hnsecs(51)));
6186 }
6187
6188 auto duration = dur!"seconds"(12);
6189 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6190 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6191 static assert(!__traits(compiles, cst += duration));
6192 //static assert(!__traits(compiles, ist += duration));
6193 static assert(!__traits(compiles, cst -= duration));
6194 //static assert(!__traits(compiles, ist -= duration));
6195 }
6196
6197
6198 /++
6199 Gives the difference between two $(LREF SysTime)s.
6200
6201 The legal types of arithmetic for $(LREF SysTime) using this operator
6202 are
6203
6204 $(BOOKTABLE,
6205 $(TR $(TD SysTime) $(TD -) $(TD SysTime) $(TD -->) $(TD duration))
6206 )
6207 +/
6208 Duration opBinary(string op)(in SysTime rhs) @safe const pure nothrow
6209 if (op == "-")
6210 {
6211 return dur!"hnsecs"(_stdTime - rhs._stdTime);
6212 }
6213
6214 @safe unittest
6215 {
6216 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1998, 7, 6, 12, 30, 33)) ==
6217 dur!"seconds"(31_536_000));
6218 assert(SysTime(DateTime(1998, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) ==
6219 dur!"seconds"(-31_536_000));
6220
6221 assert(SysTime(DateTime(1999, 8, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) ==
6222 dur!"seconds"(26_78_400));
6223 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 8, 6, 12, 30, 33)) ==
6224 dur!"seconds"(-26_78_400));
6225
6226 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 5, 12, 30, 33)) ==
6227 dur!"seconds"(86_400));
6228 assert(SysTime(DateTime(1999, 7, 5, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) ==
6229 dur!"seconds"(-86_400));
6230
6231 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 11, 30, 33)) ==
6232 dur!"seconds"(3600));
6233 assert(SysTime(DateTime(1999, 7, 6, 11, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) ==
6234 dur!"seconds"(-3600));
6235
6236 assert(SysTime(DateTime(1999, 7, 6, 12, 31, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) ==
6237 dur!"seconds"(60));
6238 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 31, 33)) ==
6239 dur!"seconds"(-60));
6240
6241 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 34)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) ==
6242 dur!"seconds"(1));
6243 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 34)) ==
6244 dur!"seconds"(-1));
6245
6246 {
6247 auto dt = DateTime(1999, 7, 6, 12, 30, 33);
6248 assert(SysTime(dt, msecs(532)) - SysTime(dt) == msecs(532));
6249 assert(SysTime(dt) - SysTime(dt, msecs(532)) == msecs(-532));
6250
6251 assert(SysTime(dt, usecs(333_347)) - SysTime(dt) == usecs(333_347));
6252 assert(SysTime(dt) - SysTime(dt, usecs(333_347)) == usecs(-333_347));
6253
6254 assert(SysTime(dt, hnsecs(1_234_567)) - SysTime(dt) == hnsecs(1_234_567));
6255 assert(SysTime(dt) - SysTime(dt, hnsecs(1_234_567)) == hnsecs(-1_234_567));
6256 }
6257
6258 assert(SysTime(DateTime(1, 1, 1, 12, 30, 33)) - SysTime(DateTime(1, 1, 1, 0, 0, 0)) == dur!"seconds"(45033));
6259 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)) - SysTime(DateTime(1, 1, 1, 12, 30, 33)) == dur!"seconds"(-45033));
6260 assert(SysTime(DateTime(0, 12, 31, 12, 30, 33)) - SysTime(DateTime(1, 1, 1, 0, 0, 0)) == dur!"seconds"(-41367));
6261 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)) - SysTime(DateTime(0, 12, 31, 12, 30, 33)) == dur!"seconds"(41367));
6262
6263 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)) - SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)) ==
6264 dur!"hnsecs"(1));
6265 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)) - SysTime(DateTime(1, 1, 1, 0, 0, 0)) ==
6266 dur!"hnsecs"(-1));
6267
6268 version (Posix)
6269 immutable tz = PosixTimeZone.getTimeZone("America/Los_Angeles");
6270 else version (Windows)
6271 immutable tz = WindowsTimeZone.getTimeZone("Pacific Standard Time");
6272
6273 {
6274 auto dt = DateTime(2011, 1, 13, 8, 17, 2);
6275 auto d = msecs(296);
6276 assert(SysTime(dt, d, tz) - SysTime(dt, d, tz) == Duration.zero);
6277 assert(SysTime(dt, d, tz) - SysTime(dt, d, UTC()) == hours(8));
6278 assert(SysTime(dt, d, UTC()) - SysTime(dt, d, tz) == hours(-8));
6279 }
6280
6281 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6282 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6283 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6284 assert(st - st == Duration.zero);
6285 assert(cst - st == Duration.zero);
6286 //assert(ist - st == Duration.zero);
6287
6288 assert(st - cst == Duration.zero);
6289 assert(cst - cst == Duration.zero);
6290 //assert(ist - cst == Duration.zero);
6291
6292 //assert(st - ist == Duration.zero);
6293 //assert(cst - ist == Duration.zero);
6294 //assert(ist - ist == Duration.zero);
6295 }
6296
6297
6298 /++
6299 Returns the difference between the two $(LREF SysTime)s in months.
6300
6301 To get the difference in years, subtract the year property
6302 of two $(LREF SysTime)s. To get the difference in days or weeks,
6303 subtract the $(LREF SysTime)s themselves and use the
6304 $(REF Duration, core,time) that results. Because converting between
6305 months and smaller units requires a specific date (which
6306 $(REF Duration, core,time)s don't have), getting the difference in
6307 months requires some math using both the year and month properties, so
6308 this is a convenience function for getting the difference in months.
6309
6310 Note that the number of days in the months or how far into the month
6311 either date is is irrelevant. It is the difference in the month property
6312 combined with the difference in years * 12. So, for instance,
6313 December 31st and January 1st are one month apart just as December 1st
6314 and January 31st are one month apart.
6315
6316 Params:
6317 rhs = The $(LREF SysTime) to subtract from this one.
6318 +/
6319 int diffMonths(in SysTime rhs) @safe const nothrow
6320 {
6321 return (cast(Date) this).diffMonths(cast(Date) rhs);
6322 }
6323
6324 ///
6325 @safe unittest
6326 {
6327 import std.datetime.date : Date;
6328
6329 assert(SysTime(Date(1999, 2, 1)).diffMonths(
6330 SysTime(Date(1999, 1, 31))) == 1);
6331
6332 assert(SysTime(Date(1999, 1, 31)).diffMonths(
6333 SysTime(Date(1999, 2, 1))) == -1);
6334
6335 assert(SysTime(Date(1999, 3, 1)).diffMonths(
6336 SysTime(Date(1999, 1, 1))) == 2);
6337
6338 assert(SysTime(Date(1999, 1, 1)).diffMonths(
6339 SysTime(Date(1999, 3, 31))) == -2);
6340 }
6341
6342 @safe unittest
6343 {
6344 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6345 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6346 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6347 assert(st.diffMonths(st) == 0);
6348 assert(cst.diffMonths(st) == 0);
6349 //assert(ist.diffMonths(st) == 0);
6350
6351 assert(st.diffMonths(cst) == 0);
6352 assert(cst.diffMonths(cst) == 0);
6353 //assert(ist.diffMonths(cst) == 0);
6354
6355 //assert(st.diffMonths(ist) == 0);
6356 //assert(cst.diffMonths(ist) == 0);
6357 //assert(ist.diffMonths(ist) == 0);
6358 }
6359
6360
6361 /++
6362 Whether this $(LREF SysTime) is in a leap year.
6363 +/
6364 @property bool isLeapYear() @safe const nothrow
6365 {
6366 return (cast(Date) this).isLeapYear;
6367 }
6368
6369 @safe unittest
6370 {
6371 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6372 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6373 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6374 assert(!st.isLeapYear);
6375 assert(!cst.isLeapYear);
6376 //assert(!ist.isLeapYear);
6377 }
6378
6379
6380 /++
6381 Day of the week this $(LREF SysTime) is on.
6382 +/
6383 @property DayOfWeek dayOfWeek() @safe const nothrow
6384 {
6385 return getDayOfWeek(dayOfGregorianCal);
6386 }
6387
6388 @safe unittest
6389 {
6390 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6391 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6392 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6393 assert(st.dayOfWeek == DayOfWeek.tue);
6394 assert(cst.dayOfWeek == DayOfWeek.tue);
6395 //assert(ist.dayOfWeek == DayOfWeek.tue);
6396 }
6397
6398
6399 /++
6400 Day of the year this $(LREF SysTime) is on.
6401 +/
6402 @property ushort dayOfYear() @safe const nothrow
6403 {
6404 return (cast(Date) this).dayOfYear;
6405 }
6406
6407 ///
6408 @safe unittest
6409 {
6410 import std.datetime.date : DateTime;
6411
6412 assert(SysTime(DateTime(1999, 1, 1, 12, 22, 7)).dayOfYear == 1);
6413 assert(SysTime(DateTime(1999, 12, 31, 7, 2, 59)).dayOfYear == 365);
6414 assert(SysTime(DateTime(2000, 12, 31, 21, 20, 0)).dayOfYear == 366);
6415 }
6416
6417 @safe unittest
6418 {
6419 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6420 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6421 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6422 assert(st.dayOfYear == 187);
6423 assert(cst.dayOfYear == 187);
6424 //assert(ist.dayOfYear == 187);
6425 }
6426
6427
6428 /++
6429 Day of the year.
6430
6431 Params:
6432 day = The day of the year to set which day of the year this
6433 $(LREF SysTime) is on.
6434 +/
6435 @property void dayOfYear(int day) @safe
6436 {
6437 immutable hnsecs = adjTime;
6438 immutable days = convert!("hnsecs", "days")(hnsecs);
6439 immutable theRest = hnsecs - convert!("days", "hnsecs")(days);
6440
6441 auto date = Date(cast(int) days);
6442 date.dayOfYear = day;
6443
6444 immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
6445
6446 adjTime = newDaysHNSecs + theRest;
6447 }
6448
6449 @safe unittest
6450 {
6451 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6452 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6453 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6454 st.dayOfYear = 12;
6455 assert(st.dayOfYear == 12);
6456 static assert(!__traits(compiles, cst.dayOfYear = 12));
6457 //static assert(!__traits(compiles, ist.dayOfYear = 12));
6458 }
6459
6460
6461 /++
6462 The Xth day of the Gregorian Calendar that this $(LREF SysTime) is on.
6463 +/
6464 @property int dayOfGregorianCal() @safe const nothrow
6465 {
6466 immutable adjustedTime = adjTime;
6467
6468 // We have to add one because 0 would be midnight, January 1st, 1 A.D.,
6469 // which would be the 1st day of the Gregorian Calendar, not the 0th. So,
6470 // simply casting to days is one day off.
6471 if (adjustedTime > 0)
6472 return cast(int) getUnitsFromHNSecs!"days"(adjustedTime) + 1;
6473
6474 long hnsecs = adjustedTime;
6475 immutable days = cast(int) splitUnitsFromHNSecs!"days"(hnsecs);
6476
6477 return hnsecs == 0 ? days + 1 : days;
6478 }
6479
6480 ///
6481 @safe unittest
6482 {
6483 import std.datetime.date : DateTime;
6484
6485 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).dayOfGregorianCal == 1);
6486 assert(SysTime(DateTime(1, 12, 31, 23, 59, 59)).dayOfGregorianCal == 365);
6487 assert(SysTime(DateTime(2, 1, 1, 2, 2, 2)).dayOfGregorianCal == 366);
6488
6489 assert(SysTime(DateTime(0, 12, 31, 7, 7, 7)).dayOfGregorianCal == 0);
6490 assert(SysTime(DateTime(0, 1, 1, 19, 30, 0)).dayOfGregorianCal == -365);
6491 assert(SysTime(DateTime(-1, 12, 31, 4, 7, 0)).dayOfGregorianCal == -366);
6492
6493 assert(SysTime(DateTime(2000, 1, 1, 9, 30, 20)).dayOfGregorianCal == 730_120);
6494 assert(SysTime(DateTime(2010, 12, 31, 15, 45, 50)).dayOfGregorianCal == 734_137);
6495 }
6496
6497 @safe unittest
6498 {
6499 // Test A.D.
6500 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).dayOfGregorianCal == 1);
6501 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)).dayOfGregorianCal == 1);
6502 assert(SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)).dayOfGregorianCal == 1);
6503
6504 assert(SysTime(DateTime(1, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 1);
6505 assert(SysTime(DateTime(1, 1, 2, 12, 2, 9), msecs(212)).dayOfGregorianCal == 2);
6506 assert(SysTime(DateTime(1, 2, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 32);
6507 assert(SysTime(DateTime(2, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 366);
6508 assert(SysTime(DateTime(3, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 731);
6509 assert(SysTime(DateTime(4, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 1096);
6510 assert(SysTime(DateTime(5, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 1462);
6511 assert(SysTime(DateTime(50, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 17_898);
6512 assert(SysTime(DateTime(97, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 35_065);
6513 assert(SysTime(DateTime(100, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 36_160);
6514 assert(SysTime(DateTime(101, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 36_525);
6515 assert(SysTime(DateTime(105, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 37_986);
6516 assert(SysTime(DateTime(200, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 72_684);
6517 assert(SysTime(DateTime(201, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 73_049);
6518 assert(SysTime(DateTime(300, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 109_208);
6519 assert(SysTime(DateTime(301, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 109_573);
6520 assert(SysTime(DateTime(400, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 145_732);
6521 assert(SysTime(DateTime(401, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 146_098);
6522 assert(SysTime(DateTime(500, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 182_257);
6523 assert(SysTime(DateTime(501, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 182_622);
6524 assert(SysTime(DateTime(1000, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 364_878);
6525 assert(SysTime(DateTime(1001, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 365_243);
6526 assert(SysTime(DateTime(1600, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 584_023);
6527 assert(SysTime(DateTime(1601, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 584_389);
6528 assert(SysTime(DateTime(1900, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 693_596);
6529 assert(SysTime(DateTime(1901, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 693_961);
6530 assert(SysTime(DateTime(1945, 11, 12, 12, 2, 9), msecs(212)).dayOfGregorianCal == 710_347);
6531 assert(SysTime(DateTime(1999, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 729_755);
6532 assert(SysTime(DateTime(2000, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 730_120);
6533 assert(SysTime(DateTime(2001, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 730_486);
6534
6535 assert(SysTime(DateTime(2010, 1, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_773);
6536 assert(SysTime(DateTime(2010, 1, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_803);
6537 assert(SysTime(DateTime(2010, 2, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_804);
6538 assert(SysTime(DateTime(2010, 2, 28, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_831);
6539 assert(SysTime(DateTime(2010, 3, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_832);
6540 assert(SysTime(DateTime(2010, 3, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_862);
6541 assert(SysTime(DateTime(2010, 4, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_863);
6542 assert(SysTime(DateTime(2010, 4, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_892);
6543 assert(SysTime(DateTime(2010, 5, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_893);
6544 assert(SysTime(DateTime(2010, 5, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_923);
6545 assert(SysTime(DateTime(2010, 6, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_924);
6546 assert(SysTime(DateTime(2010, 6, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_953);
6547 assert(SysTime(DateTime(2010, 7, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_954);
6548 assert(SysTime(DateTime(2010, 7, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_984);
6549 assert(SysTime(DateTime(2010, 8, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_985);
6550 assert(SysTime(DateTime(2010, 8, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_015);
6551 assert(SysTime(DateTime(2010, 9, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_016);
6552 assert(SysTime(DateTime(2010, 9, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_045);
6553 assert(SysTime(DateTime(2010, 10, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_046);
6554 assert(SysTime(DateTime(2010, 10, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_076);
6555 assert(SysTime(DateTime(2010, 11, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_077);
6556 assert(SysTime(DateTime(2010, 11, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_106);
6557 assert(SysTime(DateTime(2010, 12, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_107);
6558 assert(SysTime(DateTime(2010, 12, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_137);
6559
6560 assert(SysTime(DateTime(2012, 2, 1, 0, 0, 0)).dayOfGregorianCal == 734_534);
6561 assert(SysTime(DateTime(2012, 2, 28, 0, 0, 0)).dayOfGregorianCal == 734_561);
6562 assert(SysTime(DateTime(2012, 2, 29, 0, 0, 0)).dayOfGregorianCal == 734_562);
6563 assert(SysTime(DateTime(2012, 3, 1, 0, 0, 0)).dayOfGregorianCal == 734_563);
6564
6565 // Test B.C.
6566 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)).dayOfGregorianCal == 0);
6567 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_998)).dayOfGregorianCal == 0);
6568 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59)).dayOfGregorianCal == 0);
6569 assert(SysTime(DateTime(0, 12, 31, 0, 0, 0), hnsecs(1)).dayOfGregorianCal == 0);
6570 assert(SysTime(DateTime(0, 12, 31, 0, 0, 0)).dayOfGregorianCal == 0);
6571
6572 assert(SysTime(DateTime(-1, 12, 31, 23, 59, 59), hnsecs(9_999_999)).dayOfGregorianCal == -366);
6573 assert(SysTime(DateTime(-1, 12, 31, 23, 59, 59), hnsecs(9_999_998)).dayOfGregorianCal == -366);
6574 assert(SysTime(DateTime(-1, 12, 31, 23, 59, 59)).dayOfGregorianCal == -366);
6575 assert(SysTime(DateTime(-1, 12, 31, 0, 0, 0)).dayOfGregorianCal == -366);
6576
6577 assert(SysTime(DateTime(0, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == 0);
6578 assert(SysTime(DateTime(0, 12, 30, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1);
6579 assert(SysTime(DateTime(0, 12, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -30);
6580 assert(SysTime(DateTime(0, 11, 30, 12, 2, 9), msecs(212)).dayOfGregorianCal == -31);
6581
6582 assert(SysTime(DateTime(-1, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -366);
6583 assert(SysTime(DateTime(-1, 12, 30, 12, 2, 9), msecs(212)).dayOfGregorianCal == -367);
6584 assert(SysTime(DateTime(-1, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -730);
6585 assert(SysTime(DateTime(-2, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -731);
6586 assert(SysTime(DateTime(-2, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1095);
6587 assert(SysTime(DateTime(-3, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1096);
6588 assert(SysTime(DateTime(-3, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1460);
6589 assert(SysTime(DateTime(-4, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1461);
6590 assert(SysTime(DateTime(-4, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1826);
6591 assert(SysTime(DateTime(-5, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1827);
6592 assert(SysTime(DateTime(-5, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -2191);
6593 assert(SysTime(DateTime(-9, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -3652);
6594
6595 assert(SysTime(DateTime(-49, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -18_262);
6596 assert(SysTime(DateTime(-50, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -18_627);
6597 assert(SysTime(DateTime(-97, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -35_794);
6598 assert(SysTime(DateTime(-99, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -36_160);
6599 assert(SysTime(DateTime(-99, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -36_524);
6600 assert(SysTime(DateTime(-100, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -36_889);
6601 assert(SysTime(DateTime(-101, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -37_254);
6602 assert(SysTime(DateTime(-105, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -38_715);
6603 assert(SysTime(DateTime(-200, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -73_413);
6604 assert(SysTime(DateTime(-201, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -73_778);
6605 assert(SysTime(DateTime(-300, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -109_937);
6606 assert(SysTime(DateTime(-301, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -110_302);
6607 assert(SysTime(DateTime(-400, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -146_097);
6608 assert(SysTime(DateTime(-400, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -146_462);
6609 assert(SysTime(DateTime(-401, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -146_827);
6610 assert(SysTime(DateTime(-499, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -182_621);
6611 assert(SysTime(DateTime(-500, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -182_986);
6612 assert(SysTime(DateTime(-501, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -183_351);
6613 assert(SysTime(DateTime(-1000, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -365_607);
6614 assert(SysTime(DateTime(-1001, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -365_972);
6615 assert(SysTime(DateTime(-1599, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -584_387);
6616 assert(SysTime(DateTime(-1600, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -584_388);
6617 assert(SysTime(DateTime(-1600, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -584_753);
6618 assert(SysTime(DateTime(-1601, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -585_118);
6619 assert(SysTime(DateTime(-1900, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -694_325);
6620 assert(SysTime(DateTime(-1901, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -694_690);
6621 assert(SysTime(DateTime(-1999, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -730_484);
6622 assert(SysTime(DateTime(-2000, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -730_485);
6623 assert(SysTime(DateTime(-2000, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -730_850);
6624 assert(SysTime(DateTime(-2001, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -731_215);
6625
6626 assert(SysTime(DateTime(-2010, 1, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_502);
6627 assert(SysTime(DateTime(-2010, 1, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_472);
6628 assert(SysTime(DateTime(-2010, 2, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_471);
6629 assert(SysTime(DateTime(-2010, 2, 28, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_444);
6630 assert(SysTime(DateTime(-2010, 3, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_443);
6631 assert(SysTime(DateTime(-2010, 3, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_413);
6632 assert(SysTime(DateTime(-2010, 4, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_412);
6633 assert(SysTime(DateTime(-2010, 4, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_383);
6634 assert(SysTime(DateTime(-2010, 5, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_382);
6635 assert(SysTime(DateTime(-2010, 5, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_352);
6636 assert(SysTime(DateTime(-2010, 6, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_351);
6637 assert(SysTime(DateTime(-2010, 6, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_322);
6638 assert(SysTime(DateTime(-2010, 7, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_321);
6639 assert(SysTime(DateTime(-2010, 7, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_291);
6640 assert(SysTime(DateTime(-2010, 8, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_290);
6641 assert(SysTime(DateTime(-2010, 8, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_260);
6642 assert(SysTime(DateTime(-2010, 9, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_259);
6643 assert(SysTime(DateTime(-2010, 9, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_230);
6644 assert(SysTime(DateTime(-2010, 10, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_229);
6645 assert(SysTime(DateTime(-2010, 10, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_199);
6646 assert(SysTime(DateTime(-2010, 11, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_198);
6647 assert(SysTime(DateTime(-2010, 11, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_169);
6648 assert(SysTime(DateTime(-2010, 12, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_168);
6649 assert(SysTime(DateTime(-2010, 12, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_138);
6650
6651 assert(SysTime(DateTime(-2012, 2, 1, 0, 0, 0)).dayOfGregorianCal == -735_202);
6652 assert(SysTime(DateTime(-2012, 2, 28, 0, 0, 0)).dayOfGregorianCal == -735_175);
6653 assert(SysTime(DateTime(-2012, 2, 29, 0, 0, 0)).dayOfGregorianCal == -735_174);
6654 assert(SysTime(DateTime(-2012, 3, 1, 0, 0, 0)).dayOfGregorianCal == -735_173);
6655
6656 // Start of Hebrew Calendar
6657 assert(SysTime(DateTime(-3760, 9, 7, 0, 0, 0)).dayOfGregorianCal == -1_373_427);
6658
6659 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6660 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6661 assert(cst.dayOfGregorianCal == 729_941);
6662 //assert(ist.dayOfGregorianCal == 729_941);
6663 }
6664
6665
6666 // Test that the logic for the day of the Gregorian Calendar is consistent
6667 // between Date and SysTime.
6668 @safe unittest
6669 {
6670 void test(Date date, SysTime st, size_t line = __LINE__)
6671 {
6672 if (date.dayOfGregorianCal != st.dayOfGregorianCal)
6673 {
6674 throw new AssertError(format("Date [%s] SysTime [%s]", date.dayOfGregorianCal, st.dayOfGregorianCal),
6675 __FILE__, line);
6676 }
6677 }
6678
6679 // Test A.D.
6680 test(Date(1, 1, 1), SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6681 test(Date(1, 1, 2), SysTime(DateTime(1, 1, 2, 0, 0, 0), hnsecs(500)));
6682 test(Date(1, 2, 1), SysTime(DateTime(1, 2, 1, 0, 0, 0), hnsecs(50_000)));
6683 test(Date(2, 1, 1), SysTime(DateTime(2, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
6684 test(Date(3, 1, 1), SysTime(DateTime(3, 1, 1, 12, 13, 14)));
6685 test(Date(4, 1, 1), SysTime(DateTime(4, 1, 1, 12, 13, 14), hnsecs(500)));
6686 test(Date(5, 1, 1), SysTime(DateTime(5, 1, 1, 12, 13, 14), hnsecs(50_000)));
6687 test(Date(50, 1, 1), SysTime(DateTime(50, 1, 1, 12, 13, 14), hnsecs(9_999_999)));
6688 test(Date(97, 1, 1), SysTime(DateTime(97, 1, 1, 23, 59, 59)));
6689 test(Date(100, 1, 1), SysTime(DateTime(100, 1, 1, 23, 59, 59), hnsecs(500)));
6690 test(Date(101, 1, 1), SysTime(DateTime(101, 1, 1, 23, 59, 59), hnsecs(50_000)));
6691 test(Date(105, 1, 1), SysTime(DateTime(105, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
6692 test(Date(200, 1, 1), SysTime(DateTime(200, 1, 1, 0, 0, 0)));
6693 test(Date(201, 1, 1), SysTime(DateTime(201, 1, 1, 0, 0, 0), hnsecs(500)));
6694 test(Date(300, 1, 1), SysTime(DateTime(300, 1, 1, 0, 0, 0), hnsecs(50_000)));
6695 test(Date(301, 1, 1), SysTime(DateTime(301, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
6696 test(Date(400, 1, 1), SysTime(DateTime(400, 1, 1, 12, 13, 14)));
6697 test(Date(401, 1, 1), SysTime(DateTime(401, 1, 1, 12, 13, 14), hnsecs(500)));
6698 test(Date(500, 1, 1), SysTime(DateTime(500, 1, 1, 12, 13, 14), hnsecs(50_000)));
6699 test(Date(501, 1, 1), SysTime(DateTime(501, 1, 1, 12, 13, 14), hnsecs(9_999_999)));
6700 test(Date(1000, 1, 1), SysTime(DateTime(1000, 1, 1, 23, 59, 59)));
6701 test(Date(1001, 1, 1), SysTime(DateTime(1001, 1, 1, 23, 59, 59), hnsecs(500)));
6702 test(Date(1600, 1, 1), SysTime(DateTime(1600, 1, 1, 23, 59, 59), hnsecs(50_000)));
6703 test(Date(1601, 1, 1), SysTime(DateTime(1601, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
6704 test(Date(1900, 1, 1), SysTime(DateTime(1900, 1, 1, 0, 0, 0)));
6705 test(Date(1901, 1, 1), SysTime(DateTime(1901, 1, 1, 0, 0, 0), hnsecs(500)));
6706 test(Date(1945, 11, 12), SysTime(DateTime(1945, 11, 12, 0, 0, 0), hnsecs(50_000)));
6707 test(Date(1999, 1, 1), SysTime(DateTime(1999, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
6708 test(Date(1999, 7, 6), SysTime(DateTime(1999, 7, 6, 12, 13, 14)));
6709 test(Date(2000, 1, 1), SysTime(DateTime(2000, 1, 1, 12, 13, 14), hnsecs(500)));
6710 test(Date(2001, 1, 1), SysTime(DateTime(2001, 1, 1, 12, 13, 14), hnsecs(50_000)));
6711
6712 test(Date(2010, 1, 1), SysTime(DateTime(2010, 1, 1, 12, 13, 14), hnsecs(9_999_999)));
6713 test(Date(2010, 1, 31), SysTime(DateTime(2010, 1, 31, 23, 0, 0)));
6714 test(Date(2010, 2, 1), SysTime(DateTime(2010, 2, 1, 23, 59, 59), hnsecs(500)));
6715 test(Date(2010, 2, 28), SysTime(DateTime(2010, 2, 28, 23, 59, 59), hnsecs(50_000)));
6716 test(Date(2010, 3, 1), SysTime(DateTime(2010, 3, 1, 23, 59, 59), hnsecs(9_999_999)));
6717 test(Date(2010, 3, 31), SysTime(DateTime(2010, 3, 31, 0, 0, 0)));
6718 test(Date(2010, 4, 1), SysTime(DateTime(2010, 4, 1, 0, 0, 0), hnsecs(500)));
6719 test(Date(2010, 4, 30), SysTime(DateTime(2010, 4, 30, 0, 0, 0), hnsecs(50_000)));
6720 test(Date(2010, 5, 1), SysTime(DateTime(2010, 5, 1, 0, 0, 0), hnsecs(9_999_999)));
6721 test(Date(2010, 5, 31), SysTime(DateTime(2010, 5, 31, 12, 13, 14)));
6722 test(Date(2010, 6, 1), SysTime(DateTime(2010, 6, 1, 12, 13, 14), hnsecs(500)));
6723 test(Date(2010, 6, 30), SysTime(DateTime(2010, 6, 30, 12, 13, 14), hnsecs(50_000)));
6724 test(Date(2010, 7, 1), SysTime(DateTime(2010, 7, 1, 12, 13, 14), hnsecs(9_999_999)));
6725 test(Date(2010, 7, 31), SysTime(DateTime(2010, 7, 31, 23, 59, 59)));
6726 test(Date(2010, 8, 1), SysTime(DateTime(2010, 8, 1, 23, 59, 59), hnsecs(500)));
6727 test(Date(2010, 8, 31), SysTime(DateTime(2010, 8, 31, 23, 59, 59), hnsecs(50_000)));
6728 test(Date(2010, 9, 1), SysTime(DateTime(2010, 9, 1, 23, 59, 59), hnsecs(9_999_999)));
6729 test(Date(2010, 9, 30), SysTime(DateTime(2010, 9, 30, 12, 0, 0)));
6730 test(Date(2010, 10, 1), SysTime(DateTime(2010, 10, 1, 0, 12, 0), hnsecs(500)));
6731 test(Date(2010, 10, 31), SysTime(DateTime(2010, 10, 31, 0, 0, 12), hnsecs(50_000)));
6732 test(Date(2010, 11, 1), SysTime(DateTime(2010, 11, 1, 23, 0, 0), hnsecs(9_999_999)));
6733 test(Date(2010, 11, 30), SysTime(DateTime(2010, 11, 30, 0, 59, 0)));
6734 test(Date(2010, 12, 1), SysTime(DateTime(2010, 12, 1, 0, 0, 59), hnsecs(500)));
6735 test(Date(2010, 12, 31), SysTime(DateTime(2010, 12, 31, 0, 59, 59), hnsecs(50_000)));
6736
6737 test(Date(2012, 2, 1), SysTime(DateTime(2012, 2, 1, 23, 0, 59), hnsecs(9_999_999)));
6738 test(Date(2012, 2, 28), SysTime(DateTime(2012, 2, 28, 23, 59, 0)));
6739 test(Date(2012, 2, 29), SysTime(DateTime(2012, 2, 29, 7, 7, 7), hnsecs(7)));
6740 test(Date(2012, 3, 1), SysTime(DateTime(2012, 3, 1, 7, 7, 7), hnsecs(7)));
6741
6742 // Test B.C.
6743 test(Date(0, 12, 31), SysTime(DateTime(0, 12, 31, 0, 0, 0)));
6744 test(Date(0, 12, 30), SysTime(DateTime(0, 12, 30, 0, 0, 0), hnsecs(500)));
6745 test(Date(0, 12, 1), SysTime(DateTime(0, 12, 1, 0, 0, 0), hnsecs(50_000)));
6746 test(Date(0, 11, 30), SysTime(DateTime(0, 11, 30, 0, 0, 0), hnsecs(9_999_999)));
6747
6748 test(Date(-1, 12, 31), SysTime(DateTime(-1, 12, 31, 12, 13, 14)));
6749 test(Date(-1, 12, 30), SysTime(DateTime(-1, 12, 30, 12, 13, 14), hnsecs(500)));
6750 test(Date(-1, 1, 1), SysTime(DateTime(-1, 1, 1, 12, 13, 14), hnsecs(50_000)));
6751 test(Date(-2, 12, 31), SysTime(DateTime(-2, 12, 31, 12, 13, 14), hnsecs(9_999_999)));
6752 test(Date(-2, 1, 1), SysTime(DateTime(-2, 1, 1, 23, 59, 59)));
6753 test(Date(-3, 12, 31), SysTime(DateTime(-3, 12, 31, 23, 59, 59), hnsecs(500)));
6754 test(Date(-3, 1, 1), SysTime(DateTime(-3, 1, 1, 23, 59, 59), hnsecs(50_000)));
6755 test(Date(-4, 12, 31), SysTime(DateTime(-4, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6756 test(Date(-4, 1, 1), SysTime(DateTime(-4, 1, 1, 0, 0, 0)));
6757 test(Date(-5, 12, 31), SysTime(DateTime(-5, 12, 31, 0, 0, 0), hnsecs(500)));
6758 test(Date(-5, 1, 1), SysTime(DateTime(-5, 1, 1, 0, 0, 0), hnsecs(50_000)));
6759 test(Date(-9, 1, 1), SysTime(DateTime(-9, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
6760
6761 test(Date(-49, 1, 1), SysTime(DateTime(-49, 1, 1, 12, 13, 14)));
6762 test(Date(-50, 1, 1), SysTime(DateTime(-50, 1, 1, 12, 13, 14), hnsecs(500)));
6763 test(Date(-97, 1, 1), SysTime(DateTime(-97, 1, 1, 12, 13, 14), hnsecs(50_000)));
6764 test(Date(-99, 12, 31), SysTime(DateTime(-99, 12, 31, 12, 13, 14), hnsecs(9_999_999)));
6765 test(Date(-99, 1, 1), SysTime(DateTime(-99, 1, 1, 23, 59, 59)));
6766 test(Date(-100, 1, 1), SysTime(DateTime(-100, 1, 1, 23, 59, 59), hnsecs(500)));
6767 test(Date(-101, 1, 1), SysTime(DateTime(-101, 1, 1, 23, 59, 59), hnsecs(50_000)));
6768 test(Date(-105, 1, 1), SysTime(DateTime(-105, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
6769 test(Date(-200, 1, 1), SysTime(DateTime(-200, 1, 1, 0, 0, 0)));
6770 test(Date(-201, 1, 1), SysTime(DateTime(-201, 1, 1, 0, 0, 0), hnsecs(500)));
6771 test(Date(-300, 1, 1), SysTime(DateTime(-300, 1, 1, 0, 0, 0), hnsecs(50_000)));
6772 test(Date(-301, 1, 1), SysTime(DateTime(-301, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
6773 test(Date(-400, 12, 31), SysTime(DateTime(-400, 12, 31, 12, 13, 14)));
6774 test(Date(-400, 1, 1), SysTime(DateTime(-400, 1, 1, 12, 13, 14), hnsecs(500)));
6775 test(Date(-401, 1, 1), SysTime(DateTime(-401, 1, 1, 12, 13, 14), hnsecs(50_000)));
6776 test(Date(-499, 1, 1), SysTime(DateTime(-499, 1, 1, 12, 13, 14), hnsecs(9_999_999)));
6777 test(Date(-500, 1, 1), SysTime(DateTime(-500, 1, 1, 23, 59, 59)));
6778 test(Date(-501, 1, 1), SysTime(DateTime(-501, 1, 1, 23, 59, 59), hnsecs(500)));
6779 test(Date(-1000, 1, 1), SysTime(DateTime(-1000, 1, 1, 23, 59, 59), hnsecs(50_000)));
6780 test(Date(-1001, 1, 1), SysTime(DateTime(-1001, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
6781 test(Date(-1599, 1, 1), SysTime(DateTime(-1599, 1, 1, 0, 0, 0)));
6782 test(Date(-1600, 12, 31), SysTime(DateTime(-1600, 12, 31, 0, 0, 0), hnsecs(500)));
6783 test(Date(-1600, 1, 1), SysTime(DateTime(-1600, 1, 1, 0, 0, 0), hnsecs(50_000)));
6784 test(Date(-1601, 1, 1), SysTime(DateTime(-1601, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
6785 test(Date(-1900, 1, 1), SysTime(DateTime(-1900, 1, 1, 12, 13, 14)));
6786 test(Date(-1901, 1, 1), SysTime(DateTime(-1901, 1, 1, 12, 13, 14), hnsecs(500)));
6787 test(Date(-1999, 1, 1), SysTime(DateTime(-1999, 1, 1, 12, 13, 14), hnsecs(50_000)));
6788 test(Date(-1999, 7, 6), SysTime(DateTime(-1999, 7, 6, 12, 13, 14), hnsecs(9_999_999)));
6789 test(Date(-2000, 12, 31), SysTime(DateTime(-2000, 12, 31, 23, 59, 59)));
6790 test(Date(-2000, 1, 1), SysTime(DateTime(-2000, 1, 1, 23, 59, 59), hnsecs(500)));
6791 test(Date(-2001, 1, 1), SysTime(DateTime(-2001, 1, 1, 23, 59, 59), hnsecs(50_000)));
6792
6793 test(Date(-2010, 1, 1), SysTime(DateTime(-2010, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
6794 test(Date(-2010, 1, 31), SysTime(DateTime(-2010, 1, 31, 0, 0, 0)));
6795 test(Date(-2010, 2, 1), SysTime(DateTime(-2010, 2, 1, 0, 0, 0), hnsecs(500)));
6796 test(Date(-2010, 2, 28), SysTime(DateTime(-2010, 2, 28, 0, 0, 0), hnsecs(50_000)));
6797 test(Date(-2010, 3, 1), SysTime(DateTime(-2010, 3, 1, 0, 0, 0), hnsecs(9_999_999)));
6798 test(Date(-2010, 3, 31), SysTime(DateTime(-2010, 3, 31, 12, 13, 14)));
6799 test(Date(-2010, 4, 1), SysTime(DateTime(-2010, 4, 1, 12, 13, 14), hnsecs(500)));
6800 test(Date(-2010, 4, 30), SysTime(DateTime(-2010, 4, 30, 12, 13, 14), hnsecs(50_000)));
6801 test(Date(-2010, 5, 1), SysTime(DateTime(-2010, 5, 1, 12, 13, 14), hnsecs(9_999_999)));
6802 test(Date(-2010, 5, 31), SysTime(DateTime(-2010, 5, 31, 23, 59, 59)));
6803 test(Date(-2010, 6, 1), SysTime(DateTime(-2010, 6, 1, 23, 59, 59), hnsecs(500)));
6804 test(Date(-2010, 6, 30), SysTime(DateTime(-2010, 6, 30, 23, 59, 59), hnsecs(50_000)));
6805 test(Date(-2010, 7, 1), SysTime(DateTime(-2010, 7, 1, 23, 59, 59), hnsecs(9_999_999)));
6806 test(Date(-2010, 7, 31), SysTime(DateTime(-2010, 7, 31, 0, 0, 0)));
6807 test(Date(-2010, 8, 1), SysTime(DateTime(-2010, 8, 1, 0, 0, 0), hnsecs(500)));
6808 test(Date(-2010, 8, 31), SysTime(DateTime(-2010, 8, 31, 0, 0, 0), hnsecs(50_000)));
6809 test(Date(-2010, 9, 1), SysTime(DateTime(-2010, 9, 1, 0, 0, 0), hnsecs(9_999_999)));
6810 test(Date(-2010, 9, 30), SysTime(DateTime(-2010, 9, 30, 12, 0, 0)));
6811 test(Date(-2010, 10, 1), SysTime(DateTime(-2010, 10, 1, 0, 12, 0), hnsecs(500)));
6812 test(Date(-2010, 10, 31), SysTime(DateTime(-2010, 10, 31, 0, 0, 12), hnsecs(50_000)));
6813 test(Date(-2010, 11, 1), SysTime(DateTime(-2010, 11, 1, 23, 0, 0), hnsecs(9_999_999)));
6814 test(Date(-2010, 11, 30), SysTime(DateTime(-2010, 11, 30, 0, 59, 0)));
6815 test(Date(-2010, 12, 1), SysTime(DateTime(-2010, 12, 1, 0, 0, 59), hnsecs(500)));
6816 test(Date(-2010, 12, 31), SysTime(DateTime(-2010, 12, 31, 0, 59, 59), hnsecs(50_000)));
6817
6818 test(Date(-2012, 2, 1), SysTime(DateTime(-2012, 2, 1, 23, 0, 59), hnsecs(9_999_999)));
6819 test(Date(-2012, 2, 28), SysTime(DateTime(-2012, 2, 28, 23, 59, 0)));
6820 test(Date(-2012, 2, 29), SysTime(DateTime(-2012, 2, 29, 7, 7, 7), hnsecs(7)));
6821 test(Date(-2012, 3, 1), SysTime(DateTime(-2012, 3, 1, 7, 7, 7), hnsecs(7)));
6822
6823 test(Date(-3760, 9, 7), SysTime(DateTime(-3760, 9, 7, 0, 0, 0)));
6824 }
6825
6826
6827 /++
6828 The Xth day of the Gregorian Calendar that this $(LREF SysTime) is on.
6829 Setting this property does not affect the time portion of $(LREF SysTime).
6830
6831 Params:
6832 days = The day of the Gregorian Calendar to set this $(LREF SysTime)
6833 to.
6834 +/
6835 @property void dayOfGregorianCal(int days) @safe nothrow
6836 {
6837 auto hnsecs = adjTime;
6838 hnsecs = removeUnitsFromHNSecs!"days"(hnsecs);
6839
6840 if (hnsecs < 0)
6841 hnsecs += convert!("hours", "hnsecs")(24);
6842
6843 if (--days < 0)
6844 {
6845 hnsecs -= convert!("hours", "hnsecs")(24);
6846 ++days;
6847 }
6848
6849 immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
6850
6851 adjTime = newDaysHNSecs + hnsecs;
6852 }
6853
6854 ///
6855 @safe unittest
6856 {
6857 import std.datetime.date : DateTime;
6858
6859 auto st = SysTime(DateTime(0, 1, 1, 12, 0, 0));
6860 st.dayOfGregorianCal = 1;
6861 assert(st == SysTime(DateTime(1, 1, 1, 12, 0, 0)));
6862
6863 st.dayOfGregorianCal = 365;
6864 assert(st == SysTime(DateTime(1, 12, 31, 12, 0, 0)));
6865
6866 st.dayOfGregorianCal = 366;
6867 assert(st == SysTime(DateTime(2, 1, 1, 12, 0, 0)));
6868
6869 st.dayOfGregorianCal = 0;
6870 assert(st == SysTime(DateTime(0, 12, 31, 12, 0, 0)));
6871
6872 st.dayOfGregorianCal = -365;
6873 assert(st == SysTime(DateTime(-0, 1, 1, 12, 0, 0)));
6874
6875 st.dayOfGregorianCal = -366;
6876 assert(st == SysTime(DateTime(-1, 12, 31, 12, 0, 0)));
6877
6878 st.dayOfGregorianCal = 730_120;
6879 assert(st == SysTime(DateTime(2000, 1, 1, 12, 0, 0)));
6880
6881 st.dayOfGregorianCal = 734_137;
6882 assert(st == SysTime(DateTime(2010, 12, 31, 12, 0, 0)));
6883 }
6884
6885 @safe unittest
6886 {
6887 void testST(SysTime orig, int day, in SysTime expected, size_t line = __LINE__)
6888 {
6889 orig.dayOfGregorianCal = day;
6890 if (orig != expected)
6891 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
6892 }
6893
6894 // Test A.D.
6895 testST(SysTime(DateTime(1, 1, 1, 0, 0, 0)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6896 testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)));
6897 testST(SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)), 1,
6898 SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
6899
6900 // Test B.C.
6901 testST(SysTime(DateTime(0, 1, 1, 0, 0, 0)), 0, SysTime(DateTime(0, 12, 31, 0, 0, 0)));
6902 testST(SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)), 0,
6903 SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6904 testST(SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(1)), 0,
6905 SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1)));
6906 testST(SysTime(DateTime(0, 1, 1, 23, 59, 59)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59)));
6907
6908 // Test Both.
6909 testST(SysTime(DateTime(-512, 7, 20, 0, 0, 0)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6910 testST(SysTime(DateTime(-513, 6, 6, 0, 0, 0), hnsecs(1)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)));
6911 testST(SysTime(DateTime(-511, 5, 7, 23, 59, 59), hnsecs(9_999_999)), 1,
6912 SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
6913
6914 testST(SysTime(DateTime(1607, 4, 8, 0, 0, 0)), 0, SysTime(DateTime(0, 12, 31, 0, 0, 0)));
6915 testST(SysTime(DateTime(1500, 3, 9, 23, 59, 59), hnsecs(9_999_999)), 0,
6916 SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6917 testST(SysTime(DateTime(999, 2, 10, 23, 59, 59), hnsecs(1)), 0,
6918 SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1)));
6919 testST(SysTime(DateTime(2007, 12, 11, 23, 59, 59)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59)));
6920
6921
6922 auto st = SysTime(DateTime(1, 1, 1, 12, 2, 9), msecs(212));
6923
6924 void testST2(int day, in SysTime expected, size_t line = __LINE__)
6925 {
6926 st.dayOfGregorianCal = day;
6927 if (st != expected)
6928 throw new AssertError(format("Failed. actual [%s] != expected [%s]", st, expected), __FILE__, line);
6929 }
6930
6931 // Test A.D.
6932 testST2(1, SysTime(DateTime(1, 1, 1, 12, 2, 9), msecs(212)));
6933 testST2(2, SysTime(DateTime(1, 1, 2, 12, 2, 9), msecs(212)));
6934 testST2(32, SysTime(DateTime(1, 2, 1, 12, 2, 9), msecs(212)));
6935 testST2(366, SysTime(DateTime(2, 1, 1, 12, 2, 9), msecs(212)));
6936 testST2(731, SysTime(DateTime(3, 1, 1, 12, 2, 9), msecs(212)));
6937 testST2(1096, SysTime(DateTime(4, 1, 1, 12, 2, 9), msecs(212)));
6938 testST2(1462, SysTime(DateTime(5, 1, 1, 12, 2, 9), msecs(212)));
6939 testST2(17_898, SysTime(DateTime(50, 1, 1, 12, 2, 9), msecs(212)));
6940 testST2(35_065, SysTime(DateTime(97, 1, 1, 12, 2, 9), msecs(212)));
6941 testST2(36_160, SysTime(DateTime(100, 1, 1, 12, 2, 9), msecs(212)));
6942 testST2(36_525, SysTime(DateTime(101, 1, 1, 12, 2, 9), msecs(212)));
6943 testST2(37_986, SysTime(DateTime(105, 1, 1, 12, 2, 9), msecs(212)));
6944 testST2(72_684, SysTime(DateTime(200, 1, 1, 12, 2, 9), msecs(212)));
6945 testST2(73_049, SysTime(DateTime(201, 1, 1, 12, 2, 9), msecs(212)));
6946 testST2(109_208, SysTime(DateTime(300, 1, 1, 12, 2, 9), msecs(212)));
6947 testST2(109_573, SysTime(DateTime(301, 1, 1, 12, 2, 9), msecs(212)));
6948 testST2(145_732, SysTime(DateTime(400, 1, 1, 12, 2, 9), msecs(212)));
6949 testST2(146_098, SysTime(DateTime(401, 1, 1, 12, 2, 9), msecs(212)));
6950 testST2(182_257, SysTime(DateTime(500, 1, 1, 12, 2, 9), msecs(212)));
6951 testST2(182_622, SysTime(DateTime(501, 1, 1, 12, 2, 9), msecs(212)));
6952 testST2(364_878, SysTime(DateTime(1000, 1, 1, 12, 2, 9), msecs(212)));
6953 testST2(365_243, SysTime(DateTime(1001, 1, 1, 12, 2, 9), msecs(212)));
6954 testST2(584_023, SysTime(DateTime(1600, 1, 1, 12, 2, 9), msecs(212)));
6955 testST2(584_389, SysTime(DateTime(1601, 1, 1, 12, 2, 9), msecs(212)));
6956 testST2(693_596, SysTime(DateTime(1900, 1, 1, 12, 2, 9), msecs(212)));
6957 testST2(693_961, SysTime(DateTime(1901, 1, 1, 12, 2, 9), msecs(212)));
6958 testST2(729_755, SysTime(DateTime(1999, 1, 1, 12, 2, 9), msecs(212)));
6959 testST2(730_120, SysTime(DateTime(2000, 1, 1, 12, 2, 9), msecs(212)));
6960 testST2(730_486, SysTime(DateTime(2001, 1, 1, 12, 2, 9), msecs(212)));
6961
6962 testST2(733_773, SysTime(DateTime(2010, 1, 1, 12, 2, 9), msecs(212)));
6963 testST2(733_803, SysTime(DateTime(2010, 1, 31, 12, 2, 9), msecs(212)));
6964 testST2(733_804, SysTime(DateTime(2010, 2, 1, 12, 2, 9), msecs(212)));
6965 testST2(733_831, SysTime(DateTime(2010, 2, 28, 12, 2, 9), msecs(212)));
6966 testST2(733_832, SysTime(DateTime(2010, 3, 1, 12, 2, 9), msecs(212)));
6967 testST2(733_862, SysTime(DateTime(2010, 3, 31, 12, 2, 9), msecs(212)));
6968 testST2(733_863, SysTime(DateTime(2010, 4, 1, 12, 2, 9), msecs(212)));
6969 testST2(733_892, SysTime(DateTime(2010, 4, 30, 12, 2, 9), msecs(212)));
6970 testST2(733_893, SysTime(DateTime(2010, 5, 1, 12, 2, 9), msecs(212)));
6971 testST2(733_923, SysTime(DateTime(2010, 5, 31, 12, 2, 9), msecs(212)));
6972 testST2(733_924, SysTime(DateTime(2010, 6, 1, 12, 2, 9), msecs(212)));
6973 testST2(733_953, SysTime(DateTime(2010, 6, 30, 12, 2, 9), msecs(212)));
6974 testST2(733_954, SysTime(DateTime(2010, 7, 1, 12, 2, 9), msecs(212)));
6975 testST2(733_984, SysTime(DateTime(2010, 7, 31, 12, 2, 9), msecs(212)));
6976 testST2(733_985, SysTime(DateTime(2010, 8, 1, 12, 2, 9), msecs(212)));
6977 testST2(734_015, SysTime(DateTime(2010, 8, 31, 12, 2, 9), msecs(212)));
6978 testST2(734_016, SysTime(DateTime(2010, 9, 1, 12, 2, 9), msecs(212)));
6979 testST2(734_045, SysTime(DateTime(2010, 9, 30, 12, 2, 9), msecs(212)));
6980 testST2(734_046, SysTime(DateTime(2010, 10, 1, 12, 2, 9), msecs(212)));
6981 testST2(734_076, SysTime(DateTime(2010, 10, 31, 12, 2, 9), msecs(212)));
6982 testST2(734_077, SysTime(DateTime(2010, 11, 1, 12, 2, 9), msecs(212)));
6983 testST2(734_106, SysTime(DateTime(2010, 11, 30, 12, 2, 9), msecs(212)));
6984 testST2(734_107, SysTime(DateTime(2010, 12, 1, 12, 2, 9), msecs(212)));
6985 testST2(734_137, SysTime(DateTime(2010, 12, 31, 12, 2, 9), msecs(212)));
6986
6987 testST2(734_534, SysTime(DateTime(2012, 2, 1, 12, 2, 9), msecs(212)));
6988 testST2(734_561, SysTime(DateTime(2012, 2, 28, 12, 2, 9), msecs(212)));
6989 testST2(734_562, SysTime(DateTime(2012, 2, 29, 12, 2, 9), msecs(212)));
6990 testST2(734_563, SysTime(DateTime(2012, 3, 1, 12, 2, 9), msecs(212)));
6991
6992 testST2(734_534, SysTime(DateTime(2012, 2, 1, 12, 2, 9), msecs(212)));
6993
6994 testST2(734_561, SysTime(DateTime(2012, 2, 28, 12, 2, 9), msecs(212)));
6995 testST2(734_562, SysTime(DateTime(2012, 2, 29, 12, 2, 9), msecs(212)));
6996 testST2(734_563, SysTime(DateTime(2012, 3, 1, 12, 2, 9), msecs(212)));
6997
6998 // Test B.C.
6999 testST2(0, SysTime(DateTime(0, 12, 31, 12, 2, 9), msecs(212)));
7000 testST2(-1, SysTime(DateTime(0, 12, 30, 12, 2, 9), msecs(212)));
7001 testST2(-30, SysTime(DateTime(0, 12, 1, 12, 2, 9), msecs(212)));
7002 testST2(-31, SysTime(DateTime(0, 11, 30, 12, 2, 9), msecs(212)));
7003
7004 testST2(-366, SysTime(DateTime(-1, 12, 31, 12, 2, 9), msecs(212)));
7005 testST2(-367, SysTime(DateTime(-1, 12, 30, 12, 2, 9), msecs(212)));
7006 testST2(-730, SysTime(DateTime(-1, 1, 1, 12, 2, 9), msecs(212)));
7007 testST2(-731, SysTime(DateTime(-2, 12, 31, 12, 2, 9), msecs(212)));
7008 testST2(-1095, SysTime(DateTime(-2, 1, 1, 12, 2, 9), msecs(212)));
7009 testST2(-1096, SysTime(DateTime(-3, 12, 31, 12, 2, 9), msecs(212)));
7010 testST2(-1460, SysTime(DateTime(-3, 1, 1, 12, 2, 9), msecs(212)));
7011 testST2(-1461, SysTime(DateTime(-4, 12, 31, 12, 2, 9), msecs(212)));
7012 testST2(-1826, SysTime(DateTime(-4, 1, 1, 12, 2, 9), msecs(212)));
7013 testST2(-1827, SysTime(DateTime(-5, 12, 31, 12, 2, 9), msecs(212)));
7014 testST2(-2191, SysTime(DateTime(-5, 1, 1, 12, 2, 9), msecs(212)));
7015 testST2(-3652, SysTime(DateTime(-9, 1, 1, 12, 2, 9), msecs(212)));
7016
7017 testST2(-18_262, SysTime(DateTime(-49, 1, 1, 12, 2, 9), msecs(212)));
7018 testST2(-18_627, SysTime(DateTime(-50, 1, 1, 12, 2, 9), msecs(212)));
7019 testST2(-35_794, SysTime(DateTime(-97, 1, 1, 12, 2, 9), msecs(212)));
7020 testST2(-36_160, SysTime(DateTime(-99, 12, 31, 12, 2, 9), msecs(212)));
7021 testST2(-36_524, SysTime(DateTime(-99, 1, 1, 12, 2, 9), msecs(212)));
7022 testST2(-36_889, SysTime(DateTime(-100, 1, 1, 12, 2, 9), msecs(212)));
7023 testST2(-37_254, SysTime(DateTime(-101, 1, 1, 12, 2, 9), msecs(212)));
7024 testST2(-38_715, SysTime(DateTime(-105, 1, 1, 12, 2, 9), msecs(212)));
7025 testST2(-73_413, SysTime(DateTime(-200, 1, 1, 12, 2, 9), msecs(212)));
7026 testST2(-73_778, SysTime(DateTime(-201, 1, 1, 12, 2, 9), msecs(212)));
7027 testST2(-109_937, SysTime(DateTime(-300, 1, 1, 12, 2, 9), msecs(212)));
7028 testST2(-110_302, SysTime(DateTime(-301, 1, 1, 12, 2, 9), msecs(212)));
7029 testST2(-146_097, SysTime(DateTime(-400, 12, 31, 12, 2, 9), msecs(212)));
7030 testST2(-146_462, SysTime(DateTime(-400, 1, 1, 12, 2, 9), msecs(212)));
7031 testST2(-146_827, SysTime(DateTime(-401, 1, 1, 12, 2, 9), msecs(212)));
7032 testST2(-182_621, SysTime(DateTime(-499, 1, 1, 12, 2, 9), msecs(212)));
7033 testST2(-182_986, SysTime(DateTime(-500, 1, 1, 12, 2, 9), msecs(212)));
7034 testST2(-183_351, SysTime(DateTime(-501, 1, 1, 12, 2, 9), msecs(212)));
7035 testST2(-365_607, SysTime(DateTime(-1000, 1, 1, 12, 2, 9), msecs(212)));
7036 testST2(-365_972, SysTime(DateTime(-1001, 1, 1, 12, 2, 9), msecs(212)));
7037 testST2(-584_387, SysTime(DateTime(-1599, 1, 1, 12, 2, 9), msecs(212)));
7038 testST2(-584_388, SysTime(DateTime(-1600, 12, 31, 12, 2, 9), msecs(212)));
7039 testST2(-584_753, SysTime(DateTime(-1600, 1, 1, 12, 2, 9), msecs(212)));
7040 testST2(-585_118, SysTime(DateTime(-1601, 1, 1, 12, 2, 9), msecs(212)));
7041 testST2(-694_325, SysTime(DateTime(-1900, 1, 1, 12, 2, 9), msecs(212)));
7042 testST2(-694_690, SysTime(DateTime(-1901, 1, 1, 12, 2, 9), msecs(212)));
7043 testST2(-730_484, SysTime(DateTime(-1999, 1, 1, 12, 2, 9), msecs(212)));
7044 testST2(-730_485, SysTime(DateTime(-2000, 12, 31, 12, 2, 9), msecs(212)));
7045 testST2(-730_850, SysTime(DateTime(-2000, 1, 1, 12, 2, 9), msecs(212)));
7046 testST2(-731_215, SysTime(DateTime(-2001, 1, 1, 12, 2, 9), msecs(212)));
7047
7048 testST2(-734_502, SysTime(DateTime(-2010, 1, 1, 12, 2, 9), msecs(212)));
7049 testST2(-734_472, SysTime(DateTime(-2010, 1, 31, 12, 2, 9), msecs(212)));
7050 testST2(-734_471, SysTime(DateTime(-2010, 2, 1, 12, 2, 9), msecs(212)));
7051 testST2(-734_444, SysTime(DateTime(-2010, 2, 28, 12, 2, 9), msecs(212)));
7052 testST2(-734_443, SysTime(DateTime(-2010, 3, 1, 12, 2, 9), msecs(212)));
7053 testST2(-734_413, SysTime(DateTime(-2010, 3, 31, 12, 2, 9), msecs(212)));
7054 testST2(-734_412, SysTime(DateTime(-2010, 4, 1, 12, 2, 9), msecs(212)));
7055 testST2(-734_383, SysTime(DateTime(-2010, 4, 30, 12, 2, 9), msecs(212)));
7056 testST2(-734_382, SysTime(DateTime(-2010, 5, 1, 12, 2, 9), msecs(212)));
7057 testST2(-734_352, SysTime(DateTime(-2010, 5, 31, 12, 2, 9), msecs(212)));
7058 testST2(-734_351, SysTime(DateTime(-2010, 6, 1, 12, 2, 9), msecs(212)));
7059 testST2(-734_322, SysTime(DateTime(-2010, 6, 30, 12, 2, 9), msecs(212)));
7060 testST2(-734_321, SysTime(DateTime(-2010, 7, 1, 12, 2, 9), msecs(212)));
7061 testST2(-734_291, SysTime(DateTime(-2010, 7, 31, 12, 2, 9), msecs(212)));
7062 testST2(-734_290, SysTime(DateTime(-2010, 8, 1, 12, 2, 9), msecs(212)));
7063 testST2(-734_260, SysTime(DateTime(-2010, 8, 31, 12, 2, 9), msecs(212)));
7064 testST2(-734_259, SysTime(DateTime(-2010, 9, 1, 12, 2, 9), msecs(212)));
7065 testST2(-734_230, SysTime(DateTime(-2010, 9, 30, 12, 2, 9), msecs(212)));
7066 testST2(-734_229, SysTime(DateTime(-2010, 10, 1, 12, 2, 9), msecs(212)));
7067 testST2(-734_199, SysTime(DateTime(-2010, 10, 31, 12, 2, 9), msecs(212)));
7068 testST2(-734_198, SysTime(DateTime(-2010, 11, 1, 12, 2, 9), msecs(212)));
7069 testST2(-734_169, SysTime(DateTime(-2010, 11, 30, 12, 2, 9), msecs(212)));
7070 testST2(-734_168, SysTime(DateTime(-2010, 12, 1, 12, 2, 9), msecs(212)));
7071 testST2(-734_138, SysTime(DateTime(-2010, 12, 31, 12, 2, 9), msecs(212)));
7072
7073 testST2(-735_202, SysTime(DateTime(-2012, 2, 1, 12, 2, 9), msecs(212)));
7074 testST2(-735_175, SysTime(DateTime(-2012, 2, 28, 12, 2, 9), msecs(212)));
7075 testST2(-735_174, SysTime(DateTime(-2012, 2, 29, 12, 2, 9), msecs(212)));
7076 testST2(-735_173, SysTime(DateTime(-2012, 3, 1, 12, 2, 9), msecs(212)));
7077
7078 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7079 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7080 static assert(!__traits(compiles, cst.dayOfGregorianCal = 7));
7081 //static assert(!__traits(compiles, ist.dayOfGregorianCal = 7));
7082 }
7083
7084
7085 /++
7086 The ISO 8601 week of the year that this $(LREF SysTime) is in.
7087
7088 See_Also:
7089 $(HTTP en.wikipedia.org/wiki/ISO_week_date, ISO Week Date).
7090 +/
7091 @property ubyte isoWeek() @safe const nothrow
7092 {
7093 return (cast(Date) this).isoWeek;
7094 }
7095
7096 ///
7097 @safe unittest
7098 {
7099 import std.datetime.date : Date;
7100
7101 auto st = SysTime(Date(1999, 7, 6));
7102 const cst = SysTime(Date(2010, 5, 1));
7103 immutable ist = SysTime(Date(2015, 10, 10));
7104
7105 assert(st.isoWeek == 27);
7106 assert(cst.isoWeek == 17);
7107 assert(ist.isoWeek == 41);
7108 }
7109
7110
7111 /++
7112 $(LREF SysTime) for the last day in the month that this Date is in.
7113 The time portion of endOfMonth is always 23:59:59.9999999.
7114 +/
7115 @property SysTime endOfMonth() @safe const nothrow
7116 {
7117 immutable hnsecs = adjTime;
7118 immutable days = getUnitsFromHNSecs!"days"(hnsecs);
7119
7120 auto date = Date(cast(int) days + 1).endOfMonth;
7121 auto newDays = date.dayOfGregorianCal - 1;
7122 long theTimeHNSecs;
7123
7124 if (newDays < 0)
7125 {
7126 theTimeHNSecs = -1;
7127 ++newDays;
7128 }
7129 else
7130 theTimeHNSecs = convert!("days", "hnsecs")(1) - 1;
7131
7132 immutable newDaysHNSecs = convert!("days", "hnsecs")(newDays);
7133
7134 auto retval = SysTime(this._stdTime, this._timezone);
7135 retval.adjTime = newDaysHNSecs + theTimeHNSecs;
7136
7137 return retval;
7138 }
7139
7140 ///
7141 @safe unittest
7142 {
7143 import core.time : msecs, usecs, hnsecs;
7144 import std.datetime.date : DateTime;
7145
7146 assert(SysTime(DateTime(1999, 1, 6, 0, 0, 0)).endOfMonth ==
7147 SysTime(DateTime(1999, 1, 31, 23, 59, 59), hnsecs(9_999_999)));
7148
7149 assert(SysTime(DateTime(1999, 2, 7, 19, 30, 0), msecs(24)).endOfMonth ==
7150 SysTime(DateTime(1999, 2, 28, 23, 59, 59), hnsecs(9_999_999)));
7151
7152 assert(SysTime(DateTime(2000, 2, 7, 5, 12, 27), usecs(5203)).endOfMonth ==
7153 SysTime(DateTime(2000, 2, 29, 23, 59, 59), hnsecs(9_999_999)));
7154
7155 assert(SysTime(DateTime(2000, 6, 4, 12, 22, 9), hnsecs(12345)).endOfMonth ==
7156 SysTime(DateTime(2000, 6, 30, 23, 59, 59), hnsecs(9_999_999)));
7157 }
7158
7159 @safe unittest
7160 {
7161 // Test A.D.
7162 assert(SysTime(Date(1999, 1, 1)).endOfMonth == SysTime(DateTime(1999, 1, 31, 23, 59, 59), hnsecs(9_999_999)));
7163 assert(SysTime(Date(1999, 2, 1)).endOfMonth == SysTime(DateTime(1999, 2, 28, 23, 59, 59), hnsecs(9_999_999)));
7164 assert(SysTime(Date(2000, 2, 1)).endOfMonth == SysTime(DateTime(2000, 2, 29, 23, 59, 59), hnsecs(9_999_999)));
7165 assert(SysTime(Date(1999, 3, 1)).endOfMonth == SysTime(DateTime(1999, 3, 31, 23, 59, 59), hnsecs(9_999_999)));
7166 assert(SysTime(Date(1999, 4, 1)).endOfMonth == SysTime(DateTime(1999, 4, 30, 23, 59, 59), hnsecs(9_999_999)));
7167 assert(SysTime(Date(1999, 5, 1)).endOfMonth == SysTime(DateTime(1999, 5, 31, 23, 59, 59), hnsecs(9_999_999)));
7168 assert(SysTime(Date(1999, 6, 1)).endOfMonth == SysTime(DateTime(1999, 6, 30, 23, 59, 59), hnsecs(9_999_999)));
7169 assert(SysTime(Date(1999, 7, 1)).endOfMonth == SysTime(DateTime(1999, 7, 31, 23, 59, 59), hnsecs(9_999_999)));
7170 assert(SysTime(Date(1999, 8, 1)).endOfMonth == SysTime(DateTime(1999, 8, 31, 23, 59, 59), hnsecs(9_999_999)));
7171 assert(SysTime(Date(1999, 9, 1)).endOfMonth == SysTime(DateTime(1999, 9, 30, 23, 59, 59), hnsecs(9_999_999)));
7172 assert(SysTime(Date(1999, 10, 1)).endOfMonth == SysTime(DateTime(1999, 10, 31, 23, 59, 59), hnsecs(9_999_999)));
7173 assert(SysTime(Date(1999, 11, 1)).endOfMonth == SysTime(DateTime(1999, 11, 30, 23, 59, 59), hnsecs(9_999_999)));
7174 assert(SysTime(Date(1999, 12, 1)).endOfMonth == SysTime(DateTime(1999, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
7175
7176 // Test B.C.
7177 assert(SysTime(Date(-1999, 1, 1)).endOfMonth == SysTime(DateTime(-1999, 1, 31, 23, 59, 59), hnsecs(9_999_999)));
7178 assert(SysTime(Date(-1999, 2, 1)).endOfMonth == SysTime(DateTime(-1999, 2, 28, 23, 59, 59), hnsecs(9_999_999)));
7179 assert(SysTime(Date(-2000, 2, 1)).endOfMonth == SysTime(DateTime(-2000, 2, 29, 23, 59, 59), hnsecs(9_999_999)));
7180 assert(SysTime(Date(-1999, 3, 1)).endOfMonth == SysTime(DateTime(-1999, 3, 31, 23, 59, 59), hnsecs(9_999_999)));
7181 assert(SysTime(Date(-1999, 4, 1)).endOfMonth == SysTime(DateTime(-1999, 4, 30, 23, 59, 59), hnsecs(9_999_999)));
7182 assert(SysTime(Date(-1999, 5, 1)).endOfMonth == SysTime(DateTime(-1999, 5, 31, 23, 59, 59), hnsecs(9_999_999)));
7183 assert(SysTime(Date(-1999, 6, 1)).endOfMonth == SysTime(DateTime(-1999, 6, 30, 23, 59, 59), hnsecs(9_999_999)));
7184 assert(SysTime(Date(-1999, 7, 1)).endOfMonth == SysTime(DateTime(-1999, 7, 31, 23, 59, 59), hnsecs(9_999_999)));
7185 assert(SysTime(Date(-1999, 8, 1)).endOfMonth == SysTime(DateTime(-1999, 8, 31, 23, 59, 59), hnsecs(9_999_999)));
7186 assert(SysTime(Date(-1999, 9, 1)).endOfMonth == SysTime(DateTime(-1999, 9, 30, 23, 59, 59), hnsecs(9_999_999)));
7187 assert(SysTime(Date(-1999, 10, 1)).endOfMonth ==
7188 SysTime(DateTime(-1999, 10, 31, 23, 59, 59), hnsecs(9_999_999)));
7189 assert(SysTime(Date(-1999, 11, 1)).endOfMonth ==
7190 SysTime(DateTime(-1999, 11, 30, 23, 59, 59), hnsecs(9_999_999)));
7191 assert(SysTime(Date(-1999, 12, 1)).endOfMonth ==
7192 SysTime(DateTime(-1999, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
7193
7194 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7195 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7196 assert(cst.endOfMonth == SysTime(DateTime(1999, 7, 31, 23, 59, 59), hnsecs(9_999_999)));
7197 //assert(ist.endOfMonth == SysTime(DateTime(1999, 7, 31, 23, 59, 59), hnsecs(9_999_999)));
7198 }
7199
7200
7201 /++
7202 The last day in the month that this $(LREF SysTime) is in.
7203 +/
7204 @property ubyte daysInMonth() @safe const nothrow
7205 {
7206 return Date(dayOfGregorianCal).daysInMonth;
7207 }
7208
7209 ///
7210 @safe unittest
7211 {
7212 import std.datetime.date : DateTime;
7213
7214 assert(SysTime(DateTime(1999, 1, 6, 0, 0, 0)).daysInMonth == 31);
7215 assert(SysTime(DateTime(1999, 2, 7, 19, 30, 0)).daysInMonth == 28);
7216 assert(SysTime(DateTime(2000, 2, 7, 5, 12, 27)).daysInMonth == 29);
7217 assert(SysTime(DateTime(2000, 6, 4, 12, 22, 9)).daysInMonth == 30);
7218 }
7219
7220 @safe unittest
7221 {
7222 // Test A.D.
7223 assert(SysTime(DateTime(1999, 1, 1, 12, 1, 13)).daysInMonth == 31);
7224 assert(SysTime(DateTime(1999, 2, 1, 17, 13, 12)).daysInMonth == 28);
7225 assert(SysTime(DateTime(2000, 2, 1, 13, 2, 12)).daysInMonth == 29);
7226 assert(SysTime(DateTime(1999, 3, 1, 12, 13, 12)).daysInMonth == 31);
7227 assert(SysTime(DateTime(1999, 4, 1, 12, 6, 13)).daysInMonth == 30);
7228 assert(SysTime(DateTime(1999, 5, 1, 15, 13, 12)).daysInMonth == 31);
7229 assert(SysTime(DateTime(1999, 6, 1, 13, 7, 12)).daysInMonth == 30);
7230 assert(SysTime(DateTime(1999, 7, 1, 12, 13, 17)).daysInMonth == 31);
7231 assert(SysTime(DateTime(1999, 8, 1, 12, 3, 13)).daysInMonth == 31);
7232 assert(SysTime(DateTime(1999, 9, 1, 12, 13, 12)).daysInMonth == 30);
7233 assert(SysTime(DateTime(1999, 10, 1, 13, 19, 12)).daysInMonth == 31);
7234 assert(SysTime(DateTime(1999, 11, 1, 12, 13, 17)).daysInMonth == 30);
7235 assert(SysTime(DateTime(1999, 12, 1, 12, 52, 13)).daysInMonth == 31);
7236
7237 // Test B.C.
7238 assert(SysTime(DateTime(-1999, 1, 1, 12, 1, 13)).daysInMonth == 31);
7239 assert(SysTime(DateTime(-1999, 2, 1, 7, 13, 12)).daysInMonth == 28);
7240 assert(SysTime(DateTime(-2000, 2, 1, 13, 2, 12)).daysInMonth == 29);
7241 assert(SysTime(DateTime(-1999, 3, 1, 12, 13, 12)).daysInMonth == 31);
7242 assert(SysTime(DateTime(-1999, 4, 1, 12, 6, 13)).daysInMonth == 30);
7243 assert(SysTime(DateTime(-1999, 5, 1, 5, 13, 12)).daysInMonth == 31);
7244 assert(SysTime(DateTime(-1999, 6, 1, 13, 7, 12)).daysInMonth == 30);
7245 assert(SysTime(DateTime(-1999, 7, 1, 12, 13, 17)).daysInMonth == 31);
7246 assert(SysTime(DateTime(-1999, 8, 1, 12, 3, 13)).daysInMonth == 31);
7247 assert(SysTime(DateTime(-1999, 9, 1, 12, 13, 12)).daysInMonth == 30);
7248 assert(SysTime(DateTime(-1999, 10, 1, 13, 19, 12)).daysInMonth == 31);
7249 assert(SysTime(DateTime(-1999, 11, 1, 12, 13, 17)).daysInMonth == 30);
7250 assert(SysTime(DateTime(-1999, 12, 1, 12, 52, 13)).daysInMonth == 31);
7251
7252 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7253 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7254 assert(cst.daysInMonth == 31);
7255 //assert(ist.daysInMonth == 31);
7256 }
7257
7258
7259 /++
7260 Whether the current year is a date in A.D.
7261 +/
7262 @property bool isAD() @safe const nothrow
7263 {
7264 return adjTime >= 0;
7265 }
7266
7267 ///
7268 @safe unittest
7269 {
7270 import std.datetime.date : DateTime;
7271
7272 assert(SysTime(DateTime(1, 1, 1, 12, 7, 0)).isAD);
7273 assert(SysTime(DateTime(2010, 12, 31, 0, 0, 0)).isAD);
7274 assert(!SysTime(DateTime(0, 12, 31, 23, 59, 59)).isAD);
7275 assert(!SysTime(DateTime(-2010, 1, 1, 2, 2, 2)).isAD);
7276 }
7277
7278 @safe unittest
7279 {
7280 assert(SysTime(DateTime(2010, 7, 4, 12, 0, 9)).isAD);
7281 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).isAD);
7282 assert(!SysTime(DateTime(0, 12, 31, 23, 59, 59)).isAD);
7283 assert(!SysTime(DateTime(0, 1, 1, 23, 59, 59)).isAD);
7284 assert(!SysTime(DateTime(-1, 1, 1, 23 ,59 ,59)).isAD);
7285 assert(!SysTime(DateTime(-2010, 7, 4, 12, 2, 2)).isAD);
7286
7287 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7288 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7289 assert(cst.isAD);
7290 //assert(ist.isAD);
7291 }
7292
7293
7294 /++
7295 The $(HTTP en.wikipedia.org/wiki/Julian_day, Julian day)
7296 for this $(LREF SysTime) at the given time. For example,
7297 prior to noon, 1996-03-31 would be the Julian day number 2_450_173, so
7298 this function returns 2_450_173, while from noon onward, the Julian
7299 day number would be 2_450_174, so this function returns 2_450_174.
7300 +/
7301 @property long julianDay() @safe const nothrow
7302 {
7303 immutable jd = dayOfGregorianCal + 1_721_425;
7304 return hour < 12 ? jd - 1 : jd;
7305 }
7306
7307 @safe unittest
7308 {
7309 assert(SysTime(DateTime(-4713, 11, 24, 0, 0, 0)).julianDay == -1);
7310 assert(SysTime(DateTime(-4713, 11, 24, 12, 0, 0)).julianDay == 0);
7311
7312 assert(SysTime(DateTime(0, 12, 31, 0, 0, 0)).julianDay == 1_721_424);
7313 assert(SysTime(DateTime(0, 12, 31, 12, 0, 0)).julianDay == 1_721_425);
7314
7315 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).julianDay == 1_721_425);
7316 assert(SysTime(DateTime(1, 1, 1, 12, 0, 0)).julianDay == 1_721_426);
7317
7318 assert(SysTime(DateTime(1582, 10, 15, 0, 0, 0)).julianDay == 2_299_160);
7319 assert(SysTime(DateTime(1582, 10, 15, 12, 0, 0)).julianDay == 2_299_161);
7320
7321 assert(SysTime(DateTime(1858, 11, 17, 0, 0, 0)).julianDay == 2_400_000);
7322 assert(SysTime(DateTime(1858, 11, 17, 12, 0, 0)).julianDay == 2_400_001);
7323
7324 assert(SysTime(DateTime(1982, 1, 4, 0, 0, 0)).julianDay == 2_444_973);
7325 assert(SysTime(DateTime(1982, 1, 4, 12, 0, 0)).julianDay == 2_444_974);
7326
7327 assert(SysTime(DateTime(1996, 3, 31, 0, 0, 0)).julianDay == 2_450_173);
7328 assert(SysTime(DateTime(1996, 3, 31, 12, 0, 0)).julianDay == 2_450_174);
7329
7330 assert(SysTime(DateTime(2010, 8, 24, 0, 0, 0)).julianDay == 2_455_432);
7331 assert(SysTime(DateTime(2010, 8, 24, 12, 0, 0)).julianDay == 2_455_433);
7332
7333 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7334 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7335 assert(cst.julianDay == 2_451_366);
7336 //assert(ist.julianDay == 2_451_366);
7337 }
7338
7339
7340 /++
7341 The modified $(HTTP en.wikipedia.org/wiki/Julian_day, Julian day) for
7342 any time on this date (since, the modified Julian day changes at
7343 midnight).
7344 +/
7345 @property long modJulianDay() @safe const nothrow
7346 {
7347 return dayOfGregorianCal + 1_721_425 - 2_400_001;
7348 }
7349
7350 @safe unittest
7351 {
7352 assert(SysTime(DateTime(1858, 11, 17, 0, 0, 0)).modJulianDay == 0);
7353 assert(SysTime(DateTime(1858, 11, 17, 12, 0, 0)).modJulianDay == 0);
7354
7355 assert(SysTime(DateTime(2010, 8, 24, 0, 0, 0)).modJulianDay == 55_432);
7356 assert(SysTime(DateTime(2010, 8, 24, 12, 0, 0)).modJulianDay == 55_432);
7357
7358 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7359 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7360 assert(cst.modJulianDay == 51_365);
7361 //assert(ist.modJulianDay == 51_365);
7362 }
7363
7364
7365 /++
7366 Returns a $(REF Date,std,datetime,date) equivalent to this $(LREF SysTime).
7367 +/
7368 Date opCast(T)() @safe const nothrow
7369 if (is(Unqual!T == Date))
7370 {
7371 return Date(dayOfGregorianCal);
7372 }
7373
7374 @safe unittest
7375 {
7376 assert(cast(Date) SysTime(Date(1999, 7, 6)) == Date(1999, 7, 6));
7377 assert(cast(Date) SysTime(Date(2000, 12, 31)) == Date(2000, 12, 31));
7378 assert(cast(Date) SysTime(Date(2001, 1, 1)) == Date(2001, 1, 1));
7379
7380 assert(cast(Date) SysTime(DateTime(1999, 7, 6, 12, 10, 9)) == Date(1999, 7, 6));
7381 assert(cast(Date) SysTime(DateTime(2000, 12, 31, 13, 11, 10)) == Date(2000, 12, 31));
7382 assert(cast(Date) SysTime(DateTime(2001, 1, 1, 14, 12, 11)) == Date(2001, 1, 1));
7383
7384 assert(cast(Date) SysTime(Date(-1999, 7, 6)) == Date(-1999, 7, 6));
7385 assert(cast(Date) SysTime(Date(-2000, 12, 31)) == Date(-2000, 12, 31));
7386 assert(cast(Date) SysTime(Date(-2001, 1, 1)) == Date(-2001, 1, 1));
7387
7388 assert(cast(Date) SysTime(DateTime(-1999, 7, 6, 12, 10, 9)) == Date(-1999, 7, 6));
7389 assert(cast(Date) SysTime(DateTime(-2000, 12, 31, 13, 11, 10)) == Date(-2000, 12, 31));
7390 assert(cast(Date) SysTime(DateTime(-2001, 1, 1, 14, 12, 11)) == Date(-2001, 1, 1));
7391
7392 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7393 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7394 assert(cast(Date) cst != Date.init);
7395 //assert(cast(Date) ist != Date.init);
7396 }
7397
7398
7399 /++
7400 Returns a $(REF DateTime,std,datetime,date) equivalent to this
7401 $(LREF SysTime).
7402 +/
7403 DateTime opCast(T)() @safe const nothrow
7404 if (is(Unqual!T == DateTime))
7405 {
7406 try
7407 {
7408 auto hnsecs = adjTime;
7409 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
7410
7411 if (hnsecs < 0)
7412 {
7413 hnsecs += convert!("hours", "hnsecs")(24);
7414 --days;
7415 }
7416
7417 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
7418 immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
7419 immutable second = getUnitsFromHNSecs!"seconds"(hnsecs);
7420
7421 return DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour, cast(int) minute, cast(int) second));
7422 }
7423 catch (Exception e)
7424 assert(0, "Either DateTime's constructor or TimeOfDay's constructor threw.");
7425 }
7426
7427 @safe unittest
7428 {
7429 assert(cast(DateTime) SysTime(DateTime(1, 1, 6, 7, 12, 22)) == DateTime(1, 1, 6, 7, 12, 22));
7430 assert(cast(DateTime) SysTime(DateTime(1, 1, 6, 7, 12, 22), msecs(22)) == DateTime(1, 1, 6, 7, 12, 22));
7431 assert(cast(DateTime) SysTime(Date(1999, 7, 6)) == DateTime(1999, 7, 6, 0, 0, 0));
7432 assert(cast(DateTime) SysTime(Date(2000, 12, 31)) == DateTime(2000, 12, 31, 0, 0, 0));
7433 assert(cast(DateTime) SysTime(Date(2001, 1, 1)) == DateTime(2001, 1, 1, 0, 0, 0));
7434
7435 assert(cast(DateTime) SysTime(DateTime(1999, 7, 6, 12, 10, 9)) == DateTime(1999, 7, 6, 12, 10, 9));
7436 assert(cast(DateTime) SysTime(DateTime(2000, 12, 31, 13, 11, 10)) == DateTime(2000, 12, 31, 13, 11, 10));
7437 assert(cast(DateTime) SysTime(DateTime(2001, 1, 1, 14, 12, 11)) == DateTime(2001, 1, 1, 14, 12, 11));
7438
7439 assert(cast(DateTime) SysTime(DateTime(-1, 1, 6, 7, 12, 22)) == DateTime(-1, 1, 6, 7, 12, 22));
7440 assert(cast(DateTime) SysTime(DateTime(-1, 1, 6, 7, 12, 22), msecs(22)) == DateTime(-1, 1, 6, 7, 12, 22));
7441 assert(cast(DateTime) SysTime(Date(-1999, 7, 6)) == DateTime(-1999, 7, 6, 0, 0, 0));
7442 assert(cast(DateTime) SysTime(Date(-2000, 12, 31)) == DateTime(-2000, 12, 31, 0, 0, 0));
7443 assert(cast(DateTime) SysTime(Date(-2001, 1, 1)) == DateTime(-2001, 1, 1, 0, 0, 0));
7444
7445 assert(cast(DateTime) SysTime(DateTime(-1999, 7, 6, 12, 10, 9)) == DateTime(-1999, 7, 6, 12, 10, 9));
7446 assert(cast(DateTime) SysTime(DateTime(-2000, 12, 31, 13, 11, 10)) == DateTime(-2000, 12, 31, 13, 11, 10));
7447 assert(cast(DateTime) SysTime(DateTime(-2001, 1, 1, 14, 12, 11)) == DateTime(-2001, 1, 1, 14, 12, 11));
7448
7449 assert(cast(DateTime) SysTime(DateTime(2011, 1, 13, 8, 17, 2), msecs(296), LocalTime()) ==
7450 DateTime(2011, 1, 13, 8, 17, 2));
7451
7452 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7453 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7454 assert(cast(DateTime) cst != DateTime.init);
7455 //assert(cast(DateTime) ist != DateTime.init);
7456 }
7457
7458
7459 /++
7460 Returns a $(REF TimeOfDay,std,datetime,date) equivalent to this
7461 $(LREF SysTime).
7462 +/
7463 TimeOfDay opCast(T)() @safe const nothrow
7464 if (is(Unqual!T == TimeOfDay))
7465 {
7466 try
7467 {
7468 auto hnsecs = adjTime;
7469 hnsecs = removeUnitsFromHNSecs!"days"(hnsecs);
7470
7471 if (hnsecs < 0)
7472 hnsecs += convert!("hours", "hnsecs")(24);
7473
7474 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
7475 immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
7476 immutable second = getUnitsFromHNSecs!"seconds"(hnsecs);
7477
7478 return TimeOfDay(cast(int) hour, cast(int) minute, cast(int) second);
7479 }
7480 catch (Exception e)
7481 assert(0, "TimeOfDay's constructor threw.");
7482 }
7483
7484 @safe unittest
7485 {
7486 assert(cast(TimeOfDay) SysTime(Date(1999, 7, 6)) == TimeOfDay(0, 0, 0));
7487 assert(cast(TimeOfDay) SysTime(Date(2000, 12, 31)) == TimeOfDay(0, 0, 0));
7488 assert(cast(TimeOfDay) SysTime(Date(2001, 1, 1)) == TimeOfDay(0, 0, 0));
7489
7490 assert(cast(TimeOfDay) SysTime(DateTime(1999, 7, 6, 12, 10, 9)) == TimeOfDay(12, 10, 9));
7491 assert(cast(TimeOfDay) SysTime(DateTime(2000, 12, 31, 13, 11, 10)) == TimeOfDay(13, 11, 10));
7492 assert(cast(TimeOfDay) SysTime(DateTime(2001, 1, 1, 14, 12, 11)) == TimeOfDay(14, 12, 11));
7493
7494 assert(cast(TimeOfDay) SysTime(Date(-1999, 7, 6)) == TimeOfDay(0, 0, 0));
7495 assert(cast(TimeOfDay) SysTime(Date(-2000, 12, 31)) == TimeOfDay(0, 0, 0));
7496 assert(cast(TimeOfDay) SysTime(Date(-2001, 1, 1)) == TimeOfDay(0, 0, 0));
7497
7498 assert(cast(TimeOfDay) SysTime(DateTime(-1999, 7, 6, 12, 10, 9)) == TimeOfDay(12, 10, 9));
7499 assert(cast(TimeOfDay) SysTime(DateTime(-2000, 12, 31, 13, 11, 10)) == TimeOfDay(13, 11, 10));
7500 assert(cast(TimeOfDay) SysTime(DateTime(-2001, 1, 1, 14, 12, 11)) == TimeOfDay(14, 12, 11));
7501
7502 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7503 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7504 assert(cast(TimeOfDay) cst != TimeOfDay.init);
7505 //assert(cast(TimeOfDay) ist != TimeOfDay.init);
7506 }
7507
7508
7509 // Temporary hack until bug http://d.puremagic.com/issues/show_bug.cgi?id=4867 is fixed.
7510 // This allows assignment from const(SysTime) to SysTime.
7511 // It may be a good idea to keep it though, since casting from a type to itself
7512 // should be allowed, and it doesn't work without this opCast() since opCast()
7513 // has already been defined for other types.
7514 SysTime opCast(T)() @safe const pure nothrow
7515 if (is(Unqual!T == SysTime))
7516 {
7517 return SysTime(_stdTime, _timezone);
7518 }
7519
7520
7521 /++
7522 Converts this $(LREF SysTime) to a string with the format
7523 YYYYMMDDTHHMMSS.FFFFFFFTZ (where F is fractional seconds and TZ is time
7524 zone).
7525
7526 Note that the number of digits in the fractional seconds varies with the
7527 number of fractional seconds. It's a maximum of 7 (which would be
7528 hnsecs), but only has as many as are necessary to hold the correct value
7529 (so no trailing zeroes), and if there are no fractional seconds, then
7530 there is no decimal point.
7531
7532 If this $(LREF SysTime)'s time zone is
7533 $(REF LocalTime,std,datetime,timezone), then TZ is empty. If its time
7534 zone is $(D UTC), then it is "Z". Otherwise, it is the offset from UTC
7535 (e.g. +0100 or -0700). Note that the offset from UTC is $(I not) enough
7536 to uniquely identify the time zone.
7537
7538 Time zone offsets will be in the form +HHMM or -HHMM.
7539
7540 $(RED Warning:
7541 Previously, toISOString did the same as $(LREF toISOExtString) and
7542 generated +HH:MM or -HH:MM for the time zone when it was not
7543 $(REF LocalTime,std,datetime,timezone) or
7544 $(REF UTC,std,datetime,timezone), which is not in conformance with
7545 ISO 8601 for the non-extended string format. This has now been
7546 fixed. However, for now, fromISOString will continue to accept the
7547 extended format for the time zone so that any code which has been
7548 writing out the result of toISOString to read in later will continue
7549 to work. The current behavior will be kept until July 2019 at which
7550 point, fromISOString will be fixed to be standards compliant.)
7551 +/
7552 string toISOString() @safe const nothrow
7553 {
7554 try
7555 {
7556 immutable adjustedTime = adjTime;
7557 long hnsecs = adjustedTime;
7558
7559 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
7560
7561 if (hnsecs < 0)
7562 {
7563 hnsecs += convert!("hours", "hnsecs")(24);
7564 --days;
7565 }
7566
7567 auto hour = splitUnitsFromHNSecs!"hours"(hnsecs);
7568 auto minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
7569 auto second = splitUnitsFromHNSecs!"seconds"(hnsecs);
7570
7571 auto dateTime = DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour,
7572 cast(int) minute, cast(int) second));
7573 auto fracSecStr = fracSecsToISOString(cast(int) hnsecs);
7574
7575 if (_timezone is LocalTime())
7576 return dateTime.toISOString() ~ fracSecStr;
7577
7578 if (_timezone is UTC())
7579 return dateTime.toISOString() ~ fracSecStr ~ "Z";
7580
7581 immutable utcOffset = dur!"hnsecs"(adjustedTime - stdTime);
7582
7583 return format("%s%s%s",
7584 dateTime.toISOString(),
7585 fracSecStr,
7586 SimpleTimeZone.toISOExtString(utcOffset));
7587 }
7588 catch (Exception e)
7589 assert(0, "format() threw.");
7590 }
7591
7592 ///
7593 @safe unittest
7594 {
7595 import core.time : msecs, hnsecs;
7596 import std.datetime.date : DateTime;
7597
7598 assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toISOString() ==
7599 "20100704T070612");
7600
7601 assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(24)).toISOString() ==
7602 "19981225T021500.024");
7603
7604 assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toISOString() ==
7605 "00000105T230959");
7606
7607 assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toISOString() ==
7608 "-00040105T000002.052092");
7609 }
7610
7611 @safe unittest
7612 {
7613 // Test A.D.
7614 assert(SysTime(DateTime.init, UTC()).toISOString() == "00010101T000000Z");
7615 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1), UTC()).toISOString() == "00010101T000000.0000001Z");
7616
7617 assert(SysTime(DateTime(9, 12, 4, 0, 0, 0)).toISOString() == "00091204T000000");
7618 assert(SysTime(DateTime(99, 12, 4, 5, 6, 12)).toISOString() == "00991204T050612");
7619 assert(SysTime(DateTime(999, 12, 4, 13, 44, 59)).toISOString() == "09991204T134459");
7620 assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59)).toISOString() == "99990704T235959");
7621 assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1)).toISOString() == "+100001020T010101");
7622
7623 assert(SysTime(DateTime(9, 12, 4, 0, 0, 0), msecs(42)).toISOString() == "00091204T000000.042");
7624 assert(SysTime(DateTime(99, 12, 4, 5, 6, 12), msecs(100)).toISOString() == "00991204T050612.1");
7625 assert(SysTime(DateTime(999, 12, 4, 13, 44, 59), usecs(45020)).toISOString() == "09991204T134459.04502");
7626 assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59), hnsecs(12)).toISOString() == "99990704T235959.0000012");
7627 assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1), hnsecs(507890)).toISOString() == "+100001020T010101.050789");
7628
7629 assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
7630 new immutable SimpleTimeZone(dur!"minutes"(-360))).toISOString() ==
7631 "20121221T121212-06:00");
7632
7633 assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
7634 new immutable SimpleTimeZone(dur!"minutes"(420))).toISOString() ==
7635 "20121221T121212+07:00");
7636
7637 // Test B.C.
7638 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toISOString() ==
7639 "00001231T235959.9999999Z");
7640 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1), UTC()).toISOString() == "00001231T235959.0000001Z");
7641 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), UTC()).toISOString() == "00001231T235959Z");
7642
7643 assert(SysTime(DateTime(0, 12, 4, 0, 12, 4)).toISOString() == "00001204T001204");
7644 assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0)).toISOString() == "-00091204T000000");
7645 assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12)).toISOString() == "-00991204T050612");
7646 assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59)).toISOString() == "-09991204T134459");
7647 assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59)).toISOString() == "-99990704T235959");
7648 assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1)).toISOString() == "-100001020T010101");
7649
7650 assert(SysTime(DateTime(0, 12, 4, 0, 0, 0), msecs(7)).toISOString() == "00001204T000000.007");
7651 assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0), msecs(42)).toISOString() == "-00091204T000000.042");
7652 assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12), msecs(100)).toISOString() == "-00991204T050612.1");
7653 assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59), usecs(45020)).toISOString() == "-09991204T134459.04502");
7654 assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59), hnsecs(12)).toISOString() == "-99990704T235959.0000012");
7655 assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1), hnsecs(507890)).toISOString() == "-100001020T010101.050789");
7656
7657 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7658 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7659 assert(cast(TimeOfDay) cst != TimeOfDay.init);
7660 //assert(cast(TimeOfDay) ist != TimeOfDay.init);
7661 }
7662
7663
7664
7665 /++
7666 Converts this $(LREF SysTime) to a string with the format
7667 YYYY-MM-DDTHH:MM:SS.FFFFFFFTZ (where F is fractional seconds and TZ
7668 is the time zone).
7669
7670 Note that the number of digits in the fractional seconds varies with the
7671 number of fractional seconds. It's a maximum of 7 (which would be
7672 hnsecs), but only has as many as are necessary to hold the correct value
7673 (so no trailing zeroes), and if there are no fractional seconds, then
7674 there is no decimal point.
7675
7676 If this $(LREF SysTime)'s time zone is
7677 $(REF LocalTime,std,datetime,timezone), then TZ is empty. If its time
7678 zone is $(D UTC), then it is "Z". Otherwise, it is the offset from UTC
7679 (e.g. +01:00 or -07:00). Note that the offset from UTC is $(I not)
7680 enough to uniquely identify the time zone.
7681
7682 Time zone offsets will be in the form +HH:MM or -HH:MM.
7683 +/
7684 string toISOExtString() @safe const nothrow
7685 {
7686 try
7687 {
7688 immutable adjustedTime = adjTime;
7689 long hnsecs = adjustedTime;
7690
7691 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
7692
7693 if (hnsecs < 0)
7694 {
7695 hnsecs += convert!("hours", "hnsecs")(24);
7696 --days;
7697 }
7698
7699 auto hour = splitUnitsFromHNSecs!"hours"(hnsecs);
7700 auto minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
7701 auto second = splitUnitsFromHNSecs!"seconds"(hnsecs);
7702
7703 auto dateTime = DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour,
7704 cast(int) minute, cast(int) second));
7705 auto fracSecStr = fracSecsToISOString(cast(int) hnsecs);
7706
7707 if (_timezone is LocalTime())
7708 return dateTime.toISOExtString() ~ fracSecStr;
7709
7710 if (_timezone is UTC())
7711 return dateTime.toISOExtString() ~ fracSecStr ~ "Z";
7712
7713 immutable utcOffset = dur!"hnsecs"(adjustedTime - stdTime);
7714
7715 return format("%s%s%s",
7716 dateTime.toISOExtString(),
7717 fracSecStr,
7718 SimpleTimeZone.toISOExtString(utcOffset));
7719 }
7720 catch (Exception e)
7721 assert(0, "format() threw.");
7722 }
7723
7724 ///
7725 @safe unittest
7726 {
7727 import core.time : msecs, hnsecs;
7728 import std.datetime.date : DateTime;
7729
7730 assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toISOExtString() ==
7731 "2010-07-04T07:06:12");
7732
7733 assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(24)).toISOExtString() ==
7734 "1998-12-25T02:15:00.024");
7735
7736 assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toISOExtString() ==
7737 "0000-01-05T23:09:59");
7738
7739 assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toISOExtString() ==
7740 "-0004-01-05T00:00:02.052092");
7741 }
7742
7743 @safe unittest
7744 {
7745 // Test A.D.
7746 assert(SysTime(DateTime.init, UTC()).toISOExtString() == "0001-01-01T00:00:00Z");
7747 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1), UTC()).toISOExtString() ==
7748 "0001-01-01T00:00:00.0000001Z");
7749
7750 assert(SysTime(DateTime(9, 12, 4, 0, 0, 0)).toISOExtString() == "0009-12-04T00:00:00");
7751 assert(SysTime(DateTime(99, 12, 4, 5, 6, 12)).toISOExtString() == "0099-12-04T05:06:12");
7752 assert(SysTime(DateTime(999, 12, 4, 13, 44, 59)).toISOExtString() == "0999-12-04T13:44:59");
7753 assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59)).toISOExtString() == "9999-07-04T23:59:59");
7754 assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1)).toISOExtString() == "+10000-10-20T01:01:01");
7755
7756 assert(SysTime(DateTime(9, 12, 4, 0, 0, 0), msecs(42)).toISOExtString() == "0009-12-04T00:00:00.042");
7757 assert(SysTime(DateTime(99, 12, 4, 5, 6, 12), msecs(100)).toISOExtString() == "0099-12-04T05:06:12.1");
7758 assert(SysTime(DateTime(999, 12, 4, 13, 44, 59), usecs(45020)).toISOExtString() == "0999-12-04T13:44:59.04502");
7759 assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59), hnsecs(12)).toISOExtString() == "9999-07-04T23:59:59.0000012");
7760 assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1), hnsecs(507890)).toISOExtString() ==
7761 "+10000-10-20T01:01:01.050789");
7762
7763 assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
7764 new immutable SimpleTimeZone(dur!"minutes"(-360))).toISOExtString() ==
7765 "2012-12-21T12:12:12-06:00");
7766
7767 assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
7768 new immutable SimpleTimeZone(dur!"minutes"(420))).toISOExtString() ==
7769 "2012-12-21T12:12:12+07:00");
7770
7771 // Test B.C.
7772 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toISOExtString() ==
7773 "0000-12-31T23:59:59.9999999Z");
7774 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1), UTC()).toISOExtString() ==
7775 "0000-12-31T23:59:59.0000001Z");
7776 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), UTC()).toISOExtString() == "0000-12-31T23:59:59Z");
7777
7778 assert(SysTime(DateTime(0, 12, 4, 0, 12, 4)).toISOExtString() == "0000-12-04T00:12:04");
7779 assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0)).toISOExtString() == "-0009-12-04T00:00:00");
7780 assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12)).toISOExtString() == "-0099-12-04T05:06:12");
7781 assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59)).toISOExtString() == "-0999-12-04T13:44:59");
7782 assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59)).toISOExtString() == "-9999-07-04T23:59:59");
7783 assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1)).toISOExtString() == "-10000-10-20T01:01:01");
7784
7785 assert(SysTime(DateTime(0, 12, 4, 0, 0, 0), msecs(7)).toISOExtString() == "0000-12-04T00:00:00.007");
7786 assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0), msecs(42)).toISOExtString() == "-0009-12-04T00:00:00.042");
7787 assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12), msecs(100)).toISOExtString() == "-0099-12-04T05:06:12.1");
7788 assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59), usecs(45020)).toISOExtString() ==
7789 "-0999-12-04T13:44:59.04502");
7790 assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59), hnsecs(12)).toISOExtString() ==
7791 "-9999-07-04T23:59:59.0000012");
7792 assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1), hnsecs(507890)).toISOExtString() ==
7793 "-10000-10-20T01:01:01.050789");
7794
7795 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7796 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7797 assert(cast(TimeOfDay) cst != TimeOfDay.init);
7798 //assert(cast(TimeOfDay) ist != TimeOfDay.init);
7799 }
7800
7801 /++
7802 Converts this $(LREF SysTime) to a string with the format
7803 YYYY-Mon-DD HH:MM:SS.FFFFFFFTZ (where F is fractional seconds and TZ
7804 is the time zone).
7805
7806 Note that the number of digits in the fractional seconds varies with the
7807 number of fractional seconds. It's a maximum of 7 (which would be
7808 hnsecs), but only has as many as are necessary to hold the correct value
7809 (so no trailing zeroes), and if there are no fractional seconds, then
7810 there is no decimal point.
7811
7812 If this $(LREF SysTime)'s time zone is
7813 $(REF LocalTime,std,datetime,timezone), then TZ is empty. If its time
7814 zone is $(D UTC), then it is "Z". Otherwise, it is the offset from UTC
7815 (e.g. +01:00 or -07:00). Note that the offset from UTC is $(I not)
7816 enough to uniquely identify the time zone.
7817
7818 Time zone offsets will be in the form +HH:MM or -HH:MM.
7819 +/
7820 string toSimpleString() @safe const nothrow
7821 {
7822 try
7823 {
7824 immutable adjustedTime = adjTime;
7825 long hnsecs = adjustedTime;
7826
7827 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
7828
7829 if (hnsecs < 0)
7830 {
7831 hnsecs += convert!("hours", "hnsecs")(24);
7832 --days;
7833 }
7834
7835 auto hour = splitUnitsFromHNSecs!"hours"(hnsecs);
7836 auto minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
7837 auto second = splitUnitsFromHNSecs!"seconds"(hnsecs);
7838
7839 auto dateTime = DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour,
7840 cast(int) minute, cast(int) second));
7841 auto fracSecStr = fracSecsToISOString(cast(int) hnsecs);
7842
7843 if (_timezone is LocalTime())
7844 return dateTime.toSimpleString() ~ fracSecStr;
7845
7846 if (_timezone is UTC())
7847 return dateTime.toSimpleString() ~ fracSecStr ~ "Z";
7848
7849 immutable utcOffset = dur!"hnsecs"(adjustedTime - stdTime);
7850
7851 return format("%s%s%s",
7852 dateTime.toSimpleString(),
7853 fracSecStr,
7854 SimpleTimeZone.toISOExtString(utcOffset));
7855 }
7856 catch (Exception e)
7857 assert(0, "format() threw.");
7858 }
7859
7860 ///
7861 @safe unittest
7862 {
7863 import core.time : msecs, hnsecs;
7864 import std.datetime.date : DateTime;
7865
7866 assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toSimpleString() ==
7867 "2010-Jul-04 07:06:12");
7868
7869 assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(24)).toSimpleString() ==
7870 "1998-Dec-25 02:15:00.024");
7871
7872 assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toSimpleString() ==
7873 "0000-Jan-05 23:09:59");
7874
7875 assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toSimpleString() ==
7876 "-0004-Jan-05 00:00:02.052092");
7877 }
7878
7879 @safe unittest
7880 {
7881 // Test A.D.
7882 assert(SysTime(DateTime.init, UTC()).toString() == "0001-Jan-01 00:00:00Z");
7883 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1), UTC()).toString() == "0001-Jan-01 00:00:00.0000001Z");
7884
7885 assert(SysTime(DateTime(9, 12, 4, 0, 0, 0)).toSimpleString() == "0009-Dec-04 00:00:00");
7886 assert(SysTime(DateTime(99, 12, 4, 5, 6, 12)).toSimpleString() == "0099-Dec-04 05:06:12");
7887 assert(SysTime(DateTime(999, 12, 4, 13, 44, 59)).toSimpleString() == "0999-Dec-04 13:44:59");
7888 assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59)).toSimpleString() == "9999-Jul-04 23:59:59");
7889 assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1)).toSimpleString() == "+10000-Oct-20 01:01:01");
7890
7891 assert(SysTime(DateTime(9, 12, 4, 0, 0, 0), msecs(42)).toSimpleString() == "0009-Dec-04 00:00:00.042");
7892 assert(SysTime(DateTime(99, 12, 4, 5, 6, 12), msecs(100)).toSimpleString() == "0099-Dec-04 05:06:12.1");
7893 assert(SysTime(DateTime(999, 12, 4, 13, 44, 59), usecs(45020)).toSimpleString() ==
7894 "0999-Dec-04 13:44:59.04502");
7895 assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59), hnsecs(12)).toSimpleString() ==
7896 "9999-Jul-04 23:59:59.0000012");
7897 assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1), hnsecs(507890)).toSimpleString() ==
7898 "+10000-Oct-20 01:01:01.050789");
7899
7900 assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
7901 new immutable SimpleTimeZone(dur!"minutes"(-360))).toSimpleString() ==
7902 "2012-Dec-21 12:12:12-06:00");
7903
7904 assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
7905 new immutable SimpleTimeZone(dur!"minutes"(420))).toSimpleString() ==
7906 "2012-Dec-21 12:12:12+07:00");
7907
7908 // Test B.C.
7909 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toSimpleString() ==
7910 "0000-Dec-31 23:59:59.9999999Z");
7911 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1), UTC()).toSimpleString() ==
7912 "0000-Dec-31 23:59:59.0000001Z");
7913 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), UTC()).toSimpleString() == "0000-Dec-31 23:59:59Z");
7914
7915 assert(SysTime(DateTime(0, 12, 4, 0, 12, 4)).toSimpleString() == "0000-Dec-04 00:12:04");
7916 assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0)).toSimpleString() == "-0009-Dec-04 00:00:00");
7917 assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12)).toSimpleString() == "-0099-Dec-04 05:06:12");
7918 assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59)).toSimpleString() == "-0999-Dec-04 13:44:59");
7919 assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59)).toSimpleString() == "-9999-Jul-04 23:59:59");
7920 assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1)).toSimpleString() == "-10000-Oct-20 01:01:01");
7921
7922 assert(SysTime(DateTime(0, 12, 4, 0, 0, 0), msecs(7)).toSimpleString() == "0000-Dec-04 00:00:00.007");
7923 assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0), msecs(42)).toSimpleString() == "-0009-Dec-04 00:00:00.042");
7924 assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12), msecs(100)).toSimpleString() == "-0099-Dec-04 05:06:12.1");
7925 assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59), usecs(45020)).toSimpleString() ==
7926 "-0999-Dec-04 13:44:59.04502");
7927 assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59), hnsecs(12)).toSimpleString() ==
7928 "-9999-Jul-04 23:59:59.0000012");
7929 assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1), hnsecs(507890)).toSimpleString() ==
7930 "-10000-Oct-20 01:01:01.050789");
7931
7932 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7933 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7934 assert(cast(TimeOfDay) cst != TimeOfDay.init);
7935 //assert(cast(TimeOfDay) ist != TimeOfDay.init);
7936 }
7937
7938
7939 /++
7940 Converts this $(LREF SysTime) to a string.
7941
7942 This function exists to make it easy to convert a $(LREF SysTime) to a
7943 string for code that does not care what the exact format is - just that
7944 it presents the information in a clear manner. It also makes it easy to
7945 simply convert a $(LREF SysTime) to a string when using functions such
7946 as `to!string`, `format`, or `writeln` which use toString to convert
7947 user-defined types. So, it is unlikely that much code will call
7948 toString directly.
7949
7950 The format of the string is purposefully unspecified, and code that
7951 cares about the format of the string should use `toISOString`,
7952 `toISOExtString`, `toSimpleString`, or some other custom formatting
7953 function that explicitly generates the format that the code needs. The
7954 reason is that the code is then clear about what format it's using,
7955 making it less error-prone to maintain the code and interact with other
7956 software that consumes the generated strings. It's for this same reason
7957 that $(LREF SysTime) has no `fromString` function, whereas it does have
7958 `fromISOString`, `fromISOExtString`, and `fromSimpleString`.
7959
7960 The format returned by toString may or may not change in the future.
7961 +/
7962 string toString() @safe const nothrow
7963 {
7964 return toSimpleString();
7965 }
7966
7967 @safe unittest
7968 {
7969 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7970 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7971 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7972 assert(st.toString());
7973 assert(cst.toString());
7974 //assert(ist.toString());
7975 }
7976
7977
7978 /++
7979 Creates a $(LREF SysTime) from a string with the format
7980 YYYYMMDDTHHMMSS.FFFFFFFTZ (where F is fractional seconds is the time
7981 zone). Whitespace is stripped from the given string.
7982
7983 The exact format is exactly as described in $(D toISOString) except that
7984 trailing zeroes are permitted - including having fractional seconds with
7985 all zeroes. However, a decimal point with nothing following it is
7986 invalid. Also, while $(LREF toISOString) will never generate a string
7987 with more than 7 digits in the fractional seconds (because that's the
7988 limit with hecto-nanosecond precision), it will allow more than 7 digits
7989 in order to read strings from other sources that have higher precision
7990 (however, any digits beyond 7 will be truncated).
7991
7992 If there is no time zone in the string, then
7993 $(REF LocalTime,std,datetime,timezone) is used. If the time zone is "Z",
7994 then $(D UTC) is used. Otherwise, a
7995 $(REF SimpleTimeZone,std,datetime,timezone) which corresponds to the
7996 given offset from UTC is used. To get the returned $(LREF SysTime) to be
7997 a particular time zone, pass in that time zone and the $(LREF SysTime)
7998 to be returned will be converted to that time zone (though it will still
7999 be read in as whatever time zone is in its string).
8000
8001 The accepted formats for time zone offsets are +HH, -HH, +HHMM, and
8002 -HHMM.
8003
8004 $(RED Warning:
8005 Previously, $(LREF toISOString) did the same as
8006 $(LREF toISOExtString) and generated +HH:MM or -HH:MM for the time
8007 zone when it was not $(REF LocalTime,std,datetime,timezone) or
8008 $(REF UTC,std,datetime,timezone), which is not in conformance with
8009 ISO 8601 for the non-extended string format. This has now been
8010 fixed. However, for now, fromISOString will continue to accept the
8011 extended format for the time zone so that any code which has been
8012 writing out the result of toISOString to read in later will continue
8013 to work. The current behavior will be kept until July 2019 at which
8014 point, fromISOString will be fixed to be standards compliant.)
8015
8016 Params:
8017 isoString = A string formatted in the ISO format for dates and times.
8018 tz = The time zone to convert the given time to (no
8019 conversion occurs if null).
8020
8021 Throws:
8022 $(REF DateTimeException,std,datetime,date) if the given string is
8023 not in the ISO format or if the resulting $(LREF SysTime) would not
8024 be valid.
8025 +/
8026 static SysTime fromISOString(S)(in S isoString, immutable TimeZone tz = null) @safe
8027 if (isSomeString!S)
8028 {
8029 import std.algorithm.searching : startsWith, find;
8030 import std.conv : to;
8031 import std.string : strip;
8032
8033 auto dstr = to!dstring(strip(isoString));
8034 immutable skipFirst = dstr.startsWith('+', '-') != 0;
8035
8036 auto found = (skipFirst ? dstr[1..$] : dstr).find('.', 'Z', '+', '-');
8037 auto dateTimeStr = dstr[0 .. $ - found[0].length];
8038
8039 dstring fracSecStr;
8040 dstring zoneStr;
8041
8042 if (found[1] != 0)
8043 {
8044 if (found[1] == 1)
8045 {
8046 auto foundTZ = found[0].find('Z', '+', '-');
8047
8048 if (foundTZ[1] != 0)
8049 {
8050 fracSecStr = found[0][0 .. $ - foundTZ[0].length];
8051 zoneStr = foundTZ[0];
8052 }
8053 else
8054 fracSecStr = found[0];
8055 }
8056 else
8057 zoneStr = found[0];
8058 }
8059
8060 try
8061 {
8062 auto dateTime = DateTime.fromISOString(dateTimeStr);
8063 auto fracSec = fracSecsFromISOString(fracSecStr);
8064 Rebindable!(immutable TimeZone) parsedZone;
8065
8066 if (zoneStr.empty)
8067 parsedZone = LocalTime();
8068 else if (zoneStr == "Z")
8069 parsedZone = UTC();
8070 else
8071 {
8072 try
8073 parsedZone = SimpleTimeZone.fromISOString(zoneStr);
8074 catch (DateTimeException dte)
8075 parsedZone = SimpleTimeZone.fromISOExtString(zoneStr);
8076 }
8077
8078 auto retval = SysTime(dateTime, fracSec, parsedZone);
8079
8080 if (tz !is null)
8081 retval.timezone = tz;
8082
8083 return retval;
8084 }
8085 catch (DateTimeException dte)
8086 throw new DateTimeException(format("Invalid ISO String: %s", isoString));
8087 }
8088
8089 ///
8090 @safe unittest
8091 {
8092 import core.time : hours, msecs, usecs, hnsecs;
8093 import std.datetime.date : DateTime;
8094 import std.datetime.timezone : SimpleTimeZone, UTC;
8095
8096 assert(SysTime.fromISOString("20100704T070612") ==
8097 SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
8098
8099 assert(SysTime.fromISOString("19981225T021500.007") ==
8100 SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(7)));
8101
8102 assert(SysTime.fromISOString("00000105T230959.00002") ==
8103 SysTime(DateTime(0, 1, 5, 23, 9, 59), usecs(20)));
8104
8105 assert(SysTime.fromISOString("20130207T043937.000050392") ==
8106 SysTime(DateTime(2013, 2, 7, 4, 39, 37), hnsecs(503)));
8107
8108 assert(SysTime.fromISOString("-00040105T000002") ==
8109 SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
8110
8111 assert(SysTime.fromISOString(" 20100704T070612 ") ==
8112 SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
8113
8114 assert(SysTime.fromISOString("20100704T070612Z") ==
8115 SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
8116
8117 assert(SysTime.fromISOString("20100704T070612-0800") ==
8118 SysTime(DateTime(2010, 7, 4, 7, 6, 12),
8119 new immutable SimpleTimeZone(hours(-8))));
8120
8121 assert(SysTime.fromISOString("20100704T070612+0800") ==
8122 SysTime(DateTime(2010, 7, 4, 7, 6, 12),
8123 new immutable SimpleTimeZone(hours(8))));
8124 }
8125
8126 @safe unittest
8127 {
8128 foreach (str; ["", "20100704000000", "20100704 000000", "20100704t000000",
8129 "20100704T000000.", "20100704T000000.A", "20100704T000000.Z",
8130 "20100704T000000.0000000A", "20100704T000000.00000000A",
8131 "20100704T000000+", "20100704T000000-", "20100704T000000:",
8132 "20100704T000000-:", "20100704T000000+:", "20100704T000000-1:",
8133 "20100704T000000+1:", "20100704T000000+1:0",
8134 "20100704T000000-12.00", "20100704T000000+12.00",
8135 "20100704T000000-8", "20100704T000000+8",
8136 "20100704T000000-800", "20100704T000000+800",
8137 "20100704T000000-080", "20100704T000000+080",
8138 "20100704T000000-2400", "20100704T000000+2400",
8139 "20100704T000000-1260", "20100704T000000+1260",
8140 "20100704T000000.0-8", "20100704T000000.0+8",
8141 "20100704T000000.0-800", "20100704T000000.0+800",
8142 "20100704T000000.0-080", "20100704T000000.0+080",
8143 "20100704T000000.0-2400", "20100704T000000.0+2400",
8144 "20100704T000000.0-1260", "20100704T000000.0+1260",
8145 "20100704T000000-8:00", "20100704T000000+8:00",
8146 "20100704T000000-08:0", "20100704T000000+08:0",
8147 "20100704T000000-24:00", "20100704T000000+24:00",
8148 "20100704T000000-12:60", "20100704T000000+12:60",
8149 "20100704T000000.0-8:00", "20100704T000000.0+8:00",
8150 "20100704T000000.0-08:0", "20100704T000000.0+08:0",
8151 "20100704T000000.0-24:00", "20100704T000000.0+24:00",
8152 "20100704T000000.0-12:60", "20100704T000000.0+12:60",
8153 "2010-07-0400:00:00", "2010-07-04 00:00:00",
8154 "2010-07-04t00:00:00", "2010-07-04T00:00:00.",
8155 "2010-Jul-0400:00:00", "2010-Jul-04 00:00:00", "2010-Jul-04t00:00:00",
8156 "2010-Jul-04T00:00:00", "2010-Jul-04 00:00:00.",
8157 "2010-12-22T172201", "2010-Dec-22 17:22:01"])
8158 {
8159 assertThrown!DateTimeException(SysTime.fromISOString(str), format("[%s]", str));
8160 }
8161
8162 static void test(string str, SysTime st, size_t line = __LINE__)
8163 {
8164 if (SysTime.fromISOString(str) != st)
8165 throw new AssertError("unittest failure", __FILE__, line);
8166 }
8167
8168 test("20101222T172201", SysTime(DateTime(2010, 12, 22, 17, 22, 01)));
8169 test("19990706T123033", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8170 test("-19990706T123033", SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
8171 test("+019990706T123033", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8172 test("19990706T123033 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8173 test(" 19990706T123033", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8174 test(" 19990706T123033 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8175
8176 test("19070707T121212.0", SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
8177 test("19070707T121212.0000000", SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
8178 test("19070707T121212.0000001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), hnsecs(1)));
8179 test("20100704T000000.00000000", SysTime(Date(2010, 07, 04)));
8180 test("20100704T000000.00000009", SysTime(Date(2010, 07, 04)));
8181 test("20100704T000000.00000019", SysTime(DateTime(2010, 07, 04), hnsecs(1)));
8182 test("19070707T121212.000001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), usecs(1)));
8183 test("19070707T121212.0000010", SysTime(DateTime(1907, 07, 07, 12, 12, 12), usecs(1)));
8184 test("19070707T121212.001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), msecs(1)));
8185 test("19070707T121212.0010000", SysTime(DateTime(1907, 07, 07, 12, 12, 12), msecs(1)));
8186
8187 auto west60 = new immutable SimpleTimeZone(hours(-1));
8188 auto west90 = new immutable SimpleTimeZone(minutes(-90));
8189 auto west480 = new immutable SimpleTimeZone(hours(-8));
8190 auto east60 = new immutable SimpleTimeZone(hours(1));
8191 auto east90 = new immutable SimpleTimeZone(minutes(90));
8192 auto east480 = new immutable SimpleTimeZone(hours(8));
8193
8194 test("20101222T172201Z", SysTime(DateTime(2010, 12, 22, 17, 22, 01), UTC()));
8195 test("20101222T172201-0100", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60));
8196 test("20101222T172201-01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60));
8197 test("20101222T172201-0130", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west90));
8198 test("20101222T172201-0800", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west480));
8199 test("20101222T172201+0100", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
8200 test("20101222T172201+01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
8201 test("20101222T172201+0130", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90));
8202 test("20101222T172201+0800", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east480));
8203
8204 test("20101103T065106.57159Z", SysTime(DateTime(2010, 11, 3, 6, 51, 6), hnsecs(5715900), UTC()));
8205 test("20101222T172201.23412Z", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_341_200), UTC()));
8206 test("20101222T172201.23112-0100", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_311_200), west60));
8207 test("20101222T172201.45-01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), west60));
8208 test("20101222T172201.1-0130", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_000_000), west90));
8209 test("20101222T172201.55-0800", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(5_500_000), west480));
8210 test("20101222T172201.1234567+0100", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_234_567), east60));
8211 test("20101222T172201.0+01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
8212 test("20101222T172201.0000000+0130", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90));
8213 test("20101222T172201.45+0800", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), east480));
8214
8215 // @@@DEPRECATED_2019-07@@@
8216 // This isn't deprecated per se, but that text will make it so that it
8217 // pops up when deprecations are moved along around July 2019. At that
8218 // time, we will update fromISOString so that it is conformant with ISO
8219 // 8601, and it will no longer accept ISO extended time zones (it does
8220 // currently because of issue #15654 - toISOString used to incorrectly
8221 // use the ISO extended time zone format). These tests will then start
8222 // failing will need to be updated accordingly. Also, the notes about
8223 // this issue in toISOString and fromISOString's documentation will need
8224 // to be removed.
8225 test("20101222T172201-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60));
8226 test("20101222T172201-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west90));
8227 test("20101222T172201-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west480));
8228 test("20101222T172201+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
8229 test("20101222T172201+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90));
8230 test("20101222T172201+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east480));
8231
8232 test("20101222T172201.23112-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_311_200), west60));
8233 test("20101222T172201.1-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_000_000), west90));
8234 test("20101222T172201.55-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(5_500_000), west480));
8235 test("20101222T172201.1234567+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_234_567), east60));
8236 test("20101222T172201.0000000+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90));
8237 test("20101222T172201.45+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), east480));
8238 }
8239
8240 // bug# 17801
8241 @safe unittest
8242 {
8243 import std.conv : to;
8244 import std.meta : AliasSeq;
8245 foreach (C; AliasSeq!(char, wchar, dchar))
8246 {
8247 foreach (S; AliasSeq!(C[], const(C)[], immutable(C)[]))
8248 {
8249 assert(SysTime.fromISOString(to!S("20121221T141516Z")) ==
8250 SysTime(DateTime(2012, 12, 21, 14, 15, 16), UTC()));
8251 }
8252 }
8253 }
8254
8255
8256 /++
8257 Creates a $(LREF SysTime) from a string with the format
8258 YYYY-MM-DDTHH:MM:SS.FFFFFFFTZ (where F is fractional seconds is the
8259 time zone). Whitespace is stripped from the given string.
8260
8261 The exact format is exactly as described in $(D toISOExtString)
8262 except that trailing zeroes are permitted - including having fractional
8263 seconds with all zeroes. However, a decimal point with nothing following
8264 it is invalid. Also, while $(LREF toISOExtString) will never generate a
8265 string with more than 7 digits in the fractional seconds (because that's
8266 the limit with hecto-nanosecond precision), it will allow more than 7
8267 digits in order to read strings from other sources that have higher
8268 precision (however, any digits beyond 7 will be truncated).
8269
8270 If there is no time zone in the string, then
8271 $(REF LocalTime,std,datetime,timezone) is used. If the time zone is "Z",
8272 then $(D UTC) is used. Otherwise, a
8273 $(REF SimpleTimeZone,std,datetime,timezone) which corresponds to the
8274 given offset from UTC is used. To get the returned $(LREF SysTime) to be
8275 a particular time zone, pass in that time zone and the $(LREF SysTime)
8276 to be returned will be converted to that time zone (though it will still
8277 be read in as whatever time zone is in its string).
8278
8279 The accepted formats for time zone offsets are +HH, -HH, +HH:MM, and
8280 -HH:MM.
8281
8282 Params:
8283 isoExtString = A string formatted in the ISO Extended format for
8284 dates and times.
8285 tz = The time zone to convert the given time to (no
8286 conversion occurs if null).
8287
8288 Throws:
8289 $(REF DateTimeException,std,datetime,date) if the given string is
8290 not in the ISO format or if the resulting $(LREF SysTime) would not
8291 be valid.
8292 +/
8293 static SysTime fromISOExtString(S)(in S isoExtString, immutable TimeZone tz = null) @safe
8294 if (isSomeString!(S))
8295 {
8296 import std.algorithm.searching : countUntil, find;
8297 import std.conv : to;
8298 import std.string : strip;
8299
8300 auto dstr = to!dstring(strip(isoExtString));
8301
8302 auto tIndex = dstr.countUntil('T');
8303 enforce(tIndex != -1, new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
8304
8305 auto found = dstr[tIndex + 1 .. $].find('.', 'Z', '+', '-');
8306 auto dateTimeStr = dstr[0 .. $ - found[0].length];
8307
8308 dstring fracSecStr;
8309 dstring zoneStr;
8310
8311 if (found[1] != 0)
8312 {
8313 if (found[1] == 1)
8314 {
8315 auto foundTZ = found[0].find('Z', '+', '-');
8316
8317 if (foundTZ[1] != 0)
8318 {
8319 fracSecStr = found[0][0 .. $ - foundTZ[0].length];
8320 zoneStr = foundTZ[0];
8321 }
8322 else
8323 fracSecStr = found[0];
8324 }
8325 else
8326 zoneStr = found[0];
8327 }
8328
8329 try
8330 {
8331 auto dateTime = DateTime.fromISOExtString(dateTimeStr);
8332 auto fracSec = fracSecsFromISOString(fracSecStr);
8333 Rebindable!(immutable TimeZone) parsedZone;
8334
8335 if (zoneStr.empty)
8336 parsedZone = LocalTime();
8337 else if (zoneStr == "Z")
8338 parsedZone = UTC();
8339 else
8340 parsedZone = SimpleTimeZone.fromISOExtString(zoneStr);
8341
8342 auto retval = SysTime(dateTime, fracSec, parsedZone);
8343
8344 if (tz !is null)
8345 retval.timezone = tz;
8346
8347 return retval;
8348 }
8349 catch (DateTimeException dte)
8350 throw new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString));
8351 }
8352
8353 ///
8354 @safe unittest
8355 {
8356 import core.time : hours, msecs, usecs, hnsecs;
8357 import std.datetime.date : DateTime;
8358 import std.datetime.timezone : SimpleTimeZone, UTC;
8359
8360 assert(SysTime.fromISOExtString("2010-07-04T07:06:12") ==
8361 SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
8362
8363 assert(SysTime.fromISOExtString("1998-12-25T02:15:00.007") ==
8364 SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(7)));
8365
8366 assert(SysTime.fromISOExtString("0000-01-05T23:09:59.00002") ==
8367 SysTime(DateTime(0, 1, 5, 23, 9, 59), usecs(20)));
8368
8369 assert(SysTime.fromISOExtString("2013-02-07T04:39:37.000050392") ==
8370 SysTime(DateTime(2013, 2, 7, 4, 39, 37), hnsecs(503)));
8371
8372 assert(SysTime.fromISOExtString("-0004-01-05T00:00:02") ==
8373 SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
8374
8375 assert(SysTime.fromISOExtString(" 2010-07-04T07:06:12 ") ==
8376 SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
8377
8378 assert(SysTime.fromISOExtString("2010-07-04T07:06:12Z") ==
8379 SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
8380
8381 assert(SysTime.fromISOExtString("2010-07-04T07:06:12-08:00") ==
8382 SysTime(DateTime(2010, 7, 4, 7, 6, 12),
8383 new immutable SimpleTimeZone(hours(-8))));
8384 assert(SysTime.fromISOExtString("2010-07-04T07:06:12+08:00") ==
8385 SysTime(DateTime(2010, 7, 4, 7, 6, 12),
8386 new immutable SimpleTimeZone(hours(8))));
8387 }
8388
8389 @safe unittest
8390 {
8391 foreach (str; ["", "20100704000000", "20100704 000000",
8392 "20100704t000000", "20100704T000000.", "20100704T000000.0",
8393 "2010-07:0400:00:00", "2010-07-04 00:00:00",
8394 "2010-07-04 00:00:00", "2010-07-04t00:00:00",
8395 "2010-07-04T00:00:00.", "2010-07-04T00:00:00.A", "2010-07-04T00:00:00.Z",
8396 "2010-07-04T00:00:00.0000000A", "2010-07-04T00:00:00.00000000A",
8397 "2010-07-04T00:00:00+", "2010-07-04T00:00:00-",
8398 "2010-07-04T00:00:00:", "2010-07-04T00:00:00-:", "2010-07-04T00:00:00+:",
8399 "2010-07-04T00:00:00-1:", "2010-07-04T00:00:00+1:", "2010-07-04T00:00:00+1:0",
8400 "2010-07-04T00:00:00-12.00", "2010-07-04T00:00:00+12.00",
8401 "2010-07-04T00:00:00-8", "2010-07-04T00:00:00+8",
8402 "20100704T000000-800", "20100704T000000+800",
8403 "20100704T000000-080", "20100704T000000+080",
8404 "20100704T000000-2400", "20100704T000000+2400",
8405 "20100704T000000-1260", "20100704T000000+1260",
8406 "20100704T000000.0-800", "20100704T000000.0+800",
8407 "20100704T000000.0-8", "20100704T000000.0+8",
8408 "20100704T000000.0-080", "20100704T000000.0+080",
8409 "20100704T000000.0-2400", "20100704T000000.0+2400",
8410 "20100704T000000.0-1260", "20100704T000000.0+1260",
8411 "2010-07-04T00:00:00-8:00", "2010-07-04T00:00:00+8:00",
8412 "2010-07-04T00:00:00-24:00", "2010-07-04T00:00:00+24:00",
8413 "2010-07-04T00:00:00-12:60", "2010-07-04T00:00:00+12:60",
8414 "2010-07-04T00:00:00.0-8:00", "2010-07-04T00:00:00.0+8:00",
8415 "2010-07-04T00:00:00.0-8", "2010-07-04T00:00:00.0+8",
8416 "2010-07-04T00:00:00.0-24:00", "2010-07-04T00:00:00.0+24:00",
8417 "2010-07-04T00:00:00.0-12:60", "2010-07-04T00:00:00.0+12:60",
8418 "2010-Jul-0400:00:00", "2010-Jul-04t00:00:00",
8419 "2010-Jul-04 00:00:00.", "2010-Jul-04 00:00:00.0",
8420 "20101222T172201", "2010-Dec-22 17:22:01"])
8421 {
8422 assertThrown!DateTimeException(SysTime.fromISOExtString(str), format("[%s]", str));
8423 }
8424
8425 static void test(string str, SysTime st, size_t line = __LINE__)
8426 {
8427 if (SysTime.fromISOExtString(str) != st)
8428 throw new AssertError("unittest failure", __FILE__, line);
8429 }
8430
8431 test("2010-12-22T17:22:01", SysTime(DateTime(2010, 12, 22, 17, 22, 01)));
8432 test("1999-07-06T12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8433 test("-1999-07-06T12:30:33", SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
8434 test("+01999-07-06T12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8435 test("1999-07-06T12:30:33 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8436 test(" 1999-07-06T12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8437 test(" 1999-07-06T12:30:33 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8438
8439 test("1907-07-07T12:12:12.0", SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
8440 test("1907-07-07T12:12:12.0000000", SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
8441 test("1907-07-07T12:12:12.0000001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), hnsecs(1)));
8442 test("2010-07-04T00:00:00.00000000", SysTime(Date(2010, 07, 04)));
8443 test("2010-07-04T00:00:00.00000009", SysTime(Date(2010, 07, 04)));
8444 test("2010-07-04T00:00:00.00000019", SysTime(DateTime(2010, 07, 04), hnsecs(1)));
8445 test("1907-07-07T12:12:12.000001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), usecs(1)));
8446 test("1907-07-07T12:12:12.0000010", SysTime(DateTime(1907, 07, 07, 12, 12, 12), usecs(1)));
8447 test("1907-07-07T12:12:12.001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), msecs(1)));
8448 test("1907-07-07T12:12:12.0010000", SysTime(DateTime(1907, 07, 07, 12, 12, 12), msecs(1)));
8449
8450 auto west60 = new immutable SimpleTimeZone(hours(-1));
8451 auto west90 = new immutable SimpleTimeZone(minutes(-90));
8452 auto west480 = new immutable SimpleTimeZone(hours(-8));
8453 auto east60 = new immutable SimpleTimeZone(hours(1));
8454 auto east90 = new immutable SimpleTimeZone(minutes(90));
8455 auto east480 = new immutable SimpleTimeZone(hours(8));
8456
8457 test("2010-12-22T17:22:01Z", SysTime(DateTime(2010, 12, 22, 17, 22, 01), UTC()));
8458 test("2010-12-22T17:22:01-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60));
8459 test("2010-12-22T17:22:01-01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60));
8460 test("2010-12-22T17:22:01-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west90));
8461 test("2010-12-22T17:22:01-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west480));
8462 test("2010-12-22T17:22:01+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
8463 test("2010-12-22T17:22:01+01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
8464 test("2010-12-22T17:22:01+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90));
8465 test("2010-12-22T17:22:01+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east480));
8466
8467 test("2010-11-03T06:51:06.57159Z", SysTime(DateTime(2010, 11, 3, 6, 51, 6), hnsecs(5715900), UTC()));
8468 test("2010-12-22T17:22:01.23412Z", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_341_200), UTC()));
8469 test("2010-12-22T17:22:01.23112-01:00",
8470 SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_311_200), west60));
8471 test("2010-12-22T17:22:01.45-01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), west60));
8472 test("2010-12-22T17:22:01.1-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_000_000), west90));
8473 test("2010-12-22T17:22:01.55-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(5_500_000), west480));
8474 test("2010-12-22T17:22:01.1234567+01:00",
8475 SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_234_567), east60));
8476 test("2010-12-22T17:22:01.0+01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
8477 test("2010-12-22T17:22:01.0000000+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90));
8478 test("2010-12-22T17:22:01.45+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), east480));
8479 }
8480
8481 // bug# 17801
8482 @safe unittest
8483 {
8484 import std.conv : to;
8485 import std.meta : AliasSeq;
8486 foreach (C; AliasSeq!(char, wchar, dchar))
8487 {
8488 foreach (S; AliasSeq!(C[], const(C)[], immutable(C)[]))
8489 {
8490 assert(SysTime.fromISOExtString(to!S("2012-12-21T14:15:16Z")) ==
8491 SysTime(DateTime(2012, 12, 21, 14, 15, 16), UTC()));
8492 }
8493 }
8494 }
8495
8496
8497 /++
8498 Creates a $(LREF SysTime) from a string with the format
8499 YYYY-MM-DD HH:MM:SS.FFFFFFFTZ (where F is fractional seconds is the
8500 time zone). Whitespace is stripped from the given string.
8501
8502 The exact format is exactly as described in $(D toSimpleString) except
8503 that trailing zeroes are permitted - including having fractional seconds
8504 with all zeroes. However, a decimal point with nothing following it is
8505 invalid. Also, while $(LREF toSimpleString) will never generate a
8506 string with more than 7 digits in the fractional seconds (because that's
8507 the limit with hecto-nanosecond precision), it will allow more than 7
8508 digits in order to read strings from other sources that have higher
8509 precision (however, any digits beyond 7 will be truncated).
8510
8511 If there is no time zone in the string, then
8512 $(REF LocalTime,std,datetime,timezone) is used. If the time zone is "Z",
8513 then $(D UTC) is used. Otherwise, a
8514 $(REF SimpleTimeZone,std,datetime,timezone) which corresponds to the
8515 given offset from UTC is used. To get the returned $(LREF SysTime) to be
8516 a particular time zone, pass in that time zone and the $(LREF SysTime)
8517 to be returned will be converted to that time zone (though it will still
8518 be read in as whatever time zone is in its string).
8519
8520 The accepted formats for time zone offsets are +HH, -HH, +HH:MM, and
8521 -HH:MM.
8522
8523 Params:
8524 simpleString = A string formatted in the way that
8525 $(D toSimpleString) formats dates and times.
8526 tz = The time zone to convert the given time to (no
8527 conversion occurs if null).
8528
8529 Throws:
8530 $(REF DateTimeException,std,datetime,date) if the given string is
8531 not in the ISO format or if the resulting $(LREF SysTime) would not
8532 be valid.
8533 +/
8534 static SysTime fromSimpleString(S)(in S simpleString, immutable TimeZone tz = null) @safe
8535 if (isSomeString!(S))
8536 {
8537 import std.algorithm.searching : countUntil, find;
8538 import std.conv : to;
8539 import std.string : strip;
8540
8541 auto dstr = to!dstring(strip(simpleString));
8542
8543 auto spaceIndex = dstr.countUntil(' ');
8544 enforce(spaceIndex != -1, new DateTimeException(format("Invalid Simple String: %s", simpleString)));
8545
8546 auto found = dstr[spaceIndex + 1 .. $].find('.', 'Z', '+', '-');
8547 auto dateTimeStr = dstr[0 .. $ - found[0].length];
8548
8549 dstring fracSecStr;
8550 dstring zoneStr;
8551
8552 if (found[1] != 0)
8553 {
8554 if (found[1] == 1)
8555 {
8556 auto foundTZ = found[0].find('Z', '+', '-');
8557
8558 if (foundTZ[1] != 0)
8559 {
8560 fracSecStr = found[0][0 .. $ - foundTZ[0].length];
8561 zoneStr = foundTZ[0];
8562 }
8563 else
8564 fracSecStr = found[0];
8565 }
8566 else
8567 zoneStr = found[0];
8568 }
8569
8570 try
8571 {
8572 auto dateTime = DateTime.fromSimpleString(dateTimeStr);
8573 auto fracSec = fracSecsFromISOString(fracSecStr);
8574 Rebindable!(immutable TimeZone) parsedZone;
8575
8576 if (zoneStr.empty)
8577 parsedZone = LocalTime();
8578 else if (zoneStr == "Z")
8579 parsedZone = UTC();
8580 else
8581 parsedZone = SimpleTimeZone.fromISOExtString(zoneStr);
8582
8583 auto retval = SysTime(dateTime, fracSec, parsedZone);
8584
8585 if (tz !is null)
8586 retval.timezone = tz;
8587
8588 return retval;
8589 }
8590 catch (DateTimeException dte)
8591 throw new DateTimeException(format("Invalid Simple String: %s", simpleString));
8592 }
8593
8594 ///
8595 @safe unittest
8596 {
8597 import core.time : hours, msecs, usecs, hnsecs;
8598 import std.datetime.date : DateTime;
8599 import std.datetime.timezone : SimpleTimeZone, UTC;
8600
8601 assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12") ==
8602 SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
8603
8604 assert(SysTime.fromSimpleString("1998-Dec-25 02:15:00.007") ==
8605 SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(7)));
8606
8607 assert(SysTime.fromSimpleString("0000-Jan-05 23:09:59.00002") ==
8608 SysTime(DateTime(0, 1, 5, 23, 9, 59), usecs(20)));
8609
8610 assert(SysTime.fromSimpleString("2013-Feb-07 04:39:37.000050392") ==
8611 SysTime(DateTime(2013, 2, 7, 4, 39, 37), hnsecs(503)));
8612
8613 assert(SysTime.fromSimpleString("-0004-Jan-05 00:00:02") ==
8614 SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
8615
8616 assert(SysTime.fromSimpleString(" 2010-Jul-04 07:06:12 ") ==
8617 SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
8618
8619 assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12Z") ==
8620 SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
8621
8622 assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12-08:00") ==
8623 SysTime(DateTime(2010, 7, 4, 7, 6, 12),
8624 new immutable SimpleTimeZone(hours(-8))));
8625
8626 assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12+08:00") ==
8627 SysTime(DateTime(2010, 7, 4, 7, 6, 12),
8628 new immutable SimpleTimeZone(hours(8))));
8629 }
8630
8631 @safe unittest
8632 {
8633 foreach (str; ["", "20100704000000", "20100704 000000",
8634 "20100704t000000", "20100704T000000.", "20100704T000000.0",
8635 "2010-07-0400:00:00", "2010-07-04 00:00:00", "2010-07-04t00:00:00",
8636 "2010-07-04T00:00:00.", "2010-07-04T00:00:00.0",
8637 "2010-Jul-0400:00:00", "2010-Jul-04t00:00:00", "2010-Jul-04T00:00:00",
8638 "2010-Jul-04 00:00:00.", "2010-Jul-04 00:00:00.A", "2010-Jul-04 00:00:00.Z",
8639 "2010-Jul-04 00:00:00.0000000A", "2010-Jul-04 00:00:00.00000000A",
8640 "2010-Jul-04 00:00:00+", "2010-Jul-04 00:00:00-",
8641 "2010-Jul-04 00:00:00:", "2010-Jul-04 00:00:00-:",
8642 "2010-Jul-04 00:00:00+:", "2010-Jul-04 00:00:00-1:",
8643 "2010-Jul-04 00:00:00+1:", "2010-Jul-04 00:00:00+1:0",
8644 "2010-Jul-04 00:00:00-12.00", "2010-Jul-04 00:00:00+12.00",
8645 "2010-Jul-04 00:00:00-8", "2010-Jul-04 00:00:00+8",
8646 "20100704T000000-800", "20100704T000000+800",
8647 "20100704T000000-080", "20100704T000000+080",
8648 "20100704T000000-2400", "20100704T000000+2400",
8649 "20100704T000000-1260", "20100704T000000+1260",
8650 "20100704T000000.0-800", "20100704T000000.0+800",
8651 "20100704T000000.0-8", "20100704T000000.0+8",
8652 "20100704T000000.0-080", "20100704T000000.0+080",
8653 "20100704T000000.0-2400", "20100704T000000.0+2400",
8654 "20100704T000000.0-1260", "20100704T000000.0+1260",
8655 "2010-Jul-04 00:00:00-8:00", "2010-Jul-04 00:00:00+8:00",
8656 "2010-Jul-04 00:00:00-08:0", "2010-Jul-04 00:00:00+08:0",
8657 "2010-Jul-04 00:00:00-24:00", "2010-Jul-04 00:00:00+24:00",
8658 "2010-Jul-04 00:00:00-12:60", "2010-Jul-04 00:00:00+24:60",
8659 "2010-Jul-04 00:00:00.0-8:00", "2010-Jul-04 00:00:00+8:00",
8660 "2010-Jul-04 00:00:00.0-8", "2010-Jul-04 00:00:00.0+8",
8661 "2010-Jul-04 00:00:00.0-08:0", "2010-Jul-04 00:00:00.0+08:0",
8662 "2010-Jul-04 00:00:00.0-24:00", "2010-Jul-04 00:00:00.0+24:00",
8663 "2010-Jul-04 00:00:00.0-12:60", "2010-Jul-04 00:00:00.0+24:60",
8664 "20101222T172201", "2010-12-22T172201"])
8665 {
8666 assertThrown!DateTimeException(SysTime.fromSimpleString(str), format("[%s]", str));
8667 }
8668
8669 static void test(string str, SysTime st, size_t line = __LINE__)
8670 {
8671 if (SysTime.fromSimpleString(str) != st)
8672 throw new AssertError("unittest failure", __FILE__, line);
8673 }
8674
8675 test("2010-Dec-22 17:22:01", SysTime(DateTime(2010, 12, 22, 17, 22, 01)));
8676 test("1999-Jul-06 12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8677 test("-1999-Jul-06 12:30:33", SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
8678 test("+01999-Jul-06 12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8679 test("1999-Jul-06 12:30:33 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8680 test(" 1999-Jul-06 12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8681 test(" 1999-Jul-06 12:30:33 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8682
8683 test("1907-Jul-07 12:12:12.0", SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
8684 test("1907-Jul-07 12:12:12.0000000", SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
8685 test("2010-Jul-04 00:00:00.00000000", SysTime(Date(2010, 07, 04)));
8686 test("2010-Jul-04 00:00:00.00000009", SysTime(Date(2010, 07, 04)));
8687 test("2010-Jul-04 00:00:00.00000019", SysTime(DateTime(2010, 07, 04), hnsecs(1)));
8688 test("1907-Jul-07 12:12:12.0000001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), hnsecs(1)));
8689 test("1907-Jul-07 12:12:12.000001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), usecs(1)));
8690 test("1907-Jul-07 12:12:12.0000010", SysTime(DateTime(1907, 07, 07, 12, 12, 12), usecs(1)));
8691 test("1907-Jul-07 12:12:12.001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), msecs(1)));
8692 test("1907-Jul-07 12:12:12.0010000", SysTime(DateTime(1907, 07, 07, 12, 12, 12), msecs(1)));
8693
8694 auto west60 = new immutable SimpleTimeZone(hours(-1));
8695 auto west90 = new immutable SimpleTimeZone(minutes(-90));
8696 auto west480 = new immutable SimpleTimeZone(hours(-8));
8697 auto east60 = new immutable SimpleTimeZone(hours(1));
8698 auto east90 = new immutable SimpleTimeZone(minutes(90));
8699 auto east480 = new immutable SimpleTimeZone(hours(8));
8700
8701 test("2010-Dec-22 17:22:01Z", SysTime(DateTime(2010, 12, 22, 17, 22, 01), UTC()));
8702 test("2010-Dec-22 17:22:01-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60));
8703 test("2010-Dec-22 17:22:01-01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60));
8704 test("2010-Dec-22 17:22:01-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west90));
8705 test("2010-Dec-22 17:22:01-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west480));
8706 test("2010-Dec-22 17:22:01+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
8707 test("2010-Dec-22 17:22:01+01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
8708 test("2010-Dec-22 17:22:01+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90));
8709 test("2010-Dec-22 17:22:01+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east480));
8710
8711 test("2010-Nov-03 06:51:06.57159Z", SysTime(DateTime(2010, 11, 3, 6, 51, 6), hnsecs(5715900), UTC()));
8712 test("2010-Dec-22 17:22:01.23412Z", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_341_200), UTC()));
8713 test("2010-Dec-22 17:22:01.23112-01:00",
8714 SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_311_200), west60));
8715 test("2010-Dec-22 17:22:01.45-01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), west60));
8716 test("2010-Dec-22 17:22:01.1-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_000_000), west90));
8717 test("2010-Dec-22 17:22:01.55-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(5_500_000), west480));
8718 test("2010-Dec-22 17:22:01.1234567+01:00",
8719 SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_234_567), east60));
8720 test("2010-Dec-22 17:22:01.0+01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
8721 test("2010-Dec-22 17:22:01.0000000+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90));
8722 test("2010-Dec-22 17:22:01.45+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), east480));
8723 }
8724
8725 // bug# 17801
8726 @safe unittest
8727 {
8728 import std.conv : to;
8729 import std.meta : AliasSeq;
8730 foreach (C; AliasSeq!(char, wchar, dchar))
8731 {
8732 foreach (S; AliasSeq!(C[], const(C)[], immutable(C)[]))
8733 {
8734 assert(SysTime.fromSimpleString(to!S("2012-Dec-21 14:15:16Z")) ==
8735 SysTime(DateTime(2012, 12, 21, 14, 15, 16), UTC()));
8736 }
8737 }
8738 }
8739
8740
8741 /++
8742 Returns the $(LREF SysTime) farthest in the past which is representable
8743 by $(LREF SysTime).
8744
8745 The $(LREF SysTime) which is returned is in UTC.
8746 +/
8747 @property static SysTime min() @safe pure nothrow
8748 {
8749 return SysTime(long.min, UTC());
8750 }
8751
8752 @safe unittest
8753 {
8754 assert(SysTime.min.year < 0);
8755 assert(SysTime.min < SysTime.max);
8756 }
8757
8758
8759 /++
8760 Returns the $(LREF SysTime) farthest in the future which is representable
8761 by $(LREF SysTime).
8762
8763 The $(LREF SysTime) which is returned is in UTC.
8764 +/
8765 @property static SysTime max() @safe pure nothrow
8766 {
8767 return SysTime(long.max, UTC());
8768 }
8769
8770 @safe unittest
8771 {
8772 assert(SysTime.max.year > 0);
8773 assert(SysTime.max > SysTime.min);
8774 }
8775
8776
8777 private:
8778
8779 /+
8780 Returns $(D stdTime) converted to $(LREF SysTime)'s time zone.
8781 +/
8782 @property long adjTime() @safe const nothrow
8783 {
8784 return _timezone.utcToTZ(_stdTime);
8785 }
8786
8787
8788 /+
8789 Converts the given hnsecs from $(LREF SysTime)'s time zone to std time.
8790 +/
8791 @property void adjTime(long adjTime) @safe nothrow
8792 {
8793 _stdTime = _timezone.tzToUTC(adjTime);
8794 }
8795
8796
8797 // Commented out due to bug http://d.puremagic.com/issues/show_bug.cgi?id=5058
8798 /+
8799 invariant()
8800 {
8801 assert(_timezone !is null, "Invariant Failure: timezone is null. Were you foolish enough to use " ~
8802 "SysTime.init? (since timezone for SysTime.init can't be set at compile time).");
8803 }
8804 +/
8805
8806
8807 long _stdTime;
8808 Rebindable!(immutable TimeZone) _timezone;
8809 }
8810
8811
8812 /++
8813 Converts from unix time (which uses midnight, January 1st, 1970 UTC as its
8814 epoch and seconds as its units) to "std time" (which uses midnight,
8815 January 1st, 1 A.D. UTC and hnsecs as its units).
8816
8817 The C standard does not specify the representation of time_t, so it is
8818 implementation defined. On POSIX systems, unix time is equivalent to
8819 time_t, but that's not necessarily true on other systems (e.g. it is
8820 not true for the Digital Mars C runtime). So, be careful when using unix
8821 time with C functions on non-POSIX systems.
8822
8823 "std time"'s epoch is based on the Proleptic Gregorian Calendar per ISO
8824 8601 and is what $(LREF SysTime) uses internally. However, holding the time
8825 as an integer in hnescs since that epoch technically isn't actually part of
8826 the standard, much as it's based on it, so the name "std time" isn't
8827 particularly good, but there isn't an official name for it. C# uses "ticks"
8828 for the same thing, but they aren't actually clock ticks, and the term
8829 "ticks" $(I is) used for actual clock ticks for $(REF MonoTime, core,time),
8830 so it didn't make sense to use the term ticks here. So, for better or worse,
8831 std.datetime uses the term "std time" for this.
8832
8833 Params:
8834 unixTime = The unix time to convert.
8835
8836 See_Also:
8837 SysTime.fromUnixTime
8838 +/
unixTimeToStdTime(long unixTime)8839 long unixTimeToStdTime(long unixTime) @safe pure nothrow
8840 {
8841 return 621_355_968_000_000_000L + convert!("seconds", "hnsecs")(unixTime);
8842 }
8843
8844 ///
8845 @safe unittest
8846 {
8847 import std.datetime.date : DateTime;
8848 import std.datetime.timezone : UTC;
8849
8850 // Midnight, January 1st, 1970
8851 assert(unixTimeToStdTime(0) == 621_355_968_000_000_000L);
8852 assert(SysTime(unixTimeToStdTime(0)) ==
8853 SysTime(DateTime(1970, 1, 1), UTC()));
8854
8855 assert(unixTimeToStdTime(int.max) == 642_830_804_470_000_000L);
8856 assert(SysTime(unixTimeToStdTime(int.max)) ==
8857 SysTime(DateTime(2038, 1, 19, 3, 14, 07), UTC()));
8858
8859 assert(unixTimeToStdTime(-127_127) == 621_354_696_730_000_000L);
8860 assert(SysTime(unixTimeToStdTime(-127_127)) ==
8861 SysTime(DateTime(1969, 12, 30, 12, 41, 13), UTC()));
8862 }
8863
8864 @safe unittest
8865 {
8866 // Midnight, January 2nd, 1970
8867 assert(unixTimeToStdTime(86_400) == 621_355_968_000_000_000L + 864_000_000_000L);
8868 // Midnight, December 31st, 1969
8869 assert(unixTimeToStdTime(-86_400) == 621_355_968_000_000_000L - 864_000_000_000L);
8870
8871 assert(unixTimeToStdTime(0) == (Date(1970, 1, 1) - Date(1, 1, 1)).total!"hnsecs");
8872 assert(unixTimeToStdTime(0) == (DateTime(1970, 1, 1) - DateTime(1, 1, 1)).total!"hnsecs");
8873
8874 foreach (dt; [DateTime(2010, 11, 1, 19, 5, 22), DateTime(1952, 7, 6, 2, 17, 9)])
8875 assert(unixTimeToStdTime((dt - DateTime(1970, 1, 1)).total!"seconds") == (dt - DateTime.init).total!"hnsecs");
8876 }
8877
8878
8879 /++
8880 Converts std time (which uses midnight, January 1st, 1 A.D. UTC as its epoch
8881 and hnsecs as its units) to unix time (which uses midnight, January 1st,
8882 1970 UTC as its epoch and seconds as its units).
8883
8884 The C standard does not specify the representation of time_t, so it is
8885 implementation defined. On POSIX systems, unix time is equivalent to
8886 time_t, but that's not necessarily true on other systems (e.g. it is
8887 not true for the Digital Mars C runtime). So, be careful when using unix
8888 time with C functions on non-POSIX systems.
8889
8890 "std time"'s epoch is based on the Proleptic Gregorian Calendar per ISO
8891 8601 and is what $(LREF SysTime) uses internally. However, holding the time
8892 as an integer in hnescs since that epoch technically isn't actually part of
8893 the standard, much as it's based on it, so the name "std time" isn't
8894 particularly good, but there isn't an official name for it. C# uses "ticks"
8895 for the same thing, but they aren't actually clock ticks, and the term
8896 "ticks" $(I is) used for actual clock ticks for $(REF MonoTime, core,time),
8897 so it didn't make sense to use the term ticks here. So, for better or worse,
8898 std.datetime uses the term "std time" for this.
8899
8900 By default, the return type is time_t (which is normally an alias for
8901 int on 32-bit systems and long on 64-bit systems), but if a different
8902 size is required than either int or long can be passed as a template
8903 argument to get the desired size.
8904
8905 If the return type is int, and the result can't fit in an int, then the
8906 closest value that can be held in 32 bits will be used (so $(D int.max)
8907 if it goes over and $(D int.min) if it goes under). However, no attempt
8908 is made to deal with integer overflow if the return type is long.
8909
8910 Params:
8911 T = The return type (int or long). It defaults to time_t, which is
8912 normally 32 bits on a 32-bit system and 64 bits on a 64-bit
8913 system.
8914 stdTime = The std time to convert.
8915
8916 Returns:
8917 A signed integer representing the unix time which is equivalent to
8918 the given std time.
8919
8920 See_Also:
8921 SysTime.toUnixTime
8922 +/
8923 T stdTimeToUnixTime(T = time_t)(long stdTime) @safe pure nothrow
8924 if (is(T == int) || is(T == long))
8925 {
8926 immutable unixTime = convert!("hnsecs", "seconds")(stdTime - 621_355_968_000_000_000L);
8927
8928 static assert(is(time_t == int) || is(time_t == long),
8929 "Currently, std.datetime only supports systems where time_t is int or long");
8930
8931 static if (is(T == long))
8932 return unixTime;
8933 else static if (is(T == int))
8934 {
8935 if (unixTime > int.max)
8936 return int.max;
8937 return unixTime < int.min ? int.min : cast(int) unixTime;
8938 }
8939 else
8940 static assert(0, "Bug in template constraint. Only int and long allowed.");
8941 }
8942
8943 ///
8944 @safe unittest
8945 {
8946 // Midnight, January 1st, 1970 UTC
8947 assert(stdTimeToUnixTime(621_355_968_000_000_000L) == 0);
8948
8949 // 2038-01-19 03:14:07 UTC
8950 assert(stdTimeToUnixTime(642_830_804_470_000_000L) == int.max);
8951 }
8952
8953 @safe unittest
8954 {
8955 enum unixEpochAsStdTime = (Date(1970, 1, 1) - Date.init).total!"hnsecs";
8956
8957 assert(stdTimeToUnixTime(unixEpochAsStdTime) == 0); // Midnight, January 1st, 1970
8958 assert(stdTimeToUnixTime(unixEpochAsStdTime + 864_000_000_000L) == 86_400); // Midnight, January 2nd, 1970
8959 assert(stdTimeToUnixTime(unixEpochAsStdTime - 864_000_000_000L) == -86_400); // Midnight, December 31st, 1969
8960
8961 assert(stdTimeToUnixTime((Date(1970, 1, 1) - Date(1, 1, 1)).total!"hnsecs") == 0);
8962 assert(stdTimeToUnixTime((DateTime(1970, 1, 1) - DateTime(1, 1, 1)).total!"hnsecs") == 0);
8963
8964 foreach (dt; [DateTime(2010, 11, 1, 19, 5, 22), DateTime(1952, 7, 6, 2, 17, 9)])
8965 assert(stdTimeToUnixTime((dt - DateTime.init).total!"hnsecs") == (dt - DateTime(1970, 1, 1)).total!"seconds");
8966
8967 enum max = convert!("seconds", "hnsecs")(int.max);
8968 enum min = convert!("seconds", "hnsecs")(int.min);
8969 enum one = convert!("seconds", "hnsecs")(1);
8970
8971 assert(stdTimeToUnixTime!long(unixEpochAsStdTime + max) == int.max);
8972 assert(stdTimeToUnixTime!int(unixEpochAsStdTime + max) == int.max);
8973
8974 assert(stdTimeToUnixTime!long(unixEpochAsStdTime + max + one) == int.max + 1L);
8975 assert(stdTimeToUnixTime!int(unixEpochAsStdTime + max + one) == int.max);
8976 assert(stdTimeToUnixTime!long(unixEpochAsStdTime + max + 9_999_999) == int.max);
8977 assert(stdTimeToUnixTime!int(unixEpochAsStdTime + max + 9_999_999) == int.max);
8978
8979 assert(stdTimeToUnixTime!long(unixEpochAsStdTime + min) == int.min);
8980 assert(stdTimeToUnixTime!int(unixEpochAsStdTime + min) == int.min);
8981
8982 assert(stdTimeToUnixTime!long(unixEpochAsStdTime + min - one) == int.min - 1L);
8983 assert(stdTimeToUnixTime!int(unixEpochAsStdTime + min - one) == int.min);
8984 assert(stdTimeToUnixTime!long(unixEpochAsStdTime + min - 9_999_999) == int.min);
8985 assert(stdTimeToUnixTime!int(unixEpochAsStdTime + min - 9_999_999) == int.min);
8986 }
8987
8988
version(StdDdoc)8989 version (StdDdoc)
8990 {
8991 version (Windows)
8992 {}
8993 else
8994 {
8995 alias SYSTEMTIME = void*;
8996 alias FILETIME = void*;
8997 }
8998
8999 /++
9000 $(BLUE This function is Windows-Only.)
9001
9002 Converts a $(D SYSTEMTIME) struct to a $(LREF SysTime).
9003
9004 Params:
9005 st = The $(D SYSTEMTIME) struct to convert.
9006 tz = The time zone that the time in the $(D SYSTEMTIME) struct is
9007 assumed to be (if the $(D SYSTEMTIME) was supplied by a Windows
9008 system call, the $(D SYSTEMTIME) will either be in local time
9009 or UTC, depending on the call).
9010
9011 Throws:
9012 $(REF DateTimeException,std,datetime,date) if the given
9013 $(D SYSTEMTIME) will not fit in a $(LREF SysTime), which is highly
9014 unlikely to happen given that $(D SysTime.max) is in 29,228 A.D. and
9015 the maximum $(D SYSTEMTIME) is in 30,827 A.D.
9016 +/
9017 SysTime SYSTEMTIMEToSysTime(const SYSTEMTIME* st, immutable TimeZone tz = LocalTime()) @safe;
9018
9019
9020 /++
9021 $(BLUE This function is Windows-Only.)
9022
9023 Converts a $(LREF SysTime) to a $(D SYSTEMTIME) struct.
9024
9025 The $(D SYSTEMTIME) which is returned will be set using the given
9026 $(LREF SysTime)'s time zone, so to get the $(D SYSTEMTIME) in
9027 UTC, set the $(LREF SysTime)'s time zone to UTC.
9028
9029 Params:
9030 sysTime = The $(LREF SysTime) to convert.
9031
9032 Throws:
9033 $(REF DateTimeException,std,datetime,date) if the given
9034 $(LREF SysTime) will not fit in a $(D SYSTEMTIME). This will only
9035 happen if the $(LREF SysTime)'s date is prior to 1601 A.D.
9036 +/
9037 SYSTEMTIME SysTimeToSYSTEMTIME(in SysTime sysTime) @safe;
9038
9039
9040 /++
9041 $(BLUE This function is Windows-Only.)
9042
9043 Converts a $(D FILETIME) struct to the number of hnsecs since midnight,
9044 January 1st, 1 A.D.
9045
9046 Params:
9047 ft = The $(D FILETIME) struct to convert.
9048
9049 Throws:
9050 $(REF DateTimeException,std,datetime,date) if the given
9051 $(D FILETIME) cannot be represented as the return value.
9052 +/
9053 long FILETIMEToStdTime(scope const FILETIME* ft) @safe;
9054
9055
9056 /++
9057 $(BLUE This function is Windows-Only.)
9058
9059 Converts a $(D FILETIME) struct to a $(LREF SysTime).
9060
9061 Params:
9062 ft = The $(D FILETIME) struct to convert.
9063 tz = The time zone that the $(LREF SysTime) will be in
9064 ($(D FILETIME)s are in UTC).
9065
9066 Throws:
9067 $(REF DateTimeException,std,datetime,date) if the given
9068 $(D FILETIME) will not fit in a $(LREF SysTime).
9069 +/
9070 SysTime FILETIMEToSysTime(scope const FILETIME* ft, immutable TimeZone tz = LocalTime()) @safe;
9071
9072
9073 /++
9074 $(BLUE This function is Windows-Only.)
9075
9076 Converts a number of hnsecs since midnight, January 1st, 1 A.D. to a
9077 $(D FILETIME) struct.
9078
9079 Params:
9080 stdTime = The number of hnsecs since midnight, January 1st, 1 A.D.
9081 UTC.
9082
9083 Throws:
9084 $(REF DateTimeException,std,datetime,date) if the given value will
9085 not fit in a $(D FILETIME).
9086 +/
9087 FILETIME stdTimeToFILETIME(long stdTime) @safe;
9088
9089
9090 /++
9091 $(BLUE This function is Windows-Only.)
9092
9093 Converts a $(LREF SysTime) to a $(D FILETIME) struct.
9094
9095 $(D FILETIME)s are always in UTC.
9096
9097 Params:
9098 sysTime = The $(LREF SysTime) to convert.
9099
9100 Throws:
9101 $(REF DateTimeException,std,datetime,date) if the given
9102 $(LREF SysTime) will not fit in a $(D FILETIME).
9103 +/
9104 FILETIME SysTimeToFILETIME(SysTime sysTime) @safe;
9105 }
9106 else version (Windows)
9107 {
9108 SysTime SYSTEMTIMEToSysTime(const SYSTEMTIME* st, immutable TimeZone tz = LocalTime()) @safe
9109 {
9110 const max = SysTime.max;
9111
9112 static void throwLaterThanMax()
9113 {
9114 throw new DateTimeException("The given SYSTEMTIME is for a date greater than SysTime.max.");
9115 }
9116
9117 if (st.wYear > max.year)
9118 throwLaterThanMax();
9119 else if (st.wYear == max.year)
9120 {
9121 if (st.wMonth > max.month)
9122 throwLaterThanMax();
9123 else if (st.wMonth == max.month)
9124 {
9125 if (st.wDay > max.day)
9126 throwLaterThanMax();
9127 else if (st.wDay == max.day)
9128 {
9129 if (st.wHour > max.hour)
9130 throwLaterThanMax();
9131 else if (st.wHour == max.hour)
9132 {
9133 if (st.wMinute > max.minute)
9134 throwLaterThanMax();
9135 else if (st.wMinute == max.minute)
9136 {
9137 if (st.wSecond > max.second)
9138 throwLaterThanMax();
9139 else if (st.wSecond == max.second)
9140 {
9141 if (st.wMilliseconds > max.fracSecs.total!"msecs")
9142 throwLaterThanMax();
9143 }
9144 }
9145 }
9146 }
9147 }
9148 }
9149
9150 auto dt = DateTime(st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
9151
9152 return SysTime(dt, msecs(st.wMilliseconds), tz);
9153 }
9154
9155 @system unittest
9156 {
9157 auto sysTime = Clock.currTime(UTC());
9158 SYSTEMTIME st = void;
9159 GetSystemTime(&st);
9160 auto converted = SYSTEMTIMEToSysTime(&st, UTC());
9161
9162 assert(abs((converted - sysTime)) <= dur!"seconds"(2));
9163 }
9164
9165
9166 SYSTEMTIME SysTimeToSYSTEMTIME(in SysTime sysTime) @safe
9167 {
9168 immutable dt = cast(DateTime) sysTime;
9169
9170 if (dt.year < 1601)
9171 throw new DateTimeException("SYSTEMTIME cannot hold dates prior to the year 1601.");
9172
9173 SYSTEMTIME st;
9174
9175 st.wYear = dt.year;
9176 st.wMonth = dt.month;
9177 st.wDayOfWeek = dt.dayOfWeek;
9178 st.wDay = dt.day;
9179 st.wHour = dt.hour;
9180 st.wMinute = dt.minute;
9181 st.wSecond = dt.second;
9182 st.wMilliseconds = cast(ushort) sysTime.fracSecs.total!"msecs";
9183
9184 return st;
9185 }
9186
9187 @system unittest
9188 {
9189 SYSTEMTIME st = void;
9190 GetSystemTime(&st);
9191 auto sysTime = SYSTEMTIMEToSysTime(&st, UTC());
9192
9193 SYSTEMTIME result = SysTimeToSYSTEMTIME(sysTime);
9194
9195 assert(st.wYear == result.wYear);
9196 assert(st.wMonth == result.wMonth);
9197 assert(st.wDayOfWeek == result.wDayOfWeek);
9198 assert(st.wDay == result.wDay);
9199 assert(st.wHour == result.wHour);
9200 assert(st.wMinute == result.wMinute);
9201 assert(st.wSecond == result.wSecond);
9202 assert(st.wMilliseconds == result.wMilliseconds);
9203 }
9204
9205 private enum hnsecsFrom1601 = 504_911_232_000_000_000L;
9206
9207 long FILETIMEToStdTime(scope const FILETIME* ft) @safe
9208 {
9209 ULARGE_INTEGER ul;
9210 ul.HighPart = ft.dwHighDateTime;
9211 ul.LowPart = ft.dwLowDateTime;
9212 ulong tempHNSecs = ul.QuadPart;
9213
9214 if (tempHNSecs > long.max - hnsecsFrom1601)
9215 throw new DateTimeException("The given FILETIME cannot be represented as a stdTime value.");
9216
9217 return cast(long) tempHNSecs + hnsecsFrom1601;
9218 }
9219
9220 SysTime FILETIMEToSysTime(scope const FILETIME* ft, immutable TimeZone tz = LocalTime()) @safe
9221 {
9222 auto sysTime = SysTime(FILETIMEToStdTime(ft), UTC());
9223 sysTime.timezone = tz;
9224 return sysTime;
9225 }
9226
9227 @system unittest
9228 {
9229 auto sysTime = Clock.currTime(UTC());
9230 SYSTEMTIME st = void;
9231 GetSystemTime(&st);
9232
9233 FILETIME ft = void;
9234 SystemTimeToFileTime(&st, &ft);
9235
9236 auto converted = FILETIMEToSysTime(&ft);
9237
9238 assert(abs((converted - sysTime)) <= dur!"seconds"(2));
9239 }
9240
9241
9242 FILETIME stdTimeToFILETIME(long stdTime) @safe
9243 {
9244 if (stdTime < hnsecsFrom1601)
9245 throw new DateTimeException("The given stdTime value cannot be represented as a FILETIME.");
9246
9247 ULARGE_INTEGER ul;
9248 ul.QuadPart = cast(ulong) stdTime - hnsecsFrom1601;
9249
9250 FILETIME ft;
9251 ft.dwHighDateTime = ul.HighPart;
9252 ft.dwLowDateTime = ul.LowPart;
9253
9254 return ft;
9255 }
9256
9257 FILETIME SysTimeToFILETIME(SysTime sysTime) @safe
9258 {
9259 return stdTimeToFILETIME(sysTime.stdTime);
9260 }
9261
9262 @system unittest
9263 {
9264 SYSTEMTIME st = void;
9265 GetSystemTime(&st);
9266
9267 FILETIME ft = void;
9268 SystemTimeToFileTime(&st, &ft);
9269 auto sysTime = FILETIMEToSysTime(&ft, UTC());
9270
9271 FILETIME result = SysTimeToFILETIME(sysTime);
9272
9273 assert(ft.dwLowDateTime == result.dwLowDateTime);
9274 assert(ft.dwHighDateTime == result.dwHighDateTime);
9275 }
9276 }
9277
9278
9279 /++
9280 Type representing the DOS file date/time format.
9281 +/
9282 alias DosFileTime = uint;
9283
9284 /++
9285 Converts from DOS file date/time to $(LREF SysTime).
9286
9287 Params:
9288 dft = The DOS file time to convert.
9289 tz = The time zone which the DOS file time is assumed to be in.
9290
9291 Throws:
9292 $(REF DateTimeException,std,datetime,date) if the $(D DosFileTime) is
9293 invalid.
9294 +/
9295 SysTime DosFileTimeToSysTime(DosFileTime dft, immutable TimeZone tz = LocalTime()) @safe
9296 {
9297 uint dt = cast(uint) dft;
9298
9299 if (dt == 0)
9300 throw new DateTimeException("Invalid DosFileTime.");
9301
9302 int year = ((dt >> 25) & 0x7F) + 1980;
9303 int month = ((dt >> 21) & 0x0F); // 1 .. 12
9304 int dayOfMonth = ((dt >> 16) & 0x1F); // 1 .. 31
9305 int hour = (dt >> 11) & 0x1F; // 0 .. 23
9306 int minute = (dt >> 5) & 0x3F; // 0 .. 59
9307 int second = (dt << 1) & 0x3E; // 0 .. 58 (in 2 second increments)
9308
9309 try
9310 return SysTime(DateTime(year, month, dayOfMonth, hour, minute, second), tz);
9311 catch (DateTimeException dte)
9312 throw new DateTimeException("Invalid DosFileTime", __FILE__, __LINE__, dte);
9313 }
9314
9315 @safe unittest
9316 {
9317 assert(DosFileTimeToSysTime(0b00000000001000010000000000000000) == SysTime(DateTime(1980, 1, 1, 0, 0, 0)));
9318 assert(DosFileTimeToSysTime(0b11111111100111111011111101111101) == SysTime(DateTime(2107, 12, 31, 23, 59, 58)));
9319 assert(DosFileTimeToSysTime(0x3E3F8456) == SysTime(DateTime(2011, 1, 31, 16, 34, 44)));
9320 }
9321
9322
9323 /++
9324 Converts from $(LREF SysTime) to DOS file date/time.
9325
9326 Params:
9327 sysTime = The $(LREF SysTime) to convert.
9328
9329 Throws:
9330 $(REF DateTimeException,std,datetime,date) if the given
9331 $(LREF SysTime) cannot be converted to a $(D DosFileTime).
9332 +/
9333 DosFileTime SysTimeToDosFileTime(SysTime sysTime) @safe
9334 {
9335 auto dateTime = cast(DateTime) sysTime;
9336
9337 if (dateTime.year < 1980)
9338 throw new DateTimeException("DOS File Times cannot hold dates prior to 1980.");
9339
9340 if (dateTime.year > 2107)
9341 throw new DateTimeException("DOS File Times cannot hold dates past 2107.");
9342
9343 uint retval = 0;
9344 retval = (dateTime.year - 1980) << 25;
9345 retval |= (dateTime.month & 0x0F) << 21;
9346 retval |= (dateTime.day & 0x1F) << 16;
9347 retval |= (dateTime.hour & 0x1F) << 11;
9348 retval |= (dateTime.minute & 0x3F) << 5;
9349 retval |= (dateTime.second >> 1) & 0x1F;
9350
9351 return cast(DosFileTime) retval;
9352 }
9353
9354 @safe unittest
9355 {
9356 assert(SysTimeToDosFileTime(SysTime(DateTime(1980, 1, 1, 0, 0, 0))) == 0b00000000001000010000000000000000);
9357 assert(SysTimeToDosFileTime(SysTime(DateTime(2107, 12, 31, 23, 59, 58))) == 0b11111111100111111011111101111101);
9358 assert(SysTimeToDosFileTime(SysTime(DateTime(2011, 1, 31, 16, 34, 44))) == 0x3E3F8456);
9359 }
9360
9361
9362 /++
9363 The given array of $(D char) or random-access range of $(D char) or
9364 $(D ubyte) is expected to be in the format specified in
9365 $(HTTP tools.ietf.org/html/rfc5322, RFC 5322) section 3.3 with the
9366 grammar rule $(I date-time). It is the date-time format commonly used in
9367 internet messages such as e-mail and HTTP. The corresponding
9368 $(LREF SysTime) will be returned.
9369
9370 RFC 822 was the original spec (hence the function's name), whereas RFC 5322
9371 is the current spec.
9372
9373 The day of the week is ignored beyond verifying that it's a valid day of the
9374 week, as the day of the week can be inferred from the date. It is not
9375 checked whether the given day of the week matches the actual day of the week
9376 of the given date (though it is technically invalid per the spec if the
9377 day of the week doesn't match the actual day of the week of the given date).
9378
9379 If the time zone is $(D "-0000") (or considered to be equivalent to
9380 $(D "-0000") by section 4.3 of the spec), a
9381 $(REF SimpleTimeZone,std,datetime,timezone) with a utc offset of $(D 0) is
9382 used rather than $(REF UTC,std,datetime,timezone), whereas $(D "+0000") uses
9383 $(REF UTC,std,datetime,timezone).
9384
9385 Note that because $(LREF SysTime) does not currently support having a second
9386 value of 60 (as is sometimes done for leap seconds), if the date-time value
9387 does have a value of 60 for the seconds, it is treated as 59.
9388
9389 The one area in which this function violates RFC 5322 is that it accepts
9390 $(D "\n") in folding whitespace in the place of $(D "\r\n"), because the
9391 HTTP spec requires it.
9392
9393 Throws:
9394 $(REF DateTimeException,std,datetime,date) if the given string doesn't
9395 follow the grammar for a date-time field or if the resulting
9396 $(LREF SysTime) is invalid.
9397 +/
9398 SysTime parseRFC822DateTime()(in char[] value) @safe
9399 {
9400 import std.string : representation;
9401 return parseRFC822DateTime(value.representation);
9402 }
9403
9404 /++ Ditto +/
9405 SysTime parseRFC822DateTime(R)(R value) @safe
9406 if (isRandomAccessRange!R && hasSlicing!R && hasLength!R &&
9407 (is(Unqual!(ElementType!R) == char) || is(Unqual!(ElementType!R) == ubyte)))
9408 {
9409 import std.algorithm.searching : find, all;
9410 import std.ascii : isDigit, isAlpha, isPrintable;
9411 import std.conv : to;
9412 import std.functional : not;
9413 import std.string : capitalize, format;
9414 import std.traits : EnumMembers, isArray;
9415 import std.typecons : Rebindable;
9416
9417 void stripAndCheckLen(R valueBefore, size_t minLen, size_t line = __LINE__)
9418 {
9419 value = _stripCFWS(valueBefore);
9420 if (value.length < minLen)
9421 throw new DateTimeException("date-time value too short", __FILE__, line);
9422 }
9423 stripAndCheckLen(value, "7Dec1200:00A".length);
9424
9425 static if (isArray!R && (is(ElementEncodingType!R == char) || is(ElementEncodingType!R == ubyte)))
9426 {
9427 static string sliceAsString(R str) @trusted
9428 {
9429 return cast(string) str;
9430 }
9431 }
9432 else
9433 {
9434 char[4] temp;
9435 char[] sliceAsString(R str) @trusted
9436 {
9437 size_t i = 0;
9438 foreach (c; str)
9439 temp[i++] = cast(char) c;
9440 return temp[0 .. str.length];
9441 }
9442 }
9443
9444 // day-of-week
9445 if (isAlpha(value[0]))
9446 {
9447 auto dowStr = sliceAsString(value[0 .. 3]);
9448 switch (dowStr)
9449 {
9450 foreach (dow; EnumMembers!DayOfWeek)
9451 {
9452 enum dowC = capitalize(to!string(dow));
9453 case dowC:
9454 goto afterDoW;
9455 }
9456 default: throw new DateTimeException(format("Invalid day-of-week: %s", dowStr));
9457 }
9458 afterDoW: stripAndCheckLen(value[3 .. value.length], ",7Dec1200:00A".length);
9459 if (value[0] != ',')
9460 throw new DateTimeException("day-of-week missing comma");
9461 stripAndCheckLen(value[1 .. value.length], "7Dec1200:00A".length);
9462 }
9463
9464 // day
9465 immutable digits = isDigit(value[1]) ? 2 : 1;
9466 immutable day = _convDigits!short(value[0 .. digits]);
9467 if (day == -1)
9468 throw new DateTimeException("Invalid day");
9469 stripAndCheckLen(value[digits .. value.length], "Dec1200:00A".length);
9470
9471 // month
9472 Month month;
9473 {
9474 auto monStr = sliceAsString(value[0 .. 3]);
9475 switch (monStr)
9476 {
9477 foreach (mon; EnumMembers!Month)
9478 {
9479 enum monC = capitalize(to!string(mon));
9480 case monC:
9481 {
9482 month = mon;
9483 goto afterMon;
9484 }
9485 }
9486 default: throw new DateTimeException(format("Invalid month: %s", monStr));
9487 }
9488 afterMon: stripAndCheckLen(value[3 .. value.length], "1200:00A".length);
9489 }
9490
9491 // year
9492 auto found = value[2 .. value.length].find!(not!(std.ascii.isDigit))();
9493 size_t yearLen = value.length - found.length;
9494 if (found.length == 0)
9495 throw new DateTimeException("Invalid year");
9496 if (found[0] == ':')
9497 yearLen -= 2;
9498 auto year = _convDigits!short(value[0 .. yearLen]);
9499 if (year < 1900)
9500 {
9501 if (year == -1)
9502 throw new DateTimeException("Invalid year");
9503 if (yearLen < 4)
9504 {
9505 if (yearLen == 3)
9506 year += 1900;
9507 else if (yearLen == 2)
9508 year += year < 50 ? 2000 : 1900;
9509 else
9510 throw new DateTimeException("Invalid year. Too few digits.");
9511 }
9512 else
9513 throw new DateTimeException("Invalid year. Cannot be earlier than 1900.");
9514 }
9515 stripAndCheckLen(value[yearLen .. value.length], "00:00A".length);
9516
9517 // hour
9518 immutable hour = _convDigits!short(value[0 .. 2]);
9519 stripAndCheckLen(value[2 .. value.length], ":00A".length);
9520 if (value[0] != ':')
9521 throw new DateTimeException("Invalid hour");
9522 stripAndCheckLen(value[1 .. value.length], "00A".length);
9523
9524 // minute
9525 immutable minute = _convDigits!short(value[0 .. 2]);
9526 stripAndCheckLen(value[2 .. value.length], "A".length);
9527
9528 // second
9529 short second;
9530 if (value[0] == ':')
9531 {
9532 stripAndCheckLen(value[1 .. value.length], "00A".length);
9533 second = _convDigits!short(value[0 .. 2]);
9534 // this is just if/until SysTime is sorted out to fully support leap seconds
9535 if (second == 60)
9536 second = 59;
9537 stripAndCheckLen(value[2 .. value.length], "A".length);
9538 }
9539
9540 immutable(TimeZone) parseTZ(int sign)
9541 {
9542 if (value.length < 5)
9543 throw new DateTimeException("Invalid timezone");
9544 immutable zoneHours = _convDigits!short(value[1 .. 3]);
9545 immutable zoneMinutes = _convDigits!short(value[3 .. 5]);
9546 if (zoneHours == -1 || zoneMinutes == -1 || zoneMinutes > 59)
9547 throw new DateTimeException("Invalid timezone");
9548 value = value[5 .. value.length];
9549 immutable utcOffset = (dur!"hours"(zoneHours) + dur!"minutes"(zoneMinutes)) * sign;
9550 if (utcOffset == Duration.zero)
9551 {
9552 return sign == 1 ? cast(immutable(TimeZone))UTC()
9553 : cast(immutable(TimeZone))new immutable SimpleTimeZone(Duration.zero);
9554 }
9555 return new immutable(SimpleTimeZone)(utcOffset);
9556 }
9557
9558 // zone
9559 Rebindable!(immutable TimeZone) tz;
9560 if (value[0] == '-')
9561 tz = parseTZ(-1);
9562 else if (value[0] == '+')
9563 tz = parseTZ(1);
9564 else
9565 {
9566 // obs-zone
9567 immutable tzLen = value.length - find(value, ' ', '\t', '(')[0].length;
9568 switch (sliceAsString(value[0 .. tzLen <= 4 ? tzLen : 4]))
9569 {
9570 case "UT": case "GMT": tz = UTC(); break;
9571 case "EST": tz = new immutable SimpleTimeZone(dur!"hours"(-5)); break;
9572 case "EDT": tz = new immutable SimpleTimeZone(dur!"hours"(-4)); break;
9573 case "CST": tz = new immutable SimpleTimeZone(dur!"hours"(-6)); break;
9574 case "CDT": tz = new immutable SimpleTimeZone(dur!"hours"(-5)); break;
9575 case "MST": tz = new immutable SimpleTimeZone(dur!"hours"(-7)); break;
9576 case "MDT": tz = new immutable SimpleTimeZone(dur!"hours"(-6)); break;
9577 case "PST": tz = new immutable SimpleTimeZone(dur!"hours"(-8)); break;
9578 case "PDT": tz = new immutable SimpleTimeZone(dur!"hours"(-7)); break;
9579 case "J": case "j": throw new DateTimeException("Invalid timezone");
9580 default:
9581 {
9582 if (all!(std.ascii.isAlpha)(value[0 .. tzLen]))
9583 {
9584 tz = new immutable SimpleTimeZone(Duration.zero);
9585 break;
9586 }
9587 throw new DateTimeException("Invalid timezone");
9588 }
9589 }
9590 value = value[tzLen .. value.length];
9591 }
9592
9593 // This is kind of arbitrary. Technically, nothing but CFWS is legal past
9594 // the end of the timezone, but we don't want to be picky about that in a
9595 // function that's just parsing rather than validating. So, the idea here is
9596 // that if the next character is printable (and not part of CFWS), then it
9597 // might be part of the timezone and thus affect what the timezone was
9598 // supposed to be, so we'll throw, but otherwise, we'll just ignore it.
9599 if (!value.empty && isPrintable(value[0]) && value[0] != ' ' && value[0] != '(')
9600 throw new DateTimeException("Invalid timezone");
9601
9602 try
9603 return SysTime(DateTime(year, month, day, hour, minute, second), tz);
9604 catch (DateTimeException dte)
9605 throw new DateTimeException("date-time format is correct, but the resulting SysTime is invalid.", dte);
9606 }
9607
9608 ///
9609 @safe unittest
9610 {
9611 import core.time : hours;
9612 import std.datetime.date : DateTime, DateTimeException;
9613 import std.datetime.timezone : SimpleTimeZone, UTC;
9614 import std.exception : assertThrown;
9615
9616 auto tz = new immutable SimpleTimeZone(hours(-8));
9617 assert(parseRFC822DateTime("Sat, 6 Jan 1990 12:14:19 -0800") ==
9618 SysTime(DateTime(1990, 1, 6, 12, 14, 19), tz));
9619
9620 assert(parseRFC822DateTime("9 Jul 2002 13:11 +0000") ==
9621 SysTime(DateTime(2002, 7, 9, 13, 11, 0), UTC()));
9622
9623 auto badStr = "29 Feb 2001 12:17:16 +0200";
9624 assertThrown!DateTimeException(parseRFC822DateTime(badStr));
9625 }
9626
version(unittest)9627 version (unittest) void testParse822(alias cr)(string str, SysTime expected, size_t line = __LINE__)
9628 {
9629 import std.format : format;
9630 auto value = cr(str);
9631 auto result = parseRFC822DateTime(value);
9632 if (result != expected)
9633 throw new AssertError(format("wrong result. expected [%s], actual[%s]", expected, result), __FILE__, line);
9634 }
9635
version(unittest)9636 version (unittest) void testBadParse822(alias cr)(string str, size_t line = __LINE__)
9637 {
9638 try
9639 parseRFC822DateTime(cr(str));
9640 catch (DateTimeException)
9641 return;
9642 throw new AssertError("No DateTimeException was thrown", __FILE__, line);
9643 }
9644
9645 @system unittest
9646 {
9647 import std.algorithm.iteration : filter, map;
9648 import std.algorithm.searching : canFind;
9649 import std.array : array;
9650 import std.ascii : letters;
9651 import std.format : format;
9652 import std.meta : AliasSeq;
9653 import std.range : chain, iota, take;
9654 import std.stdio : writefln, writeln;
9655 import std.string : representation;
9656
9657 static struct Rand3Letters
9658 {
9659 enum empty = false;
frontRand3Letters9660 @property auto front() { return _mon; }
popFrontRand3Letters9661 void popFront()
9662 {
9663 import std.exception : assumeUnique;
9664 import std.random : rndGen;
9665 _mon = rndGen.map!(a => letters[a % letters.length])().take(3).array().assumeUnique();
9666 }
9667 string _mon;
startRand3Letters9668 static auto start() { Rand3Letters retval; retval.popFront(); return retval; }
9669 }
9670
9671 foreach (cr; AliasSeq!(function(string a){return cast(char[]) a;},
9672 function(string a){return cast(ubyte[]) a;},
9673 function(string a){return a;},
9674 function(string a){return map!(b => cast(char) b)(a.representation);}))
9675 (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396
9676 scope(failure) writeln(typeof(cr).stringof);
9677 alias test = testParse822!cr;
9678 alias testBad = testBadParse822!cr;
9679
9680 immutable std1 = DateTime(2012, 12, 21, 13, 14, 15);
9681 immutable std2 = DateTime(2012, 12, 21, 13, 14, 0);
9682 immutable dst1 = DateTime(1976, 7, 4, 5, 4, 22);
9683 immutable dst2 = DateTime(1976, 7, 4, 5, 4, 0);
9684
9685 test("21 Dec 2012 13:14:15 +0000", SysTime(std1, UTC()));
9686 test("21 Dec 2012 13:14 +0000", SysTime(std2, UTC()));
9687 test("Fri, 21 Dec 2012 13:14 +0000", SysTime(std2, UTC()));
9688 test("Fri, 21 Dec 2012 13:14:15 +0000", SysTime(std1, UTC()));
9689
9690 test("04 Jul 1976 05:04:22 +0000", SysTime(dst1, UTC()));
9691 test("04 Jul 1976 05:04 +0000", SysTime(dst2, UTC()));
9692 test("Sun, 04 Jul 1976 05:04 +0000", SysTime(dst2, UTC()));
9693 test("Sun, 04 Jul 1976 05:04:22 +0000", SysTime(dst1, UTC()));
9694
9695 test("4 Jul 1976 05:04:22 +0000", SysTime(dst1, UTC()));
9696 test("4 Jul 1976 05:04 +0000", SysTime(dst2, UTC()));
9697 test("Sun, 4 Jul 1976 05:04 +0000", SysTime(dst2, UTC()));
9698 test("Sun, 4 Jul 1976 05:04:22 +0000", SysTime(dst1, UTC()));
9699
9700 auto badTZ = new immutable SimpleTimeZone(Duration.zero);
9701 test("21 Dec 2012 13:14:15 -0000", SysTime(std1, badTZ));
9702 test("21 Dec 2012 13:14 -0000", SysTime(std2, badTZ));
9703 test("Fri, 21 Dec 2012 13:14 -0000", SysTime(std2, badTZ));
9704 test("Fri, 21 Dec 2012 13:14:15 -0000", SysTime(std1, badTZ));
9705
9706 test("04 Jul 1976 05:04:22 -0000", SysTime(dst1, badTZ));
9707 test("04 Jul 1976 05:04 -0000", SysTime(dst2, badTZ));
9708 test("Sun, 04 Jul 1976 05:04 -0000", SysTime(dst2, badTZ));
9709 test("Sun, 04 Jul 1976 05:04:22 -0000", SysTime(dst1, badTZ));
9710
9711 test("4 Jul 1976 05:04:22 -0000", SysTime(dst1, badTZ));
9712 test("4 Jul 1976 05:04 -0000", SysTime(dst2, badTZ));
9713 test("Sun, 4 Jul 1976 05:04 -0000", SysTime(dst2, badTZ));
9714 test("Sun, 4 Jul 1976 05:04:22 -0000", SysTime(dst1, badTZ));
9715
9716 auto pst = new immutable SimpleTimeZone(dur!"hours"(-8));
9717 auto pdt = new immutable SimpleTimeZone(dur!"hours"(-7));
9718 test("21 Dec 2012 13:14:15 -0800", SysTime(std1, pst));
9719 test("21 Dec 2012 13:14 -0800", SysTime(std2, pst));
9720 test("Fri, 21 Dec 2012 13:14 -0800", SysTime(std2, pst));
9721 test("Fri, 21 Dec 2012 13:14:15 -0800", SysTime(std1, pst));
9722
9723 test("04 Jul 1976 05:04:22 -0700", SysTime(dst1, pdt));
9724 test("04 Jul 1976 05:04 -0700", SysTime(dst2, pdt));
9725 test("Sun, 04 Jul 1976 05:04 -0700", SysTime(dst2, pdt));
9726 test("Sun, 04 Jul 1976 05:04:22 -0700", SysTime(dst1, pdt));
9727
9728 test("4 Jul 1976 05:04:22 -0700", SysTime(dst1, pdt));
9729 test("4 Jul 1976 05:04 -0700", SysTime(dst2, pdt));
9730 test("Sun, 4 Jul 1976 05:04 -0700", SysTime(dst2, pdt));
9731 test("Sun, 4 Jul 1976 05:04:22 -0700", SysTime(dst1, pdt));
9732
9733 auto cet = new immutable SimpleTimeZone(dur!"hours"(1));
9734 auto cest = new immutable SimpleTimeZone(dur!"hours"(2));
9735 test("21 Dec 2012 13:14:15 +0100", SysTime(std1, cet));
9736 test("21 Dec 2012 13:14 +0100", SysTime(std2, cet));
9737 test("Fri, 21 Dec 2012 13:14 +0100", SysTime(std2, cet));
9738 test("Fri, 21 Dec 2012 13:14:15 +0100", SysTime(std1, cet));
9739
9740 test("04 Jul 1976 05:04:22 +0200", SysTime(dst1, cest));
9741 test("04 Jul 1976 05:04 +0200", SysTime(dst2, cest));
9742 test("Sun, 04 Jul 1976 05:04 +0200", SysTime(dst2, cest));
9743 test("Sun, 04 Jul 1976 05:04:22 +0200", SysTime(dst1, cest));
9744
9745 test("4 Jul 1976 05:04:22 +0200", SysTime(dst1, cest));
9746 test("4 Jul 1976 05:04 +0200", SysTime(dst2, cest));
9747 test("Sun, 4 Jul 1976 05:04 +0200", SysTime(dst2, cest));
9748 test("Sun, 4 Jul 1976 05:04:22 +0200", SysTime(dst1, cest));
9749
9750 // dst and std times are switched in the Southern Hemisphere which is why the
9751 // time zone names and DateTime variables don't match.
9752 auto cstStd = new immutable SimpleTimeZone(dur!"hours"(9) + dur!"minutes"(30));
9753 auto cstDST = new immutable SimpleTimeZone(dur!"hours"(10) + dur!"minutes"(30));
9754 test("21 Dec 2012 13:14:15 +1030", SysTime(std1, cstDST));
9755 test("21 Dec 2012 13:14 +1030", SysTime(std2, cstDST));
9756 test("Fri, 21 Dec 2012 13:14 +1030", SysTime(std2, cstDST));
9757 test("Fri, 21 Dec 2012 13:14:15 +1030", SysTime(std1, cstDST));
9758
9759 test("04 Jul 1976 05:04:22 +0930", SysTime(dst1, cstStd));
9760 test("04 Jul 1976 05:04 +0930", SysTime(dst2, cstStd));
9761 test("Sun, 04 Jul 1976 05:04 +0930", SysTime(dst2, cstStd));
9762 test("Sun, 04 Jul 1976 05:04:22 +0930", SysTime(dst1, cstStd));
9763
9764 test("4 Jul 1976 05:04:22 +0930", SysTime(dst1, cstStd));
9765 test("4 Jul 1976 05:04 +0930", SysTime(dst2, cstStd));
9766 test("Sun, 4 Jul 1976 05:04 +0930", SysTime(dst2, cstStd));
9767 test("Sun, 4 Jul 1976 05:04:22 +0930", SysTime(dst1, cstStd));
9768
foreach(int i,mon;_monthNames)9769 foreach (int i, mon; _monthNames)
9770 {
9771 test(format("17 %s 2012 00:05:02 +0000", mon), SysTime(DateTime(2012, i + 1, 17, 0, 5, 2), UTC()));
9772 test(format("17 %s 2012 00:05 +0000", mon), SysTime(DateTime(2012, i + 1, 17, 0, 5, 0), UTC()));
9773 }
9774
9775 import std.uni : toLower, toUpper;
9776 foreach (mon; chain(_monthNames[].map!(a => toLower(a))(),
9777 _monthNames[].map!(a => toUpper(a))(),
9778 ["Jam", "Jen", "Fec", "Fdb", "Mas", "Mbr", "Aps", "Aqr", "Mai", "Miy",
9779 "Jum", "Jbn", "Jup", "Jal", "Aur", "Apg", "Sem", "Sap", "Ocm", "Odt",
9780 "Nom", "Nav", "Dem", "Dac"],
9781 Rand3Letters.start().filter!(a => !_monthNames[].canFind(a)).take(20)))
9782 {
9783 scope(failure) writefln("Month: %s", mon);
9784 testBad(format("17 %s 2012 00:05:02 +0000", mon));
9785 testBad(format("17 %s 2012 00:05 +0000", mon));
9786 }
9787
9788 immutable string[7] daysOfWeekNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
9789
9790 {
9791 auto start = SysTime(DateTime(2012, 11, 11, 9, 42, 0), UTC());
9792 int day = 11;
9793
foreach(int i,dow;daysOfWeekNames)9794 foreach (int i, dow; daysOfWeekNames)
9795 {
9796 auto curr = start + dur!"days"(i);
9797 test(format("%s, %s Nov 2012 09:42:00 +0000", dow, day), curr);
9798 test(format("%s, %s Nov 2012 09:42 +0000", dow, day++), curr);
9799
9800 // Whether the day of the week matches the date is ignored.
9801 test(format("%s, 11 Nov 2012 09:42:00 +0000", dow), start);
9802 test(format("%s, 11 Nov 2012 09:42 +0000", dow), start);
9803 }
9804 }
9805
9806 foreach (dow; chain(daysOfWeekNames[].map!(a => toLower(a))(),
9807 daysOfWeekNames[].map!(a => toUpper(a))(),
9808 ["Sum", "Spn", "Mom", "Man", "Tuf", "Tae", "Wem", "Wdd", "The", "Tur",
9809 "Fro", "Fai", "San", "Sut"],
9810 Rand3Letters.start().filter!(a => !daysOfWeekNames[].canFind(a)).take(20)))
9811 {
9812 scope(failure) writefln("Day of Week: %s", dow);
9813 testBad(format("%s, 11 Nov 2012 09:42:00 +0000", dow));
9814 testBad(format("%s, 11 Nov 2012 09:42 +0000", dow));
9815 }
9816
9817 testBad("31 Dec 1899 23:59:59 +0000");
9818 test("01 Jan 1900 00:00:00 +0000", SysTime(Date(1900, 1, 1), UTC()));
9819 test("01 Jan 1900 00:00:00 -0000", SysTime(Date(1900, 1, 1),
9820 new immutable SimpleTimeZone(Duration.zero)));
9821 test("01 Jan 1900 00:00:00 -0700", SysTime(Date(1900, 1, 1),
9822 new immutable SimpleTimeZone(dur!"hours"(-7))));
9823
9824 {
9825 auto st1 = SysTime(Date(1900, 1, 1), UTC());
9826 auto st2 = SysTime(Date(1900, 1, 1), new immutable SimpleTimeZone(dur!"hours"(-11)));
9827 foreach (i; 1900 .. 2102)
9828 {
9829 test(format("1 Jan %05d 00:00 +0000", i), st1);
9830 test(format("1 Jan %05d 00:00 -1100", i), st2);
9831 st1.add!"years"(1);
9832 st2.add!"years"(1);
9833 }
9834 st1.year = 9998;
9835 st2.year = 9998;
9836 foreach (i; 9998 .. 11_002)
9837 {
9838 test(format("1 Jan %05d 00:00 +0000", i), st1);
9839 test(format("1 Jan %05d 00:00 -1100", i), st2);
9840 st1.add!"years"(1);
9841 st2.add!"years"(1);
9842 }
9843 }
9844
9845 testBad("12 Feb 1907 23:17:09 0000");
9846 testBad("12 Feb 1907 23:17:09 +000");
9847 testBad("12 Feb 1907 23:17:09 -000");
9848 testBad("12 Feb 1907 23:17:09 +00000");
9849 testBad("12 Feb 1907 23:17:09 -00000");
9850 testBad("12 Feb 1907 23:17:09 +A");
9851 testBad("12 Feb 1907 23:17:09 +PST");
9852 testBad("12 Feb 1907 23:17:09 -A");
9853 testBad("12 Feb 1907 23:17:09 -PST");
9854
9855 // test trailing stuff that gets ignored
9856 {
9857 foreach (c; chain(iota(0, 33), ['('], iota(127, ubyte.max + 1)))
9858 {
9859 scope(failure) writefln("c: %d", c);
9860 test(format("21 Dec 2012 13:14:15 +0000%c", cast(char) c), SysTime(std1, UTC()));
9861 test(format("21 Dec 2012 13:14:15 +0000%c ", cast(char) c), SysTime(std1, UTC()));
9862 test(format("21 Dec 2012 13:14:15 +0000%chello", cast(char) c), SysTime(std1, UTC()));
9863 }
9864 }
9865
9866 // test trailing stuff that doesn't get ignored
9867 {
9868 foreach (c; chain(iota(33, '('), iota('(' + 1, 127)))
9869 {
9870 scope(failure) writefln("c: %d", c);
9871 testBad(format("21 Dec 2012 13:14:15 +0000%c", cast(char) c));
9872 testBad(format("21 Dec 2012 13:14:15 +0000%c ", cast(char) c));
9873 testBad(format("21 Dec 2012 13:14:15 +0000%chello", cast(char) c));
9874 }
9875 }
9876
9877 testBad("32 Jan 2012 12:13:14 -0800");
9878 testBad("31 Jan 2012 24:13:14 -0800");
9879 testBad("31 Jan 2012 12:60:14 -0800");
9880 testBad("31 Jan 2012 12:13:61 -0800");
9881 testBad("31 Jan 2012 12:13:14 -0860");
9882 test("31 Jan 2012 12:13:14 -0859",
9883 SysTime(DateTime(2012, 1, 31, 12, 13, 14),
9884 new immutable SimpleTimeZone(dur!"hours"(-8) + dur!"minutes"(-59))));
9885
9886 // leap-seconds
9887 test("21 Dec 2012 15:59:60 -0800", SysTime(DateTime(2012, 12, 21, 15, 59, 59), pst));
9888
9889 // FWS
9890 test("Sun,4 Jul 1976 05:04 +0930", SysTime(dst2, cstStd));
9891 test("Sun,4 Jul 1976 05:04:22 +0930", SysTime(dst1, cstStd));
9892 test("Sun,4 Jul 1976 05:04 +0930 (foo)", SysTime(dst2, cstStd));
9893 test("Sun,4 Jul 1976 05:04:22 +0930 (foo)", SysTime(dst1, cstStd));
9894 test("Sun,4 \r\n Jul \r\n 1976 \r\n 05:04 \r\n +0930 \r\n (foo)", SysTime(dst2, cstStd));
9895 test("Sun,4 \r\n Jul \r\n 1976 \r\n 05:04:22 \r\n +0930 \r\n (foo)", SysTime(dst1, cstStd));
9896
9897 auto str = "01 Jan 2012 12:13:14 -0800 ";
9898 test(str, SysTime(DateTime(2012, 1, 1, 12, 13, 14), new immutable SimpleTimeZone(hours(-8))));
9899 foreach (i; 0 .. str.length)
9900 {
9901 auto currStr = str.dup;
9902 currStr[i] = 'x';
9903 scope(failure) writefln("failed: %s", currStr);
9904 testBad(cast(string) currStr);
9905 }
9906 foreach (i; 2 .. str.length)
9907 {
9908 auto currStr = str[0 .. $ - i];
9909 scope(failure) writefln("failed: %s", currStr);
9910 testBad(cast(string) currStr);
9911 testBad((cast(string) currStr) ~ " ");
9912 }
9913 }();
9914 }
9915
9916 // Obsolete Format per section 4.3 of RFC 5322.
9917 @system unittest
9918 {
9919 import std.algorithm.iteration : filter, map;
9920 import std.ascii : letters;
9921 import std.exception : collectExceptionMsg;
9922 import std.format : format;
9923 import std.meta : AliasSeq;
9924 import std.range : chain, iota;
9925 import std.stdio : writefln, writeln;
9926 import std.string : representation;
9927
9928 auto std1 = SysTime(DateTime(2012, 12, 21, 13, 14, 15), UTC());
9929 auto std2 = SysTime(DateTime(2012, 12, 21, 13, 14, 0), UTC());
9930 auto std3 = SysTime(DateTime(1912, 12, 21, 13, 14, 15), UTC());
9931 auto std4 = SysTime(DateTime(1912, 12, 21, 13, 14, 0), UTC());
9932 auto dst1 = SysTime(DateTime(1976, 7, 4, 5, 4, 22), UTC());
9933 auto dst2 = SysTime(DateTime(1976, 7, 4, 5, 4, 0), UTC());
9934 auto tooLate1 = SysTime(Date(10_000, 1, 1), UTC());
9935 auto tooLate2 = SysTime(DateTime(12_007, 12, 31, 12, 22, 19), UTC());
9936
9937 foreach (cr; AliasSeq!(function(string a){return cast(char[]) a;},
9938 function(string a){return cast(ubyte[]) a;},
9939 function(string a){return a;},
9940 function(string a){return map!(b => cast(char) b)(a.representation);}))
9941 (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396
9942 scope(failure) writeln(typeof(cr).stringof);
9943 alias test = testParse822!cr;
9944 {
9945 auto list = ["", " ", " \r\n\t", "\t\r\n (hello world( frien(dog)) silly \r\n ) \t\t \r\n ()",
9946 " \n ", "\t\n\t", " \n\t (foo) \n (bar) \r\n (baz) \n "];
9947
foreach(i,cfws;list)9948 foreach (i, cfws; list)
9949 {
9950 scope(failure) writefln("i: %s", i);
9951
9952 test(format("%1$s21%1$sDec%1$s2012%1$s13:14:15%1$s+0000%1$s", cfws), std1);
9953 test(format("%1$s21%1$sDec%1$s2012%1$s13:14%1$s+0000%1$s", cfws), std2);
9954 test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s2012%1$s13:14%1$s+0000%1$s", cfws), std2);
9955 test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s2012%1$s13:14:15%1$s+0000%1$s", cfws), std1);
9956
9957 test(format("%1$s04%1$sJul%1$s1976%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
9958 test(format("%1$s04%1$sJul%1$s1976%1$s05:04%1$s+0000%1$s", cfws), dst2);
9959 test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s1976%1$s05:04%1$s+0000%1$s", cfws), dst2);
9960 test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s1976%1$s05:04:22 +0000%1$s", cfws), dst1);
9961
9962 test(format("%1$s4%1$sJul%1$s1976%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
9963 test(format("%1$s4%1$sJul%1$s1976%1$s05:04%1$s+0000%1$s", cfws), dst2);
9964 test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s1976%1$s05:04%1$s+0000%1$s", cfws), dst2);
9965 test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s1976%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
9966
9967 test(format("%1$s21%1$sDec%1$s12%1$s13:14:15%1$s+0000%1$s", cfws), std1);
9968 test(format("%1$s21%1$sDec%1$s12%1$s13:14%1$s+0000%1$s", cfws), std2);
9969 test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s12%1$s13:14%1$s+0000%1$s", cfws), std2);
9970 test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s12%1$s13:14:15%1$s+0000%1$s", cfws), std1);
9971
9972 test(format("%1$s04%1$sJul%1$s76%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
9973 test(format("%1$s04%1$sJul%1$s76%1$s05:04%1$s+0000%1$s", cfws), dst2);
9974 test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s76%1$s05:04%1$s+0000%1$s", cfws), dst2);
9975 test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s76%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
9976
9977 test(format("%1$s4%1$sJul%1$s76 05:04:22%1$s+0000%1$s", cfws), dst1);
9978 test(format("%1$s4%1$sJul%1$s76 05:04%1$s+0000%1$s", cfws), dst2);
9979 test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s76%1$s05:04%1$s+0000%1$s", cfws), dst2);
9980 test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s76%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
9981
9982 test(format("%1$s21%1$sDec%1$s012%1$s13:14:15%1$s+0000%1$s", cfws), std3);
9983 test(format("%1$s21%1$sDec%1$s012%1$s13:14%1$s+0000%1$s", cfws), std4);
9984 test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s012%1$s13:14%1$s+0000%1$s", cfws), std4);
9985 test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s012%1$s13:14:15%1$s+0000%1$s", cfws), std3);
9986
9987 test(format("%1$s04%1$sJul%1$s076%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
9988 test(format("%1$s04%1$sJul%1$s076%1$s05:04%1$s+0000%1$s", cfws), dst2);
9989 test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s076%1$s05:04%1$s+0000%1$s", cfws), dst2);
9990 test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s076%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
9991
9992 test(format("%1$s4%1$sJul%1$s076%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
9993 test(format("%1$s4%1$sJul%1$s076%1$s05:04%1$s+0000%1$s", cfws), dst2);
9994 test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s076%1$s05:04%1$s+0000%1$s", cfws), dst2);
9995 test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s076%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
9996
9997 test(format("%1$s1%1$sJan%1$s10000%1$s00:00:00%1$s+0000%1$s", cfws), tooLate1);
9998 test(format("%1$s31%1$sDec%1$s12007%1$s12:22:19%1$s+0000%1$s", cfws), tooLate2);
9999 test(format("%1$sSat%1$s,%1$s1%1$sJan%1$s10000%1$s00:00:00%1$s+0000%1$s", cfws), tooLate1);
10000 test(format("%1$sSun%1$s,%1$s31%1$sDec%1$s12007%1$s12:22:19%1$s+0000%1$s", cfws), tooLate2);
10001 }
10002 }
10003
10004 // test years of 1, 2, and 3 digits.
10005 {
10006 auto st1 = SysTime(Date(2000, 1, 1), UTC());
10007 auto st2 = SysTime(Date(2000, 1, 1), new immutable SimpleTimeZone(dur!"hours"(-12)));
10008 foreach (i; 0 .. 50)
10009 {
10010 test(format("1 Jan %02d 00:00 GMT", i), st1);
10011 test(format("1 Jan %02d 00:00 -1200", i), st2);
10012 st1.add!"years"(1);
10013 st2.add!"years"(1);
10014 }
10015 }
10016
10017 {
10018 auto st1 = SysTime(Date(1950, 1, 1), UTC());
10019 auto st2 = SysTime(Date(1950, 1, 1), new immutable SimpleTimeZone(dur!"hours"(-12)));
10020 foreach (i; 50 .. 100)
10021 {
10022 test(format("1 Jan %02d 00:00 GMT", i), st1);
10023 test(format("1 Jan %02d 00:00 -1200", i), st2);
10024 st1.add!"years"(1);
10025 st2.add!"years"(1);
10026 }
10027 }
10028
10029 {
10030 auto st1 = SysTime(Date(1900, 1, 1), UTC());
10031 auto st2 = SysTime(Date(1900, 1, 1), new immutable SimpleTimeZone(dur!"hours"(-11)));
10032 foreach (i; 0 .. 1000)
10033 {
10034 test(format("1 Jan %03d 00:00 GMT", i), st1);
10035 test(format("1 Jan %03d 00:00 -1100", i), st2);
10036 st1.add!"years"(1);
10037 st2.add!"years"(1);
10038 }
10039 }
10040
10041 foreach (i; 0 .. 10)
10042 {
10043 auto str1 = cr(format("1 Jan %d 00:00 GMT", i));
10044 auto str2 = cr(format("1 Jan %d 00:00 -1200", i));
10045 assertThrown!DateTimeException(parseRFC822DateTime(str1));
10046 assertThrown!DateTimeException(parseRFC822DateTime(str1));
10047 }
10048
10049 // test time zones
10050 {
10051 auto dt = DateTime(1982, 05, 03, 12, 22, 04);
10052 test("Wed, 03 May 1982 12:22:04 UT", SysTime(dt, UTC()));
10053 test("Wed, 03 May 1982 12:22:04 GMT", SysTime(dt, UTC()));
10054 test("Wed, 03 May 1982 12:22:04 EST", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-5))));
10055 test("Wed, 03 May 1982 12:22:04 EDT", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-4))));
10056 test("Wed, 03 May 1982 12:22:04 CST", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-6))));
10057 test("Wed, 03 May 1982 12:22:04 CDT", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-5))));
10058 test("Wed, 03 May 1982 12:22:04 MST", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-7))));
10059 test("Wed, 03 May 1982 12:22:04 MDT", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-6))));
10060 test("Wed, 03 May 1982 12:22:04 PST", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-8))));
10061 test("Wed, 03 May 1982 12:22:04 PDT", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-7))));
10062
10063 auto badTZ = new immutable SimpleTimeZone(Duration.zero);
10064 foreach (dchar c; filter!(a => a != 'j' && a != 'J')(letters))
10065 {
10066 scope(failure) writefln("c: %s", c);
10067 test(format("Wed, 03 May 1982 12:22:04 %s", c), SysTime(dt, badTZ));
10068 test(format("Wed, 03 May 1982 12:22:04%s", c), SysTime(dt, badTZ));
10069 }
10070
foreach(dchar c;['j','J'])10071 foreach (dchar c; ['j', 'J'])
10072 {
10073 scope(failure) writefln("c: %s", c);
10074 assertThrown!DateTimeException(parseRFC822DateTime(cr(format("Wed, 03 May 1982 12:22:04 %s", c))));
10075 assertThrown!DateTimeException(parseRFC822DateTime(cr(format("Wed, 03 May 1982 12:22:04%s", c))));
10076 }
10077
foreach(string s;["AAA","GQW","DDT","PDA","GT","GM"])10078 foreach (string s; ["AAA", "GQW", "DDT", "PDA", "GT", "GM"])
10079 {
10080 scope(failure) writefln("s: %s", s);
10081 test(format("Wed, 03 May 1982 12:22:04 %s", s), SysTime(dt, badTZ));
10082 }
10083
10084 // test trailing stuff that gets ignored
10085 {
10086 foreach (c; chain(iota(0, 33), ['('], iota(127, ubyte.max + 1)))
10087 {
10088 scope(failure) writefln("c: %d", c);
10089 test(format("21Dec1213:14:15+0000%c", cast(char) c), std1);
10090 test(format("21Dec1213:14:15+0000%c ", cast(char) c), std1);
10091 test(format("21Dec1213:14:15+0000%chello", cast(char) c), std1);
10092 }
10093 }
10094
10095 // test trailing stuff that doesn't get ignored
10096 {
10097 foreach (c; chain(iota(33, '('), iota('(' + 1, 127)))
10098 {
10099 scope(failure) writefln("c: %d", c);
10100 assertThrown!DateTimeException(
10101 parseRFC822DateTime(cr(format("21Dec1213:14:15+0000%c", cast(char) c))));
10102 assertThrown!DateTimeException(
10103 parseRFC822DateTime(cr(format("21Dec1213:14:15+0000%c ", cast(char) c))));
10104 assertThrown!DateTimeException(
10105 parseRFC822DateTime(cr(format("21Dec1213:14:15+0000%chello", cast(char) c))));
10106 }
10107 }
10108 }
10109
10110 // test that the checks for minimum length work correctly and avoid
10111 // any RangeErrors.
10112 test("7Dec1200:00A", SysTime(DateTime(2012, 12, 7, 00, 00, 00),
10113 new immutable SimpleTimeZone(Duration.zero)));
10114 test("Fri,7Dec1200:00A", SysTime(DateTime(2012, 12, 7, 00, 00, 00),
10115 new immutable SimpleTimeZone(Duration.zero)));
10116 test("7Dec1200:00:00A", SysTime(DateTime(2012, 12, 7, 00, 00, 00),
10117 new immutable SimpleTimeZone(Duration.zero)));
10118 test("Fri,7Dec1200:00:00A", SysTime(DateTime(2012, 12, 7, 00, 00, 00),
10119 new immutable SimpleTimeZone(Duration.zero)));
10120
10121 auto tooShortMsg = collectExceptionMsg!DateTimeException(parseRFC822DateTime(""));
foreach(str;["Fri,7Dec1200:00:00","7Dec1200:00:00"])10122 foreach (str; ["Fri,7Dec1200:00:00", "7Dec1200:00:00"])
10123 {
10124 foreach (i; 0 .. str.length)
10125 {
10126 auto value = str[0 .. $ - i];
10127 scope(failure) writeln(value);
10128 assert(collectExceptionMsg!DateTimeException(parseRFC822DateTime(value)) == tooShortMsg);
10129 }
10130 }
10131 }();
10132 }
10133
10134
10135 private:
10136
10137 /+
10138 Returns the given hnsecs as an ISO string of fractional seconds.
10139 +/
fracSecsToISOString(int hnsecs)10140 static string fracSecsToISOString(int hnsecs) @safe pure nothrow
10141 {
10142 assert(hnsecs >= 0);
10143
10144 try
10145 {
10146 if (hnsecs == 0)
10147 return "";
10148
10149 string isoString = format(".%07d", hnsecs);
10150
10151 while (isoString[$ - 1] == '0')
10152 isoString.popBack();
10153
10154 return isoString;
10155 }
10156 catch (Exception e)
10157 assert(0, "format() threw.");
10158 }
10159
10160 @safe unittest
10161 {
10162 assert(fracSecsToISOString(0) == "");
10163 assert(fracSecsToISOString(1) == ".0000001");
10164 assert(fracSecsToISOString(10) == ".000001");
10165 assert(fracSecsToISOString(100) == ".00001");
10166 assert(fracSecsToISOString(1000) == ".0001");
10167 assert(fracSecsToISOString(10_000) == ".001");
10168 assert(fracSecsToISOString(100_000) == ".01");
10169 assert(fracSecsToISOString(1_000_000) == ".1");
10170 assert(fracSecsToISOString(1_000_001) == ".1000001");
10171 assert(fracSecsToISOString(1_001_001) == ".1001001");
10172 assert(fracSecsToISOString(1_071_601) == ".1071601");
10173 assert(fracSecsToISOString(1_271_641) == ".1271641");
10174 assert(fracSecsToISOString(9_999_999) == ".9999999");
10175 assert(fracSecsToISOString(9_999_990) == ".999999");
10176 assert(fracSecsToISOString(9_999_900) == ".99999");
10177 assert(fracSecsToISOString(9_999_000) == ".9999");
10178 assert(fracSecsToISOString(9_990_000) == ".999");
10179 assert(fracSecsToISOString(9_900_000) == ".99");
10180 assert(fracSecsToISOString(9_000_000) == ".9");
10181 assert(fracSecsToISOString(999) == ".0000999");
10182 assert(fracSecsToISOString(9990) == ".000999");
10183 assert(fracSecsToISOString(99_900) == ".00999");
10184 assert(fracSecsToISOString(999_000) == ".0999");
10185 }
10186
10187
10188 /+
10189 Returns a Duration corresponding to to the given ISO string of
10190 fractional seconds.
10191 +/
10192 static Duration fracSecsFromISOString(S)(in S isoString) @trusted pure
10193 if (isSomeString!S)
10194 {
10195 import std.algorithm.searching : all;
10196 import std.ascii : isDigit;
10197 import std.conv : to;
10198 import std.string : representation;
10199
10200 if (isoString.empty)
10201 return Duration.zero;
10202
10203 auto str = isoString.representation;
10204
10205 enforce(str[0] == '.', new DateTimeException("Invalid ISO String"));
10206 str.popFront();
10207
10208 enforce(!str.empty && all!isDigit(str), new DateTimeException("Invalid ISO String"));
10209
10210 dchar[7] fullISOString = void;
foreach(i,ref dchar c;fullISOString)10211 foreach (i, ref dchar c; fullISOString)
10212 {
10213 if (i < str.length)
10214 c = str[i];
10215 else
10216 c = '0';
10217 }
10218
10219 return hnsecs(to!int(fullISOString[]));
10220 }
10221
10222 @safe unittest
10223 {
testFSInvalid(string isoString)10224 static void testFSInvalid(string isoString)
10225 {
10226 fracSecsFromISOString(isoString);
10227 }
10228
10229 assertThrown!DateTimeException(testFSInvalid("."));
10230 assertThrown!DateTimeException(testFSInvalid("0."));
10231 assertThrown!DateTimeException(testFSInvalid("0"));
10232 assertThrown!DateTimeException(testFSInvalid("0000000"));
10233 assertThrown!DateTimeException(testFSInvalid("T"));
10234 assertThrown!DateTimeException(testFSInvalid("T."));
10235 assertThrown!DateTimeException(testFSInvalid(".T"));
10236 assertThrown!DateTimeException(testFSInvalid(".00000Q0"));
10237 assertThrown!DateTimeException(testFSInvalid(".000000Q"));
10238 assertThrown!DateTimeException(testFSInvalid(".0000000Q"));
10239 assertThrown!DateTimeException(testFSInvalid(".0000000000Q"));
10240
10241 assert(fracSecsFromISOString("") == Duration.zero);
10242 assert(fracSecsFromISOString(".0000001") == hnsecs(1));
10243 assert(fracSecsFromISOString(".000001") == hnsecs(10));
10244 assert(fracSecsFromISOString(".00001") == hnsecs(100));
10245 assert(fracSecsFromISOString(".0001") == hnsecs(1000));
10246 assert(fracSecsFromISOString(".001") == hnsecs(10_000));
10247 assert(fracSecsFromISOString(".01") == hnsecs(100_000));
10248 assert(fracSecsFromISOString(".1") == hnsecs(1_000_000));
10249 assert(fracSecsFromISOString(".1000001") == hnsecs(1_000_001));
10250 assert(fracSecsFromISOString(".1001001") == hnsecs(1_001_001));
10251 assert(fracSecsFromISOString(".1071601") == hnsecs(1_071_601));
10252 assert(fracSecsFromISOString(".1271641") == hnsecs(1_271_641));
10253 assert(fracSecsFromISOString(".9999999") == hnsecs(9_999_999));
10254 assert(fracSecsFromISOString(".9999990") == hnsecs(9_999_990));
10255 assert(fracSecsFromISOString(".999999") == hnsecs(9_999_990));
10256 assert(fracSecsFromISOString(".9999900") == hnsecs(9_999_900));
10257 assert(fracSecsFromISOString(".99999") == hnsecs(9_999_900));
10258 assert(fracSecsFromISOString(".9999000") == hnsecs(9_999_000));
10259 assert(fracSecsFromISOString(".9999") == hnsecs(9_999_000));
10260 assert(fracSecsFromISOString(".9990000") == hnsecs(9_990_000));
10261 assert(fracSecsFromISOString(".999") == hnsecs(9_990_000));
10262 assert(fracSecsFromISOString(".9900000") == hnsecs(9_900_000));
10263 assert(fracSecsFromISOString(".9900") == hnsecs(9_900_000));
10264 assert(fracSecsFromISOString(".99") == hnsecs(9_900_000));
10265 assert(fracSecsFromISOString(".9000000") == hnsecs(9_000_000));
10266 assert(fracSecsFromISOString(".9") == hnsecs(9_000_000));
10267 assert(fracSecsFromISOString(".0000999") == hnsecs(999));
10268 assert(fracSecsFromISOString(".0009990") == hnsecs(9990));
10269 assert(fracSecsFromISOString(".000999") == hnsecs(9990));
10270 assert(fracSecsFromISOString(".0099900") == hnsecs(99_900));
10271 assert(fracSecsFromISOString(".00999") == hnsecs(99_900));
10272 assert(fracSecsFromISOString(".0999000") == hnsecs(999_000));
10273 assert(fracSecsFromISOString(".0999") == hnsecs(999_000));
10274 assert(fracSecsFromISOString(".00000000") == Duration.zero);
10275 assert(fracSecsFromISOString(".00000001") == Duration.zero);
10276 assert(fracSecsFromISOString(".00000009") == Duration.zero);
10277 assert(fracSecsFromISOString(".1234567890") == hnsecs(1_234_567));
10278 assert(fracSecsFromISOString(".12345678901234567890") == hnsecs(1_234_567));
10279 }
10280
10281
10282 /+
10283 This function is used to split out the units without getting the remaining
10284 hnsecs.
10285
10286 Params:
10287 units = The units to split out.
10288 hnsecs = The current total hnsecs.
10289
10290 Returns:
10291 The split out value.
10292 +/
10293 long getUnitsFromHNSecs(string units)(long hnsecs) @safe pure nothrow
10294 if (validTimeUnits(units) &&
10295 CmpTimeUnits!(units, "months") < 0)
10296 {
10297 return convert!("hnsecs", units)(hnsecs);
10298 }
10299
10300 @safe unittest
10301 {
10302 auto hnsecs = 2595000000007L;
10303 immutable days = getUnitsFromHNSecs!"days"(hnsecs);
10304 assert(days == 3);
10305 assert(hnsecs == 2595000000007L);
10306 }
10307
10308
10309 /+
10310 This function is used to split out the units without getting the units but
10311 just the remaining hnsecs.
10312
10313 Params:
10314 units = The units to split out.
10315 hnsecs = The current total hnsecs.
10316
10317 Returns:
10318 The remaining hnsecs.
10319 +/
10320 long removeUnitsFromHNSecs(string units)(long hnsecs) @safe pure nothrow
10321 if (validTimeUnits(units) &&
10322 CmpTimeUnits!(units, "months") < 0)
10323 {
10324 immutable value = convert!("hnsecs", units)(hnsecs);
10325 return hnsecs - convert!(units, "hnsecs")(value);
10326 }
10327
10328 @safe unittest
10329 {
10330 auto hnsecs = 2595000000007L;
10331 auto returned = removeUnitsFromHNSecs!"days"(hnsecs);
10332 assert(returned == 3000000007);
10333 assert(hnsecs == 2595000000007L);
10334 }
10335
10336
10337 /+
10338 Strips what RFC 5322, section 3.2.2 refers to as CFWS from the left-hand
10339 side of the given range (it strips comments delimited by $(D '(') and
10340 $(D ')') as well as folding whitespace).
10341
10342 It is assumed that the given range contains the value of a header field and
10343 no terminating CRLF for the line (though the CRLF for folding whitespace is
10344 of course expected and stripped) and thus that the only case of CR or LF is
10345 in folding whitespace.
10346
10347 If a comment does not terminate correctly (e.g. mismatched parens) or if the
10348 the FWS is malformed, then the range will be empty when stripCWFS is done.
10349 However, only minimal validation of the content is done (e.g. quoted pairs
10350 within a comment aren't validated beyond \$LPAREN or \$RPAREN, because
10351 they're inside a comment, and thus their value doesn't matter anyway). It's
10352 only when the content does not conform to the grammar rules for FWS and thus
10353 literally cannot be parsed that content is considered invalid, and an empty
10354 range is returned.
10355
10356 Note that _stripCFWS is eager, not lazy. It does not create a new range.
10357 Rather, it pops off the CFWS from the range and returns it.
10358 +/
10359 R _stripCFWS(R)(R range)
10360 if (isRandomAccessRange!R && hasSlicing!R && hasLength!R &&
10361 (is(Unqual!(ElementType!R) == char) || is(Unqual!(ElementType!R) == ubyte)))
10362 {
10363 immutable e = range.length;
10364 outer: for (size_t i = 0; i < e; )
10365 {
10366 switch (range[i])
10367 {
10368 case ' ': case '\t':
10369 {
10370 ++i;
10371 break;
10372 }
10373 case '\r':
10374 {
10375 if (i + 2 < e && range[i + 1] == '\n' && (range[i + 2] == ' ' || range[i + 2] == '\t'))
10376 {
10377 i += 3;
10378 break;
10379 }
10380 break outer;
10381 }
10382 case '\n':
10383 {
10384 if (i + 1 < e && (range[i + 1] == ' ' || range[i + 1] == '\t'))
10385 {
10386 i += 2;
10387 break;
10388 }
10389 break outer;
10390 }
10391 case '(':
10392 {
10393 ++i;
10394 size_t commentLevel = 1;
10395 while (i < e)
10396 {
10397 if (range[i] == '(')
10398 ++commentLevel;
10399 else if (range[i] == ')')
10400 {
10401 ++i;
10402 if (--commentLevel == 0)
10403 continue outer;
10404 continue;
10405 }
10406 else if (range[i] == '\\')
10407 {
10408 if (++i == e)
10409 break outer;
10410 }
10411 ++i;
10412 }
10413 break outer;
10414 }
10415 default: return range[i .. e];
10416 }
10417 }
10418 return range[e .. e];
10419 }
10420
10421 @system unittest
10422 {
10423 import std.algorithm.comparison : equal;
10424 import std.algorithm.iteration : map;
10425 import std.meta : AliasSeq;
10426 import std.stdio : writeln;
10427 import std.string : representation;
10428
10429 foreach (cr; AliasSeq!(function(string a){return cast(ubyte[]) a;},
10430 function(string a){return map!(b => cast(char) b)(a.representation);}))
10431 (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396
10432 scope(failure) writeln(typeof(cr).stringof);
10433
10434 assert(_stripCFWS(cr("")).empty);
10435 assert(_stripCFWS(cr("\r")).empty);
10436 assert(_stripCFWS(cr("\r\n")).empty);
10437 assert(_stripCFWS(cr("\r\n ")).empty);
10438 assert(_stripCFWS(cr(" \t\r\n")).empty);
10439 assert(equal(_stripCFWS(cr(" \t\r\n hello")), cr("hello")));
10440 assert(_stripCFWS(cr(" \t\r\nhello")).empty);
10441 assert(_stripCFWS(cr(" \t\r\n\v")).empty);
10442 assert(equal(_stripCFWS(cr("\v \t\r\n\v")), cr("\v \t\r\n\v")));
10443 assert(_stripCFWS(cr("()")).empty);
10444 assert(_stripCFWS(cr("(hello world)")).empty);
10445 assert(_stripCFWS(cr("(hello world)(hello world)")).empty);
10446 assert(_stripCFWS(cr("(hello world\r\n foo\r where's\nwaldo)")).empty);
10447 assert(_stripCFWS(cr(" \t (hello \tworld\r\n foo\r where's\nwaldo)\t\t ")).empty);
10448 assert(_stripCFWS(cr(" ")).empty);
10449 assert(_stripCFWS(cr("\t\t\t")).empty);
10450 assert(_stripCFWS(cr("\t \r\n\r \n")).empty);
10451 assert(_stripCFWS(cr("(hello world) (can't find waldo) (he's lost)")).empty);
10452 assert(_stripCFWS(cr("(hello\\) world) (can't \\(find waldo) (he's \\(\\)lost)")).empty);
10453 assert(_stripCFWS(cr("(((((")).empty);
10454 assert(_stripCFWS(cr("(((()))")).empty);
10455 assert(_stripCFWS(cr("(((())))")).empty);
10456 assert(equal(_stripCFWS(cr("(((()))))")), cr(")")));
10457 assert(equal(_stripCFWS(cr(")))))")), cr(")))))")));
10458 assert(equal(_stripCFWS(cr("()))))")), cr("))))")));
10459 assert(equal(_stripCFWS(cr(" hello hello ")), cr("hello hello ")));
10460 assert(equal(_stripCFWS(cr("\thello (world)")), cr("hello (world)")));
10461 assert(equal(_stripCFWS(cr(" \r\n \\((\\)) foo")), cr("\\((\\)) foo")));
10462 assert(equal(_stripCFWS(cr(" \r\n (\\((\\))) foo")), cr("foo")));
10463 assert(equal(_stripCFWS(cr(" \r\n (\\(())) foo")), cr(") foo")));
10464 assert(_stripCFWS(cr(" \r\n (((\\))) foo")).empty);
10465
10466 assert(_stripCFWS(cr("(hello)(hello)")).empty);
10467 assert(_stripCFWS(cr(" \r\n (hello)\r\n (hello)")).empty);
10468 assert(_stripCFWS(cr(" \r\n (hello) \r\n (hello) \r\n ")).empty);
10469 assert(_stripCFWS(cr("\t\t\t\t(hello)\t\t\t\t(hello)\t\t\t\t")).empty);
10470 assert(equal(_stripCFWS(cr(" \r\n (hello)\r\n (hello) \r\n hello")), cr("hello")));
10471 assert(equal(_stripCFWS(cr(" \r\n (hello) \r\n (hello) \r\n hello")), cr("hello")));
10472 assert(equal(_stripCFWS(cr("\t\r\n\t(hello)\r\n\t(hello)\t\r\n hello")), cr("hello")));
10473 assert(equal(_stripCFWS(cr("\t\r\n\t(hello)\t\r\n\t(hello)\t\r\n hello")), cr("hello")));
10474 assert(equal(_stripCFWS(cr(" \r\n (hello) \r\n \r\n (hello) \r\n hello")), cr("hello")));
10475 assert(equal(_stripCFWS(cr(" \r\n (hello) \r\n (hello) \r\n \r\n hello")), cr("hello")));
10476 assert(equal(_stripCFWS(cr(" \r\n \r\n (hello)\t\r\n (hello) \r\n hello")), cr("hello")));
10477 assert(equal(_stripCFWS(cr(" \r\n\t\r\n\t(hello)\t\r\n (hello) \r\n hello")), cr("hello")));
10478
10479 assert(equal(_stripCFWS(cr(" (\r\n ( \r\n ) \r\n ) foo")), cr("foo")));
10480 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n ) foo")), cr("foo")));
10481 assert(equal(_stripCFWS(cr(" (\t\r\n ( \r\n ) \r\n ) foo")), cr("foo")));
10482 assert(equal(_stripCFWS(cr(" (\r\n\t( \r\n ) \r\n ) foo")), cr("foo")));
10483 assert(equal(_stripCFWS(cr(" ( \r\n (\t\r\n ) \r\n ) foo")), cr("foo")));
10484 assert(equal(_stripCFWS(cr(" ( \r\n (\r\n ) \r\n ) foo")), cr("foo")));
10485 assert(equal(_stripCFWS(cr(" ( \r\n (\r\n\t) \r\n ) foo")), cr("foo")));
10486 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n) \r\n ) foo")), cr("foo")));
10487 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n )\t\r\n ) foo")), cr("foo")));
10488 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n )\r\n ) foo")), cr("foo")));
10489 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n) foo")), cr("foo")));
10490 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n\t) foo")), cr("foo")));
10491 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n ) \r\n foo")), cr("foo")));
10492 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n )\t\r\n foo")), cr("foo")));
10493 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n )\r\n foo")), cr("foo")));
10494
10495 assert(equal(_stripCFWS(cr(" ( \r\n \r\n ( \r\n \r\n ) \r\n ) foo")), cr("foo")));
10496 assert(equal(_stripCFWS(cr(" ( \r\n \r\n ( \r\n \r\n ) \r\n ) foo")), cr("foo")));
10497 assert(equal(_stripCFWS(cr(" (\t\r\n \r\n ( \r\n \r\n ) \r\n ) foo")), cr("foo")));
10498 assert(equal(_stripCFWS(cr(" (\r\n \r\n\t( \r\n \r\n ) \r\n ) foo")), cr("foo")));
10499 assert(equal(_stripCFWS(cr(" (\r\n \r\n( \r\n \r\n ) \r\n ) foo")), cr("foo")));
10500 assert(equal(_stripCFWS(cr(" (\r\n \r\n ( \r\n \r\n\t) \r\n ) foo")), cr("foo")));
10501 assert(equal(_stripCFWS(cr(" (\r\n \r\n ( \r\n \r\n )\t\r\n ) foo")), cr("foo")));
10502 assert(equal(_stripCFWS(cr(" (\r\n \r\n ( \r\n \r\n )\r\n ) foo")), cr("foo")));
10503
10504 assert(equal(_stripCFWS(cr(" ( \r\n bar \r\n ( \r\n bar \r\n ) \r\n ) foo")), cr("foo")));
10505 assert(equal(_stripCFWS(cr(" ( \r\n () \r\n ( \r\n () \r\n ) \r\n ) foo")), cr("foo")));
10506 assert(equal(_stripCFWS(cr(" ( \r\n \\\\ \r\n ( \r\n \\\\ \r\n ) \r\n ) foo")), cr("foo")));
10507
10508 assert(_stripCFWS(cr("(hello)(hello)")).empty);
10509 assert(_stripCFWS(cr(" \n (hello)\n (hello) \n ")).empty);
10510 assert(_stripCFWS(cr(" \n (hello) \n (hello) \n ")).empty);
10511 assert(equal(_stripCFWS(cr(" \n (hello)\n (hello) \n hello")), cr("hello")));
10512 assert(equal(_stripCFWS(cr(" \n (hello) \n (hello) \n hello")), cr("hello")));
10513 assert(equal(_stripCFWS(cr("\t\n\t(hello)\n\t(hello)\t\n hello")), cr("hello")));
10514 assert(equal(_stripCFWS(cr("\t\n\t(hello)\t\n\t(hello)\t\n hello")), cr("hello")));
10515 assert(equal(_stripCFWS(cr(" \n (hello) \n \n (hello) \n hello")), cr("hello")));
10516 assert(equal(_stripCFWS(cr(" \n (hello) \n (hello) \n \n hello")), cr("hello")));
10517 assert(equal(_stripCFWS(cr(" \n \n (hello)\t\n (hello) \n hello")), cr("hello")));
10518 assert(equal(_stripCFWS(cr(" \n\t\n\t(hello)\t\n (hello) \n hello")), cr("hello")));
10519 }();
10520 }
10521
10522 // This is so that we don't have to worry about std.conv.to throwing. It also
10523 // doesn't have to worry about quite as many cases as std.conv.to, since it
10524 // doesn't have to worry about a sign on the value or about whether it fits.
10525 T _convDigits(T, R)(R str)
10526 if (isIntegral!T && isSigned!T) // The constraints on R were already covered by parseRFC822DateTime.
10527 {
10528 import std.ascii : isDigit;
10529
10530 assert(!str.empty);
10531 T num = 0;
10532 foreach (i; 0 .. str.length)
10533 {
10534 if (i != 0)
10535 num *= 10;
10536 if (!isDigit(str[i]))
10537 return -1;
10538 num += str[i] - '0';
10539 }
10540 return num;
10541 }
10542
10543 @safe unittest
10544 {
10545 import std.conv : to;
10546 import std.range : chain, iota;
10547 import std.stdio : writeln;
10548 foreach (i; chain(iota(0, 101), [250, 999, 1000, 1001, 2345, 9999]))
10549 {
10550 scope(failure) writeln(i);
10551 assert(_convDigits!int(to!string(i)) == i);
10552 }
foreach(str;["-42","+42","1a","1 "," "," 42 "])10553 foreach (str; ["-42", "+42", "1a", "1 ", " ", " 42 "])
10554 {
10555 scope(failure) writeln(str);
10556 assert(_convDigits!int(str) == -1);
10557 }
10558 }
10559
10560
version(unittest)10561 version (unittest)
10562 {
10563 // Variables to help in testing.
10564 Duration currLocalDiffFromUTC;
10565 immutable (TimeZone)[] testTZs;
10566
10567 // All of these helper arrays are sorted in ascending order.
10568 auto testYearsBC = [-1999, -1200, -600, -4, -1, 0];
10569 auto testYearsAD = [1, 4, 1000, 1999, 2000, 2012];
10570
10571 // I'd use a Tuple, but I get forward reference errors if I try.
10572 struct MonthDay
10573 {
10574 Month month;
10575 short day;
10576
10577 this(int m, short d)
10578 {
10579 month = cast(Month) m;
10580 day = d;
10581 }
10582 }
10583
10584 MonthDay[] testMonthDays = [MonthDay(1, 1),
10585 MonthDay(1, 2),
10586 MonthDay(3, 17),
10587 MonthDay(7, 4),
10588 MonthDay(10, 27),
10589 MonthDay(12, 30),
10590 MonthDay(12, 31)];
10591
10592 auto testDays = [1, 2, 9, 10, 16, 20, 25, 28, 29, 30, 31];
10593
10594 auto testTODs = [TimeOfDay(0, 0, 0),
10595 TimeOfDay(0, 0, 1),
10596 TimeOfDay(0, 1, 0),
10597 TimeOfDay(1, 0, 0),
10598 TimeOfDay(13, 13, 13),
10599 TimeOfDay(23, 59, 59)];
10600
10601 auto testHours = [0, 1, 12, 22, 23];
10602 auto testMinSecs = [0, 1, 30, 58, 59];
10603
10604 // Throwing exceptions is incredibly expensive, so we want to use a smaller
10605 // set of values for tests using assertThrown.
10606 auto testTODsThrown = [TimeOfDay(0, 0, 0),
10607 TimeOfDay(13, 13, 13),
10608 TimeOfDay(23, 59, 59)];
10609
10610 Date[] testDatesBC;
10611 Date[] testDatesAD;
10612
10613 DateTime[] testDateTimesBC;
10614 DateTime[] testDateTimesAD;
10615
10616 Duration[] testFracSecs;
10617
10618 SysTime[] testSysTimesBC;
10619 SysTime[] testSysTimesAD;
10620
10621 // I'd use a Tuple, but I get forward reference errors if I try.
10622 struct GregDay { int day; Date date; }
10623 auto testGregDaysBC = [GregDay(-1_373_427, Date(-3760, 9, 7)), // Start of the Hebrew Calendar
10624 GregDay(-735_233, Date(-2012, 1, 1)),
10625 GregDay(-735_202, Date(-2012, 2, 1)),
10626 GregDay(-735_175, Date(-2012, 2, 28)),
10627 GregDay(-735_174, Date(-2012, 2, 29)),
10628 GregDay(-735_173, Date(-2012, 3, 1)),
10629 GregDay(-734_502, Date(-2010, 1, 1)),
10630 GregDay(-734_472, Date(-2010, 1, 31)),
10631 GregDay(-734_471, Date(-2010, 2, 1)),
10632 GregDay(-734_444, Date(-2010, 2, 28)),
10633 GregDay(-734_443, Date(-2010, 3, 1)),
10634 GregDay(-734_413, Date(-2010, 3, 31)),
10635 GregDay(-734_412, Date(-2010, 4, 1)),
10636 GregDay(-734_383, Date(-2010, 4, 30)),
10637 GregDay(-734_382, Date(-2010, 5, 1)),
10638 GregDay(-734_352, Date(-2010, 5, 31)),
10639 GregDay(-734_351, Date(-2010, 6, 1)),
10640 GregDay(-734_322, Date(-2010, 6, 30)),
10641 GregDay(-734_321, Date(-2010, 7, 1)),
10642 GregDay(-734_291, Date(-2010, 7, 31)),
10643 GregDay(-734_290, Date(-2010, 8, 1)),
10644 GregDay(-734_260, Date(-2010, 8, 31)),
10645 GregDay(-734_259, Date(-2010, 9, 1)),
10646 GregDay(-734_230, Date(-2010, 9, 30)),
10647 GregDay(-734_229, Date(-2010, 10, 1)),
10648 GregDay(-734_199, Date(-2010, 10, 31)),
10649 GregDay(-734_198, Date(-2010, 11, 1)),
10650 GregDay(-734_169, Date(-2010, 11, 30)),
10651 GregDay(-734_168, Date(-2010, 12, 1)),
10652 GregDay(-734_139, Date(-2010, 12, 30)),
10653 GregDay(-734_138, Date(-2010, 12, 31)),
10654 GregDay(-731_215, Date(-2001, 1, 1)),
10655 GregDay(-730_850, Date(-2000, 1, 1)),
10656 GregDay(-730_849, Date(-2000, 1, 2)),
10657 GregDay(-730_486, Date(-2000, 12, 30)),
10658 GregDay(-730_485, Date(-2000, 12, 31)),
10659 GregDay(-730_484, Date(-1999, 1, 1)),
10660 GregDay(-694_690, Date(-1901, 1, 1)),
10661 GregDay(-694_325, Date(-1900, 1, 1)),
10662 GregDay(-585_118, Date(-1601, 1, 1)),
10663 GregDay(-584_753, Date(-1600, 1, 1)),
10664 GregDay(-584_388, Date(-1600, 12, 31)),
10665 GregDay(-584_387, Date(-1599, 1, 1)),
10666 GregDay(-365_972, Date(-1001, 1, 1)),
10667 GregDay(-365_607, Date(-1000, 1, 1)),
10668 GregDay(-183_351, Date(-501, 1, 1)),
10669 GregDay(-182_986, Date(-500, 1, 1)),
10670 GregDay(-182_621, Date(-499, 1, 1)),
10671 GregDay(-146_827, Date(-401, 1, 1)),
10672 GregDay(-146_462, Date(-400, 1, 1)),
10673 GregDay(-146_097, Date(-400, 12, 31)),
10674 GregDay(-110_302, Date(-301, 1, 1)),
10675 GregDay(-109_937, Date(-300, 1, 1)),
10676 GregDay(-73_778, Date(-201, 1, 1)),
10677 GregDay(-73_413, Date(-200, 1, 1)),
10678 GregDay(-38_715, Date(-105, 1, 1)),
10679 GregDay(-37_254, Date(-101, 1, 1)),
10680 GregDay(-36_889, Date(-100, 1, 1)),
10681 GregDay(-36_524, Date(-99, 1, 1)),
10682 GregDay(-36_160, Date(-99, 12, 31)),
10683 GregDay(-35_794, Date(-97, 1, 1)),
10684 GregDay(-18_627, Date(-50, 1, 1)),
10685 GregDay(-18_262, Date(-49, 1, 1)),
10686 GregDay(-3652, Date(-9, 1, 1)),
10687 GregDay(-2191, Date(-5, 1, 1)),
10688 GregDay(-1827, Date(-5, 12, 31)),
10689 GregDay(-1826, Date(-4, 1, 1)),
10690 GregDay(-1825, Date(-4, 1, 2)),
10691 GregDay(-1462, Date(-4, 12, 30)),
10692 GregDay(-1461, Date(-4, 12, 31)),
10693 GregDay(-1460, Date(-3, 1, 1)),
10694 GregDay(-1096, Date(-3, 12, 31)),
10695 GregDay(-1095, Date(-2, 1, 1)),
10696 GregDay(-731, Date(-2, 12, 31)),
10697 GregDay(-730, Date(-1, 1, 1)),
10698 GregDay(-367, Date(-1, 12, 30)),
10699 GregDay(-366, Date(-1, 12, 31)),
10700 GregDay(-365, Date(0, 1, 1)),
10701 GregDay(-31, Date(0, 11, 30)),
10702 GregDay(-30, Date(0, 12, 1)),
10703 GregDay(-1, Date(0, 12, 30)),
10704 GregDay(0, Date(0, 12, 31))];
10705
10706 auto testGregDaysAD = [GregDay(1, Date(1, 1, 1)),
10707 GregDay(2, Date(1, 1, 2)),
10708 GregDay(32, Date(1, 2, 1)),
10709 GregDay(365, Date(1, 12, 31)),
10710 GregDay(366, Date(2, 1, 1)),
10711 GregDay(731, Date(3, 1, 1)),
10712 GregDay(1096, Date(4, 1, 1)),
10713 GregDay(1097, Date(4, 1, 2)),
10714 GregDay(1460, Date(4, 12, 30)),
10715 GregDay(1461, Date(4, 12, 31)),
10716 GregDay(1462, Date(5, 1, 1)),
10717 GregDay(17_898, Date(50, 1, 1)),
10718 GregDay(35_065, Date(97, 1, 1)),
10719 GregDay(36_160, Date(100, 1, 1)),
10720 GregDay(36_525, Date(101, 1, 1)),
10721 GregDay(37_986, Date(105, 1, 1)),
10722 GregDay(72_684, Date(200, 1, 1)),
10723 GregDay(73_049, Date(201, 1, 1)),
10724 GregDay(109_208, Date(300, 1, 1)),
10725 GregDay(109_573, Date(301, 1, 1)),
10726 GregDay(145_732, Date(400, 1, 1)),
10727 GregDay(146_098, Date(401, 1, 1)),
10728 GregDay(182_257, Date(500, 1, 1)),
10729 GregDay(182_622, Date(501, 1, 1)),
10730 GregDay(364_878, Date(1000, 1, 1)),
10731 GregDay(365_243, Date(1001, 1, 1)),
10732 GregDay(584_023, Date(1600, 1, 1)),
10733 GregDay(584_389, Date(1601, 1, 1)),
10734 GregDay(693_596, Date(1900, 1, 1)),
10735 GregDay(693_961, Date(1901, 1, 1)),
10736 GregDay(729_755, Date(1999, 1, 1)),
10737 GregDay(730_120, Date(2000, 1, 1)),
10738 GregDay(730_121, Date(2000, 1, 2)),
10739 GregDay(730_484, Date(2000, 12, 30)),
10740 GregDay(730_485, Date(2000, 12, 31)),
10741 GregDay(730_486, Date(2001, 1, 1)),
10742 GregDay(733_773, Date(2010, 1, 1)),
10743 GregDay(733_774, Date(2010, 1, 2)),
10744 GregDay(733_803, Date(2010, 1, 31)),
10745 GregDay(733_804, Date(2010, 2, 1)),
10746 GregDay(733_831, Date(2010, 2, 28)),
10747 GregDay(733_832, Date(2010, 3, 1)),
10748 GregDay(733_862, Date(2010, 3, 31)),
10749 GregDay(733_863, Date(2010, 4, 1)),
10750 GregDay(733_892, Date(2010, 4, 30)),
10751 GregDay(733_893, Date(2010, 5, 1)),
10752 GregDay(733_923, Date(2010, 5, 31)),
10753 GregDay(733_924, Date(2010, 6, 1)),
10754 GregDay(733_953, Date(2010, 6, 30)),
10755 GregDay(733_954, Date(2010, 7, 1)),
10756 GregDay(733_984, Date(2010, 7, 31)),
10757 GregDay(733_985, Date(2010, 8, 1)),
10758 GregDay(734_015, Date(2010, 8, 31)),
10759 GregDay(734_016, Date(2010, 9, 1)),
10760 GregDay(734_045, Date(2010, 9, 30)),
10761 GregDay(734_046, Date(2010, 10, 1)),
10762 GregDay(734_076, Date(2010, 10, 31)),
10763 GregDay(734_077, Date(2010, 11, 1)),
10764 GregDay(734_106, Date(2010, 11, 30)),
10765 GregDay(734_107, Date(2010, 12, 1)),
10766 GregDay(734_136, Date(2010, 12, 30)),
10767 GregDay(734_137, Date(2010, 12, 31)),
10768 GregDay(734_503, Date(2012, 1, 1)),
10769 GregDay(734_534, Date(2012, 2, 1)),
10770 GregDay(734_561, Date(2012, 2, 28)),
10771 GregDay(734_562, Date(2012, 2, 29)),
10772 GregDay(734_563, Date(2012, 3, 1)),
10773 GregDay(734_858, Date(2012, 12, 21))];
10774
10775 // I'd use a Tuple, but I get forward reference errors if I try.
10776 struct DayOfYear { int day; MonthDay md; }
10777 auto testDaysOfYear = [DayOfYear(1, MonthDay(1, 1)),
10778 DayOfYear(2, MonthDay(1, 2)),
10779 DayOfYear(3, MonthDay(1, 3)),
10780 DayOfYear(31, MonthDay(1, 31)),
10781 DayOfYear(32, MonthDay(2, 1)),
10782 DayOfYear(59, MonthDay(2, 28)),
10783 DayOfYear(60, MonthDay(3, 1)),
10784 DayOfYear(90, MonthDay(3, 31)),
10785 DayOfYear(91, MonthDay(4, 1)),
10786 DayOfYear(120, MonthDay(4, 30)),
10787 DayOfYear(121, MonthDay(5, 1)),
10788 DayOfYear(151, MonthDay(5, 31)),
10789 DayOfYear(152, MonthDay(6, 1)),
10790 DayOfYear(181, MonthDay(6, 30)),
10791 DayOfYear(182, MonthDay(7, 1)),
10792 DayOfYear(212, MonthDay(7, 31)),
10793 DayOfYear(213, MonthDay(8, 1)),
10794 DayOfYear(243, MonthDay(8, 31)),
10795 DayOfYear(244, MonthDay(9, 1)),
10796 DayOfYear(273, MonthDay(9, 30)),
10797 DayOfYear(274, MonthDay(10, 1)),
10798 DayOfYear(304, MonthDay(10, 31)),
10799 DayOfYear(305, MonthDay(11, 1)),
10800 DayOfYear(334, MonthDay(11, 30)),
10801 DayOfYear(335, MonthDay(12, 1)),
10802 DayOfYear(363, MonthDay(12, 29)),
10803 DayOfYear(364, MonthDay(12, 30)),
10804 DayOfYear(365, MonthDay(12, 31))];
10805
10806 auto testDaysOfLeapYear = [DayOfYear(1, MonthDay(1, 1)),
10807 DayOfYear(2, MonthDay(1, 2)),
10808 DayOfYear(3, MonthDay(1, 3)),
10809 DayOfYear(31, MonthDay(1, 31)),
10810 DayOfYear(32, MonthDay(2, 1)),
10811 DayOfYear(59, MonthDay(2, 28)),
10812 DayOfYear(60, MonthDay(2, 29)),
10813 DayOfYear(61, MonthDay(3, 1)),
10814 DayOfYear(91, MonthDay(3, 31)),
10815 DayOfYear(92, MonthDay(4, 1)),
10816 DayOfYear(121, MonthDay(4, 30)),
10817 DayOfYear(122, MonthDay(5, 1)),
10818 DayOfYear(152, MonthDay(5, 31)),
10819 DayOfYear(153, MonthDay(6, 1)),
10820 DayOfYear(182, MonthDay(6, 30)),
10821 DayOfYear(183, MonthDay(7, 1)),
10822 DayOfYear(213, MonthDay(7, 31)),
10823 DayOfYear(214, MonthDay(8, 1)),
10824 DayOfYear(244, MonthDay(8, 31)),
10825 DayOfYear(245, MonthDay(9, 1)),
10826 DayOfYear(274, MonthDay(9, 30)),
10827 DayOfYear(275, MonthDay(10, 1)),
10828 DayOfYear(305, MonthDay(10, 31)),
10829 DayOfYear(306, MonthDay(11, 1)),
10830 DayOfYear(335, MonthDay(11, 30)),
10831 DayOfYear(336, MonthDay(12, 1)),
10832 DayOfYear(364, MonthDay(12, 29)),
10833 DayOfYear(365, MonthDay(12, 30)),
10834 DayOfYear(366, MonthDay(12, 31))];
10835
10836 void initializeTests() @safe
10837 {
10838 import std.algorithm.sorting : sort;
10839 import std.typecons : Rebindable;
10840 immutable lt = LocalTime().utcToTZ(0);
10841 currLocalDiffFromUTC = dur!"hnsecs"(lt);
10842
10843 version (Posix)
10844 {
10845 immutable otherTZ = lt < 0 ? PosixTimeZone.getTimeZone("Australia/Sydney")
10846 : PosixTimeZone.getTimeZone("America/Denver");
10847 }
10848 else version (Windows)
10849 {
10850 immutable otherTZ = lt < 0 ? WindowsTimeZone.getTimeZone("AUS Eastern Standard Time")
10851 : WindowsTimeZone.getTimeZone("Mountain Standard Time");
10852 }
10853
10854 immutable ot = otherTZ.utcToTZ(0);
10855
10856 auto diffs = [0L, lt, ot];
10857 auto diffAA = [0L : Rebindable!(immutable TimeZone)(UTC())];
10858 diffAA[lt] = Rebindable!(immutable TimeZone)(LocalTime());
10859 diffAA[ot] = Rebindable!(immutable TimeZone)(otherTZ);
10860
10861 sort(diffs);
10862 testTZs = [diffAA[diffs[0]], diffAA[diffs[1]], diffAA[diffs[2]]];
10863
10864 testFracSecs = [Duration.zero, hnsecs(1), hnsecs(5007), hnsecs(9_999_999)];
10865
10866 foreach (year; testYearsBC)
10867 {
10868 foreach (md; testMonthDays)
10869 testDatesBC ~= Date(year, md.month, md.day);
10870 }
10871
10872 foreach (year; testYearsAD)
10873 {
10874 foreach (md; testMonthDays)
10875 testDatesAD ~= Date(year, md.month, md.day);
10876 }
10877
10878 foreach (dt; testDatesBC)
10879 {
10880 foreach (tod; testTODs)
10881 testDateTimesBC ~= DateTime(dt, tod);
10882 }
10883
10884 foreach (dt; testDatesAD)
10885 {
10886 foreach (tod; testTODs)
10887 testDateTimesAD ~= DateTime(dt, tod);
10888 }
10889
10890 foreach (dt; testDateTimesBC)
10891 {
10892 foreach (tz; testTZs)
10893 {
10894 foreach (fs; testFracSecs)
10895 testSysTimesBC ~= SysTime(dt, fs, tz);
10896 }
10897 }
10898
10899 foreach (dt; testDateTimesAD)
10900 {
10901 foreach (tz; testTZs)
10902 {
10903 foreach (fs; testFracSecs)
10904 testSysTimesAD ~= SysTime(dt, fs, tz);
10905 }
10906 }
10907 }
10908 }
10909