1 // Written in the D programming language
2
3 /++
4
5 $(DIVC quickindex,
6 $(BOOKTABLE,
7 $(TR $(TH Category) $(TH Functions))
8 $(TR $(TD Types) $(TD
9 $(LREF Clock)
10 $(LREF SysTime)
11 $(LREF DosFileTime)
12 ))
13 $(TR $(TD Conversion) $(TD
14 $(LREF parseRFC822DateTime)
15 $(LREF DosFileTimeToSysTime)
16 $(LREF FILETIMEToStdTime)
17 $(LREF FILETIMEToSysTime)
18 $(LREF stdTimeToFILETIME)
19 $(LREF stdTimeToUnixTime)
20 $(LREF SYSTEMTIMEToSysTime)
21 $(LREF SysTimeToDosFileTime)
22 $(LREF SysTimeToFILETIME)
23 $(LREF SysTimeToSYSTEMTIME)
24 $(LREF unixTimeToStdTime)
25 ))
26 ))
27
28 License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
29 Authors: $(HTTP jmdavisprog.com, Jonathan M Davis)
30 Source: $(PHOBOSSRC std/datetime/systime.d)
31 +/
32 module std.datetime.systime;
33
34 version (OSX)
35 version = Darwin;
36 else version (iOS)
37 version = Darwin;
38 else version (TVOS)
39 version = Darwin;
40 else version (WatchOS)
41 version = Darwin;
42
43 /// Get the current time as a $(LREF SysTime)
44 @safe unittest
45 {
46 import std.datetime.timezone : LocalTime;
47 SysTime today = Clock.currTime();
48 assert(today.timezone is LocalTime());
49 }
50
51 /// Construct a $(LREF SysTime) from a ISO time string
52 @safe unittest
53 {
54 import std.datetime.date : DateTime;
55 import std.datetime.timezone : UTC;
56
57 auto st = SysTime.fromISOExtString("2018-01-01T10:30:00Z");
58 assert(st == SysTime(DateTime(2018, 1, 1, 10, 30, 0), UTC()));
59 }
60
61 /// Make a specific point in time in the New York timezone
62 @safe unittest
63 {
64 import core.time : hours;
65 import std.datetime.date : DateTime;
66 import std.datetime.timezone : SimpleTimeZone;
67
68 auto ny = SysTime(
69 DateTime(2018, 1, 1, 10, 30, 0),
70 new immutable SimpleTimeZone(-5.hours, "America/New_York")
71 );
72
73 // ISO standard time strings
74 assert(ny.toISOString() == "20180101T103000-05:00");
75 assert(ny.toISOExtString() == "2018-01-01T10:30:00-05:00");
76 }
77
78 // Note: reconsider using specific imports below after
79 // https://issues.dlang.org/show_bug.cgi?id=17630 has been fixed
80 import core.time;// : ClockType, convert, dur, Duration, seconds, TimeException;
81 import std.datetime.date;// : _monthNames, AllowDayOverflow, CmpTimeUnits, Date,
82 //DateTime, DateTimeException, DayOfWeek, enforceValid, getDayOfWeek, maxDay,
83 //Month, splitUnitsFromHNSecs, TimeOfDay, validTimeUnits, yearIsLeapYear;
84 import std.datetime.timezone;// : LocalTime, SimpleTimeZone, TimeZone, UTC;
85 import std.exception : enforce;
86 import std.format : format;
87 import std.range.primitives;
88 import std.traits : isIntegral, isSigned, isSomeString, isNarrowString;
89
90 version (Windows)
91 {
92 import core.stdc.time : time_t;
93 import core.sys.windows.winbase;
94 import core.sys.windows.winnt;
95 import core.sys.windows.winsock2;
96 }
97 else version (Posix)
98 {
99 import core.sys.posix.signal : timespec;
100 import core.sys.posix.sys.types : time_t;
101 }
102
103 version (StdUnittest)
104 {
105 import core.exception : AssertError;
106 import std.exception : assertThrown;
107 }
108
109
110 @safe unittest
111 {
112 initializeTests();
113 }
114
115 version (unittest) private bool clockSupported(ClockType c)
116 {
117 // Skip unsupported clocks on older linux kernels, assume that only
118 // CLOCK_MONOTONIC and CLOCK_REALTIME exist, as that is the lowest
119 // common denominator supported by all versions of Linux pre-2.6.12.
120 version (Linux_Pre_2639)
121 return c == ClockType.normal || c == ClockType.precise;
122 else
123 return true;
124 }
125
126 /++
127 Effectively a namespace to make it clear that the methods it contains are
128 getting the time from the system clock. It cannot be instantiated.
129 +/
130 final class Clock
131 {
132 public:
133
134 /++
135 Returns the current time in the given time zone.
136
137 Params:
138 clockType = The $(REF ClockType, core,time) indicates which system
139 clock to use to get the current time. Very few programs
140 need to use anything other than the default.
141 tz = The time zone for the SysTime that's returned.
142
143 Throws:
144 $(REF DateTimeException,std,datetime,date) if it fails to get the
145 time.
146 +/
147 static SysTime currTime(ClockType clockType = ClockType.normal)(immutable TimeZone tz = LocalTime()) @safe
148 {
149 return SysTime(currStdTime!clockType, tz);
150 }
151
152 @safe unittest
153 {
154 import std.format : format;
155 import core.time;
156 assert(currTime().timezone is LocalTime());
157 assert(currTime(UTC()).timezone is UTC());
158
159 // core.stdc.time.time does not always use unix time on Windows systems.
160 // In particular, dmc does not use unix time. If we can guarantee that
161 // the MS runtime uses unix time, then we may be able run this test
162 // then, but for now, we're just not going to run this test on Windows.
163 version (Posix)
164 {
165 static import core.stdc.time;
166 static import std.math;
167 immutable unixTimeD = currTime().toUnixTime();
168 immutable unixTimeC = core.stdc.time.time(null);
169 assert(std.math.abs(unixTimeC - unixTimeD) <= 2);
170 }
171
172 auto norm1 = Clock.currTime;
173 auto norm2 = Clock.currTime(UTC());
174 assert(norm1 <= norm2, format("%s %s", norm1, norm2));
175 assert(abs(norm1 - norm2) <= seconds(2));
176
177 import std.meta : AliasSeq;
178 static foreach (ct; AliasSeq!(ClockType.coarse, ClockType.precise, ClockType.second))
179 {{
180 static if (clockSupported(ct))
181 {
182 auto value1 = Clock.currTime!ct;
183 auto value2 = Clock.currTime!ct(UTC());
184 assert(value1 <= value2, format("%s %s (ClockType: %s)", value1, value2, ct));
185 assert(abs(value1 - value2) <= seconds(2), format("ClockType.%s", ct));
186 }
187 }}
188 }
189
190
191 /++
192 Returns the number of hnsecs since midnight, January 1st, 1 A.D. for the
193 current time.
194
195 Params:
196 clockType = The $(REF ClockType, core,time) indicates which system
197 clock to use to get the current time. Very few programs
198 need to use anything other than the default.
199
200 Throws:
201 $(REF DateTimeException,std,datetime,date) if it fails to get the
202 time.
203 +/
204 static @property long currStdTime(ClockType clockType = ClockType.normal)() @trusted
205 {
206 static if (clockType != ClockType.coarse &&
207 clockType != ClockType.normal &&
208 clockType != ClockType.precise &&
209 clockType != ClockType.second)
210 {
211 static assert(0, format("ClockType.%s is not supported by Clock.currTime or Clock.currStdTime", clockType));
212 }
213
214 version (Windows)
215 {
216 FILETIME fileTime;
217 GetSystemTimeAsFileTime(&fileTime);
218 immutable result = FILETIMEToStdTime(&fileTime);
219 static if (clockType == ClockType.second)
220 {
221 // Ideally, this would use core.std.time.time, but the C runtime
222 // has to be using unix time for that to work, and that's not
223 // guaranteed on Windows. Digital Mars does not use unix time.
224 // MS may or may not. If it does, then this can be made to use
225 // core.stdc.time for MS, but for now, we'll leave it like this.
226 return convert!("seconds", "hnsecs")(convert!("hnsecs", "seconds")(result));
227 }
228 else
229 return result;
230 }
231 else version (Posix)
232 {
233 static import core.stdc.time;
234 enum hnsecsToUnixEpoch = unixTimeToStdTime(0);
235
236 version (Darwin)
237 {
238 static if (clockType == ClockType.second)
239 return unixTimeToStdTime(core.stdc.time.time(null));
240 else
241 {
242 import core.sys.posix.sys.time : gettimeofday, timeval;
243 timeval tv = void;
244 // Posix gettimeofday called with a valid timeval address
245 // and a null second parameter doesn't fail.
246 gettimeofday(&tv, null);
247 return convert!("seconds", "hnsecs")(tv.tv_sec) +
248 tv.tv_usec * 10 +
249 hnsecsToUnixEpoch;
250 }
251 }
252 else version (linux)
253 {
254 static if (clockType == ClockType.second)
255 return unixTimeToStdTime(core.stdc.time.time(null));
256 else
257 {
258 import core.sys.linux.time : CLOCK_REALTIME_COARSE;
259 import core.sys.posix.time : clock_gettime, CLOCK_REALTIME;
260 static if (clockType == ClockType.coarse) alias clockArg = CLOCK_REALTIME_COARSE;
261 else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME;
262 else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME;
263 else static assert(0, "Previous static if is wrong.");
264 timespec ts = void;
265 immutable error = clock_gettime(clockArg, &ts);
266 // Posix clock_gettime called with a valid address and valid clock_id is only
267 // permitted to fail if the number of seconds does not fit in time_t. If tv_sec
268 // is long or larger overflow won't happen before 292 billion years A.D.
269 static if (ts.tv_sec.max < long.max)
270 {
271 if (error)
272 throw new TimeException("Call to clock_gettime() failed");
273 }
274 return convert!("seconds", "hnsecs")(ts.tv_sec) +
275 ts.tv_nsec / 100 +
276 hnsecsToUnixEpoch;
277 }
278 }
279 else version (FreeBSD)
280 {
281 import core.sys.freebsd.time : clock_gettime, CLOCK_REALTIME,
282 CLOCK_REALTIME_FAST, CLOCK_REALTIME_PRECISE, CLOCK_SECOND;
283 static if (clockType == ClockType.coarse) alias clockArg = CLOCK_REALTIME_FAST;
284 else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME;
285 else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME_PRECISE;
286 else static if (clockType == ClockType.second) alias clockArg = CLOCK_SECOND;
287 else static assert(0, "Previous static if is wrong.");
288 timespec ts = void;
289 immutable error = clock_gettime(clockArg, &ts);
290 // Posix clock_gettime called with a valid address and valid clock_id is only
291 // permitted to fail if the number of seconds does not fit in time_t. If tv_sec
292 // is long or larger overflow won't happen before 292 billion years A.D.
293 static if (ts.tv_sec.max < long.max)
294 {
295 if (error)
296 throw new TimeException("Call to clock_gettime() failed");
297 }
298 return convert!("seconds", "hnsecs")(ts.tv_sec) +
299 ts.tv_nsec / 100 +
300 hnsecsToUnixEpoch;
301 }
302 else version (NetBSD)
303 {
304 static if (clockType == ClockType.second)
305 return unixTimeToStdTime(core.stdc.time.time(null));
306 else
307 {
308 import core.sys.netbsd.time : clock_gettime, CLOCK_REALTIME;
309 timespec ts = void;
310 immutable error = clock_gettime(CLOCK_REALTIME, &ts);
311 // Posix clock_gettime called with a valid address and valid clock_id is only
312 // permitted to fail if the number of seconds does not fit in time_t. If tv_sec
313 // is long or larger overflow won't happen before 292 billion years A.D.
314 static if (ts.tv_sec.max < long.max)
315 {
316 if (error)
317 throw new TimeException("Call to clock_gettime() failed");
318 }
319 return convert!("seconds", "hnsecs")(ts.tv_sec) +
320 ts.tv_nsec / 100 +
321 hnsecsToUnixEpoch;
322 }
323 }
324 else version (OpenBSD)
325 {
326 static if (clockType == ClockType.second)
327 return unixTimeToStdTime(core.stdc.time.time(null));
328 else
329 {
330 import core.sys.openbsd.time : clock_gettime, CLOCK_REALTIME;
331 static if (clockType == ClockType.coarse) alias clockArg = CLOCK_REALTIME;
332 else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME;
333 else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME;
334 else static assert(0, "Previous static if is wrong.");
335 timespec ts;
336 if (clock_gettime(clockArg, &ts) != 0)
337 throw new TimeException("Call to clock_gettime() failed");
338 return convert!("seconds", "hnsecs")(ts.tv_sec) +
339 ts.tv_nsec / 100 +
340 hnsecsToUnixEpoch;
341 }
342 }
343 else version (DragonFlyBSD)
344 {
345 import core.sys.dragonflybsd.time : clock_gettime, CLOCK_REALTIME,
346 CLOCK_REALTIME_FAST, CLOCK_REALTIME_PRECISE, CLOCK_SECOND;
347 static if (clockType == ClockType.coarse) alias clockArg = CLOCK_REALTIME_FAST;
348 else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME;
349 else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME_PRECISE;
350 else static if (clockType == ClockType.second) alias clockArg = CLOCK_SECOND;
351 else static assert(0, "Previous static if is wrong.");
352 timespec ts = void;
353 immutable error = clock_gettime(clockArg, &ts);
354 // Posix clock_gettime called with a valid address and valid clock_id is only
355 // permitted to fail if the number of seconds does not fit in time_t. If tv_sec
356 // is long or larger overflow won't happen before 292 billion years A.D.
357 static if (ts.tv_sec.max < long.max)
358 {
359 if (error)
360 throw new TimeException("Call to clock_gettime() failed");
361 }
362 return convert!("seconds", "hnsecs")(ts.tv_sec) +
363 ts.tv_nsec / 100 +
364 hnsecsToUnixEpoch;
365 }
366 else version (Solaris)
367 {
368 static if (clockType == ClockType.second)
369 return unixTimeToStdTime(core.stdc.time.time(null));
370 else
371 {
372 import core.sys.solaris.time : clock_gettime, CLOCK_REALTIME;
373 static if (clockType == ClockType.coarse) alias clockArg = CLOCK_REALTIME;
374 else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME;
375 else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME;
376 else static assert(0, "Previous static if is wrong.");
377 timespec ts = void;
378 immutable error = clock_gettime(clockArg, &ts);
379 // Posix clock_gettime called with a valid address and valid clock_id is only
380 // permitted to fail if the number of seconds does not fit in time_t. If tv_sec
381 // is long or larger overflow won't happen before 292 billion years A.D.
382 static if (ts.tv_sec.max < long.max)
383 {
384 if (error)
385 throw new TimeException("Call to clock_gettime() failed");
386 }
387 return convert!("seconds", "hnsecs")(ts.tv_sec) +
388 ts.tv_nsec / 100 +
389 hnsecsToUnixEpoch;
390 }
391 }
392 else version (Hurd)
393 {
394 static if (clockType == ClockType.second)
395 return unixTimeToStdTime(core.stdc.time.time(null));
396 else
397 {
398 import core.sys.hurd.time : CLOCK_REALTIME_COARSE;
399 import core.sys.posix.time : clock_gettime, CLOCK_REALTIME;
400 static if (clockType == ClockType.coarse) alias clockArg = CLOCK_REALTIME_COARSE;
401 else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME;
402 else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME;
403 else static assert(0, "Previous static if is wrong.");
404 timespec ts = void;
405 immutable error = clock_gettime(clockArg, &ts);
406 // Posix clock_gettime called with a valid address and valid clock_id is only
407 // permitted to fail if the number of seconds does not fit in time_t. If tv_sec
408 // is long or larger overflow won't happen before 292 billion years A.D.
409 static if (ts.tv_sec.max < long.max)
410 {
411 if (error)
412 throw new TimeException("Call to clock_gettime() failed");
413 }
414 return convert!("seconds", "hnsecs")(ts.tv_sec) +
415 ts.tv_nsec / 100 +
416 hnsecsToUnixEpoch;
417 }
418 }
419 else static assert(0, "Unsupported OS");
420 }
421 else static assert(0, "Unsupported OS");
422 }
423
424 @safe unittest
425 {
426 import std.format : format;
427 import std.math.algebraic : abs;
428 import std.meta : AliasSeq;
429 enum limit = convert!("seconds", "hnsecs")(2);
430
431 auto norm1 = Clock.currStdTime;
432 auto norm2 = Clock.currStdTime;
433 assert(norm1 <= norm2, format("%s %s", norm1, norm2));
434 assert(abs(norm1 - norm2) <= limit);
435
436 static foreach (ct; AliasSeq!(ClockType.coarse, ClockType.precise, ClockType.second))
437 {{
438 static if (clockSupported(ct))
439 {
440 auto value1 = Clock.currStdTime!ct;
441 auto value2 = Clock.currStdTime!ct;
442 assert(value1 <= value2, format("%s %s (ClockType: %s)", value1, value2, ct));
443 assert(abs(value1 - value2) <= limit);
444 }
445 }}
446 }
447
448
449 private:
450
451 @disable this();
452 }
453
454 /// Get the current time as a $(LREF SysTime)
455 @safe unittest
456 {
457 import std.datetime.timezone : LocalTime;
458 SysTime today = Clock.currTime();
459 assert(today.timezone is LocalTime());
460 }
461
462
463 /++
464 `SysTime` is the type used to get the current time from the
465 system or doing anything that involves time zones. Unlike
466 $(REF DateTime,std,datetime,date), the time zone is an integral part of
467 `SysTime` (though for local time applications, time zones can be ignored
468 and it will work, since it defaults to using the local time zone). It holds
469 its internal time in std time (hnsecs since midnight, January 1st, 1 A.D.
470 UTC), so it interfaces well with the system time.
471
472 An $(I hnsec) (hecto-nanosecond) is 100 nanoseconds. There are 10,000,000 hnsecs in a second.
473
474 $(PANEL
475 Unlike $(REF_SHORT DateTime,std,datetime,date), `SysTime` is not optimized for
476 calendar-based operations, and getting individual units from it such as
477 years or days is going to involve conversions and be less efficient.
478
479 For calendar-based operations that don't
480 care about time zones, then $(REF_SHORT DateTime,std,datetime,date) would be
481 the type to use. For system time, use `SysTime`.
482 )
483 $(P
484 Casting a `SysTime` to one of the following types will perform a conversion:
485 )
486 * $(REF Date,std,datetime,date)
487 * $(REF_SHORT DateTime,std,datetime,date)
488 * $(REF_SHORT TimeOfDay,std,datetime,date)
489 $(P
490 To convert a
491 $(REF_SHORT Date,std,datetime,date) or $(REF_SHORT DateTime,std,datetime,date) to a
492 `SysTime`, use `SysTime`'s constructor, and pass in the intended time
493 zone with it (or don't pass in a $(REF TimeZone,std,datetime,timezone), and
494 the local time zone will be used). Be aware, however, that converting from a
495 $(REF_SHORT DateTime,std,datetime,date) to a `SysTime` will not necessarily
496 be 100% accurate due to DST (one hour of the year doesn't exist and another
497 occurs twice). To not risk any conversion errors, keep times as
498 `SysTime`s. Aside from DST though, there shouldn't be any conversion
499 problems.
500 )
501 $(PANEL
502 For using time zones other than local time or UTC, use
503 $(REF PosixTimeZone,std,datetime,timezone) on Posix systems (or on Windows,
504 if providing the TZ Database files), and use
505 $(REF WindowsTimeZone,std,datetime,timezone) on Windows systems. The time in
506 `SysTime` is kept internally in hnsecs from midnight, January 1st, 1 A.D.
507 UTC. Conversion error cannot happen when changing the time zone of a
508 `SysTime`. $(REF LocalTime,std,datetime,timezone) is the
509 $(REF_SHORT TimeZone,std,datetime,timezone) class which represents the local time,
510 and `UTC` is the $(REF_SHORT TimeZone,std,datetime,timezone) class which
511 represents UTC. `SysTime` uses $(REF_SHORT LocalTime,std,datetime,timezone) if
512 no $(REF_SHORT TimeZone,std,datetime,timezone) is provided. For more details on
513 time zones, see the documentation for $(REF_SHORT TimeZone,std,datetime,timezone),
514 $(REF_SHORT PosixTimeZone,std,datetime,timezone), and
515 $(REF_SHORT WindowsTimeZone,std,datetime,timezone).
516 )
517 $(P
518 `SysTime`'s range is from approximately 29,000 B.C. to approximately
519 29,000 A.D.
520 )
521 See_Also:
522 $(RELATIVE_LINK2 .Clock.currTime, `Clock.currTime`) will return the current time as a `SysTime`.
523 +/
524 struct SysTime
525 {
526 import core.stdc.time : tm;
527 version (Posix) import core.sys.posix.sys.time : timeval;
528 import std.typecons : Rebindable;
529
530 public:
531
532 /++
533 Params:
534 dateTime = The $(REF DateTime,std,datetime,date) to use to set
535 this $(LREF SysTime)'s internal std time. As
536 $(REF DateTime,std,datetime,date) has no concept of
537 time zone, tz is used as its time zone.
538 tz = The $(REF TimeZone,std,datetime,timezone) to use for this
539 $(LREF SysTime). If null,
540 $(REF LocalTime,std,datetime,timezone) will be used. The
541 given $(REF DateTime,std,datetime,date) is assumed to
542 be in the given time zone.
543 +/
544 this(DateTime dateTime, return scope immutable TimeZone tz = null) return scope @safe nothrow
545 {
546 try
547 this(dateTime, Duration.zero, tz);
548 catch (Exception e)
549 assert(0, "SysTime's constructor threw when it shouldn't have.");
550 }
551
552 @safe unittest
553 {
554 static void test(DateTime dt, immutable TimeZone tz, long expected)
555 {
556 auto sysTime = SysTime(dt, tz);
557 assert(sysTime._stdTime == expected);
558 assert(sysTime._timezone is (tz is null ? LocalTime() : tz), format("Given DateTime: %s", dt));
559 }
560
561 test(DateTime.init, UTC(), 0);
562 test(DateTime(1, 1, 1, 12, 30, 33), UTC(), 450_330_000_000L);
563 test(DateTime(0, 12, 31, 12, 30, 33), UTC(), -413_670_000_000L);
564 test(DateTime(1, 1, 1, 0, 0, 0), UTC(), 0);
565 test(DateTime(1, 1, 1, 0, 0, 1), UTC(), 10_000_000L);
566 test(DateTime(0, 12, 31, 23, 59, 59), UTC(), -10_000_000L);
567
568 test(DateTime(1, 1, 1, 0, 0, 0), new immutable SimpleTimeZone(dur!"minutes"(-60)), 36_000_000_000L);
569 test(DateTime(1, 1, 1, 0, 0, 0), new immutable SimpleTimeZone(Duration.zero), 0);
570 test(DateTime(1, 1, 1, 0, 0, 0), new immutable SimpleTimeZone(dur!"minutes"(60)), -36_000_000_000L);
571
572 static void testScope(scope ref DateTime dt) @safe
573 {
574 auto st = SysTime(dt);
575 }
576 }
577
578 /++
579 Params:
580 dateTime = The $(REF DateTime,std,datetime,date) to use to set
581 this $(LREF SysTime)'s internal std time. As
582 $(REF DateTime,std,datetime,date) has no concept of
583 time zone, tz is used as its time zone.
584 fracSecs = The fractional seconds portion of the time.
585 tz = The $(REF TimeZone,std,datetime,timezone) to use for this
586 $(LREF SysTime). If null,
587 $(REF LocalTime,std,datetime,timezone) will be used. The
588 given $(REF DateTime,std,datetime,date) is assumed to
589 be in the given time zone.
590
591 Throws:
592 $(REF DateTimeException,std,datetime,date) if `fracSecs` is negative or if it's
593 greater than or equal to one second.
594 +/
595 this(DateTime dateTime, Duration fracSecs, return scope immutable TimeZone tz = null) return scope @safe
596 {
597 enforce(fracSecs >= Duration.zero, new DateTimeException("A SysTime cannot have negative fractional seconds."));
598 enforce(fracSecs < seconds(1), new DateTimeException("Fractional seconds must be less than one second."));
599 auto nonNullTZ = tz is null ? LocalTime() : tz;
600
601 immutable dateDiff = dateTime.date - Date.init;
602 immutable todDiff = dateTime.timeOfDay - TimeOfDay.init;
603
604 immutable adjustedTime = dateDiff + todDiff + fracSecs;
605 immutable standardTime = nonNullTZ.tzToUTC(adjustedTime.total!"hnsecs");
606
607 this(standardTime, nonNullTZ);
608 }
609
610 @safe unittest
611 {
612 import core.time;
613 static void test(DateTime dt, Duration fracSecs, immutable TimeZone tz, long expected)
614 {
615 auto sysTime = SysTime(dt, fracSecs, tz);
616 assert(sysTime._stdTime == expected);
617 assert(sysTime._timezone is (tz is null ? LocalTime() : tz),
618 format("Given DateTime: %s, Given Duration: %s", dt, fracSecs));
619 }
620
621 test(DateTime.init, Duration.zero, UTC(), 0);
622 test(DateTime(1, 1, 1, 12, 30, 33), Duration.zero, UTC(), 450_330_000_000L);
623 test(DateTime(0, 12, 31, 12, 30, 33), Duration.zero, UTC(), -413_670_000_000L);
624 test(DateTime(1, 1, 1, 0, 0, 0), msecs(1), UTC(), 10_000L);
625 test(DateTime(0, 12, 31, 23, 59, 59), msecs(999), UTC(), -10_000L);
626
627 test(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC(), -1);
628 test(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1), UTC(), -9_999_999);
629 test(DateTime(0, 12, 31, 23, 59, 59), Duration.zero, UTC(), -10_000_000);
630
631 assertThrown!DateTimeException(SysTime(DateTime.init, hnsecs(-1), UTC()));
632 assertThrown!DateTimeException(SysTime(DateTime.init, seconds(1), UTC()));
633
634 static void testScope(scope ref DateTime dt, scope ref Duration d) @safe
635 {
636 auto st = SysTime(dt, d);
637 }
638 }
639
640 /++
641 Params:
642 date = The $(REF Date,std,datetime,date) to use to set this
643 $(LREF SysTime)'s internal std time. As
644 $(REF Date,std,datetime,date) has no concept of time zone, tz
645 is used as its time zone.
646 tz = The $(REF TimeZone,std,datetime,timezone) to use for this
647 $(LREF SysTime). If null,
648 $(REF LocalTime,std,datetime,timezone) will be used. The
649 given $(REF Date,std,datetime,date) is assumed to be in the
650 given time zone.
651 +/
652 this(Date date, return scope immutable TimeZone tz = null) return scope @safe nothrow
653 {
654 _timezone = tz is null ? LocalTime() : tz;
655
656 try
657 {
658 immutable adjustedTime = (date - Date(1, 1, 1)).total!"hnsecs";
659 immutable standardTime = _timezone.tzToUTC(adjustedTime);
660
661 this(standardTime, _timezone);
662 }
663 catch (Exception e)
664 assert(0, "Date's constructor through when it shouldn't have.");
665 }
666
667 @safe unittest
668 {
669 static void test(Date d, immutable TimeZone tz, long expected)
670 {
671 auto sysTime = SysTime(d, tz);
672 assert(sysTime._stdTime == expected);
673 assert(sysTime._timezone is (tz is null ? LocalTime() : tz), format("Given Date: %s", d));
674 }
675
676 test(Date.init, UTC(), 0);
677 test(Date(1, 1, 1), UTC(), 0);
678 test(Date(1, 1, 2), UTC(), 864000000000);
679 test(Date(0, 12, 31), UTC(), -864000000000);
680
681 static void testScope(scope ref Date d) @safe
682 {
683 auto st = SysTime(d);
684 }
685 }
686
687 /++
688 Note:
689 Whereas the other constructors take in the given date/time, assume
690 that it's in the given time zone, and convert it to hnsecs in UTC
691 since midnight, January 1st, 1 A.D. UTC - i.e. std time - this
692 constructor takes a std time, which is specifically already in UTC,
693 so no conversion takes place. Of course, the various getter
694 properties and functions will use the given time zone's conversion
695 function to convert the results to that time zone, but no conversion
696 of the arguments to this constructor takes place.
697
698 Params:
699 stdTime = The number of hnsecs since midnight, January 1st, 1 A.D.
700 UTC.
701 tz = The $(REF TimeZone,std,datetime,timezone) to use for this
702 $(LREF SysTime). If null,
703 $(REF LocalTime,std,datetime,timezone) will be used.
704 +/
705 this(long stdTime, return scope immutable TimeZone tz = null) return scope @safe pure nothrow
706 {
707 _stdTime = stdTime;
708 _timezone = tz is null ? LocalTime() : tz;
709 }
710
711 @safe unittest
712 {
713 static void test(long stdTime, immutable TimeZone tz)
714 {
715 auto sysTime = SysTime(stdTime, tz);
716 assert(sysTime._stdTime == stdTime);
717 assert(sysTime._timezone is (tz is null ? LocalTime() : tz), format("Given stdTime: %s", stdTime));
718 }
719
720 foreach (stdTime; [-1234567890L, -250, 0, 250, 1235657390L])
721 {
722 foreach (tz; testTZs)
723 test(stdTime, tz);
724 }
725 }
726
727
728 /++
729 Params:
730 rhs = The $(LREF SysTime) to assign to this one.
731
732 Returns: The `this` of this `SysTime`.
733 +/
734 ref SysTime opAssign()(auto ref const(SysTime) rhs) scope return @safe pure nothrow
735 {
736 _stdTime = rhs._stdTime;
737 _timezone = rhs._timezone;
738 return this;
739 }
740
741 @safe unittest
742 {
743 SysTime st;
744 st = SysTime(DateTime(2012, 12, 21, 1, 2, 3), UTC());
745 assert(st == SysTime(DateTime(2012, 12, 21, 1, 2, 3), UTC()));
746
747 const other = SysTime(DateTime(19, 1, 7, 13, 14, 15), LocalTime());
748 st = other;
749 assert(st == other);
750
751 version (none) // https://issues.dlang.org/show_bug.cgi?id=21175
752 static void testScope(scope ref SysTime left, const scope SysTime right) @safe
753 {
754 left = right;
755 }
756 }
757
758
759 /++
760 Checks for equality between this $(LREF SysTime) and the given
761 $(LREF SysTime).
762
763 Note that the time zone is ignored. Only the internal
764 std times (which are in UTC) are compared.
765 +/
766 bool opEquals()(auto ref const(SysTime) rhs) @safe const pure nothrow scope
767 {
768 return _stdTime == rhs._stdTime;
769 }
770
771 @safe unittest
772 {
773 import std.range : chain;
774
775 assert(SysTime(DateTime.init, UTC()) == SysTime(0, UTC()));
776 assert(SysTime(DateTime.init, UTC()) == SysTime(0));
777 assert(SysTime(Date.init, UTC()) == SysTime(0));
778 assert(SysTime(0) == SysTime(0));
779
780 static void test(DateTime dt, immutable TimeZone tz1, immutable TimeZone tz2)
781 {
782 auto st1 = SysTime(dt);
783 st1.timezone = tz1;
784
785 auto st2 = SysTime(dt);
786 st2.timezone = tz2;
787
788 assert(st1 == st2);
789 }
790
791 foreach (tz1; testTZs)
792 {
793 foreach (tz2; testTZs)
794 {
795 foreach (dt; chain(testDateTimesBC, testDateTimesAD))
796 test(dt, tz1, tz2);
797 }
798 }
799
800 auto st = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
801 const cst = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
802 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
803 assert(st == st);
804 assert(st == cst);
805 assert(st == ist);
806 assert(cst == st);
807 assert(cst == cst);
808 assert(cst == ist);
809 assert(ist == st);
810 assert(ist == cst);
811 assert(ist == ist);
812
813 static void testScope(scope ref SysTime left, const scope SysTime right) @safe
814 {
815 assert(left == right);
816 assert(right == left);
817 }
818 }
819
820
821 /++
822 Compares this $(LREF SysTime) with the given $(LREF SysTime).
823
824 Time zone is irrelevant when comparing $(LREF SysTime)s.
825
826 Returns:
827 $(BOOKTABLE,
828 $(TR $(TD this < rhs) $(TD < 0))
829 $(TR $(TD this == rhs) $(TD 0))
830 $(TR $(TD this > rhs) $(TD > 0))
831 )
832 +/
833 int opCmp()(auto ref const(SysTime) rhs) @safe const pure nothrow scope
834 {
835 if (_stdTime < rhs._stdTime)
836 return -1;
837 if (_stdTime > rhs._stdTime)
838 return 1;
839 return 0;
840 }
841
842 @safe unittest
843 {
844 import std.algorithm.iteration : map;
845 import std.array : array;
846 import std.range : chain;
847
848 assert(SysTime(DateTime.init, UTC()).opCmp(SysTime(0, UTC())) == 0);
849 assert(SysTime(DateTime.init, UTC()).opCmp(SysTime(0)) == 0);
850 assert(SysTime(Date.init, UTC()).opCmp(SysTime(0)) == 0);
851 assert(SysTime(0).opCmp(SysTime(0)) == 0);
852
853 static void testEqual(SysTime st, immutable TimeZone tz1, immutable TimeZone tz2)
854 {
855 auto st1 = st;
856 st1.timezone = tz1;
857
858 auto st2 = st;
859 st2.timezone = tz2;
860
861 assert(st1.opCmp(st2) == 0);
862 }
863
864 auto sts = array(map!SysTime(chain(testDateTimesBC, testDateTimesAD)));
865
866 foreach (st; sts)
867 {
868 foreach (tz1; testTZs)
869 {
870 foreach (tz2; testTZs)
871 testEqual(st, tz1, tz2);
872 }
873 }
874
875 static void testCmp(SysTime st1, immutable TimeZone tz1, SysTime st2, immutable TimeZone tz2)
876 {
877 st1.timezone = tz1;
878 st2.timezone = tz2;
879 assert(st1.opCmp(st2) < 0);
880 assert(st2.opCmp(st1) > 0);
881 }
882
883 foreach (si, st1; sts)
884 {
885 foreach (st2; sts[si + 1 .. $])
886 {
887 foreach (tz1; testTZs)
888 {
889 foreach (tz2; testTZs)
890 testCmp(st1, tz1, st2, tz2);
891 }
892 }
893 }
894
895 auto st = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
896 const cst = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
897 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
898 assert(st.opCmp(st) == 0);
899 assert(st.opCmp(cst) == 0);
900 assert(st.opCmp(ist) == 0);
901 assert(cst.opCmp(st) == 0);
902 assert(cst.opCmp(cst) == 0);
903 assert(cst.opCmp(ist) == 0);
904 assert(ist.opCmp(st) == 0);
905 assert(ist.opCmp(cst) == 0);
906 assert(ist.opCmp(ist) == 0);
907
908 static void testScope(scope ref SysTime left, const scope SysTime right) @safe
909 {
910 assert(left < right);
911 assert(right > left);
912 }
913 }
914
915
916 /++
917 Returns: A hash of the $(LREF SysTime).
918 +/
919 size_t toHash() const @nogc pure nothrow @safe scope
920 {
921 static if (is(size_t == ulong))
922 return _stdTime;
923 else
924 {
925 // MurmurHash2
926 enum ulong m = 0xc6a4a7935bd1e995UL;
927 enum ulong n = m * 16;
928 enum uint r = 47;
929
930 ulong k = _stdTime;
931 k *= m;
932 k ^= k >> r;
933 k *= m;
934
935 ulong h = n;
936 h ^= k;
937 h *= m;
938
939 return cast(size_t) h;
940 }
941 }
942
943 @safe unittest
944 {
945 assert(SysTime(0).toHash == SysTime(0).toHash);
946 assert(SysTime(DateTime(2000, 1, 1)).toHash == SysTime(DateTime(2000, 1, 1)).toHash);
947 assert(SysTime(DateTime(2000, 1, 1)).toHash != SysTime(DateTime(2000, 1, 2)).toHash);
948
949 // test that timezones aren't taken into account
950 assert(SysTime(0, LocalTime()).toHash == SysTime(0, LocalTime()).toHash);
951 assert(SysTime(0, LocalTime()).toHash == SysTime(0, UTC()).toHash);
952 assert(SysTime(DateTime(2000, 1, 1), LocalTime()).toHash == SysTime(DateTime(2000, 1, 1), LocalTime()).toHash);
953 immutable zone = new SimpleTimeZone(dur!"minutes"(60));
954 assert(SysTime(DateTime(2000, 1, 1, 1), zone).toHash == SysTime(DateTime(2000, 1, 1), UTC()).toHash);
955 assert(SysTime(DateTime(2000, 1, 1), zone).toHash != SysTime(DateTime(2000, 1, 1), UTC()).toHash);
956
957 static void testScope(scope ref SysTime st) @safe
958 {
959 auto result = st.toHash();
960 }
961 }
962
963
964 /++
965 Year of the Gregorian Calendar. Positive numbers are A.D. Non-positive
966 are B.C.
967 +/
968 @property short year() @safe const nothrow scope
969 {
970 return (cast(Date) this).year;
971 }
972
973 @safe unittest
974 {
975 import std.range : chain;
976 static void test(SysTime sysTime, long expected)
977 {
978 assert(sysTime.year == expected, format("Value given: %s", sysTime));
979 }
980
981 test(SysTime(0, UTC()), 1);
982 test(SysTime(1, UTC()), 1);
983 test(SysTime(-1, UTC()), 0);
984
985 foreach (year; chain(testYearsBC, testYearsAD))
986 {
987 foreach (md; testMonthDays)
988 {
989 foreach (tod; testTODs)
990 {
991 auto dt = DateTime(Date(year, md.month, md.day), tod);
992 foreach (tz; testTZs)
993 {
994 foreach (fs; testFracSecs)
995 test(SysTime(dt, fs, tz), year);
996 }
997 }
998 }
999 }
1000
1001 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1002 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1003 assert(cst.year == 1999);
1004 assert(ist.year == 1999);
1005
1006 static void testScope(scope ref SysTime st) @safe
1007 {
1008 auto result = st.year;
1009 }
1010 }
1011
1012 /++
1013 Year of the Gregorian Calendar. Positive numbers are A.D. Non-positive
1014 are B.C.
1015
1016 Params:
1017 year = The year to set this $(LREF SysTime)'s year to.
1018
1019 Throws:
1020 $(REF DateTimeException,std,datetime,date) if the new year is not
1021 a leap year and the resulting date would be on February 29th.
1022 +/
1023 @property void year(int year) @safe scope
1024 {
1025 auto hnsecs = adjTime;
1026 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
1027
1028 if (hnsecs < 0)
1029 {
1030 hnsecs += convert!("hours", "hnsecs")(24);
1031 --days;
1032 }
1033
1034 auto date = Date(cast(int) days);
1035 date.year = year;
1036
1037 immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
1038 adjTime = newDaysHNSecs + hnsecs;
1039 }
1040
1041 ///
1042 @safe unittest
1043 {
1044 import std.datetime.date : DateTime;
1045
1046 assert(SysTime(DateTime(1999, 7, 6, 9, 7, 5)).year == 1999);
1047 assert(SysTime(DateTime(2010, 10, 4, 0, 0, 30)).year == 2010);
1048 assert(SysTime(DateTime(-7, 4, 5, 7, 45, 2)).year == -7);
1049 }
1050
1051 @safe unittest
1052 {
1053 import std.range : chain;
1054
1055 static void test(SysTime st, int year, SysTime expected)
1056 {
1057 st.year = year;
1058 assert(st == expected);
1059 }
1060
1061 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1062 {
1063 auto dt = cast(DateTime) st;
1064
1065 foreach (year; chain(testYearsBC, testYearsAD))
1066 {
1067 auto e = SysTime(DateTime(year, dt.month, dt.day, dt.hour, dt.minute, dt.second),
1068 st.fracSecs,
1069 st.timezone);
1070 test(st, year, e);
1071 }
1072 }
1073
1074 foreach (fs; testFracSecs)
1075 {
1076 foreach (tz; testTZs)
1077 {
1078 foreach (tod; testTODs)
1079 {
1080 test(SysTime(DateTime(Date(1999, 2, 28), tod), fs, tz), 2000,
1081 SysTime(DateTime(Date(2000, 2, 28), tod), fs, tz));
1082 test(SysTime(DateTime(Date(2000, 2, 28), tod), fs, tz), 1999,
1083 SysTime(DateTime(Date(1999, 2, 28), tod), fs, tz));
1084 }
1085
1086 foreach (tod; testTODsThrown)
1087 {
1088 auto st = SysTime(DateTime(Date(2000, 2, 29), tod), fs, tz);
1089 assertThrown!DateTimeException(st.year = 1999);
1090 }
1091 }
1092 }
1093
1094 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1095 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1096 static assert(!__traits(compiles, cst.year = 7));
1097 static assert(!__traits(compiles, ist.year = 7));
1098
1099 static void testScope(scope ref SysTime st) @safe
1100 {
1101 st.year = 42;
1102 }
1103 }
1104
1105 /++
1106 Year B.C. of the Gregorian Calendar counting year 0 as 1 B.C.
1107
1108 Throws:
1109 $(REF DateTimeException,std,datetime,date) if `isAD` is true.
1110 +/
1111 @property ushort yearBC() @safe const scope
1112 {
1113 return (cast(Date) this).yearBC;
1114 }
1115
1116 ///
1117 @safe unittest
1118 {
1119 import std.datetime.date : DateTime;
1120
1121 assert(SysTime(DateTime(0, 1, 1, 12, 30, 33)).yearBC == 1);
1122 assert(SysTime(DateTime(-1, 1, 1, 10, 7, 2)).yearBC == 2);
1123 assert(SysTime(DateTime(-100, 1, 1, 4, 59, 0)).yearBC == 101);
1124 }
1125
1126 @safe unittest
1127 {
1128 import std.exception : assertNotThrown;
1129 foreach (st; testSysTimesBC)
1130 {
1131 auto msg = format("SysTime: %s", st);
1132 assertNotThrown!DateTimeException(st.yearBC, msg);
1133 assert(st.yearBC == (st.year * -1) + 1, msg);
1134 }
1135
1136 foreach (st; [testSysTimesAD[0], testSysTimesAD[$/2], testSysTimesAD[$-1]])
1137 assertThrown!DateTimeException(st.yearBC, format("SysTime: %s", st));
1138
1139 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1140 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1141 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1142 st.year = 12;
1143 assert(st.year == 12);
1144 static assert(!__traits(compiles, cst.year = 12));
1145 static assert(!__traits(compiles, ist.year = 12));
1146
1147 static void testScope(scope ref SysTime st) @safe
1148 {
1149 auto result = st.yearBC;
1150 }
1151 }
1152
1153
1154 /++
1155 Year B.C. of the Gregorian Calendar counting year 0 as 1 B.C.
1156
1157 Params:
1158 year = The year B.C. to set this $(LREF SysTime)'s year to.
1159
1160 Throws:
1161 $(REF DateTimeException,std,datetime,date) if a non-positive value
1162 is given.
1163 +/
1164 @property void yearBC(int year) @safe scope
1165 {
1166 auto hnsecs = adjTime;
1167 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
1168
1169 if (hnsecs < 0)
1170 {
1171 hnsecs += convert!("hours", "hnsecs")(24);
1172 --days;
1173 }
1174
1175 auto date = Date(cast(int) days);
1176 date.yearBC = year;
1177
1178 immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
1179 adjTime = newDaysHNSecs + hnsecs;
1180 }
1181
1182 @safe unittest
1183 {
1184 auto st = SysTime(DateTime(2010, 1, 1, 7, 30, 0));
1185 st.yearBC = 1;
1186 assert(st == SysTime(DateTime(0, 1, 1, 7, 30, 0)));
1187
1188 st.yearBC = 10;
1189 assert(st == SysTime(DateTime(-9, 1, 1, 7, 30, 0)));
1190 }
1191
1192 @safe unittest
1193 {
1194 import std.range : chain;
1195 static void test(SysTime st, int year, SysTime expected)
1196 {
1197 st.yearBC = year;
1198 assert(st == expected, format("SysTime: %s", st));
1199 }
1200
1201 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1202 {
1203 auto dt = cast(DateTime) st;
1204
1205 foreach (year; testYearsBC)
1206 {
1207 auto e = SysTime(DateTime(year, dt.month, dt.day, dt.hour, dt.minute, dt.second),
1208 st.fracSecs,
1209 st.timezone);
1210 test(st, (year * -1) + 1, e);
1211 }
1212 }
1213
1214 foreach (st; [testSysTimesBC[0], testSysTimesBC[$ - 1], testSysTimesAD[0], testSysTimesAD[$ - 1]])
1215 {
1216 foreach (year; testYearsBC)
1217 assertThrown!DateTimeException(st.yearBC = year);
1218 }
1219
1220 foreach (fs; testFracSecs)
1221 {
1222 foreach (tz; testTZs)
1223 {
1224 foreach (tod; testTODs)
1225 {
1226 test(SysTime(DateTime(Date(-1999, 2, 28), tod), fs, tz), 2001,
1227 SysTime(DateTime(Date(-2000, 2, 28), tod), fs, tz));
1228 test(SysTime(DateTime(Date(-2000, 2, 28), tod), fs, tz), 2000,
1229 SysTime(DateTime(Date(-1999, 2, 28), tod), fs, tz));
1230 }
1231
1232 foreach (tod; testTODsThrown)
1233 {
1234 auto st = SysTime(DateTime(Date(-2000, 2, 29), tod), fs, tz);
1235 assertThrown!DateTimeException(st.year = -1999);
1236 }
1237 }
1238 }
1239
1240 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1241 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1242 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1243 st.yearBC = 12;
1244 assert(st.yearBC == 12);
1245 static assert(!__traits(compiles, cst.yearBC = 12));
1246 static assert(!__traits(compiles, ist.yearBC = 12));
1247
1248 static void testScope(scope ref SysTime st) @safe
1249 {
1250 st.yearBC = 42;
1251 }
1252 }
1253
1254
1255 /++
1256 Month of a Gregorian Year.
1257 +/
1258 @property Month month() @safe const nothrow scope
1259 {
1260 return (cast(Date) this).month;
1261 }
1262
1263 ///
1264 @safe unittest
1265 {
1266 import std.datetime.date : DateTime;
1267
1268 assert(SysTime(DateTime(1999, 7, 6, 9, 7, 5)).month == 7);
1269 assert(SysTime(DateTime(2010, 10, 4, 0, 0, 30)).month == 10);
1270 assert(SysTime(DateTime(-7, 4, 5, 7, 45, 2)).month == 4);
1271 }
1272
1273 @safe unittest
1274 {
1275 import std.range : chain;
1276
1277 static void test(SysTime sysTime, Month expected)
1278 {
1279 assert(sysTime.month == expected, format("Value given: %s", sysTime));
1280 }
1281
1282 test(SysTime(0, UTC()), Month.jan);
1283 test(SysTime(1, UTC()), Month.jan);
1284 test(SysTime(-1, UTC()), Month.dec);
1285
1286 foreach (year; chain(testYearsBC, testYearsAD))
1287 {
1288 foreach (md; testMonthDays)
1289 {
1290 foreach (tod; testTODs)
1291 {
1292 auto dt = DateTime(Date(year, md.month, md.day), tod);
1293 foreach (fs; testFracSecs)
1294 {
1295 foreach (tz; testTZs)
1296 test(SysTime(dt, fs, tz), md.month);
1297 }
1298 }
1299 }
1300 }
1301
1302 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1303 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1304 assert(cst.month == 7);
1305 assert(ist.month == 7);
1306
1307 static void testScope(scope ref SysTime st) @safe
1308 {
1309 auto result = st.month;
1310 }
1311 }
1312
1313
1314 /++
1315 Month of a Gregorian Year.
1316
1317 Params:
1318 month = The month to set this $(LREF SysTime)'s month to.
1319
1320 Throws:
1321 $(REF DateTimeException,std,datetime,date) if the given month is
1322 not a valid month.
1323 +/
1324 @property void month(Month month) @safe scope
1325 {
1326 auto hnsecs = adjTime;
1327 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
1328
1329 if (hnsecs < 0)
1330 {
1331 hnsecs += convert!("hours", "hnsecs")(24);
1332 --days;
1333 }
1334
1335 auto date = Date(cast(int) days);
1336 date.month = month;
1337
1338 immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
1339 adjTime = newDaysHNSecs + hnsecs;
1340 }
1341
1342 @safe unittest
1343 {
1344 import std.algorithm.iteration : filter;
1345 import std.range : chain;
1346
1347 static void test(SysTime st, Month month, SysTime expected)
1348 {
1349 st.month = cast(Month) month;
1350 assert(st == expected);
1351 }
1352
1353 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1354 {
1355 auto dt = cast(DateTime) st;
1356
1357 foreach (md; testMonthDays)
1358 {
1359 if (st.day > maxDay(dt.year, md.month))
1360 continue;
1361 auto e = SysTime(DateTime(dt.year, md.month, dt.day, dt.hour, dt.minute, dt.second),
1362 st.fracSecs,
1363 st.timezone);
1364 test(st, md.month, e);
1365 }
1366 }
1367
1368 foreach (fs; testFracSecs)
1369 {
1370 foreach (tz; testTZs)
1371 {
1372 foreach (tod; testTODs)
1373 {
1374 foreach (year; filter!((a){return yearIsLeapYear(a);}) (chain(testYearsBC, testYearsAD)))
1375 {
1376 test(SysTime(DateTime(Date(year, 1, 29), tod), fs, tz),
1377 Month.feb,
1378 SysTime(DateTime(Date(year, 2, 29), tod), fs, tz));
1379 }
1380
1381 foreach (year; chain(testYearsBC, testYearsAD))
1382 {
1383 test(SysTime(DateTime(Date(year, 1, 28), tod), fs, tz),
1384 Month.feb,
1385 SysTime(DateTime(Date(year, 2, 28), tod), fs, tz));
1386 test(SysTime(DateTime(Date(year, 7, 30), tod), fs, tz),
1387 Month.jun,
1388 SysTime(DateTime(Date(year, 6, 30), tod), fs, tz));
1389 }
1390 }
1391 }
1392 }
1393
1394 foreach (fs; [testFracSecs[0], testFracSecs[$-1]])
1395 {
1396 foreach (tz; testTZs)
1397 {
1398 foreach (tod; testTODsThrown)
1399 {
1400 foreach (year; [testYearsBC[$-3], testYearsBC[$-2],
1401 testYearsBC[$-2], testYearsAD[0],
1402 testYearsAD[$-2], testYearsAD[$-1]])
1403 {
1404 auto day = yearIsLeapYear(year) ? 30 : 29;
1405 auto st1 = SysTime(DateTime(Date(year, 1, day), tod), fs, tz);
1406 assertThrown!DateTimeException(st1.month = Month.feb);
1407
1408 auto st2 = SysTime(DateTime(Date(year, 7, 31), tod), fs, tz);
1409 assertThrown!DateTimeException(st2.month = Month.jun);
1410 }
1411 }
1412 }
1413 }
1414
1415 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1416 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1417 static assert(!__traits(compiles, cst.month = Month.dec));
1418 static assert(!__traits(compiles, ist.month = Month.dec));
1419
1420 static void testScope(scope ref SysTime st) @safe
1421 {
1422 st.month = Month.dec;
1423 }
1424 }
1425
1426 /++
1427 Day of a Gregorian Month.
1428 +/
1429 @property ubyte day() @safe const nothrow scope
1430 {
1431 return (cast(Date) this).day;
1432 }
1433
1434 ///
1435 @safe unittest
1436 {
1437 import std.datetime.date : DateTime;
1438
1439 assert(SysTime(DateTime(1999, 7, 6, 9, 7, 5)).day == 6);
1440 assert(SysTime(DateTime(2010, 10, 4, 0, 0, 30)).day == 4);
1441 assert(SysTime(DateTime(-7, 4, 5, 7, 45, 2)).day == 5);
1442 }
1443
1444 @safe unittest
1445 {
1446 import std.range : chain;
1447
1448 static void test(SysTime sysTime, int expected)
1449 {
1450 assert(sysTime.day == expected, format("Value given: %s", sysTime));
1451 }
1452
1453 test(SysTime(0, UTC()), 1);
1454 test(SysTime(1, UTC()), 1);
1455 test(SysTime(-1, UTC()), 31);
1456
1457 foreach (year; chain(testYearsBC, testYearsAD))
1458 {
1459 foreach (md; testMonthDays)
1460 {
1461 foreach (tod; testTODs)
1462 {
1463 auto dt = DateTime(Date(year, md.month, md.day), tod);
1464
1465 foreach (tz; testTZs)
1466 {
1467 foreach (fs; testFracSecs)
1468 test(SysTime(dt, fs, tz), md.day);
1469 }
1470 }
1471 }
1472 }
1473
1474 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1475 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1476 assert(cst.day == 6);
1477 assert(ist.day == 6);
1478
1479 static void testScope(scope ref SysTime st) @safe
1480 {
1481 auto result = st.day;
1482 }
1483 }
1484
1485
1486 /++
1487 Day of a Gregorian Month.
1488
1489 Params:
1490 day = The day of the month to set this $(LREF SysTime)'s day to.
1491
1492 Throws:
1493 $(REF DateTimeException,std,datetime,date) if the given day is not
1494 a valid day of the current month.
1495 +/
1496 @property void day(int day) @safe scope
1497 {
1498 auto hnsecs = adjTime;
1499 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
1500
1501 if (hnsecs < 0)
1502 {
1503 hnsecs += convert!("hours", "hnsecs")(24);
1504 --days;
1505 }
1506
1507 auto date = Date(cast(int) days);
1508 date.day = day;
1509
1510 immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
1511 adjTime = newDaysHNSecs + hnsecs;
1512 }
1513
1514 @safe unittest
1515 {
1516 import std.range : chain;
1517 import std.traits : EnumMembers;
1518
1519 foreach (day; chain(testDays))
1520 {
1521 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1522 {
1523 auto dt = cast(DateTime) st;
1524
1525 if (day > maxDay(dt.year, dt.month))
1526 continue;
1527 auto expected = SysTime(DateTime(dt.year, dt.month, day, dt.hour, dt.minute, dt.second),
1528 st.fracSecs,
1529 st.timezone);
1530 st.day = day;
1531 assert(st == expected, format("[%s] [%s]", st, expected));
1532 }
1533 }
1534
1535 foreach (tz; testTZs)
1536 {
1537 foreach (tod; testTODs)
1538 {
1539 foreach (fs; testFracSecs)
1540 {
1541 foreach (year; chain(testYearsBC, testYearsAD))
1542 {
1543 foreach (month; EnumMembers!Month)
1544 {
1545 auto st = SysTime(DateTime(Date(year, month, 1), tod), fs, tz);
1546 immutable max = maxDay(year, month);
1547 auto expected = SysTime(DateTime(Date(year, month, max), tod), fs, tz);
1548
1549 st.day = max;
1550 assert(st == expected, format("[%s] [%s]", st, expected));
1551 }
1552 }
1553 }
1554 }
1555 }
1556
1557 foreach (tz; testTZs)
1558 {
1559 foreach (tod; testTODsThrown)
1560 {
1561 foreach (fs; [testFracSecs[0], testFracSecs[$-1]])
1562 {
1563 foreach (year; [testYearsBC[$-3], testYearsBC[$-2],
1564 testYearsBC[$-2], testYearsAD[0],
1565 testYearsAD[$-2], testYearsAD[$-1]])
1566 {
1567 foreach (month; EnumMembers!Month)
1568 {
1569 auto st = SysTime(DateTime(Date(year, month, 1), tod), fs, tz);
1570 immutable max = maxDay(year, month);
1571
1572 assertThrown!DateTimeException(st.day = max + 1);
1573 }
1574 }
1575 }
1576 }
1577 }
1578
1579 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1580 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1581 static assert(!__traits(compiles, cst.day = 27));
1582 static assert(!__traits(compiles, ist.day = 27));
1583
1584 static void testScope(scope ref SysTime st) @safe
1585 {
1586 st.day = 12;
1587 }
1588 }
1589
1590
1591 /++
1592 Hours past midnight.
1593 +/
1594 @property ubyte hour() @safe const nothrow scope
1595 {
1596 auto hnsecs = adjTime;
1597 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
1598
1599 if (hnsecs < 0)
1600 {
1601 hnsecs += convert!("hours", "hnsecs")(24);
1602 --days;
1603 }
1604
1605 return cast(ubyte) getUnitsFromHNSecs!"hours"(hnsecs);
1606 }
1607
1608 @safe unittest
1609 {
1610 import std.range : chain;
1611
1612 static void test(SysTime sysTime, int expected)
1613 {
1614 assert(sysTime.hour == expected, format("Value given: %s", sysTime));
1615 }
1616
1617 test(SysTime(0, UTC()), 0);
1618 test(SysTime(1, UTC()), 0);
1619 test(SysTime(-1, UTC()), 23);
1620
1621 foreach (tz; testTZs)
1622 {
1623 foreach (year; chain(testYearsBC, testYearsAD))
1624 {
1625 foreach (md; testMonthDays)
1626 {
1627 foreach (hour; testHours)
1628 {
1629 foreach (minute; testMinSecs)
1630 {
1631 foreach (second; testMinSecs)
1632 {
1633 auto dt = DateTime(Date(year, md.month, md.day), TimeOfDay(hour, minute, second));
1634 foreach (fs; testFracSecs)
1635 test(SysTime(dt, fs, tz), hour);
1636 }
1637 }
1638 }
1639 }
1640 }
1641 }
1642
1643 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1644 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1645 assert(cst.hour == 12);
1646 assert(ist.hour == 12);
1647
1648 static void testScope(scope ref SysTime st) @safe
1649 {
1650 auto result = st.hour;
1651 }
1652 }
1653
1654
1655 /++
1656 Hours past midnight.
1657
1658 Params:
1659 hour = The hours to set this $(LREF SysTime)'s hour to.
1660
1661 Throws:
1662 $(REF DateTimeException,std,datetime,date) if the given hour are
1663 not a valid hour of the day.
1664 +/
1665 @property void hour(int hour) @safe scope
1666 {
1667 enforceValid!"hours"(hour);
1668
1669 auto hnsecs = adjTime;
1670 auto days = splitUnitsFromHNSecs!"days"(hnsecs);
1671 immutable daysHNSecs = convert!("days", "hnsecs")(days);
1672 immutable negative = hnsecs < 0;
1673
1674 if (negative)
1675 hnsecs += convert!("hours", "hnsecs")(24);
1676
1677 hnsecs = removeUnitsFromHNSecs!"hours"(hnsecs);
1678 hnsecs += convert!("hours", "hnsecs")(hour);
1679
1680 if (negative)
1681 hnsecs -= convert!("hours", "hnsecs")(24);
1682
1683 adjTime = daysHNSecs + hnsecs;
1684 }
1685
1686 @safe unittest
1687 {
1688 import std.range : chain;
1689
1690 foreach (hour; chain(testHours))
1691 {
1692 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1693 {
1694 auto dt = cast(DateTime) st;
1695 auto expected = SysTime(DateTime(dt.year, dt.month, dt.day, hour, dt.minute, dt.second),
1696 st.fracSecs,
1697 st.timezone);
1698 st.hour = hour;
1699 assert(st == expected, format("[%s] [%s]", st, expected));
1700 }
1701 }
1702
1703 auto st = testSysTimesAD[0];
1704 assertThrown!DateTimeException(st.hour = -1);
1705 assertThrown!DateTimeException(st.hour = 60);
1706
1707 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1708 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1709 static assert(!__traits(compiles, cst.hour = 27));
1710 static assert(!__traits(compiles, ist.hour = 27));
1711
1712 static void testScope(scope ref SysTime st) @safe
1713 {
1714 st.hour = 12;
1715 }
1716 }
1717
1718
1719 /++
1720 Minutes past the current hour.
1721 +/
1722 @property ubyte minute() @safe const nothrow scope
1723 {
1724 auto hnsecs = adjTime;
1725 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
1726
1727 if (hnsecs < 0)
1728 {
1729 hnsecs += convert!("hours", "hnsecs")(24);
1730 --days;
1731 }
1732
1733 hnsecs = removeUnitsFromHNSecs!"hours"(hnsecs);
1734
1735 return cast(ubyte) getUnitsFromHNSecs!"minutes"(hnsecs);
1736 }
1737
1738 @safe unittest
1739 {
1740 import std.range : chain;
1741
1742 static void test(SysTime sysTime, int expected)
1743 {
1744 assert(sysTime.minute == expected, format("Value given: %s", sysTime));
1745 }
1746
1747 test(SysTime(0, UTC()), 0);
1748 test(SysTime(1, UTC()), 0);
1749 test(SysTime(-1, UTC()), 59);
1750
1751 foreach (tz; testTZs)
1752 {
1753 foreach (year; chain(testYearsBC, testYearsAD))
1754 {
1755 foreach (md; testMonthDays)
1756 {
1757 foreach (hour; testHours)
1758 {
1759 foreach (minute; testMinSecs)
1760 {
1761 foreach (second; testMinSecs)
1762 {
1763 auto dt = DateTime(Date(year, md.month, md.day), TimeOfDay(hour, minute, second));
1764 foreach (fs; testFracSecs)
1765 test(SysTime(dt, fs, tz), minute);
1766 }
1767 }
1768 }
1769 }
1770 }
1771 }
1772
1773 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1774 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1775 assert(cst.minute == 30);
1776 assert(ist.minute == 30);
1777
1778 static void testScope(scope ref SysTime st) @safe
1779 {
1780 auto result = st.minute;
1781 }
1782 }
1783
1784
1785 /++
1786 Minutes past the current hour.
1787
1788 Params:
1789 minute = The minute to set this $(LREF SysTime)'s minute to.
1790
1791 Throws:
1792 $(REF DateTimeException,std,datetime,date) if the given minute are
1793 not a valid minute of an hour.
1794 +/
1795 @property void minute(int minute) @safe scope
1796 {
1797 enforceValid!"minutes"(minute);
1798
1799 auto hnsecs = adjTime;
1800 auto days = splitUnitsFromHNSecs!"days"(hnsecs);
1801 immutable daysHNSecs = convert!("days", "hnsecs")(days);
1802 immutable negative = hnsecs < 0;
1803
1804 if (negative)
1805 hnsecs += convert!("hours", "hnsecs")(24);
1806
1807 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
1808 hnsecs = removeUnitsFromHNSecs!"minutes"(hnsecs);
1809
1810 hnsecs += convert!("hours", "hnsecs")(hour);
1811 hnsecs += convert!("minutes", "hnsecs")(minute);
1812
1813 if (negative)
1814 hnsecs -= convert!("hours", "hnsecs")(24);
1815
1816 adjTime = daysHNSecs + hnsecs;
1817 }
1818
1819 @safe unittest
1820 {
1821 import std.range : chain;
1822
1823 foreach (minute; testMinSecs)
1824 {
1825 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1826 {
1827 auto dt = cast(DateTime) st;
1828 auto expected = SysTime(DateTime(dt.year, dt.month, dt.day, dt.hour, minute, dt.second),
1829 st.fracSecs,
1830 st.timezone);
1831 st.minute = minute;
1832 assert(st == expected, format("[%s] [%s]", st, expected));
1833 }
1834 }
1835
1836 auto st = testSysTimesAD[0];
1837 assertThrown!DateTimeException(st.minute = -1);
1838 assertThrown!DateTimeException(st.minute = 60);
1839
1840 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1841 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1842 static assert(!__traits(compiles, cst.minute = 27));
1843 static assert(!__traits(compiles, ist.minute = 27));
1844
1845 static void testScope(scope ref SysTime st) @safe
1846 {
1847 st.minute = 12;
1848 }
1849 }
1850
1851
1852 /++
1853 Seconds past the current minute.
1854 +/
1855 @property ubyte second() @safe const nothrow scope
1856 {
1857 auto hnsecs = adjTime;
1858 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
1859
1860 if (hnsecs < 0)
1861 {
1862 hnsecs += convert!("hours", "hnsecs")(24);
1863 --days;
1864 }
1865
1866 hnsecs = removeUnitsFromHNSecs!"hours"(hnsecs);
1867 hnsecs = removeUnitsFromHNSecs!"minutes"(hnsecs);
1868
1869 return cast(ubyte) getUnitsFromHNSecs!"seconds"(hnsecs);
1870 }
1871
1872 @safe unittest
1873 {
1874 import std.range : chain;
1875
1876 static void test(SysTime sysTime, int expected)
1877 {
1878 assert(sysTime.second == expected, format("Value given: %s", sysTime));
1879 }
1880
1881 test(SysTime(0, UTC()), 0);
1882 test(SysTime(1, UTC()), 0);
1883 test(SysTime(-1, UTC()), 59);
1884
1885 foreach (tz; testTZs)
1886 {
1887 foreach (year; chain(testYearsBC, testYearsAD))
1888 {
1889 foreach (md; testMonthDays)
1890 {
1891 foreach (hour; testHours)
1892 {
1893 foreach (minute; testMinSecs)
1894 {
1895 foreach (second; testMinSecs)
1896 {
1897 auto dt = DateTime(Date(year, md.month, md.day), TimeOfDay(hour, minute, second));
1898 foreach (fs; testFracSecs)
1899 test(SysTime(dt, fs, tz), second);
1900 }
1901 }
1902 }
1903 }
1904 }
1905 }
1906
1907 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1908 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1909 assert(cst.second == 33);
1910 assert(ist.second == 33);
1911
1912 static void testScope(scope ref SysTime st) @safe
1913 {
1914 auto result = st.second;
1915 }
1916 }
1917
1918
1919 /++
1920 Seconds past the current minute.
1921
1922 Params:
1923 second = The second to set this $(LREF SysTime)'s second to.
1924
1925 Throws:
1926 $(REF DateTimeException,std,datetime,date) if the given second are
1927 not a valid second of a minute.
1928 +/
1929 @property void second(int second) @safe scope
1930 {
1931 enforceValid!"seconds"(second);
1932
1933 auto hnsecs = adjTime;
1934 auto days = splitUnitsFromHNSecs!"days"(hnsecs);
1935 immutable daysHNSecs = convert!("days", "hnsecs")(days);
1936 immutable negative = hnsecs < 0;
1937
1938 if (negative)
1939 hnsecs += convert!("hours", "hnsecs")(24);
1940
1941 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
1942 immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
1943 hnsecs = removeUnitsFromHNSecs!"seconds"(hnsecs);
1944
1945 hnsecs += convert!("hours", "hnsecs")(hour);
1946 hnsecs += convert!("minutes", "hnsecs")(minute);
1947 hnsecs += convert!("seconds", "hnsecs")(second);
1948
1949 if (negative)
1950 hnsecs -= convert!("hours", "hnsecs")(24);
1951
1952 adjTime = daysHNSecs + hnsecs;
1953 }
1954
1955 @safe unittest
1956 {
1957 import std.range : chain;
1958
1959 foreach (second; testMinSecs)
1960 {
1961 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1962 {
1963 auto dt = cast(DateTime) st;
1964 auto expected = SysTime(DateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute, second),
1965 st.fracSecs,
1966 st.timezone);
1967 st.second = second;
1968 assert(st == expected, format("[%s] [%s]", st, expected));
1969 }
1970 }
1971
1972 auto st = testSysTimesAD[0];
1973 assertThrown!DateTimeException(st.second = -1);
1974 assertThrown!DateTimeException(st.second = 60);
1975
1976 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1977 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1978 static assert(!__traits(compiles, cst.seconds = 27));
1979 static assert(!__traits(compiles, ist.seconds = 27));
1980
1981 static void testScope(scope ref SysTime st) @safe
1982 {
1983 st.second = 12;
1984 }
1985 }
1986
1987
1988 /++
1989 Fractional seconds past the second (i.e. the portion of a
1990 $(LREF SysTime) which is less than a second).
1991 +/
1992 @property Duration fracSecs() @safe const nothrow scope
1993 {
1994 auto hnsecs = removeUnitsFromHNSecs!"days"(adjTime);
1995
1996 if (hnsecs < 0)
1997 hnsecs += convert!("hours", "hnsecs")(24);
1998
1999 return dur!"hnsecs"(removeUnitsFromHNSecs!"seconds"(hnsecs));
2000 }
2001
2002 ///
2003 @safe unittest
2004 {
2005 import core.time : msecs, usecs, hnsecs, nsecs;
2006 import std.datetime.date : DateTime;
2007
2008 auto dt = DateTime(1982, 4, 1, 20, 59, 22);
2009 assert(SysTime(dt, msecs(213)).fracSecs == msecs(213));
2010 assert(SysTime(dt, usecs(5202)).fracSecs == usecs(5202));
2011 assert(SysTime(dt, hnsecs(1234567)).fracSecs == hnsecs(1234567));
2012
2013 // SysTime and Duration both have a precision of hnsecs (100 ns),
2014 // so nsecs are going to be truncated.
2015 assert(SysTime(dt, nsecs(123456789)).fracSecs == nsecs(123456700));
2016 }
2017
2018 @safe unittest
2019 {
2020 import std.range : chain;
2021 import core.time;
2022
2023 assert(SysTime(0, UTC()).fracSecs == Duration.zero);
2024 assert(SysTime(1, UTC()).fracSecs == hnsecs(1));
2025 assert(SysTime(-1, UTC()).fracSecs == hnsecs(9_999_999));
2026
2027 foreach (tz; testTZs)
2028 {
2029 foreach (year; chain(testYearsBC, testYearsAD))
2030 {
2031 foreach (md; testMonthDays)
2032 {
2033 foreach (hour; testHours)
2034 {
2035 foreach (minute; testMinSecs)
2036 {
2037 foreach (second; testMinSecs)
2038 {
2039 auto dt = DateTime(Date(year, md.month, md.day), TimeOfDay(hour, minute, second));
2040 foreach (fs; testFracSecs)
2041 assert(SysTime(dt, fs, tz).fracSecs == fs);
2042 }
2043 }
2044 }
2045 }
2046 }
2047 }
2048
2049 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
2050 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
2051 assert(cst.fracSecs == Duration.zero);
2052 assert(ist.fracSecs == Duration.zero);
2053
2054 static void testScope(scope ref SysTime st) @safe
2055 {
2056 auto result = st.fracSecs;
2057 }
2058 }
2059
2060
2061 /++
2062 Fractional seconds past the second (i.e. the portion of a
2063 $(LREF SysTime) which is less than a second).
2064
2065 Params:
2066 fracSecs = The duration to set this $(LREF SysTime)'s fractional
2067 seconds to.
2068
2069 Throws:
2070 $(REF DateTimeException,std,datetime,date) if the given duration
2071 is negative or if it's greater than or equal to one second.
2072 +/
2073 @property void fracSecs(Duration fracSecs) @safe scope
2074 {
2075 enforce(fracSecs >= Duration.zero, new DateTimeException("A SysTime cannot have negative fractional seconds."));
2076 enforce(fracSecs < seconds(1), new DateTimeException("Fractional seconds must be less than one second."));
2077
2078 auto oldHNSecs = adjTime;
2079 auto days = splitUnitsFromHNSecs!"days"(oldHNSecs);
2080 immutable daysHNSecs = convert!("days", "hnsecs")(days);
2081 immutable negative = oldHNSecs < 0;
2082
2083 if (negative)
2084 oldHNSecs += convert!("hours", "hnsecs")(24);
2085
2086 immutable seconds = splitUnitsFromHNSecs!"seconds"(oldHNSecs);
2087 immutable secondsHNSecs = convert!("seconds", "hnsecs")(seconds);
2088 auto newHNSecs = fracSecs.total!"hnsecs" + secondsHNSecs;
2089
2090 if (negative)
2091 newHNSecs -= convert!("hours", "hnsecs")(24);
2092
2093 adjTime = daysHNSecs + newHNSecs;
2094 }
2095
2096 ///
2097 @safe unittest
2098 {
2099 import core.time : Duration, msecs, hnsecs, nsecs;
2100 import std.datetime.date : DateTime;
2101
2102 auto st = SysTime(DateTime(1982, 4, 1, 20, 59, 22));
2103 assert(st.fracSecs == Duration.zero);
2104
2105 st.fracSecs = msecs(213);
2106 assert(st.fracSecs == msecs(213));
2107
2108 st.fracSecs = hnsecs(1234567);
2109 assert(st.fracSecs == hnsecs(1234567));
2110
2111 // SysTime has a precision of hnsecs (100 ns), so nsecs are
2112 // going to be truncated.
2113 st.fracSecs = nsecs(123456789);
2114 assert(st.fracSecs == hnsecs(1234567));
2115 }
2116
2117 @safe unittest
2118 {
2119 import std.range : chain;
2120 import core.time;
2121
2122 foreach (fracSec; testFracSecs)
2123 {
2124 foreach (st; chain(testSysTimesBC, testSysTimesAD))
2125 {
2126 auto dt = cast(DateTime) st;
2127 auto expected = SysTime(dt, fracSec, st.timezone);
2128 st.fracSecs = fracSec;
2129 assert(st == expected, format("[%s] [%s]", st, expected));
2130 }
2131 }
2132
2133 auto st = testSysTimesAD[0];
2134 assertThrown!DateTimeException(st.fracSecs = hnsecs(-1));
2135 assertThrown!DateTimeException(st.fracSecs = seconds(1));
2136
2137 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
2138 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
2139 static assert(!__traits(compiles, cst.fracSecs = msecs(7)));
2140 static assert(!__traits(compiles, ist.fracSecs = msecs(7)));
2141
2142 static void testScope(scope ref SysTime st) @safe
2143 {
2144 st.fracSecs = Duration.zero;
2145 }
2146 }
2147
2148
2149 /++
2150 The total hnsecs from midnight, January 1st, 1 A.D. UTC. This is the
2151 internal representation of $(LREF SysTime).
2152 +/
2153 @property long stdTime() @safe const pure nothrow scope @nogc
2154 {
2155 return _stdTime;
2156 }
2157
2158 @safe unittest
2159 {
2160 import core.time;
2161 assert(SysTime(0).stdTime == 0);
2162 assert(SysTime(1).stdTime == 1);
2163 assert(SysTime(-1).stdTime == -1);
2164 assert(SysTime(DateTime(1, 1, 1, 0, 0, 33), hnsecs(502), UTC()).stdTime == 330_000_502L);
2165 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 0), UTC()).stdTime == 621_355_968_000_000_000L);
2166
2167 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
2168 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
2169 assert(cst.stdTime > 0);
2170 assert(ist.stdTime > 0);
2171
2172 static void testScope(scope ref SysTime st) @safe
2173 {
2174 auto result = st.stdTime;
2175 }
2176 }
2177
2178
2179 /++
2180 The total hnsecs from midnight, January 1st, 1 A.D. UTC. This is the
2181 internal representation of $(LREF SysTime).
2182
2183 Params:
2184 stdTime = The number of hnsecs since January 1st, 1 A.D. UTC.
2185 +/
2186 @property void stdTime(long stdTime) @safe pure nothrow scope
2187 {
2188 _stdTime = stdTime;
2189 }
2190
2191 @safe unittest
2192 {
2193 import core.time;
2194 static void test(long stdTime, SysTime expected, size_t line = __LINE__)
2195 {
2196 auto st = SysTime(0, UTC());
2197 st.stdTime = stdTime;
2198 assert(st == expected);
2199 }
2200
2201 test(0, SysTime(Date(1, 1, 1), UTC()));
2202 test(1, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1), UTC()));
2203 test(-1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()));
2204 test(330_000_502L, SysTime(DateTime(1, 1, 1, 0, 0, 33), hnsecs(502), UTC()));
2205 test(621_355_968_000_000_000L, SysTime(DateTime(1970, 1, 1, 0, 0, 0), UTC()));
2206
2207 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
2208 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
2209 static assert(!__traits(compiles, cst.stdTime = 27));
2210 static assert(!__traits(compiles, ist.stdTime = 27));
2211
2212 static void testScope(scope ref SysTime st) @safe
2213 {
2214 st.stdTime = 42;
2215 }
2216 }
2217
2218
2219 /++
2220 The current time zone of this $(LREF SysTime). Its internal time is
2221 always kept in UTC, so there are no conversion issues between time zones
2222 due to DST. Functions which return all or part of the time - such as
2223 hours - adjust the time to this $(LREF SysTime)'s time zone before
2224 returning.
2225 +/
2226 @property immutable(TimeZone) timezone() @safe const pure nothrow return scope
2227 {
2228 return _timezone;
2229 }
2230
2231 @safe unittest
2232 {
2233 assert(SysTime.init.timezone is InitTimeZone());
2234 assert(SysTime(DateTime.init, UTC()).timezone is UTC());
2235
2236 static void testScope(scope ref SysTime st) @safe
2237 {
2238 auto result = st.timezone;
2239 }
2240 }
2241
2242
2243 /++
2244 The current time zone of this $(LREF SysTime). It's internal time is
2245 always kept in UTC, so there are no conversion issues between time zones
2246 due to DST. Functions which return all or part of the time - such as
2247 hours - adjust the time to this $(LREF SysTime)'s time zone before
2248 returning.
2249
2250 Params:
2251 timezone = The $(REF _TimeZone,std,datetime,_timezone) to set this
2252 $(LREF SysTime)'s time zone to.
2253 +/
2254 @property void timezone(immutable TimeZone timezone) @safe pure nothrow scope
2255 {
2256 if (timezone is null)
2257 _timezone = LocalTime();
2258 else
2259 _timezone = timezone;
2260 }
2261
2262 @safe unittest
2263 {
2264 SysTime st;
2265 st.timezone = null;
2266 assert(st.timezone is LocalTime());
2267 st.timezone = UTC();
2268 assert(st.timezone is UTC());
2269
2270 static void testScope(scope ref SysTime st) @safe
2271 {
2272 st.timezone = UTC();
2273 }
2274 }
2275
2276
2277 /++
2278 Returns whether DST is in effect for this $(LREF SysTime).
2279 +/
2280 @property bool dstInEffect() @safe const nothrow return scope
2281 {
2282 return _timezone.dstInEffect(_stdTime);
2283 }
2284
2285 // This function's full unit testing is done in the time zone classes, but
2286 // this verifies that SysTime.init works correctly, since historically, it
2287 // has segfaulted due to a null _timezone.
2288 @safe unittest
2289 {
2290 assert(!SysTime.init.dstInEffect);
2291
2292 static void testScope(scope ref SysTime st) @safe
2293 {
2294 auto result = st.dstInEffect;
2295 }
2296 }
2297
2298
2299 /++
2300 Returns what the offset from UTC is for this $(LREF SysTime).
2301 It includes the DST offset in effect at that time (if any).
2302 +/
2303 @property Duration utcOffset() @safe const nothrow return scope
2304 {
2305 return _timezone.utcOffsetAt(_stdTime);
2306 }
2307
2308 // This function's full unit testing is done in the time zone classes, but
2309 // this verifies that SysTime.init works correctly, since historically, it
2310 // has segfaulted due to a null _timezone.
2311 @safe unittest
2312 {
2313 assert(SysTime.init.utcOffset == Duration.zero);
2314
2315 static void testScope(scope ref SysTime st) @safe
2316 {
2317 auto result = st.utcOffset;
2318 }
2319 }
2320
2321
2322 /++
2323 Returns a $(LREF SysTime) with the same std time as this one, but with
2324 $(REF LocalTime,std,datetime,timezone) as its time zone.
2325 +/
2326 SysTime toLocalTime() @safe const pure nothrow scope
2327 {
2328 return SysTime(_stdTime, LocalTime());
2329 }
2330
2331 @safe unittest
2332 {
2333 import core.time;
2334 {
2335 auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), hnsecs(27));
2336 assert(sysTime == sysTime.toLocalTime());
2337 assert(sysTime._stdTime == sysTime.toLocalTime()._stdTime);
2338 assert(sysTime.toLocalTime().timezone is LocalTime());
2339 assert(sysTime.toLocalTime().timezone is sysTime.timezone);
2340 assert(sysTime.toLocalTime().timezone !is UTC());
2341 }
2342
2343 {
2344 auto stz = new immutable SimpleTimeZone(dur!"minutes"(-3 * 60));
2345 auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), hnsecs(27), stz);
2346 assert(sysTime == sysTime.toLocalTime());
2347 assert(sysTime._stdTime == sysTime.toLocalTime()._stdTime);
2348 assert(sysTime.toLocalTime().timezone is LocalTime());
2349 assert(sysTime.toLocalTime().timezone !is UTC());
2350 assert(sysTime.toLocalTime().timezone !is stz);
2351 }
2352
2353 static void testScope(scope ref SysTime st) @safe
2354 {
2355 auto result = st.toLocalTime();
2356 }
2357 }
2358
2359
2360 /++
2361 Returns a $(LREF SysTime) with the same std time as this one, but with
2362 `UTC` as its time zone.
2363 +/
2364 SysTime toUTC() @safe const pure nothrow scope
2365 {
2366 return SysTime(_stdTime, UTC());
2367 }
2368
2369 @safe unittest
2370 {
2371 import core.time;
2372 auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), hnsecs(27));
2373 assert(sysTime == sysTime.toUTC());
2374 assert(sysTime._stdTime == sysTime.toUTC()._stdTime);
2375 assert(sysTime.toUTC().timezone is UTC());
2376 assert(sysTime.toUTC().timezone !is LocalTime());
2377 assert(sysTime.toUTC().timezone !is sysTime.timezone);
2378
2379 static void testScope(scope ref SysTime st) @safe
2380 {
2381 auto result = st.toUTC();
2382 }
2383 }
2384
2385
2386 /++
2387 Returns a $(LREF SysTime) with the same std time as this one, but with
2388 given time zone as its time zone.
2389 +/
2390 SysTime toOtherTZ(immutable TimeZone tz) @safe const pure nothrow scope
2391 {
2392 if (tz is null)
2393 return SysTime(_stdTime, LocalTime());
2394 else
2395 return SysTime(_stdTime, tz);
2396 }
2397
2398 @safe unittest
2399 {
2400 import core.time;
2401 auto stz = new immutable SimpleTimeZone(dur!"minutes"(11 * 60));
2402 auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), hnsecs(27));
2403 assert(sysTime == sysTime.toOtherTZ(stz));
2404 assert(sysTime._stdTime == sysTime.toOtherTZ(stz)._stdTime);
2405 assert(sysTime.toOtherTZ(stz).timezone is stz);
2406 assert(sysTime.toOtherTZ(stz).timezone !is LocalTime());
2407 assert(sysTime.toOtherTZ(stz).timezone !is UTC());
2408 assert(sysTime.toOtherTZ(null).timezone is LocalTime());
2409
2410 static void testScope(scope ref SysTime st) @safe
2411 {
2412 auto result = st.toOtherTZ(null);
2413 }
2414 }
2415
2416
2417 /++
2418 Converts this $(LREF SysTime) to unix time (i.e. seconds from midnight,
2419 January 1st, 1970 in UTC).
2420
2421 The C standard does not specify the representation of time_t, so it is
2422 implementation defined. On POSIX systems, unix time is equivalent to
2423 time_t, but that's not necessarily true on other systems (e.g. it is
2424 not true for the Digital Mars C runtime). So, be careful when using unix
2425 time with C functions on non-POSIX systems.
2426
2427 By default, the return type is time_t (which is normally an alias for
2428 int on 32-bit systems and long on 64-bit systems), but if a different
2429 size is required than either int or long can be passed as a template
2430 argument to get the desired size.
2431
2432 If the return type is int, and the result can't fit in an int, then the
2433 closest value that can be held in 32 bits will be used (so `int.max`
2434 if it goes over and `int.min` if it goes under). However, no attempt
2435 is made to deal with integer overflow if the return type is long.
2436
2437 Params:
2438 T = The return type (int or long). It defaults to time_t, which is
2439 normally 32 bits on a 32-bit system and 64 bits on a 64-bit
2440 system.
2441
2442 Returns:
2443 A signed integer representing the unix time which is equivalent to
2444 this SysTime.
2445 +/
2446 T toUnixTime(T = time_t)() @safe const pure nothrow scope
2447 if (is(T == int) || is(T == long))
2448 {
2449 return stdTimeToUnixTime!T(_stdTime);
2450 }
2451
2452 ///
2453 @safe unittest
2454 {
2455 import core.time : hours;
2456 import std.datetime.date : DateTime;
2457 import std.datetime.timezone : SimpleTimeZone, UTC;
2458
2459 assert(SysTime(DateTime(1970, 1, 1), UTC()).toUnixTime() == 0);
2460
2461 auto pst = new immutable SimpleTimeZone(hours(-8));
2462 assert(SysTime(DateTime(1970, 1, 1), pst).toUnixTime() == 28800);
2463
2464 auto utc = SysTime(DateTime(2007, 12, 22, 8, 14, 45), UTC());
2465 assert(utc.toUnixTime() == 1_198_311_285);
2466
2467 auto ca = SysTime(DateTime(2007, 12, 22, 8, 14, 45), pst);
2468 assert(ca.toUnixTime() == 1_198_340_085);
2469
2470 static void testScope(scope ref SysTime st) @safe
2471 {
2472 auto result = st.toUnixTime();
2473 }
2474 }
2475
2476 @safe unittest
2477 {
2478 import std.meta : AliasSeq;
2479 import core.time;
2480 assert(SysTime(DateTime(1970, 1, 1), UTC()).toUnixTime() == 0);
2481 static foreach (units; ["hnsecs", "usecs", "msecs"])
2482 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 0), dur!units(1), UTC()).toUnixTime() == 0);
2483 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), UTC()).toUnixTime() == 1);
2484 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toUnixTime() == 0);
2485 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), usecs(999_999), UTC()).toUnixTime() == 0);
2486 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), msecs(999), UTC()).toUnixTime() == 0);
2487 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), UTC()).toUnixTime() == -1);
2488 }
2489
2490
2491 /++
2492 Converts from unix time (i.e. seconds from midnight, January 1st, 1970
2493 in UTC) to a $(LREF SysTime).
2494
2495 The C standard does not specify the representation of time_t, so it is
2496 implementation defined. On POSIX systems, unix time is equivalent to
2497 time_t, but that's not necessarily true on other systems (e.g. it is
2498 not true for the Digital Mars C runtime). So, be careful when using unix
2499 time with C functions on non-POSIX systems.
2500
2501 Params:
2502 unixTime = Seconds from midnight, January 1st, 1970 in UTC.
2503 tz = The time zone for the SysTime that's returned.
2504 +/
2505 static SysTime fromUnixTime(long unixTime, immutable TimeZone tz = LocalTime()) @safe pure nothrow
2506 {
2507 return SysTime(unixTimeToStdTime(unixTime), tz);
2508 }
2509
2510 ///
2511 @safe unittest
2512 {
2513 import core.time : hours;
2514 import std.datetime.date : DateTime;
2515 import std.datetime.timezone : SimpleTimeZone, UTC;
2516
2517 assert(SysTime.fromUnixTime(0) ==
2518 SysTime(DateTime(1970, 1, 1), UTC()));
2519
2520 auto pst = new immutable SimpleTimeZone(hours(-8));
2521 assert(SysTime.fromUnixTime(28800) ==
2522 SysTime(DateTime(1970, 1, 1), pst));
2523
2524 auto st1 = SysTime.fromUnixTime(1_198_311_285, UTC());
2525 assert(st1 == SysTime(DateTime(2007, 12, 22, 8, 14, 45), UTC()));
2526 assert(st1.timezone is UTC());
2527 assert(st1 == SysTime(DateTime(2007, 12, 22, 0, 14, 45), pst));
2528
2529 auto st2 = SysTime.fromUnixTime(1_198_311_285, pst);
2530 assert(st2 == SysTime(DateTime(2007, 12, 22, 8, 14, 45), UTC()));
2531 assert(st2.timezone is pst);
2532 assert(st2 == SysTime(DateTime(2007, 12, 22, 0, 14, 45), pst));
2533 }
2534
2535 @safe unittest
2536 {
2537 import core.time;
2538 assert(SysTime.fromUnixTime(0) == SysTime(DateTime(1970, 1, 1), UTC()));
2539 assert(SysTime.fromUnixTime(1) == SysTime(DateTime(1970, 1, 1, 0, 0, 1), UTC()));
2540 assert(SysTime.fromUnixTime(-1) == SysTime(DateTime(1969, 12, 31, 23, 59, 59), UTC()));
2541
2542 auto st = SysTime.fromUnixTime(0);
2543 auto dt = cast(DateTime) st;
2544 assert(dt <= DateTime(1970, 2, 1) && dt >= DateTime(1969, 12, 31));
2545 assert(st.timezone is LocalTime());
2546
2547 auto aest = new immutable SimpleTimeZone(hours(10));
2548 assert(SysTime.fromUnixTime(-36000) == SysTime(DateTime(1970, 1, 1), aest));
2549 }
2550
2551
2552 /++
2553 Returns a `timeval` which represents this $(LREF SysTime).
2554
2555 Note that like all conversions in std.datetime, this is a truncating
2556 conversion.
2557
2558 If `timeval.tv_sec` is int, and the result can't fit in an int, then
2559 the closest value that can be held in 32 bits will be used for
2560 `tv_sec`. (so `int.max` if it goes over and `int.min` if it
2561 goes under).
2562 +/
2563 timeval toTimeVal() @safe const pure nothrow scope
2564 {
2565 immutable tv_sec = toUnixTime!(typeof(timeval.tv_sec))();
2566 immutable fracHNSecs = removeUnitsFromHNSecs!"seconds"(_stdTime - 621_355_968_000_000_000L);
2567 immutable tv_usec = cast(typeof(timeval.tv_usec))convert!("hnsecs", "usecs")(fracHNSecs);
2568 return timeval(tv_sec, tv_usec);
2569 }
2570
2571 @safe unittest
2572 {
2573 import core.time;
2574 assert(SysTime(DateTime(1970, 1, 1), UTC()).toTimeVal() == timeval(0, 0));
2575 assert(SysTime(DateTime(1970, 1, 1), hnsecs(9), UTC()).toTimeVal() == timeval(0, 0));
2576 assert(SysTime(DateTime(1970, 1, 1), hnsecs(10), UTC()).toTimeVal() == timeval(0, 1));
2577 assert(SysTime(DateTime(1970, 1, 1), usecs(7), UTC()).toTimeVal() == timeval(0, 7));
2578
2579 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), UTC()).toTimeVal() == timeval(1, 0));
2580 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), hnsecs(9), UTC()).toTimeVal() == timeval(1, 0));
2581 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), hnsecs(10), UTC()).toTimeVal() == timeval(1, 1));
2582 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), usecs(7), UTC()).toTimeVal() == timeval(1, 7));
2583
2584 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toTimeVal() == timeval(0, 0));
2585 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), hnsecs(9_999_990), UTC()).toTimeVal() == timeval(0, -1));
2586
2587 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), usecs(999_999), UTC()).toTimeVal() == timeval(0, -1));
2588 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), usecs(999), UTC()).toTimeVal() == timeval(0, -999_001));
2589 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), msecs(999), UTC()).toTimeVal() == timeval(0, -1000));
2590 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), UTC()).toTimeVal() == timeval(-1, 0));
2591 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 58), usecs(17), UTC()).toTimeVal() == timeval(-1, -999_983));
2592
2593 static void testScope(scope ref SysTime st) @safe
2594 {
2595 auto result = st.toTimeVal();
2596 }
2597 }
2598
2599
2600 version (StdDdoc)
2601 {
2602 version (Windows) private struct timespec {}
2603 /++
2604 Returns a `timespec` which represents this $(LREF SysTime).
2605
2606 $(BLUE This function is Posix-Only.)
2607 +/
2608 timespec toTimeSpec() @safe const pure nothrow scope;
2609 }
2610 else version (Posix)
2611 {
2612 timespec toTimeSpec() @safe const pure nothrow scope
2613 {
2614 immutable tv_sec = toUnixTime!(typeof(timespec.tv_sec))();
2615 immutable fracHNSecs = removeUnitsFromHNSecs!"seconds"(_stdTime - 621_355_968_000_000_000L);
2616 immutable tv_nsec = cast(typeof(timespec.tv_nsec))convert!("hnsecs", "nsecs")(fracHNSecs);
2617 return timespec(tv_sec, tv_nsec);
2618 }
2619
2620 @safe unittest
2621 {
2622 import core.time;
2623 assert(SysTime(DateTime(1970, 1, 1), UTC()).toTimeSpec() == timespec(0, 0));
2624 assert(SysTime(DateTime(1970, 1, 1), hnsecs(9), UTC()).toTimeSpec() == timespec(0, 900));
2625 assert(SysTime(DateTime(1970, 1, 1), hnsecs(10), UTC()).toTimeSpec() == timespec(0, 1000));
2626 assert(SysTime(DateTime(1970, 1, 1), usecs(7), UTC()).toTimeSpec() == timespec(0, 7000));
2627
2628 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), UTC()).toTimeSpec() == timespec(1, 0));
2629 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), hnsecs(9), UTC()).toTimeSpec() == timespec(1, 900));
2630 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), hnsecs(10), UTC()).toTimeSpec() == timespec(1, 1000));
2631 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), usecs(7), UTC()).toTimeSpec() == timespec(1, 7000));
2632
2633 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toTimeSpec() ==
2634 timespec(0, -100));
2635 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), hnsecs(9_999_990), UTC()).toTimeSpec() ==
2636 timespec(0, -1000));
2637
2638 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), usecs(999_999), UTC()).toTimeSpec() ==
2639 timespec(0, -1_000));
2640 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), usecs(999), UTC()).toTimeSpec() ==
2641 timespec(0, -999_001_000));
2642 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), msecs(999), UTC()).toTimeSpec() ==
2643 timespec(0, -1_000_000));
2644 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), UTC()).toTimeSpec() ==
2645 timespec(-1, 0));
2646 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 58), usecs(17), UTC()).toTimeSpec() ==
2647 timespec(-1, -999_983_000));
2648
2649 static void testScope(scope ref SysTime st) @safe
2650 {
2651 auto result = st.toTimeSpec();
2652 }
2653 }
2654 }
2655
2656 /++
2657 Returns a `tm` which represents this $(LREF SysTime).
2658 +/
2659 tm toTM() @safe const nothrow scope
2660 {
2661 auto dateTime = cast(DateTime) this;
2662 tm timeInfo;
2663
2664 timeInfo.tm_sec = dateTime.second;
2665 timeInfo.tm_min = dateTime.minute;
2666 timeInfo.tm_hour = dateTime.hour;
2667 timeInfo.tm_mday = dateTime.day;
2668 timeInfo.tm_mon = dateTime.month - 1;
2669 timeInfo.tm_year = dateTime.year - 1900;
2670 timeInfo.tm_wday = dateTime.dayOfWeek;
2671 timeInfo.tm_yday = dateTime.dayOfYear - 1;
2672 timeInfo.tm_isdst = _timezone.dstInEffect(_stdTime);
2673
2674 version (Posix)
2675 {
2676 import std.utf : toUTFz;
2677 timeInfo.tm_gmtoff = cast(int) convert!("hnsecs", "seconds")(adjTime - _stdTime);
2678 auto zone = timeInfo.tm_isdst ? _timezone.dstName : _timezone.stdName;
2679 timeInfo.tm_zone = zone.toUTFz!(char*)();
2680 }
2681
2682 return timeInfo;
2683 }
2684
2685 @system unittest
2686 {
2687 import std.conv : to;
2688 import core.time;
2689
2690 version (Posix)
2691 {
2692 import std.datetime.timezone : clearTZEnvVar, setTZEnvVar;
2693 setTZEnvVar("America/Los_Angeles");
2694 scope(exit) clearTZEnvVar();
2695 }
2696
2697 {
2698 auto timeInfo = SysTime(DateTime(1970, 1, 1)).toTM();
2699
2700 assert(timeInfo.tm_sec == 0);
2701 assert(timeInfo.tm_min == 0);
2702 assert(timeInfo.tm_hour == 0);
2703 assert(timeInfo.tm_mday == 1);
2704 assert(timeInfo.tm_mon == 0);
2705 assert(timeInfo.tm_year == 70);
2706 assert(timeInfo.tm_wday == 4);
2707 assert(timeInfo.tm_yday == 0);
2708
2709 version (Posix)
2710 assert(timeInfo.tm_isdst == 0);
2711 else version (Windows)
2712 assert(timeInfo.tm_isdst == 0 || timeInfo.tm_isdst == 1);
2713
2714 version (Posix)
2715 {
2716 assert(timeInfo.tm_gmtoff == -8 * 60 * 60);
2717 assert(to!string(timeInfo.tm_zone) == "PST");
2718 }
2719 }
2720
2721 {
2722 auto timeInfo = SysTime(DateTime(2010, 7, 4, 12, 15, 7), hnsecs(15)).toTM();
2723
2724 assert(timeInfo.tm_sec == 7);
2725 assert(timeInfo.tm_min == 15);
2726 assert(timeInfo.tm_hour == 12);
2727 assert(timeInfo.tm_mday == 4);
2728 assert(timeInfo.tm_mon == 6);
2729 assert(timeInfo.tm_year == 110);
2730 assert(timeInfo.tm_wday == 0);
2731 assert(timeInfo.tm_yday == 184);
2732
2733 version (Posix)
2734 assert(timeInfo.tm_isdst == 1);
2735 else version (Windows)
2736 assert(timeInfo.tm_isdst == 0 || timeInfo.tm_isdst == 1);
2737
2738 version (Posix)
2739 {
2740 assert(timeInfo.tm_gmtoff == -7 * 60 * 60);
2741 assert(to!string(timeInfo.tm_zone) == "PDT");
2742 }
2743 }
2744
2745 // This is more to verify that SysTime.init.toTM() doesn't segfault and
2746 // does something sane rather than that the value is anything
2747 // particularly useful.
2748 {
2749 auto timeInfo = SysTime.init.toTM();
2750
2751 assert(timeInfo.tm_sec == 0);
2752 assert(timeInfo.tm_min == 0);
2753 assert(timeInfo.tm_hour == 0);
2754 assert(timeInfo.tm_mday == 1);
2755 assert(timeInfo.tm_mon == 0);
2756 assert(timeInfo.tm_year == -1899);
2757 assert(timeInfo.tm_wday == 1);
2758 assert(timeInfo.tm_yday == 0);
2759 assert(timeInfo.tm_isdst == 0);
2760
2761 version (Posix)
2762 {
2763 assert(timeInfo.tm_gmtoff == 0);
2764 assert(to!string(timeInfo.tm_zone) == "SysTime.init's timezone");
2765 }
2766 }
2767
2768 static void testScope(scope ref SysTime st) @safe
2769 {
2770 auto result = st.toTM();
2771 }
2772 }
2773
2774
2775 /++
2776 Adds the given number of years or months to this $(LREF SysTime). A
2777 negative number will subtract.
2778
2779 Note that if day overflow is allowed, and the date with the adjusted
2780 year/month overflows the number of days in the new month, then the month
2781 will be incremented by one, and the day set to the number of days
2782 overflowed. (e.g. if the day were 31 and the new month were June, then
2783 the month would be incremented to July, and the new day would be 1). If
2784 day overflow is not allowed, then the day will be set to the last valid
2785 day in the month (e.g. June 31st would become June 30th).
2786
2787 Params:
2788 units = The type of units to add ("years" or "months").
2789 value = The number of months or years to add to this
2790 $(LREF SysTime).
2791 allowOverflow = Whether the days should be allowed to overflow,
2792 causing the month to increment.
2793 +/
2794 ref SysTime add(string units)(long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) @safe nothrow scope
2795 if (units == "years" || units == "months")
2796 {
2797 auto hnsecs = adjTime;
2798 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
2799
2800 if (hnsecs < 0)
2801 {
2802 hnsecs += convert!("hours", "hnsecs")(24);
2803 --days;
2804 }
2805
2806 auto date = Date(cast(int) days);
2807 date.add!units(value, allowOverflow);
2808 days = date.dayOfGregorianCal - 1;
2809
2810 if (days < 0)
2811 {
2812 hnsecs -= convert!("hours", "hnsecs")(24);
2813 ++days;
2814 }
2815
2816 immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
2817
2818 adjTime = newDaysHNSecs + hnsecs;
2819
2820 return this;
2821 }
2822
2823 @safe unittest
2824 {
2825 auto st1 = SysTime(DateTime(2010, 1, 1, 12, 30, 33));
2826 st1.add!"months"(11);
2827 assert(st1 == SysTime(DateTime(2010, 12, 1, 12, 30, 33)));
2828
2829 auto st2 = SysTime(DateTime(2010, 1, 1, 12, 30, 33));
2830 st2.add!"months"(-11);
2831 assert(st2 == SysTime(DateTime(2009, 2, 1, 12, 30, 33)));
2832
2833 auto st3 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
2834 st3.add!"years"(1);
2835 assert(st3 == SysTime(DateTime(2001, 3, 1, 12, 30, 33)));
2836
2837 auto st4 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
2838 st4.add!"years"(1, AllowDayOverflow.no);
2839 assert(st4 == SysTime(DateTime(2001, 2, 28, 12, 30, 33)));
2840 }
2841
2842 // Test add!"years"() with AllowDayOverflow.yes
2843 @safe unittest
2844 {
2845 import core.time;
2846 // Test A.D.
2847 {
2848 auto sysTime = SysTime(Date(1999, 7, 6));
2849 sysTime.add!"years"(7);
2850 assert(sysTime == SysTime(Date(2006, 7, 6)));
2851 sysTime.add!"years"(-9);
2852 assert(sysTime == SysTime(Date(1997, 7, 6)));
2853 }
2854
2855 {
2856 auto sysTime = SysTime(Date(1999, 2, 28));
2857 sysTime.add!"years"(1);
2858 assert(sysTime == SysTime(Date(2000, 2, 28)));
2859 }
2860
2861 {
2862 auto sysTime = SysTime(Date(2000, 2, 29));
2863 sysTime.add!"years"(-1);
2864 assert(sysTime == SysTime(Date(1999, 3, 1)));
2865 }
2866
2867 {
2868 auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 7, 3), msecs(234));
2869 sysTime.add!"years"(7);
2870 assert(sysTime == SysTime(DateTime(2006, 7, 6, 12, 7, 3), msecs(234)));
2871 sysTime.add!"years"(-9);
2872 assert(sysTime == SysTime(DateTime(1997, 7, 6, 12, 7, 3), msecs(234)));
2873 }
2874
2875 {
2876 auto sysTime = SysTime(DateTime(1999, 2, 28, 0, 7, 2), usecs(1207));
2877 sysTime.add!"years"(1);
2878 assert(sysTime == SysTime(DateTime(2000, 2, 28, 0, 7, 2), usecs(1207)));
2879 }
2880
2881 {
2882 auto sysTime = SysTime(DateTime(2000, 2, 29, 0, 7, 2), usecs(1207));
2883 sysTime.add!"years"(-1);
2884 assert(sysTime == SysTime(DateTime(1999, 3, 1, 0, 7, 2), usecs(1207)));
2885 }
2886
2887 // Test B.C.
2888 {
2889 auto sysTime = SysTime(Date(-1999, 7, 6));
2890 sysTime.add!"years"(-7);
2891 assert(sysTime == SysTime(Date(-2006, 7, 6)));
2892 sysTime.add!"years"(9);
2893 assert(sysTime == SysTime(Date(-1997, 7, 6)));
2894 }
2895
2896 {
2897 auto sysTime = SysTime(Date(-1999, 2, 28));
2898 sysTime.add!"years"(-1);
2899 assert(sysTime == SysTime(Date(-2000, 2, 28)));
2900 }
2901
2902 {
2903 auto sysTime = SysTime(Date(-2000, 2, 29));
2904 sysTime.add!"years"(1);
2905 assert(sysTime == SysTime(Date(-1999, 3, 1)));
2906 }
2907
2908 {
2909 auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 7, 3), msecs(234));
2910 sysTime.add!"years"(-7);
2911 assert(sysTime == SysTime(DateTime(-2006, 7, 6, 12, 7, 3), msecs(234)));
2912 sysTime.add!"years"(9);
2913 assert(sysTime == SysTime(DateTime(-1997, 7, 6, 12, 7, 3), msecs(234)));
2914 }
2915
2916 {
2917 auto sysTime = SysTime(DateTime(-1999, 2, 28, 3, 3, 3), hnsecs(3));
2918 sysTime.add!"years"(-1);
2919 assert(sysTime == SysTime(DateTime(-2000, 2, 28, 3, 3, 3), hnsecs(3)));
2920 }
2921
2922 {
2923 auto sysTime = SysTime(DateTime(-2000, 2, 29, 3, 3, 3), hnsecs(3));
2924 sysTime.add!"years"(1);
2925 assert(sysTime == SysTime(DateTime(-1999, 3, 1, 3, 3, 3), hnsecs(3)));
2926 }
2927
2928 // Test Both
2929 {
2930 auto sysTime = SysTime(Date(4, 7, 6));
2931 sysTime.add!"years"(-5);
2932 assert(sysTime == SysTime(Date(-1, 7, 6)));
2933 sysTime.add!"years"(5);
2934 assert(sysTime == SysTime(Date(4, 7, 6)));
2935 }
2936
2937 {
2938 auto sysTime = SysTime(Date(-4, 7, 6));
2939 sysTime.add!"years"(5);
2940 assert(sysTime == SysTime(Date(1, 7, 6)));
2941 sysTime.add!"years"(-5);
2942 assert(sysTime == SysTime(Date(-4, 7, 6)));
2943 }
2944
2945 {
2946 auto sysTime = SysTime(Date(4, 7, 6));
2947 sysTime.add!"years"(-8);
2948 assert(sysTime == SysTime(Date(-4, 7, 6)));
2949 sysTime.add!"years"(8);
2950 assert(sysTime == SysTime(Date(4, 7, 6)));
2951 }
2952
2953 {
2954 auto sysTime = SysTime(Date(-4, 7, 6));
2955 sysTime.add!"years"(8);
2956 assert(sysTime == SysTime(Date(4, 7, 6)));
2957 sysTime.add!"years"(-8);
2958 assert(sysTime == SysTime(Date(-4, 7, 6)));
2959 }
2960
2961 {
2962 auto sysTime = SysTime(Date(-4, 2, 29));
2963 sysTime.add!"years"(5);
2964 assert(sysTime == SysTime(Date(1, 3, 1)));
2965 }
2966
2967 {
2968 auto sysTime = SysTime(Date(4, 2, 29));
2969 sysTime.add!"years"(-5);
2970 assert(sysTime == SysTime(Date(-1, 3, 1)));
2971 }
2972
2973 {
2974 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
2975 sysTime.add!"years"(-1);
2976 assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0)));
2977 sysTime.add!"years"(1);
2978 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
2979 }
2980
2981 {
2982 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
2983 sysTime.add!"years"(-1);
2984 assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
2985 sysTime.add!"years"(1);
2986 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
2987 }
2988
2989 {
2990 auto sysTime = SysTime(DateTime(0, 1, 1, 0, 0, 0));
2991 sysTime.add!"years"(1);
2992 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
2993 sysTime.add!"years"(-1);
2994 assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0)));
2995 }
2996
2997 {
2998 auto sysTime = SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999));
2999 sysTime.add!"years"(1);
3000 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3001 sysTime.add!"years"(-1);
3002 assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3003 }
3004
3005 {
3006 auto sysTime = SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329));
3007 sysTime.add!"years"(-5);
3008 assert(sysTime == SysTime(DateTime(-1, 7, 6, 14, 7, 1), usecs(54329)));
3009 sysTime.add!"years"(5);
3010 assert(sysTime == SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329)));
3011 }
3012
3013 {
3014 auto sysTime = SysTime(DateTime(-4, 7, 6, 14, 7, 1), usecs(54329));
3015 sysTime.add!"years"(5);
3016 assert(sysTime == SysTime(DateTime(1, 7, 6, 14, 7, 1), usecs(54329)));
3017 sysTime.add!"years"(-5);
3018 assert(sysTime == SysTime(DateTime(-4, 7, 6, 14, 7, 1), usecs(54329)));
3019 }
3020
3021 {
3022 auto sysTime = SysTime(DateTime(-4, 2, 29, 5, 5, 5), msecs(555));
3023 sysTime.add!"years"(5);
3024 assert(sysTime == SysTime(DateTime(1, 3, 1, 5, 5, 5), msecs(555)));
3025 }
3026
3027 {
3028 auto sysTime = SysTime(DateTime(4, 2, 29, 5, 5, 5), msecs(555));
3029 sysTime.add!"years"(-5);
3030 assert(sysTime == SysTime(DateTime(-1, 3, 1, 5, 5, 5), msecs(555)));
3031 }
3032
3033 {
3034 auto sysTime = SysTime(DateTime(4, 2, 29, 5, 5, 5), msecs(555));
3035 sysTime.add!"years"(-5).add!"years"(7);
3036 assert(sysTime == SysTime(DateTime(6, 3, 1, 5, 5, 5), msecs(555)));
3037 }
3038
3039 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
3040 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
3041 static assert(!__traits(compiles, cst.add!"years"(4)));
3042 static assert(!__traits(compiles, ist.add!"years"(4)));
3043
3044 static void testScope(scope ref SysTime st) @safe
3045 {
3046 auto result = st.add!"years"(42);
3047 }
3048 }
3049
3050 // Test add!"years"() with AllowDayOverflow.no
3051 @safe unittest
3052 {
3053 import core.time;
3054 // Test A.D.
3055 {
3056 auto sysTime = SysTime(Date(1999, 7, 6));
3057 sysTime.add!"years"(7, AllowDayOverflow.no);
3058 assert(sysTime == SysTime(Date(2006, 7, 6)));
3059 sysTime.add!"years"(-9, AllowDayOverflow.no);
3060 assert(sysTime == SysTime(Date(1997, 7, 6)));
3061 }
3062
3063 {
3064 auto sysTime = SysTime(Date(1999, 2, 28));
3065 sysTime.add!"years"(1, AllowDayOverflow.no);
3066 assert(sysTime == SysTime(Date(2000, 2, 28)));
3067 }
3068
3069 {
3070 auto sysTime = SysTime(Date(2000, 2, 29));
3071 sysTime.add!"years"(-1, AllowDayOverflow.no);
3072 assert(sysTime == SysTime(Date(1999, 2, 28)));
3073 }
3074
3075 {
3076 auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 7, 3), msecs(234));
3077 sysTime.add!"years"(7, AllowDayOverflow.no);
3078 assert(sysTime == SysTime(DateTime(2006, 7, 6, 12, 7, 3), msecs(234)));
3079 sysTime.add!"years"(-9, AllowDayOverflow.no);
3080 assert(sysTime == SysTime(DateTime(1997, 7, 6, 12, 7, 3), msecs(234)));
3081 }
3082
3083 {
3084 auto sysTime = SysTime(DateTime(1999, 2, 28, 0, 7, 2), usecs(1207));
3085 sysTime.add!"years"(1, AllowDayOverflow.no);
3086 assert(sysTime == SysTime(DateTime(2000, 2, 28, 0, 7, 2), usecs(1207)));
3087 }
3088
3089 {
3090 auto sysTime = SysTime(DateTime(2000, 2, 29, 0, 7, 2), usecs(1207));
3091 sysTime.add!"years"(-1, AllowDayOverflow.no);
3092 assert(sysTime == SysTime(DateTime(1999, 2, 28, 0, 7, 2), usecs(1207)));
3093 }
3094
3095 // Test B.C.
3096 {
3097 auto sysTime = SysTime(Date(-1999, 7, 6));
3098 sysTime.add!"years"(-7, AllowDayOverflow.no);
3099 assert(sysTime == SysTime(Date(-2006, 7, 6)));
3100 sysTime.add!"years"(9, AllowDayOverflow.no);
3101 assert(sysTime == SysTime(Date(-1997, 7, 6)));
3102 }
3103
3104 {
3105 auto sysTime = SysTime(Date(-1999, 2, 28));
3106 sysTime.add!"years"(-1, AllowDayOverflow.no);
3107 assert(sysTime == SysTime(Date(-2000, 2, 28)));
3108 }
3109
3110 {
3111 auto sysTime = SysTime(Date(-2000, 2, 29));
3112 sysTime.add!"years"(1, AllowDayOverflow.no);
3113 assert(sysTime == SysTime(Date(-1999, 2, 28)));
3114 }
3115
3116 {
3117 auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 7, 3), msecs(234));
3118 sysTime.add!"years"(-7, AllowDayOverflow.no);
3119 assert(sysTime == SysTime(DateTime(-2006, 7, 6, 12, 7, 3), msecs(234)));
3120 sysTime.add!"years"(9, AllowDayOverflow.no);
3121 assert(sysTime == SysTime(DateTime(-1997, 7, 6, 12, 7, 3), msecs(234)));
3122 }
3123
3124 {
3125 auto sysTime = SysTime(DateTime(-1999, 2, 28, 3, 3, 3), hnsecs(3));
3126 sysTime.add!"years"(-1, AllowDayOverflow.no);
3127 assert(sysTime == SysTime(DateTime(-2000, 2, 28, 3, 3, 3), hnsecs(3)));
3128 }
3129
3130 {
3131 auto sysTime = SysTime(DateTime(-2000, 2, 29, 3, 3, 3), hnsecs(3));
3132 sysTime.add!"years"(1, AllowDayOverflow.no);
3133 assert(sysTime == SysTime(DateTime(-1999, 2, 28, 3, 3, 3), hnsecs(3)));
3134 }
3135
3136 // Test Both
3137 {
3138 auto sysTime = SysTime(Date(4, 7, 6));
3139 sysTime.add!"years"(-5, AllowDayOverflow.no);
3140 assert(sysTime == SysTime(Date(-1, 7, 6)));
3141 sysTime.add!"years"(5, AllowDayOverflow.no);
3142 assert(sysTime == SysTime(Date(4, 7, 6)));
3143 }
3144
3145 {
3146 auto sysTime = SysTime(Date(-4, 7, 6));
3147 sysTime.add!"years"(5, AllowDayOverflow.no);
3148 assert(sysTime == SysTime(Date(1, 7, 6)));
3149 sysTime.add!"years"(-5, AllowDayOverflow.no);
3150 assert(sysTime == SysTime(Date(-4, 7, 6)));
3151 }
3152
3153 {
3154 auto sysTime = SysTime(Date(4, 7, 6));
3155 sysTime.add!"years"(-8, AllowDayOverflow.no);
3156 assert(sysTime == SysTime(Date(-4, 7, 6)));
3157 sysTime.add!"years"(8, AllowDayOverflow.no);
3158 assert(sysTime == SysTime(Date(4, 7, 6)));
3159 }
3160
3161 {
3162 auto sysTime = SysTime(Date(-4, 7, 6));
3163 sysTime.add!"years"(8, AllowDayOverflow.no);
3164 assert(sysTime == SysTime(Date(4, 7, 6)));
3165 sysTime.add!"years"(-8, AllowDayOverflow.no);
3166 assert(sysTime == SysTime(Date(-4, 7, 6)));
3167 }
3168
3169 {
3170 auto sysTime = SysTime(Date(-4, 2, 29));
3171 sysTime.add!"years"(5, AllowDayOverflow.no);
3172 assert(sysTime == SysTime(Date(1, 2, 28)));
3173 }
3174
3175 {
3176 auto sysTime = SysTime(Date(4, 2, 29));
3177 sysTime.add!"years"(-5, AllowDayOverflow.no);
3178 assert(sysTime == SysTime(Date(-1, 2, 28)));
3179 }
3180
3181 {
3182 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
3183 sysTime.add!"years"(-1, AllowDayOverflow.no);
3184 assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0)));
3185 sysTime.add!"years"(1, AllowDayOverflow.no);
3186 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
3187 }
3188
3189 {
3190 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
3191 sysTime.add!"years"(-1, AllowDayOverflow.no);
3192 assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3193 sysTime.add!"years"(1, AllowDayOverflow.no);
3194 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3195 }
3196
3197 {
3198 auto sysTime = SysTime(DateTime(0, 1, 1, 0, 0, 0));
3199 sysTime.add!"years"(1, AllowDayOverflow.no);
3200 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
3201 sysTime.add!"years"(-1, AllowDayOverflow.no);
3202 assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0)));
3203 }
3204
3205 {
3206 auto sysTime = SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999));
3207 sysTime.add!"years"(1, AllowDayOverflow.no);
3208 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3209 sysTime.add!"years"(-1, AllowDayOverflow.no);
3210 assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3211 }
3212
3213 {
3214 auto sysTime = SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329));
3215 sysTime.add!"years"(-5);
3216 assert(sysTime == SysTime(DateTime(-1, 7, 6, 14, 7, 1), usecs(54329)));
3217 sysTime.add!"years"(5);
3218 assert(sysTime == SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329)));
3219 }
3220
3221 {
3222 auto sysTime = SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329));
3223 sysTime.add!"years"(-5, AllowDayOverflow.no);
3224 assert(sysTime == SysTime(DateTime(-1, 7, 6, 14, 7, 1), usecs(54329)));
3225 sysTime.add!"years"(5, AllowDayOverflow.no);
3226 assert(sysTime == SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329)));
3227 }
3228
3229 {
3230 auto sysTime = SysTime(DateTime(-4, 7, 6, 14, 7, 1), usecs(54329));
3231 sysTime.add!"years"(5, AllowDayOverflow.no);
3232 assert(sysTime == SysTime(DateTime(1, 7, 6, 14, 7, 1), usecs(54329)));
3233 sysTime.add!"years"(-5, AllowDayOverflow.no);
3234 assert(sysTime == SysTime(DateTime(-4, 7, 6, 14, 7, 1), usecs(54329)));
3235 }
3236
3237 {
3238 auto sysTime = SysTime(DateTime(-4, 2, 29, 5, 5, 5), msecs(555));
3239 sysTime.add!"years"(5, AllowDayOverflow.no);
3240 assert(sysTime == SysTime(DateTime(1, 2, 28, 5, 5, 5), msecs(555)));
3241 }
3242
3243 {
3244 auto sysTime = SysTime(DateTime(4, 2, 29, 5, 5, 5), msecs(555));
3245 sysTime.add!"years"(-5, AllowDayOverflow.no);
3246 assert(sysTime == SysTime(DateTime(-1, 2, 28, 5, 5, 5), msecs(555)));
3247 }
3248
3249 {
3250 auto sysTime = SysTime(DateTime(4, 2, 29, 5, 5, 5), msecs(555));
3251 sysTime.add!"years"(-5, AllowDayOverflow.no).add!"years"(7, AllowDayOverflow.no);
3252 assert(sysTime == SysTime(DateTime(6, 2, 28, 5, 5, 5), msecs(555)));
3253 }
3254 }
3255
3256 // Test add!"months"() with AllowDayOverflow.yes
3257 @safe unittest
3258 {
3259 import core.time;
3260 // Test A.D.
3261 {
3262 auto sysTime = SysTime(Date(1999, 7, 6));
3263 sysTime.add!"months"(3);
3264 assert(sysTime == SysTime(Date(1999, 10, 6)));
3265 sysTime.add!"months"(-4);
3266 assert(sysTime == SysTime(Date(1999, 6, 6)));
3267 }
3268
3269 {
3270 auto sysTime = SysTime(Date(1999, 7, 6));
3271 sysTime.add!"months"(6);
3272 assert(sysTime == SysTime(Date(2000, 1, 6)));
3273 sysTime.add!"months"(-6);
3274 assert(sysTime == SysTime(Date(1999, 7, 6)));
3275 }
3276
3277 {
3278 auto sysTime = SysTime(Date(1999, 7, 6));
3279 sysTime.add!"months"(27);
3280 assert(sysTime == SysTime(Date(2001, 10, 6)));
3281 sysTime.add!"months"(-28);
3282 assert(sysTime == SysTime(Date(1999, 6, 6)));
3283 }
3284
3285 {
3286 auto sysTime = SysTime(Date(1999, 5, 31));
3287 sysTime.add!"months"(1);
3288 assert(sysTime == SysTime(Date(1999, 7, 1)));
3289 }
3290
3291 {
3292 auto sysTime = SysTime(Date(1999, 5, 31));
3293 sysTime.add!"months"(-1);
3294 assert(sysTime == SysTime(Date(1999, 5, 1)));
3295 }
3296
3297 {
3298 auto sysTime = SysTime(Date(1999, 2, 28));
3299 sysTime.add!"months"(12);
3300 assert(sysTime == SysTime(Date(2000, 2, 28)));
3301 }
3302
3303 {
3304 auto sysTime = SysTime(Date(2000, 2, 29));
3305 sysTime.add!"months"(12);
3306 assert(sysTime == SysTime(Date(2001, 3, 1)));
3307 }
3308
3309 {
3310 auto sysTime = SysTime(Date(1999, 7, 31));
3311 sysTime.add!"months"(1);
3312 assert(sysTime == SysTime(Date(1999, 8, 31)));
3313 sysTime.add!"months"(1);
3314 assert(sysTime == SysTime(Date(1999, 10, 1)));
3315 }
3316
3317 {
3318 auto sysTime = SysTime(Date(1998, 8, 31));
3319 sysTime.add!"months"(13);
3320 assert(sysTime == SysTime(Date(1999, 10, 1)));
3321 sysTime.add!"months"(-13);
3322 assert(sysTime == SysTime(Date(1998, 9, 1)));
3323 }
3324
3325 {
3326 auto sysTime = SysTime(Date(1997, 12, 31));
3327 sysTime.add!"months"(13);
3328 assert(sysTime == SysTime(Date(1999, 1, 31)));
3329 sysTime.add!"months"(-13);
3330 assert(sysTime == SysTime(Date(1997, 12, 31)));
3331 }
3332
3333 {
3334 auto sysTime = SysTime(Date(1997, 12, 31));
3335 sysTime.add!"months"(14);
3336 assert(sysTime == SysTime(Date(1999, 3, 3)));
3337 sysTime.add!"months"(-14);
3338 assert(sysTime == SysTime(Date(1998, 1, 3)));
3339 }
3340
3341 {
3342 auto sysTime = SysTime(Date(1998, 12, 31));
3343 sysTime.add!"months"(14);
3344 assert(sysTime == SysTime(Date(2000, 3, 2)));
3345 sysTime.add!"months"(-14);
3346 assert(sysTime == SysTime(Date(1999, 1, 2)));
3347 }
3348
3349 {
3350 auto sysTime = SysTime(Date(1999, 12, 31));
3351 sysTime.add!"months"(14);
3352 assert(sysTime == SysTime(Date(2001, 3, 3)));
3353 sysTime.add!"months"(-14);
3354 assert(sysTime == SysTime(Date(2000, 1, 3)));
3355 }
3356
3357 {
3358 auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), usecs(5007));
3359 sysTime.add!"months"(3);
3360 assert(sysTime == SysTime(DateTime(1999, 10, 6, 12, 2, 7), usecs(5007)));
3361 sysTime.add!"months"(-4);
3362 assert(sysTime == SysTime(DateTime(1999, 6, 6, 12, 2, 7), usecs(5007)));
3363 }
3364
3365 {
3366 auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), hnsecs(422202));
3367 sysTime.add!"months"(14);
3368 assert(sysTime == SysTime(DateTime(2000, 3, 2, 7, 7, 7), hnsecs(422202)));
3369 sysTime.add!"months"(-14);
3370 assert(sysTime == SysTime(DateTime(1999, 1, 2, 7, 7, 7), hnsecs(422202)));
3371 }
3372
3373 {
3374 auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), hnsecs(422202));
3375 sysTime.add!"months"(14);
3376 assert(sysTime == SysTime(DateTime(2001, 3, 3, 7, 7, 7), hnsecs(422202)));
3377 sysTime.add!"months"(-14);
3378 assert(sysTime == SysTime(DateTime(2000, 1, 3, 7, 7, 7), hnsecs(422202)));
3379 }
3380
3381 // Test B.C.
3382 {
3383 auto sysTime = SysTime(Date(-1999, 7, 6));
3384 sysTime.add!"months"(3);
3385 assert(sysTime == SysTime(Date(-1999, 10, 6)));
3386 sysTime.add!"months"(-4);
3387 assert(sysTime == SysTime(Date(-1999, 6, 6)));
3388 }
3389
3390 {
3391 auto sysTime = SysTime(Date(-1999, 7, 6));
3392 sysTime.add!"months"(6);
3393 assert(sysTime == SysTime(Date(-1998, 1, 6)));
3394 sysTime.add!"months"(-6);
3395 assert(sysTime == SysTime(Date(-1999, 7, 6)));
3396 }
3397
3398 {
3399 auto sysTime = SysTime(Date(-1999, 7, 6));
3400 sysTime.add!"months"(-27);
3401 assert(sysTime == SysTime(Date(-2001, 4, 6)));
3402 sysTime.add!"months"(28);
3403 assert(sysTime == SysTime(Date(-1999, 8, 6)));
3404 }
3405
3406 {
3407 auto sysTime = SysTime(Date(-1999, 5, 31));
3408 sysTime.add!"months"(1);
3409 assert(sysTime == SysTime(Date(-1999, 7, 1)));
3410 }
3411
3412 {
3413 auto sysTime = SysTime(Date(-1999, 5, 31));
3414 sysTime.add!"months"(-1);
3415 assert(sysTime == SysTime(Date(-1999, 5, 1)));
3416 }
3417
3418 {
3419 auto sysTime = SysTime(Date(-1999, 2, 28));
3420 sysTime.add!"months"(-12);
3421 assert(sysTime == SysTime(Date(-2000, 2, 28)));
3422 }
3423
3424 {
3425 auto sysTime = SysTime(Date(-2000, 2, 29));
3426 sysTime.add!"months"(-12);
3427 assert(sysTime == SysTime(Date(-2001, 3, 1)));
3428 }
3429
3430 {
3431 auto sysTime = SysTime(Date(-1999, 7, 31));
3432 sysTime.add!"months"(1);
3433 assert(sysTime == SysTime(Date(-1999, 8, 31)));
3434 sysTime.add!"months"(1);
3435 assert(sysTime == SysTime(Date(-1999, 10, 1)));
3436 }
3437
3438 {
3439 auto sysTime = SysTime(Date(-1998, 8, 31));
3440 sysTime.add!"months"(13);
3441 assert(sysTime == SysTime(Date(-1997, 10, 1)));
3442 sysTime.add!"months"(-13);
3443 assert(sysTime == SysTime(Date(-1998, 9, 1)));
3444 }
3445
3446 {
3447 auto sysTime = SysTime(Date(-1997, 12, 31));
3448 sysTime.add!"months"(13);
3449 assert(sysTime == SysTime(Date(-1995, 1, 31)));
3450 sysTime.add!"months"(-13);
3451 assert(sysTime == SysTime(Date(-1997, 12, 31)));
3452 }
3453
3454 {
3455 auto sysTime = SysTime(Date(-1997, 12, 31));
3456 sysTime.add!"months"(14);
3457 assert(sysTime == SysTime(Date(-1995, 3, 3)));
3458 sysTime.add!"months"(-14);
3459 assert(sysTime == SysTime(Date(-1996, 1, 3)));
3460 }
3461
3462 {
3463 auto sysTime = SysTime(Date(-2002, 12, 31));
3464 sysTime.add!"months"(14);
3465 assert(sysTime == SysTime(Date(-2000, 3, 2)));
3466 sysTime.add!"months"(-14);
3467 assert(sysTime == SysTime(Date(-2001, 1, 2)));
3468 }
3469
3470 {
3471 auto sysTime = SysTime(Date(-2001, 12, 31));
3472 sysTime.add!"months"(14);
3473 assert(sysTime == SysTime(Date(-1999, 3, 3)));
3474 sysTime.add!"months"(-14);
3475 assert(sysTime == SysTime(Date(-2000, 1, 3)));
3476 }
3477
3478 {
3479 auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), usecs(5007));
3480 sysTime.add!"months"(3);
3481 assert(sysTime == SysTime(DateTime(-1999, 10, 6, 12, 2, 7), usecs(5007)));
3482 sysTime.add!"months"(-4);
3483 assert(sysTime == SysTime(DateTime(-1999, 6, 6, 12, 2, 7), usecs(5007)));
3484 }
3485
3486 {
3487 auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), hnsecs(422202));
3488 sysTime.add!"months"(14);
3489 assert(sysTime == SysTime(DateTime(-2000, 3, 2, 7, 7, 7), hnsecs(422202)));
3490 sysTime.add!"months"(-14);
3491 assert(sysTime == SysTime(DateTime(-2001, 1, 2, 7, 7, 7), hnsecs(422202)));
3492 }
3493
3494 {
3495 auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), hnsecs(422202));
3496 sysTime.add!"months"(14);
3497 assert(sysTime == SysTime(DateTime(-1999, 3, 3, 7, 7, 7), hnsecs(422202)));
3498 sysTime.add!"months"(-14);
3499 assert(sysTime == SysTime(DateTime(-2000, 1, 3, 7, 7, 7), hnsecs(422202)));
3500 }
3501
3502 // Test Both
3503 {
3504 auto sysTime = SysTime(Date(1, 1, 1));
3505 sysTime.add!"months"(-1);
3506 assert(sysTime == SysTime(Date(0, 12, 1)));
3507 sysTime.add!"months"(1);
3508 assert(sysTime == SysTime(Date(1, 1, 1)));
3509 }
3510
3511 {
3512 auto sysTime = SysTime(Date(4, 1, 1));
3513 sysTime.add!"months"(-48);
3514 assert(sysTime == SysTime(Date(0, 1, 1)));
3515 sysTime.add!"months"(48);
3516 assert(sysTime == SysTime(Date(4, 1, 1)));
3517 }
3518
3519 {
3520 auto sysTime = SysTime(Date(4, 3, 31));
3521 sysTime.add!"months"(-49);
3522 assert(sysTime == SysTime(Date(0, 3, 2)));
3523 sysTime.add!"months"(49);
3524 assert(sysTime == SysTime(Date(4, 4, 2)));
3525 }
3526
3527 {
3528 auto sysTime = SysTime(Date(4, 3, 31));
3529 sysTime.add!"months"(-85);
3530 assert(sysTime == SysTime(Date(-3, 3, 3)));
3531 sysTime.add!"months"(85);
3532 assert(sysTime == SysTime(Date(4, 4, 3)));
3533 }
3534
3535 {
3536 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
3537 sysTime.add!"months"(-1);
3538 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
3539 sysTime.add!"months"(1);
3540 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
3541 }
3542
3543 {
3544 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
3545 sysTime.add!"months"(-1);
3546 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
3547 sysTime.add!"months"(1);
3548 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3549 }
3550
3551 {
3552 auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0));
3553 sysTime.add!"months"(1);
3554 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
3555 sysTime.add!"months"(-1);
3556 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
3557 }
3558
3559 {
3560 auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999));
3561 sysTime.add!"months"(1);
3562 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3563 sysTime.add!"months"(-1);
3564 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
3565 }
3566
3567 {
3568 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17));
3569 sysTime.add!"months"(-1);
3570 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 7, 9), hnsecs(17)));
3571 sysTime.add!"months"(1);
3572 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17)));
3573 }
3574
3575 {
3576 auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), msecs(9));
3577 sysTime.add!"months"(-85);
3578 assert(sysTime == SysTime(DateTime(-3, 3, 3, 12, 11, 10), msecs(9)));
3579 sysTime.add!"months"(85);
3580 assert(sysTime == SysTime(DateTime(4, 4, 3, 12, 11, 10), msecs(9)));
3581 }
3582
3583 {
3584 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
3585 sysTime.add!"months"(85);
3586 assert(sysTime == SysTime(DateTime(4, 5, 1, 12, 11, 10), msecs(9)));
3587 sysTime.add!"months"(-85);
3588 assert(sysTime == SysTime(DateTime(-3, 4, 1, 12, 11, 10), msecs(9)));
3589 }
3590
3591 {
3592 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
3593 sysTime.add!"months"(85).add!"months"(-83);
3594 assert(sysTime == SysTime(DateTime(-3, 6, 1, 12, 11, 10), msecs(9)));
3595 }
3596
3597 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
3598 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
3599 static assert(!__traits(compiles, cst.add!"months"(4)));
3600 static assert(!__traits(compiles, ist.add!"months"(4)));
3601
3602 static void testScope(scope ref SysTime st) @safe
3603 {
3604 auto result = st.add!"months"(42);
3605 }
3606 }
3607
3608 // Test add!"months"() with AllowDayOverflow.no
3609 @safe unittest
3610 {
3611 import core.time;
3612 // Test A.D.
3613 {
3614 auto sysTime = SysTime(Date(1999, 7, 6));
3615 sysTime.add!"months"(3, AllowDayOverflow.no);
3616 assert(sysTime == SysTime(Date(1999, 10, 6)));
3617 sysTime.add!"months"(-4, AllowDayOverflow.no);
3618 assert(sysTime == SysTime(Date(1999, 6, 6)));
3619 }
3620
3621 {
3622 auto sysTime = SysTime(Date(1999, 7, 6));
3623 sysTime.add!"months"(6, AllowDayOverflow.no);
3624 assert(sysTime == SysTime(Date(2000, 1, 6)));
3625 sysTime.add!"months"(-6, AllowDayOverflow.no);
3626 assert(sysTime == SysTime(Date(1999, 7, 6)));
3627 }
3628
3629 {
3630 auto sysTime = SysTime(Date(1999, 7, 6));
3631 sysTime.add!"months"(27, AllowDayOverflow.no);
3632 assert(sysTime == SysTime(Date(2001, 10, 6)));
3633 sysTime.add!"months"(-28, AllowDayOverflow.no);
3634 assert(sysTime == SysTime(Date(1999, 6, 6)));
3635 }
3636
3637 {
3638 auto sysTime = SysTime(Date(1999, 5, 31));
3639 sysTime.add!"months"(1, AllowDayOverflow.no);
3640 assert(sysTime == SysTime(Date(1999, 6, 30)));
3641 }
3642
3643 {
3644 auto sysTime = SysTime(Date(1999, 5, 31));
3645 sysTime.add!"months"(-1, AllowDayOverflow.no);
3646 assert(sysTime == SysTime(Date(1999, 4, 30)));
3647 }
3648
3649 {
3650 auto sysTime = SysTime(Date(1999, 2, 28));
3651 sysTime.add!"months"(12, AllowDayOverflow.no);
3652 assert(sysTime == SysTime(Date(2000, 2, 28)));
3653 }
3654
3655 {
3656 auto sysTime = SysTime(Date(2000, 2, 29));
3657 sysTime.add!"months"(12, AllowDayOverflow.no);
3658 assert(sysTime == SysTime(Date(2001, 2, 28)));
3659 }
3660
3661 {
3662 auto sysTime = SysTime(Date(1999, 7, 31));
3663 sysTime.add!"months"(1, AllowDayOverflow.no);
3664 assert(sysTime == SysTime(Date(1999, 8, 31)));
3665 sysTime.add!"months"(1, AllowDayOverflow.no);
3666 assert(sysTime == SysTime(Date(1999, 9, 30)));
3667 }
3668
3669 {
3670 auto sysTime = SysTime(Date(1998, 8, 31));
3671 sysTime.add!"months"(13, AllowDayOverflow.no);
3672 assert(sysTime == SysTime(Date(1999, 9, 30)));
3673 sysTime.add!"months"(-13, AllowDayOverflow.no);
3674 assert(sysTime == SysTime(Date(1998, 8, 30)));
3675 }
3676
3677 {
3678 auto sysTime = SysTime(Date(1997, 12, 31));
3679 sysTime.add!"months"(13, AllowDayOverflow.no);
3680 assert(sysTime == SysTime(Date(1999, 1, 31)));
3681 sysTime.add!"months"(-13, AllowDayOverflow.no);
3682 assert(sysTime == SysTime(Date(1997, 12, 31)));
3683 }
3684
3685 {
3686 auto sysTime = SysTime(Date(1997, 12, 31));
3687 sysTime.add!"months"(14, AllowDayOverflow.no);
3688 assert(sysTime == SysTime(Date(1999, 2, 28)));
3689 sysTime.add!"months"(-14, AllowDayOverflow.no);
3690 assert(sysTime == SysTime(Date(1997, 12, 28)));
3691 }
3692
3693 {
3694 auto sysTime = SysTime(Date(1998, 12, 31));
3695 sysTime.add!"months"(14, AllowDayOverflow.no);
3696 assert(sysTime == SysTime(Date(2000, 2, 29)));
3697 sysTime.add!"months"(-14, AllowDayOverflow.no);
3698 assert(sysTime == SysTime(Date(1998, 12, 29)));
3699 }
3700
3701 {
3702 auto sysTime = SysTime(Date(1999, 12, 31));
3703 sysTime.add!"months"(14, AllowDayOverflow.no);
3704 assert(sysTime == SysTime(Date(2001, 2, 28)));
3705 sysTime.add!"months"(-14, AllowDayOverflow.no);
3706 assert(sysTime == SysTime(Date(1999, 12, 28)));
3707 }
3708
3709 {
3710 auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), usecs(5007));
3711 sysTime.add!"months"(3, AllowDayOverflow.no);
3712 assert(sysTime == SysTime(DateTime(1999, 10, 6, 12, 2, 7), usecs(5007)));
3713 sysTime.add!"months"(-4, AllowDayOverflow.no);
3714 assert(sysTime == SysTime(DateTime(1999, 6, 6, 12, 2, 7), usecs(5007)));
3715 }
3716
3717 {
3718 auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), hnsecs(422202));
3719 sysTime.add!"months"(14, AllowDayOverflow.no);
3720 assert(sysTime == SysTime(DateTime(2000, 2, 29, 7, 7, 7), hnsecs(422202)));
3721 sysTime.add!"months"(-14, AllowDayOverflow.no);
3722 assert(sysTime == SysTime(DateTime(1998, 12, 29, 7, 7, 7), hnsecs(422202)));
3723 }
3724
3725 {
3726 auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), hnsecs(422202));
3727 sysTime.add!"months"(14, AllowDayOverflow.no);
3728 assert(sysTime == SysTime(DateTime(2001, 2, 28, 7, 7, 7), hnsecs(422202)));
3729 sysTime.add!"months"(-14, AllowDayOverflow.no);
3730 assert(sysTime == SysTime(DateTime(1999, 12, 28, 7, 7, 7), hnsecs(422202)));
3731 }
3732
3733 // Test B.C.
3734 {
3735 auto sysTime = SysTime(Date(-1999, 7, 6));
3736 sysTime.add!"months"(3, AllowDayOverflow.no);
3737 assert(sysTime == SysTime(Date(-1999, 10, 6)));
3738 sysTime.add!"months"(-4, AllowDayOverflow.no);
3739 assert(sysTime == SysTime(Date(-1999, 6, 6)));
3740 }
3741
3742 {
3743 auto sysTime = SysTime(Date(-1999, 7, 6));
3744 sysTime.add!"months"(6, AllowDayOverflow.no);
3745 assert(sysTime == SysTime(Date(-1998, 1, 6)));
3746 sysTime.add!"months"(-6, AllowDayOverflow.no);
3747 assert(sysTime == SysTime(Date(-1999, 7, 6)));
3748 }
3749
3750 {
3751 auto sysTime = SysTime(Date(-1999, 7, 6));
3752 sysTime.add!"months"(-27, AllowDayOverflow.no);
3753 assert(sysTime == SysTime(Date(-2001, 4, 6)));
3754 sysTime.add!"months"(28, AllowDayOverflow.no);
3755 assert(sysTime == SysTime(Date(-1999, 8, 6)));
3756 }
3757
3758 {
3759 auto sysTime = SysTime(Date(-1999, 5, 31));
3760 sysTime.add!"months"(1, AllowDayOverflow.no);
3761 assert(sysTime == SysTime(Date(-1999, 6, 30)));
3762 }
3763
3764 {
3765 auto sysTime = SysTime(Date(-1999, 5, 31));
3766 sysTime.add!"months"(-1, AllowDayOverflow.no);
3767 assert(sysTime == SysTime(Date(-1999, 4, 30)));
3768 }
3769
3770 {
3771 auto sysTime = SysTime(Date(-1999, 2, 28));
3772 sysTime.add!"months"(-12, AllowDayOverflow.no);
3773 assert(sysTime == SysTime(Date(-2000, 2, 28)));
3774 }
3775
3776 {
3777 auto sysTime = SysTime(Date(-2000, 2, 29));
3778 sysTime.add!"months"(-12, AllowDayOverflow.no);
3779 assert(sysTime == SysTime(Date(-2001, 2, 28)));
3780 }
3781
3782 {
3783 auto sysTime = SysTime(Date(-1999, 7, 31));
3784 sysTime.add!"months"(1, AllowDayOverflow.no);
3785 assert(sysTime == SysTime(Date(-1999, 8, 31)));
3786 sysTime.add!"months"(1, AllowDayOverflow.no);
3787 assert(sysTime == SysTime(Date(-1999, 9, 30)));
3788 }
3789
3790 {
3791 auto sysTime = SysTime(Date(-1998, 8, 31));
3792 sysTime.add!"months"(13, AllowDayOverflow.no);
3793 assert(sysTime == SysTime(Date(-1997, 9, 30)));
3794 sysTime.add!"months"(-13, AllowDayOverflow.no);
3795 assert(sysTime == SysTime(Date(-1998, 8, 30)));
3796 }
3797
3798 {
3799 auto sysTime = SysTime(Date(-1997, 12, 31));
3800 sysTime.add!"months"(13, AllowDayOverflow.no);
3801 assert(sysTime == SysTime(Date(-1995, 1, 31)));
3802 sysTime.add!"months"(-13, AllowDayOverflow.no);
3803 assert(sysTime == SysTime(Date(-1997, 12, 31)));
3804 }
3805
3806 {
3807 auto sysTime = SysTime(Date(-1997, 12, 31));
3808 sysTime.add!"months"(14, AllowDayOverflow.no);
3809 assert(sysTime == SysTime(Date(-1995, 2, 28)));
3810 sysTime.add!"months"(-14, AllowDayOverflow.no);
3811 assert(sysTime == SysTime(Date(-1997, 12, 28)));
3812 }
3813
3814 {
3815 auto sysTime = SysTime(Date(-2002, 12, 31));
3816 sysTime.add!"months"(14, AllowDayOverflow.no);
3817 assert(sysTime == SysTime(Date(-2000, 2, 29)));
3818 sysTime.add!"months"(-14, AllowDayOverflow.no);
3819 assert(sysTime == SysTime(Date(-2002, 12, 29)));
3820 }
3821
3822 {
3823 auto sysTime = SysTime(Date(-2001, 12, 31));
3824 sysTime.add!"months"(14, AllowDayOverflow.no);
3825 assert(sysTime == SysTime(Date(-1999, 2, 28)));
3826 sysTime.add!"months"(-14, AllowDayOverflow.no);
3827 assert(sysTime == SysTime(Date(-2001, 12, 28)));
3828 }
3829
3830 {
3831 auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), usecs(5007));
3832 sysTime.add!"months"(3, AllowDayOverflow.no);
3833 assert(sysTime == SysTime(DateTime(-1999, 10, 6, 12, 2, 7), usecs(5007)));
3834 sysTime.add!"months"(-4, AllowDayOverflow.no);
3835 assert(sysTime == SysTime(DateTime(-1999, 6, 6, 12, 2, 7), usecs(5007)));
3836 }
3837
3838 {
3839 auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), hnsecs(422202));
3840 sysTime.add!"months"(14, AllowDayOverflow.no);
3841 assert(sysTime == SysTime(DateTime(-2000, 2, 29, 7, 7, 7), hnsecs(422202)));
3842 sysTime.add!"months"(-14, AllowDayOverflow.no);
3843 assert(sysTime == SysTime(DateTime(-2002, 12, 29, 7, 7, 7), hnsecs(422202)));
3844 }
3845
3846 {
3847 auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), hnsecs(422202));
3848 sysTime.add!"months"(14, AllowDayOverflow.no);
3849 assert(sysTime == SysTime(DateTime(-1999, 2, 28, 7, 7, 7), hnsecs(422202)));
3850 sysTime.add!"months"(-14, AllowDayOverflow.no);
3851 assert(sysTime == SysTime(DateTime(-2001, 12, 28, 7, 7, 7), hnsecs(422202)));
3852 }
3853
3854 // Test Both
3855 {
3856 auto sysTime = SysTime(Date(1, 1, 1));
3857 sysTime.add!"months"(-1, AllowDayOverflow.no);
3858 assert(sysTime == SysTime(Date(0, 12, 1)));
3859 sysTime.add!"months"(1, AllowDayOverflow.no);
3860 assert(sysTime == SysTime(Date(1, 1, 1)));
3861 }
3862
3863 {
3864 auto sysTime = SysTime(Date(4, 1, 1));
3865 sysTime.add!"months"(-48, AllowDayOverflow.no);
3866 assert(sysTime == SysTime(Date(0, 1, 1)));
3867 sysTime.add!"months"(48, AllowDayOverflow.no);
3868 assert(sysTime == SysTime(Date(4, 1, 1)));
3869 }
3870
3871 {
3872 auto sysTime = SysTime(Date(4, 3, 31));
3873 sysTime.add!"months"(-49, AllowDayOverflow.no);
3874 assert(sysTime == SysTime(Date(0, 2, 29)));
3875 sysTime.add!"months"(49, AllowDayOverflow.no);
3876 assert(sysTime == SysTime(Date(4, 3, 29)));
3877 }
3878
3879 {
3880 auto sysTime = SysTime(Date(4, 3, 31));
3881 sysTime.add!"months"(-85, AllowDayOverflow.no);
3882 assert(sysTime == SysTime(Date(-3, 2, 28)));
3883 sysTime.add!"months"(85, AllowDayOverflow.no);
3884 assert(sysTime == SysTime(Date(4, 3, 28)));
3885 }
3886
3887 {
3888 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
3889 sysTime.add!"months"(-1, AllowDayOverflow.no);
3890 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
3891 sysTime.add!"months"(1, AllowDayOverflow.no);
3892 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
3893 }
3894
3895 {
3896 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
3897 sysTime.add!"months"(-1, AllowDayOverflow.no);
3898 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
3899 sysTime.add!"months"(1, AllowDayOverflow.no);
3900 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3901 }
3902
3903 {
3904 auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0));
3905 sysTime.add!"months"(1, AllowDayOverflow.no);
3906 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
3907 sysTime.add!"months"(-1, AllowDayOverflow.no);
3908 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
3909 }
3910
3911 {
3912 auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999));
3913 sysTime.add!"months"(1, AllowDayOverflow.no);
3914 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3915 sysTime.add!"months"(-1, AllowDayOverflow.no);
3916 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
3917 }
3918
3919 {
3920 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17));
3921 sysTime.add!"months"(-1, AllowDayOverflow.no);
3922 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 7, 9), hnsecs(17)));
3923 sysTime.add!"months"(1, AllowDayOverflow.no);
3924 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17)));
3925 }
3926
3927 {
3928 auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), msecs(9));
3929 sysTime.add!"months"(-85, AllowDayOverflow.no);
3930 assert(sysTime == SysTime(DateTime(-3, 2, 28, 12, 11, 10), msecs(9)));
3931 sysTime.add!"months"(85, AllowDayOverflow.no);
3932 assert(sysTime == SysTime(DateTime(4, 3, 28, 12, 11, 10), msecs(9)));
3933 }
3934
3935 {
3936 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
3937 sysTime.add!"months"(85, AllowDayOverflow.no);
3938 assert(sysTime == SysTime(DateTime(4, 4, 30, 12, 11, 10), msecs(9)));
3939 sysTime.add!"months"(-85, AllowDayOverflow.no);
3940 assert(sysTime == SysTime(DateTime(-3, 3, 30, 12, 11, 10), msecs(9)));
3941 }
3942
3943 {
3944 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
3945 sysTime.add!"months"(85, AllowDayOverflow.no).add!"months"(-83, AllowDayOverflow.no);
3946 assert(sysTime == SysTime(DateTime(-3, 5, 30, 12, 11, 10), msecs(9)));
3947 }
3948 }
3949
3950
3951 /++
3952 Adds the given number of years or months to this $(LREF SysTime). A
3953 negative number will subtract.
3954
3955 The difference between rolling and adding is that rolling does not
3956 affect larger units. Rolling a $(LREF SysTime) 12 months
3957 gets the exact same $(LREF SysTime). However, the days can still be
3958 affected due to the differing number of days in each month.
3959
3960 Because there are no units larger than years, there is no difference
3961 between adding and rolling years.
3962
3963 Params:
3964 units = The type of units to add ("years" or "months").
3965 value = The number of months or years to add to this
3966 $(LREF SysTime).
3967 allowOverflow = Whether the days should be allowed to overflow,
3968 causing the month to increment.
3969 +/
3970 ref SysTime roll(string units)
3971 (long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) @safe nothrow scope
3972 if (units == "years")
3973 {
3974 return add!"years"(value, allowOverflow);
3975 }
3976
3977 ///
3978 @safe unittest
3979 {
3980 import std.datetime.date : AllowDayOverflow, DateTime;
3981
3982 auto st1 = SysTime(DateTime(2010, 1, 1, 12, 33, 33));
3983 st1.roll!"months"(1);
3984 assert(st1 == SysTime(DateTime(2010, 2, 1, 12, 33, 33)));
3985
3986 auto st2 = SysTime(DateTime(2010, 1, 1, 12, 33, 33));
3987 st2.roll!"months"(-1);
3988 assert(st2 == SysTime(DateTime(2010, 12, 1, 12, 33, 33)));
3989
3990 auto st3 = SysTime(DateTime(1999, 1, 29, 12, 33, 33));
3991 st3.roll!"months"(1);
3992 assert(st3 == SysTime(DateTime(1999, 3, 1, 12, 33, 33)));
3993
3994 auto st4 = SysTime(DateTime(1999, 1, 29, 12, 33, 33));
3995 st4.roll!"months"(1, AllowDayOverflow.no);
3996 assert(st4 == SysTime(DateTime(1999, 2, 28, 12, 33, 33)));
3997
3998 auto st5 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
3999 st5.roll!"years"(1);
4000 assert(st5 == SysTime(DateTime(2001, 3, 1, 12, 30, 33)));
4001
4002 auto st6 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
4003 st6.roll!"years"(1, AllowDayOverflow.no);
4004 assert(st6 == SysTime(DateTime(2001, 2, 28, 12, 30, 33)));
4005 }
4006
4007 @safe unittest
4008 {
4009 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
4010 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
4011 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
4012 st.roll!"years"(4);
4013 static assert(!__traits(compiles, cst.roll!"years"(4)));
4014 static assert(!__traits(compiles, ist.roll!"years"(4)));
4015
4016 static void testScope(scope ref SysTime st) @safe
4017 {
4018 auto result = st.roll!"years"(42);
4019 }
4020 }
4021
4022
4023 // Shares documentation with "years" overload.
4024 ref SysTime roll(string units)
4025 (long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) @safe nothrow scope
4026 if (units == "months")
4027 {
4028 auto hnsecs = adjTime;
4029 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
4030
4031 if (hnsecs < 0)
4032 {
4033 hnsecs += convert!("hours", "hnsecs")(24);
4034 --days;
4035 }
4036
4037 auto date = Date(cast(int) days);
4038 date.roll!"months"(value, allowOverflow);
4039 days = date.dayOfGregorianCal - 1;
4040
4041 if (days < 0)
4042 {
4043 hnsecs -= convert!("hours", "hnsecs")(24);
4044 ++days;
4045 }
4046
4047 immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
4048 adjTime = newDaysHNSecs + hnsecs;
4049 return this;
4050 }
4051
4052 // Test roll!"months"() with AllowDayOverflow.yes
4053 @safe unittest
4054 {
4055 import core.time;
4056 // Test A.D.
4057 {
4058 auto sysTime = SysTime(Date(1999, 7, 6));
4059 sysTime.roll!"months"(3);
4060 assert(sysTime == SysTime(Date(1999, 10, 6)));
4061 sysTime.roll!"months"(-4);
4062 assert(sysTime == SysTime(Date(1999, 6, 6)));
4063 }
4064
4065 {
4066 auto sysTime = SysTime(Date(1999, 7, 6));
4067 sysTime.roll!"months"(6);
4068 assert(sysTime == SysTime(Date(1999, 1, 6)));
4069 sysTime.roll!"months"(-6);
4070 assert(sysTime == SysTime(Date(1999, 7, 6)));
4071 }
4072
4073 {
4074 auto sysTime = SysTime(Date(1999, 7, 6));
4075 sysTime.roll!"months"(27);
4076 assert(sysTime == SysTime(Date(1999, 10, 6)));
4077 sysTime.roll!"months"(-28);
4078 assert(sysTime == SysTime(Date(1999, 6, 6)));
4079 }
4080
4081 {
4082 auto sysTime = SysTime(Date(1999, 5, 31));
4083 sysTime.roll!"months"(1);
4084 assert(sysTime == SysTime(Date(1999, 7, 1)));
4085 }
4086
4087 {
4088 auto sysTime = SysTime(Date(1999, 5, 31));
4089 sysTime.roll!"months"(-1);
4090 assert(sysTime == SysTime(Date(1999, 5, 1)));
4091 }
4092
4093 {
4094 auto sysTime = SysTime(Date(1999, 2, 28));
4095 sysTime.roll!"months"(12);
4096 assert(sysTime == SysTime(Date(1999, 2, 28)));
4097 }
4098
4099 {
4100 auto sysTime = SysTime(Date(2000, 2, 29));
4101 sysTime.roll!"months"(12);
4102 assert(sysTime == SysTime(Date(2000, 2, 29)));
4103 }
4104
4105 {
4106 auto sysTime = SysTime(Date(1999, 7, 31));
4107 sysTime.roll!"months"(1);
4108 assert(sysTime == SysTime(Date(1999, 8, 31)));
4109 sysTime.roll!"months"(1);
4110 assert(sysTime == SysTime(Date(1999, 10, 1)));
4111 }
4112
4113 {
4114 auto sysTime = SysTime(Date(1998, 8, 31));
4115 sysTime.roll!"months"(13);
4116 assert(sysTime == SysTime(Date(1998, 10, 1)));
4117 sysTime.roll!"months"(-13);
4118 assert(sysTime == SysTime(Date(1998, 9, 1)));
4119 }
4120
4121 {
4122 auto sysTime = SysTime(Date(1997, 12, 31));
4123 sysTime.roll!"months"(13);
4124 assert(sysTime == SysTime(Date(1997, 1, 31)));
4125 sysTime.roll!"months"(-13);
4126 assert(sysTime == SysTime(Date(1997, 12, 31)));
4127 }
4128
4129 {
4130 auto sysTime = SysTime(Date(1997, 12, 31));
4131 sysTime.roll!"months"(14);
4132 assert(sysTime == SysTime(Date(1997, 3, 3)));
4133 sysTime.roll!"months"(-14);
4134 assert(sysTime == SysTime(Date(1997, 1, 3)));
4135 }
4136
4137 {
4138 auto sysTime = SysTime(Date(1998, 12, 31));
4139 sysTime.roll!"months"(14);
4140 assert(sysTime == SysTime(Date(1998, 3, 3)));
4141 sysTime.roll!"months"(-14);
4142 assert(sysTime == SysTime(Date(1998, 1, 3)));
4143 }
4144
4145 {
4146 auto sysTime = SysTime(Date(1999, 12, 31));
4147 sysTime.roll!"months"(14);
4148 assert(sysTime == SysTime(Date(1999, 3, 3)));
4149 sysTime.roll!"months"(-14);
4150 assert(sysTime == SysTime(Date(1999, 1, 3)));
4151 }
4152
4153 {
4154 auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), usecs(5007));
4155 sysTime.roll!"months"(3);
4156 assert(sysTime == SysTime(DateTime(1999, 10, 6, 12, 2, 7), usecs(5007)));
4157 sysTime.roll!"months"(-4);
4158 assert(sysTime == SysTime(DateTime(1999, 6, 6, 12, 2, 7), usecs(5007)));
4159 }
4160
4161 {
4162 auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), hnsecs(422202));
4163 sysTime.roll!"months"(14);
4164 assert(sysTime == SysTime(DateTime(1998, 3, 3, 7, 7, 7), hnsecs(422202)));
4165 sysTime.roll!"months"(-14);
4166 assert(sysTime == SysTime(DateTime(1998, 1, 3, 7, 7, 7), hnsecs(422202)));
4167 }
4168
4169 {
4170 auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), hnsecs(422202));
4171 sysTime.roll!"months"(14);
4172 assert(sysTime == SysTime(DateTime(1999, 3, 3, 7, 7, 7), hnsecs(422202)));
4173 sysTime.roll!"months"(-14);
4174 assert(sysTime == SysTime(DateTime(1999, 1, 3, 7, 7, 7), hnsecs(422202)));
4175 }
4176
4177 // Test B.C.
4178 {
4179 auto sysTime = SysTime(Date(-1999, 7, 6));
4180 sysTime.roll!"months"(3);
4181 assert(sysTime == SysTime(Date(-1999, 10, 6)));
4182 sysTime.roll!"months"(-4);
4183 assert(sysTime == SysTime(Date(-1999, 6, 6)));
4184 }
4185
4186 {
4187 auto sysTime = SysTime(Date(-1999, 7, 6));
4188 sysTime.roll!"months"(6);
4189 assert(sysTime == SysTime(Date(-1999, 1, 6)));
4190 sysTime.roll!"months"(-6);
4191 assert(sysTime == SysTime(Date(-1999, 7, 6)));
4192 }
4193
4194 {
4195 auto sysTime = SysTime(Date(-1999, 7, 6));
4196 sysTime.roll!"months"(-27);
4197 assert(sysTime == SysTime(Date(-1999, 4, 6)));
4198 sysTime.roll!"months"(28);
4199 assert(sysTime == SysTime(Date(-1999, 8, 6)));
4200 }
4201
4202 {
4203 auto sysTime = SysTime(Date(-1999, 5, 31));
4204 sysTime.roll!"months"(1);
4205 assert(sysTime == SysTime(Date(-1999, 7, 1)));
4206 }
4207
4208 {
4209 auto sysTime = SysTime(Date(-1999, 5, 31));
4210 sysTime.roll!"months"(-1);
4211 assert(sysTime == SysTime(Date(-1999, 5, 1)));
4212 }
4213
4214 {
4215 auto sysTime = SysTime(Date(-1999, 2, 28));
4216 sysTime.roll!"months"(-12);
4217 assert(sysTime == SysTime(Date(-1999, 2, 28)));
4218 }
4219
4220 {
4221 auto sysTime = SysTime(Date(-2000, 2, 29));
4222 sysTime.roll!"months"(-12);
4223 assert(sysTime == SysTime(Date(-2000, 2, 29)));
4224 }
4225
4226 {
4227 auto sysTime = SysTime(Date(-1999, 7, 31));
4228 sysTime.roll!"months"(1);
4229 assert(sysTime == SysTime(Date(-1999, 8, 31)));
4230 sysTime.roll!"months"(1);
4231 assert(sysTime == SysTime(Date(-1999, 10, 1)));
4232 }
4233
4234 {
4235 auto sysTime = SysTime(Date(-1998, 8, 31));
4236 sysTime.roll!"months"(13);
4237 assert(sysTime == SysTime(Date(-1998, 10, 1)));
4238 sysTime.roll!"months"(-13);
4239 assert(sysTime == SysTime(Date(-1998, 9, 1)));
4240 }
4241
4242 {
4243 auto sysTime = SysTime(Date(-1997, 12, 31));
4244 sysTime.roll!"months"(13);
4245 assert(sysTime == SysTime(Date(-1997, 1, 31)));
4246 sysTime.roll!"months"(-13);
4247 assert(sysTime == SysTime(Date(-1997, 12, 31)));
4248 }
4249
4250 {
4251 auto sysTime = SysTime(Date(-1997, 12, 31));
4252 sysTime.roll!"months"(14);
4253 assert(sysTime == SysTime(Date(-1997, 3, 3)));
4254 sysTime.roll!"months"(-14);
4255 assert(sysTime == SysTime(Date(-1997, 1, 3)));
4256 }
4257
4258 {
4259 auto sysTime = SysTime(Date(-2002, 12, 31));
4260 sysTime.roll!"months"(14);
4261 assert(sysTime == SysTime(Date(-2002, 3, 3)));
4262 sysTime.roll!"months"(-14);
4263 assert(sysTime == SysTime(Date(-2002, 1, 3)));
4264 }
4265
4266 {
4267 auto sysTime = SysTime(Date(-2001, 12, 31));
4268 sysTime.roll!"months"(14);
4269 assert(sysTime == SysTime(Date(-2001, 3, 3)));
4270 sysTime.roll!"months"(-14);
4271 assert(sysTime == SysTime(Date(-2001, 1, 3)));
4272 }
4273
4274 {
4275 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
4276 sysTime.roll!"months"(-1);
4277 assert(sysTime == SysTime(DateTime(1, 12, 1, 0, 0, 0)));
4278 sysTime.roll!"months"(1);
4279 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
4280 }
4281
4282 {
4283 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
4284 sysTime.roll!"months"(-1);
4285 assert(sysTime == SysTime(DateTime(1, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
4286 sysTime.roll!"months"(1);
4287 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
4288 }
4289
4290 {
4291 auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0));
4292 sysTime.roll!"months"(1);
4293 assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0)));
4294 sysTime.roll!"months"(-1);
4295 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
4296 }
4297
4298 {
4299 auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999));
4300 sysTime.roll!"months"(1);
4301 assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
4302 sysTime.roll!"months"(-1);
4303 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
4304 }
4305
4306 {
4307 auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), hnsecs(5007));
4308 sysTime.roll!"months"(3);
4309 assert(sysTime == SysTime(DateTime(-1999, 10, 6, 12, 2, 7), hnsecs(5007)));
4310 sysTime.roll!"months"(-4);
4311 assert(sysTime == SysTime(DateTime(-1999, 6, 6, 12, 2, 7), hnsecs(5007)));
4312 }
4313
4314 {
4315 auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), hnsecs(422202));
4316 sysTime.roll!"months"(14);
4317 assert(sysTime == SysTime(DateTime(-2002, 3, 3, 7, 7, 7), hnsecs(422202)));
4318 sysTime.roll!"months"(-14);
4319 assert(sysTime == SysTime(DateTime(-2002, 1, 3, 7, 7, 7), hnsecs(422202)));
4320 }
4321
4322 {
4323 auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), hnsecs(422202));
4324 sysTime.roll!"months"(14);
4325 assert(sysTime == SysTime(DateTime(-2001, 3, 3, 7, 7, 7), hnsecs(422202)));
4326 sysTime.roll!"months"(-14);
4327 assert(sysTime == SysTime(DateTime(-2001, 1, 3, 7, 7, 7), hnsecs(422202)));
4328 }
4329
4330 // Test Both
4331 {
4332 auto sysTime = SysTime(Date(1, 1, 1));
4333 sysTime.roll!"months"(-1);
4334 assert(sysTime == SysTime(Date(1, 12, 1)));
4335 sysTime.roll!"months"(1);
4336 assert(sysTime == SysTime(Date(1, 1, 1)));
4337 }
4338
4339 {
4340 auto sysTime = SysTime(Date(4, 1, 1));
4341 sysTime.roll!"months"(-48);
4342 assert(sysTime == SysTime(Date(4, 1, 1)));
4343 sysTime.roll!"months"(48);
4344 assert(sysTime == SysTime(Date(4, 1, 1)));
4345 }
4346
4347 {
4348 auto sysTime = SysTime(Date(4, 3, 31));
4349 sysTime.roll!"months"(-49);
4350 assert(sysTime == SysTime(Date(4, 3, 2)));
4351 sysTime.roll!"months"(49);
4352 assert(sysTime == SysTime(Date(4, 4, 2)));
4353 }
4354
4355 {
4356 auto sysTime = SysTime(Date(4, 3, 31));
4357 sysTime.roll!"months"(-85);
4358 assert(sysTime == SysTime(Date(4, 3, 2)));
4359 sysTime.roll!"months"(85);
4360 assert(sysTime == SysTime(Date(4, 4, 2)));
4361 }
4362
4363 {
4364 auto sysTime = SysTime(Date(-1, 1, 1));
4365 sysTime.roll!"months"(-1);
4366 assert(sysTime == SysTime(Date(-1, 12, 1)));
4367 sysTime.roll!"months"(1);
4368 assert(sysTime == SysTime(Date(-1, 1, 1)));
4369 }
4370
4371 {
4372 auto sysTime = SysTime(Date(-4, 1, 1));
4373 sysTime.roll!"months"(-48);
4374 assert(sysTime == SysTime(Date(-4, 1, 1)));
4375 sysTime.roll!"months"(48);
4376 assert(sysTime == SysTime(Date(-4, 1, 1)));
4377 }
4378
4379 {
4380 auto sysTime = SysTime(Date(-4, 3, 31));
4381 sysTime.roll!"months"(-49);
4382 assert(sysTime == SysTime(Date(-4, 3, 2)));
4383 sysTime.roll!"months"(49);
4384 assert(sysTime == SysTime(Date(-4, 4, 2)));
4385 }
4386
4387 {
4388 auto sysTime = SysTime(Date(-4, 3, 31));
4389 sysTime.roll!"months"(-85);
4390 assert(sysTime == SysTime(Date(-4, 3, 2)));
4391 sysTime.roll!"months"(85);
4392 assert(sysTime == SysTime(Date(-4, 4, 2)));
4393 }
4394
4395 {
4396 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17));
4397 sysTime.roll!"months"(-1);
4398 assert(sysTime == SysTime(DateTime(1, 12, 1, 0, 7, 9), hnsecs(17)));
4399 sysTime.roll!"months"(1);
4400 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17)));
4401 }
4402
4403 {
4404 auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), msecs(9));
4405 sysTime.roll!"months"(-85);
4406 assert(sysTime == SysTime(DateTime(4, 3, 2, 12, 11, 10), msecs(9)));
4407 sysTime.roll!"months"(85);
4408 assert(sysTime == SysTime(DateTime(4, 4, 2, 12, 11, 10), msecs(9)));
4409 }
4410
4411 {
4412 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
4413 sysTime.roll!"months"(85);
4414 assert(sysTime == SysTime(DateTime(-3, 5, 1, 12, 11, 10), msecs(9)));
4415 sysTime.roll!"months"(-85);
4416 assert(sysTime == SysTime(DateTime(-3, 4, 1, 12, 11, 10), msecs(9)));
4417 }
4418
4419 {
4420 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
4421 sysTime.roll!"months"(85).roll!"months"(-83);
4422 assert(sysTime == SysTime(DateTime(-3, 6, 1, 12, 11, 10), msecs(9)));
4423 }
4424
4425 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
4426 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
4427 static assert(!__traits(compiles, cst.roll!"months"(4)));
4428 static assert(!__traits(compiles, ist.roll!"months"(4)));
4429
4430 static void testScope(scope ref SysTime st) @safe
4431 {
4432 auto result = st.roll!"months"(42);
4433 }
4434 }
4435
4436 // Test roll!"months"() with AllowDayOverflow.no
4437 @safe unittest
4438 {
4439 import core.time;
4440 // Test A.D.
4441 {
4442 auto sysTime = SysTime(Date(1999, 7, 6));
4443 sysTime.roll!"months"(3, AllowDayOverflow.no);
4444 assert(sysTime == SysTime(Date(1999, 10, 6)));
4445 sysTime.roll!"months"(-4, AllowDayOverflow.no);
4446 assert(sysTime == SysTime(Date(1999, 6, 6)));
4447 }
4448
4449 {
4450 auto sysTime = SysTime(Date(1999, 7, 6));
4451 sysTime.roll!"months"(6, AllowDayOverflow.no);
4452 assert(sysTime == SysTime(Date(1999, 1, 6)));
4453 sysTime.roll!"months"(-6, AllowDayOverflow.no);
4454 assert(sysTime == SysTime(Date(1999, 7, 6)));
4455 }
4456
4457 {
4458 auto sysTime = SysTime(Date(1999, 7, 6));
4459 sysTime.roll!"months"(27, AllowDayOverflow.no);
4460 assert(sysTime == SysTime(Date(1999, 10, 6)));
4461 sysTime.roll!"months"(-28, AllowDayOverflow.no);
4462 assert(sysTime == SysTime(Date(1999, 6, 6)));
4463 }
4464
4465 {
4466 auto sysTime = SysTime(Date(1999, 5, 31));
4467 sysTime.roll!"months"(1, AllowDayOverflow.no);
4468 assert(sysTime == SysTime(Date(1999, 6, 30)));
4469 }
4470
4471 {
4472 auto sysTime = SysTime(Date(1999, 5, 31));
4473 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4474 assert(sysTime == SysTime(Date(1999, 4, 30)));
4475 }
4476
4477 {
4478 auto sysTime = SysTime(Date(1999, 2, 28));
4479 sysTime.roll!"months"(12, AllowDayOverflow.no);
4480 assert(sysTime == SysTime(Date(1999, 2, 28)));
4481 }
4482
4483 {
4484 auto sysTime = SysTime(Date(2000, 2, 29));
4485 sysTime.roll!"months"(12, AllowDayOverflow.no);
4486 assert(sysTime == SysTime(Date(2000, 2, 29)));
4487 }
4488
4489 {
4490 auto sysTime = SysTime(Date(1999, 7, 31));
4491 sysTime.roll!"months"(1, AllowDayOverflow.no);
4492 assert(sysTime == SysTime(Date(1999, 8, 31)));
4493 sysTime.roll!"months"(1, AllowDayOverflow.no);
4494 assert(sysTime == SysTime(Date(1999, 9, 30)));
4495 }
4496
4497 {
4498 auto sysTime = SysTime(Date(1998, 8, 31));
4499 sysTime.roll!"months"(13, AllowDayOverflow.no);
4500 assert(sysTime == SysTime(Date(1998, 9, 30)));
4501 sysTime.roll!"months"(-13, AllowDayOverflow.no);
4502 assert(sysTime == SysTime(Date(1998, 8, 30)));
4503 }
4504
4505 {
4506 auto sysTime = SysTime(Date(1997, 12, 31));
4507 sysTime.roll!"months"(13, AllowDayOverflow.no);
4508 assert(sysTime == SysTime(Date(1997, 1, 31)));
4509 sysTime.roll!"months"(-13, AllowDayOverflow.no);
4510 assert(sysTime == SysTime(Date(1997, 12, 31)));
4511 }
4512
4513 {
4514 auto sysTime = SysTime(Date(1997, 12, 31));
4515 sysTime.roll!"months"(14, AllowDayOverflow.no);
4516 assert(sysTime == SysTime(Date(1997, 2, 28)));
4517 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4518 assert(sysTime == SysTime(Date(1997, 12, 28)));
4519 }
4520
4521 {
4522 auto sysTime = SysTime(Date(1998, 12, 31));
4523 sysTime.roll!"months"(14, AllowDayOverflow.no);
4524 assert(sysTime == SysTime(Date(1998, 2, 28)));
4525 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4526 assert(sysTime == SysTime(Date(1998, 12, 28)));
4527 }
4528
4529 {
4530 auto sysTime = SysTime(Date(1999, 12, 31));
4531 sysTime.roll!"months"(14, AllowDayOverflow.no);
4532 assert(sysTime == SysTime(Date(1999, 2, 28)));
4533 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4534 assert(sysTime == SysTime(Date(1999, 12, 28)));
4535 }
4536
4537 {
4538 auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), usecs(5007));
4539 sysTime.roll!"months"(3, AllowDayOverflow.no);
4540 assert(sysTime == SysTime(DateTime(1999, 10, 6, 12, 2, 7), usecs(5007)));
4541 sysTime.roll!"months"(-4, AllowDayOverflow.no);
4542 assert(sysTime == SysTime(DateTime(1999, 6, 6, 12, 2, 7), usecs(5007)));
4543 }
4544
4545 {
4546 auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), hnsecs(422202));
4547 sysTime.roll!"months"(14, AllowDayOverflow.no);
4548 assert(sysTime == SysTime(DateTime(1998, 2, 28, 7, 7, 7), hnsecs(422202)));
4549 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4550 assert(sysTime == SysTime(DateTime(1998, 12, 28, 7, 7, 7), hnsecs(422202)));
4551 }
4552
4553 {
4554 auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), hnsecs(422202));
4555 sysTime.roll!"months"(14, AllowDayOverflow.no);
4556 assert(sysTime == SysTime(DateTime(1999, 2, 28, 7, 7, 7), hnsecs(422202)));
4557 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4558 assert(sysTime == SysTime(DateTime(1999, 12, 28, 7, 7, 7), hnsecs(422202)));
4559 }
4560
4561 // Test B.C.
4562 {
4563 auto sysTime = SysTime(Date(-1999, 7, 6));
4564 sysTime.roll!"months"(3, AllowDayOverflow.no);
4565 assert(sysTime == SysTime(Date(-1999, 10, 6)));
4566 sysTime.roll!"months"(-4, AllowDayOverflow.no);
4567 assert(sysTime == SysTime(Date(-1999, 6, 6)));
4568 }
4569
4570 {
4571 auto sysTime = SysTime(Date(-1999, 7, 6));
4572 sysTime.roll!"months"(6, AllowDayOverflow.no);
4573 assert(sysTime == SysTime(Date(-1999, 1, 6)));
4574 sysTime.roll!"months"(-6, AllowDayOverflow.no);
4575 assert(sysTime == SysTime(Date(-1999, 7, 6)));
4576 }
4577
4578 {
4579 auto sysTime = SysTime(Date(-1999, 7, 6));
4580 sysTime.roll!"months"(-27, AllowDayOverflow.no);
4581 assert(sysTime == SysTime(Date(-1999, 4, 6)));
4582 sysTime.roll!"months"(28, AllowDayOverflow.no);
4583 assert(sysTime == SysTime(Date(-1999, 8, 6)));
4584 }
4585
4586 {
4587 auto sysTime = SysTime(Date(-1999, 5, 31));
4588 sysTime.roll!"months"(1, AllowDayOverflow.no);
4589 assert(sysTime == SysTime(Date(-1999, 6, 30)));
4590 }
4591
4592 {
4593 auto sysTime = SysTime(Date(-1999, 5, 31));
4594 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4595 assert(sysTime == SysTime(Date(-1999, 4, 30)));
4596 }
4597
4598 {
4599 auto sysTime = SysTime(Date(-1999, 2, 28));
4600 sysTime.roll!"months"(-12, AllowDayOverflow.no);
4601 assert(sysTime == SysTime(Date(-1999, 2, 28)));
4602 }
4603
4604 {
4605 auto sysTime = SysTime(Date(-2000, 2, 29));
4606 sysTime.roll!"months"(-12, AllowDayOverflow.no);
4607 assert(sysTime == SysTime(Date(-2000, 2, 29)));
4608 }
4609
4610 {
4611 auto sysTime = SysTime(Date(-1999, 7, 31));
4612 sysTime.roll!"months"(1, AllowDayOverflow.no);
4613 assert(sysTime == SysTime(Date(-1999, 8, 31)));
4614 sysTime.roll!"months"(1, AllowDayOverflow.no);
4615 assert(sysTime == SysTime(Date(-1999, 9, 30)));
4616 }
4617
4618 {
4619 auto sysTime = SysTime(Date(-1998, 8, 31));
4620 sysTime.roll!"months"(13, AllowDayOverflow.no);
4621 assert(sysTime == SysTime(Date(-1998, 9, 30)));
4622 sysTime.roll!"months"(-13, AllowDayOverflow.no);
4623 assert(sysTime == SysTime(Date(-1998, 8, 30)));
4624 }
4625
4626 {
4627 auto sysTime = SysTime(Date(-1997, 12, 31));
4628 sysTime.roll!"months"(13, AllowDayOverflow.no);
4629 assert(sysTime == SysTime(Date(-1997, 1, 31)));
4630 sysTime.roll!"months"(-13, AllowDayOverflow.no);
4631 assert(sysTime == SysTime(Date(-1997, 12, 31)));
4632 }
4633
4634 {
4635 auto sysTime = SysTime(Date(-1997, 12, 31));
4636 sysTime.roll!"months"(14, AllowDayOverflow.no);
4637 assert(sysTime == SysTime(Date(-1997, 2, 28)));
4638 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4639 assert(sysTime == SysTime(Date(-1997, 12, 28)));
4640 }
4641
4642 {
4643 auto sysTime = SysTime(Date(-2002, 12, 31));
4644 sysTime.roll!"months"(14, AllowDayOverflow.no);
4645 assert(sysTime == SysTime(Date(-2002, 2, 28)));
4646 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4647 assert(sysTime == SysTime(Date(-2002, 12, 28)));
4648 }
4649
4650 {
4651 auto sysTime = SysTime(Date(-2001, 12, 31));
4652 sysTime.roll!"months"(14, AllowDayOverflow.no);
4653 assert(sysTime == SysTime(Date(-2001, 2, 28)));
4654 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4655 assert(sysTime == SysTime(Date(-2001, 12, 28)));
4656 }
4657
4658 {
4659 auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), usecs(5007));
4660 sysTime.roll!"months"(3, AllowDayOverflow.no);
4661 assert(sysTime == SysTime(DateTime(-1999, 10, 6, 12, 2, 7), usecs(5007)));
4662 sysTime.roll!"months"(-4, AllowDayOverflow.no);
4663 assert(sysTime == SysTime(DateTime(-1999, 6, 6, 12, 2, 7), usecs(5007)));
4664 }
4665
4666 {
4667 auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), hnsecs(422202));
4668 sysTime.roll!"months"(14, AllowDayOverflow.no);
4669 assert(sysTime == SysTime(DateTime(-2002, 2, 28, 7, 7, 7), hnsecs(422202)));
4670 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4671 assert(sysTime == SysTime(DateTime(-2002, 12, 28, 7, 7, 7), hnsecs(422202)));
4672 }
4673
4674 {
4675 auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), hnsecs(422202));
4676 sysTime.roll!"months"(14, AllowDayOverflow.no);
4677 assert(sysTime == SysTime(DateTime(-2001, 2, 28, 7, 7, 7), hnsecs(422202)));
4678 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4679 assert(sysTime == SysTime(DateTime(-2001, 12, 28, 7, 7, 7), hnsecs(422202)));
4680 }
4681
4682 // Test Both
4683 {
4684 auto sysTime = SysTime(Date(1, 1, 1));
4685 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4686 assert(sysTime == SysTime(Date(1, 12, 1)));
4687 sysTime.roll!"months"(1, AllowDayOverflow.no);
4688 assert(sysTime == SysTime(Date(1, 1, 1)));
4689 }
4690
4691 {
4692 auto sysTime = SysTime(Date(4, 1, 1));
4693 sysTime.roll!"months"(-48, AllowDayOverflow.no);
4694 assert(sysTime == SysTime(Date(4, 1, 1)));
4695 sysTime.roll!"months"(48, AllowDayOverflow.no);
4696 assert(sysTime == SysTime(Date(4, 1, 1)));
4697 }
4698
4699 {
4700 auto sysTime = SysTime(Date(4, 3, 31));
4701 sysTime.roll!"months"(-49, AllowDayOverflow.no);
4702 assert(sysTime == SysTime(Date(4, 2, 29)));
4703 sysTime.roll!"months"(49, AllowDayOverflow.no);
4704 assert(sysTime == SysTime(Date(4, 3, 29)));
4705 }
4706
4707 {
4708 auto sysTime = SysTime(Date(4, 3, 31));
4709 sysTime.roll!"months"(-85, AllowDayOverflow.no);
4710 assert(sysTime == SysTime(Date(4, 2, 29)));
4711 sysTime.roll!"months"(85, AllowDayOverflow.no);
4712 assert(sysTime == SysTime(Date(4, 3, 29)));
4713 }
4714
4715 {
4716 auto sysTime = SysTime(Date(-1, 1, 1));
4717 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4718 assert(sysTime == SysTime(Date(-1, 12, 1)));
4719 sysTime.roll!"months"(1, AllowDayOverflow.no);
4720 assert(sysTime == SysTime(Date(-1, 1, 1)));
4721 }
4722
4723 {
4724 auto sysTime = SysTime(Date(-4, 1, 1));
4725 sysTime.roll!"months"(-48, AllowDayOverflow.no);
4726 assert(sysTime == SysTime(Date(-4, 1, 1)));
4727 sysTime.roll!"months"(48, AllowDayOverflow.no);
4728 assert(sysTime == SysTime(Date(-4, 1, 1)));
4729 }
4730
4731 {
4732 auto sysTime = SysTime(Date(-4, 3, 31));
4733 sysTime.roll!"months"(-49, AllowDayOverflow.no);
4734 assert(sysTime == SysTime(Date(-4, 2, 29)));
4735 sysTime.roll!"months"(49, AllowDayOverflow.no);
4736 assert(sysTime == SysTime(Date(-4, 3, 29)));
4737 }
4738
4739 {
4740 auto sysTime = SysTime(Date(-4, 3, 31));
4741 sysTime.roll!"months"(-85, AllowDayOverflow.no);
4742 assert(sysTime == SysTime(Date(-4, 2, 29)));
4743 sysTime.roll!"months"(85, AllowDayOverflow.no);
4744 assert(sysTime == SysTime(Date(-4, 3, 29)));
4745 }
4746
4747 {
4748 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
4749 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4750 assert(sysTime == SysTime(DateTime(1, 12, 1, 0, 0, 0)));
4751 sysTime.roll!"months"(1, AllowDayOverflow.no);
4752 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
4753 }
4754
4755 {
4756 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
4757 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4758 assert(sysTime == SysTime(DateTime(1, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
4759 sysTime.roll!"months"(1, AllowDayOverflow.no);
4760 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
4761 }
4762
4763 {
4764 auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0));
4765 sysTime.roll!"months"(1, AllowDayOverflow.no);
4766 assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0)));
4767 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4768 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
4769 }
4770
4771 {
4772 auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999));
4773 sysTime.roll!"months"(1, AllowDayOverflow.no);
4774 assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
4775 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4776 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
4777 }
4778
4779 {
4780 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17));
4781 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4782 assert(sysTime == SysTime(DateTime(1, 12, 1, 0, 7, 9), hnsecs(17)));
4783 sysTime.roll!"months"(1, AllowDayOverflow.no);
4784 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17)));
4785 }
4786
4787 {
4788 auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), msecs(9));
4789 sysTime.roll!"months"(-85, AllowDayOverflow.no);
4790 assert(sysTime == SysTime(DateTime(4, 2, 29, 12, 11, 10), msecs(9)));
4791 sysTime.roll!"months"(85, AllowDayOverflow.no);
4792 assert(sysTime == SysTime(DateTime(4, 3, 29, 12, 11, 10), msecs(9)));
4793 }
4794
4795 {
4796 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
4797 sysTime.roll!"months"(85, AllowDayOverflow.no);
4798 assert(sysTime == SysTime(DateTime(-3, 4, 30, 12, 11, 10), msecs(9)));
4799 sysTime.roll!"months"(-85, AllowDayOverflow.no);
4800 assert(sysTime == SysTime(DateTime(-3, 3, 30, 12, 11, 10), msecs(9)));
4801 }
4802
4803 {
4804 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
4805 sysTime.roll!"months"(85, AllowDayOverflow.no).roll!"months"(-83, AllowDayOverflow.no);
4806 assert(sysTime == SysTime(DateTime(-3, 5, 30, 12, 11, 10), msecs(9)));
4807 }
4808 }
4809
4810
4811 /++
4812 Adds the given number of units to this $(LREF SysTime). A negative number
4813 will subtract.
4814
4815 The difference between rolling and adding is that rolling does not
4816 affect larger units. For instance, rolling a $(LREF SysTime) one
4817 year's worth of days gets the exact same $(LREF SysTime).
4818
4819 Accepted units are `"days"`, `"minutes"`, `"hours"`,
4820 `"minutes"`, `"seconds"`, `"msecs"`, `"usecs"`, and
4821 `"hnsecs"`.
4822
4823 Note that when rolling msecs, usecs or hnsecs, they all add up to a
4824 second. So, for example, rolling 1000 msecs is exactly the same as
4825 rolling 100,000 usecs.
4826
4827 Params:
4828 units = The units to add.
4829 value = The number of $(D_PARAM units) to add to this
4830 $(LREF SysTime).
4831 +/
4832 ref SysTime roll(string units)(long value) @safe nothrow scope
4833 if (units == "days")
4834 {
4835 auto hnsecs = adjTime;
4836 auto gdays = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
4837
4838 if (hnsecs < 0)
4839 {
4840 hnsecs += convert!("hours", "hnsecs")(24);
4841 --gdays;
4842 }
4843
4844 auto date = Date(cast(int) gdays);
4845 date.roll!"days"(value);
4846 gdays = date.dayOfGregorianCal - 1;
4847
4848 if (gdays < 0)
4849 {
4850 hnsecs -= convert!("hours", "hnsecs")(24);
4851 ++gdays;
4852 }
4853
4854 immutable newDaysHNSecs = convert!("days", "hnsecs")(gdays);
4855 adjTime = newDaysHNSecs + hnsecs;
4856 return this;
4857 }
4858
4859 ///
4860 @safe unittest
4861 {
4862 import core.time : msecs, hnsecs;
4863 import std.datetime.date : DateTime;
4864
4865 auto st1 = SysTime(DateTime(2010, 1, 1, 11, 23, 12));
4866 st1.roll!"days"(1);
4867 assert(st1 == SysTime(DateTime(2010, 1, 2, 11, 23, 12)));
4868 st1.roll!"days"(365);
4869 assert(st1 == SysTime(DateTime(2010, 1, 26, 11, 23, 12)));
4870 st1.roll!"days"(-32);
4871 assert(st1 == SysTime(DateTime(2010, 1, 25, 11, 23, 12)));
4872
4873 auto st2 = SysTime(DateTime(2010, 7, 4, 12, 0, 0));
4874 st2.roll!"hours"(1);
4875 assert(st2 == SysTime(DateTime(2010, 7, 4, 13, 0, 0)));
4876
4877 auto st3 = SysTime(DateTime(2010, 2, 12, 12, 0, 0));
4878 st3.roll!"hours"(-1);
4879 assert(st3 == SysTime(DateTime(2010, 2, 12, 11, 0, 0)));
4880
4881 auto st4 = SysTime(DateTime(2009, 12, 31, 0, 0, 0));
4882 st4.roll!"minutes"(1);
4883 assert(st4 == SysTime(DateTime(2009, 12, 31, 0, 1, 0)));
4884
4885 auto st5 = SysTime(DateTime(2010, 1, 1, 0, 0, 0));
4886 st5.roll!"minutes"(-1);
4887 assert(st5 == SysTime(DateTime(2010, 1, 1, 0, 59, 0)));
4888
4889 auto st6 = SysTime(DateTime(2009, 12, 31, 0, 0, 0));
4890 st6.roll!"seconds"(1);
4891 assert(st6 == SysTime(DateTime(2009, 12, 31, 0, 0, 1)));
4892
4893 auto st7 = SysTime(DateTime(2010, 1, 1, 0, 0, 0));
4894 st7.roll!"seconds"(-1);
4895 assert(st7 == SysTime(DateTime(2010, 1, 1, 0, 0, 59)));
4896
4897 auto dt = DateTime(2010, 1, 1, 0, 0, 0);
4898 auto st8 = SysTime(dt);
4899 st8.roll!"msecs"(1);
4900 assert(st8 == SysTime(dt, msecs(1)));
4901
4902 auto st9 = SysTime(dt);
4903 st9.roll!"msecs"(-1);
4904 assert(st9 == SysTime(dt, msecs(999)));
4905
4906 auto st10 = SysTime(dt);
4907 st10.roll!"hnsecs"(1);
4908 assert(st10 == SysTime(dt, hnsecs(1)));
4909
4910 auto st11 = SysTime(dt);
4911 st11.roll!"hnsecs"(-1);
4912 assert(st11 == SysTime(dt, hnsecs(9_999_999)));
4913 }
4914
4915 @safe unittest
4916 {
4917 import core.time;
4918 // Test A.D.
4919 {
4920 auto sysTime = SysTime(Date(1999, 2, 28));
4921 sysTime.roll!"days"(1);
4922 assert(sysTime == SysTime(Date(1999, 2, 1)));
4923 sysTime.roll!"days"(-1);
4924 assert(sysTime == SysTime(Date(1999, 2, 28)));
4925 }
4926
4927 {
4928 auto sysTime = SysTime(Date(2000, 2, 28));
4929 sysTime.roll!"days"(1);
4930 assert(sysTime == SysTime(Date(2000, 2, 29)));
4931 sysTime.roll!"days"(1);
4932 assert(sysTime == SysTime(Date(2000, 2, 1)));
4933 sysTime.roll!"days"(-1);
4934 assert(sysTime == SysTime(Date(2000, 2, 29)));
4935 }
4936
4937 {
4938 auto sysTime = SysTime(Date(1999, 6, 30));
4939 sysTime.roll!"days"(1);
4940 assert(sysTime == SysTime(Date(1999, 6, 1)));
4941 sysTime.roll!"days"(-1);
4942 assert(sysTime == SysTime(Date(1999, 6, 30)));
4943 }
4944
4945 {
4946 auto sysTime = SysTime(Date(1999, 7, 31));
4947 sysTime.roll!"days"(1);
4948 assert(sysTime == SysTime(Date(1999, 7, 1)));
4949 sysTime.roll!"days"(-1);
4950 assert(sysTime == SysTime(Date(1999, 7, 31)));
4951 }
4952
4953 {
4954 auto sysTime = SysTime(Date(1999, 1, 1));
4955 sysTime.roll!"days"(-1);
4956 assert(sysTime == SysTime(Date(1999, 1, 31)));
4957 sysTime.roll!"days"(1);
4958 assert(sysTime == SysTime(Date(1999, 1, 1)));
4959 }
4960
4961 {
4962 auto sysTime = SysTime(Date(1999, 7, 6));
4963 sysTime.roll!"days"(9);
4964 assert(sysTime == SysTime(Date(1999, 7, 15)));
4965 sysTime.roll!"days"(-11);
4966 assert(sysTime == SysTime(Date(1999, 7, 4)));
4967 sysTime.roll!"days"(30);
4968 assert(sysTime == SysTime(Date(1999, 7, 3)));
4969 sysTime.roll!"days"(-3);
4970 assert(sysTime == SysTime(Date(1999, 7, 31)));
4971 }
4972
4973 {
4974 auto sysTime = SysTime(Date(1999, 7, 6));
4975 sysTime.roll!"days"(365);
4976 assert(sysTime == SysTime(Date(1999, 7, 30)));
4977 sysTime.roll!"days"(-365);
4978 assert(sysTime == SysTime(Date(1999, 7, 6)));
4979 sysTime.roll!"days"(366);
4980 assert(sysTime == SysTime(Date(1999, 7, 31)));
4981 sysTime.roll!"days"(730);
4982 assert(sysTime == SysTime(Date(1999, 7, 17)));
4983 sysTime.roll!"days"(-1096);
4984 assert(sysTime == SysTime(Date(1999, 7, 6)));
4985 }
4986
4987 {
4988 auto sysTime = SysTime(Date(1999, 2, 6));
4989 sysTime.roll!"days"(365);
4990 assert(sysTime == SysTime(Date(1999, 2, 7)));
4991 sysTime.roll!"days"(-365);
4992 assert(sysTime == SysTime(Date(1999, 2, 6)));
4993 sysTime.roll!"days"(366);
4994 assert(sysTime == SysTime(Date(1999, 2, 8)));
4995 sysTime.roll!"days"(730);
4996 assert(sysTime == SysTime(Date(1999, 2, 10)));
4997 sysTime.roll!"days"(-1096);
4998 assert(sysTime == SysTime(Date(1999, 2, 6)));
4999 }
5000
5001 {
5002 auto sysTime = SysTime(DateTime(1999, 2, 28, 7, 9, 2), usecs(234578));
5003 sysTime.roll!"days"(1);
5004 assert(sysTime == SysTime(DateTime(1999, 2, 1, 7, 9, 2), usecs(234578)));
5005 sysTime.roll!"days"(-1);
5006 assert(sysTime == SysTime(DateTime(1999, 2, 28, 7, 9, 2), usecs(234578)));
5007 }
5008
5009 {
5010 auto sysTime = SysTime(DateTime(1999, 7, 6, 7, 9, 2), usecs(234578));
5011 sysTime.roll!"days"(9);
5012 assert(sysTime == SysTime(DateTime(1999, 7, 15, 7, 9, 2), usecs(234578)));
5013 sysTime.roll!"days"(-11);
5014 assert(sysTime == SysTime(DateTime(1999, 7, 4, 7, 9, 2), usecs(234578)));
5015 sysTime.roll!"days"(30);
5016 assert(sysTime == SysTime(DateTime(1999, 7, 3, 7, 9, 2), usecs(234578)));
5017 sysTime.roll!"days"(-3);
5018 assert(sysTime == SysTime(DateTime(1999, 7, 31, 7, 9, 2), usecs(234578)));
5019 }
5020
5021 // Test B.C.
5022 {
5023 auto sysTime = SysTime(Date(-1999, 2, 28));
5024 sysTime.roll!"days"(1);
5025 assert(sysTime == SysTime(Date(-1999, 2, 1)));
5026 sysTime.roll!"days"(-1);
5027 assert(sysTime == SysTime(Date(-1999, 2, 28)));
5028 }
5029
5030 {
5031 auto sysTime = SysTime(Date(-2000, 2, 28));
5032 sysTime.roll!"days"(1);
5033 assert(sysTime == SysTime(Date(-2000, 2, 29)));
5034 sysTime.roll!"days"(1);
5035 assert(sysTime == SysTime(Date(-2000, 2, 1)));
5036 sysTime.roll!"days"(-1);
5037 assert(sysTime == SysTime(Date(-2000, 2, 29)));
5038 }
5039
5040 {
5041 auto sysTime = SysTime(Date(-1999, 6, 30));
5042 sysTime.roll!"days"(1);
5043 assert(sysTime == SysTime(Date(-1999, 6, 1)));
5044 sysTime.roll!"days"(-1);
5045 assert(sysTime == SysTime(Date(-1999, 6, 30)));
5046 }
5047
5048 {
5049 auto sysTime = SysTime(Date(-1999, 7, 31));
5050 sysTime.roll!"days"(1);
5051 assert(sysTime == SysTime(Date(-1999, 7, 1)));
5052 sysTime.roll!"days"(-1);
5053 assert(sysTime == SysTime(Date(-1999, 7, 31)));
5054 }
5055
5056 {
5057 auto sysTime = SysTime(Date(-1999, 1, 1));
5058 sysTime.roll!"days"(-1);
5059 assert(sysTime == SysTime(Date(-1999, 1, 31)));
5060 sysTime.roll!"days"(1);
5061 assert(sysTime == SysTime(Date(-1999, 1, 1)));
5062 }
5063
5064 {
5065 auto sysTime = SysTime(Date(-1999, 7, 6));
5066 sysTime.roll!"days"(9);
5067 assert(sysTime == SysTime(Date(-1999, 7, 15)));
5068 sysTime.roll!"days"(-11);
5069 assert(sysTime == SysTime(Date(-1999, 7, 4)));
5070 sysTime.roll!"days"(30);
5071 assert(sysTime == SysTime(Date(-1999, 7, 3)));
5072 sysTime.roll!"days"(-3);
5073 assert(sysTime == SysTime(Date(-1999, 7, 31)));
5074 }
5075
5076 {
5077 auto sysTime = SysTime(Date(-1999, 7, 6));
5078 sysTime.roll!"days"(365);
5079 assert(sysTime == SysTime(Date(-1999, 7, 30)));
5080 sysTime.roll!"days"(-365);
5081 assert(sysTime == SysTime(Date(-1999, 7, 6)));
5082 sysTime.roll!"days"(366);
5083 assert(sysTime == SysTime(Date(-1999, 7, 31)));
5084 sysTime.roll!"days"(730);
5085 assert(sysTime == SysTime(Date(-1999, 7, 17)));
5086 sysTime.roll!"days"(-1096);
5087 assert(sysTime == SysTime(Date(-1999, 7, 6)));
5088 }
5089
5090 {
5091 auto sysTime = SysTime(DateTime(-1999, 2, 28, 7, 9, 2), usecs(234578));
5092 sysTime.roll!"days"(1);
5093 assert(sysTime == SysTime(DateTime(-1999, 2, 1, 7, 9, 2), usecs(234578)));
5094 sysTime.roll!"days"(-1);
5095 assert(sysTime == SysTime(DateTime(-1999, 2, 28, 7, 9, 2), usecs(234578)));
5096 }
5097
5098 {
5099 auto sysTime = SysTime(DateTime(-1999, 7, 6, 7, 9, 2), usecs(234578));
5100 sysTime.roll!"days"(9);
5101 assert(sysTime == SysTime(DateTime(-1999, 7, 15, 7, 9, 2), usecs(234578)));
5102 sysTime.roll!"days"(-11);
5103 assert(sysTime == SysTime(DateTime(-1999, 7, 4, 7, 9, 2), usecs(234578)));
5104 sysTime.roll!"days"(30);
5105 assert(sysTime == SysTime(DateTime(-1999, 7, 3, 7, 9, 2), usecs(234578)));
5106 sysTime.roll!"days"(-3);
5107 }
5108
5109 // Test Both
5110 {
5111 auto sysTime = SysTime(Date(1, 7, 6));
5112 sysTime.roll!"days"(-365);
5113 assert(sysTime == SysTime(Date(1, 7, 13)));
5114 sysTime.roll!"days"(365);
5115 assert(sysTime == SysTime(Date(1, 7, 6)));
5116 sysTime.roll!"days"(-731);
5117 assert(sysTime == SysTime(Date(1, 7, 19)));
5118 sysTime.roll!"days"(730);
5119 assert(sysTime == SysTime(Date(1, 7, 5)));
5120 }
5121
5122 {
5123 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
5124 sysTime.roll!"days"(-1);
5125 assert(sysTime == SysTime(DateTime(1, 1, 31, 0, 0, 0)));
5126 sysTime.roll!"days"(1);
5127 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5128 }
5129
5130 {
5131 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
5132 sysTime.roll!"days"(-1);
5133 assert(sysTime == SysTime(DateTime(1, 1, 31, 23, 59, 59), hnsecs(9_999_999)));
5134 sysTime.roll!"days"(1);
5135 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
5136 }
5137
5138 {
5139 auto sysTime = SysTime(DateTime(0, 12, 31, 0, 0, 0));
5140 sysTime.roll!"days"(1);
5141 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
5142 sysTime.roll!"days"(-1);
5143 assert(sysTime == SysTime(DateTime(0, 12, 31, 0, 0, 0)));
5144 }
5145
5146 {
5147 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5148 sysTime.roll!"days"(1);
5149 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
5150 sysTime.roll!"days"(-1);
5151 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5152 }
5153
5154 {
5155 auto sysTime = SysTime(DateTime(1, 7, 6, 13, 13, 9), msecs(22));
5156 sysTime.roll!"days"(-365);
5157 assert(sysTime == SysTime(DateTime(1, 7, 13, 13, 13, 9), msecs(22)));
5158 sysTime.roll!"days"(365);
5159 assert(sysTime == SysTime(DateTime(1, 7, 6, 13, 13, 9), msecs(22)));
5160 sysTime.roll!"days"(-731);
5161 assert(sysTime == SysTime(DateTime(1, 7, 19, 13, 13, 9), msecs(22)));
5162 sysTime.roll!"days"(730);
5163 assert(sysTime == SysTime(DateTime(1, 7, 5, 13, 13, 9), msecs(22)));
5164 }
5165
5166 {
5167 auto sysTime = SysTime(DateTime(0, 7, 6, 13, 13, 9), msecs(22));
5168 sysTime.roll!"days"(-365);
5169 assert(sysTime == SysTime(DateTime(0, 7, 13, 13, 13, 9), msecs(22)));
5170 sysTime.roll!"days"(365);
5171 assert(sysTime == SysTime(DateTime(0, 7, 6, 13, 13, 9), msecs(22)));
5172 sysTime.roll!"days"(-731);
5173 assert(sysTime == SysTime(DateTime(0, 7, 19, 13, 13, 9), msecs(22)));
5174 sysTime.roll!"days"(730);
5175 assert(sysTime == SysTime(DateTime(0, 7, 5, 13, 13, 9), msecs(22)));
5176 }
5177
5178 {
5179 auto sysTime = SysTime(DateTime(0, 7, 6, 13, 13, 9), msecs(22));
5180 sysTime.roll!"days"(-365).roll!"days"(362).roll!"days"(-12).roll!"days"(730);
5181 assert(sysTime == SysTime(DateTime(0, 7, 8, 13, 13, 9), msecs(22)));
5182 }
5183
5184 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5185 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5186 static assert(!__traits(compiles, cst.roll!"days"(4)));
5187 static assert(!__traits(compiles, ist.roll!"days"(4)));
5188
5189 static void testScope(scope ref SysTime st) @safe
5190 {
5191 auto result = st.roll!"days"(42);
5192 }
5193 }
5194
5195
5196 // Shares documentation with "days" version.
5197 ref SysTime roll(string units)(long value) @safe nothrow scope
5198 if (units == "hours" || units == "minutes" || units == "seconds")
5199 {
5200 try
5201 {
5202 auto hnsecs = adjTime;
5203 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
5204
5205 if (hnsecs < 0)
5206 {
5207 hnsecs += convert!("hours", "hnsecs")(24);
5208 --days;
5209 }
5210
5211 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
5212 immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
5213 immutable second = splitUnitsFromHNSecs!"seconds"(hnsecs);
5214
5215 auto dateTime = DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour,
5216 cast(int) minute, cast(int) second));
5217 dateTime.roll!units(value);
5218 --days;
5219
5220 hnsecs += convert!("hours", "hnsecs")(dateTime.hour);
5221 hnsecs += convert!("minutes", "hnsecs")(dateTime.minute);
5222 hnsecs += convert!("seconds", "hnsecs")(dateTime.second);
5223
5224 if (days < 0)
5225 {
5226 hnsecs -= convert!("hours", "hnsecs")(24);
5227 ++days;
5228 }
5229
5230 immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
5231 adjTime = newDaysHNSecs + hnsecs;
5232 return this;
5233 }
5234 catch (Exception e)
5235 assert(0, "Either DateTime's constructor or TimeOfDay's constructor threw.");
5236 }
5237
5238 // Test roll!"hours"().
5239 @safe unittest
5240 {
5241 import core.time;
5242 static void testST(SysTime orig, int hours, SysTime expected, size_t line = __LINE__) @safe
5243 {
5244 orig.roll!"hours"(hours);
5245 if (orig != expected)
5246 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
5247 }
5248
5249 // Test A.D.
5250 immutable d = msecs(45);
5251 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), d);
5252 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5253 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 13, 30, 33), d));
5254 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 14, 30, 33), d));
5255 testST(beforeAD, 3, SysTime(DateTime(1999, 7, 6, 15, 30, 33), d));
5256 testST(beforeAD, 4, SysTime(DateTime(1999, 7, 6, 16, 30, 33), d));
5257 testST(beforeAD, 5, SysTime(DateTime(1999, 7, 6, 17, 30, 33), d));
5258 testST(beforeAD, 6, SysTime(DateTime(1999, 7, 6, 18, 30, 33), d));
5259 testST(beforeAD, 7, SysTime(DateTime(1999, 7, 6, 19, 30, 33), d));
5260 testST(beforeAD, 8, SysTime(DateTime(1999, 7, 6, 20, 30, 33), d));
5261 testST(beforeAD, 9, SysTime(DateTime(1999, 7, 6, 21, 30, 33), d));
5262 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 22, 30, 33), d));
5263 testST(beforeAD, 11, SysTime(DateTime(1999, 7, 6, 23, 30, 33), d));
5264 testST(beforeAD, 12, SysTime(DateTime(1999, 7, 6, 0, 30, 33), d));
5265 testST(beforeAD, 13, SysTime(DateTime(1999, 7, 6, 1, 30, 33), d));
5266 testST(beforeAD, 14, SysTime(DateTime(1999, 7, 6, 2, 30, 33), d));
5267 testST(beforeAD, 15, SysTime(DateTime(1999, 7, 6, 3, 30, 33), d));
5268 testST(beforeAD, 16, SysTime(DateTime(1999, 7, 6, 4, 30, 33), d));
5269 testST(beforeAD, 17, SysTime(DateTime(1999, 7, 6, 5, 30, 33), d));
5270 testST(beforeAD, 18, SysTime(DateTime(1999, 7, 6, 6, 30, 33), d));
5271 testST(beforeAD, 19, SysTime(DateTime(1999, 7, 6, 7, 30, 33), d));
5272 testST(beforeAD, 20, SysTime(DateTime(1999, 7, 6, 8, 30, 33), d));
5273 testST(beforeAD, 21, SysTime(DateTime(1999, 7, 6, 9, 30, 33), d));
5274 testST(beforeAD, 22, SysTime(DateTime(1999, 7, 6, 10, 30, 33), d));
5275 testST(beforeAD, 23, SysTime(DateTime(1999, 7, 6, 11, 30, 33), d));
5276 testST(beforeAD, 24, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5277 testST(beforeAD, 25, SysTime(DateTime(1999, 7, 6, 13, 30, 33), d));
5278 testST(beforeAD, 50, SysTime(DateTime(1999, 7, 6, 14, 30, 33), d));
5279 testST(beforeAD, 10_000, SysTime(DateTime(1999, 7, 6, 4, 30, 33), d));
5280
5281 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 11, 30, 33), d));
5282 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 10, 30, 33), d));
5283 testST(beforeAD, -3, SysTime(DateTime(1999, 7, 6, 9, 30, 33), d));
5284 testST(beforeAD, -4, SysTime(DateTime(1999, 7, 6, 8, 30, 33), d));
5285 testST(beforeAD, -5, SysTime(DateTime(1999, 7, 6, 7, 30, 33), d));
5286 testST(beforeAD, -6, SysTime(DateTime(1999, 7, 6, 6, 30, 33), d));
5287 testST(beforeAD, -7, SysTime(DateTime(1999, 7, 6, 5, 30, 33), d));
5288 testST(beforeAD, -8, SysTime(DateTime(1999, 7, 6, 4, 30, 33), d));
5289 testST(beforeAD, -9, SysTime(DateTime(1999, 7, 6, 3, 30, 33), d));
5290 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 2, 30, 33), d));
5291 testST(beforeAD, -11, SysTime(DateTime(1999, 7, 6, 1, 30, 33), d));
5292 testST(beforeAD, -12, SysTime(DateTime(1999, 7, 6, 0, 30, 33), d));
5293 testST(beforeAD, -13, SysTime(DateTime(1999, 7, 6, 23, 30, 33), d));
5294 testST(beforeAD, -14, SysTime(DateTime(1999, 7, 6, 22, 30, 33), d));
5295 testST(beforeAD, -15, SysTime(DateTime(1999, 7, 6, 21, 30, 33), d));
5296 testST(beforeAD, -16, SysTime(DateTime(1999, 7, 6, 20, 30, 33), d));
5297 testST(beforeAD, -17, SysTime(DateTime(1999, 7, 6, 19, 30, 33), d));
5298 testST(beforeAD, -18, SysTime(DateTime(1999, 7, 6, 18, 30, 33), d));
5299 testST(beforeAD, -19, SysTime(DateTime(1999, 7, 6, 17, 30, 33), d));
5300 testST(beforeAD, -20, SysTime(DateTime(1999, 7, 6, 16, 30, 33), d));
5301 testST(beforeAD, -21, SysTime(DateTime(1999, 7, 6, 15, 30, 33), d));
5302 testST(beforeAD, -22, SysTime(DateTime(1999, 7, 6, 14, 30, 33), d));
5303 testST(beforeAD, -23, SysTime(DateTime(1999, 7, 6, 13, 30, 33), d));
5304 testST(beforeAD, -24, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5305 testST(beforeAD, -25, SysTime(DateTime(1999, 7, 6, 11, 30, 33), d));
5306 testST(beforeAD, -50, SysTime(DateTime(1999, 7, 6, 10, 30, 33), d));
5307 testST(beforeAD, -10_000, SysTime(DateTime(1999, 7, 6, 20, 30, 33), d));
5308
5309 testST(SysTime(DateTime(1999, 7, 6, 0, 30, 33), d), 1, SysTime(DateTime(1999, 7, 6, 1, 30, 33), d));
5310 testST(SysTime(DateTime(1999, 7, 6, 0, 30, 33), d), 0, SysTime(DateTime(1999, 7, 6, 0, 30, 33), d));
5311 testST(SysTime(DateTime(1999, 7, 6, 0, 30, 33), d), -1, SysTime(DateTime(1999, 7, 6, 23, 30, 33), d));
5312
5313 testST(SysTime(DateTime(1999, 7, 6, 23, 30, 33), d), 1, SysTime(DateTime(1999, 7, 6, 0, 30, 33), d));
5314 testST(SysTime(DateTime(1999, 7, 6, 23, 30, 33), d), 0, SysTime(DateTime(1999, 7, 6, 23, 30, 33), d));
5315 testST(SysTime(DateTime(1999, 7, 6, 23, 30, 33), d), -1, SysTime(DateTime(1999, 7, 6, 22, 30, 33), d));
5316
5317 testST(SysTime(DateTime(1999, 7, 31, 23, 30, 33), d), 1, SysTime(DateTime(1999, 7, 31, 0, 30, 33), d));
5318 testST(SysTime(DateTime(1999, 8, 1, 0, 30, 33), d), -1, SysTime(DateTime(1999, 8, 1, 23, 30, 33), d));
5319
5320 testST(SysTime(DateTime(1999, 12, 31, 23, 30, 33), d), 1, SysTime(DateTime(1999, 12, 31, 0, 30, 33), d));
5321 testST(SysTime(DateTime(2000, 1, 1, 0, 30, 33), d), -1, SysTime(DateTime(2000, 1, 1, 23, 30, 33), d));
5322
5323 testST(SysTime(DateTime(1999, 2, 28, 23, 30, 33), d), 25, SysTime(DateTime(1999, 2, 28, 0, 30, 33), d));
5324 testST(SysTime(DateTime(1999, 3, 2, 0, 30, 33), d), -25, SysTime(DateTime(1999, 3, 2, 23, 30, 33), d));
5325
5326 testST(SysTime(DateTime(2000, 2, 28, 23, 30, 33), d), 25, SysTime(DateTime(2000, 2, 28, 0, 30, 33), d));
5327 testST(SysTime(DateTime(2000, 3, 1, 0, 30, 33), d), -25, SysTime(DateTime(2000, 3, 1, 23, 30, 33), d));
5328
5329 // Test B.C.
5330 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d);
5331 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5332 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), d));
5333 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 14, 30, 33), d));
5334 testST(beforeBC, 3, SysTime(DateTime(-1999, 7, 6, 15, 30, 33), d));
5335 testST(beforeBC, 4, SysTime(DateTime(-1999, 7, 6, 16, 30, 33), d));
5336 testST(beforeBC, 5, SysTime(DateTime(-1999, 7, 6, 17, 30, 33), d));
5337 testST(beforeBC, 6, SysTime(DateTime(-1999, 7, 6, 18, 30, 33), d));
5338 testST(beforeBC, 7, SysTime(DateTime(-1999, 7, 6, 19, 30, 33), d));
5339 testST(beforeBC, 8, SysTime(DateTime(-1999, 7, 6, 20, 30, 33), d));
5340 testST(beforeBC, 9, SysTime(DateTime(-1999, 7, 6, 21, 30, 33), d));
5341 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 22, 30, 33), d));
5342 testST(beforeBC, 11, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d));
5343 testST(beforeBC, 12, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d));
5344 testST(beforeBC, 13, SysTime(DateTime(-1999, 7, 6, 1, 30, 33), d));
5345 testST(beforeBC, 14, SysTime(DateTime(-1999, 7, 6, 2, 30, 33), d));
5346 testST(beforeBC, 15, SysTime(DateTime(-1999, 7, 6, 3, 30, 33), d));
5347 testST(beforeBC, 16, SysTime(DateTime(-1999, 7, 6, 4, 30, 33), d));
5348 testST(beforeBC, 17, SysTime(DateTime(-1999, 7, 6, 5, 30, 33), d));
5349 testST(beforeBC, 18, SysTime(DateTime(-1999, 7, 6, 6, 30, 33), d));
5350 testST(beforeBC, 19, SysTime(DateTime(-1999, 7, 6, 7, 30, 33), d));
5351 testST(beforeBC, 20, SysTime(DateTime(-1999, 7, 6, 8, 30, 33), d));
5352 testST(beforeBC, 21, SysTime(DateTime(-1999, 7, 6, 9, 30, 33), d));
5353 testST(beforeBC, 22, SysTime(DateTime(-1999, 7, 6, 10, 30, 33), d));
5354 testST(beforeBC, 23, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), d));
5355 testST(beforeBC, 24, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5356 testST(beforeBC, 25, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), d));
5357 testST(beforeBC, 50, SysTime(DateTime(-1999, 7, 6, 14, 30, 33), d));
5358 testST(beforeBC, 10_000, SysTime(DateTime(-1999, 7, 6, 4, 30, 33), d));
5359
5360 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), d));
5361 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 10, 30, 33), d));
5362 testST(beforeBC, -3, SysTime(DateTime(-1999, 7, 6, 9, 30, 33), d));
5363 testST(beforeBC, -4, SysTime(DateTime(-1999, 7, 6, 8, 30, 33), d));
5364 testST(beforeBC, -5, SysTime(DateTime(-1999, 7, 6, 7, 30, 33), d));
5365 testST(beforeBC, -6, SysTime(DateTime(-1999, 7, 6, 6, 30, 33), d));
5366 testST(beforeBC, -7, SysTime(DateTime(-1999, 7, 6, 5, 30, 33), d));
5367 testST(beforeBC, -8, SysTime(DateTime(-1999, 7, 6, 4, 30, 33), d));
5368 testST(beforeBC, -9, SysTime(DateTime(-1999, 7, 6, 3, 30, 33), d));
5369 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 2, 30, 33), d));
5370 testST(beforeBC, -11, SysTime(DateTime(-1999, 7, 6, 1, 30, 33), d));
5371 testST(beforeBC, -12, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d));
5372 testST(beforeBC, -13, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d));
5373 testST(beforeBC, -14, SysTime(DateTime(-1999, 7, 6, 22, 30, 33), d));
5374 testST(beforeBC, -15, SysTime(DateTime(-1999, 7, 6, 21, 30, 33), d));
5375 testST(beforeBC, -16, SysTime(DateTime(-1999, 7, 6, 20, 30, 33), d));
5376 testST(beforeBC, -17, SysTime(DateTime(-1999, 7, 6, 19, 30, 33), d));
5377 testST(beforeBC, -18, SysTime(DateTime(-1999, 7, 6, 18, 30, 33), d));
5378 testST(beforeBC, -19, SysTime(DateTime(-1999, 7, 6, 17, 30, 33), d));
5379 testST(beforeBC, -20, SysTime(DateTime(-1999, 7, 6, 16, 30, 33), d));
5380 testST(beforeBC, -21, SysTime(DateTime(-1999, 7, 6, 15, 30, 33), d));
5381 testST(beforeBC, -22, SysTime(DateTime(-1999, 7, 6, 14, 30, 33), d));
5382 testST(beforeBC, -23, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), d));
5383 testST(beforeBC, -24, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5384 testST(beforeBC, -25, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), d));
5385 testST(beforeBC, -50, SysTime(DateTime(-1999, 7, 6, 10, 30, 33), d));
5386 testST(beforeBC, -10_000, SysTime(DateTime(-1999, 7, 6, 20, 30, 33), d));
5387
5388 testST(SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d), 1, SysTime(DateTime(-1999, 7, 6, 1, 30, 33), d));
5389 testST(SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d), 0, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d));
5390 testST(SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d), -1, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d));
5391
5392 testST(SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d), 1, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d));
5393 testST(SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d), 0, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d));
5394 testST(SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d), -1, SysTime(DateTime(-1999, 7, 6, 22, 30, 33), d));
5395
5396 testST(SysTime(DateTime(-1999, 7, 31, 23, 30, 33), d), 1, SysTime(DateTime(-1999, 7, 31, 0, 30, 33), d));
5397 testST(SysTime(DateTime(-1999, 8, 1, 0, 30, 33), d), -1, SysTime(DateTime(-1999, 8, 1, 23, 30, 33), d));
5398
5399 testST(SysTime(DateTime(-2001, 12, 31, 23, 30, 33), d), 1, SysTime(DateTime(-2001, 12, 31, 0, 30, 33), d));
5400 testST(SysTime(DateTime(-2000, 1, 1, 0, 30, 33), d), -1, SysTime(DateTime(-2000, 1, 1, 23, 30, 33), d));
5401
5402 testST(SysTime(DateTime(-2001, 2, 28, 23, 30, 33), d), 25, SysTime(DateTime(-2001, 2, 28, 0, 30, 33), d));
5403 testST(SysTime(DateTime(-2001, 3, 2, 0, 30, 33), d), -25, SysTime(DateTime(-2001, 3, 2, 23, 30, 33), d));
5404
5405 testST(SysTime(DateTime(-2000, 2, 28, 23, 30, 33), d), 25, SysTime(DateTime(-2000, 2, 28, 0, 30, 33), d));
5406 testST(SysTime(DateTime(-2000, 3, 1, 0, 30, 33), d), -25, SysTime(DateTime(-2000, 3, 1, 23, 30, 33), d));
5407
5408 // Test Both
5409 testST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), d), 17_546, SysTime(DateTime(-1, 1, 1, 13, 30, 33), d));
5410 testST(SysTime(DateTime(1, 1, 1, 13, 30, 33), d), -17_546, SysTime(DateTime(1, 1, 1, 11, 30, 33), d));
5411
5412 {
5413 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
5414 sysTime.roll!"hours"(-1);
5415 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 0, 0)));
5416 sysTime.roll!"hours"(1);
5417 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5418 }
5419
5420 {
5421 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 59, 59), hnsecs(9_999_999));
5422 sysTime.roll!"hours"(-1);
5423 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
5424 sysTime.roll!"hours"(1);
5425 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 59, 59), hnsecs(9_999_999)));
5426 }
5427
5428 {
5429 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 0, 0));
5430 sysTime.roll!"hours"(1);
5431 assert(sysTime == SysTime(DateTime(0, 12, 31, 0, 0, 0)));
5432 sysTime.roll!"hours"(-1);
5433 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 0, 0)));
5434 }
5435
5436 {
5437 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5438 sysTime.roll!"hours"(1);
5439 assert(sysTime == SysTime(DateTime(0, 12, 31, 0, 59, 59), hnsecs(9_999_999)));
5440 sysTime.roll!"hours"(-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!"hours"(1).roll!"hours"(-67);
5447 assert(sysTime == SysTime(DateTime(0, 12, 31, 5, 59, 59), 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!"hours"(4)));
5453 static assert(!__traits(compiles, ist.roll!"hours"(4)));
5454
5455 static void testScope(scope ref SysTime st) @safe
5456 {
5457 auto result = st.roll!"hours"(42);
5458 }
5459 }
5460
5461 // Test roll!"minutes"().
5462 @safe unittest
5463 {
5464 import core.time;
5465 static void testST(SysTime orig, int minutes, SysTime expected, size_t line = __LINE__) @safe
5466 {
5467 orig.roll!"minutes"(minutes);
5468 if (orig != expected)
5469 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
5470 }
5471
5472 // Test A.D.
5473 immutable d = usecs(7203);
5474 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), d);
5475 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5476 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 31, 33), d));
5477 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 32, 33), d));
5478 testST(beforeAD, 3, SysTime(DateTime(1999, 7, 6, 12, 33, 33), d));
5479 testST(beforeAD, 4, SysTime(DateTime(1999, 7, 6, 12, 34, 33), d));
5480 testST(beforeAD, 5, SysTime(DateTime(1999, 7, 6, 12, 35, 33), d));
5481 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 40, 33), d));
5482 testST(beforeAD, 15, SysTime(DateTime(1999, 7, 6, 12, 45, 33), d));
5483 testST(beforeAD, 29, SysTime(DateTime(1999, 7, 6, 12, 59, 33), d));
5484 testST(beforeAD, 30, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5485 testST(beforeAD, 45, SysTime(DateTime(1999, 7, 6, 12, 15, 33), d));
5486 testST(beforeAD, 60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5487 testST(beforeAD, 75, SysTime(DateTime(1999, 7, 6, 12, 45, 33), d));
5488 testST(beforeAD, 90, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5489 testST(beforeAD, 100, SysTime(DateTime(1999, 7, 6, 12, 10, 33), d));
5490
5491 testST(beforeAD, 689, SysTime(DateTime(1999, 7, 6, 12, 59, 33), d));
5492 testST(beforeAD, 690, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5493 testST(beforeAD, 691, SysTime(DateTime(1999, 7, 6, 12, 1, 33), d));
5494 testST(beforeAD, 960, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5495 testST(beforeAD, 1439, SysTime(DateTime(1999, 7, 6, 12, 29, 33), d));
5496 testST(beforeAD, 1440, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5497 testST(beforeAD, 1441, SysTime(DateTime(1999, 7, 6, 12, 31, 33), d));
5498 testST(beforeAD, 2880, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5499
5500 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 29, 33), d));
5501 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 28, 33), d));
5502 testST(beforeAD, -3, SysTime(DateTime(1999, 7, 6, 12, 27, 33), d));
5503 testST(beforeAD, -4, SysTime(DateTime(1999, 7, 6, 12, 26, 33), d));
5504 testST(beforeAD, -5, SysTime(DateTime(1999, 7, 6, 12, 25, 33), d));
5505 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 20, 33), d));
5506 testST(beforeAD, -15, SysTime(DateTime(1999, 7, 6, 12, 15, 33), d));
5507 testST(beforeAD, -29, SysTime(DateTime(1999, 7, 6, 12, 1, 33), d));
5508 testST(beforeAD, -30, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5509 testST(beforeAD, -45, SysTime(DateTime(1999, 7, 6, 12, 45, 33), d));
5510 testST(beforeAD, -60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5511 testST(beforeAD, -75, SysTime(DateTime(1999, 7, 6, 12, 15, 33), d));
5512 testST(beforeAD, -90, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5513 testST(beforeAD, -100, SysTime(DateTime(1999, 7, 6, 12, 50, 33), d));
5514
5515 testST(beforeAD, -749, SysTime(DateTime(1999, 7, 6, 12, 1, 33), d));
5516 testST(beforeAD, -750, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5517 testST(beforeAD, -751, SysTime(DateTime(1999, 7, 6, 12, 59, 33), d));
5518 testST(beforeAD, -960, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5519 testST(beforeAD, -1439, SysTime(DateTime(1999, 7, 6, 12, 31, 33), d));
5520 testST(beforeAD, -1440, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5521 testST(beforeAD, -1441, SysTime(DateTime(1999, 7, 6, 12, 29, 33), d));
5522 testST(beforeAD, -2880, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5523
5524 testST(SysTime(DateTime(1999, 7, 6, 12, 0, 33), d), 1, SysTime(DateTime(1999, 7, 6, 12, 1, 33), d));
5525 testST(SysTime(DateTime(1999, 7, 6, 12, 0, 33), d), 0, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5526 testST(SysTime(DateTime(1999, 7, 6, 12, 0, 33), d), -1, SysTime(DateTime(1999, 7, 6, 12, 59, 33), d));
5527
5528 testST(SysTime(DateTime(1999, 7, 6, 11, 59, 33), d), 1, SysTime(DateTime(1999, 7, 6, 11, 0, 33), d));
5529 testST(SysTime(DateTime(1999, 7, 6, 11, 59, 33), d), 0, SysTime(DateTime(1999, 7, 6, 11, 59, 33), d));
5530 testST(SysTime(DateTime(1999, 7, 6, 11, 59, 33), d), -1, SysTime(DateTime(1999, 7, 6, 11, 58, 33), d));
5531
5532 testST(SysTime(DateTime(1999, 7, 6, 0, 0, 33), d), 1, SysTime(DateTime(1999, 7, 6, 0, 1, 33), d));
5533 testST(SysTime(DateTime(1999, 7, 6, 0, 0, 33), d), 0, SysTime(DateTime(1999, 7, 6, 0, 0, 33), d));
5534 testST(SysTime(DateTime(1999, 7, 6, 0, 0, 33), d), -1, SysTime(DateTime(1999, 7, 6, 0, 59, 33), d));
5535
5536 testST(SysTime(DateTime(1999, 7, 5, 23, 59, 33), d), 1, SysTime(DateTime(1999, 7, 5, 23, 0, 33), d));
5537 testST(SysTime(DateTime(1999, 7, 5, 23, 59, 33), d), 0, SysTime(DateTime(1999, 7, 5, 23, 59, 33), d));
5538 testST(SysTime(DateTime(1999, 7, 5, 23, 59, 33), d), -1, SysTime(DateTime(1999, 7, 5, 23, 58, 33), d));
5539
5540 testST(SysTime(DateTime(1998, 12, 31, 23, 59, 33), d), 1, SysTime(DateTime(1998, 12, 31, 23, 0, 33), d));
5541 testST(SysTime(DateTime(1998, 12, 31, 23, 59, 33), d), 0, SysTime(DateTime(1998, 12, 31, 23, 59, 33), d));
5542 testST(SysTime(DateTime(1998, 12, 31, 23, 59, 33), d), -1, SysTime(DateTime(1998, 12, 31, 23, 58, 33), d));
5543
5544 // Test B.C.
5545 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d);
5546 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5547 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), d));
5548 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 32, 33), d));
5549 testST(beforeBC, 3, SysTime(DateTime(-1999, 7, 6, 12, 33, 33), d));
5550 testST(beforeBC, 4, SysTime(DateTime(-1999, 7, 6, 12, 34, 33), d));
5551 testST(beforeBC, 5, SysTime(DateTime(-1999, 7, 6, 12, 35, 33), d));
5552 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 40, 33), d));
5553 testST(beforeBC, 15, SysTime(DateTime(-1999, 7, 6, 12, 45, 33), d));
5554 testST(beforeBC, 29, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), d));
5555 testST(beforeBC, 30, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5556 testST(beforeBC, 45, SysTime(DateTime(-1999, 7, 6, 12, 15, 33), d));
5557 testST(beforeBC, 60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5558 testST(beforeBC, 75, SysTime(DateTime(-1999, 7, 6, 12, 45, 33), d));
5559 testST(beforeBC, 90, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5560 testST(beforeBC, 100, SysTime(DateTime(-1999, 7, 6, 12, 10, 33), d));
5561
5562 testST(beforeBC, 689, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), d));
5563 testST(beforeBC, 690, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5564 testST(beforeBC, 691, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), d));
5565 testST(beforeBC, 960, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5566 testST(beforeBC, 1439, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), d));
5567 testST(beforeBC, 1440, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5568 testST(beforeBC, 1441, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), d));
5569 testST(beforeBC, 2880, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5570
5571 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), d));
5572 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 28, 33), d));
5573 testST(beforeBC, -3, SysTime(DateTime(-1999, 7, 6, 12, 27, 33), d));
5574 testST(beforeBC, -4, SysTime(DateTime(-1999, 7, 6, 12, 26, 33), d));
5575 testST(beforeBC, -5, SysTime(DateTime(-1999, 7, 6, 12, 25, 33), d));
5576 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 20, 33), d));
5577 testST(beforeBC, -15, SysTime(DateTime(-1999, 7, 6, 12, 15, 33), d));
5578 testST(beforeBC, -29, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), d));
5579 testST(beforeBC, -30, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5580 testST(beforeBC, -45, SysTime(DateTime(-1999, 7, 6, 12, 45, 33), d));
5581 testST(beforeBC, -60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5582 testST(beforeBC, -75, SysTime(DateTime(-1999, 7, 6, 12, 15, 33), d));
5583 testST(beforeBC, -90, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5584 testST(beforeBC, -100, SysTime(DateTime(-1999, 7, 6, 12, 50, 33), d));
5585
5586 testST(beforeBC, -749, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), d));
5587 testST(beforeBC, -750, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5588 testST(beforeBC, -751, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), d));
5589 testST(beforeBC, -960, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5590 testST(beforeBC, -1439, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), d));
5591 testST(beforeBC, -1440, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5592 testST(beforeBC, -1441, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), d));
5593 testST(beforeBC, -2880, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5594
5595 testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d), 1, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), d));
5596 testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d), 0, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5597 testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d), -1, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), d));
5598
5599 testST(SysTime(DateTime(-1999, 7, 6, 11, 59, 33), d), 1, SysTime(DateTime(-1999, 7, 6, 11, 0, 33), d));
5600 testST(SysTime(DateTime(-1999, 7, 6, 11, 59, 33), d), 0, SysTime(DateTime(-1999, 7, 6, 11, 59, 33), d));
5601 testST(SysTime(DateTime(-1999, 7, 6, 11, 59, 33), d), -1, SysTime(DateTime(-1999, 7, 6, 11, 58, 33), d));
5602
5603 testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 33), d), 1, SysTime(DateTime(-1999, 7, 6, 0, 1, 33), d));
5604 testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 33), d), 0, SysTime(DateTime(-1999, 7, 6, 0, 0, 33), d));
5605 testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 33), d), -1, SysTime(DateTime(-1999, 7, 6, 0, 59, 33), d));
5606
5607 testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 33), d), 1, SysTime(DateTime(-1999, 7, 5, 23, 0, 33), d));
5608 testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 33), d), 0, SysTime(DateTime(-1999, 7, 5, 23, 59, 33), d));
5609 testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 33), d), -1, SysTime(DateTime(-1999, 7, 5, 23, 58, 33), d));
5610
5611 testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 33), d), 1, SysTime(DateTime(-2000, 12, 31, 23, 0, 33), d));
5612 testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 33), d), 0, SysTime(DateTime(-2000, 12, 31, 23, 59, 33), d));
5613 testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 33), d), -1, SysTime(DateTime(-2000, 12, 31, 23, 58, 33), d));
5614
5615 // Test Both
5616 testST(SysTime(DateTime(1, 1, 1, 0, 0, 0)), -1, SysTime(DateTime(1, 1, 1, 0, 59, 0)));
5617 testST(SysTime(DateTime(0, 12, 31, 23, 59, 0)), 1, SysTime(DateTime(0, 12, 31, 23, 0, 0)));
5618
5619 testST(SysTime(DateTime(0, 1, 1, 0, 0, 0)), -1, SysTime(DateTime(0, 1, 1, 0, 59, 0)));
5620 testST(SysTime(DateTime(-1, 12, 31, 23, 59, 0)), 1, SysTime(DateTime(-1, 12, 31, 23, 0, 0)));
5621
5622 testST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), d), 1_052_760, SysTime(DateTime(-1, 1, 1, 11, 30, 33), d));
5623 testST(SysTime(DateTime(1, 1, 1, 13, 30, 33), d), -1_052_760, SysTime(DateTime(1, 1, 1, 13, 30, 33), d));
5624
5625 testST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), d), 1_052_782, SysTime(DateTime(-1, 1, 1, 11, 52, 33), d));
5626 testST(SysTime(DateTime(1, 1, 1, 13, 52, 33), d), -1_052_782, SysTime(DateTime(1, 1, 1, 13, 30, 33), d));
5627
5628 {
5629 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
5630 sysTime.roll!"minutes"(-1);
5631 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 59, 0)));
5632 sysTime.roll!"minutes"(1);
5633 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5634 }
5635
5636 {
5637 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 59), hnsecs(9_999_999));
5638 sysTime.roll!"minutes"(-1);
5639 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 59, 59), hnsecs(9_999_999)));
5640 sysTime.roll!"minutes"(1);
5641 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 59), hnsecs(9_999_999)));
5642 }
5643
5644 {
5645 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 0));
5646 sysTime.roll!"minutes"(1);
5647 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 0, 0)));
5648 sysTime.roll!"minutes"(-1);
5649 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 0)));
5650 }
5651
5652 {
5653 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5654 sysTime.roll!"minutes"(1);
5655 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 0, 59), hnsecs(9_999_999)));
5656 sysTime.roll!"minutes"(-1);
5657 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5658 }
5659
5660 {
5661 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5662 sysTime.roll!"minutes"(1).roll!"minutes"(-79);
5663 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 41, 59), hnsecs(9_999_999)));
5664 }
5665
5666 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5667 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5668 static assert(!__traits(compiles, cst.roll!"minutes"(4)));
5669 static assert(!__traits(compiles, ist.roll!"minutes"(4)));
5670
5671 static void testScope(scope ref SysTime st) @safe
5672 {
5673 auto result = st.roll!"minutes"(42);
5674 }
5675 }
5676
5677 // Test roll!"seconds"().
5678 @safe unittest
5679 {
5680 import core.time;
5681 static void testST(SysTime orig, int seconds, SysTime expected, size_t line = __LINE__) @safe
5682 {
5683 orig.roll!"seconds"(seconds);
5684 if (orig != expected)
5685 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
5686 }
5687
5688 // Test A.D.
5689 immutable d = msecs(274);
5690 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), d);
5691 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5692 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 30, 34), d));
5693 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 30, 35), d));
5694 testST(beforeAD, 3, SysTime(DateTime(1999, 7, 6, 12, 30, 36), d));
5695 testST(beforeAD, 4, SysTime(DateTime(1999, 7, 6, 12, 30, 37), d));
5696 testST(beforeAD, 5, SysTime(DateTime(1999, 7, 6, 12, 30, 38), d));
5697 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 30, 43), d));
5698 testST(beforeAD, 15, SysTime(DateTime(1999, 7, 6, 12, 30, 48), d));
5699 testST(beforeAD, 26, SysTime(DateTime(1999, 7, 6, 12, 30, 59), d));
5700 testST(beforeAD, 27, SysTime(DateTime(1999, 7, 6, 12, 30, 0), d));
5701 testST(beforeAD, 30, SysTime(DateTime(1999, 7, 6, 12, 30, 3), d));
5702 testST(beforeAD, 59, SysTime(DateTime(1999, 7, 6, 12, 30, 32), d));
5703 testST(beforeAD, 60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5704 testST(beforeAD, 61, SysTime(DateTime(1999, 7, 6, 12, 30, 34), d));
5705
5706 testST(beforeAD, 1766, SysTime(DateTime(1999, 7, 6, 12, 30, 59), d));
5707 testST(beforeAD, 1767, SysTime(DateTime(1999, 7, 6, 12, 30, 0), d));
5708 testST(beforeAD, 1768, SysTime(DateTime(1999, 7, 6, 12, 30, 1), d));
5709 testST(beforeAD, 2007, SysTime(DateTime(1999, 7, 6, 12, 30, 0), d));
5710 testST(beforeAD, 3599, SysTime(DateTime(1999, 7, 6, 12, 30, 32), d));
5711 testST(beforeAD, 3600, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5712 testST(beforeAD, 3601, SysTime(DateTime(1999, 7, 6, 12, 30, 34), d));
5713 testST(beforeAD, 7200, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5714
5715 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 30, 32), d));
5716 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 30, 31), d));
5717 testST(beforeAD, -3, SysTime(DateTime(1999, 7, 6, 12, 30, 30), d));
5718 testST(beforeAD, -4, SysTime(DateTime(1999, 7, 6, 12, 30, 29), d));
5719 testST(beforeAD, -5, SysTime(DateTime(1999, 7, 6, 12, 30, 28), d));
5720 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 30, 23), d));
5721 testST(beforeAD, -15, SysTime(DateTime(1999, 7, 6, 12, 30, 18), d));
5722 testST(beforeAD, -33, SysTime(DateTime(1999, 7, 6, 12, 30, 0), d));
5723 testST(beforeAD, -34, SysTime(DateTime(1999, 7, 6, 12, 30, 59), d));
5724 testST(beforeAD, -35, SysTime(DateTime(1999, 7, 6, 12, 30, 58), d));
5725 testST(beforeAD, -59, SysTime(DateTime(1999, 7, 6, 12, 30, 34), d));
5726 testST(beforeAD, -60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5727 testST(beforeAD, -61, SysTime(DateTime(1999, 7, 6, 12, 30, 32), d));
5728
5729 testST(SysTime(DateTime(1999, 7, 6, 12, 30, 0), d), 1, SysTime(DateTime(1999, 7, 6, 12, 30, 1), d));
5730 testST(SysTime(DateTime(1999, 7, 6, 12, 30, 0), d), 0, SysTime(DateTime(1999, 7, 6, 12, 30, 0), d));
5731 testST(SysTime(DateTime(1999, 7, 6, 12, 30, 0), d), -1, SysTime(DateTime(1999, 7, 6, 12, 30, 59), d));
5732
5733 testST(SysTime(DateTime(1999, 7, 6, 12, 0, 0), d), 1, SysTime(DateTime(1999, 7, 6, 12, 0, 1), d));
5734 testST(SysTime(DateTime(1999, 7, 6, 12, 0, 0), d), 0, SysTime(DateTime(1999, 7, 6, 12, 0, 0), d));
5735 testST(SysTime(DateTime(1999, 7, 6, 12, 0, 0), d), -1, SysTime(DateTime(1999, 7, 6, 12, 0, 59), d));
5736
5737 testST(SysTime(DateTime(1999, 7, 6, 0, 0, 0), d), 1, SysTime(DateTime(1999, 7, 6, 0, 0, 1), d));
5738 testST(SysTime(DateTime(1999, 7, 6, 0, 0, 0), d), 0, SysTime(DateTime(1999, 7, 6, 0, 0, 0), d));
5739 testST(SysTime(DateTime(1999, 7, 6, 0, 0, 0), d), -1, SysTime(DateTime(1999, 7, 6, 0, 0, 59), d));
5740
5741 testST(SysTime(DateTime(1999, 7, 5, 23, 59, 59), d), 1, SysTime(DateTime(1999, 7, 5, 23, 59, 0), d));
5742 testST(SysTime(DateTime(1999, 7, 5, 23, 59, 59), d), 0, SysTime(DateTime(1999, 7, 5, 23, 59, 59), d));
5743 testST(SysTime(DateTime(1999, 7, 5, 23, 59, 59), d), -1, SysTime(DateTime(1999, 7, 5, 23, 59, 58), d));
5744
5745 testST(SysTime(DateTime(1998, 12, 31, 23, 59, 59), d), 1, SysTime(DateTime(1998, 12, 31, 23, 59, 0), d));
5746 testST(SysTime(DateTime(1998, 12, 31, 23, 59, 59), d), 0, SysTime(DateTime(1998, 12, 31, 23, 59, 59), d));
5747 testST(SysTime(DateTime(1998, 12, 31, 23, 59, 59), d), -1, SysTime(DateTime(1998, 12, 31, 23, 59, 58), d));
5748
5749 // Test B.C.
5750 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d);
5751 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5752 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), d));
5753 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 35), d));
5754 testST(beforeBC, 3, SysTime(DateTime(-1999, 7, 6, 12, 30, 36), d));
5755 testST(beforeBC, 4, SysTime(DateTime(-1999, 7, 6, 12, 30, 37), d));
5756 testST(beforeBC, 5, SysTime(DateTime(-1999, 7, 6, 12, 30, 38), d));
5757 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 43), d));
5758 testST(beforeBC, 15, SysTime(DateTime(-1999, 7, 6, 12, 30, 48), d));
5759 testST(beforeBC, 26, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), d));
5760 testST(beforeBC, 27, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d));
5761 testST(beforeBC, 30, SysTime(DateTime(-1999, 7, 6, 12, 30, 3), d));
5762 testST(beforeBC, 59, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), d));
5763 testST(beforeBC, 60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5764 testST(beforeBC, 61, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), d));
5765
5766 testST(beforeBC, 1766, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), d));
5767 testST(beforeBC, 1767, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d));
5768 testST(beforeBC, 1768, SysTime(DateTime(-1999, 7, 6, 12, 30, 1), d));
5769 testST(beforeBC, 2007, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d));
5770 testST(beforeBC, 3599, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), d));
5771 testST(beforeBC, 3600, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5772 testST(beforeBC, 3601, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), d));
5773 testST(beforeBC, 7200, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5774
5775 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), d));
5776 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 31), d));
5777 testST(beforeBC, -3, SysTime(DateTime(-1999, 7, 6, 12, 30, 30), d));
5778 testST(beforeBC, -4, SysTime(DateTime(-1999, 7, 6, 12, 30, 29), d));
5779 testST(beforeBC, -5, SysTime(DateTime(-1999, 7, 6, 12, 30, 28), d));
5780 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 23), d));
5781 testST(beforeBC, -15, SysTime(DateTime(-1999, 7, 6, 12, 30, 18), d));
5782 testST(beforeBC, -33, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d));
5783 testST(beforeBC, -34, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), d));
5784 testST(beforeBC, -35, SysTime(DateTime(-1999, 7, 6, 12, 30, 58), d));
5785 testST(beforeBC, -59, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), d));
5786 testST(beforeBC, -60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5787 testST(beforeBC, -61, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), d));
5788
5789 testST(SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d), 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 1), d));
5790 testST(SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d), 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d));
5791 testST(SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d), -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), d));
5792
5793 testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 0), d), 1, SysTime(DateTime(-1999, 7, 6, 12, 0, 1), d));
5794 testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 0), d), 0, SysTime(DateTime(-1999, 7, 6, 12, 0, 0), d));
5795 testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 0), d), -1, SysTime(DateTime(-1999, 7, 6, 12, 0, 59), d));
5796
5797 testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 0), d), 1, SysTime(DateTime(-1999, 7, 6, 0, 0, 1), d));
5798 testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 0), d), 0, SysTime(DateTime(-1999, 7, 6, 0, 0, 0), d));
5799 testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 0), d), -1, SysTime(DateTime(-1999, 7, 6, 0, 0, 59), d));
5800
5801 testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 59), d), 1, SysTime(DateTime(-1999, 7, 5, 23, 59, 0), d));
5802 testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 59), d), 0, SysTime(DateTime(-1999, 7, 5, 23, 59, 59), d));
5803 testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 59), d), -1, SysTime(DateTime(-1999, 7, 5, 23, 59, 58), d));
5804
5805 testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 59), d), 1, SysTime(DateTime(-2000, 12, 31, 23, 59, 0), d));
5806 testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 59), d), 0, SysTime(DateTime(-2000, 12, 31, 23, 59, 59), d));
5807 testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 59), d), -1, SysTime(DateTime(-2000, 12, 31, 23, 59, 58), d));
5808
5809 // Test Both
5810 testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), d), -1, SysTime(DateTime(1, 1, 1, 0, 0, 59), d));
5811 testST(SysTime(DateTime(0, 12, 31, 23, 59, 59), d), 1, SysTime(DateTime(0, 12, 31, 23, 59, 0), d));
5812
5813 testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), d), -1, SysTime(DateTime(0, 1, 1, 0, 0, 59), d));
5814 testST(SysTime(DateTime(-1, 12, 31, 23, 59, 59), d), 1, SysTime(DateTime(-1, 12, 31, 23, 59, 0), d));
5815
5816 testST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), d), 63_165_600L, SysTime(DateTime(-1, 1, 1, 11, 30, 33), d));
5817 testST(SysTime(DateTime(1, 1, 1, 13, 30, 33), d), -63_165_600L, SysTime(DateTime(1, 1, 1, 13, 30, 33), d));
5818
5819 testST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), d), 63_165_617L, SysTime(DateTime(-1, 1, 1, 11, 30, 50), d));
5820 testST(SysTime(DateTime(1, 1, 1, 13, 30, 50), d), -63_165_617L, SysTime(DateTime(1, 1, 1, 13, 30, 33), d));
5821
5822 {
5823 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
5824 sysTime.roll!"seconds"(-1);
5825 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 59)));
5826 sysTime.roll!"seconds"(1);
5827 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5828 }
5829
5830 {
5831 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(9_999_999));
5832 sysTime.roll!"seconds"(-1);
5833 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 59), hnsecs(9_999_999)));
5834 sysTime.roll!"seconds"(1);
5835 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
5836 }
5837
5838 {
5839 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59));
5840 sysTime.roll!"seconds"(1);
5841 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 0)));
5842 sysTime.roll!"seconds"(-1);
5843 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 59)));
5844 }
5845
5846 {
5847 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5848 sysTime.roll!"seconds"(1);
5849 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 0), hnsecs(9_999_999)));
5850 sysTime.roll!"seconds"(-1);
5851 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5852 }
5853
5854 {
5855 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5856 sysTime.roll!"seconds"(1).roll!"seconds"(-102);
5857 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 18), hnsecs(9_999_999)));
5858 }
5859
5860 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5861 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5862 static assert(!__traits(compiles, cst.roll!"seconds"(4)));
5863 static assert(!__traits(compiles, ist.roll!"seconds"(4)));
5864
5865 static void testScope(scope ref SysTime st) @safe
5866 {
5867 auto result = st.roll!"seconds"(42);
5868 }
5869 }
5870
5871
5872 // Shares documentation with "days" version.
5873 ref SysTime roll(string units)(long value) @safe nothrow scope
5874 if (units == "msecs" || units == "usecs" || units == "hnsecs")
5875 {
5876 auto hnsecs = adjTime;
5877 immutable days = splitUnitsFromHNSecs!"days"(hnsecs);
5878 immutable negative = hnsecs < 0;
5879
5880 if (negative)
5881 hnsecs += convert!("hours", "hnsecs")(24);
5882
5883 immutable seconds = splitUnitsFromHNSecs!"seconds"(hnsecs);
5884 hnsecs += convert!(units, "hnsecs")(value);
5885 hnsecs %= convert!("seconds", "hnsecs")(1);
5886
5887 if (hnsecs < 0)
5888 hnsecs += convert!("seconds", "hnsecs")(1);
5889 hnsecs += convert!("seconds", "hnsecs")(seconds);
5890
5891 if (negative)
5892 hnsecs -= convert!("hours", "hnsecs")(24);
5893
5894 immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
5895 adjTime = newDaysHNSecs + hnsecs;
5896 return this;
5897 }
5898
5899
5900 // Test roll!"msecs"().
5901 @safe unittest
5902 {
5903 import core.time;
5904 static void testST(SysTime orig, int milliseconds, SysTime expected, size_t line = __LINE__) @safe
5905 {
5906 orig.roll!"msecs"(milliseconds);
5907 if (orig != expected)
5908 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
5909 }
5910
5911 // Test A.D.
5912 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274));
5913 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274)));
5914 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(275)));
5915 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(276)));
5916 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(284)));
5917 testST(beforeAD, 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(374)));
5918 testST(beforeAD, 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999)));
5919 testST(beforeAD, 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5920 testST(beforeAD, 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274)));
5921 testST(beforeAD, 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(275)));
5922 testST(beforeAD, 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274)));
5923 testST(beforeAD, 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999)));
5924 testST(beforeAD, 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5925 testST(beforeAD, 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(1)));
5926 testST(beforeAD, 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999)));
5927 testST(beforeAD, 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5928
5929 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(273)));
5930 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(272)));
5931 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(264)));
5932 testST(beforeAD, -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(174)));
5933 testST(beforeAD, -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5934 testST(beforeAD, -275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999)));
5935 testST(beforeAD, -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274)));
5936 testST(beforeAD, -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(273)));
5937 testST(beforeAD, -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274)));
5938 testST(beforeAD, -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5939 testST(beforeAD, -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999)));
5940 testST(beforeAD, -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5941 testST(beforeAD, -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999)));
5942
5943 // Test B.C.
5944 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274));
5945 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274)));
5946 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(275)));
5947 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(276)));
5948 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(284)));
5949 testST(beforeBC, 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(374)));
5950 testST(beforeBC, 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999)));
5951 testST(beforeBC, 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5952 testST(beforeBC, 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274)));
5953 testST(beforeBC, 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(275)));
5954 testST(beforeBC, 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274)));
5955 testST(beforeBC, 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999)));
5956 testST(beforeBC, 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5957 testST(beforeBC, 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(1)));
5958 testST(beforeBC, 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999)));
5959 testST(beforeBC, 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5960
5961 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(273)));
5962 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(272)));
5963 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(264)));
5964 testST(beforeBC, -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(174)));
5965 testST(beforeBC, -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5966 testST(beforeBC, -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999)));
5967 testST(beforeBC, -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274)));
5968 testST(beforeBC, -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(273)));
5969 testST(beforeBC, -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274)));
5970 testST(beforeBC, -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5971 testST(beforeBC, -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999)));
5972 testST(beforeBC, -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5973 testST(beforeBC, -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999)));
5974
5975 // Test Both
5976 auto beforeBoth1 = SysTime(DateTime(1, 1, 1, 0, 0, 0));
5977 testST(beforeBoth1, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), msecs(1)));
5978 testST(beforeBoth1, 0, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5979 testST(beforeBoth1, -1, SysTime(DateTime(1, 1, 1, 0, 0, 0), msecs(999)));
5980 testST(beforeBoth1, -2, SysTime(DateTime(1, 1, 1, 0, 0, 0), msecs(998)));
5981 testST(beforeBoth1, -1000, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5982 testST(beforeBoth1, -2000, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5983 testST(beforeBoth1, -2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), msecs(445)));
5984
5985 auto beforeBoth2 = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5986 testST(beforeBoth2, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_989_999)));
5987 testST(beforeBoth2, 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5988 testST(beforeBoth2, 1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9999)));
5989 testST(beforeBoth2, 2, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(19_999)));
5990 testST(beforeBoth2, 1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5991 testST(beforeBoth2, 2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5992 testST(beforeBoth2, 2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(5_549_999)));
5993
5994 {
5995 auto st = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5996 st.roll!"msecs"(1202).roll!"msecs"(-703);
5997 assert(st == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(4_989_999)));
5998 }
5999
6000 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6001 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6002 static assert(!__traits(compiles, cst.roll!"msecs"(4)));
6003 static assert(!__traits(compiles, ist.roll!"msecs"(4)));
6004
6005 static void testScope(scope ref SysTime st) @safe
6006 {
6007 auto result = st.roll!"msecs"(42);
6008 }
6009 }
6010
6011 // Test roll!"usecs"().
6012 @safe unittest
6013 {
6014 import core.time;
6015 static void testST(SysTime orig, long microseconds, SysTime expected, size_t line = __LINE__) @safe
6016 {
6017 orig.roll!"usecs"(microseconds);
6018 if (orig != expected)
6019 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
6020 }
6021
6022 // Test A.D.
6023 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274));
6024 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
6025 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(275)));
6026 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(276)));
6027 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(284)));
6028 testST(beforeAD, 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(374)));
6029 testST(beforeAD, 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(999)));
6030 testST(beforeAD, 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(1000)));
6031 testST(beforeAD, 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(1274)));
6032 testST(beforeAD, 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(1275)));
6033 testST(beforeAD, 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(2274)));
6034 testST(beforeAD, 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(26_999)));
6035 testST(beforeAD, 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(27_000)));
6036 testST(beforeAD, 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(27_001)));
6037 testST(beforeAD, 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(766_999)));
6038 testST(beforeAD, 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(767_000)));
6039 testST(beforeAD, 1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
6040 testST(beforeAD, 60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
6041 testST(beforeAD, 3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
6042
6043 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(273)));
6044 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(272)));
6045 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(264)));
6046 testST(beforeAD, -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(174)));
6047 testST(beforeAD, -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
6048 testST(beforeAD, -275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(999_999)));
6049 testST(beforeAD, -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(999_274)));
6050 testST(beforeAD, -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(999_273)));
6051 testST(beforeAD, -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(998_274)));
6052 testST(beforeAD, -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(967_000)));
6053 testST(beforeAD, -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(966_999)));
6054 testST(beforeAD, -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(167_000)));
6055 testST(beforeAD, -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(166_999)));
6056 testST(beforeAD, -1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
6057 testST(beforeAD, -60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
6058 testST(beforeAD, -3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
6059
6060 // Test B.C.
6061 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274));
6062 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
6063 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(275)));
6064 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(276)));
6065 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(284)));
6066 testST(beforeBC, 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(374)));
6067 testST(beforeBC, 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(999)));
6068 testST(beforeBC, 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(1000)));
6069 testST(beforeBC, 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(1274)));
6070 testST(beforeBC, 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(1275)));
6071 testST(beforeBC, 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(2274)));
6072 testST(beforeBC, 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(26_999)));
6073 testST(beforeBC, 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(27_000)));
6074 testST(beforeBC, 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(27_001)));
6075 testST(beforeBC, 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(766_999)));
6076 testST(beforeBC, 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(767_000)));
6077 testST(beforeBC, 1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
6078 testST(beforeBC, 60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
6079 testST(beforeBC, 3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
6080
6081 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(273)));
6082 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(272)));
6083 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(264)));
6084 testST(beforeBC, -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(174)));
6085 testST(beforeBC, -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
6086 testST(beforeBC, -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(999_999)));
6087 testST(beforeBC, -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(999_274)));
6088 testST(beforeBC, -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(999_273)));
6089 testST(beforeBC, -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(998_274)));
6090 testST(beforeBC, -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(967_000)));
6091 testST(beforeBC, -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(966_999)));
6092 testST(beforeBC, -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(167_000)));
6093 testST(beforeBC, -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(166_999)));
6094 testST(beforeBC, -1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
6095 testST(beforeBC, -60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
6096 testST(beforeBC, -3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
6097
6098 // Test Both
6099 auto beforeBoth1 = SysTime(DateTime(1, 1, 1, 0, 0, 0));
6100 testST(beforeBoth1, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(1)));
6101 testST(beforeBoth1, 0, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6102 testST(beforeBoth1, -1, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(999_999)));
6103 testST(beforeBoth1, -2, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(999_998)));
6104 testST(beforeBoth1, -1000, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(999_000)));
6105 testST(beforeBoth1, -2000, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(998_000)));
6106 testST(beforeBoth1, -2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(997_445)));
6107 testST(beforeBoth1, -1_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6108 testST(beforeBoth1, -2_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6109 testST(beforeBoth1, -2_333_333, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(666_667)));
6110
6111 auto beforeBoth2 = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
6112 testST(beforeBoth2, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_989)));
6113 testST(beforeBoth2, 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6114 testST(beforeBoth2, 1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9)));
6115 testST(beforeBoth2, 2, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(19)));
6116 testST(beforeBoth2, 1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9999)));
6117 testST(beforeBoth2, 2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(19_999)));
6118 testST(beforeBoth2, 2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(25_549)));
6119 testST(beforeBoth2, 1_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6120 testST(beforeBoth2, 2_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6121 testST(beforeBoth2, 2_333_333, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(3_333_329)));
6122
6123 {
6124 auto st = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
6125 st.roll!"usecs"(9_020_027);
6126 assert(st == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(200_269)));
6127 }
6128
6129 {
6130 auto st = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
6131 st.roll!"usecs"(9_020_027).roll!"usecs"(-70_034);
6132 assert(st == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_499_929)));
6133 }
6134
6135 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6136 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6137 static assert(!__traits(compiles, cst.roll!"usecs"(4)));
6138 static assert(!__traits(compiles, ist.roll!"usecs"(4)));
6139
6140 static void testScope(scope ref SysTime st) @safe
6141 {
6142 auto result = st.roll!"usecs"(42);
6143 }
6144 }
6145
6146 // Test roll!"hnsecs"().
6147 @safe unittest
6148 {
6149 import core.time;
6150 static void testST(SysTime orig, long hnsecs, SysTime expected, size_t line = __LINE__) @safe
6151 {
6152 orig.roll!"hnsecs"(hnsecs);
6153 if (orig != expected)
6154 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
6155 }
6156
6157 // Test A.D.
6158 auto dtAD = DateTime(1999, 7, 6, 12, 30, 33);
6159 auto beforeAD = SysTime(dtAD, hnsecs(274));
6160 testST(beforeAD, 0, SysTime(dtAD, hnsecs(274)));
6161 testST(beforeAD, 1, SysTime(dtAD, hnsecs(275)));
6162 testST(beforeAD, 2, SysTime(dtAD, hnsecs(276)));
6163 testST(beforeAD, 10, SysTime(dtAD, hnsecs(284)));
6164 testST(beforeAD, 100, SysTime(dtAD, hnsecs(374)));
6165 testST(beforeAD, 725, SysTime(dtAD, hnsecs(999)));
6166 testST(beforeAD, 726, SysTime(dtAD, hnsecs(1000)));
6167 testST(beforeAD, 1000, SysTime(dtAD, hnsecs(1274)));
6168 testST(beforeAD, 1001, SysTime(dtAD, hnsecs(1275)));
6169 testST(beforeAD, 2000, SysTime(dtAD, hnsecs(2274)));
6170 testST(beforeAD, 26_725, SysTime(dtAD, hnsecs(26_999)));
6171 testST(beforeAD, 26_726, SysTime(dtAD, hnsecs(27_000)));
6172 testST(beforeAD, 26_727, SysTime(dtAD, hnsecs(27_001)));
6173 testST(beforeAD, 1_766_725, SysTime(dtAD, hnsecs(1_766_999)));
6174 testST(beforeAD, 1_766_726, SysTime(dtAD, hnsecs(1_767_000)));
6175 testST(beforeAD, 1_000_000, SysTime(dtAD, hnsecs(1_000_274)));
6176 testST(beforeAD, 60_000_000L, SysTime(dtAD, hnsecs(274)));
6177 testST(beforeAD, 3_600_000_000L, SysTime(dtAD, hnsecs(274)));
6178 testST(beforeAD, 600_000_000L, SysTime(dtAD, hnsecs(274)));
6179 testST(beforeAD, 36_000_000_000L, SysTime(dtAD, hnsecs(274)));
6180
6181 testST(beforeAD, -1, SysTime(dtAD, hnsecs(273)));
6182 testST(beforeAD, -2, SysTime(dtAD, hnsecs(272)));
6183 testST(beforeAD, -10, SysTime(dtAD, hnsecs(264)));
6184 testST(beforeAD, -100, SysTime(dtAD, hnsecs(174)));
6185 testST(beforeAD, -274, SysTime(dtAD));
6186 testST(beforeAD, -275, SysTime(dtAD, hnsecs(9_999_999)));
6187 testST(beforeAD, -1000, SysTime(dtAD, hnsecs(9_999_274)));
6188 testST(beforeAD, -1001, SysTime(dtAD, hnsecs(9_999_273)));
6189 testST(beforeAD, -2000, SysTime(dtAD, hnsecs(9_998_274)));
6190 testST(beforeAD, -33_274, SysTime(dtAD, hnsecs(9_967_000)));
6191 testST(beforeAD, -33_275, SysTime(dtAD, hnsecs(9_966_999)));
6192 testST(beforeAD, -1_833_274, SysTime(dtAD, hnsecs(8_167_000)));
6193 testST(beforeAD, -1_833_275, SysTime(dtAD, hnsecs(8_166_999)));
6194 testST(beforeAD, -1_000_000, SysTime(dtAD, hnsecs(9_000_274)));
6195 testST(beforeAD, -60_000_000L, SysTime(dtAD, hnsecs(274)));
6196 testST(beforeAD, -3_600_000_000L, SysTime(dtAD, hnsecs(274)));
6197 testST(beforeAD, -600_000_000L, SysTime(dtAD, hnsecs(274)));
6198 testST(beforeAD, -36_000_000_000L, SysTime(dtAD, hnsecs(274)));
6199
6200 // Test B.C.
6201 auto dtBC = DateTime(-1999, 7, 6, 12, 30, 33);
6202 auto beforeBC = SysTime(dtBC, hnsecs(274));
6203 testST(beforeBC, 0, SysTime(dtBC, hnsecs(274)));
6204 testST(beforeBC, 1, SysTime(dtBC, hnsecs(275)));
6205 testST(beforeBC, 2, SysTime(dtBC, hnsecs(276)));
6206 testST(beforeBC, 10, SysTime(dtBC, hnsecs(284)));
6207 testST(beforeBC, 100, SysTime(dtBC, hnsecs(374)));
6208 testST(beforeBC, 725, SysTime(dtBC, hnsecs(999)));
6209 testST(beforeBC, 726, SysTime(dtBC, hnsecs(1000)));
6210 testST(beforeBC, 1000, SysTime(dtBC, hnsecs(1274)));
6211 testST(beforeBC, 1001, SysTime(dtBC, hnsecs(1275)));
6212 testST(beforeBC, 2000, SysTime(dtBC, hnsecs(2274)));
6213 testST(beforeBC, 26_725, SysTime(dtBC, hnsecs(26_999)));
6214 testST(beforeBC, 26_726, SysTime(dtBC, hnsecs(27_000)));
6215 testST(beforeBC, 26_727, SysTime(dtBC, hnsecs(27_001)));
6216 testST(beforeBC, 1_766_725, SysTime(dtBC, hnsecs(1_766_999)));
6217 testST(beforeBC, 1_766_726, SysTime(dtBC, hnsecs(1_767_000)));
6218 testST(beforeBC, 1_000_000, SysTime(dtBC, hnsecs(1_000_274)));
6219 testST(beforeBC, 60_000_000L, SysTime(dtBC, hnsecs(274)));
6220 testST(beforeBC, 3_600_000_000L, SysTime(dtBC, hnsecs(274)));
6221 testST(beforeBC, 600_000_000L, SysTime(dtBC, hnsecs(274)));
6222 testST(beforeBC, 36_000_000_000L, SysTime(dtBC, hnsecs(274)));
6223
6224 testST(beforeBC, -1, SysTime(dtBC, hnsecs(273)));
6225 testST(beforeBC, -2, SysTime(dtBC, hnsecs(272)));
6226 testST(beforeBC, -10, SysTime(dtBC, hnsecs(264)));
6227 testST(beforeBC, -100, SysTime(dtBC, hnsecs(174)));
6228 testST(beforeBC, -274, SysTime(dtBC));
6229 testST(beforeBC, -275, SysTime(dtBC, hnsecs(9_999_999)));
6230 testST(beforeBC, -1000, SysTime(dtBC, hnsecs(9_999_274)));
6231 testST(beforeBC, -1001, SysTime(dtBC, hnsecs(9_999_273)));
6232 testST(beforeBC, -2000, SysTime(dtBC, hnsecs(9_998_274)));
6233 testST(beforeBC, -33_274, SysTime(dtBC, hnsecs(9_967_000)));
6234 testST(beforeBC, -33_275, SysTime(dtBC, hnsecs(9_966_999)));
6235 testST(beforeBC, -1_833_274, SysTime(dtBC, hnsecs(8_167_000)));
6236 testST(beforeBC, -1_833_275, SysTime(dtBC, hnsecs(8_166_999)));
6237 testST(beforeBC, -1_000_000, SysTime(dtBC, hnsecs(9_000_274)));
6238 testST(beforeBC, -60_000_000L, SysTime(dtBC, hnsecs(274)));
6239 testST(beforeBC, -3_600_000_000L, SysTime(dtBC, hnsecs(274)));
6240 testST(beforeBC, -600_000_000L, SysTime(dtBC, hnsecs(274)));
6241 testST(beforeBC, -36_000_000_000L, SysTime(dtBC, hnsecs(274)));
6242
6243 // Test Both
6244 auto dtBoth1 = DateTime(1, 1, 1, 0, 0, 0);
6245 auto beforeBoth1 = SysTime(dtBoth1);
6246 testST(beforeBoth1, 1, SysTime(dtBoth1, hnsecs(1)));
6247 testST(beforeBoth1, 0, SysTime(dtBoth1));
6248 testST(beforeBoth1, -1, SysTime(dtBoth1, hnsecs(9_999_999)));
6249 testST(beforeBoth1, -2, SysTime(dtBoth1, hnsecs(9_999_998)));
6250 testST(beforeBoth1, -1000, SysTime(dtBoth1, hnsecs(9_999_000)));
6251 testST(beforeBoth1, -2000, SysTime(dtBoth1, hnsecs(9_998_000)));
6252 testST(beforeBoth1, -2555, SysTime(dtBoth1, hnsecs(9_997_445)));
6253 testST(beforeBoth1, -1_000_000, SysTime(dtBoth1, hnsecs(9_000_000)));
6254 testST(beforeBoth1, -2_000_000, SysTime(dtBoth1, hnsecs(8_000_000)));
6255 testST(beforeBoth1, -2_333_333, SysTime(dtBoth1, hnsecs(7_666_667)));
6256 testST(beforeBoth1, -10_000_000, SysTime(dtBoth1));
6257 testST(beforeBoth1, -20_000_000, SysTime(dtBoth1));
6258 testST(beforeBoth1, -20_888_888, SysTime(dtBoth1, hnsecs(9_111_112)));
6259
6260 auto dtBoth2 = DateTime(0, 12, 31, 23, 59, 59);
6261 auto beforeBoth2 = SysTime(dtBoth2, hnsecs(9_999_999));
6262 testST(beforeBoth2, -1, SysTime(dtBoth2, hnsecs(9_999_998)));
6263 testST(beforeBoth2, 0, SysTime(dtBoth2, hnsecs(9_999_999)));
6264 testST(beforeBoth2, 1, SysTime(dtBoth2));
6265 testST(beforeBoth2, 2, SysTime(dtBoth2, hnsecs(1)));
6266 testST(beforeBoth2, 1000, SysTime(dtBoth2, hnsecs(999)));
6267 testST(beforeBoth2, 2000, SysTime(dtBoth2, hnsecs(1999)));
6268 testST(beforeBoth2, 2555, SysTime(dtBoth2, hnsecs(2554)));
6269 testST(beforeBoth2, 1_000_000, SysTime(dtBoth2, hnsecs(999_999)));
6270 testST(beforeBoth2, 2_000_000, SysTime(dtBoth2, hnsecs(1_999_999)));
6271 testST(beforeBoth2, 2_333_333, SysTime(dtBoth2, hnsecs(2_333_332)));
6272 testST(beforeBoth2, 10_000_000, SysTime(dtBoth2, hnsecs(9_999_999)));
6273 testST(beforeBoth2, 20_000_000, SysTime(dtBoth2, hnsecs(9_999_999)));
6274 testST(beforeBoth2, 20_888_888, SysTime(dtBoth2, hnsecs(888_887)));
6275
6276 {
6277 auto st = SysTime(dtBoth2, hnsecs(9_999_999));
6278 st.roll!"hnsecs"(70_777_222).roll!"hnsecs"(-222_555_292);
6279 assert(st == SysTime(dtBoth2, hnsecs(8_221_929)));
6280 }
6281
6282 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6283 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6284 static assert(!__traits(compiles, cst.roll!"hnsecs"(4)));
6285 static assert(!__traits(compiles, ist.roll!"hnsecs"(4)));
6286
6287 static void testScope(scope ref SysTime st) @safe
6288 {
6289 auto result = st.roll!"hnsecs"(42);
6290 }
6291 }
6292
6293
6294 /++
6295 Gives the result of adding or subtracting a $(REF Duration, core,time)
6296 from this $(LREF SysTime).
6297
6298 The legal types of arithmetic for $(LREF SysTime) using this operator
6299 are
6300
6301 $(BOOKTABLE,
6302 $(TR $(TD SysTime) $(TD +) $(TD Duration) $(TD -->) $(TD SysTime))
6303 $(TR $(TD SysTime) $(TD -) $(TD Duration) $(TD -->) $(TD SysTime))
6304 )
6305
6306 Params:
6307 duration = The $(REF Duration, core,time) to add to or subtract from
6308 this $(LREF SysTime).
6309 +/
6310 SysTime opBinary(string op)(Duration duration) @safe const pure nothrow return scope
6311 if (op == "+" || op == "-")
6312 {
6313 SysTime retval = SysTime(this._stdTime, this._timezone);
6314 immutable hnsecs = duration.total!"hnsecs";
6315 mixin("retval._stdTime " ~ op ~ "= hnsecs;");
6316 return retval;
6317 }
6318
6319 ///
6320 @safe unittest
6321 {
6322 import core.time : hours, seconds;
6323 import std.datetime.date : DateTime;
6324
6325 assert(SysTime(DateTime(2015, 12, 31, 23, 59, 59)) + seconds(1) ==
6326 SysTime(DateTime(2016, 1, 1, 0, 0, 0)));
6327
6328 assert(SysTime(DateTime(2015, 12, 31, 23, 59, 59)) + hours(1) ==
6329 SysTime(DateTime(2016, 1, 1, 0, 59, 59)));
6330
6331 assert(SysTime(DateTime(2016, 1, 1, 0, 0, 0)) - seconds(1) ==
6332 SysTime(DateTime(2015, 12, 31, 23, 59, 59)));
6333
6334 assert(SysTime(DateTime(2016, 1, 1, 0, 59, 59)) - hours(1) ==
6335 SysTime(DateTime(2015, 12, 31, 23, 59, 59)));
6336 }
6337
6338 @safe unittest
6339 {
6340 import core.time;
6341 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_678));
6342
6343 assert(st + dur!"weeks"(7) == SysTime(DateTime(1999, 8, 24, 12, 30, 33), hnsecs(2_345_678)));
6344 assert(st + dur!"weeks"(-7) == SysTime(DateTime(1999, 5, 18, 12, 30, 33), hnsecs(2_345_678)));
6345 assert(st + dur!"days"(7) == SysTime(DateTime(1999, 7, 13, 12, 30, 33), hnsecs(2_345_678)));
6346 assert(st + dur!"days"(-7) == SysTime(DateTime(1999, 6, 29, 12, 30, 33), hnsecs(2_345_678)));
6347 assert(st + dur!"hours"(7) == SysTime(DateTime(1999, 7, 6, 19, 30, 33), hnsecs(2_345_678)));
6348 assert(st + dur!"hours"(-7) == SysTime(DateTime(1999, 7, 6, 5, 30, 33), hnsecs(2_345_678)));
6349 assert(st + dur!"minutes"(7) == SysTime(DateTime(1999, 7, 6, 12, 37, 33), hnsecs(2_345_678)));
6350 assert(st + dur!"minutes"(-7) == SysTime(DateTime(1999, 7, 6, 12, 23, 33), hnsecs(2_345_678)));
6351 assert(st + dur!"seconds"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 40), hnsecs(2_345_678)));
6352 assert(st + dur!"seconds"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 26), hnsecs(2_345_678)));
6353 assert(st + dur!"msecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_415_678)));
6354 assert(st + dur!"msecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_275_678)));
6355 assert(st + dur!"usecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_748)));
6356 assert(st + dur!"usecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_608)));
6357 assert(st + dur!"hnsecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_685)));
6358 assert(st + dur!"hnsecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_671)));
6359
6360 assert(st - dur!"weeks"(-7) == SysTime(DateTime(1999, 8, 24, 12, 30, 33), hnsecs(2_345_678)));
6361 assert(st - dur!"weeks"(7) == SysTime(DateTime(1999, 5, 18, 12, 30, 33), hnsecs(2_345_678)));
6362 assert(st - dur!"days"(-7) == SysTime(DateTime(1999, 7, 13, 12, 30, 33), hnsecs(2_345_678)));
6363 assert(st - dur!"days"(7) == SysTime(DateTime(1999, 6, 29, 12, 30, 33), hnsecs(2_345_678)));
6364 assert(st - dur!"hours"(-7) == SysTime(DateTime(1999, 7, 6, 19, 30, 33), hnsecs(2_345_678)));
6365 assert(st - dur!"hours"(7) == SysTime(DateTime(1999, 7, 6, 5, 30, 33), hnsecs(2_345_678)));
6366 assert(st - dur!"minutes"(-7) == SysTime(DateTime(1999, 7, 6, 12, 37, 33), hnsecs(2_345_678)));
6367 assert(st - dur!"minutes"(7) == SysTime(DateTime(1999, 7, 6, 12, 23, 33), hnsecs(2_345_678)));
6368 assert(st - dur!"seconds"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 40), hnsecs(2_345_678)));
6369 assert(st - dur!"seconds"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 26), hnsecs(2_345_678)));
6370 assert(st - dur!"msecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_415_678)));
6371 assert(st - dur!"msecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_275_678)));
6372 assert(st - dur!"usecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_748)));
6373 assert(st - dur!"usecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_608)));
6374 assert(st - dur!"hnsecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_685)));
6375 assert(st - dur!"hnsecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_671)));
6376
6377 static void testST(SysTime orig, long hnsecs, SysTime expected, size_t line = __LINE__) @safe
6378 {
6379 auto result = orig + dur!"hnsecs"(hnsecs);
6380 if (result != expected)
6381 throw new AssertError(format("Failed. actual [%s] != expected [%s]", result, expected), __FILE__, line);
6382 }
6383
6384 // Test A.D.
6385 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(274));
6386 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(274)));
6387 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(275)));
6388 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(276)));
6389 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(284)));
6390 testST(beforeAD, 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(374)));
6391 testST(beforeAD, 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(999)));
6392 testST(beforeAD, 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1000)));
6393 testST(beforeAD, 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1274)));
6394 testST(beforeAD, 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1275)));
6395 testST(beforeAD, 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2274)));
6396 testST(beforeAD, 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(26_999)));
6397 testST(beforeAD, 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(27_000)));
6398 testST(beforeAD, 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(27_001)));
6399 testST(beforeAD, 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_766_999)));
6400 testST(beforeAD, 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_767_000)));
6401 testST(beforeAD, 1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_000_274)));
6402 testST(beforeAD, 60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 39), hnsecs(274)));
6403 testST(beforeAD, 3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 36, 33), hnsecs(274)));
6404 testST(beforeAD, 600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 31, 33), hnsecs(274)));
6405 testST(beforeAD, 36_000_000_000L, SysTime(DateTime(1999, 7, 6, 13, 30, 33), hnsecs(274)));
6406
6407 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(273)));
6408 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(272)));
6409 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(264)));
6410 testST(beforeAD, -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(174)));
6411 testST(beforeAD, -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
6412 testST(beforeAD, -275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_999)));
6413 testST(beforeAD, -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_274)));
6414 testST(beforeAD, -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_273)));
6415 testST(beforeAD, -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_998_274)));
6416 testST(beforeAD, -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_967_000)));
6417 testST(beforeAD, -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_966_999)));
6418 testST(beforeAD, -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(8_167_000)));
6419 testST(beforeAD, -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(8_166_999)));
6420 testST(beforeAD, -1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_000_274)));
6421 testST(beforeAD, -60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 27), hnsecs(274)));
6422 testST(beforeAD, -3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 24, 33), hnsecs(274)));
6423 testST(beforeAD, -600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 29, 33), hnsecs(274)));
6424 testST(beforeAD, -36_000_000_000L, SysTime(DateTime(1999, 7, 6, 11, 30, 33), hnsecs(274)));
6425
6426 // Test B.C.
6427 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(274));
6428 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(274)));
6429 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(275)));
6430 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(276)));
6431 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(284)));
6432 testST(beforeBC, 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(374)));
6433 testST(beforeBC, 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(999)));
6434 testST(beforeBC, 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1000)));
6435 testST(beforeBC, 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1274)));
6436 testST(beforeBC, 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1275)));
6437 testST(beforeBC, 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(2274)));
6438 testST(beforeBC, 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(26_999)));
6439 testST(beforeBC, 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(27_000)));
6440 testST(beforeBC, 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(27_001)));
6441 testST(beforeBC, 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_766_999)));
6442 testST(beforeBC, 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_767_000)));
6443 testST(beforeBC, 1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_000_274)));
6444 testST(beforeBC, 60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 39), hnsecs(274)));
6445 testST(beforeBC, 3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 36, 33), hnsecs(274)));
6446 testST(beforeBC, 600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), hnsecs(274)));
6447 testST(beforeBC, 36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), hnsecs(274)));
6448
6449 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(273)));
6450 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(272)));
6451 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(264)));
6452 testST(beforeBC, -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(174)));
6453 testST(beforeBC, -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
6454 testST(beforeBC, -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_999)));
6455 testST(beforeBC, -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_274)));
6456 testST(beforeBC, -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_273)));
6457 testST(beforeBC, -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_998_274)));
6458 testST(beforeBC, -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_967_000)));
6459 testST(beforeBC, -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_966_999)));
6460 testST(beforeBC, -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(8_167_000)));
6461 testST(beforeBC, -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(8_166_999)));
6462 testST(beforeBC, -1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_000_274)));
6463 testST(beforeBC, -60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 27), hnsecs(274)));
6464 testST(beforeBC, -3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 24, 33), hnsecs(274)));
6465 testST(beforeBC, -600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), hnsecs(274)));
6466 testST(beforeBC, -36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), hnsecs(274)));
6467
6468 // Test Both
6469 auto beforeBoth1 = SysTime(DateTime(1, 1, 1, 0, 0, 0));
6470 testST(beforeBoth1, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)));
6471 testST(beforeBoth1, 0, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6472 testST(beforeBoth1, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6473 testST(beforeBoth1, -2, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_998)));
6474 testST(beforeBoth1, -1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_000)));
6475 testST(beforeBoth1, -2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_998_000)));
6476 testST(beforeBoth1, -2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_997_445)));
6477 testST(beforeBoth1, -1_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_000_000)));
6478 testST(beforeBoth1, -2_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(8_000_000)));
6479 testST(beforeBoth1, -2_333_333, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(7_666_667)));
6480 testST(beforeBoth1, -10_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59)));
6481 testST(beforeBoth1, -20_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 58)));
6482 testST(beforeBoth1, -20_888_888, SysTime(DateTime(0, 12, 31, 23, 59, 57), hnsecs(9_111_112)));
6483
6484 auto beforeBoth2 = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
6485 testST(beforeBoth2, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_998)));
6486 testST(beforeBoth2, 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6487 testST(beforeBoth2, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6488 testST(beforeBoth2, 2, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)));
6489 testST(beforeBoth2, 1000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(999)));
6490 testST(beforeBoth2, 2000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1999)));
6491 testST(beforeBoth2, 2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(2554)));
6492 testST(beforeBoth2, 1_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(999_999)));
6493 testST(beforeBoth2, 2_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1_999_999)));
6494 testST(beforeBoth2, 2_333_333, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(2_333_332)));
6495 testST(beforeBoth2, 10_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
6496 testST(beforeBoth2, 20_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 1), hnsecs(9_999_999)));
6497 testST(beforeBoth2, 20_888_888, SysTime(DateTime(1, 1, 1, 0, 0, 2), hnsecs(888_887)));
6498
6499 auto duration = dur!"seconds"(12);
6500 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6501 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6502 assert(cst + duration == SysTime(DateTime(1999, 7, 6, 12, 30, 45)));
6503 assert(ist + duration == SysTime(DateTime(1999, 7, 6, 12, 30, 45)));
6504 assert(cst - duration == SysTime(DateTime(1999, 7, 6, 12, 30, 21)));
6505 assert(ist - duration == SysTime(DateTime(1999, 7, 6, 12, 30, 21)));
6506
6507 static void testScope(scope ref SysTime st, scope ref Duration d) @safe
6508 {
6509 auto result = st + d;
6510 }
6511 }
6512
6513
6514 /++
6515 Gives the result of adding or subtracting a $(REF Duration, core,time) from
6516 this $(LREF SysTime), as well as assigning the result to this
6517 $(LREF SysTime).
6518
6519 The legal types of arithmetic for $(LREF SysTime) using this operator are
6520
6521 $(BOOKTABLE,
6522 $(TR $(TD SysTime) $(TD +) $(TD Duration) $(TD -->) $(TD SysTime))
6523 $(TR $(TD SysTime) $(TD -) $(TD Duration) $(TD -->) $(TD SysTime))
6524 )
6525
6526 Params:
6527 duration = The $(REF Duration, core,time) to add to or subtract from
6528 this $(LREF SysTime).
6529 +/
6530 ref SysTime opOpAssign(string op)(Duration duration) @safe pure nothrow scope
6531 if (op == "+" || op == "-")
6532 {
6533 immutable hnsecs = duration.total!"hnsecs";
6534 mixin("_stdTime " ~ op ~ "= hnsecs;");
6535 return this;
6536 }
6537
6538 @safe unittest
6539 {
6540 import core.time;
6541 auto before = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6542 assert(before + dur!"weeks"(7) == SysTime(DateTime(1999, 8, 24, 12, 30, 33)));
6543 assert(before + dur!"weeks"(-7) == SysTime(DateTime(1999, 5, 18, 12, 30, 33)));
6544 assert(before + dur!"days"(7) == SysTime(DateTime(1999, 7, 13, 12, 30, 33)));
6545 assert(before + dur!"days"(-7) == SysTime(DateTime(1999, 6, 29, 12, 30, 33)));
6546
6547 assert(before + dur!"hours"(7) == SysTime(DateTime(1999, 7, 6, 19, 30, 33)));
6548 assert(before + dur!"hours"(-7) == SysTime(DateTime(1999, 7, 6, 5, 30, 33)));
6549 assert(before + dur!"minutes"(7) == SysTime(DateTime(1999, 7, 6, 12, 37, 33)));
6550 assert(before + dur!"minutes"(-7) == SysTime(DateTime(1999, 7, 6, 12, 23, 33)));
6551 assert(before + dur!"seconds"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 40)));
6552 assert(before + dur!"seconds"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 26)));
6553 assert(before + dur!"msecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(7)));
6554 assert(before + dur!"msecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), msecs(993)));
6555 assert(before + dur!"usecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(7)));
6556 assert(before + dur!"usecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), usecs(999_993)));
6557 assert(before + dur!"hnsecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(7)));
6558 assert(before + dur!"hnsecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_993)));
6559
6560 assert(before - dur!"weeks"(-7) == SysTime(DateTime(1999, 8, 24, 12, 30, 33)));
6561 assert(before - dur!"weeks"(7) == SysTime(DateTime(1999, 5, 18, 12, 30, 33)));
6562 assert(before - dur!"days"(-7) == SysTime(DateTime(1999, 7, 13, 12, 30, 33)));
6563 assert(before - dur!"days"(7) == SysTime(DateTime(1999, 6, 29, 12, 30, 33)));
6564
6565 assert(before - dur!"hours"(-7) == SysTime(DateTime(1999, 7, 6, 19, 30, 33)));
6566 assert(before - dur!"hours"(7) == SysTime(DateTime(1999, 7, 6, 5, 30, 33)));
6567 assert(before - dur!"minutes"(-7) == SysTime(DateTime(1999, 7, 6, 12, 37, 33)));
6568 assert(before - dur!"minutes"(7) == SysTime(DateTime(1999, 7, 6, 12, 23, 33)));
6569 assert(before - dur!"seconds"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 40)));
6570 assert(before - dur!"seconds"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 26)));
6571 assert(before - dur!"msecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(7)));
6572 assert(before - dur!"msecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), msecs(993)));
6573 assert(before - dur!"usecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(7)));
6574 assert(before - dur!"usecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), usecs(999_993)));
6575 assert(before - dur!"hnsecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(7)));
6576 assert(before - dur!"hnsecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_993)));
6577
6578 static void testST(SysTime orig, long hnsecs, SysTime expected, size_t line = __LINE__) @safe
6579 {
6580 auto r = orig += dur!"hnsecs"(hnsecs);
6581 if (orig != expected)
6582 throw new AssertError(format("Failed 1. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
6583 if (r != expected)
6584 throw new AssertError(format("Failed 2. actual [%s] != expected [%s]", r, expected), __FILE__, line);
6585 }
6586
6587 // Test A.D.
6588 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(274));
6589 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(274)));
6590 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(275)));
6591 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(276)));
6592 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(284)));
6593 testST(beforeAD, 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(374)));
6594 testST(beforeAD, 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(999)));
6595 testST(beforeAD, 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1000)));
6596 testST(beforeAD, 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1274)));
6597 testST(beforeAD, 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1275)));
6598 testST(beforeAD, 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2274)));
6599 testST(beforeAD, 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(26_999)));
6600 testST(beforeAD, 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(27_000)));
6601 testST(beforeAD, 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(27_001)));
6602 testST(beforeAD, 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_766_999)));
6603 testST(beforeAD, 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_767_000)));
6604 testST(beforeAD, 1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_000_274)));
6605 testST(beforeAD, 60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 39), hnsecs(274)));
6606 testST(beforeAD, 3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 36, 33), hnsecs(274)));
6607 testST(beforeAD, 600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 31, 33), hnsecs(274)));
6608 testST(beforeAD, 36_000_000_000L, SysTime(DateTime(1999, 7, 6, 13, 30, 33), hnsecs(274)));
6609
6610 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(273)));
6611 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(272)));
6612 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(264)));
6613 testST(beforeAD, -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(174)));
6614 testST(beforeAD, -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
6615 testST(beforeAD, -275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_999)));
6616 testST(beforeAD, -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_274)));
6617 testST(beforeAD, -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_273)));
6618 testST(beforeAD, -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_998_274)));
6619 testST(beforeAD, -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_967_000)));
6620 testST(beforeAD, -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_966_999)));
6621 testST(beforeAD, -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(8_167_000)));
6622 testST(beforeAD, -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(8_166_999)));
6623 testST(beforeAD, -1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_000_274)));
6624 testST(beforeAD, -60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 27), hnsecs(274)));
6625 testST(beforeAD, -3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 24, 33), hnsecs(274)));
6626 testST(beforeAD, -600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 29, 33), hnsecs(274)));
6627 testST(beforeAD, -36_000_000_000L, SysTime(DateTime(1999, 7, 6, 11, 30, 33), hnsecs(274)));
6628
6629 // Test B.C.
6630 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(274));
6631 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(274)));
6632 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(275)));
6633 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(276)));
6634 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(284)));
6635 testST(beforeBC, 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(374)));
6636 testST(beforeBC, 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(999)));
6637 testST(beforeBC, 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1000)));
6638 testST(beforeBC, 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1274)));
6639 testST(beforeBC, 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1275)));
6640 testST(beforeBC, 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(2274)));
6641 testST(beforeBC, 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(26_999)));
6642 testST(beforeBC, 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(27_000)));
6643 testST(beforeBC, 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(27_001)));
6644 testST(beforeBC, 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_766_999)));
6645 testST(beforeBC, 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_767_000)));
6646 testST(beforeBC, 1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_000_274)));
6647 testST(beforeBC, 60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 39), hnsecs(274)));
6648 testST(beforeBC, 3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 36, 33), hnsecs(274)));
6649 testST(beforeBC, 600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), hnsecs(274)));
6650 testST(beforeBC, 36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), hnsecs(274)));
6651
6652 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(273)));
6653 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(272)));
6654 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(264)));
6655 testST(beforeBC, -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(174)));
6656 testST(beforeBC, -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
6657 testST(beforeBC, -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_999)));
6658 testST(beforeBC, -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_274)));
6659 testST(beforeBC, -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_273)));
6660 testST(beforeBC, -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_998_274)));
6661 testST(beforeBC, -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_967_000)));
6662 testST(beforeBC, -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_966_999)));
6663 testST(beforeBC, -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(8_167_000)));
6664 testST(beforeBC, -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(8_166_999)));
6665 testST(beforeBC, -1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_000_274)));
6666 testST(beforeBC, -60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 27), hnsecs(274)));
6667 testST(beforeBC, -3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 24, 33), hnsecs(274)));
6668 testST(beforeBC, -600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), hnsecs(274)));
6669 testST(beforeBC, -36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), hnsecs(274)));
6670
6671 // Test Both
6672 auto beforeBoth1 = SysTime(DateTime(1, 1, 1, 0, 0, 0));
6673 testST(beforeBoth1, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)));
6674 testST(beforeBoth1, 0, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6675 testST(beforeBoth1, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6676 testST(beforeBoth1, -2, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_998)));
6677 testST(beforeBoth1, -1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_000)));
6678 testST(beforeBoth1, -2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_998_000)));
6679 testST(beforeBoth1, -2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_997_445)));
6680 testST(beforeBoth1, -1_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_000_000)));
6681 testST(beforeBoth1, -2_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(8_000_000)));
6682 testST(beforeBoth1, -2_333_333, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(7_666_667)));
6683 testST(beforeBoth1, -10_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59)));
6684 testST(beforeBoth1, -20_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 58)));
6685 testST(beforeBoth1, -20_888_888, SysTime(DateTime(0, 12, 31, 23, 59, 57), hnsecs(9_111_112)));
6686
6687 auto beforeBoth2 = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
6688 testST(beforeBoth2, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_998)));
6689 testST(beforeBoth2, 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6690 testST(beforeBoth2, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6691 testST(beforeBoth2, 2, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)));
6692 testST(beforeBoth2, 1000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(999)));
6693 testST(beforeBoth2, 2000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1999)));
6694 testST(beforeBoth2, 2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(2554)));
6695 testST(beforeBoth2, 1_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(999_999)));
6696 testST(beforeBoth2, 2_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1_999_999)));
6697 testST(beforeBoth2, 2_333_333, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(2_333_332)));
6698 testST(beforeBoth2, 10_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
6699 testST(beforeBoth2, 20_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 1), hnsecs(9_999_999)));
6700 testST(beforeBoth2, 20_888_888, SysTime(DateTime(1, 1, 1, 0, 0, 2), hnsecs(888_887)));
6701
6702 {
6703 auto st = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
6704 (st += dur!"hnsecs"(52)) += dur!"seconds"(-907);
6705 assert(st == SysTime(DateTime(0, 12, 31, 23, 44, 53), hnsecs(51)));
6706 }
6707
6708 auto duration = dur!"seconds"(12);
6709 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6710 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6711 static assert(!__traits(compiles, cst += duration));
6712 static assert(!__traits(compiles, ist += duration));
6713 static assert(!__traits(compiles, cst -= duration));
6714 static assert(!__traits(compiles, ist -= duration));
6715
6716 static void testScope(scope ref SysTime st, scope ref Duration d) @safe
6717 {
6718 auto result1 = st += d;
6719 auto result2 = st -= d;
6720 }
6721 }
6722
6723
6724 /++
6725 Gives the difference between two $(LREF SysTime)s.
6726
6727 The legal types of arithmetic for $(LREF SysTime) using this operator
6728 are
6729
6730 $(BOOKTABLE,
6731 $(TR $(TD SysTime) $(TD -) $(TD SysTime) $(TD -->) $(TD duration))
6732 )
6733 +/
6734 Duration opBinary(string op)(SysTime rhs) @safe const pure nothrow scope
6735 if (op == "-")
6736 {
6737 return dur!"hnsecs"(_stdTime - rhs._stdTime);
6738 }
6739
6740 @safe unittest
6741 {
6742 import core.time;
6743 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1998, 7, 6, 12, 30, 33)) ==
6744 dur!"seconds"(31_536_000));
6745 assert(SysTime(DateTime(1998, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) ==
6746 dur!"seconds"(-31_536_000));
6747
6748 assert(SysTime(DateTime(1999, 8, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) ==
6749 dur!"seconds"(26_78_400));
6750 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 8, 6, 12, 30, 33)) ==
6751 dur!"seconds"(-26_78_400));
6752
6753 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 5, 12, 30, 33)) ==
6754 dur!"seconds"(86_400));
6755 assert(SysTime(DateTime(1999, 7, 5, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) ==
6756 dur!"seconds"(-86_400));
6757
6758 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 11, 30, 33)) ==
6759 dur!"seconds"(3600));
6760 assert(SysTime(DateTime(1999, 7, 6, 11, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) ==
6761 dur!"seconds"(-3600));
6762
6763 assert(SysTime(DateTime(1999, 7, 6, 12, 31, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) ==
6764 dur!"seconds"(60));
6765 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 31, 33)) ==
6766 dur!"seconds"(-60));
6767
6768 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 34)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) ==
6769 dur!"seconds"(1));
6770 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 34)) ==
6771 dur!"seconds"(-1));
6772
6773 {
6774 auto dt = DateTime(1999, 7, 6, 12, 30, 33);
6775 assert(SysTime(dt, msecs(532)) - SysTime(dt) == msecs(532));
6776 assert(SysTime(dt) - SysTime(dt, msecs(532)) == msecs(-532));
6777
6778 assert(SysTime(dt, usecs(333_347)) - SysTime(dt) == usecs(333_347));
6779 assert(SysTime(dt) - SysTime(dt, usecs(333_347)) == usecs(-333_347));
6780
6781 assert(SysTime(dt, hnsecs(1_234_567)) - SysTime(dt) == hnsecs(1_234_567));
6782 assert(SysTime(dt) - SysTime(dt, hnsecs(1_234_567)) == hnsecs(-1_234_567));
6783 }
6784
6785 assert(SysTime(DateTime(1, 1, 1, 12, 30, 33)) - SysTime(DateTime(1, 1, 1, 0, 0, 0)) == dur!"seconds"(45033));
6786 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)) - SysTime(DateTime(1, 1, 1, 12, 30, 33)) == dur!"seconds"(-45033));
6787 assert(SysTime(DateTime(0, 12, 31, 12, 30, 33)) - SysTime(DateTime(1, 1, 1, 0, 0, 0)) == dur!"seconds"(-41367));
6788 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)) - SysTime(DateTime(0, 12, 31, 12, 30, 33)) == dur!"seconds"(41367));
6789
6790 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)) - SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)) ==
6791 dur!"hnsecs"(1));
6792 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)) - SysTime(DateTime(1, 1, 1, 0, 0, 0)) ==
6793 dur!"hnsecs"(-1));
6794
6795 version (Posix)
6796 {
6797 import std.datetime.timezone : PosixTimeZone;
6798 immutable tz = PosixTimeZone.getTimeZone("America/Los_Angeles");
6799 }
6800 else version (Windows)
6801 {
6802 import std.datetime.timezone : WindowsTimeZone;
6803 immutable tz = WindowsTimeZone.getTimeZone("Pacific Standard Time");
6804 }
6805
6806 {
6807 auto dt = DateTime(2011, 1, 13, 8, 17, 2);
6808 auto d = msecs(296);
6809 assert(SysTime(dt, d, tz) - SysTime(dt, d, tz) == Duration.zero);
6810 assert(SysTime(dt, d, tz) - SysTime(dt, d, UTC()) == hours(8));
6811 assert(SysTime(dt, d, UTC()) - SysTime(dt, d, tz) == hours(-8));
6812 }
6813
6814 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6815 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6816 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6817 assert(st - st == Duration.zero);
6818 assert(cst - st == Duration.zero);
6819 assert(ist - st == Duration.zero);
6820
6821 assert(st - cst == Duration.zero);
6822 assert(cst - cst == Duration.zero);
6823 assert(ist - cst == Duration.zero);
6824
6825 assert(st - ist == Duration.zero);
6826 assert(cst - ist == Duration.zero);
6827 assert(ist - ist == Duration.zero);
6828
6829 static void testScope(scope ref SysTime left, scope ref SysTime right) @safe
6830 {
6831 auto result = left - right;
6832 }
6833 }
6834
6835
6836 /++
6837 Returns the difference between the two $(LREF SysTime)s in months.
6838
6839 To get the difference in years, subtract the year property
6840 of two $(LREF SysTime)s. To get the difference in days or weeks,
6841 subtract the $(LREF SysTime)s themselves and use the
6842 $(REF Duration, core,time) that results. Because converting between
6843 months and smaller units requires a specific date (which
6844 $(REF Duration, core,time)s don't have), getting the difference in
6845 months requires some math using both the year and month properties, so
6846 this is a convenience function for getting the difference in months.
6847
6848 Note that the number of days in the months or how far into the month
6849 either date is is irrelevant. It is the difference in the month property
6850 combined with the difference in years * 12. So, for instance,
6851 December 31st and January 1st are one month apart just as December 1st
6852 and January 31st are one month apart.
6853
6854 Params:
6855 rhs = The $(LREF SysTime) to subtract from this one.
6856 +/
6857 int diffMonths(scope SysTime rhs) @safe const nothrow scope
6858 {
6859 return (cast(Date) this).diffMonths(cast(Date) rhs);
6860 }
6861
6862 ///
6863 @safe unittest
6864 {
6865 import core.time;
6866 import std.datetime.date : Date;
6867
6868 assert(SysTime(Date(1999, 2, 1)).diffMonths(
6869 SysTime(Date(1999, 1, 31))) == 1);
6870
6871 assert(SysTime(Date(1999, 1, 31)).diffMonths(
6872 SysTime(Date(1999, 2, 1))) == -1);
6873
6874 assert(SysTime(Date(1999, 3, 1)).diffMonths(
6875 SysTime(Date(1999, 1, 1))) == 2);
6876
6877 assert(SysTime(Date(1999, 1, 1)).diffMonths(
6878 SysTime(Date(1999, 3, 31))) == -2);
6879 }
6880
6881 @safe unittest
6882 {
6883 import core.time;
6884 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6885 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6886 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6887 assert(st.diffMonths(st) == 0);
6888 assert(cst.diffMonths(st) == 0);
6889 assert(ist.diffMonths(st) == 0);
6890
6891 assert(st.diffMonths(cst) == 0);
6892 assert(cst.diffMonths(cst) == 0);
6893 assert(ist.diffMonths(cst) == 0);
6894
6895 assert(st.diffMonths(ist) == 0);
6896 assert(cst.diffMonths(ist) == 0);
6897 assert(ist.diffMonths(ist) == 0);
6898
6899 static void testScope(scope ref SysTime left, scope ref SysTime right) @safe
6900 {
6901 auto result = left.diffMonths(right);
6902 }
6903 }
6904
6905
6906 /++
6907 Whether this $(LREF SysTime) is in a leap year.
6908 +/
6909 @property bool isLeapYear() @safe const nothrow scope
6910 {
6911 return (cast(Date) this).isLeapYear;
6912 }
6913
6914 @safe unittest
6915 {
6916 import core.time;
6917 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6918 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6919 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6920 assert(!st.isLeapYear);
6921 assert(!cst.isLeapYear);
6922 assert(!ist.isLeapYear);
6923
6924 static void testScope(scope ref SysTime st) @safe
6925 {
6926 auto result = st.isLeapYear;
6927 }
6928 }
6929
6930
6931 /++
6932 Day of the week this $(LREF SysTime) is on.
6933 +/
6934 @property DayOfWeek dayOfWeek() @safe const nothrow scope
6935 {
6936 return getDayOfWeek(dayOfGregorianCal);
6937 }
6938
6939 @safe unittest
6940 {
6941 import core.time;
6942 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6943 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6944 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6945 assert(st.dayOfWeek == DayOfWeek.tue);
6946 assert(cst.dayOfWeek == DayOfWeek.tue);
6947 assert(ist.dayOfWeek == DayOfWeek.tue);
6948
6949 static void testScope(scope ref SysTime st) @safe
6950 {
6951 auto result = st.dayOfWeek;
6952 }
6953 }
6954
6955
6956 /++
6957 Day of the year this $(LREF SysTime) is on.
6958 +/
6959 @property ushort dayOfYear() @safe const nothrow scope
6960 {
6961 return (cast(Date) this).dayOfYear;
6962 }
6963
6964 ///
6965 @safe unittest
6966 {
6967 import core.time;
6968 import std.datetime.date : DateTime;
6969
6970 assert(SysTime(DateTime(1999, 1, 1, 12, 22, 7)).dayOfYear == 1);
6971 assert(SysTime(DateTime(1999, 12, 31, 7, 2, 59)).dayOfYear == 365);
6972 assert(SysTime(DateTime(2000, 12, 31, 21, 20, 0)).dayOfYear == 366);
6973 }
6974
6975 @safe unittest
6976 {
6977 import core.time;
6978 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6979 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6980 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6981 assert(st.dayOfYear == 187);
6982 assert(cst.dayOfYear == 187);
6983 assert(ist.dayOfYear == 187);
6984
6985 static void testScope(scope ref SysTime st) @safe
6986 {
6987 auto result = st.dayOfYear;
6988 }
6989 }
6990
6991
6992 /++
6993 Day of the year.
6994
6995 Params:
6996 day = The day of the year to set which day of the year this
6997 $(LREF SysTime) is on.
6998 +/
6999 @property void dayOfYear(int day) @safe scope
7000 {
7001 immutable hnsecs = adjTime;
7002 immutable days = convert!("hnsecs", "days")(hnsecs);
7003 immutable theRest = hnsecs - convert!("days", "hnsecs")(days);
7004
7005 auto date = Date(cast(int) days);
7006 date.dayOfYear = day;
7007
7008 immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
7009
7010 adjTime = newDaysHNSecs + theRest;
7011 }
7012
7013 @safe unittest
7014 {
7015 import core.time;
7016 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7017 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7018 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7019 st.dayOfYear = 12;
7020 assert(st.dayOfYear == 12);
7021 static assert(!__traits(compiles, cst.dayOfYear = 12));
7022 static assert(!__traits(compiles, ist.dayOfYear = 12));
7023
7024 static void testScope(scope ref SysTime st) @safe
7025 {
7026 st.dayOfYear = 42;
7027 }
7028 }
7029
7030
7031 /++
7032 The Xth day of the Gregorian Calendar that this $(LREF SysTime) is on.
7033 +/
7034 @property int dayOfGregorianCal() @safe const nothrow scope
7035 {
7036 immutable adjustedTime = adjTime;
7037
7038 // We have to add one because 0 would be midnight, January 1st, 1 A.D.,
7039 // which would be the 1st day of the Gregorian Calendar, not the 0th. So,
7040 // simply casting to days is one day off.
7041 if (adjustedTime > 0)
7042 return cast(int) getUnitsFromHNSecs!"days"(adjustedTime) + 1;
7043
7044 long hnsecs = adjustedTime;
7045 immutable days = cast(int) splitUnitsFromHNSecs!"days"(hnsecs);
7046
7047 return hnsecs == 0 ? days + 1 : days;
7048 }
7049
7050 ///
7051 @safe unittest
7052 {
7053 import core.time;
7054 import std.datetime.date : DateTime;
7055
7056 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).dayOfGregorianCal == 1);
7057 assert(SysTime(DateTime(1, 12, 31, 23, 59, 59)).dayOfGregorianCal == 365);
7058 assert(SysTime(DateTime(2, 1, 1, 2, 2, 2)).dayOfGregorianCal == 366);
7059
7060 assert(SysTime(DateTime(0, 12, 31, 7, 7, 7)).dayOfGregorianCal == 0);
7061 assert(SysTime(DateTime(0, 1, 1, 19, 30, 0)).dayOfGregorianCal == -365);
7062 assert(SysTime(DateTime(-1, 12, 31, 4, 7, 0)).dayOfGregorianCal == -366);
7063
7064 assert(SysTime(DateTime(2000, 1, 1, 9, 30, 20)).dayOfGregorianCal == 730_120);
7065 assert(SysTime(DateTime(2010, 12, 31, 15, 45, 50)).dayOfGregorianCal == 734_137);
7066 }
7067
7068 @safe unittest
7069 {
7070 import core.time;
7071 // Test A.D.
7072 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).dayOfGregorianCal == 1);
7073 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)).dayOfGregorianCal == 1);
7074 assert(SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)).dayOfGregorianCal == 1);
7075
7076 assert(SysTime(DateTime(1, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 1);
7077 assert(SysTime(DateTime(1, 1, 2, 12, 2, 9), msecs(212)).dayOfGregorianCal == 2);
7078 assert(SysTime(DateTime(1, 2, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 32);
7079 assert(SysTime(DateTime(2, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 366);
7080 assert(SysTime(DateTime(3, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 731);
7081 assert(SysTime(DateTime(4, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 1096);
7082 assert(SysTime(DateTime(5, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 1462);
7083 assert(SysTime(DateTime(50, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 17_898);
7084 assert(SysTime(DateTime(97, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 35_065);
7085 assert(SysTime(DateTime(100, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 36_160);
7086 assert(SysTime(DateTime(101, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 36_525);
7087 assert(SysTime(DateTime(105, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 37_986);
7088 assert(SysTime(DateTime(200, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 72_684);
7089 assert(SysTime(DateTime(201, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 73_049);
7090 assert(SysTime(DateTime(300, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 109_208);
7091 assert(SysTime(DateTime(301, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 109_573);
7092 assert(SysTime(DateTime(400, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 145_732);
7093 assert(SysTime(DateTime(401, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 146_098);
7094 assert(SysTime(DateTime(500, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 182_257);
7095 assert(SysTime(DateTime(501, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 182_622);
7096 assert(SysTime(DateTime(1000, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 364_878);
7097 assert(SysTime(DateTime(1001, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 365_243);
7098 assert(SysTime(DateTime(1600, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 584_023);
7099 assert(SysTime(DateTime(1601, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 584_389);
7100 assert(SysTime(DateTime(1900, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 693_596);
7101 assert(SysTime(DateTime(1901, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 693_961);
7102 assert(SysTime(DateTime(1945, 11, 12, 12, 2, 9), msecs(212)).dayOfGregorianCal == 710_347);
7103 assert(SysTime(DateTime(1999, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 729_755);
7104 assert(SysTime(DateTime(2000, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 730_120);
7105 assert(SysTime(DateTime(2001, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 730_486);
7106
7107 assert(SysTime(DateTime(2010, 1, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_773);
7108 assert(SysTime(DateTime(2010, 1, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_803);
7109 assert(SysTime(DateTime(2010, 2, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_804);
7110 assert(SysTime(DateTime(2010, 2, 28, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_831);
7111 assert(SysTime(DateTime(2010, 3, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_832);
7112 assert(SysTime(DateTime(2010, 3, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_862);
7113 assert(SysTime(DateTime(2010, 4, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_863);
7114 assert(SysTime(DateTime(2010, 4, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_892);
7115 assert(SysTime(DateTime(2010, 5, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_893);
7116 assert(SysTime(DateTime(2010, 5, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_923);
7117 assert(SysTime(DateTime(2010, 6, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_924);
7118 assert(SysTime(DateTime(2010, 6, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_953);
7119 assert(SysTime(DateTime(2010, 7, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_954);
7120 assert(SysTime(DateTime(2010, 7, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_984);
7121 assert(SysTime(DateTime(2010, 8, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_985);
7122 assert(SysTime(DateTime(2010, 8, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_015);
7123 assert(SysTime(DateTime(2010, 9, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_016);
7124 assert(SysTime(DateTime(2010, 9, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_045);
7125 assert(SysTime(DateTime(2010, 10, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_046);
7126 assert(SysTime(DateTime(2010, 10, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_076);
7127 assert(SysTime(DateTime(2010, 11, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_077);
7128 assert(SysTime(DateTime(2010, 11, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_106);
7129 assert(SysTime(DateTime(2010, 12, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_107);
7130 assert(SysTime(DateTime(2010, 12, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_137);
7131
7132 assert(SysTime(DateTime(2012, 2, 1, 0, 0, 0)).dayOfGregorianCal == 734_534);
7133 assert(SysTime(DateTime(2012, 2, 28, 0, 0, 0)).dayOfGregorianCal == 734_561);
7134 assert(SysTime(DateTime(2012, 2, 29, 0, 0, 0)).dayOfGregorianCal == 734_562);
7135 assert(SysTime(DateTime(2012, 3, 1, 0, 0, 0)).dayOfGregorianCal == 734_563);
7136
7137 // Test B.C.
7138 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)).dayOfGregorianCal == 0);
7139 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_998)).dayOfGregorianCal == 0);
7140 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59)).dayOfGregorianCal == 0);
7141 assert(SysTime(DateTime(0, 12, 31, 0, 0, 0), hnsecs(1)).dayOfGregorianCal == 0);
7142 assert(SysTime(DateTime(0, 12, 31, 0, 0, 0)).dayOfGregorianCal == 0);
7143
7144 assert(SysTime(DateTime(-1, 12, 31, 23, 59, 59), hnsecs(9_999_999)).dayOfGregorianCal == -366);
7145 assert(SysTime(DateTime(-1, 12, 31, 23, 59, 59), hnsecs(9_999_998)).dayOfGregorianCal == -366);
7146 assert(SysTime(DateTime(-1, 12, 31, 23, 59, 59)).dayOfGregorianCal == -366);
7147 assert(SysTime(DateTime(-1, 12, 31, 0, 0, 0)).dayOfGregorianCal == -366);
7148
7149 assert(SysTime(DateTime(0, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == 0);
7150 assert(SysTime(DateTime(0, 12, 30, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1);
7151 assert(SysTime(DateTime(0, 12, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -30);
7152 assert(SysTime(DateTime(0, 11, 30, 12, 2, 9), msecs(212)).dayOfGregorianCal == -31);
7153
7154 assert(SysTime(DateTime(-1, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -366);
7155 assert(SysTime(DateTime(-1, 12, 30, 12, 2, 9), msecs(212)).dayOfGregorianCal == -367);
7156 assert(SysTime(DateTime(-1, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -730);
7157 assert(SysTime(DateTime(-2, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -731);
7158 assert(SysTime(DateTime(-2, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1095);
7159 assert(SysTime(DateTime(-3, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1096);
7160 assert(SysTime(DateTime(-3, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1460);
7161 assert(SysTime(DateTime(-4, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1461);
7162 assert(SysTime(DateTime(-4, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1826);
7163 assert(SysTime(DateTime(-5, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1827);
7164 assert(SysTime(DateTime(-5, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -2191);
7165 assert(SysTime(DateTime(-9, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -3652);
7166
7167 assert(SysTime(DateTime(-49, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -18_262);
7168 assert(SysTime(DateTime(-50, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -18_627);
7169 assert(SysTime(DateTime(-97, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -35_794);
7170 assert(SysTime(DateTime(-99, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -36_160);
7171 assert(SysTime(DateTime(-99, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -36_524);
7172 assert(SysTime(DateTime(-100, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -36_889);
7173 assert(SysTime(DateTime(-101, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -37_254);
7174 assert(SysTime(DateTime(-105, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -38_715);
7175 assert(SysTime(DateTime(-200, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -73_413);
7176 assert(SysTime(DateTime(-201, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -73_778);
7177 assert(SysTime(DateTime(-300, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -109_937);
7178 assert(SysTime(DateTime(-301, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -110_302);
7179 assert(SysTime(DateTime(-400, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -146_097);
7180 assert(SysTime(DateTime(-400, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -146_462);
7181 assert(SysTime(DateTime(-401, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -146_827);
7182 assert(SysTime(DateTime(-499, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -182_621);
7183 assert(SysTime(DateTime(-500, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -182_986);
7184 assert(SysTime(DateTime(-501, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -183_351);
7185 assert(SysTime(DateTime(-1000, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -365_607);
7186 assert(SysTime(DateTime(-1001, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -365_972);
7187 assert(SysTime(DateTime(-1599, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -584_387);
7188 assert(SysTime(DateTime(-1600, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -584_388);
7189 assert(SysTime(DateTime(-1600, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -584_753);
7190 assert(SysTime(DateTime(-1601, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -585_118);
7191 assert(SysTime(DateTime(-1900, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -694_325);
7192 assert(SysTime(DateTime(-1901, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -694_690);
7193 assert(SysTime(DateTime(-1999, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -730_484);
7194 assert(SysTime(DateTime(-2000, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -730_485);
7195 assert(SysTime(DateTime(-2000, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -730_850);
7196 assert(SysTime(DateTime(-2001, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -731_215);
7197
7198 assert(SysTime(DateTime(-2010, 1, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_502);
7199 assert(SysTime(DateTime(-2010, 1, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_472);
7200 assert(SysTime(DateTime(-2010, 2, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_471);
7201 assert(SysTime(DateTime(-2010, 2, 28, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_444);
7202 assert(SysTime(DateTime(-2010, 3, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_443);
7203 assert(SysTime(DateTime(-2010, 3, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_413);
7204 assert(SysTime(DateTime(-2010, 4, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_412);
7205 assert(SysTime(DateTime(-2010, 4, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_383);
7206 assert(SysTime(DateTime(-2010, 5, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_382);
7207 assert(SysTime(DateTime(-2010, 5, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_352);
7208 assert(SysTime(DateTime(-2010, 6, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_351);
7209 assert(SysTime(DateTime(-2010, 6, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_322);
7210 assert(SysTime(DateTime(-2010, 7, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_321);
7211 assert(SysTime(DateTime(-2010, 7, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_291);
7212 assert(SysTime(DateTime(-2010, 8, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_290);
7213 assert(SysTime(DateTime(-2010, 8, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_260);
7214 assert(SysTime(DateTime(-2010, 9, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_259);
7215 assert(SysTime(DateTime(-2010, 9, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_230);
7216 assert(SysTime(DateTime(-2010, 10, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_229);
7217 assert(SysTime(DateTime(-2010, 10, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_199);
7218 assert(SysTime(DateTime(-2010, 11, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_198);
7219 assert(SysTime(DateTime(-2010, 11, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_169);
7220 assert(SysTime(DateTime(-2010, 12, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_168);
7221 assert(SysTime(DateTime(-2010, 12, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_138);
7222
7223 assert(SysTime(DateTime(-2012, 2, 1, 0, 0, 0)).dayOfGregorianCal == -735_202);
7224 assert(SysTime(DateTime(-2012, 2, 28, 0, 0, 0)).dayOfGregorianCal == -735_175);
7225 assert(SysTime(DateTime(-2012, 2, 29, 0, 0, 0)).dayOfGregorianCal == -735_174);
7226 assert(SysTime(DateTime(-2012, 3, 1, 0, 0, 0)).dayOfGregorianCal == -735_173);
7227
7228 // Start of Hebrew Calendar
7229 assert(SysTime(DateTime(-3760, 9, 7, 0, 0, 0)).dayOfGregorianCal == -1_373_427);
7230
7231 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7232 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7233 assert(cst.dayOfGregorianCal == 729_941);
7234 assert(ist.dayOfGregorianCal == 729_941);
7235
7236 static void testScope(scope ref SysTime st) @safe
7237 {
7238 auto result = st.dayOfGregorianCal;
7239 }
7240 }
7241
7242
7243 // Test that the logic for the day of the Gregorian Calendar is consistent
7244 // between Date and SysTime.
7245 @safe unittest
7246 {
7247 import core.time;
7248 void test(Date date, SysTime st, size_t line = __LINE__)
7249 {
7250 if (date.dayOfGregorianCal != st.dayOfGregorianCal)
7251 {
7252 throw new AssertError(format("Date [%s] SysTime [%s]", date.dayOfGregorianCal, st.dayOfGregorianCal),
7253 __FILE__, line);
7254 }
7255 }
7256
7257 // Test A.D.
7258 test(Date(1, 1, 1), SysTime(DateTime(1, 1, 1, 0, 0, 0)));
7259 test(Date(1, 1, 2), SysTime(DateTime(1, 1, 2, 0, 0, 0), hnsecs(500)));
7260 test(Date(1, 2, 1), SysTime(DateTime(1, 2, 1, 0, 0, 0), hnsecs(50_000)));
7261 test(Date(2, 1, 1), SysTime(DateTime(2, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
7262 test(Date(3, 1, 1), SysTime(DateTime(3, 1, 1, 12, 13, 14)));
7263 test(Date(4, 1, 1), SysTime(DateTime(4, 1, 1, 12, 13, 14), hnsecs(500)));
7264 test(Date(5, 1, 1), SysTime(DateTime(5, 1, 1, 12, 13, 14), hnsecs(50_000)));
7265 test(Date(50, 1, 1), SysTime(DateTime(50, 1, 1, 12, 13, 14), hnsecs(9_999_999)));
7266 test(Date(97, 1, 1), SysTime(DateTime(97, 1, 1, 23, 59, 59)));
7267 test(Date(100, 1, 1), SysTime(DateTime(100, 1, 1, 23, 59, 59), hnsecs(500)));
7268 test(Date(101, 1, 1), SysTime(DateTime(101, 1, 1, 23, 59, 59), hnsecs(50_000)));
7269 test(Date(105, 1, 1), SysTime(DateTime(105, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
7270 test(Date(200, 1, 1), SysTime(DateTime(200, 1, 1, 0, 0, 0)));
7271 test(Date(201, 1, 1), SysTime(DateTime(201, 1, 1, 0, 0, 0), hnsecs(500)));
7272 test(Date(300, 1, 1), SysTime(DateTime(300, 1, 1, 0, 0, 0), hnsecs(50_000)));
7273 test(Date(301, 1, 1), SysTime(DateTime(301, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
7274 test(Date(400, 1, 1), SysTime(DateTime(400, 1, 1, 12, 13, 14)));
7275 test(Date(401, 1, 1), SysTime(DateTime(401, 1, 1, 12, 13, 14), hnsecs(500)));
7276 test(Date(500, 1, 1), SysTime(DateTime(500, 1, 1, 12, 13, 14), hnsecs(50_000)));
7277 test(Date(501, 1, 1), SysTime(DateTime(501, 1, 1, 12, 13, 14), hnsecs(9_999_999)));
7278 test(Date(1000, 1, 1), SysTime(DateTime(1000, 1, 1, 23, 59, 59)));
7279 test(Date(1001, 1, 1), SysTime(DateTime(1001, 1, 1, 23, 59, 59), hnsecs(500)));
7280 test(Date(1600, 1, 1), SysTime(DateTime(1600, 1, 1, 23, 59, 59), hnsecs(50_000)));
7281 test(Date(1601, 1, 1), SysTime(DateTime(1601, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
7282 test(Date(1900, 1, 1), SysTime(DateTime(1900, 1, 1, 0, 0, 0)));
7283 test(Date(1901, 1, 1), SysTime(DateTime(1901, 1, 1, 0, 0, 0), hnsecs(500)));
7284 test(Date(1945, 11, 12), SysTime(DateTime(1945, 11, 12, 0, 0, 0), hnsecs(50_000)));
7285 test(Date(1999, 1, 1), SysTime(DateTime(1999, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
7286 test(Date(1999, 7, 6), SysTime(DateTime(1999, 7, 6, 12, 13, 14)));
7287 test(Date(2000, 1, 1), SysTime(DateTime(2000, 1, 1, 12, 13, 14), hnsecs(500)));
7288 test(Date(2001, 1, 1), SysTime(DateTime(2001, 1, 1, 12, 13, 14), hnsecs(50_000)));
7289
7290 test(Date(2010, 1, 1), SysTime(DateTime(2010, 1, 1, 12, 13, 14), hnsecs(9_999_999)));
7291 test(Date(2010, 1, 31), SysTime(DateTime(2010, 1, 31, 23, 0, 0)));
7292 test(Date(2010, 2, 1), SysTime(DateTime(2010, 2, 1, 23, 59, 59), hnsecs(500)));
7293 test(Date(2010, 2, 28), SysTime(DateTime(2010, 2, 28, 23, 59, 59), hnsecs(50_000)));
7294 test(Date(2010, 3, 1), SysTime(DateTime(2010, 3, 1, 23, 59, 59), hnsecs(9_999_999)));
7295 test(Date(2010, 3, 31), SysTime(DateTime(2010, 3, 31, 0, 0, 0)));
7296 test(Date(2010, 4, 1), SysTime(DateTime(2010, 4, 1, 0, 0, 0), hnsecs(500)));
7297 test(Date(2010, 4, 30), SysTime(DateTime(2010, 4, 30, 0, 0, 0), hnsecs(50_000)));
7298 test(Date(2010, 5, 1), SysTime(DateTime(2010, 5, 1, 0, 0, 0), hnsecs(9_999_999)));
7299 test(Date(2010, 5, 31), SysTime(DateTime(2010, 5, 31, 12, 13, 14)));
7300 test(Date(2010, 6, 1), SysTime(DateTime(2010, 6, 1, 12, 13, 14), hnsecs(500)));
7301 test(Date(2010, 6, 30), SysTime(DateTime(2010, 6, 30, 12, 13, 14), hnsecs(50_000)));
7302 test(Date(2010, 7, 1), SysTime(DateTime(2010, 7, 1, 12, 13, 14), hnsecs(9_999_999)));
7303 test(Date(2010, 7, 31), SysTime(DateTime(2010, 7, 31, 23, 59, 59)));
7304 test(Date(2010, 8, 1), SysTime(DateTime(2010, 8, 1, 23, 59, 59), hnsecs(500)));
7305 test(Date(2010, 8, 31), SysTime(DateTime(2010, 8, 31, 23, 59, 59), hnsecs(50_000)));
7306 test(Date(2010, 9, 1), SysTime(DateTime(2010, 9, 1, 23, 59, 59), hnsecs(9_999_999)));
7307 test(Date(2010, 9, 30), SysTime(DateTime(2010, 9, 30, 12, 0, 0)));
7308 test(Date(2010, 10, 1), SysTime(DateTime(2010, 10, 1, 0, 12, 0), hnsecs(500)));
7309 test(Date(2010, 10, 31), SysTime(DateTime(2010, 10, 31, 0, 0, 12), hnsecs(50_000)));
7310 test(Date(2010, 11, 1), SysTime(DateTime(2010, 11, 1, 23, 0, 0), hnsecs(9_999_999)));
7311 test(Date(2010, 11, 30), SysTime(DateTime(2010, 11, 30, 0, 59, 0)));
7312 test(Date(2010, 12, 1), SysTime(DateTime(2010, 12, 1, 0, 0, 59), hnsecs(500)));
7313 test(Date(2010, 12, 31), SysTime(DateTime(2010, 12, 31, 0, 59, 59), hnsecs(50_000)));
7314
7315 test(Date(2012, 2, 1), SysTime(DateTime(2012, 2, 1, 23, 0, 59), hnsecs(9_999_999)));
7316 test(Date(2012, 2, 28), SysTime(DateTime(2012, 2, 28, 23, 59, 0)));
7317 test(Date(2012, 2, 29), SysTime(DateTime(2012, 2, 29, 7, 7, 7), hnsecs(7)));
7318 test(Date(2012, 3, 1), SysTime(DateTime(2012, 3, 1, 7, 7, 7), hnsecs(7)));
7319
7320 // Test B.C.
7321 test(Date(0, 12, 31), SysTime(DateTime(0, 12, 31, 0, 0, 0)));
7322 test(Date(0, 12, 30), SysTime(DateTime(0, 12, 30, 0, 0, 0), hnsecs(500)));
7323 test(Date(0, 12, 1), SysTime(DateTime(0, 12, 1, 0, 0, 0), hnsecs(50_000)));
7324 test(Date(0, 11, 30), SysTime(DateTime(0, 11, 30, 0, 0, 0), hnsecs(9_999_999)));
7325
7326 test(Date(-1, 12, 31), SysTime(DateTime(-1, 12, 31, 12, 13, 14)));
7327 test(Date(-1, 12, 30), SysTime(DateTime(-1, 12, 30, 12, 13, 14), hnsecs(500)));
7328 test(Date(-1, 1, 1), SysTime(DateTime(-1, 1, 1, 12, 13, 14), hnsecs(50_000)));
7329 test(Date(-2, 12, 31), SysTime(DateTime(-2, 12, 31, 12, 13, 14), hnsecs(9_999_999)));
7330 test(Date(-2, 1, 1), SysTime(DateTime(-2, 1, 1, 23, 59, 59)));
7331 test(Date(-3, 12, 31), SysTime(DateTime(-3, 12, 31, 23, 59, 59), hnsecs(500)));
7332 test(Date(-3, 1, 1), SysTime(DateTime(-3, 1, 1, 23, 59, 59), hnsecs(50_000)));
7333 test(Date(-4, 12, 31), SysTime(DateTime(-4, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
7334 test(Date(-4, 1, 1), SysTime(DateTime(-4, 1, 1, 0, 0, 0)));
7335 test(Date(-5, 12, 31), SysTime(DateTime(-5, 12, 31, 0, 0, 0), hnsecs(500)));
7336 test(Date(-5, 1, 1), SysTime(DateTime(-5, 1, 1, 0, 0, 0), hnsecs(50_000)));
7337 test(Date(-9, 1, 1), SysTime(DateTime(-9, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
7338
7339 test(Date(-49, 1, 1), SysTime(DateTime(-49, 1, 1, 12, 13, 14)));
7340 test(Date(-50, 1, 1), SysTime(DateTime(-50, 1, 1, 12, 13, 14), hnsecs(500)));
7341 test(Date(-97, 1, 1), SysTime(DateTime(-97, 1, 1, 12, 13, 14), hnsecs(50_000)));
7342 test(Date(-99, 12, 31), SysTime(DateTime(-99, 12, 31, 12, 13, 14), hnsecs(9_999_999)));
7343 test(Date(-99, 1, 1), SysTime(DateTime(-99, 1, 1, 23, 59, 59)));
7344 test(Date(-100, 1, 1), SysTime(DateTime(-100, 1, 1, 23, 59, 59), hnsecs(500)));
7345 test(Date(-101, 1, 1), SysTime(DateTime(-101, 1, 1, 23, 59, 59), hnsecs(50_000)));
7346 test(Date(-105, 1, 1), SysTime(DateTime(-105, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
7347 test(Date(-200, 1, 1), SysTime(DateTime(-200, 1, 1, 0, 0, 0)));
7348 test(Date(-201, 1, 1), SysTime(DateTime(-201, 1, 1, 0, 0, 0), hnsecs(500)));
7349 test(Date(-300, 1, 1), SysTime(DateTime(-300, 1, 1, 0, 0, 0), hnsecs(50_000)));
7350 test(Date(-301, 1, 1), SysTime(DateTime(-301, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
7351 test(Date(-400, 12, 31), SysTime(DateTime(-400, 12, 31, 12, 13, 14)));
7352 test(Date(-400, 1, 1), SysTime(DateTime(-400, 1, 1, 12, 13, 14), hnsecs(500)));
7353 test(Date(-401, 1, 1), SysTime(DateTime(-401, 1, 1, 12, 13, 14), hnsecs(50_000)));
7354 test(Date(-499, 1, 1), SysTime(DateTime(-499, 1, 1, 12, 13, 14), hnsecs(9_999_999)));
7355 test(Date(-500, 1, 1), SysTime(DateTime(-500, 1, 1, 23, 59, 59)));
7356 test(Date(-501, 1, 1), SysTime(DateTime(-501, 1, 1, 23, 59, 59), hnsecs(500)));
7357 test(Date(-1000, 1, 1), SysTime(DateTime(-1000, 1, 1, 23, 59, 59), hnsecs(50_000)));
7358 test(Date(-1001, 1, 1), SysTime(DateTime(-1001, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
7359 test(Date(-1599, 1, 1), SysTime(DateTime(-1599, 1, 1, 0, 0, 0)));
7360 test(Date(-1600, 12, 31), SysTime(DateTime(-1600, 12, 31, 0, 0, 0), hnsecs(500)));
7361 test(Date(-1600, 1, 1), SysTime(DateTime(-1600, 1, 1, 0, 0, 0), hnsecs(50_000)));
7362 test(Date(-1601, 1, 1), SysTime(DateTime(-1601, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
7363 test(Date(-1900, 1, 1), SysTime(DateTime(-1900, 1, 1, 12, 13, 14)));
7364 test(Date(-1901, 1, 1), SysTime(DateTime(-1901, 1, 1, 12, 13, 14), hnsecs(500)));
7365 test(Date(-1999, 1, 1), SysTime(DateTime(-1999, 1, 1, 12, 13, 14), hnsecs(50_000)));
7366 test(Date(-1999, 7, 6), SysTime(DateTime(-1999, 7, 6, 12, 13, 14), hnsecs(9_999_999)));
7367 test(Date(-2000, 12, 31), SysTime(DateTime(-2000, 12, 31, 23, 59, 59)));
7368 test(Date(-2000, 1, 1), SysTime(DateTime(-2000, 1, 1, 23, 59, 59), hnsecs(500)));
7369 test(Date(-2001, 1, 1), SysTime(DateTime(-2001, 1, 1, 23, 59, 59), hnsecs(50_000)));
7370
7371 test(Date(-2010, 1, 1), SysTime(DateTime(-2010, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
7372 test(Date(-2010, 1, 31), SysTime(DateTime(-2010, 1, 31, 0, 0, 0)));
7373 test(Date(-2010, 2, 1), SysTime(DateTime(-2010, 2, 1, 0, 0, 0), hnsecs(500)));
7374 test(Date(-2010, 2, 28), SysTime(DateTime(-2010, 2, 28, 0, 0, 0), hnsecs(50_000)));
7375 test(Date(-2010, 3, 1), SysTime(DateTime(-2010, 3, 1, 0, 0, 0), hnsecs(9_999_999)));
7376 test(Date(-2010, 3, 31), SysTime(DateTime(-2010, 3, 31, 12, 13, 14)));
7377 test(Date(-2010, 4, 1), SysTime(DateTime(-2010, 4, 1, 12, 13, 14), hnsecs(500)));
7378 test(Date(-2010, 4, 30), SysTime(DateTime(-2010, 4, 30, 12, 13, 14), hnsecs(50_000)));
7379 test(Date(-2010, 5, 1), SysTime(DateTime(-2010, 5, 1, 12, 13, 14), hnsecs(9_999_999)));
7380 test(Date(-2010, 5, 31), SysTime(DateTime(-2010, 5, 31, 23, 59, 59)));
7381 test(Date(-2010, 6, 1), SysTime(DateTime(-2010, 6, 1, 23, 59, 59), hnsecs(500)));
7382 test(Date(-2010, 6, 30), SysTime(DateTime(-2010, 6, 30, 23, 59, 59), hnsecs(50_000)));
7383 test(Date(-2010, 7, 1), SysTime(DateTime(-2010, 7, 1, 23, 59, 59), hnsecs(9_999_999)));
7384 test(Date(-2010, 7, 31), SysTime(DateTime(-2010, 7, 31, 0, 0, 0)));
7385 test(Date(-2010, 8, 1), SysTime(DateTime(-2010, 8, 1, 0, 0, 0), hnsecs(500)));
7386 test(Date(-2010, 8, 31), SysTime(DateTime(-2010, 8, 31, 0, 0, 0), hnsecs(50_000)));
7387 test(Date(-2010, 9, 1), SysTime(DateTime(-2010, 9, 1, 0, 0, 0), hnsecs(9_999_999)));
7388 test(Date(-2010, 9, 30), SysTime(DateTime(-2010, 9, 30, 12, 0, 0)));
7389 test(Date(-2010, 10, 1), SysTime(DateTime(-2010, 10, 1, 0, 12, 0), hnsecs(500)));
7390 test(Date(-2010, 10, 31), SysTime(DateTime(-2010, 10, 31, 0, 0, 12), hnsecs(50_000)));
7391 test(Date(-2010, 11, 1), SysTime(DateTime(-2010, 11, 1, 23, 0, 0), hnsecs(9_999_999)));
7392 test(Date(-2010, 11, 30), SysTime(DateTime(-2010, 11, 30, 0, 59, 0)));
7393 test(Date(-2010, 12, 1), SysTime(DateTime(-2010, 12, 1, 0, 0, 59), hnsecs(500)));
7394 test(Date(-2010, 12, 31), SysTime(DateTime(-2010, 12, 31, 0, 59, 59), hnsecs(50_000)));
7395
7396 test(Date(-2012, 2, 1), SysTime(DateTime(-2012, 2, 1, 23, 0, 59), hnsecs(9_999_999)));
7397 test(Date(-2012, 2, 28), SysTime(DateTime(-2012, 2, 28, 23, 59, 0)));
7398 test(Date(-2012, 2, 29), SysTime(DateTime(-2012, 2, 29, 7, 7, 7), hnsecs(7)));
7399 test(Date(-2012, 3, 1), SysTime(DateTime(-2012, 3, 1, 7, 7, 7), hnsecs(7)));
7400
7401 test(Date(-3760, 9, 7), SysTime(DateTime(-3760, 9, 7, 0, 0, 0)));
7402 }
7403
7404
7405 /++
7406 The Xth day of the Gregorian Calendar that this $(LREF SysTime) is on.
7407 Setting this property does not affect the time portion of $(LREF SysTime).
7408
7409 Params:
7410 days = The day of the Gregorian Calendar to set this $(LREF SysTime)
7411 to.
7412 +/
7413 @property void dayOfGregorianCal(int days) @safe nothrow scope
7414 {
7415 auto hnsecs = adjTime;
7416 hnsecs = removeUnitsFromHNSecs!"days"(hnsecs);
7417
7418 if (hnsecs < 0)
7419 hnsecs += convert!("hours", "hnsecs")(24);
7420
7421 if (--days < 0)
7422 {
7423 hnsecs -= convert!("hours", "hnsecs")(24);
7424 ++days;
7425 }
7426
7427 immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
7428
7429 adjTime = newDaysHNSecs + hnsecs;
7430 }
7431
7432 ///
7433 @safe unittest
7434 {
7435 import core.time;
7436 import std.datetime.date : DateTime;
7437
7438 auto st = SysTime(DateTime(0, 1, 1, 12, 0, 0));
7439 st.dayOfGregorianCal = 1;
7440 assert(st == SysTime(DateTime(1, 1, 1, 12, 0, 0)));
7441
7442 st.dayOfGregorianCal = 365;
7443 assert(st == SysTime(DateTime(1, 12, 31, 12, 0, 0)));
7444
7445 st.dayOfGregorianCal = 366;
7446 assert(st == SysTime(DateTime(2, 1, 1, 12, 0, 0)));
7447
7448 st.dayOfGregorianCal = 0;
7449 assert(st == SysTime(DateTime(0, 12, 31, 12, 0, 0)));
7450
7451 st.dayOfGregorianCal = -365;
7452 assert(st == SysTime(DateTime(-0, 1, 1, 12, 0, 0)));
7453
7454 st.dayOfGregorianCal = -366;
7455 assert(st == SysTime(DateTime(-1, 12, 31, 12, 0, 0)));
7456
7457 st.dayOfGregorianCal = 730_120;
7458 assert(st == SysTime(DateTime(2000, 1, 1, 12, 0, 0)));
7459
7460 st.dayOfGregorianCal = 734_137;
7461 assert(st == SysTime(DateTime(2010, 12, 31, 12, 0, 0)));
7462 }
7463
7464 @safe unittest
7465 {
7466 import core.time;
7467 void testST(SysTime orig, int day, SysTime expected, size_t line = __LINE__) @safe
7468 {
7469 orig.dayOfGregorianCal = day;
7470 if (orig != expected)
7471 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
7472 }
7473
7474 // Test A.D.
7475 testST(SysTime(DateTime(1, 1, 1, 0, 0, 0)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
7476 testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)));
7477 testST(SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)), 1,
7478 SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
7479
7480 // Test B.C.
7481 testST(SysTime(DateTime(0, 1, 1, 0, 0, 0)), 0, SysTime(DateTime(0, 12, 31, 0, 0, 0)));
7482 testST(SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)), 0,
7483 SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
7484 testST(SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(1)), 0,
7485 SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1)));
7486 testST(SysTime(DateTime(0, 1, 1, 23, 59, 59)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59)));
7487
7488 // Test Both.
7489 testST(SysTime(DateTime(-512, 7, 20, 0, 0, 0)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
7490 testST(SysTime(DateTime(-513, 6, 6, 0, 0, 0), hnsecs(1)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)));
7491 testST(SysTime(DateTime(-511, 5, 7, 23, 59, 59), hnsecs(9_999_999)), 1,
7492 SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
7493
7494 testST(SysTime(DateTime(1607, 4, 8, 0, 0, 0)), 0, SysTime(DateTime(0, 12, 31, 0, 0, 0)));
7495 testST(SysTime(DateTime(1500, 3, 9, 23, 59, 59), hnsecs(9_999_999)), 0,
7496 SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
7497 testST(SysTime(DateTime(999, 2, 10, 23, 59, 59), hnsecs(1)), 0,
7498 SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1)));
7499 testST(SysTime(DateTime(2007, 12, 11, 23, 59, 59)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59)));
7500
7501
7502 auto st = SysTime(DateTime(1, 1, 1, 12, 2, 9), msecs(212));
7503
7504 void testST2(int day, SysTime expected, size_t line = __LINE__) @safe
7505 {
7506 st.dayOfGregorianCal = day;
7507 if (st != expected)
7508 throw new AssertError(format("Failed. actual [%s] != expected [%s]", st, expected), __FILE__, line);
7509 }
7510
7511 // Test A.D.
7512 testST2(1, SysTime(DateTime(1, 1, 1, 12, 2, 9), msecs(212)));
7513 testST2(2, SysTime(DateTime(1, 1, 2, 12, 2, 9), msecs(212)));
7514 testST2(32, SysTime(DateTime(1, 2, 1, 12, 2, 9), msecs(212)));
7515 testST2(366, SysTime(DateTime(2, 1, 1, 12, 2, 9), msecs(212)));
7516 testST2(731, SysTime(DateTime(3, 1, 1, 12, 2, 9), msecs(212)));
7517 testST2(1096, SysTime(DateTime(4, 1, 1, 12, 2, 9), msecs(212)));
7518 testST2(1462, SysTime(DateTime(5, 1, 1, 12, 2, 9), msecs(212)));
7519 testST2(17_898, SysTime(DateTime(50, 1, 1, 12, 2, 9), msecs(212)));
7520 testST2(35_065, SysTime(DateTime(97, 1, 1, 12, 2, 9), msecs(212)));
7521 testST2(36_160, SysTime(DateTime(100, 1, 1, 12, 2, 9), msecs(212)));
7522 testST2(36_525, SysTime(DateTime(101, 1, 1, 12, 2, 9), msecs(212)));
7523 testST2(37_986, SysTime(DateTime(105, 1, 1, 12, 2, 9), msecs(212)));
7524 testST2(72_684, SysTime(DateTime(200, 1, 1, 12, 2, 9), msecs(212)));
7525 testST2(73_049, SysTime(DateTime(201, 1, 1, 12, 2, 9), msecs(212)));
7526 testST2(109_208, SysTime(DateTime(300, 1, 1, 12, 2, 9), msecs(212)));
7527 testST2(109_573, SysTime(DateTime(301, 1, 1, 12, 2, 9), msecs(212)));
7528 testST2(145_732, SysTime(DateTime(400, 1, 1, 12, 2, 9), msecs(212)));
7529 testST2(146_098, SysTime(DateTime(401, 1, 1, 12, 2, 9), msecs(212)));
7530 testST2(182_257, SysTime(DateTime(500, 1, 1, 12, 2, 9), msecs(212)));
7531 testST2(182_622, SysTime(DateTime(501, 1, 1, 12, 2, 9), msecs(212)));
7532 testST2(364_878, SysTime(DateTime(1000, 1, 1, 12, 2, 9), msecs(212)));
7533 testST2(365_243, SysTime(DateTime(1001, 1, 1, 12, 2, 9), msecs(212)));
7534 testST2(584_023, SysTime(DateTime(1600, 1, 1, 12, 2, 9), msecs(212)));
7535 testST2(584_389, SysTime(DateTime(1601, 1, 1, 12, 2, 9), msecs(212)));
7536 testST2(693_596, SysTime(DateTime(1900, 1, 1, 12, 2, 9), msecs(212)));
7537 testST2(693_961, SysTime(DateTime(1901, 1, 1, 12, 2, 9), msecs(212)));
7538 testST2(729_755, SysTime(DateTime(1999, 1, 1, 12, 2, 9), msecs(212)));
7539 testST2(730_120, SysTime(DateTime(2000, 1, 1, 12, 2, 9), msecs(212)));
7540 testST2(730_486, SysTime(DateTime(2001, 1, 1, 12, 2, 9), msecs(212)));
7541
7542 testST2(733_773, SysTime(DateTime(2010, 1, 1, 12, 2, 9), msecs(212)));
7543 testST2(733_803, SysTime(DateTime(2010, 1, 31, 12, 2, 9), msecs(212)));
7544 testST2(733_804, SysTime(DateTime(2010, 2, 1, 12, 2, 9), msecs(212)));
7545 testST2(733_831, SysTime(DateTime(2010, 2, 28, 12, 2, 9), msecs(212)));
7546 testST2(733_832, SysTime(DateTime(2010, 3, 1, 12, 2, 9), msecs(212)));
7547 testST2(733_862, SysTime(DateTime(2010, 3, 31, 12, 2, 9), msecs(212)));
7548 testST2(733_863, SysTime(DateTime(2010, 4, 1, 12, 2, 9), msecs(212)));
7549 testST2(733_892, SysTime(DateTime(2010, 4, 30, 12, 2, 9), msecs(212)));
7550 testST2(733_893, SysTime(DateTime(2010, 5, 1, 12, 2, 9), msecs(212)));
7551 testST2(733_923, SysTime(DateTime(2010, 5, 31, 12, 2, 9), msecs(212)));
7552 testST2(733_924, SysTime(DateTime(2010, 6, 1, 12, 2, 9), msecs(212)));
7553 testST2(733_953, SysTime(DateTime(2010, 6, 30, 12, 2, 9), msecs(212)));
7554 testST2(733_954, SysTime(DateTime(2010, 7, 1, 12, 2, 9), msecs(212)));
7555 testST2(733_984, SysTime(DateTime(2010, 7, 31, 12, 2, 9), msecs(212)));
7556 testST2(733_985, SysTime(DateTime(2010, 8, 1, 12, 2, 9), msecs(212)));
7557 testST2(734_015, SysTime(DateTime(2010, 8, 31, 12, 2, 9), msecs(212)));
7558 testST2(734_016, SysTime(DateTime(2010, 9, 1, 12, 2, 9), msecs(212)));
7559 testST2(734_045, SysTime(DateTime(2010, 9, 30, 12, 2, 9), msecs(212)));
7560 testST2(734_046, SysTime(DateTime(2010, 10, 1, 12, 2, 9), msecs(212)));
7561 testST2(734_076, SysTime(DateTime(2010, 10, 31, 12, 2, 9), msecs(212)));
7562 testST2(734_077, SysTime(DateTime(2010, 11, 1, 12, 2, 9), msecs(212)));
7563 testST2(734_106, SysTime(DateTime(2010, 11, 30, 12, 2, 9), msecs(212)));
7564 testST2(734_107, SysTime(DateTime(2010, 12, 1, 12, 2, 9), msecs(212)));
7565 testST2(734_137, SysTime(DateTime(2010, 12, 31, 12, 2, 9), msecs(212)));
7566
7567 testST2(734_534, SysTime(DateTime(2012, 2, 1, 12, 2, 9), msecs(212)));
7568 testST2(734_561, SysTime(DateTime(2012, 2, 28, 12, 2, 9), msecs(212)));
7569 testST2(734_562, SysTime(DateTime(2012, 2, 29, 12, 2, 9), msecs(212)));
7570 testST2(734_563, SysTime(DateTime(2012, 3, 1, 12, 2, 9), msecs(212)));
7571
7572 testST2(734_534, SysTime(DateTime(2012, 2, 1, 12, 2, 9), msecs(212)));
7573
7574 testST2(734_561, SysTime(DateTime(2012, 2, 28, 12, 2, 9), msecs(212)));
7575 testST2(734_562, SysTime(DateTime(2012, 2, 29, 12, 2, 9), msecs(212)));
7576 testST2(734_563, SysTime(DateTime(2012, 3, 1, 12, 2, 9), msecs(212)));
7577
7578 // Test B.C.
7579 testST2(0, SysTime(DateTime(0, 12, 31, 12, 2, 9), msecs(212)));
7580 testST2(-1, SysTime(DateTime(0, 12, 30, 12, 2, 9), msecs(212)));
7581 testST2(-30, SysTime(DateTime(0, 12, 1, 12, 2, 9), msecs(212)));
7582 testST2(-31, SysTime(DateTime(0, 11, 30, 12, 2, 9), msecs(212)));
7583
7584 testST2(-366, SysTime(DateTime(-1, 12, 31, 12, 2, 9), msecs(212)));
7585 testST2(-367, SysTime(DateTime(-1, 12, 30, 12, 2, 9), msecs(212)));
7586 testST2(-730, SysTime(DateTime(-1, 1, 1, 12, 2, 9), msecs(212)));
7587 testST2(-731, SysTime(DateTime(-2, 12, 31, 12, 2, 9), msecs(212)));
7588 testST2(-1095, SysTime(DateTime(-2, 1, 1, 12, 2, 9), msecs(212)));
7589 testST2(-1096, SysTime(DateTime(-3, 12, 31, 12, 2, 9), msecs(212)));
7590 testST2(-1460, SysTime(DateTime(-3, 1, 1, 12, 2, 9), msecs(212)));
7591 testST2(-1461, SysTime(DateTime(-4, 12, 31, 12, 2, 9), msecs(212)));
7592 testST2(-1826, SysTime(DateTime(-4, 1, 1, 12, 2, 9), msecs(212)));
7593 testST2(-1827, SysTime(DateTime(-5, 12, 31, 12, 2, 9), msecs(212)));
7594 testST2(-2191, SysTime(DateTime(-5, 1, 1, 12, 2, 9), msecs(212)));
7595 testST2(-3652, SysTime(DateTime(-9, 1, 1, 12, 2, 9), msecs(212)));
7596
7597 testST2(-18_262, SysTime(DateTime(-49, 1, 1, 12, 2, 9), msecs(212)));
7598 testST2(-18_627, SysTime(DateTime(-50, 1, 1, 12, 2, 9), msecs(212)));
7599 testST2(-35_794, SysTime(DateTime(-97, 1, 1, 12, 2, 9), msecs(212)));
7600 testST2(-36_160, SysTime(DateTime(-99, 12, 31, 12, 2, 9), msecs(212)));
7601 testST2(-36_524, SysTime(DateTime(-99, 1, 1, 12, 2, 9), msecs(212)));
7602 testST2(-36_889, SysTime(DateTime(-100, 1, 1, 12, 2, 9), msecs(212)));
7603 testST2(-37_254, SysTime(DateTime(-101, 1, 1, 12, 2, 9), msecs(212)));
7604 testST2(-38_715, SysTime(DateTime(-105, 1, 1, 12, 2, 9), msecs(212)));
7605 testST2(-73_413, SysTime(DateTime(-200, 1, 1, 12, 2, 9), msecs(212)));
7606 testST2(-73_778, SysTime(DateTime(-201, 1, 1, 12, 2, 9), msecs(212)));
7607 testST2(-109_937, SysTime(DateTime(-300, 1, 1, 12, 2, 9), msecs(212)));
7608 testST2(-110_302, SysTime(DateTime(-301, 1, 1, 12, 2, 9), msecs(212)));
7609 testST2(-146_097, SysTime(DateTime(-400, 12, 31, 12, 2, 9), msecs(212)));
7610 testST2(-146_462, SysTime(DateTime(-400, 1, 1, 12, 2, 9), msecs(212)));
7611 testST2(-146_827, SysTime(DateTime(-401, 1, 1, 12, 2, 9), msecs(212)));
7612 testST2(-182_621, SysTime(DateTime(-499, 1, 1, 12, 2, 9), msecs(212)));
7613 testST2(-182_986, SysTime(DateTime(-500, 1, 1, 12, 2, 9), msecs(212)));
7614 testST2(-183_351, SysTime(DateTime(-501, 1, 1, 12, 2, 9), msecs(212)));
7615 testST2(-365_607, SysTime(DateTime(-1000, 1, 1, 12, 2, 9), msecs(212)));
7616 testST2(-365_972, SysTime(DateTime(-1001, 1, 1, 12, 2, 9), msecs(212)));
7617 testST2(-584_387, SysTime(DateTime(-1599, 1, 1, 12, 2, 9), msecs(212)));
7618 testST2(-584_388, SysTime(DateTime(-1600, 12, 31, 12, 2, 9), msecs(212)));
7619 testST2(-584_753, SysTime(DateTime(-1600, 1, 1, 12, 2, 9), msecs(212)));
7620 testST2(-585_118, SysTime(DateTime(-1601, 1, 1, 12, 2, 9), msecs(212)));
7621 testST2(-694_325, SysTime(DateTime(-1900, 1, 1, 12, 2, 9), msecs(212)));
7622 testST2(-694_690, SysTime(DateTime(-1901, 1, 1, 12, 2, 9), msecs(212)));
7623 testST2(-730_484, SysTime(DateTime(-1999, 1, 1, 12, 2, 9), msecs(212)));
7624 testST2(-730_485, SysTime(DateTime(-2000, 12, 31, 12, 2, 9), msecs(212)));
7625 testST2(-730_850, SysTime(DateTime(-2000, 1, 1, 12, 2, 9), msecs(212)));
7626 testST2(-731_215, SysTime(DateTime(-2001, 1, 1, 12, 2, 9), msecs(212)));
7627
7628 testST2(-734_502, SysTime(DateTime(-2010, 1, 1, 12, 2, 9), msecs(212)));
7629 testST2(-734_472, SysTime(DateTime(-2010, 1, 31, 12, 2, 9), msecs(212)));
7630 testST2(-734_471, SysTime(DateTime(-2010, 2, 1, 12, 2, 9), msecs(212)));
7631 testST2(-734_444, SysTime(DateTime(-2010, 2, 28, 12, 2, 9), msecs(212)));
7632 testST2(-734_443, SysTime(DateTime(-2010, 3, 1, 12, 2, 9), msecs(212)));
7633 testST2(-734_413, SysTime(DateTime(-2010, 3, 31, 12, 2, 9), msecs(212)));
7634 testST2(-734_412, SysTime(DateTime(-2010, 4, 1, 12, 2, 9), msecs(212)));
7635 testST2(-734_383, SysTime(DateTime(-2010, 4, 30, 12, 2, 9), msecs(212)));
7636 testST2(-734_382, SysTime(DateTime(-2010, 5, 1, 12, 2, 9), msecs(212)));
7637 testST2(-734_352, SysTime(DateTime(-2010, 5, 31, 12, 2, 9), msecs(212)));
7638 testST2(-734_351, SysTime(DateTime(-2010, 6, 1, 12, 2, 9), msecs(212)));
7639 testST2(-734_322, SysTime(DateTime(-2010, 6, 30, 12, 2, 9), msecs(212)));
7640 testST2(-734_321, SysTime(DateTime(-2010, 7, 1, 12, 2, 9), msecs(212)));
7641 testST2(-734_291, SysTime(DateTime(-2010, 7, 31, 12, 2, 9), msecs(212)));
7642 testST2(-734_290, SysTime(DateTime(-2010, 8, 1, 12, 2, 9), msecs(212)));
7643 testST2(-734_260, SysTime(DateTime(-2010, 8, 31, 12, 2, 9), msecs(212)));
7644 testST2(-734_259, SysTime(DateTime(-2010, 9, 1, 12, 2, 9), msecs(212)));
7645 testST2(-734_230, SysTime(DateTime(-2010, 9, 30, 12, 2, 9), msecs(212)));
7646 testST2(-734_229, SysTime(DateTime(-2010, 10, 1, 12, 2, 9), msecs(212)));
7647 testST2(-734_199, SysTime(DateTime(-2010, 10, 31, 12, 2, 9), msecs(212)));
7648 testST2(-734_198, SysTime(DateTime(-2010, 11, 1, 12, 2, 9), msecs(212)));
7649 testST2(-734_169, SysTime(DateTime(-2010, 11, 30, 12, 2, 9), msecs(212)));
7650 testST2(-734_168, SysTime(DateTime(-2010, 12, 1, 12, 2, 9), msecs(212)));
7651 testST2(-734_138, SysTime(DateTime(-2010, 12, 31, 12, 2, 9), msecs(212)));
7652
7653 testST2(-735_202, SysTime(DateTime(-2012, 2, 1, 12, 2, 9), msecs(212)));
7654 testST2(-735_175, SysTime(DateTime(-2012, 2, 28, 12, 2, 9), msecs(212)));
7655 testST2(-735_174, SysTime(DateTime(-2012, 2, 29, 12, 2, 9), msecs(212)));
7656 testST2(-735_173, SysTime(DateTime(-2012, 3, 1, 12, 2, 9), msecs(212)));
7657
7658 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7659 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7660 static assert(!__traits(compiles, cst.dayOfGregorianCal = 7));
7661 static assert(!__traits(compiles, ist.dayOfGregorianCal = 7));
7662
7663 static void testScope(scope ref SysTime st) @safe
7664 {
7665 st.dayOfGregorianCal = 42;
7666 }
7667 }
7668
7669
7670 /++
7671 The ISO 8601 week of the year that this $(LREF SysTime) is in.
7672
7673 See_Also:
7674 $(HTTP en.wikipedia.org/wiki/ISO_week_date, ISO Week Date).
7675 +/
7676 @property ubyte isoWeek() @safe const nothrow scope
7677 {
7678 return (cast(Date) this).isoWeek;
7679 }
7680
7681 ///
7682 @safe unittest
7683 {
7684 import core.time;
7685 import std.datetime.date : Date;
7686
7687 auto st = SysTime(Date(1999, 7, 6));
7688 const cst = SysTime(Date(2010, 5, 1));
7689 immutable ist = SysTime(Date(2015, 10, 10));
7690
7691 assert(st.isoWeek == 27);
7692 assert(cst.isoWeek == 17);
7693 assert(ist.isoWeek == 41);
7694 }
7695
7696 @safe unittest
7697 {
7698 static void testScope(scope ref SysTime st) @safe
7699 {
7700 auto result = st.isoWeek;
7701 }
7702 }
7703
7704
7705 /++
7706 $(LREF SysTime) for the last day in the month that this Date is in.
7707 The time portion of endOfMonth is always 23:59:59.9999999.
7708 +/
7709 @property SysTime endOfMonth() @safe const nothrow return scope
7710 {
7711 immutable hnsecs = adjTime;
7712 immutable days = getUnitsFromHNSecs!"days"(hnsecs);
7713
7714 auto date = Date(cast(int) days + 1).endOfMonth;
7715 auto newDays = date.dayOfGregorianCal - 1;
7716 long theTimeHNSecs;
7717
7718 if (newDays < 0)
7719 {
7720 theTimeHNSecs = -1;
7721 ++newDays;
7722 }
7723 else
7724 theTimeHNSecs = convert!("days", "hnsecs")(1) - 1;
7725
7726 immutable newDaysHNSecs = convert!("days", "hnsecs")(newDays);
7727
7728 auto retval = SysTime(this._stdTime, this._timezone);
7729 retval.adjTime = newDaysHNSecs + theTimeHNSecs;
7730
7731 return retval;
7732 }
7733
7734 ///
7735 @safe unittest
7736 {
7737 import core.time : msecs, usecs, hnsecs;
7738 import std.datetime.date : DateTime;
7739
7740 assert(SysTime(DateTime(1999, 1, 6, 0, 0, 0)).endOfMonth ==
7741 SysTime(DateTime(1999, 1, 31, 23, 59, 59), hnsecs(9_999_999)));
7742
7743 assert(SysTime(DateTime(1999, 2, 7, 19, 30, 0), msecs(24)).endOfMonth ==
7744 SysTime(DateTime(1999, 2, 28, 23, 59, 59), hnsecs(9_999_999)));
7745
7746 assert(SysTime(DateTime(2000, 2, 7, 5, 12, 27), usecs(5203)).endOfMonth ==
7747 SysTime(DateTime(2000, 2, 29, 23, 59, 59), hnsecs(9_999_999)));
7748
7749 assert(SysTime(DateTime(2000, 6, 4, 12, 22, 9), hnsecs(12345)).endOfMonth ==
7750 SysTime(DateTime(2000, 6, 30, 23, 59, 59), hnsecs(9_999_999)));
7751 }
7752
7753 @safe unittest
7754 {
7755 import core.time;
7756 // Test A.D.
7757 assert(SysTime(Date(1999, 1, 1)).endOfMonth == SysTime(DateTime(1999, 1, 31, 23, 59, 59), hnsecs(9_999_999)));
7758 assert(SysTime(Date(1999, 2, 1)).endOfMonth == SysTime(DateTime(1999, 2, 28, 23, 59, 59), hnsecs(9_999_999)));
7759 assert(SysTime(Date(2000, 2, 1)).endOfMonth == SysTime(DateTime(2000, 2, 29, 23, 59, 59), hnsecs(9_999_999)));
7760 assert(SysTime(Date(1999, 3, 1)).endOfMonth == SysTime(DateTime(1999, 3, 31, 23, 59, 59), hnsecs(9_999_999)));
7761 assert(SysTime(Date(1999, 4, 1)).endOfMonth == SysTime(DateTime(1999, 4, 30, 23, 59, 59), hnsecs(9_999_999)));
7762 assert(SysTime(Date(1999, 5, 1)).endOfMonth == SysTime(DateTime(1999, 5, 31, 23, 59, 59), hnsecs(9_999_999)));
7763 assert(SysTime(Date(1999, 6, 1)).endOfMonth == SysTime(DateTime(1999, 6, 30, 23, 59, 59), hnsecs(9_999_999)));
7764 assert(SysTime(Date(1999, 7, 1)).endOfMonth == SysTime(DateTime(1999, 7, 31, 23, 59, 59), hnsecs(9_999_999)));
7765 assert(SysTime(Date(1999, 8, 1)).endOfMonth == SysTime(DateTime(1999, 8, 31, 23, 59, 59), hnsecs(9_999_999)));
7766 assert(SysTime(Date(1999, 9, 1)).endOfMonth == SysTime(DateTime(1999, 9, 30, 23, 59, 59), hnsecs(9_999_999)));
7767 assert(SysTime(Date(1999, 10, 1)).endOfMonth == SysTime(DateTime(1999, 10, 31, 23, 59, 59), hnsecs(9_999_999)));
7768 assert(SysTime(Date(1999, 11, 1)).endOfMonth == SysTime(DateTime(1999, 11, 30, 23, 59, 59), hnsecs(9_999_999)));
7769 assert(SysTime(Date(1999, 12, 1)).endOfMonth == SysTime(DateTime(1999, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
7770
7771 // Test B.C.
7772 assert(SysTime(Date(-1999, 1, 1)).endOfMonth == SysTime(DateTime(-1999, 1, 31, 23, 59, 59), hnsecs(9_999_999)));
7773 assert(SysTime(Date(-1999, 2, 1)).endOfMonth == SysTime(DateTime(-1999, 2, 28, 23, 59, 59), hnsecs(9_999_999)));
7774 assert(SysTime(Date(-2000, 2, 1)).endOfMonth == SysTime(DateTime(-2000, 2, 29, 23, 59, 59), hnsecs(9_999_999)));
7775 assert(SysTime(Date(-1999, 3, 1)).endOfMonth == SysTime(DateTime(-1999, 3, 31, 23, 59, 59), hnsecs(9_999_999)));
7776 assert(SysTime(Date(-1999, 4, 1)).endOfMonth == SysTime(DateTime(-1999, 4, 30, 23, 59, 59), hnsecs(9_999_999)));
7777 assert(SysTime(Date(-1999, 5, 1)).endOfMonth == SysTime(DateTime(-1999, 5, 31, 23, 59, 59), hnsecs(9_999_999)));
7778 assert(SysTime(Date(-1999, 6, 1)).endOfMonth == SysTime(DateTime(-1999, 6, 30, 23, 59, 59), hnsecs(9_999_999)));
7779 assert(SysTime(Date(-1999, 7, 1)).endOfMonth == SysTime(DateTime(-1999, 7, 31, 23, 59, 59), hnsecs(9_999_999)));
7780 assert(SysTime(Date(-1999, 8, 1)).endOfMonth == SysTime(DateTime(-1999, 8, 31, 23, 59, 59), hnsecs(9_999_999)));
7781 assert(SysTime(Date(-1999, 9, 1)).endOfMonth == SysTime(DateTime(-1999, 9, 30, 23, 59, 59), hnsecs(9_999_999)));
7782 assert(SysTime(Date(-1999, 10, 1)).endOfMonth ==
7783 SysTime(DateTime(-1999, 10, 31, 23, 59, 59), hnsecs(9_999_999)));
7784 assert(SysTime(Date(-1999, 11, 1)).endOfMonth ==
7785 SysTime(DateTime(-1999, 11, 30, 23, 59, 59), hnsecs(9_999_999)));
7786 assert(SysTime(Date(-1999, 12, 1)).endOfMonth ==
7787 SysTime(DateTime(-1999, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
7788
7789 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7790 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7791 assert(cst.endOfMonth == SysTime(DateTime(1999, 7, 31, 23, 59, 59), hnsecs(9_999_999)));
7792 assert(ist.endOfMonth == SysTime(DateTime(1999, 7, 31, 23, 59, 59), hnsecs(9_999_999)));
7793
7794 static void testScope(scope ref SysTime st) @safe
7795 {
7796 auto result = st.endOfMonth;
7797 }
7798 }
7799
7800
7801 /++
7802 The last day in the month that this $(LREF SysTime) is in.
7803 +/
7804 @property ubyte daysInMonth() @safe const nothrow scope
7805 {
7806 return Date(dayOfGregorianCal).daysInMonth;
7807 }
7808
7809 ///
7810 @safe unittest
7811 {
7812 import core.time;
7813 import std.datetime.date : DateTime;
7814
7815 assert(SysTime(DateTime(1999, 1, 6, 0, 0, 0)).daysInMonth == 31);
7816 assert(SysTime(DateTime(1999, 2, 7, 19, 30, 0)).daysInMonth == 28);
7817 assert(SysTime(DateTime(2000, 2, 7, 5, 12, 27)).daysInMonth == 29);
7818 assert(SysTime(DateTime(2000, 6, 4, 12, 22, 9)).daysInMonth == 30);
7819 }
7820
7821 @safe unittest
7822 {
7823 import core.time;
7824 // Test A.D.
7825 assert(SysTime(DateTime(1999, 1, 1, 12, 1, 13)).daysInMonth == 31);
7826 assert(SysTime(DateTime(1999, 2, 1, 17, 13, 12)).daysInMonth == 28);
7827 assert(SysTime(DateTime(2000, 2, 1, 13, 2, 12)).daysInMonth == 29);
7828 assert(SysTime(DateTime(1999, 3, 1, 12, 13, 12)).daysInMonth == 31);
7829 assert(SysTime(DateTime(1999, 4, 1, 12, 6, 13)).daysInMonth == 30);
7830 assert(SysTime(DateTime(1999, 5, 1, 15, 13, 12)).daysInMonth == 31);
7831 assert(SysTime(DateTime(1999, 6, 1, 13, 7, 12)).daysInMonth == 30);
7832 assert(SysTime(DateTime(1999, 7, 1, 12, 13, 17)).daysInMonth == 31);
7833 assert(SysTime(DateTime(1999, 8, 1, 12, 3, 13)).daysInMonth == 31);
7834 assert(SysTime(DateTime(1999, 9, 1, 12, 13, 12)).daysInMonth == 30);
7835 assert(SysTime(DateTime(1999, 10, 1, 13, 19, 12)).daysInMonth == 31);
7836 assert(SysTime(DateTime(1999, 11, 1, 12, 13, 17)).daysInMonth == 30);
7837 assert(SysTime(DateTime(1999, 12, 1, 12, 52, 13)).daysInMonth == 31);
7838
7839 // Test B.C.
7840 assert(SysTime(DateTime(-1999, 1, 1, 12, 1, 13)).daysInMonth == 31);
7841 assert(SysTime(DateTime(-1999, 2, 1, 7, 13, 12)).daysInMonth == 28);
7842 assert(SysTime(DateTime(-2000, 2, 1, 13, 2, 12)).daysInMonth == 29);
7843 assert(SysTime(DateTime(-1999, 3, 1, 12, 13, 12)).daysInMonth == 31);
7844 assert(SysTime(DateTime(-1999, 4, 1, 12, 6, 13)).daysInMonth == 30);
7845 assert(SysTime(DateTime(-1999, 5, 1, 5, 13, 12)).daysInMonth == 31);
7846 assert(SysTime(DateTime(-1999, 6, 1, 13, 7, 12)).daysInMonth == 30);
7847 assert(SysTime(DateTime(-1999, 7, 1, 12, 13, 17)).daysInMonth == 31);
7848 assert(SysTime(DateTime(-1999, 8, 1, 12, 3, 13)).daysInMonth == 31);
7849 assert(SysTime(DateTime(-1999, 9, 1, 12, 13, 12)).daysInMonth == 30);
7850 assert(SysTime(DateTime(-1999, 10, 1, 13, 19, 12)).daysInMonth == 31);
7851 assert(SysTime(DateTime(-1999, 11, 1, 12, 13, 17)).daysInMonth == 30);
7852 assert(SysTime(DateTime(-1999, 12, 1, 12, 52, 13)).daysInMonth == 31);
7853
7854 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7855 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7856 assert(cst.daysInMonth == 31);
7857 assert(ist.daysInMonth == 31);
7858
7859 static void testScope(scope ref SysTime st) @safe
7860 {
7861 auto result = st.daysInMonth;
7862 }
7863 }
7864
7865
7866 /++
7867 Whether the current year is a date in A.D.
7868 +/
7869 @property bool isAD() @safe const nothrow scope
7870 {
7871 return adjTime >= 0;
7872 }
7873
7874 ///
7875 @safe unittest
7876 {
7877 import core.time;
7878 import std.datetime.date : DateTime;
7879
7880 assert(SysTime(DateTime(1, 1, 1, 12, 7, 0)).isAD);
7881 assert(SysTime(DateTime(2010, 12, 31, 0, 0, 0)).isAD);
7882 assert(!SysTime(DateTime(0, 12, 31, 23, 59, 59)).isAD);
7883 assert(!SysTime(DateTime(-2010, 1, 1, 2, 2, 2)).isAD);
7884 }
7885
7886 @safe unittest
7887 {
7888 import core.time;
7889 assert(SysTime(DateTime(2010, 7, 4, 12, 0, 9)).isAD);
7890 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).isAD);
7891 assert(!SysTime(DateTime(0, 12, 31, 23, 59, 59)).isAD);
7892 assert(!SysTime(DateTime(0, 1, 1, 23, 59, 59)).isAD);
7893 assert(!SysTime(DateTime(-1, 1, 1, 23 ,59 ,59)).isAD);
7894 assert(!SysTime(DateTime(-2010, 7, 4, 12, 2, 2)).isAD);
7895
7896 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7897 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7898 assert(cst.isAD);
7899 assert(ist.isAD);
7900
7901 static void testScope(scope ref SysTime st) @safe
7902 {
7903 auto result = st.isAD;
7904 }
7905 }
7906
7907
7908 /++
7909 The $(HTTP en.wikipedia.org/wiki/Julian_day, Julian day)
7910 for this $(LREF SysTime) at the given time. For example,
7911 prior to noon, 1996-03-31 would be the Julian day number 2_450_173, so
7912 this function returns 2_450_173, while from noon onward, the Julian
7913 day number would be 2_450_174, so this function returns 2_450_174.
7914 +/
7915 @property long julianDay() @safe const nothrow scope
7916 {
7917 immutable jd = dayOfGregorianCal + 1_721_425;
7918 return hour < 12 ? jd - 1 : jd;
7919 }
7920
7921 @safe unittest
7922 {
7923 import core.time;
7924 assert(SysTime(DateTime(-4713, 11, 24, 0, 0, 0)).julianDay == -1);
7925 assert(SysTime(DateTime(-4713, 11, 24, 12, 0, 0)).julianDay == 0);
7926
7927 assert(SysTime(DateTime(0, 12, 31, 0, 0, 0)).julianDay == 1_721_424);
7928 assert(SysTime(DateTime(0, 12, 31, 12, 0, 0)).julianDay == 1_721_425);
7929
7930 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).julianDay == 1_721_425);
7931 assert(SysTime(DateTime(1, 1, 1, 12, 0, 0)).julianDay == 1_721_426);
7932
7933 assert(SysTime(DateTime(1582, 10, 15, 0, 0, 0)).julianDay == 2_299_160);
7934 assert(SysTime(DateTime(1582, 10, 15, 12, 0, 0)).julianDay == 2_299_161);
7935
7936 assert(SysTime(DateTime(1858, 11, 17, 0, 0, 0)).julianDay == 2_400_000);
7937 assert(SysTime(DateTime(1858, 11, 17, 12, 0, 0)).julianDay == 2_400_001);
7938
7939 assert(SysTime(DateTime(1982, 1, 4, 0, 0, 0)).julianDay == 2_444_973);
7940 assert(SysTime(DateTime(1982, 1, 4, 12, 0, 0)).julianDay == 2_444_974);
7941
7942 assert(SysTime(DateTime(1996, 3, 31, 0, 0, 0)).julianDay == 2_450_173);
7943 assert(SysTime(DateTime(1996, 3, 31, 12, 0, 0)).julianDay == 2_450_174);
7944
7945 assert(SysTime(DateTime(2010, 8, 24, 0, 0, 0)).julianDay == 2_455_432);
7946 assert(SysTime(DateTime(2010, 8, 24, 12, 0, 0)).julianDay == 2_455_433);
7947
7948 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7949 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7950 assert(cst.julianDay == 2_451_366);
7951 assert(ist.julianDay == 2_451_366);
7952
7953 static void testScope(scope ref SysTime st) @safe
7954 {
7955 auto result = st.julianDay;
7956 }
7957 }
7958
7959
7960 /++
7961 The modified $(HTTP en.wikipedia.org/wiki/Julian_day, Julian day) for
7962 any time on this date (since, the modified Julian day changes at
7963 midnight).
7964 +/
7965 @property long modJulianDay() @safe const nothrow scope
7966 {
7967 return dayOfGregorianCal + 1_721_425 - 2_400_001;
7968 }
7969
7970 @safe unittest
7971 {
7972 import core.time;
7973 assert(SysTime(DateTime(1858, 11, 17, 0, 0, 0)).modJulianDay == 0);
7974 assert(SysTime(DateTime(1858, 11, 17, 12, 0, 0)).modJulianDay == 0);
7975
7976 assert(SysTime(DateTime(2010, 8, 24, 0, 0, 0)).modJulianDay == 55_432);
7977 assert(SysTime(DateTime(2010, 8, 24, 12, 0, 0)).modJulianDay == 55_432);
7978
7979 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7980 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7981 assert(cst.modJulianDay == 51_365);
7982 assert(ist.modJulianDay == 51_365);
7983
7984 static void testScope(scope ref SysTime st) @safe
7985 {
7986 auto result = st.modJulianDay;
7987 }
7988 }
7989
7990
7991 /++
7992 Returns a $(REF Date,std,datetime,date) equivalent to this $(LREF SysTime).
7993 +/
7994 Date opCast(T)() @safe const nothrow scope
7995 if (is(immutable T == immutable Date))
7996 {
7997 return Date(dayOfGregorianCal);
7998 }
7999
8000 @safe unittest
8001 {
8002 import core.time;
8003 assert(cast(Date) SysTime(Date(1999, 7, 6)) == Date(1999, 7, 6));
8004 assert(cast(Date) SysTime(Date(2000, 12, 31)) == Date(2000, 12, 31));
8005 assert(cast(Date) SysTime(Date(2001, 1, 1)) == Date(2001, 1, 1));
8006
8007 assert(cast(Date) SysTime(DateTime(1999, 7, 6, 12, 10, 9)) == Date(1999, 7, 6));
8008 assert(cast(Date) SysTime(DateTime(2000, 12, 31, 13, 11, 10)) == Date(2000, 12, 31));
8009 assert(cast(Date) SysTime(DateTime(2001, 1, 1, 14, 12, 11)) == Date(2001, 1, 1));
8010
8011 assert(cast(Date) SysTime(Date(-1999, 7, 6)) == Date(-1999, 7, 6));
8012 assert(cast(Date) SysTime(Date(-2000, 12, 31)) == Date(-2000, 12, 31));
8013 assert(cast(Date) SysTime(Date(-2001, 1, 1)) == Date(-2001, 1, 1));
8014
8015 assert(cast(Date) SysTime(DateTime(-1999, 7, 6, 12, 10, 9)) == Date(-1999, 7, 6));
8016 assert(cast(Date) SysTime(DateTime(-2000, 12, 31, 13, 11, 10)) == Date(-2000, 12, 31));
8017 assert(cast(Date) SysTime(DateTime(-2001, 1, 1, 14, 12, 11)) == Date(-2001, 1, 1));
8018
8019 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8020 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8021 assert(cast(Date) cst != Date.init);
8022 assert(cast(Date) ist != Date.init);
8023
8024 static void testScope(scope ref SysTime st) @safe
8025 {
8026 auto result = cast(Date) st;
8027 }
8028 }
8029
8030
8031 /++
8032 Returns a $(REF DateTime,std,datetime,date) equivalent to this
8033 $(LREF SysTime).
8034 +/
8035 DateTime opCast(T)() @safe const nothrow scope
8036 if (is(immutable T == immutable DateTime))
8037 {
8038 try
8039 {
8040 auto hnsecs = adjTime;
8041 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
8042
8043 if (hnsecs < 0)
8044 {
8045 hnsecs += convert!("hours", "hnsecs")(24);
8046 --days;
8047 }
8048
8049 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
8050 immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
8051 immutable second = getUnitsFromHNSecs!"seconds"(hnsecs);
8052
8053 return DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour, cast(int) minute, cast(int) second));
8054 }
8055 catch (Exception e)
8056 assert(0, "Either DateTime's constructor or TimeOfDay's constructor threw.");
8057 }
8058
8059 @safe unittest
8060 {
8061 import core.time;
8062 assert(cast(DateTime) SysTime(DateTime(1, 1, 6, 7, 12, 22)) == DateTime(1, 1, 6, 7, 12, 22));
8063 assert(cast(DateTime) SysTime(DateTime(1, 1, 6, 7, 12, 22), msecs(22)) == DateTime(1, 1, 6, 7, 12, 22));
8064 assert(cast(DateTime) SysTime(Date(1999, 7, 6)) == DateTime(1999, 7, 6, 0, 0, 0));
8065 assert(cast(DateTime) SysTime(Date(2000, 12, 31)) == DateTime(2000, 12, 31, 0, 0, 0));
8066 assert(cast(DateTime) SysTime(Date(2001, 1, 1)) == DateTime(2001, 1, 1, 0, 0, 0));
8067
8068 assert(cast(DateTime) SysTime(DateTime(1999, 7, 6, 12, 10, 9)) == DateTime(1999, 7, 6, 12, 10, 9));
8069 assert(cast(DateTime) SysTime(DateTime(2000, 12, 31, 13, 11, 10)) == DateTime(2000, 12, 31, 13, 11, 10));
8070 assert(cast(DateTime) SysTime(DateTime(2001, 1, 1, 14, 12, 11)) == DateTime(2001, 1, 1, 14, 12, 11));
8071
8072 assert(cast(DateTime) SysTime(DateTime(-1, 1, 6, 7, 12, 22)) == DateTime(-1, 1, 6, 7, 12, 22));
8073 assert(cast(DateTime) SysTime(DateTime(-1, 1, 6, 7, 12, 22), msecs(22)) == DateTime(-1, 1, 6, 7, 12, 22));
8074 assert(cast(DateTime) SysTime(Date(-1999, 7, 6)) == DateTime(-1999, 7, 6, 0, 0, 0));
8075 assert(cast(DateTime) SysTime(Date(-2000, 12, 31)) == DateTime(-2000, 12, 31, 0, 0, 0));
8076 assert(cast(DateTime) SysTime(Date(-2001, 1, 1)) == DateTime(-2001, 1, 1, 0, 0, 0));
8077
8078 assert(cast(DateTime) SysTime(DateTime(-1999, 7, 6, 12, 10, 9)) == DateTime(-1999, 7, 6, 12, 10, 9));
8079 assert(cast(DateTime) SysTime(DateTime(-2000, 12, 31, 13, 11, 10)) == DateTime(-2000, 12, 31, 13, 11, 10));
8080 assert(cast(DateTime) SysTime(DateTime(-2001, 1, 1, 14, 12, 11)) == DateTime(-2001, 1, 1, 14, 12, 11));
8081
8082 assert(cast(DateTime) SysTime(DateTime(2011, 1, 13, 8, 17, 2), msecs(296), LocalTime()) ==
8083 DateTime(2011, 1, 13, 8, 17, 2));
8084
8085 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8086 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8087 assert(cast(DateTime) cst != DateTime.init);
8088 assert(cast(DateTime) ist != DateTime.init);
8089
8090 static void testScope(scope ref SysTime st) @safe
8091 {
8092 auto result = cast(DateTime) st;
8093 }
8094 }
8095
8096
8097 /++
8098 Returns a $(REF TimeOfDay,std,datetime,date) equivalent to this
8099 $(LREF SysTime).
8100 +/
8101 TimeOfDay opCast(T)() @safe const nothrow scope
8102 if (is(immutable T == immutable TimeOfDay))
8103 {
8104 try
8105 {
8106 auto hnsecs = adjTime;
8107 hnsecs = removeUnitsFromHNSecs!"days"(hnsecs);
8108
8109 if (hnsecs < 0)
8110 hnsecs += convert!("hours", "hnsecs")(24);
8111
8112 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
8113 immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
8114 immutable second = getUnitsFromHNSecs!"seconds"(hnsecs);
8115
8116 return TimeOfDay(cast(int) hour, cast(int) minute, cast(int) second);
8117 }
8118 catch (Exception e)
8119 assert(0, "TimeOfDay's constructor threw.");
8120 }
8121
8122 @safe unittest
8123 {
8124 import core.time;
8125 assert(cast(TimeOfDay) SysTime(Date(1999, 7, 6)) == TimeOfDay(0, 0, 0));
8126 assert(cast(TimeOfDay) SysTime(Date(2000, 12, 31)) == TimeOfDay(0, 0, 0));
8127 assert(cast(TimeOfDay) SysTime(Date(2001, 1, 1)) == TimeOfDay(0, 0, 0));
8128
8129 assert(cast(TimeOfDay) SysTime(DateTime(1999, 7, 6, 12, 10, 9)) == TimeOfDay(12, 10, 9));
8130 assert(cast(TimeOfDay) SysTime(DateTime(2000, 12, 31, 13, 11, 10)) == TimeOfDay(13, 11, 10));
8131 assert(cast(TimeOfDay) SysTime(DateTime(2001, 1, 1, 14, 12, 11)) == TimeOfDay(14, 12, 11));
8132
8133 assert(cast(TimeOfDay) SysTime(Date(-1999, 7, 6)) == TimeOfDay(0, 0, 0));
8134 assert(cast(TimeOfDay) SysTime(Date(-2000, 12, 31)) == TimeOfDay(0, 0, 0));
8135 assert(cast(TimeOfDay) SysTime(Date(-2001, 1, 1)) == TimeOfDay(0, 0, 0));
8136
8137 assert(cast(TimeOfDay) SysTime(DateTime(-1999, 7, 6, 12, 10, 9)) == TimeOfDay(12, 10, 9));
8138 assert(cast(TimeOfDay) SysTime(DateTime(-2000, 12, 31, 13, 11, 10)) == TimeOfDay(13, 11, 10));
8139 assert(cast(TimeOfDay) SysTime(DateTime(-2001, 1, 1, 14, 12, 11)) == TimeOfDay(14, 12, 11));
8140
8141 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8142 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8143 assert(cast(TimeOfDay) cst != TimeOfDay.init);
8144 assert(cast(TimeOfDay) ist != TimeOfDay.init);
8145
8146 static void testScope(scope ref SysTime st) @safe
8147 {
8148 auto result = cast(TimeOfDay) st;
8149 }
8150 }
8151
8152
8153 // Temporary hack until bug https://issues.dlang.org/show_bug.cgi?id=4867 is fixed.
8154 // This allows assignment from const(SysTime) to SysTime.
8155 // It may be a good idea to keep it though, since casting from a type to itself
8156 // should be allowed, and it doesn't work without this opCast() since opCast()
8157 // has already been defined for other types.
8158 SysTime opCast(T)() @safe const pure nothrow scope
8159 if (is(immutable T == immutable SysTime))
8160 {
8161 return SysTime(_stdTime, _timezone);
8162 }
8163
8164 @safe unittest
8165 {
8166 static void testScope(scope ref SysTime st) @safe
8167 {
8168 auto result = cast(SysTime) st;
8169 }
8170 }
8171
8172
8173 /++
8174 Converts this $(LREF SysTime) to a string with the format
8175 YYYYMMDDTHHMMSS.FFFFFFFTZ (where F is fractional seconds and TZ is time
8176 zone).
8177
8178 Note that the number of digits in the fractional seconds varies with the
8179 number of fractional seconds. It's a maximum of 7 (which would be
8180 hnsecs), but only has as many as are necessary to hold the correct value
8181 (so no trailing zeroes), and if there are no fractional seconds, then
8182 there is no decimal point.
8183
8184 If this $(LREF SysTime)'s time zone is
8185 $(REF LocalTime,std,datetime,timezone), then TZ is empty. If its time
8186 zone is `UTC`, then it is "Z". Otherwise, it is the offset from UTC
8187 (e.g. +0100 or -0700). Note that the offset from UTC is $(I not) enough
8188 to uniquely identify the time zone.
8189
8190 Time zone offsets will be in the form +HHMM or -HHMM.
8191
8192 $(RED Warning:
8193 Previously, toISOString did the same as $(LREF toISOExtString) and
8194 generated +HH:MM or -HH:MM for the time zone when it was not
8195 $(REF LocalTime,std,datetime,timezone) or
8196 $(REF UTC,std,datetime,timezone), which is not in conformance with
8197 ISO 8601 for the non-extended string format. This has now been
8198 fixed. However, for now, fromISOString will continue to accept the
8199 extended format for the time zone so that any code which has been
8200 writing out the result of toISOString to read in later will continue
8201 to work. The current behavior will be kept until July 2019 at which
8202 point, fromISOString will be fixed to be standards compliant.)
8203
8204 Params:
8205 writer = A `char` accepting
8206 $(REF_ALTTEXT output range, isOutputRange, std, range, primitives)
8207 Returns:
8208 A `string` when not using an output range; `void` otherwise.
8209 +/
8210 string toISOString() @safe const nothrow scope
8211 {
8212 import std.array : appender;
8213 auto app = appender!string();
8214 app.reserve(30);
8215 try
8216 toISOString(app);
8217 catch (Exception e)
8218 assert(0, "toISOString() threw.");
8219 return app.data;
8220 }
8221
8222 /// ditto
8223 void toISOString(W)(ref W writer) const scope
8224 if (isOutputRange!(W, char))
8225 {
8226 immutable adjustedTime = adjTime;
8227 long hnsecs = adjustedTime;
8228
8229 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
8230
8231 if (hnsecs < 0)
8232 {
8233 hnsecs += convert!("hours", "hnsecs")(24);
8234 --days;
8235 }
8236
8237 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
8238 immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
8239 immutable second = splitUnitsFromHNSecs!"seconds"(hnsecs);
8240
8241 auto dateTime = DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour,
8242 cast(int) minute, cast(int) second));
8243
8244 if (_timezone is LocalTime())
8245 {
8246 dateTime.toISOString(writer);
8247 fracSecsToISOString(writer, cast(int) hnsecs);
8248 return;
8249 }
8250
8251 if (_timezone is UTC())
8252 {
8253 dateTime.toISOString(writer);
8254 fracSecsToISOString(writer, cast(int) hnsecs);
8255 put(writer, 'Z');
8256 return;
8257 }
8258
8259 immutable utcOffset = dur!"hnsecs"(adjustedTime - stdTime);
8260
8261 dateTime.toISOString(writer);
8262 fracSecsToISOString(writer, cast(int) hnsecs);
8263 SimpleTimeZone.toISOExtString(writer, utcOffset);
8264 }
8265
8266 ///
8267 @safe unittest
8268 {
8269 import core.time : msecs, hnsecs;
8270 import std.datetime.date : DateTime;
8271
8272 assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toISOString() ==
8273 "20100704T070612");
8274
8275 assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(24)).toISOString() ==
8276 "19981225T021500.024");
8277
8278 assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toISOString() ==
8279 "00000105T230959");
8280
8281 assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toISOString() ==
8282 "-00040105T000002.052092");
8283 }
8284
8285 @safe unittest
8286 {
8287 import core.time;
8288 // Test A.D.
8289 assert(SysTime(DateTime.init, UTC()).toISOString() == "00010101T000000Z");
8290 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1), UTC()).toISOString() == "00010101T000000.0000001Z");
8291
8292 assert(SysTime(DateTime(9, 12, 4, 0, 0, 0)).toISOString() == "00091204T000000");
8293 assert(SysTime(DateTime(99, 12, 4, 5, 6, 12)).toISOString() == "00991204T050612");
8294 assert(SysTime(DateTime(999, 12, 4, 13, 44, 59)).toISOString() == "09991204T134459");
8295 assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59)).toISOString() == "99990704T235959");
8296 assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1)).toISOString() == "+100001020T010101");
8297
8298 assert(SysTime(DateTime(9, 12, 4, 0, 0, 0), msecs(42)).toISOString() == "00091204T000000.042");
8299 assert(SysTime(DateTime(99, 12, 4, 5, 6, 12), msecs(100)).toISOString() == "00991204T050612.1");
8300 assert(SysTime(DateTime(999, 12, 4, 13, 44, 59), usecs(45020)).toISOString() == "09991204T134459.04502");
8301 assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59), hnsecs(12)).toISOString() == "99990704T235959.0000012");
8302 assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1), hnsecs(507890)).toISOString() == "+100001020T010101.050789");
8303
8304 assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
8305 new immutable SimpleTimeZone(dur!"minutes"(-360))).toISOString() ==
8306 "20121221T121212-06:00");
8307
8308 assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
8309 new immutable SimpleTimeZone(dur!"minutes"(420))).toISOString() ==
8310 "20121221T121212+07:00");
8311
8312 // Test B.C.
8313 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toISOString() ==
8314 "00001231T235959.9999999Z");
8315 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1), UTC()).toISOString() == "00001231T235959.0000001Z");
8316 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), UTC()).toISOString() == "00001231T235959Z");
8317
8318 assert(SysTime(DateTime(0, 12, 4, 0, 12, 4)).toISOString() == "00001204T001204");
8319 assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0)).toISOString() == "-00091204T000000");
8320 assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12)).toISOString() == "-00991204T050612");
8321 assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59)).toISOString() == "-09991204T134459");
8322 assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59)).toISOString() == "-99990704T235959");
8323 assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1)).toISOString() == "-100001020T010101");
8324
8325 assert(SysTime(DateTime(0, 12, 4, 0, 0, 0), msecs(7)).toISOString() == "00001204T000000.007");
8326 assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0), msecs(42)).toISOString() == "-00091204T000000.042");
8327 assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12), msecs(100)).toISOString() == "-00991204T050612.1");
8328 assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59), usecs(45020)).toISOString() == "-09991204T134459.04502");
8329 assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59), hnsecs(12)).toISOString() == "-99990704T235959.0000012");
8330 assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1), hnsecs(507890)).toISOString() == "-100001020T010101.050789");
8331
8332 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8333 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8334 assert(cst.toISOString() == "19990706T123033");
8335 assert(ist.toISOString() == "19990706T123033");
8336
8337 static void testScope(scope ref SysTime st) @safe
8338 {
8339 auto result = st.toISOString();
8340 }
8341 }
8342
8343
8344
8345 /++
8346 Converts this $(LREF SysTime) to a string with the format
8347 YYYY-MM-DDTHH:MM:SS.FFFFFFFTZ (where F is fractional seconds and TZ
8348 is the time zone).
8349
8350 Default behaviour:
8351 Note that the number of digits in the fractional seconds varies with the
8352 number of fractional seconds. It's a maximum of 7 (which would be
8353 hnsecs), but only has as many as are necessary to hold the correct value
8354 (so no trailing zeroes), and if there are no fractional seconds, then
8355 there is no decimal point.
8356
8357 The optional parameter "prec" allows to change the default behavior by
8358 specifying the precision of the fractional seconds. The accepted values
8359 are in the range [-1, 7], where -1 represents the default behavior.
8360
8361 If this $(LREF SysTime)'s time zone is
8362 $(REF LocalTime,std,datetime,timezone), then TZ is empty. If its time
8363 zone is `UTC`, then it is "Z". Otherwise, it is the offset from UTC
8364 (e.g. +01:00 or -07:00). Note that the offset from UTC is $(I not)
8365 enough to uniquely identify the time zone.
8366
8367 Time zone offsets will be in the form +HH:MM or -HH:MM.
8368
8369 Params:
8370 writer = A `char` accepting
8371 $(REF_ALTTEXT output range, isOutputRange, std, range, primitives)
8372 prec = An `int` representing the desired precision. Acceptable values range from -1 to 7, where -1 represents the default behavior.
8373 Returns:
8374 A `string` when not using an output range; `void` otherwise.
8375 +/
8376 string toISOExtString(int prec = -1) @safe const nothrow scope
8377 {
8378 assert(prec >= -1 && prec <= 7, "Precision must be in the range [-1, 7]");
8379
8380 import std.array : appender;
8381 auto app = appender!string();
8382 app.reserve(35);
8383 try
8384 toISOExtString(app, prec);
8385 catch (Exception e)
8386 assert(0, "toISOExtString() threw.");
8387 return app.data;
8388 }
8389
8390 /// ditto
8391 void toISOExtString(W)(ref W writer, int prec = -1) const scope
8392 if (isOutputRange!(W, char))
8393 {
8394 assert(prec >= -1 && prec <= 7, "Precision must be in the range [-1, 7]");
8395
8396 immutable adjustedTime = adjTime;
8397 long hnsecs = adjustedTime;
8398
8399 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
8400
8401 if (hnsecs < 0)
8402 {
8403 hnsecs += convert!("hours", "hnsecs")(24);
8404 --days;
8405 }
8406
8407 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
8408 immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
8409 immutable second = splitUnitsFromHNSecs!"seconds"(hnsecs);
8410
8411 immutable dateTime = DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour,
8412 cast(int) minute, cast(int) second));
8413
8414 if (_timezone is LocalTime())
8415 {
8416 dateTime.toISOExtString(writer);
8417 fracSecsToISOString(writer, cast(int) hnsecs, prec);
8418 return;
8419 }
8420
8421 if (_timezone is UTC())
8422 {
8423 dateTime.toISOExtString(writer);
8424 fracSecsToISOString(writer, cast(int) hnsecs, prec);
8425 put(writer, 'Z');
8426 return;
8427 }
8428
8429 immutable utcOffset = dur!"hnsecs"(adjustedTime - stdTime);
8430
8431 dateTime.toISOExtString(writer);
8432 fracSecsToISOString(writer, cast(int) hnsecs, prec);
8433 SimpleTimeZone.toISOExtString(writer, utcOffset);
8434 }
8435
8436 ///
8437 @safe unittest
8438 {
8439 import core.time : msecs, hnsecs;
8440 import std.datetime.date : DateTime;
8441
8442 assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toISOExtString() ==
8443 "2010-07-04T07:06:12");
8444
8445 assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(24)).toISOExtString() ==
8446 "1998-12-25T02:15:00.024");
8447
8448 assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toISOExtString() ==
8449 "0000-01-05T23:09:59");
8450
8451 assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toISOExtString() ==
8452 "-0004-01-05T00:00:02.052092");
8453
8454 assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toISOExtString(4) ==
8455 "-0004-01-05T00:00:02.0520");
8456
8457 assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toISOExtString(2) ==
8458 "-0004-01-05T00:00:02.05");
8459
8460 assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toISOExtString(7) ==
8461 "-0004-01-05T00:00:02.0520920");
8462 }
8463
8464 @safe unittest
8465 {
8466 import core.time;
8467 // Test A.D.
8468 assert(SysTime(DateTime.init, UTC()).toISOExtString() == "0001-01-01T00:00:00Z");
8469 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1), UTC()).toISOExtString() ==
8470 "0001-01-01T00:00:00.0000001Z");
8471
8472 assert(SysTime(DateTime(9, 12, 4, 0, 0, 0)).toISOExtString() == "0009-12-04T00:00:00");
8473 assert(SysTime(DateTime(99, 12, 4, 5, 6, 12)).toISOExtString() == "0099-12-04T05:06:12");
8474 assert(SysTime(DateTime(999, 12, 4, 13, 44, 59)).toISOExtString() == "0999-12-04T13:44:59");
8475 assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59)).toISOExtString() == "9999-07-04T23:59:59");
8476 assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1)).toISOExtString() == "+10000-10-20T01:01:01");
8477
8478 assert(SysTime(DateTime(9, 12, 4, 0, 0, 0), msecs(42)).toISOExtString() == "0009-12-04T00:00:00.042");
8479 assert(SysTime(DateTime(99, 12, 4, 5, 6, 12), msecs(100)).toISOExtString() == "0099-12-04T05:06:12.1");
8480 assert(SysTime(DateTime(999, 12, 4, 13, 44, 59), usecs(45020)).toISOExtString() == "0999-12-04T13:44:59.04502");
8481 assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59), hnsecs(12)).toISOExtString() == "9999-07-04T23:59:59.0000012");
8482 assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1), hnsecs(507890)).toISOExtString() ==
8483 "+10000-10-20T01:01:01.050789");
8484
8485 assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
8486 new immutable SimpleTimeZone(dur!"minutes"(-360))).toISOExtString() ==
8487 "2012-12-21T12:12:12-06:00");
8488
8489 assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
8490 new immutable SimpleTimeZone(dur!"minutes"(420))).toISOExtString() ==
8491 "2012-12-21T12:12:12+07:00");
8492
8493 // Test B.C.
8494 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toISOExtString() ==
8495 "0000-12-31T23:59:59.9999999Z");
8496 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1), UTC()).toISOExtString() ==
8497 "0000-12-31T23:59:59.0000001Z");
8498 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), UTC()).toISOExtString() == "0000-12-31T23:59:59Z");
8499
8500 assert(SysTime(DateTime(0, 12, 4, 0, 12, 4)).toISOExtString() == "0000-12-04T00:12:04");
8501 assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0)).toISOExtString() == "-0009-12-04T00:00:00");
8502 assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12)).toISOExtString() == "-0099-12-04T05:06:12");
8503 assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59)).toISOExtString() == "-0999-12-04T13:44:59");
8504 assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59)).toISOExtString() == "-9999-07-04T23:59:59");
8505 assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1)).toISOExtString() == "-10000-10-20T01:01:01");
8506
8507 assert(SysTime(DateTime(0, 12, 4, 0, 0, 0), msecs(7)).toISOExtString() == "0000-12-04T00:00:00.007");
8508 assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0), msecs(42)).toISOExtString() == "-0009-12-04T00:00:00.042");
8509 assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12), msecs(100)).toISOExtString() == "-0099-12-04T05:06:12.1");
8510 assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59), usecs(45020)).toISOExtString() ==
8511 "-0999-12-04T13:44:59.04502");
8512 assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59), hnsecs(12)).toISOExtString() ==
8513 "-9999-07-04T23:59:59.0000012");
8514 assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1), hnsecs(507890)).toISOExtString() ==
8515 "-10000-10-20T01:01:01.050789");
8516
8517 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8518 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8519 assert(cst.toISOExtString() == "1999-07-06T12:30:33");
8520 assert(ist.toISOExtString() == "1999-07-06T12:30:33");
8521
8522 static void testScope(scope ref SysTime st) @safe
8523 {
8524 auto result = st.toISOExtString();
8525 }
8526 }
8527
8528 /++
8529 Converts this $(LREF SysTime) to a string with the format
8530 YYYY-Mon-DD HH:MM:SS.FFFFFFFTZ (where F is fractional seconds and TZ
8531 is the time zone).
8532
8533 Note that the number of digits in the fractional seconds varies with the
8534 number of fractional seconds. It's a maximum of 7 (which would be
8535 hnsecs), but only has as many as are necessary to hold the correct value
8536 (so no trailing zeroes), and if there are no fractional seconds, then
8537 there is no decimal point.
8538
8539 If this $(LREF SysTime)'s time zone is
8540 $(REF LocalTime,std,datetime,timezone), then TZ is empty. If its time
8541 zone is `UTC`, then it is "Z". Otherwise, it is the offset from UTC
8542 (e.g. +01:00 or -07:00). Note that the offset from UTC is $(I not)
8543 enough to uniquely identify the time zone.
8544
8545 Time zone offsets will be in the form +HH:MM or -HH:MM.
8546
8547 Params:
8548 writer = A `char` accepting
8549 $(REF_ALTTEXT output range, isOutputRange, std, range, primitives)
8550 Returns:
8551 A `string` when not using an output range; `void` otherwise.
8552 +/
8553 string toSimpleString() @safe const nothrow scope
8554 {
8555 import std.array : appender;
8556 auto app = appender!string();
8557 app.reserve(35);
8558 try
8559 toSimpleString(app);
8560 catch (Exception e)
8561 assert(0, "toSimpleString() threw.");
8562 return app.data;
8563 }
8564
8565 /// ditto
8566 void toSimpleString(W)(ref W writer) const scope
8567 if (isOutputRange!(W, char))
8568 {
8569 immutable adjustedTime = adjTime;
8570 long hnsecs = adjustedTime;
8571
8572 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
8573
8574 if (hnsecs < 0)
8575 {
8576 hnsecs += convert!("hours", "hnsecs")(24);
8577 --days;
8578 }
8579
8580 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
8581 immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
8582 immutable second = splitUnitsFromHNSecs!"seconds"(hnsecs);
8583
8584 immutable dateTime = DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour,
8585 cast(int) minute, cast(int) second));
8586
8587 if (_timezone is LocalTime())
8588 {
8589 dateTime.toSimpleString(writer);
8590 fracSecsToISOString(writer, cast(int) hnsecs);
8591 return;
8592 }
8593
8594 if (_timezone is UTC())
8595 {
8596 dateTime.toSimpleString(writer);
8597 fracSecsToISOString(writer, cast(int) hnsecs);
8598 put(writer, 'Z');
8599 return;
8600 }
8601
8602 immutable utcOffset = dur!"hnsecs"(adjustedTime - stdTime);
8603
8604 dateTime.toSimpleString(writer);
8605 fracSecsToISOString(writer, cast(int) hnsecs);
8606 SimpleTimeZone.toISOExtString(writer, utcOffset);
8607 }
8608
8609 ///
8610 @safe unittest
8611 {
8612 import core.time : msecs, hnsecs;
8613 import std.datetime.date : DateTime;
8614
8615 assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toSimpleString() ==
8616 "2010-Jul-04 07:06:12");
8617
8618 assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(24)).toSimpleString() ==
8619 "1998-Dec-25 02:15:00.024");
8620
8621 assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toSimpleString() ==
8622 "0000-Jan-05 23:09:59");
8623
8624 assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toSimpleString() ==
8625 "-0004-Jan-05 00:00:02.052092");
8626 }
8627
8628 @safe unittest
8629 {
8630 import core.time;
8631 // Test A.D.
8632 assert(SysTime(DateTime.init, UTC()).toString() == "0001-Jan-01 00:00:00Z");
8633 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1), UTC()).toString() == "0001-Jan-01 00:00:00.0000001Z");
8634
8635 assert(SysTime(DateTime(9, 12, 4, 0, 0, 0)).toSimpleString() == "0009-Dec-04 00:00:00");
8636 assert(SysTime(DateTime(99, 12, 4, 5, 6, 12)).toSimpleString() == "0099-Dec-04 05:06:12");
8637 assert(SysTime(DateTime(999, 12, 4, 13, 44, 59)).toSimpleString() == "0999-Dec-04 13:44:59");
8638 assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59)).toSimpleString() == "9999-Jul-04 23:59:59");
8639 assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1)).toSimpleString() == "+10000-Oct-20 01:01:01");
8640
8641 assert(SysTime(DateTime(9, 12, 4, 0, 0, 0), msecs(42)).toSimpleString() == "0009-Dec-04 00:00:00.042");
8642 assert(SysTime(DateTime(99, 12, 4, 5, 6, 12), msecs(100)).toSimpleString() == "0099-Dec-04 05:06:12.1");
8643 assert(SysTime(DateTime(999, 12, 4, 13, 44, 59), usecs(45020)).toSimpleString() ==
8644 "0999-Dec-04 13:44:59.04502");
8645 assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59), hnsecs(12)).toSimpleString() ==
8646 "9999-Jul-04 23:59:59.0000012");
8647 assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1), hnsecs(507890)).toSimpleString() ==
8648 "+10000-Oct-20 01:01:01.050789");
8649
8650 assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
8651 new immutable SimpleTimeZone(dur!"minutes"(-360))).toSimpleString() ==
8652 "2012-Dec-21 12:12:12-06:00");
8653
8654 assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
8655 new immutable SimpleTimeZone(dur!"minutes"(420))).toSimpleString() ==
8656 "2012-Dec-21 12:12:12+07:00");
8657
8658 // Test B.C.
8659 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toSimpleString() ==
8660 "0000-Dec-31 23:59:59.9999999Z");
8661 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1), UTC()).toSimpleString() ==
8662 "0000-Dec-31 23:59:59.0000001Z");
8663 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), UTC()).toSimpleString() == "0000-Dec-31 23:59:59Z");
8664
8665 assert(SysTime(DateTime(0, 12, 4, 0, 12, 4)).toSimpleString() == "0000-Dec-04 00:12:04");
8666 assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0)).toSimpleString() == "-0009-Dec-04 00:00:00");
8667 assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12)).toSimpleString() == "-0099-Dec-04 05:06:12");
8668 assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59)).toSimpleString() == "-0999-Dec-04 13:44:59");
8669 assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59)).toSimpleString() == "-9999-Jul-04 23:59:59");
8670 assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1)).toSimpleString() == "-10000-Oct-20 01:01:01");
8671
8672 assert(SysTime(DateTime(0, 12, 4, 0, 0, 0), msecs(7)).toSimpleString() == "0000-Dec-04 00:00:00.007");
8673 assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0), msecs(42)).toSimpleString() == "-0009-Dec-04 00:00:00.042");
8674 assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12), msecs(100)).toSimpleString() == "-0099-Dec-04 05:06:12.1");
8675 assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59), usecs(45020)).toSimpleString() ==
8676 "-0999-Dec-04 13:44:59.04502");
8677 assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59), hnsecs(12)).toSimpleString() ==
8678 "-9999-Jul-04 23:59:59.0000012");
8679 assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1), hnsecs(507890)).toSimpleString() ==
8680 "-10000-Oct-20 01:01:01.050789");
8681
8682 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8683 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8684 assert(cst.toSimpleString() == "1999-Jul-06 12:30:33");
8685 assert(ist.toSimpleString() == "1999-Jul-06 12:30:33");
8686
8687 static void testScope(scope ref SysTime st) @safe
8688 {
8689 auto result = st.toSimpleString();
8690 }
8691 }
8692
8693
8694 /++
8695 Converts this $(LREF SysTime) to a string.
8696
8697 This function exists to make it easy to convert a $(LREF SysTime) to a
8698 string for code that does not care what the exact format is - just that
8699 it presents the information in a clear manner. It also makes it easy to
8700 simply convert a $(LREF SysTime) to a string when using functions such
8701 as `to!string`, `format`, or `writeln` which use toString to convert
8702 user-defined types. So, it is unlikely that much code will call
8703 toString directly.
8704
8705 The format of the string is purposefully unspecified, and code that
8706 cares about the format of the string should use `toISOString`,
8707 `toISOExtString`, `toSimpleString`, or some other custom formatting
8708 function that explicitly generates the format that the code needs. The
8709 reason is that the code is then clear about what format it's using,
8710 making it less error-prone to maintain the code and interact with other
8711 software that consumes the generated strings. It's for this same reason
8712 that $(LREF SysTime) has no `fromString` function, whereas it does have
8713 `fromISOString`, `fromISOExtString`, and `fromSimpleString`.
8714
8715 The format returned by toString may or may not change in the future.
8716
8717 Params:
8718 writer = A `char` accepting
8719 $(REF_ALTTEXT output range, isOutputRange, std, range, primitives)
8720 Returns:
8721 A `string` when not using an output range; `void` otherwise.
8722 +/
8723 string toString() @safe const nothrow scope
8724 {
8725 return toSimpleString();
8726 }
8727
8728 /// ditto
8729 void toString(W)(ref W writer) const scope
8730 if (isOutputRange!(W, char))
8731 {
8732 toSimpleString(writer);
8733 }
8734
8735 @safe unittest
8736 {
8737 import core.time;
8738 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8739 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8740 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8741 static assert(__traits(compiles, st.toString()));
8742 static assert(__traits(compiles, cst.toString()));
8743 static assert(__traits(compiles, ist.toString()));
8744
8745 static void testScope(scope ref SysTime st) @safe
8746 {
8747 auto result = st.toString();
8748 }
8749 }
8750
8751
8752 /++
8753 Creates a $(LREF SysTime) from a string with the format
8754 YYYYMMDDTHHMMSS.FFFFFFFTZ (where F is fractional seconds and TZ
8755 is the time zone). Whitespace is stripped from the given string.
8756
8757 The exact format is exactly as described in $(LREF toISOString) except
8758 that trailing zeroes are permitted - including having fractional seconds
8759 with all zeroes. The time zone and fractional seconds are optional,
8760 however, a decimal point with nothing following it is invalid.
8761 Also, while $(LREF toISOString) will never generate a string
8762 with more than 7 digits in the fractional seconds (because that's the
8763 limit with hecto-nanosecond precision), it will allow more than 7 digits
8764 in order to read strings from other sources that have higher precision
8765 (however, any digits beyond 7 will be truncated).
8766
8767 If there is no time zone in the string, then
8768 $(REF LocalTime,std,datetime,timezone) is used. If the time zone is "Z",
8769 then `UTC` is used. Otherwise, a
8770 $(REF SimpleTimeZone,std,datetime,timezone) which corresponds to the
8771 given offset from UTC is used. To get the returned $(LREF SysTime) to be
8772 a particular time zone, pass in that time zone and the $(LREF SysTime)
8773 to be returned will be converted to that time zone (though it will still
8774 be read in as whatever time zone is in its string).
8775
8776 The accepted formats for time zone offsets are +HH, -HH, +HHMM, and
8777 -HHMM.
8778
8779 $(RED Warning:
8780 Previously, $(LREF toISOString) did the same as
8781 $(LREF toISOExtString) and generated +HH:MM or -HH:MM for the time
8782 zone when it was not $(REF LocalTime,std,datetime,timezone) or
8783 $(REF UTC,std,datetime,timezone), which is not in conformance with
8784 ISO 8601 for the non-extended string format. This has now been
8785 fixed. However, for now, fromISOString will continue to accept the
8786 extended format for the time zone so that any code which has been
8787 writing out the result of toISOString to read in later will continue
8788 to work. The current behavior will be kept until July 2019 at which
8789 point, fromISOString will be fixed to be standards compliant.)
8790
8791 Params:
8792 isoString = A string formatted in the ISO format for dates and times.
8793 tz = The time zone to convert the given time to (no
8794 conversion occurs if null).
8795
8796 Throws:
8797 $(REF DateTimeException,std,datetime,date) if the given string is
8798 not in the ISO format or if the resulting $(LREF SysTime) would not
8799 be valid.
8800 +/
8801 static SysTime fromISOString(S)(scope const S isoString, immutable TimeZone tz = null) @safe
8802 if (isSomeString!S)
8803 {
8804 import std.algorithm.searching : startsWith, find;
8805 import std.conv : to;
8806 import std.string : strip;
8807 import std.utf : byCodeUnit;
8808
8809 auto str = strip(isoString);
8810 immutable skipFirst = str.startsWith('+', '-');
8811
8812 auto found = (skipFirst ? str[1..$] : str).byCodeUnit.find('.', 'Z', '+', '-');
8813 auto dateTimeStr = str[0 .. $ - found[0].length];
8814
8815 typeof(str.byCodeUnit) foundTZ; // needs to have longer lifetime than zoneStr
8816 typeof(str) fracSecStr;
8817 typeof(str) zoneStr;
8818
8819 if (found[1] != 0)
8820 {
8821 if (found[1] == 1)
8822 {
8823 foundTZ = found[0].find('Z', '+', '-')[0];
8824
8825 if (foundTZ.length != 0)
8826 {
8827 static if (isNarrowString!S)
8828 {
8829 fracSecStr = found[0][0 .. $ - foundTZ.length].source;
8830 zoneStr = foundTZ.source;
8831 }
8832 else
8833 {
8834 fracSecStr = found[0][0 .. $ - foundTZ.length];
8835 zoneStr = foundTZ;
8836 }
8837 }
8838 else
8839 {
8840 static if (isNarrowString!S)
8841 fracSecStr = found[0].source;
8842 else
8843 fracSecStr = found[0];
8844 }
8845 }
8846 else
8847 {
8848 static if (isNarrowString!S)
8849 zoneStr = found[0].source;
8850 else
8851 zoneStr = found[0];
8852 }
8853 }
8854
8855 try
8856 {
8857 auto dateTime = DateTime.fromISOString(dateTimeStr);
8858 auto fracSec = fracSecsFromISOString(fracSecStr);
8859
8860 Rebindable!(immutable TimeZone) parsedZone;
8861
8862 if (zoneStr.empty)
8863 parsedZone = LocalTime();
8864 else if (zoneStr == "Z")
8865 parsedZone = UTC();
8866 else
8867 {
8868 try
8869 parsedZone = SimpleTimeZone.fromISOString(zoneStr);
8870 catch (DateTimeException dte)
8871 parsedZone = SimpleTimeZone.fromISOExtString(zoneStr);
8872 }
8873
8874 auto retval = SysTime(dateTime, fracSec, parsedZone);
8875
8876 if (tz !is null)
8877 retval.timezone = tz;
8878
8879 return retval;
8880 }
8881 catch (DateTimeException dte)
8882 throw new DateTimeException(format("Invalid format for SysTime.fromISOString: %s", isoString));
8883 }
8884
8885 ///
8886 @safe unittest
8887 {
8888 import core.time : hours, msecs, usecs, hnsecs;
8889 import std.datetime.date : DateTime;
8890 import std.datetime.timezone : SimpleTimeZone, UTC;
8891
8892 assert(SysTime.fromISOString("20100704T070612") ==
8893 SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
8894
8895 assert(SysTime.fromISOString("19981225T021500.007") ==
8896 SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(7)));
8897
8898 assert(SysTime.fromISOString("00000105T230959.00002") ==
8899 SysTime(DateTime(0, 1, 5, 23, 9, 59), usecs(20)));
8900
8901 assert(SysTime.fromISOString("20130207T043937.000050392") ==
8902 SysTime(DateTime(2013, 2, 7, 4, 39, 37), hnsecs(503)));
8903
8904 assert(SysTime.fromISOString("-00040105T000002") ==
8905 SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
8906
8907 assert(SysTime.fromISOString(" 20100704T070612 ") ==
8908 SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
8909
8910 assert(SysTime.fromISOString("20100704T070612Z") ==
8911 SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
8912
8913 assert(SysTime.fromISOString("20100704T070612-0800") ==
8914 SysTime(DateTime(2010, 7, 4, 7, 6, 12),
8915 new immutable SimpleTimeZone(hours(-8))));
8916
8917 assert(SysTime.fromISOString("20100704T070612+0800") ==
8918 SysTime(DateTime(2010, 7, 4, 7, 6, 12),
8919 new immutable SimpleTimeZone(hours(8))));
8920 }
8921
8922 @safe unittest
8923 {
8924 import core.time;
8925 foreach (str; ["", "20100704000000", "20100704 000000", "20100704t000000",
8926 "20100704T000000.", "20100704T000000.A", "20100704T000000.Z",
8927 "20100704T000000.0000000A", "20100704T000000.00000000A",
8928 "20100704T000000+", "20100704T000000-", "20100704T000000:",
8929 "20100704T000000-:", "20100704T000000+:", "20100704T000000-1:",
8930 "20100704T000000+1:", "20100704T000000+1:0",
8931 "20100704T000000-12.00", "20100704T000000+12.00",
8932 "20100704T000000-8", "20100704T000000+8",
8933 "20100704T000000-800", "20100704T000000+800",
8934 "20100704T000000-080", "20100704T000000+080",
8935 "20100704T000000-2400", "20100704T000000+2400",
8936 "20100704T000000-1260", "20100704T000000+1260",
8937 "20100704T000000.0-8", "20100704T000000.0+8",
8938 "20100704T000000.0-800", "20100704T000000.0+800",
8939 "20100704T000000.0-080", "20100704T000000.0+080",
8940 "20100704T000000.0-2400", "20100704T000000.0+2400",
8941 "20100704T000000.0-1260", "20100704T000000.0+1260",
8942 "20100704T000000-8:00", "20100704T000000+8:00",
8943 "20100704T000000-08:0", "20100704T000000+08:0",
8944 "20100704T000000-24:00", "20100704T000000+24:00",
8945 "20100704T000000-12:60", "20100704T000000+12:60",
8946 "20100704T000000.0-8:00", "20100704T000000.0+8:00",
8947 "20100704T000000.0-08:0", "20100704T000000.0+08:0",
8948 "20100704T000000.0-24:00", "20100704T000000.0+24:00",
8949 "20100704T000000.0-12:60", "20100704T000000.0+12:60",
8950 "2010-07-0400:00:00", "2010-07-04 00:00:00",
8951 "2010-07-04t00:00:00", "2010-07-04T00:00:00.",
8952 "2010-Jul-0400:00:00", "2010-Jul-04 00:00:00", "2010-Jul-04t00:00:00",
8953 "2010-Jul-04T00:00:00", "2010-Jul-04 00:00:00.",
8954 "2010-12-22T172201", "2010-Dec-22 17:22:01"])
8955 {
8956 assertThrown!DateTimeException(SysTime.fromISOString(str), format("[%s]", str));
8957 }
8958
8959 static void test(string str, SysTime st, size_t line = __LINE__)
8960 {
8961 if (SysTime.fromISOString(str) != st)
8962 throw new AssertError("unittest failure", __FILE__, line);
8963 }
8964
8965 test("20101222T172201", SysTime(DateTime(2010, 12, 22, 17, 22, 1)));
8966 test("19990706T123033", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8967 test("-19990706T123033", SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
8968 test("+019990706T123033", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8969 test("19990706T123033 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8970 test(" 19990706T123033", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8971 test(" 19990706T123033 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8972
8973 test("19070707T121212.0", SysTime(DateTime(1907, 7, 7, 12, 12, 12)));
8974 test("19070707T121212.0000000", SysTime(DateTime(1907, 7, 7, 12, 12, 12)));
8975 test("19070707T121212.0000001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), hnsecs(1)));
8976 test("20100704T000000.00000000", SysTime(Date(2010, 7, 4)));
8977 test("20100704T000000.00000009", SysTime(Date(2010, 7, 4)));
8978 test("20100704T000000.00000019", SysTime(DateTime(2010, 7, 4), hnsecs(1)));
8979 test("19070707T121212.000001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), usecs(1)));
8980 test("19070707T121212.0000010", SysTime(DateTime(1907, 7, 7, 12, 12, 12), usecs(1)));
8981 test("19070707T121212.001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), msecs(1)));
8982 test("19070707T121212.0010000", SysTime(DateTime(1907, 7, 7, 12, 12, 12), msecs(1)));
8983
8984 auto west60 = new immutable SimpleTimeZone(hours(-1));
8985 auto west90 = new immutable SimpleTimeZone(minutes(-90));
8986 auto west480 = new immutable SimpleTimeZone(hours(-8));
8987 auto east60 = new immutable SimpleTimeZone(hours(1));
8988 auto east90 = new immutable SimpleTimeZone(minutes(90));
8989 auto east480 = new immutable SimpleTimeZone(hours(8));
8990
8991 test("20101222T172201Z", SysTime(DateTime(2010, 12, 22, 17, 22, 1), UTC()));
8992 test("20101222T172201-0100", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west60));
8993 test("20101222T172201-01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west60));
8994 test("20101222T172201-0130", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west90));
8995 test("20101222T172201-0800", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west480));
8996 test("20101222T172201+0100", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
8997 test("20101222T172201+01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
8998 test("20101222T172201+0130", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east90));
8999 test("20101222T172201+0800", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east480));
9000
9001 test("20101103T065106.57159Z", SysTime(DateTime(2010, 11, 3, 6, 51, 6), hnsecs(5715900), UTC()));
9002 test("20101222T172201.23412Z", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(2_341_200), UTC()));
9003 test("20101222T172201.23112-0100", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(2_311_200), west60));
9004 test("20101222T172201.45-01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(4_500_000), west60));
9005 test("20101222T172201.1-0130", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(1_000_000), west90));
9006 test("20101222T172201.55-0800", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(5_500_000), west480));
9007 test("20101222T172201.1234567+0100", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(1_234_567), east60));
9008 test("20101222T172201.0+01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
9009 test("20101222T172201.0000000+0130", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east90));
9010 test("20101222T172201.45+0800", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(4_500_000), east480));
9011
9012 // for dstring coverage
9013 assert(SysTime.fromISOString("20101222T172201.23112-0100"d) == SysTime(
9014 DateTime(2010, 12, 22, 17, 22, 1), hnsecs(2_311_200), west60));
9015 assert(SysTime.fromISOString("19070707T121212.0010000"d) == SysTime(
9016 DateTime(1907, 7, 7, 12, 12, 12), msecs(1)));
9017
9018 // @@@DEPRECATED_2019-07@@@
9019 // This isn't deprecated per se, but that text will make it so that it
9020 // pops up when deprecations are moved along around July 2019. At that
9021 // time, we will update fromISOString so that it is conformant with ISO
9022 // 8601, and it will no longer accept ISO extended time zones (it does
9023 // currently because of https://issues.dlang.org/show_bug.cgi?id=15654
9024 // toISOString used to incorrectly use the ISO extended time zone format).
9025 // These tests will then start failing will need to be updated accordingly.
9026 // Also, the notes about this issue in toISOString and fromISOString's
9027 // documentation will need to be removed.
9028 test("20101222T172201-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west60));
9029 test("20101222T172201-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west90));
9030 test("20101222T172201-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west480));
9031 test("20101222T172201+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
9032 test("20101222T172201+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east90));
9033 test("20101222T172201+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east480));
9034
9035 test("20101222T172201.23112-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(2_311_200), west60));
9036 test("20101222T172201.1-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(1_000_000), west90));
9037 test("20101222T172201.55-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(5_500_000), west480));
9038 test("20101222T172201.1234567+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(1_234_567), east60));
9039 test("20101222T172201.0000000+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east90));
9040 test("20101222T172201.45+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(4_500_000), east480));
9041
9042 static void testScope(scope ref string str) @safe
9043 {
9044 auto result = SysTime.fromISOString(str);
9045 }
9046 }
9047
9048 // https://issues.dlang.org/show_bug.cgi?id=17801
9049 @safe unittest
9050 {
9051 import std.conv : to;
9052 import std.meta : AliasSeq;
9053 static foreach (C; AliasSeq!(char, wchar, dchar))
9054 {
9055 static foreach (S; AliasSeq!(C[], const(C)[], immutable(C)[]))
9056 {
9057 assert(SysTime.fromISOString(to!S("20121221T141516Z")) ==
9058 SysTime(DateTime(2012, 12, 21, 14, 15, 16), UTC()));
9059 }
9060 }
9061 }
9062
9063
9064 /++
9065 Creates a $(LREF SysTime) from a string with the format
9066 YYYY-MM-DDTHH:MM:SS.FFFFFFFTZ (where F is fractional seconds and TZ
9067 is the time zone). Whitespace is stripped from the given string.
9068
9069 The exact format is exactly as described in $(LREF toISOExtString)
9070 except that trailing zeroes are permitted - including having fractional
9071 seconds with all zeroes. The time zone and fractional seconds are
9072 optional, however, a decimal point with nothing following it is invalid.
9073 Also, while $(LREF toISOExtString) will never generate a
9074 string with more than 7 digits in the fractional seconds (because that's
9075 the limit with hecto-nanosecond precision), it will allow more than 7
9076 digits in order to read strings from other sources that have higher
9077 precision (however, any digits beyond 7 will be truncated).
9078
9079 If there is no time zone in the string, then
9080 $(REF LocalTime,std,datetime,timezone) is used. If the time zone is "Z",
9081 then `UTC` is used. Otherwise, a
9082 $(REF SimpleTimeZone,std,datetime,timezone) which corresponds to the
9083 given offset from UTC is used. To get the returned $(LREF SysTime) to be
9084 a particular time zone, pass in that time zone and the $(LREF SysTime)
9085 to be returned will be converted to that time zone (though it will still
9086 be read in as whatever time zone is in its string).
9087
9088 The accepted formats for time zone offsets are +HH, -HH, +HH:MM, and
9089 -HH:MM.
9090
9091 Params:
9092 isoExtString = A string formatted in the ISO Extended format for
9093 dates and times.
9094 tz = The time zone to convert the given time to (no
9095 conversion occurs if null).
9096
9097 Throws:
9098 $(REF DateTimeException,std,datetime,date) if the given string is
9099 not in the ISO format or if the resulting $(LREF SysTime) would not
9100 be valid.
9101 +/
9102 static SysTime fromISOExtString(S)(scope const S isoExtString, immutable TimeZone tz = null) @safe
9103 if (isSomeString!(S))
9104 {
9105 import std.algorithm.searching : countUntil, find;
9106 import std.conv : to;
9107 import std.string : strip, indexOf;
9108
9109 auto str = strip(isoExtString);
9110
9111 auto tIndex = str.indexOf('T');
9112 enforce!DateTimeException(tIndex != -1,
9113 format("Invalid format for SysTime.fromISOExtString: %s", isoExtString));
9114
9115 auto found = str[tIndex + 1 .. $].find('.', 'Z', '+', '-');
9116 auto dateTimeStr = str[0 .. $ - found[0].length];
9117
9118 typeof(str) foundTZ; // needs to have longer lifetime than zoneStr
9119 typeof(str) fracSecStr;
9120 typeof(str) zoneStr;
9121
9122 if (found[1] != 0)
9123 {
9124 if (found[1] == 1)
9125 {
9126 foundTZ = found[0].find('Z', '+', '-')[0];
9127
9128 if (foundTZ.length != 0)
9129 {
9130 fracSecStr = found[0][0 .. $ - foundTZ.length];
9131 zoneStr = foundTZ;
9132 }
9133 else
9134 fracSecStr = found[0];
9135 }
9136 else
9137 zoneStr = found[0];
9138 }
9139
9140 try
9141 {
9142 auto dateTime = DateTime.fromISOExtString(dateTimeStr);
9143 auto fracSec = fracSecsFromISOString(fracSecStr);
9144 Rebindable!(immutable TimeZone) parsedZone;
9145
9146 if (zoneStr.empty)
9147 parsedZone = LocalTime();
9148 else if (zoneStr == "Z")
9149 parsedZone = UTC();
9150 else
9151 parsedZone = SimpleTimeZone.fromISOExtString(zoneStr);
9152
9153 auto retval = SysTime(dateTime, fracSec, parsedZone);
9154
9155 if (tz !is null)
9156 retval.timezone = tz;
9157
9158 return retval;
9159 }
9160 catch (DateTimeException dte)
9161 throw new DateTimeException(format("Invalid format for SysTime.fromISOExtString: %s", isoExtString));
9162 }
9163
9164 ///
9165 @safe unittest
9166 {
9167 import core.time : hours, msecs, usecs, hnsecs;
9168 import std.datetime.date : DateTime;
9169 import std.datetime.timezone : SimpleTimeZone, UTC;
9170
9171 assert(SysTime.fromISOExtString("2010-07-04T07:06:12") ==
9172 SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
9173
9174 assert(SysTime.fromISOExtString("1998-12-25T02:15:00.007") ==
9175 SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(7)));
9176
9177 assert(SysTime.fromISOExtString("0000-01-05T23:09:59.00002") ==
9178 SysTime(DateTime(0, 1, 5, 23, 9, 59), usecs(20)));
9179
9180 assert(SysTime.fromISOExtString("2013-02-07T04:39:37.000050392") ==
9181 SysTime(DateTime(2013, 2, 7, 4, 39, 37), hnsecs(503)));
9182
9183 assert(SysTime.fromISOExtString("-0004-01-05T00:00:02") ==
9184 SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
9185
9186 assert(SysTime.fromISOExtString(" 2010-07-04T07:06:12 ") ==
9187 SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
9188
9189 assert(SysTime.fromISOExtString("2010-07-04T07:06:12Z") ==
9190 SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
9191
9192 assert(SysTime.fromISOExtString("2010-07-04T07:06:12-08:00") ==
9193 SysTime(DateTime(2010, 7, 4, 7, 6, 12),
9194 new immutable SimpleTimeZone(hours(-8))));
9195 assert(SysTime.fromISOExtString("2010-07-04T07:06:12+08:00") ==
9196 SysTime(DateTime(2010, 7, 4, 7, 6, 12),
9197 new immutable SimpleTimeZone(hours(8))));
9198 }
9199
9200 @safe unittest
9201 {
9202 import core.time;
9203 foreach (str; ["", "20100704000000", "20100704 000000",
9204 "20100704t000000", "20100704T000000.", "20100704T000000.0",
9205 "2010-07:0400:00:00", "2010-07-04 00:00:00",
9206 "2010-07-04 00:00:00", "2010-07-04t00:00:00",
9207 "2010-07-04T00:00:00.", "2010-07-04T00:00:00.A", "2010-07-04T00:00:00.Z",
9208 "2010-07-04T00:00:00.0000000A", "2010-07-04T00:00:00.00000000A",
9209 "2010-07-04T00:00:00+", "2010-07-04T00:00:00-",
9210 "2010-07-04T00:00:00:", "2010-07-04T00:00:00-:", "2010-07-04T00:00:00+:",
9211 "2010-07-04T00:00:00-1:", "2010-07-04T00:00:00+1:", "2010-07-04T00:00:00+1:0",
9212 "2010-07-04T00:00:00-12.00", "2010-07-04T00:00:00+12.00",
9213 "2010-07-04T00:00:00-8", "2010-07-04T00:00:00+8",
9214 "20100704T000000-800", "20100704T000000+800",
9215 "20100704T000000-080", "20100704T000000+080",
9216 "20100704T000000-2400", "20100704T000000+2400",
9217 "20100704T000000-1260", "20100704T000000+1260",
9218 "20100704T000000.0-800", "20100704T000000.0+800",
9219 "20100704T000000.0-8", "20100704T000000.0+8",
9220 "20100704T000000.0-080", "20100704T000000.0+080",
9221 "20100704T000000.0-2400", "20100704T000000.0+2400",
9222 "20100704T000000.0-1260", "20100704T000000.0+1260",
9223 "2010-07-04T00:00:00-8:00", "2010-07-04T00:00:00+8:00",
9224 "2010-07-04T00:00:00-24:00", "2010-07-04T00:00:00+24:00",
9225 "2010-07-04T00:00:00-12:60", "2010-07-04T00:00:00+12:60",
9226 "2010-07-04T00:00:00.0-8:00", "2010-07-04T00:00:00.0+8:00",
9227 "2010-07-04T00:00:00.0-8", "2010-07-04T00:00:00.0+8",
9228 "2010-07-04T00:00:00.0-24:00", "2010-07-04T00:00:00.0+24:00",
9229 "2010-07-04T00:00:00.0-12:60", "2010-07-04T00:00:00.0+12:60",
9230 "2010-Jul-0400:00:00", "2010-Jul-04t00:00:00",
9231 "2010-Jul-04 00:00:00.", "2010-Jul-04 00:00:00.0",
9232 "20101222T172201", "2010-Dec-22 17:22:01"])
9233 {
9234 assertThrown!DateTimeException(SysTime.fromISOExtString(str), format("[%s]", str));
9235 }
9236
9237 static void test(string str, SysTime st, size_t line = __LINE__)
9238 {
9239 if (SysTime.fromISOExtString(str) != st)
9240 throw new AssertError("unittest failure", __FILE__, line);
9241 }
9242
9243 test("2010-12-22T17:22:01", SysTime(DateTime(2010, 12, 22, 17, 22, 1)));
9244 test("1999-07-06T12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
9245 test("-1999-07-06T12:30:33", SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
9246 test("+01999-07-06T12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
9247 test("1999-07-06T12:30:33 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
9248 test(" 1999-07-06T12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
9249 test(" 1999-07-06T12:30:33 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
9250
9251 test("1907-07-07T12:12:12.0", SysTime(DateTime(1907, 7, 7, 12, 12, 12)));
9252 test("1907-07-07T12:12:12.0000000", SysTime(DateTime(1907, 7, 7, 12, 12, 12)));
9253 test("1907-07-07T12:12:12.0000001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), hnsecs(1)));
9254 test("2010-07-04T00:00:00.00000000", SysTime(Date(2010, 7, 4)));
9255 test("2010-07-04T00:00:00.00000009", SysTime(Date(2010, 7, 4)));
9256 test("2010-07-04T00:00:00.00000019", SysTime(DateTime(2010, 7, 4), hnsecs(1)));
9257 test("1907-07-07T12:12:12.000001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), usecs(1)));
9258 test("1907-07-07T12:12:12.0000010", SysTime(DateTime(1907, 7, 7, 12, 12, 12), usecs(1)));
9259 test("1907-07-07T12:12:12.001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), msecs(1)));
9260 test("1907-07-07T12:12:12.0010000", SysTime(DateTime(1907, 7, 7, 12, 12, 12), msecs(1)));
9261
9262 auto west60 = new immutable SimpleTimeZone(hours(-1));
9263 auto west90 = new immutable SimpleTimeZone(minutes(-90));
9264 auto west480 = new immutable SimpleTimeZone(hours(-8));
9265 auto east60 = new immutable SimpleTimeZone(hours(1));
9266 auto east90 = new immutable SimpleTimeZone(minutes(90));
9267 auto east480 = new immutable SimpleTimeZone(hours(8));
9268
9269 test("2010-12-22T17:22:01Z", SysTime(DateTime(2010, 12, 22, 17, 22, 1), UTC()));
9270 test("2010-12-22T17:22:01-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west60));
9271 test("2010-12-22T17:22:01-01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west60));
9272 test("2010-12-22T17:22:01-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west90));
9273 test("2010-12-22T17:22:01-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west480));
9274 test("2010-12-22T17:22:01+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
9275 test("2010-12-22T17:22:01+01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
9276 test("2010-12-22T17:22:01+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east90));
9277 test("2010-12-22T17:22:01+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east480));
9278
9279 test("2010-11-03T06:51:06.57159Z", SysTime(DateTime(2010, 11, 3, 6, 51, 6), hnsecs(5715900), UTC()));
9280 test("2010-12-22T17:22:01.23412Z", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(2_341_200), UTC()));
9281 test("2010-12-22T17:22:01.23112-01:00",
9282 SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(2_311_200), west60));
9283 test("2010-12-22T17:22:01.45-01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(4_500_000), west60));
9284 test("2010-12-22T17:22:01.1-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(1_000_000), west90));
9285 test("2010-12-22T17:22:01.55-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(5_500_000), west480));
9286 test("2010-12-22T17:22:01.1234567+01:00",
9287 SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(1_234_567), east60));
9288 test("2010-12-22T17:22:01.0+01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
9289 test("2010-12-22T17:22:01.0000000+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east90));
9290 test("2010-12-22T17:22:01.45+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(4_500_000), east480));
9291
9292 static void testScope(scope ref string str) @safe
9293 {
9294 auto result = SysTime.fromISOExtString(str);
9295 }
9296 }
9297
9298 // https://issues.dlang.org/show_bug.cgi?id=17801
9299 @safe unittest
9300 {
9301 import core.time;
9302 import std.conv : to;
9303 import std.meta : AliasSeq;
9304 static foreach (C; AliasSeq!(char, wchar, dchar))
9305 {
9306 static foreach (S; AliasSeq!(C[], const(C)[], immutable(C)[]))
9307 {
9308 assert(SysTime.fromISOExtString(to!S("2012-12-21T14:15:16Z")) ==
9309 SysTime(DateTime(2012, 12, 21, 14, 15, 16), UTC()));
9310 }
9311 }
9312 }
9313
9314
9315 /++
9316 Creates a $(LREF SysTime) from a string with the format
9317 YYYY-Mon-DD HH:MM:SS.FFFFFFFTZ (where F is fractional seconds and TZ
9318 is the time zone). Whitespace is stripped from the given string.
9319
9320 The exact format is exactly as described in $(LREF toSimpleString) except
9321 that trailing zeroes are permitted - including having fractional seconds
9322 with all zeroes. The time zone and fractional seconds are optional,
9323 however, a decimal point with nothing following it is invalid.
9324 Also, while $(LREF toSimpleString) will never generate a
9325 string with more than 7 digits in the fractional seconds (because that's
9326 the limit with hecto-nanosecond precision), it will allow more than 7
9327 digits in order to read strings from other sources that have higher
9328 precision (however, any digits beyond 7 will be truncated).
9329
9330 If there is no time zone in the string, then
9331 $(REF LocalTime,std,datetime,timezone) is used. If the time zone is "Z",
9332 then `UTC` is used. Otherwise, a
9333 $(REF SimpleTimeZone,std,datetime,timezone) which corresponds to the
9334 given offset from UTC is used. To get the returned $(LREF SysTime) to be
9335 a particular time zone, pass in that time zone and the $(LREF SysTime)
9336 to be returned will be converted to that time zone (though it will still
9337 be read in as whatever time zone is in its string).
9338
9339 The accepted formats for time zone offsets are +HH, -HH, +HH:MM, and
9340 -HH:MM.
9341
9342 Params:
9343 simpleString = A string formatted in the way that
9344 `toSimpleString` formats dates and times.
9345 tz = The time zone to convert the given time to (no
9346 conversion occurs if null).
9347
9348 Throws:
9349 $(REF DateTimeException,std,datetime,date) if the given string is
9350 not in the ISO format or if the resulting $(LREF SysTime) would not
9351 be valid.
9352 +/
9353 static SysTime fromSimpleString(S)(scope const S simpleString, immutable TimeZone tz = null) @safe
9354 if (isSomeString!(S))
9355 {
9356 import std.algorithm.searching : find;
9357 import std.conv : to;
9358 import std.string : strip, indexOf;
9359
9360 auto str = strip(simpleString);
9361
9362 auto spaceIndex = str.indexOf(' ');
9363 enforce!DateTimeException(spaceIndex != -1,
9364 format("Invalid format for SysTime.fromSimpleString: %s", simpleString));
9365
9366 auto found = str[spaceIndex + 1 .. $].find('.', 'Z', '+', '-');
9367 auto dateTimeStr = str[0 .. $ - found[0].length];
9368
9369 typeof(str) foundTZ; // needs to have longer lifetime than zoneStr
9370 typeof(str) fracSecStr;
9371 typeof(str) zoneStr;
9372
9373 if (found[1] != 0)
9374 {
9375 if (found[1] == 1)
9376 {
9377 foundTZ = found[0].find('Z', '+', '-')[0];
9378
9379 if (foundTZ.length != 0)
9380 {
9381 fracSecStr = found[0][0 .. $ - foundTZ.length];
9382 zoneStr = foundTZ;
9383 }
9384 else
9385 fracSecStr = found[0];
9386 }
9387 else
9388 zoneStr = found[0];
9389 }
9390
9391 try
9392 {
9393 auto dateTime = DateTime.fromSimpleString(dateTimeStr);
9394 auto fracSec = fracSecsFromISOString(fracSecStr);
9395 Rebindable!(immutable TimeZone) parsedZone;
9396
9397 if (zoneStr.empty)
9398 parsedZone = LocalTime();
9399 else if (zoneStr == "Z")
9400 parsedZone = UTC();
9401 else
9402 parsedZone = SimpleTimeZone.fromISOExtString(zoneStr);
9403
9404 auto retval = SysTime(dateTime, fracSec, parsedZone);
9405
9406 if (tz !is null)
9407 retval.timezone = tz;
9408
9409 return retval;
9410 }
9411 catch (DateTimeException dte)
9412 throw new DateTimeException(format("Invalid format for SysTime.fromSimpleString: %s", simpleString));
9413 }
9414
9415 ///
9416 @safe unittest
9417 {
9418 import core.time : hours, msecs, usecs, hnsecs;
9419 import std.datetime.date : DateTime;
9420 import std.datetime.timezone : SimpleTimeZone, UTC;
9421
9422 assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12") ==
9423 SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
9424
9425 assert(SysTime.fromSimpleString("1998-Dec-25 02:15:00.007") ==
9426 SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(7)));
9427
9428 assert(SysTime.fromSimpleString("0000-Jan-05 23:09:59.00002") ==
9429 SysTime(DateTime(0, 1, 5, 23, 9, 59), usecs(20)));
9430
9431 assert(SysTime.fromSimpleString("2013-Feb-07 04:39:37.000050392") ==
9432 SysTime(DateTime(2013, 2, 7, 4, 39, 37), hnsecs(503)));
9433
9434 assert(SysTime.fromSimpleString("-0004-Jan-05 00:00:02") ==
9435 SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
9436
9437 assert(SysTime.fromSimpleString(" 2010-Jul-04 07:06:12 ") ==
9438 SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
9439
9440 assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12Z") ==
9441 SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
9442
9443 assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12-08:00") ==
9444 SysTime(DateTime(2010, 7, 4, 7, 6, 12),
9445 new immutable SimpleTimeZone(hours(-8))));
9446
9447 assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12+08:00") ==
9448 SysTime(DateTime(2010, 7, 4, 7, 6, 12),
9449 new immutable SimpleTimeZone(hours(8))));
9450 }
9451
9452 @safe unittest
9453 {
9454 import core.time;
9455 foreach (str; ["", "20100704000000", "20100704 000000",
9456 "20100704t000000", "20100704T000000.", "20100704T000000.0",
9457 "2010-07-0400:00:00", "2010-07-04 00:00:00", "2010-07-04t00:00:00",
9458 "2010-07-04T00:00:00.", "2010-07-04T00:00:00.0",
9459 "2010-Jul-0400:00:00", "2010-Jul-04t00:00:00", "2010-Jul-04T00:00:00",
9460 "2010-Jul-04 00:00:00.", "2010-Jul-04 00:00:00.A", "2010-Jul-04 00:00:00.Z",
9461 "2010-Jul-04 00:00:00.0000000A", "2010-Jul-04 00:00:00.00000000A",
9462 "2010-Jul-04 00:00:00+", "2010-Jul-04 00:00:00-",
9463 "2010-Jul-04 00:00:00:", "2010-Jul-04 00:00:00-:",
9464 "2010-Jul-04 00:00:00+:", "2010-Jul-04 00:00:00-1:",
9465 "2010-Jul-04 00:00:00+1:", "2010-Jul-04 00:00:00+1:0",
9466 "2010-Jul-04 00:00:00-12.00", "2010-Jul-04 00:00:00+12.00",
9467 "2010-Jul-04 00:00:00-8", "2010-Jul-04 00:00:00+8",
9468 "20100704T000000-800", "20100704T000000+800",
9469 "20100704T000000-080", "20100704T000000+080",
9470 "20100704T000000-2400", "20100704T000000+2400",
9471 "20100704T000000-1260", "20100704T000000+1260",
9472 "20100704T000000.0-800", "20100704T000000.0+800",
9473 "20100704T000000.0-8", "20100704T000000.0+8",
9474 "20100704T000000.0-080", "20100704T000000.0+080",
9475 "20100704T000000.0-2400", "20100704T000000.0+2400",
9476 "20100704T000000.0-1260", "20100704T000000.0+1260",
9477 "2010-Jul-04 00:00:00-8:00", "2010-Jul-04 00:00:00+8:00",
9478 "2010-Jul-04 00:00:00-08:0", "2010-Jul-04 00:00:00+08:0",
9479 "2010-Jul-04 00:00:00-24:00", "2010-Jul-04 00:00:00+24:00",
9480 "2010-Jul-04 00:00:00-12:60", "2010-Jul-04 00:00:00+24:60",
9481 "2010-Jul-04 00:00:00.0-8:00", "2010-Jul-04 00:00:00+8:00",
9482 "2010-Jul-04 00:00:00.0-8", "2010-Jul-04 00:00:00.0+8",
9483 "2010-Jul-04 00:00:00.0-08:0", "2010-Jul-04 00:00:00.0+08:0",
9484 "2010-Jul-04 00:00:00.0-24:00", "2010-Jul-04 00:00:00.0+24:00",
9485 "2010-Jul-04 00:00:00.0-12:60", "2010-Jul-04 00:00:00.0+24:60",
9486 "20101222T172201", "2010-12-22T172201"])
9487 {
9488 assertThrown!DateTimeException(SysTime.fromSimpleString(str), format("[%s]", str));
9489 }
9490
9491 static void test(string str, SysTime st, size_t line = __LINE__)
9492 {
9493 if (SysTime.fromSimpleString(str) != st)
9494 throw new AssertError("unittest failure", __FILE__, line);
9495 }
9496
9497 test("2010-Dec-22 17:22:01", SysTime(DateTime(2010, 12, 22, 17, 22, 1)));
9498 test("1999-Jul-06 12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
9499 test("-1999-Jul-06 12:30:33", SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
9500 test("+01999-Jul-06 12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
9501 test("1999-Jul-06 12:30:33 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
9502 test(" 1999-Jul-06 12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
9503 test(" 1999-Jul-06 12:30:33 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
9504
9505 test("1907-Jul-07 12:12:12.0", SysTime(DateTime(1907, 7, 7, 12, 12, 12)));
9506 test("1907-Jul-07 12:12:12.0000000", SysTime(DateTime(1907, 7, 7, 12, 12, 12)));
9507 test("2010-Jul-04 00:00:00.00000000", SysTime(Date(2010, 7, 4)));
9508 test("2010-Jul-04 00:00:00.00000009", SysTime(Date(2010, 7, 4)));
9509 test("2010-Jul-04 00:00:00.00000019", SysTime(DateTime(2010, 7, 4), hnsecs(1)));
9510 test("1907-Jul-07 12:12:12.0000001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), hnsecs(1)));
9511 test("1907-Jul-07 12:12:12.000001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), usecs(1)));
9512 test("1907-Jul-07 12:12:12.0000010", SysTime(DateTime(1907, 7, 7, 12, 12, 12), usecs(1)));
9513 test("1907-Jul-07 12:12:12.001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), msecs(1)));
9514 test("1907-Jul-07 12:12:12.0010000", SysTime(DateTime(1907, 7, 7, 12, 12, 12), msecs(1)));
9515
9516 auto west60 = new immutable SimpleTimeZone(hours(-1));
9517 auto west90 = new immutable SimpleTimeZone(minutes(-90));
9518 auto west480 = new immutable SimpleTimeZone(hours(-8));
9519 auto east60 = new immutable SimpleTimeZone(hours(1));
9520 auto east90 = new immutable SimpleTimeZone(minutes(90));
9521 auto east480 = new immutable SimpleTimeZone(hours(8));
9522
9523 test("2010-Dec-22 17:22:01Z", SysTime(DateTime(2010, 12, 22, 17, 22, 1), UTC()));
9524 test("2010-Dec-22 17:22:01-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west60));
9525 test("2010-Dec-22 17:22:01-01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west60));
9526 test("2010-Dec-22 17:22:01-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west90));
9527 test("2010-Dec-22 17:22:01-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west480));
9528 test("2010-Dec-22 17:22:01+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
9529 test("2010-Dec-22 17:22:01+01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
9530 test("2010-Dec-22 17:22:01+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east90));
9531 test("2010-Dec-22 17:22:01+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east480));
9532
9533 test("2010-Nov-03 06:51:06.57159Z", SysTime(DateTime(2010, 11, 3, 6, 51, 6), hnsecs(5715900), UTC()));
9534 test("2010-Dec-22 17:22:01.23412Z", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(2_341_200), UTC()));
9535 test("2010-Dec-22 17:22:01.23112-01:00",
9536 SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(2_311_200), west60));
9537 test("2010-Dec-22 17:22:01.45-01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(4_500_000), west60));
9538 test("2010-Dec-22 17:22:01.1-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(1_000_000), west90));
9539 test("2010-Dec-22 17:22:01.55-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(5_500_000), west480));
9540 test("2010-Dec-22 17:22:01.1234567+01:00",
9541 SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(1_234_567), east60));
9542 test("2010-Dec-22 17:22:01.0+01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
9543 test("2010-Dec-22 17:22:01.0000000+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east90));
9544 test("2010-Dec-22 17:22:01.45+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(4_500_000), east480));
9545
9546 static void testScope(scope ref string str) @safe
9547 {
9548 auto result = SysTime.fromSimpleString(str);
9549 }
9550 }
9551
9552 // https://issues.dlang.org/show_bug.cgi?id=17801
9553 @safe unittest
9554 {
9555 import core.time;
9556 import std.conv : to;
9557 import std.meta : AliasSeq;
9558 static foreach (C; AliasSeq!(char, wchar, dchar))
9559 {
9560 static foreach (S; AliasSeq!(C[], const(C)[], immutable(C)[]))
9561 {
9562 assert(SysTime.fromSimpleString(to!S("2012-Dec-21 14:15:16Z")) ==
9563 SysTime(DateTime(2012, 12, 21, 14, 15, 16), UTC()));
9564 }
9565 }
9566 }
9567
9568
9569 /++
9570 Returns the $(LREF SysTime) farthest in the past which is representable
9571 by $(LREF SysTime).
9572
9573 The $(LREF SysTime) which is returned is in UTC.
9574 +/
9575 @property static SysTime min() @safe pure nothrow
9576 {
9577 return SysTime(long.min, UTC());
9578 }
9579
9580 @safe unittest
9581 {
9582 assert(SysTime.min.year < 0);
9583 assert(SysTime.min < SysTime.max);
9584 }
9585
9586
9587 /++
9588 Returns the $(LREF SysTime) farthest in the future which is representable
9589 by $(LREF SysTime).
9590
9591 The $(LREF SysTime) which is returned is in UTC.
9592 +/
9593 @property static SysTime max() @safe pure nothrow
9594 {
9595 return SysTime(long.max, UTC());
9596 }
9597
9598 @safe unittest
9599 {
9600 assert(SysTime.max.year > 0);
9601 assert(SysTime.max > SysTime.min);
9602 }
9603
9604
9605 private:
9606
9607 /+
9608 Returns `stdTime` converted to $(LREF SysTime)'s time zone.
9609 +/
9610 @property long adjTime() @safe const nothrow scope
9611 {
9612 return _timezone.utcToTZ(_stdTime);
9613 }
9614
9615
9616 /+
9617 Converts the given hnsecs from $(LREF SysTime)'s time zone to std time.
9618 +/
9619 @property void adjTime(long adjTime) @safe nothrow scope
9620 {
9621 _stdTime = _timezone.tzToUTC(adjTime);
9622 }
9623
9624
9625 final class InitTimeZone : TimeZone
9626 {
9627 public:
9628
9629 static immutable(InitTimeZone) opCall() @safe pure nothrow @nogc { return _initTimeZone; }
9630
9631 @property override bool hasDST() @safe const nothrow @nogc { return false; }
9632
9633 override bool dstInEffect(long stdTime) @safe const scope nothrow @nogc { return false; }
9634
9635 override long utcToTZ(long stdTime) @safe const scope nothrow @nogc { return 0; }
9636
9637 override long tzToUTC(long adjTime) @safe const scope nothrow @nogc { return 0; }
9638
9639 override Duration utcOffsetAt(long stdTime) @safe const scope nothrow @nogc { return Duration.zero; }
9640
9641 private:
9642
9643 this() @safe immutable pure
9644 {
9645 super("SysTime.init's timezone", "SysTime.init's timezone", "SysTime.init's timezone");
9646 }
9647
9648 static immutable InitTimeZone _initTimeZone = new immutable(InitTimeZone);
9649 }
9650
9651 // https://issues.dlang.org/show_bug.cgi?id=17732
9652 @safe unittest
9653 {
9654 assert(SysTime.init.timezone is InitTimeZone());
9655 assert(SysTime.init.toISOString() == "00010101T000000+00:00");
9656 assert(SysTime.init.toISOExtString() == "0001-01-01T00:00:00+00:00");
9657 assert(SysTime.init.toSimpleString() == "0001-Jan-01 00:00:00+00:00");
9658 assert(SysTime.init.toString() == "0001-Jan-01 00:00:00+00:00");
9659 }
9660
9661 // Assigning a value to _timezone in SysTime.init currently doesn't work due
9662 // to https://issues.dlang.org/show_bug.cgi?id=17740. So, to hack around
9663 // that problem, these accessors have been added so that we can insert a
9664 // runtime check for null and then use InitTimeZone for SysTime.init (which
9665 // which is the only case where _timezone would be null). This thus fixes
9666 // the problem with segfaulting when using SysTime.init but at the cost of
9667 // what should be an unnecessary null check. Once 17740 has finally been
9668 // fixed, _timezoneStorage should be removed, these accessors should be
9669 // removed, and the _timezone variable declaration should be restored.
9670 pragma(inline, true) @property _timezone() @safe const pure nothrow @nogc
9671 {
9672 return _timezoneStorage is null ? InitTimeZone() : _timezoneStorage;
9673 }
9674
9675 pragma(inline, true) @property void _timezone(return scope immutable TimeZone tz) @safe pure nothrow @nogc scope
9676 {
9677 _timezoneStorage = tz;
9678 }
9679
9680
9681 long _stdTime;
9682 Rebindable!(immutable TimeZone) _timezoneStorage;
9683 //Rebindable!(immutable TimeZone) _timezone = InitTimeZone();
9684 }
9685
9686 ///
9687 @safe unittest
9688 {
9689 import core.time : days, hours, seconds;
9690 import std.datetime.date : Date, DateTime;
9691 import std.datetime.timezone : SimpleTimeZone, UTC;
9692
9693 const dt = DateTime(2018, 1, 1, 10, 30, 0);
9694 // make a specific point in time in the UTC timezone
9695 auto st = SysTime(dt, UTC());
9696 assert(st.year == 2018);
9697 assert(st.hour == 10);
9698
9699 // cast to convert
9700 assert(cast(DateTime) st == dt);
9701 assert(cast(Date) st == Date(2018, 1, 1));
9702
9703 // make a specific point in time in the New York timezone
9704 const ny = SysTime(dt,
9705 new immutable SimpleTimeZone(-5.hours, "America/New_York")
9706 );
9707 assert(ny != st);
9708 assert(ny.hour == 10);
9709
9710 // ISO standard time strings
9711 assert(st.toISOString() == "20180101T103000Z");
9712 assert(st.toISOExtString() == "2018-01-01T10:30:00Z");
9713
9714 // add two days and 30 seconds
9715 st += 2.days + 30.seconds;
9716 assert(st.toISOExtString() == "2018-01-03T10:30:30Z");
9717 }
9718
9719
9720 /++
9721 Converts from unix time (which uses midnight, January 1st, 1970 UTC as its
9722 epoch and seconds as its units) to "std time" (which uses midnight,
9723 January 1st, 1 A.D. UTC and hnsecs as its units).
9724
9725 The C standard does not specify the representation of time_t, so it is
9726 implementation defined. On POSIX systems, unix time is equivalent to
9727 time_t, but that's not necessarily true on other systems (e.g. it is
9728 not true for the Digital Mars C runtime). So, be careful when using unix
9729 time with C functions on non-POSIX systems.
9730
9731 "std time"'s epoch is based on the Proleptic Gregorian Calendar per ISO
9732 8601 and is what $(LREF SysTime) uses internally. However, holding the time
9733 as an integer in hnsecs since that epoch technically isn't actually part of
9734 the standard, much as it's based on it, so the name "std time" isn't
9735 particularly good, but there isn't an official name for it. C# uses "ticks"
9736 for the same thing, but they aren't actually clock ticks, and the term
9737 "ticks" $(I is) used for actual clock ticks for $(REF MonoTime, core,time),
9738 so it didn't make sense to use the term ticks here. So, for better or worse,
9739 std.datetime uses the term "std time" for this.
9740
9741 Params:
9742 unixTime = The unix time to convert.
9743
9744 See_Also:
9745 SysTime.fromUnixTime
9746 +/
9747 long unixTimeToStdTime(long unixTime) @safe pure nothrow @nogc
9748 {
9749 return 621_355_968_000_000_000L + convert!("seconds", "hnsecs")(unixTime);
9750 }
9751
9752 ///
9753 @safe unittest
9754 {
9755 import std.datetime.date : DateTime;
9756 import std.datetime.timezone : UTC;
9757
9758 // Midnight, January 1st, 1970
9759 assert(unixTimeToStdTime(0) == 621_355_968_000_000_000L);
9760 assert(SysTime(unixTimeToStdTime(0)) ==
9761 SysTime(DateTime(1970, 1, 1), UTC()));
9762
9763 assert(unixTimeToStdTime(int.max) == 642_830_804_470_000_000L);
9764 assert(SysTime(unixTimeToStdTime(int.max)) ==
9765 SysTime(DateTime(2038, 1, 19, 3, 14, 7), UTC()));
9766
9767 assert(unixTimeToStdTime(-127_127) == 621_354_696_730_000_000L);
9768 assert(SysTime(unixTimeToStdTime(-127_127)) ==
9769 SysTime(DateTime(1969, 12, 30, 12, 41, 13), UTC()));
9770 }
9771
9772 @safe unittest
9773 {
9774 // Midnight, January 2nd, 1970
9775 assert(unixTimeToStdTime(86_400) == 621_355_968_000_000_000L + 864_000_000_000L);
9776 // Midnight, December 31st, 1969
9777 assert(unixTimeToStdTime(-86_400) == 621_355_968_000_000_000L - 864_000_000_000L);
9778
9779 assert(unixTimeToStdTime(0) == (Date(1970, 1, 1) - Date(1, 1, 1)).total!"hnsecs");
9780 assert(unixTimeToStdTime(0) == (DateTime(1970, 1, 1) - DateTime(1, 1, 1)).total!"hnsecs");
9781
9782 foreach (dt; [DateTime(2010, 11, 1, 19, 5, 22), DateTime(1952, 7, 6, 2, 17, 9)])
9783 assert(unixTimeToStdTime((dt - DateTime(1970, 1, 1)).total!"seconds") == (dt - DateTime.init).total!"hnsecs");
9784 }
9785
9786
9787 /++
9788 Converts std time (which uses midnight, January 1st, 1 A.D. UTC as its epoch
9789 and hnsecs as its units) to unix time (which uses midnight, January 1st,
9790 1970 UTC as its epoch and seconds as its units).
9791
9792 The C standard does not specify the representation of time_t, so it is
9793 implementation defined. On POSIX systems, unix time is equivalent to
9794 time_t, but that's not necessarily true on other systems (e.g. it is
9795 not true for the Digital Mars C runtime). So, be careful when using unix
9796 time with C functions on non-POSIX systems.
9797
9798 "std time"'s epoch is based on the Proleptic Gregorian Calendar per ISO
9799 8601 and is what $(LREF SysTime) uses internally. However, holding the time
9800 as an integer in hnsecs since that epoch technically isn't actually part of
9801 the standard, much as it's based on it, so the name "std time" isn't
9802 particularly good, but there isn't an official name for it. C# uses "ticks"
9803 for the same thing, but they aren't actually clock ticks, and the term
9804 "ticks" $(I is) used for actual clock ticks for $(REF MonoTime, core,time),
9805 so it didn't make sense to use the term ticks here. So, for better or worse,
9806 std.datetime uses the term "std time" for this.
9807
9808 By default, the return type is time_t (which is normally an alias for
9809 int on 32-bit systems and long on 64-bit systems), but if a different
9810 size is required than either int or long can be passed as a template
9811 argument to get the desired size.
9812
9813 If the return type is int, and the result can't fit in an int, then the
9814 closest value that can be held in 32 bits will be used (so `int.max`
9815 if it goes over and `int.min` if it goes under). However, no attempt
9816 is made to deal with integer overflow if the return type is long.
9817
9818 Params:
9819 T = The return type (int or long). It defaults to time_t, which is
9820 normally 32 bits on a 32-bit system and 64 bits on a 64-bit
9821 system.
9822 stdTime = The std time to convert.
9823
9824 Returns:
9825 A signed integer representing the unix time which is equivalent to
9826 the given std time.
9827
9828 See_Also:
9829 SysTime.toUnixTime
9830 +/
9831 T stdTimeToUnixTime(T = time_t)(long stdTime) @safe pure nothrow
9832 if (is(T == int) || is(T == long))
9833 {
9834 immutable unixTime = convert!("hnsecs", "seconds")(stdTime - 621_355_968_000_000_000L);
9835
9836 static assert(is(time_t == int) || is(time_t == long),
9837 "Currently, std.datetime only supports systems where time_t is int or long");
9838
9839 static if (is(T == long))
9840 return unixTime;
9841 else static if (is(T == int))
9842 {
9843 if (unixTime > int.max)
9844 return int.max;
9845 return unixTime < int.min ? int.min : cast(int) unixTime;
9846 }
9847 else
9848 static assert(0, "Bug in template constraint. Only int and long allowed.");
9849 }
9850
9851 ///
9852 @safe unittest
9853 {
9854 // Midnight, January 1st, 1970 UTC
9855 assert(stdTimeToUnixTime(621_355_968_000_000_000L) == 0);
9856
9857 // 2038-01-19 03:14:07 UTC
9858 assert(stdTimeToUnixTime(642_830_804_470_000_000L) == int.max);
9859 }
9860
9861 @safe unittest
9862 {
9863 enum unixEpochAsStdTime = (Date(1970, 1, 1) - Date.init).total!"hnsecs";
9864
9865 assert(stdTimeToUnixTime(unixEpochAsStdTime) == 0); // Midnight, January 1st, 1970
9866 assert(stdTimeToUnixTime(unixEpochAsStdTime + 864_000_000_000L) == 86_400); // Midnight, January 2nd, 1970
9867 assert(stdTimeToUnixTime(unixEpochAsStdTime - 864_000_000_000L) == -86_400); // Midnight, December 31st, 1969
9868
9869 assert(stdTimeToUnixTime((Date(1970, 1, 1) - Date(1, 1, 1)).total!"hnsecs") == 0);
9870 assert(stdTimeToUnixTime((DateTime(1970, 1, 1) - DateTime(1, 1, 1)).total!"hnsecs") == 0);
9871
9872 foreach (dt; [DateTime(2010, 11, 1, 19, 5, 22), DateTime(1952, 7, 6, 2, 17, 9)])
9873 assert(stdTimeToUnixTime((dt - DateTime.init).total!"hnsecs") == (dt - DateTime(1970, 1, 1)).total!"seconds");
9874
9875 enum max = convert!("seconds", "hnsecs")(int.max);
9876 enum min = convert!("seconds", "hnsecs")(int.min);
9877 enum one = convert!("seconds", "hnsecs")(1);
9878
9879 assert(stdTimeToUnixTime!long(unixEpochAsStdTime + max) == int.max);
9880 assert(stdTimeToUnixTime!int(unixEpochAsStdTime + max) == int.max);
9881
9882 assert(stdTimeToUnixTime!long(unixEpochAsStdTime + max + one) == int.max + 1L);
9883 assert(stdTimeToUnixTime!int(unixEpochAsStdTime + max + one) == int.max);
9884 assert(stdTimeToUnixTime!long(unixEpochAsStdTime + max + 9_999_999) == int.max);
9885 assert(stdTimeToUnixTime!int(unixEpochAsStdTime + max + 9_999_999) == int.max);
9886
9887 assert(stdTimeToUnixTime!long(unixEpochAsStdTime + min) == int.min);
9888 assert(stdTimeToUnixTime!int(unixEpochAsStdTime + min) == int.min);
9889
9890 assert(stdTimeToUnixTime!long(unixEpochAsStdTime + min - one) == int.min - 1L);
9891 assert(stdTimeToUnixTime!int(unixEpochAsStdTime + min - one) == int.min);
9892 assert(stdTimeToUnixTime!long(unixEpochAsStdTime + min - 9_999_999) == int.min);
9893 assert(stdTimeToUnixTime!int(unixEpochAsStdTime + min - 9_999_999) == int.min);
9894 }
9895
9896
9897 version (StdDdoc)
9898 {
9899 version (Windows)
9900 {}
9901 else
9902 {
9903 alias SYSTEMTIME = void*;
9904 alias FILETIME = void*;
9905 }
9906
9907 /++
9908 $(BLUE This function is Windows-Only.)
9909
9910 Converts a `SYSTEMTIME` struct to a $(LREF SysTime).
9911
9912 Params:
9913 st = The `SYSTEMTIME` struct to convert.
9914 tz = The time zone that the time in the `SYSTEMTIME` struct is
9915 assumed to be (if the `SYSTEMTIME` was supplied by a Windows
9916 system call, the `SYSTEMTIME` will either be in local time
9917 or UTC, depending on the call).
9918
9919 Throws:
9920 $(REF DateTimeException,std,datetime,date) if the given
9921 `SYSTEMTIME` will not fit in a $(LREF SysTime), which is highly
9922 unlikely to happen given that `SysTime.max` is in 29,228 A.D. and
9923 the maximum `SYSTEMTIME` is in 30,827 A.D.
9924 +/
9925 SysTime SYSTEMTIMEToSysTime(const scope SYSTEMTIME* st, immutable TimeZone tz = LocalTime()) @safe;
9926
9927
9928 /++
9929 $(BLUE This function is Windows-Only.)
9930
9931 Converts a $(LREF SysTime) to a `SYSTEMTIME` struct.
9932
9933 The `SYSTEMTIME` which is returned will be set using the given
9934 $(LREF SysTime)'s time zone, so to get the `SYSTEMTIME` in
9935 UTC, set the $(LREF SysTime)'s time zone to UTC.
9936
9937 Params:
9938 sysTime = The $(LREF SysTime) to convert.
9939
9940 Throws:
9941 $(REF DateTimeException,std,datetime,date) if the given
9942 $(LREF SysTime) will not fit in a `SYSTEMTIME`. This will only
9943 happen if the $(LREF SysTime)'s date is prior to 1601 A.D.
9944 +/
9945 SYSTEMTIME SysTimeToSYSTEMTIME(scope SysTime sysTime) @safe;
9946
9947
9948 /++
9949 $(BLUE This function is Windows-Only.)
9950
9951 Converts a `FILETIME` struct to the number of hnsecs since midnight,
9952 January 1st, 1 A.D.
9953
9954 Params:
9955 ft = The `FILETIME` struct to convert.
9956
9957 Throws:
9958 $(REF DateTimeException,std,datetime,date) if the given
9959 `FILETIME` cannot be represented as the return value.
9960 +/
9961 long FILETIMEToStdTime(scope const FILETIME* ft) @safe;
9962
9963
9964 /++
9965 $(BLUE This function is Windows-Only.)
9966
9967 Converts a `FILETIME` struct to a $(LREF SysTime).
9968
9969 Params:
9970 ft = The `FILETIME` struct to convert.
9971 tz = The time zone that the $(LREF SysTime) will be in
9972 (`FILETIME`s are in UTC).
9973
9974 Throws:
9975 $(REF DateTimeException,std,datetime,date) if the given
9976 `FILETIME` will not fit in a $(LREF SysTime).
9977 +/
9978 SysTime FILETIMEToSysTime(scope const FILETIME* ft, immutable TimeZone tz = LocalTime()) @safe;
9979
9980
9981 /++
9982 $(BLUE This function is Windows-Only.)
9983
9984 Converts a number of hnsecs since midnight, January 1st, 1 A.D. to a
9985 `FILETIME` struct.
9986
9987 Params:
9988 stdTime = The number of hnsecs since midnight, January 1st, 1 A.D.
9989 UTC.
9990
9991 Throws:
9992 $(REF DateTimeException,std,datetime,date) if the given value will
9993 not fit in a `FILETIME`.
9994 +/
9995 FILETIME stdTimeToFILETIME(long stdTime) @safe;
9996
9997
9998 /++
9999 $(BLUE This function is Windows-Only.)
10000
10001 Converts a $(LREF SysTime) to a `FILETIME` struct.
10002
10003 `FILETIME`s are always in UTC.
10004
10005 Params:
10006 sysTime = The $(LREF SysTime) to convert.
10007
10008 Throws:
10009 $(REF DateTimeException,std,datetime,date) if the given
10010 $(LREF SysTime) will not fit in a `FILETIME`.
10011 +/
10012 FILETIME SysTimeToFILETIME(scope SysTime sysTime) @safe;
10013 }
10014 else version (Windows)
10015 {
10016 SysTime SYSTEMTIMEToSysTime(const scope SYSTEMTIME* st, immutable TimeZone tz = LocalTime()) @safe
10017 {
10018 const max = SysTime.max;
10019
10020 static void throwLaterThanMax()
10021 {
10022 throw new DateTimeException("The given SYSTEMTIME is for a date greater than SysTime.max.");
10023 }
10024
10025 if (st.wYear > max.year)
10026 throwLaterThanMax();
10027 else if (st.wYear == max.year)
10028 {
10029 if (st.wMonth > max.month)
10030 throwLaterThanMax();
10031 else if (st.wMonth == max.month)
10032 {
10033 if (st.wDay > max.day)
10034 throwLaterThanMax();
10035 else if (st.wDay == max.day)
10036 {
10037 if (st.wHour > max.hour)
10038 throwLaterThanMax();
10039 else if (st.wHour == max.hour)
10040 {
10041 if (st.wMinute > max.minute)
10042 throwLaterThanMax();
10043 else if (st.wMinute == max.minute)
10044 {
10045 if (st.wSecond > max.second)
10046 throwLaterThanMax();
10047 else if (st.wSecond == max.second)
10048 {
10049 if (st.wMilliseconds > max.fracSecs.total!"msecs")
10050 throwLaterThanMax();
10051 }
10052 }
10053 }
10054 }
10055 }
10056 }
10057
10058 auto dt = DateTime(st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
10059
10060 import core.time : msecs;
10061 return SysTime(dt, msecs(st.wMilliseconds), tz);
10062 }
10063
10064 @system unittest
10065 {
10066 auto sysTime = Clock.currTime(UTC());
10067 SYSTEMTIME st = void;
10068 GetSystemTime(&st);
10069 auto converted = SYSTEMTIMEToSysTime(&st, UTC());
10070 import core.time : abs;
10071 assert(abs((converted - sysTime)) <= dur!"seconds"(2));
10072
10073 static void testScope(scope SYSTEMTIME* st) @safe
10074 {
10075 auto result = SYSTEMTIMEToSysTime(st);
10076 }
10077 }
10078
10079
10080 SYSTEMTIME SysTimeToSYSTEMTIME(scope SysTime sysTime) @safe
10081 {
10082 immutable dt = cast(DateTime) sysTime;
10083
10084 if (dt.year < 1601)
10085 throw new DateTimeException("SYSTEMTIME cannot hold dates prior to the year 1601.");
10086
10087 SYSTEMTIME st;
10088
10089 st.wYear = dt.year;
10090 st.wMonth = dt.month;
10091 st.wDayOfWeek = dt.dayOfWeek;
10092 st.wDay = dt.day;
10093 st.wHour = dt.hour;
10094 st.wMinute = dt.minute;
10095 st.wSecond = dt.second;
10096 st.wMilliseconds = cast(ushort) sysTime.fracSecs.total!"msecs";
10097
10098 return st;
10099 }
10100
10101 @system unittest
10102 {
10103 SYSTEMTIME st = void;
10104 GetSystemTime(&st);
10105 auto sysTime = SYSTEMTIMEToSysTime(&st, UTC());
10106
10107 SYSTEMTIME result = SysTimeToSYSTEMTIME(sysTime);
10108
10109 assert(st.wYear == result.wYear);
10110 assert(st.wMonth == result.wMonth);
10111 assert(st.wDayOfWeek == result.wDayOfWeek);
10112 assert(st.wDay == result.wDay);
10113 assert(st.wHour == result.wHour);
10114 assert(st.wMinute == result.wMinute);
10115 assert(st.wSecond == result.wSecond);
10116 assert(st.wMilliseconds == result.wMilliseconds);
10117
10118 static void testScope(scope ref SysTime st) @safe
10119 {
10120 auto localResult = SysTimeToSYSTEMTIME(st);
10121 }
10122 }
10123
10124 private enum hnsecsFrom1601 = 504_911_232_000_000_000L;
10125
10126 long FILETIMEToStdTime(scope const FILETIME* ft) @safe
10127 {
10128 ULARGE_INTEGER ul;
10129 ul.HighPart = ft.dwHighDateTime;
10130 ul.LowPart = ft.dwLowDateTime;
10131 ulong tempHNSecs = ul.QuadPart;
10132
10133 if (tempHNSecs > long.max - hnsecsFrom1601)
10134 throw new DateTimeException("The given FILETIME cannot be represented as a stdTime value.");
10135
10136 return cast(long) tempHNSecs + hnsecsFrom1601;
10137 }
10138
10139 SysTime FILETIMEToSysTime(scope const FILETIME* ft, immutable TimeZone tz = LocalTime()) @safe
10140 {
10141 auto sysTime = SysTime(FILETIMEToStdTime(ft), UTC());
10142 sysTime.timezone = tz;
10143 return sysTime;
10144 }
10145
10146 @system unittest
10147 {
10148 auto sysTime = Clock.currTime(UTC());
10149 SYSTEMTIME st = void;
10150 GetSystemTime(&st);
10151
10152 FILETIME ft = void;
10153 SystemTimeToFileTime(&st, &ft);
10154
10155 auto converted = FILETIMEToSysTime(&ft);
10156
10157 import core.time : abs;
10158 assert(abs((converted - sysTime)) <= dur!"seconds"(2));
10159
10160 static void testScope(scope FILETIME* ft) @safe
10161 {
10162 auto result = FILETIMEToSysTime(ft);
10163 }
10164 }
10165
10166
10167 FILETIME stdTimeToFILETIME(long stdTime) @safe
10168 {
10169 if (stdTime < hnsecsFrom1601)
10170 throw new DateTimeException("The given stdTime value cannot be represented as a FILETIME.");
10171
10172 ULARGE_INTEGER ul;
10173 ul.QuadPart = cast(ulong) stdTime - hnsecsFrom1601;
10174
10175 FILETIME ft;
10176 ft.dwHighDateTime = ul.HighPart;
10177 ft.dwLowDateTime = ul.LowPart;
10178
10179 return ft;
10180 }
10181
10182 FILETIME SysTimeToFILETIME(scope SysTime sysTime) @safe
10183 {
10184 return stdTimeToFILETIME(sysTime.stdTime);
10185 }
10186
10187 @system unittest
10188 {
10189 SYSTEMTIME st = void;
10190 GetSystemTime(&st);
10191
10192 FILETIME ft = void;
10193 SystemTimeToFileTime(&st, &ft);
10194 auto sysTime = FILETIMEToSysTime(&ft, UTC());
10195
10196 FILETIME result = SysTimeToFILETIME(sysTime);
10197
10198 assert(ft.dwLowDateTime == result.dwLowDateTime);
10199 assert(ft.dwHighDateTime == result.dwHighDateTime);
10200
10201 static void testScope(scope ref SysTime st) @safe
10202 {
10203 auto local_result = SysTimeToFILETIME(st);
10204 }
10205 }
10206 }
10207
10208
10209 /++
10210 Type representing the DOS file date/time format.
10211 +/
10212 alias DosFileTime = uint;
10213
10214 /++
10215 Converts from DOS file date/time to $(LREF SysTime).
10216
10217 Params:
10218 dft = The DOS file time to convert.
10219 tz = The time zone which the DOS file time is assumed to be in.
10220
10221 Throws:
10222 $(REF DateTimeException,std,datetime,date) if the `DosFileTime` is
10223 invalid.
10224 +/
10225 SysTime DosFileTimeToSysTime(DosFileTime dft, immutable TimeZone tz = LocalTime()) @safe
10226 {
10227 uint dt = cast(uint) dft;
10228
10229 if (dt == 0)
10230 throw new DateTimeException("Invalid DosFileTime.");
10231
10232 int year = ((dt >> 25) & 0x7F) + 1980;
10233 int month = ((dt >> 21) & 0x0F); // 1 .. 12
10234 int dayOfMonth = ((dt >> 16) & 0x1F); // 1 .. 31
10235 int hour = (dt >> 11) & 0x1F; // 0 .. 23
10236 int minute = (dt >> 5) & 0x3F; // 0 .. 59
10237 int second = (dt << 1) & 0x3E; // 0 .. 58 (in 2 second increments)
10238
10239 try
10240 return SysTime(DateTime(year, month, dayOfMonth, hour, minute, second), tz);
10241 catch (DateTimeException dte)
10242 throw new DateTimeException("Invalid DosFileTime", __FILE__, __LINE__, dte);
10243 }
10244
10245 ///
10246 @safe unittest
10247 {
10248 import std.datetime.date : DateTime;
10249
10250 assert(DosFileTimeToSysTime(0b00000000001000010000000000000000) == SysTime(DateTime(1980, 1, 1, 0, 0, 0)));
10251 assert(DosFileTimeToSysTime(0b11111111100111111011111101111101) == SysTime(DateTime(2107, 12, 31, 23, 59, 58)));
10252 assert(DosFileTimeToSysTime(0x3E3F8456) == SysTime(DateTime(2011, 1, 31, 16, 34, 44)));
10253 }
10254
10255 @safe unittest
10256 {
10257 static void testScope(scope ref DosFileTime dft) @safe
10258 {
10259 auto result = DosFileTimeToSysTime(dft);
10260 }
10261 }
10262
10263
10264 /++
10265 Converts from $(LREF SysTime) to DOS file date/time.
10266
10267 Params:
10268 sysTime = The $(LREF SysTime) to convert.
10269
10270 Throws:
10271 $(REF DateTimeException,std,datetime,date) if the given
10272 $(LREF SysTime) cannot be converted to a `DosFileTime`.
10273 +/
10274 DosFileTime SysTimeToDosFileTime(scope SysTime sysTime) @safe
10275 {
10276 auto dateTime = cast(DateTime) sysTime;
10277
10278 if (dateTime.year < 1980)
10279 throw new DateTimeException("DOS File Times cannot hold dates prior to 1980.");
10280
10281 if (dateTime.year > 2107)
10282 throw new DateTimeException("DOS File Times cannot hold dates past 2107.");
10283
10284 uint retval = 0;
10285 retval = (dateTime.year - 1980) << 25;
10286 retval |= (dateTime.month & 0x0F) << 21;
10287 retval |= (dateTime.day & 0x1F) << 16;
10288 retval |= (dateTime.hour & 0x1F) << 11;
10289 retval |= (dateTime.minute & 0x3F) << 5;
10290 retval |= (dateTime.second >> 1) & 0x1F;
10291
10292 return cast(DosFileTime) retval;
10293 }
10294
10295 ///
10296 @safe unittest
10297 {
10298 import std.datetime.date : DateTime;
10299
10300 assert(SysTimeToDosFileTime(SysTime(DateTime(1980, 1, 1, 0, 0, 0))) == 0b00000000001000010000000000000000);
10301 assert(SysTimeToDosFileTime(SysTime(DateTime(2107, 12, 31, 23, 59, 58))) == 0b11111111100111111011111101111101);
10302 assert(SysTimeToDosFileTime(SysTime(DateTime(2011, 1, 31, 16, 34, 44))) == 0x3E3F8456);
10303 }
10304
10305 @safe unittest
10306 {
10307 static void testScope(scope ref SysTime st) @safe
10308 {
10309 auto result = SysTimeToDosFileTime(st);
10310 }
10311 }
10312
10313
10314 /++
10315 The given array of `char` or random-access range of `char` or
10316 `ubyte` is expected to be in the format specified in
10317 $(HTTP tools.ietf.org/html/rfc5322, RFC 5322) section 3.3 with the
10318 grammar rule $(I date-time). It is the date-time format commonly used in
10319 internet messages such as e-mail and HTTP. The corresponding
10320 $(LREF SysTime) will be returned.
10321
10322 RFC 822 was the original spec (hence the function's name), whereas RFC 5322
10323 is the current spec.
10324
10325 The day of the week is ignored beyond verifying that it's a valid day of the
10326 week, as the day of the week can be inferred from the date. It is not
10327 checked whether the given day of the week matches the actual day of the week
10328 of the given date (though it is technically invalid per the spec if the
10329 day of the week doesn't match the actual day of the week of the given date).
10330
10331 If the time zone is `"-0000"` (or considered to be equivalent to
10332 `"-0000"` by section 4.3 of the spec), a
10333 $(REF SimpleTimeZone,std,datetime,timezone) with a utc offset of `0` is
10334 used rather than $(REF UTC,std,datetime,timezone), whereas `"+0000"` uses
10335 $(REF UTC,std,datetime,timezone).
10336
10337 Note that because $(LREF SysTime) does not currently support having a second
10338 value of 60 (as is sometimes done for leap seconds), if the date-time value
10339 does have a value of 60 for the seconds, it is treated as 59.
10340
10341 The one area in which this function violates RFC 5322 is that it accepts
10342 `"\n"` in folding whitespace in the place of `"\r\n"`, because the
10343 HTTP spec requires it.
10344
10345 Throws:
10346 $(REF DateTimeException,std,datetime,date) if the given string doesn't
10347 follow the grammar for a date-time field or if the resulting
10348 $(LREF SysTime) is invalid.
10349 +/
10350 SysTime parseRFC822DateTime()(scope const char[] value) @safe
10351 {
10352 import std.string : representation;
10353 return parseRFC822DateTime(value.representation);
10354 }
10355
10356 /++ Ditto +/
10357 SysTime parseRFC822DateTime(R)(scope R value)
10358 if (isRandomAccessRange!R && hasSlicing!R && hasLength!R &&
10359 (is(immutable ElementType!R == immutable char) || is(immutable ElementType!R == immutable ubyte)))
10360 {
10361 import std.algorithm.searching : find, all;
10362 import std.ascii : isDigit, isAlpha, isPrintable;
10363 import std.conv : to;
10364 import std.functional : not;
10365 import std.string : capitalize, format;
10366 import std.traits : EnumMembers, isArray;
10367 import std.typecons : Rebindable;
10368
10369 void stripAndCheckLen(R valueBefore, size_t minLen, size_t line = __LINE__)
10370 {
10371 value = _stripCFWS(valueBefore);
10372 if (value.length < minLen)
10373 throw new DateTimeException("date-time value too short", __FILE__, line);
10374 }
10375 stripAndCheckLen(value, "7Dec1200:00A".length);
10376
10377 static if (isArray!R && (is(ElementEncodingType!R == char) || is(ElementEncodingType!R == ubyte)))
10378 {
10379 static string sliceAsString(R str) @trusted
10380 {
10381 return cast(string) str;
10382 }
10383 }
10384 else
10385 {
10386 char[4] temp;
10387 char[] sliceAsString(R str) @trusted
10388 {
10389 size_t i = 0;
10390 foreach (c; str)
10391 temp[i++] = cast(char) c;
10392 return temp[0 .. str.length];
10393 }
10394 }
10395
10396 // day-of-week
10397 if (isAlpha(value[0]))
10398 {
10399 auto dowStr = sliceAsString(value[0 .. 3]);
10400 switch (dowStr)
10401 {
10402 foreach (dow; EnumMembers!DayOfWeek)
10403 {
10404 enum dowC = capitalize(to!string(dow));
10405 case dowC:
10406 goto afterDoW;
10407 }
10408 default: throw new DateTimeException(format("Invalid day-of-week: %s", dowStr));
10409 }
10410 afterDoW: stripAndCheckLen(value[3 .. value.length], ",7Dec1200:00A".length);
10411 if (value[0] != ',')
10412 throw new DateTimeException("day-of-week missing comma");
10413 stripAndCheckLen(value[1 .. value.length], "7Dec1200:00A".length);
10414 }
10415
10416 // day
10417 immutable digits = isDigit(value[1]) ? 2 : 1;
10418 immutable day = _convDigits!short(value[0 .. digits]);
10419 if (day == -1)
10420 throw new DateTimeException("Invalid day");
10421 stripAndCheckLen(value[digits .. value.length], "Dec1200:00A".length);
10422
10423 // month
10424 Month month;
10425 {
10426 auto monStr = sliceAsString(value[0 .. 3]);
10427 switch (monStr)
10428 {
10429 foreach (mon; EnumMembers!Month)
10430 {
10431 enum monC = capitalize(to!string(mon));
10432 case monC:
10433 {
10434 month = mon;
10435 goto afterMon;
10436 }
10437 }
10438 default: throw new DateTimeException(format("Invalid month: %s", monStr));
10439 }
10440 afterMon: stripAndCheckLen(value[3 .. value.length], "1200:00A".length);
10441 }
10442
10443 // year
10444 auto found = value[2 .. value.length].find!(not!(isDigit))();
10445 size_t yearLen = value.length - found.length;
10446 if (found.length == 0)
10447 throw new DateTimeException("Invalid year");
10448 if (found[0] == ':')
10449 yearLen -= 2;
10450 auto year = _convDigits!short(value[0 .. yearLen]);
10451 if (year < 1900)
10452 {
10453 if (year == -1)
10454 throw new DateTimeException("Invalid year");
10455 if (yearLen < 4)
10456 {
10457 if (yearLen == 3)
10458 year += 1900;
10459 else if (yearLen == 2)
10460 year += year < 50 ? 2000 : 1900;
10461 else
10462 throw new DateTimeException("Invalid year. Too few digits.");
10463 }
10464 else
10465 throw new DateTimeException("Invalid year. Cannot be earlier than 1900.");
10466 }
10467 stripAndCheckLen(value[yearLen .. value.length], "00:00A".length);
10468
10469 // hour
10470 immutable hour = _convDigits!short(value[0 .. 2]);
10471 stripAndCheckLen(value[2 .. value.length], ":00A".length);
10472 if (value[0] != ':')
10473 throw new DateTimeException("Invalid hour");
10474 stripAndCheckLen(value[1 .. value.length], "00A".length);
10475
10476 // minute
10477 immutable minute = _convDigits!short(value[0 .. 2]);
10478 stripAndCheckLen(value[2 .. value.length], "A".length);
10479
10480 // second
10481 short second;
10482 if (value[0] == ':')
10483 {
10484 stripAndCheckLen(value[1 .. value.length], "00A".length);
10485 second = _convDigits!short(value[0 .. 2]);
10486 // this is just if/until SysTime is sorted out to fully support leap seconds
10487 if (second == 60)
10488 second = 59;
10489 stripAndCheckLen(value[2 .. value.length], "A".length);
10490 }
10491
10492 immutable(TimeZone) parseTZ(int sign)
10493 {
10494 if (value.length < 5)
10495 throw new DateTimeException("Invalid timezone");
10496 immutable zoneHours = _convDigits!short(value[1 .. 3]);
10497 immutable zoneMinutes = _convDigits!short(value[3 .. 5]);
10498 if (zoneHours == -1 || zoneMinutes == -1 || zoneMinutes > 59)
10499 throw new DateTimeException("Invalid timezone");
10500 value = value[5 .. value.length];
10501 immutable utcOffset = (dur!"hours"(zoneHours) + dur!"minutes"(zoneMinutes)) * sign;
10502 if (utcOffset == Duration.zero)
10503 {
10504 return sign == 1 ? cast(immutable(TimeZone))UTC()
10505 : cast(immutable(TimeZone))new immutable SimpleTimeZone(Duration.zero);
10506 }
10507 return new immutable(SimpleTimeZone)(utcOffset);
10508 }
10509
10510 // zone
10511 Rebindable!(immutable TimeZone) tz;
10512 if (value[0] == '-')
10513 tz = parseTZ(-1);
10514 else if (value[0] == '+')
10515 tz = parseTZ(1);
10516 else
10517 {
10518 // obs-zone
10519 immutable tzLen = value.length - find(value, ' ', '\t', '(')[0].length;
10520 switch (sliceAsString(value[0 .. tzLen <= 4 ? tzLen : 4]))
10521 {
10522 case "UT": case "GMT": tz = UTC(); break;
10523 case "EST": tz = new immutable SimpleTimeZone(dur!"hours"(-5)); break;
10524 case "EDT": tz = new immutable SimpleTimeZone(dur!"hours"(-4)); break;
10525 case "CST": tz = new immutable SimpleTimeZone(dur!"hours"(-6)); break;
10526 case "CDT": tz = new immutable SimpleTimeZone(dur!"hours"(-5)); break;
10527 case "MST": tz = new immutable SimpleTimeZone(dur!"hours"(-7)); break;
10528 case "MDT": tz = new immutable SimpleTimeZone(dur!"hours"(-6)); break;
10529 case "PST": tz = new immutable SimpleTimeZone(dur!"hours"(-8)); break;
10530 case "PDT": tz = new immutable SimpleTimeZone(dur!"hours"(-7)); break;
10531 case "J": case "j": throw new DateTimeException("Invalid timezone");
10532 default:
10533 {
10534 if (all!(isAlpha)(value[0 .. tzLen]))
10535 {
10536 tz = new immutable SimpleTimeZone(Duration.zero);
10537 break;
10538 }
10539 throw new DateTimeException("Invalid timezone");
10540 }
10541 }
10542 value = value[tzLen .. value.length];
10543 }
10544
10545 // This is kind of arbitrary. Technically, nothing but CFWS is legal past
10546 // the end of the timezone, but we don't want to be picky about that in a
10547 // function that's just parsing rather than validating. So, the idea here is
10548 // that if the next character is printable (and not part of CFWS), then it
10549 // might be part of the timezone and thus affect what the timezone was
10550 // supposed to be, so we'll throw, but otherwise, we'll just ignore it.
10551 if (!value.empty && isPrintable(value[0]) && value[0] != ' ' && value[0] != '(')
10552 throw new DateTimeException("Invalid timezone");
10553
10554 try
10555 return SysTime(DateTime(year, month, day, hour, minute, second), tz);
10556 catch (DateTimeException dte)
10557 throw new DateTimeException("date-time format is correct, but the resulting SysTime is invalid.", dte);
10558 }
10559
10560 ///
10561 @safe unittest
10562 {
10563 import core.time : hours;
10564 import std.datetime.date : DateTime, DateTimeException;
10565 import std.datetime.timezone : SimpleTimeZone, UTC;
10566 import std.exception : assertThrown;
10567
10568 auto tz = new immutable SimpleTimeZone(hours(-8));
10569 assert(parseRFC822DateTime("Sat, 6 Jan 1990 12:14:19 -0800") ==
10570 SysTime(DateTime(1990, 1, 6, 12, 14, 19), tz));
10571
10572 assert(parseRFC822DateTime("9 Jul 2002 13:11 +0000") ==
10573 SysTime(DateTime(2002, 7, 9, 13, 11, 0), UTC()));
10574
10575 auto badStr = "29 Feb 2001 12:17:16 +0200";
10576 assertThrown!DateTimeException(parseRFC822DateTime(badStr));
10577 }
10578
10579 version (StdUnittest) private void testParse822(alias cr)(string str, SysTime expected, size_t line = __LINE__)
10580 {
10581 import std.format : format;
10582 auto value = cr(str);
10583 auto result = parseRFC822DateTime(value);
10584 if (result != expected)
10585 throw new AssertError(format("wrong result. expected [%s], actual[%s]", expected, result), __FILE__, line);
10586 }
10587
10588 version (StdUnittest) private void testBadParse822(alias cr)(string str, size_t line = __LINE__)
10589 {
10590 try
10591 parseRFC822DateTime(cr(str));
10592 catch (DateTimeException)
10593 return;
10594 throw new AssertError("No DateTimeException was thrown", __FILE__, line);
10595 }
10596
10597 @system unittest
10598 {
10599 import core.time;
10600 import std.algorithm.iteration : filter, map;
10601 import std.algorithm.searching : canFind;
10602 import std.array : array;
10603 import std.ascii : letters;
10604 import std.format : format;
10605 import std.meta : AliasSeq;
10606 import std.range : chain, iota, take;
10607 import std.stdio : writefln, writeln;
10608 import std.string : representation;
10609
10610 static struct Rand3Letters
10611 {
10612 enum empty = false;
10613 @property auto front() { return _mon; }
10614 void popFront()
10615 {
10616 import std.exception : assumeUnique;
10617 import std.random : rndGen;
10618 _mon = rndGen.map!(a => letters[a % letters.length])().take(3).array().assumeUnique();
10619 }
10620 string _mon;
10621 static auto start() { Rand3Letters retval; retval.popFront(); return retval; }
10622 }
10623
10624 static foreach (cr; AliasSeq!(function(string a){return cast(char[]) a;},
10625 function(string a){return cast(ubyte[]) a;},
10626 function(string a){return a;},
10627 function(string a){return map!(b => cast(char) b)(a.representation);}))
10628 {(){ // workaround slow optimizations for large functions
10629 // https://issues.dlang.org/show_bug.cgi?id=2396
10630 scope(failure) writeln(typeof(cr).stringof);
10631 alias test = testParse822!cr;
10632 alias testBad = testBadParse822!cr;
10633
10634 immutable std1 = DateTime(2012, 12, 21, 13, 14, 15);
10635 immutable std2 = DateTime(2012, 12, 21, 13, 14, 0);
10636 immutable dst1 = DateTime(1976, 7, 4, 5, 4, 22);
10637 immutable dst2 = DateTime(1976, 7, 4, 5, 4, 0);
10638
10639 test("21 Dec 2012 13:14:15 +0000", SysTime(std1, UTC()));
10640 test("21 Dec 2012 13:14 +0000", SysTime(std2, UTC()));
10641 test("Fri, 21 Dec 2012 13:14 +0000", SysTime(std2, UTC()));
10642 test("Fri, 21 Dec 2012 13:14:15 +0000", SysTime(std1, UTC()));
10643
10644 test("04 Jul 1976 05:04:22 +0000", SysTime(dst1, UTC()));
10645 test("04 Jul 1976 05:04 +0000", SysTime(dst2, UTC()));
10646 test("Sun, 04 Jul 1976 05:04 +0000", SysTime(dst2, UTC()));
10647 test("Sun, 04 Jul 1976 05:04:22 +0000", SysTime(dst1, UTC()));
10648
10649 test("4 Jul 1976 05:04:22 +0000", SysTime(dst1, UTC()));
10650 test("4 Jul 1976 05:04 +0000", SysTime(dst2, UTC()));
10651 test("Sun, 4 Jul 1976 05:04 +0000", SysTime(dst2, UTC()));
10652 test("Sun, 4 Jul 1976 05:04:22 +0000", SysTime(dst1, UTC()));
10653
10654 auto badTZ = new immutable SimpleTimeZone(Duration.zero);
10655 test("21 Dec 2012 13:14:15 -0000", SysTime(std1, badTZ));
10656 test("21 Dec 2012 13:14 -0000", SysTime(std2, badTZ));
10657 test("Fri, 21 Dec 2012 13:14 -0000", SysTime(std2, badTZ));
10658 test("Fri, 21 Dec 2012 13:14:15 -0000", SysTime(std1, badTZ));
10659
10660 test("04 Jul 1976 05:04:22 -0000", SysTime(dst1, badTZ));
10661 test("04 Jul 1976 05:04 -0000", SysTime(dst2, badTZ));
10662 test("Sun, 04 Jul 1976 05:04 -0000", SysTime(dst2, badTZ));
10663 test("Sun, 04 Jul 1976 05:04:22 -0000", SysTime(dst1, badTZ));
10664
10665 test("4 Jul 1976 05:04:22 -0000", SysTime(dst1, badTZ));
10666 test("4 Jul 1976 05:04 -0000", SysTime(dst2, badTZ));
10667 test("Sun, 4 Jul 1976 05:04 -0000", SysTime(dst2, badTZ));
10668 test("Sun, 4 Jul 1976 05:04:22 -0000", SysTime(dst1, badTZ));
10669
10670 auto pst = new immutable SimpleTimeZone(dur!"hours"(-8));
10671 auto pdt = new immutable SimpleTimeZone(dur!"hours"(-7));
10672 test("21 Dec 2012 13:14:15 -0800", SysTime(std1, pst));
10673 test("21 Dec 2012 13:14 -0800", SysTime(std2, pst));
10674 test("Fri, 21 Dec 2012 13:14 -0800", SysTime(std2, pst));
10675 test("Fri, 21 Dec 2012 13:14:15 -0800", SysTime(std1, pst));
10676
10677 test("04 Jul 1976 05:04:22 -0700", SysTime(dst1, pdt));
10678 test("04 Jul 1976 05:04 -0700", SysTime(dst2, pdt));
10679 test("Sun, 04 Jul 1976 05:04 -0700", SysTime(dst2, pdt));
10680 test("Sun, 04 Jul 1976 05:04:22 -0700", SysTime(dst1, pdt));
10681
10682 test("4 Jul 1976 05:04:22 -0700", SysTime(dst1, pdt));
10683 test("4 Jul 1976 05:04 -0700", SysTime(dst2, pdt));
10684 test("Sun, 4 Jul 1976 05:04 -0700", SysTime(dst2, pdt));
10685 test("Sun, 4 Jul 1976 05:04:22 -0700", SysTime(dst1, pdt));
10686
10687 auto cet = new immutable SimpleTimeZone(dur!"hours"(1));
10688 auto cest = new immutable SimpleTimeZone(dur!"hours"(2));
10689 test("21 Dec 2012 13:14:15 +0100", SysTime(std1, cet));
10690 test("21 Dec 2012 13:14 +0100", SysTime(std2, cet));
10691 test("Fri, 21 Dec 2012 13:14 +0100", SysTime(std2, cet));
10692 test("Fri, 21 Dec 2012 13:14:15 +0100", SysTime(std1, cet));
10693
10694 test("04 Jul 1976 05:04:22 +0200", SysTime(dst1, cest));
10695 test("04 Jul 1976 05:04 +0200", SysTime(dst2, cest));
10696 test("Sun, 04 Jul 1976 05:04 +0200", SysTime(dst2, cest));
10697 test("Sun, 04 Jul 1976 05:04:22 +0200", SysTime(dst1, cest));
10698
10699 test("4 Jul 1976 05:04:22 +0200", SysTime(dst1, cest));
10700 test("4 Jul 1976 05:04 +0200", SysTime(dst2, cest));
10701 test("Sun, 4 Jul 1976 05:04 +0200", SysTime(dst2, cest));
10702 test("Sun, 4 Jul 1976 05:04:22 +0200", SysTime(dst1, cest));
10703
10704 // dst and std times are switched in the Southern Hemisphere which is why the
10705 // time zone names and DateTime variables don't match.
10706 auto cstStd = new immutable SimpleTimeZone(dur!"hours"(9) + dur!"minutes"(30));
10707 auto cstDST = new immutable SimpleTimeZone(dur!"hours"(10) + dur!"minutes"(30));
10708 test("21 Dec 2012 13:14:15 +1030", SysTime(std1, cstDST));
10709 test("21 Dec 2012 13:14 +1030", SysTime(std2, cstDST));
10710 test("Fri, 21 Dec 2012 13:14 +1030", SysTime(std2, cstDST));
10711 test("Fri, 21 Dec 2012 13:14:15 +1030", SysTime(std1, cstDST));
10712
10713 test("04 Jul 1976 05:04:22 +0930", SysTime(dst1, cstStd));
10714 test("04 Jul 1976 05:04 +0930", SysTime(dst2, cstStd));
10715 test("Sun, 04 Jul 1976 05:04 +0930", SysTime(dst2, cstStd));
10716 test("Sun, 04 Jul 1976 05:04:22 +0930", SysTime(dst1, cstStd));
10717
10718 test("4 Jul 1976 05:04:22 +0930", SysTime(dst1, cstStd));
10719 test("4 Jul 1976 05:04 +0930", SysTime(dst2, cstStd));
10720 test("Sun, 4 Jul 1976 05:04 +0930", SysTime(dst2, cstStd));
10721 test("Sun, 4 Jul 1976 05:04:22 +0930", SysTime(dst1, cstStd));
10722
10723 foreach (int i, mon; _monthNames)
10724 {
10725 test(format("17 %s 2012 00:05:02 +0000", mon), SysTime(DateTime(2012, i + 1, 17, 0, 5, 2), UTC()));
10726 test(format("17 %s 2012 00:05 +0000", mon), SysTime(DateTime(2012, i + 1, 17, 0, 5, 0), UTC()));
10727 }
10728
10729 import std.uni : toLower, toUpper;
10730 foreach (mon; chain(_monthNames[].map!(a => toLower(a))(),
10731 _monthNames[].map!(a => toUpper(a))(),
10732 ["Jam", "Jen", "Fec", "Fdb", "Mas", "Mbr", "Aps", "Aqr", "Mai", "Miy",
10733 "Jum", "Jbn", "Jup", "Jal", "Aur", "Apg", "Sem", "Sap", "Ocm", "Odt",
10734 "Nom", "Nav", "Dem", "Dac"],
10735 Rand3Letters.start().filter!(a => !_monthNames[].canFind(a)).take(20)))
10736 {
10737 scope(failure) writefln("Month: %s", mon);
10738 testBad(format("17 %s 2012 00:05:02 +0000", mon));
10739 testBad(format("17 %s 2012 00:05 +0000", mon));
10740 }
10741
10742 immutable string[7] daysOfWeekNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
10743
10744 {
10745 auto start = SysTime(DateTime(2012, 11, 11, 9, 42, 0), UTC());
10746 int day = 11;
10747
10748 foreach (int i, dow; daysOfWeekNames)
10749 {
10750 auto curr = start + dur!"days"(i);
10751 test(format("%s, %s Nov 2012 09:42:00 +0000", dow, day), curr);
10752 test(format("%s, %s Nov 2012 09:42 +0000", dow, day++), curr);
10753
10754 // Whether the day of the week matches the date is ignored.
10755 test(format("%s, 11 Nov 2012 09:42:00 +0000", dow), start);
10756 test(format("%s, 11 Nov 2012 09:42 +0000", dow), start);
10757 }
10758 }
10759
10760 foreach (dow; chain(daysOfWeekNames[].map!(a => toLower(a))(),
10761 daysOfWeekNames[].map!(a => toUpper(a))(),
10762 ["Sum", "Spn", "Mom", "Man", "Tuf", "Tae", "Wem", "Wdd", "The", "Tur",
10763 "Fro", "Fai", "San", "Sut"],
10764 Rand3Letters.start().filter!(a => !daysOfWeekNames[].canFind(a)).take(20)))
10765 {
10766 scope(failure) writefln("Day of Week: %s", dow);
10767 testBad(format("%s, 11 Nov 2012 09:42:00 +0000", dow));
10768 testBad(format("%s, 11 Nov 2012 09:42 +0000", dow));
10769 }
10770
10771 testBad("31 Dec 1899 23:59:59 +0000");
10772 test("01 Jan 1900 00:00:00 +0000", SysTime(Date(1900, 1, 1), UTC()));
10773 test("01 Jan 1900 00:00:00 -0000", SysTime(Date(1900, 1, 1),
10774 new immutable SimpleTimeZone(Duration.zero)));
10775 test("01 Jan 1900 00:00:00 -0700", SysTime(Date(1900, 1, 1),
10776 new immutable SimpleTimeZone(dur!"hours"(-7))));
10777
10778 {
10779 auto st1 = SysTime(Date(1900, 1, 1), UTC());
10780 auto st2 = SysTime(Date(1900, 1, 1), new immutable SimpleTimeZone(dur!"hours"(-11)));
10781 foreach (i; 1900 .. 2102)
10782 {
10783 test(format("1 Jan %05d 00:00 +0000", i), st1);
10784 test(format("1 Jan %05d 00:00 -1100", i), st2);
10785 st1.add!"years"(1);
10786 st2.add!"years"(1);
10787 }
10788 st1.year = 9998;
10789 st2.year = 9998;
10790 foreach (i; 9998 .. 11_002)
10791 {
10792 test(format("1 Jan %05d 00:00 +0000", i), st1);
10793 test(format("1 Jan %05d 00:00 -1100", i), st2);
10794 st1.add!"years"(1);
10795 st2.add!"years"(1);
10796 }
10797 }
10798
10799 testBad("12 Feb 1907 23:17:09 0000");
10800 testBad("12 Feb 1907 23:17:09 +000");
10801 testBad("12 Feb 1907 23:17:09 -000");
10802 testBad("12 Feb 1907 23:17:09 +00000");
10803 testBad("12 Feb 1907 23:17:09 -00000");
10804 testBad("12 Feb 1907 23:17:09 +A");
10805 testBad("12 Feb 1907 23:17:09 +PST");
10806 testBad("12 Feb 1907 23:17:09 -A");
10807 testBad("12 Feb 1907 23:17:09 -PST");
10808
10809 // test trailing stuff that gets ignored
10810 {
10811 foreach (c; chain(iota(0, 33), ['('], iota(127, ubyte.max + 1)))
10812 {
10813 scope(failure) writefln("c: %d", c);
10814 test(format("21 Dec 2012 13:14:15 +0000%c", cast(char) c), SysTime(std1, UTC()));
10815 test(format("21 Dec 2012 13:14:15 +0000%c ", cast(char) c), SysTime(std1, UTC()));
10816 test(format("21 Dec 2012 13:14:15 +0000%chello", cast(char) c), SysTime(std1, UTC()));
10817 }
10818 }
10819
10820 // test trailing stuff that doesn't get ignored
10821 {
10822 foreach (c; chain(iota(33, '('), iota('(' + 1, 127)))
10823 {
10824 scope(failure) writefln("c: %d", c);
10825 testBad(format("21 Dec 2012 13:14:15 +0000%c", cast(char) c));
10826 testBad(format("21 Dec 2012 13:14:15 +0000%c ", cast(char) c));
10827 testBad(format("21 Dec 2012 13:14:15 +0000%chello", cast(char) c));
10828 }
10829 }
10830
10831 testBad("32 Jan 2012 12:13:14 -0800");
10832 testBad("31 Jan 2012 24:13:14 -0800");
10833 testBad("31 Jan 2012 12:60:14 -0800");
10834 testBad("31 Jan 2012 12:13:61 -0800");
10835 testBad("31 Jan 2012 12:13:14 -0860");
10836 test("31 Jan 2012 12:13:14 -0859",
10837 SysTime(DateTime(2012, 1, 31, 12, 13, 14),
10838 new immutable SimpleTimeZone(dur!"hours"(-8) + dur!"minutes"(-59))));
10839
10840 // leap-seconds
10841 test("21 Dec 2012 15:59:60 -0800", SysTime(DateTime(2012, 12, 21, 15, 59, 59), pst));
10842
10843 // FWS
10844 test("Sun,4 Jul 1976 05:04 +0930", SysTime(dst2, cstStd));
10845 test("Sun,4 Jul 1976 05:04:22 +0930", SysTime(dst1, cstStd));
10846 test("Sun,4 Jul 1976 05:04 +0930 (foo)", SysTime(dst2, cstStd));
10847 test("Sun,4 Jul 1976 05:04:22 +0930 (foo)", SysTime(dst1, cstStd));
10848 test("Sun,4 \r\n Jul \r\n 1976 \r\n 05:04 \r\n +0930 \r\n (foo)", SysTime(dst2, cstStd));
10849 test("Sun,4 \r\n Jul \r\n 1976 \r\n 05:04:22 \r\n +0930 \r\n (foo)", SysTime(dst1, cstStd));
10850
10851 auto str = "01 Jan 2012 12:13:14 -0800 ";
10852 test(str, SysTime(DateTime(2012, 1, 1, 12, 13, 14), new immutable SimpleTimeZone(hours(-8))));
10853 foreach (i; 0 .. str.length)
10854 {
10855 auto currStr = str.dup;
10856 currStr[i] = 'x';
10857 scope(failure) writefln("failed: %s", currStr);
10858 testBad(cast(string) currStr);
10859 }
10860 foreach (i; 2 .. str.length)
10861 {
10862 auto currStr = str[0 .. $ - i];
10863 scope(failure) writefln("failed: %s", currStr);
10864 testBad(cast(string) currStr);
10865 testBad((cast(string) currStr) ~ " ");
10866 }
10867 }();}
10868
10869 static void testScope(scope ref string str) @safe
10870 {
10871 auto result = parseRFC822DateTime(str);
10872 }
10873 }
10874
10875 // Obsolete Format per section 4.3 of RFC 5322.
10876 @system unittest
10877 {
10878 import std.algorithm.iteration : filter, map;
10879 import std.ascii : letters;
10880 import std.exception : collectExceptionMsg;
10881 import std.format : format;
10882 import std.meta : AliasSeq;
10883 import std.range : chain, iota;
10884 import std.stdio : writefln, writeln;
10885 import std.string : representation;
10886
10887 auto std1 = SysTime(DateTime(2012, 12, 21, 13, 14, 15), UTC());
10888 auto std2 = SysTime(DateTime(2012, 12, 21, 13, 14, 0), UTC());
10889 auto std3 = SysTime(DateTime(1912, 12, 21, 13, 14, 15), UTC());
10890 auto std4 = SysTime(DateTime(1912, 12, 21, 13, 14, 0), UTC());
10891 auto dst1 = SysTime(DateTime(1976, 7, 4, 5, 4, 22), UTC());
10892 auto dst2 = SysTime(DateTime(1976, 7, 4, 5, 4, 0), UTC());
10893 auto tooLate1 = SysTime(Date(10_000, 1, 1), UTC());
10894 auto tooLate2 = SysTime(DateTime(12_007, 12, 31, 12, 22, 19), UTC());
10895
10896 static foreach (cr; AliasSeq!(function(string a){return cast(char[]) a;},
10897 function(string a){return cast(ubyte[]) a;},
10898 function(string a){return a;},
10899 function(string a){return map!(b => cast(char) b)(a.representation);}))
10900 {(){ // workaround slow optimizations for large functions
10901 // https://issues.dlang.org/show_bug.cgi?id=2396
10902 scope(failure) writeln(typeof(cr).stringof);
10903 alias test = testParse822!cr;
10904 {
10905 auto list = ["", " ", " \r\n\t", "\t\r\n (hello world( frien(dog)) silly \r\n ) \t\t \r\n ()",
10906 " \n ", "\t\n\t", " \n\t (foo) \n (bar) \r\n (baz) \n "];
10907
10908 foreach (i, cfws; list)
10909 {
10910 scope(failure) writefln("i: %s", i);
10911
10912 test(format("%1$s21%1$sDec%1$s2012%1$s13:14:15%1$s+0000%1$s", cfws), std1);
10913 test(format("%1$s21%1$sDec%1$s2012%1$s13:14%1$s+0000%1$s", cfws), std2);
10914 test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s2012%1$s13:14%1$s+0000%1$s", cfws), std2);
10915 test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s2012%1$s13:14:15%1$s+0000%1$s", cfws), std1);
10916
10917 test(format("%1$s04%1$sJul%1$s1976%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10918 test(format("%1$s04%1$sJul%1$s1976%1$s05:04%1$s+0000%1$s", cfws), dst2);
10919 test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s1976%1$s05:04%1$s+0000%1$s", cfws), dst2);
10920 test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s1976%1$s05:04:22 +0000%1$s", cfws), dst1);
10921
10922 test(format("%1$s4%1$sJul%1$s1976%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10923 test(format("%1$s4%1$sJul%1$s1976%1$s05:04%1$s+0000%1$s", cfws), dst2);
10924 test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s1976%1$s05:04%1$s+0000%1$s", cfws), dst2);
10925 test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s1976%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10926
10927 test(format("%1$s21%1$sDec%1$s12%1$s13:14:15%1$s+0000%1$s", cfws), std1);
10928 test(format("%1$s21%1$sDec%1$s12%1$s13:14%1$s+0000%1$s", cfws), std2);
10929 test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s12%1$s13:14%1$s+0000%1$s", cfws), std2);
10930 test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s12%1$s13:14:15%1$s+0000%1$s", cfws), std1);
10931
10932 test(format("%1$s04%1$sJul%1$s76%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10933 test(format("%1$s04%1$sJul%1$s76%1$s05:04%1$s+0000%1$s", cfws), dst2);
10934 test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s76%1$s05:04%1$s+0000%1$s", cfws), dst2);
10935 test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s76%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10936
10937 test(format("%1$s4%1$sJul%1$s76 05:04:22%1$s+0000%1$s", cfws), dst1);
10938 test(format("%1$s4%1$sJul%1$s76 05:04%1$s+0000%1$s", cfws), dst2);
10939 test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s76%1$s05:04%1$s+0000%1$s", cfws), dst2);
10940 test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s76%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10941
10942 test(format("%1$s21%1$sDec%1$s012%1$s13:14:15%1$s+0000%1$s", cfws), std3);
10943 test(format("%1$s21%1$sDec%1$s012%1$s13:14%1$s+0000%1$s", cfws), std4);
10944 test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s012%1$s13:14%1$s+0000%1$s", cfws), std4);
10945 test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s012%1$s13:14:15%1$s+0000%1$s", cfws), std3);
10946
10947 test(format("%1$s04%1$sJul%1$s076%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10948 test(format("%1$s04%1$sJul%1$s076%1$s05:04%1$s+0000%1$s", cfws), dst2);
10949 test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s076%1$s05:04%1$s+0000%1$s", cfws), dst2);
10950 test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s076%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10951
10952 test(format("%1$s4%1$sJul%1$s076%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10953 test(format("%1$s4%1$sJul%1$s076%1$s05:04%1$s+0000%1$s", cfws), dst2);
10954 test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s076%1$s05:04%1$s+0000%1$s", cfws), dst2);
10955 test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s076%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10956
10957 test(format("%1$s1%1$sJan%1$s10000%1$s00:00:00%1$s+0000%1$s", cfws), tooLate1);
10958 test(format("%1$s31%1$sDec%1$s12007%1$s12:22:19%1$s+0000%1$s", cfws), tooLate2);
10959 test(format("%1$sSat%1$s,%1$s1%1$sJan%1$s10000%1$s00:00:00%1$s+0000%1$s", cfws), tooLate1);
10960 test(format("%1$sSun%1$s,%1$s31%1$sDec%1$s12007%1$s12:22:19%1$s+0000%1$s", cfws), tooLate2);
10961 }
10962 }
10963
10964 // test years of 1, 2, and 3 digits.
10965 {
10966 auto st1 = SysTime(Date(2000, 1, 1), UTC());
10967 auto st2 = SysTime(Date(2000, 1, 1), new immutable SimpleTimeZone(dur!"hours"(-12)));
10968 foreach (i; 0 .. 50)
10969 {
10970 test(format("1 Jan %02d 00:00 GMT", i), st1);
10971 test(format("1 Jan %02d 00:00 -1200", i), st2);
10972 st1.add!"years"(1);
10973 st2.add!"years"(1);
10974 }
10975 }
10976
10977 {
10978 auto st1 = SysTime(Date(1950, 1, 1), UTC());
10979 auto st2 = SysTime(Date(1950, 1, 1), new immutable SimpleTimeZone(dur!"hours"(-12)));
10980 foreach (i; 50 .. 100)
10981 {
10982 test(format("1 Jan %02d 00:00 GMT", i), st1);
10983 test(format("1 Jan %02d 00:00 -1200", i), st2);
10984 st1.add!"years"(1);
10985 st2.add!"years"(1);
10986 }
10987 }
10988
10989 {
10990 auto st1 = SysTime(Date(1900, 1, 1), UTC());
10991 auto st2 = SysTime(Date(1900, 1, 1), new immutable SimpleTimeZone(dur!"hours"(-11)));
10992 foreach (i; 0 .. 1000)
10993 {
10994 test(format("1 Jan %03d 00:00 GMT", i), st1);
10995 test(format("1 Jan %03d 00:00 -1100", i), st2);
10996 st1.add!"years"(1);
10997 st2.add!"years"(1);
10998 }
10999 }
11000
11001 foreach (i; 0 .. 10)
11002 {
11003 auto str1 = cr(format("1 Jan %d 00:00 GMT", i));
11004 auto str2 = cr(format("1 Jan %d 00:00 -1200", i));
11005 assertThrown!DateTimeException(parseRFC822DateTime(str1));
11006 assertThrown!DateTimeException(parseRFC822DateTime(str1));
11007 }
11008
11009 // test time zones
11010 {
11011 auto dt = DateTime(1982, 5, 3, 12, 22, 4);
11012 test("Wed, 03 May 1982 12:22:04 UT", SysTime(dt, UTC()));
11013 test("Wed, 03 May 1982 12:22:04 GMT", SysTime(dt, UTC()));
11014 test("Wed, 03 May 1982 12:22:04 EST", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-5))));
11015 test("Wed, 03 May 1982 12:22:04 EDT", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-4))));
11016 test("Wed, 03 May 1982 12:22:04 CST", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-6))));
11017 test("Wed, 03 May 1982 12:22:04 CDT", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-5))));
11018 test("Wed, 03 May 1982 12:22:04 MST", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-7))));
11019 test("Wed, 03 May 1982 12:22:04 MDT", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-6))));
11020 test("Wed, 03 May 1982 12:22:04 PST", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-8))));
11021 test("Wed, 03 May 1982 12:22:04 PDT", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-7))));
11022
11023 auto badTZ = new immutable SimpleTimeZone(Duration.zero);
11024 foreach (dchar c; filter!(a => a != 'j' && a != 'J')(letters))
11025 {
11026 scope(failure) writefln("c: %s", c);
11027 test(format("Wed, 03 May 1982 12:22:04 %s", c), SysTime(dt, badTZ));
11028 test(format("Wed, 03 May 1982 12:22:04%s", c), SysTime(dt, badTZ));
11029 }
11030
11031 foreach (dchar c; ['j', 'J'])
11032 {
11033 scope(failure) writefln("c: %s", c);
11034 assertThrown!DateTimeException(parseRFC822DateTime(cr(format("Wed, 03 May 1982 12:22:04 %s", c))));
11035 assertThrown!DateTimeException(parseRFC822DateTime(cr(format("Wed, 03 May 1982 12:22:04%s", c))));
11036 }
11037
11038 foreach (string s; ["AAA", "GQW", "DDT", "PDA", "GT", "GM"])
11039 {
11040 scope(failure) writefln("s: %s", s);
11041 test(format("Wed, 03 May 1982 12:22:04 %s", s), SysTime(dt, badTZ));
11042 }
11043
11044 // test trailing stuff that gets ignored
11045 {
11046 foreach (c; chain(iota(0, 33), ['('], iota(127, ubyte.max + 1)))
11047 {
11048 scope(failure) writefln("c: %d", c);
11049 test(format("21Dec1213:14:15+0000%c", cast(char) c), std1);
11050 test(format("21Dec1213:14:15+0000%c ", cast(char) c), std1);
11051 test(format("21Dec1213:14:15+0000%chello", cast(char) c), std1);
11052 }
11053 }
11054
11055 // test trailing stuff that doesn't get ignored
11056 {
11057 foreach (c; chain(iota(33, '('), iota('(' + 1, 127)))
11058 {
11059 scope(failure) writefln("c: %d", c);
11060 assertThrown!DateTimeException(
11061 parseRFC822DateTime(cr(format("21Dec1213:14:15+0000%c", cast(char) c))));
11062 assertThrown!DateTimeException(
11063 parseRFC822DateTime(cr(format("21Dec1213:14:15+0000%c ", cast(char) c))));
11064 assertThrown!DateTimeException(
11065 parseRFC822DateTime(cr(format("21Dec1213:14:15+0000%chello", cast(char) c))));
11066 }
11067 }
11068 }
11069
11070 // test that the checks for minimum length work correctly and avoid
11071 // any RangeErrors.
11072 test("7Dec1200:00A", SysTime(DateTime(2012, 12, 7, 0, 0, 0),
11073 new immutable SimpleTimeZone(Duration.zero)));
11074 test("Fri,7Dec1200:00A", SysTime(DateTime(2012, 12, 7, 0, 0, 0),
11075 new immutable SimpleTimeZone(Duration.zero)));
11076 test("7Dec1200:00:00A", SysTime(DateTime(2012, 12, 7, 0, 0, 0),
11077 new immutable SimpleTimeZone(Duration.zero)));
11078 test("Fri,7Dec1200:00:00A", SysTime(DateTime(2012, 12, 7, 0, 0, 0),
11079 new immutable SimpleTimeZone(Duration.zero)));
11080
11081 auto tooShortMsg = collectExceptionMsg!DateTimeException(parseRFC822DateTime(""));
11082 foreach (str; ["Fri,7Dec1200:00:00", "7Dec1200:00:00"])
11083 {
11084 foreach (i; 0 .. str.length)
11085 {
11086 auto value = str[0 .. $ - i];
11087 scope(failure) writeln(value);
11088 assert(collectExceptionMsg!DateTimeException(parseRFC822DateTime(value)) == tooShortMsg);
11089 }
11090 }
11091 }();}
11092 }
11093
11094
11095 private:
11096
11097 /+
11098 Returns the given hnsecs as an ISO string of fractional seconds.
11099 +/
11100 string fracSecsToISOString(int hnsecs, int prec = -1) @safe pure nothrow
11101 {
11102 import std.array : appender;
11103 auto w = appender!string();
11104 try
11105 fracSecsToISOString(w, hnsecs, prec);
11106 catch (Exception e)
11107 assert(0, "fracSecsToISOString() threw.");
11108 return w.data;
11109 }
11110
11111 void fracSecsToISOString(W)(ref W writer, int hnsecs, int prec = -1)
11112 {
11113 import std.conv : toChars;
11114 import std.range : padLeft;
11115
11116 assert(hnsecs >= 0);
11117
11118 if (prec == 0)
11119 return;
11120
11121 if (hnsecs == 0)
11122 return;
11123
11124 put(writer, '.');
11125 auto chars = hnsecs.toChars.padLeft('0', 7);
11126
11127 if (prec == -1)
11128 {
11129 while (chars.back == '0')
11130 chars.popBack();
11131 put(writer, chars);
11132 }
11133 else
11134 put(writer, chars[0 .. prec]);
11135 }
11136
11137 @safe unittest
11138 {
11139 assert(fracSecsToISOString(0) == "");
11140 assert(fracSecsToISOString(1) == ".0000001");
11141 assert(fracSecsToISOString(10) == ".000001");
11142 assert(fracSecsToISOString(100) == ".00001");
11143 assert(fracSecsToISOString(1000) == ".0001");
11144 assert(fracSecsToISOString(10_000) == ".001");
11145 assert(fracSecsToISOString(100_000) == ".01");
11146 assert(fracSecsToISOString(1_000_000) == ".1");
11147 assert(fracSecsToISOString(1_000_001) == ".1000001");
11148 assert(fracSecsToISOString(1_001_001) == ".1001001");
11149 assert(fracSecsToISOString(1_071_601) == ".1071601");
11150 assert(fracSecsToISOString(1_271_641) == ".1271641");
11151 assert(fracSecsToISOString(9_999_999) == ".9999999");
11152 assert(fracSecsToISOString(9_999_990) == ".999999");
11153 assert(fracSecsToISOString(9_999_900) == ".99999");
11154 assert(fracSecsToISOString(9_999_000) == ".9999");
11155 assert(fracSecsToISOString(9_990_000) == ".999");
11156 assert(fracSecsToISOString(9_900_000) == ".99");
11157 assert(fracSecsToISOString(9_000_000) == ".9");
11158 assert(fracSecsToISOString(999) == ".0000999");
11159 assert(fracSecsToISOString(9990) == ".000999");
11160 assert(fracSecsToISOString(99_900) == ".00999");
11161 assert(fracSecsToISOString(999_000) == ".0999");
11162 }
11163
11164
11165 /+
11166 Returns a Duration corresponding to to the given ISO string of
11167 fractional seconds.
11168 +/
11169 static Duration fracSecsFromISOString(S)(scope const S isoString) @safe pure
11170 if (isSomeString!S)
11171 {
11172 import std.algorithm.searching : all;
11173 import std.ascii : isDigit;
11174 import std.conv : to;
11175 import std.format : format;
11176 import std.string : representation;
11177
11178 if (isoString.empty)
11179 return Duration.zero;
11180
11181 auto str = isoString.representation;
11182
11183 enforce!DateTimeException(str[0] == '.', format("Invalid format for fracSecsFromISOString: %s", isoString));
11184 str.popFront();
11185
11186 enforce!DateTimeException(!str.empty && all!isDigit(str),
11187 format("Invalid format for fracSecsFromISOString: %s", isoString));
11188
11189 dchar[7] fullISOString = void;
11190 foreach (i, ref dchar c; fullISOString)
11191 {
11192 if (i < str.length)
11193 c = str[i];
11194 else
11195 c = '0';
11196 }
11197
11198 return hnsecs(to!int(fullISOString[]));
11199 }
11200
11201 @safe unittest
11202 {
11203 import core.time;
11204 static void testFSInvalid(string isoString)
11205 {
11206 fracSecsFromISOString(isoString);
11207 }
11208
11209 assertThrown!DateTimeException(testFSInvalid("."));
11210 assertThrown!DateTimeException(testFSInvalid("0."));
11211 assertThrown!DateTimeException(testFSInvalid("0"));
11212 assertThrown!DateTimeException(testFSInvalid("0000000"));
11213 assertThrown!DateTimeException(testFSInvalid("T"));
11214 assertThrown!DateTimeException(testFSInvalid("T."));
11215 assertThrown!DateTimeException(testFSInvalid(".T"));
11216 assertThrown!DateTimeException(testFSInvalid(".00000Q0"));
11217 assertThrown!DateTimeException(testFSInvalid(".000000Q"));
11218 assertThrown!DateTimeException(testFSInvalid(".0000000Q"));
11219 assertThrown!DateTimeException(testFSInvalid(".0000000000Q"));
11220
11221 assert(fracSecsFromISOString("") == Duration.zero);
11222 assert(fracSecsFromISOString(".0000001") == hnsecs(1));
11223 assert(fracSecsFromISOString(".000001") == hnsecs(10));
11224 assert(fracSecsFromISOString(".00001") == hnsecs(100));
11225 assert(fracSecsFromISOString(".0001") == hnsecs(1000));
11226 assert(fracSecsFromISOString(".001") == hnsecs(10_000));
11227 assert(fracSecsFromISOString(".01") == hnsecs(100_000));
11228 assert(fracSecsFromISOString(".1") == hnsecs(1_000_000));
11229 assert(fracSecsFromISOString(".1000001") == hnsecs(1_000_001));
11230 assert(fracSecsFromISOString(".1001001") == hnsecs(1_001_001));
11231 assert(fracSecsFromISOString(".1071601") == hnsecs(1_071_601));
11232 assert(fracSecsFromISOString(".1271641") == hnsecs(1_271_641));
11233 assert(fracSecsFromISOString(".9999999") == hnsecs(9_999_999));
11234 assert(fracSecsFromISOString(".9999990") == hnsecs(9_999_990));
11235 assert(fracSecsFromISOString(".999999") == hnsecs(9_999_990));
11236 assert(fracSecsFromISOString(".9999900") == hnsecs(9_999_900));
11237 assert(fracSecsFromISOString(".99999") == hnsecs(9_999_900));
11238 assert(fracSecsFromISOString(".9999000") == hnsecs(9_999_000));
11239 assert(fracSecsFromISOString(".9999") == hnsecs(9_999_000));
11240 assert(fracSecsFromISOString(".9990000") == hnsecs(9_990_000));
11241 assert(fracSecsFromISOString(".999") == hnsecs(9_990_000));
11242 assert(fracSecsFromISOString(".9900000") == hnsecs(9_900_000));
11243 assert(fracSecsFromISOString(".9900") == hnsecs(9_900_000));
11244 assert(fracSecsFromISOString(".99") == hnsecs(9_900_000));
11245 assert(fracSecsFromISOString(".9000000") == hnsecs(9_000_000));
11246 assert(fracSecsFromISOString(".9") == hnsecs(9_000_000));
11247 assert(fracSecsFromISOString(".0000999") == hnsecs(999));
11248 assert(fracSecsFromISOString(".0009990") == hnsecs(9990));
11249 assert(fracSecsFromISOString(".000999") == hnsecs(9990));
11250 assert(fracSecsFromISOString(".0099900") == hnsecs(99_900));
11251 assert(fracSecsFromISOString(".00999") == hnsecs(99_900));
11252 assert(fracSecsFromISOString(".0999000") == hnsecs(999_000));
11253 assert(fracSecsFromISOString(".0999") == hnsecs(999_000));
11254 assert(fracSecsFromISOString(".00000000") == Duration.zero);
11255 assert(fracSecsFromISOString(".00000001") == Duration.zero);
11256 assert(fracSecsFromISOString(".00000009") == Duration.zero);
11257 assert(fracSecsFromISOString(".1234567890") == hnsecs(1_234_567));
11258 assert(fracSecsFromISOString(".12345678901234567890") == hnsecs(1_234_567));
11259 }
11260
11261
11262 /+
11263 This function is used to split out the units without getting the remaining
11264 hnsecs.
11265
11266 Params:
11267 units = The units to split out.
11268 hnsecs = The current total hnsecs.
11269
11270 Returns:
11271 The split out value.
11272 +/
11273 long getUnitsFromHNSecs(string units)(long hnsecs) @safe pure nothrow
11274 if (validTimeUnits(units) &&
11275 CmpTimeUnits!(units, "months") < 0)
11276 {
11277 return convert!("hnsecs", units)(hnsecs);
11278 }
11279
11280 @safe unittest
11281 {
11282 auto hnsecs = 2595000000007L;
11283 immutable days = getUnitsFromHNSecs!"days"(hnsecs);
11284 assert(days == 3);
11285 assert(hnsecs == 2595000000007L);
11286 }
11287
11288
11289 /+
11290 This function is used to split out the units without getting the units but
11291 just the remaining hnsecs.
11292
11293 Params:
11294 units = The units to split out.
11295 hnsecs = The current total hnsecs.
11296
11297 Returns:
11298 The remaining hnsecs.
11299 +/
11300 long removeUnitsFromHNSecs(string units)(long hnsecs) @safe pure nothrow
11301 if (validTimeUnits(units) &&
11302 CmpTimeUnits!(units, "months") < 0)
11303 {
11304 immutable value = convert!("hnsecs", units)(hnsecs);
11305 return hnsecs - convert!(units, "hnsecs")(value);
11306 }
11307
11308 @safe unittest
11309 {
11310 auto hnsecs = 2595000000007L;
11311 auto returned = removeUnitsFromHNSecs!"days"(hnsecs);
11312 assert(returned == 3000000007);
11313 assert(hnsecs == 2595000000007L);
11314 }
11315
11316
11317 /+
11318 Strips what RFC 5322, section 3.2.2 refers to as CFWS from the left-hand
11319 side of the given range (it strips comments delimited by $(D '(') and
11320 `'`') as well as folding whitespace).
11321
11322 It is assumed that the given range contains the value of a header field and
11323 no terminating CRLF for the line (though the CRLF for folding whitespace is
11324 of course expected and stripped) and thus that the only case of CR or LF is
11325 in folding whitespace.
11326
11327 If a comment does not terminate correctly (e.g. mismatched parens) or if the
11328 the FWS is malformed, then the range will be empty when stripCWFS is done.
11329 However, only minimal validation of the content is done (e.g. quoted pairs
11330 within a comment aren't validated beyond \$LPAREN or \$RPAREN, because
11331 they're inside a comment, and thus their value doesn't matter anyway). It's
11332 only when the content does not conform to the grammar rules for FWS and thus
11333 literally cannot be parsed that content is considered invalid, and an empty
11334 range is returned.
11335
11336 Note that _stripCFWS is eager, not lazy. It does not create a new range.
11337 Rather, it pops off the CFWS from the range and returns it.
11338 +/
11339 R _stripCFWS(R)(R range)
11340 if (isRandomAccessRange!R && hasSlicing!R && hasLength!R &&
11341 (is(immutable ElementType!R == immutable char) || is(immutable ElementType!R == immutable ubyte)))
11342 {
11343 immutable e = range.length;
11344 outer: for (size_t i = 0; i < e; )
11345 {
11346 switch (range[i])
11347 {
11348 case ' ': case '\t':
11349 {
11350 ++i;
11351 break;
11352 }
11353 case '\r':
11354 {
11355 if (i + 2 < e && range[i + 1] == '\n' && (range[i + 2] == ' ' || range[i + 2] == '\t'))
11356 {
11357 i += 3;
11358 break;
11359 }
11360 break outer;
11361 }
11362 case '\n':
11363 {
11364 if (i + 1 < e && (range[i + 1] == ' ' || range[i + 1] == '\t'))
11365 {
11366 i += 2;
11367 break;
11368 }
11369 break outer;
11370 }
11371 case '(':
11372 {
11373 ++i;
11374 size_t commentLevel = 1;
11375 while (i < e)
11376 {
11377 if (range[i] == '(')
11378 ++commentLevel;
11379 else if (range[i] == ')')
11380 {
11381 ++i;
11382 if (--commentLevel == 0)
11383 continue outer;
11384 continue;
11385 }
11386 else if (range[i] == '\\')
11387 {
11388 if (++i == e)
11389 break outer;
11390 }
11391 ++i;
11392 }
11393 break outer;
11394 }
11395 default: return range[i .. e];
11396 }
11397 }
11398 return range[e .. e];
11399 }
11400
11401 @system unittest
11402 {
11403 import std.algorithm.comparison : equal;
11404 import std.algorithm.iteration : map;
11405 import std.meta : AliasSeq;
11406 import std.stdio : writeln;
11407 import std.string : representation;
11408
11409 static foreach (cr; AliasSeq!(function(string a){return cast(ubyte[]) a;},
11410 function(string a){return map!(b => cast(char) b)(a.representation);}))
11411 {
11412 scope(failure) writeln(typeof(cr).stringof);
11413
11414 assert(_stripCFWS(cr("")).empty);
11415 assert(_stripCFWS(cr("\r")).empty);
11416 assert(_stripCFWS(cr("\r\n")).empty);
11417 assert(_stripCFWS(cr("\r\n ")).empty);
11418 assert(_stripCFWS(cr(" \t\r\n")).empty);
11419 assert(equal(_stripCFWS(cr(" \t\r\n hello")), cr("hello")));
11420 assert(_stripCFWS(cr(" \t\r\nhello")).empty);
11421 assert(_stripCFWS(cr(" \t\r\n\v")).empty);
11422 assert(equal(_stripCFWS(cr("\v \t\r\n\v")), cr("\v \t\r\n\v")));
11423 assert(_stripCFWS(cr("()")).empty);
11424 assert(_stripCFWS(cr("(hello world)")).empty);
11425 assert(_stripCFWS(cr("(hello world)(hello world)")).empty);
11426 assert(_stripCFWS(cr("(hello world\r\n foo\r where's\nwaldo)")).empty);
11427 assert(_stripCFWS(cr(" \t (hello \tworld\r\n foo\r where's\nwaldo)\t\t ")).empty);
11428 assert(_stripCFWS(cr(" ")).empty);
11429 assert(_stripCFWS(cr("\t\t\t")).empty);
11430 assert(_stripCFWS(cr("\t \r\n\r \n")).empty);
11431 assert(_stripCFWS(cr("(hello world) (can't find waldo) (he's lost)")).empty);
11432 assert(_stripCFWS(cr("(hello\\) world) (can't \\(find waldo) (he's \\(\\)lost)")).empty);
11433 assert(_stripCFWS(cr("(((((")).empty);
11434 assert(_stripCFWS(cr("(((()))")).empty);
11435 assert(_stripCFWS(cr("(((())))")).empty);
11436 assert(equal(_stripCFWS(cr("(((()))))")), cr(")")));
11437 assert(equal(_stripCFWS(cr(")))))")), cr(")))))")));
11438 assert(equal(_stripCFWS(cr("()))))")), cr("))))")));
11439 assert(equal(_stripCFWS(cr(" hello hello ")), cr("hello hello ")));
11440 assert(equal(_stripCFWS(cr("\thello (world)")), cr("hello (world)")));
11441 assert(equal(_stripCFWS(cr(" \r\n \\((\\)) foo")), cr("\\((\\)) foo")));
11442 assert(equal(_stripCFWS(cr(" \r\n (\\((\\))) foo")), cr("foo")));
11443 assert(equal(_stripCFWS(cr(" \r\n (\\(())) foo")), cr(") foo")));
11444 assert(_stripCFWS(cr(" \r\n (((\\))) foo")).empty);
11445
11446 assert(_stripCFWS(cr("(hello)(hello)")).empty);
11447 assert(_stripCFWS(cr(" \r\n (hello)\r\n (hello)")).empty);
11448 assert(_stripCFWS(cr(" \r\n (hello) \r\n (hello) \r\n ")).empty);
11449 assert(_stripCFWS(cr("\t\t\t\t(hello)\t\t\t\t(hello)\t\t\t\t")).empty);
11450 assert(equal(_stripCFWS(cr(" \r\n (hello)\r\n (hello) \r\n hello")), cr("hello")));
11451 assert(equal(_stripCFWS(cr(" \r\n (hello) \r\n (hello) \r\n hello")), cr("hello")));
11452 assert(equal(_stripCFWS(cr("\t\r\n\t(hello)\r\n\t(hello)\t\r\n hello")), cr("hello")));
11453 assert(equal(_stripCFWS(cr("\t\r\n\t(hello)\t\r\n\t(hello)\t\r\n hello")), cr("hello")));
11454 assert(equal(_stripCFWS(cr(" \r\n (hello) \r\n \r\n (hello) \r\n hello")), cr("hello")));
11455 assert(equal(_stripCFWS(cr(" \r\n (hello) \r\n (hello) \r\n \r\n hello")), cr("hello")));
11456 assert(equal(_stripCFWS(cr(" \r\n \r\n (hello)\t\r\n (hello) \r\n hello")), cr("hello")));
11457 assert(equal(_stripCFWS(cr(" \r\n\t\r\n\t(hello)\t\r\n (hello) \r\n hello")), cr("hello")));
11458
11459 assert(equal(_stripCFWS(cr(" (\r\n ( \r\n ) \r\n ) foo")), cr("foo")));
11460 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n ) foo")), cr("foo")));
11461 assert(equal(_stripCFWS(cr(" (\t\r\n ( \r\n ) \r\n ) foo")), cr("foo")));
11462 assert(equal(_stripCFWS(cr(" (\r\n\t( \r\n ) \r\n ) foo")), cr("foo")));
11463 assert(equal(_stripCFWS(cr(" ( \r\n (\t\r\n ) \r\n ) foo")), cr("foo")));
11464 assert(equal(_stripCFWS(cr(" ( \r\n (\r\n ) \r\n ) foo")), cr("foo")));
11465 assert(equal(_stripCFWS(cr(" ( \r\n (\r\n\t) \r\n ) foo")), cr("foo")));
11466 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n) \r\n ) foo")), cr("foo")));
11467 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n )\t\r\n ) foo")), cr("foo")));
11468 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n )\r\n ) foo")), cr("foo")));
11469 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n) foo")), cr("foo")));
11470 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n\t) foo")), cr("foo")));
11471 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n ) \r\n foo")), cr("foo")));
11472 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n )\t\r\n foo")), cr("foo")));
11473 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n )\r\n foo")), cr("foo")));
11474
11475 assert(equal(_stripCFWS(cr(" ( \r\n \r\n ( \r\n \r\n ) \r\n ) foo")), cr("foo")));
11476 assert(equal(_stripCFWS(cr(" ( \r\n \r\n ( \r\n \r\n ) \r\n ) foo")), cr("foo")));
11477 assert(equal(_stripCFWS(cr(" (\t\r\n \r\n ( \r\n \r\n ) \r\n ) foo")), cr("foo")));
11478 assert(equal(_stripCFWS(cr(" (\r\n \r\n\t( \r\n \r\n ) \r\n ) foo")), cr("foo")));
11479 assert(equal(_stripCFWS(cr(" (\r\n \r\n( \r\n \r\n ) \r\n ) foo")), cr("foo")));
11480 assert(equal(_stripCFWS(cr(" (\r\n \r\n ( \r\n \r\n\t) \r\n ) foo")), cr("foo")));
11481 assert(equal(_stripCFWS(cr(" (\r\n \r\n ( \r\n \r\n )\t\r\n ) foo")), cr("foo")));
11482 assert(equal(_stripCFWS(cr(" (\r\n \r\n ( \r\n \r\n )\r\n ) foo")), cr("foo")));
11483
11484 assert(equal(_stripCFWS(cr(" ( \r\n bar \r\n ( \r\n bar \r\n ) \r\n ) foo")), cr("foo")));
11485 assert(equal(_stripCFWS(cr(" ( \r\n () \r\n ( \r\n () \r\n ) \r\n ) foo")), cr("foo")));
11486 assert(equal(_stripCFWS(cr(" ( \r\n \\\\ \r\n ( \r\n \\\\ \r\n ) \r\n ) foo")), cr("foo")));
11487
11488 assert(_stripCFWS(cr("(hello)(hello)")).empty);
11489 assert(_stripCFWS(cr(" \n (hello)\n (hello) \n ")).empty);
11490 assert(_stripCFWS(cr(" \n (hello) \n (hello) \n ")).empty);
11491 assert(equal(_stripCFWS(cr(" \n (hello)\n (hello) \n hello")), cr("hello")));
11492 assert(equal(_stripCFWS(cr(" \n (hello) \n (hello) \n hello")), cr("hello")));
11493 assert(equal(_stripCFWS(cr("\t\n\t(hello)\n\t(hello)\t\n hello")), cr("hello")));
11494 assert(equal(_stripCFWS(cr("\t\n\t(hello)\t\n\t(hello)\t\n hello")), cr("hello")));
11495 assert(equal(_stripCFWS(cr(" \n (hello) \n \n (hello) \n hello")), cr("hello")));
11496 assert(equal(_stripCFWS(cr(" \n (hello) \n (hello) \n \n hello")), cr("hello")));
11497 assert(equal(_stripCFWS(cr(" \n \n (hello)\t\n (hello) \n hello")), cr("hello")));
11498 assert(equal(_stripCFWS(cr(" \n\t\n\t(hello)\t\n (hello) \n hello")), cr("hello")));
11499 }
11500 }
11501
11502 // This is so that we don't have to worry about std.conv.to throwing. It also
11503 // doesn't have to worry about quite as many cases as std.conv.to, since it
11504 // doesn't have to worry about a sign on the value or about whether it fits.
11505 T _convDigits(T, R)(R str)
11506 if (isIntegral!T && isSigned!T) // The constraints on R were already covered by parseRFC822DateTime.
11507 {
11508 import std.ascii : isDigit;
11509
11510 assert(!str.empty);
11511 T num = 0;
11512 foreach (i; 0 .. str.length)
11513 {
11514 if (i != 0)
11515 num *= 10;
11516 if (!isDigit(str[i]))
11517 return -1;
11518 num += str[i] - '0';
11519 }
11520 return num;
11521 }
11522
11523 @safe unittest
11524 {
11525 import std.conv : to;
11526 import std.range : chain, iota;
11527 foreach (i; chain(iota(0, 101), [250, 999, 1000, 1001, 2345, 9999]))
11528 {
11529 assert(_convDigits!int(to!string(i)) == i, i.to!string);
11530 }
11531 foreach (str; ["-42", "+42", "1a", "1 ", " ", " 42 "])
11532 {
11533 assert(_convDigits!int(str) == -1, str);
11534 }
11535 }
11536
11537
11538 // NOTE: all the non-simple array literals are wrapped in functions, because
11539 // otherwise importing causes re-evaluation of the static initializers using
11540 // CTFE with unittests enabled
11541 version (StdUnittest)
11542 {
11543 private @safe:
11544 // Variables to help in testing.
11545 Duration currLocalDiffFromUTC;
11546 immutable (TimeZone)[] testTZs;
11547
11548 // All of these helper arrays are sorted in ascending order.
11549 auto testYearsBC = [-1999, -1200, -600, -4, -1, 0];
11550 auto testYearsAD = [1, 4, 1000, 1999, 2000, 2012];
11551
11552 // I'd use a Tuple, but I get forward reference errors if I try.
11553 struct MonthDay
11554 {
11555 Month month;
11556 short day;
11557
11558 this(int m, short d)
11559 {
11560 month = cast(Month) m;
11561 day = d;
11562 }
11563 }
11564
11565 MonthDay[] testMonthDays()
11566 {
11567 static result = [MonthDay(1, 1),
11568 MonthDay(1, 2),
11569 MonthDay(3, 17),
11570 MonthDay(7, 4),
11571 MonthDay(10, 27),
11572 MonthDay(12, 30),
11573 MonthDay(12, 31)];
11574 return result;
11575 }
11576
11577 auto testDays = [1, 2, 9, 10, 16, 20, 25, 28, 29, 30, 31];
11578
11579 TimeOfDay[] testTODs()
11580 {
11581 static result = [TimeOfDay(0, 0, 0),
11582 TimeOfDay(0, 0, 1),
11583 TimeOfDay(0, 1, 0),
11584 TimeOfDay(1, 0, 0),
11585 TimeOfDay(13, 13, 13),
11586 TimeOfDay(23, 59, 59)];
11587 return result;
11588 }
11589
11590 auto testHours = [0, 1, 12, 22, 23];
11591 auto testMinSecs = [0, 1, 30, 58, 59];
11592
11593 // Throwing exceptions is incredibly expensive, so we want to use a smaller
11594 // set of values for tests using assertThrown.
11595 TimeOfDay[] testTODsThrown()
11596 {
11597 static result = [TimeOfDay(0, 0, 0),
11598 TimeOfDay(13, 13, 13),
11599 TimeOfDay(23, 59, 59)];
11600 return result;
11601 }
11602
11603 Date[] testDatesBC;
11604 Date[] testDatesAD;
11605
11606 DateTime[] testDateTimesBC;
11607 DateTime[] testDateTimesAD;
11608
11609 Duration[] testFracSecs;
11610
11611 SysTime[] testSysTimesBC;
11612 SysTime[] testSysTimesAD;
11613
11614 // I'd use a Tuple, but I get forward reference errors if I try.
11615 struct GregDay { int day; Date date; }
11616 GregDay[] testGregDaysBC()
11617 {
11618 static result = [GregDay(-1_373_427, Date(-3760, 9, 7)), // Start of the Hebrew Calendar
11619 GregDay(-735_233, Date(-2012, 1, 1)),
11620 GregDay(-735_202, Date(-2012, 2, 1)),
11621 GregDay(-735_175, Date(-2012, 2, 28)),
11622 GregDay(-735_174, Date(-2012, 2, 29)),
11623 GregDay(-735_173, Date(-2012, 3, 1)),
11624 GregDay(-734_502, Date(-2010, 1, 1)),
11625 GregDay(-734_472, Date(-2010, 1, 31)),
11626 GregDay(-734_471, Date(-2010, 2, 1)),
11627 GregDay(-734_444, Date(-2010, 2, 28)),
11628 GregDay(-734_443, Date(-2010, 3, 1)),
11629 GregDay(-734_413, Date(-2010, 3, 31)),
11630 GregDay(-734_412, Date(-2010, 4, 1)),
11631 GregDay(-734_383, Date(-2010, 4, 30)),
11632 GregDay(-734_382, Date(-2010, 5, 1)),
11633 GregDay(-734_352, Date(-2010, 5, 31)),
11634 GregDay(-734_351, Date(-2010, 6, 1)),
11635 GregDay(-734_322, Date(-2010, 6, 30)),
11636 GregDay(-734_321, Date(-2010, 7, 1)),
11637 GregDay(-734_291, Date(-2010, 7, 31)),
11638 GregDay(-734_290, Date(-2010, 8, 1)),
11639 GregDay(-734_260, Date(-2010, 8, 31)),
11640 GregDay(-734_259, Date(-2010, 9, 1)),
11641 GregDay(-734_230, Date(-2010, 9, 30)),
11642 GregDay(-734_229, Date(-2010, 10, 1)),
11643 GregDay(-734_199, Date(-2010, 10, 31)),
11644 GregDay(-734_198, Date(-2010, 11, 1)),
11645 GregDay(-734_169, Date(-2010, 11, 30)),
11646 GregDay(-734_168, Date(-2010, 12, 1)),
11647 GregDay(-734_139, Date(-2010, 12, 30)),
11648 GregDay(-734_138, Date(-2010, 12, 31)),
11649 GregDay(-731_215, Date(-2001, 1, 1)),
11650 GregDay(-730_850, Date(-2000, 1, 1)),
11651 GregDay(-730_849, Date(-2000, 1, 2)),
11652 GregDay(-730_486, Date(-2000, 12, 30)),
11653 GregDay(-730_485, Date(-2000, 12, 31)),
11654 GregDay(-730_484, Date(-1999, 1, 1)),
11655 GregDay(-694_690, Date(-1901, 1, 1)),
11656 GregDay(-694_325, Date(-1900, 1, 1)),
11657 GregDay(-585_118, Date(-1601, 1, 1)),
11658 GregDay(-584_753, Date(-1600, 1, 1)),
11659 GregDay(-584_388, Date(-1600, 12, 31)),
11660 GregDay(-584_387, Date(-1599, 1, 1)),
11661 GregDay(-365_972, Date(-1001, 1, 1)),
11662 GregDay(-365_607, Date(-1000, 1, 1)),
11663 GregDay(-183_351, Date(-501, 1, 1)),
11664 GregDay(-182_986, Date(-500, 1, 1)),
11665 GregDay(-182_621, Date(-499, 1, 1)),
11666 GregDay(-146_827, Date(-401, 1, 1)),
11667 GregDay(-146_462, Date(-400, 1, 1)),
11668 GregDay(-146_097, Date(-400, 12, 31)),
11669 GregDay(-110_302, Date(-301, 1, 1)),
11670 GregDay(-109_937, Date(-300, 1, 1)),
11671 GregDay(-73_778, Date(-201, 1, 1)),
11672 GregDay(-73_413, Date(-200, 1, 1)),
11673 GregDay(-38_715, Date(-105, 1, 1)),
11674 GregDay(-37_254, Date(-101, 1, 1)),
11675 GregDay(-36_889, Date(-100, 1, 1)),
11676 GregDay(-36_524, Date(-99, 1, 1)),
11677 GregDay(-36_160, Date(-99, 12, 31)),
11678 GregDay(-35_794, Date(-97, 1, 1)),
11679 GregDay(-18_627, Date(-50, 1, 1)),
11680 GregDay(-18_262, Date(-49, 1, 1)),
11681 GregDay(-3652, Date(-9, 1, 1)),
11682 GregDay(-2191, Date(-5, 1, 1)),
11683 GregDay(-1827, Date(-5, 12, 31)),
11684 GregDay(-1826, Date(-4, 1, 1)),
11685 GregDay(-1825, Date(-4, 1, 2)),
11686 GregDay(-1462, Date(-4, 12, 30)),
11687 GregDay(-1461, Date(-4, 12, 31)),
11688 GregDay(-1460, Date(-3, 1, 1)),
11689 GregDay(-1096, Date(-3, 12, 31)),
11690 GregDay(-1095, Date(-2, 1, 1)),
11691 GregDay(-731, Date(-2, 12, 31)),
11692 GregDay(-730, Date(-1, 1, 1)),
11693 GregDay(-367, Date(-1, 12, 30)),
11694 GregDay(-366, Date(-1, 12, 31)),
11695 GregDay(-365, Date(0, 1, 1)),
11696 GregDay(-31, Date(0, 11, 30)),
11697 GregDay(-30, Date(0, 12, 1)),
11698 GregDay(-1, Date(0, 12, 30)),
11699 GregDay(0, Date(0, 12, 31))];
11700 return result;
11701 }
11702
11703 GregDay[] testGregDaysAD()
11704 {
11705 static result = [GregDay(1, Date(1, 1, 1)),
11706 GregDay(2, Date(1, 1, 2)),
11707 GregDay(32, Date(1, 2, 1)),
11708 GregDay(365, Date(1, 12, 31)),
11709 GregDay(366, Date(2, 1, 1)),
11710 GregDay(731, Date(3, 1, 1)),
11711 GregDay(1096, Date(4, 1, 1)),
11712 GregDay(1097, Date(4, 1, 2)),
11713 GregDay(1460, Date(4, 12, 30)),
11714 GregDay(1461, Date(4, 12, 31)),
11715 GregDay(1462, Date(5, 1, 1)),
11716 GregDay(17_898, Date(50, 1, 1)),
11717 GregDay(35_065, Date(97, 1, 1)),
11718 GregDay(36_160, Date(100, 1, 1)),
11719 GregDay(36_525, Date(101, 1, 1)),
11720 GregDay(37_986, Date(105, 1, 1)),
11721 GregDay(72_684, Date(200, 1, 1)),
11722 GregDay(73_049, Date(201, 1, 1)),
11723 GregDay(109_208, Date(300, 1, 1)),
11724 GregDay(109_573, Date(301, 1, 1)),
11725 GregDay(145_732, Date(400, 1, 1)),
11726 GregDay(146_098, Date(401, 1, 1)),
11727 GregDay(182_257, Date(500, 1, 1)),
11728 GregDay(182_622, Date(501, 1, 1)),
11729 GregDay(364_878, Date(1000, 1, 1)),
11730 GregDay(365_243, Date(1001, 1, 1)),
11731 GregDay(584_023, Date(1600, 1, 1)),
11732 GregDay(584_389, Date(1601, 1, 1)),
11733 GregDay(693_596, Date(1900, 1, 1)),
11734 GregDay(693_961, Date(1901, 1, 1)),
11735 GregDay(729_755, Date(1999, 1, 1)),
11736 GregDay(730_120, Date(2000, 1, 1)),
11737 GregDay(730_121, Date(2000, 1, 2)),
11738 GregDay(730_484, Date(2000, 12, 30)),
11739 GregDay(730_485, Date(2000, 12, 31)),
11740 GregDay(730_486, Date(2001, 1, 1)),
11741 GregDay(733_773, Date(2010, 1, 1)),
11742 GregDay(733_774, Date(2010, 1, 2)),
11743 GregDay(733_803, Date(2010, 1, 31)),
11744 GregDay(733_804, Date(2010, 2, 1)),
11745 GregDay(733_831, Date(2010, 2, 28)),
11746 GregDay(733_832, Date(2010, 3, 1)),
11747 GregDay(733_862, Date(2010, 3, 31)),
11748 GregDay(733_863, Date(2010, 4, 1)),
11749 GregDay(733_892, Date(2010, 4, 30)),
11750 GregDay(733_893, Date(2010, 5, 1)),
11751 GregDay(733_923, Date(2010, 5, 31)),
11752 GregDay(733_924, Date(2010, 6, 1)),
11753 GregDay(733_953, Date(2010, 6, 30)),
11754 GregDay(733_954, Date(2010, 7, 1)),
11755 GregDay(733_984, Date(2010, 7, 31)),
11756 GregDay(733_985, Date(2010, 8, 1)),
11757 GregDay(734_015, Date(2010, 8, 31)),
11758 GregDay(734_016, Date(2010, 9, 1)),
11759 GregDay(734_045, Date(2010, 9, 30)),
11760 GregDay(734_046, Date(2010, 10, 1)),
11761 GregDay(734_076, Date(2010, 10, 31)),
11762 GregDay(734_077, Date(2010, 11, 1)),
11763 GregDay(734_106, Date(2010, 11, 30)),
11764 GregDay(734_107, Date(2010, 12, 1)),
11765 GregDay(734_136, Date(2010, 12, 30)),
11766 GregDay(734_137, Date(2010, 12, 31)),
11767 GregDay(734_503, Date(2012, 1, 1)),
11768 GregDay(734_534, Date(2012, 2, 1)),
11769 GregDay(734_561, Date(2012, 2, 28)),
11770 GregDay(734_562, Date(2012, 2, 29)),
11771 GregDay(734_563, Date(2012, 3, 1)),
11772 GregDay(734_858, Date(2012, 12, 21))];
11773 return result;
11774 }
11775
11776 // I'd use a Tuple, but I get forward reference errors if I try.
11777 struct DayOfYear { int day; MonthDay md; }
11778 DayOfYear[] testDaysOfYear()
11779 {
11780 static result = [DayOfYear(1, MonthDay(1, 1)),
11781 DayOfYear(2, MonthDay(1, 2)),
11782 DayOfYear(3, MonthDay(1, 3)),
11783 DayOfYear(31, MonthDay(1, 31)),
11784 DayOfYear(32, MonthDay(2, 1)),
11785 DayOfYear(59, MonthDay(2, 28)),
11786 DayOfYear(60, MonthDay(3, 1)),
11787 DayOfYear(90, MonthDay(3, 31)),
11788 DayOfYear(91, MonthDay(4, 1)),
11789 DayOfYear(120, MonthDay(4, 30)),
11790 DayOfYear(121, MonthDay(5, 1)),
11791 DayOfYear(151, MonthDay(5, 31)),
11792 DayOfYear(152, MonthDay(6, 1)),
11793 DayOfYear(181, MonthDay(6, 30)),
11794 DayOfYear(182, MonthDay(7, 1)),
11795 DayOfYear(212, MonthDay(7, 31)),
11796 DayOfYear(213, MonthDay(8, 1)),
11797 DayOfYear(243, MonthDay(8, 31)),
11798 DayOfYear(244, MonthDay(9, 1)),
11799 DayOfYear(273, MonthDay(9, 30)),
11800 DayOfYear(274, MonthDay(10, 1)),
11801 DayOfYear(304, MonthDay(10, 31)),
11802 DayOfYear(305, MonthDay(11, 1)),
11803 DayOfYear(334, MonthDay(11, 30)),
11804 DayOfYear(335, MonthDay(12, 1)),
11805 DayOfYear(363, MonthDay(12, 29)),
11806 DayOfYear(364, MonthDay(12, 30)),
11807 DayOfYear(365, MonthDay(12, 31))];
11808 return result;
11809 }
11810
11811 DayOfYear[] testDaysOfLeapYear()
11812 {
11813 static result = [DayOfYear(1, MonthDay(1, 1)),
11814 DayOfYear(2, MonthDay(1, 2)),
11815 DayOfYear(3, MonthDay(1, 3)),
11816 DayOfYear(31, MonthDay(1, 31)),
11817 DayOfYear(32, MonthDay(2, 1)),
11818 DayOfYear(59, MonthDay(2, 28)),
11819 DayOfYear(60, MonthDay(2, 29)),
11820 DayOfYear(61, MonthDay(3, 1)),
11821 DayOfYear(91, MonthDay(3, 31)),
11822 DayOfYear(92, MonthDay(4, 1)),
11823 DayOfYear(121, MonthDay(4, 30)),
11824 DayOfYear(122, MonthDay(5, 1)),
11825 DayOfYear(152, MonthDay(5, 31)),
11826 DayOfYear(153, MonthDay(6, 1)),
11827 DayOfYear(182, MonthDay(6, 30)),
11828 DayOfYear(183, MonthDay(7, 1)),
11829 DayOfYear(213, MonthDay(7, 31)),
11830 DayOfYear(214, MonthDay(8, 1)),
11831 DayOfYear(244, MonthDay(8, 31)),
11832 DayOfYear(245, MonthDay(9, 1)),
11833 DayOfYear(274, MonthDay(9, 30)),
11834 DayOfYear(275, MonthDay(10, 1)),
11835 DayOfYear(305, MonthDay(10, 31)),
11836 DayOfYear(306, MonthDay(11, 1)),
11837 DayOfYear(335, MonthDay(11, 30)),
11838 DayOfYear(336, MonthDay(12, 1)),
11839 DayOfYear(364, MonthDay(12, 29)),
11840 DayOfYear(365, MonthDay(12, 30)),
11841 DayOfYear(366, MonthDay(12, 31))];
11842 return result;
11843 }
11844
11845 void initializeTests()
11846 {
11847 import std.algorithm.sorting : sort;
11848 import std.typecons : Rebindable;
11849 immutable lt = LocalTime().utcToTZ(0);
11850 currLocalDiffFromUTC = dur!"hnsecs"(lt);
11851
11852 version (Posix)
11853 {
11854 import std.datetime.timezone : PosixTimeZone;
11855 immutable otherTZ = lt < 0 ? PosixTimeZone.getTimeZone("Australia/Sydney")
11856 : PosixTimeZone.getTimeZone("America/Denver");
11857 }
11858 else version (Windows)
11859 {
11860 import std.datetime.timezone : WindowsTimeZone;
11861 immutable otherTZ = lt < 0 ? WindowsTimeZone.getTimeZone("AUS Eastern Standard Time")
11862 : WindowsTimeZone.getTimeZone("Mountain Standard Time");
11863 }
11864
11865 immutable ot = otherTZ.utcToTZ(0);
11866
11867 auto diffs = [0L, lt, ot];
11868 auto diffAA = [0L : Rebindable!(immutable TimeZone)(UTC())];
11869 diffAA[lt] = Rebindable!(immutable TimeZone)(LocalTime());
11870 diffAA[ot] = Rebindable!(immutable TimeZone)(otherTZ);
11871
11872 sort(diffs);
11873 testTZs = [diffAA[diffs[0]], diffAA[diffs[1]], diffAA[diffs[2]]];
11874
11875 testFracSecs = [Duration.zero, hnsecs(1), hnsecs(5007), hnsecs(9_999_999)];
11876
11877 foreach (year; testYearsBC)
11878 {
11879 foreach (md; testMonthDays)
11880 testDatesBC ~= Date(year, md.month, md.day);
11881 }
11882
11883 foreach (year; testYearsAD)
11884 {
11885 foreach (md; testMonthDays)
11886 testDatesAD ~= Date(year, md.month, md.day);
11887 }
11888
11889 foreach (dt; testDatesBC)
11890 {
11891 foreach (tod; testTODs)
11892 testDateTimesBC ~= DateTime(dt, tod);
11893 }
11894
11895 foreach (dt; testDatesAD)
11896 {
11897 foreach (tod; testTODs)
11898 testDateTimesAD ~= DateTime(dt, tod);
11899 }
11900
11901 foreach (dt; testDateTimesBC)
11902 {
11903 foreach (tz; testTZs)
11904 {
11905 foreach (fs; testFracSecs)
11906 testSysTimesBC ~= SysTime(dt, fs, tz);
11907 }
11908 }
11909
11910 foreach (dt; testDateTimesAD)
11911 {
11912 foreach (tz; testTZs)
11913 {
11914 foreach (fs; testFracSecs)
11915 testSysTimesAD ~= SysTime(dt, fs, tz);
11916 }
11917 }
11918 }
11919 }