| // 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; |
| |
| version (OSX) |
| version = Darwin; |
| else version (iOS) |
| version = Darwin; |
| else version (TVOS) |
| version = Darwin; |
| else version (WatchOS) |
| version = Darwin; |
| |
| 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(); |
| } |
| |
| version (unittest) private bool clockSupported(ClockType c) |
| { |
| // Skip unsupported clocks on older linux kernels, assume that only |
| // CLOCK_MONOTONIC and CLOCK_REALTIME exist, as that is the lowest |
| // common denominator supported by all versions of Linux pre-2.6.12. |
| version (Linux_Pre_2639) |
| return c == ClockType.normal || c == ClockType.precise; |
| else |
| return true; |
| } |
| |
| /++ |
| 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); |
| static if (clockSupported(ct)) |
| { |
| auto value1 = Clock.currTime!ct; |
| auto value2 = Clock.currTime!ct(UTC()); |
| assert(value1 <= value2, format("%s %s (ClockType: %s)", value1, value2, ct)); |
| assert(abs(value1 - value2) <= seconds(2), format("ClockType.%s", ct)); |
| } |
| } |
| } |
| |
| |
| /++ |
| 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 (Darwin) |
| { |
| static if (clockType == ClockType.second) |
| return unixTimeToStdTime(core.stdc.time.time(null)); |
| else |
| { |
| import core.sys.posix.sys.time : gettimeofday, timeval; |
| timeval tv = void; |
| // Posix gettimeofday called with a valid timeval address |
| // and a null second parameter doesn't fail. |
| gettimeofday(&tv, null); |
| return convert!("seconds", "hnsecs")(tv.tv_sec) + |
| tv.tv_usec * 10 + |
| 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 = void; |
| immutable error = clock_gettime(clockArg, &ts); |
| // Posix clock_gettime called with a valid address and valid clock_id is only |
| // permitted to fail if the number of seconds does not fit in time_t. If tv_sec |
| // is long or larger overflow won't happen before 292 billion years A.D. |
| static if (ts.tv_sec.max < long.max) |
| { |
| if (error) |
| 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 = void; |
| immutable error = clock_gettime(clockArg, &ts); |
| // Posix clock_gettime called with a valid address and valid clock_id is only |
| // permitted to fail if the number of seconds does not fit in time_t. If tv_sec |
| // is long or larger overflow won't happen before 292 billion years A.D. |
| static if (ts.tv_sec.max < long.max) |
| { |
| if (error) |
| 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.netbsd.time : clock_gettime, CLOCK_REALTIME; |
| timespec ts = void; |
| immutable error = clock_gettime(CLOCK_REALTIME, &ts); |
| // Posix clock_gettime called with a valid address and valid clock_id is only |
| // permitted to fail if the number of seconds does not fit in time_t. If tv_sec |
| // is long or larger overflow won't happen before 292 billion years A.D. |
| static if (ts.tv_sec.max < long.max) |
| { |
| if (error) |
| throw new TimeException("Call to clock_gettime() failed"); |
| } |
| return convert!("seconds", "hnsecs")(ts.tv_sec) + |
| ts.tv_nsec / 100 + |
| hnsecsToUnixEpoch; |
| } |
| } |
| else version (OpenBSD) |
| { |
| static if (clockType == ClockType.second) |
| return unixTimeToStdTime(core.stdc.time.time(null)); |
| else |
| { |
| import core.sys.openbsd.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 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 = void; |
| immutable error = clock_gettime(clockArg, &ts); |
| // Posix clock_gettime called with a valid address and valid clock_id is only |
| // permitted to fail if the number of seconds does not fit in time_t. If tv_sec |
| // is long or larger overflow won't happen before 292 billion years A.D. |
| static if (ts.tv_sec.max < long.max) |
| { |
| if (error) |
| 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 = void; |
| immutable error = clock_gettime(clockArg, &ts); |
| // Posix clock_gettime called with a valid address and valid clock_id is only |
| // permitted to fail if the number of seconds does not fit in time_t. If tv_sec |
| // is long or larger overflow won't happen before 292 billion years A.D. |
| static if (ts.tv_sec.max < long.max) |
| { |
| if (error) |
| 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); |
| static if (clockSupported(ct)) |
| { |
| auto value1 = Clock.currStdTime!ct; |
| auto value2 = Clock.currStdTime!ct; |
| assert(value1 <= value2, format("%s %s (ClockType: %s)", value1, value2, ct)); |
| 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))); |
| } |
| |
|