| // Written in the D programming language |
| |
| /++ |
| License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0). |
| Authors: Jonathan M Davis |
| Source: $(PHOBOSSRC std/datetime/_systime.d) |
| +/ |
| module std.datetime.systime; |
| |
| import core.time; |
| import std.datetime.date; |
| import std.datetime.timezone; |
| import std.exception : enforce; |
| import std.format : format; |
| import std.range.primitives; |
| import std.traits : isIntegral, isSigned, isSomeString, Unqual; |
| |
| version (Windows) |
| { |
| import core.stdc.time : time_t; |
| import core.sys.windows.windows; |
| import core.sys.windows.winsock2; |
| } |
| else version (Posix) |
| { |
| import core.sys.posix.signal : timespec; |
| import core.sys.posix.sys.types : time_t; |
| } |
| |
| version (unittest) |
| { |
| import core.exception : AssertError; |
| import std.exception : assertThrown; |
| } |
| |
| |
| @safe unittest |
| { |
| initializeTests(); |
| } |
| |
| |
| /++ |
| Effectively a namespace to make it clear that the methods it contains are |
| getting the time from the system clock. It cannot be instantiated. |
| +/ |
| final class Clock |
| { |
| public: |
| |
| /++ |
| Returns the current time in the given time zone. |
| |
| Params: |
| clockType = The $(REF ClockType, core,time) indicates which system |
| clock to use to get the current time. Very few programs |
| need to use anything other than the default. |
| tz = The time zone for the SysTime that's returned. |
| |
| Throws: |
| $(REF DateTimeException,std,datetime,date) if it fails to get the |
| time. |
| +/ |
| static SysTime currTime(ClockType clockType = ClockType.normal)(immutable TimeZone tz = LocalTime()) @safe |
| { |
| return SysTime(currStdTime!clockType, tz); |
| } |
| |
| @safe unittest |
| { |
| import std.format : format; |
| import std.stdio : writefln; |
| assert(currTime().timezone is LocalTime()); |
| assert(currTime(UTC()).timezone is UTC()); |
| |
| // core.stdc.time.time does not always use unix time on Windows systems. |
| // In particular, dmc does not use unix time. If we can guarantee that |
| // the MS runtime uses unix time, then we may be able run this test |
| // then, but for now, we're just not going to run this test on Windows. |
| version (Posix) |
| { |
| static import core.stdc.time; |
| static import std.math; |
| immutable unixTimeD = currTime().toUnixTime(); |
| immutable unixTimeC = core.stdc.time.time(null); |
| assert(std.math.abs(unixTimeC - unixTimeD) <= 2); |
| } |
| |
| auto norm1 = Clock.currTime; |
| auto norm2 = Clock.currTime(UTC()); |
| assert(norm1 <= norm2, format("%s %s", norm1, norm2)); |
| assert(abs(norm1 - norm2) <= seconds(2)); |
| |
| import std.meta : AliasSeq; |
| foreach (ct; AliasSeq!(ClockType.coarse, ClockType.precise, ClockType.second)) |
| { |
| scope(failure) writefln("ClockType.%s", ct); |
| auto value1 = Clock.currTime!ct; |
| auto value2 = Clock.currTime!ct(UTC()); |
| assert(value1 <= value2, format("%s %s", value1, value2)); |
| assert(abs(value1 - value2) <= seconds(2)); |
| } |
| } |
| |
| |
| /++ |
| Returns the number of hnsecs since midnight, January 1st, 1 A.D. for the |
| current time. |
| |
| Params: |
| clockType = The $(REF ClockType, core,time) indicates which system |
| clock to use to get the current time. Very few programs |
| need to use anything other than the default. |
| |
| Throws: |
| $(REF DateTimeException,std,datetime,date) if it fails to get the |
| time. |
| +/ |
| static @property long currStdTime(ClockType clockType = ClockType.normal)() @trusted |
| { |
| static if (clockType != ClockType.coarse && |
| clockType != ClockType.normal && |
| clockType != ClockType.precise && |
| clockType != ClockType.second) |
| { |
| static assert(0, format("ClockType.%s is not supported by Clock.currTime or Clock.currStdTime", clockType)); |
| } |
| |
| version (Windows) |
| { |
| FILETIME fileTime; |
| GetSystemTimeAsFileTime(&fileTime); |
| immutable result = FILETIMEToStdTime(&fileTime); |
| static if (clockType == ClockType.second) |
| { |
| // Ideally, this would use core.std.time.time, but the C runtime |
| // has to be using unix time for that to work, and that's not |
| // guaranteed on Windows. Digital Mars does not use unix time. |
| // MS may or may not. If it does, then this can be made to use |
| // core.stdc.time for MS, but for now, we'll leave it like this. |
| return convert!("seconds", "hnsecs")(convert!("hnsecs", "seconds")(result)); |
| } |
| else |
| return result; |
| } |
| else version (Posix) |
| { |
| static import core.stdc.time; |
| enum hnsecsToUnixEpoch = unixTimeToStdTime(0); |
| |
| version (OSX) |
| { |
| static if (clockType == ClockType.second) |
| return unixTimeToStdTime(core.stdc.time.time(null)); |
| else |
| { |
| import core.sys.posix.sys.time : gettimeofday, timeval; |
| timeval tv; |
| if (gettimeofday(&tv, null) != 0) |
| throw new TimeException("Call to gettimeofday() failed"); |
| return convert!("seconds", "hnsecs")(tv.tv_sec) + |
| convert!("usecs", "hnsecs")(tv.tv_usec) + |
| hnsecsToUnixEpoch; |
| } |
| } |
| else version (linux) |
| { |
| static if (clockType == ClockType.second) |
| return unixTimeToStdTime(core.stdc.time.time(null)); |
| else |
| { |
| import core.sys.linux.time : CLOCK_REALTIME_COARSE; |
| import core.sys.posix.time : clock_gettime, CLOCK_REALTIME; |
| static if (clockType == ClockType.coarse) alias clockArg = CLOCK_REALTIME_COARSE; |
| else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME; |
| else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME; |
| else static assert(0, "Previous static if is wrong."); |
| timespec ts; |
| if (clock_gettime(clockArg, &ts) != 0) |
| throw new TimeException("Call to clock_gettime() failed"); |
| return convert!("seconds", "hnsecs")(ts.tv_sec) + |
| ts.tv_nsec / 100 + |
| hnsecsToUnixEpoch; |
| } |
| } |
| else version (FreeBSD) |
| { |
| import core.sys.freebsd.time : clock_gettime, CLOCK_REALTIME, |
| CLOCK_REALTIME_FAST, CLOCK_REALTIME_PRECISE, CLOCK_SECOND; |
| static if (clockType == ClockType.coarse) alias clockArg = CLOCK_REALTIME_FAST; |
| else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME; |
| else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME_PRECISE; |
| else static if (clockType == ClockType.second) alias clockArg = CLOCK_SECOND; |
| else static assert(0, "Previous static if is wrong."); |
| timespec ts; |
| if (clock_gettime(clockArg, &ts) != 0) |
| throw new TimeException("Call to clock_gettime() failed"); |
| return convert!("seconds", "hnsecs")(ts.tv_sec) + |
| ts.tv_nsec / 100 + |
| hnsecsToUnixEpoch; |
| } |
| else version (NetBSD) |
| { |
| static if (clockType == ClockType.second) |
| return unixTimeToStdTime(core.stdc.time.time(null)); |
| else |
| { |
| import core.sys.posix.sys.time : gettimeofday, timeval; |
| timeval tv; |
| if (gettimeofday(&tv, null) != 0) |
| throw new TimeException("Call to gettimeofday() failed"); |
| return convert!("seconds", "hnsecs")(tv.tv_sec) + |
| convert!("usecs", "hnsecs")(tv.tv_usec) + |
| hnsecsToUnixEpoch; |
| } |
| } |
| else version (DragonFlyBSD) |
| { |
| import core.sys.dragonflybsd.time : clock_gettime, CLOCK_REALTIME, |
| CLOCK_REALTIME_FAST, CLOCK_REALTIME_PRECISE, CLOCK_SECOND; |
| static if (clockType == ClockType.coarse) alias clockArg = CLOCK_REALTIME_FAST; |
| else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME; |
| else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME_PRECISE; |
| else static if (clockType == ClockType.second) alias clockArg = CLOCK_SECOND; |
| else static assert(0, "Previous static if is wrong."); |
| timespec ts; |
| if (clock_gettime(clockArg, &ts) != 0) |
| throw new TimeException("Call to clock_gettime() failed"); |
| return convert!("seconds", "hnsecs")(ts.tv_sec) + |
| ts.tv_nsec / 100 + |
| hnsecsToUnixEpoch; |
| } |
| else version (Solaris) |
| { |
| static if (clockType == ClockType.second) |
| return unixTimeToStdTime(core.stdc.time.time(null)); |
| else |
| { |
| import core.sys.solaris.time : clock_gettime, CLOCK_REALTIME; |
| static if (clockType == ClockType.coarse) alias clockArg = CLOCK_REALTIME; |
| else static if (clockType == ClockType.normal) alias clockArg = CLOCK_REALTIME; |
| else static if (clockType == ClockType.precise) alias clockArg = CLOCK_REALTIME; |
| else static assert(0, "Previous static if is wrong."); |
| timespec ts; |
| if (clock_gettime(clockArg, &ts) != 0) |
| throw new TimeException("Call to clock_gettime() failed"); |
| return convert!("seconds", "hnsecs")(ts.tv_sec) + |
| ts.tv_nsec / 100 + |
| hnsecsToUnixEpoch; |
| } |
| } |
| else static assert(0, "Unsupported OS"); |
| } |
| else static assert(0, "Unsupported OS"); |
| } |
| |
| @safe unittest |
| { |
| import std.format : format; |
| import std.math : abs; |
| import std.meta : AliasSeq; |
| import std.stdio : writefln; |
| enum limit = convert!("seconds", "hnsecs")(2); |
| |
| auto norm1 = Clock.currStdTime; |
| auto norm2 = Clock.currStdTime; |
| assert(norm1 <= norm2, format("%s %s", norm1, norm2)); |
| assert(abs(norm1 - norm2) <= limit); |
| |
| foreach (ct; AliasSeq!(ClockType.coarse, ClockType.precise, ClockType.second)) |
| { |
| scope(failure) writefln("ClockType.%s", ct); |
| auto value1 = Clock.currStdTime!ct; |
| auto value2 = Clock.currStdTime!ct; |
| assert(value1 <= value2, format("%s %s", value1, value2)); |
| assert(abs(value1 - value2) <= limit); |
| } |
| } |
| |
| |
| private: |
| |
| @disable this() {} |
| } |
| |
| |
| /++ |
| $(D SysTime) is the type used to get the current time from the |
| system or doing anything that involves time zones. Unlike |
| $(REF DateTime,std,datetime,date), the time zone is an integral part of |
| $(D SysTime) (though for local time applications, time zones can be ignored |
| and it will work, since it defaults to using the local time zone). It holds |
| its internal time in std time (hnsecs since midnight, January 1st, 1 A.D. |
| UTC), so it interfaces well with the system time. However, that means that, |
| unlike $(REF DateTime,std,datetime,date), it is not optimized for |
| calendar-based operations, and getting individual units from it such as |
| years or days is going to involve conversions and be less efficient. |
| |
| For calendar-based operations that don't |
| care about time zones, then $(REF DateTime,std,datetime,date) would be |
| the type to use. For system time, use $(D SysTime). |
| |
| $(LREF Clock.currTime) will return the current time as a $(D SysTime). |
| To convert a $(D SysTime) to a $(REF Date,std,datetime,date) or |
| $(REF DateTime,std,datetime,date), simply cast it. To convert a |
| $(REF Date,std,datetime,date) or $(REF DateTime,std,datetime,date) to a |
| $(D SysTime), use $(D SysTime)'s constructor, and pass in the ntended time |
| zone with it (or don't pass in a $(REF TimeZone,std,datetime,timezone), and |
| the local time zone will be used). Be aware, however, that converting from a |
| $(REF DateTime,std,datetime,date) to a $(D SysTime) will not necessarily |
| be 100% accurate due to DST (one hour of the year doesn't exist and another |
| occurs twice). To not risk any conversion errors, keep times as |
| $(D SysTime)s. Aside from DST though, there shouldn't be any conversion |
| problems. |
| |
| For using time zones other than local time or UTC, use |
| $(REF PosixTimeZone,std,datetime,timezone) on Posix systems (or on Windows, |
| if providing the TZ Database files), and use |
| $(REF WindowsTimeZone,std,datetime,timezone) on Windows systems. The time in |
| $(D SysTime) is kept internally in hnsecs from midnight, January 1st, 1 A.D. |
| UTC. Conversion error cannot happen when changing the time zone of a |
| $(D SysTime). $(REF LocalTime,std,datetime,timezone) is the |
| $(REF TimeZone,std,datetime,timezone) class which represents the local time, |
| and $(D UTC) is the $(REF TimeZone,std,datetime,timezone) class which |
| represents UTC. $(D SysTime) uses $(REF LocalTime,std,datetime,timezone) if |
| no $(REF TimeZone,std,datetime,timezone) is provided. For more details on |
| time zones, see the documentation for $(REF TimeZone,std,datetime,timezone), |
| $(REF PosixTimeZone,std,datetime,timezone), and |
| $(REF WindowsTimeZone,std,datetime,timezone). |
| |
| $(D SysTime)'s range is from approximately 29,000 B.C. to approximately |
| 29,000 A.D. |
| +/ |
| struct SysTime |
| { |
| import core.stdc.time : tm; |
| version (Posix) import core.sys.posix.sys.time : timeval; |
| import std.typecons : Rebindable; |
| |
| public: |
| |
| /++ |
| Params: |
| dateTime = The $(REF DateTime,std,datetime,date) to use to set |
| this $(LREF SysTime)'s internal std time. As |
| $(REF DateTime,std,datetime,date) has no concept of |
| time zone, tz is used as its time zone. |
| tz = The $(REF TimeZone,std,datetime,timezone) to use for this |
| $(LREF SysTime). If null, |
| $(REF LocalTime,std,datetime,timezone) will be used. The |
| given $(REF DateTime,std,datetime,date) is assumed to |
| be in the given time zone. |
| +/ |
| this(in DateTime dateTime, immutable TimeZone tz = null) @safe nothrow |
| { |
| try |
| this(dateTime, Duration.zero, tz); |
| catch (Exception e) |
| assert(0, "SysTime's constructor threw when it shouldn't have."); |
| } |
| |
| @safe unittest |
| { |
| static void test(DateTime dt, immutable TimeZone tz, long expected) |
| { |
| auto sysTime = SysTime(dt, tz); |
| assert(sysTime._stdTime == expected); |
| assert(sysTime._timezone is (tz is null ? LocalTime() : tz), format("Given DateTime: %s", dt)); |
| } |
| |
| test(DateTime.init, UTC(), 0); |
| test(DateTime(1, 1, 1, 12, 30, 33), UTC(), 450_330_000_000L); |
| test(DateTime(0, 12, 31, 12, 30, 33), UTC(), -413_670_000_000L); |
| test(DateTime(1, 1, 1, 0, 0, 0), UTC(), 0); |
| test(DateTime(1, 1, 1, 0, 0, 1), UTC(), 10_000_000L); |
| test(DateTime(0, 12, 31, 23, 59, 59), UTC(), -10_000_000L); |
| |
| test(DateTime(1, 1, 1, 0, 0, 0), new immutable SimpleTimeZone(dur!"minutes"(-60)), 36_000_000_000L); |
| test(DateTime(1, 1, 1, 0, 0, 0), new immutable SimpleTimeZone(Duration.zero), 0); |
| test(DateTime(1, 1, 1, 0, 0, 0), new immutable SimpleTimeZone(dur!"minutes"(60)), -36_000_000_000L); |
| } |
| |
| /++ |
| Params: |
| dateTime = The $(REF DateTime,std,datetime,date) to use to set |
| this $(LREF SysTime)'s internal std time. As |
| $(REF DateTime,std,datetime,date) has no concept of |
| time zone, tz is used as its time zone. |
| fracSecs = The fractional seconds portion of the time. |
| tz = The $(REF TimeZone,std,datetime,timezone) to use for this |
| $(LREF SysTime). If null, |
| $(REF LocalTime,std,datetime,timezone) will be used. The |
| given $(REF DateTime,std,datetime,date) is assumed to |
| be in the given time zone. |
| |
| Throws: |
| $(REF DateTimeException,std,datetime,date) if $(D fracSecs) is negative or if it's |
| greater than or equal to one second. |
| +/ |
| this(in DateTime dateTime, in Duration fracSecs, immutable TimeZone tz = null) @safe |
| { |
| enforce(fracSecs >= Duration.zero, new DateTimeException("A SysTime cannot have negative fractional seconds.")); |
| enforce(fracSecs < seconds(1), new DateTimeException("Fractional seconds must be less than one second.")); |
| auto nonNullTZ = tz is null ? LocalTime() : tz; |
| |
| immutable dateDiff = dateTime.date - Date.init; |
| immutable todDiff = dateTime.timeOfDay - TimeOfDay.init; |
| |
| immutable adjustedTime = dateDiff + todDiff + fracSecs; |
| immutable standardTime = nonNullTZ.tzToUTC(adjustedTime.total!"hnsecs"); |
| |
| this(standardTime, nonNullTZ); |
| } |
| |
| @safe unittest |
| { |
| static void test(DateTime dt, Duration fracSecs, immutable TimeZone tz, long expected) |
| { |
| auto sysTime = SysTime(dt, fracSecs, tz); |
| assert(sysTime._stdTime == expected); |
| assert(sysTime._timezone is (tz is null ? LocalTime() : tz), |
| format("Given DateTime: %s, Given Duration: %s", dt, fracSecs)); |
| } |
| |
| test(DateTime.init, Duration.zero, UTC(), 0); |
| test(DateTime(1, 1, 1, 12, 30, 33), Duration.zero, UTC(), 450_330_000_000L); |
| test(DateTime(0, 12, 31, 12, 30, 33), Duration.zero, UTC(), -413_670_000_000L); |
| test(DateTime(1, 1, 1, 0, 0, 0), msecs(1), UTC(), 10_000L); |
| test(DateTime(0, 12, 31, 23, 59, 59), msecs(999), UTC(), -10_000L); |
| |
| test(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC(), -1); |
| test(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1), UTC(), -9_999_999); |
| test(DateTime(0, 12, 31, 23, 59, 59), Duration.zero, UTC(), -10_000_000); |
| |
| assertThrown!DateTimeException(SysTime(DateTime.init, hnsecs(-1), UTC())); |
| assertThrown!DateTimeException(SysTime(DateTime.init, seconds(1), UTC())); |
| } |
| |
| /++ |
| Params: |
| date = The $(REF Date,std,datetime,date) to use to set this |
| $(LREF SysTime)'s internal std time. As |
| $(REF Date,std,datetime,date) has no concept of time zone, tz |
| is used as its time zone. |
| tz = The $(REF TimeZone,std,datetime,timezone) to use for this |
| $(LREF SysTime). If null, |
| $(REF LocalTime,std,datetime,timezone) will be used. The |
| given $(REF Date,std,datetime,date) is assumed to be in the |
| given time zone. |
| +/ |
| this(in Date date, immutable TimeZone tz = null) @safe nothrow |
| { |
| _timezone = tz is null ? LocalTime() : tz; |
| |
| try |
| { |
| immutable adjustedTime = (date - Date(1, 1, 1)).total!"hnsecs"; |
| immutable standardTime = _timezone.tzToUTC(adjustedTime); |
| |
| this(standardTime, _timezone); |
| } |
| catch (Exception e) |
| assert(0, "Date's constructor through when it shouldn't have."); |
| } |
| |
| @safe unittest |
| { |
| static void test(Date d, immutable TimeZone tz, long expected) |
| { |
| auto sysTime = SysTime(d, tz); |
| assert(sysTime._stdTime == expected); |
| assert(sysTime._timezone is (tz is null ? LocalTime() : tz), format("Given Date: %s", d)); |
| } |
| |
| test(Date.init, UTC(), 0); |
| test(Date(1, 1, 1), UTC(), 0); |
| test(Date(1, 1, 2), UTC(), 864000000000); |
| test(Date(0, 12, 31), UTC(), -864000000000); |
| } |
| |
| /++ |
| Note: |
| Whereas the other constructors take in the given date/time, assume |
| that it's in the given time zone, and convert it to hnsecs in UTC |
| since midnight, January 1st, 1 A.D. UTC - i.e. std time - this |
| constructor takes a std time, which is specifically already in UTC, |
| so no conversion takes place. Of course, the various getter |
| properties and functions will use the given time zone's conversion |
| function to convert the results to that time zone, but no conversion |
| of the arguments to this constructor takes place. |
| |
| Params: |
| stdTime = The number of hnsecs since midnight, January 1st, 1 A.D. |
| UTC. |
| tz = The $(REF TimeZone,std,datetime,timezone) to use for this |
| $(LREF SysTime). If null, |
| $(REF LocalTime,std,datetime,timezone) will be used. |
| +/ |
| this(long stdTime, immutable TimeZone tz = null) @safe pure nothrow |
| { |
| _stdTime = stdTime; |
| _timezone = tz is null ? LocalTime() : tz; |
| } |
| |
| @safe unittest |
| { |
| static void test(long stdTime, immutable TimeZone tz) |
| { |
| auto sysTime = SysTime(stdTime, tz); |
| assert(sysTime._stdTime == stdTime); |
| assert(sysTime._timezone is (tz is null ? LocalTime() : tz), format("Given stdTime: %s", stdTime)); |
| } |
| |
| foreach (stdTime; [-1234567890L, -250, 0, 250, 1235657390L]) |
| { |
| foreach (tz; testTZs) |
| test(stdTime, tz); |
| } |
| } |
| |
| /++ |
| Params: |
| rhs = The $(LREF SysTime) to assign to this one. |
| +/ |
| ref SysTime opAssign(const ref SysTime rhs) return @safe pure nothrow |
| { |
| _stdTime = rhs._stdTime; |
| _timezone = rhs._timezone; |
| return this; |
| } |
| |
| /++ |
| Params: |
| rhs = The $(LREF SysTime) to assign to this one. |
| +/ |
| ref SysTime opAssign(SysTime rhs) scope return @safe pure nothrow |
| { |
| _stdTime = rhs._stdTime; |
| _timezone = rhs._timezone; |
| return this; |
| } |
| |
| /++ |
| Checks for equality between this $(LREF SysTime) and the given |
| $(LREF SysTime). |
| |
| Note that the time zone is ignored. Only the internal |
| std times (which are in UTC) are compared. |
| +/ |
| bool opEquals(const SysTime rhs) @safe const pure nothrow |
| { |
| return opEquals(rhs); |
| } |
| |
| /// ditto |
| bool opEquals(const ref SysTime rhs) @safe const pure nothrow |
| { |
| return _stdTime == rhs._stdTime; |
| } |
| |
| @safe unittest |
| { |
| import std.range : chain; |
| |
| assert(SysTime(DateTime.init, UTC()) == SysTime(0, UTC())); |
| assert(SysTime(DateTime.init, UTC()) == SysTime(0)); |
| assert(SysTime(Date.init, UTC()) == SysTime(0)); |
| assert(SysTime(0) == SysTime(0)); |
| |
| static void test(DateTime dt, immutable TimeZone tz1, immutable TimeZone tz2) |
| { |
| auto st1 = SysTime(dt); |
| st1.timezone = tz1; |
| |
| auto st2 = SysTime(dt); |
| st2.timezone = tz2; |
| |
| assert(st1 == st2); |
| } |
| |
| foreach (tz1; testTZs) |
| { |
| foreach (tz2; testTZs) |
| { |
| foreach (dt; chain(testDateTimesBC, testDateTimesAD)) |
| test(dt, tz1, tz2); |
| } |
| } |
| |
| auto st = SysTime(DateTime(1999, 7, 6, 12, 33, 30)); |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 33, 30)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 33, 30)); |
| assert(st == st); |
| assert(st == cst); |
| //assert(st == ist); |
| assert(cst == st); |
| assert(cst == cst); |
| //assert(cst == ist); |
| //assert(ist == st); |
| //assert(ist == cst); |
| //assert(ist == ist); |
| } |
| |
| /++ |
| Compares this $(LREF SysTime) with the given $(LREF SysTime). |
| |
| Time zone is irrelevant when comparing $(LREF SysTime)s. |
| |
| Returns: |
| $(BOOKTABLE, |
| $(TR $(TD this < rhs) $(TD < 0)) |
| $(TR $(TD this == rhs) $(TD 0)) |
| $(TR $(TD this > rhs) $(TD > 0)) |
| ) |
| +/ |
| int opCmp(in SysTime rhs) @safe const pure nothrow |
| { |
| if (_stdTime < rhs._stdTime) |
| return -1; |
| if (_stdTime > rhs._stdTime) |
| return 1; |
| return 0; |
| } |
| |
| @safe unittest |
| { |
| import std.algorithm.iteration : map; |
| import std.array : array; |
| import std.range : chain; |
| |
| assert(SysTime(DateTime.init, UTC()).opCmp(SysTime(0, UTC())) == 0); |
| assert(SysTime(DateTime.init, UTC()).opCmp(SysTime(0)) == 0); |
| assert(SysTime(Date.init, UTC()).opCmp(SysTime(0)) == 0); |
| assert(SysTime(0).opCmp(SysTime(0)) == 0); |
| |
| static void testEqual(SysTime st, immutable TimeZone tz1, immutable TimeZone tz2) |
| { |
| auto st1 = st; |
| st1.timezone = tz1; |
| |
| auto st2 = st; |
| st2.timezone = tz2; |
| |
| assert(st1.opCmp(st2) == 0); |
| } |
| |
| auto sts = array(map!SysTime(chain(testDateTimesBC, testDateTimesAD))); |
| |
| foreach (st; sts) |
| { |
| foreach (tz1; testTZs) |
| { |
| foreach (tz2; testTZs) |
| testEqual(st, tz1, tz2); |
| } |
| } |
| |
| static void testCmp(SysTime st1, immutable TimeZone tz1, SysTime st2, immutable TimeZone tz2) |
| { |
| st1.timezone = tz1; |
| st2.timezone = tz2; |
| assert(st1.opCmp(st2) < 0); |
| assert(st2.opCmp(st1) > 0); |
| } |
| |
| foreach (si, st1; sts) |
| { |
| foreach (st2; sts[si + 1 .. $]) |
| { |
| foreach (tz1; testTZs) |
| { |
| foreach (tz2; testTZs) |
| testCmp(st1, tz1, st2, tz2); |
| } |
| } |
| } |
| |
| auto st = SysTime(DateTime(1999, 7, 6, 12, 33, 30)); |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 33, 30)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 33, 30)); |
| assert(st.opCmp(st) == 0); |
| assert(st.opCmp(cst) == 0); |
| //assert(st.opCmp(ist) == 0); |
| assert(cst.opCmp(st) == 0); |
| assert(cst.opCmp(cst) == 0); |
| //assert(cst.opCmp(ist) == 0); |
| //assert(ist.opCmp(st) == 0); |
| //assert(ist.opCmp(cst) == 0); |
| //assert(ist.opCmp(ist) == 0); |
| } |
| |
| /** |
| * Returns: A hash of the $(LREF SysTime) |
| */ |
| size_t toHash() const @nogc pure nothrow @safe |
| { |
| static if (is(size_t == ulong)) |
| return _stdTime; |
| else |
| { |
| // MurmurHash2 |
| enum ulong m = 0xc6a4a7935bd1e995UL; |
| enum ulong n = m * 16; |
| enum uint r = 47; |
| |
| ulong k = _stdTime; |
| k *= m; |
| k ^= k >> r; |
| k *= m; |
| |
| ulong h = n; |
| h ^= k; |
| h *= m; |
| |
| return cast(size_t) h; |
| } |
| } |
| |
| @safe unittest |
| { |
| assert(SysTime(0).toHash == SysTime(0).toHash); |
| assert(SysTime(DateTime(2000, 1, 1)).toHash == SysTime(DateTime(2000, 1, 1)).toHash); |
| assert(SysTime(DateTime(2000, 1, 1)).toHash != SysTime(DateTime(2000, 1, 2)).toHash); |
| |
| // test that timezones aren't taken into account |
| assert(SysTime(0, LocalTime()).toHash == SysTime(0, LocalTime()).toHash); |
| assert(SysTime(0, LocalTime()).toHash == SysTime(0, UTC()).toHash); |
| assert(SysTime(DateTime(2000, 1, 1), LocalTime()).toHash == SysTime(DateTime(2000, 1, 1), LocalTime()).toHash); |
| immutable zone = new SimpleTimeZone(dur!"minutes"(60)); |
| assert(SysTime(DateTime(2000, 1, 1, 1), zone).toHash == SysTime(DateTime(2000, 1, 1), UTC()).toHash); |
| assert(SysTime(DateTime(2000, 1, 1), zone).toHash != SysTime(DateTime(2000, 1, 1), UTC()).toHash); |
| } |
| |
| /++ |
| Year of the Gregorian Calendar. Positive numbers are A.D. Non-positive |
| are B.C. |
| +/ |
| @property short year() @safe const nothrow |
| { |
| return (cast(Date) this).year; |
| } |
| |
| @safe unittest |
| { |
| import std.range : chain; |
| static void test(SysTime sysTime, long expected) |
| { |
| assert(sysTime.year == expected, format("Value given: %s", sysTime)); |
| } |
| |
| test(SysTime(0, UTC()), 1); |
| test(SysTime(1, UTC()), 1); |
| test(SysTime(-1, UTC()), 0); |
| |
| foreach (year; chain(testYearsBC, testYearsAD)) |
| { |
| foreach (md; testMonthDays) |
| { |
| foreach (tod; testTODs) |
| { |
| auto dt = DateTime(Date(year, md.month, md.day), tod); |
| foreach (tz; testTZs) |
| { |
| foreach (fs; testFracSecs) |
| test(SysTime(dt, fs, tz), year); |
| } |
| } |
| } |
| } |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(cst.year == 1999); |
| //assert(ist.year == 1999); |
| } |
| |
| /++ |
| Year of the Gregorian Calendar. Positive numbers are A.D. Non-positive |
| are B.C. |
| |
| Params: |
| year = The year to set this $(LREF SysTime)'s year to. |
| |
| Throws: |
| $(REF DateTimeException,std,datetime,date) if the new year is not |
| a leap year and the resulting date would be on February 29th. |
| +/ |
| @property void year(int year) @safe |
| { |
| auto hnsecs = adjTime; |
| auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1; |
| |
| if (hnsecs < 0) |
| { |
| hnsecs += convert!("hours", "hnsecs")(24); |
| --days; |
| } |
| |
| auto date = Date(cast(int) days); |
| date.year = year; |
| |
| immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1); |
| adjTime = newDaysHNSecs + hnsecs; |
| } |
| |
| /// |
| @safe unittest |
| { |
| import std.datetime.date : DateTime; |
| |
| assert(SysTime(DateTime(1999, 7, 6, 9, 7, 5)).year == 1999); |
| assert(SysTime(DateTime(2010, 10, 4, 0, 0, 30)).year == 2010); |
| assert(SysTime(DateTime(-7, 4, 5, 7, 45, 2)).year == -7); |
| } |
| |
| @safe unittest |
| { |
| import std.range : chain; |
| |
| static void test(SysTime st, int year, in SysTime expected) |
| { |
| st.year = year; |
| assert(st == expected); |
| } |
| |
| foreach (st; chain(testSysTimesBC, testSysTimesAD)) |
| { |
| auto dt = cast(DateTime) st; |
| |
| foreach (year; chain(testYearsBC, testYearsAD)) |
| { |
| auto e = SysTime(DateTime(year, dt.month, dt.day, dt.hour, dt.minute, dt.second), |
| st.fracSecs, |
| st.timezone); |
| test(st, year, e); |
| } |
| } |
| |
| foreach (fs; testFracSecs) |
| { |
| foreach (tz; testTZs) |
| { |
| foreach (tod; testTODs) |
| { |
| test(SysTime(DateTime(Date(1999, 2, 28), tod), fs, tz), 2000, |
| SysTime(DateTime(Date(2000, 2, 28), tod), fs, tz)); |
| test(SysTime(DateTime(Date(2000, 2, 28), tod), fs, tz), 1999, |
| SysTime(DateTime(Date(1999, 2, 28), tod), fs, tz)); |
| } |
| |
| foreach (tod; testTODsThrown) |
| { |
| auto st = SysTime(DateTime(Date(2000, 2, 29), tod), fs, tz); |
| assertThrown!DateTimeException(st.year = 1999); |
| } |
| } |
| } |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| static assert(!__traits(compiles, cst.year = 7)); |
| //static assert(!__traits(compiles, ist.year = 7)); |
| } |
| |
| /++ |
| Year B.C. of the Gregorian Calendar counting year 0 as 1 B.C. |
| |
| Throws: |
| $(REF DateTimeException,std,datetime,date) if $(D isAD) is true. |
| +/ |
| @property ushort yearBC() @safe const |
| { |
| return (cast(Date) this).yearBC; |
| } |
| |
| /// |
| @safe unittest |
| { |
| import std.datetime.date : DateTime; |
| |
| assert(SysTime(DateTime(0, 1, 1, 12, 30, 33)).yearBC == 1); |
| assert(SysTime(DateTime(-1, 1, 1, 10, 7, 2)).yearBC == 2); |
| assert(SysTime(DateTime(-100, 1, 1, 4, 59, 0)).yearBC == 101); |
| } |
| |
| @safe unittest |
| { |
| import std.exception : assertNotThrown; |
| foreach (st; testSysTimesBC) |
| { |
| auto msg = format("SysTime: %s", st); |
| assertNotThrown!DateTimeException(st.yearBC, msg); |
| assert(st.yearBC == (st.year * -1) + 1, msg); |
| } |
| |
| foreach (st; [testSysTimesAD[0], testSysTimesAD[$/2], testSysTimesAD[$-1]]) |
| assertThrown!DateTimeException(st.yearBC, format("SysTime: %s", st)); |
| |
| auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| st.year = 12; |
| assert(st.year == 12); |
| static assert(!__traits(compiles, cst.year = 12)); |
| //static assert(!__traits(compiles, ist.year = 12)); |
| } |
| |
| |
| /++ |
| Year B.C. of the Gregorian Calendar counting year 0 as 1 B.C. |
| |
| Params: |
| year = The year B.C. to set this $(LREF SysTime)'s year to. |
| |
| Throws: |
| $(REF DateTimeException,std,datetime,date) if a non-positive value |
| is given. |
| +/ |
| @property void yearBC(int year) @safe |
| { |
| auto hnsecs = adjTime; |
| auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1; |
| |
| if (hnsecs < 0) |
| { |
| hnsecs += convert!("hours", "hnsecs")(24); |
| --days; |
| } |
| |
| auto date = Date(cast(int) days); |
| date.yearBC = year; |
| |
| immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1); |
| adjTime = newDaysHNSecs + hnsecs; |
| } |
| |
| @safe unittest |
| { |
| auto st = SysTime(DateTime(2010, 1, 1, 7, 30, 0)); |
| st.yearBC = 1; |
| assert(st == SysTime(DateTime(0, 1, 1, 7, 30, 0))); |
| |
| st.yearBC = 10; |
| assert(st == SysTime(DateTime(-9, 1, 1, 7, 30, 0))); |
| } |
| |
| @safe unittest |
| { |
| import std.range : chain; |
| static void test(SysTime st, int year, in SysTime expected) |
| { |
| st.yearBC = year; |
| assert(st == expected, format("SysTime: %s", st)); |
| } |
| |
| foreach (st; chain(testSysTimesBC, testSysTimesAD)) |
| { |
| auto dt = cast(DateTime) st; |
| |
| foreach (year; testYearsBC) |
| { |
| auto e = SysTime(DateTime(year, dt.month, dt.day, dt.hour, dt.minute, dt.second), |
| st.fracSecs, |
| st.timezone); |
| test(st, (year * -1) + 1, e); |
| } |
| } |
| |
| foreach (st; [testSysTimesBC[0], testSysTimesBC[$ - 1], testSysTimesAD[0], testSysTimesAD[$ - 1]]) |
| { |
| foreach (year; testYearsBC) |
| assertThrown!DateTimeException(st.yearBC = year); |
| } |
| |
| foreach (fs; testFracSecs) |
| { |
| foreach (tz; testTZs) |
| { |
| foreach (tod; testTODs) |
| { |
| test(SysTime(DateTime(Date(-1999, 2, 28), tod), fs, tz), 2001, |
| SysTime(DateTime(Date(-2000, 2, 28), tod), fs, tz)); |
| test(SysTime(DateTime(Date(-2000, 2, 28), tod), fs, tz), 2000, |
| SysTime(DateTime(Date(-1999, 2, 28), tod), fs, tz)); |
| } |
| |
| foreach (tod; testTODsThrown) |
| { |
| auto st = SysTime(DateTime(Date(-2000, 2, 29), tod), fs, tz); |
| assertThrown!DateTimeException(st.year = -1999); |
| } |
| } |
| } |
| |
| auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| st.yearBC = 12; |
| assert(st.yearBC == 12); |
| static assert(!__traits(compiles, cst.yearBC = 12)); |
| //static assert(!__traits(compiles, ist.yearBC = 12)); |
| } |
| |
| /++ |
| Month of a Gregorian Year. |
| +/ |
| @property Month month() @safe const nothrow |
| { |
| return (cast(Date) this).month; |
| } |
| |
| /// |
| @safe unittest |
| { |
| import std.datetime.date : DateTime; |
| |
| assert(SysTime(DateTime(1999, 7, 6, 9, 7, 5)).month == 7); |
| assert(SysTime(DateTime(2010, 10, 4, 0, 0, 30)).month == 10); |
| assert(SysTime(DateTime(-7, 4, 5, 7, 45, 2)).month == 4); |
| } |
| |
| @safe unittest |
| { |
| import std.range : chain; |
| |
| static void test(SysTime sysTime, Month expected) |
| { |
| assert(sysTime.month == expected, format("Value given: %s", sysTime)); |
| } |
| |
| test(SysTime(0, UTC()), Month.jan); |
| test(SysTime(1, UTC()), Month.jan); |
| test(SysTime(-1, UTC()), Month.dec); |
| |
| foreach (year; chain(testYearsBC, testYearsAD)) |
| { |
| foreach (md; testMonthDays) |
| { |
| foreach (tod; testTODs) |
| { |
| auto dt = DateTime(Date(year, md.month, md.day), tod); |
| foreach (fs; testFracSecs) |
| { |
| foreach (tz; testTZs) |
| test(SysTime(dt, fs, tz), md.month); |
| } |
| } |
| } |
| } |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(cst.month == 7); |
| //assert(ist.month == 7); |
| } |
| |
| |
| /++ |
| Month of a Gregorian Year. |
| |
| Params: |
| month = The month to set this $(LREF SysTime)'s month to. |
| |
| Throws: |
| $(REF DateTimeException,std,datetime,date) if the given month is |
| not a valid month. |
| +/ |
| @property void month(Month month) @safe |
| { |
| auto hnsecs = adjTime; |
| auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1; |
| |
| if (hnsecs < 0) |
| { |
| hnsecs += convert!("hours", "hnsecs")(24); |
| --days; |
| } |
| |
| auto date = Date(cast(int) days); |
| date.month = month; |
| |
| immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1); |
| adjTime = newDaysHNSecs + hnsecs; |
| } |
| |
| @safe unittest |
| { |
| import std.algorithm.iteration : filter; |
| import std.range : chain; |
| |
| static void test(SysTime st, Month month, in SysTime expected) |
| { |
| st.month = cast(Month) month; |
| assert(st == expected); |
| } |
| |
| foreach (st; chain(testSysTimesBC, testSysTimesAD)) |
| { |
| auto dt = cast(DateTime) st; |
| |
| foreach (md; testMonthDays) |
| { |
| if (st.day > maxDay(dt.year, md.month)) |
| continue; |
| auto e = SysTime(DateTime(dt.year, md.month, dt.day, dt.hour, dt.minute, dt.second), |
| st.fracSecs, |
| st.timezone); |
| test(st, md.month, e); |
| } |
| } |
| |
| foreach (fs; testFracSecs) |
| { |
| foreach (tz; testTZs) |
| { |
| foreach (tod; testTODs) |
| { |
| foreach (year; filter!((a){return yearIsLeapYear(a);}) (chain(testYearsBC, testYearsAD))) |
| { |
| test(SysTime(DateTime(Date(year, 1, 29), tod), fs, tz), |
| Month.feb, |
| SysTime(DateTime(Date(year, 2, 29), tod), fs, tz)); |
| } |
| |
| foreach (year; chain(testYearsBC, testYearsAD)) |
| { |
| test(SysTime(DateTime(Date(year, 1, 28), tod), fs, tz), |
| Month.feb, |
| SysTime(DateTime(Date(year, 2, 28), tod), fs, tz)); |
| test(SysTime(DateTime(Date(year, 7, 30), tod), fs, tz), |
| Month.jun, |
| SysTime(DateTime(Date(year, 6, 30), tod), fs, tz)); |
| } |
| } |
| } |
| } |
| |
| foreach (fs; [testFracSecs[0], testFracSecs[$-1]]) |
| { |
| foreach (tz; testTZs) |
| { |
| foreach (tod; testTODsThrown) |
| { |
| foreach (year; [testYearsBC[$-3], testYearsBC[$-2], |
| testYearsBC[$-2], testYearsAD[0], |
| testYearsAD[$-2], testYearsAD[$-1]]) |
| { |
| auto day = yearIsLeapYear(year) ? 30 : 29; |
| auto st1 = SysTime(DateTime(Date(year, 1, day), tod), fs, tz); |
| assertThrown!DateTimeException(st1.month = Month.feb); |
| |
| auto st2 = SysTime(DateTime(Date(year, 7, 31), tod), fs, tz); |
| assertThrown!DateTimeException(st2.month = Month.jun); |
| } |
| } |
| } |
| } |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| static assert(!__traits(compiles, cst.month = 12)); |
| //static assert(!__traits(compiles, ist.month = 12)); |
| } |
| |
| /++ |
| Day of a Gregorian Month. |
| +/ |
| @property ubyte day() @safe const nothrow |
| { |
| return (cast(Date) this).day; |
| } |
| |
| /// |
| @safe unittest |
| { |
| import std.datetime.date : DateTime; |
| |
| assert(SysTime(DateTime(1999, 7, 6, 9, 7, 5)).day == 6); |
| assert(SysTime(DateTime(2010, 10, 4, 0, 0, 30)).day == 4); |
| assert(SysTime(DateTime(-7, 4, 5, 7, 45, 2)).day == 5); |
| } |
| |
| @safe unittest |
| { |
| import std.range : chain; |
| |
| static void test(SysTime sysTime, int expected) |
| { |
| assert(sysTime.day == expected, format("Value given: %s", sysTime)); |
| } |
| |
| test(SysTime(0, UTC()), 1); |
| test(SysTime(1, UTC()), 1); |
| test(SysTime(-1, UTC()), 31); |
| |
| foreach (year; chain(testYearsBC, testYearsAD)) |
| { |
| foreach (md; testMonthDays) |
| { |
| foreach (tod; testTODs) |
| { |
| auto dt = DateTime(Date(year, md.month, md.day), tod); |
| |
| foreach (tz; testTZs) |
| { |
| foreach (fs; testFracSecs) |
| test(SysTime(dt, fs, tz), md.day); |
| } |
| } |
| } |
| } |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(cst.day == 6); |
| //assert(ist.day == 6); |
| } |
| |
| |
| /++ |
| Day of a Gregorian Month. |
| |
| Params: |
| day = The day of the month to set this $(LREF SysTime)'s day to. |
| |
| Throws: |
| $(REF DateTimeException,std,datetime,date) if the given day is not |
| a valid day of the current month. |
| +/ |
| @property void day(int day) @safe |
| { |
| auto hnsecs = adjTime; |
| auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1; |
| |
| if (hnsecs < 0) |
| { |
| hnsecs += convert!("hours", "hnsecs")(24); |
| --days; |
| } |
| |
| auto date = Date(cast(int) days); |
| date.day = day; |
| |
| immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1); |
| adjTime = newDaysHNSecs + hnsecs; |
| } |
| |
| @safe unittest |
| { |
| import std.range : chain; |
| import std.traits : EnumMembers; |
| |
| foreach (day; chain(testDays)) |
| { |
| foreach (st; chain(testSysTimesBC, testSysTimesAD)) |
| { |
| auto dt = cast(DateTime) st; |
| |
| if (day > maxDay(dt.year, dt.month)) |
| continue; |
| auto expected = SysTime(DateTime(dt.year, dt.month, day, dt.hour, dt.minute, dt.second), |
| st.fracSecs, |
| st.timezone); |
| st.day = day; |
| assert(st == expected, format("[%s] [%s]", st, expected)); |
| } |
| } |
| |
| foreach (tz; testTZs) |
| { |
| foreach (tod; testTODs) |
| { |
| foreach (fs; testFracSecs) |
| { |
| foreach (year; chain(testYearsBC, testYearsAD)) |
| { |
| foreach (month; EnumMembers!Month) |
| { |
| auto st = SysTime(DateTime(Date(year, month, 1), tod), fs, tz); |
| immutable max = maxDay(year, month); |
| auto expected = SysTime(DateTime(Date(year, month, max), tod), fs, tz); |
| |
| st.day = max; |
| assert(st == expected, format("[%s] [%s]", st, expected)); |
| } |
| } |
| } |
| } |
| } |
| |
| foreach (tz; testTZs) |
| { |
| foreach (tod; testTODsThrown) |
| { |
| foreach (fs; [testFracSecs[0], testFracSecs[$-1]]) |
| { |
| foreach (year; [testYearsBC[$-3], testYearsBC[$-2], |
| testYearsBC[$-2], testYearsAD[0], |
| testYearsAD[$-2], testYearsAD[$-1]]) |
| { |
| foreach (month; EnumMembers!Month) |
| { |
| auto st = SysTime(DateTime(Date(year, month, 1), tod), fs, tz); |
| immutable max = maxDay(year, month); |
| |
| assertThrown!DateTimeException(st.day = max + 1); |
| } |
| } |
| } |
| } |
| } |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| static assert(!__traits(compiles, cst.day = 27)); |
| //static assert(!__traits(compiles, ist.day = 27)); |
| } |
| |
| |
| /++ |
| Hours past midnight. |
| +/ |
| @property ubyte hour() @safe const nothrow |
| { |
| auto hnsecs = adjTime; |
| auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1; |
| |
| if (hnsecs < 0) |
| { |
| hnsecs += convert!("hours", "hnsecs")(24); |
| --days; |
| } |
| |
| return cast(ubyte) getUnitsFromHNSecs!"hours"(hnsecs); |
| } |
| |
| @safe unittest |
| { |
| import std.range : chain; |
| |
| static void test(SysTime sysTime, int expected) |
| { |
| assert(sysTime.hour == expected, format("Value given: %s", sysTime)); |
| } |
| |
| test(SysTime(0, UTC()), 0); |
| test(SysTime(1, UTC()), 0); |
| test(SysTime(-1, UTC()), 23); |
| |
| foreach (tz; testTZs) |
| { |
| foreach (year; chain(testYearsBC, testYearsAD)) |
| { |
| foreach (md; testMonthDays) |
| { |
| foreach (hour; testHours) |
| { |
| foreach (minute; testMinSecs) |
| { |
| foreach (second; testMinSecs) |
| { |
| auto dt = DateTime(Date(year, md.month, md.day), TimeOfDay(hour, minute, second)); |
| foreach (fs; testFracSecs) |
| test(SysTime(dt, fs, tz), hour); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(cst.hour == 12); |
| //assert(ist.hour == 12); |
| } |
| |
| |
| /++ |
| Hours past midnight. |
| |
| Params: |
| hour = The hours to set this $(LREF SysTime)'s hour to. |
| |
| Throws: |
| $(REF DateTimeException,std,datetime,date) if the given hour are |
| not a valid hour of the day. |
| +/ |
| @property void hour(int hour) @safe |
| { |
| enforceValid!"hours"(hour); |
| |
| auto hnsecs = adjTime; |
| auto days = splitUnitsFromHNSecs!"days"(hnsecs); |
| immutable daysHNSecs = convert!("days", "hnsecs")(days); |
| immutable negative = hnsecs < 0; |
| |
| if (negative) |
| hnsecs += convert!("hours", "hnsecs")(24); |
| |
| hnsecs = removeUnitsFromHNSecs!"hours"(hnsecs); |
| hnsecs += convert!("hours", "hnsecs")(hour); |
| |
| if (negative) |
| hnsecs -= convert!("hours", "hnsecs")(24); |
| |
| adjTime = daysHNSecs + hnsecs; |
| } |
| |
| @safe unittest |
| { |
| import std.range : chain; |
| |
| foreach (hour; chain(testHours)) |
| { |
| foreach (st; chain(testSysTimesBC, testSysTimesAD)) |
| { |
| auto dt = cast(DateTime) st; |
| auto expected = SysTime(DateTime(dt.year, dt.month, dt.day, hour, dt.minute, dt.second), |
| st.fracSecs, |
| st.timezone); |
| st.hour = hour; |
| assert(st == expected, format("[%s] [%s]", st, expected)); |
| } |
| } |
| |
| auto st = testSysTimesAD[0]; |
| assertThrown!DateTimeException(st.hour = -1); |
| assertThrown!DateTimeException(st.hour = 60); |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| static assert(!__traits(compiles, cst.hour = 27)); |
| //static assert(!__traits(compiles, ist.hour = 27)); |
| } |
| |
| |
| /++ |
| Minutes past the current hour. |
| +/ |
| @property ubyte minute() @safe const nothrow |
| { |
| auto hnsecs = adjTime; |
| auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1; |
| |
| if (hnsecs < 0) |
| { |
| hnsecs += convert!("hours", "hnsecs")(24); |
| --days; |
| } |
| |
| hnsecs = removeUnitsFromHNSecs!"hours"(hnsecs); |
| |
| return cast(ubyte) getUnitsFromHNSecs!"minutes"(hnsecs); |
| } |
| |
| @safe unittest |
| { |
| import std.range : chain; |
| |
| static void test(SysTime sysTime, int expected) |
| { |
| assert(sysTime.minute == expected, format("Value given: %s", sysTime)); |
| } |
| |
| test(SysTime(0, UTC()), 0); |
| test(SysTime(1, UTC()), 0); |
| test(SysTime(-1, UTC()), 59); |
| |
| foreach (tz; testTZs) |
| { |
| foreach (year; chain(testYearsBC, testYearsAD)) |
| { |
| foreach (md; testMonthDays) |
| { |
| foreach (hour; testHours) |
| { |
| foreach (minute; testMinSecs) |
| { |
| foreach (second; testMinSecs) |
| { |
| auto dt = DateTime(Date(year, md.month, md.day), TimeOfDay(hour, minute, second)); |
| foreach (fs; testFracSecs) |
| test(SysTime(dt, fs, tz), minute); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(cst.minute == 30); |
| //assert(ist.minute == 30); |
| } |
| |
| |
| /++ |
| Minutes past the current hour. |
| |
| Params: |
| minute = The minute to set this $(LREF SysTime)'s minute to. |
| |
| Throws: |
| $(REF DateTimeException,std,datetime,date) if the given minute are |
| not a valid minute of an hour. |
| +/ |
| @property void minute(int minute) @safe |
| { |
| enforceValid!"minutes"(minute); |
| |
| auto hnsecs = adjTime; |
| auto days = splitUnitsFromHNSecs!"days"(hnsecs); |
| immutable daysHNSecs = convert!("days", "hnsecs")(days); |
| immutable negative = hnsecs < 0; |
| |
| if (negative) |
| hnsecs += convert!("hours", "hnsecs")(24); |
| |
| immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs); |
| hnsecs = removeUnitsFromHNSecs!"minutes"(hnsecs); |
| |
| hnsecs += convert!("hours", "hnsecs")(hour); |
| hnsecs += convert!("minutes", "hnsecs")(minute); |
| |
| if (negative) |
| hnsecs -= convert!("hours", "hnsecs")(24); |
| |
| adjTime = daysHNSecs + hnsecs; |
| } |
| |
| @safe unittest |
| { |
| import std.range : chain; |
| |
| foreach (minute; testMinSecs) |
| { |
| foreach (st; chain(testSysTimesBC, testSysTimesAD)) |
| { |
| auto dt = cast(DateTime) st; |
| auto expected = SysTime(DateTime(dt.year, dt.month, dt.day, dt.hour, minute, dt.second), |
| st.fracSecs, |
| st.timezone); |
| st.minute = minute; |
| assert(st == expected, format("[%s] [%s]", st, expected)); |
| } |
| } |
| |
| auto st = testSysTimesAD[0]; |
| assertThrown!DateTimeException(st.minute = -1); |
| assertThrown!DateTimeException(st.minute = 60); |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| static assert(!__traits(compiles, cst.minute = 27)); |
| //static assert(!__traits(compiles, ist.minute = 27)); |
| } |
| |
| |
| /++ |
| Seconds past the current minute. |
| +/ |
| @property ubyte second() @safe const nothrow |
| { |
| auto hnsecs = adjTime; |
| auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1; |
| |
| if (hnsecs < 0) |
| { |
| hnsecs += convert!("hours", "hnsecs")(24); |
| --days; |
| } |
| |
| hnsecs = removeUnitsFromHNSecs!"hours"(hnsecs); |
| hnsecs = removeUnitsFromHNSecs!"minutes"(hnsecs); |
| |
| return cast(ubyte) getUnitsFromHNSecs!"seconds"(hnsecs); |
| } |
| |
| @safe unittest |
| { |
| import std.range : chain; |
| |
| static void test(SysTime sysTime, int expected) |
| { |
| assert(sysTime.second == expected, format("Value given: %s", sysTime)); |
| } |
| |
| test(SysTime(0, UTC()), 0); |
| test(SysTime(1, UTC()), 0); |
| test(SysTime(-1, UTC()), 59); |
| |
| foreach (tz; testTZs) |
| { |
| foreach (year; chain(testYearsBC, testYearsAD)) |
| { |
| foreach (md; testMonthDays) |
| { |
| foreach (hour; testHours) |
| { |
| foreach (minute; testMinSecs) |
| { |
| foreach (second; testMinSecs) |
| { |
| auto dt = DateTime(Date(year, md.month, md.day), TimeOfDay(hour, minute, second)); |
| foreach (fs; testFracSecs) |
| test(SysTime(dt, fs, tz), second); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(cst.second == 33); |
| //assert(ist.second == 33); |
| } |
| |
| |
| /++ |
| Seconds past the current minute. |
| |
| Params: |
| second = The second to set this $(LREF SysTime)'s second to. |
| |
| Throws: |
| $(REF DateTimeException,std,datetime,date) if the given second are |
| not a valid second of a minute. |
| +/ |
| @property void second(int second) @safe |
| { |
| enforceValid!"seconds"(second); |
| |
| auto hnsecs = adjTime; |
| auto days = splitUnitsFromHNSecs!"days"(hnsecs); |
| immutable daysHNSecs = convert!("days", "hnsecs")(days); |
| immutable negative = hnsecs < 0; |
| |
| if (negative) |
| hnsecs += convert!("hours", "hnsecs")(24); |
| |
| immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs); |
| immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs); |
| hnsecs = removeUnitsFromHNSecs!"seconds"(hnsecs); |
| |
| hnsecs += convert!("hours", "hnsecs")(hour); |
| hnsecs += convert!("minutes", "hnsecs")(minute); |
| hnsecs += convert!("seconds", "hnsecs")(second); |
| |
| if (negative) |
| hnsecs -= convert!("hours", "hnsecs")(24); |
| |
| adjTime = daysHNSecs + hnsecs; |
| } |
| |
| @safe unittest |
| { |
| import std.range : chain; |
| |
| foreach (second; testMinSecs) |
| { |
| foreach (st; chain(testSysTimesBC, testSysTimesAD)) |
| { |
| auto dt = cast(DateTime) st; |
| auto expected = SysTime(DateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute, second), |
| st.fracSecs, |
| st.timezone); |
| st.second = second; |
| assert(st == expected, format("[%s] [%s]", st, expected)); |
| } |
| } |
| |
| auto st = testSysTimesAD[0]; |
| assertThrown!DateTimeException(st.second = -1); |
| assertThrown!DateTimeException(st.second = 60); |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| static assert(!__traits(compiles, cst.seconds = 27)); |
| //static assert(!__traits(compiles, ist.seconds = 27)); |
| } |
| |
| |
| /++ |
| Fractional seconds past the second (i.e. the portion of a |
| $(LREF SysTime) which is less than a second). |
| +/ |
| @property Duration fracSecs() @safe const nothrow |
| { |
| auto hnsecs = removeUnitsFromHNSecs!"days"(adjTime); |
| |
| if (hnsecs < 0) |
| hnsecs += convert!("hours", "hnsecs")(24); |
| |
| return dur!"hnsecs"(removeUnitsFromHNSecs!"seconds"(hnsecs)); |
| } |
| |
| /// |
| @safe unittest |
| { |
| import core.time : msecs, usecs, hnsecs, nsecs; |
| import std.datetime.date : DateTime; |
| |
| auto dt = DateTime(1982, 4, 1, 20, 59, 22); |
| assert(SysTime(dt, msecs(213)).fracSecs == msecs(213)); |
| assert(SysTime(dt, usecs(5202)).fracSecs == usecs(5202)); |
| assert(SysTime(dt, hnsecs(1234567)).fracSecs == hnsecs(1234567)); |
| |
| // SysTime and Duration both have a precision of hnsecs (100 ns), |
| // so nsecs are going to be truncated. |
| assert(SysTime(dt, nsecs(123456789)).fracSecs == nsecs(123456700)); |
| } |
| |
| @safe unittest |
| { |
| import std.range : chain; |
| |
| assert(SysTime(0, UTC()).fracSecs == Duration.zero); |
| assert(SysTime(1, UTC()).fracSecs == hnsecs(1)); |
| assert(SysTime(-1, UTC()).fracSecs == hnsecs(9_999_999)); |
| |
| foreach (tz; testTZs) |
| { |
| foreach (year; chain(testYearsBC, testYearsAD)) |
| { |
| foreach (md; testMonthDays) |
| { |
| foreach (hour; testHours) |
| { |
| foreach (minute; testMinSecs) |
| { |
| foreach (second; testMinSecs) |
| { |
| auto dt = DateTime(Date(year, md.month, md.day), TimeOfDay(hour, minute, second)); |
| foreach (fs; testFracSecs) |
| assert(SysTime(dt, fs, tz).fracSecs == fs); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(cst.fracSecs == Duration.zero); |
| //assert(ist.fracSecs == Duration.zero); |
| } |
| |
| |
| /++ |
| Fractional seconds past the second (i.e. the portion of a |
| $(LREF SysTime) which is less than a second). |
| |
| Params: |
| fracSecs = The duration to set this $(LREF SysTime)'s fractional |
| seconds to. |
| |
| Throws: |
| $(REF DateTimeException,std,datetime,date) if the given duration |
| is negative or if it's greater than or equal to one second. |
| +/ |
| @property void fracSecs(Duration fracSecs) @safe |
| { |
| enforce(fracSecs >= Duration.zero, new DateTimeException("A SysTime cannot have negative fractional seconds.")); |
| enforce(fracSecs < seconds(1), new DateTimeException("Fractional seconds must be less than one second.")); |
| |
| auto oldHNSecs = adjTime; |
| auto days = splitUnitsFromHNSecs!"days"(oldHNSecs); |
| immutable daysHNSecs = convert!("days", "hnsecs")(days); |
| immutable negative = oldHNSecs < 0; |
| |
| if (negative) |
| oldHNSecs += convert!("hours", "hnsecs")(24); |
| |
| immutable seconds = splitUnitsFromHNSecs!"seconds"(oldHNSecs); |
| immutable secondsHNSecs = convert!("seconds", "hnsecs")(seconds); |
| auto newHNSecs = fracSecs.total!"hnsecs" + secondsHNSecs; |
| |
| if (negative) |
| newHNSecs -= convert!("hours", "hnsecs")(24); |
| |
| adjTime = daysHNSecs + newHNSecs; |
| } |
| |
| /// |
| @safe unittest |
| { |
| import core.time : Duration, msecs, hnsecs, nsecs; |
| import std.datetime.date : DateTime; |
| |
| auto st = SysTime(DateTime(1982, 4, 1, 20, 59, 22)); |
| assert(st.fracSecs == Duration.zero); |
| |
| st.fracSecs = msecs(213); |
| assert(st.fracSecs == msecs(213)); |
| |
| st.fracSecs = hnsecs(1234567); |
| assert(st.fracSecs == hnsecs(1234567)); |
| |
| // SysTime has a precision of hnsecs (100 ns), so nsecs are |
| // going to be truncated. |
| st.fracSecs = nsecs(123456789); |
| assert(st.fracSecs == hnsecs(1234567)); |
| } |
| |
| @safe unittest |
| { |
| import std.range : chain; |
| |
| foreach (fracSec; testFracSecs) |
| { |
| foreach (st; chain(testSysTimesBC, testSysTimesAD)) |
| { |
| auto dt = cast(DateTime) st; |
| auto expected = SysTime(dt, fracSec, st.timezone); |
| st.fracSecs = fracSec; |
| assert(st == expected, format("[%s] [%s]", st, expected)); |
| } |
| } |
| |
| auto st = testSysTimesAD[0]; |
| assertThrown!DateTimeException(st.fracSecs = hnsecs(-1)); |
| assertThrown!DateTimeException(st.fracSecs = seconds(1)); |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| static assert(!__traits(compiles, cst.fracSecs = msecs(7))); |
| //static assert(!__traits(compiles, ist.fracSecs = msecs(7))); |
| } |
| |
| |
| /++ |
| The total hnsecs from midnight, January 1st, 1 A.D. UTC. This is the |
| internal representation of $(LREF SysTime). |
| +/ |
| @property long stdTime() @safe const pure nothrow |
| { |
| return _stdTime; |
| } |
| |
| @safe unittest |
| { |
| assert(SysTime(0).stdTime == 0); |
| assert(SysTime(1).stdTime == 1); |
| assert(SysTime(-1).stdTime == -1); |
| assert(SysTime(DateTime(1, 1, 1, 0, 0, 33), hnsecs(502), UTC()).stdTime == 330_000_502L); |
| assert(SysTime(DateTime(1970, 1, 1, 0, 0, 0), UTC()).stdTime == 621_355_968_000_000_000L); |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(cst.stdTime > 0); |
| //assert(ist.stdTime > 0); |
| } |
| |
| |
| /++ |
| The total hnsecs from midnight, January 1st, 1 A.D. UTC. This is the |
| internal representation of $(LREF SysTime). |
| |
| Params: |
| stdTime = The number of hnsecs since January 1st, 1 A.D. UTC. |
| +/ |
| @property void stdTime(long stdTime) @safe pure nothrow |
| { |
| _stdTime = stdTime; |
| } |
| |
| @safe unittest |
| { |
| static void test(long stdTime, in SysTime expected, size_t line = __LINE__) |
| { |
| auto st = SysTime(0, UTC()); |
| st.stdTime = stdTime; |
| assert(st == expected); |
| } |
| |
| test(0, SysTime(Date(1, 1, 1), UTC())); |
| test(1, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1), UTC())); |
| test(-1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC())); |
| test(330_000_502L, SysTime(DateTime(1, 1, 1, 0, 0, 33), hnsecs(502), UTC())); |
| test(621_355_968_000_000_000L, SysTime(DateTime(1970, 1, 1, 0, 0, 0), UTC())); |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| static assert(!__traits(compiles, cst.stdTime = 27)); |
| //static assert(!__traits(compiles, ist.stdTime = 27)); |
| } |
| |
| |
| /++ |
| The current time zone of this $(LREF SysTime). Its internal time is |
| always kept in UTC, so there are no conversion issues between time zones |
| due to DST. Functions which return all or part of the time - such as |
| hours - adjust the time to this $(LREF SysTime)'s time zone before |
| returning. |
| +/ |
| @property immutable(TimeZone) timezone() @safe const pure nothrow |
| { |
| return _timezone; |
| } |
| |
| |
| /++ |
| The current time zone of this $(LREF SysTime). It's internal time is |
| always kept in UTC, so there are no conversion issues between time zones |
| due to DST. Functions which return all or part of the time - such as |
| hours - adjust the time to this $(LREF SysTime)'s time zone before |
| returning. |
| |
| Params: |
| timezone = The $(REF _TimeZone,std,datetime,_timezone) to set this |
| $(LREF SysTime)'s time zone to. |
| +/ |
| @property void timezone(immutable TimeZone timezone) @safe pure nothrow |
| { |
| if (timezone is null) |
| _timezone = LocalTime(); |
| else |
| _timezone = timezone; |
| } |
| |
| |
| /++ |
| Returns whether DST is in effect for this $(LREF SysTime). |
| +/ |
| @property bool dstInEffect() @safe const nothrow |
| { |
| return _timezone.dstInEffect(_stdTime); |
| // This function's unit testing is done in the time zone classes. |
| } |
| |
| |
| /++ |
| Returns what the offset from UTC is for this $(LREF SysTime). |
| It includes the DST offset in effect at that time (if any). |
| +/ |
| @property Duration utcOffset() @safe const nothrow |
| { |
| return _timezone.utcOffsetAt(_stdTime); |
| } |
| |
| |
| /++ |
| Returns a $(LREF SysTime) with the same std time as this one, but with |
| $(REF LocalTime,std,datetime,timezone) as its time zone. |
| +/ |
| SysTime toLocalTime() @safe const pure nothrow |
| { |
| return SysTime(_stdTime, LocalTime()); |
| } |
| |
| @safe unittest |
| { |
| { |
| auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), hnsecs(27)); |
| assert(sysTime == sysTime.toLocalTime()); |
| assert(sysTime._stdTime == sysTime.toLocalTime()._stdTime); |
| assert(sysTime.toLocalTime().timezone is LocalTime()); |
| assert(sysTime.toLocalTime().timezone is sysTime.timezone); |
| assert(sysTime.toLocalTime().timezone !is UTC()); |
| } |
| |
| { |
| auto stz = new immutable SimpleTimeZone(dur!"minutes"(-3 * 60)); |
| auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), hnsecs(27), stz); |
| assert(sysTime == sysTime.toLocalTime()); |
| assert(sysTime._stdTime == sysTime.toLocalTime()._stdTime); |
| assert(sysTime.toLocalTime().timezone is LocalTime()); |
| assert(sysTime.toLocalTime().timezone !is UTC()); |
| assert(sysTime.toLocalTime().timezone !is stz); |
| } |
| } |
| |
| |
| /++ |
| Returns a $(LREF SysTime) with the same std time as this one, but with |
| $(D UTC) as its time zone. |
| +/ |
| SysTime toUTC() @safe const pure nothrow |
| { |
| return SysTime(_stdTime, UTC()); |
| } |
| |
| @safe unittest |
| { |
| auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), hnsecs(27)); |
| assert(sysTime == sysTime.toUTC()); |
| assert(sysTime._stdTime == sysTime.toUTC()._stdTime); |
| assert(sysTime.toUTC().timezone is UTC()); |
| assert(sysTime.toUTC().timezone !is LocalTime()); |
| assert(sysTime.toUTC().timezone !is sysTime.timezone); |
| } |
| |
| |
| /++ |
| Returns a $(LREF SysTime) with the same std time as this one, but with |
| given time zone as its time zone. |
| +/ |
| SysTime toOtherTZ(immutable TimeZone tz) @safe const pure nothrow |
| { |
| if (tz is null) |
| return SysTime(_stdTime, LocalTime()); |
| else |
| return SysTime(_stdTime, tz); |
| } |
| |
| @safe unittest |
| { |
| auto stz = new immutable SimpleTimeZone(dur!"minutes"(11 * 60)); |
| auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), hnsecs(27)); |
| assert(sysTime == sysTime.toOtherTZ(stz)); |
| assert(sysTime._stdTime == sysTime.toOtherTZ(stz)._stdTime); |
| assert(sysTime.toOtherTZ(stz).timezone is stz); |
| assert(sysTime.toOtherTZ(stz).timezone !is LocalTime()); |
| assert(sysTime.toOtherTZ(stz).timezone !is UTC()); |
| } |
| |
| |
| /++ |
| Converts this $(LREF SysTime) to unix time (i.e. seconds from midnight, |
| January 1st, 1970 in UTC). |
| |
| The C standard does not specify the representation of time_t, so it is |
| implementation defined. On POSIX systems, unix time is equivalent to |
| time_t, but that's not necessarily true on other systems (e.g. it is |
| not true for the Digital Mars C runtime). So, be careful when using unix |
| time with C functions on non-POSIX systems. |
| |
| By default, the return type is time_t (which is normally an alias for |
| int on 32-bit systems and long on 64-bit systems), but if a different |
| size is required than either int or long can be passed as a template |
| argument to get the desired size. |
| |
| If the return type is int, and the result can't fit in an int, then the |
| closest value that can be held in 32 bits will be used (so $(D int.max) |
| if it goes over and $(D int.min) if it goes under). However, no attempt |
| is made to deal with integer overflow if the return type is long. |
| |
| Params: |
| T = The return type (int or long). It defaults to time_t, which is |
| normally 32 bits on a 32-bit system and 64 bits on a 64-bit |
| system. |
| |
| Returns: |
| A signed integer representing the unix time which is equivalent to |
| this SysTime. |
| +/ |
| T toUnixTime(T = time_t)() @safe const pure nothrow |
| if (is(T == int) || is(T == long)) |
| { |
| return stdTimeToUnixTime!T(_stdTime); |
| } |
| |
| /// |
| @safe unittest |
| { |
| import core.time : hours; |
| import std.datetime.date : DateTime; |
| import std.datetime.timezone : SimpleTimeZone, UTC; |
| |
| assert(SysTime(DateTime(1970, 1, 1), UTC()).toUnixTime() == 0); |
| |
| auto pst = new immutable SimpleTimeZone(hours(-8)); |
| assert(SysTime(DateTime(1970, 1, 1), pst).toUnixTime() == 28800); |
| |
| auto utc = SysTime(DateTime(2007, 12, 22, 8, 14, 45), UTC()); |
| assert(utc.toUnixTime() == 1_198_311_285); |
| |
| auto ca = SysTime(DateTime(2007, 12, 22, 8, 14, 45), pst); |
| assert(ca.toUnixTime() == 1_198_340_085); |
| } |
| |
| @safe unittest |
| { |
| import std.meta : AliasSeq; |
| assert(SysTime(DateTime(1970, 1, 1), UTC()).toUnixTime() == 0); |
| foreach (units; AliasSeq!("hnsecs", "usecs", "msecs")) |
| assert(SysTime(DateTime(1970, 1, 1, 0, 0, 0), dur!units(1), UTC()).toUnixTime() == 0); |
| assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), UTC()).toUnixTime() == 1); |
| assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toUnixTime() == 0); |
| assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), usecs(999_999), UTC()).toUnixTime() == 0); |
| assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), msecs(999), UTC()).toUnixTime() == 0); |
| assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), UTC()).toUnixTime() == -1); |
| } |
| |
| |
| /++ |
| Converts from unix time (i.e. seconds from midnight, January 1st, 1970 |
| in UTC) to a $(LREF SysTime). |
| |
| The C standard does not specify the representation of time_t, so it is |
| implementation defined. On POSIX systems, unix time is equivalent to |
| time_t, but that's not necessarily true on other systems (e.g. it is |
| not true for the Digital Mars C runtime). So, be careful when using unix |
| time with C functions on non-POSIX systems. |
| |
| Params: |
| unixTime = Seconds from midnight, January 1st, 1970 in UTC. |
| tz = The time zone for the SysTime that's returned. |
| +/ |
| static SysTime fromUnixTime(long unixTime, immutable TimeZone tz = LocalTime()) @safe pure nothrow |
| { |
| return SysTime(unixTimeToStdTime(unixTime), tz); |
| } |
| |
| /// |
| @safe unittest |
| { |
| import core.time : hours; |
| import std.datetime.date : DateTime; |
| import std.datetime.timezone : SimpleTimeZone, UTC; |
| |
| assert(SysTime.fromUnixTime(0) == |
| SysTime(DateTime(1970, 1, 1), UTC())); |
| |
| auto pst = new immutable SimpleTimeZone(hours(-8)); |
| assert(SysTime.fromUnixTime(28800) == |
| SysTime(DateTime(1970, 1, 1), pst)); |
| |
| auto st1 = SysTime.fromUnixTime(1_198_311_285, UTC()); |
| assert(st1 == SysTime(DateTime(2007, 12, 22, 8, 14, 45), UTC())); |
| assert(st1.timezone is UTC()); |
| assert(st1 == SysTime(DateTime(2007, 12, 22, 0, 14, 45), pst)); |
| |
| auto st2 = SysTime.fromUnixTime(1_198_311_285, pst); |
| assert(st2 == SysTime(DateTime(2007, 12, 22, 8, 14, 45), UTC())); |
| assert(st2.timezone is pst); |
| assert(st2 == SysTime(DateTime(2007, 12, 22, 0, 14, 45), pst)); |
| } |
| |
| @safe unittest |
| { |
| assert(SysTime.fromUnixTime(0) == SysTime(DateTime(1970, 1, 1), UTC())); |
| assert(SysTime.fromUnixTime(1) == SysTime(DateTime(1970, 1, 1, 0, 0, 1), UTC())); |
| assert(SysTime.fromUnixTime(-1) == SysTime(DateTime(1969, 12, 31, 23, 59, 59), UTC())); |
| |
| auto st = SysTime.fromUnixTime(0); |
| auto dt = cast(DateTime) st; |
| assert(dt <= DateTime(1970, 2, 1) && dt >= DateTime(1969, 12, 31)); |
| assert(st.timezone is LocalTime()); |
| |
| auto aest = new immutable SimpleTimeZone(hours(10)); |
| assert(SysTime.fromUnixTime(-36000) == SysTime(DateTime(1970, 1, 1), aest)); |
| } |
| |
| |
| /++ |
| Returns a $(D timeval) which represents this $(LREF SysTime). |
| |
| Note that like all conversions in std.datetime, this is a truncating |
| conversion. |
| |
| If $(D timeval.tv_sec) is int, and the result can't fit in an int, then |
| the closest value that can be held in 32 bits will be used for |
| $(D tv_sec). (so $(D int.max) if it goes over and $(D int.min) if it |
| goes under). |
| +/ |
| timeval toTimeVal() @safe const pure nothrow |
| { |
| immutable tv_sec = toUnixTime!(typeof(timeval.tv_sec))(); |
| immutable fracHNSecs = removeUnitsFromHNSecs!"seconds"(_stdTime - 621_355_968_000_000_000L); |
| immutable tv_usec = cast(typeof(timeval.tv_usec))convert!("hnsecs", "usecs")(fracHNSecs); |
| return timeval(tv_sec, tv_usec); |
| } |
| |
| @safe unittest |
| { |
| assert(SysTime(DateTime(1970, 1, 1), UTC()).toTimeVal() == timeval(0, 0)); |
| assert(SysTime(DateTime(1970, 1, 1), hnsecs(9), UTC()).toTimeVal() == timeval(0, 0)); |
| assert(SysTime(DateTime(1970, 1, 1), hnsecs(10), UTC()).toTimeVal() == timeval(0, 1)); |
| assert(SysTime(DateTime(1970, 1, 1), usecs(7), UTC()).toTimeVal() == timeval(0, 7)); |
| |
| assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), UTC()).toTimeVal() == timeval(1, 0)); |
| assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), hnsecs(9), UTC()).toTimeVal() == timeval(1, 0)); |
| assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), hnsecs(10), UTC()).toTimeVal() == timeval(1, 1)); |
| assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), usecs(7), UTC()).toTimeVal() == timeval(1, 7)); |
| |
| assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toTimeVal() == timeval(0, 0)); |
| assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), hnsecs(9_999_990), UTC()).toTimeVal() == timeval(0, -1)); |
| |
| assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), usecs(999_999), UTC()).toTimeVal() == timeval(0, -1)); |
| assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), usecs(999), UTC()).toTimeVal() == timeval(0, -999_001)); |
| assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), msecs(999), UTC()).toTimeVal() == timeval(0, -1000)); |
| assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), UTC()).toTimeVal() == timeval(-1, 0)); |
| assert(SysTime(DateTime(1969, 12, 31, 23, 59, 58), usecs(17), UTC()).toTimeVal() == timeval(-1, -999_983)); |
| } |
| |
| |
| version (StdDdoc) |
| { |
| private struct timespec {} |
| /++ |
| Returns a $(D timespec) which represents this $(LREF SysTime). |
| |
| $(BLUE This function is Posix-Only.) |
| +/ |
| timespec toTimeSpec() @safe const pure nothrow; |
| } |
| else version (Posix) |
| { |
| timespec toTimeSpec() @safe const pure nothrow |
| { |
| immutable tv_sec = toUnixTime!(typeof(timespec.tv_sec))(); |
| immutable fracHNSecs = removeUnitsFromHNSecs!"seconds"(_stdTime - 621_355_968_000_000_000L); |
| immutable tv_nsec = cast(typeof(timespec.tv_nsec))convert!("hnsecs", "nsecs")(fracHNSecs); |
| return timespec(tv_sec, tv_nsec); |
| } |
| |
| @safe unittest |
| { |
| assert(SysTime(DateTime(1970, 1, 1), UTC()).toTimeSpec() == timespec(0, 0)); |
| assert(SysTime(DateTime(1970, 1, 1), hnsecs(9), UTC()).toTimeSpec() == timespec(0, 900)); |
| assert(SysTime(DateTime(1970, 1, 1), hnsecs(10), UTC()).toTimeSpec() == timespec(0, 1000)); |
| assert(SysTime(DateTime(1970, 1, 1), usecs(7), UTC()).toTimeSpec() == timespec(0, 7000)); |
| |
| assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), UTC()).toTimeSpec() == timespec(1, 0)); |
| assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), hnsecs(9), UTC()).toTimeSpec() == timespec(1, 900)); |
| assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), hnsecs(10), UTC()).toTimeSpec() == timespec(1, 1000)); |
| assert(SysTime(DateTime(1970, 1, 1, 0, 0, 1), usecs(7), UTC()).toTimeSpec() == timespec(1, 7000)); |
| |
| assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toTimeSpec() == |
| timespec(0, -100)); |
| assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), hnsecs(9_999_990), UTC()).toTimeSpec() == |
| timespec(0, -1000)); |
| |
| assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), usecs(999_999), UTC()).toTimeSpec() == |
| timespec(0, -1_000)); |
| assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), usecs(999), UTC()).toTimeSpec() == |
| timespec(0, -999_001_000)); |
| assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), msecs(999), UTC()).toTimeSpec() == |
| timespec(0, -1_000_000)); |
| assert(SysTime(DateTime(1969, 12, 31, 23, 59, 59), UTC()).toTimeSpec() == |
| timespec(-1, 0)); |
| assert(SysTime(DateTime(1969, 12, 31, 23, 59, 58), usecs(17), UTC()).toTimeSpec() == |
| timespec(-1, -999_983_000)); |
| } |
| } |
| |
| /++ |
| Returns a $(D tm) which represents this $(LREF SysTime). |
| +/ |
| tm toTM() @safe const nothrow |
| { |
| auto dateTime = cast(DateTime) this; |
| tm timeInfo; |
| |
| timeInfo.tm_sec = dateTime.second; |
| timeInfo.tm_min = dateTime.minute; |
| timeInfo.tm_hour = dateTime.hour; |
| timeInfo.tm_mday = dateTime.day; |
| timeInfo.tm_mon = dateTime.month - 1; |
| timeInfo.tm_year = dateTime.year - 1900; |
| timeInfo.tm_wday = dateTime.dayOfWeek; |
| timeInfo.tm_yday = dateTime.dayOfYear - 1; |
| timeInfo.tm_isdst = _timezone.dstInEffect(_stdTime); |
| |
| version (Posix) |
| { |
| import std.utf : toUTFz; |
| timeInfo.tm_gmtoff = cast(int) convert!("hnsecs", "seconds")(adjTime - _stdTime); |
| auto zone = (timeInfo.tm_isdst ? _timezone.dstName : _timezone.stdName); |
| timeInfo.tm_zone = zone.toUTFz!(char*)(); |
| } |
| |
| return timeInfo; |
| } |
| |
| @system unittest |
| { |
| import std.conv : to; |
| |
| version (Posix) |
| { |
| scope(exit) clearTZEnvVar(); |
| setTZEnvVar("America/Los_Angeles"); |
| } |
| |
| { |
| auto timeInfo = SysTime(DateTime(1970, 1, 1)).toTM(); |
| |
| assert(timeInfo.tm_sec == 0); |
| assert(timeInfo.tm_min == 0); |
| assert(timeInfo.tm_hour == 0); |
| assert(timeInfo.tm_mday == 1); |
| assert(timeInfo.tm_mon == 0); |
| assert(timeInfo.tm_year == 70); |
| assert(timeInfo.tm_wday == 4); |
| assert(timeInfo.tm_yday == 0); |
| |
| version (Posix) |
| assert(timeInfo.tm_isdst == 0); |
| else version (Windows) |
| assert(timeInfo.tm_isdst == 0 || timeInfo.tm_isdst == 1); |
| |
| version (Posix) |
| { |
| assert(timeInfo.tm_gmtoff == -8 * 60 * 60); |
| assert(to!string(timeInfo.tm_zone) == "PST"); |
| } |
| } |
| |
| { |
| auto timeInfo = SysTime(DateTime(2010, 7, 4, 12, 15, 7), hnsecs(15)).toTM(); |
| |
| assert(timeInfo.tm_sec == 7); |
| assert(timeInfo.tm_min == 15); |
| assert(timeInfo.tm_hour == 12); |
| assert(timeInfo.tm_mday == 4); |
| assert(timeInfo.tm_mon == 6); |
| assert(timeInfo.tm_year == 110); |
| assert(timeInfo.tm_wday == 0); |
| assert(timeInfo.tm_yday == 184); |
| |
| version (Posix) |
| assert(timeInfo.tm_isdst == 1); |
| else version (Windows) |
| assert(timeInfo.tm_isdst == 0 || timeInfo.tm_isdst == 1); |
| |
| version (Posix) |
| { |
| assert(timeInfo.tm_gmtoff == -7 * 60 * 60); |
| assert(to!string(timeInfo.tm_zone) == "PDT"); |
| } |
| } |
| } |
| |
| |
| /++ |
| Adds the given number of years or months to this $(LREF SysTime). A |
| negative number will subtract. |
| |
| Note that if day overflow is allowed, and the date with the adjusted |
| year/month overflows the number of days in the new month, then the month |
| will be incremented by one, and the day set to the number of days |
| overflowed. (e.g. if the day were 31 and the new month were June, then |
| the month would be incremented to July, and the new day would be 1). If |
| day overflow is not allowed, then the day will be set to the last valid |
| day in the month (e.g. June 31st would become June 30th). |
| |
| Params: |
| units = The type of units to add ("years" or "months"). |
| value = The number of months or years to add to this |
| $(LREF SysTime). |
| allowOverflow = Whether the days should be allowed to overflow, |
| causing the month to increment. |
| +/ |
| ref SysTime add(string units)(long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) @safe nothrow |
| if (units == "years" || units == "months") |
| { |
| auto hnsecs = adjTime; |
| auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1; |
| |
| if (hnsecs < 0) |
| { |
| hnsecs += convert!("hours", "hnsecs")(24); |
| --days; |
| } |
| |
| auto date = Date(cast(int) days); |
| date.add!units(value, allowOverflow); |
| days = date.dayOfGregorianCal - 1; |
| |
| if (days < 0) |
| { |
| hnsecs -= convert!("hours", "hnsecs")(24); |
| ++days; |
| } |
| |
| immutable newDaysHNSecs = convert!("days", "hnsecs")(days); |
| |
| adjTime = newDaysHNSecs + hnsecs; |
| |
| return this; |
| } |
| |
| @safe unittest |
| { |
| auto st1 = SysTime(DateTime(2010, 1, 1, 12, 30, 33)); |
| st1.add!"months"(11); |
| assert(st1 == SysTime(DateTime(2010, 12, 1, 12, 30, 33))); |
| |
| auto st2 = SysTime(DateTime(2010, 1, 1, 12, 30, 33)); |
| st2.add!"months"(-11); |
| assert(st2 == SysTime(DateTime(2009, 2, 1, 12, 30, 33))); |
| |
| auto st3 = SysTime(DateTime(2000, 2, 29, 12, 30, 33)); |
| st3.add!"years"(1); |
| assert(st3 == SysTime(DateTime(2001, 3, 1, 12, 30, 33))); |
| |
| auto st4 = SysTime(DateTime(2000, 2, 29, 12, 30, 33)); |
| st4.add!"years"(1, AllowDayOverflow.no); |
| assert(st4 == SysTime(DateTime(2001, 2, 28, 12, 30, 33))); |
| } |
| |
| // Test add!"years"() with AllowDayOverflow.yes |
| @safe unittest |
| { |
| // Test A.D. |
| { |
| auto sysTime = SysTime(Date(1999, 7, 6)); |
| sysTime.add!"years"(7); |
| assert(sysTime == SysTime(Date(2006, 7, 6))); |
| sysTime.add!"years"(-9); |
| assert(sysTime == SysTime(Date(1997, 7, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 2, 28)); |
| sysTime.add!"years"(1); |
| assert(sysTime == SysTime(Date(2000, 2, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(2000, 2, 29)); |
| sysTime.add!"years"(-1); |
| assert(sysTime == SysTime(Date(1999, 3, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 7, 3), msecs(234)); |
| sysTime.add!"years"(7); |
| assert(sysTime == SysTime(DateTime(2006, 7, 6, 12, 7, 3), msecs(234))); |
| sysTime.add!"years"(-9); |
| assert(sysTime == SysTime(DateTime(1997, 7, 6, 12, 7, 3), msecs(234))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1999, 2, 28, 0, 7, 2), usecs(1207)); |
| sysTime.add!"years"(1); |
| assert(sysTime == SysTime(DateTime(2000, 2, 28, 0, 7, 2), usecs(1207))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(2000, 2, 29, 0, 7, 2), usecs(1207)); |
| sysTime.add!"years"(-1); |
| assert(sysTime == SysTime(DateTime(1999, 3, 1, 0, 7, 2), usecs(1207))); |
| } |
| |
| // Test B.C. |
| { |
| auto sysTime = SysTime(Date(-1999, 7, 6)); |
| sysTime.add!"years"(-7); |
| assert(sysTime == SysTime(Date(-2006, 7, 6))); |
| sysTime.add!"years"(9); |
| assert(sysTime == SysTime(Date(-1997, 7, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 2, 28)); |
| sysTime.add!"years"(-1); |
| assert(sysTime == SysTime(Date(-2000, 2, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-2000, 2, 29)); |
| sysTime.add!"years"(1); |
| assert(sysTime == SysTime(Date(-1999, 3, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 7, 3), msecs(234)); |
| sysTime.add!"years"(-7); |
| assert(sysTime == SysTime(DateTime(-2006, 7, 6, 12, 7, 3), msecs(234))); |
| sysTime.add!"years"(9); |
| assert(sysTime == SysTime(DateTime(-1997, 7, 6, 12, 7, 3), msecs(234))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-1999, 2, 28, 3, 3, 3), hnsecs(3)); |
| sysTime.add!"years"(-1); |
| assert(sysTime == SysTime(DateTime(-2000, 2, 28, 3, 3, 3), hnsecs(3))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-2000, 2, 29, 3, 3, 3), hnsecs(3)); |
| sysTime.add!"years"(1); |
| assert(sysTime == SysTime(DateTime(-1999, 3, 1, 3, 3, 3), hnsecs(3))); |
| } |
| |
| // Test Both |
| { |
| auto sysTime = SysTime(Date(4, 7, 6)); |
| sysTime.add!"years"(-5); |
| assert(sysTime == SysTime(Date(-1, 7, 6))); |
| sysTime.add!"years"(5); |
| assert(sysTime == SysTime(Date(4, 7, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-4, 7, 6)); |
| sysTime.add!"years"(5); |
| assert(sysTime == SysTime(Date(1, 7, 6))); |
| sysTime.add!"years"(-5); |
| assert(sysTime == SysTime(Date(-4, 7, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(4, 7, 6)); |
| sysTime.add!"years"(-8); |
| assert(sysTime == SysTime(Date(-4, 7, 6))); |
| sysTime.add!"years"(8); |
| assert(sysTime == SysTime(Date(4, 7, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-4, 7, 6)); |
| sysTime.add!"years"(8); |
| assert(sysTime == SysTime(Date(4, 7, 6))); |
| sysTime.add!"years"(-8); |
| assert(sysTime == SysTime(Date(-4, 7, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-4, 2, 29)); |
| sysTime.add!"years"(5); |
| assert(sysTime == SysTime(Date(1, 3, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(4, 2, 29)); |
| sysTime.add!"years"(-5); |
| assert(sysTime == SysTime(Date(-1, 3, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0)); |
| sysTime.add!"years"(-1); |
| assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0))); |
| sysTime.add!"years"(1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)); |
| sysTime.add!"years"(-1); |
| assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999))); |
| sysTime.add!"years"(1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(0, 1, 1, 0, 0, 0)); |
| sysTime.add!"years"(1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| sysTime.add!"years"(-1); |
| assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)); |
| sysTime.add!"years"(1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999))); |
| sysTime.add!"years"(-1); |
| assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329)); |
| sysTime.add!"years"(-5); |
| assert(sysTime == SysTime(DateTime(-1, 7, 6, 14, 7, 1), usecs(54329))); |
| sysTime.add!"years"(5); |
| assert(sysTime == SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-4, 7, 6, 14, 7, 1), usecs(54329)); |
| sysTime.add!"years"(5); |
| assert(sysTime == SysTime(DateTime(1, 7, 6, 14, 7, 1), usecs(54329))); |
| sysTime.add!"years"(-5); |
| assert(sysTime == SysTime(DateTime(-4, 7, 6, 14, 7, 1), usecs(54329))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-4, 2, 29, 5, 5, 5), msecs(555)); |
| sysTime.add!"years"(5); |
| assert(sysTime == SysTime(DateTime(1, 3, 1, 5, 5, 5), msecs(555))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(4, 2, 29, 5, 5, 5), msecs(555)); |
| sysTime.add!"years"(-5); |
| assert(sysTime == SysTime(DateTime(-1, 3, 1, 5, 5, 5), msecs(555))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(4, 2, 29, 5, 5, 5), msecs(555)); |
| sysTime.add!"years"(-5).add!"years"(7); |
| assert(sysTime == SysTime(DateTime(6, 3, 1, 5, 5, 5), msecs(555))); |
| } |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| static assert(!__traits(compiles, cst.add!"years"(4))); |
| //static assert(!__traits(compiles, ist.add!"years"(4))); |
| } |
| |
| // Test add!"years"() with AllowDayOverflow.no |
| @safe unittest |
| { |
| // Test A.D. |
| { |
| auto sysTime = SysTime(Date(1999, 7, 6)); |
| sysTime.add!"years"(7, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(2006, 7, 6))); |
| sysTime.add!"years"(-9, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1997, 7, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 2, 28)); |
| sysTime.add!"years"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(2000, 2, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(2000, 2, 29)); |
| sysTime.add!"years"(-1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 2, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 7, 3), msecs(234)); |
| sysTime.add!"years"(7, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(2006, 7, 6, 12, 7, 3), msecs(234))); |
| sysTime.add!"years"(-9, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1997, 7, 6, 12, 7, 3), msecs(234))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1999, 2, 28, 0, 7, 2), usecs(1207)); |
| sysTime.add!"years"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(2000, 2, 28, 0, 7, 2), usecs(1207))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(2000, 2, 29, 0, 7, 2), usecs(1207)); |
| sysTime.add!"years"(-1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1999, 2, 28, 0, 7, 2), usecs(1207))); |
| } |
| |
| // Test B.C. |
| { |
| auto sysTime = SysTime(Date(-1999, 7, 6)); |
| sysTime.add!"years"(-7, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-2006, 7, 6))); |
| sysTime.add!"years"(9, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1997, 7, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 2, 28)); |
| sysTime.add!"years"(-1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-2000, 2, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-2000, 2, 29)); |
| sysTime.add!"years"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1999, 2, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 7, 3), msecs(234)); |
| sysTime.add!"years"(-7, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(-2006, 7, 6, 12, 7, 3), msecs(234))); |
| sysTime.add!"years"(9, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(-1997, 7, 6, 12, 7, 3), msecs(234))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-1999, 2, 28, 3, 3, 3), hnsecs(3)); |
| sysTime.add!"years"(-1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(-2000, 2, 28, 3, 3, 3), hnsecs(3))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-2000, 2, 29, 3, 3, 3), hnsecs(3)); |
| sysTime.add!"years"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(-1999, 2, 28, 3, 3, 3), hnsecs(3))); |
| } |
| |
| // Test Both |
| { |
| auto sysTime = SysTime(Date(4, 7, 6)); |
| sysTime.add!"years"(-5, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1, 7, 6))); |
| sysTime.add!"years"(5, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(4, 7, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-4, 7, 6)); |
| sysTime.add!"years"(5, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1, 7, 6))); |
| sysTime.add!"years"(-5, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-4, 7, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(4, 7, 6)); |
| sysTime.add!"years"(-8, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-4, 7, 6))); |
| sysTime.add!"years"(8, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(4, 7, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-4, 7, 6)); |
| sysTime.add!"years"(8, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(4, 7, 6))); |
| sysTime.add!"years"(-8, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-4, 7, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-4, 2, 29)); |
| sysTime.add!"years"(5, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1, 2, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(4, 2, 29)); |
| sysTime.add!"years"(-5, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1, 2, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0)); |
| sysTime.add!"years"(-1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0))); |
| sysTime.add!"years"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)); |
| sysTime.add!"years"(-1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999))); |
| sysTime.add!"years"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(0, 1, 1, 0, 0, 0)); |
| sysTime.add!"years"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| sysTime.add!"years"(-1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)); |
| sysTime.add!"years"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999))); |
| sysTime.add!"years"(-1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329)); |
| sysTime.add!"years"(-5); |
| assert(sysTime == SysTime(DateTime(-1, 7, 6, 14, 7, 1), usecs(54329))); |
| sysTime.add!"years"(5); |
| assert(sysTime == SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329)); |
| sysTime.add!"years"(-5, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(-1, 7, 6, 14, 7, 1), usecs(54329))); |
| sysTime.add!"years"(5, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(4, 7, 6, 14, 7, 1), usecs(54329))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-4, 7, 6, 14, 7, 1), usecs(54329)); |
| sysTime.add!"years"(5, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1, 7, 6, 14, 7, 1), usecs(54329))); |
| sysTime.add!"years"(-5, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(-4, 7, 6, 14, 7, 1), usecs(54329))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-4, 2, 29, 5, 5, 5), msecs(555)); |
| sysTime.add!"years"(5, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1, 2, 28, 5, 5, 5), msecs(555))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(4, 2, 29, 5, 5, 5), msecs(555)); |
| sysTime.add!"years"(-5, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(-1, 2, 28, 5, 5, 5), msecs(555))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(4, 2, 29, 5, 5, 5), msecs(555)); |
| sysTime.add!"years"(-5, AllowDayOverflow.no).add!"years"(7, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(6, 2, 28, 5, 5, 5), msecs(555))); |
| } |
| } |
| |
| // Test add!"months"() with AllowDayOverflow.yes |
| @safe unittest |
| { |
| // Test A.D. |
| { |
| auto sysTime = SysTime(Date(1999, 7, 6)); |
| sysTime.add!"months"(3); |
| assert(sysTime == SysTime(Date(1999, 10, 6))); |
| sysTime.add!"months"(-4); |
| assert(sysTime == SysTime(Date(1999, 6, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 7, 6)); |
| sysTime.add!"months"(6); |
| assert(sysTime == SysTime(Date(2000, 1, 6))); |
| sysTime.add!"months"(-6); |
| assert(sysTime == SysTime(Date(1999, 7, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 7, 6)); |
| sysTime.add!"months"(27); |
| assert(sysTime == SysTime(Date(2001, 10, 6))); |
| sysTime.add!"months"(-28); |
| assert(sysTime == SysTime(Date(1999, 6, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 5, 31)); |
| sysTime.add!"months"(1); |
| assert(sysTime == SysTime(Date(1999, 7, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 5, 31)); |
| sysTime.add!"months"(-1); |
| assert(sysTime == SysTime(Date(1999, 5, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 2, 28)); |
| sysTime.add!"months"(12); |
| assert(sysTime == SysTime(Date(2000, 2, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(2000, 2, 29)); |
| sysTime.add!"months"(12); |
| assert(sysTime == SysTime(Date(2001, 3, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 7, 31)); |
| sysTime.add!"months"(1); |
| assert(sysTime == SysTime(Date(1999, 8, 31))); |
| sysTime.add!"months"(1); |
| assert(sysTime == SysTime(Date(1999, 10, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1998, 8, 31)); |
| sysTime.add!"months"(13); |
| assert(sysTime == SysTime(Date(1999, 10, 1))); |
| sysTime.add!"months"(-13); |
| assert(sysTime == SysTime(Date(1998, 9, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1997, 12, 31)); |
| sysTime.add!"months"(13); |
| assert(sysTime == SysTime(Date(1999, 1, 31))); |
| sysTime.add!"months"(-13); |
| assert(sysTime == SysTime(Date(1997, 12, 31))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1997, 12, 31)); |
| sysTime.add!"months"(14); |
| assert(sysTime == SysTime(Date(1999, 3, 3))); |
| sysTime.add!"months"(-14); |
| assert(sysTime == SysTime(Date(1998, 1, 3))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1998, 12, 31)); |
| sysTime.add!"months"(14); |
| assert(sysTime == SysTime(Date(2000, 3, 2))); |
| sysTime.add!"months"(-14); |
| assert(sysTime == SysTime(Date(1999, 1, 2))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 12, 31)); |
| sysTime.add!"months"(14); |
| assert(sysTime == SysTime(Date(2001, 3, 3))); |
| sysTime.add!"months"(-14); |
| assert(sysTime == SysTime(Date(2000, 1, 3))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), usecs(5007)); |
| sysTime.add!"months"(3); |
| assert(sysTime == SysTime(DateTime(1999, 10, 6, 12, 2, 7), usecs(5007))); |
| sysTime.add!"months"(-4); |
| assert(sysTime == SysTime(DateTime(1999, 6, 6, 12, 2, 7), usecs(5007))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), hnsecs(422202)); |
| sysTime.add!"months"(14); |
| assert(sysTime == SysTime(DateTime(2000, 3, 2, 7, 7, 7), hnsecs(422202))); |
| sysTime.add!"months"(-14); |
| assert(sysTime == SysTime(DateTime(1999, 1, 2, 7, 7, 7), hnsecs(422202))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), hnsecs(422202)); |
| sysTime.add!"months"(14); |
| assert(sysTime == SysTime(DateTime(2001, 3, 3, 7, 7, 7), hnsecs(422202))); |
| sysTime.add!"months"(-14); |
| assert(sysTime == SysTime(DateTime(2000, 1, 3, 7, 7, 7), hnsecs(422202))); |
| } |
| |
| // Test B.C. |
| { |
| auto sysTime = SysTime(Date(-1999, 7, 6)); |
| sysTime.add!"months"(3); |
| assert(sysTime == SysTime(Date(-1999, 10, 6))); |
| sysTime.add!"months"(-4); |
| assert(sysTime == SysTime(Date(-1999, 6, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 7, 6)); |
| sysTime.add!"months"(6); |
| assert(sysTime == SysTime(Date(-1998, 1, 6))); |
| sysTime.add!"months"(-6); |
| assert(sysTime == SysTime(Date(-1999, 7, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 7, 6)); |
| sysTime.add!"months"(-27); |
| assert(sysTime == SysTime(Date(-2001, 4, 6))); |
| sysTime.add!"months"(28); |
| assert(sysTime == SysTime(Date(-1999, 8, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 5, 31)); |
| sysTime.add!"months"(1); |
| assert(sysTime == SysTime(Date(-1999, 7, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 5, 31)); |
| sysTime.add!"months"(-1); |
| assert(sysTime == SysTime(Date(-1999, 5, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 2, 28)); |
| sysTime.add!"months"(-12); |
| assert(sysTime == SysTime(Date(-2000, 2, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-2000, 2, 29)); |
| sysTime.add!"months"(-12); |
| assert(sysTime == SysTime(Date(-2001, 3, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 7, 31)); |
| sysTime.add!"months"(1); |
| assert(sysTime == SysTime(Date(-1999, 8, 31))); |
| sysTime.add!"months"(1); |
| assert(sysTime == SysTime(Date(-1999, 10, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1998, 8, 31)); |
| sysTime.add!"months"(13); |
| assert(sysTime == SysTime(Date(-1997, 10, 1))); |
| sysTime.add!"months"(-13); |
| assert(sysTime == SysTime(Date(-1998, 9, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1997, 12, 31)); |
| sysTime.add!"months"(13); |
| assert(sysTime == SysTime(Date(-1995, 1, 31))); |
| sysTime.add!"months"(-13); |
| assert(sysTime == SysTime(Date(-1997, 12, 31))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1997, 12, 31)); |
| sysTime.add!"months"(14); |
| assert(sysTime == SysTime(Date(-1995, 3, 3))); |
| sysTime.add!"months"(-14); |
| assert(sysTime == SysTime(Date(-1996, 1, 3))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-2002, 12, 31)); |
| sysTime.add!"months"(14); |
| assert(sysTime == SysTime(Date(-2000, 3, 2))); |
| sysTime.add!"months"(-14); |
| assert(sysTime == SysTime(Date(-2001, 1, 2))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-2001, 12, 31)); |
| sysTime.add!"months"(14); |
| assert(sysTime == SysTime(Date(-1999, 3, 3))); |
| sysTime.add!"months"(-14); |
| assert(sysTime == SysTime(Date(-2000, 1, 3))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), usecs(5007)); |
| sysTime.add!"months"(3); |
| assert(sysTime == SysTime(DateTime(-1999, 10, 6, 12, 2, 7), usecs(5007))); |
| sysTime.add!"months"(-4); |
| assert(sysTime == SysTime(DateTime(-1999, 6, 6, 12, 2, 7), usecs(5007))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), hnsecs(422202)); |
| sysTime.add!"months"(14); |
| assert(sysTime == SysTime(DateTime(-2000, 3, 2, 7, 7, 7), hnsecs(422202))); |
| sysTime.add!"months"(-14); |
| assert(sysTime == SysTime(DateTime(-2001, 1, 2, 7, 7, 7), hnsecs(422202))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), hnsecs(422202)); |
| sysTime.add!"months"(14); |
| assert(sysTime == SysTime(DateTime(-1999, 3, 3, 7, 7, 7), hnsecs(422202))); |
| sysTime.add!"months"(-14); |
| assert(sysTime == SysTime(DateTime(-2000, 1, 3, 7, 7, 7), hnsecs(422202))); |
| } |
| |
| // Test Both |
| { |
| auto sysTime = SysTime(Date(1, 1, 1)); |
| sysTime.add!"months"(-1); |
| assert(sysTime == SysTime(Date(0, 12, 1))); |
| sysTime.add!"months"(1); |
| assert(sysTime == SysTime(Date(1, 1, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(4, 1, 1)); |
| sysTime.add!"months"(-48); |
| assert(sysTime == SysTime(Date(0, 1, 1))); |
| sysTime.add!"months"(48); |
| assert(sysTime == SysTime(Date(4, 1, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(4, 3, 31)); |
| sysTime.add!"months"(-49); |
| assert(sysTime == SysTime(Date(0, 3, 2))); |
| sysTime.add!"months"(49); |
| assert(sysTime == SysTime(Date(4, 4, 2))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(4, 3, 31)); |
| sysTime.add!"months"(-85); |
| assert(sysTime == SysTime(Date(-3, 3, 3))); |
| sysTime.add!"months"(85); |
| assert(sysTime == SysTime(Date(4, 4, 3))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0)); |
| sysTime.add!"months"(-1); |
| assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0))); |
| sysTime.add!"months"(1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)); |
| sysTime.add!"months"(-1); |
| assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999))); |
| sysTime.add!"months"(1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0)); |
| sysTime.add!"months"(1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| sysTime.add!"months"(-1); |
| assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)); |
| sysTime.add!"months"(1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999))); |
| sysTime.add!"months"(-1); |
| assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17)); |
| sysTime.add!"months"(-1); |
| assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 7, 9), hnsecs(17))); |
| sysTime.add!"months"(1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), msecs(9)); |
| sysTime.add!"months"(-85); |
| assert(sysTime == SysTime(DateTime(-3, 3, 3, 12, 11, 10), msecs(9))); |
| sysTime.add!"months"(85); |
| assert(sysTime == SysTime(DateTime(4, 4, 3, 12, 11, 10), msecs(9))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9)); |
| sysTime.add!"months"(85); |
| assert(sysTime == SysTime(DateTime(4, 5, 1, 12, 11, 10), msecs(9))); |
| sysTime.add!"months"(-85); |
| assert(sysTime == SysTime(DateTime(-3, 4, 1, 12, 11, 10), msecs(9))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9)); |
| sysTime.add!"months"(85).add!"months"(-83); |
| assert(sysTime == SysTime(DateTime(-3, 6, 1, 12, 11, 10), msecs(9))); |
| } |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| static assert(!__traits(compiles, cst.add!"months"(4))); |
| //static assert(!__traits(compiles, ist.add!"months"(4))); |
| } |
| |
| // Test add!"months"() with AllowDayOverflow.no |
| @safe unittest |
| { |
| // Test A.D. |
| { |
| auto sysTime = SysTime(Date(1999, 7, 6)); |
| sysTime.add!"months"(3, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 10, 6))); |
| sysTime.add!"months"(-4, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 6, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 7, 6)); |
| sysTime.add!"months"(6, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(2000, 1, 6))); |
| sysTime.add!"months"(-6, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 7, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 7, 6)); |
| sysTime.add!"months"(27, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(2001, 10, 6))); |
| sysTime.add!"months"(-28, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 6, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 5, 31)); |
| sysTime.add!"months"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 6, 30))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 5, 31)); |
| sysTime.add!"months"(-1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 4, 30))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 2, 28)); |
| sysTime.add!"months"(12, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(2000, 2, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(2000, 2, 29)); |
| sysTime.add!"months"(12, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(2001, 2, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 7, 31)); |
| sysTime.add!"months"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 8, 31))); |
| sysTime.add!"months"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 9, 30))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1998, 8, 31)); |
| sysTime.add!"months"(13, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 9, 30))); |
| sysTime.add!"months"(-13, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1998, 8, 30))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1997, 12, 31)); |
| sysTime.add!"months"(13, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 1, 31))); |
| sysTime.add!"months"(-13, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1997, 12, 31))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1997, 12, 31)); |
| sysTime.add!"months"(14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 2, 28))); |
| sysTime.add!"months"(-14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1997, 12, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1998, 12, 31)); |
| sysTime.add!"months"(14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(2000, 2, 29))); |
| sysTime.add!"months"(-14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1998, 12, 29))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 12, 31)); |
| sysTime.add!"months"(14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(2001, 2, 28))); |
| sysTime.add!"months"(-14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 12, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), usecs(5007)); |
| sysTime.add!"months"(3, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1999, 10, 6, 12, 2, 7), usecs(5007))); |
| sysTime.add!"months"(-4, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1999, 6, 6, 12, 2, 7), usecs(5007))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), hnsecs(422202)); |
| sysTime.add!"months"(14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(2000, 2, 29, 7, 7, 7), hnsecs(422202))); |
| sysTime.add!"months"(-14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1998, 12, 29, 7, 7, 7), hnsecs(422202))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), hnsecs(422202)); |
| sysTime.add!"months"(14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(2001, 2, 28, 7, 7, 7), hnsecs(422202))); |
| sysTime.add!"months"(-14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1999, 12, 28, 7, 7, 7), hnsecs(422202))); |
| } |
| |
| // Test B.C. |
| { |
| auto sysTime = SysTime(Date(-1999, 7, 6)); |
| sysTime.add!"months"(3, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1999, 10, 6))); |
| sysTime.add!"months"(-4, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1999, 6, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 7, 6)); |
| sysTime.add!"months"(6, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1998, 1, 6))); |
| sysTime.add!"months"(-6, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1999, 7, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 7, 6)); |
| sysTime.add!"months"(-27, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-2001, 4, 6))); |
| sysTime.add!"months"(28, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1999, 8, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 5, 31)); |
| sysTime.add!"months"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1999, 6, 30))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 5, 31)); |
| sysTime.add!"months"(-1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1999, 4, 30))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 2, 28)); |
| sysTime.add!"months"(-12, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-2000, 2, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-2000, 2, 29)); |
| sysTime.add!"months"(-12, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-2001, 2, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 7, 31)); |
| sysTime.add!"months"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1999, 8, 31))); |
| sysTime.add!"months"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1999, 9, 30))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1998, 8, 31)); |
| sysTime.add!"months"(13, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1997, 9, 30))); |
| sysTime.add!"months"(-13, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1998, 8, 30))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1997, 12, 31)); |
| sysTime.add!"months"(13, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1995, 1, 31))); |
| sysTime.add!"months"(-13, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1997, 12, 31))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1997, 12, 31)); |
| sysTime.add!"months"(14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1995, 2, 28))); |
| sysTime.add!"months"(-14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1997, 12, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-2002, 12, 31)); |
| sysTime.add!"months"(14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-2000, 2, 29))); |
| sysTime.add!"months"(-14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-2002, 12, 29))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-2001, 12, 31)); |
| sysTime.add!"months"(14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1999, 2, 28))); |
| sysTime.add!"months"(-14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-2001, 12, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), usecs(5007)); |
| sysTime.add!"months"(3, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(-1999, 10, 6, 12, 2, 7), usecs(5007))); |
| sysTime.add!"months"(-4, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(-1999, 6, 6, 12, 2, 7), usecs(5007))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), hnsecs(422202)); |
| sysTime.add!"months"(14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(-2000, 2, 29, 7, 7, 7), hnsecs(422202))); |
| sysTime.add!"months"(-14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(-2002, 12, 29, 7, 7, 7), hnsecs(422202))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), hnsecs(422202)); |
| sysTime.add!"months"(14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(-1999, 2, 28, 7, 7, 7), hnsecs(422202))); |
| sysTime.add!"months"(-14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(-2001, 12, 28, 7, 7, 7), hnsecs(422202))); |
| } |
| |
| // Test Both |
| { |
| auto sysTime = SysTime(Date(1, 1, 1)); |
| sysTime.add!"months"(-1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(0, 12, 1))); |
| sysTime.add!"months"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1, 1, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(4, 1, 1)); |
| sysTime.add!"months"(-48, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(0, 1, 1))); |
| sysTime.add!"months"(48, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(4, 1, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(4, 3, 31)); |
| sysTime.add!"months"(-49, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(0, 2, 29))); |
| sysTime.add!"months"(49, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(4, 3, 29))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(4, 3, 31)); |
| sysTime.add!"months"(-85, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-3, 2, 28))); |
| sysTime.add!"months"(85, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(4, 3, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0)); |
| sysTime.add!"months"(-1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0))); |
| sysTime.add!"months"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)); |
| sysTime.add!"months"(-1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999))); |
| sysTime.add!"months"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0)); |
| sysTime.add!"months"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| sysTime.add!"months"(-1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)); |
| sysTime.add!"months"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999))); |
| sysTime.add!"months"(-1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17)); |
| sysTime.add!"months"(-1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 7, 9), hnsecs(17))); |
| sysTime.add!"months"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), msecs(9)); |
| sysTime.add!"months"(-85, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(-3, 2, 28, 12, 11, 10), msecs(9))); |
| sysTime.add!"months"(85, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(4, 3, 28, 12, 11, 10), msecs(9))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9)); |
| sysTime.add!"months"(85, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(4, 4, 30, 12, 11, 10), msecs(9))); |
| sysTime.add!"months"(-85, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(-3, 3, 30, 12, 11, 10), msecs(9))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9)); |
| sysTime.add!"months"(85, AllowDayOverflow.no).add!"months"(-83, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(-3, 5, 30, 12, 11, 10), msecs(9))); |
| } |
| } |
| |
| |
| /++ |
| Adds the given number of years or months to this $(LREF SysTime). A |
| negative number will subtract. |
| |
| The difference between rolling and adding is that rolling does not |
| affect larger units. Rolling a $(LREF SysTime) 12 months |
| gets the exact same $(LREF SysTime). However, the days can still be |
| affected due to the differing number of days in each month. |
| |
| Because there are no units larger than years, there is no difference |
| between adding and rolling years. |
| |
| Params: |
| units = The type of units to add ("years" or "months"). |
| value = The number of months or years to add to this |
| $(LREF SysTime). |
| allowOverflow = Whether the days should be allowed to overflow, |
| causing the month to increment. |
| +/ |
| ref SysTime roll(string units)(long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) @safe nothrow |
| if (units == "years") |
| { |
| return add!"years"(value, allowOverflow); |
| } |
| |
| /// |
| @safe unittest |
| { |
| import std.datetime.date : AllowDayOverflow, DateTime; |
| |
| auto st1 = SysTime(DateTime(2010, 1, 1, 12, 33, 33)); |
| st1.roll!"months"(1); |
| assert(st1 == SysTime(DateTime(2010, 2, 1, 12, 33, 33))); |
| |
| auto st2 = SysTime(DateTime(2010, 1, 1, 12, 33, 33)); |
| st2.roll!"months"(-1); |
| assert(st2 == SysTime(DateTime(2010, 12, 1, 12, 33, 33))); |
| |
| auto st3 = SysTime(DateTime(1999, 1, 29, 12, 33, 33)); |
| st3.roll!"months"(1); |
| assert(st3 == SysTime(DateTime(1999, 3, 1, 12, 33, 33))); |
| |
| auto st4 = SysTime(DateTime(1999, 1, 29, 12, 33, 33)); |
| st4.roll!"months"(1, AllowDayOverflow.no); |
| assert(st4 == SysTime(DateTime(1999, 2, 28, 12, 33, 33))); |
| |
| auto st5 = SysTime(DateTime(2000, 2, 29, 12, 30, 33)); |
| st5.roll!"years"(1); |
| assert(st5 == SysTime(DateTime(2001, 3, 1, 12, 30, 33))); |
| |
| auto st6 = SysTime(DateTime(2000, 2, 29, 12, 30, 33)); |
| st6.roll!"years"(1, AllowDayOverflow.no); |
| assert(st6 == SysTime(DateTime(2001, 2, 28, 12, 30, 33))); |
| } |
| |
| @safe unittest |
| { |
| auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| st.roll!"years"(4); |
| static assert(!__traits(compiles, cst.roll!"years"(4))); |
| //static assert(!__traits(compiles, ist.roll!"years"(4))); |
| } |
| |
| |
| // Shares documentation with "years" overload. |
| ref SysTime roll(string units)(long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) @safe nothrow |
| if (units == "months") |
| { |
| auto hnsecs = adjTime; |
| auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1; |
| |
| if (hnsecs < 0) |
| { |
| hnsecs += convert!("hours", "hnsecs")(24); |
| --days; |
| } |
| |
| auto date = Date(cast(int) days); |
| date.roll!"months"(value, allowOverflow); |
| days = date.dayOfGregorianCal - 1; |
| |
| if (days < 0) |
| { |
| hnsecs -= convert!("hours", "hnsecs")(24); |
| ++days; |
| } |
| |
| immutable newDaysHNSecs = convert!("days", "hnsecs")(days); |
| adjTime = newDaysHNSecs + hnsecs; |
| return this; |
| } |
| |
| // Test roll!"months"() with AllowDayOverflow.yes |
| @safe unittest |
| { |
| // Test A.D. |
| { |
| auto sysTime = SysTime(Date(1999, 7, 6)); |
| sysTime.roll!"months"(3); |
| assert(sysTime == SysTime(Date(1999, 10, 6))); |
| sysTime.roll!"months"(-4); |
| assert(sysTime == SysTime(Date(1999, 6, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 7, 6)); |
| sysTime.roll!"months"(6); |
| assert(sysTime == SysTime(Date(1999, 1, 6))); |
| sysTime.roll!"months"(-6); |
| assert(sysTime == SysTime(Date(1999, 7, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 7, 6)); |
| sysTime.roll!"months"(27); |
| assert(sysTime == SysTime(Date(1999, 10, 6))); |
| sysTime.roll!"months"(-28); |
| assert(sysTime == SysTime(Date(1999, 6, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 5, 31)); |
| sysTime.roll!"months"(1); |
| assert(sysTime == SysTime(Date(1999, 7, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 5, 31)); |
| sysTime.roll!"months"(-1); |
| assert(sysTime == SysTime(Date(1999, 5, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 2, 28)); |
| sysTime.roll!"months"(12); |
| assert(sysTime == SysTime(Date(1999, 2, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(2000, 2, 29)); |
| sysTime.roll!"months"(12); |
| assert(sysTime == SysTime(Date(2000, 2, 29))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 7, 31)); |
| sysTime.roll!"months"(1); |
| assert(sysTime == SysTime(Date(1999, 8, 31))); |
| sysTime.roll!"months"(1); |
| assert(sysTime == SysTime(Date(1999, 10, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1998, 8, 31)); |
| sysTime.roll!"months"(13); |
| assert(sysTime == SysTime(Date(1998, 10, 1))); |
| sysTime.roll!"months"(-13); |
| assert(sysTime == SysTime(Date(1998, 9, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1997, 12, 31)); |
| sysTime.roll!"months"(13); |
| assert(sysTime == SysTime(Date(1997, 1, 31))); |
| sysTime.roll!"months"(-13); |
| assert(sysTime == SysTime(Date(1997, 12, 31))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1997, 12, 31)); |
| sysTime.roll!"months"(14); |
| assert(sysTime == SysTime(Date(1997, 3, 3))); |
| sysTime.roll!"months"(-14); |
| assert(sysTime == SysTime(Date(1997, 1, 3))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1998, 12, 31)); |
| sysTime.roll!"months"(14); |
| assert(sysTime == SysTime(Date(1998, 3, 3))); |
| sysTime.roll!"months"(-14); |
| assert(sysTime == SysTime(Date(1998, 1, 3))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 12, 31)); |
| sysTime.roll!"months"(14); |
| assert(sysTime == SysTime(Date(1999, 3, 3))); |
| sysTime.roll!"months"(-14); |
| assert(sysTime == SysTime(Date(1999, 1, 3))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), usecs(5007)); |
| sysTime.roll!"months"(3); |
| assert(sysTime == SysTime(DateTime(1999, 10, 6, 12, 2, 7), usecs(5007))); |
| sysTime.roll!"months"(-4); |
| assert(sysTime == SysTime(DateTime(1999, 6, 6, 12, 2, 7), usecs(5007))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), hnsecs(422202)); |
| sysTime.roll!"months"(14); |
| assert(sysTime == SysTime(DateTime(1998, 3, 3, 7, 7, 7), hnsecs(422202))); |
| sysTime.roll!"months"(-14); |
| assert(sysTime == SysTime(DateTime(1998, 1, 3, 7, 7, 7), hnsecs(422202))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), hnsecs(422202)); |
| sysTime.roll!"months"(14); |
| assert(sysTime == SysTime(DateTime(1999, 3, 3, 7, 7, 7), hnsecs(422202))); |
| sysTime.roll!"months"(-14); |
| assert(sysTime == SysTime(DateTime(1999, 1, 3, 7, 7, 7), hnsecs(422202))); |
| } |
| |
| // Test B.C. |
| { |
| auto sysTime = SysTime(Date(-1999, 7, 6)); |
| sysTime.roll!"months"(3); |
| assert(sysTime == SysTime(Date(-1999, 10, 6))); |
| sysTime.roll!"months"(-4); |
| assert(sysTime == SysTime(Date(-1999, 6, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 7, 6)); |
| sysTime.roll!"months"(6); |
| assert(sysTime == SysTime(Date(-1999, 1, 6))); |
| sysTime.roll!"months"(-6); |
| assert(sysTime == SysTime(Date(-1999, 7, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 7, 6)); |
| sysTime.roll!"months"(-27); |
| assert(sysTime == SysTime(Date(-1999, 4, 6))); |
| sysTime.roll!"months"(28); |
| assert(sysTime == SysTime(Date(-1999, 8, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 5, 31)); |
| sysTime.roll!"months"(1); |
| assert(sysTime == SysTime(Date(-1999, 7, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 5, 31)); |
| sysTime.roll!"months"(-1); |
| assert(sysTime == SysTime(Date(-1999, 5, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 2, 28)); |
| sysTime.roll!"months"(-12); |
| assert(sysTime == SysTime(Date(-1999, 2, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-2000, 2, 29)); |
| sysTime.roll!"months"(-12); |
| assert(sysTime == SysTime(Date(-2000, 2, 29))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 7, 31)); |
| sysTime.roll!"months"(1); |
| assert(sysTime == SysTime(Date(-1999, 8, 31))); |
| sysTime.roll!"months"(1); |
| assert(sysTime == SysTime(Date(-1999, 10, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1998, 8, 31)); |
| sysTime.roll!"months"(13); |
| assert(sysTime == SysTime(Date(-1998, 10, 1))); |
| sysTime.roll!"months"(-13); |
| assert(sysTime == SysTime(Date(-1998, 9, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1997, 12, 31)); |
| sysTime.roll!"months"(13); |
| assert(sysTime == SysTime(Date(-1997, 1, 31))); |
| sysTime.roll!"months"(-13); |
| assert(sysTime == SysTime(Date(-1997, 12, 31))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1997, 12, 31)); |
| sysTime.roll!"months"(14); |
| assert(sysTime == SysTime(Date(-1997, 3, 3))); |
| sysTime.roll!"months"(-14); |
| assert(sysTime == SysTime(Date(-1997, 1, 3))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-2002, 12, 31)); |
| sysTime.roll!"months"(14); |
| assert(sysTime == SysTime(Date(-2002, 3, 3))); |
| sysTime.roll!"months"(-14); |
| assert(sysTime == SysTime(Date(-2002, 1, 3))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-2001, 12, 31)); |
| sysTime.roll!"months"(14); |
| assert(sysTime == SysTime(Date(-2001, 3, 3))); |
| sysTime.roll!"months"(-14); |
| assert(sysTime == SysTime(Date(-2001, 1, 3))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0)); |
| sysTime.roll!"months"(-1); |
| assert(sysTime == SysTime(DateTime(1, 12, 1, 0, 0, 0))); |
| sysTime.roll!"months"(1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)); |
| sysTime.roll!"months"(-1); |
| assert(sysTime == SysTime(DateTime(1, 12, 1, 23, 59, 59), hnsecs(9_999_999))); |
| sysTime.roll!"months"(1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0)); |
| sysTime.roll!"months"(1); |
| assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0))); |
| sysTime.roll!"months"(-1); |
| assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)); |
| sysTime.roll!"months"(1); |
| assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999))); |
| sysTime.roll!"months"(-1); |
| assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), hnsecs(5007)); |
| sysTime.roll!"months"(3); |
| assert(sysTime == SysTime(DateTime(-1999, 10, 6, 12, 2, 7), hnsecs(5007))); |
| sysTime.roll!"months"(-4); |
| assert(sysTime == SysTime(DateTime(-1999, 6, 6, 12, 2, 7), hnsecs(5007))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), hnsecs(422202)); |
| sysTime.roll!"months"(14); |
| assert(sysTime == SysTime(DateTime(-2002, 3, 3, 7, 7, 7), hnsecs(422202))); |
| sysTime.roll!"months"(-14); |
| assert(sysTime == SysTime(DateTime(-2002, 1, 3, 7, 7, 7), hnsecs(422202))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), hnsecs(422202)); |
| sysTime.roll!"months"(14); |
| assert(sysTime == SysTime(DateTime(-2001, 3, 3, 7, 7, 7), hnsecs(422202))); |
| sysTime.roll!"months"(-14); |
| assert(sysTime == SysTime(DateTime(-2001, 1, 3, 7, 7, 7), hnsecs(422202))); |
| } |
| |
| // Test Both |
| { |
| auto sysTime = SysTime(Date(1, 1, 1)); |
| sysTime.roll!"months"(-1); |
| assert(sysTime == SysTime(Date(1, 12, 1))); |
| sysTime.roll!"months"(1); |
| assert(sysTime == SysTime(Date(1, 1, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(4, 1, 1)); |
| sysTime.roll!"months"(-48); |
| assert(sysTime == SysTime(Date(4, 1, 1))); |
| sysTime.roll!"months"(48); |
| assert(sysTime == SysTime(Date(4, 1, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(4, 3, 31)); |
| sysTime.roll!"months"(-49); |
| assert(sysTime == SysTime(Date(4, 3, 2))); |
| sysTime.roll!"months"(49); |
| assert(sysTime == SysTime(Date(4, 4, 2))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(4, 3, 31)); |
| sysTime.roll!"months"(-85); |
| assert(sysTime == SysTime(Date(4, 3, 2))); |
| sysTime.roll!"months"(85); |
| assert(sysTime == SysTime(Date(4, 4, 2))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1, 1, 1)); |
| sysTime.roll!"months"(-1); |
| assert(sysTime == SysTime(Date(-1, 12, 1))); |
| sysTime.roll!"months"(1); |
| assert(sysTime == SysTime(Date(-1, 1, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-4, 1, 1)); |
| sysTime.roll!"months"(-48); |
| assert(sysTime == SysTime(Date(-4, 1, 1))); |
| sysTime.roll!"months"(48); |
| assert(sysTime == SysTime(Date(-4, 1, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-4, 3, 31)); |
| sysTime.roll!"months"(-49); |
| assert(sysTime == SysTime(Date(-4, 3, 2))); |
| sysTime.roll!"months"(49); |
| assert(sysTime == SysTime(Date(-4, 4, 2))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-4, 3, 31)); |
| sysTime.roll!"months"(-85); |
| assert(sysTime == SysTime(Date(-4, 3, 2))); |
| sysTime.roll!"months"(85); |
| assert(sysTime == SysTime(Date(-4, 4, 2))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17)); |
| sysTime.roll!"months"(-1); |
| assert(sysTime == SysTime(DateTime(1, 12, 1, 0, 7, 9), hnsecs(17))); |
| sysTime.roll!"months"(1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), msecs(9)); |
| sysTime.roll!"months"(-85); |
| assert(sysTime == SysTime(DateTime(4, 3, 2, 12, 11, 10), msecs(9))); |
| sysTime.roll!"months"(85); |
| assert(sysTime == SysTime(DateTime(4, 4, 2, 12, 11, 10), msecs(9))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9)); |
| sysTime.roll!"months"(85); |
| assert(sysTime == SysTime(DateTime(-3, 5, 1, 12, 11, 10), msecs(9))); |
| sysTime.roll!"months"(-85); |
| assert(sysTime == SysTime(DateTime(-3, 4, 1, 12, 11, 10), msecs(9))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9)); |
| sysTime.roll!"months"(85).roll!"months"(-83); |
| assert(sysTime == SysTime(DateTime(-3, 6, 1, 12, 11, 10), msecs(9))); |
| } |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| static assert(!__traits(compiles, cst.roll!"months"(4))); |
| //static assert(!__traits(compiles, ist.roll!"months"(4))); |
| } |
| |
| // Test roll!"months"() with AllowDayOverflow.no |
| @safe unittest |
| { |
| // Test A.D. |
| { |
| auto sysTime = SysTime(Date(1999, 7, 6)); |
| sysTime.roll!"months"(3, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 10, 6))); |
| sysTime.roll!"months"(-4, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 6, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 7, 6)); |
| sysTime.roll!"months"(6, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 1, 6))); |
| sysTime.roll!"months"(-6, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 7, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 7, 6)); |
| sysTime.roll!"months"(27, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 10, 6))); |
| sysTime.roll!"months"(-28, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 6, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 5, 31)); |
| sysTime.roll!"months"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 6, 30))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 5, 31)); |
| sysTime.roll!"months"(-1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 4, 30))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 2, 28)); |
| sysTime.roll!"months"(12, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 2, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(2000, 2, 29)); |
| sysTime.roll!"months"(12, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(2000, 2, 29))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 7, 31)); |
| sysTime.roll!"months"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 8, 31))); |
| sysTime.roll!"months"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 9, 30))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1998, 8, 31)); |
| sysTime.roll!"months"(13, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1998, 9, 30))); |
| sysTime.roll!"months"(-13, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1998, 8, 30))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1997, 12, 31)); |
| sysTime.roll!"months"(13, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1997, 1, 31))); |
| sysTime.roll!"months"(-13, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1997, 12, 31))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1997, 12, 31)); |
| sysTime.roll!"months"(14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1997, 2, 28))); |
| sysTime.roll!"months"(-14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1997, 12, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1998, 12, 31)); |
| sysTime.roll!"months"(14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1998, 2, 28))); |
| sysTime.roll!"months"(-14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1998, 12, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 12, 31)); |
| sysTime.roll!"months"(14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 2, 28))); |
| sysTime.roll!"months"(-14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1999, 12, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), usecs(5007)); |
| sysTime.roll!"months"(3, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1999, 10, 6, 12, 2, 7), usecs(5007))); |
| sysTime.roll!"months"(-4, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1999, 6, 6, 12, 2, 7), usecs(5007))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), hnsecs(422202)); |
| sysTime.roll!"months"(14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1998, 2, 28, 7, 7, 7), hnsecs(422202))); |
| sysTime.roll!"months"(-14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1998, 12, 28, 7, 7, 7), hnsecs(422202))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), hnsecs(422202)); |
| sysTime.roll!"months"(14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1999, 2, 28, 7, 7, 7), hnsecs(422202))); |
| sysTime.roll!"months"(-14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1999, 12, 28, 7, 7, 7), hnsecs(422202))); |
| } |
| |
| // Test B.C. |
| { |
| auto sysTime = SysTime(Date(-1999, 7, 6)); |
| sysTime.roll!"months"(3, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1999, 10, 6))); |
| sysTime.roll!"months"(-4, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1999, 6, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 7, 6)); |
| sysTime.roll!"months"(6, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1999, 1, 6))); |
| sysTime.roll!"months"(-6, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1999, 7, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 7, 6)); |
| sysTime.roll!"months"(-27, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1999, 4, 6))); |
| sysTime.roll!"months"(28, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1999, 8, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 5, 31)); |
| sysTime.roll!"months"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1999, 6, 30))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 5, 31)); |
| sysTime.roll!"months"(-1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1999, 4, 30))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 2, 28)); |
| sysTime.roll!"months"(-12, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1999, 2, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-2000, 2, 29)); |
| sysTime.roll!"months"(-12, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-2000, 2, 29))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 7, 31)); |
| sysTime.roll!"months"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1999, 8, 31))); |
| sysTime.roll!"months"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1999, 9, 30))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1998, 8, 31)); |
| sysTime.roll!"months"(13, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1998, 9, 30))); |
| sysTime.roll!"months"(-13, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1998, 8, 30))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1997, 12, 31)); |
| sysTime.roll!"months"(13, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1997, 1, 31))); |
| sysTime.roll!"months"(-13, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1997, 12, 31))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1997, 12, 31)); |
| sysTime.roll!"months"(14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1997, 2, 28))); |
| sysTime.roll!"months"(-14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1997, 12, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-2002, 12, 31)); |
| sysTime.roll!"months"(14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-2002, 2, 28))); |
| sysTime.roll!"months"(-14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-2002, 12, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-2001, 12, 31)); |
| sysTime.roll!"months"(14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-2001, 2, 28))); |
| sysTime.roll!"months"(-14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-2001, 12, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), usecs(5007)); |
| sysTime.roll!"months"(3, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(-1999, 10, 6, 12, 2, 7), usecs(5007))); |
| sysTime.roll!"months"(-4, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(-1999, 6, 6, 12, 2, 7), usecs(5007))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), hnsecs(422202)); |
| sysTime.roll!"months"(14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(-2002, 2, 28, 7, 7, 7), hnsecs(422202))); |
| sysTime.roll!"months"(-14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(-2002, 12, 28, 7, 7, 7), hnsecs(422202))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), hnsecs(422202)); |
| sysTime.roll!"months"(14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(-2001, 2, 28, 7, 7, 7), hnsecs(422202))); |
| sysTime.roll!"months"(-14, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(-2001, 12, 28, 7, 7, 7), hnsecs(422202))); |
| } |
| |
| // Test Both |
| { |
| auto sysTime = SysTime(Date(1, 1, 1)); |
| sysTime.roll!"months"(-1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1, 12, 1))); |
| sysTime.roll!"months"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(1, 1, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(4, 1, 1)); |
| sysTime.roll!"months"(-48, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(4, 1, 1))); |
| sysTime.roll!"months"(48, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(4, 1, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(4, 3, 31)); |
| sysTime.roll!"months"(-49, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(4, 2, 29))); |
| sysTime.roll!"months"(49, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(4, 3, 29))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(4, 3, 31)); |
| sysTime.roll!"months"(-85, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(4, 2, 29))); |
| sysTime.roll!"months"(85, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(4, 3, 29))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1, 1, 1)); |
| sysTime.roll!"months"(-1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1, 12, 1))); |
| sysTime.roll!"months"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-1, 1, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-4, 1, 1)); |
| sysTime.roll!"months"(-48, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-4, 1, 1))); |
| sysTime.roll!"months"(48, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-4, 1, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-4, 3, 31)); |
| sysTime.roll!"months"(-49, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-4, 2, 29))); |
| sysTime.roll!"months"(49, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-4, 3, 29))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-4, 3, 31)); |
| sysTime.roll!"months"(-85, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-4, 2, 29))); |
| sysTime.roll!"months"(85, AllowDayOverflow.no); |
| assert(sysTime == SysTime(Date(-4, 3, 29))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0)); |
| sysTime.roll!"months"(-1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1, 12, 1, 0, 0, 0))); |
| sysTime.roll!"months"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)); |
| sysTime.roll!"months"(-1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1, 12, 1, 23, 59, 59), hnsecs(9_999_999))); |
| sysTime.roll!"months"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0)); |
| sysTime.roll!"months"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(0, 1, 1, 0, 0, 0))); |
| sysTime.roll!"months"(-1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999)); |
| sysTime.roll!"months"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999))); |
| sysTime.roll!"months"(-1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17)); |
| sysTime.roll!"months"(-1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1, 12, 1, 0, 7, 9), hnsecs(17))); |
| sysTime.roll!"months"(1, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 7, 9), hnsecs(17))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), msecs(9)); |
| sysTime.roll!"months"(-85, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(4, 2, 29, 12, 11, 10), msecs(9))); |
| sysTime.roll!"months"(85, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(4, 3, 29, 12, 11, 10), msecs(9))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9)); |
| sysTime.roll!"months"(85, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(-3, 4, 30, 12, 11, 10), msecs(9))); |
| sysTime.roll!"months"(-85, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(-3, 3, 30, 12, 11, 10), msecs(9))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), msecs(9)); |
| sysTime.roll!"months"(85, AllowDayOverflow.no).roll!"months"(-83, AllowDayOverflow.no); |
| assert(sysTime == SysTime(DateTime(-3, 5, 30, 12, 11, 10), msecs(9))); |
| } |
| } |
| |
| |
| /++ |
| Adds the given number of units to this $(LREF SysTime). A negative number |
| will subtract. |
| |
| The difference between rolling and adding is that rolling does not |
| affect larger units. For instance, rolling a $(LREF SysTime) one |
| year's worth of days gets the exact same $(LREF SysTime). |
| |
| Accepted units are $(D "days"), $(D "minutes"), $(D "hours"), |
| $(D "minutes"), $(D "seconds"), $(D "msecs"), $(D "usecs"), and |
| $(D "hnsecs"). |
| |
| Note that when rolling msecs, usecs or hnsecs, they all add up to a |
| second. So, for example, rolling 1000 msecs is exactly the same as |
| rolling 100,000 usecs. |
| |
| Params: |
| units = The units to add. |
| value = The number of $(D_PARAM units) to add to this |
| $(LREF SysTime). |
| +/ |
| ref SysTime roll(string units)(long value) @safe nothrow |
| if (units == "days") |
| { |
| auto hnsecs = adjTime; |
| auto gdays = splitUnitsFromHNSecs!"days"(hnsecs) + 1; |
| |
| if (hnsecs < 0) |
| { |
| hnsecs += convert!("hours", "hnsecs")(24); |
| --gdays; |
| } |
| |
| auto date = Date(cast(int) gdays); |
| date.roll!"days"(value); |
| gdays = date.dayOfGregorianCal - 1; |
| |
| if (gdays < 0) |
| { |
| hnsecs -= convert!("hours", "hnsecs")(24); |
| ++gdays; |
| } |
| |
| immutable newDaysHNSecs = convert!("days", "hnsecs")(gdays); |
| adjTime = newDaysHNSecs + hnsecs; |
| return this; |
| } |
| |
| /// |
| @safe unittest |
| { |
| import core.time : msecs, hnsecs; |
| import std.datetime.date : DateTime; |
| |
| auto st1 = SysTime(DateTime(2010, 1, 1, 11, 23, 12)); |
| st1.roll!"days"(1); |
| assert(st1 == SysTime(DateTime(2010, 1, 2, 11, 23, 12))); |
| st1.roll!"days"(365); |
| assert(st1 == SysTime(DateTime(2010, 1, 26, 11, 23, 12))); |
| st1.roll!"days"(-32); |
| assert(st1 == SysTime(DateTime(2010, 1, 25, 11, 23, 12))); |
| |
| auto st2 = SysTime(DateTime(2010, 7, 4, 12, 0, 0)); |
| st2.roll!"hours"(1); |
| assert(st2 == SysTime(DateTime(2010, 7, 4, 13, 0, 0))); |
| |
| auto st3 = SysTime(DateTime(2010, 2, 12, 12, 0, 0)); |
| st3.roll!"hours"(-1); |
| assert(st3 == SysTime(DateTime(2010, 2, 12, 11, 0, 0))); |
| |
| auto st4 = SysTime(DateTime(2009, 12, 31, 0, 0, 0)); |
| st4.roll!"minutes"(1); |
| assert(st4 == SysTime(DateTime(2009, 12, 31, 0, 1, 0))); |
| |
| auto st5 = SysTime(DateTime(2010, 1, 1, 0, 0, 0)); |
| st5.roll!"minutes"(-1); |
| assert(st5 == SysTime(DateTime(2010, 1, 1, 0, 59, 0))); |
| |
| auto st6 = SysTime(DateTime(2009, 12, 31, 0, 0, 0)); |
| st6.roll!"seconds"(1); |
| assert(st6 == SysTime(DateTime(2009, 12, 31, 0, 0, 1))); |
| |
| auto st7 = SysTime(DateTime(2010, 1, 1, 0, 0, 0)); |
| st7.roll!"seconds"(-1); |
| assert(st7 == SysTime(DateTime(2010, 1, 1, 0, 0, 59))); |
| |
| auto dt = DateTime(2010, 1, 1, 0, 0, 0); |
| auto st8 = SysTime(dt); |
| st8.roll!"msecs"(1); |
| assert(st8 == SysTime(dt, msecs(1))); |
| |
| auto st9 = SysTime(dt); |
| st9.roll!"msecs"(-1); |
| assert(st9 == SysTime(dt, msecs(999))); |
| |
| auto st10 = SysTime(dt); |
| st10.roll!"hnsecs"(1); |
| assert(st10 == SysTime(dt, hnsecs(1))); |
| |
| auto st11 = SysTime(dt); |
| st11.roll!"hnsecs"(-1); |
| assert(st11 == SysTime(dt, hnsecs(9_999_999))); |
| } |
| |
| @safe unittest |
| { |
| // Test A.D. |
| { |
| auto sysTime = SysTime(Date(1999, 2, 28)); |
| sysTime.roll!"days"(1); |
| assert(sysTime == SysTime(Date(1999, 2, 1))); |
| sysTime.roll!"days"(-1); |
| assert(sysTime == SysTime(Date(1999, 2, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(2000, 2, 28)); |
| sysTime.roll!"days"(1); |
| assert(sysTime == SysTime(Date(2000, 2, 29))); |
| sysTime.roll!"days"(1); |
| assert(sysTime == SysTime(Date(2000, 2, 1))); |
| sysTime.roll!"days"(-1); |
| assert(sysTime == SysTime(Date(2000, 2, 29))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 6, 30)); |
| sysTime.roll!"days"(1); |
| assert(sysTime == SysTime(Date(1999, 6, 1))); |
| sysTime.roll!"days"(-1); |
| assert(sysTime == SysTime(Date(1999, 6, 30))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 7, 31)); |
| sysTime.roll!"days"(1); |
| assert(sysTime == SysTime(Date(1999, 7, 1))); |
| sysTime.roll!"days"(-1); |
| assert(sysTime == SysTime(Date(1999, 7, 31))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 1, 1)); |
| sysTime.roll!"days"(-1); |
| assert(sysTime == SysTime(Date(1999, 1, 31))); |
| sysTime.roll!"days"(1); |
| assert(sysTime == SysTime(Date(1999, 1, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 7, 6)); |
| sysTime.roll!"days"(9); |
| assert(sysTime == SysTime(Date(1999, 7, 15))); |
| sysTime.roll!"days"(-11); |
| assert(sysTime == SysTime(Date(1999, 7, 4))); |
| sysTime.roll!"days"(30); |
| assert(sysTime == SysTime(Date(1999, 7, 3))); |
| sysTime.roll!"days"(-3); |
| assert(sysTime == SysTime(Date(1999, 7, 31))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 7, 6)); |
| sysTime.roll!"days"(365); |
| assert(sysTime == SysTime(Date(1999, 7, 30))); |
| sysTime.roll!"days"(-365); |
| assert(sysTime == SysTime(Date(1999, 7, 6))); |
| sysTime.roll!"days"(366); |
| assert(sysTime == SysTime(Date(1999, 7, 31))); |
| sysTime.roll!"days"(730); |
| assert(sysTime == SysTime(Date(1999, 7, 17))); |
| sysTime.roll!"days"(-1096); |
| assert(sysTime == SysTime(Date(1999, 7, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(1999, 2, 6)); |
| sysTime.roll!"days"(365); |
| assert(sysTime == SysTime(Date(1999, 2, 7))); |
| sysTime.roll!"days"(-365); |
| assert(sysTime == SysTime(Date(1999, 2, 6))); |
| sysTime.roll!"days"(366); |
| assert(sysTime == SysTime(Date(1999, 2, 8))); |
| sysTime.roll!"days"(730); |
| assert(sysTime == SysTime(Date(1999, 2, 10))); |
| sysTime.roll!"days"(-1096); |
| assert(sysTime == SysTime(Date(1999, 2, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1999, 2, 28, 7, 9, 2), usecs(234578)); |
| sysTime.roll!"days"(1); |
| assert(sysTime == SysTime(DateTime(1999, 2, 1, 7, 9, 2), usecs(234578))); |
| sysTime.roll!"days"(-1); |
| assert(sysTime == SysTime(DateTime(1999, 2, 28, 7, 9, 2), usecs(234578))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1999, 7, 6, 7, 9, 2), usecs(234578)); |
| sysTime.roll!"days"(9); |
| assert(sysTime == SysTime(DateTime(1999, 7, 15, 7, 9, 2), usecs(234578))); |
| sysTime.roll!"days"(-11); |
| assert(sysTime == SysTime(DateTime(1999, 7, 4, 7, 9, 2), usecs(234578))); |
| sysTime.roll!"days"(30); |
| assert(sysTime == SysTime(DateTime(1999, 7, 3, 7, 9, 2), usecs(234578))); |
| sysTime.roll!"days"(-3); |
| assert(sysTime == SysTime(DateTime(1999, 7, 31, 7, 9, 2), usecs(234578))); |
| } |
| |
| // Test B.C. |
| { |
| auto sysTime = SysTime(Date(-1999, 2, 28)); |
| sysTime.roll!"days"(1); |
| assert(sysTime == SysTime(Date(-1999, 2, 1))); |
| sysTime.roll!"days"(-1); |
| assert(sysTime == SysTime(Date(-1999, 2, 28))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-2000, 2, 28)); |
| sysTime.roll!"days"(1); |
| assert(sysTime == SysTime(Date(-2000, 2, 29))); |
| sysTime.roll!"days"(1); |
| assert(sysTime == SysTime(Date(-2000, 2, 1))); |
| sysTime.roll!"days"(-1); |
| assert(sysTime == SysTime(Date(-2000, 2, 29))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 6, 30)); |
| sysTime.roll!"days"(1); |
| assert(sysTime == SysTime(Date(-1999, 6, 1))); |
| sysTime.roll!"days"(-1); |
| assert(sysTime == SysTime(Date(-1999, 6, 30))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 7, 31)); |
| sysTime.roll!"days"(1); |
| assert(sysTime == SysTime(Date(-1999, 7, 1))); |
| sysTime.roll!"days"(-1); |
| assert(sysTime == SysTime(Date(-1999, 7, 31))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 1, 1)); |
| sysTime.roll!"days"(-1); |
| assert(sysTime == SysTime(Date(-1999, 1, 31))); |
| sysTime.roll!"days"(1); |
| assert(sysTime == SysTime(Date(-1999, 1, 1))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 7, 6)); |
| sysTime.roll!"days"(9); |
| assert(sysTime == SysTime(Date(-1999, 7, 15))); |
| sysTime.roll!"days"(-11); |
| assert(sysTime == SysTime(Date(-1999, 7, 4))); |
| sysTime.roll!"days"(30); |
| assert(sysTime == SysTime(Date(-1999, 7, 3))); |
| sysTime.roll!"days"(-3); |
| assert(sysTime == SysTime(Date(-1999, 7, 31))); |
| } |
| |
| { |
| auto sysTime = SysTime(Date(-1999, 7, 6)); |
| sysTime.roll!"days"(365); |
| assert(sysTime == SysTime(Date(-1999, 7, 30))); |
| sysTime.roll!"days"(-365); |
| assert(sysTime == SysTime(Date(-1999, 7, 6))); |
| sysTime.roll!"days"(366); |
| assert(sysTime == SysTime(Date(-1999, 7, 31))); |
| sysTime.roll!"days"(730); |
| assert(sysTime == SysTime(Date(-1999, 7, 17))); |
| sysTime.roll!"days"(-1096); |
| assert(sysTime == SysTime(Date(-1999, 7, 6))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-1999, 2, 28, 7, 9, 2), usecs(234578)); |
| sysTime.roll!"days"(1); |
| assert(sysTime == SysTime(DateTime(-1999, 2, 1, 7, 9, 2), usecs(234578))); |
| sysTime.roll!"days"(-1); |
| assert(sysTime == SysTime(DateTime(-1999, 2, 28, 7, 9, 2), usecs(234578))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(-1999, 7, 6, 7, 9, 2), usecs(234578)); |
| sysTime.roll!"days"(9); |
| assert(sysTime == SysTime(DateTime(-1999, 7, 15, 7, 9, 2), usecs(234578))); |
| sysTime.roll!"days"(-11); |
| assert(sysTime == SysTime(DateTime(-1999, 7, 4, 7, 9, 2), usecs(234578))); |
| sysTime.roll!"days"(30); |
| assert(sysTime == SysTime(DateTime(-1999, 7, 3, 7, 9, 2), usecs(234578))); |
| sysTime.roll!"days"(-3); |
| } |
| |
| // Test Both |
| { |
| auto sysTime = SysTime(Date(1, 7, 6)); |
| sysTime.roll!"days"(-365); |
| assert(sysTime == SysTime(Date(1, 7, 13))); |
| sysTime.roll!"days"(365); |
| assert(sysTime == SysTime(Date(1, 7, 6))); |
| sysTime.roll!"days"(-731); |
| assert(sysTime == SysTime(Date(1, 7, 19))); |
| sysTime.roll!"days"(730); |
| assert(sysTime == SysTime(Date(1, 7, 5))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0)); |
| sysTime.roll!"days"(-1); |
| assert(sysTime == SysTime(DateTime(1, 1, 31, 0, 0, 0))); |
| sysTime.roll!"days"(1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)); |
| sysTime.roll!"days"(-1); |
| assert(sysTime == SysTime(DateTime(1, 1, 31, 23, 59, 59), hnsecs(9_999_999))); |
| sysTime.roll!"days"(1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(0, 12, 31, 0, 0, 0)); |
| sysTime.roll!"days"(1); |
| assert(sysTime == SysTime(DateTime(0, 12, 1, 0, 0, 0))); |
| sysTime.roll!"days"(-1); |
| assert(sysTime == SysTime(DateTime(0, 12, 31, 0, 0, 0))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)); |
| sysTime.roll!"days"(1); |
| assert(sysTime == SysTime(DateTime(0, 12, 1, 23, 59, 59), hnsecs(9_999_999))); |
| sysTime.roll!"days"(-1); |
| assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1, 7, 6, 13, 13, 9), msecs(22)); |
| sysTime.roll!"days"(-365); |
| assert(sysTime == SysTime(DateTime(1, 7, 13, 13, 13, 9), msecs(22))); |
| sysTime.roll!"days"(365); |
| assert(sysTime == SysTime(DateTime(1, 7, 6, 13, 13, 9), msecs(22))); |
| sysTime.roll!"days"(-731); |
| assert(sysTime == SysTime(DateTime(1, 7, 19, 13, 13, 9), msecs(22))); |
| sysTime.roll!"days"(730); |
| assert(sysTime == SysTime(DateTime(1, 7, 5, 13, 13, 9), msecs(22))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(0, 7, 6, 13, 13, 9), msecs(22)); |
| sysTime.roll!"days"(-365); |
| assert(sysTime == SysTime(DateTime(0, 7, 13, 13, 13, 9), msecs(22))); |
| sysTime.roll!"days"(365); |
| assert(sysTime == SysTime(DateTime(0, 7, 6, 13, 13, 9), msecs(22))); |
| sysTime.roll!"days"(-731); |
| assert(sysTime == SysTime(DateTime(0, 7, 19, 13, 13, 9), msecs(22))); |
| sysTime.roll!"days"(730); |
| assert(sysTime == SysTime(DateTime(0, 7, 5, 13, 13, 9), msecs(22))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(0, 7, 6, 13, 13, 9), msecs(22)); |
| sysTime.roll!"days"(-365).roll!"days"(362).roll!"days"(-12).roll!"days"(730); |
| assert(sysTime == SysTime(DateTime(0, 7, 8, 13, 13, 9), msecs(22))); |
| } |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| static assert(!__traits(compiles, cst.roll!"days"(4))); |
| //static assert(!__traits(compiles, ist.roll!"days"(4))); |
| } |
| |
| |
| // Shares documentation with "days" version. |
| ref SysTime roll(string units)(long value) @safe nothrow |
| if (units == "hours" || units == "minutes" || units == "seconds") |
| { |
| try |
| { |
| auto hnsecs = adjTime; |
| auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1; |
| |
| if (hnsecs < 0) |
| { |
| hnsecs += convert!("hours", "hnsecs")(24); |
| --days; |
| } |
| |
| immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs); |
| immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs); |
| immutable second = splitUnitsFromHNSecs!"seconds"(hnsecs); |
| |
| auto dateTime = DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour, |
| cast(int) minute, cast(int) second)); |
| dateTime.roll!units(value); |
| --days; |
| |
| hnsecs += convert!("hours", "hnsecs")(dateTime.hour); |
| hnsecs += convert!("minutes", "hnsecs")(dateTime.minute); |
| hnsecs += convert!("seconds", "hnsecs")(dateTime.second); |
| |
| if (days < 0) |
| { |
| hnsecs -= convert!("hours", "hnsecs")(24); |
| ++days; |
| } |
| |
| immutable newDaysHNSecs = convert!("days", "hnsecs")(days); |
| adjTime = newDaysHNSecs + hnsecs; |
| return this; |
| } |
| catch (Exception e) |
| assert(0, "Either DateTime's constructor or TimeOfDay's constructor threw."); |
| } |
| |
| // Test roll!"hours"(). |
| @safe unittest |
| { |
| static void testST(SysTime orig, int hours, in SysTime expected, size_t line = __LINE__) |
| { |
| orig.roll!"hours"(hours); |
| if (orig != expected) |
| throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line); |
| } |
| |
| // Test A.D. |
| immutable d = msecs(45); |
| auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), d); |
| testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 13, 30, 33), d)); |
| testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 14, 30, 33), d)); |
| testST(beforeAD, 3, SysTime(DateTime(1999, 7, 6, 15, 30, 33), d)); |
| testST(beforeAD, 4, SysTime(DateTime(1999, 7, 6, 16, 30, 33), d)); |
| testST(beforeAD, 5, SysTime(DateTime(1999, 7, 6, 17, 30, 33), d)); |
| testST(beforeAD, 6, SysTime(DateTime(1999, 7, 6, 18, 30, 33), d)); |
| testST(beforeAD, 7, SysTime(DateTime(1999, 7, 6, 19, 30, 33), d)); |
| testST(beforeAD, 8, SysTime(DateTime(1999, 7, 6, 20, 30, 33), d)); |
| testST(beforeAD, 9, SysTime(DateTime(1999, 7, 6, 21, 30, 33), d)); |
| testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 22, 30, 33), d)); |
| testST(beforeAD, 11, SysTime(DateTime(1999, 7, 6, 23, 30, 33), d)); |
| testST(beforeAD, 12, SysTime(DateTime(1999, 7, 6, 0, 30, 33), d)); |
| testST(beforeAD, 13, SysTime(DateTime(1999, 7, 6, 1, 30, 33), d)); |
| testST(beforeAD, 14, SysTime(DateTime(1999, 7, 6, 2, 30, 33), d)); |
| testST(beforeAD, 15, SysTime(DateTime(1999, 7, 6, 3, 30, 33), d)); |
| testST(beforeAD, 16, SysTime(DateTime(1999, 7, 6, 4, 30, 33), d)); |
| testST(beforeAD, 17, SysTime(DateTime(1999, 7, 6, 5, 30, 33), d)); |
| testST(beforeAD, 18, SysTime(DateTime(1999, 7, 6, 6, 30, 33), d)); |
| testST(beforeAD, 19, SysTime(DateTime(1999, 7, 6, 7, 30, 33), d)); |
| testST(beforeAD, 20, SysTime(DateTime(1999, 7, 6, 8, 30, 33), d)); |
| testST(beforeAD, 21, SysTime(DateTime(1999, 7, 6, 9, 30, 33), d)); |
| testST(beforeAD, 22, SysTime(DateTime(1999, 7, 6, 10, 30, 33), d)); |
| testST(beforeAD, 23, SysTime(DateTime(1999, 7, 6, 11, 30, 33), d)); |
| testST(beforeAD, 24, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeAD, 25, SysTime(DateTime(1999, 7, 6, 13, 30, 33), d)); |
| testST(beforeAD, 50, SysTime(DateTime(1999, 7, 6, 14, 30, 33), d)); |
| testST(beforeAD, 10_000, SysTime(DateTime(1999, 7, 6, 4, 30, 33), d)); |
| |
| testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 11, 30, 33), d)); |
| testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 10, 30, 33), d)); |
| testST(beforeAD, -3, SysTime(DateTime(1999, 7, 6, 9, 30, 33), d)); |
| testST(beforeAD, -4, SysTime(DateTime(1999, 7, 6, 8, 30, 33), d)); |
| testST(beforeAD, -5, SysTime(DateTime(1999, 7, 6, 7, 30, 33), d)); |
| testST(beforeAD, -6, SysTime(DateTime(1999, 7, 6, 6, 30, 33), d)); |
| testST(beforeAD, -7, SysTime(DateTime(1999, 7, 6, 5, 30, 33), d)); |
| testST(beforeAD, -8, SysTime(DateTime(1999, 7, 6, 4, 30, 33), d)); |
| testST(beforeAD, -9, SysTime(DateTime(1999, 7, 6, 3, 30, 33), d)); |
| testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 2, 30, 33), d)); |
| testST(beforeAD, -11, SysTime(DateTime(1999, 7, 6, 1, 30, 33), d)); |
| testST(beforeAD, -12, SysTime(DateTime(1999, 7, 6, 0, 30, 33), d)); |
| testST(beforeAD, -13, SysTime(DateTime(1999, 7, 6, 23, 30, 33), d)); |
| testST(beforeAD, -14, SysTime(DateTime(1999, 7, 6, 22, 30, 33), d)); |
| testST(beforeAD, -15, SysTime(DateTime(1999, 7, 6, 21, 30, 33), d)); |
| testST(beforeAD, -16, SysTime(DateTime(1999, 7, 6, 20, 30, 33), d)); |
| testST(beforeAD, -17, SysTime(DateTime(1999, 7, 6, 19, 30, 33), d)); |
| testST(beforeAD, -18, SysTime(DateTime(1999, 7, 6, 18, 30, 33), d)); |
| testST(beforeAD, -19, SysTime(DateTime(1999, 7, 6, 17, 30, 33), d)); |
| testST(beforeAD, -20, SysTime(DateTime(1999, 7, 6, 16, 30, 33), d)); |
| testST(beforeAD, -21, SysTime(DateTime(1999, 7, 6, 15, 30, 33), d)); |
| testST(beforeAD, -22, SysTime(DateTime(1999, 7, 6, 14, 30, 33), d)); |
| testST(beforeAD, -23, SysTime(DateTime(1999, 7, 6, 13, 30, 33), d)); |
| testST(beforeAD, -24, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeAD, -25, SysTime(DateTime(1999, 7, 6, 11, 30, 33), d)); |
| testST(beforeAD, -50, SysTime(DateTime(1999, 7, 6, 10, 30, 33), d)); |
| testST(beforeAD, -10_000, SysTime(DateTime(1999, 7, 6, 20, 30, 33), d)); |
| |
| testST(SysTime(DateTime(1999, 7, 6, 0, 30, 33), d), 1, SysTime(DateTime(1999, 7, 6, 1, 30, 33), d)); |
| testST(SysTime(DateTime(1999, 7, 6, 0, 30, 33), d), 0, SysTime(DateTime(1999, 7, 6, 0, 30, 33), d)); |
| testST(SysTime(DateTime(1999, 7, 6, 0, 30, 33), d), -1, SysTime(DateTime(1999, 7, 6, 23, 30, 33), d)); |
| |
| testST(SysTime(DateTime(1999, 7, 6, 23, 30, 33), d), 1, SysTime(DateTime(1999, 7, 6, 0, 30, 33), d)); |
| testST(SysTime(DateTime(1999, 7, 6, 23, 30, 33), d), 0, SysTime(DateTime(1999, 7, 6, 23, 30, 33), d)); |
| testST(SysTime(DateTime(1999, 7, 6, 23, 30, 33), d), -1, SysTime(DateTime(1999, 7, 6, 22, 30, 33), d)); |
| |
| testST(SysTime(DateTime(1999, 7, 31, 23, 30, 33), d), 1, SysTime(DateTime(1999, 7, 31, 0, 30, 33), d)); |
| testST(SysTime(DateTime(1999, 8, 1, 0, 30, 33), d), -1, SysTime(DateTime(1999, 8, 1, 23, 30, 33), d)); |
| |
| testST(SysTime(DateTime(1999, 12, 31, 23, 30, 33), d), 1, SysTime(DateTime(1999, 12, 31, 0, 30, 33), d)); |
| testST(SysTime(DateTime(2000, 1, 1, 0, 30, 33), d), -1, SysTime(DateTime(2000, 1, 1, 23, 30, 33), d)); |
| |
| testST(SysTime(DateTime(1999, 2, 28, 23, 30, 33), d), 25, SysTime(DateTime(1999, 2, 28, 0, 30, 33), d)); |
| testST(SysTime(DateTime(1999, 3, 2, 0, 30, 33), d), -25, SysTime(DateTime(1999, 3, 2, 23, 30, 33), d)); |
| |
| testST(SysTime(DateTime(2000, 2, 28, 23, 30, 33), d), 25, SysTime(DateTime(2000, 2, 28, 0, 30, 33), d)); |
| testST(SysTime(DateTime(2000, 3, 1, 0, 30, 33), d), -25, SysTime(DateTime(2000, 3, 1, 23, 30, 33), d)); |
| |
| // Test B.C. |
| auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d); |
| testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), d)); |
| testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 14, 30, 33), d)); |
| testST(beforeBC, 3, SysTime(DateTime(-1999, 7, 6, 15, 30, 33), d)); |
| testST(beforeBC, 4, SysTime(DateTime(-1999, 7, 6, 16, 30, 33), d)); |
| testST(beforeBC, 5, SysTime(DateTime(-1999, 7, 6, 17, 30, 33), d)); |
| testST(beforeBC, 6, SysTime(DateTime(-1999, 7, 6, 18, 30, 33), d)); |
| testST(beforeBC, 7, SysTime(DateTime(-1999, 7, 6, 19, 30, 33), d)); |
| testST(beforeBC, 8, SysTime(DateTime(-1999, 7, 6, 20, 30, 33), d)); |
| testST(beforeBC, 9, SysTime(DateTime(-1999, 7, 6, 21, 30, 33), d)); |
| testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 22, 30, 33), d)); |
| testST(beforeBC, 11, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d)); |
| testST(beforeBC, 12, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d)); |
| testST(beforeBC, 13, SysTime(DateTime(-1999, 7, 6, 1, 30, 33), d)); |
| testST(beforeBC, 14, SysTime(DateTime(-1999, 7, 6, 2, 30, 33), d)); |
| testST(beforeBC, 15, SysTime(DateTime(-1999, 7, 6, 3, 30, 33), d)); |
| testST(beforeBC, 16, SysTime(DateTime(-1999, 7, 6, 4, 30, 33), d)); |
| testST(beforeBC, 17, SysTime(DateTime(-1999, 7, 6, 5, 30, 33), d)); |
| testST(beforeBC, 18, SysTime(DateTime(-1999, 7, 6, 6, 30, 33), d)); |
| testST(beforeBC, 19, SysTime(DateTime(-1999, 7, 6, 7, 30, 33), d)); |
| testST(beforeBC, 20, SysTime(DateTime(-1999, 7, 6, 8, 30, 33), d)); |
| testST(beforeBC, 21, SysTime(DateTime(-1999, 7, 6, 9, 30, 33), d)); |
| testST(beforeBC, 22, SysTime(DateTime(-1999, 7, 6, 10, 30, 33), d)); |
| testST(beforeBC, 23, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), d)); |
| testST(beforeBC, 24, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeBC, 25, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), d)); |
| testST(beforeBC, 50, SysTime(DateTime(-1999, 7, 6, 14, 30, 33), d)); |
| testST(beforeBC, 10_000, SysTime(DateTime(-1999, 7, 6, 4, 30, 33), d)); |
| |
| testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), d)); |
| testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 10, 30, 33), d)); |
| testST(beforeBC, -3, SysTime(DateTime(-1999, 7, 6, 9, 30, 33), d)); |
| testST(beforeBC, -4, SysTime(DateTime(-1999, 7, 6, 8, 30, 33), d)); |
| testST(beforeBC, -5, SysTime(DateTime(-1999, 7, 6, 7, 30, 33), d)); |
| testST(beforeBC, -6, SysTime(DateTime(-1999, 7, 6, 6, 30, 33), d)); |
| testST(beforeBC, -7, SysTime(DateTime(-1999, 7, 6, 5, 30, 33), d)); |
| testST(beforeBC, -8, SysTime(DateTime(-1999, 7, 6, 4, 30, 33), d)); |
| testST(beforeBC, -9, SysTime(DateTime(-1999, 7, 6, 3, 30, 33), d)); |
| testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 2, 30, 33), d)); |
| testST(beforeBC, -11, SysTime(DateTime(-1999, 7, 6, 1, 30, 33), d)); |
| testST(beforeBC, -12, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d)); |
| testST(beforeBC, -13, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d)); |
| testST(beforeBC, -14, SysTime(DateTime(-1999, 7, 6, 22, 30, 33), d)); |
| testST(beforeBC, -15, SysTime(DateTime(-1999, 7, 6, 21, 30, 33), d)); |
| testST(beforeBC, -16, SysTime(DateTime(-1999, 7, 6, 20, 30, 33), d)); |
| testST(beforeBC, -17, SysTime(DateTime(-1999, 7, 6, 19, 30, 33), d)); |
| testST(beforeBC, -18, SysTime(DateTime(-1999, 7, 6, 18, 30, 33), d)); |
| testST(beforeBC, -19, SysTime(DateTime(-1999, 7, 6, 17, 30, 33), d)); |
| testST(beforeBC, -20, SysTime(DateTime(-1999, 7, 6, 16, 30, 33), d)); |
| testST(beforeBC, -21, SysTime(DateTime(-1999, 7, 6, 15, 30, 33), d)); |
| testST(beforeBC, -22, SysTime(DateTime(-1999, 7, 6, 14, 30, 33), d)); |
| testST(beforeBC, -23, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), d)); |
| testST(beforeBC, -24, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeBC, -25, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), d)); |
| testST(beforeBC, -50, SysTime(DateTime(-1999, 7, 6, 10, 30, 33), d)); |
| testST(beforeBC, -10_000, SysTime(DateTime(-1999, 7, 6, 20, 30, 33), d)); |
| |
| testST(SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d), 1, SysTime(DateTime(-1999, 7, 6, 1, 30, 33), d)); |
| testST(SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d), 0, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d)); |
| testST(SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d), -1, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d)); |
| |
| testST(SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d), 1, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), d)); |
| testST(SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d), 0, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d)); |
| testST(SysTime(DateTime(-1999, 7, 6, 23, 30, 33), d), -1, SysTime(DateTime(-1999, 7, 6, 22, 30, 33), d)); |
| |
| testST(SysTime(DateTime(-1999, 7, 31, 23, 30, 33), d), 1, SysTime(DateTime(-1999, 7, 31, 0, 30, 33), d)); |
| testST(SysTime(DateTime(-1999, 8, 1, 0, 30, 33), d), -1, SysTime(DateTime(-1999, 8, 1, 23, 30, 33), d)); |
| |
| testST(SysTime(DateTime(-2001, 12, 31, 23, 30, 33), d), 1, SysTime(DateTime(-2001, 12, 31, 0, 30, 33), d)); |
| testST(SysTime(DateTime(-2000, 1, 1, 0, 30, 33), d), -1, SysTime(DateTime(-2000, 1, 1, 23, 30, 33), d)); |
| |
| testST(SysTime(DateTime(-2001, 2, 28, 23, 30, 33), d), 25, SysTime(DateTime(-2001, 2, 28, 0, 30, 33), d)); |
| testST(SysTime(DateTime(-2001, 3, 2, 0, 30, 33), d), -25, SysTime(DateTime(-2001, 3, 2, 23, 30, 33), d)); |
| |
| testST(SysTime(DateTime(-2000, 2, 28, 23, 30, 33), d), 25, SysTime(DateTime(-2000, 2, 28, 0, 30, 33), d)); |
| testST(SysTime(DateTime(-2000, 3, 1, 0, 30, 33), d), -25, SysTime(DateTime(-2000, 3, 1, 23, 30, 33), d)); |
| |
| // Test Both |
| testST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), d), 17_546, SysTime(DateTime(-1, 1, 1, 13, 30, 33), d)); |
| testST(SysTime(DateTime(1, 1, 1, 13, 30, 33), d), -17_546, SysTime(DateTime(1, 1, 1, 11, 30, 33), d)); |
| |
| { |
| auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0)); |
| sysTime.roll!"hours"(-1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 0, 0))); |
| sysTime.roll!"hours"(1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1, 1, 1, 0, 59, 59), hnsecs(9_999_999)); |
| sysTime.roll!"hours"(-1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999))); |
| sysTime.roll!"hours"(1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 59, 59), hnsecs(9_999_999))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(0, 12, 31, 23, 0, 0)); |
| sysTime.roll!"hours"(1); |
| assert(sysTime == SysTime(DateTime(0, 12, 31, 0, 0, 0))); |
| sysTime.roll!"hours"(-1); |
| assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 0, 0))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)); |
| sysTime.roll!"hours"(1); |
| assert(sysTime == SysTime(DateTime(0, 12, 31, 0, 59, 59), hnsecs(9_999_999))); |
| sysTime.roll!"hours"(-1); |
| assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)); |
| sysTime.roll!"hours"(1).roll!"hours"(-67); |
| assert(sysTime == SysTime(DateTime(0, 12, 31, 5, 59, 59), hnsecs(9_999_999))); |
| } |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| static assert(!__traits(compiles, cst.roll!"hours"(4))); |
| //static assert(!__traits(compiles, ist.roll!"hours"(4))); |
| } |
| |
| // Test roll!"minutes"(). |
| @safe unittest |
| { |
| static void testST(SysTime orig, int minutes, in SysTime expected, size_t line = __LINE__) |
| { |
| orig.roll!"minutes"(minutes); |
| if (orig != expected) |
| throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line); |
| } |
| |
| // Test A.D. |
| immutable d = usecs(7203); |
| auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), d); |
| testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 31, 33), d)); |
| testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 32, 33), d)); |
| testST(beforeAD, 3, SysTime(DateTime(1999, 7, 6, 12, 33, 33), d)); |
| testST(beforeAD, 4, SysTime(DateTime(1999, 7, 6, 12, 34, 33), d)); |
| testST(beforeAD, 5, SysTime(DateTime(1999, 7, 6, 12, 35, 33), d)); |
| testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 40, 33), d)); |
| testST(beforeAD, 15, SysTime(DateTime(1999, 7, 6, 12, 45, 33), d)); |
| testST(beforeAD, 29, SysTime(DateTime(1999, 7, 6, 12, 59, 33), d)); |
| testST(beforeAD, 30, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d)); |
| testST(beforeAD, 45, SysTime(DateTime(1999, 7, 6, 12, 15, 33), d)); |
| testST(beforeAD, 60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeAD, 75, SysTime(DateTime(1999, 7, 6, 12, 45, 33), d)); |
| testST(beforeAD, 90, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d)); |
| testST(beforeAD, 100, SysTime(DateTime(1999, 7, 6, 12, 10, 33), d)); |
| |
| testST(beforeAD, 689, SysTime(DateTime(1999, 7, 6, 12, 59, 33), d)); |
| testST(beforeAD, 690, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d)); |
| testST(beforeAD, 691, SysTime(DateTime(1999, 7, 6, 12, 1, 33), d)); |
| testST(beforeAD, 960, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeAD, 1439, SysTime(DateTime(1999, 7, 6, 12, 29, 33), d)); |
| testST(beforeAD, 1440, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeAD, 1441, SysTime(DateTime(1999, 7, 6, 12, 31, 33), d)); |
| testST(beforeAD, 2880, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d)); |
| |
| testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 29, 33), d)); |
| testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 28, 33), d)); |
| testST(beforeAD, -3, SysTime(DateTime(1999, 7, 6, 12, 27, 33), d)); |
| testST(beforeAD, -4, SysTime(DateTime(1999, 7, 6, 12, 26, 33), d)); |
| testST(beforeAD, -5, SysTime(DateTime(1999, 7, 6, 12, 25, 33), d)); |
| testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 20, 33), d)); |
| testST(beforeAD, -15, SysTime(DateTime(1999, 7, 6, 12, 15, 33), d)); |
| testST(beforeAD, -29, SysTime(DateTime(1999, 7, 6, 12, 1, 33), d)); |
| testST(beforeAD, -30, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d)); |
| testST(beforeAD, -45, SysTime(DateTime(1999, 7, 6, 12, 45, 33), d)); |
| testST(beforeAD, -60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeAD, -75, SysTime(DateTime(1999, 7, 6, 12, 15, 33), d)); |
| testST(beforeAD, -90, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d)); |
| testST(beforeAD, -100, SysTime(DateTime(1999, 7, 6, 12, 50, 33), d)); |
| |
| testST(beforeAD, -749, SysTime(DateTime(1999, 7, 6, 12, 1, 33), d)); |
| testST(beforeAD, -750, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d)); |
| testST(beforeAD, -751, SysTime(DateTime(1999, 7, 6, 12, 59, 33), d)); |
| testST(beforeAD, -960, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeAD, -1439, SysTime(DateTime(1999, 7, 6, 12, 31, 33), d)); |
| testST(beforeAD, -1440, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeAD, -1441, SysTime(DateTime(1999, 7, 6, 12, 29, 33), d)); |
| testST(beforeAD, -2880, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d)); |
| |
| testST(SysTime(DateTime(1999, 7, 6, 12, 0, 33), d), 1, SysTime(DateTime(1999, 7, 6, 12, 1, 33), d)); |
| testST(SysTime(DateTime(1999, 7, 6, 12, 0, 33), d), 0, SysTime(DateTime(1999, 7, 6, 12, 0, 33), d)); |
| testST(SysTime(DateTime(1999, 7, 6, 12, 0, 33), d), -1, SysTime(DateTime(1999, 7, 6, 12, 59, 33), d)); |
| |
| testST(SysTime(DateTime(1999, 7, 6, 11, 59, 33), d), 1, SysTime(DateTime(1999, 7, 6, 11, 0, 33), d)); |
| testST(SysTime(DateTime(1999, 7, 6, 11, 59, 33), d), 0, SysTime(DateTime(1999, 7, 6, 11, 59, 33), d)); |
| testST(SysTime(DateTime(1999, 7, 6, 11, 59, 33), d), -1, SysTime(DateTime(1999, 7, 6, 11, 58, 33), d)); |
| |
| testST(SysTime(DateTime(1999, 7, 6, 0, 0, 33), d), 1, SysTime(DateTime(1999, 7, 6, 0, 1, 33), d)); |
| testST(SysTime(DateTime(1999, 7, 6, 0, 0, 33), d), 0, SysTime(DateTime(1999, 7, 6, 0, 0, 33), d)); |
| testST(SysTime(DateTime(1999, 7, 6, 0, 0, 33), d), -1, SysTime(DateTime(1999, 7, 6, 0, 59, 33), d)); |
| |
| testST(SysTime(DateTime(1999, 7, 5, 23, 59, 33), d), 1, SysTime(DateTime(1999, 7, 5, 23, 0, 33), d)); |
| testST(SysTime(DateTime(1999, 7, 5, 23, 59, 33), d), 0, SysTime(DateTime(1999, 7, 5, 23, 59, 33), d)); |
| testST(SysTime(DateTime(1999, 7, 5, 23, 59, 33), d), -1, SysTime(DateTime(1999, 7, 5, 23, 58, 33), d)); |
| |
| testST(SysTime(DateTime(1998, 12, 31, 23, 59, 33), d), 1, SysTime(DateTime(1998, 12, 31, 23, 0, 33), d)); |
| testST(SysTime(DateTime(1998, 12, 31, 23, 59, 33), d), 0, SysTime(DateTime(1998, 12, 31, 23, 59, 33), d)); |
| testST(SysTime(DateTime(1998, 12, 31, 23, 59, 33), d), -1, SysTime(DateTime(1998, 12, 31, 23, 58, 33), d)); |
| |
| // Test B.C. |
| auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d); |
| testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), d)); |
| testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 32, 33), d)); |
| testST(beforeBC, 3, SysTime(DateTime(-1999, 7, 6, 12, 33, 33), d)); |
| testST(beforeBC, 4, SysTime(DateTime(-1999, 7, 6, 12, 34, 33), d)); |
| testST(beforeBC, 5, SysTime(DateTime(-1999, 7, 6, 12, 35, 33), d)); |
| testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 40, 33), d)); |
| testST(beforeBC, 15, SysTime(DateTime(-1999, 7, 6, 12, 45, 33), d)); |
| testST(beforeBC, 29, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), d)); |
| testST(beforeBC, 30, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d)); |
| testST(beforeBC, 45, SysTime(DateTime(-1999, 7, 6, 12, 15, 33), d)); |
| testST(beforeBC, 60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeBC, 75, SysTime(DateTime(-1999, 7, 6, 12, 45, 33), d)); |
| testST(beforeBC, 90, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d)); |
| testST(beforeBC, 100, SysTime(DateTime(-1999, 7, 6, 12, 10, 33), d)); |
| |
| testST(beforeBC, 689, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), d)); |
| testST(beforeBC, 690, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d)); |
| testST(beforeBC, 691, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), d)); |
| testST(beforeBC, 960, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeBC, 1439, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), d)); |
| testST(beforeBC, 1440, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeBC, 1441, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), d)); |
| testST(beforeBC, 2880, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d)); |
| |
| testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), d)); |
| testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 28, 33), d)); |
| testST(beforeBC, -3, SysTime(DateTime(-1999, 7, 6, 12, 27, 33), d)); |
| testST(beforeBC, -4, SysTime(DateTime(-1999, 7, 6, 12, 26, 33), d)); |
| testST(beforeBC, -5, SysTime(DateTime(-1999, 7, 6, 12, 25, 33), d)); |
| testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 20, 33), d)); |
| testST(beforeBC, -15, SysTime(DateTime(-1999, 7, 6, 12, 15, 33), d)); |
| testST(beforeBC, -29, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), d)); |
| testST(beforeBC, -30, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d)); |
| testST(beforeBC, -45, SysTime(DateTime(-1999, 7, 6, 12, 45, 33), d)); |
| testST(beforeBC, -60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeBC, -75, SysTime(DateTime(-1999, 7, 6, 12, 15, 33), d)); |
| testST(beforeBC, -90, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d)); |
| testST(beforeBC, -100, SysTime(DateTime(-1999, 7, 6, 12, 50, 33), d)); |
| |
| testST(beforeBC, -749, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), d)); |
| testST(beforeBC, -750, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d)); |
| testST(beforeBC, -751, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), d)); |
| testST(beforeBC, -960, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeBC, -1439, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), d)); |
| testST(beforeBC, -1440, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeBC, -1441, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), d)); |
| testST(beforeBC, -2880, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d)); |
| |
| testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d), 1, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), d)); |
| testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d), 0, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d)); |
| testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 33), d), -1, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), d)); |
| |
| testST(SysTime(DateTime(-1999, 7, 6, 11, 59, 33), d), 1, SysTime(DateTime(-1999, 7, 6, 11, 0, 33), d)); |
| testST(SysTime(DateTime(-1999, 7, 6, 11, 59, 33), d), 0, SysTime(DateTime(-1999, 7, 6, 11, 59, 33), d)); |
| testST(SysTime(DateTime(-1999, 7, 6, 11, 59, 33), d), -1, SysTime(DateTime(-1999, 7, 6, 11, 58, 33), d)); |
| |
| testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 33), d), 1, SysTime(DateTime(-1999, 7, 6, 0, 1, 33), d)); |
| testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 33), d), 0, SysTime(DateTime(-1999, 7, 6, 0, 0, 33), d)); |
| testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 33), d), -1, SysTime(DateTime(-1999, 7, 6, 0, 59, 33), d)); |
| |
| testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 33), d), 1, SysTime(DateTime(-1999, 7, 5, 23, 0, 33), d)); |
| testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 33), d), 0, SysTime(DateTime(-1999, 7, 5, 23, 59, 33), d)); |
| testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 33), d), -1, SysTime(DateTime(-1999, 7, 5, 23, 58, 33), d)); |
| |
| testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 33), d), 1, SysTime(DateTime(-2000, 12, 31, 23, 0, 33), d)); |
| testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 33), d), 0, SysTime(DateTime(-2000, 12, 31, 23, 59, 33), d)); |
| testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 33), d), -1, SysTime(DateTime(-2000, 12, 31, 23, 58, 33), d)); |
| |
| // Test Both |
| testST(SysTime(DateTime(1, 1, 1, 0, 0, 0)), -1, SysTime(DateTime(1, 1, 1, 0, 59, 0))); |
| testST(SysTime(DateTime(0, 12, 31, 23, 59, 0)), 1, SysTime(DateTime(0, 12, 31, 23, 0, 0))); |
| |
| testST(SysTime(DateTime(0, 1, 1, 0, 0, 0)), -1, SysTime(DateTime(0, 1, 1, 0, 59, 0))); |
| testST(SysTime(DateTime(-1, 12, 31, 23, 59, 0)), 1, SysTime(DateTime(-1, 12, 31, 23, 0, 0))); |
| |
| testST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), d), 1_052_760, SysTime(DateTime(-1, 1, 1, 11, 30, 33), d)); |
| testST(SysTime(DateTime(1, 1, 1, 13, 30, 33), d), -1_052_760, SysTime(DateTime(1, 1, 1, 13, 30, 33), d)); |
| |
| testST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), d), 1_052_782, SysTime(DateTime(-1, 1, 1, 11, 52, 33), d)); |
| testST(SysTime(DateTime(1, 1, 1, 13, 52, 33), d), -1_052_782, SysTime(DateTime(1, 1, 1, 13, 30, 33), d)); |
| |
| { |
| auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0)); |
| sysTime.roll!"minutes"(-1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 59, 0))); |
| sysTime.roll!"minutes"(1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 59), hnsecs(9_999_999)); |
| sysTime.roll!"minutes"(-1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 59, 59), hnsecs(9_999_999))); |
| sysTime.roll!"minutes"(1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 59), hnsecs(9_999_999))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 0)); |
| sysTime.roll!"minutes"(1); |
| assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 0, 0))); |
| sysTime.roll!"minutes"(-1); |
| assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 0))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)); |
| sysTime.roll!"minutes"(1); |
| assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 0, 59), hnsecs(9_999_999))); |
| sysTime.roll!"minutes"(-1); |
| assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)); |
| sysTime.roll!"minutes"(1).roll!"minutes"(-79); |
| assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 41, 59), hnsecs(9_999_999))); |
| } |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| static assert(!__traits(compiles, cst.roll!"minutes"(4))); |
| //static assert(!__traits(compiles, ist.roll!"minutes"(4))); |
| } |
| |
| // Test roll!"seconds"(). |
| @safe unittest |
| { |
| static void testST(SysTime orig, int seconds, in SysTime expected, size_t line = __LINE__) |
| { |
| orig.roll!"seconds"(seconds); |
| if (orig != expected) |
| throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line); |
| } |
| |
| // Test A.D. |
| immutable d = msecs(274); |
| auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), d); |
| testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 30, 34), d)); |
| testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 30, 35), d)); |
| testST(beforeAD, 3, SysTime(DateTime(1999, 7, 6, 12, 30, 36), d)); |
| testST(beforeAD, 4, SysTime(DateTime(1999, 7, 6, 12, 30, 37), d)); |
| testST(beforeAD, 5, SysTime(DateTime(1999, 7, 6, 12, 30, 38), d)); |
| testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 30, 43), d)); |
| testST(beforeAD, 15, SysTime(DateTime(1999, 7, 6, 12, 30, 48), d)); |
| testST(beforeAD, 26, SysTime(DateTime(1999, 7, 6, 12, 30, 59), d)); |
| testST(beforeAD, 27, SysTime(DateTime(1999, 7, 6, 12, 30, 0), d)); |
| testST(beforeAD, 30, SysTime(DateTime(1999, 7, 6, 12, 30, 3), d)); |
| testST(beforeAD, 59, SysTime(DateTime(1999, 7, 6, 12, 30, 32), d)); |
| testST(beforeAD, 60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeAD, 61, SysTime(DateTime(1999, 7, 6, 12, 30, 34), d)); |
| |
| testST(beforeAD, 1766, SysTime(DateTime(1999, 7, 6, 12, 30, 59), d)); |
| testST(beforeAD, 1767, SysTime(DateTime(1999, 7, 6, 12, 30, 0), d)); |
| testST(beforeAD, 1768, SysTime(DateTime(1999, 7, 6, 12, 30, 1), d)); |
| testST(beforeAD, 2007, SysTime(DateTime(1999, 7, 6, 12, 30, 0), d)); |
| testST(beforeAD, 3599, SysTime(DateTime(1999, 7, 6, 12, 30, 32), d)); |
| testST(beforeAD, 3600, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeAD, 3601, SysTime(DateTime(1999, 7, 6, 12, 30, 34), d)); |
| testST(beforeAD, 7200, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d)); |
| |
| testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 30, 32), d)); |
| testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 30, 31), d)); |
| testST(beforeAD, -3, SysTime(DateTime(1999, 7, 6, 12, 30, 30), d)); |
| testST(beforeAD, -4, SysTime(DateTime(1999, 7, 6, 12, 30, 29), d)); |
| testST(beforeAD, -5, SysTime(DateTime(1999, 7, 6, 12, 30, 28), d)); |
| testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 30, 23), d)); |
| testST(beforeAD, -15, SysTime(DateTime(1999, 7, 6, 12, 30, 18), d)); |
| testST(beforeAD, -33, SysTime(DateTime(1999, 7, 6, 12, 30, 0), d)); |
| testST(beforeAD, -34, SysTime(DateTime(1999, 7, 6, 12, 30, 59), d)); |
| testST(beforeAD, -35, SysTime(DateTime(1999, 7, 6, 12, 30, 58), d)); |
| testST(beforeAD, -59, SysTime(DateTime(1999, 7, 6, 12, 30, 34), d)); |
| testST(beforeAD, -60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeAD, -61, SysTime(DateTime(1999, 7, 6, 12, 30, 32), d)); |
| |
| testST(SysTime(DateTime(1999, 7, 6, 12, 30, 0), d), 1, SysTime(DateTime(1999, 7, 6, 12, 30, 1), d)); |
| testST(SysTime(DateTime(1999, 7, 6, 12, 30, 0), d), 0, SysTime(DateTime(1999, 7, 6, 12, 30, 0), d)); |
| testST(SysTime(DateTime(1999, 7, 6, 12, 30, 0), d), -1, SysTime(DateTime(1999, 7, 6, 12, 30, 59), d)); |
| |
| testST(SysTime(DateTime(1999, 7, 6, 12, 0, 0), d), 1, SysTime(DateTime(1999, 7, 6, 12, 0, 1), d)); |
| testST(SysTime(DateTime(1999, 7, 6, 12, 0, 0), d), 0, SysTime(DateTime(1999, 7, 6, 12, 0, 0), d)); |
| testST(SysTime(DateTime(1999, 7, 6, 12, 0, 0), d), -1, SysTime(DateTime(1999, 7, 6, 12, 0, 59), d)); |
| |
| testST(SysTime(DateTime(1999, 7, 6, 0, 0, 0), d), 1, SysTime(DateTime(1999, 7, 6, 0, 0, 1), d)); |
| testST(SysTime(DateTime(1999, 7, 6, 0, 0, 0), d), 0, SysTime(DateTime(1999, 7, 6, 0, 0, 0), d)); |
| testST(SysTime(DateTime(1999, 7, 6, 0, 0, 0), d), -1, SysTime(DateTime(1999, 7, 6, 0, 0, 59), d)); |
| |
| testST(SysTime(DateTime(1999, 7, 5, 23, 59, 59), d), 1, SysTime(DateTime(1999, 7, 5, 23, 59, 0), d)); |
| testST(SysTime(DateTime(1999, 7, 5, 23, 59, 59), d), 0, SysTime(DateTime(1999, 7, 5, 23, 59, 59), d)); |
| testST(SysTime(DateTime(1999, 7, 5, 23, 59, 59), d), -1, SysTime(DateTime(1999, 7, 5, 23, 59, 58), d)); |
| |
| testST(SysTime(DateTime(1998, 12, 31, 23, 59, 59), d), 1, SysTime(DateTime(1998, 12, 31, 23, 59, 0), d)); |
| testST(SysTime(DateTime(1998, 12, 31, 23, 59, 59), d), 0, SysTime(DateTime(1998, 12, 31, 23, 59, 59), d)); |
| testST(SysTime(DateTime(1998, 12, 31, 23, 59, 59), d), -1, SysTime(DateTime(1998, 12, 31, 23, 59, 58), d)); |
| |
| // Test B.C. |
| auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d); |
| testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), d)); |
| testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 35), d)); |
| testST(beforeBC, 3, SysTime(DateTime(-1999, 7, 6, 12, 30, 36), d)); |
| testST(beforeBC, 4, SysTime(DateTime(-1999, 7, 6, 12, 30, 37), d)); |
| testST(beforeBC, 5, SysTime(DateTime(-1999, 7, 6, 12, 30, 38), d)); |
| testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 43), d)); |
| testST(beforeBC, 15, SysTime(DateTime(-1999, 7, 6, 12, 30, 48), d)); |
| testST(beforeBC, 26, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), d)); |
| testST(beforeBC, 27, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d)); |
| testST(beforeBC, 30, SysTime(DateTime(-1999, 7, 6, 12, 30, 3), d)); |
| testST(beforeBC, 59, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), d)); |
| testST(beforeBC, 60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeBC, 61, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), d)); |
| |
| testST(beforeBC, 1766, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), d)); |
| testST(beforeBC, 1767, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d)); |
| testST(beforeBC, 1768, SysTime(DateTime(-1999, 7, 6, 12, 30, 1), d)); |
| testST(beforeBC, 2007, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d)); |
| testST(beforeBC, 3599, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), d)); |
| testST(beforeBC, 3600, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeBC, 3601, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), d)); |
| testST(beforeBC, 7200, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d)); |
| |
| testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), d)); |
| testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 31), d)); |
| testST(beforeBC, -3, SysTime(DateTime(-1999, 7, 6, 12, 30, 30), d)); |
| testST(beforeBC, -4, SysTime(DateTime(-1999, 7, 6, 12, 30, 29), d)); |
| testST(beforeBC, -5, SysTime(DateTime(-1999, 7, 6, 12, 30, 28), d)); |
| testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 23), d)); |
| testST(beforeBC, -15, SysTime(DateTime(-1999, 7, 6, 12, 30, 18), d)); |
| testST(beforeBC, -33, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d)); |
| testST(beforeBC, -34, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), d)); |
| testST(beforeBC, -35, SysTime(DateTime(-1999, 7, 6, 12, 30, 58), d)); |
| testST(beforeBC, -59, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), d)); |
| testST(beforeBC, -60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), d)); |
| testST(beforeBC, -61, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), d)); |
| |
| testST(SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d), 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 1), d)); |
| testST(SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d), 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d)); |
| testST(SysTime(DateTime(-1999, 7, 6, 12, 30, 0), d), -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), d)); |
| |
| testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 0), d), 1, SysTime(DateTime(-1999, 7, 6, 12, 0, 1), d)); |
| testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 0), d), 0, SysTime(DateTime(-1999, 7, 6, 12, 0, 0), d)); |
| testST(SysTime(DateTime(-1999, 7, 6, 12, 0, 0), d), -1, SysTime(DateTime(-1999, 7, 6, 12, 0, 59), d)); |
| |
| testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 0), d), 1, SysTime(DateTime(-1999, 7, 6, 0, 0, 1), d)); |
| testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 0), d), 0, SysTime(DateTime(-1999, 7, 6, 0, 0, 0), d)); |
| testST(SysTime(DateTime(-1999, 7, 6, 0, 0, 0), d), -1, SysTime(DateTime(-1999, 7, 6, 0, 0, 59), d)); |
| |
| testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 59), d), 1, SysTime(DateTime(-1999, 7, 5, 23, 59, 0), d)); |
| testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 59), d), 0, SysTime(DateTime(-1999, 7, 5, 23, 59, 59), d)); |
| testST(SysTime(DateTime(-1999, 7, 5, 23, 59, 59), d), -1, SysTime(DateTime(-1999, 7, 5, 23, 59, 58), d)); |
| |
| testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 59), d), 1, SysTime(DateTime(-2000, 12, 31, 23, 59, 0), d)); |
| testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 59), d), 0, SysTime(DateTime(-2000, 12, 31, 23, 59, 59), d)); |
| testST(SysTime(DateTime(-2000, 12, 31, 23, 59, 59), d), -1, SysTime(DateTime(-2000, 12, 31, 23, 59, 58), d)); |
| |
| // Test Both |
| testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), d), -1, SysTime(DateTime(1, 1, 1, 0, 0, 59), d)); |
| testST(SysTime(DateTime(0, 12, 31, 23, 59, 59), d), 1, SysTime(DateTime(0, 12, 31, 23, 59, 0), d)); |
| |
| testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), d), -1, SysTime(DateTime(0, 1, 1, 0, 0, 59), d)); |
| testST(SysTime(DateTime(-1, 12, 31, 23, 59, 59), d), 1, SysTime(DateTime(-1, 12, 31, 23, 59, 0), d)); |
| |
| testST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), d), 63_165_600L, SysTime(DateTime(-1, 1, 1, 11, 30, 33), d)); |
| testST(SysTime(DateTime(1, 1, 1, 13, 30, 33), d), -63_165_600L, SysTime(DateTime(1, 1, 1, 13, 30, 33), d)); |
| |
| testST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), d), 63_165_617L, SysTime(DateTime(-1, 1, 1, 11, 30, 50), d)); |
| testST(SysTime(DateTime(1, 1, 1, 13, 30, 50), d), -63_165_617L, SysTime(DateTime(1, 1, 1, 13, 30, 33), d)); |
| |
| { |
| auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0)); |
| sysTime.roll!"seconds"(-1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 59))); |
| sysTime.roll!"seconds"(1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(9_999_999)); |
| sysTime.roll!"seconds"(-1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 59), hnsecs(9_999_999))); |
| sysTime.roll!"seconds"(1); |
| assert(sysTime == SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(9_999_999))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59)); |
| sysTime.roll!"seconds"(1); |
| assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 0))); |
| sysTime.roll!"seconds"(-1); |
| assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 59))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)); |
| sysTime.roll!"seconds"(1); |
| assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 0), hnsecs(9_999_999))); |
| sysTime.roll!"seconds"(-1); |
| assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999))); |
| } |
| |
| { |
| auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)); |
| sysTime.roll!"seconds"(1).roll!"seconds"(-102); |
| assert(sysTime == SysTime(DateTime(0, 12, 31, 23, 59, 18), hnsecs(9_999_999))); |
| } |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| static assert(!__traits(compiles, cst.roll!"seconds"(4))); |
| //static assert(!__traits(compiles, ist.roll!"seconds"(4))); |
| } |
| |
| |
| // Shares documentation with "days" version. |
| ref SysTime roll(string units)(long value) @safe nothrow |
| if (units == "msecs" || units == "usecs" || units == "hnsecs") |
| { |
| auto hnsecs = adjTime; |
| immutable days = splitUnitsFromHNSecs!"days"(hnsecs); |
| immutable negative = hnsecs < 0; |
| |
| if (negative) |
| hnsecs += convert!("hours", "hnsecs")(24); |
| |
| immutable seconds = splitUnitsFromHNSecs!"seconds"(hnsecs); |
| hnsecs += convert!(units, "hnsecs")(value); |
| hnsecs %= convert!("seconds", "hnsecs")(1); |
| |
| if (hnsecs < 0) |
| hnsecs += convert!("seconds", "hnsecs")(1); |
| hnsecs += convert!("seconds", "hnsecs")(seconds); |
| |
| if (negative) |
| hnsecs -= convert!("hours", "hnsecs")(24); |
| |
| immutable newDaysHNSecs = convert!("days", "hnsecs")(days); |
| adjTime = newDaysHNSecs + hnsecs; |
| return this; |
| } |
| |
| |
| // Test roll!"msecs"(). |
| @safe unittest |
| { |
| static void testST(SysTime orig, int milliseconds, in SysTime expected, size_t line = __LINE__) |
| { |
| orig.roll!"msecs"(milliseconds); |
| if (orig != expected) |
| throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line); |
| } |
| |
| // Test A.D. |
| auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274)); |
| testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274))); |
| testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(275))); |
| testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(276))); |
| testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(284))); |
| testST(beforeAD, 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(374))); |
| testST(beforeAD, 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999))); |
| testST(beforeAD, 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33))); |
| testST(beforeAD, 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274))); |
| testST(beforeAD, 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(275))); |
| testST(beforeAD, 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274))); |
| testST(beforeAD, 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999))); |
| testST(beforeAD, 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33))); |
| testST(beforeAD, 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(1))); |
| testST(beforeAD, 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999))); |
| testST(beforeAD, 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33))); |
| |
| testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(273))); |
| testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(272))); |
| testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(264))); |
| testST(beforeAD, -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(174))); |
| testST(beforeAD, -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33))); |
| testST(beforeAD, -275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999))); |
| testST(beforeAD, -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274))); |
| testST(beforeAD, -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(273))); |
| testST(beforeAD, -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(274))); |
| testST(beforeAD, -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33))); |
| testST(beforeAD, -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999))); |
| testST(beforeAD, -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33))); |
| testST(beforeAD, -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(999))); |
| |
| // Test B.C. |
| auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274)); |
| testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274))); |
| testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(275))); |
| testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(276))); |
| testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(284))); |
| testST(beforeBC, 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(374))); |
| testST(beforeBC, 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999))); |
| testST(beforeBC, 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33))); |
| testST(beforeBC, 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274))); |
| testST(beforeBC, 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(275))); |
| testST(beforeBC, 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274))); |
| testST(beforeBC, 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999))); |
| testST(beforeBC, 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33))); |
| testST(beforeBC, 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(1))); |
| testST(beforeBC, 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999))); |
| testST(beforeBC, 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33))); |
| |
| testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(273))); |
| testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(272))); |
| testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(264))); |
| testST(beforeBC, -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(174))); |
| testST(beforeBC, -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33))); |
| testST(beforeBC, -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999))); |
| testST(beforeBC, -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274))); |
| testST(beforeBC, -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(273))); |
| testST(beforeBC, -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(274))); |
| testST(beforeBC, -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33))); |
| testST(beforeBC, -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999))); |
| testST(beforeBC, -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33))); |
| testST(beforeBC, -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), msecs(999))); |
| |
| // Test Both |
| auto beforeBoth1 = SysTime(DateTime(1, 1, 1, 0, 0, 0)); |
| testST(beforeBoth1, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), msecs(1))); |
| testST(beforeBoth1, 0, SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| testST(beforeBoth1, -1, SysTime(DateTime(1, 1, 1, 0, 0, 0), msecs(999))); |
| testST(beforeBoth1, -2, SysTime(DateTime(1, 1, 1, 0, 0, 0), msecs(998))); |
| testST(beforeBoth1, -1000, SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| testST(beforeBoth1, -2000, SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| testST(beforeBoth1, -2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), msecs(445))); |
| |
| auto beforeBoth2 = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)); |
| testST(beforeBoth2, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_989_999))); |
| testST(beforeBoth2, 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999))); |
| testST(beforeBoth2, 1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9999))); |
| testST(beforeBoth2, 2, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(19_999))); |
| testST(beforeBoth2, 1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999))); |
| testST(beforeBoth2, 2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999))); |
| testST(beforeBoth2, 2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(5_549_999))); |
| |
| { |
| auto st = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)); |
| st.roll!"msecs"(1202).roll!"msecs"(-703); |
| assert(st == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(4_989_999))); |
| } |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| static assert(!__traits(compiles, cst.addMSecs(4))); |
| //static assert(!__traits(compiles, ist.addMSecs(4))); |
| } |
| |
| // Test roll!"usecs"(). |
| @safe unittest |
| { |
| static void testST(SysTime orig, long microseconds, in SysTime expected, size_t line = __LINE__) |
| { |
| orig.roll!"usecs"(microseconds); |
| if (orig != expected) |
| throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line); |
| } |
| |
| // Test A.D. |
| auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274)); |
| testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274))); |
| testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(275))); |
| testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(276))); |
| testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(284))); |
| testST(beforeAD, 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(374))); |
| testST(beforeAD, 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(999))); |
| testST(beforeAD, 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(1000))); |
| testST(beforeAD, 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(1274))); |
| testST(beforeAD, 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(1275))); |
| testST(beforeAD, 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(2274))); |
| testST(beforeAD, 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(26_999))); |
| testST(beforeAD, 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(27_000))); |
| testST(beforeAD, 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(27_001))); |
| testST(beforeAD, 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(766_999))); |
| testST(beforeAD, 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(767_000))); |
| testST(beforeAD, 1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274))); |
| testST(beforeAD, 60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274))); |
| testST(beforeAD, 3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274))); |
| |
| testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(273))); |
| testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(272))); |
| testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(264))); |
| testST(beforeAD, -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(174))); |
| testST(beforeAD, -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33))); |
| testST(beforeAD, -275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(999_999))); |
| testST(beforeAD, -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(999_274))); |
| testST(beforeAD, -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(999_273))); |
| testST(beforeAD, -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(998_274))); |
| testST(beforeAD, -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(967_000))); |
| testST(beforeAD, -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(966_999))); |
| testST(beforeAD, -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(167_000))); |
| testST(beforeAD, -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(166_999))); |
| testST(beforeAD, -1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274))); |
| testST(beforeAD, -60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274))); |
| testST(beforeAD, -3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(274))); |
| |
| // Test B.C. |
| auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274)); |
| testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274))); |
| testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(275))); |
| testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(276))); |
| testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(284))); |
| testST(beforeBC, 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(374))); |
| testST(beforeBC, 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(999))); |
| testST(beforeBC, 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(1000))); |
| testST(beforeBC, 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(1274))); |
| testST(beforeBC, 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(1275))); |
| testST(beforeBC, 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(2274))); |
| testST(beforeBC, 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(26_999))); |
| testST(beforeBC, 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(27_000))); |
| testST(beforeBC, 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(27_001))); |
| testST(beforeBC, 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(766_999))); |
| testST(beforeBC, 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(767_000))); |
| testST(beforeBC, 1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274))); |
| testST(beforeBC, 60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274))); |
| testST(beforeBC, 3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274))); |
| |
| testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(273))); |
| testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(272))); |
| testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(264))); |
| testST(beforeBC, -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(174))); |
| testST(beforeBC, -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33))); |
| testST(beforeBC, -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(999_999))); |
| testST(beforeBC, -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(999_274))); |
| testST(beforeBC, -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(999_273))); |
| testST(beforeBC, -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(998_274))); |
| testST(beforeBC, -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(967_000))); |
| testST(beforeBC, -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(966_999))); |
| testST(beforeBC, -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(167_000))); |
| testST(beforeBC, -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(166_999))); |
| testST(beforeBC, -1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274))); |
| testST(beforeBC, -60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274))); |
| testST(beforeBC, -3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), usecs(274))); |
| |
| // Test Both |
| auto beforeBoth1 = SysTime(DateTime(1, 1, 1, 0, 0, 0)); |
| testST(beforeBoth1, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(1))); |
| testST(beforeBoth1, 0, SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| testST(beforeBoth1, -1, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(999_999))); |
| testST(beforeBoth1, -2, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(999_998))); |
| testST(beforeBoth1, -1000, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(999_000))); |
| testST(beforeBoth1, -2000, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(998_000))); |
| testST(beforeBoth1, -2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(997_445))); |
| testST(beforeBoth1, -1_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| testST(beforeBoth1, -2_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| testST(beforeBoth1, -2_333_333, SysTime(DateTime(1, 1, 1, 0, 0, 0), usecs(666_667))); |
| |
| auto beforeBoth2 = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)); |
| testST(beforeBoth2, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_989))); |
| testST(beforeBoth2, 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999))); |
| testST(beforeBoth2, 1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9))); |
| testST(beforeBoth2, 2, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(19))); |
| testST(beforeBoth2, 1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9999))); |
| testST(beforeBoth2, 2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(19_999))); |
| testST(beforeBoth2, 2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(25_549))); |
| testST(beforeBoth2, 1_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999))); |
| testST(beforeBoth2, 2_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999))); |
| testST(beforeBoth2, 2_333_333, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(3_333_329))); |
| |
| { |
| auto st = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)); |
| st.roll!"usecs"(9_020_027); |
| assert(st == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(200_269))); |
| } |
| |
| { |
| auto st = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)); |
| st.roll!"usecs"(9_020_027).roll!"usecs"(-70_034); |
| assert(st == SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_499_929))); |
| } |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| static assert(!__traits(compiles, cst.roll!"usecs"(4))); |
| //static assert(!__traits(compiles, ist.roll!"usecs"(4))); |
| } |
| |
| // Test roll!"hnsecs"(). |
| @safe unittest |
| { |
| static void testST(SysTime orig, long hnsecs, in SysTime expected, size_t line = __LINE__) |
| { |
| orig.roll!"hnsecs"(hnsecs); |
| if (orig != expected) |
| throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line); |
| } |
| |
| // Test A.D. |
| auto dtAD = DateTime(1999, 7, 6, 12, 30, 33); |
| auto beforeAD = SysTime(dtAD, hnsecs(274)); |
| testST(beforeAD, 0, SysTime(dtAD, hnsecs(274))); |
| testST(beforeAD, 1, SysTime(dtAD, hnsecs(275))); |
| testST(beforeAD, 2, SysTime(dtAD, hnsecs(276))); |
| testST(beforeAD, 10, SysTime(dtAD, hnsecs(284))); |
| testST(beforeAD, 100, SysTime(dtAD, hnsecs(374))); |
| testST(beforeAD, 725, SysTime(dtAD, hnsecs(999))); |
| testST(beforeAD, 726, SysTime(dtAD, hnsecs(1000))); |
| testST(beforeAD, 1000, SysTime(dtAD, hnsecs(1274))); |
| testST(beforeAD, 1001, SysTime(dtAD, hnsecs(1275))); |
| testST(beforeAD, 2000, SysTime(dtAD, hnsecs(2274))); |
| testST(beforeAD, 26_725, SysTime(dtAD, hnsecs(26_999))); |
| testST(beforeAD, 26_726, SysTime(dtAD, hnsecs(27_000))); |
| testST(beforeAD, 26_727, SysTime(dtAD, hnsecs(27_001))); |
| testST(beforeAD, 1_766_725, SysTime(dtAD, hnsecs(1_766_999))); |
| testST(beforeAD, 1_766_726, SysTime(dtAD, hnsecs(1_767_000))); |
| testST(beforeAD, 1_000_000, SysTime(dtAD, hnsecs(1_000_274))); |
| testST(beforeAD, 60_000_000L, SysTime(dtAD, hnsecs(274))); |
| testST(beforeAD, 3_600_000_000L, SysTime(dtAD, hnsecs(274))); |
| testST(beforeAD, 600_000_000L, SysTime(dtAD, hnsecs(274))); |
| testST(beforeAD, 36_000_000_000L, SysTime(dtAD, hnsecs(274))); |
| |
| testST(beforeAD, -1, SysTime(dtAD, hnsecs(273))); |
| testST(beforeAD, -2, SysTime(dtAD, hnsecs(272))); |
| testST(beforeAD, -10, SysTime(dtAD, hnsecs(264))); |
| testST(beforeAD, -100, SysTime(dtAD, hnsecs(174))); |
| testST(beforeAD, -274, SysTime(dtAD)); |
| testST(beforeAD, -275, SysTime(dtAD, hnsecs(9_999_999))); |
| testST(beforeAD, -1000, SysTime(dtAD, hnsecs(9_999_274))); |
| testST(beforeAD, -1001, SysTime(dtAD, hnsecs(9_999_273))); |
| testST(beforeAD, -2000, SysTime(dtAD, hnsecs(9_998_274))); |
| testST(beforeAD, -33_274, SysTime(dtAD, hnsecs(9_967_000))); |
| testST(beforeAD, -33_275, SysTime(dtAD, hnsecs(9_966_999))); |
| testST(beforeAD, -1_833_274, SysTime(dtAD, hnsecs(8_167_000))); |
| testST(beforeAD, -1_833_275, SysTime(dtAD, hnsecs(8_166_999))); |
| testST(beforeAD, -1_000_000, SysTime(dtAD, hnsecs(9_000_274))); |
| testST(beforeAD, -60_000_000L, SysTime(dtAD, hnsecs(274))); |
| testST(beforeAD, -3_600_000_000L, SysTime(dtAD, hnsecs(274))); |
| testST(beforeAD, -600_000_000L, SysTime(dtAD, hnsecs(274))); |
| testST(beforeAD, -36_000_000_000L, SysTime(dtAD, hnsecs(274))); |
| |
| // Test B.C. |
| auto dtBC = DateTime(-1999, 7, 6, 12, 30, 33); |
| auto beforeBC = SysTime(dtBC, hnsecs(274)); |
| testST(beforeBC, 0, SysTime(dtBC, hnsecs(274))); |
| testST(beforeBC, 1, SysTime(dtBC, hnsecs(275))); |
| testST(beforeBC, 2, SysTime(dtBC, hnsecs(276))); |
| testST(beforeBC, 10, SysTime(dtBC, hnsecs(284))); |
| testST(beforeBC, 100, SysTime(dtBC, hnsecs(374))); |
| testST(beforeBC, 725, SysTime(dtBC, hnsecs(999))); |
| testST(beforeBC, 726, SysTime(dtBC, hnsecs(1000))); |
| testST(beforeBC, 1000, SysTime(dtBC, hnsecs(1274))); |
| testST(beforeBC, 1001, SysTime(dtBC, hnsecs(1275))); |
| testST(beforeBC, 2000, SysTime(dtBC, hnsecs(2274))); |
| testST(beforeBC, 26_725, SysTime(dtBC, hnsecs(26_999))); |
| testST(beforeBC, 26_726, SysTime(dtBC, hnsecs(27_000))); |
| testST(beforeBC, 26_727, SysTime(dtBC, hnsecs(27_001))); |
| testST(beforeBC, 1_766_725, SysTime(dtBC, hnsecs(1_766_999))); |
| testST(beforeBC, 1_766_726, SysTime(dtBC, hnsecs(1_767_000))); |
| testST(beforeBC, 1_000_000, SysTime(dtBC, hnsecs(1_000_274))); |
| testST(beforeBC, 60_000_000L, SysTime(dtBC, hnsecs(274))); |
| testST(beforeBC, 3_600_000_000L, SysTime(dtBC, hnsecs(274))); |
| testST(beforeBC, 600_000_000L, SysTime(dtBC, hnsecs(274))); |
| testST(beforeBC, 36_000_000_000L, SysTime(dtBC, hnsecs(274))); |
| |
| testST(beforeBC, -1, SysTime(dtBC, hnsecs(273))); |
| testST(beforeBC, -2, SysTime(dtBC, hnsecs(272))); |
| testST(beforeBC, -10, SysTime(dtBC, hnsecs(264))); |
| testST(beforeBC, -100, SysTime(dtBC, hnsecs(174))); |
| testST(beforeBC, -274, SysTime(dtBC)); |
| testST(beforeBC, -275, SysTime(dtBC, hnsecs(9_999_999))); |
| testST(beforeBC, -1000, SysTime(dtBC, hnsecs(9_999_274))); |
| testST(beforeBC, -1001, SysTime(dtBC, hnsecs(9_999_273))); |
| testST(beforeBC, -2000, SysTime(dtBC, hnsecs(9_998_274))); |
| testST(beforeBC, -33_274, SysTime(dtBC, hnsecs(9_967_000))); |
| testST(beforeBC, -33_275, SysTime(dtBC, hnsecs(9_966_999))); |
| testST(beforeBC, -1_833_274, SysTime(dtBC, hnsecs(8_167_000))); |
| testST(beforeBC, -1_833_275, SysTime(dtBC, hnsecs(8_166_999))); |
| testST(beforeBC, -1_000_000, SysTime(dtBC, hnsecs(9_000_274))); |
| testST(beforeBC, -60_000_000L, SysTime(dtBC, hnsecs(274))); |
| testST(beforeBC, -3_600_000_000L, SysTime(dtBC, hnsecs(274))); |
| testST(beforeBC, -600_000_000L, SysTime(dtBC, hnsecs(274))); |
| testST(beforeBC, -36_000_000_000L, SysTime(dtBC, hnsecs(274))); |
| |
| // Test Both |
| auto dtBoth1 = DateTime(1, 1, 1, 0, 0, 0); |
| auto beforeBoth1 = SysTime(dtBoth1); |
| testST(beforeBoth1, 1, SysTime(dtBoth1, hnsecs(1))); |
| testST(beforeBoth1, 0, SysTime(dtBoth1)); |
| testST(beforeBoth1, -1, SysTime(dtBoth1, hnsecs(9_999_999))); |
| testST(beforeBoth1, -2, SysTime(dtBoth1, hnsecs(9_999_998))); |
| testST(beforeBoth1, -1000, SysTime(dtBoth1, hnsecs(9_999_000))); |
| testST(beforeBoth1, -2000, SysTime(dtBoth1, hnsecs(9_998_000))); |
| testST(beforeBoth1, -2555, SysTime(dtBoth1, hnsecs(9_997_445))); |
| testST(beforeBoth1, -1_000_000, SysTime(dtBoth1, hnsecs(9_000_000))); |
| testST(beforeBoth1, -2_000_000, SysTime(dtBoth1, hnsecs(8_000_000))); |
| testST(beforeBoth1, -2_333_333, SysTime(dtBoth1, hnsecs(7_666_667))); |
| testST(beforeBoth1, -10_000_000, SysTime(dtBoth1)); |
| testST(beforeBoth1, -20_000_000, SysTime(dtBoth1)); |
| testST(beforeBoth1, -20_888_888, SysTime(dtBoth1, hnsecs(9_111_112))); |
| |
| auto dtBoth2 = DateTime(0, 12, 31, 23, 59, 59); |
| auto beforeBoth2 = SysTime(dtBoth2, hnsecs(9_999_999)); |
| testST(beforeBoth2, -1, SysTime(dtBoth2, hnsecs(9_999_998))); |
| testST(beforeBoth2, 0, SysTime(dtBoth2, hnsecs(9_999_999))); |
| testST(beforeBoth2, 1, SysTime(dtBoth2)); |
| testST(beforeBoth2, 2, SysTime(dtBoth2, hnsecs(1))); |
| testST(beforeBoth2, 1000, SysTime(dtBoth2, hnsecs(999))); |
| testST(beforeBoth2, 2000, SysTime(dtBoth2, hnsecs(1999))); |
| testST(beforeBoth2, 2555, SysTime(dtBoth2, hnsecs(2554))); |
| testST(beforeBoth2, 1_000_000, SysTime(dtBoth2, hnsecs(999_999))); |
| testST(beforeBoth2, 2_000_000, SysTime(dtBoth2, hnsecs(1_999_999))); |
| testST(beforeBoth2, 2_333_333, SysTime(dtBoth2, hnsecs(2_333_332))); |
| testST(beforeBoth2, 10_000_000, SysTime(dtBoth2, hnsecs(9_999_999))); |
| testST(beforeBoth2, 20_000_000, SysTime(dtBoth2, hnsecs(9_999_999))); |
| testST(beforeBoth2, 20_888_888, SysTime(dtBoth2, hnsecs(888_887))); |
| |
| { |
| auto st = SysTime(dtBoth2, hnsecs(9_999_999)); |
| st.roll!"hnsecs"(70_777_222).roll!"hnsecs"(-222_555_292); |
| assert(st == SysTime(dtBoth2, hnsecs(8_221_929))); |
| } |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| static assert(!__traits(compiles, cst.roll!"hnsecs"(4))); |
| //static assert(!__traits(compiles, ist.roll!"hnsecs"(4))); |
| } |
| |
| |
| /++ |
| Gives the result of adding or subtracting a $(REF Duration, core,time) |
| from this $(LREF SysTime). |
| |
| The legal types of arithmetic for $(LREF SysTime) using this operator |
| are |
| |
| $(BOOKTABLE, |
| $(TR $(TD SysTime) $(TD +) $(TD Duration) $(TD -->) $(TD SysTime)) |
| $(TR $(TD SysTime) $(TD -) $(TD Duration) $(TD -->) $(TD SysTime)) |
| ) |
| |
| Params: |
| duration = The $(REF Duration, core,time) to add to or subtract from |
| this $(LREF SysTime). |
| +/ |
| SysTime opBinary(string op)(Duration duration) @safe const pure nothrow |
| if (op == "+" || op == "-") |
| { |
| SysTime retval = SysTime(this._stdTime, this._timezone); |
| immutable hnsecs = duration.total!"hnsecs"; |
| mixin("retval._stdTime " ~ op ~ "= hnsecs;"); |
| return retval; |
| } |
| |
| /// |
| @safe unittest |
| { |
| import core.time : hours, seconds; |
| import std.datetime.date : DateTime; |
| |
| assert(SysTime(DateTime(2015, 12, 31, 23, 59, 59)) + seconds(1) == |
| SysTime(DateTime(2016, 1, 1, 0, 0, 0))); |
| |
| assert(SysTime(DateTime(2015, 12, 31, 23, 59, 59)) + hours(1) == |
| SysTime(DateTime(2016, 1, 1, 0, 59, 59))); |
| |
| assert(SysTime(DateTime(2016, 1, 1, 0, 0, 0)) - seconds(1) == |
| SysTime(DateTime(2015, 12, 31, 23, 59, 59))); |
| |
| assert(SysTime(DateTime(2016, 1, 1, 0, 59, 59)) - hours(1) == |
| SysTime(DateTime(2015, 12, 31, 23, 59, 59))); |
| } |
| |
| @safe unittest |
| { |
| auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_678)); |
| |
| assert(st + dur!"weeks"(7) == SysTime(DateTime(1999, 8, 24, 12, 30, 33), hnsecs(2_345_678))); |
| assert(st + dur!"weeks"(-7) == SysTime(DateTime(1999, 5, 18, 12, 30, 33), hnsecs(2_345_678))); |
| assert(st + dur!"days"(7) == SysTime(DateTime(1999, 7, 13, 12, 30, 33), hnsecs(2_345_678))); |
| assert(st + dur!"days"(-7) == SysTime(DateTime(1999, 6, 29, 12, 30, 33), hnsecs(2_345_678))); |
| assert(st + dur!"hours"(7) == SysTime(DateTime(1999, 7, 6, 19, 30, 33), hnsecs(2_345_678))); |
| assert(st + dur!"hours"(-7) == SysTime(DateTime(1999, 7, 6, 5, 30, 33), hnsecs(2_345_678))); |
| assert(st + dur!"minutes"(7) == SysTime(DateTime(1999, 7, 6, 12, 37, 33), hnsecs(2_345_678))); |
| assert(st + dur!"minutes"(-7) == SysTime(DateTime(1999, 7, 6, 12, 23, 33), hnsecs(2_345_678))); |
| assert(st + dur!"seconds"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 40), hnsecs(2_345_678))); |
| assert(st + dur!"seconds"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 26), hnsecs(2_345_678))); |
| assert(st + dur!"msecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_415_678))); |
| assert(st + dur!"msecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_275_678))); |
| assert(st + dur!"usecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_748))); |
| assert(st + dur!"usecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_608))); |
| assert(st + dur!"hnsecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_685))); |
| assert(st + dur!"hnsecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_671))); |
| |
| assert(st - dur!"weeks"(-7) == SysTime(DateTime(1999, 8, 24, 12, 30, 33), hnsecs(2_345_678))); |
| assert(st - dur!"weeks"(7) == SysTime(DateTime(1999, 5, 18, 12, 30, 33), hnsecs(2_345_678))); |
| assert(st - dur!"days"(-7) == SysTime(DateTime(1999, 7, 13, 12, 30, 33), hnsecs(2_345_678))); |
| assert(st - dur!"days"(7) == SysTime(DateTime(1999, 6, 29, 12, 30, 33), hnsecs(2_345_678))); |
| assert(st - dur!"hours"(-7) == SysTime(DateTime(1999, 7, 6, 19, 30, 33), hnsecs(2_345_678))); |
| assert(st - dur!"hours"(7) == SysTime(DateTime(1999, 7, 6, 5, 30, 33), hnsecs(2_345_678))); |
| assert(st - dur!"minutes"(-7) == SysTime(DateTime(1999, 7, 6, 12, 37, 33), hnsecs(2_345_678))); |
| assert(st - dur!"minutes"(7) == SysTime(DateTime(1999, 7, 6, 12, 23, 33), hnsecs(2_345_678))); |
| assert(st - dur!"seconds"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 40), hnsecs(2_345_678))); |
| assert(st - dur!"seconds"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 26), hnsecs(2_345_678))); |
| assert(st - dur!"msecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_415_678))); |
| assert(st - dur!"msecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_275_678))); |
| assert(st - dur!"usecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_748))); |
| assert(st - dur!"usecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_608))); |
| assert(st - dur!"hnsecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_685))); |
| assert(st - dur!"hnsecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2_345_671))); |
| |
| static void testST(in SysTime orig, long hnsecs, in SysTime expected, size_t line = __LINE__) |
| { |
| auto result = orig + dur!"hnsecs"(hnsecs); |
| if (result != expected) |
| throw new AssertError(format("Failed. actual [%s] != expected [%s]", result, expected), __FILE__, line); |
| } |
| |
| // Test A.D. |
| auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(274)); |
| testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(274))); |
| testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(275))); |
| testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(276))); |
| testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(284))); |
| testST(beforeAD, 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(374))); |
| testST(beforeAD, 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(999))); |
| testST(beforeAD, 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1000))); |
| testST(beforeAD, 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1274))); |
| testST(beforeAD, 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1275))); |
| testST(beforeAD, 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2274))); |
| testST(beforeAD, 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(26_999))); |
| testST(beforeAD, 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(27_000))); |
| testST(beforeAD, 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(27_001))); |
| testST(beforeAD, 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_766_999))); |
| testST(beforeAD, 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_767_000))); |
| testST(beforeAD, 1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_000_274))); |
| testST(beforeAD, 60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 39), hnsecs(274))); |
| testST(beforeAD, 3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 36, 33), hnsecs(274))); |
| testST(beforeAD, 600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 31, 33), hnsecs(274))); |
| testST(beforeAD, 36_000_000_000L, SysTime(DateTime(1999, 7, 6, 13, 30, 33), hnsecs(274))); |
| |
| testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(273))); |
| testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(272))); |
| testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(264))); |
| testST(beforeAD, -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(174))); |
| testST(beforeAD, -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33))); |
| testST(beforeAD, -275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_999))); |
| testST(beforeAD, -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_274))); |
| testST(beforeAD, -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_273))); |
| testST(beforeAD, -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_998_274))); |
| testST(beforeAD, -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_967_000))); |
| testST(beforeAD, -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_966_999))); |
| testST(beforeAD, -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(8_167_000))); |
| testST(beforeAD, -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(8_166_999))); |
| testST(beforeAD, -1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_000_274))); |
| testST(beforeAD, -60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 27), hnsecs(274))); |
| testST(beforeAD, -3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 24, 33), hnsecs(274))); |
| testST(beforeAD, -600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 29, 33), hnsecs(274))); |
| testST(beforeAD, -36_000_000_000L, SysTime(DateTime(1999, 7, 6, 11, 30, 33), hnsecs(274))); |
| |
| // Test B.C. |
| auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(274)); |
| testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(274))); |
| testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(275))); |
| testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(276))); |
| testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(284))); |
| testST(beforeBC, 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(374))); |
| testST(beforeBC, 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(999))); |
| testST(beforeBC, 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1000))); |
| testST(beforeBC, 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1274))); |
| testST(beforeBC, 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1275))); |
| testST(beforeBC, 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(2274))); |
| testST(beforeBC, 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(26_999))); |
| testST(beforeBC, 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(27_000))); |
| testST(beforeBC, 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(27_001))); |
| testST(beforeBC, 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_766_999))); |
| testST(beforeBC, 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_767_000))); |
| testST(beforeBC, 1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_000_274))); |
| testST(beforeBC, 60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 39), hnsecs(274))); |
| testST(beforeBC, 3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 36, 33), hnsecs(274))); |
| testST(beforeBC, 600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), hnsecs(274))); |
| testST(beforeBC, 36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), hnsecs(274))); |
| |
| testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(273))); |
| testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(272))); |
| testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(264))); |
| testST(beforeBC, -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(174))); |
| testST(beforeBC, -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33))); |
| testST(beforeBC, -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_999))); |
| testST(beforeBC, -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_274))); |
| testST(beforeBC, -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_273))); |
| testST(beforeBC, -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_998_274))); |
| testST(beforeBC, -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_967_000))); |
| testST(beforeBC, -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_966_999))); |
| testST(beforeBC, -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(8_167_000))); |
| testST(beforeBC, -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(8_166_999))); |
| testST(beforeBC, -1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_000_274))); |
| testST(beforeBC, -60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 27), hnsecs(274))); |
| testST(beforeBC, -3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 24, 33), hnsecs(274))); |
| testST(beforeBC, -600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), hnsecs(274))); |
| testST(beforeBC, -36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), hnsecs(274))); |
| |
| // Test Both |
| auto beforeBoth1 = SysTime(DateTime(1, 1, 1, 0, 0, 0)); |
| testST(beforeBoth1, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1))); |
| testST(beforeBoth1, 0, SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| testST(beforeBoth1, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999))); |
| testST(beforeBoth1, -2, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_998))); |
| testST(beforeBoth1, -1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_000))); |
| testST(beforeBoth1, -2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_998_000))); |
| testST(beforeBoth1, -2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_997_445))); |
| testST(beforeBoth1, -1_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_000_000))); |
| testST(beforeBoth1, -2_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(8_000_000))); |
| testST(beforeBoth1, -2_333_333, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(7_666_667))); |
| testST(beforeBoth1, -10_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59))); |
| testST(beforeBoth1, -20_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 58))); |
| testST(beforeBoth1, -20_888_888, SysTime(DateTime(0, 12, 31, 23, 59, 57), hnsecs(9_111_112))); |
| |
| auto beforeBoth2 = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)); |
| testST(beforeBoth2, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_998))); |
| testST(beforeBoth2, 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999))); |
| testST(beforeBoth2, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| testST(beforeBoth2, 2, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1))); |
| testST(beforeBoth2, 1000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(999))); |
| testST(beforeBoth2, 2000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1999))); |
| testST(beforeBoth2, 2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(2554))); |
| testST(beforeBoth2, 1_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(999_999))); |
| testST(beforeBoth2, 2_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1_999_999))); |
| testST(beforeBoth2, 2_333_333, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(2_333_332))); |
| testST(beforeBoth2, 10_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(9_999_999))); |
| testST(beforeBoth2, 20_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 1), hnsecs(9_999_999))); |
| testST(beforeBoth2, 20_888_888, SysTime(DateTime(1, 1, 1, 0, 0, 2), hnsecs(888_887))); |
| |
| auto duration = dur!"seconds"(12); |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(cst + duration == SysTime(DateTime(1999, 7, 6, 12, 30, 45))); |
| //assert(ist + duration == SysTime(DateTime(1999, 7, 6, 12, 30, 45))); |
| assert(cst - duration == SysTime(DateTime(1999, 7, 6, 12, 30, 21))); |
| //assert(ist - duration == SysTime(DateTime(1999, 7, 6, 12, 30, 21))); |
| } |
| |
| |
| /++ |
| Gives the result of adding or subtracting a $(REF Duration, core,time) from |
| this $(LREF SysTime), as well as assigning the result to this |
| $(LREF SysTime). |
| |
| The legal types of arithmetic for $(LREF SysTime) using this operator are |
| |
| $(BOOKTABLE, |
| $(TR $(TD SysTime) $(TD +) $(TD Duration) $(TD -->) $(TD SysTime)) |
| $(TR $(TD SysTime) $(TD -) $(TD Duration) $(TD -->) $(TD SysTime)) |
| ) |
| |
| Params: |
| duration = The $(REF Duration, core,time) to add to or subtract from |
| this $(LREF SysTime). |
| +/ |
| ref SysTime opOpAssign(string op)(Duration duration) @safe pure nothrow |
| if (op == "+" || op == "-") |
| { |
| immutable hnsecs = duration.total!"hnsecs"; |
| mixin("_stdTime " ~ op ~ "= hnsecs;"); |
| return this; |
| } |
| |
| @safe unittest |
| { |
| auto before = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(before + dur!"weeks"(7) == SysTime(DateTime(1999, 8, 24, 12, 30, 33))); |
| assert(before + dur!"weeks"(-7) == SysTime(DateTime(1999, 5, 18, 12, 30, 33))); |
| assert(before + dur!"days"(7) == SysTime(DateTime(1999, 7, 13, 12, 30, 33))); |
| assert(before + dur!"days"(-7) == SysTime(DateTime(1999, 6, 29, 12, 30, 33))); |
| |
| assert(before + dur!"hours"(7) == SysTime(DateTime(1999, 7, 6, 19, 30, 33))); |
| assert(before + dur!"hours"(-7) == SysTime(DateTime(1999, 7, 6, 5, 30, 33))); |
| assert(before + dur!"minutes"(7) == SysTime(DateTime(1999, 7, 6, 12, 37, 33))); |
| assert(before + dur!"minutes"(-7) == SysTime(DateTime(1999, 7, 6, 12, 23, 33))); |
| assert(before + dur!"seconds"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 40))); |
| assert(before + dur!"seconds"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 26))); |
| assert(before + dur!"msecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(7))); |
| assert(before + dur!"msecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), msecs(993))); |
| assert(before + dur!"usecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(7))); |
| assert(before + dur!"usecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), usecs(999_993))); |
| assert(before + dur!"hnsecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(7))); |
| assert(before + dur!"hnsecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_993))); |
| |
| assert(before - dur!"weeks"(-7) == SysTime(DateTime(1999, 8, 24, 12, 30, 33))); |
| assert(before - dur!"weeks"(7) == SysTime(DateTime(1999, 5, 18, 12, 30, 33))); |
| assert(before - dur!"days"(-7) == SysTime(DateTime(1999, 7, 13, 12, 30, 33))); |
| assert(before - dur!"days"(7) == SysTime(DateTime(1999, 6, 29, 12, 30, 33))); |
| |
| assert(before - dur!"hours"(-7) == SysTime(DateTime(1999, 7, 6, 19, 30, 33))); |
| assert(before - dur!"hours"(7) == SysTime(DateTime(1999, 7, 6, 5, 30, 33))); |
| assert(before - dur!"minutes"(-7) == SysTime(DateTime(1999, 7, 6, 12, 37, 33))); |
| assert(before - dur!"minutes"(7) == SysTime(DateTime(1999, 7, 6, 12, 23, 33))); |
| assert(before - dur!"seconds"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 40))); |
| assert(before - dur!"seconds"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 26))); |
| assert(before - dur!"msecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), msecs(7))); |
| assert(before - dur!"msecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), msecs(993))); |
| assert(before - dur!"usecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), usecs(7))); |
| assert(before - dur!"usecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), usecs(999_993))); |
| assert(before - dur!"hnsecs"(-7) == SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(7))); |
| assert(before - dur!"hnsecs"(7) == SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_993))); |
| |
| static void testST(SysTime orig, long hnsecs, in SysTime expected, size_t line = __LINE__) |
| { |
| auto r = orig += dur!"hnsecs"(hnsecs); |
| if (orig != expected) |
| throw new AssertError(format("Failed 1. actual [%s] != expected [%s]", orig, expected), __FILE__, line); |
| if (r != expected) |
| throw new AssertError(format("Failed 2. actual [%s] != expected [%s]", r, expected), __FILE__, line); |
| } |
| |
| // Test A.D. |
| auto beforeAD = SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(274)); |
| testST(beforeAD, 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(274))); |
| testST(beforeAD, 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(275))); |
| testST(beforeAD, 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(276))); |
| testST(beforeAD, 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(284))); |
| testST(beforeAD, 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(374))); |
| testST(beforeAD, 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(999))); |
| testST(beforeAD, 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1000))); |
| testST(beforeAD, 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1274))); |
| testST(beforeAD, 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1275))); |
| testST(beforeAD, 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(2274))); |
| testST(beforeAD, 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(26_999))); |
| testST(beforeAD, 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(27_000))); |
| testST(beforeAD, 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(27_001))); |
| testST(beforeAD, 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_766_999))); |
| testST(beforeAD, 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_767_000))); |
| testST(beforeAD, 1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(1_000_274))); |
| testST(beforeAD, 60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 39), hnsecs(274))); |
| testST(beforeAD, 3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 36, 33), hnsecs(274))); |
| testST(beforeAD, 600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 31, 33), hnsecs(274))); |
| testST(beforeAD, 36_000_000_000L, SysTime(DateTime(1999, 7, 6, 13, 30, 33), hnsecs(274))); |
| |
| testST(beforeAD, -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(273))); |
| testST(beforeAD, -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(272))); |
| testST(beforeAD, -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(264))); |
| testST(beforeAD, -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), hnsecs(174))); |
| testST(beforeAD, -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33))); |
| testST(beforeAD, -275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_999))); |
| testST(beforeAD, -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_274))); |
| testST(beforeAD, -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_999_273))); |
| testST(beforeAD, -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_998_274))); |
| testST(beforeAD, -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_967_000))); |
| testST(beforeAD, -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_966_999))); |
| testST(beforeAD, -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(8_167_000))); |
| testST(beforeAD, -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(8_166_999))); |
| testST(beforeAD, -1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), hnsecs(9_000_274))); |
| testST(beforeAD, -60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 27), hnsecs(274))); |
| testST(beforeAD, -3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 24, 33), hnsecs(274))); |
| testST(beforeAD, -600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 29, 33), hnsecs(274))); |
| testST(beforeAD, -36_000_000_000L, SysTime(DateTime(1999, 7, 6, 11, 30, 33), hnsecs(274))); |
| |
| // Test B.C. |
| auto beforeBC = SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(274)); |
| testST(beforeBC, 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(274))); |
| testST(beforeBC, 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(275))); |
| testST(beforeBC, 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(276))); |
| testST(beforeBC, 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(284))); |
| testST(beforeBC, 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(374))); |
| testST(beforeBC, 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(999))); |
| testST(beforeBC, 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1000))); |
| testST(beforeBC, 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1274))); |
| testST(beforeBC, 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1275))); |
| testST(beforeBC, 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(2274))); |
| testST(beforeBC, 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(26_999))); |
| testST(beforeBC, 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(27_000))); |
| testST(beforeBC, 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(27_001))); |
| testST(beforeBC, 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_766_999))); |
| testST(beforeBC, 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_767_000))); |
| testST(beforeBC, 1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(1_000_274))); |
| testST(beforeBC, 60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 39), hnsecs(274))); |
| testST(beforeBC, 3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 36, 33), hnsecs(274))); |
| testST(beforeBC, 600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), hnsecs(274))); |
| testST(beforeBC, 36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), hnsecs(274))); |
| |
| testST(beforeBC, -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(273))); |
| testST(beforeBC, -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(272))); |
| testST(beforeBC, -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(264))); |
| testST(beforeBC, -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), hnsecs(174))); |
| testST(beforeBC, -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33))); |
| testST(beforeBC, -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_999))); |
| testST(beforeBC, -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_274))); |
| testST(beforeBC, -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_999_273))); |
| testST(beforeBC, -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_998_274))); |
| testST(beforeBC, -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_967_000))); |
| testST(beforeBC, -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_966_999))); |
| testST(beforeBC, -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(8_167_000))); |
| testST(beforeBC, -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(8_166_999))); |
| testST(beforeBC, -1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), hnsecs(9_000_274))); |
| testST(beforeBC, -60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 27), hnsecs(274))); |
| testST(beforeBC, -3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 24, 33), hnsecs(274))); |
| testST(beforeBC, -600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), hnsecs(274))); |
| testST(beforeBC, -36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), hnsecs(274))); |
| |
| // Test Both |
| auto beforeBoth1 = SysTime(DateTime(1, 1, 1, 0, 0, 0)); |
| testST(beforeBoth1, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1))); |
| testST(beforeBoth1, 0, SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| testST(beforeBoth1, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999))); |
| testST(beforeBoth1, -2, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_998))); |
| testST(beforeBoth1, -1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_000))); |
| testST(beforeBoth1, -2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_998_000))); |
| testST(beforeBoth1, -2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_997_445))); |
| testST(beforeBoth1, -1_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_000_000))); |
| testST(beforeBoth1, -2_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(8_000_000))); |
| testST(beforeBoth1, -2_333_333, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(7_666_667))); |
| testST(beforeBoth1, -10_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59))); |
| testST(beforeBoth1, -20_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 58))); |
| testST(beforeBoth1, -20_888_888, SysTime(DateTime(0, 12, 31, 23, 59, 57), hnsecs(9_111_112))); |
| |
| auto beforeBoth2 = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)); |
| testST(beforeBoth2, -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_998))); |
| testST(beforeBoth2, 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999))); |
| testST(beforeBoth2, 1, SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| testST(beforeBoth2, 2, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1))); |
| testST(beforeBoth2, 1000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(999))); |
| testST(beforeBoth2, 2000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1999))); |
| testST(beforeBoth2, 2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(2554))); |
| testST(beforeBoth2, 1_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(999_999))); |
| testST(beforeBoth2, 2_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1_999_999))); |
| testST(beforeBoth2, 2_333_333, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(2_333_332))); |
| testST(beforeBoth2, 10_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(9_999_999))); |
| testST(beforeBoth2, 20_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 1), hnsecs(9_999_999))); |
| testST(beforeBoth2, 20_888_888, SysTime(DateTime(1, 1, 1, 0, 0, 2), hnsecs(888_887))); |
| |
| { |
| auto st = SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)); |
| (st += dur!"hnsecs"(52)) += dur!"seconds"(-907); |
| assert(st == SysTime(DateTime(0, 12, 31, 23, 44, 53), hnsecs(51))); |
| } |
| |
| auto duration = dur!"seconds"(12); |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| static assert(!__traits(compiles, cst += duration)); |
| //static assert(!__traits(compiles, ist += duration)); |
| static assert(!__traits(compiles, cst -= duration)); |
| //static assert(!__traits(compiles, ist -= duration)); |
| } |
| |
| |
| /++ |
| Gives the difference between two $(LREF SysTime)s. |
| |
| The legal types of arithmetic for $(LREF SysTime) using this operator |
| are |
| |
| $(BOOKTABLE, |
| $(TR $(TD SysTime) $(TD -) $(TD SysTime) $(TD -->) $(TD duration)) |
| ) |
| +/ |
| Duration opBinary(string op)(in SysTime rhs) @safe const pure nothrow |
| if (op == "-") |
| { |
| return dur!"hnsecs"(_stdTime - rhs._stdTime); |
| } |
| |
| @safe unittest |
| { |
| assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1998, 7, 6, 12, 30, 33)) == |
| dur!"seconds"(31_536_000)); |
| assert(SysTime(DateTime(1998, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) == |
| dur!"seconds"(-31_536_000)); |
| |
| assert(SysTime(DateTime(1999, 8, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) == |
| dur!"seconds"(26_78_400)); |
| assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 8, 6, 12, 30, 33)) == |
| dur!"seconds"(-26_78_400)); |
| |
| assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 5, 12, 30, 33)) == |
| dur!"seconds"(86_400)); |
| assert(SysTime(DateTime(1999, 7, 5, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) == |
| dur!"seconds"(-86_400)); |
| |
| assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 11, 30, 33)) == |
| dur!"seconds"(3600)); |
| assert(SysTime(DateTime(1999, 7, 6, 11, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) == |
| dur!"seconds"(-3600)); |
| |
| assert(SysTime(DateTime(1999, 7, 6, 12, 31, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) == |
| dur!"seconds"(60)); |
| assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 31, 33)) == |
| dur!"seconds"(-60)); |
| |
| assert(SysTime(DateTime(1999, 7, 6, 12, 30, 34)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)) == |
| dur!"seconds"(1)); |
| assert(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 34)) == |
| dur!"seconds"(-1)); |
| |
| { |
| auto dt = DateTime(1999, 7, 6, 12, 30, 33); |
| assert(SysTime(dt, msecs(532)) - SysTime(dt) == msecs(532)); |
| assert(SysTime(dt) - SysTime(dt, msecs(532)) == msecs(-532)); |
| |
| assert(SysTime(dt, usecs(333_347)) - SysTime(dt) == usecs(333_347)); |
| assert(SysTime(dt) - SysTime(dt, usecs(333_347)) == usecs(-333_347)); |
| |
| assert(SysTime(dt, hnsecs(1_234_567)) - SysTime(dt) == hnsecs(1_234_567)); |
| assert(SysTime(dt) - SysTime(dt, hnsecs(1_234_567)) == hnsecs(-1_234_567)); |
| } |
| |
| assert(SysTime(DateTime(1, 1, 1, 12, 30, 33)) - SysTime(DateTime(1, 1, 1, 0, 0, 0)) == dur!"seconds"(45033)); |
| assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)) - SysTime(DateTime(1, 1, 1, 12, 30, 33)) == dur!"seconds"(-45033)); |
| assert(SysTime(DateTime(0, 12, 31, 12, 30, 33)) - SysTime(DateTime(1, 1, 1, 0, 0, 0)) == dur!"seconds"(-41367)); |
| assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)) - SysTime(DateTime(0, 12, 31, 12, 30, 33)) == dur!"seconds"(41367)); |
| |
| assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)) - SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)) == |
| dur!"hnsecs"(1)); |
| assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)) - SysTime(DateTime(1, 1, 1, 0, 0, 0)) == |
| dur!"hnsecs"(-1)); |
| |
| version (Posix) |
| immutable tz = PosixTimeZone.getTimeZone("America/Los_Angeles"); |
| else version (Windows) |
| immutable tz = WindowsTimeZone.getTimeZone("Pacific Standard Time"); |
| |
| { |
| auto dt = DateTime(2011, 1, 13, 8, 17, 2); |
| auto d = msecs(296); |
| assert(SysTime(dt, d, tz) - SysTime(dt, d, tz) == Duration.zero); |
| assert(SysTime(dt, d, tz) - SysTime(dt, d, UTC()) == hours(8)); |
| assert(SysTime(dt, d, UTC()) - SysTime(dt, d, tz) == hours(-8)); |
| } |
| |
| auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(st - st == Duration.zero); |
| assert(cst - st == Duration.zero); |
| //assert(ist - st == Duration.zero); |
| |
| assert(st - cst == Duration.zero); |
| assert(cst - cst == Duration.zero); |
| //assert(ist - cst == Duration.zero); |
| |
| //assert(st - ist == Duration.zero); |
| //assert(cst - ist == Duration.zero); |
| //assert(ist - ist == Duration.zero); |
| } |
| |
| |
| /++ |
| Returns the difference between the two $(LREF SysTime)s in months. |
| |
| To get the difference in years, subtract the year property |
| of two $(LREF SysTime)s. To get the difference in days or weeks, |
| subtract the $(LREF SysTime)s themselves and use the |
| $(REF Duration, core,time) that results. Because converting between |
| months and smaller units requires a specific date (which |
| $(REF Duration, core,time)s don't have), getting the difference in |
| months requires some math using both the year and month properties, so |
| this is a convenience function for getting the difference in months. |
| |
| Note that the number of days in the months or how far into the month |
| either date is is irrelevant. It is the difference in the month property |
| combined with the difference in years * 12. So, for instance, |
| December 31st and January 1st are one month apart just as December 1st |
| and January 31st are one month apart. |
| |
| Params: |
| rhs = The $(LREF SysTime) to subtract from this one. |
| +/ |
| int diffMonths(in SysTime rhs) @safe const nothrow |
| { |
| return (cast(Date) this).diffMonths(cast(Date) rhs); |
| } |
| |
| /// |
| @safe unittest |
| { |
| import std.datetime.date : Date; |
| |
| assert(SysTime(Date(1999, 2, 1)).diffMonths( |
| SysTime(Date(1999, 1, 31))) == 1); |
| |
| assert(SysTime(Date(1999, 1, 31)).diffMonths( |
| SysTime(Date(1999, 2, 1))) == -1); |
| |
| assert(SysTime(Date(1999, 3, 1)).diffMonths( |
| SysTime(Date(1999, 1, 1))) == 2); |
| |
| assert(SysTime(Date(1999, 1, 1)).diffMonths( |
| SysTime(Date(1999, 3, 31))) == -2); |
| } |
| |
| @safe unittest |
| { |
| auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(st.diffMonths(st) == 0); |
| assert(cst.diffMonths(st) == 0); |
| //assert(ist.diffMonths(st) == 0); |
| |
| assert(st.diffMonths(cst) == 0); |
| assert(cst.diffMonths(cst) == 0); |
| //assert(ist.diffMonths(cst) == 0); |
| |
| //assert(st.diffMonths(ist) == 0); |
| //assert(cst.diffMonths(ist) == 0); |
| //assert(ist.diffMonths(ist) == 0); |
| } |
| |
| |
| /++ |
| Whether this $(LREF SysTime) is in a leap year. |
| +/ |
| @property bool isLeapYear() @safe const nothrow |
| { |
| return (cast(Date) this).isLeapYear; |
| } |
| |
| @safe unittest |
| { |
| auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(!st.isLeapYear); |
| assert(!cst.isLeapYear); |
| //assert(!ist.isLeapYear); |
| } |
| |
| |
| /++ |
| Day of the week this $(LREF SysTime) is on. |
| +/ |
| @property DayOfWeek dayOfWeek() @safe const nothrow |
| { |
| return getDayOfWeek(dayOfGregorianCal); |
| } |
| |
| @safe unittest |
| { |
| auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(st.dayOfWeek == DayOfWeek.tue); |
| assert(cst.dayOfWeek == DayOfWeek.tue); |
| //assert(ist.dayOfWeek == DayOfWeek.tue); |
| } |
| |
| |
| /++ |
| Day of the year this $(LREF SysTime) is on. |
| +/ |
| @property ushort dayOfYear() @safe const nothrow |
| { |
| return (cast(Date) this).dayOfYear; |
| } |
| |
| /// |
| @safe unittest |
| { |
| import std.datetime.date : DateTime; |
| |
| assert(SysTime(DateTime(1999, 1, 1, 12, 22, 7)).dayOfYear == 1); |
| assert(SysTime(DateTime(1999, 12, 31, 7, 2, 59)).dayOfYear == 365); |
| assert(SysTime(DateTime(2000, 12, 31, 21, 20, 0)).dayOfYear == 366); |
| } |
| |
| @safe unittest |
| { |
| auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(st.dayOfYear == 187); |
| assert(cst.dayOfYear == 187); |
| //assert(ist.dayOfYear == 187); |
| } |
| |
| |
| /++ |
| Day of the year. |
| |
| Params: |
| day = The day of the year to set which day of the year this |
| $(LREF SysTime) is on. |
| +/ |
| @property void dayOfYear(int day) @safe |
| { |
| immutable hnsecs = adjTime; |
| immutable days = convert!("hnsecs", "days")(hnsecs); |
| immutable theRest = hnsecs - convert!("days", "hnsecs")(days); |
| |
| auto date = Date(cast(int) days); |
| date.dayOfYear = day; |
| |
| immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1); |
| |
| adjTime = newDaysHNSecs + theRest; |
| } |
| |
| @safe unittest |
| { |
| auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| st.dayOfYear = 12; |
| assert(st.dayOfYear == 12); |
| static assert(!__traits(compiles, cst.dayOfYear = 12)); |
| //static assert(!__traits(compiles, ist.dayOfYear = 12)); |
| } |
| |
| |
| /++ |
| The Xth day of the Gregorian Calendar that this $(LREF SysTime) is on. |
| +/ |
| @property int dayOfGregorianCal() @safe const nothrow |
| { |
| immutable adjustedTime = adjTime; |
| |
| // We have to add one because 0 would be midnight, January 1st, 1 A.D., |
| // which would be the 1st day of the Gregorian Calendar, not the 0th. So, |
| // simply casting to days is one day off. |
| if (adjustedTime > 0) |
| return cast(int) getUnitsFromHNSecs!"days"(adjustedTime) + 1; |
| |
| long hnsecs = adjustedTime; |
| immutable days = cast(int) splitUnitsFromHNSecs!"days"(hnsecs); |
| |
| return hnsecs == 0 ? days + 1 : days; |
| } |
| |
| /// |
| @safe unittest |
| { |
| import std.datetime.date : DateTime; |
| |
| assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).dayOfGregorianCal == 1); |
| assert(SysTime(DateTime(1, 12, 31, 23, 59, 59)).dayOfGregorianCal == 365); |
| assert(SysTime(DateTime(2, 1, 1, 2, 2, 2)).dayOfGregorianCal == 366); |
| |
| assert(SysTime(DateTime(0, 12, 31, 7, 7, 7)).dayOfGregorianCal == 0); |
| assert(SysTime(DateTime(0, 1, 1, 19, 30, 0)).dayOfGregorianCal == -365); |
| assert(SysTime(DateTime(-1, 12, 31, 4, 7, 0)).dayOfGregorianCal == -366); |
| |
| assert(SysTime(DateTime(2000, 1, 1, 9, 30, 20)).dayOfGregorianCal == 730_120); |
| assert(SysTime(DateTime(2010, 12, 31, 15, 45, 50)).dayOfGregorianCal == 734_137); |
| } |
| |
| @safe unittest |
| { |
| // Test A.D. |
| assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).dayOfGregorianCal == 1); |
| assert(SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)).dayOfGregorianCal == 1); |
| assert(SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)).dayOfGregorianCal == 1); |
| |
| assert(SysTime(DateTime(1, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 1); |
| assert(SysTime(DateTime(1, 1, 2, 12, 2, 9), msecs(212)).dayOfGregorianCal == 2); |
| assert(SysTime(DateTime(1, 2, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 32); |
| assert(SysTime(DateTime(2, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 366); |
| assert(SysTime(DateTime(3, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 731); |
| assert(SysTime(DateTime(4, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 1096); |
| assert(SysTime(DateTime(5, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 1462); |
| assert(SysTime(DateTime(50, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 17_898); |
| assert(SysTime(DateTime(97, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 35_065); |
| assert(SysTime(DateTime(100, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 36_160); |
| assert(SysTime(DateTime(101, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 36_525); |
| assert(SysTime(DateTime(105, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 37_986); |
| assert(SysTime(DateTime(200, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 72_684); |
| assert(SysTime(DateTime(201, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 73_049); |
| assert(SysTime(DateTime(300, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 109_208); |
| assert(SysTime(DateTime(301, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 109_573); |
| assert(SysTime(DateTime(400, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 145_732); |
| assert(SysTime(DateTime(401, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 146_098); |
| assert(SysTime(DateTime(500, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 182_257); |
| assert(SysTime(DateTime(501, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 182_622); |
| assert(SysTime(DateTime(1000, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 364_878); |
| assert(SysTime(DateTime(1001, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 365_243); |
| assert(SysTime(DateTime(1600, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 584_023); |
| assert(SysTime(DateTime(1601, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 584_389); |
| assert(SysTime(DateTime(1900, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 693_596); |
| assert(SysTime(DateTime(1901, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 693_961); |
| assert(SysTime(DateTime(1945, 11, 12, 12, 2, 9), msecs(212)).dayOfGregorianCal == 710_347); |
| assert(SysTime(DateTime(1999, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 729_755); |
| assert(SysTime(DateTime(2000, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 730_120); |
| assert(SysTime(DateTime(2001, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == 730_486); |
| |
| assert(SysTime(DateTime(2010, 1, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_773); |
| assert(SysTime(DateTime(2010, 1, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_803); |
| assert(SysTime(DateTime(2010, 2, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_804); |
| assert(SysTime(DateTime(2010, 2, 28, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_831); |
| assert(SysTime(DateTime(2010, 3, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_832); |
| assert(SysTime(DateTime(2010, 3, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_862); |
| assert(SysTime(DateTime(2010, 4, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_863); |
| assert(SysTime(DateTime(2010, 4, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_892); |
| assert(SysTime(DateTime(2010, 5, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_893); |
| assert(SysTime(DateTime(2010, 5, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_923); |
| assert(SysTime(DateTime(2010, 6, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_924); |
| assert(SysTime(DateTime(2010, 6, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_953); |
| assert(SysTime(DateTime(2010, 7, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_954); |
| assert(SysTime(DateTime(2010, 7, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_984); |
| assert(SysTime(DateTime(2010, 8, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 733_985); |
| assert(SysTime(DateTime(2010, 8, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_015); |
| assert(SysTime(DateTime(2010, 9, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_016); |
| assert(SysTime(DateTime(2010, 9, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_045); |
| assert(SysTime(DateTime(2010, 10, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_046); |
| assert(SysTime(DateTime(2010, 10, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_076); |
| assert(SysTime(DateTime(2010, 11, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_077); |
| assert(SysTime(DateTime(2010, 11, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_106); |
| assert(SysTime(DateTime(2010, 12, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_107); |
| assert(SysTime(DateTime(2010, 12, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == 734_137); |
| |
| assert(SysTime(DateTime(2012, 2, 1, 0, 0, 0)).dayOfGregorianCal == 734_534); |
| assert(SysTime(DateTime(2012, 2, 28, 0, 0, 0)).dayOfGregorianCal == 734_561); |
| assert(SysTime(DateTime(2012, 2, 29, 0, 0, 0)).dayOfGregorianCal == 734_562); |
| assert(SysTime(DateTime(2012, 3, 1, 0, 0, 0)).dayOfGregorianCal == 734_563); |
| |
| // Test B.C. |
| assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999)).dayOfGregorianCal == 0); |
| assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_998)).dayOfGregorianCal == 0); |
| assert(SysTime(DateTime(0, 12, 31, 23, 59, 59)).dayOfGregorianCal == 0); |
| assert(SysTime(DateTime(0, 12, 31, 0, 0, 0), hnsecs(1)).dayOfGregorianCal == 0); |
| assert(SysTime(DateTime(0, 12, 31, 0, 0, 0)).dayOfGregorianCal == 0); |
| |
| assert(SysTime(DateTime(-1, 12, 31, 23, 59, 59), hnsecs(9_999_999)).dayOfGregorianCal == -366); |
| assert(SysTime(DateTime(-1, 12, 31, 23, 59, 59), hnsecs(9_999_998)).dayOfGregorianCal == -366); |
| assert(SysTime(DateTime(-1, 12, 31, 23, 59, 59)).dayOfGregorianCal == -366); |
| assert(SysTime(DateTime(-1, 12, 31, 0, 0, 0)).dayOfGregorianCal == -366); |
| |
| assert(SysTime(DateTime(0, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == 0); |
| assert(SysTime(DateTime(0, 12, 30, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1); |
| assert(SysTime(DateTime(0, 12, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -30); |
| assert(SysTime(DateTime(0, 11, 30, 12, 2, 9), msecs(212)).dayOfGregorianCal == -31); |
| |
| assert(SysTime(DateTime(-1, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -366); |
| assert(SysTime(DateTime(-1, 12, 30, 12, 2, 9), msecs(212)).dayOfGregorianCal == -367); |
| assert(SysTime(DateTime(-1, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -730); |
| assert(SysTime(DateTime(-2, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -731); |
| assert(SysTime(DateTime(-2, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1095); |
| assert(SysTime(DateTime(-3, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1096); |
| assert(SysTime(DateTime(-3, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1460); |
| assert(SysTime(DateTime(-4, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1461); |
| assert(SysTime(DateTime(-4, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1826); |
| assert(SysTime(DateTime(-5, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -1827); |
| assert(SysTime(DateTime(-5, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -2191); |
| assert(SysTime(DateTime(-9, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -3652); |
| |
| assert(SysTime(DateTime(-49, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -18_262); |
| assert(SysTime(DateTime(-50, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -18_627); |
| assert(SysTime(DateTime(-97, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -35_794); |
| assert(SysTime(DateTime(-99, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -36_160); |
| assert(SysTime(DateTime(-99, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -36_524); |
| assert(SysTime(DateTime(-100, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -36_889); |
| assert(SysTime(DateTime(-101, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -37_254); |
| assert(SysTime(DateTime(-105, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -38_715); |
| assert(SysTime(DateTime(-200, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -73_413); |
| assert(SysTime(DateTime(-201, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -73_778); |
| assert(SysTime(DateTime(-300, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -109_937); |
| assert(SysTime(DateTime(-301, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -110_302); |
| assert(SysTime(DateTime(-400, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -146_097); |
| assert(SysTime(DateTime(-400, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -146_462); |
| assert(SysTime(DateTime(-401, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -146_827); |
| assert(SysTime(DateTime(-499, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -182_621); |
| assert(SysTime(DateTime(-500, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -182_986); |
| assert(SysTime(DateTime(-501, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -183_351); |
| assert(SysTime(DateTime(-1000, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -365_607); |
| assert(SysTime(DateTime(-1001, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -365_972); |
| assert(SysTime(DateTime(-1599, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -584_387); |
| assert(SysTime(DateTime(-1600, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -584_388); |
| assert(SysTime(DateTime(-1600, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -584_753); |
| assert(SysTime(DateTime(-1601, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -585_118); |
| assert(SysTime(DateTime(-1900, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -694_325); |
| assert(SysTime(DateTime(-1901, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -694_690); |
| assert(SysTime(DateTime(-1999, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -730_484); |
| assert(SysTime(DateTime(-2000, 12, 31, 12, 2, 9), msecs(212)).dayOfGregorianCal == -730_485); |
| assert(SysTime(DateTime(-2000, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -730_850); |
| assert(SysTime(DateTime(-2001, 1, 1, 12, 2, 9), msecs(212)).dayOfGregorianCal == -731_215); |
| |
| assert(SysTime(DateTime(-2010, 1, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_502); |
| assert(SysTime(DateTime(-2010, 1, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_472); |
| assert(SysTime(DateTime(-2010, 2, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_471); |
| assert(SysTime(DateTime(-2010, 2, 28, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_444); |
| assert(SysTime(DateTime(-2010, 3, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_443); |
| assert(SysTime(DateTime(-2010, 3, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_413); |
| assert(SysTime(DateTime(-2010, 4, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_412); |
| assert(SysTime(DateTime(-2010, 4, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_383); |
| assert(SysTime(DateTime(-2010, 5, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_382); |
| assert(SysTime(DateTime(-2010, 5, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_352); |
| assert(SysTime(DateTime(-2010, 6, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_351); |
| assert(SysTime(DateTime(-2010, 6, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_322); |
| assert(SysTime(DateTime(-2010, 7, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_321); |
| assert(SysTime(DateTime(-2010, 7, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_291); |
| assert(SysTime(DateTime(-2010, 8, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_290); |
| assert(SysTime(DateTime(-2010, 8, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_260); |
| assert(SysTime(DateTime(-2010, 9, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_259); |
| assert(SysTime(DateTime(-2010, 9, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_230); |
| assert(SysTime(DateTime(-2010, 10, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_229); |
| assert(SysTime(DateTime(-2010, 10, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_199); |
| assert(SysTime(DateTime(-2010, 11, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_198); |
| assert(SysTime(DateTime(-2010, 11, 30, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_169); |
| assert(SysTime(DateTime(-2010, 12, 1, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_168); |
| assert(SysTime(DateTime(-2010, 12, 31, 23, 59, 59), msecs(999)).dayOfGregorianCal == -734_138); |
| |
| assert(SysTime(DateTime(-2012, 2, 1, 0, 0, 0)).dayOfGregorianCal == -735_202); |
| assert(SysTime(DateTime(-2012, 2, 28, 0, 0, 0)).dayOfGregorianCal == -735_175); |
| assert(SysTime(DateTime(-2012, 2, 29, 0, 0, 0)).dayOfGregorianCal == -735_174); |
| assert(SysTime(DateTime(-2012, 3, 1, 0, 0, 0)).dayOfGregorianCal == -735_173); |
| |
| // Start of Hebrew Calendar |
| assert(SysTime(DateTime(-3760, 9, 7, 0, 0, 0)).dayOfGregorianCal == -1_373_427); |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(cst.dayOfGregorianCal == 729_941); |
| //assert(ist.dayOfGregorianCal == 729_941); |
| } |
| |
| |
| // Test that the logic for the day of the Gregorian Calendar is consistent |
| // between Date and SysTime. |
| @safe unittest |
| { |
| void test(Date date, SysTime st, size_t line = __LINE__) |
| { |
| if (date.dayOfGregorianCal != st.dayOfGregorianCal) |
| { |
| throw new AssertError(format("Date [%s] SysTime [%s]", date.dayOfGregorianCal, st.dayOfGregorianCal), |
| __FILE__, line); |
| } |
| } |
| |
| // Test A.D. |
| test(Date(1, 1, 1), SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| test(Date(1, 1, 2), SysTime(DateTime(1, 1, 2, 0, 0, 0), hnsecs(500))); |
| test(Date(1, 2, 1), SysTime(DateTime(1, 2, 1, 0, 0, 0), hnsecs(50_000))); |
| test(Date(2, 1, 1), SysTime(DateTime(2, 1, 1, 0, 0, 0), hnsecs(9_999_999))); |
| test(Date(3, 1, 1), SysTime(DateTime(3, 1, 1, 12, 13, 14))); |
| test(Date(4, 1, 1), SysTime(DateTime(4, 1, 1, 12, 13, 14), hnsecs(500))); |
| test(Date(5, 1, 1), SysTime(DateTime(5, 1, 1, 12, 13, 14), hnsecs(50_000))); |
| test(Date(50, 1, 1), SysTime(DateTime(50, 1, 1, 12, 13, 14), hnsecs(9_999_999))); |
| test(Date(97, 1, 1), SysTime(DateTime(97, 1, 1, 23, 59, 59))); |
| test(Date(100, 1, 1), SysTime(DateTime(100, 1, 1, 23, 59, 59), hnsecs(500))); |
| test(Date(101, 1, 1), SysTime(DateTime(101, 1, 1, 23, 59, 59), hnsecs(50_000))); |
| test(Date(105, 1, 1), SysTime(DateTime(105, 1, 1, 23, 59, 59), hnsecs(9_999_999))); |
| test(Date(200, 1, 1), SysTime(DateTime(200, 1, 1, 0, 0, 0))); |
| test(Date(201, 1, 1), SysTime(DateTime(201, 1, 1, 0, 0, 0), hnsecs(500))); |
| test(Date(300, 1, 1), SysTime(DateTime(300, 1, 1, 0, 0, 0), hnsecs(50_000))); |
| test(Date(301, 1, 1), SysTime(DateTime(301, 1, 1, 0, 0, 0), hnsecs(9_999_999))); |
| test(Date(400, 1, 1), SysTime(DateTime(400, 1, 1, 12, 13, 14))); |
| test(Date(401, 1, 1), SysTime(DateTime(401, 1, 1, 12, 13, 14), hnsecs(500))); |
| test(Date(500, 1, 1), SysTime(DateTime(500, 1, 1, 12, 13, 14), hnsecs(50_000))); |
| test(Date(501, 1, 1), SysTime(DateTime(501, 1, 1, 12, 13, 14), hnsecs(9_999_999))); |
| test(Date(1000, 1, 1), SysTime(DateTime(1000, 1, 1, 23, 59, 59))); |
| test(Date(1001, 1, 1), SysTime(DateTime(1001, 1, 1, 23, 59, 59), hnsecs(500))); |
| test(Date(1600, 1, 1), SysTime(DateTime(1600, 1, 1, 23, 59, 59), hnsecs(50_000))); |
| test(Date(1601, 1, 1), SysTime(DateTime(1601, 1, 1, 23, 59, 59), hnsecs(9_999_999))); |
| test(Date(1900, 1, 1), SysTime(DateTime(1900, 1, 1, 0, 0, 0))); |
| test(Date(1901, 1, 1), SysTime(DateTime(1901, 1, 1, 0, 0, 0), hnsecs(500))); |
| test(Date(1945, 11, 12), SysTime(DateTime(1945, 11, 12, 0, 0, 0), hnsecs(50_000))); |
| test(Date(1999, 1, 1), SysTime(DateTime(1999, 1, 1, 0, 0, 0), hnsecs(9_999_999))); |
| test(Date(1999, 7, 6), SysTime(DateTime(1999, 7, 6, 12, 13, 14))); |
| test(Date(2000, 1, 1), SysTime(DateTime(2000, 1, 1, 12, 13, 14), hnsecs(500))); |
| test(Date(2001, 1, 1), SysTime(DateTime(2001, 1, 1, 12, 13, 14), hnsecs(50_000))); |
| |
| test(Date(2010, 1, 1), SysTime(DateTime(2010, 1, 1, 12, 13, 14), hnsecs(9_999_999))); |
| test(Date(2010, 1, 31), SysTime(DateTime(2010, 1, 31, 23, 0, 0))); |
| test(Date(2010, 2, 1), SysTime(DateTime(2010, 2, 1, 23, 59, 59), hnsecs(500))); |
| test(Date(2010, 2, 28), SysTime(DateTime(2010, 2, 28, 23, 59, 59), hnsecs(50_000))); |
| test(Date(2010, 3, 1), SysTime(DateTime(2010, 3, 1, 23, 59, 59), hnsecs(9_999_999))); |
| test(Date(2010, 3, 31), SysTime(DateTime(2010, 3, 31, 0, 0, 0))); |
| test(Date(2010, 4, 1), SysTime(DateTime(2010, 4, 1, 0, 0, 0), hnsecs(500))); |
| test(Date(2010, 4, 30), SysTime(DateTime(2010, 4, 30, 0, 0, 0), hnsecs(50_000))); |
| test(Date(2010, 5, 1), SysTime(DateTime(2010, 5, 1, 0, 0, 0), hnsecs(9_999_999))); |
| test(Date(2010, 5, 31), SysTime(DateTime(2010, 5, 31, 12, 13, 14))); |
| test(Date(2010, 6, 1), SysTime(DateTime(2010, 6, 1, 12, 13, 14), hnsecs(500))); |
| test(Date(2010, 6, 30), SysTime(DateTime(2010, 6, 30, 12, 13, 14), hnsecs(50_000))); |
| test(Date(2010, 7, 1), SysTime(DateTime(2010, 7, 1, 12, 13, 14), hnsecs(9_999_999))); |
| test(Date(2010, 7, 31), SysTime(DateTime(2010, 7, 31, 23, 59, 59))); |
| test(Date(2010, 8, 1), SysTime(DateTime(2010, 8, 1, 23, 59, 59), hnsecs(500))); |
| test(Date(2010, 8, 31), SysTime(DateTime(2010, 8, 31, 23, 59, 59), hnsecs(50_000))); |
| test(Date(2010, 9, 1), SysTime(DateTime(2010, 9, 1, 23, 59, 59), hnsecs(9_999_999))); |
| test(Date(2010, 9, 30), SysTime(DateTime(2010, 9, 30, 12, 0, 0))); |
| test(Date(2010, 10, 1), SysTime(DateTime(2010, 10, 1, 0, 12, 0), hnsecs(500))); |
| test(Date(2010, 10, 31), SysTime(DateTime(2010, 10, 31, 0, 0, 12), hnsecs(50_000))); |
| test(Date(2010, 11, 1), SysTime(DateTime(2010, 11, 1, 23, 0, 0), hnsecs(9_999_999))); |
| test(Date(2010, 11, 30), SysTime(DateTime(2010, 11, 30, 0, 59, 0))); |
| test(Date(2010, 12, 1), SysTime(DateTime(2010, 12, 1, 0, 0, 59), hnsecs(500))); |
| test(Date(2010, 12, 31), SysTime(DateTime(2010, 12, 31, 0, 59, 59), hnsecs(50_000))); |
| |
| test(Date(2012, 2, 1), SysTime(DateTime(2012, 2, 1, 23, 0, 59), hnsecs(9_999_999))); |
| test(Date(2012, 2, 28), SysTime(DateTime(2012, 2, 28, 23, 59, 0))); |
| test(Date(2012, 2, 29), SysTime(DateTime(2012, 2, 29, 7, 7, 7), hnsecs(7))); |
| test(Date(2012, 3, 1), SysTime(DateTime(2012, 3, 1, 7, 7, 7), hnsecs(7))); |
| |
| // Test B.C. |
| test(Date(0, 12, 31), SysTime(DateTime(0, 12, 31, 0, 0, 0))); |
| test(Date(0, 12, 30), SysTime(DateTime(0, 12, 30, 0, 0, 0), hnsecs(500))); |
| test(Date(0, 12, 1), SysTime(DateTime(0, 12, 1, 0, 0, 0), hnsecs(50_000))); |
| test(Date(0, 11, 30), SysTime(DateTime(0, 11, 30, 0, 0, 0), hnsecs(9_999_999))); |
| |
| test(Date(-1, 12, 31), SysTime(DateTime(-1, 12, 31, 12, 13, 14))); |
| test(Date(-1, 12, 30), SysTime(DateTime(-1, 12, 30, 12, 13, 14), hnsecs(500))); |
| test(Date(-1, 1, 1), SysTime(DateTime(-1, 1, 1, 12, 13, 14), hnsecs(50_000))); |
| test(Date(-2, 12, 31), SysTime(DateTime(-2, 12, 31, 12, 13, 14), hnsecs(9_999_999))); |
| test(Date(-2, 1, 1), SysTime(DateTime(-2, 1, 1, 23, 59, 59))); |
| test(Date(-3, 12, 31), SysTime(DateTime(-3, 12, 31, 23, 59, 59), hnsecs(500))); |
| test(Date(-3, 1, 1), SysTime(DateTime(-3, 1, 1, 23, 59, 59), hnsecs(50_000))); |
| test(Date(-4, 12, 31), SysTime(DateTime(-4, 12, 31, 23, 59, 59), hnsecs(9_999_999))); |
| test(Date(-4, 1, 1), SysTime(DateTime(-4, 1, 1, 0, 0, 0))); |
| test(Date(-5, 12, 31), SysTime(DateTime(-5, 12, 31, 0, 0, 0), hnsecs(500))); |
| test(Date(-5, 1, 1), SysTime(DateTime(-5, 1, 1, 0, 0, 0), hnsecs(50_000))); |
| test(Date(-9, 1, 1), SysTime(DateTime(-9, 1, 1, 0, 0, 0), hnsecs(9_999_999))); |
| |
| test(Date(-49, 1, 1), SysTime(DateTime(-49, 1, 1, 12, 13, 14))); |
| test(Date(-50, 1, 1), SysTime(DateTime(-50, 1, 1, 12, 13, 14), hnsecs(500))); |
| test(Date(-97, 1, 1), SysTime(DateTime(-97, 1, 1, 12, 13, 14), hnsecs(50_000))); |
| test(Date(-99, 12, 31), SysTime(DateTime(-99, 12, 31, 12, 13, 14), hnsecs(9_999_999))); |
| test(Date(-99, 1, 1), SysTime(DateTime(-99, 1, 1, 23, 59, 59))); |
| test(Date(-100, 1, 1), SysTime(DateTime(-100, 1, 1, 23, 59, 59), hnsecs(500))); |
| test(Date(-101, 1, 1), SysTime(DateTime(-101, 1, 1, 23, 59, 59), hnsecs(50_000))); |
| test(Date(-105, 1, 1), SysTime(DateTime(-105, 1, 1, 23, 59, 59), hnsecs(9_999_999))); |
| test(Date(-200, 1, 1), SysTime(DateTime(-200, 1, 1, 0, 0, 0))); |
| test(Date(-201, 1, 1), SysTime(DateTime(-201, 1, 1, 0, 0, 0), hnsecs(500))); |
| test(Date(-300, 1, 1), SysTime(DateTime(-300, 1, 1, 0, 0, 0), hnsecs(50_000))); |
| test(Date(-301, 1, 1), SysTime(DateTime(-301, 1, 1, 0, 0, 0), hnsecs(9_999_999))); |
| test(Date(-400, 12, 31), SysTime(DateTime(-400, 12, 31, 12, 13, 14))); |
| test(Date(-400, 1, 1), SysTime(DateTime(-400, 1, 1, 12, 13, 14), hnsecs(500))); |
| test(Date(-401, 1, 1), SysTime(DateTime(-401, 1, 1, 12, 13, 14), hnsecs(50_000))); |
| test(Date(-499, 1, 1), SysTime(DateTime(-499, 1, 1, 12, 13, 14), hnsecs(9_999_999))); |
| test(Date(-500, 1, 1), SysTime(DateTime(-500, 1, 1, 23, 59, 59))); |
| test(Date(-501, 1, 1), SysTime(DateTime(-501, 1, 1, 23, 59, 59), hnsecs(500))); |
| test(Date(-1000, 1, 1), SysTime(DateTime(-1000, 1, 1, 23, 59, 59), hnsecs(50_000))); |
| test(Date(-1001, 1, 1), SysTime(DateTime(-1001, 1, 1, 23, 59, 59), hnsecs(9_999_999))); |
| test(Date(-1599, 1, 1), SysTime(DateTime(-1599, 1, 1, 0, 0, 0))); |
| test(Date(-1600, 12, 31), SysTime(DateTime(-1600, 12, 31, 0, 0, 0), hnsecs(500))); |
| test(Date(-1600, 1, 1), SysTime(DateTime(-1600, 1, 1, 0, 0, 0), hnsecs(50_000))); |
| test(Date(-1601, 1, 1), SysTime(DateTime(-1601, 1, 1, 0, 0, 0), hnsecs(9_999_999))); |
| test(Date(-1900, 1, 1), SysTime(DateTime(-1900, 1, 1, 12, 13, 14))); |
| test(Date(-1901, 1, 1), SysTime(DateTime(-1901, 1, 1, 12, 13, 14), hnsecs(500))); |
| test(Date(-1999, 1, 1), SysTime(DateTime(-1999, 1, 1, 12, 13, 14), hnsecs(50_000))); |
| test(Date(-1999, 7, 6), SysTime(DateTime(-1999, 7, 6, 12, 13, 14), hnsecs(9_999_999))); |
| test(Date(-2000, 12, 31), SysTime(DateTime(-2000, 12, 31, 23, 59, 59))); |
| test(Date(-2000, 1, 1), SysTime(DateTime(-2000, 1, 1, 23, 59, 59), hnsecs(500))); |
| test(Date(-2001, 1, 1), SysTime(DateTime(-2001, 1, 1, 23, 59, 59), hnsecs(50_000))); |
| |
| test(Date(-2010, 1, 1), SysTime(DateTime(-2010, 1, 1, 23, 59, 59), hnsecs(9_999_999))); |
| test(Date(-2010, 1, 31), SysTime(DateTime(-2010, 1, 31, 0, 0, 0))); |
| test(Date(-2010, 2, 1), SysTime(DateTime(-2010, 2, 1, 0, 0, 0), hnsecs(500))); |
| test(Date(-2010, 2, 28), SysTime(DateTime(-2010, 2, 28, 0, 0, 0), hnsecs(50_000))); |
| test(Date(-2010, 3, 1), SysTime(DateTime(-2010, 3, 1, 0, 0, 0), hnsecs(9_999_999))); |
| test(Date(-2010, 3, 31), SysTime(DateTime(-2010, 3, 31, 12, 13, 14))); |
| test(Date(-2010, 4, 1), SysTime(DateTime(-2010, 4, 1, 12, 13, 14), hnsecs(500))); |
| test(Date(-2010, 4, 30), SysTime(DateTime(-2010, 4, 30, 12, 13, 14), hnsecs(50_000))); |
| test(Date(-2010, 5, 1), SysTime(DateTime(-2010, 5, 1, 12, 13, 14), hnsecs(9_999_999))); |
| test(Date(-2010, 5, 31), SysTime(DateTime(-2010, 5, 31, 23, 59, 59))); |
| test(Date(-2010, 6, 1), SysTime(DateTime(-2010, 6, 1, 23, 59, 59), hnsecs(500))); |
| test(Date(-2010, 6, 30), SysTime(DateTime(-2010, 6, 30, 23, 59, 59), hnsecs(50_000))); |
| test(Date(-2010, 7, 1), SysTime(DateTime(-2010, 7, 1, 23, 59, 59), hnsecs(9_999_999))); |
| test(Date(-2010, 7, 31), SysTime(DateTime(-2010, 7, 31, 0, 0, 0))); |
| test(Date(-2010, 8, 1), SysTime(DateTime(-2010, 8, 1, 0, 0, 0), hnsecs(500))); |
| test(Date(-2010, 8, 31), SysTime(DateTime(-2010, 8, 31, 0, 0, 0), hnsecs(50_000))); |
| test(Date(-2010, 9, 1), SysTime(DateTime(-2010, 9, 1, 0, 0, 0), hnsecs(9_999_999))); |
| test(Date(-2010, 9, 30), SysTime(DateTime(-2010, 9, 30, 12, 0, 0))); |
| test(Date(-2010, 10, 1), SysTime(DateTime(-2010, 10, 1, 0, 12, 0), hnsecs(500))); |
| test(Date(-2010, 10, 31), SysTime(DateTime(-2010, 10, 31, 0, 0, 12), hnsecs(50_000))); |
| test(Date(-2010, 11, 1), SysTime(DateTime(-2010, 11, 1, 23, 0, 0), hnsecs(9_999_999))); |
| test(Date(-2010, 11, 30), SysTime(DateTime(-2010, 11, 30, 0, 59, 0))); |
| test(Date(-2010, 12, 1), SysTime(DateTime(-2010, 12, 1, 0, 0, 59), hnsecs(500))); |
| test(Date(-2010, 12, 31), SysTime(DateTime(-2010, 12, 31, 0, 59, 59), hnsecs(50_000))); |
| |
| test(Date(-2012, 2, 1), SysTime(DateTime(-2012, 2, 1, 23, 0, 59), hnsecs(9_999_999))); |
| test(Date(-2012, 2, 28), SysTime(DateTime(-2012, 2, 28, 23, 59, 0))); |
| test(Date(-2012, 2, 29), SysTime(DateTime(-2012, 2, 29, 7, 7, 7), hnsecs(7))); |
| test(Date(-2012, 3, 1), SysTime(DateTime(-2012, 3, 1, 7, 7, 7), hnsecs(7))); |
| |
| test(Date(-3760, 9, 7), SysTime(DateTime(-3760, 9, 7, 0, 0, 0))); |
| } |
| |
| |
| /++ |
| The Xth day of the Gregorian Calendar that this $(LREF SysTime) is on. |
| Setting this property does not affect the time portion of $(LREF SysTime). |
| |
| Params: |
| days = The day of the Gregorian Calendar to set this $(LREF SysTime) |
| to. |
| +/ |
| @property void dayOfGregorianCal(int days) @safe nothrow |
| { |
| auto hnsecs = adjTime; |
| hnsecs = removeUnitsFromHNSecs!"days"(hnsecs); |
| |
| if (hnsecs < 0) |
| hnsecs += convert!("hours", "hnsecs")(24); |
| |
| if (--days < 0) |
| { |
| hnsecs -= convert!("hours", "hnsecs")(24); |
| ++days; |
| } |
| |
| immutable newDaysHNSecs = convert!("days", "hnsecs")(days); |
| |
| adjTime = newDaysHNSecs + hnsecs; |
| } |
| |
| /// |
| @safe unittest |
| { |
| import std.datetime.date : DateTime; |
| |
| auto st = SysTime(DateTime(0, 1, 1, 12, 0, 0)); |
| st.dayOfGregorianCal = 1; |
| assert(st == SysTime(DateTime(1, 1, 1, 12, 0, 0))); |
| |
| st.dayOfGregorianCal = 365; |
| assert(st == SysTime(DateTime(1, 12, 31, 12, 0, 0))); |
| |
| st.dayOfGregorianCal = 366; |
| assert(st == SysTime(DateTime(2, 1, 1, 12, 0, 0))); |
| |
| st.dayOfGregorianCal = 0; |
| assert(st == SysTime(DateTime(0, 12, 31, 12, 0, 0))); |
| |
| st.dayOfGregorianCal = -365; |
| assert(st == SysTime(DateTime(-0, 1, 1, 12, 0, 0))); |
| |
| st.dayOfGregorianCal = -366; |
| assert(st == SysTime(DateTime(-1, 12, 31, 12, 0, 0))); |
| |
| st.dayOfGregorianCal = 730_120; |
| assert(st == SysTime(DateTime(2000, 1, 1, 12, 0, 0))); |
| |
| st.dayOfGregorianCal = 734_137; |
| assert(st == SysTime(DateTime(2010, 12, 31, 12, 0, 0))); |
| } |
| |
| @safe unittest |
| { |
| void testST(SysTime orig, int day, in SysTime expected, size_t line = __LINE__) |
| { |
| orig.dayOfGregorianCal = day; |
| if (orig != expected) |
| throw new AssertError(format("Failed. actual [%s] != expected [%s]", orig, expected), __FILE__, line); |
| } |
| |
| // Test A.D. |
| testST(SysTime(DateTime(1, 1, 1, 0, 0, 0)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1))); |
| testST(SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999)), 1, |
| SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999))); |
| |
| // Test B.C. |
| testST(SysTime(DateTime(0, 1, 1, 0, 0, 0)), 0, SysTime(DateTime(0, 12, 31, 0, 0, 0))); |
| testST(SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(9_999_999)), 0, |
| SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999))); |
| testST(SysTime(DateTime(0, 1, 1, 23, 59, 59), hnsecs(1)), 0, |
| SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1))); |
| testST(SysTime(DateTime(0, 1, 1, 23, 59, 59)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59))); |
| |
| // Test Both. |
| testST(SysTime(DateTime(-512, 7, 20, 0, 0, 0)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0))); |
| testST(SysTime(DateTime(-513, 6, 6, 0, 0, 0), hnsecs(1)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1))); |
| testST(SysTime(DateTime(-511, 5, 7, 23, 59, 59), hnsecs(9_999_999)), 1, |
| SysTime(DateTime(1, 1, 1, 23, 59, 59), hnsecs(9_999_999))); |
| |
| testST(SysTime(DateTime(1607, 4, 8, 0, 0, 0)), 0, SysTime(DateTime(0, 12, 31, 0, 0, 0))); |
| testST(SysTime(DateTime(1500, 3, 9, 23, 59, 59), hnsecs(9_999_999)), 0, |
| SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999))); |
| testST(SysTime(DateTime(999, 2, 10, 23, 59, 59), hnsecs(1)), 0, |
| SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1))); |
| testST(SysTime(DateTime(2007, 12, 11, 23, 59, 59)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59))); |
| |
| |
| auto st = SysTime(DateTime(1, 1, 1, 12, 2, 9), msecs(212)); |
| |
| void testST2(int day, in SysTime expected, size_t line = __LINE__) |
| { |
| st.dayOfGregorianCal = day; |
| if (st != expected) |
| throw new AssertError(format("Failed. actual [%s] != expected [%s]", st, expected), __FILE__, line); |
| } |
| |
| // Test A.D. |
| testST2(1, SysTime(DateTime(1, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(2, SysTime(DateTime(1, 1, 2, 12, 2, 9), msecs(212))); |
| testST2(32, SysTime(DateTime(1, 2, 1, 12, 2, 9), msecs(212))); |
| testST2(366, SysTime(DateTime(2, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(731, SysTime(DateTime(3, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(1096, SysTime(DateTime(4, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(1462, SysTime(DateTime(5, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(17_898, SysTime(DateTime(50, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(35_065, SysTime(DateTime(97, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(36_160, SysTime(DateTime(100, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(36_525, SysTime(DateTime(101, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(37_986, SysTime(DateTime(105, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(72_684, SysTime(DateTime(200, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(73_049, SysTime(DateTime(201, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(109_208, SysTime(DateTime(300, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(109_573, SysTime(DateTime(301, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(145_732, SysTime(DateTime(400, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(146_098, SysTime(DateTime(401, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(182_257, SysTime(DateTime(500, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(182_622, SysTime(DateTime(501, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(364_878, SysTime(DateTime(1000, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(365_243, SysTime(DateTime(1001, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(584_023, SysTime(DateTime(1600, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(584_389, SysTime(DateTime(1601, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(693_596, SysTime(DateTime(1900, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(693_961, SysTime(DateTime(1901, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(729_755, SysTime(DateTime(1999, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(730_120, SysTime(DateTime(2000, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(730_486, SysTime(DateTime(2001, 1, 1, 12, 2, 9), msecs(212))); |
| |
| testST2(733_773, SysTime(DateTime(2010, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(733_803, SysTime(DateTime(2010, 1, 31, 12, 2, 9), msecs(212))); |
| testST2(733_804, SysTime(DateTime(2010, 2, 1, 12, 2, 9), msecs(212))); |
| testST2(733_831, SysTime(DateTime(2010, 2, 28, 12, 2, 9), msecs(212))); |
| testST2(733_832, SysTime(DateTime(2010, 3, 1, 12, 2, 9), msecs(212))); |
| testST2(733_862, SysTime(DateTime(2010, 3, 31, 12, 2, 9), msecs(212))); |
| testST2(733_863, SysTime(DateTime(2010, 4, 1, 12, 2, 9), msecs(212))); |
| testST2(733_892, SysTime(DateTime(2010, 4, 30, 12, 2, 9), msecs(212))); |
| testST2(733_893, SysTime(DateTime(2010, 5, 1, 12, 2, 9), msecs(212))); |
| testST2(733_923, SysTime(DateTime(2010, 5, 31, 12, 2, 9), msecs(212))); |
| testST2(733_924, SysTime(DateTime(2010, 6, 1, 12, 2, 9), msecs(212))); |
| testST2(733_953, SysTime(DateTime(2010, 6, 30, 12, 2, 9), msecs(212))); |
| testST2(733_954, SysTime(DateTime(2010, 7, 1, 12, 2, 9), msecs(212))); |
| testST2(733_984, SysTime(DateTime(2010, 7, 31, 12, 2, 9), msecs(212))); |
| testST2(733_985, SysTime(DateTime(2010, 8, 1, 12, 2, 9), msecs(212))); |
| testST2(734_015, SysTime(DateTime(2010, 8, 31, 12, 2, 9), msecs(212))); |
| testST2(734_016, SysTime(DateTime(2010, 9, 1, 12, 2, 9), msecs(212))); |
| testST2(734_045, SysTime(DateTime(2010, 9, 30, 12, 2, 9), msecs(212))); |
| testST2(734_046, SysTime(DateTime(2010, 10, 1, 12, 2, 9), msecs(212))); |
| testST2(734_076, SysTime(DateTime(2010, 10, 31, 12, 2, 9), msecs(212))); |
| testST2(734_077, SysTime(DateTime(2010, 11, 1, 12, 2, 9), msecs(212))); |
| testST2(734_106, SysTime(DateTime(2010, 11, 30, 12, 2, 9), msecs(212))); |
| testST2(734_107, SysTime(DateTime(2010, 12, 1, 12, 2, 9), msecs(212))); |
| testST2(734_137, SysTime(DateTime(2010, 12, 31, 12, 2, 9), msecs(212))); |
| |
| testST2(734_534, SysTime(DateTime(2012, 2, 1, 12, 2, 9), msecs(212))); |
| testST2(734_561, SysTime(DateTime(2012, 2, 28, 12, 2, 9), msecs(212))); |
| testST2(734_562, SysTime(DateTime(2012, 2, 29, 12, 2, 9), msecs(212))); |
| testST2(734_563, SysTime(DateTime(2012, 3, 1, 12, 2, 9), msecs(212))); |
| |
| testST2(734_534, SysTime(DateTime(2012, 2, 1, 12, 2, 9), msecs(212))); |
| |
| testST2(734_561, SysTime(DateTime(2012, 2, 28, 12, 2, 9), msecs(212))); |
| testST2(734_562, SysTime(DateTime(2012, 2, 29, 12, 2, 9), msecs(212))); |
| testST2(734_563, SysTime(DateTime(2012, 3, 1, 12, 2, 9), msecs(212))); |
| |
| // Test B.C. |
| testST2(0, SysTime(DateTime(0, 12, 31, 12, 2, 9), msecs(212))); |
| testST2(-1, SysTime(DateTime(0, 12, 30, 12, 2, 9), msecs(212))); |
| testST2(-30, SysTime(DateTime(0, 12, 1, 12, 2, 9), msecs(212))); |
| testST2(-31, SysTime(DateTime(0, 11, 30, 12, 2, 9), msecs(212))); |
| |
| testST2(-366, SysTime(DateTime(-1, 12, 31, 12, 2, 9), msecs(212))); |
| testST2(-367, SysTime(DateTime(-1, 12, 30, 12, 2, 9), msecs(212))); |
| testST2(-730, SysTime(DateTime(-1, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-731, SysTime(DateTime(-2, 12, 31, 12, 2, 9), msecs(212))); |
| testST2(-1095, SysTime(DateTime(-2, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-1096, SysTime(DateTime(-3, 12, 31, 12, 2, 9), msecs(212))); |
| testST2(-1460, SysTime(DateTime(-3, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-1461, SysTime(DateTime(-4, 12, 31, 12, 2, 9), msecs(212))); |
| testST2(-1826, SysTime(DateTime(-4, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-1827, SysTime(DateTime(-5, 12, 31, 12, 2, 9), msecs(212))); |
| testST2(-2191, SysTime(DateTime(-5, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-3652, SysTime(DateTime(-9, 1, 1, 12, 2, 9), msecs(212))); |
| |
| testST2(-18_262, SysTime(DateTime(-49, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-18_627, SysTime(DateTime(-50, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-35_794, SysTime(DateTime(-97, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-36_160, SysTime(DateTime(-99, 12, 31, 12, 2, 9), msecs(212))); |
| testST2(-36_524, SysTime(DateTime(-99, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-36_889, SysTime(DateTime(-100, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-37_254, SysTime(DateTime(-101, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-38_715, SysTime(DateTime(-105, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-73_413, SysTime(DateTime(-200, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-73_778, SysTime(DateTime(-201, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-109_937, SysTime(DateTime(-300, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-110_302, SysTime(DateTime(-301, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-146_097, SysTime(DateTime(-400, 12, 31, 12, 2, 9), msecs(212))); |
| testST2(-146_462, SysTime(DateTime(-400, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-146_827, SysTime(DateTime(-401, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-182_621, SysTime(DateTime(-499, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-182_986, SysTime(DateTime(-500, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-183_351, SysTime(DateTime(-501, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-365_607, SysTime(DateTime(-1000, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-365_972, SysTime(DateTime(-1001, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-584_387, SysTime(DateTime(-1599, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-584_388, SysTime(DateTime(-1600, 12, 31, 12, 2, 9), msecs(212))); |
| testST2(-584_753, SysTime(DateTime(-1600, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-585_118, SysTime(DateTime(-1601, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-694_325, SysTime(DateTime(-1900, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-694_690, SysTime(DateTime(-1901, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-730_484, SysTime(DateTime(-1999, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-730_485, SysTime(DateTime(-2000, 12, 31, 12, 2, 9), msecs(212))); |
| testST2(-730_850, SysTime(DateTime(-2000, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-731_215, SysTime(DateTime(-2001, 1, 1, 12, 2, 9), msecs(212))); |
| |
| testST2(-734_502, SysTime(DateTime(-2010, 1, 1, 12, 2, 9), msecs(212))); |
| testST2(-734_472, SysTime(DateTime(-2010, 1, 31, 12, 2, 9), msecs(212))); |
| testST2(-734_471, SysTime(DateTime(-2010, 2, 1, 12, 2, 9), msecs(212))); |
| testST2(-734_444, SysTime(DateTime(-2010, 2, 28, 12, 2, 9), msecs(212))); |
| testST2(-734_443, SysTime(DateTime(-2010, 3, 1, 12, 2, 9), msecs(212))); |
| testST2(-734_413, SysTime(DateTime(-2010, 3, 31, 12, 2, 9), msecs(212))); |
| testST2(-734_412, SysTime(DateTime(-2010, 4, 1, 12, 2, 9), msecs(212))); |
| testST2(-734_383, SysTime(DateTime(-2010, 4, 30, 12, 2, 9), msecs(212))); |
| testST2(-734_382, SysTime(DateTime(-2010, 5, 1, 12, 2, 9), msecs(212))); |
| testST2(-734_352, SysTime(DateTime(-2010, 5, 31, 12, 2, 9), msecs(212))); |
| testST2(-734_351, SysTime(DateTime(-2010, 6, 1, 12, 2, 9), msecs(212))); |
| testST2(-734_322, SysTime(DateTime(-2010, 6, 30, 12, 2, 9), msecs(212))); |
| testST2(-734_321, SysTime(DateTime(-2010, 7, 1, 12, 2, 9), msecs(212))); |
| testST2(-734_291, SysTime(DateTime(-2010, 7, 31, 12, 2, 9), msecs(212))); |
| testST2(-734_290, SysTime(DateTime(-2010, 8, 1, 12, 2, 9), msecs(212))); |
| testST2(-734_260, SysTime(DateTime(-2010, 8, 31, 12, 2, 9), msecs(212))); |
| testST2(-734_259, SysTime(DateTime(-2010, 9, 1, 12, 2, 9), msecs(212))); |
| testST2(-734_230, SysTime(DateTime(-2010, 9, 30, 12, 2, 9), msecs(212))); |
| testST2(-734_229, SysTime(DateTime(-2010, 10, 1, 12, 2, 9), msecs(212))); |
| testST2(-734_199, SysTime(DateTime(-2010, 10, 31, 12, 2, 9), msecs(212))); |
| testST2(-734_198, SysTime(DateTime(-2010, 11, 1, 12, 2, 9), msecs(212))); |
| testST2(-734_169, SysTime(DateTime(-2010, 11, 30, 12, 2, 9), msecs(212))); |
| testST2(-734_168, SysTime(DateTime(-2010, 12, 1, 12, 2, 9), msecs(212))); |
| testST2(-734_138, SysTime(DateTime(-2010, 12, 31, 12, 2, 9), msecs(212))); |
| |
| testST2(-735_202, SysTime(DateTime(-2012, 2, 1, 12, 2, 9), msecs(212))); |
| testST2(-735_175, SysTime(DateTime(-2012, 2, 28, 12, 2, 9), msecs(212))); |
| testST2(-735_174, SysTime(DateTime(-2012, 2, 29, 12, 2, 9), msecs(212))); |
| testST2(-735_173, SysTime(DateTime(-2012, 3, 1, 12, 2, 9), msecs(212))); |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| static assert(!__traits(compiles, cst.dayOfGregorianCal = 7)); |
| //static assert(!__traits(compiles, ist.dayOfGregorianCal = 7)); |
| } |
| |
| |
| /++ |
| The ISO 8601 week of the year that this $(LREF SysTime) is in. |
| |
| See_Also: |
| $(HTTP en.wikipedia.org/wiki/ISO_week_date, ISO Week Date). |
| +/ |
| @property ubyte isoWeek() @safe const nothrow |
| { |
| return (cast(Date) this).isoWeek; |
| } |
| |
| /// |
| @safe unittest |
| { |
| import std.datetime.date : Date; |
| |
| auto st = SysTime(Date(1999, 7, 6)); |
| const cst = SysTime(Date(2010, 5, 1)); |
| immutable ist = SysTime(Date(2015, 10, 10)); |
| |
| assert(st.isoWeek == 27); |
| assert(cst.isoWeek == 17); |
| assert(ist.isoWeek == 41); |
| } |
| |
| |
| /++ |
| $(LREF SysTime) for the last day in the month that this Date is in. |
| The time portion of endOfMonth is always 23:59:59.9999999. |
| +/ |
| @property SysTime endOfMonth() @safe const nothrow |
| { |
| immutable hnsecs = adjTime; |
| immutable days = getUnitsFromHNSecs!"days"(hnsecs); |
| |
| auto date = Date(cast(int) days + 1).endOfMonth; |
| auto newDays = date.dayOfGregorianCal - 1; |
| long theTimeHNSecs; |
| |
| if (newDays < 0) |
| { |
| theTimeHNSecs = -1; |
| ++newDays; |
| } |
| else |
| theTimeHNSecs = convert!("days", "hnsecs")(1) - 1; |
| |
| immutable newDaysHNSecs = convert!("days", "hnsecs")(newDays); |
| |
| auto retval = SysTime(this._stdTime, this._timezone); |
| retval.adjTime = newDaysHNSecs + theTimeHNSecs; |
| |
| return retval; |
| } |
| |
| /// |
| @safe unittest |
| { |
| import core.time : msecs, usecs, hnsecs; |
| import std.datetime.date : DateTime; |
| |
| assert(SysTime(DateTime(1999, 1, 6, 0, 0, 0)).endOfMonth == |
| SysTime(DateTime(1999, 1, 31, 23, 59, 59), hnsecs(9_999_999))); |
| |
| assert(SysTime(DateTime(1999, 2, 7, 19, 30, 0), msecs(24)).endOfMonth == |
| SysTime(DateTime(1999, 2, 28, 23, 59, 59), hnsecs(9_999_999))); |
| |
| assert(SysTime(DateTime(2000, 2, 7, 5, 12, 27), usecs(5203)).endOfMonth == |
| SysTime(DateTime(2000, 2, 29, 23, 59, 59), hnsecs(9_999_999))); |
| |
| assert(SysTime(DateTime(2000, 6, 4, 12, 22, 9), hnsecs(12345)).endOfMonth == |
| SysTime(DateTime(2000, 6, 30, 23, 59, 59), hnsecs(9_999_999))); |
| } |
| |
| @safe unittest |
| { |
| // Test A.D. |
| assert(SysTime(Date(1999, 1, 1)).endOfMonth == SysTime(DateTime(1999, 1, 31, 23, 59, 59), hnsecs(9_999_999))); |
| assert(SysTime(Date(1999, 2, 1)).endOfMonth == SysTime(DateTime(1999, 2, 28, 23, 59, 59), hnsecs(9_999_999))); |
| assert(SysTime(Date(2000, 2, 1)).endOfMonth == SysTime(DateTime(2000, 2, 29, 23, 59, 59), hnsecs(9_999_999))); |
| assert(SysTime(Date(1999, 3, 1)).endOfMonth == SysTime(DateTime(1999, 3, 31, 23, 59, 59), hnsecs(9_999_999))); |
| assert(SysTime(Date(1999, 4, 1)).endOfMonth == SysTime(DateTime(1999, 4, 30, 23, 59, 59), hnsecs(9_999_999))); |
| assert(SysTime(Date(1999, 5, 1)).endOfMonth == SysTime(DateTime(1999, 5, 31, 23, 59, 59), hnsecs(9_999_999))); |
| assert(SysTime(Date(1999, 6, 1)).endOfMonth == SysTime(DateTime(1999, 6, 30, 23, 59, 59), hnsecs(9_999_999))); |
| assert(SysTime(Date(1999, 7, 1)).endOfMonth == SysTime(DateTime(1999, 7, 31, 23, 59, 59), hnsecs(9_999_999))); |
| assert(SysTime(Date(1999, 8, 1)).endOfMonth == SysTime(DateTime(1999, 8, 31, 23, 59, 59), hnsecs(9_999_999))); |
| assert(SysTime(Date(1999, 9, 1)).endOfMonth == SysTime(DateTime(1999, 9, 30, 23, 59, 59), hnsecs(9_999_999))); |
| assert(SysTime(Date(1999, 10, 1)).endOfMonth == SysTime(DateTime(1999, 10, 31, 23, 59, 59), hnsecs(9_999_999))); |
| assert(SysTime(Date(1999, 11, 1)).endOfMonth == SysTime(DateTime(1999, 11, 30, 23, 59, 59), hnsecs(9_999_999))); |
| assert(SysTime(Date(1999, 12, 1)).endOfMonth == SysTime(DateTime(1999, 12, 31, 23, 59, 59), hnsecs(9_999_999))); |
| |
| // Test B.C. |
| assert(SysTime(Date(-1999, 1, 1)).endOfMonth == SysTime(DateTime(-1999, 1, 31, 23, 59, 59), hnsecs(9_999_999))); |
| assert(SysTime(Date(-1999, 2, 1)).endOfMonth == SysTime(DateTime(-1999, 2, 28, 23, 59, 59), hnsecs(9_999_999))); |
| assert(SysTime(Date(-2000, 2, 1)).endOfMonth == SysTime(DateTime(-2000, 2, 29, 23, 59, 59), hnsecs(9_999_999))); |
| assert(SysTime(Date(-1999, 3, 1)).endOfMonth == SysTime(DateTime(-1999, 3, 31, 23, 59, 59), hnsecs(9_999_999))); |
| assert(SysTime(Date(-1999, 4, 1)).endOfMonth == SysTime(DateTime(-1999, 4, 30, 23, 59, 59), hnsecs(9_999_999))); |
| assert(SysTime(Date(-1999, 5, 1)).endOfMonth == SysTime(DateTime(-1999, 5, 31, 23, 59, 59), hnsecs(9_999_999))); |
| assert(SysTime(Date(-1999, 6, 1)).endOfMonth == SysTime(DateTime(-1999, 6, 30, 23, 59, 59), hnsecs(9_999_999))); |
| assert(SysTime(Date(-1999, 7, 1)).endOfMonth == SysTime(DateTime(-1999, 7, 31, 23, 59, 59), hnsecs(9_999_999))); |
| assert(SysTime(Date(-1999, 8, 1)).endOfMonth == SysTime(DateTime(-1999, 8, 31, 23, 59, 59), hnsecs(9_999_999))); |
| assert(SysTime(Date(-1999, 9, 1)).endOfMonth == SysTime(DateTime(-1999, 9, 30, 23, 59, 59), hnsecs(9_999_999))); |
| assert(SysTime(Date(-1999, 10, 1)).endOfMonth == |
| SysTime(DateTime(-1999, 10, 31, 23, 59, 59), hnsecs(9_999_999))); |
| assert(SysTime(Date(-1999, 11, 1)).endOfMonth == |
| SysTime(DateTime(-1999, 11, 30, 23, 59, 59), hnsecs(9_999_999))); |
| assert(SysTime(Date(-1999, 12, 1)).endOfMonth == |
| SysTime(DateTime(-1999, 12, 31, 23, 59, 59), hnsecs(9_999_999))); |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(cst.endOfMonth == SysTime(DateTime(1999, 7, 31, 23, 59, 59), hnsecs(9_999_999))); |
| //assert(ist.endOfMonth == SysTime(DateTime(1999, 7, 31, 23, 59, 59), hnsecs(9_999_999))); |
| } |
| |
| |
| /++ |
| The last day in the month that this $(LREF SysTime) is in. |
| +/ |
| @property ubyte daysInMonth() @safe const nothrow |
| { |
| return Date(dayOfGregorianCal).daysInMonth; |
| } |
| |
| /// |
| @safe unittest |
| { |
| import std.datetime.date : DateTime; |
| |
| assert(SysTime(DateTime(1999, 1, 6, 0, 0, 0)).daysInMonth == 31); |
| assert(SysTime(DateTime(1999, 2, 7, 19, 30, 0)).daysInMonth == 28); |
| assert(SysTime(DateTime(2000, 2, 7, 5, 12, 27)).daysInMonth == 29); |
| assert(SysTime(DateTime(2000, 6, 4, 12, 22, 9)).daysInMonth == 30); |
| } |
| |
| @safe unittest |
| { |
| // Test A.D. |
| assert(SysTime(DateTime(1999, 1, 1, 12, 1, 13)).daysInMonth == 31); |
| assert(SysTime(DateTime(1999, 2, 1, 17, 13, 12)).daysInMonth == 28); |
| assert(SysTime(DateTime(2000, 2, 1, 13, 2, 12)).daysInMonth == 29); |
| assert(SysTime(DateTime(1999, 3, 1, 12, 13, 12)).daysInMonth == 31); |
| assert(SysTime(DateTime(1999, 4, 1, 12, 6, 13)).daysInMonth == 30); |
| assert(SysTime(DateTime(1999, 5, 1, 15, 13, 12)).daysInMonth == 31); |
| assert(SysTime(DateTime(1999, 6, 1, 13, 7, 12)).daysInMonth == 30); |
| assert(SysTime(DateTime(1999, 7, 1, 12, 13, 17)).daysInMonth == 31); |
| assert(SysTime(DateTime(1999, 8, 1, 12, 3, 13)).daysInMonth == 31); |
| assert(SysTime(DateTime(1999, 9, 1, 12, 13, 12)).daysInMonth == 30); |
| assert(SysTime(DateTime(1999, 10, 1, 13, 19, 12)).daysInMonth == 31); |
| assert(SysTime(DateTime(1999, 11, 1, 12, 13, 17)).daysInMonth == 30); |
| assert(SysTime(DateTime(1999, 12, 1, 12, 52, 13)).daysInMonth == 31); |
| |
| // Test B.C. |
| assert(SysTime(DateTime(-1999, 1, 1, 12, 1, 13)).daysInMonth == 31); |
| assert(SysTime(DateTime(-1999, 2, 1, 7, 13, 12)).daysInMonth == 28); |
| assert(SysTime(DateTime(-2000, 2, 1, 13, 2, 12)).daysInMonth == 29); |
| assert(SysTime(DateTime(-1999, 3, 1, 12, 13, 12)).daysInMonth == 31); |
| assert(SysTime(DateTime(-1999, 4, 1, 12, 6, 13)).daysInMonth == 30); |
| assert(SysTime(DateTime(-1999, 5, 1, 5, 13, 12)).daysInMonth == 31); |
| assert(SysTime(DateTime(-1999, 6, 1, 13, 7, 12)).daysInMonth == 30); |
| assert(SysTime(DateTime(-1999, 7, 1, 12, 13, 17)).daysInMonth == 31); |
| assert(SysTime(DateTime(-1999, 8, 1, 12, 3, 13)).daysInMonth == 31); |
| assert(SysTime(DateTime(-1999, 9, 1, 12, 13, 12)).daysInMonth == 30); |
| assert(SysTime(DateTime(-1999, 10, 1, 13, 19, 12)).daysInMonth == 31); |
| assert(SysTime(DateTime(-1999, 11, 1, 12, 13, 17)).daysInMonth == 30); |
| assert(SysTime(DateTime(-1999, 12, 1, 12, 52, 13)).daysInMonth == 31); |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(cst.daysInMonth == 31); |
| //assert(ist.daysInMonth == 31); |
| } |
| |
| |
| /++ |
| Whether the current year is a date in A.D. |
| +/ |
| @property bool isAD() @safe const nothrow |
| { |
| return adjTime >= 0; |
| } |
| |
| /// |
| @safe unittest |
| { |
| import std.datetime.date : DateTime; |
| |
| assert(SysTime(DateTime(1, 1, 1, 12, 7, 0)).isAD); |
| assert(SysTime(DateTime(2010, 12, 31, 0, 0, 0)).isAD); |
| assert(!SysTime(DateTime(0, 12, 31, 23, 59, 59)).isAD); |
| assert(!SysTime(DateTime(-2010, 1, 1, 2, 2, 2)).isAD); |
| } |
| |
| @safe unittest |
| { |
| assert(SysTime(DateTime(2010, 7, 4, 12, 0, 9)).isAD); |
| assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).isAD); |
| assert(!SysTime(DateTime(0, 12, 31, 23, 59, 59)).isAD); |
| assert(!SysTime(DateTime(0, 1, 1, 23, 59, 59)).isAD); |
| assert(!SysTime(DateTime(-1, 1, 1, 23 ,59 ,59)).isAD); |
| assert(!SysTime(DateTime(-2010, 7, 4, 12, 2, 2)).isAD); |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(cst.isAD); |
| //assert(ist.isAD); |
| } |
| |
| |
| /++ |
| The $(HTTP en.wikipedia.org/wiki/Julian_day, Julian day) |
| for this $(LREF SysTime) at the given time. For example, |
| prior to noon, 1996-03-31 would be the Julian day number 2_450_173, so |
| this function returns 2_450_173, while from noon onward, the Julian |
| day number would be 2_450_174, so this function returns 2_450_174. |
| +/ |
| @property long julianDay() @safe const nothrow |
| { |
| immutable jd = dayOfGregorianCal + 1_721_425; |
| return hour < 12 ? jd - 1 : jd; |
| } |
| |
| @safe unittest |
| { |
| assert(SysTime(DateTime(-4713, 11, 24, 0, 0, 0)).julianDay == -1); |
| assert(SysTime(DateTime(-4713, 11, 24, 12, 0, 0)).julianDay == 0); |
| |
| assert(SysTime(DateTime(0, 12, 31, 0, 0, 0)).julianDay == 1_721_424); |
| assert(SysTime(DateTime(0, 12, 31, 12, 0, 0)).julianDay == 1_721_425); |
| |
| assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).julianDay == 1_721_425); |
| assert(SysTime(DateTime(1, 1, 1, 12, 0, 0)).julianDay == 1_721_426); |
| |
| assert(SysTime(DateTime(1582, 10, 15, 0, 0, 0)).julianDay == 2_299_160); |
| assert(SysTime(DateTime(1582, 10, 15, 12, 0, 0)).julianDay == 2_299_161); |
| |
| assert(SysTime(DateTime(1858, 11, 17, 0, 0, 0)).julianDay == 2_400_000); |
| assert(SysTime(DateTime(1858, 11, 17, 12, 0, 0)).julianDay == 2_400_001); |
| |
| assert(SysTime(DateTime(1982, 1, 4, 0, 0, 0)).julianDay == 2_444_973); |
| assert(SysTime(DateTime(1982, 1, 4, 12, 0, 0)).julianDay == 2_444_974); |
| |
| assert(SysTime(DateTime(1996, 3, 31, 0, 0, 0)).julianDay == 2_450_173); |
| assert(SysTime(DateTime(1996, 3, 31, 12, 0, 0)).julianDay == 2_450_174); |
| |
| assert(SysTime(DateTime(2010, 8, 24, 0, 0, 0)).julianDay == 2_455_432); |
| assert(SysTime(DateTime(2010, 8, 24, 12, 0, 0)).julianDay == 2_455_433); |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(cst.julianDay == 2_451_366); |
| //assert(ist.julianDay == 2_451_366); |
| } |
| |
| |
| /++ |
| The modified $(HTTP en.wikipedia.org/wiki/Julian_day, Julian day) for |
| any time on this date (since, the modified Julian day changes at |
| midnight). |
| +/ |
| @property long modJulianDay() @safe const nothrow |
| { |
| return dayOfGregorianCal + 1_721_425 - 2_400_001; |
| } |
| |
| @safe unittest |
| { |
| assert(SysTime(DateTime(1858, 11, 17, 0, 0, 0)).modJulianDay == 0); |
| assert(SysTime(DateTime(1858, 11, 17, 12, 0, 0)).modJulianDay == 0); |
| |
| assert(SysTime(DateTime(2010, 8, 24, 0, 0, 0)).modJulianDay == 55_432); |
| assert(SysTime(DateTime(2010, 8, 24, 12, 0, 0)).modJulianDay == 55_432); |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(cst.modJulianDay == 51_365); |
| //assert(ist.modJulianDay == 51_365); |
| } |
| |
| |
| /++ |
| Returns a $(REF Date,std,datetime,date) equivalent to this $(LREF SysTime). |
| +/ |
| Date opCast(T)() @safe const nothrow |
| if (is(Unqual!T == Date)) |
| { |
| return Date(dayOfGregorianCal); |
| } |
| |
| @safe unittest |
| { |
| assert(cast(Date) SysTime(Date(1999, 7, 6)) == Date(1999, 7, 6)); |
| assert(cast(Date) SysTime(Date(2000, 12, 31)) == Date(2000, 12, 31)); |
| assert(cast(Date) SysTime(Date(2001, 1, 1)) == Date(2001, 1, 1)); |
| |
| assert(cast(Date) SysTime(DateTime(1999, 7, 6, 12, 10, 9)) == Date(1999, 7, 6)); |
| assert(cast(Date) SysTime(DateTime(2000, 12, 31, 13, 11, 10)) == Date(2000, 12, 31)); |
| assert(cast(Date) SysTime(DateTime(2001, 1, 1, 14, 12, 11)) == Date(2001, 1, 1)); |
| |
| assert(cast(Date) SysTime(Date(-1999, 7, 6)) == Date(-1999, 7, 6)); |
| assert(cast(Date) SysTime(Date(-2000, 12, 31)) == Date(-2000, 12, 31)); |
| assert(cast(Date) SysTime(Date(-2001, 1, 1)) == Date(-2001, 1, 1)); |
| |
| assert(cast(Date) SysTime(DateTime(-1999, 7, 6, 12, 10, 9)) == Date(-1999, 7, 6)); |
| assert(cast(Date) SysTime(DateTime(-2000, 12, 31, 13, 11, 10)) == Date(-2000, 12, 31)); |
| assert(cast(Date) SysTime(DateTime(-2001, 1, 1, 14, 12, 11)) == Date(-2001, 1, 1)); |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(cast(Date) cst != Date.init); |
| //assert(cast(Date) ist != Date.init); |
| } |
| |
| |
| /++ |
| Returns a $(REF DateTime,std,datetime,date) equivalent to this |
| $(LREF SysTime). |
| +/ |
| DateTime opCast(T)() @safe const nothrow |
| if (is(Unqual!T == DateTime)) |
| { |
| try |
| { |
| auto hnsecs = adjTime; |
| auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1; |
| |
| if (hnsecs < 0) |
| { |
| hnsecs += convert!("hours", "hnsecs")(24); |
| --days; |
| } |
| |
| immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs); |
| immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs); |
| immutable second = getUnitsFromHNSecs!"seconds"(hnsecs); |
| |
| return DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour, cast(int) minute, cast(int) second)); |
| } |
| catch (Exception e) |
| assert(0, "Either DateTime's constructor or TimeOfDay's constructor threw."); |
| } |
| |
| @safe unittest |
| { |
| assert(cast(DateTime) SysTime(DateTime(1, 1, 6, 7, 12, 22)) == DateTime(1, 1, 6, 7, 12, 22)); |
| assert(cast(DateTime) SysTime(DateTime(1, 1, 6, 7, 12, 22), msecs(22)) == DateTime(1, 1, 6, 7, 12, 22)); |
| assert(cast(DateTime) SysTime(Date(1999, 7, 6)) == DateTime(1999, 7, 6, 0, 0, 0)); |
| assert(cast(DateTime) SysTime(Date(2000, 12, 31)) == DateTime(2000, 12, 31, 0, 0, 0)); |
| assert(cast(DateTime) SysTime(Date(2001, 1, 1)) == DateTime(2001, 1, 1, 0, 0, 0)); |
| |
| assert(cast(DateTime) SysTime(DateTime(1999, 7, 6, 12, 10, 9)) == DateTime(1999, 7, 6, 12, 10, 9)); |
| assert(cast(DateTime) SysTime(DateTime(2000, 12, 31, 13, 11, 10)) == DateTime(2000, 12, 31, 13, 11, 10)); |
| assert(cast(DateTime) SysTime(DateTime(2001, 1, 1, 14, 12, 11)) == DateTime(2001, 1, 1, 14, 12, 11)); |
| |
| assert(cast(DateTime) SysTime(DateTime(-1, 1, 6, 7, 12, 22)) == DateTime(-1, 1, 6, 7, 12, 22)); |
| assert(cast(DateTime) SysTime(DateTime(-1, 1, 6, 7, 12, 22), msecs(22)) == DateTime(-1, 1, 6, 7, 12, 22)); |
| assert(cast(DateTime) SysTime(Date(-1999, 7, 6)) == DateTime(-1999, 7, 6, 0, 0, 0)); |
| assert(cast(DateTime) SysTime(Date(-2000, 12, 31)) == DateTime(-2000, 12, 31, 0, 0, 0)); |
| assert(cast(DateTime) SysTime(Date(-2001, 1, 1)) == DateTime(-2001, 1, 1, 0, 0, 0)); |
| |
| assert(cast(DateTime) SysTime(DateTime(-1999, 7, 6, 12, 10, 9)) == DateTime(-1999, 7, 6, 12, 10, 9)); |
| assert(cast(DateTime) SysTime(DateTime(-2000, 12, 31, 13, 11, 10)) == DateTime(-2000, 12, 31, 13, 11, 10)); |
| assert(cast(DateTime) SysTime(DateTime(-2001, 1, 1, 14, 12, 11)) == DateTime(-2001, 1, 1, 14, 12, 11)); |
| |
| assert(cast(DateTime) SysTime(DateTime(2011, 1, 13, 8, 17, 2), msecs(296), LocalTime()) == |
| DateTime(2011, 1, 13, 8, 17, 2)); |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(cast(DateTime) cst != DateTime.init); |
| //assert(cast(DateTime) ist != DateTime.init); |
| } |
| |
| |
| /++ |
| Returns a $(REF TimeOfDay,std,datetime,date) equivalent to this |
| $(LREF SysTime). |
| +/ |
| TimeOfDay opCast(T)() @safe const nothrow |
| if (is(Unqual!T == TimeOfDay)) |
| { |
| try |
| { |
| auto hnsecs = adjTime; |
| hnsecs = removeUnitsFromHNSecs!"days"(hnsecs); |
| |
| if (hnsecs < 0) |
| hnsecs += convert!("hours", "hnsecs")(24); |
| |
| immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs); |
| immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs); |
| immutable second = getUnitsFromHNSecs!"seconds"(hnsecs); |
| |
| return TimeOfDay(cast(int) hour, cast(int) minute, cast(int) second); |
| } |
| catch (Exception e) |
| assert(0, "TimeOfDay's constructor threw."); |
| } |
| |
| @safe unittest |
| { |
| assert(cast(TimeOfDay) SysTime(Date(1999, 7, 6)) == TimeOfDay(0, 0, 0)); |
| assert(cast(TimeOfDay) SysTime(Date(2000, 12, 31)) == TimeOfDay(0, 0, 0)); |
| assert(cast(TimeOfDay) SysTime(Date(2001, 1, 1)) == TimeOfDay(0, 0, 0)); |
| |
| assert(cast(TimeOfDay) SysTime(DateTime(1999, 7, 6, 12, 10, 9)) == TimeOfDay(12, 10, 9)); |
| assert(cast(TimeOfDay) SysTime(DateTime(2000, 12, 31, 13, 11, 10)) == TimeOfDay(13, 11, 10)); |
| assert(cast(TimeOfDay) SysTime(DateTime(2001, 1, 1, 14, 12, 11)) == TimeOfDay(14, 12, 11)); |
| |
| assert(cast(TimeOfDay) SysTime(Date(-1999, 7, 6)) == TimeOfDay(0, 0, 0)); |
| assert(cast(TimeOfDay) SysTime(Date(-2000, 12, 31)) == TimeOfDay(0, 0, 0)); |
| assert(cast(TimeOfDay) SysTime(Date(-2001, 1, 1)) == TimeOfDay(0, 0, 0)); |
| |
| assert(cast(TimeOfDay) SysTime(DateTime(-1999, 7, 6, 12, 10, 9)) == TimeOfDay(12, 10, 9)); |
| assert(cast(TimeOfDay) SysTime(DateTime(-2000, 12, 31, 13, 11, 10)) == TimeOfDay(13, 11, 10)); |
| assert(cast(TimeOfDay) SysTime(DateTime(-2001, 1, 1, 14, 12, 11)) == TimeOfDay(14, 12, 11)); |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(cast(TimeOfDay) cst != TimeOfDay.init); |
| //assert(cast(TimeOfDay) ist != TimeOfDay.init); |
| } |
| |
| |
| // Temporary hack until bug http://d.puremagic.com/issues/show_bug.cgi?id=4867 is fixed. |
| // This allows assignment from const(SysTime) to SysTime. |
| // It may be a good idea to keep it though, since casting from a type to itself |
| // should be allowed, and it doesn't work without this opCast() since opCast() |
| // has already been defined for other types. |
| SysTime opCast(T)() @safe const pure nothrow |
| if (is(Unqual!T == SysTime)) |
| { |
| return SysTime(_stdTime, _timezone); |
| } |
| |
| |
| /++ |
| Converts this $(LREF SysTime) to a string with the format |
| YYYYMMDDTHHMMSS.FFFFFFFTZ (where F is fractional seconds and TZ is time |
| zone). |
| |
| Note that the number of digits in the fractional seconds varies with the |
| number of fractional seconds. It's a maximum of 7 (which would be |
| hnsecs), but only has as many as are necessary to hold the correct value |
| (so no trailing zeroes), and if there are no fractional seconds, then |
| there is no decimal point. |
| |
| If this $(LREF SysTime)'s time zone is |
| $(REF LocalTime,std,datetime,timezone), then TZ is empty. If its time |
| zone is $(D UTC), then it is "Z". Otherwise, it is the offset from UTC |
| (e.g. +0100 or -0700). Note that the offset from UTC is $(I not) enough |
| to uniquely identify the time zone. |
| |
| Time zone offsets will be in the form +HHMM or -HHMM. |
| |
| $(RED Warning: |
| Previously, toISOString did the same as $(LREF toISOExtString) and |
| generated +HH:MM or -HH:MM for the time zone when it was not |
| $(REF LocalTime,std,datetime,timezone) or |
| $(REF UTC,std,datetime,timezone), which is not in conformance with |
| ISO 8601 for the non-extended string format. This has now been |
| fixed. However, for now, fromISOString will continue to accept the |
| extended format for the time zone so that any code which has been |
| writing out the result of toISOString to read in later will continue |
| to work. The current behavior will be kept until July 2019 at which |
| point, fromISOString will be fixed to be standards compliant.) |
| +/ |
| string toISOString() @safe const nothrow |
| { |
| try |
| { |
| immutable adjustedTime = adjTime; |
| long hnsecs = adjustedTime; |
| |
| auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1; |
| |
| if (hnsecs < 0) |
| { |
| hnsecs += convert!("hours", "hnsecs")(24); |
| --days; |
| } |
| |
| auto hour = splitUnitsFromHNSecs!"hours"(hnsecs); |
| auto minute = splitUnitsFromHNSecs!"minutes"(hnsecs); |
| auto second = splitUnitsFromHNSecs!"seconds"(hnsecs); |
| |
| auto dateTime = DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour, |
| cast(int) minute, cast(int) second)); |
| auto fracSecStr = fracSecsToISOString(cast(int) hnsecs); |
| |
| if (_timezone is LocalTime()) |
| return dateTime.toISOString() ~ fracSecStr; |
| |
| if (_timezone is UTC()) |
| return dateTime.toISOString() ~ fracSecStr ~ "Z"; |
| |
| immutable utcOffset = dur!"hnsecs"(adjustedTime - stdTime); |
| |
| return format("%s%s%s", |
| dateTime.toISOString(), |
| fracSecStr, |
| SimpleTimeZone.toISOExtString(utcOffset)); |
| } |
| catch (Exception e) |
| assert(0, "format() threw."); |
| } |
| |
| /// |
| @safe unittest |
| { |
| import core.time : msecs, hnsecs; |
| import std.datetime.date : DateTime; |
| |
| assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toISOString() == |
| "20100704T070612"); |
| |
| assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(24)).toISOString() == |
| "19981225T021500.024"); |
| |
| assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toISOString() == |
| "00000105T230959"); |
| |
| assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toISOString() == |
| "-00040105T000002.052092"); |
| } |
| |
| @safe unittest |
| { |
| // Test A.D. |
| assert(SysTime(DateTime.init, UTC()).toISOString() == "00010101T000000Z"); |
| assert(SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1), UTC()).toISOString() == "00010101T000000.0000001Z"); |
| |
| assert(SysTime(DateTime(9, 12, 4, 0, 0, 0)).toISOString() == "00091204T000000"); |
| assert(SysTime(DateTime(99, 12, 4, 5, 6, 12)).toISOString() == "00991204T050612"); |
| assert(SysTime(DateTime(999, 12, 4, 13, 44, 59)).toISOString() == "09991204T134459"); |
| assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59)).toISOString() == "99990704T235959"); |
| assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1)).toISOString() == "+100001020T010101"); |
| |
| assert(SysTime(DateTime(9, 12, 4, 0, 0, 0), msecs(42)).toISOString() == "00091204T000000.042"); |
| assert(SysTime(DateTime(99, 12, 4, 5, 6, 12), msecs(100)).toISOString() == "00991204T050612.1"); |
| assert(SysTime(DateTime(999, 12, 4, 13, 44, 59), usecs(45020)).toISOString() == "09991204T134459.04502"); |
| assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59), hnsecs(12)).toISOString() == "99990704T235959.0000012"); |
| assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1), hnsecs(507890)).toISOString() == "+100001020T010101.050789"); |
| |
| assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12), |
| new immutable SimpleTimeZone(dur!"minutes"(-360))).toISOString() == |
| "20121221T121212-06:00"); |
| |
| assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12), |
| new immutable SimpleTimeZone(dur!"minutes"(420))).toISOString() == |
| "20121221T121212+07:00"); |
| |
| // Test B.C. |
| assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toISOString() == |
| "00001231T235959.9999999Z"); |
| assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1), UTC()).toISOString() == "00001231T235959.0000001Z"); |
| assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), UTC()).toISOString() == "00001231T235959Z"); |
| |
| assert(SysTime(DateTime(0, 12, 4, 0, 12, 4)).toISOString() == "00001204T001204"); |
| assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0)).toISOString() == "-00091204T000000"); |
| assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12)).toISOString() == "-00991204T050612"); |
| assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59)).toISOString() == "-09991204T134459"); |
| assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59)).toISOString() == "-99990704T235959"); |
| assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1)).toISOString() == "-100001020T010101"); |
| |
| assert(SysTime(DateTime(0, 12, 4, 0, 0, 0), msecs(7)).toISOString() == "00001204T000000.007"); |
| assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0), msecs(42)).toISOString() == "-00091204T000000.042"); |
| assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12), msecs(100)).toISOString() == "-00991204T050612.1"); |
| assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59), usecs(45020)).toISOString() == "-09991204T134459.04502"); |
| assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59), hnsecs(12)).toISOString() == "-99990704T235959.0000012"); |
| assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1), hnsecs(507890)).toISOString() == "-100001020T010101.050789"); |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(cast(TimeOfDay) cst != TimeOfDay.init); |
| //assert(cast(TimeOfDay) ist != TimeOfDay.init); |
| } |
| |
| |
| |
| /++ |
| Converts this $(LREF SysTime) to a string with the format |
| YYYY-MM-DDTHH:MM:SS.FFFFFFFTZ (where F is fractional seconds and TZ |
| is the time zone). |
| |
| Note that the number of digits in the fractional seconds varies with the |
| number of fractional seconds. It's a maximum of 7 (which would be |
| hnsecs), but only has as many as are necessary to hold the correct value |
| (so no trailing zeroes), and if there are no fractional seconds, then |
| there is no decimal point. |
| |
| If this $(LREF SysTime)'s time zone is |
| $(REF LocalTime,std,datetime,timezone), then TZ is empty. If its time |
| zone is $(D UTC), then it is "Z". Otherwise, it is the offset from UTC |
| (e.g. +01:00 or -07:00). Note that the offset from UTC is $(I not) |
| enough to uniquely identify the time zone. |
| |
| Time zone offsets will be in the form +HH:MM or -HH:MM. |
| +/ |
| string toISOExtString() @safe const nothrow |
| { |
| try |
| { |
| immutable adjustedTime = adjTime; |
| long hnsecs = adjustedTime; |
| |
| auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1; |
| |
| if (hnsecs < 0) |
| { |
| hnsecs += convert!("hours", "hnsecs")(24); |
| --days; |
| } |
| |
| auto hour = splitUnitsFromHNSecs!"hours"(hnsecs); |
| auto minute = splitUnitsFromHNSecs!"minutes"(hnsecs); |
| auto second = splitUnitsFromHNSecs!"seconds"(hnsecs); |
| |
| auto dateTime = DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour, |
| cast(int) minute, cast(int) second)); |
| auto fracSecStr = fracSecsToISOString(cast(int) hnsecs); |
| |
| if (_timezone is LocalTime()) |
| return dateTime.toISOExtString() ~ fracSecStr; |
| |
| if (_timezone is UTC()) |
| return dateTime.toISOExtString() ~ fracSecStr ~ "Z"; |
| |
| immutable utcOffset = dur!"hnsecs"(adjustedTime - stdTime); |
| |
| return format("%s%s%s", |
| dateTime.toISOExtString(), |
| fracSecStr, |
| SimpleTimeZone.toISOExtString(utcOffset)); |
| } |
| catch (Exception e) |
| assert(0, "format() threw."); |
| } |
| |
| /// |
| @safe unittest |
| { |
| import core.time : msecs, hnsecs; |
| import std.datetime.date : DateTime; |
| |
| assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toISOExtString() == |
| "2010-07-04T07:06:12"); |
| |
| assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(24)).toISOExtString() == |
| "1998-12-25T02:15:00.024"); |
| |
| assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toISOExtString() == |
| "0000-01-05T23:09:59"); |
| |
| assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toISOExtString() == |
| "-0004-01-05T00:00:02.052092"); |
| } |
| |
| @safe unittest |
| { |
| // Test A.D. |
| assert(SysTime(DateTime.init, UTC()).toISOExtString() == "0001-01-01T00:00:00Z"); |
| assert(SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1), UTC()).toISOExtString() == |
| "0001-01-01T00:00:00.0000001Z"); |
| |
| assert(SysTime(DateTime(9, 12, 4, 0, 0, 0)).toISOExtString() == "0009-12-04T00:00:00"); |
| assert(SysTime(DateTime(99, 12, 4, 5, 6, 12)).toISOExtString() == "0099-12-04T05:06:12"); |
| assert(SysTime(DateTime(999, 12, 4, 13, 44, 59)).toISOExtString() == "0999-12-04T13:44:59"); |
| assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59)).toISOExtString() == "9999-07-04T23:59:59"); |
| assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1)).toISOExtString() == "+10000-10-20T01:01:01"); |
| |
| assert(SysTime(DateTime(9, 12, 4, 0, 0, 0), msecs(42)).toISOExtString() == "0009-12-04T00:00:00.042"); |
| assert(SysTime(DateTime(99, 12, 4, 5, 6, 12), msecs(100)).toISOExtString() == "0099-12-04T05:06:12.1"); |
| assert(SysTime(DateTime(999, 12, 4, 13, 44, 59), usecs(45020)).toISOExtString() == "0999-12-04T13:44:59.04502"); |
| assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59), hnsecs(12)).toISOExtString() == "9999-07-04T23:59:59.0000012"); |
| assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1), hnsecs(507890)).toISOExtString() == |
| "+10000-10-20T01:01:01.050789"); |
| |
| assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12), |
| new immutable SimpleTimeZone(dur!"minutes"(-360))).toISOExtString() == |
| "2012-12-21T12:12:12-06:00"); |
| |
| assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12), |
| new immutable SimpleTimeZone(dur!"minutes"(420))).toISOExtString() == |
| "2012-12-21T12:12:12+07:00"); |
| |
| // Test B.C. |
| assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toISOExtString() == |
| "0000-12-31T23:59:59.9999999Z"); |
| assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1), UTC()).toISOExtString() == |
| "0000-12-31T23:59:59.0000001Z"); |
| assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), UTC()).toISOExtString() == "0000-12-31T23:59:59Z"); |
| |
| assert(SysTime(DateTime(0, 12, 4, 0, 12, 4)).toISOExtString() == "0000-12-04T00:12:04"); |
| assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0)).toISOExtString() == "-0009-12-04T00:00:00"); |
| assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12)).toISOExtString() == "-0099-12-04T05:06:12"); |
| assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59)).toISOExtString() == "-0999-12-04T13:44:59"); |
| assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59)).toISOExtString() == "-9999-07-04T23:59:59"); |
| assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1)).toISOExtString() == "-10000-10-20T01:01:01"); |
| |
| assert(SysTime(DateTime(0, 12, 4, 0, 0, 0), msecs(7)).toISOExtString() == "0000-12-04T00:00:00.007"); |
| assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0), msecs(42)).toISOExtString() == "-0009-12-04T00:00:00.042"); |
| assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12), msecs(100)).toISOExtString() == "-0099-12-04T05:06:12.1"); |
| assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59), usecs(45020)).toISOExtString() == |
| "-0999-12-04T13:44:59.04502"); |
| assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59), hnsecs(12)).toISOExtString() == |
| "-9999-07-04T23:59:59.0000012"); |
| assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1), hnsecs(507890)).toISOExtString() == |
| "-10000-10-20T01:01:01.050789"); |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(cast(TimeOfDay) cst != TimeOfDay.init); |
| //assert(cast(TimeOfDay) ist != TimeOfDay.init); |
| } |
| |
| /++ |
| Converts this $(LREF SysTime) to a string with the format |
| YYYY-Mon-DD HH:MM:SS.FFFFFFFTZ (where F is fractional seconds and TZ |
| is the time zone). |
| |
| Note that the number of digits in the fractional seconds varies with the |
| number of fractional seconds. It's a maximum of 7 (which would be |
| hnsecs), but only has as many as are necessary to hold the correct value |
| (so no trailing zeroes), and if there are no fractional seconds, then |
| there is no decimal point. |
| |
| If this $(LREF SysTime)'s time zone is |
| $(REF LocalTime,std,datetime,timezone), then TZ is empty. If its time |
| zone is $(D UTC), then it is "Z". Otherwise, it is the offset from UTC |
| (e.g. +01:00 or -07:00). Note that the offset from UTC is $(I not) |
| enough to uniquely identify the time zone. |
| |
| Time zone offsets will be in the form +HH:MM or -HH:MM. |
| +/ |
| string toSimpleString() @safe const nothrow |
| { |
| try |
| { |
| immutable adjustedTime = adjTime; |
| long hnsecs = adjustedTime; |
| |
| auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1; |
| |
| if (hnsecs < 0) |
| { |
| hnsecs += convert!("hours", "hnsecs")(24); |
| --days; |
| } |
| |
| auto hour = splitUnitsFromHNSecs!"hours"(hnsecs); |
| auto minute = splitUnitsFromHNSecs!"minutes"(hnsecs); |
| auto second = splitUnitsFromHNSecs!"seconds"(hnsecs); |
| |
| auto dateTime = DateTime(Date(cast(int) days), TimeOfDay(cast(int) hour, |
| cast(int) minute, cast(int) second)); |
| auto fracSecStr = fracSecsToISOString(cast(int) hnsecs); |
| |
| if (_timezone is LocalTime()) |
| return dateTime.toSimpleString() ~ fracSecStr; |
| |
| if (_timezone is UTC()) |
| return dateTime.toSimpleString() ~ fracSecStr ~ "Z"; |
| |
| immutable utcOffset = dur!"hnsecs"(adjustedTime - stdTime); |
| |
| return format("%s%s%s", |
| dateTime.toSimpleString(), |
| fracSecStr, |
| SimpleTimeZone.toISOExtString(utcOffset)); |
| } |
| catch (Exception e) |
| assert(0, "format() threw."); |
| } |
| |
| /// |
| @safe unittest |
| { |
| import core.time : msecs, hnsecs; |
| import std.datetime.date : DateTime; |
| |
| assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toSimpleString() == |
| "2010-Jul-04 07:06:12"); |
| |
| assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(24)).toSimpleString() == |
| "1998-Dec-25 02:15:00.024"); |
| |
| assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toSimpleString() == |
| "0000-Jan-05 23:09:59"); |
| |
| assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), hnsecs(520_920)).toSimpleString() == |
| "-0004-Jan-05 00:00:02.052092"); |
| } |
| |
| @safe unittest |
| { |
| // Test A.D. |
| assert(SysTime(DateTime.init, UTC()).toString() == "0001-Jan-01 00:00:00Z"); |
| assert(SysTime(DateTime(1, 1, 1, 0, 0, 0), hnsecs(1), UTC()).toString() == "0001-Jan-01 00:00:00.0000001Z"); |
| |
| assert(SysTime(DateTime(9, 12, 4, 0, 0, 0)).toSimpleString() == "0009-Dec-04 00:00:00"); |
| assert(SysTime(DateTime(99, 12, 4, 5, 6, 12)).toSimpleString() == "0099-Dec-04 05:06:12"); |
| assert(SysTime(DateTime(999, 12, 4, 13, 44, 59)).toSimpleString() == "0999-Dec-04 13:44:59"); |
| assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59)).toSimpleString() == "9999-Jul-04 23:59:59"); |
| assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1)).toSimpleString() == "+10000-Oct-20 01:01:01"); |
| |
| assert(SysTime(DateTime(9, 12, 4, 0, 0, 0), msecs(42)).toSimpleString() == "0009-Dec-04 00:00:00.042"); |
| assert(SysTime(DateTime(99, 12, 4, 5, 6, 12), msecs(100)).toSimpleString() == "0099-Dec-04 05:06:12.1"); |
| assert(SysTime(DateTime(999, 12, 4, 13, 44, 59), usecs(45020)).toSimpleString() == |
| "0999-Dec-04 13:44:59.04502"); |
| assert(SysTime(DateTime(9999, 7, 4, 23, 59, 59), hnsecs(12)).toSimpleString() == |
| "9999-Jul-04 23:59:59.0000012"); |
| assert(SysTime(DateTime(10000, 10, 20, 1, 1, 1), hnsecs(507890)).toSimpleString() == |
| "+10000-Oct-20 01:01:01.050789"); |
| |
| assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12), |
| new immutable SimpleTimeZone(dur!"minutes"(-360))).toSimpleString() == |
| "2012-Dec-21 12:12:12-06:00"); |
| |
| assert(SysTime(DateTime(2012, 12, 21, 12, 12, 12), |
| new immutable SimpleTimeZone(dur!"minutes"(420))).toSimpleString() == |
| "2012-Dec-21 12:12:12+07:00"); |
| |
| // Test B.C. |
| assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(9_999_999), UTC()).toSimpleString() == |
| "0000-Dec-31 23:59:59.9999999Z"); |
| assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), hnsecs(1), UTC()).toSimpleString() == |
| "0000-Dec-31 23:59:59.0000001Z"); |
| assert(SysTime(DateTime(0, 12, 31, 23, 59, 59), UTC()).toSimpleString() == "0000-Dec-31 23:59:59Z"); |
| |
| assert(SysTime(DateTime(0, 12, 4, 0, 12, 4)).toSimpleString() == "0000-Dec-04 00:12:04"); |
| assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0)).toSimpleString() == "-0009-Dec-04 00:00:00"); |
| assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12)).toSimpleString() == "-0099-Dec-04 05:06:12"); |
| assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59)).toSimpleString() == "-0999-Dec-04 13:44:59"); |
| assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59)).toSimpleString() == "-9999-Jul-04 23:59:59"); |
| assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1)).toSimpleString() == "-10000-Oct-20 01:01:01"); |
| |
| assert(SysTime(DateTime(0, 12, 4, 0, 0, 0), msecs(7)).toSimpleString() == "0000-Dec-04 00:00:00.007"); |
| assert(SysTime(DateTime(-9, 12, 4, 0, 0, 0), msecs(42)).toSimpleString() == "-0009-Dec-04 00:00:00.042"); |
| assert(SysTime(DateTime(-99, 12, 4, 5, 6, 12), msecs(100)).toSimpleString() == "-0099-Dec-04 05:06:12.1"); |
| assert(SysTime(DateTime(-999, 12, 4, 13, 44, 59), usecs(45020)).toSimpleString() == |
| "-0999-Dec-04 13:44:59.04502"); |
| assert(SysTime(DateTime(-9999, 7, 4, 23, 59, 59), hnsecs(12)).toSimpleString() == |
| "-9999-Jul-04 23:59:59.0000012"); |
| assert(SysTime(DateTime(-10000, 10, 20, 1, 1, 1), hnsecs(507890)).toSimpleString() == |
| "-10000-Oct-20 01:01:01.050789"); |
| |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(cast(TimeOfDay) cst != TimeOfDay.init); |
| //assert(cast(TimeOfDay) ist != TimeOfDay.init); |
| } |
| |
| |
| /++ |
| Converts this $(LREF SysTime) to a string. |
| |
| This function exists to make it easy to convert a $(LREF SysTime) to a |
| string for code that does not care what the exact format is - just that |
| it presents the information in a clear manner. It also makes it easy to |
| simply convert a $(LREF SysTime) to a string when using functions such |
| as `to!string`, `format`, or `writeln` which use toString to convert |
| user-defined types. So, it is unlikely that much code will call |
| toString directly. |
| |
| The format of the string is purposefully unspecified, and code that |
| cares about the format of the string should use `toISOString`, |
| `toISOExtString`, `toSimpleString`, or some other custom formatting |
| function that explicitly generates the format that the code needs. The |
| reason is that the code is then clear about what format it's using, |
| making it less error-prone to maintain the code and interact with other |
| software that consumes the generated strings. It's for this same reason |
| that $(LREF SysTime) has no `fromString` function, whereas it does have |
| `fromISOString`, `fromISOExtString`, and `fromSimpleString`. |
| |
| The format returned by toString may or may not change in the future. |
| +/ |
| string toString() @safe const nothrow |
| { |
| return toSimpleString(); |
| } |
| |
| @safe unittest |
| { |
| auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| //immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33)); |
| assert(st.toString()); |
| assert(cst.toString()); |
| //assert(ist.toString()); |
| } |
| |
| |
| /++ |
| Creates a $(LREF SysTime) from a string with the format |
| YYYYMMDDTHHMMSS.FFFFFFFTZ (where F is fractional seconds is the time |
| zone). Whitespace is stripped from the given string. |
| |
| The exact format is exactly as described in $(D toISOString) except that |
| trailing zeroes are permitted - including having fractional seconds with |
| all zeroes. However, a decimal point with nothing following it is |
| invalid. Also, while $(LREF toISOString) will never generate a string |
| with more than 7 digits in the fractional seconds (because that's the |
| limit with hecto-nanosecond precision), it will allow more than 7 digits |
| in order to read strings from other sources that have higher precision |
| (however, any digits beyond 7 will be truncated). |
| |
| If there is no time zone in the string, then |
| $(REF LocalTime,std,datetime,timezone) is used. If the time zone is "Z", |
| then $(D UTC) is used. Otherwise, a |
| $(REF SimpleTimeZone,std,datetime,timezone) which corresponds to the |
| given offset from UTC is used. To get the returned $(LREF SysTime) to be |
| a particular time zone, pass in that time zone and the $(LREF SysTime) |
| to be returned will be converted to that time zone (though it will still |
| be read in as whatever time zone is in its string). |
| |
| The accepted formats for time zone offsets are +HH, -HH, +HHMM, and |
| -HHMM. |
| |
| $(RED Warning: |
| Previously, $(LREF toISOString) did the same as |
| $(LREF toISOExtString) and generated +HH:MM or -HH:MM for the time |
| zone when it was not $(REF LocalTime,std,datetime,timezone) or |
| $(REF UTC,std,datetime,timezone), which is not in conformance with |
| ISO 8601 for the non-extended string format. This has now been |
| fixed. However, for now, fromISOString will continue to accept the |
| extended format for the time zone so that any code which has been |
| writing out the result of toISOString to read in later will continue |
| to work. The current behavior will be kept until July 2019 at which |
| point, fromISOString will be fixed to be standards compliant.) |
| |
| Params: |
| isoString = A string formatted in the ISO format for dates and times. |
| tz = The time zone to convert the given time to (no |
| conversion occurs if null). |
| |
| Throws: |
| $(REF DateTimeException,std,datetime,date) if the given string is |
| not in the ISO format or if the resulting $(LREF SysTime) would not |
| be valid. |
| +/ |
| static SysTime fromISOString(S)(in S isoString, immutable TimeZone tz = null) @safe |
| if (isSomeString!S) |
| { |
| import std.algorithm.searching : startsWith, find; |
| import std.conv : to; |
| import std.string : strip; |
| |
| auto dstr = to!dstring(strip(isoString)); |
| immutable skipFirst = dstr.startsWith('+', '-') != 0; |
| |
| auto found = (skipFirst ? dstr[1..$] : dstr).find('.', 'Z', '+', '-'); |
| auto dateTimeStr = dstr[0 .. $ - found[0].length]; |
| |
| dstring fracSecStr; |
| dstring zoneStr; |
| |
| if (found[1] != 0) |
| { |
| if (found[1] == 1) |
| { |
| auto foundTZ = found[0].find('Z', '+', '-'); |
| |
| if (foundTZ[1] != 0) |
| { |
| fracSecStr = found[0][0 .. $ - foundTZ[0].length]; |
| zoneStr = foundTZ[0]; |
| } |
| else |
| fracSecStr = found[0]; |
| } |
| else |
| zoneStr = found[0]; |
| } |
| |
| try |
| { |
| auto dateTime = DateTime.fromISOString(dateTimeStr); |
| auto fracSec = fracSecsFromISOString(fracSecStr); |
| Rebindable!(immutable TimeZone) parsedZone; |
| |
| if (zoneStr.empty) |
| parsedZone = LocalTime(); |
| else if (zoneStr == "Z") |
| parsedZone = UTC(); |
| else |
| { |
| try |
| parsedZone = SimpleTimeZone.fromISOString(zoneStr); |
| catch (DateTimeException dte) |
| parsedZone = SimpleTimeZone.fromISOExtString(zoneStr); |
| } |
| |
| auto retval = SysTime(dateTime, fracSec, parsedZone); |
| |
| if (tz !is null) |
| retval.timezone = tz; |
| |
| return retval; |
| } |
| catch (DateTimeException dte) |
| throw new DateTimeException(format("Invalid ISO String: %s", isoString)); |
| } |
| |
| /// |
| @safe unittest |
| { |
| import core.time : hours, msecs, usecs, hnsecs; |
| import std.datetime.date : DateTime; |
| import std.datetime.timezone : SimpleTimeZone, UTC; |
| |
| assert(SysTime.fromISOString("20100704T070612") == |
| SysTime(DateTime(2010, 7, 4, 7, 6, 12))); |
| |
| assert(SysTime.fromISOString("19981225T021500.007") == |
| SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(7))); |
| |
| assert(SysTime.fromISOString("00000105T230959.00002") == |
| SysTime(DateTime(0, 1, 5, 23, 9, 59), usecs(20))); |
| |
| assert(SysTime.fromISOString("20130207T043937.000050392") == |
| SysTime(DateTime(2013, 2, 7, 4, 39, 37), hnsecs(503))); |
| |
| assert(SysTime.fromISOString("-00040105T000002") == |
| SysTime(DateTime(-4, 1, 5, 0, 0, 2))); |
| |
| assert(SysTime.fromISOString(" 20100704T070612 ") == |
| SysTime(DateTime(2010, 7, 4, 7, 6, 12))); |
| |
| assert(SysTime.fromISOString("20100704T070612Z") == |
| SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC())); |
| |
| assert(SysTime.fromISOString("20100704T070612-0800") == |
| SysTime(DateTime(2010, 7, 4, 7, 6, 12), |
| new immutable SimpleTimeZone(hours(-8)))); |
| |
| assert(SysTime.fromISOString("20100704T070612+0800") == |
| SysTime(DateTime(2010, 7, 4, 7, 6, 12), |
| new immutable SimpleTimeZone(hours(8)))); |
| } |
| |
| @safe unittest |
| { |
| foreach (str; ["", "20100704000000", "20100704 000000", "20100704t000000", |
| "20100704T000000.", "20100704T000000.A", "20100704T000000.Z", |
| "20100704T000000.0000000A", "20100704T000000.00000000A", |
| "20100704T000000+", "20100704T000000-", "20100704T000000:", |
| "20100704T000000-:", "20100704T000000+:", "20100704T000000-1:", |
| "20100704T000000+1:", "20100704T000000+1:0", |
| "20100704T000000-12.00", "20100704T000000+12.00", |
| "20100704T000000-8", "20100704T000000+8", |
| "20100704T000000-800", "20100704T000000+800", |
| "20100704T000000-080", "20100704T000000+080", |
| "20100704T000000-2400", "20100704T000000+2400", |
| "20100704T000000-1260", "20100704T000000+1260", |
| "20100704T000000.0-8", "20100704T000000.0+8", |
| "20100704T000000.0-800", "20100704T000000.0+800", |
| "20100704T000000.0-080", "20100704T000000.0+080", |
| "20100704T000000.0-2400", "20100704T000000.0+2400", |
| "20100704T000000.0-1260", "20100704T000000.0+1260", |
| "20100704T000000-8:00", "20100704T000000+8:00", |
| "20100704T000000-08:0", "20100704T000000+08:0", |
| "20100704T000000-24:00", "20100704T000000+24:00", |
| "20100704T000000-12:60", "20100704T000000+12:60", |
| "20100704T000000.0-8:00", "20100704T000000.0+8:00", |
| "20100704T000000.0-08:0", "20100704T000000.0+08:0", |
| "20100704T000000.0-24:00", "20100704T000000.0+24:00", |
| "20100704T000000.0-12:60", "20100704T000000.0+12:60", |
| "2010-07-0400:00:00", "2010-07-04 00:00:00", |
| "2010-07-04t00:00:00", "2010-07-04T00:00:00.", |
| "2010-Jul-0400:00:00", "2010-Jul-04 00:00:00", "2010-Jul-04t00:00:00", |
| "2010-Jul-04T00:00:00", "2010-Jul-04 00:00:00.", |
| "2010-12-22T172201", "2010-Dec-22 17:22:01"]) |
| { |
| assertThrown!DateTimeException(SysTime.fromISOString(str), format("[%s]", str)); |
| } |
| |
| static void test(string str, SysTime st, size_t line = __LINE__) |
| { |
| if (SysTime.fromISOString(str) != st) |
| throw new AssertError("unittest failure", __FILE__, line); |
| } |
| |
| test("20101222T172201", SysTime(DateTime(2010, 12, 22, 17, 22, 01))); |
| test("19990706T123033", SysTime(DateTime(1999, 7, 6, 12, 30, 33))); |
| test("-19990706T123033", SysTime(DateTime(-1999, 7, 6, 12, 30, 33))); |
| test("+019990706T123033", SysTime(DateTime(1999, 7, 6, 12, 30, 33))); |
| test("19990706T123033 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33))); |
| test(" 19990706T123033", SysTime(DateTime(1999, 7, 6, 12, 30, 33))); |
| test(" 19990706T123033 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33))); |
| |
| test("19070707T121212.0", SysTime(DateTime(1907, 07, 07, 12, 12, 12))); |
| test("19070707T121212.0000000", SysTime(DateTime(1907, 07, 07, 12, 12, 12))); |
| test("19070707T121212.0000001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), hnsecs(1))); |
| test("20100704T000000.00000000", SysTime(Date(2010, 07, 04))); |
| test("20100704T000000.00000009", SysTime(Date(2010, 07, 04))); |
| test("20100704T000000.00000019", SysTime(DateTime(2010, 07, 04), hnsecs(1))); |
| test("19070707T121212.000001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), usecs(1))); |
| test("19070707T121212.0000010", SysTime(DateTime(1907, 07, 07, 12, 12, 12), usecs(1))); |
| test("19070707T121212.001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), msecs(1))); |
| test("19070707T121212.0010000", SysTime(DateTime(1907, 07, 07, 12, 12, 12), msecs(1))); |
| |
| auto west60 = new immutable SimpleTimeZone(hours(-1)); |
| auto west90 = new immutable SimpleTimeZone(minutes(-90)); |
| auto west480 = new immutable SimpleTimeZone(hours(-8)); |
| auto east60 = new immutable SimpleTimeZone(hours(1)); |
| auto east90 = new immutable SimpleTimeZone(minutes(90)); |
| auto east480 = new immutable SimpleTimeZone(hours(8)); |
| |
| test("20101222T172201Z", SysTime(DateTime(2010, 12, 22, 17, 22, 01), UTC())); |
| test("20101222T172201-0100", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60)); |
| test("20101222T172201-01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60)); |
| test("20101222T172201-0130", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west90)); |
| test("20101222T172201-0800", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west480)); |
| test("20101222T172201+0100", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60)); |
| test("20101222T172201+01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60)); |
| test("20101222T172201+0130", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90)); |
| test("20101222T172201+0800", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east480)); |
| |
| test("20101103T065106.57159Z", SysTime(DateTime(2010, 11, 3, 6, 51, 6), hnsecs(5715900), UTC())); |
| test("20101222T172201.23412Z", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_341_200), UTC())); |
| test("20101222T172201.23112-0100", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_311_200), west60)); |
| test("20101222T172201.45-01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), west60)); |
| test("20101222T172201.1-0130", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_000_000), west90)); |
| test("20101222T172201.55-0800", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(5_500_000), west480)); |
| test("20101222T172201.1234567+0100", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_234_567), east60)); |
| test("20101222T172201.0+01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60)); |
| test("20101222T172201.0000000+0130", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90)); |
| test("20101222T172201.45+0800", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), east480)); |
| |
| // @@@DEPRECATED_2019-07@@@ |
| // This isn't deprecated per se, but that text will make it so that it |
| // pops up when deprecations are moved along around July 2019. At that |
| // time, we will update fromISOString so that it is conformant with ISO |
| // 8601, and it will no longer accept ISO extended time zones (it does |
| // currently because of issue #15654 - toISOString used to incorrectly |
| // use the ISO extended time zone format). These tests will then start |
| // failing will need to be updated accordingly. Also, the notes about |
| // this issue in toISOString and fromISOString's documentation will need |
| // to be removed. |
| test("20101222T172201-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60)); |
| test("20101222T172201-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west90)); |
| test("20101222T172201-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west480)); |
| test("20101222T172201+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60)); |
| test("20101222T172201+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90)); |
| test("20101222T172201+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east480)); |
| |
| test("20101222T172201.23112-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_311_200), west60)); |
| test("20101222T172201.1-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_000_000), west90)); |
| test("20101222T172201.55-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(5_500_000), west480)); |
| test("20101222T172201.1234567+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_234_567), east60)); |
| test("20101222T172201.0000000+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90)); |
| test("20101222T172201.45+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), east480)); |
| } |
| |
| // bug# 17801 |
| @safe unittest |
| { |
| import std.conv : to; |
| import std.meta : AliasSeq; |
| foreach (C; AliasSeq!(char, wchar, dchar)) |
| { |
| foreach (S; AliasSeq!(C[], const(C)[], immutable(C)[])) |
| { |
| assert(SysTime.fromISOString(to!S("20121221T141516Z")) == |
| SysTime(DateTime(2012, 12, 21, 14, 15, 16), UTC())); |
| } |
| } |
| } |
| |
| |
| /++ |
| Creates a $(LREF SysTime) from a string with the format |
| YYYY-MM-DDTHH:MM:SS.FFFFFFFTZ (where F is fractional seconds is the |
| time zone). Whitespace is stripped from the given string. |
| |
| The exact format is exactly as described in $(D toISOExtString) |
| except that trailing zeroes are permitted - including having fractional |
| seconds with all zeroes. However, a decimal point with nothing following |
| it is invalid. Also, while $(LREF toISOExtString) will never generate a |
| string with more than 7 digits in the fractional seconds (because that's |
| the limit with hecto-nanosecond precision), it will allow more than 7 |
| digits in order to read strings from other sources that have higher |
| precision (however, any digits beyond 7 will be truncated). |
| |
| If there is no time zone in the string, then |
| $(REF LocalTime,std,datetime,timezone) is used. If the time zone is "Z", |
| then $(D UTC) is used. Otherwise, a |
| $(REF SimpleTimeZone,std,datetime,timezone) which corresponds to the |
| given offset from UTC is used. To get the returned $(LREF SysTime) to be |
| a particular time zone, pass in that time zone and the $(LREF SysTime) |
| to be returned will be converted to that time zone (though it will still |
| be read in as whatever time zone is in its string). |
| |
| The accepted formats for time zone offsets are +HH, -HH, +HH:MM, and |
| -HH:MM. |
| |
| Params: |
| isoExtString = A string formatted in the ISO Extended format for |
| dates and times. |
| tz = The time zone to convert the given time to (no |
| conversion occurs if null). |
| |
| Throws: |
| $(REF DateTimeException,std,datetime,date) if the given string is |
| not in the ISO format or if the resulting $(LREF SysTime) would not |
| be valid. |
| +/ |
| static SysTime fromISOExtString(S)(in S isoExtString, immutable TimeZone tz = null) @safe |
| if (isSomeString!(S)) |
| { |
| import std.algorithm.searching : countUntil, find; |
| import std.conv : to; |
| import std.string : strip; |
| |
| auto dstr = to!dstring(strip(isoExtString)); |
| |
| auto tIndex = dstr.countUntil('T'); |
| enforce(tIndex != -1, new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString))); |
| |
| auto found = dstr[tIndex + 1 .. $].find('.', 'Z', '+', '-'); |
| auto dateTimeStr = dstr[0 .. $ - found[0].length]; |
| |
| dstring fracSecStr; |
| dstring zoneStr; |
| |
| if (found[1] != 0) |
| { |
| if (found[1] == 1) |
| { |
| auto foundTZ = found[0].find('Z', '+', '-'); |
| |
| if (foundTZ[1] != 0) |
| { |
| fracSecStr = found[0][0 .. $ - foundTZ[0].length]; |
| zoneStr = foundTZ[0]; |
| } |
| else |
| fracSecStr = found[0]; |
| } |
| else |
| zoneStr = found[0]; |
| } |
| |
| try |
| { |
| auto dateTime = DateTime.fromISOExtString(dateTimeStr); |
| auto fracSec = fracSecsFromISOString(fracSecStr); |
| Rebindable!(immutable TimeZone) parsedZone; |
| |
| if (zoneStr.empty) |
| parsedZone = LocalTime(); |
| else if (zoneStr == "Z") |
| parsedZone = UTC(); |
| else |
| parsedZone = SimpleTimeZone.fromISOExtString(zoneStr); |
| |
| auto retval = SysTime(dateTime, fracSec, parsedZone); |
| |
| if (tz !is null) |
| retval.timezone = tz; |
| |
| return retval; |
| } |
| catch (DateTimeException dte) |
| throw new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)); |
| } |
| |
| /// |
| @safe unittest |
| { |
| import core.time : hours, msecs, usecs, hnsecs; |
| import std.datetime.date : DateTime; |
| import std.datetime.timezone : SimpleTimeZone, UTC; |
| |
| assert(SysTime.fromISOExtString("2010-07-04T07:06:12") == |
| SysTime(DateTime(2010, 7, 4, 7, 6, 12))); |
| |
| assert(SysTime.fromISOExtString("1998-12-25T02:15:00.007") == |
| SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(7))); |
| |
| assert(SysTime.fromISOExtString("0000-01-05T23:09:59.00002") == |
| SysTime(DateTime(0, 1, 5, 23, 9, 59), usecs(20))); |
| |
| assert(SysTime.fromISOExtString("2013-02-07T04:39:37.000050392") == |
| SysTime(DateTime(2013, 2, 7, 4, 39, 37), hnsecs(503))); |
| |
| assert(SysTime.fromISOExtString("-0004-01-05T00:00:02") == |
| SysTime(DateTime(-4, 1, 5, 0, 0, 2))); |
| |
| assert(SysTime.fromISOExtString(" 2010-07-04T07:06:12 ") == |
| SysTime(DateTime(2010, 7, 4, 7, 6, 12))); |
| |
| assert(SysTime.fromISOExtString("2010-07-04T07:06:12Z") == |
| SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC())); |
| |
| assert(SysTime.fromISOExtString("2010-07-04T07:06:12-08:00") == |
| SysTime(DateTime(2010, 7, 4, 7, 6, 12), |
| new immutable SimpleTimeZone(hours(-8)))); |
| assert(SysTime.fromISOExtString("2010-07-04T07:06:12+08:00") == |
| SysTime(DateTime(2010, 7, 4, 7, 6, 12), |
| new immutable SimpleTimeZone(hours(8)))); |
| } |
| |
| @safe unittest |
| { |
| foreach (str; ["", "20100704000000", "20100704 000000", |
| "20100704t000000", "20100704T000000.", "20100704T000000.0", |
| "2010-07:0400:00:00", "2010-07-04 00:00:00", |
| "2010-07-04 00:00:00", "2010-07-04t00:00:00", |
| "2010-07-04T00:00:00.", "2010-07-04T00:00:00.A", "2010-07-04T00:00:00.Z", |
| "2010-07-04T00:00:00.0000000A", "2010-07-04T00:00:00.00000000A", |
| "2010-07-04T00:00:00+", "2010-07-04T00:00:00-", |
| "2010-07-04T00:00:00:", "2010-07-04T00:00:00-:", "2010-07-04T00:00:00+:", |
| "2010-07-04T00:00:00-1:", "2010-07-04T00:00:00+1:", "2010-07-04T00:00:00+1:0", |
| "2010-07-04T00:00:00-12.00", "2010-07-04T00:00:00+12.00", |
| "2010-07-04T00:00:00-8", "2010-07-04T00:00:00+8", |
| "20100704T000000-800", "20100704T000000+800", |
| "20100704T000000-080", "20100704T000000+080", |
| "20100704T000000-2400", "20100704T000000+2400", |
| "20100704T000000-1260", "20100704T000000+1260", |
| "20100704T000000.0-800", "20100704T000000.0+800", |
| "20100704T000000.0-8", "20100704T000000.0+8", |
| "20100704T000000.0-080", "20100704T000000.0+080", |
| "20100704T000000.0-2400", "20100704T000000.0+2400", |
| "20100704T000000.0-1260", "20100704T000000.0+1260", |
| "2010-07-04T00:00:00-8:00", "2010-07-04T00:00:00+8:00", |
| "2010-07-04T00:00:00-24:00", "2010-07-04T00:00:00+24:00", |
| "2010-07-04T00:00:00-12:60", "2010-07-04T00:00:00+12:60", |
| "2010-07-04T00:00:00.0-8:00", "2010-07-04T00:00:00.0+8:00", |
| "2010-07-04T00:00:00.0-8", "2010-07-04T00:00:00.0+8", |
| "2010-07-04T00:00:00.0-24:00", "2010-07-04T00:00:00.0+24:00", |
| "2010-07-04T00:00:00.0-12:60", "2010-07-04T00:00:00.0+12:60", |
| "2010-Jul-0400:00:00", "2010-Jul-04t00:00:00", |
| "2010-Jul-04 00:00:00.", "2010-Jul-04 00:00:00.0", |
| "20101222T172201", "2010-Dec-22 17:22:01"]) |
| { |
| assertThrown!DateTimeException(SysTime.fromISOExtString(str), format("[%s]", str)); |
| } |
| |
| static void test(string str, SysTime st, size_t line = __LINE__) |
| { |
| if (SysTime.fromISOExtString(str) != st) |
| throw new AssertError("unittest failure", __FILE__, line); |
| } |
| |
| test("2010-12-22T17:22:01", SysTime(DateTime(2010, 12, 22, 17, 22, 01))); |
| test("1999-07-06T12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33))); |
| test("-1999-07-06T12:30:33", SysTime(DateTime(-1999, 7, 6, 12, 30, 33))); |
| test("+01999-07-06T12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33))); |
| test("1999-07-06T12:30:33 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33))); |
| test(" 1999-07-06T12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33))); |
| test(" 1999-07-06T12:30:33 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33))); |
| |
| test("1907-07-07T12:12:12.0", SysTime(DateTime(1907, 07, 07, 12, 12, 12))); |
| test("1907-07-07T12:12:12.0000000", SysTime(DateTime(1907, 07, 07, 12, 12, 12))); |
| test("1907-07-07T12:12:12.0000001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), hnsecs(1))); |
| test("2010-07-04T00:00:00.00000000", SysTime(Date(2010, 07, 04))); |
| test("2010-07-04T00:00:00.00000009", SysTime(Date(2010, 07, 04))); |
| test("2010-07-04T00:00:00.00000019", SysTime(DateTime(2010, 07, 04), hnsecs(1))); |
| test("1907-07-07T12:12:12.000001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), usecs(1))); |
| test("1907-07-07T12:12:12.0000010", SysTime(DateTime(1907, 07, 07, 12, 12, 12), usecs(1))); |
| test("1907-07-07T12:12:12.001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), msecs(1))); |
| test("1907-07-07T12:12:12.0010000", SysTime(DateTime(1907, 07, 07, 12, 12, 12), msecs(1))); |
| |
| auto west60 = new immutable SimpleTimeZone(hours(-1)); |
| auto west90 = new immutable SimpleTimeZone(minutes(-90)); |
| auto west480 = new immutable SimpleTimeZone(hours(-8)); |
| auto east60 = new immutable SimpleTimeZone(hours(1)); |
| auto east90 = new immutable SimpleTimeZone(minutes(90)); |
| auto east480 = new immutable SimpleTimeZone(hours(8)); |
| |
| test("2010-12-22T17:22:01Z", SysTime(DateTime(2010, 12, 22, 17, 22, 01), UTC())); |
| test("2010-12-22T17:22:01-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60)); |
| test("2010-12-22T17:22:01-01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60)); |
| test("2010-12-22T17:22:01-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west90)); |
| test("2010-12-22T17:22:01-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west480)); |
| test("2010-12-22T17:22:01+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60)); |
| test("2010-12-22T17:22:01+01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60)); |
| test("2010-12-22T17:22:01+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90)); |
| test("2010-12-22T17:22:01+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east480)); |
| |
| test("2010-11-03T06:51:06.57159Z", SysTime(DateTime(2010, 11, 3, 6, 51, 6), hnsecs(5715900), UTC())); |
| test("2010-12-22T17:22:01.23412Z", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_341_200), UTC())); |
| test("2010-12-22T17:22:01.23112-01:00", |
| SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_311_200), west60)); |
| test("2010-12-22T17:22:01.45-01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), west60)); |
| test("2010-12-22T17:22:01.1-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_000_000), west90)); |
| test("2010-12-22T17:22:01.55-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(5_500_000), west480)); |
| test("2010-12-22T17:22:01.1234567+01:00", |
| SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_234_567), east60)); |
| test("2010-12-22T17:22:01.0+01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60)); |
| test("2010-12-22T17:22:01.0000000+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90)); |
| test("2010-12-22T17:22:01.45+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), east480)); |
| } |
| |
| // bug# 17801 |
| @safe unittest |
| { |
| import std.conv : to; |
| import std.meta : AliasSeq; |
| foreach (C; AliasSeq!(char, wchar, dchar)) |
| { |
| foreach (S; AliasSeq!(C[], const(C)[], immutable(C)[])) |
| { |
| assert(SysTime.fromISOExtString(to!S("2012-12-21T14:15:16Z")) == |
| SysTime(DateTime(2012, 12, 21, 14, 15, 16), UTC())); |
| } |
| } |
| } |
| |
| |
| /++ |
| Creates a $(LREF SysTime) from a string with the format |
| YYYY-MM-DD HH:MM:SS.FFFFFFFTZ (where F is fractional seconds is the |
| time zone). Whitespace is stripped from the given string. |
| |
| The exact format is exactly as described in $(D toSimpleString) except |
| that trailing zeroes are permitted - including having fractional seconds |
| with all zeroes. However, a decimal point with nothing following it is |
| invalid. Also, while $(LREF toSimpleString) will never generate a |
| string with more than 7 digits in the fractional seconds (because that's |
| the limit with hecto-nanosecond precision), it will allow more than 7 |
| digits in order to read strings from other sources that have higher |
| precision (however, any digits beyond 7 will be truncated). |
| |
| If there is no time zone in the string, then |
| $(REF LocalTime,std,datetime,timezone) is used. If the time zone is "Z", |
| then $(D UTC) is used. Otherwise, a |
| $(REF SimpleTimeZone,std,datetime,timezone) which corresponds to the |
| given offset from UTC is used. To get the returned $(LREF SysTime) to be |
| a particular time zone, pass in that time zone and the $(LREF SysTime) |
| to be returned will be converted to that time zone (though it will still |
| be read in as whatever time zone is in its string). |
| |
| The accepted formats for time zone offsets are +HH, -HH, +HH:MM, and |
| -HH:MM. |
| |
| Params: |
| simpleString = A string formatted in the way that |
| $(D toSimpleString) formats dates and times. |
| tz = The time zone to convert the given time to (no |
| conversion occurs if null). |
| |
| Throws: |
| $(REF DateTimeException,std,datetime,date) if the given string is |
| not in the ISO format or if the resulting $(LREF SysTime) would not |
| be valid. |
| +/ |
| static SysTime fromSimpleString(S)(in S simpleString, immutable TimeZone tz = null) @safe |
| if (isSomeString!(S)) |
| { |
| import std.algorithm.searching : countUntil, find; |
| import std.conv : to; |
| import std.string : strip; |
| |
| auto dstr = to!dstring(strip(simpleString)); |
| |
| auto spaceIndex = dstr.countUntil(' '); |
| enforce(spaceIndex != -1, new DateTimeException(format("Invalid Simple String: %s", simpleString))); |
| |
| auto found = dstr[spaceIndex + 1 .. $].find('.', 'Z', '+', '-'); |
| auto dateTimeStr = dstr[0 .. $ - found[0].length]; |
| |
| dstring fracSecStr; |
| dstring zoneStr; |
| |
| if (found[1] != 0) |
| { |
| if (found[1] == 1) |
| { |
| auto foundTZ = found[0].find('Z', '+', '-'); |
| |
| if (foundTZ[1] != 0) |
| { |
| fracSecStr = found[0][0 .. $ - foundTZ[0].length]; |
| zoneStr = foundTZ[0]; |
| } |
| else |
| fracSecStr = found[0]; |
| } |
| else |
| zoneStr = found[0]; |
| } |
| |
| try |
| { |
| auto dateTime = DateTime.fromSimpleString(dateTimeStr); |
| auto fracSec = fracSecsFromISOString(fracSecStr); |
| Rebindable!(immutable TimeZone) parsedZone; |
| |
| if (zoneStr.empty) |
| parsedZone = LocalTime(); |
| else if (zoneStr == "Z") |
| parsedZone = UTC(); |
| else |
| parsedZone = SimpleTimeZone.fromISOExtString(zoneStr); |
| |
| auto retval = SysTime(dateTime, fracSec, parsedZone); |
| |
| if (tz !is null) |
| retval.timezone = tz; |
| |
| return retval; |
| } |
| catch (DateTimeException dte) |
| throw new DateTimeException(format("Invalid Simple String: %s", simpleString)); |
| } |
| |
| /// |
| @safe unittest |
| { |
| import core.time : hours, msecs, usecs, hnsecs; |
| import std.datetime.date : DateTime; |
| import std.datetime.timezone : SimpleTimeZone, UTC; |
| |
| assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12") == |
| SysTime(DateTime(2010, 7, 4, 7, 6, 12))); |
| |
| assert(SysTime.fromSimpleString("1998-Dec-25 02:15:00.007") == |
| SysTime(DateTime(1998, 12, 25, 2, 15, 0), msecs(7))); |
| |
| assert(SysTime.fromSimpleString("0000-Jan-05 23:09:59.00002") == |
| SysTime(DateTime(0, 1, 5, 23, 9, 59), usecs(20))); |
| |
| assert(SysTime.fromSimpleString("2013-Feb-07 04:39:37.000050392") == |
| SysTime(DateTime(2013, 2, 7, 4, 39, 37), hnsecs(503))); |
| |
| assert(SysTime.fromSimpleString("-0004-Jan-05 00:00:02") == |
| SysTime(DateTime(-4, 1, 5, 0, 0, 2))); |
| |
| assert(SysTime.fromSimpleString(" 2010-Jul-04 07:06:12 ") == |
| SysTime(DateTime(2010, 7, 4, 7, 6, 12))); |
| |
| assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12Z") == |
| SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC())); |
| |
| assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12-08:00") == |
| SysTime(DateTime(2010, 7, 4, 7, 6, 12), |
| new immutable SimpleTimeZone(hours(-8)))); |
| |
| assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12+08:00") == |
| SysTime(DateTime(2010, 7, 4, 7, 6, 12), |
| new immutable SimpleTimeZone(hours(8)))); |
| } |
| |
| @safe unittest |
| { |
| foreach (str; ["", "20100704000000", "20100704 000000", |
| "20100704t000000", "20100704T000000.", "20100704T000000.0", |
| "2010-07-0400:00:00", "2010-07-04 00:00:00", "2010-07-04t00:00:00", |
| "2010-07-04T00:00:00.", "2010-07-04T00:00:00.0", |
| "2010-Jul-0400:00:00", "2010-Jul-04t00:00:00", "2010-Jul-04T00:00:00", |
| "2010-Jul-04 00:00:00.", "2010-Jul-04 00:00:00.A", "2010-Jul-04 00:00:00.Z", |
| "2010-Jul-04 00:00:00.0000000A", "2010-Jul-04 00:00:00.00000000A", |
| "2010-Jul-04 00:00:00+", "2010-Jul-04 00:00:00-", |
| "2010-Jul-04 00:00:00:", "2010-Jul-04 00:00:00-:", |
| "2010-Jul-04 00:00:00+:", "2010-Jul-04 00:00:00-1:", |
| "2010-Jul-04 00:00:00+1:", "2010-Jul-04 00:00:00+1:0", |
| "2010-Jul-04 00:00:00-12.00", "2010-Jul-04 00:00:00+12.00", |
| "2010-Jul-04 00:00:00-8", "2010-Jul-04 00:00:00+8", |
| "20100704T000000-800", "20100704T000000+800", |
| "20100704T000000-080", "20100704T000000+080", |
| "20100704T000000-2400", "20100704T000000+2400", |
| "20100704T000000-1260", "20100704T000000+1260", |
| "20100704T000000.0-800", "20100704T000000.0+800", |
| "20100704T000000.0-8", "20100704T000000.0+8", |
| "20100704T000000.0-080", "20100704T000000.0+080", |
| "20100704T000000.0-2400", "20100704T000000.0+2400", |
| "20100704T000000.0-1260", "20100704T000000.0+1260", |
| "2010-Jul-04 00:00:00-8:00", "2010-Jul-04 00:00:00+8:00", |
| "2010-Jul-04 00:00:00-08:0", "2010-Jul-04 00:00:00+08:0", |
| "2010-Jul-04 00:00:00-24:00", "2010-Jul-04 00:00:00+24:00", |
| "2010-Jul-04 00:00:00-12:60", "2010-Jul-04 00:00:00+24:60", |
| "2010-Jul-04 00:00:00.0-8:00", "2010-Jul-04 00:00:00+8:00", |
| "2010-Jul-04 00:00:00.0-8", "2010-Jul-04 00:00:00.0+8", |
| "2010-Jul-04 00:00:00.0-08:0", "2010-Jul-04 00:00:00.0+08:0", |
| "2010-Jul-04 00:00:00.0-24:00", "2010-Jul-04 00:00:00.0+24:00", |
| "2010-Jul-04 00:00:00.0-12:60", "2010-Jul-04 00:00:00.0+24:60", |
| "20101222T172201", "2010-12-22T172201"]) |
| { |
| assertThrown!DateTimeException(SysTime.fromSimpleString(str), format("[%s]", str)); |
| } |
| |
| static void test(string str, SysTime st, size_t line = __LINE__) |
| { |
| if (SysTime.fromSimpleString(str) != st) |
| throw new AssertError("unittest failure", __FILE__, line); |
| } |
| |
| test("2010-Dec-22 17:22:01", SysTime(DateTime(2010, 12, 22, 17, 22, 01))); |
| test("1999-Jul-06 12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33))); |
| test("-1999-Jul-06 12:30:33", SysTime(DateTime(-1999, 7, 6, 12, 30, 33))); |
| test("+01999-Jul-06 12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33))); |
| test("1999-Jul-06 12:30:33 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33))); |
| test(" 1999-Jul-06 12:30:33", SysTime(DateTime(1999, 7, 6, 12, 30, 33))); |
| test(" 1999-Jul-06 12:30:33 ", SysTime(DateTime(1999, 7, 6, 12, 30, 33))); |
| |
| test("1907-Jul-07 12:12:12.0", SysTime(DateTime(1907, 07, 07, 12, 12, 12))); |
| test("1907-Jul-07 12:12:12.0000000", SysTime(DateTime(1907, 07, 07, 12, 12, 12))); |
| test("2010-Jul-04 00:00:00.00000000", SysTime(Date(2010, 07, 04))); |
| test("2010-Jul-04 00:00:00.00000009", SysTime(Date(2010, 07, 04))); |
| test("2010-Jul-04 00:00:00.00000019", SysTime(DateTime(2010, 07, 04), hnsecs(1))); |
| test("1907-Jul-07 12:12:12.0000001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), hnsecs(1))); |
| test("1907-Jul-07 12:12:12.000001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), usecs(1))); |
| test("1907-Jul-07 12:12:12.0000010", SysTime(DateTime(1907, 07, 07, 12, 12, 12), usecs(1))); |
| test("1907-Jul-07 12:12:12.001", SysTime(DateTime(1907, 07, 07, 12, 12, 12), msecs(1))); |
| test("1907-Jul-07 12:12:12.0010000", SysTime(DateTime(1907, 07, 07, 12, 12, 12), msecs(1))); |
| |
| auto west60 = new immutable SimpleTimeZone(hours(-1)); |
| auto west90 = new immutable SimpleTimeZone(minutes(-90)); |
| auto west480 = new immutable SimpleTimeZone(hours(-8)); |
| auto east60 = new immutable SimpleTimeZone(hours(1)); |
| auto east90 = new immutable SimpleTimeZone(minutes(90)); |
| auto east480 = new immutable SimpleTimeZone(hours(8)); |
| |
| test("2010-Dec-22 17:22:01Z", SysTime(DateTime(2010, 12, 22, 17, 22, 01), UTC())); |
| test("2010-Dec-22 17:22:01-01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60)); |
| test("2010-Dec-22 17:22:01-01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west60)); |
| test("2010-Dec-22 17:22:01-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west90)); |
| test("2010-Dec-22 17:22:01-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), west480)); |
| test("2010-Dec-22 17:22:01+01:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60)); |
| test("2010-Dec-22 17:22:01+01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60)); |
| test("2010-Dec-22 17:22:01+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90)); |
| test("2010-Dec-22 17:22:01+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east480)); |
| |
| test("2010-Nov-03 06:51:06.57159Z", SysTime(DateTime(2010, 11, 3, 6, 51, 6), hnsecs(5715900), UTC())); |
| test("2010-Dec-22 17:22:01.23412Z", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_341_200), UTC())); |
| test("2010-Dec-22 17:22:01.23112-01:00", |
| SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(2_311_200), west60)); |
| test("2010-Dec-22 17:22:01.45-01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), west60)); |
| test("2010-Dec-22 17:22:01.1-01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_000_000), west90)); |
| test("2010-Dec-22 17:22:01.55-08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(5_500_000), west480)); |
| test("2010-Dec-22 17:22:01.1234567+01:00", |
| SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(1_234_567), east60)); |
| test("2010-Dec-22 17:22:01.0+01", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east60)); |
| test("2010-Dec-22 17:22:01.0000000+01:30", SysTime(DateTime(2010, 12, 22, 17, 22, 01), east90)); |
| test("2010-Dec-22 17:22:01.45+08:00", SysTime(DateTime(2010, 12, 22, 17, 22, 01), hnsecs(4_500_000), east480)); |
| } |
| |
| // bug# 17801 |
| @safe unittest |
| { |
| import std.conv : to; |
| import std.meta : AliasSeq; |
| foreach (C; AliasSeq!(char, wchar, dchar)) |
| { |
| foreach (S; AliasSeq!(C[], const(C)[], immutable(C)[])) |
| { |
| assert(SysTime.fromSimpleString(to!S("2012-Dec-21 14:15:16Z")) == |
| SysTime(DateTime(2012, 12, 21, 14, 15, 16), UTC())); |
| } |
| } |
| } |
| |
| |
| /++ |
| Returns the $(LREF SysTime) farthest in the past which is representable |
| by $(LREF SysTime). |
| |
| The $(LREF SysTime) which is returned is in UTC. |
| +/ |
| @property static SysTime min() @safe pure nothrow |
| { |
| return SysTime(long.min, UTC()); |
| } |
| |
| @safe unittest |
| { |
| assert(SysTime.min.year < 0); |
| assert(SysTime.min < SysTime.max); |
| } |
| |
| |
| /++ |
| Returns the $(LREF SysTime) farthest in the future which is representable |
| by $(LREF SysTime). |
| |
| The $(LREF SysTime) which is returned is in UTC. |
| +/ |
| @property static SysTime max() @safe pure nothrow |
| { |
| return SysTime(long.max, UTC()); |
| } |
| |
| @safe unittest |
| { |
| assert(SysTime.max.year > 0); |
| assert(SysTime.max > SysTime.min); |
| } |
| |
| |
| private: |
| |
| /+ |
| Returns $(D stdTime) converted to $(LREF SysTime)'s time zone. |
| +/ |
| @property long adjTime() @safe const nothrow |
| { |
| return _timezone.utcToTZ(_stdTime); |
| } |
| |
| |
| /+ |
| Converts the given hnsecs from $(LREF SysTime)'s time zone to std time. |
| +/ |
| @property void adjTime(long adjTime) @safe nothrow |
| { |
| _stdTime = _timezone.tzToUTC(adjTime); |
| } |
| |
| |
| // Commented out due to bug http://d.puremagic.com/issues/show_bug.cgi?id=5058 |
| /+ |
| invariant() |
| { |
| assert(_timezone !is null, "Invariant Failure: timezone is null. Were you foolish enough to use " ~ |
| "SysTime.init? (since timezone for SysTime.init can't be set at compile time)."); |
| } |
| +/ |
| |
| |
| long _stdTime; |
| Rebindable!(immutable TimeZone) _timezone; |
| } |
| |
| |
| /++ |
| Converts from unix time (which uses midnight, January 1st, 1970 UTC as its |
| epoch and seconds as its units) to "std time" (which uses midnight, |
| January 1st, 1 A.D. UTC and hnsecs as its units). |
| |
| The C standard does not specify the representation of time_t, so it is |
| implementation defined. On POSIX systems, unix time is equivalent to |
| time_t, but that's not necessarily true on other systems (e.g. it is |
| not true for the Digital Mars C runtime). So, be careful when using unix |
| time with C functions on non-POSIX systems. |
| |
| "std time"'s epoch is based on the Proleptic Gregorian Calendar per ISO |
| 8601 and is what $(LREF SysTime) uses internally. However, holding the time |
| as an integer in hnescs since that epoch technically isn't actually part of |
| the standard, much as it's based on it, so the name "std time" isn't |
| particularly good, but there isn't an official name for it. C# uses "ticks" |
| for the same thing, but they aren't actually clock ticks, and the term |
| "ticks" $(I is) used for actual clock ticks for $(REF MonoTime, core,time), |
| so it didn't make sense to use the term ticks here. So, for better or worse, |
| std.datetime uses the term "std time" for this. |
| |
| Params: |
| unixTime = The unix time to convert. |
| |
| See_Also: |
| SysTime.fromUnixTime |
| +/ |
| long unixTimeToStdTime(long unixTime) @safe pure nothrow |
| { |
| return 621_355_968_000_000_000L + convert!("seconds", "hnsecs")(unixTime); |
| } |
| |
| /// |
| @safe unittest |
| { |
| import std.datetime.date : DateTime; |
| import std.datetime.timezone : UTC; |
| |
| // Midnight, January 1st, 1970 |
| assert(unixTimeToStdTime(0) == 621_355_968_000_000_000L); |
| assert(SysTime(unixTimeToStdTime(0)) == |
| SysTime(DateTime(1970, 1, 1), UTC())); |
| |
| assert(unixTimeToStdTime(int.max) == 642_830_804_470_000_000L); |
| assert(SysTime(unixTimeToStdTime(int.max)) == |
| SysTime(DateTime(2038, 1, 19, 3, 14, 07), UTC())); |
| |
| assert(unixTimeToStdTime(-127_127) == 621_354_696_730_000_000L); |
| assert(SysTime(unixTimeToStdTime(-127_127)) == |
| SysTime(DateTime(1969, 12, 30, 12, 41, 13), UTC())); |
| } |
| |
| @safe unittest |
| { |
| // Midnight, January 2nd, 1970 |
| assert(unixTimeToStdTime(86_400) == 621_355_968_000_000_000L + 864_000_000_000L); |
| // Midnight, December 31st, 1969 |
| assert(unixTimeToStdTime(-86_400) == 621_355_968_000_000_000L - 864_000_000_000L); |
| |
| assert(unixTimeToStdTime(0) == (Date(1970, 1, 1) - Date(1, 1, 1)).total!"hnsecs"); |
| assert(unixTimeToStdTime(0) == (DateTime(1970, 1, 1) - DateTime(1, 1, 1)).total!"hnsecs"); |
| |
| foreach (dt; [DateTime(2010, 11, 1, 19, 5, 22), DateTime(1952, 7, 6, 2, 17, 9)]) |
| assert(unixTimeToStdTime((dt - DateTime(1970, 1, 1)).total!"seconds") == (dt - DateTime.init).total!"hnsecs"); |
| } |
| |
| |
| /++ |
| Converts std time (which uses midnight, January 1st, 1 A.D. UTC as its epoch |
| and hnsecs as its units) to unix time (which uses midnight, January 1st, |
| 1970 UTC as its epoch and seconds as its units). |
| |
| The C standard does not specify the representation of time_t, so it is |
| implementation defined. On POSIX systems, unix time is equivalent to |
| time_t, but that's not necessarily true on other systems (e.g. it is |
| not true for the Digital Mars C runtime). So, be careful when using unix |
| time with C functions on non-POSIX systems. |
| |
| "std time"'s epoch is based on the Proleptic Gregorian Calendar per ISO |
| 8601 and is what $(LREF SysTime) uses internally. However, holding the time |
| as an integer in hnescs since that epoch technically isn't actually part of |
| the standard, much as it's based on it, so the name "std time" isn't |
| particularly good, but there isn't an official name for it. C# uses "ticks" |
| for the same thing, but they aren't actually clock ticks, and the term |
| "ticks" $(I is) used for actual clock ticks for $(REF MonoTime, core,time), |
| so it didn't make sense to use the term ticks here. So, for better or worse, |
| std.datetime uses the term "std time" for this. |
| |
| By default, the return type is time_t (which is normally an alias for |
| int on 32-bit systems and long on 64-bit systems), but if a different |
| size is required than either int or long can be passed as a template |
| argument to get the desired size. |
| |
| If the return type is int, and the result can't fit in an int, then the |
| closest value that can be held in 32 bits will be used (so $(D int.max) |
| if it goes over and $(D int.min) if it goes under). However, no attempt |
| is made to deal with integer overflow if the return type is long. |
| |
| Params: |
| T = The return type (int or long). It defaults to time_t, which is |
| normally 32 bits on a 32-bit system and 64 bits on a 64-bit |
| system. |
| stdTime = The std time to convert. |
| |
| Returns: |
| A signed integer representing the unix time which is equivalent to |
| the given std time. |
| |
| See_Also: |
| SysTime.toUnixTime |
| +/ |
| T stdTimeToUnixTime(T = time_t)(long stdTime) @safe pure nothrow |
| if (is(T == int) || is(T == long)) |
| { |
| immutable unixTime = convert!("hnsecs", "seconds")(stdTime - 621_355_968_000_000_000L); |
| |
| static assert(is(time_t == int) || is(time_t == long), |
| "Currently, std.datetime only supports systems where time_t is int or long"); |
| |
| static if (is(T == long)) |
| return unixTime; |
| else static if (is(T == int)) |
| { |
| if (unixTime > int.max) |
| return int.max; |
| return unixTime < int.min ? int.min : cast(int) unixTime; |
| } |
| else |
| static assert(0, "Bug in template constraint. Only int and long allowed."); |
| } |
| |
| /// |
| @safe unittest |
| { |
| // Midnight, January 1st, 1970 UTC |
| assert(stdTimeToUnixTime(621_355_968_000_000_000L) == 0); |
| |
| // 2038-01-19 03:14:07 UTC |
| assert(stdTimeToUnixTime(642_830_804_470_000_000L) == int.max); |
| } |
| |
| @safe unittest |
| { |
| enum unixEpochAsStdTime = (Date(1970, 1, 1) - Date.init).total!"hnsecs"; |
| |
| assert(stdTimeToUnixTime(unixEpochAsStdTime) == 0); // Midnight, January 1st, 1970 |
| assert(stdTimeToUnixTime(unixEpochAsStdTime + 864_000_000_000L) == 86_400); // Midnight, January 2nd, 1970 |
| assert(stdTimeToUnixTime(unixEpochAsStdTime - 864_000_000_000L) == -86_400); // Midnight, December 31st, 1969 |
| |
| assert(stdTimeToUnixTime((Date(1970, 1, 1) - Date(1, 1, 1)).total!"hnsecs") == 0); |
| assert(stdTimeToUnixTime((DateTime(1970, 1, 1) - DateTime(1, 1, 1)).total!"hnsecs") == 0); |
| |
| foreach (dt; [DateTime(2010, 11, 1, 19, 5, 22), DateTime(1952, 7, 6, 2, 17, 9)]) |
| assert(stdTimeToUnixTime((dt - DateTime.init).total!"hnsecs") == (dt - DateTime(1970, 1, 1)).total!"seconds"); |
| |
| enum max = convert!("seconds", "hnsecs")(int.max); |
| enum min = convert!("seconds", "hnsecs")(int.min); |
| enum one = convert!("seconds", "hnsecs")(1); |
| |
| assert(stdTimeToUnixTime!long(unixEpochAsStdTime + max) == int.max); |
| assert(stdTimeToUnixTime!int(unixEpochAsStdTime + max) == int.max); |
| |
| assert(stdTimeToUnixTime!long(unixEpochAsStdTime + max + one) == int.max + 1L); |
| assert(stdTimeToUnixTime!int(unixEpochAsStdTime + max + one) == int.max); |
| assert(stdTimeToUnixTime!long(unixEpochAsStdTime + max + 9_999_999) == int.max); |
| assert(stdTimeToUnixTime!int(unixEpochAsStdTime + max + 9_999_999) == int.max); |
| |
| assert(stdTimeToUnixTime!long(unixEpochAsStdTime + min) == int.min); |
| assert(stdTimeToUnixTime!int(unixEpochAsStdTime + min) == int.min); |
| |
| assert(stdTimeToUnixTime!long(unixEpochAsStdTime + min - one) == int.min - 1L); |
| assert(stdTimeToUnixTime!int(unixEpochAsStdTime + min - one) == int.min); |
| assert(stdTimeToUnixTime!long(unixEpochAsStdTime + min - 9_999_999) == int.min); |
| assert(stdTimeToUnixTime!int(unixEpochAsStdTime + min - 9_999_999) == int.min); |
| } |
| |
| |
| version (StdDdoc) |
| { |
| version (Windows) |
| {} |
| else |
| { |
| alias SYSTEMTIME = void*; |
| alias FILETIME = void*; |
| } |
| |
| /++ |
| $(BLUE This function is Windows-Only.) |
| |
| Converts a $(D SYSTEMTIME) struct to a $(LREF SysTime). |
| |
| Params: |
| st = The $(D SYSTEMTIME) struct to convert. |
| tz = The time zone that the time in the $(D SYSTEMTIME) struct is |
| assumed to be (if the $(D SYSTEMTIME) was supplied by a Windows |
| system call, the $(D SYSTEMTIME) will either be in local time |
| or UTC, depending on the call). |
| |
| Throws: |
| $(REF DateTimeException,std,datetime,date) if the given |
| $(D SYSTEMTIME) will not fit in a $(LREF SysTime), which is highly |
| unlikely to happen given that $(D SysTime.max) is in 29,228 A.D. and |
| the maximum $(D SYSTEMTIME) is in 30,827 A.D. |
| +/ |
| SysTime SYSTEMTIMEToSysTime(const SYSTEMTIME* st, immutable TimeZone tz = LocalTime()) @safe; |
| |
| |
| /++ |
| $(BLUE This function is Windows-Only.) |
| |
| Converts a $(LREF SysTime) to a $(D SYSTEMTIME) struct. |
| |
| The $(D SYSTEMTIME) which is returned will be set using the given |
| $(LREF SysTime)'s time zone, so to get the $(D SYSTEMTIME) in |
| UTC, set the $(LREF SysTime)'s time zone to UTC. |
| |
| Params: |
| sysTime = The $(LREF SysTime) to convert. |
| |
| Throws: |
| $(REF DateTimeException,std,datetime,date) if the given |
| $(LREF SysTime) will not fit in a $(D SYSTEMTIME). This will only |
| happen if the $(LREF SysTime)'s date is prior to 1601 A.D. |
| +/ |
| SYSTEMTIME SysTimeToSYSTEMTIME(in SysTime sysTime) @safe; |
| |
| |
| /++ |
| $(BLUE This function is Windows-Only.) |
| |
| Converts a $(D FILETIME) struct to the number of hnsecs since midnight, |
| January 1st, 1 A.D. |
| |
| Params: |
| ft = The $(D FILETIME) struct to convert. |
| |
| Throws: |
| $(REF DateTimeException,std,datetime,date) if the given |
| $(D FILETIME) cannot be represented as the return value. |
| +/ |
| long FILETIMEToStdTime(scope const FILETIME* ft) @safe; |
| |
| |
| /++ |
| $(BLUE This function is Windows-Only.) |
| |
| Converts a $(D FILETIME) struct to a $(LREF SysTime). |
| |
| Params: |
| ft = The $(D FILETIME) struct to convert. |
| tz = The time zone that the $(LREF SysTime) will be in |
| ($(D FILETIME)s are in UTC). |
| |
| Throws: |
| $(REF DateTimeException,std,datetime,date) if the given |
| $(D FILETIME) will not fit in a $(LREF SysTime). |
| +/ |
| SysTime FILETIMEToSysTime(scope const FILETIME* ft, immutable TimeZone tz = LocalTime()) @safe; |
| |
| |
| /++ |
| $(BLUE This function is Windows-Only.) |
| |
| Converts a number of hnsecs since midnight, January 1st, 1 A.D. to a |
| $(D FILETIME) struct. |
| |
| Params: |
| stdTime = The number of hnsecs since midnight, January 1st, 1 A.D. |
| UTC. |
| |
| Throws: |
| $(REF DateTimeException,std,datetime,date) if the given value will |
| not fit in a $(D FILETIME). |
| +/ |
| FILETIME stdTimeToFILETIME(long stdTime) @safe; |
| |
| |
| /++ |
| $(BLUE This function is Windows-Only.) |
| |
| Converts a $(LREF SysTime) to a $(D FILETIME) struct. |
| |
| $(D FILETIME)s are always in UTC. |
| |
| Params: |
| sysTime = The $(LREF SysTime) to convert. |
| |
| Throws: |
| $(REF DateTimeException,std,datetime,date) if the given |
| $(LREF SysTime) will not fit in a $(D FILETIME). |
| +/ |
| FILETIME SysTimeToFILETIME(SysTime sysTime) @safe; |
| } |
| else version (Windows) |
| { |
| SysTime SYSTEMTIMEToSysTime(const SYSTEMTIME* st, immutable TimeZone tz = LocalTime()) @safe |
| { |
| const max = SysTime.max; |
| |
| static void throwLaterThanMax() |
| { |
| throw new DateTimeException("The given SYSTEMTIME is for a date greater than SysTime.max."); |
| } |
| |
| if (st.wYear > max.year) |
| throwLaterThanMax(); |
| else if (st.wYear == max.year) |
| { |
| if (st.wMonth > max.month) |
| throwLaterThanMax(); |
| else if (st.wMonth == max.month) |
| { |
| if (st.wDay > max.day) |
| throwLaterThanMax(); |
| else if (st.wDay == max.day) |
| { |
| if (st.wHour > max.hour) |
| throwLaterThanMax(); |
| else if (st.wHour == max.hour) |
| { |
| if (st.wMinute > max.minute) |
| throwLaterThanMax(); |
| else if (st.wMinute == max.minute) |
| { |
| if (st.wSecond > max.second) |
| throwLaterThanMax(); |
| else if (st.wSecond == max.second) |
| { |
| if (st.wMilliseconds > max.fracSecs.total!"msecs") |
| throwLaterThanMax(); |
| } |
| } |
| } |
| } |
| } |
| } |
| |
| auto dt = DateTime(st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond); |
| |
| return SysTime(dt, msecs(st.wMilliseconds), tz); |
| } |
| |
| @system unittest |
| { |
| auto sysTime = Clock.currTime(UTC()); |
| SYSTEMTIME st = void; |
| GetSystemTime(&st); |
| auto converted = SYSTEMTIMEToSysTime(&st, UTC()); |
| |
| assert(abs((converted - sysTime)) <= dur!"seconds"(2)); |
| } |
| |
| |
| SYSTEMTIME SysTimeToSYSTEMTIME(in SysTime sysTime) @safe |
| { |
| immutable dt = cast(DateTime) sysTime; |
| |
| if (dt.year < 1601) |
| throw new DateTimeException("SYSTEMTIME cannot hold dates prior to the year 1601."); |
| |
| SYSTEMTIME st; |
| |
| st.wYear = dt.year; |
| st.wMonth = dt.month; |
| st.wDayOfWeek = dt.dayOfWeek; |
| st.wDay = dt.day; |
| st.wHour = dt.hour; |
| st.wMinute = dt.minute; |
| st.wSecond = dt.second; |
| st.wMilliseconds = cast(ushort) sysTime.fracSecs.total!"msecs"; |
| |
| return st; |
| } |
| |
| @system unittest |
| { |
| SYSTEMTIME st = void; |
| GetSystemTime(&st); |
| auto sysTime = SYSTEMTIMEToSysTime(&st, UTC()); |
| |
| SYSTEMTIME result = SysTimeToSYSTEMTIME(sysTime); |
| |
| assert(st.wYear == result.wYear); |
| assert(st.wMonth == result.wMonth); |
| assert(st.wDayOfWeek == result.wDayOfWeek); |
| assert(st.wDay == result.wDay); |
| assert(st.wHour == result.wHour); |
| assert(st.wMinute == result.wMinute); |
| assert(st.wSecond == result.wSecond); |
| assert(st.wMilliseconds == result.wMilliseconds); |
| } |
| |
| private enum hnsecsFrom1601 = 504_911_232_000_000_000L; |
| |
| long FILETIMEToStdTime(scope const FILETIME* ft) @safe |
| { |
| ULARGE_INTEGER ul; |
| ul.HighPart = ft.dwHighDateTime; |
| ul.LowPart = ft.dwLowDateTime; |
| ulong tempHNSecs = ul.QuadPart; |
| |
| if (tempHNSecs > long.max - hnsecsFrom1601) |
| throw new DateTimeException("The given FILETIME cannot be represented as a stdTime value."); |
| |
| return cast(long) tempHNSecs + hnsecsFrom1601; |
| } |
| |
| SysTime FILETIMEToSysTime(scope const FILETIME* ft, immutable TimeZone tz = LocalTime()) @safe |
| { |
| auto sysTime = SysTime(FILETIMEToStdTime(ft), UTC()); |
| sysTime.timezone = tz; |
| return sysTime; |
| } |
| |
| @system unittest |
| { |
| auto sysTime = Clock.currTime(UTC()); |
| SYSTEMTIME st = void; |
| GetSystemTime(&st); |
| |
| FILETIME ft = void; |
| SystemTimeToFileTime(&st, &ft); |
| |
| auto converted = FILETIMEToSysTime(&ft); |
| |
| assert(abs((converted - sysTime)) <= dur!"seconds"(2)); |
| } |
| |
| |
| FILETIME stdTimeToFILETIME(long stdTime) @safe |
| { |
| if (stdTime < hnsecsFrom1601) |
| throw new DateTimeException("The given stdTime value cannot be represented as a FILETIME."); |
| |
| ULARGE_INTEGER ul; |
| ul.QuadPart = cast(ulong) stdTime - hnsecsFrom1601; |
| |
| FILETIME ft; |
| ft.dwHighDateTime = ul.HighPart; |
| ft.dwLowDateTime = ul.LowPart; |
| |
| return ft; |
| } |
| |
| FILETIME SysTimeToFILETIME(SysTime sysTime) @safe |
| { |
| return stdTimeToFILETIME(sysTime.stdTime); |
| } |
| |
| @system unittest |
| { |
| SYSTEMTIME st = void; |
| GetSystemTime(&st); |
| |
| FILETIME ft = void; |
| SystemTimeToFileTime(&st, &ft); |
| auto sysTime = FILETIMEToSysTime(&ft, UTC()); |
| |
| FILETIME result = SysTimeToFILETIME(sysTime); |
| |
| assert(ft.dwLowDateTime == result.dwLowDateTime); |
| assert(ft.dwHighDateTime == result.dwHighDateTime); |
| } |
| } |
| |
| |
| /++ |
| Type representing the DOS file date/time format. |
| +/ |
| alias DosFileTime = uint; |
| |
| /++ |
| Converts from DOS file date/time to $(LREF SysTime). |
| |
| Params: |
| dft = The DOS file time to convert. |
| tz = The time zone which the DOS file time is assumed to be in. |
| |
| Throws: |
| $(REF DateTimeException,std,datetime,date) if the $(D DosFileTime) is |
| invalid. |
| +/ |
| SysTime DosFileTimeToSysTime(DosFileTime dft, immutable TimeZone tz = LocalTime()) @safe |
| { |
| uint dt = cast(uint) dft; |
| |
| if (dt == 0) |
| throw new DateTimeException("Invalid DosFileTime."); |
| |
| int year = ((dt >> 25) & 0x7F) + 1980; |
| int month = ((dt >> 21) & 0x0F); // 1 .. 12 |
| int dayOfMonth = ((dt >> 16) & 0x1F); // 1 .. 31 |
| int hour = (dt >> 11) & 0x1F; // 0 .. 23 |
| int minute = (dt >> 5) & 0x3F; // 0 .. 59 |
| int second = (dt << 1) & 0x3E; // 0 .. 58 (in 2 second increments) |
| |
| try |
| return SysTime(DateTime(year, month, dayOfMonth, hour, minute, second), tz); |
| catch (DateTimeException dte) |
| throw new DateTimeException("Invalid DosFileTime", __FILE__, __LINE__, dte); |
| } |
| |
| @safe unittest |
| { |
| assert(DosFileTimeToSysTime(0b00000000001000010000000000000000) == SysTime(DateTime(1980, 1, 1, 0, 0, 0))); |
| assert(DosFileTimeToSysTime(0b11111111100111111011111101111101) == SysTime(DateTime(2107, 12, 31, 23, 59, 58))); |
| assert(DosFileTimeToSysTime(0x3E3F8456) == SysTime(DateTime(2011, 1, 31, 16, 34, 44))); |
| } |
| |
| |
| /++ |
| Converts from $(LREF SysTime) to DOS file date/time. |
| |
| Params: |
| sysTime = The $(LREF SysTime) to convert. |
| |
| Throws: |
| $(REF DateTimeException,std,datetime,date) if the given |
| $(LREF SysTime) cannot be converted to a $(D DosFileTime). |
| +/ |
| DosFileTime SysTimeToDosFileTime(SysTime sysTime) @safe |
| { |
| auto dateTime = cast(DateTime) sysTime; |
| |
| if (dateTime.year < 1980) |
| throw new DateTimeException("DOS File Times cannot hold dates prior to 1980."); |
| |
| if (dateTime.year > 2107) |
| throw new DateTimeException("DOS File Times cannot hold dates past 2107."); |
| |
| uint retval = 0; |
| retval = (dateTime.year - 1980) << 25; |
| retval |= (dateTime.month & 0x0F) << 21; |
| retval |= (dateTime.day & 0x1F) << 16; |
| retval |= (dateTime.hour & 0x1F) << 11; |
| retval |= (dateTime.minute & 0x3F) << 5; |
| retval |= (dateTime.second >> 1) & 0x1F; |
| |
| return cast(DosFileTime) retval; |
| } |
| |
| @safe unittest |
| { |
| assert(SysTimeToDosFileTime(SysTime(DateTime(1980, 1, 1, 0, 0, 0))) == 0b00000000001000010000000000000000); |
| assert(SysTimeToDosFileTime(SysTime(DateTime(2107, 12, 31, 23, 59, 58))) == 0b11111111100111111011111101111101); |
| assert(SysTimeToDosFileTime(SysTime(DateTime(2011, 1, 31, 16, 34, 44))) == 0x3E3F8456); |
| } |
| |
| |
| /++ |
| The given array of $(D char) or random-access range of $(D char) or |
| $(D ubyte) is expected to be in the format specified in |
| $(HTTP tools.ietf.org/html/rfc5322, RFC 5322) section 3.3 with the |
| grammar rule $(I date-time). It is the date-time format commonly used in |
| internet messages such as e-mail and HTTP. The corresponding |
| $(LREF SysTime) will be returned. |
| |
| RFC 822 was the original spec (hence the function's name), whereas RFC 5322 |
| is the current spec. |
| |
| The day of the week is ignored beyond verifying that it's a valid day of the |
| week, as the day of the week can be inferred from the date. It is not |
| checked whether the given day of the week matches the actual day of the week |
| of the given date (though it is technically invalid per the spec if the |
| day of the week doesn't match the actual day of the week of the given date). |
| |
| If the time zone is $(D "-0000") (or considered to be equivalent to |
| $(D "-0000") by section 4.3 of the spec), a |
| $(REF SimpleTimeZone,std,datetime,timezone) with a utc offset of $(D 0) is |
| used rather than $(REF UTC,std,datetime,timezone), whereas $(D "+0000") uses |
| $(REF UTC,std,datetime,timezone). |
| |
| Note that because $(LREF SysTime) does not currently support having a second |
| value of 60 (as is sometimes done for leap seconds), if the date-time value |
| does have a value of 60 for the seconds, it is treated as 59. |
| |
| The one area in which this function violates RFC 5322 is that it accepts |
| $(D "\n") in folding whitespace in the place of $(D "\r\n"), because the |
| HTTP spec requires it. |
| |
| Throws: |
| $(REF DateTimeException,std,datetime,date) if the given string doesn't |
| follow the grammar for a date-time field or if the resulting |
| $(LREF SysTime) is invalid. |
| +/ |
| SysTime parseRFC822DateTime()(in char[] value) @safe |
| { |
| import std.string : representation; |
| return parseRFC822DateTime(value.representation); |
| } |
| |
| /++ Ditto +/ |
| SysTime parseRFC822DateTime(R)(R value) @safe |
| if (isRandomAccessRange!R && hasSlicing!R && hasLength!R && |
| (is(Unqual!(ElementType!R) == char) || is(Unqual!(ElementType!R) == ubyte))) |
| { |
| import std.algorithm.searching : find, all; |
| import std.ascii : isDigit, isAlpha, isPrintable; |
| import std.conv : to; |
| import std.functional : not; |
| import std.string : capitalize, format; |
| import std.traits : EnumMembers, isArray; |
| import std.typecons : Rebindable; |
| |
| void stripAndCheckLen(R valueBefore, size_t minLen, size_t line = __LINE__) |
| { |
| value = _stripCFWS(valueBefore); |
| if (value.length < minLen) |
| throw new DateTimeException("date-time value too short", __FILE__, line); |
| } |
| stripAndCheckLen(value, "7Dec1200:00A".length); |
| |
| static if (isArray!R && (is(ElementEncodingType!R == char) || is(ElementEncodingType!R == ubyte))) |
| { |
| static string sliceAsString(R str) @trusted |
| { |
| return cast(string) str; |
| } |
| } |
| else |
| { |
| char[4] temp; |
| char[] sliceAsString(R str) @trusted |
| { |
| size_t i = 0; |
| foreach (c; str) |
| temp[i++] = cast(char) c; |
| return temp[0 .. str.length]; |
| } |
| } |
| |
| // day-of-week |
| if (isAlpha(value[0])) |
| { |
| auto dowStr = sliceAsString(value[0 .. 3]); |
| switch (dowStr) |
| { |
| foreach (dow; EnumMembers!DayOfWeek) |
| { |
| enum dowC = capitalize(to!string(dow)); |
| case dowC: |
| goto afterDoW; |
| } |
| default: throw new DateTimeException(format("Invalid day-of-week: %s", dowStr)); |
| } |
| afterDoW: stripAndCheckLen(value[3 .. value.length], ",7Dec1200:00A".length); |
| if (value[0] != ',') |
| throw new DateTimeException("day-of-week missing comma"); |
| stripAndCheckLen(value[1 .. value.length], "7Dec1200:00A".length); |
| } |
| |
| // day |
| immutable digits = isDigit(value[1]) ? 2 : 1; |
| immutable day = _convDigits!short(value[0 .. digits]); |
| if (day == -1) |
| throw new DateTimeException("Invalid day"); |
| stripAndCheckLen(value[digits .. value.length], "Dec1200:00A".length); |
| |
| // month |
| Month month; |
| { |
| auto monStr = sliceAsString(value[0 .. 3]); |
| switch (monStr) |
| { |
| foreach (mon; EnumMembers!Month) |
| { |
| enum monC = capitalize(to!string(mon)); |
| case monC: |
| { |
| month = mon; |
| goto afterMon; |
| } |
| } |
| default: throw new DateTimeException(format("Invalid month: %s", monStr)); |
| } |
| afterMon: stripAndCheckLen(value[3 .. value.length], "1200:00A".length); |
| } |
| |
| // year |
| auto found = value[2 .. value.length].find!(not!(std.ascii.isDigit))(); |
| size_t yearLen = value.length - found.length; |
| if (found.length == 0) |
| throw new DateTimeException("Invalid year"); |
| if (found[0] == ':') |
| yearLen -= 2; |
| auto year = _convDigits!short(value[0 .. yearLen]); |
| if (year < 1900) |
| { |
| if (year == -1) |
| throw new DateTimeException("Invalid year"); |
| if (yearLen < 4) |
| { |
| if (yearLen == 3) |
| year += 1900; |
| else if (yearLen == 2) |
| year += year < 50 ? 2000 : 1900; |
| else |
| throw new DateTimeException("Invalid year. Too few digits."); |
| } |
| else |
| throw new DateTimeException("Invalid year. Cannot be earlier than 1900."); |
| } |
| stripAndCheckLen(value[yearLen .. value.length], "00:00A".length); |
| |
| // hour |
| immutable hour = _convDigits!short(value[0 .. 2]); |
| stripAndCheckLen(value[2 .. value.length], ":00A".length); |
| if (value[0] != ':') |
| throw new DateTimeException("Invalid hour"); |
| stripAndCheckLen(value[1 .. value.length], "00A".length); |
| |
| // minute |
| immutable minute = _convDigits!short(value[0 .. 2]); |
| stripAndCheckLen(value[2 .. value.length], "A".length); |
| |
| // second |
| short second; |
| if (value[0] == ':') |
| { |
| stripAndCheckLen(value[1 .. value.length], "00A".length); |
| second = _convDigits!short(value[0 .. 2]); |
| // this is just if/until SysTime is sorted out to fully support leap seconds |
| if (second == 60) |
| second = 59; |
| stripAndCheckLen(value[2 .. value.length], "A".length); |
| } |
| |
| immutable(TimeZone) parseTZ(int sign) |
| { |
| if (value.length < 5) |
| throw new DateTimeException("Invalid timezone"); |
| immutable zoneHours = _convDigits!short(value[1 .. 3]); |
| immutable zoneMinutes = _convDigits!short(value[3 .. 5]); |
| if (zoneHours == -1 || zoneMinutes == -1 || zoneMinutes > 59) |
| throw new DateTimeException("Invalid timezone"); |
| value = value[5 .. value.length]; |
| immutable utcOffset = (dur!"hours"(zoneHours) + dur!"minutes"(zoneMinutes)) * sign; |
| if (utcOffset == Duration.zero) |
| { |
| return sign == 1 ? cast(immutable(TimeZone))UTC() |
| : cast(immutable(TimeZone))new immutable SimpleTimeZone(Duration.zero); |
| } |
| return new immutable(SimpleTimeZone)(utcOffset); |
| } |
| |
| // zone |
| Rebindable!(immutable TimeZone) tz; |
| if (value[0] == '-') |
| tz = parseTZ(-1); |
| else if (value[0] == '+') |
| tz = parseTZ(1); |
| else |
| { |
| // obs-zone |
| immutable tzLen = value.length - find(value, ' ', '\t', '(')[0].length; |
| switch (sliceAsString(value[0 .. tzLen <= 4 ? tzLen : 4])) |
| { |
| case "UT": case "GMT": tz = UTC(); break; |
| case "EST": tz = new immutable SimpleTimeZone(dur!"hours"(-5)); break; |
| case "EDT": tz = new immutable SimpleTimeZone(dur!"hours"(-4)); break; |
| case "CST": tz = new immutable SimpleTimeZone(dur!"hours"(-6)); break; |
| case "CDT": tz = new immutable SimpleTimeZone(dur!"hours"(-5)); break; |
| case "MST": tz = new immutable SimpleTimeZone(dur!"hours"(-7)); break; |
| case "MDT": tz = new immutable SimpleTimeZone(dur!"hours"(-6)); break; |
| case "PST": tz = new immutable SimpleTimeZone(dur!"hours"(-8)); break; |
| case "PDT": tz = new immutable SimpleTimeZone(dur!"hours"(-7)); break; |
| case "J": case "j": throw new DateTimeException("Invalid timezone"); |
| default: |
| { |
| if (all!(std.ascii.isAlpha)(value[0 .. tzLen])) |
| { |
| tz = new immutable SimpleTimeZone(Duration.zero); |
| break; |
| } |
| throw new DateTimeException("Invalid timezone"); |
| } |
| } |
| value = value[tzLen .. value.length]; |
| } |
| |
| // This is kind of arbitrary. Technically, nothing but CFWS is legal past |
| // the end of the timezone, but we don't want to be picky about that in a |
| // function that's just parsing rather than validating. So, the idea here is |
| // that if the next character is printable (and not part of CFWS), then it |
| // might be part of the timezone and thus affect what the timezone was |
| // supposed to be, so we'll throw, but otherwise, we'll just ignore it. |
| if (!value.empty && isPrintable(value[0]) && value[0] != ' ' && value[0] != '(') |
| throw new DateTimeException("Invalid timezone"); |
| |
| try |
| return SysTime(DateTime(year, month, day, hour, minute, second), tz); |
| catch (DateTimeException dte) |
| throw new DateTimeException("date-time format is correct, but the resulting SysTime is invalid.", dte); |
| } |
| |
| /// |
| @safe unittest |
| { |
| import core.time : hours; |
| import std.datetime.date : DateTime, DateTimeException; |
| import std.datetime.timezone : SimpleTimeZone, UTC; |
| import std.exception : assertThrown; |
| |
| auto tz = new immutable SimpleTimeZone(hours(-8)); |
| assert(parseRFC822DateTime("Sat, 6 Jan 1990 12:14:19 -0800") == |
| SysTime(DateTime(1990, 1, 6, 12, 14, 19), tz)); |
| |
| assert(parseRFC822DateTime("9 Jul 2002 13:11 +0000") == |
| SysTime(DateTime(2002, 7, 9, 13, 11, 0), UTC())); |
| |
| auto badStr = "29 Feb 2001 12:17:16 +0200"; |
| assertThrown!DateTimeException(parseRFC822DateTime(badStr)); |
| } |
| |
| version (unittest) void testParse822(alias cr)(string str, SysTime expected, size_t line = __LINE__) |
| { |
| import std.format : format; |
| auto value = cr(str); |
| auto result = parseRFC822DateTime(value); |
| if (result != expected) |
| throw new AssertError(format("wrong result. expected [%s], actual[%s]", expected, result), __FILE__, line); |
| } |
| |
| version (unittest) void testBadParse822(alias cr)(string str, size_t line = __LINE__) |
| { |
| try |
| parseRFC822DateTime(cr(str)); |
| catch (DateTimeException) |
| return; |
| throw new AssertError("No DateTimeException was thrown", __FILE__, line); |
| } |
| |
| @system unittest |
| { |
| import std.algorithm.iteration : filter, map; |
| import std.algorithm.searching : canFind; |
| import std.array : array; |
| import std.ascii : letters; |
| import std.format : format; |
| import std.meta : AliasSeq; |
| import std.range : chain, iota, take; |
| import std.stdio : writefln, writeln; |
| import std.string : representation; |
| |
| static struct Rand3Letters |
| { |
| enum empty = false; |
| @property auto front() { return _mon; } |
| void popFront() |
| { |
| import std.exception : assumeUnique; |
| import std.random : rndGen; |
| _mon = rndGen.map!(a => letters[a % letters.length])().take(3).array().assumeUnique(); |
| } |
| string _mon; |
| static auto start() { Rand3Letters retval; retval.popFront(); return retval; } |
| } |
| |
| foreach (cr; AliasSeq!(function(string a){return cast(char[]) a;}, |
| function(string a){return cast(ubyte[]) a;}, |
| function(string a){return a;}, |
| function(string a){return map!(b => cast(char) b)(a.representation);})) |
| (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396 |
| scope(failure) writeln(typeof(cr).stringof); |
| alias test = testParse822!cr; |
| alias testBad = testBadParse822!cr; |
| |
| immutable std1 = DateTime(2012, 12, 21, 13, 14, 15); |
| immutable std2 = DateTime(2012, 12, 21, 13, 14, 0); |
| immutable dst1 = DateTime(1976, 7, 4, 5, 4, 22); |
| immutable dst2 = DateTime(1976, 7, 4, 5, 4, 0); |
| |
| test("21 Dec 2012 13:14:15 +0000", SysTime(std1, UTC())); |
| test("21 Dec 2012 13:14 +0000", SysTime(std2, UTC())); |
| test("Fri, 21 Dec 2012 13:14 +0000", SysTime(std2, UTC())); |
| test("Fri, 21 Dec 2012 13:14:15 +0000", SysTime(std1, UTC())); |
| |
| test("04 Jul 1976 05:04:22 +0000", SysTime(dst1, UTC())); |
| test("04 Jul 1976 05:04 +0000", SysTime(dst2, UTC())); |
| test("Sun, 04 Jul 1976 05:04 +0000", SysTime(dst2, UTC())); |
| test("Sun, 04 Jul 1976 05:04:22 +0000", SysTime(dst1, UTC())); |
| |
| test("4 Jul 1976 05:04:22 +0000", SysTime(dst1, UTC())); |
| test("4 Jul 1976 05:04 +0000", SysTime(dst2, UTC())); |
| test("Sun, 4 Jul 1976 05:04 +0000", SysTime(dst2, UTC())); |
| test("Sun, 4 Jul 1976 05:04:22 +0000", SysTime(dst1, UTC())); |
| |
| auto badTZ = new immutable SimpleTimeZone(Duration.zero); |
| test("21 Dec 2012 13:14:15 -0000", SysTime(std1, badTZ)); |
| test("21 Dec 2012 13:14 -0000", SysTime(std2, badTZ)); |
| test("Fri, 21 Dec 2012 13:14 -0000", SysTime(std2, badTZ)); |
| test("Fri, 21 Dec 2012 13:14:15 -0000", SysTime(std1, badTZ)); |
| |
| test("04 Jul 1976 05:04:22 -0000", SysTime(dst1, badTZ)); |
| test("04 Jul 1976 05:04 -0000", SysTime(dst2, badTZ)); |
| test("Sun, 04 Jul 1976 05:04 -0000", SysTime(dst2, badTZ)); |
| test("Sun, 04 Jul 1976 05:04:22 -0000", SysTime(dst1, badTZ)); |
| |
| test("4 Jul 1976 05:04:22 -0000", SysTime(dst1, badTZ)); |
| test("4 Jul 1976 05:04 -0000", SysTime(dst2, badTZ)); |
| test("Sun, 4 Jul 1976 05:04 -0000", SysTime(dst2, badTZ)); |
| test("Sun, 4 Jul 1976 05:04:22 -0000", SysTime(dst1, badTZ)); |
| |
| auto pst = new immutable SimpleTimeZone(dur!"hours"(-8)); |
| auto pdt = new immutable SimpleTimeZone(dur!"hours"(-7)); |
| test("21 Dec 2012 13:14:15 -0800", SysTime(std1, pst)); |
| test("21 Dec 2012 13:14 -0800", SysTime(std2, pst)); |
| test("Fri, 21 Dec 2012 13:14 -0800", SysTime(std2, pst)); |
| test("Fri, 21 Dec 2012 13:14:15 -0800", SysTime(std1, pst)); |
| |
| test("04 Jul 1976 05:04:22 -0700", SysTime(dst1, pdt)); |
| test("04 Jul 1976 05:04 -0700", SysTime(dst2, pdt)); |
| test("Sun, 04 Jul 1976 05:04 -0700", SysTime(dst2, pdt)); |
| test("Sun, 04 Jul 1976 05:04:22 -0700", SysTime(dst1, pdt)); |
| |
| test("4 Jul 1976 05:04:22 -0700", SysTime(dst1, pdt)); |
| test("4 Jul 1976 05:04 -0700", SysTime(dst2, pdt)); |
| test("Sun, 4 Jul 1976 05:04 -0700", SysTime(dst2, pdt)); |
| test("Sun, 4 Jul 1976 05:04:22 -0700", SysTime(dst1, pdt)); |
| |
| auto cet = new immutable SimpleTimeZone(dur!"hours"(1)); |
| auto cest = new immutable SimpleTimeZone(dur!"hours"(2)); |
| test("21 Dec 2012 13:14:15 +0100", SysTime(std1, cet)); |
| test("21 Dec 2012 13:14 +0100", SysTime(std2, cet)); |
| test("Fri, 21 Dec 2012 13:14 +0100", SysTime(std2, cet)); |
| test("Fri, 21 Dec 2012 13:14:15 +0100", SysTime(std1, cet)); |
| |
| test("04 Jul 1976 05:04:22 +0200", SysTime(dst1, cest)); |
| test("04 Jul 1976 05:04 +0200", SysTime(dst2, cest)); |
| test("Sun, 04 Jul 1976 05:04 +0200", SysTime(dst2, cest)); |
| test("Sun, 04 Jul 1976 05:04:22 +0200", SysTime(dst1, cest)); |
| |
| test("4 Jul 1976 05:04:22 +0200", SysTime(dst1, cest)); |
| test("4 Jul 1976 05:04 +0200", SysTime(dst2, cest)); |
| test("Sun, 4 Jul 1976 05:04 +0200", SysTime(dst2, cest)); |
| test("Sun, 4 Jul 1976 05:04:22 +0200", SysTime(dst1, cest)); |
| |
| // dst and std times are switched in the Southern Hemisphere which is why the |
| // time zone names and DateTime variables don't match. |
| auto cstStd = new immutable SimpleTimeZone(dur!"hours"(9) + dur!"minutes"(30)); |
| auto cstDST = new immutable SimpleTimeZone(dur!"hours"(10) + dur!"minutes"(30)); |
| test("21 Dec 2012 13:14:15 +1030", SysTime(std1, cstDST)); |
| test("21 Dec 2012 13:14 +1030", SysTime(std2, cstDST)); |
| test("Fri, 21 Dec 2012 13:14 +1030", SysTime(std2, cstDST)); |
| test("Fri, 21 Dec 2012 13:14:15 +1030", SysTime(std1, cstDST)); |
| |
| test("04 Jul 1976 05:04:22 +0930", SysTime(dst1, cstStd)); |
| test("04 Jul 1976 05:04 +0930", SysTime(dst2, cstStd)); |
| test("Sun, 04 Jul 1976 05:04 +0930", SysTime(dst2, cstStd)); |
| test("Sun, 04 Jul 1976 05:04:22 +0930", SysTime(dst1, cstStd)); |
| |
| test("4 Jul 1976 05:04:22 +0930", SysTime(dst1, cstStd)); |
| test("4 Jul 1976 05:04 +0930", SysTime(dst2, cstStd)); |
| test("Sun, 4 Jul 1976 05:04 +0930", SysTime(dst2, cstStd)); |
| test("Sun, 4 Jul 1976 05:04:22 +0930", SysTime(dst1, cstStd)); |
| |
| foreach (int i, mon; _monthNames) |
| { |
| test(format("17 %s 2012 00:05:02 +0000", mon), SysTime(DateTime(2012, i + 1, 17, 0, 5, 2), UTC())); |
| test(format("17 %s 2012 00:05 +0000", mon), SysTime(DateTime(2012, i + 1, 17, 0, 5, 0), UTC())); |
| } |
| |
| import std.uni : toLower, toUpper; |
| foreach (mon; chain(_monthNames[].map!(a => toLower(a))(), |
| _monthNames[].map!(a => toUpper(a))(), |
| ["Jam", "Jen", "Fec", "Fdb", "Mas", "Mbr", "Aps", "Aqr", "Mai", "Miy", |
| "Jum", "Jbn", "Jup", "Jal", "Aur", "Apg", "Sem", "Sap", "Ocm", "Odt", |
| "Nom", "Nav", "Dem", "Dac"], |
| Rand3Letters.start().filter!(a => !_monthNames[].canFind(a)).take(20))) |
| { |
| scope(failure) writefln("Month: %s", mon); |
| testBad(format("17 %s 2012 00:05:02 +0000", mon)); |
| testBad(format("17 %s 2012 00:05 +0000", mon)); |
| } |
| |
| immutable string[7] daysOfWeekNames = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]; |
| |
| { |
| auto start = SysTime(DateTime(2012, 11, 11, 9, 42, 0), UTC()); |
| int day = 11; |
| |
| foreach (int i, dow; daysOfWeekNames) |
| { |
| auto curr = start + dur!"days"(i); |
| test(format("%s, %s Nov 2012 09:42:00 +0000", dow, day), curr); |
| test(format("%s, %s Nov 2012 09:42 +0000", dow, day++), curr); |
| |
| // Whether the day of the week matches the date is ignored. |
| test(format("%s, 11 Nov 2012 09:42:00 +0000", dow), start); |
| test(format("%s, 11 Nov 2012 09:42 +0000", dow), start); |
| } |
| } |
| |
| foreach (dow; chain(daysOfWeekNames[].map!(a => toLower(a))(), |
| daysOfWeekNames[].map!(a => toUpper(a))(), |
| ["Sum", "Spn", "Mom", "Man", "Tuf", "Tae", "Wem", "Wdd", "The", "Tur", |
| "Fro", "Fai", "San", "Sut"], |
| Rand3Letters.start().filter!(a => !daysOfWeekNames[].canFind(a)).take(20))) |
| { |
| scope(failure) writefln("Day of Week: %s", dow); |
| testBad(format("%s, 11 Nov 2012 09:42:00 +0000", dow)); |
| testBad(format("%s, 11 Nov 2012 09:42 +0000", dow)); |
| } |
| |
| testBad("31 Dec 1899 23:59:59 +0000"); |
| test("01 Jan 1900 00:00:00 +0000", SysTime(Date(1900, 1, 1), UTC())); |
| test("01 Jan 1900 00:00:00 -0000", SysTime(Date(1900, 1, 1), |
| new immutable SimpleTimeZone(Duration.zero))); |
| test("01 Jan 1900 00:00:00 -0700", SysTime(Date(1900, 1, 1), |
| new immutable SimpleTimeZone(dur!"hours"(-7)))); |
| |
| { |
| auto st1 = SysTime(Date(1900, 1, 1), UTC()); |
| auto st2 = SysTime(Date(1900, 1, 1), new immutable SimpleTimeZone(dur!"hours"(-11))); |
| foreach (i; 1900 .. 2102) |
| { |
| test(format("1 Jan %05d 00:00 +0000", i), st1); |
| test(format("1 Jan %05d 00:00 -1100", i), st2); |
| st1.add!"years"(1); |
| st2.add!"years"(1); |
| } |
| st1.year = 9998; |
| st2.year = 9998; |
| foreach (i; 9998 .. 11_002) |
| { |
| test(format("1 Jan %05d 00:00 +0000", i), st1); |
| test(format("1 Jan %05d 00:00 -1100", i), st2); |
| st1.add!"years"(1); |
| st2.add!"years"(1); |
| } |
| } |
| |
| testBad("12 Feb 1907 23:17:09 0000"); |
| testBad("12 Feb 1907 23:17:09 +000"); |
| testBad("12 Feb 1907 23:17:09 -000"); |
| testBad("12 Feb 1907 23:17:09 +00000"); |
| testBad("12 Feb 1907 23:17:09 -00000"); |
| testBad("12 Feb 1907 23:17:09 +A"); |
| testBad("12 Feb 1907 23:17:09 +PST"); |
| testBad("12 Feb 1907 23:17:09 -A"); |
| testBad("12 Feb 1907 23:17:09 -PST"); |
| |
| // test trailing stuff that gets ignored |
| { |
| foreach (c; chain(iota(0, 33), ['('], iota(127, ubyte.max + 1))) |
| { |
| scope(failure) writefln("c: %d", c); |
| test(format("21 Dec 2012 13:14:15 +0000%c", cast(char) c), SysTime(std1, UTC())); |
| test(format("21 Dec 2012 13:14:15 +0000%c ", cast(char) c), SysTime(std1, UTC())); |
| test(format("21 Dec 2012 13:14:15 +0000%chello", cast(char) c), SysTime(std1, UTC())); |
| } |
| } |
| |
| // test trailing stuff that doesn't get ignored |
| { |
| foreach (c; chain(iota(33, '('), iota('(' + 1, 127))) |
| { |
| scope(failure) writefln("c: %d", c); |
| testBad(format("21 Dec 2012 13:14:15 +0000%c", cast(char) c)); |
| testBad(format("21 Dec 2012 13:14:15 +0000%c ", cast(char) c)); |
| testBad(format("21 Dec 2012 13:14:15 +0000%chello", cast(char) c)); |
| } |
| } |
| |
| testBad("32 Jan 2012 12:13:14 -0800"); |
| testBad("31 Jan 2012 24:13:14 -0800"); |
| testBad("31 Jan 2012 12:60:14 -0800"); |
| testBad("31 Jan 2012 12:13:61 -0800"); |
| testBad("31 Jan 2012 12:13:14 -0860"); |
| test("31 Jan 2012 12:13:14 -0859", |
| SysTime(DateTime(2012, 1, 31, 12, 13, 14), |
| new immutable SimpleTimeZone(dur!"hours"(-8) + dur!"minutes"(-59)))); |
| |
| // leap-seconds |
| test("21 Dec 2012 15:59:60 -0800", SysTime(DateTime(2012, 12, 21, 15, 59, 59), pst)); |
| |
| // FWS |
| test("Sun,4 Jul 1976 05:04 +0930", SysTime(dst2, cstStd)); |
| test("Sun,4 Jul 1976 05:04:22 +0930", SysTime(dst1, cstStd)); |
| test("Sun,4 Jul 1976 05:04 +0930 (foo)", SysTime(dst2, cstStd)); |
| test("Sun,4 Jul 1976 05:04:22 +0930 (foo)", SysTime(dst1, cstStd)); |
| test("Sun,4 \r\n Jul \r\n 1976 \r\n 05:04 \r\n +0930 \r\n (foo)", SysTime(dst2, cstStd)); |
| test("Sun,4 \r\n Jul \r\n 1976 \r\n 05:04:22 \r\n +0930 \r\n (foo)", SysTime(dst1, cstStd)); |
| |
| auto str = "01 Jan 2012 12:13:14 -0800 "; |
| test(str, SysTime(DateTime(2012, 1, 1, 12, 13, 14), new immutable SimpleTimeZone(hours(-8)))); |
| foreach (i; 0 .. str.length) |
| { |
| auto currStr = str.dup; |
| currStr[i] = 'x'; |
| scope(failure) writefln("failed: %s", currStr); |
| testBad(cast(string) currStr); |
| } |
| foreach (i; 2 .. str.length) |
| { |
| auto currStr = str[0 .. $ - i]; |
| scope(failure) writefln("failed: %s", currStr); |
| testBad(cast(string) currStr); |
| testBad((cast(string) currStr) ~ " "); |
| } |
| }(); |
| } |
| |
| // Obsolete Format per section 4.3 of RFC 5322. |
| @system unittest |
| { |
| import std.algorithm.iteration : filter, map; |
| import std.ascii : letters; |
| import std.exception : collectExceptionMsg; |
| import std.format : format; |
| import std.meta : AliasSeq; |
| import std.range : chain, iota; |
| import std.stdio : writefln, writeln; |
| import std.string : representation; |
| |
| auto std1 = SysTime(DateTime(2012, 12, 21, 13, 14, 15), UTC()); |
| auto std2 = SysTime(DateTime(2012, 12, 21, 13, 14, 0), UTC()); |
| auto std3 = SysTime(DateTime(1912, 12, 21, 13, 14, 15), UTC()); |
| auto std4 = SysTime(DateTime(1912, 12, 21, 13, 14, 0), UTC()); |
| auto dst1 = SysTime(DateTime(1976, 7, 4, 5, 4, 22), UTC()); |
| auto dst2 = SysTime(DateTime(1976, 7, 4, 5, 4, 0), UTC()); |
| auto tooLate1 = SysTime(Date(10_000, 1, 1), UTC()); |
| auto tooLate2 = SysTime(DateTime(12_007, 12, 31, 12, 22, 19), UTC()); |
| |
| foreach (cr; AliasSeq!(function(string a){return cast(char[]) a;}, |
| function(string a){return cast(ubyte[]) a;}, |
| function(string a){return a;}, |
| function(string a){return map!(b => cast(char) b)(a.representation);})) |
| (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396 |
| scope(failure) writeln(typeof(cr).stringof); |
| alias test = testParse822!cr; |
| { |
| auto list = ["", " ", " \r\n\t", "\t\r\n (hello world( frien(dog)) silly \r\n ) \t\t \r\n ()", |
| " \n ", "\t\n\t", " \n\t (foo) \n (bar) \r\n (baz) \n "]; |
| |
| foreach (i, cfws; list) |
| { |
| scope(failure) writefln("i: %s", i); |
| |
| test(format("%1$s21%1$sDec%1$s2012%1$s13:14:15%1$s+0000%1$s", cfws), std1); |
| test(format("%1$s21%1$sDec%1$s2012%1$s13:14%1$s+0000%1$s", cfws), std2); |
| test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s2012%1$s13:14%1$s+0000%1$s", cfws), std2); |
| test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s2012%1$s13:14:15%1$s+0000%1$s", cfws), std1); |
| |
| test(format("%1$s04%1$sJul%1$s1976%1$s05:04:22%1$s+0000%1$s", cfws), dst1); |
| test(format("%1$s04%1$sJul%1$s1976%1$s05:04%1$s+0000%1$s", cfws), dst2); |
| test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s1976%1$s05:04%1$s+0000%1$s", cfws), dst2); |
| test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s1976%1$s05:04:22 +0000%1$s", cfws), dst1); |
| |
| test(format("%1$s4%1$sJul%1$s1976%1$s05:04:22%1$s+0000%1$s", cfws), dst1); |
| test(format("%1$s4%1$sJul%1$s1976%1$s05:04%1$s+0000%1$s", cfws), dst2); |
| test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s1976%1$s05:04%1$s+0000%1$s", cfws), dst2); |
| test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s1976%1$s05:04:22%1$s+0000%1$s", cfws), dst1); |
| |
| test(format("%1$s21%1$sDec%1$s12%1$s13:14:15%1$s+0000%1$s", cfws), std1); |
| test(format("%1$s21%1$sDec%1$s12%1$s13:14%1$s+0000%1$s", cfws), std2); |
| test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s12%1$s13:14%1$s+0000%1$s", cfws), std2); |
| test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s12%1$s13:14:15%1$s+0000%1$s", cfws), std1); |
| |
| test(format("%1$s04%1$sJul%1$s76%1$s05:04:22%1$s+0000%1$s", cfws), dst1); |
| test(format("%1$s04%1$sJul%1$s76%1$s05:04%1$s+0000%1$s", cfws), dst2); |
| test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s76%1$s05:04%1$s+0000%1$s", cfws), dst2); |
| test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s76%1$s05:04:22%1$s+0000%1$s", cfws), dst1); |
| |
| test(format("%1$s4%1$sJul%1$s76 05:04:22%1$s+0000%1$s", cfws), dst1); |
| test(format("%1$s4%1$sJul%1$s76 05:04%1$s+0000%1$s", cfws), dst2); |
| test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s76%1$s05:04%1$s+0000%1$s", cfws), dst2); |
| test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s76%1$s05:04:22%1$s+0000%1$s", cfws), dst1); |
| |
| test(format("%1$s21%1$sDec%1$s012%1$s13:14:15%1$s+0000%1$s", cfws), std3); |
| test(format("%1$s21%1$sDec%1$s012%1$s13:14%1$s+0000%1$s", cfws), std4); |
| test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s012%1$s13:14%1$s+0000%1$s", cfws), std4); |
| test(format("%1$sFri%1$s,%1$s21%1$sDec%1$s012%1$s13:14:15%1$s+0000%1$s", cfws), std3); |
| |
| test(format("%1$s04%1$sJul%1$s076%1$s05:04:22%1$s+0000%1$s", cfws), dst1); |
| test(format("%1$s04%1$sJul%1$s076%1$s05:04%1$s+0000%1$s", cfws), dst2); |
| test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s076%1$s05:04%1$s+0000%1$s", cfws), dst2); |
| test(format("%1$sSun%1$s,%1$s04%1$sJul%1$s076%1$s05:04:22%1$s+0000%1$s", cfws), dst1); |
| |
| test(format("%1$s4%1$sJul%1$s076%1$s05:04:22%1$s+0000%1$s", cfws), dst1); |
| test(format("%1$s4%1$sJul%1$s076%1$s05:04%1$s+0000%1$s", cfws), dst2); |
| test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s076%1$s05:04%1$s+0000%1$s", cfws), dst2); |
| test(format("%1$sSun%1$s,%1$s4%1$sJul%1$s076%1$s05:04:22%1$s+0000%1$s", cfws), dst1); |
| |
| test(format("%1$s1%1$sJan%1$s10000%1$s00:00:00%1$s+0000%1$s", cfws), tooLate1); |
| test(format("%1$s31%1$sDec%1$s12007%1$s12:22:19%1$s+0000%1$s", cfws), tooLate2); |
| test(format("%1$sSat%1$s,%1$s1%1$sJan%1$s10000%1$s00:00:00%1$s+0000%1$s", cfws), tooLate1); |
| test(format("%1$sSun%1$s,%1$s31%1$sDec%1$s12007%1$s12:22:19%1$s+0000%1$s", cfws), tooLate2); |
| } |
| } |
| |
| // test years of 1, 2, and 3 digits. |
| { |
| auto st1 = SysTime(Date(2000, 1, 1), UTC()); |
| auto st2 = SysTime(Date(2000, 1, 1), new immutable SimpleTimeZone(dur!"hours"(-12))); |
| foreach (i; 0 .. 50) |
| { |
| test(format("1 Jan %02d 00:00 GMT", i), st1); |
| test(format("1 Jan %02d 00:00 -1200", i), st2); |
| st1.add!"years"(1); |
| st2.add!"years"(1); |
| } |
| } |
| |
| { |
| auto st1 = SysTime(Date(1950, 1, 1), UTC()); |
| auto st2 = SysTime(Date(1950, 1, 1), new immutable SimpleTimeZone(dur!"hours"(-12))); |
| foreach (i; 50 .. 100) |
| { |
| test(format("1 Jan %02d 00:00 GMT", i), st1); |
| test(format("1 Jan %02d 00:00 -1200", i), st2); |
| st1.add!"years"(1); |
| st2.add!"years"(1); |
| } |
| } |
| |
| { |
| auto st1 = SysTime(Date(1900, 1, 1), UTC()); |
| auto st2 = SysTime(Date(1900, 1, 1), new immutable SimpleTimeZone(dur!"hours"(-11))); |
| foreach (i; 0 .. 1000) |
| { |
| test(format("1 Jan %03d 00:00 GMT", i), st1); |
| test(format("1 Jan %03d 00:00 -1100", i), st2); |
| st1.add!"years"(1); |
| st2.add!"years"(1); |
| } |
| } |
| |
| foreach (i; 0 .. 10) |
| { |
| auto str1 = cr(format("1 Jan %d 00:00 GMT", i)); |
| auto str2 = cr(format("1 Jan %d 00:00 -1200", i)); |
| assertThrown!DateTimeException(parseRFC822DateTime(str1)); |
| assertThrown!DateTimeException(parseRFC822DateTime(str1)); |
| } |
| |
| // test time zones |
| { |
| auto dt = DateTime(1982, 05, 03, 12, 22, 04); |
| test("Wed, 03 May 1982 12:22:04 UT", SysTime(dt, UTC())); |
| test("Wed, 03 May 1982 12:22:04 GMT", SysTime(dt, UTC())); |
| test("Wed, 03 May 1982 12:22:04 EST", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-5)))); |
| test("Wed, 03 May 1982 12:22:04 EDT", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-4)))); |
| test("Wed, 03 May 1982 12:22:04 CST", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-6)))); |
| test("Wed, 03 May 1982 12:22:04 CDT", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-5)))); |
| test("Wed, 03 May 1982 12:22:04 MST", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-7)))); |
| test("Wed, 03 May 1982 12:22:04 MDT", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-6)))); |
| test("Wed, 03 May 1982 12:22:04 PST", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-8)))); |
| test("Wed, 03 May 1982 12:22:04 PDT", SysTime(dt, new immutable SimpleTimeZone(dur!"hours"(-7)))); |
| |
| auto badTZ = new immutable SimpleTimeZone(Duration.zero); |
| foreach (dchar c; filter!(a => a != 'j' && a != 'J')(letters)) |
| { |
| scope(failure) writefln("c: %s", c); |
| test(format("Wed, 03 May 1982 12:22:04 %s", c), SysTime(dt, badTZ)); |
| test(format("Wed, 03 May 1982 12:22:04%s", c), SysTime(dt, badTZ)); |
| } |
| |
| foreach (dchar c; ['j', 'J']) |
| { |
| scope(failure) writefln("c: %s", c); |
| assertThrown!DateTimeException(parseRFC822DateTime(cr(format("Wed, 03 May 1982 12:22:04 %s", c)))); |
| assertThrown!DateTimeException(parseRFC822DateTime(cr(format("Wed, 03 May 1982 12:22:04%s", c)))); |
| } |
| |
| foreach (string s; ["AAA", "GQW", "DDT", "PDA", "GT", "GM"]) |
| { |
| scope(failure) writefln("s: %s", s); |
| test(format("Wed, 03 May 1982 12:22:04 %s", s), SysTime(dt, badTZ)); |
| } |
| |
| // test trailing stuff that gets ignored |
| { |
| foreach (c; chain(iota(0, 33), ['('], iota(127, ubyte.max + 1))) |
| { |
| scope(failure) writefln("c: %d", c); |
| test(format("21Dec1213:14:15+0000%c", cast(char) c), std1); |
| test(format("21Dec1213:14:15+0000%c ", cast(char) c), std1); |
| test(format("21Dec1213:14:15+0000%chello", cast(char) c), std1); |
| } |
| } |
| |
| // test trailing stuff that doesn't get ignored |
| { |
| foreach (c; chain(iota(33, '('), iota('(' + 1, 127))) |
| { |
| scope(failure) writefln("c: %d", c); |
| assertThrown!DateTimeException( |
| parseRFC822DateTime(cr(format("21Dec1213:14:15+0000%c", cast(char) c)))); |
| assertThrown!DateTimeException( |
| parseRFC822DateTime(cr(format("21Dec1213:14:15+0000%c ", cast(char) c)))); |
| assertThrown!DateTimeException( |
| parseRFC822DateTime(cr(format("21Dec1213:14:15+0000%chello", cast(char) c)))); |
| } |
| } |
| } |
| |
| // test that the checks for minimum length work correctly and avoid |
| // any RangeErrors. |
| test("7Dec1200:00A", SysTime(DateTime(2012, 12, 7, 00, 00, 00), |
| new immutable SimpleTimeZone(Duration.zero))); |
| test("Fri,7Dec1200:00A", SysTime(DateTime(2012, 12, 7, 00, 00, 00), |
| new immutable SimpleTimeZone(Duration.zero))); |
| test("7Dec1200:00:00A", SysTime(DateTime(2012, 12, 7, 00, 00, 00), |
| new immutable SimpleTimeZone(Duration.zero))); |
| test("Fri,7Dec1200:00:00A", SysTime(DateTime(2012, 12, 7, 00, 00, 00), |
| new immutable SimpleTimeZone(Duration.zero))); |
| |
| auto tooShortMsg = collectExceptionMsg!DateTimeException(parseRFC822DateTime("")); |
| foreach (str; ["Fri,7Dec1200:00:00", "7Dec1200:00:00"]) |
| { |
| foreach (i; 0 .. str.length) |
| { |
| auto value = str[0 .. $ - i]; |
| scope(failure) writeln(value); |
| assert(collectExceptionMsg!DateTimeException(parseRFC822DateTime(value)) == tooShortMsg); |
| } |
| } |
| }(); |
| } |
| |
| |
| private: |
| |
| /+ |
| Returns the given hnsecs as an ISO string of fractional seconds. |
| +/ |
| static string fracSecsToISOString(int hnsecs) @safe pure nothrow |
| { |
| assert(hnsecs >= 0); |
| |
| try |
| { |
| if (hnsecs == 0) |
| return ""; |
| |
| string isoString = format(".%07d", hnsecs); |
| |
| while (isoString[$ - 1] == '0') |
| isoString.popBack(); |
| |
| return isoString; |
| } |
| catch (Exception e) |
| assert(0, "format() threw."); |
| } |
| |
| @safe unittest |
| { |
| assert(fracSecsToISOString(0) == ""); |
| assert(fracSecsToISOString(1) == ".0000001"); |
| assert(fracSecsToISOString(10) == ".000001"); |
| assert(fracSecsToISOString(100) == ".00001"); |
| assert(fracSecsToISOString(1000) == ".0001"); |
| assert(fracSecsToISOString(10_000) == ".001"); |
| assert(fracSecsToISOString(100_000) == ".01"); |
| assert(fracSecsToISOString(1_000_000) == ".1"); |
| assert(fracSecsToISOString(1_000_001) == ".1000001"); |
| assert(fracSecsToISOString(1_001_001) == ".1001001"); |
| assert(fracSecsToISOString(1_071_601) == ".1071601"); |
| assert(fracSecsToISOString(1_271_641) == ".1271641"); |
| assert(fracSecsToISOString(9_999_999) == ".9999999"); |
| assert(fracSecsToISOString(9_999_990) == ".999999"); |
| assert(fracSecsToISOString(9_999_900) == ".99999"); |
| assert(fracSecsToISOString(9_999_000) == ".9999"); |
| assert(fracSecsToISOString(9_990_000) == ".999"); |
| assert(fracSecsToISOString(9_900_000) == ".99"); |
| assert(fracSecsToISOString(9_000_000) == ".9"); |
| assert(fracSecsToISOString(999) == ".0000999"); |
| assert(fracSecsToISOString(9990) == ".000999"); |
| assert(fracSecsToISOString(99_900) == ".00999"); |
| assert(fracSecsToISOString(999_000) == ".0999"); |
| } |
| |
| |
| /+ |
| Returns a Duration corresponding to to the given ISO string of |
| fractional seconds. |
| +/ |
| static Duration fracSecsFromISOString(S)(in S isoString) @trusted pure |
| if (isSomeString!S) |
| { |
| import std.algorithm.searching : all; |
| import std.ascii : isDigit; |
| import std.conv : to; |
| import std.string : representation; |
| |
| if (isoString.empty) |
| return Duration.zero; |
| |
| auto str = isoString.representation; |
| |
| enforce(str[0] == '.', new DateTimeException("Invalid ISO String")); |
| str.popFront(); |
| |
| enforce(!str.empty && all!isDigit(str), new DateTimeException("Invalid ISO String")); |
| |
| dchar[7] fullISOString = void; |
| foreach (i, ref dchar c; fullISOString) |
| { |
| if (i < str.length) |
| c = str[i]; |
| else |
| c = '0'; |
| } |
| |
| return hnsecs(to!int(fullISOString[])); |
| } |
| |
| @safe unittest |
| { |
| static void testFSInvalid(string isoString) |
| { |
| fracSecsFromISOString(isoString); |
| } |
| |
| assertThrown!DateTimeException(testFSInvalid(".")); |
| assertThrown!DateTimeException(testFSInvalid("0.")); |
| assertThrown!DateTimeException(testFSInvalid("0")); |
| assertThrown!DateTimeException(testFSInvalid("0000000")); |
| assertThrown!DateTimeException(testFSInvalid("T")); |
| assertThrown!DateTimeException(testFSInvalid("T.")); |
| assertThrown!DateTimeException(testFSInvalid(".T")); |
| assertThrown!DateTimeException(testFSInvalid(".00000Q0")); |
| assertThrown!DateTimeException(testFSInvalid(".000000Q")); |
| assertThrown!DateTimeException(testFSInvalid(".0000000Q")); |
| assertThrown!DateTimeException(testFSInvalid(".0000000000Q")); |
| |
| assert(fracSecsFromISOString("") == Duration.zero); |
| assert(fracSecsFromISOString(".0000001") == hnsecs(1)); |
| assert(fracSecsFromISOString(".000001") == hnsecs(10)); |
| assert(fracSecsFromISOString(".00001") == hnsecs(100)); |
| assert(fracSecsFromISOString(".0001") == hnsecs(1000)); |
| assert(fracSecsFromISOString(".001") == hnsecs(10_000)); |
| assert(fracSecsFromISOString(".01") == hnsecs(100_000)); |
| assert(fracSecsFromISOString(".1") == hnsecs(1_000_000)); |
| assert(fracSecsFromISOString(".1000001") == hnsecs(1_000_001)); |
| assert(fracSecsFromISOString(".1001001") == hnsecs(1_001_001)); |
| assert(fracSecsFromISOString(".1071601") == hnsecs(1_071_601)); |
| assert(fracSecsFromISOString(".1271641") == hnsecs(1_271_641)); |
| assert(fracSecsFromISOString(".9999999") == hnsecs(9_999_999)); |
| assert(fracSecsFromISOString(".9999990") == hnsecs(9_999_990)); |
| assert(fracSecsFromISOString(".999999") == hnsecs(9_999_990)); |
| assert(fracSecsFromISOString(".9999900") == hnsecs(9_999_900)); |
| assert(fracSecsFromISOString(".99999") == hnsecs(9_999_900)); |
| assert(fracSecsFromISOString(".9999000") == hnsecs(9_999_000)); |
| assert(fracSecsFromISOString(".9999") == hnsecs(9_999_000)); |
| assert(fracSecsFromISOString(".9990000") == hnsecs(9_990_000)); |
| assert(fracSecsFromISOString(".999") == hnsecs(9_990_000)); |
| assert(fracSecsFromISOString(".9900000") == hnsecs(9_900_000)); |
| assert(fracSecsFromISOString(".9900") == hnsecs(9_900_000)); |
| assert(fracSecsFromISOString(".99") == hnsecs(9_900_000)); |
| assert(fracSecsFromISOString(".9000000") == hnsecs(9_000_000)); |
| assert(fracSecsFromISOString(".9") == hnsecs(9_000_000)); |
| assert(fracSecsFromISOString(".0000999") == hnsecs(999)); |
| assert(fracSecsFromISOString(".0009990") == hnsecs(9990)); |
| assert(fracSecsFromISOString(".000999") == hnsecs(9990)); |
| assert(fracSecsFromISOString(".0099900") == hnsecs(99_900)); |
| assert(fracSecsFromISOString(".00999") == hnsecs(99_900)); |
| assert(fracSecsFromISOString(".0999000") == hnsecs(999_000)); |
| assert(fracSecsFromISOString(".0999") == hnsecs(999_000)); |
| assert(fracSecsFromISOString(".00000000") == Duration.zero); |
| assert(fracSecsFromISOString(".00000001") == Duration.zero); |
| assert(fracSecsFromISOString(".00000009") == Duration.zero); |
| assert(fracSecsFromISOString(".1234567890") == hnsecs(1_234_567)); |
| assert(fracSecsFromISOString(".12345678901234567890") == hnsecs(1_234_567)); |
| } |
| |
| |
| /+ |
| This function is used to split out the units without getting the remaining |
| hnsecs. |
| |
| Params: |
| units = The units to split out. |
| hnsecs = The current total hnsecs. |
| |
| Returns: |
| The split out value. |
| +/ |
| long getUnitsFromHNSecs(string units)(long hnsecs) @safe pure nothrow |
| if (validTimeUnits(units) && |
| CmpTimeUnits!(units, "months") < 0) |
| { |
| return convert!("hnsecs", units)(hnsecs); |
| } |
| |
| @safe unittest |
| { |
| auto hnsecs = 2595000000007L; |
| immutable days = getUnitsFromHNSecs!"days"(hnsecs); |
| assert(days == 3); |
| assert(hnsecs == 2595000000007L); |
| } |
| |
| |
| /+ |
| This function is used to split out the units without getting the units but |
| just the remaining hnsecs. |
| |
| Params: |
| units = The units to split out. |
| hnsecs = The current total hnsecs. |
| |
| Returns: |
| The remaining hnsecs. |
| +/ |
| long removeUnitsFromHNSecs(string units)(long hnsecs) @safe pure nothrow |
| if (validTimeUnits(units) && |
| CmpTimeUnits!(units, "months") < 0) |
| { |
| immutable value = convert!("hnsecs", units)(hnsecs); |
| return hnsecs - convert!(units, "hnsecs")(value); |
| } |
| |
| @safe unittest |
| { |
| auto hnsecs = 2595000000007L; |
| auto returned = removeUnitsFromHNSecs!"days"(hnsecs); |
| assert(returned == 3000000007); |
| assert(hnsecs == 2595000000007L); |
| } |
| |
| |
| /+ |
| Strips what RFC 5322, section 3.2.2 refers to as CFWS from the left-hand |
| side of the given range (it strips comments delimited by $(D '(') and |
| $(D ')') as well as folding whitespace). |
| |
| It is assumed that the given range contains the value of a header field and |
| no terminating CRLF for the line (though the CRLF for folding whitespace is |
| of course expected and stripped) and thus that the only case of CR or LF is |
| in folding whitespace. |
| |
| If a comment does not terminate correctly (e.g. mismatched parens) or if the |
| the FWS is malformed, then the range will be empty when stripCWFS is done. |
| However, only minimal validation of the content is done (e.g. quoted pairs |
| within a comment aren't validated beyond \$LPAREN or \$RPAREN, because |
| they're inside a comment, and thus their value doesn't matter anyway). It's |
| only when the content does not conform to the grammar rules for FWS and thus |
| literally cannot be parsed that content is considered invalid, and an empty |
| range is returned. |
| |
| Note that _stripCFWS is eager, not lazy. It does not create a new range. |
| Rather, it pops off the CFWS from the range and returns it. |
| +/ |
| R _stripCFWS(R)(R range) |
| if (isRandomAccessRange!R && hasSlicing!R && hasLength!R && |
| (is(Unqual!(ElementType!R) == char) || is(Unqual!(ElementType!R) == ubyte))) |
| { |
| immutable e = range.length; |
| outer: for (size_t i = 0; i < e; ) |
| { |
| switch (range[i]) |
| { |
| case ' ': case '\t': |
| { |
| ++i; |
| break; |
| } |
| case '\r': |
| { |
| if (i + 2 < e && range[i + 1] == '\n' && (range[i + 2] == ' ' || range[i + 2] == '\t')) |
| { |
| i += 3; |
| break; |
| } |
| break outer; |
| } |
| case '\n': |
| { |
| if (i + 1 < e && (range[i + 1] == ' ' || range[i + 1] == '\t')) |
| { |
| i += 2; |
| break; |
| } |
| break outer; |
| } |
| case '(': |
| { |
| ++i; |
| size_t commentLevel = 1; |
| while (i < e) |
| { |
| if (range[i] == '(') |
| ++commentLevel; |
| else if (range[i] == ')') |
| { |
| ++i; |
| if (--commentLevel == 0) |
| continue outer; |
| continue; |
| } |
| else if (range[i] == '\\') |
| { |
| if (++i == e) |
| break outer; |
| } |
| ++i; |
| } |
| break outer; |
| } |
| default: return range[i .. e]; |
| } |
| } |
| return range[e .. e]; |
| } |
| |
| @system unittest |
| { |
| import std.algorithm.comparison : equal; |
| import std.algorithm.iteration : map; |
| import std.meta : AliasSeq; |
| import std.stdio : writeln; |
| import std.string : representation; |
| |
| foreach (cr; AliasSeq!(function(string a){return cast(ubyte[]) a;}, |
| function(string a){return map!(b => cast(char) b)(a.representation);})) |
| (){ // avoid slow optimizations for large functions @@@BUG@@@ 2396 |
| scope(failure) writeln(typeof(cr).stringof); |
| |
| assert(_stripCFWS(cr("")).empty); |
| assert(_stripCFWS(cr("\r")).empty); |
| assert(_stripCFWS(cr("\r\n")).empty); |
| assert(_stripCFWS(cr("\r\n ")).empty); |
| assert(_stripCFWS(cr(" \t\r\n")).empty); |
| assert(equal(_stripCFWS(cr(" \t\r\n hello")), cr("hello"))); |
| assert(_stripCFWS(cr(" \t\r\nhello")).empty); |
| assert(_stripCFWS(cr(" \t\r\n\v")).empty); |
| assert(equal(_stripCFWS(cr("\v \t\r\n\v")), cr("\v \t\r\n\v"))); |
| assert(_stripCFWS(cr("()")).empty); |
| assert(_stripCFWS(cr("(hello world)")).empty); |
| assert(_stripCFWS(cr("(hello world)(hello world)")).empty); |
| assert(_stripCFWS(cr("(hello world\r\n foo\r where's\nwaldo)")).empty); |
| assert(_stripCFWS(cr(" \t (hello \tworld\r\n foo\r where's\nwaldo)\t\t ")).empty); |
| assert(_stripCFWS(cr(" ")).empty); |
| assert(_stripCFWS(cr("\t\t\t")).empty); |
| assert(_stripCFWS(cr("\t \r\n\r \n")).empty); |
| assert(_stripCFWS(cr("(hello world) (can't find waldo) (he's lost)")).empty); |
| assert(_stripCFWS(cr("(hello\\) world) (can't \\(find waldo) (he's \\(\\)lost)")).empty); |
| assert(_stripCFWS(cr("(((((")).empty); |
| assert(_stripCFWS(cr("(((()))")).empty); |
| assert(_stripCFWS(cr("(((())))")).empty); |
| assert(equal(_stripCFWS(cr("(((()))))")), cr(")"))); |
| assert(equal(_stripCFWS(cr(")))))")), cr(")))))"))); |
| assert(equal(_stripCFWS(cr("()))))")), cr("))))"))); |
| assert(equal(_stripCFWS(cr(" hello hello ")), cr("hello hello "))); |
| assert(equal(_stripCFWS(cr("\thello (world)")), cr("hello (world)"))); |
| assert(equal(_stripCFWS(cr(" \r\n \\((\\)) foo")), cr("\\((\\)) foo"))); |
| assert(equal(_stripCFWS(cr(" \r\n (\\((\\))) foo")), cr("foo"))); |
| assert(equal(_stripCFWS(cr(" \r\n (\\(())) foo")), cr(") foo"))); |
| assert(_stripCFWS(cr(" \r\n (((\\))) foo")).empty); |
| |
| assert(_stripCFWS(cr("(hello)(hello)")).empty); |
| assert(_stripCFWS(cr(" \r\n (hello)\r\n (hello)")).empty); |
| assert(_stripCFWS(cr(" \r\n (hello) \r\n (hello) \r\n ")).empty); |
| assert(_stripCFWS(cr("\t\t\t\t(hello)\t\t\t\t(hello)\t\t\t\t")).empty); |
| assert(equal(_stripCFWS(cr(" \r\n (hello)\r\n (hello) \r\n hello")), cr("hello"))); |
| assert(equal(_stripCFWS(cr(" \r\n (hello) \r\n (hello) \r\n hello")), cr("hello"))); |
| assert(equal(_stripCFWS(cr("\t\r\n\t(hello)\r\n\t(hello)\t\r\n hello")), cr("hello"))); |
| assert(equal(_stripCFWS(cr("\t\r\n\t(hello)\t\r\n\t(hello)\t\r\n hello")), cr("hello"))); |
| assert(equal(_stripCFWS(cr(" \r\n (hello) \r\n \r\n (hello) \r\n hello")), cr("hello"))); |
| assert(equal(_stripCFWS(cr(" \r\n (hello) \r\n (hello) \r\n \r\n hello")), cr("hello"))); |
| assert(equal(_stripCFWS(cr(" \r\n \r\n (hello)\t\r\n (hello) \r\n hello")), cr("hello"))); |
| assert(equal(_stripCFWS(cr(" \r\n\t\r\n\t(hello)\t\r\n (hello) \r\n hello")), cr("hello"))); |
| |
| assert(equal(_stripCFWS(cr(" (\r\n ( \r\n ) \r\n ) foo")), cr("foo"))); |
| assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n ) foo")), cr("foo"))); |
| assert(equal(_stripCFWS(cr(" (\t\r\n ( \r\n ) \r\n ) foo")), cr("foo"))); |
| assert(equal(_stripCFWS(cr(" (\r\n\t( \r\n ) \r\n ) foo")), cr("foo"))); |
| assert(equal(_stripCFWS(cr(" ( \r\n (\t\r\n ) \r\n ) foo")), cr("foo"))); |
| assert(equal(_stripCFWS(cr(" ( \r\n (\r\n ) \r\n ) foo")), cr("foo"))); |
| assert(equal(_stripCFWS(cr(" ( \r\n (\r\n\t) \r\n ) foo")), cr("foo"))); |
| assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n) \r\n ) foo")), cr("foo"))); |
| assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n )\t\r\n ) foo")), cr("foo"))); |
| assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n )\r\n ) foo")), cr("foo"))); |
| assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n) foo")), cr("foo"))); |
| assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n\t) foo")), cr("foo"))); |
| assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n ) \r\n foo")), cr("foo"))); |
| assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n )\t\r\n foo")), cr("foo"))); |
| assert(equal(_stripCFWS(cr(" ( \r\n ( \r\n ) \r\n )\r\n foo")), cr("foo"))); |
| |
| assert(equal(_stripCFWS(cr(" ( \r\n \r\n ( \r\n \r\n ) \r\n ) foo")), cr("foo"))); |
| assert(equal(_stripCFWS(cr(" ( \r\n \r\n ( \r\n \r\n ) \r\n ) foo")), cr("foo"))); |
| assert(equal(_stripCFWS(cr(" (\t\r\n \r\n ( \r\n \r\n ) \r\n ) foo")), cr("foo"))); |
| assert(equal(_stripCFWS(cr(" (\r\n \r\n\t( \r\n \r\n ) \r\n ) foo")), cr("foo"))); |
| assert(equal(_stripCFWS(cr(" (\r\n \r\n( \r\n \r\n ) \r\n ) foo")), cr("foo"))); |
| assert(equal(_stripCFWS(cr(" (\r\n \r\n ( \r\n \r\n\t) \r\n ) foo")), cr("foo"))); |
| assert(equal(_stripCFWS(cr(" (\r\n \r\n ( \r\n \r\n )\t\r\n ) foo")), cr("foo"))); |
| assert(equal(_stripCFWS(cr(" (\r\n \r\n ( \r\n \r\n )\r\n ) foo")), cr("foo"))); |
| |
| assert(equal(_stripCFWS(cr(" ( \r\n bar \r\n ( \r\n bar \r\n ) \r\n ) foo")), cr("foo"))); |
| assert(equal(_stripCFWS(cr(" ( \r\n () \r\n ( \r\n () \r\n ) \r\n ) foo")), cr("foo"))); |
| assert(equal(_stripCFWS(cr(" ( \r\n \\\\ \r\n ( \r\n \\\\ \r\n ) \r\n ) foo")), cr("foo"))); |
| |
| assert(_stripCFWS(cr("(hello)(hello)")).empty); |
| assert(_stripCFWS(cr(" \n (hello)\n (hello) \n ")).empty); |
| assert(_stripCFWS(cr(" \n (hello) \n (hello) \n ")).empty); |
| assert(equal(_stripCFWS(cr(" \n (hello)\n (hello) \n hello")), cr("hello"))); |
| assert(equal(_stripCFWS(cr(" \n (hello) \n (hello) \n hello")), cr("hello"))); |
| assert(equal(_stripCFWS(cr("\t\n\t(hello)\n\t(hello)\t\n hello")), cr("hello"))); |
| assert(equal(_stripCFWS(cr("\t\n\t(hello)\t\n\t(hello)\t\n hello")), cr("hello"))); |
| assert(equal(_stripCFWS(cr(" \n (hello) \n \n (hello) \n hello")), cr("hello"))); |
| assert(equal(_stripCFWS(cr(" \n (hello) \n (hello) \n \n hello")), cr("hello"))); |
| assert(equal(_stripCFWS(cr(" \n \n (hello)\t\n (hello) \n hello")), cr("hello"))); |
| assert(equal(_stripCFWS(cr(" \n\t\n\t(hello)\t\n (hello) \n hello")), cr("hello"))); |
| }(); |
| } |
| |
| // This is so that we don't have to worry about std.conv.to throwing. It also |
| // doesn't have to worry about quite as many cases as std.conv.to, since it |
| // doesn't have to worry about a sign on the value or about whether it fits. |
| T _convDigits(T, R)(R str) |
| if (isIntegral!T && isSigned!T) // The constraints on R were already covered by parseRFC822DateTime. |
| { |
| import std.ascii : isDigit; |
| |
| assert(!str.empty); |
| T num = 0; |
| foreach (i; 0 .. str.length) |
| { |
| if (i != 0) |
| num *= 10; |
| if (!isDigit(str[i])) |
| return -1; |
| num += str[i] - '0'; |
| } |
| return num; |
| } |
| |
| @safe unittest |
| { |
| import std.conv : to; |
| import std.range : chain, iota; |
| import std.stdio : writeln; |
| foreach (i; chain(iota(0, 101), [250, 999, 1000, 1001, 2345, 9999])) |
| { |
| scope(failure) writeln(i); |
| assert(_convDigits!int(to!string(i)) == i); |
| } |
| foreach (str; ["-42", "+42", "1a", "1 ", " ", " 42 "]) |
| { |
| scope(failure) writeln(str); |
| assert(_convDigits!int(str) == -1); |
| } |
| } |
| |
| |
| version (unittest) |
| { |
| // Variables to help in testing. |
| Duration currLocalDiffFromUTC; |
| immutable (TimeZone)[] testTZs; |
| |
| // All of these helper arrays are sorted in ascending order. |
| auto testYearsBC = [-1999, -1200, -600, -4, -1, 0]; |
| auto testYearsAD = [1, 4, 1000, 1999, 2000, 2012]; |
| |
| // I'd use a Tuple, but I get forward reference errors if I try. |
| struct MonthDay |
| { |
| Month month; |
| short day; |
| |
| this(int m, short d) |
| { |
| month = cast(Month) m; |
| day = d; |
| } |
| } |
| |
| MonthDay[] testMonthDays = [MonthDay(1, 1), |
| MonthDay(1, 2), |
| MonthDay(3, 17), |
| MonthDay(7, 4), |
| MonthDay(10, 27), |
| MonthDay(12, 30), |
| MonthDay(12, 31)]; |
| |
| auto testDays = [1, 2, 9, 10, 16, 20, 25, 28, 29, 30, 31]; |
| |
| auto testTODs = [TimeOfDay(0, 0, 0), |
| TimeOfDay(0, 0, 1), |
| TimeOfDay(0, 1, 0), |
| TimeOfDay(1, 0, 0), |
| TimeOfDay(13, 13, 13), |
| TimeOfDay(23, 59, 59)]; |
| |
| auto testHours = [0, 1, 12, 22, 23]; |
| auto testMinSecs = [0, 1, 30, 58, 59]; |
| |
| // Throwing exceptions is incredibly expensive, so we want to use a smaller |
| // set of values for tests using assertThrown. |
| auto testTODsThrown = [TimeOfDay(0, 0, 0), |
| TimeOfDay(13, 13, 13), |
| TimeOfDay(23, 59, 59)]; |
| |
| Date[] testDatesBC; |
| Date[] testDatesAD; |
| |
| DateTime[] testDateTimesBC; |
| DateTime[] testDateTimesAD; |
| |
| Duration[] testFracSecs; |
| |
| SysTime[] testSysTimesBC; |
| SysTime[] testSysTimesAD; |
| |
| // I'd use a Tuple, but I get forward reference errors if I try. |
| struct GregDay { int day; Date date; } |
| auto testGregDaysBC = [GregDay(-1_373_427, Date(-3760, 9, 7)), // Start of the Hebrew Calendar |
| GregDay(-735_233, Date(-2012, 1, 1)), |
| GregDay(-735_202, Date(-2012, 2, 1)), |
| GregDay(-735_175, Date(-2012, 2, 28)), |
| GregDay(-735_174, Date(-2012, 2, 29)), |
| GregDay(-735_173, Date(-2012, 3, 1)), |
| GregDay(-734_502, Date(-2010, 1, 1)), |
| GregDay(-734_472, Date(-2010, 1, 31)), |
| GregDay(-734_471, Date(-2010, 2, 1)), |
| GregDay(-734_444, Date(-2010, 2, 28)), |
| GregDay(-734_443, Date(-2010, 3, 1)), |
| GregDay(-734_413, Date(-2010, 3, 31)), |
| GregDay(-734_412, Date(-2010, 4, 1)), |
| GregDay(-734_383, Date(-2010, 4, 30)), |
| GregDay(-734_382, Date(-2010, 5, 1)), |
| GregDay(-734_352, Date(-2010, 5, 31)), |
| GregDay(-734_351, Date(-2010, 6, 1)), |
| GregDay(-734_322, Date(-2010, 6, 30)), |
| GregDay(-734_321, Date(-2010, 7, 1)), |
| GregDay(-734_291, Date(-2010, 7, 31)), |
| GregDay(-734_290, Date(-2010, 8, 1)), |
| GregDay(-734_260, Date(-2010, 8, 31)), |
| GregDay(-734_259, Date(-2010, 9, 1)), |
| GregDay(-734_230, Date(-2010, 9, 30)), |
| GregDay(-734_229, Date(-2010, 10, 1)), |
| GregDay(-734_199, Date(-2010, 10, 31)), |
| GregDay(-734_198, Date(-2010, 11, 1)), |
| GregDay(-734_169, Date(-2010, 11, 30)), |
| GregDay(-734_168, Date(-2010, 12, 1)), |
| GregDay(-734_139, Date(-2010, 12, 30)), |
| GregDay(-734_138, Date(-2010, 12, 31)), |
| GregDay(-731_215, Date(-2001, 1, 1)), |
| GregDay(-730_850, Date(-2000, 1, 1)), |
| GregDay(-730_849, Date(-2000, 1, 2)), |
| GregDay(-730_486, Date(-2000, 12, 30)), |
| GregDay(-730_485, Date(-2000, 12, 31)), |
| GregDay(-730_484, Date(-1999, 1, 1)), |
| GregDay(-694_690, Date(-1901, 1, 1)), |
| GregDay(-694_325, Date(-1900, 1, 1)), |
| GregDay(-585_118, Date(-1601, 1, 1)), |
| GregDay(-584_753, Date(-1600, 1, 1)), |
| GregDay(-584_388, Date(-1600, 12, 31)), |
| GregDay(-584_387, Date(-1599, 1, 1)), |
| GregDay(-365_972, Date(-1001, 1, 1)), |
| GregDay(-365_607, Date(-1000, 1, 1)), |
| GregDay(-183_351, Date(-501, 1, 1)), |
| GregDay(-182_986, Date(-500, 1, 1)), |
| GregDay(-182_621, Date(-499, 1, 1)), |
| GregDay(-146_827, Date(-401, 1, 1)), |
| GregDay(-146_462, Date(-400, 1, 1)), |
| GregDay(-146_097, Date(-400, 12, 31)), |
| GregDay(-110_302, Date(-301, 1, 1)), |
| GregDay(-109_937, Date(-300, 1, 1)), |
| GregDay(-73_778, Date(-201, 1, 1)), |
| GregDay(-73_413, Date(-200, 1, 1)), |
| GregDay(-38_715, Date(-105, 1, 1)), |
| GregDay(-37_254, Date(-101, 1, 1)), |
| GregDay(-36_889, Date(-100, 1, 1)), |
| GregDay(-36_524, Date(-99, 1, 1)), |
| GregDay(-36_160, Date(-99, 12, 31)), |
| GregDay(-35_794, Date(-97, 1, 1)), |
| GregDay(-18_627, Date(-50, 1, 1)), |
| GregDay(-18_262, Date(-49, 1, 1)), |
| GregDay(-3652, Date(-9, 1, 1)), |
| GregDay(-2191, Date(-5, 1, 1)), |
| GregDay(-1827, Date(-5, 12, 31)), |
| GregDay(-1826, Date(-4, 1, 1)), |
| GregDay(-1825, Date(-4, 1, 2)), |
| GregDay(-1462, Date(-4, 12, 30)), |
| GregDay(-1461, Date(-4, 12, 31)), |
| GregDay(-1460, Date(-3, 1, 1)), |
| GregDay(-1096, Date(-3, 12, 31)), |
| GregDay(-1095, Date(-2, 1, 1)), |
| GregDay(-731, Date(-2, 12, 31)), |
| GregDay(-730, Date(-1, 1, 1)), |
| GregDay(-367, Date(-1, 12, 30)), |
| GregDay(-366, Date(-1, 12, 31)), |
| GregDay(-365, Date(0, 1, 1)), |
| GregDay(-31, Date(0, 11, 30)), |
| GregDay(-30, Date(0, 12, 1)), |
| GregDay(-1, Date(0, 12, 30)), |
| GregDay(0, Date(0, 12, 31))]; |
| |
| auto testGregDaysAD = [GregDay(1, Date(1, 1, 1)), |
| GregDay(2, Date(1, 1, 2)), |
| GregDay(32, Date(1, 2, 1)), |
| GregDay(365, Date(1, 12, 31)), |
| GregDay(366, Date(2, 1, 1)), |
| GregDay(731, Date(3, 1, 1)), |
| GregDay(1096, Date(4, 1, 1)), |
| GregDay(1097, Date(4, 1, 2)), |
| GregDay(1460, Date(4, 12, 30)), |
| GregDay(1461, Date(4, 12, 31)), |
| GregDay(1462, Date(5, 1, 1)), |
| GregDay(17_898, Date(50, 1, 1)), |
| GregDay(35_065, Date(97, 1, 1)), |
| GregDay(36_160, Date(100, 1, 1)), |
| GregDay(36_525, Date(101, 1, 1)), |
| GregDay(37_986, Date(105, 1, 1)), |
| GregDay(72_684, Date(200, 1, 1)), |
| GregDay(73_049, Date(201, 1, 1)), |
| GregDay(109_208, Date(300, 1, 1)), |
| GregDay(109_573, Date(301, 1, 1)), |
| GregDay(145_732, Date(400, 1, 1)), |
| GregDay(146_098, Date(401, 1, 1)), |
| GregDay(182_257, Date(500, 1, 1)), |
| GregDay(182_622, Date(501, 1, 1)), |
| GregDay(364_878, Date(1000, 1, 1)), |
| GregDay(365_243, Date(1001, 1, 1)), |
| GregDay(584_023, Date(1600, 1, 1)), |
| GregDay(584_389, Date(1601, 1, 1)), |
| GregDay(693_596, Date(1900, 1, 1)), |
| GregDay(693_961, Date(1901, 1, 1)), |
| GregDay(729_755, Date(1999, 1, 1)), |
| GregDay(730_120, Date(2000, 1, 1)), |
| GregDay(730_121, Date(2000, 1, 2)), |
| GregDay(730_484, Date(2000, 12, 30)), |
| GregDay(730_485, Date(2000, 12, 31)), |
| GregDay(730_486, Date(2001, 1, 1)), |
| GregDay(733_773, Date(2010, 1, 1)), |
| GregDay(733_774, Date(2010, 1, 2)), |
| GregDay(733_803, Date(2010, 1, 31)), |
| GregDay(733_804, Date(2010, 2, 1)), |
| GregDay(733_831, Date(2010, 2, 28)), |
| GregDay(733_832, Date(2010, 3, 1)), |
| GregDay(733_862, Date(2010, 3, 31)), |
| GregDay(733_863, Date(2010, 4, 1)), |
| GregDay(733_892, Date(2010, 4, 30)), |
| GregDay(733_893, Date(2010, 5, 1)), |
| GregDay(733_923, Date(2010, 5, 31)), |
| GregDay(733_924, Date(2010, 6, 1)), |
| GregDay(733_953, Date(2010, 6, 30)), |
| GregDay(733_954, Date(2010, 7, 1)), |
| GregDay(733_984, Date(2010, 7, 31)), |
| GregDay(733_985, Date(2010, 8, 1)), |
| GregDay(734_015, Date(2010, 8, 31)), |
| GregDay(734_016, Date(2010, 9, 1)), |
| GregDay(734_045, Date(2010, 9, 30)), |
| GregDay(734_046, Date(2010, 10, 1)), |
| GregDay(734_076, Date(2010, 10, 31)), |
| GregDay(734_077, Date(2010, 11, 1)), |
| GregDay(734_106, Date(2010, 11, 30)), |
| GregDay(734_107, Date(2010, 12, 1)), |
| GregDay(734_136, Date(2010, 12, 30)), |
| GregDay(734_137, Date(2010, 12, 31)), |
| GregDay(734_503, Date(2012, 1, 1)), |
| GregDay(734_534, Date(2012, 2, 1)), |
| GregDay(734_561, Date(2012, 2, 28)), |
| GregDay(734_562, Date(2012, 2, 29)), |
| GregDay(734_563, Date(2012, 3, 1)), |
| GregDay(734_858, Date(2012, 12, 21))]; |
| |
| // I'd use a Tuple, but I get forward reference errors if I try. |
| struct DayOfYear { int day; MonthDay md; } |
| auto testDaysOfYear = [DayOfYear(1, MonthDay(1, 1)), |
| DayOfYear(2, MonthDay(1, 2)), |
| DayOfYear(3, MonthDay(1, 3)), |
| DayOfYear(31, MonthDay(1, 31)), |
| DayOfYear(32, MonthDay(2, 1)), |
| DayOfYear(59, MonthDay(2, 28)), |
| DayOfYear(60, MonthDay(3, 1)), |
| DayOfYear(90, MonthDay(3, 31)), |
| DayOfYear(91, MonthDay(4, 1)), |
| DayOfYear(120, MonthDay(4, 30)), |
| DayOfYear(121, MonthDay(5, 1)), |
| DayOfYear(151, MonthDay(5, 31)), |
| DayOfYear(152, MonthDay(6, 1)), |
| DayOfYear(181, MonthDay(6, 30)), |
| DayOfYear(182, MonthDay(7, 1)), |
| DayOfYear(212, MonthDay(7, 31)), |
| DayOfYear(213, MonthDay(8, 1)), |
| DayOfYear(243, MonthDay(8, 31)), |
| DayOfYear(244, MonthDay(9, 1)), |
| DayOfYear(273, MonthDay(9, 30)), |
| DayOfYear(274, MonthDay(10, 1)), |
| DayOfYear(304, MonthDay(10, 31)), |
| DayOfYear(305, MonthDay(11, 1)), |
| DayOfYear(334, MonthDay(11, 30)), |
| DayOfYear(335, MonthDay(12, 1)), |
| DayOfYear(363, MonthDay(12, 29)), |
| DayOfYear(364, MonthDay(12, 30)), |
| DayOfYear(365, MonthDay(12, 31))]; |
| |
| auto testDaysOfLeapYear = [DayOfYear(1, MonthDay(1, 1)), |
| DayOfYear(2, MonthDay(1, 2)), |
| DayOfYear(3, MonthDay(1, 3)), |
| DayOfYear(31, MonthDay(1, 31)), |
| DayOfYear(32, MonthDay(2, 1)), |
| DayOfYear(59, MonthDay(2, 28)), |
| DayOfYear(60, MonthDay(2, 29)), |
| DayOfYear(61, MonthDay(3, 1)), |
| DayOfYear(91, MonthDay(3, 31)), |
| DayOfYear(92, MonthDay(4, 1)), |
| DayOfYear(121, MonthDay(4, 30)), |
| DayOfYear(122, MonthDay(5, 1)), |
| DayOfYear(152, MonthDay(5, 31)), |
| DayOfYear(153, MonthDay(6, 1)), |
| DayOfYear(182, MonthDay(6, 30)), |
| DayOfYear(183, MonthDay(7, 1)), |
| DayOfYear(213, MonthDay(7, 31)), |
| DayOfYear(214, MonthDay(8, 1)), |
| DayOfYear(244, MonthDay(8, 31)), |
| DayOfYear(245, MonthDay(9, 1)), |
| DayOfYear(274, MonthDay(9, 30)), |
| DayOfYear(275, MonthDay(10, 1)), |
| DayOfYear(305, MonthDay(10, 31)), |
| DayOfYear(306, MonthDay(11, 1)), |
| DayOfYear(335, MonthDay(11, 30)), |
| DayOfYear(336, MonthDay(12, 1)), |
| DayOfYear(364, MonthDay(12, 29)), |
| DayOfYear(365, MonthDay(12, 30)), |
| DayOfYear(366, MonthDay(12, 31))]; |
| |
| void initializeTests() @safe |
| { |
| import std.algorithm.sorting : sort; |
| import std.typecons : Rebindable; |
| immutable lt = LocalTime().utcToTZ(0); |
| currLocalDiffFromUTC = dur!"hnsecs"(lt); |
| |
| version (Posix) |
| { |
| immutable otherTZ = lt < 0 ? PosixTimeZone.getTimeZone("Australia/Sydney") |
| : PosixTimeZone.getTimeZone("America/Denver"); |
| } |
| else version (Windows) |
| { |
| immutable otherTZ = lt < 0 ? WindowsTimeZone.getTimeZone("AUS Eastern Standard Time") |
| : WindowsTimeZone.getTimeZone("Mountain Standard Time"); |
| } |
| |
| immutable ot = otherTZ.utcToTZ(0); |
| |
| auto diffs = [0L, lt, ot]; |
| auto diffAA = [0L : Rebindable!(immutable TimeZone)(UTC())]; |
| diffAA[lt] = Rebindable!(immutable TimeZone)(LocalTime()); |
| diffAA[ot] = Rebindable!(immutable TimeZone)(otherTZ); |
| |
| sort(diffs); |
| testTZs = [diffAA[diffs[0]], diffAA[diffs[1]], diffAA[diffs[2]]]; |
| |
| testFracSecs = [Duration.zero, hnsecs(1), hnsecs(5007), hnsecs(9_999_999)]; |
| |
| foreach (year; testYearsBC) |
| { |
| foreach (md; testMonthDays) |
| testDatesBC ~= Date(year, md.month, md.day); |
| } |
| |
| foreach (year; testYearsAD) |
| { |
| foreach (md; testMonthDays) |
| testDatesAD ~= Date(year, md.month, md.day); |
| } |
| |
| foreach (dt; testDatesBC) |
| { |
| foreach (tod; testTODs) |
| testDateTimesBC ~= DateTime(dt, tod); |
| } |
| |
| foreach (dt; testDatesAD) |
| { |
| foreach (tod; testTODs) |
| testDateTimesAD ~= DateTime(dt, tod); |
| } |
| |
| foreach (dt; testDateTimesBC) |
| { |
| foreach (tz; testTZs) |
| { |
| foreach (fs; testFracSecs) |
| testSysTimesBC ~= SysTime(dt, fs, tz); |
| } |
| } |
| |
| foreach (dt; testDateTimesAD) |
| { |
| foreach (tz; testTZs) |
| { |
| foreach (fs; testFracSecs) |
| testSysTimesAD ~= SysTime(dt, fs, tz); |
| } |
| } |
| } |
| } |