1 // Written in the D programming language
2
3 /++
4
5 $(SCRIPT inhibitQuickIndex = 1;)
6 $(DIVC quickindex,
7 $(BOOKTABLE,
8 $(TR $(TH Category) $(TH Functions))
9 $(TR $(TD Types) $(TD
10 $(LREF Clock)
11 $(LREF SysTime)
12 $(LREF DosFileTime)
13 ))
14 $(TR $(TD Conversion) $(TD
15 $(LREF parseRFC822DateTime)
16 $(LREF DosFileTimeToSysTime)
17 $(LREF FILETIMEToStdTime)
18 $(LREF FILETIMEToSysTime)
19 $(LREF stdTimeToFILETIME)
20 $(LREF stdTimeToUnixTime)
21 $(LREF SYSTEMTIMEToSysTime)
22 $(LREF SysTimeToDosFileTime)
23 $(LREF SysTimeToFILETIME)
24 $(LREF SysTimeToSYSTEMTIME)
25 $(LREF unixTimeToStdTime)
26 ))
27 ))
28
29 License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
30 Authors: $(HTTP jmdavisprog.com, Jonathan M Davis)
31 Source: $(PHOBOSSRC std/datetime/systime.d)
32 +/
33 module std.datetime.systime;
34
35 version (OSX)
36 version = Darwin;
37 else version (iOS)
38 version = Darwin;
39 else version (TVOS)
40 version = Darwin;
41 else version (WatchOS)
42 version = Darwin;
43
44 /// Get the current time as a $(LREF SysTime)
45 @safe unittest
46 {
47 import std.datetime.timezone : LocalTime;
48 SysTime today = Clock.currTime();
49 assert(today.timezone is LocalTime());
50 }
51
52 /// Construct a $(LREF SysTime) from a ISO time string
53 @safe unittest
54 {
55 import std.datetime.date : DateTime;
56 import std.datetime.timezone : UTC;
57
58 auto st = SysTime.fromISOExtString("2018-01-01T10:30:00Z");
59 assert(st == SysTime(DateTime(2018, 1, 1, 10, 30, 0), UTC()));
60 }
61
62 /// Make a specific point in time in the New York timezone
63 @safe unittest
64 {
65 import core.time : hours;
66 import std.datetime.date : DateTime;
67 import std.datetime.timezone : SimpleTimeZone;
68
69 auto ny = SysTime(
70 DateTime(2018, 1, 1, 10, 30, 0),
71 new immutable SimpleTimeZone(-5.hours, "America/New_York")
72 );
73
74 // ISO standard time strings
75 assert(ny.toISOString() == "20180101T103000-05:00");
76 assert(ny.toISOExtString() == "2018-01-01T10:30:00-05:00");
77 }
78
79 // Note: reconsider using specific imports below after
80 // https://issues.dlang.org/show_bug.cgi?id=17630 has been fixed
81 import core.time;// : ClockType, convert, dur, Duration, seconds, TimeException;
82 import std.datetime.date;// : _monthNames, AllowDayOverflow, CmpTimeUnits, Date,
83 //DateTime, DateTimeException, DayOfWeek, enforceValid, getDayOfWeek, maxDay,
84 //Month, splitUnitsFromHNSecs, TimeOfDay, validTimeUnits, yearIsLeapYear;
85 import std.datetime.timezone;// : LocalTime, SimpleTimeZone, TimeZone, UTC;
86 import std.exception : enforce;
87 import std.format : format;
88 import std.range.primitives;
89 import std.traits : isIntegral, isSigned, isSomeString, isNarrowString;
90
version(Windows)91 version (Windows)
92 {
93 import core.stdc.time : time_t;
94 import core.sys.windows.winbase;
95 import core.sys.windows.winnt;
96 import core.sys.windows.winsock2;
97 }
version(Posix)98 else version (Posix)
99 {
100 import core.sys.posix.signal : timespec;
101 import core.sys.posix.sys.types : time_t;
102 }
103
version(StdUnittest)104 version (StdUnittest)
105 {
106 import core.exception : AssertError;
107 import std.exception : assertThrown;
108 }
109
110
111 @safe unittest
112 {
113 initializeTests();
114 }
115
version(unittest)116 version (unittest) private bool clockSupported(ClockType c)
117 {
118 // Skip unsupported clocks on older linux kernels, assume that only
119 // CLOCK_MONOTONIC and CLOCK_REALTIME exist, as that is the lowest
120 // common denominator supported by all versions of Linux pre-2.6.12.
121 version (Linux_Pre_2639)
122 return c == ClockType.normal || c == ClockType.precise;
123 else
124 return true;
125 }
126
127 /++
128 Effectively a namespace to make it clear that the methods it contains are
129 getting the time from the system clock. It cannot be instantiated.
130 +/
131 final class Clock
132 {
133 public:
134
135 /++
136 Returns the current time in the given time zone.
137
138 Params:
139 clockType = The $(REF ClockType, core,time) indicates which system
140 clock to use to get the current time. Very few programs
141 need to use anything other than the default.
142 tz = The time zone for the SysTime that's returned.
143
144 Throws:
145 $(REF DateTimeException,std,datetime,date) if it fails to get the
146 time.
147 +/
148 static SysTime currTime(ClockType clockType = ClockType.normal)(immutable TimeZone tz = LocalTime()) @safe
149 {
150 return SysTime(currStdTime!clockType, tz);
151 }
152
153 @safe unittest
154 {
155 import std.format : format;
156 import core.time;
157 assert(currTime().timezone is LocalTime());
158 assert(currTime(UTC()).timezone is UTC());
159
160 // core.stdc.time.time does not always use unix time on Windows systems.
161 // In particular, dmc does not use unix time. If we can guarantee that
162 // the MS runtime uses unix time, then we may be able run this test
163 // then, but for now, we're just not going to run this test on Windows.
version(Posix)164 version (Posix)
165 {
166 static import core.stdc.time;
167 static import std.math;
168 immutable unixTimeD = currTime().toUnixTime();
169 immutable unixTimeC = core.stdc.time.time(null);
170 assert(std.math.abs(unixTimeC - unixTimeD) <= 2);
171 }
172
173 auto norm1 = Clock.currTime;
174 auto norm2 = Clock.currTime(UTC());
175 assert(norm1 <= norm2, format("%s %s", norm1, norm2));
176 assert(abs(norm1 - norm2) <= seconds(2));
177
178 import std.meta : AliasSeq;
179 static foreach (ct; AliasSeq!(ClockType.coarse, ClockType.precise, ClockType.second))
180 {{
181 static if (clockSupported(ct))
182 {
183 auto value1 = Clock.currTime!ct;
184 auto value2 = Clock.currTime!ct(UTC());
185 assert(value1 <= value2, format("%s %s (ClockType: %s)", value1, value2, ct));
186 assert(abs(value1 - value2) <= seconds(2), format("ClockType.%s", ct));
187 }
188 }}
189 }
190
191
192 /++
193 Returns the number of hnsecs since midnight, January 1st, 1 A.D. for the
194 current time.
195
196 Params:
197 clockType = The $(REF ClockType, core,time) indicates which system
198 clock to use to get the current time. Very few programs
199 need to use anything other than the default.
200
201 Throws:
202 $(REF DateTimeException,std,datetime,date) if it fails to get the
203 time.
204 +/
205 static @property long currStdTime(ClockType clockType = ClockType.normal)() @trusted
206 {
207 static if (clockType != ClockType.coarse &&
208 clockType != ClockType.normal &&
209 clockType != ClockType.precise &&
210 clockType != ClockType.second)
211 {
212 static assert(0, format("ClockType.%s is not supported by Clock.currTime or Clock.currStdTime", clockType));
213 }
214
version(Windows)215 version (Windows)
216 {
217 FILETIME fileTime;
218 GetSystemTimeAsFileTime(&fileTime);
219 immutable result = FILETIMEToStdTime(&fileTime);
220 static if (clockType == ClockType.second)
221 {
222 // Ideally, this would use core.std.time.time, but the C runtime
223 // has to be using unix time for that to work, and that's not
224 // guaranteed on Windows. Digital Mars does not use unix time.
225 // MS may or may not. If it does, then this can be made to use
226 // core.stdc.time for MS, but for now, we'll leave it like this.
227 return convert!("seconds", "hnsecs")(convert!("hnsecs", "seconds")(result));
228 }
229 else
230 return result;
231 }
version(Posix)232 else version (Posix)
233 {
234 static import core.stdc.time;
235 enum hnsecsToUnixEpoch = unixTimeToStdTime(0);
236
237 version (Darwin)
238 {
239 static if (clockType == ClockType.second)
240 return unixTimeToStdTime(core.stdc.time.time(null));
241 else
242 {
243 import core.sys.posix.sys.time : gettimeofday, timeval;
244 timeval tv = void;
245 // Posix gettimeofday called with a valid timeval address
246 // and a null second parameter doesn't fail.
247 gettimeofday(&tv, null);
248 return convert!("seconds", "hnsecs")(tv.tv_sec) +
249 tv.tv_usec * 10 +
250 hnsecsToUnixEpoch;
251 }
252 }
253 else version (linux)
254 {
255 static if (clockType == ClockType.second)
256 return unixTimeToStdTime(core.stdc.time.time(null));
257 else
258 {
259 import core.sys.linux.time : CLOCK_REALTIME_COARSE;
260 import core.sys.posix.time : clock_gettime, CLOCK_REALTIME;
261 static if (clockType == ClockType.coarse) alias clockArg = CLOCK_REALTIME_COARSE;
262 else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME;
263 else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME;
264 else static assert(0, "Previous static if is wrong.");
265 timespec ts = void;
266 immutable error = clock_gettime(clockArg, &ts);
267 // Posix clock_gettime called with a valid address and valid clock_id is only
268 // permitted to fail if the number of seconds does not fit in time_t. If tv_sec
269 // is long or larger overflow won't happen before 292 billion years A.D.
270 static if (ts.tv_sec.max < long.max)
271 {
272 if (error)
273 throw new TimeException("Call to clock_gettime() failed");
274 }
275 return convert!("seconds", "hnsecs")(ts.tv_sec) +
276 ts.tv_nsec / 100 +
277 hnsecsToUnixEpoch;
278 }
279 }
280 else version (FreeBSD)
281 {
282 import core.sys.freebsd.time : clock_gettime, CLOCK_REALTIME,
283 CLOCK_REALTIME_FAST, CLOCK_REALTIME_PRECISE, CLOCK_SECOND;
284 static if (clockType == ClockType.coarse) alias clockArg = CLOCK_REALTIME_FAST;
285 else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME;
286 else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME_PRECISE;
287 else static if (clockType == ClockType.second) alias clockArg = CLOCK_SECOND;
288 else static assert(0, "Previous static if is wrong.");
289 timespec ts = void;
290 immutable error = clock_gettime(clockArg, &ts);
291 // Posix clock_gettime called with a valid address and valid clock_id is only
292 // permitted to fail if the number of seconds does not fit in time_t. If tv_sec
293 // is long or larger overflow won't happen before 292 billion years A.D.
294 static if (ts.tv_sec.max < long.max)
295 {
296 if (error)
297 throw new TimeException("Call to clock_gettime() failed");
298 }
299 return convert!("seconds", "hnsecs")(ts.tv_sec) +
300 ts.tv_nsec / 100 +
301 hnsecsToUnixEpoch;
302 }
303 else version (NetBSD)
304 {
305 static if (clockType == ClockType.second)
306 return unixTimeToStdTime(core.stdc.time.time(null));
307 else
308 {
309 import core.sys.netbsd.time : clock_gettime, CLOCK_REALTIME;
310 timespec ts = void;
311 immutable error = clock_gettime(CLOCK_REALTIME, &ts);
312 // Posix clock_gettime called with a valid address and valid clock_id is only
313 // permitted to fail if the number of seconds does not fit in time_t. If tv_sec
314 // is long or larger overflow won't happen before 292 billion years A.D.
315 static if (ts.tv_sec.max < long.max)
316 {
317 if (error)
318 throw new TimeException("Call to clock_gettime() failed");
319 }
320 return convert!("seconds", "hnsecs")(ts.tv_sec) +
321 ts.tv_nsec / 100 +
322 hnsecsToUnixEpoch;
323 }
324 }
325 else version (OpenBSD)
326 {
327 static if (clockType == ClockType.second)
328 return unixTimeToStdTime(core.stdc.time.time(null));
329 else
330 {
331 import core.sys.openbsd.time : clock_gettime, CLOCK_REALTIME;
332 static if (clockType == ClockType.coarse) alias clockArg = CLOCK_REALTIME;
333 else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME;
334 else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME;
335 else static assert(0, "Previous static if is wrong.");
336 timespec ts;
337 if (clock_gettime(clockArg, &ts) != 0)
338 throw new TimeException("Call to clock_gettime() failed");
339 return convert!("seconds", "hnsecs")(ts.tv_sec) +
340 ts.tv_nsec / 100 +
341 hnsecsToUnixEpoch;
342 }
343 }
344 else version (DragonFlyBSD)
345 {
346 import core.sys.dragonflybsd.time : clock_gettime, CLOCK_REALTIME,
347 CLOCK_REALTIME_FAST, CLOCK_REALTIME_PRECISE, CLOCK_SECOND;
348 static if (clockType == ClockType.coarse) alias clockArg = CLOCK_REALTIME_FAST;
349 else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME;
350 else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME_PRECISE;
351 else static if (clockType == ClockType.second) alias clockArg = CLOCK_SECOND;
352 else static assert(0, "Previous static if is wrong.");
353 timespec ts = void;
354 immutable error = clock_gettime(clockArg, &ts);
355 // Posix clock_gettime called with a valid address and valid clock_id is only
356 // permitted to fail if the number of seconds does not fit in time_t. If tv_sec
357 // is long or larger overflow won't happen before 292 billion years A.D.
358 static if (ts.tv_sec.max < long.max)
359 {
360 if (error)
361 throw new TimeException("Call to clock_gettime() failed");
362 }
363 return convert!("seconds", "hnsecs")(ts.tv_sec) +
364 ts.tv_nsec / 100 +
365 hnsecsToUnixEpoch;
366 }
367 else version (Solaris)
368 {
369 static if (clockType == ClockType.second)
370 return unixTimeToStdTime(core.stdc.time.time(null));
371 else
372 {
373 import core.sys.solaris.time : clock_gettime, CLOCK_REALTIME;
374 static if (clockType == ClockType.coarse) alias clockArg = CLOCK_REALTIME;
375 else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME;
376 else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME;
377 else static assert(0, "Previous static if is wrong.");
378 timespec ts = void;
379 immutable error = clock_gettime(clockArg, &ts);
380 // Posix clock_gettime called with a valid address and valid clock_id is only
381 // permitted to fail if the number of seconds does not fit in time_t. If tv_sec
382 // is long or larger overflow won't happen before 292 billion years A.D.
383 static if (ts.tv_sec.max < long.max)
384 {
385 if (error)
386 throw new TimeException("Call to clock_gettime() failed");
387 }
388 return convert!("seconds", "hnsecs")(ts.tv_sec) +
389 ts.tv_nsec / 100 +
390 hnsecsToUnixEpoch;
391 }
392 }
393 else static assert(0, "Unsupported OS");
394 }
395 else static assert(0, "Unsupported OS");
396 }
397
398 @safe unittest
399 {
400 import std.format : format;
401 import std.math.algebraic : abs;
402 import std.meta : AliasSeq;
403 enum limit = convert!("seconds", "hnsecs")(2);
404
405 auto norm1 = Clock.currStdTime;
406 auto norm2 = Clock.currStdTime;
407 assert(norm1 <= norm2, format("%s %s", norm1, norm2));
408 assert(abs(norm1 - norm2) <= limit);
409
410 static foreach (ct; AliasSeq!(ClockType.coarse, ClockType.precise, ClockType.second))
411 {{
412 static if (clockSupported(ct))
413 {
414 auto value1 = Clock.currStdTime!ct;
415 auto value2 = Clock.currStdTime!ct;
416 assert(value1 <= value2, format("%s %s (ClockType: %s)", value1, value2, ct));
417 assert(abs(value1 - value2) <= limit);
418 }
419 }}
420 }
421
422
423 private:
424
425 @disable this();
426 }
427
428 /// Get the current time as a $(LREF SysTime)
429 @safe unittest
430 {
431 import std.datetime.timezone : LocalTime;
432 SysTime today = Clock.currTime();
433 assert(today.timezone is LocalTime());
434 }
435
436
437 /++
438 `SysTime` is the type used to get the current time from the
439 system or doing anything that involves time zones. Unlike
440 $(REF DateTime,std,datetime,date), the time zone is an integral part of
441 `SysTime` (though for local time applications, time zones can be ignored
442 and it will work, since it defaults to using the local time zone). It holds
443 its internal time in std time (hnsecs since midnight, January 1st, 1 A.D.
444 UTC), so it interfaces well with the system time. However, that means that,
445 unlike $(REF DateTime,std,datetime,date), it is not optimized for
446 calendar-based operations, and getting individual units from it such as
447 years or days is going to involve conversions and be less efficient.
448
449 An $(I hnsec) (hecto-nanosecond) is 100 nanoseconds. There are 10,000,000 hnsecs in a second.
450
451 For calendar-based operations that don't
452 care about time zones, then $(REF DateTime,std,datetime,date) would be
453 the type to use. For system time, use `SysTime`.
454
455 $(LREF Clock.currTime) will return the current time as a `SysTime`.
456 To convert a `SysTime` to a $(REF Date,std,datetime,date) or
457 $(REF DateTime,std,datetime,date), simply cast it. To convert a
458 $(REF Date,std,datetime,date) or $(REF DateTime,std,datetime,date) to a
459 `SysTime`, use `SysTime`'s constructor, and pass in the intended time
460 zone with it (or don't pass in a $(REF TimeZone,std,datetime,timezone), and
461 the local time zone will be used). Be aware, however, that converting from a
462 $(REF DateTime,std,datetime,date) to a `SysTime` will not necessarily
463 be 100% accurate due to DST (one hour of the year doesn't exist and another
464 occurs twice). To not risk any conversion errors, keep times as
465 `SysTime`s. Aside from DST though, there shouldn't be any conversion
466 problems.
467
468 For using time zones other than local time or UTC, use
469 $(REF PosixTimeZone,std,datetime,timezone) on Posix systems (or on Windows,
470 if providing the TZ Database files), and use
471 $(REF WindowsTimeZone,std,datetime,timezone) on Windows systems. The time in
472 `SysTime` is kept internally in hnsecs from midnight, January 1st, 1 A.D.
473 UTC. Conversion error cannot happen when changing the time zone of a
474 `SysTime`. $(REF LocalTime,std,datetime,timezone) is the
475 $(REF TimeZone,std,datetime,timezone) class which represents the local time,
476 and `UTC` is the $(REF TimeZone,std,datetime,timezone) class which
477 represents UTC. `SysTime` uses $(REF LocalTime,std,datetime,timezone) if
478 no $(REF TimeZone,std,datetime,timezone) is provided. For more details on
479 time zones, see the documentation for $(REF TimeZone,std,datetime,timezone),
480 $(REF PosixTimeZone,std,datetime,timezone), and
481 $(REF WindowsTimeZone,std,datetime,timezone).
482
483 `SysTime`'s range is from approximately 29,000 B.C. to approximately
484 29,000 A.D.
485 +/
486 struct SysTime
487 {
488 import core.stdc.time : tm;
489 version (Posix) import core.sys.posix.sys.time : timeval;
490 import std.typecons : Rebindable;
491
492 public:
493
494 /++
495 Params:
496 dateTime = The $(REF DateTime,std,datetime,date) to use to set
497 this $(LREF SysTime)'s internal std time. As
498 $(REF DateTime,std,datetime,date) has no concept of
499 time zone, tz is used as its time zone.
500 tz = The $(REF TimeZone,std,datetime,timezone) to use for this
501 $(LREF SysTime). If null,
502 $(REF LocalTime,std,datetime,timezone) will be used. The
503 given $(REF DateTime,std,datetime,date) is assumed to
504 be in the given time zone.
505 +/
506 this(DateTime dateTime, immutable TimeZone tz = null) @safe nothrow
507 {
508 try
509 this(dateTime, Duration.zero, tz);
510 catch (Exception e)
511 assert(0, "SysTime's constructor threw when it shouldn't have.");
512 }
513
514 @safe unittest
515 {
testSysTime516 static void test(DateTime dt, immutable TimeZone tz, long expected)
517 {
518 auto sysTime = SysTime(dt, tz);
519 assert(sysTime._stdTime == expected);
520 assert(sysTime._timezone is (tz is null ? LocalTime() : tz), format("Given DateTime: %s", dt));
521 }
522
523 test(DateTime.init, UTC(), 0);
524 test(DateTime(1, 1, 1, 12, 30, 33), UTC(), 450_330_000_000L);
525 test(DateTime(0, 12, 31, 12, 30, 33), UTC(), -413_670_000_000L);
526 test(DateTime(1, 1, 1, 0, 0, 0), UTC(), 0);
527 test(DateTime(1, 1, 1, 0, 0, 1), UTC(), 10_000_000L);
528 test(DateTime(0, 12, 31, 23, 59, 59), UTC(), -10_000_000L);
529
530 test(DateTime(1, 1, 1, 0, 0, 0), new immutable SimpleTimeZone(dur!"minutes"(-60)), 36_000_000_000L);
531 test(DateTime(1, 1, 1, 0, 0, 0), new immutable SimpleTimeZone(Duration.zero), 0);
532 test(DateTime(1, 1, 1, 0, 0, 0), new immutable SimpleTimeZone(dur!"minutes"(60)), -36_000_000_000L);
533
534 static void testScope(scope ref DateTime dt) @safe
535 {
536 auto st = SysTime(dt);
537 }
538 }
539
540 /++
541 Params:
542 dateTime = The $(REF DateTime,std,datetime,date) to use to set
543 this $(LREF SysTime)'s internal std time. As
544 $(REF DateTime,std,datetime,date) has no concept of
545 time zone, tz is used as its time zone.
546 fracSecs = The fractional seconds portion of the time.
547 tz = The $(REF TimeZone,std,datetime,timezone) to use for this
548 $(LREF SysTime). If null,
549 $(REF LocalTime,std,datetime,timezone) will be used. The
550 given $(REF DateTime,std,datetime,date) is assumed to
551 be in the given time zone.
552
553 Throws:
554 $(REF DateTimeException,std,datetime,date) if `fracSecs` is negative or if it's
555 greater than or equal to one second.
556 +/
557 this(DateTime dateTime, Duration fracSecs, immutable TimeZone tz = null) @safe
558 {
559 enforce(fracSecs >= Duration.zero, new DateTimeException("A SysTime cannot have negative fractional seconds."));
560 enforce(fracSecs < seconds(1), new DateTimeException("Fractional seconds must be less than one second."));
561 auto nonNullTZ = tz is null ? LocalTime() : tz;
562
563 immutable dateDiff = dateTime.date - Date.init;
564 immutable todDiff = dateTime.timeOfDay - TimeOfDay.init;
565
566 immutable adjustedTime = dateDiff + todDiff + fracSecs;
567 immutable standardTime = nonNullTZ.tzToUTC(adjustedTime.total!"hnsecs");
568
569 this(standardTime, nonNullTZ);
570 }
571
572 @safe unittest
573 {
574 import core.time;
575 static void test(DateTime dt, Duration fracSecs, immutable TimeZone tz, long expected)
576 {
577 auto sysTime = SysTime(dt, fracSecs, tz);
578 assert(sysTime._stdTime == expected);
579 assert(sysTime._timezone is (tz is null ? LocalTime() : tz),
580 format("Given DateTime: %s, Given Duration: %s", dt, fracSecs));
581 }
582
583 test(DateTime.init, Duration.zero, UTC(), 0);
584 test(DateTime(1, 1, 1, 12, 30, 33), Duration.zero, UTC(), 450_330_000_000L);
585 test(DateTime(0, 12, 31, 12, 30, 33), Duration.zero, UTC(), -413_670_000_000L);
586 test(DateTime(1, 1, 1, 0, 0, 0), msecs(1), UTC(), 10_000L);
587 test(DateTime(0, 12, 31, 23, 59, 59), msecs(999), UTC(), -10_000L);
588
589 test(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC(), -1);
590 test(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1), UTC(), -9_999_999);
591 test(DateTime(0, 12, 31, 23, 59, 59), Duration.zero, UTC(), -10_000_000);
592
593 assertThrown!DateTimeException(SysTime(DateTime.init, hnsecs(-1), UTC()));
594 assertThrown!DateTimeException(SysTime(DateTime.init, seconds(1), UTC()));
595
596 static void testScope(scope ref DateTime dt, scope ref Duration d) @safe
597 {
598 auto st = SysTime(dt, d);
599 }
600 }
601
602 /++
603 Params:
604 date = The $(REF Date,std,datetime,date) to use to set this
605 $(LREF SysTime)'s internal std time. As
606 $(REF Date,std,datetime,date) has no concept of time zone, tz
607 is used as its time zone.
608 tz = The $(REF TimeZone,std,datetime,timezone) to use for this
609 $(LREF SysTime). If null,
610 $(REF LocalTime,std,datetime,timezone) will be used. The
611 given $(REF Date,std,datetime,date) is assumed to be in the
612 given time zone.
613 +/
614 this(Date date, immutable TimeZone tz = null) @safe nothrow
615 {
616 _timezone = tz is null ? LocalTime() : tz;
617
618 try
619 {
620 immutable adjustedTime = (date - Date(1, 1, 1)).total!"hnsecs";
621 immutable standardTime = _timezone.tzToUTC(adjustedTime);
622
623 this(standardTime, _timezone);
624 }
625 catch (Exception e)
626 assert(0, "Date's constructor through when it shouldn't have.");
627 }
628
629 @safe unittest
630 {
testSysTime631 static void test(Date d, immutable TimeZone tz, long expected)
632 {
633 auto sysTime = SysTime(d, tz);
634 assert(sysTime._stdTime == expected);
635 assert(sysTime._timezone is (tz is null ? LocalTime() : tz), format("Given Date: %s", d));
636 }
637
638 test(Date.init, UTC(), 0);
639 test(Date(1, 1, 1), UTC(), 0);
640 test(Date(1, 1, 2), UTC(), 864000000000);
641 test(Date(0, 12, 31), UTC(), -864000000000);
642
testScopeSysTime643 static void testScope(scope ref Date d) @safe
644 {
645 auto st = SysTime(d);
646 }
647 }
648
649 /++
650 Note:
651 Whereas the other constructors take in the given date/time, assume
652 that it's in the given time zone, and convert it to hnsecs in UTC
653 since midnight, January 1st, 1 A.D. UTC - i.e. std time - this
654 constructor takes a std time, which is specifically already in UTC,
655 so no conversion takes place. Of course, the various getter
656 properties and functions will use the given time zone's conversion
657 function to convert the results to that time zone, but no conversion
658 of the arguments to this constructor takes place.
659
660 Params:
661 stdTime = The number of hnsecs since midnight, January 1st, 1 A.D.
662 UTC.
663 tz = The $(REF TimeZone,std,datetime,timezone) to use for this
664 $(LREF SysTime). If null,
665 $(REF LocalTime,std,datetime,timezone) will be used.
666 +/
667 this(long stdTime, immutable TimeZone tz = null) @safe pure nothrow
668 {
669 _stdTime = stdTime;
670 _timezone = tz is null ? LocalTime() : tz;
671 }
672
673 @safe unittest
674 {
testSysTime675 static void test(long stdTime, immutable TimeZone tz)
676 {
677 auto sysTime = SysTime(stdTime, tz);
678 assert(sysTime._stdTime == stdTime);
679 assert(sysTime._timezone is (tz is null ? LocalTime() : tz), format("Given stdTime: %s", stdTime));
680 }
681
foreachSysTime682 foreach (stdTime; [-1234567890L, -250, 0, 250, 1235657390L])
683 {
684 foreach (tz; testTZs)
685 test(stdTime, tz);
686 }
687 }
688
689
690 /++
691 Params:
692 rhs = The $(LREF SysTime) to assign to this one.
693
694 Returns: The `this` of this `SysTime`.
695 +/
696 ref SysTime opAssign()(auto ref const(SysTime) rhs) return @safe pure nothrow scope
697 {
698 _stdTime = rhs._stdTime;
699 _timezone = rhs._timezone;
700 return this;
701 }
702
703 @safe unittest
704 {
705 SysTime st;
706 st = SysTime(DateTime(2012, 12, 21, 1, 2, 3), UTC());
707 assert(st == SysTime(DateTime(2012, 12, 21, 1, 2, 3), UTC()));
708
709 const other = SysTime(DateTime(19, 1, 7, 13, 14, 15), LocalTime());
710 st = other;
711 assert(st == other);
712
713 static void testScope(scope ref SysTime left, const scope SysTime right) @safe
714 {
715 left = right;
716 }
717 }
718
719
720 /++
721 Checks for equality between this $(LREF SysTime) and the given
722 $(LREF SysTime).
723
724 Note that the time zone is ignored. Only the internal
725 std times (which are in UTC) are compared.
726 +/
727 bool opEquals()(auto ref const(SysTime) rhs) @safe const pure nothrow scope
728 {
729 return _stdTime == rhs._stdTime;
730 }
731
732 @safe unittest
733 {
734 import std.range : chain;
735
736 assert(SysTime(DateTime.init, UTC()) == SysTime(0, UTC()));
737 assert(SysTime(DateTime.init, UTC()) == SysTime(0));
738 assert(SysTime(Date.init, UTC()) == SysTime(0));
739 assert(SysTime(0) == SysTime(0));
740
741 static void test(DateTime dt, immutable TimeZone tz1, immutable TimeZone tz2)
742 {
743 auto st1 = SysTime(dt);
744 st1.timezone = tz1;
745
746 auto st2 = SysTime(dt);
747 st2.timezone = tz2;
748
749 assert(st1 == st2);
750 }
751
752 foreach (tz1; testTZs)
753 {
754 foreach (tz2; testTZs)
755 {
756 foreach (dt; chain(testDateTimesBC, testDateTimesAD))
757 test(dt, tz1, tz2);
758 }
759 }
760
761 auto st = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
762 const cst = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
763 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
764 assert(st == st);
765 assert(st == cst);
766 assert(st == ist);
767 assert(cst == st);
768 assert(cst == cst);
769 assert(cst == ist);
770 assert(ist == st);
771 assert(ist == cst);
772 assert(ist == ist);
773
774 static void testScope(scope ref SysTime left, const scope SysTime right) @safe
775 {
776 assert(left == right);
777 assert(right == left);
778 }
779 }
780
781
782 /++
783 Compares this $(LREF SysTime) with the given $(LREF SysTime).
784
785 Time zone is irrelevant when comparing $(LREF SysTime)s.
786
787 Returns:
788 $(BOOKTABLE,
789 $(TR $(TD this < rhs) $(TD < 0))
790 $(TR $(TD this == rhs) $(TD 0))
791 $(TR $(TD this > rhs) $(TD > 0))
792 )
793 +/
794 int opCmp()(auto ref const(SysTime) rhs) @safe const pure nothrow scope
795 {
796 if (_stdTime < rhs._stdTime)
797 return -1;
798 if (_stdTime > rhs._stdTime)
799 return 1;
800 return 0;
801 }
802
803 @safe unittest
804 {
805 import std.algorithm.iteration : map;
806 import std.array : array;
807 import std.range : chain;
808
809 assert(SysTime(DateTime.init, UTC()).opCmp(SysTime(0, UTC())) == 0);
810 assert(SysTime(DateTime.init, UTC()).opCmp(SysTime(0)) == 0);
811 assert(SysTime(Date.init, UTC()).opCmp(SysTime(0)) == 0);
812 assert(SysTime(0).opCmp(SysTime(0)) == 0);
813
814 static void testEqual(SysTime st, immutable TimeZone tz1, immutable TimeZone tz2)
815 {
816 auto st1 = st;
817 st1.timezone = tz1;
818
819 auto st2 = st;
820 st2.timezone = tz2;
821
822 assert(st1.opCmp(st2) == 0);
823 }
824
825 auto sts = array(map!SysTime(chain(testDateTimesBC, testDateTimesAD)));
826
827 foreach (st; sts)
828 {
829 foreach (tz1; testTZs)
830 {
831 foreach (tz2; testTZs)
832 testEqual(st, tz1, tz2);
833 }
834 }
835
836 static void testCmp(SysTime st1, immutable TimeZone tz1, SysTime st2, immutable TimeZone tz2)
837 {
838 st1.timezone = tz1;
839 st2.timezone = tz2;
840 assert(st1.opCmp(st2) < 0);
841 assert(st2.opCmp(st1) > 0);
842 }
843
844 foreach (si, st1; sts)
845 {
846 foreach (st2; sts[si + 1 .. $])
847 {
848 foreach (tz1; testTZs)
849 {
850 foreach (tz2; testTZs)
851 testCmp(st1, tz1, st2, tz2);
852 }
853 }
854 }
855
856 auto st = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
857 const cst = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
858 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 33, 30));
859 assert(st.opCmp(st) == 0);
860 assert(st.opCmp(cst) == 0);
861 assert(st.opCmp(ist) == 0);
862 assert(cst.opCmp(st) == 0);
863 assert(cst.opCmp(cst) == 0);
864 assert(cst.opCmp(ist) == 0);
865 assert(ist.opCmp(st) == 0);
866 assert(ist.opCmp(cst) == 0);
867 assert(ist.opCmp(ist) == 0);
868
869 static void testScope(scope ref SysTime left, const scope SysTime right) @safe
870 {
871 assert(left < right);
872 assert(right > left);
873 }
874 }
875
876
877 /++
878 Returns: A hash of the $(LREF SysTime).
879 +/
880 size_t toHash() const @nogc pure nothrow @safe scope
881 {
882 static if (is(size_t == ulong))
883 return _stdTime;
884 else
885 {
886 // MurmurHash2
887 enum ulong m = 0xc6a4a7935bd1e995UL;
888 enum ulong n = m * 16;
889 enum uint r = 47;
890
891 ulong k = _stdTime;
892 k *= m;
893 k ^= k >> r;
894 k *= m;
895
896 ulong h = n;
897 h ^= k;
898 h *= m;
899
900 return cast(size_t) h;
901 }
902 }
903
904 @safe unittest
905 {
906 assert(SysTime(0).toHash == SysTime(0).toHash);
907 assert(SysTime(DateTime(2000, 1, 1)).toHash == SysTime(DateTime(2000, 1, 1)).toHash);
908 assert(SysTime(DateTime(2000, 1, 1)).toHash != SysTime(DateTime(2000, 1, 2)).toHash);
909
910 // test that timezones aren't taken into account
911 assert(SysTime(0, LocalTime()).toHash == SysTime(0, LocalTime()).toHash);
912 assert(SysTime(0, LocalTime()).toHash == SysTime(0, UTC()).toHash);
913 assert(SysTime(DateTime(2000, 1, 1), LocalTime()).toHash == SysTime(DateTime(2000, 1, 1), LocalTime()).toHash);
914 immutable zone = new SimpleTimeZone(dur!"minutes"(60));
915 assert(SysTime(DateTime(2000, 1, 1, 1), zone).toHash == SysTime(DateTime(2000, 1, 1), UTC()).toHash);
916 assert(SysTime(DateTime(2000, 1, 1), zone).toHash != SysTime(DateTime(2000, 1, 1), UTC()).toHash);
917
918 static void testScope(scope ref SysTime st) @safe
919 {
920 auto result = st.toHash();
921 }
922 }
923
924
925 /++
926 Year of the Gregorian Calendar. Positive numbers are A.D. Non-positive
927 are B.C.
928 +/
929 @property short year() @safe const nothrow scope
930 {
931 return (cast(Date) this).year;
932 }
933
934 @safe unittest
935 {
936 import std.range : chain;
937 static void test(SysTime sysTime, long expected)
938 {
939 assert(sysTime.year == expected, format("Value given: %s", sysTime));
940 }
941
942 test(SysTime(0, UTC()), 1);
943 test(SysTime(1, UTC()), 1);
944 test(SysTime(-1, UTC()), 0);
945
946 foreach (year; chain(testYearsBC, testYearsAD))
947 {
948 foreach (md; testMonthDays)
949 {
950 foreach (tod; testTODs)
951 {
952 auto dt = DateTime(Date(year, md.month, md.day), tod);
953 foreach (tz; testTZs)
954 {
955 foreach (fs; testFracSecs)
956 test(SysTime(dt, fs, tz), year);
957 }
958 }
959 }
960 }
961
962 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
963 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
964 assert(cst.year == 1999);
965 assert(ist.year == 1999);
966
967 static void testScope(scope ref SysTime st) @safe
968 {
969 auto result = st.year;
970 }
971 }
972
973 /++
974 Year of the Gregorian Calendar. Positive numbers are A.D. Non-positive
975 are B.C.
976
977 Params:
978 year = The year to set this $(LREF SysTime)'s year to.
979
980 Throws:
981 $(REF DateTimeException,std,datetime,date) if the new year is not
982 a leap year and the resulting date would be on February 29th.
983 +/
984 @property void year(int year) @safe scope
985 {
986 auto hnsecs = adjTime;
987 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
988
989 if (hnsecs < 0)
990 {
991 hnsecs += convert!("hours", "hnsecs")(24);
992 --days;
993 }
994
995 auto date = Date(cast(int) days);
996 date.year = year;
997
998 immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
999 adjTime = newDaysHNSecs + hnsecs;
1000 }
1001
1002 ///
1003 @safe unittest
1004 {
1005 import std.datetime.date : DateTime;
1006
1007 assert(SysTime(DateTime(1999, 7, 6, 9, 7, 5)).year == 1999);
1008 assert(SysTime(DateTime(2010, 10, 4, 0, 0, 30)).year == 2010);
1009 assert(SysTime(DateTime(-7, 4, 5, 7, 45, 2)).year == -7);
1010 }
1011
1012 @safe unittest
1013 {
1014 import std.range : chain;
1015
1016 static void test(SysTime st, int year, SysTime expected)
1017 {
1018 st.year = year;
1019 assert(st == expected);
1020 }
1021
1022 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1023 {
1024 auto dt = cast(DateTime) st;
1025
1026 foreach (year; chain(testYearsBC, testYearsAD))
1027 {
1028 auto e = SysTime(DateTime(year, dt.month, dt.day, dt.hour, dt.minute, dt.second),
1029 st.fracSecs,
1030 st.timezone);
1031 test(st, year, e);
1032 }
1033 }
1034
1035 foreach (fs; testFracSecs)
1036 {
1037 foreach (tz; testTZs)
1038 {
1039 foreach (tod; testTODs)
1040 {
1041 test(SysTime(DateTime(Date(1999, 2, 28), tod), fs, tz), 2000,
1042 SysTime(DateTime(Date(2000, 2, 28), tod), fs, tz));
1043 test(SysTime(DateTime(Date(2000, 2, 28), tod), fs, tz), 1999,
1044 SysTime(DateTime(Date(1999, 2, 28), tod), fs, tz));
1045 }
1046
1047 foreach (tod; testTODsThrown)
1048 {
1049 auto st = SysTime(DateTime(Date(2000, 2, 29), tod), fs, tz);
1050 assertThrown!DateTimeException(st.year = 1999);
1051 }
1052 }
1053 }
1054
1055 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1056 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1057 static assert(!__traits(compiles, cst.year = 7));
1058 static assert(!__traits(compiles, ist.year = 7));
1059
1060 static void testScope(scope ref SysTime st) @safe
1061 {
1062 st.year = 42;
1063 }
1064 }
1065
1066 /++
1067 Year B.C. of the Gregorian Calendar counting year 0 as 1 B.C.
1068
1069 Throws:
1070 $(REF DateTimeException,std,datetime,date) if `isAD` is true.
1071 +/
1072 @property ushort yearBC() @safe const scope
1073 {
1074 return (cast(Date) this).yearBC;
1075 }
1076
1077 ///
1078 @safe unittest
1079 {
1080 import std.datetime.date : DateTime;
1081
1082 assert(SysTime(DateTime(0, 1, 1, 12, 30, 33)).yearBC == 1);
1083 assert(SysTime(DateTime(-1, 1, 1, 10, 7, 2)).yearBC == 2);
1084 assert(SysTime(DateTime(-100, 1, 1, 4, 59, 0)).yearBC == 101);
1085 }
1086
1087 @safe unittest
1088 {
1089 import std.exception : assertNotThrown;
1090 foreach (st; testSysTimesBC)
1091 {
1092 auto msg = format("SysTime: %s", st);
1093 assertNotThrown!DateTimeException(st.yearBC, msg);
1094 assert(st.yearBC == (st.year * -1) + 1, msg);
1095 }
1096
1097 foreach (st; [testSysTimesAD[0], testSysTimesAD[$/2], testSysTimesAD[$-1]])
1098 assertThrown!DateTimeException(st.yearBC, format("SysTime: %s", st));
1099
1100 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1101 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1102 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1103 st.year = 12;
1104 assert(st.year == 12);
1105 static assert(!__traits(compiles, cst.year = 12));
1106 static assert(!__traits(compiles, ist.year = 12));
1107
1108 static void testScope(scope ref SysTime st) @safe
1109 {
1110 auto result = st.yearBC;
1111 }
1112 }
1113
1114
1115 /++
1116 Year B.C. of the Gregorian Calendar counting year 0 as 1 B.C.
1117
1118 Params:
1119 year = The year B.C. to set this $(LREF SysTime)'s year to.
1120
1121 Throws:
1122 $(REF DateTimeException,std,datetime,date) if a non-positive value
1123 is given.
1124 +/
1125 @property void yearBC(int year) @safe scope
1126 {
1127 auto hnsecs = adjTime;
1128 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
1129
1130 if (hnsecs < 0)
1131 {
1132 hnsecs += convert!("hours", "hnsecs")(24);
1133 --days;
1134 }
1135
1136 auto date = Date(cast(int) days);
1137 date.yearBC = year;
1138
1139 immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
1140 adjTime = newDaysHNSecs + hnsecs;
1141 }
1142
1143 @safe unittest
1144 {
1145 auto st = SysTime(DateTime(2010, 1, 1, 7, 30, 0));
1146 st.yearBC = 1;
1147 assert(st == SysTime(DateTime(0, 1, 1, 7, 30, 0)));
1148
1149 st.yearBC = 10;
1150 assert(st == SysTime(DateTime(-9, 1, 1, 7, 30, 0)));
1151 }
1152
1153 @safe unittest
1154 {
1155 import std.range : chain;
1156 static void test(SysTime st, int year, SysTime expected)
1157 {
1158 st.yearBC = year;
1159 assert(st == expected, format("SysTime: %s", st));
1160 }
1161
1162 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1163 {
1164 auto dt = cast(DateTime) st;
1165
1166 foreach (year; testYearsBC)
1167 {
1168 auto e = SysTime(DateTime(year, dt.month, dt.day, dt.hour, dt.minute, dt.second),
1169 st.fracSecs,
1170 st.timezone);
1171 test(st, (year * -1) + 1, e);
1172 }
1173 }
1174
1175 foreach (st; [testSysTimesBC[0], testSysTimesBC[$ - 1], testSysTimesAD[0], testSysTimesAD[$ - 1]])
1176 {
1177 foreach (year; testYearsBC)
1178 assertThrown!DateTimeException(st.yearBC = year);
1179 }
1180
1181 foreach (fs; testFracSecs)
1182 {
1183 foreach (tz; testTZs)
1184 {
1185 foreach (tod; testTODs)
1186 {
1187 test(SysTime(DateTime(Date(-1999, 2, 28), tod), fs, tz), 2001,
1188 SysTime(DateTime(Date(-2000, 2, 28), tod), fs, tz));
1189 test(SysTime(DateTime(Date(-2000, 2, 28), tod), fs, tz), 2000,
1190 SysTime(DateTime(Date(-1999, 2, 28), tod), fs, tz));
1191 }
1192
1193 foreach (tod; testTODsThrown)
1194 {
1195 auto st = SysTime(DateTime(Date(-2000, 2, 29), tod), fs, tz);
1196 assertThrown!DateTimeException(st.year = -1999);
1197 }
1198 }
1199 }
1200
1201 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1202 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1203 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1204 st.yearBC = 12;
1205 assert(st.yearBC == 12);
1206 static assert(!__traits(compiles, cst.yearBC = 12));
1207 static assert(!__traits(compiles, ist.yearBC = 12));
1208
1209 static void testScope(scope ref SysTime st) @safe
1210 {
1211 st.yearBC = 42;
1212 }
1213 }
1214
1215
1216 /++
1217 Month of a Gregorian Year.
1218 +/
1219 @property Month month() @safe const nothrow scope
1220 {
1221 return (cast(Date) this).month;
1222 }
1223
1224 ///
1225 @safe unittest
1226 {
1227 import std.datetime.date : DateTime;
1228
1229 assert(SysTime(DateTime(1999, 7, 6, 9, 7, 5)).month == 7);
1230 assert(SysTime(DateTime(2010, 10, 4, 0, 0, 30)).month == 10);
1231 assert(SysTime(DateTime(-7, 4, 5, 7, 45, 2)).month == 4);
1232 }
1233
1234 @safe unittest
1235 {
1236 import std.range : chain;
1237
1238 static void test(SysTime sysTime, Month expected)
1239 {
1240 assert(sysTime.month == expected, format("Value given: %s", sysTime));
1241 }
1242
1243 test(SysTime(0, UTC()), Month.jan);
1244 test(SysTime(1, UTC()), Month.jan);
1245 test(SysTime(-1, UTC()), Month.dec);
1246
1247 foreach (year; chain(testYearsBC, testYearsAD))
1248 {
1249 foreach (md; testMonthDays)
1250 {
1251 foreach (tod; testTODs)
1252 {
1253 auto dt = DateTime(Date(year, md.month, md.day), tod);
1254 foreach (fs; testFracSecs)
1255 {
1256 foreach (tz; testTZs)
1257 test(SysTime(dt, fs, tz), md.month);
1258 }
1259 }
1260 }
1261 }
1262
1263 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1264 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1265 assert(cst.month == 7);
1266 assert(ist.month == 7);
1267
1268 static void testScope(scope ref SysTime st) @safe
1269 {
1270 auto result = st.month;
1271 }
1272 }
1273
1274
1275 /++
1276 Month of a Gregorian Year.
1277
1278 Params:
1279 month = The month to set this $(LREF SysTime)'s month to.
1280
1281 Throws:
1282 $(REF DateTimeException,std,datetime,date) if the given month is
1283 not a valid month.
1284 +/
1285 @property void month(Month month) @safe scope
1286 {
1287 auto hnsecs = adjTime;
1288 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
1289
1290 if (hnsecs < 0)
1291 {
1292 hnsecs += convert!("hours", "hnsecs")(24);
1293 --days;
1294 }
1295
1296 auto date = Date(cast(int) days);
1297 date.month = month;
1298
1299 immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
1300 adjTime = newDaysHNSecs + hnsecs;
1301 }
1302
1303 @safe unittest
1304 {
1305 import std.algorithm.iteration : filter;
1306 import std.range : chain;
1307
1308 static void test(SysTime st, Month month, SysTime expected)
1309 {
1310 st.month = cast(Month) month;
1311 assert(st == expected);
1312 }
1313
1314 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1315 {
1316 auto dt = cast(DateTime) st;
1317
1318 foreach (md; testMonthDays)
1319 {
1320 if (st.day > maxDay(dt.year, md.month))
1321 continue;
1322 auto e = SysTime(DateTime(dt.year, md.month, dt.day, dt.hour, dt.minute, dt.second),
1323 st.fracSecs,
1324 st.timezone);
1325 test(st, md.month, e);
1326 }
1327 }
1328
1329 foreach (fs; testFracSecs)
1330 {
1331 foreach (tz; testTZs)
1332 {
1333 foreach (tod; testTODs)
1334 {
1335 foreach (year; filter!((a){return yearIsLeapYear(a);}) (chain(testYearsBC, testYearsAD)))
1336 {
1337 test(SysTime(DateTime(Date(year, 1, 29), tod), fs, tz),
1338 Month.feb,
1339 SysTime(DateTime(Date(year, 2, 29), tod), fs, tz));
1340 }
1341
1342 foreach (year; chain(testYearsBC, testYearsAD))
1343 {
1344 test(SysTime(DateTime(Date(year, 1, 28), tod), fs, tz),
1345 Month.feb,
1346 SysTime(DateTime(Date(year, 2, 28), tod), fs, tz));
1347 test(SysTime(DateTime(Date(year, 7, 30), tod), fs, tz),
1348 Month.jun,
1349 SysTime(DateTime(Date(year, 6, 30), tod), fs, tz));
1350 }
1351 }
1352 }
1353 }
1354
1355 foreach (fs; [testFracSecs[0], testFracSecs[$-1]])
1356 {
1357 foreach (tz; testTZs)
1358 {
1359 foreach (tod; testTODsThrown)
1360 {
1361 foreach (year; [testYearsBC[$-3], testYearsBC[$-2],
1362 testYearsBC[$-2], testYearsAD[0],
1363 testYearsAD[$-2], testYearsAD[$-1]])
1364 {
1365 auto day = yearIsLeapYear(year) ? 30 : 29;
1366 auto st1 = SysTime(DateTime(Date(year, 1, day), tod), fs, tz);
1367 assertThrown!DateTimeException(st1.month = Month.feb);
1368
1369 auto st2 = SysTime(DateTime(Date(year, 7, 31), tod), fs, tz);
1370 assertThrown!DateTimeException(st2.month = Month.jun);
1371 }
1372 }
1373 }
1374 }
1375
1376 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1377 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1378 static assert(!__traits(compiles, cst.month = Month.dec));
1379 static assert(!__traits(compiles, ist.month = Month.dec));
1380
1381 static void testScope(scope ref SysTime st) @safe
1382 {
1383 st.month = Month.dec;
1384 }
1385 }
1386
1387 /++
1388 Day of a Gregorian Month.
1389 +/
1390 @property ubyte day() @safe const nothrow scope
1391 {
1392 return (cast(Date) this).day;
1393 }
1394
1395 ///
1396 @safe unittest
1397 {
1398 import std.datetime.date : DateTime;
1399
1400 assert(SysTime(DateTime(1999, 7, 6, 9, 7, 5)).day == 6);
1401 assert(SysTime(DateTime(2010, 10, 4, 0, 0, 30)).day == 4);
1402 assert(SysTime(DateTime(-7, 4, 5, 7, 45, 2)).day == 5);
1403 }
1404
1405 @safe unittest
1406 {
1407 import std.range : chain;
1408
1409 static void test(SysTime sysTime, int expected)
1410 {
1411 assert(sysTime.day == expected, format("Value given: %s", sysTime));
1412 }
1413
1414 test(SysTime(0, UTC()), 1);
1415 test(SysTime(1, UTC()), 1);
1416 test(SysTime(-1, UTC()), 31);
1417
1418 foreach (year; chain(testYearsBC, testYearsAD))
1419 {
1420 foreach (md; testMonthDays)
1421 {
1422 foreach (tod; testTODs)
1423 {
1424 auto dt = DateTime(Date(year, md.month, md.day), tod);
1425
1426 foreach (tz; testTZs)
1427 {
1428 foreach (fs; testFracSecs)
1429 test(SysTime(dt, fs, tz), md.day);
1430 }
1431 }
1432 }
1433 }
1434
1435 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1436 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1437 assert(cst.day == 6);
1438 assert(ist.day == 6);
1439
1440 static void testScope(scope ref SysTime st) @safe
1441 {
1442 auto result = st.day;
1443 }
1444 }
1445
1446
1447 /++
1448 Day of a Gregorian Month.
1449
1450 Params:
1451 day = The day of the month to set this $(LREF SysTime)'s day to.
1452
1453 Throws:
1454 $(REF DateTimeException,std,datetime,date) if the given day is not
1455 a valid day of the current month.
1456 +/
1457 @property void day(int day) @safe scope
1458 {
1459 auto hnsecs = adjTime;
1460 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
1461
1462 if (hnsecs < 0)
1463 {
1464 hnsecs += convert!("hours", "hnsecs")(24);
1465 --days;
1466 }
1467
1468 auto date = Date(cast(int) days);
1469 date.day = day;
1470
1471 immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
1472 adjTime = newDaysHNSecs + hnsecs;
1473 }
1474
1475 @safe unittest
1476 {
1477 import std.range : chain;
1478 import std.traits : EnumMembers;
1479
1480 foreach (day; chain(testDays))
1481 {
1482 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1483 {
1484 auto dt = cast(DateTime) st;
1485
1486 if (day > maxDay(dt.year, dt.month))
1487 continue;
1488 auto expected = SysTime(DateTime(dt.year, dt.month, day, dt.hour, dt.minute, dt.second),
1489 st.fracSecs,
1490 st.timezone);
1491 st.day = day;
1492 assert(st == expected, format("[%s] [%s]", st, expected));
1493 }
1494 }
1495
1496 foreach (tz; testTZs)
1497 {
1498 foreach (tod; testTODs)
1499 {
1500 foreach (fs; testFracSecs)
1501 {
1502 foreach (year; chain(testYearsBC, testYearsAD))
1503 {
1504 foreach (month; EnumMembers!Month)
1505 {
1506 auto st = SysTime(DateTime(Date(year, month, 1), tod), fs, tz);
1507 immutable max = maxDay(year, month);
1508 auto expected = SysTime(DateTime(Date(year, month, max), tod), fs, tz);
1509
1510 st.day = max;
1511 assert(st == expected, format("[%s] [%s]", st, expected));
1512 }
1513 }
1514 }
1515 }
1516 }
1517
1518 foreach (tz; testTZs)
1519 {
1520 foreach (tod; testTODsThrown)
1521 {
1522 foreach (fs; [testFracSecs[0], testFracSecs[$-1]])
1523 {
1524 foreach (year; [testYearsBC[$-3], testYearsBC[$-2],
1525 testYearsBC[$-2], testYearsAD[0],
1526 testYearsAD[$-2], testYearsAD[$-1]])
1527 {
1528 foreach (month; EnumMembers!Month)
1529 {
1530 auto st = SysTime(DateTime(Date(year, month, 1), tod), fs, tz);
1531 immutable max = maxDay(year, month);
1532
1533 assertThrown!DateTimeException(st.day = max + 1);
1534 }
1535 }
1536 }
1537 }
1538 }
1539
1540 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1541 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1542 static assert(!__traits(compiles, cst.day = 27));
1543 static assert(!__traits(compiles, ist.day = 27));
1544
1545 static void testScope(scope ref SysTime st) @safe
1546 {
1547 st.day = 12;
1548 }
1549 }
1550
1551
1552 /++
1553 Hours past midnight.
1554 +/
1555 @property ubyte hour() @safe const nothrow scope
1556 {
1557 auto hnsecs = adjTime;
1558 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
1559
1560 if (hnsecs < 0)
1561 {
1562 hnsecs += convert!("hours", "hnsecs")(24);
1563 --days;
1564 }
1565
1566 return cast(ubyte) getUnitsFromHNSecs!"hours"(hnsecs);
1567 }
1568
1569 @safe unittest
1570 {
1571 import std.range : chain;
1572
1573 static void test(SysTime sysTime, int expected)
1574 {
1575 assert(sysTime.hour == expected, format("Value given: %s", sysTime));
1576 }
1577
1578 test(SysTime(0, UTC()), 0);
1579 test(SysTime(1, UTC()), 0);
1580 test(SysTime(-1, UTC()), 23);
1581
1582 foreach (tz; testTZs)
1583 {
1584 foreach (year; chain(testYearsBC, testYearsAD))
1585 {
1586 foreach (md; testMonthDays)
1587 {
1588 foreach (hour; testHours)
1589 {
1590 foreach (minute; testMinSecs)
1591 {
1592 foreach (second; testMinSecs)
1593 {
1594 auto dt = DateTime(Date(year, md.month, md.day), TimeOfDay(hour, minute, second));
1595 foreach (fs; testFracSecs)
1596 test(SysTime(dt, fs, tz), hour);
1597 }
1598 }
1599 }
1600 }
1601 }
1602 }
1603
1604 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1605 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1606 assert(cst.hour == 12);
1607 assert(ist.hour == 12);
1608
1609 static void testScope(scope ref SysTime st) @safe
1610 {
1611 auto result = st.hour;
1612 }
1613 }
1614
1615
1616 /++
1617 Hours past midnight.
1618
1619 Params:
1620 hour = The hours to set this $(LREF SysTime)'s hour to.
1621
1622 Throws:
1623 $(REF DateTimeException,std,datetime,date) if the given hour are
1624 not a valid hour of the day.
1625 +/
1626 @property void hour(int hour) @safe scope
1627 {
1628 enforceValid!"hours"(hour);
1629
1630 auto hnsecs = adjTime;
1631 auto days = splitUnitsFromHNSecs!"days"(hnsecs);
1632 immutable daysHNSecs = convert!("days", "hnsecs")(days);
1633 immutable negative = hnsecs < 0;
1634
1635 if (negative)
1636 hnsecs += convert!("hours", "hnsecs")(24);
1637
1638 hnsecs = removeUnitsFromHNSecs!"hours"(hnsecs);
1639 hnsecs += convert!("hours", "hnsecs")(hour);
1640
1641 if (negative)
1642 hnsecs -= convert!("hours", "hnsecs")(24);
1643
1644 adjTime = daysHNSecs + hnsecs;
1645 }
1646
1647 @safe unittest
1648 {
1649 import std.range : chain;
1650
1651 foreach (hour; chain(testHours))
1652 {
1653 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1654 {
1655 auto dt = cast(DateTime) st;
1656 auto expected = SysTime(DateTime(dt.year, dt.month, dt.day, hour, dt.minute, dt.second),
1657 st.fracSecs,
1658 st.timezone);
1659 st.hour = hour;
1660 assert(st == expected, format("[%s] [%s]", st, expected));
1661 }
1662 }
1663
1664 auto st = testSysTimesAD[0];
1665 assertThrown!DateTimeException(st.hour = -1);
1666 assertThrown!DateTimeException(st.hour = 60);
1667
1668 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1669 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1670 static assert(!__traits(compiles, cst.hour = 27));
1671 static assert(!__traits(compiles, ist.hour = 27));
1672
1673 static void testScope(scope ref SysTime st) @safe
1674 {
1675 st.hour = 12;
1676 }
1677 }
1678
1679
1680 /++
1681 Minutes past the current hour.
1682 +/
1683 @property ubyte minute() @safe const nothrow scope
1684 {
1685 auto hnsecs = adjTime;
1686 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
1687
1688 if (hnsecs < 0)
1689 {
1690 hnsecs += convert!("hours", "hnsecs")(24);
1691 --days;
1692 }
1693
1694 hnsecs = removeUnitsFromHNSecs!"hours"(hnsecs);
1695
1696 return cast(ubyte) getUnitsFromHNSecs!"minutes"(hnsecs);
1697 }
1698
1699 @safe unittest
1700 {
1701 import std.range : chain;
1702
1703 static void test(SysTime sysTime, int expected)
1704 {
1705 assert(sysTime.minute == expected, format("Value given: %s", sysTime));
1706 }
1707
1708 test(SysTime(0, UTC()), 0);
1709 test(SysTime(1, UTC()), 0);
1710 test(SysTime(-1, UTC()), 59);
1711
1712 foreach (tz; testTZs)
1713 {
1714 foreach (year; chain(testYearsBC, testYearsAD))
1715 {
1716 foreach (md; testMonthDays)
1717 {
1718 foreach (hour; testHours)
1719 {
1720 foreach (minute; testMinSecs)
1721 {
1722 foreach (second; testMinSecs)
1723 {
1724 auto dt = DateTime(Date(year, md.month, md.day), TimeOfDay(hour, minute, second));
1725 foreach (fs; testFracSecs)
1726 test(SysTime(dt, fs, tz), minute);
1727 }
1728 }
1729 }
1730 }
1731 }
1732 }
1733
1734 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1735 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1736 assert(cst.minute == 30);
1737 assert(ist.minute == 30);
1738
1739 static void testScope(scope ref SysTime st) @safe
1740 {
1741 auto result = st.minute;
1742 }
1743 }
1744
1745
1746 /++
1747 Minutes past the current hour.
1748
1749 Params:
1750 minute = The minute to set this $(LREF SysTime)'s minute to.
1751
1752 Throws:
1753 $(REF DateTimeException,std,datetime,date) if the given minute are
1754 not a valid minute of an hour.
1755 +/
1756 @property void minute(int minute) @safe scope
1757 {
1758 enforceValid!"minutes"(minute);
1759
1760 auto hnsecs = adjTime;
1761 auto days = splitUnitsFromHNSecs!"days"(hnsecs);
1762 immutable daysHNSecs = convert!("days", "hnsecs")(days);
1763 immutable negative = hnsecs < 0;
1764
1765 if (negative)
1766 hnsecs += convert!("hours", "hnsecs")(24);
1767
1768 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
1769 hnsecs = removeUnitsFromHNSecs!"minutes"(hnsecs);
1770
1771 hnsecs += convert!("hours", "hnsecs")(hour);
1772 hnsecs += convert!("minutes", "hnsecs")(minute);
1773
1774 if (negative)
1775 hnsecs -= convert!("hours", "hnsecs")(24);
1776
1777 adjTime = daysHNSecs + hnsecs;
1778 }
1779
1780 @safe unittest
1781 {
1782 import std.range : chain;
1783
1784 foreach (minute; testMinSecs)
1785 {
1786 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1787 {
1788 auto dt = cast(DateTime) st;
1789 auto expected = SysTime(DateTime(dt.year, dt.month, dt.day, dt.hour, minute, dt.second),
1790 st.fracSecs,
1791 st.timezone);
1792 st.minute = minute;
1793 assert(st == expected, format("[%s] [%s]", st, expected));
1794 }
1795 }
1796
1797 auto st = testSysTimesAD[0];
1798 assertThrown!DateTimeException(st.minute = -1);
1799 assertThrown!DateTimeException(st.minute = 60);
1800
1801 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1802 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1803 static assert(!__traits(compiles, cst.minute = 27));
1804 static assert(!__traits(compiles, ist.minute = 27));
1805
1806 static void testScope(scope ref SysTime st) @safe
1807 {
1808 st.minute = 12;
1809 }
1810 }
1811
1812
1813 /++
1814 Seconds past the current minute.
1815 +/
1816 @property ubyte second() @safe const nothrow scope
1817 {
1818 auto hnsecs = adjTime;
1819 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
1820
1821 if (hnsecs < 0)
1822 {
1823 hnsecs += convert!("hours", "hnsecs")(24);
1824 --days;
1825 }
1826
1827 hnsecs = removeUnitsFromHNSecs!"hours"(hnsecs);
1828 hnsecs = removeUnitsFromHNSecs!"minutes"(hnsecs);
1829
1830 return cast(ubyte) getUnitsFromHNSecs!"seconds"(hnsecs);
1831 }
1832
1833 @safe unittest
1834 {
1835 import std.range : chain;
1836
1837 static void test(SysTime sysTime, int expected)
1838 {
1839 assert(sysTime.second == expected, format("Value given: %s", sysTime));
1840 }
1841
1842 test(SysTime(0, UTC()), 0);
1843 test(SysTime(1, UTC()), 0);
1844 test(SysTime(-1, UTC()), 59);
1845
1846 foreach (tz; testTZs)
1847 {
1848 foreach (year; chain(testYearsBC, testYearsAD))
1849 {
1850 foreach (md; testMonthDays)
1851 {
1852 foreach (hour; testHours)
1853 {
1854 foreach (minute; testMinSecs)
1855 {
1856 foreach (second; testMinSecs)
1857 {
1858 auto dt = DateTime(Date(year, md.month, md.day), TimeOfDay(hour, minute, second));
1859 foreach (fs; testFracSecs)
1860 test(SysTime(dt, fs, tz), second);
1861 }
1862 }
1863 }
1864 }
1865 }
1866 }
1867
1868 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1869 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1870 assert(cst.second == 33);
1871 assert(ist.second == 33);
1872
1873 static void testScope(scope ref SysTime st) @safe
1874 {
1875 auto result = st.second;
1876 }
1877 }
1878
1879
1880 /++
1881 Seconds past the current minute.
1882
1883 Params:
1884 second = The second to set this $(LREF SysTime)'s second to.
1885
1886 Throws:
1887 $(REF DateTimeException,std,datetime,date) if the given second are
1888 not a valid second of a minute.
1889 +/
1890 @property void second(int second) @safe scope
1891 {
1892 enforceValid!"seconds"(second);
1893
1894 auto hnsecs = adjTime;
1895 auto days = splitUnitsFromHNSecs!"days"(hnsecs);
1896 immutable daysHNSecs = convert!("days", "hnsecs")(days);
1897 immutable negative = hnsecs < 0;
1898
1899 if (negative)
1900 hnsecs += convert!("hours", "hnsecs")(24);
1901
1902 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
1903 immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
1904 hnsecs = removeUnitsFromHNSecs!"seconds"(hnsecs);
1905
1906 hnsecs += convert!("hours", "hnsecs")(hour);
1907 hnsecs += convert!("minutes", "hnsecs")(minute);
1908 hnsecs += convert!("seconds", "hnsecs")(second);
1909
1910 if (negative)
1911 hnsecs -= convert!("hours", "hnsecs")(24);
1912
1913 adjTime = daysHNSecs + hnsecs;
1914 }
1915
1916 @safe unittest
1917 {
1918 import std.range : chain;
1919
1920 foreach (second; testMinSecs)
1921 {
1922 foreach (st; chain(testSysTimesBC, testSysTimesAD))
1923 {
1924 auto dt = cast(DateTime) st;
1925 auto expected = SysTime(DateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute, second),
1926 st.fracSecs,
1927 st.timezone);
1928 st.second = second;
1929 assert(st == expected, format("[%s] [%s]", st, expected));
1930 }
1931 }
1932
1933 auto st = testSysTimesAD[0];
1934 assertThrown!DateTimeException(st.second = -1);
1935 assertThrown!DateTimeException(st.second = 60);
1936
1937 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1938 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
1939 static assert(!__traits(compiles, cst.seconds = 27));
1940 static assert(!__traits(compiles, ist.seconds = 27));
1941
1942 static void testScope(scope ref SysTime st) @safe
1943 {
1944 st.second = 12;
1945 }
1946 }
1947
1948
1949 /++
1950 Fractional seconds past the second (i.e. the portion of a
1951 $(LREF SysTime) which is less than a second).
1952 +/
1953 @property Duration fracSecs() @safe const nothrow scope
1954 {
1955 auto hnsecs = removeUnitsFromHNSecs!"days"(adjTime);
1956
1957 if (hnsecs < 0)
1958 hnsecs += convert!("hours", "hnsecs")(24);
1959
1960 return dur!"hnsecs"(removeUnitsFromHNSecs!"seconds"(hnsecs));
1961 }
1962
1963 ///
1964 @safe unittest
1965 {
1966 import core.time : msecs, usecs, hnsecs, nsecs;
1967 import std.datetime.date : DateTime;
1968
1969 auto dt = DateTime(1982, 4, 1, 20, 59, 22);
1970 assert(SysTime(dt, msecs(213)).fracSecs == msecs(213));
1971 assert(SysTime(dt, usecs(5202)).fracSecs == usecs(5202));
1972 assert(SysTime(dt, hnsecs(1234567)).fracSecs == hnsecs(1234567));
1973
1974 // SysTime and Duration both have a precision of hnsecs (100 ns),
1975 // so nsecs are going to be truncated.
1976 assert(SysTime(dt, nsecs(123456789)).fracSecs == nsecs(123456700));
1977 }
1978
1979 @safe unittest
1980 {
1981 import std.range : chain;
1982 import core.time;
1983
1984 assert(SysTime(0, UTC()).fracSecs == Duration.zero);
1985 assert(SysTime(1, UTC()).fracSecs == hnsecs(1));
1986 assert(SysTime(-1, UTC()).fracSecs == hnsecs(9_999_999));
1987
1988 foreach (tz; testTZs)
1989 {
1990 foreach (year; chain(testYearsBC, testYearsAD))
1991 {
1992 foreach (md; testMonthDays)
1993 {
1994 foreach (hour; testHours)
1995 {
1996 foreach (minute; testMinSecs)
1997 {
1998 foreach (second; testMinSecs)
1999 {
2000 auto dt = DateTime(Date(year, md.month, md.day), TimeOfDay(hour, minute, second));
2001 foreach (fs; testFracSecs)
2002 assert(SysTime(dt, fs, tz).fracSecs == fs);
2003 }
2004 }
2005 }
2006 }
2007 }
2008 }
2009
2010 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
2011 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
2012 assert(cst.fracSecs == Duration.zero);
2013 assert(ist.fracSecs == Duration.zero);
2014
2015 static void testScope(scope ref SysTime st) @safe
2016 {
2017 auto result = st.fracSecs;
2018 }
2019 }
2020
2021
2022 /++
2023 Fractional seconds past the second (i.e. the portion of a
2024 $(LREF SysTime) which is less than a second).
2025
2026 Params:
2027 fracSecs = The duration to set this $(LREF SysTime)'s fractional
2028 seconds to.
2029
2030 Throws:
2031 $(REF DateTimeException,std,datetime,date) if the given duration
2032 is negative or if it's greater than or equal to one second.
2033 +/
2034 @property void fracSecs(Duration fracSecs) @safe scope
2035 {
2036 enforce(fracSecs >= Duration.zero, new DateTimeException("A SysTime cannot have negative fractional seconds."));
2037 enforce(fracSecs < seconds(1), new DateTimeException("Fractional seconds must be less than one second."));
2038
2039 auto oldHNSecs = adjTime;
2040 auto days = splitUnitsFromHNSecs!"days"(oldHNSecs);
2041 immutable daysHNSecs = convert!("days", "hnsecs")(days);
2042 immutable negative = oldHNSecs < 0;
2043
2044 if (negative)
2045 oldHNSecs += convert!("hours", "hnsecs")(24);
2046
2047 immutable seconds = splitUnitsFromHNSecs!"seconds"(oldHNSecs);
2048 immutable secondsHNSecs = convert!("seconds", "hnsecs")(seconds);
2049 auto newHNSecs = fracSecs.total!"hnsecs" + secondsHNSecs;
2050
2051 if (negative)
2052 newHNSecs -= convert!("hours", "hnsecs")(24);
2053
2054 adjTime = daysHNSecs + newHNSecs;
2055 }
2056
2057 ///
2058 @safe unittest
2059 {
2060 import core.time : Duration, msecs, hnsecs, nsecs;
2061 import std.datetime.date : DateTime;
2062
2063 auto st = SysTime(DateTime(1982, 4, 1, 20, 59, 22));
2064 assert(st.fracSecs == Duration.zero);
2065
2066 st.fracSecs = msecs(213);
2067 assert(st.fracSecs == msecs(213));
2068
2069 st.fracSecs = hnsecs(1234567);
2070 assert(st.fracSecs == hnsecs(1234567));
2071
2072 // SysTime has a precision of hnsecs (100 ns), so nsecs are
2073 // going to be truncated.
2074 st.fracSecs = nsecs(123456789);
2075 assert(st.fracSecs == hnsecs(1234567));
2076 }
2077
2078 @safe unittest
2079 {
2080 import std.range : chain;
2081 import core.time;
2082
2083 foreach (fracSec; testFracSecs)
2084 {
2085 foreach (st; chain(testSysTimesBC, testSysTimesAD))
2086 {
2087 auto dt = cast(DateTime) st;
2088 auto expected = SysTime(dt, fracSec, st.timezone);
2089 st.fracSecs = fracSec;
2090 assert(st == expected, format("[%s] [%s]", st, expected));
2091 }
2092 }
2093
2094 auto st = testSysTimesAD[0];
2095 assertThrown!DateTimeException(st.fracSecs = hnsecs(-1));
2096 assertThrown!DateTimeException(st.fracSecs = seconds(1));
2097
2098 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
2099 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
2100 static assert(!__traits(compiles, cst.fracSecs = msecs(7)));
2101 static assert(!__traits(compiles, ist.fracSecs = msecs(7)));
2102
2103 static void testScope(scope ref SysTime st) @safe
2104 {
2105 st.fracSecs = Duration.zero;
2106 }
2107 }
2108
2109
2110 /++
2111 The total hnsecs from midnight, January 1st, 1 A.D. UTC. This is the
2112 internal representation of $(LREF SysTime).
2113 +/
2114 @property long stdTime() @safe const pure nothrow scope @nogc
2115 {
2116 return _stdTime;
2117 }
2118
2119 @safe unittest
2120 {
2121 import core.time;
2122 assert(SysTime(0).stdTime == 0);
2123 assert(SysTime(1).stdTime == 1);
2124 assert(SysTime(-1).stdTime == -1);
2125 assert(SysTime(DateTime(1, 1, 1, 0, 0, 33), hnsecs(502), UTC()).stdTime == 330_000_502L);
2126 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 0), UTC()).stdTime == 621_355_968_000_000_000L);
2127
2128 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
2129 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
2130 assert(cst.stdTime > 0);
2131 assert(ist.stdTime > 0);
2132
2133 static void testScope(scope ref SysTime st) @safe
2134 {
2135 auto result = st.stdTime;
2136 }
2137 }
2138
2139
2140 /++
2141 The total hnsecs from midnight, January 1st, 1 A.D. UTC. This is the
2142 internal representation of $(LREF SysTime).
2143
2144 Params:
2145 stdTime = The number of hnsecs since January 1st, 1 A.D. UTC.
2146 +/
2147 @property void stdTime(long stdTime) @safe pure nothrow scope
2148 {
2149 _stdTime = stdTime;
2150 }
2151
2152 @safe unittest
2153 {
2154 import core.time;
2155 static void test(long stdTime, SysTime expected, size_t line = __LINE__)
2156 {
2157 auto st = SysTime(0, UTC());
2158 st.stdTime = stdTime;
2159 assert(st == expected);
2160 }
2161
2162 test(0, SysTime(Date(1, 1, 1), UTC()));
2163 test(1, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1), UTC()));
2164 test(-1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()));
2165 test(330_000_502L, SysTime(DateTime(1, 1, 1, 0, 0, 33), hnsecs(502), UTC()));
2166 test(621_355_968_000_000_000L, SysTime(DateTime(1970, 1, 1, 0, 0, 0), UTC()));
2167
2168 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
2169 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
2170 static assert(!__traits(compiles, cst.stdTime = 27));
2171 static assert(!__traits(compiles, ist.stdTime = 27));
2172
2173 static void testScope(scope ref SysTime st) @safe
2174 {
2175 st.stdTime = 42;
2176 }
2177 }
2178
2179
2180 /++
2181 The current time zone of this $(LREF SysTime). Its internal time is
2182 always kept in UTC, so there are no conversion issues between time zones
2183 due to DST. Functions which return all or part of the time - such as
2184 hours - adjust the time to this $(LREF SysTime)'s time zone before
2185 returning.
2186 +/
2187 @property immutable(TimeZone) timezone() @safe const pure nothrow scope
2188 {
2189 return _timezone;
2190 }
2191
2192 @safe unittest
2193 {
2194 assert(SysTime.init.timezone is InitTimeZone());
2195 assert(SysTime(DateTime.init, UTC()).timezone is UTC());
2196
2197 static void testScope(scope ref SysTime st) @safe
2198 {
2199 auto result = st.timezone;
2200 }
2201 }
2202
2203
2204 /++
2205 The current time zone of this $(LREF SysTime). It's internal time is
2206 always kept in UTC, so there are no conversion issues between time zones
2207 due to DST. Functions which return all or part of the time - such as
2208 hours - adjust the time to this $(LREF SysTime)'s time zone before
2209 returning.
2210
2211 Params:
2212 timezone = The $(REF _TimeZone,std,datetime,_timezone) to set this
2213 $(LREF SysTime)'s time zone to.
2214 +/
2215 @property void timezone(immutable TimeZone timezone) @safe pure nothrow scope
2216 {
2217 if (timezone is null)
2218 _timezone = LocalTime();
2219 else
2220 _timezone = timezone;
2221 }
2222
2223 @safe unittest
2224 {
2225 SysTime st;
2226 st.timezone = null;
2227 assert(st.timezone is LocalTime());
2228 st.timezone = UTC();
2229 assert(st.timezone is UTC());
2230
2231 static void testScope(scope ref SysTime st) @safe
2232 {
2233 st.timezone = UTC();
2234 }
2235 }
2236
2237
2238 /++
2239 Returns whether DST is in effect for this $(LREF SysTime).
2240 +/
2241 @property bool dstInEffect() @safe const nothrow scope
2242 {
2243 return _timezone.dstInEffect(_stdTime);
2244 }
2245
2246 // This function's full unit testing is done in the time zone classes, but
2247 // this verifies that SysTime.init works correctly, since historically, it
2248 // has segfaulted due to a null _timezone.
2249 @safe unittest
2250 {
2251 assert(!SysTime.init.dstInEffect);
2252
2253 static void testScope(scope ref SysTime st) @safe
2254 {
2255 auto result = st.dstInEffect;
2256 }
2257 }
2258
2259
2260 /++
2261 Returns what the offset from UTC is for this $(LREF SysTime).
2262 It includes the DST offset in effect at that time (if any).
2263 +/
2264 @property Duration utcOffset() @safe const nothrow scope
2265 {
2266 return _timezone.utcOffsetAt(_stdTime);
2267 }
2268
2269 // This function's full unit testing is done in the time zone classes, but
2270 // this verifies that SysTime.init works correctly, since historically, it
2271 // has segfaulted due to a null _timezone.
2272 @safe unittest
2273 {
2274 assert(SysTime.init.utcOffset == Duration.zero);
2275
2276 static void testScope(scope ref SysTime st) @safe
2277 {
2278 auto result = st.utcOffset;
2279 }
2280 }
2281
2282
2283 /++
2284 Returns a $(LREF SysTime) with the same std time as this one, but with
2285 $(REF LocalTime,std,datetime,timezone) as its time zone.
2286 +/
2287 SysTime toLocalTime() @safe const pure nothrow scope
2288 {
2289 return SysTime(_stdTime, LocalTime());
2290 }
2291
2292 @safe unittest
2293 {
2294 import core.time;
2295 {
2296 auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), hnsecs(27));
2297 assert(sysTime == sysTime.toLocalTime());
2298 assert(sysTime._stdTime == sysTime.toLocalTime()._stdTime);
2299 assert(sysTime.toLocalTime().timezone is LocalTime());
2300 assert(sysTime.toLocalTime().timezone is sysTime.timezone);
2301 assert(sysTime.toLocalTime().timezone !is UTC());
2302 }
2303
2304 {
2305 auto stz = new immutable SimpleTimeZone(dur!"minutes"(-3 * 60));
2306 auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), hnsecs(27), stz);
2307 assert(sysTime == sysTime.toLocalTime());
2308 assert(sysTime._stdTime == sysTime.toLocalTime()._stdTime);
2309 assert(sysTime.toLocalTime().timezone is LocalTime());
2310 assert(sysTime.toLocalTime().timezone !is UTC());
2311 assert(sysTime.toLocalTime().timezone !is stz);
2312 }
2313
2314 static void testScope(scope ref SysTime st) @safe
2315 {
2316 auto result = st.toLocalTime();
2317 }
2318 }
2319
2320
2321 /++
2322 Returns a $(LREF SysTime) with the same std time as this one, but with
2323 `UTC` as its time zone.
2324 +/
2325 SysTime toUTC() @safe const pure nothrow scope
2326 {
2327 return SysTime(_stdTime, UTC());
2328 }
2329
2330 @safe unittest
2331 {
2332 import core.time;
2333 auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), hnsecs(27));
2334 assert(sysTime == sysTime.toUTC());
2335 assert(sysTime._stdTime == sysTime.toUTC()._stdTime);
2336 assert(sysTime.toUTC().timezone is UTC());
2337 assert(sysTime.toUTC().timezone !is LocalTime());
2338 assert(sysTime.toUTC().timezone !is sysTime.timezone);
2339
2340 static void testScope(scope ref SysTime st) @safe
2341 {
2342 auto result = st.toUTC();
2343 }
2344 }
2345
2346
2347 /++
2348 Returns a $(LREF SysTime) with the same std time as this one, but with
2349 given time zone as its time zone.
2350 +/
2351 SysTime toOtherTZ(immutable TimeZone tz) @safe const pure nothrow scope
2352 {
2353 if (tz is null)
2354 return SysTime(_stdTime, LocalTime());
2355 else
2356 return SysTime(_stdTime, tz);
2357 }
2358
2359 @safe unittest
2360 {
2361 import core.time;
2362 auto stz = new immutable SimpleTimeZone(dur!"minutes"(11 * 60));
2363 auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), hnsecs(27));
2364 assert(sysTime == sysTime.toOtherTZ(stz));
2365 assert(sysTime._stdTime == sysTime.toOtherTZ(stz)._stdTime);
2366 assert(sysTime.toOtherTZ(stz).timezone is stz);
2367 assert(sysTime.toOtherTZ(stz).timezone !is LocalTime());
2368 assert(sysTime.toOtherTZ(stz).timezone !is UTC());
2369 assert(sysTime.toOtherTZ(null).timezone is LocalTime());
2370
2371 static void testScope(scope ref SysTime st) @safe
2372 {
2373 auto result = st.toOtherTZ(null);
2374 }
2375 }
2376
2377
2378 /++
2379 Converts this $(LREF SysTime) to unix time (i.e. seconds from midnight,
2380 January 1st, 1970 in UTC).
2381
2382 The C standard does not specify the representation of time_t, so it is
2383 implementation defined. On POSIX systems, unix time is equivalent to
2384 time_t, but that's not necessarily true on other systems (e.g. it is
2385 not true for the Digital Mars C runtime). So, be careful when using unix
2386 time with C functions on non-POSIX systems.
2387
2388 By default, the return type is time_t (which is normally an alias for
2389 int on 32-bit systems and long on 64-bit systems), but if a different
2390 size is required than either int or long can be passed as a template
2391 argument to get the desired size.
2392
2393 If the return type is int, and the result can't fit in an int, then the
2394 closest value that can be held in 32 bits will be used (so `int.max`
2395 if it goes over and `int.min` if it goes under). However, no attempt
2396 is made to deal with integer overflow if the return type is long.
2397
2398 Params:
2399 T = The return type (int or long). It defaults to time_t, which is
2400 normally 32 bits on a 32-bit system and 64 bits on a 64-bit
2401 system.
2402
2403 Returns:
2404 A signed integer representing the unix time which is equivalent to
2405 this SysTime.
2406 +/
2407 T toUnixTime(T = time_t)() @safe const pure nothrow scope
2408 if (is(T == int) || is(T == long))
2409 {
2410 return stdTimeToUnixTime!T(_stdTime);
2411 }
2412
2413 ///
2414 @safe unittest
2415 {
2416 import core.time : hours;
2417 import std.datetime.date : DateTime;
2418 import std.datetime.timezone : SimpleTimeZone, UTC;
2419
2420 assert(SysTime(DateTime(1970, 1, 1), UTC()).toUnixTime() == 0);
2421
2422 auto pst = new immutable SimpleTimeZone(hours(-8));
2423 assert(SysTime(DateTime(1970, 1, 1), pst).toUnixTime() == 28800);
2424
2425 auto utc = SysTime(DateTime(2007, 12, 22, 8, 14, 45), UTC());
2426 assert(utc.toUnixTime() == 1_198_311_285);
2427
2428 auto ca = SysTime(DateTime(2007, 12, 22, 8, 14, 45), pst);
2429 assert(ca.toUnixTime() == 1_198_340_085);
2430
2431 static void testScope(scope ref SysTime st) @safe
2432 {
2433 auto result = st.toUnixTime();
2434 }
2435 }
2436
2437 @safe unittest
2438 {
2439 import std.meta : AliasSeq;
2440 import core.time;
2441 assert(SysTime(DateTime(1970, 1, 1), UTC()).toUnixTime() == 0);
2442 static foreach (units; ["hnsecs", "usecs", "msecs"])
2443 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 0), dur!units(1), UTC()).toUnixTime() == 0);
2444 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), UTC()).toUnixTime() == 1);
2445 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toUnixTime() == 0);
2446 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), usecs(999_999), UTC()).toUnixTime() == 0);
2447 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), msecs(999), UTC()).toUnixTime() == 0);
2448 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), UTC()).toUnixTime() == -1);
2449 }
2450
2451
2452 /++
2453 Converts from unix time (i.e. seconds from midnight, January 1st, 1970
2454 in UTC) to a $(LREF SysTime).
2455
2456 The C standard does not specify the representation of time_t, so it is
2457 implementation defined. On POSIX systems, unix time is equivalent to
2458 time_t, but that's not necessarily true on other systems (e.g. it is
2459 not true for the Digital Mars C runtime). So, be careful when using unix
2460 time with C functions on non-POSIX systems.
2461
2462 Params:
2463 unixTime = Seconds from midnight, January 1st, 1970 in UTC.
2464 tz = The time zone for the SysTime that's returned.
2465 +/
2466 static SysTime fromUnixTime(long unixTime, immutable TimeZone tz = LocalTime()) @safe pure nothrow
2467 {
2468 return SysTime(unixTimeToStdTime(unixTime), tz);
2469 }
2470
2471 ///
2472 @safe unittest
2473 {
2474 import core.time : hours;
2475 import std.datetime.date : DateTime;
2476 import std.datetime.timezone : SimpleTimeZone, UTC;
2477
2478 assert(SysTime.fromUnixTime(0) ==
2479 SysTime(DateTime(1970, 1, 1), UTC()));
2480
2481 auto pst = new immutable SimpleTimeZone(hours(-8));
2482 assert(SysTime.fromUnixTime(28800) ==
2483 SysTime(DateTime(1970, 1, 1), pst));
2484
2485 auto st1 = SysTime.fromUnixTime(1_198_311_285, UTC());
2486 assert(st1 == SysTime(DateTime(2007, 12, 22, 8, 14, 45), UTC()));
2487 assert(st1.timezone is UTC());
2488 assert(st1 == SysTime(DateTime(2007, 12, 22, 0, 14, 45), pst));
2489
2490 auto st2 = SysTime.fromUnixTime(1_198_311_285, pst);
2491 assert(st2 == SysTime(DateTime(2007, 12, 22, 8, 14, 45), UTC()));
2492 assert(st2.timezone is pst);
2493 assert(st2 == SysTime(DateTime(2007, 12, 22, 0, 14, 45), pst));
2494 }
2495
2496 @safe unittest
2497 {
2498 import core.time;
2499 assert(SysTime.fromUnixTime(0) == SysTime(DateTime(1970, 1, 1), UTC()));
2500 assert(SysTime.fromUnixTime(1) == SysTime(DateTime(1970, 1, 1, 0, 0, 1), UTC()));
2501 assert(SysTime.fromUnixTime(-1) == SysTime(DateTime(1969, 12, 31, 23, 59, 59), UTC()));
2502
2503 auto st = SysTime.fromUnixTime(0);
2504 auto dt = cast(DateTime) st;
2505 assert(dt <= DateTime(1970, 2, 1) && dt >= DateTime(1969, 12, 31));
2506 assert(st.timezone is LocalTime());
2507
2508 auto aest = new immutable SimpleTimeZone(hours(10));
2509 assert(SysTime.fromUnixTime(-36000) == SysTime(DateTime(1970, 1, 1), aest));
2510 }
2511
2512
2513 /++
2514 Returns a `timeval` which represents this $(LREF SysTime).
2515
2516 Note that like all conversions in std.datetime, this is a truncating
2517 conversion.
2518
2519 If `timeval.tv_sec` is int, and the result can't fit in an int, then
2520 the closest value that can be held in 32 bits will be used for
2521 `tv_sec`. (so `int.max` if it goes over and `int.min` if it
2522 goes under).
2523 +/
2524 timeval toTimeVal() @safe const pure nothrow scope
2525 {
2526 immutable tv_sec = toUnixTime!(typeof(timeval.tv_sec))();
2527 immutable fracHNSecs = removeUnitsFromHNSecs!"seconds"(_stdTime - 621_355_968_000_000_000L);
2528 immutable tv_usec = cast(typeof(timeval.tv_usec))convert!("hnsecs", "usecs")(fracHNSecs);
2529 return timeval(tv_sec, tv_usec);
2530 }
2531
2532 @safe unittest
2533 {
2534 import core.time;
2535 assert(SysTime(DateTime(1970, 1, 1), UTC()).toTimeVal() == timeval(0, 0));
2536 assert(SysTime(DateTime(1970, 1, 1), hnsecs(9), UTC()).toTimeVal() == timeval(0, 0));
2537 assert(SysTime(DateTime(1970, 1, 1), hnsecs(10), UTC()).toTimeVal() == timeval(0, 1));
2538 assert(SysTime(DateTime(1970, 1, 1), usecs(7), UTC()).toTimeVal() == timeval(0, 7));
2539
2540 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), UTC()).toTimeVal() == timeval(1, 0));
2541 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), hnsecs(9), UTC()).toTimeVal() == timeval(1, 0));
2542 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), hnsecs(10), UTC()).toTimeVal() == timeval(1, 1));
2543 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), usecs(7), UTC()).toTimeVal() == timeval(1, 7));
2544
2545 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toTimeVal() == timeval(0, 0));
2546 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), hnsecs(9_999_990), UTC()).toTimeVal() == timeval(0, -1));
2547
2548 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), usecs(999_999), UTC()).toTimeVal() == timeval(0, -1));
2549 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), usecs(999), UTC()).toTimeVal() == timeval(0, -999_001));
2550 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), msecs(999), UTC()).toTimeVal() == timeval(0, -1000));
2551 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), UTC()).toTimeVal() == timeval(-1, 0));
2552 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 58), usecs(17), UTC()).toTimeVal() == timeval(-1, -999_983));
2553
2554 static void testScope(scope ref SysTime st) @safe
2555 {
2556 auto result = st.toTimeVal();
2557 }
2558 }
2559
2560
2561 version (StdDdoc)
2562 {
2563 version (Windows) private struct timespec {}
2564 /++
2565 Returns a `timespec` which represents this $(LREF SysTime).
2566
2567 $(BLUE This function is Posix-Only.)
2568 +/
2569 timespec toTimeSpec() @safe const pure nothrow scope;
2570 }
2571 else version (Posix)
2572 {
2573 timespec toTimeSpec() @safe const pure nothrow scope
2574 {
2575 immutable tv_sec = toUnixTime!(typeof(timespec.tv_sec))();
2576 immutable fracHNSecs = removeUnitsFromHNSecs!"seconds"(_stdTime - 621_355_968_000_000_000L);
2577 immutable tv_nsec = cast(typeof(timespec.tv_nsec))convert!("hnsecs", "nsecs")(fracHNSecs);
2578 return timespec(tv_sec, tv_nsec);
2579 }
2580
2581 @safe unittest
2582 {
2583 import core.time;
2584 assert(SysTime(DateTime(1970, 1, 1), UTC()).toTimeSpec() == timespec(0, 0));
2585 assert(SysTime(DateTime(1970, 1, 1), hnsecs(9), UTC()).toTimeSpec() == timespec(0, 900));
2586 assert(SysTime(DateTime(1970, 1, 1), hnsecs(10), UTC()).toTimeSpec() == timespec(0, 1000));
2587 assert(SysTime(DateTime(1970, 1, 1), usecs(7), UTC()).toTimeSpec() == timespec(0, 7000));
2588
2589 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), UTC()).toTimeSpec() == timespec(1, 0));
2590 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), hnsecs(9), UTC()).toTimeSpec() == timespec(1, 900));
2591 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), hnsecs(10), UTC()).toTimeSpec() == timespec(1, 1000));
2592 assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), usecs(7), UTC()).toTimeSpec() == timespec(1, 7000));
2593
2594 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toTimeSpec() ==
2595 timespec(0, -100));
2596 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), hnsecs(9_999_990), UTC()).toTimeSpec() ==
2597 timespec(0, -1000));
2598
2599 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), usecs(999_999), UTC()).toTimeSpec() ==
2600 timespec(0, -1_000));
2601 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), usecs(999), UTC()).toTimeSpec() ==
2602 timespec(0, -999_001_000));
2603 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), msecs(999), UTC()).toTimeSpec() ==
2604 timespec(0, -1_000_000));
2605 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), UTC()).toTimeSpec() ==
2606 timespec(-1, 0));
2607 assert(SysTime(DateTime(1969, 12, 31, 23, 59, 58), usecs(17), UTC()).toTimeSpec() ==
2608 timespec(-1, -999_983_000));
2609
2610 static void testScope(scope ref SysTime st) @safe
2611 {
2612 auto result = st.toTimeSpec();
2613 }
2614 }
2615 }
2616
2617 /++
2618 Returns a `tm` which represents this $(LREF SysTime).
2619 +/
2620 tm toTM() @safe const nothrow scope
2621 {
2622 auto dateTime = cast(DateTime) this;
2623 tm timeInfo;
2624
2625 timeInfo.tm_sec = dateTime.second;
2626 timeInfo.tm_min = dateTime.minute;
2627 timeInfo.tm_hour = dateTime.hour;
2628 timeInfo.tm_mday = dateTime.day;
2629 timeInfo.tm_mon = dateTime.month - 1;
2630 timeInfo.tm_year = dateTime.year - 1900;
2631 timeInfo.tm_wday = dateTime.dayOfWeek;
2632 timeInfo.tm_yday = dateTime.dayOfYear - 1;
2633 timeInfo.tm_isdst = _timezone.dstInEffect(_stdTime);
2634
2635 version (Posix)
2636 {
2637 import std.utf : toUTFz;
2638 timeInfo.tm_gmtoff = cast(int) convert!("hnsecs", "seconds")(adjTime - _stdTime);
2639 auto zone = timeInfo.tm_isdst ? _timezone.dstName : _timezone.stdName;
2640 timeInfo.tm_zone = zone.toUTFz!(char*)();
2641 }
2642
2643 return timeInfo;
2644 }
2645
2646 @system unittest
2647 {
2648 import std.conv : to;
2649 import core.time;
2650
2651 version (Posix)
2652 {
2653 import std.datetime.timezone : clearTZEnvVar, setTZEnvVar;
2654 setTZEnvVar("America/Los_Angeles");
2655 scope(exit) clearTZEnvVar();
2656 }
2657
2658 {
2659 auto timeInfo = SysTime(DateTime(1970, 1, 1)).toTM();
2660
2661 assert(timeInfo.tm_sec == 0);
2662 assert(timeInfo.tm_min == 0);
2663 assert(timeInfo.tm_hour == 0);
2664 assert(timeInfo.tm_mday == 1);
2665 assert(timeInfo.tm_mon == 0);
2666 assert(timeInfo.tm_year == 70);
2667 assert(timeInfo.tm_wday == 4);
2668 assert(timeInfo.tm_yday == 0);
2669
2670 version (Posix)
2671 assert(timeInfo.tm_isdst == 0);
2672 else version (Windows)
2673 assert(timeInfo.tm_isdst == 0 || timeInfo.tm_isdst == 1);
2674
2675 version (Posix)
2676 {
2677 assert(timeInfo.tm_gmtoff == -8 * 60 * 60);
2678 assert(to!string(timeInfo.tm_zone) == "PST");
2679 }
2680 }
2681
2682 {
2683 auto timeInfo = SysTime(DateTime(2010, 7, 4, 12, 15, 7), hnsecs(15)).toTM();
2684
2685 assert(timeInfo.tm_sec == 7);
2686 assert(timeInfo.tm_min == 15);
2687 assert(timeInfo.tm_hour == 12);
2688 assert(timeInfo.tm_mday == 4);
2689 assert(timeInfo.tm_mon == 6);
2690 assert(timeInfo.tm_year == 110);
2691 assert(timeInfo.tm_wday == 0);
2692 assert(timeInfo.tm_yday == 184);
2693
2694 version (Posix)
2695 assert(timeInfo.tm_isdst == 1);
2696 else version (Windows)
2697 assert(timeInfo.tm_isdst == 0 || timeInfo.tm_isdst == 1);
2698
2699 version (Posix)
2700 {
2701 assert(timeInfo.tm_gmtoff == -7 * 60 * 60);
2702 assert(to!string(timeInfo.tm_zone) == "PDT");
2703 }
2704 }
2705
2706 // This is more to verify that SysTime.init.toTM() doesn't segfault and
2707 // does something sane rather than that the value is anything
2708 // particularly useful.
2709 {
2710 auto timeInfo = SysTime.init.toTM();
2711
2712 assert(timeInfo.tm_sec == 0);
2713 assert(timeInfo.tm_min == 0);
2714 assert(timeInfo.tm_hour == 0);
2715 assert(timeInfo.tm_mday == 1);
2716 assert(timeInfo.tm_mon == 0);
2717 assert(timeInfo.tm_year == -1899);
2718 assert(timeInfo.tm_wday == 1);
2719 assert(timeInfo.tm_yday == 0);
2720 assert(timeInfo.tm_isdst == 0);
2721
2722 version (Posix)
2723 {
2724 assert(timeInfo.tm_gmtoff == 0);
2725 assert(to!string(timeInfo.tm_zone) == "SysTime.init's timezone");
2726 }
2727 }
2728
2729 static void testScope(scope ref SysTime st) @safe
2730 {
2731 auto result = st.toTM();
2732 }
2733 }
2734
2735
2736 /++
2737 Adds the given number of years or months to this $(LREF SysTime). A
2738 negative number will subtract.
2739
2740 Note that if day overflow is allowed, and the date with the adjusted
2741 year/month overflows the number of days in the new month, then the month
2742 will be incremented by one, and the day set to the number of days
2743 overflowed. (e.g. if the day were 31 and the new month were June, then
2744 the month would be incremented to July, and the new day would be 1). If
2745 day overflow is not allowed, then the day will be set to the last valid
2746 day in the month (e.g. June 31st would become June 30th).
2747
2748 Params:
2749 units = The type of units to add ("years" or "months").
2750 value = The number of months or years to add to this
2751 $(LREF SysTime).
2752 allowOverflow = Whether the days should be allowed to overflow,
2753 causing the month to increment.
2754 +/
2755 ref SysTime add(string units)(long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) @safe nothrow scope
2756 if (units == "years" || units == "months")
2757 {
2758 auto hnsecs = adjTime;
2759 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
2760
2761 if (hnsecs < 0)
2762 {
2763 hnsecs += convert!("hours", "hnsecs")(24);
2764 --days;
2765 }
2766
2767 auto date = Date(cast(int) days);
2768 date.add!units(value, allowOverflow);
2769 days = date.dayOfGregorianCal - 1;
2770
2771 if (days < 0)
2772 {
2773 hnsecs -= convert!("hours", "hnsecs")(24);
2774 ++days;
2775 }
2776
2777 immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
2778
2779 adjTime = newDaysHNSecs + hnsecs;
2780
2781 return this;
2782 }
2783
2784 @safe unittest
2785 {
2786 auto st1 = SysTime(DateTime(2010, 1, 1, 12, 30, 33));
2787 st1.add!"months"(11);
2788 assert(st1 == SysTime(DateTime(2010, 12, 1, 12, 30, 33)));
2789
2790 auto st2 = SysTime(DateTime(2010, 1, 1, 12, 30, 33));
2791 st2.add!"months"(-11);
2792 assert(st2 == SysTime(DateTime(2009, 2, 1, 12, 30, 33)));
2793
2794 auto st3 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
2795 st3.add!"years"(1);
2796 assert(st3 == SysTime(DateTime(2001, 3, 1, 12, 30, 33)));
2797
2798 auto st4 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
2799 st4.add!"years"(1, AllowDayOverflow.no);
2800 assert(st4 == SysTime(DateTime(2001, 2, 28, 12, 30, 33)));
2801 }
2802
2803 // Test add!"years"() with AllowDayOverflow.yes
2804 @safe unittest
2805 {
2806 import core.time;
2807 // Test A.D.
2808 {
2809 auto sysTime = SysTime(Date(1999, 7, 6));
2810 sysTime.add!"years"(7);
2811 assert(sysTime == SysTime(Date(2006, 7, 6)));
2812 sysTime.add!"years"(-9);
2813 assert(sysTime == SysTime(Date(1997, 7, 6)));
2814 }
2815
2816 {
2817 auto sysTime = SysTime(Date(1999, 2, 28));
2818 sysTime.add!"years"(1);
2819 assert(sysTime == SysTime(Date(2000, 2, 28)));
2820 }
2821
2822 {
2823 auto sysTime = SysTime(Date(2000, 2, 29));
2824 sysTime.add!"years"(-1);
2825 assert(sysTime == SysTime(Date(1999, 3, 1)));
2826 }
2827
2828 {
2829 auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 7, 3), msecs(234));
2830 sysTime.add!"years"(7);
2831 assert(sysTime == SysTime(DateTime(2006, 7, 6, 12, 7, 3), msecs(234)));
2832 sysTime.add!"years"(-9);
2833 assert(sysTime == SysTime(DateTime(1997, 7, 6, 12, 7, 3), msecs(234)));
2834 }
2835
2836 {
2837 auto sysTime = SysTime(DateTime(1999, 2, 28, 0, 7, 2), usecs(1207));
2838 sysTime.add!"years"(1);
2839 assert(sysTime == SysTime(DateTime(2000, 2, 28, 0, 7, 2), usecs(1207)));
2840 }
2841
2842 {
2843 auto sysTime = SysTime(DateTime(2000, 2, 29, 0, 7, 2), usecs(1207));
2844 sysTime.add!"years"(-1);
2845 assert(sysTime == SysTime(DateTime(1999, 3, 1, 0, 7, 2), usecs(1207)));
2846 }
2847
2848 // Test B.C.
2849 {
2850 auto sysTime = SysTime(Date(-1999, 7, 6));
2851 sysTime.add!"years"(-7);
2852 assert(sysTime == SysTime(Date(-2006, 7, 6)));
2853 sysTime.add!"years"(9);
2854 assert(sysTime == SysTime(Date(-1997, 7, 6)));
2855 }
2856
2857 {
2858 auto sysTime = SysTime(Date(-1999, 2, 28));
2859 sysTime.add!"years"(-1);
2860 assert(sysTime == SysTime(Date(-2000, 2, 28)));
2861 }
2862
2863 {
2864 auto sysTime = SysTime(Date(-2000, 2, 29));
2865 sysTime.add!"years"(1);
2866 assert(sysTime == SysTime(Date(-1999, 3, 1)));
2867 }
2868
2869 {
2870 auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 7, 3), msecs(234));
2871 sysTime.add!"years"(-7);
2872 assert(sysTime == SysTime(DateTime(-2006, 7, 6, 12, 7, 3), msecs(234)));
2873 sysTime.add!"years"(9);
2874 assert(sysTime == SysTime(DateTime(-1997, 7, 6, 12, 7, 3), msecs(234)));
2875 }
2876
2877 {
2878 auto sysTime = SysTime(DateTime(-1999, 2, 28, 3, 3, 3), hnsecs(3));
2879 sysTime.add!"years"(-1);
2880 assert(sysTime == SysTime(DateTime(-2000, 2, 28, 3, 3, 3), hnsecs(3)));
2881 }
2882
2883 {
2884 auto sysTime = SysTime(DateTime(-2000, 2, 29, 3, 3, 3), hnsecs(3));
2885 sysTime.add!"years"(1);
2886 assert(sysTime == SysTime(DateTime(-1999, 3, 1, 3, 3, 3), hnsecs(3)));
2887 }
2888
2889 // Test Both
2890 {
2891 auto sysTime = SysTime(Date(4, 7, 6));
2892 sysTime.add!"years"(-5);
2893 assert(sysTime == SysTime(Date(-1, 7, 6)));
2894 sysTime.add!"years"(5);
2895 assert(sysTime == SysTime(Date(4, 7, 6)));
2896 }
2897
2898 {
2899 auto sysTime = SysTime(Date(-4, 7, 6));
2900 sysTime.add!"years"(5);
2901 assert(sysTime == SysTime(Date(1, 7, 6)));
2902 sysTime.add!"years"(-5);
2903 assert(sysTime == SysTime(Date(-4, 7, 6)));
2904 }
2905
2906 {
2907 auto sysTime = SysTime(Date(4, 7, 6));
2908 sysTime.add!"years"(-8);
2909 assert(sysTime == SysTime(Date(-4, 7, 6)));
2910 sysTime.add!"years"(8);
2911 assert(sysTime == SysTime(Date(4, 7, 6)));
2912 }
2913
2914 {
2915 auto sysTime = SysTime(Date(-4, 7, 6));
2916 sysTime.add!"years"(8);
2917 assert(sysTime == SysTime(Date(4, 7, 6)));
2918 sysTime.add!"years"(-8);
2919 assert(sysTime == SysTime(Date(-4, 7, 6)));
2920 }
2921
2922 {
2923 auto sysTime = SysTime(Date(-4, 2, 29));
2924 sysTime.add!"years"(5);
2925 assert(sysTime == SysTime(Date(1, 3, 1)));
2926 }
2927
2928 {
2929 auto sysTime = SysTime(Date(4, 2, 29));
2930 sysTime.add!"years"(-5);
2931 assert(sysTime == SysTime(Date(-1, 3, 1)));
2932 }
2933
2934 {
2935 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
2936 sysTime.add!"years"(-1);
2937 assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0)));
2938 sysTime.add!"years"(1);
2939 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
2940 }
2941
2942 {
2943 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
2944 sysTime.add!"years"(-1);
2945 assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
2946 sysTime.add!"years"(1);
2947 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
2948 }
2949
2950 {
2951 auto sysTime = SysTime(DateTime(0, 1, 1, 0, 0, 0));
2952 sysTime.add!"years"(1);
2953 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
2954 sysTime.add!"years"(-1);
2955 assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0)));
2956 }
2957
2958 {
2959 auto sysTime = SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999));
2960 sysTime.add!"years"(1);
2961 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
2962 sysTime.add!"years"(-1);
2963 assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
2964 }
2965
2966 {
2967 auto sysTime = SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329));
2968 sysTime.add!"years"(-5);
2969 assert(sysTime == SysTime(DateTime(-1, 7, 6, 14, 7, 1), usecs(54329)));
2970 sysTime.add!"years"(5);
2971 assert(sysTime == SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329)));
2972 }
2973
2974 {
2975 auto sysTime = SysTime(DateTime(-4, 7, 6, 14, 7, 1), usecs(54329));
2976 sysTime.add!"years"(5);
2977 assert(sysTime == SysTime(DateTime(1, 7, 6, 14, 7, 1), usecs(54329)));
2978 sysTime.add!"years"(-5);
2979 assert(sysTime == SysTime(DateTime(-4, 7, 6, 14, 7, 1), usecs(54329)));
2980 }
2981
2982 {
2983 auto sysTime = SysTime(DateTime(-4, 2, 29, 5, 5, 5), msecs(555));
2984 sysTime.add!"years"(5);
2985 assert(sysTime == SysTime(DateTime(1, 3, 1, 5, 5, 5), msecs(555)));
2986 }
2987
2988 {
2989 auto sysTime = SysTime(DateTime(4, 2, 29, 5, 5, 5), msecs(555));
2990 sysTime.add!"years"(-5);
2991 assert(sysTime == SysTime(DateTime(-1, 3, 1, 5, 5, 5), msecs(555)));
2992 }
2993
2994 {
2995 auto sysTime = SysTime(DateTime(4, 2, 29, 5, 5, 5), msecs(555));
2996 sysTime.add!"years"(-5).add!"years"(7);
2997 assert(sysTime == SysTime(DateTime(6, 3, 1, 5, 5, 5), msecs(555)));
2998 }
2999
3000 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
3001 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
3002 static assert(!__traits(compiles, cst.add!"years"(4)));
3003 static assert(!__traits(compiles, ist.add!"years"(4)));
3004
3005 static void testScope(scope ref SysTime st) @safe
3006 {
3007 auto result = st.add!"years"(42);
3008 }
3009 }
3010
3011 // Test add!"years"() with AllowDayOverflow.no
3012 @safe unittest
3013 {
3014 import core.time;
3015 // Test A.D.
3016 {
3017 auto sysTime = SysTime(Date(1999, 7, 6));
3018 sysTime.add!"years"(7, AllowDayOverflow.no);
3019 assert(sysTime == SysTime(Date(2006, 7, 6)));
3020 sysTime.add!"years"(-9, AllowDayOverflow.no);
3021 assert(sysTime == SysTime(Date(1997, 7, 6)));
3022 }
3023
3024 {
3025 auto sysTime = SysTime(Date(1999, 2, 28));
3026 sysTime.add!"years"(1, AllowDayOverflow.no);
3027 assert(sysTime == SysTime(Date(2000, 2, 28)));
3028 }
3029
3030 {
3031 auto sysTime = SysTime(Date(2000, 2, 29));
3032 sysTime.add!"years"(-1, AllowDayOverflow.no);
3033 assert(sysTime == SysTime(Date(1999, 2, 28)));
3034 }
3035
3036 {
3037 auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 7, 3), msecs(234));
3038 sysTime.add!"years"(7, AllowDayOverflow.no);
3039 assert(sysTime == SysTime(DateTime(2006, 7, 6, 12, 7, 3), msecs(234)));
3040 sysTime.add!"years"(-9, AllowDayOverflow.no);
3041 assert(sysTime == SysTime(DateTime(1997, 7, 6, 12, 7, 3), msecs(234)));
3042 }
3043
3044 {
3045 auto sysTime = SysTime(DateTime(1999, 2, 28, 0, 7, 2), usecs(1207));
3046 sysTime.add!"years"(1, AllowDayOverflow.no);
3047 assert(sysTime == SysTime(DateTime(2000, 2, 28, 0, 7, 2), usecs(1207)));
3048 }
3049
3050 {
3051 auto sysTime = SysTime(DateTime(2000, 2, 29, 0, 7, 2), usecs(1207));
3052 sysTime.add!"years"(-1, AllowDayOverflow.no);
3053 assert(sysTime == SysTime(DateTime(1999, 2, 28, 0, 7, 2), usecs(1207)));
3054 }
3055
3056 // Test B.C.
3057 {
3058 auto sysTime = SysTime(Date(-1999, 7, 6));
3059 sysTime.add!"years"(-7, AllowDayOverflow.no);
3060 assert(sysTime == SysTime(Date(-2006, 7, 6)));
3061 sysTime.add!"years"(9, AllowDayOverflow.no);
3062 assert(sysTime == SysTime(Date(-1997, 7, 6)));
3063 }
3064
3065 {
3066 auto sysTime = SysTime(Date(-1999, 2, 28));
3067 sysTime.add!"years"(-1, AllowDayOverflow.no);
3068 assert(sysTime == SysTime(Date(-2000, 2, 28)));
3069 }
3070
3071 {
3072 auto sysTime = SysTime(Date(-2000, 2, 29));
3073 sysTime.add!"years"(1, AllowDayOverflow.no);
3074 assert(sysTime == SysTime(Date(-1999, 2, 28)));
3075 }
3076
3077 {
3078 auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 7, 3), msecs(234));
3079 sysTime.add!"years"(-7, AllowDayOverflow.no);
3080 assert(sysTime == SysTime(DateTime(-2006, 7, 6, 12, 7, 3), msecs(234)));
3081 sysTime.add!"years"(9, AllowDayOverflow.no);
3082 assert(sysTime == SysTime(DateTime(-1997, 7, 6, 12, 7, 3), msecs(234)));
3083 }
3084
3085 {
3086 auto sysTime = SysTime(DateTime(-1999, 2, 28, 3, 3, 3), hnsecs(3));
3087 sysTime.add!"years"(-1, AllowDayOverflow.no);
3088 assert(sysTime == SysTime(DateTime(-2000, 2, 28, 3, 3, 3), hnsecs(3)));
3089 }
3090
3091 {
3092 auto sysTime = SysTime(DateTime(-2000, 2, 29, 3, 3, 3), hnsecs(3));
3093 sysTime.add!"years"(1, AllowDayOverflow.no);
3094 assert(sysTime == SysTime(DateTime(-1999, 2, 28, 3, 3, 3), hnsecs(3)));
3095 }
3096
3097 // Test Both
3098 {
3099 auto sysTime = SysTime(Date(4, 7, 6));
3100 sysTime.add!"years"(-5, AllowDayOverflow.no);
3101 assert(sysTime == SysTime(Date(-1, 7, 6)));
3102 sysTime.add!"years"(5, AllowDayOverflow.no);
3103 assert(sysTime == SysTime(Date(4, 7, 6)));
3104 }
3105
3106 {
3107 auto sysTime = SysTime(Date(-4, 7, 6));
3108 sysTime.add!"years"(5, AllowDayOverflow.no);
3109 assert(sysTime == SysTime(Date(1, 7, 6)));
3110 sysTime.add!"years"(-5, AllowDayOverflow.no);
3111 assert(sysTime == SysTime(Date(-4, 7, 6)));
3112 }
3113
3114 {
3115 auto sysTime = SysTime(Date(4, 7, 6));
3116 sysTime.add!"years"(-8, AllowDayOverflow.no);
3117 assert(sysTime == SysTime(Date(-4, 7, 6)));
3118 sysTime.add!"years"(8, AllowDayOverflow.no);
3119 assert(sysTime == SysTime(Date(4, 7, 6)));
3120 }
3121
3122 {
3123 auto sysTime = SysTime(Date(-4, 7, 6));
3124 sysTime.add!"years"(8, AllowDayOverflow.no);
3125 assert(sysTime == SysTime(Date(4, 7, 6)));
3126 sysTime.add!"years"(-8, AllowDayOverflow.no);
3127 assert(sysTime == SysTime(Date(-4, 7, 6)));
3128 }
3129
3130 {
3131 auto sysTime = SysTime(Date(-4, 2, 29));
3132 sysTime.add!"years"(5, AllowDayOverflow.no);
3133 assert(sysTime == SysTime(Date(1, 2, 28)));
3134 }
3135
3136 {
3137 auto sysTime = SysTime(Date(4, 2, 29));
3138 sysTime.add!"years"(-5, AllowDayOverflow.no);
3139 assert(sysTime == SysTime(Date(-1, 2, 28)));
3140 }
3141
3142 {
3143 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
3144 sysTime.add!"years"(-1, AllowDayOverflow.no);
3145 assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0)));
3146 sysTime.add!"years"(1, AllowDayOverflow.no);
3147 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
3148 }
3149
3150 {
3151 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
3152 sysTime.add!"years"(-1, AllowDayOverflow.no);
3153 assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3154 sysTime.add!"years"(1, AllowDayOverflow.no);
3155 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3156 }
3157
3158 {
3159 auto sysTime = SysTime(DateTime(0, 1, 1, 0, 0, 0));
3160 sysTime.add!"years"(1, AllowDayOverflow.no);
3161 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
3162 sysTime.add!"years"(-1, AllowDayOverflow.no);
3163 assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0)));
3164 }
3165
3166 {
3167 auto sysTime = SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999));
3168 sysTime.add!"years"(1, AllowDayOverflow.no);
3169 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3170 sysTime.add!"years"(-1, AllowDayOverflow.no);
3171 assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3172 }
3173
3174 {
3175 auto sysTime = SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329));
3176 sysTime.add!"years"(-5);
3177 assert(sysTime == SysTime(DateTime(-1, 7, 6, 14, 7, 1), usecs(54329)));
3178 sysTime.add!"years"(5);
3179 assert(sysTime == SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329)));
3180 }
3181
3182 {
3183 auto sysTime = SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329));
3184 sysTime.add!"years"(-5, AllowDayOverflow.no);
3185 assert(sysTime == SysTime(DateTime(-1, 7, 6, 14, 7, 1), usecs(54329)));
3186 sysTime.add!"years"(5, AllowDayOverflow.no);
3187 assert(sysTime == SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329)));
3188 }
3189
3190 {
3191 auto sysTime = SysTime(DateTime(-4, 7, 6, 14, 7, 1), usecs(54329));
3192 sysTime.add!"years"(5, AllowDayOverflow.no);
3193 assert(sysTime == SysTime(DateTime(1, 7, 6, 14, 7, 1), usecs(54329)));
3194 sysTime.add!"years"(-5, AllowDayOverflow.no);
3195 assert(sysTime == SysTime(DateTime(-4, 7, 6, 14, 7, 1), usecs(54329)));
3196 }
3197
3198 {
3199 auto sysTime = SysTime(DateTime(-4, 2, 29, 5, 5, 5), msecs(555));
3200 sysTime.add!"years"(5, AllowDayOverflow.no);
3201 assert(sysTime == SysTime(DateTime(1, 2, 28, 5, 5, 5), msecs(555)));
3202 }
3203
3204 {
3205 auto sysTime = SysTime(DateTime(4, 2, 29, 5, 5, 5), msecs(555));
3206 sysTime.add!"years"(-5, AllowDayOverflow.no);
3207 assert(sysTime == SysTime(DateTime(-1, 2, 28, 5, 5, 5), msecs(555)));
3208 }
3209
3210 {
3211 auto sysTime = SysTime(DateTime(4, 2, 29, 5, 5, 5), msecs(555));
3212 sysTime.add!"years"(-5, AllowDayOverflow.no).add!"years"(7, AllowDayOverflow.no);
3213 assert(sysTime == SysTime(DateTime(6, 2, 28, 5, 5, 5), msecs(555)));
3214 }
3215 }
3216
3217 // Test add!"months"() with AllowDayOverflow.yes
3218 @safe unittest
3219 {
3220 import core.time;
3221 // Test A.D.
3222 {
3223 auto sysTime = SysTime(Date(1999, 7, 6));
3224 sysTime.add!"months"(3);
3225 assert(sysTime == SysTime(Date(1999, 10, 6)));
3226 sysTime.add!"months"(-4);
3227 assert(sysTime == SysTime(Date(1999, 6, 6)));
3228 }
3229
3230 {
3231 auto sysTime = SysTime(Date(1999, 7, 6));
3232 sysTime.add!"months"(6);
3233 assert(sysTime == SysTime(Date(2000, 1, 6)));
3234 sysTime.add!"months"(-6);
3235 assert(sysTime == SysTime(Date(1999, 7, 6)));
3236 }
3237
3238 {
3239 auto sysTime = SysTime(Date(1999, 7, 6));
3240 sysTime.add!"months"(27);
3241 assert(sysTime == SysTime(Date(2001, 10, 6)));
3242 sysTime.add!"months"(-28);
3243 assert(sysTime == SysTime(Date(1999, 6, 6)));
3244 }
3245
3246 {
3247 auto sysTime = SysTime(Date(1999, 5, 31));
3248 sysTime.add!"months"(1);
3249 assert(sysTime == SysTime(Date(1999, 7, 1)));
3250 }
3251
3252 {
3253 auto sysTime = SysTime(Date(1999, 5, 31));
3254 sysTime.add!"months"(-1);
3255 assert(sysTime == SysTime(Date(1999, 5, 1)));
3256 }
3257
3258 {
3259 auto sysTime = SysTime(Date(1999, 2, 28));
3260 sysTime.add!"months"(12);
3261 assert(sysTime == SysTime(Date(2000, 2, 28)));
3262 }
3263
3264 {
3265 auto sysTime = SysTime(Date(2000, 2, 29));
3266 sysTime.add!"months"(12);
3267 assert(sysTime == SysTime(Date(2001, 3, 1)));
3268 }
3269
3270 {
3271 auto sysTime = SysTime(Date(1999, 7, 31));
3272 sysTime.add!"months"(1);
3273 assert(sysTime == SysTime(Date(1999, 8, 31)));
3274 sysTime.add!"months"(1);
3275 assert(sysTime == SysTime(Date(1999, 10, 1)));
3276 }
3277
3278 {
3279 auto sysTime = SysTime(Date(1998, 8, 31));
3280 sysTime.add!"months"(13);
3281 assert(sysTime == SysTime(Date(1999, 10, 1)));
3282 sysTime.add!"months"(-13);
3283 assert(sysTime == SysTime(Date(1998, 9, 1)));
3284 }
3285
3286 {
3287 auto sysTime = SysTime(Date(1997, 12, 31));
3288 sysTime.add!"months"(13);
3289 assert(sysTime == SysTime(Date(1999, 1, 31)));
3290 sysTime.add!"months"(-13);
3291 assert(sysTime == SysTime(Date(1997, 12, 31)));
3292 }
3293
3294 {
3295 auto sysTime = SysTime(Date(1997, 12, 31));
3296 sysTime.add!"months"(14);
3297 assert(sysTime == SysTime(Date(1999, 3, 3)));
3298 sysTime.add!"months"(-14);
3299 assert(sysTime == SysTime(Date(1998, 1, 3)));
3300 }
3301
3302 {
3303 auto sysTime = SysTime(Date(1998, 12, 31));
3304 sysTime.add!"months"(14);
3305 assert(sysTime == SysTime(Date(2000, 3, 2)));
3306 sysTime.add!"months"(-14);
3307 assert(sysTime == SysTime(Date(1999, 1, 2)));
3308 }
3309
3310 {
3311 auto sysTime = SysTime(Date(1999, 12, 31));
3312 sysTime.add!"months"(14);
3313 assert(sysTime == SysTime(Date(2001, 3, 3)));
3314 sysTime.add!"months"(-14);
3315 assert(sysTime == SysTime(Date(2000, 1, 3)));
3316 }
3317
3318 {
3319 auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), usecs(5007));
3320 sysTime.add!"months"(3);
3321 assert(sysTime == SysTime(DateTime(1999, 10, 6, 12, 2, 7), usecs(5007)));
3322 sysTime.add!"months"(-4);
3323 assert(sysTime == SysTime(DateTime(1999, 6, 6, 12, 2, 7), usecs(5007)));
3324 }
3325
3326 {
3327 auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), hnsecs(422202));
3328 sysTime.add!"months"(14);
3329 assert(sysTime == SysTime(DateTime(2000, 3, 2, 7, 7, 7), hnsecs(422202)));
3330 sysTime.add!"months"(-14);
3331 assert(sysTime == SysTime(DateTime(1999, 1, 2, 7, 7, 7), hnsecs(422202)));
3332 }
3333
3334 {
3335 auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), hnsecs(422202));
3336 sysTime.add!"months"(14);
3337 assert(sysTime == SysTime(DateTime(2001, 3, 3, 7, 7, 7), hnsecs(422202)));
3338 sysTime.add!"months"(-14);
3339 assert(sysTime == SysTime(DateTime(2000, 1, 3, 7, 7, 7), hnsecs(422202)));
3340 }
3341
3342 // Test B.C.
3343 {
3344 auto sysTime = SysTime(Date(-1999, 7, 6));
3345 sysTime.add!"months"(3);
3346 assert(sysTime == SysTime(Date(-1999, 10, 6)));
3347 sysTime.add!"months"(-4);
3348 assert(sysTime == SysTime(Date(-1999, 6, 6)));
3349 }
3350
3351 {
3352 auto sysTime = SysTime(Date(-1999, 7, 6));
3353 sysTime.add!"months"(6);
3354 assert(sysTime == SysTime(Date(-1998, 1, 6)));
3355 sysTime.add!"months"(-6);
3356 assert(sysTime == SysTime(Date(-1999, 7, 6)));
3357 }
3358
3359 {
3360 auto sysTime = SysTime(Date(-1999, 7, 6));
3361 sysTime.add!"months"(-27);
3362 assert(sysTime == SysTime(Date(-2001, 4, 6)));
3363 sysTime.add!"months"(28);
3364 assert(sysTime == SysTime(Date(-1999, 8, 6)));
3365 }
3366
3367 {
3368 auto sysTime = SysTime(Date(-1999, 5, 31));
3369 sysTime.add!"months"(1);
3370 assert(sysTime == SysTime(Date(-1999, 7, 1)));
3371 }
3372
3373 {
3374 auto sysTime = SysTime(Date(-1999, 5, 31));
3375 sysTime.add!"months"(-1);
3376 assert(sysTime == SysTime(Date(-1999, 5, 1)));
3377 }
3378
3379 {
3380 auto sysTime = SysTime(Date(-1999, 2, 28));
3381 sysTime.add!"months"(-12);
3382 assert(sysTime == SysTime(Date(-2000, 2, 28)));
3383 }
3384
3385 {
3386 auto sysTime = SysTime(Date(-2000, 2, 29));
3387 sysTime.add!"months"(-12);
3388 assert(sysTime == SysTime(Date(-2001, 3, 1)));
3389 }
3390
3391 {
3392 auto sysTime = SysTime(Date(-1999, 7, 31));
3393 sysTime.add!"months"(1);
3394 assert(sysTime == SysTime(Date(-1999, 8, 31)));
3395 sysTime.add!"months"(1);
3396 assert(sysTime == SysTime(Date(-1999, 10, 1)));
3397 }
3398
3399 {
3400 auto sysTime = SysTime(Date(-1998, 8, 31));
3401 sysTime.add!"months"(13);
3402 assert(sysTime == SysTime(Date(-1997, 10, 1)));
3403 sysTime.add!"months"(-13);
3404 assert(sysTime == SysTime(Date(-1998, 9, 1)));
3405 }
3406
3407 {
3408 auto sysTime = SysTime(Date(-1997, 12, 31));
3409 sysTime.add!"months"(13);
3410 assert(sysTime == SysTime(Date(-1995, 1, 31)));
3411 sysTime.add!"months"(-13);
3412 assert(sysTime == SysTime(Date(-1997, 12, 31)));
3413 }
3414
3415 {
3416 auto sysTime = SysTime(Date(-1997, 12, 31));
3417 sysTime.add!"months"(14);
3418 assert(sysTime == SysTime(Date(-1995, 3, 3)));
3419 sysTime.add!"months"(-14);
3420 assert(sysTime == SysTime(Date(-1996, 1, 3)));
3421 }
3422
3423 {
3424 auto sysTime = SysTime(Date(-2002, 12, 31));
3425 sysTime.add!"months"(14);
3426 assert(sysTime == SysTime(Date(-2000, 3, 2)));
3427 sysTime.add!"months"(-14);
3428 assert(sysTime == SysTime(Date(-2001, 1, 2)));
3429 }
3430
3431 {
3432 auto sysTime = SysTime(Date(-2001, 12, 31));
3433 sysTime.add!"months"(14);
3434 assert(sysTime == SysTime(Date(-1999, 3, 3)));
3435 sysTime.add!"months"(-14);
3436 assert(sysTime == SysTime(Date(-2000, 1, 3)));
3437 }
3438
3439 {
3440 auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), usecs(5007));
3441 sysTime.add!"months"(3);
3442 assert(sysTime == SysTime(DateTime(-1999, 10, 6, 12, 2, 7), usecs(5007)));
3443 sysTime.add!"months"(-4);
3444 assert(sysTime == SysTime(DateTime(-1999, 6, 6, 12, 2, 7), usecs(5007)));
3445 }
3446
3447 {
3448 auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), hnsecs(422202));
3449 sysTime.add!"months"(14);
3450 assert(sysTime == SysTime(DateTime(-2000, 3, 2, 7, 7, 7), hnsecs(422202)));
3451 sysTime.add!"months"(-14);
3452 assert(sysTime == SysTime(DateTime(-2001, 1, 2, 7, 7, 7), hnsecs(422202)));
3453 }
3454
3455 {
3456 auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), hnsecs(422202));
3457 sysTime.add!"months"(14);
3458 assert(sysTime == SysTime(DateTime(-1999, 3, 3, 7, 7, 7), hnsecs(422202)));
3459 sysTime.add!"months"(-14);
3460 assert(sysTime == SysTime(DateTime(-2000, 1, 3, 7, 7, 7), hnsecs(422202)));
3461 }
3462
3463 // Test Both
3464 {
3465 auto sysTime = SysTime(Date(1, 1, 1));
3466 sysTime.add!"months"(-1);
3467 assert(sysTime == SysTime(Date(0, 12, 1)));
3468 sysTime.add!"months"(1);
3469 assert(sysTime == SysTime(Date(1, 1, 1)));
3470 }
3471
3472 {
3473 auto sysTime = SysTime(Date(4, 1, 1));
3474 sysTime.add!"months"(-48);
3475 assert(sysTime == SysTime(Date(0, 1, 1)));
3476 sysTime.add!"months"(48);
3477 assert(sysTime == SysTime(Date(4, 1, 1)));
3478 }
3479
3480 {
3481 auto sysTime = SysTime(Date(4, 3, 31));
3482 sysTime.add!"months"(-49);
3483 assert(sysTime == SysTime(Date(0, 3, 2)));
3484 sysTime.add!"months"(49);
3485 assert(sysTime == SysTime(Date(4, 4, 2)));
3486 }
3487
3488 {
3489 auto sysTime = SysTime(Date(4, 3, 31));
3490 sysTime.add!"months"(-85);
3491 assert(sysTime == SysTime(Date(-3, 3, 3)));
3492 sysTime.add!"months"(85);
3493 assert(sysTime == SysTime(Date(4, 4, 3)));
3494 }
3495
3496 {
3497 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
3498 sysTime.add!"months"(-1);
3499 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
3500 sysTime.add!"months"(1);
3501 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
3502 }
3503
3504 {
3505 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
3506 sysTime.add!"months"(-1);
3507 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
3508 sysTime.add!"months"(1);
3509 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3510 }
3511
3512 {
3513 auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0));
3514 sysTime.add!"months"(1);
3515 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
3516 sysTime.add!"months"(-1);
3517 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
3518 }
3519
3520 {
3521 auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999));
3522 sysTime.add!"months"(1);
3523 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3524 sysTime.add!"months"(-1);
3525 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
3526 }
3527
3528 {
3529 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17));
3530 sysTime.add!"months"(-1);
3531 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 7, 9), hnsecs(17)));
3532 sysTime.add!"months"(1);
3533 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17)));
3534 }
3535
3536 {
3537 auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), msecs(9));
3538 sysTime.add!"months"(-85);
3539 assert(sysTime == SysTime(DateTime(-3, 3, 3, 12, 11, 10), msecs(9)));
3540 sysTime.add!"months"(85);
3541 assert(sysTime == SysTime(DateTime(4, 4, 3, 12, 11, 10), msecs(9)));
3542 }
3543
3544 {
3545 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
3546 sysTime.add!"months"(85);
3547 assert(sysTime == SysTime(DateTime(4, 5, 1, 12, 11, 10), msecs(9)));
3548 sysTime.add!"months"(-85);
3549 assert(sysTime == SysTime(DateTime(-3, 4, 1, 12, 11, 10), msecs(9)));
3550 }
3551
3552 {
3553 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
3554 sysTime.add!"months"(85).add!"months"(-83);
3555 assert(sysTime == SysTime(DateTime(-3, 6, 1, 12, 11, 10), msecs(9)));
3556 }
3557
3558 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
3559 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
3560 static assert(!__traits(compiles, cst.add!"months"(4)));
3561 static assert(!__traits(compiles, ist.add!"months"(4)));
3562
3563 static void testScope(scope ref SysTime st) @safe
3564 {
3565 auto result = st.add!"months"(42);
3566 }
3567 }
3568
3569 // Test add!"months"() with AllowDayOverflow.no
3570 @safe unittest
3571 {
3572 import core.time;
3573 // Test A.D.
3574 {
3575 auto sysTime = SysTime(Date(1999, 7, 6));
3576 sysTime.add!"months"(3, AllowDayOverflow.no);
3577 assert(sysTime == SysTime(Date(1999, 10, 6)));
3578 sysTime.add!"months"(-4, AllowDayOverflow.no);
3579 assert(sysTime == SysTime(Date(1999, 6, 6)));
3580 }
3581
3582 {
3583 auto sysTime = SysTime(Date(1999, 7, 6));
3584 sysTime.add!"months"(6, AllowDayOverflow.no);
3585 assert(sysTime == SysTime(Date(2000, 1, 6)));
3586 sysTime.add!"months"(-6, AllowDayOverflow.no);
3587 assert(sysTime == SysTime(Date(1999, 7, 6)));
3588 }
3589
3590 {
3591 auto sysTime = SysTime(Date(1999, 7, 6));
3592 sysTime.add!"months"(27, AllowDayOverflow.no);
3593 assert(sysTime == SysTime(Date(2001, 10, 6)));
3594 sysTime.add!"months"(-28, AllowDayOverflow.no);
3595 assert(sysTime == SysTime(Date(1999, 6, 6)));
3596 }
3597
3598 {
3599 auto sysTime = SysTime(Date(1999, 5, 31));
3600 sysTime.add!"months"(1, AllowDayOverflow.no);
3601 assert(sysTime == SysTime(Date(1999, 6, 30)));
3602 }
3603
3604 {
3605 auto sysTime = SysTime(Date(1999, 5, 31));
3606 sysTime.add!"months"(-1, AllowDayOverflow.no);
3607 assert(sysTime == SysTime(Date(1999, 4, 30)));
3608 }
3609
3610 {
3611 auto sysTime = SysTime(Date(1999, 2, 28));
3612 sysTime.add!"months"(12, AllowDayOverflow.no);
3613 assert(sysTime == SysTime(Date(2000, 2, 28)));
3614 }
3615
3616 {
3617 auto sysTime = SysTime(Date(2000, 2, 29));
3618 sysTime.add!"months"(12, AllowDayOverflow.no);
3619 assert(sysTime == SysTime(Date(2001, 2, 28)));
3620 }
3621
3622 {
3623 auto sysTime = SysTime(Date(1999, 7, 31));
3624 sysTime.add!"months"(1, AllowDayOverflow.no);
3625 assert(sysTime == SysTime(Date(1999, 8, 31)));
3626 sysTime.add!"months"(1, AllowDayOverflow.no);
3627 assert(sysTime == SysTime(Date(1999, 9, 30)));
3628 }
3629
3630 {
3631 auto sysTime = SysTime(Date(1998, 8, 31));
3632 sysTime.add!"months"(13, AllowDayOverflow.no);
3633 assert(sysTime == SysTime(Date(1999, 9, 30)));
3634 sysTime.add!"months"(-13, AllowDayOverflow.no);
3635 assert(sysTime == SysTime(Date(1998, 8, 30)));
3636 }
3637
3638 {
3639 auto sysTime = SysTime(Date(1997, 12, 31));
3640 sysTime.add!"months"(13, AllowDayOverflow.no);
3641 assert(sysTime == SysTime(Date(1999, 1, 31)));
3642 sysTime.add!"months"(-13, AllowDayOverflow.no);
3643 assert(sysTime == SysTime(Date(1997, 12, 31)));
3644 }
3645
3646 {
3647 auto sysTime = SysTime(Date(1997, 12, 31));
3648 sysTime.add!"months"(14, AllowDayOverflow.no);
3649 assert(sysTime == SysTime(Date(1999, 2, 28)));
3650 sysTime.add!"months"(-14, AllowDayOverflow.no);
3651 assert(sysTime == SysTime(Date(1997, 12, 28)));
3652 }
3653
3654 {
3655 auto sysTime = SysTime(Date(1998, 12, 31));
3656 sysTime.add!"months"(14, AllowDayOverflow.no);
3657 assert(sysTime == SysTime(Date(2000, 2, 29)));
3658 sysTime.add!"months"(-14, AllowDayOverflow.no);
3659 assert(sysTime == SysTime(Date(1998, 12, 29)));
3660 }
3661
3662 {
3663 auto sysTime = SysTime(Date(1999, 12, 31));
3664 sysTime.add!"months"(14, AllowDayOverflow.no);
3665 assert(sysTime == SysTime(Date(2001, 2, 28)));
3666 sysTime.add!"months"(-14, AllowDayOverflow.no);
3667 assert(sysTime == SysTime(Date(1999, 12, 28)));
3668 }
3669
3670 {
3671 auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), usecs(5007));
3672 sysTime.add!"months"(3, AllowDayOverflow.no);
3673 assert(sysTime == SysTime(DateTime(1999, 10, 6, 12, 2, 7), usecs(5007)));
3674 sysTime.add!"months"(-4, AllowDayOverflow.no);
3675 assert(sysTime == SysTime(DateTime(1999, 6, 6, 12, 2, 7), usecs(5007)));
3676 }
3677
3678 {
3679 auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), hnsecs(422202));
3680 sysTime.add!"months"(14, AllowDayOverflow.no);
3681 assert(sysTime == SysTime(DateTime(2000, 2, 29, 7, 7, 7), hnsecs(422202)));
3682 sysTime.add!"months"(-14, AllowDayOverflow.no);
3683 assert(sysTime == SysTime(DateTime(1998, 12, 29, 7, 7, 7), hnsecs(422202)));
3684 }
3685
3686 {
3687 auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), hnsecs(422202));
3688 sysTime.add!"months"(14, AllowDayOverflow.no);
3689 assert(sysTime == SysTime(DateTime(2001, 2, 28, 7, 7, 7), hnsecs(422202)));
3690 sysTime.add!"months"(-14, AllowDayOverflow.no);
3691 assert(sysTime == SysTime(DateTime(1999, 12, 28, 7, 7, 7), hnsecs(422202)));
3692 }
3693
3694 // Test B.C.
3695 {
3696 auto sysTime = SysTime(Date(-1999, 7, 6));
3697 sysTime.add!"months"(3, AllowDayOverflow.no);
3698 assert(sysTime == SysTime(Date(-1999, 10, 6)));
3699 sysTime.add!"months"(-4, AllowDayOverflow.no);
3700 assert(sysTime == SysTime(Date(-1999, 6, 6)));
3701 }
3702
3703 {
3704 auto sysTime = SysTime(Date(-1999, 7, 6));
3705 sysTime.add!"months"(6, AllowDayOverflow.no);
3706 assert(sysTime == SysTime(Date(-1998, 1, 6)));
3707 sysTime.add!"months"(-6, AllowDayOverflow.no);
3708 assert(sysTime == SysTime(Date(-1999, 7, 6)));
3709 }
3710
3711 {
3712 auto sysTime = SysTime(Date(-1999, 7, 6));
3713 sysTime.add!"months"(-27, AllowDayOverflow.no);
3714 assert(sysTime == SysTime(Date(-2001, 4, 6)));
3715 sysTime.add!"months"(28, AllowDayOverflow.no);
3716 assert(sysTime == SysTime(Date(-1999, 8, 6)));
3717 }
3718
3719 {
3720 auto sysTime = SysTime(Date(-1999, 5, 31));
3721 sysTime.add!"months"(1, AllowDayOverflow.no);
3722 assert(sysTime == SysTime(Date(-1999, 6, 30)));
3723 }
3724
3725 {
3726 auto sysTime = SysTime(Date(-1999, 5, 31));
3727 sysTime.add!"months"(-1, AllowDayOverflow.no);
3728 assert(sysTime == SysTime(Date(-1999, 4, 30)));
3729 }
3730
3731 {
3732 auto sysTime = SysTime(Date(-1999, 2, 28));
3733 sysTime.add!"months"(-12, AllowDayOverflow.no);
3734 assert(sysTime == SysTime(Date(-2000, 2, 28)));
3735 }
3736
3737 {
3738 auto sysTime = SysTime(Date(-2000, 2, 29));
3739 sysTime.add!"months"(-12, AllowDayOverflow.no);
3740 assert(sysTime == SysTime(Date(-2001, 2, 28)));
3741 }
3742
3743 {
3744 auto sysTime = SysTime(Date(-1999, 7, 31));
3745 sysTime.add!"months"(1, AllowDayOverflow.no);
3746 assert(sysTime == SysTime(Date(-1999, 8, 31)));
3747 sysTime.add!"months"(1, AllowDayOverflow.no);
3748 assert(sysTime == SysTime(Date(-1999, 9, 30)));
3749 }
3750
3751 {
3752 auto sysTime = SysTime(Date(-1998, 8, 31));
3753 sysTime.add!"months"(13, AllowDayOverflow.no);
3754 assert(sysTime == SysTime(Date(-1997, 9, 30)));
3755 sysTime.add!"months"(-13, AllowDayOverflow.no);
3756 assert(sysTime == SysTime(Date(-1998, 8, 30)));
3757 }
3758
3759 {
3760 auto sysTime = SysTime(Date(-1997, 12, 31));
3761 sysTime.add!"months"(13, AllowDayOverflow.no);
3762 assert(sysTime == SysTime(Date(-1995, 1, 31)));
3763 sysTime.add!"months"(-13, AllowDayOverflow.no);
3764 assert(sysTime == SysTime(Date(-1997, 12, 31)));
3765 }
3766
3767 {
3768 auto sysTime = SysTime(Date(-1997, 12, 31));
3769 sysTime.add!"months"(14, AllowDayOverflow.no);
3770 assert(sysTime == SysTime(Date(-1995, 2, 28)));
3771 sysTime.add!"months"(-14, AllowDayOverflow.no);
3772 assert(sysTime == SysTime(Date(-1997, 12, 28)));
3773 }
3774
3775 {
3776 auto sysTime = SysTime(Date(-2002, 12, 31));
3777 sysTime.add!"months"(14, AllowDayOverflow.no);
3778 assert(sysTime == SysTime(Date(-2000, 2, 29)));
3779 sysTime.add!"months"(-14, AllowDayOverflow.no);
3780 assert(sysTime == SysTime(Date(-2002, 12, 29)));
3781 }
3782
3783 {
3784 auto sysTime = SysTime(Date(-2001, 12, 31));
3785 sysTime.add!"months"(14, AllowDayOverflow.no);
3786 assert(sysTime == SysTime(Date(-1999, 2, 28)));
3787 sysTime.add!"months"(-14, AllowDayOverflow.no);
3788 assert(sysTime == SysTime(Date(-2001, 12, 28)));
3789 }
3790
3791 {
3792 auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), usecs(5007));
3793 sysTime.add!"months"(3, AllowDayOverflow.no);
3794 assert(sysTime == SysTime(DateTime(-1999, 10, 6, 12, 2, 7), usecs(5007)));
3795 sysTime.add!"months"(-4, AllowDayOverflow.no);
3796 assert(sysTime == SysTime(DateTime(-1999, 6, 6, 12, 2, 7), usecs(5007)));
3797 }
3798
3799 {
3800 auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), hnsecs(422202));
3801 sysTime.add!"months"(14, AllowDayOverflow.no);
3802 assert(sysTime == SysTime(DateTime(-2000, 2, 29, 7, 7, 7), hnsecs(422202)));
3803 sysTime.add!"months"(-14, AllowDayOverflow.no);
3804 assert(sysTime == SysTime(DateTime(-2002, 12, 29, 7, 7, 7), hnsecs(422202)));
3805 }
3806
3807 {
3808 auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), hnsecs(422202));
3809 sysTime.add!"months"(14, AllowDayOverflow.no);
3810 assert(sysTime == SysTime(DateTime(-1999, 2, 28, 7, 7, 7), hnsecs(422202)));
3811 sysTime.add!"months"(-14, AllowDayOverflow.no);
3812 assert(sysTime == SysTime(DateTime(-2001, 12, 28, 7, 7, 7), hnsecs(422202)));
3813 }
3814
3815 // Test Both
3816 {
3817 auto sysTime = SysTime(Date(1, 1, 1));
3818 sysTime.add!"months"(-1, AllowDayOverflow.no);
3819 assert(sysTime == SysTime(Date(0, 12, 1)));
3820 sysTime.add!"months"(1, AllowDayOverflow.no);
3821 assert(sysTime == SysTime(Date(1, 1, 1)));
3822 }
3823
3824 {
3825 auto sysTime = SysTime(Date(4, 1, 1));
3826 sysTime.add!"months"(-48, AllowDayOverflow.no);
3827 assert(sysTime == SysTime(Date(0, 1, 1)));
3828 sysTime.add!"months"(48, AllowDayOverflow.no);
3829 assert(sysTime == SysTime(Date(4, 1, 1)));
3830 }
3831
3832 {
3833 auto sysTime = SysTime(Date(4, 3, 31));
3834 sysTime.add!"months"(-49, AllowDayOverflow.no);
3835 assert(sysTime == SysTime(Date(0, 2, 29)));
3836 sysTime.add!"months"(49, AllowDayOverflow.no);
3837 assert(sysTime == SysTime(Date(4, 3, 29)));
3838 }
3839
3840 {
3841 auto sysTime = SysTime(Date(4, 3, 31));
3842 sysTime.add!"months"(-85, AllowDayOverflow.no);
3843 assert(sysTime == SysTime(Date(-3, 2, 28)));
3844 sysTime.add!"months"(85, AllowDayOverflow.no);
3845 assert(sysTime == SysTime(Date(4, 3, 28)));
3846 }
3847
3848 {
3849 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
3850 sysTime.add!"months"(-1, AllowDayOverflow.no);
3851 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
3852 sysTime.add!"months"(1, AllowDayOverflow.no);
3853 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
3854 }
3855
3856 {
3857 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
3858 sysTime.add!"months"(-1, AllowDayOverflow.no);
3859 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
3860 sysTime.add!"months"(1, AllowDayOverflow.no);
3861 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3862 }
3863
3864 {
3865 auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0));
3866 sysTime.add!"months"(1, AllowDayOverflow.no);
3867 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
3868 sysTime.add!"months"(-1, AllowDayOverflow.no);
3869 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
3870 }
3871
3872 {
3873 auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999));
3874 sysTime.add!"months"(1, AllowDayOverflow.no);
3875 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
3876 sysTime.add!"months"(-1, AllowDayOverflow.no);
3877 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
3878 }
3879
3880 {
3881 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17));
3882 sysTime.add!"months"(-1, AllowDayOverflow.no);
3883 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 7, 9), hnsecs(17)));
3884 sysTime.add!"months"(1, AllowDayOverflow.no);
3885 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17)));
3886 }
3887
3888 {
3889 auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), msecs(9));
3890 sysTime.add!"months"(-85, AllowDayOverflow.no);
3891 assert(sysTime == SysTime(DateTime(-3, 2, 28, 12, 11, 10), msecs(9)));
3892 sysTime.add!"months"(85, AllowDayOverflow.no);
3893 assert(sysTime == SysTime(DateTime(4, 3, 28, 12, 11, 10), msecs(9)));
3894 }
3895
3896 {
3897 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
3898 sysTime.add!"months"(85, AllowDayOverflow.no);
3899 assert(sysTime == SysTime(DateTime(4, 4, 30, 12, 11, 10), msecs(9)));
3900 sysTime.add!"months"(-85, AllowDayOverflow.no);
3901 assert(sysTime == SysTime(DateTime(-3, 3, 30, 12, 11, 10), msecs(9)));
3902 }
3903
3904 {
3905 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
3906 sysTime.add!"months"(85, AllowDayOverflow.no).add!"months"(-83, AllowDayOverflow.no);
3907 assert(sysTime == SysTime(DateTime(-3, 5, 30, 12, 11, 10), msecs(9)));
3908 }
3909 }
3910
3911
3912 /++
3913 Adds the given number of years or months to this $(LREF SysTime). A
3914 negative number will subtract.
3915
3916 The difference between rolling and adding is that rolling does not
3917 affect larger units. Rolling a $(LREF SysTime) 12 months
3918 gets the exact same $(LREF SysTime). However, the days can still be
3919 affected due to the differing number of days in each month.
3920
3921 Because there are no units larger than years, there is no difference
3922 between adding and rolling years.
3923
3924 Params:
3925 units = The type of units to add ("years" or "months").
3926 value = The number of months or years to add to this
3927 $(LREF SysTime).
3928 allowOverflow = Whether the days should be allowed to overflow,
3929 causing the month to increment.
3930 +/
3931 ref SysTime roll(string units)
3932 (long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) @safe nothrow scope
3933 if (units == "years")
3934 {
3935 return add!"years"(value, allowOverflow);
3936 }
3937
3938 ///
3939 @safe unittest
3940 {
3941 import std.datetime.date : AllowDayOverflow, DateTime;
3942
3943 auto st1 = SysTime(DateTime(2010, 1, 1, 12, 33, 33));
3944 st1.roll!"months"(1);
3945 assert(st1 == SysTime(DateTime(2010, 2, 1, 12, 33, 33)));
3946
3947 auto st2 = SysTime(DateTime(2010, 1, 1, 12, 33, 33));
3948 st2.roll!"months"(-1);
3949 assert(st2 == SysTime(DateTime(2010, 12, 1, 12, 33, 33)));
3950
3951 auto st3 = SysTime(DateTime(1999, 1, 29, 12, 33, 33));
3952 st3.roll!"months"(1);
3953 assert(st3 == SysTime(DateTime(1999, 3, 1, 12, 33, 33)));
3954
3955 auto st4 = SysTime(DateTime(1999, 1, 29, 12, 33, 33));
3956 st4.roll!"months"(1, AllowDayOverflow.no);
3957 assert(st4 == SysTime(DateTime(1999, 2, 28, 12, 33, 33)));
3958
3959 auto st5 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
3960 st5.roll!"years"(1);
3961 assert(st5 == SysTime(DateTime(2001, 3, 1, 12, 30, 33)));
3962
3963 auto st6 = SysTime(DateTime(2000, 2, 29, 12, 30, 33));
3964 st6.roll!"years"(1, AllowDayOverflow.no);
3965 assert(st6 == SysTime(DateTime(2001, 2, 28, 12, 30, 33)));
3966 }
3967
3968 @safe unittest
3969 {
3970 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
3971 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
3972 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
3973 st.roll!"years"(4);
3974 static assert(!__traits(compiles, cst.roll!"years"(4)));
3975 static assert(!__traits(compiles, ist.roll!"years"(4)));
3976
3977 static void testScope(scope ref SysTime st) @safe
3978 {
3979 auto result = st.roll!"years"(42);
3980 }
3981 }
3982
3983
3984 // Shares documentation with "years" overload.
3985 ref SysTime roll(string units)
3986 (long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) @safe nothrow scope
3987 if (units == "months")
3988 {
3989 auto hnsecs = adjTime;
3990 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
3991
3992 if (hnsecs < 0)
3993 {
3994 hnsecs += convert!("hours", "hnsecs")(24);
3995 --days;
3996 }
3997
3998 auto date = Date(cast(int) days);
3999 date.roll!"months"(value, allowOverflow);
4000 days = date.dayOfGregorianCal - 1;
4001
4002 if (days < 0)
4003 {
4004 hnsecs -= convert!("hours", "hnsecs")(24);
4005 ++days;
4006 }
4007
4008 immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
4009 adjTime = newDaysHNSecs + hnsecs;
4010 return this;
4011 }
4012
4013 // Test roll!"months"() with AllowDayOverflow.yes
4014 @safe unittest
4015 {
4016 import core.time;
4017 // Test A.D.
4018 {
4019 auto sysTime = SysTime(Date(1999, 7, 6));
4020 sysTime.roll!"months"(3);
4021 assert(sysTime == SysTime(Date(1999, 10, 6)));
4022 sysTime.roll!"months"(-4);
4023 assert(sysTime == SysTime(Date(1999, 6, 6)));
4024 }
4025
4026 {
4027 auto sysTime = SysTime(Date(1999, 7, 6));
4028 sysTime.roll!"months"(6);
4029 assert(sysTime == SysTime(Date(1999, 1, 6)));
4030 sysTime.roll!"months"(-6);
4031 assert(sysTime == SysTime(Date(1999, 7, 6)));
4032 }
4033
4034 {
4035 auto sysTime = SysTime(Date(1999, 7, 6));
4036 sysTime.roll!"months"(27);
4037 assert(sysTime == SysTime(Date(1999, 10, 6)));
4038 sysTime.roll!"months"(-28);
4039 assert(sysTime == SysTime(Date(1999, 6, 6)));
4040 }
4041
4042 {
4043 auto sysTime = SysTime(Date(1999, 5, 31));
4044 sysTime.roll!"months"(1);
4045 assert(sysTime == SysTime(Date(1999, 7, 1)));
4046 }
4047
4048 {
4049 auto sysTime = SysTime(Date(1999, 5, 31));
4050 sysTime.roll!"months"(-1);
4051 assert(sysTime == SysTime(Date(1999, 5, 1)));
4052 }
4053
4054 {
4055 auto sysTime = SysTime(Date(1999, 2, 28));
4056 sysTime.roll!"months"(12);
4057 assert(sysTime == SysTime(Date(1999, 2, 28)));
4058 }
4059
4060 {
4061 auto sysTime = SysTime(Date(2000, 2, 29));
4062 sysTime.roll!"months"(12);
4063 assert(sysTime == SysTime(Date(2000, 2, 29)));
4064 }
4065
4066 {
4067 auto sysTime = SysTime(Date(1999, 7, 31));
4068 sysTime.roll!"months"(1);
4069 assert(sysTime == SysTime(Date(1999, 8, 31)));
4070 sysTime.roll!"months"(1);
4071 assert(sysTime == SysTime(Date(1999, 10, 1)));
4072 }
4073
4074 {
4075 auto sysTime = SysTime(Date(1998, 8, 31));
4076 sysTime.roll!"months"(13);
4077 assert(sysTime == SysTime(Date(1998, 10, 1)));
4078 sysTime.roll!"months"(-13);
4079 assert(sysTime == SysTime(Date(1998, 9, 1)));
4080 }
4081
4082 {
4083 auto sysTime = SysTime(Date(1997, 12, 31));
4084 sysTime.roll!"months"(13);
4085 assert(sysTime == SysTime(Date(1997, 1, 31)));
4086 sysTime.roll!"months"(-13);
4087 assert(sysTime == SysTime(Date(1997, 12, 31)));
4088 }
4089
4090 {
4091 auto sysTime = SysTime(Date(1997, 12, 31));
4092 sysTime.roll!"months"(14);
4093 assert(sysTime == SysTime(Date(1997, 3, 3)));
4094 sysTime.roll!"months"(-14);
4095 assert(sysTime == SysTime(Date(1997, 1, 3)));
4096 }
4097
4098 {
4099 auto sysTime = SysTime(Date(1998, 12, 31));
4100 sysTime.roll!"months"(14);
4101 assert(sysTime == SysTime(Date(1998, 3, 3)));
4102 sysTime.roll!"months"(-14);
4103 assert(sysTime == SysTime(Date(1998, 1, 3)));
4104 }
4105
4106 {
4107 auto sysTime = SysTime(Date(1999, 12, 31));
4108 sysTime.roll!"months"(14);
4109 assert(sysTime == SysTime(Date(1999, 3, 3)));
4110 sysTime.roll!"months"(-14);
4111 assert(sysTime == SysTime(Date(1999, 1, 3)));
4112 }
4113
4114 {
4115 auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), usecs(5007));
4116 sysTime.roll!"months"(3);
4117 assert(sysTime == SysTime(DateTime(1999, 10, 6, 12, 2, 7), usecs(5007)));
4118 sysTime.roll!"months"(-4);
4119 assert(sysTime == SysTime(DateTime(1999, 6, 6, 12, 2, 7), usecs(5007)));
4120 }
4121
4122 {
4123 auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), hnsecs(422202));
4124 sysTime.roll!"months"(14);
4125 assert(sysTime == SysTime(DateTime(1998, 3, 3, 7, 7, 7), hnsecs(422202)));
4126 sysTime.roll!"months"(-14);
4127 assert(sysTime == SysTime(DateTime(1998, 1, 3, 7, 7, 7), hnsecs(422202)));
4128 }
4129
4130 {
4131 auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), hnsecs(422202));
4132 sysTime.roll!"months"(14);
4133 assert(sysTime == SysTime(DateTime(1999, 3, 3, 7, 7, 7), hnsecs(422202)));
4134 sysTime.roll!"months"(-14);
4135 assert(sysTime == SysTime(DateTime(1999, 1, 3, 7, 7, 7), hnsecs(422202)));
4136 }
4137
4138 // Test B.C.
4139 {
4140 auto sysTime = SysTime(Date(-1999, 7, 6));
4141 sysTime.roll!"months"(3);
4142 assert(sysTime == SysTime(Date(-1999, 10, 6)));
4143 sysTime.roll!"months"(-4);
4144 assert(sysTime == SysTime(Date(-1999, 6, 6)));
4145 }
4146
4147 {
4148 auto sysTime = SysTime(Date(-1999, 7, 6));
4149 sysTime.roll!"months"(6);
4150 assert(sysTime == SysTime(Date(-1999, 1, 6)));
4151 sysTime.roll!"months"(-6);
4152 assert(sysTime == SysTime(Date(-1999, 7, 6)));
4153 }
4154
4155 {
4156 auto sysTime = SysTime(Date(-1999, 7, 6));
4157 sysTime.roll!"months"(-27);
4158 assert(sysTime == SysTime(Date(-1999, 4, 6)));
4159 sysTime.roll!"months"(28);
4160 assert(sysTime == SysTime(Date(-1999, 8, 6)));
4161 }
4162
4163 {
4164 auto sysTime = SysTime(Date(-1999, 5, 31));
4165 sysTime.roll!"months"(1);
4166 assert(sysTime == SysTime(Date(-1999, 7, 1)));
4167 }
4168
4169 {
4170 auto sysTime = SysTime(Date(-1999, 5, 31));
4171 sysTime.roll!"months"(-1);
4172 assert(sysTime == SysTime(Date(-1999, 5, 1)));
4173 }
4174
4175 {
4176 auto sysTime = SysTime(Date(-1999, 2, 28));
4177 sysTime.roll!"months"(-12);
4178 assert(sysTime == SysTime(Date(-1999, 2, 28)));
4179 }
4180
4181 {
4182 auto sysTime = SysTime(Date(-2000, 2, 29));
4183 sysTime.roll!"months"(-12);
4184 assert(sysTime == SysTime(Date(-2000, 2, 29)));
4185 }
4186
4187 {
4188 auto sysTime = SysTime(Date(-1999, 7, 31));
4189 sysTime.roll!"months"(1);
4190 assert(sysTime == SysTime(Date(-1999, 8, 31)));
4191 sysTime.roll!"months"(1);
4192 assert(sysTime == SysTime(Date(-1999, 10, 1)));
4193 }
4194
4195 {
4196 auto sysTime = SysTime(Date(-1998, 8, 31));
4197 sysTime.roll!"months"(13);
4198 assert(sysTime == SysTime(Date(-1998, 10, 1)));
4199 sysTime.roll!"months"(-13);
4200 assert(sysTime == SysTime(Date(-1998, 9, 1)));
4201 }
4202
4203 {
4204 auto sysTime = SysTime(Date(-1997, 12, 31));
4205 sysTime.roll!"months"(13);
4206 assert(sysTime == SysTime(Date(-1997, 1, 31)));
4207 sysTime.roll!"months"(-13);
4208 assert(sysTime == SysTime(Date(-1997, 12, 31)));
4209 }
4210
4211 {
4212 auto sysTime = SysTime(Date(-1997, 12, 31));
4213 sysTime.roll!"months"(14);
4214 assert(sysTime == SysTime(Date(-1997, 3, 3)));
4215 sysTime.roll!"months"(-14);
4216 assert(sysTime == SysTime(Date(-1997, 1, 3)));
4217 }
4218
4219 {
4220 auto sysTime = SysTime(Date(-2002, 12, 31));
4221 sysTime.roll!"months"(14);
4222 assert(sysTime == SysTime(Date(-2002, 3, 3)));
4223 sysTime.roll!"months"(-14);
4224 assert(sysTime == SysTime(Date(-2002, 1, 3)));
4225 }
4226
4227 {
4228 auto sysTime = SysTime(Date(-2001, 12, 31));
4229 sysTime.roll!"months"(14);
4230 assert(sysTime == SysTime(Date(-2001, 3, 3)));
4231 sysTime.roll!"months"(-14);
4232 assert(sysTime == SysTime(Date(-2001, 1, 3)));
4233 }
4234
4235 {
4236 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
4237 sysTime.roll!"months"(-1);
4238 assert(sysTime == SysTime(DateTime(1, 12, 1, 0, 0, 0)));
4239 sysTime.roll!"months"(1);
4240 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
4241 }
4242
4243 {
4244 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
4245 sysTime.roll!"months"(-1);
4246 assert(sysTime == SysTime(DateTime(1, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
4247 sysTime.roll!"months"(1);
4248 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
4249 }
4250
4251 {
4252 auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0));
4253 sysTime.roll!"months"(1);
4254 assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0)));
4255 sysTime.roll!"months"(-1);
4256 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
4257 }
4258
4259 {
4260 auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999));
4261 sysTime.roll!"months"(1);
4262 assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
4263 sysTime.roll!"months"(-1);
4264 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
4265 }
4266
4267 {
4268 auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), hnsecs(5007));
4269 sysTime.roll!"months"(3);
4270 assert(sysTime == SysTime(DateTime(-1999, 10, 6, 12, 2, 7), hnsecs(5007)));
4271 sysTime.roll!"months"(-4);
4272 assert(sysTime == SysTime(DateTime(-1999, 6, 6, 12, 2, 7), hnsecs(5007)));
4273 }
4274
4275 {
4276 auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), hnsecs(422202));
4277 sysTime.roll!"months"(14);
4278 assert(sysTime == SysTime(DateTime(-2002, 3, 3, 7, 7, 7), hnsecs(422202)));
4279 sysTime.roll!"months"(-14);
4280 assert(sysTime == SysTime(DateTime(-2002, 1, 3, 7, 7, 7), hnsecs(422202)));
4281 }
4282
4283 {
4284 auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), hnsecs(422202));
4285 sysTime.roll!"months"(14);
4286 assert(sysTime == SysTime(DateTime(-2001, 3, 3, 7, 7, 7), hnsecs(422202)));
4287 sysTime.roll!"months"(-14);
4288 assert(sysTime == SysTime(DateTime(-2001, 1, 3, 7, 7, 7), hnsecs(422202)));
4289 }
4290
4291 // Test Both
4292 {
4293 auto sysTime = SysTime(Date(1, 1, 1));
4294 sysTime.roll!"months"(-1);
4295 assert(sysTime == SysTime(Date(1, 12, 1)));
4296 sysTime.roll!"months"(1);
4297 assert(sysTime == SysTime(Date(1, 1, 1)));
4298 }
4299
4300 {
4301 auto sysTime = SysTime(Date(4, 1, 1));
4302 sysTime.roll!"months"(-48);
4303 assert(sysTime == SysTime(Date(4, 1, 1)));
4304 sysTime.roll!"months"(48);
4305 assert(sysTime == SysTime(Date(4, 1, 1)));
4306 }
4307
4308 {
4309 auto sysTime = SysTime(Date(4, 3, 31));
4310 sysTime.roll!"months"(-49);
4311 assert(sysTime == SysTime(Date(4, 3, 2)));
4312 sysTime.roll!"months"(49);
4313 assert(sysTime == SysTime(Date(4, 4, 2)));
4314 }
4315
4316 {
4317 auto sysTime = SysTime(Date(4, 3, 31));
4318 sysTime.roll!"months"(-85);
4319 assert(sysTime == SysTime(Date(4, 3, 2)));
4320 sysTime.roll!"months"(85);
4321 assert(sysTime == SysTime(Date(4, 4, 2)));
4322 }
4323
4324 {
4325 auto sysTime = SysTime(Date(-1, 1, 1));
4326 sysTime.roll!"months"(-1);
4327 assert(sysTime == SysTime(Date(-1, 12, 1)));
4328 sysTime.roll!"months"(1);
4329 assert(sysTime == SysTime(Date(-1, 1, 1)));
4330 }
4331
4332 {
4333 auto sysTime = SysTime(Date(-4, 1, 1));
4334 sysTime.roll!"months"(-48);
4335 assert(sysTime == SysTime(Date(-4, 1, 1)));
4336 sysTime.roll!"months"(48);
4337 assert(sysTime == SysTime(Date(-4, 1, 1)));
4338 }
4339
4340 {
4341 auto sysTime = SysTime(Date(-4, 3, 31));
4342 sysTime.roll!"months"(-49);
4343 assert(sysTime == SysTime(Date(-4, 3, 2)));
4344 sysTime.roll!"months"(49);
4345 assert(sysTime == SysTime(Date(-4, 4, 2)));
4346 }
4347
4348 {
4349 auto sysTime = SysTime(Date(-4, 3, 31));
4350 sysTime.roll!"months"(-85);
4351 assert(sysTime == SysTime(Date(-4, 3, 2)));
4352 sysTime.roll!"months"(85);
4353 assert(sysTime == SysTime(Date(-4, 4, 2)));
4354 }
4355
4356 {
4357 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17));
4358 sysTime.roll!"months"(-1);
4359 assert(sysTime == SysTime(DateTime(1, 12, 1, 0, 7, 9), hnsecs(17)));
4360 sysTime.roll!"months"(1);
4361 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17)));
4362 }
4363
4364 {
4365 auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), msecs(9));
4366 sysTime.roll!"months"(-85);
4367 assert(sysTime == SysTime(DateTime(4, 3, 2, 12, 11, 10), msecs(9)));
4368 sysTime.roll!"months"(85);
4369 assert(sysTime == SysTime(DateTime(4, 4, 2, 12, 11, 10), msecs(9)));
4370 }
4371
4372 {
4373 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
4374 sysTime.roll!"months"(85);
4375 assert(sysTime == SysTime(DateTime(-3, 5, 1, 12, 11, 10), msecs(9)));
4376 sysTime.roll!"months"(-85);
4377 assert(sysTime == SysTime(DateTime(-3, 4, 1, 12, 11, 10), msecs(9)));
4378 }
4379
4380 {
4381 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
4382 sysTime.roll!"months"(85).roll!"months"(-83);
4383 assert(sysTime == SysTime(DateTime(-3, 6, 1, 12, 11, 10), msecs(9)));
4384 }
4385
4386 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
4387 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
4388 static assert(!__traits(compiles, cst.roll!"months"(4)));
4389 static assert(!__traits(compiles, ist.roll!"months"(4)));
4390
4391 static void testScope(scope ref SysTime st) @safe
4392 {
4393 auto result = st.roll!"months"(42);
4394 }
4395 }
4396
4397 // Test roll!"months"() with AllowDayOverflow.no
4398 @safe unittest
4399 {
4400 import core.time;
4401 // Test A.D.
4402 {
4403 auto sysTime = SysTime(Date(1999, 7, 6));
4404 sysTime.roll!"months"(3, AllowDayOverflow.no);
4405 assert(sysTime == SysTime(Date(1999, 10, 6)));
4406 sysTime.roll!"months"(-4, AllowDayOverflow.no);
4407 assert(sysTime == SysTime(Date(1999, 6, 6)));
4408 }
4409
4410 {
4411 auto sysTime = SysTime(Date(1999, 7, 6));
4412 sysTime.roll!"months"(6, AllowDayOverflow.no);
4413 assert(sysTime == SysTime(Date(1999, 1, 6)));
4414 sysTime.roll!"months"(-6, AllowDayOverflow.no);
4415 assert(sysTime == SysTime(Date(1999, 7, 6)));
4416 }
4417
4418 {
4419 auto sysTime = SysTime(Date(1999, 7, 6));
4420 sysTime.roll!"months"(27, AllowDayOverflow.no);
4421 assert(sysTime == SysTime(Date(1999, 10, 6)));
4422 sysTime.roll!"months"(-28, AllowDayOverflow.no);
4423 assert(sysTime == SysTime(Date(1999, 6, 6)));
4424 }
4425
4426 {
4427 auto sysTime = SysTime(Date(1999, 5, 31));
4428 sysTime.roll!"months"(1, AllowDayOverflow.no);
4429 assert(sysTime == SysTime(Date(1999, 6, 30)));
4430 }
4431
4432 {
4433 auto sysTime = SysTime(Date(1999, 5, 31));
4434 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4435 assert(sysTime == SysTime(Date(1999, 4, 30)));
4436 }
4437
4438 {
4439 auto sysTime = SysTime(Date(1999, 2, 28));
4440 sysTime.roll!"months"(12, AllowDayOverflow.no);
4441 assert(sysTime == SysTime(Date(1999, 2, 28)));
4442 }
4443
4444 {
4445 auto sysTime = SysTime(Date(2000, 2, 29));
4446 sysTime.roll!"months"(12, AllowDayOverflow.no);
4447 assert(sysTime == SysTime(Date(2000, 2, 29)));
4448 }
4449
4450 {
4451 auto sysTime = SysTime(Date(1999, 7, 31));
4452 sysTime.roll!"months"(1, AllowDayOverflow.no);
4453 assert(sysTime == SysTime(Date(1999, 8, 31)));
4454 sysTime.roll!"months"(1, AllowDayOverflow.no);
4455 assert(sysTime == SysTime(Date(1999, 9, 30)));
4456 }
4457
4458 {
4459 auto sysTime = SysTime(Date(1998, 8, 31));
4460 sysTime.roll!"months"(13, AllowDayOverflow.no);
4461 assert(sysTime == SysTime(Date(1998, 9, 30)));
4462 sysTime.roll!"months"(-13, AllowDayOverflow.no);
4463 assert(sysTime == SysTime(Date(1998, 8, 30)));
4464 }
4465
4466 {
4467 auto sysTime = SysTime(Date(1997, 12, 31));
4468 sysTime.roll!"months"(13, AllowDayOverflow.no);
4469 assert(sysTime == SysTime(Date(1997, 1, 31)));
4470 sysTime.roll!"months"(-13, AllowDayOverflow.no);
4471 assert(sysTime == SysTime(Date(1997, 12, 31)));
4472 }
4473
4474 {
4475 auto sysTime = SysTime(Date(1997, 12, 31));
4476 sysTime.roll!"months"(14, AllowDayOverflow.no);
4477 assert(sysTime == SysTime(Date(1997, 2, 28)));
4478 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4479 assert(sysTime == SysTime(Date(1997, 12, 28)));
4480 }
4481
4482 {
4483 auto sysTime = SysTime(Date(1998, 12, 31));
4484 sysTime.roll!"months"(14, AllowDayOverflow.no);
4485 assert(sysTime == SysTime(Date(1998, 2, 28)));
4486 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4487 assert(sysTime == SysTime(Date(1998, 12, 28)));
4488 }
4489
4490 {
4491 auto sysTime = SysTime(Date(1999, 12, 31));
4492 sysTime.roll!"months"(14, AllowDayOverflow.no);
4493 assert(sysTime == SysTime(Date(1999, 2, 28)));
4494 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4495 assert(sysTime == SysTime(Date(1999, 12, 28)));
4496 }
4497
4498 {
4499 auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), usecs(5007));
4500 sysTime.roll!"months"(3, AllowDayOverflow.no);
4501 assert(sysTime == SysTime(DateTime(1999, 10, 6, 12, 2, 7), usecs(5007)));
4502 sysTime.roll!"months"(-4, AllowDayOverflow.no);
4503 assert(sysTime == SysTime(DateTime(1999, 6, 6, 12, 2, 7), usecs(5007)));
4504 }
4505
4506 {
4507 auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), hnsecs(422202));
4508 sysTime.roll!"months"(14, AllowDayOverflow.no);
4509 assert(sysTime == SysTime(DateTime(1998, 2, 28, 7, 7, 7), hnsecs(422202)));
4510 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4511 assert(sysTime == SysTime(DateTime(1998, 12, 28, 7, 7, 7), hnsecs(422202)));
4512 }
4513
4514 {
4515 auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), hnsecs(422202));
4516 sysTime.roll!"months"(14, AllowDayOverflow.no);
4517 assert(sysTime == SysTime(DateTime(1999, 2, 28, 7, 7, 7), hnsecs(422202)));
4518 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4519 assert(sysTime == SysTime(DateTime(1999, 12, 28, 7, 7, 7), hnsecs(422202)));
4520 }
4521
4522 // Test B.C.
4523 {
4524 auto sysTime = SysTime(Date(-1999, 7, 6));
4525 sysTime.roll!"months"(3, AllowDayOverflow.no);
4526 assert(sysTime == SysTime(Date(-1999, 10, 6)));
4527 sysTime.roll!"months"(-4, AllowDayOverflow.no);
4528 assert(sysTime == SysTime(Date(-1999, 6, 6)));
4529 }
4530
4531 {
4532 auto sysTime = SysTime(Date(-1999, 7, 6));
4533 sysTime.roll!"months"(6, AllowDayOverflow.no);
4534 assert(sysTime == SysTime(Date(-1999, 1, 6)));
4535 sysTime.roll!"months"(-6, AllowDayOverflow.no);
4536 assert(sysTime == SysTime(Date(-1999, 7, 6)));
4537 }
4538
4539 {
4540 auto sysTime = SysTime(Date(-1999, 7, 6));
4541 sysTime.roll!"months"(-27, AllowDayOverflow.no);
4542 assert(sysTime == SysTime(Date(-1999, 4, 6)));
4543 sysTime.roll!"months"(28, AllowDayOverflow.no);
4544 assert(sysTime == SysTime(Date(-1999, 8, 6)));
4545 }
4546
4547 {
4548 auto sysTime = SysTime(Date(-1999, 5, 31));
4549 sysTime.roll!"months"(1, AllowDayOverflow.no);
4550 assert(sysTime == SysTime(Date(-1999, 6, 30)));
4551 }
4552
4553 {
4554 auto sysTime = SysTime(Date(-1999, 5, 31));
4555 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4556 assert(sysTime == SysTime(Date(-1999, 4, 30)));
4557 }
4558
4559 {
4560 auto sysTime = SysTime(Date(-1999, 2, 28));
4561 sysTime.roll!"months"(-12, AllowDayOverflow.no);
4562 assert(sysTime == SysTime(Date(-1999, 2, 28)));
4563 }
4564
4565 {
4566 auto sysTime = SysTime(Date(-2000, 2, 29));
4567 sysTime.roll!"months"(-12, AllowDayOverflow.no);
4568 assert(sysTime == SysTime(Date(-2000, 2, 29)));
4569 }
4570
4571 {
4572 auto sysTime = SysTime(Date(-1999, 7, 31));
4573 sysTime.roll!"months"(1, AllowDayOverflow.no);
4574 assert(sysTime == SysTime(Date(-1999, 8, 31)));
4575 sysTime.roll!"months"(1, AllowDayOverflow.no);
4576 assert(sysTime == SysTime(Date(-1999, 9, 30)));
4577 }
4578
4579 {
4580 auto sysTime = SysTime(Date(-1998, 8, 31));
4581 sysTime.roll!"months"(13, AllowDayOverflow.no);
4582 assert(sysTime == SysTime(Date(-1998, 9, 30)));
4583 sysTime.roll!"months"(-13, AllowDayOverflow.no);
4584 assert(sysTime == SysTime(Date(-1998, 8, 30)));
4585 }
4586
4587 {
4588 auto sysTime = SysTime(Date(-1997, 12, 31));
4589 sysTime.roll!"months"(13, AllowDayOverflow.no);
4590 assert(sysTime == SysTime(Date(-1997, 1, 31)));
4591 sysTime.roll!"months"(-13, AllowDayOverflow.no);
4592 assert(sysTime == SysTime(Date(-1997, 12, 31)));
4593 }
4594
4595 {
4596 auto sysTime = SysTime(Date(-1997, 12, 31));
4597 sysTime.roll!"months"(14, AllowDayOverflow.no);
4598 assert(sysTime == SysTime(Date(-1997, 2, 28)));
4599 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4600 assert(sysTime == SysTime(Date(-1997, 12, 28)));
4601 }
4602
4603 {
4604 auto sysTime = SysTime(Date(-2002, 12, 31));
4605 sysTime.roll!"months"(14, AllowDayOverflow.no);
4606 assert(sysTime == SysTime(Date(-2002, 2, 28)));
4607 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4608 assert(sysTime == SysTime(Date(-2002, 12, 28)));
4609 }
4610
4611 {
4612 auto sysTime = SysTime(Date(-2001, 12, 31));
4613 sysTime.roll!"months"(14, AllowDayOverflow.no);
4614 assert(sysTime == SysTime(Date(-2001, 2, 28)));
4615 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4616 assert(sysTime == SysTime(Date(-2001, 12, 28)));
4617 }
4618
4619 {
4620 auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), usecs(5007));
4621 sysTime.roll!"months"(3, AllowDayOverflow.no);
4622 assert(sysTime == SysTime(DateTime(-1999, 10, 6, 12, 2, 7), usecs(5007)));
4623 sysTime.roll!"months"(-4, AllowDayOverflow.no);
4624 assert(sysTime == SysTime(DateTime(-1999, 6, 6, 12, 2, 7), usecs(5007)));
4625 }
4626
4627 {
4628 auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), hnsecs(422202));
4629 sysTime.roll!"months"(14, AllowDayOverflow.no);
4630 assert(sysTime == SysTime(DateTime(-2002, 2, 28, 7, 7, 7), hnsecs(422202)));
4631 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4632 assert(sysTime == SysTime(DateTime(-2002, 12, 28, 7, 7, 7), hnsecs(422202)));
4633 }
4634
4635 {
4636 auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), hnsecs(422202));
4637 sysTime.roll!"months"(14, AllowDayOverflow.no);
4638 assert(sysTime == SysTime(DateTime(-2001, 2, 28, 7, 7, 7), hnsecs(422202)));
4639 sysTime.roll!"months"(-14, AllowDayOverflow.no);
4640 assert(sysTime == SysTime(DateTime(-2001, 12, 28, 7, 7, 7), hnsecs(422202)));
4641 }
4642
4643 // Test Both
4644 {
4645 auto sysTime = SysTime(Date(1, 1, 1));
4646 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4647 assert(sysTime == SysTime(Date(1, 12, 1)));
4648 sysTime.roll!"months"(1, AllowDayOverflow.no);
4649 assert(sysTime == SysTime(Date(1, 1, 1)));
4650 }
4651
4652 {
4653 auto sysTime = SysTime(Date(4, 1, 1));
4654 sysTime.roll!"months"(-48, AllowDayOverflow.no);
4655 assert(sysTime == SysTime(Date(4, 1, 1)));
4656 sysTime.roll!"months"(48, AllowDayOverflow.no);
4657 assert(sysTime == SysTime(Date(4, 1, 1)));
4658 }
4659
4660 {
4661 auto sysTime = SysTime(Date(4, 3, 31));
4662 sysTime.roll!"months"(-49, AllowDayOverflow.no);
4663 assert(sysTime == SysTime(Date(4, 2, 29)));
4664 sysTime.roll!"months"(49, AllowDayOverflow.no);
4665 assert(sysTime == SysTime(Date(4, 3, 29)));
4666 }
4667
4668 {
4669 auto sysTime = SysTime(Date(4, 3, 31));
4670 sysTime.roll!"months"(-85, AllowDayOverflow.no);
4671 assert(sysTime == SysTime(Date(4, 2, 29)));
4672 sysTime.roll!"months"(85, AllowDayOverflow.no);
4673 assert(sysTime == SysTime(Date(4, 3, 29)));
4674 }
4675
4676 {
4677 auto sysTime = SysTime(Date(-1, 1, 1));
4678 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4679 assert(sysTime == SysTime(Date(-1, 12, 1)));
4680 sysTime.roll!"months"(1, AllowDayOverflow.no);
4681 assert(sysTime == SysTime(Date(-1, 1, 1)));
4682 }
4683
4684 {
4685 auto sysTime = SysTime(Date(-4, 1, 1));
4686 sysTime.roll!"months"(-48, AllowDayOverflow.no);
4687 assert(sysTime == SysTime(Date(-4, 1, 1)));
4688 sysTime.roll!"months"(48, AllowDayOverflow.no);
4689 assert(sysTime == SysTime(Date(-4, 1, 1)));
4690 }
4691
4692 {
4693 auto sysTime = SysTime(Date(-4, 3, 31));
4694 sysTime.roll!"months"(-49, AllowDayOverflow.no);
4695 assert(sysTime == SysTime(Date(-4, 2, 29)));
4696 sysTime.roll!"months"(49, AllowDayOverflow.no);
4697 assert(sysTime == SysTime(Date(-4, 3, 29)));
4698 }
4699
4700 {
4701 auto sysTime = SysTime(Date(-4, 3, 31));
4702 sysTime.roll!"months"(-85, AllowDayOverflow.no);
4703 assert(sysTime == SysTime(Date(-4, 2, 29)));
4704 sysTime.roll!"months"(85, AllowDayOverflow.no);
4705 assert(sysTime == SysTime(Date(-4, 3, 29)));
4706 }
4707
4708 {
4709 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
4710 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4711 assert(sysTime == SysTime(DateTime(1, 12, 1, 0, 0, 0)));
4712 sysTime.roll!"months"(1, AllowDayOverflow.no);
4713 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
4714 }
4715
4716 {
4717 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
4718 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4719 assert(sysTime == SysTime(DateTime(1, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
4720 sysTime.roll!"months"(1, AllowDayOverflow.no);
4721 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
4722 }
4723
4724 {
4725 auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0));
4726 sysTime.roll!"months"(1, AllowDayOverflow.no);
4727 assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0)));
4728 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4729 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
4730 }
4731
4732 {
4733 auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999));
4734 sysTime.roll!"months"(1, AllowDayOverflow.no);
4735 assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
4736 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4737 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
4738 }
4739
4740 {
4741 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17));
4742 sysTime.roll!"months"(-1, AllowDayOverflow.no);
4743 assert(sysTime == SysTime(DateTime(1, 12, 1, 0, 7, 9), hnsecs(17)));
4744 sysTime.roll!"months"(1, AllowDayOverflow.no);
4745 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17)));
4746 }
4747
4748 {
4749 auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), msecs(9));
4750 sysTime.roll!"months"(-85, AllowDayOverflow.no);
4751 assert(sysTime == SysTime(DateTime(4, 2, 29, 12, 11, 10), msecs(9)));
4752 sysTime.roll!"months"(85, AllowDayOverflow.no);
4753 assert(sysTime == SysTime(DateTime(4, 3, 29, 12, 11, 10), msecs(9)));
4754 }
4755
4756 {
4757 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
4758 sysTime.roll!"months"(85, AllowDayOverflow.no);
4759 assert(sysTime == SysTime(DateTime(-3, 4, 30, 12, 11, 10), msecs(9)));
4760 sysTime.roll!"months"(-85, AllowDayOverflow.no);
4761 assert(sysTime == SysTime(DateTime(-3, 3, 30, 12, 11, 10), msecs(9)));
4762 }
4763
4764 {
4765 auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9));
4766 sysTime.roll!"months"(85, AllowDayOverflow.no).roll!"months"(-83, AllowDayOverflow.no);
4767 assert(sysTime == SysTime(DateTime(-3, 5, 30, 12, 11, 10), msecs(9)));
4768 }
4769 }
4770
4771
4772 /++
4773 Adds the given number of units to this $(LREF SysTime). A negative number
4774 will subtract.
4775
4776 The difference between rolling and adding is that rolling does not
4777 affect larger units. For instance, rolling a $(LREF SysTime) one
4778 year's worth of days gets the exact same $(LREF SysTime).
4779
4780 Accepted units are `"days"`, `"minutes"`, `"hours"`,
4781 `"minutes"`, `"seconds"`, `"msecs"`, `"usecs"`, and
4782 `"hnsecs"`.
4783
4784 Note that when rolling msecs, usecs or hnsecs, they all add up to a
4785 second. So, for example, rolling 1000 msecs is exactly the same as
4786 rolling 100,000 usecs.
4787
4788 Params:
4789 units = The units to add.
4790 value = The number of $(D_PARAM units) to add to this
4791 $(LREF SysTime).
4792 +/
4793 ref SysTime roll(string units)(long value) @safe nothrow scope
4794 if (units == "days")
4795 {
4796 auto hnsecs = adjTime;
4797 auto gdays = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
4798
4799 if (hnsecs < 0)
4800 {
4801 hnsecs += convert!("hours", "hnsecs")(24);
4802 --gdays;
4803 }
4804
4805 auto date = Date(cast(int) gdays);
4806 date.roll!"days"(value);
4807 gdays = date.dayOfGregorianCal - 1;
4808
4809 if (gdays < 0)
4810 {
4811 hnsecs -= convert!("hours", "hnsecs")(24);
4812 ++gdays;
4813 }
4814
4815 immutable newDaysHNSecs = convert!("days", "hnsecs")(gdays);
4816 adjTime = newDaysHNSecs + hnsecs;
4817 return this;
4818 }
4819
4820 ///
4821 @safe unittest
4822 {
4823 import core.time : msecs, hnsecs;
4824 import std.datetime.date : DateTime;
4825
4826 auto st1 = SysTime(DateTime(2010, 1, 1, 11, 23, 12));
4827 st1.roll!"days"(1);
4828 assert(st1 == SysTime(DateTime(2010, 1, 2, 11, 23, 12)));
4829 st1.roll!"days"(365);
4830 assert(st1 == SysTime(DateTime(2010, 1, 26, 11, 23, 12)));
4831 st1.roll!"days"(-32);
4832 assert(st1 == SysTime(DateTime(2010, 1, 25, 11, 23, 12)));
4833
4834 auto st2 = SysTime(DateTime(2010, 7, 4, 12, 0, 0));
4835 st2.roll!"hours"(1);
4836 assert(st2 == SysTime(DateTime(2010, 7, 4, 13, 0, 0)));
4837
4838 auto st3 = SysTime(DateTime(2010, 2, 12, 12, 0, 0));
4839 st3.roll!"hours"(-1);
4840 assert(st3 == SysTime(DateTime(2010, 2, 12, 11, 0, 0)));
4841
4842 auto st4 = SysTime(DateTime(2009, 12, 31, 0, 0, 0));
4843 st4.roll!"minutes"(1);
4844 assert(st4 == SysTime(DateTime(2009, 12, 31, 0, 1, 0)));
4845
4846 auto st5 = SysTime(DateTime(2010, 1, 1, 0, 0, 0));
4847 st5.roll!"minutes"(-1);
4848 assert(st5 == SysTime(DateTime(2010, 1, 1, 0, 59, 0)));
4849
4850 auto st6 = SysTime(DateTime(2009, 12, 31, 0, 0, 0));
4851 st6.roll!"seconds"(1);
4852 assert(st6 == SysTime(DateTime(2009, 12, 31, 0, 0, 1)));
4853
4854 auto st7 = SysTime(DateTime(2010, 1, 1, 0, 0, 0));
4855 st7.roll!"seconds"(-1);
4856 assert(st7 == SysTime(DateTime(2010, 1, 1, 0, 0, 59)));
4857
4858 auto dt = DateTime(2010, 1, 1, 0, 0, 0);
4859 auto st8 = SysTime(dt);
4860 st8.roll!"msecs"(1);
4861 assert(st8 == SysTime(dt, msecs(1)));
4862
4863 auto st9 = SysTime(dt);
4864 st9.roll!"msecs"(-1);
4865 assert(st9 == SysTime(dt, msecs(999)));
4866
4867 auto st10 = SysTime(dt);
4868 st10.roll!"hnsecs"(1);
4869 assert(st10 == SysTime(dt, hnsecs(1)));
4870
4871 auto st11 = SysTime(dt);
4872 st11.roll!"hnsecs"(-1);
4873 assert(st11 == SysTime(dt, hnsecs(9_999_999)));
4874 }
4875
4876 @safe unittest
4877 {
4878 import core.time;
4879 // Test A.D.
4880 {
4881 auto sysTime = SysTime(Date(1999, 2, 28));
4882 sysTime.roll!"days"(1);
4883 assert(sysTime == SysTime(Date(1999, 2, 1)));
4884 sysTime.roll!"days"(-1);
4885 assert(sysTime == SysTime(Date(1999, 2, 28)));
4886 }
4887
4888 {
4889 auto sysTime = SysTime(Date(2000, 2, 28));
4890 sysTime.roll!"days"(1);
4891 assert(sysTime == SysTime(Date(2000, 2, 29)));
4892 sysTime.roll!"days"(1);
4893 assert(sysTime == SysTime(Date(2000, 2, 1)));
4894 sysTime.roll!"days"(-1);
4895 assert(sysTime == SysTime(Date(2000, 2, 29)));
4896 }
4897
4898 {
4899 auto sysTime = SysTime(Date(1999, 6, 30));
4900 sysTime.roll!"days"(1);
4901 assert(sysTime == SysTime(Date(1999, 6, 1)));
4902 sysTime.roll!"days"(-1);
4903 assert(sysTime == SysTime(Date(1999, 6, 30)));
4904 }
4905
4906 {
4907 auto sysTime = SysTime(Date(1999, 7, 31));
4908 sysTime.roll!"days"(1);
4909 assert(sysTime == SysTime(Date(1999, 7, 1)));
4910 sysTime.roll!"days"(-1);
4911 assert(sysTime == SysTime(Date(1999, 7, 31)));
4912 }
4913
4914 {
4915 auto sysTime = SysTime(Date(1999, 1, 1));
4916 sysTime.roll!"days"(-1);
4917 assert(sysTime == SysTime(Date(1999, 1, 31)));
4918 sysTime.roll!"days"(1);
4919 assert(sysTime == SysTime(Date(1999, 1, 1)));
4920 }
4921
4922 {
4923 auto sysTime = SysTime(Date(1999, 7, 6));
4924 sysTime.roll!"days"(9);
4925 assert(sysTime == SysTime(Date(1999, 7, 15)));
4926 sysTime.roll!"days"(-11);
4927 assert(sysTime == SysTime(Date(1999, 7, 4)));
4928 sysTime.roll!"days"(30);
4929 assert(sysTime == SysTime(Date(1999, 7, 3)));
4930 sysTime.roll!"days"(-3);
4931 assert(sysTime == SysTime(Date(1999, 7, 31)));
4932 }
4933
4934 {
4935 auto sysTime = SysTime(Date(1999, 7, 6));
4936 sysTime.roll!"days"(365);
4937 assert(sysTime == SysTime(Date(1999, 7, 30)));
4938 sysTime.roll!"days"(-365);
4939 assert(sysTime == SysTime(Date(1999, 7, 6)));
4940 sysTime.roll!"days"(366);
4941 assert(sysTime == SysTime(Date(1999, 7, 31)));
4942 sysTime.roll!"days"(730);
4943 assert(sysTime == SysTime(Date(1999, 7, 17)));
4944 sysTime.roll!"days"(-1096);
4945 assert(sysTime == SysTime(Date(1999, 7, 6)));
4946 }
4947
4948 {
4949 auto sysTime = SysTime(Date(1999, 2, 6));
4950 sysTime.roll!"days"(365);
4951 assert(sysTime == SysTime(Date(1999, 2, 7)));
4952 sysTime.roll!"days"(-365);
4953 assert(sysTime == SysTime(Date(1999, 2, 6)));
4954 sysTime.roll!"days"(366);
4955 assert(sysTime == SysTime(Date(1999, 2, 8)));
4956 sysTime.roll!"days"(730);
4957 assert(sysTime == SysTime(Date(1999, 2, 10)));
4958 sysTime.roll!"days"(-1096);
4959 assert(sysTime == SysTime(Date(1999, 2, 6)));
4960 }
4961
4962 {
4963 auto sysTime = SysTime(DateTime(1999, 2, 28, 7, 9, 2), usecs(234578));
4964 sysTime.roll!"days"(1);
4965 assert(sysTime == SysTime(DateTime(1999, 2, 1, 7, 9, 2), usecs(234578)));
4966 sysTime.roll!"days"(-1);
4967 assert(sysTime == SysTime(DateTime(1999, 2, 28, 7, 9, 2), usecs(234578)));
4968 }
4969
4970 {
4971 auto sysTime = SysTime(DateTime(1999, 7, 6, 7, 9, 2), usecs(234578));
4972 sysTime.roll!"days"(9);
4973 assert(sysTime == SysTime(DateTime(1999, 7, 15, 7, 9, 2), usecs(234578)));
4974 sysTime.roll!"days"(-11);
4975 assert(sysTime == SysTime(DateTime(1999, 7, 4, 7, 9, 2), usecs(234578)));
4976 sysTime.roll!"days"(30);
4977 assert(sysTime == SysTime(DateTime(1999, 7, 3, 7, 9, 2), usecs(234578)));
4978 sysTime.roll!"days"(-3);
4979 assert(sysTime == SysTime(DateTime(1999, 7, 31, 7, 9, 2), usecs(234578)));
4980 }
4981
4982 // Test B.C.
4983 {
4984 auto sysTime = SysTime(Date(-1999, 2, 28));
4985 sysTime.roll!"days"(1);
4986 assert(sysTime == SysTime(Date(-1999, 2, 1)));
4987 sysTime.roll!"days"(-1);
4988 assert(sysTime == SysTime(Date(-1999, 2, 28)));
4989 }
4990
4991 {
4992 auto sysTime = SysTime(Date(-2000, 2, 28));
4993 sysTime.roll!"days"(1);
4994 assert(sysTime == SysTime(Date(-2000, 2, 29)));
4995 sysTime.roll!"days"(1);
4996 assert(sysTime == SysTime(Date(-2000, 2, 1)));
4997 sysTime.roll!"days"(-1);
4998 assert(sysTime == SysTime(Date(-2000, 2, 29)));
4999 }
5000
5001 {
5002 auto sysTime = SysTime(Date(-1999, 6, 30));
5003 sysTime.roll!"days"(1);
5004 assert(sysTime == SysTime(Date(-1999, 6, 1)));
5005 sysTime.roll!"days"(-1);
5006 assert(sysTime == SysTime(Date(-1999, 6, 30)));
5007 }
5008
5009 {
5010 auto sysTime = SysTime(Date(-1999, 7, 31));
5011 sysTime.roll!"days"(1);
5012 assert(sysTime == SysTime(Date(-1999, 7, 1)));
5013 sysTime.roll!"days"(-1);
5014 assert(sysTime == SysTime(Date(-1999, 7, 31)));
5015 }
5016
5017 {
5018 auto sysTime = SysTime(Date(-1999, 1, 1));
5019 sysTime.roll!"days"(-1);
5020 assert(sysTime == SysTime(Date(-1999, 1, 31)));
5021 sysTime.roll!"days"(1);
5022 assert(sysTime == SysTime(Date(-1999, 1, 1)));
5023 }
5024
5025 {
5026 auto sysTime = SysTime(Date(-1999, 7, 6));
5027 sysTime.roll!"days"(9);
5028 assert(sysTime == SysTime(Date(-1999, 7, 15)));
5029 sysTime.roll!"days"(-11);
5030 assert(sysTime == SysTime(Date(-1999, 7, 4)));
5031 sysTime.roll!"days"(30);
5032 assert(sysTime == SysTime(Date(-1999, 7, 3)));
5033 sysTime.roll!"days"(-3);
5034 assert(sysTime == SysTime(Date(-1999, 7, 31)));
5035 }
5036
5037 {
5038 auto sysTime = SysTime(Date(-1999, 7, 6));
5039 sysTime.roll!"days"(365);
5040 assert(sysTime == SysTime(Date(-1999, 7, 30)));
5041 sysTime.roll!"days"(-365);
5042 assert(sysTime == SysTime(Date(-1999, 7, 6)));
5043 sysTime.roll!"days"(366);
5044 assert(sysTime == SysTime(Date(-1999, 7, 31)));
5045 sysTime.roll!"days"(730);
5046 assert(sysTime == SysTime(Date(-1999, 7, 17)));
5047 sysTime.roll!"days"(-1096);
5048 assert(sysTime == SysTime(Date(-1999, 7, 6)));
5049 }
5050
5051 {
5052 auto sysTime = SysTime(DateTime(-1999, 2, 28, 7, 9, 2), usecs(234578));
5053 sysTime.roll!"days"(1);
5054 assert(sysTime == SysTime(DateTime(-1999, 2, 1, 7, 9, 2), usecs(234578)));
5055 sysTime.roll!"days"(-1);
5056 assert(sysTime == SysTime(DateTime(-1999, 2, 28, 7, 9, 2), usecs(234578)));
5057 }
5058
5059 {
5060 auto sysTime = SysTime(DateTime(-1999, 7, 6, 7, 9, 2), usecs(234578));
5061 sysTime.roll!"days"(9);
5062 assert(sysTime == SysTime(DateTime(-1999, 7, 15, 7, 9, 2), usecs(234578)));
5063 sysTime.roll!"days"(-11);
5064 assert(sysTime == SysTime(DateTime(-1999, 7, 4, 7, 9, 2), usecs(234578)));
5065 sysTime.roll!"days"(30);
5066 assert(sysTime == SysTime(DateTime(-1999, 7, 3, 7, 9, 2), usecs(234578)));
5067 sysTime.roll!"days"(-3);
5068 }
5069
5070 // Test Both
5071 {
5072 auto sysTime = SysTime(Date(1, 7, 6));
5073 sysTime.roll!"days"(-365);
5074 assert(sysTime == SysTime(Date(1, 7, 13)));
5075 sysTime.roll!"days"(365);
5076 assert(sysTime == SysTime(Date(1, 7, 6)));
5077 sysTime.roll!"days"(-731);
5078 assert(sysTime == SysTime(Date(1, 7, 19)));
5079 sysTime.roll!"days"(730);
5080 assert(sysTime == SysTime(Date(1, 7, 5)));
5081 }
5082
5083 {
5084 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
5085 sysTime.roll!"days"(-1);
5086 assert(sysTime == SysTime(DateTime(1, 1, 31, 0, 0, 0)));
5087 sysTime.roll!"days"(1);
5088 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5089 }
5090
5091 {
5092 auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999));
5093 sysTime.roll!"days"(-1);
5094 assert(sysTime == SysTime(DateTime(1, 1, 31, 23, 59, 59), hnsecs(9_999_999)));
5095 sysTime.roll!"days"(1);
5096 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
5097 }
5098
5099 {
5100 auto sysTime = SysTime(DateTime(0, 12, 31, 0, 0, 0));
5101 sysTime.roll!"days"(1);
5102 assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0)));
5103 sysTime.roll!"days"(-1);
5104 assert(sysTime == SysTime(DateTime(0, 12, 31, 0, 0, 0)));
5105 }
5106
5107 {
5108 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5109 sysTime.roll!"days"(1);
5110 assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)));
5111 sysTime.roll!"days"(-1);
5112 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5113 }
5114
5115 {
5116 auto sysTime = SysTime(DateTime(1, 7, 6, 13, 13, 9), msecs(22));
5117 sysTime.roll!"days"(-365);
5118 assert(sysTime == SysTime(DateTime(1, 7, 13, 13, 13, 9), msecs(22)));
5119 sysTime.roll!"days"(365);
5120 assert(sysTime == SysTime(DateTime(1, 7, 6, 13, 13, 9), msecs(22)));
5121 sysTime.roll!"days"(-731);
5122 assert(sysTime == SysTime(DateTime(1, 7, 19, 13, 13, 9), msecs(22)));
5123 sysTime.roll!"days"(730);
5124 assert(sysTime == SysTime(DateTime(1, 7, 5, 13, 13, 9), msecs(22)));
5125 }
5126
5127 {
5128 auto sysTime = SysTime(DateTime(0, 7, 6, 13, 13, 9), msecs(22));
5129 sysTime.roll!"days"(-365);
5130 assert(sysTime == SysTime(DateTime(0, 7, 13, 13, 13, 9), msecs(22)));
5131 sysTime.roll!"days"(365);
5132 assert(sysTime == SysTime(DateTime(0, 7, 6, 13, 13, 9), msecs(22)));
5133 sysTime.roll!"days"(-731);
5134 assert(sysTime == SysTime(DateTime(0, 7, 19, 13, 13, 9), msecs(22)));
5135 sysTime.roll!"days"(730);
5136 assert(sysTime == SysTime(DateTime(0, 7, 5, 13, 13, 9), msecs(22)));
5137 }
5138
5139 {
5140 auto sysTime = SysTime(DateTime(0, 7, 6, 13, 13, 9), msecs(22));
5141 sysTime.roll!"days"(-365).roll!"days"(362).roll!"days"(-12).roll!"days"(730);
5142 assert(sysTime == SysTime(DateTime(0, 7, 8, 13, 13, 9), msecs(22)));
5143 }
5144
5145 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5146 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5147 static assert(!__traits(compiles, cst.roll!"days"(4)));
5148 static assert(!__traits(compiles, ist.roll!"days"(4)));
5149
5150 static void testScope(scope ref SysTime st) @safe
5151 {
5152 auto result = st.roll!"days"(42);
5153 }
5154 }
5155
5156
5157 // Shares documentation with "days" version.
5158 ref SysTime roll(string units)(long value) @safe nothrow scope
5159 if (units == "hours" || units == "minutes" || units == "seconds")
5160 {
5161 try
5162 {
5163 auto hnsecs = adjTime;
5164 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
5165
5166 if (hnsecs < 0)
5167 {
5168 hnsecs += convert!("hours", "hnsecs")(24);
5169 --days;
5170 }
5171
5172 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
5173 immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
5174 immutable second = splitUnitsFromHNSecs!"seconds"(hnsecs);
5175
5176 auto dateTime = DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour,
5177 cast(int) minute, cast(int) second));
5178 dateTime.roll!units(value);
5179 --days;
5180
5181 hnsecs += convert!("hours", "hnsecs")(dateTime.hour);
5182 hnsecs += convert!("minutes", "hnsecs")(dateTime.minute);
5183 hnsecs += convert!("seconds", "hnsecs")(dateTime.second);
5184
5185 if (days < 0)
5186 {
5187 hnsecs -= convert!("hours", "hnsecs")(24);
5188 ++days;
5189 }
5190
5191 immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
5192 adjTime = newDaysHNSecs + hnsecs;
5193 return this;
5194 }
5195 catch (Exception e)
5196 assert(0, "Either DateTime's constructor or TimeOfDay's constructor threw.");
5197 }
5198
5199 // Test roll!"hours"().
5200 @safe unittest
5201 {
5202 import core.time;
5203 static void testST(SysTime orig, int hours, SysTime expected, size_t line = __LINE__) @safe
5204 {
5205 orig.roll!"hours"(hours);
5206 if (orig != expected)
5207 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
5208 }
5209
5210 // Test A.D.
5211 immutable d = msecs(45);
5212 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), d);
5213 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5214 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 13, 30, 33), d));
5215 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 14, 30, 33), d));
5216 testST(beforeAD, 3, SysTime(DateTime(1999, 7, 6, 15, 30, 33), d));
5217 testST(beforeAD, 4, SysTime(DateTime(1999, 7, 6, 16, 30, 33), d));
5218 testST(beforeAD, 5, SysTime(DateTime(1999, 7, 6, 17, 30, 33), d));
5219 testST(beforeAD, 6, SysTime(DateTime(1999, 7, 6, 18, 30, 33), d));
5220 testST(beforeAD, 7, SysTime(DateTime(1999, 7, 6, 19, 30, 33), d));
5221 testST(beforeAD, 8, SysTime(DateTime(1999, 7, 6, 20, 30, 33), d));
5222 testST(beforeAD, 9, SysTime(DateTime(1999, 7, 6, 21, 30, 33), d));
5223 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 22, 30, 33), d));
5224 testST(beforeAD, 11, SysTime(DateTime(1999, 7, 6, 23, 30, 33), d));
5225 testST(beforeAD, 12, SysTime(DateTime(1999, 7, 6, 0, 30, 33), d));
5226 testST(beforeAD, 13, SysTime(DateTime(1999, 7, 6, 1, 30, 33), d));
5227 testST(beforeAD, 14, SysTime(DateTime(1999, 7, 6, 2, 30, 33), d));
5228 testST(beforeAD, 15, SysTime(DateTime(1999, 7, 6, 3, 30, 33), d));
5229 testST(beforeAD, 16, SysTime(DateTime(1999, 7, 6, 4, 30, 33), d));
5230 testST(beforeAD, 17, SysTime(DateTime(1999, 7, 6, 5, 30, 33), d));
5231 testST(beforeAD, 18, SysTime(DateTime(1999, 7, 6, 6, 30, 33), d));
5232 testST(beforeAD, 19, SysTime(DateTime(1999, 7, 6, 7, 30, 33), d));
5233 testST(beforeAD, 20, SysTime(DateTime(1999, 7, 6, 8, 30, 33), d));
5234 testST(beforeAD, 21, SysTime(DateTime(1999, 7, 6, 9, 30, 33), d));
5235 testST(beforeAD, 22, SysTime(DateTime(1999, 7, 6, 10, 30, 33), d));
5236 testST(beforeAD, 23, SysTime(DateTime(1999, 7, 6, 11, 30, 33), d));
5237 testST(beforeAD, 24, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5238 testST(beforeAD, 25, SysTime(DateTime(1999, 7, 6, 13, 30, 33), d));
5239 testST(beforeAD, 50, SysTime(DateTime(1999, 7, 6, 14, 30, 33), d));
5240 testST(beforeAD, 10_000, SysTime(DateTime(1999, 7, 6, 4, 30, 33), d));
5241
5242 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 11, 30, 33), d));
5243 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 10, 30, 33), d));
5244 testST(beforeAD, -3, SysTime(DateTime(1999, 7, 6, 9, 30, 33), d));
5245 testST(beforeAD, -4, SysTime(DateTime(1999, 7, 6, 8, 30, 33), d));
5246 testST(beforeAD, -5, SysTime(DateTime(1999, 7, 6, 7, 30, 33), d));
5247 testST(beforeAD, -6, SysTime(DateTime(1999, 7, 6, 6, 30, 33), d));
5248 testST(beforeAD, -7, SysTime(DateTime(1999, 7, 6, 5, 30, 33), d));
5249 testST(beforeAD, -8, SysTime(DateTime(1999, 7, 6, 4, 30, 33), d));
5250 testST(beforeAD, -9, SysTime(DateTime(1999, 7, 6, 3, 30, 33), d));
5251 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 2, 30, 33), d));
5252 testST(beforeAD, -11, SysTime(DateTime(1999, 7, 6, 1, 30, 33), d));
5253 testST(beforeAD, -12, SysTime(DateTime(1999, 7, 6, 0, 30, 33), d));
5254 testST(beforeAD, -13, SysTime(DateTime(1999, 7, 6, 23, 30, 33), d));
5255 testST(beforeAD, -14, SysTime(DateTime(1999, 7, 6, 22, 30, 33), d));
5256 testST(beforeAD, -15, SysTime(DateTime(1999, 7, 6, 21, 30, 33), d));
5257 testST(beforeAD, -16, SysTime(DateTime(1999, 7, 6, 20, 30, 33), d));
5258 testST(beforeAD, -17, SysTime(DateTime(1999, 7, 6, 19, 30, 33), d));
5259 testST(beforeAD, -18, SysTime(DateTime(1999, 7, 6, 18, 30, 33), d));
5260 testST(beforeAD, -19, SysTime(DateTime(1999, 7, 6, 17, 30, 33), d));
5261 testST(beforeAD, -20, SysTime(DateTime(1999, 7, 6, 16, 30, 33), d));
5262 testST(beforeAD, -21, SysTime(DateTime(1999, 7, 6, 15, 30, 33), d));
5263 testST(beforeAD, -22, SysTime(DateTime(1999, 7, 6, 14, 30, 33), d));
5264 testST(beforeAD, -23, SysTime(DateTime(1999, 7, 6, 13, 30, 33), d));
5265 testST(beforeAD, -24, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5266 testST(beforeAD, -25, SysTime(DateTime(1999, 7, 6, 11, 30, 33), d));
5267 testST(beforeAD, -50, SysTime(DateTime(1999, 7, 6, 10, 30, 33), d));
5268 testST(beforeAD, -10_000, SysTime(DateTime(1999, 7, 6, 20, 30, 33), d));
5269
5270 testST(SysTime(DateTime(1999, 7, 6, 0, 30, 33), d), 1, SysTime(DateTime(1999, 7, 6, 1, 30, 33), d));
5271 testST(SysTime(DateTime(1999, 7, 6, 0, 30, 33), d), 0, SysTime(DateTime(1999, 7, 6, 0, 30, 33), d));
5272 testST(SysTime(DateTime(1999, 7, 6, 0, 30, 33), d), -1, SysTime(DateTime(1999, 7, 6, 23, 30, 33), d));
5273
5274 testST(SysTime(DateTime(1999, 7, 6, 23, 30, 33), d), 1, SysTime(DateTime(1999, 7, 6, 0, 30, 33), d));
5275 testST(SysTime(DateTime(1999, 7, 6, 23, 30, 33), d), 0, SysTime(DateTime(1999, 7, 6, 23, 30, 33), d));
5276 testST(SysTime(DateTime(1999, 7, 6, 23, 30, 33), d), -1, SysTime(DateTime(1999, 7, 6, 22, 30, 33), d));
5277
5278 testST(SysTime(DateTime(1999, 7, 31, 23, 30, 33), d), 1, SysTime(DateTime(1999, 7, 31, 0, 30, 33), d));
5279 testST(SysTime(DateTime(1999, 8, 1, 0, 30, 33), d), -1, SysTime(DateTime(1999, 8, 1, 23, 30, 33), d));
5280
5281 testST(SysTime(DateTime(1999, 12, 31, 23, 30, 33), d), 1, SysTime(DateTime(1999, 12, 31, 0, 30, 33), d));
5282 testST(SysTime(DateTime(2000, 1, 1, 0, 30, 33), d), -1, SysTime(DateTime(2000, 1, 1, 23, 30, 33), d));
5283
5284 testST(SysTime(DateTime(1999, 2, 28, 23, 30, 33), d), 25, SysTime(DateTime(1999, 2, 28, 0, 30, 33), d));
5285 testST(SysTime(DateTime(1999, 3, 2, 0, 30, 33), d), -25, SysTime(DateTime(1999, 3, 2, 23, 30, 33), d));
5286
5287 testST(SysTime(DateTime(2000, 2, 28, 23, 30, 33), d), 25, SysTime(DateTime(2000, 2, 28, 0, 30, 33), d));
5288 testST(SysTime(DateTime(2000, 3, 1, 0, 30, 33), d), -25, SysTime(DateTime(2000, 3, 1, 23, 30, 33), d));
5289
5290 // Test B.C.
5291 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d);
5292 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5293 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), d));
5294 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 14, 30, 33), d));
5295 testST(beforeBC, 3, SysTime(DateTime(-1999, 7, 6, 15, 30, 33), d));
5296 testST(beforeBC, 4, SysTime(DateTime(-1999, 7, 6, 16, 30, 33), d));
5297 testST(beforeBC, 5, SysTime(DateTime(-1999, 7, 6, 17, 30, 33), d));
5298 testST(beforeBC, 6, SysTime(DateTime(-1999, 7, 6, 18, 30, 33), d));
5299 testST(beforeBC, 7, SysTime(DateTime(-1999, 7, 6, 19, 30, 33), d));
5300 testST(beforeBC, 8, SysTime(DateTime(-1999, 7, 6, 20, 30, 33), d));
5301 testST(beforeBC, 9, SysTime(DateTime(-1999, 7, 6, 21, 30, 33), d));
5302 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 22, 30, 33), d));
5303 testST(beforeBC, 11, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d));
5304 testST(beforeBC, 12, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d));
5305 testST(beforeBC, 13, SysTime(DateTime(-1999, 7, 6, 1, 30, 33), d));
5306 testST(beforeBC, 14, SysTime(DateTime(-1999, 7, 6, 2, 30, 33), d));
5307 testST(beforeBC, 15, SysTime(DateTime(-1999, 7, 6, 3, 30, 33), d));
5308 testST(beforeBC, 16, SysTime(DateTime(-1999, 7, 6, 4, 30, 33), d));
5309 testST(beforeBC, 17, SysTime(DateTime(-1999, 7, 6, 5, 30, 33), d));
5310 testST(beforeBC, 18, SysTime(DateTime(-1999, 7, 6, 6, 30, 33), d));
5311 testST(beforeBC, 19, SysTime(DateTime(-1999, 7, 6, 7, 30, 33), d));
5312 testST(beforeBC, 20, SysTime(DateTime(-1999, 7, 6, 8, 30, 33), d));
5313 testST(beforeBC, 21, SysTime(DateTime(-1999, 7, 6, 9, 30, 33), d));
5314 testST(beforeBC, 22, SysTime(DateTime(-1999, 7, 6, 10, 30, 33), d));
5315 testST(beforeBC, 23, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), d));
5316 testST(beforeBC, 24, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5317 testST(beforeBC, 25, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), d));
5318 testST(beforeBC, 50, SysTime(DateTime(-1999, 7, 6, 14, 30, 33), d));
5319 testST(beforeBC, 10_000, SysTime(DateTime(-1999, 7, 6, 4, 30, 33), d));
5320
5321 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), d));
5322 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 10, 30, 33), d));
5323 testST(beforeBC, -3, SysTime(DateTime(-1999, 7, 6, 9, 30, 33), d));
5324 testST(beforeBC, -4, SysTime(DateTime(-1999, 7, 6, 8, 30, 33), d));
5325 testST(beforeBC, -5, SysTime(DateTime(-1999, 7, 6, 7, 30, 33), d));
5326 testST(beforeBC, -6, SysTime(DateTime(-1999, 7, 6, 6, 30, 33), d));
5327 testST(beforeBC, -7, SysTime(DateTime(-1999, 7, 6, 5, 30, 33), d));
5328 testST(beforeBC, -8, SysTime(DateTime(-1999, 7, 6, 4, 30, 33), d));
5329 testST(beforeBC, -9, SysTime(DateTime(-1999, 7, 6, 3, 30, 33), d));
5330 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 2, 30, 33), d));
5331 testST(beforeBC, -11, SysTime(DateTime(-1999, 7, 6, 1, 30, 33), d));
5332 testST(beforeBC, -12, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d));
5333 testST(beforeBC, -13, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d));
5334 testST(beforeBC, -14, SysTime(DateTime(-1999, 7, 6, 22, 30, 33), d));
5335 testST(beforeBC, -15, SysTime(DateTime(-1999, 7, 6, 21, 30, 33), d));
5336 testST(beforeBC, -16, SysTime(DateTime(-1999, 7, 6, 20, 30, 33), d));
5337 testST(beforeBC, -17, SysTime(DateTime(-1999, 7, 6, 19, 30, 33), d));
5338 testST(beforeBC, -18, SysTime(DateTime(-1999, 7, 6, 18, 30, 33), d));
5339 testST(beforeBC, -19, SysTime(DateTime(-1999, 7, 6, 17, 30, 33), d));
5340 testST(beforeBC, -20, SysTime(DateTime(-1999, 7, 6, 16, 30, 33), d));
5341 testST(beforeBC, -21, SysTime(DateTime(-1999, 7, 6, 15, 30, 33), d));
5342 testST(beforeBC, -22, SysTime(DateTime(-1999, 7, 6, 14, 30, 33), d));
5343 testST(beforeBC, -23, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), d));
5344 testST(beforeBC, -24, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5345 testST(beforeBC, -25, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), d));
5346 testST(beforeBC, -50, SysTime(DateTime(-1999, 7, 6, 10, 30, 33), d));
5347 testST(beforeBC, -10_000, SysTime(DateTime(-1999, 7, 6, 20, 30, 33), d));
5348
5349 testST(SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d), 1, SysTime(DateTime(-1999, 7, 6, 1, 30, 33), d));
5350 testST(SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d), 0, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d));
5351 testST(SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d), -1, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d));
5352
5353 testST(SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d), 1, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d));
5354 testST(SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d), 0, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d));
5355 testST(SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d), -1, SysTime(DateTime(-1999, 7, 6, 22, 30, 33), d));
5356
5357 testST(SysTime(DateTime(-1999, 7, 31, 23, 30, 33), d), 1, SysTime(DateTime(-1999, 7, 31, 0, 30, 33), d));
5358 testST(SysTime(DateTime(-1999, 8, 1, 0, 30, 33), d), -1, SysTime(DateTime(-1999, 8, 1, 23, 30, 33), d));
5359
5360 testST(SysTime(DateTime(-2001, 12, 31, 23, 30, 33), d), 1, SysTime(DateTime(-2001, 12, 31, 0, 30, 33), d));
5361 testST(SysTime(DateTime(-2000, 1, 1, 0, 30, 33), d), -1, SysTime(DateTime(-2000, 1, 1, 23, 30, 33), d));
5362
5363 testST(SysTime(DateTime(-2001, 2, 28, 23, 30, 33), d), 25, SysTime(DateTime(-2001, 2, 28, 0, 30, 33), d));
5364 testST(SysTime(DateTime(-2001, 3, 2, 0, 30, 33), d), -25, SysTime(DateTime(-2001, 3, 2, 23, 30, 33), d));
5365
5366 testST(SysTime(DateTime(-2000, 2, 28, 23, 30, 33), d), 25, SysTime(DateTime(-2000, 2, 28, 0, 30, 33), d));
5367 testST(SysTime(DateTime(-2000, 3, 1, 0, 30, 33), d), -25, SysTime(DateTime(-2000, 3, 1, 23, 30, 33), d));
5368
5369 // Test Both
5370 testST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), d), 17_546, SysTime(DateTime(-1, 1, 1, 13, 30, 33), d));
5371 testST(SysTime(DateTime(1, 1, 1, 13, 30, 33), d), -17_546, SysTime(DateTime(1, 1, 1, 11, 30, 33), d));
5372
5373 {
5374 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
5375 sysTime.roll!"hours"(-1);
5376 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 0, 0)));
5377 sysTime.roll!"hours"(1);
5378 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5379 }
5380
5381 {
5382 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 59, 59), hnsecs(9_999_999));
5383 sysTime.roll!"hours"(-1);
5384 assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
5385 sysTime.roll!"hours"(1);
5386 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 59, 59), hnsecs(9_999_999)));
5387 }
5388
5389 {
5390 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 0, 0));
5391 sysTime.roll!"hours"(1);
5392 assert(sysTime == SysTime(DateTime(0, 12, 31, 0, 0, 0)));
5393 sysTime.roll!"hours"(-1);
5394 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 0, 0)));
5395 }
5396
5397 {
5398 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5399 sysTime.roll!"hours"(1);
5400 assert(sysTime == SysTime(DateTime(0, 12, 31, 0, 59, 59), hnsecs(9_999_999)));
5401 sysTime.roll!"hours"(-1);
5402 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5403 }
5404
5405 {
5406 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5407 sysTime.roll!"hours"(1).roll!"hours"(-67);
5408 assert(sysTime == SysTime(DateTime(0, 12, 31, 5, 59, 59), hnsecs(9_999_999)));
5409 }
5410
5411 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5412 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5413 static assert(!__traits(compiles, cst.roll!"hours"(4)));
5414 static assert(!__traits(compiles, ist.roll!"hours"(4)));
5415
5416 static void testScope(scope ref SysTime st) @safe
5417 {
5418 auto result = st.roll!"hours"(42);
5419 }
5420 }
5421
5422 // Test roll!"minutes"().
5423 @safe unittest
5424 {
5425 import core.time;
5426 static void testST(SysTime orig, int minutes, SysTime expected, size_t line = __LINE__) @safe
5427 {
5428 orig.roll!"minutes"(minutes);
5429 if (orig != expected)
5430 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
5431 }
5432
5433 // Test A.D.
5434 immutable d = usecs(7203);
5435 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), d);
5436 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5437 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 31, 33), d));
5438 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 32, 33), d));
5439 testST(beforeAD, 3, SysTime(DateTime(1999, 7, 6, 12, 33, 33), d));
5440 testST(beforeAD, 4, SysTime(DateTime(1999, 7, 6, 12, 34, 33), d));
5441 testST(beforeAD, 5, SysTime(DateTime(1999, 7, 6, 12, 35, 33), d));
5442 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 40, 33), d));
5443 testST(beforeAD, 15, SysTime(DateTime(1999, 7, 6, 12, 45, 33), d));
5444 testST(beforeAD, 29, SysTime(DateTime(1999, 7, 6, 12, 59, 33), d));
5445 testST(beforeAD, 30, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5446 testST(beforeAD, 45, SysTime(DateTime(1999, 7, 6, 12, 15, 33), d));
5447 testST(beforeAD, 60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5448 testST(beforeAD, 75, SysTime(DateTime(1999, 7, 6, 12, 45, 33), d));
5449 testST(beforeAD, 90, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5450 testST(beforeAD, 100, SysTime(DateTime(1999, 7, 6, 12, 10, 33), d));
5451
5452 testST(beforeAD, 689, SysTime(DateTime(1999, 7, 6, 12, 59, 33), d));
5453 testST(beforeAD, 690, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5454 testST(beforeAD, 691, SysTime(DateTime(1999, 7, 6, 12, 1, 33), d));
5455 testST(beforeAD, 960, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5456 testST(beforeAD, 1439, SysTime(DateTime(1999, 7, 6, 12, 29, 33), d));
5457 testST(beforeAD, 1440, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5458 testST(beforeAD, 1441, SysTime(DateTime(1999, 7, 6, 12, 31, 33), d));
5459 testST(beforeAD, 2880, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5460
5461 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 29, 33), d));
5462 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 28, 33), d));
5463 testST(beforeAD, -3, SysTime(DateTime(1999, 7, 6, 12, 27, 33), d));
5464 testST(beforeAD, -4, SysTime(DateTime(1999, 7, 6, 12, 26, 33), d));
5465 testST(beforeAD, -5, SysTime(DateTime(1999, 7, 6, 12, 25, 33), d));
5466 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 20, 33), d));
5467 testST(beforeAD, -15, SysTime(DateTime(1999, 7, 6, 12, 15, 33), d));
5468 testST(beforeAD, -29, SysTime(DateTime(1999, 7, 6, 12, 1, 33), d));
5469 testST(beforeAD, -30, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5470 testST(beforeAD, -45, SysTime(DateTime(1999, 7, 6, 12, 45, 33), d));
5471 testST(beforeAD, -60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5472 testST(beforeAD, -75, SysTime(DateTime(1999, 7, 6, 12, 15, 33), d));
5473 testST(beforeAD, -90, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5474 testST(beforeAD, -100, SysTime(DateTime(1999, 7, 6, 12, 50, 33), d));
5475
5476 testST(beforeAD, -749, SysTime(DateTime(1999, 7, 6, 12, 1, 33), d));
5477 testST(beforeAD, -750, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5478 testST(beforeAD, -751, SysTime(DateTime(1999, 7, 6, 12, 59, 33), d));
5479 testST(beforeAD, -960, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5480 testST(beforeAD, -1439, SysTime(DateTime(1999, 7, 6, 12, 31, 33), d));
5481 testST(beforeAD, -1440, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5482 testST(beforeAD, -1441, SysTime(DateTime(1999, 7, 6, 12, 29, 33), d));
5483 testST(beforeAD, -2880, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5484
5485 testST(SysTime(DateTime(1999, 7, 6, 12, 0, 33), d), 1, SysTime(DateTime(1999, 7, 6, 12, 1, 33), d));
5486 testST(SysTime(DateTime(1999, 7, 6, 12, 0, 33), d), 0, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d));
5487 testST(SysTime(DateTime(1999, 7, 6, 12, 0, 33), d), -1, SysTime(DateTime(1999, 7, 6, 12, 59, 33), d));
5488
5489 testST(SysTime(DateTime(1999, 7, 6, 11, 59, 33), d), 1, SysTime(DateTime(1999, 7, 6, 11, 0, 33), d));
5490 testST(SysTime(DateTime(1999, 7, 6, 11, 59, 33), d), 0, SysTime(DateTime(1999, 7, 6, 11, 59, 33), d));
5491 testST(SysTime(DateTime(1999, 7, 6, 11, 59, 33), d), -1, SysTime(DateTime(1999, 7, 6, 11, 58, 33), d));
5492
5493 testST(SysTime(DateTime(1999, 7, 6, 0, 0, 33), d), 1, SysTime(DateTime(1999, 7, 6, 0, 1, 33), d));
5494 testST(SysTime(DateTime(1999, 7, 6, 0, 0, 33), d), 0, SysTime(DateTime(1999, 7, 6, 0, 0, 33), d));
5495 testST(SysTime(DateTime(1999, 7, 6, 0, 0, 33), d), -1, SysTime(DateTime(1999, 7, 6, 0, 59, 33), d));
5496
5497 testST(SysTime(DateTime(1999, 7, 5, 23, 59, 33), d), 1, SysTime(DateTime(1999, 7, 5, 23, 0, 33), d));
5498 testST(SysTime(DateTime(1999, 7, 5, 23, 59, 33), d), 0, SysTime(DateTime(1999, 7, 5, 23, 59, 33), d));
5499 testST(SysTime(DateTime(1999, 7, 5, 23, 59, 33), d), -1, SysTime(DateTime(1999, 7, 5, 23, 58, 33), d));
5500
5501 testST(SysTime(DateTime(1998, 12, 31, 23, 59, 33), d), 1, SysTime(DateTime(1998, 12, 31, 23, 0, 33), d));
5502 testST(SysTime(DateTime(1998, 12, 31, 23, 59, 33), d), 0, SysTime(DateTime(1998, 12, 31, 23, 59, 33), d));
5503 testST(SysTime(DateTime(1998, 12, 31, 23, 59, 33), d), -1, SysTime(DateTime(1998, 12, 31, 23, 58, 33), d));
5504
5505 // Test B.C.
5506 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d);
5507 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5508 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), d));
5509 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 32, 33), d));
5510 testST(beforeBC, 3, SysTime(DateTime(-1999, 7, 6, 12, 33, 33), d));
5511 testST(beforeBC, 4, SysTime(DateTime(-1999, 7, 6, 12, 34, 33), d));
5512 testST(beforeBC, 5, SysTime(DateTime(-1999, 7, 6, 12, 35, 33), d));
5513 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 40, 33), d));
5514 testST(beforeBC, 15, SysTime(DateTime(-1999, 7, 6, 12, 45, 33), d));
5515 testST(beforeBC, 29, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), d));
5516 testST(beforeBC, 30, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5517 testST(beforeBC, 45, SysTime(DateTime(-1999, 7, 6, 12, 15, 33), d));
5518 testST(beforeBC, 60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5519 testST(beforeBC, 75, SysTime(DateTime(-1999, 7, 6, 12, 45, 33), d));
5520 testST(beforeBC, 90, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5521 testST(beforeBC, 100, SysTime(DateTime(-1999, 7, 6, 12, 10, 33), d));
5522
5523 testST(beforeBC, 689, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), d));
5524 testST(beforeBC, 690, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5525 testST(beforeBC, 691, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), d));
5526 testST(beforeBC, 960, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5527 testST(beforeBC, 1439, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), d));
5528 testST(beforeBC, 1440, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5529 testST(beforeBC, 1441, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), d));
5530 testST(beforeBC, 2880, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5531
5532 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), d));
5533 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 28, 33), d));
5534 testST(beforeBC, -3, SysTime(DateTime(-1999, 7, 6, 12, 27, 33), d));
5535 testST(beforeBC, -4, SysTime(DateTime(-1999, 7, 6, 12, 26, 33), d));
5536 testST(beforeBC, -5, SysTime(DateTime(-1999, 7, 6, 12, 25, 33), d));
5537 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 20, 33), d));
5538 testST(beforeBC, -15, SysTime(DateTime(-1999, 7, 6, 12, 15, 33), d));
5539 testST(beforeBC, -29, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), d));
5540 testST(beforeBC, -30, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5541 testST(beforeBC, -45, SysTime(DateTime(-1999, 7, 6, 12, 45, 33), d));
5542 testST(beforeBC, -60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5543 testST(beforeBC, -75, SysTime(DateTime(-1999, 7, 6, 12, 15, 33), d));
5544 testST(beforeBC, -90, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5545 testST(beforeBC, -100, SysTime(DateTime(-1999, 7, 6, 12, 50, 33), d));
5546
5547 testST(beforeBC, -749, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), d));
5548 testST(beforeBC, -750, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5549 testST(beforeBC, -751, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), d));
5550 testST(beforeBC, -960, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5551 testST(beforeBC, -1439, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), d));
5552 testST(beforeBC, -1440, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5553 testST(beforeBC, -1441, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), d));
5554 testST(beforeBC, -2880, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5555
5556 testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d), 1, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), d));
5557 testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d), 0, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d));
5558 testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d), -1, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), d));
5559
5560 testST(SysTime(DateTime(-1999, 7, 6, 11, 59, 33), d), 1, SysTime(DateTime(-1999, 7, 6, 11, 0, 33), d));
5561 testST(SysTime(DateTime(-1999, 7, 6, 11, 59, 33), d), 0, SysTime(DateTime(-1999, 7, 6, 11, 59, 33), d));
5562 testST(SysTime(DateTime(-1999, 7, 6, 11, 59, 33), d), -1, SysTime(DateTime(-1999, 7, 6, 11, 58, 33), d));
5563
5564 testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 33), d), 1, SysTime(DateTime(-1999, 7, 6, 0, 1, 33), d));
5565 testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 33), d), 0, SysTime(DateTime(-1999, 7, 6, 0, 0, 33), d));
5566 testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 33), d), -1, SysTime(DateTime(-1999, 7, 6, 0, 59, 33), d));
5567
5568 testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 33), d), 1, SysTime(DateTime(-1999, 7, 5, 23, 0, 33), d));
5569 testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 33), d), 0, SysTime(DateTime(-1999, 7, 5, 23, 59, 33), d));
5570 testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 33), d), -1, SysTime(DateTime(-1999, 7, 5, 23, 58, 33), d));
5571
5572 testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 33), d), 1, SysTime(DateTime(-2000, 12, 31, 23, 0, 33), d));
5573 testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 33), d), 0, SysTime(DateTime(-2000, 12, 31, 23, 59, 33), d));
5574 testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 33), d), -1, SysTime(DateTime(-2000, 12, 31, 23, 58, 33), d));
5575
5576 // Test Both
5577 testST(SysTime(DateTime(1, 1, 1, 0, 0, 0)), -1, SysTime(DateTime(1, 1, 1, 0, 59, 0)));
5578 testST(SysTime(DateTime(0, 12, 31, 23, 59, 0)), 1, SysTime(DateTime(0, 12, 31, 23, 0, 0)));
5579
5580 testST(SysTime(DateTime(0, 1, 1, 0, 0, 0)), -1, SysTime(DateTime(0, 1, 1, 0, 59, 0)));
5581 testST(SysTime(DateTime(-1, 12, 31, 23, 59, 0)), 1, SysTime(DateTime(-1, 12, 31, 23, 0, 0)));
5582
5583 testST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), d), 1_052_760, SysTime(DateTime(-1, 1, 1, 11, 30, 33), d));
5584 testST(SysTime(DateTime(1, 1, 1, 13, 30, 33), d), -1_052_760, SysTime(DateTime(1, 1, 1, 13, 30, 33), d));
5585
5586 testST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), d), 1_052_782, SysTime(DateTime(-1, 1, 1, 11, 52, 33), d));
5587 testST(SysTime(DateTime(1, 1, 1, 13, 52, 33), d), -1_052_782, SysTime(DateTime(1, 1, 1, 13, 30, 33), d));
5588
5589 {
5590 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
5591 sysTime.roll!"minutes"(-1);
5592 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 59, 0)));
5593 sysTime.roll!"minutes"(1);
5594 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5595 }
5596
5597 {
5598 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 59), hnsecs(9_999_999));
5599 sysTime.roll!"minutes"(-1);
5600 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 59, 59), hnsecs(9_999_999)));
5601 sysTime.roll!"minutes"(1);
5602 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 59), hnsecs(9_999_999)));
5603 }
5604
5605 {
5606 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 0));
5607 sysTime.roll!"minutes"(1);
5608 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 0, 0)));
5609 sysTime.roll!"minutes"(-1);
5610 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 0)));
5611 }
5612
5613 {
5614 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5615 sysTime.roll!"minutes"(1);
5616 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 0, 59), hnsecs(9_999_999)));
5617 sysTime.roll!"minutes"(-1);
5618 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5619 }
5620
5621 {
5622 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5623 sysTime.roll!"minutes"(1).roll!"minutes"(-79);
5624 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 41, 59), hnsecs(9_999_999)));
5625 }
5626
5627 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5628 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5629 static assert(!__traits(compiles, cst.roll!"minutes"(4)));
5630 static assert(!__traits(compiles, ist.roll!"minutes"(4)));
5631
5632 static void testScope(scope ref SysTime st) @safe
5633 {
5634 auto result = st.roll!"minutes"(42);
5635 }
5636 }
5637
5638 // Test roll!"seconds"().
5639 @safe unittest
5640 {
5641 import core.time;
5642 static void testST(SysTime orig, int seconds, SysTime expected, size_t line = __LINE__) @safe
5643 {
5644 orig.roll!"seconds"(seconds);
5645 if (orig != expected)
5646 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
5647 }
5648
5649 // Test A.D.
5650 immutable d = msecs(274);
5651 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), d);
5652 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5653 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 30, 34), d));
5654 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 30, 35), d));
5655 testST(beforeAD, 3, SysTime(DateTime(1999, 7, 6, 12, 30, 36), d));
5656 testST(beforeAD, 4, SysTime(DateTime(1999, 7, 6, 12, 30, 37), d));
5657 testST(beforeAD, 5, SysTime(DateTime(1999, 7, 6, 12, 30, 38), d));
5658 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 30, 43), d));
5659 testST(beforeAD, 15, SysTime(DateTime(1999, 7, 6, 12, 30, 48), d));
5660 testST(beforeAD, 26, SysTime(DateTime(1999, 7, 6, 12, 30, 59), d));
5661 testST(beforeAD, 27, SysTime(DateTime(1999, 7, 6, 12, 30, 0), d));
5662 testST(beforeAD, 30, SysTime(DateTime(1999, 7, 6, 12, 30, 3), d));
5663 testST(beforeAD, 59, SysTime(DateTime(1999, 7, 6, 12, 30, 32), d));
5664 testST(beforeAD, 60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5665 testST(beforeAD, 61, SysTime(DateTime(1999, 7, 6, 12, 30, 34), d));
5666
5667 testST(beforeAD, 1766, SysTime(DateTime(1999, 7, 6, 12, 30, 59), d));
5668 testST(beforeAD, 1767, SysTime(DateTime(1999, 7, 6, 12, 30, 0), d));
5669 testST(beforeAD, 1768, SysTime(DateTime(1999, 7, 6, 12, 30, 1), d));
5670 testST(beforeAD, 2007, SysTime(DateTime(1999, 7, 6, 12, 30, 0), d));
5671 testST(beforeAD, 3599, SysTime(DateTime(1999, 7, 6, 12, 30, 32), d));
5672 testST(beforeAD, 3600, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5673 testST(beforeAD, 3601, SysTime(DateTime(1999, 7, 6, 12, 30, 34), d));
5674 testST(beforeAD, 7200, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5675
5676 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 30, 32), d));
5677 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 30, 31), d));
5678 testST(beforeAD, -3, SysTime(DateTime(1999, 7, 6, 12, 30, 30), d));
5679 testST(beforeAD, -4, SysTime(DateTime(1999, 7, 6, 12, 30, 29), d));
5680 testST(beforeAD, -5, SysTime(DateTime(1999, 7, 6, 12, 30, 28), d));
5681 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 30, 23), d));
5682 testST(beforeAD, -15, SysTime(DateTime(1999, 7, 6, 12, 30, 18), d));
5683 testST(beforeAD, -33, SysTime(DateTime(1999, 7, 6, 12, 30, 0), d));
5684 testST(beforeAD, -34, SysTime(DateTime(1999, 7, 6, 12, 30, 59), d));
5685 testST(beforeAD, -35, SysTime(DateTime(1999, 7, 6, 12, 30, 58), d));
5686 testST(beforeAD, -59, SysTime(DateTime(1999, 7, 6, 12, 30, 34), d));
5687 testST(beforeAD, -60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d));
5688 testST(beforeAD, -61, SysTime(DateTime(1999, 7, 6, 12, 30, 32), d));
5689
5690 testST(SysTime(DateTime(1999, 7, 6, 12, 30, 0), d), 1, SysTime(DateTime(1999, 7, 6, 12, 30, 1), d));
5691 testST(SysTime(DateTime(1999, 7, 6, 12, 30, 0), d), 0, SysTime(DateTime(1999, 7, 6, 12, 30, 0), d));
5692 testST(SysTime(DateTime(1999, 7, 6, 12, 30, 0), d), -1, SysTime(DateTime(1999, 7, 6, 12, 30, 59), d));
5693
5694 testST(SysTime(DateTime(1999, 7, 6, 12, 0, 0), d), 1, SysTime(DateTime(1999, 7, 6, 12, 0, 1), d));
5695 testST(SysTime(DateTime(1999, 7, 6, 12, 0, 0), d), 0, SysTime(DateTime(1999, 7, 6, 12, 0, 0), d));
5696 testST(SysTime(DateTime(1999, 7, 6, 12, 0, 0), d), -1, SysTime(DateTime(1999, 7, 6, 12, 0, 59), d));
5697
5698 testST(SysTime(DateTime(1999, 7, 6, 0, 0, 0), d), 1, SysTime(DateTime(1999, 7, 6, 0, 0, 1), d));
5699 testST(SysTime(DateTime(1999, 7, 6, 0, 0, 0), d), 0, SysTime(DateTime(1999, 7, 6, 0, 0, 0), d));
5700 testST(SysTime(DateTime(1999, 7, 6, 0, 0, 0), d), -1, SysTime(DateTime(1999, 7, 6, 0, 0, 59), d));
5701
5702 testST(SysTime(DateTime(1999, 7, 5, 23, 59, 59), d), 1, SysTime(DateTime(1999, 7, 5, 23, 59, 0), d));
5703 testST(SysTime(DateTime(1999, 7, 5, 23, 59, 59), d), 0, SysTime(DateTime(1999, 7, 5, 23, 59, 59), d));
5704 testST(SysTime(DateTime(1999, 7, 5, 23, 59, 59), d), -1, SysTime(DateTime(1999, 7, 5, 23, 59, 58), d));
5705
5706 testST(SysTime(DateTime(1998, 12, 31, 23, 59, 59), d), 1, SysTime(DateTime(1998, 12, 31, 23, 59, 0), d));
5707 testST(SysTime(DateTime(1998, 12, 31, 23, 59, 59), d), 0, SysTime(DateTime(1998, 12, 31, 23, 59, 59), d));
5708 testST(SysTime(DateTime(1998, 12, 31, 23, 59, 59), d), -1, SysTime(DateTime(1998, 12, 31, 23, 59, 58), d));
5709
5710 // Test B.C.
5711 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d);
5712 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5713 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), d));
5714 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 35), d));
5715 testST(beforeBC, 3, SysTime(DateTime(-1999, 7, 6, 12, 30, 36), d));
5716 testST(beforeBC, 4, SysTime(DateTime(-1999, 7, 6, 12, 30, 37), d));
5717 testST(beforeBC, 5, SysTime(DateTime(-1999, 7, 6, 12, 30, 38), d));
5718 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 43), d));
5719 testST(beforeBC, 15, SysTime(DateTime(-1999, 7, 6, 12, 30, 48), d));
5720 testST(beforeBC, 26, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), d));
5721 testST(beforeBC, 27, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d));
5722 testST(beforeBC, 30, SysTime(DateTime(-1999, 7, 6, 12, 30, 3), d));
5723 testST(beforeBC, 59, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), d));
5724 testST(beforeBC, 60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5725 testST(beforeBC, 61, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), d));
5726
5727 testST(beforeBC, 1766, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), d));
5728 testST(beforeBC, 1767, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d));
5729 testST(beforeBC, 1768, SysTime(DateTime(-1999, 7, 6, 12, 30, 1), d));
5730 testST(beforeBC, 2007, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d));
5731 testST(beforeBC, 3599, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), d));
5732 testST(beforeBC, 3600, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5733 testST(beforeBC, 3601, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), d));
5734 testST(beforeBC, 7200, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5735
5736 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), d));
5737 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 31), d));
5738 testST(beforeBC, -3, SysTime(DateTime(-1999, 7, 6, 12, 30, 30), d));
5739 testST(beforeBC, -4, SysTime(DateTime(-1999, 7, 6, 12, 30, 29), d));
5740 testST(beforeBC, -5, SysTime(DateTime(-1999, 7, 6, 12, 30, 28), d));
5741 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 23), d));
5742 testST(beforeBC, -15, SysTime(DateTime(-1999, 7, 6, 12, 30, 18), d));
5743 testST(beforeBC, -33, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d));
5744 testST(beforeBC, -34, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), d));
5745 testST(beforeBC, -35, SysTime(DateTime(-1999, 7, 6, 12, 30, 58), d));
5746 testST(beforeBC, -59, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), d));
5747 testST(beforeBC, -60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d));
5748 testST(beforeBC, -61, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), d));
5749
5750 testST(SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d), 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 1), d));
5751 testST(SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d), 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d));
5752 testST(SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d), -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), d));
5753
5754 testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 0), d), 1, SysTime(DateTime(-1999, 7, 6, 12, 0, 1), d));
5755 testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 0), d), 0, SysTime(DateTime(-1999, 7, 6, 12, 0, 0), d));
5756 testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 0), d), -1, SysTime(DateTime(-1999, 7, 6, 12, 0, 59), d));
5757
5758 testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 0), d), 1, SysTime(DateTime(-1999, 7, 6, 0, 0, 1), d));
5759 testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 0), d), 0, SysTime(DateTime(-1999, 7, 6, 0, 0, 0), d));
5760 testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 0), d), -1, SysTime(DateTime(-1999, 7, 6, 0, 0, 59), d));
5761
5762 testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 59), d), 1, SysTime(DateTime(-1999, 7, 5, 23, 59, 0), d));
5763 testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 59), d), 0, SysTime(DateTime(-1999, 7, 5, 23, 59, 59), d));
5764 testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 59), d), -1, SysTime(DateTime(-1999, 7, 5, 23, 59, 58), d));
5765
5766 testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 59), d), 1, SysTime(DateTime(-2000, 12, 31, 23, 59, 0), d));
5767 testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 59), d), 0, SysTime(DateTime(-2000, 12, 31, 23, 59, 59), d));
5768 testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 59), d), -1, SysTime(DateTime(-2000, 12, 31, 23, 59, 58), d));
5769
5770 // Test Both
5771 testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), d), -1, SysTime(DateTime(1, 1, 1, 0, 0, 59), d));
5772 testST(SysTime(DateTime(0, 12, 31, 23, 59, 59), d), 1, SysTime(DateTime(0, 12, 31, 23, 59, 0), d));
5773
5774 testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), d), -1, SysTime(DateTime(0, 1, 1, 0, 0, 59), d));
5775 testST(SysTime(DateTime(-1, 12, 31, 23, 59, 59), d), 1, SysTime(DateTime(-1, 12, 31, 23, 59, 0), d));
5776
5777 testST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), d), 63_165_600L, SysTime(DateTime(-1, 1, 1, 11, 30, 33), d));
5778 testST(SysTime(DateTime(1, 1, 1, 13, 30, 33), d), -63_165_600L, SysTime(DateTime(1, 1, 1, 13, 30, 33), d));
5779
5780 testST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), d), 63_165_617L, SysTime(DateTime(-1, 1, 1, 11, 30, 50), d));
5781 testST(SysTime(DateTime(1, 1, 1, 13, 30, 50), d), -63_165_617L, SysTime(DateTime(1, 1, 1, 13, 30, 33), d));
5782
5783 {
5784 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0));
5785 sysTime.roll!"seconds"(-1);
5786 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 59)));
5787 sysTime.roll!"seconds"(1);
5788 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5789 }
5790
5791 {
5792 auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(9_999_999));
5793 sysTime.roll!"seconds"(-1);
5794 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 59), hnsecs(9_999_999)));
5795 sysTime.roll!"seconds"(1);
5796 assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
5797 }
5798
5799 {
5800 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59));
5801 sysTime.roll!"seconds"(1);
5802 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 0)));
5803 sysTime.roll!"seconds"(-1);
5804 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 59)));
5805 }
5806
5807 {
5808 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5809 sysTime.roll!"seconds"(1);
5810 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 0), hnsecs(9_999_999)));
5811 sysTime.roll!"seconds"(-1);
5812 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5813 }
5814
5815 {
5816 auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5817 sysTime.roll!"seconds"(1).roll!"seconds"(-102);
5818 assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 18), hnsecs(9_999_999)));
5819 }
5820
5821 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5822 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5823 static assert(!__traits(compiles, cst.roll!"seconds"(4)));
5824 static assert(!__traits(compiles, ist.roll!"seconds"(4)));
5825
5826 static void testScope(scope ref SysTime st) @safe
5827 {
5828 auto result = st.roll!"seconds"(42);
5829 }
5830 }
5831
5832
5833 // Shares documentation with "days" version.
5834 ref SysTime roll(string units)(long value) @safe nothrow scope
5835 if (units == "msecs" || units == "usecs" || units == "hnsecs")
5836 {
5837 auto hnsecs = adjTime;
5838 immutable days = splitUnitsFromHNSecs!"days"(hnsecs);
5839 immutable negative = hnsecs < 0;
5840
5841 if (negative)
5842 hnsecs += convert!("hours", "hnsecs")(24);
5843
5844 immutable seconds = splitUnitsFromHNSecs!"seconds"(hnsecs);
5845 hnsecs += convert!(units, "hnsecs")(value);
5846 hnsecs %= convert!("seconds", "hnsecs")(1);
5847
5848 if (hnsecs < 0)
5849 hnsecs += convert!("seconds", "hnsecs")(1);
5850 hnsecs += convert!("seconds", "hnsecs")(seconds);
5851
5852 if (negative)
5853 hnsecs -= convert!("hours", "hnsecs")(24);
5854
5855 immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
5856 adjTime = newDaysHNSecs + hnsecs;
5857 return this;
5858 }
5859
5860
5861 // Test roll!"msecs"().
5862 @safe unittest
5863 {
5864 import core.time;
5865 static void testST(SysTime orig, int milliseconds, SysTime expected, size_t line = __LINE__) @safe
5866 {
5867 orig.roll!"msecs"(milliseconds);
5868 if (orig != expected)
5869 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
5870 }
5871
5872 // Test A.D.
5873 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274));
5874 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274)));
5875 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(275)));
5876 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(276)));
5877 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(284)));
5878 testST(beforeAD, 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(374)));
5879 testST(beforeAD, 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999)));
5880 testST(beforeAD, 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5881 testST(beforeAD, 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274)));
5882 testST(beforeAD, 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(275)));
5883 testST(beforeAD, 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274)));
5884 testST(beforeAD, 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999)));
5885 testST(beforeAD, 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5886 testST(beforeAD, 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(1)));
5887 testST(beforeAD, 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999)));
5888 testST(beforeAD, 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5889
5890 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(273)));
5891 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(272)));
5892 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(264)));
5893 testST(beforeAD, -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(174)));
5894 testST(beforeAD, -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5895 testST(beforeAD, -275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999)));
5896 testST(beforeAD, -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274)));
5897 testST(beforeAD, -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(273)));
5898 testST(beforeAD, -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274)));
5899 testST(beforeAD, -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5900 testST(beforeAD, -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999)));
5901 testST(beforeAD, -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
5902 testST(beforeAD, -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999)));
5903
5904 // Test B.C.
5905 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274));
5906 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274)));
5907 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(275)));
5908 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(276)));
5909 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(284)));
5910 testST(beforeBC, 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(374)));
5911 testST(beforeBC, 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999)));
5912 testST(beforeBC, 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5913 testST(beforeBC, 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274)));
5914 testST(beforeBC, 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(275)));
5915 testST(beforeBC, 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274)));
5916 testST(beforeBC, 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999)));
5917 testST(beforeBC, 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5918 testST(beforeBC, 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(1)));
5919 testST(beforeBC, 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999)));
5920 testST(beforeBC, 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5921
5922 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(273)));
5923 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(272)));
5924 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(264)));
5925 testST(beforeBC, -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(174)));
5926 testST(beforeBC, -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5927 testST(beforeBC, -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999)));
5928 testST(beforeBC, -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274)));
5929 testST(beforeBC, -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(273)));
5930 testST(beforeBC, -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274)));
5931 testST(beforeBC, -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5932 testST(beforeBC, -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999)));
5933 testST(beforeBC, -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
5934 testST(beforeBC, -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999)));
5935
5936 // Test Both
5937 auto beforeBoth1 = SysTime(DateTime(1, 1, 1, 0, 0, 0));
5938 testST(beforeBoth1, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), msecs(1)));
5939 testST(beforeBoth1, 0, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5940 testST(beforeBoth1, -1, SysTime(DateTime(1, 1, 1, 0, 0, 0), msecs(999)));
5941 testST(beforeBoth1, -2, SysTime(DateTime(1, 1, 1, 0, 0, 0), msecs(998)));
5942 testST(beforeBoth1, -1000, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5943 testST(beforeBoth1, -2000, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
5944 testST(beforeBoth1, -2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), msecs(445)));
5945
5946 auto beforeBoth2 = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5947 testST(beforeBoth2, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_989_999)));
5948 testST(beforeBoth2, 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5949 testST(beforeBoth2, 1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9999)));
5950 testST(beforeBoth2, 2, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(19_999)));
5951 testST(beforeBoth2, 1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5952 testST(beforeBoth2, 2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
5953 testST(beforeBoth2, 2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(5_549_999)));
5954
5955 {
5956 auto st = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
5957 st.roll!"msecs"(1202).roll!"msecs"(-703);
5958 assert(st == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(4_989_999)));
5959 }
5960
5961 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5962 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
5963 static assert(!__traits(compiles, cst.roll!"msecs"(4)));
5964 static assert(!__traits(compiles, ist.roll!"msecs"(4)));
5965
5966 static void testScope(scope ref SysTime st) @safe
5967 {
5968 auto result = st.roll!"msecs"(42);
5969 }
5970 }
5971
5972 // Test roll!"usecs"().
5973 @safe unittest
5974 {
5975 import core.time;
5976 static void testST(SysTime orig, long microseconds, SysTime expected, size_t line = __LINE__) @safe
5977 {
5978 orig.roll!"usecs"(microseconds);
5979 if (orig != expected)
5980 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
5981 }
5982
5983 // Test A.D.
5984 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274));
5985 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
5986 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(275)));
5987 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(276)));
5988 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(284)));
5989 testST(beforeAD, 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(374)));
5990 testST(beforeAD, 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(999)));
5991 testST(beforeAD, 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(1000)));
5992 testST(beforeAD, 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(1274)));
5993 testST(beforeAD, 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(1275)));
5994 testST(beforeAD, 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(2274)));
5995 testST(beforeAD, 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(26_999)));
5996 testST(beforeAD, 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(27_000)));
5997 testST(beforeAD, 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(27_001)));
5998 testST(beforeAD, 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(766_999)));
5999 testST(beforeAD, 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(767_000)));
6000 testST(beforeAD, 1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
6001 testST(beforeAD, 60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
6002 testST(beforeAD, 3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
6003
6004 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(273)));
6005 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(272)));
6006 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(264)));
6007 testST(beforeAD, -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(174)));
6008 testST(beforeAD, -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
6009 testST(beforeAD, -275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(999_999)));
6010 testST(beforeAD, -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(999_274)));
6011 testST(beforeAD, -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(999_273)));
6012 testST(beforeAD, -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(998_274)));
6013 testST(beforeAD, -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(967_000)));
6014 testST(beforeAD, -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(966_999)));
6015 testST(beforeAD, -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(167_000)));
6016 testST(beforeAD, -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(166_999)));
6017 testST(beforeAD, -1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
6018 testST(beforeAD, -60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
6019 testST(beforeAD, -3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)));
6020
6021 // Test B.C.
6022 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274));
6023 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
6024 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(275)));
6025 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(276)));
6026 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(284)));
6027 testST(beforeBC, 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(374)));
6028 testST(beforeBC, 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(999)));
6029 testST(beforeBC, 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(1000)));
6030 testST(beforeBC, 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(1274)));
6031 testST(beforeBC, 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(1275)));
6032 testST(beforeBC, 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(2274)));
6033 testST(beforeBC, 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(26_999)));
6034 testST(beforeBC, 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(27_000)));
6035 testST(beforeBC, 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(27_001)));
6036 testST(beforeBC, 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(766_999)));
6037 testST(beforeBC, 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(767_000)));
6038 testST(beforeBC, 1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
6039 testST(beforeBC, 60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
6040 testST(beforeBC, 3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
6041
6042 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(273)));
6043 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(272)));
6044 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(264)));
6045 testST(beforeBC, -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(174)));
6046 testST(beforeBC, -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
6047 testST(beforeBC, -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(999_999)));
6048 testST(beforeBC, -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(999_274)));
6049 testST(beforeBC, -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(999_273)));
6050 testST(beforeBC, -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(998_274)));
6051 testST(beforeBC, -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(967_000)));
6052 testST(beforeBC, -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(966_999)));
6053 testST(beforeBC, -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(167_000)));
6054 testST(beforeBC, -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(166_999)));
6055 testST(beforeBC, -1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
6056 testST(beforeBC, -60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
6057 testST(beforeBC, -3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)));
6058
6059 // Test Both
6060 auto beforeBoth1 = SysTime(DateTime(1, 1, 1, 0, 0, 0));
6061 testST(beforeBoth1, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(1)));
6062 testST(beforeBoth1, 0, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6063 testST(beforeBoth1, -1, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(999_999)));
6064 testST(beforeBoth1, -2, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(999_998)));
6065 testST(beforeBoth1, -1000, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(999_000)));
6066 testST(beforeBoth1, -2000, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(998_000)));
6067 testST(beforeBoth1, -2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(997_445)));
6068 testST(beforeBoth1, -1_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6069 testST(beforeBoth1, -2_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6070 testST(beforeBoth1, -2_333_333, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(666_667)));
6071
6072 auto beforeBoth2 = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
6073 testST(beforeBoth2, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_989)));
6074 testST(beforeBoth2, 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6075 testST(beforeBoth2, 1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9)));
6076 testST(beforeBoth2, 2, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(19)));
6077 testST(beforeBoth2, 1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9999)));
6078 testST(beforeBoth2, 2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(19_999)));
6079 testST(beforeBoth2, 2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(25_549)));
6080 testST(beforeBoth2, 1_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6081 testST(beforeBoth2, 2_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6082 testST(beforeBoth2, 2_333_333, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(3_333_329)));
6083
6084 {
6085 auto st = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
6086 st.roll!"usecs"(9_020_027);
6087 assert(st == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(200_269)));
6088 }
6089
6090 {
6091 auto st = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
6092 st.roll!"usecs"(9_020_027).roll!"usecs"(-70_034);
6093 assert(st == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_499_929)));
6094 }
6095
6096 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6097 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6098 static assert(!__traits(compiles, cst.roll!"usecs"(4)));
6099 static assert(!__traits(compiles, ist.roll!"usecs"(4)));
6100
6101 static void testScope(scope ref SysTime st) @safe
6102 {
6103 auto result = st.roll!"usecs"(42);
6104 }
6105 }
6106
6107 // Test roll!"hnsecs"().
6108 @safe unittest
6109 {
6110 import core.time;
6111 static void testST(SysTime orig, long hnsecs, SysTime expected, size_t line = __LINE__) @safe
6112 {
6113 orig.roll!"hnsecs"(hnsecs);
6114 if (orig != expected)
6115 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
6116 }
6117
6118 // Test A.D.
6119 auto dtAD = DateTime(1999, 7, 6, 12, 30, 33);
6120 auto beforeAD = SysTime(dtAD, hnsecs(274));
6121 testST(beforeAD, 0, SysTime(dtAD, hnsecs(274)));
6122 testST(beforeAD, 1, SysTime(dtAD, hnsecs(275)));
6123 testST(beforeAD, 2, SysTime(dtAD, hnsecs(276)));
6124 testST(beforeAD, 10, SysTime(dtAD, hnsecs(284)));
6125 testST(beforeAD, 100, SysTime(dtAD, hnsecs(374)));
6126 testST(beforeAD, 725, SysTime(dtAD, hnsecs(999)));
6127 testST(beforeAD, 726, SysTime(dtAD, hnsecs(1000)));
6128 testST(beforeAD, 1000, SysTime(dtAD, hnsecs(1274)));
6129 testST(beforeAD, 1001, SysTime(dtAD, hnsecs(1275)));
6130 testST(beforeAD, 2000, SysTime(dtAD, hnsecs(2274)));
6131 testST(beforeAD, 26_725, SysTime(dtAD, hnsecs(26_999)));
6132 testST(beforeAD, 26_726, SysTime(dtAD, hnsecs(27_000)));
6133 testST(beforeAD, 26_727, SysTime(dtAD, hnsecs(27_001)));
6134 testST(beforeAD, 1_766_725, SysTime(dtAD, hnsecs(1_766_999)));
6135 testST(beforeAD, 1_766_726, SysTime(dtAD, hnsecs(1_767_000)));
6136 testST(beforeAD, 1_000_000, SysTime(dtAD, hnsecs(1_000_274)));
6137 testST(beforeAD, 60_000_000L, SysTime(dtAD, hnsecs(274)));
6138 testST(beforeAD, 3_600_000_000L, SysTime(dtAD, hnsecs(274)));
6139 testST(beforeAD, 600_000_000L, SysTime(dtAD, hnsecs(274)));
6140 testST(beforeAD, 36_000_000_000L, SysTime(dtAD, hnsecs(274)));
6141
6142 testST(beforeAD, -1, SysTime(dtAD, hnsecs(273)));
6143 testST(beforeAD, -2, SysTime(dtAD, hnsecs(272)));
6144 testST(beforeAD, -10, SysTime(dtAD, hnsecs(264)));
6145 testST(beforeAD, -100, SysTime(dtAD, hnsecs(174)));
6146 testST(beforeAD, -274, SysTime(dtAD));
6147 testST(beforeAD, -275, SysTime(dtAD, hnsecs(9_999_999)));
6148 testST(beforeAD, -1000, SysTime(dtAD, hnsecs(9_999_274)));
6149 testST(beforeAD, -1001, SysTime(dtAD, hnsecs(9_999_273)));
6150 testST(beforeAD, -2000, SysTime(dtAD, hnsecs(9_998_274)));
6151 testST(beforeAD, -33_274, SysTime(dtAD, hnsecs(9_967_000)));
6152 testST(beforeAD, -33_275, SysTime(dtAD, hnsecs(9_966_999)));
6153 testST(beforeAD, -1_833_274, SysTime(dtAD, hnsecs(8_167_000)));
6154 testST(beforeAD, -1_833_275, SysTime(dtAD, hnsecs(8_166_999)));
6155 testST(beforeAD, -1_000_000, SysTime(dtAD, hnsecs(9_000_274)));
6156 testST(beforeAD, -60_000_000L, SysTime(dtAD, hnsecs(274)));
6157 testST(beforeAD, -3_600_000_000L, SysTime(dtAD, hnsecs(274)));
6158 testST(beforeAD, -600_000_000L, SysTime(dtAD, hnsecs(274)));
6159 testST(beforeAD, -36_000_000_000L, SysTime(dtAD, hnsecs(274)));
6160
6161 // Test B.C.
6162 auto dtBC = DateTime(-1999, 7, 6, 12, 30, 33);
6163 auto beforeBC = SysTime(dtBC, hnsecs(274));
6164 testST(beforeBC, 0, SysTime(dtBC, hnsecs(274)));
6165 testST(beforeBC, 1, SysTime(dtBC, hnsecs(275)));
6166 testST(beforeBC, 2, SysTime(dtBC, hnsecs(276)));
6167 testST(beforeBC, 10, SysTime(dtBC, hnsecs(284)));
6168 testST(beforeBC, 100, SysTime(dtBC, hnsecs(374)));
6169 testST(beforeBC, 725, SysTime(dtBC, hnsecs(999)));
6170 testST(beforeBC, 726, SysTime(dtBC, hnsecs(1000)));
6171 testST(beforeBC, 1000, SysTime(dtBC, hnsecs(1274)));
6172 testST(beforeBC, 1001, SysTime(dtBC, hnsecs(1275)));
6173 testST(beforeBC, 2000, SysTime(dtBC, hnsecs(2274)));
6174 testST(beforeBC, 26_725, SysTime(dtBC, hnsecs(26_999)));
6175 testST(beforeBC, 26_726, SysTime(dtBC, hnsecs(27_000)));
6176 testST(beforeBC, 26_727, SysTime(dtBC, hnsecs(27_001)));
6177 testST(beforeBC, 1_766_725, SysTime(dtBC, hnsecs(1_766_999)));
6178 testST(beforeBC, 1_766_726, SysTime(dtBC, hnsecs(1_767_000)));
6179 testST(beforeBC, 1_000_000, SysTime(dtBC, hnsecs(1_000_274)));
6180 testST(beforeBC, 60_000_000L, SysTime(dtBC, hnsecs(274)));
6181 testST(beforeBC, 3_600_000_000L, SysTime(dtBC, hnsecs(274)));
6182 testST(beforeBC, 600_000_000L, SysTime(dtBC, hnsecs(274)));
6183 testST(beforeBC, 36_000_000_000L, SysTime(dtBC, hnsecs(274)));
6184
6185 testST(beforeBC, -1, SysTime(dtBC, hnsecs(273)));
6186 testST(beforeBC, -2, SysTime(dtBC, hnsecs(272)));
6187 testST(beforeBC, -10, SysTime(dtBC, hnsecs(264)));
6188 testST(beforeBC, -100, SysTime(dtBC, hnsecs(174)));
6189 testST(beforeBC, -274, SysTime(dtBC));
6190 testST(beforeBC, -275, SysTime(dtBC, hnsecs(9_999_999)));
6191 testST(beforeBC, -1000, SysTime(dtBC, hnsecs(9_999_274)));
6192 testST(beforeBC, -1001, SysTime(dtBC, hnsecs(9_999_273)));
6193 testST(beforeBC, -2000, SysTime(dtBC, hnsecs(9_998_274)));
6194 testST(beforeBC, -33_274, SysTime(dtBC, hnsecs(9_967_000)));
6195 testST(beforeBC, -33_275, SysTime(dtBC, hnsecs(9_966_999)));
6196 testST(beforeBC, -1_833_274, SysTime(dtBC, hnsecs(8_167_000)));
6197 testST(beforeBC, -1_833_275, SysTime(dtBC, hnsecs(8_166_999)));
6198 testST(beforeBC, -1_000_000, SysTime(dtBC, hnsecs(9_000_274)));
6199 testST(beforeBC, -60_000_000L, SysTime(dtBC, hnsecs(274)));
6200 testST(beforeBC, -3_600_000_000L, SysTime(dtBC, hnsecs(274)));
6201 testST(beforeBC, -600_000_000L, SysTime(dtBC, hnsecs(274)));
6202 testST(beforeBC, -36_000_000_000L, SysTime(dtBC, hnsecs(274)));
6203
6204 // Test Both
6205 auto dtBoth1 = DateTime(1, 1, 1, 0, 0, 0);
6206 auto beforeBoth1 = SysTime(dtBoth1);
6207 testST(beforeBoth1, 1, SysTime(dtBoth1, hnsecs(1)));
6208 testST(beforeBoth1, 0, SysTime(dtBoth1));
6209 testST(beforeBoth1, -1, SysTime(dtBoth1, hnsecs(9_999_999)));
6210 testST(beforeBoth1, -2, SysTime(dtBoth1, hnsecs(9_999_998)));
6211 testST(beforeBoth1, -1000, SysTime(dtBoth1, hnsecs(9_999_000)));
6212 testST(beforeBoth1, -2000, SysTime(dtBoth1, hnsecs(9_998_000)));
6213 testST(beforeBoth1, -2555, SysTime(dtBoth1, hnsecs(9_997_445)));
6214 testST(beforeBoth1, -1_000_000, SysTime(dtBoth1, hnsecs(9_000_000)));
6215 testST(beforeBoth1, -2_000_000, SysTime(dtBoth1, hnsecs(8_000_000)));
6216 testST(beforeBoth1, -2_333_333, SysTime(dtBoth1, hnsecs(7_666_667)));
6217 testST(beforeBoth1, -10_000_000, SysTime(dtBoth1));
6218 testST(beforeBoth1, -20_000_000, SysTime(dtBoth1));
6219 testST(beforeBoth1, -20_888_888, SysTime(dtBoth1, hnsecs(9_111_112)));
6220
6221 auto dtBoth2 = DateTime(0, 12, 31, 23, 59, 59);
6222 auto beforeBoth2 = SysTime(dtBoth2, hnsecs(9_999_999));
6223 testST(beforeBoth2, -1, SysTime(dtBoth2, hnsecs(9_999_998)));
6224 testST(beforeBoth2, 0, SysTime(dtBoth2, hnsecs(9_999_999)));
6225 testST(beforeBoth2, 1, SysTime(dtBoth2));
6226 testST(beforeBoth2, 2, SysTime(dtBoth2, hnsecs(1)));
6227 testST(beforeBoth2, 1000, SysTime(dtBoth2, hnsecs(999)));
6228 testST(beforeBoth2, 2000, SysTime(dtBoth2, hnsecs(1999)));
6229 testST(beforeBoth2, 2555, SysTime(dtBoth2, hnsecs(2554)));
6230 testST(beforeBoth2, 1_000_000, SysTime(dtBoth2, hnsecs(999_999)));
6231 testST(beforeBoth2, 2_000_000, SysTime(dtBoth2, hnsecs(1_999_999)));
6232 testST(beforeBoth2, 2_333_333, SysTime(dtBoth2, hnsecs(2_333_332)));
6233 testST(beforeBoth2, 10_000_000, SysTime(dtBoth2, hnsecs(9_999_999)));
6234 testST(beforeBoth2, 20_000_000, SysTime(dtBoth2, hnsecs(9_999_999)));
6235 testST(beforeBoth2, 20_888_888, SysTime(dtBoth2, hnsecs(888_887)));
6236
6237 {
6238 auto st = SysTime(dtBoth2, hnsecs(9_999_999));
6239 st.roll!"hnsecs"(70_777_222).roll!"hnsecs"(-222_555_292);
6240 assert(st == SysTime(dtBoth2, hnsecs(8_221_929)));
6241 }
6242
6243 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6244 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6245 static assert(!__traits(compiles, cst.roll!"hnsecs"(4)));
6246 static assert(!__traits(compiles, ist.roll!"hnsecs"(4)));
6247
6248 static void testScope(scope ref SysTime st) @safe
6249 {
6250 auto result = st.roll!"hnsecs"(42);
6251 }
6252 }
6253
6254
6255 /++
6256 Gives the result of adding or subtracting a $(REF Duration, core,time)
6257 from this $(LREF SysTime).
6258
6259 The legal types of arithmetic for $(LREF SysTime) using this operator
6260 are
6261
6262 $(BOOKTABLE,
6263 $(TR $(TD SysTime) $(TD +) $(TD Duration) $(TD -->) $(TD SysTime))
6264 $(TR $(TD SysTime) $(TD -) $(TD Duration) $(TD -->) $(TD SysTime))
6265 )
6266
6267 Params:
6268 duration = The $(REF Duration, core,time) to add to or subtract from
6269 this $(LREF SysTime).
6270 +/
6271 SysTime opBinary(string op)(Duration duration) @safe const pure nothrow scope
6272 if (op == "+" || op == "-")
6273 {
6274 SysTime retval = SysTime(this._stdTime, this._timezone);
6275 immutable hnsecs = duration.total!"hnsecs";
6276 mixin("retval._stdTime " ~ op ~ "= hnsecs;");
6277 return retval;
6278 }
6279
6280 ///
6281 @safe unittest
6282 {
6283 import core.time : hours, seconds;
6284 import std.datetime.date : DateTime;
6285
6286 assert(SysTime(DateTime(2015, 12, 31, 23, 59, 59)) + seconds(1) ==
6287 SysTime(DateTime(2016, 1, 1, 0, 0, 0)));
6288
6289 assert(SysTime(DateTime(2015, 12, 31, 23, 59, 59)) + hours(1) ==
6290 SysTime(DateTime(2016, 1, 1, 0, 59, 59)));
6291
6292 assert(SysTime(DateTime(2016, 1, 1, 0, 0, 0)) - seconds(1) ==
6293 SysTime(DateTime(2015, 12, 31, 23, 59, 59)));
6294
6295 assert(SysTime(DateTime(2016, 1, 1, 0, 59, 59)) - hours(1) ==
6296 SysTime(DateTime(2015, 12, 31, 23, 59, 59)));
6297 }
6298
6299 @safe unittest
6300 {
6301 import core.time;
6302 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_678));
6303
6304 assert(st + dur!"weeks"(7) == SysTime(DateTime(1999, 8, 24, 12, 30, 33), hnsecs(2_345_678)));
6305 assert(st + dur!"weeks"(-7) == SysTime(DateTime(1999, 5, 18, 12, 30, 33), hnsecs(2_345_678)));
6306 assert(st + dur!"days"(7) == SysTime(DateTime(1999, 7, 13, 12, 30, 33), hnsecs(2_345_678)));
6307 assert(st + dur!"days"(-7) == SysTime(DateTime(1999, 6, 29, 12, 30, 33), hnsecs(2_345_678)));
6308 assert(st + dur!"hours"(7) == SysTime(DateTime(1999, 7, 6, 19, 30, 33), hnsecs(2_345_678)));
6309 assert(st + dur!"hours"(-7) == SysTime(DateTime(1999, 7, 6, 5, 30, 33), hnsecs(2_345_678)));
6310 assert(st + dur!"minutes"(7) == SysTime(DateTime(1999, 7, 6, 12, 37, 33), hnsecs(2_345_678)));
6311 assert(st + dur!"minutes"(-7) == SysTime(DateTime(1999, 7, 6, 12, 23, 33), hnsecs(2_345_678)));
6312 assert(st + dur!"seconds"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 40), hnsecs(2_345_678)));
6313 assert(st + dur!"seconds"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 26), hnsecs(2_345_678)));
6314 assert(st + dur!"msecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_415_678)));
6315 assert(st + dur!"msecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_275_678)));
6316 assert(st + dur!"usecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_748)));
6317 assert(st + dur!"usecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_608)));
6318 assert(st + dur!"hnsecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_685)));
6319 assert(st + dur!"hnsecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_671)));
6320
6321 assert(st - dur!"weeks"(-7) == SysTime(DateTime(1999, 8, 24, 12, 30, 33), hnsecs(2_345_678)));
6322 assert(st - dur!"weeks"(7) == SysTime(DateTime(1999, 5, 18, 12, 30, 33), hnsecs(2_345_678)));
6323 assert(st - dur!"days"(-7) == SysTime(DateTime(1999, 7, 13, 12, 30, 33), hnsecs(2_345_678)));
6324 assert(st - dur!"days"(7) == SysTime(DateTime(1999, 6, 29, 12, 30, 33), hnsecs(2_345_678)));
6325 assert(st - dur!"hours"(-7) == SysTime(DateTime(1999, 7, 6, 19, 30, 33), hnsecs(2_345_678)));
6326 assert(st - dur!"hours"(7) == SysTime(DateTime(1999, 7, 6, 5, 30, 33), hnsecs(2_345_678)));
6327 assert(st - dur!"minutes"(-7) == SysTime(DateTime(1999, 7, 6, 12, 37, 33), hnsecs(2_345_678)));
6328 assert(st - dur!"minutes"(7) == SysTime(DateTime(1999, 7, 6, 12, 23, 33), hnsecs(2_345_678)));
6329 assert(st - dur!"seconds"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 40), hnsecs(2_345_678)));
6330 assert(st - dur!"seconds"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 26), hnsecs(2_345_678)));
6331 assert(st - dur!"msecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_415_678)));
6332 assert(st - dur!"msecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_275_678)));
6333 assert(st - dur!"usecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_748)));
6334 assert(st - dur!"usecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_608)));
6335 assert(st - dur!"hnsecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_685)));
6336 assert(st - dur!"hnsecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_671)));
6337
6338 static void testST(SysTime orig, long hnsecs, SysTime expected, size_t line = __LINE__) @safe
6339 {
6340 auto result = orig + dur!"hnsecs"(hnsecs);
6341 if (result != expected)
6342 throw new AssertError(format("Failed. actual [%s] != expected [%s]", result, expected), __FILE__, line);
6343 }
6344
6345 // Test A.D.
6346 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(274));
6347 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(274)));
6348 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(275)));
6349 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(276)));
6350 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(284)));
6351 testST(beforeAD, 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(374)));
6352 testST(beforeAD, 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(999)));
6353 testST(beforeAD, 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1000)));
6354 testST(beforeAD, 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1274)));
6355 testST(beforeAD, 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1275)));
6356 testST(beforeAD, 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2274)));
6357 testST(beforeAD, 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(26_999)));
6358 testST(beforeAD, 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(27_000)));
6359 testST(beforeAD, 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(27_001)));
6360 testST(beforeAD, 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_766_999)));
6361 testST(beforeAD, 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_767_000)));
6362 testST(beforeAD, 1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_000_274)));
6363 testST(beforeAD, 60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 39), hnsecs(274)));
6364 testST(beforeAD, 3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 36, 33), hnsecs(274)));
6365 testST(beforeAD, 600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 31, 33), hnsecs(274)));
6366 testST(beforeAD, 36_000_000_000L, SysTime(DateTime(1999, 7, 6, 13, 30, 33), hnsecs(274)));
6367
6368 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(273)));
6369 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(272)));
6370 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(264)));
6371 testST(beforeAD, -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(174)));
6372 testST(beforeAD, -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
6373 testST(beforeAD, -275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_999)));
6374 testST(beforeAD, -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_274)));
6375 testST(beforeAD, -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_273)));
6376 testST(beforeAD, -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_998_274)));
6377 testST(beforeAD, -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_967_000)));
6378 testST(beforeAD, -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_966_999)));
6379 testST(beforeAD, -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(8_167_000)));
6380 testST(beforeAD, -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(8_166_999)));
6381 testST(beforeAD, -1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_000_274)));
6382 testST(beforeAD, -60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 27), hnsecs(274)));
6383 testST(beforeAD, -3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 24, 33), hnsecs(274)));
6384 testST(beforeAD, -600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 29, 33), hnsecs(274)));
6385 testST(beforeAD, -36_000_000_000L, SysTime(DateTime(1999, 7, 6, 11, 30, 33), hnsecs(274)));
6386
6387 // Test B.C.
6388 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(274));
6389 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(274)));
6390 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(275)));
6391 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(276)));
6392 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(284)));
6393 testST(beforeBC, 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(374)));
6394 testST(beforeBC, 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(999)));
6395 testST(beforeBC, 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1000)));
6396 testST(beforeBC, 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1274)));
6397 testST(beforeBC, 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1275)));
6398 testST(beforeBC, 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(2274)));
6399 testST(beforeBC, 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(26_999)));
6400 testST(beforeBC, 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(27_000)));
6401 testST(beforeBC, 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(27_001)));
6402 testST(beforeBC, 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_766_999)));
6403 testST(beforeBC, 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_767_000)));
6404 testST(beforeBC, 1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_000_274)));
6405 testST(beforeBC, 60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 39), hnsecs(274)));
6406 testST(beforeBC, 3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 36, 33), hnsecs(274)));
6407 testST(beforeBC, 600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), hnsecs(274)));
6408 testST(beforeBC, 36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), hnsecs(274)));
6409
6410 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(273)));
6411 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(272)));
6412 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(264)));
6413 testST(beforeBC, -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(174)));
6414 testST(beforeBC, -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
6415 testST(beforeBC, -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_999)));
6416 testST(beforeBC, -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_274)));
6417 testST(beforeBC, -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_273)));
6418 testST(beforeBC, -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_998_274)));
6419 testST(beforeBC, -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_967_000)));
6420 testST(beforeBC, -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_966_999)));
6421 testST(beforeBC, -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(8_167_000)));
6422 testST(beforeBC, -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(8_166_999)));
6423 testST(beforeBC, -1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_000_274)));
6424 testST(beforeBC, -60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 27), hnsecs(274)));
6425 testST(beforeBC, -3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 24, 33), hnsecs(274)));
6426 testST(beforeBC, -600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), hnsecs(274)));
6427 testST(beforeBC, -36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), hnsecs(274)));
6428
6429 // Test Both
6430 auto beforeBoth1 = SysTime(DateTime(1, 1, 1, 0, 0, 0));
6431 testST(beforeBoth1, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)));
6432 testST(beforeBoth1, 0, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6433 testST(beforeBoth1, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6434 testST(beforeBoth1, -2, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_998)));
6435 testST(beforeBoth1, -1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_000)));
6436 testST(beforeBoth1, -2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_998_000)));
6437 testST(beforeBoth1, -2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_997_445)));
6438 testST(beforeBoth1, -1_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_000_000)));
6439 testST(beforeBoth1, -2_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(8_000_000)));
6440 testST(beforeBoth1, -2_333_333, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(7_666_667)));
6441 testST(beforeBoth1, -10_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59)));
6442 testST(beforeBoth1, -20_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 58)));
6443 testST(beforeBoth1, -20_888_888, SysTime(DateTime(0, 12, 31, 23, 59, 57), hnsecs(9_111_112)));
6444
6445 auto beforeBoth2 = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
6446 testST(beforeBoth2, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_998)));
6447 testST(beforeBoth2, 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6448 testST(beforeBoth2, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6449 testST(beforeBoth2, 2, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)));
6450 testST(beforeBoth2, 1000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(999)));
6451 testST(beforeBoth2, 2000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1999)));
6452 testST(beforeBoth2, 2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(2554)));
6453 testST(beforeBoth2, 1_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(999_999)));
6454 testST(beforeBoth2, 2_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1_999_999)));
6455 testST(beforeBoth2, 2_333_333, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(2_333_332)));
6456 testST(beforeBoth2, 10_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
6457 testST(beforeBoth2, 20_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 1), hnsecs(9_999_999)));
6458 testST(beforeBoth2, 20_888_888, SysTime(DateTime(1, 1, 1, 0, 0, 2), hnsecs(888_887)));
6459
6460 auto duration = dur!"seconds"(12);
6461 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6462 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6463 assert(cst + duration == SysTime(DateTime(1999, 7, 6, 12, 30, 45)));
6464 assert(ist + duration == SysTime(DateTime(1999, 7, 6, 12, 30, 45)));
6465 assert(cst - duration == SysTime(DateTime(1999, 7, 6, 12, 30, 21)));
6466 assert(ist - duration == SysTime(DateTime(1999, 7, 6, 12, 30, 21)));
6467
6468 static void testScope(scope ref SysTime st, scope ref Duration d) @safe
6469 {
6470 auto result = st + d;
6471 }
6472 }
6473
6474
6475 /++
6476 Gives the result of adding or subtracting a $(REF Duration, core,time) from
6477 this $(LREF SysTime), as well as assigning the result to this
6478 $(LREF SysTime).
6479
6480 The legal types of arithmetic for $(LREF SysTime) using this operator are
6481
6482 $(BOOKTABLE,
6483 $(TR $(TD SysTime) $(TD +) $(TD Duration) $(TD -->) $(TD SysTime))
6484 $(TR $(TD SysTime) $(TD -) $(TD Duration) $(TD -->) $(TD SysTime))
6485 )
6486
6487 Params:
6488 duration = The $(REF Duration, core,time) to add to or subtract from
6489 this $(LREF SysTime).
6490 +/
6491 ref SysTime opOpAssign(string op)(Duration duration) @safe pure nothrow scope
6492 if (op == "+" || op == "-")
6493 {
6494 immutable hnsecs = duration.total!"hnsecs";
6495 mixin("_stdTime " ~ op ~ "= hnsecs;");
6496 return this;
6497 }
6498
6499 @safe unittest
6500 {
6501 import core.time;
6502 auto before = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6503 assert(before + dur!"weeks"(7) == SysTime(DateTime(1999, 8, 24, 12, 30, 33)));
6504 assert(before + dur!"weeks"(-7) == SysTime(DateTime(1999, 5, 18, 12, 30, 33)));
6505 assert(before + dur!"days"(7) == SysTime(DateTime(1999, 7, 13, 12, 30, 33)));
6506 assert(before + dur!"days"(-7) == SysTime(DateTime(1999, 6, 29, 12, 30, 33)));
6507
6508 assert(before + dur!"hours"(7) == SysTime(DateTime(1999, 7, 6, 19, 30, 33)));
6509 assert(before + dur!"hours"(-7) == SysTime(DateTime(1999, 7, 6, 5, 30, 33)));
6510 assert(before + dur!"minutes"(7) == SysTime(DateTime(1999, 7, 6, 12, 37, 33)));
6511 assert(before + dur!"minutes"(-7) == SysTime(DateTime(1999, 7, 6, 12, 23, 33)));
6512 assert(before + dur!"seconds"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 40)));
6513 assert(before + dur!"seconds"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 26)));
6514 assert(before + dur!"msecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(7)));
6515 assert(before + dur!"msecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), msecs(993)));
6516 assert(before + dur!"usecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(7)));
6517 assert(before + dur!"usecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), usecs(999_993)));
6518 assert(before + dur!"hnsecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(7)));
6519 assert(before + dur!"hnsecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_993)));
6520
6521 assert(before - dur!"weeks"(-7) == SysTime(DateTime(1999, 8, 24, 12, 30, 33)));
6522 assert(before - dur!"weeks"(7) == SysTime(DateTime(1999, 5, 18, 12, 30, 33)));
6523 assert(before - dur!"days"(-7) == SysTime(DateTime(1999, 7, 13, 12, 30, 33)));
6524 assert(before - dur!"days"(7) == SysTime(DateTime(1999, 6, 29, 12, 30, 33)));
6525
6526 assert(before - dur!"hours"(-7) == SysTime(DateTime(1999, 7, 6, 19, 30, 33)));
6527 assert(before - dur!"hours"(7) == SysTime(DateTime(1999, 7, 6, 5, 30, 33)));
6528 assert(before - dur!"minutes"(-7) == SysTime(DateTime(1999, 7, 6, 12, 37, 33)));
6529 assert(before - dur!"minutes"(7) == SysTime(DateTime(1999, 7, 6, 12, 23, 33)));
6530 assert(before - dur!"seconds"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 40)));
6531 assert(before - dur!"seconds"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 26)));
6532 assert(before - dur!"msecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(7)));
6533 assert(before - dur!"msecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), msecs(993)));
6534 assert(before - dur!"usecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(7)));
6535 assert(before - dur!"usecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), usecs(999_993)));
6536 assert(before - dur!"hnsecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(7)));
6537 assert(before - dur!"hnsecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_993)));
6538
6539 static void testST(SysTime orig, long hnsecs, SysTime expected, size_t line = __LINE__) @safe
6540 {
6541 auto r = orig += dur!"hnsecs"(hnsecs);
6542 if (orig != expected)
6543 throw new AssertError(format("Failed 1. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
6544 if (r != expected)
6545 throw new AssertError(format("Failed 2. actual [%s] != expected [%s]", r, expected), __FILE__, line);
6546 }
6547
6548 // Test A.D.
6549 auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(274));
6550 testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(274)));
6551 testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(275)));
6552 testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(276)));
6553 testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(284)));
6554 testST(beforeAD, 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(374)));
6555 testST(beforeAD, 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(999)));
6556 testST(beforeAD, 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1000)));
6557 testST(beforeAD, 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1274)));
6558 testST(beforeAD, 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1275)));
6559 testST(beforeAD, 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2274)));
6560 testST(beforeAD, 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(26_999)));
6561 testST(beforeAD, 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(27_000)));
6562 testST(beforeAD, 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(27_001)));
6563 testST(beforeAD, 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_766_999)));
6564 testST(beforeAD, 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_767_000)));
6565 testST(beforeAD, 1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_000_274)));
6566 testST(beforeAD, 60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 39), hnsecs(274)));
6567 testST(beforeAD, 3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 36, 33), hnsecs(274)));
6568 testST(beforeAD, 600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 31, 33), hnsecs(274)));
6569 testST(beforeAD, 36_000_000_000L, SysTime(DateTime(1999, 7, 6, 13, 30, 33), hnsecs(274)));
6570
6571 testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(273)));
6572 testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(272)));
6573 testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(264)));
6574 testST(beforeAD, -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(174)));
6575 testST(beforeAD, -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
6576 testST(beforeAD, -275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_999)));
6577 testST(beforeAD, -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_274)));
6578 testST(beforeAD, -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_273)));
6579 testST(beforeAD, -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_998_274)));
6580 testST(beforeAD, -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_967_000)));
6581 testST(beforeAD, -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_966_999)));
6582 testST(beforeAD, -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(8_167_000)));
6583 testST(beforeAD, -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(8_166_999)));
6584 testST(beforeAD, -1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_000_274)));
6585 testST(beforeAD, -60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 27), hnsecs(274)));
6586 testST(beforeAD, -3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 24, 33), hnsecs(274)));
6587 testST(beforeAD, -600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 29, 33), hnsecs(274)));
6588 testST(beforeAD, -36_000_000_000L, SysTime(DateTime(1999, 7, 6, 11, 30, 33), hnsecs(274)));
6589
6590 // Test B.C.
6591 auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(274));
6592 testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(274)));
6593 testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(275)));
6594 testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(276)));
6595 testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(284)));
6596 testST(beforeBC, 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(374)));
6597 testST(beforeBC, 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(999)));
6598 testST(beforeBC, 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1000)));
6599 testST(beforeBC, 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1274)));
6600 testST(beforeBC, 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1275)));
6601 testST(beforeBC, 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(2274)));
6602 testST(beforeBC, 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(26_999)));
6603 testST(beforeBC, 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(27_000)));
6604 testST(beforeBC, 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(27_001)));
6605 testST(beforeBC, 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_766_999)));
6606 testST(beforeBC, 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_767_000)));
6607 testST(beforeBC, 1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_000_274)));
6608 testST(beforeBC, 60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 39), hnsecs(274)));
6609 testST(beforeBC, 3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 36, 33), hnsecs(274)));
6610 testST(beforeBC, 600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), hnsecs(274)));
6611 testST(beforeBC, 36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), hnsecs(274)));
6612
6613 testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(273)));
6614 testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(272)));
6615 testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(264)));
6616 testST(beforeBC, -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(174)));
6617 testST(beforeBC, -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
6618 testST(beforeBC, -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_999)));
6619 testST(beforeBC, -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_274)));
6620 testST(beforeBC, -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_273)));
6621 testST(beforeBC, -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_998_274)));
6622 testST(beforeBC, -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_967_000)));
6623 testST(beforeBC, -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_966_999)));
6624 testST(beforeBC, -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(8_167_000)));
6625 testST(beforeBC, -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(8_166_999)));
6626 testST(beforeBC, -1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_000_274)));
6627 testST(beforeBC, -60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 27), hnsecs(274)));
6628 testST(beforeBC, -3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 24, 33), hnsecs(274)));
6629 testST(beforeBC, -600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), hnsecs(274)));
6630 testST(beforeBC, -36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), hnsecs(274)));
6631
6632 // Test Both
6633 auto beforeBoth1 = SysTime(DateTime(1, 1, 1, 0, 0, 0));
6634 testST(beforeBoth1, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)));
6635 testST(beforeBoth1, 0, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6636 testST(beforeBoth1, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6637 testST(beforeBoth1, -2, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_998)));
6638 testST(beforeBoth1, -1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_000)));
6639 testST(beforeBoth1, -2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_998_000)));
6640 testST(beforeBoth1, -2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_997_445)));
6641 testST(beforeBoth1, -1_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_000_000)));
6642 testST(beforeBoth1, -2_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(8_000_000)));
6643 testST(beforeBoth1, -2_333_333, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(7_666_667)));
6644 testST(beforeBoth1, -10_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59)));
6645 testST(beforeBoth1, -20_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 58)));
6646 testST(beforeBoth1, -20_888_888, SysTime(DateTime(0, 12, 31, 23, 59, 57), hnsecs(9_111_112)));
6647
6648 auto beforeBoth2 = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
6649 testST(beforeBoth2, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_998)));
6650 testST(beforeBoth2, 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
6651 testST(beforeBoth2, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
6652 testST(beforeBoth2, 2, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)));
6653 testST(beforeBoth2, 1000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(999)));
6654 testST(beforeBoth2, 2000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1999)));
6655 testST(beforeBoth2, 2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(2554)));
6656 testST(beforeBoth2, 1_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(999_999)));
6657 testST(beforeBoth2, 2_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1_999_999)));
6658 testST(beforeBoth2, 2_333_333, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(2_333_332)));
6659 testST(beforeBoth2, 10_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
6660 testST(beforeBoth2, 20_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 1), hnsecs(9_999_999)));
6661 testST(beforeBoth2, 20_888_888, SysTime(DateTime(1, 1, 1, 0, 0, 2), hnsecs(888_887)));
6662
6663 {
6664 auto st = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999));
6665 (st += dur!"hnsecs"(52)) += dur!"seconds"(-907);
6666 assert(st == SysTime(DateTime(0, 12, 31, 23, 44, 53), hnsecs(51)));
6667 }
6668
6669 auto duration = dur!"seconds"(12);
6670 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6671 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6672 static assert(!__traits(compiles, cst += duration));
6673 static assert(!__traits(compiles, ist += duration));
6674 static assert(!__traits(compiles, cst -= duration));
6675 static assert(!__traits(compiles, ist -= duration));
6676
6677 static void testScope(scope ref SysTime st, scope ref Duration d) @safe
6678 {
6679 auto result1 = st += d;
6680 auto result2 = st -= d;
6681 }
6682 }
6683
6684
6685 /++
6686 Gives the difference between two $(LREF SysTime)s.
6687
6688 The legal types of arithmetic for $(LREF SysTime) using this operator
6689 are
6690
6691 $(BOOKTABLE,
6692 $(TR $(TD SysTime) $(TD -) $(TD SysTime) $(TD -->) $(TD duration))
6693 )
6694 +/
6695 Duration opBinary(string op)(SysTime rhs) @safe const pure nothrow scope
6696 if (op == "-")
6697 {
6698 return dur!"hnsecs"(_stdTime - rhs._stdTime);
6699 }
6700
6701 @safe unittest
6702 {
6703 import core.time;
6704 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1998, 7, 6, 12, 30, 33)) ==
6705 dur!"seconds"(31_536_000));
6706 assert(SysTime(DateTime(1998, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) ==
6707 dur!"seconds"(-31_536_000));
6708
6709 assert(SysTime(DateTime(1999, 8, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) ==
6710 dur!"seconds"(26_78_400));
6711 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 8, 6, 12, 30, 33)) ==
6712 dur!"seconds"(-26_78_400));
6713
6714 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 5, 12, 30, 33)) ==
6715 dur!"seconds"(86_400));
6716 assert(SysTime(DateTime(1999, 7, 5, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) ==
6717 dur!"seconds"(-86_400));
6718
6719 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 11, 30, 33)) ==
6720 dur!"seconds"(3600));
6721 assert(SysTime(DateTime(1999, 7, 6, 11, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) ==
6722 dur!"seconds"(-3600));
6723
6724 assert(SysTime(DateTime(1999, 7, 6, 12, 31, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) ==
6725 dur!"seconds"(60));
6726 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 31, 33)) ==
6727 dur!"seconds"(-60));
6728
6729 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 34)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) ==
6730 dur!"seconds"(1));
6731 assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 34)) ==
6732 dur!"seconds"(-1));
6733
6734 {
6735 auto dt = DateTime(1999, 7, 6, 12, 30, 33);
6736 assert(SysTime(dt, msecs(532)) - SysTime(dt) == msecs(532));
6737 assert(SysTime(dt) - SysTime(dt, msecs(532)) == msecs(-532));
6738
6739 assert(SysTime(dt, usecs(333_347)) - SysTime(dt) == usecs(333_347));
6740 assert(SysTime(dt) - SysTime(dt, usecs(333_347)) == usecs(-333_347));
6741
6742 assert(SysTime(dt, hnsecs(1_234_567)) - SysTime(dt) == hnsecs(1_234_567));
6743 assert(SysTime(dt) - SysTime(dt, hnsecs(1_234_567)) == hnsecs(-1_234_567));
6744 }
6745
6746 assert(SysTime(DateTime(1, 1, 1, 12, 30, 33)) - SysTime(DateTime(1, 1, 1, 0, 0, 0)) == dur!"seconds"(45033));
6747 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)) - SysTime(DateTime(1, 1, 1, 12, 30, 33)) == dur!"seconds"(-45033));
6748 assert(SysTime(DateTime(0, 12, 31, 12, 30, 33)) - SysTime(DateTime(1, 1, 1, 0, 0, 0)) == dur!"seconds"(-41367));
6749 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)) - SysTime(DateTime(0, 12, 31, 12, 30, 33)) == dur!"seconds"(41367));
6750
6751 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)) - SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)) ==
6752 dur!"hnsecs"(1));
6753 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)) - SysTime(DateTime(1, 1, 1, 0, 0, 0)) ==
6754 dur!"hnsecs"(-1));
6755
6756 version (Posix)
6757 {
6758 import std.datetime.timezone : PosixTimeZone;
6759 immutable tz = PosixTimeZone.getTimeZone("America/Los_Angeles");
6760 }
6761 else version (Windows)
6762 {
6763 import std.datetime.timezone : WindowsTimeZone;
6764 immutable tz = WindowsTimeZone.getTimeZone("Pacific Standard Time");
6765 }
6766
6767 {
6768 auto dt = DateTime(2011, 1, 13, 8, 17, 2);
6769 auto d = msecs(296);
6770 assert(SysTime(dt, d, tz) - SysTime(dt, d, tz) == Duration.zero);
6771 assert(SysTime(dt, d, tz) - SysTime(dt, d, UTC()) == hours(8));
6772 assert(SysTime(dt, d, UTC()) - SysTime(dt, d, tz) == hours(-8));
6773 }
6774
6775 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6776 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6777 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6778 assert(st - st == Duration.zero);
6779 assert(cst - st == Duration.zero);
6780 assert(ist - st == Duration.zero);
6781
6782 assert(st - cst == Duration.zero);
6783 assert(cst - cst == Duration.zero);
6784 assert(ist - cst == Duration.zero);
6785
6786 assert(st - ist == Duration.zero);
6787 assert(cst - ist == Duration.zero);
6788 assert(ist - ist == Duration.zero);
6789
6790 static void testScope(scope ref SysTime left, scope ref SysTime right) @safe
6791 {
6792 auto result = left - right;
6793 }
6794 }
6795
6796
6797 /++
6798 Returns the difference between the two $(LREF SysTime)s in months.
6799
6800 To get the difference in years, subtract the year property
6801 of two $(LREF SysTime)s. To get the difference in days or weeks,
6802 subtract the $(LREF SysTime)s themselves and use the
6803 $(REF Duration, core,time) that results. Because converting between
6804 months and smaller units requires a specific date (which
6805 $(REF Duration, core,time)s don't have), getting the difference in
6806 months requires some math using both the year and month properties, so
6807 this is a convenience function for getting the difference in months.
6808
6809 Note that the number of days in the months or how far into the month
6810 either date is is irrelevant. It is the difference in the month property
6811 combined with the difference in years * 12. So, for instance,
6812 December 31st and January 1st are one month apart just as December 1st
6813 and January 31st are one month apart.
6814
6815 Params:
6816 rhs = The $(LREF SysTime) to subtract from this one.
6817 +/
6818 int diffMonths(scope SysTime rhs) @safe const nothrow scope
6819 {
6820 return (cast(Date) this).diffMonths(cast(Date) rhs);
6821 }
6822
6823 ///
6824 @safe unittest
6825 {
6826 import core.time;
6827 import std.datetime.date : Date;
6828
6829 assert(SysTime(Date(1999, 2, 1)).diffMonths(
6830 SysTime(Date(1999, 1, 31))) == 1);
6831
6832 assert(SysTime(Date(1999, 1, 31)).diffMonths(
6833 SysTime(Date(1999, 2, 1))) == -1);
6834
6835 assert(SysTime(Date(1999, 3, 1)).diffMonths(
6836 SysTime(Date(1999, 1, 1))) == 2);
6837
6838 assert(SysTime(Date(1999, 1, 1)).diffMonths(
6839 SysTime(Date(1999, 3, 31))) == -2);
6840 }
6841
6842 @safe unittest
6843 {
6844 import core.time;
6845 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6846 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6847 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6848 assert(st.diffMonths(st) == 0);
6849 assert(cst.diffMonths(st) == 0);
6850 assert(ist.diffMonths(st) == 0);
6851
6852 assert(st.diffMonths(cst) == 0);
6853 assert(cst.diffMonths(cst) == 0);
6854 assert(ist.diffMonths(cst) == 0);
6855
6856 assert(st.diffMonths(ist) == 0);
6857 assert(cst.diffMonths(ist) == 0);
6858 assert(ist.diffMonths(ist) == 0);
6859
6860 static void testScope(scope ref SysTime left, scope ref SysTime right) @safe
6861 {
6862 auto result = left.diffMonths(right);
6863 }
6864 }
6865
6866
6867 /++
6868 Whether this $(LREF SysTime) is in a leap year.
6869 +/
6870 @property bool isLeapYear() @safe const nothrow scope
6871 {
6872 return (cast(Date) this).isLeapYear;
6873 }
6874
6875 @safe unittest
6876 {
6877 import core.time;
6878 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6879 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6880 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6881 assert(!st.isLeapYear);
6882 assert(!cst.isLeapYear);
6883 assert(!ist.isLeapYear);
6884
6885 static void testScope(scope ref SysTime st) @safe
6886 {
6887 auto result = st.isLeapYear;
6888 }
6889 }
6890
6891
6892 /++
6893 Day of the week this $(LREF SysTime) is on.
6894 +/
6895 @property DayOfWeek dayOfWeek() @safe const nothrow scope
6896 {
6897 return getDayOfWeek(dayOfGregorianCal);
6898 }
6899
6900 @safe unittest
6901 {
6902 import core.time;
6903 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6904 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6905 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6906 assert(st.dayOfWeek == DayOfWeek.tue);
6907 assert(cst.dayOfWeek == DayOfWeek.tue);
6908 assert(ist.dayOfWeek == DayOfWeek.tue);
6909
6910 static void testScope(scope ref SysTime st) @safe
6911 {
6912 auto result = st.dayOfWeek;
6913 }
6914 }
6915
6916
6917 /++
6918 Day of the year this $(LREF SysTime) is on.
6919 +/
6920 @property ushort dayOfYear() @safe const nothrow scope
6921 {
6922 return (cast(Date) this).dayOfYear;
6923 }
6924
6925 ///
6926 @safe unittest
6927 {
6928 import core.time;
6929 import std.datetime.date : DateTime;
6930
6931 assert(SysTime(DateTime(1999, 1, 1, 12, 22, 7)).dayOfYear == 1);
6932 assert(SysTime(DateTime(1999, 12, 31, 7, 2, 59)).dayOfYear == 365);
6933 assert(SysTime(DateTime(2000, 12, 31, 21, 20, 0)).dayOfYear == 366);
6934 }
6935
6936 @safe unittest
6937 {
6938 import core.time;
6939 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6940 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6941 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6942 assert(st.dayOfYear == 187);
6943 assert(cst.dayOfYear == 187);
6944 assert(ist.dayOfYear == 187);
6945
6946 static void testScope(scope ref SysTime st) @safe
6947 {
6948 auto result = st.dayOfYear;
6949 }
6950 }
6951
6952
6953 /++
6954 Day of the year.
6955
6956 Params:
6957 day = The day of the year to set which day of the year this
6958 $(LREF SysTime) is on.
6959 +/
6960 @property void dayOfYear(int day) @safe scope
6961 {
6962 immutable hnsecs = adjTime;
6963 immutable days = convert!("hnsecs", "days")(hnsecs);
6964 immutable theRest = hnsecs - convert!("days", "hnsecs")(days);
6965
6966 auto date = Date(cast(int) days);
6967 date.dayOfYear = day;
6968
6969 immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
6970
6971 adjTime = newDaysHNSecs + theRest;
6972 }
6973
6974 @safe unittest
6975 {
6976 import core.time;
6977 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6978 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6979 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
6980 st.dayOfYear = 12;
6981 assert(st.dayOfYear == 12);
6982 static assert(!__traits(compiles, cst.dayOfYear = 12));
6983 static assert(!__traits(compiles, ist.dayOfYear = 12));
6984
6985 static void testScope(scope ref SysTime st) @safe
6986 {
6987 st.dayOfYear = 42;
6988 }
6989 }
6990
6991
6992 /++
6993 The Xth day of the Gregorian Calendar that this $(LREF SysTime) is on.
6994 +/
6995 @property int dayOfGregorianCal() @safe const nothrow scope
6996 {
6997 immutable adjustedTime = adjTime;
6998
6999 // We have to add one because 0 would be midnight, January 1st, 1 A.D.,
7000 // which would be the 1st day of the Gregorian Calendar, not the 0th. So,
7001 // simply casting to days is one day off.
7002 if (adjustedTime > 0)
7003 return cast(int) getUnitsFromHNSecs!"days"(adjustedTime) + 1;
7004
7005 long hnsecs = adjustedTime;
7006 immutable days = cast(int) splitUnitsFromHNSecs!"days"(hnsecs);
7007
7008 return hnsecs == 0 ? days + 1 : days;
7009 }
7010
7011 ///
7012 @safe unittest
7013 {
7014 import core.time;
7015 import std.datetime.date : DateTime;
7016
7017 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).dayOfGregorianCal == 1);
7018 assert(SysTime(DateTime(1, 12, 31, 23, 59, 59)).dayOfGregorianCal == 365);
7019 assert(SysTime(DateTime(2, 1, 1, 2, 2, 2)).dayOfGregorianCal == 366);
7020
7021 assert(SysTime(DateTime(0, 12, 31, 7, 7, 7)).dayOfGregorianCal == 0);
7022 assert(SysTime(DateTime(0, 1, 1, 19, 30, 0)).dayOfGregorianCal == -365);
7023 assert(SysTime(DateTime(-1, 12, 31, 4, 7, 0)).dayOfGregorianCal == -366);
7024
7025 assert(SysTime(DateTime(2000, 1, 1, 9, 30, 20)).dayOfGregorianCal == 730_120);
7026 assert(SysTime(DateTime(2010, 12, 31, 15, 45, 50)).dayOfGregorianCal == 734_137);
7027 }
7028
7029 @safe unittest
7030 {
7031 import core.time;
7032 // Test A.D.
7033 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).dayOfGregorianCal == 1);
7034 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)).dayOfGregorianCal == 1);
7035 assert(SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)).dayOfGregorianCal == 1);
7036
7037 assert(SysTime(DateTime(1, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 1);
7038 assert(SysTime(DateTime(1, 1, 2, 12, 2, 9), msecs(212)).dayOfGregorianCal == 2);
7039 assert(SysTime(DateTime(1, 2, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 32);
7040 assert(SysTime(DateTime(2, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 366);
7041 assert(SysTime(DateTime(3, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 731);
7042 assert(SysTime(DateTime(4, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 1096);
7043 assert(SysTime(DateTime(5, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 1462);
7044 assert(SysTime(DateTime(50, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 17_898);
7045 assert(SysTime(DateTime(97, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 35_065);
7046 assert(SysTime(DateTime(100, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 36_160);
7047 assert(SysTime(DateTime(101, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 36_525);
7048 assert(SysTime(DateTime(105, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 37_986);
7049 assert(SysTime(DateTime(200, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 72_684);
7050 assert(SysTime(DateTime(201, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 73_049);
7051 assert(SysTime(DateTime(300, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 109_208);
7052 assert(SysTime(DateTime(301, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 109_573);
7053 assert(SysTime(DateTime(400, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 145_732);
7054 assert(SysTime(DateTime(401, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 146_098);
7055 assert(SysTime(DateTime(500, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 182_257);
7056 assert(SysTime(DateTime(501, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 182_622);
7057 assert(SysTime(DateTime(1000, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 364_878);
7058 assert(SysTime(DateTime(1001, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 365_243);
7059 assert(SysTime(DateTime(1600, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 584_023);
7060 assert(SysTime(DateTime(1601, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 584_389);
7061 assert(SysTime(DateTime(1900, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 693_596);
7062 assert(SysTime(DateTime(1901, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 693_961);
7063 assert(SysTime(DateTime(1945, 11, 12, 12, 2, 9), msecs(212)).dayOfGregorianCal == 710_347);
7064 assert(SysTime(DateTime(1999, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 729_755);
7065 assert(SysTime(DateTime(2000, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 730_120);
7066 assert(SysTime(DateTime(2001, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 730_486);
7067
7068 assert(SysTime(DateTime(2010, 1, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_773);
7069 assert(SysTime(DateTime(2010, 1, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_803);
7070 assert(SysTime(DateTime(2010, 2, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_804);
7071 assert(SysTime(DateTime(2010, 2, 28, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_831);
7072 assert(SysTime(DateTime(2010, 3, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_832);
7073 assert(SysTime(DateTime(2010, 3, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_862);
7074 assert(SysTime(DateTime(2010, 4, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_863);
7075 assert(SysTime(DateTime(2010, 4, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_892);
7076 assert(SysTime(DateTime(2010, 5, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_893);
7077 assert(SysTime(DateTime(2010, 5, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_923);
7078 assert(SysTime(DateTime(2010, 6, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_924);
7079 assert(SysTime(DateTime(2010, 6, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_953);
7080 assert(SysTime(DateTime(2010, 7, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_954);
7081 assert(SysTime(DateTime(2010, 7, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_984);
7082 assert(SysTime(DateTime(2010, 8, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_985);
7083 assert(SysTime(DateTime(2010, 8, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_015);
7084 assert(SysTime(DateTime(2010, 9, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_016);
7085 assert(SysTime(DateTime(2010, 9, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_045);
7086 assert(SysTime(DateTime(2010, 10, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_046);
7087 assert(SysTime(DateTime(2010, 10, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_076);
7088 assert(SysTime(DateTime(2010, 11, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_077);
7089 assert(SysTime(DateTime(2010, 11, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_106);
7090 assert(SysTime(DateTime(2010, 12, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_107);
7091 assert(SysTime(DateTime(2010, 12, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_137);
7092
7093 assert(SysTime(DateTime(2012, 2, 1, 0, 0, 0)).dayOfGregorianCal == 734_534);
7094 assert(SysTime(DateTime(2012, 2, 28, 0, 0, 0)).dayOfGregorianCal == 734_561);
7095 assert(SysTime(DateTime(2012, 2, 29, 0, 0, 0)).dayOfGregorianCal == 734_562);
7096 assert(SysTime(DateTime(2012, 3, 1, 0, 0, 0)).dayOfGregorianCal == 734_563);
7097
7098 // Test B.C.
7099 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)).dayOfGregorianCal == 0);
7100 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_998)).dayOfGregorianCal == 0);
7101 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59)).dayOfGregorianCal == 0);
7102 assert(SysTime(DateTime(0, 12, 31, 0, 0, 0), hnsecs(1)).dayOfGregorianCal == 0);
7103 assert(SysTime(DateTime(0, 12, 31, 0, 0, 0)).dayOfGregorianCal == 0);
7104
7105 assert(SysTime(DateTime(-1, 12, 31, 23, 59, 59), hnsecs(9_999_999)).dayOfGregorianCal == -366);
7106 assert(SysTime(DateTime(-1, 12, 31, 23, 59, 59), hnsecs(9_999_998)).dayOfGregorianCal == -366);
7107 assert(SysTime(DateTime(-1, 12, 31, 23, 59, 59)).dayOfGregorianCal == -366);
7108 assert(SysTime(DateTime(-1, 12, 31, 0, 0, 0)).dayOfGregorianCal == -366);
7109
7110 assert(SysTime(DateTime(0, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == 0);
7111 assert(SysTime(DateTime(0, 12, 30, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1);
7112 assert(SysTime(DateTime(0, 12, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -30);
7113 assert(SysTime(DateTime(0, 11, 30, 12, 2, 9), msecs(212)).dayOfGregorianCal == -31);
7114
7115 assert(SysTime(DateTime(-1, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -366);
7116 assert(SysTime(DateTime(-1, 12, 30, 12, 2, 9), msecs(212)).dayOfGregorianCal == -367);
7117 assert(SysTime(DateTime(-1, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -730);
7118 assert(SysTime(DateTime(-2, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -731);
7119 assert(SysTime(DateTime(-2, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1095);
7120 assert(SysTime(DateTime(-3, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1096);
7121 assert(SysTime(DateTime(-3, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1460);
7122 assert(SysTime(DateTime(-4, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1461);
7123 assert(SysTime(DateTime(-4, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1826);
7124 assert(SysTime(DateTime(-5, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1827);
7125 assert(SysTime(DateTime(-5, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -2191);
7126 assert(SysTime(DateTime(-9, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -3652);
7127
7128 assert(SysTime(DateTime(-49, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -18_262);
7129 assert(SysTime(DateTime(-50, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -18_627);
7130 assert(SysTime(DateTime(-97, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -35_794);
7131 assert(SysTime(DateTime(-99, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -36_160);
7132 assert(SysTime(DateTime(-99, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -36_524);
7133 assert(SysTime(DateTime(-100, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -36_889);
7134 assert(SysTime(DateTime(-101, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -37_254);
7135 assert(SysTime(DateTime(-105, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -38_715);
7136 assert(SysTime(DateTime(-200, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -73_413);
7137 assert(SysTime(DateTime(-201, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -73_778);
7138 assert(SysTime(DateTime(-300, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -109_937);
7139 assert(SysTime(DateTime(-301, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -110_302);
7140 assert(SysTime(DateTime(-400, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -146_097);
7141 assert(SysTime(DateTime(-400, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -146_462);
7142 assert(SysTime(DateTime(-401, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -146_827);
7143 assert(SysTime(DateTime(-499, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -182_621);
7144 assert(SysTime(DateTime(-500, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -182_986);
7145 assert(SysTime(DateTime(-501, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -183_351);
7146 assert(SysTime(DateTime(-1000, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -365_607);
7147 assert(SysTime(DateTime(-1001, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -365_972);
7148 assert(SysTime(DateTime(-1599, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -584_387);
7149 assert(SysTime(DateTime(-1600, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -584_388);
7150 assert(SysTime(DateTime(-1600, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -584_753);
7151 assert(SysTime(DateTime(-1601, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -585_118);
7152 assert(SysTime(DateTime(-1900, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -694_325);
7153 assert(SysTime(DateTime(-1901, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -694_690);
7154 assert(SysTime(DateTime(-1999, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -730_484);
7155 assert(SysTime(DateTime(-2000, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -730_485);
7156 assert(SysTime(DateTime(-2000, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -730_850);
7157 assert(SysTime(DateTime(-2001, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -731_215);
7158
7159 assert(SysTime(DateTime(-2010, 1, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_502);
7160 assert(SysTime(DateTime(-2010, 1, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_472);
7161 assert(SysTime(DateTime(-2010, 2, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_471);
7162 assert(SysTime(DateTime(-2010, 2, 28, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_444);
7163 assert(SysTime(DateTime(-2010, 3, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_443);
7164 assert(SysTime(DateTime(-2010, 3, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_413);
7165 assert(SysTime(DateTime(-2010, 4, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_412);
7166 assert(SysTime(DateTime(-2010, 4, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_383);
7167 assert(SysTime(DateTime(-2010, 5, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_382);
7168 assert(SysTime(DateTime(-2010, 5, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_352);
7169 assert(SysTime(DateTime(-2010, 6, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_351);
7170 assert(SysTime(DateTime(-2010, 6, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_322);
7171 assert(SysTime(DateTime(-2010, 7, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_321);
7172 assert(SysTime(DateTime(-2010, 7, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_291);
7173 assert(SysTime(DateTime(-2010, 8, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_290);
7174 assert(SysTime(DateTime(-2010, 8, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_260);
7175 assert(SysTime(DateTime(-2010, 9, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_259);
7176 assert(SysTime(DateTime(-2010, 9, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_230);
7177 assert(SysTime(DateTime(-2010, 10, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_229);
7178 assert(SysTime(DateTime(-2010, 10, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_199);
7179 assert(SysTime(DateTime(-2010, 11, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_198);
7180 assert(SysTime(DateTime(-2010, 11, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_169);
7181 assert(SysTime(DateTime(-2010, 12, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_168);
7182 assert(SysTime(DateTime(-2010, 12, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_138);
7183
7184 assert(SysTime(DateTime(-2012, 2, 1, 0, 0, 0)).dayOfGregorianCal == -735_202);
7185 assert(SysTime(DateTime(-2012, 2, 28, 0, 0, 0)).dayOfGregorianCal == -735_175);
7186 assert(SysTime(DateTime(-2012, 2, 29, 0, 0, 0)).dayOfGregorianCal == -735_174);
7187 assert(SysTime(DateTime(-2012, 3, 1, 0, 0, 0)).dayOfGregorianCal == -735_173);
7188
7189 // Start of Hebrew Calendar
7190 assert(SysTime(DateTime(-3760, 9, 7, 0, 0, 0)).dayOfGregorianCal == -1_373_427);
7191
7192 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7193 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7194 assert(cst.dayOfGregorianCal == 729_941);
7195 assert(ist.dayOfGregorianCal == 729_941);
7196
7197 static void testScope(scope ref SysTime st) @safe
7198 {
7199 auto result = st.dayOfGregorianCal;
7200 }
7201 }
7202
7203
7204 // Test that the logic for the day of the Gregorian Calendar is consistent
7205 // between Date and SysTime.
7206 @safe unittest
7207 {
7208 import core.time;
7209 void test(Date date, SysTime st, size_t line = __LINE__)
7210 {
7211 if (date.dayOfGregorianCal != st.dayOfGregorianCal)
7212 {
7213 throw new AssertError(format("Date [%s] SysTime [%s]", date.dayOfGregorianCal, st.dayOfGregorianCal),
7214 __FILE__, line);
7215 }
7216 }
7217
7218 // Test A.D.
7219 test(Date(1, 1, 1), SysTime(DateTime(1, 1, 1, 0, 0, 0)));
7220 test(Date(1, 1, 2), SysTime(DateTime(1, 1, 2, 0, 0, 0), hnsecs(500)));
7221 test(Date(1, 2, 1), SysTime(DateTime(1, 2, 1, 0, 0, 0), hnsecs(50_000)));
7222 test(Date(2, 1, 1), SysTime(DateTime(2, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
7223 test(Date(3, 1, 1), SysTime(DateTime(3, 1, 1, 12, 13, 14)));
7224 test(Date(4, 1, 1), SysTime(DateTime(4, 1, 1, 12, 13, 14), hnsecs(500)));
7225 test(Date(5, 1, 1), SysTime(DateTime(5, 1, 1, 12, 13, 14), hnsecs(50_000)));
7226 test(Date(50, 1, 1), SysTime(DateTime(50, 1, 1, 12, 13, 14), hnsecs(9_999_999)));
7227 test(Date(97, 1, 1), SysTime(DateTime(97, 1, 1, 23, 59, 59)));
7228 test(Date(100, 1, 1), SysTime(DateTime(100, 1, 1, 23, 59, 59), hnsecs(500)));
7229 test(Date(101, 1, 1), SysTime(DateTime(101, 1, 1, 23, 59, 59), hnsecs(50_000)));
7230 test(Date(105, 1, 1), SysTime(DateTime(105, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
7231 test(Date(200, 1, 1), SysTime(DateTime(200, 1, 1, 0, 0, 0)));
7232 test(Date(201, 1, 1), SysTime(DateTime(201, 1, 1, 0, 0, 0), hnsecs(500)));
7233 test(Date(300, 1, 1), SysTime(DateTime(300, 1, 1, 0, 0, 0), hnsecs(50_000)));
7234 test(Date(301, 1, 1), SysTime(DateTime(301, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
7235 test(Date(400, 1, 1), SysTime(DateTime(400, 1, 1, 12, 13, 14)));
7236 test(Date(401, 1, 1), SysTime(DateTime(401, 1, 1, 12, 13, 14), hnsecs(500)));
7237 test(Date(500, 1, 1), SysTime(DateTime(500, 1, 1, 12, 13, 14), hnsecs(50_000)));
7238 test(Date(501, 1, 1), SysTime(DateTime(501, 1, 1, 12, 13, 14), hnsecs(9_999_999)));
7239 test(Date(1000, 1, 1), SysTime(DateTime(1000, 1, 1, 23, 59, 59)));
7240 test(Date(1001, 1, 1), SysTime(DateTime(1001, 1, 1, 23, 59, 59), hnsecs(500)));
7241 test(Date(1600, 1, 1), SysTime(DateTime(1600, 1, 1, 23, 59, 59), hnsecs(50_000)));
7242 test(Date(1601, 1, 1), SysTime(DateTime(1601, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
7243 test(Date(1900, 1, 1), SysTime(DateTime(1900, 1, 1, 0, 0, 0)));
7244 test(Date(1901, 1, 1), SysTime(DateTime(1901, 1, 1, 0, 0, 0), hnsecs(500)));
7245 test(Date(1945, 11, 12), SysTime(DateTime(1945, 11, 12, 0, 0, 0), hnsecs(50_000)));
7246 test(Date(1999, 1, 1), SysTime(DateTime(1999, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
7247 test(Date(1999, 7, 6), SysTime(DateTime(1999, 7, 6, 12, 13, 14)));
7248 test(Date(2000, 1, 1), SysTime(DateTime(2000, 1, 1, 12, 13, 14), hnsecs(500)));
7249 test(Date(2001, 1, 1), SysTime(DateTime(2001, 1, 1, 12, 13, 14), hnsecs(50_000)));
7250
7251 test(Date(2010, 1, 1), SysTime(DateTime(2010, 1, 1, 12, 13, 14), hnsecs(9_999_999)));
7252 test(Date(2010, 1, 31), SysTime(DateTime(2010, 1, 31, 23, 0, 0)));
7253 test(Date(2010, 2, 1), SysTime(DateTime(2010, 2, 1, 23, 59, 59), hnsecs(500)));
7254 test(Date(2010, 2, 28), SysTime(DateTime(2010, 2, 28, 23, 59, 59), hnsecs(50_000)));
7255 test(Date(2010, 3, 1), SysTime(DateTime(2010, 3, 1, 23, 59, 59), hnsecs(9_999_999)));
7256 test(Date(2010, 3, 31), SysTime(DateTime(2010, 3, 31, 0, 0, 0)));
7257 test(Date(2010, 4, 1), SysTime(DateTime(2010, 4, 1, 0, 0, 0), hnsecs(500)));
7258 test(Date(2010, 4, 30), SysTime(DateTime(2010, 4, 30, 0, 0, 0), hnsecs(50_000)));
7259 test(Date(2010, 5, 1), SysTime(DateTime(2010, 5, 1, 0, 0, 0), hnsecs(9_999_999)));
7260 test(Date(2010, 5, 31), SysTime(DateTime(2010, 5, 31, 12, 13, 14)));
7261 test(Date(2010, 6, 1), SysTime(DateTime(2010, 6, 1, 12, 13, 14), hnsecs(500)));
7262 test(Date(2010, 6, 30), SysTime(DateTime(2010, 6, 30, 12, 13, 14), hnsecs(50_000)));
7263 test(Date(2010, 7, 1), SysTime(DateTime(2010, 7, 1, 12, 13, 14), hnsecs(9_999_999)));
7264 test(Date(2010, 7, 31), SysTime(DateTime(2010, 7, 31, 23, 59, 59)));
7265 test(Date(2010, 8, 1), SysTime(DateTime(2010, 8, 1, 23, 59, 59), hnsecs(500)));
7266 test(Date(2010, 8, 31), SysTime(DateTime(2010, 8, 31, 23, 59, 59), hnsecs(50_000)));
7267 test(Date(2010, 9, 1), SysTime(DateTime(2010, 9, 1, 23, 59, 59), hnsecs(9_999_999)));
7268 test(Date(2010, 9, 30), SysTime(DateTime(2010, 9, 30, 12, 0, 0)));
7269 test(Date(2010, 10, 1), SysTime(DateTime(2010, 10, 1, 0, 12, 0), hnsecs(500)));
7270 test(Date(2010, 10, 31), SysTime(DateTime(2010, 10, 31, 0, 0, 12), hnsecs(50_000)));
7271 test(Date(2010, 11, 1), SysTime(DateTime(2010, 11, 1, 23, 0, 0), hnsecs(9_999_999)));
7272 test(Date(2010, 11, 30), SysTime(DateTime(2010, 11, 30, 0, 59, 0)));
7273 test(Date(2010, 12, 1), SysTime(DateTime(2010, 12, 1, 0, 0, 59), hnsecs(500)));
7274 test(Date(2010, 12, 31), SysTime(DateTime(2010, 12, 31, 0, 59, 59), hnsecs(50_000)));
7275
7276 test(Date(2012, 2, 1), SysTime(DateTime(2012, 2, 1, 23, 0, 59), hnsecs(9_999_999)));
7277 test(Date(2012, 2, 28), SysTime(DateTime(2012, 2, 28, 23, 59, 0)));
7278 test(Date(2012, 2, 29), SysTime(DateTime(2012, 2, 29, 7, 7, 7), hnsecs(7)));
7279 test(Date(2012, 3, 1), SysTime(DateTime(2012, 3, 1, 7, 7, 7), hnsecs(7)));
7280
7281 // Test B.C.
7282 test(Date(0, 12, 31), SysTime(DateTime(0, 12, 31, 0, 0, 0)));
7283 test(Date(0, 12, 30), SysTime(DateTime(0, 12, 30, 0, 0, 0), hnsecs(500)));
7284 test(Date(0, 12, 1), SysTime(DateTime(0, 12, 1, 0, 0, 0), hnsecs(50_000)));
7285 test(Date(0, 11, 30), SysTime(DateTime(0, 11, 30, 0, 0, 0), hnsecs(9_999_999)));
7286
7287 test(Date(-1, 12, 31), SysTime(DateTime(-1, 12, 31, 12, 13, 14)));
7288 test(Date(-1, 12, 30), SysTime(DateTime(-1, 12, 30, 12, 13, 14), hnsecs(500)));
7289 test(Date(-1, 1, 1), SysTime(DateTime(-1, 1, 1, 12, 13, 14), hnsecs(50_000)));
7290 test(Date(-2, 12, 31), SysTime(DateTime(-2, 12, 31, 12, 13, 14), hnsecs(9_999_999)));
7291 test(Date(-2, 1, 1), SysTime(DateTime(-2, 1, 1, 23, 59, 59)));
7292 test(Date(-3, 12, 31), SysTime(DateTime(-3, 12, 31, 23, 59, 59), hnsecs(500)));
7293 test(Date(-3, 1, 1), SysTime(DateTime(-3, 1, 1, 23, 59, 59), hnsecs(50_000)));
7294 test(Date(-4, 12, 31), SysTime(DateTime(-4, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
7295 test(Date(-4, 1, 1), SysTime(DateTime(-4, 1, 1, 0, 0, 0)));
7296 test(Date(-5, 12, 31), SysTime(DateTime(-5, 12, 31, 0, 0, 0), hnsecs(500)));
7297 test(Date(-5, 1, 1), SysTime(DateTime(-5, 1, 1, 0, 0, 0), hnsecs(50_000)));
7298 test(Date(-9, 1, 1), SysTime(DateTime(-9, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
7299
7300 test(Date(-49, 1, 1), SysTime(DateTime(-49, 1, 1, 12, 13, 14)));
7301 test(Date(-50, 1, 1), SysTime(DateTime(-50, 1, 1, 12, 13, 14), hnsecs(500)));
7302 test(Date(-97, 1, 1), SysTime(DateTime(-97, 1, 1, 12, 13, 14), hnsecs(50_000)));
7303 test(Date(-99, 12, 31), SysTime(DateTime(-99, 12, 31, 12, 13, 14), hnsecs(9_999_999)));
7304 test(Date(-99, 1, 1), SysTime(DateTime(-99, 1, 1, 23, 59, 59)));
7305 test(Date(-100, 1, 1), SysTime(DateTime(-100, 1, 1, 23, 59, 59), hnsecs(500)));
7306 test(Date(-101, 1, 1), SysTime(DateTime(-101, 1, 1, 23, 59, 59), hnsecs(50_000)));
7307 test(Date(-105, 1, 1), SysTime(DateTime(-105, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
7308 test(Date(-200, 1, 1), SysTime(DateTime(-200, 1, 1, 0, 0, 0)));
7309 test(Date(-201, 1, 1), SysTime(DateTime(-201, 1, 1, 0, 0, 0), hnsecs(500)));
7310 test(Date(-300, 1, 1), SysTime(DateTime(-300, 1, 1, 0, 0, 0), hnsecs(50_000)));
7311 test(Date(-301, 1, 1), SysTime(DateTime(-301, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
7312 test(Date(-400, 12, 31), SysTime(DateTime(-400, 12, 31, 12, 13, 14)));
7313 test(Date(-400, 1, 1), SysTime(DateTime(-400, 1, 1, 12, 13, 14), hnsecs(500)));
7314 test(Date(-401, 1, 1), SysTime(DateTime(-401, 1, 1, 12, 13, 14), hnsecs(50_000)));
7315 test(Date(-499, 1, 1), SysTime(DateTime(-499, 1, 1, 12, 13, 14), hnsecs(9_999_999)));
7316 test(Date(-500, 1, 1), SysTime(DateTime(-500, 1, 1, 23, 59, 59)));
7317 test(Date(-501, 1, 1), SysTime(DateTime(-501, 1, 1, 23, 59, 59), hnsecs(500)));
7318 test(Date(-1000, 1, 1), SysTime(DateTime(-1000, 1, 1, 23, 59, 59), hnsecs(50_000)));
7319 test(Date(-1001, 1, 1), SysTime(DateTime(-1001, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
7320 test(Date(-1599, 1, 1), SysTime(DateTime(-1599, 1, 1, 0, 0, 0)));
7321 test(Date(-1600, 12, 31), SysTime(DateTime(-1600, 12, 31, 0, 0, 0), hnsecs(500)));
7322 test(Date(-1600, 1, 1), SysTime(DateTime(-1600, 1, 1, 0, 0, 0), hnsecs(50_000)));
7323 test(Date(-1601, 1, 1), SysTime(DateTime(-1601, 1, 1, 0, 0, 0), hnsecs(9_999_999)));
7324 test(Date(-1900, 1, 1), SysTime(DateTime(-1900, 1, 1, 12, 13, 14)));
7325 test(Date(-1901, 1, 1), SysTime(DateTime(-1901, 1, 1, 12, 13, 14), hnsecs(500)));
7326 test(Date(-1999, 1, 1), SysTime(DateTime(-1999, 1, 1, 12, 13, 14), hnsecs(50_000)));
7327 test(Date(-1999, 7, 6), SysTime(DateTime(-1999, 7, 6, 12, 13, 14), hnsecs(9_999_999)));
7328 test(Date(-2000, 12, 31), SysTime(DateTime(-2000, 12, 31, 23, 59, 59)));
7329 test(Date(-2000, 1, 1), SysTime(DateTime(-2000, 1, 1, 23, 59, 59), hnsecs(500)));
7330 test(Date(-2001, 1, 1), SysTime(DateTime(-2001, 1, 1, 23, 59, 59), hnsecs(50_000)));
7331
7332 test(Date(-2010, 1, 1), SysTime(DateTime(-2010, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
7333 test(Date(-2010, 1, 31), SysTime(DateTime(-2010, 1, 31, 0, 0, 0)));
7334 test(Date(-2010, 2, 1), SysTime(DateTime(-2010, 2, 1, 0, 0, 0), hnsecs(500)));
7335 test(Date(-2010, 2, 28), SysTime(DateTime(-2010, 2, 28, 0, 0, 0), hnsecs(50_000)));
7336 test(Date(-2010, 3, 1), SysTime(DateTime(-2010, 3, 1, 0, 0, 0), hnsecs(9_999_999)));
7337 test(Date(-2010, 3, 31), SysTime(DateTime(-2010, 3, 31, 12, 13, 14)));
7338 test(Date(-2010, 4, 1), SysTime(DateTime(-2010, 4, 1, 12, 13, 14), hnsecs(500)));
7339 test(Date(-2010, 4, 30), SysTime(DateTime(-2010, 4, 30, 12, 13, 14), hnsecs(50_000)));
7340 test(Date(-2010, 5, 1), SysTime(DateTime(-2010, 5, 1, 12, 13, 14), hnsecs(9_999_999)));
7341 test(Date(-2010, 5, 31), SysTime(DateTime(-2010, 5, 31, 23, 59, 59)));
7342 test(Date(-2010, 6, 1), SysTime(DateTime(-2010, 6, 1, 23, 59, 59), hnsecs(500)));
7343 test(Date(-2010, 6, 30), SysTime(DateTime(-2010, 6, 30, 23, 59, 59), hnsecs(50_000)));
7344 test(Date(-2010, 7, 1), SysTime(DateTime(-2010, 7, 1, 23, 59, 59), hnsecs(9_999_999)));
7345 test(Date(-2010, 7, 31), SysTime(DateTime(-2010, 7, 31, 0, 0, 0)));
7346 test(Date(-2010, 8, 1), SysTime(DateTime(-2010, 8, 1, 0, 0, 0), hnsecs(500)));
7347 test(Date(-2010, 8, 31), SysTime(DateTime(-2010, 8, 31, 0, 0, 0), hnsecs(50_000)));
7348 test(Date(-2010, 9, 1), SysTime(DateTime(-2010, 9, 1, 0, 0, 0), hnsecs(9_999_999)));
7349 test(Date(-2010, 9, 30), SysTime(DateTime(-2010, 9, 30, 12, 0, 0)));
7350 test(Date(-2010, 10, 1), SysTime(DateTime(-2010, 10, 1, 0, 12, 0), hnsecs(500)));
7351 test(Date(-2010, 10, 31), SysTime(DateTime(-2010, 10, 31, 0, 0, 12), hnsecs(50_000)));
7352 test(Date(-2010, 11, 1), SysTime(DateTime(-2010, 11, 1, 23, 0, 0), hnsecs(9_999_999)));
7353 test(Date(-2010, 11, 30), SysTime(DateTime(-2010, 11, 30, 0, 59, 0)));
7354 test(Date(-2010, 12, 1), SysTime(DateTime(-2010, 12, 1, 0, 0, 59), hnsecs(500)));
7355 test(Date(-2010, 12, 31), SysTime(DateTime(-2010, 12, 31, 0, 59, 59), hnsecs(50_000)));
7356
7357 test(Date(-2012, 2, 1), SysTime(DateTime(-2012, 2, 1, 23, 0, 59), hnsecs(9_999_999)));
7358 test(Date(-2012, 2, 28), SysTime(DateTime(-2012, 2, 28, 23, 59, 0)));
7359 test(Date(-2012, 2, 29), SysTime(DateTime(-2012, 2, 29, 7, 7, 7), hnsecs(7)));
7360 test(Date(-2012, 3, 1), SysTime(DateTime(-2012, 3, 1, 7, 7, 7), hnsecs(7)));
7361
7362 test(Date(-3760, 9, 7), SysTime(DateTime(-3760, 9, 7, 0, 0, 0)));
7363 }
7364
7365
7366 /++
7367 The Xth day of the Gregorian Calendar that this $(LREF SysTime) is on.
7368 Setting this property does not affect the time portion of $(LREF SysTime).
7369
7370 Params:
7371 days = The day of the Gregorian Calendar to set this $(LREF SysTime)
7372 to.
7373 +/
7374 @property void dayOfGregorianCal(int days) @safe nothrow scope
7375 {
7376 auto hnsecs = adjTime;
7377 hnsecs = removeUnitsFromHNSecs!"days"(hnsecs);
7378
7379 if (hnsecs < 0)
7380 hnsecs += convert!("hours", "hnsecs")(24);
7381
7382 if (--days < 0)
7383 {
7384 hnsecs -= convert!("hours", "hnsecs")(24);
7385 ++days;
7386 }
7387
7388 immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
7389
7390 adjTime = newDaysHNSecs + hnsecs;
7391 }
7392
7393 ///
7394 @safe unittest
7395 {
7396 import core.time;
7397 import std.datetime.date : DateTime;
7398
7399 auto st = SysTime(DateTime(0, 1, 1, 12, 0, 0));
7400 st.dayOfGregorianCal = 1;
7401 assert(st == SysTime(DateTime(1, 1, 1, 12, 0, 0)));
7402
7403 st.dayOfGregorianCal = 365;
7404 assert(st == SysTime(DateTime(1, 12, 31, 12, 0, 0)));
7405
7406 st.dayOfGregorianCal = 366;
7407 assert(st == SysTime(DateTime(2, 1, 1, 12, 0, 0)));
7408
7409 st.dayOfGregorianCal = 0;
7410 assert(st == SysTime(DateTime(0, 12, 31, 12, 0, 0)));
7411
7412 st.dayOfGregorianCal = -365;
7413 assert(st == SysTime(DateTime(-0, 1, 1, 12, 0, 0)));
7414
7415 st.dayOfGregorianCal = -366;
7416 assert(st == SysTime(DateTime(-1, 12, 31, 12, 0, 0)));
7417
7418 st.dayOfGregorianCal = 730_120;
7419 assert(st == SysTime(DateTime(2000, 1, 1, 12, 0, 0)));
7420
7421 st.dayOfGregorianCal = 734_137;
7422 assert(st == SysTime(DateTime(2010, 12, 31, 12, 0, 0)));
7423 }
7424
7425 @safe unittest
7426 {
7427 import core.time;
7428 void testST(SysTime orig, int day, SysTime expected, size_t line = __LINE__) @safe
7429 {
7430 orig.dayOfGregorianCal = day;
7431 if (orig != expected)
7432 throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line);
7433 }
7434
7435 // Test A.D.
7436 testST(SysTime(DateTime(1, 1, 1, 0, 0, 0)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
7437 testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)));
7438 testST(SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)), 1,
7439 SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
7440
7441 // Test B.C.
7442 testST(SysTime(DateTime(0, 1, 1, 0, 0, 0)), 0, SysTime(DateTime(0, 12, 31, 0, 0, 0)));
7443 testST(SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)), 0,
7444 SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
7445 testST(SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(1)), 0,
7446 SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1)));
7447 testST(SysTime(DateTime(0, 1, 1, 23, 59, 59)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59)));
7448
7449 // Test Both.
7450 testST(SysTime(DateTime(-512, 7, 20, 0, 0, 0)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0)));
7451 testST(SysTime(DateTime(-513, 6, 6, 0, 0, 0), hnsecs(1)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)));
7452 testST(SysTime(DateTime(-511, 5, 7, 23, 59, 59), hnsecs(9_999_999)), 1,
7453 SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)));
7454
7455 testST(SysTime(DateTime(1607, 4, 8, 0, 0, 0)), 0, SysTime(DateTime(0, 12, 31, 0, 0, 0)));
7456 testST(SysTime(DateTime(1500, 3, 9, 23, 59, 59), hnsecs(9_999_999)), 0,
7457 SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
7458 testST(SysTime(DateTime(999, 2, 10, 23, 59, 59), hnsecs(1)), 0,
7459 SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1)));
7460 testST(SysTime(DateTime(2007, 12, 11, 23, 59, 59)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59)));
7461
7462
7463 auto st = SysTime(DateTime(1, 1, 1, 12, 2, 9), msecs(212));
7464
7465 void testST2(int day, SysTime expected, size_t line = __LINE__) @safe
7466 {
7467 st.dayOfGregorianCal = day;
7468 if (st != expected)
7469 throw new AssertError(format("Failed. actual [%s] != expected [%s]", st, expected), __FILE__, line);
7470 }
7471
7472 // Test A.D.
7473 testST2(1, SysTime(DateTime(1, 1, 1, 12, 2, 9), msecs(212)));
7474 testST2(2, SysTime(DateTime(1, 1, 2, 12, 2, 9), msecs(212)));
7475 testST2(32, SysTime(DateTime(1, 2, 1, 12, 2, 9), msecs(212)));
7476 testST2(366, SysTime(DateTime(2, 1, 1, 12, 2, 9), msecs(212)));
7477 testST2(731, SysTime(DateTime(3, 1, 1, 12, 2, 9), msecs(212)));
7478 testST2(1096, SysTime(DateTime(4, 1, 1, 12, 2, 9), msecs(212)));
7479 testST2(1462, SysTime(DateTime(5, 1, 1, 12, 2, 9), msecs(212)));
7480 testST2(17_898, SysTime(DateTime(50, 1, 1, 12, 2, 9), msecs(212)));
7481 testST2(35_065, SysTime(DateTime(97, 1, 1, 12, 2, 9), msecs(212)));
7482 testST2(36_160, SysTime(DateTime(100, 1, 1, 12, 2, 9), msecs(212)));
7483 testST2(36_525, SysTime(DateTime(101, 1, 1, 12, 2, 9), msecs(212)));
7484 testST2(37_986, SysTime(DateTime(105, 1, 1, 12, 2, 9), msecs(212)));
7485 testST2(72_684, SysTime(DateTime(200, 1, 1, 12, 2, 9), msecs(212)));
7486 testST2(73_049, SysTime(DateTime(201, 1, 1, 12, 2, 9), msecs(212)));
7487 testST2(109_208, SysTime(DateTime(300, 1, 1, 12, 2, 9), msecs(212)));
7488 testST2(109_573, SysTime(DateTime(301, 1, 1, 12, 2, 9), msecs(212)));
7489 testST2(145_732, SysTime(DateTime(400, 1, 1, 12, 2, 9), msecs(212)));
7490 testST2(146_098, SysTime(DateTime(401, 1, 1, 12, 2, 9), msecs(212)));
7491 testST2(182_257, SysTime(DateTime(500, 1, 1, 12, 2, 9), msecs(212)));
7492 testST2(182_622, SysTime(DateTime(501, 1, 1, 12, 2, 9), msecs(212)));
7493 testST2(364_878, SysTime(DateTime(1000, 1, 1, 12, 2, 9), msecs(212)));
7494 testST2(365_243, SysTime(DateTime(1001, 1, 1, 12, 2, 9), msecs(212)));
7495 testST2(584_023, SysTime(DateTime(1600, 1, 1, 12, 2, 9), msecs(212)));
7496 testST2(584_389, SysTime(DateTime(1601, 1, 1, 12, 2, 9), msecs(212)));
7497 testST2(693_596, SysTime(DateTime(1900, 1, 1, 12, 2, 9), msecs(212)));
7498 testST2(693_961, SysTime(DateTime(1901, 1, 1, 12, 2, 9), msecs(212)));
7499 testST2(729_755, SysTime(DateTime(1999, 1, 1, 12, 2, 9), msecs(212)));
7500 testST2(730_120, SysTime(DateTime(2000, 1, 1, 12, 2, 9), msecs(212)));
7501 testST2(730_486, SysTime(DateTime(2001, 1, 1, 12, 2, 9), msecs(212)));
7502
7503 testST2(733_773, SysTime(DateTime(2010, 1, 1, 12, 2, 9), msecs(212)));
7504 testST2(733_803, SysTime(DateTime(2010, 1, 31, 12, 2, 9), msecs(212)));
7505 testST2(733_804, SysTime(DateTime(2010, 2, 1, 12, 2, 9), msecs(212)));
7506 testST2(733_831, SysTime(DateTime(2010, 2, 28, 12, 2, 9), msecs(212)));
7507 testST2(733_832, SysTime(DateTime(2010, 3, 1, 12, 2, 9), msecs(212)));
7508 testST2(733_862, SysTime(DateTime(2010, 3, 31, 12, 2, 9), msecs(212)));
7509 testST2(733_863, SysTime(DateTime(2010, 4, 1, 12, 2, 9), msecs(212)));
7510 testST2(733_892, SysTime(DateTime(2010, 4, 30, 12, 2, 9), msecs(212)));
7511 testST2(733_893, SysTime(DateTime(2010, 5, 1, 12, 2, 9), msecs(212)));
7512 testST2(733_923, SysTime(DateTime(2010, 5, 31, 12, 2, 9), msecs(212)));
7513 testST2(733_924, SysTime(DateTime(2010, 6, 1, 12, 2, 9), msecs(212)));
7514 testST2(733_953, SysTime(DateTime(2010, 6, 30, 12, 2, 9), msecs(212)));
7515 testST2(733_954, SysTime(DateTime(2010, 7, 1, 12, 2, 9), msecs(212)));
7516 testST2(733_984, SysTime(DateTime(2010, 7, 31, 12, 2, 9), msecs(212)));
7517 testST2(733_985, SysTime(DateTime(2010, 8, 1, 12, 2, 9), msecs(212)));
7518 testST2(734_015, SysTime(DateTime(2010, 8, 31, 12, 2, 9), msecs(212)));
7519 testST2(734_016, SysTime(DateTime(2010, 9, 1, 12, 2, 9), msecs(212)));
7520 testST2(734_045, SysTime(DateTime(2010, 9, 30, 12, 2, 9), msecs(212)));
7521 testST2(734_046, SysTime(DateTime(2010, 10, 1, 12, 2, 9), msecs(212)));
7522 testST2(734_076, SysTime(DateTime(2010, 10, 31, 12, 2, 9), msecs(212)));
7523 testST2(734_077, SysTime(DateTime(2010, 11, 1, 12, 2, 9), msecs(212)));
7524 testST2(734_106, SysTime(DateTime(2010, 11, 30, 12, 2, 9), msecs(212)));
7525 testST2(734_107, SysTime(DateTime(2010, 12, 1, 12, 2, 9), msecs(212)));
7526 testST2(734_137, SysTime(DateTime(2010, 12, 31, 12, 2, 9), msecs(212)));
7527
7528 testST2(734_534, SysTime(DateTime(2012, 2, 1, 12, 2, 9), msecs(212)));
7529 testST2(734_561, SysTime(DateTime(2012, 2, 28, 12, 2, 9), msecs(212)));
7530 testST2(734_562, SysTime(DateTime(2012, 2, 29, 12, 2, 9), msecs(212)));
7531 testST2(734_563, SysTime(DateTime(2012, 3, 1, 12, 2, 9), msecs(212)));
7532
7533 testST2(734_534, SysTime(DateTime(2012, 2, 1, 12, 2, 9), msecs(212)));
7534
7535 testST2(734_561, SysTime(DateTime(2012, 2, 28, 12, 2, 9), msecs(212)));
7536 testST2(734_562, SysTime(DateTime(2012, 2, 29, 12, 2, 9), msecs(212)));
7537 testST2(734_563, SysTime(DateTime(2012, 3, 1, 12, 2, 9), msecs(212)));
7538
7539 // Test B.C.
7540 testST2(0, SysTime(DateTime(0, 12, 31, 12, 2, 9), msecs(212)));
7541 testST2(-1, SysTime(DateTime(0, 12, 30, 12, 2, 9), msecs(212)));
7542 testST2(-30, SysTime(DateTime(0, 12, 1, 12, 2, 9), msecs(212)));
7543 testST2(-31, SysTime(DateTime(0, 11, 30, 12, 2, 9), msecs(212)));
7544
7545 testST2(-366, SysTime(DateTime(-1, 12, 31, 12, 2, 9), msecs(212)));
7546 testST2(-367, SysTime(DateTime(-1, 12, 30, 12, 2, 9), msecs(212)));
7547 testST2(-730, SysTime(DateTime(-1, 1, 1, 12, 2, 9), msecs(212)));
7548 testST2(-731, SysTime(DateTime(-2, 12, 31, 12, 2, 9), msecs(212)));
7549 testST2(-1095, SysTime(DateTime(-2, 1, 1, 12, 2, 9), msecs(212)));
7550 testST2(-1096, SysTime(DateTime(-3, 12, 31, 12, 2, 9), msecs(212)));
7551 testST2(-1460, SysTime(DateTime(-3, 1, 1, 12, 2, 9), msecs(212)));
7552 testST2(-1461, SysTime(DateTime(-4, 12, 31, 12, 2, 9), msecs(212)));
7553 testST2(-1826, SysTime(DateTime(-4, 1, 1, 12, 2, 9), msecs(212)));
7554 testST2(-1827, SysTime(DateTime(-5, 12, 31, 12, 2, 9), msecs(212)));
7555 testST2(-2191, SysTime(DateTime(-5, 1, 1, 12, 2, 9), msecs(212)));
7556 testST2(-3652, SysTime(DateTime(-9, 1, 1, 12, 2, 9), msecs(212)));
7557
7558 testST2(-18_262, SysTime(DateTime(-49, 1, 1, 12, 2, 9), msecs(212)));
7559 testST2(-18_627, SysTime(DateTime(-50, 1, 1, 12, 2, 9), msecs(212)));
7560 testST2(-35_794, SysTime(DateTime(-97, 1, 1, 12, 2, 9), msecs(212)));
7561 testST2(-36_160, SysTime(DateTime(-99, 12, 31, 12, 2, 9), msecs(212)));
7562 testST2(-36_524, SysTime(DateTime(-99, 1, 1, 12, 2, 9), msecs(212)));
7563 testST2(-36_889, SysTime(DateTime(-100, 1, 1, 12, 2, 9), msecs(212)));
7564 testST2(-37_254, SysTime(DateTime(-101, 1, 1, 12, 2, 9), msecs(212)));
7565 testST2(-38_715, SysTime(DateTime(-105, 1, 1, 12, 2, 9), msecs(212)));
7566 testST2(-73_413, SysTime(DateTime(-200, 1, 1, 12, 2, 9), msecs(212)));
7567 testST2(-73_778, SysTime(DateTime(-201, 1, 1, 12, 2, 9), msecs(212)));
7568 testST2(-109_937, SysTime(DateTime(-300, 1, 1, 12, 2, 9), msecs(212)));
7569 testST2(-110_302, SysTime(DateTime(-301, 1, 1, 12, 2, 9), msecs(212)));
7570 testST2(-146_097, SysTime(DateTime(-400, 12, 31, 12, 2, 9), msecs(212)));
7571 testST2(-146_462, SysTime(DateTime(-400, 1, 1, 12, 2, 9), msecs(212)));
7572 testST2(-146_827, SysTime(DateTime(-401, 1, 1, 12, 2, 9), msecs(212)));
7573 testST2(-182_621, SysTime(DateTime(-499, 1, 1, 12, 2, 9), msecs(212)));
7574 testST2(-182_986, SysTime(DateTime(-500, 1, 1, 12, 2, 9), msecs(212)));
7575 testST2(-183_351, SysTime(DateTime(-501, 1, 1, 12, 2, 9), msecs(212)));
7576 testST2(-365_607, SysTime(DateTime(-1000, 1, 1, 12, 2, 9), msecs(212)));
7577 testST2(-365_972, SysTime(DateTime(-1001, 1, 1, 12, 2, 9), msecs(212)));
7578 testST2(-584_387, SysTime(DateTime(-1599, 1, 1, 12, 2, 9), msecs(212)));
7579 testST2(-584_388, SysTime(DateTime(-1600, 12, 31, 12, 2, 9), msecs(212)));
7580 testST2(-584_753, SysTime(DateTime(-1600, 1, 1, 12, 2, 9), msecs(212)));
7581 testST2(-585_118, SysTime(DateTime(-1601, 1, 1, 12, 2, 9), msecs(212)));
7582 testST2(-694_325, SysTime(DateTime(-1900, 1, 1, 12, 2, 9), msecs(212)));
7583 testST2(-694_690, SysTime(DateTime(-1901, 1, 1, 12, 2, 9), msecs(212)));
7584 testST2(-730_484, SysTime(DateTime(-1999, 1, 1, 12, 2, 9), msecs(212)));
7585 testST2(-730_485, SysTime(DateTime(-2000, 12, 31, 12, 2, 9), msecs(212)));
7586 testST2(-730_850, SysTime(DateTime(-2000, 1, 1, 12, 2, 9), msecs(212)));
7587 testST2(-731_215, SysTime(DateTime(-2001, 1, 1, 12, 2, 9), msecs(212)));
7588
7589 testST2(-734_502, SysTime(DateTime(-2010, 1, 1, 12, 2, 9), msecs(212)));
7590 testST2(-734_472, SysTime(DateTime(-2010, 1, 31, 12, 2, 9), msecs(212)));
7591 testST2(-734_471, SysTime(DateTime(-2010, 2, 1, 12, 2, 9), msecs(212)));
7592 testST2(-734_444, SysTime(DateTime(-2010, 2, 28, 12, 2, 9), msecs(212)));
7593 testST2(-734_443, SysTime(DateTime(-2010, 3, 1, 12, 2, 9), msecs(212)));
7594 testST2(-734_413, SysTime(DateTime(-2010, 3, 31, 12, 2, 9), msecs(212)));
7595 testST2(-734_412, SysTime(DateTime(-2010, 4, 1, 12, 2, 9), msecs(212)));
7596 testST2(-734_383, SysTime(DateTime(-2010, 4, 30, 12, 2, 9), msecs(212)));
7597 testST2(-734_382, SysTime(DateTime(-2010, 5, 1, 12, 2, 9), msecs(212)));
7598 testST2(-734_352, SysTime(DateTime(-2010, 5, 31, 12, 2, 9), msecs(212)));
7599 testST2(-734_351, SysTime(DateTime(-2010, 6, 1, 12, 2, 9), msecs(212)));
7600 testST2(-734_322, SysTime(DateTime(-2010, 6, 30, 12, 2, 9), msecs(212)));
7601 testST2(-734_321, SysTime(DateTime(-2010, 7, 1, 12, 2, 9), msecs(212)));
7602 testST2(-734_291, SysTime(DateTime(-2010, 7, 31, 12, 2, 9), msecs(212)));
7603 testST2(-734_290, SysTime(DateTime(-2010, 8, 1, 12, 2, 9), msecs(212)));
7604 testST2(-734_260, SysTime(DateTime(-2010, 8, 31, 12, 2, 9), msecs(212)));
7605 testST2(-734_259, SysTime(DateTime(-2010, 9, 1, 12, 2, 9), msecs(212)));
7606 testST2(-734_230, SysTime(DateTime(-2010, 9, 30, 12, 2, 9), msecs(212)));
7607 testST2(-734_229, SysTime(DateTime(-2010, 10, 1, 12, 2, 9), msecs(212)));
7608 testST2(-734_199, SysTime(DateTime(-2010, 10, 31, 12, 2, 9), msecs(212)));
7609 testST2(-734_198, SysTime(DateTime(-2010, 11, 1, 12, 2, 9), msecs(212)));
7610 testST2(-734_169, SysTime(DateTime(-2010, 11, 30, 12, 2, 9), msecs(212)));
7611 testST2(-734_168, SysTime(DateTime(-2010, 12, 1, 12, 2, 9), msecs(212)));
7612 testST2(-734_138, SysTime(DateTime(-2010, 12, 31, 12, 2, 9), msecs(212)));
7613
7614 testST2(-735_202, SysTime(DateTime(-2012, 2, 1, 12, 2, 9), msecs(212)));
7615 testST2(-735_175, SysTime(DateTime(-2012, 2, 28, 12, 2, 9), msecs(212)));
7616 testST2(-735_174, SysTime(DateTime(-2012, 2, 29, 12, 2, 9), msecs(212)));
7617 testST2(-735_173, SysTime(DateTime(-2012, 3, 1, 12, 2, 9), msecs(212)));
7618
7619 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7620 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7621 static assert(!__traits(compiles, cst.dayOfGregorianCal = 7));
7622 static assert(!__traits(compiles, ist.dayOfGregorianCal = 7));
7623
7624 static void testScope(scope ref SysTime st) @safe
7625 {
7626 st.dayOfGregorianCal = 42;
7627 }
7628 }
7629
7630
7631 /++
7632 The ISO 8601 week of the year that this $(LREF SysTime) is in.
7633
7634 See_Also:
7635 $(HTTP en.wikipedia.org/wiki/ISO_week_date, ISO Week Date).
7636 +/
7637 @property ubyte isoWeek() @safe const nothrow scope
7638 {
7639 return (cast(Date) this).isoWeek;
7640 }
7641
7642 ///
7643 @safe unittest
7644 {
7645 import core.time;
7646 import std.datetime.date : Date;
7647
7648 auto st = SysTime(Date(1999, 7, 6));
7649 const cst = SysTime(Date(2010, 5, 1));
7650 immutable ist = SysTime(Date(2015, 10, 10));
7651
7652 assert(st.isoWeek == 27);
7653 assert(cst.isoWeek == 17);
7654 assert(ist.isoWeek == 41);
7655 }
7656
7657 @safe unittest
7658 {
7659 static void testScope(scope ref SysTime st) @safe
7660 {
7661 auto result = st.isoWeek;
7662 }
7663 }
7664
7665
7666 /++
7667 $(LREF SysTime) for the last day in the month that this Date is in.
7668 The time portion of endOfMonth is always 23:59:59.9999999.
7669 +/
7670 @property SysTime endOfMonth() @safe const nothrow scope
7671 {
7672 immutable hnsecs = adjTime;
7673 immutable days = getUnitsFromHNSecs!"days"(hnsecs);
7674
7675 auto date = Date(cast(int) days + 1).endOfMonth;
7676 auto newDays = date.dayOfGregorianCal - 1;
7677 long theTimeHNSecs;
7678
7679 if (newDays < 0)
7680 {
7681 theTimeHNSecs = -1;
7682 ++newDays;
7683 }
7684 else
7685 theTimeHNSecs = convert!("days", "hnsecs")(1) - 1;
7686
7687 immutable newDaysHNSecs = convert!("days", "hnsecs")(newDays);
7688
7689 auto retval = SysTime(this._stdTime, this._timezone);
7690 retval.adjTime = newDaysHNSecs + theTimeHNSecs;
7691
7692 return retval;
7693 }
7694
7695 ///
7696 @safe unittest
7697 {
7698 import core.time : msecs, usecs, hnsecs;
7699 import std.datetime.date : DateTime;
7700
7701 assert(SysTime(DateTime(1999, 1, 6, 0, 0, 0)).endOfMonth ==
7702 SysTime(DateTime(1999, 1, 31, 23, 59, 59), hnsecs(9_999_999)));
7703
7704 assert(SysTime(DateTime(1999, 2, 7, 19, 30, 0), msecs(24)).endOfMonth ==
7705 SysTime(DateTime(1999, 2, 28, 23, 59, 59), hnsecs(9_999_999)));
7706
7707 assert(SysTime(DateTime(2000, 2, 7, 5, 12, 27), usecs(5203)).endOfMonth ==
7708 SysTime(DateTime(2000, 2, 29, 23, 59, 59), hnsecs(9_999_999)));
7709
7710 assert(SysTime(DateTime(2000, 6, 4, 12, 22, 9), hnsecs(12345)).endOfMonth ==
7711 SysTime(DateTime(2000, 6, 30, 23, 59, 59), hnsecs(9_999_999)));
7712 }
7713
7714 @safe unittest
7715 {
7716 import core.time;
7717 // Test A.D.
7718 assert(SysTime(Date(1999, 1, 1)).endOfMonth == SysTime(DateTime(1999, 1, 31, 23, 59, 59), hnsecs(9_999_999)));
7719 assert(SysTime(Date(1999, 2, 1)).endOfMonth == SysTime(DateTime(1999, 2, 28, 23, 59, 59), hnsecs(9_999_999)));
7720 assert(SysTime(Date(2000, 2, 1)).endOfMonth == SysTime(DateTime(2000, 2, 29, 23, 59, 59), hnsecs(9_999_999)));
7721 assert(SysTime(Date(1999, 3, 1)).endOfMonth == SysTime(DateTime(1999, 3, 31, 23, 59, 59), hnsecs(9_999_999)));
7722 assert(SysTime(Date(1999, 4, 1)).endOfMonth == SysTime(DateTime(1999, 4, 30, 23, 59, 59), hnsecs(9_999_999)));
7723 assert(SysTime(Date(1999, 5, 1)).endOfMonth == SysTime(DateTime(1999, 5, 31, 23, 59, 59), hnsecs(9_999_999)));
7724 assert(SysTime(Date(1999, 6, 1)).endOfMonth == SysTime(DateTime(1999, 6, 30, 23, 59, 59), hnsecs(9_999_999)));
7725 assert(SysTime(Date(1999, 7, 1)).endOfMonth == SysTime(DateTime(1999, 7, 31, 23, 59, 59), hnsecs(9_999_999)));
7726 assert(SysTime(Date(1999, 8, 1)).endOfMonth == SysTime(DateTime(1999, 8, 31, 23, 59, 59), hnsecs(9_999_999)));
7727 assert(SysTime(Date(1999, 9, 1)).endOfMonth == SysTime(DateTime(1999, 9, 30, 23, 59, 59), hnsecs(9_999_999)));
7728 assert(SysTime(Date(1999, 10, 1)).endOfMonth == SysTime(DateTime(1999, 10, 31, 23, 59, 59), hnsecs(9_999_999)));
7729 assert(SysTime(Date(1999, 11, 1)).endOfMonth == SysTime(DateTime(1999, 11, 30, 23, 59, 59), hnsecs(9_999_999)));
7730 assert(SysTime(Date(1999, 12, 1)).endOfMonth == SysTime(DateTime(1999, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
7731
7732 // Test B.C.
7733 assert(SysTime(Date(-1999, 1, 1)).endOfMonth == SysTime(DateTime(-1999, 1, 31, 23, 59, 59), hnsecs(9_999_999)));
7734 assert(SysTime(Date(-1999, 2, 1)).endOfMonth == SysTime(DateTime(-1999, 2, 28, 23, 59, 59), hnsecs(9_999_999)));
7735 assert(SysTime(Date(-2000, 2, 1)).endOfMonth == SysTime(DateTime(-2000, 2, 29, 23, 59, 59), hnsecs(9_999_999)));
7736 assert(SysTime(Date(-1999, 3, 1)).endOfMonth == SysTime(DateTime(-1999, 3, 31, 23, 59, 59), hnsecs(9_999_999)));
7737 assert(SysTime(Date(-1999, 4, 1)).endOfMonth == SysTime(DateTime(-1999, 4, 30, 23, 59, 59), hnsecs(9_999_999)));
7738 assert(SysTime(Date(-1999, 5, 1)).endOfMonth == SysTime(DateTime(-1999, 5, 31, 23, 59, 59), hnsecs(9_999_999)));
7739 assert(SysTime(Date(-1999, 6, 1)).endOfMonth == SysTime(DateTime(-1999, 6, 30, 23, 59, 59), hnsecs(9_999_999)));
7740 assert(SysTime(Date(-1999, 7, 1)).endOfMonth == SysTime(DateTime(-1999, 7, 31, 23, 59, 59), hnsecs(9_999_999)));
7741 assert(SysTime(Date(-1999, 8, 1)).endOfMonth == SysTime(DateTime(-1999, 8, 31, 23, 59, 59), hnsecs(9_999_999)));
7742 assert(SysTime(Date(-1999, 9, 1)).endOfMonth == SysTime(DateTime(-1999, 9, 30, 23, 59, 59), hnsecs(9_999_999)));
7743 assert(SysTime(Date(-1999, 10, 1)).endOfMonth ==
7744 SysTime(DateTime(-1999, 10, 31, 23, 59, 59), hnsecs(9_999_999)));
7745 assert(SysTime(Date(-1999, 11, 1)).endOfMonth ==
7746 SysTime(DateTime(-1999, 11, 30, 23, 59, 59), hnsecs(9_999_999)));
7747 assert(SysTime(Date(-1999, 12, 1)).endOfMonth ==
7748 SysTime(DateTime(-1999, 12, 31, 23, 59, 59), hnsecs(9_999_999)));
7749
7750 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7751 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7752 assert(cst.endOfMonth == SysTime(DateTime(1999, 7, 31, 23, 59, 59), hnsecs(9_999_999)));
7753 assert(ist.endOfMonth == SysTime(DateTime(1999, 7, 31, 23, 59, 59), hnsecs(9_999_999)));
7754
7755 static void testScope(scope ref SysTime st) @safe
7756 {
7757 auto result = st.endOfMonth;
7758 }
7759 }
7760
7761
7762 /++
7763 The last day in the month that this $(LREF SysTime) is in.
7764 +/
7765 @property ubyte daysInMonth() @safe const nothrow scope
7766 {
7767 return Date(dayOfGregorianCal).daysInMonth;
7768 }
7769
7770 ///
7771 @safe unittest
7772 {
7773 import core.time;
7774 import std.datetime.date : DateTime;
7775
7776 assert(SysTime(DateTime(1999, 1, 6, 0, 0, 0)).daysInMonth == 31);
7777 assert(SysTime(DateTime(1999, 2, 7, 19, 30, 0)).daysInMonth == 28);
7778 assert(SysTime(DateTime(2000, 2, 7, 5, 12, 27)).daysInMonth == 29);
7779 assert(SysTime(DateTime(2000, 6, 4, 12, 22, 9)).daysInMonth == 30);
7780 }
7781
7782 @safe unittest
7783 {
7784 import core.time;
7785 // Test A.D.
7786 assert(SysTime(DateTime(1999, 1, 1, 12, 1, 13)).daysInMonth == 31);
7787 assert(SysTime(DateTime(1999, 2, 1, 17, 13, 12)).daysInMonth == 28);
7788 assert(SysTime(DateTime(2000, 2, 1, 13, 2, 12)).daysInMonth == 29);
7789 assert(SysTime(DateTime(1999, 3, 1, 12, 13, 12)).daysInMonth == 31);
7790 assert(SysTime(DateTime(1999, 4, 1, 12, 6, 13)).daysInMonth == 30);
7791 assert(SysTime(DateTime(1999, 5, 1, 15, 13, 12)).daysInMonth == 31);
7792 assert(SysTime(DateTime(1999, 6, 1, 13, 7, 12)).daysInMonth == 30);
7793 assert(SysTime(DateTime(1999, 7, 1, 12, 13, 17)).daysInMonth == 31);
7794 assert(SysTime(DateTime(1999, 8, 1, 12, 3, 13)).daysInMonth == 31);
7795 assert(SysTime(DateTime(1999, 9, 1, 12, 13, 12)).daysInMonth == 30);
7796 assert(SysTime(DateTime(1999, 10, 1, 13, 19, 12)).daysInMonth == 31);
7797 assert(SysTime(DateTime(1999, 11, 1, 12, 13, 17)).daysInMonth == 30);
7798 assert(SysTime(DateTime(1999, 12, 1, 12, 52, 13)).daysInMonth == 31);
7799
7800 // Test B.C.
7801 assert(SysTime(DateTime(-1999, 1, 1, 12, 1, 13)).daysInMonth == 31);
7802 assert(SysTime(DateTime(-1999, 2, 1, 7, 13, 12)).daysInMonth == 28);
7803 assert(SysTime(DateTime(-2000, 2, 1, 13, 2, 12)).daysInMonth == 29);
7804 assert(SysTime(DateTime(-1999, 3, 1, 12, 13, 12)).daysInMonth == 31);
7805 assert(SysTime(DateTime(-1999, 4, 1, 12, 6, 13)).daysInMonth == 30);
7806 assert(SysTime(DateTime(-1999, 5, 1, 5, 13, 12)).daysInMonth == 31);
7807 assert(SysTime(DateTime(-1999, 6, 1, 13, 7, 12)).daysInMonth == 30);
7808 assert(SysTime(DateTime(-1999, 7, 1, 12, 13, 17)).daysInMonth == 31);
7809 assert(SysTime(DateTime(-1999, 8, 1, 12, 3, 13)).daysInMonth == 31);
7810 assert(SysTime(DateTime(-1999, 9, 1, 12, 13, 12)).daysInMonth == 30);
7811 assert(SysTime(DateTime(-1999, 10, 1, 13, 19, 12)).daysInMonth == 31);
7812 assert(SysTime(DateTime(-1999, 11, 1, 12, 13, 17)).daysInMonth == 30);
7813 assert(SysTime(DateTime(-1999, 12, 1, 12, 52, 13)).daysInMonth == 31);
7814
7815 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7816 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7817 assert(cst.daysInMonth == 31);
7818 assert(ist.daysInMonth == 31);
7819
7820 static void testScope(scope ref SysTime st) @safe
7821 {
7822 auto result = st.daysInMonth;
7823 }
7824 }
7825
7826
7827 /++
7828 Whether the current year is a date in A.D.
7829 +/
7830 @property bool isAD() @safe const nothrow scope
7831 {
7832 return adjTime >= 0;
7833 }
7834
7835 ///
7836 @safe unittest
7837 {
7838 import core.time;
7839 import std.datetime.date : DateTime;
7840
7841 assert(SysTime(DateTime(1, 1, 1, 12, 7, 0)).isAD);
7842 assert(SysTime(DateTime(2010, 12, 31, 0, 0, 0)).isAD);
7843 assert(!SysTime(DateTime(0, 12, 31, 23, 59, 59)).isAD);
7844 assert(!SysTime(DateTime(-2010, 1, 1, 2, 2, 2)).isAD);
7845 }
7846
7847 @safe unittest
7848 {
7849 import core.time;
7850 assert(SysTime(DateTime(2010, 7, 4, 12, 0, 9)).isAD);
7851 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).isAD);
7852 assert(!SysTime(DateTime(0, 12, 31, 23, 59, 59)).isAD);
7853 assert(!SysTime(DateTime(0, 1, 1, 23, 59, 59)).isAD);
7854 assert(!SysTime(DateTime(-1, 1, 1, 23 ,59 ,59)).isAD);
7855 assert(!SysTime(DateTime(-2010, 7, 4, 12, 2, 2)).isAD);
7856
7857 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7858 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7859 assert(cst.isAD);
7860 assert(ist.isAD);
7861
7862 static void testScope(scope ref SysTime st) @safe
7863 {
7864 auto result = st.isAD;
7865 }
7866 }
7867
7868
7869 /++
7870 The $(HTTP en.wikipedia.org/wiki/Julian_day, Julian day)
7871 for this $(LREF SysTime) at the given time. For example,
7872 prior to noon, 1996-03-31 would be the Julian day number 2_450_173, so
7873 this function returns 2_450_173, while from noon onward, the Julian
7874 day number would be 2_450_174, so this function returns 2_450_174.
7875 +/
7876 @property long julianDay() @safe const nothrow scope
7877 {
7878 immutable jd = dayOfGregorianCal + 1_721_425;
7879 return hour < 12 ? jd - 1 : jd;
7880 }
7881
7882 @safe unittest
7883 {
7884 import core.time;
7885 assert(SysTime(DateTime(-4713, 11, 24, 0, 0, 0)).julianDay == -1);
7886 assert(SysTime(DateTime(-4713, 11, 24, 12, 0, 0)).julianDay == 0);
7887
7888 assert(SysTime(DateTime(0, 12, 31, 0, 0, 0)).julianDay == 1_721_424);
7889 assert(SysTime(DateTime(0, 12, 31, 12, 0, 0)).julianDay == 1_721_425);
7890
7891 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).julianDay == 1_721_425);
7892 assert(SysTime(DateTime(1, 1, 1, 12, 0, 0)).julianDay == 1_721_426);
7893
7894 assert(SysTime(DateTime(1582, 10, 15, 0, 0, 0)).julianDay == 2_299_160);
7895 assert(SysTime(DateTime(1582, 10, 15, 12, 0, 0)).julianDay == 2_299_161);
7896
7897 assert(SysTime(DateTime(1858, 11, 17, 0, 0, 0)).julianDay == 2_400_000);
7898 assert(SysTime(DateTime(1858, 11, 17, 12, 0, 0)).julianDay == 2_400_001);
7899
7900 assert(SysTime(DateTime(1982, 1, 4, 0, 0, 0)).julianDay == 2_444_973);
7901 assert(SysTime(DateTime(1982, 1, 4, 12, 0, 0)).julianDay == 2_444_974);
7902
7903 assert(SysTime(DateTime(1996, 3, 31, 0, 0, 0)).julianDay == 2_450_173);
7904 assert(SysTime(DateTime(1996, 3, 31, 12, 0, 0)).julianDay == 2_450_174);
7905
7906 assert(SysTime(DateTime(2010, 8, 24, 0, 0, 0)).julianDay == 2_455_432);
7907 assert(SysTime(DateTime(2010, 8, 24, 12, 0, 0)).julianDay == 2_455_433);
7908
7909 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7910 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7911 assert(cst.julianDay == 2_451_366);
7912 assert(ist.julianDay == 2_451_366);
7913
7914 static void testScope(scope ref SysTime st) @safe
7915 {
7916 auto result = st.julianDay;
7917 }
7918 }
7919
7920
7921 /++
7922 The modified $(HTTP en.wikipedia.org/wiki/Julian_day, Julian day) for
7923 any time on this date (since, the modified Julian day changes at
7924 midnight).
7925 +/
7926 @property long modJulianDay() @safe const nothrow scope
7927 {
7928 return dayOfGregorianCal + 1_721_425 - 2_400_001;
7929 }
7930
7931 @safe unittest
7932 {
7933 import core.time;
7934 assert(SysTime(DateTime(1858, 11, 17, 0, 0, 0)).modJulianDay == 0);
7935 assert(SysTime(DateTime(1858, 11, 17, 12, 0, 0)).modJulianDay == 0);
7936
7937 assert(SysTime(DateTime(2010, 8, 24, 0, 0, 0)).modJulianDay == 55_432);
7938 assert(SysTime(DateTime(2010, 8, 24, 12, 0, 0)).modJulianDay == 55_432);
7939
7940 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7941 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7942 assert(cst.modJulianDay == 51_365);
7943 assert(ist.modJulianDay == 51_365);
7944
7945 static void testScope(scope ref SysTime st) @safe
7946 {
7947 auto result = st.modJulianDay;
7948 }
7949 }
7950
7951
7952 /++
7953 Returns a $(REF Date,std,datetime,date) equivalent to this $(LREF SysTime).
7954 +/
7955 Date opCast(T)() @safe const nothrow scope
7956 if (is(immutable T == immutable Date))
7957 {
7958 return Date(dayOfGregorianCal);
7959 }
7960
7961 @safe unittest
7962 {
7963 import core.time;
7964 assert(cast(Date) SysTime(Date(1999, 7, 6)) == Date(1999, 7, 6));
7965 assert(cast(Date) SysTime(Date(2000, 12, 31)) == Date(2000, 12, 31));
7966 assert(cast(Date) SysTime(Date(2001, 1, 1)) == Date(2001, 1, 1));
7967
7968 assert(cast(Date) SysTime(DateTime(1999, 7, 6, 12, 10, 9)) == Date(1999, 7, 6));
7969 assert(cast(Date) SysTime(DateTime(2000, 12, 31, 13, 11, 10)) == Date(2000, 12, 31));
7970 assert(cast(Date) SysTime(DateTime(2001, 1, 1, 14, 12, 11)) == Date(2001, 1, 1));
7971
7972 assert(cast(Date) SysTime(Date(-1999, 7, 6)) == Date(-1999, 7, 6));
7973 assert(cast(Date) SysTime(Date(-2000, 12, 31)) == Date(-2000, 12, 31));
7974 assert(cast(Date) SysTime(Date(-2001, 1, 1)) == Date(-2001, 1, 1));
7975
7976 assert(cast(Date) SysTime(DateTime(-1999, 7, 6, 12, 10, 9)) == Date(-1999, 7, 6));
7977 assert(cast(Date) SysTime(DateTime(-2000, 12, 31, 13, 11, 10)) == Date(-2000, 12, 31));
7978 assert(cast(Date) SysTime(DateTime(-2001, 1, 1, 14, 12, 11)) == Date(-2001, 1, 1));
7979
7980 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7981 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
7982 assert(cast(Date) cst != Date.init);
7983 assert(cast(Date) ist != Date.init);
7984
7985 static void testScope(scope ref SysTime st) @safe
7986 {
7987 auto result = cast(Date) st;
7988 }
7989 }
7990
7991
7992 /++
7993 Returns a $(REF DateTime,std,datetime,date) equivalent to this
7994 $(LREF SysTime).
7995 +/
7996 DateTime opCast(T)() @safe const nothrow scope
7997 if (is(immutable T == immutable DateTime))
7998 {
7999 try
8000 {
8001 auto hnsecs = adjTime;
8002 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
8003
8004 if (hnsecs < 0)
8005 {
8006 hnsecs += convert!("hours", "hnsecs")(24);
8007 --days;
8008 }
8009
8010 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
8011 immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
8012 immutable second = getUnitsFromHNSecs!"seconds"(hnsecs);
8013
8014 return DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour, cast(int) minute, cast(int) second));
8015 }
8016 catch (Exception e)
8017 assert(0, "Either DateTime's constructor or TimeOfDay's constructor threw.");
8018 }
8019
8020 @safe unittest
8021 {
8022 import core.time;
8023 assert(cast(DateTime) SysTime(DateTime(1, 1, 6, 7, 12, 22)) == DateTime(1, 1, 6, 7, 12, 22));
8024 assert(cast(DateTime) SysTime(DateTime(1, 1, 6, 7, 12, 22), msecs(22)) == DateTime(1, 1, 6, 7, 12, 22));
8025 assert(cast(DateTime) SysTime(Date(1999, 7, 6)) == DateTime(1999, 7, 6, 0, 0, 0));
8026 assert(cast(DateTime) SysTime(Date(2000, 12, 31)) == DateTime(2000, 12, 31, 0, 0, 0));
8027 assert(cast(DateTime) SysTime(Date(2001, 1, 1)) == DateTime(2001, 1, 1, 0, 0, 0));
8028
8029 assert(cast(DateTime) SysTime(DateTime(1999, 7, 6, 12, 10, 9)) == DateTime(1999, 7, 6, 12, 10, 9));
8030 assert(cast(DateTime) SysTime(DateTime(2000, 12, 31, 13, 11, 10)) == DateTime(2000, 12, 31, 13, 11, 10));
8031 assert(cast(DateTime) SysTime(DateTime(2001, 1, 1, 14, 12, 11)) == DateTime(2001, 1, 1, 14, 12, 11));
8032
8033 assert(cast(DateTime) SysTime(DateTime(-1, 1, 6, 7, 12, 22)) == DateTime(-1, 1, 6, 7, 12, 22));
8034 assert(cast(DateTime) SysTime(DateTime(-1, 1, 6, 7, 12, 22), msecs(22)) == DateTime(-1, 1, 6, 7, 12, 22));
8035 assert(cast(DateTime) SysTime(Date(-1999, 7, 6)) == DateTime(-1999, 7, 6, 0, 0, 0));
8036 assert(cast(DateTime) SysTime(Date(-2000, 12, 31)) == DateTime(-2000, 12, 31, 0, 0, 0));
8037 assert(cast(DateTime) SysTime(Date(-2001, 1, 1)) == DateTime(-2001, 1, 1, 0, 0, 0));
8038
8039 assert(cast(DateTime) SysTime(DateTime(-1999, 7, 6, 12, 10, 9)) == DateTime(-1999, 7, 6, 12, 10, 9));
8040 assert(cast(DateTime) SysTime(DateTime(-2000, 12, 31, 13, 11, 10)) == DateTime(-2000, 12, 31, 13, 11, 10));
8041 assert(cast(DateTime) SysTime(DateTime(-2001, 1, 1, 14, 12, 11)) == DateTime(-2001, 1, 1, 14, 12, 11));
8042
8043 assert(cast(DateTime) SysTime(DateTime(2011, 1, 13, 8, 17, 2), msecs(296), LocalTime()) ==
8044 DateTime(2011, 1, 13, 8, 17, 2));
8045
8046 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8047 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8048 assert(cast(DateTime) cst != DateTime.init);
8049 assert(cast(DateTime) ist != DateTime.init);
8050
8051 static void testScope(scope ref SysTime st) @safe
8052 {
8053 auto result = cast(DateTime) st;
8054 }
8055 }
8056
8057
8058 /++
8059 Returns a $(REF TimeOfDay,std,datetime,date) equivalent to this
8060 $(LREF SysTime).
8061 +/
8062 TimeOfDay opCast(T)() @safe const nothrow scope
8063 if (is(immutable T == immutable TimeOfDay))
8064 {
8065 try
8066 {
8067 auto hnsecs = adjTime;
8068 hnsecs = removeUnitsFromHNSecs!"days"(hnsecs);
8069
8070 if (hnsecs < 0)
8071 hnsecs += convert!("hours", "hnsecs")(24);
8072
8073 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
8074 immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
8075 immutable second = getUnitsFromHNSecs!"seconds"(hnsecs);
8076
8077 return TimeOfDay(cast(int) hour, cast(int) minute, cast(int) second);
8078 }
8079 catch (Exception e)
8080 assert(0, "TimeOfDay's constructor threw.");
8081 }
8082
8083 @safe unittest
8084 {
8085 import core.time;
8086 assert(cast(TimeOfDay) SysTime(Date(1999, 7, 6)) == TimeOfDay(0, 0, 0));
8087 assert(cast(TimeOfDay) SysTime(Date(2000, 12, 31)) == TimeOfDay(0, 0, 0));
8088 assert(cast(TimeOfDay) SysTime(Date(2001, 1, 1)) == TimeOfDay(0, 0, 0));
8089
8090 assert(cast(TimeOfDay) SysTime(DateTime(1999, 7, 6, 12, 10, 9)) == TimeOfDay(12, 10, 9));
8091 assert(cast(TimeOfDay) SysTime(DateTime(2000, 12, 31, 13, 11, 10)) == TimeOfDay(13, 11, 10));
8092 assert(cast(TimeOfDay) SysTime(DateTime(2001, 1, 1, 14, 12, 11)) == TimeOfDay(14, 12, 11));
8093
8094 assert(cast(TimeOfDay) SysTime(Date(-1999, 7, 6)) == TimeOfDay(0, 0, 0));
8095 assert(cast(TimeOfDay) SysTime(Date(-2000, 12, 31)) == TimeOfDay(0, 0, 0));
8096 assert(cast(TimeOfDay) SysTime(Date(-2001, 1, 1)) == TimeOfDay(0, 0, 0));
8097
8098 assert(cast(TimeOfDay) SysTime(DateTime(-1999, 7, 6, 12, 10, 9)) == TimeOfDay(12, 10, 9));
8099 assert(cast(TimeOfDay) SysTime(DateTime(-2000, 12, 31, 13, 11, 10)) == TimeOfDay(13, 11, 10));
8100 assert(cast(TimeOfDay) SysTime(DateTime(-2001, 1, 1, 14, 12, 11)) == TimeOfDay(14, 12, 11));
8101
8102 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8103 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8104 assert(cast(TimeOfDay) cst != TimeOfDay.init);
8105 assert(cast(TimeOfDay) ist != TimeOfDay.init);
8106
8107 static void testScope(scope ref SysTime st) @safe
8108 {
8109 auto result = cast(TimeOfDay) st;
8110 }
8111 }
8112
8113
8114 // Temporary hack until bug https://issues.dlang.org/show_bug.cgi?id=4867 is fixed.
8115 // This allows assignment from const(SysTime) to SysTime.
8116 // It may be a good idea to keep it though, since casting from a type to itself
8117 // should be allowed, and it doesn't work without this opCast() since opCast()
8118 // has already been defined for other types.
8119 SysTime opCast(T)() @safe const pure nothrow scope
8120 if (is(immutable T == immutable SysTime))
8121 {
8122 return SysTime(_stdTime, _timezone);
8123 }
8124
8125 @safe unittest
8126 {
8127 static void testScope(scope ref SysTime st) @safe
8128 {
8129 auto result = cast(SysTime) st;
8130 }
8131 }
8132
8133
8134 /++
8135 Converts this $(LREF SysTime) to a string with the format
8136 YYYYMMDDTHHMMSS.FFFFFFFTZ (where F is fractional seconds and TZ is time
8137 zone).
8138
8139 Note that the number of digits in the fractional seconds varies with the
8140 number of fractional seconds. It's a maximum of 7 (which would be
8141 hnsecs), but only has as many as are necessary to hold the correct value
8142 (so no trailing zeroes), and if there are no fractional seconds, then
8143 there is no decimal point.
8144
8145 If this $(LREF SysTime)'s time zone is
8146 $(REF LocalTime,std,datetime,timezone), then TZ is empty. If its time
8147 zone is `UTC`, then it is "Z". Otherwise, it is the offset from UTC
8148 (e.g. +0100 or -0700). Note that the offset from UTC is $(I not) enough
8149 to uniquely identify the time zone.
8150
8151 Time zone offsets will be in the form +HHMM or -HHMM.
8152
8153 $(RED Warning:
8154 Previously, toISOString did the same as $(LREF toISOExtString) and
8155 generated +HH:MM or -HH:MM for the time zone when it was not
8156 $(REF LocalTime,std,datetime,timezone) or
8157 $(REF UTC,std,datetime,timezone), which is not in conformance with
8158 ISO 8601 for the non-extended string format. This has now been
8159 fixed. However, for now, fromISOString will continue to accept the
8160 extended format for the time zone so that any code which has been
8161 writing out the result of toISOString to read in later will continue
8162 to work. The current behavior will be kept until July 2019 at which
8163 point, fromISOString will be fixed to be standards compliant.)
8164
8165 Params:
8166 writer = A `char` accepting
8167 $(REF_ALTTEXT output range, isOutputRange, std, range, primitives)
8168 Returns:
8169 A `string` when not using an output range; `void` otherwise.
8170 +/
8171 string toISOString() @safe const nothrow scope
8172 {
8173 import std.array : appender;
8174 auto app = appender!string();
8175 app.reserve(30);
8176 try
8177 toISOString(app);
8178 catch (Exception e)
8179 assert(0, "toISOString() threw.");
8180 return app.data;
8181 }
8182
8183 /// ditto
8184 void toISOString(W)(ref W writer) const scope
8185 if (isOutputRange!(W, char))
8186 {
8187 immutable adjustedTime = adjTime;
8188 long hnsecs = adjustedTime;
8189
8190 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
8191
8192 if (hnsecs < 0)
8193 {
8194 hnsecs += convert!("hours", "hnsecs")(24);
8195 --days;
8196 }
8197
8198 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
8199 immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
8200 immutable second = splitUnitsFromHNSecs!"seconds"(hnsecs);
8201
8202 auto dateTime = DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour,
8203 cast(int) minute, cast(int) second));
8204
8205 if (_timezone is LocalTime())
8206 {
8207 dateTime.toISOString(writer);
8208 fracSecsToISOString(writer, cast(int) hnsecs);
8209 return;
8210 }
8211
8212 if (_timezone is UTC())
8213 {
8214 dateTime.toISOString(writer);
8215 fracSecsToISOString(writer, cast(int) hnsecs);
8216 put(writer, 'Z');
8217 return;
8218 }
8219
8220 immutable utcOffset = dur!"hnsecs"(adjustedTime - stdTime);
8221
8222 dateTime.toISOString(writer);
8223 fracSecsToISOString(writer, cast(int) hnsecs);
8224 SimpleTimeZone.toISOExtString(writer, utcOffset);
8225 }
8226
8227 ///
8228 @safe unittest
8229 {
8230 import core.time : msecs, hnsecs;
8231 import std.datetime.date : DateTime;
8232
8233 assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toISOString() ==
8234 "20100704T070612");
8235
8236 assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(24)).toISOString() ==
8237 "19981225T021500.024");
8238
8239 assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toISOString() ==
8240 "00000105T230959");
8241
8242 assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toISOString() ==
8243 "-00040105T000002.052092");
8244 }
8245
8246 @safe unittest
8247 {
8248 import core.time;
8249 // Test A.D.
8250 assert(SysTime(DateTime.init, UTC()).toISOString() == "00010101T000000Z");
8251 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1), UTC()).toISOString() == "00010101T000000.0000001Z");
8252
8253 assert(SysTime(DateTime(9, 12, 4, 0, 0, 0)).toISOString() == "00091204T000000");
8254 assert(SysTime(DateTime(99, 12, 4, 5, 6, 12)).toISOString() == "00991204T050612");
8255 assert(SysTime(DateTime(999, 12, 4, 13, 44, 59)).toISOString() == "09991204T134459");
8256 assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59)).toISOString() == "99990704T235959");
8257 assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1)).toISOString() == "+100001020T010101");
8258
8259 assert(SysTime(DateTime(9, 12, 4, 0, 0, 0), msecs(42)).toISOString() == "00091204T000000.042");
8260 assert(SysTime(DateTime(99, 12, 4, 5, 6, 12), msecs(100)).toISOString() == "00991204T050612.1");
8261 assert(SysTime(DateTime(999, 12, 4, 13, 44, 59), usecs(45020)).toISOString() == "09991204T134459.04502");
8262 assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59), hnsecs(12)).toISOString() == "99990704T235959.0000012");
8263 assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1), hnsecs(507890)).toISOString() == "+100001020T010101.050789");
8264
8265 assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
8266 new immutable SimpleTimeZone(dur!"minutes"(-360))).toISOString() ==
8267 "20121221T121212-06:00");
8268
8269 assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
8270 new immutable SimpleTimeZone(dur!"minutes"(420))).toISOString() ==
8271 "20121221T121212+07:00");
8272
8273 // Test B.C.
8274 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toISOString() ==
8275 "00001231T235959.9999999Z");
8276 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1), UTC()).toISOString() == "00001231T235959.0000001Z");
8277 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), UTC()).toISOString() == "00001231T235959Z");
8278
8279 assert(SysTime(DateTime(0, 12, 4, 0, 12, 4)).toISOString() == "00001204T001204");
8280 assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0)).toISOString() == "-00091204T000000");
8281 assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12)).toISOString() == "-00991204T050612");
8282 assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59)).toISOString() == "-09991204T134459");
8283 assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59)).toISOString() == "-99990704T235959");
8284 assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1)).toISOString() == "-100001020T010101");
8285
8286 assert(SysTime(DateTime(0, 12, 4, 0, 0, 0), msecs(7)).toISOString() == "00001204T000000.007");
8287 assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0), msecs(42)).toISOString() == "-00091204T000000.042");
8288 assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12), msecs(100)).toISOString() == "-00991204T050612.1");
8289 assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59), usecs(45020)).toISOString() == "-09991204T134459.04502");
8290 assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59), hnsecs(12)).toISOString() == "-99990704T235959.0000012");
8291 assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1), hnsecs(507890)).toISOString() == "-100001020T010101.050789");
8292
8293 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8294 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8295 assert(cst.toISOString() == "19990706T123033");
8296 assert(ist.toISOString() == "19990706T123033");
8297
8298 static void testScope(scope ref SysTime st) @safe
8299 {
8300 auto result = st.toISOString();
8301 }
8302 }
8303
8304
8305
8306 /++
8307 Converts this $(LREF SysTime) to a string with the format
8308 YYYY-MM-DDTHH:MM:SS.FFFFFFFTZ (where F is fractional seconds and TZ
8309 is the time zone).
8310
8311 Note that the number of digits in the fractional seconds varies with the
8312 number of fractional seconds. It's a maximum of 7 (which would be
8313 hnsecs), but only has as many as are necessary to hold the correct value
8314 (so no trailing zeroes), and if there are no fractional seconds, then
8315 there is no decimal point.
8316
8317 If this $(LREF SysTime)'s time zone is
8318 $(REF LocalTime,std,datetime,timezone), then TZ is empty. If its time
8319 zone is `UTC`, then it is "Z". Otherwise, it is the offset from UTC
8320 (e.g. +01:00 or -07:00). Note that the offset from UTC is $(I not)
8321 enough to uniquely identify the time zone.
8322
8323 Time zone offsets will be in the form +HH:MM or -HH:MM.
8324
8325 Params:
8326 writer = A `char` accepting
8327 $(REF_ALTTEXT output range, isOutputRange, std, range, primitives)
8328 Returns:
8329 A `string` when not using an output range; `void` otherwise.
8330 +/
8331 string toISOExtString() @safe const nothrow scope
8332 {
8333 import std.array : appender;
8334 auto app = appender!string();
8335 app.reserve(35);
8336 try
8337 toISOExtString(app);
8338 catch (Exception e)
8339 assert(0, "toISOExtString() threw.");
8340 return app.data;
8341 }
8342
8343 /// ditto
8344 void toISOExtString(W)(ref W writer) const scope
8345 if (isOutputRange!(W, char))
8346 {
8347 immutable adjustedTime = adjTime;
8348 long hnsecs = adjustedTime;
8349
8350 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
8351
8352 if (hnsecs < 0)
8353 {
8354 hnsecs += convert!("hours", "hnsecs")(24);
8355 --days;
8356 }
8357
8358 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
8359 immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
8360 immutable second = splitUnitsFromHNSecs!"seconds"(hnsecs);
8361
8362 immutable dateTime = DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour,
8363 cast(int) minute, cast(int) second));
8364
8365 if (_timezone is LocalTime())
8366 {
8367 dateTime.toISOExtString(writer);
8368 fracSecsToISOString(writer, cast(int) hnsecs);
8369 return;
8370 }
8371
8372 if (_timezone is UTC())
8373 {
8374 dateTime.toISOExtString(writer);
8375 fracSecsToISOString(writer, cast(int) hnsecs);
8376 put(writer, 'Z');
8377 return;
8378 }
8379
8380 immutable utcOffset = dur!"hnsecs"(adjustedTime - stdTime);
8381
8382 dateTime.toISOExtString(writer);
8383 fracSecsToISOString(writer, cast(int) hnsecs);
8384 SimpleTimeZone.toISOExtString(writer, utcOffset);
8385 }
8386
8387 ///
8388 @safe unittest
8389 {
8390 import core.time : msecs, hnsecs;
8391 import std.datetime.date : DateTime;
8392
8393 assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toISOExtString() ==
8394 "2010-07-04T07:06:12");
8395
8396 assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(24)).toISOExtString() ==
8397 "1998-12-25T02:15:00.024");
8398
8399 assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toISOExtString() ==
8400 "0000-01-05T23:09:59");
8401
8402 assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toISOExtString() ==
8403 "-0004-01-05T00:00:02.052092");
8404 }
8405
8406 @safe unittest
8407 {
8408 import core.time;
8409 // Test A.D.
8410 assert(SysTime(DateTime.init, UTC()).toISOExtString() == "0001-01-01T00:00:00Z");
8411 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1), UTC()).toISOExtString() ==
8412 "0001-01-01T00:00:00.0000001Z");
8413
8414 assert(SysTime(DateTime(9, 12, 4, 0, 0, 0)).toISOExtString() == "0009-12-04T00:00:00");
8415 assert(SysTime(DateTime(99, 12, 4, 5, 6, 12)).toISOExtString() == "0099-12-04T05:06:12");
8416 assert(SysTime(DateTime(999, 12, 4, 13, 44, 59)).toISOExtString() == "0999-12-04T13:44:59");
8417 assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59)).toISOExtString() == "9999-07-04T23:59:59");
8418 assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1)).toISOExtString() == "+10000-10-20T01:01:01");
8419
8420 assert(SysTime(DateTime(9, 12, 4, 0, 0, 0), msecs(42)).toISOExtString() == "0009-12-04T00:00:00.042");
8421 assert(SysTime(DateTime(99, 12, 4, 5, 6, 12), msecs(100)).toISOExtString() == "0099-12-04T05:06:12.1");
8422 assert(SysTime(DateTime(999, 12, 4, 13, 44, 59), usecs(45020)).toISOExtString() == "0999-12-04T13:44:59.04502");
8423 assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59), hnsecs(12)).toISOExtString() == "9999-07-04T23:59:59.0000012");
8424 assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1), hnsecs(507890)).toISOExtString() ==
8425 "+10000-10-20T01:01:01.050789");
8426
8427 assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
8428 new immutable SimpleTimeZone(dur!"minutes"(-360))).toISOExtString() ==
8429 "2012-12-21T12:12:12-06:00");
8430
8431 assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
8432 new immutable SimpleTimeZone(dur!"minutes"(420))).toISOExtString() ==
8433 "2012-12-21T12:12:12+07:00");
8434
8435 // Test B.C.
8436 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toISOExtString() ==
8437 "0000-12-31T23:59:59.9999999Z");
8438 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1), UTC()).toISOExtString() ==
8439 "0000-12-31T23:59:59.0000001Z");
8440 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), UTC()).toISOExtString() == "0000-12-31T23:59:59Z");
8441
8442 assert(SysTime(DateTime(0, 12, 4, 0, 12, 4)).toISOExtString() == "0000-12-04T00:12:04");
8443 assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0)).toISOExtString() == "-0009-12-04T00:00:00");
8444 assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12)).toISOExtString() == "-0099-12-04T05:06:12");
8445 assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59)).toISOExtString() == "-0999-12-04T13:44:59");
8446 assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59)).toISOExtString() == "-9999-07-04T23:59:59");
8447 assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1)).toISOExtString() == "-10000-10-20T01:01:01");
8448
8449 assert(SysTime(DateTime(0, 12, 4, 0, 0, 0), msecs(7)).toISOExtString() == "0000-12-04T00:00:00.007");
8450 assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0), msecs(42)).toISOExtString() == "-0009-12-04T00:00:00.042");
8451 assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12), msecs(100)).toISOExtString() == "-0099-12-04T05:06:12.1");
8452 assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59), usecs(45020)).toISOExtString() ==
8453 "-0999-12-04T13:44:59.04502");
8454 assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59), hnsecs(12)).toISOExtString() ==
8455 "-9999-07-04T23:59:59.0000012");
8456 assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1), hnsecs(507890)).toISOExtString() ==
8457 "-10000-10-20T01:01:01.050789");
8458
8459 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8460 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8461 assert(cst.toISOExtString() == "1999-07-06T12:30:33");
8462 assert(ist.toISOExtString() == "1999-07-06T12:30:33");
8463
8464 static void testScope(scope ref SysTime st) @safe
8465 {
8466 auto result = st.toISOExtString();
8467 }
8468 }
8469
8470 /++
8471 Converts this $(LREF SysTime) to a string with the format
8472 YYYY-Mon-DD HH:MM:SS.FFFFFFFTZ (where F is fractional seconds and TZ
8473 is the time zone).
8474
8475 Note that the number of digits in the fractional seconds varies with the
8476 number of fractional seconds. It's a maximum of 7 (which would be
8477 hnsecs), but only has as many as are necessary to hold the correct value
8478 (so no trailing zeroes), and if there are no fractional seconds, then
8479 there is no decimal point.
8480
8481 If this $(LREF SysTime)'s time zone is
8482 $(REF LocalTime,std,datetime,timezone), then TZ is empty. If its time
8483 zone is `UTC`, then it is "Z". Otherwise, it is the offset from UTC
8484 (e.g. +01:00 or -07:00). Note that the offset from UTC is $(I not)
8485 enough to uniquely identify the time zone.
8486
8487 Time zone offsets will be in the form +HH:MM or -HH:MM.
8488
8489 Params:
8490 writer = A `char` accepting
8491 $(REF_ALTTEXT output range, isOutputRange, std, range, primitives)
8492 Returns:
8493 A `string` when not using an output range; `void` otherwise.
8494 +/
8495 string toSimpleString() @safe const nothrow scope
8496 {
8497 import std.array : appender;
8498 auto app = appender!string();
8499 app.reserve(35);
8500 try
8501 toSimpleString(app);
8502 catch (Exception e)
8503 assert(0, "toSimpleString() threw.");
8504 return app.data;
8505 }
8506
8507 /// ditto
8508 void toSimpleString(W)(ref W writer) const scope
8509 if (isOutputRange!(W, char))
8510 {
8511 immutable adjustedTime = adjTime;
8512 long hnsecs = adjustedTime;
8513
8514 auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
8515
8516 if (hnsecs < 0)
8517 {
8518 hnsecs += convert!("hours", "hnsecs")(24);
8519 --days;
8520 }
8521
8522 immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
8523 immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
8524 immutable second = splitUnitsFromHNSecs!"seconds"(hnsecs);
8525
8526 immutable dateTime = DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour,
8527 cast(int) minute, cast(int) second));
8528
8529 if (_timezone is LocalTime())
8530 {
8531 dateTime.toSimpleString(writer);
8532 fracSecsToISOString(writer, cast(int) hnsecs);
8533 return;
8534 }
8535
8536 if (_timezone is UTC())
8537 {
8538 dateTime.toSimpleString(writer);
8539 fracSecsToISOString(writer, cast(int) hnsecs);
8540 put(writer, 'Z');
8541 return;
8542 }
8543
8544 immutable utcOffset = dur!"hnsecs"(adjustedTime - stdTime);
8545
8546 dateTime.toSimpleString(writer);
8547 fracSecsToISOString(writer, cast(int) hnsecs);
8548 SimpleTimeZone.toISOExtString(writer, utcOffset);
8549 }
8550
8551 ///
8552 @safe unittest
8553 {
8554 import core.time : msecs, hnsecs;
8555 import std.datetime.date : DateTime;
8556
8557 assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toSimpleString() ==
8558 "2010-Jul-04 07:06:12");
8559
8560 assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(24)).toSimpleString() ==
8561 "1998-Dec-25 02:15:00.024");
8562
8563 assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toSimpleString() ==
8564 "0000-Jan-05 23:09:59");
8565
8566 assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toSimpleString() ==
8567 "-0004-Jan-05 00:00:02.052092");
8568 }
8569
8570 @safe unittest
8571 {
8572 import core.time;
8573 // Test A.D.
8574 assert(SysTime(DateTime.init, UTC()).toString() == "0001-Jan-01 00:00:00Z");
8575 assert(SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1), UTC()).toString() == "0001-Jan-01 00:00:00.0000001Z");
8576
8577 assert(SysTime(DateTime(9, 12, 4, 0, 0, 0)).toSimpleString() == "0009-Dec-04 00:00:00");
8578 assert(SysTime(DateTime(99, 12, 4, 5, 6, 12)).toSimpleString() == "0099-Dec-04 05:06:12");
8579 assert(SysTime(DateTime(999, 12, 4, 13, 44, 59)).toSimpleString() == "0999-Dec-04 13:44:59");
8580 assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59)).toSimpleString() == "9999-Jul-04 23:59:59");
8581 assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1)).toSimpleString() == "+10000-Oct-20 01:01:01");
8582
8583 assert(SysTime(DateTime(9, 12, 4, 0, 0, 0), msecs(42)).toSimpleString() == "0009-Dec-04 00:00:00.042");
8584 assert(SysTime(DateTime(99, 12, 4, 5, 6, 12), msecs(100)).toSimpleString() == "0099-Dec-04 05:06:12.1");
8585 assert(SysTime(DateTime(999, 12, 4, 13, 44, 59), usecs(45020)).toSimpleString() ==
8586 "0999-Dec-04 13:44:59.04502");
8587 assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59), hnsecs(12)).toSimpleString() ==
8588 "9999-Jul-04 23:59:59.0000012");
8589 assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1), hnsecs(507890)).toSimpleString() ==
8590 "+10000-Oct-20 01:01:01.050789");
8591
8592 assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
8593 new immutable SimpleTimeZone(dur!"minutes"(-360))).toSimpleString() ==
8594 "2012-Dec-21 12:12:12-06:00");
8595
8596 assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12),
8597 new immutable SimpleTimeZone(dur!"minutes"(420))).toSimpleString() ==
8598 "2012-Dec-21 12:12:12+07:00");
8599
8600 // Test B.C.
8601 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toSimpleString() ==
8602 "0000-Dec-31 23:59:59.9999999Z");
8603 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1), UTC()).toSimpleString() ==
8604 "0000-Dec-31 23:59:59.0000001Z");
8605 assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), UTC()).toSimpleString() == "0000-Dec-31 23:59:59Z");
8606
8607 assert(SysTime(DateTime(0, 12, 4, 0, 12, 4)).toSimpleString() == "0000-Dec-04 00:12:04");
8608 assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0)).toSimpleString() == "-0009-Dec-04 00:00:00");
8609 assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12)).toSimpleString() == "-0099-Dec-04 05:06:12");
8610 assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59)).toSimpleString() == "-0999-Dec-04 13:44:59");
8611 assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59)).toSimpleString() == "-9999-Jul-04 23:59:59");
8612 assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1)).toSimpleString() == "-10000-Oct-20 01:01:01");
8613
8614 assert(SysTime(DateTime(0, 12, 4, 0, 0, 0), msecs(7)).toSimpleString() == "0000-Dec-04 00:00:00.007");
8615 assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0), msecs(42)).toSimpleString() == "-0009-Dec-04 00:00:00.042");
8616 assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12), msecs(100)).toSimpleString() == "-0099-Dec-04 05:06:12.1");
8617 assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59), usecs(45020)).toSimpleString() ==
8618 "-0999-Dec-04 13:44:59.04502");
8619 assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59), hnsecs(12)).toSimpleString() ==
8620 "-9999-Jul-04 23:59:59.0000012");
8621 assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1), hnsecs(507890)).toSimpleString() ==
8622 "-10000-Oct-20 01:01:01.050789");
8623
8624 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8625 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8626 assert(cst.toSimpleString() == "1999-Jul-06 12:30:33");
8627 assert(ist.toSimpleString() == "1999-Jul-06 12:30:33");
8628
8629 static void testScope(scope ref SysTime st) @safe
8630 {
8631 auto result = st.toSimpleString();
8632 }
8633 }
8634
8635
8636 /++
8637 Converts this $(LREF SysTime) to a string.
8638
8639 This function exists to make it easy to convert a $(LREF SysTime) to a
8640 string for code that does not care what the exact format is - just that
8641 it presents the information in a clear manner. It also makes it easy to
8642 simply convert a $(LREF SysTime) to a string when using functions such
8643 as `to!string`, `format`, or `writeln` which use toString to convert
8644 user-defined types. So, it is unlikely that much code will call
8645 toString directly.
8646
8647 The format of the string is purposefully unspecified, and code that
8648 cares about the format of the string should use `toISOString`,
8649 `toISOExtString`, `toSimpleString`, or some other custom formatting
8650 function that explicitly generates the format that the code needs. The
8651 reason is that the code is then clear about what format it's using,
8652 making it less error-prone to maintain the code and interact with other
8653 software that consumes the generated strings. It's for this same reason
8654 that $(LREF SysTime) has no `fromString` function, whereas it does have
8655 `fromISOString`, `fromISOExtString`, and `fromSimpleString`.
8656
8657 The format returned by toString may or may not change in the future.
8658
8659 Params:
8660 writer = A `char` accepting
8661 $(REF_ALTTEXT output range, isOutputRange, std, range, primitives)
8662 Returns:
8663 A `string` when not using an output range; `void` otherwise.
8664 +/
8665 string toString() @safe const nothrow scope
8666 {
8667 return toSimpleString();
8668 }
8669
8670 /// ditto
8671 void toString(W)(ref W writer) const scope
8672 if (isOutputRange!(W, char))
8673 {
8674 toSimpleString(writer);
8675 }
8676
8677 @safe unittest
8678 {
8679 import core.time;
8680 auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8681 const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8682 immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
8683 static assert(__traits(compiles, st.toString()));
8684 static assert(__traits(compiles, cst.toString()));
8685 static assert(__traits(compiles, ist.toString()));
8686
8687 static void testScope(scope ref SysTime st) @safe
8688 {
8689 auto result = st.toString();
8690 }
8691 }
8692
8693
8694 /++
8695 Creates a $(LREF SysTime) from a string with the format
8696 YYYYMMDDTHHMMSS.FFFFFFFTZ (where F is fractional seconds is the time
8697 zone). Whitespace is stripped from the given string.
8698
8699 The exact format is exactly as described in `toISOString` except that
8700 trailing zeroes are permitted - including having fractional seconds with
8701 all zeroes. However, a decimal point with nothing following it is
8702 invalid. Also, while $(LREF toISOString) will never generate a string
8703 with more than 7 digits in the fractional seconds (because that's the
8704 limit with hecto-nanosecond precision), it will allow more than 7 digits
8705 in order to read strings from other sources that have higher precision
8706 (however, any digits beyond 7 will be truncated).
8707
8708 If there is no time zone in the string, then
8709 $(REF LocalTime,std,datetime,timezone) is used. If the time zone is "Z",
8710 then `UTC` is used. Otherwise, a
8711 $(REF SimpleTimeZone,std,datetime,timezone) which corresponds to the
8712 given offset from UTC is used. To get the returned $(LREF SysTime) to be
8713 a particular time zone, pass in that time zone and the $(LREF SysTime)
8714 to be returned will be converted to that time zone (though it will still
8715 be read in as whatever time zone is in its string).
8716
8717 The accepted formats for time zone offsets are +HH, -HH, +HHMM, and
8718 -HHMM.
8719
8720 $(RED Warning:
8721 Previously, $(LREF toISOString) did the same as
8722 $(LREF toISOExtString) and generated +HH:MM or -HH:MM for the time
8723 zone when it was not $(REF LocalTime,std,datetime,timezone) or
8724 $(REF UTC,std,datetime,timezone), which is not in conformance with
8725 ISO 8601 for the non-extended string format. This has now been
8726 fixed. However, for now, fromISOString will continue to accept the
8727 extended format for the time zone so that any code which has been
8728 writing out the result of toISOString to read in later will continue
8729 to work. The current behavior will be kept until July 2019 at which
8730 point, fromISOString will be fixed to be standards compliant.)
8731
8732 Params:
8733 isoString = A string formatted in the ISO format for dates and times.
8734 tz = The time zone to convert the given time to (no
8735 conversion occurs if null).
8736
8737 Throws:
8738 $(REF DateTimeException,std,datetime,date) if the given string is
8739 not in the ISO format or if the resulting $(LREF SysTime) would not
8740 be valid.
8741 +/
8742 static SysTime fromISOString(S)(scope const S isoString, immutable TimeZone tz = null) @safe
8743 if (isSomeString!S)
8744 {
8745 import std.algorithm.searching : startsWith, find;
8746 import std.conv : to;
8747 import std.string : strip;
8748 import std.utf : byCodeUnit;
8749
8750 auto str = strip(isoString);
8751 immutable skipFirst = str.startsWith('+', '-');
8752
8753 auto found = (skipFirst ? str[1..$] : str).byCodeUnit.find('.', 'Z', '+', '-');
8754 auto dateTimeStr = str[0 .. $ - found[0].length];
8755
8756 typeof(str.byCodeUnit) foundTZ; // needs to have longer lifetime than zoneStr
8757 typeof(str) fracSecStr;
8758 typeof(str) zoneStr;
8759
8760 if (found[1] != 0)
8761 {
8762 if (found[1] == 1)
8763 {
8764 foundTZ = found[0].find('Z', '+', '-')[0];
8765
8766 if (foundTZ.length != 0)
8767 {
8768 static if (isNarrowString!S)
8769 {
8770 fracSecStr = found[0][0 .. $ - foundTZ.length].source;
8771 zoneStr = foundTZ.source;
8772 }
8773 else
8774 {
8775 fracSecStr = found[0][0 .. $ - foundTZ.length];
8776 zoneStr = foundTZ;
8777 }
8778 }
8779 else
8780 {
8781 static if (isNarrowString!S)
8782 fracSecStr = found[0].source;
8783 else
8784 fracSecStr = found[0];
8785 }
8786 }
8787 else
8788 {
8789 static if (isNarrowString!S)
8790 zoneStr = found[0].source;
8791 else
8792 zoneStr = found[0];
8793 }
8794 }
8795
8796 try
8797 {
8798 auto dateTime = DateTime.fromISOString(dateTimeStr);
8799 auto fracSec = fracSecsFromISOString(fracSecStr);
8800
8801 Rebindable!(immutable TimeZone) parsedZone;
8802
8803 if (zoneStr.empty)
8804 parsedZone = LocalTime();
8805 else if (zoneStr == "Z")
8806 parsedZone = UTC();
8807 else
8808 {
8809 try
8810 parsedZone = SimpleTimeZone.fromISOString(zoneStr);
8811 catch (DateTimeException dte)
8812 parsedZone = SimpleTimeZone.fromISOExtString(zoneStr);
8813 }
8814
8815 auto retval = SysTime(dateTime, fracSec, parsedZone);
8816
8817 if (tz !is null)
8818 retval.timezone = tz;
8819
8820 return retval;
8821 }
8822 catch (DateTimeException dte)
8823 throw new DateTimeException(format("Invalid ISO String: %s", isoString));
8824 }
8825
8826 ///
8827 @safe unittest
8828 {
8829 import core.time : hours, msecs, usecs, hnsecs;
8830 import std.datetime.date : DateTime;
8831 import std.datetime.timezone : SimpleTimeZone, UTC;
8832
8833 assert(SysTime.fromISOString("20100704T070612") ==
8834 SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
8835
8836 assert(SysTime.fromISOString("19981225T021500.007") ==
8837 SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(7)));
8838
8839 assert(SysTime.fromISOString("00000105T230959.00002") ==
8840 SysTime(DateTime(0, 1, 5, 23, 9, 59), usecs(20)));
8841
8842 assert(SysTime.fromISOString("20130207T043937.000050392") ==
8843 SysTime(DateTime(2013, 2, 7, 4, 39, 37), hnsecs(503)));
8844
8845 assert(SysTime.fromISOString("-00040105T000002") ==
8846 SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
8847
8848 assert(SysTime.fromISOString(" 20100704T070612 ") ==
8849 SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
8850
8851 assert(SysTime.fromISOString("20100704T070612Z") ==
8852 SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
8853
8854 assert(SysTime.fromISOString("20100704T070612-0800") ==
8855 SysTime(DateTime(2010, 7, 4, 7, 6, 12),
8856 new immutable SimpleTimeZone(hours(-8))));
8857
8858 assert(SysTime.fromISOString("20100704T070612+0800") ==
8859 SysTime(DateTime(2010, 7, 4, 7, 6, 12),
8860 new immutable SimpleTimeZone(hours(8))));
8861 }
8862
8863 @safe unittest
8864 {
8865 import core.time;
8866 foreach (str; ["", "20100704000000", "20100704 000000", "20100704t000000",
8867 "20100704T000000.", "20100704T000000.A", "20100704T000000.Z",
8868 "20100704T000000.0000000A", "20100704T000000.00000000A",
8869 "20100704T000000+", "20100704T000000-", "20100704T000000:",
8870 "20100704T000000-:", "20100704T000000+:", "20100704T000000-1:",
8871 "20100704T000000+1:", "20100704T000000+1:0",
8872 "20100704T000000-12.00", "20100704T000000+12.00",
8873 "20100704T000000-8", "20100704T000000+8",
8874 "20100704T000000-800", "20100704T000000+800",
8875 "20100704T000000-080", "20100704T000000+080",
8876 "20100704T000000-2400", "20100704T000000+2400",
8877 "20100704T000000-1260", "20100704T000000+1260",
8878 "20100704T000000.0-8", "20100704T000000.0+8",
8879 "20100704T000000.0-800", "20100704T000000.0+800",
8880 "20100704T000000.0-080", "20100704T000000.0+080",
8881 "20100704T000000.0-2400", "20100704T000000.0+2400",
8882 "20100704T000000.0-1260", "20100704T000000.0+1260",
8883 "20100704T000000-8:00", "20100704T000000+8:00",
8884 "20100704T000000-08:0", "20100704T000000+08:0",
8885 "20100704T000000-24:00", "20100704T000000+24:00",
8886 "20100704T000000-12:60", "20100704T000000+12:60",
8887 "20100704T000000.0-8:00", "20100704T000000.0+8:00",
8888 "20100704T000000.0-08:0", "20100704T000000.0+08:0",
8889 "20100704T000000.0-24:00", "20100704T000000.0+24:00",
8890 "20100704T000000.0-12:60", "20100704T000000.0+12:60",
8891 "2010-07-0400:00:00", "2010-07-04 00:00:00",
8892 "2010-07-04t00:00:00", "2010-07-04T00:00:00.",
8893 "2010-Jul-0400:00:00", "2010-Jul-04 00:00:00", "2010-Jul-04t00:00:00",
8894 "2010-Jul-04T00:00:00", "2010-Jul-04 00:00:00.",
8895 "2010-12-22T172201", "2010-Dec-22 17:22:01"])
8896 {
8897 assertThrown!DateTimeException(SysTime.fromISOString(str), format("[%s]", str));
8898 }
8899
8900 static void test(string str, SysTime st, size_t line = __LINE__)
8901 {
8902 if (SysTime.fromISOString(str) != st)
8903 throw new AssertError("unittest failure", __FILE__, line);
8904 }
8905
8906 test("20101222T172201", SysTime(DateTime(2010, 12, 22, 17, 22, 1)));
8907 test("19990706T123033", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8908 test("-19990706T123033", SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
8909 test("+019990706T123033", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8910 test("19990706T123033 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8911 test(" 19990706T123033", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8912 test(" 19990706T123033 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
8913
8914 test("19070707T121212.0", SysTime(DateTime(1907, 7, 7, 12, 12, 12)));
8915 test("19070707T121212.0000000", SysTime(DateTime(1907, 7, 7, 12, 12, 12)));
8916 test("19070707T121212.0000001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), hnsecs(1)));
8917 test("20100704T000000.00000000", SysTime(Date(2010, 7, 4)));
8918 test("20100704T000000.00000009", SysTime(Date(2010, 7, 4)));
8919 test("20100704T000000.00000019", SysTime(DateTime(2010, 7, 4), hnsecs(1)));
8920 test("19070707T121212.000001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), usecs(1)));
8921 test("19070707T121212.0000010", SysTime(DateTime(1907, 7, 7, 12, 12, 12), usecs(1)));
8922 test("19070707T121212.001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), msecs(1)));
8923 test("19070707T121212.0010000", SysTime(DateTime(1907, 7, 7, 12, 12, 12), msecs(1)));
8924
8925 auto west60 = new immutable SimpleTimeZone(hours(-1));
8926 auto west90 = new immutable SimpleTimeZone(minutes(-90));
8927 auto west480 = new immutable SimpleTimeZone(hours(-8));
8928 auto east60 = new immutable SimpleTimeZone(hours(1));
8929 auto east90 = new immutable SimpleTimeZone(minutes(90));
8930 auto east480 = new immutable SimpleTimeZone(hours(8));
8931
8932 test("20101222T172201Z", SysTime(DateTime(2010, 12, 22, 17, 22, 1), UTC()));
8933 test("20101222T172201-0100", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west60));
8934 test("20101222T172201-01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west60));
8935 test("20101222T172201-0130", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west90));
8936 test("20101222T172201-0800", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west480));
8937 test("20101222T172201+0100", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
8938 test("20101222T172201+01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
8939 test("20101222T172201+0130", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east90));
8940 test("20101222T172201+0800", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east480));
8941
8942 test("20101103T065106.57159Z", SysTime(DateTime(2010, 11, 3, 6, 51, 6), hnsecs(5715900), UTC()));
8943 test("20101222T172201.23412Z", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(2_341_200), UTC()));
8944 test("20101222T172201.23112-0100", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(2_311_200), west60));
8945 test("20101222T172201.45-01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(4_500_000), west60));
8946 test("20101222T172201.1-0130", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(1_000_000), west90));
8947 test("20101222T172201.55-0800", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(5_500_000), west480));
8948 test("20101222T172201.1234567+0100", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(1_234_567), east60));
8949 test("20101222T172201.0+01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
8950 test("20101222T172201.0000000+0130", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east90));
8951 test("20101222T172201.45+0800", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(4_500_000), east480));
8952
8953 // for dstring coverage
8954 assert(SysTime.fromISOString("20101222T172201.23112-0100"d) == SysTime(
8955 DateTime(2010, 12, 22, 17, 22, 1), hnsecs(2_311_200), west60));
8956 assert(SysTime.fromISOString("19070707T121212.0010000"d) == SysTime(
8957 DateTime(1907, 7, 7, 12, 12, 12), msecs(1)));
8958
8959 // @@@DEPRECATED_2019-07@@@
8960 // This isn't deprecated per se, but that text will make it so that it
8961 // pops up when deprecations are moved along around July 2019. At that
8962 // time, we will update fromISOString so that it is conformant with ISO
8963 // 8601, and it will no longer accept ISO extended time zones (it does
8964 // currently because of https://issues.dlang.org/show_bug.cgi?id=15654
8965 // toISOString used to incorrectly use the ISO extended time zone format).
8966 // These tests will then start failing will need to be updated accordingly.
8967 // Also, the notes about this issue in toISOString and fromISOString's
8968 // documentation will need to be removed.
8969 test("20101222T172201-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west60));
8970 test("20101222T172201-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west90));
8971 test("20101222T172201-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west480));
8972 test("20101222T172201+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
8973 test("20101222T172201+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east90));
8974 test("20101222T172201+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east480));
8975
8976 test("20101222T172201.23112-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(2_311_200), west60));
8977 test("20101222T172201.1-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(1_000_000), west90));
8978 test("20101222T172201.55-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(5_500_000), west480));
8979 test("20101222T172201.1234567+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(1_234_567), east60));
8980 test("20101222T172201.0000000+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east90));
8981 test("20101222T172201.45+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(4_500_000), east480));
8982
8983 static void testScope(scope ref string str) @safe
8984 {
8985 auto result = SysTime.fromISOString(str);
8986 }
8987 }
8988
8989 // https://issues.dlang.org/show_bug.cgi?id=17801
8990 @safe unittest
8991 {
8992 import std.conv : to;
8993 import std.meta : AliasSeq;
8994 static foreach (C; AliasSeq!(char, wchar, dchar))
8995 {
8996 static foreach (S; AliasSeq!(C[], const(C)[], immutable(C)[]))
8997 {
8998 assert(SysTime.fromISOString(to!S("20121221T141516Z")) ==
8999 SysTime(DateTime(2012, 12, 21, 14, 15, 16), UTC()));
9000 }
9001 }
9002 }
9003
9004
9005 /++
9006 Creates a $(LREF SysTime) from a string with the format
9007 YYYY-MM-DDTHH:MM:SS.FFFFFFFTZ (where F is fractional seconds is the
9008 time zone). Whitespace is stripped from the given string.
9009
9010 The exact format is exactly as described in `toISOExtString`
9011 except that trailing zeroes are permitted - including having fractional
9012 seconds with all zeroes. However, a decimal point with nothing following
9013 it is invalid. Also, while $(LREF toISOExtString) will never generate a
9014 string with more than 7 digits in the fractional seconds (because that's
9015 the limit with hecto-nanosecond precision), it will allow more than 7
9016 digits in order to read strings from other sources that have higher
9017 precision (however, any digits beyond 7 will be truncated).
9018
9019 If there is no time zone in the string, then
9020 $(REF LocalTime,std,datetime,timezone) is used. If the time zone is "Z",
9021 then `UTC` is used. Otherwise, a
9022 $(REF SimpleTimeZone,std,datetime,timezone) which corresponds to the
9023 given offset from UTC is used. To get the returned $(LREF SysTime) to be
9024 a particular time zone, pass in that time zone and the $(LREF SysTime)
9025 to be returned will be converted to that time zone (though it will still
9026 be read in as whatever time zone is in its string).
9027
9028 The accepted formats for time zone offsets are +HH, -HH, +HH:MM, and
9029 -HH:MM.
9030
9031 Params:
9032 isoExtString = A string formatted in the ISO Extended format for
9033 dates and times.
9034 tz = The time zone to convert the given time to (no
9035 conversion occurs if null).
9036
9037 Throws:
9038 $(REF DateTimeException,std,datetime,date) if the given string is
9039 not in the ISO format or if the resulting $(LREF SysTime) would not
9040 be valid.
9041 +/
9042 static SysTime fromISOExtString(S)(scope const S isoExtString, immutable TimeZone tz = null) @safe
9043 if (isSomeString!(S))
9044 {
9045 import std.algorithm.searching : countUntil, find;
9046 import std.conv : to;
9047 import std.string : strip, indexOf;
9048
9049 auto str = strip(isoExtString);
9050
9051 auto tIndex = str.indexOf('T');
9052 enforce(tIndex != -1, new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
9053
9054 auto found = str[tIndex + 1 .. $].find('.', 'Z', '+', '-');
9055 auto dateTimeStr = str[0 .. $ - found[0].length];
9056
9057 typeof(str) foundTZ; // needs to have longer lifetime than zoneStr
9058 typeof(str) fracSecStr;
9059 typeof(str) zoneStr;
9060
9061 if (found[1] != 0)
9062 {
9063 if (found[1] == 1)
9064 {
9065 foundTZ = found[0].find('Z', '+', '-')[0];
9066
9067 if (foundTZ.length != 0)
9068 {
9069 fracSecStr = found[0][0 .. $ - foundTZ.length];
9070 zoneStr = foundTZ;
9071 }
9072 else
9073 fracSecStr = found[0];
9074 }
9075 else
9076 zoneStr = found[0];
9077 }
9078
9079 try
9080 {
9081 auto dateTime = DateTime.fromISOExtString(dateTimeStr);
9082 auto fracSec = fracSecsFromISOString(fracSecStr);
9083 Rebindable!(immutable TimeZone) parsedZone;
9084
9085 if (zoneStr.empty)
9086 parsedZone = LocalTime();
9087 else if (zoneStr == "Z")
9088 parsedZone = UTC();
9089 else
9090 parsedZone = SimpleTimeZone.fromISOExtString(zoneStr);
9091
9092 auto retval = SysTime(dateTime, fracSec, parsedZone);
9093
9094 if (tz !is null)
9095 retval.timezone = tz;
9096
9097 return retval;
9098 }
9099 catch (DateTimeException dte)
9100 throw new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString));
9101 }
9102
9103 ///
9104 @safe unittest
9105 {
9106 import core.time : hours, msecs, usecs, hnsecs;
9107 import std.datetime.date : DateTime;
9108 import std.datetime.timezone : SimpleTimeZone, UTC;
9109
9110 assert(SysTime.fromISOExtString("2010-07-04T07:06:12") ==
9111 SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
9112
9113 assert(SysTime.fromISOExtString("1998-12-25T02:15:00.007") ==
9114 SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(7)));
9115
9116 assert(SysTime.fromISOExtString("0000-01-05T23:09:59.00002") ==
9117 SysTime(DateTime(0, 1, 5, 23, 9, 59), usecs(20)));
9118
9119 assert(SysTime.fromISOExtString("2013-02-07T04:39:37.000050392") ==
9120 SysTime(DateTime(2013, 2, 7, 4, 39, 37), hnsecs(503)));
9121
9122 assert(SysTime.fromISOExtString("-0004-01-05T00:00:02") ==
9123 SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
9124
9125 assert(SysTime.fromISOExtString(" 2010-07-04T07:06:12 ") ==
9126 SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
9127
9128 assert(SysTime.fromISOExtString("2010-07-04T07:06:12Z") ==
9129 SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
9130
9131 assert(SysTime.fromISOExtString("2010-07-04T07:06:12-08:00") ==
9132 SysTime(DateTime(2010, 7, 4, 7, 6, 12),
9133 new immutable SimpleTimeZone(hours(-8))));
9134 assert(SysTime.fromISOExtString("2010-07-04T07:06:12+08:00") ==
9135 SysTime(DateTime(2010, 7, 4, 7, 6, 12),
9136 new immutable SimpleTimeZone(hours(8))));
9137 }
9138
9139 @safe unittest
9140 {
9141 import core.time;
9142 foreach (str; ["", "20100704000000", "20100704 000000",
9143 "20100704t000000", "20100704T000000.", "20100704T000000.0",
9144 "2010-07:0400:00:00", "2010-07-04 00:00:00",
9145 "2010-07-04 00:00:00", "2010-07-04t00:00:00",
9146 "2010-07-04T00:00:00.", "2010-07-04T00:00:00.A", "2010-07-04T00:00:00.Z",
9147 "2010-07-04T00:00:00.0000000A", "2010-07-04T00:00:00.00000000A",
9148 "2010-07-04T00:00:00+", "2010-07-04T00:00:00-",
9149 "2010-07-04T00:00:00:", "2010-07-04T00:00:00-:", "2010-07-04T00:00:00+:",
9150 "2010-07-04T00:00:00-1:", "2010-07-04T00:00:00+1:", "2010-07-04T00:00:00+1:0",
9151 "2010-07-04T00:00:00-12.00", "2010-07-04T00:00:00+12.00",
9152 "2010-07-04T00:00:00-8", "2010-07-04T00:00:00+8",
9153 "20100704T000000-800", "20100704T000000+800",
9154 "20100704T000000-080", "20100704T000000+080",
9155 "20100704T000000-2400", "20100704T000000+2400",
9156 "20100704T000000-1260", "20100704T000000+1260",
9157 "20100704T000000.0-800", "20100704T000000.0+800",
9158 "20100704T000000.0-8", "20100704T000000.0+8",
9159 "20100704T000000.0-080", "20100704T000000.0+080",
9160 "20100704T000000.0-2400", "20100704T000000.0+2400",
9161 "20100704T000000.0-1260", "20100704T000000.0+1260",
9162 "2010-07-04T00:00:00-8:00", "2010-07-04T00:00:00+8:00",
9163 "2010-07-04T00:00:00-24:00", "2010-07-04T00:00:00+24:00",
9164 "2010-07-04T00:00:00-12:60", "2010-07-04T00:00:00+12:60",
9165 "2010-07-04T00:00:00.0-8:00", "2010-07-04T00:00:00.0+8:00",
9166 "2010-07-04T00:00:00.0-8", "2010-07-04T00:00:00.0+8",
9167 "2010-07-04T00:00:00.0-24:00", "2010-07-04T00:00:00.0+24:00",
9168 "2010-07-04T00:00:00.0-12:60", "2010-07-04T00:00:00.0+12:60",
9169 "2010-Jul-0400:00:00", "2010-Jul-04t00:00:00",
9170 "2010-Jul-04 00:00:00.", "2010-Jul-04 00:00:00.0",
9171 "20101222T172201", "2010-Dec-22 17:22:01"])
9172 {
9173 assertThrown!DateTimeException(SysTime.fromISOExtString(str), format("[%s]", str));
9174 }
9175
9176 static void test(string str, SysTime st, size_t line = __LINE__)
9177 {
9178 if (SysTime.fromISOExtString(str) != st)
9179 throw new AssertError("unittest failure", __FILE__, line);
9180 }
9181
9182 test("2010-12-22T17:22:01", SysTime(DateTime(2010, 12, 22, 17, 22, 1)));
9183 test("1999-07-06T12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
9184 test("-1999-07-06T12:30:33", SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
9185 test("+01999-07-06T12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
9186 test("1999-07-06T12:30:33 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
9187 test(" 1999-07-06T12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
9188 test(" 1999-07-06T12:30:33 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
9189
9190 test("1907-07-07T12:12:12.0", SysTime(DateTime(1907, 7, 7, 12, 12, 12)));
9191 test("1907-07-07T12:12:12.0000000", SysTime(DateTime(1907, 7, 7, 12, 12, 12)));
9192 test("1907-07-07T12:12:12.0000001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), hnsecs(1)));
9193 test("2010-07-04T00:00:00.00000000", SysTime(Date(2010, 7, 4)));
9194 test("2010-07-04T00:00:00.00000009", SysTime(Date(2010, 7, 4)));
9195 test("2010-07-04T00:00:00.00000019", SysTime(DateTime(2010, 7, 4), hnsecs(1)));
9196 test("1907-07-07T12:12:12.000001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), usecs(1)));
9197 test("1907-07-07T12:12:12.0000010", SysTime(DateTime(1907, 7, 7, 12, 12, 12), usecs(1)));
9198 test("1907-07-07T12:12:12.001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), msecs(1)));
9199 test("1907-07-07T12:12:12.0010000", SysTime(DateTime(1907, 7, 7, 12, 12, 12), msecs(1)));
9200
9201 auto west60 = new immutable SimpleTimeZone(hours(-1));
9202 auto west90 = new immutable SimpleTimeZone(minutes(-90));
9203 auto west480 = new immutable SimpleTimeZone(hours(-8));
9204 auto east60 = new immutable SimpleTimeZone(hours(1));
9205 auto east90 = new immutable SimpleTimeZone(minutes(90));
9206 auto east480 = new immutable SimpleTimeZone(hours(8));
9207
9208 test("2010-12-22T17:22:01Z", SysTime(DateTime(2010, 12, 22, 17, 22, 1), UTC()));
9209 test("2010-12-22T17:22:01-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west60));
9210 test("2010-12-22T17:22:01-01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west60));
9211 test("2010-12-22T17:22:01-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west90));
9212 test("2010-12-22T17:22:01-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west480));
9213 test("2010-12-22T17:22:01+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
9214 test("2010-12-22T17:22:01+01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
9215 test("2010-12-22T17:22:01+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east90));
9216 test("2010-12-22T17:22:01+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east480));
9217
9218 test("2010-11-03T06:51:06.57159Z", SysTime(DateTime(2010, 11, 3, 6, 51, 6), hnsecs(5715900), UTC()));
9219 test("2010-12-22T17:22:01.23412Z", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(2_341_200), UTC()));
9220 test("2010-12-22T17:22:01.23112-01:00",
9221 SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(2_311_200), west60));
9222 test("2010-12-22T17:22:01.45-01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(4_500_000), west60));
9223 test("2010-12-22T17:22:01.1-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(1_000_000), west90));
9224 test("2010-12-22T17:22:01.55-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(5_500_000), west480));
9225 test("2010-12-22T17:22:01.1234567+01:00",
9226 SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(1_234_567), east60));
9227 test("2010-12-22T17:22:01.0+01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
9228 test("2010-12-22T17:22:01.0000000+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east90));
9229 test("2010-12-22T17:22:01.45+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(4_500_000), east480));
9230
9231 static void testScope(scope ref string str) @safe
9232 {
9233 auto result = SysTime.fromISOExtString(str);
9234 }
9235 }
9236
9237 // https://issues.dlang.org/show_bug.cgi?id=17801
9238 @safe unittest
9239 {
9240 import core.time;
9241 import std.conv : to;
9242 import std.meta : AliasSeq;
9243 static foreach (C; AliasSeq!(char, wchar, dchar))
9244 {
9245 static foreach (S; AliasSeq!(C[], const(C)[], immutable(C)[]))
9246 {
9247 assert(SysTime.fromISOExtString(to!S("2012-12-21T14:15:16Z")) ==
9248 SysTime(DateTime(2012, 12, 21, 14, 15, 16), UTC()));
9249 }
9250 }
9251 }
9252
9253
9254 /++
9255 Creates a $(LREF SysTime) from a string with the format
9256 YYYY-MM-DD HH:MM:SS.FFFFFFFTZ (where F is fractional seconds is the
9257 time zone). Whitespace is stripped from the given string.
9258
9259 The exact format is exactly as described in `toSimpleString` except
9260 that trailing zeroes are permitted - including having fractional seconds
9261 with all zeroes. However, a decimal point with nothing following it is
9262 invalid. Also, while $(LREF toSimpleString) will never generate a
9263 string with more than 7 digits in the fractional seconds (because that's
9264 the limit with hecto-nanosecond precision), it will allow more than 7
9265 digits in order to read strings from other sources that have higher
9266 precision (however, any digits beyond 7 will be truncated).
9267
9268 If there is no time zone in the string, then
9269 $(REF LocalTime,std,datetime,timezone) is used. If the time zone is "Z",
9270 then `UTC` is used. Otherwise, a
9271 $(REF SimpleTimeZone,std,datetime,timezone) which corresponds to the
9272 given offset from UTC is used. To get the returned $(LREF SysTime) to be
9273 a particular time zone, pass in that time zone and the $(LREF SysTime)
9274 to be returned will be converted to that time zone (though it will still
9275 be read in as whatever time zone is in its string).
9276
9277 The accepted formats for time zone offsets are +HH, -HH, +HH:MM, and
9278 -HH:MM.
9279
9280 Params:
9281 simpleString = A string formatted in the way that
9282 `toSimpleString` formats dates and times.
9283 tz = The time zone to convert the given time to (no
9284 conversion occurs if null).
9285
9286 Throws:
9287 $(REF DateTimeException,std,datetime,date) if the given string is
9288 not in the ISO format or if the resulting $(LREF SysTime) would not
9289 be valid.
9290 +/
9291 static SysTime fromSimpleString(S)(scope const S simpleString, immutable TimeZone tz = null) @safe
9292 if (isSomeString!(S))
9293 {
9294 import std.algorithm.searching : find;
9295 import std.conv : to;
9296 import std.string : strip, indexOf;
9297
9298 auto str = strip(simpleString);
9299
9300 auto spaceIndex = str.indexOf(' ');
9301 enforce(spaceIndex != -1, new DateTimeException(format("Invalid Simple String: %s", simpleString)));
9302
9303 auto found = str[spaceIndex + 1 .. $].find('.', 'Z', '+', '-');
9304 auto dateTimeStr = str[0 .. $ - found[0].length];
9305
9306 typeof(str) foundTZ; // needs to have longer lifetime than zoneStr
9307 typeof(str) fracSecStr;
9308 typeof(str) zoneStr;
9309
9310 if (found[1] != 0)
9311 {
9312 if (found[1] == 1)
9313 {
9314 foundTZ = found[0].find('Z', '+', '-')[0];
9315
9316 if (foundTZ.length != 0)
9317 {
9318 fracSecStr = found[0][0 .. $ - foundTZ.length];
9319 zoneStr = foundTZ;
9320 }
9321 else
9322 fracSecStr = found[0];
9323 }
9324 else
9325 zoneStr = found[0];
9326 }
9327
9328 try
9329 {
9330 auto dateTime = DateTime.fromSimpleString(dateTimeStr);
9331 auto fracSec = fracSecsFromISOString(fracSecStr);
9332 Rebindable!(immutable TimeZone) parsedZone;
9333
9334 if (zoneStr.empty)
9335 parsedZone = LocalTime();
9336 else if (zoneStr == "Z")
9337 parsedZone = UTC();
9338 else
9339 parsedZone = SimpleTimeZone.fromISOExtString(zoneStr);
9340
9341 auto retval = SysTime(dateTime, fracSec, parsedZone);
9342
9343 if (tz !is null)
9344 retval.timezone = tz;
9345
9346 return retval;
9347 }
9348 catch (DateTimeException dte)
9349 throw new DateTimeException(format("Invalid Simple String: %s", simpleString));
9350 }
9351
9352 ///
9353 @safe unittest
9354 {
9355 import core.time : hours, msecs, usecs, hnsecs;
9356 import std.datetime.date : DateTime;
9357 import std.datetime.timezone : SimpleTimeZone, UTC;
9358
9359 assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12") ==
9360 SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
9361
9362 assert(SysTime.fromSimpleString("1998-Dec-25 02:15:00.007") ==
9363 SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(7)));
9364
9365 assert(SysTime.fromSimpleString("0000-Jan-05 23:09:59.00002") ==
9366 SysTime(DateTime(0, 1, 5, 23, 9, 59), usecs(20)));
9367
9368 assert(SysTime.fromSimpleString("2013-Feb-07 04:39:37.000050392") ==
9369 SysTime(DateTime(2013, 2, 7, 4, 39, 37), hnsecs(503)));
9370
9371 assert(SysTime.fromSimpleString("-0004-Jan-05 00:00:02") ==
9372 SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
9373
9374 assert(SysTime.fromSimpleString(" 2010-Jul-04 07:06:12 ") ==
9375 SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
9376
9377 assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12Z") ==
9378 SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
9379
9380 assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12-08:00") ==
9381 SysTime(DateTime(2010, 7, 4, 7, 6, 12),
9382 new immutable SimpleTimeZone(hours(-8))));
9383
9384 assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12+08:00") ==
9385 SysTime(DateTime(2010, 7, 4, 7, 6, 12),
9386 new immutable SimpleTimeZone(hours(8))));
9387 }
9388
9389 @safe unittest
9390 {
9391 import core.time;
9392 foreach (str; ["", "20100704000000", "20100704 000000",
9393 "20100704t000000", "20100704T000000.", "20100704T000000.0",
9394 "2010-07-0400:00:00", "2010-07-04 00:00:00", "2010-07-04t00:00:00",
9395 "2010-07-04T00:00:00.", "2010-07-04T00:00:00.0",
9396 "2010-Jul-0400:00:00", "2010-Jul-04t00:00:00", "2010-Jul-04T00:00:00",
9397 "2010-Jul-04 00:00:00.", "2010-Jul-04 00:00:00.A", "2010-Jul-04 00:00:00.Z",
9398 "2010-Jul-04 00:00:00.0000000A", "2010-Jul-04 00:00:00.00000000A",
9399 "2010-Jul-04 00:00:00+", "2010-Jul-04 00:00:00-",
9400 "2010-Jul-04 00:00:00:", "2010-Jul-04 00:00:00-:",
9401 "2010-Jul-04 00:00:00+:", "2010-Jul-04 00:00:00-1:",
9402 "2010-Jul-04 00:00:00+1:", "2010-Jul-04 00:00:00+1:0",
9403 "2010-Jul-04 00:00:00-12.00", "2010-Jul-04 00:00:00+12.00",
9404 "2010-Jul-04 00:00:00-8", "2010-Jul-04 00:00:00+8",
9405 "20100704T000000-800", "20100704T000000+800",
9406 "20100704T000000-080", "20100704T000000+080",
9407 "20100704T000000-2400", "20100704T000000+2400",
9408 "20100704T000000-1260", "20100704T000000+1260",
9409 "20100704T000000.0-800", "20100704T000000.0+800",
9410 "20100704T000000.0-8", "20100704T000000.0+8",
9411 "20100704T000000.0-080", "20100704T000000.0+080",
9412 "20100704T000000.0-2400", "20100704T000000.0+2400",
9413 "20100704T000000.0-1260", "20100704T000000.0+1260",
9414 "2010-Jul-04 00:00:00-8:00", "2010-Jul-04 00:00:00+8:00",
9415 "2010-Jul-04 00:00:00-08:0", "2010-Jul-04 00:00:00+08:0",
9416 "2010-Jul-04 00:00:00-24:00", "2010-Jul-04 00:00:00+24:00",
9417 "2010-Jul-04 00:00:00-12:60", "2010-Jul-04 00:00:00+24:60",
9418 "2010-Jul-04 00:00:00.0-8:00", "2010-Jul-04 00:00:00+8:00",
9419 "2010-Jul-04 00:00:00.0-8", "2010-Jul-04 00:00:00.0+8",
9420 "2010-Jul-04 00:00:00.0-08:0", "2010-Jul-04 00:00:00.0+08:0",
9421 "2010-Jul-04 00:00:00.0-24:00", "2010-Jul-04 00:00:00.0+24:00",
9422 "2010-Jul-04 00:00:00.0-12:60", "2010-Jul-04 00:00:00.0+24:60",
9423 "20101222T172201", "2010-12-22T172201"])
9424 {
9425 assertThrown!DateTimeException(SysTime.fromSimpleString(str), format("[%s]", str));
9426 }
9427
9428 static void test(string str, SysTime st, size_t line = __LINE__)
9429 {
9430 if (SysTime.fromSimpleString(str) != st)
9431 throw new AssertError("unittest failure", __FILE__, line);
9432 }
9433
9434 test("2010-Dec-22 17:22:01", SysTime(DateTime(2010, 12, 22, 17, 22, 1)));
9435 test("1999-Jul-06 12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
9436 test("-1999-Jul-06 12:30:33", SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
9437 test("+01999-Jul-06 12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
9438 test("1999-Jul-06 12:30:33 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
9439 test(" 1999-Jul-06 12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
9440 test(" 1999-Jul-06 12:30:33 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
9441
9442 test("1907-Jul-07 12:12:12.0", SysTime(DateTime(1907, 7, 7, 12, 12, 12)));
9443 test("1907-Jul-07 12:12:12.0000000", SysTime(DateTime(1907, 7, 7, 12, 12, 12)));
9444 test("2010-Jul-04 00:00:00.00000000", SysTime(Date(2010, 7, 4)));
9445 test("2010-Jul-04 00:00:00.00000009", SysTime(Date(2010, 7, 4)));
9446 test("2010-Jul-04 00:00:00.00000019", SysTime(DateTime(2010, 7, 4), hnsecs(1)));
9447 test("1907-Jul-07 12:12:12.0000001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), hnsecs(1)));
9448 test("1907-Jul-07 12:12:12.000001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), usecs(1)));
9449 test("1907-Jul-07 12:12:12.0000010", SysTime(DateTime(1907, 7, 7, 12, 12, 12), usecs(1)));
9450 test("1907-Jul-07 12:12:12.001", SysTime(DateTime(1907, 7, 7, 12, 12, 12), msecs(1)));
9451 test("1907-Jul-07 12:12:12.0010000", SysTime(DateTime(1907, 7, 7, 12, 12, 12), msecs(1)));
9452
9453 auto west60 = new immutable SimpleTimeZone(hours(-1));
9454 auto west90 = new immutable SimpleTimeZone(minutes(-90));
9455 auto west480 = new immutable SimpleTimeZone(hours(-8));
9456 auto east60 = new immutable SimpleTimeZone(hours(1));
9457 auto east90 = new immutable SimpleTimeZone(minutes(90));
9458 auto east480 = new immutable SimpleTimeZone(hours(8));
9459
9460 test("2010-Dec-22 17:22:01Z", SysTime(DateTime(2010, 12, 22, 17, 22, 1), UTC()));
9461 test("2010-Dec-22 17:22:01-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west60));
9462 test("2010-Dec-22 17:22:01-01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west60));
9463 test("2010-Dec-22 17:22:01-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west90));
9464 test("2010-Dec-22 17:22:01-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), west480));
9465 test("2010-Dec-22 17:22:01+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
9466 test("2010-Dec-22 17:22:01+01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
9467 test("2010-Dec-22 17:22:01+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east90));
9468 test("2010-Dec-22 17:22:01+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east480));
9469
9470 test("2010-Nov-03 06:51:06.57159Z", SysTime(DateTime(2010, 11, 3, 6, 51, 6), hnsecs(5715900), UTC()));
9471 test("2010-Dec-22 17:22:01.23412Z", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(2_341_200), UTC()));
9472 test("2010-Dec-22 17:22:01.23112-01:00",
9473 SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(2_311_200), west60));
9474 test("2010-Dec-22 17:22:01.45-01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(4_500_000), west60));
9475 test("2010-Dec-22 17:22:01.1-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(1_000_000), west90));
9476 test("2010-Dec-22 17:22:01.55-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(5_500_000), west480));
9477 test("2010-Dec-22 17:22:01.1234567+01:00",
9478 SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(1_234_567), east60));
9479 test("2010-Dec-22 17:22:01.0+01", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east60));
9480 test("2010-Dec-22 17:22:01.0000000+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 1), east90));
9481 test("2010-Dec-22 17:22:01.45+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 1), hnsecs(4_500_000), east480));
9482
9483 static void testScope(scope ref string str) @safe
9484 {
9485 auto result = SysTime.fromSimpleString(str);
9486 }
9487 }
9488
9489 // https://issues.dlang.org/show_bug.cgi?id=17801
9490 @safe unittest
9491 {
9492 import core.time;
9493 import std.conv : to;
9494 import std.meta : AliasSeq;
9495 static foreach (C; AliasSeq!(char, wchar, dchar))
9496 {
9497 static foreach (S; AliasSeq!(C[], const(C)[], immutable(C)[]))
9498 {
9499 assert(SysTime.fromSimpleString(to!S("2012-Dec-21 14:15:16Z")) ==
9500 SysTime(DateTime(2012, 12, 21, 14, 15, 16), UTC()));
9501 }
9502 }
9503 }
9504
9505
9506 /++
9507 Returns the $(LREF SysTime) farthest in the past which is representable
9508 by $(LREF SysTime).
9509
9510 The $(LREF SysTime) which is returned is in UTC.
9511 +/
9512 @property static SysTime min() @safe pure nothrow
9513 {
9514 return SysTime(long.min, UTC());
9515 }
9516
9517 @safe unittest
9518 {
9519 assert(SysTime.min.year < 0);
9520 assert(SysTime.min < SysTime.max);
9521 }
9522
9523
9524 /++
9525 Returns the $(LREF SysTime) farthest in the future which is representable
9526 by $(LREF SysTime).
9527
9528 The $(LREF SysTime) which is returned is in UTC.
9529 +/
9530 @property static SysTime max() @safe pure nothrow
9531 {
9532 return SysTime(long.max, UTC());
9533 }
9534
9535 @safe unittest
9536 {
9537 assert(SysTime.max.year > 0);
9538 assert(SysTime.max > SysTime.min);
9539 }
9540
9541
9542 private:
9543
9544 /+
9545 Returns `stdTime` converted to $(LREF SysTime)'s time zone.
9546 +/
9547 @property long adjTime() @safe const nothrow scope
9548 {
9549 return _timezone.utcToTZ(_stdTime);
9550 }
9551
9552
9553 /+
9554 Converts the given hnsecs from $(LREF SysTime)'s time zone to std time.
9555 +/
9556 @property void adjTime(long adjTime) @safe nothrow scope
9557 {
9558 _stdTime = _timezone.tzToUTC(adjTime);
9559 }
9560
9561
9562 final class InitTimeZone : TimeZone
9563 {
9564 public:
9565
9566 static immutable(InitTimeZone) opCall() @safe pure nothrow @nogc { return _initTimeZone; }
9567
9568 @property override bool hasDST() @safe const nothrow @nogc { return false; }
9569
9570 override bool dstInEffect(long stdTime) @safe const nothrow @nogc { return false; }
9571
9572 override long utcToTZ(long stdTime) @safe const nothrow @nogc { return 0; }
9573
9574 override long tzToUTC(long adjTime) @safe const nothrow @nogc { return 0; }
9575
9576 override Duration utcOffsetAt(long stdTime) @safe const nothrow @nogc { return Duration.zero; }
9577
9578 private:
9579
9580 this() @safe immutable pure
9581 {
9582 super("SysTime.init's timezone", "SysTime.init's timezone", "SysTime.init's timezone");
9583 }
9584
9585 static immutable InitTimeZone _initTimeZone = new immutable(InitTimeZone);
9586 }
9587
9588 // https://issues.dlang.org/show_bug.cgi?id=17732
9589 @safe unittest
9590 {
9591 assert(SysTime.init.timezone is InitTimeZone());
9592 assert(SysTime.init.toISOString() == "00010101T000000+00:00");
9593 assert(SysTime.init.toISOExtString() == "0001-01-01T00:00:00+00:00");
9594 assert(SysTime.init.toSimpleString() == "0001-Jan-01 00:00:00+00:00");
9595 assert(SysTime.init.toString() == "0001-Jan-01 00:00:00+00:00");
9596 }
9597
9598 // Assigning a value to _timezone in SysTime.init currently doesn't work due
9599 // to https://issues.dlang.org/show_bug.cgi?id=17740. So, to hack around
9600 // that problem, these accessors have been added so that we can insert a
9601 // runtime check for null and then use InitTimeZone for SysTime.init (which
9602 // which is the only case where _timezone would be null). This thus fixes
9603 // the problem with segfaulting when using SysTime.init but at the cost of
9604 // what should be an unnecessary null check. Once 17740 has finally been
9605 // fixed, _timezoneStorage should be removed, these accessors should be
9606 // removed, and the _timezone variable declaration should be restored.
9607 pragma(inline, true) @property _timezone() @safe const pure nothrow @nogc
9608 {
9609 return _timezoneStorage is null ? InitTimeZone() : _timezoneStorage;
9610 }
9611
9612 pragma(inline, true) @property void _timezone(immutable TimeZone tz) @safe pure nothrow @nogc scope
9613 {
9614 _timezoneStorage = tz;
9615 }
9616
9617
9618 long _stdTime;
9619 Rebindable!(immutable TimeZone) _timezoneStorage;
9620 //Rebindable!(immutable TimeZone) _timezone = InitTimeZone();
9621 }
9622
9623 ///
9624 @safe unittest
9625 {
9626 import core.time : days, hours, seconds;
9627 import std.datetime.date : DateTime;
9628 import std.datetime.timezone : SimpleTimeZone, UTC;
9629
9630 // make a specific point in time in the UTC timezone
9631 auto st = SysTime(DateTime(2018, 1, 1, 10, 30, 0), UTC());
9632 // make a specific point in time in the New York timezone
9633 auto ny = SysTime(
9634 DateTime(2018, 1, 1, 10, 30, 0),
9635 new immutable SimpleTimeZone(-5.hours, "America/New_York")
9636 );
9637
9638 // ISO standard time strings
9639 assert(st.toISOString() == "20180101T103000Z");
9640 assert(st.toISOExtString() == "2018-01-01T10:30:00Z");
9641
9642 // add two days and 30 seconds
9643 st += 2.days + 30.seconds;
9644 assert(st.toISOExtString() == "2018-01-03T10:30:30Z");
9645 }
9646
9647
9648 /++
9649 Converts from unix time (which uses midnight, January 1st, 1970 UTC as its
9650 epoch and seconds as its units) to "std time" (which uses midnight,
9651 January 1st, 1 A.D. UTC and hnsecs as its units).
9652
9653 The C standard does not specify the representation of time_t, so it is
9654 implementation defined. On POSIX systems, unix time is equivalent to
9655 time_t, but that's not necessarily true on other systems (e.g. it is
9656 not true for the Digital Mars C runtime). So, be careful when using unix
9657 time with C functions on non-POSIX systems.
9658
9659 "std time"'s epoch is based on the Proleptic Gregorian Calendar per ISO
9660 8601 and is what $(LREF SysTime) uses internally. However, holding the time
9661 as an integer in hnsecs since that epoch technically isn't actually part of
9662 the standard, much as it's based on it, so the name "std time" isn't
9663 particularly good, but there isn't an official name for it. C# uses "ticks"
9664 for the same thing, but they aren't actually clock ticks, and the term
9665 "ticks" $(I is) used for actual clock ticks for $(REF MonoTime, core,time),
9666 so it didn't make sense to use the term ticks here. So, for better or worse,
9667 std.datetime uses the term "std time" for this.
9668
9669 Params:
9670 unixTime = The unix time to convert.
9671
9672 See_Also:
9673 SysTime.fromUnixTime
9674 +/
unixTimeToStdTime(long unixTime)9675 long unixTimeToStdTime(long unixTime) @safe pure nothrow @nogc
9676 {
9677 return 621_355_968_000_000_000L + convert!("seconds", "hnsecs")(unixTime);
9678 }
9679
9680 ///
9681 @safe unittest
9682 {
9683 import std.datetime.date : DateTime;
9684 import std.datetime.timezone : UTC;
9685
9686 // Midnight, January 1st, 1970
9687 assert(unixTimeToStdTime(0) == 621_355_968_000_000_000L);
9688 assert(SysTime(unixTimeToStdTime(0)) ==
9689 SysTime(DateTime(1970, 1, 1), UTC()));
9690
9691 assert(unixTimeToStdTime(int.max) == 642_830_804_470_000_000L);
9692 assert(SysTime(unixTimeToStdTime(int.max)) ==
9693 SysTime(DateTime(2038, 1, 19, 3, 14, 7), UTC()));
9694
9695 assert(unixTimeToStdTime(-127_127) == 621_354_696_730_000_000L);
9696 assert(SysTime(unixTimeToStdTime(-127_127)) ==
9697 SysTime(DateTime(1969, 12, 30, 12, 41, 13), UTC()));
9698 }
9699
9700 @safe unittest
9701 {
9702 // Midnight, January 2nd, 1970
9703 assert(unixTimeToStdTime(86_400) == 621_355_968_000_000_000L + 864_000_000_000L);
9704 // Midnight, December 31st, 1969
9705 assert(unixTimeToStdTime(-86_400) == 621_355_968_000_000_000L - 864_000_000_000L);
9706
9707 assert(unixTimeToStdTime(0) == (Date(1970, 1, 1) - Date(1, 1, 1)).total!"hnsecs");
9708 assert(unixTimeToStdTime(0) == (DateTime(1970, 1, 1) - DateTime(1, 1, 1)).total!"hnsecs");
9709
9710 foreach (dt; [DateTime(2010, 11, 1, 19, 5, 22), DateTime(1952, 7, 6, 2, 17, 9)])
9711 assert(unixTimeToStdTime((dt - DateTime(1970, 1, 1)).total!"seconds") == (dt - DateTime.init).total!"hnsecs");
9712 }
9713
9714
9715 /++
9716 Converts std time (which uses midnight, January 1st, 1 A.D. UTC as its epoch
9717 and hnsecs as its units) to unix time (which uses midnight, January 1st,
9718 1970 UTC as its epoch and seconds as its units).
9719
9720 The C standard does not specify the representation of time_t, so it is
9721 implementation defined. On POSIX systems, unix time is equivalent to
9722 time_t, but that's not necessarily true on other systems (e.g. it is
9723 not true for the Digital Mars C runtime). So, be careful when using unix
9724 time with C functions on non-POSIX systems.
9725
9726 "std time"'s epoch is based on the Proleptic Gregorian Calendar per ISO
9727 8601 and is what $(LREF SysTime) uses internally. However, holding the time
9728 as an integer in hnescs since that epoch technically isn't actually part of
9729 the standard, much as it's based on it, so the name "std time" isn't
9730 particularly good, but there isn't an official name for it. C# uses "ticks"
9731 for the same thing, but they aren't actually clock ticks, and the term
9732 "ticks" $(I is) used for actual clock ticks for $(REF MonoTime, core,time),
9733 so it didn't make sense to use the term ticks here. So, for better or worse,
9734 std.datetime uses the term "std time" for this.
9735
9736 By default, the return type is time_t (which is normally an alias for
9737 int on 32-bit systems and long on 64-bit systems), but if a different
9738 size is required than either int or long can be passed as a template
9739 argument to get the desired size.
9740
9741 If the return type is int, and the result can't fit in an int, then the
9742 closest value that can be held in 32 bits will be used (so `int.max`
9743 if it goes over and `int.min` if it goes under). However, no attempt
9744 is made to deal with integer overflow if the return type is long.
9745
9746 Params:
9747 T = The return type (int or long). It defaults to time_t, which is
9748 normally 32 bits on a 32-bit system and 64 bits on a 64-bit
9749 system.
9750 stdTime = The std time to convert.
9751
9752 Returns:
9753 A signed integer representing the unix time which is equivalent to
9754 the given std time.
9755
9756 See_Also:
9757 SysTime.toUnixTime
9758 +/
9759 T stdTimeToUnixTime(T = time_t)(long stdTime) @safe pure nothrow
9760 if (is(T == int) || is(T == long))
9761 {
9762 immutable unixTime = convert!("hnsecs", "seconds")(stdTime - 621_355_968_000_000_000L);
9763
9764 static assert(is(time_t == int) || is(time_t == long),
9765 "Currently, std.datetime only supports systems where time_t is int or long");
9766
9767 static if (is(T == long))
9768 return unixTime;
9769 else static if (is(T == int))
9770 {
9771 if (unixTime > int.max)
9772 return int.max;
9773 return unixTime < int.min ? int.min : cast(int) unixTime;
9774 }
9775 else
9776 static assert(0, "Bug in template constraint. Only int and long allowed.");
9777 }
9778
9779 ///
9780 @safe unittest
9781 {
9782 // Midnight, January 1st, 1970 UTC
9783 assert(stdTimeToUnixTime(621_355_968_000_000_000L) == 0);
9784
9785 // 2038-01-19 03:14:07 UTC
9786 assert(stdTimeToUnixTime(642_830_804_470_000_000L) == int.max);
9787 }
9788
9789 @safe unittest
9790 {
9791 enum unixEpochAsStdTime = (Date(1970, 1, 1) - Date.init).total!"hnsecs";
9792
9793 assert(stdTimeToUnixTime(unixEpochAsStdTime) == 0); // Midnight, January 1st, 1970
9794 assert(stdTimeToUnixTime(unixEpochAsStdTime + 864_000_000_000L) == 86_400); // Midnight, January 2nd, 1970
9795 assert(stdTimeToUnixTime(unixEpochAsStdTime - 864_000_000_000L) == -86_400); // Midnight, December 31st, 1969
9796
9797 assert(stdTimeToUnixTime((Date(1970, 1, 1) - Date(1, 1, 1)).total!"hnsecs") == 0);
9798 assert(stdTimeToUnixTime((DateTime(1970, 1, 1) - DateTime(1, 1, 1)).total!"hnsecs") == 0);
9799
9800 foreach (dt; [DateTime(2010, 11, 1, 19, 5, 22), DateTime(1952, 7, 6, 2, 17, 9)])
9801 assert(stdTimeToUnixTime((dt - DateTime.init).total!"hnsecs") == (dt - DateTime(1970, 1, 1)).total!"seconds");
9802
9803 enum max = convert!("seconds", "hnsecs")(int.max);
9804 enum min = convert!("seconds", "hnsecs")(int.min);
9805 enum one = convert!("seconds", "hnsecs")(1);
9806
9807 assert(stdTimeToUnixTime!long(unixEpochAsStdTime + max) == int.max);
9808 assert(stdTimeToUnixTime!int(unixEpochAsStdTime + max) == int.max);
9809
9810 assert(stdTimeToUnixTime!long(unixEpochAsStdTime + max + one) == int.max + 1L);
9811 assert(stdTimeToUnixTime!int(unixEpochAsStdTime + max + one) == int.max);
9812 assert(stdTimeToUnixTime!long(unixEpochAsStdTime + max + 9_999_999) == int.max);
9813 assert(stdTimeToUnixTime!int(unixEpochAsStdTime + max + 9_999_999) == int.max);
9814
9815 assert(stdTimeToUnixTime!long(unixEpochAsStdTime + min) == int.min);
9816 assert(stdTimeToUnixTime!int(unixEpochAsStdTime + min) == int.min);
9817
9818 assert(stdTimeToUnixTime!long(unixEpochAsStdTime + min - one) == int.min - 1L);
9819 assert(stdTimeToUnixTime!int(unixEpochAsStdTime + min - one) == int.min);
9820 assert(stdTimeToUnixTime!long(unixEpochAsStdTime + min - 9_999_999) == int.min);
9821 assert(stdTimeToUnixTime!int(unixEpochAsStdTime + min - 9_999_999) == int.min);
9822 }
9823
9824
version(StdDdoc)9825 version (StdDdoc)
9826 {
9827 version (Windows)
9828 {}
9829 else
9830 {
9831 alias SYSTEMTIME = void*;
9832 alias FILETIME = void*;
9833 }
9834
9835 /++
9836 $(BLUE This function is Windows-Only.)
9837
9838 Converts a `SYSTEMTIME` struct to a $(LREF SysTime).
9839
9840 Params:
9841 st = The `SYSTEMTIME` struct to convert.
9842 tz = The time zone that the time in the `SYSTEMTIME` struct is
9843 assumed to be (if the `SYSTEMTIME` was supplied by a Windows
9844 system call, the `SYSTEMTIME` will either be in local time
9845 or UTC, depending on the call).
9846
9847 Throws:
9848 $(REF DateTimeException,std,datetime,date) if the given
9849 `SYSTEMTIME` will not fit in a $(LREF SysTime), which is highly
9850 unlikely to happen given that `SysTime.max` is in 29,228 A.D. and
9851 the maximum `SYSTEMTIME` is in 30,827 A.D.
9852 +/
9853 SysTime SYSTEMTIMEToSysTime(const scope SYSTEMTIME* st, immutable TimeZone tz = LocalTime()) @safe;
9854
9855
9856 /++
9857 $(BLUE This function is Windows-Only.)
9858
9859 Converts a $(LREF SysTime) to a `SYSTEMTIME` struct.
9860
9861 The `SYSTEMTIME` which is returned will be set using the given
9862 $(LREF SysTime)'s time zone, so to get the `SYSTEMTIME` in
9863 UTC, set the $(LREF SysTime)'s time zone to UTC.
9864
9865 Params:
9866 sysTime = The $(LREF SysTime) to convert.
9867
9868 Throws:
9869 $(REF DateTimeException,std,datetime,date) if the given
9870 $(LREF SysTime) will not fit in a `SYSTEMTIME`. This will only
9871 happen if the $(LREF SysTime)'s date is prior to 1601 A.D.
9872 +/
9873 SYSTEMTIME SysTimeToSYSTEMTIME(scope SysTime sysTime) @safe;
9874
9875
9876 /++
9877 $(BLUE This function is Windows-Only.)
9878
9879 Converts a `FILETIME` struct to the number of hnsecs since midnight,
9880 January 1st, 1 A.D.
9881
9882 Params:
9883 ft = The `FILETIME` struct to convert.
9884
9885 Throws:
9886 $(REF DateTimeException,std,datetime,date) if the given
9887 `FILETIME` cannot be represented as the return value.
9888 +/
9889 long FILETIMEToStdTime(scope const FILETIME* ft) @safe;
9890
9891
9892 /++
9893 $(BLUE This function is Windows-Only.)
9894
9895 Converts a `FILETIME` struct to a $(LREF SysTime).
9896
9897 Params:
9898 ft = The `FILETIME` struct to convert.
9899 tz = The time zone that the $(LREF SysTime) will be in
9900 (`FILETIME`s are in UTC).
9901
9902 Throws:
9903 $(REF DateTimeException,std,datetime,date) if the given
9904 `FILETIME` will not fit in a $(LREF SysTime).
9905 +/
9906 SysTime FILETIMEToSysTime(scope const FILETIME* ft, immutable TimeZone tz = LocalTime()) @safe;
9907
9908
9909 /++
9910 $(BLUE This function is Windows-Only.)
9911
9912 Converts a number of hnsecs since midnight, January 1st, 1 A.D. to a
9913 `FILETIME` struct.
9914
9915 Params:
9916 stdTime = The number of hnsecs since midnight, January 1st, 1 A.D.
9917 UTC.
9918
9919 Throws:
9920 $(REF DateTimeException,std,datetime,date) if the given value will
9921 not fit in a `FILETIME`.
9922 +/
9923 FILETIME stdTimeToFILETIME(long stdTime) @safe;
9924
9925
9926 /++
9927 $(BLUE This function is Windows-Only.)
9928
9929 Converts a $(LREF SysTime) to a `FILETIME` struct.
9930
9931 `FILETIME`s are always in UTC.
9932
9933 Params:
9934 sysTime = The $(LREF SysTime) to convert.
9935
9936 Throws:
9937 $(REF DateTimeException,std,datetime,date) if the given
9938 $(LREF SysTime) will not fit in a `FILETIME`.
9939 +/
9940 FILETIME SysTimeToFILETIME(scope SysTime sysTime) @safe;
9941 }
version(Windows)9942 else version (Windows)
9943 {
9944 SysTime SYSTEMTIMEToSysTime(const scope SYSTEMTIME* st, immutable TimeZone tz = LocalTime()) @safe
9945 {
9946 const max = SysTime.max;
9947
9948 static void throwLaterThanMax()
9949 {
9950 throw new DateTimeException("The given SYSTEMTIME is for a date greater than SysTime.max.");
9951 }
9952
9953 if (st.wYear > max.year)
9954 throwLaterThanMax();
9955 else if (st.wYear == max.year)
9956 {
9957 if (st.wMonth > max.month)
9958 throwLaterThanMax();
9959 else if (st.wMonth == max.month)
9960 {
9961 if (st.wDay > max.day)
9962 throwLaterThanMax();
9963 else if (st.wDay == max.day)
9964 {
9965 if (st.wHour > max.hour)
9966 throwLaterThanMax();
9967 else if (st.wHour == max.hour)
9968 {
9969 if (st.wMinute > max.minute)
9970 throwLaterThanMax();
9971 else if (st.wMinute == max.minute)
9972 {
9973 if (st.wSecond > max.second)
9974 throwLaterThanMax();
9975 else if (st.wSecond == max.second)
9976 {
9977 if (st.wMilliseconds > max.fracSecs.total!"msecs")
9978 throwLaterThanMax();
9979 }
9980 }
9981 }
9982 }
9983 }
9984 }
9985
9986 auto dt = DateTime(st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
9987
9988 import core.time : msecs;
9989 return SysTime(dt, msecs(st.wMilliseconds), tz);
9990 }
9991
9992 @system unittest
9993 {
9994 auto sysTime = Clock.currTime(UTC());
9995 SYSTEMTIME st = void;
9996 GetSystemTime(&st);
9997 auto converted = SYSTEMTIMEToSysTime(&st, UTC());
9998 import core.time : abs;
9999 assert(abs((converted - sysTime)) <= dur!"seconds"(2));
10000
10001 static void testScope(scope SYSTEMTIME* st) @safe
10002 {
10003 auto result = SYSTEMTIMEToSysTime(st);
10004 }
10005 }
10006
10007
10008 SYSTEMTIME SysTimeToSYSTEMTIME(scope SysTime sysTime) @safe
10009 {
10010 immutable dt = cast(DateTime) sysTime;
10011
10012 if (dt.year < 1601)
10013 throw new DateTimeException("SYSTEMTIME cannot hold dates prior to the year 1601.");
10014
10015 SYSTEMTIME st;
10016
10017 st.wYear = dt.year;
10018 st.wMonth = dt.month;
10019 st.wDayOfWeek = dt.dayOfWeek;
10020 st.wDay = dt.day;
10021 st.wHour = dt.hour;
10022 st.wMinute = dt.minute;
10023 st.wSecond = dt.second;
10024 st.wMilliseconds = cast(ushort) sysTime.fracSecs.total!"msecs";
10025
10026 return st;
10027 }
10028
10029 @system unittest
10030 {
10031 SYSTEMTIME st = void;
10032 GetSystemTime(&st);
10033 auto sysTime = SYSTEMTIMEToSysTime(&st, UTC());
10034
10035 SYSTEMTIME result = SysTimeToSYSTEMTIME(sysTime);
10036
10037 assert(st.wYear == result.wYear);
10038 assert(st.wMonth == result.wMonth);
10039 assert(st.wDayOfWeek == result.wDayOfWeek);
10040 assert(st.wDay == result.wDay);
10041 assert(st.wHour == result.wHour);
10042 assert(st.wMinute == result.wMinute);
10043 assert(st.wSecond == result.wSecond);
10044 assert(st.wMilliseconds == result.wMilliseconds);
10045
10046 static void testScope(scope ref SysTime st) @safe
10047 {
10048 auto result = SysTimeToSYSTEMTIME(st);
10049 }
10050 }
10051
10052 private enum hnsecsFrom1601 = 504_911_232_000_000_000L;
10053
10054 long FILETIMEToStdTime(scope const FILETIME* ft) @safe
10055 {
10056 ULARGE_INTEGER ul;
10057 ul.HighPart = ft.dwHighDateTime;
10058 ul.LowPart = ft.dwLowDateTime;
10059 ulong tempHNSecs = ul.QuadPart;
10060
10061 if (tempHNSecs > long.max - hnsecsFrom1601)
10062 throw new DateTimeException("The given FILETIME cannot be represented as a stdTime value.");
10063
10064 return cast(long) tempHNSecs + hnsecsFrom1601;
10065 }
10066
10067 SysTime FILETIMEToSysTime(scope const FILETIME* ft, immutable TimeZone tz = LocalTime()) @safe
10068 {
10069 auto sysTime = SysTime(FILETIMEToStdTime(ft), UTC());
10070 sysTime.timezone = tz;
10071 return sysTime;
10072 }
10073
10074 @system unittest
10075 {
10076 auto sysTime = Clock.currTime(UTC());
10077 SYSTEMTIME st = void;
10078 GetSystemTime(&st);
10079
10080 FILETIME ft = void;
10081 SystemTimeToFileTime(&st, &ft);
10082
10083 auto converted = FILETIMEToSysTime(&ft);
10084
10085 import core.time : abs;
10086 assert(abs((converted - sysTime)) <= dur!"seconds"(2));
10087
10088 static void testScope(scope FILETIME* ft) @safe
10089 {
10090 auto result = FILETIMEToSysTime(ft);
10091 }
10092 }
10093
10094
10095 FILETIME stdTimeToFILETIME(long stdTime) @safe
10096 {
10097 if (stdTime < hnsecsFrom1601)
10098 throw new DateTimeException("The given stdTime value cannot be represented as a FILETIME.");
10099
10100 ULARGE_INTEGER ul;
10101 ul.QuadPart = cast(ulong) stdTime - hnsecsFrom1601;
10102
10103 FILETIME ft;
10104 ft.dwHighDateTime = ul.HighPart;
10105 ft.dwLowDateTime = ul.LowPart;
10106
10107 return ft;
10108 }
10109
10110 FILETIME SysTimeToFILETIME(scope SysTime sysTime) @safe
10111 {
10112 return stdTimeToFILETIME(sysTime.stdTime);
10113 }
10114
10115 @system unittest
10116 {
10117 SYSTEMTIME st = void;
10118 GetSystemTime(&st);
10119
10120 FILETIME ft = void;
10121 SystemTimeToFileTime(&st, &ft);
10122 auto sysTime = FILETIMEToSysTime(&ft, UTC());
10123
10124 FILETIME result = SysTimeToFILETIME(sysTime);
10125
10126 assert(ft.dwLowDateTime == result.dwLowDateTime);
10127 assert(ft.dwHighDateTime == result.dwHighDateTime);
10128
10129 static void testScope(scope ref SysTime st) @safe
10130 {
10131 auto result = SysTimeToFILETIME(st);
10132 }
10133 }
10134 }
10135
10136
10137 /++
10138 Type representing the DOS file date/time format.
10139 +/
10140 alias DosFileTime = uint;
10141
10142 /++
10143 Converts from DOS file date/time to $(LREF SysTime).
10144
10145 Params:
10146 dft = The DOS file time to convert.
10147 tz = The time zone which the DOS file time is assumed to be in.
10148
10149 Throws:
10150 $(REF DateTimeException,std,datetime,date) if the `DosFileTime` is
10151 invalid.
10152 +/
10153 SysTime DosFileTimeToSysTime(DosFileTime dft, immutable TimeZone tz = LocalTime()) @safe
10154 {
10155 uint dt = cast(uint) dft;
10156
10157 if (dt == 0)
10158 throw new DateTimeException("Invalid DosFileTime.");
10159
10160 int year = ((dt >> 25) & 0x7F) + 1980;
10161 int month = ((dt >> 21) & 0x0F); // 1 .. 12
10162 int dayOfMonth = ((dt >> 16) & 0x1F); // 1 .. 31
10163 int hour = (dt >> 11) & 0x1F; // 0 .. 23
10164 int minute = (dt >> 5) & 0x3F; // 0 .. 59
10165 int second = (dt << 1) & 0x3E; // 0 .. 58 (in 2 second increments)
10166
10167 try
10168 return SysTime(DateTime(year, month, dayOfMonth, hour, minute, second), tz);
10169 catch (DateTimeException dte)
10170 throw new DateTimeException("Invalid DosFileTime", __FILE__, __LINE__, dte);
10171 }
10172
10173 ///
10174 @safe unittest
10175 {
10176 import std.datetime.date : DateTime;
10177
10178 assert(DosFileTimeToSysTime(0b00000000001000010000000000000000) == SysTime(DateTime(1980, 1, 1, 0, 0, 0)));
10179 assert(DosFileTimeToSysTime(0b11111111100111111011111101111101) == SysTime(DateTime(2107, 12, 31, 23, 59, 58)));
10180 assert(DosFileTimeToSysTime(0x3E3F8456) == SysTime(DateTime(2011, 1, 31, 16, 34, 44)));
10181 }
10182
10183 @safe unittest
10184 {
testScope(scope ref DosFileTime dft)10185 static void testScope(scope ref DosFileTime dft) @safe
10186 {
10187 auto result = DosFileTimeToSysTime(dft);
10188 }
10189 }
10190
10191
10192 /++
10193 Converts from $(LREF SysTime) to DOS file date/time.
10194
10195 Params:
10196 sysTime = The $(LREF SysTime) to convert.
10197
10198 Throws:
10199 $(REF DateTimeException,std,datetime,date) if the given
10200 $(LREF SysTime) cannot be converted to a `DosFileTime`.
10201 +/
SysTimeToDosFileTime(scope SysTime sysTime)10202 DosFileTime SysTimeToDosFileTime(scope SysTime sysTime) @safe
10203 {
10204 auto dateTime = cast(DateTime) sysTime;
10205
10206 if (dateTime.year < 1980)
10207 throw new DateTimeException("DOS File Times cannot hold dates prior to 1980.");
10208
10209 if (dateTime.year > 2107)
10210 throw new DateTimeException("DOS File Times cannot hold dates past 2107.");
10211
10212 uint retval = 0;
10213 retval = (dateTime.year - 1980) << 25;
10214 retval |= (dateTime.month & 0x0F) << 21;
10215 retval |= (dateTime.day & 0x1F) << 16;
10216 retval |= (dateTime.hour & 0x1F) << 11;
10217 retval |= (dateTime.minute & 0x3F) << 5;
10218 retval |= (dateTime.second >> 1) & 0x1F;
10219
10220 return cast(DosFileTime) retval;
10221 }
10222
10223 ///
10224 @safe unittest
10225 {
10226 import std.datetime.date : DateTime;
10227
10228 assert(SysTimeToDosFileTime(SysTime(DateTime(1980, 1, 1, 0, 0, 0))) == 0b00000000001000010000000000000000);
10229 assert(SysTimeToDosFileTime(SysTime(DateTime(2107, 12, 31, 23, 59, 58))) == 0b11111111100111111011111101111101);
10230 assert(SysTimeToDosFileTime(SysTime(DateTime(2011, 1, 31, 16, 34, 44))) == 0x3E3F8456);
10231 }
10232
10233 @safe unittest
10234 {
testScope(scope ref SysTime st)10235 static void testScope(scope ref SysTime st) @safe
10236 {
10237 auto result = SysTimeToDosFileTime(st);
10238 }
10239 }
10240
10241
10242 /++
10243 The given array of `char` or random-access range of `char` or
10244 `ubyte` is expected to be in the format specified in
10245 $(HTTP tools.ietf.org/html/rfc5322, RFC 5322) section 3.3 with the
10246 grammar rule $(I date-time). It is the date-time format commonly used in
10247 internet messages such as e-mail and HTTP. The corresponding
10248 $(LREF SysTime) will be returned.
10249
10250 RFC 822 was the original spec (hence the function's name), whereas RFC 5322
10251 is the current spec.
10252
10253 The day of the week is ignored beyond verifying that it's a valid day of the
10254 week, as the day of the week can be inferred from the date. It is not
10255 checked whether the given day of the week matches the actual day of the week
10256 of the given date (though it is technically invalid per the spec if the
10257 day of the week doesn't match the actual day of the week of the given date).
10258
10259 If the time zone is `"-0000"` (or considered to be equivalent to
10260 `"-0000"` by section 4.3 of the spec), a
10261 $(REF SimpleTimeZone,std,datetime,timezone) with a utc offset of `0` is
10262 used rather than $(REF UTC,std,datetime,timezone), whereas `"+0000"` uses
10263 $(REF UTC,std,datetime,timezone).
10264
10265 Note that because $(LREF SysTime) does not currently support having a second
10266 value of 60 (as is sometimes done for leap seconds), if the date-time value
10267 does have a value of 60 for the seconds, it is treated as 59.
10268
10269 The one area in which this function violates RFC 5322 is that it accepts
10270 `"\n"` in folding whitespace in the place of `"\r\n"`, because the
10271 HTTP spec requires it.
10272
10273 Throws:
10274 $(REF DateTimeException,std,datetime,date) if the given string doesn't
10275 follow the grammar for a date-time field or if the resulting
10276 $(LREF SysTime) is invalid.
10277 +/
parseRFC822DateTime()10278 SysTime parseRFC822DateTime()(scope const char[] value) @safe
10279 {
10280 import std.string : representation;
10281 return parseRFC822DateTime(value.representation);
10282 }
10283
10284 /++ Ditto +/
10285 SysTime parseRFC822DateTime(R)(scope R value)
10286 if (isRandomAccessRange!R && hasSlicing!R && hasLength!R &&
10287 (is(immutable ElementType!R == immutable char) || is(immutable ElementType!R == immutable ubyte)))
10288 {
10289 import std.algorithm.searching : find, all;
10290 import std.ascii : isDigit, isAlpha, isPrintable;
10291 import std.conv : to;
10292 import std.functional : not;
10293 import std.string : capitalize, format;
10294 import std.traits : EnumMembers, isArray;
10295 import std.typecons : Rebindable;
10296
10297 void stripAndCheckLen(R valueBefore, size_t minLen, size_t line = __LINE__)
10298 {
10299 value = _stripCFWS(valueBefore);
10300 if (value.length < minLen)
10301 throw new DateTimeException("date-time value too short", __FILE__, line);
10302 }
10303 stripAndCheckLen(value, "7Dec1200:00A".length);
10304
10305 static if (isArray!R && (is(ElementEncodingType!R == char) || is(ElementEncodingType!R == ubyte)))
10306 {
sliceAsString(R str)10307 static string sliceAsString(R str) @trusted
10308 {
10309 return cast(string) str;
10310 }
10311 }
10312 else
10313 {
10314 char[4] temp;
sliceAsString(R str)10315 char[] sliceAsString(R str) @trusted
10316 {
10317 size_t i = 0;
10318 foreach (c; str)
10319 temp[i++] = cast(char) c;
10320 return temp[0 .. str.length];
10321 }
10322 }
10323
10324 // day-of-week
10325 if (isAlpha(value[0]))
10326 {
10327 auto dowStr = sliceAsString(value[0 .. 3]);
10328 switch (dowStr)
10329 {
10330 foreach (dow; EnumMembers!DayOfWeek)
10331 {
10332 enum dowC = capitalize(to!string(dow));
10333 case dowC:
10334 goto afterDoW;
10335 }
10336 default: throw new DateTimeException(format("Invalid day-of-week: %s", dowStr));
10337 }
10338 afterDoW: stripAndCheckLen(value[3 .. value.length], ",7Dec1200:00A".length);
10339 if (value[0] != ',')
10340 throw new DateTimeException("day-of-week missing comma");
10341 stripAndCheckLen(value[1 .. value.length], "7Dec1200:00A".length);
10342 }
10343
10344 // day
10345 immutable digits = isDigit(value[1]) ? 2 : 1;
10346 immutable day = _convDigits!short(value[0 .. digits]);
10347 if (day == -1)
10348 throw new DateTimeException("Invalid day");
10349 stripAndCheckLen(value[digits .. value.length], "Dec1200:00A".length);
10350
10351 // month
10352 Month month;
10353 {
10354 auto monStr = sliceAsString(value[0 .. 3]);
10355 switch (monStr)
10356 {
10357 foreach (mon; EnumMembers!Month)
10358 {
10359 enum monC = capitalize(to!string(mon));
10360 case monC:
10361 {
10362 month = mon;
10363 goto afterMon;
10364 }
10365 }
10366 default: throw new DateTimeException(format("Invalid month: %s", monStr));
10367 }
10368 afterMon: stripAndCheckLen(value[3 .. value.length], "1200:00A".length);
10369 }
10370
10371 // year
10372 auto found = value[2 .. value.length].find!(not!(isDigit))();
10373 size_t yearLen = value.length - found.length;
10374 if (found.length == 0)
10375 throw new DateTimeException("Invalid year");
10376 if (found[0] == ':')
10377 yearLen -= 2;
10378 auto year = _convDigits!short(value[0 .. yearLen]);
10379 if (year < 1900)
10380 {
10381 if (year == -1)
10382 throw new DateTimeException("Invalid year");
10383 if (yearLen < 4)
10384 {
10385 if (yearLen == 3)
10386 year += 1900;
10387 else if (yearLen == 2)
10388 year += year < 50 ? 2000 : 1900;
10389 else
10390 throw new DateTimeException("Invalid year. Too few digits.");
10391 }
10392 else
10393 throw new DateTimeException("Invalid year. Cannot be earlier than 1900.");
10394 }
10395 stripAndCheckLen(value[yearLen .. value.length], "00:00A".length);
10396
10397 // hour
10398 immutable hour = _convDigits!short(value[0 .. 2]);
10399 stripAndCheckLen(value[2 .. value.length], ":00A".length);
10400 if (value[0] != ':')
10401 throw new DateTimeException("Invalid hour");
10402 stripAndCheckLen(value[1 .. value.length], "00A".length);
10403
10404 // minute
10405 immutable minute = _convDigits!short(value[0 .. 2]);
10406 stripAndCheckLen(value[2 .. value.length], "A".length);
10407
10408 // second
10409 short second;
10410 if (value[0] == ':')
10411 {
10412 stripAndCheckLen(value[1 .. value.length], "00A".length);
10413 second = _convDigits!short(value[0 .. 2]);
10414 // this is just if/until SysTime is sorted out to fully support leap seconds
10415 if (second == 60)
10416 second = 59;
10417 stripAndCheckLen(value[2 .. value.length], "A".length);
10418 }
10419
parseTZ(int sign)10420 immutable(TimeZone) parseTZ(int sign)
10421 {
10422 if (value.length < 5)
10423 throw new DateTimeException("Invalid timezone");
10424 immutable zoneHours = _convDigits!short(value[1 .. 3]);
10425 immutable zoneMinutes = _convDigits!short(value[3 .. 5]);
10426 if (zoneHours == -1 || zoneMinutes == -1 || zoneMinutes > 59)
10427 throw new DateTimeException("Invalid timezone");
10428 value = value[5 .. value.length];
10429 immutable utcOffset = (dur!"hours"(zoneHours) + dur!"minutes"(zoneMinutes)) * sign;
10430 if (utcOffset == Duration.zero)
10431 {
10432 return sign == 1 ? cast(immutable(TimeZone))UTC()
10433 : cast(immutable(TimeZone))new immutable SimpleTimeZone(Duration.zero);
10434 }
10435 return new immutable(SimpleTimeZone)(utcOffset);
10436 }
10437
10438 // zone
10439 Rebindable!(immutable TimeZone) tz;
10440 if (value[0] == '-')
10441 tz = parseTZ(-1);
10442 else if (value[0] == '+')
10443 tz = parseTZ(1);
10444 else
10445 {
10446 // obs-zone
10447 immutable tzLen = value.length - find(value, ' ', '\t', '(')[0].length;
10448 switch (sliceAsString(value[0 .. tzLen <= 4 ? tzLen : 4]))
10449 {
10450 case "UT": case "GMT": tz = UTC(); break;
10451 case "EST": tz = new immutable SimpleTimeZone(dur!"hours"(-5)); break;
10452 case "EDT": tz = new immutable SimpleTimeZone(dur!"hours"(-4)); break;
10453 case "CST": tz = new immutable SimpleTimeZone(dur!"hours"(-6)); break;
10454 case "CDT": tz = new immutable SimpleTimeZone(dur!"hours"(-5)); break;
10455 case "MST": tz = new immutable SimpleTimeZone(dur!"hours"(-7)); break;
10456 case "MDT": tz = new immutable SimpleTimeZone(dur!"hours"(-6)); break;
10457 case "PST": tz = new immutable SimpleTimeZone(dur!"hours"(-8)); break;
10458 case "PDT": tz = new immutable SimpleTimeZone(dur!"hours"(-7)); break;
10459 case "J": case "j": throw new DateTimeException("Invalid timezone");
10460 default:
10461 {
10462 if (all!(isAlpha)(value[0 .. tzLen]))
10463 {
10464 tz = new immutable SimpleTimeZone(Duration.zero);
10465 break;
10466 }
10467 throw new DateTimeException("Invalid timezone");
10468 }
10469 }
10470 value = value[tzLen .. value.length];
10471 }
10472
10473 // This is kind of arbitrary. Technically, nothing but CFWS is legal past
10474 // the end of the timezone, but we don't want to be picky about that in a
10475 // function that's just parsing rather than validating. So, the idea here is
10476 // that if the next character is printable (and not part of CFWS), then it
10477 // might be part of the timezone and thus affect what the timezone was
10478 // supposed to be, so we'll throw, but otherwise, we'll just ignore it.
10479 if (!value.empty && isPrintable(value[0]) && value[0] != ' ' && value[0] != '(')
10480 throw new DateTimeException("Invalid timezone");
10481
10482 try
10483 return SysTime(DateTime(year, month, day, hour, minute, second), tz);
10484 catch (DateTimeException dte)
10485 throw new DateTimeException("date-time format is correct, but the resulting SysTime is invalid.", dte);
10486 }
10487
10488 ///
10489 @safe unittest
10490 {
10491 import core.time : hours;
10492 import std.datetime.date : DateTime, DateTimeException;
10493 import std.datetime.timezone : SimpleTimeZone, UTC;
10494 import std.exception : assertThrown;
10495
10496 auto tz = new immutable SimpleTimeZone(hours(-8));
10497 assert(parseRFC822DateTime("Sat, 6 Jan 1990 12:14:19 -0800") ==
10498 SysTime(DateTime(1990, 1, 6, 12, 14, 19), tz));
10499
10500 assert(parseRFC822DateTime("9 Jul 2002 13:11 +0000") ==
10501 SysTime(DateTime(2002, 7, 9, 13, 11, 0), UTC()));
10502
10503 auto badStr = "29 Feb 2001 12:17:16 +0200";
10504 assertThrown!DateTimeException(parseRFC822DateTime(badStr));
10505 }
10506
version(StdUnittest)10507 version (StdUnittest) private void testParse822(alias cr)(string str, SysTime expected, size_t line = __LINE__)
10508 {
10509 import std.format : format;
10510 auto value = cr(str);
10511 auto result = parseRFC822DateTime(value);
10512 if (result != expected)
10513 throw new AssertError(format("wrong result. expected [%s], actual[%s]", expected, result), __FILE__, line);
10514 }
10515
version(StdUnittest)10516 version (StdUnittest) private void testBadParse822(alias cr)(string str, size_t line = __LINE__)
10517 {
10518 try
10519 parseRFC822DateTime(cr(str));
10520 catch (DateTimeException)
10521 return;
10522 throw new AssertError("No DateTimeException was thrown", __FILE__, line);
10523 }
10524
10525 @system unittest
10526 {
10527 import core.time;
10528 import std.algorithm.iteration : filter, map;
10529 import std.algorithm.searching : canFind;
10530 import std.array : array;
10531 import std.ascii : letters;
10532 import std.format : format;
10533 import std.meta : AliasSeq;
10534 import std.range : chain, iota, take;
10535 import std.stdio : writefln, writeln;
10536 import std.string : representation;
10537
10538 static struct Rand3Letters
10539 {
10540 enum empty = false;
frontRand3Letters10541 @property auto front() { return _mon; }
popFrontRand3Letters10542 void popFront()
10543 {
10544 import std.exception : assumeUnique;
10545 import std.random : rndGen;
10546 _mon = rndGen.map!(a => letters[a % letters.length])().take(3).array().assumeUnique();
10547 }
10548 string _mon;
startRand3Letters10549 static auto start() { Rand3Letters retval; retval.popFront(); return retval; }
10550 }
10551
10552 static foreach (cr; AliasSeq!(function(string a){return cast(char[]) a;},
10553 function(string a){return cast(ubyte[]) a;},
10554 function(string a){return a;},
10555 function(string a){return map!(b => cast(char) b)(a.representation);}))
10556 {(){ // workaround slow optimizations for large functions
10557 // https://issues.dlang.org/show_bug.cgi?id=2396
10558 scope(failure) writeln(typeof(cr).stringof);
10559 alias test = testParse822!cr;
10560 alias testBad = testBadParse822!cr;
10561
10562 immutable std1 = DateTime(2012, 12, 21, 13, 14, 15);
10563 immutable std2 = DateTime(2012, 12, 21, 13, 14, 0);
10564 immutable dst1 = DateTime(1976, 7, 4, 5, 4, 22);
10565 immutable dst2 = DateTime(1976, 7, 4, 5, 4, 0);
10566
10567 test("21 Dec 2012 13:14:15 +0000", SysTime(std1, UTC()));
10568 test("21 Dec 2012 13:14 +0000", SysTime(std2, UTC()));
10569 test("Fri, 21 Dec 2012 13:14 +0000", SysTime(std2, UTC()));
10570 test("Fri, 21 Dec 2012 13:14:15 +0000", SysTime(std1, UTC()));
10571
10572 test("04 Jul 1976 05:04:22 +0000", SysTime(dst1, UTC()));
10573 test("04 Jul 1976 05:04 +0000", SysTime(dst2, UTC()));
10574 test("Sun, 04 Jul 1976 05:04 +0000", SysTime(dst2, UTC()));
10575 test("Sun, 04 Jul 1976 05:04:22 +0000", SysTime(dst1, UTC()));
10576
10577 test("4 Jul 1976 05:04:22 +0000", SysTime(dst1, UTC()));
10578 test("4 Jul 1976 05:04 +0000", SysTime(dst2, UTC()));
10579 test("Sun, 4 Jul 1976 05:04 +0000", SysTime(dst2, UTC()));
10580 test("Sun, 4 Jul 1976 05:04:22 +0000", SysTime(dst1, UTC()));
10581
10582 auto badTZ = new immutable SimpleTimeZone(Duration.zero);
10583 test("21 Dec 2012 13:14:15 -0000", SysTime(std1, badTZ));
10584 test("21 Dec 2012 13:14 -0000", SysTime(std2, badTZ));
10585 test("Fri, 21 Dec 2012 13:14 -0000", SysTime(std2, badTZ));
10586 test("Fri, 21 Dec 2012 13:14:15 -0000", SysTime(std1, badTZ));
10587
10588 test("04 Jul 1976 05:04:22 -0000", SysTime(dst1, badTZ));
10589 test("04 Jul 1976 05:04 -0000", SysTime(dst2, badTZ));
10590 test("Sun, 04 Jul 1976 05:04 -0000", SysTime(dst2, badTZ));
10591 test("Sun, 04 Jul 1976 05:04:22 -0000", SysTime(dst1, badTZ));
10592
10593 test("4 Jul 1976 05:04:22 -0000", SysTime(dst1, badTZ));
10594 test("4 Jul 1976 05:04 -0000", SysTime(dst2, badTZ));
10595 test("Sun, 4 Jul 1976 05:04 -0000", SysTime(dst2, badTZ));
10596 test("Sun, 4 Jul 1976 05:04:22 -0000", SysTime(dst1, badTZ));
10597
10598 auto pst = new immutable SimpleTimeZone(dur!"hours"(-8));
10599 auto pdt = new immutable SimpleTimeZone(dur!"hours"(-7));
10600 test("21 Dec 2012 13:14:15 -0800", SysTime(std1, pst));
10601 test("21 Dec 2012 13:14 -0800", SysTime(std2, pst));
10602 test("Fri, 21 Dec 2012 13:14 -0800", SysTime(std2, pst));
10603 test("Fri, 21 Dec 2012 13:14:15 -0800", SysTime(std1, pst));
10604
10605 test("04 Jul 1976 05:04:22 -0700", SysTime(dst1, pdt));
10606 test("04 Jul 1976 05:04 -0700", SysTime(dst2, pdt));
10607 test("Sun, 04 Jul 1976 05:04 -0700", SysTime(dst2, pdt));
10608 test("Sun, 04 Jul 1976 05:04:22 -0700", SysTime(dst1, pdt));
10609
10610 test("4 Jul 1976 05:04:22 -0700", SysTime(dst1, pdt));
10611 test("4 Jul 1976 05:04 -0700", SysTime(dst2, pdt));
10612 test("Sun, 4 Jul 1976 05:04 -0700", SysTime(dst2, pdt));
10613 test("Sun, 4 Jul 1976 05:04:22 -0700", SysTime(dst1, pdt));
10614
10615 auto cet = new immutable SimpleTimeZone(dur!"hours"(1));
10616 auto cest = new immutable SimpleTimeZone(dur!"hours"(2));
10617 test("21 Dec 2012 13:14:15 +0100", SysTime(std1, cet));
10618 test("21 Dec 2012 13:14 +0100", SysTime(std2, cet));
10619 test("Fri, 21 Dec 2012 13:14 +0100", SysTime(std2, cet));
10620 test("Fri, 21 Dec 2012 13:14:15 +0100", SysTime(std1, cet));
10621
10622 test("04 Jul 1976 05:04:22 +0200", SysTime(dst1, cest));
10623 test("04 Jul 1976 05:04 +0200", SysTime(dst2, cest));
10624 test("Sun, 04 Jul 1976 05:04 +0200", SysTime(dst2, cest));
10625 test("Sun, 04 Jul 1976 05:04:22 +0200", SysTime(dst1, cest));
10626
10627 test("4 Jul 1976 05:04:22 +0200", SysTime(dst1, cest));
10628 test("4 Jul 1976 05:04 +0200", SysTime(dst2, cest));
10629 test("Sun, 4 Jul 1976 05:04 +0200", SysTime(dst2, cest));
10630 test("Sun, 4 Jul 1976 05:04:22 +0200", SysTime(dst1, cest));
10631
10632 // dst and std times are switched in the Southern Hemisphere which is why the
10633 // time zone names and DateTime variables don't match.
10634 auto cstStd = new immutable SimpleTimeZone(dur!"hours"(9) + dur!"minutes"(30));
10635 auto cstDST = new immutable SimpleTimeZone(dur!"hours"(10) + dur!"minutes"(30));
10636 test("21 Dec 2012 13:14:15 +1030", SysTime(std1, cstDST));
10637 test("21 Dec 2012 13:14 +1030", SysTime(std2, cstDST));
10638 test("Fri, 21 Dec 2012 13:14 +1030", SysTime(std2, cstDST));
10639 test("Fri, 21 Dec 2012 13:14:15 +1030", SysTime(std1, cstDST));
10640
10641 test("04 Jul 1976 05:04:22 +0930", SysTime(dst1, cstStd));
10642 test("04 Jul 1976 05:04 +0930", SysTime(dst2, cstStd));
10643 test("Sun, 04 Jul 1976 05:04 +0930", SysTime(dst2, cstStd));
10644 test("Sun, 04 Jul 1976 05:04:22 +0930", SysTime(dst1, cstStd));
10645
10646 test("4 Jul 1976 05:04:22 +0930", SysTime(dst1, cstStd));
10647 test("4 Jul 1976 05:04 +0930", SysTime(dst2, cstStd));
10648 test("Sun, 4 Jul 1976 05:04 +0930", SysTime(dst2, cstStd));
10649 test("Sun, 4 Jul 1976 05:04:22 +0930", SysTime(dst1, cstStd));
10650
foreach(int i,mon;_monthNames)10651 foreach (int i, mon; _monthNames)
10652 {
10653 test(format("17 %s 2012 00:05:02 +0000", mon), SysTime(DateTime(2012, i + 1, 17, 0, 5, 2), UTC()));
10654 test(format("17 %s 2012 00:05 +0000", mon), SysTime(DateTime(2012, i + 1, 17, 0, 5, 0), UTC()));
10655 }
10656
10657 import std.uni : toLower, toUpper;
10658 foreach (mon; chain(_monthNames[].map!(a => toLower(a))(),
10659 _monthNames[].map!(a => toUpper(a))(),
10660 ["Jam", "Jen", "Fec", "Fdb", "Mas", "Mbr", "Aps", "Aqr", "Mai", "Miy",
10661 "Jum", "Jbn", "Jup", "Jal", "Aur", "Apg", "Sem", "Sap", "Ocm", "Odt",
10662 "Nom", "Nav", "Dem", "Dac"],
10663 Rand3Letters.start().filter!(a => !_monthNames[].canFind(a)).take(20)))
10664 {
10665 scope(failure) writefln("Month: %s", mon);
10666 testBad(format("17 %s 2012 00:05:02 +0000", mon));
10667 testBad(format("17 %s 2012 00:05 +0000", mon));
10668 }
10669
10670 immutable string[7] daysOfWeekNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
10671
10672 {
10673 auto start = SysTime(DateTime(2012, 11, 11, 9, 42, 0), UTC());
10674 int day = 11;
10675
foreach(int i,dow;daysOfWeekNames)10676 foreach (int i, dow; daysOfWeekNames)
10677 {
10678 auto curr = start + dur!"days"(i);
10679 test(format("%s, %s Nov 2012 09:42:00 +0000", dow, day), curr);
10680 test(format("%s, %s Nov 2012 09:42 +0000", dow, day++), curr);
10681
10682 // Whether the day of the week matches the date is ignored.
10683 test(format("%s, 11 Nov 2012 09:42:00 +0000", dow), start);
10684 test(format("%s, 11 Nov 2012 09:42 +0000", dow), start);
10685 }
10686 }
10687
10688 foreach (dow; chain(daysOfWeekNames[].map!(a => toLower(a))(),
10689 daysOfWeekNames[].map!(a => toUpper(a))(),
10690 ["Sum", "Spn", "Mom", "Man", "Tuf", "Tae", "Wem", "Wdd", "The", "Tur",
10691 "Fro", "Fai", "San", "Sut"],
10692 Rand3Letters.start().filter!(a => !daysOfWeekNames[].canFind(a)).take(20)))
10693 {
10694 scope(failure) writefln("Day of Week: %s", dow);
10695 testBad(format("%s, 11 Nov 2012 09:42:00 +0000", dow));
10696 testBad(format("%s, 11 Nov 2012 09:42 +0000", dow));
10697 }
10698
10699 testBad("31 Dec 1899 23:59:59 +0000");
10700 test("01 Jan 1900 00:00:00 +0000", SysTime(Date(1900, 1, 1), UTC()));
10701 test("01 Jan 1900 00:00:00 -0000", SysTime(Date(1900, 1, 1),
10702 new immutable SimpleTimeZone(Duration.zero)));
10703 test("01 Jan 1900 00:00:00 -0700", SysTime(Date(1900, 1, 1),
10704 new immutable SimpleTimeZone(dur!"hours"(-7))));
10705
10706 {
10707 auto st1 = SysTime(Date(1900, 1, 1), UTC());
10708 auto st2 = SysTime(Date(1900, 1, 1), new immutable SimpleTimeZone(dur!"hours"(-11)));
10709 foreach (i; 1900 .. 2102)
10710 {
10711 test(format("1 Jan %05d 00:00 +0000", i), st1);
10712 test(format("1 Jan %05d 00:00 -1100", i), st2);
10713 st1.add!"years"(1);
10714 st2.add!"years"(1);
10715 }
10716 st1.year = 9998;
10717 st2.year = 9998;
10718 foreach (i; 9998 .. 11_002)
10719 {
10720 test(format("1 Jan %05d 00:00 +0000", i), st1);
10721 test(format("1 Jan %05d 00:00 -1100", i), st2);
10722 st1.add!"years"(1);
10723 st2.add!"years"(1);
10724 }
10725 }
10726
10727 testBad("12 Feb 1907 23:17:09 0000");
10728 testBad("12 Feb 1907 23:17:09 +000");
10729 testBad("12 Feb 1907 23:17:09 -000");
10730 testBad("12 Feb 1907 23:17:09 +00000");
10731 testBad("12 Feb 1907 23:17:09 -00000");
10732 testBad("12 Feb 1907 23:17:09 +A");
10733 testBad("12 Feb 1907 23:17:09 +PST");
10734 testBad("12 Feb 1907 23:17:09 -A");
10735 testBad("12 Feb 1907 23:17:09 -PST");
10736
10737 // test trailing stuff that gets ignored
10738 {
10739 foreach (c; chain(iota(0, 33), ['('], iota(127, ubyte.max + 1)))
10740 {
10741 scope(failure) writefln("c: %d", c);
10742 test(format("21 Dec 2012 13:14:15 +0000%c", cast(char) c), SysTime(std1, UTC()));
10743 test(format("21 Dec 2012 13:14:15 +0000%c ", cast(char) c), SysTime(std1, UTC()));
10744 test(format("21 Dec 2012 13:14:15 +0000%chello", cast(char) c), SysTime(std1, UTC()));
10745 }
10746 }
10747
10748 // test trailing stuff that doesn't get ignored
10749 {
10750 foreach (c; chain(iota(33, '('), iota('(' + 1, 127)))
10751 {
10752 scope(failure) writefln("c: %d", c);
10753 testBad(format("21 Dec 2012 13:14:15 +0000%c", cast(char) c));
10754 testBad(format("21 Dec 2012 13:14:15 +0000%c ", cast(char) c));
10755 testBad(format("21 Dec 2012 13:14:15 +0000%chello", cast(char) c));
10756 }
10757 }
10758
10759 testBad("32 Jan 2012 12:13:14 -0800");
10760 testBad("31 Jan 2012 24:13:14 -0800");
10761 testBad("31 Jan 2012 12:60:14 -0800");
10762 testBad("31 Jan 2012 12:13:61 -0800");
10763 testBad("31 Jan 2012 12:13:14 -0860");
10764 test("31 Jan 2012 12:13:14 -0859",
10765 SysTime(DateTime(2012, 1, 31, 12, 13, 14),
10766 new immutable SimpleTimeZone(dur!"hours"(-8) + dur!"minutes"(-59))));
10767
10768 // leap-seconds
10769 test("21 Dec 2012 15:59:60 -0800", SysTime(DateTime(2012, 12, 21, 15, 59, 59), pst));
10770
10771 // FWS
10772 test("Sun,4 Jul 1976 05:04 +0930", SysTime(dst2, cstStd));
10773 test("Sun,4 Jul 1976 05:04:22 +0930", SysTime(dst1, cstStd));
10774 test("Sun,4 Jul 1976 05:04 +0930 (foo)", SysTime(dst2, cstStd));
10775 test("Sun,4 Jul 1976 05:04:22 +0930 (foo)", SysTime(dst1, cstStd));
10776 test("Sun,4 \r\n Jul \r\n 1976 \r\n 05:04 \r\n +0930 \r\n (foo)", SysTime(dst2, cstStd));
10777 test("Sun,4 \r\n Jul \r\n 1976 \r\n 05:04:22 \r\n +0930 \r\n (foo)", SysTime(dst1, cstStd));
10778
10779 auto str = "01 Jan 2012 12:13:14 -0800 ";
10780 test(str, SysTime(DateTime(2012, 1, 1, 12, 13, 14), new immutable SimpleTimeZone(hours(-8))));
10781 foreach (i; 0 .. str.length)
10782 {
10783 auto currStr = str.dup;
10784 currStr[i] = 'x';
10785 scope(failure) writefln("failed: %s", currStr);
10786 testBad(cast(string) currStr);
10787 }
10788 foreach (i; 2 .. str.length)
10789 {
10790 auto currStr = str[0 .. $ - i];
10791 scope(failure) writefln("failed: %s", currStr);
10792 testBad(cast(string) currStr);
10793 testBad((cast(string) currStr) ~ " ");
10794 }
10795 }();}
10796
testScope(scope ref string str)10797 static void testScope(scope ref string str) @safe
10798 {
10799 auto result = parseRFC822DateTime(str);
10800 }
10801 }
10802
10803 // Obsolete Format per section 4.3 of RFC 5322.
10804 @system unittest
10805 {
10806 import std.algorithm.iteration : filter, map;
10807 import std.ascii : letters;
10808 import std.exception : collectExceptionMsg;
10809 import std.format : format;
10810 import std.meta : AliasSeq;
10811 import std.range : chain, iota;
10812 import std.stdio : writefln, writeln;
10813 import std.string : representation;
10814
10815 auto std1 = SysTime(DateTime(2012, 12, 21, 13, 14, 15), UTC());
10816 auto std2 = SysTime(DateTime(2012, 12, 21, 13, 14, 0), UTC());
10817 auto std3 = SysTime(DateTime(1912, 12, 21, 13, 14, 15), UTC());
10818 auto std4 = SysTime(DateTime(1912, 12, 21, 13, 14, 0), UTC());
10819 auto dst1 = SysTime(DateTime(1976, 7, 4, 5, 4, 22), UTC());
10820 auto dst2 = SysTime(DateTime(1976, 7, 4, 5, 4, 0), UTC());
10821 auto tooLate1 = SysTime(Date(10_000, 1, 1), UTC());
10822 auto tooLate2 = SysTime(DateTime(12_007, 12, 31, 12, 22, 19), UTC());
10823
10824 static foreach (cr; AliasSeq!(function(string a){return cast(char[]) a;},
10825 function(string a){return cast(ubyte[]) a;},
10826 function(string a){return a;},
10827 function(string a){return map!(b => cast(char) b)(a.representation);}))
10828 {(){ // workaround slow optimizations for large functions
10829 // https://issues.dlang.org/show_bug.cgi?id=2396
10830 scope(failure) writeln(typeof(cr).stringof);
10831 alias test = testParse822!cr;
10832 {
10833 auto list = ["", " ", " \r\n\t", "\t\r\n (hello world( frien(dog)) silly \r\n ) \t\t \r\n ()",
10834 " \n ", "\t\n\t", " \n\t (foo) \n (bar) \r\n (baz) \n "];
10835
foreach(i,cfws;list)10836 foreach (i, cfws; list)
10837 {
10838 scope(failure) writefln("i: %s", i);
10839
10840 test(format("%1$s21%1$sDec%1$s2012%1$s13:14:15%1$s+0000%1$s", cfws), std1);
10841 test(format("%1$s21%1$sDec%1$s2012%1$s13:14%1$s+0000%1$s", cfws), std2);
10842 test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s2012%1$s13:14%1$s+0000%1$s", cfws), std2);
10843 test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s2012%1$s13:14:15%1$s+0000%1$s", cfws), std1);
10844
10845 test(format("%1$s04%1$sJul%1$s1976%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10846 test(format("%1$s04%1$sJul%1$s1976%1$s05:04%1$s+0000%1$s", cfws), dst2);
10847 test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s1976%1$s05:04%1$s+0000%1$s", cfws), dst2);
10848 test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s1976%1$s05:04:22 +0000%1$s", cfws), dst1);
10849
10850 test(format("%1$s4%1$sJul%1$s1976%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10851 test(format("%1$s4%1$sJul%1$s1976%1$s05:04%1$s+0000%1$s", cfws), dst2);
10852 test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s1976%1$s05:04%1$s+0000%1$s", cfws), dst2);
10853 test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s1976%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10854
10855 test(format("%1$s21%1$sDec%1$s12%1$s13:14:15%1$s+0000%1$s", cfws), std1);
10856 test(format("%1$s21%1$sDec%1$s12%1$s13:14%1$s+0000%1$s", cfws), std2);
10857 test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s12%1$s13:14%1$s+0000%1$s", cfws), std2);
10858 test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s12%1$s13:14:15%1$s+0000%1$s", cfws), std1);
10859
10860 test(format("%1$s04%1$sJul%1$s76%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10861 test(format("%1$s04%1$sJul%1$s76%1$s05:04%1$s+0000%1$s", cfws), dst2);
10862 test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s76%1$s05:04%1$s+0000%1$s", cfws), dst2);
10863 test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s76%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10864
10865 test(format("%1$s4%1$sJul%1$s76 05:04:22%1$s+0000%1$s", cfws), dst1);
10866 test(format("%1$s4%1$sJul%1$s76 05:04%1$s+0000%1$s", cfws), dst2);
10867 test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s76%1$s05:04%1$s+0000%1$s", cfws), dst2);
10868 test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s76%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10869
10870 test(format("%1$s21%1$sDec%1$s012%1$s13:14:15%1$s+0000%1$s", cfws), std3);
10871 test(format("%1$s21%1$sDec%1$s012%1$s13:14%1$s+0000%1$s", cfws), std4);
10872 test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s012%1$s13:14%1$s+0000%1$s", cfws), std4);
10873 test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s012%1$s13:14:15%1$s+0000%1$s", cfws), std3);
10874
10875 test(format("%1$s04%1$sJul%1$s076%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10876 test(format("%1$s04%1$sJul%1$s076%1$s05:04%1$s+0000%1$s", cfws), dst2);
10877 test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s076%1$s05:04%1$s+0000%1$s", cfws), dst2);
10878 test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s076%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10879
10880 test(format("%1$s4%1$sJul%1$s076%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10881 test(format("%1$s4%1$sJul%1$s076%1$s05:04%1$s+0000%1$s", cfws), dst2);
10882 test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s076%1$s05:04%1$s+0000%1$s", cfws), dst2);
10883 test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s076%1$s05:04:22%1$s+0000%1$s", cfws), dst1);
10884
10885 test(format("%1$s1%1$sJan%1$s10000%1$s00:00:00%1$s+0000%1$s", cfws), tooLate1);
10886 test(format("%1$s31%1$sDec%1$s12007%1$s12:22:19%1$s+0000%1$s", cfws), tooLate2);
10887 test(format("%1$sSat%1$s,%1$s1%1$sJan%1$s10000%1$s00:00:00%1$s+0000%1$s", cfws), tooLate1);
10888 test(format("%1$sSun%1$s,%1$s31%1$sDec%1$s12007%1$s12:22:19%1$s+0000%1$s", cfws), tooLate2);
10889 }
10890 }
10891
10892 // test years of 1, 2, and 3 digits.
10893 {
10894 auto st1 = SysTime(Date(2000, 1, 1), UTC());
10895 auto st2 = SysTime(Date(2000, 1, 1), new immutable SimpleTimeZone(dur!"hours"(-12)));
10896 foreach (i; 0 .. 50)
10897 {
10898 test(format("1 Jan %02d 00:00 GMT", i), st1);
10899 test(format("1 Jan %02d 00:00 -1200", i), st2);
10900 st1.add!"years"(1);
10901 st2.add!"years"(1);
10902 }
10903 }
10904
10905 {
10906 auto st1 = SysTime(Date(1950, 1, 1), UTC());
10907 auto st2 = SysTime(Date(1950, 1, 1), new immutable SimpleTimeZone(dur!"hours"(-12)));
10908 foreach (i; 50 .. 100)
10909 {
10910 test(format("1 Jan %02d 00:00 GMT", i), st1);
10911 test(format("1 Jan %02d 00:00 -1200", i), st2);
10912 st1.add!"years"(1);
10913 st2.add!"years"(1);
10914 }
10915 }
10916
10917 {
10918 auto st1 = SysTime(Date(1900, 1, 1), UTC());
10919 auto st2 = SysTime(Date(1900, 1, 1), new immutable SimpleTimeZone(dur!"hours"(-11)));
10920 foreach (i; 0 .. 1000)
10921 {
10922 test(format("1 Jan %03d 00:00 GMT", i), st1);
10923 test(format("1 Jan %03d 00:00 -1100", i), st2);
10924 st1.add!"years"(1);
10925 st2.add!"years"(1);
10926 }
10927 }
10928
10929 foreach (i; 0 .. 10)
10930 {
10931 auto str1 = cr(format("1 Jan %d 00:00 GMT", i));
10932 auto str2 = cr(format("1 Jan %d 00:00 -1200", i));
10933 assertThrown!DateTimeException(parseRFC822DateTime(str1));
10934 assertThrown!DateTimeException(parseRFC822DateTime(str1));
10935 }
10936
10937 // test time zones
10938 {
10939 auto dt = DateTime(1982, 5, 3, 12, 22, 4);
10940 test("Wed, 03 May 1982 12:22:04 UT", SysTime(dt, UTC()));
10941 test("Wed, 03 May 1982 12:22:04 GMT", SysTime(dt, UTC()));
10942 test("Wed, 03 May 1982 12:22:04 EST", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-5))));
10943 test("Wed, 03 May 1982 12:22:04 EDT", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-4))));
10944 test("Wed, 03 May 1982 12:22:04 CST", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-6))));
10945 test("Wed, 03 May 1982 12:22:04 CDT", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-5))));
10946 test("Wed, 03 May 1982 12:22:04 MST", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-7))));
10947 test("Wed, 03 May 1982 12:22:04 MDT", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-6))));
10948 test("Wed, 03 May 1982 12:22:04 PST", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-8))));
10949 test("Wed, 03 May 1982 12:22:04 PDT", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-7))));
10950
10951 auto badTZ = new immutable SimpleTimeZone(Duration.zero);
10952 foreach (dchar c; filter!(a => a != 'j' && a != 'J')(letters))
10953 {
10954 scope(failure) writefln("c: %s", c);
10955 test(format("Wed, 03 May 1982 12:22:04 %s", c), SysTime(dt, badTZ));
10956 test(format("Wed, 03 May 1982 12:22:04%s", c), SysTime(dt, badTZ));
10957 }
10958
foreach(dchar c;['j','J'])10959 foreach (dchar c; ['j', 'J'])
10960 {
10961 scope(failure) writefln("c: %s", c);
10962 assertThrown!DateTimeException(parseRFC822DateTime(cr(format("Wed, 03 May 1982 12:22:04 %s", c))));
10963 assertThrown!DateTimeException(parseRFC822DateTime(cr(format("Wed, 03 May 1982 12:22:04%s", c))));
10964 }
10965
foreach(string s;["AAA","GQW","DDT","PDA","GT","GM"])10966 foreach (string s; ["AAA", "GQW", "DDT", "PDA", "GT", "GM"])
10967 {
10968 scope(failure) writefln("s: %s", s);
10969 test(format("Wed, 03 May 1982 12:22:04 %s", s), SysTime(dt, badTZ));
10970 }
10971
10972 // test trailing stuff that gets ignored
10973 {
10974 foreach (c; chain(iota(0, 33), ['('], iota(127, ubyte.max + 1)))
10975 {
10976 scope(failure) writefln("c: %d", c);
10977 test(format("21Dec1213:14:15+0000%c", cast(char) c), std1);
10978 test(format("21Dec1213:14:15+0000%c ", cast(char) c), std1);
10979 test(format("21Dec1213:14:15+0000%chello", cast(char) c), std1);
10980 }
10981 }
10982
10983 // test trailing stuff that doesn't get ignored
10984 {
10985 foreach (c; chain(iota(33, '('), iota('(' + 1, 127)))
10986 {
10987 scope(failure) writefln("c: %d", c);
10988 assertThrown!DateTimeException(
10989 parseRFC822DateTime(cr(format("21Dec1213:14:15+0000%c", cast(char) c))));
10990 assertThrown!DateTimeException(
10991 parseRFC822DateTime(cr(format("21Dec1213:14:15+0000%c ", cast(char) c))));
10992 assertThrown!DateTimeException(
10993 parseRFC822DateTime(cr(format("21Dec1213:14:15+0000%chello", cast(char) c))));
10994 }
10995 }
10996 }
10997
10998 // test that the checks for minimum length work correctly and avoid
10999 // any RangeErrors.
11000 test("7Dec1200:00A", SysTime(DateTime(2012, 12, 7, 0, 0, 0),
11001 new immutable SimpleTimeZone(Duration.zero)));
11002 test("Fri,7Dec1200:00A", SysTime(DateTime(2012, 12, 7, 0, 0, 0),
11003 new immutable SimpleTimeZone(Duration.zero)));
11004 test("7Dec1200:00:00A", SysTime(DateTime(2012, 12, 7, 0, 0, 0),
11005 new immutable SimpleTimeZone(Duration.zero)));
11006 test("Fri,7Dec1200:00:00A", SysTime(DateTime(2012, 12, 7, 0, 0, 0),
11007 new immutable SimpleTimeZone(Duration.zero)));
11008
11009 auto tooShortMsg = collectExceptionMsg!DateTimeException(parseRFC822DateTime(""));
foreach(str;["Fri,7Dec1200:00:00","7Dec1200:00:00"])11010 foreach (str; ["Fri,7Dec1200:00:00", "7Dec1200:00:00"])
11011 {
11012 foreach (i; 0 .. str.length)
11013 {
11014 auto value = str[0 .. $ - i];
11015 scope(failure) writeln(value);
11016 assert(collectExceptionMsg!DateTimeException(parseRFC822DateTime(value)) == tooShortMsg);
11017 }
11018 }
11019 }();}
11020 }
11021
11022
11023 private:
11024
11025 /+
11026 Returns the given hnsecs as an ISO string of fractional seconds.
11027 +/
fracSecsToISOString(int hnsecs)11028 string fracSecsToISOString(int hnsecs) @safe pure nothrow
11029 {
11030 import std.array : appender;
11031 auto w = appender!string();
11032 try
11033 fracSecsToISOString(w, hnsecs);
11034 catch (Exception e)
11035 assert(0, "fracSecsToISOString() threw.");
11036 return w.data;
11037 }
11038
fracSecsToISOString(W)11039 void fracSecsToISOString(W)(ref W writer, int hnsecs)
11040 {
11041 import std.conv : toChars;
11042 import std.range : padLeft;
11043
11044 assert(hnsecs >= 0);
11045
11046 if (hnsecs == 0)
11047 return;
11048
11049 put(writer, '.');
11050 auto chars = hnsecs.toChars.padLeft('0', 7);
11051 while (chars.back == '0')
11052 chars.popBack();
11053 put(writer, chars);
11054 }
11055
11056 @safe unittest
11057 {
11058 assert(fracSecsToISOString(0) == "");
11059 assert(fracSecsToISOString(1) == ".0000001");
11060 assert(fracSecsToISOString(10) == ".000001");
11061 assert(fracSecsToISOString(100) == ".00001");
11062 assert(fracSecsToISOString(1000) == ".0001");
11063 assert(fracSecsToISOString(10_000) == ".001");
11064 assert(fracSecsToISOString(100_000) == ".01");
11065 assert(fracSecsToISOString(1_000_000) == ".1");
11066 assert(fracSecsToISOString(1_000_001) == ".1000001");
11067 assert(fracSecsToISOString(1_001_001) == ".1001001");
11068 assert(fracSecsToISOString(1_071_601) == ".1071601");
11069 assert(fracSecsToISOString(1_271_641) == ".1271641");
11070 assert(fracSecsToISOString(9_999_999) == ".9999999");
11071 assert(fracSecsToISOString(9_999_990) == ".999999");
11072 assert(fracSecsToISOString(9_999_900) == ".99999");
11073 assert(fracSecsToISOString(9_999_000) == ".9999");
11074 assert(fracSecsToISOString(9_990_000) == ".999");
11075 assert(fracSecsToISOString(9_900_000) == ".99");
11076 assert(fracSecsToISOString(9_000_000) == ".9");
11077 assert(fracSecsToISOString(999) == ".0000999");
11078 assert(fracSecsToISOString(9990) == ".000999");
11079 assert(fracSecsToISOString(99_900) == ".00999");
11080 assert(fracSecsToISOString(999_000) == ".0999");
11081 }
11082
11083
11084 /+
11085 Returns a Duration corresponding to to the given ISO string of
11086 fractional seconds.
11087 +/
11088 static Duration fracSecsFromISOString(S)(scope const S isoString) @safe pure
11089 if (isSomeString!S)
11090 {
11091 import std.algorithm.searching : all;
11092 import std.ascii : isDigit;
11093 import std.conv : to;
11094 import std.string : representation;
11095
11096 if (isoString.empty)
11097 return Duration.zero;
11098
11099 auto str = isoString.representation;
11100
11101 enforce(str[0] == '.', new DateTimeException("Invalid ISO String"));
11102 str.popFront();
11103
11104 enforce(!str.empty && all!isDigit(str), new DateTimeException("Invalid ISO String"));
11105
11106 dchar[7] fullISOString = void;
foreach(i,ref dchar c;fullISOString)11107 foreach (i, ref dchar c; fullISOString)
11108 {
11109 if (i < str.length)
11110 c = str[i];
11111 else
11112 c = '0';
11113 }
11114
11115 return hnsecs(to!int(fullISOString[]));
11116 }
11117
11118 @safe unittest
11119 {
11120 import core.time;
testFSInvalid(string isoString)11121 static void testFSInvalid(string isoString)
11122 {
11123 fracSecsFromISOString(isoString);
11124 }
11125
11126 assertThrown!DateTimeException(testFSInvalid("."));
11127 assertThrown!DateTimeException(testFSInvalid("0."));
11128 assertThrown!DateTimeException(testFSInvalid("0"));
11129 assertThrown!DateTimeException(testFSInvalid("0000000"));
11130 assertThrown!DateTimeException(testFSInvalid("T"));
11131 assertThrown!DateTimeException(testFSInvalid("T."));
11132 assertThrown!DateTimeException(testFSInvalid(".T"));
11133 assertThrown!DateTimeException(testFSInvalid(".00000Q0"));
11134 assertThrown!DateTimeException(testFSInvalid(".000000Q"));
11135 assertThrown!DateTimeException(testFSInvalid(".0000000Q"));
11136 assertThrown!DateTimeException(testFSInvalid(".0000000000Q"));
11137
11138 assert(fracSecsFromISOString("") == Duration.zero);
11139 assert(fracSecsFromISOString(".0000001") == hnsecs(1));
11140 assert(fracSecsFromISOString(".000001") == hnsecs(10));
11141 assert(fracSecsFromISOString(".00001") == hnsecs(100));
11142 assert(fracSecsFromISOString(".0001") == hnsecs(1000));
11143 assert(fracSecsFromISOString(".001") == hnsecs(10_000));
11144 assert(fracSecsFromISOString(".01") == hnsecs(100_000));
11145 assert(fracSecsFromISOString(".1") == hnsecs(1_000_000));
11146 assert(fracSecsFromISOString(".1000001") == hnsecs(1_000_001));
11147 assert(fracSecsFromISOString(".1001001") == hnsecs(1_001_001));
11148 assert(fracSecsFromISOString(".1071601") == hnsecs(1_071_601));
11149 assert(fracSecsFromISOString(".1271641") == hnsecs(1_271_641));
11150 assert(fracSecsFromISOString(".9999999") == hnsecs(9_999_999));
11151 assert(fracSecsFromISOString(".9999990") == hnsecs(9_999_990));
11152 assert(fracSecsFromISOString(".999999") == hnsecs(9_999_990));
11153 assert(fracSecsFromISOString(".9999900") == hnsecs(9_999_900));
11154 assert(fracSecsFromISOString(".99999") == hnsecs(9_999_900));
11155 assert(fracSecsFromISOString(".9999000") == hnsecs(9_999_000));
11156 assert(fracSecsFromISOString(".9999") == hnsecs(9_999_000));
11157 assert(fracSecsFromISOString(".9990000") == hnsecs(9_990_000));
11158 assert(fracSecsFromISOString(".999") == hnsecs(9_990_000));
11159 assert(fracSecsFromISOString(".9900000") == hnsecs(9_900_000));
11160 assert(fracSecsFromISOString(".9900") == hnsecs(9_900_000));
11161 assert(fracSecsFromISOString(".99") == hnsecs(9_900_000));
11162 assert(fracSecsFromISOString(".9000000") == hnsecs(9_000_000));
11163 assert(fracSecsFromISOString(".9") == hnsecs(9_000_000));
11164 assert(fracSecsFromISOString(".0000999") == hnsecs(999));
11165 assert(fracSecsFromISOString(".0009990") == hnsecs(9990));
11166 assert(fracSecsFromISOString(".000999") == hnsecs(9990));
11167 assert(fracSecsFromISOString(".0099900") == hnsecs(99_900));
11168 assert(fracSecsFromISOString(".00999") == hnsecs(99_900));
11169 assert(fracSecsFromISOString(".0999000") == hnsecs(999_000));
11170 assert(fracSecsFromISOString(".0999") == hnsecs(999_000));
11171 assert(fracSecsFromISOString(".00000000") == Duration.zero);
11172 assert(fracSecsFromISOString(".00000001") == Duration.zero);
11173 assert(fracSecsFromISOString(".00000009") == Duration.zero);
11174 assert(fracSecsFromISOString(".1234567890") == hnsecs(1_234_567));
11175 assert(fracSecsFromISOString(".12345678901234567890") == hnsecs(1_234_567));
11176 }
11177
11178
11179 /+
11180 This function is used to split out the units without getting the remaining
11181 hnsecs.
11182
11183 Params:
11184 units = The units to split out.
11185 hnsecs = The current total hnsecs.
11186
11187 Returns:
11188 The split out value.
11189 +/
11190 long getUnitsFromHNSecs(string units)(long hnsecs) @safe pure nothrow
11191 if (validTimeUnits(units) &&
11192 CmpTimeUnits!(units, "months") < 0)
11193 {
11194 return convert!("hnsecs", units)(hnsecs);
11195 }
11196
11197 @safe unittest
11198 {
11199 auto hnsecs = 2595000000007L;
11200 immutable days = getUnitsFromHNSecs!"days"(hnsecs);
11201 assert(days == 3);
11202 assert(hnsecs == 2595000000007L);
11203 }
11204
11205
11206 /+
11207 This function is used to split out the units without getting the units but
11208 just the remaining hnsecs.
11209
11210 Params:
11211 units = The units to split out.
11212 hnsecs = The current total hnsecs.
11213
11214 Returns:
11215 The remaining hnsecs.
11216 +/
11217 long removeUnitsFromHNSecs(string units)(long hnsecs) @safe pure nothrow
11218 if (validTimeUnits(units) &&
11219 CmpTimeUnits!(units, "months") < 0)
11220 {
11221 immutable value = convert!("hnsecs", units)(hnsecs);
11222 return hnsecs - convert!(units, "hnsecs")(value);
11223 }
11224
11225 @safe unittest
11226 {
11227 auto hnsecs = 2595000000007L;
11228 auto returned = removeUnitsFromHNSecs!"days"(hnsecs);
11229 assert(returned == 3000000007);
11230 assert(hnsecs == 2595000000007L);
11231 }
11232
11233
11234 /+
11235 Strips what RFC 5322, section 3.2.2 refers to as CFWS from the left-hand
11236 side of the given range (it strips comments delimited by $(D '(') and
11237 `'`') as well as folding whitespace).
11238
11239 It is assumed that the given range contains the value of a header field and
11240 no terminating CRLF for the line (though the CRLF for folding whitespace is
11241 of course expected and stripped) and thus that the only case of CR or LF is
11242 in folding whitespace.
11243
11244 If a comment does not terminate correctly (e.g. mismatched parens) or if the
11245 the FWS is malformed, then the range will be empty when stripCWFS is done.
11246 However, only minimal validation of the content is done (e.g. quoted pairs
11247 within a comment aren't validated beyond \$LPAREN or \$RPAREN, because
11248 they're inside a comment, and thus their value doesn't matter anyway). It's
11249 only when the content does not conform to the grammar rules for FWS and thus
11250 literally cannot be parsed that content is considered invalid, and an empty
11251 range is returned.
11252
11253 Note that _stripCFWS is eager, not lazy. It does not create a new range.
11254 Rather, it pops off the CFWS from the range and returns it.
11255 +/
11256 R _stripCFWS(R)(R range)
11257 if (isRandomAccessRange!R && hasSlicing!R && hasLength!R &&
11258 (is(immutable ElementType!R == immutable char) || is(immutable ElementType!R == immutable ubyte)))
11259 {
11260 immutable e = range.length;
11261 outer: for (size_t i = 0; i < e; )
11262 {
11263 switch (range[i])
11264 {
11265 case ' ': case '\t':
11266 {
11267 ++i;
11268 break;
11269 }
11270 case '\r':
11271 {
11272 if (i + 2 < e && range[i + 1] == '\n' && (range[i + 2] == ' ' || range[i + 2] == '\t'))
11273 {
11274 i += 3;
11275 break;
11276 }
11277 break outer;
11278 }
11279 case '\n':
11280 {
11281 if (i + 1 < e && (range[i + 1] == ' ' || range[i + 1] == '\t'))
11282 {
11283 i += 2;
11284 break;
11285 }
11286 break outer;
11287 }
11288 case '(':
11289 {
11290 ++i;
11291 size_t commentLevel = 1;
11292 while (i < e)
11293 {
11294 if (range[i] == '(')
11295 ++commentLevel;
11296 else if (range[i] == ')')
11297 {
11298 ++i;
11299 if (--commentLevel == 0)
11300 continue outer;
11301 continue;
11302 }
11303 else if (range[i] == '\\')
11304 {
11305 if (++i == e)
11306 break outer;
11307 }
11308 ++i;
11309 }
11310 break outer;
11311 }
11312 default: return range[i .. e];
11313 }
11314 }
11315 return range[e .. e];
11316 }
11317
11318 @system unittest
11319 {
11320 import std.algorithm.comparison : equal;
11321 import std.algorithm.iteration : map;
11322 import std.meta : AliasSeq;
11323 import std.stdio : writeln;
11324 import std.string : representation;
11325
11326 static foreach (cr; AliasSeq!(function(string a){return cast(ubyte[]) a;},
11327 function(string a){return map!(b => cast(char) b)(a.representation);}))
11328 {
11329 scope(failure) writeln(typeof(cr).stringof);
11330
11331 assert(_stripCFWS(cr("")).empty);
11332 assert(_stripCFWS(cr("\r")).empty);
11333 assert(_stripCFWS(cr("\r\n")).empty);
11334 assert(_stripCFWS(cr("\r\n ")).empty);
11335 assert(_stripCFWS(cr(" \t\r\n")).empty);
11336 assert(equal(_stripCFWS(cr(" \t\r\n hello")), cr("hello")));
11337 assert(_stripCFWS(cr(" \t\r\nhello")).empty);
11338 assert(_stripCFWS(cr(" \t\r\n\v")).empty);
11339 assert(equal(_stripCFWS(cr("\v \t\r\n\v")), cr("\v \t\r\n\v")));
11340 assert(_stripCFWS(cr("()")).empty);
11341 assert(_stripCFWS(cr("(hello world)")).empty);
11342 assert(_stripCFWS(cr("(hello world)(hello world)")).empty);
11343 assert(_stripCFWS(cr("(hello world\r\n foo\r where's\nwaldo)")).empty);
11344 assert(_stripCFWS(cr(" \t (hello \tworld\r\n foo\r where's\nwaldo)\t\t ")).empty);
11345 assert(_stripCFWS(cr(" ")).empty);
11346 assert(_stripCFWS(cr("\t\t\t")).empty);
11347 assert(_stripCFWS(cr("\t \r\n\r \n")).empty);
11348 assert(_stripCFWS(cr("(hello world) (can't find waldo) (he's lost)")).empty);
11349 assert(_stripCFWS(cr("(hello\\) world) (can't \\(find waldo) (he's \\(\\)lost)")).empty);
11350 assert(_stripCFWS(cr("(((((")).empty);
11351 assert(_stripCFWS(cr("(((()))")).empty);
11352 assert(_stripCFWS(cr("(((())))")).empty);
11353 assert(equal(_stripCFWS(cr("(((()))))")), cr(")")));
11354 assert(equal(_stripCFWS(cr(")))))")), cr(")))))")));
11355 assert(equal(_stripCFWS(cr("()))))")), cr("))))")));
11356 assert(equal(_stripCFWS(cr(" hello hello ")), cr("hello hello ")));
11357 assert(equal(_stripCFWS(cr("\thello (world)")), cr("hello (world)")));
11358 assert(equal(_stripCFWS(cr(" \r\n \\((\\)) foo")), cr("\\((\\)) foo")));
11359 assert(equal(_stripCFWS(cr(" \r\n (\\((\\))) foo")), cr("foo")));
11360 assert(equal(_stripCFWS(cr(" \r\n (\\(())) foo")), cr(") foo")));
11361 assert(_stripCFWS(cr(" \r\n (((\\))) foo")).empty);
11362
11363 assert(_stripCFWS(cr("(hello)(hello)")).empty);
11364 assert(_stripCFWS(cr(" \r\n (hello)\r\n (hello)")).empty);
11365 assert(_stripCFWS(cr(" \r\n (hello) \r\n (hello) \r\n ")).empty);
11366 assert(_stripCFWS(cr("\t\t\t\t(hello)\t\t\t\t(hello)\t\t\t\t")).empty);
11367 assert(equal(_stripCFWS(cr(" \r\n (hello)\r\n (hello) \r\n hello")), cr("hello")));
11368 assert(equal(_stripCFWS(cr(" \r\n (hello) \r\n (hello) \r\n hello")), cr("hello")));
11369 assert(equal(_stripCFWS(cr("\t\r\n\t(hello)\r\n\t(hello)\t\r\n hello")), cr("hello")));
11370 assert(equal(_stripCFWS(cr("\t\r\n\t(hello)\t\r\n\t(hello)\t\r\n hello")), cr("hello")));
11371 assert(equal(_stripCFWS(cr(" \r\n (hello) \r\n \r\n (hello) \r\n hello")), cr("hello")));
11372 assert(equal(_stripCFWS(cr(" \r\n (hello) \r\n (hello) \r\n \r\n hello")), cr("hello")));
11373 assert(equal(_stripCFWS(cr(" \r\n \r\n (hello)\t\r\n (hello) \r\n hello")), cr("hello")));
11374 assert(equal(_stripCFWS(cr(" \r\n\t\r\n\t(hello)\t\r\n (hello) \r\n hello")), cr("hello")));
11375
11376 assert(equal(_stripCFWS(cr(" (\r\n ( \r\n ) \r\n ) foo")), cr("foo")));
11377 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n ) foo")), cr("foo")));
11378 assert(equal(_stripCFWS(cr(" (\t\r\n ( \r\n ) \r\n ) foo")), cr("foo")));
11379 assert(equal(_stripCFWS(cr(" (\r\n\t( \r\n ) \r\n ) foo")), cr("foo")));
11380 assert(equal(_stripCFWS(cr(" ( \r\n (\t\r\n ) \r\n ) foo")), cr("foo")));
11381 assert(equal(_stripCFWS(cr(" ( \r\n (\r\n ) \r\n ) foo")), cr("foo")));
11382 assert(equal(_stripCFWS(cr(" ( \r\n (\r\n\t) \r\n ) foo")), cr("foo")));
11383 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n) \r\n ) foo")), cr("foo")));
11384 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n )\t\r\n ) foo")), cr("foo")));
11385 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n )\r\n ) foo")), cr("foo")));
11386 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n) foo")), cr("foo")));
11387 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n\t) foo")), cr("foo")));
11388 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n ) \r\n foo")), cr("foo")));
11389 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n )\t\r\n foo")), cr("foo")));
11390 assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n )\r\n foo")), cr("foo")));
11391
11392 assert(equal(_stripCFWS(cr(" ( \r\n \r\n ( \r\n \r\n ) \r\n ) foo")), cr("foo")));
11393 assert(equal(_stripCFWS(cr(" ( \r\n \r\n ( \r\n \r\n ) \r\n ) foo")), cr("foo")));
11394 assert(equal(_stripCFWS(cr(" (\t\r\n \r\n ( \r\n \r\n ) \r\n ) foo")), cr("foo")));
11395 assert(equal(_stripCFWS(cr(" (\r\n \r\n\t( \r\n \r\n ) \r\n ) foo")), cr("foo")));
11396 assert(equal(_stripCFWS(cr(" (\r\n \r\n( \r\n \r\n ) \r\n ) foo")), cr("foo")));
11397 assert(equal(_stripCFWS(cr(" (\r\n \r\n ( \r\n \r\n\t) \r\n ) foo")), cr("foo")));
11398 assert(equal(_stripCFWS(cr(" (\r\n \r\n ( \r\n \r\n )\t\r\n ) foo")), cr("foo")));
11399 assert(equal(_stripCFWS(cr(" (\r\n \r\n ( \r\n \r\n )\r\n ) foo")), cr("foo")));
11400
11401 assert(equal(_stripCFWS(cr(" ( \r\n bar \r\n ( \r\n bar \r\n ) \r\n ) foo")), cr("foo")));
11402 assert(equal(_stripCFWS(cr(" ( \r\n () \r\n ( \r\n () \r\n ) \r\n ) foo")), cr("foo")));
11403 assert(equal(_stripCFWS(cr(" ( \r\n \\\\ \r\n ( \r\n \\\\ \r\n ) \r\n ) foo")), cr("foo")));
11404
11405 assert(_stripCFWS(cr("(hello)(hello)")).empty);
11406 assert(_stripCFWS(cr(" \n (hello)\n (hello) \n ")).empty);
11407 assert(_stripCFWS(cr(" \n (hello) \n (hello) \n ")).empty);
11408 assert(equal(_stripCFWS(cr(" \n (hello)\n (hello) \n hello")), cr("hello")));
11409 assert(equal(_stripCFWS(cr(" \n (hello) \n (hello) \n hello")), cr("hello")));
11410 assert(equal(_stripCFWS(cr("\t\n\t(hello)\n\t(hello)\t\n hello")), cr("hello")));
11411 assert(equal(_stripCFWS(cr("\t\n\t(hello)\t\n\t(hello)\t\n hello")), cr("hello")));
11412 assert(equal(_stripCFWS(cr(" \n (hello) \n \n (hello) \n hello")), cr("hello")));
11413 assert(equal(_stripCFWS(cr(" \n (hello) \n (hello) \n \n hello")), cr("hello")));
11414 assert(equal(_stripCFWS(cr(" \n \n (hello)\t\n (hello) \n hello")), cr("hello")));
11415 assert(equal(_stripCFWS(cr(" \n\t\n\t(hello)\t\n (hello) \n hello")), cr("hello")));
11416 }
11417 }
11418
11419 // This is so that we don't have to worry about std.conv.to throwing. It also
11420 // doesn't have to worry about quite as many cases as std.conv.to, since it
11421 // doesn't have to worry about a sign on the value or about whether it fits.
11422 T _convDigits(T, R)(R str)
11423 if (isIntegral!T && isSigned!T) // The constraints on R were already covered by parseRFC822DateTime.
11424 {
11425 import std.ascii : isDigit;
11426
11427 assert(!str.empty);
11428 T num = 0;
11429 foreach (i; 0 .. str.length)
11430 {
11431 if (i != 0)
11432 num *= 10;
11433 if (!isDigit(str[i]))
11434 return -1;
11435 num += str[i] - '0';
11436 }
11437 return num;
11438 }
11439
11440 @safe unittest
11441 {
11442 import std.conv : to;
11443 import std.range : chain, iota;
11444 foreach (i; chain(iota(0, 101), [250, 999, 1000, 1001, 2345, 9999]))
11445 {
11446 assert(_convDigits!int(to!string(i)) == i, i.to!string);
11447 }
foreach(str;["-42","+42","1a","1 "," "," 42 "])11448 foreach (str; ["-42", "+42", "1a", "1 ", " ", " 42 "])
11449 {
11450 assert(_convDigits!int(str) == -1, str);
11451 }
11452 }
11453
11454
11455 // NOTE: all the non-simple array literals are wrapped in functions, because
11456 // otherwise importing causes re-evaluation of the static initializers using
11457 // CTFE with unittests enabled
version(StdUnittest)11458 version (StdUnittest)
11459 {
11460 private @safe:
11461 // Variables to help in testing.
11462 Duration currLocalDiffFromUTC;
11463 immutable (TimeZone)[] testTZs;
11464
11465 // All of these helper arrays are sorted in ascending order.
11466 auto testYearsBC = [-1999, -1200, -600, -4, -1, 0];
11467 auto testYearsAD = [1, 4, 1000, 1999, 2000, 2012];
11468
11469 // I'd use a Tuple, but I get forward reference errors if I try.
11470 struct MonthDay
11471 {
11472 Month month;
11473 short day;
11474
11475 this(int m, short d)
11476 {
11477 month = cast(Month) m;
11478 day = d;
11479 }
11480 }
11481
11482 MonthDay[] testMonthDays()
11483 {
11484 static result = [MonthDay(1, 1),
11485 MonthDay(1, 2),
11486 MonthDay(3, 17),
11487 MonthDay(7, 4),
11488 MonthDay(10, 27),
11489 MonthDay(12, 30),
11490 MonthDay(12, 31)];
11491 return result;
11492 }
11493
11494 auto testDays = [1, 2, 9, 10, 16, 20, 25, 28, 29, 30, 31];
11495
11496 TimeOfDay[] testTODs()
11497 {
11498 static result = [TimeOfDay(0, 0, 0),
11499 TimeOfDay(0, 0, 1),
11500 TimeOfDay(0, 1, 0),
11501 TimeOfDay(1, 0, 0),
11502 TimeOfDay(13, 13, 13),
11503 TimeOfDay(23, 59, 59)];
11504 return result;
11505 }
11506
11507 auto testHours = [0, 1, 12, 22, 23];
11508 auto testMinSecs = [0, 1, 30, 58, 59];
11509
11510 // Throwing exceptions is incredibly expensive, so we want to use a smaller
11511 // set of values for tests using assertThrown.
11512 TimeOfDay[] testTODsThrown()
11513 {
11514 static result = [TimeOfDay(0, 0, 0),
11515 TimeOfDay(13, 13, 13),
11516 TimeOfDay(23, 59, 59)];
11517 return result;
11518 }
11519
11520 Date[] testDatesBC;
11521 Date[] testDatesAD;
11522
11523 DateTime[] testDateTimesBC;
11524 DateTime[] testDateTimesAD;
11525
11526 Duration[] testFracSecs;
11527
11528 SysTime[] testSysTimesBC;
11529 SysTime[] testSysTimesAD;
11530
11531 // I'd use a Tuple, but I get forward reference errors if I try.
11532 struct GregDay { int day; Date date; }
11533 GregDay[] testGregDaysBC()
11534 {
11535 static result = [GregDay(-1_373_427, Date(-3760, 9, 7)), // Start of the Hebrew Calendar
11536 GregDay(-735_233, Date(-2012, 1, 1)),
11537 GregDay(-735_202, Date(-2012, 2, 1)),
11538 GregDay(-735_175, Date(-2012, 2, 28)),
11539 GregDay(-735_174, Date(-2012, 2, 29)),
11540 GregDay(-735_173, Date(-2012, 3, 1)),
11541 GregDay(-734_502, Date(-2010, 1, 1)),
11542 GregDay(-734_472, Date(-2010, 1, 31)),
11543 GregDay(-734_471, Date(-2010, 2, 1)),
11544 GregDay(-734_444, Date(-2010, 2, 28)),
11545 GregDay(-734_443, Date(-2010, 3, 1)),
11546 GregDay(-734_413, Date(-2010, 3, 31)),
11547 GregDay(-734_412, Date(-2010, 4, 1)),
11548 GregDay(-734_383, Date(-2010, 4, 30)),
11549 GregDay(-734_382, Date(-2010, 5, 1)),
11550 GregDay(-734_352, Date(-2010, 5, 31)),
11551 GregDay(-734_351, Date(-2010, 6, 1)),
11552 GregDay(-734_322, Date(-2010, 6, 30)),
11553 GregDay(-734_321, Date(-2010, 7, 1)),
11554 GregDay(-734_291, Date(-2010, 7, 31)),
11555 GregDay(-734_290, Date(-2010, 8, 1)),
11556 GregDay(-734_260, Date(-2010, 8, 31)),
11557 GregDay(-734_259, Date(-2010, 9, 1)),
11558 GregDay(-734_230, Date(-2010, 9, 30)),
11559 GregDay(-734_229, Date(-2010, 10, 1)),
11560 GregDay(-734_199, Date(-2010, 10, 31)),
11561 GregDay(-734_198, Date(-2010, 11, 1)),
11562 GregDay(-734_169, Date(-2010, 11, 30)),
11563 GregDay(-734_168, Date(-2010, 12, 1)),
11564 GregDay(-734_139, Date(-2010, 12, 30)),
11565 GregDay(-734_138, Date(-2010, 12, 31)),
11566 GregDay(-731_215, Date(-2001, 1, 1)),
11567 GregDay(-730_850, Date(-2000, 1, 1)),
11568 GregDay(-730_849, Date(-2000, 1, 2)),
11569 GregDay(-730_486, Date(-2000, 12, 30)),
11570 GregDay(-730_485, Date(-2000, 12, 31)),
11571 GregDay(-730_484, Date(-1999, 1, 1)),
11572 GregDay(-694_690, Date(-1901, 1, 1)),
11573 GregDay(-694_325, Date(-1900, 1, 1)),
11574 GregDay(-585_118, Date(-1601, 1, 1)),
11575 GregDay(-584_753, Date(-1600, 1, 1)),
11576 GregDay(-584_388, Date(-1600, 12, 31)),
11577 GregDay(-584_387, Date(-1599, 1, 1)),
11578 GregDay(-365_972, Date(-1001, 1, 1)),
11579 GregDay(-365_607, Date(-1000, 1, 1)),
11580 GregDay(-183_351, Date(-501, 1, 1)),
11581 GregDay(-182_986, Date(-500, 1, 1)),
11582 GregDay(-182_621, Date(-499, 1, 1)),
11583 GregDay(-146_827, Date(-401, 1, 1)),
11584 GregDay(-146_462, Date(-400, 1, 1)),
11585 GregDay(-146_097, Date(-400, 12, 31)),
11586 GregDay(-110_302, Date(-301, 1, 1)),
11587 GregDay(-109_937, Date(-300, 1, 1)),
11588 GregDay(-73_778, Date(-201, 1, 1)),
11589 GregDay(-73_413, Date(-200, 1, 1)),
11590 GregDay(-38_715, Date(-105, 1, 1)),
11591 GregDay(-37_254, Date(-101, 1, 1)),
11592 GregDay(-36_889, Date(-100, 1, 1)),
11593 GregDay(-36_524, Date(-99, 1, 1)),
11594 GregDay(-36_160, Date(-99, 12, 31)),
11595 GregDay(-35_794, Date(-97, 1, 1)),
11596 GregDay(-18_627, Date(-50, 1, 1)),
11597 GregDay(-18_262, Date(-49, 1, 1)),
11598 GregDay(-3652, Date(-9, 1, 1)),
11599 GregDay(-2191, Date(-5, 1, 1)),
11600 GregDay(-1827, Date(-5, 12, 31)),
11601 GregDay(-1826, Date(-4, 1, 1)),
11602 GregDay(-1825, Date(-4, 1, 2)),
11603 GregDay(-1462, Date(-4, 12, 30)),
11604 GregDay(-1461, Date(-4, 12, 31)),
11605 GregDay(-1460, Date(-3, 1, 1)),
11606 GregDay(-1096, Date(-3, 12, 31)),
11607 GregDay(-1095, Date(-2, 1, 1)),
11608 GregDay(-731, Date(-2, 12, 31)),
11609 GregDay(-730, Date(-1, 1, 1)),
11610 GregDay(-367, Date(-1, 12, 30)),
11611 GregDay(-366, Date(-1, 12, 31)),
11612 GregDay(-365, Date(0, 1, 1)),
11613 GregDay(-31, Date(0, 11, 30)),
11614 GregDay(-30, Date(0, 12, 1)),
11615 GregDay(-1, Date(0, 12, 30)),
11616 GregDay(0, Date(0, 12, 31))];
11617 return result;
11618 }
11619
11620 GregDay[] testGregDaysAD()
11621 {
11622 static result = [GregDay(1, Date(1, 1, 1)),
11623 GregDay(2, Date(1, 1, 2)),
11624 GregDay(32, Date(1, 2, 1)),
11625 GregDay(365, Date(1, 12, 31)),
11626 GregDay(366, Date(2, 1, 1)),
11627 GregDay(731, Date(3, 1, 1)),
11628 GregDay(1096, Date(4, 1, 1)),
11629 GregDay(1097, Date(4, 1, 2)),
11630 GregDay(1460, Date(4, 12, 30)),
11631 GregDay(1461, Date(4, 12, 31)),
11632 GregDay(1462, Date(5, 1, 1)),
11633 GregDay(17_898, Date(50, 1, 1)),
11634 GregDay(35_065, Date(97, 1, 1)),
11635 GregDay(36_160, Date(100, 1, 1)),
11636 GregDay(36_525, Date(101, 1, 1)),
11637 GregDay(37_986, Date(105, 1, 1)),
11638 GregDay(72_684, Date(200, 1, 1)),
11639 GregDay(73_049, Date(201, 1, 1)),
11640 GregDay(109_208, Date(300, 1, 1)),
11641 GregDay(109_573, Date(301, 1, 1)),
11642 GregDay(145_732, Date(400, 1, 1)),
11643 GregDay(146_098, Date(401, 1, 1)),
11644 GregDay(182_257, Date(500, 1, 1)),
11645 GregDay(182_622, Date(501, 1, 1)),
11646 GregDay(364_878, Date(1000, 1, 1)),
11647 GregDay(365_243, Date(1001, 1, 1)),
11648 GregDay(584_023, Date(1600, 1, 1)),
11649 GregDay(584_389, Date(1601, 1, 1)),
11650 GregDay(693_596, Date(1900, 1, 1)),
11651 GregDay(693_961, Date(1901, 1, 1)),
11652 GregDay(729_755, Date(1999, 1, 1)),
11653 GregDay(730_120, Date(2000, 1, 1)),
11654 GregDay(730_121, Date(2000, 1, 2)),
11655 GregDay(730_484, Date(2000, 12, 30)),
11656 GregDay(730_485, Date(2000, 12, 31)),
11657 GregDay(730_486, Date(2001, 1, 1)),
11658 GregDay(733_773, Date(2010, 1, 1)),
11659 GregDay(733_774, Date(2010, 1, 2)),
11660 GregDay(733_803, Date(2010, 1, 31)),
11661 GregDay(733_804, Date(2010, 2, 1)),
11662 GregDay(733_831, Date(2010, 2, 28)),
11663 GregDay(733_832, Date(2010, 3, 1)),
11664 GregDay(733_862, Date(2010, 3, 31)),
11665 GregDay(733_863, Date(2010, 4, 1)),
11666 GregDay(733_892, Date(2010, 4, 30)),
11667 GregDay(733_893, Date(2010, 5, 1)),
11668 GregDay(733_923, Date(2010, 5, 31)),
11669 GregDay(733_924, Date(2010, 6, 1)),
11670 GregDay(733_953, Date(2010, 6, 30)),
11671 GregDay(733_954, Date(2010, 7, 1)),
11672 GregDay(733_984, Date(2010, 7, 31)),
11673 GregDay(733_985, Date(2010, 8, 1)),
11674 GregDay(734_015, Date(2010, 8, 31)),
11675 GregDay(734_016, Date(2010, 9, 1)),
11676 GregDay(734_045, Date(2010, 9, 30)),
11677 GregDay(734_046, Date(2010, 10, 1)),
11678 GregDay(734_076, Date(2010, 10, 31)),
11679 GregDay(734_077, Date(2010, 11, 1)),
11680 GregDay(734_106, Date(2010, 11, 30)),
11681 GregDay(734_107, Date(2010, 12, 1)),
11682 GregDay(734_136, Date(2010, 12, 30)),
11683 GregDay(734_137, Date(2010, 12, 31)),
11684 GregDay(734_503, Date(2012, 1, 1)),
11685 GregDay(734_534, Date(2012, 2, 1)),
11686 GregDay(734_561, Date(2012, 2, 28)),
11687 GregDay(734_562, Date(2012, 2, 29)),
11688 GregDay(734_563, Date(2012, 3, 1)),
11689 GregDay(734_858, Date(2012, 12, 21))];
11690 return result;
11691 }
11692
11693 // I'd use a Tuple, but I get forward reference errors if I try.
11694 struct DayOfYear { int day; MonthDay md; }
11695 DayOfYear[] testDaysOfYear()
11696 {
11697 static result = [DayOfYear(1, MonthDay(1, 1)),
11698 DayOfYear(2, MonthDay(1, 2)),
11699 DayOfYear(3, MonthDay(1, 3)),
11700 DayOfYear(31, MonthDay(1, 31)),
11701 DayOfYear(32, MonthDay(2, 1)),
11702 DayOfYear(59, MonthDay(2, 28)),
11703 DayOfYear(60, MonthDay(3, 1)),
11704 DayOfYear(90, MonthDay(3, 31)),
11705 DayOfYear(91, MonthDay(4, 1)),
11706 DayOfYear(120, MonthDay(4, 30)),
11707 DayOfYear(121, MonthDay(5, 1)),
11708 DayOfYear(151, MonthDay(5, 31)),
11709 DayOfYear(152, MonthDay(6, 1)),
11710 DayOfYear(181, MonthDay(6, 30)),
11711 DayOfYear(182, MonthDay(7, 1)),
11712 DayOfYear(212, MonthDay(7, 31)),
11713 DayOfYear(213, MonthDay(8, 1)),
11714 DayOfYear(243, MonthDay(8, 31)),
11715 DayOfYear(244, MonthDay(9, 1)),
11716 DayOfYear(273, MonthDay(9, 30)),
11717 DayOfYear(274, MonthDay(10, 1)),
11718 DayOfYear(304, MonthDay(10, 31)),
11719 DayOfYear(305, MonthDay(11, 1)),
11720 DayOfYear(334, MonthDay(11, 30)),
11721 DayOfYear(335, MonthDay(12, 1)),
11722 DayOfYear(363, MonthDay(12, 29)),
11723 DayOfYear(364, MonthDay(12, 30)),
11724 DayOfYear(365, MonthDay(12, 31))];
11725 return result;
11726 }
11727
11728 DayOfYear[] testDaysOfLeapYear()
11729 {
11730 static result = [DayOfYear(1, MonthDay(1, 1)),
11731 DayOfYear(2, MonthDay(1, 2)),
11732 DayOfYear(3, MonthDay(1, 3)),
11733 DayOfYear(31, MonthDay(1, 31)),
11734 DayOfYear(32, MonthDay(2, 1)),
11735 DayOfYear(59, MonthDay(2, 28)),
11736 DayOfYear(60, MonthDay(2, 29)),
11737 DayOfYear(61, MonthDay(3, 1)),
11738 DayOfYear(91, MonthDay(3, 31)),
11739 DayOfYear(92, MonthDay(4, 1)),
11740 DayOfYear(121, MonthDay(4, 30)),
11741 DayOfYear(122, MonthDay(5, 1)),
11742 DayOfYear(152, MonthDay(5, 31)),
11743 DayOfYear(153, MonthDay(6, 1)),
11744 DayOfYear(182, MonthDay(6, 30)),
11745 DayOfYear(183, MonthDay(7, 1)),
11746 DayOfYear(213, MonthDay(7, 31)),
11747 DayOfYear(214, MonthDay(8, 1)),
11748 DayOfYear(244, MonthDay(8, 31)),
11749 DayOfYear(245, MonthDay(9, 1)),
11750 DayOfYear(274, MonthDay(9, 30)),
11751 DayOfYear(275, MonthDay(10, 1)),
11752 DayOfYear(305, MonthDay(10, 31)),
11753 DayOfYear(306, MonthDay(11, 1)),
11754 DayOfYear(335, MonthDay(11, 30)),
11755 DayOfYear(336, MonthDay(12, 1)),
11756 DayOfYear(364, MonthDay(12, 29)),
11757 DayOfYear(365, MonthDay(12, 30)),
11758 DayOfYear(366, MonthDay(12, 31))];
11759 return result;
11760 }
11761
11762 void initializeTests()
11763 {
11764 import std.algorithm.sorting : sort;
11765 import std.typecons : Rebindable;
11766 immutable lt = LocalTime().utcToTZ(0);
11767 currLocalDiffFromUTC = dur!"hnsecs"(lt);
11768
11769 version (Posix)
11770 {
11771 import std.datetime.timezone : PosixTimeZone;
11772 immutable otherTZ = lt < 0 ? PosixTimeZone.getTimeZone("Australia/Sydney")
11773 : PosixTimeZone.getTimeZone("America/Denver");
11774 }
11775 else version (Windows)
11776 {
11777 import std.datetime.timezone : WindowsTimeZone;
11778 immutable otherTZ = lt < 0 ? WindowsTimeZone.getTimeZone("AUS Eastern Standard Time")
11779 : WindowsTimeZone.getTimeZone("Mountain Standard Time");
11780 }
11781
11782 immutable ot = otherTZ.utcToTZ(0);
11783
11784 auto diffs = [0L, lt, ot];
11785 auto diffAA = [0L : Rebindable!(immutable TimeZone)(UTC())];
11786 diffAA[lt] = Rebindable!(immutable TimeZone)(LocalTime());
11787 diffAA[ot] = Rebindable!(immutable TimeZone)(otherTZ);
11788
11789 sort(diffs);
11790 testTZs = [diffAA[diffs[0]], diffAA[diffs[1]], diffAA[diffs[2]]];
11791
11792 testFracSecs = [Duration.zero, hnsecs(1), hnsecs(5007), hnsecs(9_999_999)];
11793
11794 foreach (year; testYearsBC)
11795 {
11796 foreach (md; testMonthDays)
11797 testDatesBC ~= Date(year, md.month, md.day);
11798 }
11799
11800 foreach (year; testYearsAD)
11801 {
11802 foreach (md; testMonthDays)
11803 testDatesAD ~= Date(year, md.month, md.day);
11804 }
11805
11806 foreach (dt; testDatesBC)
11807 {
11808 foreach (tod; testTODs)
11809 testDateTimesBC ~= DateTime(dt, tod);
11810 }
11811
11812 foreach (dt; testDatesAD)
11813 {
11814 foreach (tod; testTODs)
11815 testDateTimesAD ~= DateTime(dt, tod);
11816 }
11817
11818 foreach (dt; testDateTimesBC)
11819 {
11820 foreach (tz; testTZs)
11821 {
11822 foreach (fs; testFracSecs)
11823 testSysTimesBC ~= SysTime(dt, fs, tz);
11824 }
11825 }
11826
11827 foreach (dt; testDateTimesAD)
11828 {
11829 foreach (tz; testTZs)
11830 {
11831 foreach (fs; testFracSecs)
11832 testSysTimesAD ~= SysTime(dt, fs, tz);
11833 }
11834 }
11835 }
11836 }
11837