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 version (OSX)
11 version = Darwin;
12 else version (iOS)
13 version = Darwin;
14 else version (TVOS)
15 version = Darwin;
16 else version (WatchOS)
17 version = Darwin;
18
19 import core.time;
20 import std.datetime.date;
21 import std.datetime.timezone;
22 import std.exception : enforce;
23 import std.format : format;
24 import std.range.primitives;
25 import std.traits : isIntegral, isSigned, isSomeString, Unqual;
26
version(Windows)27 version (Windows)
28 {
29 import core.stdc.time : time_t;
30 import core.sys.windows.windows;
31 import core.sys.windows.winsock2;
32 }
version(Posix)33 else version (Posix)
34 {
35 import core.sys.posix.signal : timespec;
36 import core.sys.posix.sys.types : time_t;
37 }
38
version(unittest)39 version (unittest)
40 {
41 import core.exception : AssertError;
42 import std.exception : assertThrown;
43 }
44
45
46 @safe unittest
47 {
48 initializeTests();
49 }
50
version(unittest)51 version (unittest) private bool clockSupported(ClockType c)
52 {
53 // Skip unsupported clocks on older linux kernels, assume that only
54 // CLOCK_MONOTONIC and CLOCK_REALTIME exist, as that is the lowest
55 // common denominator supported by all versions of Linux pre-2.6.12.
56 version (Linux_Pre_2639)
57 return c == ClockType.normal || c == ClockType.precise;
58 else
59 return true;
60 }
61
62 /++
63 Effectively a namespace to make it clear that the methods it contains are
64 getting the time from the system clock. It cannot be instantiated.
65 +/
66 final class Clock
67 {
68 public:
69
70 /++
71 Returns the current time in the given time zone.
72
73 Params:
74 clockType = The $(REF ClockType, core,time) indicates which system
75 clock to use to get the current time. Very few programs
76 need to use anything other than the default.
77 tz = The time zone for the SysTime that's returned.
78
79 Throws:
80 $(REF DateTimeException,std,datetime,date) if it fails to get the
81 time.
82 +/
83 static SysTime currTime(ClockType clockType = ClockType.normal)(immutable TimeZone tz = LocalTime()) @safe
84 {
85 return SysTime(currStdTime!clockType, tz);
86 }
87
88 @safe unittest
89 {
90 import std.format : format;
91 import std.stdio : writefln;
92 assert(currTime().timezone is LocalTime());
93 assert(currTime(UTC()).timezone is UTC());
94
95 // core.stdc.time.time does not always use unix time on Windows systems.
96 // In particular, dmc does not use unix time. If we can guarantee that
97 // the MS runtime uses unix time, then we may be able run this test
98 // then, but for now, we're just not going to run this test on Windows.
version(Posix)99 version (Posix)
100 {
101 static import core.stdc.time;
102 static import std.math;
103 immutable unixTimeD = currTime().toUnixTime();
104 immutable unixTimeC = core.stdc.time.time(null);
105 assert(std.math.abs(unixTimeC - unixTimeD) <= 2);
106 }
107
108 auto norm1 = Clock.currTime;
109 auto norm2 = Clock.currTime(UTC());
110 assert(norm1 <= norm2, format("%s %s", norm1, norm2));
111 assert(abs(norm1 - norm2) <= seconds(2));
112
113 import std.meta : AliasSeq;
114 foreach (ct; AliasSeq!(ClockType.coarse, ClockType.precise, ClockType.second))
115 {
116 scope(failure) writefln("ClockType.%s", ct);
117 static if (clockSupported(ct))
118 {
119 auto value1 = Clock.currTime!ct;
120 auto value2 = Clock.currTime!ct(UTC());
121 assert(value1 <= value2, format("%s %s (ClockType: %s)", value1, value2, ct));
122 assert(abs(value1 - value2) <= seconds(2), format("ClockType.%s", ct));
123 }
124 }
125 }
126
127
128 /++
129 Returns the number of hnsecs since midnight, January 1st, 1 A.D. for the
130 current time.
131
132 Params:
133 clockType = The $(REF ClockType, core,time) indicates which system
134 clock to use to get the current time. Very few programs
135 need to use anything other than the default.
136
137 Throws:
138 $(REF DateTimeException,std,datetime,date) if it fails to get the
139 time.
140 +/
141 static @property long currStdTime(ClockType clockType = ClockType.normal)() @trusted
142 {
143 static if (clockType != ClockType.coarse &&
144 clockType != ClockType.normal &&
145 clockType != ClockType.precise &&
146 clockType != ClockType.second)
147 {
148 static assert(0, format("ClockType.%s is not supported by Clock.currTime or Clock.currStdTime", clockType));
149 }
150
version(Windows)151 version (Windows)
152 {
153 FILETIME fileTime;
154 GetSystemTimeAsFileTime(&fileTime);
155 immutable result = FILETIMEToStdTime(&fileTime);
156 static if (clockType == ClockType.second)
157 {
158 // Ideally, this would use core.std.time.time, but the C runtime
159 // has to be using unix time for that to work, and that's not
160 // guaranteed on Windows. Digital Mars does not use unix time.
161 // MS may or may not. If it does, then this can be made to use
162 // core.stdc.time for MS, but for now, we'll leave it like this.
163 return convert!("seconds", "hnsecs")(convert!("hnsecs", "seconds")(result));
164 }
165 else
166 return result;
167 }
version(Posix)168 else version (Posix)
169 {
170 static import core.stdc.time;
171 enum hnsecsToUnixEpoch = unixTimeToStdTime(0);
172
173 version (Darwin)
174 {
175 static if (clockType == ClockType.second)
176 return unixTimeToStdTime(core.stdc.time.time(null));
177 else
178 {
179 import core.sys.posix.sys.time : gettimeofday, timeval;
180 timeval tv = void;
181 // Posix gettimeofday called with a valid timeval address
182 // and a null second parameter doesn't fail.
183 gettimeofday(&tv, null);
184 return convert!("seconds", "hnsecs")(tv.tv_sec) +
185 tv.tv_usec * 10 +
186 hnsecsToUnixEpoch;
187 }
188 }
189 else version (linux)
190 {
191 static if (clockType == ClockType.second)
192 return unixTimeToStdTime(core.stdc.time.time(null));
193 else
194 {
195 import core.sys.linux.time : CLOCK_REALTIME_COARSE;
196 import core.sys.posix.time : clock_gettime, CLOCK_REALTIME;
197 static if (clockType == ClockType.coarse) alias clockArg = CLOCK_REALTIME_COARSE;
198 else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME;
199 else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME;
200 else static assert(0, "Previous static if is wrong.");
201 timespec ts = void;
202 immutable error = clock_gettime(clockArg, &ts);
203 // Posix clock_gettime called with a valid address and valid clock_id is only
204 // permitted to fail if the number of seconds does not fit in time_t. If tv_sec
205 // is long or larger overflow won't happen before 292 billion years A.D.
206 static if (ts.tv_sec.max < long.max)
207 {
208 if (error)
209 throw new TimeException("Call to clock_gettime() failed");
210 }
211 return convert!("seconds", "hnsecs")(ts.tv_sec) +
212 ts.tv_nsec / 100 +
213 hnsecsToUnixEpoch;
214 }
215 }
216 else version (FreeBSD)
217 {
218 import core.sys.freebsd.time : clock_gettime, CLOCK_REALTIME,
219 CLOCK_REALTIME_FAST, CLOCK_REALTIME_PRECISE, CLOCK_SECOND;
220 static if (clockType == ClockType.coarse) alias clockArg = CLOCK_REALTIME_FAST;
221 else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME;
222 else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME_PRECISE;
223 else static if (clockType == ClockType.second) alias clockArg = CLOCK_SECOND;
224 else static assert(0, "Previous static if is wrong.");
225 timespec ts = void;
226 immutable error = clock_gettime(clockArg, &ts);
227 // Posix clock_gettime called with a valid address and valid clock_id is only
228 // permitted to fail if the number of seconds does not fit in time_t. If tv_sec
229 // is long or larger overflow won't happen before 292 billion years A.D.
230 static if (ts.tv_sec.max < long.max)
231 {
232 if (error)
233 throw new TimeException("Call to clock_gettime() failed");
234 }
235 return convert!("seconds", "hnsecs")(ts.tv_sec) +
236 ts.tv_nsec / 100 +
237 hnsecsToUnixEpoch;
238 }
239 else version (NetBSD)
240 {
241 static if (clockType == ClockType.second)
242 return unixTimeToStdTime(core.stdc.time.time(null));
243 else
244 {
245 import core.sys.netbsd.time : clock_gettime, CLOCK_REALTIME;
246 timespec ts = void;
247 immutable error = clock_gettime(CLOCK_REALTIME, &ts);
248 // Posix clock_gettime called with a valid address and valid clock_id is only
249 // permitted to fail if the number of seconds does not fit in time_t. If tv_sec
250 // is long or larger overflow won't happen before 292 billion years A.D.
251 static if (ts.tv_sec.max < long.max)
252 {
253 if (error)
254 throw new TimeException("Call to clock_gettime() failed");
255 }
256 return convert!("seconds", "hnsecs")(ts.tv_sec) +
257 ts.tv_nsec / 100 +
258 hnsecsToUnixEpoch;
259 }
260 }
261 else version (OpenBSD)
262 {
263 static if (clockType == ClockType.second)
264 return unixTimeToStdTime(core.stdc.time.time(null));
265 else
266 {
267 import core.sys.openbsd.time : clock_gettime, CLOCK_REALTIME;
268 static if (clockType == ClockType.coarse) alias clockArg = CLOCK_REALTIME;
269 else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME;
270 else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME;
271 else static assert(0, "Previous static if is wrong.");
272 timespec ts;
273 if (clock_gettime(clockArg, &ts) != 0)
274 throw new TimeException("Call to clock_gettime() failed");
275 return convert!("seconds", "hnsecs")(ts.tv_sec) +
276 ts.tv_nsec / 100 +
277 hnsecsToUnixEpoch;
278 }
279 }
280 else version (DragonFlyBSD)
281 {
282 import core.sys.dragonflybsd.time : clock_gettime, CLOCK_REALTIME,
283 CLOCK_REALTIME_FAST, CLOCK_REALTIME_PRECISE, CLOCK_SECOND;
284 static if (clockType == ClockType.coarse) alias clockArg = CLOCK_REALTIME_FAST;
285 else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME;
286 else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME_PRECISE;
287 else static if (clockType == ClockType.second) alias clockArg = CLOCK_SECOND;
288 else static assert(0, "Previous static if is wrong.");
289 timespec ts = void;
290 immutable error = clock_gettime(clockArg, &ts);
291 // Posix clock_gettime called with a valid address and valid clock_id is only
292 // permitted to fail if the number of seconds does not fit in time_t. If tv_sec
293 // is long or larger overflow won't happen before 292 billion years A.D.
294 static if (ts.tv_sec.max < long.max)
295 {
296 if (error)
297 throw new TimeException("Call to clock_gettime() failed");
298 }
299 return convert!("seconds", "hnsecs")(ts.tv_sec) +
300 ts.tv_nsec / 100 +
301 hnsecsToUnixEpoch;
302 }
303 else version (Solaris)
304 {
305 static if (clockType == ClockType.second)
306 return unixTimeToStdTime(core.stdc.time.time(null));
307 else
308 {
309 import core.sys.solaris.time : clock_gettime, CLOCK_REALTIME;
310 static if (clockType == ClockType.coarse) alias clockArg = CLOCK_REALTIME;
311 else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME;
312 else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME;
313 else static assert(0, "Previous static if is wrong.");
314 timespec ts = void;
315 immutable error = clock_gettime(clockArg, &ts);
316 // Posix clock_gettime called with a valid address and valid clock_id is only
317 // permitted to fail if the number of seconds does not fit in time_t. If tv_sec
318 // is long or larger overflow won't happen before 292 billion years A.D.
319 static if (ts.tv_sec.max < long.max)
320 {
321 if (error)
322 throw new TimeException("Call to clock_gettime() failed");
323 }
324 return convert!("seconds", "hnsecs")(ts.tv_sec) +
325 ts.tv_nsec / 100 +
326 hnsecsToUnixEpoch;
327 }
328 }
329 else static assert(0, "Unsupported OS");
330 }
331 else static assert(0, "Unsupported OS");
332 }
333
334 @safe unittest
335 {
336 import std.format : format;
337 import std.math : abs;
338 import std.meta : AliasSeq;
339 import std.stdio : writefln;
340 enum limit = convert!("seconds", "hnsecs")(2);
341
342 auto norm1 = Clock.currStdTime;
343 auto norm2 = Clock.currStdTime;
344 assert(norm1 <= norm2, format("%s %s", norm1, norm2));
345 assert(abs(norm1 - norm2) <= limit);
346
347 foreach (ct; AliasSeq!(ClockType.coarse, ClockType.precise, ClockType.second))
348 {
349 scope(failure) writefln("ClockType.%s", ct);
350 static if (clockSupported(ct))
351 {
352 auto value1 = Clock.currStdTime!ct;
353 auto value2 = Clock.currStdTime!ct;
354 assert(value1 <= value2, format("%s %s (ClockType: %s)", value1, value2, ct));
355 assert(abs(value1 - value2) <= limit);
356 }
357 }
358 }
359
360
361 private:
362
this()363 @disable this() {}
364 }
365
366
367 /++
368 $(D SysTime) is the type used to get the current time from the
369 system or doing anything that involves time zones. Unlike
370 $(REF DateTime,std,datetime,date), the time zone is an integral part of
371 $(D SysTime) (though for local time applications, time zones can be ignored
372 and it will work, since it defaults to using the local time zone). It holds
373 its internal time in std time (hnsecs since midnight, January 1st, 1 A.D.
374 UTC), so it interfaces well with the system time. However, that means that,
375 unlike $(REF DateTime,std,datetime,date), it is not optimized for
376 calendar-based operations, and getting individual units from it such as
377 years or days is going to involve conversions and be less efficient.
378
379 For calendar-based operations that don't
380 care about time zones, then $(REF DateTime,std,datetime,date) would be
381 the type to use. For system time, use $(D SysTime).
382
383 $(LREF Clock.currTime) will return the current time as a $(D SysTime).
384 To convert a $(D SysTime) to a $(REF Date,std,datetime,date) or
385 $(REF DateTime,std,datetime,date), simply cast it. To convert a
386 $(REF Date,std,datetime,date) or $(REF DateTime,std,datetime,date) to a
387 $(D SysTime), use $(D SysTime)'s constructor, and pass in the ntended time
388 zone with it (or don't pass in a $(REF TimeZone,std,datetime,timezone), and
389 the local time zone will be used). Be aware, however, that converting from a
390 $(REF DateTime,std,datetime,date) to a $(D SysTime) will not necessarily
391 be 100% accurate due to DST (one hour of the year doesn't exist and another
392 occurs twice). To not risk any conversion errors, keep times as
393 $(D SysTime)s. Aside from DST though, there shouldn't be any conversion
394 problems.
395
396 For using time zones other than local time or UTC, use
397 $(REF PosixTimeZone,std,datetime,timezone) on Posix systems (or on Windows,
398 if providing the TZ Database files), and use
399 $(REF WindowsTimeZone,std,datetime,timezone) on Windows systems. The time in
400 $(D SysTime) is kept internally in hnsecs from midnight, January 1st, 1 A.D.
401 UTC. Conversion error cannot happen when changing the time zone of a
402 $(D SysTime). $(REF LocalTime,std,datetime,timezone) is the
403 $(REF TimeZone,std,datetime,timezone) class which represents the local time,
404 and $(D UTC) is the $(REF TimeZone,std,datetime,timezone) class which
405 represents UTC. $(D SysTime) uses $(REF LocalTime,std,datetime,timezone) if
406 no $(REF TimeZone,std,datetime,timezone) is provided. For more details on
407 time zones, see the documentation for $(REF TimeZone,std,datetime,timezone),
408 $(REF PosixTimeZone,std,datetime,timezone), and
409 $(REF WindowsTimeZone,std,datetime,timezone).
410
411 $(D SysTime)'s range is from approximately 29,000 B.C. to approximately
412 29,000 A.D.
413 +/
414 struct SysTime
415 {
416 import core.stdc.time : tm;
417 version (Posix) import core.sys.posix.sys.time : timeval;
418 import std.typecons : Rebindable;
419
420 public:
421
422 /++
423 Params:
424 dateTime = The $(REF DateTime,std,datetime,date) to use to set
425 this $(LREF SysTime)'s internal std time. As
426 $(REF DateTime,std,datetime,date) has no concept of
427 time zone, tz is used as its time zone.
428 tz = The $(REF TimeZone,std,datetime,timezone) to use for this
429 $(LREF SysTime). If null,
430 $(REF LocalTime,std,datetime,timezone) will be used. The
431 given $(REF DateTime,std,datetime,date) is assumed to
432 be in the given time zone.
433 +/
434 this(in DateTime dateTime, immutable TimeZone tz = null) @safe nothrow
435 {
436 try
437 this(dateTime, Duration.zero, tz);
438 catch (Exception e)
439 assert(0, "SysTime's constructor threw when it shouldn't have.");
440 }
441
442 @safe unittest
443 {
testSysTime444 static void test(DateTime dt, immutable TimeZone tz, long expected)
445 {
446 auto sysTime = SysTime(dt, tz);
447 assert(sysTime._stdTime == expected);
448 assert(sysTime._timezone is (tz is null ? LocalTime() : tz), format("Given DateTime: %s", dt));
449 }
450
451 test(DateTime.init, UTC(), 0);
452 test(DateTime(1, 1, 1, 12, 30, 33), UTC(), 450_330_000_000L);
453 test(DateTime(0, 12, 31, 12, 30, 33), UTC(), -413_670_000_000L);
454 test(DateTime(1, 1, 1, 0, 0, 0), UTC(), 0);
455 test(DateTime(1, 1, 1, 0, 0, 1), UTC(), 10_000_000L);
456 test(DateTime(0, 12, 31, 23, 59, 59), UTC(), -10_000_000L);
457
458 test(DateTime(1, 1, 1, 0, 0, 0), new immutable SimpleTimeZone(dur!"minutes"(-60)), 36_000_000_000L);
459 test(DateTime(1, 1, 1, 0, 0, 0), new immutable SimpleTimeZone(Duration.zero), 0);
460 test(DateTime(1, 1, 1, 0, 0, 0), new immutable SimpleTimeZone(dur!"minutes"(60)), -36_000_000_000L);
461 }
462
463 /++
464 Params:
465 dateTime = The $(REF DateTime,std,datetime,date) to use to set
466 this $(LREF SysTime)'s internal std time. As
467 $(REF DateTime,std,datetime,date) has no concept of
468 time zone, tz is used as its time zone.
469 fracSecs = The fractional seconds portion of the time.
470 tz = The $(REF TimeZone,std,datetime,timezone) to use for this
471 $(LREF SysTime). If null,
472 $(REF LocalTime,std,datetime,timezone) will be used. The
473 given $(REF DateTime,std,datetime,date) is assumed to
474 be in the given time zone.
475
476 Throws:
477 $(REF DateTimeException,std,datetime,date) if $(D fracSecs) is negative or if it's
478 greater than or equal to one second.
479 +/
480 this(in DateTime dateTime, in Duration fracSecs, immutable TimeZone tz = null) @safe
481 {
482 enforce(fracSecs >= Duration.zero, new DateTimeException("A SysTime cannot have negative fractional seconds."));
483 enforce(fracSecs < seconds(1), new DateTimeException("Fractional seconds must be less than one second."));
484 auto nonNullTZ = tz is null ? LocalTime() : tz;
485
486 immutable dateDiff = dateTime.date - Date.init;
487 immutable todDiff = dateTime.timeOfDay - TimeOfDay.init;
488
489 immutable adjustedTime = dateDiff + todDiff + fracSecs;
490 immutable standardTime = nonNullTZ.tzToUTC(adjustedTime.total!"hnsecs");
491
492 this(standardTime, nonNullTZ);
493 }
494
495 @safe unittest
496 {
497 static void test(DateTime dt, Duration fracSecs, immutable TimeZone tz, long expected)
498 {
499 auto sysTime = SysTime(dt, fracSecs, tz);
500 assert(sysTime._stdTime == expected);
501 assert(sysTime._timezone is (tz is null ? LocalTime() : tz),
502 format("Given DateTime: %s, Given Duration: %s", dt, fracSecs));
503 }
504
505 test(DateTime.init, Duration.zero, UTC(), 0);
506 test(DateTime(1, 1, 1, 12, 30, 33), Duration.zero, UTC(), 450_330_000_000L);
507 test(DateTime(0, 12, 31, 12, 30, 33), Duration.zero, UTC(), -413_670_000_000L);
508 test(DateTime(1, 1, 1, 0, 0, 0), msecs(1), UTC(), 10_000L);
509 test(DateTime(0, 12, 31, 23, 59, 59), msecs(999), UTC(), -10_000L);
510
511 test(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC(), -1);
512 test(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1), UTC(), -9_999_999);
513 test(DateTime(0, 12, 31, 23, 59, 59), Duration.zero, UTC(), -10_000_000);
514
515 assertThrown!DateTimeException(SysTime(DateTime.init, hnsecs(-1), UTC()));
516 assertThrown!DateTimeException(SysTime(DateTime.init, seconds(1), UTC()));
517 }
518
519 /++
520 Params:
521 date = The $(REF Date,std,datetime,date) to use to set this
522 $(LREF SysTime)'s internal std time. As
523 $(REF Date,std,datetime,date) has no concept of time zone, tz
524 is used as its time zone.
525 tz = The $(REF TimeZone,std,datetime,timezone) to use for this
526 $(LREF SysTime). If null,
527 $(REF LocalTime,std,datetime,timezone) will be used. The
528 given $(REF Date,std,datetime,date) is assumed to be in the
529 given time zone.
530 +/
531 this(in Date date, immutable TimeZone tz = null) @safe nothrow
532 {
533 _timezone = tz is null ? LocalTime() : tz;
534
535 try
536 {
537 immutable adjustedTime = (date - Date(1, 1, 1)).total!"hnsecs";
538 immutable standardTime = _timezone.tzToUTC(adjustedTime);
539
540 this(standardTime, _timezone);
541 }
542 catch (Exception e)
543 assert(0, "Date's constructor through when it shouldn't have.");
544 }
545
546 @safe unittest
547 {
testSysTime548 static void test(Date d, immutable TimeZone tz, long expected)
549 {
550 auto sysTime = SysTime(d, tz);
551 assert(sysTime._stdTime == expected);
552 assert(sysTime._timezone is (tz is null ? LocalTime() : tz), format("Given Date: %s", d));
553 }
554
555 test(Date.init, UTC(), 0);
556 test(Date(1, 1, 1), UTC(), 0);
557 test(Date(1, 1, 2), UTC(), 864000000000);
558 test(Date(0, 12, 31), UTC(), -864000000000);
559 }
560
561 /++
562 Note:
563 Whereas the other constructors take in the given date/time, assume
564 that it's in the given time zone, and convert it to hnsecs in UTC
565 since midnight, January 1st, 1 A.D. UTC - i.e. std time - this
566 constructor takes a std time, which is specifically already in UTC,
567 so no conversion takes place. Of course, the various getter
568 properties and functions will use the given time zone's conversion
569 function to convert the results to that time zone, but no conversion
570 of the arguments to this constructor takes place.
571
572 Params:
573 stdTime = The number of hnsecs since midnight, January 1st, 1 A.D.
574 UTC.
575 tz = The $(REF TimeZone,std,datetime,timezone) to use for this
576 $(LREF SysTime). If null,
577 $(REF LocalTime,std,datetime,timezone) will be used.
578 +/
579 this(long stdTime, immutable TimeZone tz = null) @safe pure nothrow
580 {
581 _stdTime = stdTime;
582 _timezone = tz is null ? LocalTime() : tz;
583 }
584
585 @safe unittest
586 {
testSysTime587 static void test(long stdTime, immutable TimeZone tz)
588 {
589 auto sysTime = SysTime(stdTime, tz);
590 assert(sysTime._stdTime == stdTime);
591 assert(sysTime._timezone is (tz is null ? LocalTime() : tz), format("Given stdTime: %s", stdTime));
592 }
593
foreachSysTime594 foreach (stdTime; [-1234567890L, -250, 0, 250, 1235657390L])
595 {
596 foreach (tz; testTZs)
597 test(stdTime, tz);
598 }
599 }
600
601 /++
602 Params:
603 rhs = The $(LREF SysTime) to assign to this one.
604 +/
605 ref SysTime opAssign(const ref SysTime rhs) return @safe pure nothrow
606 {
607 _stdTime = rhs._stdTime;
608 _timezone = rhs._timezone;
609 return this;
610 }
611
612 /++
613 Params:
614 rhs = The $(LREF SysTime) to assign to this one.
615 +/
616 ref SysTime opAssign(SysTime rhs) scope return @safe pure nothrow
617 {
618 _stdTime = rhs._stdTime;
619 _timezone = rhs._timezone;
620 return this;
621 }
622
623 /++
624 Checks for equality between this $(LREF SysTime) and the given
625 $(LREF SysTime).
626
627 Note that the time zone is ignored. Only the internal
628 std times (which are in UTC) are compared.
629 +/
630 bool opEquals(const SysTime rhs) @safe const pure nothrow
631 {
632 return opEquals(rhs);
633 }
634
635 /// ditto
636 bool opEquals(const ref SysTime rhs) @safe const pure nothrow
637 {
638 return _stdTime == rhs._stdTime;
639 }
640
641 @safe unittest
642 {
643 import std.range : chain;
644
645 assert(SysTime(DateTime.init, UTC()) == SysTime(0, UTC()));
646 assert(SysTime(DateTime.init, UTC()) == SysTime(0));
647 assert(SysTime(Date.init, UTC()) == SysTime(0));
648 assert(SysTime(0) == SysTime(0));
649
650 static void test(DateTime dt, immutable TimeZone tz1, immutable TimeZone tz2)
651 {
652 auto st1 = SysTime(dt);
653 st1.timezone = tz1;
654
655 auto st2 = SysTime(dt);
656 st2.timezone = tz2;
657
658 assert(st1 == st2);
659 }
660
661 foreach (tz1; testTZs)
662 {
663 foreach (tz2; testTZs)
664 {
665 foreach (dt; chain(testDateTimesBC, testDateTimesAD))
666 test(dt, tz1, tz2);
667 }
668 }
669
670 auto st = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
671 const cst = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
672 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
673 assert(st == st);
674 assert(st == cst);
675 //assert(st == ist);
676 assert(cst == st);
677 assert(cst == cst);
678 //assert(cst == ist);
679 //assert(ist == st);
680 //assert(ist == cst);
681 //assert(ist == ist);
682 }
683
684 /++
685 Compares this $(LREF SysTime) with the given $(LREF SysTime).
686
687 Time zone is irrelevant when comparing $(LREF SysTime)s.
688
689 Returns:
690 $(BOOKTABLE,
691 $(TR $(TD this < rhs) $(TD < 0))
692 $(TR $(TD this == rhs) $(TD 0))
693 $(TR $(TD this > rhs) $(TD > 0))
694 )
695 +/
696 int opCmp(in SysTime rhs) @safe const pure nothrow
697 {
698 if (_stdTime < rhs._stdTime)
699 return -1;
700 if (_stdTime > rhs._stdTime)
701 return 1;
702 return 0;
703 }
704
705 @safe unittest
706 {
707 import std.algorithm.iteration : map;
708 import std.array : array;
709 import std.range : chain;
710
711 assert(SysTime(DateTime.init, UTC()).opCmp(SysTime(0, UTC())) == 0);
712 assert(SysTime(DateTime.init, UTC()).opCmp(SysTime(0)) == 0);
713 assert(SysTime(Date.init, UTC()).opCmp(SysTime(0)) == 0);
714 assert(SysTime(0).opCmp(SysTime(0)) == 0);
715
716 static void testEqual(SysTime st, immutable TimeZone tz1, immutable TimeZone tz2)
717 {
718 auto st1 = st;
719 st1.timezone = tz1;
720
721 auto st2 = st;
722 st2.timezone = tz2;
723
724 assert(st1.opCmp(st2) == 0);
725 }
726
727 auto sts = array(map!SysTime(chain(testDateTimesBC, testDateTimesAD)));
728
729 foreach (st; sts)
730 {
731 foreach (tz1; testTZs)
732 {
733 foreach (tz2; testTZs)
734 testEqual(st, tz1, tz2);
735 }
736 }
737
738 static void testCmp(SysTime st1, immutable TimeZone tz1, SysTime st2, immutable TimeZone tz2)
739 {
740 st1.timezone = tz1;
741 st2.timezone = tz2;
742 assert(st1.opCmp(st2) < 0);
743 assert(st2.opCmp(st1) > 0);
744 }
745
746 foreach (si, st1; sts)
747 {
748 foreach (st2; sts[si + 1 .. $])
749 {
750 foreach (tz1; testTZs)
751 {
752 foreach (tz2; testTZs)
753 testCmp(st1, tz1, st2, tz2);
754 }
755 }
756 }
757
758 auto st = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
759 const cst = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
760 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
761 assert(st.opCmp(st) == 0);
762 assert(st.opCmp(cst) == 0);
763 //assert(st.opCmp(ist) == 0);
764 assert(cst.opCmp(st) == 0);
765 assert(cst.opCmp(cst) == 0);
766 //assert(cst.opCmp(ist) == 0);
767 //assert(ist.opCmp(st) == 0);
768 //assert(ist.opCmp(cst) == 0);
769 //assert(ist.opCmp(ist) == 0);
770 }
771
772 /**
773 * Returns: A hash of the $(LREF SysTime)
774 */
775 size_t toHash() const @nogc pure nothrow @safe
776 {
777 static if (is(size_t == ulong))
778 return _stdTime;
779 else
780 {
781 // MurmurHash2
782 enum ulong m = 0xc6a4a7935bd1e995UL;
783 enum ulong n = m * 16;
784 enum uint r = 47;
785
786 ulong k = _stdTime;
787 k *= m;
788 k ^= k >> r;
789 k *= m;
790
791 ulong h = n;
792 h ^= k;
793 h *= m;
794
795 return cast(size_t) h;
796 }
797 }
798
799 @safe unittest
800 {
801 assert(SysTime(0).toHash == SysTime(0).toHash);
802 assert(SysTime(DateTime(2000, 1, 1)).toHash == SysTime(DateTime(2000, 1, 1)).toHash);
803 assert(SysTime(DateTime(2000, 1, 1)).toHash != SysTime(DateTime(2000, 1, 2)).toHash);
804
805 // test that timezones aren't taken into account
806 assert(SysTime(0, LocalTime()).toHash == SysTime(0, LocalTime()).toHash);
807 assert(SysTime(0, LocalTime()).toHash == SysTime(0, UTC()).toHash);
808 assert(SysTime(DateTime(2000, 1, 1), LocalTime()).toHash == SysTime(DateTime(2000, 1, 1), LocalTime()).toHash);
809 immutable zone = new SimpleTimeZone(dur!"minutes"(60));
810 assert(SysTime(DateTime(2000, 1, 1, 1), zone).toHash == SysTime(DateTime(2000, 1, 1), UTC()).toHash);
811 assert(SysTime(DateTime(2000, 1, 1), zone).toHash != SysTime(DateTime(2000, 1, 1), UTC()).toHash);
812 }
813
814 /++
815 Year of the Gregorian Calendar. Positive numbers are A.D. Non-positive
816 are B.C.
817 +/
818 @property short year() @safe const nothrow
819 {
820 return (cast(Date) this).year;
821 }
822
823 @safe unittest
824 {
825 import std.range : chain;
826 static void test(SysTime sysTime, long expected)
827 {
828 assert(sysTime.year == expected, format("Value given: %s", sysTime));
829 }
830
831 test(SysTime(0, UTC()), 1);
832 test(SysTime(1, UTC()), 1);
833 test(SysTime(-1, UTC()), 0);
834
835 foreach (year; chain(testYearsBC, testYearsAD))
836 {
837 foreach (md; testMonthDays)
838 {
839 foreach (tod; testTODs)
840 {
841 auto dt = DateTime(Date(year, md.month, md.day), tod);
842 foreach (tz; testTZs)
843 {
844 foreach (fs; testFracSecs)
845 test(SysTime(dt, fs, tz), year);
846 }
847 }
848 }
849 }
850
851 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
852 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
853 assert(cst.year == 1999);
854 //assert(ist.year == 1999);
855 }
856
857 /++
858 Year of the Gregorian Calendar. Positive numbers are A.D. Non-positive
859 are B.C.
860
861 Params:
862 year = The year to set this $(LREF SysTime)'s year to.
863
864 Throws:
865 $(REF DateTimeException,std,datetime,date) if the new year is not
866 a leap year and the resulting date would be on February 29th.
867 +/
868 @property void year(int year) @safe
869 {
870 auto hnsecs = adjTime;
871 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
872
873 if (hnsecs < 0)
874 {
875 hnsecs += convert!("hours", "hnsecs")(24);
876 --days;
877 }
878
879 auto date = Date(cast(int) days);
880 date.year = year;
881
882 immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
883 adjTime = newDaysHNSecs + hnsecs;
884 }
885
886 ///
887 @safe unittest
888 {
889 import std.datetime.date : DateTime;
890
891 assert(SysTime(DateTime(1999, 7, 6, 9, 7, 5)).year == 1999);
892 assert(SysTime(DateTime(2010, 10, 4, 0, 0, 30)).year == 2010);
893 assert(SysTime(DateTime(-7, 4, 5, 7, 45, 2)).year == -7);
894 }
895
896 @safe unittest
897 {
898 import std.range : chain;
899
900 static void test(SysTime st, int year, in SysTime expected)
901 {
902 st.year = year;
903 assert(st == expected);
904 }
905
906 foreach (st; chain(testSysTimesBC, testSysTimesAD))
907 {
908 auto dt = cast(DateTime) st;
909
910 foreach (year; chain(testYearsBC, testYearsAD))
911 {
912 auto e = SysTime(DateTime(year, dt.month, dt.day, dt.hour, dt.minute, dt.second),
913 st.fracSecs,
914 st.timezone);
915 test(st, year, e);
916 }
917 }
918
919 foreach (fs; testFracSecs)
920 {
921 foreach (tz; testTZs)
922 {
923 foreach (tod; testTODs)
924 {
925 test(SysTime(DateTime(Date(1999, 2, 28), tod), fs, tz), 2000,
926 SysTime(DateTime(Date(2000, 2, 28), tod), fs, tz));
927 test(SysTime(DateTime(Date(2000, 2, 28), tod), fs, tz), 1999,
928 SysTime(DateTime(Date(1999, 2, 28), tod), fs, tz));
929 }
930
931 foreach (tod; testTODsThrown)
932 {
933 auto st = SysTime(DateTime(Date(2000, 2, 29), tod), fs, tz);
934 assertThrown!DateTimeException(st.year = 1999);
935 }
936 }
937 }
938
939 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
940 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
941 static assert(!__traits(compiles, cst.year = 7));
942 //static assert(!__traits(compiles, ist.year = 7));
943 }
944
945 /++
946 Year B.C. of the Gregorian Calendar counting year 0 as 1 B.C.
947
948 Throws:
949 $(REF DateTimeException,std,datetime,date) if $(D isAD) is true.
950 +/
951 @property ushort yearBC() @safe const
952 {
953 return (cast(Date) this).yearBC;
954 }
955
956 ///
957 @safe unittest
958 {
959 import std.datetime.date : DateTime;
960
961 assert(SysTime(DateTime(0, 1, 1, 12, 30, 33)).yearBC == 1);
962 assert(SysTime(DateTime(-1, 1, 1, 10, 7, 2)).yearBC == 2);
963 assert(SysTime(DateTime(-100, 1, 1, 4, 59, 0)).yearBC == 101);
964 }
965
966 @safe unittest
967 {
968 import std.exception : assertNotThrown;
969 foreach (st; testSysTimesBC)
970 {
971 auto msg = format("SysTime: %s", st);
972 assertNotThrown!DateTimeException(st.yearBC, msg);
973 assert(st.yearBC == (st.year * -1) + 1, msg);
974 }
975
976 foreach (st; [testSysTimesAD[0], testSysTimesAD[$/2], testSysTimesAD[$-1]])
977 assertThrown!DateTimeException(st.yearBC, format("SysTime: %s", st));
978
979 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
980 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
981 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
982 st.year = 12;
983 assert(st.year == 12);
984 static assert(!__traits(compiles, cst.year = 12));
985 //static assert(!__traits(compiles, ist.year = 12));
986 }
987
988
989 /++
990 Year B.C. of the Gregorian Calendar counting year 0 as 1 B.C.
991
992 Params:
993 year = The year B.C. to set this $(LREF SysTime)'s year to.
994
995 Throws:
996 $(REF DateTimeException,std,datetime,date) if a non-positive value
997 is given.
998 +/
999 @property void yearBC(int year) @safe
1000 {
1001 auto hnsecs = adjTime;
1002 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
1003
1004 if (hnsecs < 0)
1005 {
1006 hnsecs += convert!("hours", "hnsecs")(24);
1007 --days;
1008 }
1009
1010 auto date = Date(cast(int) days);
1011 date.yearBC = year;
1012
1013 immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
1014 adjTime = newDaysHNSecs + hnsecs;
1015 }
1016
1017 @safe unittest
1018 {
1019 auto st = SysTime(DateTime(2010, 1, 1, 7, 30, 0));
1020 st.yearBC = 1;
1021 assert(st == SysTime(DateTime(0, 1, 1, 7, 30, 0)));
1022
1023 st.yearBC = 10;
1024 assert(st == SysTime(DateTime(-9, 1, 1, 7, 30, 0)));
1025 }
1026
1027 @safe unittest
1028 {
1029 import std.range : chain;
1030 static void test(SysTime st, int year, in SysTime expected)
1031 {
1032 st.yearBC = year;
1033 assert(st == expected, format("SysTime: %s", st));
1034 }
1035
1036 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1037 {
1038 auto dt = cast(DateTime) st;
1039
1040 foreach (year; testYearsBC)
1041 {
1042 auto e = SysTime(DateTime(year, dt.month, dt.day, dt.hour, dt.minute, dt.second),
1043 st.fracSecs,
1044 st.timezone);
1045 test(st, (year * -1) + 1, e);
1046 }
1047 }
1048
1049 foreach (st; [testSysTimesBC[0], testSysTimesBC[$ - 1], testSysTimesAD[0], testSysTimesAD[$ - 1]])
1050 {
1051 foreach (year; testYearsBC)
1052 assertThrown!DateTimeException(st.yearBC = year);
1053 }
1054
1055 foreach (fs; testFracSecs)
1056 {
1057 foreach (tz; testTZs)
1058 {
1059 foreach (tod; testTODs)
1060 {
1061 test(SysTime(DateTime(Date(-1999, 2, 28), tod), fs, tz), 2001,
1062 SysTime(DateTime(Date(-2000, 2, 28), tod), fs, tz));
1063 test(SysTime(DateTime(Date(-2000, 2, 28), tod), fs, tz), 2000,
1064 SysTime(DateTime(Date(-1999, 2, 28), tod), fs, tz));
1065 }
1066
1067 foreach (tod; testTODsThrown)
1068 {
1069 auto st = SysTime(DateTime(Date(-2000, 2, 29), tod), fs, tz);
1070 assertThrown!DateTimeException(st.year = -1999);
1071 }
1072 }
1073 }
1074
1075 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1076 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1077 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1078 st.yearBC = 12;
1079 assert(st.yearBC == 12);
1080 static assert(!__traits(compiles, cst.yearBC = 12));
1081 //static assert(!__traits(compiles, ist.yearBC = 12));
1082 }
1083
1084 /++
1085 Month of a Gregorian Year.
1086 +/
1087 @property Month month() @safe const nothrow
1088 {
1089 return (cast(Date) this).month;
1090 }
1091
1092 ///
1093 @safe unittest
1094 {
1095 import std.datetime.date : DateTime;
1096
1097 assert(SysTime(DateTime(1999, 7, 6, 9, 7, 5)).month == 7);
1098 assert(SysTime(DateTime(2010, 10, 4, 0, 0, 30)).month == 10);
1099 assert(SysTime(DateTime(-7, 4, 5, 7, 45, 2)).month == 4);
1100 }
1101
1102 @safe unittest
1103 {
1104 import std.range : chain;
1105
1106 static void test(SysTime sysTime, Month expected)
1107 {
1108 assert(sysTime.month == expected, format("Value given: %s", sysTime));
1109 }
1110
1111 test(SysTime(0, UTC()), Month.jan);
1112 test(SysTime(1, UTC()), Month.jan);
1113 test(SysTime(-1, UTC()), Month.dec);
1114
1115 foreach (year; chain(testYearsBC, testYearsAD))
1116 {
1117 foreach (md; testMonthDays)
1118 {
1119 foreach (tod; testTODs)
1120 {
1121 auto dt = DateTime(Date(year, md.month, md.day), tod);
1122 foreach (fs; testFracSecs)
1123 {
1124 foreach (tz; testTZs)
1125 test(SysTime(dt, fs, tz), md.month);
1126 }
1127 }
1128 }
1129 }
1130
1131 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1132 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1133 assert(cst.month == 7);
1134 //assert(ist.month == 7);
1135 }
1136
1137
1138 /++
1139 Month of a Gregorian Year.
1140
1141 Params:
1142 month = The month to set this $(LREF SysTime)'s month to.
1143
1144 Throws:
1145 $(REF DateTimeException,std,datetime,date) if the given month is
1146 not a valid month.
1147 +/
1148 @property void month(Month month) @safe
1149 {
1150 auto hnsecs = adjTime;
1151 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
1152
1153 if (hnsecs < 0)
1154 {
1155 hnsecs += convert!("hours", "hnsecs")(24);
1156 --days;
1157 }
1158
1159 auto date = Date(cast(int) days);
1160 date.month = month;
1161
1162 immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
1163 adjTime = newDaysHNSecs + hnsecs;
1164 }
1165
1166 @safe unittest
1167 {
1168 import std.algorithm.iteration : filter;
1169 import std.range : chain;
1170
1171 static void test(SysTime st, Month month, in SysTime expected)
1172 {
1173 st.month = cast(Month) month;
1174 assert(st == expected);
1175 }
1176
1177 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1178 {
1179 auto dt = cast(DateTime) st;
1180
1181 foreach (md; testMonthDays)
1182 {
1183 if (st.day > maxDay(dt.year, md.month))
1184 continue;
1185 auto e = SysTime(DateTime(dt.year, md.month, dt.day, dt.hour, dt.minute, dt.second),
1186 st.fracSecs,
1187 st.timezone);
1188 test(st, md.month, e);
1189 }
1190 }
1191
1192 foreach (fs; testFracSecs)
1193 {
1194 foreach (tz; testTZs)
1195 {
1196 foreach (tod; testTODs)
1197 {
1198 foreach (year; filter!((a){return yearIsLeapYear(a);}) (chain(testYearsBC, testYearsAD)))
1199 {
1200 test(SysTime(DateTime(Date(year, 1, 29), tod), fs, tz),
1201 Month.feb,
1202 SysTime(DateTime(Date(year, 2, 29), tod), fs, tz));
1203 }
1204
1205 foreach (year; chain(testYearsBC, testYearsAD))
1206 {
1207 test(SysTime(DateTime(Date(year, 1, 28), tod), fs, tz),
1208 Month.feb,
1209 SysTime(DateTime(Date(year, 2, 28), tod), fs, tz));
1210 test(SysTime(DateTime(Date(year, 7, 30), tod), fs, tz),
1211 Month.jun,
1212 SysTime(DateTime(Date(year, 6, 30), tod), fs, tz));
1213 }
1214 }
1215 }
1216 }
1217
1218 foreach (fs; [testFracSecs[0], testFracSecs[$-1]])
1219 {
1220 foreach (tz; testTZs)
1221 {
1222 foreach (tod; testTODsThrown)
1223 {
1224 foreach (year; [testYearsBC[$-3], testYearsBC[$-2],
1225 testYearsBC[$-2], testYearsAD[0],
1226 testYearsAD[$-2], testYearsAD[$-1]])
1227 {
1228 auto day = yearIsLeapYear(year) ? 30 : 29;
1229 auto st1 = SysTime(DateTime(Date(year, 1, day), tod), fs, tz);
1230 assertThrown!DateTimeException(st1.month = Month.feb);
1231
1232 auto st2 = SysTime(DateTime(Date(year, 7, 31), tod), fs, tz);
1233 assertThrown!DateTimeException(st2.month = Month.jun);
1234 }
1235 }
1236 }
1237 }
1238
1239 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1240 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1241 static assert(!__traits(compiles, cst.month = 12));
1242 //static assert(!__traits(compiles, ist.month = 12));
1243 }
1244
1245 /++
1246 Day of a Gregorian Month.
1247 +/
1248 @property ubyte day() @safe const nothrow
1249 {
1250 return (cast(Date) this).day;
1251 }
1252
1253 ///
1254 @safe unittest
1255 {
1256 import std.datetime.date : DateTime;
1257
1258 assert(SysTime(DateTime(1999, 7, 6, 9, 7, 5)).day == 6);
1259 assert(SysTime(DateTime(2010, 10, 4, 0, 0, 30)).day == 4);
1260 assert(SysTime(DateTime(-7, 4, 5, 7, 45, 2)).day == 5);
1261 }
1262
1263 @safe unittest
1264 {
1265 import std.range : chain;
1266
1267 static void test(SysTime sysTime, int expected)
1268 {
1269 assert(sysTime.day == expected, format("Value given: %s", sysTime));
1270 }
1271
1272 test(SysTime(0, UTC()), 1);
1273 test(SysTime(1, UTC()), 1);
1274 test(SysTime(-1, UTC()), 31);
1275
1276 foreach (year; chain(testYearsBC, testYearsAD))
1277 {
1278 foreach (md; testMonthDays)
1279 {
1280 foreach (tod; testTODs)
1281 {
1282 auto dt = DateTime(Date(year, md.month, md.day), tod);
1283
1284 foreach (tz; testTZs)
1285 {
1286 foreach (fs; testFracSecs)
1287 test(SysTime(dt, fs, tz), md.day);
1288 }
1289 }
1290 }
1291 }
1292
1293 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1294 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1295 assert(cst.day == 6);
1296 //assert(ist.day == 6);
1297 }
1298
1299
1300 /++
1301 Day of a Gregorian Month.
1302
1303 Params:
1304 day = The day of the month to set this $(LREF SysTime)'s day to.
1305
1306 Throws:
1307 $(REF DateTimeException,std,datetime,date) if the given day is not
1308 a valid day of the current month.
1309 +/
1310 @property void day(int day) @safe
1311 {
1312 auto hnsecs = adjTime;
1313 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
1314
1315 if (hnsecs < 0)
1316 {
1317 hnsecs += convert!("hours", "hnsecs")(24);
1318 --days;
1319 }
1320
1321 auto date = Date(cast(int) days);
1322 date.day = day;
1323
1324 immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
1325 adjTime = newDaysHNSecs + hnsecs;
1326 }
1327
1328 @safe unittest
1329 {
1330 import std.range : chain;
1331 import std.traits : EnumMembers;
1332
1333 foreach (day; chain(testDays))
1334 {
1335 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1336 {
1337 auto dt = cast(DateTime) st;
1338
1339 if (day > maxDay(dt.year, dt.month))
1340 continue;
1341 auto expected = SysTime(DateTime(dt.year, dt.month, day, dt.hour, dt.minute, dt.second),
1342 st.fracSecs,
1343 st.timezone);
1344 st.day = day;
1345 assert(st == expected, format("[%s] [%s]", st, expected));
1346 }
1347 }
1348
1349 foreach (tz; testTZs)
1350 {
1351 foreach (tod; testTODs)
1352 {
1353 foreach (fs; testFracSecs)
1354 {
1355 foreach (year; chain(testYearsBC, testYearsAD))
1356 {
1357 foreach (month; EnumMembers!Month)
1358 {
1359 auto st = SysTime(DateTime(Date(year, month, 1), tod), fs, tz);
1360 immutable max = maxDay(year, month);
1361 auto expected = SysTime(DateTime(Date(year, month, max), tod), fs, tz);
1362
1363 st.day = max;
1364 assert(st == expected, format("[%s] [%s]", st, expected));
1365 }
1366 }
1367 }
1368 }
1369 }
1370
1371 foreach (tz; testTZs)
1372 {
1373 foreach (tod; testTODsThrown)
1374 {
1375 foreach (fs; [testFracSecs[0], testFracSecs[$-1]])
1376 {
1377 foreach (year; [testYearsBC[$-3], testYearsBC[$-2],
1378 testYearsBC[$-2], testYearsAD[0],
1379 testYearsAD[$-2], testYearsAD[$-1]])
1380 {
1381 foreach (month; EnumMembers!Month)
1382 {
1383 auto st = SysTime(DateTime(Date(year, month, 1), tod), fs, tz);
1384 immutable max = maxDay(year, month);
1385
1386 assertThrown!DateTimeException(st.day = max + 1);
1387 }
1388 }
1389 }
1390 }
1391 }
1392
1393 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1394 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1395 static assert(!__traits(compiles, cst.day = 27));
1396 //static assert(!__traits(compiles, ist.day = 27));
1397 }
1398
1399
1400 /++
1401 Hours past midnight.
1402 +/
1403 @property ubyte hour() @safe const nothrow
1404 {
1405 auto hnsecs = adjTime;
1406 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
1407
1408 if (hnsecs < 0)
1409 {
1410 hnsecs += convert!("hours", "hnsecs")(24);
1411 --days;
1412 }
1413
1414 return cast(ubyte) getUnitsFromHNSecs!"hours"(hnsecs);
1415 }
1416
1417 @safe unittest
1418 {
1419 import std.range : chain;
1420
1421 static void test(SysTime sysTime, int expected)
1422 {
1423 assert(sysTime.hour == expected, format("Value given: %s", sysTime));
1424 }
1425
1426 test(SysTime(0, UTC()), 0);
1427 test(SysTime(1, UTC()), 0);
1428 test(SysTime(-1, UTC()), 23);
1429
1430 foreach (tz; testTZs)
1431 {
1432 foreach (year; chain(testYearsBC, testYearsAD))
1433 {
1434 foreach (md; testMonthDays)
1435 {
1436 foreach (hour; testHours)
1437 {
1438 foreach (minute; testMinSecs)
1439 {
1440 foreach (second; testMinSecs)
1441 {
1442 auto dt = DateTime(Date(year, md.month, md.day), TimeOfDay(hour, minute, second));
1443 foreach (fs; testFracSecs)
1444 test(SysTime(dt, fs, tz), hour);
1445 }
1446 }
1447 }
1448 }
1449 }
1450 }
1451
1452 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1453 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1454 assert(cst.hour == 12);
1455 //assert(ist.hour == 12);
1456 }
1457
1458
1459 /++
1460 Hours past midnight.
1461
1462 Params:
1463 hour = The hours to set this $(LREF SysTime)'s hour to.
1464
1465 Throws:
1466 $(REF DateTimeException,std,datetime,date) if the given hour are
1467 not a valid hour of the day.
1468 +/
1469 @property void hour(int hour) @safe
1470 {
1471 enforceValid!"hours"(hour);
1472
1473 auto hnsecs = adjTime;
1474 auto days = splitUnitsFromHNSecs!"days"(hnsecs);
1475 immutable daysHNSecs = convert!("days", "hnsecs")(days);
1476 immutable negative = hnsecs < 0;
1477
1478 if (negative)
1479 hnsecs += convert!("hours", "hnsecs")(24);
1480
1481 hnsecs = removeUnitsFromHNSecs!"hours"(hnsecs);
1482 hnsecs += convert!("hours", "hnsecs")(hour);
1483
1484 if (negative)
1485 hnsecs -= convert!("hours", "hnsecs")(24);
1486
1487 adjTime = daysHNSecs + hnsecs;
1488 }
1489
1490 @safe unittest
1491 {
1492 import std.range : chain;
1493
1494 foreach (hour; chain(testHours))
1495 {
1496 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1497 {
1498 auto dt = cast(DateTime) st;
1499 auto expected = SysTime(DateTime(dt.year, dt.month, dt.day, hour, dt.minute, dt.second),
1500 st.fracSecs,
1501 st.timezone);
1502 st.hour = hour;
1503 assert(st == expected, format("[%s] [%s]", st, expected));
1504 }
1505 }
1506
1507 auto st = testSysTimesAD[0];
1508 assertThrown!DateTimeException(st.hour = -1);
1509 assertThrown!DateTimeException(st.hour = 60);
1510
1511 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1512 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1513 static assert(!__traits(compiles, cst.hour = 27));
1514 //static assert(!__traits(compiles, ist.hour = 27));
1515 }
1516
1517
1518 /++
1519 Minutes past the current hour.
1520 +/
1521 @property ubyte minute() @safe const nothrow
1522 {
1523 auto hnsecs = adjTime;
1524 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
1525
1526 if (hnsecs < 0)
1527 {
1528 hnsecs += convert!("hours", "hnsecs")(24);
1529 --days;
1530 }
1531
1532 hnsecs = removeUnitsFromHNSecs!"hours"(hnsecs);
1533
1534 return cast(ubyte) getUnitsFromHNSecs!"minutes"(hnsecs);
1535 }
1536
1537 @safe unittest
1538 {
1539 import std.range : chain;
1540
1541 static void test(SysTime sysTime, int expected)
1542 {
1543 assert(sysTime.minute == expected, format("Value given: %s", sysTime));
1544 }
1545
1546 test(SysTime(0, UTC()), 0);
1547 test(SysTime(1, UTC()), 0);
1548 test(SysTime(-1, UTC()), 59);
1549
1550 foreach (tz; testTZs)
1551 {
1552 foreach (year; chain(testYearsBC, testYearsAD))
1553 {
1554 foreach (md; testMonthDays)
1555 {
1556 foreach (hour; testHours)
1557 {
1558 foreach (minute; testMinSecs)
1559 {
1560 foreach (second; testMinSecs)
1561 {
1562 auto dt = DateTime(Date(year, md.month, md.day), TimeOfDay(hour, minute, second));
1563 foreach (fs; testFracSecs)
1564 test(SysTime(dt, fs, tz), minute);
1565 }
1566 }
1567 }
1568 }
1569 }
1570 }
1571
1572 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1573 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1574 assert(cst.minute == 30);
1575 //assert(ist.minute == 30);
1576 }
1577
1578
1579 /++
1580 Minutes past the current hour.
1581
1582 Params:
1583 minute = The minute to set this $(LREF SysTime)'s minute to.
1584
1585 Throws:
1586 $(REF DateTimeException,std,datetime,date) if the given minute are
1587 not a valid minute of an hour.
1588 +/
1589 @property void minute(int minute) @safe
1590 {
1591 enforceValid!"minutes"(minute);
1592
1593 auto hnsecs = adjTime;
1594 auto days = splitUnitsFromHNSecs!"days"(hnsecs);
1595 immutable daysHNSecs = convert!("days", "hnsecs")(days);
1596 immutable negative = hnsecs < 0;
1597
1598 if (negative)
1599 hnsecs += convert!("hours", "hnsecs")(24);
1600
1601 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
1602 hnsecs = removeUnitsFromHNSecs!"minutes"(hnsecs);
1603
1604 hnsecs += convert!("hours", "hnsecs")(hour);
1605 hnsecs += convert!("minutes", "hnsecs")(minute);
1606
1607 if (negative)
1608 hnsecs -= convert!("hours", "hnsecs")(24);
1609
1610 adjTime = daysHNSecs + hnsecs;
1611 }
1612
1613 @safe unittest
1614 {
1615 import std.range : chain;
1616
1617 foreach (minute; testMinSecs)
1618 {
1619 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1620 {
1621 auto dt = cast(DateTime) st;
1622 auto expected = SysTime(DateTime(dt.year, dt.month, dt.day, dt.hour, minute, dt.second),
1623 st.fracSecs,
1624 st.timezone);
1625 st.minute = minute;
1626 assert(st == expected, format("[%s] [%s]", st, expected));
1627 }
1628 }
1629
1630 auto st = testSysTimesAD[0];
1631 assertThrown!DateTimeException(st.minute = -1);
1632 assertThrown!DateTimeException(st.minute = 60);
1633
1634 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1635 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1636 static assert(!__traits(compiles, cst.minute = 27));
1637 //static assert(!__traits(compiles, ist.minute = 27));
1638 }
1639
1640
1641 /++
1642 Seconds past the current minute.
1643 +/
1644 @property ubyte second() @safe const nothrow
1645 {
1646 auto hnsecs = adjTime;
1647 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
1648
1649 if (hnsecs < 0)
1650 {
1651 hnsecs += convert!("hours", "hnsecs")(24);
1652 --days;
1653 }
1654
1655 hnsecs = removeUnitsFromHNSecs!"hours"(hnsecs);
1656 hnsecs = removeUnitsFromHNSecs!"minutes"(hnsecs);
1657
1658 return cast(ubyte) getUnitsFromHNSecs!"seconds"(hnsecs);
1659 }
1660
1661 @safe unittest
1662 {
1663 import std.range : chain;
1664
1665 static void test(SysTime sysTime, int expected)
1666 {
1667 assert(sysTime.second == expected, format("Value given: %s", sysTime));
1668 }
1669
1670 test(SysTime(0, UTC()), 0);
1671 test(SysTime(1, UTC()), 0);
1672 test(SysTime(-1, UTC()), 59);
1673
1674 foreach (tz; testTZs)
1675 {
1676 foreach (year; chain(testYearsBC, testYearsAD))
1677 {
1678 foreach (md; testMonthDays)
1679 {
1680 foreach (hour; testHours)
1681 {
1682 foreach (minute; testMinSecs)
1683 {
1684 foreach (second; testMinSecs)
1685 {
1686 auto dt = DateTime(Date(year, md.month, md.day), TimeOfDay(hour, minute, second));
1687 foreach (fs; testFracSecs)
1688 test(SysTime(dt, fs, tz), second);
1689 }
1690 }
1691 }
1692 }
1693 }
1694 }
1695
1696 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1697 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1698 assert(cst.second == 33);
1699 //assert(ist.second == 33);
1700 }
1701
1702
1703 /++
1704 Seconds past the current minute.
1705
1706 Params:
1707 second = The second to set this $(LREF SysTime)'s second to.
1708
1709 Throws:
1710 $(REF DateTimeException,std,datetime,date) if the given second are
1711 not a valid second of a minute.
1712 +/
1713 @property void second(int second) @safe
1714 {
1715 enforceValid!"seconds"(second);
1716
1717 auto hnsecs = adjTime;
1718 auto days = splitUnitsFromHNSecs!"days"(hnsecs);
1719 immutable daysHNSecs = convert!("days", "hnsecs")(days);
1720 immutable negative = hnsecs < 0;
1721
1722 if (negative)
1723 hnsecs += convert!("hours", "hnsecs")(24);
1724
1725 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
1726 immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
1727 hnsecs = removeUnitsFromHNSecs!"seconds"(hnsecs);
1728
1729 hnsecs += convert!("hours", "hnsecs")(hour);
1730 hnsecs += convert!("minutes", "hnsecs")(minute);
1731 hnsecs += convert!("seconds", "hnsecs")(second);
1732
1733 if (negative)
1734 hnsecs -= convert!("hours", "hnsecs")(24);
1735
1736 adjTime = daysHNSecs + hnsecs;
1737 }
1738
1739 @safe unittest
1740 {
1741 import std.range : chain;
1742
1743 foreach (second; testMinSecs)
1744 {
1745 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1746 {
1747 auto dt = cast(DateTime) st;
1748 auto expected = SysTime(DateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute, second),
1749 st.fracSecs,
1750 st.timezone);
1751 st.second = second;
1752 assert(st == expected, format("[%s] [%s]", st, expected));
1753 }
1754 }
1755
1756 auto st = testSysTimesAD[0];
1757 assertThrown!DateTimeException(st.second = -1);
1758 assertThrown!DateTimeException(st.second = 60);
1759
1760 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1761 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1762 static assert(!__traits(compiles, cst.seconds = 27));
1763 //static assert(!__traits(compiles, ist.seconds = 27));
1764 }
1765
1766
1767 /++
1768 Fractional seconds past the second (i.e. the portion of a
1769 $(LREF SysTime) which is less than a second).
1770 +/
1771 @property Duration fracSecs() @safe const nothrow
1772 {
1773 auto hnsecs = removeUnitsFromHNSecs!"days"(adjTime);
1774
1775 if (hnsecs < 0)
1776 hnsecs += convert!("hours", "hnsecs")(24);
1777
1778 return dur!"hnsecs"(removeUnitsFromHNSecs!"seconds"(hnsecs));
1779 }
1780
1781 ///
1782 @safe unittest
1783 {
1784 import core.time : msecs, usecs, hnsecs, nsecs;
1785 import std.datetime.date : DateTime;
1786
1787 auto dt = DateTime(1982, 4, 1, 20, 59, 22);
1788 assert(SysTime(dt, msecs(213)).fracSecs == msecs(213));
1789 assert(SysTime(dt, usecs(5202)).fracSecs == usecs(5202));
1790 assert(SysTime(dt, hnsecs(1234567)).fracSecs == hnsecs(1234567));
1791
1792 // SysTime and Duration both have a precision of hnsecs (100 ns),
1793 // so nsecs are going to be truncated.
1794 assert(SysTime(dt, nsecs(123456789)).fracSecs == nsecs(123456700));
1795 }
1796
1797 @safe unittest
1798 {
1799 import std.range : chain;
1800
1801 assert(SysTime(0, UTC()).fracSecs == Duration.zero);
1802 assert(SysTime(1, UTC()).fracSecs == hnsecs(1));
1803 assert(SysTime(-1, UTC()).fracSecs == hnsecs(9_999_999));
1804
1805 foreach (tz; testTZs)
1806 {
1807 foreach (year; chain(testYearsBC, testYearsAD))
1808 {
1809 foreach (md; testMonthDays)
1810 {
1811 foreach (hour; testHours)
1812 {
1813 foreach (minute; testMinSecs)
1814 {
1815 foreach (second; testMinSecs)
1816 {
1817 auto dt = DateTime(Date(year, md.month, md.day), TimeOfDay(hour, minute, second));
1818 foreach (fs; testFracSecs)
1819 assert(SysTime(dt, fs, tz).fracSecs == fs);
1820 }
1821 }
1822 }
1823 }
1824 }
1825 }
1826
1827 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1828 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1829 assert(cst.fracSecs == Duration.zero);
1830 //assert(ist.fracSecs == Duration.zero);
1831 }
1832
1833
1834 /++
1835 Fractional seconds past the second (i.e. the portion of a
1836 $(LREF SysTime) which is less than a second).
1837
1838 Params:
1839 fracSecs = The duration to set this $(LREF SysTime)'s fractional
1840 seconds to.
1841
1842 Throws:
1843 $(REF DateTimeException,std,datetime,date) if the given duration
1844 is negative or if it's greater than or equal to one second.
1845 +/
1846 @property void fracSecs(Duration fracSecs) @safe
1847 {
1848 enforce(fracSecs >= Duration.zero, new DateTimeException("A SysTime cannot have negative fractional seconds."));
1849 enforce(fracSecs < seconds(1), new DateTimeException("Fractional seconds must be less than one second."));
1850
1851 auto oldHNSecs = adjTime;
1852 auto days = splitUnitsFromHNSecs!"days"(oldHNSecs);
1853 immutable daysHNSecs = convert!("days", "hnsecs")(days);
1854 immutable negative = oldHNSecs < 0;
1855
1856 if (negative)
1857 oldHNSecs += convert!("hours", "hnsecs")(24);
1858
1859 immutable seconds = splitUnitsFromHNSecs!"seconds"(oldHNSecs);
1860 immutable secondsHNSecs = convert!("seconds", "hnsecs")(seconds);
1861 auto newHNSecs = fracSecs.total!"hnsecs" + secondsHNSecs;
1862
1863 if (negative)
1864 newHNSecs -= convert!("hours", "hnsecs")(24);
1865
1866 adjTime = daysHNSecs + newHNSecs;
1867 }
1868
1869 ///
1870 @safe unittest
1871 {
1872 import core.time : Duration, msecs, hnsecs, nsecs;
1873 import std.datetime.date : DateTime;
1874
1875 auto st = SysTime(DateTime(1982, 4, 1, 20, 59, 22));
1876 assert(st.fracSecs == Duration.zero);
1877
1878 st.fracSecs = msecs(213);
1879 assert(st.fracSecs == msecs(213));
1880
1881 st.fracSecs = hnsecs(1234567);
1882 assert(st.fracSecs == hnsecs(1234567));
1883
1884 // SysTime has a precision of hnsecs (100 ns), so nsecs are
1885 // going to be truncated.
1886 st.fracSecs = nsecs(123456789);
1887 assert(st.fracSecs == hnsecs(1234567));
1888 }
1889
1890 @safe unittest
1891 {
1892 import std.range : chain;
1893
1894 foreach (fracSec; testFracSecs)
1895 {
1896 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1897 {
1898 auto dt = cast(DateTime) st;
1899 auto expected = SysTime(dt, fracSec, st.timezone);
1900 st.fracSecs = fracSec;
1901 assert(st == expected, format("[%s] [%s]", st, expected));
1902 }
1903 }
1904
1905 auto st = testSysTimesAD[0];
1906 assertThrown!DateTimeException(st.fracSecs = hnsecs(-1));
1907 assertThrown!DateTimeException(st.fracSecs = seconds(1));
1908
1909 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1910 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1911 static assert(!__traits(compiles, cst.fracSecs = msecs(7)));
1912 //static assert(!__traits(compiles, ist.fracSecs = msecs(7)));
1913 }
1914
1915
1916 /++
1917 The total hnsecs from midnight, January 1st, 1 A.D. UTC. This is the
1918 internal representation of $(LREF SysTime).
1919 +/
1920 @property long stdTime() @safe const pure nothrow
1921 {
1922 return _stdTime;
1923 }
1924
1925 @safe unittest
1926 {
1927 assert(SysTime(0).stdTime == 0);
1928 assert(SysTime(1).stdTime == 1);
1929 assert(SysTime(-1).stdTime == -1);
1930 assert(SysTime(DateTime(1, 1, 1, 0, 0, 33), hnsecs(502), UTC()).stdTime == 330_000_502L);
1931 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 0), UTC()).stdTime == 621_355_968_000_000_000L);
1932
1933 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1934 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1935 assert(cst.stdTime > 0);
1936 //assert(ist.stdTime > 0);
1937 }
1938
1939
1940 /++
1941 The total hnsecs from midnight, January 1st, 1 A.D. UTC. This is the
1942 internal representation of $(LREF SysTime).
1943
1944 Params:
1945 stdTime = The number of hnsecs since January 1st, 1 A.D. UTC.
1946 +/
1947 @property void stdTime(long stdTime) @safe pure nothrow
1948 {
1949 _stdTime = stdTime;
1950 }
1951
1952 @safe unittest
1953 {
1954 static void test(long stdTime, in SysTime expected, size_t line = __LINE__)
1955 {
1956 auto st = SysTime(0, UTC());
1957 st.stdTime = stdTime;
1958 assert(st == expected);
1959 }
1960
1961 test(0, SysTime(Date(1, 1, 1), UTC()));
1962 test(1, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1), UTC()));
1963 test(-1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()));
1964 test(330_000_502L, SysTime(DateTime(1, 1, 1, 0, 0, 33), hnsecs(502), UTC()));
1965 test(621_355_968_000_000_000L, SysTime(DateTime(1970, 1, 1, 0, 0, 0), UTC()));
1966
1967 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1968 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1969 static assert(!__traits(compiles, cst.stdTime = 27));
1970 //static assert(!__traits(compiles, ist.stdTime = 27));
1971 }
1972
1973
1974 /++
1975 The current time zone of this $(LREF SysTime). Its internal time is
1976 always kept in UTC, so there are no conversion issues between time zones
1977 due to DST. Functions which return all or part of the time - such as
1978 hours - adjust the time to this $(LREF SysTime)'s time zone before
1979 returning.
1980 +/
1981 @property immutable(TimeZone) timezone() @safe const pure nothrow
1982 {
1983 return _timezone;
1984 }
1985
1986
1987 /++
1988 The current time zone of this $(LREF SysTime). It's internal time is
1989 always kept in UTC, so there are no conversion issues between time zones
1990 due to DST. Functions which return all or part of the time - such as
1991 hours - adjust the time to this $(LREF SysTime)'s time zone before
1992 returning.
1993
1994 Params:
1995 timezone = The $(REF _TimeZone,std,datetime,_timezone) to set this
1996 $(LREF SysTime)'s time zone to.
1997 +/
1998 @property void timezone(immutable TimeZone timezone) @safe pure nothrow
1999 {
2000 if (timezone is null)
2001 _timezone = LocalTime();
2002 else
2003 _timezone = timezone;
2004 }
2005
2006
2007 /++
2008 Returns whether DST is in effect for this $(LREF SysTime).
2009 +/
2010 @property bool dstInEffect() @safe const nothrow
2011 {
2012 return _timezone.dstInEffect(_stdTime);
2013 // This function's unit testing is done in the time zone classes.
2014 }
2015
2016
2017 /++
2018 Returns what the offset from UTC is for this $(LREF SysTime).
2019 It includes the DST offset in effect at that time (if any).
2020 +/
2021 @property Duration utcOffset() @safe const nothrow
2022 {
2023 return _timezone.utcOffsetAt(_stdTime);
2024 }
2025
2026
2027 /++
2028 Returns a $(LREF SysTime) with the same std time as this one, but with
2029 $(REF LocalTime,std,datetime,timezone) as its time zone.
2030 +/
2031 SysTime toLocalTime() @safe const pure nothrow
2032 {
2033 return SysTime(_stdTime, LocalTime());
2034 }
2035
2036 @safe unittest
2037 {
2038 {
2039 auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), hnsecs(27));
2040 assert(sysTime == sysTime.toLocalTime());
2041 assert(sysTime._stdTime == sysTime.toLocalTime()._stdTime);
2042 assert(sysTime.toLocalTime().timezone is LocalTime());
2043 assert(sysTime.toLocalTime().timezone is sysTime.timezone);
2044 assert(sysTime.toLocalTime().timezone !is UTC());
2045 }
2046
2047 {
2048 auto stz = new immutable SimpleTimeZone(dur!"minutes"(-3 * 60));
2049 auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), hnsecs(27), stz);
2050 assert(sysTime == sysTime.toLocalTime());
2051 assert(sysTime._stdTime == sysTime.toLocalTime()._stdTime);
2052 assert(sysTime.toLocalTime().timezone is LocalTime());
2053 assert(sysTime.toLocalTime().timezone !is UTC());
2054 assert(sysTime.toLocalTime().timezone !is stz);
2055 }
2056 }
2057
2058
2059 /++
2060 Returns a $(LREF SysTime) with the same std time as this one, but with
2061 $(D UTC) as its time zone.
2062 +/
2063 SysTime toUTC() @safe const pure nothrow
2064 {
2065 return SysTime(_stdTime, UTC());
2066 }
2067
2068 @safe unittest
2069 {
2070 auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), hnsecs(27));
2071 assert(sysTime == sysTime.toUTC());
2072 assert(sysTime._stdTime == sysTime.toUTC()._stdTime);
2073 assert(sysTime.toUTC().timezone is UTC());
2074 assert(sysTime.toUTC().timezone !is LocalTime());
2075 assert(sysTime.toUTC().timezone !is sysTime.timezone);
2076 }
2077
2078
2079 /++
2080 Returns a $(LREF SysTime) with the same std time as this one, but with
2081 given time zone as its time zone.
2082 +/
2083 SysTime toOtherTZ(immutable TimeZone tz) @safe const pure nothrow
2084 {
2085 if (tz is null)
2086 return SysTime(_stdTime, LocalTime());
2087 else
2088 return SysTime(_stdTime, tz);
2089 }
2090
2091 @safe unittest
2092 {
2093 auto stz = new immutable SimpleTimeZone(dur!"minutes"(11 * 60));
2094 auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), hnsecs(27));
2095 assert(sysTime == sysTime.toOtherTZ(stz));
2096 assert(sysTime._stdTime == sysTime.toOtherTZ(stz)._stdTime);
2097 assert(sysTime.toOtherTZ(stz).timezone is stz);
2098 assert(sysTime.toOtherTZ(stz).timezone !is LocalTime());
2099 assert(sysTime.toOtherTZ(stz).timezone !is UTC());
2100 }
2101
2102
2103 /++
2104 Converts this $(LREF SysTime) to unix time (i.e. seconds from midnight,
2105 January 1st, 1970 in UTC).
2106
2107 The C standard does not specify the representation of time_t, so it is
2108 implementation defined. On POSIX systems, unix time is equivalent to
2109 time_t, but that's not necessarily true on other systems (e.g. it is
2110 not true for the Digital Mars C runtime). So, be careful when using unix
2111 time with C functions on non-POSIX systems.
2112
2113 By default, the return type is time_t (which is normally an alias for
2114 int on 32-bit systems and long on 64-bit systems), but if a different
2115 size is required than either int or long can be passed as a template
2116 argument to get the desired size.
2117
2118 If the return type is int, and the result can't fit in an int, then the
2119 closest value that can be held in 32 bits will be used (so $(D int.max)
2120 if it goes over and $(D int.min) if it goes under). However, no attempt
2121 is made to deal with integer overflow if the return type is long.
2122
2123 Params:
2124 T = The return type (int or long). It defaults to time_t, which is
2125 normally 32 bits on a 32-bit system and 64 bits on a 64-bit
2126 system.
2127
2128 Returns:
2129 A signed integer representing the unix time which is equivalent to
2130 this SysTime.
2131 +/
2132 T toUnixTime(T = time_t)() @safe const pure nothrow
2133 if (is(T == int) || is(T == long))
2134 {
2135 return stdTimeToUnixTime!T(_stdTime);
2136 }
2137
2138 ///
2139 @safe unittest
2140 {
2141 import core.time : hours;
2142 import std.datetime.date : DateTime;
2143 import std.datetime.timezone : SimpleTimeZone, UTC;
2144
2145 assert(SysTime(DateTime(1970, 1, 1), UTC()).toUnixTime() == 0);
2146
2147 auto pst = new immutable SimpleTimeZone(hours(-8));
2148 assert(SysTime(DateTime(1970, 1, 1), pst).toUnixTime() == 28800);
2149
2150 auto utc = SysTime(DateTime(2007, 12, 22, 8, 14, 45), UTC());
2151 assert(utc.toUnixTime() == 1_198_311_285);
2152
2153 auto ca = SysTime(DateTime(2007, 12, 22, 8, 14, 45), pst);
2154 assert(ca.toUnixTime() == 1_198_340_085);
2155 }
2156
2157 @safe unittest
2158 {
2159 import std.meta : AliasSeq;
2160 assert(SysTime(DateTime(1970, 1, 1), UTC()).toUnixTime() == 0);
2161 foreach (units; AliasSeq!("hnsecs", "usecs", "msecs"))
2162 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 0), dur!units(1), UTC()).toUnixTime() == 0);
2163 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), UTC()).toUnixTime() == 1);
2164 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toUnixTime() == 0);
2165 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), usecs(999_999), UTC()).toUnixTime() == 0);
2166 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), msecs(999), UTC()).toUnixTime() == 0);
2167 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), UTC()).toUnixTime() == -1);
2168 }
2169
2170
2171 /++
2172 Converts from unix time (i.e. seconds from midnight, January 1st, 1970
2173 in UTC) to a $(LREF SysTime).
2174
2175 The C standard does not specify the representation of time_t, so it is
2176 implementation defined. On POSIX systems, unix time is equivalent to
2177 time_t, but that's not necessarily true on other systems (e.g. it is
2178 not true for the Digital Mars C runtime). So, be careful when using unix
2179 time with C functions on non-POSIX systems.
2180
2181 Params:
2182 unixTime = Seconds from midnight, January 1st, 1970 in UTC.
2183 tz = The time zone for the SysTime that's returned.
2184 +/
2185 static SysTime fromUnixTime(long unixTime, immutable TimeZone tz = LocalTime()) @safe pure nothrow
2186 {
2187 return SysTime(unixTimeToStdTime(unixTime), tz);
2188 }
2189
2190 ///
2191 @safe unittest
2192 {
2193 import core.time : hours;
2194 import std.datetime.date : DateTime;
2195 import std.datetime.timezone : SimpleTimeZone, UTC;
2196
2197 assert(SysTime.fromUnixTime(0) ==
2198 SysTime(DateTime(1970, 1, 1), UTC()));
2199
2200 auto pst = new immutable SimpleTimeZone(hours(-8));
2201 assert(SysTime.fromUnixTime(28800) ==
2202 SysTime(DateTime(1970, 1, 1), pst));
2203
2204 auto st1 = SysTime.fromUnixTime(1_198_311_285, UTC());
2205 assert(st1 == SysTime(DateTime(2007, 12, 22, 8, 14, 45), UTC()));
2206 assert(st1.timezone is UTC());
2207 assert(st1 == SysTime(DateTime(2007, 12, 22, 0, 14, 45), pst));
2208
2209 auto st2 = SysTime.fromUnixTime(1_198_311_285, pst);
2210 assert(st2 == SysTime(DateTime(2007, 12, 22, 8, 14, 45), UTC()));
2211 assert(st2.timezone is pst);
2212 assert(st2 == SysTime(DateTime(2007, 12, 22, 0, 14, 45), pst));
2213 }
2214
2215 @safe unittest
2216 {
2217 assert(SysTime.fromUnixTime(0) == SysTime(DateTime(1970, 1, 1), UTC()));
2218 assert(SysTime.fromUnixTime(1) == SysTime(DateTime(1970, 1, 1, 0, 0, 1), UTC()));
2219 assert(SysTime.fromUnixTime(-1) == SysTime(DateTime(1969, 12, 31, 23, 59, 59), UTC()));
2220
2221 auto st = SysTime.fromUnixTime(0);
2222 auto dt = cast(DateTime) st;
2223 assert(dt <= DateTime(1970, 2, 1) && dt >= DateTime(1969, 12, 31));
2224 assert(st.timezone is LocalTime());
2225
2226 auto aest = new immutable SimpleTimeZone(hours(10));
2227 assert(SysTime.fromUnixTime(-36000) == SysTime(DateTime(1970, 1, 1), aest));
2228 }
2229
2230
2231 /++
2232 Returns a $(D timeval) which represents this $(LREF SysTime).
2233
2234 Note that like all conversions in std.datetime, this is a truncating
2235 conversion.
2236
2237 If $(D timeval.tv_sec) is int, and the result can't fit in an int, then
2238 the closest value that can be held in 32 bits will be used for
2239 $(D tv_sec). (so $(D int.max) if it goes over and $(D int.min) if it
2240 goes under).
2241 +/
2242 timeval toTimeVal() @safe const pure nothrow
2243 {
2244 immutable tv_sec = toUnixTime!(typeof(timeval.tv_sec))();
2245 immutable fracHNSecs = removeUnitsFromHNSecs!"seconds"(_stdTime - 621_355_968_000_000_000L);
2246 immutable tv_usec = cast(typeof(timeval.tv_usec))convert!("hnsecs", "usecs")(fracHNSecs);
2247 return timeval(tv_sec, tv_usec);
2248 }
2249
2250 @safe unittest
2251 {
2252 assert(SysTime(DateTime(1970, 1, 1), UTC()).toTimeVal() == timeval(0, 0));
2253 assert(SysTime(DateTime(1970, 1, 1), hnsecs(9), UTC()).toTimeVal() == timeval(0, 0));
2254 assert(SysTime(DateTime(1970, 1, 1), hnsecs(10), UTC()).toTimeVal() == timeval(0, 1));
2255 assert(SysTime(DateTime(1970, 1, 1), usecs(7), UTC()).toTimeVal() == timeval(0, 7));
2256
2257 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), UTC()).toTimeVal() == timeval(1, 0));
2258 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), hnsecs(9), UTC()).toTimeVal() == timeval(1, 0));
2259 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), hnsecs(10), UTC()).toTimeVal() == timeval(1, 1));
2260 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), usecs(7), UTC()).toTimeVal() == timeval(1, 7));
2261
2262 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toTimeVal() == timeval(0, 0));
2263 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), hnsecs(9_999_990), UTC()).toTimeVal() == timeval(0, -1));
2264
2265 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), usecs(999_999), UTC()).toTimeVal() == timeval(0, -1));
2266 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), usecs(999), UTC()).toTimeVal() == timeval(0, -999_001));
2267 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), msecs(999), UTC()).toTimeVal() == timeval(0, -1000));
2268 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), UTC()).toTimeVal() == timeval(-1, 0));
2269 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 58), usecs(17), UTC()).toTimeVal() == timeval(-1, -999_983));
2270 }
2271
2272
2273 version (StdDdoc)
2274 {
2275 private struct timespec {}
2276 /++
2277 Returns a $(D timespec) which represents this $(LREF SysTime).
2278
2279 $(BLUE This function is Posix-Only.)
2280 +/
2281 timespec toTimeSpec() @safe const pure nothrow;
2282 }
2283 else version (Posix)
2284 {
2285 timespec toTimeSpec() @safe const pure nothrow
2286 {
2287 immutable tv_sec = toUnixTime!(typeof(timespec.tv_sec))();
2288 immutable fracHNSecs = removeUnitsFromHNSecs!"seconds"(_stdTime - 621_355_968_000_000_000L);
2289 immutable tv_nsec = cast(typeof(timespec.tv_nsec))convert!("hnsecs", "nsecs")(fracHNSecs);
2290 return timespec(tv_sec, tv_nsec);
2291 }
2292
2293 @safe unittest
2294 {
2295 assert(SysTime(DateTime(1970, 1, 1), UTC()).toTimeSpec() == timespec(0, 0));
2296 assert(SysTime(DateTime(1970, 1, 1), hnsecs(9), UTC()).toTimeSpec() == timespec(0, 900));
2297 assert(SysTime(DateTime(1970, 1, 1), hnsecs(10), UTC()).toTimeSpec() == timespec(0, 1000));
2298 assert(SysTime(DateTime(1970, 1, 1), usecs(7), UTC()).toTimeSpec() == timespec(0, 7000));
2299
2300 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), UTC()).toTimeSpec() == timespec(1, 0));
2301 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), hnsecs(9), UTC()).toTimeSpec() == timespec(1, 900));
2302 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), hnsecs(10), UTC()).toTimeSpec() == timespec(1, 1000));
2303 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), usecs(7), UTC()).toTimeSpec() == timespec(1, 7000));
2304
2305 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toTimeSpec() ==
2306 timespec(0, -100));
2307 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), hnsecs(9_999_990), UTC()).toTimeSpec() ==
2308 timespec(0, -1000));
2309
2310 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), usecs(999_999), UTC()).toTimeSpec() ==
2311 timespec(0, -1_000));
2312 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), usecs(999), UTC()).toTimeSpec() ==
2313 timespec(0, -999_001_000));
2314 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), msecs(999), UTC()).toTimeSpec() ==
2315 timespec(0, -1_000_000));
2316 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), UTC()).toTimeSpec() ==
2317 timespec(-1, 0));
2318 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 58), usecs(17), UTC()).toTimeSpec() ==
2319 timespec(-1, -999_983_000));
2320 }
2321 }
2322
2323 /++
2324 Returns a $(D tm) which represents this $(LREF SysTime).
2325 +/
2326 tm toTM() @safe const nothrow
2327 {
2328 auto dateTime = cast(DateTime) this;
2329 tm timeInfo;
2330
2331 timeInfo.tm_sec = dateTime.second;
2332 timeInfo.tm_min = dateTime.minute;
2333 timeInfo.tm_hour = dateTime.hour;
2334 timeInfo.tm_mday = dateTime.day;
2335 timeInfo.tm_mon = dateTime.month - 1;
2336 timeInfo.tm_year = dateTime.year - 1900;
2337 timeInfo.tm_wday = dateTime.dayOfWeek;
2338 timeInfo.tm_yday = dateTime.dayOfYear - 1;
2339 timeInfo.tm_isdst = _timezone.dstInEffect(_stdTime);
2340
2341 version (Posix)
2342 {
2343 import std.utf : toUTFz;
2344 timeInfo.tm_gmtoff = cast(int) convert!("hnsecs", "seconds")(adjTime - _stdTime);
2345 auto zone = (timeInfo.tm_isdst ? _timezone.dstName : _timezone.stdName);
2346 timeInfo.tm_zone = zone.toUTFz!(char*)();
2347 }
2348
2349 return timeInfo;
2350 }
2351
2352 @system unittest
2353 {
2354 import std.conv : to;
2355
2356 version (Posix)
2357 {
2358 scope(exit) clearTZEnvVar();
2359 setTZEnvVar("America/Los_Angeles");
2360 }
2361
2362 {
2363 auto timeInfo = SysTime(DateTime(1970, 1, 1)).toTM();
2364
2365 assert(timeInfo.tm_sec == 0);
2366 assert(timeInfo.tm_min == 0);
2367 assert(timeInfo.tm_hour == 0);
2368 assert(timeInfo.tm_mday == 1);
2369 assert(timeInfo.tm_mon == 0);
2370 assert(timeInfo.tm_year == 70);
2371 assert(timeInfo.tm_wday == 4);
2372 assert(timeInfo.tm_yday == 0);
2373
2374 version (Posix)
2375 assert(timeInfo.tm_isdst == 0);
2376 else version (Windows)
2377 assert(timeInfo.tm_isdst == 0 || timeInfo.tm_isdst == 1);
2378
2379 version (Posix)
2380 {
2381 assert(timeInfo.tm_gmtoff == -8 * 60 * 60);
2382 assert(to!string(timeInfo.tm_zone) == "PST");
2383 }
2384 }
2385
2386 {
2387 auto timeInfo = SysTime(DateTime(2010, 7, 4, 12, 15, 7), hnsecs(15)).toTM();
2388
2389 assert(timeInfo.tm_sec == 7);
2390 assert(timeInfo.tm_min == 15);
2391 assert(timeInfo.tm_hour == 12);
2392 assert(timeInfo.tm_mday == 4);
2393 assert(timeInfo.tm_mon == 6);
2394 assert(timeInfo.tm_year == 110);
2395 assert(timeInfo.tm_wday == 0);
2396 assert(timeInfo.tm_yday == 184);
2397
2398 version (Posix)
2399 assert(timeInfo.tm_isdst == 1);
2400 else version (Windows)
2401 assert(timeInfo.tm_isdst == 0 || timeInfo.tm_isdst == 1);
2402
2403 version (Posix)
2404 {
2405 assert(timeInfo.tm_gmtoff == -7 * 60 * 60);
2406 assert(to!string(timeInfo.tm_zone) == "PDT");
2407 }
2408 }
2409 }
2410
2411
2412 /++
2413 Adds the given number of years or months to this $(LREF SysTime). A
2414 negative number will subtract.
2415
2416 Note that if day overflow is allowed, and the date with the adjusted
2417 year/month overflows the number of days in the new month, then the month
2418 will be incremented by one, and the day set to the number of days
2419 overflowed. (e.g. if the day were 31 and the new month were June, then
2420 the month would be incremented to July, and the new day would be 1). If
2421 day overflow is not allowed, then the day will be set to the last valid
2422 day in the month (e.g. June 31st would become June 30th).
2423
2424 Params:
2425 units = The type of units to add ("years" or "months").
2426 value = The number of months or years to add to this
2427 $(LREF SysTime).
2428 allowOverflow = Whether the days should be allowed to overflow,
2429 causing the month to increment.
2430 +/
2431 ref SysTime add(string units)(long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) @safe nothrow
2432 if (units == "years" || units == "months")
2433 {
2434 auto hnsecs = adjTime;
2435 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
2436
2437 if (hnsecs < 0)
2438 {
2439 hnsecs += convert!("hours", "hnsecs")(24);
2440 --days;
2441 }
2442
2443 auto date = Date(cast(int) days);
2444 date.add!units(value, allowOverflow);
2445 days = date.dayOfGregorianCal - 1;
2446
2447 if (days < 0)
2448 {
2449 hnsecs -= convert!("hours", "hnsecs")(24);
2450 ++days;
2451 }
2452
2453 immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
2454
2455 adjTime = newDaysHNSecs + hnsecs;
2456
2457 return this;
2458 }
2459
2460 @safe unittest
2461 {
2462 auto st1 = SysTime(DateTime(2010, 1, 1, 12, 30, 33));
2463 st1.add!"months"(11);
2464 assert(st1 == SysTime(DateTime(2010, 12, 1, 12, 30, 33)));
2465
2466 auto st2 = SysTime(DateTime(2010, 1, 1, 12, 30, 33));
2467 st2.add!"months"(-11);
2468 assert(st2 == SysTime(DateTime(2009, 2, 1, 12, 30, 33)));
2469
2470 auto st3 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
2471 st3.add!"years"(1);
2472 assert(st3 == SysTime(DateTime(2001, 3, 1, 12, 30, 33)));
2473
2474 auto st4 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
2475 st4.add!"years"(1, AllowDayOverflow.no);
2476 assert(st4 == SysTime(DateTime(2001, 2, 28, 12, 30, 33)));
2477 }
2478
2479 // Test add!"years"() with AllowDayOverflow.yes
2480 @safe unittest
2481 {
2482 // Test A.D.
2483 {
2484 auto sysTime = SysTime(Date(1999, 7, 6));
2485 sysTime.add!"years"(7);
2486 assert(sysTime == SysTime(Date(2006, 7, 6)));
2487 sysTime.add!"years"(-9);
2488 assert(sysTime == SysTime(Date(1997, 7, 6)));
2489 }
2490
2491 {
2492 auto sysTime = SysTime(Date(1999, 2, 28));
2493 sysTime.add!"years"(1);
2494 assert(sysTime == SysTime(Date(2000, 2, 28)));
2495 }
2496
2497 {
2498 auto sysTime = SysTime(Date(2000, 2, 29));
2499 sysTime.add!"years"(-1);
2500 assert(sysTime == SysTime(Date(1999, 3, 1)));
2501 }
2502
2503 {
2504 auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 7, 3), msecs(234));
2505 sysTime.add!"years"(7);
2506 assert(sysTime == SysTime(DateTime(2006, 7, 6, 12, 7, 3), msecs(234)));
2507 sysTime.add!"years"(-9);
2508 assert(sysTime == SysTime(DateTime(1997, 7, 6, 12, 7, 3), msecs(234)));
2509 }
2510
2511 {
2512 auto sysTime = SysTime(DateTime(1999, 2, 28, 0, 7, 2), usecs(1207));
2513 sysTime.add!"years"(1);
2514 assert(sysTime == SysTime(DateTime(2000, 2, 28, 0, 7, 2), usecs(1207)));
2515 }
2516
2517 {
2518 auto sysTime = SysTime(DateTime(2000, 2, 29, 0, 7, 2), usecs(1207));
2519 sysTime.add!"years"(-1);
2520 assert(sysTime == SysTime(DateTime(1999, 3, 1, 0, 7, 2), usecs(1207)));
2521 }
2522
2523 // Test B.C.
2524 {
2525 auto sysTime = SysTime(Date(-1999, 7, 6));
2526 sysTime.add!"years"(-7);
2527 assert(sysTime == SysTime(Date(-2006, 7, 6)));
2528 sysTime.add!"years"(9);
2529 assert(sysTime == SysTime(Date(-1997, 7, 6)));
2530 }
2531
2532 {
2533 auto sysTime = SysTime(Date(-1999, 2, 28));
2534 sysTime.add!"years"(-1);
2535 assert(sysTime == SysTime(Date(-2000, 2, 28)));
2536 }
2537
2538 {
2539 auto sysTime = SysTime(Date(-2000, 2, 29));
2540 sysTime.add!"years"(1);
2541 assert(sysTime == SysTime(Date(-1999, 3, 1)));
2542 }
2543
2544 {
2545 auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 7, 3), msecs(234));
2546 sysTime.add!"years"(-7);
2547 assert(sysTime == SysTime(DateTime(-2006, 7, 6, 12, 7, 3), msecs(234)));
2548 sysTime.add!"years"(9);
2549 assert(sysTime == SysTime(DateTime(-1997, 7, 6, 12, 7, 3), msecs(234)));
2550 }
2551
2552 {
2553 auto sysTime = SysTime(DateTime(-1999, 2, 28, 3, 3, 3), hnsecs(3));
2554 sysTime.add!"years"(-1);
2555 assert(sysTime == SysTime(DateTime(-2000, 2, 28, 3, 3, 3), hnsecs(3)));
2556 }
2557
2558 {
2559 auto sysTime = SysTime(DateTime(-2000, 2, 29, 3, 3, 3), hnsecs(3));
2560 sysTime.add!"years"(1);
2561 assert(sysTime == SysTime(DateTime(-1999, 3, 1, 3, 3, 3), hnsecs(3)));
2562 }
2563
2564 // Test Both
2565 {
2566 auto sysTime = SysTime(Date(4, 7, 6));
2567 sysTime.add!"years"(-5);
2568 assert(sysTime == SysTime(Date(-1, 7, 6)));
2569 sysTime.add!"years"(5);
2570 assert(sysTime == SysTime(Date(4, 7, 6)));
2571 }
2572
2573 {
2574 auto sysTime = SysTime(Date(-4, 7, 6));
2575 sysTime.add!"years"(5);
2576 assert(sysTime == SysTime(Date(1, 7, 6)));
2577 sysTime.add!"years"(-5);
2578 assert(sysTime == SysTime(Date(-4, 7, 6)));
2579 }
2580
2581 {
2582 auto sysTime = SysTime(Date(4, 7, 6));
2583 sysTime.add!"years"(-8);
2584 assert(sysTime == SysTime(Date(-4, 7, 6)));
2585 sysTime.add!"years"(8);
2586 assert(sysTime == SysTime(Date(4, 7, 6)));
2587 }
2588
2589 {
2590 auto sysTime = SysTime(Date(-4, 7, 6));
2591 sysTime.add!"years"(8);
2592 assert(sysTime == SysTime(Date(4, 7, 6)));
2593 sysTime.add!"years"(-8);
2594 assert(sysTime == SysTime(Date(-4, 7, 6)));
2595 }
2596
2597 {
2598 auto sysTime = SysTime(Date(-4, 2, 29));
2599 sysTime.add!"years"(5);
2600 assert(sysTime == SysTime(Date(1, 3, 1)));
2601 }
2602
2603 {
2604 auto sysTime = SysTime(Date(4, 2, 29));
2605 sysTime.add!"years"(-5);
2606 assert(sysTime == SysTime(Date(-1, 3, 1)));
2607 }
2608
2609 {
2610 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
2611 sysTime.add!"years"(-1);
2612 assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0)));
2613 sysTime.add!"years"(1);
2614 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
2615 }
2616
2617 {
2618 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
2619 sysTime.add!"years"(-1);
2620 assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
2621 sysTime.add!"years"(1);
2622 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
2623 }
2624
2625 {
2626 auto sysTime = SysTime(DateTime(0, 1, 1, 0, 0, 0));
2627 sysTime.add!"years"(1);
2628 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
2629 sysTime.add!"years"(-1);
2630 assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0)));
2631 }
2632
2633 {
2634 auto sysTime = SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999));
2635 sysTime.add!"years"(1);
2636 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
2637 sysTime.add!"years"(-1);
2638 assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
2639 }
2640
2641 {
2642 auto sysTime = SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329));
2643 sysTime.add!"years"(-5);
2644 assert(sysTime == SysTime(DateTime(-1, 7, 6, 14, 7, 1), usecs(54329)));
2645 sysTime.add!"years"(5);
2646 assert(sysTime == SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329)));
2647 }
2648
2649 {
2650 auto sysTime = SysTime(DateTime(-4, 7, 6, 14, 7, 1), usecs(54329));
2651 sysTime.add!"years"(5);
2652 assert(sysTime == SysTime(DateTime(1, 7, 6, 14, 7, 1), usecs(54329)));
2653 sysTime.add!"years"(-5);
2654 assert(sysTime == SysTime(DateTime(-4, 7, 6, 14, 7, 1), usecs(54329)));
2655 }
2656
2657 {
2658 auto sysTime = SysTime(DateTime(-4, 2, 29, 5, 5, 5), msecs(555));
2659 sysTime.add!"years"(5);
2660 assert(sysTime == SysTime(DateTime(1, 3, 1, 5, 5, 5), msecs(555)));
2661 }
2662
2663 {
2664 auto sysTime = SysTime(DateTime(4, 2, 29, 5, 5, 5), msecs(555));
2665 sysTime.add!"years"(-5);
2666 assert(sysTime == SysTime(DateTime(-1, 3, 1, 5, 5, 5), msecs(555)));
2667 }
2668
2669 {
2670 auto sysTime = SysTime(DateTime(4, 2, 29, 5, 5, 5), msecs(555));
2671 sysTime.add!"years"(-5).add!"years"(7);
2672 assert(sysTime == SysTime(DateTime(6, 3, 1, 5, 5, 5), msecs(555)));
2673 }
2674
2675 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
2676 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
2677 static assert(!__traits(compiles, cst.add!"years"(4)));
2678 //static assert(!__traits(compiles, ist.add!"years"(4)));
2679 }
2680
2681 // Test add!"years"() with AllowDayOverflow.no
2682 @safe unittest
2683 {
2684 // Test A.D.
2685 {
2686 auto sysTime = SysTime(Date(1999, 7, 6));
2687 sysTime.add!"years"(7, AllowDayOverflow.no);
2688 assert(sysTime == SysTime(Date(2006, 7, 6)));
2689 sysTime.add!"years"(-9, AllowDayOverflow.no);
2690 assert(sysTime == SysTime(Date(1997, 7, 6)));
2691 }
2692
2693 {
2694 auto sysTime = SysTime(Date(1999, 2, 28));
2695 sysTime.add!"years"(1, AllowDayOverflow.no);
2696 assert(sysTime == SysTime(Date(2000, 2, 28)));
2697 }
2698
2699 {
2700 auto sysTime = SysTime(Date(2000, 2, 29));
2701 sysTime.add!"years"(-1, AllowDayOverflow.no);
2702 assert(sysTime == SysTime(Date(1999, 2, 28)));
2703 }
2704
2705 {
2706 auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 7, 3), msecs(234));
2707 sysTime.add!"years"(7, AllowDayOverflow.no);
2708 assert(sysTime == SysTime(DateTime(2006, 7, 6, 12, 7, 3), msecs(234)));
2709 sysTime.add!"years"(-9, AllowDayOverflow.no);
2710 assert(sysTime == SysTime(DateTime(1997, 7, 6, 12, 7, 3), msecs(234)));
2711 }
2712
2713 {
2714 auto sysTime = SysTime(DateTime(1999, 2, 28, 0, 7, 2), usecs(1207));
2715 sysTime.add!"years"(1, AllowDayOverflow.no);
2716 assert(sysTime == SysTime(DateTime(2000, 2, 28, 0, 7, 2), usecs(1207)));
2717 }
2718
2719 {
2720 auto sysTime = SysTime(DateTime(2000, 2, 29, 0, 7, 2), usecs(1207));
2721 sysTime.add!"years"(-1, AllowDayOverflow.no);
2722 assert(sysTime == SysTime(DateTime(1999, 2, 28, 0, 7, 2), usecs(1207)));
2723 }
2724
2725 // Test B.C.
2726 {
2727 auto sysTime = SysTime(Date(-1999, 7, 6));
2728 sysTime.add!"years"(-7, AllowDayOverflow.no);
2729 assert(sysTime == SysTime(Date(-2006, 7, 6)));
2730 sysTime.add!"years"(9, AllowDayOverflow.no);
2731 assert(sysTime == SysTime(Date(-1997, 7, 6)));
2732 }
2733
2734 {
2735 auto sysTime = SysTime(Date(-1999, 2, 28));
2736 sysTime.add!"years"(-1, AllowDayOverflow.no);
2737 assert(sysTime == SysTime(Date(-2000, 2, 28)));
2738 }
2739
2740 {
2741 auto sysTime = SysTime(Date(-2000, 2, 29));
2742 sysTime.add!"years"(1, AllowDayOverflow.no);
2743 assert(sysTime == SysTime(Date(-1999, 2, 28)));
2744 }
2745
2746 {
2747 auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 7, 3), msecs(234));
2748 sysTime.add!"years"(-7, AllowDayOverflow.no);
2749 assert(sysTime == SysTime(DateTime(-2006, 7, 6, 12, 7, 3), msecs(234)));
2750 sysTime.add!"years"(9, AllowDayOverflow.no);
2751 assert(sysTime == SysTime(DateTime(-1997, 7, 6, 12, 7, 3), msecs(234)));
2752 }
2753
2754 {
2755 auto sysTime = SysTime(DateTime(-1999, 2, 28, 3, 3, 3), hnsecs(3));
2756 sysTime.add!"years"(-1, AllowDayOverflow.no);
2757 assert(sysTime == SysTime(DateTime(-2000, 2, 28, 3, 3, 3), hnsecs(3)));
2758 }
2759
2760 {
2761 auto sysTime = SysTime(DateTime(-2000, 2, 29, 3, 3, 3), hnsecs(3));
2762 sysTime.add!"years"(1, AllowDayOverflow.no);
2763 assert(sysTime == SysTime(DateTime(-1999, 2, 28, 3, 3, 3), hnsecs(3)));
2764 }
2765
2766 // Test Both
2767 {
2768 auto sysTime = SysTime(Date(4, 7, 6));
2769 sysTime.add!"years"(-5, AllowDayOverflow.no);
2770 assert(sysTime == SysTime(Date(-1, 7, 6)));
2771 sysTime.add!"years"(5, AllowDayOverflow.no);
2772 assert(sysTime == SysTime(Date(4, 7, 6)));
2773 }
2774
2775 {
2776 auto sysTime = SysTime(Date(-4, 7, 6));
2777 sysTime.add!"years"(5, AllowDayOverflow.no);
2778 assert(sysTime == SysTime(Date(1, 7, 6)));
2779 sysTime.add!"years"(-5, AllowDayOverflow.no);
2780 assert(sysTime == SysTime(Date(-4, 7, 6)));
2781 }
2782
2783 {
2784 auto sysTime = SysTime(Date(4, 7, 6));
2785 sysTime.add!"years"(-8, AllowDayOverflow.no);
2786 assert(sysTime == SysTime(Date(-4, 7, 6)));
2787 sysTime.add!"years"(8, AllowDayOverflow.no);
2788 assert(sysTime == SysTime(Date(4, 7, 6)));
2789 }
2790
2791 {
2792 auto sysTime = SysTime(Date(-4, 7, 6));
2793 sysTime.add!"years"(8, AllowDayOverflow.no);
2794 assert(sysTime == SysTime(Date(4, 7, 6)));
2795 sysTime.add!"years"(-8, AllowDayOverflow.no);
2796 assert(sysTime == SysTime(Date(-4, 7, 6)));
2797 }
2798
2799 {
2800 auto sysTime = SysTime(Date(-4, 2, 29));
2801 sysTime.add!"years"(5, AllowDayOverflow.no);
2802 assert(sysTime == SysTime(Date(1, 2, 28)));
2803 }
2804
2805 {
2806 auto sysTime = SysTime(Date(4, 2, 29));
2807 sysTime.add!"years"(-5, AllowDayOverflow.no);
2808 assert(sysTime == SysTime(Date(-1, 2, 28)));
2809 }
2810
2811 {
2812 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
2813 sysTime.add!"years"(-1, AllowDayOverflow.no);
2814 assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0)));
2815 sysTime.add!"years"(1, AllowDayOverflow.no);
2816 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
2817 }
2818
2819 {
2820 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
2821 sysTime.add!"years"(-1, AllowDayOverflow.no);
2822 assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
2823 sysTime.add!"years"(1, AllowDayOverflow.no);
2824 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
2825 }
2826
2827 {
2828 auto sysTime = SysTime(DateTime(0, 1, 1, 0, 0, 0));
2829 sysTime.add!"years"(1, AllowDayOverflow.no);
2830 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
2831 sysTime.add!"years"(-1, AllowDayOverflow.no);
2832 assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0)));
2833 }
2834
2835 {
2836 auto sysTime = SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999));
2837 sysTime.add!"years"(1, AllowDayOverflow.no);
2838 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
2839 sysTime.add!"years"(-1, AllowDayOverflow.no);
2840 assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
2841 }
2842
2843 {
2844 auto sysTime = SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329));
2845 sysTime.add!"years"(-5);
2846 assert(sysTime == SysTime(DateTime(-1, 7, 6, 14, 7, 1), usecs(54329)));
2847 sysTime.add!"years"(5);
2848 assert(sysTime == SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329)));
2849 }
2850
2851 {
2852 auto sysTime = SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329));
2853 sysTime.add!"years"(-5, AllowDayOverflow.no);
2854 assert(sysTime == SysTime(DateTime(-1, 7, 6, 14, 7, 1), usecs(54329)));
2855 sysTime.add!"years"(5, AllowDayOverflow.no);
2856 assert(sysTime == SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329)));
2857 }
2858
2859 {
2860 auto sysTime = SysTime(DateTime(-4, 7, 6, 14, 7, 1), usecs(54329));
2861 sysTime.add!"years"(5, AllowDayOverflow.no);
2862 assert(sysTime == SysTime(DateTime(1, 7, 6, 14, 7, 1), usecs(54329)));
2863 sysTime.add!"years"(-5, AllowDayOverflow.no);
2864 assert(sysTime == SysTime(DateTime(-4, 7, 6, 14, 7, 1), usecs(54329)));
2865 }
2866
2867 {
2868 auto sysTime = SysTime(DateTime(-4, 2, 29, 5, 5, 5), msecs(555));
2869 sysTime.add!"years"(5, AllowDayOverflow.no);
2870 assert(sysTime == SysTime(DateTime(1, 2, 28, 5, 5, 5), msecs(555)));
2871 }
2872
2873 {
2874 auto sysTime = SysTime(DateTime(4, 2, 29, 5, 5, 5), msecs(555));
2875 sysTime.add!"years"(-5, AllowDayOverflow.no);
2876 assert(sysTime == SysTime(DateTime(-1, 2, 28, 5, 5, 5), msecs(555)));
2877 }
2878
2879 {
2880 auto sysTime = SysTime(DateTime(4, 2, 29, 5, 5, 5), msecs(555));
2881 sysTime.add!"years"(-5, AllowDayOverflow.no).add!"years"(7, AllowDayOverflow.no);
2882 assert(sysTime == SysTime(DateTime(6, 2, 28, 5, 5, 5), msecs(555)));
2883 }
2884 }
2885
2886 // Test add!"months"() with AllowDayOverflow.yes
2887 @safe unittest
2888 {
2889 // Test A.D.
2890 {
2891 auto sysTime = SysTime(Date(1999, 7, 6));
2892 sysTime.add!"months"(3);
2893 assert(sysTime == SysTime(Date(1999, 10, 6)));
2894 sysTime.add!"months"(-4);
2895 assert(sysTime == SysTime(Date(1999, 6, 6)));
2896 }
2897
2898 {
2899 auto sysTime = SysTime(Date(1999, 7, 6));
2900 sysTime.add!"months"(6);
2901 assert(sysTime == SysTime(Date(2000, 1, 6)));
2902 sysTime.add!"months"(-6);
2903 assert(sysTime == SysTime(Date(1999, 7, 6)));
2904 }
2905
2906 {
2907 auto sysTime = SysTime(Date(1999, 7, 6));
2908 sysTime.add!"months"(27);
2909 assert(sysTime == SysTime(Date(2001, 10, 6)));
2910 sysTime.add!"months"(-28);
2911 assert(sysTime == SysTime(Date(1999, 6, 6)));
2912 }
2913
2914 {
2915 auto sysTime = SysTime(Date(1999, 5, 31));
2916 sysTime.add!"months"(1);
2917 assert(sysTime == SysTime(Date(1999, 7, 1)));
2918 }
2919
2920 {
2921 auto sysTime = SysTime(Date(1999, 5, 31));
2922 sysTime.add!"months"(-1);
2923 assert(sysTime == SysTime(Date(1999, 5, 1)));
2924 }
2925
2926 {
2927 auto sysTime = SysTime(Date(1999, 2, 28));
2928 sysTime.add!"months"(12);
2929 assert(sysTime == SysTime(Date(2000, 2, 28)));
2930 }
2931
2932 {
2933 auto sysTime = SysTime(Date(2000, 2, 29));
2934 sysTime.add!"months"(12);
2935 assert(sysTime == SysTime(Date(2001, 3, 1)));
2936 }
2937
2938 {
2939 auto sysTime = SysTime(Date(1999, 7, 31));
2940 sysTime.add!"months"(1);
2941 assert(sysTime == SysTime(Date(1999, 8, 31)));
2942 sysTime.add!"months"(1);
2943 assert(sysTime == SysTime(Date(1999, 10, 1)));
2944 }
2945
2946 {
2947 auto sysTime = SysTime(Date(1998, 8, 31));
2948 sysTime.add!"months"(13);
2949 assert(sysTime == SysTime(Date(1999, 10, 1)));
2950 sysTime.add!"months"(-13);
2951 assert(sysTime == SysTime(Date(1998, 9, 1)));
2952 }
2953
2954 {
2955 auto sysTime = SysTime(Date(1997, 12, 31));
2956 sysTime.add!"months"(13);
2957 assert(sysTime == SysTime(Date(1999, 1, 31)));
2958 sysTime.add!"months"(-13);
2959 assert(sysTime == SysTime(Date(1997, 12, 31)));
2960 }
2961
2962 {
2963 auto sysTime = SysTime(Date(1997, 12, 31));
2964 sysTime.add!"months"(14);
2965 assert(sysTime == SysTime(Date(1999, 3, 3)));
2966 sysTime.add!"months"(-14);
2967 assert(sysTime == SysTime(Date(1998, 1, 3)));
2968 }
2969
2970 {
2971 auto sysTime = SysTime(Date(1998, 12, 31));
2972 sysTime.add!"months"(14);
2973 assert(sysTime == SysTime(Date(2000, 3, 2)));
2974 sysTime.add!"months"(-14);
2975 assert(sysTime == SysTime(Date(1999, 1, 2)));
2976 }
2977
2978 {
2979 auto sysTime = SysTime(Date(1999, 12, 31));
2980 sysTime.add!"months"(14);
2981 assert(sysTime == SysTime(Date(2001, 3, 3)));
2982 sysTime.add!"months"(-14);
2983 assert(sysTime == SysTime(Date(2000, 1, 3)));
2984 }
2985
2986 {
2987 auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), usecs(5007));
2988 sysTime.add!"months"(3);
2989 assert(sysTime == SysTime(DateTime(1999, 10, 6, 12, 2, 7), usecs(5007)));
2990 sysTime.add!"months"(-4);
2991 assert(sysTime == SysTime(DateTime(1999, 6, 6, 12, 2, 7), usecs(5007)));
2992 }
2993
2994 {
2995 auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), hnsecs(422202));
2996 sysTime.add!"months"(14);
2997 assert(sysTime == SysTime(DateTime(2000, 3, 2, 7, 7, 7), hnsecs(422202)));
2998 sysTime.add!"months"(-14);
2999 assert(sysTime == SysTime(DateTime(1999, 1, 2, 7, 7, 7), hnsecs(422202)));
3000 }
3001
3002 {
3003 auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), hnsecs(422202));
3004 sysTime.add!"months"(14);
3005 assert(sysTime == SysTime(DateTime(2001, 3, 3, 7, 7, 7), hnsecs(422202)));
3006 sysTime.add!"months"(-14);
3007 assert(sysTime == SysTime(DateTime(2000, 1, 3, 7, 7, 7), hnsecs(422202)));
3008 }
3009
3010 // Test B.C.
3011 {
3012 auto sysTime = SysTime(Date(-1999, 7, 6));
3013 sysTime.add!"months"(3);
3014 assert(sysTime == SysTime(Date(-1999, 10, 6)));
3015 sysTime.add!"months"(-4);
3016 assert(sysTime == SysTime(Date(-1999, 6, 6)));
3017 }
3018
3019 {
3020 auto sysTime = SysTime(Date(-1999, 7, 6));
3021 sysTime.add!"months"(6);
3022 assert(sysTime == SysTime(Date(-1998, 1, 6)));
3023 sysTime.add!"months"(-6);
3024 assert(sysTime == SysTime(Date(-1999, 7, 6)));
3025 }
3026
3027 {
3028 auto sysTime = SysTime(Date(-1999, 7, 6));
3029 sysTime.add!"months"(-27);
3030 assert(sysTime == SysTime(Date(-2001, 4, 6)));
3031 sysTime.add!"months"(28);
3032 assert(sysTime == SysTime(Date(-1999, 8, 6)));
3033 }
3034
3035 {
3036 auto sysTime = SysTime(Date(-1999, 5, 31));
3037 sysTime.add!"months"(1);
3038 assert(sysTime == SysTime(Date(-1999, 7, 1)));
3039 }
3040
3041 {
3042 auto sysTime = SysTime(Date(-1999, 5, 31));
3043 sysTime.add!"months"(-1);
3044 assert(sysTime == SysTime(Date(-1999, 5, 1)));
3045 }
3046
3047 {
3048 auto sysTime = SysTime(Date(-1999, 2, 28));
3049 sysTime.add!"months"(-12);
3050 assert(sysTime == SysTime(Date(-2000, 2, 28)));
3051 }
3052
3053 {
3054 auto sysTime = SysTime(Date(-2000, 2, 29));
3055 sysTime.add!"months"(-12);
3056 assert(sysTime == SysTime(Date(-2001, 3, 1)));
3057 }
3058
3059 {
3060 auto sysTime = SysTime(Date(-1999, 7, 31));
3061 sysTime.add!"months"(1);
3062 assert(sysTime == SysTime(Date(-1999, 8, 31)));
3063 sysTime.add!"months"(1);
3064 assert(sysTime == SysTime(Date(-1999, 10, 1)));
3065 }
3066
3067 {
3068 auto sysTime = SysTime(Date(-1998, 8, 31));
3069 sysTime.add!"months"(13);
3070 assert(sysTime == SysTime(Date(-1997, 10, 1)));
3071 sysTime.add!"months"(-13);
3072 assert(sysTime == SysTime(Date(-1998, 9, 1)));
3073 }
3074
3075 {
3076 auto sysTime = SysTime(Date(-1997, 12, 31));
3077 sysTime.add!"months"(13);
3078 assert(sysTime == SysTime(Date(-1995, 1, 31)));
3079 sysTime.add!"months"(-13);
3080 assert(sysTime == SysTime(Date(-1997, 12, 31)));
3081 }
3082
3083 {
3084 auto sysTime = SysTime(Date(-1997, 12, 31));
3085 sysTime.add!"months"(14);
3086 assert(sysTime == SysTime(Date(-1995, 3, 3)));
3087 sysTime.add!"months"(-14);
3088 assert(sysTime == SysTime(Date(-1996, 1, 3)));
3089 }
3090
3091 {
3092 auto sysTime = SysTime(Date(-2002, 12, 31));
3093 sysTime.add!"months"(14);
3094 assert(sysTime == SysTime(Date(-2000, 3, 2)));
3095 sysTime.add!"months"(-14);
3096 assert(sysTime == SysTime(Date(-2001, 1, 2)));
3097 }
3098
3099 {
3100 auto sysTime = SysTime(Date(-2001, 12, 31));
3101 sysTime.add!"months"(14);
3102 assert(sysTime == SysTime(Date(-1999, 3, 3)));
3103 sysTime.add!"months"(-14);
3104 assert(sysTime == SysTime(Date(-2000, 1, 3)));
3105 }
3106
3107 {
3108 auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), usecs(5007));
3109 sysTime.add!"months"(3);
3110 assert(sysTime == SysTime(DateTime(-1999, 10, 6, 12, 2, 7), usecs(5007)));
3111 sysTime.add!"months"(-4);
3112 assert(sysTime == SysTime(DateTime(-1999, 6, 6, 12, 2, 7), usecs(5007)));
3113 }
3114
3115 {
3116 auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), hnsecs(422202));
3117 sysTime.add!"months"(14);
3118 assert(sysTime == SysTime(DateTime(-2000, 3, 2, 7, 7, 7), hnsecs(422202)));
3119 sysTime.add!"months"(-14);
3120 assert(sysTime == SysTime(DateTime(-2001, 1, 2, 7, 7, 7), hnsecs(422202)));
3121 }
3122
3123 {
3124 auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), hnsecs(422202));
3125 sysTime.add!"months"(14);
3126 assert(sysTime == SysTime(DateTime(-1999, 3, 3, 7, 7, 7), hnsecs(422202)));
3127 sysTime.add!"months"(-14);
3128 assert(sysTime == SysTime(DateTime(-2000, 1, 3, 7, 7, 7), hnsecs(422202)));
3129 }
3130
3131 // Test Both
3132 {
3133 auto sysTime = SysTime(Date(1, 1, 1));
3134 sysTime.add!"months"(-1);
3135 assert(sysTime == SysTime(Date(0, 12, 1)));
3136 sysTime.add!"months"(1);
3137 assert(sysTime == SysTime(Date(1, 1, 1)));
3138 }
3139
3140 {
3141 auto sysTime = SysTime(Date(4, 1, 1));
3142 sysTime.add!"months"(-48);
3143 assert(sysTime == SysTime(Date(0, 1, 1)));
3144 sysTime.add!"months"(48);
3145 assert(sysTime == SysTime(Date(4, 1, 1)));
3146 }
3147
3148 {
3149 auto sysTime = SysTime(Date(4, 3, 31));
3150 sysTime.add!"months"(-49);
3151 assert(sysTime == SysTime(Date(0, 3, 2)));
3152 sysTime.add!"months"(49);
3153 assert(sysTime == SysTime(Date(4, 4, 2)));
3154 }
3155
3156 {
3157 auto sysTime = SysTime(Date(4, 3, 31));
3158 sysTime.add!"months"(-85);
3159 assert(sysTime == SysTime(Date(-3, 3, 3)));
3160 sysTime.add!"months"(85);
3161 assert(sysTime == SysTime(Date(4, 4, 3)));
3162 }
3163
3164 {
3165 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
3166 sysTime.add!"months"(-1);
3167 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
3168 sysTime.add!"months"(1);
3169 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
3170 }
3171
3172 {
3173 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
3174 sysTime.add!"months"(-1);
3175 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
3176 sysTime.add!"months"(1);
3177 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3178 }
3179
3180 {
3181 auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0));
3182 sysTime.add!"months"(1);
3183 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
3184 sysTime.add!"months"(-1);
3185 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
3186 }
3187
3188 {
3189 auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999));
3190 sysTime.add!"months"(1);
3191 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3192 sysTime.add!"months"(-1);
3193 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
3194 }
3195
3196 {
3197 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17));
3198 sysTime.add!"months"(-1);
3199 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 7, 9), hnsecs(17)));
3200 sysTime.add!"months"(1);
3201 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17)));
3202 }
3203
3204 {
3205 auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), msecs(9));
3206 sysTime.add!"months"(-85);
3207 assert(sysTime == SysTime(DateTime(-3, 3, 3, 12, 11, 10), msecs(9)));
3208 sysTime.add!"months"(85);
3209 assert(sysTime == SysTime(DateTime(4, 4, 3, 12, 11, 10), msecs(9)));
3210 }
3211
3212 {
3213 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
3214 sysTime.add!"months"(85);
3215 assert(sysTime == SysTime(DateTime(4, 5, 1, 12, 11, 10), msecs(9)));
3216 sysTime.add!"months"(-85);
3217 assert(sysTime == SysTime(DateTime(-3, 4, 1, 12, 11, 10), msecs(9)));
3218 }
3219
3220 {
3221 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
3222 sysTime.add!"months"(85).add!"months"(-83);
3223 assert(sysTime == SysTime(DateTime(-3, 6, 1, 12, 11, 10), msecs(9)));
3224 }
3225
3226 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
3227 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
3228 static assert(!__traits(compiles, cst.add!"months"(4)));
3229 //static assert(!__traits(compiles, ist.add!"months"(4)));
3230 }
3231
3232 // Test add!"months"() with AllowDayOverflow.no
3233 @safe unittest
3234 {
3235 // Test A.D.
3236 {
3237 auto sysTime = SysTime(Date(1999, 7, 6));
3238 sysTime.add!"months"(3, AllowDayOverflow.no);
3239 assert(sysTime == SysTime(Date(1999, 10, 6)));
3240 sysTime.add!"months"(-4, AllowDayOverflow.no);
3241 assert(sysTime == SysTime(Date(1999, 6, 6)));
3242 }
3243
3244 {
3245 auto sysTime = SysTime(Date(1999, 7, 6));
3246 sysTime.add!"months"(6, AllowDayOverflow.no);
3247 assert(sysTime == SysTime(Date(2000, 1, 6)));
3248 sysTime.add!"months"(-6, AllowDayOverflow.no);
3249 assert(sysTime == SysTime(Date(1999, 7, 6)));
3250 }
3251
3252 {
3253 auto sysTime = SysTime(Date(1999, 7, 6));
3254 sysTime.add!"months"(27, AllowDayOverflow.no);
3255 assert(sysTime == SysTime(Date(2001, 10, 6)));
3256 sysTime.add!"months"(-28, AllowDayOverflow.no);
3257 assert(sysTime == SysTime(Date(1999, 6, 6)));
3258 }
3259
3260 {
3261 auto sysTime = SysTime(Date(1999, 5, 31));
3262 sysTime.add!"months"(1, AllowDayOverflow.no);
3263 assert(sysTime == SysTime(Date(1999, 6, 30)));
3264 }
3265
3266 {
3267 auto sysTime = SysTime(Date(1999, 5, 31));
3268 sysTime.add!"months"(-1, AllowDayOverflow.no);
3269 assert(sysTime == SysTime(Date(1999, 4, 30)));
3270 }
3271
3272 {
3273 auto sysTime = SysTime(Date(1999, 2, 28));
3274 sysTime.add!"months"(12, AllowDayOverflow.no);
3275 assert(sysTime == SysTime(Date(2000, 2, 28)));
3276 }
3277
3278 {
3279 auto sysTime = SysTime(Date(2000, 2, 29));
3280 sysTime.add!"months"(12, AllowDayOverflow.no);
3281 assert(sysTime == SysTime(Date(2001, 2, 28)));
3282 }
3283
3284 {
3285 auto sysTime = SysTime(Date(1999, 7, 31));
3286 sysTime.add!"months"(1, AllowDayOverflow.no);
3287 assert(sysTime == SysTime(Date(1999, 8, 31)));
3288 sysTime.add!"months"(1, AllowDayOverflow.no);
3289 assert(sysTime == SysTime(Date(1999, 9, 30)));
3290 }
3291
3292 {
3293 auto sysTime = SysTime(Date(1998, 8, 31));
3294 sysTime.add!"months"(13, AllowDayOverflow.no);
3295 assert(sysTime == SysTime(Date(1999, 9, 30)));
3296 sysTime.add!"months"(-13, AllowDayOverflow.no);
3297 assert(sysTime == SysTime(Date(1998, 8, 30)));
3298 }
3299
3300 {
3301 auto sysTime = SysTime(Date(1997, 12, 31));
3302 sysTime.add!"months"(13, AllowDayOverflow.no);
3303 assert(sysTime == SysTime(Date(1999, 1, 31)));
3304 sysTime.add!"months"(-13, AllowDayOverflow.no);
3305 assert(sysTime == SysTime(Date(1997, 12, 31)));
3306 }
3307
3308 {
3309 auto sysTime = SysTime(Date(1997, 12, 31));
3310 sysTime.add!"months"(14, AllowDayOverflow.no);
3311 assert(sysTime == SysTime(Date(1999, 2, 28)));
3312 sysTime.add!"months"(-14, AllowDayOverflow.no);
3313 assert(sysTime == SysTime(Date(1997, 12, 28)));
3314 }
3315
3316 {
3317 auto sysTime = SysTime(Date(1998, 12, 31));
3318 sysTime.add!"months"(14, AllowDayOverflow.no);
3319 assert(sysTime == SysTime(Date(2000, 2, 29)));
3320 sysTime.add!"months"(-14, AllowDayOverflow.no);
3321 assert(sysTime == SysTime(Date(1998, 12, 29)));
3322 }
3323
3324 {
3325 auto sysTime = SysTime(Date(1999, 12, 31));
3326 sysTime.add!"months"(14, AllowDayOverflow.no);
3327 assert(sysTime == SysTime(Date(2001, 2, 28)));
3328 sysTime.add!"months"(-14, AllowDayOverflow.no);
3329 assert(sysTime == SysTime(Date(1999, 12, 28)));
3330 }
3331
3332 {
3333 auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), usecs(5007));
3334 sysTime.add!"months"(3, AllowDayOverflow.no);
3335 assert(sysTime == SysTime(DateTime(1999, 10, 6, 12, 2, 7), usecs(5007)));
3336 sysTime.add!"months"(-4, AllowDayOverflow.no);
3337 assert(sysTime == SysTime(DateTime(1999, 6, 6, 12, 2, 7), usecs(5007)));
3338 }
3339
3340 {
3341 auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), hnsecs(422202));
3342 sysTime.add!"months"(14, AllowDayOverflow.no);
3343 assert(sysTime == SysTime(DateTime(2000, 2, 29, 7, 7, 7), hnsecs(422202)));
3344 sysTime.add!"months"(-14, AllowDayOverflow.no);
3345 assert(sysTime == SysTime(DateTime(1998, 12, 29, 7, 7, 7), hnsecs(422202)));
3346 }
3347
3348 {
3349 auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), hnsecs(422202));
3350 sysTime.add!"months"(14, AllowDayOverflow.no);
3351 assert(sysTime == SysTime(DateTime(2001, 2, 28, 7, 7, 7), hnsecs(422202)));
3352 sysTime.add!"months"(-14, AllowDayOverflow.no);
3353 assert(sysTime == SysTime(DateTime(1999, 12, 28, 7, 7, 7), hnsecs(422202)));
3354 }
3355
3356 // Test B.C.
3357 {
3358 auto sysTime = SysTime(Date(-1999, 7, 6));
3359 sysTime.add!"months"(3, AllowDayOverflow.no);
3360 assert(sysTime == SysTime(Date(-1999, 10, 6)));
3361 sysTime.add!"months"(-4, AllowDayOverflow.no);
3362 assert(sysTime == SysTime(Date(-1999, 6, 6)));
3363 }
3364
3365 {
3366 auto sysTime = SysTime(Date(-1999, 7, 6));
3367 sysTime.add!"months"(6, AllowDayOverflow.no);
3368 assert(sysTime == SysTime(Date(-1998, 1, 6)));
3369 sysTime.add!"months"(-6, AllowDayOverflow.no);
3370 assert(sysTime == SysTime(Date(-1999, 7, 6)));
3371 }
3372
3373 {
3374 auto sysTime = SysTime(Date(-1999, 7, 6));
3375 sysTime.add!"months"(-27, AllowDayOverflow.no);
3376 assert(sysTime == SysTime(Date(-2001, 4, 6)));
3377 sysTime.add!"months"(28, AllowDayOverflow.no);
3378 assert(sysTime == SysTime(Date(-1999, 8, 6)));
3379 }
3380
3381 {
3382 auto sysTime = SysTime(Date(-1999, 5, 31));
3383 sysTime.add!"months"(1, AllowDayOverflow.no);
3384 assert(sysTime == SysTime(Date(-1999, 6, 30)));
3385 }
3386
3387 {
3388 auto sysTime = SysTime(Date(-1999, 5, 31));
3389 sysTime.add!"months"(-1, AllowDayOverflow.no);
3390 assert(sysTime == SysTime(Date(-1999, 4, 30)));
3391 }
3392
3393 {
3394 auto sysTime = SysTime(Date(-1999, 2, 28));
3395 sysTime.add!"months"(-12, AllowDayOverflow.no);
3396 assert(sysTime == SysTime(Date(-2000, 2, 28)));
3397 }
3398
3399 {
3400 auto sysTime = SysTime(Date(-2000, 2, 29));
3401 sysTime.add!"months"(-12, AllowDayOverflow.no);
3402 assert(sysTime == SysTime(Date(-2001, 2, 28)));
3403 }
3404
3405 {
3406 auto sysTime = SysTime(Date(-1999, 7, 31));
3407 sysTime.add!"months"(1, AllowDayOverflow.no);
3408 assert(sysTime == SysTime(Date(-1999, 8, 31)));
3409 sysTime.add!"months"(1, AllowDayOverflow.no);
3410 assert(sysTime == SysTime(Date(-1999, 9, 30)));
3411 }
3412
3413 {
3414 auto sysTime = SysTime(Date(-1998, 8, 31));
3415 sysTime.add!"months"(13, AllowDayOverflow.no);
3416 assert(sysTime == SysTime(Date(-1997, 9, 30)));
3417 sysTime.add!"months"(-13, AllowDayOverflow.no);
3418 assert(sysTime == SysTime(Date(-1998, 8, 30)));
3419 }
3420
3421 {
3422 auto sysTime = SysTime(Date(-1997, 12, 31));
3423 sysTime.add!"months"(13, AllowDayOverflow.no);
3424 assert(sysTime == SysTime(Date(-1995, 1, 31)));
3425 sysTime.add!"months"(-13, AllowDayOverflow.no);
3426 assert(sysTime == SysTime(Date(-1997, 12, 31)));
3427 }
3428
3429 {
3430 auto sysTime = SysTime(Date(-1997, 12, 31));
3431 sysTime.add!"months"(14, AllowDayOverflow.no);
3432 assert(sysTime == SysTime(Date(-1995, 2, 28)));
3433 sysTime.add!"months"(-14, AllowDayOverflow.no);
3434 assert(sysTime == SysTime(Date(-1997, 12, 28)));
3435 }
3436
3437 {
3438 auto sysTime = SysTime(Date(-2002, 12, 31));
3439 sysTime.add!"months"(14, AllowDayOverflow.no);
3440 assert(sysTime == SysTime(Date(-2000, 2, 29)));
3441 sysTime.add!"months"(-14, AllowDayOverflow.no);
3442 assert(sysTime == SysTime(Date(-2002, 12, 29)));
3443 }
3444
3445 {
3446 auto sysTime = SysTime(Date(-2001, 12, 31));
3447 sysTime.add!"months"(14, AllowDayOverflow.no);
3448 assert(sysTime == SysTime(Date(-1999, 2, 28)));
3449 sysTime.add!"months"(-14, AllowDayOverflow.no);
3450 assert(sysTime == SysTime(Date(-2001, 12, 28)));
3451 }
3452
3453 {
3454 auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), usecs(5007));
3455 sysTime.add!"months"(3, AllowDayOverflow.no);
3456 assert(sysTime == SysTime(DateTime(-1999, 10, 6, 12, 2, 7), usecs(5007)));
3457 sysTime.add!"months"(-4, AllowDayOverflow.no);
3458 assert(sysTime == SysTime(DateTime(-1999, 6, 6, 12, 2, 7), usecs(5007)));
3459 }
3460
3461 {
3462 auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), hnsecs(422202));
3463 sysTime.add!"months"(14, AllowDayOverflow.no);
3464 assert(sysTime == SysTime(DateTime(-2000, 2, 29, 7, 7, 7), hnsecs(422202)));
3465 sysTime.add!"months"(-14, AllowDayOverflow.no);
3466 assert(sysTime == SysTime(DateTime(-2002, 12, 29, 7, 7, 7), hnsecs(422202)));
3467 }
3468
3469 {
3470 auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), hnsecs(422202));
3471 sysTime.add!"months"(14, AllowDayOverflow.no);
3472 assert(sysTime == SysTime(DateTime(-1999, 2, 28, 7, 7, 7), hnsecs(422202)));
3473 sysTime.add!"months"(-14, AllowDayOverflow.no);
3474 assert(sysTime == SysTime(DateTime(-2001, 12, 28, 7, 7, 7), hnsecs(422202)));
3475 }
3476
3477 // Test Both
3478 {
3479 auto sysTime = SysTime(Date(1, 1, 1));
3480 sysTime.add!"months"(-1, AllowDayOverflow.no);
3481 assert(sysTime == SysTime(Date(0, 12, 1)));
3482 sysTime.add!"months"(1, AllowDayOverflow.no);
3483 assert(sysTime == SysTime(Date(1, 1, 1)));
3484 }
3485
3486 {
3487 auto sysTime = SysTime(Date(4, 1, 1));
3488 sysTime.add!"months"(-48, AllowDayOverflow.no);
3489 assert(sysTime == SysTime(Date(0, 1, 1)));
3490 sysTime.add!"months"(48, AllowDayOverflow.no);
3491 assert(sysTime == SysTime(Date(4, 1, 1)));
3492 }
3493
3494 {
3495 auto sysTime = SysTime(Date(4, 3, 31));
3496 sysTime.add!"months"(-49, AllowDayOverflow.no);
3497 assert(sysTime == SysTime(Date(0, 2, 29)));
3498 sysTime.add!"months"(49, AllowDayOverflow.no);
3499 assert(sysTime == SysTime(Date(4, 3, 29)));
3500 }
3501
3502 {
3503 auto sysTime = SysTime(Date(4, 3, 31));
3504 sysTime.add!"months"(-85, AllowDayOverflow.no);
3505 assert(sysTime == SysTime(Date(-3, 2, 28)));
3506 sysTime.add!"months"(85, AllowDayOverflow.no);
3507 assert(sysTime == SysTime(Date(4, 3, 28)));
3508 }
3509
3510 {
3511 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
3512 sysTime.add!"months"(-1, AllowDayOverflow.no);
3513 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
3514 sysTime.add!"months"(1, AllowDayOverflow.no);
3515 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
3516 }
3517
3518 {
3519 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
3520 sysTime.add!"months"(-1, AllowDayOverflow.no);
3521 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
3522 sysTime.add!"months"(1, AllowDayOverflow.no);
3523 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3524 }
3525
3526 {
3527 auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0));
3528 sysTime.add!"months"(1, AllowDayOverflow.no);
3529 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
3530 sysTime.add!"months"(-1, AllowDayOverflow.no);
3531 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
3532 }
3533
3534 {
3535 auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999));
3536 sysTime.add!"months"(1, AllowDayOverflow.no);
3537 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3538 sysTime.add!"months"(-1, AllowDayOverflow.no);
3539 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
3540 }
3541
3542 {
3543 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17));
3544 sysTime.add!"months"(-1, AllowDayOverflow.no);
3545 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 7, 9), hnsecs(17)));
3546 sysTime.add!"months"(1, AllowDayOverflow.no);
3547 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17)));
3548 }
3549
3550 {
3551 auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), msecs(9));
3552 sysTime.add!"months"(-85, AllowDayOverflow.no);
3553 assert(sysTime == SysTime(DateTime(-3, 2, 28, 12, 11, 10), msecs(9)));
3554 sysTime.add!"months"(85, AllowDayOverflow.no);
3555 assert(sysTime == SysTime(DateTime(4, 3, 28, 12, 11, 10), msecs(9)));
3556 }
3557
3558 {
3559 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
3560 sysTime.add!"months"(85, AllowDayOverflow.no);
3561 assert(sysTime == SysTime(DateTime(4, 4, 30, 12, 11, 10), msecs(9)));
3562 sysTime.add!"months"(-85, AllowDayOverflow.no);
3563 assert(sysTime == SysTime(DateTime(-3, 3, 30, 12, 11, 10), msecs(9)));
3564 }
3565
3566 {
3567 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
3568 sysTime.add!"months"(85, AllowDayOverflow.no).add!"months"(-83, AllowDayOverflow.no);
3569 assert(sysTime == SysTime(DateTime(-3, 5, 30, 12, 11, 10), msecs(9)));
3570 }
3571 }
3572
3573
3574 /++
3575 Adds the given number of years or months to this $(LREF SysTime). A
3576 negative number will subtract.
3577
3578 The difference between rolling and adding is that rolling does not
3579 affect larger units. Rolling a $(LREF SysTime) 12 months
3580 gets the exact same $(LREF SysTime). However, the days can still be
3581 affected due to the differing number of days in each month.
3582
3583 Because there are no units larger than years, there is no difference
3584 between adding and rolling years.
3585
3586 Params:
3587 units = The type of units to add ("years" or "months").
3588 value = The number of months or years to add to this
3589 $(LREF SysTime).
3590 allowOverflow = Whether the days should be allowed to overflow,
3591 causing the month to increment.
3592 +/
3593 ref SysTime roll(string units)(long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) @safe nothrow
3594 if (units == "years")
3595 {
3596 return add!"years"(value, allowOverflow);
3597 }
3598
3599 ///
3600 @safe unittest
3601 {
3602 import std.datetime.date : AllowDayOverflow, DateTime;
3603
3604 auto st1 = SysTime(DateTime(2010, 1, 1, 12, 33, 33));
3605 st1.roll!"months"(1);
3606 assert(st1 == SysTime(DateTime(2010, 2, 1, 12, 33, 33)));
3607
3608 auto st2 = SysTime(DateTime(2010, 1, 1, 12, 33, 33));
3609 st2.roll!"months"(-1);
3610 assert(st2 == SysTime(DateTime(2010, 12, 1, 12, 33, 33)));
3611
3612 auto st3 = SysTime(DateTime(1999, 1, 29, 12, 33, 33));
3613 st3.roll!"months"(1);
3614 assert(st3 == SysTime(DateTime(1999, 3, 1, 12, 33, 33)));
3615
3616 auto st4 = SysTime(DateTime(1999, 1, 29, 12, 33, 33));
3617 st4.roll!"months"(1, AllowDayOverflow.no);
3618 assert(st4 == SysTime(DateTime(1999, 2, 28, 12, 33, 33)));
3619
3620 auto st5 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
3621 st5.roll!"years"(1);
3622 assert(st5 == SysTime(DateTime(2001, 3, 1, 12, 30, 33)));
3623
3624 auto st6 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
3625 st6.roll!"years"(1, AllowDayOverflow.no);
3626 assert(st6 == SysTime(DateTime(2001, 2, 28, 12, 30, 33)));
3627 }
3628
3629 @safe unittest
3630 {
3631 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
3632 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
3633 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
3634 st.roll!"years"(4);
3635 static assert(!__traits(compiles, cst.roll!"years"(4)));
3636 //static assert(!__traits(compiles, ist.roll!"years"(4)));
3637 }
3638
3639
3640 // Shares documentation with "years" overload.
3641 ref SysTime roll(string units)(long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) @safe nothrow
3642 if (units == "months")
3643 {
3644 auto hnsecs = adjTime;
3645 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
3646
3647 if (hnsecs < 0)
3648 {
3649 hnsecs += convert!("hours", "hnsecs")(24);
3650 --days;
3651 }
3652
3653 auto date = Date(cast(int) days);
3654 date.roll!"months"(value, allowOverflow);
3655 days = date.dayOfGregorianCal - 1;
3656
3657 if (days < 0)
3658 {
3659 hnsecs -= convert!("hours", "hnsecs")(24);
3660 ++days;
3661 }
3662
3663 immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
3664 adjTime = newDaysHNSecs + hnsecs;
3665 return this;
3666 }
3667
3668 // Test roll!"months"() with AllowDayOverflow.yes
3669 @safe unittest
3670 {
3671 // Test A.D.
3672 {
3673 auto sysTime = SysTime(Date(1999, 7, 6));
3674 sysTime.roll!"months"(3);
3675 assert(sysTime == SysTime(Date(1999, 10, 6)));
3676 sysTime.roll!"months"(-4);
3677 assert(sysTime == SysTime(Date(1999, 6, 6)));
3678 }
3679
3680 {
3681 auto sysTime = SysTime(Date(1999, 7, 6));
3682 sysTime.roll!"months"(6);
3683 assert(sysTime == SysTime(Date(1999, 1, 6)));
3684 sysTime.roll!"months"(-6);
3685 assert(sysTime == SysTime(Date(1999, 7, 6)));
3686 }
3687
3688 {
3689 auto sysTime = SysTime(Date(1999, 7, 6));
3690 sysTime.roll!"months"(27);
3691 assert(sysTime == SysTime(Date(1999, 10, 6)));
3692 sysTime.roll!"months"(-28);
3693 assert(sysTime == SysTime(Date(1999, 6, 6)));
3694 }
3695
3696 {
3697 auto sysTime = SysTime(Date(1999, 5, 31));
3698 sysTime.roll!"months"(1);
3699 assert(sysTime == SysTime(Date(1999, 7, 1)));
3700 }
3701
3702 {
3703 auto sysTime = SysTime(Date(1999, 5, 31));
3704 sysTime.roll!"months"(-1);
3705 assert(sysTime == SysTime(Date(1999, 5, 1)));
3706 }
3707
3708 {
3709 auto sysTime = SysTime(Date(1999, 2, 28));
3710 sysTime.roll!"months"(12);
3711 assert(sysTime == SysTime(Date(1999, 2, 28)));
3712 }
3713
3714 {
3715 auto sysTime = SysTime(Date(2000, 2, 29));
3716 sysTime.roll!"months"(12);
3717 assert(sysTime == SysTime(Date(2000, 2, 29)));
3718 }
3719
3720 {
3721 auto sysTime = SysTime(Date(1999, 7, 31));
3722 sysTime.roll!"months"(1);
3723 assert(sysTime == SysTime(Date(1999, 8, 31)));
3724 sysTime.roll!"months"(1);
3725 assert(sysTime == SysTime(Date(1999, 10, 1)));
3726 }
3727
3728 {
3729 auto sysTime = SysTime(Date(1998, 8, 31));
3730 sysTime.roll!"months"(13);
3731 assert(sysTime == SysTime(Date(1998, 10, 1)));
3732 sysTime.roll!"months"(-13);
3733 assert(sysTime == SysTime(Date(1998, 9, 1)));
3734 }
3735
3736 {
3737 auto sysTime = SysTime(Date(1997, 12, 31));
3738 sysTime.roll!"months"(13);
3739 assert(sysTime == SysTime(Date(1997, 1, 31)));
3740 sysTime.roll!"months"(-13);
3741 assert(sysTime == SysTime(Date(1997, 12, 31)));
3742 }
3743
3744 {
3745 auto sysTime = SysTime(Date(1997, 12, 31));
3746 sysTime.roll!"months"(14);
3747 assert(sysTime == SysTime(Date(1997, 3, 3)));
3748 sysTime.roll!"months"(-14);
3749 assert(sysTime == SysTime(Date(1997, 1, 3)));
3750 }
3751
3752 {
3753 auto sysTime = SysTime(Date(1998, 12, 31));
3754 sysTime.roll!"months"(14);
3755 assert(sysTime == SysTime(Date(1998, 3, 3)));
3756 sysTime.roll!"months"(-14);
3757 assert(sysTime == SysTime(Date(1998, 1, 3)));
3758 }
3759
3760 {
3761 auto sysTime = SysTime(Date(1999, 12, 31));
3762 sysTime.roll!"months"(14);
3763 assert(sysTime == SysTime(Date(1999, 3, 3)));
3764 sysTime.roll!"months"(-14);
3765 assert(sysTime == SysTime(Date(1999, 1, 3)));
3766 }
3767
3768 {
3769 auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), usecs(5007));
3770 sysTime.roll!"months"(3);
3771 assert(sysTime == SysTime(DateTime(1999, 10, 6, 12, 2, 7), usecs(5007)));
3772 sysTime.roll!"months"(-4);
3773 assert(sysTime == SysTime(DateTime(1999, 6, 6, 12, 2, 7), usecs(5007)));
3774 }
3775
3776 {
3777 auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), hnsecs(422202));
3778 sysTime.roll!"months"(14);
3779 assert(sysTime == SysTime(DateTime(1998, 3, 3, 7, 7, 7), hnsecs(422202)));
3780 sysTime.roll!"months"(-14);
3781 assert(sysTime == SysTime(DateTime(1998, 1, 3, 7, 7, 7), hnsecs(422202)));
3782 }
3783
3784 {
3785 auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), hnsecs(422202));
3786 sysTime.roll!"months"(14);
3787 assert(sysTime == SysTime(DateTime(1999, 3, 3, 7, 7, 7), hnsecs(422202)));
3788 sysTime.roll!"months"(-14);
3789 assert(sysTime == SysTime(DateTime(1999, 1, 3, 7, 7, 7), hnsecs(422202)));
3790 }
3791
3792 // Test B.C.
3793 {
3794 auto sysTime = SysTime(Date(-1999, 7, 6));
3795 sysTime.roll!"months"(3);
3796 assert(sysTime == SysTime(Date(-1999, 10, 6)));
3797 sysTime.roll!"months"(-4);
3798 assert(sysTime == SysTime(Date(-1999, 6, 6)));
3799 }
3800
3801 {
3802 auto sysTime = SysTime(Date(-1999, 7, 6));
3803 sysTime.roll!"months"(6);
3804 assert(sysTime == SysTime(Date(-1999, 1, 6)));
3805 sysTime.roll!"months"(-6);
3806 assert(sysTime == SysTime(Date(-1999, 7, 6)));
3807 }
3808
3809 {
3810 auto sysTime = SysTime(Date(-1999, 7, 6));
3811 sysTime.roll!"months"(-27);
3812 assert(sysTime == SysTime(Date(-1999, 4, 6)));
3813 sysTime.roll!"months"(28);
3814 assert(sysTime == SysTime(Date(-1999, 8, 6)));
3815 }
3816
3817 {
3818 auto sysTime = SysTime(Date(-1999, 5, 31));
3819 sysTime.roll!"months"(1);
3820 assert(sysTime == SysTime(Date(-1999, 7, 1)));
3821 }
3822
3823 {
3824 auto sysTime = SysTime(Date(-1999, 5, 31));
3825 sysTime.roll!"months"(-1);
3826 assert(sysTime == SysTime(Date(-1999, 5, 1)));
3827 }
3828
3829 {
3830 auto sysTime = SysTime(Date(-1999, 2, 28));
3831 sysTime.roll!"months"(-12);
3832 assert(sysTime == SysTime(Date(-1999, 2, 28)));
3833 }
3834
3835 {
3836 auto sysTime = SysTime(Date(-2000, 2, 29));
3837 sysTime.roll!"months"(-12);
3838 assert(sysTime == SysTime(Date(-2000, 2, 29)));
3839 }
3840
3841 {
3842 auto sysTime = SysTime(Date(-1999, 7, 31));
3843 sysTime.roll!"months"(1);
3844 assert(sysTime == SysTime(Date(-1999, 8, 31)));
3845 sysTime.roll!"months"(1);
3846 assert(sysTime == SysTime(Date(-1999, 10, 1)));
3847 }
3848
3849 {
3850 auto sysTime = SysTime(Date(-1998, 8, 31));
3851 sysTime.roll!"months"(13);
3852 assert(sysTime == SysTime(Date(-1998, 10, 1)));
3853 sysTime.roll!"months"(-13);
3854 assert(sysTime == SysTime(Date(-1998, 9, 1)));
3855 }
3856
3857 {
3858 auto sysTime = SysTime(Date(-1997, 12, 31));
3859 sysTime.roll!"months"(13);
3860 assert(sysTime == SysTime(Date(-1997, 1, 31)));
3861 sysTime.roll!"months"(-13);
3862 assert(sysTime == SysTime(Date(-1997, 12, 31)));
3863 }
3864
3865 {
3866 auto sysTime = SysTime(Date(-1997, 12, 31));
3867 sysTime.roll!"months"(14);
3868 assert(sysTime == SysTime(Date(-1997, 3, 3)));
3869 sysTime.roll!"months"(-14);
3870 assert(sysTime == SysTime(Date(-1997, 1, 3)));
3871 }
3872
3873 {
3874 auto sysTime = SysTime(Date(-2002, 12, 31));
3875 sysTime.roll!"months"(14);
3876 assert(sysTime == SysTime(Date(-2002, 3, 3)));
3877 sysTime.roll!"months"(-14);
3878 assert(sysTime == SysTime(Date(-2002, 1, 3)));
3879 }
3880
3881 {
3882 auto sysTime = SysTime(Date(-2001, 12, 31));
3883 sysTime.roll!"months"(14);
3884 assert(sysTime == SysTime(Date(-2001, 3, 3)));
3885 sysTime.roll!"months"(-14);
3886 assert(sysTime == SysTime(Date(-2001, 1, 3)));
3887 }
3888
3889 {
3890 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
3891 sysTime.roll!"months"(-1);
3892 assert(sysTime == SysTime(DateTime(1, 12, 1, 0, 0, 0)));
3893 sysTime.roll!"months"(1);
3894 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
3895 }
3896
3897 {
3898 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
3899 sysTime.roll!"months"(-1);
3900 assert(sysTime == SysTime(DateTime(1, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
3901 sysTime.roll!"months"(1);
3902 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3903 }
3904
3905 {
3906 auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0));
3907 sysTime.roll!"months"(1);
3908 assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0)));
3909 sysTime.roll!"months"(-1);
3910 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
3911 }
3912
3913 {
3914 auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999));
3915 sysTime.roll!"months"(1);
3916 assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3917 sysTime.roll!"months"(-1);
3918 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
3919 }
3920
3921 {
3922 auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), hnsecs(5007));
3923 sysTime.roll!"months"(3);
3924 assert(sysTime == SysTime(DateTime(-1999, 10, 6, 12, 2, 7), hnsecs(5007)));
3925 sysTime.roll!"months"(-4);
3926 assert(sysTime == SysTime(DateTime(-1999, 6, 6, 12, 2, 7), hnsecs(5007)));
3927 }
3928
3929 {
3930 auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), hnsecs(422202));
3931 sysTime.roll!"months"(14);
3932 assert(sysTime == SysTime(DateTime(-2002, 3, 3, 7, 7, 7), hnsecs(422202)));
3933 sysTime.roll!"months"(-14);
3934 assert(sysTime == SysTime(DateTime(-2002, 1, 3, 7, 7, 7), hnsecs(422202)));
3935 }
3936
3937 {
3938 auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), hnsecs(422202));
3939 sysTime.roll!"months"(14);
3940 assert(sysTime == SysTime(DateTime(-2001, 3, 3, 7, 7, 7), hnsecs(422202)));
3941 sysTime.roll!"months"(-14);
3942 assert(sysTime == SysTime(DateTime(-2001, 1, 3, 7, 7, 7), hnsecs(422202)));
3943 }
3944
3945 // Test Both
3946 {
3947 auto sysTime = SysTime(Date(1, 1, 1));
3948 sysTime.roll!"months"(-1);
3949 assert(sysTime == SysTime(Date(1, 12, 1)));
3950 sysTime.roll!"months"(1);
3951 assert(sysTime == SysTime(Date(1, 1, 1)));
3952 }
3953
3954 {
3955 auto sysTime = SysTime(Date(4, 1, 1));
3956 sysTime.roll!"months"(-48);
3957 assert(sysTime == SysTime(Date(4, 1, 1)));
3958 sysTime.roll!"months"(48);
3959 assert(sysTime == SysTime(Date(4, 1, 1)));
3960 }
3961
3962 {
3963 auto sysTime = SysTime(Date(4, 3, 31));
3964 sysTime.roll!"months"(-49);
3965 assert(sysTime == SysTime(Date(4, 3, 2)));
3966 sysTime.roll!"months"(49);
3967 assert(sysTime == SysTime(Date(4, 4, 2)));
3968 }
3969
3970 {
3971 auto sysTime = SysTime(Date(4, 3, 31));
3972 sysTime.roll!"months"(-85);
3973 assert(sysTime == SysTime(Date(4, 3, 2)));
3974 sysTime.roll!"months"(85);
3975 assert(sysTime == SysTime(Date(4, 4, 2)));
3976 }
3977
3978 {
3979 auto sysTime = SysTime(Date(-1, 1, 1));
3980 sysTime.roll!"months"(-1);
3981 assert(sysTime == SysTime(Date(-1, 12, 1)));
3982 sysTime.roll!"months"(1);
3983 assert(sysTime == SysTime(Date(-1, 1, 1)));
3984 }
3985
3986 {
3987 auto sysTime = SysTime(Date(-4, 1, 1));
3988 sysTime.roll!"months"(-48);
3989 assert(sysTime == SysTime(Date(-4, 1, 1)));
3990 sysTime.roll!"months"(48);
3991 assert(sysTime == SysTime(Date(-4, 1, 1)));
3992 }
3993
3994 {
3995 auto sysTime = SysTime(Date(-4, 3, 31));
3996 sysTime.roll!"months"(-49);
3997 assert(sysTime == SysTime(Date(-4, 3, 2)));
3998 sysTime.roll!"months"(49);
3999 assert(sysTime == SysTime(Date(-4, 4, 2)));
4000 }
4001
4002 {
4003 auto sysTime = SysTime(Date(-4, 3, 31));
4004 sysTime.roll!"months"(-85);
4005 assert(sysTime == SysTime(Date(-4, 3, 2)));
4006 sysTime.roll!"months"(85);
4007 assert(sysTime == SysTime(Date(-4, 4, 2)));
4008 }
4009
4010 {
4011 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17));
4012 sysTime.roll!"months"(-1);
4013 assert(sysTime == SysTime(DateTime(1, 12, 1, 0, 7, 9), hnsecs(17)));
4014 sysTime.roll!"months"(1);
4015 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17)));
4016 }
4017
4018 {
4019 auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), msecs(9));
4020 sysTime.roll!"months"(-85);
4021 assert(sysTime == SysTime(DateTime(4, 3, 2, 12, 11, 10), msecs(9)));
4022 sysTime.roll!"months"(85);
4023 assert(sysTime == SysTime(DateTime(4, 4, 2, 12, 11, 10), msecs(9)));
4024 }
4025
4026 {
4027 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
4028 sysTime.roll!"months"(85);
4029 assert(sysTime == SysTime(DateTime(-3, 5, 1, 12, 11, 10), msecs(9)));
4030 sysTime.roll!"months"(-85);
4031 assert(sysTime == SysTime(DateTime(-3, 4, 1, 12, 11, 10), msecs(9)));
4032 }
4033
4034 {
4035 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
4036 sysTime.roll!"months"(85).roll!"months"(-83);
4037 assert(sysTime == SysTime(DateTime(-3, 6, 1, 12, 11, 10), msecs(9)));
4038 }
4039
4040 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
4041 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
4042 static assert(!__traits(compiles, cst.roll!"months"(4)));
4043 //static assert(!__traits(compiles, ist.roll!"months"(4)));
4044 }
4045
4046 // Test roll!"months"() with AllowDayOverflow.no
4047 @safe unittest
4048 {
4049 // Test A.D.
4050 {
4051 auto sysTime = SysTime(Date(1999, 7, 6));
4052 sysTime.roll!"months"(3, AllowDayOverflow.no);
4053 assert(sysTime == SysTime(Date(1999, 10, 6)));
4054 sysTime.roll!"months"(-4, AllowDayOverflow.no);
4055 assert(sysTime == SysTime(Date(1999, 6, 6)));
4056 }
4057
4058 {
4059 auto sysTime = SysTime(Date(1999, 7, 6));
4060 sysTime.roll!"months"(6, AllowDayOverflow.no);
4061 assert(sysTime == SysTime(Date(1999, 1, 6)));
4062 sysTime.roll!"months"(-6, AllowDayOverflow.no);
4063 assert(sysTime == SysTime(Date(1999, 7, 6)));
4064 }
4065
4066 {
4067 auto sysTime = SysTime(Date(1999, 7, 6));
4068 sysTime.roll!"months"(27, AllowDayOverflow.no);
4069 assert(sysTime == SysTime(Date(1999, 10, 6)));
4070 sysTime.roll!"months"(-28, AllowDayOverflow.no);
4071 assert(sysTime == SysTime(Date(1999, 6, 6)));
4072 }
4073
4074 {
4075 auto sysTime = SysTime(Date(1999, 5, 31));
4076 sysTime.roll!"months"(1, AllowDayOverflow.no);
4077 assert(sysTime == SysTime(Date(1999, 6, 30)));
4078 }
4079
4080 {
4081 auto sysTime = SysTime(Date(1999, 5, 31));
4082 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4083 assert(sysTime == SysTime(Date(1999, 4, 30)));
4084 }
4085
4086 {
4087 auto sysTime = SysTime(Date(1999, 2, 28));
4088 sysTime.roll!"months"(12, AllowDayOverflow.no);
4089 assert(sysTime == SysTime(Date(1999, 2, 28)));
4090 }
4091
4092 {
4093 auto sysTime = SysTime(Date(2000, 2, 29));
4094 sysTime.roll!"months"(12, AllowDayOverflow.no);
4095 assert(sysTime == SysTime(Date(2000, 2, 29)));
4096 }
4097
4098 {
4099 auto sysTime = SysTime(Date(1999, 7, 31));
4100 sysTime.roll!"months"(1, AllowDayOverflow.no);
4101 assert(sysTime == SysTime(Date(1999, 8, 31)));
4102 sysTime.roll!"months"(1, AllowDayOverflow.no);
4103 assert(sysTime == SysTime(Date(1999, 9, 30)));
4104 }
4105
4106 {
4107 auto sysTime = SysTime(Date(1998, 8, 31));
4108 sysTime.roll!"months"(13, AllowDayOverflow.no);
4109 assert(sysTime == SysTime(Date(1998, 9, 30)));
4110 sysTime.roll!"months"(-13, AllowDayOverflow.no);
4111 assert(sysTime == SysTime(Date(1998, 8, 30)));
4112 }
4113
4114 {
4115 auto sysTime = SysTime(Date(1997, 12, 31));
4116 sysTime.roll!"months"(13, AllowDayOverflow.no);
4117 assert(sysTime == SysTime(Date(1997, 1, 31)));
4118 sysTime.roll!"months"(-13, AllowDayOverflow.no);
4119 assert(sysTime == SysTime(Date(1997, 12, 31)));
4120 }
4121
4122 {
4123 auto sysTime = SysTime(Date(1997, 12, 31));
4124 sysTime.roll!"months"(14, AllowDayOverflow.no);
4125 assert(sysTime == SysTime(Date(1997, 2, 28)));
4126 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4127 assert(sysTime == SysTime(Date(1997, 12, 28)));
4128 }
4129
4130 {
4131 auto sysTime = SysTime(Date(1998, 12, 31));
4132 sysTime.roll!"months"(14, AllowDayOverflow.no);
4133 assert(sysTime == SysTime(Date(1998, 2, 28)));
4134 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4135 assert(sysTime == SysTime(Date(1998, 12, 28)));
4136 }
4137
4138 {
4139 auto sysTime = SysTime(Date(1999, 12, 31));
4140 sysTime.roll!"months"(14, AllowDayOverflow.no);
4141 assert(sysTime == SysTime(Date(1999, 2, 28)));
4142 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4143 assert(sysTime == SysTime(Date(1999, 12, 28)));
4144 }
4145
4146 {
4147 auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), usecs(5007));
4148 sysTime.roll!"months"(3, AllowDayOverflow.no);
4149 assert(sysTime == SysTime(DateTime(1999, 10, 6, 12, 2, 7), usecs(5007)));
4150 sysTime.roll!"months"(-4, AllowDayOverflow.no);
4151 assert(sysTime == SysTime(DateTime(1999, 6, 6, 12, 2, 7), usecs(5007)));
4152 }
4153
4154 {
4155 auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), hnsecs(422202));
4156 sysTime.roll!"months"(14, AllowDayOverflow.no);
4157 assert(sysTime == SysTime(DateTime(1998, 2, 28, 7, 7, 7), hnsecs(422202)));
4158 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4159 assert(sysTime == SysTime(DateTime(1998, 12, 28, 7, 7, 7), hnsecs(422202)));
4160 }
4161
4162 {
4163 auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), hnsecs(422202));
4164 sysTime.roll!"months"(14, AllowDayOverflow.no);
4165 assert(sysTime == SysTime(DateTime(1999, 2, 28, 7, 7, 7), hnsecs(422202)));
4166 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4167 assert(sysTime == SysTime(DateTime(1999, 12, 28, 7, 7, 7), hnsecs(422202)));
4168 }
4169
4170 // Test B.C.
4171 {
4172 auto sysTime = SysTime(Date(-1999, 7, 6));
4173 sysTime.roll!"months"(3, AllowDayOverflow.no);
4174 assert(sysTime == SysTime(Date(-1999, 10, 6)));
4175 sysTime.roll!"months"(-4, AllowDayOverflow.no);
4176 assert(sysTime == SysTime(Date(-1999, 6, 6)));
4177 }
4178
4179 {
4180 auto sysTime = SysTime(Date(-1999, 7, 6));
4181 sysTime.roll!"months"(6, AllowDayOverflow.no);
4182 assert(sysTime == SysTime(Date(-1999, 1, 6)));
4183 sysTime.roll!"months"(-6, AllowDayOverflow.no);
4184 assert(sysTime == SysTime(Date(-1999, 7, 6)));
4185 }
4186
4187 {
4188 auto sysTime = SysTime(Date(-1999, 7, 6));
4189 sysTime.roll!"months"(-27, AllowDayOverflow.no);
4190 assert(sysTime == SysTime(Date(-1999, 4, 6)));
4191 sysTime.roll!"months"(28, AllowDayOverflow.no);
4192 assert(sysTime == SysTime(Date(-1999, 8, 6)));
4193 }
4194
4195 {
4196 auto sysTime = SysTime(Date(-1999, 5, 31));
4197 sysTime.roll!"months"(1, AllowDayOverflow.no);
4198 assert(sysTime == SysTime(Date(-1999, 6, 30)));
4199 }
4200
4201 {
4202 auto sysTime = SysTime(Date(-1999, 5, 31));
4203 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4204 assert(sysTime == SysTime(Date(-1999, 4, 30)));
4205 }
4206
4207 {
4208 auto sysTime = SysTime(Date(-1999, 2, 28));
4209 sysTime.roll!"months"(-12, AllowDayOverflow.no);
4210 assert(sysTime == SysTime(Date(-1999, 2, 28)));
4211 }
4212
4213 {
4214 auto sysTime = SysTime(Date(-2000, 2, 29));
4215 sysTime.roll!"months"(-12, AllowDayOverflow.no);
4216 assert(sysTime == SysTime(Date(-2000, 2, 29)));
4217 }
4218
4219 {
4220 auto sysTime = SysTime(Date(-1999, 7, 31));
4221 sysTime.roll!"months"(1, AllowDayOverflow.no);
4222 assert(sysTime == SysTime(Date(-1999, 8, 31)));
4223 sysTime.roll!"months"(1, AllowDayOverflow.no);
4224 assert(sysTime == SysTime(Date(-1999, 9, 30)));
4225 }
4226
4227 {
4228 auto sysTime = SysTime(Date(-1998, 8, 31));
4229 sysTime.roll!"months"(13, AllowDayOverflow.no);
4230 assert(sysTime == SysTime(Date(-1998, 9, 30)));
4231 sysTime.roll!"months"(-13, AllowDayOverflow.no);
4232 assert(sysTime == SysTime(Date(-1998, 8, 30)));
4233 }
4234
4235 {
4236 auto sysTime = SysTime(Date(-1997, 12, 31));
4237 sysTime.roll!"months"(13, AllowDayOverflow.no);
4238 assert(sysTime == SysTime(Date(-1997, 1, 31)));
4239 sysTime.roll!"months"(-13, AllowDayOverflow.no);
4240 assert(sysTime == SysTime(Date(-1997, 12, 31)));
4241 }
4242
4243 {
4244 auto sysTime = SysTime(Date(-1997, 12, 31));
4245 sysTime.roll!"months"(14, AllowDayOverflow.no);
4246 assert(sysTime == SysTime(Date(-1997, 2, 28)));
4247 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4248 assert(sysTime == SysTime(Date(-1997, 12, 28)));
4249 }
4250
4251 {
4252 auto sysTime = SysTime(Date(-2002, 12, 31));
4253 sysTime.roll!"months"(14, AllowDayOverflow.no);
4254 assert(sysTime == SysTime(Date(-2002, 2, 28)));
4255 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4256 assert(sysTime == SysTime(Date(-2002, 12, 28)));
4257 }
4258
4259 {
4260 auto sysTime = SysTime(Date(-2001, 12, 31));
4261 sysTime.roll!"months"(14, AllowDayOverflow.no);
4262 assert(sysTime == SysTime(Date(-2001, 2, 28)));
4263 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4264 assert(sysTime == SysTime(Date(-2001, 12, 28)));
4265 }
4266
4267 {
4268 auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), usecs(5007));
4269 sysTime.roll!"months"(3, AllowDayOverflow.no);
4270 assert(sysTime == SysTime(DateTime(-1999, 10, 6, 12, 2, 7), usecs(5007)));
4271 sysTime.roll!"months"(-4, AllowDayOverflow.no);
4272 assert(sysTime == SysTime(DateTime(-1999, 6, 6, 12, 2, 7), usecs(5007)));
4273 }
4274
4275 {
4276 auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), hnsecs(422202));
4277 sysTime.roll!"months"(14, AllowDayOverflow.no);
4278 assert(sysTime == SysTime(DateTime(-2002, 2, 28, 7, 7, 7), hnsecs(422202)));
4279 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4280 assert(sysTime == SysTime(DateTime(-2002, 12, 28, 7, 7, 7), hnsecs(422202)));
4281 }
4282
4283 {
4284 auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), hnsecs(422202));
4285 sysTime.roll!"months"(14, AllowDayOverflow.no);
4286 assert(sysTime == SysTime(DateTime(-2001, 2, 28, 7, 7, 7), hnsecs(422202)));
4287 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4288 assert(sysTime == SysTime(DateTime(-2001, 12, 28, 7, 7, 7), hnsecs(422202)));
4289 }
4290
4291 // Test Both
4292 {
4293 auto sysTime = SysTime(Date(1, 1, 1));
4294 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4295 assert(sysTime == SysTime(Date(1, 12, 1)));
4296 sysTime.roll!"months"(1, AllowDayOverflow.no);
4297 assert(sysTime == SysTime(Date(1, 1, 1)));
4298 }
4299
4300 {
4301 auto sysTime = SysTime(Date(4, 1, 1));
4302 sysTime.roll!"months"(-48, AllowDayOverflow.no);
4303 assert(sysTime == SysTime(Date(4, 1, 1)));
4304 sysTime.roll!"months"(48, AllowDayOverflow.no);
4305 assert(sysTime == SysTime(Date(4, 1, 1)));
4306 }
4307
4308 {
4309 auto sysTime = SysTime(Date(4, 3, 31));
4310 sysTime.roll!"months"(-49, AllowDayOverflow.no);
4311 assert(sysTime == SysTime(Date(4, 2, 29)));
4312 sysTime.roll!"months"(49, AllowDayOverflow.no);
4313 assert(sysTime == SysTime(Date(4, 3, 29)));
4314 }
4315
4316 {
4317 auto sysTime = SysTime(Date(4, 3, 31));
4318 sysTime.roll!"months"(-85, AllowDayOverflow.no);
4319 assert(sysTime == SysTime(Date(4, 2, 29)));
4320 sysTime.roll!"months"(85, AllowDayOverflow.no);
4321 assert(sysTime == SysTime(Date(4, 3, 29)));
4322 }
4323
4324 {
4325 auto sysTime = SysTime(Date(-1, 1, 1));
4326 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4327 assert(sysTime == SysTime(Date(-1, 12, 1)));
4328 sysTime.roll!"months"(1, AllowDayOverflow.no);
4329 assert(sysTime == SysTime(Date(-1, 1, 1)));
4330 }
4331
4332 {
4333 auto sysTime = SysTime(Date(-4, 1, 1));
4334 sysTime.roll!"months"(-48, AllowDayOverflow.no);
4335 assert(sysTime == SysTime(Date(-4, 1, 1)));
4336 sysTime.roll!"months"(48, AllowDayOverflow.no);
4337 assert(sysTime == SysTime(Date(-4, 1, 1)));
4338 }
4339
4340 {
4341 auto sysTime = SysTime(Date(-4, 3, 31));
4342 sysTime.roll!"months"(-49, AllowDayOverflow.no);
4343 assert(sysTime == SysTime(Date(-4, 2, 29)));
4344 sysTime.roll!"months"(49, AllowDayOverflow.no);
4345 assert(sysTime == SysTime(Date(-4, 3, 29)));
4346 }
4347
4348 {
4349 auto sysTime = SysTime(Date(-4, 3, 31));
4350 sysTime.roll!"months"(-85, AllowDayOverflow.no);
4351 assert(sysTime == SysTime(Date(-4, 2, 29)));
4352 sysTime.roll!"months"(85, AllowDayOverflow.no);
4353 assert(sysTime == SysTime(Date(-4, 3, 29)));
4354 }
4355
4356 {
4357 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
4358 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4359 assert(sysTime == SysTime(DateTime(1, 12, 1, 0, 0, 0)));
4360 sysTime.roll!"months"(1, AllowDayOverflow.no);
4361 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
4362 }
4363
4364 {
4365 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
4366 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4367 assert(sysTime == SysTime(DateTime(1, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
4368 sysTime.roll!"months"(1, AllowDayOverflow.no);
4369 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
4370 }
4371
4372 {
4373 auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0));
4374 sysTime.roll!"months"(1, AllowDayOverflow.no);
4375 assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0)));
4376 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4377 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
4378 }
4379
4380 {
4381 auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999));
4382 sysTime.roll!"months"(1, AllowDayOverflow.no);
4383 assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
4384 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4385 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
4386 }
4387
4388 {
4389 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17));
4390 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4391 assert(sysTime == SysTime(DateTime(1, 12, 1, 0, 7, 9), hnsecs(17)));
4392 sysTime.roll!"months"(1, AllowDayOverflow.no);
4393 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17)));
4394 }
4395
4396 {
4397 auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), msecs(9));
4398 sysTime.roll!"months"(-85, AllowDayOverflow.no);
4399 assert(sysTime == SysTime(DateTime(4, 2, 29, 12, 11, 10), msecs(9)));
4400 sysTime.roll!"months"(85, AllowDayOverflow.no);
4401 assert(sysTime == SysTime(DateTime(4, 3, 29, 12, 11, 10), msecs(9)));
4402 }
4403
4404 {
4405 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
4406 sysTime.roll!"months"(85, AllowDayOverflow.no);
4407 assert(sysTime == SysTime(DateTime(-3, 4, 30, 12, 11, 10), msecs(9)));
4408 sysTime.roll!"months"(-85, AllowDayOverflow.no);
4409 assert(sysTime == SysTime(DateTime(-3, 3, 30, 12, 11, 10), msecs(9)));
4410 }
4411
4412 {
4413 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
4414 sysTime.roll!"months"(85, AllowDayOverflow.no).roll!"months"(-83, AllowDayOverflow.no);
4415 assert(sysTime == SysTime(DateTime(-3, 5, 30, 12, 11, 10), msecs(9)));
4416 }
4417 }
4418
4419
4420 /++
4421 Adds the given number of units to this $(LREF SysTime). A negative number
4422 will subtract.
4423
4424 The difference between rolling and adding is that rolling does not
4425 affect larger units. For instance, rolling a $(LREF SysTime) one
4426 year's worth of days gets the exact same $(LREF SysTime).
4427
4428 Accepted units are $(D "days"), $(D "minutes"), $(D "hours"),
4429 $(D "minutes"), $(D "seconds"), $(D "msecs"), $(D "usecs"), and
4430 $(D "hnsecs").
4431
4432 Note that when rolling msecs, usecs or hnsecs, they all add up to a
4433 second. So, for example, rolling 1000 msecs is exactly the same as
4434 rolling 100,000 usecs.
4435
4436 Params:
4437 units = The units to add.
4438 value = The number of $(D_PARAM units) to add to this
4439 $(LREF SysTime).
4440 +/
4441 ref SysTime roll(string units)(long value) @safe nothrow
4442 if (units == "days")
4443 {
4444 auto hnsecs = adjTime;
4445 auto gdays = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
4446
4447 if (hnsecs < 0)
4448 {
4449 hnsecs += convert!("hours", "hnsecs")(24);
4450 --gdays;
4451 }
4452
4453 auto date = Date(cast(int) gdays);
4454 date.roll!"days"(value);
4455 gdays = date.dayOfGregorianCal - 1;
4456
4457 if (gdays < 0)
4458 {
4459 hnsecs -= convert!("hours", "hnsecs")(24);
4460 ++gdays;
4461 }
4462
4463 immutable newDaysHNSecs = convert!("days", "hnsecs")(gdays);
4464 adjTime = newDaysHNSecs + hnsecs;
4465 return this;
4466 }
4467
4468 ///
4469 @safe unittest
4470 {
4471 import core.time : msecs, hnsecs;
4472 import std.datetime.date : DateTime;
4473
4474 auto st1 = SysTime(DateTime(2010, 1, 1, 11, 23, 12));
4475 st1.roll!"days"(1);
4476 assert(st1 == SysTime(DateTime(2010, 1, 2, 11, 23, 12)));
4477 st1.roll!"days"(365);
4478 assert(st1 == SysTime(DateTime(2010, 1, 26, 11, 23, 12)));
4479 st1.roll!"days"(-32);
4480 assert(st1 == SysTime(DateTime(2010, 1, 25, 11, 23, 12)));
4481
4482 auto st2 = SysTime(DateTime(2010, 7, 4, 12, 0, 0));
4483 st2.roll!"hours"(1);
4484 assert(st2 == SysTime(DateTime(2010, 7, 4, 13, 0, 0)));
4485
4486 auto st3 = SysTime(DateTime(2010, 2, 12, 12, 0, 0));
4487 st3.roll!"hours"(-1);
4488 assert(st3 == SysTime(DateTime(2010, 2, 12, 11, 0, 0)));
4489
4490 auto st4 = SysTime(DateTime(2009, 12, 31, 0, 0, 0));
4491 st4.roll!"minutes"(1);
4492 assert(st4 == SysTime(DateTime(2009, 12, 31, 0, 1, 0)));
4493
4494 auto st5 = SysTime(DateTime(2010, 1, 1, 0, 0, 0));
4495 st5.roll!"minutes"(-1);
4496 assert(st5 == SysTime(DateTime(2010, 1, 1, 0, 59, 0)));
4497
4498 auto st6 = SysTime(DateTime(2009, 12, 31, 0, 0, 0));
4499 st6.roll!"seconds"(1);
4500 assert(st6 == SysTime(DateTime(2009, 12, 31, 0, 0, 1)));
4501
4502 auto st7 = SysTime(DateTime(2010, 1, 1, 0, 0, 0));
4503 st7.roll!"seconds"(-1);
4504 assert(st7 == SysTime(DateTime(2010, 1, 1, 0, 0, 59)));
4505
4506 auto dt = DateTime(2010, 1, 1, 0, 0, 0);
4507 auto st8 = SysTime(dt);
4508 st8.roll!"msecs"(1);
4509 assert(st8 == SysTime(dt, msecs(1)));
4510
4511 auto st9 = SysTime(dt);
4512 st9.roll!"msecs"(-1);
4513 assert(st9 == SysTime(dt, msecs(999)));
4514
4515 auto st10 = SysTime(dt);
4516 st10.roll!"hnsecs"(1);
4517 assert(st10 == SysTime(dt, hnsecs(1)));
4518
4519 auto st11 = SysTime(dt);
4520 st11.roll!"hnsecs"(-1);
4521 assert(st11 == SysTime(dt, hnsecs(9_999_999)));
4522 }
4523
4524 @safe unittest
4525 {
4526 // Test A.D.
4527 {
4528 auto sysTime = SysTime(Date(1999, 2, 28));
4529 sysTime.roll!"days"(1);
4530 assert(sysTime == SysTime(Date(1999, 2, 1)));
4531 sysTime.roll!"days"(-1);
4532 assert(sysTime == SysTime(Date(1999, 2, 28)));
4533 }
4534
4535 {
4536 auto sysTime = SysTime(Date(2000, 2, 28));
4537 sysTime.roll!"days"(1);
4538 assert(sysTime == SysTime(Date(2000, 2, 29)));
4539 sysTime.roll!"days"(1);
4540 assert(sysTime == SysTime(Date(2000, 2, 1)));
4541 sysTime.roll!"days"(-1);
4542 assert(sysTime == SysTime(Date(2000, 2, 29)));
4543 }
4544
4545 {
4546 auto sysTime = SysTime(Date(1999, 6, 30));
4547 sysTime.roll!"days"(1);
4548 assert(sysTime == SysTime(Date(1999, 6, 1)));
4549 sysTime.roll!"days"(-1);
4550 assert(sysTime == SysTime(Date(1999, 6, 30)));
4551 }
4552
4553 {
4554 auto sysTime = SysTime(Date(1999, 7, 31));
4555 sysTime.roll!"days"(1);
4556 assert(sysTime == SysTime(Date(1999, 7, 1)));
4557 sysTime.roll!"days"(-1);
4558 assert(sysTime == SysTime(Date(1999, 7, 31)));
4559 }
4560
4561 {
4562 auto sysTime = SysTime(Date(1999, 1, 1));
4563 sysTime.roll!"days"(-1);
4564 assert(sysTime == SysTime(Date(1999, 1, 31)));
4565 sysTime.roll!"days"(1);
4566 assert(sysTime == SysTime(Date(1999, 1, 1)));
4567 }
4568
4569 {
4570 auto sysTime = SysTime(Date(1999, 7, 6));
4571 sysTime.roll!"days"(9);
4572 assert(sysTime == SysTime(Date(1999, 7, 15)));
4573 sysTime.roll!"days"(-11);
4574 assert(sysTime == SysTime(Date(1999, 7, 4)));
4575 sysTime.roll!"days"(30);
4576 assert(sysTime == SysTime(Date(1999, 7, 3)));
4577 sysTime.roll!"days"(-3);
4578 assert(sysTime == SysTime(Date(1999, 7, 31)));
4579 }
4580
4581 {
4582 auto sysTime = SysTime(Date(1999, 7, 6));
4583 sysTime.roll!"days"(365);
4584 assert(sysTime == SysTime(Date(1999, 7, 30)));
4585 sysTime.roll!"days"(-365);
4586 assert(sysTime == SysTime(Date(1999, 7, 6)));
4587 sysTime.roll!"days"(366);
4588 assert(sysTime == SysTime(Date(1999, 7, 31)));
4589 sysTime.roll!"days"(730);
4590 assert(sysTime == SysTime(Date(1999, 7, 17)));
4591 sysTime.roll!"days"(-1096);
4592 assert(sysTime == SysTime(Date(1999, 7, 6)));
4593 }
4594
4595 {
4596 auto sysTime = SysTime(Date(1999, 2, 6));
4597 sysTime.roll!"days"(365);
4598 assert(sysTime == SysTime(Date(1999, 2, 7)));
4599 sysTime.roll!"days"(-365);
4600 assert(sysTime == SysTime(Date(1999, 2, 6)));
4601 sysTime.roll!"days"(366);
4602 assert(sysTime == SysTime(Date(1999, 2, 8)));
4603 sysTime.roll!"days"(730);
4604 assert(sysTime == SysTime(Date(1999, 2, 10)));
4605 sysTime.roll!"days"(-1096);
4606 assert(sysTime == SysTime(Date(1999, 2, 6)));
4607 }
4608
4609 {
4610 auto sysTime = SysTime(DateTime(1999, 2, 28, 7, 9, 2), usecs(234578));
4611 sysTime.roll!"days"(1);
4612 assert(sysTime == SysTime(DateTime(1999, 2, 1, 7, 9, 2), usecs(234578)));
4613 sysTime.roll!"days"(-1);
4614 assert(sysTime == SysTime(DateTime(1999, 2, 28, 7, 9, 2), usecs(234578)));
4615 }
4616
4617 {
4618 auto sysTime = SysTime(DateTime(1999, 7, 6, 7, 9, 2), usecs(234578));
4619 sysTime.roll!"days"(9);
4620 assert(sysTime == SysTime(DateTime(1999, 7, 15, 7, 9, 2), usecs(234578)));
4621 sysTime.roll!"days"(-11);
4622 assert(sysTime == SysTime(DateTime(1999, 7, 4, 7, 9, 2), usecs(234578)));
4623 sysTime.roll!"days"(30);
4624 assert(sysTime == SysTime(DateTime(1999, 7, 3, 7, 9, 2), usecs(234578)));
4625 sysTime.roll!"days"(-3);
4626 assert(sysTime == SysTime(DateTime(1999, 7, 31, 7, 9, 2), usecs(234578)));
4627 }
4628
4629 // Test B.C.
4630 {
4631 auto sysTime = SysTime(Date(-1999, 2, 28));
4632 sysTime.roll!"days"(1);
4633 assert(sysTime == SysTime(Date(-1999, 2, 1)));
4634 sysTime.roll!"days"(-1);
4635 assert(sysTime == SysTime(Date(-1999, 2, 28)));
4636 }
4637
4638 {
4639 auto sysTime = SysTime(Date(-2000, 2, 28));
4640 sysTime.roll!"days"(1);
4641 assert(sysTime == SysTime(Date(-2000, 2, 29)));
4642 sysTime.roll!"days"(1);
4643 assert(sysTime == SysTime(Date(-2000, 2, 1)));
4644 sysTime.roll!"days"(-1);
4645 assert(sysTime == SysTime(Date(-2000, 2, 29)));
4646 }
4647
4648 {
4649 auto sysTime = SysTime(Date(-1999, 6, 30));
4650 sysTime.roll!"days"(1);
4651 assert(sysTime == SysTime(Date(-1999, 6, 1)));
4652 sysTime.roll!"days"(-1);
4653 assert(sysTime == SysTime(Date(-1999, 6, 30)));
4654 }
4655
4656 {
4657 auto sysTime = SysTime(Date(-1999, 7, 31));
4658 sysTime.roll!"days"(1);
4659 assert(sysTime == SysTime(Date(-1999, 7, 1)));
4660 sysTime.roll!"days"(-1);
4661 assert(sysTime == SysTime(Date(-1999, 7, 31)));
4662 }
4663
4664 {
4665 auto sysTime = SysTime(Date(-1999, 1, 1));
4666 sysTime.roll!"days"(-1);
4667 assert(sysTime == SysTime(Date(-1999, 1, 31)));
4668 sysTime.roll!"days"(1);
4669 assert(sysTime == SysTime(Date(-1999, 1, 1)));
4670 }
4671
4672 {
4673 auto sysTime = SysTime(Date(-1999, 7, 6));
4674 sysTime.roll!"days"(9);
4675 assert(sysTime == SysTime(Date(-1999, 7, 15)));
4676 sysTime.roll!"days"(-11);
4677 assert(sysTime == SysTime(Date(-1999, 7, 4)));
4678 sysTime.roll!"days"(30);
4679 assert(sysTime == SysTime(Date(-1999, 7, 3)));
4680 sysTime.roll!"days"(-3);
4681 assert(sysTime == SysTime(Date(-1999, 7, 31)));
4682 }
4683
4684 {
4685 auto sysTime = SysTime(Date(-1999, 7, 6));
4686 sysTime.roll!"days"(365);
4687 assert(sysTime == SysTime(Date(-1999, 7, 30)));
4688 sysTime.roll!"days"(-365);
4689 assert(sysTime == SysTime(Date(-1999, 7, 6)));
4690 sysTime.roll!"days"(366);
4691 assert(sysTime == SysTime(Date(-1999, 7, 31)));
4692 sysTime.roll!"days"(730);
4693 assert(sysTime == SysTime(Date(-1999, 7, 17)));
4694 sysTime.roll!"days"(-1096);
4695 assert(sysTime == SysTime(Date(-1999, 7, 6)));
4696 }
4697
4698 {
4699 auto sysTime = SysTime(DateTime(-1999, 2, 28, 7, 9, 2), usecs(234578));
4700 sysTime.roll!"days"(1);
4701 assert(sysTime == SysTime(DateTime(-1999, 2, 1, 7, 9, 2), usecs(234578)));
4702 sysTime.roll!"days"(-1);
4703 assert(sysTime == SysTime(DateTime(-1999, 2, 28, 7, 9, 2), usecs(234578)));
4704 }
4705
4706 {
4707 auto sysTime = SysTime(DateTime(-1999, 7, 6, 7, 9, 2), usecs(234578));
4708 sysTime.roll!"days"(9);
4709 assert(sysTime == SysTime(DateTime(-1999, 7, 15, 7, 9, 2), usecs(234578)));
4710 sysTime.roll!"days"(-11);
4711 assert(sysTime == SysTime(DateTime(-1999, 7, 4, 7, 9, 2), usecs(234578)));
4712 sysTime.roll!"days"(30);
4713 assert(sysTime == SysTime(DateTime(-1999, 7, 3, 7, 9, 2), usecs(234578)));
4714 sysTime.roll!"days"(-3);
4715 }
4716
4717 // Test Both
4718 {
4719 auto sysTime = SysTime(Date(1, 7, 6));
4720 sysTime.roll!"days"(-365);
4721 assert(sysTime == SysTime(Date(1, 7, 13)));
4722 sysTime.roll!"days"(365);
4723 assert(sysTime == SysTime(Date(1, 7, 6)));
4724 sysTime.roll!"days"(-731);
4725 assert(sysTime == SysTime(Date(1, 7, 19)));
4726 sysTime.roll!"days"(730);
4727 assert(sysTime == SysTime(Date(1, 7, 5)));
4728 }
4729
4730 {
4731 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
4732 sysTime.roll!"days"(-1);
4733 assert(sysTime == SysTime(DateTime(1, 1, 31, 0, 0, 0)));
4734 sysTime.roll!"days"(1);
4735 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
4736 }
4737
4738 {
4739 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
4740 sysTime.roll!"days"(-1);
4741 assert(sysTime == SysTime(DateTime(1, 1, 31, 23, 59, 59), hnsecs(9_999_999)));
4742 sysTime.roll!"days"(1);
4743 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
4744 }
4745
4746 {
4747 auto sysTime = SysTime(DateTime(0, 12, 31, 0, 0, 0));
4748 sysTime.roll!"days"(1);
4749 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
4750 sysTime.roll!"days"(-1);
4751 assert(sysTime == SysTime(DateTime(0, 12, 31, 0, 0, 0)));
4752 }
4753
4754 {
4755 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
4756 sysTime.roll!"days"(1);
4757 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
4758 sysTime.roll!"days"(-1);
4759 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
4760 }
4761
4762 {
4763 auto sysTime = SysTime(DateTime(1, 7, 6, 13, 13, 9), msecs(22));
4764 sysTime.roll!"days"(-365);
4765 assert(sysTime == SysTime(DateTime(1, 7, 13, 13, 13, 9), msecs(22)));
4766 sysTime.roll!"days"(365);
4767 assert(sysTime == SysTime(DateTime(1, 7, 6, 13, 13, 9), msecs(22)));
4768 sysTime.roll!"days"(-731);
4769 assert(sysTime == SysTime(DateTime(1, 7, 19, 13, 13, 9), msecs(22)));
4770 sysTime.roll!"days"(730);
4771 assert(sysTime == SysTime(DateTime(1, 7, 5, 13, 13, 9), msecs(22)));
4772 }
4773
4774 {
4775 auto sysTime = SysTime(DateTime(0, 7, 6, 13, 13, 9), msecs(22));
4776 sysTime.roll!"days"(-365);
4777 assert(sysTime == SysTime(DateTime(0, 7, 13, 13, 13, 9), msecs(22)));
4778 sysTime.roll!"days"(365);
4779 assert(sysTime == SysTime(DateTime(0, 7, 6, 13, 13, 9), msecs(22)));
4780 sysTime.roll!"days"(-731);
4781 assert(sysTime == SysTime(DateTime(0, 7, 19, 13, 13, 9), msecs(22)));
4782 sysTime.roll!"days"(730);
4783 assert(sysTime == SysTime(DateTime(0, 7, 5, 13, 13, 9), msecs(22)));
4784 }
4785
4786 {
4787 auto sysTime = SysTime(DateTime(0, 7, 6, 13, 13, 9), msecs(22));
4788 sysTime.roll!"days"(-365).roll!"days"(362).roll!"days"(-12).roll!"days"(730);
4789 assert(sysTime == SysTime(DateTime(0, 7, 8, 13, 13, 9), msecs(22)));
4790 }
4791
4792 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
4793 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
4794 static assert(!__traits(compiles, cst.roll!"days"(4)));
4795 //static assert(!__traits(compiles, ist.roll!"days"(4)));
4796 }
4797
4798
4799 // Shares documentation with "days" version.
4800 ref SysTime roll(string units)(long value) @safe nothrow
4801 if (units == "hours" || units == "minutes" || units == "seconds")
4802 {
4803 try
4804 {
4805 auto hnsecs = adjTime;
4806 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
4807
4808 if (hnsecs < 0)
4809 {
4810 hnsecs += convert!("hours", "hnsecs")(24);
4811 --days;
4812 }
4813
4814 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
4815 immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
4816 immutable second = splitUnitsFromHNSecs!"seconds"(hnsecs);
4817
4818 auto dateTime = DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour,
4819 cast(int) minute, cast(int) second));
4820 dateTime.roll!units(value);
4821 --days;
4822
4823 hnsecs += convert!("hours", "hnsecs")(dateTime.hour);
4824 hnsecs += convert!("minutes", "hnsecs")(dateTime.minute);
4825 hnsecs += convert!("seconds", "hnsecs")(dateTime.second);
4826
4827 if (days < 0)
4828 {
4829 hnsecs -= convert!("hours", "hnsecs")(24);
4830 ++days;
4831 }
4832
4833 immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
4834 adjTime = newDaysHNSecs + hnsecs;
4835 return this;
4836 }
4837 catch (Exception e)
4838 assert(0, "Either DateTime's constructor or TimeOfDay's constructor threw.");
4839 }
4840
4841 // Test roll!"hours"().
4842 @safe unittest
4843 {
4844 static void testST(SysTime orig, int hours, in SysTime expected, size_t line = __LINE__)
4845 {
4846 orig.roll!"hours"(hours);
4847 if (orig != expected)
4848 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
4849 }
4850
4851 // Test A.D.
4852 immutable d = msecs(45);
4853 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), d);
4854 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
4855 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 13, 30, 33), d));
4856 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 14, 30, 33), d));
4857 testST(beforeAD, 3, SysTime(DateTime(1999, 7, 6, 15, 30, 33), d));
4858 testST(beforeAD, 4, SysTime(DateTime(1999, 7, 6, 16, 30, 33), d));
4859 testST(beforeAD, 5, SysTime(DateTime(1999, 7, 6, 17, 30, 33), d));
4860 testST(beforeAD, 6, SysTime(DateTime(1999, 7, 6, 18, 30, 33), d));
4861 testST(beforeAD, 7, SysTime(DateTime(1999, 7, 6, 19, 30, 33), d));
4862 testST(beforeAD, 8, SysTime(DateTime(1999, 7, 6, 20, 30, 33), d));
4863 testST(beforeAD, 9, SysTime(DateTime(1999, 7, 6, 21, 30, 33), d));
4864 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 22, 30, 33), d));
4865 testST(beforeAD, 11, SysTime(DateTime(1999, 7, 6, 23, 30, 33), d));
4866 testST(beforeAD, 12, SysTime(DateTime(1999, 7, 6, 0, 30, 33), d));
4867 testST(beforeAD, 13, SysTime(DateTime(1999, 7, 6, 1, 30, 33), d));
4868 testST(beforeAD, 14, SysTime(DateTime(1999, 7, 6, 2, 30, 33), d));
4869 testST(beforeAD, 15, SysTime(DateTime(1999, 7, 6, 3, 30, 33), d));
4870 testST(beforeAD, 16, SysTime(DateTime(1999, 7, 6, 4, 30, 33), d));
4871 testST(beforeAD, 17, SysTime(DateTime(1999, 7, 6, 5, 30, 33), d));
4872 testST(beforeAD, 18, SysTime(DateTime(1999, 7, 6, 6, 30, 33), d));
4873 testST(beforeAD, 19, SysTime(DateTime(1999, 7, 6, 7, 30, 33), d));
4874 testST(beforeAD, 20, SysTime(DateTime(1999, 7, 6, 8, 30, 33), d));
4875 testST(beforeAD, 21, SysTime(DateTime(1999, 7, 6, 9, 30, 33), d));
4876 testST(beforeAD, 22, SysTime(DateTime(1999, 7, 6, 10, 30, 33), d));
4877 testST(beforeAD, 23, SysTime(DateTime(1999, 7, 6, 11, 30, 33), d));
4878 testST(beforeAD, 24, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
4879 testST(beforeAD, 25, SysTime(DateTime(1999, 7, 6, 13, 30, 33), d));
4880 testST(beforeAD, 50, SysTime(DateTime(1999, 7, 6, 14, 30, 33), d));
4881 testST(beforeAD, 10_000, SysTime(DateTime(1999, 7, 6, 4, 30, 33), d));
4882
4883 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 11, 30, 33), d));
4884 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 10, 30, 33), d));
4885 testST(beforeAD, -3, SysTime(DateTime(1999, 7, 6, 9, 30, 33), d));
4886 testST(beforeAD, -4, SysTime(DateTime(1999, 7, 6, 8, 30, 33), d));
4887 testST(beforeAD, -5, SysTime(DateTime(1999, 7, 6, 7, 30, 33), d));
4888 testST(beforeAD, -6, SysTime(DateTime(1999, 7, 6, 6, 30, 33), d));
4889 testST(beforeAD, -7, SysTime(DateTime(1999, 7, 6, 5, 30, 33), d));
4890 testST(beforeAD, -8, SysTime(DateTime(1999, 7, 6, 4, 30, 33), d));
4891 testST(beforeAD, -9, SysTime(DateTime(1999, 7, 6, 3, 30, 33), d));
4892 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 2, 30, 33), d));
4893 testST(beforeAD, -11, SysTime(DateTime(1999, 7, 6, 1, 30, 33), d));
4894 testST(beforeAD, -12, SysTime(DateTime(1999, 7, 6, 0, 30, 33), d));
4895 testST(beforeAD, -13, SysTime(DateTime(1999, 7, 6, 23, 30, 33), d));
4896 testST(beforeAD, -14, SysTime(DateTime(1999, 7, 6, 22, 30, 33), d));
4897 testST(beforeAD, -15, SysTime(DateTime(1999, 7, 6, 21, 30, 33), d));
4898 testST(beforeAD, -16, SysTime(DateTime(1999, 7, 6, 20, 30, 33), d));
4899 testST(beforeAD, -17, SysTime(DateTime(1999, 7, 6, 19, 30, 33), d));
4900 testST(beforeAD, -18, SysTime(DateTime(1999, 7, 6, 18, 30, 33), d));
4901 testST(beforeAD, -19, SysTime(DateTime(1999, 7, 6, 17, 30, 33), d));
4902 testST(beforeAD, -20, SysTime(DateTime(1999, 7, 6, 16, 30, 33), d));
4903 testST(beforeAD, -21, SysTime(DateTime(1999, 7, 6, 15, 30, 33), d));
4904 testST(beforeAD, -22, SysTime(DateTime(1999, 7, 6, 14, 30, 33), d));
4905 testST(beforeAD, -23, SysTime(DateTime(1999, 7, 6, 13, 30, 33), d));
4906 testST(beforeAD, -24, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
4907 testST(beforeAD, -25, SysTime(DateTime(1999, 7, 6, 11, 30, 33), d));
4908 testST(beforeAD, -50, SysTime(DateTime(1999, 7, 6, 10, 30, 33), d));
4909 testST(beforeAD, -10_000, SysTime(DateTime(1999, 7, 6, 20, 30, 33), d));
4910
4911 testST(SysTime(DateTime(1999, 7, 6, 0, 30, 33), d), 1, SysTime(DateTime(1999, 7, 6, 1, 30, 33), d));
4912 testST(SysTime(DateTime(1999, 7, 6, 0, 30, 33), d), 0, SysTime(DateTime(1999, 7, 6, 0, 30, 33), d));
4913 testST(SysTime(DateTime(1999, 7, 6, 0, 30, 33), d), -1, SysTime(DateTime(1999, 7, 6, 23, 30, 33), d));
4914
4915 testST(SysTime(DateTime(1999, 7, 6, 23, 30, 33), d), 1, SysTime(DateTime(1999, 7, 6, 0, 30, 33), d));
4916 testST(SysTime(DateTime(1999, 7, 6, 23, 30, 33), d), 0, SysTime(DateTime(1999, 7, 6, 23, 30, 33), d));
4917 testST(SysTime(DateTime(1999, 7, 6, 23, 30, 33), d), -1, SysTime(DateTime(1999, 7, 6, 22, 30, 33), d));
4918
4919 testST(SysTime(DateTime(1999, 7, 31, 23, 30, 33), d), 1, SysTime(DateTime(1999, 7, 31, 0, 30, 33), d));
4920 testST(SysTime(DateTime(1999, 8, 1, 0, 30, 33), d), -1, SysTime(DateTime(1999, 8, 1, 23, 30, 33), d));
4921
4922 testST(SysTime(DateTime(1999, 12, 31, 23, 30, 33), d), 1, SysTime(DateTime(1999, 12, 31, 0, 30, 33), d));
4923 testST(SysTime(DateTime(2000, 1, 1, 0, 30, 33), d), -1, SysTime(DateTime(2000, 1, 1, 23, 30, 33), d));
4924
4925 testST(SysTime(DateTime(1999, 2, 28, 23, 30, 33), d), 25, SysTime(DateTime(1999, 2, 28, 0, 30, 33), d));
4926 testST(SysTime(DateTime(1999, 3, 2, 0, 30, 33), d), -25, SysTime(DateTime(1999, 3, 2, 23, 30, 33), d));
4927
4928 testST(SysTime(DateTime(2000, 2, 28, 23, 30, 33), d), 25, SysTime(DateTime(2000, 2, 28, 0, 30, 33), d));
4929 testST(SysTime(DateTime(2000, 3, 1, 0, 30, 33), d), -25, SysTime(DateTime(2000, 3, 1, 23, 30, 33), d));
4930
4931 // Test B.C.
4932 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d);
4933 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
4934 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), d));
4935 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 14, 30, 33), d));
4936 testST(beforeBC, 3, SysTime(DateTime(-1999, 7, 6, 15, 30, 33), d));
4937 testST(beforeBC, 4, SysTime(DateTime(-1999, 7, 6, 16, 30, 33), d));
4938 testST(beforeBC, 5, SysTime(DateTime(-1999, 7, 6, 17, 30, 33), d));
4939 testST(beforeBC, 6, SysTime(DateTime(-1999, 7, 6, 18, 30, 33), d));
4940 testST(beforeBC, 7, SysTime(DateTime(-1999, 7, 6, 19, 30, 33), d));
4941 testST(beforeBC, 8, SysTime(DateTime(-1999, 7, 6, 20, 30, 33), d));
4942 testST(beforeBC, 9, SysTime(DateTime(-1999, 7, 6, 21, 30, 33), d));
4943 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 22, 30, 33), d));
4944 testST(beforeBC, 11, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d));
4945 testST(beforeBC, 12, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d));
4946 testST(beforeBC, 13, SysTime(DateTime(-1999, 7, 6, 1, 30, 33), d));
4947 testST(beforeBC, 14, SysTime(DateTime(-1999, 7, 6, 2, 30, 33), d));
4948 testST(beforeBC, 15, SysTime(DateTime(-1999, 7, 6, 3, 30, 33), d));
4949 testST(beforeBC, 16, SysTime(DateTime(-1999, 7, 6, 4, 30, 33), d));
4950 testST(beforeBC, 17, SysTime(DateTime(-1999, 7, 6, 5, 30, 33), d));
4951 testST(beforeBC, 18, SysTime(DateTime(-1999, 7, 6, 6, 30, 33), d));
4952 testST(beforeBC, 19, SysTime(DateTime(-1999, 7, 6, 7, 30, 33), d));
4953 testST(beforeBC, 20, SysTime(DateTime(-1999, 7, 6, 8, 30, 33), d));
4954 testST(beforeBC, 21, SysTime(DateTime(-1999, 7, 6, 9, 30, 33), d));
4955 testST(beforeBC, 22, SysTime(DateTime(-1999, 7, 6, 10, 30, 33), d));
4956 testST(beforeBC, 23, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), d));
4957 testST(beforeBC, 24, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
4958 testST(beforeBC, 25, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), d));
4959 testST(beforeBC, 50, SysTime(DateTime(-1999, 7, 6, 14, 30, 33), d));
4960 testST(beforeBC, 10_000, SysTime(DateTime(-1999, 7, 6, 4, 30, 33), d));
4961
4962 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), d));
4963 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 10, 30, 33), d));
4964 testST(beforeBC, -3, SysTime(DateTime(-1999, 7, 6, 9, 30, 33), d));
4965 testST(beforeBC, -4, SysTime(DateTime(-1999, 7, 6, 8, 30, 33), d));
4966 testST(beforeBC, -5, SysTime(DateTime(-1999, 7, 6, 7, 30, 33), d));
4967 testST(beforeBC, -6, SysTime(DateTime(-1999, 7, 6, 6, 30, 33), d));
4968 testST(beforeBC, -7, SysTime(DateTime(-1999, 7, 6, 5, 30, 33), d));
4969 testST(beforeBC, -8, SysTime(DateTime(-1999, 7, 6, 4, 30, 33), d));
4970 testST(beforeBC, -9, SysTime(DateTime(-1999, 7, 6, 3, 30, 33), d));
4971 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 2, 30, 33), d));
4972 testST(beforeBC, -11, SysTime(DateTime(-1999, 7, 6, 1, 30, 33), d));
4973 testST(beforeBC, -12, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d));
4974 testST(beforeBC, -13, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d));
4975 testST(beforeBC, -14, SysTime(DateTime(-1999, 7, 6, 22, 30, 33), d));
4976 testST(beforeBC, -15, SysTime(DateTime(-1999, 7, 6, 21, 30, 33), d));
4977 testST(beforeBC, -16, SysTime(DateTime(-1999, 7, 6, 20, 30, 33), d));
4978 testST(beforeBC, -17, SysTime(DateTime(-1999, 7, 6, 19, 30, 33), d));
4979 testST(beforeBC, -18, SysTime(DateTime(-1999, 7, 6, 18, 30, 33), d));
4980 testST(beforeBC, -19, SysTime(DateTime(-1999, 7, 6, 17, 30, 33), d));
4981 testST(beforeBC, -20, SysTime(DateTime(-1999, 7, 6, 16, 30, 33), d));
4982 testST(beforeBC, -21, SysTime(DateTime(-1999, 7, 6, 15, 30, 33), d));
4983 testST(beforeBC, -22, SysTime(DateTime(-1999, 7, 6, 14, 30, 33), d));
4984 testST(beforeBC, -23, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), d));
4985 testST(beforeBC, -24, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
4986 testST(beforeBC, -25, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), d));
4987 testST(beforeBC, -50, SysTime(DateTime(-1999, 7, 6, 10, 30, 33), d));
4988 testST(beforeBC, -10_000, SysTime(DateTime(-1999, 7, 6, 20, 30, 33), d));
4989
4990 testST(SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d), 1, SysTime(DateTime(-1999, 7, 6, 1, 30, 33), d));
4991 testST(SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d), 0, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d));
4992 testST(SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d), -1, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d));
4993
4994 testST(SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d), 1, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d));
4995 testST(SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d), 0, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d));
4996 testST(SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d), -1, SysTime(DateTime(-1999, 7, 6, 22, 30, 33), d));
4997
4998 testST(SysTime(DateTime(-1999, 7, 31, 23, 30, 33), d), 1, SysTime(DateTime(-1999, 7, 31, 0, 30, 33), d));
4999 testST(SysTime(DateTime(-1999, 8, 1, 0, 30, 33), d), -1, SysTime(DateTime(-1999, 8, 1, 23, 30, 33), d));
5000
5001 testST(SysTime(DateTime(-2001, 12, 31, 23, 30, 33), d), 1, SysTime(DateTime(-2001, 12, 31, 0, 30, 33), d));
5002 testST(SysTime(DateTime(-2000, 1, 1, 0, 30, 33), d), -1, SysTime(DateTime(-2000, 1, 1, 23, 30, 33), d));
5003
5004 testST(SysTime(DateTime(-2001, 2, 28, 23, 30, 33), d), 25, SysTime(DateTime(-2001, 2, 28, 0, 30, 33), d));
5005 testST(SysTime(DateTime(-2001, 3, 2, 0, 30, 33), d), -25, SysTime(DateTime(-2001, 3, 2, 23, 30, 33), d));
5006
5007 testST(SysTime(DateTime(-2000, 2, 28, 23, 30, 33), d), 25, SysTime(DateTime(-2000, 2, 28, 0, 30, 33), d));
5008 testST(SysTime(DateTime(-2000, 3, 1, 0, 30, 33), d), -25, SysTime(DateTime(-2000, 3, 1, 23, 30, 33), d));
5009
5010 // Test Both
5011 testST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), d), 17_546, SysTime(DateTime(-1, 1, 1, 13, 30, 33), d));
5012 testST(SysTime(DateTime(1, 1, 1, 13, 30, 33), d), -17_546, SysTime(DateTime(1, 1, 1, 11, 30, 33), d));
5013
5014 {
5015 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
5016 sysTime.roll!"hours"(-1);
5017 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 0, 0)));
5018 sysTime.roll!"hours"(1);
5019 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5020 }
5021
5022 {
5023 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 59, 59), hnsecs(9_999_999));
5024 sysTime.roll!"hours"(-1);
5025 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
5026 sysTime.roll!"hours"(1);
5027 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 59, 59), hnsecs(9_999_999)));
5028 }
5029
5030 {
5031 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 0, 0));
5032 sysTime.roll!"hours"(1);
5033 assert(sysTime == SysTime(DateTime(0, 12, 31, 0, 0, 0)));
5034 sysTime.roll!"hours"(-1);
5035 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 0, 0)));
5036 }
5037
5038 {
5039 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5040 sysTime.roll!"hours"(1);
5041 assert(sysTime == SysTime(DateTime(0, 12, 31, 0, 59, 59), hnsecs(9_999_999)));
5042 sysTime.roll!"hours"(-1);
5043 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5044 }
5045
5046 {
5047 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5048 sysTime.roll!"hours"(1).roll!"hours"(-67);
5049 assert(sysTime == SysTime(DateTime(0, 12, 31, 5, 59, 59), hnsecs(9_999_999)));
5050 }
5051
5052 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5053 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5054 static assert(!__traits(compiles, cst.roll!"hours"(4)));
5055 //static assert(!__traits(compiles, ist.roll!"hours"(4)));
5056 }
5057
5058 // Test roll!"minutes"().
5059 @safe unittest
5060 {
5061 static void testST(SysTime orig, int minutes, in SysTime expected, size_t line = __LINE__)
5062 {
5063 orig.roll!"minutes"(minutes);
5064 if (orig != expected)
5065 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
5066 }
5067
5068 // Test A.D.
5069 immutable d = usecs(7203);
5070 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), d);
5071 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5072 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 31, 33), d));
5073 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 32, 33), d));
5074 testST(beforeAD, 3, SysTime(DateTime(1999, 7, 6, 12, 33, 33), d));
5075 testST(beforeAD, 4, SysTime(DateTime(1999, 7, 6, 12, 34, 33), d));
5076 testST(beforeAD, 5, SysTime(DateTime(1999, 7, 6, 12, 35, 33), d));
5077 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 40, 33), d));
5078 testST(beforeAD, 15, SysTime(DateTime(1999, 7, 6, 12, 45, 33), d));
5079 testST(beforeAD, 29, SysTime(DateTime(1999, 7, 6, 12, 59, 33), d));
5080 testST(beforeAD, 30, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5081 testST(beforeAD, 45, SysTime(DateTime(1999, 7, 6, 12, 15, 33), d));
5082 testST(beforeAD, 60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5083 testST(beforeAD, 75, SysTime(DateTime(1999, 7, 6, 12, 45, 33), d));
5084 testST(beforeAD, 90, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5085 testST(beforeAD, 100, SysTime(DateTime(1999, 7, 6, 12, 10, 33), d));
5086
5087 testST(beforeAD, 689, SysTime(DateTime(1999, 7, 6, 12, 59, 33), d));
5088 testST(beforeAD, 690, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5089 testST(beforeAD, 691, SysTime(DateTime(1999, 7, 6, 12, 1, 33), d));
5090 testST(beforeAD, 960, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5091 testST(beforeAD, 1439, SysTime(DateTime(1999, 7, 6, 12, 29, 33), d));
5092 testST(beforeAD, 1440, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5093 testST(beforeAD, 1441, SysTime(DateTime(1999, 7, 6, 12, 31, 33), d));
5094 testST(beforeAD, 2880, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5095
5096 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 29, 33), d));
5097 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 28, 33), d));
5098 testST(beforeAD, -3, SysTime(DateTime(1999, 7, 6, 12, 27, 33), d));
5099 testST(beforeAD, -4, SysTime(DateTime(1999, 7, 6, 12, 26, 33), d));
5100 testST(beforeAD, -5, SysTime(DateTime(1999, 7, 6, 12, 25, 33), d));
5101 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 20, 33), d));
5102 testST(beforeAD, -15, SysTime(DateTime(1999, 7, 6, 12, 15, 33), d));
5103 testST(beforeAD, -29, SysTime(DateTime(1999, 7, 6, 12, 1, 33), d));
5104 testST(beforeAD, -30, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5105 testST(beforeAD, -45, SysTime(DateTime(1999, 7, 6, 12, 45, 33), d));
5106 testST(beforeAD, -60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5107 testST(beforeAD, -75, SysTime(DateTime(1999, 7, 6, 12, 15, 33), d));
5108 testST(beforeAD, -90, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5109 testST(beforeAD, -100, SysTime(DateTime(1999, 7, 6, 12, 50, 33), d));
5110
5111 testST(beforeAD, -749, SysTime(DateTime(1999, 7, 6, 12, 1, 33), d));
5112 testST(beforeAD, -750, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5113 testST(beforeAD, -751, SysTime(DateTime(1999, 7, 6, 12, 59, 33), d));
5114 testST(beforeAD, -960, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5115 testST(beforeAD, -1439, SysTime(DateTime(1999, 7, 6, 12, 31, 33), d));
5116 testST(beforeAD, -1440, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5117 testST(beforeAD, -1441, SysTime(DateTime(1999, 7, 6, 12, 29, 33), d));
5118 testST(beforeAD, -2880, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5119
5120 testST(SysTime(DateTime(1999, 7, 6, 12, 0, 33), d), 1, SysTime(DateTime(1999, 7, 6, 12, 1, 33), d));
5121 testST(SysTime(DateTime(1999, 7, 6, 12, 0, 33), d), 0, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5122 testST(SysTime(DateTime(1999, 7, 6, 12, 0, 33), d), -1, SysTime(DateTime(1999, 7, 6, 12, 59, 33), d));
5123
5124 testST(SysTime(DateTime(1999, 7, 6, 11, 59, 33), d), 1, SysTime(DateTime(1999, 7, 6, 11, 0, 33), d));
5125 testST(SysTime(DateTime(1999, 7, 6, 11, 59, 33), d), 0, SysTime(DateTime(1999, 7, 6, 11, 59, 33), d));
5126 testST(SysTime(DateTime(1999, 7, 6, 11, 59, 33), d), -1, SysTime(DateTime(1999, 7, 6, 11, 58, 33), d));
5127
5128 testST(SysTime(DateTime(1999, 7, 6, 0, 0, 33), d), 1, SysTime(DateTime(1999, 7, 6, 0, 1, 33), d));
5129 testST(SysTime(DateTime(1999, 7, 6, 0, 0, 33), d), 0, SysTime(DateTime(1999, 7, 6, 0, 0, 33), d));
5130 testST(SysTime(DateTime(1999, 7, 6, 0, 0, 33), d), -1, SysTime(DateTime(1999, 7, 6, 0, 59, 33), d));
5131
5132 testST(SysTime(DateTime(1999, 7, 5, 23, 59, 33), d), 1, SysTime(DateTime(1999, 7, 5, 23, 0, 33), d));
5133 testST(SysTime(DateTime(1999, 7, 5, 23, 59, 33), d), 0, SysTime(DateTime(1999, 7, 5, 23, 59, 33), d));
5134 testST(SysTime(DateTime(1999, 7, 5, 23, 59, 33), d), -1, SysTime(DateTime(1999, 7, 5, 23, 58, 33), d));
5135
5136 testST(SysTime(DateTime(1998, 12, 31, 23, 59, 33), d), 1, SysTime(DateTime(1998, 12, 31, 23, 0, 33), d));
5137 testST(SysTime(DateTime(1998, 12, 31, 23, 59, 33), d), 0, SysTime(DateTime(1998, 12, 31, 23, 59, 33), d));
5138 testST(SysTime(DateTime(1998, 12, 31, 23, 59, 33), d), -1, SysTime(DateTime(1998, 12, 31, 23, 58, 33), d));
5139
5140 // Test B.C.
5141 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d);
5142 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5143 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), d));
5144 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 32, 33), d));
5145 testST(beforeBC, 3, SysTime(DateTime(-1999, 7, 6, 12, 33, 33), d));
5146 testST(beforeBC, 4, SysTime(DateTime(-1999, 7, 6, 12, 34, 33), d));
5147 testST(beforeBC, 5, SysTime(DateTime(-1999, 7, 6, 12, 35, 33), d));
5148 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 40, 33), d));
5149 testST(beforeBC, 15, SysTime(DateTime(-1999, 7, 6, 12, 45, 33), d));
5150 testST(beforeBC, 29, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), d));
5151 testST(beforeBC, 30, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5152 testST(beforeBC, 45, SysTime(DateTime(-1999, 7, 6, 12, 15, 33), d));
5153 testST(beforeBC, 60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5154 testST(beforeBC, 75, SysTime(DateTime(-1999, 7, 6, 12, 45, 33), d));
5155 testST(beforeBC, 90, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5156 testST(beforeBC, 100, SysTime(DateTime(-1999, 7, 6, 12, 10, 33), d));
5157
5158 testST(beforeBC, 689, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), d));
5159 testST(beforeBC, 690, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5160 testST(beforeBC, 691, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), d));
5161 testST(beforeBC, 960, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5162 testST(beforeBC, 1439, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), d));
5163 testST(beforeBC, 1440, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5164 testST(beforeBC, 1441, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), d));
5165 testST(beforeBC, 2880, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5166
5167 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), d));
5168 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 28, 33), d));
5169 testST(beforeBC, -3, SysTime(DateTime(-1999, 7, 6, 12, 27, 33), d));
5170 testST(beforeBC, -4, SysTime(DateTime(-1999, 7, 6, 12, 26, 33), d));
5171 testST(beforeBC, -5, SysTime(DateTime(-1999, 7, 6, 12, 25, 33), d));
5172 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 20, 33), d));
5173 testST(beforeBC, -15, SysTime(DateTime(-1999, 7, 6, 12, 15, 33), d));
5174 testST(beforeBC, -29, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), d));
5175 testST(beforeBC, -30, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5176 testST(beforeBC, -45, SysTime(DateTime(-1999, 7, 6, 12, 45, 33), d));
5177 testST(beforeBC, -60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5178 testST(beforeBC, -75, SysTime(DateTime(-1999, 7, 6, 12, 15, 33), d));
5179 testST(beforeBC, -90, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5180 testST(beforeBC, -100, SysTime(DateTime(-1999, 7, 6, 12, 50, 33), d));
5181
5182 testST(beforeBC, -749, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), d));
5183 testST(beforeBC, -750, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5184 testST(beforeBC, -751, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), d));
5185 testST(beforeBC, -960, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5186 testST(beforeBC, -1439, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), d));
5187 testST(beforeBC, -1440, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5188 testST(beforeBC, -1441, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), d));
5189 testST(beforeBC, -2880, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5190
5191 testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d), 1, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), d));
5192 testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d), 0, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5193 testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d), -1, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), d));
5194
5195 testST(SysTime(DateTime(-1999, 7, 6, 11, 59, 33), d), 1, SysTime(DateTime(-1999, 7, 6, 11, 0, 33), d));
5196 testST(SysTime(DateTime(-1999, 7, 6, 11, 59, 33), d), 0, SysTime(DateTime(-1999, 7, 6, 11, 59, 33), d));
5197 testST(SysTime(DateTime(-1999, 7, 6, 11, 59, 33), d), -1, SysTime(DateTime(-1999, 7, 6, 11, 58, 33), d));
5198
5199 testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 33), d), 1, SysTime(DateTime(-1999, 7, 6, 0, 1, 33), d));
5200 testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 33), d), 0, SysTime(DateTime(-1999, 7, 6, 0, 0, 33), d));
5201 testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 33), d), -1, SysTime(DateTime(-1999, 7, 6, 0, 59, 33), d));
5202
5203 testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 33), d), 1, SysTime(DateTime(-1999, 7, 5, 23, 0, 33), d));
5204 testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 33), d), 0, SysTime(DateTime(-1999, 7, 5, 23, 59, 33), d));
5205 testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 33), d), -1, SysTime(DateTime(-1999, 7, 5, 23, 58, 33), d));
5206
5207 testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 33), d), 1, SysTime(DateTime(-2000, 12, 31, 23, 0, 33), d));
5208 testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 33), d), 0, SysTime(DateTime(-2000, 12, 31, 23, 59, 33), d));
5209 testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 33), d), -1, SysTime(DateTime(-2000, 12, 31, 23, 58, 33), d));
5210
5211 // Test Both
5212 testST(SysTime(DateTime(1, 1, 1, 0, 0, 0)), -1, SysTime(DateTime(1, 1, 1, 0, 59, 0)));
5213 testST(SysTime(DateTime(0, 12, 31, 23, 59, 0)), 1, SysTime(DateTime(0, 12, 31, 23, 0, 0)));
5214
5215 testST(SysTime(DateTime(0, 1, 1, 0, 0, 0)), -1, SysTime(DateTime(0, 1, 1, 0, 59, 0)));
5216 testST(SysTime(DateTime(-1, 12, 31, 23, 59, 0)), 1, SysTime(DateTime(-1, 12, 31, 23, 0, 0)));
5217
5218 testST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), d), 1_052_760, SysTime(DateTime(-1, 1, 1, 11, 30, 33), d));
5219 testST(SysTime(DateTime(1, 1, 1, 13, 30, 33), d), -1_052_760, SysTime(DateTime(1, 1, 1, 13, 30, 33), d));
5220
5221 testST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), d), 1_052_782, SysTime(DateTime(-1, 1, 1, 11, 52, 33), d));
5222 testST(SysTime(DateTime(1, 1, 1, 13, 52, 33), d), -1_052_782, SysTime(DateTime(1, 1, 1, 13, 30, 33), d));
5223
5224 {
5225 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
5226 sysTime.roll!"minutes"(-1);
5227 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 59, 0)));
5228 sysTime.roll!"minutes"(1);
5229 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5230 }
5231
5232 {
5233 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 59), hnsecs(9_999_999));
5234 sysTime.roll!"minutes"(-1);
5235 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 59, 59), hnsecs(9_999_999)));
5236 sysTime.roll!"minutes"(1);
5237 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 59), hnsecs(9_999_999)));
5238 }
5239
5240 {
5241 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 0));
5242 sysTime.roll!"minutes"(1);
5243 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 0, 0)));
5244 sysTime.roll!"minutes"(-1);
5245 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 0)));
5246 }
5247
5248 {
5249 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5250 sysTime.roll!"minutes"(1);
5251 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 0, 59), hnsecs(9_999_999)));
5252 sysTime.roll!"minutes"(-1);
5253 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5254 }
5255
5256 {
5257 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5258 sysTime.roll!"minutes"(1).roll!"minutes"(-79);
5259 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 41, 59), hnsecs(9_999_999)));
5260 }
5261
5262 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5263 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5264 static assert(!__traits(compiles, cst.roll!"minutes"(4)));
5265 //static assert(!__traits(compiles, ist.roll!"minutes"(4)));
5266 }
5267
5268 // Test roll!"seconds"().
5269 @safe unittest
5270 {
5271 static void testST(SysTime orig, int seconds, in SysTime expected, size_t line = __LINE__)
5272 {
5273 orig.roll!"seconds"(seconds);
5274 if (orig != expected)
5275 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
5276 }
5277
5278 // Test A.D.
5279 immutable d = msecs(274);
5280 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), d);
5281 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5282 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 30, 34), d));
5283 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 30, 35), d));
5284 testST(beforeAD, 3, SysTime(DateTime(1999, 7, 6, 12, 30, 36), d));
5285 testST(beforeAD, 4, SysTime(DateTime(1999, 7, 6, 12, 30, 37), d));
5286 testST(beforeAD, 5, SysTime(DateTime(1999, 7, 6, 12, 30, 38), d));
5287 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 30, 43), d));
5288 testST(beforeAD, 15, SysTime(DateTime(1999, 7, 6, 12, 30, 48), d));
5289 testST(beforeAD, 26, SysTime(DateTime(1999, 7, 6, 12, 30, 59), d));
5290 testST(beforeAD, 27, SysTime(DateTime(1999, 7, 6, 12, 30, 0), d));
5291 testST(beforeAD, 30, SysTime(DateTime(1999, 7, 6, 12, 30, 3), d));
5292 testST(beforeAD, 59, SysTime(DateTime(1999, 7, 6, 12, 30, 32), d));
5293 testST(beforeAD, 60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5294 testST(beforeAD, 61, SysTime(DateTime(1999, 7, 6, 12, 30, 34), d));
5295
5296 testST(beforeAD, 1766, SysTime(DateTime(1999, 7, 6, 12, 30, 59), d));
5297 testST(beforeAD, 1767, SysTime(DateTime(1999, 7, 6, 12, 30, 0), d));
5298 testST(beforeAD, 1768, SysTime(DateTime(1999, 7, 6, 12, 30, 1), d));
5299 testST(beforeAD, 2007, SysTime(DateTime(1999, 7, 6, 12, 30, 0), d));
5300 testST(beforeAD, 3599, SysTime(DateTime(1999, 7, 6, 12, 30, 32), d));
5301 testST(beforeAD, 3600, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5302 testST(beforeAD, 3601, SysTime(DateTime(1999, 7, 6, 12, 30, 34), d));
5303 testST(beforeAD, 7200, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5304
5305 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 30, 32), d));
5306 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 30, 31), d));
5307 testST(beforeAD, -3, SysTime(DateTime(1999, 7, 6, 12, 30, 30), d));
5308 testST(beforeAD, -4, SysTime(DateTime(1999, 7, 6, 12, 30, 29), d));
5309 testST(beforeAD, -5, SysTime(DateTime(1999, 7, 6, 12, 30, 28), d));
5310 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 30, 23), d));
5311 testST(beforeAD, -15, SysTime(DateTime(1999, 7, 6, 12, 30, 18), d));
5312 testST(beforeAD, -33, SysTime(DateTime(1999, 7, 6, 12, 30, 0), d));
5313 testST(beforeAD, -34, SysTime(DateTime(1999, 7, 6, 12, 30, 59), d));
5314 testST(beforeAD, -35, SysTime(DateTime(1999, 7, 6, 12, 30, 58), d));
5315 testST(beforeAD, -59, SysTime(DateTime(1999, 7, 6, 12, 30, 34), d));
5316 testST(beforeAD, -60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5317 testST(beforeAD, -61, SysTime(DateTime(1999, 7, 6, 12, 30, 32), d));
5318
5319 testST(SysTime(DateTime(1999, 7, 6, 12, 30, 0), d), 1, SysTime(DateTime(1999, 7, 6, 12, 30, 1), d));
5320 testST(SysTime(DateTime(1999, 7, 6, 12, 30, 0), d), 0, SysTime(DateTime(1999, 7, 6, 12, 30, 0), d));
5321 testST(SysTime(DateTime(1999, 7, 6, 12, 30, 0), d), -1, SysTime(DateTime(1999, 7, 6, 12, 30, 59), d));
5322
5323 testST(SysTime(DateTime(1999, 7, 6, 12, 0, 0), d), 1, SysTime(DateTime(1999, 7, 6, 12, 0, 1), d));
5324 testST(SysTime(DateTime(1999, 7, 6, 12, 0, 0), d), 0, SysTime(DateTime(1999, 7, 6, 12, 0, 0), d));
5325 testST(SysTime(DateTime(1999, 7, 6, 12, 0, 0), d), -1, SysTime(DateTime(1999, 7, 6, 12, 0, 59), d));
5326
5327 testST(SysTime(DateTime(1999, 7, 6, 0, 0, 0), d), 1, SysTime(DateTime(1999, 7, 6, 0, 0, 1), d));
5328 testST(SysTime(DateTime(1999, 7, 6, 0, 0, 0), d), 0, SysTime(DateTime(1999, 7, 6, 0, 0, 0), d));
5329 testST(SysTime(DateTime(1999, 7, 6, 0, 0, 0), d), -1, SysTime(DateTime(1999, 7, 6, 0, 0, 59), d));
5330
5331 testST(SysTime(DateTime(1999, 7, 5, 23, 59, 59), d), 1, SysTime(DateTime(1999, 7, 5, 23, 59, 0), d));
5332 testST(SysTime(DateTime(1999, 7, 5, 23, 59, 59), d), 0, SysTime(DateTime(1999, 7, 5, 23, 59, 59), d));
5333 testST(SysTime(DateTime(1999, 7, 5, 23, 59, 59), d), -1, SysTime(DateTime(1999, 7, 5, 23, 59, 58), d));
5334
5335 testST(SysTime(DateTime(1998, 12, 31, 23, 59, 59), d), 1, SysTime(DateTime(1998, 12, 31, 23, 59, 0), d));
5336 testST(SysTime(DateTime(1998, 12, 31, 23, 59, 59), d), 0, SysTime(DateTime(1998, 12, 31, 23, 59, 59), d));
5337 testST(SysTime(DateTime(1998, 12, 31, 23, 59, 59), d), -1, SysTime(DateTime(1998, 12, 31, 23, 59, 58), d));
5338
5339 // Test B.C.
5340 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d);
5341 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5342 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), d));
5343 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 35), d));
5344 testST(beforeBC, 3, SysTime(DateTime(-1999, 7, 6, 12, 30, 36), d));
5345 testST(beforeBC, 4, SysTime(DateTime(-1999, 7, 6, 12, 30, 37), d));
5346 testST(beforeBC, 5, SysTime(DateTime(-1999, 7, 6, 12, 30, 38), d));
5347 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 43), d));
5348 testST(beforeBC, 15, SysTime(DateTime(-1999, 7, 6, 12, 30, 48), d));
5349 testST(beforeBC, 26, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), d));
5350 testST(beforeBC, 27, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d));
5351 testST(beforeBC, 30, SysTime(DateTime(-1999, 7, 6, 12, 30, 3), d));
5352 testST(beforeBC, 59, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), d));
5353 testST(beforeBC, 60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5354 testST(beforeBC, 61, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), d));
5355
5356 testST(beforeBC, 1766, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), d));
5357 testST(beforeBC, 1767, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d));
5358 testST(beforeBC, 1768, SysTime(DateTime(-1999, 7, 6, 12, 30, 1), d));
5359 testST(beforeBC, 2007, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d));
5360 testST(beforeBC, 3599, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), d));
5361 testST(beforeBC, 3600, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5362 testST(beforeBC, 3601, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), d));
5363 testST(beforeBC, 7200, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5364
5365 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), d));
5366 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 31), d));
5367 testST(beforeBC, -3, SysTime(DateTime(-1999, 7, 6, 12, 30, 30), d));
5368 testST(beforeBC, -4, SysTime(DateTime(-1999, 7, 6, 12, 30, 29), d));
5369 testST(beforeBC, -5, SysTime(DateTime(-1999, 7, 6, 12, 30, 28), d));
5370 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 23), d));
5371 testST(beforeBC, -15, SysTime(DateTime(-1999, 7, 6, 12, 30, 18), d));
5372 testST(beforeBC, -33, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d));
5373 testST(beforeBC, -34, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), d));
5374 testST(beforeBC, -35, SysTime(DateTime(-1999, 7, 6, 12, 30, 58), d));
5375 testST(beforeBC, -59, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), d));
5376 testST(beforeBC, -60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5377 testST(beforeBC, -61, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), d));
5378
5379 testST(SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d), 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 1), d));
5380 testST(SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d), 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d));
5381 testST(SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d), -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), d));
5382
5383 testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 0), d), 1, SysTime(DateTime(-1999, 7, 6, 12, 0, 1), d));
5384 testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 0), d), 0, SysTime(DateTime(-1999, 7, 6, 12, 0, 0), d));
5385 testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 0), d), -1, SysTime(DateTime(-1999, 7, 6, 12, 0, 59), d));
5386
5387 testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 0), d), 1, SysTime(DateTime(-1999, 7, 6, 0, 0, 1), d));
5388 testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 0), d), 0, SysTime(DateTime(-1999, 7, 6, 0, 0, 0), d));
5389 testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 0), d), -1, SysTime(DateTime(-1999, 7, 6, 0, 0, 59), d));
5390
5391 testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 59), d), 1, SysTime(DateTime(-1999, 7, 5, 23, 59, 0), d));
5392 testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 59), d), 0, SysTime(DateTime(-1999, 7, 5, 23, 59, 59), d));
5393 testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 59), d), -1, SysTime(DateTime(-1999, 7, 5, 23, 59, 58), d));
5394
5395 testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 59), d), 1, SysTime(DateTime(-2000, 12, 31, 23, 59, 0), d));
5396 testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 59), d), 0, SysTime(DateTime(-2000, 12, 31, 23, 59, 59), d));
5397 testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 59), d), -1, SysTime(DateTime(-2000, 12, 31, 23, 59, 58), d));
5398
5399 // Test Both
5400 testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), d), -1, SysTime(DateTime(1, 1, 1, 0, 0, 59), d));
5401 testST(SysTime(DateTime(0, 12, 31, 23, 59, 59), d), 1, SysTime(DateTime(0, 12, 31, 23, 59, 0), d));
5402
5403 testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), d), -1, SysTime(DateTime(0, 1, 1, 0, 0, 59), d));
5404 testST(SysTime(DateTime(-1, 12, 31, 23, 59, 59), d), 1, SysTime(DateTime(-1, 12, 31, 23, 59, 0), d));
5405
5406 testST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), d), 63_165_600L, SysTime(DateTime(-1, 1, 1, 11, 30, 33), d));
5407 testST(SysTime(DateTime(1, 1, 1, 13, 30, 33), d), -63_165_600L, SysTime(DateTime(1, 1, 1, 13, 30, 33), d));
5408
5409 testST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), d), 63_165_617L, SysTime(DateTime(-1, 1, 1, 11, 30, 50), d));
5410 testST(SysTime(DateTime(1, 1, 1, 13, 30, 50), d), -63_165_617L, SysTime(DateTime(1, 1, 1, 13, 30, 33), d));
5411
5412 {
5413 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
5414 sysTime.roll!"seconds"(-1);
5415 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 59)));
5416 sysTime.roll!"seconds"(1);
5417 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5418 }
5419
5420 {
5421 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(9_999_999));
5422 sysTime.roll!"seconds"(-1);
5423 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 59), hnsecs(9_999_999)));
5424 sysTime.roll!"seconds"(1);
5425 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
5426 }
5427
5428 {
5429 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59));
5430 sysTime.roll!"seconds"(1);
5431 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 0)));
5432 sysTime.roll!"seconds"(-1);
5433 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 59)));
5434 }
5435
5436 {
5437 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5438 sysTime.roll!"seconds"(1);
5439 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 0), hnsecs(9_999_999)));
5440 sysTime.roll!"seconds"(-1);
5441 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5442 }
5443
5444 {
5445 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5446 sysTime.roll!"seconds"(1).roll!"seconds"(-102);
5447 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 18), hnsecs(9_999_999)));
5448 }
5449
5450 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5451 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5452 static assert(!__traits(compiles, cst.roll!"seconds"(4)));
5453 //static assert(!__traits(compiles, ist.roll!"seconds"(4)));
5454 }
5455
5456
5457 // Shares documentation with "days" version.
5458 ref SysTime roll(string units)(long value) @safe nothrow
5459 if (units == "msecs" || units == "usecs" || units == "hnsecs")
5460 {
5461 auto hnsecs = adjTime;
5462 immutable days = splitUnitsFromHNSecs!"days"(hnsecs);
5463 immutable negative = hnsecs < 0;
5464
5465 if (negative)
5466 hnsecs += convert!("hours", "hnsecs")(24);
5467
5468 immutable seconds = splitUnitsFromHNSecs!"seconds"(hnsecs);
5469 hnsecs += convert!(units, "hnsecs")(value);
5470 hnsecs %= convert!("seconds", "hnsecs")(1);
5471
5472 if (hnsecs < 0)
5473 hnsecs += convert!("seconds", "hnsecs")(1);
5474 hnsecs += convert!("seconds", "hnsecs")(seconds);
5475
5476 if (negative)
5477 hnsecs -= convert!("hours", "hnsecs")(24);
5478
5479 immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
5480 adjTime = newDaysHNSecs + hnsecs;
5481 return this;
5482 }
5483
5484
5485 // Test roll!"msecs"().
5486 @safe unittest
5487 {
5488 static void testST(SysTime orig, int milliseconds, in SysTime expected, size_t line = __LINE__)
5489 {
5490 orig.roll!"msecs"(milliseconds);
5491 if (orig != expected)
5492 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
5493 }
5494
5495 // Test A.D.
5496 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274));
5497 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274)));
5498 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(275)));
5499 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(276)));
5500 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(284)));
5501 testST(beforeAD, 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(374)));
5502 testST(beforeAD, 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999)));
5503 testST(beforeAD, 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5504 testST(beforeAD, 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274)));
5505 testST(beforeAD, 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(275)));
5506 testST(beforeAD, 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274)));
5507 testST(beforeAD, 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999)));
5508 testST(beforeAD, 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5509 testST(beforeAD, 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(1)));
5510 testST(beforeAD, 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999)));
5511 testST(beforeAD, 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5512
5513 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(273)));
5514 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(272)));
5515 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(264)));
5516 testST(beforeAD, -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(174)));
5517 testST(beforeAD, -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5518 testST(beforeAD, -275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999)));
5519 testST(beforeAD, -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274)));
5520 testST(beforeAD, -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(273)));
5521 testST(beforeAD, -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274)));
5522 testST(beforeAD, -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5523 testST(beforeAD, -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999)));
5524 testST(beforeAD, -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5525 testST(beforeAD, -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999)));
5526
5527 // Test B.C.
5528 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274));
5529 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274)));
5530 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(275)));
5531 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(276)));
5532 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(284)));
5533 testST(beforeBC, 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(374)));
5534 testST(beforeBC, 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999)));
5535 testST(beforeBC, 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5536 testST(beforeBC, 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274)));
5537 testST(beforeBC, 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(275)));
5538 testST(beforeBC, 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274)));
5539 testST(beforeBC, 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999)));
5540 testST(beforeBC, 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5541 testST(beforeBC, 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(1)));
5542 testST(beforeBC, 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999)));
5543 testST(beforeBC, 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5544
5545 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(273)));
5546 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(272)));
5547 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(264)));
5548 testST(beforeBC, -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(174)));
5549 testST(beforeBC, -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5550 testST(beforeBC, -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999)));
5551 testST(beforeBC, -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274)));
5552 testST(beforeBC, -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(273)));
5553 testST(beforeBC, -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274)));
5554 testST(beforeBC, -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5555 testST(beforeBC, -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999)));
5556 testST(beforeBC, -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5557 testST(beforeBC, -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999)));
5558
5559 // Test Both
5560 auto beforeBoth1 = SysTime(DateTime(1, 1, 1, 0, 0, 0));
5561 testST(beforeBoth1, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), msecs(1)));
5562 testST(beforeBoth1, 0, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5563 testST(beforeBoth1, -1, SysTime(DateTime(1, 1, 1, 0, 0, 0), msecs(999)));
5564 testST(beforeBoth1, -2, SysTime(DateTime(1, 1, 1, 0, 0, 0), msecs(998)));
5565 testST(beforeBoth1, -1000, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5566 testST(beforeBoth1, -2000, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5567 testST(beforeBoth1, -2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), msecs(445)));
5568
5569 auto beforeBoth2 = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5570 testST(beforeBoth2, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_989_999)));
5571 testST(beforeBoth2, 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5572 testST(beforeBoth2, 1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9999)));
5573 testST(beforeBoth2, 2, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(19_999)));
5574 testST(beforeBoth2, 1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5575 testST(beforeBoth2, 2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5576 testST(beforeBoth2, 2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(5_549_999)));
5577
5578 {
5579 auto st = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5580 st.roll!"msecs"(1202).roll!"msecs"(-703);
5581 assert(st == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(4_989_999)));
5582 }
5583
5584 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5585 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5586 static assert(!__traits(compiles, cst.addMSecs(4)));
5587 //static assert(!__traits(compiles, ist.addMSecs(4)));
5588 }
5589
5590 // Test roll!"usecs"().
5591 @safe unittest
5592 {
5593 static void testST(SysTime orig, long microseconds, in SysTime expected, size_t line = __LINE__)
5594 {
5595 orig.roll!"usecs"(microseconds);
5596 if (orig != expected)
5597 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
5598 }
5599
5600 // Test A.D.
5601 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274));
5602 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
5603 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(275)));
5604 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(276)));
5605 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(284)));
5606 testST(beforeAD, 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(374)));
5607 testST(beforeAD, 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(999)));
5608 testST(beforeAD, 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(1000)));
5609 testST(beforeAD, 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(1274)));
5610 testST(beforeAD, 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(1275)));
5611 testST(beforeAD, 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(2274)));
5612 testST(beforeAD, 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(26_999)));
5613 testST(beforeAD, 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(27_000)));
5614 testST(beforeAD, 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(27_001)));
5615 testST(beforeAD, 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(766_999)));
5616 testST(beforeAD, 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(767_000)));
5617 testST(beforeAD, 1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
5618 testST(beforeAD, 60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
5619 testST(beforeAD, 3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
5620
5621 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(273)));
5622 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(272)));
5623 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(264)));
5624 testST(beforeAD, -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(174)));
5625 testST(beforeAD, -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5626 testST(beforeAD, -275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(999_999)));
5627 testST(beforeAD, -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(999_274)));
5628 testST(beforeAD, -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(999_273)));
5629 testST(beforeAD, -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(998_274)));
5630 testST(beforeAD, -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(967_000)));
5631 testST(beforeAD, -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(966_999)));
5632 testST(beforeAD, -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(167_000)));
5633 testST(beforeAD, -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(166_999)));
5634 testST(beforeAD, -1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
5635 testST(beforeAD, -60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
5636 testST(beforeAD, -3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
5637
5638 // Test B.C.
5639 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274));
5640 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
5641 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(275)));
5642 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(276)));
5643 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(284)));
5644 testST(beforeBC, 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(374)));
5645 testST(beforeBC, 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(999)));
5646 testST(beforeBC, 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(1000)));
5647 testST(beforeBC, 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(1274)));
5648 testST(beforeBC, 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(1275)));
5649 testST(beforeBC, 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(2274)));
5650 testST(beforeBC, 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(26_999)));
5651 testST(beforeBC, 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(27_000)));
5652 testST(beforeBC, 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(27_001)));
5653 testST(beforeBC, 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(766_999)));
5654 testST(beforeBC, 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(767_000)));
5655 testST(beforeBC, 1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
5656 testST(beforeBC, 60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
5657 testST(beforeBC, 3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
5658
5659 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(273)));
5660 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(272)));
5661 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(264)));
5662 testST(beforeBC, -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(174)));
5663 testST(beforeBC, -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5664 testST(beforeBC, -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(999_999)));
5665 testST(beforeBC, -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(999_274)));
5666 testST(beforeBC, -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(999_273)));
5667 testST(beforeBC, -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(998_274)));
5668 testST(beforeBC, -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(967_000)));
5669 testST(beforeBC, -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(966_999)));
5670 testST(beforeBC, -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(167_000)));
5671 testST(beforeBC, -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(166_999)));
5672 testST(beforeBC, -1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
5673 testST(beforeBC, -60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
5674 testST(beforeBC, -3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
5675
5676 // Test Both
5677 auto beforeBoth1 = SysTime(DateTime(1, 1, 1, 0, 0, 0));
5678 testST(beforeBoth1, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(1)));
5679 testST(beforeBoth1, 0, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5680 testST(beforeBoth1, -1, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(999_999)));
5681 testST(beforeBoth1, -2, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(999_998)));
5682 testST(beforeBoth1, -1000, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(999_000)));
5683 testST(beforeBoth1, -2000, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(998_000)));
5684 testST(beforeBoth1, -2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(997_445)));
5685 testST(beforeBoth1, -1_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5686 testST(beforeBoth1, -2_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5687 testST(beforeBoth1, -2_333_333, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(666_667)));
5688
5689 auto beforeBoth2 = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5690 testST(beforeBoth2, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_989)));
5691 testST(beforeBoth2, 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5692 testST(beforeBoth2, 1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9)));
5693 testST(beforeBoth2, 2, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(19)));
5694 testST(beforeBoth2, 1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9999)));
5695 testST(beforeBoth2, 2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(19_999)));
5696 testST(beforeBoth2, 2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(25_549)));
5697 testST(beforeBoth2, 1_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5698 testST(beforeBoth2, 2_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5699 testST(beforeBoth2, 2_333_333, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(3_333_329)));
5700
5701 {
5702 auto st = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5703 st.roll!"usecs"(9_020_027);
5704 assert(st == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(200_269)));
5705 }
5706
5707 {
5708 auto st = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5709 st.roll!"usecs"(9_020_027).roll!"usecs"(-70_034);
5710 assert(st == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_499_929)));
5711 }
5712
5713 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5714 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5715 static assert(!__traits(compiles, cst.roll!"usecs"(4)));
5716 //static assert(!__traits(compiles, ist.roll!"usecs"(4)));
5717 }
5718
5719 // Test roll!"hnsecs"().
5720 @safe unittest
5721 {
5722 static void testST(SysTime orig, long hnsecs, in SysTime expected, size_t line = __LINE__)
5723 {
5724 orig.roll!"hnsecs"(hnsecs);
5725 if (orig != expected)
5726 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
5727 }
5728
5729 // Test A.D.
5730 auto dtAD = DateTime(1999, 7, 6, 12, 30, 33);
5731 auto beforeAD = SysTime(dtAD, hnsecs(274));
5732 testST(beforeAD, 0, SysTime(dtAD, hnsecs(274)));
5733 testST(beforeAD, 1, SysTime(dtAD, hnsecs(275)));
5734 testST(beforeAD, 2, SysTime(dtAD, hnsecs(276)));
5735 testST(beforeAD, 10, SysTime(dtAD, hnsecs(284)));
5736 testST(beforeAD, 100, SysTime(dtAD, hnsecs(374)));
5737 testST(beforeAD, 725, SysTime(dtAD, hnsecs(999)));
5738 testST(beforeAD, 726, SysTime(dtAD, hnsecs(1000)));
5739 testST(beforeAD, 1000, SysTime(dtAD, hnsecs(1274)));
5740 testST(beforeAD, 1001, SysTime(dtAD, hnsecs(1275)));
5741 testST(beforeAD, 2000, SysTime(dtAD, hnsecs(2274)));
5742 testST(beforeAD, 26_725, SysTime(dtAD, hnsecs(26_999)));
5743 testST(beforeAD, 26_726, SysTime(dtAD, hnsecs(27_000)));
5744 testST(beforeAD, 26_727, SysTime(dtAD, hnsecs(27_001)));
5745 testST(beforeAD, 1_766_725, SysTime(dtAD, hnsecs(1_766_999)));
5746 testST(beforeAD, 1_766_726, SysTime(dtAD, hnsecs(1_767_000)));
5747 testST(beforeAD, 1_000_000, SysTime(dtAD, hnsecs(1_000_274)));
5748 testST(beforeAD, 60_000_000L, SysTime(dtAD, hnsecs(274)));
5749 testST(beforeAD, 3_600_000_000L, SysTime(dtAD, hnsecs(274)));
5750 testST(beforeAD, 600_000_000L, SysTime(dtAD, hnsecs(274)));
5751 testST(beforeAD, 36_000_000_000L, SysTime(dtAD, hnsecs(274)));
5752
5753 testST(beforeAD, -1, SysTime(dtAD, hnsecs(273)));
5754 testST(beforeAD, -2, SysTime(dtAD, hnsecs(272)));
5755 testST(beforeAD, -10, SysTime(dtAD, hnsecs(264)));
5756 testST(beforeAD, -100, SysTime(dtAD, hnsecs(174)));
5757 testST(beforeAD, -274, SysTime(dtAD));
5758 testST(beforeAD, -275, SysTime(dtAD, hnsecs(9_999_999)));
5759 testST(beforeAD, -1000, SysTime(dtAD, hnsecs(9_999_274)));
5760 testST(beforeAD, -1001, SysTime(dtAD, hnsecs(9_999_273)));
5761 testST(beforeAD, -2000, SysTime(dtAD, hnsecs(9_998_274)));
5762 testST(beforeAD, -33_274, SysTime(dtAD, hnsecs(9_967_000)));
5763 testST(beforeAD, -33_275, SysTime(dtAD, hnsecs(9_966_999)));
5764 testST(beforeAD, -1_833_274, SysTime(dtAD, hnsecs(8_167_000)));
5765 testST(beforeAD, -1_833_275, SysTime(dtAD, hnsecs(8_166_999)));
5766 testST(beforeAD, -1_000_000, SysTime(dtAD, hnsecs(9_000_274)));
5767 testST(beforeAD, -60_000_000L, SysTime(dtAD, hnsecs(274)));
5768 testST(beforeAD, -3_600_000_000L, SysTime(dtAD, hnsecs(274)));
5769 testST(beforeAD, -600_000_000L, SysTime(dtAD, hnsecs(274)));
5770 testST(beforeAD, -36_000_000_000L, SysTime(dtAD, hnsecs(274)));
5771
5772 // Test B.C.
5773 auto dtBC = DateTime(-1999, 7, 6, 12, 30, 33);
5774 auto beforeBC = SysTime(dtBC, hnsecs(274));
5775 testST(beforeBC, 0, SysTime(dtBC, hnsecs(274)));
5776 testST(beforeBC, 1, SysTime(dtBC, hnsecs(275)));
5777 testST(beforeBC, 2, SysTime(dtBC, hnsecs(276)));
5778 testST(beforeBC, 10, SysTime(dtBC, hnsecs(284)));
5779 testST(beforeBC, 100, SysTime(dtBC, hnsecs(374)));
5780 testST(beforeBC, 725, SysTime(dtBC, hnsecs(999)));
5781 testST(beforeBC, 726, SysTime(dtBC, hnsecs(1000)));
5782 testST(beforeBC, 1000, SysTime(dtBC, hnsecs(1274)));
5783 testST(beforeBC, 1001, SysTime(dtBC, hnsecs(1275)));
5784 testST(beforeBC, 2000, SysTime(dtBC, hnsecs(2274)));
5785 testST(beforeBC, 26_725, SysTime(dtBC, hnsecs(26_999)));
5786 testST(beforeBC, 26_726, SysTime(dtBC, hnsecs(27_000)));
5787 testST(beforeBC, 26_727, SysTime(dtBC, hnsecs(27_001)));
5788 testST(beforeBC, 1_766_725, SysTime(dtBC, hnsecs(1_766_999)));
5789 testST(beforeBC, 1_766_726, SysTime(dtBC, hnsecs(1_767_000)));
5790 testST(beforeBC, 1_000_000, SysTime(dtBC, hnsecs(1_000_274)));
5791 testST(beforeBC, 60_000_000L, SysTime(dtBC, hnsecs(274)));
5792 testST(beforeBC, 3_600_000_000L, SysTime(dtBC, hnsecs(274)));
5793 testST(beforeBC, 600_000_000L, SysTime(dtBC, hnsecs(274)));
5794 testST(beforeBC, 36_000_000_000L, SysTime(dtBC, hnsecs(274)));
5795
5796 testST(beforeBC, -1, SysTime(dtBC, hnsecs(273)));
5797 testST(beforeBC, -2, SysTime(dtBC, hnsecs(272)));
5798 testST(beforeBC, -10, SysTime(dtBC, hnsecs(264)));
5799 testST(beforeBC, -100, SysTime(dtBC, hnsecs(174)));
5800 testST(beforeBC, -274, SysTime(dtBC));
5801 testST(beforeBC, -275, SysTime(dtBC, hnsecs(9_999_999)));
5802 testST(beforeBC, -1000, SysTime(dtBC, hnsecs(9_999_274)));
5803 testST(beforeBC, -1001, SysTime(dtBC, hnsecs(9_999_273)));
5804 testST(beforeBC, -2000, SysTime(dtBC, hnsecs(9_998_274)));
5805 testST(beforeBC, -33_274, SysTime(dtBC, hnsecs(9_967_000)));
5806 testST(beforeBC, -33_275, SysTime(dtBC, hnsecs(9_966_999)));
5807 testST(beforeBC, -1_833_274, SysTime(dtBC, hnsecs(8_167_000)));
5808 testST(beforeBC, -1_833_275, SysTime(dtBC, hnsecs(8_166_999)));
5809 testST(beforeBC, -1_000_000, SysTime(dtBC, hnsecs(9_000_274)));
5810 testST(beforeBC, -60_000_000L, SysTime(dtBC, hnsecs(274)));
5811 testST(beforeBC, -3_600_000_000L, SysTime(dtBC, hnsecs(274)));
5812 testST(beforeBC, -600_000_000L, SysTime(dtBC, hnsecs(274)));
5813 testST(beforeBC, -36_000_000_000L, SysTime(dtBC, hnsecs(274)));
5814
5815 // Test Both
5816 auto dtBoth1 = DateTime(1, 1, 1, 0, 0, 0);
5817 auto beforeBoth1 = SysTime(dtBoth1);
5818 testST(beforeBoth1, 1, SysTime(dtBoth1, hnsecs(1)));
5819 testST(beforeBoth1, 0, SysTime(dtBoth1));
5820 testST(beforeBoth1, -1, SysTime(dtBoth1, hnsecs(9_999_999)));
5821 testST(beforeBoth1, -2, SysTime(dtBoth1, hnsecs(9_999_998)));
5822 testST(beforeBoth1, -1000, SysTime(dtBoth1, hnsecs(9_999_000)));
5823 testST(beforeBoth1, -2000, SysTime(dtBoth1, hnsecs(9_998_000)));
5824 testST(beforeBoth1, -2555, SysTime(dtBoth1, hnsecs(9_997_445)));
5825 testST(beforeBoth1, -1_000_000, SysTime(dtBoth1, hnsecs(9_000_000)));
5826 testST(beforeBoth1, -2_000_000, SysTime(dtBoth1, hnsecs(8_000_000)));
5827 testST(beforeBoth1, -2_333_333, SysTime(dtBoth1, hnsecs(7_666_667)));
5828 testST(beforeBoth1, -10_000_000, SysTime(dtBoth1));
5829 testST(beforeBoth1, -20_000_000, SysTime(dtBoth1));
5830 testST(beforeBoth1, -20_888_888, SysTime(dtBoth1, hnsecs(9_111_112)));
5831
5832 auto dtBoth2 = DateTime(0, 12, 31, 23, 59, 59);
5833 auto beforeBoth2 = SysTime(dtBoth2, hnsecs(9_999_999));
5834 testST(beforeBoth2, -1, SysTime(dtBoth2, hnsecs(9_999_998)));
5835 testST(beforeBoth2, 0, SysTime(dtBoth2, hnsecs(9_999_999)));
5836 testST(beforeBoth2, 1, SysTime(dtBoth2));
5837 testST(beforeBoth2, 2, SysTime(dtBoth2, hnsecs(1)));
5838 testST(beforeBoth2, 1000, SysTime(dtBoth2, hnsecs(999)));
5839 testST(beforeBoth2, 2000, SysTime(dtBoth2, hnsecs(1999)));
5840 testST(beforeBoth2, 2555, SysTime(dtBoth2, hnsecs(2554)));
5841 testST(beforeBoth2, 1_000_000, SysTime(dtBoth2, hnsecs(999_999)));
5842 testST(beforeBoth2, 2_000_000, SysTime(dtBoth2, hnsecs(1_999_999)));
5843 testST(beforeBoth2, 2_333_333, SysTime(dtBoth2, hnsecs(2_333_332)));
5844 testST(beforeBoth2, 10_000_000, SysTime(dtBoth2, hnsecs(9_999_999)));
5845 testST(beforeBoth2, 20_000_000, SysTime(dtBoth2, hnsecs(9_999_999)));
5846 testST(beforeBoth2, 20_888_888, SysTime(dtBoth2, hnsecs(888_887)));
5847
5848 {
5849 auto st = SysTime(dtBoth2, hnsecs(9_999_999));
5850 st.roll!"hnsecs"(70_777_222).roll!"hnsecs"(-222_555_292);
5851 assert(st == SysTime(dtBoth2, hnsecs(8_221_929)));
5852 }
5853
5854 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5855 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5856 static assert(!__traits(compiles, cst.roll!"hnsecs"(4)));
5857 //static assert(!__traits(compiles, ist.roll!"hnsecs"(4)));
5858 }
5859
5860
5861 /++
5862 Gives the result of adding or subtracting a $(REF Duration, core,time)
5863 from this $(LREF SysTime).
5864
5865 The legal types of arithmetic for $(LREF SysTime) using this operator
5866 are
5867
5868 $(BOOKTABLE,
5869 $(TR $(TD SysTime) $(TD +) $(TD Duration) $(TD -->) $(TD SysTime))
5870 $(TR $(TD SysTime) $(TD -) $(TD Duration) $(TD -->) $(TD SysTime))
5871 )
5872
5873 Params:
5874 duration = The $(REF Duration, core,time) to add to or subtract from
5875 this $(LREF SysTime).
5876 +/
5877 SysTime opBinary(string op)(Duration duration) @safe const pure nothrow
5878 if (op == "+" || op == "-")
5879 {
5880 SysTime retval = SysTime(this._stdTime, this._timezone);
5881 immutable hnsecs = duration.total!"hnsecs";
5882 mixin("retval._stdTime " ~ op ~ "= hnsecs;");
5883 return retval;
5884 }
5885
5886 ///
5887 @safe unittest
5888 {
5889 import core.time : hours, seconds;
5890 import std.datetime.date : DateTime;
5891
5892 assert(SysTime(DateTime(2015, 12, 31, 23, 59, 59)) + seconds(1) ==
5893 SysTime(DateTime(2016, 1, 1, 0, 0, 0)));
5894
5895 assert(SysTime(DateTime(2015, 12, 31, 23, 59, 59)) + hours(1) ==
5896 SysTime(DateTime(2016, 1, 1, 0, 59, 59)));
5897
5898 assert(SysTime(DateTime(2016, 1, 1, 0, 0, 0)) - seconds(1) ==
5899 SysTime(DateTime(2015, 12, 31, 23, 59, 59)));
5900
5901 assert(SysTime(DateTime(2016, 1, 1, 0, 59, 59)) - hours(1) ==
5902 SysTime(DateTime(2015, 12, 31, 23, 59, 59)));
5903 }
5904
5905 @safe unittest
5906 {
5907 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_678));
5908
5909 assert(st + dur!"weeks"(7) == SysTime(DateTime(1999, 8, 24, 12, 30, 33), hnsecs(2_345_678)));
5910 assert(st + dur!"weeks"(-7) == SysTime(DateTime(1999, 5, 18, 12, 30, 33), hnsecs(2_345_678)));
5911 assert(st + dur!"days"(7) == SysTime(DateTime(1999, 7, 13, 12, 30, 33), hnsecs(2_345_678)));
5912 assert(st + dur!"days"(-7) == SysTime(DateTime(1999, 6, 29, 12, 30, 33), hnsecs(2_345_678)));
5913 assert(st + dur!"hours"(7) == SysTime(DateTime(1999, 7, 6, 19, 30, 33), hnsecs(2_345_678)));
5914 assert(st + dur!"hours"(-7) == SysTime(DateTime(1999, 7, 6, 5, 30, 33), hnsecs(2_345_678)));
5915 assert(st + dur!"minutes"(7) == SysTime(DateTime(1999, 7, 6, 12, 37, 33), hnsecs(2_345_678)));
5916 assert(st + dur!"minutes"(-7) == SysTime(DateTime(1999, 7, 6, 12, 23, 33), hnsecs(2_345_678)));
5917 assert(st + dur!"seconds"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 40), hnsecs(2_345_678)));
5918 assert(st + dur!"seconds"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 26), hnsecs(2_345_678)));
5919 assert(st + dur!"msecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_415_678)));
5920 assert(st + dur!"msecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_275_678)));
5921 assert(st + dur!"usecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_748)));
5922 assert(st + dur!"usecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_608)));
5923 assert(st + dur!"hnsecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_685)));
5924 assert(st + dur!"hnsecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_671)));
5925
5926 assert(st - dur!"weeks"(-7) == SysTime(DateTime(1999, 8, 24, 12, 30, 33), hnsecs(2_345_678)));
5927 assert(st - dur!"weeks"(7) == SysTime(DateTime(1999, 5, 18, 12, 30, 33), hnsecs(2_345_678)));
5928 assert(st - dur!"days"(-7) == SysTime(DateTime(1999, 7, 13, 12, 30, 33), hnsecs(2_345_678)));
5929 assert(st - dur!"days"(7) == SysTime(DateTime(1999, 6, 29, 12, 30, 33), hnsecs(2_345_678)));
5930 assert(st - dur!"hours"(-7) == SysTime(DateTime(1999, 7, 6, 19, 30, 33), hnsecs(2_345_678)));
5931 assert(st - dur!"hours"(7) == SysTime(DateTime(1999, 7, 6, 5, 30, 33), hnsecs(2_345_678)));
5932 assert(st - dur!"minutes"(-7) == SysTime(DateTime(1999, 7, 6, 12, 37, 33), hnsecs(2_345_678)));
5933 assert(st - dur!"minutes"(7) == SysTime(DateTime(1999, 7, 6, 12, 23, 33), hnsecs(2_345_678)));
5934 assert(st - dur!"seconds"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 40), hnsecs(2_345_678)));
5935 assert(st - dur!"seconds"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 26), hnsecs(2_345_678)));
5936 assert(st - dur!"msecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_415_678)));
5937 assert(st - dur!"msecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_275_678)));
5938 assert(st - dur!"usecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_748)));
5939 assert(st - dur!"usecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_608)));
5940 assert(st - dur!"hnsecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_685)));
5941 assert(st - dur!"hnsecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_671)));
5942
5943 static void testST(in SysTime orig, long hnsecs, in SysTime expected, size_t line = __LINE__)
5944 {
5945 auto result = orig + dur!"hnsecs"(hnsecs);
5946 if (result != expected)
5947 throw new AssertError(format("Failed. actual [%s] != expected [%s]", result, expected), __FILE__, line);
5948 }
5949
5950 // Test A.D.
5951 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(274));
5952 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(274)));
5953 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(275)));
5954 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(276)));
5955 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(284)));
5956 testST(beforeAD, 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(374)));
5957 testST(beforeAD, 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(999)));
5958 testST(beforeAD, 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1000)));
5959 testST(beforeAD, 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1274)));
5960 testST(beforeAD, 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1275)));
5961 testST(beforeAD, 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2274)));
5962 testST(beforeAD, 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(26_999)));
5963 testST(beforeAD, 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(27_000)));
5964 testST(beforeAD, 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(27_001)));
5965 testST(beforeAD, 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_766_999)));
5966 testST(beforeAD, 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_767_000)));
5967 testST(beforeAD, 1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_000_274)));
5968 testST(beforeAD, 60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 39), hnsecs(274)));
5969 testST(beforeAD, 3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 36, 33), hnsecs(274)));
5970 testST(beforeAD, 600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 31, 33), hnsecs(274)));
5971 testST(beforeAD, 36_000_000_000L, SysTime(DateTime(1999, 7, 6, 13, 30, 33), hnsecs(274)));
5972
5973 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(273)));
5974 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(272)));
5975 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(264)));
5976 testST(beforeAD, -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(174)));
5977 testST(beforeAD, -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5978 testST(beforeAD, -275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_999)));
5979 testST(beforeAD, -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_274)));
5980 testST(beforeAD, -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_273)));
5981 testST(beforeAD, -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_998_274)));
5982 testST(beforeAD, -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_967_000)));
5983 testST(beforeAD, -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_966_999)));
5984 testST(beforeAD, -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(8_167_000)));
5985 testST(beforeAD, -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(8_166_999)));
5986 testST(beforeAD, -1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_000_274)));
5987 testST(beforeAD, -60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 27), hnsecs(274)));
5988 testST(beforeAD, -3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 24, 33), hnsecs(274)));
5989 testST(beforeAD, -600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 29, 33), hnsecs(274)));
5990 testST(beforeAD, -36_000_000_000L, SysTime(DateTime(1999, 7, 6, 11, 30, 33), hnsecs(274)));
5991
5992 // Test B.C.
5993 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(274));
5994 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(274)));
5995 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(275)));
5996 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(276)));
5997 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(284)));
5998 testST(beforeBC, 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(374)));
5999 testST(beforeBC, 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(999)));
6000 testST(beforeBC, 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1000)));
6001 testST(beforeBC, 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1274)));
6002 testST(beforeBC, 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1275)));
6003 testST(beforeBC, 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(2274)));
6004 testST(beforeBC, 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(26_999)));
6005 testST(beforeBC, 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(27_000)));
6006 testST(beforeBC, 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(27_001)));
6007 testST(beforeBC, 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_766_999)));
6008 testST(beforeBC, 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_767_000)));
6009 testST(beforeBC, 1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_000_274)));
6010 testST(beforeBC, 60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 39), hnsecs(274)));
6011 testST(beforeBC, 3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 36, 33), hnsecs(274)));
6012 testST(beforeBC, 600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), hnsecs(274)));
6013 testST(beforeBC, 36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), hnsecs(274)));
6014
6015 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(273)));
6016 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(272)));
6017 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(264)));
6018 testST(beforeBC, -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(174)));
6019 testST(beforeBC, -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
6020 testST(beforeBC, -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_999)));
6021 testST(beforeBC, -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_274)));
6022 testST(beforeBC, -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_273)));
6023 testST(beforeBC, -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_998_274)));
6024 testST(beforeBC, -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_967_000)));
6025 testST(beforeBC, -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_966_999)));
6026 testST(beforeBC, -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(8_167_000)));
6027 testST(beforeBC, -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(8_166_999)));
6028 testST(beforeBC, -1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_000_274)));
6029 testST(beforeBC, -60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 27), hnsecs(274)));
6030 testST(beforeBC, -3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 24, 33), hnsecs(274)));
6031 testST(beforeBC, -600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), hnsecs(274)));
6032 testST(beforeBC, -36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), hnsecs(274)));
6033
6034 // Test Both
6035 auto beforeBoth1 = SysTime(DateTime(1, 1, 1, 0, 0, 0));
6036 testST(beforeBoth1, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)));
6037 testST(beforeBoth1, 0, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6038 testST(beforeBoth1, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6039 testST(beforeBoth1, -2, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_998)));
6040 testST(beforeBoth1, -1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_000)));
6041 testST(beforeBoth1, -2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_998_000)));
6042 testST(beforeBoth1, -2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_997_445)));
6043 testST(beforeBoth1, -1_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_000_000)));
6044 testST(beforeBoth1, -2_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(8_000_000)));
6045 testST(beforeBoth1, -2_333_333, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(7_666_667)));
6046 testST(beforeBoth1, -10_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59)));
6047 testST(beforeBoth1, -20_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 58)));
6048 testST(beforeBoth1, -20_888_888, SysTime(DateTime(0, 12, 31, 23, 59, 57), hnsecs(9_111_112)));
6049
6050 auto beforeBoth2 = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
6051 testST(beforeBoth2, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_998)));
6052 testST(beforeBoth2, 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6053 testST(beforeBoth2, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6054 testST(beforeBoth2, 2, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)));
6055 testST(beforeBoth2, 1000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(999)));
6056 testST(beforeBoth2, 2000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1999)));
6057 testST(beforeBoth2, 2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(2554)));
6058 testST(beforeBoth2, 1_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(999_999)));
6059 testST(beforeBoth2, 2_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1_999_999)));
6060 testST(beforeBoth2, 2_333_333, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(2_333_332)));
6061 testST(beforeBoth2, 10_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
6062 testST(beforeBoth2, 20_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 1), hnsecs(9_999_999)));
6063 testST(beforeBoth2, 20_888_888, SysTime(DateTime(1, 1, 1, 0, 0, 2), hnsecs(888_887)));
6064
6065 auto duration = dur!"seconds"(12);
6066 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6067 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6068 assert(cst + duration == SysTime(DateTime(1999, 7, 6, 12, 30, 45)));
6069 //assert(ist + duration == SysTime(DateTime(1999, 7, 6, 12, 30, 45)));
6070 assert(cst - duration == SysTime(DateTime(1999, 7, 6, 12, 30, 21)));
6071 //assert(ist - duration == SysTime(DateTime(1999, 7, 6, 12, 30, 21)));
6072 }
6073
6074
6075 /++
6076 Gives the result of adding or subtracting a $(REF Duration, core,time) from
6077 this $(LREF SysTime), as well as assigning the result to this
6078 $(LREF SysTime).
6079
6080 The legal types of arithmetic for $(LREF SysTime) using this operator are
6081
6082 $(BOOKTABLE,
6083 $(TR $(TD SysTime) $(TD +) $(TD Duration) $(TD -->) $(TD SysTime))
6084 $(TR $(TD SysTime) $(TD -) $(TD Duration) $(TD -->) $(TD SysTime))
6085 )
6086
6087 Params:
6088 duration = The $(REF Duration, core,time) to add to or subtract from
6089 this $(LREF SysTime).
6090 +/
6091 ref SysTime opOpAssign(string op)(Duration duration) @safe pure nothrow
6092 if (op == "+" || op == "-")
6093 {
6094 immutable hnsecs = duration.total!"hnsecs";
6095 mixin("_stdTime " ~ op ~ "= hnsecs;");
6096 return this;
6097 }
6098
6099 @safe unittest
6100 {
6101 auto before = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6102 assert(before + dur!"weeks"(7) == SysTime(DateTime(1999, 8, 24, 12, 30, 33)));
6103 assert(before + dur!"weeks"(-7) == SysTime(DateTime(1999, 5, 18, 12, 30, 33)));
6104 assert(before + dur!"days"(7) == SysTime(DateTime(1999, 7, 13, 12, 30, 33)));
6105 assert(before + dur!"days"(-7) == SysTime(DateTime(1999, 6, 29, 12, 30, 33)));
6106
6107 assert(before + dur!"hours"(7) == SysTime(DateTime(1999, 7, 6, 19, 30, 33)));
6108 assert(before + dur!"hours"(-7) == SysTime(DateTime(1999, 7, 6, 5, 30, 33)));
6109 assert(before + dur!"minutes"(7) == SysTime(DateTime(1999, 7, 6, 12, 37, 33)));
6110 assert(before + dur!"minutes"(-7) == SysTime(DateTime(1999, 7, 6, 12, 23, 33)));
6111 assert(before + dur!"seconds"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 40)));
6112 assert(before + dur!"seconds"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 26)));
6113 assert(before + dur!"msecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(7)));
6114 assert(before + dur!"msecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), msecs(993)));
6115 assert(before + dur!"usecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(7)));
6116 assert(before + dur!"usecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), usecs(999_993)));
6117 assert(before + dur!"hnsecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(7)));
6118 assert(before + dur!"hnsecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_993)));
6119
6120 assert(before - dur!"weeks"(-7) == SysTime(DateTime(1999, 8, 24, 12, 30, 33)));
6121 assert(before - dur!"weeks"(7) == SysTime(DateTime(1999, 5, 18, 12, 30, 33)));
6122 assert(before - dur!"days"(-7) == SysTime(DateTime(1999, 7, 13, 12, 30, 33)));
6123 assert(before - dur!"days"(7) == SysTime(DateTime(1999, 6, 29, 12, 30, 33)));
6124
6125 assert(before - dur!"hours"(-7) == SysTime(DateTime(1999, 7, 6, 19, 30, 33)));
6126 assert(before - dur!"hours"(7) == SysTime(DateTime(1999, 7, 6, 5, 30, 33)));
6127 assert(before - dur!"minutes"(-7) == SysTime(DateTime(1999, 7, 6, 12, 37, 33)));
6128 assert(before - dur!"minutes"(7) == SysTime(DateTime(1999, 7, 6, 12, 23, 33)));
6129 assert(before - dur!"seconds"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 40)));
6130 assert(before - dur!"seconds"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 26)));
6131 assert(before - dur!"msecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(7)));
6132 assert(before - dur!"msecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), msecs(993)));
6133 assert(before - dur!"usecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(7)));
6134 assert(before - dur!"usecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), usecs(999_993)));
6135 assert(before - dur!"hnsecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(7)));
6136 assert(before - dur!"hnsecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_993)));
6137
6138 static void testST(SysTime orig, long hnsecs, in SysTime expected, size_t line = __LINE__)
6139 {
6140 auto r = orig += dur!"hnsecs"(hnsecs);
6141 if (orig != expected)
6142 throw new AssertError(format("Failed 1. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
6143 if (r != expected)
6144 throw new AssertError(format("Failed 2. actual [%s] != expected [%s]", r, expected), __FILE__, line);
6145 }
6146
6147 // Test A.D.
6148 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(274));
6149 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(274)));
6150 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(275)));
6151 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(276)));
6152 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(284)));
6153 testST(beforeAD, 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(374)));
6154 testST(beforeAD, 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(999)));
6155 testST(beforeAD, 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1000)));
6156 testST(beforeAD, 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1274)));
6157 testST(beforeAD, 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1275)));
6158 testST(beforeAD, 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2274)));
6159 testST(beforeAD, 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(26_999)));
6160 testST(beforeAD, 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(27_000)));
6161 testST(beforeAD, 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(27_001)));
6162 testST(beforeAD, 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_766_999)));
6163 testST(beforeAD, 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_767_000)));
6164 testST(beforeAD, 1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_000_274)));
6165 testST(beforeAD, 60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 39), hnsecs(274)));
6166 testST(beforeAD, 3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 36, 33), hnsecs(274)));
6167 testST(beforeAD, 600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 31, 33), hnsecs(274)));
6168 testST(beforeAD, 36_000_000_000L, SysTime(DateTime(1999, 7, 6, 13, 30, 33), hnsecs(274)));
6169
6170 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(273)));
6171 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(272)));
6172 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(264)));
6173 testST(beforeAD, -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(174)));
6174 testST(beforeAD, -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
6175 testST(beforeAD, -275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_999)));
6176 testST(beforeAD, -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_274)));
6177 testST(beforeAD, -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_273)));
6178 testST(beforeAD, -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_998_274)));
6179 testST(beforeAD, -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_967_000)));
6180 testST(beforeAD, -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_966_999)));
6181 testST(beforeAD, -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(8_167_000)));
6182 testST(beforeAD, -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(8_166_999)));
6183 testST(beforeAD, -1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_000_274)));
6184 testST(beforeAD, -60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 27), hnsecs(274)));
6185 testST(beforeAD, -3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 24, 33), hnsecs(274)));
6186 testST(beforeAD, -600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 29, 33), hnsecs(274)));
6187 testST(beforeAD, -36_000_000_000L, SysTime(DateTime(1999, 7, 6, 11, 30, 33), hnsecs(274)));
6188
6189 // Test B.C.
6190 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(274));
6191 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(274)));
6192 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(275)));
6193 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(276)));
6194 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(284)));
6195 testST(beforeBC, 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(374)));
6196 testST(beforeBC, 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(999)));
6197 testST(beforeBC, 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1000)));
6198 testST(beforeBC, 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1274)));
6199 testST(beforeBC, 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1275)));
6200 testST(beforeBC, 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(2274)));
6201 testST(beforeBC, 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(26_999)));
6202 testST(beforeBC, 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(27_000)));
6203 testST(beforeBC, 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(27_001)));
6204 testST(beforeBC, 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_766_999)));
6205 testST(beforeBC, 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_767_000)));
6206 testST(beforeBC, 1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_000_274)));
6207 testST(beforeBC, 60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 39), hnsecs(274)));
6208 testST(beforeBC, 3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 36, 33), hnsecs(274)));
6209 testST(beforeBC, 600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), hnsecs(274)));
6210 testST(beforeBC, 36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), hnsecs(274)));
6211
6212 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(273)));
6213 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(272)));
6214 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(264)));
6215 testST(beforeBC, -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(174)));
6216 testST(beforeBC, -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
6217 testST(beforeBC, -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_999)));
6218 testST(beforeBC, -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_274)));
6219 testST(beforeBC, -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_273)));
6220 testST(beforeBC, -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_998_274)));
6221 testST(beforeBC, -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_967_000)));
6222 testST(beforeBC, -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_966_999)));
6223 testST(beforeBC, -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(8_167_000)));
6224 testST(beforeBC, -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(8_166_999)));
6225 testST(beforeBC, -1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_000_274)));
6226 testST(beforeBC, -60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 27), hnsecs(274)));
6227 testST(beforeBC, -3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 24, 33), hnsecs(274)));
6228 testST(beforeBC, -600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), hnsecs(274)));
6229 testST(beforeBC, -36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), hnsecs(274)));
6230
6231 // Test Both
6232 auto beforeBoth1 = SysTime(DateTime(1, 1, 1, 0, 0, 0));
6233 testST(beforeBoth1, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)));
6234 testST(beforeBoth1, 0, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6235 testST(beforeBoth1, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6236 testST(beforeBoth1, -2, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_998)));
6237 testST(beforeBoth1, -1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_000)));
6238 testST(beforeBoth1, -2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_998_000)));
6239 testST(beforeBoth1, -2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_997_445)));
6240 testST(beforeBoth1, -1_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_000_000)));
6241 testST(beforeBoth1, -2_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(8_000_000)));
6242 testST(beforeBoth1, -2_333_333, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(7_666_667)));
6243 testST(beforeBoth1, -10_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59)));
6244 testST(beforeBoth1, -20_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 58)));
6245 testST(beforeBoth1, -20_888_888, SysTime(DateTime(0, 12, 31, 23, 59, 57), hnsecs(9_111_112)));
6246
6247 auto beforeBoth2 = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
6248 testST(beforeBoth2, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_998)));
6249 testST(beforeBoth2, 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6250 testST(beforeBoth2, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6251 testST(beforeBoth2, 2, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)));
6252 testST(beforeBoth2, 1000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(999)));
6253 testST(beforeBoth2, 2000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1999)));
6254 testST(beforeBoth2, 2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(2554)));
6255 testST(beforeBoth2, 1_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(999_999)));
6256 testST(beforeBoth2, 2_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1_999_999)));
6257 testST(beforeBoth2, 2_333_333, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(2_333_332)));
6258 testST(beforeBoth2, 10_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
6259 testST(beforeBoth2, 20_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 1), hnsecs(9_999_999)));
6260 testST(beforeBoth2, 20_888_888, SysTime(DateTime(1, 1, 1, 0, 0, 2), hnsecs(888_887)));
6261
6262 {
6263 auto st = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
6264 (st += dur!"hnsecs"(52)) += dur!"seconds"(-907);
6265 assert(st == SysTime(DateTime(0, 12, 31, 23, 44, 53), hnsecs(51)));
6266 }
6267
6268 auto duration = dur!"seconds"(12);
6269 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6270 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6271 static assert(!__traits(compiles, cst += duration));
6272 //static assert(!__traits(compiles, ist += duration));
6273 static assert(!__traits(compiles, cst -= duration));
6274 //static assert(!__traits(compiles, ist -= duration));
6275 }
6276
6277
6278 /++
6279 Gives the difference between two $(LREF SysTime)s.
6280
6281 The legal types of arithmetic for $(LREF SysTime) using this operator
6282 are
6283
6284 $(BOOKTABLE,
6285 $(TR $(TD SysTime) $(TD -) $(TD SysTime) $(TD -->) $(TD duration))
6286 )
6287 +/
6288 Duration opBinary(string op)(in SysTime rhs) @safe const pure nothrow
6289 if (op == "-")
6290 {
6291 return dur!"hnsecs"(_stdTime - rhs._stdTime);
6292 }
6293
6294 @safe unittest
6295 {
6296 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1998, 7, 6, 12, 30, 33)) ==
6297 dur!"seconds"(31_536_000));
6298 assert(SysTime(DateTime(1998, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) ==
6299 dur!"seconds"(-31_536_000));
6300
6301 assert(SysTime(DateTime(1999, 8, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) ==
6302 dur!"seconds"(26_78_400));
6303 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 8, 6, 12, 30, 33)) ==
6304 dur!"seconds"(-26_78_400));
6305
6306 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 5, 12, 30, 33)) ==
6307 dur!"seconds"(86_400));
6308 assert(SysTime(DateTime(1999, 7, 5, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) ==
6309 dur!"seconds"(-86_400));
6310
6311 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 11, 30, 33)) ==
6312 dur!"seconds"(3600));
6313 assert(SysTime(DateTime(1999, 7, 6, 11, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) ==
6314 dur!"seconds"(-3600));
6315
6316 assert(SysTime(DateTime(1999, 7, 6, 12, 31, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) ==
6317 dur!"seconds"(60));
6318 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 31, 33)) ==
6319 dur!"seconds"(-60));
6320
6321 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 34)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) ==
6322 dur!"seconds"(1));
6323 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 34)) ==
6324 dur!"seconds"(-1));
6325
6326 {
6327 auto dt = DateTime(1999, 7, 6, 12, 30, 33);
6328 assert(SysTime(dt, msecs(532)) - SysTime(dt) == msecs(532));
6329 assert(SysTime(dt) - SysTime(dt, msecs(532)) == msecs(-532));
6330
6331 assert(SysTime(dt, usecs(333_347)) - SysTime(dt) == usecs(333_347));
6332 assert(SysTime(dt) - SysTime(dt, usecs(333_347)) == usecs(-333_347));
6333
6334 assert(SysTime(dt, hnsecs(1_234_567)) - SysTime(dt) == hnsecs(1_234_567));
6335 assert(SysTime(dt) - SysTime(dt, hnsecs(1_234_567)) == hnsecs(-1_234_567));
6336 }
6337
6338 assert(SysTime(DateTime(1, 1, 1, 12, 30, 33)) - SysTime(DateTime(1, 1, 1, 0, 0, 0)) == dur!"seconds"(45033));
6339 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)) - SysTime(DateTime(1, 1, 1, 12, 30, 33)) == dur!"seconds"(-45033));
6340 assert(SysTime(DateTime(0, 12, 31, 12, 30, 33)) - SysTime(DateTime(1, 1, 1, 0, 0, 0)) == dur!"seconds"(-41367));
6341 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)) - SysTime(DateTime(0, 12, 31, 12, 30, 33)) == dur!"seconds"(41367));
6342
6343 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)) - SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)) ==
6344 dur!"hnsecs"(1));
6345 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)) - SysTime(DateTime(1, 1, 1, 0, 0, 0)) ==
6346 dur!"hnsecs"(-1));
6347
6348 version (Posix)
6349 immutable tz = PosixTimeZone.getTimeZone("America/Los_Angeles");
6350 else version (Windows)
6351 immutable tz = WindowsTimeZone.getTimeZone("Pacific Standard Time");
6352
6353 {
6354 auto dt = DateTime(2011, 1, 13, 8, 17, 2);
6355 auto d = msecs(296);
6356 assert(SysTime(dt, d, tz) - SysTime(dt, d, tz) == Duration.zero);
6357 assert(SysTime(dt, d, tz) - SysTime(dt, d, UTC()) == hours(8));
6358 assert(SysTime(dt, d, UTC()) - SysTime(dt, d, tz) == hours(-8));
6359 }
6360
6361 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6362 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6363 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6364 assert(st - st == Duration.zero);
6365 assert(cst - st == Duration.zero);
6366 //assert(ist - st == Duration.zero);
6367
6368 assert(st - cst == Duration.zero);
6369 assert(cst - cst == Duration.zero);
6370 //assert(ist - cst == Duration.zero);
6371
6372 //assert(st - ist == Duration.zero);
6373 //assert(cst - ist == Duration.zero);
6374 //assert(ist - ist == Duration.zero);
6375 }
6376
6377
6378 /++
6379 Returns the difference between the two $(LREF SysTime)s in months.
6380
6381 To get the difference in years, subtract the year property
6382 of two $(LREF SysTime)s. To get the difference in days or weeks,
6383 subtract the $(LREF SysTime)s themselves and use the
6384 $(REF Duration, core,time) that results. Because converting between
6385 months and smaller units requires a specific date (which
6386 $(REF Duration, core,time)s don't have), getting the difference in
6387 months requires some math using both the year and month properties, so
6388 this is a convenience function for getting the difference in months.
6389
6390 Note that the number of days in the months or how far into the month
6391 either date is is irrelevant. It is the difference in the month property
6392 combined with the difference in years * 12. So, for instance,
6393 December 31st and January 1st are one month apart just as December 1st
6394 and January 31st are one month apart.
6395
6396 Params:
6397 rhs = The $(LREF SysTime) to subtract from this one.
6398 +/
6399 int diffMonths(in SysTime rhs) @safe const nothrow
6400 {
6401 return (cast(Date) this).diffMonths(cast(Date) rhs);
6402 }
6403
6404 ///
6405 @safe unittest
6406 {
6407 import std.datetime.date : Date;
6408
6409 assert(SysTime(Date(1999, 2, 1)).diffMonths(
6410 SysTime(Date(1999, 1, 31))) == 1);
6411
6412 assert(SysTime(Date(1999, 1, 31)).diffMonths(
6413 SysTime(Date(1999, 2, 1))) == -1);
6414
6415 assert(SysTime(Date(1999, 3, 1)).diffMonths(
6416 SysTime(Date(1999, 1, 1))) == 2);
6417
6418 assert(SysTime(Date(1999, 1, 1)).diffMonths(
6419 SysTime(Date(1999, 3, 31))) == -2);
6420 }
6421
6422 @safe unittest
6423 {
6424 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6425 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6426 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6427 assert(st.diffMonths(st) == 0);
6428 assert(cst.diffMonths(st) == 0);
6429 //assert(ist.diffMonths(st) == 0);
6430
6431 assert(st.diffMonths(cst) == 0);
6432 assert(cst.diffMonths(cst) == 0);
6433 //assert(ist.diffMonths(cst) == 0);
6434
6435 //assert(st.diffMonths(ist) == 0);
6436 //assert(cst.diffMonths(ist) == 0);
6437 //assert(ist.diffMonths(ist) == 0);
6438 }
6439
6440
6441 /++
6442 Whether this $(LREF SysTime) is in a leap year.
6443 +/
6444 @property bool isLeapYear() @safe const nothrow
6445 {
6446 return (cast(Date) this).isLeapYear;
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 assert(!st.isLeapYear);
6455 assert(!cst.isLeapYear);
6456 //assert(!ist.isLeapYear);
6457 }
6458
6459
6460 /++
6461 Day of the week this $(LREF SysTime) is on.
6462 +/
6463 @property DayOfWeek dayOfWeek() @safe const nothrow
6464 {
6465 return getDayOfWeek(dayOfGregorianCal);
6466 }
6467
6468 @safe unittest
6469 {
6470 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6471 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6472 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6473 assert(st.dayOfWeek == DayOfWeek.tue);
6474 assert(cst.dayOfWeek == DayOfWeek.tue);
6475 //assert(ist.dayOfWeek == DayOfWeek.tue);
6476 }
6477
6478
6479 /++
6480 Day of the year this $(LREF SysTime) is on.
6481 +/
6482 @property ushort dayOfYear() @safe const nothrow
6483 {
6484 return (cast(Date) this).dayOfYear;
6485 }
6486
6487 ///
6488 @safe unittest
6489 {
6490 import std.datetime.date : DateTime;
6491
6492 assert(SysTime(DateTime(1999, 1, 1, 12, 22, 7)).dayOfYear == 1);
6493 assert(SysTime(DateTime(1999, 12, 31, 7, 2, 59)).dayOfYear == 365);
6494 assert(SysTime(DateTime(2000, 12, 31, 21, 20, 0)).dayOfYear == 366);
6495 }
6496
6497 @safe unittest
6498 {
6499 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6500 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6501 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6502 assert(st.dayOfYear == 187);
6503 assert(cst.dayOfYear == 187);
6504 //assert(ist.dayOfYear == 187);
6505 }
6506
6507
6508 /++
6509 Day of the year.
6510
6511 Params:
6512 day = The day of the year to set which day of the year this
6513 $(LREF SysTime) is on.
6514 +/
6515 @property void dayOfYear(int day) @safe
6516 {
6517 immutable hnsecs = adjTime;
6518 immutable days = convert!("hnsecs", "days")(hnsecs);
6519 immutable theRest = hnsecs - convert!("days", "hnsecs")(days);
6520
6521 auto date = Date(cast(int) days);
6522 date.dayOfYear = day;
6523
6524 immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
6525
6526 adjTime = newDaysHNSecs + theRest;
6527 }
6528
6529 @safe unittest
6530 {
6531 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6532 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6533 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6534 st.dayOfYear = 12;
6535 assert(st.dayOfYear == 12);
6536 static assert(!__traits(compiles, cst.dayOfYear = 12));
6537 //static assert(!__traits(compiles, ist.dayOfYear = 12));
6538 }
6539
6540
6541 /++
6542 The Xth day of the Gregorian Calendar that this $(LREF SysTime) is on.
6543 +/
6544 @property int dayOfGregorianCal() @safe const nothrow
6545 {
6546 immutable adjustedTime = adjTime;
6547
6548 // We have to add one because 0 would be midnight, January 1st, 1 A.D.,
6549 // which would be the 1st day of the Gregorian Calendar, not the 0th. So,
6550 // simply casting to days is one day off.
6551 if (adjustedTime > 0)
6552 return cast(int) getUnitsFromHNSecs!"days"(adjustedTime) + 1;
6553
6554 long hnsecs = adjustedTime;
6555 immutable days = cast(int) splitUnitsFromHNSecs!"days"(hnsecs);
6556
6557 return hnsecs == 0 ? days + 1 : days;
6558 }
6559
6560 ///
6561 @safe unittest
6562 {
6563 import std.datetime.date : DateTime;
6564
6565 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).dayOfGregorianCal == 1);
6566 assert(SysTime(DateTime(1, 12, 31, 23, 59, 59)).dayOfGregorianCal == 365);
6567 assert(SysTime(DateTime(2, 1, 1, 2, 2, 2)).dayOfGregorianCal == 366);
6568
6569 assert(SysTime(DateTime(0, 12, 31, 7, 7, 7)).dayOfGregorianCal == 0);
6570 assert(SysTime(DateTime(0, 1, 1, 19, 30, 0)).dayOfGregorianCal == -365);
6571 assert(SysTime(DateTime(-1, 12, 31, 4, 7, 0)).dayOfGregorianCal == -366);
6572
6573 assert(SysTime(DateTime(2000, 1, 1, 9, 30, 20)).dayOfGregorianCal == 730_120);
6574 assert(SysTime(DateTime(2010, 12, 31, 15, 45, 50)).dayOfGregorianCal == 734_137);
6575 }
6576
6577 @safe unittest
6578 {
6579 // Test A.D.
6580 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).dayOfGregorianCal == 1);
6581 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)).dayOfGregorianCal == 1);
6582 assert(SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)).dayOfGregorianCal == 1);
6583
6584 assert(SysTime(DateTime(1, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 1);
6585 assert(SysTime(DateTime(1, 1, 2, 12, 2, 9), msecs(212)).dayOfGregorianCal == 2);
6586 assert(SysTime(DateTime(1, 2, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 32);
6587 assert(SysTime(DateTime(2, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 366);
6588 assert(SysTime(DateTime(3, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 731);
6589 assert(SysTime(DateTime(4, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 1096);
6590 assert(SysTime(DateTime(5, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 1462);
6591 assert(SysTime(DateTime(50, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 17_898);
6592 assert(SysTime(DateTime(97, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 35_065);
6593 assert(SysTime(DateTime(100, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 36_160);
6594 assert(SysTime(DateTime(101, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 36_525);
6595 assert(SysTime(DateTime(105, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 37_986);
6596 assert(SysTime(DateTime(200, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 72_684);
6597 assert(SysTime(DateTime(201, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 73_049);
6598 assert(SysTime(DateTime(300, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 109_208);
6599 assert(SysTime(DateTime(301, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 109_573);
6600 assert(SysTime(DateTime(400, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 145_732);
6601 assert(SysTime(DateTime(401, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 146_098);
6602 assert(SysTime(DateTime(500, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 182_257);
6603 assert(SysTime(DateTime(501, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 182_622);
6604 assert(SysTime(DateTime(1000, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 364_878);
6605 assert(SysTime(DateTime(1001, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 365_243);
6606 assert(SysTime(DateTime(1600, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 584_023);
6607 assert(SysTime(DateTime(1601, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 584_389);
6608 assert(SysTime(DateTime(1900, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 693_596);
6609 assert(SysTime(DateTime(1901, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 693_961);
6610 assert(SysTime(DateTime(1945, 11, 12, 12, 2, 9), msecs(212)).dayOfGregorianCal == 710_347);
6611 assert(SysTime(DateTime(1999, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 729_755);
6612 assert(SysTime(DateTime(2000, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 730_120);
6613 assert(SysTime(DateTime(2001, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 730_486);
6614
6615 assert(SysTime(DateTime(2010, 1, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_773);
6616 assert(SysTime(DateTime(2010, 1, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_803);
6617 assert(SysTime(DateTime(2010, 2, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_804);
6618 assert(SysTime(DateTime(2010, 2, 28, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_831);
6619 assert(SysTime(DateTime(2010, 3, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_832);
6620 assert(SysTime(DateTime(2010, 3, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_862);
6621 assert(SysTime(DateTime(2010, 4, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_863);
6622 assert(SysTime(DateTime(2010, 4, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_892);
6623 assert(SysTime(DateTime(2010, 5, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_893);
6624 assert(SysTime(DateTime(2010, 5, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_923);
6625 assert(SysTime(DateTime(2010, 6, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_924);
6626 assert(SysTime(DateTime(2010, 6, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_953);
6627 assert(SysTime(DateTime(2010, 7, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_954);
6628 assert(SysTime(DateTime(2010, 7, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_984);
6629 assert(SysTime(DateTime(2010, 8, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_985);
6630 assert(SysTime(DateTime(2010, 8, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_015);
6631 assert(SysTime(DateTime(2010, 9, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_016);
6632 assert(SysTime(DateTime(2010, 9, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_045);
6633 assert(SysTime(DateTime(2010, 10, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_046);
6634 assert(SysTime(DateTime(2010, 10, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_076);
6635 assert(SysTime(DateTime(2010, 11, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_077);
6636 assert(SysTime(DateTime(2010, 11, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_106);
6637 assert(SysTime(DateTime(2010, 12, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_107);
6638 assert(SysTime(DateTime(2010, 12, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_137);
6639
6640 assert(SysTime(DateTime(2012, 2, 1, 0, 0, 0)).dayOfGregorianCal == 734_534);
6641 assert(SysTime(DateTime(2012, 2, 28, 0, 0, 0)).dayOfGregorianCal == 734_561);
6642 assert(SysTime(DateTime(2012, 2, 29, 0, 0, 0)).dayOfGregorianCal == 734_562);
6643 assert(SysTime(DateTime(2012, 3, 1, 0, 0, 0)).dayOfGregorianCal == 734_563);
6644
6645 // Test B.C.
6646 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)).dayOfGregorianCal == 0);
6647 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_998)).dayOfGregorianCal == 0);
6648 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59)).dayOfGregorianCal == 0);
6649 assert(SysTime(DateTime(0, 12, 31, 0, 0, 0), hnsecs(1)).dayOfGregorianCal == 0);
6650 assert(SysTime(DateTime(0, 12, 31, 0, 0, 0)).dayOfGregorianCal == 0);
6651
6652 assert(SysTime(DateTime(-1, 12, 31, 23, 59, 59), hnsecs(9_999_999)).dayOfGregorianCal == -366);
6653 assert(SysTime(DateTime(-1, 12, 31, 23, 59, 59), hnsecs(9_999_998)).dayOfGregorianCal == -366);
6654 assert(SysTime(DateTime(-1, 12, 31, 23, 59, 59)).dayOfGregorianCal == -366);
6655 assert(SysTime(DateTime(-1, 12, 31, 0, 0, 0)).dayOfGregorianCal == -366);
6656
6657 assert(SysTime(DateTime(0, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == 0);
6658 assert(SysTime(DateTime(0, 12, 30, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1);
6659 assert(SysTime(DateTime(0, 12, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -30);
6660 assert(SysTime(DateTime(0, 11, 30, 12, 2, 9), msecs(212)).dayOfGregorianCal == -31);
6661
6662 assert(SysTime(DateTime(-1, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -366);
6663 assert(SysTime(DateTime(-1, 12, 30, 12, 2, 9), msecs(212)).dayOfGregorianCal == -367);
6664 assert(SysTime(DateTime(-1, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -730);
6665 assert(SysTime(DateTime(-2, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -731);
6666 assert(SysTime(DateTime(-2, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1095);
6667 assert(SysTime(DateTime(-3, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1096);
6668 assert(SysTime(DateTime(-3, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1460);
6669 assert(SysTime(DateTime(-4, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1461);
6670 assert(SysTime(DateTime(-4, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1826);
6671 assert(SysTime(DateTime(-5, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1827);
6672 assert(SysTime(DateTime(-5, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -2191);
6673 assert(SysTime(DateTime(-9, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -3652);
6674
6675 assert(SysTime(DateTime(-49, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -18_262);
6676 assert(SysTime(DateTime(-50, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -18_627);
6677 assert(SysTime(DateTime(-97, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -35_794);
6678 assert(SysTime(DateTime(-99, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -36_160);
6679 assert(SysTime(DateTime(-99, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -36_524);
6680 assert(SysTime(DateTime(-100, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -36_889);
6681 assert(SysTime(DateTime(-101, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -37_254);
6682 assert(SysTime(DateTime(-105, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -38_715);
6683 assert(SysTime(DateTime(-200, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -73_413);
6684 assert(SysTime(DateTime(-201, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -73_778);
6685 assert(SysTime(DateTime(-300, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -109_937);
6686 assert(SysTime(DateTime(-301, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -110_302);
6687 assert(SysTime(DateTime(-400, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -146_097);
6688 assert(SysTime(DateTime(-400, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -146_462);
6689 assert(SysTime(DateTime(-401, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -146_827);
6690 assert(SysTime(DateTime(-499, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -182_621);
6691 assert(SysTime(DateTime(-500, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -182_986);
6692 assert(SysTime(DateTime(-501, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -183_351);
6693 assert(SysTime(DateTime(-1000, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -365_607);
6694 assert(SysTime(DateTime(-1001, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -365_972);
6695 assert(SysTime(DateTime(-1599, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -584_387);
6696 assert(SysTime(DateTime(-1600, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -584_388);
6697 assert(SysTime(DateTime(-1600, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -584_753);
6698 assert(SysTime(DateTime(-1601, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -585_118);
6699 assert(SysTime(DateTime(-1900, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -694_325);
6700 assert(SysTime(DateTime(-1901, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -694_690);
6701 assert(SysTime(DateTime(-1999, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -730_484);
6702 assert(SysTime(DateTime(-2000, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -730_485);
6703 assert(SysTime(DateTime(-2000, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -730_850);
6704 assert(SysTime(DateTime(-2001, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -731_215);
6705
6706 assert(SysTime(DateTime(-2010, 1, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_502);
6707 assert(SysTime(DateTime(-2010, 1, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_472);
6708 assert(SysTime(DateTime(-2010, 2, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_471);
6709 assert(SysTime(DateTime(-2010, 2, 28, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_444);
6710 assert(SysTime(DateTime(-2010, 3, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_443);
6711 assert(SysTime(DateTime(-2010, 3, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_413);
6712 assert(SysTime(DateTime(-2010, 4, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_412);
6713 assert(SysTime(DateTime(-2010, 4, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_383);
6714 assert(SysTime(DateTime(-2010, 5, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_382);
6715 assert(SysTime(DateTime(-2010, 5, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_352);
6716 assert(SysTime(DateTime(-2010, 6, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_351);
6717 assert(SysTime(DateTime(-2010, 6, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_322);
6718 assert(SysTime(DateTime(-2010, 7, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_321);
6719 assert(SysTime(DateTime(-2010, 7, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_291);
6720 assert(SysTime(DateTime(-2010, 8, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_290);
6721 assert(SysTime(DateTime(-2010, 8, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_260);
6722 assert(SysTime(DateTime(-2010, 9, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_259);
6723 assert(SysTime(DateTime(-2010, 9, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_230);
6724 assert(SysTime(DateTime(-2010, 10, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_229);
6725 assert(SysTime(DateTime(-2010, 10, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_199);
6726 assert(SysTime(DateTime(-2010, 11, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_198);
6727 assert(SysTime(DateTime(-2010, 11, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_169);
6728 assert(SysTime(DateTime(-2010, 12, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_168);
6729 assert(SysTime(DateTime(-2010, 12, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_138);
6730
6731 assert(SysTime(DateTime(-2012, 2, 1, 0, 0, 0)).dayOfGregorianCal == -735_202);
6732 assert(SysTime(DateTime(-2012, 2, 28, 0, 0, 0)).dayOfGregorianCal == -735_175);
6733 assert(SysTime(DateTime(-2012, 2, 29, 0, 0, 0)).dayOfGregorianCal == -735_174);
6734 assert(SysTime(DateTime(-2012, 3, 1, 0, 0, 0)).dayOfGregorianCal == -735_173);
6735
6736 // Start of Hebrew Calendar
6737 assert(SysTime(DateTime(-3760, 9, 7, 0, 0, 0)).dayOfGregorianCal == -1_373_427);
6738
6739 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6740 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6741 assert(cst.dayOfGregorianCal == 729_941);
6742 //assert(ist.dayOfGregorianCal == 729_941);
6743 }
6744
6745
6746 // Test that the logic for the day of the Gregorian Calendar is consistent
6747 // between Date and SysTime.
6748 @safe unittest
6749 {
6750 void test(Date date, SysTime st, size_t line = __LINE__)
6751 {
6752 if (date.dayOfGregorianCal != st.dayOfGregorianCal)
6753 {
6754 throw new AssertError(format("Date [%s] SysTime [%s]", date.dayOfGregorianCal, st.dayOfGregorianCal),
6755 __FILE__, line);
6756 }
6757 }
6758
6759 // Test A.D.
6760 test(Date(1, 1, 1), SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6761 test(Date(1, 1, 2), SysTime(DateTime(1, 1, 2, 0, 0, 0), hnsecs(500)));
6762 test(Date(1, 2, 1), SysTime(DateTime(1, 2, 1, 0, 0, 0), hnsecs(50_000)));
6763 test(Date(2, 1, 1), SysTime(DateTime(2, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
6764 test(Date(3, 1, 1), SysTime(DateTime(3, 1, 1, 12, 13, 14)));
6765 test(Date(4, 1, 1), SysTime(DateTime(4, 1, 1, 12, 13, 14), hnsecs(500)));
6766 test(Date(5, 1, 1), SysTime(DateTime(5, 1, 1, 12, 13, 14), hnsecs(50_000)));
6767 test(Date(50, 1, 1), SysTime(DateTime(50, 1, 1, 12, 13, 14), hnsecs(9_999_999)));
6768 test(Date(97, 1, 1), SysTime(DateTime(97, 1, 1, 23, 59, 59)));
6769 test(Date(100, 1, 1), SysTime(DateTime(100, 1, 1, 23, 59, 59), hnsecs(500)));
6770 test(Date(101, 1, 1), SysTime(DateTime(101, 1, 1, 23, 59, 59), hnsecs(50_000)));
6771 test(Date(105, 1, 1), SysTime(DateTime(105, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
6772 test(Date(200, 1, 1), SysTime(DateTime(200, 1, 1, 0, 0, 0)));
6773 test(Date(201, 1, 1), SysTime(DateTime(201, 1, 1, 0, 0, 0), hnsecs(500)));
6774 test(Date(300, 1, 1), SysTime(DateTime(300, 1, 1, 0, 0, 0), hnsecs(50_000)));
6775 test(Date(301, 1, 1), SysTime(DateTime(301, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
6776 test(Date(400, 1, 1), SysTime(DateTime(400, 1, 1, 12, 13, 14)));
6777 test(Date(401, 1, 1), SysTime(DateTime(401, 1, 1, 12, 13, 14), hnsecs(500)));
6778 test(Date(500, 1, 1), SysTime(DateTime(500, 1, 1, 12, 13, 14), hnsecs(50_000)));
6779 test(Date(501, 1, 1), SysTime(DateTime(501, 1, 1, 12, 13, 14), hnsecs(9_999_999)));
6780 test(Date(1000, 1, 1), SysTime(DateTime(1000, 1, 1, 23, 59, 59)));
6781 test(Date(1001, 1, 1), SysTime(DateTime(1001, 1, 1, 23, 59, 59), hnsecs(500)));
6782 test(Date(1600, 1, 1), SysTime(DateTime(1600, 1, 1, 23, 59, 59), hnsecs(50_000)));
6783 test(Date(1601, 1, 1), SysTime(DateTime(1601, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
6784 test(Date(1900, 1, 1), SysTime(DateTime(1900, 1, 1, 0, 0, 0)));
6785 test(Date(1901, 1, 1), SysTime(DateTime(1901, 1, 1, 0, 0, 0), hnsecs(500)));
6786 test(Date(1945, 11, 12), SysTime(DateTime(1945, 11, 12, 0, 0, 0), hnsecs(50_000)));
6787 test(Date(1999, 1, 1), SysTime(DateTime(1999, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
6788 test(Date(1999, 7, 6), SysTime(DateTime(1999, 7, 6, 12, 13, 14)));
6789 test(Date(2000, 1, 1), SysTime(DateTime(2000, 1, 1, 12, 13, 14), hnsecs(500)));
6790 test(Date(2001, 1, 1), SysTime(DateTime(2001, 1, 1, 12, 13, 14), hnsecs(50_000)));
6791
6792 test(Date(2010, 1, 1), SysTime(DateTime(2010, 1, 1, 12, 13, 14), hnsecs(9_999_999)));
6793 test(Date(2010, 1, 31), SysTime(DateTime(2010, 1, 31, 23, 0, 0)));
6794 test(Date(2010, 2, 1), SysTime(DateTime(2010, 2, 1, 23, 59, 59), hnsecs(500)));
6795 test(Date(2010, 2, 28), SysTime(DateTime(2010, 2, 28, 23, 59, 59), hnsecs(50_000)));
6796 test(Date(2010, 3, 1), SysTime(DateTime(2010, 3, 1, 23, 59, 59), hnsecs(9_999_999)));
6797 test(Date(2010, 3, 31), SysTime(DateTime(2010, 3, 31, 0, 0, 0)));
6798 test(Date(2010, 4, 1), SysTime(DateTime(2010, 4, 1, 0, 0, 0), hnsecs(500)));
6799 test(Date(2010, 4, 30), SysTime(DateTime(2010, 4, 30, 0, 0, 0), hnsecs(50_000)));
6800 test(Date(2010, 5, 1), SysTime(DateTime(2010, 5, 1, 0, 0, 0), hnsecs(9_999_999)));
6801 test(Date(2010, 5, 31), SysTime(DateTime(2010, 5, 31, 12, 13, 14)));
6802 test(Date(2010, 6, 1), SysTime(DateTime(2010, 6, 1, 12, 13, 14), hnsecs(500)));
6803 test(Date(2010, 6, 30), SysTime(DateTime(2010, 6, 30, 12, 13, 14), hnsecs(50_000)));
6804 test(Date(2010, 7, 1), SysTime(DateTime(2010, 7, 1, 12, 13, 14), hnsecs(9_999_999)));
6805 test(Date(2010, 7, 31), SysTime(DateTime(2010, 7, 31, 23, 59, 59)));
6806 test(Date(2010, 8, 1), SysTime(DateTime(2010, 8, 1, 23, 59, 59), hnsecs(500)));
6807 test(Date(2010, 8, 31), SysTime(DateTime(2010, 8, 31, 23, 59, 59), hnsecs(50_000)));
6808 test(Date(2010, 9, 1), SysTime(DateTime(2010, 9, 1, 23, 59, 59), hnsecs(9_999_999)));
6809 test(Date(2010, 9, 30), SysTime(DateTime(2010, 9, 30, 12, 0, 0)));
6810 test(Date(2010, 10, 1), SysTime(DateTime(2010, 10, 1, 0, 12, 0), hnsecs(500)));
6811 test(Date(2010, 10, 31), SysTime(DateTime(2010, 10, 31, 0, 0, 12), hnsecs(50_000)));
6812 test(Date(2010, 11, 1), SysTime(DateTime(2010, 11, 1, 23, 0, 0), hnsecs(9_999_999)));
6813 test(Date(2010, 11, 30), SysTime(DateTime(2010, 11, 30, 0, 59, 0)));
6814 test(Date(2010, 12, 1), SysTime(DateTime(2010, 12, 1, 0, 0, 59), hnsecs(500)));
6815 test(Date(2010, 12, 31), SysTime(DateTime(2010, 12, 31, 0, 59, 59), hnsecs(50_000)));
6816
6817 test(Date(2012, 2, 1), SysTime(DateTime(2012, 2, 1, 23, 0, 59), hnsecs(9_999_999)));
6818 test(Date(2012, 2, 28), SysTime(DateTime(2012, 2, 28, 23, 59, 0)));
6819 test(Date(2012, 2, 29), SysTime(DateTime(2012, 2, 29, 7, 7, 7), hnsecs(7)));
6820 test(Date(2012, 3, 1), SysTime(DateTime(2012, 3, 1, 7, 7, 7), hnsecs(7)));
6821
6822 // Test B.C.
6823 test(Date(0, 12, 31), SysTime(DateTime(0, 12, 31, 0, 0, 0)));
6824 test(Date(0, 12, 30), SysTime(DateTime(0, 12, 30, 0, 0, 0), hnsecs(500)));
6825 test(Date(0, 12, 1), SysTime(DateTime(0, 12, 1, 0, 0, 0), hnsecs(50_000)));
6826 test(Date(0, 11, 30), SysTime(DateTime(0, 11, 30, 0, 0, 0), hnsecs(9_999_999)));
6827
6828 test(Date(-1, 12, 31), SysTime(DateTime(-1, 12, 31, 12, 13, 14)));
6829 test(Date(-1, 12, 30), SysTime(DateTime(-1, 12, 30, 12, 13, 14), hnsecs(500)));
6830 test(Date(-1, 1, 1), SysTime(DateTime(-1, 1, 1, 12, 13, 14), hnsecs(50_000)));
6831 test(Date(-2, 12, 31), SysTime(DateTime(-2, 12, 31, 12, 13, 14), hnsecs(9_999_999)));
6832 test(Date(-2, 1, 1), SysTime(DateTime(-2, 1, 1, 23, 59, 59)));
6833 test(Date(-3, 12, 31), SysTime(DateTime(-3, 12, 31, 23, 59, 59), hnsecs(500)));
6834 test(Date(-3, 1, 1), SysTime(DateTime(-3, 1, 1, 23, 59, 59), hnsecs(50_000)));
6835 test(Date(-4, 12, 31), SysTime(DateTime(-4, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6836 test(Date(-4, 1, 1), SysTime(DateTime(-4, 1, 1, 0, 0, 0)));
6837 test(Date(-5, 12, 31), SysTime(DateTime(-5, 12, 31, 0, 0, 0), hnsecs(500)));
6838 test(Date(-5, 1, 1), SysTime(DateTime(-5, 1, 1, 0, 0, 0), hnsecs(50_000)));
6839 test(Date(-9, 1, 1), SysTime(DateTime(-9, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
6840
6841 test(Date(-49, 1, 1), SysTime(DateTime(-49, 1, 1, 12, 13, 14)));
6842 test(Date(-50, 1, 1), SysTime(DateTime(-50, 1, 1, 12, 13, 14), hnsecs(500)));
6843 test(Date(-97, 1, 1), SysTime(DateTime(-97, 1, 1, 12, 13, 14), hnsecs(50_000)));
6844 test(Date(-99, 12, 31), SysTime(DateTime(-99, 12, 31, 12, 13, 14), hnsecs(9_999_999)));
6845 test(Date(-99, 1, 1), SysTime(DateTime(-99, 1, 1, 23, 59, 59)));
6846 test(Date(-100, 1, 1), SysTime(DateTime(-100, 1, 1, 23, 59, 59), hnsecs(500)));
6847 test(Date(-101, 1, 1), SysTime(DateTime(-101, 1, 1, 23, 59, 59), hnsecs(50_000)));
6848 test(Date(-105, 1, 1), SysTime(DateTime(-105, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
6849 test(Date(-200, 1, 1), SysTime(DateTime(-200, 1, 1, 0, 0, 0)));
6850 test(Date(-201, 1, 1), SysTime(DateTime(-201, 1, 1, 0, 0, 0), hnsecs(500)));
6851 test(Date(-300, 1, 1), SysTime(DateTime(-300, 1, 1, 0, 0, 0), hnsecs(50_000)));
6852 test(Date(-301, 1, 1), SysTime(DateTime(-301, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
6853 test(Date(-400, 12, 31), SysTime(DateTime(-400, 12, 31, 12, 13, 14)));
6854 test(Date(-400, 1, 1), SysTime(DateTime(-400, 1, 1, 12, 13, 14), hnsecs(500)));
6855 test(Date(-401, 1, 1), SysTime(DateTime(-401, 1, 1, 12, 13, 14), hnsecs(50_000)));
6856 test(Date(-499, 1, 1), SysTime(DateTime(-499, 1, 1, 12, 13, 14), hnsecs(9_999_999)));
6857 test(Date(-500, 1, 1), SysTime(DateTime(-500, 1, 1, 23, 59, 59)));
6858 test(Date(-501, 1, 1), SysTime(DateTime(-501, 1, 1, 23, 59, 59), hnsecs(500)));
6859 test(Date(-1000, 1, 1), SysTime(DateTime(-1000, 1, 1, 23, 59, 59), hnsecs(50_000)));
6860 test(Date(-1001, 1, 1), SysTime(DateTime(-1001, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
6861 test(Date(-1599, 1, 1), SysTime(DateTime(-1599, 1, 1, 0, 0, 0)));
6862 test(Date(-1600, 12, 31), SysTime(DateTime(-1600, 12, 31, 0, 0, 0), hnsecs(500)));
6863 test(Date(-1600, 1, 1), SysTime(DateTime(-1600, 1, 1, 0, 0, 0), hnsecs(50_000)));
6864 test(Date(-1601, 1, 1), SysTime(DateTime(-1601, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
6865 test(Date(-1900, 1, 1), SysTime(DateTime(-1900, 1, 1, 12, 13, 14)));
6866 test(Date(-1901, 1, 1), SysTime(DateTime(-1901, 1, 1, 12, 13, 14), hnsecs(500)));
6867 test(Date(-1999, 1, 1), SysTime(DateTime(-1999, 1, 1, 12, 13, 14), hnsecs(50_000)));
6868 test(Date(-1999, 7, 6), SysTime(DateTime(-1999, 7, 6, 12, 13, 14), hnsecs(9_999_999)));
6869 test(Date(-2000, 12, 31), SysTime(DateTime(-2000, 12, 31, 23, 59, 59)));
6870 test(Date(-2000, 1, 1), SysTime(DateTime(-2000, 1, 1, 23, 59, 59), hnsecs(500)));
6871 test(Date(-2001, 1, 1), SysTime(DateTime(-2001, 1, 1, 23, 59, 59), hnsecs(50_000)));
6872
6873 test(Date(-2010, 1, 1), SysTime(DateTime(-2010, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
6874 test(Date(-2010, 1, 31), SysTime(DateTime(-2010, 1, 31, 0, 0, 0)));
6875 test(Date(-2010, 2, 1), SysTime(DateTime(-2010, 2, 1, 0, 0, 0), hnsecs(500)));
6876 test(Date(-2010, 2, 28), SysTime(DateTime(-2010, 2, 28, 0, 0, 0), hnsecs(50_000)));
6877 test(Date(-2010, 3, 1), SysTime(DateTime(-2010, 3, 1, 0, 0, 0), hnsecs(9_999_999)));
6878 test(Date(-2010, 3, 31), SysTime(DateTime(-2010, 3, 31, 12, 13, 14)));
6879 test(Date(-2010, 4, 1), SysTime(DateTime(-2010, 4, 1, 12, 13, 14), hnsecs(500)));
6880 test(Date(-2010, 4, 30), SysTime(DateTime(-2010, 4, 30, 12, 13, 14), hnsecs(50_000)));
6881 test(Date(-2010, 5, 1), SysTime(DateTime(-2010, 5, 1, 12, 13, 14), hnsecs(9_999_999)));
6882 test(Date(-2010, 5, 31), SysTime(DateTime(-2010, 5, 31, 23, 59, 59)));
6883 test(Date(-2010, 6, 1), SysTime(DateTime(-2010, 6, 1, 23, 59, 59), hnsecs(500)));
6884 test(Date(-2010, 6, 30), SysTime(DateTime(-2010, 6, 30, 23, 59, 59), hnsecs(50_000)));
6885 test(Date(-2010, 7, 1), SysTime(DateTime(-2010, 7, 1, 23, 59, 59), hnsecs(9_999_999)));
6886 test(Date(-2010, 7, 31), SysTime(DateTime(-2010, 7, 31, 0, 0, 0)));
6887 test(Date(-2010, 8, 1), SysTime(DateTime(-2010, 8, 1, 0, 0, 0), hnsecs(500)));
6888 test(Date(-2010, 8, 31), SysTime(DateTime(-2010, 8, 31, 0, 0, 0), hnsecs(50_000)));
6889 test(Date(-2010, 9, 1), SysTime(DateTime(-2010, 9, 1, 0, 0, 0), hnsecs(9_999_999)));
6890 test(Date(-2010, 9, 30), SysTime(DateTime(-2010, 9, 30, 12, 0, 0)));
6891 test(Date(-2010, 10, 1), SysTime(DateTime(-2010, 10, 1, 0, 12, 0), hnsecs(500)));
6892 test(Date(-2010, 10, 31), SysTime(DateTime(-2010, 10, 31, 0, 0, 12), hnsecs(50_000)));
6893 test(Date(-2010, 11, 1), SysTime(DateTime(-2010, 11, 1, 23, 0, 0), hnsecs(9_999_999)));
6894 test(Date(-2010, 11, 30), SysTime(DateTime(-2010, 11, 30, 0, 59, 0)));
6895 test(Date(-2010, 12, 1), SysTime(DateTime(-2010, 12, 1, 0, 0, 59), hnsecs(500)));
6896 test(Date(-2010, 12, 31), SysTime(DateTime(-2010, 12, 31, 0, 59, 59), hnsecs(50_000)));
6897
6898 test(Date(-2012, 2, 1), SysTime(DateTime(-2012, 2, 1, 23, 0, 59), hnsecs(9_999_999)));
6899 test(Date(-2012, 2, 28), SysTime(DateTime(-2012, 2, 28, 23, 59, 0)));
6900 test(Date(-2012, 2, 29), SysTime(DateTime(-2012, 2, 29, 7, 7, 7), hnsecs(7)));
6901 test(Date(-2012, 3, 1), SysTime(DateTime(-2012, 3, 1, 7, 7, 7), hnsecs(7)));
6902
6903 test(Date(-3760, 9, 7), SysTime(DateTime(-3760, 9, 7, 0, 0, 0)));
6904 }
6905
6906
6907 /++
6908 The Xth day of the Gregorian Calendar that this $(LREF SysTime) is on.
6909 Setting this property does not affect the time portion of $(LREF SysTime).
6910
6911 Params:
6912 days = The day of the Gregorian Calendar to set this $(LREF SysTime)
6913 to.
6914 +/
6915 @property void dayOfGregorianCal(int days) @safe nothrow
6916 {
6917 auto hnsecs = adjTime;
6918 hnsecs = removeUnitsFromHNSecs!"days"(hnsecs);
6919
6920 if (hnsecs < 0)
6921 hnsecs += convert!("hours", "hnsecs")(24);
6922
6923 if (--days < 0)
6924 {
6925 hnsecs -= convert!("hours", "hnsecs")(24);
6926 ++days;
6927 }
6928
6929 immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
6930
6931 adjTime = newDaysHNSecs + hnsecs;
6932 }
6933
6934 ///
6935 @safe unittest
6936 {
6937 import std.datetime.date : DateTime;
6938
6939 auto st = SysTime(DateTime(0, 1, 1, 12, 0, 0));
6940 st.dayOfGregorianCal = 1;
6941 assert(st == SysTime(DateTime(1, 1, 1, 12, 0, 0)));
6942
6943 st.dayOfGregorianCal = 365;
6944 assert(st == SysTime(DateTime(1, 12, 31, 12, 0, 0)));
6945
6946 st.dayOfGregorianCal = 366;
6947 assert(st == SysTime(DateTime(2, 1, 1, 12, 0, 0)));
6948
6949 st.dayOfGregorianCal = 0;
6950 assert(st == SysTime(DateTime(0, 12, 31, 12, 0, 0)));
6951
6952 st.dayOfGregorianCal = -365;
6953 assert(st == SysTime(DateTime(-0, 1, 1, 12, 0, 0)));
6954
6955 st.dayOfGregorianCal = -366;
6956 assert(st == SysTime(DateTime(-1, 12, 31, 12, 0, 0)));
6957
6958 st.dayOfGregorianCal = 730_120;
6959 assert(st == SysTime(DateTime(2000, 1, 1, 12, 0, 0)));
6960
6961 st.dayOfGregorianCal = 734_137;
6962 assert(st == SysTime(DateTime(2010, 12, 31, 12, 0, 0)));
6963 }
6964
6965 @safe unittest
6966 {
6967 void testST(SysTime orig, int day, in SysTime expected, size_t line = __LINE__)
6968 {
6969 orig.dayOfGregorianCal = day;
6970 if (orig != expected)
6971 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
6972 }
6973
6974 // Test A.D.
6975 testST(SysTime(DateTime(1, 1, 1, 0, 0, 0)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6976 testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)));
6977 testST(SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)), 1,
6978 SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
6979
6980 // Test B.C.
6981 testST(SysTime(DateTime(0, 1, 1, 0, 0, 0)), 0, SysTime(DateTime(0, 12, 31, 0, 0, 0)));
6982 testST(SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)), 0,
6983 SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6984 testST(SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(1)), 0,
6985 SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1)));
6986 testST(SysTime(DateTime(0, 1, 1, 23, 59, 59)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59)));
6987
6988 // Test Both.
6989 testST(SysTime(DateTime(-512, 7, 20, 0, 0, 0)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6990 testST(SysTime(DateTime(-513, 6, 6, 0, 0, 0), hnsecs(1)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)));
6991 testST(SysTime(DateTime(-511, 5, 7, 23, 59, 59), hnsecs(9_999_999)), 1,
6992 SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
6993
6994 testST(SysTime(DateTime(1607, 4, 8, 0, 0, 0)), 0, SysTime(DateTime(0, 12, 31, 0, 0, 0)));
6995 testST(SysTime(DateTime(1500, 3, 9, 23, 59, 59), hnsecs(9_999_999)), 0,
6996 SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6997 testST(SysTime(DateTime(999, 2, 10, 23, 59, 59), hnsecs(1)), 0,
6998 SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1)));
6999 testST(SysTime(DateTime(2007, 12, 11, 23, 59, 59)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59)));
7000
7001
7002 auto st = SysTime(DateTime(1, 1, 1, 12, 2, 9), msecs(212));
7003
7004 void testST2(int day, in SysTime expected, size_t line = __LINE__)
7005 {
7006 st.dayOfGregorianCal = day;
7007 if (st != expected)
7008 throw new AssertError(format("Failed. actual [%s] != expected [%s]", st, expected), __FILE__, line);
7009 }
7010
7011 // Test A.D.
7012 testST2(1, SysTime(DateTime(1, 1, 1, 12, 2, 9), msecs(212)));
7013 testST2(2, SysTime(DateTime(1, 1, 2, 12, 2, 9), msecs(212)));
7014 testST2(32, SysTime(DateTime(1, 2, 1, 12, 2, 9), msecs(212)));
7015 testST2(366, SysTime(DateTime(2, 1, 1, 12, 2, 9), msecs(212)));
7016 testST2(731, SysTime(DateTime(3, 1, 1, 12, 2, 9), msecs(212)));
7017 testST2(1096, SysTime(DateTime(4, 1, 1, 12, 2, 9), msecs(212)));
7018 testST2(1462, SysTime(DateTime(5, 1, 1, 12, 2, 9), msecs(212)));
7019 testST2(17_898, SysTime(DateTime(50, 1, 1, 12, 2, 9), msecs(212)));
7020 testST2(35_065, SysTime(DateTime(97, 1, 1, 12, 2, 9), msecs(212)));
7021 testST2(36_160, SysTime(DateTime(100, 1, 1, 12, 2, 9), msecs(212)));
7022 testST2(36_525, SysTime(DateTime(101, 1, 1, 12, 2, 9), msecs(212)));
7023 testST2(37_986, SysTime(DateTime(105, 1, 1, 12, 2, 9), msecs(212)));
7024 testST2(72_684, SysTime(DateTime(200, 1, 1, 12, 2, 9), msecs(212)));
7025 testST2(73_049, SysTime(DateTime(201, 1, 1, 12, 2, 9), msecs(212)));
7026 testST2(109_208, SysTime(DateTime(300, 1, 1, 12, 2, 9), msecs(212)));
7027 testST2(109_573, SysTime(DateTime(301, 1, 1, 12, 2, 9), msecs(212)));
7028 testST2(145_732, SysTime(DateTime(400, 1, 1, 12, 2, 9), msecs(212)));
7029 testST2(146_098, SysTime(DateTime(401, 1, 1, 12, 2, 9), msecs(212)));
7030 testST2(182_257, SysTime(DateTime(500, 1, 1, 12, 2, 9), msecs(212)));
7031 testST2(182_622, SysTime(DateTime(501, 1, 1, 12, 2, 9), msecs(212)));
7032 testST2(364_878, SysTime(DateTime(1000, 1, 1, 12, 2, 9), msecs(212)));
7033 testST2(365_243, SysTime(DateTime(1001, 1, 1, 12, 2, 9), msecs(212)));
7034 testST2(584_023, SysTime(DateTime(1600, 1, 1, 12, 2, 9), msecs(212)));
7035 testST2(584_389, SysTime(DateTime(1601, 1, 1, 12, 2, 9), msecs(212)));
7036 testST2(693_596, SysTime(DateTime(1900, 1, 1, 12, 2, 9), msecs(212)));
7037 testST2(693_961, SysTime(DateTime(1901, 1, 1, 12, 2, 9), msecs(212)));
7038 testST2(729_755, SysTime(DateTime(1999, 1, 1, 12, 2, 9), msecs(212)));
7039 testST2(730_120, SysTime(DateTime(2000, 1, 1, 12, 2, 9), msecs(212)));
7040 testST2(730_486, SysTime(DateTime(2001, 1, 1, 12, 2, 9), msecs(212)));
7041
7042 testST2(733_773, SysTime(DateTime(2010, 1, 1, 12, 2, 9), msecs(212)));
7043 testST2(733_803, SysTime(DateTime(2010, 1, 31, 12, 2, 9), msecs(212)));
7044 testST2(733_804, SysTime(DateTime(2010, 2, 1, 12, 2, 9), msecs(212)));
7045 testST2(733_831, SysTime(DateTime(2010, 2, 28, 12, 2, 9), msecs(212)));
7046 testST2(733_832, SysTime(DateTime(2010, 3, 1, 12, 2, 9), msecs(212)));
7047 testST2(733_862, SysTime(DateTime(2010, 3, 31, 12, 2, 9), msecs(212)));
7048 testST2(733_863, SysTime(DateTime(2010, 4, 1, 12, 2, 9), msecs(212)));
7049 testST2(733_892, SysTime(DateTime(2010, 4, 30, 12, 2, 9), msecs(212)));
7050 testST2(733_893, SysTime(DateTime(2010, 5, 1, 12, 2, 9), msecs(212)));
7051 testST2(733_923, SysTime(DateTime(2010, 5, 31, 12, 2, 9), msecs(212)));
7052 testST2(733_924, SysTime(DateTime(2010, 6, 1, 12, 2, 9), msecs(212)));
7053 testST2(733_953, SysTime(DateTime(2010, 6, 30, 12, 2, 9), msecs(212)));
7054 testST2(733_954, SysTime(DateTime(2010, 7, 1, 12, 2, 9), msecs(212)));
7055 testST2(733_984, SysTime(DateTime(2010, 7, 31, 12, 2, 9), msecs(212)));
7056 testST2(733_985, SysTime(DateTime(2010, 8, 1, 12, 2, 9), msecs(212)));
7057 testST2(734_015, SysTime(DateTime(2010, 8, 31, 12, 2, 9), msecs(212)));
7058 testST2(734_016, SysTime(DateTime(2010, 9, 1, 12, 2, 9), msecs(212)));
7059 testST2(734_045, SysTime(DateTime(2010, 9, 30, 12, 2, 9), msecs(212)));
7060 testST2(734_046, SysTime(DateTime(2010, 10, 1, 12, 2, 9), msecs(212)));
7061 testST2(734_076, SysTime(DateTime(2010, 10, 31, 12, 2, 9), msecs(212)));
7062 testST2(734_077, SysTime(DateTime(2010, 11, 1, 12, 2, 9), msecs(212)));
7063 testST2(734_106, SysTime(DateTime(2010, 11, 30, 12, 2, 9), msecs(212)));
7064 testST2(734_107, SysTime(DateTime(2010, 12, 1, 12, 2, 9), msecs(212)));
7065 testST2(734_137, SysTime(DateTime(2010, 12, 31, 12, 2, 9), msecs(212)));
7066
7067 testST2(734_534, SysTime(DateTime(2012, 2, 1, 12, 2, 9), msecs(212)));
7068 testST2(734_561, SysTime(DateTime(2012, 2, 28, 12, 2, 9), msecs(212)));
7069 testST2(734_562, SysTime(DateTime(2012, 2, 29, 12, 2, 9), msecs(212)));
7070 testST2(734_563, SysTime(DateTime(2012, 3, 1, 12, 2, 9), msecs(212)));
7071
7072 testST2(734_534, SysTime(DateTime(2012, 2, 1, 12, 2, 9), msecs(212)));
7073
7074 testST2(734_561, SysTime(DateTime(2012, 2, 28, 12, 2, 9), msecs(212)));
7075 testST2(734_562, SysTime(DateTime(2012, 2, 29, 12, 2, 9), msecs(212)));
7076 testST2(734_563, SysTime(DateTime(2012, 3, 1, 12, 2, 9), msecs(212)));
7077
7078 // Test B.C.
7079 testST2(0, SysTime(DateTime(0, 12, 31, 12, 2, 9), msecs(212)));
7080 testST2(-1, SysTime(DateTime(0, 12, 30, 12, 2, 9), msecs(212)));
7081 testST2(-30, SysTime(DateTime(0, 12, 1, 12, 2, 9), msecs(212)));
7082 testST2(-31, SysTime(DateTime(0, 11, 30, 12, 2, 9), msecs(212)));
7083
7084 testST2(-366, SysTime(DateTime(-1, 12, 31, 12, 2, 9), msecs(212)));
7085 testST2(-367, SysTime(DateTime(-1, 12, 30, 12, 2, 9), msecs(212)));
7086 testST2(-730, SysTime(DateTime(-1, 1, 1, 12, 2, 9), msecs(212)));
7087 testST2(-731, SysTime(DateTime(-2, 12, 31, 12, 2, 9), msecs(212)));
7088 testST2(-1095, SysTime(DateTime(-2, 1, 1, 12, 2, 9), msecs(212)));
7089 testST2(-1096, SysTime(DateTime(-3, 12, 31, 12, 2, 9), msecs(212)));
7090 testST2(-1460, SysTime(DateTime(-3, 1, 1, 12, 2, 9), msecs(212)));
7091 testST2(-1461, SysTime(DateTime(-4, 12, 31, 12, 2, 9), msecs(212)));
7092 testST2(-1826, SysTime(DateTime(-4, 1, 1, 12, 2, 9), msecs(212)));
7093 testST2(-1827, SysTime(DateTime(-5, 12, 31, 12, 2, 9), msecs(212)));
7094 testST2(-2191, SysTime(DateTime(-5, 1, 1, 12, 2, 9), msecs(212)));
7095 testST2(-3652, SysTime(DateTime(-9, 1, 1, 12, 2, 9), msecs(212)));
7096
7097 testST2(-18_262, SysTime(DateTime(-49, 1, 1, 12, 2, 9), msecs(212)));
7098 testST2(-18_627, SysTime(DateTime(-50, 1, 1, 12, 2, 9), msecs(212)));
7099 testST2(-35_794, SysTime(DateTime(-97, 1, 1, 12, 2, 9), msecs(212)));
7100 testST2(-36_160, SysTime(DateTime(-99, 12, 31, 12, 2, 9), msecs(212)));
7101 testST2(-36_524, SysTime(DateTime(-99, 1, 1, 12, 2, 9), msecs(212)));
7102 testST2(-36_889, SysTime(DateTime(-100, 1, 1, 12, 2, 9), msecs(212)));
7103 testST2(-37_254, SysTime(DateTime(-101, 1, 1, 12, 2, 9), msecs(212)));
7104 testST2(-38_715, SysTime(DateTime(-105, 1, 1, 12, 2, 9), msecs(212)));
7105 testST2(-73_413, SysTime(DateTime(-200, 1, 1, 12, 2, 9), msecs(212)));
7106 testST2(-73_778, SysTime(DateTime(-201, 1, 1, 12, 2, 9), msecs(212)));
7107 testST2(-109_937, SysTime(DateTime(-300, 1, 1, 12, 2, 9), msecs(212)));
7108 testST2(-110_302, SysTime(DateTime(-301, 1, 1, 12, 2, 9), msecs(212)));
7109 testST2(-146_097, SysTime(DateTime(-400, 12, 31, 12, 2, 9), msecs(212)));
7110 testST2(-146_462, SysTime(DateTime(-400, 1, 1, 12, 2, 9), msecs(212)));
7111 testST2(-146_827, SysTime(DateTime(-401, 1, 1, 12, 2, 9), msecs(212)));
7112 testST2(-182_621, SysTime(DateTime(-499, 1, 1, 12, 2, 9), msecs(212)));
7113 testST2(-182_986, SysTime(DateTime(-500, 1, 1, 12, 2, 9), msecs(212)));
7114 testST2(-183_351, SysTime(DateTime(-501, 1, 1, 12, 2, 9), msecs(212)));
7115 testST2(-365_607, SysTime(DateTime(-1000, 1, 1, 12, 2, 9), msecs(212)));
7116 testST2(-365_972, SysTime(DateTime(-1001, 1, 1, 12, 2, 9), msecs(212)));
7117 testST2(-584_387, SysTime(DateTime(-1599, 1, 1, 12, 2, 9), msecs(212)));
7118 testST2(-584_388, SysTime(DateTime(-1600, 12, 31, 12, 2, 9), msecs(212)));
7119 testST2(-584_753, SysTime(DateTime(-1600, 1, 1, 12, 2, 9), msecs(212)));
7120 testST2(-585_118, SysTime(DateTime(-1601, 1, 1, 12, 2, 9), msecs(212)));
7121 testST2(-694_325, SysTime(DateTime(-1900, 1, 1, 12, 2, 9), msecs(212)));
7122 testST2(-694_690, SysTime(DateTime(-1901, 1, 1, 12, 2, 9), msecs(212)));
7123 testST2(-730_484, SysTime(DateTime(-1999, 1, 1, 12, 2, 9), msecs(212)));
7124 testST2(-730_485, SysTime(DateTime(-2000, 12, 31, 12, 2, 9), msecs(212)));
7125 testST2(-730_850, SysTime(DateTime(-2000, 1, 1, 12, 2, 9), msecs(212)));
7126 testST2(-731_215, SysTime(DateTime(-2001, 1, 1, 12, 2, 9), msecs(212)));
7127
7128 testST2(-734_502, SysTime(DateTime(-2010, 1, 1, 12, 2, 9), msecs(212)));
7129 testST2(-734_472, SysTime(DateTime(-2010, 1, 31, 12, 2, 9), msecs(212)));
7130 testST2(-734_471, SysTime(DateTime(-2010, 2, 1, 12, 2, 9), msecs(212)));
7131 testST2(-734_444, SysTime(DateTime(-2010, 2, 28, 12, 2, 9), msecs(212)));
7132 testST2(-734_443, SysTime(DateTime(-2010, 3, 1, 12, 2, 9), msecs(212)));
7133 testST2(-734_413, SysTime(DateTime(-2010, 3, 31, 12, 2, 9), msecs(212)));
7134 testST2(-734_412, SysTime(DateTime(-2010, 4, 1, 12, 2, 9), msecs(212)));
7135 testST2(-734_383, SysTime(DateTime(-2010, 4, 30, 12, 2, 9), msecs(212)));
7136 testST2(-734_382, SysTime(DateTime(-2010, 5, 1, 12, 2, 9), msecs(212)));
7137 testST2(-734_352, SysTime(DateTime(-2010, 5, 31, 12, 2, 9), msecs(212)));
7138 testST2(-734_351, SysTime(DateTime(-2010, 6, 1, 12, 2, 9), msecs(212)));
7139 testST2(-734_322, SysTime(DateTime(-2010, 6, 30, 12, 2, 9), msecs(212)));
7140 testST2(-734_321, SysTime(DateTime(-2010, 7, 1, 12, 2, 9), msecs(212)));
7141 testST2(-734_291, SysTime(DateTime(-2010, 7, 31, 12, 2, 9), msecs(212)));
7142 testST2(-734_290, SysTime(DateTime(-2010, 8, 1, 12, 2, 9), msecs(212)));
7143 testST2(-734_260, SysTime(DateTime(-2010, 8, 31, 12, 2, 9), msecs(212)));
7144 testST2(-734_259, SysTime(DateTime(-2010, 9, 1, 12, 2, 9), msecs(212)));
7145 testST2(-734_230, SysTime(DateTime(-2010, 9, 30, 12, 2, 9), msecs(212)));
7146 testST2(-734_229, SysTime(DateTime(-2010, 10, 1, 12, 2, 9), msecs(212)));
7147 testST2(-734_199, SysTime(DateTime(-2010, 10, 31, 12, 2, 9), msecs(212)));
7148 testST2(-734_198, SysTime(DateTime(-2010, 11, 1, 12, 2, 9), msecs(212)));
7149 testST2(-734_169, SysTime(DateTime(-2010, 11, 30, 12, 2, 9), msecs(212)));
7150 testST2(-734_168, SysTime(DateTime(-2010, 12, 1, 12, 2, 9), msecs(212)));
7151 testST2(-734_138, SysTime(DateTime(-2010, 12, 31, 12, 2, 9), msecs(212)));
7152
7153 testST2(-735_202, SysTime(DateTime(-2012, 2, 1, 12, 2, 9), msecs(212)));
7154 testST2(-735_175, SysTime(DateTime(-2012, 2, 28, 12, 2, 9), msecs(212)));
7155 testST2(-735_174, SysTime(DateTime(-2012, 2, 29, 12, 2, 9), msecs(212)));
7156 testST2(-735_173, SysTime(DateTime(-2012, 3, 1, 12, 2, 9), msecs(212)));
7157
7158 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7159 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7160 static assert(!__traits(compiles, cst.dayOfGregorianCal = 7));
7161 //static assert(!__traits(compiles, ist.dayOfGregorianCal = 7));
7162 }
7163
7164
7165 /++
7166 The ISO 8601 week of the year that this $(LREF SysTime) is in.
7167
7168 See_Also:
7169 $(HTTP en.wikipedia.org/wiki/ISO_week_date, ISO Week Date).
7170 +/
7171 @property ubyte isoWeek() @safe const nothrow
7172 {
7173 return (cast(Date) this).isoWeek;
7174 }
7175
7176 ///
7177 @safe unittest
7178 {
7179 import std.datetime.date : Date;
7180
7181 auto st = SysTime(Date(1999, 7, 6));
7182 const cst = SysTime(Date(2010, 5, 1));
7183 immutable ist = SysTime(Date(2015, 10, 10));
7184
7185 assert(st.isoWeek == 27);
7186 assert(cst.isoWeek == 17);
7187 assert(ist.isoWeek == 41);
7188 }
7189
7190
7191 /++
7192 $(LREF SysTime) for the last day in the month that this Date is in.
7193 The time portion of endOfMonth is always 23:59:59.9999999.
7194 +/
7195 @property SysTime endOfMonth() @safe const nothrow
7196 {
7197 immutable hnsecs = adjTime;
7198 immutable days = getUnitsFromHNSecs!"days"(hnsecs);
7199
7200 auto date = Date(cast(int) days + 1).endOfMonth;
7201 auto newDays = date.dayOfGregorianCal - 1;
7202 long theTimeHNSecs;
7203
7204 if (newDays < 0)
7205 {
7206 theTimeHNSecs = -1;
7207 ++newDays;
7208 }
7209 else
7210 theTimeHNSecs = convert!("days", "hnsecs")(1) - 1;
7211
7212 immutable newDaysHNSecs = convert!("days", "hnsecs")(newDays);
7213
7214 auto retval = SysTime(this._stdTime, this._timezone);
7215 retval.adjTime = newDaysHNSecs + theTimeHNSecs;
7216
7217 return retval;
7218 }
7219
7220 ///
7221 @safe unittest
7222 {
7223 import core.time : msecs, usecs, hnsecs;
7224 import std.datetime.date : DateTime;
7225
7226 assert(SysTime(DateTime(1999, 1, 6, 0, 0, 0)).endOfMonth ==
7227 SysTime(DateTime(1999, 1, 31, 23, 59, 59), hnsecs(9_999_999)));
7228
7229 assert(SysTime(DateTime(1999, 2, 7, 19, 30, 0), msecs(24)).endOfMonth ==
7230 SysTime(DateTime(1999, 2, 28, 23, 59, 59), hnsecs(9_999_999)));
7231
7232 assert(SysTime(DateTime(2000, 2, 7, 5, 12, 27), usecs(5203)).endOfMonth ==
7233 SysTime(DateTime(2000, 2, 29, 23, 59, 59), hnsecs(9_999_999)));
7234
7235 assert(SysTime(DateTime(2000, 6, 4, 12, 22, 9), hnsecs(12345)).endOfMonth ==
7236 SysTime(DateTime(2000, 6, 30, 23, 59, 59), hnsecs(9_999_999)));
7237 }
7238
7239 @safe unittest
7240 {
7241 // Test A.D.
7242 assert(SysTime(Date(1999, 1, 1)).endOfMonth == SysTime(DateTime(1999, 1, 31, 23, 59, 59), hnsecs(9_999_999)));
7243 assert(SysTime(Date(1999, 2, 1)).endOfMonth == SysTime(DateTime(1999, 2, 28, 23, 59, 59), hnsecs(9_999_999)));
7244 assert(SysTime(Date(2000, 2, 1)).endOfMonth == SysTime(DateTime(2000, 2, 29, 23, 59, 59), hnsecs(9_999_999)));
7245 assert(SysTime(Date(1999, 3, 1)).endOfMonth == SysTime(DateTime(1999, 3, 31, 23, 59, 59), hnsecs(9_999_999)));
7246 assert(SysTime(Date(1999, 4, 1)).endOfMonth == SysTime(DateTime(1999, 4, 30, 23, 59, 59), hnsecs(9_999_999)));
7247 assert(SysTime(Date(1999, 5, 1)).endOfMonth == SysTime(DateTime(1999, 5, 31, 23, 59, 59), hnsecs(9_999_999)));
7248 assert(SysTime(Date(1999, 6, 1)).endOfMonth == SysTime(DateTime(1999, 6, 30, 23, 59, 59), hnsecs(9_999_999)));
7249 assert(SysTime(Date(1999, 7, 1)).endOfMonth == SysTime(DateTime(1999, 7, 31, 23, 59, 59), hnsecs(9_999_999)));
7250 assert(SysTime(Date(1999, 8, 1)).endOfMonth == SysTime(DateTime(1999, 8, 31, 23, 59, 59), hnsecs(9_999_999)));
7251 assert(SysTime(Date(1999, 9, 1)).endOfMonth == SysTime(DateTime(1999, 9, 30, 23, 59, 59), hnsecs(9_999_999)));
7252 assert(SysTime(Date(1999, 10, 1)).endOfMonth == SysTime(DateTime(1999, 10, 31, 23, 59, 59), hnsecs(9_999_999)));
7253 assert(SysTime(Date(1999, 11, 1)).endOfMonth == SysTime(DateTime(1999, 11, 30, 23, 59, 59), hnsecs(9_999_999)));
7254 assert(SysTime(Date(1999, 12, 1)).endOfMonth == SysTime(DateTime(1999, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
7255
7256 // Test B.C.
7257 assert(SysTime(Date(-1999, 1, 1)).endOfMonth == SysTime(DateTime(-1999, 1, 31, 23, 59, 59), hnsecs(9_999_999)));
7258 assert(SysTime(Date(-1999, 2, 1)).endOfMonth == SysTime(DateTime(-1999, 2, 28, 23, 59, 59), hnsecs(9_999_999)));
7259 assert(SysTime(Date(-2000, 2, 1)).endOfMonth == SysTime(DateTime(-2000, 2, 29, 23, 59, 59), hnsecs(9_999_999)));
7260 assert(SysTime(Date(-1999, 3, 1)).endOfMonth == SysTime(DateTime(-1999, 3, 31, 23, 59, 59), hnsecs(9_999_999)));
7261 assert(SysTime(Date(-1999, 4, 1)).endOfMonth == SysTime(DateTime(-1999, 4, 30, 23, 59, 59), hnsecs(9_999_999)));
7262 assert(SysTime(Date(-1999, 5, 1)).endOfMonth == SysTime(DateTime(-1999, 5, 31, 23, 59, 59), hnsecs(9_999_999)));
7263 assert(SysTime(Date(-1999, 6, 1)).endOfMonth == SysTime(DateTime(-1999, 6, 30, 23, 59, 59), hnsecs(9_999_999)));
7264 assert(SysTime(Date(-1999, 7, 1)).endOfMonth == SysTime(DateTime(-1999, 7, 31, 23, 59, 59), hnsecs(9_999_999)));
7265 assert(SysTime(Date(-1999, 8, 1)).endOfMonth == SysTime(DateTime(-1999, 8, 31, 23, 59, 59), hnsecs(9_999_999)));
7266 assert(SysTime(Date(-1999, 9, 1)).endOfMonth == SysTime(DateTime(-1999, 9, 30, 23, 59, 59), hnsecs(9_999_999)));
7267 assert(SysTime(Date(-1999, 10, 1)).endOfMonth ==
7268 SysTime(DateTime(-1999, 10, 31, 23, 59, 59), hnsecs(9_999_999)));
7269 assert(SysTime(Date(-1999, 11, 1)).endOfMonth ==
7270 SysTime(DateTime(-1999, 11, 30, 23, 59, 59), hnsecs(9_999_999)));
7271 assert(SysTime(Date(-1999, 12, 1)).endOfMonth ==
7272 SysTime(DateTime(-1999, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
7273
7274 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7275 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7276 assert(cst.endOfMonth == SysTime(DateTime(1999, 7, 31, 23, 59, 59), hnsecs(9_999_999)));
7277 //assert(ist.endOfMonth == SysTime(DateTime(1999, 7, 31, 23, 59, 59), hnsecs(9_999_999)));
7278 }
7279
7280
7281 /++
7282 The last day in the month that this $(LREF SysTime) is in.
7283 +/
7284 @property ubyte daysInMonth() @safe const nothrow
7285 {
7286 return Date(dayOfGregorianCal).daysInMonth;
7287 }
7288
7289 ///
7290 @safe unittest
7291 {
7292 import std.datetime.date : DateTime;
7293
7294 assert(SysTime(DateTime(1999, 1, 6, 0, 0, 0)).daysInMonth == 31);
7295 assert(SysTime(DateTime(1999, 2, 7, 19, 30, 0)).daysInMonth == 28);
7296 assert(SysTime(DateTime(2000, 2, 7, 5, 12, 27)).daysInMonth == 29);
7297 assert(SysTime(DateTime(2000, 6, 4, 12, 22, 9)).daysInMonth == 30);
7298 }
7299
7300 @safe unittest
7301 {
7302 // Test A.D.
7303 assert(SysTime(DateTime(1999, 1, 1, 12, 1, 13)).daysInMonth == 31);
7304 assert(SysTime(DateTime(1999, 2, 1, 17, 13, 12)).daysInMonth == 28);
7305 assert(SysTime(DateTime(2000, 2, 1, 13, 2, 12)).daysInMonth == 29);
7306 assert(SysTime(DateTime(1999, 3, 1, 12, 13, 12)).daysInMonth == 31);
7307 assert(SysTime(DateTime(1999, 4, 1, 12, 6, 13)).daysInMonth == 30);
7308 assert(SysTime(DateTime(1999, 5, 1, 15, 13, 12)).daysInMonth == 31);
7309 assert(SysTime(DateTime(1999, 6, 1, 13, 7, 12)).daysInMonth == 30);
7310 assert(SysTime(DateTime(1999, 7, 1, 12, 13, 17)).daysInMonth == 31);
7311 assert(SysTime(DateTime(1999, 8, 1, 12, 3, 13)).daysInMonth == 31);
7312 assert(SysTime(DateTime(1999, 9, 1, 12, 13, 12)).daysInMonth == 30);
7313 assert(SysTime(DateTime(1999, 10, 1, 13, 19, 12)).daysInMonth == 31);
7314 assert(SysTime(DateTime(1999, 11, 1, 12, 13, 17)).daysInMonth == 30);
7315 assert(SysTime(DateTime(1999, 12, 1, 12, 52, 13)).daysInMonth == 31);
7316
7317 // Test B.C.
7318 assert(SysTime(DateTime(-1999, 1, 1, 12, 1, 13)).daysInMonth == 31);
7319 assert(SysTime(DateTime(-1999, 2, 1, 7, 13, 12)).daysInMonth == 28);
7320 assert(SysTime(DateTime(-2000, 2, 1, 13, 2, 12)).daysInMonth == 29);
7321 assert(SysTime(DateTime(-1999, 3, 1, 12, 13, 12)).daysInMonth == 31);
7322 assert(SysTime(DateTime(-1999, 4, 1, 12, 6, 13)).daysInMonth == 30);
7323 assert(SysTime(DateTime(-1999, 5, 1, 5, 13, 12)).daysInMonth == 31);
7324 assert(SysTime(DateTime(-1999, 6, 1, 13, 7, 12)).daysInMonth == 30);
7325 assert(SysTime(DateTime(-1999, 7, 1, 12, 13, 17)).daysInMonth == 31);
7326 assert(SysTime(DateTime(-1999, 8, 1, 12, 3, 13)).daysInMonth == 31);
7327 assert(SysTime(DateTime(-1999, 9, 1, 12, 13, 12)).daysInMonth == 30);
7328 assert(SysTime(DateTime(-1999, 10, 1, 13, 19, 12)).daysInMonth == 31);
7329 assert(SysTime(DateTime(-1999, 11, 1, 12, 13, 17)).daysInMonth == 30);
7330 assert(SysTime(DateTime(-1999, 12, 1, 12, 52, 13)).daysInMonth == 31);
7331
7332 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7333 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7334 assert(cst.daysInMonth == 31);
7335 //assert(ist.daysInMonth == 31);
7336 }
7337
7338
7339 /++
7340 Whether the current year is a date in A.D.
7341 +/
7342 @property bool isAD() @safe const nothrow
7343 {
7344 return adjTime >= 0;
7345 }
7346
7347 ///
7348 @safe unittest
7349 {
7350 import std.datetime.date : DateTime;
7351
7352 assert(SysTime(DateTime(1, 1, 1, 12, 7, 0)).isAD);
7353 assert(SysTime(DateTime(2010, 12, 31, 0, 0, 0)).isAD);
7354 assert(!SysTime(DateTime(0, 12, 31, 23, 59, 59)).isAD);
7355 assert(!SysTime(DateTime(-2010, 1, 1, 2, 2, 2)).isAD);
7356 }
7357
7358 @safe unittest
7359 {
7360 assert(SysTime(DateTime(2010, 7, 4, 12, 0, 9)).isAD);
7361 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).isAD);
7362 assert(!SysTime(DateTime(0, 12, 31, 23, 59, 59)).isAD);
7363 assert(!SysTime(DateTime(0, 1, 1, 23, 59, 59)).isAD);
7364 assert(!SysTime(DateTime(-1, 1, 1, 23 ,59 ,59)).isAD);
7365 assert(!SysTime(DateTime(-2010, 7, 4, 12, 2, 2)).isAD);
7366
7367 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7368 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7369 assert(cst.isAD);
7370 //assert(ist.isAD);
7371 }
7372
7373
7374 /++
7375 The $(HTTP en.wikipedia.org/wiki/Julian_day, Julian day)
7376 for this $(LREF SysTime) at the given time. For example,
7377 prior to noon, 1996-03-31 would be the Julian day number 2_450_173, so
7378 this function returns 2_450_173, while from noon onward, the Julian
7379 day number would be 2_450_174, so this function returns 2_450_174.
7380 +/
7381 @property long julianDay() @safe const nothrow
7382 {
7383 immutable jd = dayOfGregorianCal + 1_721_425;
7384 return hour < 12 ? jd - 1 : jd;
7385 }
7386
7387 @safe unittest
7388 {
7389 assert(SysTime(DateTime(-4713, 11, 24, 0, 0, 0)).julianDay == -1);
7390 assert(SysTime(DateTime(-4713, 11, 24, 12, 0, 0)).julianDay == 0);
7391
7392 assert(SysTime(DateTime(0, 12, 31, 0, 0, 0)).julianDay == 1_721_424);
7393 assert(SysTime(DateTime(0, 12, 31, 12, 0, 0)).julianDay == 1_721_425);
7394
7395 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).julianDay == 1_721_425);
7396 assert(SysTime(DateTime(1, 1, 1, 12, 0, 0)).julianDay == 1_721_426);
7397
7398 assert(SysTime(DateTime(1582, 10, 15, 0, 0, 0)).julianDay == 2_299_160);
7399 assert(SysTime(DateTime(1582, 10, 15, 12, 0, 0)).julianDay == 2_299_161);
7400
7401 assert(SysTime(DateTime(1858, 11, 17, 0, 0, 0)).julianDay == 2_400_000);
7402 assert(SysTime(DateTime(1858, 11, 17, 12, 0, 0)).julianDay == 2_400_001);
7403
7404 assert(SysTime(DateTime(1982, 1, 4, 0, 0, 0)).julianDay == 2_444_973);
7405 assert(SysTime(DateTime(1982, 1, 4, 12, 0, 0)).julianDay == 2_444_974);
7406
7407 assert(SysTime(DateTime(1996, 3, 31, 0, 0, 0)).julianDay == 2_450_173);
7408 assert(SysTime(DateTime(1996, 3, 31, 12, 0, 0)).julianDay == 2_450_174);
7409
7410 assert(SysTime(DateTime(2010, 8, 24, 0, 0, 0)).julianDay == 2_455_432);
7411 assert(SysTime(DateTime(2010, 8, 24, 12, 0, 0)).julianDay == 2_455_433);
7412
7413 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7414 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7415 assert(cst.julianDay == 2_451_366);
7416 //assert(ist.julianDay == 2_451_366);
7417 }
7418
7419
7420 /++
7421 The modified $(HTTP en.wikipedia.org/wiki/Julian_day, Julian day) for
7422 any time on this date (since, the modified Julian day changes at
7423 midnight).
7424 +/
7425 @property long modJulianDay() @safe const nothrow
7426 {
7427 return dayOfGregorianCal + 1_721_425 - 2_400_001;
7428 }
7429
7430 @safe unittest
7431 {
7432 assert(SysTime(DateTime(1858, 11, 17, 0, 0, 0)).modJulianDay == 0);
7433 assert(SysTime(DateTime(1858, 11, 17, 12, 0, 0)).modJulianDay == 0);
7434
7435 assert(SysTime(DateTime(2010, 8, 24, 0, 0, 0)).modJulianDay == 55_432);
7436 assert(SysTime(DateTime(2010, 8, 24, 12, 0, 0)).modJulianDay == 55_432);
7437
7438 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7439 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7440 assert(cst.modJulianDay == 51_365);
7441 //assert(ist.modJulianDay == 51_365);
7442 }
7443
7444
7445 /++
7446 Returns a $(REF Date,std,datetime,date) equivalent to this $(LREF SysTime).
7447 +/
7448 Date opCast(T)() @safe const nothrow
7449 if (is(Unqual!T == Date))
7450 {
7451 return Date(dayOfGregorianCal);
7452 }
7453
7454 @safe unittest
7455 {
7456 assert(cast(Date) SysTime(Date(1999, 7, 6)) == Date(1999, 7, 6));
7457 assert(cast(Date) SysTime(Date(2000, 12, 31)) == Date(2000, 12, 31));
7458 assert(cast(Date) SysTime(Date(2001, 1, 1)) == Date(2001, 1, 1));
7459
7460 assert(cast(Date) SysTime(DateTime(1999, 7, 6, 12, 10, 9)) == Date(1999, 7, 6));
7461 assert(cast(Date) SysTime(DateTime(2000, 12, 31, 13, 11, 10)) == Date(2000, 12, 31));
7462 assert(cast(Date) SysTime(DateTime(2001, 1, 1, 14, 12, 11)) == Date(2001, 1, 1));
7463
7464 assert(cast(Date) SysTime(Date(-1999, 7, 6)) == Date(-1999, 7, 6));
7465 assert(cast(Date) SysTime(Date(-2000, 12, 31)) == Date(-2000, 12, 31));
7466 assert(cast(Date) SysTime(Date(-2001, 1, 1)) == Date(-2001, 1, 1));
7467
7468 assert(cast(Date) SysTime(DateTime(-1999, 7, 6, 12, 10, 9)) == Date(-1999, 7, 6));
7469 assert(cast(Date) SysTime(DateTime(-2000, 12, 31, 13, 11, 10)) == Date(-2000, 12, 31));
7470 assert(cast(Date) SysTime(DateTime(-2001, 1, 1, 14, 12, 11)) == Date(-2001, 1, 1));
7471
7472 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7473 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7474 assert(cast(Date) cst != Date.init);
7475 //assert(cast(Date) ist != Date.init);
7476 }
7477
7478
7479 /++
7480 Returns a $(REF DateTime,std,datetime,date) equivalent to this
7481 $(LREF SysTime).
7482 +/
7483 DateTime opCast(T)() @safe const nothrow
7484 if (is(Unqual!T == DateTime))
7485 {
7486 try
7487 {
7488 auto hnsecs = adjTime;
7489 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
7490
7491 if (hnsecs < 0)
7492 {
7493 hnsecs += convert!("hours", "hnsecs")(24);
7494 --days;
7495 }
7496
7497 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
7498 immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
7499 immutable second = getUnitsFromHNSecs!"seconds"(hnsecs);
7500
7501 return DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour, cast(int) minute, cast(int) second));
7502 }
7503 catch (Exception e)
7504 assert(0, "Either DateTime's constructor or TimeOfDay's constructor threw.");
7505 }
7506
7507 @safe unittest
7508 {
7509 assert(cast(DateTime) SysTime(DateTime(1, 1, 6, 7, 12, 22)) == DateTime(1, 1, 6, 7, 12, 22));
7510 assert(cast(DateTime) SysTime(DateTime(1, 1, 6, 7, 12, 22), msecs(22)) == DateTime(1, 1, 6, 7, 12, 22));
7511 assert(cast(DateTime) SysTime(Date(1999, 7, 6)) == DateTime(1999, 7, 6, 0, 0, 0));
7512 assert(cast(DateTime) SysTime(Date(2000, 12, 31)) == DateTime(2000, 12, 31, 0, 0, 0));
7513 assert(cast(DateTime) SysTime(Date(2001, 1, 1)) == DateTime(2001, 1, 1, 0, 0, 0));
7514
7515 assert(cast(DateTime) SysTime(DateTime(1999, 7, 6, 12, 10, 9)) == DateTime(1999, 7, 6, 12, 10, 9));
7516 assert(cast(DateTime) SysTime(DateTime(2000, 12, 31, 13, 11, 10)) == DateTime(2000, 12, 31, 13, 11, 10));
7517 assert(cast(DateTime) SysTime(DateTime(2001, 1, 1, 14, 12, 11)) == DateTime(2001, 1, 1, 14, 12, 11));
7518
7519 assert(cast(DateTime) SysTime(DateTime(-1, 1, 6, 7, 12, 22)) == DateTime(-1, 1, 6, 7, 12, 22));
7520 assert(cast(DateTime) SysTime(DateTime(-1, 1, 6, 7, 12, 22), msecs(22)) == DateTime(-1, 1, 6, 7, 12, 22));
7521 assert(cast(DateTime) SysTime(Date(-1999, 7, 6)) == DateTime(-1999, 7, 6, 0, 0, 0));
7522 assert(cast(DateTime) SysTime(Date(-2000, 12, 31)) == DateTime(-2000, 12, 31, 0, 0, 0));
7523 assert(cast(DateTime) SysTime(Date(-2001, 1, 1)) == DateTime(-2001, 1, 1, 0, 0, 0));
7524
7525 assert(cast(DateTime) SysTime(DateTime(-1999, 7, 6, 12, 10, 9)) == DateTime(-1999, 7, 6, 12, 10, 9));
7526 assert(cast(DateTime) SysTime(DateTime(-2000, 12, 31, 13, 11, 10)) == DateTime(-2000, 12, 31, 13, 11, 10));
7527 assert(cast(DateTime) SysTime(DateTime(-2001, 1, 1, 14, 12, 11)) == DateTime(-2001, 1, 1, 14, 12, 11));
7528
7529 assert(cast(DateTime) SysTime(DateTime(2011, 1, 13, 8, 17, 2), msecs(296), LocalTime()) ==
7530 DateTime(2011, 1, 13, 8, 17, 2));
7531
7532 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7533 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7534 assert(cast(DateTime) cst != DateTime.init);
7535 //assert(cast(DateTime) ist != DateTime.init);
7536 }
7537
7538
7539 /++
7540 Returns a $(REF TimeOfDay,std,datetime,date) equivalent to this
7541 $(LREF SysTime).
7542 +/
7543 TimeOfDay opCast(T)() @safe const nothrow
7544 if (is(Unqual!T == TimeOfDay))
7545 {
7546 try
7547 {
7548 auto hnsecs = adjTime;
7549 hnsecs = removeUnitsFromHNSecs!"days"(hnsecs);
7550
7551 if (hnsecs < 0)
7552 hnsecs += convert!("hours", "hnsecs")(24);
7553
7554 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
7555 immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
7556 immutable second = getUnitsFromHNSecs!"seconds"(hnsecs);
7557
7558 return TimeOfDay(cast(int) hour, cast(int) minute, cast(int) second);
7559 }
7560 catch (Exception e)
7561 assert(0, "TimeOfDay's constructor threw.");
7562 }
7563
7564 @safe unittest
7565 {
7566 assert(cast(TimeOfDay) SysTime(Date(1999, 7, 6)) == TimeOfDay(0, 0, 0));
7567 assert(cast(TimeOfDay) SysTime(Date(2000, 12, 31)) == TimeOfDay(0, 0, 0));
7568 assert(cast(TimeOfDay) SysTime(Date(2001, 1, 1)) == TimeOfDay(0, 0, 0));
7569
7570 assert(cast(TimeOfDay) SysTime(DateTime(1999, 7, 6, 12, 10, 9)) == TimeOfDay(12, 10, 9));
7571 assert(cast(TimeOfDay) SysTime(DateTime(2000, 12, 31, 13, 11, 10)) == TimeOfDay(13, 11, 10));
7572 assert(cast(TimeOfDay) SysTime(DateTime(2001, 1, 1, 14, 12, 11)) == TimeOfDay(14, 12, 11));
7573
7574 assert(cast(TimeOfDay) SysTime(Date(-1999, 7, 6)) == TimeOfDay(0, 0, 0));
7575 assert(cast(TimeOfDay) SysTime(Date(-2000, 12, 31)) == TimeOfDay(0, 0, 0));
7576 assert(cast(TimeOfDay) SysTime(Date(-2001, 1, 1)) == TimeOfDay(0, 0, 0));
7577
7578 assert(cast(TimeOfDay) SysTime(DateTime(-1999, 7, 6, 12, 10, 9)) == TimeOfDay(12, 10, 9));
7579 assert(cast(TimeOfDay) SysTime(DateTime(-2000, 12, 31, 13, 11, 10)) == TimeOfDay(13, 11, 10));
7580 assert(cast(TimeOfDay) SysTime(DateTime(-2001, 1, 1, 14, 12, 11)) == TimeOfDay(14, 12, 11));
7581
7582 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7583 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7584 assert(cast(TimeOfDay) cst != TimeOfDay.init);
7585 //assert(cast(TimeOfDay) ist != TimeOfDay.init);
7586 }
7587
7588
7589 // Temporary hack until bug http://d.puremagic.com/issues/show_bug.cgi?id=4867 is fixed.
7590 // This allows assignment from const(SysTime) to SysTime.
7591 // It may be a good idea to keep it though, since casting from a type to itself
7592 // should be allowed, and it doesn't work without this opCast() since opCast()
7593 // has already been defined for other types.
7594 SysTime opCast(T)() @safe const pure nothrow
7595 if (is(Unqual!T == SysTime))
7596 {
7597 return SysTime(_stdTime, _timezone);
7598 }
7599
7600
7601 /++
7602 Converts this $(LREF SysTime) to a string with the format
7603 YYYYMMDDTHHMMSS.FFFFFFFTZ (where F is fractional seconds and TZ is time
7604 zone).
7605
7606 Note that the number of digits in the fractional seconds varies with the
7607 number of fractional seconds. It's a maximum of 7 (which would be
7608 hnsecs), but only has as many as are necessary to hold the correct value
7609 (so no trailing zeroes), and if there are no fractional seconds, then
7610 there is no decimal point.
7611
7612 If this $(LREF SysTime)'s time zone is
7613 $(REF LocalTime,std,datetime,timezone), then TZ is empty. If its time
7614 zone is $(D UTC), then it is "Z". Otherwise, it is the offset from UTC
7615 (e.g. +0100 or -0700). Note that the offset from UTC is $(I not) enough
7616 to uniquely identify the time zone.
7617
7618 Time zone offsets will be in the form +HHMM or -HHMM.
7619
7620 $(RED Warning:
7621 Previously, toISOString did the same as $(LREF toISOExtString) and
7622 generated +HH:MM or -HH:MM for the time zone when it was not
7623 $(REF LocalTime,std,datetime,timezone) or
7624 $(REF UTC,std,datetime,timezone), which is not in conformance with
7625 ISO 8601 for the non-extended string format. This has now been
7626 fixed. However, for now, fromISOString will continue to accept the
7627 extended format for the time zone so that any code which has been
7628 writing out the result of toISOString to read in later will continue
7629 to work. The current behavior will be kept until July 2019 at which
7630 point, fromISOString will be fixed to be standards compliant.)
7631 +/
7632 string toISOString() @safe const nothrow
7633 {
7634 try
7635 {
7636 immutable adjustedTime = adjTime;
7637 long hnsecs = adjustedTime;
7638
7639 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
7640
7641 if (hnsecs < 0)
7642 {
7643 hnsecs += convert!("hours", "hnsecs")(24);
7644 --days;
7645 }
7646
7647 auto hour = splitUnitsFromHNSecs!"hours"(hnsecs);
7648 auto minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
7649 auto second = splitUnitsFromHNSecs!"seconds"(hnsecs);
7650
7651 auto dateTime = DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour,
7652 cast(int) minute, cast(int) second));
7653 auto fracSecStr = fracSecsToISOString(cast(int) hnsecs);
7654
7655 if (_timezone is LocalTime())
7656 return dateTime.toISOString() ~ fracSecStr;
7657
7658 if (_timezone is UTC())
7659 return dateTime.toISOString() ~ fracSecStr ~ "Z";
7660
7661 immutable utcOffset = dur!"hnsecs"(adjustedTime - stdTime);
7662
7663 return format("%s%s%s",
7664 dateTime.toISOString(),
7665 fracSecStr,
7666 SimpleTimeZone.toISOExtString(utcOffset));
7667 }
7668 catch (Exception e)
7669 assert(0, "format() threw.");
7670 }
7671
7672 ///
7673 @safe unittest
7674 {
7675 import core.time : msecs, hnsecs;
7676 import std.datetime.date : DateTime;
7677
7678 assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toISOString() ==
7679 "20100704T070612");
7680
7681 assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(24)).toISOString() ==
7682 "19981225T021500.024");
7683
7684 assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toISOString() ==
7685 "00000105T230959");
7686
7687 assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toISOString() ==
7688 "-00040105T000002.052092");
7689 }
7690
7691 @safe unittest
7692 {
7693 // Test A.D.
7694 assert(SysTime(DateTime.init, UTC()).toISOString() == "00010101T000000Z");
7695 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1), UTC()).toISOString() == "00010101T000000.0000001Z");
7696
7697 assert(SysTime(DateTime(9, 12, 4, 0, 0, 0)).toISOString() == "00091204T000000");
7698 assert(SysTime(DateTime(99, 12, 4, 5, 6, 12)).toISOString() == "00991204T050612");
7699 assert(SysTime(DateTime(999, 12, 4, 13, 44, 59)).toISOString() == "09991204T134459");
7700 assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59)).toISOString() == "99990704T235959");
7701 assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1)).toISOString() == "+100001020T010101");
7702
7703 assert(SysTime(DateTime(9, 12, 4, 0, 0, 0), msecs(42)).toISOString() == "00091204T000000.042");
7704 assert(SysTime(DateTime(99, 12, 4, 5, 6, 12), msecs(100)).toISOString() == "00991204T050612.1");
7705 assert(SysTime(DateTime(999, 12, 4, 13, 44, 59), usecs(45020)).toISOString() == "09991204T134459.04502");
7706 assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59), hnsecs(12)).toISOString() == "99990704T235959.0000012");
7707 assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1), hnsecs(507890)).toISOString() == "+100001020T010101.050789");
7708
7709 assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
7710 new immutable SimpleTimeZone(dur!"minutes"(-360))).toISOString() ==
7711 "20121221T121212-06:00");
7712
7713 assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
7714 new immutable SimpleTimeZone(dur!"minutes"(420))).toISOString() ==
7715 "20121221T121212+07:00");
7716
7717 // Test B.C.
7718 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toISOString() ==
7719 "00001231T235959.9999999Z");
7720 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1), UTC()).toISOString() == "00001231T235959.0000001Z");
7721 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), UTC()).toISOString() == "00001231T235959Z");
7722
7723 assert(SysTime(DateTime(0, 12, 4, 0, 12, 4)).toISOString() == "00001204T001204");
7724 assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0)).toISOString() == "-00091204T000000");
7725 assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12)).toISOString() == "-00991204T050612");
7726 assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59)).toISOString() == "-09991204T134459");
7727 assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59)).toISOString() == "-99990704T235959");
7728 assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1)).toISOString() == "-100001020T010101");
7729
7730 assert(SysTime(DateTime(0, 12, 4, 0, 0, 0), msecs(7)).toISOString() == "00001204T000000.007");
7731 assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0), msecs(42)).toISOString() == "-00091204T000000.042");
7732 assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12), msecs(100)).toISOString() == "-00991204T050612.1");
7733 assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59), usecs(45020)).toISOString() == "-09991204T134459.04502");
7734 assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59), hnsecs(12)).toISOString() == "-99990704T235959.0000012");
7735 assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1), hnsecs(507890)).toISOString() == "-100001020T010101.050789");
7736
7737 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7738 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7739 assert(cast(TimeOfDay) cst != TimeOfDay.init);
7740 //assert(cast(TimeOfDay) ist != TimeOfDay.init);
7741 }
7742
7743
7744
7745 /++
7746 Converts this $(LREF SysTime) to a string with the format
7747 YYYY-MM-DDTHH:MM:SS.FFFFFFFTZ (where F is fractional seconds and TZ
7748 is the time zone).
7749
7750 Note that the number of digits in the fractional seconds varies with the
7751 number of fractional seconds. It's a maximum of 7 (which would be
7752 hnsecs), but only has as many as are necessary to hold the correct value
7753 (so no trailing zeroes), and if there are no fractional seconds, then
7754 there is no decimal point.
7755
7756 If this $(LREF SysTime)'s time zone is
7757 $(REF LocalTime,std,datetime,timezone), then TZ is empty. If its time
7758 zone is $(D UTC), then it is "Z". Otherwise, it is the offset from UTC
7759 (e.g. +01:00 or -07:00). Note that the offset from UTC is $(I not)
7760 enough to uniquely identify the time zone.
7761
7762 Time zone offsets will be in the form +HH:MM or -HH:MM.
7763 +/
7764 string toISOExtString() @safe const nothrow
7765 {
7766 try
7767 {
7768 immutable adjustedTime = adjTime;
7769 long hnsecs = adjustedTime;
7770
7771 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
7772
7773 if (hnsecs < 0)
7774 {
7775 hnsecs += convert!("hours", "hnsecs")(24);
7776 --days;
7777 }
7778
7779 auto hour = splitUnitsFromHNSecs!"hours"(hnsecs);
7780 auto minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
7781 auto second = splitUnitsFromHNSecs!"seconds"(hnsecs);
7782
7783 auto dateTime = DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour,
7784 cast(int) minute, cast(int) second));
7785 auto fracSecStr = fracSecsToISOString(cast(int) hnsecs);
7786
7787 if (_timezone is LocalTime())
7788 return dateTime.toISOExtString() ~ fracSecStr;
7789
7790 if (_timezone is UTC())
7791 return dateTime.toISOExtString() ~ fracSecStr ~ "Z";
7792
7793 immutable utcOffset = dur!"hnsecs"(adjustedTime - stdTime);
7794
7795 return format("%s%s%s",
7796 dateTime.toISOExtString(),
7797 fracSecStr,
7798 SimpleTimeZone.toISOExtString(utcOffset));
7799 }
7800 catch (Exception e)
7801 assert(0, "format() threw.");
7802 }
7803
7804 ///
7805 @safe unittest
7806 {
7807 import core.time : msecs, hnsecs;
7808 import std.datetime.date : DateTime;
7809
7810 assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toISOExtString() ==
7811 "2010-07-04T07:06:12");
7812
7813 assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(24)).toISOExtString() ==
7814 "1998-12-25T02:15:00.024");
7815
7816 assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toISOExtString() ==
7817 "0000-01-05T23:09:59");
7818
7819 assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toISOExtString() ==
7820 "-0004-01-05T00:00:02.052092");
7821 }
7822
7823 @safe unittest
7824 {
7825 // Test A.D.
7826 assert(SysTime(DateTime.init, UTC()).toISOExtString() == "0001-01-01T00:00:00Z");
7827 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1), UTC()).toISOExtString() ==
7828 "0001-01-01T00:00:00.0000001Z");
7829
7830 assert(SysTime(DateTime(9, 12, 4, 0, 0, 0)).toISOExtString() == "0009-12-04T00:00:00");
7831 assert(SysTime(DateTime(99, 12, 4, 5, 6, 12)).toISOExtString() == "0099-12-04T05:06:12");
7832 assert(SysTime(DateTime(999, 12, 4, 13, 44, 59)).toISOExtString() == "0999-12-04T13:44:59");
7833 assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59)).toISOExtString() == "9999-07-04T23:59:59");
7834 assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1)).toISOExtString() == "+10000-10-20T01:01:01");
7835
7836 assert(SysTime(DateTime(9, 12, 4, 0, 0, 0), msecs(42)).toISOExtString() == "0009-12-04T00:00:00.042");
7837 assert(SysTime(DateTime(99, 12, 4, 5, 6, 12), msecs(100)).toISOExtString() == "0099-12-04T05:06:12.1");
7838 assert(SysTime(DateTime(999, 12, 4, 13, 44, 59), usecs(45020)).toISOExtString() == "0999-12-04T13:44:59.04502");
7839 assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59), hnsecs(12)).toISOExtString() == "9999-07-04T23:59:59.0000012");
7840 assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1), hnsecs(507890)).toISOExtString() ==
7841 "+10000-10-20T01:01:01.050789");
7842
7843 assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
7844 new immutable SimpleTimeZone(dur!"minutes"(-360))).toISOExtString() ==
7845 "2012-12-21T12:12:12-06:00");
7846
7847 assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
7848 new immutable SimpleTimeZone(dur!"minutes"(420))).toISOExtString() ==
7849 "2012-12-21T12:12:12+07:00");
7850
7851 // Test B.C.
7852 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toISOExtString() ==
7853 "0000-12-31T23:59:59.9999999Z");
7854 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1), UTC()).toISOExtString() ==
7855 "0000-12-31T23:59:59.0000001Z");
7856 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), UTC()).toISOExtString() == "0000-12-31T23:59:59Z");
7857
7858 assert(SysTime(DateTime(0, 12, 4, 0, 12, 4)).toISOExtString() == "0000-12-04T00:12:04");
7859 assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0)).toISOExtString() == "-0009-12-04T00:00:00");
7860 assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12)).toISOExtString() == "-0099-12-04T05:06:12");
7861 assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59)).toISOExtString() == "-0999-12-04T13:44:59");
7862 assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59)).toISOExtString() == "-9999-07-04T23:59:59");
7863 assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1)).toISOExtString() == "-10000-10-20T01:01:01");
7864
7865 assert(SysTime(DateTime(0, 12, 4, 0, 0, 0), msecs(7)).toISOExtString() == "0000-12-04T00:00:00.007");
7866 assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0), msecs(42)).toISOExtString() == "-0009-12-04T00:00:00.042");
7867 assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12), msecs(100)).toISOExtString() == "-0099-12-04T05:06:12.1");
7868 assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59), usecs(45020)).toISOExtString() ==
7869 "-0999-12-04T13:44:59.04502");
7870 assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59), hnsecs(12)).toISOExtString() ==
7871 "-9999-07-04T23:59:59.0000012");
7872 assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1), hnsecs(507890)).toISOExtString() ==
7873 "-10000-10-20T01:01:01.050789");
7874
7875 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7876 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7877 assert(cast(TimeOfDay) cst != TimeOfDay.init);
7878 //assert(cast(TimeOfDay) ist != TimeOfDay.init);
7879 }
7880
7881 /++
7882 Converts this $(LREF SysTime) to a string with the format
7883 YYYY-Mon-DD HH:MM:SS.FFFFFFFTZ (where F is fractional seconds and TZ
7884 is the time zone).
7885
7886 Note that the number of digits in the fractional seconds varies with the
7887 number of fractional seconds. It's a maximum of 7 (which would be
7888 hnsecs), but only has as many as are necessary to hold the correct value
7889 (so no trailing zeroes), and if there are no fractional seconds, then
7890 there is no decimal point.
7891
7892 If this $(LREF SysTime)'s time zone is
7893 $(REF LocalTime,std,datetime,timezone), then TZ is empty. If its time
7894 zone is $(D UTC), then it is "Z". Otherwise, it is the offset from UTC
7895 (e.g. +01:00 or -07:00). Note that the offset from UTC is $(I not)
7896 enough to uniquely identify the time zone.
7897
7898 Time zone offsets will be in the form +HH:MM or -HH:MM.
7899 +/
7900 string toSimpleString() @safe const nothrow
7901 {
7902 try
7903 {
7904 immutable adjustedTime = adjTime;
7905 long hnsecs = adjustedTime;
7906
7907 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
7908
7909 if (hnsecs < 0)
7910 {
7911 hnsecs += convert!("hours", "hnsecs")(24);
7912 --days;
7913 }
7914
7915 auto hour = splitUnitsFromHNSecs!"hours"(hnsecs);
7916 auto minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
7917 auto second = splitUnitsFromHNSecs!"seconds"(hnsecs);
7918
7919 auto dateTime = DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour,
7920 cast(int) minute, cast(int) second));
7921 auto fracSecStr = fracSecsToISOString(cast(int) hnsecs);
7922
7923 if (_timezone is LocalTime())
7924 return dateTime.toSimpleString() ~ fracSecStr;
7925
7926 if (_timezone is UTC())
7927 return dateTime.toSimpleString() ~ fracSecStr ~ "Z";
7928
7929 immutable utcOffset = dur!"hnsecs"(adjustedTime - stdTime);
7930
7931 return format("%s%s%s",
7932 dateTime.toSimpleString(),
7933 fracSecStr,
7934 SimpleTimeZone.toISOExtString(utcOffset));
7935 }
7936 catch (Exception e)
7937 assert(0, "format() threw.");
7938 }
7939
7940 ///
7941 @safe unittest
7942 {
7943 import core.time : msecs, hnsecs;
7944 import std.datetime.date : DateTime;
7945
7946 assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toSimpleString() ==
7947 "2010-Jul-04 07:06:12");
7948
7949 assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(24)).toSimpleString() ==
7950 "1998-Dec-25 02:15:00.024");
7951
7952 assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toSimpleString() ==
7953 "0000-Jan-05 23:09:59");
7954
7955 assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toSimpleString() ==
7956 "-0004-Jan-05 00:00:02.052092");
7957 }
7958
7959 @safe unittest
7960 {
7961 // Test A.D.
7962 assert(SysTime(DateTime.init, UTC()).toString() == "0001-Jan-01 00:00:00Z");
7963 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1), UTC()).toString() == "0001-Jan-01 00:00:00.0000001Z");
7964
7965 assert(SysTime(DateTime(9, 12, 4, 0, 0, 0)).toSimpleString() == "0009-Dec-04 00:00:00");
7966 assert(SysTime(DateTime(99, 12, 4, 5, 6, 12)).toSimpleString() == "0099-Dec-04 05:06:12");
7967 assert(SysTime(DateTime(999, 12, 4, 13, 44, 59)).toSimpleString() == "0999-Dec-04 13:44:59");
7968 assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59)).toSimpleString() == "9999-Jul-04 23:59:59");
7969 assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1)).toSimpleString() == "+10000-Oct-20 01:01:01");
7970
7971 assert(SysTime(DateTime(9, 12, 4, 0, 0, 0), msecs(42)).toSimpleString() == "0009-Dec-04 00:00:00.042");
7972 assert(SysTime(DateTime(99, 12, 4, 5, 6, 12), msecs(100)).toSimpleString() == "0099-Dec-04 05:06:12.1");
7973 assert(SysTime(DateTime(999, 12, 4, 13, 44, 59), usecs(45020)).toSimpleString() ==
7974 "0999-Dec-04 13:44:59.04502");
7975 assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59), hnsecs(12)).toSimpleString() ==
7976 "9999-Jul-04 23:59:59.0000012");
7977 assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1), hnsecs(507890)).toSimpleString() ==
7978 "+10000-Oct-20 01:01:01.050789");
7979
7980 assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
7981 new immutable SimpleTimeZone(dur!"minutes"(-360))).toSimpleString() ==
7982 "2012-Dec-21 12:12:12-06:00");
7983
7984 assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
7985 new immutable SimpleTimeZone(dur!"minutes"(420))).toSimpleString() ==
7986 "2012-Dec-21 12:12:12+07:00");
7987
7988 // Test B.C.
7989 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toSimpleString() ==
7990 "0000-Dec-31 23:59:59.9999999Z");
7991 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1), UTC()).toSimpleString() ==
7992 "0000-Dec-31 23:59:59.0000001Z");
7993 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), UTC()).toSimpleString() == "0000-Dec-31 23:59:59Z");
7994
7995 assert(SysTime(DateTime(0, 12, 4, 0, 12, 4)).toSimpleString() == "0000-Dec-04 00:12:04");
7996 assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0)).toSimpleString() == "-0009-Dec-04 00:00:00");
7997 assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12)).toSimpleString() == "-0099-Dec-04 05:06:12");
7998 assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59)).toSimpleString() == "-0999-Dec-04 13:44:59");
7999 assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59)).toSimpleString() == "-9999-Jul-04 23:59:59");
8000 assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1)).toSimpleString() == "-10000-Oct-20 01:01:01");
8001
8002 assert(SysTime(DateTime(0, 12, 4, 0, 0, 0), msecs(7)).toSimpleString() == "0000-Dec-04 00:00:00.007");
8003 assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0), msecs(42)).toSimpleString() == "-0009-Dec-04 00:00:00.042");
8004 assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12), msecs(100)).toSimpleString() == "-0099-Dec-04 05:06:12.1");
8005 assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59), usecs(45020)).toSimpleString() ==
8006 "-0999-Dec-04 13:44:59.04502");
8007 assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59), hnsecs(12)).toSimpleString() ==
8008 "-9999-Jul-04 23:59:59.0000012");
8009 assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1), hnsecs(507890)).toSimpleString() ==
8010 "-10000-Oct-20 01:01:01.050789");
8011
8012 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8013 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8014 assert(cast(TimeOfDay) cst != TimeOfDay.init);
8015 //assert(cast(TimeOfDay) ist != TimeOfDay.init);
8016 }
8017
8018
8019 /++
8020 Converts this $(LREF SysTime) to a string.
8021
8022 This function exists to make it easy to convert a $(LREF SysTime) to a
8023 string for code that does not care what the exact format is - just that
8024 it presents the information in a clear manner. It also makes it easy to
8025 simply convert a $(LREF SysTime) to a string when using functions such
8026 as `to!string`, `format`, or `writeln` which use toString to convert
8027 user-defined types. So, it is unlikely that much code will call
8028 toString directly.
8029
8030 The format of the string is purposefully unspecified, and code that
8031 cares about the format of the string should use `toISOString`,
8032 `toISOExtString`, `toSimpleString`, or some other custom formatting
8033 function that explicitly generates the format that the code needs. The
8034 reason is that the code is then clear about what format it's using,
8035 making it less error-prone to maintain the code and interact with other
8036 software that consumes the generated strings. It's for this same reason
8037 that $(LREF SysTime) has no `fromString` function, whereas it does have
8038 `fromISOString`, `fromISOExtString`, and `fromSimpleString`.
8039
8040 The format returned by toString may or may not change in the future.
8041 +/
8042 string toString() @safe const nothrow
8043 {
8044 return toSimpleString();
8045 }
8046
8047 @safe unittest
8048 {
8049 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8050 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8051 //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8052 assert(st.toString());
8053 assert(cst.toString());
8054 //assert(ist.toString());
8055 }
8056
8057
8058 /++
8059 Creates a $(LREF SysTime) from a string with the format
8060 YYYYMMDDTHHMMSS.FFFFFFFTZ (where F is fractional seconds is the time
8061 zone). Whitespace is stripped from the given string.
8062
8063 The exact format is exactly as described in $(D toISOString) except that
8064 trailing zeroes are permitted - including having fractional seconds with
8065 all zeroes. However, a decimal point with nothing following it is
8066 invalid. Also, while $(LREF toISOString) will never generate a string
8067 with more than 7 digits in the fractional seconds (because that's the
8068 limit with hecto-nanosecond precision), it will allow more than 7 digits
8069 in order to read strings from other sources that have higher precision
8070 (however, any digits beyond 7 will be truncated).
8071
8072 If there is no time zone in the string, then
8073 $(REF LocalTime,std,datetime,timezone) is used. If the time zone is "Z",
8074 then $(D UTC) is used. Otherwise, a
8075 $(REF SimpleTimeZone,std,datetime,timezone) which corresponds to the
8076 given offset from UTC is used. To get the returned $(LREF SysTime) to be
8077 a particular time zone, pass in that time zone and the $(LREF SysTime)
8078 to be returned will be converted to that time zone (though it will still
8079 be read in as whatever time zone is in its string).
8080
8081 The accepted formats for time zone offsets are +HH, -HH, +HHMM, and
8082 -HHMM.
8083
8084 $(RED Warning:
8085 Previously, $(LREF toISOString) did the same as
8086 $(LREF toISOExtString) and generated +HH:MM or -HH:MM for the time
8087 zone when it was not $(REF LocalTime,std,datetime,timezone) or
8088 $(REF UTC,std,datetime,timezone), which is not in conformance with
8089 ISO 8601 for the non-extended string format. This has now been
8090 fixed. However, for now, fromISOString will continue to accept the
8091 extended format for the time zone so that any code which has been
8092 writing out the result of toISOString to read in later will continue
8093 to work. The current behavior will be kept until July 2019 at which
8094 point, fromISOString will be fixed to be standards compliant.)
8095
8096 Params:
8097 isoString = A string formatted in the ISO format for dates and times.
8098 tz = The time zone to convert the given time to (no
8099 conversion occurs if null).
8100
8101 Throws:
8102 $(REF DateTimeException,std,datetime,date) if the given string is
8103 not in the ISO format or if the resulting $(LREF SysTime) would not
8104 be valid.
8105 +/
8106 static SysTime fromISOString(S)(in S isoString, immutable TimeZone tz = null) @safe
8107 if (isSomeString!S)
8108 {
8109 import std.algorithm.searching : startsWith, find;
8110 import std.conv : to;
8111 import std.string : strip;
8112
8113 auto dstr = to!dstring(strip(isoString));
8114 immutable skipFirst = dstr.startsWith('+', '-') != 0;
8115
8116 auto found = (skipFirst ? dstr[1..$] : dstr).find('.', 'Z', '+', '-');
8117 auto dateTimeStr = dstr[0 .. $ - found[0].length];
8118
8119 dstring fracSecStr;
8120 dstring zoneStr;
8121
8122 if (found[1] != 0)
8123 {
8124 if (found[1] == 1)
8125 {
8126 auto foundTZ = found[0].find('Z', '+', '-');
8127
8128 if (foundTZ[1] != 0)
8129 {
8130 fracSecStr = found[0][0 .. $ - foundTZ[0].length];
8131 zoneStr = foundTZ[0];
8132 }
8133 else
8134 fracSecStr = found[0];
8135 }
8136 else
8137 zoneStr = found[0];
8138 }
8139
8140 try
8141 {
8142 auto dateTime = DateTime.fromISOString(dateTimeStr);
8143 auto fracSec = fracSecsFromISOString(fracSecStr);
8144 Rebindable!(immutable TimeZone) parsedZone;
8145
8146 if (zoneStr.empty)
8147 parsedZone = LocalTime();
8148 else if (zoneStr == "Z")
8149 parsedZone = UTC();
8150 else
8151 {
8152 try
8153 parsedZone = SimpleTimeZone.fromISOString(zoneStr);
8154 catch (DateTimeException dte)
8155 parsedZone = SimpleTimeZone.fromISOExtString(zoneStr);
8156 }
8157
8158 auto retval = SysTime(dateTime, fracSec, parsedZone);
8159
8160 if (tz !is null)
8161 retval.timezone = tz;
8162
8163 return retval;
8164 }
8165 catch (DateTimeException dte)
8166 throw new DateTimeException(format("Invalid ISO String: %s", isoString));
8167 }
8168
8169 ///
8170 @safe unittest
8171 {
8172 import core.time : hours, msecs, usecs, hnsecs;
8173 import std.datetime.date : DateTime;
8174 import std.datetime.timezone : SimpleTimeZone, UTC;
8175
8176 assert(SysTime.fromISOString("20100704T070612") ==
8177 SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
8178
8179 assert(SysTime.fromISOString("19981225T021500.007") ==
8180 SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(7)));
8181
8182 assert(SysTime.fromISOString("00000105T230959.00002") ==
8183 SysTime(DateTime(0, 1, 5, 23, 9, 59), usecs(20)));
8184
8185 assert(SysTime.fromISOString("20130207T043937.000050392") ==
8186 SysTime(DateTime(2013, 2, 7, 4, 39, 37), hnsecs(503)));
8187
8188 assert(SysTime.fromISOString("-00040105T000002") ==
8189 SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
8190
8191 assert(SysTime.fromISOString(" 20100704T070612 ") ==
8192 SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
8193
8194 assert(SysTime.fromISOString("20100704T070612Z") ==
8195 SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
8196
8197 assert(SysTime.fromISOString("20100704T070612-0800") ==
8198 SysTime(DateTime(2010, 7, 4, 7, 6, 12),
8199 new immutable SimpleTimeZone(hours(-8))));
8200
8201 assert(SysTime.fromISOString("20100704T070612+0800") ==
8202 SysTime(DateTime(2010, 7, 4, 7, 6, 12),
8203 new immutable SimpleTimeZone(hours(8))));
8204 }
8205
8206 @safe unittest
8207 {
8208 foreach (str; ["", "20100704000000", "20100704 000000", "20100704t000000",
8209 "20100704T000000.", "20100704T000000.A", "20100704T000000.Z",
8210 "20100704T000000.0000000A", "20100704T000000.00000000A",
8211 "20100704T000000+", "20100704T000000-", "20100704T000000:",
8212 "20100704T000000-:", "20100704T000000+:", "20100704T000000-1:",
8213 "20100704T000000+1:", "20100704T000000+1:0",
8214 "20100704T000000-12.00", "20100704T000000+12.00",
8215 "20100704T000000-8", "20100704T000000+8",
8216 "20100704T000000-800", "20100704T000000+800",
8217 "20100704T000000-080", "20100704T000000+080",
8218 "20100704T000000-2400", "20100704T000000+2400",
8219 "20100704T000000-1260", "20100704T000000+1260",
8220 "20100704T000000.0-8", "20100704T000000.0+8",
8221 "20100704T000000.0-800", "20100704T000000.0+800",
8222 "20100704T000000.0-080", "20100704T000000.0+080",
8223 "20100704T000000.0-2400", "20100704T000000.0+2400",
8224 "20100704T000000.0-1260", "20100704T000000.0+1260",
8225 "20100704T000000-8:00", "20100704T000000+8:00",
8226 "20100704T000000-08:0", "20100704T000000+08:0",
8227 "20100704T000000-24:00", "20100704T000000+24:00",
8228 "20100704T000000-12:60", "20100704T000000+12:60",
8229 "20100704T000000.0-8:00", "20100704T000000.0+8:00",
8230 "20100704T000000.0-08:0", "20100704T000000.0+08:0",
8231 "20100704T000000.0-24:00", "20100704T000000.0+24:00",
8232 "20100704T000000.0-12:60", "20100704T000000.0+12:60",
8233 "2010-07-0400:00:00", "2010-07-04 00:00:00",
8234 "2010-07-04t00:00:00", "2010-07-04T00:00:00.",
8235 "2010-Jul-0400:00:00", "2010-Jul-04 00:00:00", "2010-Jul-04t00:00:00",
8236 "2010-Jul-04T00:00:00", "2010-Jul-04 00:00:00.",
8237 "2010-12-22T172201", "2010-Dec-22 17:22:01"])
8238 {
8239 assertThrown!DateTimeException(SysTime.fromISOString(str), format("[%s]", str));
8240 }
8241
8242 static void test(string str, SysTime st, size_t line = __LINE__)
8243 {
8244 if (SysTime.fromISOString(str) != st)
8245 throw new AssertError("unittest failure", __FILE__, line);
8246 }
8247
8248 test("20101222T172201", SysTime(DateTime(2010, 12, 22, 17, 22, 01)));
8249 test("19990706T123033", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8250 test("-19990706T123033", SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
8251 test("+019990706T123033", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8252 test("19990706T123033 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8253 test(" 19990706T123033", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8254 test(" 19990706T123033 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8255
8256 test("19070707T121212.0", SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
8257 test("19070707T121212.0000000", SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
8258 test("19070707T121212.0000001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), hnsecs(1)));
8259 test("20100704T000000.00000000", SysTime(Date(2010, 07, 04)));
8260 test("20100704T000000.00000009", SysTime(Date(2010, 07, 04)));
8261 test("20100704T000000.00000019", SysTime(DateTime(2010, 07, 04), hnsecs(1)));
8262 test("19070707T121212.000001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), usecs(1)));
8263 test("19070707T121212.0000010", SysTime(DateTime(1907, 07, 07, 12, 12, 12), usecs(1)));
8264 test("19070707T121212.001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), msecs(1)));
8265 test("19070707T121212.0010000", SysTime(DateTime(1907, 07, 07, 12, 12, 12), msecs(1)));
8266
8267 auto west60 = new immutable SimpleTimeZone(hours(-1));
8268 auto west90 = new immutable SimpleTimeZone(minutes(-90));
8269 auto west480 = new immutable SimpleTimeZone(hours(-8));
8270 auto east60 = new immutable SimpleTimeZone(hours(1));
8271 auto east90 = new immutable SimpleTimeZone(minutes(90));
8272 auto east480 = new immutable SimpleTimeZone(hours(8));
8273
8274 test("20101222T172201Z", SysTime(DateTime(2010, 12, 22, 17, 22, 01), UTC()));
8275 test("20101222T172201-0100", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60));
8276 test("20101222T172201-01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60));
8277 test("20101222T172201-0130", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west90));
8278 test("20101222T172201-0800", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west480));
8279 test("20101222T172201+0100", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
8280 test("20101222T172201+01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
8281 test("20101222T172201+0130", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90));
8282 test("20101222T172201+0800", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east480));
8283
8284 test("20101103T065106.57159Z", SysTime(DateTime(2010, 11, 3, 6, 51, 6), hnsecs(5715900), UTC()));
8285 test("20101222T172201.23412Z", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_341_200), UTC()));
8286 test("20101222T172201.23112-0100", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_311_200), west60));
8287 test("20101222T172201.45-01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), west60));
8288 test("20101222T172201.1-0130", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_000_000), west90));
8289 test("20101222T172201.55-0800", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(5_500_000), west480));
8290 test("20101222T172201.1234567+0100", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_234_567), east60));
8291 test("20101222T172201.0+01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
8292 test("20101222T172201.0000000+0130", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90));
8293 test("20101222T172201.45+0800", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), east480));
8294
8295 // @@@DEPRECATED_2019-07@@@
8296 // This isn't deprecated per se, but that text will make it so that it
8297 // pops up when deprecations are moved along around July 2019. At that
8298 // time, we will update fromISOString so that it is conformant with ISO
8299 // 8601, and it will no longer accept ISO extended time zones (it does
8300 // currently because of issue #15654 - toISOString used to incorrectly
8301 // use the ISO extended time zone format). These tests will then start
8302 // failing will need to be updated accordingly. Also, the notes about
8303 // this issue in toISOString and fromISOString's documentation will need
8304 // to be removed.
8305 test("20101222T172201-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60));
8306 test("20101222T172201-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west90));
8307 test("20101222T172201-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west480));
8308 test("20101222T172201+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
8309 test("20101222T172201+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90));
8310 test("20101222T172201+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east480));
8311
8312 test("20101222T172201.23112-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_311_200), west60));
8313 test("20101222T172201.1-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_000_000), west90));
8314 test("20101222T172201.55-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(5_500_000), west480));
8315 test("20101222T172201.1234567+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_234_567), east60));
8316 test("20101222T172201.0000000+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90));
8317 test("20101222T172201.45+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), east480));
8318 }
8319
8320 // bug# 17801
8321 @safe unittest
8322 {
8323 import std.conv : to;
8324 import std.meta : AliasSeq;
8325 foreach (C; AliasSeq!(char, wchar, dchar))
8326 {
8327 foreach (S; AliasSeq!(C[], const(C)[], immutable(C)[]))
8328 {
8329 assert(SysTime.fromISOString(to!S("20121221T141516Z")) ==
8330 SysTime(DateTime(2012, 12, 21, 14, 15, 16), UTC()));
8331 }
8332 }
8333 }
8334
8335
8336 /++
8337 Creates a $(LREF SysTime) from a string with the format
8338 YYYY-MM-DDTHH:MM:SS.FFFFFFFTZ (where F is fractional seconds is the
8339 time zone). Whitespace is stripped from the given string.
8340
8341 The exact format is exactly as described in $(D toISOExtString)
8342 except that trailing zeroes are permitted - including having fractional
8343 seconds with all zeroes. However, a decimal point with nothing following
8344 it is invalid. Also, while $(LREF toISOExtString) will never generate a
8345 string with more than 7 digits in the fractional seconds (because that's
8346 the limit with hecto-nanosecond precision), it will allow more than 7
8347 digits in order to read strings from other sources that have higher
8348 precision (however, any digits beyond 7 will be truncated).
8349
8350 If there is no time zone in the string, then
8351 $(REF LocalTime,std,datetime,timezone) is used. If the time zone is "Z",
8352 then $(D UTC) is used. Otherwise, a
8353 $(REF SimpleTimeZone,std,datetime,timezone) which corresponds to the
8354 given offset from UTC is used. To get the returned $(LREF SysTime) to be
8355 a particular time zone, pass in that time zone and the $(LREF SysTime)
8356 to be returned will be converted to that time zone (though it will still
8357 be read in as whatever time zone is in its string).
8358
8359 The accepted formats for time zone offsets are +HH, -HH, +HH:MM, and
8360 -HH:MM.
8361
8362 Params:
8363 isoExtString = A string formatted in the ISO Extended format for
8364 dates and times.
8365 tz = The time zone to convert the given time to (no
8366 conversion occurs if null).
8367
8368 Throws:
8369 $(REF DateTimeException,std,datetime,date) if the given string is
8370 not in the ISO format or if the resulting $(LREF SysTime) would not
8371 be valid.
8372 +/
8373 static SysTime fromISOExtString(S)(in S isoExtString, immutable TimeZone tz = null) @safe
8374 if (isSomeString!(S))
8375 {
8376 import std.algorithm.searching : countUntil, find;
8377 import std.conv : to;
8378 import std.string : strip;
8379
8380 auto dstr = to!dstring(strip(isoExtString));
8381
8382 auto tIndex = dstr.countUntil('T');
8383 enforce(tIndex != -1, new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
8384
8385 auto found = dstr[tIndex + 1 .. $].find('.', 'Z', '+', '-');
8386 auto dateTimeStr = dstr[0 .. $ - found[0].length];
8387
8388 dstring fracSecStr;
8389 dstring zoneStr;
8390
8391 if (found[1] != 0)
8392 {
8393 if (found[1] == 1)
8394 {
8395 auto foundTZ = found[0].find('Z', '+', '-');
8396
8397 if (foundTZ[1] != 0)
8398 {
8399 fracSecStr = found[0][0 .. $ - foundTZ[0].length];
8400 zoneStr = foundTZ[0];
8401 }
8402 else
8403 fracSecStr = found[0];
8404 }
8405 else
8406 zoneStr = found[0];
8407 }
8408
8409 try
8410 {
8411 auto dateTime = DateTime.fromISOExtString(dateTimeStr);
8412 auto fracSec = fracSecsFromISOString(fracSecStr);
8413 Rebindable!(immutable TimeZone) parsedZone;
8414
8415 if (zoneStr.empty)
8416 parsedZone = LocalTime();
8417 else if (zoneStr == "Z")
8418 parsedZone = UTC();
8419 else
8420 parsedZone = SimpleTimeZone.fromISOExtString(zoneStr);
8421
8422 auto retval = SysTime(dateTime, fracSec, parsedZone);
8423
8424 if (tz !is null)
8425 retval.timezone = tz;
8426
8427 return retval;
8428 }
8429 catch (DateTimeException dte)
8430 throw new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString));
8431 }
8432
8433 ///
8434 @safe unittest
8435 {
8436 import core.time : hours, msecs, usecs, hnsecs;
8437 import std.datetime.date : DateTime;
8438 import std.datetime.timezone : SimpleTimeZone, UTC;
8439
8440 assert(SysTime.fromISOExtString("2010-07-04T07:06:12") ==
8441 SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
8442
8443 assert(SysTime.fromISOExtString("1998-12-25T02:15:00.007") ==
8444 SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(7)));
8445
8446 assert(SysTime.fromISOExtString("0000-01-05T23:09:59.00002") ==
8447 SysTime(DateTime(0, 1, 5, 23, 9, 59), usecs(20)));
8448
8449 assert(SysTime.fromISOExtString("2013-02-07T04:39:37.000050392") ==
8450 SysTime(DateTime(2013, 2, 7, 4, 39, 37), hnsecs(503)));
8451
8452 assert(SysTime.fromISOExtString("-0004-01-05T00:00:02") ==
8453 SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
8454
8455 assert(SysTime.fromISOExtString(" 2010-07-04T07:06:12 ") ==
8456 SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
8457
8458 assert(SysTime.fromISOExtString("2010-07-04T07:06:12Z") ==
8459 SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
8460
8461 assert(SysTime.fromISOExtString("2010-07-04T07:06:12-08:00") ==
8462 SysTime(DateTime(2010, 7, 4, 7, 6, 12),
8463 new immutable SimpleTimeZone(hours(-8))));
8464 assert(SysTime.fromISOExtString("2010-07-04T07:06:12+08:00") ==
8465 SysTime(DateTime(2010, 7, 4, 7, 6, 12),
8466 new immutable SimpleTimeZone(hours(8))));
8467 }
8468
8469 @safe unittest
8470 {
8471 foreach (str; ["", "20100704000000", "20100704 000000",
8472 "20100704t000000", "20100704T000000.", "20100704T000000.0",
8473 "2010-07:0400:00:00", "2010-07-04 00:00:00",
8474 "2010-07-04 00:00:00", "2010-07-04t00:00:00",
8475 "2010-07-04T00:00:00.", "2010-07-04T00:00:00.A", "2010-07-04T00:00:00.Z",
8476 "2010-07-04T00:00:00.0000000A", "2010-07-04T00:00:00.00000000A",
8477 "2010-07-04T00:00:00+", "2010-07-04T00:00:00-",
8478 "2010-07-04T00:00:00:", "2010-07-04T00:00:00-:", "2010-07-04T00:00:00+:",
8479 "2010-07-04T00:00:00-1:", "2010-07-04T00:00:00+1:", "2010-07-04T00:00:00+1:0",
8480 "2010-07-04T00:00:00-12.00", "2010-07-04T00:00:00+12.00",
8481 "2010-07-04T00:00:00-8", "2010-07-04T00:00:00+8",
8482 "20100704T000000-800", "20100704T000000+800",
8483 "20100704T000000-080", "20100704T000000+080",
8484 "20100704T000000-2400", "20100704T000000+2400",
8485 "20100704T000000-1260", "20100704T000000+1260",
8486 "20100704T000000.0-800", "20100704T000000.0+800",
8487 "20100704T000000.0-8", "20100704T000000.0+8",
8488 "20100704T000000.0-080", "20100704T000000.0+080",
8489 "20100704T000000.0-2400", "20100704T000000.0+2400",
8490 "20100704T000000.0-1260", "20100704T000000.0+1260",
8491 "2010-07-04T00:00:00-8:00", "2010-07-04T00:00:00+8:00",
8492 "2010-07-04T00:00:00-24:00", "2010-07-04T00:00:00+24:00",
8493 "2010-07-04T00:00:00-12:60", "2010-07-04T00:00:00+12:60",
8494 "2010-07-04T00:00:00.0-8:00", "2010-07-04T00:00:00.0+8:00",
8495 "2010-07-04T00:00:00.0-8", "2010-07-04T00:00:00.0+8",
8496 "2010-07-04T00:00:00.0-24:00", "2010-07-04T00:00:00.0+24:00",
8497 "2010-07-04T00:00:00.0-12:60", "2010-07-04T00:00:00.0+12:60",
8498 "2010-Jul-0400:00:00", "2010-Jul-04t00:00:00",
8499 "2010-Jul-04 00:00:00.", "2010-Jul-04 00:00:00.0",
8500 "20101222T172201", "2010-Dec-22 17:22:01"])
8501 {
8502 assertThrown!DateTimeException(SysTime.fromISOExtString(str), format("[%s]", str));
8503 }
8504
8505 static void test(string str, SysTime st, size_t line = __LINE__)
8506 {
8507 if (SysTime.fromISOExtString(str) != st)
8508 throw new AssertError("unittest failure", __FILE__, line);
8509 }
8510
8511 test("2010-12-22T17:22:01", SysTime(DateTime(2010, 12, 22, 17, 22, 01)));
8512 test("1999-07-06T12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8513 test("-1999-07-06T12:30:33", SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
8514 test("+01999-07-06T12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8515 test("1999-07-06T12:30:33 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8516 test(" 1999-07-06T12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8517 test(" 1999-07-06T12:30:33 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8518
8519 test("1907-07-07T12:12:12.0", SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
8520 test("1907-07-07T12:12:12.0000000", SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
8521 test("1907-07-07T12:12:12.0000001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), hnsecs(1)));
8522 test("2010-07-04T00:00:00.00000000", SysTime(Date(2010, 07, 04)));
8523 test("2010-07-04T00:00:00.00000009", SysTime(Date(2010, 07, 04)));
8524 test("2010-07-04T00:00:00.00000019", SysTime(DateTime(2010, 07, 04), hnsecs(1)));
8525 test("1907-07-07T12:12:12.000001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), usecs(1)));
8526 test("1907-07-07T12:12:12.0000010", SysTime(DateTime(1907, 07, 07, 12, 12, 12), usecs(1)));
8527 test("1907-07-07T12:12:12.001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), msecs(1)));
8528 test("1907-07-07T12:12:12.0010000", SysTime(DateTime(1907, 07, 07, 12, 12, 12), msecs(1)));
8529
8530 auto west60 = new immutable SimpleTimeZone(hours(-1));
8531 auto west90 = new immutable SimpleTimeZone(minutes(-90));
8532 auto west480 = new immutable SimpleTimeZone(hours(-8));
8533 auto east60 = new immutable SimpleTimeZone(hours(1));
8534 auto east90 = new immutable SimpleTimeZone(minutes(90));
8535 auto east480 = new immutable SimpleTimeZone(hours(8));
8536
8537 test("2010-12-22T17:22:01Z", SysTime(DateTime(2010, 12, 22, 17, 22, 01), UTC()));
8538 test("2010-12-22T17:22:01-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60));
8539 test("2010-12-22T17:22:01-01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60));
8540 test("2010-12-22T17:22:01-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west90));
8541 test("2010-12-22T17:22:01-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west480));
8542 test("2010-12-22T17:22:01+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
8543 test("2010-12-22T17:22:01+01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
8544 test("2010-12-22T17:22:01+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90));
8545 test("2010-12-22T17:22:01+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east480));
8546
8547 test("2010-11-03T06:51:06.57159Z", SysTime(DateTime(2010, 11, 3, 6, 51, 6), hnsecs(5715900), UTC()));
8548 test("2010-12-22T17:22:01.23412Z", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_341_200), UTC()));
8549 test("2010-12-22T17:22:01.23112-01:00",
8550 SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_311_200), west60));
8551 test("2010-12-22T17:22:01.45-01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), west60));
8552 test("2010-12-22T17:22:01.1-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_000_000), west90));
8553 test("2010-12-22T17:22:01.55-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(5_500_000), west480));
8554 test("2010-12-22T17:22:01.1234567+01:00",
8555 SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_234_567), east60));
8556 test("2010-12-22T17:22:01.0+01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
8557 test("2010-12-22T17:22:01.0000000+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90));
8558 test("2010-12-22T17:22:01.45+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), east480));
8559 }
8560
8561 // bug# 17801
8562 @safe unittest
8563 {
8564 import std.conv : to;
8565 import std.meta : AliasSeq;
8566 foreach (C; AliasSeq!(char, wchar, dchar))
8567 {
8568 foreach (S; AliasSeq!(C[], const(C)[], immutable(C)[]))
8569 {
8570 assert(SysTime.fromISOExtString(to!S("2012-12-21T14:15:16Z")) ==
8571 SysTime(DateTime(2012, 12, 21, 14, 15, 16), UTC()));
8572 }
8573 }
8574 }
8575
8576
8577 /++
8578 Creates a $(LREF SysTime) from a string with the format
8579 YYYY-MM-DD HH:MM:SS.FFFFFFFTZ (where F is fractional seconds is the
8580 time zone). Whitespace is stripped from the given string.
8581
8582 The exact format is exactly as described in $(D toSimpleString) except
8583 that trailing zeroes are permitted - including having fractional seconds
8584 with all zeroes. However, a decimal point with nothing following it is
8585 invalid. Also, while $(LREF toSimpleString) will never generate a
8586 string with more than 7 digits in the fractional seconds (because that's
8587 the limit with hecto-nanosecond precision), it will allow more than 7
8588 digits in order to read strings from other sources that have higher
8589 precision (however, any digits beyond 7 will be truncated).
8590
8591 If there is no time zone in the string, then
8592 $(REF LocalTime,std,datetime,timezone) is used. If the time zone is "Z",
8593 then $(D UTC) is used. Otherwise, a
8594 $(REF SimpleTimeZone,std,datetime,timezone) which corresponds to the
8595 given offset from UTC is used. To get the returned $(LREF SysTime) to be
8596 a particular time zone, pass in that time zone and the $(LREF SysTime)
8597 to be returned will be converted to that time zone (though it will still
8598 be read in as whatever time zone is in its string).
8599
8600 The accepted formats for time zone offsets are +HH, -HH, +HH:MM, and
8601 -HH:MM.
8602
8603 Params:
8604 simpleString = A string formatted in the way that
8605 $(D toSimpleString) formats dates and times.
8606 tz = The time zone to convert the given time to (no
8607 conversion occurs if null).
8608
8609 Throws:
8610 $(REF DateTimeException,std,datetime,date) if the given string is
8611 not in the ISO format or if the resulting $(LREF SysTime) would not
8612 be valid.
8613 +/
8614 static SysTime fromSimpleString(S)(in S simpleString, immutable TimeZone tz = null) @safe
8615 if (isSomeString!(S))
8616 {
8617 import std.algorithm.searching : countUntil, find;
8618 import std.conv : to;
8619 import std.string : strip;
8620
8621 auto dstr = to!dstring(strip(simpleString));
8622
8623 auto spaceIndex = dstr.countUntil(' ');
8624 enforce(spaceIndex != -1, new DateTimeException(format("Invalid Simple String: %s", simpleString)));
8625
8626 auto found = dstr[spaceIndex + 1 .. $].find('.', 'Z', '+', '-');
8627 auto dateTimeStr = dstr[0 .. $ - found[0].length];
8628
8629 dstring fracSecStr;
8630 dstring zoneStr;
8631
8632 if (found[1] != 0)
8633 {
8634 if (found[1] == 1)
8635 {
8636 auto foundTZ = found[0].find('Z', '+', '-');
8637
8638 if (foundTZ[1] != 0)
8639 {
8640 fracSecStr = found[0][0 .. $ - foundTZ[0].length];
8641 zoneStr = foundTZ[0];
8642 }
8643 else
8644 fracSecStr = found[0];
8645 }
8646 else
8647 zoneStr = found[0];
8648 }
8649
8650 try
8651 {
8652 auto dateTime = DateTime.fromSimpleString(dateTimeStr);
8653 auto fracSec = fracSecsFromISOString(fracSecStr);
8654 Rebindable!(immutable TimeZone) parsedZone;
8655
8656 if (zoneStr.empty)
8657 parsedZone = LocalTime();
8658 else if (zoneStr == "Z")
8659 parsedZone = UTC();
8660 else
8661 parsedZone = SimpleTimeZone.fromISOExtString(zoneStr);
8662
8663 auto retval = SysTime(dateTime, fracSec, parsedZone);
8664
8665 if (tz !is null)
8666 retval.timezone = tz;
8667
8668 return retval;
8669 }
8670 catch (DateTimeException dte)
8671 throw new DateTimeException(format("Invalid Simple String: %s", simpleString));
8672 }
8673
8674 ///
8675 @safe unittest
8676 {
8677 import core.time : hours, msecs, usecs, hnsecs;
8678 import std.datetime.date : DateTime;
8679 import std.datetime.timezone : SimpleTimeZone, UTC;
8680
8681 assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12") ==
8682 SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
8683
8684 assert(SysTime.fromSimpleString("1998-Dec-25 02:15:00.007") ==
8685 SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(7)));
8686
8687 assert(SysTime.fromSimpleString("0000-Jan-05 23:09:59.00002") ==
8688 SysTime(DateTime(0, 1, 5, 23, 9, 59), usecs(20)));
8689
8690 assert(SysTime.fromSimpleString("2013-Feb-07 04:39:37.000050392") ==
8691 SysTime(DateTime(2013, 2, 7, 4, 39, 37), hnsecs(503)));
8692
8693 assert(SysTime.fromSimpleString("-0004-Jan-05 00:00:02") ==
8694 SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
8695
8696 assert(SysTime.fromSimpleString(" 2010-Jul-04 07:06:12 ") ==
8697 SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
8698
8699 assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12Z") ==
8700 SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
8701
8702 assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12-08:00") ==
8703 SysTime(DateTime(2010, 7, 4, 7, 6, 12),
8704 new immutable SimpleTimeZone(hours(-8))));
8705
8706 assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12+08:00") ==
8707 SysTime(DateTime(2010, 7, 4, 7, 6, 12),
8708 new immutable SimpleTimeZone(hours(8))));
8709 }
8710
8711 @safe unittest
8712 {
8713 foreach (str; ["", "20100704000000", "20100704 000000",
8714 "20100704t000000", "20100704T000000.", "20100704T000000.0",
8715 "2010-07-0400:00:00", "2010-07-04 00:00:00", "2010-07-04t00:00:00",
8716 "2010-07-04T00:00:00.", "2010-07-04T00:00:00.0",
8717 "2010-Jul-0400:00:00", "2010-Jul-04t00:00:00", "2010-Jul-04T00:00:00",
8718 "2010-Jul-04 00:00:00.", "2010-Jul-04 00:00:00.A", "2010-Jul-04 00:00:00.Z",
8719 "2010-Jul-04 00:00:00.0000000A", "2010-Jul-04 00:00:00.00000000A",
8720 "2010-Jul-04 00:00:00+", "2010-Jul-04 00:00:00-",
8721 "2010-Jul-04 00:00:00:", "2010-Jul-04 00:00:00-:",
8722 "2010-Jul-04 00:00:00+:", "2010-Jul-04 00:00:00-1:",
8723 "2010-Jul-04 00:00:00+1:", "2010-Jul-04 00:00:00+1:0",
8724 "2010-Jul-04 00:00:00-12.00", "2010-Jul-04 00:00:00+12.00",
8725 "2010-Jul-04 00:00:00-8", "2010-Jul-04 00:00:00+8",
8726 "20100704T000000-800", "20100704T000000+800",
8727 "20100704T000000-080", "20100704T000000+080",
8728 "20100704T000000-2400", "20100704T000000+2400",
8729 "20100704T000000-1260", "20100704T000000+1260",
8730 "20100704T000000.0-800", "20100704T000000.0+800",
8731 "20100704T000000.0-8", "20100704T000000.0+8",
8732 "20100704T000000.0-080", "20100704T000000.0+080",
8733 "20100704T000000.0-2400", "20100704T000000.0+2400",
8734 "20100704T000000.0-1260", "20100704T000000.0+1260",
8735 "2010-Jul-04 00:00:00-8:00", "2010-Jul-04 00:00:00+8:00",
8736 "2010-Jul-04 00:00:00-08:0", "2010-Jul-04 00:00:00+08:0",
8737 "2010-Jul-04 00:00:00-24:00", "2010-Jul-04 00:00:00+24:00",
8738 "2010-Jul-04 00:00:00-12:60", "2010-Jul-04 00:00:00+24:60",
8739 "2010-Jul-04 00:00:00.0-8:00", "2010-Jul-04 00:00:00+8:00",
8740 "2010-Jul-04 00:00:00.0-8", "2010-Jul-04 00:00:00.0+8",
8741 "2010-Jul-04 00:00:00.0-08:0", "2010-Jul-04 00:00:00.0+08:0",
8742 "2010-Jul-04 00:00:00.0-24:00", "2010-Jul-04 00:00:00.0+24:00",
8743 "2010-Jul-04 00:00:00.0-12:60", "2010-Jul-04 00:00:00.0+24:60",
8744 "20101222T172201", "2010-12-22T172201"])
8745 {
8746 assertThrown!DateTimeException(SysTime.fromSimpleString(str), format("[%s]", str));
8747 }
8748
8749 static void test(string str, SysTime st, size_t line = __LINE__)
8750 {
8751 if (SysTime.fromSimpleString(str) != st)
8752 throw new AssertError("unittest failure", __FILE__, line);
8753 }
8754
8755 test("2010-Dec-22 17:22:01", SysTime(DateTime(2010, 12, 22, 17, 22, 01)));
8756 test("1999-Jul-06 12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8757 test("-1999-Jul-06 12:30:33", SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
8758 test("+01999-Jul-06 12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8759 test("1999-Jul-06 12:30:33 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8760 test(" 1999-Jul-06 12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8761 test(" 1999-Jul-06 12:30:33 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8762
8763 test("1907-Jul-07 12:12:12.0", SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
8764 test("1907-Jul-07 12:12:12.0000000", SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
8765 test("2010-Jul-04 00:00:00.00000000", SysTime(Date(2010, 07, 04)));
8766 test("2010-Jul-04 00:00:00.00000009", SysTime(Date(2010, 07, 04)));
8767 test("2010-Jul-04 00:00:00.00000019", SysTime(DateTime(2010, 07, 04), hnsecs(1)));
8768 test("1907-Jul-07 12:12:12.0000001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), hnsecs(1)));
8769 test("1907-Jul-07 12:12:12.000001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), usecs(1)));
8770 test("1907-Jul-07 12:12:12.0000010", SysTime(DateTime(1907, 07, 07, 12, 12, 12), usecs(1)));
8771 test("1907-Jul-07 12:12:12.001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), msecs(1)));
8772 test("1907-Jul-07 12:12:12.0010000", SysTime(DateTime(1907, 07, 07, 12, 12, 12), msecs(1)));
8773
8774 auto west60 = new immutable SimpleTimeZone(hours(-1));
8775 auto west90 = new immutable SimpleTimeZone(minutes(-90));
8776 auto west480 = new immutable SimpleTimeZone(hours(-8));
8777 auto east60 = new immutable SimpleTimeZone(hours(1));
8778 auto east90 = new immutable SimpleTimeZone(minutes(90));
8779 auto east480 = new immutable SimpleTimeZone(hours(8));
8780
8781 test("2010-Dec-22 17:22:01Z", SysTime(DateTime(2010, 12, 22, 17, 22, 01), UTC()));
8782 test("2010-Dec-22 17:22:01-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60));
8783 test("2010-Dec-22 17:22:01-01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60));
8784 test("2010-Dec-22 17:22:01-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west90));
8785 test("2010-Dec-22 17:22:01-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west480));
8786 test("2010-Dec-22 17:22:01+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
8787 test("2010-Dec-22 17:22:01+01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
8788 test("2010-Dec-22 17:22:01+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90));
8789 test("2010-Dec-22 17:22:01+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east480));
8790
8791 test("2010-Nov-03 06:51:06.57159Z", SysTime(DateTime(2010, 11, 3, 6, 51, 6), hnsecs(5715900), UTC()));
8792 test("2010-Dec-22 17:22:01.23412Z", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_341_200), UTC()));
8793 test("2010-Dec-22 17:22:01.23112-01:00",
8794 SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_311_200), west60));
8795 test("2010-Dec-22 17:22:01.45-01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), west60));
8796 test("2010-Dec-22 17:22:01.1-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_000_000), west90));
8797 test("2010-Dec-22 17:22:01.55-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(5_500_000), west480));
8798 test("2010-Dec-22 17:22:01.1234567+01:00",
8799 SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_234_567), east60));
8800 test("2010-Dec-22 17:22:01.0+01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60));
8801 test("2010-Dec-22 17:22:01.0000000+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90));
8802 test("2010-Dec-22 17:22:01.45+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), east480));
8803 }
8804
8805 // bug# 17801
8806 @safe unittest
8807 {
8808 import std.conv : to;
8809 import std.meta : AliasSeq;
8810 foreach (C; AliasSeq!(char, wchar, dchar))
8811 {
8812 foreach (S; AliasSeq!(C[], const(C)[], immutable(C)[]))
8813 {
8814 assert(SysTime.fromSimpleString(to!S("2012-Dec-21 14:15:16Z")) ==
8815 SysTime(DateTime(2012, 12, 21, 14, 15, 16), UTC()));
8816 }
8817 }
8818 }
8819
8820
8821 /++
8822 Returns the $(LREF SysTime) farthest in the past which is representable
8823 by $(LREF SysTime).
8824
8825 The $(LREF SysTime) which is returned is in UTC.
8826 +/
8827 @property static SysTime min() @safe pure nothrow
8828 {
8829 return SysTime(long.min, UTC());
8830 }
8831
8832 @safe unittest
8833 {
8834 assert(SysTime.min.year < 0);
8835 assert(SysTime.min < SysTime.max);
8836 }
8837
8838
8839 /++
8840 Returns the $(LREF SysTime) farthest in the future which is representable
8841 by $(LREF SysTime).
8842
8843 The $(LREF SysTime) which is returned is in UTC.
8844 +/
8845 @property static SysTime max() @safe pure nothrow
8846 {
8847 return SysTime(long.max, UTC());
8848 }
8849
8850 @safe unittest
8851 {
8852 assert(SysTime.max.year > 0);
8853 assert(SysTime.max > SysTime.min);
8854 }
8855
8856
8857 private:
8858
8859 /+
8860 Returns $(D stdTime) converted to $(LREF SysTime)'s time zone.
8861 +/
8862 @property long adjTime() @safe const nothrow
8863 {
8864 return _timezone.utcToTZ(_stdTime);
8865 }
8866
8867
8868 /+
8869 Converts the given hnsecs from $(LREF SysTime)'s time zone to std time.
8870 +/
8871 @property void adjTime(long adjTime) @safe nothrow
8872 {
8873 _stdTime = _timezone.tzToUTC(adjTime);
8874 }
8875
8876
8877 // Commented out due to bug http://d.puremagic.com/issues/show_bug.cgi?id=5058
8878 /+
8879 invariant()
8880 {
8881 assert(_timezone !is null, "Invariant Failure: timezone is null. Were you foolish enough to use " ~
8882 "SysTime.init? (since timezone for SysTime.init can't be set at compile time).");
8883 }
8884 +/
8885
8886
8887 long _stdTime;
8888 Rebindable!(immutable TimeZone) _timezone;
8889 }
8890
8891
8892 /++
8893 Converts from unix time (which uses midnight, January 1st, 1970 UTC as its
8894 epoch and seconds as its units) to "std time" (which uses midnight,
8895 January 1st, 1 A.D. UTC and hnsecs as its units).
8896
8897 The C standard does not specify the representation of time_t, so it is
8898 implementation defined. On POSIX systems, unix time is equivalent to
8899 time_t, but that's not necessarily true on other systems (e.g. it is
8900 not true for the Digital Mars C runtime). So, be careful when using unix
8901 time with C functions on non-POSIX systems.
8902
8903 "std time"'s epoch is based on the Proleptic Gregorian Calendar per ISO
8904 8601 and is what $(LREF SysTime) uses internally. However, holding the time
8905 as an integer in hnescs since that epoch technically isn't actually part of
8906 the standard, much as it's based on it, so the name "std time" isn't
8907 particularly good, but there isn't an official name for it. C# uses "ticks"
8908 for the same thing, but they aren't actually clock ticks, and the term
8909 "ticks" $(I is) used for actual clock ticks for $(REF MonoTime, core,time),
8910 so it didn't make sense to use the term ticks here. So, for better or worse,
8911 std.datetime uses the term "std time" for this.
8912
8913 Params:
8914 unixTime = The unix time to convert.
8915
8916 See_Also:
8917 SysTime.fromUnixTime
8918 +/
unixTimeToStdTime(long unixTime)8919 long unixTimeToStdTime(long unixTime) @safe pure nothrow
8920 {
8921 return 621_355_968_000_000_000L + convert!("seconds", "hnsecs")(unixTime);
8922 }
8923
8924 ///
8925 @safe unittest
8926 {
8927 import std.datetime.date : DateTime;
8928 import std.datetime.timezone : UTC;
8929
8930 // Midnight, January 1st, 1970
8931 assert(unixTimeToStdTime(0) == 621_355_968_000_000_000L);
8932 assert(SysTime(unixTimeToStdTime(0)) ==
8933 SysTime(DateTime(1970, 1, 1), UTC()));
8934
8935 assert(unixTimeToStdTime(int.max) == 642_830_804_470_000_000L);
8936 assert(SysTime(unixTimeToStdTime(int.max)) ==
8937 SysTime(DateTime(2038, 1, 19, 3, 14, 07), UTC()));
8938
8939 assert(unixTimeToStdTime(-127_127) == 621_354_696_730_000_000L);
8940 assert(SysTime(unixTimeToStdTime(-127_127)) ==
8941 SysTime(DateTime(1969, 12, 30, 12, 41, 13), UTC()));
8942 }
8943
8944 @safe unittest
8945 {
8946 // Midnight, January 2nd, 1970
8947 assert(unixTimeToStdTime(86_400) == 621_355_968_000_000_000L + 864_000_000_000L);
8948 // Midnight, December 31st, 1969
8949 assert(unixTimeToStdTime(-86_400) == 621_355_968_000_000_000L - 864_000_000_000L);
8950
8951 assert(unixTimeToStdTime(0) == (Date(1970, 1, 1) - Date(1, 1, 1)).total!"hnsecs");
8952 assert(unixTimeToStdTime(0) == (DateTime(1970, 1, 1) - DateTime(1, 1, 1)).total!"hnsecs");
8953
8954 foreach (dt; [DateTime(2010, 11, 1, 19, 5, 22), DateTime(1952, 7, 6, 2, 17, 9)])
8955 assert(unixTimeToStdTime((dt - DateTime(1970, 1, 1)).total!"seconds") == (dt - DateTime.init).total!"hnsecs");
8956 }
8957
8958
8959 /++
8960 Converts std time (which uses midnight, January 1st, 1 A.D. UTC as its epoch
8961 and hnsecs as its units) to unix time (which uses midnight, January 1st,
8962 1970 UTC as its epoch and seconds as its units).
8963
8964 The C standard does not specify the representation of time_t, so it is
8965 implementation defined. On POSIX systems, unix time is equivalent to
8966 time_t, but that's not necessarily true on other systems (e.g. it is
8967 not true for the Digital Mars C runtime). So, be careful when using unix
8968 time with C functions on non-POSIX systems.
8969
8970 "std time"'s epoch is based on the Proleptic Gregorian Calendar per ISO
8971 8601 and is what $(LREF SysTime) uses internally. However, holding the time
8972 as an integer in hnescs since that epoch technically isn't actually part of
8973 the standard, much as it's based on it, so the name "std time" isn't
8974 particularly good, but there isn't an official name for it. C# uses "ticks"
8975 for the same thing, but they aren't actually clock ticks, and the term
8976 "ticks" $(I is) used for actual clock ticks for $(REF MonoTime, core,time),
8977 so it didn't make sense to use the term ticks here. So, for better or worse,
8978 std.datetime uses the term "std time" for this.
8979
8980 By default, the return type is time_t (which is normally an alias for
8981 int on 32-bit systems and long on 64-bit systems), but if a different
8982 size is required than either int or long can be passed as a template
8983 argument to get the desired size.
8984
8985 If the return type is int, and the result can't fit in an int, then the
8986 closest value that can be held in 32 bits will be used (so $(D int.max)
8987 if it goes over and $(D int.min) if it goes under). However, no attempt
8988 is made to deal with integer overflow if the return type is long.
8989
8990 Params:
8991 T = The return type (int or long). It defaults to time_t, which is
8992 normally 32 bits on a 32-bit system and 64 bits on a 64-bit
8993 system.
8994 stdTime = The std time to convert.
8995
8996 Returns:
8997 A signed integer representing the unix time which is equivalent to
8998 the given std time.
8999
9000 See_Also:
9001 SysTime.toUnixTime
9002 +/
9003 T stdTimeToUnixTime(T = time_t)(long stdTime) @safe pure nothrow
9004 if (is(T == int) || is(T == long))
9005 {
9006 immutable unixTime = convert!("hnsecs", "seconds")(stdTime - 621_355_968_000_000_000L);
9007
9008 static assert(is(time_t == int) || is(time_t == long),
9009 "Currently, std.datetime only supports systems where time_t is int or long");
9010
9011 static if (is(T == long))
9012 return unixTime;
9013 else static if (is(T == int))
9014 {
9015 if (unixTime > int.max)
9016 return int.max;
9017 return unixTime < int.min ? int.min : cast(int) unixTime;
9018 }
9019 else
9020 static assert(0, "Bug in template constraint. Only int and long allowed.");
9021 }
9022
9023 ///
9024 @safe unittest
9025 {
9026 // Midnight, January 1st, 1970 UTC
9027 assert(stdTimeToUnixTime(621_355_968_000_000_000L) == 0);
9028
9029 // 2038-01-19 03:14:07 UTC
9030 assert(stdTimeToUnixTime(642_830_804_470_000_000L) == int.max);
9031 }
9032
9033 @safe unittest
9034 {
9035 enum unixEpochAsStdTime = (Date(1970, 1, 1) - Date.init).total!"hnsecs";
9036
9037 assert(stdTimeToUnixTime(unixEpochAsStdTime) == 0); // Midnight, January 1st, 1970
9038 assert(stdTimeToUnixTime(unixEpochAsStdTime + 864_000_000_000L) == 86_400); // Midnight, January 2nd, 1970
9039 assert(stdTimeToUnixTime(unixEpochAsStdTime - 864_000_000_000L) == -86_400); // Midnight, December 31st, 1969
9040
9041 assert(stdTimeToUnixTime((Date(1970, 1, 1) - Date(1, 1, 1)).total!"hnsecs") == 0);
9042 assert(stdTimeToUnixTime((DateTime(1970, 1, 1) - DateTime(1, 1, 1)).total!"hnsecs") == 0);
9043
9044 foreach (dt; [DateTime(2010, 11, 1, 19, 5, 22), DateTime(1952, 7, 6, 2, 17, 9)])
9045 assert(stdTimeToUnixTime((dt - DateTime.init).total!"hnsecs") == (dt - DateTime(1970, 1, 1)).total!"seconds");
9046
9047 enum max = convert!("seconds", "hnsecs")(int.max);
9048 enum min = convert!("seconds", "hnsecs")(int.min);
9049 enum one = convert!("seconds", "hnsecs")(1);
9050
9051 assert(stdTimeToUnixTime!long(unixEpochAsStdTime + max) == int.max);
9052 assert(stdTimeToUnixTime!int(unixEpochAsStdTime + max) == int.max);
9053
9054 assert(stdTimeToUnixTime!long(unixEpochAsStdTime + max + one) == int.max + 1L);
9055 assert(stdTimeToUnixTime!int(unixEpochAsStdTime + max + one) == int.max);
9056 assert(stdTimeToUnixTime!long(unixEpochAsStdTime + max + 9_999_999) == int.max);
9057 assert(stdTimeToUnixTime!int(unixEpochAsStdTime + max + 9_999_999) == int.max);
9058
9059 assert(stdTimeToUnixTime!long(unixEpochAsStdTime + min) == int.min);
9060 assert(stdTimeToUnixTime!int(unixEpochAsStdTime + min) == int.min);
9061
9062 assert(stdTimeToUnixTime!long(unixEpochAsStdTime + min - one) == int.min - 1L);
9063 assert(stdTimeToUnixTime!int(unixEpochAsStdTime + min - one) == int.min);
9064 assert(stdTimeToUnixTime!long(unixEpochAsStdTime + min - 9_999_999) == int.min);
9065 assert(stdTimeToUnixTime!int(unixEpochAsStdTime + min - 9_999_999) == int.min);
9066 }
9067
9068
version(StdDdoc)9069 version (StdDdoc)
9070 {
9071 version (Windows)
9072 {}
9073 else
9074 {
9075 alias SYSTEMTIME = void*;
9076 alias FILETIME = void*;
9077 }
9078
9079 /++
9080 $(BLUE This function is Windows-Only.)
9081
9082 Converts a $(D SYSTEMTIME) struct to a $(LREF SysTime).
9083
9084 Params:
9085 st = The $(D SYSTEMTIME) struct to convert.
9086 tz = The time zone that the time in the $(D SYSTEMTIME) struct is
9087 assumed to be (if the $(D SYSTEMTIME) was supplied by a Windows
9088 system call, the $(D SYSTEMTIME) will either be in local time
9089 or UTC, depending on the call).
9090
9091 Throws:
9092 $(REF DateTimeException,std,datetime,date) if the given
9093 $(D SYSTEMTIME) will not fit in a $(LREF SysTime), which is highly
9094 unlikely to happen given that $(D SysTime.max) is in 29,228 A.D. and
9095 the maximum $(D SYSTEMTIME) is in 30,827 A.D.
9096 +/
9097 SysTime SYSTEMTIMEToSysTime(const SYSTEMTIME* st, immutable TimeZone tz = LocalTime()) @safe;
9098
9099
9100 /++
9101 $(BLUE This function is Windows-Only.)
9102
9103 Converts a $(LREF SysTime) to a $(D SYSTEMTIME) struct.
9104
9105 The $(D SYSTEMTIME) which is returned will be set using the given
9106 $(LREF SysTime)'s time zone, so to get the $(D SYSTEMTIME) in
9107 UTC, set the $(LREF SysTime)'s time zone to UTC.
9108
9109 Params:
9110 sysTime = The $(LREF SysTime) to convert.
9111
9112 Throws:
9113 $(REF DateTimeException,std,datetime,date) if the given
9114 $(LREF SysTime) will not fit in a $(D SYSTEMTIME). This will only
9115 happen if the $(LREF SysTime)'s date is prior to 1601 A.D.
9116 +/
9117 SYSTEMTIME SysTimeToSYSTEMTIME(in SysTime sysTime) @safe;
9118
9119
9120 /++
9121 $(BLUE This function is Windows-Only.)
9122
9123 Converts a $(D FILETIME) struct to the number of hnsecs since midnight,
9124 January 1st, 1 A.D.
9125
9126 Params:
9127 ft = The $(D FILETIME) struct to convert.
9128
9129 Throws:
9130 $(REF DateTimeException,std,datetime,date) if the given
9131 $(D FILETIME) cannot be represented as the return value.
9132 +/
9133 long FILETIMEToStdTime(scope const FILETIME* ft) @safe;
9134
9135
9136 /++
9137 $(BLUE This function is Windows-Only.)
9138
9139 Converts a $(D FILETIME) struct to a $(LREF SysTime).
9140
9141 Params:
9142 ft = The $(D FILETIME) struct to convert.
9143 tz = The time zone that the $(LREF SysTime) will be in
9144 ($(D FILETIME)s are in UTC).
9145
9146 Throws:
9147 $(REF DateTimeException,std,datetime,date) if the given
9148 $(D FILETIME) will not fit in a $(LREF SysTime).
9149 +/
9150 SysTime FILETIMEToSysTime(scope const FILETIME* ft, immutable TimeZone tz = LocalTime()) @safe;
9151
9152
9153 /++
9154 $(BLUE This function is Windows-Only.)
9155
9156 Converts a number of hnsecs since midnight, January 1st, 1 A.D. to a
9157 $(D FILETIME) struct.
9158
9159 Params:
9160 stdTime = The number of hnsecs since midnight, January 1st, 1 A.D.
9161 UTC.
9162
9163 Throws:
9164 $(REF DateTimeException,std,datetime,date) if the given value will
9165 not fit in a $(D FILETIME).
9166 +/
9167 FILETIME stdTimeToFILETIME(long stdTime) @safe;
9168
9169
9170 /++
9171 $(BLUE This function is Windows-Only.)
9172
9173 Converts a $(LREF SysTime) to a $(D FILETIME) struct.
9174
9175 $(D FILETIME)s are always in UTC.
9176
9177 Params:
9178 sysTime = The $(LREF SysTime) to convert.
9179
9180 Throws:
9181 $(REF DateTimeException,std,datetime,date) if the given
9182 $(LREF SysTime) will not fit in a $(D FILETIME).
9183 +/
9184 FILETIME SysTimeToFILETIME(SysTime sysTime) @safe;
9185 }
9186 else version (Windows)
9187 {
9188 SysTime SYSTEMTIMEToSysTime(const SYSTEMTIME* st, immutable TimeZone tz = LocalTime()) @safe
9189 {
9190 const max = SysTime.max;
9191
9192 static void throwLaterThanMax()
9193 {
9194 throw new DateTimeException("The given SYSTEMTIME is for a date greater than SysTime.max.");
9195 }
9196
9197 if (st.wYear > max.year)
9198 throwLaterThanMax();
9199 else if (st.wYear == max.year)
9200 {
9201 if (st.wMonth > max.month)
9202 throwLaterThanMax();
9203 else if (st.wMonth == max.month)
9204 {
9205 if (st.wDay > max.day)
9206 throwLaterThanMax();
9207 else if (st.wDay == max.day)
9208 {
9209 if (st.wHour > max.hour)
9210 throwLaterThanMax();
9211 else if (st.wHour == max.hour)
9212 {
9213 if (st.wMinute > max.minute)
9214 throwLaterThanMax();
9215 else if (st.wMinute == max.minute)
9216 {
9217 if (st.wSecond > max.second)
9218 throwLaterThanMax();
9219 else if (st.wSecond == max.second)
9220 {
9221 if (st.wMilliseconds > max.fracSecs.total!"msecs")
9222 throwLaterThanMax();
9223 }
9224 }
9225 }
9226 }
9227 }
9228 }
9229
9230 auto dt = DateTime(st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
9231
9232 return SysTime(dt, msecs(st.wMilliseconds), tz);
9233 }
9234
9235 @system unittest
9236 {
9237 auto sysTime = Clock.currTime(UTC());
9238 SYSTEMTIME st = void;
9239 GetSystemTime(&st);
9240 auto converted = SYSTEMTIMEToSysTime(&st, UTC());
9241
9242 assert(abs((converted - sysTime)) <= dur!"seconds"(2));
9243 }
9244
9245
9246 SYSTEMTIME SysTimeToSYSTEMTIME(in SysTime sysTime) @safe
9247 {
9248 immutable dt = cast(DateTime) sysTime;
9249
9250 if (dt.year < 1601)
9251 throw new DateTimeException("SYSTEMTIME cannot hold dates prior to the year 1601.");
9252
9253 SYSTEMTIME st;
9254
9255 st.wYear = dt.year;
9256 st.wMonth = dt.month;
9257 st.wDayOfWeek = dt.dayOfWeek;
9258 st.wDay = dt.day;
9259 st.wHour = dt.hour;
9260 st.wMinute = dt.minute;
9261 st.wSecond = dt.second;
9262 st.wMilliseconds = cast(ushort) sysTime.fracSecs.total!"msecs";
9263
9264 return st;
9265 }
9266
9267 @system unittest
9268 {
9269 SYSTEMTIME st = void;
9270 GetSystemTime(&st);
9271 auto sysTime = SYSTEMTIMEToSysTime(&st, UTC());
9272
9273 SYSTEMTIME result = SysTimeToSYSTEMTIME(sysTime);
9274
9275 assert(st.wYear == result.wYear);
9276 assert(st.wMonth == result.wMonth);
9277 assert(st.wDayOfWeek == result.wDayOfWeek);
9278 assert(st.wDay == result.wDay);
9279 assert(st.wHour == result.wHour);
9280 assert(st.wMinute == result.wMinute);
9281 assert(st.wSecond == result.wSecond);
9282 assert(st.wMilliseconds == result.wMilliseconds);
9283 }
9284
9285 private enum hnsecsFrom1601 = 504_911_232_000_000_000L;
9286
9287 long FILETIMEToStdTime(scope const FILETIME* ft) @safe
9288 {
9289 ULARGE_INTEGER ul;
9290 ul.HighPart = ft.dwHighDateTime;
9291 ul.LowPart = ft.dwLowDateTime;
9292 ulong tempHNSecs = ul.QuadPart;
9293
9294 if (tempHNSecs > long.max - hnsecsFrom1601)
9295 throw new DateTimeException("The given FILETIME cannot be represented as a stdTime value.");
9296
9297 return cast(long) tempHNSecs + hnsecsFrom1601;
9298 }
9299
9300 SysTime FILETIMEToSysTime(scope const FILETIME* ft, immutable TimeZone tz = LocalTime()) @safe
9301 {
9302 auto sysTime = SysTime(FILETIMEToStdTime(ft), UTC());
9303 sysTime.timezone = tz;
9304 return sysTime;
9305 }
9306
9307 @system unittest
9308 {
9309 auto sysTime = Clock.currTime(UTC());
9310 SYSTEMTIME st = void;
9311 GetSystemTime(&st);
9312
9313 FILETIME ft = void;
9314 SystemTimeToFileTime(&st, &ft);
9315
9316 auto converted = FILETIMEToSysTime(&ft);
9317
9318 assert(abs((converted - sysTime)) <= dur!"seconds"(2));
9319 }
9320
9321
9322 FILETIME stdTimeToFILETIME(long stdTime) @safe
9323 {
9324 if (stdTime < hnsecsFrom1601)
9325 throw new DateTimeException("The given stdTime value cannot be represented as a FILETIME.");
9326
9327 ULARGE_INTEGER ul;
9328 ul.QuadPart = cast(ulong) stdTime - hnsecsFrom1601;
9329
9330 FILETIME ft;
9331 ft.dwHighDateTime = ul.HighPart;
9332 ft.dwLowDateTime = ul.LowPart;
9333
9334 return ft;
9335 }
9336
9337 FILETIME SysTimeToFILETIME(SysTime sysTime) @safe
9338 {
9339 return stdTimeToFILETIME(sysTime.stdTime);
9340 }
9341
9342 @system unittest
9343 {
9344 SYSTEMTIME st = void;
9345 GetSystemTime(&st);
9346
9347 FILETIME ft = void;
9348 SystemTimeToFileTime(&st, &ft);
9349 auto sysTime = FILETIMEToSysTime(&ft, UTC());
9350
9351 FILETIME result = SysTimeToFILETIME(sysTime);
9352
9353 assert(ft.dwLowDateTime == result.dwLowDateTime);
9354 assert(ft.dwHighDateTime == result.dwHighDateTime);
9355 }
9356 }
9357
9358
9359 /++
9360 Type representing the DOS file date/time format.
9361 +/
9362 alias DosFileTime = uint;
9363
9364 /++
9365 Converts from DOS file date/time to $(LREF SysTime).
9366
9367 Params:
9368 dft = The DOS file time to convert.
9369 tz = The time zone which the DOS file time is assumed to be in.
9370
9371 Throws:
9372 $(REF DateTimeException,std,datetime,date) if the $(D DosFileTime) is
9373 invalid.
9374 +/
9375 SysTime DosFileTimeToSysTime(DosFileTime dft, immutable TimeZone tz = LocalTime()) @safe
9376 {
9377 uint dt = cast(uint) dft;
9378
9379 if (dt == 0)
9380 throw new DateTimeException("Invalid DosFileTime.");
9381
9382 int year = ((dt >> 25) & 0x7F) + 1980;
9383 int month = ((dt >> 21) & 0x0F); // 1 .. 12
9384 int dayOfMonth = ((dt >> 16) & 0x1F); // 1 .. 31
9385 int hour = (dt >> 11) & 0x1F; // 0 .. 23
9386 int minute = (dt >> 5) & 0x3F; // 0 .. 59
9387 int second = (dt << 1) & 0x3E; // 0 .. 58 (in 2 second increments)
9388
9389 try
9390 return SysTime(DateTime(year, month, dayOfMonth, hour, minute, second), tz);
9391 catch (DateTimeException dte)
9392 throw new DateTimeException("Invalid DosFileTime", __FILE__, __LINE__, dte);
9393 }
9394
9395 @safe unittest
9396 {
9397 assert(DosFileTimeToSysTime(0b00000000001000010000000000000000) == SysTime(DateTime(1980, 1, 1, 0, 0, 0)));
9398 assert(DosFileTimeToSysTime(0b11111111100111111011111101111101) == SysTime(DateTime(2107, 12, 31, 23, 59, 58)));
9399 assert(DosFileTimeToSysTime(0x3E3F8456) == SysTime(DateTime(2011, 1, 31, 16, 34, 44)));
9400 }
9401
9402
9403 /++
9404 Converts from $(LREF SysTime) to DOS file date/time.
9405
9406 Params:
9407 sysTime = The $(LREF SysTime) to convert.
9408
9409 Throws:
9410 $(REF DateTimeException,std,datetime,date) if the given
9411 $(LREF SysTime) cannot be converted to a $(D DosFileTime).
9412 +/
9413 DosFileTime SysTimeToDosFileTime(SysTime sysTime) @safe
9414 {
9415 auto dateTime = cast(DateTime) sysTime;
9416
9417 if (dateTime.year < 1980)
9418 throw new DateTimeException("DOS File Times cannot hold dates prior to 1980.");
9419
9420 if (dateTime.year > 2107)
9421 throw new DateTimeException("DOS File Times cannot hold dates past 2107.");
9422
9423 uint retval = 0;
9424 retval = (dateTime.year - 1980) << 25;
9425 retval |= (dateTime.month & 0x0F) << 21;
9426 retval |= (dateTime.day & 0x1F) << 16;
9427 retval |= (dateTime.hour & 0x1F) << 11;
9428 retval |= (dateTime.minute & 0x3F) << 5;
9429 retval |= (dateTime.second >> 1) & 0x1F;
9430
9431 return cast(DosFileTime) retval;
9432 }
9433
9434 @safe unittest
9435 {
9436 assert(SysTimeToDosFileTime(SysTime(DateTime(1980, 1, 1, 0, 0, 0))) == 0b00000000001000010000000000000000);
9437 assert(SysTimeToDosFileTime(SysTime(DateTime(2107, 12, 31, 23, 59, 58))) == 0b11111111100111111011111101111101);
9438 assert(SysTimeToDosFileTime(SysTime(DateTime(2011, 1, 31, 16, 34, 44))) == 0x3E3F8456);
9439 }
9440
9441
9442 /++
9443 The given array of $(D char) or random-access range of $(D char) or
9444 $(D ubyte) is expected to be in the format specified in
9445 $(HTTP tools.ietf.org/html/rfc5322, RFC 5322) section 3.3 with the
9446 grammar rule $(I date-time). It is the date-time format commonly used in
9447 internet messages such as e-mail and HTTP. The corresponding
9448 $(LREF SysTime) will be returned.
9449
9450 RFC 822 was the original spec (hence the function's name), whereas RFC 5322
9451 is the current spec.
9452
9453 The day of the week is ignored beyond verifying that it's a valid day of the
9454 week, as the day of the week can be inferred from the date. It is not
9455 checked whether the given day of the week matches the actual day of the week
9456 of the given date (though it is technically invalid per the spec if the
9457 day of the week doesn't match the actual day of the week of the given date).
9458
9459 If the time zone is $(D "-0000") (or considered to be equivalent to
9460 $(D "-0000") by section 4.3 of the spec), a
9461 $(REF SimpleTimeZone,std,datetime,timezone) with a utc offset of $(D 0) is
9462 used rather than $(REF UTC,std,datetime,timezone), whereas $(D "+0000") uses
9463 $(REF UTC,std,datetime,timezone).
9464
9465 Note that because $(LREF SysTime) does not currently support having a second
9466 value of 60 (as is sometimes done for leap seconds), if the date-time value
9467 does have a value of 60 for the seconds, it is treated as 59.
9468
9469 The one area in which this function violates RFC 5322 is that it accepts
9470 $(D "\n") in folding whitespace in the place of $(D "\r\n"), because the
9471 HTTP spec requires it.
9472
9473 Throws:
9474 $(REF DateTimeException,std,datetime,date) if the given string doesn't
9475 follow the grammar for a date-time field or if the resulting
9476 $(LREF SysTime) is invalid.
9477 +/
9478 SysTime parseRFC822DateTime()(in char[] value) @safe
9479 {
9480 import std.string : representation;
9481 return parseRFC822DateTime(value.representation);
9482 }
9483
9484 /++ Ditto +/
9485 SysTime parseRFC822DateTime(R)(R value) @safe
9486 if (isRandomAccessRange!R && hasSlicing!R && hasLength!R &&
9487 (is(Unqual!(ElementType!R) == char) || is(Unqual!(ElementType!R) == ubyte)))
9488 {
9489 import std.algorithm.searching : find, all;
9490 import std.ascii : isDigit, isAlpha, isPrintable;
9491 import std.conv : to;
9492 import std.functional : not;
9493 import std.string : capitalize, format;
9494 import std.traits : EnumMembers, isArray;
9495 import std.typecons : Rebindable;
9496
9497 void stripAndCheckLen(R valueBefore, size_t minLen, size_t line = __LINE__)
9498 {
9499 value = _stripCFWS(valueBefore);
9500 if (value.length < minLen)
9501 throw new DateTimeException("date-time value too short", __FILE__, line);
9502 }
9503 stripAndCheckLen(value, "7Dec1200:00A".length);
9504
9505 static if (isArray!R && (is(ElementEncodingType!R == char) || is(ElementEncodingType!R == ubyte)))
9506 {
9507 static string sliceAsString(R str) @trusted
9508 {
9509 return cast(string) str;
9510 }
9511 }
9512 else
9513 {
9514 char[4] temp;
9515 char[] sliceAsString(R str) @trusted
9516 {
9517 size_t i = 0;
9518 foreach (c; str)
9519 temp[i++] = cast(char) c;
9520 return temp[0 .. str.length];
9521 }
9522 }
9523
9524 // day-of-week
9525 if (isAlpha(value[0]))
9526 {
9527 auto dowStr = sliceAsString(value[0 .. 3]);
9528 switch (dowStr)
9529 {
9530 foreach (dow; EnumMembers!DayOfWeek)
9531 {
9532 enum dowC = capitalize(to!string(dow));
9533 case dowC:
9534 goto afterDoW;
9535 }
9536 default: throw new DateTimeException(format("Invalid day-of-week: %s", dowStr));
9537 }
9538 afterDoW: stripAndCheckLen(value[3 .. value.length], ",7Dec1200:00A".length);
9539 if (value[0] != ',')
9540 throw new DateTimeException("day-of-week missing comma");
9541 stripAndCheckLen(value[1 .. value.length], "7Dec1200:00A".length);
9542 }
9543
9544 // day
9545 immutable digits = isDigit(value[1]) ? 2 : 1;
9546 immutable day = _convDigits!short(value[0 .. digits]);
9547 if (day == -1)
9548 throw new DateTimeException("Invalid day");
9549 stripAndCheckLen(value[digits .. value.length], "Dec1200:00A".length);
9550
9551 // month
9552 Month month;
9553 {
9554 auto monStr = sliceAsString(value[0 .. 3]);
9555 switch (monStr)
9556 {
9557 foreach (mon; EnumMembers!Month)
9558 {
9559 enum monC = capitalize(to!string(mon));
9560 case monC:
9561 {
9562 month = mon;
9563 goto afterMon;
9564 }
9565 }
9566 default: throw new DateTimeException(format("Invalid month: %s", monStr));
9567 }
9568 afterMon: stripAndCheckLen(value[3 .. value.length], "1200:00A".length);
9569 }
9570
9571 // year
9572 auto found = value[2 .. value.length].find!(not!(isDigit))();
9573 size_t yearLen = value.length - found.length;
9574 if (found.length == 0)
9575 throw new DateTimeException("Invalid year");
9576 if (found[0] == ':')
9577 yearLen -= 2;
9578 auto year = _convDigits!short(value[0 .. yearLen]);
9579 if (year < 1900)
9580 {
9581 if (year == -1)
9582 throw new DateTimeException("Invalid year");
9583 if (yearLen < 4)
9584 {
9585 if (yearLen == 3)
9586 year += 1900;
9587 else if (yearLen == 2)
9588 year += year < 50 ? 2000 : 1900;
9589 else
9590 throw new DateTimeException("Invalid year. Too few digits.");
9591 }
9592 else
9593 throw new DateTimeException("Invalid year. Cannot be earlier than 1900.");
9594 }
9595 stripAndCheckLen(value[yearLen .. value.length], "00:00A".length);
9596
9597 // hour
9598 immutable hour = _convDigits!short(value[0 .. 2]);
9599 stripAndCheckLen(value[2 .. value.length], ":00A".length);
9600 if (value[0] != ':')
9601 throw new DateTimeException("Invalid hour");
9602 stripAndCheckLen(value[1 .. value.length], "00A".length);
9603
9604 // minute
9605 immutable minute = _convDigits!short(value[0 .. 2]);
9606 stripAndCheckLen(value[2 .. value.length], "A".length);
9607
9608 // second
9609 short second;
9610 if (value[0] == ':')
9611 {
9612 stripAndCheckLen(value[1 .. value.length], "00A".length);
9613 second = _convDigits!short(value[0 .. 2]);
9614 // this is just if/until SysTime is sorted out to fully support leap seconds
9615 if (second == 60)
9616 second = 59;
9617 stripAndCheckLen(value[2 .. value.length], "A".length);
9618 }
9619
9620 immutable(TimeZone) parseTZ(int sign)
9621 {
9622 if (value.length < 5)
9623 throw new DateTimeException("Invalid timezone");
9624 immutable zoneHours = _convDigits!short(value[1 .. 3]);
9625 immutable zoneMinutes = _convDigits!short(value[3 .. 5]);
9626 if (zoneHours == -1 || zoneMinutes == -1 || zoneMinutes > 59)
9627 throw new DateTimeException("Invalid timezone");
9628 value = value[5 .. value.length];
9629 immutable utcOffset = (dur!"hours"(zoneHours) + dur!"minutes"(zoneMinutes)) * sign;
9630 if (utcOffset == Duration.zero)
9631 {
9632 return sign == 1 ? cast(immutable(TimeZone))UTC()
9633 : cast(immutable(TimeZone))new immutable SimpleTimeZone(Duration.zero);
9634 }
9635 return new immutable(SimpleTimeZone)(utcOffset);
9636 }
9637
9638 // zone
9639 Rebindable!(immutable TimeZone) tz;
9640 if (value[0] == '-')
9641 tz = parseTZ(-1);
9642 else if (value[0] == '+')
9643 tz = parseTZ(1);
9644 else
9645 {
9646 // obs-zone
9647 immutable tzLen = value.length - find(value, ' ', '\t', '(')[0].length;
9648 switch (sliceAsString(value[0 .. tzLen <= 4 ? tzLen : 4]))
9649 {
9650 case "UT": case "GMT": tz = UTC(); break;
9651 case "EST": tz = new immutable SimpleTimeZone(dur!"hours"(-5)); break;
9652 case "EDT": tz = new immutable SimpleTimeZone(dur!"hours"(-4)); break;
9653 case "CST": tz = new immutable SimpleTimeZone(dur!"hours"(-6)); break;
9654 case "CDT": tz = new immutable SimpleTimeZone(dur!"hours"(-5)); break;
9655 case "MST": tz = new immutable SimpleTimeZone(dur!"hours"(-7)); break;
9656 case "MDT": tz = new immutable SimpleTimeZone(dur!"hours"(-6)); break;
9657 case "PST": tz = new immutable SimpleTimeZone(dur!"hours"(-8)); break;
9658 case "PDT": tz = new immutable SimpleTimeZone(dur!"hours"(-7)); break;
9659 case "J": case "j": throw new DateTimeException("Invalid timezone");
9660 default:
9661 {
9662 if (all!(isAlpha)(value[0 .. tzLen]))
9663 {
9664 tz = new immutable SimpleTimeZone(Duration.zero);
9665 break;
9666 }
9667 throw new DateTimeException("Invalid timezone");
9668 }
9669 }
9670 value = value[tzLen .. value.length];
9671 }
9672
9673 // This is kind of arbitrary. Technically, nothing but CFWS is legal past
9674 // the end of the timezone, but we don't want to be picky about that in a
9675 // function that's just parsing rather than validating. So, the idea here is
9676 // that if the next character is printable (and not part of CFWS), then it
9677 // might be part of the timezone and thus affect what the timezone was
9678 // supposed to be, so we'll throw, but otherwise, we'll just ignore it.
9679 if (!value.empty && isPrintable(value[0]) && value[0] != ' ' && value[0] != '(')
9680 throw new DateTimeException("Invalid timezone");
9681
9682 try
9683 return SysTime(DateTime(year, month, day, hour, minute, second), tz);
9684 catch (DateTimeException dte)
9685 throw new DateTimeException("date-time format is correct, but the resulting SysTime is invalid.", dte);
9686 }
9687
9688 ///
9689 @safe unittest
9690 {
9691 import core.time : hours;
9692 import std.datetime.date : DateTime, DateTimeException;
9693 import std.datetime.timezone : SimpleTimeZone, UTC;
9694 import std.exception : assertThrown;
9695
9696 auto tz = new immutable SimpleTimeZone(hours(-8));
9697 assert(parseRFC822DateTime("Sat, 6 Jan 1990 12:14:19 -0800") ==
9698 SysTime(DateTime(1990, 1, 6, 12, 14, 19), tz));
9699
9700 assert(parseRFC822DateTime("9 Jul 2002 13:11 +0000") ==
9701 SysTime(DateTime(2002, 7, 9, 13, 11, 0), UTC()));
9702
9703 auto badStr = "29 Feb 2001 12:17:16 +0200";
9704 assertThrown!DateTimeException(parseRFC822DateTime(badStr));
9705 }
9706
version(unittest)9707 version (unittest) void testParse822(alias cr)(string str, SysTime expected, size_t line = __LINE__)
9708 {
9709 import std.format : format;
9710 auto value = cr(str);
9711 auto result = parseRFC822DateTime(value);
9712 if (result != expected)
9713 throw new AssertError(format("wrong result. expected [%s], actual[%s]", expected, result), __FILE__, line);
9714 }
9715
version(unittest)9716 version (unittest) void testBadParse822(alias cr)(string str, size_t line = __LINE__)
9717 {
9718 try
9719 parseRFC822DateTime(cr(str));
9720 catch (DateTimeException)
9721 return;
9722 throw new AssertError("No DateTimeException was thrown", __FILE__, line);
9723 }
9724
9725 @system unittest
9726 {
9727 import std.algorithm.iteration : filter, map;
9728 import std.algorithm.searching : canFind;
9729 import std.array : array;
9730 import std.ascii : letters;
9731 import std.format : format;
9732 import std.meta : AliasSeq;
9733 import std.range : chain, iota, take;
9734 import std.stdio : writefln, writeln;
9735 import std.string : representation;
9736
9737 static struct Rand3Letters
9738 {
9739 enum empty = false;
frontRand3Letters9740 @property auto front() { return _mon; }
popFrontRand3Letters9741 void popFront()
9742 {
9743 import std.exception : assumeUnique;
9744 import std.random : rndGen;
9745 _mon = rndGen.map!(a => letters[a % letters.length])().take(3).array().assumeUnique();
9746 }
9747 string _mon;
startRand3Letters9748 static auto start() { Rand3Letters retval; retval.popFront(); return retval; }
9749 }
9750
9751 foreach (cr; AliasSeq!(function(string a){return cast(char[]) a;},
9752 function(string a){return cast(ubyte[]) a;},
9753 function(string a){return a;},
9754 function(string a){return map!(b => cast(char) b)(a.representation);}))
9755 (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396
9756 scope(failure) writeln(typeof(cr).stringof);
9757 alias test = testParse822!cr;
9758 alias testBad = testBadParse822!cr;
9759
9760 immutable std1 = DateTime(2012, 12, 21, 13, 14, 15);
9761 immutable std2 = DateTime(2012, 12, 21, 13, 14, 0);
9762 immutable dst1 = DateTime(1976, 7, 4, 5, 4, 22);
9763 immutable dst2 = DateTime(1976, 7, 4, 5, 4, 0);
9764
9765 test("21 Dec 2012 13:14:15 +0000", SysTime(std1, UTC()));
9766 test("21 Dec 2012 13:14 +0000", SysTime(std2, UTC()));
9767 test("Fri, 21 Dec 2012 13:14 +0000", SysTime(std2, UTC()));
9768 test("Fri, 21 Dec 2012 13:14:15 +0000", SysTime(std1, UTC()));
9769
9770 test("04 Jul 1976 05:04:22 +0000", SysTime(dst1, UTC()));
9771 test("04 Jul 1976 05:04 +0000", SysTime(dst2, UTC()));
9772 test("Sun, 04 Jul 1976 05:04 +0000", SysTime(dst2, UTC()));
9773 test("Sun, 04 Jul 1976 05:04:22 +0000", SysTime(dst1, UTC()));
9774
9775 test("4 Jul 1976 05:04:22 +0000", SysTime(dst1, UTC()));
9776 test("4 Jul 1976 05:04 +0000", SysTime(dst2, UTC()));
9777 test("Sun, 4 Jul 1976 05:04 +0000", SysTime(dst2, UTC()));
9778 test("Sun, 4 Jul 1976 05:04:22 +0000", SysTime(dst1, UTC()));
9779
9780 auto badTZ = new immutable SimpleTimeZone(Duration.zero);
9781 test("21 Dec 2012 13:14:15 -0000", SysTime(std1, badTZ));
9782 test("21 Dec 2012 13:14 -0000", SysTime(std2, badTZ));
9783 test("Fri, 21 Dec 2012 13:14 -0000", SysTime(std2, badTZ));
9784 test("Fri, 21 Dec 2012 13:14:15 -0000", SysTime(std1, badTZ));
9785
9786 test("04 Jul 1976 05:04:22 -0000", SysTime(dst1, badTZ));
9787 test("04 Jul 1976 05:04 -0000", SysTime(dst2, badTZ));
9788 test("Sun, 04 Jul 1976 05:04 -0000", SysTime(dst2, badTZ));
9789 test("Sun, 04 Jul 1976 05:04:22 -0000", SysTime(dst1, badTZ));
9790
9791 test("4 Jul 1976 05:04:22 -0000", SysTime(dst1, badTZ));
9792 test("4 Jul 1976 05:04 -0000", SysTime(dst2, badTZ));
9793 test("Sun, 4 Jul 1976 05:04 -0000", SysTime(dst2, badTZ));
9794 test("Sun, 4 Jul 1976 05:04:22 -0000", SysTime(dst1, badTZ));
9795
9796 auto pst = new immutable SimpleTimeZone(dur!"hours"(-8));
9797 auto pdt = new immutable SimpleTimeZone(dur!"hours"(-7));
9798 test("21 Dec 2012 13:14:15 -0800", SysTime(std1, pst));
9799 test("21 Dec 2012 13:14 -0800", SysTime(std2, pst));
9800 test("Fri, 21 Dec 2012 13:14 -0800", SysTime(std2, pst));
9801 test("Fri, 21 Dec 2012 13:14:15 -0800", SysTime(std1, pst));
9802
9803 test("04 Jul 1976 05:04:22 -0700", SysTime(dst1, pdt));
9804 test("04 Jul 1976 05:04 -0700", SysTime(dst2, pdt));
9805 test("Sun, 04 Jul 1976 05:04 -0700", SysTime(dst2, pdt));
9806 test("Sun, 04 Jul 1976 05:04:22 -0700", SysTime(dst1, pdt));
9807
9808 test("4 Jul 1976 05:04:22 -0700", SysTime(dst1, pdt));
9809 test("4 Jul 1976 05:04 -0700", SysTime(dst2, pdt));
9810 test("Sun, 4 Jul 1976 05:04 -0700", SysTime(dst2, pdt));
9811 test("Sun, 4 Jul 1976 05:04:22 -0700", SysTime(dst1, pdt));
9812
9813 auto cet = new immutable SimpleTimeZone(dur!"hours"(1));
9814 auto cest = new immutable SimpleTimeZone(dur!"hours"(2));
9815 test("21 Dec 2012 13:14:15 +0100", SysTime(std1, cet));
9816 test("21 Dec 2012 13:14 +0100", SysTime(std2, cet));
9817 test("Fri, 21 Dec 2012 13:14 +0100", SysTime(std2, cet));
9818 test("Fri, 21 Dec 2012 13:14:15 +0100", SysTime(std1, cet));
9819
9820 test("04 Jul 1976 05:04:22 +0200", SysTime(dst1, cest));
9821 test("04 Jul 1976 05:04 +0200", SysTime(dst2, cest));
9822 test("Sun, 04 Jul 1976 05:04 +0200", SysTime(dst2, cest));
9823 test("Sun, 04 Jul 1976 05:04:22 +0200", SysTime(dst1, cest));
9824
9825 test("4 Jul 1976 05:04:22 +0200", SysTime(dst1, cest));
9826 test("4 Jul 1976 05:04 +0200", SysTime(dst2, cest));
9827 test("Sun, 4 Jul 1976 05:04 +0200", SysTime(dst2, cest));
9828 test("Sun, 4 Jul 1976 05:04:22 +0200", SysTime(dst1, cest));
9829
9830 // dst and std times are switched in the Southern Hemisphere which is why the
9831 // time zone names and DateTime variables don't match.
9832 auto cstStd = new immutable SimpleTimeZone(dur!"hours"(9) + dur!"minutes"(30));
9833 auto cstDST = new immutable SimpleTimeZone(dur!"hours"(10) + dur!"minutes"(30));
9834 test("21 Dec 2012 13:14:15 +1030", SysTime(std1, cstDST));
9835 test("21 Dec 2012 13:14 +1030", SysTime(std2, cstDST));
9836 test("Fri, 21 Dec 2012 13:14 +1030", SysTime(std2, cstDST));
9837 test("Fri, 21 Dec 2012 13:14:15 +1030", SysTime(std1, cstDST));
9838
9839 test("04 Jul 1976 05:04:22 +0930", SysTime(dst1, cstStd));
9840 test("04 Jul 1976 05:04 +0930", SysTime(dst2, cstStd));
9841 test("Sun, 04 Jul 1976 05:04 +0930", SysTime(dst2, cstStd));
9842 test("Sun, 04 Jul 1976 05:04:22 +0930", SysTime(dst1, cstStd));
9843
9844 test("4 Jul 1976 05:04:22 +0930", SysTime(dst1, cstStd));
9845 test("4 Jul 1976 05:04 +0930", SysTime(dst2, cstStd));
9846 test("Sun, 4 Jul 1976 05:04 +0930", SysTime(dst2, cstStd));
9847 test("Sun, 4 Jul 1976 05:04:22 +0930", SysTime(dst1, cstStd));
9848
foreach(int i,mon;_monthNames)9849 foreach (int i, mon; _monthNames)
9850 {
9851 test(format("17 %s 2012 00:05:02 +0000", mon), SysTime(DateTime(2012, i + 1, 17, 0, 5, 2), UTC()));
9852 test(format("17 %s 2012 00:05 +0000", mon), SysTime(DateTime(2012, i + 1, 17, 0, 5, 0), UTC()));
9853 }
9854
9855 import std.uni : toLower, toUpper;
9856 foreach (mon; chain(_monthNames[].map!(a => toLower(a))(),
9857 _monthNames[].map!(a => toUpper(a))(),
9858 ["Jam", "Jen", "Fec", "Fdb", "Mas", "Mbr", "Aps", "Aqr", "Mai", "Miy",
9859 "Jum", "Jbn", "Jup", "Jal", "Aur", "Apg", "Sem", "Sap", "Ocm", "Odt",
9860 "Nom", "Nav", "Dem", "Dac"],
9861 Rand3Letters.start().filter!(a => !_monthNames[].canFind(a)).take(20)))
9862 {
9863 scope(failure) writefln("Month: %s", mon);
9864 testBad(format("17 %s 2012 00:05:02 +0000", mon));
9865 testBad(format("17 %s 2012 00:05 +0000", mon));
9866 }
9867
9868 immutable string[7] daysOfWeekNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
9869
9870 {
9871 auto start = SysTime(DateTime(2012, 11, 11, 9, 42, 0), UTC());
9872 int day = 11;
9873
foreach(int i,dow;daysOfWeekNames)9874 foreach (int i, dow; daysOfWeekNames)
9875 {
9876 auto curr = start + dur!"days"(i);
9877 test(format("%s, %s Nov 2012 09:42:00 +0000", dow, day), curr);
9878 test(format("%s, %s Nov 2012 09:42 +0000", dow, day++), curr);
9879
9880 // Whether the day of the week matches the date is ignored.
9881 test(format("%s, 11 Nov 2012 09:42:00 +0000", dow), start);
9882 test(format("%s, 11 Nov 2012 09:42 +0000", dow), start);
9883 }
9884 }
9885
9886 foreach (dow; chain(daysOfWeekNames[].map!(a => toLower(a))(),
9887 daysOfWeekNames[].map!(a => toUpper(a))(),
9888 ["Sum", "Spn", "Mom", "Man", "Tuf", "Tae", "Wem", "Wdd", "The", "Tur",
9889 "Fro", "Fai", "San", "Sut"],
9890 Rand3Letters.start().filter!(a => !daysOfWeekNames[].canFind(a)).take(20)))
9891 {
9892 scope(failure) writefln("Day of Week: %s", dow);
9893 testBad(format("%s, 11 Nov 2012 09:42:00 +0000", dow));
9894 testBad(format("%s, 11 Nov 2012 09:42 +0000", dow));
9895 }
9896
9897 testBad("31 Dec 1899 23:59:59 +0000");
9898 test("01 Jan 1900 00:00:00 +0000", SysTime(Date(1900, 1, 1), UTC()));
9899 test("01 Jan 1900 00:00:00 -0000", SysTime(Date(1900, 1, 1),
9900 new immutable SimpleTimeZone(Duration.zero)));
9901 test("01 Jan 1900 00:00:00 -0700", SysTime(Date(1900, 1, 1),
9902 new immutable SimpleTimeZone(dur!"hours"(-7))));
9903
9904 {
9905 auto st1 = SysTime(Date(1900, 1, 1), UTC());
9906 auto st2 = SysTime(Date(1900, 1, 1), new immutable SimpleTimeZone(dur!"hours"(-11)));
9907 foreach (i; 1900 .. 2102)
9908 {
9909 test(format("1 Jan %05d 00:00 +0000", i), st1);
9910 test(format("1 Jan %05d 00:00 -1100", i), st2);
9911 st1.add!"years"(1);
9912 st2.add!"years"(1);
9913 }
9914 st1.year = 9998;
9915 st2.year = 9998;
9916 foreach (i; 9998 .. 11_002)
9917 {
9918 test(format("1 Jan %05d 00:00 +0000", i), st1);
9919 test(format("1 Jan %05d 00:00 -1100", i), st2);
9920 st1.add!"years"(1);
9921 st2.add!"years"(1);
9922 }
9923 }
9924
9925 testBad("12 Feb 1907 23:17:09 0000");
9926 testBad("12 Feb 1907 23:17:09 +000");
9927 testBad("12 Feb 1907 23:17:09 -000");
9928 testBad("12 Feb 1907 23:17:09 +00000");
9929 testBad("12 Feb 1907 23:17:09 -00000");
9930 testBad("12 Feb 1907 23:17:09 +A");
9931 testBad("12 Feb 1907 23:17:09 +PST");
9932 testBad("12 Feb 1907 23:17:09 -A");
9933 testBad("12 Feb 1907 23:17:09 -PST");
9934
9935 // test trailing stuff that gets ignored
9936 {
9937 foreach (c; chain(iota(0, 33), ['('], iota(127, ubyte.max + 1)))
9938 {
9939 scope(failure) writefln("c: %d", c);
9940 test(format("21 Dec 2012 13:14:15 +0000%c", cast(char) c), SysTime(std1, UTC()));
9941 test(format("21 Dec 2012 13:14:15 +0000%c ", cast(char) c), SysTime(std1, UTC()));
9942 test(format("21 Dec 2012 13:14:15 +0000%chello", cast(char) c), SysTime(std1, UTC()));
9943 }
9944 }
9945
9946 // test trailing stuff that doesn't get ignored
9947 {
9948 foreach (c; chain(iota(33, '('), iota('(' + 1, 127)))
9949 {
9950 scope(failure) writefln("c: %d", c);
9951 testBad(format("21 Dec 2012 13:14:15 +0000%c", cast(char) c));
9952 testBad(format("21 Dec 2012 13:14:15 +0000%c ", cast(char) c));
9953 testBad(format("21 Dec 2012 13:14:15 +0000%chello", cast(char) c));
9954 }
9955 }
9956
9957 testBad("32 Jan 2012 12:13:14 -0800");
9958 testBad("31 Jan 2012 24:13:14 -0800");
9959 testBad("31 Jan 2012 12:60:14 -0800");
9960 testBad("31 Jan 2012 12:13:61 -0800");
9961 testBad("31 Jan 2012 12:13:14 -0860");
9962 test("31 Jan 2012 12:13:14 -0859",
9963 SysTime(DateTime(2012, 1, 31, 12, 13, 14),
9964 new immutable SimpleTimeZone(dur!"hours"(-8) + dur!"minutes"(-59))));
9965
9966 // leap-seconds
9967 test("21 Dec 2012 15:59:60 -0800", SysTime(DateTime(2012, 12, 21, 15, 59, 59), pst));
9968
9969 // FWS
9970 test("Sun,4 Jul 1976 05:04 +0930", SysTime(dst2, cstStd));
9971 test("Sun,4 Jul 1976 05:04:22 +0930", SysTime(dst1, cstStd));
9972 test("Sun,4 Jul 1976 05:04 +0930 (foo)", SysTime(dst2, cstStd));
9973 test("Sun,4 Jul 1976 05:04:22 +0930 (foo)", SysTime(dst1, cstStd));
9974 test("Sun,4 \r\n Jul \r\n 1976 \r\n 05:04 \r\n +0930 \r\n (foo)", SysTime(dst2, cstStd));
9975 test("Sun,4 \r\n Jul \r\n 1976 \r\n 05:04:22 \r\n +0930 \r\n (foo)", SysTime(dst1, cstStd));
9976
9977 auto str = "01 Jan 2012 12:13:14 -0800 ";
9978 test(str, SysTime(DateTime(2012, 1, 1, 12, 13, 14), new immutable SimpleTimeZone(hours(-8))));
9979 foreach (i; 0 .. str.length)
9980 {
9981 auto currStr = str.dup;
9982 currStr[i] = 'x';
9983 scope(failure) writefln("failed: %s", currStr);
9984 testBad(cast(string) currStr);
9985 }
9986 foreach (i; 2 .. str.length)
9987 {
9988 auto currStr = str[0 .. $ - i];
9989 scope(failure) writefln("failed: %s", currStr);
9990 testBad(cast(string) currStr);
9991 testBad((cast(string) currStr) ~ " ");
9992 }
9993 }();
9994 }
9995
9996 // Obsolete Format per section 4.3 of RFC 5322.
9997 @system unittest
9998 {
9999 import std.algorithm.iteration : filter, map;
10000 import std.ascii : letters;
10001 import std.exception : collectExceptionMsg;
10002 import std.format : format;
10003 import std.meta : AliasSeq;
10004 import std.range : chain, iota;
10005 import std.stdio : writefln, writeln;
10006 import std.string : representation;
10007
10008 auto std1 = SysTime(DateTime(2012, 12, 21, 13, 14, 15), UTC());
10009 auto std2 = SysTime(DateTime(2012, 12, 21, 13, 14, 0), UTC());
10010 auto std3 = SysTime(DateTime(1912, 12, 21, 13, 14, 15), UTC());
10011 auto std4 = SysTime(DateTime(1912, 12, 21, 13, 14, 0), UTC());
10012 auto dst1 = SysTime(DateTime(1976, 7, 4, 5, 4, 22), UTC());
10013 auto dst2 = SysTime(DateTime(1976, 7, 4, 5, 4, 0), UTC());
10014 auto tooLate1 = SysTime(Date(10_000, 1, 1), UTC());
10015 auto tooLate2 = SysTime(DateTime(12_007, 12, 31, 12, 22, 19), UTC());
10016
10017 foreach (cr; AliasSeq!(function(string a){return cast(char[]) a;},
10018 function(string a){return cast(ubyte[]) a;},
10019 function(string a){return a;},
10020 function(string a){return map!(b => cast(char) b)(a.representation);}))
10021 (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396
10022 scope(failure) writeln(typeof(cr).stringof);
10023 alias test = testParse822!cr;
10024 {
10025 auto list = ["", " ", " \r\n\t", "\t\r\n (hello world( frien(dog)) silly \r\n ) \t\t \r\n ()",
10026 " \n ", "\t\n\t", " \n\t (foo) \n (bar) \r\n (baz) \n "];
10027
foreach(i,cfws;list)10028 foreach (i, cfws; list)
10029 {
10030 scope(failure) writefln("i: %s", i);
10031
10032 test(format("%1$s21%1$sDec%1$s2012%1$s13:14:15%1$s+0000%1$s", cfws), std1);
10033 test(format("%1$s21%1$sDec%1$s2012%1$s13:14%1$s+0000%1$s", cfws), std2);
10034 test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s2012%1$s13:14%1$s+0000%1$s", cfws), std2);
10035 test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s2012%1$s13:14:15%1$s+0000%1$s", cfws), std1);
10036
10037 test(format("%1$s04%1$sJul%1$s1976%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10038 test(format("%1$s04%1$sJul%1$s1976%1$s05:04%1$s+0000%1$s", cfws), dst2);
10039 test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s1976%1$s05:04%1$s+0000%1$s", cfws), dst2);
10040 test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s1976%1$s05:04:22 +0000%1$s", cfws), dst1);
10041
10042 test(format("%1$s4%1$sJul%1$s1976%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10043 test(format("%1$s4%1$sJul%1$s1976%1$s05:04%1$s+0000%1$s", cfws), dst2);
10044 test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s1976%1$s05:04%1$s+0000%1$s", cfws), dst2);
10045 test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s1976%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10046
10047 test(format("%1$s21%1$sDec%1$s12%1$s13:14:15%1$s+0000%1$s", cfws), std1);
10048 test(format("%1$s21%1$sDec%1$s12%1$s13:14%1$s+0000%1$s", cfws), std2);
10049 test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s12%1$s13:14%1$s+0000%1$s", cfws), std2);
10050 test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s12%1$s13:14:15%1$s+0000%1$s", cfws), std1);
10051
10052 test(format("%1$s04%1$sJul%1$s76%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10053 test(format("%1$s04%1$sJul%1$s76%1$s05:04%1$s+0000%1$s", cfws), dst2);
10054 test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s76%1$s05:04%1$s+0000%1$s", cfws), dst2);
10055 test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s76%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10056
10057 test(format("%1$s4%1$sJul%1$s76 05:04:22%1$s+0000%1$s", cfws), dst1);
10058 test(format("%1$s4%1$sJul%1$s76 05:04%1$s+0000%1$s", cfws), dst2);
10059 test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s76%1$s05:04%1$s+0000%1$s", cfws), dst2);
10060 test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s76%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10061
10062 test(format("%1$s21%1$sDec%1$s012%1$s13:14:15%1$s+0000%1$s", cfws), std3);
10063 test(format("%1$s21%1$sDec%1$s012%1$s13:14%1$s+0000%1$s", cfws), std4);
10064 test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s012%1$s13:14%1$s+0000%1$s", cfws), std4);
10065 test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s012%1$s13:14:15%1$s+0000%1$s", cfws), std3);
10066
10067 test(format("%1$s04%1$sJul%1$s076%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10068 test(format("%1$s04%1$sJul%1$s076%1$s05:04%1$s+0000%1$s", cfws), dst2);
10069 test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s076%1$s05:04%1$s+0000%1$s", cfws), dst2);
10070 test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s076%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10071
10072 test(format("%1$s4%1$sJul%1$s076%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10073 test(format("%1$s4%1$sJul%1$s076%1$s05:04%1$s+0000%1$s", cfws), dst2);
10074 test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s076%1$s05:04%1$s+0000%1$s", cfws), dst2);
10075 test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s076%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10076
10077 test(format("%1$s1%1$sJan%1$s10000%1$s00:00:00%1$s+0000%1$s", cfws), tooLate1);
10078 test(format("%1$s31%1$sDec%1$s12007%1$s12:22:19%1$s+0000%1$s", cfws), tooLate2);
10079 test(format("%1$sSat%1$s,%1$s1%1$sJan%1$s10000%1$s00:00:00%1$s+0000%1$s", cfws), tooLate1);
10080 test(format("%1$sSun%1$s,%1$s31%1$sDec%1$s12007%1$s12:22:19%1$s+0000%1$s", cfws), tooLate2);
10081 }
10082 }
10083
10084 // test years of 1, 2, and 3 digits.
10085 {
10086 auto st1 = SysTime(Date(2000, 1, 1), UTC());
10087 auto st2 = SysTime(Date(2000, 1, 1), new immutable SimpleTimeZone(dur!"hours"(-12)));
10088 foreach (i; 0 .. 50)
10089 {
10090 test(format("1 Jan %02d 00:00 GMT", i), st1);
10091 test(format("1 Jan %02d 00:00 -1200", i), st2);
10092 st1.add!"years"(1);
10093 st2.add!"years"(1);
10094 }
10095 }
10096
10097 {
10098 auto st1 = SysTime(Date(1950, 1, 1), UTC());
10099 auto st2 = SysTime(Date(1950, 1, 1), new immutable SimpleTimeZone(dur!"hours"(-12)));
10100 foreach (i; 50 .. 100)
10101 {
10102 test(format("1 Jan %02d 00:00 GMT", i), st1);
10103 test(format("1 Jan %02d 00:00 -1200", i), st2);
10104 st1.add!"years"(1);
10105 st2.add!"years"(1);
10106 }
10107 }
10108
10109 {
10110 auto st1 = SysTime(Date(1900, 1, 1), UTC());
10111 auto st2 = SysTime(Date(1900, 1, 1), new immutable SimpleTimeZone(dur!"hours"(-11)));
10112 foreach (i; 0 .. 1000)
10113 {
10114 test(format("1 Jan %03d 00:00 GMT", i), st1);
10115 test(format("1 Jan %03d 00:00 -1100", i), st2);
10116 st1.add!"years"(1);
10117 st2.add!"years"(1);
10118 }
10119 }
10120
10121 foreach (i; 0 .. 10)
10122 {
10123 auto str1 = cr(format("1 Jan %d 00:00 GMT", i));
10124 auto str2 = cr(format("1 Jan %d 00:00 -1200", i));
10125 assertThrown!DateTimeException(parseRFC822DateTime(str1));
10126 assertThrown!DateTimeException(parseRFC822DateTime(str1));
10127 }
10128
10129 // test time zones
10130 {
10131 auto dt = DateTime(1982, 05, 03, 12, 22, 04);
10132 test("Wed, 03 May 1982 12:22:04 UT", SysTime(dt, UTC()));
10133 test("Wed, 03 May 1982 12:22:04 GMT", SysTime(dt, UTC()));
10134 test("Wed, 03 May 1982 12:22:04 EST", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-5))));
10135 test("Wed, 03 May 1982 12:22:04 EDT", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-4))));
10136 test("Wed, 03 May 1982 12:22:04 CST", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-6))));
10137 test("Wed, 03 May 1982 12:22:04 CDT", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-5))));
10138 test("Wed, 03 May 1982 12:22:04 MST", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-7))));
10139 test("Wed, 03 May 1982 12:22:04 MDT", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-6))));
10140 test("Wed, 03 May 1982 12:22:04 PST", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-8))));
10141 test("Wed, 03 May 1982 12:22:04 PDT", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-7))));
10142
10143 auto badTZ = new immutable SimpleTimeZone(Duration.zero);
10144 foreach (dchar c; filter!(a => a != 'j' && a != 'J')(letters))
10145 {
10146 scope(failure) writefln("c: %s", c);
10147 test(format("Wed, 03 May 1982 12:22:04 %s", c), SysTime(dt, badTZ));
10148 test(format("Wed, 03 May 1982 12:22:04%s", c), SysTime(dt, badTZ));
10149 }
10150
foreach(dchar c;['j','J'])10151 foreach (dchar c; ['j', 'J'])
10152 {
10153 scope(failure) writefln("c: %s", c);
10154 assertThrown!DateTimeException(parseRFC822DateTime(cr(format("Wed, 03 May 1982 12:22:04 %s", c))));
10155 assertThrown!DateTimeException(parseRFC822DateTime(cr(format("Wed, 03 May 1982 12:22:04%s", c))));
10156 }
10157
foreach(string s;["AAA","GQW","DDT","PDA","GT","GM"])10158 foreach (string s; ["AAA", "GQW", "DDT", "PDA", "GT", "GM"])
10159 {
10160 scope(failure) writefln("s: %s", s);
10161 test(format("Wed, 03 May 1982 12:22:04 %s", s), SysTime(dt, badTZ));
10162 }
10163
10164 // test trailing stuff that gets ignored
10165 {
10166 foreach (c; chain(iota(0, 33), ['('], iota(127, ubyte.max + 1)))
10167 {
10168 scope(failure) writefln("c: %d", c);
10169 test(format("21Dec1213:14:15+0000%c", cast(char) c), std1);
10170 test(format("21Dec1213:14:15+0000%c ", cast(char) c), std1);
10171 test(format("21Dec1213:14:15+0000%chello", cast(char) c), std1);
10172 }
10173 }
10174
10175 // test trailing stuff that doesn't get ignored
10176 {
10177 foreach (c; chain(iota(33, '('), iota('(' + 1, 127)))
10178 {
10179 scope(failure) writefln("c: %d", c);
10180 assertThrown!DateTimeException(
10181 parseRFC822DateTime(cr(format("21Dec1213:14:15+0000%c", cast(char) c))));
10182 assertThrown!DateTimeException(
10183 parseRFC822DateTime(cr(format("21Dec1213:14:15+0000%c ", cast(char) c))));
10184 assertThrown!DateTimeException(
10185 parseRFC822DateTime(cr(format("21Dec1213:14:15+0000%chello", cast(char) c))));
10186 }
10187 }
10188 }
10189
10190 // test that the checks for minimum length work correctly and avoid
10191 // any RangeErrors.
10192 test("7Dec1200:00A", SysTime(DateTime(2012, 12, 7, 00, 00, 00),
10193 new immutable SimpleTimeZone(Duration.zero)));
10194 test("Fri,7Dec1200:00A", SysTime(DateTime(2012, 12, 7, 00, 00, 00),
10195 new immutable SimpleTimeZone(Duration.zero)));
10196 test("7Dec1200:00:00A", SysTime(DateTime(2012, 12, 7, 00, 00, 00),
10197 new immutable SimpleTimeZone(Duration.zero)));
10198 test("Fri,7Dec1200:00:00A", SysTime(DateTime(2012, 12, 7, 00, 00, 00),
10199 new immutable SimpleTimeZone(Duration.zero)));
10200
10201 auto tooShortMsg = collectExceptionMsg!DateTimeException(parseRFC822DateTime(""));
foreach(str;["Fri,7Dec1200:00:00","7Dec1200:00:00"])10202 foreach (str; ["Fri,7Dec1200:00:00", "7Dec1200:00:00"])
10203 {
10204 foreach (i; 0 .. str.length)
10205 {
10206 auto value = str[0 .. $ - i];
10207 scope(failure) writeln(value);
10208 assert(collectExceptionMsg!DateTimeException(parseRFC822DateTime(value)) == tooShortMsg);
10209 }
10210 }
10211 }();
10212 }
10213
10214
10215 private:
10216
10217 /+
10218 Returns the given hnsecs as an ISO string of fractional seconds.
10219 +/
fracSecsToISOString(int hnsecs)10220 static string fracSecsToISOString(int hnsecs) @safe pure nothrow
10221 {
10222 assert(hnsecs >= 0);
10223
10224 try
10225 {
10226 if (hnsecs == 0)
10227 return "";
10228
10229 string isoString = format(".%07d", hnsecs);
10230
10231 while (isoString[$ - 1] == '0')
10232 isoString.popBack();
10233
10234 return isoString;
10235 }
10236 catch (Exception e)
10237 assert(0, "format() threw.");
10238 }
10239
10240 @safe unittest
10241 {
10242 assert(fracSecsToISOString(0) == "");
10243 assert(fracSecsToISOString(1) == ".0000001");
10244 assert(fracSecsToISOString(10) == ".000001");
10245 assert(fracSecsToISOString(100) == ".00001");
10246 assert(fracSecsToISOString(1000) == ".0001");
10247 assert(fracSecsToISOString(10_000) == ".001");
10248 assert(fracSecsToISOString(100_000) == ".01");
10249 assert(fracSecsToISOString(1_000_000) == ".1");
10250 assert(fracSecsToISOString(1_000_001) == ".1000001");
10251 assert(fracSecsToISOString(1_001_001) == ".1001001");
10252 assert(fracSecsToISOString(1_071_601) == ".1071601");
10253 assert(fracSecsToISOString(1_271_641) == ".1271641");
10254 assert(fracSecsToISOString(9_999_999) == ".9999999");
10255 assert(fracSecsToISOString(9_999_990) == ".999999");
10256 assert(fracSecsToISOString(9_999_900) == ".99999");
10257 assert(fracSecsToISOString(9_999_000) == ".9999");
10258 assert(fracSecsToISOString(9_990_000) == ".999");
10259 assert(fracSecsToISOString(9_900_000) == ".99");
10260 assert(fracSecsToISOString(9_000_000) == ".9");
10261 assert(fracSecsToISOString(999) == ".0000999");
10262 assert(fracSecsToISOString(9990) == ".000999");
10263 assert(fracSecsToISOString(99_900) == ".00999");
10264 assert(fracSecsToISOString(999_000) == ".0999");
10265 }
10266
10267
10268 /+
10269 Returns a Duration corresponding to to the given ISO string of
10270 fractional seconds.
10271 +/
10272 static Duration fracSecsFromISOString(S)(in S isoString) @trusted pure
10273 if (isSomeString!S)
10274 {
10275 import std.algorithm.searching : all;
10276 import std.ascii : isDigit;
10277 import std.conv : to;
10278 import std.string : representation;
10279
10280 if (isoString.empty)
10281 return Duration.zero;
10282
10283 auto str = isoString.representation;
10284
10285 enforce(str[0] == '.', new DateTimeException("Invalid ISO String"));
10286 str.popFront();
10287
10288 enforce(!str.empty && all!isDigit(str), new DateTimeException("Invalid ISO String"));
10289
10290 dchar[7] fullISOString = void;
foreach(i,ref dchar c;fullISOString)10291 foreach (i, ref dchar c; fullISOString)
10292 {
10293 if (i < str.length)
10294 c = str[i];
10295 else
10296 c = '0';
10297 }
10298
10299 return hnsecs(to!int(fullISOString[]));
10300 }
10301
10302 @safe unittest
10303 {
testFSInvalid(string isoString)10304 static void testFSInvalid(string isoString)
10305 {
10306 fracSecsFromISOString(isoString);
10307 }
10308
10309 assertThrown!DateTimeException(testFSInvalid("."));
10310 assertThrown!DateTimeException(testFSInvalid("0."));
10311 assertThrown!DateTimeException(testFSInvalid("0"));
10312 assertThrown!DateTimeException(testFSInvalid("0000000"));
10313 assertThrown!DateTimeException(testFSInvalid("T"));
10314 assertThrown!DateTimeException(testFSInvalid("T."));
10315 assertThrown!DateTimeException(testFSInvalid(".T"));
10316 assertThrown!DateTimeException(testFSInvalid(".00000Q0"));
10317 assertThrown!DateTimeException(testFSInvalid(".000000Q"));
10318 assertThrown!DateTimeException(testFSInvalid(".0000000Q"));
10319 assertThrown!DateTimeException(testFSInvalid(".0000000000Q"));
10320
10321 assert(fracSecsFromISOString("") == Duration.zero);
10322 assert(fracSecsFromISOString(".0000001") == hnsecs(1));
10323 assert(fracSecsFromISOString(".000001") == hnsecs(10));
10324 assert(fracSecsFromISOString(".00001") == hnsecs(100));
10325 assert(fracSecsFromISOString(".0001") == hnsecs(1000));
10326 assert(fracSecsFromISOString(".001") == hnsecs(10_000));
10327 assert(fracSecsFromISOString(".01") == hnsecs(100_000));
10328 assert(fracSecsFromISOString(".1") == hnsecs(1_000_000));
10329 assert(fracSecsFromISOString(".1000001") == hnsecs(1_000_001));
10330 assert(fracSecsFromISOString(".1001001") == hnsecs(1_001_001));
10331 assert(fracSecsFromISOString(".1071601") == hnsecs(1_071_601));
10332 assert(fracSecsFromISOString(".1271641") == hnsecs(1_271_641));
10333 assert(fracSecsFromISOString(".9999999") == hnsecs(9_999_999));
10334 assert(fracSecsFromISOString(".9999990") == hnsecs(9_999_990));
10335 assert(fracSecsFromISOString(".999999") == hnsecs(9_999_990));
10336 assert(fracSecsFromISOString(".9999900") == hnsecs(9_999_900));
10337 assert(fracSecsFromISOString(".99999") == hnsecs(9_999_900));
10338 assert(fracSecsFromISOString(".9999000") == hnsecs(9_999_000));
10339 assert(fracSecsFromISOString(".9999") == hnsecs(9_999_000));
10340 assert(fracSecsFromISOString(".9990000") == hnsecs(9_990_000));
10341 assert(fracSecsFromISOString(".999") == hnsecs(9_990_000));
10342 assert(fracSecsFromISOString(".9900000") == hnsecs(9_900_000));
10343 assert(fracSecsFromISOString(".9900") == hnsecs(9_900_000));
10344 assert(fracSecsFromISOString(".99") == hnsecs(9_900_000));
10345 assert(fracSecsFromISOString(".9000000") == hnsecs(9_000_000));
10346 assert(fracSecsFromISOString(".9") == hnsecs(9_000_000));
10347 assert(fracSecsFromISOString(".0000999") == hnsecs(999));
10348 assert(fracSecsFromISOString(".0009990") == hnsecs(9990));
10349 assert(fracSecsFromISOString(".000999") == hnsecs(9990));
10350 assert(fracSecsFromISOString(".0099900") == hnsecs(99_900));
10351 assert(fracSecsFromISOString(".00999") == hnsecs(99_900));
10352 assert(fracSecsFromISOString(".0999000") == hnsecs(999_000));
10353 assert(fracSecsFromISOString(".0999") == hnsecs(999_000));
10354 assert(fracSecsFromISOString(".00000000") == Duration.zero);
10355 assert(fracSecsFromISOString(".00000001") == Duration.zero);
10356 assert(fracSecsFromISOString(".00000009") == Duration.zero);
10357 assert(fracSecsFromISOString(".1234567890") == hnsecs(1_234_567));
10358 assert(fracSecsFromISOString(".12345678901234567890") == hnsecs(1_234_567));
10359 }
10360
10361
10362 /+
10363 This function is used to split out the units without getting the remaining
10364 hnsecs.
10365
10366 Params:
10367 units = The units to split out.
10368 hnsecs = The current total hnsecs.
10369
10370 Returns:
10371 The split out value.
10372 +/
10373 long getUnitsFromHNSecs(string units)(long hnsecs) @safe pure nothrow
10374 if (validTimeUnits(units) &&
10375 CmpTimeUnits!(units, "months") < 0)
10376 {
10377 return convert!("hnsecs", units)(hnsecs);
10378 }
10379
10380 @safe unittest
10381 {
10382 auto hnsecs = 2595000000007L;
10383 immutable days = getUnitsFromHNSecs!"days"(hnsecs);
10384 assert(days == 3);
10385 assert(hnsecs == 2595000000007L);
10386 }
10387
10388
10389 /+
10390 This function is used to split out the units without getting the units but
10391 just the remaining hnsecs.
10392
10393 Params:
10394 units = The units to split out.
10395 hnsecs = The current total hnsecs.
10396
10397 Returns:
10398 The remaining hnsecs.
10399 +/
10400 long removeUnitsFromHNSecs(string units)(long hnsecs) @safe pure nothrow
10401 if (validTimeUnits(units) &&
10402 CmpTimeUnits!(units, "months") < 0)
10403 {
10404 immutable value = convert!("hnsecs", units)(hnsecs);
10405 return hnsecs - convert!(units, "hnsecs")(value);
10406 }
10407
10408 @safe unittest
10409 {
10410 auto hnsecs = 2595000000007L;
10411 auto returned = removeUnitsFromHNSecs!"days"(hnsecs);
10412 assert(returned == 3000000007);
10413 assert(hnsecs == 2595000000007L);
10414 }
10415
10416
10417 /+
10418 Strips what RFC 5322, section 3.2.2 refers to as CFWS from the left-hand
10419 side of the given range (it strips comments delimited by $(D '(') and
10420 $(D ')') as well as folding whitespace).
10421
10422 It is assumed that the given range contains the value of a header field and
10423 no terminating CRLF for the line (though the CRLF for folding whitespace is
10424 of course expected and stripped) and thus that the only case of CR or LF is
10425 in folding whitespace.
10426
10427 If a comment does not terminate correctly (e.g. mismatched parens) or if the
10428 the FWS is malformed, then the range will be empty when stripCWFS is done.
10429 However, only minimal validation of the content is done (e.g. quoted pairs
10430 within a comment aren't validated beyond \$LPAREN or \$RPAREN, because
10431 they're inside a comment, and thus their value doesn't matter anyway). It's
10432 only when the content does not conform to the grammar rules for FWS and thus
10433 literally cannot be parsed that content is considered invalid, and an empty
10434 range is returned.
10435
10436 Note that _stripCFWS is eager, not lazy. It does not create a new range.
10437 Rather, it pops off the CFWS from the range and returns it.
10438 +/
10439 R _stripCFWS(R)(R range)
10440 if (isRandomAccessRange!R && hasSlicing!R && hasLength!R &&
10441 (is(Unqual!(ElementType!R) == char) || is(Unqual!(ElementType!R) == ubyte)))
10442 {
10443 immutable e = range.length;
10444 outer: for (size_t i = 0; i < e; )
10445 {
10446 switch (range[i])
10447 {
10448 case ' ': case '\t':
10449 {
10450 ++i;
10451 break;
10452 }
10453 case '\r':
10454 {
10455 if (i + 2 < e && range[i + 1] == '\n' && (range[i + 2] == ' ' || range[i + 2] == '\t'))
10456 {
10457 i += 3;
10458 break;
10459 }
10460 break outer;
10461 }
10462 case '\n':
10463 {
10464 if (i + 1 < e && (range[i + 1] == ' ' || range[i + 1] == '\t'))
10465 {
10466 i += 2;
10467 break;
10468 }
10469 break outer;
10470 }
10471 case '(':
10472 {
10473 ++i;
10474 size_t commentLevel = 1;
10475 while (i < e)
10476 {
10477 if (range[i] == '(')
10478 ++commentLevel;
10479 else if (range[i] == ')')
10480 {
10481 ++i;
10482 if (--commentLevel == 0)
10483 continue outer;
10484 continue;
10485 }
10486 else if (range[i] == '\\')
10487 {
10488 if (++i == e)
10489 break outer;
10490 }
10491 ++i;
10492 }
10493 break outer;
10494 }
10495 default: return range[i .. e];
10496 }
10497 }
10498 return range[e .. e];
10499 }
10500
10501 @system unittest
10502 {
10503 import std.algorithm.comparison : equal;
10504 import std.algorithm.iteration : map;
10505 import std.meta : AliasSeq;
10506 import std.stdio : writeln;
10507 import std.string : representation;
10508
10509 foreach (cr; AliasSeq!(function(string a){return cast(ubyte[]) a;},
10510 function(string a){return map!(b => cast(char) b)(a.representation);}))
10511 (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396
10512 scope(failure) writeln(typeof(cr).stringof);
10513
10514 assert(_stripCFWS(cr("")).empty);
10515 assert(_stripCFWS(cr("\r")).empty);
10516 assert(_stripCFWS(cr("\r\n")).empty);
10517 assert(_stripCFWS(cr("\r\n ")).empty);
10518 assert(_stripCFWS(cr(" \t\r\n")).empty);
10519 assert(equal(_stripCFWS(cr(" \t\r\n hello")), cr("hello")));
10520 assert(_stripCFWS(cr(" \t\r\nhello")).empty);
10521 assert(_stripCFWS(cr(" \t\r\n\v")).empty);
10522 assert(equal(_stripCFWS(cr("\v \t\r\n\v")), cr("\v \t\r\n\v")));
10523 assert(_stripCFWS(cr("()")).empty);
10524 assert(_stripCFWS(cr("(hello world)")).empty);
10525 assert(_stripCFWS(cr("(hello world)(hello world)")).empty);
10526 assert(_stripCFWS(cr("(hello world\r\n foo\r where's\nwaldo)")).empty);
10527 assert(_stripCFWS(cr(" \t (hello \tworld\r\n foo\r where's\nwaldo)\t\t ")).empty);
10528 assert(_stripCFWS(cr(" ")).empty);
10529 assert(_stripCFWS(cr("\t\t\t")).empty);
10530 assert(_stripCFWS(cr("\t \r\n\r \n")).empty);
10531 assert(_stripCFWS(cr("(hello world) (can't find waldo) (he's lost)")).empty);
10532 assert(_stripCFWS(cr("(hello\\) world) (can't \\(find waldo) (he's \\(\\)lost)")).empty);
10533 assert(_stripCFWS(cr("(((((")).empty);
10534 assert(_stripCFWS(cr("(((()))")).empty);
10535 assert(_stripCFWS(cr("(((())))")).empty);
10536 assert(equal(_stripCFWS(cr("(((()))))")), cr(")")));
10537 assert(equal(_stripCFWS(cr(")))))")), cr(")))))")));
10538 assert(equal(_stripCFWS(cr("()))))")), cr("))))")));
10539 assert(equal(_stripCFWS(cr(" hello hello ")), cr("hello hello ")));
10540 assert(equal(_stripCFWS(cr("\thello (world)")), cr("hello (world)")));
10541 assert(equal(_stripCFWS(cr(" \r\n \\((\\)) foo")), cr("\\((\\)) foo")));
10542 assert(equal(_stripCFWS(cr(" \r\n (\\((\\))) foo")), cr("foo")));
10543 assert(equal(_stripCFWS(cr(" \r\n (\\(())) foo")), cr(") foo")));
10544 assert(_stripCFWS(cr(" \r\n (((\\))) foo")).empty);
10545
10546 assert(_stripCFWS(cr("(hello)(hello)")).empty);
10547 assert(_stripCFWS(cr(" \r\n (hello)\r\n (hello)")).empty);
10548 assert(_stripCFWS(cr(" \r\n (hello) \r\n (hello) \r\n ")).empty);
10549 assert(_stripCFWS(cr("\t\t\t\t(hello)\t\t\t\t(hello)\t\t\t\t")).empty);
10550 assert(equal(_stripCFWS(cr(" \r\n (hello)\r\n (hello) \r\n hello")), cr("hello")));
10551 assert(equal(_stripCFWS(cr(" \r\n (hello) \r\n (hello) \r\n hello")), cr("hello")));
10552 assert(equal(_stripCFWS(cr("\t\r\n\t(hello)\r\n\t(hello)\t\r\n hello")), cr("hello")));
10553 assert(equal(_stripCFWS(cr("\t\r\n\t(hello)\t\r\n\t(hello)\t\r\n hello")), cr("hello")));
10554 assert(equal(_stripCFWS(cr(" \r\n (hello) \r\n \r\n (hello) \r\n hello")), cr("hello")));
10555 assert(equal(_stripCFWS(cr(" \r\n (hello) \r\n (hello) \r\n \r\n hello")), cr("hello")));
10556 assert(equal(_stripCFWS(cr(" \r\n \r\n (hello)\t\r\n (hello) \r\n hello")), cr("hello")));
10557 assert(equal(_stripCFWS(cr(" \r\n\t\r\n\t(hello)\t\r\n (hello) \r\n hello")), cr("hello")));
10558
10559 assert(equal(_stripCFWS(cr(" (\r\n ( \r\n ) \r\n ) foo")), cr("foo")));
10560 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n ) foo")), cr("foo")));
10561 assert(equal(_stripCFWS(cr(" (\t\r\n ( \r\n ) \r\n ) foo")), cr("foo")));
10562 assert(equal(_stripCFWS(cr(" (\r\n\t( \r\n ) \r\n ) foo")), cr("foo")));
10563 assert(equal(_stripCFWS(cr(" ( \r\n (\t\r\n ) \r\n ) foo")), cr("foo")));
10564 assert(equal(_stripCFWS(cr(" ( \r\n (\r\n ) \r\n ) foo")), cr("foo")));
10565 assert(equal(_stripCFWS(cr(" ( \r\n (\r\n\t) \r\n ) foo")), cr("foo")));
10566 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n) \r\n ) foo")), cr("foo")));
10567 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n )\t\r\n ) foo")), cr("foo")));
10568 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n )\r\n ) foo")), cr("foo")));
10569 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n) foo")), cr("foo")));
10570 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n\t) foo")), cr("foo")));
10571 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n ) \r\n foo")), cr("foo")));
10572 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n )\t\r\n foo")), cr("foo")));
10573 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n )\r\n foo")), cr("foo")));
10574
10575 assert(equal(_stripCFWS(cr(" ( \r\n \r\n ( \r\n \r\n ) \r\n ) foo")), cr("foo")));
10576 assert(equal(_stripCFWS(cr(" ( \r\n \r\n ( \r\n \r\n ) \r\n ) foo")), cr("foo")));
10577 assert(equal(_stripCFWS(cr(" (\t\r\n \r\n ( \r\n \r\n ) \r\n ) foo")), cr("foo")));
10578 assert(equal(_stripCFWS(cr(" (\r\n \r\n\t( \r\n \r\n ) \r\n ) foo")), cr("foo")));
10579 assert(equal(_stripCFWS(cr(" (\r\n \r\n( \r\n \r\n ) \r\n ) foo")), cr("foo")));
10580 assert(equal(_stripCFWS(cr(" (\r\n \r\n ( \r\n \r\n\t) \r\n ) foo")), cr("foo")));
10581 assert(equal(_stripCFWS(cr(" (\r\n \r\n ( \r\n \r\n )\t\r\n ) foo")), cr("foo")));
10582 assert(equal(_stripCFWS(cr(" (\r\n \r\n ( \r\n \r\n )\r\n ) foo")), cr("foo")));
10583
10584 assert(equal(_stripCFWS(cr(" ( \r\n bar \r\n ( \r\n bar \r\n ) \r\n ) foo")), cr("foo")));
10585 assert(equal(_stripCFWS(cr(" ( \r\n () \r\n ( \r\n () \r\n ) \r\n ) foo")), cr("foo")));
10586 assert(equal(_stripCFWS(cr(" ( \r\n \\\\ \r\n ( \r\n \\\\ \r\n ) \r\n ) foo")), cr("foo")));
10587
10588 assert(_stripCFWS(cr("(hello)(hello)")).empty);
10589 assert(_stripCFWS(cr(" \n (hello)\n (hello) \n ")).empty);
10590 assert(_stripCFWS(cr(" \n (hello) \n (hello) \n ")).empty);
10591 assert(equal(_stripCFWS(cr(" \n (hello)\n (hello) \n hello")), cr("hello")));
10592 assert(equal(_stripCFWS(cr(" \n (hello) \n (hello) \n hello")), cr("hello")));
10593 assert(equal(_stripCFWS(cr("\t\n\t(hello)\n\t(hello)\t\n hello")), cr("hello")));
10594 assert(equal(_stripCFWS(cr("\t\n\t(hello)\t\n\t(hello)\t\n hello")), cr("hello")));
10595 assert(equal(_stripCFWS(cr(" \n (hello) \n \n (hello) \n hello")), cr("hello")));
10596 assert(equal(_stripCFWS(cr(" \n (hello) \n (hello) \n \n hello")), cr("hello")));
10597 assert(equal(_stripCFWS(cr(" \n \n (hello)\t\n (hello) \n hello")), cr("hello")));
10598 assert(equal(_stripCFWS(cr(" \n\t\n\t(hello)\t\n (hello) \n hello")), cr("hello")));
10599 }();
10600 }
10601
10602 // This is so that we don't have to worry about std.conv.to throwing. It also
10603 // doesn't have to worry about quite as many cases as std.conv.to, since it
10604 // doesn't have to worry about a sign on the value or about whether it fits.
10605 T _convDigits(T, R)(R str)
10606 if (isIntegral!T && isSigned!T) // The constraints on R were already covered by parseRFC822DateTime.
10607 {
10608 import std.ascii : isDigit;
10609
10610 assert(!str.empty);
10611 T num = 0;
10612 foreach (i; 0 .. str.length)
10613 {
10614 if (i != 0)
10615 num *= 10;
10616 if (!isDigit(str[i]))
10617 return -1;
10618 num += str[i] - '0';
10619 }
10620 return num;
10621 }
10622
10623 @safe unittest
10624 {
10625 import std.conv : to;
10626 import std.range : chain, iota;
10627 import std.stdio : writeln;
10628 foreach (i; chain(iota(0, 101), [250, 999, 1000, 1001, 2345, 9999]))
10629 {
10630 scope(failure) writeln(i);
10631 assert(_convDigits!int(to!string(i)) == i);
10632 }
foreach(str;["-42","+42","1a","1 "," "," 42 "])10633 foreach (str; ["-42", "+42", "1a", "1 ", " ", " 42 "])
10634 {
10635 scope(failure) writeln(str);
10636 assert(_convDigits!int(str) == -1);
10637 }
10638 }
10639
10640
version(unittest)10641 version (unittest)
10642 {
10643 // Variables to help in testing.
10644 Duration currLocalDiffFromUTC;
10645 immutable (TimeZone)[] testTZs;
10646
10647 // All of these helper arrays are sorted in ascending order.
10648 auto testYearsBC = [-1999, -1200, -600, -4, -1, 0];
10649 auto testYearsAD = [1, 4, 1000, 1999, 2000, 2012];
10650
10651 // I'd use a Tuple, but I get forward reference errors if I try.
10652 struct MonthDay
10653 {
10654 Month month;
10655 short day;
10656
10657 this(int m, short d)
10658 {
10659 month = cast(Month) m;
10660 day = d;
10661 }
10662 }
10663
10664 MonthDay[] testMonthDays = [MonthDay(1, 1),
10665 MonthDay(1, 2),
10666 MonthDay(3, 17),
10667 MonthDay(7, 4),
10668 MonthDay(10, 27),
10669 MonthDay(12, 30),
10670 MonthDay(12, 31)];
10671
10672 auto testDays = [1, 2, 9, 10, 16, 20, 25, 28, 29, 30, 31];
10673
10674 auto testTODs = [TimeOfDay(0, 0, 0),
10675 TimeOfDay(0, 0, 1),
10676 TimeOfDay(0, 1, 0),
10677 TimeOfDay(1, 0, 0),
10678 TimeOfDay(13, 13, 13),
10679 TimeOfDay(23, 59, 59)];
10680
10681 auto testHours = [0, 1, 12, 22, 23];
10682 auto testMinSecs = [0, 1, 30, 58, 59];
10683
10684 // Throwing exceptions is incredibly expensive, so we want to use a smaller
10685 // set of values for tests using assertThrown.
10686 auto testTODsThrown = [TimeOfDay(0, 0, 0),
10687 TimeOfDay(13, 13, 13),
10688 TimeOfDay(23, 59, 59)];
10689
10690 Date[] testDatesBC;
10691 Date[] testDatesAD;
10692
10693 DateTime[] testDateTimesBC;
10694 DateTime[] testDateTimesAD;
10695
10696 Duration[] testFracSecs;
10697
10698 SysTime[] testSysTimesBC;
10699 SysTime[] testSysTimesAD;
10700
10701 // I'd use a Tuple, but I get forward reference errors if I try.
10702 struct GregDay { int day; Date date; }
10703 auto testGregDaysBC = [GregDay(-1_373_427, Date(-3760, 9, 7)), // Start of the Hebrew Calendar
10704 GregDay(-735_233, Date(-2012, 1, 1)),
10705 GregDay(-735_202, Date(-2012, 2, 1)),
10706 GregDay(-735_175, Date(-2012, 2, 28)),
10707 GregDay(-735_174, Date(-2012, 2, 29)),
10708 GregDay(-735_173, Date(-2012, 3, 1)),
10709 GregDay(-734_502, Date(-2010, 1, 1)),
10710 GregDay(-734_472, Date(-2010, 1, 31)),
10711 GregDay(-734_471, Date(-2010, 2, 1)),
10712 GregDay(-734_444, Date(-2010, 2, 28)),
10713 GregDay(-734_443, Date(-2010, 3, 1)),
10714 GregDay(-734_413, Date(-2010, 3, 31)),
10715 GregDay(-734_412, Date(-2010, 4, 1)),
10716 GregDay(-734_383, Date(-2010, 4, 30)),
10717 GregDay(-734_382, Date(-2010, 5, 1)),
10718 GregDay(-734_352, Date(-2010, 5, 31)),
10719 GregDay(-734_351, Date(-2010, 6, 1)),
10720 GregDay(-734_322, Date(-2010, 6, 30)),
10721 GregDay(-734_321, Date(-2010, 7, 1)),
10722 GregDay(-734_291, Date(-2010, 7, 31)),
10723 GregDay(-734_290, Date(-2010, 8, 1)),
10724 GregDay(-734_260, Date(-2010, 8, 31)),
10725 GregDay(-734_259, Date(-2010, 9, 1)),
10726 GregDay(-734_230, Date(-2010, 9, 30)),
10727 GregDay(-734_229, Date(-2010, 10, 1)),
10728 GregDay(-734_199, Date(-2010, 10, 31)),
10729 GregDay(-734_198, Date(-2010, 11, 1)),
10730 GregDay(-734_169, Date(-2010, 11, 30)),
10731 GregDay(-734_168, Date(-2010, 12, 1)),
10732 GregDay(-734_139, Date(-2010, 12, 30)),
10733 GregDay(-734_138, Date(-2010, 12, 31)),
10734 GregDay(-731_215, Date(-2001, 1, 1)),
10735 GregDay(-730_850, Date(-2000, 1, 1)),
10736 GregDay(-730_849, Date(-2000, 1, 2)),
10737 GregDay(-730_486, Date(-2000, 12, 30)),
10738 GregDay(-730_485, Date(-2000, 12, 31)),
10739 GregDay(-730_484, Date(-1999, 1, 1)),
10740 GregDay(-694_690, Date(-1901, 1, 1)),
10741 GregDay(-694_325, Date(-1900, 1, 1)),
10742 GregDay(-585_118, Date(-1601, 1, 1)),
10743 GregDay(-584_753, Date(-1600, 1, 1)),
10744 GregDay(-584_388, Date(-1600, 12, 31)),
10745 GregDay(-584_387, Date(-1599, 1, 1)),
10746 GregDay(-365_972, Date(-1001, 1, 1)),
10747 GregDay(-365_607, Date(-1000, 1, 1)),
10748 GregDay(-183_351, Date(-501, 1, 1)),
10749 GregDay(-182_986, Date(-500, 1, 1)),
10750 GregDay(-182_621, Date(-499, 1, 1)),
10751 GregDay(-146_827, Date(-401, 1, 1)),
10752 GregDay(-146_462, Date(-400, 1, 1)),
10753 GregDay(-146_097, Date(-400, 12, 31)),
10754 GregDay(-110_302, Date(-301, 1, 1)),
10755 GregDay(-109_937, Date(-300, 1, 1)),
10756 GregDay(-73_778, Date(-201, 1, 1)),
10757 GregDay(-73_413, Date(-200, 1, 1)),
10758 GregDay(-38_715, Date(-105, 1, 1)),
10759 GregDay(-37_254, Date(-101, 1, 1)),
10760 GregDay(-36_889, Date(-100, 1, 1)),
10761 GregDay(-36_524, Date(-99, 1, 1)),
10762 GregDay(-36_160, Date(-99, 12, 31)),
10763 GregDay(-35_794, Date(-97, 1, 1)),
10764 GregDay(-18_627, Date(-50, 1, 1)),
10765 GregDay(-18_262, Date(-49, 1, 1)),
10766 GregDay(-3652, Date(-9, 1, 1)),
10767 GregDay(-2191, Date(-5, 1, 1)),
10768 GregDay(-1827, Date(-5, 12, 31)),
10769 GregDay(-1826, Date(-4, 1, 1)),
10770 GregDay(-1825, Date(-4, 1, 2)),
10771 GregDay(-1462, Date(-4, 12, 30)),
10772 GregDay(-1461, Date(-4, 12, 31)),
10773 GregDay(-1460, Date(-3, 1, 1)),
10774 GregDay(-1096, Date(-3, 12, 31)),
10775 GregDay(-1095, Date(-2, 1, 1)),
10776 GregDay(-731, Date(-2, 12, 31)),
10777 GregDay(-730, Date(-1, 1, 1)),
10778 GregDay(-367, Date(-1, 12, 30)),
10779 GregDay(-366, Date(-1, 12, 31)),
10780 GregDay(-365, Date(0, 1, 1)),
10781 GregDay(-31, Date(0, 11, 30)),
10782 GregDay(-30, Date(0, 12, 1)),
10783 GregDay(-1, Date(0, 12, 30)),
10784 GregDay(0, Date(0, 12, 31))];
10785
10786 auto testGregDaysAD = [GregDay(1, Date(1, 1, 1)),
10787 GregDay(2, Date(1, 1, 2)),
10788 GregDay(32, Date(1, 2, 1)),
10789 GregDay(365, Date(1, 12, 31)),
10790 GregDay(366, Date(2, 1, 1)),
10791 GregDay(731, Date(3, 1, 1)),
10792 GregDay(1096, Date(4, 1, 1)),
10793 GregDay(1097, Date(4, 1, 2)),
10794 GregDay(1460, Date(4, 12, 30)),
10795 GregDay(1461, Date(4, 12, 31)),
10796 GregDay(1462, Date(5, 1, 1)),
10797 GregDay(17_898, Date(50, 1, 1)),
10798 GregDay(35_065, Date(97, 1, 1)),
10799 GregDay(36_160, Date(100, 1, 1)),
10800 GregDay(36_525, Date(101, 1, 1)),
10801 GregDay(37_986, Date(105, 1, 1)),
10802 GregDay(72_684, Date(200, 1, 1)),
10803 GregDay(73_049, Date(201, 1, 1)),
10804 GregDay(109_208, Date(300, 1, 1)),
10805 GregDay(109_573, Date(301, 1, 1)),
10806 GregDay(145_732, Date(400, 1, 1)),
10807 GregDay(146_098, Date(401, 1, 1)),
10808 GregDay(182_257, Date(500, 1, 1)),
10809 GregDay(182_622, Date(501, 1, 1)),
10810 GregDay(364_878, Date(1000, 1, 1)),
10811 GregDay(365_243, Date(1001, 1, 1)),
10812 GregDay(584_023, Date(1600, 1, 1)),
10813 GregDay(584_389, Date(1601, 1, 1)),
10814 GregDay(693_596, Date(1900, 1, 1)),
10815 GregDay(693_961, Date(1901, 1, 1)),
10816 GregDay(729_755, Date(1999, 1, 1)),
10817 GregDay(730_120, Date(2000, 1, 1)),
10818 GregDay(730_121, Date(2000, 1, 2)),
10819 GregDay(730_484, Date(2000, 12, 30)),
10820 GregDay(730_485, Date(2000, 12, 31)),
10821 GregDay(730_486, Date(2001, 1, 1)),
10822 GregDay(733_773, Date(2010, 1, 1)),
10823 GregDay(733_774, Date(2010, 1, 2)),
10824 GregDay(733_803, Date(2010, 1, 31)),
10825 GregDay(733_804, Date(2010, 2, 1)),
10826 GregDay(733_831, Date(2010, 2, 28)),
10827 GregDay(733_832, Date(2010, 3, 1)),
10828 GregDay(733_862, Date(2010, 3, 31)),
10829 GregDay(733_863, Date(2010, 4, 1)),
10830 GregDay(733_892, Date(2010, 4, 30)),
10831 GregDay(733_893, Date(2010, 5, 1)),
10832 GregDay(733_923, Date(2010, 5, 31)),
10833 GregDay(733_924, Date(2010, 6, 1)),
10834 GregDay(733_953, Date(2010, 6, 30)),
10835 GregDay(733_954, Date(2010, 7, 1)),
10836 GregDay(733_984, Date(2010, 7, 31)),
10837 GregDay(733_985, Date(2010, 8, 1)),
10838 GregDay(734_015, Date(2010, 8, 31)),
10839 GregDay(734_016, Date(2010, 9, 1)),
10840 GregDay(734_045, Date(2010, 9, 30)),
10841 GregDay(734_046, Date(2010, 10, 1)),
10842 GregDay(734_076, Date(2010, 10, 31)),
10843 GregDay(734_077, Date(2010, 11, 1)),
10844 GregDay(734_106, Date(2010, 11, 30)),
10845 GregDay(734_107, Date(2010, 12, 1)),
10846 GregDay(734_136, Date(2010, 12, 30)),
10847 GregDay(734_137, Date(2010, 12, 31)),
10848 GregDay(734_503, Date(2012, 1, 1)),
10849 GregDay(734_534, Date(2012, 2, 1)),
10850 GregDay(734_561, Date(2012, 2, 28)),
10851 GregDay(734_562, Date(2012, 2, 29)),
10852 GregDay(734_563, Date(2012, 3, 1)),
10853 GregDay(734_858, Date(2012, 12, 21))];
10854
10855 // I'd use a Tuple, but I get forward reference errors if I try.
10856 struct DayOfYear { int day; MonthDay md; }
10857 auto testDaysOfYear = [DayOfYear(1, MonthDay(1, 1)),
10858 DayOfYear(2, MonthDay(1, 2)),
10859 DayOfYear(3, MonthDay(1, 3)),
10860 DayOfYear(31, MonthDay(1, 31)),
10861 DayOfYear(32, MonthDay(2, 1)),
10862 DayOfYear(59, MonthDay(2, 28)),
10863 DayOfYear(60, MonthDay(3, 1)),
10864 DayOfYear(90, MonthDay(3, 31)),
10865 DayOfYear(91, MonthDay(4, 1)),
10866 DayOfYear(120, MonthDay(4, 30)),
10867 DayOfYear(121, MonthDay(5, 1)),
10868 DayOfYear(151, MonthDay(5, 31)),
10869 DayOfYear(152, MonthDay(6, 1)),
10870 DayOfYear(181, MonthDay(6, 30)),
10871 DayOfYear(182, MonthDay(7, 1)),
10872 DayOfYear(212, MonthDay(7, 31)),
10873 DayOfYear(213, MonthDay(8, 1)),
10874 DayOfYear(243, MonthDay(8, 31)),
10875 DayOfYear(244, MonthDay(9, 1)),
10876 DayOfYear(273, MonthDay(9, 30)),
10877 DayOfYear(274, MonthDay(10, 1)),
10878 DayOfYear(304, MonthDay(10, 31)),
10879 DayOfYear(305, MonthDay(11, 1)),
10880 DayOfYear(334, MonthDay(11, 30)),
10881 DayOfYear(335, MonthDay(12, 1)),
10882 DayOfYear(363, MonthDay(12, 29)),
10883 DayOfYear(364, MonthDay(12, 30)),
10884 DayOfYear(365, MonthDay(12, 31))];
10885
10886 auto testDaysOfLeapYear = [DayOfYear(1, MonthDay(1, 1)),
10887 DayOfYear(2, MonthDay(1, 2)),
10888 DayOfYear(3, MonthDay(1, 3)),
10889 DayOfYear(31, MonthDay(1, 31)),
10890 DayOfYear(32, MonthDay(2, 1)),
10891 DayOfYear(59, MonthDay(2, 28)),
10892 DayOfYear(60, MonthDay(2, 29)),
10893 DayOfYear(61, MonthDay(3, 1)),
10894 DayOfYear(91, MonthDay(3, 31)),
10895 DayOfYear(92, MonthDay(4, 1)),
10896 DayOfYear(121, MonthDay(4, 30)),
10897 DayOfYear(122, MonthDay(5, 1)),
10898 DayOfYear(152, MonthDay(5, 31)),
10899 DayOfYear(153, MonthDay(6, 1)),
10900 DayOfYear(182, MonthDay(6, 30)),
10901 DayOfYear(183, MonthDay(7, 1)),
10902 DayOfYear(213, MonthDay(7, 31)),
10903 DayOfYear(214, MonthDay(8, 1)),
10904 DayOfYear(244, MonthDay(8, 31)),
10905 DayOfYear(245, MonthDay(9, 1)),
10906 DayOfYear(274, MonthDay(9, 30)),
10907 DayOfYear(275, MonthDay(10, 1)),
10908 DayOfYear(305, MonthDay(10, 31)),
10909 DayOfYear(306, MonthDay(11, 1)),
10910 DayOfYear(335, MonthDay(11, 30)),
10911 DayOfYear(336, MonthDay(12, 1)),
10912 DayOfYear(364, MonthDay(12, 29)),
10913 DayOfYear(365, MonthDay(12, 30)),
10914 DayOfYear(366, MonthDay(12, 31))];
10915
10916 void initializeTests() @safe
10917 {
10918 import std.algorithm.sorting : sort;
10919 import std.typecons : Rebindable;
10920 immutable lt = LocalTime().utcToTZ(0);
10921 currLocalDiffFromUTC = dur!"hnsecs"(lt);
10922
10923 version (Posix)
10924 {
10925 immutable otherTZ = lt < 0 ? PosixTimeZone.getTimeZone("Australia/Sydney")
10926 : PosixTimeZone.getTimeZone("America/Denver");
10927 }
10928 else version (Windows)
10929 {
10930 immutable otherTZ = lt < 0 ? WindowsTimeZone.getTimeZone("AUS Eastern Standard Time")
10931 : WindowsTimeZone.getTimeZone("Mountain Standard Time");
10932 }
10933
10934 immutable ot = otherTZ.utcToTZ(0);
10935
10936 auto diffs = [0L, lt, ot];
10937 auto diffAA = [0L : Rebindable!(immutable TimeZone)(UTC())];
10938 diffAA[lt] = Rebindable!(immutable TimeZone)(LocalTime());
10939 diffAA[ot] = Rebindable!(immutable TimeZone)(otherTZ);
10940
10941 sort(diffs);
10942 testTZs = [diffAA[diffs[0]], diffAA[diffs[1]], diffAA[diffs[2]]];
10943
10944 testFracSecs = [Duration.zero, hnsecs(1), hnsecs(5007), hnsecs(9_999_999)];
10945
10946 foreach (year; testYearsBC)
10947 {
10948 foreach (md; testMonthDays)
10949 testDatesBC ~= Date(year, md.month, md.day);
10950 }
10951
10952 foreach (year; testYearsAD)
10953 {
10954 foreach (md; testMonthDays)
10955 testDatesAD ~= Date(year, md.month, md.day);
10956 }
10957
10958 foreach (dt; testDatesBC)
10959 {
10960 foreach (tod; testTODs)
10961 testDateTimesBC ~= DateTime(dt, tod);
10962 }
10963
10964 foreach (dt; testDatesAD)
10965 {
10966 foreach (tod; testTODs)
10967 testDateTimesAD ~= DateTime(dt, tod);
10968 }
10969
10970 foreach (dt; testDateTimesBC)
10971 {
10972 foreach (tz; testTZs)
10973 {
10974 foreach (fs; testFracSecs)
10975 testSysTimesBC ~= SysTime(dt, fs, tz);
10976 }
10977 }
10978
10979 foreach (dt; testDateTimesAD)
10980 {
10981 foreach (tz; testTZs)
10982 {
10983 foreach (fs; testFracSecs)
10984 testSysTimesAD ~= SysTime(dt, fs, tz);
10985 }
10986 }
10987 }
10988 }
10989