//Written in the D programming language
/++
Module containing Date/Time functionality.
This module provides:
$(UL
$(LI Types to represent points in time: SysTime, Date, TimeOfDay, and DateTime.)
$(LI Types to represent durations of time.)
$(LI Types to represent intervals of time.)
$(LI Types to represent ranges over intervals of time.)
$(LI Types to represent time zones (used by SysTime).)
$(LI A platform-independent, high precision stop watch type: StopWatch)
$(LI Benchmarking functions.)
$(LI Various helper functions.)
)
Three of the main concepts used in this module are time points, time durations,
and time intervals.
A time point is a specific point in time. e.g. January 5th, 2010
or 5:00.
A time duration is a length of time with units. e.g. 5 days or 231 seconds.
A time interval indicates a period of time associated with a fixed point in time.
So, it is either two time points associated with each other, indicating the time
starting at the first point up to, but not including, the second point - e.g.
[January 5th, 2010 - March 10th, 2010$(RPAREN) - or it is a time point and a time
duration associated with one another. e.g. January 5th, 2010 and 5 days,
indicating [January 5th, 2010 - January 10th, 2010$(RPAREN).
Various arithmetic operations are supported between time points and durations
(e.g. the difference between two time points is a time duration), and ranges
can be gotten from time intervals, so range-based operations may be done on a
series of time points.
The types that the typical user is most likely to be interested in are Date
(if they want dates but don't care about time), DateTime (if they want dates
and times but don't care about time zones), SysTime (if they want the date
and time from the OS and/or do care about time zones), and StopWatch (a
platform-independent, high precision stop watch). Date and DateTime are
optimized for calendar-based operations, while SysTime is designed for dealing
with time from the OS. Check out their specific documentation for more details.
To get the current time, use $(D Clock.currTime()). It will return the current
time as a SysTime. If you want to print it, simple $(D toString()) will do,
but if you use one of $(D toISOString()), $(D toISOExtendedString()), or
$(D toSimpleString()), you can use the corresponding $(D fromISOString()),
$(D fromISOExtendedString()), or $(D fromISOExtendedString()) to create a
$(D SysTime) from the string.
Examples:
--------------------
auto currentTime = Clock.currTime();
auto timeString = currentTime.toISOExtendedString();
auto restoredTime = SysTime.fromISOExtendedString(timeString);
--------------------
Various functions take a string (or strings) to represent a unit of time
(e.g. $(D convert!("days", "hours")(numDays))). The valid strings to use
with such functions are "years", "months", "weeks", "days", "hours",
"minutes", "seconds", "msecs" (milliseconds), "usecs" (microseconds),
"hnsecs" (hecto-nanoseconds - i.e. 100 ns) or some subset thereof. There
are a few functions in core.time which take "nsecs", but because nothing
in std.datetime has precision greater than hnsecs, and very little in
core.time does, no functions in std.datetime accept "nsecs".
Note:
core.time is publicly imported by std.datetime, so if you're using
std.datetime, you don't need to import core.time. Also, DateTimeException
is an alias for core.time's TimeException, so you don't need to worry
about core.time functions and std.datetime functions throwing a different
type of exception (except in the rare case that they throw something other
than TimeException or DateTimeException).
See_Also:
ISO 8601
Wikipedia entry on TZ database
List of Time Zones
Copyright: Copyright 2010
License: Boost License 1.0.
Authors: Jonathan M Davis and Kato Shoichi
+/
module std.datetime;
public import core.time;
import core.exception;
import core.stdc.time;
import std.array;
import std.algorithm;
import std.conv;
import std.ctype;
import std.exception;
import std.file;
import std.functional;
import std.math;
import std.metastrings;
import std.path;
import std.range;
import std.stdio;
import std.string;
import std.system;
import std.traits;
version(Windows)
{
import core.sys.windows.windows;
import std.c.windows.winsock;
//For system call to access the registry.
pragma(lib, "advapi32.lib");
}
else version(Posix)
{
import core.sys.posix.arpa.inet;
import core.sys.posix.stdlib;
import core.sys.posix.time;
import core.sys.posix.sys.time;
}
version(unittest)
{
import std.c.string;
}
alias std.string.indexOf indexOf;
alias std.math.abs abs;
//Note: There various functions which void as their return type and ref of the
// struct type which they're in as a commented out return type. Ideally,
// they would return the ref, but there are several dmd bugs which prevent
// that, relating to both ref and invariants. So, I've left the ref return
// types commented out with the idea that those functions can be made to
// return a ref to this once those bugs have been fixed.
//==============================================================================
// Section with public enums and constants.
//==============================================================================
/++
Represents the 12 months of the Gregorian year (January is 1).
+/
enum Month : ubyte { jan = 1, ///
feb, ///
mar, ///
apr, ///
may, ///
jun, ///
jul, ///
aug, ///
sep, ///
oct, ///
nov, ///
dec ///
}
/++
Represents the 7 days of the Gregorian week (Sunday is 0).
+/
enum DayOfWeek : ubyte { sun = 0, ///
mon, ///
tue, ///
wed, ///
thu, ///
fri, ///
sat ///
}
/++
In some date calculations, adding months or years can cause the date to fall on
a day of the month which is not valid (e.g. February 29th 2001 or June 31st 2000).
If overflow is allowed (as is the default), then the month will be incremented
accordingly (so, February 29th 2001 would become March 1st 2001, and June 31st 2000
would become July 1st 2000). If overflow is not allowed, then the day will be
adjusted to the last valid day in that month (so, February 29th 2001 would become
February 28th 2001 and June 31st 2000 would become June 30th 2000).
AllowDayOverflow only applies to calculations involving months or years.
+/
enum AllowDayOverflow
{
/// No, don't allow day overflow.
no,
/// Yes, allow day overflow.
yes
}
/++
Indicates a direction in time. One example of its use is $(D Interval)'s
$(D expand()) function which uses it to indicate whether the interval should
be expanded backwards (into the past), forwards (into the future), or both.
+/
enum Direction
{
/// Backward.
bwd,
/// Forward.
fwd,
/// Both backward and forward.
both
}
/++
Used to indicate whether $(D popFront()) should be called immediately upon
creating a range. The idea is that for some functions used to generate a
range for an interval, $(D front) is not necessarily a time point which would
ever be generated by the range, and if you want the first time point in the
range to match what the function generates, then you use $(D PopFirst.yes)
to indicate that the range should have $(D popFront()) called on it before the
range is returned so that $(D front) is a time point which the function would
generate.
For instance, if the function used to generate a range of time points generated
successive Easters (i.e. you're iterating over all of the Easters within the
interval), the initial date probably isn't an Easter. By using $(D PopFirst.yes),
you would be telling the function which returned the range that you wanted
$(D popFront()) to be called so that front would then be an Easter - the next
one generated by the function (which if you were iterating forward, would be
the Easter following the original $(D front), while if you were iterating backward,
it would be the Easter prior to the original $(D front)). If $(D PopFirst.no)
were used, then $(D front) would remain the original time point and it would
not necessarily be a time point which would be generated by the range-generating
function (which in many cases is exactly what you want - e.g. if you were
iterating over every day starting at the beginning of the interval).
+/
enum PopFirst
{
/// No, don't call popFront() before returning the range.
no,
/// Yes, call popFront() before returning the range.
yes
}
/++
Used by StopWatch to indicate whether it should start immediately upon construction.
+/
enum AutoStart
{
/// No, don't start the StopWatch when it is constructed.
no,
/// Yes, do start the StopWatch when it is constructed.
yes
}
/++
Array of the strings representing time units, starting with the smallest unit
and going to the largest. It does not include "nsecs".
"hnsecs" (hecto-nanoseconds (100 ns)), "usecs" (microseconds), "msecs" (milliseconds),
"seconds", "minutes", "hours", "days", "weeks", "months", "years"
+/
immutable string[] timeStrings = ["hnsecs", "usecs", "msecs", "seconds", "minutes",
"hours", "days", "weeks", "months", "years"];
//==============================================================================
// Section with time points.
//==============================================================================
/++
Represents a date in the Proleptic Gregorian Calendar ranging from 32,768 B.C.
to 32,767 A.D. Positive years are A.D. Non-positive years are B.C.
Year, month, and day are kept separately internally so that Date is optimized for
calendar operations.
Date uses the Proleptic Gregorian Calendar, so it assumes the Gregorian leap year
calculations for its entire length. And, as per ISO 8601, it also treats 1 B.C. as
year 0, so 1 B.C. is 0, 2 B.C. is -1, etc. Use $(D yearBC) if want B.C. as a positive
integer with 1 B.C. being the year prior to 1 A.D.
Year 0 is a leap year.
+/
struct Date
{
public:
/++
Throws:
DateTimeException if the resulting Date would not be valid.
Params:
year = Year of the Gregorian Calendar. Positive values are A.D.
Non-positive values are B.C. with year 0 being the year
prior to 1 A.D.
month = Month of the year.
day = Day of the month.
+/
this(int year, int month, int day) pure
{
enforceValid!"months"(cast(Month)month);
enforceValid!"days"(year, cast(Month)month, day);
_year = cast(short)year;
_month = cast(Month)month;
_day = cast(ubyte)day;
}
unittest
{
assertPred!"=="(Date(1, 1, 1), Date.init);
static void testDate(in Date date, int year, int month, int day, size_t line = __LINE__)
{
assertPred!"=="(date._year, year, "", __FILE__, line);
assertPred!"=="(date._month, month, "", __FILE__, line);
assertPred!"=="(date._day, day, "", __FILE__, line);
}
testDate(Date(1999, 1 , 1), 1999, Month.jan, 1);
testDate(Date(1999, 7 , 1), 1999, Month.jul, 1);
testDate(Date(1999, 7 , 6), 1999, Month.jul, 6);
//Test A.D.
assertThrown!DateTimeException(Date(1, 0, 1));
assertThrown!DateTimeException(Date(1, 1, 0));
assertThrown!DateTimeException(Date(1999, 13, 1));
assertThrown!DateTimeException(Date(1999, 1, 32));
assertThrown!DateTimeException(Date(1999, 2, 29));
assertThrown!DateTimeException(Date(2000, 2, 30));
assertThrown!DateTimeException(Date(1999, 3, 32));
assertThrown!DateTimeException(Date(1999, 4, 31));
assertThrown!DateTimeException(Date(1999, 5, 32));
assertThrown!DateTimeException(Date(1999, 6, 31));
assertThrown!DateTimeException(Date(1999, 7, 32));
assertThrown!DateTimeException(Date(1999, 8, 32));
assertThrown!DateTimeException(Date(1999, 9, 31));
assertThrown!DateTimeException(Date(1999, 10, 32));
assertThrown!DateTimeException(Date(1999, 11, 31));
assertThrown!DateTimeException(Date(1999, 12, 32));
assertNotThrown!DateTimeException(Date(1999, 1, 31));
assertNotThrown!DateTimeException(Date(1999, 2, 28));
assertNotThrown!DateTimeException(Date(2000, 2, 29));
assertNotThrown!DateTimeException(Date(1999, 3, 31));
assertNotThrown!DateTimeException(Date(1999, 4, 30));
assertNotThrown!DateTimeException(Date(1999, 5, 31));
assertNotThrown!DateTimeException(Date(1999, 6, 30));
assertNotThrown!DateTimeException(Date(1999, 7, 31));
assertNotThrown!DateTimeException(Date(1999, 8, 31));
assertNotThrown!DateTimeException(Date(1999, 9, 30));
assertNotThrown!DateTimeException(Date(1999, 10, 31));
assertNotThrown!DateTimeException(Date(1999, 11, 30));
assertNotThrown!DateTimeException(Date(1999, 12, 31));
//Test B.C.
assertNotThrown!DateTimeException(Date(0, 1, 1));
assertNotThrown!DateTimeException(Date(-1, 1, 1));
assertNotThrown!DateTimeException(Date(-1, 12, 31));
assertNotThrown!DateTimeException(Date(-1, 2, 28));
assertNotThrown!DateTimeException(Date(-4, 2, 29));
assertThrown!DateTimeException(Date(-1, 2, 29));
assertThrown!DateTimeException(Date(-2, 2, 29));
assertThrown!DateTimeException(Date(-3, 2, 29));
}
/++
Params:
day = The Xth day of the Gregorian Calendar that the constructed Date
will be for.
+/
this(int day) pure nothrow
{
if(day > 0)
{
int years = (day / daysIn400Years) * 400 + 1;
day %= daysIn400Years;
years += (day / daysIn100Years) * 100;
day %= daysIn100Years;
years += (day / daysIn4Years) * 4;
day %= daysIn4Years;
years += day / daysInYear;
day %= daysInYear;
if(day == 0)
{
_year = cast(short)(years - 1);
_month = Month.dec;
_day = 31;
}
else
{
_year = cast(short)years;
try
dayOfYear = day;
catch(Exception e)
assert(0, "dayOfYear assignment threw.");
}
}
else if(day <= 0 && -day < daysInLeapYear)
{
_year = 0;
try
dayOfYear = (daysInLeapYear + day);
catch(Exception e)
assert(0, "dayOfYear assignment threw.");
}
else
{
day += daysInLeapYear - 1;
int years = (day / daysIn400Years) * 400 - 1;
day %= daysIn400Years;
years += (day / daysIn100Years) * 100;
day %= daysIn100Years;
years += (day / daysIn4Years) * 4;
day %= daysIn4Years;
years += day / daysInYear;
day %= daysInYear;
if(day == 0)
{
_year = cast(short)(years + 1);
_month = Month.jan;
_day = 1;
}
else
{
_year = cast(short)years;
immutable newDoY = (yearIsLeapYear(_year) ? daysInLeapYear : daysInYear) + day + 1;
try
dayOfYear = newDoY;
catch(Exception e)
assert(0, "dayOfYear assignment threw.");
}
}
}
unittest
{
//Test A.D.
assertPred!"=="(Date(1), Date(1, 1, 1));
assertPred!"=="(Date(2), Date(1, 1, 2));
assertPred!"=="(Date(32), Date(1, 2, 1));
assertPred!"=="(Date(366), Date(2, 1, 1));
assertPred!"=="(Date(731), Date(3, 1, 1));
assertPred!"=="(Date(1096), Date(4, 1, 1));
assertPred!"=="(Date(1462), Date(5, 1, 1));
assertPred!"=="(Date(17_898), Date(50, 1, 1));
assertPred!"=="(Date(35_065), Date(97, 1, 1));
assertPred!"=="(Date(36_160), Date(100, 1, 1));
assertPred!"=="(Date(36_525), Date(101, 1, 1));
assertPred!"=="(Date(37_986), Date(105, 1, 1));
assertPred!"=="(Date(72_684), Date(200, 1, 1));
assertPred!"=="(Date(73_049), Date(201, 1, 1));
assertPred!"=="(Date(109_208), Date(300, 1, 1));
assertPred!"=="(Date(109_573), Date(301, 1, 1));
assertPred!"=="(Date(145_732), Date(400, 1, 1));
assertPred!"=="(Date(146_098), Date(401, 1, 1));
assertPred!"=="(Date(182_257), Date(500, 1, 1));
assertPred!"=="(Date(182_622), Date(501, 1, 1));
assertPred!"=="(Date(364_878), Date(1000, 1, 1));
assertPred!"=="(Date(365_243), Date(1001, 1, 1));
assertPred!"=="(Date(584_023), Date(1600, 1, 1));
assertPred!"=="(Date(584_389), Date(1601, 1, 1));
assertPred!"=="(Date(693_596), Date(1900, 1, 1));
assertPred!"=="(Date(693_961), Date(1901, 1, 1));
assertPred!"=="(Date(729_755), Date(1999, 1, 1));
assertPred!"=="(Date(730_120), Date(2000, 1, 1));
assertPred!"=="(Date(730_486), Date(2001, 1, 1));
assertPred!"=="(Date(733_773), Date(2010, 1, 1));
assertPred!"=="(Date(733_803), Date(2010, 1, 31));
assertPred!"=="(Date(733_804), Date(2010, 2, 1));
assertPred!"=="(Date(733_831), Date(2010, 2, 28));
assertPred!"=="(Date(733_832), Date(2010, 3, 1));
assertPred!"=="(Date(733_862), Date(2010, 3, 31));
assertPred!"=="(Date(733_863), Date(2010, 4, 1));
assertPred!"=="(Date(733_892), Date(2010, 4, 30));
assertPred!"=="(Date(733_893), Date(2010, 5, 1));
assertPred!"=="(Date(733_923), Date(2010, 5, 31));
assertPred!"=="(Date(733_924), Date(2010, 6, 1));
assertPred!"=="(Date(733_953), Date(2010, 6, 30));
assertPred!"=="(Date(733_954), Date(2010, 7, 1));
assertPred!"=="(Date(733_984), Date(2010, 7, 31));
assertPred!"=="(Date(733_985), Date(2010, 8, 1));
assertPred!"=="(Date(734_015), Date(2010, 8, 31));
assertPred!"=="(Date(734_016), Date(2010, 9, 1));
assertPred!"=="(Date(734_045), Date(2010, 9, 30));
assertPred!"=="(Date(734_046), Date(2010, 10, 1));
assertPred!"=="(Date(734_076), Date(2010, 10, 31));
assertPred!"=="(Date(734_077), Date(2010, 11, 1));
assertPred!"=="(Date(734_106), Date(2010, 11, 30));
assertPred!"=="(Date(734_107), Date(2010, 12, 1));
assertPred!"=="(Date(734_137), Date(2010, 12, 31));
assertPred!"=="(Date(734_534), Date(2012, 2, 1));
assertPred!"=="(Date(734_561), Date(2012, 2, 28));
assertPred!"=="(Date(734_562), Date(2012, 2, 29));
assertPred!"=="(Date(734_563), Date(2012, 3, 1));
assertPred!"=="(Date(734_534), Date(2012, 2, 1));
assertPred!"=="(Date(734_561), Date(2012, 2, 28));
assertPred!"=="(Date(734_562), Date(2012, 2, 29));
assertPred!"=="(Date(734_563), Date(2012, 3, 1));
//Test B.C.
assertPred!"=="(Date(0), Date(0, 12, 31));
assertPred!"=="(Date(-1), Date(0, 12, 30));
assertPred!"=="(Date(-30), Date(0, 12, 1));
assertPred!"=="(Date(-31), Date(0, 11, 30));
assertPred!"=="(Date(-366), Date(-1, 12, 31));
assertPred!"=="(Date(-367), Date(-1, 12, 30));
assertPred!"=="(Date(-730), Date(-1, 1, 1));
assertPred!"=="(Date(-731), Date(-2, 12, 31));
assertPred!"=="(Date(-1095), Date(-2, 1, 1));
assertPred!"=="(Date(-1096), Date(-3, 12, 31));
assertPred!"=="(Date(-1460), Date(-3, 1, 1));
assertPred!"=="(Date(-1461), Date(-4, 12, 31));
assertPred!"=="(Date(-1826), Date(-4, 1, 1));
assertPred!"=="(Date(-1827), Date(-5, 12, 31));
assertPred!"=="(Date(-2191), Date(-5, 1, 1));
assertPred!"=="(Date(-3652), Date(-9, 1, 1));
assertPred!"=="(Date(-18_262), Date(-49, 1, 1));
assertPred!"=="(Date(-18_627), Date(-50, 1, 1));
assertPred!"=="(Date(-35_794), Date(-97, 1, 1));
assertPred!"=="(Date(-36_160), Date(-99, 12, 31));
assertPred!"=="(Date(-36_524), Date(-99, 1, 1));
assertPred!"=="(Date(-36_889), Date(-100, 1, 1));
assertPred!"=="(Date(-37_254), Date(-101, 1, 1));
assertPred!"=="(Date(-38_715), Date(-105, 1, 1));
assertPred!"=="(Date(-73_413), Date(-200, 1, 1));
assertPred!"=="(Date(-73_778), Date(-201, 1, 1));
assertPred!"=="(Date(-109_937), Date(-300, 1, 1));
assertPred!"=="(Date(-110_302), Date(-301, 1, 1));
assertPred!"=="(Date(-146_097), Date(-400, 12, 31));
assertPred!"=="(Date(-146_462), Date(-400, 1, 1));
assertPred!"=="(Date(-146_827), Date(-401, 1, 1));
assertPred!"=="(Date(-182_621), Date(-499, 1, 1));
assertPred!"=="(Date(-182_986), Date(-500, 1, 1));
assertPred!"=="(Date(-183_351), Date(-501, 1, 1));
assertPred!"=="(Date(-365_607), Date(-1000, 1, 1));
assertPred!"=="(Date(-365_972), Date(-1001, 1, 1));
assertPred!"=="(Date(-584_387), Date(-1599, 1, 1));
assertPred!"=="(Date(-584_388), Date(-1600, 12, 31));
assertPred!"=="(Date(-584_753), Date(-1600, 1, 1));
assertPred!"=="(Date(-585_118), Date(-1601, 1, 1));
assertPred!"=="(Date(-694_325), Date(-1900, 1, 1));
assertPred!"=="(Date(-694_690), Date(-1901, 1, 1));
assertPred!"=="(Date(-730_484), Date(-1999, 1, 1));
assertPred!"=="(Date(-730_485), Date(-2000, 12, 31));
assertPred!"=="(Date(-730_850), Date(-2000, 1, 1));
assertPred!"=="(Date(-731_215), Date(-2001, 1, 1));
assertPred!"=="(Date(-734_502), Date(-2010, 1, 1));
assertPred!"=="(Date(-734_472), Date(-2010, 1, 31));
assertPred!"=="(Date(-734_471), Date(-2010, 2, 1));
assertPred!"=="(Date(-734_444), Date(-2010, 2, 28));
assertPred!"=="(Date(-734_443), Date(-2010, 3, 1));
assertPred!"=="(Date(-734_413), Date(-2010, 3, 31));
assertPred!"=="(Date(-734_412), Date(-2010, 4, 1));
assertPred!"=="(Date(-734_383), Date(-2010, 4, 30));
assertPred!"=="(Date(-734_382), Date(-2010, 5, 1));
assertPred!"=="(Date(-734_352), Date(-2010, 5, 31));
assertPred!"=="(Date(-734_351), Date(-2010, 6, 1));
assertPred!"=="(Date(-734_322), Date(-2010, 6, 30));
assertPred!"=="(Date(-734_321), Date(-2010, 7, 1));
assertPred!"=="(Date(-734_291), Date(-2010, 7, 31));
assertPred!"=="(Date(-734_290), Date(-2010, 8, 1));
assertPred!"=="(Date(-734_260), Date(-2010, 8, 31));
assertPred!"=="(Date(-734_259), Date(-2010, 9, 1));
assertPred!"=="(Date(-734_230), Date(-2010, 9, 30));
assertPred!"=="(Date(-734_229), Date(-2010, 10, 1));
assertPred!"=="(Date(-734_199), Date(-2010, 10, 31));
assertPred!"=="(Date(-734_198), Date(-2010, 11, 1));
assertPred!"=="(Date(-734_169), Date(-2010, 11, 30));
assertPred!"=="(Date(-734_168), Date(-2010, 12, 1));
assertPred!"=="(Date(-734_138), Date(-2010, 12, 31));
assertPred!"=="(Date(-735_202), Date(-2012, 2, 1));
assertPred!"=="(Date(-735_175), Date(-2012, 2, 28));
assertPred!"=="(Date(-735_174), Date(-2012, 2, 29));
assertPred!"=="(Date(-735_173), Date(-2012, 3, 1));
assertPred!"=="(Date(-1_373_427), Date(-3760, 9, 7)); //Start of the Hebrew Calendar
}
/++
Compares this Date with the given Date.
Returns:
$(TABLE
$(TR $(TD this < rhs) $(TD < 0))
$(TR $(TD this == rhs) $(TD 0))
$(TR $(TD this > rhs) $(TD > 0))
)
+/
int opCmp(in Date rhs) const pure nothrow
{
if(_year < rhs._year)
return -1;
if(_year > rhs._year)
return 1;
if(_month < rhs._month)
return -1;
if(_month > rhs._month)
return 1;
if(_day < rhs._day)
return -1;
if(_day > rhs._day)
return 1;
return 0;
}
unittest
{
//Test A.D.
assertPred!("opCmp", "==")(Date(1, 1, 1), Date.init);
assertPred!("opCmp", "==")(Date(1999, 1, 1), Date(1999, 1, 1));
assertPred!("opCmp", "==")(Date(1, 7, 1), Date(1, 7, 1));
assertPred!("opCmp", "==")(Date(1, 1, 6), Date(1, 1, 6));
assertPred!("opCmp", "==")(Date(1999, 7, 1), Date(1999, 7, 1));
assertPred!("opCmp", "==")(Date(1999, 7, 6), Date(1999, 7, 6));
assertPred!("opCmp", "==")(Date(1, 7, 6), Date(1, 7, 6));
assertPred!("opCmp", "<")(Date(1999, 7, 6), Date(2000, 7, 6));
assertPred!("opCmp", ">")(Date(2000, 7, 6), Date(1999, 7, 6));
assertPred!("opCmp", "<")(Date(1999, 7, 6), Date(1999, 8, 6));
assertPred!("opCmp", ">")(Date(1999, 8, 6), Date(1999, 7, 6));
assertPred!("opCmp", "<")(Date(1999, 7, 6), Date(1999, 7, 7));
assertPred!("opCmp", ">")(Date(1999, 7, 7), Date(1999, 7, 6));
assertPred!("opCmp", "<")(Date(1999, 8, 7), Date(2000, 7, 6));
assertPred!("opCmp", ">")(Date(2000, 8, 6), Date(1999, 7, 7));
assertPred!("opCmp", "<")(Date(1999, 7, 7), Date(2000, 7, 6));
assertPred!("opCmp", ">")(Date(2000, 7, 6), Date(1999, 7, 7));
assertPred!("opCmp", "<")(Date(1999, 7, 7), Date(1999, 8, 6));
assertPred!("opCmp", ">")(Date(1999, 8, 6), Date(1999, 7, 7));
//Test B.C.
assertPred!("opCmp", "==")(Date(0, 1, 1), Date(0, 1, 1));
assertPred!("opCmp", "==")(Date(-1, 1, 1), Date(-1, 1, 1));
assertPred!("opCmp", "==")(Date(-1, 7, 1), Date(-1, 7, 1));
assertPred!("opCmp", "==")(Date(-1, 1, 6), Date(-1, 1, 6));
assertPred!("opCmp", "==")(Date(-1999, 7, 1), Date(-1999, 7, 1));
assertPred!("opCmp", "==")(Date(-1999, 7, 6), Date(-1999, 7, 6));
assertPred!("opCmp", "==")(Date(-1, 7, 6), Date(-1, 7, 6));
assertPred!("opCmp", "<")(Date(-2000, 7, 6), Date(-1999, 7, 6));
assertPred!("opCmp", ">")(Date(-1999, 7, 6), Date(-2000, 7, 6));
assertPred!("opCmp", "<")(Date(-1999, 7, 6), Date(-1999, 8, 6));
assertPred!("opCmp", ">")(Date(-1999, 8, 6), Date(-1999, 7, 6));
assertPred!("opCmp", "<")(Date(-1999, 7, 6), Date(-1999, 7, 7));
assertPred!("opCmp", ">")(Date(-1999, 7, 7), Date(-1999, 7, 6));
assertPred!("opCmp", "<")(Date(-2000, 8, 6), Date(-1999, 7, 7));
assertPred!("opCmp", ">")(Date(-1999, 8, 7), Date(-2000, 7, 6));
assertPred!("opCmp", "<")(Date(-2000, 7, 6), Date(-1999, 7, 7));
assertPred!("opCmp", ">")(Date(-1999, 7, 7), Date(-2000, 7, 6));
assertPred!("opCmp", "<")(Date(-1999, 7, 7), Date(-1999, 8, 6));
assertPred!("opCmp", ">")(Date(-1999, 8, 6), Date(-1999, 7, 7));
//Test Both
assertPred!("opCmp", "<")(Date(-1999, 7, 6), Date(1999, 7, 6));
assertPred!("opCmp", ">")(Date(1999, 7, 6), Date(-1999, 7, 6));
assertPred!("opCmp", "<")(Date(-1999, 8, 6), Date(1999, 7, 6));
assertPred!("opCmp", ">")(Date(1999, 7, 6), Date(-1999, 8, 6));
assertPred!("opCmp", "<")(Date(-1999, 7, 7), Date(1999, 7, 6));
assertPred!("opCmp", ">")(Date(1999, 7, 6), Date(-1999, 7, 7));
assertPred!("opCmp", "<")(Date(-1999, 8, 7), Date(1999, 7, 6));
assertPred!("opCmp", ">")(Date(1999, 7, 6), Date(-1999, 8, 7));
assertPred!("opCmp", "<")(Date(-1999, 8, 6), Date(1999, 6, 6));
assertPred!("opCmp", ">")(Date(1999, 6, 8), Date(-1999, 7, 6));
auto date = Date(1999, 7, 6);
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(__traits(compiles, date.opCmp(date)));
static assert(__traits(compiles, date.opCmp(cdate)));
static assert(__traits(compiles, date.opCmp(idate)));
static assert(__traits(compiles, cdate.opCmp(date)));
static assert(__traits(compiles, cdate.opCmp(cdate)));
static assert(__traits(compiles, cdate.opCmp(idate)));
static assert(__traits(compiles, idate.opCmp(date)));
static assert(__traits(compiles, idate.opCmp(cdate)));
static assert(__traits(compiles, idate.opCmp(idate)));
}
/++
Year of the Gregorian Calendar. Positive numbers are A.D. Non-positive
are B.C.
Examples:
--------------------
assert(Date(1999, 7, 6).year == 1999);
assert(Date(2010, 10, 4).year == 2010);
assert(Date(-7, 4, 5).year == -7);
--------------------
+/
@property short year() const pure nothrow
{
return _year;
}
unittest
{
assertPred!"=="(Date.init.year, 1);
assertPred!"=="(Date(1999, 7, 6).year, 1999);
assertPred!"=="(Date(-1999, 7, 6).year, -1999);
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(__traits(compiles, cdate.year == 1999));
static assert(__traits(compiles, idate.year == 1999));
//Verify Examples.
assert(Date(1999, 7, 6).year == 1999);
assert(Date(2010, 10, 4).year == 2010);
assert(Date(-7, 4, 5).year == -7);
}
/++
Year of the Gregorian Calendar. Positive numbers are A.D. Non-positive
are B.C.
Params:
year = The year to set this Date's year to.
Throws:
DateTimeException if the new year is not a leap year and the resulting
date would be on February 29th.
+/
@property void year(int year) pure
{
enforceValid!"days"(year, _month, _day);
_year = cast(short)year;
}
unittest
{
static void testDateInvalid(Date date, int year)
{
date.year = year;
}
static void testDate(Date date, int year, in Date expected, size_t line = __LINE__)
{
date.year = year;
assertPred!"=="(date, expected, "", __FILE__, line);
}
assertThrown!DateTimeException(testDateInvalid(Date(4, 2, 29), 1));
testDate(Date(1, 1, 1), 1999, Date(1999, 1, 1));
testDate(Date(1, 1, 1), 0, Date(0, 1, 1));
testDate(Date(1, 1, 1), -1999, Date(-1999, 1, 1));
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(!__traits(compiles, cdate.year = 1999));
static assert(!__traits(compiles, idate.year = 1999));
//Verify Examples.
assert(Date(1999, 7, 6).year == 1999);
assert(Date(2010, 10, 4).year == 2010);
assert(Date(-7, 4, 5).year == -7);
}
/++
Year B.C. of the Gregorian Calendar counting year 0 as 1 B.C.
Throws:
DateTimeException if $(D isAD) is true.
Examples:
--------------------
assert(Date(0, 1, 1).yearBC == 1);
assert(Date(-1, 1, 1).yearBC == 2);
assert(Date(-100, 1, 1).yearBC == 101);
--------------------
+/
@property ushort yearBC() const pure
{
if(isAD)
throw new DateTimeException("Year " ~ numToString(_year) ~ " is A.D.");
//Once format is pure, this would be a better error message.
//throw new DateTimeException(format("%s is A.D.", this));
return cast(ushort)((_year * -1) + 1);
}
unittest
{
assertThrown!DateTimeException((in Date date){date.yearBC;}(Date(1, 1, 1)));
auto date = Date(0, 7, 6);
const cdate = Date(0, 7, 6);
immutable idate = Date(0, 7, 6);
static assert(__traits(compiles, date.yearBC));
static assert(__traits(compiles, cdate.yearBC));
static assert(__traits(compiles, idate.yearBC));
//Verify Examples.
assert(Date(0, 1, 1).yearBC == 1);
assert(Date(-1, 1, 1).yearBC == 2);
assert(Date(-100, 1, 1).yearBC == 101);
}
/++
Year B.C. of the Gregorian Calendar counting year 0 as 1 B.C.
Params:
year = The year B.C. to set this Date's year to.
Throws:
DateTimeException if a non-positive value is given.
Examples:
--------------------
auto date = Date(2010, 1, 1);
date.yearBC = 1;
assert(date == Date(0, 1, 1));
date.yearBC = 10;
assert(date == Date(-9, 1, 1));
--------------------
+/
@property void yearBC(int year) pure
{
if(year <= 0)
throw new DateTimeException("The given year is not a year B.C.");
_year = cast(short)((year - 1) * -1);
}
unittest
{
assertThrown!DateTimeException((Date date){date.yearBC = -1;}(Date(1, 1, 1)));
{
auto date = Date(0, 7, 6);
const cdate = Date(0, 7, 6);
immutable idate = Date(0, 7, 6);
static assert(__traits(compiles, date.yearBC = 7));
static assert(!__traits(compiles, cdate.yearBC = 7));
static assert(!__traits(compiles, idate.yearBC = 7));
}
//Verify Examples.
{
auto date = Date(2010, 1, 1);
date.yearBC = 1;
assert(date == Date(0, 1, 1));
date.yearBC = 10;
assert(date == Date(-9, 1, 1));
}
}
/++
Month of a Gregorian Year.
Examples:
--------------------
assert(Date(1999, 7, 6).month == 7);
assert(Date(2010, 10, 4).month == 10);
assert(Date(-7, 4, 5).month == 4);
--------------------
+/
@property Month month() const pure nothrow
{
return _month;
}
unittest
{
assertPred!"=="(Date.init.month, 1);
assertPred!"=="(Date(1999, 7, 6).month, 7);
assertPred!"=="(Date(-1999, 7, 6).month, 7);
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(__traits(compiles, cdate.month == 7));
static assert(__traits(compiles, idate.month == 7));
//Verify Examples.
assert(Date(1999, 7, 6).month == 7);
assert(Date(2010, 10, 4).month == 10);
assert(Date(-7, 4, 5).month == 4);
}
/++
Month of a Gregorian Year.
Params:
month = The month to set this Date's month to.
Throws:
DateTimeException if the given month is not a valid month or if
the current day would not be valid in the given month.
+/
@property void month(Month month) pure
{
enforceValid!"months"(month);
enforceValid!"days"(_year, month, _day);
_month = cast(Month)month;
}
unittest
{
static void testDate(Date date, Month month, in Date expected = Date.init, size_t line = __LINE__)
{
date.month = month;
assert(expected != Date.init);
assertPred!"=="(date, expected, "", __FILE__, line);
}
assertThrown!DateTimeException(testDate(Date(1, 1, 1), cast(Month)0));
assertThrown!DateTimeException(testDate(Date(1, 1, 1), cast(Month)13));
assertThrown!DateTimeException(testDate(Date(1, 1, 29), cast(Month)2));
assertThrown!DateTimeException(testDate(Date(0, 1, 30), cast(Month)2));
testDate(Date(1, 1, 1), cast(Month)7, Date(1, 7, 1));
testDate(Date(-1, 1, 1), cast(Month)7, Date(-1, 7, 1));
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(!__traits(compiles, cdate.month = 7));
static assert(!__traits(compiles, idate.month = 7));
}
/++
Day of a Gregorian Month.
Examples:
--------------------
assert(Date(1999, 7, 6).day == 6);
assert(Date(2010, 10, 4).day == 4);
assert(Date(-7, 4, 5).day == 5);
--------------------
+/
@property ubyte day() const pure nothrow
{
return _day;
}
unittest
{
assertPred!"=="(Date.init.day, 1);
assertPred!"=="(Date(1999, 7, 6).day, 6);
assertPred!"=="(Date(-1999, 7, 6).day, 6);
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(__traits(compiles, cdate.day == 6));
static assert(__traits(compiles, idate.day == 6));
//Verify Examples.
assert(Date(1999, 7, 6).day == 6);
assert(Date(2010, 10, 4).day == 4);
assert(Date(-7, 4, 5).day == 5);
}
/++
Day of a Gregorian Month.
Params:
day = The day of the month to set this Date's day to.
Throws:
DateTimeException if the given day is not a valid day of the current month.
+/
@property void day(int day) pure
{
enforceValid!"days"(_year, _month, day);
_day = cast(ubyte)day;
}
unittest
{
static void testDate(Date date, int day)
{
date.day = day;
}
//Test A.D.
assertThrown!DateTimeException(testDate(Date(1, 1, 1), 0));
assertThrown!DateTimeException(testDate(Date(1, 1, 1), 32));
assertThrown!DateTimeException(testDate(Date(1, 2, 1), 29));
assertThrown!DateTimeException(testDate(Date(4, 2, 1), 30));
assertThrown!DateTimeException(testDate(Date(1, 3, 1), 32));
assertThrown!DateTimeException(testDate(Date(1, 4, 1), 31));
assertThrown!DateTimeException(testDate(Date(1, 5, 1), 32));
assertThrown!DateTimeException(testDate(Date(1, 6, 1), 31));
assertThrown!DateTimeException(testDate(Date(1, 7, 1), 32));
assertThrown!DateTimeException(testDate(Date(1, 8, 1), 32));
assertThrown!DateTimeException(testDate(Date(1, 9, 1), 31));
assertThrown!DateTimeException(testDate(Date(1, 10, 1), 32));
assertThrown!DateTimeException(testDate(Date(1, 11, 1), 31));
assertThrown!DateTimeException(testDate(Date(1, 12, 1), 32));
assertNotThrown!DateTimeException(testDate(Date(1, 1, 1), 31));
assertNotThrown!DateTimeException(testDate(Date(1, 2, 1), 28));
assertNotThrown!DateTimeException(testDate(Date(4, 2, 1), 29));
assertNotThrown!DateTimeException(testDate(Date(1, 3, 1), 31));
assertNotThrown!DateTimeException(testDate(Date(1, 4, 1), 30));
assertNotThrown!DateTimeException(testDate(Date(1, 5, 1), 31));
assertNotThrown!DateTimeException(testDate(Date(1, 6, 1), 30));
assertNotThrown!DateTimeException(testDate(Date(1, 7, 1), 31));
assertNotThrown!DateTimeException(testDate(Date(1, 8, 1), 31));
assertNotThrown!DateTimeException(testDate(Date(1, 9, 1), 30));
assertNotThrown!DateTimeException(testDate(Date(1, 10, 1), 31));
assertNotThrown!DateTimeException(testDate(Date(1, 11, 1), 30));
assertNotThrown!DateTimeException(testDate(Date(1, 12, 1), 31));
{
auto date = Date(1, 1, 1);
date.day = 6;
assertPred!"=="(date, Date(1, 1, 6));
}
//Test B.C.
assertThrown!DateTimeException(testDate(Date(-1, 1, 1), 0));
assertThrown!DateTimeException(testDate(Date(-1, 1, 1), 32));
assertThrown!DateTimeException(testDate(Date(-1, 2, 1), 29));
assertThrown!DateTimeException(testDate(Date(0, 2, 1), 30));
assertThrown!DateTimeException(testDate(Date(-1, 3, 1), 32));
assertThrown!DateTimeException(testDate(Date(-1, 4, 1), 31));
assertThrown!DateTimeException(testDate(Date(-1, 5, 1), 32));
assertThrown!DateTimeException(testDate(Date(-1, 6, 1), 31));
assertThrown!DateTimeException(testDate(Date(-1, 7, 1), 32));
assertThrown!DateTimeException(testDate(Date(-1, 8, 1), 32));
assertThrown!DateTimeException(testDate(Date(-1, 9, 1), 31));
assertThrown!DateTimeException(testDate(Date(-1, 10, 1), 32));
assertThrown!DateTimeException(testDate(Date(-1, 11, 1), 31));
assertThrown!DateTimeException(testDate(Date(-1, 12, 1), 32));
assertNotThrown!DateTimeException(testDate(Date(-1, 1, 1), 31));
assertNotThrown!DateTimeException(testDate(Date(-1, 2, 1), 28));
assertNotThrown!DateTimeException(testDate(Date(0, 2, 1), 29));
assertNotThrown!DateTimeException(testDate(Date(-1, 3, 1), 31));
assertNotThrown!DateTimeException(testDate(Date(-1, 4, 1), 30));
assertNotThrown!DateTimeException(testDate(Date(-1, 5, 1), 31));
assertNotThrown!DateTimeException(testDate(Date(-1, 6, 1), 30));
assertNotThrown!DateTimeException(testDate(Date(-1, 7, 1), 31));
assertNotThrown!DateTimeException(testDate(Date(-1, 8, 1), 31));
assertNotThrown!DateTimeException(testDate(Date(-1, 9, 1), 30));
assertNotThrown!DateTimeException(testDate(Date(-1, 10, 1), 31));
assertNotThrown!DateTimeException(testDate(Date(-1, 11, 1), 30));
assertNotThrown!DateTimeException(testDate(Date(-1, 12, 1), 31));
{
auto date = Date(-1, 1, 1);
date.day = 6;
assertPred!"=="(date, Date(-1, 1, 6));
}
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(!__traits(compiles, cdate.day = 6));
static assert(!__traits(compiles, idate.day = 6));
}
/++
Adds the given number of years to this Date. A negative number will subtract.
Note that if day overflow is allowed, and the date is Febuary 29th of a
leap year, and the new year is not a leap year, then the date is shifted
to March 1st. If day overflow is not allowed, then the date is shifted to
February 28th.
Params:
years = The number of years to add to this Date.
allowOverflow = Whether the days should be allowed to overflow, causing
the month to increment.
Examples:
--------------------
auto date1 = Date(2010, 1, 1);
date1.add!"years"(1);
assert(date1 == Date(2011, 1, 1));
auto date2 = Date(2010, 1, 1);
date2.add!"years"(-1);
assert(date2 == Date(2009, 1, 1));
auto date3 = Date(2000, 2, 29);
date3.add!"years"(1);
assert(date3 == Date(2001, 3, 1));
auto date4 = Date(2000, 2, 29);
date4.add!"years"(1, AllowDayOverflow.no);
assert(date4 == Date(2001, 2, 28));
--------------------
+/
/+ref Date+/ void add(string units)(long years, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) pure nothrow
if(units == "years")
{
immutable newYear = _year + years;
_year += years;
if(_month == Month.feb && _day == 29 && !yearIsLeapYear(_year))
{
if(allowOverflow == AllowDayOverflow.yes)
{
_month = Month.mar;
_day = 1;
}
else
_day = 28;
}
}
//Test add!"years"() with AllowDayOverlow.yes
unittest
{
//Test A.D.
{
auto date = Date(1999, 7, 6);
date.add!"years"(7);
assertPred!"=="(date, Date(2006, 7, 6));
date.add!"years"(-9);
assertPred!"=="(date, Date(1997, 7, 6));
}
{
auto date = Date(1999, 2, 28);
date.add!"years"(1);
assertPred!"=="(date, Date(2000, 2, 28));
}
{
auto date = Date(2000, 2, 29);
date.add!"years"(-1);
assertPred!"=="(date, Date(1999, 3, 1));
}
//Test B.C.
{
auto date = Date(-1999, 7, 6);
date.add!"years"(-7);
assertPred!"=="(date, Date(-2006, 7, 6));
date.add!"years"(9);
assertPred!"=="(date, Date(-1997, 7, 6));
}
{
auto date = Date(-1999, 2, 28);
date.add!"years"(-1);
assertPred!"=="(date, Date(-2000, 2, 28));
}
{
auto date = Date(-2000, 2, 29);
date.add!"years"(1);
assertPred!"=="(date, Date(-1999, 3, 1));
}
//Test Both
{
auto date = Date(4, 7, 6);
date.add!"years"(-5);
assertPred!"=="(date, Date(-1, 7, 6));
date.add!"years"(5);
assertPred!"=="(date, Date(4, 7, 6));
}
{
auto date = Date(-4, 7, 6);
date.add!"years"(5);
assertPred!"=="(date, Date(1, 7, 6));
date.add!"years"(-5);
assertPred!"=="(date, Date(-4, 7, 6));
}
{
auto date = Date(4, 7, 6);
date.add!"years"(-8);
assertPred!"=="(date, Date(-4, 7, 6));
date.add!"years"(8);
assertPred!"=="(date, Date(4, 7, 6));
}
{
auto date = Date(-4, 7, 6);
date.add!"years"(8);
assertPred!"=="(date, Date(4, 7, 6));
date.add!"years"(-8);
assertPred!"=="(date, Date(-4, 7, 6));
}
{
auto date = Date(-4, 2, 29);
date.add!"years"(5);
assertPred!"=="(date, Date(1, 3, 1));
}
{
auto date = Date(4, 2, 29);
date.add!"years"(-5);
assertPred!"=="(date, Date(-1, 3, 1));
}
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(!__traits(compiles, cdate.add!"years"(7)));
static assert(!__traits(compiles, idate.add!"years"(7)));
//Verify Examples.
auto date1 = Date(2010, 1, 1);
date1.add!"years"(1);
assert(date1 == Date(2011, 1, 1));
auto date2 = Date(2010, 1, 1);
date2.add!"years"(-1);
assert(date2 == Date(2009, 1, 1));
auto date3 = Date(2000, 2, 29);
date3.add!"years"(1);
assert(date3 == Date(2001, 3, 1));
auto date4 = Date(2000, 2, 29);
date4.add!"years"(1, AllowDayOverflow.no);
assert(date4 == Date(2001, 2, 28));
}
//Test add!"years"() with AllowDayOverlow.no
unittest
{
//Test A.D.
{
auto date = Date(1999, 7, 6);
date.add!"years"(7, AllowDayOverflow.no);
assertPred!"=="(date, Date(2006, 7, 6));
date.add!"years"(-9, AllowDayOverflow.no);
assertPred!"=="(date, Date(1997, 7, 6));
}
{
auto date = Date(1999, 2, 28);
date.add!"years"(1, AllowDayOverflow.no);
assertPred!"=="(date, Date(2000, 2, 28));
}
{
auto date = Date(2000, 2, 29);
date.add!"years"(-1, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 2, 28));
}
//Test B.C.
{
auto date = Date(-1999, 7, 6);
date.add!"years"(-7, AllowDayOverflow.no);
assertPred!"=="(date, Date(-2006, 7, 6));
date.add!"years"(9, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1997, 7, 6));
}
{
auto date = Date(-1999, 2, 28);
date.add!"years"(-1, AllowDayOverflow.no);
assertPred!"=="(date, Date(-2000, 2, 28));
}
{
auto date = Date(-2000, 2, 29);
date.add!"years"(1, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1999, 2, 28));
}
//Test Both
{
auto date = Date(4, 7, 6);
date.add!"years"(-5, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1, 7, 6));
date.add!"years"(5, AllowDayOverflow.no);
assertPred!"=="(date, Date(4, 7, 6));
}
{
auto date = Date(-4, 7, 6);
date.add!"years"(5, AllowDayOverflow.no);
assertPred!"=="(date, Date(1, 7, 6));
date.add!"years"(-5, AllowDayOverflow.no);
assertPred!"=="(date, Date(-4, 7, 6));
}
{
auto date = Date(4, 7, 6);
date.add!"years"(-8, AllowDayOverflow.no);
assertPred!"=="(date, Date(-4, 7, 6));
date.add!"years"(8, AllowDayOverflow.no);
assertPred!"=="(date, Date(4, 7, 6));
}
{
auto date = Date(-4, 7, 6);
date.add!"years"(8, AllowDayOverflow.no);
assertPred!"=="(date, Date(4, 7, 6));
date.add!"years"(-8, AllowDayOverflow.no);
assertPred!"=="(date, Date(-4, 7, 6));
}
{
auto date = Date(-4, 2, 29);
date.add!"years"(5, AllowDayOverflow.no);
assertPred!"=="(date, Date(1, 2, 28));
}
{
auto date = Date(4, 2, 29);
date.add!"years"(-5, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1, 2, 28));
}
}
/++
Adds the given number of months to this Date. A negative number will subtract.
The year will be adjusted along with the month if the number of months added
(or subtracted) would overflow (or underflow) the current year.
Note that if day overflow is allowed, and the date with the adjusted month
overflows the number of days in the new month, then the month will be
incremented by one, and the days 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:
months = The number of months to add to this Date.
allowOverflow = Whether the days should be allowed to overflow, causing
the month to increment.
Examples:
--------------------
auto date1 = Date(2010, 1, 1);
date1.add!"months"(1);
assert(date1 == Date(2010, 2, 1));
auto date2 = Date(2010, 1, 1);
date2.add!"months"(-1);
assert(date2 == Date(2009, 12, 1));
auto date3 = Date(1999, 1, 29);
date3.add!"months"(1);
assert(date3 == Date(1999, 3, 1));
auto date4 = Date(1999, 1, 29);
date4.add!"months"(1, AllowDayOverflow.no);
assert(date4 == Date(1999, 2, 28));
--------------------
+/
/+ref Date+/ void add(string units)(long months, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) pure nothrow
if(units == "months")
{
auto years = months / 12;
months %= 12;
auto newMonth = _month + months;
if(months < 0)
{
if(newMonth < 1)
{
newMonth += 12;
--years;
}
}
else if(newMonth > 12)
{
newMonth -= 12;
++years;
}
_year += years;
_month = cast(Month)newMonth;
immutable currMaxDay = maxDay(_year, _month);
immutable overflow = _day - currMaxDay;
if(overflow > 0)
{
if(allowOverflow == AllowDayOverflow.yes)
{
++_month;
_day = cast(ubyte)overflow;
}
else
_day = cast(ubyte)currMaxDay;
}
}
//Test add!"months"() with AllowDayOverlow.yes
unittest
{
//Test A.D.
{
auto date = Date(1999, 7, 6);
date.add!"months"(3);
assertPred!"=="(date, Date(1999, 10, 6));
date.add!"months"(-4);
assertPred!"=="(date, Date(1999, 6, 6));
}
{
auto date = Date(1999, 7, 6);
date.add!"months"(6);
assertPred!"=="(date, Date(2000, 1, 6));
date.add!"months"(-6);
assertPred!"=="(date, Date(1999, 7, 6));
}
{
auto date = Date(1999, 7, 6);
date.add!"months"(27);
assertPred!"=="(date, Date(2001, 10, 6));
date.add!"months"(-28);
assertPred!"=="(date, Date(1999, 6, 6));
}
{
auto date = Date(1999, 5, 31);
date.add!"months"(1);
assertPred!"=="(date, Date(1999, 7, 1));
}
{
auto date = Date(1999, 5, 31);
date.add!"months"(-1);
assertPred!"=="(date, Date(1999, 5, 1));
}
{
auto date = Date(1999, 2, 28);
date.add!"months"(12);
assertPred!"=="(date, Date(2000, 2, 28));
}
{
auto date = Date(2000, 2, 29);
date.add!"months"(12);
assertPred!"=="(date, Date(2001, 3, 1));
}
{
auto date = Date(1999, 7, 31);
date.add!"months"(1);
assertPred!"=="(date, Date(1999, 8, 31));
date.add!"months"(1);
assertPred!"=="(date, Date(1999, 10, 1));
}
{
auto date = Date(1998, 8, 31);
date.add!"months"(13);
assertPred!"=="(date, Date(1999, 10, 1));
date.add!"months"(-13);
assertPred!"=="(date, Date(1998, 9, 1));
}
{
auto date = Date(1997, 12, 31);
date.add!"months"(13);
assertPred!"=="(date, Date(1999, 1, 31));
date.add!"months"(-13);
assertPred!"=="(date, Date(1997, 12, 31));
}
{
auto date = Date(1997, 12, 31);
date.add!"months"(14);
assertPred!"=="(date, Date(1999, 3, 3));
date.add!"months"(-14);
assertPred!"=="(date, Date(1998, 1, 3));
}
{
auto date = Date(1998, 12, 31);
date.add!"months"(14);
assertPred!"=="(date, Date(2000, 3, 2));
date.add!"months"(-14);
assertPred!"=="(date, Date(1999, 1, 2));
}
{
auto date = Date(1999, 12, 31);
date.add!"months"(14);
assertPred!"=="(date, Date(2001, 3, 3));
date.add!"months"(-14);
assertPred!"=="(date, Date(2000, 1, 3));
}
//Test B.C.
{
auto date = Date(-1999, 7, 6);
date.add!"months"(3);
assertPred!"=="(date, Date(-1999, 10, 6));
date.add!"months"(-4);
assertPred!"=="(date, Date(-1999, 6, 6));
}
{
auto date = Date(-1999, 7, 6);
date.add!"months"(6);
assertPred!"=="(date, Date(-1998, 1, 6));
date.add!"months"(-6);
assertPred!"=="(date, Date(-1999, 7, 6));
}
{
auto date = Date(-1999, 7, 6);
date.add!"months"(-27);
assertPred!"=="(date, Date(-2001, 4, 6));
date.add!"months"(28);
assertPred!"=="(date, Date(-1999, 8, 6));
}
{
auto date = Date(-1999, 5, 31);
date.add!"months"(1);
assertPred!"=="(date, Date(-1999, 7, 1));
}
{
auto date = Date(-1999, 5, 31);
date.add!"months"(-1);
assertPred!"=="(date, Date(-1999, 5, 1));
}
{
auto date = Date(-1999, 2, 28);
date.add!"months"(-12);
assertPred!"=="(date, Date(-2000, 2, 28));
}
{
auto date = Date(-2000, 2, 29);
date.add!"months"(-12);
assertPred!"=="(date, Date(-2001, 3, 1));
}
{
auto date = Date(-1999, 7, 31);
date.add!"months"(1);
assertPred!"=="(date, Date(-1999, 8, 31));
date.add!"months"(1);
assertPred!"=="(date, Date(-1999, 10, 1));
}
{
auto date = Date(-1998, 8, 31);
date.add!"months"(13);
assertPred!"=="(date, Date(-1997, 10, 1));
date.add!"months"(-13);
assertPred!"=="(date, Date(-1998, 9, 1));
}
{
auto date = Date(-1997, 12, 31);
date.add!"months"(13);
assertPred!"=="(date, Date(-1995, 1, 31));
date.add!"months"(-13);
assertPred!"=="(date, Date(-1997, 12, 31));
}
{
auto date = Date(-1997, 12, 31);
date.add!"months"(14);
assertPred!"=="(date, Date(-1995, 3, 3));
date.add!"months"(-14);
assertPred!"=="(date, Date(-1996, 1, 3));
}
{
auto date = Date(-2002, 12, 31);
date.add!"months"(14);
assertPred!"=="(date, Date(-2000, 3, 2));
date.add!"months"(-14);
assertPred!"=="(date, Date(-2001, 1, 2));
}
{
auto date = Date(-2001, 12, 31);
date.add!"months"(14);
assertPred!"=="(date, Date(-1999, 3, 3));
date.add!"months"(-14);
assertPred!"=="(date, Date(-2000, 1, 3));
}
//Test Both
{
auto date = Date(1, 1, 1);
date.add!"months"(-1);
assertPred!"=="(date, Date(0, 12, 1));
date.add!"months"(1);
assertPred!"=="(date, Date(1, 1, 1));
}
{
auto date = Date(4, 1, 1);
date.add!"months"(-48);
assertPred!"=="(date, Date(0, 1, 1));
date.add!"months"(48);
assertPred!"=="(date, Date(4, 1, 1));
}
{
auto date = Date(4, 3, 31);
date.add!"months"(-49);
assertPred!"=="(date, Date(0, 3, 2));
date.add!"months"(49);
assertPred!"=="(date, Date(4, 4, 2));
}
{
auto date = Date(4, 3, 31);
date.add!"months"(-85);
assertPred!"=="(date, Date(-3, 3, 3));
date.add!"months"(85);
assertPred!"=="(date, Date(4, 4, 3));
}
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(!__traits(compiles, cdate.add!"months"(3)));
static assert(!__traits(compiles, idate.add!"months"(3)));
//Verify Examples.
auto date1 = Date(2010, 1, 1);
date1.add!"months"(1);
assert(date1 == Date(2010, 2, 1));
auto date2 = Date(2010, 1, 1);
date2.add!"months"(-1);
assert(date2 == Date(2009, 12, 1));
auto date3 = Date(1999, 1, 29);
date3.add!"months"(1);
assert(date3 == Date(1999, 3, 1));
auto date4 = Date(1999, 1, 29);
date4.add!"months"(1, AllowDayOverflow.no);
assert(date4 == Date(1999, 2, 28));
}
//Test add!"months"() with AllowDayOverlow.no
unittest
{
//Test A.D.
{
auto date = Date(1999, 7, 6);
date.add!"months"(3, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 10, 6));
date.add!"months"(-4, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 6, 6));
}
{
auto date = Date(1999, 7, 6);
date.add!"months"(6, AllowDayOverflow.no);
assertPred!"=="(date, Date(2000, 1, 6));
date.add!"months"(-6, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 7, 6));
}
{
auto date = Date(1999, 7, 6);
date.add!"months"(27, AllowDayOverflow.no);
assertPred!"=="(date, Date(2001, 10, 6));
date.add!"months"(-28, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 6, 6));
}
{
auto date = Date(1999, 5, 31);
date.add!"months"(1, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 6, 30));
}
{
auto date = Date(1999, 5, 31);
date.add!"months"(-1, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 4, 30));
}
{
auto date = Date(1999, 2, 28);
date.add!"months"(12, AllowDayOverflow.no);
assertPred!"=="(date, Date(2000, 2, 28));
}
{
auto date = Date(2000, 2, 29);
date.add!"months"(12, AllowDayOverflow.no);
assertPred!"=="(date, Date(2001, 2, 28));
}
{
auto date = Date(1999, 7, 31);
date.add!"months"(1, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 8, 31));
date.add!"months"(1, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 9, 30));
}
{
auto date = Date(1998, 8, 31);
date.add!"months"(13, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 9, 30));
date.add!"months"(-13, AllowDayOverflow.no);
assertPred!"=="(date, Date(1998, 8, 30));
}
{
auto date = Date(1997, 12, 31);
date.add!"months"(13, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 1, 31));
date.add!"months"(-13, AllowDayOverflow.no);
assertPred!"=="(date, Date(1997, 12, 31));
}
{
auto date = Date(1997, 12, 31);
date.add!"months"(14, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 2, 28));
date.add!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(date, Date(1997, 12, 28));
}
{
auto date = Date(1998, 12, 31);
date.add!"months"(14, AllowDayOverflow.no);
assertPred!"=="(date, Date(2000, 2, 29));
date.add!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(date, Date(1998, 12, 29));
}
{
auto date = Date(1999, 12, 31);
date.add!"months"(14, AllowDayOverflow.no);
assertPred!"=="(date, Date(2001, 2, 28));
date.add!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 12, 28));
}
//Test B.C.
{
auto date = Date(-1999, 7, 6);
date.add!"months"(3, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1999, 10, 6));
date.add!"months"(-4, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1999, 6, 6));
}
{
auto date = Date(-1999, 7, 6);
date.add!"months"(6, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1998, 1, 6));
date.add!"months"(-6, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1999, 7, 6));
}
{
auto date = Date(-1999, 7, 6);
date.add!"months"(-27, AllowDayOverflow.no);
assertPred!"=="(date, Date(-2001, 4, 6));
date.add!"months"(28, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1999, 8, 6));
}
{
auto date = Date(-1999, 5, 31);
date.add!"months"(1, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1999, 6, 30));
}
{
auto date = Date(-1999, 5, 31);
date.add!"months"(-1, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1999, 4, 30));
}
{
auto date = Date(-1999, 2, 28);
date.add!"months"(-12, AllowDayOverflow.no);
assertPred!"=="(date, Date(-2000, 2, 28));
}
{
auto date = Date(-2000, 2, 29);
date.add!"months"(-12, AllowDayOverflow.no);
assertPred!"=="(date, Date(-2001, 2, 28));
}
{
auto date = Date(-1999, 7, 31);
date.add!"months"(1, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1999, 8, 31));
date.add!"months"(1, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1999, 9, 30));
}
{
auto date = Date(-1998, 8, 31);
date.add!"months"(13, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1997, 9, 30));
date.add!"months"(-13, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1998, 8, 30));
}
{
auto date = Date(-1997, 12, 31);
date.add!"months"(13, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1995, 1, 31));
date.add!"months"(-13, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1997, 12, 31));
}
{
auto date = Date(-1997, 12, 31);
date.add!"months"(14, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1995, 2, 28));
date.add!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1997, 12, 28));
}
{
auto date = Date(-2002, 12, 31);
date.add!"months"(14, AllowDayOverflow.no);
assertPred!"=="(date, Date(-2000, 2, 29));
date.add!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(date, Date(-2002, 12, 29));
}
{
auto date = Date(-2001, 12, 31);
date.add!"months"(14, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1999, 2, 28));
date.add!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(date, Date(-2001, 12, 28));
}
//Test Both
{
auto date = Date(1, 1, 1);
date.add!"months"(-1, AllowDayOverflow.no);
assertPred!"=="(date, Date(0, 12, 1));
date.add!"months"(1, AllowDayOverflow.no);
assertPred!"=="(date, Date(1, 1, 1));
}
{
auto date = Date(4, 1, 1);
date.add!"months"(-48, AllowDayOverflow.no);
assertPred!"=="(date, Date(0, 1, 1));
date.add!"months"(48, AllowDayOverflow.no);
assertPred!"=="(date, Date(4, 1, 1));
}
{
auto date = Date(4, 3, 31);
date.add!"months"(-49, AllowDayOverflow.no);
assertPred!"=="(date, Date(0, 2, 29));
date.add!"months"(49, AllowDayOverflow.no);
assertPred!"=="(date, Date(4, 3, 29));
}
{
auto date = Date(4, 3, 31);
date.add!"months"(-85, AllowDayOverflow.no);
assertPred!"=="(date, Date(-3, 2, 28));
date.add!"months"(85, AllowDayOverflow.no);
assertPred!"=="(date, Date(4, 3, 28));
}
}
/++
Adds the given number of years to this Date. A negative number will subtract.
For years, because they are the largest unit in Date, there is no difference
between adding or rolling.
Params:
years = The number of years to add to this Date.
allowOverflow = Whether the days should be allowed to overflow, causing
the month to increment.
+/
/+ref Date+/ void roll(string units)(long years, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) pure nothrow
if(units == "years")
{
add!"years"(years, allowOverflow);
}
unittest
{
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(!__traits(compiles, cdate.roll!"years"(3)));
static assert(!__traits(compiles, idate.rolYears(3)));
}
/++
Adds the given number of months to this Date. A negative number will subtract.
The difference between rolling and adding is that rolling does not affect
larger units. So, if you roll the Date 12 months, you get the exact same
Date. However, the days can still be affected due to the differing number
of days in each month.
Params:
months = The number of months to add to this Date.
allowOverflow = Whether the days should be allowed to overflow, causing
the month to increment.
Examples:
--------------------
auto date1 = Date(2010, 1, 1);
date1.roll!"months"(1);
assert(date1 == Date(2010, 2, 1));
auto date2 = Date(2010, 1, 1);
date2.roll!"months"(-1);
assert(date2 == Date(2010, 12, 1));
auto date3 = Date(1999, 1, 29);
date3.roll!"months"(1);
assert(date3 == Date(1999, 3, 1));
auto date4 = Date(1999, 1, 29);
date4.roll!"months"(1, AllowDayOverflow.no);
assert(date4 == Date(1999, 2, 28));
--------------------
+/
/+ref Date+/ void roll(string units)(long months, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) pure nothrow
if(units == "months")
{
months %= 12;
auto newMonth = _month + months;
if(months < 0)
{
if(newMonth < 1)
newMonth += 12;
}
else
{
if(newMonth > 12)
newMonth -= 12;
}
_month = cast(Month)newMonth;
immutable currMaxDay = maxDay(_year, _month);
immutable overflow = _day - currMaxDay;
if(overflow > 0)
{
if(allowOverflow == AllowDayOverflow.yes)
{
++_month;
_day = cast(ubyte)overflow;
}
else
_day = cast(ubyte)currMaxDay;
}
}
//Test roll!"months"() with AllowDayOverlow.yes
unittest
{
//Test A.D.
{
auto date = Date(1999, 7, 6);
date.roll!"months"(3);
assertPred!"=="(date, Date(1999, 10, 6));
date.roll!"months"(-4);
assertPred!"=="(date, Date(1999, 6, 6));
}
{
auto date = Date(1999, 7, 6);
date.roll!"months"(6);
assertPred!"=="(date, Date(1999, 1, 6));
date.roll!"months"(-6);
assertPred!"=="(date, Date(1999, 7, 6));
}
{
auto date = Date(1999, 7, 6);
date.roll!"months"(27);
assertPred!"=="(date, Date(1999, 10, 6));
date.roll!"months"(-28);
assertPred!"=="(date, Date(1999, 6, 6));
}
{
auto date = Date(1999, 5, 31);
date.roll!"months"(1);
assertPred!"=="(date, Date(1999, 7, 1));
}
{
auto date = Date(1999, 5, 31);
date.roll!"months"(-1);
assertPred!"=="(date, Date(1999, 5, 1));
}
{
auto date = Date(1999, 2, 28);
date.roll!"months"(12);
assertPred!"=="(date, Date(1999, 2, 28));
}
{
auto date = Date(2000, 2, 29);
date.roll!"months"(12);
assertPred!"=="(date, Date(2000, 2, 29));
}
{
auto date = Date(1999, 7, 31);
date.roll!"months"(1);
assertPred!"=="(date, Date(1999, 8, 31));
date.roll!"months"(1);
assertPred!"=="(date, Date(1999, 10, 1));
}
{
auto date = Date(1998, 8, 31);
date.roll!"months"(13);
assertPred!"=="(date, Date(1998, 10, 1));
date.roll!"months"(-13);
assertPred!"=="(date, Date(1998, 9, 1));
}
{
auto date = Date(1997, 12, 31);
date.roll!"months"(13);
assertPred!"=="(date, Date(1997, 1, 31));
date.roll!"months"(-13);
assertPred!"=="(date, Date(1997, 12, 31));
}
{
auto date = Date(1997, 12, 31);
date.roll!"months"(14);
assertPred!"=="(date, Date(1997, 3, 3));
date.roll!"months"(-14);
assertPred!"=="(date, Date(1997, 1, 3));
}
{
auto date = Date(1998, 12, 31);
date.roll!"months"(14);
assertPred!"=="(date, Date(1998, 3, 3));
date.roll!"months"(-14);
assertPred!"=="(date, Date(1998, 1, 3));
}
{
auto date = Date(1999, 12, 31);
date.roll!"months"(14);
assertPred!"=="(date, Date(1999, 3, 3));
date.roll!"months"(-14);
assertPred!"=="(date, Date(1999, 1, 3));
}
//Test B.C.
{
auto date = Date(-1999, 7, 6);
date.roll!"months"(3);
assertPred!"=="(date, Date(-1999, 10, 6));
date.roll!"months"(-4);
assertPred!"=="(date, Date(-1999, 6, 6));
}
{
auto date = Date(-1999, 7, 6);
date.roll!"months"(6);
assertPred!"=="(date, Date(-1999, 1, 6));
date.roll!"months"(-6);
assertPred!"=="(date, Date(-1999, 7, 6));
}
{
auto date = Date(-1999, 7, 6);
date.roll!"months"(-27);
assertPred!"=="(date, Date(-1999, 4, 6));
date.roll!"months"(28);
assertPred!"=="(date, Date(-1999, 8, 6));
}
{
auto date = Date(-1999, 5, 31);
date.roll!"months"(1);
assertPred!"=="(date, Date(-1999, 7, 1));
}
{
auto date = Date(-1999, 5, 31);
date.roll!"months"(-1);
assertPred!"=="(date, Date(-1999, 5, 1));
}
{
auto date = Date(-1999, 2, 28);
date.roll!"months"(-12);
assertPred!"=="(date, Date(-1999, 2, 28));
}
{
auto date = Date(-2000, 2, 29);
date.roll!"months"(-12);
assertPred!"=="(date, Date(-2000, 2, 29));
}
{
auto date = Date(-1999, 7, 31);
date.roll!"months"(1);
assertPred!"=="(date, Date(-1999, 8, 31));
date.roll!"months"(1);
assertPred!"=="(date, Date(-1999, 10, 1));
}
{
auto date = Date(-1998, 8, 31);
date.roll!"months"(13);
assertPred!"=="(date, Date(-1998, 10, 1));
date.roll!"months"(-13);
assertPred!"=="(date, Date(-1998, 9, 1));
}
{
auto date = Date(-1997, 12, 31);
date.roll!"months"(13);
assertPred!"=="(date, Date(-1997, 1, 31));
date.roll!"months"(-13);
assertPred!"=="(date, Date(-1997, 12, 31));
}
{
auto date = Date(-1997, 12, 31);
date.roll!"months"(14);
assertPred!"=="(date, Date(-1997, 3, 3));
date.roll!"months"(-14);
assertPred!"=="(date, Date(-1997, 1, 3));
}
{
auto date = Date(-2002, 12, 31);
date.roll!"months"(14);
assertPred!"=="(date, Date(-2002, 3, 3));
date.roll!"months"(-14);
assertPred!"=="(date, Date(-2002, 1, 3));
}
{
auto date = Date(-2001, 12, 31);
date.roll!"months"(14);
assertPred!"=="(date, Date(-2001, 3, 3));
date.roll!"months"(-14);
assertPred!"=="(date, Date(-2001, 1, 3));
}
//Test Both
{
auto date = Date(1, 1, 1);
date.roll!"months"(-1);
assertPred!"=="(date, Date(1, 12, 1));
date.roll!"months"(1);
assertPred!"=="(date, Date(1, 1, 1));
}
{
auto date = Date(4, 1, 1);
date.roll!"months"(-48);
assertPred!"=="(date, Date(4, 1, 1));
date.roll!"months"(48);
assertPred!"=="(date, Date(4, 1, 1));
}
{
auto date = Date(4, 3, 31);
date.roll!"months"(-49);
assertPred!"=="(date, Date(4, 3, 2));
date.roll!"months"(49);
assertPred!"=="(date, Date(4, 4, 2));
}
{
auto date = Date(4, 3, 31);
date.roll!"months"(-85);
assertPred!"=="(date, Date(4, 3, 2));
date.roll!"months"(85);
assertPred!"=="(date, Date(4, 4, 2));
}
{
auto date = Date(-1, 1, 1);
date.roll!"months"(-1);
assertPred!"=="(date, Date(-1, 12, 1));
date.roll!"months"(1);
assertPred!"=="(date, Date(-1, 1, 1));
}
{
auto date = Date(-4, 1, 1);
date.roll!"months"(-48);
assertPred!"=="(date, Date(-4, 1, 1));
date.roll!"months"(48);
assertPred!"=="(date, Date(-4, 1, 1));
}
{
auto date = Date(-4, 3, 31);
date.roll!"months"(-49);
assertPred!"=="(date, Date(-4, 3, 2));
date.roll!"months"(49);
assertPred!"=="(date, Date(-4, 4, 2));
}
{
auto date = Date(-4, 3, 31);
date.roll!"months"(-85);
assertPred!"=="(date, Date(-4, 3, 2));
date.roll!"months"(85);
assertPred!"=="(date, Date(-4, 4, 2));
}
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(!__traits(compiles, cdate.roll!"months"(3)));
static assert(!__traits(compiles, idate.roll!"months"(3)));
//Verify Examples.
auto date1 = Date(2010, 1, 1);
date1.roll!"months"(1);
assert(date1 == Date(2010, 2, 1));
auto date2 = Date(2010, 1, 1);
date2.roll!"months"(-1);
assert(date2 == Date(2010, 12, 1));
auto date3 = Date(1999, 1, 29);
date3.roll!"months"(1);
assert(date3 == Date(1999, 3, 1));
auto date4 = Date(1999, 1, 29);
date4.roll!"months"(1, AllowDayOverflow.no);
assert(date4 == Date(1999, 2, 28));
}
//Test roll!"months"() with AllowDayOverlow.no
unittest
{
//Test A.D.
{
auto date = Date(1999, 7, 6);
date.roll!"months"(3, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 10, 6));
date.roll!"months"(-4, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 6, 6));
}
{
auto date = Date(1999, 7, 6);
date.roll!"months"(6, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 1, 6));
date.roll!"months"(-6, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 7, 6));
}
{
auto date = Date(1999, 7, 6);
date.roll!"months"(27, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 10, 6));
date.roll!"months"(-28, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 6, 6));
}
{
auto date = Date(1999, 5, 31);
date.roll!"months"(1, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 6, 30));
}
{
auto date = Date(1999, 5, 31);
date.roll!"months"(-1, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 4, 30));
}
{
auto date = Date(1999, 2, 28);
date.roll!"months"(12, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 2, 28));
}
{
auto date = Date(2000, 2, 29);
date.roll!"months"(12, AllowDayOverflow.no);
assertPred!"=="(date, Date(2000, 2, 29));
}
{
auto date = Date(1999, 7, 31);
date.roll!"months"(1, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 8, 31));
date.roll!"months"(1, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 9, 30));
}
{
auto date = Date(1998, 8, 31);
date.roll!"months"(13, AllowDayOverflow.no);
assertPred!"=="(date, Date(1998, 9, 30));
date.roll!"months"(-13, AllowDayOverflow.no);
assertPred!"=="(date, Date(1998, 8, 30));
}
{
auto date = Date(1997, 12, 31);
date.roll!"months"(13, AllowDayOverflow.no);
assertPred!"=="(date, Date(1997, 1, 31));
date.roll!"months"(-13, AllowDayOverflow.no);
assertPred!"=="(date, Date(1997, 12, 31));
}
{
auto date = Date(1997, 12, 31);
date.roll!"months"(14, AllowDayOverflow.no);
assertPred!"=="(date, Date(1997, 2, 28));
date.roll!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(date, Date(1997, 12, 28));
}
{
auto date = Date(1998, 12, 31);
date.roll!"months"(14, AllowDayOverflow.no);
assertPred!"=="(date, Date(1998, 2, 28));
date.roll!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(date, Date(1998, 12, 28));
}
{
auto date = Date(1999, 12, 31);
date.roll!"months"(14, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 2, 28));
date.roll!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(date, Date(1999, 12, 28));
}
//Test B.C.
{
auto date = Date(-1999, 7, 6);
date.roll!"months"(3, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1999, 10, 6));
date.roll!"months"(-4, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1999, 6, 6));
}
{
auto date = Date(-1999, 7, 6);
date.roll!"months"(6, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1999, 1, 6));
date.roll!"months"(-6, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1999, 7, 6));
}
{
auto date = Date(-1999, 7, 6);
date.roll!"months"(-27, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1999, 4, 6));
date.roll!"months"(28, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1999, 8, 6));
}
{
auto date = Date(-1999, 5, 31);
date.roll!"months"(1, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1999, 6, 30));
}
{
auto date = Date(-1999, 5, 31);
date.roll!"months"(-1, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1999, 4, 30));
}
{
auto date = Date(-1999, 2, 28);
date.roll!"months"(-12, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1999, 2, 28));
}
{
auto date = Date(-2000, 2, 29);
date.roll!"months"(-12, AllowDayOverflow.no);
assertPred!"=="(date, Date(-2000, 2, 29));
}
{
auto date = Date(-1999, 7, 31);
date.roll!"months"(1, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1999, 8, 31));
date.roll!"months"(1, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1999, 9, 30));
}
{
auto date = Date(-1998, 8, 31);
date.roll!"months"(13, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1998, 9, 30));
date.roll!"months"(-13, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1998, 8, 30));
}
{
auto date = Date(-1997, 12, 31);
date.roll!"months"(13, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1997, 1, 31));
date.roll!"months"(-13, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1997, 12, 31));
}
{
auto date = Date(-1997, 12, 31);
date.roll!"months"(14, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1997, 2, 28));
date.roll!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1997, 12, 28));
}
{
auto date = Date(-2002, 12, 31);
date.roll!"months"(14, AllowDayOverflow.no);
assertPred!"=="(date, Date(-2002, 2, 28));
date.roll!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(date, Date(-2002, 12, 28));
}
{
auto date = Date(-2001, 12, 31);
date.roll!"months"(14, AllowDayOverflow.no);
assertPred!"=="(date, Date(-2001, 2, 28));
date.roll!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(date, Date(-2001, 12, 28));
}
//Test Both
{
auto date = Date(1, 1, 1);
date.roll!"months"(-1, AllowDayOverflow.no);
assertPred!"=="(date, Date(1, 12, 1));
date.roll!"months"(1, AllowDayOverflow.no);
assertPred!"=="(date, Date(1, 1, 1));
}
{
auto date = Date(4, 1, 1);
date.roll!"months"(-48, AllowDayOverflow.no);
assertPred!"=="(date, Date(4, 1, 1));
date.roll!"months"(48, AllowDayOverflow.no);
assertPred!"=="(date, Date(4, 1, 1));
}
{
auto date = Date(4, 3, 31);
date.roll!"months"(-49, AllowDayOverflow.no);
assertPred!"=="(date, Date(4, 2, 29));
date.roll!"months"(49, AllowDayOverflow.no);
assertPred!"=="(date, Date(4, 3, 29));
}
{
auto date = Date(4, 3, 31);
date.roll!"months"(-85, AllowDayOverflow.no);
assertPred!"=="(date, Date(4, 2, 29));
date.roll!"months"(85, AllowDayOverflow.no);
assertPred!"=="(date, Date(4, 3, 29));
}
{
auto date = Date(-1, 1, 1);
date.roll!"months"(-1, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1, 12, 1));
date.roll!"months"(1, AllowDayOverflow.no);
assertPred!"=="(date, Date(-1, 1, 1));
}
{
auto date = Date(-4, 1, 1);
date.roll!"months"(-48, AllowDayOverflow.no);
assertPred!"=="(date, Date(-4, 1, 1));
date.roll!"months"(48, AllowDayOverflow.no);
assertPred!"=="(date, Date(-4, 1, 1));
}
{
auto date = Date(-4, 3, 31);
date.roll!"months"(-49, AllowDayOverflow.no);
assertPred!"=="(date, Date(-4, 2, 29));
date.roll!"months"(49, AllowDayOverflow.no);
assertPred!"=="(date, Date(-4, 3, 29));
}
{
auto date = Date(-4, 3, 31);
date.roll!"months"(-85, AllowDayOverflow.no);
assertPred!"=="(date, Date(-4, 2, 29));
date.roll!"months"(85, AllowDayOverflow.no);
assertPred!"=="(date, Date(-4, 3, 29));
}
}
/++
Adds the given number of days to this Date. A negative number will subtract.
The difference between rolling and adding is that rolling does not affect
larger units. So, if you roll the Date one year's worth of days, then you
get the exact same Date.
Note that there is no $(D add!"days"()) because you can add days to a Date by
adding a duration to it.
Params:
days = The number of days to add to this Date.
Examples:
--------------------
auto date = Date(2010, 1, 1);
date.roll!"days"(1);
assert(date == Date(2010, 1, 2));
date.roll!"days"(365);
assert(date == Date(2010, 1, 26));
date.roll!"days"(-32);
assert(date == Date(2010, 1, 25));
--------------------
+/
/+ref Date+/ void roll(string units)(long days) pure nothrow
if(units == "days")
{
immutable limit = maxDay(_year, _month);
days %= limit;
auto newDay = _day + days;
if(days < 0)
{
if(newDay < 1)
newDay += limit;
}
else if(newDay > limit)
newDay -= limit;
_day = cast(ubyte)newDay;
}
unittest
{
//Test A.D.
{
auto date = Date(1999, 2, 28);
date.roll!"days"(1);
assertPred!"=="(date, Date(1999, 2, 1));
date.roll!"days"(-1);
assertPred!"=="(date, Date(1999, 2, 28));
}
{
auto date = Date(2000, 2, 28);
date.roll!"days"(1);
assertPred!"=="(date, Date(2000, 2, 29));
date.roll!"days"(1);
assertPred!"=="(date, Date(2000, 2, 1));
date.roll!"days"(-1);
assertPred!"=="(date, Date(2000, 2, 29));
}
{
auto date = Date(1999, 6, 30);
date.roll!"days"(1);
assertPred!"=="(date, Date(1999, 6, 1));
date.roll!"days"(-1);
assertPred!"=="(date, Date(1999, 6, 30));
}
{
auto date = Date(1999, 7, 31);
date.roll!"days"(1);
assertPred!"=="(date, Date(1999, 7, 1));
date.roll!"days"(-1);
assertPred!"=="(date, Date(1999, 7, 31));
}
{
auto date = Date(1999, 1, 1);
date.roll!"days"(-1);
assertPred!"=="(date, Date(1999, 1, 31));
date.roll!"days"(1);
assertPred!"=="(date, Date(1999, 1, 1));
}
{
auto date = Date(1999, 7, 6);
date.roll!"days"(9);
assertPred!"=="(date, Date(1999, 7, 15));
date.roll!"days"(-11);
assertPred!"=="(date, Date(1999, 7, 4));
date.roll!"days"(30);
assertPred!"=="(date, Date(1999, 7, 3));
date.roll!"days"(-3);
assertPred!"=="(date, Date(1999, 7, 31));
}
{
auto date = Date(1999, 7, 6);
date.roll!"days"(365);
assertPred!"=="(date, Date(1999, 7, 30));
date.roll!"days"(-365);
assertPred!"=="(date, Date(1999, 7, 6));
date.roll!"days"(366);
assertPred!"=="(date, Date(1999, 7, 31));
date.roll!"days"(730);
assertPred!"=="(date, Date(1999, 7, 17));
date.roll!"days"(-1096);
assertPred!"=="(date, Date(1999, 7, 6));
}
{
auto date = Date(1999, 2, 6);
date.roll!"days"(365);
assertPred!"=="(date, Date(1999, 2, 7));
date.roll!"days"(-365);
assertPred!"=="(date, Date(1999, 2, 6));
date.roll!"days"(366);
assertPred!"=="(date, Date(1999, 2, 8));
date.roll!"days"(730);
assertPred!"=="(date, Date(1999, 2, 10));
date.roll!"days"(-1096);
assertPred!"=="(date, Date(1999, 2, 6));
}
//Test B.C.
{
auto date = Date(-1999, 2, 28);
date.roll!"days"(1);
assertPred!"=="(date, Date(-1999, 2, 1));
date.roll!"days"(-1);
assertPred!"=="(date, Date(-1999, 2, 28));
}
{
auto date = Date(-2000, 2, 28);
date.roll!"days"(1);
assertPred!"=="(date, Date(-2000, 2, 29));
date.roll!"days"(1);
assertPred!"=="(date, Date(-2000, 2, 1));
date.roll!"days"(-1);
assertPred!"=="(date, Date(-2000, 2, 29));
}
{
auto date = Date(-1999, 6, 30);
date.roll!"days"(1);
assertPred!"=="(date, Date(-1999, 6, 1));
date.roll!"days"(-1);
assertPred!"=="(date, Date(-1999, 6, 30));
}
{
auto date = Date(-1999, 7, 31);
date.roll!"days"(1);
assertPred!"=="(date, Date(-1999, 7, 1));
date.roll!"days"(-1);
assertPred!"=="(date, Date(-1999, 7, 31));
}
{
auto date = Date(-1999, 1, 1);
date.roll!"days"(-1);
assertPred!"=="(date, Date(-1999, 1, 31));
date.roll!"days"(1);
assertPred!"=="(date, Date(-1999, 1, 1));
}
{
auto date = Date(-1999, 7, 6);
date.roll!"days"(9);
assertPred!"=="(date, Date(-1999, 7, 15));
date.roll!"days"(-11);
assertPred!"=="(date, Date(-1999, 7, 4));
date.roll!"days"(30);
assertPred!"=="(date, Date(-1999, 7, 3));
date.roll!"days"(-3);
assertPred!"=="(date, Date(-1999, 7, 31));
}
{
auto date = Date(-1999, 7, 6);
date.roll!"days"(365);
assertPred!"=="(date, Date(-1999, 7, 30));
date.roll!"days"(-365);
assertPred!"=="(date, Date(-1999, 7, 6));
date.roll!"days"(366);
assertPred!"=="(date, Date(-1999, 7, 31));
date.roll!"days"(730);
assertPred!"=="(date, Date(-1999, 7, 17));
date.roll!"days"(-1096);
assertPred!"=="(date, Date(-1999, 7, 6));
}
//Test Both
{
auto date = Date(1, 7, 6);
date.roll!"days"(-365);
assertPred!"=="(date, Date(1, 7, 13));
date.roll!"days"(365);
assertPred!"=="(date, Date(1, 7, 6));
date.roll!"days"(-731);
assertPred!"=="(date, Date(1, 7, 19));
date.roll!"days"(730);
assertPred!"=="(date, Date(1, 7, 5));
}
{
auto date = Date(0, 7, 6);
date.roll!"days"(-365);
assertPred!"=="(date, Date(0, 7, 13));
date.roll!"days"(365);
assertPred!"=="(date, Date(0, 7, 6));
date.roll!"days"(-731);
assertPred!"=="(date, Date(0, 7, 19));
date.roll!"days"(730);
assertPred!"=="(date, Date(0, 7, 5));
}
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(!__traits(compiles, cdate.roll!"days"(12)));
static assert(!__traits(compiles, idate.roll!"days"(12)));
//Verify Examples.
auto date = Date(2010, 1, 1);
date.roll!"days"(1);
assert(date == Date(2010, 1, 2));
date.roll!"days"(365);
assert(date == Date(2010, 1, 26));
date.roll!"days"(-32);
assert(date == Date(2010, 1, 25));
}
/++
Gives the result of adding or subtracting a duration from this Date.
The legal types of arithmetic for Date using this operator are
$(TABLE
$(TR $(TD Date) $(TD +) $(TD duration) $(TD -->) $(TD Date))
$(TR $(TD Date) $(TD -) $(TD duration) $(TD -->) $(TD Date))
)
Params:
duration = The duration to add to or subtract from this Date.
+/
Date opBinary(string op, D)(in D duration) const pure nothrow
if((op == "+" || op == "-") &&
(is(Unqual!D == Duration) ||
is(Unqual!D == TickDuration)))
{
Date retval = this;
static if(is(Unqual!D == Duration))
immutable days = duration.total!"days";
else static if(is(Unqual!D == TickDuration))
immutable days = convert!("hnsecs", "days")(duration.hnsecs);
//Ideally, this would just be
//return retval.addDays(unaryFun!(op ~ "a")(days));
//But there isn't currently a pure version of unaryFun!().
static if(op == "+")
immutable signedDays = days;
else static if(op == "-")
immutable signedDays = -days;
else
static assert(0);
return retval.addDays(signedDays);
}
unittest
{
auto date = Date(1999, 7, 6);
assertPred!"=="(date + dur!"weeks"(7), Date(1999, 8, 24));
assertPred!"=="(date + dur!"weeks"(-7), Date(1999, 5, 18));
assertPred!"=="(date + dur!"days"(7), Date(1999, 7, 13));
assertPred!"=="(date + dur!"days"(-7), Date(1999, 6, 29));
assertPred!"=="(date + dur!"hours"(24), Date(1999, 7, 7));
assertPred!"=="(date + dur!"hours"(-24), Date(1999, 7, 5));
assertPred!"=="(date + dur!"minutes"(1440), Date(1999, 7, 7));
assertPred!"=="(date + dur!"minutes"(-1440), Date(1999, 7, 5));
assertPred!"=="(date + dur!"seconds"(86_400), Date(1999, 7, 7));
assertPred!"=="(date + dur!"seconds"(-86_400), Date(1999, 7, 5));
assertPred!"=="(date + dur!"msecs"(86_400_000), Date(1999, 7, 7));
assertPred!"=="(date + dur!"msecs"(-86_400_000), Date(1999, 7, 5));
assertPred!"=="(date + dur!"usecs"(86_400_000_000), Date(1999, 7, 7));
assertPred!"=="(date + dur!"usecs"(-86_400_000_000), Date(1999, 7, 5));
assertPred!"=="(date + dur!"hnsecs"(864_000_000_000), Date(1999, 7, 7));
assertPred!"=="(date + dur!"hnsecs"(-864_000_000_000), Date(1999, 7, 5));
//This probably only runs in cases where gettimeofday() is used, but it's
//hard to do this test correctly with variable ticksPerSec.
if(TickDuration.ticksPerSec == 1_000_000)
{
assertPred!"=="(date + TickDuration.from!"usecs"(86_400_000_000), Date(1999, 7, 7));
assertPred!"=="(date + TickDuration.from!"usecs"(-86_400_000_000), Date(1999, 7, 5));
}
assertPred!"=="(date - dur!"weeks"(-7), Date(1999, 8, 24));
assertPred!"=="(date - dur!"weeks"(7), Date(1999, 5, 18));
assertPred!"=="(date - dur!"days"(-7), Date(1999, 7, 13));
assertPred!"=="(date - dur!"days"(7), Date(1999, 6, 29));
assertPred!"=="(date - dur!"hours"(-24), Date(1999, 7, 7));
assertPred!"=="(date - dur!"hours"(24), Date(1999, 7, 5));
assertPred!"=="(date - dur!"minutes"(-1440), Date(1999, 7, 7));
assertPred!"=="(date - dur!"minutes"(1440), Date(1999, 7, 5));
assertPred!"=="(date - dur!"seconds"(-86_400), Date(1999, 7, 7));
assertPred!"=="(date - dur!"seconds"(86_400), Date(1999, 7, 5));
assertPred!"=="(date - dur!"msecs"(-86_400_000), Date(1999, 7, 7));
assertPred!"=="(date - dur!"msecs"(86_400_000), Date(1999, 7, 5));
assertPred!"=="(date - dur!"usecs"(-86_400_000_000), Date(1999, 7, 7));
assertPred!"=="(date - dur!"usecs"(86_400_000_000), Date(1999, 7, 5));
assertPred!"=="(date - dur!"hnsecs"(-864_000_000_000), Date(1999, 7, 7));
assertPred!"=="(date - dur!"hnsecs"(864_000_000_000), Date(1999, 7, 5));
//This probably only runs in cases where gettimeofday() is used, but it's
//hard to do this test correctly with variable ticksPerSec.
if(TickDuration.ticksPerSec == 1_000_000)
{
assertPred!"=="(date - TickDuration.from!"usecs"(-86_400_000_000), Date(1999, 7, 7));
assertPred!"=="(date - TickDuration.from!"usecs"(86_400_000_000), Date(1999, 7, 5));
}
auto duration = dur!"days"(12);
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(__traits(compiles, date + duration));
static assert(__traits(compiles, cdate + duration));
static assert(__traits(compiles, idate + duration));
static assert(__traits(compiles, date - duration));
static assert(__traits(compiles, cdate - duration));
static assert(__traits(compiles, idate - duration));
}
/++
Gives the result of adding or subtracting a duration from this Date, as
well as assigning the result to this Date.
The legal types of arithmetic for Date using this operator are
$(TABLE
$(TR $(TD Date) $(TD +) $(TD duration) $(TD -->) $(TD Date))
$(TR $(TD Date) $(TD -) $(TD duration) $(TD -->) $(TD Date))
)
Params:
duration = The duration to add to or subtract from this Date.
+/
/+ref+/ Date opOpAssign(string op, D)(in D duration) pure nothrow
if((op == "+" || op == "-") &&
(is(Unqual!D == Duration) ||
is(Unqual!D == TickDuration)))
{
static if(is(Unqual!D == Duration))
immutable days = duration.total!"days";
else static if(is(Unqual!D == TickDuration))
immutable days = convert!("hnsecs", "days")(duration.hnsecs);
//Ideally, this would just be
//return addDays(unaryFun!(op ~ "a")(days));
//But there isn't currently a pure version of unaryFun!().
static if(op == "+")
immutable signedDays = days;
else static if(op == "-")
immutable signedDays = -days;
else
static assert(0);
return addDays(signedDays);
}
unittest
{
assertPred!"+="(Date(1999, 7, 6), dur!"weeks"(7), Date(1999, 8, 24));
assertPred!"+="(Date(1999, 7, 6), dur!"weeks"(-7), Date(1999, 5, 18));
assertPred!"+="(Date(1999, 7, 6), dur!"days"(7), Date(1999, 7, 13));
assertPred!"+="(Date(1999, 7, 6), dur!"days"(-7), Date(1999, 6, 29));
assertPred!"+="(Date(1999, 7, 6), dur!"hours"(24), Date(1999, 7, 7));
assertPred!"+="(Date(1999, 7, 6), dur!"hours"(-24), Date(1999, 7, 5));
assertPred!"+="(Date(1999, 7, 6), dur!"minutes"(1440), Date(1999, 7, 7));
assertPred!"+="(Date(1999, 7, 6), dur!"minutes"(-1440), Date(1999, 7, 5));
assertPred!"+="(Date(1999, 7, 6), dur!"seconds"(86_400), Date(1999, 7, 7));
assertPred!"+="(Date(1999, 7, 6), dur!"seconds"(-86_400), Date(1999, 7, 5));
assertPred!"+="(Date(1999, 7, 6), dur!"msecs"(86_400_000), Date(1999, 7, 7));
assertPred!"+="(Date(1999, 7, 6), dur!"msecs"(-86_400_000), Date(1999, 7, 5));
assertPred!"+="(Date(1999, 7, 6), dur!"usecs"(86_400_000_000), Date(1999, 7, 7));
assertPred!"+="(Date(1999, 7, 6), dur!"usecs"(-86_400_000_000), Date(1999, 7, 5));
assertPred!"+="(Date(1999, 7, 6), dur!"hnsecs"(864_000_000_000), Date(1999, 7, 7));
assertPred!"+="(Date(1999, 7, 6), dur!"hnsecs"(-864_000_000_000), Date(1999, 7, 5));
assertPred!"-="(Date(1999, 7, 6), dur!"weeks"(-7), Date(1999, 8, 24));
assertPred!"-="(Date(1999, 7, 6), dur!"weeks"(7), Date(1999, 5, 18));
assertPred!"-="(Date(1999, 7, 6), dur!"days"(-7), Date(1999, 7, 13));
assertPred!"-="(Date(1999, 7, 6), dur!"days"(7), Date(1999, 6, 29));
assertPred!"-="(Date(1999, 7, 6), dur!"hours"(-24), Date(1999, 7, 7));
assertPred!"-="(Date(1999, 7, 6), dur!"hours"(24), Date(1999, 7, 5));
assertPred!"-="(Date(1999, 7, 6), dur!"minutes"(-1440), Date(1999, 7, 7));
assertPred!"-="(Date(1999, 7, 6), dur!"minutes"(1440), Date(1999, 7, 5));
assertPred!"-="(Date(1999, 7, 6), dur!"seconds"(-86_400), Date(1999, 7, 7));
assertPred!"-="(Date(1999, 7, 6), dur!"seconds"(86_400), Date(1999, 7, 5));
assertPred!"-="(Date(1999, 7, 6), dur!"msecs"(-86_400_000), Date(1999, 7, 7));
assertPred!"-="(Date(1999, 7, 6), dur!"msecs"(86_400_000), Date(1999, 7, 5));
assertPred!"-="(Date(1999, 7, 6), dur!"usecs"(-86_400_000_000), Date(1999, 7, 7));
assertPred!"-="(Date(1999, 7, 6), dur!"usecs"(86_400_000_000), Date(1999, 7, 5));
assertPred!"-="(Date(1999, 7, 6), dur!"hnsecs"(-864_000_000_000), Date(1999, 7, 7));
assertPred!"-="(Date(1999, 7, 6), dur!"hnsecs"(864_000_000_000), Date(1999, 7, 5));
auto duration = dur!"days"(12);
auto date = Date(1999, 7, 6);
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(__traits(compiles, date += duration));
static assert(!__traits(compiles, cdate += duration));
static assert(!__traits(compiles, idate += duration));
static assert(__traits(compiles, date -= duration));
static assert(!__traits(compiles, cdate -= duration));
static assert(!__traits(compiles, idate -= duration));
}
/++
Gives the difference between two Dates.
The legal types of arithmetic for Date using this operator are
$(TABLE
$(TR $(TD Date) $(TD -) $(TD Date) $(TD -->) $(TD duration))
)
+/
Duration opBinary(string op)(in Date rhs) const pure nothrow
if(op == "-")
{
return dur!"days"(this.dayOfGregorianCal - rhs.dayOfGregorianCal);
}
unittest
{
auto date = Date(1999, 7, 6);
assertPred!"=="(Date(1999, 7, 6) - Date(1998, 7, 6), dur!"days"(365));
assertPred!"=="(Date(1998, 7, 6) - Date(1999, 7, 6), dur!"days"(-365));
assertPred!"=="(Date(1999, 6, 6) - Date(1999, 5, 6), dur!"days"(31));
assertPred!"=="(Date(1999, 5, 6) - Date(1999, 6, 6), dur!"days"(-31));
assertPred!"=="(Date(1999, 1, 1) - Date(1998, 12, 31), dur!"days"(1));
assertPred!"=="(Date(1998, 12, 31) - Date(1999, 1, 1), dur!"days"(-1));
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(__traits(compiles, date - date));
static assert(__traits(compiles, cdate - date));
static assert(__traits(compiles, idate - date));
static assert(__traits(compiles, date - cdate));
static assert(__traits(compiles, cdate - cdate));
static assert(__traits(compiles, idate - cdate));
static assert(__traits(compiles, date - idate));
static assert(__traits(compiles, cdate - idate));
static assert(__traits(compiles, idate - idate));
}
/++
Returns the difference between the two Dates in months.
You can get the difference in years by subtracting the year property
of two Dates, and you can get the difference in days or weeks by
subtracting the Dates themselves and using the Duration that results,
but because you cannot convert between months and smaller units without
a specific date (which Durations don't have), you cannot get the difference
in months without doing some math using both the year and month properties,
so this is a convenience function for getting the difference in months.
Note that the number of days in the months or how far into the month either
date is is irrelevant. It is the difference in the month property combined
with the difference in years * 12. So, for instance, December 31st and
January 1st are one month apart just as December 1st and January 31st are
one month apart.
Params:
rhs = The Date to subtract from this one.
Examples:
--------------------
assert(Date(1999, 2, 1).diffMonths(Date(1999, 1, 31)) == 1);
assert(Date(1999, 1, 31).diffMonths(Date(1999, 2, 1)) == -1);
assert(Date(1999, 3, 1).diffMonths(Date(1999, 1, 1)) == 2);
assert(Date(1999, 1, 1).diffMonths(Date(1999, 3, 31)) == -2);
--------------------
+/
int diffMonths(in Date rhs) const pure nothrow
{
immutable yearDiff = _year - rhs._year;
immutable monthDiff = _month - rhs._month;
return yearDiff * 12 + monthDiff;
}
unittest
{
auto date = Date(1999, 7, 6);
//Test A.D.
assertPred!"=="(date.diffMonths(Date(1998, 6, 5)), 13);
assertPred!"=="(date.diffMonths(Date(1998, 7, 5)), 12);
assertPred!"=="(date.diffMonths(Date(1998, 8, 5)), 11);
assertPred!"=="(date.diffMonths(Date(1998, 9, 5)), 10);
assertPred!"=="(date.diffMonths(Date(1998, 10, 5)), 9);
assertPred!"=="(date.diffMonths(Date(1998, 11, 5)), 8);
assertPred!"=="(date.diffMonths(Date(1998, 12, 5)), 7);
assertPred!"=="(date.diffMonths(Date(1999, 1, 5)), 6);
assertPred!"=="(date.diffMonths(Date(1999, 2, 6)), 5);
assertPred!"=="(date.diffMonths(Date(1999, 3, 6)), 4);
assertPred!"=="(date.diffMonths(Date(1999, 4, 6)), 3);
assertPred!"=="(date.diffMonths(Date(1999, 5, 6)), 2);
assertPred!"=="(date.diffMonths(Date(1999, 6, 6)), 1);
assertPred!"=="(date.diffMonths(date), 0);
assertPred!"=="(date.diffMonths(Date(1999, 8, 6)), -1);
assertPred!"=="(date.diffMonths(Date(1999, 9, 6)), -2);
assertPred!"=="(date.diffMonths(Date(1999, 10, 6)), -3);
assertPred!"=="(date.diffMonths(Date(1999, 11, 6)), -4);
assertPred!"=="(date.diffMonths(Date(1999, 12, 6)), -5);
assertPred!"=="(date.diffMonths(Date(2000, 1, 6)), -6);
assertPred!"=="(date.diffMonths(Date(2000, 2, 6)), -7);
assertPred!"=="(date.diffMonths(Date(2000, 3, 6)), -8);
assertPred!"=="(date.diffMonths(Date(2000, 4, 6)), -9);
assertPred!"=="(date.diffMonths(Date(2000, 5, 6)), -10);
assertPred!"=="(date.diffMonths(Date(2000, 6, 6)), -11);
assertPred!"=="(date.diffMonths(Date(2000, 7, 6)), -12);
assertPred!"=="(date.diffMonths(Date(2000, 8, 6)), -13);
assertPred!"=="(Date(1998, 6, 5).diffMonths(date), -13);
assertPred!"=="(Date(1998, 7, 5).diffMonths(date), -12);
assertPred!"=="(Date(1998, 8, 5).diffMonths(date), -11);
assertPred!"=="(Date(1998, 9, 5).diffMonths(date), -10);
assertPred!"=="(Date(1998, 10, 5).diffMonths(date), -9);
assertPred!"=="(Date(1998, 11, 5).diffMonths(date), -8);
assertPred!"=="(Date(1998, 12, 5).diffMonths(date), -7);
assertPred!"=="(Date(1999, 1, 5).diffMonths(date), -6);
assertPred!"=="(Date(1999, 2, 6).diffMonths(date), -5);
assertPred!"=="(Date(1999, 3, 6).diffMonths(date), -4);
assertPred!"=="(Date(1999, 4, 6).diffMonths(date), -3);
assertPred!"=="(Date(1999, 5, 6).diffMonths(date), -2);
assertPred!"=="(Date(1999, 6, 6).diffMonths(date), -1);
assertPred!"=="(Date(1999, 8, 6).diffMonths(date), 1);
assertPred!"=="(Date(1999, 9, 6).diffMonths(date), 2);
assertPred!"=="(Date(1999, 10, 6).diffMonths(date), 3);
assertPred!"=="(Date(1999, 11, 6).diffMonths(date), 4);
assertPred!"=="(Date(1999, 12, 6).diffMonths(date), 5);
assertPred!"=="(Date(2000, 1, 6).diffMonths(date), 6);
assertPred!"=="(Date(2000, 2, 6).diffMonths(date), 7);
assertPred!"=="(Date(2000, 3, 6).diffMonths(date), 8);
assertPred!"=="(Date(2000, 4, 6).diffMonths(date), 9);
assertPred!"=="(Date(2000, 5, 6).diffMonths(date), 10);
assertPred!"=="(Date(2000, 6, 6).diffMonths(date), 11);
assertPred!"=="(Date(2000, 7, 6).diffMonths(date), 12);
assertPred!"=="(Date(2000, 8, 6).diffMonths(date), 13);
assertPred!"=="(date.diffMonths(Date(1999, 6, 30)), 1);
assertPred!"=="(date.diffMonths(Date(1999, 7, 1)), 0);
assertPred!"=="(date.diffMonths(Date(1999, 7, 6)), 0);
assertPred!"=="(date.diffMonths(Date(1999, 7, 11)), 0);
assertPred!"=="(date.diffMonths(Date(1999, 7, 16)), 0);
assertPred!"=="(date.diffMonths(Date(1999, 7, 21)), 0);
assertPred!"=="(date.diffMonths(Date(1999, 7, 26)), 0);
assertPred!"=="(date.diffMonths(Date(1999, 7, 31)), 0);
assertPred!"=="(date.diffMonths(Date(1999, 8, 1)), -1);
assertPred!"=="(date.diffMonths(Date(1990, 6, 30)), 109);
assertPred!"=="(date.diffMonths(Date(1990, 7, 1)), 108);
assertPred!"=="(date.diffMonths(Date(1990, 7, 6)), 108);
assertPred!"=="(date.diffMonths(Date(1990, 7, 11)), 108);
assertPred!"=="(date.diffMonths(Date(1990, 7, 16)), 108);
assertPred!"=="(date.diffMonths(Date(1990, 7, 21)), 108);
assertPred!"=="(date.diffMonths(Date(1990, 7, 26)), 108);
assertPred!"=="(date.diffMonths(Date(1990, 7, 31)), 108);
assertPred!"=="(date.diffMonths(Date(1990, 8, 1)), 107);
assertPred!"=="(Date(1999, 6, 30).diffMonths(date), -1);
assertPred!"=="(Date(1999, 7, 1).diffMonths(date), 0);
assertPred!"=="(Date(1999, 7, 6).diffMonths(date), 0);
assertPred!"=="(Date(1999, 7, 11).diffMonths(date), 0);
assertPred!"=="(Date(1999, 7, 16).diffMonths(date), 0);
assertPred!"=="(Date(1999, 7, 21).diffMonths(date), 0);
assertPred!"=="(Date(1999, 7, 26).diffMonths(date), 0);
assertPred!"=="(Date(1999, 7, 31).diffMonths(date), 0);
assertPred!"=="(Date(1999, 8, 1).diffMonths(date), 1);
assertPred!"=="(Date(1990, 6, 30).diffMonths(date), -109);
assertPred!"=="(Date(1990, 7, 1).diffMonths(date), -108);
assertPred!"=="(Date(1990, 7, 6).diffMonths(date), -108);
assertPred!"=="(Date(1990, 7, 11).diffMonths(date), -108);
assertPred!"=="(Date(1990, 7, 16).diffMonths(date), -108);
assertPred!"=="(Date(1990, 7, 21).diffMonths(date), -108);
assertPred!"=="(Date(1990, 7, 26).diffMonths(date), -108);
assertPred!"=="(Date(1990, 7, 31).diffMonths(date), -108);
assertPred!"=="(Date(1990, 8, 1).diffMonths(date), -107);
//Test B.C.
auto dateBC = Date(-1999, 7, 6);
assertPred!"=="(dateBC.diffMonths(Date(-2000, 6, 5)), 13);
assertPred!"=="(dateBC.diffMonths(Date(-2000, 7, 5)), 12);
assertPred!"=="(dateBC.diffMonths(Date(-2000, 8, 5)), 11);
assertPred!"=="(dateBC.diffMonths(Date(-2000, 9, 5)), 10);
assertPred!"=="(dateBC.diffMonths(Date(-2000, 10, 5)), 9);
assertPred!"=="(dateBC.diffMonths(Date(-2000, 11, 5)), 8);
assertPred!"=="(dateBC.diffMonths(Date(-2000, 12, 5)), 7);
assertPred!"=="(dateBC.diffMonths(Date(-1999, 1, 5)), 6);
assertPred!"=="(dateBC.diffMonths(Date(-1999, 2, 6)), 5);
assertPred!"=="(dateBC.diffMonths(Date(-1999, 3, 6)), 4);
assertPred!"=="(dateBC.diffMonths(Date(-1999, 4, 6)), 3);
assertPred!"=="(dateBC.diffMonths(Date(-1999, 5, 6)), 2);
assertPred!"=="(dateBC.diffMonths(Date(-1999, 6, 6)), 1);
assertPred!"=="(dateBC.diffMonths(dateBC), 0);
assertPred!"=="(dateBC.diffMonths(Date(-1999, 8, 6)), -1);
assertPred!"=="(dateBC.diffMonths(Date(-1999, 9, 6)), -2);
assertPred!"=="(dateBC.diffMonths(Date(-1999, 10, 6)), -3);
assertPred!"=="(dateBC.diffMonths(Date(-1999, 11, 6)), -4);
assertPred!"=="(dateBC.diffMonths(Date(-1999, 12, 6)), -5);
assertPred!"=="(dateBC.diffMonths(Date(-1998, 1, 6)), -6);
assertPred!"=="(dateBC.diffMonths(Date(-1998, 2, 6)), -7);
assertPred!"=="(dateBC.diffMonths(Date(-1998, 3, 6)), -8);
assertPred!"=="(dateBC.diffMonths(Date(-1998, 4, 6)), -9);
assertPred!"=="(dateBC.diffMonths(Date(-1998, 5, 6)), -10);
assertPred!"=="(dateBC.diffMonths(Date(-1998, 6, 6)), -11);
assertPred!"=="(dateBC.diffMonths(Date(-1998, 7, 6)), -12);
assertPred!"=="(dateBC.diffMonths(Date(-1998, 8, 6)), -13);
assertPred!"=="(Date(-2000, 6, 5).diffMonths(dateBC), -13);
assertPred!"=="(Date(-2000, 7, 5).diffMonths(dateBC), -12);
assertPred!"=="(Date(-2000, 8, 5).diffMonths(dateBC), -11);
assertPred!"=="(Date(-2000, 9, 5).diffMonths(dateBC), -10);
assertPred!"=="(Date(-2000, 10, 5).diffMonths(dateBC), -9);
assertPred!"=="(Date(-2000, 11, 5).diffMonths(dateBC), -8);
assertPred!"=="(Date(-2000, 12, 5).diffMonths(dateBC), -7);
assertPred!"=="(Date(-1999, 1, 5).diffMonths(dateBC), -6);
assertPred!"=="(Date(-1999, 2, 6).diffMonths(dateBC), -5);
assertPred!"=="(Date(-1999, 3, 6).diffMonths(dateBC), -4);
assertPred!"=="(Date(-1999, 4, 6).diffMonths(dateBC), -3);
assertPred!"=="(Date(-1999, 5, 6).diffMonths(dateBC), -2);
assertPred!"=="(Date(-1999, 6, 6).diffMonths(dateBC), -1);
assertPred!"=="(Date(-1999, 8, 6).diffMonths(dateBC), 1);
assertPred!"=="(Date(-1999, 9, 6).diffMonths(dateBC), 2);
assertPred!"=="(Date(-1999, 10, 6).diffMonths(dateBC), 3);
assertPred!"=="(Date(-1999, 11, 6).diffMonths(dateBC), 4);
assertPred!"=="(Date(-1999, 12, 6).diffMonths(dateBC), 5);
assertPred!"=="(Date(-1998, 1, 6).diffMonths(dateBC), 6);
assertPred!"=="(Date(-1998, 2, 6).diffMonths(dateBC), 7);
assertPred!"=="(Date(-1998, 3, 6).diffMonths(dateBC), 8);
assertPred!"=="(Date(-1998, 4, 6).diffMonths(dateBC), 9);
assertPred!"=="(Date(-1998, 5, 6).diffMonths(dateBC), 10);
assertPred!"=="(Date(-1998, 6, 6).diffMonths(dateBC), 11);
assertPred!"=="(Date(-1998, 7, 6).diffMonths(dateBC), 12);
assertPred!"=="(Date(-1998, 8, 6).diffMonths(dateBC), 13);
assertPred!"=="(dateBC.diffMonths(Date(-1999, 6, 30)), 1);
assertPred!"=="(dateBC.diffMonths(Date(-1999, 7, 1)), 0);
assertPred!"=="(dateBC.diffMonths(Date(-1999, 7, 6)), 0);
assertPred!"=="(dateBC.diffMonths(Date(-1999, 7, 11)), 0);
assertPred!"=="(dateBC.diffMonths(Date(-1999, 7, 16)), 0);
assertPred!"=="(dateBC.diffMonths(Date(-1999, 7, 21)), 0);
assertPred!"=="(dateBC.diffMonths(Date(-1999, 7, 26)), 0);
assertPred!"=="(dateBC.diffMonths(Date(-1999, 7, 31)), 0);
assertPred!"=="(dateBC.diffMonths(Date(-1999, 8, 1)), -1);
assertPred!"=="(dateBC.diffMonths(Date(-2008, 6, 30)), 109);
assertPred!"=="(dateBC.diffMonths(Date(-2008, 7, 1)), 108);
assertPred!"=="(dateBC.diffMonths(Date(-2008, 7, 6)), 108);
assertPred!"=="(dateBC.diffMonths(Date(-2008, 7, 11)), 108);
assertPred!"=="(dateBC.diffMonths(Date(-2008, 7, 16)), 108);
assertPred!"=="(dateBC.diffMonths(Date(-2008, 7, 21)), 108);
assertPred!"=="(dateBC.diffMonths(Date(-2008, 7, 26)), 108);
assertPred!"=="(dateBC.diffMonths(Date(-2008, 7, 31)), 108);
assertPred!"=="(dateBC.diffMonths(Date(-2008, 8, 1)), 107);
assertPred!"=="(Date(-1999, 6, 30).diffMonths(dateBC), -1);
assertPred!"=="(Date(-1999, 7, 1).diffMonths(dateBC), 0);
assertPred!"=="(Date(-1999, 7, 6).diffMonths(dateBC), 0);
assertPred!"=="(Date(-1999, 7, 11).diffMonths(dateBC), 0);
assertPred!"=="(Date(-1999, 7, 16).diffMonths(dateBC), 0);
assertPred!"=="(Date(-1999, 7, 21).diffMonths(dateBC), 0);
assertPred!"=="(Date(-1999, 7, 26).diffMonths(dateBC), 0);
assertPred!"=="(Date(-1999, 7, 31).diffMonths(dateBC), 0);
assertPred!"=="(Date(-1999, 8, 1).diffMonths(dateBC), 1);
assertPred!"=="(Date(-2008, 6, 30).diffMonths(dateBC), -109);
assertPred!"=="(Date(-2008, 7, 1).diffMonths(dateBC), -108);
assertPred!"=="(Date(-2008, 7, 6).diffMonths(dateBC), -108);
assertPred!"=="(Date(-2008, 7, 11).diffMonths(dateBC), -108);
assertPred!"=="(Date(-2008, 7, 16).diffMonths(dateBC), -108);
assertPred!"=="(Date(-2008, 7, 21).diffMonths(dateBC), -108);
assertPred!"=="(Date(-2008, 7, 26).diffMonths(dateBC), -108);
assertPred!"=="(Date(-2008, 7, 31).diffMonths(dateBC), -108);
assertPred!"=="(Date(-2008, 8, 1).diffMonths(dateBC), -107);
//Test Both
assertPred!"=="(Date(3, 3, 3).diffMonths(Date(-5, 5, 5)), 94);
assertPred!"=="(Date(-5, 5, 5).diffMonths(Date(3, 3, 3)), -94);
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(__traits(compiles, date.diffMonths(date)));
static assert(__traits(compiles, cdate.diffMonths(date)));
static assert(__traits(compiles, idate.diffMonths(date)));
static assert(__traits(compiles, date.diffMonths(cdate)));
static assert(__traits(compiles, cdate.diffMonths(cdate)));
static assert(__traits(compiles, idate.diffMonths(cdate)));
static assert(__traits(compiles, date.diffMonths(idate)));
static assert(__traits(compiles, cdate.diffMonths(idate)));
static assert(__traits(compiles, idate.diffMonths(idate)));
//Verify Examples.
assert(Date(1999, 2, 1).diffMonths(Date(1999, 1, 31)) == 1);
assert(Date(1999, 1, 31).diffMonths(Date(1999, 2, 1)) == -1);
assert(Date(1999, 3, 1).diffMonths(Date(1999, 1, 1)) == 2);
assert(Date(1999, 1, 1).diffMonths(Date(1999, 3, 31)) == -2);
}
/++
Whether this Date is in a leap year.
+/
@property bool isLeapYear() const pure nothrow
{
return yearIsLeapYear(_year);
}
unittest
{
auto date = Date(1999, 7, 6);
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(!__traits(compiles, date.isLeapYear = true));
static assert(!__traits(compiles, cdate.isLeapYear = true));
static assert(!__traits(compiles, idate.isLeapYear = true));
}
/++
Day of the week this Date is on.
+/
@property DayOfWeek dayOfWeek() const pure nothrow
{
return getDayOfWeek(dayOfGregorianCal);
}
unittest
{
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(__traits(compiles, cdate.dayOfWeek == DayOfWeek.sun));
static assert(!__traits(compiles, cdate.dayOfWeek = DayOfWeek.sun));
static assert(__traits(compiles, idate.dayOfWeek == DayOfWeek.sun));
static assert(!__traits(compiles, idate.dayOfWeek = DayOfWeek.sun));
}
/++
Day of the year this Date is on.
Examples:
--------------------
assert(Date(1999, 1, 1).dayOfYear == 1);
assert(Date(1999, 12, 31).dayOfYear == 365);
assert(Date(2000, 12, 31).dayOfYear == 366);
--------------------
+/
@property ushort dayOfYear() const pure nothrow
{
switch(_month)
{
case Month.jan:
return _day;
case Month.feb:
return cast(ushort)(31 + _day);
case Month.mar:
return cast(ushort)((isLeapYear ? 60 : 59) + _day);
case Month.apr:
return cast(ushort)((isLeapYear ? 91 : 90) + _day);
case Month.may:
return cast(ushort)((isLeapYear ? 121 : 120) + _day);
case Month.jun:
return cast(ushort)((isLeapYear ? 152 : 151) + _day);
case Month.jul:
return cast(ushort)((isLeapYear ? 182 : 181) + _day);
case Month.aug:
return cast(ushort)((isLeapYear ? 213 : 212) + _day);
case Month.sep:
return cast(ushort)((isLeapYear ? 244 : 243) + _day);
case Month.oct:
return cast(ushort)((isLeapYear ? 274 : 273) + _day);
case Month.nov:
return cast(ushort)((isLeapYear ? 305 : 304) + _day);
case Month.dec:
return cast(ushort)((isLeapYear ? 335 : 334) + _day);
default:
assert(0, "Invalid month.");
}
}
unittest
{
//Test A.D.
assertPred!"=="(Date(1999, 1, 1).dayOfYear, 1);
assertPred!"=="(Date(1999, 1, 2).dayOfYear, 2);
assertPred!"=="(Date(1999, 1, 3).dayOfYear, 3);
assertPred!"=="(Date(1999, 1, 31).dayOfYear, 31);
assertPred!"=="(Date(1999, 2, 1).dayOfYear, 32);
assertPred!"=="(Date(1999, 2, 28).dayOfYear, 59);
assertPred!"=="(Date(1999, 3, 1).dayOfYear, 60);
assertPred!"=="(Date(1999, 3, 31).dayOfYear, 90);
assertPred!"=="(Date(1999, 4, 1).dayOfYear, 91);
assertPred!"=="(Date(1999, 4, 30).dayOfYear, 120);
assertPred!"=="(Date(1999, 5, 1).dayOfYear, 121);
assertPred!"=="(Date(1999, 5, 31).dayOfYear, 151);
assertPred!"=="(Date(1999, 6, 1).dayOfYear, 152);
assertPred!"=="(Date(1999, 6, 30).dayOfYear, 181);
assertPred!"=="(Date(1999, 7, 1).dayOfYear, 182);
assertPred!"=="(Date(1999, 7, 31).dayOfYear, 212);
assertPred!"=="(Date(1999, 8, 1).dayOfYear, 213);
assertPred!"=="(Date(1999, 8, 31).dayOfYear, 243);
assertPred!"=="(Date(1999, 9, 1).dayOfYear, 244);
assertPred!"=="(Date(1999, 9, 30).dayOfYear, 273);
assertPred!"=="(Date(1999, 10, 1).dayOfYear, 274);
assertPred!"=="(Date(1999, 10, 31).dayOfYear, 304);
assertPred!"=="(Date(1999, 11, 1).dayOfYear, 305);
assertPred!"=="(Date(1999, 11, 30).dayOfYear, 334);
assertPred!"=="(Date(1999, 12, 1).dayOfYear, 335);
assertPred!"=="(Date(1999, 12, 31).dayOfYear, 365);
assertPred!"=="(Date(2000, 1, 1).dayOfYear, 1);
assertPred!"=="(Date(2000, 2, 1).dayOfYear, 32);
assertPred!"=="(Date(2000, 2, 29).dayOfYear, 60);
assertPred!"=="(Date(2000, 3, 1).dayOfYear, 61);
assertPred!"=="(Date(2000, 3, 31).dayOfYear, 91);
assertPred!"=="(Date(2000, 4, 1).dayOfYear, 92);
assertPred!"=="(Date(2000, 4, 30).dayOfYear, 121);
assertPred!"=="(Date(2000, 5, 1).dayOfYear, 122);
assertPred!"=="(Date(2000, 5, 31).dayOfYear, 152);
assertPred!"=="(Date(2000, 6, 1).dayOfYear, 153);
assertPred!"=="(Date(2000, 6, 30).dayOfYear, 182);
assertPred!"=="(Date(2000, 7, 1).dayOfYear, 183);
assertPred!"=="(Date(2000, 7, 31).dayOfYear, 213);
assertPred!"=="(Date(2000, 8, 1).dayOfYear, 214);
assertPred!"=="(Date(2000, 8, 31).dayOfYear, 244);
assertPred!"=="(Date(2000, 9, 1).dayOfYear, 245);
assertPred!"=="(Date(2000, 9, 30).dayOfYear, 274);
assertPred!"=="(Date(2000, 10, 1).dayOfYear, 275);
assertPred!"=="(Date(2000, 10, 31).dayOfYear, 305);
assertPred!"=="(Date(2000, 11, 1).dayOfYear, 306);
assertPred!"=="(Date(2000, 11, 30).dayOfYear, 335);
assertPred!"=="(Date(2000, 12, 1).dayOfYear, 336);
assertPred!"=="(Date(2000, 12, 31).dayOfYear, 366);
//Test B.C.
assertPred!"=="(Date(0, 1, 1).dayOfYear, 1);
assertPred!"=="(Date(0, 12, 31).dayOfYear, 366);
assertPred!"=="(Date(1, 1, 1).dayOfYear, 1);
assertPred!"=="(Date(1, 12, 31).dayOfYear, 365);
assertPred!"=="(Date(-1, 1, 1).dayOfYear, 1);
assertPred!"=="(Date(-1, 12, 31).dayOfYear, 365);
assertPred!"=="(Date(4, 1, 1).dayOfYear, 1);
assertPred!"=="(Date(4, 12, 31).dayOfYear, 366);
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(__traits(compiles, cdate.dayOfYear == 187));
static assert(__traits(compiles, idate.dayOfYear == 187));
//Verify Examples.
assert(Date(1999, 1, 1).dayOfYear == 1);
assert(Date(1999, 12, 31).dayOfYear == 365);
assert(Date(2000, 12, 31).dayOfYear == 366);
}
/++
Day of the year.
Params:
day = The day of the year to set which day of the year this Date is on.
Throws:
DateTimeException if the given day is an invalid day of the year.
+/
@property void dayOfYear(int day) pure
{
if(isLeapYear)
{
if(day <= 0 || day > daysInLeapYear)
throw new DateTimeException("Invalid day of the year.");
switch(day)
{
case 1: .. case 31:
{
_month = Month.jan;
_day = cast(ubyte)day;
break;
}
case 32: .. case 60:
{
_month = Month.feb;
_day = cast(ubyte)(day - 31);
break;
}
case 61: .. case 91:
{
_month = Month.mar;
_day = cast(ubyte)(day - 60);
break;
}
case 92: .. case 121:
{
_month = Month.apr;
_day = cast(ubyte)(day - 91);
break;
}
case 122: .. case 152:
{
_month = Month.may;
_day = cast(ubyte)(day - 121);
break;
}
case 153: .. case 182:
{
_month = Month.jun;
_day = cast(ubyte)(day - 152);
break;
}
case 183: .. case 213:
{
_month = Month.jul;
_day = cast(ubyte)(day - 182);
break;
}
case 214: .. case 244:
{
_month = Month.aug;
_day = cast(ubyte)(day - 213);
break;
}
case 245: .. case 274:
{
_month = Month.sep;
_day = cast(ubyte)(day - 244);
break;
}
case 275: .. case 305:
{
_month = Month.oct;
_day = cast(ubyte)(day - 274);
break;
}
case 306: .. case 335:
{
_month = Month.nov;
_day = cast(ubyte)(day - 305);
break;
}
case 336: .. case 366:
{
_month = Month.dec;
_day = cast(ubyte)(day - 335);
break;
}
default:
assert(0, "Invalid day of the year.");
}
}
else
{
if(day <= 0 || day > daysInYear)
throw new DateTimeException("Invalid day of the year.");
switch(day)
{
case 1: .. case 31:
{
_month = Month.jan;
_day = cast(ubyte)day;
break;
}
case 32: .. case 59:
{
_month = Month.feb;
_day = cast(ubyte)(day - 31);
break;
}
case 60: .. case 90:
{
_month = Month.mar;
_day = cast(ubyte)(day - 59);
break;
}
case 91: .. case 120:
{
_month = Month.apr;
_day = cast(ubyte)(day - 90);
break;
}
case 121: .. case 151:
{
_month = Month.may;
_day = cast(ubyte)(day - 120);
break;
}
case 152: .. case 181:
{
_month = Month.jun;
_day = cast(ubyte)(day - 151);
break;
}
case 182: .. case 212:
{
_month = Month.jul;
_day = cast(ubyte)(day - 181);
break;
}
case 213: .. case 243:
{
_month = Month.aug;
_day = cast(ubyte)(day - 212);
break;
}
case 244: .. case 273:
{
_month = Month.sep;
_day = cast(ubyte)(day - 243);
break;
}
case 274: .. case 304:
{
_month = Month.oct;
_day = cast(ubyte)(day - 273);
break;
}
case 305: .. case 334:
{
_month = Month.nov;
_day = cast(ubyte)(day - 304);
break;
}
case 335: .. case 365:
{
_month = Month.dec;
_day = cast(ubyte)(day - 334);
break;
}
default:
assert(0, "Invalid day of the year.");
}
}
}
unittest
{
auto date = Date(1999, 1, 1);
void testFunc(int day, int expectedMonth, int expectedDay, size_t line = __LINE__)
{
date.dayOfYear = day;
assertPred!"=="(date.month, expectedMonth, "", __FILE__, line);
assertPred!"=="(date.day, expectedDay, "", __FILE__, line);
}
//Test A.D.
testFunc(1, 1, 1);
testFunc(2, 1, 2);
testFunc(3, 1, 3);
testFunc(31, 1, 31);
testFunc(32, 2, 1);
testFunc(59, 2, 28);
testFunc(60, 3, 1);
testFunc(90, 3, 31);
testFunc(91, 4, 1);
testFunc(120, 4, 30);
testFunc(121, 5, 1);
testFunc(151, 5, 31);
testFunc(152, 6, 1);
testFunc(181, 6, 30);
testFunc(182, 7, 1);
testFunc(212, 7, 31);
testFunc(213, 8, 1);
testFunc(243, 8, 31);
testFunc(244, 9, 1);
testFunc(273, 9, 30);
testFunc(274, 10, 1);
testFunc(304, 10, 31);
testFunc(305, 11, 1);
testFunc(334, 11, 30);
testFunc(335, 12, 1);
testFunc(365, 12, 31);
date.year = 2000;
testFunc(1, 1, 1);
testFunc(32, 2, 1);
testFunc(60, 2, 29);
testFunc(61, 3, 1);
testFunc(91, 3, 31);
testFunc(92, 4, 1);
testFunc(121, 4, 30);
testFunc(122, 5, 1);
testFunc(152, 5, 31);
testFunc(153, 6, 1);
testFunc(182, 6, 30);
testFunc(183, 7, 1);
testFunc(213, 7, 31);
testFunc(214, 8, 1);
testFunc(244, 8, 31);
testFunc(245, 9, 1);
testFunc(274, 9, 30);
testFunc(275, 10, 1);
testFunc(305, 10, 31);
testFunc(306, 11, 1);
testFunc(335, 11, 30);
testFunc(336, 12, 1);
testFunc(366, 12, 31);
//Test B.C.
date.year = 0;
testFunc(1, 1, 1);
testFunc(32, 2, 1);
testFunc(60, 2, 29);
testFunc(61, 3, 1);
testFunc(91, 3, 31);
testFunc(92, 4, 1);
testFunc(121, 4, 30);
testFunc(122, 5, 1);
testFunc(152, 5, 31);
testFunc(153, 6, 1);
testFunc(182, 6, 30);
testFunc(183, 7, 1);
testFunc(213, 7, 31);
testFunc(214, 8, 1);
testFunc(244, 8, 31);
testFunc(245, 9, 1);
testFunc(274, 9, 30);
testFunc(275, 10, 1);
testFunc(305, 10, 31);
testFunc(306, 11, 1);
testFunc(335, 11, 30);
testFunc(336, 12, 1);
testFunc(366, 12, 31);
date.year = -1;
testFunc(1, 1, 1);
testFunc(2, 1, 2);
testFunc(3, 1, 3);
testFunc(31, 1, 31);
testFunc(32, 2, 1);
testFunc(59, 2, 28);
testFunc(60, 3, 1);
testFunc(90, 3, 31);
testFunc(91, 4, 1);
testFunc(120, 4, 30);
testFunc(121, 5, 1);
testFunc(151, 5, 31);
testFunc(152, 6, 1);
testFunc(181, 6, 30);
testFunc(182, 7, 1);
testFunc(212, 7, 31);
testFunc(213, 8, 1);
testFunc(243, 8, 31);
testFunc(244, 9, 1);
testFunc(273, 9, 30);
testFunc(274, 10, 1);
testFunc(304, 10, 31);
testFunc(305, 11, 1);
testFunc(334, 11, 30);
testFunc(335, 12, 1);
testFunc(365, 12, 31);
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(!__traits(compiles, cdate.dayOfYear = 187));
static assert(!__traits(compiles, idate.dayOfYear = 187));
}
/++
The Xth day of the Gregorian Calendar that this Date is on.
Examples:
--------------------
assert(Date(1, 1, 1).dayOfGregorianCal == 1);
assert(Date(1, 12, 31).dayOfGregorianCal == 365);
assert(Date(2, 1, 1).dayOfGregorianCal == 366);
assert(Date(0, 12, 31).dayOfGregorianCal == 0);
assert(Date(0, 1, 1).dayOfGregorianCal == -365);
assert(Date(-1, 12, 31).dayOfGregorianCal == -366);
assert(Date(2000, 1, 1).dayOfGregorianCal == 730_120);
assert(Date(2010, 12, 31).dayOfGregorianCal == 734_137);
--------------------
+/
@property int dayOfGregorianCal() const pure nothrow
{
if(isAD)
{
if(_year == 1)
return dayOfYear;
int years = _year - 1;
auto days = (years / 400) * daysIn400Years;
years %= 400;
days += (years / 100) * daysIn100Years;
years %= 100;
days += (years / 4) * daysIn4Years;
years %= 4;
days += years * daysInYear;
days += dayOfYear;
return days;
}
else if(_year == 0)
return dayOfYear - daysInLeapYear;
else
{
int years = _year;
auto days = (years / 400) * daysIn400Years;
years %= 400;
days += (years / 100) * daysIn100Years;
years %= 100;
days += (years / 4) * daysIn4Years;
years %= 4;
if(years < 0)
{
days -= daysInLeapYear;
++years;
days += years * daysInYear;
days -= daysInYear - dayOfYear;
}
else
days -= daysInLeapYear - dayOfYear;
return days;
}
}
unittest
{
//Test A.D.
assertPred!"=="(Date(1, 1, 1).dayOfGregorianCal, 1);
assertPred!"=="(Date(1, 1, 2).dayOfGregorianCal, 2);
assertPred!"=="(Date(1, 2, 1).dayOfGregorianCal, 32);
assertPred!"=="(Date(2, 1, 1).dayOfGregorianCal, 366);
assertPred!"=="(Date(3, 1, 1).dayOfGregorianCal, 731);
assertPred!"=="(Date(4, 1, 1).dayOfGregorianCal, 1096);
assertPred!"=="(Date(5, 1, 1).dayOfGregorianCal, 1462);
assertPred!"=="(Date(50, 1, 1).dayOfGregorianCal, 17_898);
assertPred!"=="(Date(97, 1, 1).dayOfGregorianCal, 35_065);
assertPred!"=="(Date(100, 1, 1).dayOfGregorianCal, 36_160);
assertPred!"=="(Date(101, 1, 1).dayOfGregorianCal, 36_525);
assertPred!"=="(Date(105, 1, 1).dayOfGregorianCal, 37_986);
assertPred!"=="(Date(200, 1, 1).dayOfGregorianCal, 72_684);
assertPred!"=="(Date(201, 1, 1).dayOfGregorianCal, 73_049);
assertPred!"=="(Date(300, 1, 1).dayOfGregorianCal, 109_208);
assertPred!"=="(Date(301, 1, 1).dayOfGregorianCal, 109_573);
assertPred!"=="(Date(400, 1, 1).dayOfGregorianCal, 145_732);
assertPred!"=="(Date(401, 1, 1).dayOfGregorianCal, 146_098);
assertPred!"=="(Date(500, 1, 1).dayOfGregorianCal, 182_257);
assertPred!"=="(Date(501, 1, 1).dayOfGregorianCal, 182_622);
assertPred!"=="(Date(1000, 1, 1).dayOfGregorianCal, 364_878);
assertPred!"=="(Date(1001, 1, 1).dayOfGregorianCal, 365_243);
assertPred!"=="(Date(1600, 1, 1).dayOfGregorianCal, 584_023);
assertPred!"=="(Date(1601, 1, 1).dayOfGregorianCal, 584_389);
assertPred!"=="(Date(1900, 1, 1).dayOfGregorianCal, 693_596);
assertPred!"=="(Date(1901, 1, 1).dayOfGregorianCal, 693_961);
assertPred!"=="(Date(1945, 11, 12).dayOfGregorianCal, 710_347);
assertPred!"=="(Date(1999, 1, 1).dayOfGregorianCal, 729_755);
assertPred!"=="(Date(2000, 1, 1).dayOfGregorianCal, 730_120);
assertPred!"=="(Date(2001, 1, 1).dayOfGregorianCal, 730_486);
assertPred!"=="(Date(2010, 1, 1).dayOfGregorianCal, 733_773);
assertPred!"=="(Date(2010, 1, 31).dayOfGregorianCal, 733_803);
assertPred!"=="(Date(2010, 2, 1).dayOfGregorianCal, 733_804);
assertPred!"=="(Date(2010, 2, 28).dayOfGregorianCal, 733_831);
assertPred!"=="(Date(2010, 3, 1).dayOfGregorianCal, 733_832);
assertPred!"=="(Date(2010, 3, 31).dayOfGregorianCal, 733_862);
assertPred!"=="(Date(2010, 4, 1).dayOfGregorianCal, 733_863);
assertPred!"=="(Date(2010, 4, 30).dayOfGregorianCal, 733_892);
assertPred!"=="(Date(2010, 5, 1).dayOfGregorianCal, 733_893);
assertPred!"=="(Date(2010, 5, 31).dayOfGregorianCal, 733_923);
assertPred!"=="(Date(2010, 6, 1).dayOfGregorianCal, 733_924);
assertPred!"=="(Date(2010, 6, 30).dayOfGregorianCal, 733_953);
assertPred!"=="(Date(2010, 7, 1).dayOfGregorianCal, 733_954);
assertPred!"=="(Date(2010, 7, 31).dayOfGregorianCal, 733_984);
assertPred!"=="(Date(2010, 8, 1).dayOfGregorianCal, 733_985);
assertPred!"=="(Date(2010, 8, 31).dayOfGregorianCal, 734_015);
assertPred!"=="(Date(2010, 9, 1).dayOfGregorianCal, 734_016);
assertPred!"=="(Date(2010, 9, 30).dayOfGregorianCal, 734_045);
assertPred!"=="(Date(2010, 10, 1).dayOfGregorianCal, 734_046);
assertPred!"=="(Date(2010, 10, 31).dayOfGregorianCal, 734_076);
assertPred!"=="(Date(2010, 11, 1).dayOfGregorianCal, 734_077);
assertPred!"=="(Date(2010, 11, 30).dayOfGregorianCal, 734_106);
assertPred!"=="(Date(2010, 12, 1).dayOfGregorianCal, 734_107);
assertPred!"=="(Date(2010, 12, 31).dayOfGregorianCal, 734_137);
assertPred!"=="(Date(2012, 2, 1).dayOfGregorianCal, 734_534);
assertPred!"=="(Date(2012, 2, 28).dayOfGregorianCal, 734_561);
assertPred!"=="(Date(2012, 2, 29).dayOfGregorianCal, 734_562);
assertPred!"=="(Date(2012, 3, 1).dayOfGregorianCal, 734_563);
//Test B.C.
assertPred!"=="(Date(0, 12, 31).dayOfGregorianCal, 0);
assertPred!"=="(Date(0, 12, 30).dayOfGregorianCal, -1);
assertPred!"=="(Date(0, 12, 1).dayOfGregorianCal, -30);
assertPred!"=="(Date(0, 11, 30).dayOfGregorianCal, -31);
assertPred!"=="(Date(-1, 12, 31).dayOfGregorianCal, -366);
assertPred!"=="(Date(-1, 12, 30).dayOfGregorianCal, -367);
assertPred!"=="(Date(-1, 1, 1).dayOfGregorianCal, -730);
assertPred!"=="(Date(-2, 12, 31).dayOfGregorianCal, -731);
assertPred!"=="(Date(-2, 1, 1).dayOfGregorianCal, -1095);
assertPred!"=="(Date(-3, 12, 31).dayOfGregorianCal, -1096);
assertPred!"=="(Date(-3, 1, 1).dayOfGregorianCal, -1460);
assertPred!"=="(Date(-4, 12, 31).dayOfGregorianCal, -1461);
assertPred!"=="(Date(-4, 1, 1).dayOfGregorianCal, -1826);
assertPred!"=="(Date(-5, 12, 31).dayOfGregorianCal, -1827);
assertPred!"=="(Date(-5, 1, 1).dayOfGregorianCal, -2191);
assertPred!"=="(Date(-9, 1, 1).dayOfGregorianCal, -3652);
assertPred!"=="(Date(-49, 1, 1).dayOfGregorianCal, -18_262);
assertPred!"=="(Date(-50, 1, 1).dayOfGregorianCal, -18_627);
assertPred!"=="(Date(-97, 1, 1).dayOfGregorianCal, -35_794);
assertPred!"=="(Date(-99, 12, 31).dayOfGregorianCal, -36_160);
assertPred!"=="(Date(-99, 1, 1).dayOfGregorianCal, -36_524);
assertPred!"=="(Date(-100, 1, 1).dayOfGregorianCal, -36_889);
assertPred!"=="(Date(-101, 1, 1).dayOfGregorianCal, -37_254);
assertPred!"=="(Date(-105, 1, 1).dayOfGregorianCal, -38_715);
assertPred!"=="(Date(-200, 1, 1).dayOfGregorianCal, -73_413);
assertPred!"=="(Date(-201, 1, 1).dayOfGregorianCal, -73_778);
assertPred!"=="(Date(-300, 1, 1).dayOfGregorianCal, -109_937);
assertPred!"=="(Date(-301, 1, 1).dayOfGregorianCal, -110_302);
assertPred!"=="(Date(-400, 12, 31).dayOfGregorianCal, -146_097);
assertPred!"=="(Date(-400, 1, 1).dayOfGregorianCal, -146_462);
assertPred!"=="(Date(-401, 1, 1).dayOfGregorianCal, -146_827);
assertPred!"=="(Date(-499, 1, 1).dayOfGregorianCal, -182_621);
assertPred!"=="(Date(-500, 1, 1).dayOfGregorianCal, -182_986);
assertPred!"=="(Date(-501, 1, 1).dayOfGregorianCal, -183_351);
assertPred!"=="(Date(-1000, 1, 1).dayOfGregorianCal, -365_607);
assertPred!"=="(Date(-1001, 1, 1).dayOfGregorianCal, -365_972);
assertPred!"=="(Date(-1599, 1, 1).dayOfGregorianCal, -584_387);
assertPred!"=="(Date(-1600, 12, 31).dayOfGregorianCal, -584_388);
assertPred!"=="(Date(-1600, 1, 1).dayOfGregorianCal, -584_753);
assertPred!"=="(Date(-1601, 1, 1).dayOfGregorianCal, -585_118);
assertPred!"=="(Date(-1900, 1, 1).dayOfGregorianCal, -694_325);
assertPred!"=="(Date(-1901, 1, 1).dayOfGregorianCal, -694_690);
assertPred!"=="(Date(-1999, 1, 1).dayOfGregorianCal, -730_484);
assertPred!"=="(Date(-2000, 12, 31).dayOfGregorianCal, -730_485);
assertPred!"=="(Date(-2000, 1, 1).dayOfGregorianCal, -730_850);
assertPred!"=="(Date(-2001, 1, 1).dayOfGregorianCal, -731_215);
assertPred!"=="(Date(-2010, 1, 1).dayOfGregorianCal, -734_502);
assertPred!"=="(Date(-2010, 1, 31).dayOfGregorianCal, -734_472);
assertPred!"=="(Date(-2010, 2, 1).dayOfGregorianCal, -734_471);
assertPred!"=="(Date(-2010, 2, 28).dayOfGregorianCal, -734_444);
assertPred!"=="(Date(-2010, 3, 1).dayOfGregorianCal, -734_443);
assertPred!"=="(Date(-2010, 3, 31).dayOfGregorianCal, -734_413);
assertPred!"=="(Date(-2010, 4, 1).dayOfGregorianCal, -734_412);
assertPred!"=="(Date(-2010, 4, 30).dayOfGregorianCal, -734_383);
assertPred!"=="(Date(-2010, 5, 1).dayOfGregorianCal, -734_382);
assertPred!"=="(Date(-2010, 5, 31).dayOfGregorianCal, -734_352);
assertPred!"=="(Date(-2010, 6, 1).dayOfGregorianCal, -734_351);
assertPred!"=="(Date(-2010, 6, 30).dayOfGregorianCal, -734_322);
assertPred!"=="(Date(-2010, 7, 1).dayOfGregorianCal, -734_321);
assertPred!"=="(Date(-2010, 7, 31).dayOfGregorianCal, -734_291);
assertPred!"=="(Date(-2010, 8, 1).dayOfGregorianCal, -734_290);
assertPred!"=="(Date(-2010, 8, 31).dayOfGregorianCal, -734_260);
assertPred!"=="(Date(-2010, 9, 1).dayOfGregorianCal, -734_259);
assertPred!"=="(Date(-2010, 9, 30).dayOfGregorianCal, -734_230);
assertPred!"=="(Date(-2010, 10, 1).dayOfGregorianCal, -734_229);
assertPred!"=="(Date(-2010, 10, 31).dayOfGregorianCal, -734_199);
assertPred!"=="(Date(-2010, 11, 1).dayOfGregorianCal, -734_198);
assertPred!"=="(Date(-2010, 11, 30).dayOfGregorianCal, -734_169);
assertPred!"=="(Date(-2010, 12, 1).dayOfGregorianCal, -734_168);
assertPred!"=="(Date(-2010, 12, 31).dayOfGregorianCal, -734_138);
assertPred!"=="(Date(-2012, 2, 1).dayOfGregorianCal, -735_202);
assertPred!"=="(Date(-2012, 2, 28).dayOfGregorianCal, -735_175);
assertPred!"=="(Date(-2012, 2, 29).dayOfGregorianCal, -735_174);
assertPred!"=="(Date(-2012, 3, 1).dayOfGregorianCal, -735_173);
assertPred!"=="(Date(-3760, 9, 7).dayOfGregorianCal, -1_373_427); //Start of Hebrew Calendar
auto date = Date(1999, 7, 6);
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(__traits(compiles, date.dayOfGregorianCal));
static assert(__traits(compiles, cdate.dayOfGregorianCal));
static assert(__traits(compiles, idate.dayOfGregorianCal));
//Verify Examples.
assert(Date(1, 1, 1).dayOfGregorianCal == 1);
assert(Date(1, 12, 31).dayOfGregorianCal == 365);
assert(Date(2, 1, 1).dayOfGregorianCal == 366);
assert(Date(0, 12, 31).dayOfGregorianCal == 0);
assert(Date(0, 1, 1).dayOfGregorianCal == -365);
assert(Date(-1, 12, 31).dayOfGregorianCal == -366);
assert(Date(2000, 1, 1).dayOfGregorianCal == 730_120);
assert(Date(2010, 12, 31).dayOfGregorianCal == 734_137);
}
/++
The Xth day of the Gregorian Calendar that this Date is on.
Params:
day = The day of the Gregorian Calendar to set this Date to.
Examples:
--------------------
auto date = Date.init;
date.dayOfGregorianCal = 1;
assert(date == Date(1, 1, 1));
date.dayOfGregorianCal = 365;
assert(date == Date(1, 12, 31));
date.dayOfGregorianCal = 366;
assert(date == Date(2, 1, 1));
date.dayOfGregorianCal = 0;
assert(date == Date(0, 12, 31));
date.dayOfGregorianCal = -365;
assert(date == Date(-0, 1, 1));
date.dayOfGregorianCal = -366;
assert(date == Date(-1, 12, 31));
date.dayOfGregorianCal = 730_120;
assert(date == Date(2000, 1, 1));
date.dayOfGregorianCal = 734_137;
assert(date == Date(2010, 12, 31));
--------------------
+/
@property void dayOfGregorianCal(int day) pure nothrow
{
this = Date(day);
}
unittest
{
{
auto date = Date(1999, 7, 6);
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(__traits(compiles, date.dayOfGregorianCal = 187));
static assert(!__traits(compiles, cdate.dayOfGregorianCal = 187));
static assert(!__traits(compiles, idate.dayOfGregorianCal = 187));
}
//Verify Examples.
{
auto date = Date.init;
date.dayOfGregorianCal = 1;
assert(date == Date(1, 1, 1));
date.dayOfGregorianCal = 365;
assert(date == Date(1, 12, 31));
date.dayOfGregorianCal = 366;
assert(date == Date(2, 1, 1));
date.dayOfGregorianCal = 0;
assert(date == Date(0, 12, 31));
date.dayOfGregorianCal = -365;
assert(date == Date(-0, 1, 1));
date.dayOfGregorianCal = -366;
assert(date == Date(-1, 12, 31));
date.dayOfGregorianCal = 730_120;
assert(date == Date(2000, 1, 1));
date.dayOfGregorianCal = 734_137;
assert(date == Date(2010, 12, 31));
}
}
/++
The ISO 8601 week of the year that this Date is in.
See_Also:
ISO Week Date
+/
@property ubyte isoWeek() const pure nothrow
{
immutable weekday = dayOfWeek;
immutable adjustedWeekday = weekday == DayOfWeek.sun ? 7 : weekday;
immutable week = (dayOfYear - adjustedWeekday + 10) / 7;
try
{
if(week == 53)
{
switch(Date(_year + 1, 1, 1).dayOfWeek)
{
case DayOfWeek.mon:
case DayOfWeek.tue:
case DayOfWeek.wed:
case DayOfWeek.thu:
return 1;
case DayOfWeek.fri:
case DayOfWeek.sat:
case DayOfWeek.sun:
return 53;
default:
assert(0, "Invalid ISO Week");
}
}
else if(week > 0)
return cast(ubyte)week;
else
return Date(_year - 1, 12, 31).isoWeek;
}
catch(Exception e)
assert(0, "Date's constructor threw.");
}
unittest
{
//Test A.D.
assertPred!"=="(Date(2009, 12, 28).isoWeek, 53);
assertPred!"=="(Date(2009, 12, 29).isoWeek, 53);
assertPred!"=="(Date(2009, 12, 30).isoWeek, 53);
assertPred!"=="(Date(2009, 12, 31).isoWeek, 53);
assertPred!"=="(Date(2010, 1, 1).isoWeek, 53);
assertPred!"=="(Date(2010, 1, 2).isoWeek, 53);
assertPred!"=="(Date(2010, 1, 3).isoWeek, 53);
assertPred!"=="(Date(2010, 1, 4).isoWeek, 1);
assertPred!"=="(Date(2010, 1, 5).isoWeek, 1);
assertPred!"=="(Date(2010, 1, 6).isoWeek, 1);
assertPred!"=="(Date(2010, 1, 7).isoWeek, 1);
assertPred!"=="(Date(2010, 1, 8).isoWeek, 1);
assertPred!"=="(Date(2010, 1, 9).isoWeek, 1);
assertPred!"=="(Date(2010, 1, 10).isoWeek, 1);
assertPred!"=="(Date(2010, 1, 11).isoWeek, 2);
assertPred!"=="(Date(2010, 12, 31).isoWeek, 52);
assertPred!"=="(Date(2004, 12, 26).isoWeek, 52);
assertPred!"=="(Date(2004, 12, 27).isoWeek, 53);
assertPred!"=="(Date(2004, 12, 28).isoWeek, 53);
assertPred!"=="(Date(2004, 12, 29).isoWeek, 53);
assertPred!"=="(Date(2004, 12, 30).isoWeek, 53);
assertPred!"=="(Date(2004, 12, 31).isoWeek, 53);
assertPred!"=="(Date(2005, 1, 1).isoWeek, 53);
assertPred!"=="(Date(2005, 1, 2).isoWeek, 53);
assertPred!"=="(Date(2005, 12, 31).isoWeek, 52);
assertPred!"=="(Date(2007, 1, 1).isoWeek, 1);
assertPred!"=="(Date(2007, 12, 30).isoWeek, 52);
assertPred!"=="(Date(2007, 12, 31).isoWeek, 1);
assertPred!"=="(Date(2008, 1, 1).isoWeek, 1);
assertPred!"=="(Date(2008, 12, 28).isoWeek, 52);
assertPred!"=="(Date(2008, 12, 29).isoWeek, 1);
assertPred!"=="(Date(2008, 12, 30).isoWeek, 1);
assertPred!"=="(Date(2008, 12, 31).isoWeek, 1);
assertPred!"=="(Date(2009, 1, 1).isoWeek, 1);
assertPred!"=="(Date(2009, 1, 2).isoWeek, 1);
assertPred!"=="(Date(2009, 1, 3).isoWeek, 1);
assertPred!"=="(Date(2009, 1, 4).isoWeek, 1);
//Test B.C.
//The algorithm should work identically for both A.D. and B.C. since
//it doesn't really take the year into account, so B.C. testing
//probably isn't really needed.
assertPred!"=="(Date(0, 12, 31).isoWeek, 52);
assertPred!"=="(Date(0, 1, 4).isoWeek, 1);
assertPred!"=="(Date(0, 1, 1).isoWeek, 52);
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(__traits(compiles, cdate.isoWeek == 3));
static assert(!__traits(compiles, cdate.isoWeek = 3));
static assert(__traits(compiles, idate.isoWeek == 3));
static assert(!__traits(compiles, idate.isoWeek = 3));
}
/++
Date for the last day in the month that this Date is in.
Examples:
--------------------
assert(Date(1999, 1, 6).endOfMonth == Date(1999, 1, 31));
assert(Date(1999, 2, 7).endOfMonth == Date(1999, 2, 28));
assert(Date(2000, 2, 7).endOfMonth == Date(1999, 2, 29));
assert(Date(2000, 6, 4).endOfMonth == Date(1999, 6, 30));
--------------------
+/
@property Date endOfMonth() const pure nothrow
{
try
return Date(_year, _month, maxDay(_year, _month));
catch(Exception e)
assert(0, "Date's constructor threw.");
}
unittest
{
//Test A.D.
assertPred!"=="(Date(1999, 1, 1).endOfMonth, Date(1999, 1, 31));
assertPred!"=="(Date(1999, 2, 1).endOfMonth, Date(1999, 2, 28));
assertPred!"=="(Date(2000, 2, 1).endOfMonth, Date(2000, 2, 29));
assertPred!"=="(Date(1999, 3, 1).endOfMonth, Date(1999, 3, 31));
assertPred!"=="(Date(1999, 4, 1).endOfMonth, Date(1999, 4, 30));
assertPred!"=="(Date(1999, 5, 1).endOfMonth, Date(1999, 5, 31));
assertPred!"=="(Date(1999, 6, 1).endOfMonth, Date(1999, 6, 30));
assertPred!"=="(Date(1999, 7, 1).endOfMonth, Date(1999, 7, 31));
assertPred!"=="(Date(1999, 8, 1).endOfMonth, Date(1999, 8, 31));
assertPred!"=="(Date(1999, 9, 1).endOfMonth, Date(1999, 9, 30));
assertPred!"=="(Date(1999, 10, 1).endOfMonth, Date(1999, 10, 31));
assertPred!"=="(Date(1999, 11, 1).endOfMonth, Date(1999, 11, 30));
assertPred!"=="(Date(1999, 12, 1).endOfMonth, Date(1999, 12, 31));
//Test B.C.
assertPred!"=="(Date(-1999, 1, 1).endOfMonth, Date(-1999, 1, 31));
assertPred!"=="(Date(-1999, 2, 1).endOfMonth, Date(-1999, 2, 28));
assertPred!"=="(Date(-2000, 2, 1).endOfMonth, Date(-2000, 2, 29));
assertPred!"=="(Date(-1999, 3, 1).endOfMonth, Date(-1999, 3, 31));
assertPred!"=="(Date(-1999, 4, 1).endOfMonth, Date(-1999, 4, 30));
assertPred!"=="(Date(-1999, 5, 1).endOfMonth, Date(-1999, 5, 31));
assertPred!"=="(Date(-1999, 6, 1).endOfMonth, Date(-1999, 6, 30));
assertPred!"=="(Date(-1999, 7, 1).endOfMonth, Date(-1999, 7, 31));
assertPred!"=="(Date(-1999, 8, 1).endOfMonth, Date(-1999, 8, 31));
assertPred!"=="(Date(-1999, 9, 1).endOfMonth, Date(-1999, 9, 30));
assertPred!"=="(Date(-1999, 10, 1).endOfMonth, Date(-1999, 10, 31));
assertPred!"=="(Date(-1999, 11, 1).endOfMonth, Date(-1999, 11, 30));
assertPred!"=="(Date(-1999, 12, 1).endOfMonth, Date(-1999, 12, 31));
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(!__traits(compiles, cdate.endOfMonth = Date(1999, 7, 30)));
static assert(!__traits(compiles, idate.endOfMonth = Date(1999, 7, 30)));
//Verify Examples.
assert(Date(1999, 1, 6).endOfMonth == Date(1999, 1, 31));
assert(Date(1999, 2, 7).endOfMonth == Date(1999, 2, 28));
assert(Date(2000, 2, 7).endOfMonth == Date(2000, 2, 29));
assert(Date(2000, 6, 4).endOfMonth == Date(2000, 6, 30));
}
/++
The last day in the month that this Date is in.
Examples:
--------------------
assert(Date(1999, 1, 6).endOfMonthDay == 31);
assert(Date(1999, 2, 7).endOfMonthDay == 28);
assert(Date(2000, 2, 7).endOfMonthDay == 29);
assert(Date(2000, 6, 4).endOfMonthDay == 30);
--------------------
+/
@property ubyte endOfMonthDay() const pure nothrow
{
return maxDay(_year, _month);
}
unittest
{
//Test A.D.
assertPred!"=="(Date(1999, 1, 1).endOfMonthDay, 31);
assertPred!"=="(Date(1999, 2, 1).endOfMonthDay, 28);
assertPred!"=="(Date(2000, 2, 1).endOfMonthDay, 29);
assertPred!"=="(Date(1999, 3, 1).endOfMonthDay, 31);
assertPred!"=="(Date(1999, 4, 1).endOfMonthDay, 30);
assertPred!"=="(Date(1999, 5, 1).endOfMonthDay, 31);
assertPred!"=="(Date(1999, 6, 1).endOfMonthDay, 30);
assertPred!"=="(Date(1999, 7, 1).endOfMonthDay, 31);
assertPred!"=="(Date(1999, 8, 1).endOfMonthDay, 31);
assertPred!"=="(Date(1999, 9, 1).endOfMonthDay, 30);
assertPred!"=="(Date(1999, 10, 1).endOfMonthDay, 31);
assertPred!"=="(Date(1999, 11, 1).endOfMonthDay, 30);
assertPred!"=="(Date(1999, 12, 1).endOfMonthDay, 31);
//Test B.C.
assertPred!"=="(Date(-1999, 1, 1).endOfMonthDay, 31);
assertPred!"=="(Date(-1999, 2, 1).endOfMonthDay, 28);
assertPred!"=="(Date(-2000, 2, 1).endOfMonthDay, 29);
assertPred!"=="(Date(-1999, 3, 1).endOfMonthDay, 31);
assertPred!"=="(Date(-1999, 4, 1).endOfMonthDay, 30);
assertPred!"=="(Date(-1999, 5, 1).endOfMonthDay, 31);
assertPred!"=="(Date(-1999, 6, 1).endOfMonthDay, 30);
assertPred!"=="(Date(-1999, 7, 1).endOfMonthDay, 31);
assertPred!"=="(Date(-1999, 8, 1).endOfMonthDay, 31);
assertPred!"=="(Date(-1999, 9, 1).endOfMonthDay, 30);
assertPred!"=="(Date(-1999, 10, 1).endOfMonthDay, 31);
assertPred!"=="(Date(-1999, 11, 1).endOfMonthDay, 30);
assertPred!"=="(Date(-1999, 12, 1).endOfMonthDay, 31);
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(!__traits(compiles, cdate.endOfMonthDay = 30));
static assert(!__traits(compiles, idate.endOfMonthDay = 30));
//Verify Examples.
assert(Date(1999, 1, 6).endOfMonthDay == 31);
assert(Date(1999, 2, 7).endOfMonthDay == 28);
assert(Date(2000, 2, 7).endOfMonthDay == 29);
assert(Date(2000, 6, 4).endOfMonthDay == 30);
}
/++
Whether the current year is a date in A.D.
Examples:
--------------------
assert(Date(1, 1, 1).isAD);
assert(Date(2010, 12, 31).isAD);
assert(!Date(0, 12, 31).isAD);
assert(!Date(-2010, 1, 1).isAD);
--------------------
+/
@property bool isAD() const pure nothrow
{
return _year > 0;
}
unittest
{
assert(Date(2010, 7, 4).isAD);
assert(Date(1, 1, 1).isAD);
assert(!Date(0, 1, 1).isAD);
assert(!Date(-1, 1, 1).isAD);
assert(!Date(-2010, 7, 4).isAD);
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(__traits(compiles, cdate.isAD));
static assert(__traits(compiles, idate.isAD));
//Verify Examples.
assert(Date(1, 1, 1).isAD);
assert(Date(2010, 12, 31).isAD);
assert(!Date(0, 12, 31).isAD);
assert(!Date(-2010, 1, 1).isAD);
}
/++
The julian day for this Date at noon (since the julian day changes at noon).
+/
@property long julianDay() const pure nothrow
{
return dayOfGregorianCal + 1_721_425;
}
unittest
{
assertPred!"=="(Date(-4713, 11, 24).julianDay, 0);
assertPred!"=="(Date(0, 12, 31).julianDay, 1_721_425);
assertPred!"=="(Date(1, 1, 1).julianDay, 1_721_426);
assertPred!"=="(Date(1582, 10, 15).julianDay, 2_299_161);
assertPred!"=="(Date(1858, 11, 17).julianDay, 2_400_001);
assertPred!"=="(Date(1982, 1, 4).julianDay, 2_444_974);
assertPred!"=="(Date(1996, 3, 31).julianDay, 2_450_174);
assertPred!"=="(Date(2010, 8, 24).julianDay, 2_455_433);
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(__traits(compiles, cdate.julianDay));
static assert(__traits(compiles, idate.julianDay));
}
/++
The modified julian day for any time on this Date (since, the modified
julian day changes at midnight).
+/
@property long modJulianDay() const pure nothrow
{
return julianDay - 2_400_001;
}
unittest
{
assertPred!"=="(Date(1858, 11, 17).modJulianDay, 0);
assertPred!"=="(Date(2010, 8, 24).modJulianDay, 55_432);
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(__traits(compiles, cdate.modJulianDay));
static assert(__traits(compiles, idate.modJulianDay));
}
/++
Converts this Date to a string with the format YYYYMMDD.
Examples:
--------------------
assert(Date(2010, 7, 4).toISOString() == "20100704");
assert(Date(1998, 12, 25).toISOString() == "19981225");
assert(Date(0, 1, 5).toISOString() == "00000105");
assert(Date(-4, 1, 5).toISOString() == "-00040105");
--------------------
+/
string toISOString() const nothrow
{
try
{
if(_year >= 0)
{
if(_year < 10_000)
return format("%04d%02d%02d", _year, _month, _day);
else
return format("+%05d%02d%02d", _year, _month, _day);
}
else if(_year > -10_000)
return format("%05d%02d%02d", _year, _month, _day);
else
return format("%06d%02d%02d", _year, _month, _day);
}
catch(Exception e)
assert(0, "format() threw.");
}
unittest
{
//Test A.D.
assertPred!"=="(Date(9, 12, 4).toISOString(), "00091204");
assertPred!"=="(Date(99, 12, 4).toISOString(), "00991204");
assertPred!"=="(Date(999, 12, 4).toISOString(), "09991204");
assertPred!"=="(Date(9999, 7, 4).toISOString(), "99990704");
assertPred!"=="(Date(10000, 10, 20).toISOString(), "+100001020");
//Test B.C.
assertPred!"=="(Date(0, 12, 4).toISOString(), "00001204");
assertPred!"=="(Date(-9, 12, 4).toISOString(), "-00091204");
assertPred!"=="(Date(-99, 12, 4).toISOString(), "-00991204");
assertPred!"=="(Date(-999, 12, 4).toISOString(), "-09991204");
assertPred!"=="(Date(-9999, 7, 4).toISOString(), "-99990704");
assertPred!"=="(Date(-10000, 10, 20).toISOString(), "-100001020");
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(__traits(compiles, cdate.toISOString()));
static assert(__traits(compiles, idate.toISOString()));
//Verify Examples.
assert(Date(2010, 7, 4).toISOString() == "20100704");
assert(Date(1998, 12, 25).toISOString() == "19981225");
assert(Date(0, 1, 5).toISOString() == "00000105");
assert(Date(-4, 1, 5).toISOString() == "-00040105");
}
/++
Converts this Date to a string with the format YYYY-MM-DD.
Examples:
--------------------
assert(Date(2010, 7, 4).toISOExtendedString() == "2010-07-04");
assert(Date(1998, 12, 25).toISOExtendedString() == "1998-12-25");
assert(Date(0, 1, 5).toISOExtendedString() == "0000-01-05");
assert(Date(-4, 1, 5).toISOExtendedString() == "-0004-01-05");
--------------------
+/
string toISOExtendedString() const nothrow
{
try
{
if(_year >= 0)
{
if(_year < 10_000)
return format("%04d-%02d-%02d", _year, _month, _day);
else
return format("+%05d-%02d-%02d", _year, _month, _day);
}
else if(_year > -10_000)
return format("%05d-%02d-%02d", _year, _month, _day);
else
return format("%06d-%02d-%02d", _year, _month, _day);
}
catch(Exception e)
assert(0, "format() threw.");
}
unittest
{
//Test A.D.
assertPred!"=="(Date(9, 12, 4).toISOExtendedString(), "0009-12-04");
assertPred!"=="(Date(99, 12, 4).toISOExtendedString(), "0099-12-04");
assertPred!"=="(Date(999, 12, 4).toISOExtendedString(), "0999-12-04");
assertPred!"=="(Date(9999, 7, 4).toISOExtendedString(), "9999-07-04");
assertPred!"=="(Date(10000, 10, 20).toISOExtendedString(), "+10000-10-20");
//Test B.C.
assertPred!"=="(Date(0, 12, 4).toISOExtendedString(), "0000-12-04");
assertPred!"=="(Date(-9, 12, 4).toISOExtendedString(), "-0009-12-04");
assertPred!"=="(Date(-99, 12, 4).toISOExtendedString(), "-0099-12-04");
assertPred!"=="(Date(-999, 12, 4).toISOExtendedString(), "-0999-12-04");
assertPred!"=="(Date(-9999, 7, 4).toISOExtendedString(), "-9999-07-04");
assertPred!"=="(Date(-10000, 10, 20).toISOExtendedString(), "-10000-10-20");
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(__traits(compiles, cdate.toISOExtendedString()));
static assert(__traits(compiles, idate.toISOExtendedString()));
//Verify Examples.
assert(Date(2010, 7, 4).toISOExtendedString() == "2010-07-04");
assert(Date(1998, 12, 25).toISOExtendedString() == "1998-12-25");
assert(Date(0, 1, 5).toISOExtendedString() == "0000-01-05");
assert(Date(-4, 1, 5).toISOExtendedString() == "-0004-01-05");
}
/++
Converts this Date to a string with the format YYYY-Mon-DD.
Examples:
--------------------
assert(Date(2010, 7, 4).toSimpleString() == "2010-Jul-04");
assert(Date(1998, 12, 25).toSimpleString() == "1998-Dec-25");
assert(Date(0, 1, 5).toSimpleString() == "0000-Jan-05");
assert(Date(-4, 1, 5).toSimpleString() == "-0004-Jan-05");
--------------------
+/
string toSimpleString() const nothrow
{
try
{
if(_year >= 0)
{
if(_year < 10_000)
return format("%04d-%s-%02d", _year, monthToString(_month, false), _day);
else
return format("+%05d-%s-%02d", _year, monthToString(_month, false), _day);
}
else if(_year > -10_000)
return format("%05d-%s-%02d", _year, monthToString(_month, false), _day);
else
return format("%06d-%s-%02d", _year, monthToString(_month, false), _day);
}
catch(Exception e)
assert(0, "format() threw.");
}
unittest
{
//Test A.D.
assertPred!"=="(Date(9, 12, 4).toSimpleString(), "0009-Dec-04");
assertPred!"=="(Date(99, 12, 4).toSimpleString(), "0099-Dec-04");
assertPred!"=="(Date(999, 12, 4).toSimpleString(), "0999-Dec-04");
assertPred!"=="(Date(9999, 7, 4).toSimpleString(), "9999-Jul-04");
assertPred!"=="(Date(10000, 10, 20).toSimpleString(), "+10000-Oct-20");
//Test B.C.
assertPred!"=="(Date(0, 12, 4).toSimpleString(), "0000-Dec-04");
assertPred!"=="(Date(-9, 12, 4).toSimpleString(), "-0009-Dec-04");
assertPred!"=="(Date(-99, 12, 4).toSimpleString(), "-0099-Dec-04");
assertPred!"=="(Date(-999, 12, 4).toSimpleString(), "-0999-Dec-04");
assertPred!"=="(Date(-9999, 7, 4).toSimpleString(), "-9999-Jul-04");
assertPred!"=="(Date(-10000, 10, 20).toSimpleString(), "-10000-Oct-20");
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(__traits(compiles, cdate.toSimpleString()));
static assert(__traits(compiles, idate.toSimpleString()));
//Verify Examples.
assert(Date(2010, 7, 4).toSimpleString() == "2010-Jul-04");
assert(Date(1998, 12, 25).toSimpleString() == "1998-Dec-25");
assert(Date(0, 1, 5).toSimpleString() == "0000-Jan-05");
assert(Date(-4, 1, 5).toSimpleString() == "-0004-Jan-05");
}
//TODO Add a function which returns a string in a user-specified format.
/+
Converts this Date to a string.
+/
//Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
//have versions of toString() with extra modifiers, so we define one version
//with modifiers and one without.
string toString()
{
return toSimpleString();
}
/++
Converts this Date to a string.
+/
//Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
//have versions of toString() with extra modifiers, so we define one version
//with modifiers and one without.
string toString() const nothrow
{
return toSimpleString();
}
unittest
{
auto date = Date(1999, 7, 6);
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(__traits(compiles, date.toString()));
static assert(__traits(compiles, cdate.toString()));
static assert(__traits(compiles, idate.toString()));
}
/++
Creates a Date from a string with the format YYYYMMDD. Whitespace is
stripped from the given string.
Params:
isoString = A string formatted in the ISO format for dates.
Throws:
DateTimeException if the given string is not in the ISO format or if
the resulting Date would not be valid.
Examples:
--------------------
assert(Date.fromISOString("20100704") == Date(2010, 7, 4));
assert(Date.fromISOString("19981225") == Date(1998, 12, 25));
assert(Date.fromISOString("00000105") == Date(0, 1, 5));
assert(Date.fromISOString("-00040105") == Date(-4, 1, 5));
assert(Date.fromISOString(" 20100704 ") == Date(2010, 7, 4));
--------------------
+/
static Date fromISOString(S)(in S isoString)
if(isSomeString!S)
{
auto dstr = to!dstring(strip(isoString));
enforce(dstr.length >= 8, new DateTimeException(format("Invalid ISO String: %s", isoString)));
auto day = dstr[$-2 .. $];
auto month = dstr[$-4 .. $-2];
auto year = dstr[0 .. $-4];
enforce(!canFind!((dchar c){return !isdigit(c);})(day), new DateTimeException(format("Invalid ISO String: %s", isoString)));
enforce(!canFind!((dchar c){return !isdigit(c);})(month), new DateTimeException(format("Invalid ISO String: %s", isoString)));
if(year.length > 4)
{
enforce(year.startsWith("-") || year.startsWith("+"), new DateTimeException(format("Invalid ISO String: %s", isoString)));
enforce(!canFind!((dchar c){return !isdigit(c);})(year[1..$]), new DateTimeException(format("Invalid ISO String: %s", isoString)));
}
else
enforce(!canFind!((dchar c){return !isdigit(c);})(year), new DateTimeException(format("Invalid ISO String: %s", isoString)));
return Date(to!short(year), to!ubyte(month), to!ubyte(day));
}
unittest
{
assertThrown!DateTimeException(Date.fromISOString(""));
assertThrown!DateTimeException(Date.fromISOString("990704"));
assertThrown!DateTimeException(Date.fromISOString("0100704"));
assertThrown!DateTimeException(Date.fromISOString("2010070"));
assertThrown!DateTimeException(Date.fromISOString("2010070 "));
assertThrown!DateTimeException(Date.fromISOString("120100704"));
assertThrown!DateTimeException(Date.fromISOString("-0100704"));
assertThrown!DateTimeException(Date.fromISOString("+0100704"));
assertThrown!DateTimeException(Date.fromISOString("2010070a"));
assertThrown!DateTimeException(Date.fromISOString("20100a04"));
assertThrown!DateTimeException(Date.fromISOString("2010a704"));
assertThrown!DateTimeException(Date.fromISOString("99-07-04"));
assertThrown!DateTimeException(Date.fromISOString("010-07-04"));
assertThrown!DateTimeException(Date.fromISOString("2010-07-0"));
assertThrown!DateTimeException(Date.fromISOString("2010-07-0 "));
assertThrown!DateTimeException(Date.fromISOString("12010-07-04"));
assertThrown!DateTimeException(Date.fromISOString("-010-07-04"));
assertThrown!DateTimeException(Date.fromISOString("+010-07-04"));
assertThrown!DateTimeException(Date.fromISOString("2010-07-0a"));
assertThrown!DateTimeException(Date.fromISOString("2010-0a-04"));
assertThrown!DateTimeException(Date.fromISOString("2010-a7-04"));
assertThrown!DateTimeException(Date.fromISOString("2010/07/04"));
assertThrown!DateTimeException(Date.fromISOString("2010/7/04"));
assertThrown!DateTimeException(Date.fromISOString("2010/7/4"));
assertThrown!DateTimeException(Date.fromISOString("2010/07/4"));
assertThrown!DateTimeException(Date.fromISOString("2010-7-04"));
assertThrown!DateTimeException(Date.fromISOString("2010-7-4"));
assertThrown!DateTimeException(Date.fromISOString("2010-07-4"));
assertThrown!DateTimeException(Date.fromISOString("99Jul04"));
assertThrown!DateTimeException(Date.fromISOString("010Jul04"));
assertThrown!DateTimeException(Date.fromISOString("2010Jul0"));
assertThrown!DateTimeException(Date.fromISOString("2010Jul0 "));
assertThrown!DateTimeException(Date.fromISOString("12010Jul04"));
assertThrown!DateTimeException(Date.fromISOString("-010Jul04"));
assertThrown!DateTimeException(Date.fromISOString("+010Jul04"));
assertThrown!DateTimeException(Date.fromISOString("2010Jul0a"));
assertThrown!DateTimeException(Date.fromISOString("2010Jua04"));
assertThrown!DateTimeException(Date.fromISOString("2010aul04"));
assertThrown!DateTimeException(Date.fromISOString("99-Jul-04"));
assertThrown!DateTimeException(Date.fromISOString("010-Jul-04"));
assertThrown!DateTimeException(Date.fromISOString("2010-Jul-0"));
assertThrown!DateTimeException(Date.fromISOString("2010-Jul-0 "));
assertThrown!DateTimeException(Date.fromISOString("12010-Jul-04"));
assertThrown!DateTimeException(Date.fromISOString("-010-Jul-04"));
assertThrown!DateTimeException(Date.fromISOString("+010-Jul-04"));
assertThrown!DateTimeException(Date.fromISOString("2010-Jul-0a"));
assertThrown!DateTimeException(Date.fromISOString("2010-Jua-04"));
assertThrown!DateTimeException(Date.fromISOString("2010-Jal-04"));
assertThrown!DateTimeException(Date.fromISOString("2010-aul-04"));
assertThrown!DateTimeException(Date.fromISOString("2010-07-04"));
assertThrown!DateTimeException(Date.fromISOString("2010-Jul-04"));
assertPred!"=="(Date.fromISOString("19990706"), Date(1999, 7, 6));
assertPred!"=="(Date.fromISOString("-19990706"), Date(-1999, 7, 6));
assertPred!"=="(Date.fromISOString("+019990706"), Date(1999, 7, 6));
assertPred!"=="(Date.fromISOString("19990706 "), Date(1999, 7, 6));
assertPred!"=="(Date.fromISOString(" 19990706"), Date(1999, 7, 6));
assertPred!"=="(Date.fromISOString(" 19990706 "), Date(1999, 7, 6));
//Verify Examples.
assert(Date.fromISOString("20100704") == Date(2010, 7, 4));
assert(Date.fromISOString("19981225") == Date(1998, 12, 25));
assert(Date.fromISOString("00000105") == Date(0, 1, 5));
assert(Date.fromISOString("-00040105") == Date(-4, 1, 5));
assert(Date.fromISOString(" 20100704 ") == Date(2010, 7, 4));
}
/++
Creates a Date from a string with the format YYYY-MM-DD. Whitespace is
stripped from the given string.
Params:
isoExtString = A string formatted in the ISO Extended format for
dates.
Throws:
DateTimeException if the given string is not in the ISO Extended
format or if the resulting Date would not be valid.
Examples:
--------------------
assert(Date.fromISOExtendedString("2010-07-04") == Date(2010, 7, 4));
assert(Date.fromISOExtendedString("1998-12-25") == Date(1998, 12, 25));
assert(Date.fromISOExtendedString("0000-01-05") == Date(0, 1, 5));
assert(Date.fromISOExtendedString("-0004-01-05") == Date(-4, 1, 5));
assert(Date.fromISOExtendedString(" 2010-07-04 ") == Date(2010, 7, 4));
--------------------
+/
static Date fromISOExtendedString(S)(in S isoExtString)
if(isSomeString!(S))
{
auto dstr = to!dstring(strip(isoExtString));
enforce(dstr.length >= 10, new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
auto day = dstr[$-2 .. $];
auto month = dstr[$-5 .. $-3];
auto year = dstr[0 .. $-6];
enforce(dstr[$-3] == '-', new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
enforce(dstr[$-6] == '-', new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
enforce(!canFind!((dchar c){return !isdigit(c);})(day), new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
enforce(!canFind!((dchar c){return !isdigit(c);})(month), new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
if(year.length > 4)
{
enforce(year.startsWith("-") || year.startsWith("+"), new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
enforce(!canFind!((dchar c){return !isdigit(c);})(year[1..$]), new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
}
else
enforce(!canFind!((dchar c){return !isdigit(c);})(year), new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
return Date(to!short(year), to!ubyte(month), to!ubyte(day));
}
unittest
{
assertThrown!DateTimeException(Date.fromISOExtendedString(""));
assertThrown!DateTimeException(Date.fromISOExtendedString("990704"));
assertThrown!DateTimeException(Date.fromISOExtendedString("0100704"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010070"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010070 "));
assertThrown!DateTimeException(Date.fromISOExtendedString("120100704"));
assertThrown!DateTimeException(Date.fromISOExtendedString("-0100704"));
assertThrown!DateTimeException(Date.fromISOExtendedString("+0100704"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010070a"));
assertThrown!DateTimeException(Date.fromISOExtendedString("20100a04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010a704"));
assertThrown!DateTimeException(Date.fromISOExtendedString("99-07-04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("010-07-04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010-07-0"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010-07-0 "));
assertThrown!DateTimeException(Date.fromISOExtendedString("12010-07-04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("-010-07-04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("+010-07-04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010-07-0a"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010-0a-04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010-a7-04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010/07/04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010/7/04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010/7/4"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010/07/4"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010-7-04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010-7-4"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010-07-4"));
assertThrown!DateTimeException(Date.fromISOExtendedString("99Jul04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("010Jul04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010Jul0"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010-Jul-0 "));
assertThrown!DateTimeException(Date.fromISOExtendedString("12010Jul04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("-010Jul04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("+010Jul04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010Jul0a"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010Jua04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010aul04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("99-Jul-04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("010-Jul-04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010-Jul-0"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010Jul0 "));
assertThrown!DateTimeException(Date.fromISOExtendedString("12010-Jul-04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("-010-Jul-04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("+010-Jul-04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010-Jul-0a"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010-Jua-04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010-Jal-04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010-aul-04"));
assertThrown!DateTimeException(Date.fromISOExtendedString("20100704"));
assertThrown!DateTimeException(Date.fromISOExtendedString("2010-Jul-04"));
assertPred!"=="(Date.fromISOExtendedString("1999-07-06"), Date(1999, 7, 6));
assertPred!"=="(Date.fromISOExtendedString("-1999-07-06"), Date(-1999, 7, 6));
assertPred!"=="(Date.fromISOExtendedString("+01999-07-06"), Date(1999, 7, 6));
assertPred!"=="(Date.fromISOExtendedString("1999-07-06 "), Date(1999, 7, 6));
assertPred!"=="(Date.fromISOExtendedString(" 1999-07-06"), Date(1999, 7, 6));
assertPred!"=="(Date.fromISOExtendedString(" 1999-07-06 "), Date(1999, 7, 6));
//Verify Examples.
assert(Date.fromISOExtendedString("2010-07-04") == Date(2010, 7, 4));
assert(Date.fromISOExtendedString("1998-12-25") == Date(1998, 12, 25));
assert(Date.fromISOExtendedString("0000-01-05") == Date(0, 1, 5));
assert(Date.fromISOExtendedString("-0004-01-05") == Date(-4, 1, 5));
assert(Date.fromISOExtendedString(" 2010-07-04 ") == Date(2010, 7, 4));
}
/++
Creates a Date from a string with the format YYYY-Mon-DD. Whitespace is
stripped from the given string.
Params:
simpleString = A string formatted in the way that toSimpleString()
formats dates.
Throws:
DateTimeException if the given string is not in the correct format or
if the resulting Date would not be valid.
Examples:
--------------------
assert(Date.fromSimpleString("2010-Jul-04") == Date(2010, 7, 4));
assert(Date.fromSimpleString("1998-Dec-25") == Date(1998, 12, 25));
assert(Date.fromSimpleString("0000-Jan-05") == Date(0, 1, 5));
assert(Date.fromSimpleString("-0004-Jan-05") == Date(-4, 1, 5));
assert(Date.fromSimpleString(" 2010-Jul-04 ") == Date(2010, 7, 4));
--------------------
+/
static Date fromSimpleString(S)(in S simpleString)
if(isSomeString!(S))
{
auto dstr = to!dstring(strip(simpleString));
enforce(dstr.length >= 11, new DateTimeException(format("Invalid string format: %s", simpleString)));
auto day = dstr[$-2 .. $];
auto month = monthFromString(to!string(dstr[$-6 .. $-3]));
auto year = dstr[0 .. $-7];
enforce(dstr[$-3] == '-', new DateTimeException(format("Invalid string format: %s", simpleString)));
enforce(dstr[$-7] == '-', new DateTimeException(format("Invalid string format: %s", simpleString)));
enforce(!canFind!((dchar c){return !isdigit(c);})(day), new DateTimeException(format("Invalid string format: %s", simpleString)));
if(year.length > 4)
{
enforce(year.startsWith("-") || year.startsWith("+"), new DateTimeException(format("Invalid string format: %s", simpleString)));
enforce(!canFind!((dchar c){return !isdigit(c);})(year[1..$]), new DateTimeException(format("Invalid string format: %s", simpleString)));
}
else
enforce(!canFind!((dchar c){return !isdigit(c);})(year), new DateTimeException(format("Invalid string format: %s", simpleString)));
return Date(to!short(year), month, to!ubyte(day));
}
unittest
{
assertThrown!DateTimeException(Date.fromSimpleString(""));
assertThrown!DateTimeException(Date.fromSimpleString("990704"));
assertThrown!DateTimeException(Date.fromSimpleString("0100704"));
assertThrown!DateTimeException(Date.fromSimpleString("2010070"));
assertThrown!DateTimeException(Date.fromSimpleString("2010070 "));
assertThrown!DateTimeException(Date.fromSimpleString("120100704"));
assertThrown!DateTimeException(Date.fromSimpleString("-0100704"));
assertThrown!DateTimeException(Date.fromSimpleString("+0100704"));
assertThrown!DateTimeException(Date.fromSimpleString("2010070a"));
assertThrown!DateTimeException(Date.fromSimpleString("20100a04"));
assertThrown!DateTimeException(Date.fromSimpleString("2010a704"));
assertThrown!DateTimeException(Date.fromSimpleString("99-07-04"));
assertThrown!DateTimeException(Date.fromSimpleString("010-07-04"));
assertThrown!DateTimeException(Date.fromSimpleString("2010-07-0"));
assertThrown!DateTimeException(Date.fromSimpleString("2010-07-0 "));
assertThrown!DateTimeException(Date.fromSimpleString("12010-07-04"));
assertThrown!DateTimeException(Date.fromSimpleString("-010-07-04"));
assertThrown!DateTimeException(Date.fromSimpleString("+010-07-04"));
assertThrown!DateTimeException(Date.fromSimpleString("2010-07-0a"));
assertThrown!DateTimeException(Date.fromSimpleString("2010-0a-04"));
assertThrown!DateTimeException(Date.fromSimpleString("2010-a7-04"));
assertThrown!DateTimeException(Date.fromSimpleString("2010/07/04"));
assertThrown!DateTimeException(Date.fromSimpleString("2010/7/04"));
assertThrown!DateTimeException(Date.fromSimpleString("2010/7/4"));
assertThrown!DateTimeException(Date.fromSimpleString("2010/07/4"));
assertThrown!DateTimeException(Date.fromSimpleString("2010-7-04"));
assertThrown!DateTimeException(Date.fromSimpleString("2010-7-4"));
assertThrown!DateTimeException(Date.fromSimpleString("2010-07-4"));
assertThrown!DateTimeException(Date.fromSimpleString("99Jul04"));
assertThrown!DateTimeException(Date.fromSimpleString("010Jul04"));
assertThrown!DateTimeException(Date.fromSimpleString("2010Jul0"));
assertThrown!DateTimeException(Date.fromSimpleString("2010Jul0 "));
assertThrown!DateTimeException(Date.fromSimpleString("12010Jul04"));
assertThrown!DateTimeException(Date.fromSimpleString("-010Jul04"));
assertThrown!DateTimeException(Date.fromSimpleString("+010Jul04"));
assertThrown!DateTimeException(Date.fromSimpleString("2010Jul0a"));
assertThrown!DateTimeException(Date.fromSimpleString("2010Jua04"));
assertThrown!DateTimeException(Date.fromSimpleString("2010aul04"));
assertThrown!DateTimeException(Date.fromSimpleString("99-Jul-04"));
assertThrown!DateTimeException(Date.fromSimpleString("010-Jul-04"));
assertThrown!DateTimeException(Date.fromSimpleString("2010-Jul-0"));
assertThrown!DateTimeException(Date.fromSimpleString("2010-Jul-0 "));
assertThrown!DateTimeException(Date.fromSimpleString("12010-Jul-04"));
assertThrown!DateTimeException(Date.fromSimpleString("-010-Jul-04"));
assertThrown!DateTimeException(Date.fromSimpleString("+010-Jul-04"));
assertThrown!DateTimeException(Date.fromSimpleString("2010-Jul-0a"));
assertThrown!DateTimeException(Date.fromSimpleString("2010-Jua-04"));
assertThrown!DateTimeException(Date.fromSimpleString("2010-Jal-04"));
assertThrown!DateTimeException(Date.fromSimpleString("2010-aul-04"));
assertThrown!DateTimeException(Date.fromSimpleString("20100704"));
assertThrown!DateTimeException(Date.fromSimpleString("2010-07-04"));
assertPred!"=="(Date.fromSimpleString("1999-Jul-06"), Date(1999, 7, 6));
assertPred!"=="(Date.fromSimpleString("-1999-Jul-06"), Date(-1999, 7, 6));
assertPred!"=="(Date.fromSimpleString("+01999-Jul-06"), Date(1999, 7, 6));
assertPred!"=="(Date.fromSimpleString("1999-Jul-06 "), Date(1999, 7, 6));
assertPred!"=="(Date.fromSimpleString(" 1999-Jul-06"), Date(1999, 7, 6));
assertPred!"=="(Date.fromSimpleString(" 1999-Jul-06 "), Date(1999, 7, 6));
//Verify Examples.
assert(Date.fromSimpleString("2010-Jul-04") == Date(2010, 7, 4));
assert(Date.fromSimpleString("1998-Dec-25") == Date(1998, 12, 25));
assert(Date.fromSimpleString("0000-Jan-05") == Date(0, 1, 5));
assert(Date.fromSimpleString("-0004-Jan-05") == Date(-4, 1, 5));
assert(Date.fromSimpleString(" 2010-Jul-04 ") == Date(2010, 7, 4));
}
//TODO Add function which takes a user-specified time format and produces a Date
//TODO Add function which takes pretty much any time-string and produces a Date
// Obviously, it will be less efficient, and it probably won't manage _every_
// possible date format, but a smart conversion function would be nice.
/++
Returns the Date farthest in the past which is representable by Date.
+/
@property static Date min() pure nothrow
{
auto date = Date.init;
date._year = short.min;
date._month = Month.jan;
date._day = 1;
return date;
}
unittest
{
assert(Date.min.year < 0);
assert(Date.min < Date.max);
}
/++
Returns the Date farthest in the future which is representable by Date.
+/
@property static Date max() pure nothrow
{
auto date = Date.init;
date._year = short.max;
date._month = Month.dec;
date._day = 31;
return date;
}
unittest
{
assert(Date.max.year > 0);
assert(Date.max > Date.min);
}
private:
/++
Whether the given values form a valid date.
Params:
year = The year to test.
month = The month of the Gregorian Calendar to test.
day = The day of the month to test.
+/
static bool _valid(int year, int month, int day) pure nothrow
{
if(!valid!"months"(month))
return false;
return valid!"days"(year, month, day);
}
/++
Adds the given number of days to this Date. A negative number will subtract.
The month will be adjusted along with the day if the number of days added
(or subtracted) would overflow (or underflow) the current month. The year
will be adjusted along with the month if the increase (or decrease) to the
month would cause it to overflow (or underflow) the current year.
addDays(numDays) is effectively equivalent to date.dayOfGregorianCal = date.dayOfGregorianCal + days.
Params:
days = The number of days to add to this Date.
+/
ref Date addDays(long days) pure nothrow
{
dayOfGregorianCal = cast(int)(dayOfGregorianCal + days);
return this;
}
unittest
{
//Test A.D.
{
auto date = Date(1999, 2, 28);
date.addDays(1);
assertPred!"=="(date, Date(1999, 3, 1));
date.addDays(-1);
assertPred!"=="(date, Date(1999, 2, 28));
}
{
auto date = Date(2000, 2, 28);
date.addDays(1);
assertPred!"=="(date, Date(2000, 2, 29));
date.addDays(1);
assertPred!"=="(date, Date(2000, 3, 1));
date.addDays(-1);
assertPred!"=="(date, Date(2000, 2, 29));
}
{
auto date = Date(1999, 6, 30);
date.addDays(1);
assertPred!"=="(date, Date(1999, 7, 1));
date.addDays(-1);
assertPred!"=="(date, Date(1999, 6, 30));
}
{
auto date = Date(1999, 7, 31);
date.addDays(1);
assertPred!"=="(date, Date(1999, 8, 1));
date.addDays(-1);
assertPred!"=="(date, Date(1999, 7, 31));
}
{
auto date = Date(1999, 1, 1);
date.addDays(-1);
assertPred!"=="(date, Date(1998, 12, 31));
date.addDays(1);
assertPred!"=="(date, Date(1999, 1, 1));
}
{
auto date = Date(1999, 7, 6);
date.addDays(9);
assertPred!"=="(date, Date(1999, 7, 15));
date.addDays(-11);
assertPred!"=="(date, Date(1999, 7, 4));
date.addDays(30);
assertPred!"=="(date, Date(1999, 8, 3));
date.addDays(-3);
assertPred!"=="(date, Date(1999, 7, 31));
}
{
auto date = Date(1999, 7, 6);
date.addDays(365);
assertPred!"=="(date, Date(2000, 7, 5));
date.addDays(-365);
assertPred!"=="(date, Date(1999, 7, 6));
date.addDays(366);
assertPred!"=="(date, Date(2000, 7, 6));
date.addDays(730);
assertPred!"=="(date, Date(2002, 7, 6));
date.addDays(-1096);
assertPred!"=="(date, Date(1999, 7, 6));
}
//Test B.C.
{
auto date = Date(-1999, 2, 28);
date.addDays(1);
assertPred!"=="(date, Date(-1999, 3, 1));
date.addDays(-1);
assertPred!"=="(date, Date(-1999, 2, 28));
}
{
auto date = Date(-2000, 2, 28);
date.addDays(1);
assertPred!"=="(date, Date(-2000, 2, 29));
date.addDays(1);
assertPred!"=="(date, Date(-2000, 3, 1));
date.addDays(-1);
assertPred!"=="(date, Date(-2000, 2, 29));
}
{
auto date = Date(-1999, 6, 30);
date.addDays(1);
assertPred!"=="(date, Date(-1999, 7, 1));
date.addDays(-1);
assertPred!"=="(date, Date(-1999, 6, 30));
}
{
auto date = Date(-1999, 7, 31);
date.addDays(1);
assertPred!"=="(date, Date(-1999, 8, 1));
date.addDays(-1);
assertPred!"=="(date, Date(-1999, 7, 31));
}
{
auto date = Date(-1999, 1, 1);
date.addDays(-1);
assertPred!"=="(date, Date(-2000, 12, 31));
date.addDays(1);
assertPred!"=="(date, Date(-1999, 1, 1));
}
{
auto date = Date(-1999, 7, 6);
date.addDays(9);
assertPred!"=="(date, Date(-1999, 7, 15));
date.addDays(-11);
assertPred!"=="(date, Date(-1999, 7, 4));
date.addDays(30);
assertPred!"=="(date, Date(-1999, 8, 3));
date.addDays(-3);
}
{
auto date = Date(-1999, 7, 6);
date.addDays(365);
assertPred!"=="(date, Date(-1998, 7, 6));
date.addDays(-365);
assertPred!"=="(date, Date(-1999, 7, 6));
date.addDays(366);
assertPred!"=="(date, Date(-1998, 7, 7));
date.addDays(730);
assertPred!"=="(date, Date(-1996, 7, 6));
date.addDays(-1096);
assertPred!"=="(date, Date(-1999, 7, 6));
}
//Test Both
{
auto date = Date(1, 7, 6);
date.addDays(-365);
assertPred!"=="(date, Date(0, 7, 6));
date.addDays(365);
assertPred!"=="(date, Date(1, 7, 6));
date.addDays(-731);
assertPred!"=="(date, Date(-1, 7, 6));
date.addDays(730);
assertPred!"=="(date, Date(1, 7, 5));
}
const cdate = Date(1999, 7, 6);
immutable idate = Date(1999, 7, 6);
static assert(!__traits(compiles, cdate.addDays(12)));
static assert(!__traits(compiles, idate.addDays(12)));
}
pure invariant()
{
assert(valid!"months"(_month), "Invariant Failure: year [" ~
numToString(_year) ~
"] month [" ~
numToString(_month) ~
"] day [" ~
numToString(_day) ~
"]");
assert(valid!"days"(_year, _month, _day), "Invariant Failure: year [" ~
numToString(_year) ~
"] month [" ~
numToString(_month) ~
"] day [" ~
numToString(_day) ~
"]");
}
short _year = 1;
Month _month = Month.jan;
ubyte _day = 1;
}
/++
Represents a time of day with hours, minutes, and seconds. It uses 24 hour time.
+/
struct TimeOfDay
{
public:
/++
Params:
hour = Hour of the day [0 - 24$(RPAREN).
minute = Minute of the hour [0 - 60$(RPAREN).
second = Second of the minute [0 - 60$(RPAREN).
Throws:
DateTimeException if the resulting TimeOfDay would be not be valid.
+/
this(int hour, int minute, int second = 0) pure
{
enforceValid!"hours"(hour);
enforceValid!"minutes"(minute);
enforceValid!"seconds"(second);
_hour = cast(ubyte)hour;
_minute = cast(ubyte)minute;
_second = cast(ubyte)second;
}
unittest
{
assert(TimeOfDay(0, 0) == TimeOfDay.init);
{
auto tod = TimeOfDay(0, 0);
assertPred!"=="(tod._hour, 0);
assertPred!"=="(tod._minute, 0);
assertPred!"=="(tod._second, 0);
}
{
auto tod = TimeOfDay(12, 30, 33);
assertPred!"=="(tod._hour, 12);
assertPred!"=="(tod._minute, 30);
assertPred!"=="(tod._second, 33);
}
{
auto tod = TimeOfDay(23, 59, 59);
assertPred!"=="(tod._hour, 23);
assertPred!"=="(tod._minute, 59);
assertPred!"=="(tod._second, 59);
}
assertThrown!DateTimeException(TimeOfDay(24, 0, 0));
assertThrown!DateTimeException(TimeOfDay(0, 60, 0));
assertThrown!DateTimeException(TimeOfDay(0, 0, 60));
}
/++
Compares this TimeOfDay with the given TimeOfDay.
Returns:
$(TABLE
$(TR $(TD this < rhs) $(TD < 0))
$(TR $(TD this == rhs) $(TD 0))
$(TR $(TD this > rhs) $(TD > 0))
)
+/
int opCmp(in TimeOfDay rhs) const pure nothrow
{
if(_hour < rhs._hour)
return -1;
if(_hour > rhs._hour)
return 1;
if(_minute < rhs._minute)
return -1;
if(_minute > rhs._minute)
return 1;
if(_second < rhs._second)
return -1;
if(_second > rhs._second)
return 1;
return 0;
}
unittest
{
assertPred!("opCmp", "==")(TimeOfDay(0, 0, 0), TimeOfDay.init);
assertPred!("opCmp", "==")(TimeOfDay(0, 0, 0), TimeOfDay(0, 0, 0));
assertPred!("opCmp", "==")(TimeOfDay(12, 0, 0), TimeOfDay(12, 0, 0));
assertPred!("opCmp", "==")(TimeOfDay(0, 30, 0), TimeOfDay(0, 30, 0));
assertPred!("opCmp", "==")(TimeOfDay(0, 0, 33), TimeOfDay(0, 0, 33));
assertPred!("opCmp", "==")(TimeOfDay(12, 30, 0), TimeOfDay(12, 30, 0));
assertPred!("opCmp", "==")(TimeOfDay(12, 30, 33), TimeOfDay(12, 30, 33));
assertPred!("opCmp", "==")(TimeOfDay(0, 30, 33), TimeOfDay(0, 30, 33));
assertPred!("opCmp", "==")(TimeOfDay(0, 0, 33), TimeOfDay(0, 0, 33));
assertPred!("opCmp", "<")(TimeOfDay(12, 30, 33), TimeOfDay(13, 30, 33));
assertPred!("opCmp", ">")(TimeOfDay(13, 30, 33), TimeOfDay(12, 30, 33));
assertPred!("opCmp", "<")(TimeOfDay(12, 30, 33), TimeOfDay(12, 31, 33));
assertPred!("opCmp", ">")(TimeOfDay(12, 31, 33), TimeOfDay(12, 30, 33));
assertPred!("opCmp", "<")(TimeOfDay(12, 30, 33), TimeOfDay(12, 30, 34));
assertPred!("opCmp", ">")(TimeOfDay(12, 30, 34), TimeOfDay(12, 30, 33));
assertPred!("opCmp", ">")(TimeOfDay(13, 30, 33), TimeOfDay(12, 30, 34));
assertPred!("opCmp", "<")(TimeOfDay(12, 30, 34), TimeOfDay(13, 30, 33));
assertPred!("opCmp", ">")(TimeOfDay(13, 30, 33), TimeOfDay(12, 31, 33));
assertPred!("opCmp", "<")(TimeOfDay(12, 31, 33), TimeOfDay(13, 30, 33));
assertPred!("opCmp", ">")(TimeOfDay(12, 31, 33), TimeOfDay(12, 30, 34));
assertPred!("opCmp", "<")(TimeOfDay(12, 30, 34), TimeOfDay(12, 31, 33));
const ctod = TimeOfDay(12, 30, 33);
immutable itod = TimeOfDay(12, 30, 33);
static assert(__traits(compiles, ctod.opCmp(itod)));
static assert(__traits(compiles, itod.opCmp(ctod)));
}
/++
Hours passed midnight.
+/
@property ubyte hour() const pure nothrow
{
return _hour;
}
unittest
{
assertPred!"=="(TimeOfDay.init.hour, 0);
assertPred!"=="(TimeOfDay(12, 0, 0).hour, 12);
const ctod = TimeOfDay(12, 0, 0);
immutable itod = TimeOfDay(12, 0, 0);
static assert(__traits(compiles, ctod.hour == 12));
static assert(__traits(compiles, itod.hour == 12));
}
/++
Hours passed midnight.
Params:
hour = The hour of the day to set this TimeOfDay's hour to.
Throws:
DateTimeException if the given hour would result in an invalid TimeOfDay.
+/
@property void hour(int hour) pure
{
enforceValid!"hours"(hour);
_hour = cast(ubyte)hour;
}
unittest
{
assertThrown!DateTimeException((){TimeOfDay(0, 0, 0).hour = 24;}());
auto tod = TimeOfDay(0, 0, 0);
tod.hour = 12;
assertPred!"=="(tod, TimeOfDay(12, 0, 0));
const ctod = TimeOfDay(0, 0, 0);
immutable itod = TimeOfDay(0, 0, 0);
static assert(!__traits(compiles, ctod.hour = 12));
static assert(!__traits(compiles, itod.hour = 12));
}
/++
Minutes passed the hour.
+/
@property ubyte minute() const pure nothrow
{
return _minute;
}
unittest
{
assertPred!"=="(TimeOfDay.init.minute, 0);
assertPred!"=="(TimeOfDay(0, 30, 0).minute, 30);
const ctod = TimeOfDay(0, 30, 0);
immutable itod = TimeOfDay(0, 30, 0);
static assert(__traits(compiles, ctod.minute == 30));
static assert(__traits(compiles, itod.minute == 30));
}
/++
Minutes passed the hour.
Params:
minute = The minute to set this TimeOfDay's minute to.
Throws:
DateTimeException if the given minute would result in an invalid TimeOfDay.
+/
@property void minute(int minute) pure
{
enforceValid!"minutes"(minute);
_minute = cast(ubyte)minute;
}
unittest
{
assertThrown!DateTimeException((){TimeOfDay(0, 0, 0).minute = 60;}());
auto tod = TimeOfDay(0, 0, 0);
tod.minute = 30;
assertPred!"=="(tod, TimeOfDay(0, 30, 0));
const ctod = TimeOfDay(0, 0, 0);
immutable itod = TimeOfDay(0, 0, 0);
static assert(!__traits(compiles, ctod.minute = 30));
static assert(!__traits(compiles, itod.minute = 30));
}
/++
Seconds passed the minute.
+/
@property ubyte second() const pure nothrow
{
return _second;
}
unittest
{
assertPred!"=="(TimeOfDay.init.second, 0);
assertPred!"=="(TimeOfDay(0, 0, 33).second, 33);
const ctod = TimeOfDay(0, 0, 33);
immutable itod = TimeOfDay(0, 0, 33);
static assert(__traits(compiles, ctod.second == 33));
static assert(__traits(compiles, itod.second == 33));
}
/++
Seconds passed the minute.
Params:
second = The second to set this TimeOfDay's second to.
Throws:
DateTimeException if the given second would result in an invalid TimeOfDay.
+/
@property void second(int second) pure
{
enforceValid!"seconds"(second);
_second = cast(ubyte)second;
}
unittest
{
assertThrown!DateTimeException((){TimeOfDay(0, 0, 0).second = 60;}());
auto tod = TimeOfDay(0, 0, 0);
tod.second = 33;
assertPred!"=="(tod, TimeOfDay(0, 0, 33));
const ctod = TimeOfDay(0, 0, 0);
immutable itod = TimeOfDay(0, 0, 0);
static assert(!__traits(compiles, ctod.second = 33));
static assert(!__traits(compiles, itod.second = 33));
}
/++
Adds the given number of hours to this TimeOfDay. A negative number will
subtract.
For hours, because they are the largest unit in TimeOfDay, there is no
difference between adding or rolling.
Note that TimeOfDay has no $(D add!()) function because you can add to a
TimeOfDay by adding a duration to it.
Params:
hours = The number of hours to add to this TimeOfDay.
Examples:
--------------------
auto tod1 = TimeOfDay(7, 12, 0);
tod1.roll!"hours"(1);
assert(tod1 == TimeOfDay(8, 12, 0));
auto tod2 = TimeOfDay(7, 12, 0);
tod2.roll!"hours"(-1);
assert(tod2 == TimeOfDay(6, 12, 0));
auto tod3 = TimeOfDay(23, 0, 0);
tod3.roll!"hours"(1);
assert(tod3 == TimeOfDay(0, 0, 0));
auto tod4 = TimeOfDay(0, 0, 0);
tod4.roll!"hours"(-1);
assert(tod4 == TimeOfDay(23, 0, 0));
--------------------
+/
/+ref TimeOfDay+/ void roll(string units)(long hours) pure nothrow
if(units == "hours")
{
this += dur!"hours"(hours);
}
unittest
{
const ctod = TimeOfDay(0, 0, 0);
immutable itod = TimeOfDay(0, 0, 0);
static assert(!__traits(compiles, ctod.roll!"hours"(53)));
static assert(!__traits(compiles, itod.roll!"hours"(53)));
//Verify Examples.
auto tod1 = TimeOfDay(7, 12, 0);
tod1.roll!"hours"(1);
assert(tod1 == TimeOfDay(8, 12, 0));
auto tod2 = TimeOfDay(7, 12, 0);
tod2.roll!"hours"(-1);
assert(tod2 == TimeOfDay(6, 12, 0));
auto tod3 = TimeOfDay(23, 0, 0);
tod3.roll!"hours"(1);
assert(tod3 == TimeOfDay(0, 0, 0));
auto tod4 = TimeOfDay(0, 0, 0);
tod4.roll!"hours"(-1);
assert(tod4 == TimeOfDay(23, 0, 0));
}
/++
Add minutes to the time of day. Negative values will subtract.
The difference between rolling and adding is that rolling does not affect
larger units. So, if you roll the TimeOfDay 60 minutes, you get the exact
same TimeOfDay.
Note that TimeOfDay has no $(D add!()) function because you can add to a
TimeOfDay by adding a duration to it.
Params:
minutes = The number of Minutes to add to this TimeOfDay.
Examples:
--------------------
auto tod1 = TimeOfDay(7, 12, 0);
tod1.roll!"minutes"(1);
assert(tod1 == TimeOfDay(7, 13, 0));
auto tod2 = TimeOfDay(7, 12, 0);
tod2.roll!"minutes"(-1);
assert(tod2 == TimeOfDay(7, 11, 0));
auto tod3 = TimeOfDay(23, 59, 0);
tod3.roll!"minutes"(1);
assert(tod3 == TimeOfDay(23, 0, 0));
auto tod4 = TimeOfDay(0, 0, 0);
tod4.roll!"minutes"(-1);
assert(tod4 == TimeOfDay(0, 59, 0));
auto tod5 = TimeOfDay(7, 32, 12);
tod5.roll!"seconds"(1);
assert(tod5 == TimeOfDay(7, 32, 13));
auto tod6 = TimeOfDay(7, 32, 12);
tod6.roll!"seconds"(-1);
assert(tod6 == TimeOfDay(7, 32, 11));
auto tod7 = TimeOfDay(23, 59, 59);
tod7.roll!"seconds"(1);
assert(tod7 == TimeOfDay(23, 59, 0));
auto tod8 = TimeOfDay(0, 0, 0);
tod8.roll!"seconds"(-1);
assert(tod8 == TimeOfDay(0, 0, 59));
--------------------
+/
/+ref TimeOfDay+/ void roll(string units)(long value) pure nothrow
if(units == "minutes" ||
units == "seconds")
{
static if(units == "minutes")
enum memberVarStr = "minute";
else static if(units == "seconds")
enum memberVarStr = "second";
else
static assert(0);
value %= 60;
mixin("auto newVal = cast(ubyte)(_" ~ memberVarStr ~ ") + value;");
if(value < 0)
{
if(newVal < 0)
newVal += 60;
}
else if(newVal >= 60)
newVal -= 60;
mixin("_" ~ memberVarStr ~ " = cast(ubyte)newVal;");
}
//Test roll!"minutes"().
unittest
{
static void testTOD(TimeOfDay orig, int minutes, in TimeOfDay expected, size_t line = __LINE__)
{
orig.roll!"minutes"(minutes);
assertPred!"=="(orig, expected, "", __FILE__, line);
}
testTOD(TimeOfDay(12, 30, 33), 0, TimeOfDay(12, 30, 33));
testTOD(TimeOfDay(12, 30, 33), 1, TimeOfDay(12, 31, 33));
testTOD(TimeOfDay(12, 30, 33), 2, TimeOfDay(12, 32, 33));
testTOD(TimeOfDay(12, 30, 33), 3, TimeOfDay(12, 33, 33));
testTOD(TimeOfDay(12, 30, 33), 4, TimeOfDay(12, 34, 33));
testTOD(TimeOfDay(12, 30, 33), 5, TimeOfDay(12, 35, 33));
testTOD(TimeOfDay(12, 30, 33), 10, TimeOfDay(12, 40, 33));
testTOD(TimeOfDay(12, 30, 33), 15, TimeOfDay(12, 45, 33));
testTOD(TimeOfDay(12, 30, 33), 29, TimeOfDay(12, 59, 33));
testTOD(TimeOfDay(12, 30, 33), 30, TimeOfDay(12, 0, 33));
testTOD(TimeOfDay(12, 30, 33), 45, TimeOfDay(12, 15, 33));
testTOD(TimeOfDay(12, 30, 33), 60, TimeOfDay(12, 30, 33));
testTOD(TimeOfDay(12, 30, 33), 75, TimeOfDay(12, 45, 33));
testTOD(TimeOfDay(12, 30, 33), 90, TimeOfDay(12, 0, 33));
testTOD(TimeOfDay(12, 30, 33), 100, TimeOfDay(12, 10, 33));
testTOD(TimeOfDay(12, 30, 33), 689, TimeOfDay(12, 59, 33));
testTOD(TimeOfDay(12, 30, 33), 690, TimeOfDay(12, 0, 33));
testTOD(TimeOfDay(12, 30, 33), 691, TimeOfDay(12, 1, 33));
testTOD(TimeOfDay(12, 30, 33), 960, TimeOfDay(12, 30, 33));
testTOD(TimeOfDay(12, 30, 33), 1439, TimeOfDay(12, 29, 33));
testTOD(TimeOfDay(12, 30, 33), 1440, TimeOfDay(12, 30, 33));
testTOD(TimeOfDay(12, 30, 33), 1441, TimeOfDay(12, 31, 33));
testTOD(TimeOfDay(12, 30, 33), 2880, TimeOfDay(12, 30, 33));
testTOD(TimeOfDay(12, 30, 33), -1, TimeOfDay(12, 29, 33));
testTOD(TimeOfDay(12, 30, 33), -2, TimeOfDay(12, 28, 33));
testTOD(TimeOfDay(12, 30, 33), -3, TimeOfDay(12, 27, 33));
testTOD(TimeOfDay(12, 30, 33), -4, TimeOfDay(12, 26, 33));
testTOD(TimeOfDay(12, 30, 33), -5, TimeOfDay(12, 25, 33));
testTOD(TimeOfDay(12, 30, 33), -10, TimeOfDay(12, 20, 33));
testTOD(TimeOfDay(12, 30, 33), -15, TimeOfDay(12, 15, 33));
testTOD(TimeOfDay(12, 30, 33), -29, TimeOfDay(12, 1, 33));
testTOD(TimeOfDay(12, 30, 33), -30, TimeOfDay(12, 0, 33));
testTOD(TimeOfDay(12, 30, 33), -45, TimeOfDay(12, 45, 33));
testTOD(TimeOfDay(12, 30, 33), -60, TimeOfDay(12, 30, 33));
testTOD(TimeOfDay(12, 30, 33), -75, TimeOfDay(12, 15, 33));
testTOD(TimeOfDay(12, 30, 33), -90, TimeOfDay(12, 0, 33));
testTOD(TimeOfDay(12, 30, 33), -100, TimeOfDay(12, 50, 33));
testTOD(TimeOfDay(12, 30, 33), -749, TimeOfDay(12, 1, 33));
testTOD(TimeOfDay(12, 30, 33), -750, TimeOfDay(12, 0, 33));
testTOD(TimeOfDay(12, 30, 33), -751, TimeOfDay(12, 59, 33));
testTOD(TimeOfDay(12, 30, 33), -960, TimeOfDay(12, 30, 33));
testTOD(TimeOfDay(12, 30, 33), -1439, TimeOfDay(12, 31, 33));
testTOD(TimeOfDay(12, 30, 33), -1440, TimeOfDay(12, 30, 33));
testTOD(TimeOfDay(12, 30, 33), -1441, TimeOfDay(12, 29, 33));
testTOD(TimeOfDay(12, 30, 33), -2880, TimeOfDay(12, 30, 33));
testTOD(TimeOfDay(12, 0, 33), 1, TimeOfDay(12, 1, 33));
testTOD(TimeOfDay(12, 0, 33), 0, TimeOfDay(12, 0, 33));
testTOD(TimeOfDay(12, 0, 33), -1, TimeOfDay(12, 59, 33));
testTOD(TimeOfDay(11, 59, 33), 1, TimeOfDay(11, 0, 33));
testTOD(TimeOfDay(11, 59, 33), 0, TimeOfDay(11, 59, 33));
testTOD(TimeOfDay(11, 59, 33), -1, TimeOfDay(11, 58, 33));
testTOD(TimeOfDay(0, 0, 33), 1, TimeOfDay(0, 1, 33));
testTOD(TimeOfDay(0, 0, 33), 0, TimeOfDay(0, 0, 33));
testTOD(TimeOfDay(0, 0, 33), -1, TimeOfDay(0, 59, 33));
testTOD(TimeOfDay(23, 59, 33), 1, TimeOfDay(23, 0, 33));
testTOD(TimeOfDay(23, 59, 33), 0, TimeOfDay(23, 59, 33));
testTOD(TimeOfDay(23, 59, 33), -1, TimeOfDay(23, 58, 33));
const ctod = TimeOfDay(0, 0, 0);
immutable itod = TimeOfDay(0, 0, 0);
static assert(!__traits(compiles, ctod.roll!"minutes"(7)));
static assert(!__traits(compiles, itod.roll!"minutes"(7)));
//Verify Examples.
auto tod1 = TimeOfDay(7, 12, 0);
tod1.roll!"minutes"(1);
assert(tod1 == TimeOfDay(7, 13, 0));
auto tod2 = TimeOfDay(7, 12, 0);
tod2.roll!"minutes"(-1);
assert(tod2 == TimeOfDay(7, 11, 0));
auto tod3 = TimeOfDay(23, 59, 0);
tod3.roll!"minutes"(1);
assert(tod3 == TimeOfDay(23, 0, 0));
auto tod4 = TimeOfDay(0, 0, 0);
tod4.roll!"minutes"(-1);
assert(tod4 == TimeOfDay(0, 59, 0));
auto tod5 = TimeOfDay(7, 32, 12);
tod5.roll!"seconds"(1);
assert(tod5 == TimeOfDay(7, 32, 13));
auto tod6 = TimeOfDay(7, 32, 12);
tod6.roll!"seconds"(-1);
assert(tod6 == TimeOfDay(7, 32, 11));
auto tod7 = TimeOfDay(23, 59, 59);
tod7.roll!"seconds"(1);
assert(tod7 == TimeOfDay(23, 59, 0));
auto tod8 = TimeOfDay(0, 0, 0);
tod8.roll!"seconds"(-1);
assert(tod8 == TimeOfDay(0, 0, 59));
}
//Test roll!"seconds"().
unittest
{
static void testTOD(TimeOfDay orig, int seconds, in TimeOfDay expected, size_t line = __LINE__)
{
orig.roll!"seconds"(seconds);
assertPred!"=="(orig, expected, "", __FILE__, line);
}
testTOD(TimeOfDay(12, 30, 33), 0, TimeOfDay(12, 30, 33));
testTOD(TimeOfDay(12, 30, 33), 1, TimeOfDay(12, 30, 34));
testTOD(TimeOfDay(12, 30, 33), 2, TimeOfDay(12, 30, 35));
testTOD(TimeOfDay(12, 30, 33), 3, TimeOfDay(12, 30, 36));
testTOD(TimeOfDay(12, 30, 33), 4, TimeOfDay(12, 30, 37));
testTOD(TimeOfDay(12, 30, 33), 5, TimeOfDay(12, 30, 38));
testTOD(TimeOfDay(12, 30, 33), 10, TimeOfDay(12, 30, 43));
testTOD(TimeOfDay(12, 30, 33), 15, TimeOfDay(12, 30, 48));
testTOD(TimeOfDay(12, 30, 33), 26, TimeOfDay(12, 30, 59));
testTOD(TimeOfDay(12, 30, 33), 27, TimeOfDay(12, 30, 0));
testTOD(TimeOfDay(12, 30, 33), 30, TimeOfDay(12, 30, 3));
testTOD(TimeOfDay(12, 30, 33), 59, TimeOfDay(12, 30, 32));
testTOD(TimeOfDay(12, 30, 33), 60, TimeOfDay(12, 30, 33));
testTOD(TimeOfDay(12, 30, 33), 61, TimeOfDay(12, 30, 34));
testTOD(TimeOfDay(12, 30, 33), 1766, TimeOfDay(12, 30, 59));
testTOD(TimeOfDay(12, 30, 33), 1767, TimeOfDay(12, 30, 0));
testTOD(TimeOfDay(12, 30, 33), 1768, TimeOfDay(12, 30, 1));
testTOD(TimeOfDay(12, 30, 33), 2007, TimeOfDay(12, 30, 0));
testTOD(TimeOfDay(12, 30, 33), 3599, TimeOfDay(12, 30, 32));
testTOD(TimeOfDay(12, 30, 33), 3600, TimeOfDay(12, 30, 33));
testTOD(TimeOfDay(12, 30, 33), 3601, TimeOfDay(12, 30, 34));
testTOD(TimeOfDay(12, 30, 33), 7200, TimeOfDay(12, 30, 33));
testTOD(TimeOfDay(12, 30, 33), -1, TimeOfDay(12, 30, 32));
testTOD(TimeOfDay(12, 30, 33), -2, TimeOfDay(12, 30, 31));
testTOD(TimeOfDay(12, 30, 33), -3, TimeOfDay(12, 30, 30));
testTOD(TimeOfDay(12, 30, 33), -4, TimeOfDay(12, 30, 29));
testTOD(TimeOfDay(12, 30, 33), -5, TimeOfDay(12, 30, 28));
testTOD(TimeOfDay(12, 30, 33), -10, TimeOfDay(12, 30, 23));
testTOD(TimeOfDay(12, 30, 33), -15, TimeOfDay(12, 30, 18));
testTOD(TimeOfDay(12, 30, 33), -33, TimeOfDay(12, 30, 0));
testTOD(TimeOfDay(12, 30, 33), -34, TimeOfDay(12, 30, 59));
testTOD(TimeOfDay(12, 30, 33), -35, TimeOfDay(12, 30, 58));
testTOD(TimeOfDay(12, 30, 33), -59, TimeOfDay(12, 30, 34));
testTOD(TimeOfDay(12, 30, 33), -60, TimeOfDay(12, 30, 33));
testTOD(TimeOfDay(12, 30, 33), -61, TimeOfDay(12, 30, 32));
testTOD(TimeOfDay(12, 30, 0), 1, TimeOfDay(12, 30, 1));
testTOD(TimeOfDay(12, 30, 0), 0, TimeOfDay(12, 30, 0));
testTOD(TimeOfDay(12, 30, 0), -1, TimeOfDay(12, 30, 59));
testTOD(TimeOfDay(12, 0, 0), 1, TimeOfDay(12, 0, 1));
testTOD(TimeOfDay(12, 0, 0), 0, TimeOfDay(12, 0, 0));
testTOD(TimeOfDay(12, 0, 0), -1, TimeOfDay(12, 0, 59));
testTOD(TimeOfDay(0, 0, 0), 1, TimeOfDay(0, 0, 1));
testTOD(TimeOfDay(0, 0, 0), 0, TimeOfDay(0, 0, 0));
testTOD(TimeOfDay(0, 0, 0), -1, TimeOfDay(0, 0, 59));
testTOD(TimeOfDay(23, 59, 59), 1, TimeOfDay(23, 59, 0));
testTOD(TimeOfDay(23, 59, 59), 0, TimeOfDay(23, 59, 59));
testTOD(TimeOfDay(23, 59, 59), -1, TimeOfDay(23, 59, 58));
const ctod = TimeOfDay(0, 0, 0);
immutable itod = TimeOfDay(0, 0, 0);
static assert(!__traits(compiles, ctod.roll!"seconds"(7)));
static assert(!__traits(compiles, itod.roll!"seconds"(7)));
}
/++
Gives the result of adding or subtracting a duration from this TimeOfDay.
The legal types of arithmetic for TimeOfDay using this operator are
$(TABLE
$(TR $(TD TimeOfDay) $(TD +) $(TD duration) $(TD -->) $(TD TimeOfDay))
$(TR $(TD TimeOfDay) $(TD -) $(TD duration) $(TD -->) $(TD TimeOfDay))
)
Params:
duration = The duration to add to or subtract from this Date.
+/
TimeOfDay opBinary(string op, D)(in D duration) const pure nothrow
if((op == "+" || op == "-") &&
(is(Unqual!D == Duration) ||
is(Unqual!D == TickDuration)))
{
TimeOfDay retval = this;
static if(is(Unqual!D == Duration))
immutable hnsecs = duration.total!"hnsecs";
else static if(is(Unqual!D == TickDuration))
immutable hnsecs = duration.hnsecs;
//Ideally, this would just be
//return retval.addSeconds(convert!("hnsecs", "seconds")(unaryFun!(op ~ "a")(hnsecs)));
//But there isn't currently a pure version of unaryFun!().
static if(op == "+")
immutable signedHNSecs = hnsecs;
else static if(op == "-")
immutable signedHNSecs = -hnsecs;
else
static assert(0);
return retval.addSeconds(convert!("hnsecs", "seconds")(signedHNSecs));
}
unittest
{
auto tod = TimeOfDay(12, 30, 33);
assertPred!"=="(tod + dur!"hours"(7), TimeOfDay(19, 30, 33));
assertPred!"=="(tod + dur!"hours"(-7), TimeOfDay(5, 30, 33));
assertPred!"=="(tod + dur!"minutes"(7), TimeOfDay(12, 37, 33));
assertPred!"=="(tod + dur!"minutes"(-7), TimeOfDay(12, 23, 33));
assertPred!"=="(tod + dur!"seconds"(7), TimeOfDay(12, 30, 40));
assertPred!"=="(tod + dur!"seconds"(-7), TimeOfDay(12, 30, 26));
assertPred!"=="(tod + dur!"msecs"(7000), TimeOfDay(12, 30, 40));
assertPred!"=="(tod + dur!"msecs"(-7000), TimeOfDay(12, 30, 26));
assertPred!"=="(tod + dur!"usecs"(7_000_000), TimeOfDay(12, 30, 40));
assertPred!"=="(tod + dur!"usecs"(-7_000_000), TimeOfDay(12, 30, 26));
assertPred!"=="(tod + dur!"hnsecs"(70_000_000), TimeOfDay(12, 30, 40));
assertPred!"=="(tod + dur!"hnsecs"(-70_000_000), TimeOfDay(12, 30, 26));
//This probably only runs in cases where gettimeofday() is used, but it's
//hard to do this test correctly with variable ticksPerSec.
if(TickDuration.ticksPerSec == 1_000_000)
{
assertPred!"=="(tod + TickDuration.from!"usecs"(7_000_000), TimeOfDay(12, 30, 40));
assertPred!"=="(tod + TickDuration.from!"usecs"(-7_000_000), TimeOfDay(12, 30, 26));
}
assertPred!"=="(tod - dur!"hours"(-7), TimeOfDay(19, 30, 33));
assertPred!"=="(tod - dur!"hours"(7), TimeOfDay(5, 30, 33));
assertPred!"=="(tod - dur!"minutes"(-7), TimeOfDay(12, 37, 33));
assertPred!"=="(tod - dur!"minutes"(7), TimeOfDay(12, 23, 33));
assertPred!"=="(tod - dur!"seconds"(-7), TimeOfDay(12, 30, 40));
assertPred!"=="(tod - dur!"seconds"(7), TimeOfDay(12, 30, 26));
assertPred!"=="(tod - dur!"msecs"(-7000), TimeOfDay(12, 30, 40));
assertPred!"=="(tod - dur!"msecs"(7000), TimeOfDay(12, 30, 26));
assertPred!"=="(tod - dur!"usecs"(-7_000_000), TimeOfDay(12, 30, 40));
assertPred!"=="(tod - dur!"usecs"(7_000_000), TimeOfDay(12, 30, 26));
assertPred!"=="(tod - dur!"hnsecs"(-70_000_000), TimeOfDay(12, 30, 40));
assertPred!"=="(tod - dur!"hnsecs"(70_000_000), TimeOfDay(12, 30, 26));
//This probably only runs in cases where gettimeofday() is used, but it's
//hard to do this test correctly with variable ticksPerSec.
if(TickDuration.ticksPerSec == 1_000_000)
{
assertPred!"=="(tod - TickDuration.from!"usecs"(-7_000_000), TimeOfDay(12, 30, 40));
assertPred!"=="(tod - TickDuration.from!"usecs"(7_000_000), TimeOfDay(12, 30, 26));
}
auto duration = dur!"hours"(11);
const ctod = TimeOfDay(12, 33, 30);
immutable itod = TimeOfDay(12, 33, 30);
static assert(__traits(compiles, tod + duration));
static assert(__traits(compiles, ctod + duration));
static assert(__traits(compiles, itod + duration));
static assert(__traits(compiles, tod - duration));
static assert(__traits(compiles, ctod - duration));
static assert(__traits(compiles, itod - duration));
}
/++
Gives the result of adding or subtracting a duration from this TimeOfDay,
as well as assigning the result to this TimeOfDay.
The legal types of arithmetic for TimeOfDay using this operator are
$(TABLE
$(TR $(TD TimeOfDay) $(TD +) $(TD duration) $(TD -->) $(TD TimeOfDay))
$(TR $(TD TimeOfDay) $(TD -) $(TD duration) $(TD -->) $(TD TimeOfDay))
)
Params:
duration = The duration to add to or subtract from this TimeOfDay.
+/
/+ref+/ TimeOfDay opOpAssign(string op, D)(in D duration) pure nothrow
if((op == "+" || op == "-") &&
(is(Unqual!D == Duration) ||
is(Unqual!D == TickDuration)))
{
static if(is(Unqual!D == Duration))
immutable hnsecs = duration.total!"hnsecs";
else static if(is(Unqual!D == TickDuration))
immutable hnsecs = duration.hnsecs;
//Ideally, this would just be
//return addSeconds(convert!("hnsecs", "seconds")(unaryFun!(op ~ "a")(hnsecs)));
//But there isn't currently a pure version of unaryFun!().
static if(op == "+")
immutable signedHNSecs = hnsecs;
else static if(op == "-")
immutable signedHNSecs = -hnsecs;
else
static assert(0);
return addSeconds(convert!("hnsecs", "seconds")(signedHNSecs));
}
unittest
{
auto duration = dur!"hours"(12);
assertPred!"+="(TimeOfDay(12, 30, 33), dur!"hours"(7), TimeOfDay(19, 30, 33));
assertPred!"+="(TimeOfDay(12, 30, 33), dur!"hours"(-7), TimeOfDay(5, 30, 33));
assertPred!"+="(TimeOfDay(12, 30, 33), dur!"minutes"(7), TimeOfDay(12, 37, 33));
assertPred!"+="(TimeOfDay(12, 30, 33), dur!"minutes"(-7), TimeOfDay(12, 23, 33));
assertPred!"+="(TimeOfDay(12, 30, 33), dur!"seconds"(7), TimeOfDay(12, 30, 40));
assertPred!"+="(TimeOfDay(12, 30, 33), dur!"seconds"(-7), TimeOfDay(12, 30, 26));
assertPred!"+="(TimeOfDay(12, 30, 33), dur!"msecs"(7000), TimeOfDay(12, 30, 40));
assertPred!"+="(TimeOfDay(12, 30, 33), dur!"msecs"(-7000), TimeOfDay(12, 30, 26));
assertPred!"+="(TimeOfDay(12, 30, 33), dur!"usecs"(7_000_000), TimeOfDay(12, 30, 40));
assertPred!"+="(TimeOfDay(12, 30, 33), dur!"usecs"(-7_000_000), TimeOfDay(12, 30, 26));
assertPred!"+="(TimeOfDay(12, 30, 33), dur!"hnsecs"(70_000_000), TimeOfDay(12, 30, 40));
assertPred!"+="(TimeOfDay(12, 30, 33), dur!"hnsecs"(-70_000_000), TimeOfDay(12, 30, 26));
assertPred!"-="(TimeOfDay(12, 30, 33), dur!"hours"(-7), TimeOfDay(19, 30, 33));
assertPred!"-="(TimeOfDay(12, 30, 33), dur!"hours"(7), TimeOfDay(5, 30, 33));
assertPred!"-="(TimeOfDay(12, 30, 33), dur!"minutes"(-7), TimeOfDay(12, 37, 33));
assertPred!"-="(TimeOfDay(12, 30, 33), dur!"minutes"(7), TimeOfDay(12, 23, 33));
assertPred!"-="(TimeOfDay(12, 30, 33), dur!"seconds"(-7), TimeOfDay(12, 30, 40));
assertPred!"-="(TimeOfDay(12, 30, 33), dur!"seconds"(7), TimeOfDay(12, 30, 26));
assertPred!"-="(TimeOfDay(12, 30, 33), dur!"msecs"(-7000), TimeOfDay(12, 30, 40));
assertPred!"-="(TimeOfDay(12, 30, 33), dur!"msecs"(7000), TimeOfDay(12, 30, 26));
assertPred!"-="(TimeOfDay(12, 30, 33), dur!"usecs"(-7_000_000), TimeOfDay(12, 30, 40));
assertPred!"-="(TimeOfDay(12, 30, 33), dur!"usecs"(7_000_000), TimeOfDay(12, 30, 26));
assertPred!"-="(TimeOfDay(12, 30, 33), dur!"hnsecs"(-70_000_000), TimeOfDay(12, 30, 40));
assertPred!"-="(TimeOfDay(12, 30, 33), dur!"hnsecs"(70_000_000), TimeOfDay(12, 30, 26));
const ctod = TimeOfDay(12, 33, 30);
immutable itod = TimeOfDay(12, 33, 30);
static assert(!__traits(compiles, ctod += duration));
static assert(!__traits(compiles, itod += duration));
static assert(!__traits(compiles, ctod -= duration));
static assert(!__traits(compiles, itod -= duration));
}
/++
Gives the difference between two TimeOfDays.
The legal types of arithmetic for TimeOfDay using this operator are
$(TABLE
$(TR $(TD TimeOfDay) $(TD -) $(TD TimeOfDay) $(TD -->) $(TD duration))
)
Params:
rhs = The TimeOfDay to subtract from this one.
+/
Duration opBinary(string op)(in TimeOfDay rhs) const pure nothrow
if(op == "-")
{
immutable lhsSec = _hour * 3600 + _minute * 60 + _second;
immutable rhsSec = rhs._hour * 3600 + rhs._minute * 60 + rhs._second;
return dur!"seconds"(lhsSec - rhsSec);
}
unittest
{
auto tod = TimeOfDay(12, 30, 33);
assertPred!"=="(TimeOfDay(7, 12, 52) - TimeOfDay(12, 30, 33), dur!"seconds"(-19_061));
assertPred!"=="(TimeOfDay(12, 30, 33) - TimeOfDay(7, 12, 52), dur!"seconds"(19_061));
assertPred!"=="(TimeOfDay(12, 30, 33) - TimeOfDay(14, 30, 33), dur!"seconds"(-7200));
assertPred!"=="(TimeOfDay(14, 30, 33) - TimeOfDay(12, 30, 33), dur!"seconds"(7200));
assertPred!"=="(TimeOfDay(12, 30, 33) - TimeOfDay(12, 34, 33), dur!"seconds"(-240));
assertPred!"=="(TimeOfDay(12, 34, 33) - TimeOfDay(12, 30, 33), dur!"seconds"(240));
assertPred!"=="(TimeOfDay(12, 30, 33) - TimeOfDay(12, 30, 34), dur!"seconds"(-1));
assertPred!"=="(TimeOfDay(12, 30, 34) - TimeOfDay(12, 30, 33), dur!"seconds"(1));
const ctod = TimeOfDay(12, 30, 33);
immutable itod = TimeOfDay(12, 30, 33);
static assert(__traits(compiles, tod - tod));
static assert(__traits(compiles, ctod - tod));
static assert(__traits(compiles, itod - tod));
static assert(__traits(compiles, tod - ctod));
static assert(__traits(compiles, ctod - ctod));
static assert(__traits(compiles, itod - ctod));
static assert(__traits(compiles, tod - itod));
static assert(__traits(compiles, ctod - itod));
static assert(__traits(compiles, itod - itod));
}
/++
Converts this TimeOfDay to a string with the format HHMMSS.
Examples:
--------------------
assert(TimeOfDay(0, 0, 0).toISOString() == "000000");
assert(TimeOfDay(12, 30, 33).toISOString() == "123033");
--------------------
+/
string toISOString() const nothrow
{
try
return format("%02d%02d%02d", _hour, _minute, _second);
catch(Exception e)
assert(0, "format() threw.");
}
unittest
{
auto tod = TimeOfDay(12, 30, 33);
const ctod = TimeOfDay(12, 30, 33);
immutable itod = TimeOfDay(12, 30, 33);
static assert(__traits(compiles, tod.toISOString()));
static assert(__traits(compiles, ctod.toISOString()));
static assert(__traits(compiles, itod.toISOString()));
//Verify Examples.
assert(TimeOfDay(0, 0, 0).toISOString() == "000000");
assert(TimeOfDay(12, 30, 33).toISOString() == "123033");
}
/++
Converts this TimeOfDay to a string with the format HH:MM:SS.
Examples:
--------------------
assert(TimeOfDay(0, 0, 0).toISOExtendedString() == "000000");
assert(TimeOfDay(12, 30, 33).toISOExtendedString() == "123033");
--------------------
+/
string toISOExtendedString() const nothrow
{
try
return format("%02d:%02d:%02d", _hour, _minute, _second);
catch(Exception e)
assert(0, "format() threw.");
}
unittest
{
auto tod = TimeOfDay(12, 30, 33);
const ctod = TimeOfDay(12, 30, 33);
immutable itod = TimeOfDay(12, 30, 33);
static assert(__traits(compiles, tod.toISOExtendedString()));
static assert(__traits(compiles, ctod.toISOExtendedString()));
static assert(__traits(compiles, itod.toISOExtendedString()));
//Verify Examples.
assert(TimeOfDay(0, 0, 0).toISOExtendedString() == "00:00:00");
assert(TimeOfDay(12, 30, 33).toISOExtendedString() == "12:30:33");
}
/+
Converts this TimeOfDay to a string.
+/
//Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
//have versions of toString() with extra modifiers, so we define one version
//with modifiers and one without.
string toString()
{
return toISOExtendedString();
}
/++
Converts this TimeOfDay to a string.
+/
//Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
//have versions of toString() with extra modifiers, so we define one version
//with modifiers and one without.
string toString() const nothrow
{
return toISOExtendedString();
}
unittest
{
auto tod = TimeOfDay(12, 30, 33);
const ctod = TimeOfDay(12, 30, 33);
immutable itod = TimeOfDay(12, 30, 33);
static assert(__traits(compiles, tod.toString()));
static assert(__traits(compiles, ctod.toString()));
static assert(__traits(compiles, itod.toString()));
}
//TODO Add a function which returns a string in a user-specified format.
/++
Creates a TimeOfDay from a string with the format HHMMSS. Whitespace is
stripped from the given string.
Params:
isoString = A string formatted in the ISO format for times.
Throws:
DateTimeException if the given string is not in the ISO format or if
the resulting TimeOfDay would not be valid.
Examples:
--------------------
assert(TimeOfDay.fromISOString("000000") == TimeOfDay(0, 0, 0));
assert(TimeOfDay.fromISOString("123033") == TimeOfDay(12, 30, 33));
assert(TimeOfDay.fromISOString(" 123033 ") == TimeOfDay(12, 30, 33));
--------------------
+/
static TimeOfDay fromISOString(S)(in S isoString)
if(isSomeString!S)
{
auto dstr = to!dstring(strip(isoString));
enforce(dstr.length == 6, new DateTimeException(format("Invalid ISO String: %s", isoString)));
auto hours = dstr[0 .. 2];
auto minutes = dstr[2 .. 4];
auto seconds = dstr[4 .. $];
enforce(!canFind!((dchar c){return !isdigit(c);})(hours), new DateTimeException(format("Invalid ISO String: %s", isoString)));
enforce(!canFind!((dchar c){return !isdigit(c);})(minutes), new DateTimeException(format("Invalid ISO String: %s", isoString)));
enforce(!canFind!((dchar c){return !isdigit(c);})(seconds), new DateTimeException(format("Invalid ISO String: %s", isoString)));
return TimeOfDay(to!int(hours), to!int(minutes), to!int(seconds));
}
unittest
{
assertThrown!DateTimeException(TimeOfDay.fromISOString(""));
assertThrown!DateTimeException(TimeOfDay.fromISOString("0"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("00"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("000"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("0000"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("00000"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("13033"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("1277"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("12707"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("12070"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("12303a"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("1230a3"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("123a33"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("12a033"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("1a0033"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("a20033"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("1200330"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("0120033"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("-120033"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("+120033"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("120033am"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("120033pm"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("0::"));
assertThrown!DateTimeException(TimeOfDay.fromISOString(":0:"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("::0"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("0:0:0"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("0:0:00"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("0:00:0"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("00:0:0"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("00:00:0"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("00:0:00"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("13:0:33"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("12:7:7"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("12:7:07"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("12:07:0"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("12:30:3a"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("12:30:a3"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("12:3a:33"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("12:a0:33"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("1a:00:33"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("a2:00:33"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("12:003:30"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("120:03:30"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("012:00:33"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("01:200:33"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("-12:00:33"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("+12:00:33"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("12:00:33am"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("12:00:33pm"));
assertThrown!DateTimeException(TimeOfDay.fromISOString("12:00:33"));
assertPred!"=="(TimeOfDay.fromISOString("011217"), TimeOfDay(1, 12, 17));
assertPred!"=="(TimeOfDay.fromISOString("001412"), TimeOfDay(0, 14, 12));
assertPred!"=="(TimeOfDay.fromISOString("000007"), TimeOfDay(0, 0, 7));
assertPred!"=="(TimeOfDay.fromISOString("011217 "), TimeOfDay(1, 12, 17));
assertPred!"=="(TimeOfDay.fromISOString(" 011217"), TimeOfDay(1, 12, 17));
assertPred!"=="(TimeOfDay.fromISOString(" 011217 "), TimeOfDay(1, 12, 17));
//Verify Examples.
assert(TimeOfDay.fromISOString("000000") == TimeOfDay(0, 0, 0));
assert(TimeOfDay.fromISOString("123033") == TimeOfDay(12, 30, 33));
assert(TimeOfDay.fromISOString(" 123033 ") == TimeOfDay(12, 30, 33));
}
/++
Creates a TimeOfDay from a string with the format HH:MM:SS. Whitespace is
stripped from the given string.
Params:
isoString = A string formatted in the ISO Extended format for times.
Throws:
DateTimeException if the given string is not in the ISO Extended
format or if the resulting TimeOfDay would not be valid.
Examples:
--------------------
assert(TimeOfDay.fromISOExtendedString("00:00:00") == TimeOfDay(0, 0, 0));
assert(TimeOfDay.fromISOExtendedString("12:30:33") == TimeOfDay(12, 30, 33));
assert(TimeOfDay.fromISOExtendedString(" 12:30:33 ") == TimeOfDay(12, 30, 33));
--------------------
+/
static TimeOfDay fromISOExtendedString(S)(in S isoExtString)
if(isSomeString!S)
{
auto dstr = to!dstring(strip(isoExtString));
enforce(dstr.length == 8, new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
auto hours = dstr[0 .. 2];
auto minutes = dstr[3 .. 5];
auto seconds = dstr[6 .. $];
enforce(dstr[2] == ':', new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
enforce(dstr[5] == ':', new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
enforce(!canFind!((dchar c){return !isdigit(c);})(hours), new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
enforce(!canFind!((dchar c){return !isdigit(c);})(minutes), new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
enforce(!canFind!((dchar c){return !isdigit(c);})(seconds), new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
return TimeOfDay(to!int(hours), to!int(minutes), to!int(seconds));
}
unittest
{
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString(""));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("0"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("00"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("000"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("0000"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("00000"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("13033"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("1277"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("12707"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("12070"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("12303a"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("1230a3"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("123a33"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("12a033"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("1a0033"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("a20033"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("1200330"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("0120033"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("-120033"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("+120033"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("120033am"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("120033pm"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("0::"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString(":0:"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("::0"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("0:0:0"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("0:0:00"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("0:00:0"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("00:0:0"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("00:00:0"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("00:0:00"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("13:0:33"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("12:7:7"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("12:7:07"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("12:07:0"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("12:30:3a"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("12:30:a3"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("12:3a:33"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("12:a0:33"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("1a:00:33"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("a2:00:33"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("12:003:30"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("120:03:30"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("012:00:33"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("01:200:33"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("-12:00:33"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("+12:00:33"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("12:00:33am"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("12:00:33pm"));
assertThrown!DateTimeException(TimeOfDay.fromISOExtendedString("120033"));
assertPred!"=="(TimeOfDay.fromISOExtendedString("01:12:17"), TimeOfDay(1, 12, 17));
assertPred!"=="(TimeOfDay.fromISOExtendedString("00:14:12"), TimeOfDay(0, 14, 12));
assertPred!"=="(TimeOfDay.fromISOExtendedString("00:00:07"), TimeOfDay(0, 0, 7));
assertPred!"=="(TimeOfDay.fromISOExtendedString("01:12:17 "), TimeOfDay(1, 12, 17));
assertPred!"=="(TimeOfDay.fromISOExtendedString(" 01:12:17"), TimeOfDay(1, 12, 17));
assertPred!"=="(TimeOfDay.fromISOExtendedString(" 01:12:17 "), TimeOfDay(1, 12, 17));
//Verify Examples.
assert(TimeOfDay.fromISOExtendedString("00:00:00") == TimeOfDay(0, 0, 0));
assert(TimeOfDay.fromISOExtendedString("12:30:33") == TimeOfDay(12, 30, 33));
assert(TimeOfDay.fromISOExtendedString(" 12:30:33 ") == TimeOfDay(12, 30, 33));
}
//TODO Add function which takes a user-specified time format and produces a TimeOfDay
//TODO Add function which takes pretty much any time-string and produces a TimeOfDay
// Obviously, it will be less efficient, and it probably won't manage _every_
// possible date format, but a smart conversion function would be nice.
/++
Returns midnight.
+/
@property static TimeOfDay min() pure nothrow
{
return TimeOfDay.init;
}
unittest
{
assert(TimeOfDay.min.hour == 0);
assert(TimeOfDay.min.minute == 0);
assert(TimeOfDay.min.second == 0);
assert(TimeOfDay.min < TimeOfDay.max);
}
/++
Returns one second short of midnight.
+/
@property static TimeOfDay max() pure nothrow
{
auto tod = TimeOfDay.init;
tod._hour = maxHour;
tod._minute = maxMinute;
tod._second = maxSecond;
return tod;
}
unittest
{
assert(TimeOfDay.max.hour == 23);
assert(TimeOfDay.max.minute == 59);
assert(TimeOfDay.max.second == 59);
assert(TimeOfDay.max > TimeOfDay.min);
}
private:
/++
Add seconds to the time of day. Negative values will subtract. If the
number of seconds overflows (or underflows), then the seconds will wrap,
increasing (or decreasing) the number of minutes accordingly. If the
number of minutes overflows (or underflows), then the minutes will wrap.
If the number of minutes overflows(or underflows), then the hour will
wrap. (e.g. adding 90 seconds to 23:59:00 would result in 00:00:30).
Params:
seconds = The number of seconds to add to this TimeOfDay.
+/
ref TimeOfDay addSeconds(long seconds) pure nothrow
{
long hnsecs = convert!("seconds", "hnsecs")(seconds);
hnsecs += convert!("hours", "hnsecs")(_hour);
hnsecs += convert!("minutes", "hnsecs")(_minute);
hnsecs += convert!("seconds", "hnsecs")(_second);
hnsecs %= convert!("days", "hnsecs")(1);
if(hnsecs < 0)
hnsecs += convert!("days", "hnsecs")(1);
immutable newHours = splitUnitsFromHNSecs!"hours"(hnsecs);
immutable newMinutes = splitUnitsFromHNSecs!"minutes"(hnsecs);
immutable newSeconds = splitUnitsFromHNSecs!"seconds"(hnsecs);
_hour = cast(ubyte)newHours;
_minute = cast(ubyte)newMinutes;
_second = cast(ubyte)newSeconds;
return this;
}
unittest
{
static void testTOD(TimeOfDay orig, int seconds, in TimeOfDay expected, size_t line = __LINE__)
{
orig.addSeconds(seconds);
assertPred!"=="(orig, expected, "", __FILE__, line);
}
testTOD(TimeOfDay(12, 30, 33), 0, TimeOfDay(12, 30, 33));
testTOD(TimeOfDay(12, 30, 33), 1, TimeOfDay(12, 30, 34));
testTOD(TimeOfDay(12, 30, 33), 2, TimeOfDay(12, 30, 35));
testTOD(TimeOfDay(12, 30, 33), 3, TimeOfDay(12, 30, 36));
testTOD(TimeOfDay(12, 30, 33), 4, TimeOfDay(12, 30, 37));
testTOD(TimeOfDay(12, 30, 33), 5, TimeOfDay(12, 30, 38));
testTOD(TimeOfDay(12, 30, 33), 10, TimeOfDay(12, 30, 43));
testTOD(TimeOfDay(12, 30, 33), 15, TimeOfDay(12, 30, 48));
testTOD(TimeOfDay(12, 30, 33), 26, TimeOfDay(12, 30, 59));
testTOD(TimeOfDay(12, 30, 33), 27, TimeOfDay(12, 31, 0));
testTOD(TimeOfDay(12, 30, 33), 30, TimeOfDay(12, 31, 3));
testTOD(TimeOfDay(12, 30, 33), 59, TimeOfDay(12, 31, 32));
testTOD(TimeOfDay(12, 30, 33), 60, TimeOfDay(12, 31, 33));
testTOD(TimeOfDay(12, 30, 33), 61, TimeOfDay(12, 31, 34));
testTOD(TimeOfDay(12, 30, 33), 1766, TimeOfDay(12, 59, 59));
testTOD(TimeOfDay(12, 30, 33), 1767, TimeOfDay(13, 0, 0));
testTOD(TimeOfDay(12, 30, 33), 1768, TimeOfDay(13, 0, 1));
testTOD(TimeOfDay(12, 30, 33), 2007, TimeOfDay(13, 4, 0));
testTOD(TimeOfDay(12, 30, 33), 3599, TimeOfDay(13, 30, 32));
testTOD(TimeOfDay(12, 30, 33), 3600, TimeOfDay(13, 30, 33));
testTOD(TimeOfDay(12, 30, 33), 3601, TimeOfDay(13, 30, 34));
testTOD(TimeOfDay(12, 30, 33), 7200, TimeOfDay(14, 30, 33));
testTOD(TimeOfDay(12, 30, 33), -1, TimeOfDay(12, 30, 32));
testTOD(TimeOfDay(12, 30, 33), -2, TimeOfDay(12, 30, 31));
testTOD(TimeOfDay(12, 30, 33), -3, TimeOfDay(12, 30, 30));
testTOD(TimeOfDay(12, 30, 33), -4, TimeOfDay(12, 30, 29));
testTOD(TimeOfDay(12, 30, 33), -5, TimeOfDay(12, 30, 28));
testTOD(TimeOfDay(12, 30, 33), -10, TimeOfDay(12, 30, 23));
testTOD(TimeOfDay(12, 30, 33), -15, TimeOfDay(12, 30, 18));
testTOD(TimeOfDay(12, 30, 33), -33, TimeOfDay(12, 30, 0));
testTOD(TimeOfDay(12, 30, 33), -34, TimeOfDay(12, 29, 59));
testTOD(TimeOfDay(12, 30, 33), -35, TimeOfDay(12, 29, 58));
testTOD(TimeOfDay(12, 30, 33), -59, TimeOfDay(12, 29, 34));
testTOD(TimeOfDay(12, 30, 33), -60, TimeOfDay(12, 29, 33));
testTOD(TimeOfDay(12, 30, 33), -61, TimeOfDay(12, 29, 32));
testTOD(TimeOfDay(12, 30, 33), -1833, TimeOfDay(12, 0, 0));
testTOD(TimeOfDay(12, 30, 33), -1834, TimeOfDay(11, 59, 59));
testTOD(TimeOfDay(12, 30, 33), -3600, TimeOfDay(11, 30, 33));
testTOD(TimeOfDay(12, 30, 33), -3601, TimeOfDay(11, 30, 32));
testTOD(TimeOfDay(12, 30, 33), -5134, TimeOfDay(11, 4, 59));
testTOD(TimeOfDay(12, 30, 33), -7200, TimeOfDay(10, 30, 33));
testTOD(TimeOfDay(12, 30, 0), 1, TimeOfDay(12, 30, 1));
testTOD(TimeOfDay(12, 30, 0), 0, TimeOfDay(12, 30, 0));
testTOD(TimeOfDay(12, 30, 0), -1, TimeOfDay(12, 29, 59));
testTOD(TimeOfDay(12, 0, 0), 1, TimeOfDay(12, 0, 1));
testTOD(TimeOfDay(12, 0, 0), 0, TimeOfDay(12, 0, 0));
testTOD(TimeOfDay(12, 0, 0), -1, TimeOfDay(11, 59, 59));
testTOD(TimeOfDay(0, 0, 0), 1, TimeOfDay(0, 0, 1));
testTOD(TimeOfDay(0, 0, 0), 0, TimeOfDay(0, 0, 0));
testTOD(TimeOfDay(0, 0, 0), -1, TimeOfDay(23, 59, 59));
testTOD(TimeOfDay(23, 59, 59), 1, TimeOfDay(0, 0, 0));
testTOD(TimeOfDay(23, 59, 59), 0, TimeOfDay(23, 59, 59));
testTOD(TimeOfDay(23, 59, 59), -1, TimeOfDay(23, 59, 58));
const ctod = TimeOfDay(0, 0, 0);
immutable itod = TimeOfDay(0, 0, 0);
static assert(!__traits(compiles, ctod.addSeconds(7)));
static assert(!__traits(compiles, itod.addSeconds(7)));
}
/++
Whether the given values form a valid TimeOfDay
+/
static bool _valid(int hour, int minute, int second) pure nothrow
{
return valid!"hours"(hour) && valid!"minutes"(minute) && valid!"seconds"(second);
}
pure invariant()
{
assert(_valid(_hour, _minute, _second),
"Invariant Failure: hour [" ~
numToString(_hour) ~
"] minute [" ~
numToString(_minute) ~
"] second [" ~
numToString(_second) ~
"]");
}
ubyte _hour;
ubyte _minute;
ubyte _second;
enum ubyte maxHour = 24 - 1;
enum ubyte maxMinute = 60 - 1;
enum ubyte maxSecond = 60 - 1;
}
/++
Combines Date and TimeOfDay structs to give you an object which holds both
the date and the time. It is optimized for calendar operations and has no
concept of time zone. If you want an object which is optimized for time
operations based on the system time, then use SysTime. SysTime has a concept
of time zone and has much higher precision (hnsecs). DateTime is intended
primarily for calendar-based uses rather than precise time operations.
+/
struct DateTime
{
public:
/++
Params:
date = The date portion of DateTime.
tod = The time portion of DateTime.
+/
this(in Date date, in TimeOfDay tod = TimeOfDay.init) pure nothrow
{
_date = date;
_tod = tod;
}
unittest
{
{
auto dt = DateTime.init;
assertPred!"=="(dt._date, Date.init);
assertPred!"=="(dt._tod, TimeOfDay.init);
}
{
auto dt = DateTime(Date(1999, 7 ,6));
assertPred!"=="(dt._date, Date(1999, 7, 6));
assertPred!"=="(dt._tod, TimeOfDay.init);
}
{
auto dt = DateTime(Date(1999, 7 ,6), TimeOfDay(12, 30, 33));
assertPred!"=="(dt._date, Date(1999, 7, 6));
assertPred!"=="(dt._tod, TimeOfDay(12, 30, 33));
}
}
/++
Params:
year = The year portion of the date.
month = The month portion of the date.
day = The day portion of the date.
hour = The hour portion of the time;
minute = The minute portion of the time;
second = The second portion of the time;
+/
this(int year, int month, int day,
int hour = 0, int minute = 0, int second = 0) pure
{
_date = Date(year, month, day);
_tod = TimeOfDay(hour, minute, second);
}
unittest
{
{
auto dt = DateTime(1999, 7 ,6);
assertPred!"=="(dt._date, Date(1999, 7, 6));
assertPred!"=="(dt._tod, TimeOfDay.init);
}
{
auto dt = DateTime(1999, 7 ,6, 12, 30, 33);
assertPred!"=="(dt._date, Date(1999, 7, 6));
assertPred!"=="(dt._tod, TimeOfDay(12, 30, 33));
}
}
/++
Compares this DateTime with the given DateTime.
Returns:
$(TABLE
$(TR $(TD this < rhs) $(TD < 0))
$(TR $(TD this == rhs) $(TD 0))
$(TR $(TD this > rhs) $(TD > 0))
)
+/
int opCmp(in DateTime rhs) const pure nothrow
{
immutable dateResult = _date.opCmp(rhs._date);
if(dateResult != 0)
return dateResult;
return _tod.opCmp(rhs._tod);
}
unittest
{
//Test A.D.
assertPred!("opCmp", "==")(DateTime(Date.init, TimeOfDay.init), DateTime.init);
assertPred!("opCmp", "==")(DateTime(Date(1999, 1, 1)), DateTime(Date(1999, 1, 1)));
assertPred!("opCmp", "==")(DateTime(Date(1, 7, 1)), DateTime(Date(1, 7, 1)));
assertPred!("opCmp", "==")(DateTime(Date(1, 1, 6)), DateTime(Date(1, 1, 6)));
assertPred!("opCmp", "==")(DateTime(Date(1999, 7, 1)), DateTime(Date(1999, 7, 1)));
assertPred!("opCmp", "==")(DateTime(Date(1999, 7, 6)), DateTime(Date(1999, 7, 6)));
assertPred!("opCmp", "==")(DateTime(Date(1, 7, 6)), DateTime(Date(1, 7, 6)));
assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6)), DateTime(Date(2000, 7, 6)));
assertPred!("opCmp", ">")(DateTime(Date(2000, 7, 6)), DateTime(Date(1999, 7, 6)));
assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6)), DateTime(Date(1999, 8, 6)));
assertPred!("opCmp", ">")(DateTime(Date(1999, 8, 6)), DateTime(Date(1999, 7, 6)));
assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6)), DateTime(Date(1999, 7, 7)));
assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 7)), DateTime(Date(1999, 7, 6)));
assertPred!("opCmp", "<")(DateTime(Date(1999, 8, 7)), DateTime(Date(2000, 7, 6)));
assertPred!("opCmp", ">")(DateTime(Date(2000, 8, 6)), DateTime(Date(1999, 7, 7)));
assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 7)), DateTime(Date(2000, 7, 6)));
assertPred!("opCmp", ">")(DateTime(Date(2000, 7, 6)), DateTime(Date(1999, 7, 7)));
assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 7)), DateTime(Date(1999, 8, 6)));
assertPred!("opCmp", ">")(DateTime(Date(1999, 8, 6)), DateTime(Date(1999, 7, 7)));
assertPred!("opCmp", "==")(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)),
DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)));
assertPred!("opCmp", "==")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 0)),
DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 0)));
assertPred!("opCmp", "==")(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 0)),
DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 0)));
assertPred!("opCmp", "==")(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33)));
assertPred!("opCmp", "==")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0)),
DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0)));
assertPred!("opCmp", "==")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", "==")(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33)));
assertPred!("opCmp", "==")(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33)));
assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)));
assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)));
assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)));
assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)),
DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)));
assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)),
DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)));
assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)));
assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)));
assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)));
assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)),
DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)));
assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)),
DateTime(Date(2000, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", ">")(DateTime(Date(2000, 7, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)));
assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)),
DateTime(Date(2000, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", ">")(DateTime(Date(2000, 7, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)));
assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)),
DateTime(Date(2000, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", ">")(DateTime(Date(2000, 7, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)));
assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)),
DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", ">")(DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)));
assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)),
DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", ">")(DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)));
assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)),
DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", ">")(DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)));
assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)),
DateTime(Date(1999, 7, 7), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 7), TimeOfDay(12, 30, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)));
assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)),
DateTime(Date(1999, 7, 7), TimeOfDay(12, 31, 33)));
assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 7), TimeOfDay(12, 30, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", "<")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)),
DateTime(Date(1999, 7, 7), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 7), TimeOfDay(12, 30, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)));
//Test B.C.
assertPred!("opCmp", "==")(DateTime(Date(-1, 1, 1), TimeOfDay(12, 30, 33)),
DateTime(Date(-1, 1, 1), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", "==")(DateTime(Date(-1, 7, 1), TimeOfDay(12, 30, 33)),
DateTime(Date(-1, 7, 1), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", "==")(DateTime(Date(-1, 1, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(-1, 1, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", "==")(DateTime(Date(-1999, 7, 1), TimeOfDay(12, 30, 33)),
DateTime(Date(-1999, 7, 1), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", "==")(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", "==")(DateTime(Date(-1, 7, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(-1, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", "<")(DateTime(Date(-2000, 7, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", ">")(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(-2000, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", "<")(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", ">")(DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", "<")(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", ">")(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33)),
DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", "<")(DateTime(Date(-2000, 8, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", ">")(DateTime(Date(-1999, 8, 7), TimeOfDay(12, 30, 33)),
DateTime(Date(-2000, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", "<")(DateTime(Date(-2000, 7, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", ">")(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33)),
DateTime(Date(-2000, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", "<")(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33)),
DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", ">")(DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33)));
//Test Both
assertPred!("opCmp", "<")(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", "<")(DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", "<")(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", "<")(DateTime(Date(-1999, 8, 7), TimeOfDay(12, 30, 33)),
DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", ">")(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(-1999, 8, 7), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", "<")(DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33)),
DateTime(Date(1999, 6, 6), TimeOfDay(12, 30, 33)));
assertPred!("opCmp", ">")(DateTime(Date(1999, 6, 8), TimeOfDay(12, 30, 33)),
DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
auto dt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 33, 30));
const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 33, 30));
immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 33, 30));
static assert(__traits(compiles, dt.opCmp(dt)));
static assert(__traits(compiles, dt.opCmp(cdt)));
static assert(__traits(compiles, dt.opCmp(idt)));
static assert(__traits(compiles, cdt.opCmp(dt)));
static assert(__traits(compiles, cdt.opCmp(cdt)));
static assert(__traits(compiles, cdt.opCmp(idt)));
static assert(__traits(compiles, idt.opCmp(dt)));
static assert(__traits(compiles, idt.opCmp(cdt)));
static assert(__traits(compiles, idt.opCmp(idt)));
}
/++
The date portion of DateTime.
+/
@property Date date() const pure nothrow
{
return _date;
}
unittest
{
{
auto dt = DateTime.init;
assertPred!"=="(dt.date, Date.init);
}
{
auto dt = DateTime(Date(1999, 7, 6));
assertPred!"=="(dt.date, Date(1999, 7, 6));
}
const cdt = DateTime(1999, 7, 6);
immutable idt = DateTime(1999, 7, 6);
static assert(__traits(compiles, cdt.date == Date(2010, 1, 1)));
static assert(__traits(compiles, idt.date == Date(2010, 1, 1)));
}
/++
The date portion of DateTime.
Params:
date = The Date to set this DateTime's date portion to.
+/
@property void date(in Date date) pure nothrow
{
_date = date;
}
unittest
{
auto dt = DateTime.init;
dt.date = Date(1999, 7, 6);
assertPred!"=="(dt._date, Date(1999, 7, 6));
assertPred!"=="(dt._tod, TimeOfDay.init);
const cdt = DateTime(1999, 7, 6);
immutable idt = DateTime(1999, 7, 6);
static assert(!__traits(compiles, cdt.date = Date(2010, 1, 1)));
static assert(!__traits(compiles, idt.date = Date(2010, 1, 1)));
}
/++
The time portion of DateTime.
+/
@property TimeOfDay timeOfDay() const pure nothrow
{
return _tod;
}
unittest
{
{
auto dt = DateTime.init;
assertPred!"=="(dt.timeOfDay, TimeOfDay.init);
}
{
auto dt = DateTime(Date.init, TimeOfDay(12, 30, 33));
assertPred!"=="(dt.timeOfDay, TimeOfDay(12, 30, 33));
}
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(__traits(compiles, cdt.timeOfDay == TimeOfDay(12, 30, 33)));
static assert(__traits(compiles, idt.timeOfDay == TimeOfDay(12, 30, 33)));
}
/++
The time portion of DateTime.
Params:
tod = The TimeOfDay to set this DateTime's time portion to.
+/
@property void timeOfDay(in TimeOfDay tod) pure nothrow
{
_tod = tod;
}
unittest
{
auto dt = DateTime.init;
dt.timeOfDay = TimeOfDay(12, 30, 33);
assertPred!"=="(dt._date, date.init);
assertPred!"=="(dt._tod, TimeOfDay(12, 30, 33));
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(!__traits(compiles, cdt.timeOfDay = TimeOfDay(12, 30, 33)));
static assert(!__traits(compiles, idt.timeOfDay = TimeOfDay(12, 30, 33)));
}
/++
Year of the Gregorian Calendar. Positive numbers are A.D. Non-positive
are B.C.
+/
@property short year() const pure nothrow
{
return _date.year;
}
unittest
{
assertPred!"=="(Date.init.year, 1);
assertPred!"=="(Date(1999, 7, 6).year, 1999);
assertPred!"=="(Date(-1999, 7, 6).year, -1999);
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(__traits(compiles, idt.year));
static assert(__traits(compiles, idt.year));
}
/++
Year of the Gregorian Calendar. Positive numbers are A.D. Non-positive
are B.C.
Params:
year = The year to set this DateTime's year to.
Throws:
DateTimeException if the new year is not a leap year and if the
resulting date would be on February 29th.
Examples:
--------------------
assert(DateTime(Date(1999, 7, 6), TimeOfDay(9, 7, 5)).year == 1999);
assert(DateTime(Date(2010, 10, 4), TimeOfDay(0, 0, 30)).year == 2010);
assert(DateTime(Date(-7, 4, 5), TimeOfDay(7, 45, 2)).year == -7);
--------------------
+/
@property void year(int year) pure
{
_date.year = year;
}
unittest
{
static void testDT(DateTime dt, int year, in DateTime expected, size_t line = __LINE__)
{
dt.year = year;
assertPred!"=="(dt, expected, "", __FILE__, line);
}
testDT(DateTime(Date(1, 1, 1), TimeOfDay(12, 30, 33)), 1999, DateTime(Date(1999, 1, 1), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(1, 1, 1), TimeOfDay(12, 30, 33)), 0, DateTime(Date(0, 1, 1), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(1, 1, 1), TimeOfDay(12, 30, 33)), -1999, DateTime(Date(-1999, 1, 1), TimeOfDay(12, 30, 33)));
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(!__traits(compiles, cdt.year = 7));
static assert(!__traits(compiles, idt.year = 7));
//Verify Examples.
assert(DateTime(Date(1999, 7, 6), TimeOfDay(9, 7, 5)).year == 1999);
assert(DateTime(Date(2010, 10, 4), TimeOfDay(0, 0, 30)).year == 2010);
assert(DateTime(Date(-7, 4, 5), TimeOfDay(7, 45, 2)).year == -7);
}
/++
Year B.C. of the Gregorian Calendar counting year 0 as 1 B.C.
Throws:
DateTimeException if $(D isAD) is true.
Examples:
--------------------
assert(DateTime(Date(0, 1, 1), TimeOfDay(12, 30, 33)).yearBC == 1);
assert(DateTime(Date(-1, 1, 1), TimeOfDay(10, 7, 2)).yearBC == 2);
assert(DateTime(Date(-100, 1, 1), TimeOfDay(4, 59, 0)).yearBC == 101);
--------------------
+/
@property short yearBC() const pure
{
return _date.yearBC;
}
unittest
{
assertThrown!DateTimeException((in DateTime dt){dt.yearBC;}(DateTime(Date(1, 1, 1))));
auto dt = DateTime(1999, 7, 6, 12, 30, 33);
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(__traits(compiles, dt.yearBC = 12));
static assert(!__traits(compiles, cdt.yearBC = 12));
static assert(!__traits(compiles, idt.yearBC = 12));
//Verify Examples.
assert(DateTime(Date(0, 1, 1), TimeOfDay(12, 30, 33)).yearBC == 1);
assert(DateTime(Date(-1, 1, 1), TimeOfDay(10, 7, 2)).yearBC == 2);
assert(DateTime(Date(-100, 1, 1), TimeOfDay(4, 59, 0)).yearBC == 101);
}
/++
Year B.C. of the Gregorian Calendar counting year 0 as 1 B.C.
Params:
year = The year B.C. to set this DateTime's year to.
Throws:
DateTimeException if a non-positive value is given.
Examples:
--------------------
auto dt = DateTime(Date(2010, 1, 1), TimeOfDay(7, 30, 0));
dt.yearBC = 1;
assert(dt == DateTime(Date(0, 1, 1), TimeOfDay(7, 30, 0)));
dt.yearBC = 10;
assert(dt == DateTime(Date(-9, 1, 1), TimeOfDay(7, 30, 0)));
--------------------
+/
@property void yearBC(int year) pure
{
_date.yearBC = year;
}
unittest
{
assertThrown!DateTimeException((DateTime dt){dt.yearBC = -1;}(DateTime(Date(1, 1, 1))));
{
auto dt = DateTime(1999, 7, 6, 12, 30, 33);
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(__traits(compiles, dt.yearBC = 12));
static assert(!__traits(compiles, cdt.yearBC = 12));
static assert(!__traits(compiles, idt.yearBC = 12));
}
//Verify Examples.
{
auto dt = DateTime(Date(2010, 1, 1), TimeOfDay(7, 30, 0));
dt.yearBC = 1;
assert(dt == DateTime(Date(0, 1, 1), TimeOfDay(7, 30, 0)));
dt.yearBC = 10;
assert(dt == DateTime(Date(-9, 1, 1), TimeOfDay(7, 30, 0)));
}
}
/++
Month of a Gregorian Year.
Examples:
--------------------
assert(DateTime(Date(1999, 7, 6), TimeOfDay(9, 7, 5)).month == 7);
assert(DateTime(Date(2010, 10, 4), TimeOfDay(0, 0, 30)).month == 10);
assert(DateTime(Date(-7, 4, 5), TimeOfDay(7, 45, 2)).month == 4);
--------------------
+/
@property Month month() const pure nothrow
{
return _date.month;
}
unittest
{
assertPred!"=="(DateTime.init.month, 1);
assertPred!"=="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)).month, 7);
assertPred!"=="(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)).month, 7);
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(__traits(compiles, cdt.month));
static assert(__traits(compiles, idt.month));
//Verify Examples.
assert(DateTime(Date(1999, 7, 6), TimeOfDay(9, 7, 5)).month == 7);
assert(DateTime(Date(2010, 10, 4), TimeOfDay(0, 0, 30)).month == 10);
assert(DateTime(Date(-7, 4, 5), TimeOfDay(7, 45, 2)).month == 4);
}
/++
Month of a Gregorian Year.
Params:
month = The month to set this DateTime's month to.
Throws:
DateTimeException if the given month is not a valid month.
+/
@property void month(Month month) pure
{
_date.month = month;
}
unittest
{
static void testDT(DateTime dt, Month month, in DateTime expected = DateTime.init, size_t line = __LINE__)
{
dt.month = month;
assert(expected != DateTime.init);
assertPred!"=="(dt, expected, "", __FILE__, line);
}
assertThrown!DateTimeException(testDT(DateTime(Date(1, 1, 1), TimeOfDay(12, 30, 33)), cast(Month)0));
assertThrown!DateTimeException(testDT(DateTime(Date(1, 1, 1), TimeOfDay(12, 30, 33)), cast(Month)13));
testDT(DateTime(Date(1, 1, 1), TimeOfDay(12, 30, 33)), cast(Month)7, DateTime(Date(1, 7, 1), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(-1, 1, 1), TimeOfDay(12, 30, 33)), cast(Month)7, DateTime(Date(-1, 7, 1), TimeOfDay(12, 30, 33)));
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(!__traits(compiles, cdt.month = 12));
static assert(!__traits(compiles, idt.month = 12));
}
/++
Day of a Gregorian Month.
Examples:
--------------------
assert(DateTime(Date(1999, 7, 6), TimeOfDay(9, 7, 5)).day == 6);
assert(DateTime(Date(2010, 10, 4), TimeOfDay(0, 0, 30)).day == 4);
assert(DateTime(Date(-7, 4, 5), TimeOfDay(7, 45, 2)).day == 5);
--------------------
+/
@property ubyte day() const pure nothrow
{
return _date.day;
}
unittest
{
assertPred!"=="(DateTime.init.day, 1);
assertPred!"=="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)).day, 6);
assertPred!"=="(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)).day, 6);
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(__traits(compiles, cdt.day));
static assert(__traits(compiles, idt.day));
//Verify Examples.
assert(DateTime(Date(1999, 7, 6), TimeOfDay(9, 7, 5)).day == 6);
assert(DateTime(Date(2010, 10, 4), TimeOfDay(0, 0, 30)).day == 4);
assert(DateTime(Date(-7, 4, 5), TimeOfDay(7, 45, 2)).day == 5);
}
/++
Day of a Gregorian Month.
Params:
day = The day of the month to set this DateTime's day to.
Throws:
DateTimeException if the given day is not a valid day of the current month.
+/
@property void day(int day) pure
{
_date.day = day;
}
unittest
{
static void testDT(DateTime dt, int day)
{
dt.day = day;
}
//Test A.D.
assertThrown!DateTimeException(testDT(DateTime(Date(1, 1, 1)), 0));
assertThrown!DateTimeException(testDT(DateTime(Date(1, 1, 1)), 32));
assertThrown!DateTimeException(testDT(DateTime(Date(1, 2, 1)), 29));
assertThrown!DateTimeException(testDT(DateTime(Date(4, 2, 1)), 30));
assertThrown!DateTimeException(testDT(DateTime(Date(1, 3, 1)), 32));
assertThrown!DateTimeException(testDT(DateTime(Date(1, 4, 1)), 31));
assertThrown!DateTimeException(testDT(DateTime(Date(1, 5, 1)), 32));
assertThrown!DateTimeException(testDT(DateTime(Date(1, 6, 1)), 31));
assertThrown!DateTimeException(testDT(DateTime(Date(1, 7, 1)), 32));
assertThrown!DateTimeException(testDT(DateTime(Date(1, 8, 1)), 32));
assertThrown!DateTimeException(testDT(DateTime(Date(1, 9, 1)), 31));
assertThrown!DateTimeException(testDT(DateTime(Date(1, 10, 1)), 32));
assertThrown!DateTimeException(testDT(DateTime(Date(1, 11, 1)), 31));
assertThrown!DateTimeException(testDT(DateTime(Date(1, 12, 1)), 32));
assertNotThrown!DateTimeException(testDT(DateTime(Date(1, 1, 1)), 31));
assertNotThrown!DateTimeException(testDT(DateTime(Date(1, 2, 1)), 28));
assertNotThrown!DateTimeException(testDT(DateTime(Date(4, 2, 1)), 29));
assertNotThrown!DateTimeException(testDT(DateTime(Date(1, 3, 1)), 31));
assertNotThrown!DateTimeException(testDT(DateTime(Date(1, 4, 1)), 30));
assertNotThrown!DateTimeException(testDT(DateTime(Date(1, 5, 1)), 31));
assertNotThrown!DateTimeException(testDT(DateTime(Date(1, 6, 1)), 30));
assertNotThrown!DateTimeException(testDT(DateTime(Date(1, 7, 1)), 31));
assertNotThrown!DateTimeException(testDT(DateTime(Date(1, 8, 1)), 31));
assertNotThrown!DateTimeException(testDT(DateTime(Date(1, 9, 1)), 30));
assertNotThrown!DateTimeException(testDT(DateTime(Date(1, 10, 1)), 31));
assertNotThrown!DateTimeException(testDT(DateTime(Date(1, 11, 1)), 30));
assertNotThrown!DateTimeException(testDT(DateTime(Date(1, 12, 1)), 31));
{
auto dt = DateTime(Date(1, 1, 1), TimeOfDay(7, 12, 22));
dt.day = 6;
assertPred!"=="(dt, DateTime(Date(1, 1, 6), TimeOfDay(7, 12, 22)));
}
//Test B.C.
assertThrown!DateTimeException(testDT(DateTime(Date(-1, 1, 1)), 0));
assertThrown!DateTimeException(testDT(DateTime(Date(-1, 1, 1)), 32));
assertThrown!DateTimeException(testDT(DateTime(Date(-1, 2, 1)), 29));
assertThrown!DateTimeException(testDT(DateTime(Date(0, 2, 1)), 30));
assertThrown!DateTimeException(testDT(DateTime(Date(-1, 3, 1)), 32));
assertThrown!DateTimeException(testDT(DateTime(Date(-1, 4, 1)), 31));
assertThrown!DateTimeException(testDT(DateTime(Date(-1, 5, 1)), 32));
assertThrown!DateTimeException(testDT(DateTime(Date(-1, 6, 1)), 31));
assertThrown!DateTimeException(testDT(DateTime(Date(-1, 7, 1)), 32));
assertThrown!DateTimeException(testDT(DateTime(Date(-1, 8, 1)), 32));
assertThrown!DateTimeException(testDT(DateTime(Date(-1, 9, 1)), 31));
assertThrown!DateTimeException(testDT(DateTime(Date(-1, 10, 1)), 32));
assertThrown!DateTimeException(testDT(DateTime(Date(-1, 11, 1)), 31));
assertThrown!DateTimeException(testDT(DateTime(Date(-1, 12, 1)), 32));
assertNotThrown!DateTimeException(testDT(DateTime(Date(-1, 1, 1)), 31));
assertNotThrown!DateTimeException(testDT(DateTime(Date(-1, 2, 1)), 28));
assertNotThrown!DateTimeException(testDT(DateTime(Date(0, 2, 1)), 29));
assertNotThrown!DateTimeException(testDT(DateTime(Date(-1, 3, 1)), 31));
assertNotThrown!DateTimeException(testDT(DateTime(Date(-1, 4, 1)), 30));
assertNotThrown!DateTimeException(testDT(DateTime(Date(-1, 5, 1)), 31));
assertNotThrown!DateTimeException(testDT(DateTime(Date(-1, 6, 1)), 30));
assertNotThrown!DateTimeException(testDT(DateTime(Date(-1, 7, 1)), 31));
assertNotThrown!DateTimeException(testDT(DateTime(Date(-1, 8, 1)), 31));
assertNotThrown!DateTimeException(testDT(DateTime(Date(-1, 9, 1)), 30));
assertNotThrown!DateTimeException(testDT(DateTime(Date(-1, 10, 1)), 31));
assertNotThrown!DateTimeException(testDT(DateTime(Date(-1, 11, 1)), 30));
assertNotThrown!DateTimeException(testDT(DateTime(Date(-1, 12, 1)), 31));
auto dt = DateTime(Date(-1, 1, 1), TimeOfDay(7, 12, 22));
dt.day = 6;
assertPred!"=="(dt, DateTime(Date(-1, 1, 6), TimeOfDay(7, 12, 22)));
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(!__traits(compiles, cdt.day = 27));
static assert(!__traits(compiles, idt.day = 27));
}
/++
Hours passed midnight.
+/
@property ubyte hour() const pure nothrow
{
return _tod.hour;
}
unittest
{
assertPred!"=="(DateTime.init.hour, 0);
assertPred!"=="(DateTime(Date.init, TimeOfDay(12, 0, 0)).hour, 12);
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(__traits(compiles, cdt.hour));
static assert(__traits(compiles, idt.hour));
}
/++
Hours passed midnight.
Params:
hour = The hour of the day to set this DateTime's hour to.
Throws:
DateTimeException if the given hour would result in an invalid
DateTime.
+/
@property void hour(int hour) pure
{
_tod.hour = hour;
}
unittest
{
assertThrown!DateTimeException((){DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)).hour = 24;}());
auto dt = DateTime.init;
dt.hour = 12;
assertPred!"=="(dt, DateTime(1, 1, 1, 12, 0, 0));
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(!__traits(compiles, cdt.hour = 27));
static assert(!__traits(compiles, idt.hour = 27));
}
/++
Minutes passed the hour.
+/
@property ubyte minute() const pure nothrow
{
return _tod.minute;
}
unittest
{
assertPred!"=="(DateTime.init.minute, 0);
assertPred!"=="(DateTime(1, 1, 1, 0, 30, 0).minute, 30);
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(__traits(compiles, cdt.minute));
static assert(__traits(compiles, idt.minute));
}
/++
Minutes passed the hour.
Params:
minute = The minute to set this DateTime's minute to.
Throws:
DateTimeException if the given minute would result in an invalid
DateTime.
+/
@property void minute(int minute) pure
{
_tod.minute = minute;
}
unittest
{
assertThrown!DateTimeException((){DateTime.init.minute = 60;}());
auto dt = DateTime.init;
dt.minute = 30;
assertPred!"=="(dt, DateTime(1, 1, 1, 0, 30, 0));
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(!__traits(compiles, cdt.minute = 27));
static assert(!__traits(compiles, idt.minute = 27));
}
/++
Seconds passed the minute.
+/
@property ubyte second() const pure nothrow
{
return _tod.second;
}
unittest
{
assertPred!"=="(DateTime.init.second, 0);
assertPred!"=="(DateTime(1, 1, 1, 0, 0, 33).second, 33);
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(__traits(compiles, cdt.second));
static assert(__traits(compiles, idt.second));
}
/++
Seconds passed the minute.
Params
second = The second to set this DateTime's second to.
Throws:
DateTimeException if the given seconds would result in an invalid
DateTime.
+/
@property void second(int second) pure
{
_tod.second = second;
}
unittest
{
assertThrown!DateTimeException((){DateTime.init.second = 60;}());
auto dt = DateTime.init;
dt.second = 33;
assertPred!"=="(dt, DateTime(1, 1, 1, 0, 0, 33));
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(!__traits(compiles, cdt.second = 27));
static assert(!__traits(compiles, idt.second = 27));
}
/++
Adds the given number of years or months to this DateTime. 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 days 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 DateTime.
allowOverflow = Whether the days should be allowed to overflow, causing
the month to increment.
Examples:
--------------------
auto dt1 = DateTime(Date(2010, 1, 1), TimeOfDay(12, 30, 33));
dt1.add!"months"(11);
assert(dt1 == DateTime(Date(2010, 12, 1), TimeOfDay(12, 30, 33)));
auto dt2 = DateTime(Date(2010, 1, 1), TimeOfDay(12, 30, 33));
dt2.add!"months"(-11);
assert(dt2 == DateTime(Date(2009, 2, 1), TimeOfDay(12, 30, 33)));
auto dt3 = DateTime(Date(2000, 2, 29), TimeOfDay(12, 30, 33));
dt3.add!"years"(1);
assert(dt3 == DateTime(Date(2001, 3, 1), TimeOfDay(12, 30, 33)));
auto dt4 = DateTime(Date(2000, 2, 29), TimeOfDay(12, 30, 33));
dt4.add!"years"(1, AllowDayOverflow.no);
assert(dt4 == DateTime(Date(2001, 2, 28), TimeOfDay(12, 30, 33)));
--------------------
+/
/+ref DateTime+/ void add(string units)(long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) pure nothrow
if(units == "years" ||
units == "months")
{
_date.add!units(value, allowOverflow);
}
unittest
{
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(!__traits(compiles, cdt.add!"years"(4)));
static assert(!__traits(compiles, idt.add!"years"(4)));
static assert(!__traits(compiles, cdt.add!"months"(4)));
static assert(!__traits(compiles, idt.add!"months"(4)));
//Verify Examples.
auto dt1 = DateTime(Date(2010, 1, 1), TimeOfDay(12, 30, 33));
dt1.add!"months"(11);
assert(dt1 == DateTime(Date(2010, 12, 1), TimeOfDay(12, 30, 33)));
auto dt2 = DateTime(Date(2010, 1, 1), TimeOfDay(12, 30, 33));
dt2.add!"months"(-11);
assert(dt2 == DateTime(Date(2009, 2, 1), TimeOfDay(12, 30, 33)));
auto dt3 = DateTime(Date(2000, 2, 29), TimeOfDay(12, 30, 33));
dt3.add!"years"(1);
assert(dt3 == DateTime(Date(2001, 3, 1), TimeOfDay(12, 30, 33)));
auto dt4 = DateTime(Date(2000, 2, 29), TimeOfDay(12, 30, 33));
dt4.add!"years"(1, AllowDayOverflow.no);
assert(dt4 == DateTime(Date(2001, 2, 28), TimeOfDay(12, 30, 33)));
}
/++
Adds the given number of years or months this DateTime. A negative
number will subtract.
The difference between rolling and adding is that rolling does not
affect larger units. So, if you roll the DateTime 12 months, you get
the exact same Date. However, the days can still be affected due to
the differing number of days in each month.
Params:
units = The units to roll.
value = The number of units to add to this DateTime.
allowOverflow = Whether the days should be allowed to overflow, causing the month to increment.
Examples:
--------------------
auto dt1 = DateTime(Date(2010, 1, 1), TimeOfDay(12, 33, 33));
dt1.roll!"years"(1);
assert(dt1 == DateTime(Date(2011, 1, 1), TimeOfDay(12, 33, 33)));
auto dt2 = DateTime(Date(2010, 1, 1), TimeOfDay(12, 33, 33));
dt2.roll!"months"(-12);
assert(dt2 == DateTime(Date(2010, 1, 1), TimeOfDay(12, 33, 33)));
auto dt3 = DateTime(Date(1999, 1, 29), TimeOfDay(12, 33, 33));
dt3.roll!"months"(1);
assert(dt3 == DateTime(Date(1999, 3, 1), TimeOfDay(12, 33, 33)));
auto dt4 = DateTime(Date(1999, 1, 29), TimeOfDay(12, 33, 33));
dt4.roll!"months"(1, AllowDayOverflow.no);
assert(dt4 == DateTime(Date(1999, 2, 28), TimeOfDay(12, 33, 33)));
--------------------
+/
/+ref DateTime+/ void roll(string units)(long value, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) pure nothrow
if(units == "years" ||
units == "months")
{
_date.roll!units(value, allowOverflow);
}
unittest
{
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(!__traits(compiles, cdt.roll!"years"(4)));
static assert(!__traits(compiles, idt.roll!"years"(4)));
static assert(!__traits(compiles, cdt.roll!"months"(4)));
static assert(!__traits(compiles, idt.roll!"months"(4)));
static assert(!__traits(compiles, cdt.roll!"days"(4)));
static assert(!__traits(compiles, idt.roll!"days"(4)));
//Verify Examples
auto dt1 = DateTime(Date(2010, 1, 1), TimeOfDay(12, 33, 33));
dt1.roll!"years"(1);
assert(dt1 == DateTime(Date(2011, 1, 1), TimeOfDay(12, 33, 33)));
auto dt2 = DateTime(Date(2010, 1, 1), TimeOfDay(12, 33, 33));
dt2.roll!"months"(-12);
assert(dt2 == DateTime(Date(2010, 1, 1), TimeOfDay(12, 33, 33)));
auto dt3 = DateTime(Date(1999, 1, 29), TimeOfDay(12, 33, 33));
dt3.roll!"months"(1);
assert(dt3 == DateTime(Date(1999, 3, 1), TimeOfDay(12, 33, 33)));
auto dt4 = DateTime(Date(1999, 1, 29), TimeOfDay(12, 33, 33));
dt4.roll!"months"(1, AllowDayOverflow.no);
assert(dt4 == DateTime(Date(1999, 2, 28), TimeOfDay(12, 33, 33)));
}
/++
Adds the given number of days this DateTime. A negative number will subtract.
The difference between rolling and adding is that rolling does not affect
larger units. So, if you roll the Date one year's worth of days, then you
get the exact same Date.
Note that there is no $(D add!"days"()) because you can add days to a DateTime
by adding a duration to it.
Params:
days = The number of days to add to this DateTime.
Examples:
--------------------
auto dt = DateTime(Date(2010, 1, 1), TimeOfDay(11, 23, 12));
dt.roll!"days"(1);
assert(dt == DateTime(Date(2010, 1, 2), TimeOfDay(11, 23, 12)));
dt.roll!"days"(365);
assert(dt == DateTime(Date(2010, 1, 26), TimeOfDay(11, 23, 12)));
dt.roll!"days"(-32);
assert(dt == DateTime(Date(2010, 1, 25), TimeOfDay(11, 23, 12)));
--------------------
+/
/+ref DateTime+/ void roll(string units)(long days) pure nothrow
if(units == "days")
{
_date.roll!"days"(days);
}
unittest
{
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(!__traits(compiles, cdt.roll!"days"(4)));
static assert(!__traits(compiles, idt.roll!"days"(4)));
//Verify Examples.
auto dt = DateTime(Date(2010, 1, 1), TimeOfDay(11, 23, 12));
dt.roll!"days"(1);
assert(dt == DateTime(Date(2010, 1, 2), TimeOfDay(11, 23, 12)));
dt.roll!"days"(365);
assert(dt == DateTime(Date(2010, 1, 26), TimeOfDay(11, 23, 12)));
dt.roll!"days"(-32);
assert(dt == DateTime(Date(2010, 1, 25), TimeOfDay(11, 23, 12)));
}
/++
Add the given number of the given units to the time of day. Negative
values will subtract.
The difference between rolling and adding is that rolling does not
affect larger units. So, if you roll the DateTime 24 hours, you get
the exact same DateTime.
Note that there is no $(D add!"hours"()), $(D add!"minutes"()), or
$(D add!"seconds"()) function because you can add them to a DateTime by
adding a duration to it.
Params:
units = The units to roll.
value = The number of units to add to this DateTime.
Examples:
--------------------
auto dt1 = DateTime(Date(2010, 7, 4), TimeOfDay(12, 0, 0));
dt1.roll!"hours"(1);
assert(dt1 == DateTime(Date(2010, 7, 4), TimeOfDay(13, 0, 0)));
auto dt2 = DateTime(Date(2010, 2, 12), TimeOfDay(12, 0, 0));
dt2.roll!"hours"(-1);
assert(dt2 == DateTime(Date(2010, 2, 12), TimeOfDay(11, 0, 0)));
auto dt3 = DateTime(Date(2009, 12, 31), TimeOfDay(23, 0, 0));
dt3.roll!"hours"(1);
assert(dt3 == DateTime(Date(2009, 12, 31), TimeOfDay(0, 0, 0)));
auto dt4 = DateTime(Date(2010, 1, 1), TimeOfDay(0, 0, 0));
dt4.roll!"hours"(-1);
assert(dt4 == DateTime(Date(2010, 1, 1), TimeOfDay(23, 0, 0)));
--------------------
+/
/+ref DateTime+/ void roll(string units)(long value) pure nothrow
if(units == "hours" ||
units == "minutes" ||
units == "seconds")
{
_tod.roll!units(value);
}
//Test roll!"hours"().
unittest
{
static void testDT(DateTime orig, int hours, in DateTime expected, size_t line = __LINE__)
{
orig.roll!"hours"(hours);
assertPred!"=="(orig, expected, "", __FILE__, line);
}
//Test A.D.
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 0, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 1, DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 2, DateTime(Date(1999, 7, 6), TimeOfDay(14, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 3, DateTime(Date(1999, 7, 6), TimeOfDay(15, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 4, DateTime(Date(1999, 7, 6), TimeOfDay(16, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 5, DateTime(Date(1999, 7, 6), TimeOfDay(17, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 6, DateTime(Date(1999, 7, 6), TimeOfDay(18, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 7, DateTime(Date(1999, 7, 6), TimeOfDay(19, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 8, DateTime(Date(1999, 7, 6), TimeOfDay(20, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 9, DateTime(Date(1999, 7, 6), TimeOfDay(21, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 10, DateTime(Date(1999, 7, 6), TimeOfDay(22, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 11, DateTime(Date(1999, 7, 6), TimeOfDay(23, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 12, DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 13, DateTime(Date(1999, 7, 6), TimeOfDay(1, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 14, DateTime(Date(1999, 7, 6), TimeOfDay(2, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 15, DateTime(Date(1999, 7, 6), TimeOfDay(3, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 16, DateTime(Date(1999, 7, 6), TimeOfDay(4, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 17, DateTime(Date(1999, 7, 6), TimeOfDay(5, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 18, DateTime(Date(1999, 7, 6), TimeOfDay(6, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 19, DateTime(Date(1999, 7, 6), TimeOfDay(7, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 20, DateTime(Date(1999, 7, 6), TimeOfDay(8, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 21, DateTime(Date(1999, 7, 6), TimeOfDay(9, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 22, DateTime(Date(1999, 7, 6), TimeOfDay(10, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 23, DateTime(Date(1999, 7, 6), TimeOfDay(11, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 24, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 25, DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -1, DateTime(Date(1999, 7, 6), TimeOfDay(11, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -2, DateTime(Date(1999, 7, 6), TimeOfDay(10, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -3, DateTime(Date(1999, 7, 6), TimeOfDay(9, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -4, DateTime(Date(1999, 7, 6), TimeOfDay(8, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -5, DateTime(Date(1999, 7, 6), TimeOfDay(7, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -6, DateTime(Date(1999, 7, 6), TimeOfDay(6, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -7, DateTime(Date(1999, 7, 6), TimeOfDay(5, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -8, DateTime(Date(1999, 7, 6), TimeOfDay(4, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -9, DateTime(Date(1999, 7, 6), TimeOfDay(3, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -10, DateTime(Date(1999, 7, 6), TimeOfDay(2, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -11, DateTime(Date(1999, 7, 6), TimeOfDay(1, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -12, DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -13, DateTime(Date(1999, 7, 6), TimeOfDay(23, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -14, DateTime(Date(1999, 7, 6), TimeOfDay(22, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -15, DateTime(Date(1999, 7, 6), TimeOfDay(21, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -16, DateTime(Date(1999, 7, 6), TimeOfDay(20, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -17, DateTime(Date(1999, 7, 6), TimeOfDay(19, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -18, DateTime(Date(1999, 7, 6), TimeOfDay(18, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -19, DateTime(Date(1999, 7, 6), TimeOfDay(17, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -20, DateTime(Date(1999, 7, 6), TimeOfDay(16, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -21, DateTime(Date(1999, 7, 6), TimeOfDay(15, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -22, DateTime(Date(1999, 7, 6), TimeOfDay(14, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -23, DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -24, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -25, DateTime(Date(1999, 7, 6), TimeOfDay(11, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33)), 1, DateTime(Date(1999, 7, 6), TimeOfDay(1, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33)), 0, DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33)), -1, DateTime(Date(1999, 7, 6), TimeOfDay(23, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(23, 30, 33)), 1, DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(23, 30, 33)), 0, DateTime(Date(1999, 7, 6), TimeOfDay(23, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(23, 30, 33)), -1, DateTime(Date(1999, 7, 6), TimeOfDay(22, 30, 33)));
testDT(DateTime(Date(1999, 7, 31), TimeOfDay(23, 30, 33)), 1, DateTime(Date(1999, 7, 31), TimeOfDay(0, 30, 33)));
testDT(DateTime(Date(1999, 8, 1), TimeOfDay(0, 30, 33)), -1, DateTime(Date(1999, 8, 1), TimeOfDay(23, 30, 33)));
testDT(DateTime(Date(1999, 12, 31), TimeOfDay(23, 30, 33)), 1, DateTime(Date(1999, 12, 31), TimeOfDay(0, 30, 33)));
testDT(DateTime(Date(2000, 1, 1), TimeOfDay(0, 30, 33)), -1, DateTime(Date(2000, 1, 1), TimeOfDay(23, 30, 33)));
testDT(DateTime(Date(1999, 2, 28), TimeOfDay(23, 30, 33)), 25, DateTime(Date(1999, 2, 28), TimeOfDay(0, 30, 33)));
testDT(DateTime(Date(1999, 3, 2), TimeOfDay(0, 30, 33)), -25, DateTime(Date(1999, 3, 2), TimeOfDay(23, 30, 33)));
testDT(DateTime(Date(2000, 2, 28), TimeOfDay(23, 30, 33)), 25, DateTime(Date(2000, 2, 28), TimeOfDay(0, 30, 33)));
testDT(DateTime(Date(2000, 3, 1), TimeOfDay(0, 30, 33)), -25, DateTime(Date(2000, 3, 1), TimeOfDay(23, 30, 33)));
//Test B.C.
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 0, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 1, DateTime(Date(-1999, 7, 6), TimeOfDay(13, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 2, DateTime(Date(-1999, 7, 6), TimeOfDay(14, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 3, DateTime(Date(-1999, 7, 6), TimeOfDay(15, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 4, DateTime(Date(-1999, 7, 6), TimeOfDay(16, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 5, DateTime(Date(-1999, 7, 6), TimeOfDay(17, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 6, DateTime(Date(-1999, 7, 6), TimeOfDay(18, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 7, DateTime(Date(-1999, 7, 6), TimeOfDay(19, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 8, DateTime(Date(-1999, 7, 6), TimeOfDay(20, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 9, DateTime(Date(-1999, 7, 6), TimeOfDay(21, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 10, DateTime(Date(-1999, 7, 6), TimeOfDay(22, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 11, DateTime(Date(-1999, 7, 6), TimeOfDay(23, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 12, DateTime(Date(-1999, 7, 6), TimeOfDay(0, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 13, DateTime(Date(-1999, 7, 6), TimeOfDay(1, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 14, DateTime(Date(-1999, 7, 6), TimeOfDay(2, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 15, DateTime(Date(-1999, 7, 6), TimeOfDay(3, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 16, DateTime(Date(-1999, 7, 6), TimeOfDay(4, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 17, DateTime(Date(-1999, 7, 6), TimeOfDay(5, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 18, DateTime(Date(-1999, 7, 6), TimeOfDay(6, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 19, DateTime(Date(-1999, 7, 6), TimeOfDay(7, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 20, DateTime(Date(-1999, 7, 6), TimeOfDay(8, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 21, DateTime(Date(-1999, 7, 6), TimeOfDay(9, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 22, DateTime(Date(-1999, 7, 6), TimeOfDay(10, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 23, DateTime(Date(-1999, 7, 6), TimeOfDay(11, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 24, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 25, DateTime(Date(-1999, 7, 6), TimeOfDay(13, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -1, DateTime(Date(-1999, 7, 6), TimeOfDay(11, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -2, DateTime(Date(-1999, 7, 6), TimeOfDay(10, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -3, DateTime(Date(-1999, 7, 6), TimeOfDay(9, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -4, DateTime(Date(-1999, 7, 6), TimeOfDay(8, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -5, DateTime(Date(-1999, 7, 6), TimeOfDay(7, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -6, DateTime(Date(-1999, 7, 6), TimeOfDay(6, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -7, DateTime(Date(-1999, 7, 6), TimeOfDay(5, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -8, DateTime(Date(-1999, 7, 6), TimeOfDay(4, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -9, DateTime(Date(-1999, 7, 6), TimeOfDay(3, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -10, DateTime(Date(-1999, 7, 6), TimeOfDay(2, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -11, DateTime(Date(-1999, 7, 6), TimeOfDay(1, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -12, DateTime(Date(-1999, 7, 6), TimeOfDay(0, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -13, DateTime(Date(-1999, 7, 6), TimeOfDay(23, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -14, DateTime(Date(-1999, 7, 6), TimeOfDay(22, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -15, DateTime(Date(-1999, 7, 6), TimeOfDay(21, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -16, DateTime(Date(-1999, 7, 6), TimeOfDay(20, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -17, DateTime(Date(-1999, 7, 6), TimeOfDay(19, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -18, DateTime(Date(-1999, 7, 6), TimeOfDay(18, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -19, DateTime(Date(-1999, 7, 6), TimeOfDay(17, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -20, DateTime(Date(-1999, 7, 6), TimeOfDay(16, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -21, DateTime(Date(-1999, 7, 6), TimeOfDay(15, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -22, DateTime(Date(-1999, 7, 6), TimeOfDay(14, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -23, DateTime(Date(-1999, 7, 6), TimeOfDay(13, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -24, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -25, DateTime(Date(-1999, 7, 6), TimeOfDay(11, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(0, 30, 33)), 1, DateTime(Date(-1999, 7, 6), TimeOfDay(1, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(0, 30, 33)), 0, DateTime(Date(-1999, 7, 6), TimeOfDay(0, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(0, 30, 33)), -1, DateTime(Date(-1999, 7, 6), TimeOfDay(23, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(23, 30, 33)), 1, DateTime(Date(-1999, 7, 6), TimeOfDay(0, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(23, 30, 33)), 0, DateTime(Date(-1999, 7, 6), TimeOfDay(23, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(23, 30, 33)), -1, DateTime(Date(-1999, 7, 6), TimeOfDay(22, 30, 33)));
testDT(DateTime(Date(-1999, 7, 31), TimeOfDay(23, 30, 33)), 1, DateTime(Date(-1999, 7, 31), TimeOfDay(0, 30, 33)));
testDT(DateTime(Date(-1999, 8, 1), TimeOfDay(0, 30, 33)), -1, DateTime(Date(-1999, 8, 1), TimeOfDay(23, 30, 33)));
testDT(DateTime(Date(-2001, 12, 31), TimeOfDay(23, 30, 33)), 1, DateTime(Date(-2001, 12, 31), TimeOfDay(0, 30, 33)));
testDT(DateTime(Date(-2000, 1, 1), TimeOfDay(0, 30, 33)), -1, DateTime(Date(-2000, 1, 1), TimeOfDay(23, 30, 33)));
testDT(DateTime(Date(-2001, 2, 28), TimeOfDay(23, 30, 33)), 25, DateTime(Date(-2001, 2, 28), TimeOfDay(0, 30, 33)));
testDT(DateTime(Date(-2001, 3, 2), TimeOfDay(0, 30, 33)), -25, DateTime(Date(-2001, 3, 2), TimeOfDay(23, 30, 33)));
testDT(DateTime(Date(-2000, 2, 28), TimeOfDay(23, 30, 33)), 25, DateTime(Date(-2000, 2, 28), TimeOfDay(0, 30, 33)));
testDT(DateTime(Date(-2000, 3, 1), TimeOfDay(0, 30, 33)), -25, DateTime(Date(-2000, 3, 1), TimeOfDay(23, 30, 33)));
//Test Both
testDT(DateTime(Date(-1, 1, 1), TimeOfDay(11, 30, 33)), 17_546, DateTime(Date(-1, 1, 1), TimeOfDay(13, 30, 33)));
testDT(DateTime(Date(1, 1, 1), TimeOfDay(13, 30, 33)), -17_546, DateTime(Date(1, 1, 1), TimeOfDay(11, 30, 33)));
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(!__traits(compiles, cdt.roll!"hours"(4)));
static assert(!__traits(compiles, idt.roll!"hours"(4)));
//Verify Examples.
auto dt1 = DateTime(Date(2010, 7, 4), TimeOfDay(12, 0, 0));
dt1.roll!"hours"(1);
assert(dt1 == DateTime(Date(2010, 7, 4), TimeOfDay(13, 0, 0)));
auto dt2 = DateTime(Date(2010, 2, 12), TimeOfDay(12, 0, 0));
dt2.roll!"hours"(-1);
assert(dt2 == DateTime(Date(2010, 2, 12), TimeOfDay(11, 0, 0)));
auto dt3 = DateTime(Date(2009, 12, 31), TimeOfDay(23, 0, 0));
dt3.roll!"hours"(1);
assert(dt3 == DateTime(Date(2009, 12, 31), TimeOfDay(0, 0, 0)));
auto dt4 = DateTime(Date(2010, 1, 1), TimeOfDay(0, 0, 0));
dt4.roll!"hours"(-1);
assert(dt4 == DateTime(Date(2010, 1, 1), TimeOfDay(23, 0, 0)));
}
//Test roll!"minutes"().
unittest
{
static void testDT(DateTime orig, int minutes, in DateTime expected, size_t line = __LINE__)
{
orig.roll!"minutes"(minutes);
assertPred!"=="(orig, expected, "", __FILE__, line);
}
//Test A.D.
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 0, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 1, DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 2, DateTime(Date(1999, 7, 6), TimeOfDay(12, 32, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 3, DateTime(Date(1999, 7, 6), TimeOfDay(12, 33, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 4, DateTime(Date(1999, 7, 6), TimeOfDay(12, 34, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 5, DateTime(Date(1999, 7, 6), TimeOfDay(12, 35, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 10, DateTime(Date(1999, 7, 6), TimeOfDay(12, 40, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 15, DateTime(Date(1999, 7, 6), TimeOfDay(12, 45, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 29, DateTime(Date(1999, 7, 6), TimeOfDay(12, 59, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 30, DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 45, DateTime(Date(1999, 7, 6), TimeOfDay(12, 15, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 60, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 75, DateTime(Date(1999, 7, 6), TimeOfDay(12, 45, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 90, DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 100, DateTime(Date(1999, 7, 6), TimeOfDay(12, 10, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 689, DateTime(Date(1999, 7, 6), TimeOfDay(12, 59, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 690, DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 691, DateTime(Date(1999, 7, 6), TimeOfDay(12, 1, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 960, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 1439, DateTime(Date(1999, 7, 6), TimeOfDay(12, 29, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 1440, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 1441, DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 2880, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -1, DateTime(Date(1999, 7, 6), TimeOfDay(12, 29, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -2, DateTime(Date(1999, 7, 6), TimeOfDay(12, 28, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -3, DateTime(Date(1999, 7, 6), TimeOfDay(12, 27, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -4, DateTime(Date(1999, 7, 6), TimeOfDay(12, 26, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -5, DateTime(Date(1999, 7, 6), TimeOfDay(12, 25, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -10, DateTime(Date(1999, 7, 6), TimeOfDay(12, 20, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -15, DateTime(Date(1999, 7, 6), TimeOfDay(12, 15, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -29, DateTime(Date(1999, 7, 6), TimeOfDay(12, 1, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -30, DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -45, DateTime(Date(1999, 7, 6), TimeOfDay(12, 45, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -60, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -75, DateTime(Date(1999, 7, 6), TimeOfDay(12, 15, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -90, DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -100, DateTime(Date(1999, 7, 6), TimeOfDay(12, 50, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -749, DateTime(Date(1999, 7, 6), TimeOfDay(12, 1, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -750, DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -751, DateTime(Date(1999, 7, 6), TimeOfDay(12, 59, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -960, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -1439, DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -1440, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -1441, DateTime(Date(1999, 7, 6), TimeOfDay(12, 29, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -2880, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 33)), 1, DateTime(Date(1999, 7, 6), TimeOfDay(12, 1, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 33)), 0, DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 33)), -1, DateTime(Date(1999, 7, 6), TimeOfDay(12, 59, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(11, 59, 33)), 1, DateTime(Date(1999, 7, 6), TimeOfDay(11, 0, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(11, 59, 33)), 0, DateTime(Date(1999, 7, 6), TimeOfDay(11, 59, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(11, 59, 33)), -1, DateTime(Date(1999, 7, 6), TimeOfDay(11, 58, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33)), 1, DateTime(Date(1999, 7, 6), TimeOfDay(0, 1, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33)), 0, DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33)), -1, DateTime(Date(1999, 7, 6), TimeOfDay(0, 59, 33)));
testDT(DateTime(Date(1999, 7, 5), TimeOfDay(23, 59, 33)), 1, DateTime(Date(1999, 7, 5), TimeOfDay(23, 0, 33)));
testDT(DateTime(Date(1999, 7, 5), TimeOfDay(23, 59, 33)), 0, DateTime(Date(1999, 7, 5), TimeOfDay(23, 59, 33)));
testDT(DateTime(Date(1999, 7, 5), TimeOfDay(23, 59, 33)), -1, DateTime(Date(1999, 7, 5), TimeOfDay(23, 58, 33)));
testDT(DateTime(Date(1998, 12, 31), TimeOfDay(23, 59, 33)), 1, DateTime(Date(1998, 12, 31), TimeOfDay(23, 0, 33)));
testDT(DateTime(Date(1998, 12, 31), TimeOfDay(23, 59, 33)), 0, DateTime(Date(1998, 12, 31), TimeOfDay(23, 59, 33)));
testDT(DateTime(Date(1998, 12, 31), TimeOfDay(23, 59, 33)), -1, DateTime(Date(1998, 12, 31), TimeOfDay(23, 58, 33)));
//Test B.C.
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 0, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 1, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 31, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 2, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 32, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 3, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 33, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 4, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 34, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 5, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 35, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 10, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 40, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 15, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 45, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 29, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 59, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 30, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 45, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 15, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 60, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 75, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 45, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 90, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 100, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 10, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 689, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 59, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 690, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 691, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 1, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 960, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 1439, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 29, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 1440, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 1441, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 31, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 2880, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -1, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 29, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -2, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 28, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -3, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 27, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -4, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 26, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -5, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 25, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -10, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 20, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -15, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 15, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -29, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 1, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -30, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -45, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 45, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -60, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -75, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 15, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -90, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -100, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 50, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -749, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 1, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -750, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -751, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 59, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -960, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -1439, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 31, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -1440, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -1441, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 29, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -2880, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 33)), 1, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 1, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 33)), 0, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 33)), -1, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 59, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(11, 59, 33)), 1, DateTime(Date(-1999, 7, 6), TimeOfDay(11, 0, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(11, 59, 33)), 0, DateTime(Date(-1999, 7, 6), TimeOfDay(11, 59, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(11, 59, 33)), -1, DateTime(Date(-1999, 7, 6), TimeOfDay(11, 58, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(0, 0, 33)), 1, DateTime(Date(-1999, 7, 6), TimeOfDay(0, 1, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(0, 0, 33)), 0, DateTime(Date(-1999, 7, 6), TimeOfDay(0, 0, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(0, 0, 33)), -1, DateTime(Date(-1999, 7, 6), TimeOfDay(0, 59, 33)));
testDT(DateTime(Date(-1999, 7, 5), TimeOfDay(23, 59, 33)), 1, DateTime(Date(-1999, 7, 5), TimeOfDay(23, 0, 33)));
testDT(DateTime(Date(-1999, 7, 5), TimeOfDay(23, 59, 33)), 0, DateTime(Date(-1999, 7, 5), TimeOfDay(23, 59, 33)));
testDT(DateTime(Date(-1999, 7, 5), TimeOfDay(23, 59, 33)), -1, DateTime(Date(-1999, 7, 5), TimeOfDay(23, 58, 33)));
testDT(DateTime(Date(-2000, 12, 31), TimeOfDay(23, 59, 33)), 1, DateTime(Date(-2000, 12, 31), TimeOfDay(23, 0, 33)));
testDT(DateTime(Date(-2000, 12, 31), TimeOfDay(23, 59, 33)), 0, DateTime(Date(-2000, 12, 31), TimeOfDay(23, 59, 33)));
testDT(DateTime(Date(-2000, 12, 31), TimeOfDay(23, 59, 33)), -1, DateTime(Date(-2000, 12, 31), TimeOfDay(23, 58, 33)));
//Test Both
testDT(DateTime(Date(1, 1, 1), TimeOfDay(0, 0, 0)), -1, DateTime(Date(1, 1, 1), TimeOfDay(0, 59, 0)));
testDT(DateTime(Date(0, 12, 31), TimeOfDay(23, 59, 0)), 1, DateTime(Date(0, 12, 31), TimeOfDay(23, 0, 0)));
testDT(DateTime(Date(0, 1, 1), TimeOfDay(0, 0, 0)), -1, DateTime(Date(0, 1, 1), TimeOfDay(0, 59, 0)));
testDT(DateTime(Date(-1, 12, 31), TimeOfDay(23, 59, 0)), 1, DateTime(Date(-1, 12, 31), TimeOfDay(23, 0, 0)));
testDT(DateTime(Date(-1, 1, 1), TimeOfDay(11, 30, 33)), 1_052_760, DateTime(Date(-1, 1, 1), TimeOfDay(11, 30, 33)));
testDT(DateTime(Date(1, 1, 1), TimeOfDay(13, 30, 33)), -1_052_760, DateTime(Date(1, 1, 1), TimeOfDay(13, 30, 33)));
testDT(DateTime(Date(-1, 1, 1), TimeOfDay(11, 30, 33)), 1_052_782, DateTime(Date(-1, 1, 1), TimeOfDay(11, 52, 33)));
testDT(DateTime(Date(1, 1, 1), TimeOfDay(13, 52, 33)), -1_052_782, DateTime(Date(1, 1, 1), TimeOfDay(13, 30, 33)));
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(!__traits(compiles, cdt.roll!"minutes"(4)));
static assert(!__traits(compiles, idt.roll!"minutes"(4)));
}
//Test roll!"seconds"().
unittest
{
static void testDT(DateTime orig, int seconds, in DateTime expected, size_t line = __LINE__)
{
orig.roll!"seconds"(seconds);
assertPred!"=="(orig, expected, "", __FILE__, line);
}
//Test A.D.
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 0, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 1, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 2, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 35)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 3, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 36)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 4, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 37)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 5, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 38)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 10, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 43)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 15, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 48)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 26, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 59)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 27, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 30, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 3)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 59, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 32)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 60, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 61, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 1766, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 59)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 1767, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 1768, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 1)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 2007, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 3599, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 32)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 3600, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 3601, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), 7200, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -1, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 32)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -2, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 31)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -3, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 30)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -4, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 29)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -5, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 28)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -10, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 23)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -15, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 18)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -33, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -34, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 59)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -35, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 58)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -59, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -60, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), -61, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 32)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0)), 1, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 1)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0)), 0, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0)), -1, DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 59)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 0)), 1, DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 1)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 0)), 0, DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 0)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 0)), -1, DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 59)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), 1, DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 1)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), 0, DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)));
testDT(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), -1, DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 59)));
testDT(DateTime(Date(1999, 7, 5), TimeOfDay(23, 59, 59)), 1, DateTime(Date(1999, 7, 5), TimeOfDay(23, 59, 0)));
testDT(DateTime(Date(1999, 7, 5), TimeOfDay(23, 59, 59)), 0, DateTime(Date(1999, 7, 5), TimeOfDay(23, 59, 59)));
testDT(DateTime(Date(1999, 7, 5), TimeOfDay(23, 59, 59)), -1, DateTime(Date(1999, 7, 5), TimeOfDay(23, 59, 58)));
testDT(DateTime(Date(1998, 12, 31), TimeOfDay(23, 59, 59)), 1, DateTime(Date(1998, 12, 31), TimeOfDay(23, 59, 0)));
testDT(DateTime(Date(1998, 12, 31), TimeOfDay(23, 59, 59)), 0, DateTime(Date(1998, 12, 31), TimeOfDay(23, 59, 59)));
testDT(DateTime(Date(1998, 12, 31), TimeOfDay(23, 59, 59)), -1, DateTime(Date(1998, 12, 31), TimeOfDay(23, 59, 58)));
//Test B.C.
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 0, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 1, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 34)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 2, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 35)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 3, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 36)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 4, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 37)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 5, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 38)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 10, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 43)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 15, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 48)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 26, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 59)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 27, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 0)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 30, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 3)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 59, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 32)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 60, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 61, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 34)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 1766, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 59)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 1767, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 0)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 1768, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 1)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 2007, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 0)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 3599, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 32)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 3600, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 3601, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 34)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), 7200, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -1, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 32)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -2, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 31)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -3, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 30)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -4, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 29)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -5, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 28)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -10, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 23)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -15, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 18)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -33, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 0)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -34, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 59)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -35, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 58)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -59, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 34)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -60, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)), -61, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 32)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 0)), 1, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 1)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 0)), 0, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 0)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 0)), -1, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 59)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 0)), 1, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 1)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 0)), 0, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 0)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 0)), -1, DateTime(Date(-1999, 7, 6), TimeOfDay(12, 0, 59)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(0, 0, 0)), 1, DateTime(Date(-1999, 7, 6), TimeOfDay(0, 0, 1)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(0, 0, 0)), 0, DateTime(Date(-1999, 7, 6), TimeOfDay(0, 0, 0)));
testDT(DateTime(Date(-1999, 7, 6), TimeOfDay(0, 0, 0)), -1, DateTime(Date(-1999, 7, 6), TimeOfDay(0, 0, 59)));
testDT(DateTime(Date(-1999, 7, 5), TimeOfDay(23, 59, 59)), 1, DateTime(Date(-1999, 7, 5), TimeOfDay(23, 59, 0)));
testDT(DateTime(Date(-1999, 7, 5), TimeOfDay(23, 59, 59)), 0, DateTime(Date(-1999, 7, 5), TimeOfDay(23, 59, 59)));
testDT(DateTime(Date(-1999, 7, 5), TimeOfDay(23, 59, 59)), -1, DateTime(Date(-1999, 7, 5), TimeOfDay(23, 59, 58)));
testDT(DateTime(Date(-2000, 12, 31), TimeOfDay(23, 59, 59)), 1, DateTime(Date(-2000, 12, 31), TimeOfDay(23, 59, 0)));
testDT(DateTime(Date(-2000, 12, 31), TimeOfDay(23, 59, 59)), 0, DateTime(Date(-2000, 12, 31), TimeOfDay(23, 59, 59)));
testDT(DateTime(Date(-2000, 12, 31), TimeOfDay(23, 59, 59)), -1, DateTime(Date(-2000, 12, 31), TimeOfDay(23, 59, 58)));
//Test Both
testDT(DateTime(Date(1, 1, 1), TimeOfDay(0, 0, 0)), -1, DateTime(Date(1, 1, 1), TimeOfDay(0, 0, 59)));
testDT(DateTime(Date(0, 12, 31), TimeOfDay(23, 59, 59)), 1, DateTime(Date(0, 12, 31), TimeOfDay(23, 59, 0)));
testDT(DateTime(Date(0, 1, 1), TimeOfDay(0, 0, 0)), -1, DateTime(Date(0, 1, 1), TimeOfDay(0, 0, 59)));
testDT(DateTime(Date(-1, 12, 31), TimeOfDay(23, 59, 59)), 1, DateTime(Date(-1, 12, 31), TimeOfDay(23, 59, 0)));
testDT(DateTime(Date(-1, 1, 1), TimeOfDay(11, 30, 33)), 63_165_600L, DateTime(Date(-1, 1, 1), TimeOfDay(11, 30, 33)));
testDT(DateTime(Date(1, 1, 1), TimeOfDay(13, 30, 33)), -63_165_600L, DateTime(Date(1, 1, 1), TimeOfDay(13, 30, 33)));
testDT(DateTime(Date(-1, 1, 1), TimeOfDay(11, 30, 33)), 63_165_617L, DateTime(Date(-1, 1, 1), TimeOfDay(11, 30, 50)));
testDT(DateTime(Date(1, 1, 1), TimeOfDay(13, 30, 50)), -63_165_617L, DateTime(Date(1, 1, 1), TimeOfDay(13, 30, 33)));
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(!__traits(compiles, cdt.roll!"seconds"(4)));
static assert(!__traits(compiles, idt.roll!"seconds"(4)));
}
/++
Gives the result of adding or subtracting a duration from this DateTime.
The legal types of arithmetic for DateTime using this operator are
$(TABLE
$(TR $(TD DateTime) $(TD +) $(TD duration) $(TD -->) $(TD DateTime))
$(TR $(TD DateTime) $(TD -) $(TD duration) $(TD -->) $(TD DateTime))
)
Params:
duration = The duration to add to or subtract from this DateTime.
+/
DateTime opBinary(string op, D)(in D duration) const pure nothrow
if((op == "+" || op == "-") &&
(is(Unqual!D == Duration) ||
is(Unqual!D == TickDuration)))
{
DateTime retval = this;
static if(is(Unqual!D == Duration))
immutable hnsecs = duration.total!"hnsecs";
else static if(is(Unqual!D == TickDuration))
immutable hnsecs = duration.hnsecs;
//Ideally, this would just be
//return retval.addSeconds(convert!("hnsecs", "seconds")(unaryFun!(op ~ "a")(hnsecs)));
//But there isn't currently a pure version of unaryFun!().
static if(op == "+")
immutable signedHNSecs = hnsecs;
else static if(op == "-")
immutable signedHNSecs = -hnsecs;
else
static assert(0);
return retval.addSeconds(convert!("hnsecs", "seconds")(signedHNSecs));
}
unittest
{
auto dt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
assertPred!"=="(dt + dur!"weeks"(7), DateTime(Date(1999, 8, 24), TimeOfDay(12, 30, 33)));
assertPred!"=="(dt + dur!"weeks"(-7), DateTime(Date(1999, 5, 18), TimeOfDay(12, 30, 33)));
assertPred!"=="(dt + dur!"days"(7), DateTime(Date(1999, 7, 13), TimeOfDay(12, 30, 33)));
assertPred!"=="(dt + dur!"days"(-7), DateTime(Date(1999, 6, 29), TimeOfDay(12, 30, 33)));
assertPred!"=="(dt + dur!"hours"(7), DateTime(Date(1999, 7, 6), TimeOfDay(19, 30, 33)));
assertPred!"=="(dt + dur!"hours"(-7), DateTime(Date(1999, 7, 6), TimeOfDay(5, 30, 33)));
assertPred!"=="(dt + dur!"minutes"(7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 37, 33)));
assertPred!"=="(dt + dur!"minutes"(-7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 23, 33)));
assertPred!"=="(dt + dur!"seconds"(7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
assertPred!"=="(dt + dur!"seconds"(-7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
assertPred!"=="(dt + dur!"msecs"(7_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
assertPred!"=="(dt + dur!"msecs"(-7_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
assertPred!"=="(dt + dur!"usecs"(7_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
assertPred!"=="(dt + dur!"usecs"(-7_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
assertPred!"=="(dt + dur!"hnsecs"(70_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
assertPred!"=="(dt + dur!"hnsecs"(-70_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
//This probably only runs in cases where gettimeofday() is used, but it's
//hard to do this test correctly with variable ticksPerSec.
if(TickDuration.ticksPerSec == 1_000_000)
{
assertPred!"=="(dt + TickDuration.from!"usecs"(7_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
assertPred!"=="(dt + TickDuration.from!"usecs"(-7_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
}
assertPred!"=="(dt - dur!"weeks"(-7), DateTime(Date(1999, 8, 24), TimeOfDay(12, 30, 33)));
assertPred!"=="(dt - dur!"weeks"(7), DateTime(Date(1999, 5, 18), TimeOfDay(12, 30, 33)));
assertPred!"=="(dt - dur!"days"(-7), DateTime(Date(1999, 7, 13), TimeOfDay(12, 30, 33)));
assertPred!"=="(dt - dur!"days"(7), DateTime(Date(1999, 6, 29), TimeOfDay(12, 30, 33)));
assertPred!"=="(dt - dur!"hours"(-7), DateTime(Date(1999, 7, 6), TimeOfDay(19, 30, 33)));
assertPred!"=="(dt - dur!"hours"(7), DateTime(Date(1999, 7, 6), TimeOfDay(5, 30, 33)));
assertPred!"=="(dt - dur!"minutes"(-7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 37, 33)));
assertPred!"=="(dt - dur!"minutes"(7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 23, 33)));
assertPred!"=="(dt - dur!"seconds"(-7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
assertPred!"=="(dt - dur!"seconds"(7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
assertPred!"=="(dt - dur!"msecs"(-7_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
assertPred!"=="(dt - dur!"msecs"(7_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
assertPred!"=="(dt - dur!"usecs"(-7_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
assertPred!"=="(dt - dur!"usecs"(7_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
assertPred!"=="(dt - dur!"hnsecs"(-70_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
assertPred!"=="(dt - dur!"hnsecs"(70_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
//This probably only runs in cases where gettimeofday() is used, but it's
//hard to do this test correctly with variable ticksPerSec.
if(TickDuration.ticksPerSec == 1_000_000)
{
assertPred!"=="(dt - TickDuration.from!"usecs"(-7_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
assertPred!"=="(dt - TickDuration.from!"usecs"(7_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
}
auto duration = dur!"seconds"(12);
const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
static assert(__traits(compiles, cdt + duration));
static assert(__traits(compiles, idt + duration));
static assert(__traits(compiles, cdt - duration));
static assert(__traits(compiles, idt - duration));
}
/++
Gives the result of adding or subtracting a duration from this DateTime,
as well as assigning the result to this DateTime.
The legal types of arithmetic for DateTime using this operator are
$(TABLE
$(TR $(TD DateTime) $(TD +) $(TD duration) $(TD -->) $(TD DateTime))
$(TR $(TD DateTime) $(TD -) $(TD duration) $(TD -->) $(TD DateTime))
)
Params:
duration = The duration to add to or subtract from this DateTime.
+/
/+ref+/ DateTime opOpAssign(string op, D)(in D duration) pure nothrow
if((op == "+" || op == "-") &&
(is(Unqual!D == Duration) ||
is(Unqual!D == TickDuration)))
{
DateTime retval = this;
static if(is(Unqual!D == Duration))
immutable hnsecs = duration.total!"hnsecs";
else static if(is(Unqual!D == TickDuration))
immutable hnsecs = duration.hnsecs;
//Ideally, this would just be
//return addSeconds(convert!("hnsecs", "seconds")(unaryFun!(op ~ "a")(hnsecs)));
//But there isn't currently a pure version of unaryFun!().
static if(op == "+")
immutable signedHNSecs = hnsecs;
else static if(op == "-")
immutable signedHNSecs = -hnsecs;
else
static assert(0);
return addSeconds(convert!("hnsecs", "seconds")(signedHNSecs));
}
unittest
{
assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"weeks"(7), DateTime(Date(1999, 8, 24), TimeOfDay(12, 30, 33)));
assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"weeks"(-7), DateTime(Date(1999, 5, 18), TimeOfDay(12, 30, 33)));
assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"days"(7), DateTime(Date(1999, 7, 13), TimeOfDay(12, 30, 33)));
assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"days"(-7), DateTime(Date(1999, 6, 29), TimeOfDay(12, 30, 33)));
assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"hours"(7), DateTime(Date(1999, 7, 6), TimeOfDay(19, 30, 33)));
assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"hours"(-7), DateTime(Date(1999, 7, 6), TimeOfDay(5, 30, 33)));
assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"minutes"(7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 37, 33)));
assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"minutes"(-7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 23, 33)));
assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"seconds"(7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"seconds"(-7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"msecs"(7_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"msecs"(-7_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"usecs"(7_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"usecs"(-7_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"hnsecs"(70_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
assertPred!"+="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"hnsecs"(-70_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"weeks"(-7), DateTime(Date(1999, 8, 24), TimeOfDay(12, 30, 33)));
assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"weeks"(7), DateTime(Date(1999, 5, 18), TimeOfDay(12, 30, 33)));
assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"days"(-7), DateTime(Date(1999, 7, 13), TimeOfDay(12, 30, 33)));
assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"days"(7), DateTime(Date(1999, 6, 29), TimeOfDay(12, 30, 33)));
assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"hours"(-7), DateTime(Date(1999, 7, 6), TimeOfDay(19, 30, 33)));
assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"hours"(7), DateTime(Date(1999, 7, 6), TimeOfDay(5, 30, 33)));
assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"minutes"(-7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 37, 33)));
assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"minutes"(7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 23, 33)));
assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"seconds"(-7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"seconds"(7), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"msecs"(-7_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"msecs"(7_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"usecs"(-7_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"usecs"(7_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"hnsecs"(-70_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 40)));
assertPred!"-="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)), dur!"hnsecs"(70_000_000), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 26)));
auto duration = dur!"seconds"(12);
const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
static assert(!__traits(compiles, cdt += duration));
static assert(!__traits(compiles, idt += duration));
static assert(!__traits(compiles, cdt -= duration));
static assert(!__traits(compiles, idt -= duration));
}
/++
Gives the difference between two DateTimes.
The legal types of arithmetic for DateTime using this operator are
$(TABLE
$(TR $(TD DateTime) $(TD -) $(TD DateTime) $(TD -->) $(TD duration))
)
+/
Duration opBinary(string op)(in DateTime rhs) const pure nothrow
if(op == "-")
{
immutable dateResult = _date - rhs.date;
immutable todResult = _tod - rhs._tod;
return dur!"hnsecs"(dateResult.total!"hnsecs" + todResult.total!"hnsecs");
}
unittest
{
auto dt = DateTime(1999, 7, 6, 12, 30, 33);
assertPred!"=="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)) -
DateTime(Date(1998, 7, 6), TimeOfDay(12, 30, 33)),
dur!"seconds"(31_536_000));
assertPred!"=="(DateTime(Date(1998, 7, 6), TimeOfDay(12, 30, 33)) -
DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
dur!"seconds"(-31_536_000));
assertPred!"=="(DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33)) -
DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
dur!"seconds"(26_78_400));
assertPred!"=="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)) -
DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33)),
dur!"seconds"(-26_78_400));
assertPred!"=="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)) -
DateTime(Date(1999, 7, 5), TimeOfDay(12, 30, 33)),
dur!"seconds"(86_400));
assertPred!"=="(DateTime(Date(1999, 7, 5), TimeOfDay(12, 30, 33)) -
DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
dur!"seconds"(-86_400));
assertPred!"=="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)) -
DateTime(Date(1999, 7, 6), TimeOfDay(11, 30, 33)),
dur!"seconds"(3600));
assertPred!"=="(DateTime(Date(1999, 7, 6), TimeOfDay(11, 30, 33)) -
DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
dur!"seconds"(-3600));
assertPred!"=="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)) -
DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
dur!"seconds"(60));
assertPred!"=="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)) -
DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33)),
dur!"seconds"(-60));
assertPred!"=="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)) -
DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)),
dur!"seconds"(1));
assertPred!"=="(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)) -
DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34)),
dur!"seconds"(-1));
assertPred!"=="(DateTime(1, 1, 1, 12, 30, 33) - DateTime(1, 1, 1, 0, 0, 0), dur!"seconds"(45033));
assertPred!"=="(DateTime(1, 1, 1, 0, 0, 0) - DateTime(1, 1, 1, 12, 30, 33), dur!"seconds"(-45033));
assertPred!"=="(DateTime(0, 12, 31, 12, 30, 33) - DateTime(1, 1, 1, 0, 0, 0), dur!"seconds"(-41367));
assertPred!"=="(DateTime(1, 1, 1, 0, 0, 0) - DateTime(0, 12, 31, 12, 30, 33), dur!"seconds"(41367));
const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
static assert(__traits(compiles, dt - dt));
static assert(__traits(compiles, cdt - dt));
static assert(__traits(compiles, idt - dt));
static assert(__traits(compiles, dt - cdt));
static assert(__traits(compiles, cdt - cdt));
static assert(__traits(compiles, idt - cdt));
static assert(__traits(compiles, dt - idt));
static assert(__traits(compiles, cdt - idt));
static assert(__traits(compiles, idt - idt));
}
/++
Returns the difference between the two DateTimes in months.
You can get the difference in years by subtracting the year property
of two DateTimes, and you can get the difference in days or weeks by
subtracting the DateTimes themselves and using the Duration that results,
but because you cannot convert between months and smaller units without
a specific date (which Durations don't have), you cannot get the difference
in months without doing some math using both the year and month properties,
so this is a convenience function for getting the difference in months.
Note that the number of days in the months or how far into the month either
date is is irrelevant. It is the difference in the month property combined
with the difference in years * 12. So, for instance, December 31st and
January 1st are one month apart just as December 1st and January 31st are
one month apart.
Params:
rhs = The DateTime to subtract from this one.
Examples:
--------------------
assert(DateTime(1999, 2, 1, 12, 2, 3).diffMonths(DateTime(1999, 1, 31, 23, 59, 59)) == 1);
assert(DateTime(1999, 1, 31, 0, 0, 0).diffMonths(DateTime(1999, 2, 1, 12, 3, 42)) == -1);
assert(DateTime(1999, 3, 1, 5, 30, 0).diffMonths(DateTime(1999, 1, 1, 2, 4, 7)) == 2);
assert(DateTime(1999, 1, 1, 7, 2, 4).diffMonths(DateTime(1999, 3, 31, 0, 30, 58)) == -2);
--------------------
+/
int diffMonths(in DateTime rhs) const pure nothrow
{
return _date.diffMonths(rhs._date);
}
unittest
{
auto dt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
static assert(__traits(compiles, dt.diffMonths(dt)));
static assert(__traits(compiles, cdt.diffMonths(dt)));
static assert(__traits(compiles, idt.diffMonths(dt)));
static assert(__traits(compiles, dt.diffMonths(cdt)));
static assert(__traits(compiles, cdt.diffMonths(cdt)));
static assert(__traits(compiles, idt.diffMonths(cdt)));
static assert(__traits(compiles, dt.diffMonths(idt)));
static assert(__traits(compiles, cdt.diffMonths(idt)));
static assert(__traits(compiles, idt.diffMonths(idt)));
//Verify Examples.
assert(DateTime(1999, 2, 1, 12, 2, 3).diffMonths(DateTime(1999, 1, 31, 23, 59, 59)) == 1);
assert(DateTime(1999, 1, 31, 0, 0, 0).diffMonths(DateTime(1999, 2, 1, 12, 3, 42)) == -1);
assert(DateTime(1999, 3, 1, 5, 30, 0).diffMonths(DateTime(1999, 1, 1, 2, 4, 7)) == 2);
assert(DateTime(1999, 1, 1, 7, 2, 4).diffMonths(DateTime(1999, 3, 31, 0, 30, 58)) == -2);
}
/++
Whether this DateTime is in a leap year.
+/
@property bool isLeapYear() const pure nothrow
{
return _date.isLeapYear;
}
unittest
{
auto dt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
static assert(__traits(compiles, dt.isLeapYear));
static assert(__traits(compiles, cdt.isLeapYear));
static assert(__traits(compiles, idt.isLeapYear));
}
/++
Day of the week this DateTime is on.
+/
@property DayOfWeek dayOfWeek() const pure nothrow
{
return _date.dayOfWeek;
}
unittest
{
auto dt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
static assert(__traits(compiles, dt.dayOfWeek));
static assert(__traits(compiles, cdt.dayOfWeek));
static assert(__traits(compiles, idt.dayOfWeek));
}
/++
Day of the year this DateTime is on.
Examples:
--------------------
assert(DateTime(Date(1999, 1, 1), TimeOfDay(12, 22, 7)).dayOfYear == 1);
assert(DateTime(Date(1999, 12, 31), TimeOfDay(7, 2, 59)).dayOfYear == 365);
assert(DateTime(Date(2000, 12, 31), TimeOfDay(21, 20, 0)).dayOfYear == 366);
--------------------
+/
@property ushort dayOfYear() const pure nothrow
{
return _date.dayOfYear;
}
unittest
{
auto dt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
static assert(__traits(compiles, dt.dayOfYear));
static assert(__traits(compiles, cdt.dayOfYear));
static assert(__traits(compiles, idt.dayOfYear));
//Verify Examples.
assert(DateTime(Date(1999, 1, 1), TimeOfDay(12, 22, 7)).dayOfYear == 1);
assert(DateTime(Date(1999, 12, 31), TimeOfDay(7, 2, 59)).dayOfYear == 365);
assert(DateTime(Date(2000, 12, 31), TimeOfDay(21, 20, 0)).dayOfYear == 366);
}
/++
Day of the year.
Params:
day = The day of the year to set which day of the year this DateTime is on.
+/
@property void dayOfYear(int day) pure
{
_date.dayOfYear = day;
}
unittest
{
auto dt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
static assert(__traits(compiles, dt.dayOfYear = 12));
static assert(!__traits(compiles, cdt.dayOfYear = 12));
static assert(!__traits(compiles, idt.dayOfYear = 12));
}
/++
The Xth day of the Gregorian Calendar that this DateTime is on.
Examples:
--------------------
assert(DateTime(Date(1, 1, 1), TimeOfDay(0, 0, 0)).dayOfGregorianCal == 1);
assert(DateTime(Date(1, 12, 31), TimeOfDay(23, 59, 59)).dayOfGregorianCal == 365);
assert(DateTime(Date(2, 1, 1), TimeOfDay(2, 2, 2)).dayOfGregorianCal == 366);
assert(DateTime(Date(0, 12, 31), TimeOfDay(7, 7, 7)).dayOfGregorianCal == 0);
assert(DateTime(Date(0, 1, 1), TimeOfDay(19, 30, 0)).dayOfGregorianCal == -365);
assert(DateTime(Date(-1, 12, 31), TimeOfDay(4, 7, 0)).dayOfGregorianCal == -366);
assert(DateTime(Date(2000, 1, 1), TimeOfDay(9, 30, 20)).dayOfGregorianCal == 730_120);
assert(DateTime(Date(2010, 12, 31), TimeOfDay(15, 45, 50)).dayOfGregorianCal == 734_137);
--------------------
+/
@property int dayOfGregorianCal() const pure nothrow
{
return _date.dayOfGregorianCal;
}
unittest
{
const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
static assert(__traits(compiles, cdt.dayOfGregorianCal));
static assert(__traits(compiles, idt.dayOfGregorianCal));
//Verify Examples.
assert(DateTime(Date(1, 1, 1), TimeOfDay(0, 0, 0)).dayOfGregorianCal == 1);
assert(DateTime(Date(1, 12, 31), TimeOfDay(23, 59, 59)).dayOfGregorianCal == 365);
assert(DateTime(Date(2, 1, 1), TimeOfDay(2, 2, 2)).dayOfGregorianCal == 366);
assert(DateTime(Date(0, 12, 31), TimeOfDay(7, 7, 7)).dayOfGregorianCal == 0);
assert(DateTime(Date(0, 1, 1), TimeOfDay(19, 30, 0)).dayOfGregorianCal == -365);
assert(DateTime(Date(-1, 12, 31), TimeOfDay(4, 7, 0)).dayOfGregorianCal == -366);
assert(DateTime(Date(2000, 1, 1), TimeOfDay(9, 30, 20)).dayOfGregorianCal == 730_120);
assert(DateTime(Date(2010, 12, 31), TimeOfDay(15, 45, 50)).dayOfGregorianCal == 734_137);
}
/++
The Xth day of the Gregorian Calendar that this DateTime is on. Setting
this property does not affect the time portion of DateTime.
Params:
days = The day of the Gregorian Calendar to set this DateTime to.
Examples:
--------------------
auto dt = DateTime(Date.init, TimeOfDay(12, 0, 0));
dt.dayOfGregorianCal = 1;
assert(dt == DateTime(Date(1, 1, 1), TimeOfDay(12, 0, 0)));
dt.dayOfGregorianCal = 365;
assert(dt == DateTime(Date(1, 12, 31), TimeOfDay(12, 0, 0)));
dt.dayOfGregorianCal = 366;
assert(dt == DateTime(Date(2, 1, 1), TimeOfDay(12, 0, 0)));
dt.dayOfGregorianCal = 0;
assert(dt == DateTime(Date(0, 12, 31), TimeOfDay(12, 0, 0)));
dt.dayOfGregorianCal = -365;
assert(dt == DateTime(Date(-0, 1, 1), TimeOfDay(12, 0, 0)));
dt.dayOfGregorianCal = -366;
assert(dt == DateTime(Date(-1, 12, 31), TimeOfDay(12, 0, 0)));
dt.dayOfGregorianCal = 730_120;
assert(dt == DateTime(Date(2000, 1, 1), TimeOfDay(12, 0, 0)));
dt.dayOfGregorianCal = 734_137;
assert(dt == DateTime(Date(2010, 12, 31), TimeOfDay(12, 0, 0)));
--------------------
+/
@property void dayOfGregorianCal(int days) pure nothrow
{
_date.dayOfGregorianCal = days;
}
unittest
{
const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
static assert(!__traits(compiles, cdt.dayOfGregorianCal = 7));
static assert(!__traits(compiles, idt.dayOfGregorianCal = 7));
//Verify Examples.
auto dt = DateTime(Date.init, TimeOfDay(12, 0, 0));
dt.dayOfGregorianCal = 1;
assert(dt == DateTime(Date(1, 1, 1), TimeOfDay(12, 0, 0)));
dt.dayOfGregorianCal = 365;
assert(dt == DateTime(Date(1, 12, 31), TimeOfDay(12, 0, 0)));
dt.dayOfGregorianCal = 366;
assert(dt == DateTime(Date(2, 1, 1), TimeOfDay(12, 0, 0)));
dt.dayOfGregorianCal = 0;
assert(dt == DateTime(Date(0, 12, 31), TimeOfDay(12, 0, 0)));
dt.dayOfGregorianCal = -365;
assert(dt == DateTime(Date(-0, 1, 1), TimeOfDay(12, 0, 0)));
dt.dayOfGregorianCal = -366;
assert(dt == DateTime(Date(-1, 12, 31), TimeOfDay(12, 0, 0)));
dt.dayOfGregorianCal = 730_120;
assert(dt == DateTime(Date(2000, 1, 1), TimeOfDay(12, 0, 0)));
dt.dayOfGregorianCal = 734_137;
assert(dt == DateTime(Date(2010, 12, 31), TimeOfDay(12, 0, 0)));
}
/++
The ISO 8601 week of the year that this DateTime is in.
See_Also:
ISO Week Date
+/
@property ubyte isoWeek() const pure nothrow
{
return _date.isoWeek;
}
unittest
{
auto dt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
static assert(__traits(compiles, dt.isoWeek));
static assert(__traits(compiles, cdt.isoWeek));
static assert(__traits(compiles, idt.isoWeek));
}
/++
DateTime for the last day in the month that this DateTime is in.
The time portion of endOfMonth is always 23:59:59.
Examples:
--------------------
assert(DateTime(Date(1999, 1, 6), TimeOfDay(0, 0, 0)).endOfMonth == DateTime(Date(1999, 1, 31), TimeOfDay(23, 59, 59)));
assert(DateTime(Date(1999, 2, 7), TimeOfDay(19, 30, 0)).endOfMonth == DateTime(Date(1999, 2, 28), TimeOfDay(23, 59, 59)));
assert(DateTime(Date(2000, 2, 7), TimeOfDay(5, 12, 27)).endOfMonth == DateTime(Date(2000, 2, 29), TimeOfDay(23, 59, 59)));
assert(DateTime(Date(2000, 6, 4), TimeOfDay(12, 22, 9)).endOfMonth == DateTime(Date(2000, 6, 30), TimeOfDay(23, 59, 59)));
--------------------
+/
@property DateTime endOfMonth() const pure nothrow
{
try
return DateTime(_date.endOfMonth, TimeOfDay(23, 59, 59));
catch(Exception e)
assert(0, "DateTime constructor threw.");
}
unittest
{
//Test A.D.
assertPred!"=="(DateTime(1999, 1, 1, 0, 13, 26).endOfMonth, DateTime(1999, 1, 31, 23, 59, 59));
assertPred!"=="(DateTime(1999, 2, 1, 1, 14, 27).endOfMonth, DateTime(1999, 2, 28, 23, 59, 59));
assertPred!"=="(DateTime(2000, 2, 1, 2, 15, 28).endOfMonth, DateTime(2000, 2, 29, 23, 59, 59));
assertPred!"=="(DateTime(1999, 3, 1, 3, 16, 29).endOfMonth, DateTime(1999, 3, 31, 23, 59, 59));
assertPred!"=="(DateTime(1999, 4, 1, 4, 17, 30).endOfMonth, DateTime(1999, 4, 30, 23, 59, 59));
assertPred!"=="(DateTime(1999, 5, 1, 5, 18, 31).endOfMonth, DateTime(1999, 5, 31, 23, 59, 59));
assertPred!"=="(DateTime(1999, 6, 1, 6, 19, 32).endOfMonth, DateTime(1999, 6, 30, 23, 59, 59));
assertPred!"=="(DateTime(1999, 7, 1, 7, 20, 33).endOfMonth, DateTime(1999, 7, 31, 23, 59, 59));
assertPred!"=="(DateTime(1999, 8, 1, 8, 21, 34).endOfMonth, DateTime(1999, 8, 31, 23, 59, 59));
assertPred!"=="(DateTime(1999, 9, 1, 9, 22, 35).endOfMonth, DateTime(1999, 9, 30, 23, 59, 59));
assertPred!"=="(DateTime(1999, 10, 1, 10, 23, 36).endOfMonth, DateTime(1999, 10, 31, 23, 59, 59));
assertPred!"=="(DateTime(1999, 11, 1, 11, 24, 37).endOfMonth, DateTime(1999, 11, 30, 23, 59, 59));
assertPred!"=="(DateTime(1999, 12, 1, 12, 25, 38).endOfMonth, DateTime(1999, 12, 31, 23, 59, 59));
//Test B.C.
assertPred!"=="(DateTime(-1999, 1, 1, 0, 13, 26).endOfMonth, DateTime(-1999, 1, 31, 23, 59, 59));
assertPred!"=="(DateTime(-1999, 2, 1, 1, 14, 27).endOfMonth, DateTime(-1999, 2, 28, 23, 59, 59));
assertPred!"=="(DateTime(-2000, 2, 1, 2, 15, 28).endOfMonth, DateTime(-2000, 2, 29, 23, 59, 59));
assertPred!"=="(DateTime(-1999, 3, 1, 3, 16, 29).endOfMonth, DateTime(-1999, 3, 31, 23, 59, 59));
assertPred!"=="(DateTime(-1999, 4, 1, 4, 17, 30).endOfMonth, DateTime(-1999, 4, 30, 23, 59, 59));
assertPred!"=="(DateTime(-1999, 5, 1, 5, 18, 31).endOfMonth, DateTime(-1999, 5, 31, 23, 59, 59));
assertPred!"=="(DateTime(-1999, 6, 1, 6, 19, 32).endOfMonth, DateTime(-1999, 6, 30, 23, 59, 59));
assertPred!"=="(DateTime(-1999, 7, 1, 7, 20, 33).endOfMonth, DateTime(-1999, 7, 31, 23, 59, 59));
assertPred!"=="(DateTime(-1999, 8, 1, 8, 21, 34).endOfMonth, DateTime(-1999, 8, 31, 23, 59, 59));
assertPred!"=="(DateTime(-1999, 9, 1, 9, 22, 35).endOfMonth, DateTime(-1999, 9, 30, 23, 59, 59));
assertPred!"=="(DateTime(-1999, 10, 1, 10, 23, 36).endOfMonth, DateTime(-1999, 10, 31, 23, 59, 59));
assertPred!"=="(DateTime(-1999, 11, 1, 11, 24, 37).endOfMonth, DateTime(-1999, 11, 30, 23, 59, 59));
assertPred!"=="(DateTime(-1999, 12, 1, 12, 25, 38).endOfMonth, DateTime(-1999, 12, 31, 23, 59, 59));
const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
static assert(__traits(compiles, cdt.endOfMonth));
static assert(__traits(compiles, idt.endOfMonth));
//Verify Examples.
assert(DateTime(Date(1999, 1, 6), TimeOfDay(0, 0, 0)).endOfMonth == DateTime(Date(1999, 1, 31), TimeOfDay(23, 59, 59)));
assert(DateTime(Date(1999, 2, 7), TimeOfDay(19, 30, 0)).endOfMonth == DateTime(Date(1999, 2, 28), TimeOfDay(23, 59, 59)));
assert(DateTime(Date(2000, 2, 7), TimeOfDay(5, 12, 27)).endOfMonth == DateTime(Date(2000, 2, 29), TimeOfDay(23, 59, 59)));
assert(DateTime(Date(2000, 6, 4), TimeOfDay(12, 22, 9)).endOfMonth == DateTime(Date(2000, 6, 30), TimeOfDay(23, 59, 59)));
}
/++
The last day in the month that this DateTime is in.
Examples:
--------------------
assert(DateTime(Date(1999, 1, 6), TimeOfDay(0, 0, 0)).endOfMonthDay == 31);
assert(DateTime(Date(1999, 2, 7), TimeOfDay(19, 30, 0)).endOfMonthDay == 28);
assert(DateTime(Date(2000, 2, 7), TimeOfDay(5, 12, 27)).endOfMonthDay == 29);
assert(DateTime(Date(2000, 6, 4), TimeOfDay(12, 22, 9)).endOfMonthDay == 30);
--------------------
+/
@property ubyte endOfMonthDay() const pure nothrow
{
return _date.endOfMonthDay;
}
unittest
{
const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
static assert(__traits(compiles, cdt.endOfMonthDay));
static assert(__traits(compiles, idt.endOfMonthDay));
//Verify Examples.
assert(DateTime(Date(1999, 1, 6), TimeOfDay(0, 0, 0)).endOfMonthDay == 31);
assert(DateTime(Date(1999, 2, 7), TimeOfDay(19, 30, 0)).endOfMonthDay == 28);
assert(DateTime(Date(2000, 2, 7), TimeOfDay(5, 12, 27)).endOfMonthDay == 29);
assert(DateTime(Date(2000, 6, 4), TimeOfDay(12, 22, 9)).endOfMonthDay == 30);
}
/++
Whether the current year is a date in A.D.
Examples:
--------------------
assert(DateTime(Date(1, 1, 1), TimeOfDay(12, 7, 0)).isAD);
assert(DateTime(Date(2010, 12, 31), TimeOfDay(0, 0, 0)).isAD);
assert(!DateTime(Date(0, 12, 31), TimeOfDay(23, 59, 59)).isAD);
assert(!DateTime(Date(-2010, 1, 1), TimeOfDay(2, 2, 2)).isAD);
--------------------
+/
@property bool isAD() const pure nothrow
{
return _date.isAD;
}
unittest
{
const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
static assert(__traits(compiles, cdt.isAD));
static assert(__traits(compiles, idt.isAD));
//Verify Examples.
assert(DateTime(Date(1, 1, 1), TimeOfDay(12, 7, 0)).isAD);
assert(DateTime(Date(2010, 12, 31), TimeOfDay(0, 0, 0)).isAD);
assert(!DateTime(Date(0, 12, 31), TimeOfDay(23, 59, 59)).isAD);
assert(!DateTime(Date(-2010, 1, 1), TimeOfDay(2, 2, 2)).isAD);
}
/++
The julian day for this DateTime at the given time. For example,
prior to noon, 1996-03-31 would be the julian day number 2_450_173,
so this function returns 2_450_173, while from noon onward, it the
julian day number would be 2_450_174, so this function returns 2_450_174.
+/
@property long julianDay() const pure nothrow
{
if(_tod._hour < 12)
return _date.julianDay - 1;
else
return _date.julianDay;
}
unittest
{
assertPred!"=="(DateTime(Date(-4713, 11, 24), TimeOfDay(0, 0, 0)).julianDay, -1);
assertPred!"=="(DateTime(Date(-4713, 11, 24), TimeOfDay(12, 0, 0)).julianDay, 0);
assertPred!"=="(DateTime(Date(0, 12, 31), TimeOfDay(0, 0, 0)).julianDay, 1_721_424);
assertPred!"=="(DateTime(Date(0, 12, 31), TimeOfDay(12, 0, 0)).julianDay, 1_721_425);
assertPred!"=="(DateTime(Date(1, 1, 1), TimeOfDay(0, 0, 0)).julianDay, 1_721_425);
assertPred!"=="(DateTime(Date(1, 1, 1), TimeOfDay(12, 0, 0)).julianDay, 1_721_426);
assertPred!"=="(DateTime(Date(1582, 10, 15), TimeOfDay(0, 0, 0)).julianDay, 2_299_160);
assertPred!"=="(DateTime(Date(1582, 10, 15), TimeOfDay(12, 0, 0)).julianDay, 2_299_161);
assertPred!"=="(DateTime(Date(1858, 11, 17), TimeOfDay(0, 0, 0)).julianDay, 2_400_000);
assertPred!"=="(DateTime(Date(1858, 11, 17), TimeOfDay(12, 0, 0)).julianDay, 2_400_001);
assertPred!"=="(DateTime(Date(1982, 1, 4), TimeOfDay(0, 0, 0)).julianDay, 2_444_973);
assertPred!"=="(DateTime(Date(1982, 1, 4), TimeOfDay(12, 0, 0)).julianDay, 2_444_974);
assertPred!"=="(DateTime(Date(1996, 3, 31), TimeOfDay(0, 0, 0)).julianDay, 2_450_173);
assertPred!"=="(DateTime(Date(1996, 3, 31), TimeOfDay(12, 0, 0)).julianDay, 2_450_174);
assertPred!"=="(DateTime(Date(2010, 8, 24), TimeOfDay(0, 0, 0)).julianDay, 2_455_432);
assertPred!"=="(DateTime(Date(2010, 8, 24), TimeOfDay(12, 0, 0)).julianDay, 2_455_433);
const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
static assert(__traits(compiles, cdt.julianDay));
static assert(__traits(compiles, idt.julianDay));
}
/++
The modified julian day for any time on this Date (since, the modified
julian day changes at midnight).
+/
@property long modJulianDay() const pure nothrow
{
return _date.modJulianDay;
}
unittest
{
assertPred!"=="(DateTime(Date(1858, 11, 17), TimeOfDay(0, 0, 0)).modJulianDay, 0);
assertPred!"=="(DateTime(Date(1858, 11, 17), TimeOfDay(12, 0, 0)).modJulianDay, 0);
assertPred!"=="(DateTime(Date(2010, 8, 24), TimeOfDay(0, 0, 0)).modJulianDay, 55_432);
assertPred!"=="(DateTime(Date(2010, 8, 24), TimeOfDay(12, 0, 0)).modJulianDay, 55_432);
const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
static assert(__traits(compiles, cdt.modJulianDay));
static assert(__traits(compiles, idt.modJulianDay));
}
/++
Converts this DateTime to a string with the format YYYYMMDDTHHMMSS.
Examples:
--------------------
assert(DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)).toISOString() == "20100704T070612");
assert(DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)).toISOString() == "19981225T021500");
assert(DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)).toISOString() == "00000105T230959");
assert(DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)).toISOString() == "-00040105T000002");
--------------------
+/
string toISOString() const nothrow
{
try
return format("%sT%s", _date.toISOString(), _tod.toISOString());
catch(Exception e)
assert(0, "format() threw.");
}
unittest
{
//Test A.D.
assertPred!"=="(DateTime(Date(9, 12, 4), TimeOfDay(0, 0, 0)).toISOString(), "00091204T000000");
assertPred!"=="(DateTime(Date(99, 12, 4), TimeOfDay(5, 6, 12)).toISOString(), "00991204T050612");
assertPred!"=="(DateTime(Date(999, 12, 4), TimeOfDay(13, 44, 59)).toISOString(), "09991204T134459");
assertPred!"=="(DateTime(Date(9999, 7, 4), TimeOfDay(23, 59, 59)).toISOString(), "99990704T235959");
assertPred!"=="(DateTime(Date(10000, 10, 20), TimeOfDay(1, 1, 1)).toISOString(), "+100001020T010101");
//Test B.C.
assertPred!"=="(DateTime(Date(0, 12, 4), TimeOfDay(0, 12, 4)).toISOString(), "00001204T001204");
assertPred!"=="(DateTime(Date(-9, 12, 4), TimeOfDay(0, 0, 0)).toISOString(), "-00091204T000000");
assertPred!"=="(DateTime(Date(-99, 12, 4), TimeOfDay(5, 6, 12)).toISOString(), "-00991204T050612");
assertPred!"=="(DateTime(Date(-999, 12, 4), TimeOfDay(13, 44, 59)).toISOString(), "-09991204T134459");
assertPred!"=="(DateTime(Date(-9999, 7, 4), TimeOfDay(23, 59, 59)).toISOString(), "-99990704T235959");
assertPred!"=="(DateTime(Date(-10000, 10, 20), TimeOfDay(1, 1, 1)).toISOString(), "-100001020T010101");
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(__traits(compiles, cdt.toISOString()));
static assert(__traits(compiles, idt.toISOString()));
//Verify Examples.
assert(DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)).toISOString() == "20100704T070612");
assert(DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)).toISOString() == "19981225T021500");
assert(DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)).toISOString() == "00000105T230959");
assert(DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)).toISOString() == "-00040105T000002");
}
/++
Converts this DateTime to a string with the format YYYY-MM-DDTHH:MM:SS.
Examples:
--------------------
assert(DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)).toISOExtendedString() == "2010-07-04T07:06:12");
assert(DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)).toISOExtendedString() == "1998-12-25T02:15:00");
assert(DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)).toISOExtendedString() == "0000-01-05T23:09:59");
assert(DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)).toISOExtendedString() == "-0004-01-05T00:00:02");
--------------------
+/
string toISOExtendedString() const nothrow
{
try
return format("%sT%s", _date.toISOExtendedString(), _tod.toISOExtendedString());
catch(Exception e)
assert(0, "format() threw.");
}
unittest
{
//Test A.D.
assertPred!"=="(DateTime(Date(9, 12, 4), TimeOfDay(0, 0, 0)).toISOExtendedString(), "0009-12-04T00:00:00");
assertPred!"=="(DateTime(Date(99, 12, 4), TimeOfDay(5, 6, 12)).toISOExtendedString(), "0099-12-04T05:06:12");
assertPred!"=="(DateTime(Date(999, 12, 4), TimeOfDay(13, 44, 59)).toISOExtendedString(), "0999-12-04T13:44:59");
assertPred!"=="(DateTime(Date(9999, 7, 4), TimeOfDay(23, 59, 59)).toISOExtendedString(), "9999-07-04T23:59:59");
assertPred!"=="(DateTime(Date(10000, 10, 20), TimeOfDay(1, 1, 1)).toISOExtendedString(), "+10000-10-20T01:01:01");
//Test B.C.
assertPred!"=="(DateTime(Date(0, 12, 4), TimeOfDay(0, 12, 4)).toISOExtendedString(), "0000-12-04T00:12:04");
assertPred!"=="(DateTime(Date(-9, 12, 4), TimeOfDay(0, 0, 0)).toISOExtendedString(), "-0009-12-04T00:00:00");
assertPred!"=="(DateTime(Date(-99, 12, 4), TimeOfDay(5, 6, 12)).toISOExtendedString(), "-0099-12-04T05:06:12");
assertPred!"=="(DateTime(Date(-999, 12, 4), TimeOfDay(13, 44, 59)).toISOExtendedString(), "-0999-12-04T13:44:59");
assertPred!"=="(DateTime(Date(-9999, 7, 4), TimeOfDay(23, 59, 59)).toISOExtendedString(), "-9999-07-04T23:59:59");
assertPred!"=="(DateTime(Date(-10000, 10, 20), TimeOfDay(1, 1, 1)).toISOExtendedString(), "-10000-10-20T01:01:01");
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(__traits(compiles, cdt.toISOExtendedString()));
static assert(__traits(compiles, idt.toISOExtendedString()));
//Verify Examples.
assert(DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)).toISOExtendedString() == "2010-07-04T07:06:12");
assert(DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)).toISOExtendedString() == "1998-12-25T02:15:00");
assert(DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)).toISOExtendedString() == "0000-01-05T23:09:59");
assert(DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)).toISOExtendedString() == "-0004-01-05T00:00:02");
}
/++
Converts this DateTime to a string with the format YYYY-Mon-DD HH:MM:SS.
Examples:
--------------------
assert(DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)).toSimpleString() == "2010-Jul-04 07:06:12");
assert(DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)).toSimpleString() == "1998-Dec-25 02:15:00");
assert(DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)).toSimpleString() == "0000-Jan-05 23:09:59");
assert(DateTime(Dte(-4, 1, 5), TimeOfDay(0, 0, 2)).toSimpleString() == "-0004-Jan-05 00:00:02");
--------------------
+/
string toSimpleString() const nothrow
{
try
return format("%s %s", _date.toSimpleString(), _tod.toString());
catch(Exception e)
assert(0, "format() threw.");
}
unittest
{
//Test A.D.
assertPred!"=="(DateTime(Date(9, 12, 4), TimeOfDay(0, 0, 0)).toSimpleString(), "0009-Dec-04 00:00:00");
assertPred!"=="(DateTime(Date(99, 12, 4), TimeOfDay(5, 6, 12)).toSimpleString(), "0099-Dec-04 05:06:12");
assertPred!"=="(DateTime(Date(999, 12, 4), TimeOfDay(13, 44, 59)).toSimpleString(), "0999-Dec-04 13:44:59");
assertPred!"=="(DateTime(Date(9999, 7, 4), TimeOfDay(23, 59, 59)).toSimpleString(), "9999-Jul-04 23:59:59");
assertPred!"=="(DateTime(Date(10000, 10, 20), TimeOfDay(1, 1, 1)).toSimpleString(), "+10000-Oct-20 01:01:01");
//Test B.C.
assertPred!"=="(DateTime(Date(0, 12, 4), TimeOfDay(0, 12, 4)).toSimpleString(), "0000-Dec-04 00:12:04");
assertPred!"=="(DateTime(Date(-9, 12, 4), TimeOfDay(0, 0, 0)).toSimpleString(), "-0009-Dec-04 00:00:00");
assertPred!"=="(DateTime(Date(-99, 12, 4), TimeOfDay(5, 6, 12)).toSimpleString(), "-0099-Dec-04 05:06:12");
assertPred!"=="(DateTime(Date(-999, 12, 4), TimeOfDay(13, 44, 59)).toSimpleString(), "-0999-Dec-04 13:44:59");
assertPred!"=="(DateTime(Date(-9999, 7, 4), TimeOfDay(23, 59, 59)).toSimpleString(), "-9999-Jul-04 23:59:59");
assertPred!"=="(DateTime(Date(-10000, 10, 20), TimeOfDay(1, 1, 1)).toSimpleString(), "-10000-Oct-20 01:01:01");
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(__traits(compiles, cdt.toSimpleString()));
static assert(__traits(compiles, idt.toSimpleString()));
//Verify Examples.
assert(DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)).toSimpleString() == "2010-Jul-04 07:06:12");
assert(DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)).toSimpleString() == "1998-Dec-25 02:15:00");
assert(DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)).toSimpleString() == "0000-Jan-05 23:09:59");
assert(DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)).toSimpleString() == "-0004-Jan-05 00:00:02");
}
/+
Converts this DateTime to a string.
+/
//Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
//have versions of toString() with extra modifiers, so we define one version
//with modifiers and one without.
string toString()
{
return toSimpleString();
}
/++
Converts this DateTime to a string.
+/
//Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
//have versions of toString() with extra modifiers, so we define one version
//with modifiers and one without.
string toString() const nothrow
{
return toSimpleString();
}
unittest
{
auto dt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
const cdt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
immutable idt = DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33));
static assert(__traits(compiles, dt.toString()));
static assert(__traits(compiles, cdt.toString()));
static assert(__traits(compiles, idt.toString()));
}
/++
Creates a DateTime from a string with the format YYYYMMDDTHHMMSS.
Whitespace is stripped from the given string.
Params:
isoString = A string formatted in the ISO format for dates and times.
Throws:
DateTimeException if the given string is not in the ISO format or if
the resulting DateTime would not be valid.
Examples:
--------------------
assert(DateTime.fromISOString("20100704T070612") == DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
assert(DateTime.fromISOString("19981225T021500") == DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)));
assert(DateTime.fromISOString("00000105T230959") == DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)));
assert(DateTime.fromISOString("-00040105T000002") == DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)));
assert(DateTime.fromISOString(" 20100704T070612 ") == DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
--------------------
+/
static DateTime fromISOString(S)(in S isoString)
if(isSomeString!S)
{
immutable dstr = to!dstring(strip(isoString));
enforce(dstr.length >= 15, new DateTimeException(format("Invalid ISO String: %s", isoString)));
auto t = dstr.indexOf('T');
enforce(t != -1, new DateTimeException(format("Invalid ISO String: %s", isoString)));
immutable date = Date.fromISOString(dstr[0..t]);
immutable tod = TimeOfDay.fromISOString(dstr[t+1 .. $]);
return DateTime(date, tod);
}
unittest
{
assertThrown!DateTimeException(DateTime.fromISOString(""));
assertThrown!DateTimeException(DateTime.fromISOString("20100704000000"));
assertThrown!DateTimeException(DateTime.fromISOString("20100704 000000"));
assertThrown!DateTimeException(DateTime.fromISOString("20100704t000000"));
assertThrown!DateTimeException(DateTime.fromISOString("20100704T000000."));
assertThrown!DateTimeException(DateTime.fromISOString("20100704T000000.0"));
assertThrown!DateTimeException(DateTime.fromISOString("2010-07-0400:00:00"));
assertThrown!DateTimeException(DateTime.fromISOString("2010-07-04 00:00:00"));
assertThrown!DateTimeException(DateTime.fromISOString("2010-07-04t00:00:00"));
assertThrown!DateTimeException(DateTime.fromISOString("2010-07-04T00:00:00."));
assertThrown!DateTimeException(DateTime.fromISOString("2010-07-04T00:00:00.0"));
assertThrown!DateTimeException(DateTime.fromISOString("2010-Jul-0400:00:00"));
assertThrown!DateTimeException(DateTime.fromISOString("2010-Jul-04 00:00:00"));
assertThrown!DateTimeException(DateTime.fromISOString("2010-Jul-04t00:00:00"));
assertThrown!DateTimeException(DateTime.fromISOString("2010-Jul-04T00:00:00"));
assertThrown!DateTimeException(DateTime.fromISOString("2010-Jul-04 00:00:00."));
assertThrown!DateTimeException(DateTime.fromISOString("2010-Jul-04 00:00:00.0"));
assertThrown!DateTimeException(DateTime.fromISOString("2010-12-22T172201"));
assertThrown!DateTimeException(DateTime.fromISOString("2010-Dec-22 17:22:01"));
assertPred!"=="(DateTime.fromISOString("20101222T172201"), DateTime(Date(2010, 12, 22), TimeOfDay(17, 22, 01)));
assertPred!"=="(DateTime.fromISOString("19990706T123033"), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!"=="(DateTime.fromISOString("-19990706T123033"), DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!"=="(DateTime.fromISOString("+019990706T123033"), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!"=="(DateTime.fromISOString("19990706T123033 "), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!"=="(DateTime.fromISOString(" 19990706T123033"), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!"=="(DateTime.fromISOString(" 19990706T123033 "), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
//Verify Examples.
assert(DateTime.fromISOString("20100704T070612") == DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
assert(DateTime.fromISOString("19981225T021500") == DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)));
assert(DateTime.fromISOString("00000105T230959") == DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)));
assert(DateTime.fromISOString("-00040105T000002") == DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)));
assert(DateTime.fromISOString(" 20100704T070612 ") == DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
}
/++
Creates a DateTime from a string with the format YYYY-MM-DDTHH:MM:SS.
Whitespace is stripped from the given string.
Params:
isoString = A string formatted in the ISO Extended format for dates
and times.
Throws:
DateTimeException if the given string is not in the ISO Extended
format or if the resulting DateTime would not be valid.
Examples:
--------------------
assert(DateTime.fromISOExtendedString("2010-07-04T07:06:12") ==
DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
assert(DateTime.fromISOExtendedString("1998-12-25T02:15:00") ==
DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)));
assert(DateTime.fromISOExtendedString("0000-01-05T23:09:59") ==
DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)));
assert(DateTime.fromISOExtendedString("-0004-01-05T00:00:02") ==
DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)));
assert(DateTime.fromISOExtendedString(" 2010-07-04T07:06:12 ") ==
DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
--------------------
+/
static DateTime fromISOExtendedString(S)(in S isoExtString)
if(isSomeString!(S))
{
immutable dstr = to!dstring(strip(isoExtString));
enforce(dstr.length >= 15, new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
auto t = dstr.indexOf('T');
enforce(t != -1, new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
immutable date = Date.fromISOExtendedString(dstr[0..t]);
immutable tod = TimeOfDay.fromISOExtendedString(dstr[t+1 .. $]);
return DateTime(date, tod);
}
unittest
{
assertThrown!DateTimeException(DateTime.fromISOExtendedString(""));
assertThrown!DateTimeException(DateTime.fromISOExtendedString("20100704000000"));
assertThrown!DateTimeException(DateTime.fromISOExtendedString("20100704 000000"));
assertThrown!DateTimeException(DateTime.fromISOExtendedString("20100704t000000"));
assertThrown!DateTimeException(DateTime.fromISOExtendedString("20100704T000000."));
assertThrown!DateTimeException(DateTime.fromISOExtendedString("20100704T000000.0"));
assertThrown!DateTimeException(DateTime.fromISOExtendedString("2010-07:0400:00:00"));
assertThrown!DateTimeException(DateTime.fromISOExtendedString("2010-07-04 00:00:00"));
assertThrown!DateTimeException(DateTime.fromISOExtendedString("2010-07-04 00:00:00"));
assertThrown!DateTimeException(DateTime.fromISOExtendedString("2010-07-04t00:00:00"));
assertThrown!DateTimeException(DateTime.fromISOExtendedString("2010-07-04T00:00:00."));
assertThrown!DateTimeException(DateTime.fromISOExtendedString("2010-07-04T00:00:00.0"));
assertThrown!DateTimeException(DateTime.fromISOExtendedString("2010-Jul-0400:00:00"));
assertThrown!DateTimeException(DateTime.fromISOExtendedString("2010-Jul-04t00:00:00"));
assertThrown!DateTimeException(DateTime.fromISOExtendedString("2010-Jul-04 00:00:00."));
assertThrown!DateTimeException(DateTime.fromISOExtendedString("2010-Jul-04 00:00:00.0"));
assertThrown!DateTimeException(DateTime.fromISOExtendedString("20101222T172201"));
assertThrown!DateTimeException(DateTime.fromISOExtendedString("2010-Dec-22 17:22:01"));
assertPred!"=="(DateTime.fromISOExtendedString("2010-12-22T17:22:01"), DateTime(Date(2010, 12, 22), TimeOfDay(17, 22, 01)));
assertPred!"=="(DateTime.fromISOExtendedString("1999-07-06T12:30:33"), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!"=="(DateTime.fromISOExtendedString("-1999-07-06T12:30:33"), DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!"=="(DateTime.fromISOExtendedString("+01999-07-06T12:30:33"), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!"=="(DateTime.fromISOExtendedString("1999-07-06T12:30:33 "), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!"=="(DateTime.fromISOExtendedString(" 1999-07-06T12:30:33"), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!"=="(DateTime.fromISOExtendedString(" 1999-07-06T12:30:33 "), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
//Verify Examples.
assert(DateTime.fromISOExtendedString("2010-07-04T07:06:12") == DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
assert(DateTime.fromISOExtendedString("1998-12-25T02:15:00") == DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)));
assert(DateTime.fromISOExtendedString("0000-01-05T23:09:59") == DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)));
assert(DateTime.fromISOExtendedString("-0004-01-05T00:00:02") == DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)));
assert(DateTime.fromISOExtendedString(" 2010-07-04T07:06:12 ") == DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
}
/++
Creates a DateTime from a string with the format YYYY-Mon-DD HH:MM:SS.
Whitespace is stripped from the given string.
Params:
simpleString = A string formatted in the way that toSimpleString()
formats dates and times.
Throws:
DateTimeException if the given string is not in the correct format or if
the resulting DateTime would not be valid.
Examples:
--------------------
assert(DateTime.fromSimpleString("2010-Jul-04 07:06:12") ==
DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
assert(DateTime.fromSimpleString("1998-Dec-25 02:15:00") ==
DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)));
assert(DateTime.fromSimpleString("0000-Jan-05 23:09:59") ==
DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)));
assert(DateTime.fromSimpleString("-0004-Jan-05 00:00:02") ==
DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)));
assert(DateTime.fromSimpleString(" 2010-Jul-04 07:06:12 ") ==
DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
--------------------
+/
static DateTime fromSimpleString(S)(in S simpleString)
if(isSomeString!(S))
{
immutable dstr = to!dstring(strip(simpleString));
enforce(dstr.length >= 15, new DateTimeException(format("Invalid string format: %s", simpleString)));
auto t = dstr.indexOf(' ');
enforce(t != -1, new DateTimeException(format("Invalid string format: %s", simpleString)));
immutable date = Date.fromSimpleString(dstr[0..t]);
immutable tod = TimeOfDay.fromISOExtendedString(dstr[t+1 .. $]);
return DateTime(date, tod);
}
unittest
{
assertThrown!DateTimeException(DateTime.fromISOString(""));
assertThrown!DateTimeException(DateTime.fromISOString("20100704000000"));
assertThrown!DateTimeException(DateTime.fromISOString("20100704 000000"));
assertThrown!DateTimeException(DateTime.fromISOString("20100704t000000"));
assertThrown!DateTimeException(DateTime.fromISOString("20100704T000000."));
assertThrown!DateTimeException(DateTime.fromISOString("20100704T000000.0"));
assertThrown!DateTimeException(DateTime.fromISOString("2010-07-0400:00:00"));
assertThrown!DateTimeException(DateTime.fromISOString("2010-07-04 00:00:00"));
assertThrown!DateTimeException(DateTime.fromISOString("2010-07-04t00:00:00"));
assertThrown!DateTimeException(DateTime.fromISOString("2010-07-04T00:00:00."));
assertThrown!DateTimeException(DateTime.fromISOString("2010-07-04T00:00:00.0"));
assertThrown!DateTimeException(DateTime.fromISOString("2010-Jul-0400:00:00"));
assertThrown!DateTimeException(DateTime.fromISOString("2010-Jul-04 00:00:00"));
assertThrown!DateTimeException(DateTime.fromISOString("2010-Jul-04t00:00:00"));
assertThrown!DateTimeException(DateTime.fromISOString("2010-Jul-04T00:00:00"));
assertThrown!DateTimeException(DateTime.fromISOString("2010-Jul-04 00:00:00."));
assertThrown!DateTimeException(DateTime.fromISOString("2010-Jul-04 00:00:00.0"));
assertThrown!DateTimeException(DateTime.fromSimpleString("20101222T172201"));
assertThrown!DateTimeException(DateTime.fromSimpleString("2010-12-22T172201"));
assertPred!"=="(DateTime.fromSimpleString("2010-Dec-22 17:22:01"), DateTime(Date(2010, 12, 22), TimeOfDay(17, 22, 01)));
assertPred!"=="(DateTime.fromSimpleString("1999-Jul-06 12:30:33"), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!"=="(DateTime.fromSimpleString("-1999-Jul-06 12:30:33"), DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!"=="(DateTime.fromSimpleString("+01999-Jul-06 12:30:33"), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!"=="(DateTime.fromSimpleString("1999-Jul-06 12:30:33 "), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!"=="(DateTime.fromSimpleString(" 1999-Jul-06 12:30:33"), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
assertPred!"=="(DateTime.fromSimpleString(" 1999-Jul-06 12:30:33 "), DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33)));
//Verify Examples.
assert(DateTime.fromSimpleString("2010-Jul-04 07:06:12") == DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
assert(DateTime.fromSimpleString("1998-Dec-25 02:15:00") == DateTime(Date(1998, 12, 25), TimeOfDay(2, 15, 0)));
assert(DateTime.fromSimpleString("0000-Jan-05 23:09:59") == DateTime(Date(0, 1, 5), TimeOfDay(23, 9, 59)));
assert(DateTime.fromSimpleString("-0004-Jan-05 00:00:02") == DateTime(Date(-4, 1, 5), TimeOfDay(0, 0, 2)));
assert(DateTime.fromSimpleString(" 2010-Jul-04 07:06:12 ") == DateTime(Date(2010, 7, 4), TimeOfDay(7, 6, 12)));
}
//TODO Add function which takes a user-specified time format and produces a DateTime
//TODO Add function which takes pretty much any time-string and produces a DateTime
// Obviously, it will be less efficient, and it probably won't manage _every_
// possible date format, but a smart conversion function would be nice.
/++
Returns the DateTime farthest in the past which is representable by DateTime.
+/
@property static DateTime min() pure nothrow
out(result)
{
assert(result._date == Date.min);
assert(result._tod == TimeOfDay.min);
}
body
{
auto dt = DateTime.init;
dt._date._year = short.min;
dt._date._month = Month.jan;
dt._date._day = 1;
return dt;
}
unittest
{
assert(DateTime.min.year < 0);
assert(DateTime.min < DateTime.max);
}
/++
Returns the DateTime farthest in the future which is representable by DateTime.
+/
@property static DateTime max() pure nothrow
out(result)
{
assert(result._date == Date.max);
assert(result._tod == TimeOfDay.max);
}
body
{
auto dt = DateTime.init;
dt._date._year = short.max;
dt._date._month = Month.dec;
dt._date._day = 31;
dt._tod._hour = TimeOfDay.maxHour;
dt._tod._minute = TimeOfDay.maxMinute;
dt._tod._second = TimeOfDay.maxSecond;
return dt;
}
unittest
{
assert(DateTime.max.year > 0);
assert(DateTime.max > DateTime.min);
}
private:
/++
Add seconds to the time of day. Negative values will subtract. If the
number of seconds overflows (or underflows), then the seconds will wrap,
increasing (or decreasing) the number of minutes accordingly. The
same goes for any larger units.
Params:
seconds = The number of seconds to add to this DateTime.
+/
ref DateTime addSeconds(long seconds) pure nothrow
{
long hnsecs = convert!("seconds", "hnsecs")(seconds);
hnsecs += convert!("hours", "hnsecs")(_tod._hour);
hnsecs += convert!("minutes", "hnsecs")(_tod._minute);
hnsecs += convert!("seconds", "hnsecs")(_tod._second);
auto days = splitUnitsFromHNSecs!"days"(hnsecs);
if(hnsecs < 0)
{
hnsecs += convert!("days", "hnsecs")(1);
--days;
}
_date.addDays(days);
immutable newHours = splitUnitsFromHNSecs!"hours"(hnsecs);
immutable newMinutes = splitUnitsFromHNSecs!"minutes"(hnsecs);
immutable newSeconds = splitUnitsFromHNSecs!"seconds"(hnsecs);
_tod._hour = cast(ubyte)newHours;
_tod._minute = cast(ubyte)newMinutes;
_tod._second = cast(ubyte)newSeconds;
return this;
}
unittest
{
static void testDT(DateTime orig, int seconds, in DateTime expected, size_t line = __LINE__)
{
orig.addSeconds(seconds);
assertPred!"=="(orig, expected, "", __FILE__, line);
}
//Test A.D.
testDT(DateTime(1999, 7, 6, 12, 30, 33), 0, DateTime(1999, 7, 6, 12, 30, 33));
testDT(DateTime(1999, 7, 6, 12, 30, 33), 1, DateTime(1999, 7, 6, 12, 30, 34));
testDT(DateTime(1999, 7, 6, 12, 30, 33), 2, DateTime(1999, 7, 6, 12, 30, 35));
testDT(DateTime(1999, 7, 6, 12, 30, 33), 3, DateTime(1999, 7, 6, 12, 30, 36));
testDT(DateTime(1999, 7, 6, 12, 30, 33), 4, DateTime(1999, 7, 6, 12, 30, 37));
testDT(DateTime(1999, 7, 6, 12, 30, 33), 5, DateTime(1999, 7, 6, 12, 30, 38));
testDT(DateTime(1999, 7, 6, 12, 30, 33), 10, DateTime(1999, 7, 6, 12, 30, 43));
testDT(DateTime(1999, 7, 6, 12, 30, 33), 15, DateTime(1999, 7, 6, 12, 30, 48));
testDT(DateTime(1999, 7, 6, 12, 30, 33), 26, DateTime(1999, 7, 6, 12, 30, 59));
testDT(DateTime(1999, 7, 6, 12, 30, 33), 27, DateTime(1999, 7, 6, 12, 31, 0));
testDT(DateTime(1999, 7, 6, 12, 30, 33), 30, DateTime(1999, 7, 6, 12, 31, 3));
testDT(DateTime(1999, 7, 6, 12, 30, 33), 59, DateTime(1999, 7, 6, 12, 31, 32));
testDT(DateTime(1999, 7, 6, 12, 30, 33), 60, DateTime(1999, 7, 6, 12, 31, 33));
testDT(DateTime(1999, 7, 6, 12, 30, 33), 61, DateTime(1999, 7, 6, 12, 31, 34));
testDT(DateTime(1999, 7, 6, 12, 30, 33), 1766, DateTime(1999, 7, 6, 12, 59, 59));
testDT(DateTime(1999, 7, 6, 12, 30, 33), 1767, DateTime(1999, 7, 6, 13, 0, 0));
testDT(DateTime(1999, 7, 6, 12, 30, 33), 1768, DateTime(1999, 7, 6, 13, 0, 1));
testDT(DateTime(1999, 7, 6, 12, 30, 33), 2007, DateTime(1999, 7, 6, 13, 4, 0));
testDT(DateTime(1999, 7, 6, 12, 30, 33), 3599, DateTime(1999, 7, 6, 13, 30, 32));
testDT(DateTime(1999, 7, 6, 12, 30, 33), 3600, DateTime(1999, 7, 6, 13, 30, 33));
testDT(DateTime(1999, 7, 6, 12, 30, 33), 3601, DateTime(1999, 7, 6, 13, 30, 34));
testDT(DateTime(1999, 7, 6, 12, 30, 33), 7200, DateTime(1999, 7, 6, 14, 30, 33));
testDT(DateTime(1999, 7, 6, 23, 0, 0), 432_123, DateTime(1999, 7, 11, 23, 2, 3));
testDT(DateTime(1999, 7, 6, 12, 30, 33), -1, DateTime(1999, 7, 6, 12, 30, 32));
testDT(DateTime(1999, 7, 6, 12, 30, 33), -2, DateTime(1999, 7, 6, 12, 30, 31));
testDT(DateTime(1999, 7, 6, 12, 30, 33), -3, DateTime(1999, 7, 6, 12, 30, 30));
testDT(DateTime(1999, 7, 6, 12, 30, 33), -4, DateTime(1999, 7, 6, 12, 30, 29));
testDT(DateTime(1999, 7, 6, 12, 30, 33), -5, DateTime(1999, 7, 6, 12, 30, 28));
testDT(DateTime(1999, 7, 6, 12, 30, 33), -10, DateTime(1999, 7, 6, 12, 30, 23));
testDT(DateTime(1999, 7, 6, 12, 30, 33), -15, DateTime(1999, 7, 6, 12, 30, 18));
testDT(DateTime(1999, 7, 6, 12, 30, 33), -33, DateTime(1999, 7, 6, 12, 30, 0));
testDT(DateTime(1999, 7, 6, 12, 30, 33), -34, DateTime(1999, 7, 6, 12, 29, 59));
testDT(DateTime(1999, 7, 6, 12, 30, 33), -35, DateTime(1999, 7, 6, 12, 29, 58));
testDT(DateTime(1999, 7, 6, 12, 30, 33), -59, DateTime(1999, 7, 6, 12, 29, 34));
testDT(DateTime(1999, 7, 6, 12, 30, 33), -60, DateTime(1999, 7, 6, 12, 29, 33));
testDT(DateTime(1999, 7, 6, 12, 30, 33), -61, DateTime(1999, 7, 6, 12, 29, 32));
testDT(DateTime(1999, 7, 6, 12, 30, 33), -1833, DateTime(1999, 7, 6, 12, 0, 0));
testDT(DateTime(1999, 7, 6, 12, 30, 33), -1834, DateTime(1999, 7, 6, 11, 59, 59));
testDT(DateTime(1999, 7, 6, 12, 30, 33), -3600, DateTime(1999, 7, 6, 11, 30, 33));
testDT(DateTime(1999, 7, 6, 12, 30, 33), -3601, DateTime(1999, 7, 6, 11, 30, 32));
testDT(DateTime(1999, 7, 6, 12, 30, 33), -5134, DateTime(1999, 7, 6, 11, 4, 59));
testDT(DateTime(1999, 7, 6, 23, 0, 0), -432_123, DateTime(1999, 7, 1, 22, 57, 57));
testDT(DateTime(1999, 7, 6, 12, 30, 0), 1, DateTime(1999, 7, 6, 12, 30, 1));
testDT(DateTime(1999, 7, 6, 12, 30, 0), 0, DateTime(1999, 7, 6, 12, 30, 0));
testDT(DateTime(1999, 7, 6, 12, 30, 0), -1, DateTime(1999, 7, 6, 12, 29, 59));
testDT(DateTime(1999, 7, 6, 12, 0, 0), 1, DateTime(1999, 7, 6, 12, 0, 1));
testDT(DateTime(1999, 7, 6, 12, 0, 0), 0, DateTime(1999, 7, 6, 12, 0, 0));
testDT(DateTime(1999, 7, 6, 12, 0, 0), -1, DateTime(1999, 7, 6, 11, 59, 59));
testDT(DateTime(1999, 7, 6, 0, 0, 0), 1, DateTime(1999, 7, 6, 0, 0, 1));
testDT(DateTime(1999, 7, 6, 0, 0, 0), 0, DateTime(1999, 7, 6, 0, 0, 0));
testDT(DateTime(1999, 7, 6, 0, 0, 0), -1, DateTime(1999, 7, 5, 23, 59, 59));
testDT(DateTime(1999, 7, 5, 23, 59, 59), 1, DateTime(1999, 7, 6, 0, 0, 0));
testDT(DateTime(1999, 7, 5, 23, 59, 59), 0, DateTime(1999, 7, 5, 23, 59, 59));
testDT(DateTime(1999, 7, 5, 23, 59, 59), -1, DateTime(1999, 7, 5, 23, 59, 58));
testDT(DateTime(1998, 12, 31, 23, 59, 59), 1, DateTime(1999, 1, 1, 0, 0, 0));
testDT(DateTime(1998, 12, 31, 23, 59, 59), 0, DateTime(1998, 12, 31, 23, 59, 59));
testDT(DateTime(1998, 12, 31, 23, 59, 59), -1, DateTime(1998, 12, 31, 23, 59, 58));
testDT(DateTime(1998, 1, 1, 0, 0, 0), 1, DateTime(1998, 1, 1, 0, 0, 1));
testDT(DateTime(1998, 1, 1, 0, 0, 0), 0, DateTime(1998, 1, 1, 0, 0, 0));
testDT(DateTime(1998, 1, 1, 0, 0, 0), -1, DateTime(1997, 12, 31, 23, 59, 59));
//Test B.C.
testDT(DateTime(-1999, 7, 6, 12, 30, 33), 0, DateTime(-1999, 7, 6, 12, 30, 33));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), 1, DateTime(-1999, 7, 6, 12, 30, 34));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), 2, DateTime(-1999, 7, 6, 12, 30, 35));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), 3, DateTime(-1999, 7, 6, 12, 30, 36));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), 4, DateTime(-1999, 7, 6, 12, 30, 37));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), 5, DateTime(-1999, 7, 6, 12, 30, 38));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), 10, DateTime(-1999, 7, 6, 12, 30, 43));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), 15, DateTime(-1999, 7, 6, 12, 30, 48));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), 26, DateTime(-1999, 7, 6, 12, 30, 59));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), 27, DateTime(-1999, 7, 6, 12, 31, 0));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), 30, DateTime(-1999, 7, 6, 12, 31, 3));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), 59, DateTime(-1999, 7, 6, 12, 31, 32));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), 60, DateTime(-1999, 7, 6, 12, 31, 33));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), 61, DateTime(-1999, 7, 6, 12, 31, 34));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), 1766, DateTime(-1999, 7, 6, 12, 59, 59));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), 1767, DateTime(-1999, 7, 6, 13, 0, 0));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), 1768, DateTime(-1999, 7, 6, 13, 0, 1));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), 2007, DateTime(-1999, 7, 6, 13, 4, 0));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), 3599, DateTime(-1999, 7, 6, 13, 30, 32));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), 3600, DateTime(-1999, 7, 6, 13, 30, 33));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), 3601, DateTime(-1999, 7, 6, 13, 30, 34));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), 7200, DateTime(-1999, 7, 6, 14, 30, 33));
testDT(DateTime(-1999, 7, 6, 23, 0, 0), 432_123, DateTime(-1999, 7, 11, 23, 2, 3));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), -1, DateTime(-1999, 7, 6, 12, 30, 32));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), -2, DateTime(-1999, 7, 6, 12, 30, 31));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), -3, DateTime(-1999, 7, 6, 12, 30, 30));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), -4, DateTime(-1999, 7, 6, 12, 30, 29));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), -5, DateTime(-1999, 7, 6, 12, 30, 28));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), -10, DateTime(-1999, 7, 6, 12, 30, 23));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), -15, DateTime(-1999, 7, 6, 12, 30, 18));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), -33, DateTime(-1999, 7, 6, 12, 30, 0));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), -34, DateTime(-1999, 7, 6, 12, 29, 59));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), -35, DateTime(-1999, 7, 6, 12, 29, 58));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), -59, DateTime(-1999, 7, 6, 12, 29, 34));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), -60, DateTime(-1999, 7, 6, 12, 29, 33));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), -61, DateTime(-1999, 7, 6, 12, 29, 32));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), -1833, DateTime(-1999, 7, 6, 12, 0, 0));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), -1834, DateTime(-1999, 7, 6, 11, 59, 59));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), -3600, DateTime(-1999, 7, 6, 11, 30, 33));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), -3601, DateTime(-1999, 7, 6, 11, 30, 32));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), -5134, DateTime(-1999, 7, 6, 11, 4, 59));
testDT(DateTime(-1999, 7, 6, 12, 30, 33), -7200, DateTime(-1999, 7, 6, 10, 30, 33));
testDT(DateTime(-1999, 7, 6, 23, 0, 0), -432_123, DateTime(-1999, 7, 1, 22, 57, 57));
testDT(DateTime(-1999, 7, 6, 12, 30, 0), 1, DateTime(-1999, 7, 6, 12, 30, 1));
testDT(DateTime(-1999, 7, 6, 12, 30, 0), 0, DateTime(-1999, 7, 6, 12, 30, 0));
testDT(DateTime(-1999, 7, 6, 12, 30, 0), -1, DateTime(-1999, 7, 6, 12, 29, 59));
testDT(DateTime(-1999, 7, 6, 12, 0, 0), 1, DateTime(-1999, 7, 6, 12, 0, 1));
testDT(DateTime(-1999, 7, 6, 12, 0, 0), 0, DateTime(-1999, 7, 6, 12, 0, 0));
testDT(DateTime(-1999, 7, 6, 12, 0, 0), -1, DateTime(-1999, 7, 6, 11, 59, 59));
testDT(DateTime(-1999, 7, 6, 0, 0, 0), 1, DateTime(-1999, 7, 6, 0, 0, 1));
testDT(DateTime(-1999, 7, 6, 0, 0, 0), 0, DateTime(-1999, 7, 6, 0, 0, 0));
testDT(DateTime(-1999, 7, 6, 0, 0, 0), -1, DateTime(-1999, 7, 5, 23, 59, 59));
testDT(DateTime(-1999, 7, 5, 23, 59, 59), 1, DateTime(-1999, 7, 6, 0, 0, 0));
testDT(DateTime(-1999, 7, 5, 23, 59, 59), 0, DateTime(-1999, 7, 5, 23, 59, 59));
testDT(DateTime(-1999, 7, 5, 23, 59, 59), -1, DateTime(-1999, 7, 5, 23, 59, 58));
testDT(DateTime(-2000, 12, 31, 23, 59, 59), 1, DateTime(-1999, 1, 1, 0, 0, 0));
testDT(DateTime(-2000, 12, 31, 23, 59, 59), 0, DateTime(-2000, 12, 31, 23, 59, 59));
testDT(DateTime(-2000, 12, 31, 23, 59, 59), -1, DateTime(-2000, 12, 31, 23, 59, 58));
testDT(DateTime(-2000, 1, 1, 0, 0, 0), 1, DateTime(-2000, 1, 1, 0, 0, 1));
testDT(DateTime(-2000, 1, 1, 0, 0, 0), 0, DateTime(-2000, 1, 1, 0, 0, 0));
testDT(DateTime(-2000, 1, 1, 0, 0, 0), -1, DateTime(-2001, 12, 31, 23, 59, 59));
//Test Both
testDT(DateTime(1, 1, 1, 0, 0, 0), -1, DateTime(0, 12, 31, 23, 59, 59));
testDT(DateTime(0, 12, 31, 23, 59, 59), 1, DateTime(1, 1, 1, 0, 0, 0));
testDT(DateTime(0, 1, 1, 0, 0, 0), -1, DateTime(-1, 12, 31, 23, 59, 59));
testDT(DateTime(-1, 12, 31, 23, 59, 59), 1, DateTime(0, 1, 1, 0, 0, 0));
testDT(DateTime(-1, 1, 1, 11, 30, 33), 63_165_600L, DateTime(1, 1, 1, 13, 30, 33));
testDT(DateTime(1, 1, 1, 13, 30, 33), -63_165_600L, DateTime(-1, 1, 1, 11, 30, 33));
testDT(DateTime(-1, 1, 1, 11, 30, 33), 63_165_617L, DateTime(1, 1, 1, 13, 30, 50));
testDT(DateTime(1, 1, 1, 13, 30, 50), -63_165_617L, DateTime(-1, 1, 1, 11, 30, 33));
const cdt = DateTime(1999, 7, 6, 12, 30, 33);
immutable idt = DateTime(1999, 7, 6, 12, 30, 33);
static assert(!__traits(compiles, cdt.addSeconds(4)));
static assert(!__traits(compiles, idt.addSeconds(4)));
}
Date _date;
TimeOfDay _tod;
}
/++
SysTime is the type used when you want to get the current time from the system
or if you're doing anything that involves time zones. Unlike DateTime, time
zone is an integral part of SysTime (though if all you care about is local
time, you can pretty much ignore time zones, 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 DateTime, it is not optimized
for calendar operations, and getting individual units from it such as years
or days is going to involve conversions and be less efficient.
Basically, if you care about calendar operations and don't necessarily care
about time zones, then DateTime would be the type to use. However, if what
you care about is the system time, then SysTime is the type to use.
$(D Clock.currTime()) will return the current time as a SysTime. If you want
to convert a SysTime to a Date or DateTime, simply cast it. And if you ever
want to convert a Date or DateTime to a SysTime, use SysTime's constructor,
and you can pass in the intended time zone with it (or don't pass in a
TimeZone, and the local time zone will be used).
If you care about using time zones other than local time or UTC, you can use
PosixTimeZone on Posix systems (or on Windows, if you provide the TZ database
files), and you can use WindowsTimeZone on Windows systems. The time in SysTime
is kept internally in hnsecs from midnight, January 1st, 1 A.D. UTC. So, you
never get conversion errors when changing the time zone of a SysTime (since,
if the hnecs were kept in local time, DST would cause problems with conversions).
LocalTime is the TimeZone class which represents the local time, and UTC is the
TimeZone class which represents UTC. SysTime uses LocalTime if no TimeZone is
provided. For more details on time zones, look at the documentation for
TimeZone, PosixTimeZone, and WindowsTimeZone.
SysTime's range is from approximately 29,000 B.C. to 29,000 A.D.
+/
struct SysTime
{
public:
/++
Params:
dateTime = The DateTime to use to set this SysTime's internal std
time. As DateTime has no concept of time zone, tz is used
as its time zone.
tz = The TimeZone to use for this SysTime. If null, LocalTime
will be used. The given DateTime is assumed to be in the
given time zone.
+/
this(in DateTime dateTime, immutable TimeZone tz = null) nothrow
{
try
this(dateTime, FracSec.from!"hnsecs"(0), tz);
catch(Exception e)
assert(0, "FracSec's constructor threw when it shouldn't have.");
}
unittest
{
assertPred!"=="(SysTime(DateTime.init, UTC())._stdTime, 0);
assertPred!"=="(SysTime(DateTime(1, 1, 1, 12, 30, 33), UTC())._stdTime, 450_330_000_000L);
assertPred!"=="(SysTime(DateTime(0, 12, 31, 12, 30, 33), UTC())._stdTime, -413_670_000_000L);
assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0), UTC())._stdTime, 0);
assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 1), UTC())._stdTime, 10_000_000L);
assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), UTC())._stdTime, -10_000_000L);
assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0), new SimpleTimeZone(-60)).stdTime, 36_000_000_000L);
assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0), new SimpleTimeZone(0)).stdTime, 0);
assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0), new SimpleTimeZone(60)).stdTime, -36_000_000_000L);
}
/++
Params:
dateTime = The DateTime to use to set this SysTime's internal std time.
As DateTime has no concept of time zone, tz is used as its
time zone.
fsec = The fractional seconds portion of the time.
tz = The TimeZone to use for this SysTime. If null, LocalTime will
be used. The given DateTime is assumed to be in the given
time zone.
+/
this(in DateTime dateTime, in FracSec fsec, immutable TimeZone tz = null) nothrow
{
if(tz is null)
_timezone = LocalTime();
else
_timezone = tz;
try
{
immutable dateDiff = (dateTime.date - Date(1, 1, 1)).total!"hnsecs";
immutable todDiff = (dateTime.timeOfDay - TimeOfDay(0, 0, 0)).total!"hnsecs";
immutable adjustedTime = dateDiff + todDiff + fsec.hnsecs;
immutable standardTime = _timezone.tzToUTC(adjustedTime);
this(standardTime, _timezone.get);
}
catch(Exception e)
assert(0, "Date, TimeOfDay, or DateTime's constructor threw when it shouldn't have.");
}
unittest
{
assertPred!"=="(SysTime(DateTime.init, FracSec.init, UTC())._stdTime, 0);
assertPred!"=="(SysTime(DateTime(1, 1, 1, 12, 30, 33), FracSec.init, UTC())._stdTime, 450_330_000_000L);
assertPred!"=="(SysTime(DateTime(0, 12, 31, 12, 30, 33), FracSec.init, UTC())._stdTime, -413_670_000_000L);
assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(1), UTC())._stdTime, 10_000L);
assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"msecs"(999), UTC())._stdTime, -10_000L);
assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999), UTC()).stdTime, -1);
assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1), UTC()).stdTime, -9_999_999);
assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0), UTC()).stdTime, -10_000_000);
}
/++
Params:
date = The Date to use to set this SysTime's internal std time.
As Date has no concept of time zone, tz is used as its
time zone.
tz = The TimeZone to use for this SysTime. If null, LocalTime will
be used. The given Date is assumed to be in the given time zone.
+/
this(in Date date, immutable TimeZone tz = null) nothrow
{
if(tz is null)
_timezone = LocalTime();
else
_timezone = tz;
try
{
immutable adjustedTime = (date - Date(1, 1, 1)).total!"hnsecs";
immutable standardTime = _timezone.tzToUTC(adjustedTime);
this(standardTime, _timezone.get);
}
catch(Exception e)
assert(0, "Date's constructor through when it shouldn't have");
}
unittest
{
assertPred!"=="(SysTime(Date.init, UTC())._stdTime, 0);
assertPred!"=="(SysTime(Date(1, 1, 1), UTC())._stdTime, 0);
assertPred!"=="(SysTime(Date(1, 1, 2), UTC())._stdTime, 864000000000);
assertPred!"=="(SysTime(Date(0, 12, 31), UTC())._stdTime, -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 TimeZone to use for this SysTime. If null, LocalTime will be used.
+/
this(long stdTime, immutable TimeZone tz = null) pure nothrow
{
_stdTime = stdTime;
if(tz is null)
_timezone = LocalTime();
else
_timezone = tz;
}
unittest
{
assertPred!"=="(SysTime(0)._stdTime, 0);
}
/++
Params:
rhs = The SysTime to assign to this one.
+/
ref SysTime opAssign(const ref SysTime rhs) pure nothrow
{
_stdTime = rhs._stdTime;
_timezone = rhs._timezone.get;
return this;
}
/++
Params:
rhs = The SysTime to assign to this one.
+/
ref SysTime opAssign(SysTime rhs) pure nothrow
{
_stdTime = rhs._stdTime;
_timezone = rhs._timezone.get;
return this;
}
/++
Checks for equality between this SysTime and the given
SysTime.
Note that the time zone is ignored. Only the internal
std times (which are in UTC) are compared.
+/
bool opEquals(const ref SysTime rhs) const pure nothrow
{
return _stdTime == rhs._stdTime;
}
unittest
{
auto a = SysTime(DateTime.init, UTC());
auto b = SysTime(0, UTC());
assert(a == b);
assertPred!"=="(a, b);
assertPred!"=="(SysTime(DateTime.init, UTC()), SysTime(0, UTC()));
assertPred!"=="(SysTime(Date.init, UTC()), SysTime(0, UTC()));
assertPred!"=="(SysTime(0), SysTime(0));
assertPred!"=="(SysTime(Date(1999, 1, 1)), SysTime(Date(1999, 1, 1)));
assertPred!"=="(SysTime(Date(1999, 1, 1)), SysTime(Date(1999, 1, 1)));
assertPred!"=="(SysTime(Date(1, 7, 1)), SysTime(Date(1, 7, 1)));
assertPred!"=="(SysTime(Date(1, 1, 6)), SysTime(Date(1, 1, 6)));
assertPred!"=="(SysTime(Date(1999, 7, 1)), SysTime(Date(1999, 7, 1)));
assertPred!"=="(SysTime(Date(1999, 7, 6)), SysTime(Date(1999, 7, 6)));
assertPred!"=="(SysTime(Date(1, 7, 6)), SysTime(Date(1, 7, 6)));
assertPred!"=="(SysTime(DateTime(1999, 1, 1, 0, 0, 0)), SysTime(Date(1999, 1, 1)));
assertPred!"=="(SysTime(Date(1999, 1, 1)), SysTime(DateTime(1999, 1, 1, 0, 0, 0)));
assertPred!"!="(SysTime(DateTime(1999, 1, 1, 11, 30, 20)), SysTime(Date(1999, 1, 1)));
assertPred!"!="(SysTime(Date(1999, 1, 1)), SysTime(DateTime(1999, 1, 1, 11, 30, 20)));
assertPred!"=="(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0))));
assertPred!"=="(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 0))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 0))));
assertPred!"=="(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 0))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 0))));
assertPred!"=="(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33))));
assertPred!"=="(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0))));
assertPred!"=="(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))));
assertPred!"=="(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33))));
assertPred!"=="(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33))));
{
auto sysUTC = SysTime(Date(1999, 1, 1));
sysUTC.timezone = UTC();
auto sysLocal = SysTime(Date(1999, 1, 1));
sysUTC.timezone = LocalTime();
assertPred!"=="(sysUTC, sysLocal);
assertPred!"=="(sysLocal, sysUTC);
assertPred!"!="(SysTime(Date(1999, 1, 1), UTC()), SysTime(Date(1999, 1, 1), LocalTime()));
assertPred!"!="(SysTime(Date(1999, 7, 1), LocalTime()), SysTime(Date(1999, 7, 1), UTC()));
}
{
auto sysUTC = SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)));
sysUTC.timezone = UTC();
auto sysSimple = SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)));
sysSimple.timezone = new SimpleTimeZone(-360);
assertPred!"=="(sysUTC, sysSimple);
assertPred!"=="(sysSimple, sysUTC);
assertPred!"!="(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), UTC()),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), sysSimple.timezone));
assertPred!"!="(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), sysSimple.timezone),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), UTC()));
}
{
auto sysUTC = SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), UTC());
auto sysSimple = SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), new SimpleTimeZone(240));
assertPred!"!="(sysUTC, sysSimple);
assertPred!"!="(sysSimple, sysUTC);
sysUTC = SysTime(DateTime(Date(1999, 7, 5), TimeOfDay(20, 0, 0)), UTC());
assertPred!"=="(sysUTC, sysSimple);
assertPred!"=="(sysSimple, sysUTC);
}
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));
static assert(__traits(compiles, st == st));
static assert(__traits(compiles, st == cst));
//static assert(__traits(compiles, st == ist));
static assert(__traits(compiles, cst == st));
static assert(__traits(compiles, cst == cst));
//static assert(__traits(compiles, cst == ist));
//static assert(__traits(compiles, ist == st));
//static assert(__traits(compiles, ist == cst));
//static assert(__traits(compiles, ist == ist));
}
/++
Compares this SysTime with the given SysTime.
Time zone is irrelevant to comparing SysTimes.
Returns:
$(TABLE
$(TR $(TD this < rhs) $(TD < 0))
$(TR $(TD this == rhs) $(TD 0))
$(TR $(TD this > rhs) $(TD > 0))
)
+/
int opCmp(in SysTime rhs) const pure nothrow
{
if(_stdTime < rhs._stdTime)
return -1;
if(_stdTime > rhs._stdTime)
return 1;
return 0;
}
unittest
{
//Test A.D.
assertPred!("opCmp", "==")(SysTime(DateTime.init, UTC()), SysTime(0));
assertPred!("opCmp", "==")(SysTime(Date.init, UTC()), SysTime(0));
assertPred!("opCmp", "==")(SysTime(Date(1999, 1, 1)), SysTime(Date(1999, 1, 1)));
assertPred!("opCmp", "==")(SysTime(Date(1999, 1, 1)), SysTime(Date(1999, 1, 1)));
assertPred!("opCmp", "==")(SysTime(Date(1, 7, 1)), SysTime(Date(1, 7, 1)));
assertPred!("opCmp", "==")(SysTime(Date(1, 1, 6)), SysTime(Date(1, 1, 6)));
assertPred!("opCmp", "==")(SysTime(Date(1999, 7, 1)), SysTime(Date(1999, 7, 1)));
assertPred!("opCmp", "==")(SysTime(Date(1999, 7, 6)), SysTime(Date(1999, 7, 6)));
assertPred!("opCmp", "==")(SysTime(Date(1, 7, 6)), SysTime(Date(1, 7, 6)));
assertPred!("opCmp", ">")(SysTime(DateTime(1999, 1, 1, 11, 30, 20)), SysTime(Date(1999, 1, 1)));
assertPred!("opCmp", "<")(SysTime(Date(1999, 1, 1)), SysTime(DateTime(1999, 1, 1, 11, 30, 20)));
assertPred!("opCmp", "<")(SysTime(Date(1999, 7, 6)), SysTime(Date(2000, 7, 6)));
assertPred!("opCmp", ">")(SysTime(Date(2000, 7, 6)), SysTime(Date(1999, 7, 6)));
assertPred!("opCmp", "<")(SysTime(Date(1999, 7, 6)), SysTime(Date(1999, 8, 6)));
assertPred!("opCmp", ">")(SysTime(Date(1999, 8, 6)), SysTime(Date(1999, 7, 6)));
assertPred!("opCmp", "<")(SysTime(Date(1999, 7, 6)), SysTime(Date(1999, 7, 7)));
assertPred!("opCmp", ">")(SysTime(Date(1999, 7, 7)), SysTime(Date(1999, 7, 6)));
assertPred!("opCmp", "<")(SysTime(Date(1999, 8, 7)), SysTime(Date(2000, 7, 6)));
assertPred!("opCmp", ">")(SysTime(Date(2000, 8, 6)), SysTime(Date(1999, 7, 7)));
assertPred!("opCmp", "<")(SysTime(Date(1999, 7, 7)), SysTime(Date(2000, 7, 6)));
assertPred!("opCmp", ">")(SysTime(Date(2000, 7, 6)), SysTime(Date(1999, 7, 7)));
assertPred!("opCmp", "<")(SysTime(Date(1999, 7, 7)), SysTime(Date(1999, 8, 6)));
assertPred!("opCmp", ">")(SysTime(Date(1999, 8, 6)), SysTime(Date(1999, 7, 7)));
assertPred!("opCmp", "==")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0))));
assertPred!("opCmp", "==")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 0))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 0, 0))));
assertPred!("opCmp", "==")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 0))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 0)))),
assertPred!("opCmp", "==")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33))));
assertPred!("opCmp", "==")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 0))));
assertPred!("opCmp", "==")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", "==")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 30, 33))));
assertPred!("opCmp", "==")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 33))));
assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34))));
assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33))));
assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34))));
assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33))));
assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33))),
SysTime(DateTime(Date(2000, 7, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(2000, 7, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33))));
assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33))),
SysTime(DateTime(Date(2000, 7, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(2000, 7, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33))));
assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34))),
SysTime(DateTime(Date(2000, 7, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(2000, 7, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34))));
assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33))),
SysTime(DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33))));
assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33))),
SysTime(DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33))));
assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34))),
SysTime(DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 8, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34))));
assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33))),
SysTime(DateTime(Date(1999, 7, 7), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 7), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(13, 30, 33))));
assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 31, 33))),
SysTime(DateTime(Date(1999, 7, 7), TimeOfDay(12, 31, 33))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 7), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34))),
SysTime(DateTime(Date(1999, 7, 7), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 7), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 34))));
//Test B.C.
assertPred!("opCmp", "==")(SysTime(DateTime(Date(-1, 1, 1), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(-1, 1, 1), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", "==")(SysTime(DateTime(Date(-1, 7, 1), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(-1, 7, 1), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", "==")(SysTime(DateTime(Date(-1, 1, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(-1, 1, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", "==")(SysTime(DateTime(Date(-1999, 7, 1), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(-1999, 7, 1), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", "==")(SysTime(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", "==")(SysTime(DateTime(Date(-1, 7, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(-1, 7, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", "<")(SysTime(DateTime(Date(-2000, 7, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(-2000, 7, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", "<")(SysTime(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", "<")(SysTime(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", "<")(SysTime(DateTime(Date(-2000, 8, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(-1999, 8, 7), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(-2000, 7, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", "<")(SysTime(DateTime(Date(-2000, 7, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(-2000, 7, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", "<")(SysTime(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33))));
//Test Both
assertPred!("opCmp", "<")(SysTime(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", "<")(SysTime(DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", "<")(SysTime(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(-1999, 7, 7), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", "<")(SysTime(DateTime(Date(-1999, 8, 7), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(-1999, 8, 7), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", "<")(SysTime(DateTime(Date(-1999, 8, 6), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(1999, 6, 6), TimeOfDay(12, 30, 33))));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 6, 8), TimeOfDay(12, 30, 33))),
SysTime(DateTime(Date(-1999, 7, 6), TimeOfDay(12, 30, 33))));
{
auto sysUTC = SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)));
sysUTC.timezone = UTC();
auto sysSimple = SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)));
sysSimple.timezone = new SimpleTimeZone(-360);
assertPred!("opCmp", "==")(sysUTC, sysSimple);
assertPred!("opCmp", "==")(sysSimple, sysUTC);
assertPred!("opCmp", "<")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), UTC()),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), sysSimple.timezone));
assertPred!("opCmp", ">")(SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), sysSimple.timezone),
SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), UTC()));
}
{
auto sysUTC = SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), UTC());
auto sysSimple = SysTime(DateTime(Date(1999, 7, 6), TimeOfDay(0, 0, 0)), new SimpleTimeZone(240));
assertPred!("opCmp", ">")(sysUTC, sysSimple);
assertPred!("opCmp", "<")(sysSimple, sysUTC);
sysUTC = SysTime(DateTime(Date(1999, 7, 5), TimeOfDay(20, 0, 0)), UTC());
assertPred!("opCmp", "==")(sysUTC, sysSimple);
assertPred!("opCmp", "==")(sysSimple, sysUTC);
}
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));
static assert(__traits(compiles, st.opCmp(st)));
static assert(__traits(compiles, st.opCmp(cst)));
//static assert(__traits(compiles, st.opCmp(ist)));
static assert(__traits(compiles, cst.opCmp(st)));
static assert(__traits(compiles, cst.opCmp(cst)));
//static assert(__traits(compiles, cst.opCmp(ist)));
//static assert(__traits(compiles, ist.opCmp(st)));
//static assert(__traits(compiles, ist.opCmp(cst)));
//static assert(__traits(compiles, ist.opCmp(ist)));
}
/++
Year of the Gregorian Calendar. Positive numbers are A.D. Non-positive
are B.C.
+/
@property short year() const nothrow
{
return (cast(Date)this).year;
}
unittest
{
assertPred!"=="(SysTime(0, UTC()).year, 1);
assertPred!"=="(SysTime(1, UTC()).year, 1);
assertPred!"=="(SysTime(-1, UTC()).year, 0);
assertPred!"=="(SysTime(DateTime(12, 1, 1, 0, 0, 0)).year, 12);
assertPred!"=="(SysTime(DateTime(-12, 1, 1, 0, 0, 0)).year, -12);
assertPred!"=="(SysTime(Date(1999, 7, 6)).year, 1999);
assertPred!"=="(SysTime(Date(-1999, 7, 6)).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));
//static assert(__traits(compiles, ist.year));
}
/++
Year of the Gregorian Calendar. Positive numbers are A.D. Non-positive
are B.C.
Params:
year = The year to set this SysTime's year to.
Throws:
DateTimeException if the new year is not a leap year and the resulting
date would be on February 29th.
Examples:
--------------------
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);
--------------------
+/
@property void year(int year)
{
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;
}
unittest
{
static void testST(SysTime st, int year, in SysTime expected, size_t line = __LINE__)
{
st.year = year;
assertPred!"=="(st, expected, "", __FILE__, line);
}
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0)), 1999, SysTime(Date(1999, 1, 1)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0)), 0, SysTime(Date(0, 1, 1)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0)), -1999, SysTime(Date(-1999, 1, 1)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 1999, SysTime(DateTime(1999, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 0, SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), -1999, SysTime(DateTime(-1999, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0)), 1999, SysTime(Date(1999, 1, 1)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0)), 0, SysTime(Date(0, 1, 1)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0)), -1999, SysTime(Date(-1999, 1, 1)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 1999, SysTime(DateTime(1999, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 0, SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), -1999, SysTime(DateTime(-1999, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(Date(1, 7, 2)), 12, SysTime(Date(12, 7, 2)));
testST(SysTime(Date(5007, 7, 2)), 5, SysTime(Date(5, 7, 2)));
testST(SysTime(Date(0, 7, 2)), 999, SysTime(Date(999, 7, 2)));
testST(SysTime(Date(-1202, 7, 2)), 2300, SysTime(Date(2300, 7, 2)));
testST(SysTime(Date(1, 7, 2)), -12, SysTime(Date(-12, 7, 2)));
testST(SysTime(Date(5007, 7, 2)), -5, SysTime(Date(-5, 7, 2)));
testST(SysTime(Date(0, 7, 2)), -999, SysTime(Date(-999, 7, 2)));
testST(SysTime(Date(-1202, 7, 2)), -2300, SysTime(Date(-2300, 7, 2)));
testST(SysTime(DateTime(1, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(0)), 12, SysTime(DateTime(12, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(0)));
testST(SysTime(DateTime(1, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 12, SysTime(DateTime(12, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(1, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 0, SysTime(DateTime(0, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(1, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), -1, SysTime(DateTime(-1, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(1, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 1, SysTime(DateTime(1, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(1, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 999, SysTime(DateTime(999, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(1, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 2010, SysTime(DateTime(2010, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(5007, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(0)), 5, SysTime(DateTime(5, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(0)));
testST(SysTime(DateTime(5007, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 5, SysTime(DateTime(5, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(5007, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 0, SysTime(DateTime(0, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(5007, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), -507, SysTime(DateTime(-507, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(5007, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 2300, SysTime(DateTime(2300, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(5007, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 5007, SysTime(DateTime(5007, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(0, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(0)), 12, SysTime(DateTime(12, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(0)));
testST(SysTime(DateTime(0, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 12, SysTime(DateTime(12, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(0, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 0, SysTime(DateTime(0, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(0, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), -1, SysTime(DateTime(-1, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(0, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 1, SysTime(DateTime(1, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(0, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 999, SysTime(DateTime(999, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(0, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 2010, SysTime(DateTime(2010, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(-1202, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(0)), 5, SysTime(DateTime(5, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(0)));
testST(SysTime(DateTime(-1202, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 5, SysTime(DateTime(5, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(-1202, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 0, SysTime(DateTime(0, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(-1202, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), -507, SysTime(DateTime(-507, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(-1202, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 2300, SysTime(DateTime(2300, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(-1202, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 5007, SysTime(DateTime(5007, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(0, UTC()), 12, SysTime(DateTime(12, 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.year = 7));
//static assert(!__traits(compiles, ist.year = 7));
//Verify Examples.
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);
}
/++
Year B.C. of the Gregorian Calendar counting year 0 as 1 B.C.
Throws:
DateTimeException if $(D isAD) is true.
Examples:
--------------------
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);
--------------------
+/
@property ushort yearBC() const
{
return (cast(Date)this).yearBC;
}
unittest
{
assertThrown!DateTimeException((in SysTime st){st.yearBC;}(SysTime(Date(1, 1, 1), UTC())));
assertThrown!DateTimeException((in SysTime st){st.yearBC;}(SysTime(0, UTC())));
assertThrown!DateTimeException((in SysTime st){st.yearBC;}(SysTime(1, UTC())));
assertPred!"=="(SysTime(-1, UTC()).yearBC, 1);
assertPred!"=="(SysTime(DateTime(-12, 1, 1, 0, 0, 0)).yearBC, 13);
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));
static assert(__traits(compiles, st.year = 12));
static assert(!__traits(compiles, cst.year = 12));
//static assert(!__traits(compiles, ist.year = 12));
//Verify Examples.
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);
}
/++
Year B.C. of the Gregorian Calendar counting year 0 as 1 B.C.
Params:
year = The year B.C. to set this SysTime's year to.
Throws:
DateTimeException if a non-positive value is given.
Examples:
--------------------
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)));
--------------------
+/
@property void yearBC(int year)
{
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;
}
unittest
{
static void testSTInvalid(SysTime st, int year)
{
st.yearBC = year;
}
static void testST(SysTime st, int year, in SysTime expected, size_t line = __LINE__)
{
st.yearBC = year;
assertPred!"=="(st, expected, "", __FILE__, line);
}
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 1, 1)), 0));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 1, 1)), -1));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 1, 1)), -1202));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0)), 1999, SysTime(Date(-1998, 1, 1)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0)), 1, SysTime(Date(0, 1, 1)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 1999, SysTime(DateTime(-1998, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 1, SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(Date(1, 7, 2)), 12, SysTime(Date(-11, 7, 2)));
testST(SysTime(Date(5007, 7, 2)), 5, SysTime(Date(-4, 7, 2)));
testST(SysTime(Date(0, 7, 2)), 999, SysTime(Date(-998, 7, 2)));
testST(SysTime(Date(-1202, 7, 2)), 2300, SysTime(Date(-2299, 7, 2)));
testST(SysTime(DateTime(1, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(0)), 12, SysTime(DateTime(-11, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(0)));
testST(SysTime(DateTime(1, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 12, SysTime(DateTime(-11, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(1, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 1, SysTime(DateTime(0, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(1, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 999, SysTime(DateTime(-998, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(1, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 2010, SysTime(DateTime(-2009, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(5007, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(0)), 5, SysTime(DateTime(-4, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(0)));
testST(SysTime(DateTime(5007, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 5, SysTime(DateTime(-4, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(5007, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 2300, SysTime(DateTime(-2299, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(5007, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 5007, SysTime(DateTime(-5006, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(0, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(0)), 12, SysTime(DateTime(-11, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(0)));
testST(SysTime(DateTime(0, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 12, SysTime(DateTime(-11, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(0, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 1, SysTime(DateTime(0, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(0, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 999, SysTime(DateTime(-998, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(0, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 2010, SysTime(DateTime(-2009, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(-1202, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(0)), 5, SysTime(DateTime(-4, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(0)));
testST(SysTime(DateTime(-1202, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 5, SysTime(DateTime(-4, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(-1202, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 2300, SysTime(DateTime(-2299, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(DateTime(-1202, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)), 5007, SysTime(DateTime(-5006, 7, 2, 1, 3, 2), FracSec.from!"hnsecs"(5007)));
testST(SysTime(0, UTC()), 12, SysTime(DateTime(-11, 1, 1, 0, 0, 0), UTC()));
{
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));
static assert(__traits(compiles, st.yearBC = 12));
static assert(!__traits(compiles, cst.yearBC = 12));
//static assert(!__traits(compiles, ist.yearBC = 12));
}
//Verify Examples.
{
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)));
}
}
/++
Month of a Gregorian Year.
Examples:
--------------------
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);
--------------------
+/
@property Month month() const nothrow
{
return (cast(Date)this).month;
}
unittest
{
assertPred!"=="(SysTime(0, UTC()).month, 1);
assertPred!"=="(SysTime(1, UTC()).month, 1);
assertPred!"=="(SysTime(-1, UTC()).month, 12);
assertPred!"=="(SysTime(DateTime(1, 12, 1, 0, 0, 0)).month, 12);
assertPred!"=="(SysTime(DateTime(0, 12, 1, 0, 0, 0)).month, 12);
assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)).month, 7);
assertPred!"=="(SysTime(DateTime(-1999, 7, 6, 12, 30, 33)).month, 7);
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));
//static assert(__traits(compiles, ist.month));
//Verify Examples.
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);
}
/++
Month of a Gregorian Year.
Params:
month = The month to set this SysTime's month to.
Throws:
DateTimeException if the given month is not a valid month.
+/
@property void month(Month month)
{
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;
}
unittest
{
static void testSTInvalid(SysTime st, Month month)
{
st.month = month;
}
static void testST(SysTime st, Month month, in SysTime expected, size_t line = __LINE__)
{
st.month = month;
assertPred!"=="(st, expected, "", __FILE__, line);
}
assertThrown!DateTimeException(testSTInvalid(SysTime(DateTime(1, 1, 1, 12, 30, 33)), cast(Month)0));
assertThrown!DateTimeException(testSTInvalid(SysTime(DateTime(1, 1, 1, 12, 30, 33)), cast(Month)13));
assertThrown!DateTimeException(testSTInvalid(SysTime(DateTime(1, 1, 29, 12, 30, 33)), cast(Month)2));
assertThrown!DateTimeException(testSTInvalid(SysTime(DateTime(1, 7, 31, 12, 30, 33)), cast(Month)6));
assertThrown!DateTimeException(testSTInvalid(SysTime(DateTime(4, 7, 30, 12, 30, 33)), cast(Month)2));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0)), cast(Month)1, SysTime(Date(1, 1, 1)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0)), cast(Month)7, SysTime(Date(1, 7, 1)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0)), cast(Month)12, SysTime(Date(1, 12, 1)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), cast(Month)1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), cast(Month)7, SysTime(DateTime(1, 7, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), cast(Month)12, SysTime(DateTime(1, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0)), cast(Month)1, SysTime(Date(0, 1, 1)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0)), cast(Month)7, SysTime(Date(0, 7, 1)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0)), cast(Month)12, SysTime(Date(0, 12, 1)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), cast(Month)1, SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), cast(Month)7, SysTime(DateTime(0, 7, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), cast(Month)12, SysTime(DateTime(0, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(Date(1, 7, 2)), cast(Month)12, SysTime(Date(1, 12, 2)));
testST(SysTime(Date(5007, 7, 2)), cast(Month)5, SysTime(Date(5007, 5, 2)));
testST(SysTime(Date(0, 7, 2)), cast(Month)7, SysTime(Date(0, 7, 2)));
testST(SysTime(Date(-1202, 7, 2)), cast(Month)1, SysTime(Date(-1202, 1, 2)));
testST(SysTime(DateTime(1, 12, 29, 9, 13, 2), FracSec.from!"hnsecs"(0)), cast(Month)12, SysTime(DateTime(1, 12, 29, 9, 13, 2), FracSec.from!"hnsecs"(0)));
testST(SysTime(DateTime(1, 12, 29, 9, 13, 2), FracSec.from!"hnsecs"(1)), cast(Month)12, SysTime(DateTime(1, 12, 29, 9, 13, 2), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 12, 29, 9, 13, 2), FracSec.from!"hnsecs"(2)), cast(Month)7, SysTime(DateTime(1, 7, 29, 9, 13, 2), FracSec.from!"hnsecs"(2)));
testST(SysTime(DateTime(1, 11, 28, 10, 13, 2), FracSec.from!"hnsecs"(3)), cast(Month)1, SysTime(DateTime(1, 1, 28, 10, 13, 2), FracSec.from!"hnsecs"(3)));
testST(SysTime(DateTime(1, 1, 28, 10, 13, 2), FracSec.from!"hnsecs"(4)), cast(Month)2, SysTime(DateTime(1, 2, 28, 10, 13, 2), FracSec.from!"hnsecs"(4)));
testST(SysTime(DateTime(1, 7, 28, 10, 13, 2), FracSec.from!"hnsecs"(5)),cast(Month) 6, SysTime(DateTime(1, 6, 28, 10, 13, 2), FracSec.from!"hnsecs"(5)));
testST(SysTime(DateTime(4, 7, 29, 10, 13, 2), FracSec.from!"hnsecs"(6)), cast(Month)2, SysTime(DateTime(4, 2, 29, 10, 13, 2), FracSec.from!"hnsecs"(6)));
testST(SysTime(DateTime(4, 7, 31, 10, 13, 2), FracSec.from!"hnsecs"(6)), cast(Month)8, SysTime(DateTime(4, 8, 31, 10, 13, 2), FracSec.from!"hnsecs"(6)));
testST(SysTime(DateTime(1207, 12, 29, 9, 12, 2), FracSec.from!"hnsecs"(0)), cast(Month)12, SysTime(DateTime(1207, 12, 29, 9, 12, 2), FracSec.from!"hnsecs"(0)));
testST(SysTime(DateTime(1207, 12, 29, 9, 12, 2), FracSec.from!"hnsecs"(11)), cast(Month)12, SysTime(DateTime(1207, 12, 29, 9, 12, 2), FracSec.from!"hnsecs"(11)));
testST(SysTime(DateTime(1207, 12, 29, 9, 12, 3), FracSec.from!"hnsecs"(10)), cast(Month)7, SysTime(DateTime(1207, 7, 29, 9, 12, 3), FracSec.from!"hnsecs"(10)));
testST(SysTime(DateTime(1207, 11, 28, 10, 12, 3), FracSec.from!"hnsecs"(9)), cast(Month)1, SysTime(DateTime(1207, 1, 28, 10, 12, 3), FracSec.from!"hnsecs"(9)));
testST(SysTime(DateTime(1207, 1, 28, 10, 12, 3), FracSec.from!"hnsecs"(8)), cast(Month)2, SysTime(DateTime(1207, 2, 28, 10, 12, 3), FracSec.from!"hnsecs"(8)));
testST(SysTime(DateTime(1207, 7, 28, 10, 12, 3), FracSec.from!"hnsecs"(7)), cast(Month)6, SysTime(DateTime(1207, 6, 28, 10, 12, 3), FracSec.from!"hnsecs"(7)));
testST(SysTime(DateTime(0, 12, 29, 9, 13, 2), FracSec.from!"hnsecs"(0)), cast(Month)12, SysTime(DateTime(0, 12, 29, 9, 13, 2), FracSec.from!"hnsecs"(0)));
testST(SysTime(DateTime(0, 12, 29, 9, 13, 2), FracSec.from!"hnsecs"(1)), cast(Month)12, SysTime(DateTime(0, 12, 29, 9, 13, 2), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 12, 29, 9, 13, 2), FracSec.from!"hnsecs"(2)), cast(Month)7, SysTime(DateTime(0, 7, 29, 9, 13, 2), FracSec.from!"hnsecs"(2)));
testST(SysTime(DateTime(0, 11, 28, 10, 13, 2), FracSec.from!"hnsecs"(3)), cast(Month)1, SysTime(DateTime(0, 1, 28, 10, 13, 2), FracSec.from!"hnsecs"(3)));
testST(SysTime(DateTime(0, 1, 28, 10, 13, 2), FracSec.from!"hnsecs"(4)), cast(Month)2, SysTime(DateTime(0, 2, 28, 10, 13, 2), FracSec.from!"hnsecs"(4)));
testST(SysTime(DateTime(0, 7, 28, 10, 13, 2), FracSec.from!"hnsecs"(5)), cast(Month)6, SysTime(DateTime(0, 6, 28, 10, 13, 2), FracSec.from!"hnsecs"(5)));
testST(SysTime(DateTime(0, 12, 30, 0, 0, 0), FracSec.from!"hnsecs"(1)), cast(Month)11, SysTime(DateTime(0, 11, 30, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(-1, 7, 28, 0, 0, 0), FracSec.from!"hnsecs"(1)), cast(Month)2, SysTime(DateTime(-1, 2, 28, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 7, 29, 0, 0, 0), FracSec.from!"hnsecs"(1)), cast(Month)2, SysTime(DateTime(0, 2, 29, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 7, 29, 10, 13, 2), FracSec.from!"hnsecs"(6)), cast(Month)2, SysTime(DateTime(0, 2, 29, 10, 13, 2), FracSec.from!"hnsecs"(6)));
testST(SysTime(DateTime(0, 7, 31, 10, 13, 2), FracSec.from!"hnsecs"(6)), cast(Month)8, SysTime(DateTime(0, 8, 31, 10, 13, 2), FracSec.from!"hnsecs"(6)));
testST(SysTime(DateTime(-9999, 12, 29, 9, 12, 2), FracSec.from!"hnsecs"(0)), cast(Month)12, SysTime(DateTime(-9999, 12, 29, 9, 12, 2), FracSec.from!"hnsecs"(0)));
testST(SysTime(DateTime(-9999, 12, 29, 9, 12, 2), FracSec.from!"hnsecs"(11)), cast(Month)12, SysTime(DateTime(-9999, 12, 29, 9, 12, 2), FracSec.from!"hnsecs"(11)));
testST(SysTime(DateTime(-9999, 12, 29, 9, 12, 3), FracSec.from!"hnsecs"(10)), cast(Month)7, SysTime(DateTime(-9999, 7, 29, 9, 12, 3), FracSec.from!"hnsecs"(10)));
testST(SysTime(DateTime(-9999, 11, 28, 10, 12, 3), FracSec.from!"hnsecs"(9)), cast(Month)1, SysTime(DateTime(-9999, 1, 28, 10, 12, 3), FracSec.from!"hnsecs"(9)));
testST(SysTime(DateTime(-9999, 1, 28, 10, 12, 3), FracSec.from!"hnsecs"(8)), cast(Month)2, SysTime(DateTime(-9999, 2, 28, 10, 12, 3), FracSec.from!"hnsecs"(8)));
testST(SysTime(DateTime(-9999, 7, 28, 10, 12, 3), FracSec.from!"hnsecs"(7)), cast(Month)6, SysTime(DateTime(-9999, 6, 28, 10, 12, 3), FracSec.from!"hnsecs"(7)));
testST(SysTime(0, UTC()), cast(Month)12, SysTime(DateTime(1, 12, 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.month = 12));
//static assert(!__traits(compiles, ist.month = 12));
}
/++
Day of a Gregorian Month.
Examples:
--------------------
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);
--------------------
+/
@property ubyte day() const nothrow
{
return (cast(Date)this).day;
}
unittest
{
assertPred!"=="(SysTime(0, UTC()).day, 1);
assertPred!"=="(SysTime(1, UTC()).day, 1);
assertPred!"=="(SysTime(-1, UTC()).day, 31);
assertPred!"=="(SysTime(DateTime(50, 2, 4)).day, 4);
assertPred!"=="(SysTime(DateTime(50, 2, 4, 0, 0, 1)).day, 4);
assertPred!"=="(SysTime(DateTime(1999, 7, 6)).day, 6);
assertPred!"=="(SysTime(DateTime(1999, 7, 6, 0, 0, 0)).day, 6);
assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)).day, 6);
assertPred!"=="(SysTime(DateTime(-50, 2, 4)).day, 4);
assertPred!"=="(SysTime(DateTime(-50, 2, 4, 0, 0, 1)).day, 4);
assertPred!"=="(SysTime(Date(-1999, 7, 6)).day, 6);
assertPred!"=="(SysTime(DateTime(-1999, 7, 6, 0, 0, 0)).day, 6);
assertPred!"=="(SysTime(DateTime(-1999, 7, 6, 12, 30, 33)).day, 6);
assertPred!"=="(SysTime(DateTime(1, 1, 12, 0, 0, 0)).day, 12);
assertPred!"=="(SysTime(DateTime(0, 1, 12, 0, 0, 0)).day, 12);
const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
//immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
static assert(__traits(compiles, cst.day));
//static assert(__traits(compiles, ist.day));
//Verify Examples.
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);
}
/++
Day of a Gregorian Month.
Params:
day = The day of the month to set this SysTime's day to.
Throws:
DateTimeException if the given day is not a valid day of the current
month.
+/
@property void day(int day)
{
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;
}
unittest
{
static void testSTInvalid(SysTime st, int day)
{
st.day = day;
}
static void testST(SysTime st, int day, in SysTime expected, size_t line = __LINE__)
{
st.day = day;
assertPred!"=="(st, expected, "", __FILE__, line);
}
//Test A.D.
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 1, 1)), 0));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 1, 1)), 32));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 2, 1)), 29));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(4, 2, 1)), 30));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 3, 1)), 32));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 4, 1)), 31));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 5, 1)), 32));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 6, 1)), 31));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 7, 1)), 32));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 8, 1)), 32));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 9, 1)), 31));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 10, 1)), 32));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 11, 1)), 31));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 12, 1)), 32));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 1, 1)), 31));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 2, 1)), 28));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(4, 2, 1)), 29));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 3, 1)), 31));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 4, 1)), 30));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 5, 1)), 31));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 6, 1)), 30));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 7, 1)), 31));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 8, 1)), 31));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 9, 1)), 30));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 10, 1)), 31));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 11, 1)), 30));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(1, 12, 1)), 31));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0)), 1, SysTime(Date(1, 1, 1)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0)), 7, SysTime(Date(1, 1, 7)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0)), 12, SysTime(Date(1, 1, 12)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 7, SysTime(DateTime(1, 1, 7, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 12, SysTime(DateTime(1, 1, 12, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(Date(1, 7, 2)), 12, SysTime(Date(1, 7, 12)));
testST(SysTime(Date(5007, 7, 2)), 5, SysTime(Date(5007, 7, 5)));
testST(SysTime(DateTime(1, 1, 7, 12, 22, 17), FracSec.from!"hnsecs"(7)), 6, SysTime(DateTime(1, 1, 6, 12, 22, 17), FracSec.from!"hnsecs"(7)));
testST(SysTime(DateTime(1, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(70)), 1, SysTime(DateTime(1, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(70)));
testST(SysTime(DateTime(1, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(700)), 1, SysTime(DateTime(1, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(700)));
testST(SysTime(DateTime(1, 2, 27, 12, 22, 17), FracSec.from!"hnsecs"(7000)), 5, SysTime(DateTime(1, 2, 5, 12, 22, 17), FracSec.from!"hnsecs"(7000)));
testST(SysTime(DateTime(1, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(70_000)), 1, SysTime(DateTime(1, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(70_000)));
testST(SysTime(DateTime(1, 12, 31, 12, 22, 17), FracSec.from!"hnsecs"(700_000)), 29, SysTime(DateTime(1, 12, 29, 12, 22, 17), FracSec.from!"hnsecs"(700_000)));
testST(SysTime(DateTime(999, 1, 7, 12, 22, 17), FracSec.from!"hnsecs"(9)), 6, SysTime(DateTime(999, 1, 6, 12, 22, 17), FracSec.from!"hnsecs"(9)));
testST(SysTime(DateTime(999, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(90)), 1, SysTime(DateTime(999, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(90)));
testST(SysTime(DateTime(999, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(900)), 1, SysTime(DateTime(999, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(900)));
testST(SysTime(DateTime(999, 2, 27, 12, 22, 17), FracSec.from!"hnsecs"(9000)), 5, SysTime(DateTime(999, 2, 5, 12, 22, 17), FracSec.from!"hnsecs"(9000)));
testST(SysTime(DateTime(999, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(90_000)), 1, SysTime(DateTime(999, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(90_000)));
testST(SysTime(DateTime(999, 12, 31, 12, 22, 17), FracSec.from!"hnsecs"(900_000)), 29, SysTime(DateTime(999, 12, 29, 12, 22, 17), FracSec.from!"hnsecs"(900_000)));
//Test B.C.
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(-1, 1, 1)), 0));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(-1, 1, 1)), 32));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(-1, 2, 1)), 29));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(0, 2, 1)), 30));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(-1, 3, 1)), 32));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(-1, 4, 1)), 31));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(-1, 5, 1)), 32));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(-1, 6, 1)), 31));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(-1, 7, 1)), 32));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(-1, 8, 1)), 32));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(-1, 9, 1)), 31));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(-1, 10, 1)), 32));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(-1, 11, 1)), 31));
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(-1, 12, 1)), 32));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(-1, 1, 1)), 31));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(-1, 2, 1)), 28));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(0, 2, 1)), 29));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(-1, 3, 1)), 31));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(-1, 4, 1)), 30));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(-1, 5, 1)), 31));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(-1, 6, 1)), 30));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(-1, 7, 1)), 31));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(-1, 8, 1)), 31));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(-1, 9, 1)), 30));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(-1, 10, 1)), 31));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(-1, 11, 1)), 30));
assertNotThrown!DateTimeException(testSTInvalid(SysTime(Date(-1, 12, 1)), 31));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0)), 1, SysTime(Date(0, 1, 1)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0)), 7, SysTime(Date(0, 1, 7)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0)), 12, SysTime(Date(0, 1, 12)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 1, SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 7, SysTime(DateTime(0, 1, 7, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 12, SysTime(DateTime(0, 1, 12, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(Date(0, 7, 2)), 7, SysTime(Date(0, 7, 7)));
testST(SysTime(Date(-1202, 7, 2)), 1, SysTime(Date(-1202, 7, 1)));
testST(SysTime(DateTime(0, 1, 7, 12, 22, 17), FracSec.from!"hnsecs"(7)), 6, SysTime(DateTime(0, 1, 6, 12, 22, 17), FracSec.from!"hnsecs"(7)));
testST(SysTime(DateTime(0, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(70)), 1, SysTime(DateTime(0, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(70)));
testST(SysTime(DateTime(0, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(700)), 1, SysTime(DateTime(0, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(700)));
testST(SysTime(DateTime(0, 2, 27, 12, 22, 17), FracSec.from!"hnsecs"(7000)), 5, SysTime(DateTime(0, 2, 5, 12, 22, 17), FracSec.from!"hnsecs"(7000)));
testST(SysTime(DateTime(0, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(70_000)), 1, SysTime(DateTime(0, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(70_000)));
testST(SysTime(DateTime(0, 12, 31, 12, 22, 17), FracSec.from!"hnsecs"(700_000)), 29, SysTime(DateTime(0, 12, 29, 12, 22, 17), FracSec.from!"hnsecs"(700_000)));
testST(SysTime(DateTime(-1, 1, 7, 12, 22, 17), FracSec.from!"hnsecs"(9)), 6, SysTime(DateTime(-1, 1, 6, 12, 22, 17), FracSec.from!"hnsecs"(9)));
testST(SysTime(DateTime(-1, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(90)), 1, SysTime(DateTime(-1, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(90)));
testST(SysTime(DateTime(-1, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(900)), 1, SysTime(DateTime(-1, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(900)));
testST(SysTime(DateTime(-1, 2, 27, 12, 22, 17), FracSec.from!"hnsecs"(9000)), 5, SysTime(DateTime(-1, 2, 5, 12, 22, 17), FracSec.from!"hnsecs"(9000)));
testST(SysTime(DateTime(-1, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(90_000)), 1, SysTime(DateTime(-1, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(90_000)));
testST(SysTime(DateTime(-1, 12, 31, 12, 22, 17), FracSec.from!"hnsecs"(900_000)), 29, SysTime(DateTime(-1, 12, 29, 12, 22, 17), FracSec.from!"hnsecs"(900_000)));
testST(SysTime(0, UTC()), 12, SysTime(DateTime(1, 1, 12, 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.day = 27));
//static assert(!__traits(compiles, ist.day = 27));
}
/++
Hours past midnight.
+/
@property ubyte hour() 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);
}
unittest
{
assertPred!"=="(SysTime(0, UTC()).hour, 0);
assertPred!"=="(SysTime(1, UTC()).hour, 0);
assertPred!"=="(SysTime(-1, UTC()).hour, 23);
assertPred!"=="(SysTime(DateTime(1, 1, 1, 12, 0, 0)).hour, 12);
assertPred!"=="(SysTime(DateTime(0, 1, 1, 12, 0, 0)).hour, 12);
const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
//immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
static assert(__traits(compiles, cst.hour));
//static assert(__traits(compiles, ist.hour));
}
/++
Hours past midnight.
Params:
hour = The hours to set this SysTime's hour to.
Throws:
DateTimeException if the given hour are not a valid hour of the day.
+/
@property void hour(int hour)
{
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;
}
unittest
{
static void testSTInvalid(SysTime st, int hour)
{
st.hour = hour;
}
static void testST(SysTime st, int hour, in SysTime expected, size_t line = __LINE__)
{
st.hour = hour;
assertPred!"=="(st, expected, "", __FILE__, line);
}
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(1999, 7, 6)), 24));
//Test A.D.
testST(SysTime(Date(1, 1, 1)), 1, SysTime(DateTime(1, 1, 1, 1, 0, 0)));
testST(SysTime(Date(1, 1, 1)), 7, SysTime(DateTime(1, 1, 1, 7, 0, 0)));
testST(SysTime(Date(1, 1, 1)), 12, SysTime(DateTime(1, 1, 1, 12, 0, 0)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 1, SysTime(DateTime(1, 1, 1, 1, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 7, SysTime(DateTime(1, 1, 1, 7, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 12, SysTime(DateTime(1, 1, 1, 12, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 12, 31, 23, 59, 59)), 1, SysTime(DateTime(1, 12, 31, 1, 59, 59)));
testST(SysTime(DateTime(1, 12, 31, 23, 59, 59)), 7, SysTime(DateTime(1, 12, 31, 7, 59, 59)));
testST(SysTime(DateTime(1, 12, 31, 23, 59, 59)), 12, SysTime(DateTime(1, 12, 31, 12, 59, 59)));
testST(SysTime(DateTime(1, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)), 1, SysTime(DateTime(1, 12, 31, 1, 59, 59), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)), 7, SysTime(DateTime(1, 12, 31, 7, 59, 59), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)), 12, SysTime(DateTime(1, 12, 31, 12, 59, 59), FracSec.from!"hnsecs"(1)));
testST(SysTime(Date(1, 7, 2)), 12, SysTime(DateTime(1, 7, 2, 12, 0, 0)));
testST(SysTime(Date(5007, 7, 2)), 5, SysTime(DateTime(5007, 7, 2, 5, 0, 0)));
testST(SysTime(DateTime(1, 1, 7, 12, 22, 17), FracSec.from!"hnsecs"(7)), 6, SysTime(DateTime(1, 1, 7, 6, 22, 17), FracSec.from!"hnsecs"(7)));
testST(SysTime(DateTime(1, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(70)), 1, SysTime(DateTime(1, 1, 1, 1, 22, 17), FracSec.from!"hnsecs"(70)));
testST(SysTime(DateTime(1, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(700)), 1, SysTime(DateTime(1, 2, 1, 1, 22, 17), FracSec.from!"hnsecs"(700)));
testST(SysTime(DateTime(1, 2, 27, 12, 22, 17), FracSec.from!"hnsecs"(7000)), 5, SysTime(DateTime(1, 2, 27, 5, 22, 17), FracSec.from!"hnsecs"(7000)));
testST(SysTime(DateTime(1, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(70_000)), 1, SysTime(DateTime(1, 12, 1, 1, 22, 17), FracSec.from!"hnsecs"(70_000)));
testST(SysTime(DateTime(1, 12, 31, 12, 22, 17), FracSec.from!"hnsecs"(700_000)), 23, SysTime(DateTime(1, 12, 31, 23, 22, 17), FracSec.from!"hnsecs"(700_000)));
testST(SysTime(DateTime(999, 1, 7, 12, 22, 17), FracSec.from!"hnsecs"(9)), 6, SysTime(DateTime(999, 1, 7, 6, 22, 17), FracSec.from!"hnsecs"(9)));
testST(SysTime(DateTime(999, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(90)), 1, SysTime(DateTime(999, 1, 1, 1, 22, 17), FracSec.from!"hnsecs"(90)));
testST(SysTime(DateTime(999, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(900)), 1, SysTime(DateTime(999, 2, 1, 1, 22, 17), FracSec.from!"hnsecs"(900)));
testST(SysTime(DateTime(999, 2, 27, 12, 22, 17), FracSec.from!"hnsecs"(9000)), 5, SysTime(DateTime(999, 2, 27, 5, 22, 17), FracSec.from!"hnsecs"(9000)));
testST(SysTime(DateTime(999, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(90_000)), 1, SysTime(DateTime(999, 12, 1, 1, 22, 17), FracSec.from!"hnsecs"(90_000)));
testST(SysTime(DateTime(999, 12, 31, 12, 22, 17), FracSec.from!"hnsecs"(900_000)), 23, SysTime(DateTime(999, 12, 31, 23, 22, 17), FracSec.from!"hnsecs"(900_000)));
//Test B.C.
testST(SysTime(Date(0, 1, 1)), 1, SysTime(DateTime(0, 1, 1, 1, 0, 0)));
testST(SysTime(Date(0, 1, 1)), 7, SysTime(DateTime(0, 1, 1, 7, 0, 0)));
testST(SysTime(Date(0, 1, 1)), 12, SysTime(DateTime(0, 1, 1, 12, 0, 0)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 1, SysTime(DateTime(0, 1, 1, 1, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 7, SysTime(DateTime(0, 1, 1, 7, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 12, SysTime(DateTime(0, 1, 1, 12, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 12, 31, 23, 59, 59)), 1, SysTime(DateTime(0, 12, 31, 1, 59, 59)));
testST(SysTime(DateTime(0, 12, 31, 23, 59, 59)), 7, SysTime(DateTime(0, 12, 31, 7, 59, 59)));
testST(SysTime(DateTime(0, 12, 31, 23, 59, 59)), 12, SysTime(DateTime(0, 12, 31, 12, 59, 59)));
testST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)), 1, SysTime(DateTime(0, 12, 31, 1, 59, 59), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)), 7, SysTime(DateTime(0, 12, 31, 7, 59, 59), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)), 12, SysTime(DateTime(0, 12, 31, 12, 59, 59), FracSec.from!"hnsecs"(1)));
testST(SysTime(Date(0, 7, 2)), 7, SysTime(DateTime(0, 7, 2, 7, 0, 0)));
testST(SysTime(Date(-1202, 7, 2)), 1, SysTime(DateTime(-1202, 7, 2, 1, 0, 0)));
testST(SysTime(DateTime(0, 1, 7, 12, 22, 17), FracSec.from!"hnsecs"(7)), 6, SysTime(DateTime(0, 1, 7, 6, 22, 17), FracSec.from!"hnsecs"(7)));
testST(SysTime(DateTime(0, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(70)), 1, SysTime(DateTime(0, 1, 1, 1, 22, 17), FracSec.from!"hnsecs"(70)));
testST(SysTime(DateTime(0, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(700)), 1, SysTime(DateTime(0, 2, 1, 1, 22, 17), FracSec.from!"hnsecs"(700)));
testST(SysTime(DateTime(0, 2, 27, 12, 22, 17), FracSec.from!"hnsecs"(7000)), 5, SysTime(DateTime(0, 2, 27, 5, 22, 17), FracSec.from!"hnsecs"(7000)));
testST(SysTime(DateTime(0, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(70_000)), 1, SysTime(DateTime(0, 12, 1, 1, 22, 17), FracSec.from!"hnsecs"(70_000)));
testST(SysTime(DateTime(0, 12, 31, 12, 22, 17), FracSec.from!"hnsecs"(700_000)), 23, SysTime(DateTime(0, 12, 31, 23, 22, 17), FracSec.from!"hnsecs"(700_000)));
testST(SysTime(DateTime(-1, 1, 7, 12, 22, 17), FracSec.from!"hnsecs"(9)), 6, SysTime(DateTime(-1, 1, 7, 6, 22, 17), FracSec.from!"hnsecs"(9)));
testST(SysTime(DateTime(-1, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(90)), 1, SysTime(DateTime(-1, 1, 1, 1, 22, 17), FracSec.from!"hnsecs"(90)));
testST(SysTime(DateTime(-1, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(900)), 1, SysTime(DateTime(-1, 2, 1, 1, 22, 17), FracSec.from!"hnsecs"(900)));
testST(SysTime(DateTime(-1, 2, 27, 12, 22, 17), FracSec.from!"hnsecs"(9000)), 5, SysTime(DateTime(-1, 2, 27, 5, 22, 17), FracSec.from!"hnsecs"(9000)));
testST(SysTime(DateTime(-1, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(90_000)), 1, SysTime(DateTime(-1, 12, 1, 1, 22, 17), FracSec.from!"hnsecs"(90_000)));
testST(SysTime(DateTime(-1, 12, 31, 12, 22, 17), FracSec.from!"hnsecs"(900_000)), 23, SysTime(DateTime(-1, 12, 31, 23, 22, 17), FracSec.from!"hnsecs"(900_000)));
testST(SysTime(0, UTC()), 12, SysTime(DateTime(1, 1, 1, 12, 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.hour = 27));
//static assert(!__traits(compiles, ist.hour = 27));
}
/++
Minutes past the current hour.
+/
@property ubyte minute() 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);
}
unittest
{
assertPred!"=="(SysTime(0, UTC()).minute, 0);
assertPred!"=="(SysTime(1, UTC()).minute, 0);
assertPred!"=="(SysTime(-1, UTC()).minute, 59);
assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 30, 0)).minute, 30);
assertPred!"=="(SysTime(DateTime(0, 1, 1, 0, 30, 0)).minute, 30);
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));
//static assert(__traits(compiles, ist.minute));
}
/++
Minutes past the current hour.
Params:
minutes = The minute to set this SysTime's minute to.
Throws:
DateTimeException if the given minute are not a valid minute of an
hour.
+/
@property void minute(int minute)
{
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;
}
unittest
{
static void testSTInvalid(SysTime st, int minute)
{
st.minute = minute;
}
static void testST(SysTime st, int minute, in SysTime expected, size_t line = __LINE__)
{
st.minute = minute;
assertPred!"=="(st, expected, "", __FILE__, line);
}
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(1999, 7, 6)), 60));
//Test A.D.
testST(SysTime(Date(1, 1, 1)), 1, SysTime(DateTime(1, 1, 1, 0, 1, 0)));
testST(SysTime(Date(1, 1, 1)), 7, SysTime(DateTime(1, 1, 1, 0, 7, 0)));
testST(SysTime(Date(1, 1, 1)), 12, SysTime(DateTime(1, 1, 1, 0, 12, 0)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 1, SysTime(DateTime(1, 1, 1, 0, 1, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 7, SysTime(DateTime(1, 1, 1, 0, 7, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 12, SysTime(DateTime(1, 1, 1, 0, 12, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 12, 31, 23, 59, 59)), 1, SysTime(DateTime(1, 12, 31, 23, 1, 59)));
testST(SysTime(DateTime(1, 12, 31, 23, 59, 59)), 7, SysTime(DateTime(1, 12, 31, 23, 7, 59)));
testST(SysTime(DateTime(1, 12, 31, 23, 59, 59)), 12, SysTime(DateTime(1, 12, 31, 23, 12, 59)));
testST(SysTime(DateTime(1, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)), 1, SysTime(DateTime(1, 12, 31, 23, 1, 59), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)), 7, SysTime(DateTime(1, 12, 31, 23, 7, 59), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)), 12, SysTime(DateTime(1, 12, 31, 23, 12, 59), FracSec.from!"hnsecs"(1)));
testST(SysTime(Date(1, 7, 2)), 12, SysTime(DateTime(1, 7, 2, 0, 12, 0)));
testST(SysTime(Date(5007, 7, 2)), 5, SysTime(DateTime(5007, 7, 2, 0, 5, 0)));
testST(SysTime(DateTime(1, 1, 7, 12, 22, 17), FracSec.from!"hnsecs"(7)), 6, SysTime(DateTime(1, 1, 7, 12, 6, 17), FracSec.from!"hnsecs"(7)));
testST(SysTime(DateTime(1, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(70)), 1, SysTime(DateTime(1, 1, 1, 12, 1, 17), FracSec.from!"hnsecs"(70)));
testST(SysTime(DateTime(1, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(700)), 1, SysTime(DateTime(1, 2, 1, 12, 1, 17), FracSec.from!"hnsecs"(700)));
testST(SysTime(DateTime(1, 2, 27, 12, 22, 17), FracSec.from!"hnsecs"(7000)), 5, SysTime(DateTime(1, 2, 27, 12, 5, 17), FracSec.from!"hnsecs"(7000)));
testST(SysTime(DateTime(1, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(70_000)), 1, SysTime(DateTime(1, 12, 1, 12, 1, 17), FracSec.from!"hnsecs"(70_000)));
testST(SysTime(DateTime(1, 12, 31, 12, 22, 17), FracSec.from!"hnsecs"(700_000)), 23, SysTime(DateTime(1, 12, 31, 12, 23, 17), FracSec.from!"hnsecs"(700_000)));
testST(SysTime(DateTime(999, 1, 7, 12, 22, 17), FracSec.from!"hnsecs"(9)), 6, SysTime(DateTime(999, 1, 7, 12, 6, 17), FracSec.from!"hnsecs"(9)));
testST(SysTime(DateTime(999, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(90)), 1, SysTime(DateTime(999, 1, 1, 12, 1, 17), FracSec.from!"hnsecs"(90)));
testST(SysTime(DateTime(999, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(900)), 1, SysTime(DateTime(999, 2, 1, 12, 1, 17), FracSec.from!"hnsecs"(900)));
testST(SysTime(DateTime(999, 2, 27, 12, 22, 17), FracSec.from!"hnsecs"(9000)), 5, SysTime(DateTime(999, 2, 27, 12, 5, 17), FracSec.from!"hnsecs"(9000)));
testST(SysTime(DateTime(999, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(90_000)), 1, SysTime(DateTime(999, 12, 1, 12, 1, 17), FracSec.from!"hnsecs"(90_000)));
testST(SysTime(DateTime(999, 12, 31, 12, 22, 17), FracSec.from!"hnsecs"(900_000)), 23, SysTime(DateTime(999, 12, 31, 12, 23, 17), FracSec.from!"hnsecs"(900_000)));
//Test B.C.
testST(SysTime(Date(0, 1, 1)), 1, SysTime(DateTime(0, 1, 1, 0, 1, 0)));
testST(SysTime(Date(0, 1, 1)), 7, SysTime(DateTime(0, 1, 1, 0, 7, 0)));
testST(SysTime(Date(0, 1, 1)), 12, SysTime(DateTime(0, 1, 1, 0, 12, 0)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 1, SysTime(DateTime(0, 1, 1, 0, 1, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 7, SysTime(DateTime(0, 1, 1, 0, 7, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 12, SysTime(DateTime(0, 1, 1, 0, 12, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 12, 31, 23, 59, 59)), 1, SysTime(DateTime(0, 12, 31, 23, 1, 59)));
testST(SysTime(DateTime(0, 12, 31, 23, 59, 59)), 7, SysTime(DateTime(0, 12, 31, 23, 7, 59)));
testST(SysTime(DateTime(0, 12, 31, 23, 59, 59)), 12, SysTime(DateTime(0, 12, 31, 23, 12, 59)));
testST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)), 1, SysTime(DateTime(0, 12, 31, 23, 1, 59), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)), 7, SysTime(DateTime(0, 12, 31, 23, 7, 59), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)), 12, SysTime(DateTime(0, 12, 31, 23, 12, 59), FracSec.from!"hnsecs"(1)));
testST(SysTime(Date(0, 7, 2)), 7, SysTime(DateTime(0, 7, 2, 0, 7, 0)));
testST(SysTime(Date(-1202, 7, 2)), 1, SysTime(DateTime(-1202, 7, 2, 0, 1, 0)));
testST(SysTime(DateTime(0, 1, 7, 12, 22, 17), FracSec.from!"hnsecs"(7)), 6, SysTime(DateTime(0, 1, 7, 12, 6, 17), FracSec.from!"hnsecs"(7)));
testST(SysTime(DateTime(0, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(70)), 1, SysTime(DateTime(0, 1, 1, 12, 1, 17), FracSec.from!"hnsecs"(70)));
testST(SysTime(DateTime(0, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(700)), 1, SysTime(DateTime(0, 2, 1, 12, 1, 17), FracSec.from!"hnsecs"(700)));
testST(SysTime(DateTime(0, 2, 27, 12, 22, 17), FracSec.from!"hnsecs"(7000)), 5, SysTime(DateTime(0, 2, 27, 12, 5, 17), FracSec.from!"hnsecs"(7000)));
testST(SysTime(DateTime(0, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(70_000)), 1, SysTime(DateTime(0, 12, 1, 12, 1, 17), FracSec.from!"hnsecs"(70_000)));
testST(SysTime(DateTime(0, 12, 31, 12, 22, 17), FracSec.from!"hnsecs"(700_000)), 23, SysTime(DateTime(0, 12, 31, 12, 23, 17), FracSec.from!"hnsecs"(700_000)));
testST(SysTime(DateTime(-1, 1, 7, 12, 22, 17), FracSec.from!"hnsecs"(9)), 6, SysTime(DateTime(-1, 1, 7, 12, 6, 17), FracSec.from!"hnsecs"(9)));
testST(SysTime(DateTime(-1, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(90)), 1, SysTime(DateTime(-1, 1, 1, 12, 1, 17), FracSec.from!"hnsecs"(90)));
testST(SysTime(DateTime(-1, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(900)), 1, SysTime(DateTime(-1, 2, 1, 12, 1, 17), FracSec.from!"hnsecs"(900)));
testST(SysTime(DateTime(-1, 2, 27, 12, 22, 17), FracSec.from!"hnsecs"(9000)), 5, SysTime(DateTime(-1, 2, 27, 12, 5, 17), FracSec.from!"hnsecs"(9000)));
testST(SysTime(DateTime(-1, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(90_000)), 1, SysTime(DateTime(-1, 12, 1, 12, 1, 17), FracSec.from!"hnsecs"(90_000)));
testST(SysTime(DateTime(-1, 12, 31, 12, 22, 17), FracSec.from!"hnsecs"(900_000)), 23, SysTime(DateTime(-1, 12, 31, 12, 23, 17), FracSec.from!"hnsecs"(900_000)));
testST(SysTime(0, UTC()), 12, SysTime(DateTime(1, 1, 1, 0, 12, 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.minute = 27));
//static assert(!__traits(compiles, ist.minute = 27));
}
/++
Seconds past the current minute.
+/
@property ubyte second() 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);
}
unittest
{
assertPred!"=="(SysTime(0, UTC()).second, 0);
assertPred!"=="(SysTime(1, UTC()).second, 0);
assertPred!"=="(SysTime(-1, UTC()).second, 59);
assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 33)).second, 33);
assertPred!"=="(SysTime(DateTime(0, 1, 1, 0, 0, 33)).second, 33);
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.second));
//static assert(__traits(compiles, ist.second));
}
/++
Seconds past the current minute.
Params
second = The second to set this SysTime's second to.
Throws:
DateTimeException if the given second are not a valid second of a minute.
+/
@property void second(int second)
{
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;
}
unittest
{
static void testSTInvalid(SysTime st, int second)
{
st.second = second;
}
static void testST(SysTime st, int second, in SysTime expected, size_t line = __LINE__)
{
st.second = second;
assertPred!"=="(st, expected, "", __FILE__, line);
}
assertThrown!DateTimeException(testSTInvalid(SysTime(Date(1999, 7, 6)), 60));
//Test A.D.
testST(SysTime(Date(1, 1, 1)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 1)));
testST(SysTime(Date(1, 1, 1)), 7, SysTime(DateTime(1, 1, 1, 0, 0, 7)));
testST(SysTime(Date(1, 1, 1)), 12, SysTime(DateTime(1, 1, 1, 0, 0, 12)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 1), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 7, SysTime(DateTime(1, 1, 1, 0, 0, 7), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 12, SysTime(DateTime(1, 1, 1, 0, 0, 12), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 12, 31, 23, 59, 59)), 1, SysTime(DateTime(1, 12, 31, 23, 59, 1)));
testST(SysTime(DateTime(1, 12, 31, 23, 59, 59)), 7, SysTime(DateTime(1, 12, 31, 23, 59, 7)));
testST(SysTime(DateTime(1, 12, 31, 23, 59, 59)), 12, SysTime(DateTime(1, 12, 31, 23, 59, 12)));
testST(SysTime(DateTime(1, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)), 1, SysTime(DateTime(1, 12, 31, 23, 59, 1), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)), 7, SysTime(DateTime(1, 12, 31, 23, 59, 7), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)), 12, SysTime(DateTime(1, 12, 31, 23, 59, 12), FracSec.from!"hnsecs"(1)));
testST(SysTime(Date(1, 7, 2)), 12, SysTime(DateTime(1, 7, 2, 0, 0, 12)));
testST(SysTime(Date(5007, 7, 2)), 5, SysTime(DateTime(5007, 7, 2, 0, 0, 5)));
testST(SysTime(DateTime(1, 1, 7, 12, 22, 17), FracSec.from!"hnsecs"(7)), 6, SysTime(DateTime(1, 1, 7, 12, 22, 6), FracSec.from!"hnsecs"(7)));
testST(SysTime(DateTime(1, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(70)), 1, SysTime(DateTime(1, 1, 1, 12, 22, 1), FracSec.from!"hnsecs"(70)));
testST(SysTime(DateTime(1, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(700)), 1, SysTime(DateTime(1, 2, 1, 12, 22, 1), FracSec.from!"hnsecs"(700)));
testST(SysTime(DateTime(1, 2, 27, 12, 22, 17), FracSec.from!"hnsecs"(7000)), 5, SysTime(DateTime(1, 2, 27, 12, 22, 5), FracSec.from!"hnsecs"(7000)));
testST(SysTime(DateTime(1, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(70_000)), 1, SysTime(DateTime(1, 12, 1, 12, 22, 1), FracSec.from!"hnsecs"(70_000)));
testST(SysTime(DateTime(1, 12, 31, 12, 22, 17), FracSec.from!"hnsecs"(700_000)), 23, SysTime(DateTime(1, 12, 31, 12, 22, 23), FracSec.from!"hnsecs"(700_000)));
testST(SysTime(DateTime(999, 1, 7, 12, 22, 17), FracSec.from!"hnsecs"(9)), 6, SysTime(DateTime(999, 1, 7, 12, 22, 6), FracSec.from!"hnsecs"(9)));
testST(SysTime(DateTime(999, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(90)), 1, SysTime(DateTime(999, 1, 1, 12, 22, 1), FracSec.from!"hnsecs"(90)));
testST(SysTime(DateTime(999, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(900)), 1, SysTime(DateTime(999, 2, 1, 12, 22, 1), FracSec.from!"hnsecs"(900)));
testST(SysTime(DateTime(999, 2, 27, 12, 22, 17), FracSec.from!"hnsecs"(9000)), 5, SysTime(DateTime(999, 2, 27, 12, 22, 5), FracSec.from!"hnsecs"(9000)));
testST(SysTime(DateTime(999, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(90_000)), 1, SysTime(DateTime(999, 12, 1, 12, 22, 1), FracSec.from!"hnsecs"(90_000)));
testST(SysTime(DateTime(999, 12, 31, 12, 22, 17), FracSec.from!"hnsecs"(900_000)), 23, SysTime(DateTime(999, 12, 31, 12, 22, 23), FracSec.from!"hnsecs"(900_000)));
//Test B.C.
testST(SysTime(Date(0, 1, 1)), 1, SysTime(DateTime(0, 1, 1, 0, 0, 1)));
testST(SysTime(Date(0, 1, 1)), 7, SysTime(DateTime(0, 1, 1, 0, 0, 7)));
testST(SysTime(Date(0, 1, 1)), 12, SysTime(DateTime(0, 1, 1, 0, 0, 12)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 1, SysTime(DateTime(0, 1, 1, 0, 0, 1), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 7, SysTime(DateTime(0, 1, 1, 0, 0, 7), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 12, SysTime(DateTime(0, 1, 1, 0, 0, 12), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 12, 31, 23, 59, 59)), 1, SysTime(DateTime(0, 12, 31, 23, 59, 1)));
testST(SysTime(DateTime(0, 12, 31, 23, 59, 59)), 7, SysTime(DateTime(0, 12, 31, 23, 59, 7)));
testST(SysTime(DateTime(0, 12, 31, 23, 59, 59)), 12, SysTime(DateTime(0, 12, 31, 23, 59, 12)));
testST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)), 1, SysTime(DateTime(0, 12, 31, 23, 59, 1), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)), 7, SysTime(DateTime(0, 12, 31, 23, 59, 7), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)), 12, SysTime(DateTime(0, 12, 31, 23, 59, 12), FracSec.from!"hnsecs"(1)));
testST(SysTime(Date(0, 7, 2)), 7, SysTime(DateTime(0, 7, 2, 0, 0, 7)));
testST(SysTime(Date(-1202, 7, 2)), 1, SysTime(DateTime(-1202, 7, 2, 0, 0, 1)));
testST(SysTime(DateTime(0, 1, 7, 12, 22, 17), FracSec.from!"hnsecs"(7)), 6, SysTime(DateTime(0, 1, 7, 12, 22, 6), FracSec.from!"hnsecs"(7)));
testST(SysTime(DateTime(0, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(70)), 1, SysTime(DateTime(0, 1, 1, 12, 22, 1), FracSec.from!"hnsecs"(70)));
testST(SysTime(DateTime(0, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(700)), 1, SysTime(DateTime(0, 2, 1, 12, 22, 1), FracSec.from!"hnsecs"(700)));
testST(SysTime(DateTime(0, 2, 27, 12, 22, 17), FracSec.from!"hnsecs"(7000)), 5, SysTime(DateTime(0, 2, 27, 12, 22, 5), FracSec.from!"hnsecs"(7000)));
testST(SysTime(DateTime(0, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(70_000)), 1, SysTime(DateTime(0, 12, 1, 12, 22, 1), FracSec.from!"hnsecs"(70_000)));
testST(SysTime(DateTime(0, 12, 31, 12, 22, 17), FracSec.from!"hnsecs"(700_000)), 23, SysTime(DateTime(0, 12, 31, 12, 22, 23), FracSec.from!"hnsecs"(700_000)));
testST(SysTime(DateTime(-1, 1, 7, 12, 22, 17), FracSec.from!"hnsecs"(9)), 6, SysTime(DateTime(-1, 1, 7, 12, 22, 6), FracSec.from!"hnsecs"(9)));
testST(SysTime(DateTime(-1, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(90)), 1, SysTime(DateTime(-1, 1, 1, 12, 22, 1), FracSec.from!"hnsecs"(90)));
testST(SysTime(DateTime(-1, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(900)), 1, SysTime(DateTime(-1, 2, 1, 12, 22, 1), FracSec.from!"hnsecs"(900)));
testST(SysTime(DateTime(-1, 2, 27, 12, 22, 17), FracSec.from!"hnsecs"(9000)), 5, SysTime(DateTime(-1, 2, 27, 12, 22, 5), FracSec.from!"hnsecs"(9000)));
testST(SysTime(DateTime(-1, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(90_000)), 1, SysTime(DateTime(-1, 12, 1, 12, 22, 1), FracSec.from!"hnsecs"(90_000)));
testST(SysTime(DateTime(-1, 12, 31, 12, 22, 17), FracSec.from!"hnsecs"(900_000)), 23, SysTime(DateTime(-1, 12, 31, 12, 22, 23), FracSec.from!"hnsecs"(900_000)));
testST(SysTime(0, UTC()), 12, SysTime(DateTime(1, 1, 1, 0, 0, 12), 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.seconds = 27));
//static assert(!__traits(compiles, ist.seconds = 27));
}
/++
Fractional seconds passed the second.
+/
@property FracSec fracSec() const nothrow
{
try
{
auto hnsecs = removeUnitsFromHNSecs!"days"(adjTime);
if(hnsecs < 0)
hnsecs += convert!("hours", "hnsecs")(24);
hnsecs = removeUnitsFromHNSecs!"seconds"(hnsecs);
return FracSec.from!"hnsecs"(cast(int)hnsecs);
}
catch(Exception e)
assert(0, "FracSec.from!\"hnsecs\"() threw.");
}
unittest
{
assertPred!"=="(SysTime(0, UTC()).fracSec.hnsecs, 0);
assertPred!"=="(SysTime(1, UTC()).fracSec.hnsecs, 1);
assertPred!"=="(SysTime(-1, UTC()).fracSec.hnsecs, 9_999_999);
assertPred!"=="(SysTime(DateTime(200, 3, 30, 1, 27, 19), FracSec.from!"hnsecs"(348), UTC()).fracSec.hnsecs, 348);
assertPred!"=="(SysTime(DateTime(-1, 2, 17, 4, 5, 22), FracSec.from!"hnsecs"(347), UTC()).fracSec.hnsecs, 347);
assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 33), FracSec.from!"hnsecs"(502)).fracSec, FracSec.from!"hnsecs"(502));
assertPred!"=="(SysTime(DateTime(0, 1, 1, 0, 0, 33), FracSec.from!"hnsecs"(502)).fracSec, FracSec.from!"hnsecs"(502));
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.fracSec));
//static assert(__traits(compiles, ist.fracSec));
}
/++
Fractional seconds passed the second.
Params
fracSec = The fractional seconds to set this SysTimes's fractional
seconds to.
+/
@property void fracSec(FracSec fracSec) nothrow
{
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);
immutable second = getUnitsFromHNSecs!"seconds"(hnsecs);
hnsecs = fracSec.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;
}
unittest
{
static void testST(SysTime st, int hnsecs, in SysTime expected, size_t line = __LINE__)
{
st.fracSec = FracSec.from!"hnsecs"(hnsecs);
assertPred!"=="(st, expected, "", __FILE__, line);
}
//Test A.D.
testST(SysTime(Date(1, 1, 1)), 0, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
testST(SysTime(Date(1, 1, 1)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(Date(1, 1, 1)), 7, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(7)));
testST(SysTime(Date(1, 1, 1)), 12, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(12)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 7, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(7)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 12, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(12)));
testST(SysTime(DateTime(1, 12, 31, 23, 59, 59)), 0, SysTime(DateTime(1, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0)));
testST(SysTime(DateTime(1, 12, 31, 23, 59, 59)), 1, SysTime(DateTime(1, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 12, 31, 23, 59, 59)), 7, SysTime(DateTime(1, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(7)));
testST(SysTime(DateTime(1, 12, 31, 23, 59, 59)), 12, SysTime(DateTime(1, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(12)));
testST(SysTime(DateTime(1, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)), 1, SysTime(DateTime(1, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)), 7, SysTime(DateTime(1, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(7)));
testST(SysTime(DateTime(1, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)), 12, SysTime(DateTime(1, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(12)));
testST(SysTime(Date(1, 7, 2)), 12, SysTime(DateTime(1, 7, 2, 0, 0, 0), FracSec.from!"hnsecs"(12)));
testST(SysTime(Date(5007, 7, 2)), 5, SysTime(DateTime(5007, 7, 2, 0, 0, 0), FracSec.from!"hnsecs"(5)));
testST(SysTime(DateTime(1, 1, 7, 12, 22, 17), FracSec.from!"hnsecs"(7)), 6, SysTime(DateTime(1, 1, 7, 12, 22, 17), FracSec.from!"hnsecs"(6)));
testST(SysTime(DateTime(1, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(70)), 1, SysTime(DateTime(1, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(700)), 1, SysTime(DateTime(1, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 2, 27, 12, 22, 17), FracSec.from!"hnsecs"(7000)), 5, SysTime(DateTime(1, 2, 27, 12, 22, 17), FracSec.from!"hnsecs"(5)));
testST(SysTime(DateTime(1, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(70_000)), 1, SysTime(DateTime(1, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 12, 31, 12, 22, 17), FracSec.from!"hnsecs"(700_000)), 23, SysTime(DateTime(1, 12, 31, 12, 22, 17), FracSec.from!"hnsecs"(23)));
testST(SysTime(DateTime(999, 1, 7, 12, 22, 17), FracSec.from!"hnsecs"(9)), 6, SysTime(DateTime(999, 1, 7, 12, 22, 17), FracSec.from!"hnsecs"(6)));
testST(SysTime(DateTime(999, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(90)), 1, SysTime(DateTime(999, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(999, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(900)), 1, SysTime(DateTime(999, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(999, 2, 27, 12, 22, 17), FracSec.from!"hnsecs"(9000)), 5, SysTime(DateTime(999, 2, 27, 12, 22, 17), FracSec.from!"hnsecs"(5)));
testST(SysTime(DateTime(999, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(90_000)), 1, SysTime(DateTime(999, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(999, 12, 31, 12, 22, 17), FracSec.from!"hnsecs"(900_000)), 23, SysTime(DateTime(999, 12, 31, 12, 22, 17), FracSec.from!"hnsecs"(23)));
//Test B.C.
testST(SysTime(Date(0, 1, 1)), 0, SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
testST(SysTime(Date(0, 1, 1)), 1, SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(Date(0, 1, 1)), 7, SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(7)));
testST(SysTime(Date(0, 1, 1)), 12, SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(12)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 0, SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 1, SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 7, SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(7)));
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 12, SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(12)));
testST(SysTime(DateTime(0, 12, 31, 23, 59, 59)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0)));
testST(SysTime(DateTime(0, 12, 31, 23, 59, 59)), 1, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 12, 31, 23, 59, 59)), 7, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(7)));
testST(SysTime(DateTime(0, 12, 31, 23, 59, 59)), 12, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(12)));
testST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)), 1, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)), 7, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(7)));
testST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)), 12, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(12)));
testST(SysTime(Date(0, 7, 2)), 7, SysTime(DateTime(0, 7, 2, 0, 0, 0), FracSec.from!"hnsecs"(7)));
testST(SysTime(Date(-1202, 7, 2)), 1, SysTime(DateTime(-1202, 7, 2, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 1, 7, 12, 22, 17), FracSec.from!"hnsecs"(7)), 6, SysTime(DateTime(0, 1, 7, 12, 22, 17), FracSec.from!"hnsecs"(6)));
testST(SysTime(DateTime(0, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(70)), 1, SysTime(DateTime(0, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(700)), 1, SysTime(DateTime(0, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 2, 27, 12, 22, 17), FracSec.from!"hnsecs"(7000)), 5, SysTime(DateTime(0, 2, 27, 12, 22, 17), FracSec.from!"hnsecs"(5)));
testST(SysTime(DateTime(0, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(70_000)), 1, SysTime(DateTime(0, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 12, 31, 12, 22, 17), FracSec.from!"hnsecs"(700_000)), 23, SysTime(DateTime(0, 12, 31, 12, 22, 17), FracSec.from!"hnsecs"(23)));
testST(SysTime(DateTime(-1, 1, 7, 12, 22, 17), FracSec.from!"hnsecs"(9)), 6, SysTime(DateTime(-1, 1, 7, 12, 22, 17), FracSec.from!"hnsecs"(6)));
testST(SysTime(DateTime(-1, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(90)), 1, SysTime(DateTime(-1, 1, 1, 12, 22, 17), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(-1, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(900)), 1, SysTime(DateTime(-1, 2, 1, 12, 22, 17), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(-1, 2, 27, 12, 22, 17), FracSec.from!"hnsecs"(9000)), 5, SysTime(DateTime(-1, 2, 27, 12, 22, 17), FracSec.from!"hnsecs"(5)));
testST(SysTime(DateTime(-1, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(90_000)), 1, SysTime(DateTime(-1, 12, 1, 12, 22, 17), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(-1, 12, 31, 12, 22, 17), FracSec.from!"hnsecs"(900_000)), 23, SysTime(DateTime(-1, 12, 31, 12, 22, 17), FracSec.from!"hnsecs"(23)));
testST(SysTime(0, UTC()), 12, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(12), 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.fracSec = FracSec.from!"msecs"(7)));
//static assert(!__traits(compiles, ist.fracSec = FracSec.from!"msecs"(7)));
}
/++
The total hnsecs from midnight, January 1st, 1 A.D. UTC. This is the internal
representation of SysTime.
+/
@property long stdTime() const pure nothrow
{
return _stdTime;
}
unittest
{
assertPred!"=="(SysTime(0).stdTime, 0);
assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 33), FracSec.from!"hnsecs"(502), UTC()).stdTime, 330000502L);
assertPred!"=="(SysTime(DateTime(1970, 1, 1, 0, 0, 0), UTC()).stdTime, 621355968000000000L);
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));
//static assert(__traits(compiles, ist.stdTime));
}
/++
The total hnsecs from midnight, January 1st, 1 A.D. UTC. This is the internal
representation of SysTime.
Params
stdTime = The number of hnsecs since January 1st, 1 A.D. UTC.
+/
@property void stdTime(long stdTime) pure nothrow
{
_stdTime = stdTime;
}
unittest
{
{
auto st = SysTime(0, UTC());
st.stdTime = 330000502L;
assertPred!"=="(st, SysTime(DateTime(1, 1, 1, 0, 0, 33), FracSec.from!"hnsecs"(502), UTC()));
}
{
auto st = SysTime(0, UTC());
st.stdTime = 621355968000000000L;
assertPred!"=="(st, 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 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 SysTime's time zone before returning.
+/
@property immutable(TimeZone) timezone() const pure nothrow
{
return _timezone.get;
}
/++
The current time zone of this 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 SysTime's time zone before returning.
+/
@property void timezone(immutable TimeZone timezone) pure nothrow
{
_timezone = timezone;
}
/++
Returns whether DST is in effect for this SysTime.
+/
@property bool dstInEffect() const nothrow
{
return _timezone.dstInEffect(_stdTime);
//This function's unit testing is done in the time zone classes.
}
/++
Returns a SysTime with the same std time as this one, but with LocalTime
as its time zone.
+/
SysTime toLocalTime() const nothrow
{
return SysTime(_stdTime, LocalTime());
}
unittest
{
{
auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), FracSec.from!"hnsecs"(27));
assertPred!"=="(sysTime, sysTime.toLocalTime());
assertPred!"=="(sysTime._stdTime, sysTime.toLocalTime()._stdTime);
assert(sysTime.toLocalTime().timezone is LocalTime());
assert(sysTime.toLocalTime().timezone is sysTime.timezone);
assert(sysTime.toLocalTime().timezone !is UTC());
}
{
immutable stz = new SimpleTimeZone(-3 * 60);
auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), FracSec.from!"hnsecs"(27), stz);
assertPred!"=="(sysTime, sysTime.toLocalTime());
assertPred!"=="(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 SysTime with the same std time as this one, but with UTC as
its time zone.
+/
SysTime toUTC() const pure nothrow
{
return SysTime(_stdTime, UTC());
}
unittest
{
auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), FracSec.from!"hnsecs"(27));
assertPred!"=="(sysTime, sysTime.toUTC());
assertPred!"=="(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 SysTime with the same std time as this one, but with given
time zone as its time zone.
+/
SysTime toOtherTZ(immutable TimeZone tz) const pure nothrow
{
return SysTime(_stdTime, tz);
}
unittest
{
immutable stz = new SimpleTimeZone(11 * 60);
auto sysTime = SysTime(DateTime(1982, 1, 4, 8, 59, 7), FracSec.from!"hnsecs"(27));
assertPred!"=="(sysTime, sysTime.toOtherTZ(stz));
assertPred!"=="(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());
}
/++
Returns a time_t which represents this SysTime.
If time_t is 32 bits, rather than 64, and the result can't fit in a 32-bit value, then the
closest value that can be held in 32 bits will be used (so time_t.max if it goes over or time_t.min
if it goes under).
+/
time_t toUnixTime() const pure nothrow
{
return stdTimeToUnixTime(_stdTime);
}
unittest
{
assertPred!"=="(SysTime(DateTime(1970, 1, 1), UTC()).toUnixTime, 0);
assertPred!"=="(SysTime(DateTime(1970, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1), UTC()).toUnixTime, 0);
assertPred!"=="(SysTime(DateTime(1970, 1, 1, 0, 0, 0), FracSec.from!"usecs"(1), UTC()).toUnixTime, 0);
assertPred!"=="(SysTime(DateTime(1970, 1, 1, 0, 0, 0), FracSec.from!"msecs"(1), UTC()).toUnixTime, 0);
assertPred!"=="(SysTime(DateTime(1970, 1, 1, 0, 0, 1), UTC()).toUnixTime, 1);
assertPred!"=="(SysTime(DateTime(1969, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999), UTC()).toUnixTime, 0);
assertPred!"=="(SysTime(DateTime(1969, 12, 31, 23, 59, 59), FracSec.from!"usecs"(999_999), UTC()).toUnixTime, 0);
assertPred!"=="(SysTime(DateTime(1969, 12, 31, 23, 59, 59), FracSec.from!"msecs"(999), UTC()).toUnixTime, 0);
assertPred!"=="(SysTime(DateTime(1969, 12, 31, 23, 59, 59), UTC()).toUnixTime, -1);
}
/++
Returns a tm which represents this SysTime.
+/
tm toTM() const nothrow
{
try
{
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)
{
char[] zone = (timeInfo.tm_isdst ? _timezone.dstName : _timezone.stdName).dup;
zone ~= "\0";
timeInfo.tm_gmtoff = cast(int)convert!("hnsecs", "seconds")(adjTime - _stdTime);
timeInfo.tm_zone = zone.ptr;
}
return timeInfo;
}
catch(Exception e)
assert(0, "Either DateTime's constructor threw.");
}
unittest
{
version(Posix)
{
scope(exit) clearTZEnvVar();
setTZEnvVar("America/Los_Angeles");
}
{
auto timeInfo = SysTime(DateTime(1970, 1, 1)).toTM();
assertPred!"=="(timeInfo.tm_sec, 0);
assertPred!"=="(timeInfo.tm_min, 0);
assertPred!"=="(timeInfo.tm_hour, 0);
assertPred!"=="(timeInfo.tm_mday, 1);
assertPred!"=="(timeInfo.tm_mon, 0);
assertPred!"=="(timeInfo.tm_year, 70);
assertPred!"=="(timeInfo.tm_wday, 4);
assertPred!"=="(timeInfo.tm_yday, 0);
version(Posix)
assertPred!"=="(timeInfo.tm_isdst, 0);
else version(Windows)
assert(timeInfo.tm_isdst == 0 || timeInfo.tm_isdst == 1);
version(Posix)
{
assertPred!"=="(timeInfo.tm_gmtoff, -8 * 60 * 60);
assertPred!"=="(to!string(timeInfo.tm_zone), "PST");
}
}
{
auto timeInfo = SysTime(DateTime(2010, 7, 4, 12, 15, 7), FracSec.from!"hnsecs"(15)).toTM();
assertPred!"=="(timeInfo.tm_sec, 7);
assertPred!"=="(timeInfo.tm_min, 15);
assertPred!"=="(timeInfo.tm_hour, 12);
assertPred!"=="(timeInfo.tm_mday, 4);
assertPred!"=="(timeInfo.tm_mon, 6);
assertPred!"=="(timeInfo.tm_year, 110);
assertPred!"=="(timeInfo.tm_wday, 0);
assertPred!"=="(timeInfo.tm_yday, 184);
version(Posix)
assertPred!"=="(timeInfo.tm_isdst, 1);
else version(Windows)
assert(timeInfo.tm_isdst == 0 || timeInfo.tm_isdst == 1);
version(Posix)
{
assertPred!"=="(timeInfo.tm_gmtoff, -7 * 60 * 60);
assertPred!"=="(to!string(timeInfo.tm_zone), "PDT");
}
}
}
/++
Adds the given number of years or months to this 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 days 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 SysTime.
allowOverflow = Whether the days should be allowed to overflow, causing
the month to increment.
Examples:
--------------------
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)));
--------------------
+/
ref SysTime add(string units)(long years, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) 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(years, 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 add!"years"() with AllowDayOverlow.yes
unittest
{
//Test A.D.
{
auto sysTime = SysTime(Date(1999, 7, 6));
sysTime.add!"years"(7);
assertPred!"=="(sysTime, SysTime(Date(2006, 7, 6)));
sysTime.add!"years"(-9);
assertPred!"=="(sysTime, SysTime(Date(1997, 7, 6)));
}
{
auto sysTime = SysTime(Date(1999, 2, 28));
sysTime.add!"years"(1);
assertPred!"=="(sysTime, SysTime(Date(2000, 2, 28)));
}
{
auto sysTime = SysTime(Date(2000, 2, 29));
sysTime.add!"years"(-1);
assertPred!"=="(sysTime, SysTime(Date(1999, 3, 1)));
}
{
auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 7, 3), FracSec.from!"msecs"(234));
sysTime.add!"years"(7);
assertPred!"=="(sysTime, SysTime(DateTime(2006, 7, 6, 12, 7, 3), FracSec.from!"msecs"(234)));
sysTime.add!"years"(-9);
assertPred!"=="(sysTime, SysTime(DateTime(1997, 7, 6, 12, 7, 3), FracSec.from!"msecs"(234)));
}
{
auto sysTime = SysTime(DateTime(1999, 2, 28, 0, 7, 2), FracSec.from!"usecs"(1207));
sysTime.add!"years"(1);
assertPred!"=="(sysTime, SysTime(DateTime(2000, 2, 28, 0, 7, 2), FracSec.from!"usecs"(1207)));
}
{
auto sysTime = SysTime(DateTime(2000, 2, 29, 0, 7, 2), FracSec.from!"usecs"(1207));
sysTime.add!"years"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(1999, 3, 1, 0, 7, 2), FracSec.from!"usecs"(1207)));
}
//Test B.C.
{
auto sysTime = SysTime(Date(-1999, 7, 6));
sysTime.add!"years"(-7);
assertPred!"=="(sysTime, SysTime(Date(-2006, 7, 6)));
sysTime.add!"years"(9);
assertPred!"=="(sysTime, SysTime(Date(-1997, 7, 6)));
}
{
auto sysTime = SysTime(Date(-1999, 2, 28));
sysTime.add!"years"(-1);
assertPred!"=="(sysTime, SysTime(Date(-2000, 2, 28)));
}
{
auto sysTime = SysTime(Date(-2000, 2, 29));
sysTime.add!"years"(1);
assertPred!"=="(sysTime, SysTime(Date(-1999, 3, 1)));
}
{
auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 7, 3), FracSec.from!"msecs"(234));
sysTime.add!"years"(-7);
assertPred!"=="(sysTime, SysTime(DateTime(-2006, 7, 6, 12, 7, 3), FracSec.from!"msecs"(234)));
sysTime.add!"years"(9);
assertPred!"=="(sysTime, SysTime(DateTime(-1997, 7, 6, 12, 7, 3), FracSec.from!"msecs"(234)));
}
{
auto sysTime = SysTime(DateTime(-1999, 2, 28, 3, 3, 3), FracSec.from!"hnsecs"(3));
sysTime.add!"years"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(-2000, 2, 28, 3, 3, 3), FracSec.from!"hnsecs"(3)));
}
{
auto sysTime = SysTime(DateTime(-2000, 2, 29, 3, 3, 3), FracSec.from!"hnsecs"(3));
sysTime.add!"years"(1);
assertPred!"=="(sysTime, SysTime(DateTime(-1999, 3, 1, 3, 3, 3), FracSec.from!"hnsecs"(3)));
}
//Test Both
{
auto sysTime = SysTime(Date(4, 7, 6));
sysTime.add!"years"(-5);
assertPred!"=="(sysTime, SysTime(Date(-1, 7, 6)));
sysTime.add!"years"(5);
assertPred!"=="(sysTime, SysTime(Date(4, 7, 6)));
}
{
auto sysTime = SysTime(Date(-4, 7, 6));
sysTime.add!"years"(5);
assertPred!"=="(sysTime, SysTime(Date(1, 7, 6)));
sysTime.add!"years"(-5);
assertPred!"=="(sysTime, SysTime(Date(-4, 7, 6)));
}
{
auto sysTime = SysTime(Date(4, 7, 6));
sysTime.add!"years"(-8);
assertPred!"=="(sysTime, SysTime(Date(-4, 7, 6)));
sysTime.add!"years"(8);
assertPred!"=="(sysTime, SysTime(Date(4, 7, 6)));
}
{
auto sysTime = SysTime(Date(-4, 7, 6));
sysTime.add!"years"(8);
assertPred!"=="(sysTime, SysTime(Date(4, 7, 6)));
sysTime.add!"years"(-8);
assertPred!"=="(sysTime, SysTime(Date(-4, 7, 6)));
}
{
auto sysTime = SysTime(Date(-4, 2, 29));
sysTime.add!"years"(5);
assertPred!"=="(sysTime, SysTime(Date(1, 3, 1)));
}
{
auto sysTime = SysTime(Date(4, 2, 29));
sysTime.add!"years"(-5);
assertPred!"=="(sysTime, SysTime(Date(-1, 3, 1)));
}
{
auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
sysTime.add!"years"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
sysTime.add!"years"(1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
}
{
auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
sysTime.add!"years"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
sysTime.add!"years"(1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
}
{
auto sysTime = SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
sysTime.add!"years"(1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
sysTime.add!"years"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
}
{
auto sysTime = SysTime(DateTime(0, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
sysTime.add!"years"(1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
sysTime.add!"years"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
}
{
auto sysTime = SysTime(DateTime(4, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329));
sysTime.add!"years"(-5);
assertPred!"=="(sysTime, SysTime(DateTime(-1, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329)));
sysTime.add!"years"(5);
assertPred!"=="(sysTime, SysTime(DateTime(4, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329)));
}
{
auto sysTime = SysTime(DateTime(-4, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329));
sysTime.add!"years"(5);
assertPred!"=="(sysTime, SysTime(DateTime(1, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329)));
sysTime.add!"years"(-5);
assertPred!"=="(sysTime, SysTime(DateTime(-4, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329)));
}
{
auto sysTime = SysTime(DateTime(-4, 2, 29, 5, 5, 5), FracSec.from!"msecs"(555));
sysTime.add!"years"(5);
assertPred!"=="(sysTime, SysTime(DateTime(1, 3, 1, 5, 5, 5), FracSec.from!"msecs"(555)));
}
{
auto sysTime = SysTime(DateTime(4, 2, 29, 5, 5, 5), FracSec.from!"msecs"(555));
sysTime.add!"years"(-5);
assertPred!"=="(sysTime, SysTime(DateTime(-1, 3, 1, 5, 5, 5), FracSec.from!"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)));
//Verify Examples.
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 AllowDayOverlow.no
unittest
{
//Test A.D.
{
auto sysTime = SysTime(Date(1999, 7, 6));
sysTime.add!"years"(7, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(2006, 7, 6)));
sysTime.add!"years"(-9, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1997, 7, 6)));
}
{
auto sysTime = SysTime(Date(1999, 2, 28));
sysTime.add!"years"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(2000, 2, 28)));
}
{
auto sysTime = SysTime(Date(2000, 2, 29));
sysTime.add!"years"(-1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 2, 28)));
}
{
auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 7, 3), FracSec.from!"msecs"(234));
sysTime.add!"years"(7, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(2006, 7, 6, 12, 7, 3), FracSec.from!"msecs"(234)));
sysTime.add!"years"(-9, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1997, 7, 6, 12, 7, 3), FracSec.from!"msecs"(234)));
}
{
auto sysTime = SysTime(DateTime(1999, 2, 28, 0, 7, 2), FracSec.from!"usecs"(1207));
sysTime.add!"years"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(2000, 2, 28, 0, 7, 2), FracSec.from!"usecs"(1207)));
}
{
auto sysTime = SysTime(DateTime(2000, 2, 29, 0, 7, 2), FracSec.from!"usecs"(1207));
sysTime.add!"years"(-1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1999, 2, 28, 0, 7, 2), FracSec.from!"usecs"(1207)));
}
//Test B.C.
{
auto sysTime = SysTime(Date(-1999, 7, 6));
sysTime.add!"years"(-7, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-2006, 7, 6)));
sysTime.add!"years"(9, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1997, 7, 6)));
}
{
auto sysTime = SysTime(Date(-1999, 2, 28));
sysTime.add!"years"(-1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-2000, 2, 28)));
}
{
auto sysTime = SysTime(Date(-2000, 2, 29));
sysTime.add!"years"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1999, 2, 28)));
}
{
auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 7, 3), FracSec.from!"msecs"(234));
sysTime.add!"years"(-7, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(-2006, 7, 6, 12, 7, 3), FracSec.from!"msecs"(234)));
sysTime.add!"years"(9, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(-1997, 7, 6, 12, 7, 3), FracSec.from!"msecs"(234)));
}
{
auto sysTime = SysTime(DateTime(-1999, 2, 28, 3, 3, 3), FracSec.from!"hnsecs"(3));
sysTime.add!"years"(-1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(-2000, 2, 28, 3, 3, 3), FracSec.from!"hnsecs"(3)));
}
{
auto sysTime = SysTime(DateTime(-2000, 2, 29, 3, 3, 3), FracSec.from!"hnsecs"(3));
sysTime.add!"years"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(-1999, 2, 28, 3, 3, 3), FracSec.from!"hnsecs"(3)));
}
//Test Both
{
auto sysTime = SysTime(Date(4, 7, 6));
sysTime.add!"years"(-5, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1, 7, 6)));
sysTime.add!"years"(5, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(4, 7, 6)));
}
{
auto sysTime = SysTime(Date(-4, 7, 6));
sysTime.add!"years"(5, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1, 7, 6)));
sysTime.add!"years"(-5, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-4, 7, 6)));
}
{
auto sysTime = SysTime(Date(4, 7, 6));
sysTime.add!"years"(-8, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-4, 7, 6)));
sysTime.add!"years"(8, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(4, 7, 6)));
}
{
auto sysTime = SysTime(Date(-4, 7, 6));
sysTime.add!"years"(8, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(4, 7, 6)));
sysTime.add!"years"(-8, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-4, 7, 6)));
}
{
auto sysTime = SysTime(Date(-4, 2, 29));
sysTime.add!"years"(5, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1, 2, 28)));
}
{
auto sysTime = SysTime(Date(4, 2, 29));
sysTime.add!"years"(-5, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1, 2, 28)));
}
{
auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
sysTime.add!"years"(-1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
sysTime.add!"years"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
}
{
auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
sysTime.add!"years"(-1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(0, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
sysTime.add!"years"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
}
{
auto sysTime = SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
sysTime.add!"years"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
sysTime.add!"years"(-1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
}
{
auto sysTime = SysTime(DateTime(0, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
sysTime.add!"years"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
sysTime.add!"years"(-1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(0, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
}
{
auto sysTime = SysTime(DateTime(4, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329));
sysTime.add!"years"(-5);
assertPred!"=="(sysTime, SysTime(DateTime(-1, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329)));
sysTime.add!"years"(5);
assertPred!"=="(sysTime, SysTime(DateTime(4, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329)));
}
{
auto sysTime = SysTime(DateTime(4, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329));
sysTime.add!"years"(-5, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(-1, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329)));
sysTime.add!"years"(5, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(4, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329)));
}
{
auto sysTime = SysTime(DateTime(-4, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329));
sysTime.add!"years"(5, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329)));
sysTime.add!"years"(-5, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(-4, 7, 6, 14, 7, 1), FracSec.from!"usecs"(54329)));
}
{
auto sysTime = SysTime(DateTime(-4, 2, 29, 5, 5, 5), FracSec.from!"msecs"(555));
sysTime.add!"years"(5, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1, 2, 28, 5, 5, 5), FracSec.from!"msecs"(555)));
}
{
auto sysTime = SysTime(DateTime(4, 2, 29, 5, 5, 5), FracSec.from!"msecs"(555));
sysTime.add!"years"(-5, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(-1, 2, 28, 5, 5, 5), FracSec.from!"msecs"(555)));
}
}
//Test add!"months"() with AllowDayOverlow.yes
unittest
{
//Test A.D.
{
auto sysTime = SysTime(Date(1999, 7, 6));
sysTime.add!"months"(3);
assertPred!"=="(sysTime, SysTime(Date(1999, 10, 6)));
sysTime.add!"months"(-4);
assertPred!"=="(sysTime, SysTime(Date(1999, 6, 6)));
}
{
auto sysTime = SysTime(Date(1999, 7, 6));
sysTime.add!"months"(6);
assertPred!"=="(sysTime, SysTime(Date(2000, 1, 6)));
sysTime.add!"months"(-6);
assertPred!"=="(sysTime, SysTime(Date(1999, 7, 6)));
}
{
auto sysTime = SysTime(Date(1999, 7, 6));
sysTime.add!"months"(27);
assertPred!"=="(sysTime, SysTime(Date(2001, 10, 6)));
sysTime.add!"months"(-28);
assertPred!"=="(sysTime, SysTime(Date(1999, 6, 6)));
}
{
auto sysTime = SysTime(Date(1999, 5, 31));
sysTime.add!"months"(1);
assertPred!"=="(sysTime, SysTime(Date(1999, 7, 1)));
}
{
auto sysTime = SysTime(Date(1999, 5, 31));
sysTime.add!"months"(-1);
assertPred!"=="(sysTime, SysTime(Date(1999, 5, 1)));
}
{
auto sysTime = SysTime(Date(1999, 2, 28));
sysTime.add!"months"(12);
assertPred!"=="(sysTime, SysTime(Date(2000, 2, 28)));
}
{
auto sysTime = SysTime(Date(2000, 2, 29));
sysTime.add!"months"(12);
assertPred!"=="(sysTime, SysTime(Date(2001, 3, 1)));
}
{
auto sysTime = SysTime(Date(1999, 7, 31));
sysTime.add!"months"(1);
assertPred!"=="(sysTime, SysTime(Date(1999, 8, 31)));
sysTime.add!"months"(1);
assertPred!"=="(sysTime, SysTime(Date(1999, 10, 1)));
}
{
auto sysTime = SysTime(Date(1998, 8, 31));
sysTime.add!"months"(13);
assertPred!"=="(sysTime, SysTime(Date(1999, 10, 1)));
sysTime.add!"months"(-13);
assertPred!"=="(sysTime, SysTime(Date(1998, 9, 1)));
}
{
auto sysTime = SysTime(Date(1997, 12, 31));
sysTime.add!"months"(13);
assertPred!"=="(sysTime, SysTime(Date(1999, 1, 31)));
sysTime.add!"months"(-13);
assertPred!"=="(sysTime, SysTime(Date(1997, 12, 31)));
}
{
auto sysTime = SysTime(Date(1997, 12, 31));
sysTime.add!"months"(14);
assertPred!"=="(sysTime, SysTime(Date(1999, 3, 3)));
sysTime.add!"months"(-14);
assertPred!"=="(sysTime, SysTime(Date(1998, 1, 3)));
}
{
auto sysTime = SysTime(Date(1998, 12, 31));
sysTime.add!"months"(14);
assertPred!"=="(sysTime, SysTime(Date(2000, 3, 2)));
sysTime.add!"months"(-14);
assertPred!"=="(sysTime, SysTime(Date(1999, 1, 2)));
}
{
auto sysTime = SysTime(Date(1999, 12, 31));
sysTime.add!"months"(14);
assertPred!"=="(sysTime, SysTime(Date(2001, 3, 3)));
sysTime.add!"months"(-14);
assertPred!"=="(sysTime, SysTime(Date(2000, 1, 3)));
}
{
auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), FracSec.from!"usecs"(5007));
sysTime.add!"months"(3);
assertPred!"=="(sysTime, SysTime(DateTime(1999, 10, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
sysTime.add!"months"(-4);
assertPred!"=="(sysTime, SysTime(DateTime(1999, 6, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
}
{
auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
sysTime.add!"months"(14);
assertPred!"=="(sysTime, SysTime(DateTime(2000, 3, 2, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
sysTime.add!"months"(-14);
assertPred!"=="(sysTime, SysTime(DateTime(1999, 1, 2, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
}
{
auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
sysTime.add!"months"(14);
assertPred!"=="(sysTime, SysTime(DateTime(2001, 3, 3, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
sysTime.add!"months"(-14);
assertPred!"=="(sysTime, SysTime(DateTime(2000, 1, 3, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
}
//Test B.C.
{
auto sysTime = SysTime(Date(-1999, 7, 6));
sysTime.add!"months"(3);
assertPred!"=="(sysTime, SysTime(Date(-1999, 10, 6)));
sysTime.add!"months"(-4);
assertPred!"=="(sysTime, SysTime(Date(-1999, 6, 6)));
}
{
auto sysTime = SysTime(Date(-1999, 7, 6));
sysTime.add!"months"(6);
assertPred!"=="(sysTime, SysTime(Date(-1998, 1, 6)));
sysTime.add!"months"(-6);
assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 6)));
}
{
auto sysTime = SysTime(Date(-1999, 7, 6));
sysTime.add!"months"(-27);
assertPred!"=="(sysTime, SysTime(Date(-2001, 4, 6)));
sysTime.add!"months"(28);
assertPred!"=="(sysTime, SysTime(Date(-1999, 8, 6)));
}
{
auto sysTime = SysTime(Date(-1999, 5, 31));
sysTime.add!"months"(1);
assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 1)));
}
{
auto sysTime = SysTime(Date(-1999, 5, 31));
sysTime.add!"months"(-1);
assertPred!"=="(sysTime, SysTime(Date(-1999, 5, 1)));
}
{
auto sysTime = SysTime(Date(-1999, 2, 28));
sysTime.add!"months"(-12);
assertPred!"=="(sysTime, SysTime(Date(-2000, 2, 28)));
}
{
auto sysTime = SysTime(Date(-2000, 2, 29));
sysTime.add!"months"(-12);
assertPred!"=="(sysTime, SysTime(Date(-2001, 3, 1)));
}
{
auto sysTime = SysTime(Date(-1999, 7, 31));
sysTime.add!"months"(1);
assertPred!"=="(sysTime, SysTime(Date(-1999, 8, 31)));
sysTime.add!"months"(1);
assertPred!"=="(sysTime, SysTime(Date(-1999, 10, 1)));
}
{
auto sysTime = SysTime(Date(-1998, 8, 31));
sysTime.add!"months"(13);
assertPred!"=="(sysTime, SysTime(Date(-1997, 10, 1)));
sysTime.add!"months"(-13);
assertPred!"=="(sysTime, SysTime(Date(-1998, 9, 1)));
}
{
auto sysTime = SysTime(Date(-1997, 12, 31));
sysTime.add!"months"(13);
assertPred!"=="(sysTime, SysTime(Date(-1995, 1, 31)));
sysTime.add!"months"(-13);
assertPred!"=="(sysTime, SysTime(Date(-1997, 12, 31)));
}
{
auto sysTime = SysTime(Date(-1997, 12, 31));
sysTime.add!"months"(14);
assertPred!"=="(sysTime, SysTime(Date(-1995, 3, 3)));
sysTime.add!"months"(-14);
assertPred!"=="(sysTime, SysTime(Date(-1996, 1, 3)));
}
{
auto sysTime = SysTime(Date(-2002, 12, 31));
sysTime.add!"months"(14);
assertPred!"=="(sysTime, SysTime(Date(-2000, 3, 2)));
sysTime.add!"months"(-14);
assertPred!"=="(sysTime, SysTime(Date(-2001, 1, 2)));
}
{
auto sysTime = SysTime(Date(-2001, 12, 31));
sysTime.add!"months"(14);
assertPred!"=="(sysTime, SysTime(Date(-1999, 3, 3)));
sysTime.add!"months"(-14);
assertPred!"=="(sysTime, SysTime(Date(-2000, 1, 3)));
}
{
auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), FracSec.from!"usecs"(5007));
sysTime.add!"months"(3);
assertPred!"=="(sysTime, SysTime(DateTime(-1999, 10, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
sysTime.add!"months"(-4);
assertPred!"=="(sysTime, SysTime(DateTime(-1999, 6, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
}
{
auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
sysTime.add!"months"(14);
assertPred!"=="(sysTime, SysTime(DateTime(-2000, 3, 2, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
sysTime.add!"months"(-14);
assertPred!"=="(sysTime, SysTime(DateTime(-2001, 1, 2, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
}
{
auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
sysTime.add!"months"(14);
assertPred!"=="(sysTime, SysTime(DateTime(-1999, 3, 3, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
sysTime.add!"months"(-14);
assertPred!"=="(sysTime, SysTime(DateTime(-2000, 1, 3, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
}
//Test Both
{
auto sysTime = SysTime(Date(1, 1, 1));
sysTime.add!"months"(-1);
assertPred!"=="(sysTime, SysTime(Date(0, 12, 1)));
sysTime.add!"months"(1);
assertPred!"=="(sysTime, SysTime(Date(1, 1, 1)));
}
{
auto sysTime = SysTime(Date(4, 1, 1));
sysTime.add!"months"(-48);
assertPred!"=="(sysTime, SysTime(Date(0, 1, 1)));
sysTime.add!"months"(48);
assertPred!"=="(sysTime, SysTime(Date(4, 1, 1)));
}
{
auto sysTime = SysTime(Date(4, 3, 31));
sysTime.add!"months"(-49);
assertPred!"=="(sysTime, SysTime(Date(0, 3, 2)));
sysTime.add!"months"(49);
assertPred!"=="(sysTime, SysTime(Date(4, 4, 2)));
}
{
auto sysTime = SysTime(Date(4, 3, 31));
sysTime.add!"months"(-85);
assertPred!"=="(sysTime, SysTime(Date(-3, 3, 3)));
sysTime.add!"months"(85);
assertPred!"=="(sysTime, SysTime(Date(4, 4, 3)));
}
{
auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
sysTime.add!"months"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
sysTime.add!"months"(1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
}
{
auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
sysTime.add!"months"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
sysTime.add!"months"(1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
}
{
auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
sysTime.add!"months"(1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
sysTime.add!"months"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
}
{
auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
sysTime.add!"months"(1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
sysTime.add!"months"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
}
{
auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), FracSec.from!"hnsecs"(17));
sysTime.add!"months"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 0, 7, 9), FracSec.from!"hnsecs"(17)));
sysTime.add!"months"(1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 7, 9), FracSec.from!"hnsecs"(17)));
}
{
auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), FracSec.from!"msecs"(9));
sysTime.add!"months"(-85);
assertPred!"=="(sysTime, SysTime(DateTime(-3, 3, 3, 12, 11, 10), FracSec.from!"msecs"(9)));
sysTime.add!"months"(85);
assertPred!"=="(sysTime, SysTime(DateTime(4, 4, 3, 12, 11, 10), FracSec.from!"msecs"(9)));
}
{
auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), FracSec.from!"msecs"(9));
sysTime.add!"months"(85);
assertPred!"=="(sysTime, SysTime(DateTime(4, 5, 1, 12, 11, 10), FracSec.from!"msecs"(9)));
sysTime.add!"months"(-85);
assertPred!"=="(sysTime, SysTime(DateTime(-3, 4, 1, 12, 11, 10), FracSec.from!"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)));
//Verify Examples.
auto st1 = SysTime(DateTime(2010, 1, 1, 12, 30 ,33));
st1.add!"months"(1);
assert(st1 == SysTime(DateTime(2010, 2, 1, 12, 30 ,33)));
auto st2 = SysTime(DateTime(2010, 1, 1, 12, 30 ,33));
st2.add!"months"(-1);
assert(st2 == SysTime(DateTime(2009, 12, 1, 12, 30 ,33)));
auto st3 = SysTime(DateTime(1999, 1, 29, 12, 30 ,33));
st3.add!"months"(1);
assert(st3 == SysTime(DateTime(1999, 3, 1, 12, 30 ,33)));
auto st4 = SysTime(DateTime(1999, 1, 29, 12, 30 ,33));
st4.add!"months"(1, AllowDayOverflow.no);
assert(st4 == SysTime(DateTime(1999, 2, 28, 12, 30 ,33)));
}
//Test add!"months"() with AllowDayOverlow.no
unittest
{
//Test A.D.
{
auto sysTime = SysTime(Date(1999, 7, 6));
sysTime.add!"months"(3, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 10, 6)));
sysTime.add!"months"(-4, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 6, 6)));
}
{
auto sysTime = SysTime(Date(1999, 7, 6));
sysTime.add!"months"(6, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(2000, 1, 6)));
sysTime.add!"months"(-6, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 7, 6)));
}
{
auto sysTime = SysTime(Date(1999, 7, 6));
sysTime.add!"months"(27, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(2001, 10, 6)));
sysTime.add!"months"(-28, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 6, 6)));
}
{
auto sysTime = SysTime(Date(1999, 5, 31));
sysTime.add!"months"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 6, 30)));
}
{
auto sysTime = SysTime(Date(1999, 5, 31));
sysTime.add!"months"(-1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 4, 30)));
}
{
auto sysTime = SysTime(Date(1999, 2, 28));
sysTime.add!"months"(12, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(2000, 2, 28)));
}
{
auto sysTime = SysTime(Date(2000, 2, 29));
sysTime.add!"months"(12, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(2001, 2, 28)));
}
{
auto sysTime = SysTime(Date(1999, 7, 31));
sysTime.add!"months"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 8, 31)));
sysTime.add!"months"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 9, 30)));
}
{
auto sysTime = SysTime(Date(1998, 8, 31));
sysTime.add!"months"(13, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 9, 30)));
sysTime.add!"months"(-13, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1998, 8, 30)));
}
{
auto sysTime = SysTime(Date(1997, 12, 31));
sysTime.add!"months"(13, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 1, 31)));
sysTime.add!"months"(-13, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1997, 12, 31)));
}
{
auto sysTime = SysTime(Date(1997, 12, 31));
sysTime.add!"months"(14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 2, 28)));
sysTime.add!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1997, 12, 28)));
}
{
auto sysTime = SysTime(Date(1998, 12, 31));
sysTime.add!"months"(14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(2000, 2, 29)));
sysTime.add!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1998, 12, 29)));
}
{
auto sysTime = SysTime(Date(1999, 12, 31));
sysTime.add!"months"(14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(2001, 2, 28)));
sysTime.add!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 12, 28)));
}
{
auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), FracSec.from!"usecs"(5007));
sysTime.add!"months"(3, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1999, 10, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
sysTime.add!"months"(-4, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1999, 6, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
}
{
auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
sysTime.add!"months"(14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(2000, 2, 29, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
sysTime.add!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1998, 12, 29, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
}
{
auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
sysTime.add!"months"(14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(2001, 2, 28, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
sysTime.add!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1999, 12, 28, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
}
//Test B.C.
{
auto sysTime = SysTime(Date(-1999, 7, 6));
sysTime.add!"months"(3, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1999, 10, 6)));
sysTime.add!"months"(-4, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1999, 6, 6)));
}
{
auto sysTime = SysTime(Date(-1999, 7, 6));
sysTime.add!"months"(6, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1998, 1, 6)));
sysTime.add!"months"(-6, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 6)));
}
{
auto sysTime = SysTime(Date(-1999, 7, 6));
sysTime.add!"months"(-27, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-2001, 4, 6)));
sysTime.add!"months"(28, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1999, 8, 6)));
}
{
auto sysTime = SysTime(Date(-1999, 5, 31));
sysTime.add!"months"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1999, 6, 30)));
}
{
auto sysTime = SysTime(Date(-1999, 5, 31));
sysTime.add!"months"(-1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1999, 4, 30)));
}
{
auto sysTime = SysTime(Date(-1999, 2, 28));
sysTime.add!"months"(-12, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-2000, 2, 28)));
}
{
auto sysTime = SysTime(Date(-2000, 2, 29));
sysTime.add!"months"(-12, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-2001, 2, 28)));
}
{
auto sysTime = SysTime(Date(-1999, 7, 31));
sysTime.add!"months"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1999, 8, 31)));
sysTime.add!"months"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1999, 9, 30)));
}
{
auto sysTime = SysTime(Date(-1998, 8, 31));
sysTime.add!"months"(13, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1997, 9, 30)));
sysTime.add!"months"(-13, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1998, 8, 30)));
}
{
auto sysTime = SysTime(Date(-1997, 12, 31));
sysTime.add!"months"(13, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1995, 1, 31)));
sysTime.add!"months"(-13, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1997, 12, 31)));
}
{
auto sysTime = SysTime(Date(-1997, 12, 31));
sysTime.add!"months"(14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1995, 2, 28)));
sysTime.add!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1997, 12, 28)));
}
{
auto sysTime = SysTime(Date(-2002, 12, 31));
sysTime.add!"months"(14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-2000, 2, 29)));
sysTime.add!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-2002, 12, 29)));
}
{
auto sysTime = SysTime(Date(-2001, 12, 31));
sysTime.add!"months"(14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1999, 2, 28)));
sysTime.add!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-2001, 12, 28)));
}
{
auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), FracSec.from!"usecs"(5007));
sysTime.add!"months"(3, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(-1999, 10, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
sysTime.add!"months"(-4, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(-1999, 6, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
}
{
auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
sysTime.add!"months"(14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(-2000, 2, 29, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
sysTime.add!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(-2002, 12, 29, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
}
{
auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
sysTime.add!"months"(14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(-1999, 2, 28, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
sysTime.add!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(-2001, 12, 28, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
}
//Test Both
{
auto sysTime = SysTime(Date(1, 1, 1));
sysTime.add!"months"(-1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(0, 12, 1)));
sysTime.add!"months"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1, 1, 1)));
}
{
auto sysTime = SysTime(Date(4, 1, 1));
sysTime.add!"months"(-48, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(0, 1, 1)));
sysTime.add!"months"(48, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(4, 1, 1)));
}
{
auto sysTime = SysTime(Date(4, 3, 31));
sysTime.add!"months"(-49, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(0, 2, 29)));
sysTime.add!"months"(49, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(4, 3, 29)));
}
{
auto sysTime = SysTime(Date(4, 3, 31));
sysTime.add!"months"(-85, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-3, 2, 28)));
sysTime.add!"months"(85, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(4, 3, 28)));
}
{
auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
sysTime.add!"months"(-1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
sysTime.add!"months"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
}
{
auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
sysTime.add!"months"(-1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
sysTime.add!"months"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
}
{
auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
sysTime.add!"months"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
sysTime.add!"months"(-1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
}
{
auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
sysTime.add!"months"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
sysTime.add!"months"(-1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
}
{
auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), FracSec.from!"hnsecs"(17));
sysTime.add!"months"(-1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 0, 7, 9), FracSec.from!"hnsecs"(17)));
sysTime.add!"months"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 7, 9), FracSec.from!"hnsecs"(17)));
}
{
auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), FracSec.from!"msecs"(9));
sysTime.add!"months"(-85, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(-3, 2, 28, 12, 11, 10), FracSec.from!"msecs"(9)));
sysTime.add!"months"(85, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(4, 3, 28, 12, 11, 10), FracSec.from!"msecs"(9)));
}
{
auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), FracSec.from!"msecs"(9));
sysTime.add!"months"(85, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(4, 4, 30, 12, 11, 10), FracSec.from!"msecs"(9)));
sysTime.add!"months"(-85, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(-3, 3, 30, 12, 11, 10), FracSec.from!"msecs"(9)));
}
}
/++
Adds the given number of years to this SysTime. A negative number will
subtract.
For years, because they are the largest unit in SysTime, there is no
difference between adding or rolling.
Params:
years = The number of years to add to this SysTime.
allowOverflow = Whether the days should be allowed to overflow,
causing the month to increment.
+/
/+ref SysTime+/ void roll(string units)(long years, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) nothrow
if(units == "years")
{
add!"years"(years, allowOverflow);
}
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));
static assert(__traits(compiles, st.roll!"years"(4)));
static assert(!__traits(compiles, cst.roll!"years"(4)));
//static assert(!__traits(compiles, ist.roll!"years"(4)));
}
/++
Adds the given number of months to this SysTime. A negative number will
subtract.
The difference between rolling and adding is that rolling does not affect
larger units. So, if you roll the SysTime 12 months, you get the exact
same SysTime. However, the days can still be affected due to the differing
number of days in each month.
Params:
months = The number of months to add to this SysTime.
allowOverflow = Whether the days should be allowed to overflow,
causing the month to increment.
Examples:
--------------------
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)));
--------------------
+/
/+ref SysTime+/ void roll(string units)(long months, AllowDayOverflow allowOverflow = AllowDayOverflow.yes) 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"(months, allowOverflow);
days = date.dayOfGregorianCal - 1;
if(days < 0)
{
hnsecs -= convert!("hours", "hnsecs")(24);
++days;
}
immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
adjTime = newDaysHNSecs + hnsecs;
}
//Test roll!"months"() with AllowDayOverlow.yes
unittest
{
//Test A.D.
{
auto sysTime = SysTime(Date(1999, 7, 6));
sysTime.roll!"months"(3);
assertPred!"=="(sysTime, SysTime(Date(1999, 10, 6)));
sysTime.roll!"months"(-4);
assertPred!"=="(sysTime, SysTime(Date(1999, 6, 6)));
}
{
auto sysTime = SysTime(Date(1999, 7, 6));
sysTime.roll!"months"(6);
assertPred!"=="(sysTime, SysTime(Date(1999, 1, 6)));
sysTime.roll!"months"(-6);
assertPred!"=="(sysTime, SysTime(Date(1999, 7, 6)));
}
{
auto sysTime = SysTime(Date(1999, 7, 6));
sysTime.roll!"months"(27);
assertPred!"=="(sysTime, SysTime(Date(1999, 10, 6)));
sysTime.roll!"months"(-28);
assertPred!"=="(sysTime, SysTime(Date(1999, 6, 6)));
}
{
auto sysTime = SysTime(Date(1999, 5, 31));
sysTime.roll!"months"(1);
assertPred!"=="(sysTime, SysTime(Date(1999, 7, 1)));
}
{
auto sysTime = SysTime(Date(1999, 5, 31));
sysTime.roll!"months"(-1);
assertPred!"=="(sysTime, SysTime(Date(1999, 5, 1)));
}
{
auto sysTime = SysTime(Date(1999, 2, 28));
sysTime.roll!"months"(12);
assertPred!"=="(sysTime, SysTime(Date(1999, 2, 28)));
}
{
auto sysTime = SysTime(Date(2000, 2, 29));
sysTime.roll!"months"(12);
assertPred!"=="(sysTime, SysTime(Date(2000, 2, 29)));
}
{
auto sysTime = SysTime(Date(1999, 7, 31));
sysTime.roll!"months"(1);
assertPred!"=="(sysTime, SysTime(Date(1999, 8, 31)));
sysTime.roll!"months"(1);
assertPred!"=="(sysTime, SysTime(Date(1999, 10, 1)));
}
{
auto sysTime = SysTime(Date(1998, 8, 31));
sysTime.roll!"months"(13);
assertPred!"=="(sysTime, SysTime(Date(1998, 10, 1)));
sysTime.roll!"months"(-13);
assertPred!"=="(sysTime, SysTime(Date(1998, 9, 1)));
}
{
auto sysTime = SysTime(Date(1997, 12, 31));
sysTime.roll!"months"(13);
assertPred!"=="(sysTime, SysTime(Date(1997, 1, 31)));
sysTime.roll!"months"(-13);
assertPred!"=="(sysTime, SysTime(Date(1997, 12, 31)));
}
{
auto sysTime = SysTime(Date(1997, 12, 31));
sysTime.roll!"months"(14);
assertPred!"=="(sysTime, SysTime(Date(1997, 3, 3)));
sysTime.roll!"months"(-14);
assertPred!"=="(sysTime, SysTime(Date(1997, 1, 3)));
}
{
auto sysTime = SysTime(Date(1998, 12, 31));
sysTime.roll!"months"(14);
assertPred!"=="(sysTime, SysTime(Date(1998, 3, 3)));
sysTime.roll!"months"(-14);
assertPred!"=="(sysTime, SysTime(Date(1998, 1, 3)));
}
{
auto sysTime = SysTime(Date(1999, 12, 31));
sysTime.roll!"months"(14);
assertPred!"=="(sysTime, SysTime(Date(1999, 3, 3)));
sysTime.roll!"months"(-14);
assertPred!"=="(sysTime, SysTime(Date(1999, 1, 3)));
}
{
auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), FracSec.from!"usecs"(5007));
sysTime.roll!"months"(3);
assertPred!"=="(sysTime, SysTime(DateTime(1999, 10, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
sysTime.roll!"months"(-4);
assertPred!"=="(sysTime, SysTime(DateTime(1999, 6, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
}
{
auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
sysTime.roll!"months"(14);
assertPred!"=="(sysTime, SysTime(DateTime(1998, 3, 3, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
sysTime.roll!"months"(-14);
assertPred!"=="(sysTime, SysTime(DateTime(1998, 1, 3, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
}
{
auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
sysTime.roll!"months"(14);
assertPred!"=="(sysTime, SysTime(DateTime(1999, 3, 3, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
sysTime.roll!"months"(-14);
assertPred!"=="(sysTime, SysTime(DateTime(1999, 1, 3, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
}
//Test B.C.
{
auto sysTime = SysTime(Date(-1999, 7, 6));
sysTime.roll!"months"(3);
assertPred!"=="(sysTime, SysTime(Date(-1999, 10, 6)));
sysTime.roll!"months"(-4);
assertPred!"=="(sysTime, SysTime(Date(-1999, 6, 6)));
}
{
auto sysTime = SysTime(Date(-1999, 7, 6));
sysTime.roll!"months"(6);
assertPred!"=="(sysTime, SysTime(Date(-1999, 1, 6)));
sysTime.roll!"months"(-6);
assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 6)));
}
{
auto sysTime = SysTime(Date(-1999, 7, 6));
sysTime.roll!"months"(-27);
assertPred!"=="(sysTime, SysTime(Date(-1999, 4, 6)));
sysTime.roll!"months"(28);
assertPred!"=="(sysTime, SysTime(Date(-1999, 8, 6)));
}
{
auto sysTime = SysTime(Date(-1999, 5, 31));
sysTime.roll!"months"(1);
assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 1)));
}
{
auto sysTime = SysTime(Date(-1999, 5, 31));
sysTime.roll!"months"(-1);
assertPred!"=="(sysTime, SysTime(Date(-1999, 5, 1)));
}
{
auto sysTime = SysTime(Date(-1999, 2, 28));
sysTime.roll!"months"(-12);
assertPred!"=="(sysTime, SysTime(Date(-1999, 2, 28)));
}
{
auto sysTime = SysTime(Date(-2000, 2, 29));
sysTime.roll!"months"(-12);
assertPred!"=="(sysTime, SysTime(Date(-2000, 2, 29)));
}
{
auto sysTime = SysTime(Date(-1999, 7, 31));
sysTime.roll!"months"(1);
assertPred!"=="(sysTime, SysTime(Date(-1999, 8, 31)));
sysTime.roll!"months"(1);
assertPred!"=="(sysTime, SysTime(Date(-1999, 10, 1)));
}
{
auto sysTime = SysTime(Date(-1998, 8, 31));
sysTime.roll!"months"(13);
assertPred!"=="(sysTime, SysTime(Date(-1998, 10, 1)));
sysTime.roll!"months"(-13);
assertPred!"=="(sysTime, SysTime(Date(-1998, 9, 1)));
}
{
auto sysTime = SysTime(Date(-1997, 12, 31));
sysTime.roll!"months"(13);
assertPred!"=="(sysTime, SysTime(Date(-1997, 1, 31)));
sysTime.roll!"months"(-13);
assertPred!"=="(sysTime, SysTime(Date(-1997, 12, 31)));
}
{
auto sysTime = SysTime(Date(-1997, 12, 31));
sysTime.roll!"months"(14);
assertPred!"=="(sysTime, SysTime(Date(-1997, 3, 3)));
sysTime.roll!"months"(-14);
assertPred!"=="(sysTime, SysTime(Date(-1997, 1, 3)));
}
{
auto sysTime = SysTime(Date(-2002, 12, 31));
sysTime.roll!"months"(14);
assertPred!"=="(sysTime, SysTime(Date(-2002, 3, 3)));
sysTime.roll!"months"(-14);
assertPred!"=="(sysTime, SysTime(Date(-2002, 1, 3)));
}
{
auto sysTime = SysTime(Date(-2001, 12, 31));
sysTime.roll!"months"(14);
assertPred!"=="(sysTime, SysTime(Date(-2001, 3, 3)));
sysTime.roll!"months"(-14);
assertPred!"=="(sysTime, SysTime(Date(-2001, 1, 3)));
}
{
auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
sysTime.roll!"months"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
sysTime.roll!"months"(1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
}
{
auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
sysTime.roll!"months"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
sysTime.roll!"months"(1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
}
{
auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
sysTime.roll!"months"(1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
sysTime.roll!"months"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
}
{
auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
sysTime.roll!"months"(1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
sysTime.roll!"months"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
}
{
auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), FracSec.from!"hnsecs"(5007));
sysTime.roll!"months"(3);
assertPred!"=="(sysTime, SysTime(DateTime(-1999, 10, 6, 12, 2, 7), FracSec.from!"hnsecs"(5007)));
sysTime.roll!"months"(-4);
assertPred!"=="(sysTime, SysTime(DateTime(-1999, 6, 6, 12, 2, 7), FracSec.from!"hnsecs"(5007)));
}
{
auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
sysTime.roll!"months"(14);
assertPred!"=="(sysTime, SysTime(DateTime(-2002, 3, 3, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
sysTime.roll!"months"(-14);
assertPred!"=="(sysTime, SysTime(DateTime(-2002, 1, 3, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
}
{
auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
sysTime.roll!"months"(14);
assertPred!"=="(sysTime, SysTime(DateTime(-2001, 3, 3, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
sysTime.roll!"months"(-14);
assertPred!"=="(sysTime, SysTime(DateTime(-2001, 1, 3, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
}
//Test Both
{
auto sysTime = SysTime(Date(1, 1, 1));
sysTime.roll!"months"(-1);
assertPred!"=="(sysTime, SysTime(Date(1, 12, 1)));
sysTime.roll!"months"(1);
assertPred!"=="(sysTime, SysTime(Date(1, 1, 1)));
}
{
auto sysTime = SysTime(Date(4, 1, 1));
sysTime.roll!"months"(-48);
assertPred!"=="(sysTime, SysTime(Date(4, 1, 1)));
sysTime.roll!"months"(48);
assertPred!"=="(sysTime, SysTime(Date(4, 1, 1)));
}
{
auto sysTime = SysTime(Date(4, 3, 31));
sysTime.roll!"months"(-49);
assertPred!"=="(sysTime, SysTime(Date(4, 3, 2)));
sysTime.roll!"months"(49);
assertPred!"=="(sysTime, SysTime(Date(4, 4, 2)));
}
{
auto sysTime = SysTime(Date(4, 3, 31));
sysTime.roll!"months"(-85);
assertPred!"=="(sysTime, SysTime(Date(4, 3, 2)));
sysTime.roll!"months"(85);
assertPred!"=="(sysTime, SysTime(Date(4, 4, 2)));
}
{
auto sysTime = SysTime(Date(-1, 1, 1));
sysTime.roll!"months"(-1);
assertPred!"=="(sysTime, SysTime(Date(-1, 12, 1)));
sysTime.roll!"months"(1);
assertPred!"=="(sysTime, SysTime(Date(-1, 1, 1)));
}
{
auto sysTime = SysTime(Date(-4, 1, 1));
sysTime.roll!"months"(-48);
assertPred!"=="(sysTime, SysTime(Date(-4, 1, 1)));
sysTime.roll!"months"(48);
assertPred!"=="(sysTime, SysTime(Date(-4, 1, 1)));
}
{
auto sysTime = SysTime(Date(-4, 3, 31));
sysTime.roll!"months"(-49);
assertPred!"=="(sysTime, SysTime(Date(-4, 3, 2)));
sysTime.roll!"months"(49);
assertPred!"=="(sysTime, SysTime(Date(-4, 4, 2)));
}
{
auto sysTime = SysTime(Date(-4, 3, 31));
sysTime.roll!"months"(-85);
assertPred!"=="(sysTime, SysTime(Date(-4, 3, 2)));
sysTime.roll!"months"(85);
assertPred!"=="(sysTime, SysTime(Date(-4, 4, 2)));
}
{
auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), FracSec.from!"hnsecs"(17));
sysTime.roll!"months"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 12, 1, 0, 7, 9), FracSec.from!"hnsecs"(17)));
sysTime.roll!"months"(1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 7, 9), FracSec.from!"hnsecs"(17)));
}
{
auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), FracSec.from!"msecs"(9));
sysTime.roll!"months"(-85);
assertPred!"=="(sysTime, SysTime(DateTime(4, 3, 2, 12, 11, 10), FracSec.from!"msecs"(9)));
sysTime.roll!"months"(85);
assertPred!"=="(sysTime, SysTime(DateTime(4, 4, 2, 12, 11, 10), FracSec.from!"msecs"(9)));
}
{
auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), FracSec.from!"msecs"(9));
sysTime.roll!"months"(85);
assertPred!"=="(sysTime, SysTime(DateTime(-3, 5, 1, 12, 11, 10), FracSec.from!"msecs"(9)));
sysTime.roll!"months"(-85);
assertPred!"=="(sysTime, SysTime(DateTime(-3, 4, 1, 12, 11, 10), FracSec.from!"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)));
//Verify Examples.
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)));
}
//Test roll!"months"() with AllowDayOverlow.no
unittest
{
//Test A.D.
{
auto sysTime = SysTime(Date(1999, 7, 6));
sysTime.roll!"months"(3, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 10, 6)));
sysTime.roll!"months"(-4, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 6, 6)));
}
{
auto sysTime = SysTime(Date(1999, 7, 6));
sysTime.roll!"months"(6, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 1, 6)));
sysTime.roll!"months"(-6, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 7, 6)));
}
{
auto sysTime = SysTime(Date(1999, 7, 6));
sysTime.roll!"months"(27, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 10, 6)));
sysTime.roll!"months"(-28, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 6, 6)));
}
{
auto sysTime = SysTime(Date(1999, 5, 31));
sysTime.roll!"months"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 6, 30)));
}
{
auto sysTime = SysTime(Date(1999, 5, 31));
sysTime.roll!"months"(-1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 4, 30)));
}
{
auto sysTime = SysTime(Date(1999, 2, 28));
sysTime.roll!"months"(12, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 2, 28)));
}
{
auto sysTime = SysTime(Date(2000, 2, 29));
sysTime.roll!"months"(12, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(2000, 2, 29)));
}
{
auto sysTime = SysTime(Date(1999, 7, 31));
sysTime.roll!"months"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 8, 31)));
sysTime.roll!"months"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 9, 30)));
}
{
auto sysTime = SysTime(Date(1998, 8, 31));
sysTime.roll!"months"(13, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1998, 9, 30)));
sysTime.roll!"months"(-13, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1998, 8, 30)));
}
{
auto sysTime = SysTime(Date(1997, 12, 31));
sysTime.roll!"months"(13, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1997, 1, 31)));
sysTime.roll!"months"(-13, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1997, 12, 31)));
}
{
auto sysTime = SysTime(Date(1997, 12, 31));
sysTime.roll!"months"(14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1997, 2, 28)));
sysTime.roll!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1997, 12, 28)));
}
{
auto sysTime = SysTime(Date(1998, 12, 31));
sysTime.roll!"months"(14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1998, 2, 28)));
sysTime.roll!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1998, 12, 28)));
}
{
auto sysTime = SysTime(Date(1999, 12, 31));
sysTime.roll!"months"(14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 2, 28)));
sysTime.roll!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1999, 12, 28)));
}
{
auto sysTime = SysTime(DateTime(1999, 7, 6, 12, 2, 7), FracSec.from!"usecs"(5007));
sysTime.roll!"months"(3, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1999, 10, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
sysTime.roll!"months"(-4, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1999, 6, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
}
{
auto sysTime = SysTime(DateTime(1998, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
sysTime.roll!"months"(14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1998, 2, 28, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
sysTime.roll!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1998, 12, 28, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
}
{
auto sysTime = SysTime(DateTime(1999, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
sysTime.roll!"months"(14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1999, 2, 28, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
sysTime.roll!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1999, 12, 28, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
}
//Test B.C.
{
auto sysTime = SysTime(Date(-1999, 7, 6));
sysTime.roll!"months"(3, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1999, 10, 6)));
sysTime.roll!"months"(-4, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1999, 6, 6)));
}
{
auto sysTime = SysTime(Date(-1999, 7, 6));
sysTime.roll!"months"(6, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1999, 1, 6)));
sysTime.roll!"months"(-6, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 6)));
}
{
auto sysTime = SysTime(Date(-1999, 7, 6));
sysTime.roll!"months"(-27, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1999, 4, 6)));
sysTime.roll!"months"(28, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1999, 8, 6)));
}
{
auto sysTime = SysTime(Date(-1999, 5, 31));
sysTime.roll!"months"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1999, 6, 30)));
}
{
auto sysTime = SysTime(Date(-1999, 5, 31));
sysTime.roll!"months"(-1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1999, 4, 30)));
}
{
auto sysTime = SysTime(Date(-1999, 2, 28));
sysTime.roll!"months"(-12, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1999, 2, 28)));
}
{
auto sysTime = SysTime(Date(-2000, 2, 29));
sysTime.roll!"months"(-12, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-2000, 2, 29)));
}
{
auto sysTime = SysTime(Date(-1999, 7, 31));
sysTime.roll!"months"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1999, 8, 31)));
sysTime.roll!"months"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1999, 9, 30)));
}
{
auto sysTime = SysTime(Date(-1998, 8, 31));
sysTime.roll!"months"(13, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1998, 9, 30)));
sysTime.roll!"months"(-13, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1998, 8, 30)));
}
{
auto sysTime = SysTime(Date(-1997, 12, 31));
sysTime.roll!"months"(13, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1997, 1, 31)));
sysTime.roll!"months"(-13, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1997, 12, 31)));
}
{
auto sysTime = SysTime(Date(-1997, 12, 31));
sysTime.roll!"months"(14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1997, 2, 28)));
sysTime.roll!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1997, 12, 28)));
}
{
auto sysTime = SysTime(Date(-2002, 12, 31));
sysTime.roll!"months"(14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-2002, 2, 28)));
sysTime.roll!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-2002, 12, 28)));
}
{
auto sysTime = SysTime(Date(-2001, 12, 31));
sysTime.roll!"months"(14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-2001, 2, 28)));
sysTime.roll!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-2001, 12, 28)));
}
{
auto sysTime = SysTime(DateTime(-1999, 7, 6, 12, 2, 7), FracSec.from!"usecs"(5007));
sysTime.roll!"months"(3, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(-1999, 10, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
sysTime.roll!"months"(-4, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(-1999, 6, 6, 12, 2, 7), FracSec.from!"usecs"(5007)));
}
{
auto sysTime = SysTime(DateTime(-2002, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
sysTime.roll!"months"(14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(-2002, 2, 28, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
sysTime.roll!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(-2002, 12, 28, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
}
{
auto sysTime = SysTime(DateTime(-2001, 12, 31, 7, 7, 7), FracSec.from!"hnsecs"(422202));
sysTime.roll!"months"(14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(-2001, 2, 28, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
sysTime.roll!"months"(-14, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(-2001, 12, 28, 7, 7, 7), FracSec.from!"hnsecs"(422202)));
}
//Test Both
{
auto sysTime = SysTime(Date(1, 1, 1));
sysTime.roll!"months"(-1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1, 12, 1)));
sysTime.roll!"months"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(1, 1, 1)));
}
{
auto sysTime = SysTime(Date(4, 1, 1));
sysTime.roll!"months"(-48, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(4, 1, 1)));
sysTime.roll!"months"(48, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(4, 1, 1)));
}
{
auto sysTime = SysTime(Date(4, 3, 31));
sysTime.roll!"months"(-49, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(4, 2, 29)));
sysTime.roll!"months"(49, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(4, 3, 29)));
}
{
auto sysTime = SysTime(Date(4, 3, 31));
sysTime.roll!"months"(-85, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(4, 2, 29)));
sysTime.roll!"months"(85, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(4, 3, 29)));
}
{
auto sysTime = SysTime(Date(-1, 1, 1));
sysTime.roll!"months"(-1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1, 12, 1)));
sysTime.roll!"months"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-1, 1, 1)));
}
{
auto sysTime = SysTime(Date(-4, 1, 1));
sysTime.roll!"months"(-48, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-4, 1, 1)));
sysTime.roll!"months"(48, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-4, 1, 1)));
}
{
auto sysTime = SysTime(Date(-4, 3, 31));
sysTime.roll!"months"(-49, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-4, 2, 29)));
sysTime.roll!"months"(49, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-4, 3, 29)));
}
{
auto sysTime = SysTime(Date(-4, 3, 31));
sysTime.roll!"months"(-85, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-4, 2, 29)));
sysTime.roll!"months"(85, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(Date(-4, 3, 29)));
}
{
auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
sysTime.roll!"months"(-1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
sysTime.roll!"months"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
}
{
auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
sysTime.roll!"months"(-1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
sysTime.roll!"months"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
}
{
auto sysTime = SysTime(DateTime(0, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
sysTime.roll!"months"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
sysTime.roll!"months"(-1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
}
{
auto sysTime = SysTime(DateTime(0, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
sysTime.roll!"months"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(0, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
sysTime.roll!"months"(-1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
}
{
auto sysTime = SysTime(DateTime(1, 1, 1, 0, 7, 9), FracSec.from!"hnsecs"(17));
sysTime.roll!"months"(-1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1, 12, 1, 0, 7, 9), FracSec.from!"hnsecs"(17)));
sysTime.roll!"months"(1, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 7, 9), FracSec.from!"hnsecs"(17)));
}
{
auto sysTime = SysTime(DateTime(4, 3, 31, 12, 11, 10), FracSec.from!"msecs"(9));
sysTime.roll!"months"(-85, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(4, 2, 29, 12, 11, 10), FracSec.from!"msecs"(9)));
sysTime.roll!"months"(85, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(4, 3, 29, 12, 11, 10), FracSec.from!"msecs"(9)));
}
{
auto sysTime = SysTime(DateTime(-3, 3, 31, 12, 11, 10), FracSec.from!"msecs"(9));
sysTime.roll!"months"(85, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(-3, 4, 30, 12, 11, 10), FracSec.from!"msecs"(9)));
sysTime.roll!"months"(-85, AllowDayOverflow.no);
assertPred!"=="(sysTime, SysTime(DateTime(-3, 3, 30, 12, 11, 10), FracSec.from!"msecs"(9)));
}
}
/++
Adds the given number of days to this SysTime. A negative number will
subtract.
The difference between rolling and adding is that rolling does not affect
larger units. So, if you roll the SysTime one year's worth of days, then
you get the exact same SysTime.
Note that TimeOfDay has no $(D add!"days"()) function because you can add
days to a SysTime by adding a duration to it.
Params:
days = The number of days to add to this SysTime.
Examples:
--------------------
auto st = SysTime(DateTime(2010, 1, 1, 11, 23, 12));
st.roll!"days"(1);
assert(st == SysTime(DateTime(2010, 1, 2, 11, 23, 12)));
st.roll!"days"(365);
assert(st == SysTime(DateTime(2010, 1, 26, 11, 23, 12)));
st.roll!"days"(-32);
assert(st == SysTime(DateTime(2010, 1, 25, 11, 23, 12)));
--------------------
+/
/+ref SysTime+/ void roll(string units)(long days) nothrow
if(units == "days")
{
auto hnsecs = adjTime;
auto gdays = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
if(hnsecs < 0)
{
hnsecs += convert!("hours", "hnsecs")(24);
--gdays;
}
auto date = Date(cast(int)gdays);
date.roll!"days"(days);
gdays = date.dayOfGregorianCal - 1;
if(gdays < 0)
{
hnsecs -= convert!("hours", "hnsecs")(24);
++gdays;
}
immutable newDaysHNSecs = convert!("days", "hnsecs")(gdays);
adjTime = newDaysHNSecs + hnsecs;
}
unittest
{
//Test A.D.
{
auto sysTime = SysTime(Date(1999, 2, 28));
sysTime.roll!"days"(1);
assertPred!"=="(sysTime, SysTime(Date(1999, 2, 1)));
sysTime.roll!"days"(-1);
assertPred!"=="(sysTime, SysTime(Date(1999, 2, 28)));
}
{
auto sysTime = SysTime(Date(2000, 2, 28));
sysTime.roll!"days"(1);
assertPred!"=="(sysTime, SysTime(Date(2000, 2, 29)));
sysTime.roll!"days"(1);
assertPred!"=="(sysTime, SysTime(Date(2000, 2, 1)));
sysTime.roll!"days"(-1);
assertPred!"=="(sysTime, SysTime(Date(2000, 2, 29)));
}
{
auto sysTime = SysTime(Date(1999, 6, 30));
sysTime.roll!"days"(1);
assertPred!"=="(sysTime, SysTime(Date(1999, 6, 1)));
sysTime.roll!"days"(-1);
assertPred!"=="(sysTime, SysTime(Date(1999, 6, 30)));
}
{
auto sysTime = SysTime(Date(1999, 7, 31));
sysTime.roll!"days"(1);
assertPred!"=="(sysTime, SysTime(Date(1999, 7, 1)));
sysTime.roll!"days"(-1);
assertPred!"=="(sysTime, SysTime(Date(1999, 7, 31)));
}
{
auto sysTime = SysTime(Date(1999, 1, 1));
sysTime.roll!"days"(-1);
assertPred!"=="(sysTime, SysTime(Date(1999, 1, 31)));
sysTime.roll!"days"(1);
assertPred!"=="(sysTime, SysTime(Date(1999, 1, 1)));
}
{
auto sysTime = SysTime(Date(1999, 7, 6));
sysTime.roll!"days"(9);
assertPred!"=="(sysTime, SysTime(Date(1999, 7, 15)));
sysTime.roll!"days"(-11);
assertPred!"=="(sysTime, SysTime(Date(1999, 7, 4)));
sysTime.roll!"days"(30);
assertPred!"=="(sysTime, SysTime(Date(1999, 7, 3)));
sysTime.roll!"days"(-3);
assertPred!"=="(sysTime, SysTime(Date(1999, 7, 31)));
}
{
auto sysTime = SysTime(Date(1999, 7, 6));
sysTime.roll!"days"(365);
assertPred!"=="(sysTime, SysTime(Date(1999, 7, 30)));
sysTime.roll!"days"(-365);
assertPred!"=="(sysTime, SysTime(Date(1999, 7, 6)));
sysTime.roll!"days"(366);
assertPred!"=="(sysTime, SysTime(Date(1999, 7, 31)));
sysTime.roll!"days"(730);
assertPred!"=="(sysTime, SysTime(Date(1999, 7, 17)));
sysTime.roll!"days"(-1096);
assertPred!"=="(sysTime, SysTime(Date(1999, 7, 6)));
}
{
auto sysTime = SysTime(Date(1999, 2, 6));
sysTime.roll!"days"(365);
assertPred!"=="(sysTime, SysTime(Date(1999, 2, 7)));
sysTime.roll!"days"(-365);
assertPred!"=="(sysTime, SysTime(Date(1999, 2, 6)));
sysTime.roll!"days"(366);
assertPred!"=="(sysTime, SysTime(Date(1999, 2, 8)));
sysTime.roll!"days"(730);
assertPred!"=="(sysTime, SysTime(Date(1999, 2, 10)));
sysTime.roll!"days"(-1096);
assertPred!"=="(sysTime, SysTime(Date(1999, 2, 6)));
}
{
auto sysTime = SysTime(DateTime(1999, 2, 28, 7, 9, 2), FracSec.from!"usecs"(234578));
sysTime.roll!"days"(1);
assertPred!"=="(sysTime, SysTime(DateTime(1999, 2, 1, 7, 9, 2), FracSec.from!"usecs"(234578)));
sysTime.roll!"days"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(1999, 2, 28, 7, 9, 2), FracSec.from!"usecs"(234578)));
}
{
auto sysTime = SysTime(DateTime(1999, 7, 6, 7, 9, 2), FracSec.from!"usecs"(234578));
sysTime.roll!"days"(9);
assertPred!"=="(sysTime, SysTime(DateTime(1999, 7, 15, 7, 9, 2), FracSec.from!"usecs"(234578)));
sysTime.roll!"days"(-11);
assertPred!"=="(sysTime, SysTime(DateTime(1999, 7, 4, 7, 9, 2), FracSec.from!"usecs"(234578)));
sysTime.roll!"days"(30);
assertPred!"=="(sysTime, SysTime(DateTime(1999, 7, 3, 7, 9, 2), FracSec.from!"usecs"(234578)));
sysTime.roll!"days"(-3);
assertPred!"=="(sysTime, SysTime(DateTime(1999, 7, 31, 7, 9, 2), FracSec.from!"usecs"(234578)));
}
//Test B.C.
{
auto sysTime = SysTime(Date(-1999, 2, 28));
sysTime.roll!"days"(1);
assertPred!"=="(sysTime, SysTime(Date(-1999, 2, 1)));
sysTime.roll!"days"(-1);
assertPred!"=="(sysTime, SysTime(Date(-1999, 2, 28)));
}
{
auto sysTime = SysTime(Date(-2000, 2, 28));
sysTime.roll!"days"(1);
assertPred!"=="(sysTime, SysTime(Date(-2000, 2, 29)));
sysTime.roll!"days"(1);
assertPred!"=="(sysTime, SysTime(Date(-2000, 2, 1)));
sysTime.roll!"days"(-1);
assertPred!"=="(sysTime, SysTime(Date(-2000, 2, 29)));
}
{
auto sysTime = SysTime(Date(-1999, 6, 30));
sysTime.roll!"days"(1);
assertPred!"=="(sysTime, SysTime(Date(-1999, 6, 1)));
sysTime.roll!"days"(-1);
assertPred!"=="(sysTime, SysTime(Date(-1999, 6, 30)));
}
{
auto sysTime = SysTime(Date(-1999, 7, 31));
sysTime.roll!"days"(1);
assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 1)));
sysTime.roll!"days"(-1);
assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 31)));
}
{
auto sysTime = SysTime(Date(-1999, 1, 1));
sysTime.roll!"days"(-1);
assertPred!"=="(sysTime, SysTime(Date(-1999, 1, 31)));
sysTime.roll!"days"(1);
assertPred!"=="(sysTime, SysTime(Date(-1999, 1, 1)));
}
{
auto sysTime = SysTime(Date(-1999, 7, 6));
sysTime.roll!"days"(9);
assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 15)));
sysTime.roll!"days"(-11);
assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 4)));
sysTime.roll!"days"(30);
assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 3)));
sysTime.roll!"days"(-3);
assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 31)));
}
{
auto sysTime = SysTime(Date(-1999, 7, 6));
sysTime.roll!"days"(365);
assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 30)));
sysTime.roll!"days"(-365);
assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 6)));
sysTime.roll!"days"(366);
assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 31)));
sysTime.roll!"days"(730);
assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 17)));
sysTime.roll!"days"(-1096);
assertPred!"=="(sysTime, SysTime(Date(-1999, 7, 6)));
}
{
auto sysTime = SysTime(DateTime(-1999, 2, 28, 7, 9, 2), FracSec.from!"usecs"(234578));
sysTime.roll!"days"(1);
assertPred!"=="(sysTime, SysTime(DateTime(-1999, 2, 1, 7, 9, 2), FracSec.from!"usecs"(234578)));
sysTime.roll!"days"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(-1999, 2, 28, 7, 9, 2), FracSec.from!"usecs"(234578)));
}
{
auto sysTime = SysTime(DateTime(-1999, 7, 6, 7, 9, 2), FracSec.from!"usecs"(234578));
sysTime.roll!"days"(9);
assertPred!"=="(sysTime, SysTime(DateTime(-1999, 7, 15, 7, 9, 2), FracSec.from!"usecs"(234578)));
sysTime.roll!"days"(-11);
assertPred!"=="(sysTime, SysTime(DateTime(-1999, 7, 4, 7, 9, 2), FracSec.from!"usecs"(234578)));
sysTime.roll!"days"(30);
assertPred!"=="(sysTime, SysTime(DateTime(-1999, 7, 3, 7, 9, 2), FracSec.from!"usecs"(234578)));
sysTime.roll!"days"(-3);
}
//Test Both
{
auto sysTime = SysTime(Date(1, 7, 6));
sysTime.roll!"days"(-365);
assertPred!"=="(sysTime, SysTime(Date(1, 7, 13)));
sysTime.roll!"days"(365);
assertPred!"=="(sysTime, SysTime(Date(1, 7, 6)));
sysTime.roll!"days"(-731);
assertPred!"=="(sysTime, SysTime(Date(1, 7, 19)));
sysTime.roll!"days"(730);
assertPred!"=="(sysTime, SysTime(Date(1, 7, 5)));
}
{
auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
sysTime.roll!"days"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 31, 0, 0, 0), FracSec.from!"hnsecs"(0)));
sysTime.roll!"days"(1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
}
{
auto sysTime = SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
sysTime.roll!"days"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
sysTime.roll!"days"(1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
}
{
auto sysTime = SysTime(DateTime(0, 12, 31, 0, 0, 0), FracSec.from!"hnsecs"(0));
sysTime.roll!"days"(1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
sysTime.roll!"days"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 0, 0, 0), FracSec.from!"hnsecs"(0)));
}
{
auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
sysTime.roll!"days"(1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
sysTime.roll!"days"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
}
{
auto sysTime = SysTime(DateTime(1, 7, 6, 13, 13, 9), FracSec.from!"msecs"(22));
sysTime.roll!"days"(-365);
assertPred!"=="(sysTime, SysTime(DateTime(1, 7, 13, 13, 13, 9), FracSec.from!"msecs"(22)));
sysTime.roll!"days"(365);
assertPred!"=="(sysTime, SysTime(DateTime(1, 7, 6, 13, 13, 9), FracSec.from!"msecs"(22)));
sysTime.roll!"days"(-731);
assertPred!"=="(sysTime, SysTime(DateTime(1, 7, 19, 13, 13, 9), FracSec.from!"msecs"(22)));
sysTime.roll!"days"(730);
assertPred!"=="(sysTime, SysTime(DateTime(1, 7, 5, 13, 13, 9), FracSec.from!"msecs"(22)));
}
{
auto sysTime = SysTime(DateTime(0, 7, 6, 13, 13, 9), FracSec.from!"msecs"(22));
sysTime.roll!"days"(-365);
assertPred!"=="(sysTime, SysTime(DateTime(0, 7, 13, 13, 13, 9), FracSec.from!"msecs"(22)));
sysTime.roll!"days"(365);
assertPred!"=="(sysTime, SysTime(DateTime(0, 7, 6, 13, 13, 9), FracSec.from!"msecs"(22)));
sysTime.roll!"days"(-731);
assertPred!"=="(sysTime, SysTime(DateTime(0, 7, 19, 13, 13, 9), FracSec.from!"msecs"(22)));
sysTime.roll!"days"(730);
assertPred!"=="(sysTime, SysTime(DateTime(0, 7, 5, 13, 13, 9), FracSec.from!"msecs"(22)));
}
const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
//immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
static assert(!__traits(compiles, cst.roll!"days"(4)));
//static assert(!__traits(compiles, ist.roll!"days"(4)));
//Verify Examples.
auto st = SysTime(DateTime(2010, 1, 1, 11, 23, 12));
st.roll!"days"(1);
assert(st == SysTime(DateTime(2010, 1, 2, 11, 23, 12)));
st.roll!"days"(365);
assert(st == SysTime(DateTime(2010, 1, 26, 11, 23, 12)));
st.roll!"days"(-32);
assert(st == SysTime(DateTime(2010, 1, 25, 11, 23, 12)));
}
/++
Add hours to the time of day. Negative values will subtract.
The difference between rolling and adding is that rolling does not
affect larger units. So, if you roll the SysTime 24 hours, you get
the exact same SysTime.
Note that SysTime has no $(D add!"hours"()), $(D add!"minutes"()), or
$(D add!"seconds"()) function because you can add those units to
a SysTime by adding a duration to it.
Params:
hours = The number of hours to add to this SysTime.
Examples:
--------------------
auto st1 = SysTime(DateTime(2010, 7, 4, 12, 0, 0));
st1.roll!"hours"(1);
assert(st1 == SysTime(DateTime(2010, 7, 4, 13, 0, 0)));
auto st2 = SysTime(DateTime(2010, 2, 12, 12, 0, 0));
st2.roll!"hours"(-1);
assert(st2 == SysTime(DateTime(2010, 2, 12, 11, 0, 0)));
auto st3 = SysTime(DateTime(2009, 12, 31, 0, 0, 0));
st3.roll!"minutes"(1);
assert(st3 == SysTime(DateTime(2009, 12, 31, 0, 1, 0)));
auto st4 = SysTime(DateTime(2010, 1, 1, 0, 0, 0));
st4.roll!"minutes"(-1);
assert(st4 == SysTime(DateTime(2010, 1, 1, 0, 59, 0)));
auto st5 = SysTime(DateTime(2009, 12, 31, 0, 0, 0));
st5.roll!"seconds"(1);
assert(st5 == SysTime(DateTime(2009, 12, 31, 0, 0, 1)));
auto st6 = SysTime(DateTime(2010, 1, 1, 0, 0, 0));
st6.roll!"seconds"(-1);
assert(st6 == SysTime(DateTime(2010, 1, 1, 0, 0, 59)));
--------------------
+/
/+ref SysTime+/ void roll(string units)(long value) nothrow
if(units == "hours" ||
units == "minutes" ||
units == "seconds")
{
try
{
auto hnsecs = adjTime;
auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
if(hnsecs < 0)
{
hnsecs += convert!("hours", "hnsecs")(24);
--days;
}
immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
immutable second = splitUnitsFromHNSecs!"seconds"(hnsecs);
auto dateTime = DateTime(Date(cast(int)days), TimeOfDay(cast(int)hour, cast(int)minute, cast(int)second));
dateTime.roll!units(value);
--days;
hnsecs += convert!("hours", "hnsecs")(dateTime.hour);
hnsecs += convert!("minutes", "hnsecs")(dateTime.minute);
hnsecs += convert!("seconds", "hnsecs")(dateTime.second);
if(days < 0)
{
hnsecs -= convert!("hours", "hnsecs")(24);
++days;
}
immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
adjTime = newDaysHNSecs + hnsecs;
}
catch(Exception e)
assert(0, "Either DateTime's constructor or TimeOfDay's constructor threw.");
}
//Test roll!"hours"().
unittest
{
static void TestST(SysTime orig, int hours, in SysTime expected, size_t line = __LINE__)
{
orig.roll!"hours"(hours);
assertPred!"=="(orig, expected, "", __FILE__, line);
}
//Test A.D.
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 1, SysTime(DateTime(1999, 7, 6, 13, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 2, SysTime(DateTime(1999, 7, 6, 14, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 3, SysTime(DateTime(1999, 7, 6, 15, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 4, SysTime(DateTime(1999, 7, 6, 16, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 5, SysTime(DateTime(1999, 7, 6, 17, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 6, SysTime(DateTime(1999, 7, 6, 18, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 7, SysTime(DateTime(1999, 7, 6, 19, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 8, SysTime(DateTime(1999, 7, 6, 20, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 9, SysTime(DateTime(1999, 7, 6, 21, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 10, SysTime(DateTime(1999, 7, 6, 22, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 11, SysTime(DateTime(1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 12, SysTime(DateTime(1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 13, SysTime(DateTime(1999, 7, 6, 1, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 14, SysTime(DateTime(1999, 7, 6, 2, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 15, SysTime(DateTime(1999, 7, 6, 3, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 16, SysTime(DateTime(1999, 7, 6, 4, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 17, SysTime(DateTime(1999, 7, 6, 5, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 18, SysTime(DateTime(1999, 7, 6, 6, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 19, SysTime(DateTime(1999, 7, 6, 7, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 20, SysTime(DateTime(1999, 7, 6, 8, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 21, SysTime(DateTime(1999, 7, 6, 9, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 22, SysTime(DateTime(1999, 7, 6, 10, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 23, SysTime(DateTime(1999, 7, 6, 11, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 24, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 25, SysTime(DateTime(1999, 7, 6, 13, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 50, SysTime(DateTime(1999, 7, 6, 14, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 10_000, SysTime(DateTime(1999, 7, 6, 4, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -1, SysTime(DateTime(1999, 7, 6, 11, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -2, SysTime(DateTime(1999, 7, 6, 10, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -3, SysTime(DateTime(1999, 7, 6, 9, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -4, SysTime(DateTime(1999, 7, 6, 8, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -5, SysTime(DateTime(1999, 7, 6, 7, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -6, SysTime(DateTime(1999, 7, 6, 6, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -7, SysTime(DateTime(1999, 7, 6, 5, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -8, SysTime(DateTime(1999, 7, 6, 4, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -9, SysTime(DateTime(1999, 7, 6, 3, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -10, SysTime(DateTime(1999, 7, 6, 2, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -11, SysTime(DateTime(1999, 7, 6, 1, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -12, SysTime(DateTime(1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -13, SysTime(DateTime(1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -14, SysTime(DateTime(1999, 7, 6, 22, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -15, SysTime(DateTime(1999, 7, 6, 21, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -16, SysTime(DateTime(1999, 7, 6, 20, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -17, SysTime(DateTime(1999, 7, 6, 19, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -18, SysTime(DateTime(1999, 7, 6, 18, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -19, SysTime(DateTime(1999, 7, 6, 17, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -20, SysTime(DateTime(1999, 7, 6, 16, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -21, SysTime(DateTime(1999, 7, 6, 15, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -22, SysTime(DateTime(1999, 7, 6, 14, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -23, SysTime(DateTime(1999, 7, 6, 13, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -24, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -25, SysTime(DateTime(1999, 7, 6, 11, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -50, SysTime(DateTime(1999, 7, 6, 10, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -10_000, SysTime(DateTime(1999, 7, 6, 20, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)), 1, SysTime(DateTime(1999, 7, 6, 1, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)), 0, SysTime(DateTime(1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)), -1, SysTime(DateTime(1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)), 1, SysTime(DateTime(1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)), 0, SysTime(DateTime(1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)), -1, SysTime(DateTime(1999, 7, 6, 22, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 7, 31, 23, 30, 33), FracSec.from!"msecs"(45)), 1, SysTime(DateTime(1999, 7, 31, 0, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 8, 1, 0, 30, 33), FracSec.from!"msecs"(45)), -1, SysTime(DateTime(1999, 8, 1, 23, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 12, 31, 23, 30, 33), FracSec.from!"msecs"(45)), 1, SysTime(DateTime(1999, 12, 31, 0, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(2000, 1, 1, 0, 30, 33), FracSec.from!"msecs"(45)), -1, SysTime(DateTime(2000, 1, 1, 23, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 2, 28, 23, 30, 33), FracSec.from!"msecs"(45)), 25, SysTime(DateTime(1999, 2, 28, 0, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1999, 3, 2, 0, 30, 33), FracSec.from!"msecs"(45)), -25, SysTime(DateTime(1999, 3, 2, 23, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(2000, 2, 28, 23, 30, 33), FracSec.from!"msecs"(45)), 25, SysTime(DateTime(2000, 2, 28, 0, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(2000, 3, 1, 0, 30, 33), FracSec.from!"msecs"(45)), -25, SysTime(DateTime(2000, 3, 1, 23, 30, 33), FracSec.from!"msecs"(45)));
//Test B.C.
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 1, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 2, SysTime(DateTime(-1999, 7, 6, 14, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 3, SysTime(DateTime(-1999, 7, 6, 15, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 4, SysTime(DateTime(-1999, 7, 6, 16, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 5, SysTime(DateTime(-1999, 7, 6, 17, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 6, SysTime(DateTime(-1999, 7, 6, 18, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 7, SysTime(DateTime(-1999, 7, 6, 19, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 8, SysTime(DateTime(-1999, 7, 6, 20, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 9, SysTime(DateTime(-1999, 7, 6, 21, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 10, SysTime(DateTime(-1999, 7, 6, 22, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 11, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 12, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 13, SysTime(DateTime(-1999, 7, 6, 1, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 14, SysTime(DateTime(-1999, 7, 6, 2, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 15, SysTime(DateTime(-1999, 7, 6, 3, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 16, SysTime(DateTime(-1999, 7, 6, 4, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 17, SysTime(DateTime(-1999, 7, 6, 5, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 18, SysTime(DateTime(-1999, 7, 6, 6, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 19, SysTime(DateTime(-1999, 7, 6, 7, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 20, SysTime(DateTime(-1999, 7, 6, 8, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 21, SysTime(DateTime(-1999, 7, 6, 9, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 22, SysTime(DateTime(-1999, 7, 6, 10, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 23, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 24, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 25, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 50, SysTime(DateTime(-1999, 7, 6, 14, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), 10_000, SysTime(DateTime(-1999, 7, 6, 4, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -1, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -2, SysTime(DateTime(-1999, 7, 6, 10, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -3, SysTime(DateTime(-1999, 7, 6, 9, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -4, SysTime(DateTime(-1999, 7, 6, 8, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -5, SysTime(DateTime(-1999, 7, 6, 7, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -6, SysTime(DateTime(-1999, 7, 6, 6, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -7, SysTime(DateTime(-1999, 7, 6, 5, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -8, SysTime(DateTime(-1999, 7, 6, 4, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -9, SysTime(DateTime(-1999, 7, 6, 3, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -10, SysTime(DateTime(-1999, 7, 6, 2, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -11, SysTime(DateTime(-1999, 7, 6, 1, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -12, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -13, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -14, SysTime(DateTime(-1999, 7, 6, 22, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -15, SysTime(DateTime(-1999, 7, 6, 21, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -16, SysTime(DateTime(-1999, 7, 6, 20, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -17, SysTime(DateTime(-1999, 7, 6, 19, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -18, SysTime(DateTime(-1999, 7, 6, 18, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -19, SysTime(DateTime(-1999, 7, 6, 17, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -20, SysTime(DateTime(-1999, 7, 6, 16, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -21, SysTime(DateTime(-1999, 7, 6, 15, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -22, SysTime(DateTime(-1999, 7, 6, 14, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -23, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -24, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -25, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -50, SysTime(DateTime(-1999, 7, 6, 10, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(45)), -10_000, SysTime(DateTime(-1999, 7, 6, 20, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)), 1, SysTime(DateTime(-1999, 7, 6, 1, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)), 0, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)), -1, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)), 1, SysTime(DateTime(-1999, 7, 6, 0, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)), 0, SysTime(DateTime(-1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 6, 23, 30, 33), FracSec.from!"msecs"(45)), -1, SysTime(DateTime(-1999, 7, 6, 22, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 7, 31, 23, 30, 33), FracSec.from!"msecs"(45)), 1, SysTime(DateTime(-1999, 7, 31, 0, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-1999, 8, 1, 0, 30, 33), FracSec.from!"msecs"(45)), -1, SysTime(DateTime(-1999, 8, 1, 23, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-2001, 12, 31, 23, 30, 33), FracSec.from!"msecs"(45)), 1, SysTime(DateTime(-2001, 12, 31, 0, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-2000, 1, 1, 0, 30, 33), FracSec.from!"msecs"(45)), -1, SysTime(DateTime(-2000, 1, 1, 23, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-2001, 2, 28, 23, 30, 33), FracSec.from!"msecs"(45)), 25, SysTime(DateTime(-2001, 2, 28, 0, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-2001, 3, 2, 0, 30, 33), FracSec.from!"msecs"(45)), -25, SysTime(DateTime(-2001, 3, 2, 23, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-2000, 2, 28, 23, 30, 33), FracSec.from!"msecs"(45)), 25, SysTime(DateTime(-2000, 2, 28, 0, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(-2000, 3, 1, 0, 30, 33), FracSec.from!"msecs"(45)), -25, SysTime(DateTime(-2000, 3, 1, 23, 30, 33), FracSec.from!"msecs"(45)));
//Test Both
TestST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), FracSec.from!"msecs"(45)), 17_546, SysTime(DateTime(-1, 1, 1, 13, 30, 33), FracSec.from!"msecs"(45)));
TestST(SysTime(DateTime(1, 1, 1, 13, 30, 33), FracSec.from!"msecs"(45)), -17_546, SysTime(DateTime(1, 1, 1, 11, 30, 33), FracSec.from!"msecs"(45)));
{
auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
sysTime.roll!"hours"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 0, 0), FracSec.from!"hnsecs"(0)));
sysTime.roll!"hours"(1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
}
{
auto sysTime = SysTime(DateTime(1, 1, 1, 0, 59, 59), FracSec.from!"hnsecs"(9_999_999));
sysTime.roll!"hours"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
sysTime.roll!"hours"(1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
}
{
auto sysTime = SysTime(DateTime(0, 12, 31, 23, 0, 0), FracSec.from!"hnsecs"(0));
sysTime.roll!"hours"(1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 0, 0, 0), FracSec.from!"hnsecs"(0)));
sysTime.roll!"hours"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 23, 0, 0), FracSec.from!"hnsecs"(0)));
}
{
auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
sysTime.roll!"hours"(1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 0, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
sysTime.roll!"hours"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
}
const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
//immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
static assert(!__traits(compiles, cst.roll!"hours"(4)));
//static assert(!__traits(compiles, ist.roll!"hours"(4)));
//Verify Examples.
auto st1 = SysTime(DateTime(2010, 7, 4, 12, 0, 0));
st1.roll!"hours"(1);
assert(st1 == SysTime(DateTime(2010, 7, 4, 13, 0, 0)));
auto st2 = SysTime(DateTime(2010, 2, 12, 12, 0, 0));
st2.roll!"hours"(-1);
assert(st2 == SysTime(DateTime(2010, 2, 12, 11, 0, 0)));
auto st3 = SysTime(DateTime(2009, 12, 31, 0, 0, 0));
st3.roll!"minutes"(1);
assert(st3 == SysTime(DateTime(2009, 12, 31, 0, 1, 0)));
auto st4 = SysTime(DateTime(2010, 1, 1, 0, 0, 0));
st4.roll!"minutes"(-1);
assert(st4 == SysTime(DateTime(2010, 1, 1, 0, 59, 0)));
auto st5 = SysTime(DateTime(2009, 12, 31, 0, 0, 0));
st5.roll!"seconds"(1);
assert(st5 == SysTime(DateTime(2009, 12, 31, 0, 0, 1)));
auto st6 = SysTime(DateTime(2010, 1, 1, 0, 0, 0));
st6.roll!"seconds"(-1);
assert(st6 == SysTime(DateTime(2010, 1, 1, 0, 0, 59)));
}
//Test roll!"minutes"().
unittest
{
static void TestST(SysTime orig, int minutes, in SysTime expected, size_t line = __LINE__)
{
orig.roll!"minutes"(minutes);
assertPred!"=="(orig, expected, "", __FILE__, line);
}
//Test A.D.
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 1, SysTime(DateTime(1999, 7, 6, 12, 31, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 2, SysTime(DateTime(1999, 7, 6, 12, 32, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 3, SysTime(DateTime(1999, 7, 6, 12, 33, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 4, SysTime(DateTime(1999, 7, 6, 12, 34, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 5, SysTime(DateTime(1999, 7, 6, 12, 35, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 10, SysTime(DateTime(1999, 7, 6, 12, 40, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 15, SysTime(DateTime(1999, 7, 6, 12, 45, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 29, SysTime(DateTime(1999, 7, 6, 12, 59, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 30, SysTime(DateTime(1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 45, SysTime(DateTime(1999, 7, 6, 12, 15, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 75, SysTime(DateTime(1999, 7, 6, 12, 45, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 90, SysTime(DateTime(1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 100, SysTime(DateTime(1999, 7, 6, 12, 10, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 689, SysTime(DateTime(1999, 7, 6, 12, 59, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 690, SysTime(DateTime(1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 691, SysTime(DateTime(1999, 7, 6, 12, 1, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 960, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 1439, SysTime(DateTime(1999, 7, 6, 12, 29, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 1440, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 1441, SysTime(DateTime(1999, 7, 6, 12, 31, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 2880, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -1, SysTime(DateTime(1999, 7, 6, 12, 29, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -2, SysTime(DateTime(1999, 7, 6, 12, 28, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -3, SysTime(DateTime(1999, 7, 6, 12, 27, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -4, SysTime(DateTime(1999, 7, 6, 12, 26, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -5, SysTime(DateTime(1999, 7, 6, 12, 25, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -10, SysTime(DateTime(1999, 7, 6, 12, 20, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -15, SysTime(DateTime(1999, 7, 6, 12, 15, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -29, SysTime(DateTime(1999, 7, 6, 12, 1, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -30, SysTime(DateTime(1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -45, SysTime(DateTime(1999, 7, 6, 12, 45, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -75, SysTime(DateTime(1999, 7, 6, 12, 15, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -90, SysTime(DateTime(1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -100, SysTime(DateTime(1999, 7, 6, 12, 50, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -749, SysTime(DateTime(1999, 7, 6, 12, 1, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -750, SysTime(DateTime(1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -751, SysTime(DateTime(1999, 7, 6, 12, 59, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -960, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -1439, SysTime(DateTime(1999, 7, 6, 12, 31, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -1440, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -1441, SysTime(DateTime(1999, 7, 6, 12, 29, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -2880, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)), 1, SysTime(DateTime(1999, 7, 6, 12, 1, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)), 0, SysTime(DateTime(1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)), -1, SysTime(DateTime(1999, 7, 6, 12, 59, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 11, 59, 33), FracSec.from!"usecs"(7203)), 1, SysTime(DateTime(1999, 7, 6, 11, 0, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 11, 59, 33), FracSec.from!"usecs"(7203)), 0, SysTime(DateTime(1999, 7, 6, 11, 59, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 11, 59, 33), FracSec.from!"usecs"(7203)), -1, SysTime(DateTime(1999, 7, 6, 11, 58, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 0, 0, 33), FracSec.from!"usecs"(7203)), 1, SysTime(DateTime(1999, 7, 6, 0, 1, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 0, 0, 33), FracSec.from!"usecs"(7203)), 0, SysTime(DateTime(1999, 7, 6, 0, 0, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 6, 0, 0, 33), FracSec.from!"usecs"(7203)), -1, SysTime(DateTime(1999, 7, 6, 0, 59, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 5, 23, 59, 33), FracSec.from!"usecs"(7203)), 1, SysTime(DateTime(1999, 7, 5, 23, 0, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 5, 23, 59, 33), FracSec.from!"usecs"(7203)), 0, SysTime(DateTime(1999, 7, 5, 23, 59, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1999, 7, 5, 23, 59, 33), FracSec.from!"usecs"(7203)), -1, SysTime(DateTime(1999, 7, 5, 23, 58, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1998, 12, 31, 23, 59, 33), FracSec.from!"usecs"(7203)), 1, SysTime(DateTime(1998, 12, 31, 23, 0, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1998, 12, 31, 23, 59, 33), FracSec.from!"usecs"(7203)), 0, SysTime(DateTime(1998, 12, 31, 23, 59, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1998, 12, 31, 23, 59, 33), FracSec.from!"usecs"(7203)), -1, SysTime(DateTime(1998, 12, 31, 23, 58, 33), FracSec.from!"usecs"(7203)));
//Test B.C.
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 1, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 2, SysTime(DateTime(-1999, 7, 6, 12, 32, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 3, SysTime(DateTime(-1999, 7, 6, 12, 33, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 4, SysTime(DateTime(-1999, 7, 6, 12, 34, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 5, SysTime(DateTime(-1999, 7, 6, 12, 35, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 10, SysTime(DateTime(-1999, 7, 6, 12, 40, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 15, SysTime(DateTime(-1999, 7, 6, 12, 45, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 29, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 30, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 45, SysTime(DateTime(-1999, 7, 6, 12, 15, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 75, SysTime(DateTime(-1999, 7, 6, 12, 45, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 90, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 100, SysTime(DateTime(-1999, 7, 6, 12, 10, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 689, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 690, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 691, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 960, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 1439, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 1440, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 1441, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), 2880, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -1, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -2, SysTime(DateTime(-1999, 7, 6, 12, 28, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -3, SysTime(DateTime(-1999, 7, 6, 12, 27, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -4, SysTime(DateTime(-1999, 7, 6, 12, 26, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -5, SysTime(DateTime(-1999, 7, 6, 12, 25, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -10, SysTime(DateTime(-1999, 7, 6, 12, 20, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -15, SysTime(DateTime(-1999, 7, 6, 12, 15, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -29, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -30, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -45, SysTime(DateTime(-1999, 7, 6, 12, 45, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -75, SysTime(DateTime(-1999, 7, 6, 12, 15, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -90, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -100, SysTime(DateTime(-1999, 7, 6, 12, 50, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -749, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -750, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -751, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -960, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -1439, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -1440, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -1441, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)), -2880, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)), 1, SysTime(DateTime(-1999, 7, 6, 12, 1, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)), 0, SysTime(DateTime(-1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 0, 33), FracSec.from!"usecs"(7203)), -1, SysTime(DateTime(-1999, 7, 6, 12, 59, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 11, 59, 33), FracSec.from!"usecs"(7203)), 1, SysTime(DateTime(-1999, 7, 6, 11, 0, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 11, 59, 33), FracSec.from!"usecs"(7203)), 0, SysTime(DateTime(-1999, 7, 6, 11, 59, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 11, 59, 33), FracSec.from!"usecs"(7203)), -1, SysTime(DateTime(-1999, 7, 6, 11, 58, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 0, 0, 33), FracSec.from!"usecs"(7203)), 1, SysTime(DateTime(-1999, 7, 6, 0, 1, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 0, 0, 33), FracSec.from!"usecs"(7203)), 0, SysTime(DateTime(-1999, 7, 6, 0, 0, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 6, 0, 0, 33), FracSec.from!"usecs"(7203)), -1, SysTime(DateTime(-1999, 7, 6, 0, 59, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 5, 23, 59, 33), FracSec.from!"usecs"(7203)), 1, SysTime(DateTime(-1999, 7, 5, 23, 0, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 5, 23, 59, 33), FracSec.from!"usecs"(7203)), 0, SysTime(DateTime(-1999, 7, 5, 23, 59, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1999, 7, 5, 23, 59, 33), FracSec.from!"usecs"(7203)), -1, SysTime(DateTime(-1999, 7, 5, 23, 58, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-2000, 12, 31, 23, 59, 33), FracSec.from!"usecs"(7203)), 1, SysTime(DateTime(-2000, 12, 31, 23, 0, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-2000, 12, 31, 23, 59, 33), FracSec.from!"usecs"(7203)), 0, SysTime(DateTime(-2000, 12, 31, 23, 59, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-2000, 12, 31, 23, 59, 33), FracSec.from!"usecs"(7203)), -1, SysTime(DateTime(-2000, 12, 31, 23, 58, 33), FracSec.from!"usecs"(7203)));
//Test Both
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0)), -1, SysTime(DateTime(1, 1, 1, 0, 59, 0)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 0)), 1, SysTime(DateTime(0, 12, 31, 23, 0, 0)));
TestST(SysTime(DateTime(0, 1, 1, 0, 0, 0)), -1, SysTime(DateTime(0, 1, 1, 0, 59, 0)));
TestST(SysTime(DateTime(-1, 12, 31, 23, 59, 0)), 1, SysTime(DateTime(-1, 12, 31, 23, 0, 0)));
TestST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), FracSec.from!"usecs"(7203)), 1_052_760, SysTime(DateTime(-1, 1, 1, 11, 30, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1, 1, 1, 13, 30, 33), FracSec.from!"usecs"(7203)), -1_052_760, SysTime(DateTime(1, 1, 1, 13, 30, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), FracSec.from!"usecs"(7203)), 1_052_782, SysTime(DateTime(-1, 1, 1, 11, 52, 33), FracSec.from!"usecs"(7203)));
TestST(SysTime(DateTime(1, 1, 1, 13, 52, 33), FracSec.from!"usecs"(7203)), -1_052_782, SysTime(DateTime(1, 1, 1, 13, 30, 33), FracSec.from!"usecs"(7203)));
{
auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
sysTime.roll!"minutes"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 59, 0), FracSec.from!"hnsecs"(0)));
sysTime.roll!"minutes"(1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
}
{
auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 59), FracSec.from!"hnsecs"(9_999_999));
sysTime.roll!"minutes"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
sysTime.roll!"minutes"(1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 59), FracSec.from!"hnsecs"(9_999_999)));
}
{
auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 0), FracSec.from!"hnsecs"(0));
sysTime.roll!"minutes"(1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 23, 0, 0), FracSec.from!"hnsecs"(0)));
sysTime.roll!"minutes"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 23, 59, 0), FracSec.from!"hnsecs"(0)));
}
{
auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
sysTime.roll!"minutes"(1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 23, 0, 59), FracSec.from!"hnsecs"(9_999_999)));
sysTime.roll!"minutes"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
}
const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
//immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
static assert(!__traits(compiles, cst.roll!"minutes"(4)));
//static assert(!__traits(compiles, ist.roll!"minutes"(4)));
}
//Test roll!"seconds"().
unittest
{
static void TestST(SysTime orig, int seconds, in SysTime expected, size_t line = __LINE__)
{
orig.roll!"seconds"(seconds);
assertPred!"=="(orig, expected, "", __FILE__, line);
}
//Test A.D.
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(1999, 7, 6, 12, 30, 34), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 2, SysTime(DateTime(1999, 7, 6, 12, 30, 35), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 3, SysTime(DateTime(1999, 7, 6, 12, 30, 36), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 4, SysTime(DateTime(1999, 7, 6, 12, 30, 37), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 5, SysTime(DateTime(1999, 7, 6, 12, 30, 38), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 10, SysTime(DateTime(1999, 7, 6, 12, 30, 43), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 15, SysTime(DateTime(1999, 7, 6, 12, 30, 48), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 26, SysTime(DateTime(1999, 7, 6, 12, 30, 59), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 27, SysTime(DateTime(1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 30, SysTime(DateTime(1999, 7, 6, 12, 30, 3), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 59, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 61, SysTime(DateTime(1999, 7, 6, 12, 30, 34), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1766, SysTime(DateTime(1999, 7, 6, 12, 30, 59), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1767, SysTime(DateTime(1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1768, SysTime(DateTime(1999, 7, 6, 12, 30, 1), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 2007, SysTime(DateTime(1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 3599, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 3600, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 3601, SysTime(DateTime(1999, 7, 6, 12, 30, 34), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 7200, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -2, SysTime(DateTime(1999, 7, 6, 12, 30, 31), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -3, SysTime(DateTime(1999, 7, 6, 12, 30, 30), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -4, SysTime(DateTime(1999, 7, 6, 12, 30, 29), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -5, SysTime(DateTime(1999, 7, 6, 12, 30, 28), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -10, SysTime(DateTime(1999, 7, 6, 12, 30, 23), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -15, SysTime(DateTime(1999, 7, 6, 12, 30, 18), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -33, SysTime(DateTime(1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -34, SysTime(DateTime(1999, 7, 6, 12, 30, 59), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -35, SysTime(DateTime(1999, 7, 6, 12, 30, 58), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -59, SysTime(DateTime(1999, 7, 6, 12, 30, 34), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -60, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -61, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(1999, 7, 6, 12, 30, 1), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(1999, 7, 6, 12, 30, 59), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 0, 0), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(1999, 7, 6, 12, 0, 1), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 0, 0), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(1999, 7, 6, 12, 0, 0), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 0, 0), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(1999, 7, 6, 12, 0, 59), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 0, 0, 0), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(1999, 7, 6, 0, 0, 1), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 0, 0, 0), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(1999, 7, 6, 0, 0, 0), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 0, 0, 0), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(1999, 7, 6, 0, 0, 59), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 5, 23, 59, 59), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(1999, 7, 5, 23, 59, 0), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 5, 23, 59, 59), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(1999, 7, 5, 23, 59, 59), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 5, 23, 59, 59), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(1999, 7, 5, 23, 59, 58), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1998, 12, 31, 23, 59, 59), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(1998, 12, 31, 23, 59, 0), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1998, 12, 31, 23, 59, 59), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(1998, 12, 31, 23, 59, 59), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1998, 12, 31, 23, 59, 59), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(1998, 12, 31, 23, 59, 58), FracSec.from!"msecs"(274)));
//Test B.C.
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 35), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 3, SysTime(DateTime(-1999, 7, 6, 12, 30, 36), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 4, SysTime(DateTime(-1999, 7, 6, 12, 30, 37), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 5, SysTime(DateTime(-1999, 7, 6, 12, 30, 38), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 43), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 15, SysTime(DateTime(-1999, 7, 6, 12, 30, 48), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 26, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 27, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 30, SysTime(DateTime(-1999, 7, 6, 12, 30, 3), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 59, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 61, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1766, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1767, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1768, SysTime(DateTime(-1999, 7, 6, 12, 30, 1), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 2007, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 3599, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 3600, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 3601, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 7200, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 31), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -3, SysTime(DateTime(-1999, 7, 6, 12, 30, 30), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -4, SysTime(DateTime(-1999, 7, 6, 12, 30, 29), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -5, SysTime(DateTime(-1999, 7, 6, 12, 30, 28), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 23), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -15, SysTime(DateTime(-1999, 7, 6, 12, 30, 18), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -33, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -34, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -35, SysTime(DateTime(-1999, 7, 6, 12, 30, 58), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -59, SysTime(DateTime(-1999, 7, 6, 12, 30, 34), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -60, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -61, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 1), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 0), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 59), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 0, 0), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(-1999, 7, 6, 12, 0, 1), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 0, 0), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(-1999, 7, 6, 12, 0, 0), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 0, 0), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(-1999, 7, 6, 12, 0, 59), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 0, 0, 0), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(-1999, 7, 6, 0, 0, 1), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 0, 0, 0), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(-1999, 7, 6, 0, 0, 0), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 0, 0, 0), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(-1999, 7, 6, 0, 0, 59), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 5, 23, 59, 59), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(-1999, 7, 5, 23, 59, 0), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 5, 23, 59, 59), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(-1999, 7, 5, 23, 59, 59), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 5, 23, 59, 59), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(-1999, 7, 5, 23, 59, 58), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-2000, 12, 31, 23, 59, 59), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(-2000, 12, 31, 23, 59, 0), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-2000, 12, 31, 23, 59, 59), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(-2000, 12, 31, 23, 59, 59), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-2000, 12, 31, 23, 59, 59), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(-2000, 12, 31, 23, 59, 58), FracSec.from!"msecs"(274)));
//Test Both
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(1, 1, 1, 0, 0, 59), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(0, 12, 31, 23, 59, 0), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(0, 1, 1, 0, 0, 59), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1, 12, 31, 23, 59, 59), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(-1, 12, 31, 23, 59, 0), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), FracSec.from!"msecs"(274)), 63_165_600L, SysTime(DateTime(-1, 1, 1, 11, 30, 33), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1, 1, 1, 13, 30, 33), FracSec.from!"msecs"(274)), -63_165_600L, SysTime(DateTime(1, 1, 1, 13, 30, 33), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1, 1, 1, 11, 30, 33), FracSec.from!"msecs"(274)), 63_165_617L, SysTime(DateTime(-1, 1, 1, 11, 30, 50), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1, 1, 1, 13, 30, 50), FracSec.from!"msecs"(274)), -63_165_617L, SysTime(DateTime(1, 1, 1, 13, 30, 33), FracSec.from!"msecs"(274)));
{
auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0));
sysTime.roll!"seconds"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 59), FracSec.from!"hnsecs"(0)));
sysTime.roll!"seconds"(1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
}
{
auto sysTime = SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999));
sysTime.roll!"seconds"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 59), FracSec.from!"hnsecs"(9_999_999)));
sysTime.roll!"seconds"(1);
assertPred!"=="(sysTime, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)));
}
{
auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0));
sysTime.roll!"seconds"(1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 23, 59, 0), FracSec.from!"hnsecs"(0)));
sysTime.roll!"seconds"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0)));
}
{
auto sysTime = SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
sysTime.roll!"seconds"(1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 23, 59, 0), FracSec.from!"hnsecs"(9_999_999)));
sysTime.roll!"seconds"(-1);
assertPred!"=="(sysTime, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
}
const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
//immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
static assert(!__traits(compiles, cst.roll!"seconds"(4)));
//static assert(!__traits(compiles, ist.roll!"seconds"(4)));
}
/++
Add to the fractional seconds of the time of day. Negative values will
subtract.
The difference between rolling and adding is that rolling does not affect
larger units. So, if you roll the SysTime 1 second, you get the exact same
SysTime.
Note that SysTime has no $(D add!"msecs"()), $(D add!"usecs"()), or
$(D add!"hnsecs"()) function because you can add those units to
a SysTime by adding a duration to it.
Params:
units = The units to add to this SysTime.
value = The number of units to add to this SysTime.
+/
/+ref SysTime+/ void roll(string units)(long value) nothrow
if(units == "msecs" ||
units == "usecs" ||
units == "hnsecs")
{
auto hnsecs = adjTime;
immutable days = splitUnitsFromHNSecs!"days"(hnsecs);
immutable negative = hnsecs < 0;
if(negative)
hnsecs += convert!("hours", "hnsecs")(24);
immutable seconds = splitUnitsFromHNSecs!"seconds"(hnsecs);
hnsecs += convert!(units, "hnsecs")(value);
hnsecs %= convert!("seconds", "hnsecs")(1);
if(hnsecs < 0)
hnsecs += convert!("seconds", "hnsecs")(1);
hnsecs += convert!("seconds", "hnsecs")(seconds);
if(negative)
hnsecs -= convert!("hours", "hnsecs")(24);
immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
adjTime = newDaysHNSecs + hnsecs;
}
//Test roll!"msecs"().
unittest
{
static void TestST(SysTime orig, int milliseconds, in SysTime expected, size_t line = __LINE__)
{
orig.roll!"msecs"(milliseconds);
assertPred!"=="(orig, expected, "", __FILE__, line);
}
//Test A.D.
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(275)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(276)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(284)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(374)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(0)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(275)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(0)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(1)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(0)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(273)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(272)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(264)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(174)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(0)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(273)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(0)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(0)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(999)));
//Test B.C.
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(275)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(276)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(284)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(374)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(0)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(275)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(0)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(1)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(0)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(273)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(272)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(264)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(174)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(0)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(273)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(0)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(0)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(274)), -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(999)));
//Test Both
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(0)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(1)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(0)), 0, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(0)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(0)), -1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(999)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(0)), -2, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(998)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(0)), -1000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(0)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(0)), -2000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(0)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(0)), -2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"msecs"(445)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_989_999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(19_999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(5_549_999)));
const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
//immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
static assert(!__traits(compiles, cst.addMSecs(4)));
//static assert(!__traits(compiles, ist.addMSecs(4)));
}
//Test roll!"usecs"().
unittest
{
static void TestST(SysTime orig, long microseconds, in SysTime expected, size_t line = __LINE__)
{
orig.roll!"usecs"(microseconds);
assertPred!"=="(orig, expected, "", __FILE__, line);
}
//Test A.D.
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(275)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(276)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(284)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(374)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(1000)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(1274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(1275)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(2274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(26_999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(27_000)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(27_001)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(766_999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(767_000)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(273)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(272)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(264)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(174)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(0)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(999_999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(999_274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(999_273)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(998_274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(967_000)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(966_999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(167_000)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(166_999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
//Test B.C.
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(275)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(276)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(284)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(374)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(1000)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(1274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(1275)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(2274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(26_999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(27_000)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(27_001)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(766_999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(767_000)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), 3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(273)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(272)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(264)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(174)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(0)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(999_999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(999_274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(999_273)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(998_274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(967_000)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(966_999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(167_000)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(166_999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)), -3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(274)));
//Test Both
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(1)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)), 0, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)), -1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(999_999)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)), -2, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(999_998)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)), -1000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(999_000)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)), -2000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(998_000)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)), -2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(997_445)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)), -1_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)), -2_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(0)), -2_333_333, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"usecs"(666_667)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_989)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(19)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(19_999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(25_549)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2_333_333, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(3_333_329)));
const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
//immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
static assert(!__traits(compiles, cst.roll!"usecs"(4)));
//static assert(!__traits(compiles, ist.roll!"usecs"(4)));
}
//Test roll!"hnsecs"().
unittest
{
static void TestST(SysTime orig, long hnsecs, in SysTime expected, size_t line = __LINE__)
{
orig.roll!"hnsecs"(hnsecs);
assertPred!"=="(orig, expected, "", __FILE__, line);
}
//Test A.D.
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(275)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(276)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(284)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(374)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1000)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1275)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(26_999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(27_000)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(27_001)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_766_999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_767_000)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_000_274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 36_000_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(273)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(272)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(264)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(174)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(0)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_999_999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_999_274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_999_273)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_998_274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_967_000)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_966_999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(8_167_000)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(8_166_999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_000_274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -36_000_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
//Test B.C.
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(275)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(276)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(284)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(374)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1000)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1275)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(26_999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(27_000)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(27_001)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_766_999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_767_000)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_000_274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(273)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(272)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(264)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(174)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(0)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_999_999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_999_274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_999_273)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_998_274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_967_000)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_966_999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(8_167_000)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(8_166_999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(9_000_274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
//Test Both
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), 0, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_998)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -1000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_000)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_998_000)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_997_445)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -1_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_000_000)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(8_000_000)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2_333_333, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(7_666_667)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -10_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -20_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -20_888_888, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_111_112)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_998)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(2554)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(999_999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1_999_999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2_333_333, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(2_333_332)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 10_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 20_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 20_888_888, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(888_887)));
const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
//immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
static assert(!__traits(compiles, cst.roll!"hnsecs"(4)));
//static assert(!__traits(compiles, ist.roll!"hnsecs"(4)));
//Verify Examples.
auto st1 = SysTime(DateTime(2010, 7, 4, 7, 32, 12));
st1.roll!"hnsecs"(1);
assert(st1 == SysTime(DateTime(2010, 7, 4, 7, 32, 12), FracSec.from!"hnsecs"(1)));
auto st2 = SysTime(DateTime(2010, 7, 4, 7, 32, 12));
st2.roll!"hnsecs"(-1);
assert(st2 == SysTime(DateTime(2010, 7, 4, 7, 32, 12), FracSec.from!"hnsecs"(9_999_999)));
auto st3 = SysTime(DateTime(2009, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
st3.roll!"hnsecs"(1);
assert(st3 == SysTime(DateTime(2009, 12, 31, 23, 59, 59)));
auto st4 = SysTime(DateTime(2010, 1, 1, 0, 0, 0));
st4.roll!"hnsecs"(-1);
assert(st4 == SysTime(DateTime(2010, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)));
auto st5 = SysTime(DateTime(2009, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999));
st5.roll!"hnsecs"(1);
assert(st5 == SysTime(DateTime(2009, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0)));
}
/++
Gives the result of adding or subtracting a duration from this SysTime.
The legal types of arithmetic for SysTime using this operator are
$(TABLE
$(TR $(TD SysTime) $(TD +) $(TD duration) $(TD -->) $(TD SysTime))
$(TR $(TD SysTime) $(TD -) $(TD duration) $(TD -->) $(TD SysTime))
)
Params:
duration = The duration to add to or subtract from this SysTime.
+/
SysTime opBinary(string op, D)(in D duration) const pure nothrow
if((op == "+" || op == "-") &&
(is(Unqual!D == Duration) ||
is(Unqual!D == TickDuration)))
{
SysTime retval = SysTime(this._stdTime, this._timezone.get);
static if(is(Unqual!D == Duration))
immutable hnsecs = duration.total!"hnsecs";
else static if(is(Unqual!D == TickDuration))
immutable hnsecs = duration.hnsecs;
//Ideally, this would just be
//retval._stdTime += unaryFun!(op ~ "a")(hnsecs);
//But there isn't currently a pure version of unaryFun!().
static if(op == "+")
immutable signedHNSecs = hnsecs;
else static if(op == "-")
immutable signedHNSecs = -hnsecs;
else
static assert(0);
retval._stdTime += signedHNSecs;
return retval;
}
unittest
{
auto st = SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_678));
assertPred!"=="(st + dur!"weeks"(7), SysTime(DateTime(1999, 8, 24, 12, 30, 33), FracSec.from!"hnsecs"(2_345_678)));
assertPred!"=="(st + dur!"weeks"(-7), SysTime(DateTime(1999, 5, 18, 12, 30, 33), FracSec.from!"hnsecs"(2_345_678)));
assertPred!"=="(st + dur!"days"(7), SysTime(DateTime(1999, 7, 13, 12, 30, 33), FracSec.from!"hnsecs"(2_345_678)));
assertPred!"=="(st + dur!"days"(-7), SysTime(DateTime(1999, 6, 29, 12, 30, 33), FracSec.from!"hnsecs"(2_345_678)));
assertPred!"=="(st + dur!"hours"(7), SysTime(DateTime(1999, 7, 6, 19, 30, 33), FracSec.from!"hnsecs"(2_345_678)));
assertPred!"=="(st + dur!"hours"(-7), SysTime(DateTime(1999, 7, 6, 5, 30, 33), FracSec.from!"hnsecs"(2_345_678)));
assertPred!"=="(st + dur!"minutes"(7), SysTime(DateTime(1999, 7, 6, 12, 37, 33), FracSec.from!"hnsecs"(2_345_678)));
assertPred!"=="(st + dur!"minutes"(-7), SysTime(DateTime(1999, 7, 6, 12, 23, 33), FracSec.from!"hnsecs"(2_345_678)));
assertPred!"=="(st + dur!"seconds"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 40), FracSec.from!"hnsecs"(2_345_678)));
assertPred!"=="(st + dur!"seconds"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 26), FracSec.from!"hnsecs"(2_345_678)));
assertPred!"=="(st + dur!"msecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_415_678)));
assertPred!"=="(st + dur!"msecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_275_678)));
assertPred!"=="(st + dur!"usecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_748)));
assertPred!"=="(st + dur!"usecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_608)));
assertPred!"=="(st + dur!"hnsecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_685)));
assertPred!"=="(st + dur!"hnsecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_671)));
//This probably only runs in cases where gettimeofday() is used, but it's
//hard to do this test correctly with variable ticksPerSec.
if(TickDuration.ticksPerSec == 1_000_000)
{
assertPred!"=="(st + TickDuration.from!"usecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_748)));
assertPred!"=="(st + TickDuration.from!"usecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_608)));
}
assertPred!"=="(st - dur!"weeks"(-7), SysTime(DateTime(1999, 8, 24, 12, 30, 33), FracSec.from!"hnsecs"(2_345_678)));
assertPred!"=="(st - dur!"weeks"(7), SysTime(DateTime(1999, 5, 18, 12, 30, 33), FracSec.from!"hnsecs"(2_345_678)));
assertPred!"=="(st - dur!"days"(-7), SysTime(DateTime(1999, 7, 13, 12, 30, 33), FracSec.from!"hnsecs"(2_345_678)));
assertPred!"=="(st - dur!"days"(7), SysTime(DateTime(1999, 6, 29, 12, 30, 33), FracSec.from!"hnsecs"(2_345_678)));
assertPred!"=="(st - dur!"hours"(-7), SysTime(DateTime(1999, 7, 6, 19, 30, 33), FracSec.from!"hnsecs"(2_345_678)));
assertPred!"=="(st - dur!"hours"(7), SysTime(DateTime(1999, 7, 6, 5, 30, 33), FracSec.from!"hnsecs"(2_345_678)));
assertPred!"=="(st - dur!"minutes"(-7), SysTime(DateTime(1999, 7, 6, 12, 37, 33), FracSec.from!"hnsecs"(2_345_678)));
assertPred!"=="(st - dur!"minutes"(7), SysTime(DateTime(1999, 7, 6, 12, 23, 33), FracSec.from!"hnsecs"(2_345_678)));
assertPred!"=="(st - dur!"seconds"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 40), FracSec.from!"hnsecs"(2_345_678)));
assertPred!"=="(st - dur!"seconds"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 26), FracSec.from!"hnsecs"(2_345_678)));
assertPred!"=="(st - dur!"msecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_415_678)));
assertPred!"=="(st - dur!"msecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_275_678)));
assertPred!"=="(st - dur!"usecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_748)));
assertPred!"=="(st - dur!"usecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_608)));
assertPred!"=="(st - dur!"hnsecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_685)));
assertPred!"=="(st - dur!"hnsecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_671)));
//This probably only runs in cases where gettimeofday() is used, but it's
//hard to do this test correctly with variable ticksPerSec.
if(TickDuration.ticksPerSec == 1_000_000)
{
assertPred!"=="(st - TickDuration.from!"usecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_748)));
assertPred!"=="(st - TickDuration.from!"usecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2_345_608)));
}
static void TestST(in SysTime orig, long hnsecs, in SysTime expected, size_t line = __LINE__)
{
assertPred!"=="(orig + dur!"hnsecs"(hnsecs), expected, "", __FILE__, line);
}
//Test A.D.
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(275)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(276)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(284)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(374)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1000)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1275)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(26_999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(27_000)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(27_001)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_766_999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_767_000)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_000_274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 39), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 36, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 31, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 36_000_000_000L, SysTime(DateTime(1999, 7, 6, 13, 30, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(273)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(272)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(264)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(174)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(0)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_273)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_998_274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_967_000)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_966_999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(8_167_000)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(8_166_999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_000_274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 27), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 24, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 29, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -36_000_000_000L, SysTime(DateTime(1999, 7, 6, 11, 30, 33), FracSec.from!"hnsecs"(274)));
//Test B.C.
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(275)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(276)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(284)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(374)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1000)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1275)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(26_999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(27_000)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(27_001)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_766_999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_767_000)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_000_274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 39), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 36, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(273)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(272)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(264)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(174)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(0)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_273)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_998_274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_967_000)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_966_999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(8_167_000)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(8_166_999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_000_274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 27), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 24, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), FracSec.from!"hnsecs"(274)));
//Test Both
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), 0, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_998)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_000)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_998_000)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_997_445)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -1_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_000_000)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(8_000_000)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2_333_333, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(7_666_667)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -10_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -20_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 58), FracSec.from!"hnsecs"(0)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -20_888_888, SysTime(DateTime(0, 12, 31, 23, 59, 57), FracSec.from!"hnsecs"(9_111_112)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_998)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(2554)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(999_999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1_999_999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2_333_333, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(2_333_332)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 10_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 20_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 1), FracSec.from!"hnsecs"(9_999_999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 20_888_888, SysTime(DateTime(1, 1, 1, 0, 0, 2), FracSec.from!"hnsecs"(888_887)));
auto duration = dur!"seconds"(12);
const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
//immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
static assert(__traits(compiles, cst + duration));
//static assert(__traits(compiles, ist + duration));
static assert(__traits(compiles, cst - duration));
//static assert(__traits(compiles, ist - duration));
}
/++
Gives the result of adding or subtracting a duration from this SysTime,
as well as assigning the result to this SysTime.
The legal types of arithmetic for SysTime using this operator are
$(TABLE
$(TR $(TD SysTime) $(TD +) $(TD duration) $(TD -->) $(TD SysTime))
$(TR $(TD SysTime) $(TD -) $(TD duration) $(TD -->) $(TD SysTime))
)
Params:
duration = The duration to add to or subtract from this SysTime.
+/
/+ref+/ SysTime opOpAssign(string op, D)(in D duration) pure nothrow
if((op == "+" || op == "-") &&
(is(Unqual!D == Duration) ||
is(Unqual!D == TickDuration)))
{
static if(is(Unqual!D == Duration))
auto hnsecs = duration.total!"hnsecs";
else static if(is(Unqual!D == TickDuration))
auto hnsecs = duration.hnsecs;
//Ideally, this would just be
//_stdTime += unaryFun!(op ~ "a")(hnsecs);
//But there isn't currently a pure version of unaryFun!().
static if(op == "+")
immutable signedHNSecs = hnsecs;
else static if(op == "-")
immutable signedHNSecs = -hnsecs;
else
static assert(0);
_stdTime += signedHNSecs;
return this;
}
unittest
{
assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"weeks"(7), SysTime(DateTime(1999, 8, 24, 12, 30, 33)));
assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"weeks"(-7), SysTime(DateTime(1999, 5, 18, 12, 30, 33)));
assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"days"(7), SysTime(DateTime(1999, 7, 13, 12, 30, 33)));
assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"days"(-7), SysTime(DateTime(1999, 6, 29, 12, 30, 33)));
assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"hours"(7), SysTime(DateTime(1999, 7, 6, 19, 30, 33)));
assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"hours"(-7), SysTime(DateTime(1999, 7, 6, 5, 30, 33)));
assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"minutes"(7), SysTime(DateTime(1999, 7, 6, 12, 37, 33)));
assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"minutes"(-7), SysTime(DateTime(1999, 7, 6, 12, 23, 33)));
assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"seconds"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 40)));
assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"seconds"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 26)));
assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"msecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(7)));
assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"msecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"msecs"(993)));
assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"usecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7)));
assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"usecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"usecs"(999_993)));
assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"hnsecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(7)));
assertPred!"+="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"hnsecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_993)));
assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"weeks"(-7), SysTime(DateTime(1999, 8, 24, 12, 30, 33)));
assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"weeks"(7), SysTime(DateTime(1999, 5, 18, 12, 30, 33)));
assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"days"(-7), SysTime(DateTime(1999, 7, 13, 12, 30, 33)));
assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"days"(7), SysTime(DateTime(1999, 6, 29, 12, 30, 33)));
assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"hours"(-7), SysTime(DateTime(1999, 7, 6, 19, 30, 33)));
assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"hours"(7), SysTime(DateTime(1999, 7, 6, 5, 30, 33)));
assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"minutes"(-7), SysTime(DateTime(1999, 7, 6, 12, 37, 33)));
assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"minutes"(7), SysTime(DateTime(1999, 7, 6, 12, 23, 33)));
assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"seconds"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 40)));
assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"seconds"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 26)));
assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"msecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(7)));
assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"msecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"msecs"(993)));
assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"usecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(7)));
assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"usecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"usecs"(999_993)));
assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"hnsecs"(-7), SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(7)));
assertPred!"-="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)), dur!"hnsecs"(7), SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_993)));
static void TestST(SysTime orig, long hnsecs, in SysTime expected, size_t line = __LINE__)
{
orig += dur!"hnsecs"(hnsecs);
assertPred!"=="(orig, expected, "", __FILE__, line);
}
//Test A.D.
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 0, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(275)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(276)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(284)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(374)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1000)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1001, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1275)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 2000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(26_999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(27_000)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_727, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(27_001)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_766_725, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_766_999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_766_726, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_767_000)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_000_274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 39), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 36, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 31, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 36_000_000_000L, SysTime(DateTime(1999, 7, 6, 13, 30, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(273)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -2, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(272)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -10, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(264)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -100, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(174)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -274, SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(0)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1001, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_273)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -2000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_998_274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -33_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_967_000)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -33_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_966_999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_833_274, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(8_167_000)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_833_275, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(8_166_999)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_000_000, SysTime(DateTime(1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_000_274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -60_000_000L, SysTime(DateTime(1999, 7, 6, 12, 30, 27), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -3_600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 24, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -600_000_000L, SysTime(DateTime(1999, 7, 6, 12, 29, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -36_000_000_000L, SysTime(DateTime(1999, 7, 6, 11, 30, 33), FracSec.from!"hnsecs"(274)));
//Test B.C.
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 0, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(275)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(276)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(284)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(374)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1000)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1275)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(2274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(26_999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(27_000)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 26_727, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(27_001)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_766_725, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_766_999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_766_726, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_767_000)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_000_274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 39), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 36, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 31, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), 36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 13, 30, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(273)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -2, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(272)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -10, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(264)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -100, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(174)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -274, SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(0)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1001, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_999_273)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -2000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_998_274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -33_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_967_000)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -33_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_966_999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_833_274, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(8_167_000)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_833_275, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(8_166_999)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -1_000_000, SysTime(DateTime(-1999, 7, 6, 12, 30, 32), FracSec.from!"hnsecs"(9_000_274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -60_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 30, 27), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -3_600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 24, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -600_000_000L, SysTime(DateTime(-1999, 7, 6, 12, 29, 33), FracSec.from!"hnsecs"(274)));
TestST(SysTime(DateTime(-1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(274)), -36_000_000_000L, SysTime(DateTime(-1999, 7, 6, 11, 30, 33), FracSec.from!"hnsecs"(274)));
//Test Both
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), 0, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_998)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -1000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_000)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_998_000)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2555, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_997_445)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -1_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_000_000)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(8_000_000)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -2_333_333, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(7_666_667)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -10_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -20_000_000, SysTime(DateTime(0, 12, 31, 23, 59, 58), FracSec.from!"hnsecs"(0)));
TestST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), -20_888_888, SysTime(DateTime(0, 12, 31, 23, 59, 57), FracSec.from!"hnsecs"(9_111_112)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), -1, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_998)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2555, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(2554)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(999_999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1_999_999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 2_333_333, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(2_333_332)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 10_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 20_000_000, SysTime(DateTime(1, 1, 1, 0, 0, 1), FracSec.from!"hnsecs"(9_999_999)));
TestST(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 20_888_888, SysTime(DateTime(1, 1, 1, 0, 0, 2), FracSec.from!"hnsecs"(888_887)));
auto duration = dur!"seconds"(12);
const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
//immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
static assert(!__traits(compiles, cst += duration));
//static assert(!__traits(compiles, ist += duration));
static assert(!__traits(compiles, cst -= duration));
//static assert(!__traits(compiles, ist -= duration));
}
/++
Gives the difference between two SysTimes.
The legal types of arithmetic for SysTime using this operator are
$(TABLE
$(TR $(TD SysTime) $(TD -) $(TD SysTime) $(TD -->) $(TD duration))
)
+/
Duration opBinary(string op)(in SysTime rhs) const pure nothrow
if(op == "-")
{
return dur!"hnsecs"(_stdTime - rhs._stdTime);
}
unittest
{
assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1998, 7, 6, 12, 30, 33)),
dur!"seconds"(31_536_000));
assertPred!"=="(SysTime(DateTime(1998, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)),
dur!"seconds"(-31_536_000));
assertPred!"=="(SysTime(DateTime(1999, 8, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)),
dur!"seconds"(26_78_400));
assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 8, 6, 12, 30, 33)),
dur!"seconds"(-26_78_400));
assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 5, 12, 30, 33)),
dur!"seconds"(86_400));
assertPred!"=="(SysTime(DateTime(1999, 7, 5, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)),
dur!"seconds"(-86_400));
assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 11, 30, 33)),
dur!"seconds"(3600));
assertPred!"=="(SysTime(DateTime(1999, 7, 6, 11, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)),
dur!"seconds"(-3600));
assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 31, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)),
dur!"seconds"(60));
assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 31, 33)),
dur!"seconds"(-60));
assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 34)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)),
dur!"seconds"(1));
assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 34)),
dur!"seconds"(-1));
assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(532)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)),
dur!"msecs"(532));
assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"msecs"(532)),
dur!"msecs"(-532));
assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(333_347)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)),
dur!"usecs"(333_347));
assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"usecs"(333_347)),
dur!"usecs"(-333_347));
assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_234_567)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33)),
dur!"hnsecs"(1_234_567));
assertPred!"=="(SysTime(DateTime(1999, 7, 6, 12, 30, 33)) - SysTime(DateTime(1999, 7, 6, 12, 30, 33), FracSec.from!"hnsecs"(1_234_567)),
dur!"hnsecs"(-1_234_567));
assertPred!"=="(SysTime(DateTime(1, 1, 1, 12, 30, 33)) - SysTime(DateTime(1, 1, 1, 0, 0, 0)), dur!"seconds"(45033));
assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0)) - SysTime(DateTime(1, 1, 1, 12, 30, 33)), dur!"seconds"(-45033));
assertPred!"=="(SysTime(DateTime(0, 12, 31, 12, 30, 33)) - SysTime(DateTime(1, 1, 1, 0, 0, 0)), dur!"seconds"(-41367));
assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0)) - SysTime(DateTime(0, 12, 31, 12, 30, 33)), dur!"seconds"(41367));
assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0)) - SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), dur!"hnsecs"(1));
assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)) - SysTime(DateTime(1, 1, 1, 0, 0, 0)), dur!"hnsecs"(-1));
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));
static assert(__traits(compiles, st - st));
static assert(__traits(compiles, cst - st));
//static assert(__traits(compiles, ist - st));
static assert(__traits(compiles, st - cst));
static assert(__traits(compiles, cst - cst));
//static assert(__traits(compiles, ist - cst));
//static assert(__traits(compiles, st - ist));
//static assert(__traits(compiles, cst - ist));
//static assert(__traits(compiles, ist - ist));
}
/++
Returns the difference between the two SysTimes in months.
You can get the difference in years by subtracting the year property
of two SysTimes, and you can get the difference in days or weeks by
subtracting the SysTimes themselves and using the Duration that results,
but because you cannot convert between months and smaller units without
a specific date (which the Duration from the subtraction of two SysTimes
won't have), you cannot get the difference in months without doing some
math using both the year and month properties, so this is a convenience
function for getting the difference in months.
Note that the number of days in the months or how far into the month either
date is is irrelevant. It is the difference in the month property combined
with the difference in years * 12. So, for instance, December 31st and
January 1st are one month apart just as December 1st and January 31st are
one month apart.
Params:
rhs = The SysTime to subtract from this one.
Examples:
--------------------
assert(SysTime(Date(1999, 2, 1)).diffMonths(SysTime(Date(1999, 1, 31))) == 1);
assert(SysTime(Date(1999, 1, 31)).diffMonths(SysTime(Date(1999, 2, 1))) == -1);
assert(SysTime(Date(1999, 3, 1)).diffMonths(SysTime(Date(1999, 1, 1))) == 2);
assert(SysTime(Date(1999, 1, 1)).diffMonths(SysTime(Date(1999, 3, 31))) == -2);
--------------------
+/
int diffMonths(in SysTime rhs) const nothrow
{
return (cast(Date)this).diffMonths(cast(Date)rhs);
}
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));
static assert(__traits(compiles, st.diffMonths(st)));
static assert(__traits(compiles, cst.diffMonths(st)));
//static assert(__traits(compiles, ist.diffMonths(st)));
static assert(__traits(compiles, st.diffMonths(cst)));
static assert(__traits(compiles, cst.diffMonths(cst)));
//static assert(__traits(compiles, ist.diffMonths(cst)));
//static assert(__traits(compiles, st.diffMonths(ist)));
//static assert(__traits(compiles, cst.diffMonths(ist)));
//static assert(__traits(compiles, ist.diffMonths(ist)));
//Verify Examples.
assert(SysTime(Date(1999, 2, 1)).diffMonths(SysTime(Date(1999, 1, 31))) == 1);
assert(SysTime(Date(1999, 1, 31)).diffMonths(SysTime(Date(1999, 2, 1))) == -1);
assert(SysTime(Date(1999, 3, 1)).diffMonths(SysTime(Date(1999, 1, 1))) == 2);
assert(SysTime(Date(1999, 1, 1)).diffMonths(SysTime(Date(1999, 3, 31))) == -2);
}
/++
Whether this SysTime is in a leap year.
+/
@property bool isLeapYear() const nothrow
{
return (cast(Date)this).isLeapYear;
}
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));
static assert(__traits(compiles, st.isLeapYear));
static assert(__traits(compiles, cst.isLeapYear));
//static assert(__traits(compiles, ist.isLeapYear));
}
/++
Day of the week this SysTime is on.
+/
@property DayOfWeek dayOfWeek() const nothrow
{
return getDayOfWeek(dayOfGregorianCal);
}
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));
static assert(__traits(compiles, st.dayOfWeek));
static assert(__traits(compiles, cst.dayOfWeek));
//static assert(__traits(compiles, ist.dayOfWeek));
}
/++
Day of the year this SysTime is on.
Examples:
--------------------
assert(SysTime(DateTime(1999, 1, 1, 12, 22, 7)).dayOfYear == 1);
assert(SysTime(DateTime(1999, 12, 31, 7, 2, 59)).dayOfYear == 365);
assert(SysTime(DateTime(2000, 12, 31, 21, 20, 0)).dayOfYear == 366);
--------------------
+/
@property ushort dayOfYear() const nothrow
{
return (cast(Date)this).dayOfYear;
}
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));
static assert(__traits(compiles, st.dayOfYear));
static assert(__traits(compiles, cst.dayOfYear));
//static assert(__traits(compiles, ist.dayOfYear));
//Verify Examples.
assert(SysTime(DateTime(1999, 1, 1, 12, 22, 7)).dayOfYear == 1);
assert(SysTime(DateTime(1999, 12, 31, 7, 2, 59)).dayOfYear == 365);
assert(SysTime(DateTime(2000, 12, 31, 21, 20, 0)).dayOfYear == 366);
}
/++
Day of the year.
Params:
day = The day of the year to set which day of the year this SysTime is on.
+/
@property void dayOfYear(int day)
{
immutable hnsecs = adjTime;
immutable days = convert!("hnsecs", "days")(hnsecs);
immutable theRest = hnsecs - convert!("days", "hnsecs")(days);
auto date = Date(cast(int)days);
date.dayOfYear = day;
immutable newDaysHNSecs = convert!("days", "hnsecs")(date.dayOfGregorianCal - 1);
adjTime = newDaysHNSecs + theRest;
}
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));
static assert(__traits(compiles, st.dayOfYear = 12));
static assert(!__traits(compiles, cst.dayOfYear = 12));
//static assert(!__traits(compiles, ist.dayOfYear = 12));
}
/++
The Xth day of the Gregorian Calendar that this SysTime is on.
Examples:
--------------------
assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).dayOfGregorianCal == 1);
assert(SysTime(DateTime(1, 12, 31, 23, 59, 59)).dayOfGregorianCal == 365);
assert(SysTime(DateTime(2, 1, 1, 2, 2, 2)).dayOfGregorianCal == 366);
assert(SysTime(DateTime(0, 12, 31, 7, 7, 7)).dayOfGregorianCal == 0);
assert(SysTime(DateTime(0, 1, 1, 19, 30, 0)).dayOfGregorianCal == -365);
assert(SysTime(DateTime(-1, 12, 31, 4, 7, 0)).dayOfGregorianCal == -366);
assert(SysTime(DateTime(2000, 1, 1, 9, 30, 20)).dayOfGregorianCal == 730_120);
assert(SysTime(DateTime(2010, 12, 31, 15, 45, 50)).dayOfGregorianCal == 734_137);
--------------------
+/
@property int dayOfGregorianCal() const nothrow
{
immutable adjustedTime = adjTime;
//We have to add one because 0 would be midnight, January 1st, 1 A.D., which would be
//the 1st day of the Gregorian Calendar, not the 0th. So, simply casting to days
//is one day off.
if(adjustedTime > 0)
return cast(int)getUnitsFromHNSecs!"days"(adjustedTime) + 1;
auto hnsecs = adjustedTime;
immutable days = cast(int)splitUnitsFromHNSecs!"days"(hnsecs);
return hnsecs == 0 ? days + 1 : days;
}
unittest
{
//Test A.D.
assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal, 1);
assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)).dayOfGregorianCal, 1);
assertPred!"=="(SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal, 1);
assertPred!"=="(SysTime(DateTime(1, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 1);
assertPred!"=="(SysTime(DateTime(1, 1, 2, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 2);
assertPred!"=="(SysTime(DateTime(1, 2, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 32);
assertPred!"=="(SysTime(DateTime(2, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 366);
assertPred!"=="(SysTime(DateTime(3, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 731);
assertPred!"=="(SysTime(DateTime(4, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 1096);
assertPred!"=="(SysTime(DateTime(5, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 1462);
assertPred!"=="(SysTime(DateTime(50, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 17_898);
assertPred!"=="(SysTime(DateTime(97, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 35_065);
assertPred!"=="(SysTime(DateTime(100, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 36_160);
assertPred!"=="(SysTime(DateTime(101, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 36_525);
assertPred!"=="(SysTime(DateTime(105, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 37_986);
assertPred!"=="(SysTime(DateTime(200, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 72_684);
assertPred!"=="(SysTime(DateTime(201, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 73_049);
assertPred!"=="(SysTime(DateTime(300, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 109_208);
assertPred!"=="(SysTime(DateTime(301, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 109_573);
assertPred!"=="(SysTime(DateTime(400, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 145_732);
assertPred!"=="(SysTime(DateTime(401, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 146_098);
assertPred!"=="(SysTime(DateTime(500, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 182_257);
assertPred!"=="(SysTime(DateTime(501, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 182_622);
assertPred!"=="(SysTime(DateTime(1000, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 364_878);
assertPred!"=="(SysTime(DateTime(1001, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 365_243);
assertPred!"=="(SysTime(DateTime(1600, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 584_023);
assertPred!"=="(SysTime(DateTime(1601, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 584_389);
assertPred!"=="(SysTime(DateTime(1900, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 693_596);
assertPred!"=="(SysTime(DateTime(1901, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 693_961);
assertPred!"=="(SysTime(DateTime(1945, 11, 12, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 710_347);
assertPred!"=="(SysTime(DateTime(1999, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 729_755);
assertPred!"=="(SysTime(DateTime(2000, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 730_120);
assertPred!"=="(SysTime(DateTime(2001, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 730_486);
assertPred!"=="(SysTime(DateTime(2010, 1, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_773);
assertPred!"=="(SysTime(DateTime(2010, 1, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_803);
assertPred!"=="(SysTime(DateTime(2010, 2, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_804);
assertPred!"=="(SysTime(DateTime(2010, 2, 28, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_831);
assertPred!"=="(SysTime(DateTime(2010, 3, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_832);
assertPred!"=="(SysTime(DateTime(2010, 3, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_862);
assertPred!"=="(SysTime(DateTime(2010, 4, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_863);
assertPred!"=="(SysTime(DateTime(2010, 4, 30, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_892);
assertPred!"=="(SysTime(DateTime(2010, 5, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_893);
assertPred!"=="(SysTime(DateTime(2010, 5, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_923);
assertPred!"=="(SysTime(DateTime(2010, 6, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_924);
assertPred!"=="(SysTime(DateTime(2010, 6, 30, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_953);
assertPred!"=="(SysTime(DateTime(2010, 7, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_954);
assertPred!"=="(SysTime(DateTime(2010, 7, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_984);
assertPred!"=="(SysTime(DateTime(2010, 8, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 733_985);
assertPred!"=="(SysTime(DateTime(2010, 8, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 734_015);
assertPred!"=="(SysTime(DateTime(2010, 9, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 734_016);
assertPred!"=="(SysTime(DateTime(2010, 9, 30, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 734_045);
assertPred!"=="(SysTime(DateTime(2010, 10, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 734_046);
assertPred!"=="(SysTime(DateTime(2010, 10, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 734_076);
assertPred!"=="(SysTime(DateTime(2010, 11, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 734_077);
assertPred!"=="(SysTime(DateTime(2010, 11, 30, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 734_106);
assertPred!"=="(SysTime(DateTime(2010, 12, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 734_107);
assertPred!"=="(SysTime(DateTime(2010, 12, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, 734_137);
assertPred!"=="(SysTime(DateTime(2012, 2, 1, 0, 0, 0), FracSec.from!"msecs"(0)).dayOfGregorianCal, 734_534);
assertPred!"=="(SysTime(DateTime(2012, 2, 28, 0, 0, 0), FracSec.from!"msecs"(0)).dayOfGregorianCal, 734_561);
assertPred!"=="(SysTime(DateTime(2012, 2, 29, 0, 0, 0), FracSec.from!"msecs"(0)).dayOfGregorianCal, 734_562);
assertPred!"=="(SysTime(DateTime(2012, 3, 1, 0, 0, 0), FracSec.from!"msecs"(0)).dayOfGregorianCal, 734_563);
//Test B.C.
assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal, 0);
assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_998)).dayOfGregorianCal, 0);
assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0)).dayOfGregorianCal, 0);
assertPred!"=="(SysTime(DateTime(0, 12, 31, 0, 0, 0), FracSec.from!"hnsecs"(1)).dayOfGregorianCal, 0);
assertPred!"=="(SysTime(DateTime(0, 12, 31, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal, 0);
assertPred!"=="(SysTime(DateTime(-1, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal, -366);
assertPred!"=="(SysTime(DateTime(-1, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_998)).dayOfGregorianCal, -366);
assertPred!"=="(SysTime(DateTime(-1, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0)).dayOfGregorianCal, -366);
assertPred!"=="(SysTime(DateTime(-1, 12, 31, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal, -366);
assertPred!"=="(SysTime(DateTime(0, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, 0);
assertPred!"=="(SysTime(DateTime(0, 12, 30, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -1);
assertPred!"=="(SysTime(DateTime(0, 12, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -30);
assertPred!"=="(SysTime(DateTime(0, 11, 30, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -31);
assertPred!"=="(SysTime(DateTime(-1, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -366);
assertPred!"=="(SysTime(DateTime(-1, 12, 30, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -367);
assertPred!"=="(SysTime(DateTime(-1, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -730);
assertPred!"=="(SysTime(DateTime(-2, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -731);
assertPred!"=="(SysTime(DateTime(-2, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -1095);
assertPred!"=="(SysTime(DateTime(-3, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -1096);
assertPred!"=="(SysTime(DateTime(-3, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -1460);
assertPred!"=="(SysTime(DateTime(-4, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -1461);
assertPred!"=="(SysTime(DateTime(-4, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -1826);
assertPred!"=="(SysTime(DateTime(-5, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -1827);
assertPred!"=="(SysTime(DateTime(-5, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -2191);
assertPred!"=="(SysTime(DateTime(-9, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -3652);
assertPred!"=="(SysTime(DateTime(-49, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -18_262);
assertPred!"=="(SysTime(DateTime(-50, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -18_627);
assertPred!"=="(SysTime(DateTime(-97, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -35_794);
assertPred!"=="(SysTime(DateTime(-99, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -36_160);
assertPred!"=="(SysTime(DateTime(-99, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -36_524);
assertPred!"=="(SysTime(DateTime(-100, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -36_889);
assertPred!"=="(SysTime(DateTime(-101, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -37_254);
assertPred!"=="(SysTime(DateTime(-105, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -38_715);
assertPred!"=="(SysTime(DateTime(-200, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -73_413);
assertPred!"=="(SysTime(DateTime(-201, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -73_778);
assertPred!"=="(SysTime(DateTime(-300, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -109_937);
assertPred!"=="(SysTime(DateTime(-301, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -110_302);
assertPred!"=="(SysTime(DateTime(-400, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -146_097);
assertPred!"=="(SysTime(DateTime(-400, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -146_462);
assertPred!"=="(SysTime(DateTime(-401, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -146_827);
assertPred!"=="(SysTime(DateTime(-499, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -182_621);
assertPred!"=="(SysTime(DateTime(-500, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -182_986);
assertPred!"=="(SysTime(DateTime(-501, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -183_351);
assertPred!"=="(SysTime(DateTime(-1000, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -365_607);
assertPred!"=="(SysTime(DateTime(-1001, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -365_972);
assertPred!"=="(SysTime(DateTime(-1599, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -584_387);
assertPred!"=="(SysTime(DateTime(-1600, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -584_388);
assertPred!"=="(SysTime(DateTime(-1600, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -584_753);
assertPred!"=="(SysTime(DateTime(-1601, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -585_118);
assertPred!"=="(SysTime(DateTime(-1900, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -694_325);
assertPred!"=="(SysTime(DateTime(-1901, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -694_690);
assertPred!"=="(SysTime(DateTime(-1999, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -730_484);
assertPred!"=="(SysTime(DateTime(-2000, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -730_485);
assertPred!"=="(SysTime(DateTime(-2000, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -730_850);
assertPred!"=="(SysTime(DateTime(-2001, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)).dayOfGregorianCal, -731_215);
assertPred!"=="(SysTime(DateTime(-2010, 1, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_502);
assertPred!"=="(SysTime(DateTime(-2010, 1, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_472);
assertPred!"=="(SysTime(DateTime(-2010, 2, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_471);
assertPred!"=="(SysTime(DateTime(-2010, 2, 28, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_444);
assertPred!"=="(SysTime(DateTime(-2010, 3, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_443);
assertPred!"=="(SysTime(DateTime(-2010, 3, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_413);
assertPred!"=="(SysTime(DateTime(-2010, 4, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_412);
assertPred!"=="(SysTime(DateTime(-2010, 4, 30, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_383);
assertPred!"=="(SysTime(DateTime(-2010, 5, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_382);
assertPred!"=="(SysTime(DateTime(-2010, 5, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_352);
assertPred!"=="(SysTime(DateTime(-2010, 6, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_351);
assertPred!"=="(SysTime(DateTime(-2010, 6, 30, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_322);
assertPred!"=="(SysTime(DateTime(-2010, 7, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_321);
assertPred!"=="(SysTime(DateTime(-2010, 7, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_291);
assertPred!"=="(SysTime(DateTime(-2010, 8, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_290);
assertPred!"=="(SysTime(DateTime(-2010, 8, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_260);
assertPred!"=="(SysTime(DateTime(-2010, 9, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_259);
assertPred!"=="(SysTime(DateTime(-2010, 9, 30, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_230);
assertPred!"=="(SysTime(DateTime(-2010, 10, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_229);
assertPred!"=="(SysTime(DateTime(-2010, 10, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_199);
assertPred!"=="(SysTime(DateTime(-2010, 11, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_198);
assertPred!"=="(SysTime(DateTime(-2010, 11, 30, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_169);
assertPred!"=="(SysTime(DateTime(-2010, 12, 1, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_168);
assertPred!"=="(SysTime(DateTime(-2010, 12, 31, 23, 59, 59), FracSec.from!"msecs"(999)).dayOfGregorianCal, -734_138);
assertPred!"=="(SysTime(DateTime(-2012, 2, 1, 0, 0, 0), FracSec.from!"msecs"(0)).dayOfGregorianCal, -735_202);
assertPred!"=="(SysTime(DateTime(-2012, 2, 28, 0, 0, 0), FracSec.from!"msecs"(0)).dayOfGregorianCal, -735_175);
assertPred!"=="(SysTime(DateTime(-2012, 2, 29, 0, 0, 0), FracSec.from!"msecs"(0)).dayOfGregorianCal, -735_174);
assertPred!"=="(SysTime(DateTime(-2012, 3, 1, 0, 0, 0), FracSec.from!"msecs"(0)).dayOfGregorianCal, -735_173);
assertPred!"=="(SysTime(DateTime(-3760, 9, 7, 0, 0, 0), FracSec.from!"msecs"(0)).dayOfGregorianCal, -1_373_427); //Start of Hebrew Calendar
const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
//immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
static assert(__traits(compiles, cst.dayOfGregorianCal));
//static assert(__traits(compiles, ist.dayOfGregorianCal));
//Verify Examples.
assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).dayOfGregorianCal == 1);
assert(SysTime(DateTime(1, 12, 31, 23, 59, 59)).dayOfGregorianCal == 365);
assert(SysTime(DateTime(2, 1, 1, 2, 2, 2)).dayOfGregorianCal == 366);
assert(SysTime(DateTime(0, 12, 31, 7, 7, 7)).dayOfGregorianCal == 0);
assert(SysTime(DateTime(0, 1, 1, 19, 30, 0)).dayOfGregorianCal == -365);
assert(SysTime(DateTime(-1, 12, 31, 4, 7, 0)).dayOfGregorianCal == -366);
assert(SysTime(DateTime(2000, 1, 1, 9, 30, 20)).dayOfGregorianCal == 730_120);
assert(SysTime(DateTime(2010, 12, 31, 15, 45, 50)).dayOfGregorianCal == 734_137);
}
//Test that the logic for the day of the Gregorian Calendar is consistent
//between Date and SysTime.
unittest
{
//Test A.D.
assertPred!"=="(Date(1, 1, 1).dayOfGregorianCal, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(1, 1, 2).dayOfGregorianCal, SysTime(DateTime(1, 1, 2, 0, 0, 0), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(1, 2, 1).dayOfGregorianCal, SysTime(DateTime(1, 2, 1, 0, 0, 0), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(2, 1, 1).dayOfGregorianCal, SysTime(DateTime(2, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(3, 1, 1).dayOfGregorianCal, SysTime(DateTime(3, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(4, 1, 1).dayOfGregorianCal, SysTime(DateTime(4, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(5, 1, 1).dayOfGregorianCal, SysTime(DateTime(5, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(50, 1, 1).dayOfGregorianCal, SysTime(DateTime(50, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(97, 1, 1).dayOfGregorianCal, SysTime(DateTime(97, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(100, 1, 1).dayOfGregorianCal, SysTime(DateTime(100, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(101, 1, 1).dayOfGregorianCal, SysTime(DateTime(101, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(105, 1, 1).dayOfGregorianCal, SysTime(DateTime(105, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(200, 1, 1).dayOfGregorianCal, SysTime(DateTime(200, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(201, 1, 1).dayOfGregorianCal, SysTime(DateTime(201, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(300, 1, 1).dayOfGregorianCal, SysTime(DateTime(300, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(301, 1, 1).dayOfGregorianCal, SysTime(DateTime(301, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(400, 1, 1).dayOfGregorianCal, SysTime(DateTime(400, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(401, 1, 1).dayOfGregorianCal, SysTime(DateTime(401, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(500, 1, 1).dayOfGregorianCal, SysTime(DateTime(500, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(501, 1, 1).dayOfGregorianCal, SysTime(DateTime(501, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(1000, 1, 1).dayOfGregorianCal, SysTime(DateTime(1000, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(1001, 1, 1).dayOfGregorianCal, SysTime(DateTime(1001, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(1600, 1, 1).dayOfGregorianCal, SysTime(DateTime(1600, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(1601, 1, 1).dayOfGregorianCal, SysTime(DateTime(1601, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(1900, 1, 1).dayOfGregorianCal, SysTime(DateTime(1900, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(1901, 1, 1).dayOfGregorianCal, SysTime(DateTime(1901, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(1945, 11, 12).dayOfGregorianCal, SysTime(DateTime(1945, 11, 12, 0, 0, 0), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(1999, 1, 1).dayOfGregorianCal, SysTime(DateTime(1999, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(1999, 7, 6).dayOfGregorianCal, SysTime(DateTime(1999, 7, 6, 12, 13, 14), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(2000, 1, 1).dayOfGregorianCal, SysTime(DateTime(2000, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(2001, 1, 1).dayOfGregorianCal, SysTime(DateTime(2001, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(2010, 1, 1).dayOfGregorianCal, SysTime(DateTime(2010, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(2010, 1, 31).dayOfGregorianCal, SysTime(DateTime(2010, 1, 31, 23, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(2010, 2, 1).dayOfGregorianCal, SysTime(DateTime(2010, 2, 1, 23, 59, 59), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(2010, 2, 28).dayOfGregorianCal, SysTime(DateTime(2010, 2, 28, 23, 59, 59), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(2010, 3, 1).dayOfGregorianCal, SysTime(DateTime(2010, 3, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(2010, 3, 31).dayOfGregorianCal, SysTime(DateTime(2010, 3, 31, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(2010, 4, 1).dayOfGregorianCal, SysTime(DateTime(2010, 4, 1, 0, 0, 0), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(2010, 4, 30).dayOfGregorianCal, SysTime(DateTime(2010, 4, 30, 0, 0, 0), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(2010, 5, 1).dayOfGregorianCal, SysTime(DateTime(2010, 5, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(2010, 5, 31).dayOfGregorianCal, SysTime(DateTime(2010, 5, 31, 12, 13, 14), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(2010, 6, 1).dayOfGregorianCal, SysTime(DateTime(2010, 6, 1, 12, 13, 14), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(2010, 6, 30).dayOfGregorianCal, SysTime(DateTime(2010, 6, 30, 12, 13, 14), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(2010, 7, 1).dayOfGregorianCal, SysTime(DateTime(2010, 7, 1, 12, 13, 14), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(2010, 7, 31).dayOfGregorianCal, SysTime(DateTime(2010, 7, 31, 23, 59, 59), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(2010, 8, 1).dayOfGregorianCal, SysTime(DateTime(2010, 8, 1, 23, 59, 59), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(2010, 8, 31).dayOfGregorianCal, SysTime(DateTime(2010, 8, 31, 23, 59, 59), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(2010, 9, 1).dayOfGregorianCal, SysTime(DateTime(2010, 9, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(2010, 9, 30).dayOfGregorianCal, SysTime(DateTime(2010, 9, 30, 12, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(2010, 10, 1).dayOfGregorianCal, SysTime(DateTime(2010, 10, 1, 0, 12, 0), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(2010, 10, 31).dayOfGregorianCal, SysTime(DateTime(2010, 10, 31, 0, 0, 12), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(2010, 11, 1).dayOfGregorianCal, SysTime(DateTime(2010, 11, 1, 23, 0, 0), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(2010, 11, 30).dayOfGregorianCal, SysTime(DateTime(2010, 11, 30, 0, 59, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(2010, 12, 1).dayOfGregorianCal, SysTime(DateTime(2010, 12, 1, 0, 0, 59), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(2010, 12, 31).dayOfGregorianCal, SysTime(DateTime(2010, 12, 31, 0, 59, 59), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(2012, 2, 1).dayOfGregorianCal, SysTime(DateTime(2012, 2, 1, 23, 0, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(2012, 2, 28).dayOfGregorianCal, SysTime(DateTime(2012, 2, 28, 23, 59, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(2012, 2, 29).dayOfGregorianCal, SysTime(DateTime(2012, 2, 29, 7, 7, 7), FracSec.from!"hnsecs"(7)).dayOfGregorianCal);
assertPred!"=="(Date(2012, 3, 1).dayOfGregorianCal, SysTime(DateTime(2012, 3, 1, 7, 7, 7), FracSec.from!"hnsecs"(7)).dayOfGregorianCal);
//Test B.C.
assertPred!"=="(Date(0, 12, 31).dayOfGregorianCal, SysTime(DateTime(0, 12, 31, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(0, 12, 30).dayOfGregorianCal, SysTime(DateTime(0, 12, 30, 0, 0, 0), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(0, 12, 1).dayOfGregorianCal, SysTime(DateTime(0, 12, 1, 0, 0, 0), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(0, 11, 30).dayOfGregorianCal, SysTime(DateTime(0, 11, 30, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(-1, 12, 31).dayOfGregorianCal, SysTime(DateTime(-1, 12, 31, 12, 13, 14), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(-1, 12, 30).dayOfGregorianCal, SysTime(DateTime(-1, 12, 30, 12, 13, 14), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(-1, 1, 1).dayOfGregorianCal, SysTime(DateTime(-1, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(-2, 12, 31).dayOfGregorianCal, SysTime(DateTime(-2, 12, 31, 12, 13, 14), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(-2, 1, 1).dayOfGregorianCal, SysTime(DateTime(-2, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(-3, 12, 31).dayOfGregorianCal, SysTime(DateTime(-3, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(-3, 1, 1).dayOfGregorianCal, SysTime(DateTime(-3, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(-4, 12, 31).dayOfGregorianCal, SysTime(DateTime(-4, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(-4, 1, 1).dayOfGregorianCal, SysTime(DateTime(-4, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(-5, 12, 31).dayOfGregorianCal, SysTime(DateTime(-5, 12, 31, 0, 0, 0), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(-5, 1, 1).dayOfGregorianCal, SysTime(DateTime(-5, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(-9, 1, 1).dayOfGregorianCal, SysTime(DateTime(-9, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(-49, 1, 1).dayOfGregorianCal, SysTime(DateTime(-49, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(-50, 1, 1).dayOfGregorianCal, SysTime(DateTime(-50, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(-97, 1, 1).dayOfGregorianCal, SysTime(DateTime(-97, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(-99, 12, 31).dayOfGregorianCal, SysTime(DateTime(-99, 12, 31, 12, 13, 14), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(-99, 1, 1).dayOfGregorianCal, SysTime(DateTime(-99, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(-100, 1, 1).dayOfGregorianCal, SysTime(DateTime(-100, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(-101, 1, 1).dayOfGregorianCal, SysTime(DateTime(-101, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(-105, 1, 1).dayOfGregorianCal, SysTime(DateTime(-105, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(-200, 1, 1).dayOfGregorianCal, SysTime(DateTime(-200, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(-201, 1, 1).dayOfGregorianCal, SysTime(DateTime(-201, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(-300, 1, 1).dayOfGregorianCal, SysTime(DateTime(-300, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(-301, 1, 1).dayOfGregorianCal, SysTime(DateTime(-301, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(-400, 12, 31).dayOfGregorianCal, SysTime(DateTime(-400, 12, 31, 12, 13, 14), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(-400, 1, 1).dayOfGregorianCal, SysTime(DateTime(-400, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(-401, 1, 1).dayOfGregorianCal, SysTime(DateTime(-401, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(-499, 1, 1).dayOfGregorianCal, SysTime(DateTime(-499, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(-500, 1, 1).dayOfGregorianCal, SysTime(DateTime(-500, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(-501, 1, 1).dayOfGregorianCal, SysTime(DateTime(-501, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(-1000, 1, 1).dayOfGregorianCal, SysTime(DateTime(-1000, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(-1001, 1, 1).dayOfGregorianCal, SysTime(DateTime(-1001, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(-1599, 1, 1).dayOfGregorianCal, SysTime(DateTime(-1599, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(-1600, 12, 31).dayOfGregorianCal, SysTime(DateTime(-1600, 12, 31, 0, 0, 0), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(-1600, 1, 1).dayOfGregorianCal, SysTime(DateTime(-1600, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(-1601, 1, 1).dayOfGregorianCal, SysTime(DateTime(-1601, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(-1900, 1, 1).dayOfGregorianCal, SysTime(DateTime(-1900, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(-1901, 1, 1).dayOfGregorianCal, SysTime(DateTime(-1901, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(-1999, 1, 1).dayOfGregorianCal, SysTime(DateTime(-1999, 1, 1, 12, 13, 14), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(-1999, 7, 6).dayOfGregorianCal, SysTime(DateTime(-1999, 7, 6, 12, 13, 14), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(-2000, 12, 31).dayOfGregorianCal, SysTime(DateTime(-2000, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(-2000, 1, 1).dayOfGregorianCal, SysTime(DateTime(-2000, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(-2001, 1, 1).dayOfGregorianCal, SysTime(DateTime(-2001, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(-2010, 1, 1).dayOfGregorianCal, SysTime(DateTime(-2010, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(-2010, 1, 31).dayOfGregorianCal, SysTime(DateTime(-2010, 1, 31, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(-2010, 2, 1).dayOfGregorianCal, SysTime(DateTime(-2010, 2, 1, 0, 0, 0), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(-2010, 2, 28).dayOfGregorianCal, SysTime(DateTime(-2010, 2, 28, 0, 0, 0), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(-2010, 3, 1).dayOfGregorianCal, SysTime(DateTime(-2010, 3, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(-2010, 3, 31).dayOfGregorianCal, SysTime(DateTime(-2010, 3, 31, 12, 13, 14), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(-2010, 4, 1).dayOfGregorianCal, SysTime(DateTime(-2010, 4, 1, 12, 13, 14), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(-2010, 4, 30).dayOfGregorianCal, SysTime(DateTime(-2010, 4, 30, 12, 13, 14), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(-2010, 5, 1).dayOfGregorianCal, SysTime(DateTime(-2010, 5, 1, 12, 13, 14), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(-2010, 5, 31).dayOfGregorianCal, SysTime(DateTime(-2010, 5, 31, 23, 59, 59), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(-2010, 6, 1).dayOfGregorianCal, SysTime(DateTime(-2010, 6, 1, 23, 59, 59), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(-2010, 6, 30).dayOfGregorianCal, SysTime(DateTime(-2010, 6, 30, 23, 59, 59), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(-2010, 7, 1).dayOfGregorianCal, SysTime(DateTime(-2010, 7, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(-2010, 7, 31).dayOfGregorianCal, SysTime(DateTime(-2010, 7, 31, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(-2010, 8, 1).dayOfGregorianCal, SysTime(DateTime(-2010, 8, 1, 0, 0, 0), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(-2010, 8, 31).dayOfGregorianCal, SysTime(DateTime(-2010, 8, 31, 0, 0, 0), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(-2010, 9, 1).dayOfGregorianCal, SysTime(DateTime(-2010, 9, 1, 0, 0, 0), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(-2010, 9, 30).dayOfGregorianCal, SysTime(DateTime(-2010, 9, 30, 12, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(-2010, 10, 1).dayOfGregorianCal, SysTime(DateTime(-2010, 10, 1, 0, 12, 0), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(-2010, 10, 31).dayOfGregorianCal, SysTime(DateTime(-2010, 10, 31, 0, 0, 12), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(-2010, 11, 1).dayOfGregorianCal, SysTime(DateTime(-2010, 11, 1, 23, 0, 0), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(-2010, 11, 30).dayOfGregorianCal, SysTime(DateTime(-2010, 11, 30, 0, 59, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(-2010, 12, 1).dayOfGregorianCal, SysTime(DateTime(-2010, 12, 1, 0, 0, 59), FracSec.from!"hnsecs"(500)).dayOfGregorianCal);
assertPred!"=="(Date(-2010, 12, 31).dayOfGregorianCal, SysTime(DateTime(-2010, 12, 31, 0, 59, 59), FracSec.from!"hnsecs"(50_000)).dayOfGregorianCal);
assertPred!"=="(Date(-2012, 2, 1).dayOfGregorianCal, SysTime(DateTime(-2012, 2, 1, 23, 0, 59), FracSec.from!"hnsecs"(9_999_999)).dayOfGregorianCal);
assertPred!"=="(Date(-2012, 2, 28).dayOfGregorianCal, SysTime(DateTime(-2012, 2, 28, 23, 59, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
assertPred!"=="(Date(-2012, 2, 29).dayOfGregorianCal, SysTime(DateTime(-2012, 2, 29, 7, 7, 7), FracSec.from!"hnsecs"(7)).dayOfGregorianCal);
assertPred!"=="(Date(-2012, 3, 1).dayOfGregorianCal, SysTime(DateTime(-2012, 3, 1, 7, 7, 7), FracSec.from!"hnsecs"(7)).dayOfGregorianCal);
assertPred!"=="(Date(-3760, 9, 7).dayOfGregorianCal, SysTime(DateTime(-3760, 9, 7, 0, 0, 0), FracSec.from!"hnsecs"(0)).dayOfGregorianCal);
}
/++
The Xth day of the Gregorian Calendar that this SysTime is on. Setting
this property does not affect the time portion of SysTime.
Params:
days = The day of the Gregorian Calendar to set this Date to.
Examples:
--------------------
auto st = SysTime(DateTime(0, 0, 0, 12, 0, 0));
st.dayOfGregorianCal = 1;
assert(st == SysTime(DateTime(1, 1, 1, 12, 0, 0)));
st.dayOfGregorianCal = 365;
assert(st == SysTime(DateTime(1, 12, 31, 12, 0, 0)));
st.dayOfGregorianCal = 366;
assert(st == SysTime(DateTime(2, 1, 1, 12, 0, 0)));
st.dayOfGregorianCal = 0;
assert(st == SysTime(DateTime(0, 12, 31, 12, 0, 0)));
st.dayOfGregorianCal = -365;
assert(st == SysTime(DateTime(-0, 1, 1, 12, 0, 0)));
st.dayOfGregorianCal = -366;
assert(st == SysTime(DateTime(-1, 12, 31, 12, 0, 0)));
st.dayOfGregorianCal = 730_120;
assert(st == SysTime(DateTime(2000, 1, 1, 12, 0, 0)));
st.dayOfGregorianCal = 734_137;
assert(st == SysTime(DateTime(2010, 12, 31, 12, 0, 0)));
--------------------
+/
@property void dayOfGregorianCal(int days) nothrow
{
auto hnsecs = adjTime;
hnsecs = removeUnitsFromHNSecs!"days"(hnsecs);
if(hnsecs < 0)
hnsecs += convert!("hours", "hnsecs")(24);
if(--days < 0)
{
hnsecs -= convert!("hours", "hnsecs")(24);
++days;
}
immutable newDaysHNSecs = convert!("days", "hnsecs")(days);
adjTime = newDaysHNSecs + hnsecs;
}
unittest
{
void testST(SysTime orig, int day, in SysTime expected, size_t line = __LINE__)
{
orig.dayOfGregorianCal = day;
assertPred!"=="(orig, expected, "", __FILE__, line);
}
//Test A.D.
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
testST(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
//Test B.C.
testST(SysTime(DateTime(0, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)), 0, SysTime(DateTime(0, 12, 31, 0, 0, 0), FracSec.from!"hnsecs"(0)));
testST(SysTime(DateTime(0, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
testST(SysTime(DateTime(0, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(1)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(0, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(0)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0)));
//Test Both.
testST(SysTime(DateTime(-512, 7, 20, 0, 0, 0), FracSec.from!"hnsecs"(0)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(0)));
testST(SysTime(DateTime(-513, 6, 6, 0, 0, 0), FracSec.from!"hnsecs"(1)), 1, SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(-511, 5, 7, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 1, SysTime(DateTime(1, 1, 1, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
testST(SysTime(DateTime(1607, 4, 8, 0, 0, 0), FracSec.from!"hnsecs"(0)), 0, SysTime(DateTime(0, 12, 31, 0, 0, 0), FracSec.from!"hnsecs"(0)));
testST(SysTime(DateTime(1500, 3, 9, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
testST(SysTime(DateTime(999, 2, 10, 23, 59, 59), FracSec.from!"hnsecs"(1)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1)));
testST(SysTime(DateTime(2007, 12, 11, 23, 59, 59), FracSec.from!"hnsecs"(0)), 0, SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(0)));
auto sysTime = SysTime(DateTime(1, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212));
void testST2(int day, in SysTime expected, size_t line = __LINE__)
{
sysTime.dayOfGregorianCal = day;
assertPred!"=="(sysTime, expected, "", __FILE__, line);
}
//Test A.D.
testST2(1, SysTime(DateTime(1, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(2, SysTime(DateTime(1, 1, 2, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(32, SysTime(DateTime(1, 2, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(366, SysTime(DateTime(2, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(731, SysTime(DateTime(3, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(1096, SysTime(DateTime(4, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(1462, SysTime(DateTime(5, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(17_898, SysTime(DateTime(50, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(35_065, SysTime(DateTime(97, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(36_160, SysTime(DateTime(100, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(36_525, SysTime(DateTime(101, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(37_986, SysTime(DateTime(105, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(72_684, SysTime(DateTime(200, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(73_049, SysTime(DateTime(201, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(109_208, SysTime(DateTime(300, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(109_573, SysTime(DateTime(301, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(145_732, SysTime(DateTime(400, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(146_098, SysTime(DateTime(401, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(182_257, SysTime(DateTime(500, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(182_622, SysTime(DateTime(501, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(364_878, SysTime(DateTime(1000, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(365_243, SysTime(DateTime(1001, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(584_023, SysTime(DateTime(1600, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(584_389, SysTime(DateTime(1601, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(693_596, SysTime(DateTime(1900, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(693_961, SysTime(DateTime(1901, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(729_755, SysTime(DateTime(1999, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(730_120, SysTime(DateTime(2000, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(730_486, SysTime(DateTime(2001, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(733_773, SysTime(DateTime(2010, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(733_803, SysTime(DateTime(2010, 1, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(733_804, SysTime(DateTime(2010, 2, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(733_831, SysTime(DateTime(2010, 2, 28, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(733_832, SysTime(DateTime(2010, 3, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(733_862, SysTime(DateTime(2010, 3, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(733_863, SysTime(DateTime(2010, 4, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(733_892, SysTime(DateTime(2010, 4, 30, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(733_893, SysTime(DateTime(2010, 5, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(733_923, SysTime(DateTime(2010, 5, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(733_924, SysTime(DateTime(2010, 6, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(733_953, SysTime(DateTime(2010, 6, 30, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(733_954, SysTime(DateTime(2010, 7, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(733_984, SysTime(DateTime(2010, 7, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(733_985, SysTime(DateTime(2010, 8, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(734_015, SysTime(DateTime(2010, 8, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(734_016, SysTime(DateTime(2010, 9, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(734_045, SysTime(DateTime(2010, 9, 30, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(734_046, SysTime(DateTime(2010, 10, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(734_076, SysTime(DateTime(2010, 10, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(734_077, SysTime(DateTime(2010, 11, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(734_106, SysTime(DateTime(2010, 11, 30, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(734_107, SysTime(DateTime(2010, 12, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(734_137, SysTime(DateTime(2010, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(734_534, SysTime(DateTime(2012, 2, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(734_561, SysTime(DateTime(2012, 2, 28, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(734_562, SysTime(DateTime(2012, 2, 29, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(734_563, SysTime(DateTime(2012, 3, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(734_534, SysTime(DateTime(2012, 2, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(734_561, SysTime(DateTime(2012, 2, 28, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(734_562, SysTime(DateTime(2012, 2, 29, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(734_563, SysTime(DateTime(2012, 3, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
//Test B.C.
testST2(0, SysTime(DateTime(0, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-1, SysTime(DateTime(0, 12, 30, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-30, SysTime(DateTime(0, 12, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-31, SysTime(DateTime(0, 11, 30, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-366, SysTime(DateTime(-1, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-367, SysTime(DateTime(-1, 12, 30, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-730, SysTime(DateTime(-1, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-731, SysTime(DateTime(-2, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-1095, SysTime(DateTime(-2, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-1096, SysTime(DateTime(-3, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-1460, SysTime(DateTime(-3, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-1461, SysTime(DateTime(-4, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-1826, SysTime(DateTime(-4, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-1827, SysTime(DateTime(-5, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-2191, SysTime(DateTime(-5, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-3652, SysTime(DateTime(-9, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-18_262, SysTime(DateTime(-49, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-18_627, SysTime(DateTime(-50, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-35_794, SysTime(DateTime(-97, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-36_160, SysTime(DateTime(-99, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-36_524, SysTime(DateTime(-99, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-36_889, SysTime(DateTime(-100, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-37_254, SysTime(DateTime(-101, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-38_715, SysTime(DateTime(-105, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-73_413, SysTime(DateTime(-200, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-73_778, SysTime(DateTime(-201, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-109_937, SysTime(DateTime(-300, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-110_302, SysTime(DateTime(-301, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-146_097, SysTime(DateTime(-400, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-146_462, SysTime(DateTime(-400, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-146_827, SysTime(DateTime(-401, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-182_621, SysTime(DateTime(-499, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-182_986, SysTime(DateTime(-500, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-183_351, SysTime(DateTime(-501, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-365_607, SysTime(DateTime(-1000, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-365_972, SysTime(DateTime(-1001, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-584_387, SysTime(DateTime(-1599, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-584_388, SysTime(DateTime(-1600, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-584_753, SysTime(DateTime(-1600, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-585_118, SysTime(DateTime(-1601, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-694_325, SysTime(DateTime(-1900, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-694_690, SysTime(DateTime(-1901, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-730_484, SysTime(DateTime(-1999, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-730_485, SysTime(DateTime(-2000, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-730_850, SysTime(DateTime(-2000, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-731_215, SysTime(DateTime(-2001, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-734_502, SysTime(DateTime(-2010, 1, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-734_472, SysTime(DateTime(-2010, 1, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-734_471, SysTime(DateTime(-2010, 2, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-734_444, SysTime(DateTime(-2010, 2, 28, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-734_443, SysTime(DateTime(-2010, 3, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-734_413, SysTime(DateTime(-2010, 3, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-734_412, SysTime(DateTime(-2010, 4, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-734_383, SysTime(DateTime(-2010, 4, 30, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-734_382, SysTime(DateTime(-2010, 5, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-734_352, SysTime(DateTime(-2010, 5, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-734_351, SysTime(DateTime(-2010, 6, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-734_322, SysTime(DateTime(-2010, 6, 30, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-734_321, SysTime(DateTime(-2010, 7, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-734_291, SysTime(DateTime(-2010, 7, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-734_290, SysTime(DateTime(-2010, 8, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-734_260, SysTime(DateTime(-2010, 8, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-734_259, SysTime(DateTime(-2010, 9, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-734_230, SysTime(DateTime(-2010, 9, 30, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-734_229, SysTime(DateTime(-2010, 10, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-734_199, SysTime(DateTime(-2010, 10, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-734_198, SysTime(DateTime(-2010, 11, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-734_169, SysTime(DateTime(-2010, 11, 30, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-734_168, SysTime(DateTime(-2010, 12, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-734_138, SysTime(DateTime(-2010, 12, 31, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-735_202, SysTime(DateTime(-2012, 2, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-735_175, SysTime(DateTime(-2012, 2, 28, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-735_174, SysTime(DateTime(-2012, 2, 29, 12, 2, 9), FracSec.from!"msecs"(212)));
testST2(-735_173, SysTime(DateTime(-2012, 3, 1, 12, 2, 9), FracSec.from!"msecs"(212)));
const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
//immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
static assert(!__traits(compiles, cst.dayOfGregorianCal = 7));
//static assert(!__traits(compiles, ist.dayOfGregorianCal = 7));
//Verify Examples.
auto st = SysTime(DateTime(0, 1, 1, 12, 0, 0));
st.dayOfGregorianCal = 1;
assert(st == SysTime(DateTime(1, 1, 1, 12, 0, 0)));
st.dayOfGregorianCal = 365;
assert(st == SysTime(DateTime(1, 12, 31, 12, 0, 0)));
st.dayOfGregorianCal = 366;
assert(st == SysTime(DateTime(2, 1, 1, 12, 0, 0)));
st.dayOfGregorianCal = 0;
assert(st == SysTime(DateTime(0, 12, 31, 12, 0, 0)));
st.dayOfGregorianCal = -365;
assert(st == SysTime(DateTime(-0, 1, 1, 12, 0, 0)));
st.dayOfGregorianCal = -366;
assert(st == SysTime(DateTime(-1, 12, 31, 12, 0, 0)));
st.dayOfGregorianCal = 730_120;
assert(st == SysTime(DateTime(2000, 1, 1, 12, 0, 0)));
st.dayOfGregorianCal = 734_137;
assert(st == SysTime(DateTime(2010, 12, 31, 12, 0, 0)));
}
/++
The ISO 8601 week of the year that this SysTime is in.
See_Also:
ISO Week Date
+/
@property ubyte isoWeek() const nothrow
{
return (cast(Date)this).isoWeek;
}
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));
static assert(__traits(compiles, st.isoWeek));
static assert(__traits(compiles, cst.isoWeek));
//static assert(__traits(compiles, ist.isoWeek));
}
/++
SysTime for the last day in the month that this Date is in.
The time portion of endOfMonth is always 23:59:59.9999999.
Examples:
--------------------
assert(SysTime(DateTime(1999, 1, 6, 0, 0, 0)).endOfMonth == SysTime(DateTime(1999, 1, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assert(SysTime(DateTime(1999, 2, 7, 19, 30, 0), FracSec.from!"msecs"(24)).endOfMonth == SysTime(DateTime(1999, 2, 28, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assert(SysTime(DateTime(2000, 2, 7, 5, 12, 27), FracSec.from!"usecs"(5203)).endOfMonth == SysTime(DateTime(2000, 2, 29, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assert(SysTime(DateTime(2000, 6, 4, 12, 22, 9), FracSec.from!"hnsecs"(12345)).endOfMonth == SysTime(DateTime(2000, 6, 30, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
--------------------
+/
@property SysTime endOfMonth() const nothrow
{
immutable hnsecs = adjTime;
immutable days = getUnitsFromHNSecs!"days"(hnsecs);
auto date = Date(cast(int)days + 1).endOfMonth;
auto newDays = date.dayOfGregorianCal - 1;
long theTimeHNSecs;
if(newDays < 0)
{
theTimeHNSecs = -1;
++newDays;
}
else
theTimeHNSecs = convert!("days", "hnsecs")(1) - 1;
immutable newDaysHNSecs = convert!("days", "hnsecs")(newDays);
auto retval = SysTime(this._stdTime, this._timezone.get);
retval.adjTime = newDaysHNSecs + theTimeHNSecs;
return retval;
}
unittest
{
//Test A.D.
assertPred!"=="(SysTime(Date(1999, 1, 1)).endOfMonth, SysTime(DateTime(1999, 1, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assertPred!"=="(SysTime(Date(1999, 2, 1)).endOfMonth, SysTime(DateTime(1999, 2, 28, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assertPred!"=="(SysTime(Date(2000, 2, 1)).endOfMonth, SysTime(DateTime(2000, 2, 29, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assertPred!"=="(SysTime(Date(1999, 3, 1)).endOfMonth, SysTime(DateTime(1999, 3, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assertPred!"=="(SysTime(Date(1999, 4, 1)).endOfMonth, SysTime(DateTime(1999, 4, 30, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assertPred!"=="(SysTime(Date(1999, 5, 1)).endOfMonth, SysTime(DateTime(1999, 5, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assertPred!"=="(SysTime(Date(1999, 6, 1)).endOfMonth, SysTime(DateTime(1999, 6, 30, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assertPred!"=="(SysTime(Date(1999, 7, 1)).endOfMonth, SysTime(DateTime(1999, 7, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assertPred!"=="(SysTime(Date(1999, 8, 1)).endOfMonth, SysTime(DateTime(1999, 8, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assertPred!"=="(SysTime(Date(1999, 9, 1)).endOfMonth, SysTime(DateTime(1999, 9, 30, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assertPred!"=="(SysTime(Date(1999, 10, 1)).endOfMonth, SysTime(DateTime(1999, 10, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assertPred!"=="(SysTime(Date(1999, 11, 1)).endOfMonth, SysTime(DateTime(1999, 11, 30, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assertPred!"=="(SysTime(Date(1999, 12, 1)).endOfMonth, SysTime(DateTime(1999, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
//Test B.C.
assertPred!"=="(SysTime(Date(-1999, 1, 1)).endOfMonth, SysTime(DateTime(-1999, 1, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assertPred!"=="(SysTime(Date(-1999, 2, 1)).endOfMonth, SysTime(DateTime(-1999, 2, 28, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assertPred!"=="(SysTime(Date(-2000, 2, 1)).endOfMonth, SysTime(DateTime(-2000, 2, 29, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assertPred!"=="(SysTime(Date(-1999, 3, 1)).endOfMonth, SysTime(DateTime(-1999, 3, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assertPred!"=="(SysTime(Date(-1999, 4, 1)).endOfMonth, SysTime(DateTime(-1999, 4, 30, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assertPred!"=="(SysTime(Date(-1999, 5, 1)).endOfMonth, SysTime(DateTime(-1999, 5, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assertPred!"=="(SysTime(Date(-1999, 6, 1)).endOfMonth, SysTime(DateTime(-1999, 6, 30, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assertPred!"=="(SysTime(Date(-1999, 7, 1)).endOfMonth, SysTime(DateTime(-1999, 7, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assertPred!"=="(SysTime(Date(-1999, 8, 1)).endOfMonth, SysTime(DateTime(-1999, 8, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assertPred!"=="(SysTime(Date(-1999, 9, 1)).endOfMonth, SysTime(DateTime(-1999, 9, 30, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assertPred!"=="(SysTime(Date(-1999, 10, 1)).endOfMonth, SysTime(DateTime(-1999, 10, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assertPred!"=="(SysTime(Date(-1999, 11, 1)).endOfMonth, SysTime(DateTime(-1999, 11, 30, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assertPred!"=="(SysTime(Date(-1999, 12, 1)).endOfMonth, SysTime(DateTime(-1999, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
//immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
static assert(__traits(compiles, cst.endOfMonth));
//static assert(__traits(compiles, ist.endOfMonth));
//Verify Examples.
assert(SysTime(DateTime(1999, 1, 6, 0, 0, 0)).endOfMonth == SysTime(DateTime(1999, 1, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assert(SysTime(DateTime(1999, 2, 7, 19, 30, 0), FracSec.from!"msecs"(24)).endOfMonth == SysTime(DateTime(1999, 2, 28, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assert(SysTime(DateTime(2000, 2, 7, 5, 12, 27), FracSec.from!"usecs"(5203)).endOfMonth == SysTime(DateTime(2000, 2, 29, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
assert(SysTime(DateTime(2000, 6, 4, 12, 22, 9), FracSec.from!"hnsecs"(12345)).endOfMonth == SysTime(DateTime(2000, 6, 30, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999)));
}
/++
The last day in the month that this SysTime is in.
Examples:
--------------------
assert(SysTime(DateTime(1999, 1, 6, 0, 0, 0)).endOfMonthDay == 31);
assert(SysTime(DateTime(1999, 2, 7, 19, 30, 0)).endOfMonthDay == 28);
assert(SysTime(DateTime(2000, 2, 7, 5, 12, 27)).endOfMonthDay == 29);
assert(SysTime(DateTime(2000, 6, 4, 12, 22, 9)).endOfMonthDay == 30);
--------------------
+/
@property ubyte endOfMonthDay() const nothrow
{
return Date(dayOfGregorianCal).endOfMonthDay;
}
unittest
{
//Test A.D.
assertPred!"=="(SysTime(DateTime(1999, 1, 1, 12, 1, 13)).endOfMonthDay, 31);
assertPred!"=="(SysTime(DateTime(1999, 2, 1, 17, 13, 12)).endOfMonthDay, 28);
assertPred!"=="(SysTime(DateTime(2000, 2, 1, 13, 2, 12)).endOfMonthDay, 29);
assertPred!"=="(SysTime(DateTime(1999, 3, 1, 12, 13, 12)).endOfMonthDay, 31);
assertPred!"=="(SysTime(DateTime(1999, 4, 1, 12, 6, 13)).endOfMonthDay, 30);
assertPred!"=="(SysTime(DateTime(1999, 5, 1, 15, 13, 12)).endOfMonthDay, 31);
assertPred!"=="(SysTime(DateTime(1999, 6, 1, 13, 7, 12)).endOfMonthDay, 30);
assertPred!"=="(SysTime(DateTime(1999, 7, 1, 12, 13, 17)).endOfMonthDay, 31);
assertPred!"=="(SysTime(DateTime(1999, 8, 1, 12, 3, 13)).endOfMonthDay, 31);
assertPred!"=="(SysTime(DateTime(1999, 9, 1, 12, 13, 12)).endOfMonthDay, 30);
assertPred!"=="(SysTime(DateTime(1999, 10, 1, 13, 19, 12)).endOfMonthDay, 31);
assertPred!"=="(SysTime(DateTime(1999, 11, 1, 12, 13, 17)).endOfMonthDay, 30);
assertPred!"=="(SysTime(DateTime(1999, 12, 1, 12, 52, 13)).endOfMonthDay, 31);
//Test B.C.
assertPred!"=="(SysTime(DateTime(-1999, 1, 1, 12, 1, 13)).endOfMonthDay, 31);
assertPred!"=="(SysTime(DateTime(-1999, 2, 1, 7, 13, 12)).endOfMonthDay, 28);
assertPred!"=="(SysTime(DateTime(-2000, 2, 1, 13, 2, 12)).endOfMonthDay, 29);
assertPred!"=="(SysTime(DateTime(-1999, 3, 1, 12, 13, 12)).endOfMonthDay, 31);
assertPred!"=="(SysTime(DateTime(-1999, 4, 1, 12, 6, 13)).endOfMonthDay, 30);
assertPred!"=="(SysTime(DateTime(-1999, 5, 1, 5, 13, 12)).endOfMonthDay, 31);
assertPred!"=="(SysTime(DateTime(-1999, 6, 1, 13, 7, 12)).endOfMonthDay, 30);
assertPred!"=="(SysTime(DateTime(-1999, 7, 1, 12, 13, 17)).endOfMonthDay, 31);
assertPred!"=="(SysTime(DateTime(-1999, 8, 1, 12, 3, 13)).endOfMonthDay, 31);
assertPred!"=="(SysTime(DateTime(-1999, 9, 1, 12, 13, 12)).endOfMonthDay, 30);
assertPred!"=="(SysTime(DateTime(-1999, 10, 1, 13, 19, 12)).endOfMonthDay, 31);
assertPred!"=="(SysTime(DateTime(-1999, 11, 1, 12, 13, 17)).endOfMonthDay, 30);
assertPred!"=="(SysTime(DateTime(-1999, 12, 1, 12, 52, 13)).endOfMonthDay, 31);
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.endOfMonthDay));
//static assert(__traits(compiles, ist.endOfMonthDay));
//Verify Examples.
assert(SysTime(DateTime(1999, 1, 6, 0, 0, 0)).endOfMonthDay == 31);
assert(SysTime(DateTime(1999, 2, 7, 19, 30, 0)).endOfMonthDay == 28);
assert(SysTime(DateTime(2000, 2, 7, 5, 12, 27)).endOfMonthDay == 29);
assert(SysTime(DateTime(2000, 6, 4, 12, 22, 9)).endOfMonthDay == 30);
}
/++
Whether the current year is a date in A.D.
Examples:
--------------------
assert(SysTime(DateTime(1, 1, 1, 12, 7, 0)).isAD);
assert(SysTime(DateTime(2010, 12, 31, 0, 0, 0)).isAD);
assert(!SysTime(DateTime(0, 12, 31, 23, 59, 59)).isAD);
assert(!SysTime(DateTime(-2010, 1, 1, 2, 2, 2)).isAD);
--------------------
+/
@property bool isAD() const nothrow
{
return adjTime >= 0;
}
unittest
{
assert(SysTime(DateTime(2010, 7, 4, 12, 0, 9)).isAD);
assert(SysTime(DateTime(1, 1, 1, 0, 0, 0)).isAD);
assert(!SysTime(DateTime(0, 12, 31, 23, 59, 59)).isAD);
assert(!SysTime(DateTime(0, 1, 1, 23, 59, 59)).isAD);
assert(!SysTime(DateTime(-1, 1, 1, 23 ,59 ,59)).isAD);
assert(!SysTime(DateTime(-2010, 7, 4, 12, 2, 2)).isAD);
const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
//immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
static assert(__traits(compiles, cst.isAD));
//static assert(__traits(compiles, ist.isAD));
//Verify Examples.
assert(SysTime(DateTime(1, 1, 1, 12, 7, 0)).isAD);
assert(SysTime(DateTime(2010, 12, 31, 0, 0, 0)).isAD);
assert(!SysTime(DateTime(0, 12, 31, 23, 59, 59)).isAD);
assert(!SysTime(DateTime(-2010, 1, 1, 2, 2, 2)).isAD);
}
/++
The julian day for this SysTime at the given time. For example, prior
to noon, 1996-03-31 would be the julian day number 2_450_173, so this
function returns 2_450_173, while from noon onward, it the julian day
number would be 2_450_174, so this function returns 2_450_174.
+/
@property long julianDay() const nothrow
{
immutable jd = dayOfGregorianCal + 1_721_425;
return hour < 12 ? jd - 1 : jd;
}
unittest
{
assertPred!"=="(SysTime(DateTime(-4713, 11, 24, 0, 0, 0)).julianDay, -1);
assertPred!"=="(SysTime(DateTime(-4713, 11, 24, 12, 0, 0)).julianDay, 0);
assertPred!"=="(SysTime(DateTime(0, 12, 31, 0, 0, 0)).julianDay, 1_721_424);
assertPred!"=="(SysTime(DateTime(0, 12, 31, 12, 0, 0)).julianDay, 1_721_425);
assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0)).julianDay, 1_721_425);
assertPred!"=="(SysTime(DateTime(1, 1, 1, 12, 0, 0)).julianDay, 1_721_426);
assertPred!"=="(SysTime(DateTime(1582, 10, 15, 0, 0, 0)).julianDay, 2_299_160);
assertPred!"=="(SysTime(DateTime(1582, 10, 15, 12, 0, 0)).julianDay, 2_299_161);
assertPred!"=="(SysTime(DateTime(1858, 11, 17, 0, 0, 0)).julianDay, 2_400_000);
assertPred!"=="(SysTime(DateTime(1858, 11, 17, 12, 0, 0)).julianDay, 2_400_001);
assertPred!"=="(SysTime(DateTime(1982, 1, 4, 0, 0, 0)).julianDay, 2_444_973);
assertPred!"=="(SysTime(DateTime(1982, 1, 4, 12, 0, 0)).julianDay, 2_444_974);
assertPred!"=="(SysTime(DateTime(1996, 3, 31, 0, 0, 0)).julianDay, 2_450_173);
assertPred!"=="(SysTime(DateTime(1996, 3, 31, 12, 0, 0)).julianDay, 2_450_174);
assertPred!"=="(SysTime(DateTime(2010, 8, 24, 0, 0, 0)).julianDay, 2_455_432);
assertPred!"=="(SysTime(DateTime(2010, 8, 24, 12, 0, 0)).julianDay, 2_455_433);
const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
//immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
static assert(__traits(compiles, cst.julianDay));
//static assert(__traits(compiles, ist.julianDay));
}
/++
The modified julian day for any time on this Date (since, the modified
julian day changes at midnight).
+/
@property long modJulianDay() const nothrow
{
return (dayOfGregorianCal + 1_721_425) - 2_400_001;
}
unittest
{
assertPred!"=="(SysTime(DateTime(1858, 11, 17, 0, 0, 0)).modJulianDay, 0);
assertPred!"=="(SysTime(DateTime(1858, 11, 17, 12, 0, 0)).modJulianDay, 0);
assertPred!"=="(SysTime(DateTime(2010, 8, 24, 0, 0, 0)).modJulianDay, 55_432);
assertPred!"=="(SysTime(DateTime(2010, 8, 24, 12, 0, 0)).modJulianDay, 55_432);
const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
//immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
static assert(__traits(compiles, cst.modJulianDay));
//static assert(__traits(compiles, ist.modJulianDay));
}
/++
Returns a Date equivalent to this SysTime.
+/
Date opCast(T)() const nothrow
if(is(Unqual!T == Date))
{
return Date(dayOfGregorianCal);
}
unittest
{
assertPred!"=="(cast(Date)SysTime(Date(1999, 7, 6)), Date(1999, 7, 6));
assertPred!"=="(cast(Date)SysTime(Date(2000, 12, 31)), Date(2000, 12, 31));
assertPred!"=="(cast(Date)SysTime(Date(2001, 1, 1)), Date(2001, 1, 1));
assertPred!"=="(cast(Date)SysTime(DateTime(1999, 7, 6, 12, 10, 9)), Date(1999, 7, 6));
assertPred!"=="(cast(Date)SysTime(DateTime(2000, 12, 31, 13, 11, 10)), Date(2000, 12, 31));
assertPred!"=="(cast(Date)SysTime(DateTime(2001, 1, 1, 14, 12, 11)), Date(2001, 1, 1));
assertPred!"=="(cast(Date)SysTime(Date(-1999, 7, 6)), Date(-1999, 7, 6));
assertPred!"=="(cast(Date)SysTime(Date(-2000, 12, 31)), Date(-2000, 12, 31));
assertPred!"=="(cast(Date)SysTime(Date(-2001, 1, 1)), Date(-2001, 1, 1));
assertPred!"=="(cast(Date)SysTime(DateTime(-1999, 7, 6, 12, 10, 9)), Date(-1999, 7, 6));
assertPred!"=="(cast(Date)SysTime(DateTime(-2000, 12, 31, 13, 11, 10)), Date(-2000, 12, 31));
assertPred!"=="(cast(Date)SysTime(DateTime(-2001, 1, 1, 14, 12, 11)), Date(-2001, 1, 1));
const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
//immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
static assert(__traits(compiles, cast(Date)cst));
//static assert(__traits(compiles, cast(Date)ist));
}
/++
Returns a DateTime equivalent to this SysTime.
+/
DateTime opCast(T)() const nothrow
if(is(Unqual!T == DateTime))
{
try
{
auto hnsecs = adjTime;
auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
if(hnsecs < 0)
{
hnsecs += convert!("hours", "hnsecs")(24);
--days;
}
immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
immutable second = getUnitsFromHNSecs!"seconds"(hnsecs);
return DateTime(Date(cast(int)days), TimeOfDay(cast(int)hour, cast(int)minute, cast(int)second));
}
catch(Exception e)
assert(0, "Either DateTime's constructor or TimeOfDay's constructor threw.");
}
unittest
{
assertPred!"=="(cast(DateTime)SysTime(DateTime(1, 1, 6, 7, 12, 22)), DateTime(1, 1, 6, 7, 12, 22));
assertPred!"=="(cast(DateTime)SysTime(DateTime(1, 1, 6, 7, 12, 22), FracSec.from!"msecs"(22)), DateTime(1, 1, 6, 7, 12, 22));
assertPred!"=="(cast(DateTime)SysTime(Date(1999, 7, 6)), DateTime(1999, 7, 6, 0, 0, 0));
assertPred!"=="(cast(DateTime)SysTime(Date(2000, 12, 31)), DateTime(2000, 12, 31, 0, 0, 0));
assertPred!"=="(cast(DateTime)SysTime(Date(2001, 1, 1)), DateTime(2001, 1, 1, 0, 0, 0));
assertPred!"=="(cast(DateTime)SysTime(DateTime(1999, 7, 6, 12, 10, 9)), DateTime(1999, 7, 6, 12, 10, 9));
assertPred!"=="(cast(DateTime)SysTime(DateTime(2000, 12, 31, 13, 11, 10)), DateTime(2000, 12, 31, 13, 11, 10));
assertPred!"=="(cast(DateTime)SysTime(DateTime(2001, 1, 1, 14, 12, 11)), DateTime(2001, 1, 1, 14, 12, 11));
assertPred!"=="(cast(DateTime)SysTime(DateTime(-1, 1, 6, 7, 12, 22)), DateTime(-1, 1, 6, 7, 12, 22));
assertPred!"=="(cast(DateTime)SysTime(DateTime(-1, 1, 6, 7, 12, 22), FracSec.from!"msecs"(22)), DateTime(-1, 1, 6, 7, 12, 22));
assertPred!"=="(cast(DateTime)SysTime(Date(-1999, 7, 6)), DateTime(-1999, 7, 6, 0, 0, 0));
assertPred!"=="(cast(DateTime)SysTime(Date(-2000, 12, 31)), DateTime(-2000, 12, 31, 0, 0, 0));
assertPred!"=="(cast(DateTime)SysTime(Date(-2001, 1, 1)), DateTime(-2001, 1, 1, 0, 0, 0));
assertPred!"=="(cast(DateTime)SysTime(DateTime(-1999, 7, 6, 12, 10, 9)), DateTime(-1999, 7, 6, 12, 10, 9));
assertPred!"=="(cast(DateTime)SysTime(DateTime(-2000, 12, 31, 13, 11, 10)), DateTime(-2000, 12, 31, 13, 11, 10));
assertPred!"=="(cast(DateTime)SysTime(DateTime(-2001, 1, 1, 14, 12, 11)), DateTime(-2001, 1, 1, 14, 12, 11));
const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
//immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
static assert(__traits(compiles, cast(DateTime)cst));
//static assert(__traits(compiles, cast(DateTime)ist));
}
/++
Returns a TimeOfDay equivalent to this SysTime.
+/
TimeOfDay opCast(T)() const nothrow
if(is(Unqual!T == TimeOfDay))
{
try
{
auto hnsecs = adjTime;
hnsecs = removeUnitsFromHNSecs!"days"(hnsecs);
if(hnsecs < 0)
hnsecs += convert!("hours", "hnsecs")(24);
immutable hour = splitUnitsFromHNSecs!"hours"(hnsecs);
immutable minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
immutable second = getUnitsFromHNSecs!"seconds"(hnsecs);
return TimeOfDay(cast(int)hour, cast(int)minute, cast(int)second);
}
catch(Exception e)
assert(0, "TimeOfDay's constructor threw.");
}
unittest
{
assertPred!"=="(cast(TimeOfDay)SysTime(Date(1999, 7, 6)), TimeOfDay(0, 0, 0));
assertPred!"=="(cast(TimeOfDay)SysTime(Date(2000, 12, 31)), TimeOfDay(0, 0, 0));
assertPred!"=="(cast(TimeOfDay)SysTime(Date(2001, 1, 1)), TimeOfDay(0, 0, 0));
assertPred!"=="(cast(TimeOfDay)SysTime(DateTime(1999, 7, 6, 12, 10, 9)), TimeOfDay(12, 10, 9));
assertPred!"=="(cast(TimeOfDay)SysTime(DateTime(2000, 12, 31, 13, 11, 10)), TimeOfDay(13, 11, 10));
assertPred!"=="(cast(TimeOfDay)SysTime(DateTime(2001, 1, 1, 14, 12, 11)), TimeOfDay(14, 12, 11));
assertPred!"=="(cast(TimeOfDay)SysTime(Date(-1999, 7, 6)), TimeOfDay(0, 0, 0));
assertPred!"=="(cast(TimeOfDay)SysTime(Date(-2000, 12, 31)), TimeOfDay(0, 0, 0));
assertPred!"=="(cast(TimeOfDay)SysTime(Date(-2001, 1, 1)), TimeOfDay(0, 0, 0));
assertPred!"=="(cast(TimeOfDay)SysTime(DateTime(-1999, 7, 6, 12, 10, 9)), TimeOfDay(12, 10, 9));
assertPred!"=="(cast(TimeOfDay)SysTime(DateTime(-2000, 12, 31, 13, 11, 10)), TimeOfDay(13, 11, 10));
assertPred!"=="(cast(TimeOfDay)SysTime(DateTime(-2001, 1, 1, 14, 12, 11)), TimeOfDay(14, 12, 11));
const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
//immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
static assert(__traits(compiles, cast(TimeOfDay)cst));
//static assert(__traits(compiles, cast(TimeOfDay)ist));
}
//Temporary hack until bug http://d.puremagic.com/issues/show_bug.cgi?id=4867 is fixed.
//This allows assignment from const(SysTime) to SysTime.
//It may be a good idea to keep it though, since casting from a type to itself
//should be allowed, and it doesn't work without this opCast() since opCast()
//has already been defined for other types.
SysTime opCast(T)() const pure nothrow
if(is(Unqual!T == SysTime))
{
return SysTime(_stdTime, _timezone.get);
}
/++
Converts this SysTime to a string with the format YYYYMMDDTHHMMSS.FFFFFFFTZ
(where F is fractional seconds and TZ is time zone).
Note that the number of digits in the fractional seconds varies with the
number of fractional seconds. It's a maximum of 7 (which would be hnsecs),
but only has as many as are necessary to hold the correct value (so no
trailing zeroes), and if there are no fractional seconds, then there is
no decimal point.
If this SysTime's time zone is LocalTime, then TZ is empty. If the time zone
is UTC, then it is "Z". Otherwise, it is the offset from UTC (e.g. +1:00 or -7:00).
Note that the offset from UTC is $(I not) enough to uniquely identify the time zone.
Time zone offsets will be in the form +HH:MM or -HH:MM.
Examples:
--------------------
assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toISOString() ==
"20100704T070612");
assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0), FracSec.from!"msecs"(24)).toISOString() ==
"19981225T021500.024");
assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toISOString() ==
"00000105T230959");
assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), FracSec.from!"hnsecs"(520920)).toISOString() ==
"-00040105T000002.052092");
--------------------
+/
string toISOString() const nothrow
{
try
{
immutable adjustedTime = adjTime;
long hnsecs = adjustedTime;
auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
if(hnsecs < 0)
{
hnsecs += convert!("hours", "hnsecs")(24);
--days;
}
auto hour = splitUnitsFromHNSecs!"hours"(hnsecs);
auto minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
auto second = splitUnitsFromHNSecs!"seconds"(hnsecs);
auto dateTime = DateTime(Date(cast(int)days), TimeOfDay(cast(int)hour, cast(int)minute, cast(int)second));
auto fracSecStr = fracSecToISOString(cast(int)hnsecs);
if(_timezone.get is LocalTime())
return dateTime.toISOString() ~ fracSecToISOString(cast(int)hnsecs);
if(_timezone.get is UTC())
return dateTime.toISOString() ~ fracSecToISOString(cast(int)hnsecs) ~ "Z";
immutable utcOffset = cast(int)convert!("hnsecs", "minutes")(stdTime - adjustedTime);
return dateTime.toISOString() ~ fracSecToISOString(cast(int)hnsecs) ~ SimpleTimeZone.toISOString(utcOffset);
}
catch(Exception e)
assert(0, "format() threw.");
}
unittest
{
//Test A.D.
assertPred!"=="(SysTime(DateTime.init, UTC()).toISOString(), "00010101T000000Z");
assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1), UTC()).toISOString(), "00010101T000000.0000001Z");
assertPred!"=="(SysTime(DateTime(9, 12, 4, 0, 0, 0)).toISOString(), "00091204T000000");
assertPred!"=="(SysTime(DateTime(99, 12, 4, 5, 6, 12)).toISOString(), "00991204T050612");
assertPred!"=="(SysTime(DateTime(999, 12, 4, 13, 44, 59)).toISOString(), "09991204T134459");
assertPred!"=="(SysTime(DateTime(9999, 7, 4, 23, 59, 59)).toISOString(), "99990704T235959");
assertPred!"=="(SysTime(DateTime(10000, 10, 20, 1, 1, 1)).toISOString(), "+100001020T010101");
assertPred!"=="(SysTime(DateTime(9, 12, 4, 0, 0, 0), FracSec.from!"msecs"(42)).toISOString(), "00091204T000000.042");
assertPred!"=="(SysTime(DateTime(99, 12, 4, 5, 6, 12), FracSec.from!"msecs"(100)).toISOString(), "00991204T050612.1");
assertPred!"=="(SysTime(DateTime(999, 12, 4, 13, 44, 59), FracSec.from!"usecs"(45020)).toISOString(), "09991204T134459.04502");
assertPred!"=="(SysTime(DateTime(9999, 7, 4, 23, 59, 59), FracSec.from!"hnsecs"(12)).toISOString(), "99990704T235959.0000012");
assertPred!"=="(SysTime(DateTime(10000, 10, 20, 1, 1, 1), FracSec.from!"hnsecs"(507890)).toISOString(), "+100001020T010101.050789");
//Test B.C.
assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999), UTC()).toISOString(), "00001231T235959.9999999Z");
assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1), UTC()).toISOString(), "00001231T235959.0000001Z");
assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), UTC()).toISOString(), "00001231T235959Z");
assertPred!"=="(SysTime(DateTime(0, 12, 4, 0, 12, 4)).toISOString(), "00001204T001204");
assertPred!"=="(SysTime(DateTime(-9, 12, 4, 0, 0, 0)).toISOString(), "-00091204T000000");
assertPred!"=="(SysTime(DateTime(-99, 12, 4, 5, 6, 12)).toISOString(), "-00991204T050612");
assertPred!"=="(SysTime(DateTime(-999, 12, 4, 13, 44, 59)).toISOString(), "-09991204T134459");
assertPred!"=="(SysTime(DateTime(-9999, 7, 4, 23, 59, 59)).toISOString(), "-99990704T235959");
assertPred!"=="(SysTime(DateTime(-10000, 10, 20, 1, 1, 1)).toISOString(), "-100001020T010101");
assertPred!"=="(SysTime(DateTime(0, 12, 4, 0, 0, 0), FracSec.from!"msecs"(7)).toISOString(), "00001204T000000.007");
assertPred!"=="(SysTime(DateTime(-9, 12, 4, 0, 0, 0), FracSec.from!"msecs"(42)).toISOString(), "-00091204T000000.042");
assertPred!"=="(SysTime(DateTime(-99, 12, 4, 5, 6, 12), FracSec.from!"msecs"(100)).toISOString(), "-00991204T050612.1");
assertPred!"=="(SysTime(DateTime(-999, 12, 4, 13, 44, 59), FracSec.from!"usecs"(45020)).toISOString(), "-09991204T134459.04502");
assertPred!"=="(SysTime(DateTime(-9999, 7, 4, 23, 59, 59), FracSec.from!"hnsecs"(12)).toISOString(), "-99990704T235959.0000012");
assertPred!"=="(SysTime(DateTime(-10000, 10, 20, 1, 1, 1), FracSec.from!"hnsecs"(507890)).toISOString(), "-100001020T010101.050789");
const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
//immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
static assert(__traits(compiles, cast(TimeOfDay)cst));
//static assert(__traits(compiles, cast(TimeOfDay)ist));
//Verify Examples.
assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toISOString() == "20100704T070612");
assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0), FracSec.from!"msecs"(24)).toISOString() == "19981225T021500.024");
assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toISOString() == "00000105T230959");
assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), FracSec.from!"hnsecs"(520920)).toISOString() == "-00040105T000002.052092");
}
/++
Converts this SysTime to a string with the format YYYY-MM-DDTHH:MM:SS.FFFFFFFTZ
(where F is fractional seconds and TZ is time zone).
Note that the number of digits in the fractional seconds varies with the
number of fractional seconds. It's a maximum of 7 (which would be hnsecs),
but only has as many as are necessary to hold the correct value (so no
trailing zeroes), and if there are no fractional seconds, then there is
no decimal point.
If this SysTime's time zone is LocalTime, then TZ is empty. If the time
zone is UTC, then it is "Z". Otherwise, it is the offset from UTC
(e.g. +1:00 or -7:00). Note that the offset from UTC is $(I not) enough
to uniquely identify the time zone.
Time zone offsets will be in the form +HH:MM or -HH:MM.
Examples:
--------------------
assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toISOExtendedString() ==
"2010-07-04T07:06:12");
assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0), FracSec.from!"msecs"(24)).toISOExtendedString() ==
"1998-12-25T02:15:00.024");
assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toISOExtendedString() ==
"0000-01-05T23:09:59");
assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), FracSec.from!"hnsecs"(520920)).toISOExtendedString() ==
"-0004-01-05T00:00:02.052092");
--------------------
+/
string toISOExtendedString() const nothrow
{
try
{
immutable adjustedTime = adjTime;
long hnsecs = adjustedTime;
auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
if(hnsecs < 0)
{
hnsecs += convert!("hours", "hnsecs")(24);
--days;
}
auto hour = splitUnitsFromHNSecs!"hours"(hnsecs);
auto minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
auto second = splitUnitsFromHNSecs!"seconds"(hnsecs);
auto dateTime = DateTime(Date(cast(int)days), TimeOfDay(cast(int)hour, cast(int)minute, cast(int)second));
auto fracSecStr = fracSecToISOString(cast(int)hnsecs);
if(_timezone.get is LocalTime())
return dateTime.toISOExtendedString() ~ fracSecToISOString(cast(int)hnsecs);
if(_timezone.get is UTC())
return dateTime.toISOExtendedString() ~ fracSecToISOString(cast(int)hnsecs) ~ "Z";
immutable utcOffset = cast(int)convert!("hnsecs", "minutes")(stdTime - adjustedTime);
return dateTime.toISOExtendedString() ~ fracSecToISOString(cast(int)hnsecs) ~ SimpleTimeZone.toISOString(utcOffset);
}
catch(Exception e)
assert(0, "format() threw.");
}
unittest
{
//Test A.D.
assertPred!"=="(SysTime(DateTime.init, UTC()).toISOExtendedString(), "0001-01-01T00:00:00Z");
assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1), UTC()).toISOExtendedString(), "0001-01-01T00:00:00.0000001Z");
assertPred!"=="(SysTime(DateTime(9, 12, 4, 0, 0, 0)).toISOExtendedString(), "0009-12-04T00:00:00");
assertPred!"=="(SysTime(DateTime(99, 12, 4, 5, 6, 12)).toISOExtendedString(), "0099-12-04T05:06:12");
assertPred!"=="(SysTime(DateTime(999, 12, 4, 13, 44, 59)).toISOExtendedString(), "0999-12-04T13:44:59");
assertPred!"=="(SysTime(DateTime(9999, 7, 4, 23, 59, 59)).toISOExtendedString(), "9999-07-04T23:59:59");
assertPred!"=="(SysTime(DateTime(10000, 10, 20, 1, 1, 1)).toISOExtendedString(), "+10000-10-20T01:01:01");
assertPred!"=="(SysTime(DateTime(9, 12, 4, 0, 0, 0), FracSec.from!"msecs"(42)).toISOExtendedString(), "0009-12-04T00:00:00.042");
assertPred!"=="(SysTime(DateTime(99, 12, 4, 5, 6, 12), FracSec.from!"msecs"(100)).toISOExtendedString(), "0099-12-04T05:06:12.1");
assertPred!"=="(SysTime(DateTime(999, 12, 4, 13, 44, 59), FracSec.from!"usecs"(45020)).toISOExtendedString(), "0999-12-04T13:44:59.04502");
assertPred!"=="(SysTime(DateTime(9999, 7, 4, 23, 59, 59), FracSec.from!"hnsecs"(12)).toISOExtendedString(), "9999-07-04T23:59:59.0000012");
assertPred!"=="(SysTime(DateTime(10000, 10, 20, 1, 1, 1), FracSec.from!"hnsecs"(507890)).toISOExtendedString(), "+10000-10-20T01:01:01.050789");
//Test B.C.
assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999), UTC()).toISOExtendedString(), "0000-12-31T23:59:59.9999999Z");
assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1), UTC()).toISOExtendedString(), "0000-12-31T23:59:59.0000001Z");
assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), UTC()).toISOExtendedString(), "0000-12-31T23:59:59Z");
assertPred!"=="(SysTime(DateTime(0, 12, 4, 0, 12, 4)).toISOExtendedString(), "0000-12-04T00:12:04");
assertPred!"=="(SysTime(DateTime(-9, 12, 4, 0, 0, 0)).toISOExtendedString(), "-0009-12-04T00:00:00");
assertPred!"=="(SysTime(DateTime(-99, 12, 4, 5, 6, 12)).toISOExtendedString(), "-0099-12-04T05:06:12");
assertPred!"=="(SysTime(DateTime(-999, 12, 4, 13, 44, 59)).toISOExtendedString(), "-0999-12-04T13:44:59");
assertPred!"=="(SysTime(DateTime(-9999, 7, 4, 23, 59, 59)).toISOExtendedString(), "-9999-07-04T23:59:59");
assertPred!"=="(SysTime(DateTime(-10000, 10, 20, 1, 1, 1)).toISOExtendedString(), "-10000-10-20T01:01:01");
assertPred!"=="(SysTime(DateTime(0, 12, 4, 0, 0, 0), FracSec.from!"msecs"(7)).toISOExtendedString(), "0000-12-04T00:00:00.007");
assertPred!"=="(SysTime(DateTime(-9, 12, 4, 0, 0, 0), FracSec.from!"msecs"(42)).toISOExtendedString(), "-0009-12-04T00:00:00.042");
assertPred!"=="(SysTime(DateTime(-99, 12, 4, 5, 6, 12), FracSec.from!"msecs"(100)).toISOExtendedString(), "-0099-12-04T05:06:12.1");
assertPred!"=="(SysTime(DateTime(-999, 12, 4, 13, 44, 59), FracSec.from!"usecs"(45020)).toISOExtendedString(), "-0999-12-04T13:44:59.04502");
assertPred!"=="(SysTime(DateTime(-9999, 7, 4, 23, 59, 59), FracSec.from!"hnsecs"(12)).toISOExtendedString(), "-9999-07-04T23:59:59.0000012");
assertPred!"=="(SysTime(DateTime(-10000, 10, 20, 1, 1, 1), FracSec.from!"hnsecs"(507890)).toISOExtendedString(), "-10000-10-20T01:01:01.050789");
const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
//immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
static assert(__traits(compiles, cast(TimeOfDay)cst));
//static assert(__traits(compiles, cast(TimeOfDay)ist));
//Verify Examples.
assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toISOExtendedString() == "2010-07-04T07:06:12");
assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0), FracSec.from!"msecs"(24)).toISOExtendedString() == "1998-12-25T02:15:00.024");
assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toISOExtendedString() == "0000-01-05T23:09:59");
assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), FracSec.from!"hnsecs"(520920)).toISOExtendedString() == "-0004-01-05T00:00:02.052092");
}
/++
Converts this SysTime to a string with the format YYYY-Mon-DD HH:MM:SS.FFFFFFFTZ
(where F is fractional seconds and TZ is time zone).
Note that the number of digits in the fractional seconds varies with the
number of fractional seconds. It's a maximum of 7 (which would be hnsecs),
but only has as many as are necessary to hold the correct value (so no
trailing zeroes), and if there are no fractional seconds, then there is
no decimal point.
If this SysTime's time zone is LocalTime, then TZ is empty. If the time
zone is UTC, then it is "Z". Otherwise, it is the offset from UTC
(e.g. +1:00 or -7:00). Note that the offset from UTC is $(I not) enough
to uniquely identify the time zone.
Time zone offsets will be in the form +HH:MM or -HH:MM.
Examples:
--------------------
assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toSimpleString() ==
"2010-Jul-04 07:06:12");
assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0), FracSec.from!"msecs"(24)).toSimpleString() ==
"1998-Dec-25 02:15:00.024");
assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toSimpleString() ==
"0000-Jan-05 23:09:59");
assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), FracSec.from!"hnsecs"(520920)).toSimpleString() ==
"-0004-Jan-05 00:00:02.052092");
--------------------
+/
string toSimpleString() const nothrow
{
try
{
immutable adjustedTime = adjTime;
long hnsecs = adjustedTime;
auto days = splitUnitsFromHNSecs!"days"(hnsecs) + 1;
if(hnsecs < 0)
{
hnsecs += convert!("hours", "hnsecs")(24);
--days;
}
auto hour = splitUnitsFromHNSecs!"hours"(hnsecs);
auto minute = splitUnitsFromHNSecs!"minutes"(hnsecs);
auto second = splitUnitsFromHNSecs!"seconds"(hnsecs);
auto dateTime = DateTime(Date(cast(int)days), TimeOfDay(cast(int)hour, cast(int)minute, cast(int)second));
auto fracSecStr = fracSecToISOString(cast(int)hnsecs);
if(_timezone.get is LocalTime())
return dateTime.toSimpleString() ~ fracSecToISOString(cast(int)hnsecs);
if(_timezone.get is UTC())
return dateTime.toSimpleString() ~ fracSecToISOString(cast(int)hnsecs) ~ "Z";
immutable utcOffset = cast(int)convert!("hnsecs", "minutes")(stdTime - adjustedTime);
return dateTime.toSimpleString() ~ fracSecToISOString(cast(int)hnsecs) ~ SimpleTimeZone.toISOString(utcOffset);
}
catch(Exception e)
assert(0, "format() threw.");
}
unittest
{
//Test A.D.
assertPred!"=="(SysTime(DateTime.init, UTC()).toString(), "0001-Jan-01 00:00:00Z");
assertPred!"=="(SysTime(DateTime(1, 1, 1, 0, 0, 0), FracSec.from!"hnsecs"(1), UTC()).toString(), "0001-Jan-01 00:00:00.0000001Z");
assertPred!"=="(SysTime(DateTime(9, 12, 4, 0, 0, 0)).toSimpleString(), "0009-Dec-04 00:00:00");
assertPred!"=="(SysTime(DateTime(99, 12, 4, 5, 6, 12)).toSimpleString(), "0099-Dec-04 05:06:12");
assertPred!"=="(SysTime(DateTime(999, 12, 4, 13, 44, 59)).toSimpleString(), "0999-Dec-04 13:44:59");
assertPred!"=="(SysTime(DateTime(9999, 7, 4, 23, 59, 59)).toSimpleString(), "9999-Jul-04 23:59:59");
assertPred!"=="(SysTime(DateTime(10000, 10, 20, 1, 1, 1)).toSimpleString(), "+10000-Oct-20 01:01:01");
assertPred!"=="(SysTime(DateTime(9, 12, 4, 0, 0, 0), FracSec.from!"msecs"(42)).toSimpleString(), "0009-Dec-04 00:00:00.042");
assertPred!"=="(SysTime(DateTime(99, 12, 4, 5, 6, 12), FracSec.from!"msecs"(100)).toSimpleString(), "0099-Dec-04 05:06:12.1");
assertPred!"=="(SysTime(DateTime(999, 12, 4, 13, 44, 59), FracSec.from!"usecs"(45020)).toSimpleString(), "0999-Dec-04 13:44:59.04502");
assertPred!"=="(SysTime(DateTime(9999, 7, 4, 23, 59, 59), FracSec.from!"hnsecs"(12)).toSimpleString(), "9999-Jul-04 23:59:59.0000012");
assertPred!"=="(SysTime(DateTime(10000, 10, 20, 1, 1, 1), FracSec.from!"hnsecs"(507890)).toSimpleString(), "+10000-Oct-20 01:01:01.050789");
//Test B.C.
assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(9_999_999), UTC()).toSimpleString(), "0000-Dec-31 23:59:59.9999999Z");
assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), FracSec.from!"hnsecs"(1), UTC()).toSimpleString(), "0000-Dec-31 23:59:59.0000001Z");
assertPred!"=="(SysTime(DateTime(0, 12, 31, 23, 59, 59), UTC()).toSimpleString(), "0000-Dec-31 23:59:59Z");
assertPred!"=="(SysTime(DateTime(0, 12, 4, 0, 12, 4)).toSimpleString(), "0000-Dec-04 00:12:04");
assertPred!"=="(SysTime(DateTime(-9, 12, 4, 0, 0, 0)).toSimpleString(), "-0009-Dec-04 00:00:00");
assertPred!"=="(SysTime(DateTime(-99, 12, 4, 5, 6, 12)).toSimpleString(), "-0099-Dec-04 05:06:12");
assertPred!"=="(SysTime(DateTime(-999, 12, 4, 13, 44, 59)).toSimpleString(), "-0999-Dec-04 13:44:59");
assertPred!"=="(SysTime(DateTime(-9999, 7, 4, 23, 59, 59)).toSimpleString(), "-9999-Jul-04 23:59:59");
assertPred!"=="(SysTime(DateTime(-10000, 10, 20, 1, 1, 1)).toSimpleString(), "-10000-Oct-20 01:01:01");
assertPred!"=="(SysTime(DateTime(0, 12, 4, 0, 0, 0), FracSec.from!"msecs"(7)).toSimpleString(), "0000-Dec-04 00:00:00.007");
assertPred!"=="(SysTime(DateTime(-9, 12, 4, 0, 0, 0), FracSec.from!"msecs"(42)).toSimpleString(), "-0009-Dec-04 00:00:00.042");
assertPred!"=="(SysTime(DateTime(-99, 12, 4, 5, 6, 12), FracSec.from!"msecs"(100)).toSimpleString(), "-0099-Dec-04 05:06:12.1");
assertPred!"=="(SysTime(DateTime(-999, 12, 4, 13, 44, 59), FracSec.from!"usecs"(45020)).toSimpleString(), "-0999-Dec-04 13:44:59.04502");
assertPred!"=="(SysTime(DateTime(-9999, 7, 4, 23, 59, 59), FracSec.from!"hnsecs"(12)).toSimpleString(), "-9999-Jul-04 23:59:59.0000012");
assertPred!"=="(SysTime(DateTime(-10000, 10, 20, 1, 1, 1), FracSec.from!"hnsecs"(507890)).toSimpleString(), "-10000-Oct-20 01:01:01.050789");
const cst = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
//immutable ist = SysTime(DateTime(1999, 7, 6, 12, 30, 33));
static assert(__traits(compiles, cast(TimeOfDay)cst));
//static assert(__traits(compiles, cast(TimeOfDay)ist));
//Verify Examples.
assert(SysTime(DateTime(2010, 7, 4, 7, 6, 12)).toSimpleString() == "2010-Jul-04 07:06:12");
assert(SysTime(DateTime(1998, 12, 25, 2, 15, 0), FracSec.from!"msecs"(24)).toSimpleString() == "1998-Dec-25 02:15:00.024");
assert(SysTime(DateTime(0, 1, 5, 23, 9, 59)).toSimpleString() == "0000-Jan-05 23:09:59");
assert(SysTime(DateTime(-4, 1, 5, 0, 0, 2), FracSec.from!"hnsecs"(520920)).toSimpleString() == "-0004-Jan-05 00:00:02.052092");
}
/+
Converts this SysTime to a string.
+/
//Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
//have versions of toString() with extra modifiers, so we define one version
//with modifiers and one without.
string toString()
{
return toSimpleString();
}
/++
Converts this SysTime to a string.
+/
//Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
//have versions of toString() with extra modifiers, so we define one version
//with modifiers and one without.
string toString() const nothrow
{
return toSimpleString();
}
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));
static assert(__traits(compiles, st.toString()));
static assert(__traits(compiles, cst.toString()));
//static assert(__traits(compiles, ist.toString()));
}
/++
Creates a SysTime from a string with the format YYYYMMDDTHHMMSS.FFFFFFFTZ
(where F is fractional seconds is time zone). Whitespace is stripped from
the given string.
The exact format is exactly as described in toISOString() except that
trailing zeroes are permitted - including having fractional seconds with
all zeroes. However, a decimal point with nothing following it is invalid.
If there is no time zone in the string, then LocalTime is used. If the
time zone is "Z", then UTC is used. Otherwise, a SimpleTimeZone which
corresponds to the given offset from UTC is used. If you wish the
returned SysTime to be a particular time zone, then pass in that time
zone and the SysTime to be returned will be converted to that time zone
(though it will still be read in as whatever time zone is in its string).
The accepted formats for time zone offsets are +H, -H, +HH, -HH, +H:MM,
-H:MM, +HH:MM, and -HH:MM.
Params:
isoString = A string formatted in the ISO format for dates and times.
tz = The time zone to convert the given time to (no conversion
occurs if null).
Throws:
DateTimeException if the given string is not in the ISO format or if
the resulting SysTime would not be valid.
Examples:
--------------------
assert(SysTime.fromISOString("20100704T070612") ==
SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
assert(SysTime.fromISOString("19981225T021500.007") ==
SysTime(DateTime(1998, 12, 25, 2, 15, 0), FracSec.from!"msecs"(7)));
assert(SysTime.fromISOString("00000105T230959.00002") ==
SysTime(DateTime(0, 1, 5, 23, 9, 59), FracSec.from!"usecs"(20)));
assert(SysTime.fromISOString("-00040105T000002") ==
SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
assert(SysTime.fromISOString(" 20100704T070612 ") ==
SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
assert(SysTime.fromISOString("20100704T070612Z") ==
SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
assert(SysTime.fromISOString("20100704T070612-8:00") ==
SysTime(DateTime(2010, 7, 4, 7, 6, 12), new SimpleTimeZone(-480)));
assert(SysTime.fromISOString("20100704T070612+8:00") ==
SysTime(DateTime(2010, 7, 3, 7, 6, 12), new SimpleTimeZone(480)));
--------------------
+/
static SysTime fromISOString(S)(in S isoString, immutable TimeZone tz = null)
if(isSomeString!S)
{
auto dstr = to!dstring(strip(isoString));
immutable skipFirst = dstr.startsWith("+", "-") != 0;
auto found = (skipFirst ? dstr[1..$] : dstr).find(".", "Z", "+", "-");
auto dateTimeStr = dstr[0 .. $ - found[0].length];
dstring fracSecStr;
dstring zoneStr;
if(found[1] != 0)
{
if(found[1] == 1)
{
auto foundTZ = found[0].find("Z", "+", "-");
if(foundTZ[1] != 0)
{
fracSecStr = found[0][0 .. $ - foundTZ[0].length];
zoneStr = foundTZ[0];
}
else
fracSecStr = found[0];
}
else
zoneStr = found[0];
}
try
{
auto dateTime = DateTime.fromISOString(dateTimeStr);
auto fracSec = fracSecFromISOString(fracSecStr);
DTRebindable!(immutable TimeZone) parsedZone;
if(zoneStr.empty)
parsedZone = LocalTime();
else if(zoneStr == "Z")
parsedZone = UTC();
else
parsedZone = SimpleTimeZone.fromISOString(zoneStr);
auto retval = SysTime(dateTime, fracSec, parsedZone.get);
if(tz !is null)
retval.timezone = tz;
return retval;
}
catch(DateTimeException dte)
throw new DateTimeException(format("Invalid ISO String: %s", isoString));
}
unittest
{
assertThrown!DateTimeException(SysTime.fromISOString(""));
assertThrown!DateTimeException(SysTime.fromISOString("20100704000000"));
assertThrown!DateTimeException(SysTime.fromISOString("20100704 000000"));
assertThrown!DateTimeException(SysTime.fromISOString("20100704t000000"));
assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000."));
assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000.A"));
assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000.Z"));
assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000.00000000"));
assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000.00000000"));
assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000+"));
assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000-"));
assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000:"));
assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000-:"));
assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000+:"));
assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000-1:"));
assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000+1:"));
assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000+1:0"));
assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000-24.00"));
assertThrown!DateTimeException(SysTime.fromISOString("20100704T000000+24.00"));
assertThrown!DateTimeException(SysTime.fromISOString("2010-07-0400:00:00"));
assertThrown!DateTimeException(SysTime.fromISOString("2010-07-04 00:00:00"));
assertThrown!DateTimeException(SysTime.fromISOString("2010-07-04t00:00:00"));
assertThrown!DateTimeException(SysTime.fromISOString("2010-07-04T00:00:00."));
assertThrown!DateTimeException(SysTime.fromISOString("2010-Jul-0400:00:00"));
assertThrown!DateTimeException(SysTime.fromISOString("2010-Jul-04 00:00:00"));
assertThrown!DateTimeException(SysTime.fromISOString("2010-Jul-04t00:00:00"));
assertThrown!DateTimeException(SysTime.fromISOString("2010-Jul-04T00:00:00"));
assertThrown!DateTimeException(SysTime.fromISOString("2010-Jul-04 00:00:00."));
assertThrown!DateTimeException(SysTime.fromISOString("2010-12-22T172201"));
assertThrown!DateTimeException(SysTime.fromISOString("2010-Dec-22 17:22:01"));
assertPred!"=="(SysTime.fromISOString("20101222T172201"), SysTime(DateTime(2010, 12, 22, 17, 22, 01)));
assertPred!"=="(SysTime.fromISOString("19990706T123033"), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
assertPred!"=="(SysTime.fromISOString("-19990706T123033"), SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
assertPred!"=="(SysTime.fromISOString("+019990706T123033"), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
assertPred!"=="(SysTime.fromISOString("19990706T123033 "), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
assertPred!"=="(SysTime.fromISOString(" 19990706T123033"), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
assertPred!"=="(SysTime.fromISOString(" 19990706T123033 "), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
assertPred!"=="(SysTime.fromISOString("19070707T121212.0"), SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
assertPred!"=="(SysTime.fromISOString("19070707T121212.0000000"), SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
assertPred!"=="(SysTime.fromISOString("19070707T121212.0000001"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"hnsecs"(1)));
assertPred!"=="(SysTime.fromISOString("19070707T121212.000001"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"usecs"(1)));
assertPred!"=="(SysTime.fromISOString("19070707T121212.0000010"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"usecs"(1)));
assertPred!"=="(SysTime.fromISOString("19070707T121212.001"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"msecs"(1)));
assertPred!"=="(SysTime.fromISOString("19070707T121212.0010000"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"msecs"(1)));
assertPred!"=="(SysTime.fromISOString("20101222T172201Z"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), UTC()));
assertPred!"=="(SysTime.fromISOString("20101222T172201-1:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(-60)));
assertPred!"=="(SysTime.fromISOString("20101222T172201-1"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(-60)));
assertPred!"=="(SysTime.fromISOString("20101222T172201-1:30"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(-90)));
assertPred!"=="(SysTime.fromISOString("20101222T172201-8:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(-480)));
assertPred!"=="(SysTime.fromISOString("20101222T172201+1:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(60)));
assertPred!"=="(SysTime.fromISOString("20101222T172201+1"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(60)));
assertPred!"=="(SysTime.fromISOString("20101222T172201+1:30"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(90)));
assertPred!"=="(SysTime.fromISOString("20101222T172201+8:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(480)));
assertPred!"=="(SysTime.fromISOString("20101103T065106.57159Z"), SysTime(DateTime(2010, 11, 3, 6, 51, 6), FracSec.from!"hnsecs"(5715900), UTC()));
assertPred!"=="(SysTime.fromISOString("20101222T172201.23412Z"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(2_341_200), UTC()));
assertPred!"=="(SysTime.fromISOString("20101222T172201.23112-1:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(2_311_200), new SimpleTimeZone(-60)));
assertPred!"=="(SysTime.fromISOString("20101222T172201.45-1"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(4_500_000), new SimpleTimeZone(-60)));
assertPred!"=="(SysTime.fromISOString("20101222T172201.1-1:30"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(1_000_000), new SimpleTimeZone(-90)));
assertPred!"=="(SysTime.fromISOString("20101222T172201.55-8:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(5_500_000), new SimpleTimeZone(-480)));
assertPred!"=="(SysTime.fromISOString("20101222T172201.1234567+1:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(1_234_567), new SimpleTimeZone(60)));
assertPred!"=="(SysTime.fromISOString("20101222T172201.0+1"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(0), new SimpleTimeZone(60)));
assertPred!"=="(SysTime.fromISOString("20101222T172201.0000000+1:30"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(0), new SimpleTimeZone(90)));
assertPred!"=="(SysTime.fromISOString("20101222T172201.45+8:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(4_500_000), new SimpleTimeZone(480)));
//Verify Examples.
assert(SysTime.fromISOString("20100704T070612") == SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
assert(SysTime.fromISOString("19981225T021500.007") == SysTime(DateTime(1998, 12, 25, 2, 15, 0), FracSec.from!"msecs"(7)));
assert(SysTime.fromISOString("00000105T230959.00002") == SysTime(DateTime(0, 1, 5, 23, 9, 59), FracSec.from!"usecs"(20)));
assert(SysTime.fromISOString("-00040105T000002") == SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
assert(SysTime.fromISOString(" 20100704T070612 ") == SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
assert(SysTime.fromISOString("20100704T070612Z") == SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
assert(SysTime.fromISOString("20100704T070612-8:00") == SysTime(DateTime(2010, 7, 4, 7, 6, 12), new SimpleTimeZone(-480)));
assert(SysTime.fromISOString("20100704T070612+8:00") == SysTime(DateTime(2010, 7, 4, 7, 6, 12), new SimpleTimeZone(480)));
}
/++
Creates a SysTime from a string with the format YYYY-MM-DDTHH:MM:SS.FFFFFFFTZ
(where F is fractional seconds is time zone). Whitespace is stripped from the
given string.
The exact format is exactly as described in toISOExtendedString() except
that trailing zeroes are permitted - including having fractional seconds
with all zeroes. However, a decimal point with nothing following it is
invalid.
If there is no time zone in the string, then LocalTime is used. If the
time zone is "Z", then UTC is used. Otherwise, a SimpleTimeZone which
corresponds to the given offset from UTC is used. If you wish the
returned SysTime to be a particular time zone, then pass in that time
zone and the SysTime to be returned will be converted to that time zone
(though it will still be read in as whatever time zone is in its string).
The accepted formats for time zone offsets are +H, -H, +HH, -HH, +H:MM,
-H:MM, +HH:MM, and -HH:MM.
Params:
isoString = A string formatted in the ISO Extended format for dates
and times.
tz = The time zone to convert the given time to (no conversion
occurs if null).
Throws:
DateTimeException if the given string is not in the ISO format or if
the resulting SysTime would not be valid.
Examples:
--------------------
assert(SysTime.fromISOExtendedString("2010-07-04T07:06:12") ==
SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
assert(SysTime.fromISOExtendedString("1998-12-25T02:15:00.007") ==
SysTime(DateTime(1998, 12, 25, 2, 15, 0), FracSec.from!"msecs"(7)));
assert(SysTime.fromISOExtendedString("0000-01-05T23:09:59.00002") ==
SysTime(DateTime(0, 1, 5, 23, 9, 59), FracSec.from!"usecs"(20)));
assert(SysTime.fromISOExtendedString("-0004-01-05T00:00:02") ==
SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
assert(SysTime.fromISOExtendedString(" 2010-07-04T07:06:12 ") ==
SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
assert(SysTime.fromISOExtendedString("2010-07-04T07:06:12Z") ==
SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
assert(SysTime.fromISOExtendedString("2010-07-04T07:06:12-8:00") ==
SysTime(DateTime(2010, 7, 4, 7, 6, 12), new SimpleTimeZone(-480)));
assert(SysTime.fromISOExtendedString("2010-07-04T07:06:12+8:00") ==
SysTime(DateTime(2010, 7, 4, 7, 6, 12), new SimpleTimeZone(480)));
--------------------
+/
static SysTime fromISOExtendedString(S)(in S isoExtString, immutable TimeZone tz = null)
if(isSomeString!(S))
{
auto dstr = to!dstring(strip(isoExtString));
auto tIndex = dstr.indexOf("T");
enforce(tIndex != -1, new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString)));
auto found = dstr[tIndex + 1 .. $].find(".", "Z", "+", "-");
auto dateTimeStr = dstr[0 .. $ - found[0].length];
dstring fracSecStr;
dstring zoneStr;
if(found[1] != 0)
{
if(found[1] == 1)
{
auto foundTZ = found[0].find("Z", "+", "-");
if(foundTZ[1] != 0)
{
fracSecStr = found[0][0 .. $ - foundTZ[0].length];
zoneStr = foundTZ[0];
}
else
fracSecStr = found[0];
}
else
zoneStr = found[0];
}
try
{
auto dateTime = DateTime.fromISOExtendedString(dateTimeStr);
auto fracSec = fracSecFromISOString(fracSecStr);
DTRebindable!(immutable TimeZone) parsedZone;
if(zoneStr.empty)
parsedZone = LocalTime();
else if(zoneStr == "Z")
parsedZone = UTC();
else
parsedZone = SimpleTimeZone.fromISOString(zoneStr);
auto retval = SysTime(dateTime, fracSec, parsedZone.get);
if(tz !is null)
retval.timezone = tz;
return retval;
}
catch(DateTimeException dte)
throw new DateTimeException(format("Invalid ISO Extended String: %s", isoExtString));
}
unittest
{
assertThrown!DateTimeException(SysTime.fromISOExtendedString(""));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("20100704000000"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("20100704 000000"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("20100704t000000"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("20100704T000000."));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("20100704T000000.0"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("2010-07:0400:00:00"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("2010-07-04 00:00:00"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("2010-07-04 00:00:00"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("2010-07-04t00:00:00"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("2010-07-04T00:00:00."));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("2010-07-04T00:00:00.A"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("2010-07-04T00:00:00.Z"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("2010-07-04T00:00:00.00000000"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("2010-07-04T00:00:00.00000000"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("2010-07-04T00:00:00+"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("2010-07-04T00:00:00-"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("2010-07-04T00:00:00:"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("2010-07-04T00:00:00-:"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("2010-07-04T00:00:00+:"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("2010-07-04T00:00:00-1:"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("2010-07-04T00:00:00+1:"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("2010-07-04T00:00:00+1:0"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("2010-07-04T00:00:00-24.00"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("2010-07-04T00:00:00+24.00"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("2010-Jul-0400:00:00"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("2010-Jul-04t00:00:00"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("2010-Jul-04 00:00:00."));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("2010-Jul-04 00:00:00.0"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("20101222T172201"));
assertThrown!DateTimeException(SysTime.fromISOExtendedString("2010-Dec-22 17:22:01"));
assertPred!"=="(SysTime.fromISOExtendedString("2010-12-22T17:22:01"), SysTime(DateTime(2010, 12, 22, 17, 22, 01)));
assertPred!"=="(SysTime.fromISOExtendedString("1999-07-06T12:30:33"), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
assertPred!"=="(SysTime.fromISOExtendedString("-1999-07-06T12:30:33"), SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
assertPred!"=="(SysTime.fromISOExtendedString("+01999-07-06T12:30:33"), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
assertPred!"=="(SysTime.fromISOExtendedString("1999-07-06T12:30:33 "), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
assertPred!"=="(SysTime.fromISOExtendedString(" 1999-07-06T12:30:33"), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
assertPred!"=="(SysTime.fromISOExtendedString(" 1999-07-06T12:30:33 "), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
assertPred!"=="(SysTime.fromISOExtendedString("1907-07-07T12:12:12.0"), SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
assertPred!"=="(SysTime.fromISOExtendedString("1907-07-07T12:12:12.0000000"), SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
assertPred!"=="(SysTime.fromISOExtendedString("1907-07-07T12:12:12.0000001"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"hnsecs"(1)));
assertPred!"=="(SysTime.fromISOExtendedString("1907-07-07T12:12:12.000001"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"usecs"(1)));
assertPred!"=="(SysTime.fromISOExtendedString("1907-07-07T12:12:12.0000010"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"usecs"(1)));
assertPred!"=="(SysTime.fromISOExtendedString("1907-07-07T12:12:12.001"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"msecs"(1)));
assertPred!"=="(SysTime.fromISOExtendedString("1907-07-07T12:12:12.0010000"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"msecs"(1)));
assertPred!"=="(SysTime.fromISOExtendedString("2010-12-22T17:22:01Z"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), UTC()));
assertPred!"=="(SysTime.fromISOExtendedString("2010-12-22T17:22:01-1:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(-60)));
assertPred!"=="(SysTime.fromISOExtendedString("2010-12-22T17:22:01-1"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(-60)));
assertPred!"=="(SysTime.fromISOExtendedString("2010-12-22T17:22:01-1:30"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(-90)));
assertPred!"=="(SysTime.fromISOExtendedString("2010-12-22T17:22:01-8:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(-480)));
assertPred!"=="(SysTime.fromISOExtendedString("2010-12-22T17:22:01+1:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(60)));
assertPred!"=="(SysTime.fromISOExtendedString("2010-12-22T17:22:01+1"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(60)));
assertPred!"=="(SysTime.fromISOExtendedString("2010-12-22T17:22:01+1:30"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(90)));
assertPred!"=="(SysTime.fromISOExtendedString("2010-12-22T17:22:01+8:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(480)));
assertPred!"=="(SysTime.fromISOExtendedString("2010-11-03T06:51:06.57159Z"), SysTime(DateTime(2010, 11, 3, 6, 51, 6), FracSec.from!"hnsecs"(5715900), UTC()));
assertPred!"=="(SysTime.fromISOExtendedString("2010-12-22T17:22:01.23412Z"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(2_341_200), UTC()));
assertPred!"=="(SysTime.fromISOExtendedString("2010-12-22T17:22:01.23112-1:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(2_311_200), new SimpleTimeZone(-60)));
assertPred!"=="(SysTime.fromISOExtendedString("2010-12-22T17:22:01.45-1"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(4_500_000), new SimpleTimeZone(-60)));
assertPred!"=="(SysTime.fromISOExtendedString("2010-12-22T17:22:01.1-1:30"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(1_000_000), new SimpleTimeZone(-90)));
assertPred!"=="(SysTime.fromISOExtendedString("2010-12-22T17:22:01.55-8:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(5_500_000), new SimpleTimeZone(-480)));
assertPred!"=="(SysTime.fromISOExtendedString("2010-12-22T17:22:01.1234567+1:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(1_234_567), new SimpleTimeZone(60)));
assertPred!"=="(SysTime.fromISOExtendedString("2010-12-22T17:22:01.0+1"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(0), new SimpleTimeZone(60)));
assertPred!"=="(SysTime.fromISOExtendedString("2010-12-22T17:22:01.0000000+1:30"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(0), new SimpleTimeZone(90)));
assertPred!"=="(SysTime.fromISOExtendedString("2010-12-22T17:22:01.45+8:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(4_500_000), new SimpleTimeZone(480)));
//Verify Examples.
assert(SysTime.fromISOExtendedString("2010-07-04T07:06:12") == SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
assert(SysTime.fromISOExtendedString("1998-12-25T02:15:00.007") == SysTime(DateTime(1998, 12, 25, 2, 15, 0), FracSec.from!"msecs"(7)));
assert(SysTime.fromISOExtendedString("0000-01-05T23:09:59.00002") == SysTime(DateTime(0, 1, 5, 23, 9, 59), FracSec.from!"usecs"(20)));
assert(SysTime.fromISOExtendedString("-0004-01-05T00:00:02") == SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
assert(SysTime.fromISOExtendedString(" 2010-07-04T07:06:12 ") == SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
assert(SysTime.fromISOExtendedString("2010-07-04T07:06:12Z") == SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
assert(SysTime.fromISOExtendedString("2010-07-04T07:06:12-8:00") == SysTime(DateTime(2010, 7, 4, 7, 6, 12), new SimpleTimeZone(-480)));
assert(SysTime.fromISOExtendedString("2010-07-04T07:06:12+8:00") == SysTime(DateTime(2010, 7, 4, 7, 6, 12), new SimpleTimeZone(480)));
}
/++
Creates a SysTime from a string with the format YYYY-MM-DD HH:MM:SS.FFFFFFFTZ
(where F is fractional seconds is time zone). Whitespace is stripped from the
given string.
The exact format is exactly as described in toSimpleString() except that
trailing zeroes are permitted - including having fractional seconds with
all zeroes. However, a decimal point with nothing following it is invalid.
If there is no time zone in the string, then LocalTime is used. If the
time zone is "Z", then UTC is used. Otherwise, a SimpleTimeZone which
corresponds to the given offset from UTC is used. If you wish the
returned SysTime to be a particular time zone, then pass in that time
zone and the SysTime to be returned will be converted to that time zone
(though it will still be read in as whatever time zone is in its string).
The accepted formats for time zone offsets are +H, -H, +HH, -HH, +H:MM,
-H:MM, +HH:MM, and -HH:MM.
Params:
simpleString = A string formatted in the way that toSimpleString()
formats dates and times.
tz = The time zone to convert the given time to (no
conversion occurs if null).
Throws:
DateTimeException if the given string is not in the ISO format or if
the resulting SysTime would not be valid.
Examples:
--------------------
assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12") ==
SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
assert(SysTime.fromSimpleString("1998-Dec-25 02:15:00.007") ==
SysTime(DateTime(1998, 12, 25, 2, 15, 0), FracSec.from!"msecs"(7)));
assert(SysTime.fromSimpleString("0000-Jan-05 23:09:59.00002") ==
SysTime(DateTime(0, 1, 5, 23, 9, 59), FracSec.from!"usecs"(20)));
assert(SysTime.fromSimpleString("-0004-Jan-05 00:00:02") ==
SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
assert(SysTime.fromSimpleString(" 2010-Jul-04 07:06:12 ") ==
SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12Z") ==
SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12-8:00") ==
SysTime(DateTime(2010, 7, 4, 7, 6, 12), new SimpleTimeZone(-480)));
assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12+8:00") ==
SysTime(DateTime(2010, 7, 4, 7, 6, 12), new SimpleTimeZone(480)));
--------------------
+/
static SysTime fromSimpleString(S)(in S simpleString, immutable TimeZone tz = null)
if(isSomeString!(S))
{
auto dstr = to!dstring(strip(simpleString));
auto spaceIndex = dstr.indexOf(" ");
enforce(spaceIndex != -1, new DateTimeException(format("Invalid Simple String: %s", simpleString)));
auto found = dstr[spaceIndex + 1 .. $].find(".", "Z", "+", "-");
auto dateTimeStr = dstr[0 .. $ - found[0].length];
dstring fracSecStr;
dstring zoneStr;
if(found[1] != 0)
{
if(found[1] == 1)
{
auto foundTZ = found[0].find("Z", "+", "-");
if(foundTZ[1] != 0)
{
fracSecStr = found[0][0 .. $ - foundTZ[0].length];
zoneStr = foundTZ[0];
}
else
fracSecStr = found[0];
}
else
zoneStr = found[0];
}
try
{
auto dateTime = DateTime.fromSimpleString(dateTimeStr);
auto fracSec = fracSecFromISOString(fracSecStr);
DTRebindable!(immutable TimeZone) parsedZone;
if(zoneStr.empty)
parsedZone = LocalTime();
else if(zoneStr == "Z")
parsedZone = UTC();
else
parsedZone = SimpleTimeZone.fromISOString(zoneStr);
auto retval = SysTime(dateTime, fracSec, parsedZone.get);
if(tz !is null)
retval.timezone = tz;
return retval;
}
catch(DateTimeException dte)
throw new DateTimeException(format("Invalid Simple String: %s", simpleString));
}
unittest
{
assertThrown!DateTimeException(SysTime.fromSimpleString(""));
assertThrown!DateTimeException(SysTime.fromSimpleString("20100704000000"));
assertThrown!DateTimeException(SysTime.fromSimpleString("20100704 000000"));
assertThrown!DateTimeException(SysTime.fromSimpleString("20100704t000000"));
assertThrown!DateTimeException(SysTime.fromSimpleString("20100704T000000."));
assertThrown!DateTimeException(SysTime.fromSimpleString("20100704T000000.0"));
assertThrown!DateTimeException(SysTime.fromSimpleString("2010-07-0400:00:00"));
assertThrown!DateTimeException(SysTime.fromSimpleString("2010-07-04 00:00:00"));
assertThrown!DateTimeException(SysTime.fromSimpleString("2010-07-04t00:00:00"));
assertThrown!DateTimeException(SysTime.fromSimpleString("2010-07-04T00:00:00."));
assertThrown!DateTimeException(SysTime.fromSimpleString("2010-07-04T00:00:00.0"));
assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-0400:00:00"));
assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04t00:00:00"));
assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04T00:00:00"));
assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00."));
assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00.A"));
assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00.Z"));
assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00.00000000"));
assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00.00000000"));
assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00+"));
assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00-"));
assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00:"));
assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00-:"));
assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00+:"));
assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00-1:"));
assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00+1:"));
assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00+1:0"));
assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00-24.00"));
assertThrown!DateTimeException(SysTime.fromSimpleString("2010-Jul-04 00:00:00+24.00"));
assertThrown!DateTimeException(SysTime.fromSimpleString("20101222T172201"));
assertThrown!DateTimeException(SysTime.fromSimpleString("2010-12-22T172201"));
assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01"), SysTime(DateTime(2010, 12, 22, 17, 22, 01)));
assertPred!"=="(SysTime.fromSimpleString("1999-Jul-06 12:30:33"), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
assertPred!"=="(SysTime.fromSimpleString("-1999-Jul-06 12:30:33"), SysTime(DateTime(-1999, 7, 6, 12, 30, 33)));
assertPred!"=="(SysTime.fromSimpleString("+01999-Jul-06 12:30:33"), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
assertPred!"=="(SysTime.fromSimpleString("1999-Jul-06 12:30:33 "), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
assertPred!"=="(SysTime.fromSimpleString(" 1999-Jul-06 12:30:33"), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
assertPred!"=="(SysTime.fromSimpleString(" 1999-Jul-06 12:30:33 "), SysTime(DateTime(1999, 7, 6, 12, 30, 33)));
assertPred!"=="(SysTime.fromSimpleString("1907-Jul-07 12:12:12.0"), SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
assertPred!"=="(SysTime.fromSimpleString("1907-Jul-07 12:12:12.0000000"), SysTime(DateTime(1907, 07, 07, 12, 12, 12)));
assertPred!"=="(SysTime.fromSimpleString("1907-Jul-07 12:12:12.0000001"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"hnsecs"(1)));
assertPred!"=="(SysTime.fromSimpleString("1907-Jul-07 12:12:12.000001"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"usecs"(1)));
assertPred!"=="(SysTime.fromSimpleString("1907-Jul-07 12:12:12.0000010"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"usecs"(1)));
assertPred!"=="(SysTime.fromSimpleString("1907-Jul-07 12:12:12.001"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"msecs"(1)));
assertPred!"=="(SysTime.fromSimpleString("1907-Jul-07 12:12:12.0010000"), SysTime(DateTime(1907, 07, 07, 12, 12, 12), FracSec.from!"msecs"(1)));
assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01Z"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), UTC()));
assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01-1:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(-60)));
assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01-1"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(-60)));
assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01-1:30"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(-90)));
assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01-8:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(-480)));
assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01+1:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(60)));
assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01+1"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(60)));
assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01+1:30"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(90)));
assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01+8:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), new SimpleTimeZone(480)));
assertPred!"=="(SysTime.fromSimpleString("2010-Nov-03 06:51:06.57159Z"), SysTime(DateTime(2010, 11, 3, 6, 51, 6), FracSec.from!"hnsecs"(5715900), UTC()));
assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01.23412Z"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(2_341_200), UTC()));
assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01.23112-1:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(2_311_200), new SimpleTimeZone(-60)));
assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01.45-1"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(4_500_000), new SimpleTimeZone(-60)));
assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01.1-1:30"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(1_000_000), new SimpleTimeZone(-90)));
assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01.55-8:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(5_500_000), new SimpleTimeZone(-480)));
assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01.1234567+1:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(1_234_567), new SimpleTimeZone(60)));
assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01.0+1"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(0), new SimpleTimeZone(60)));
assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01.0000000+1:30"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(0), new SimpleTimeZone(90)));
assertPred!"=="(SysTime.fromSimpleString("2010-Dec-22 17:22:01.45+8:00"), SysTime(DateTime(2010, 12, 22, 17, 22, 01), FracSec.from!"hnsecs"(4_500_000), new SimpleTimeZone(480)));
//Verify Examples.
assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12") == SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
assert(SysTime.fromSimpleString("1998-Dec-25 02:15:00.007") == SysTime(DateTime(1998, 12, 25, 2, 15, 0), FracSec.from!"msecs"(7)));
assert(SysTime.fromSimpleString("0000-Jan-05 23:09:59.00002") == SysTime(DateTime(0, 1, 5, 23, 9, 59), FracSec.from!"usecs"(20)));
assert(SysTime.fromSimpleString("-0004-Jan-05 00:00:02") == SysTime(DateTime(-4, 1, 5, 0, 0, 2)));
assert(SysTime.fromSimpleString(" 2010-Jul-04 07:06:12 ") == SysTime(DateTime(2010, 7, 4, 7, 6, 12)));
assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12Z") == SysTime(DateTime(2010, 7, 4, 7, 6, 12), UTC()));
assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12-8:00") == SysTime(DateTime(2010, 7, 4, 7, 6, 12), new SimpleTimeZone(-480)));
assert(SysTime.fromSimpleString("2010-Jul-04 07:06:12+8:00") == SysTime(DateTime(2010, 7, 4, 7, 6, 12), new SimpleTimeZone(480)));
}
//TODO Add function which takes a user-specified time format and produces a SysTime
//TODO Add function which takes pretty much any time-string and produces a SysTime.
// Obviously, it will be less efficient, and it probably won't manage _every_
// possible date format, but a smart conversion function would be nice.
/++
Returns the SysTime farthest in the past which is representable by SysTime.
The SysTime which is returned is in UTC.
+/
@property static SysTime min() pure nothrow
{
return SysTime(long.min, UTC());
}
unittest
{
assert(SysTime.min.year < 0);
assert(SysTime.min < SysTime.max);
}
/++
Returns the SysTime farthest in the future which is representable by SysTime.
The SysTime which is returned is in UTC.
+/
@property static SysTime max() pure nothrow
{
return SysTime(long.max, UTC());
}
unittest
{
assert(SysTime.max.year > 0);
assert(SysTime.max > SysTime.min);
}
private:
/++
Returns stdTime converted to SysTime's time zone.
+/
@property long adjTime() const nothrow
{
return _timezone.utcToTZ(_stdTime);
}
/++
Converts the given hnsecs from SysTime's time zone to std time.
+/
@property void adjTime(long adjTime) nothrow
{
_stdTime = _timezone.tzToUTC(adjTime);
}
//Commented out due to bug http://d.puremagic.com/issues/show_bug.cgi?id=5058
/+
invariant()
{
assert(_timezone.get !is null, "Invariant Failure: timezone is null. Were you foolish enough to use SysTime.init? (since timezone for SysTime.init can't be set at compile time).");
}
+/
long _stdTime;
DTRebindable!(immutable TimeZone) _timezone;
}
//==============================================================================
// Section with intervals.
//==============================================================================
/++
Represents an interval of time.
An $(D Interval) has a begin point and an end point. The interval of time is
therefore the time starting at the begin point up to, but not including, the
end point. e.g.
$(TABLE
$(TR $(TD [January 5th, 2010 - March 10th, 2010$(RPAREN)))
$(TR $(TD [05:00:30 - 12:00:00$(RPAREN)))
$(TR $(TD [1982-01-04T08:59:00 - 2010-07-04T12:00:00$(RPAREN)))
)
A range can be obtained from an $(D Interval), allowing you to iterate over
that interval, with the exact time points which are iterated over depending
on the function which generates the range.
+/
struct Interval(TP)
{
public:
/++
Params:
begin = The time point which begins the interval.
end = The time point which ends (but is not included in) the interval.
Throws:
DateTimeException if end is before begin.
Examples:
--------------------
Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
--------------------
+/
this(U)(in TP begin, in U end) pure
if(is(Unqual!TP == Unqual!U))
{
if(!_valid(begin, end))
throw new DateTimeException("Arguments would result in an invalid Interval.");
_begin = cast(TP)begin;
_end = cast(TP)end;
}
/++
Params:
begin = The time point which begins the interval.
duration = The duration from the begin point to the end point.
Throws:
DateTimeException if the resulting end is before begin.
Examples:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Dur.years(3)) == Interval!Date(Date(1996, 1, 2), Date(1999, 1, 2)));
--------------------
+/
this(D)(in TP begin, in D duration) pure
if(__traits(compiles, begin + duration))
{
_begin = cast(TP)begin;
_end = begin + duration;
if(!_valid(_begin, _end))
throw new DateTimeException("Arguments would result in an invalid Interval.");
}
/++
Params:
rhs = The Interval to assign to this one.
+/
/+ref+/ Interval opAssign(const ref Interval rhs) pure nothrow
{
_begin = cast(TP)rhs._begin;
_end = cast(TP)rhs._end;
return this;
}
/++
Params:
rhs = The Interval to assign to this one.
+/
/+ref+/ Interval opAssign(Interval rhs) pure nothrow
{
_begin = cast(TP)rhs._begin;
_end = cast(TP)rhs._end;
return this;
}
/++
The begin point of the interval. It is included in the interval.
Examples:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).begin == Date(1996, 1, 2));
--------------------
+/
@property TP begin() const pure nothrow
{
return cast(TP)_begin;
}
/++
The begin point of the interval. It is included in the interval.
Params:
timePoint = The time point to set begin to.
Throws:
DateTimeException if the resulting interval would be invalid.
+/
@property void begin(TP timePoint) pure
{
if(!_valid(timePoint, _end))
throw new DateTimeException("Arguments would result in an invalid Interval.");
_begin = timePoint;
}
/++
The end point of the interval. It is excluded from the interval.
Examples:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).end == Date(2012, 3, 1));
--------------------
+/
@property TP end() const pure nothrow
{
return cast(TP)_end;
}
/++
The end point of the interval. It is excluded from the interval.
Params:
timePoint = The time point to set end to.
Throws:
DateTimeException if the resulting interval would be invalid.
+/
@property void end(TP timePoint) pure
{
if(!_valid(_begin, timePoint))
throw new DateTimeException("Arguments would result in an invalid Interval.");
_end = timePoint;
}
/++
Returns the duration between begin and end.
Examples:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).length == dur!"days"(5903));
--------------------
+/
@property typeof(end - begin) length() const pure nothrow
{
return _end - _begin;
}
/++
Whether the interval's length is 0, that is, whether begin == end.
Examples:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(1996, 1, 2)).empty);
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).empty);
--------------------
+/
@property bool empty() const pure nothrow
{
return _begin == _end;
}
/++
Whether the given time point is within this interval.
Params:
timePoint = The time point to check for inclusion in this interval.
Throws:
DateTimeException if empty is true.
Examples:
--------------------
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Date(1994, 12, 24)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Date(2000, 1, 5)));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Date(2012, 3, 1)));
--------------------
+/
bool contains(in TP timePoint) const pure
{
_enforceNotEmpty();
return timePoint >= _begin && timePoint < _end;
}
/++
Whether the given interval is completely within this interval.
Params:
interval = The interval to check for inclusion in this interval.
Throws:
DateTimeException if either interval is empty.
Examples:
--------------------
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
--------------------
+/
bool contains(in Interval interval) const pure
{
_enforceNotEmpty();
interval._enforceNotEmpty();
return interval._begin >= _begin &&
interval._begin < _end &&
interval._end <= _end;
}
/++
Whether the given interval is completely within this interval.
Always returns false (unless this interval is empty), because an interval
going to positive infinity can never be contained in a finite interval.
Params:
interval = The interval to check for inclusion in this interval.
Throws:
DateTimeException if this interval is empty.
Examples:
--------------------
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(PosInfInterval!Date(Date(1999, 5, 4))));
--------------------
+/
bool contains(in PosInfInterval!TP interval) const pure
{
_enforceNotEmpty();
return false;
}
/++
Whether the given interval is completely within this interval.
Always returns false (unless this interval is empty), because an interval
begging at negative infinity can never be contained in a finite interval.
Params:
interval = The interval to check for inclusion in this interval.
Throws:
DateTimeException if this interval is empty.
Examples:
--------------------
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(NegInfInterval!Date(Date(1996, 5, 4))));
--------------------
+/
bool contains(in NegInfInterval!TP interval) const pure
{
_enforceNotEmpty();
return false;
}
/++
Whether this interval is before the given time point.
Params:
timePoint = The time point to check whether this interval is before it.
Throws:
DateTimeException if empty is true.
Examples:
--------------------
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Date(1994, 12, 24)));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Date(2000, 1, 5)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Date(2012, 3, 1)));
--------------------
+/
bool isBefore(in TP timePoint) const pure
{
_enforceNotEmpty();
return _end <= timePoint;
}
/++
Whether this interval is before the given interval and does not intersect
with it.
Params:
interval = The interval to check for against this interval.
Throws:
DateTimeException if either interval is empty.
Examples:
--------------------
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Interval!Date(Date(2012, 3, 1), Date(2013, 5, 1))));
--------------------
+/
bool isBefore(in Interval interval) const pure
{
_enforceNotEmpty();
interval._enforceNotEmpty();
return _end <= interval._begin;
}
/++
Whether this interval is before the given interval and does not intersect
with it.
Params:
interval = The interval to check for against this interval.
Throws:
DateTimeException if this interval is empty.
Examples:
--------------------
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(PosInfInterval!Date(Date(1999, 5, 4))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(PosInfInterval!Date(Date(2013, 3, 7))));
--------------------
+/
bool isBefore(in PosInfInterval!TP interval) const pure
{
_enforceNotEmpty();
return _end <= interval._begin;
}
/++
Whether this interval is before the given interval and does not intersect
with it.
Always returns false (unless this interval is empty) because a finite
interval can never be before an interval beginning at negative infinity.
Params:
interval = The interval to check for against this interval.
Throws:
DateTimeException if this interval is empty.
Examples:
--------------------
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(NegInfInterval!Date(Date(1996, 5, 4))));
--------------------
+/
bool isBefore(in NegInfInterval!TP interval) const pure
{
_enforceNotEmpty();
return false;
}
/++
Whether this interval is after the given time point.
Params:
timePoint = The time point to check whether this interval is after it.
Throws:
DateTimeException if empty is true.
Examples:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Date(1994, 12, 24)));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Date(2000, 1, 5)));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Date(2012, 3, 1)));
--------------------
+/
bool isAfter(in TP timePoint) const pure
{
_enforceNotEmpty();
return timePoint < _begin;
}
/++
Whether this interval is after the given interval and does not intersect
with it.
Params:
interval = The interval to check against this interval.
Throws:
DateTimeException if either interval is empty.
Examples:
--------------------
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
--------------------
+/
bool isAfter(in Interval interval) const pure
{
_enforceNotEmpty();
interval._enforceNotEmpty();
return _begin >= interval._end;
}
/++
Whether this interval is after the given interval and does not intersect
with it.
Always returns false (unless this interval is empty) because a finite
interval can never be after an interval going to positive infinity.
Params:
interval = The interval to check against this interval.
Throws:
DateTimeException if this interval is empty.
Examples:
--------------------
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(PosInfInterval!Date(Date(1999, 5, 4))));
--------------------
+/
bool isAfter(in PosInfInterval!TP interval) const pure
{
_enforceNotEmpty();
return false;
}
/++
Whether this interval is after the given interval and does not intersect
with it.
Params:
interval = The interval to check against this interval.
Throws:
DateTimeException if this interval is empty.
Examples:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(NegInfInterval!Date(Date(1996, 1, 2))));
--------------------
+/
bool isAfter(in NegInfInterval!TP interval) const pure
{
_enforceNotEmpty();
return _begin >= interval._end;
}
/++
Whether the given interval overlaps with this interval.
Params:
interval = The interval to check for intersection with this interval.
Throws:
DateTimeException if either interval is empty.
Examples:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
--------------------
+/
bool intersects(in Interval interval) const pure
{
_enforceNotEmpty();
interval._enforceNotEmpty();
return interval._begin < _end && interval._end > _begin;
}
/++
Whether the given interval overlaps with this interval.
Params:
interval = The interval to check for intersection with this interval.
Throws:
DateTimeException if this interval is empty.
Examples:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(PosInfInterval!Date(Date(1999, 5, 4))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(PosInfInterval!Date(Date(2012, 3, 1))));
--------------------
+/
bool intersects(in PosInfInterval!TP interval) const pure
{
_enforceNotEmpty();
return _end > interval._begin;
}
/++
Whether the given interval overlaps with this interval.
Params:
interval = The interval to check for intersection with this interval.
Throws:
DateTimeException if this interval is empty.
Examples:
--------------------
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(NegInfInterval!Date(Date(1996, 1, 2))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(NegInfInterval!Date(Date(2000, 1, 2))));
--------------------
+/
bool intersects(in NegInfInterval!TP interval) const pure
{
_enforceNotEmpty();
return _begin < interval._end;
}
/++
Returns the intersection of two intervals
Params:
interval = The interval to intersect with this interval.
Throws:
DateTimeException if the two intervals do not intersect or if
either interval is empty.
Examples:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) == Interval!Date(Date(1996, 1 , 2), Date(2000, 8, 2)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) == Interval!Date(Date(1999, 1 , 12), Date(2011, 9, 17)));
--------------------
+/
Interval intersection(in Interval interval) const
{
enforce(this.intersects(interval), new DateTimeException(format("%s and %s do not intersect.", this, interval)));
auto begin = _begin > interval._begin ? _begin : interval._begin;
auto end = _end < interval._end ? _end : interval._end;
return Interval(begin, end);
}
/++
Returns the intersection of two intervals
Params:
interval = The interval to intersect with this interval.
Throws:
DateTimeException if the two intervals do not intersect or if this
interval is empty.
Examples:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(PosInfInterval!Date(Date(1990, 7, 6))) == Interval!Date(Date(1996, 1 , 2), Date(2012, 3, 1)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(PosInfInterval!Date(Date(1999, 1, 12))) == Interval!Date(Date(1999, 1 , 12), Date(2012, 3, 1)));
--------------------
+/
Interval intersection(in PosInfInterval!TP interval) const
{
enforce(this.intersects(interval), new DateTimeException(format("%s and %s do not intersect.", this, interval)));
return Interval(_begin > interval._begin ? _begin : interval._begin, _end);
}
/++
Returns the intersection of two intervals
Params:
interval = The interval to intersect with this interval.
Throws:
DateTimeException if the two intervals do not intersect or if this
interval is empty.
Examples:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(NegInfInterval!Date(Date(1999, 7, 6))) == Interval!Date(Date(1996, 1 , 2), Date(1999, 7, 6)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(NegInfInterval!Date(Date(2013, 1, 12))) == Interval!Date(Date(1996, 1 , 2), Date(2012, 3, 1)));
--------------------
+/
Interval intersection(in NegInfInterval!TP interval) const
{
enforce(this.intersects(interval), new DateTimeException(format("%s and %s do not intersect.", this, interval)));
return Interval(_begin, _end < interval._end ? _end : interval._end);
}
/++
Whether the given interval is adjacent to this interval.
Params:
interval = The interval to check whether its adjacent with this
interval.
Throws:
DateTimeException if either interval is empty.
Examples:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(1990, 7, 6), Date(1996, 1, 2))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(2012, 3, 1), Date(2013, 9, 17))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(1989, 3, 1), Date(2012, 3, 1))));
--------------------
+/
bool isAdjacent(in Interval interval) const pure
{
_enforceNotEmpty();
interval._enforceNotEmpty();
return _begin == interval._end || _end == interval._begin;
}
/++
Whether the given interval is adjacent to this interval.
Params:
interval = The interval to check whether its adjacent with this
interval.
Throws:
DateTimeException if this is empty.
Examples:
--------------------
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(PosInfInterval!Date(Date(1999, 5, 4))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(PosInfInterval!Date(Date(2012, 3, 1))));
--------------------
+/
bool isAdjacent(in PosInfInterval!TP interval) const pure
{
_enforceNotEmpty();
return _end == interval._begin;
}
/++
Whether the given interval is adjacent to this interval.
Params:
interval = The interval to check whether its adjacent with this
interval.
Throws:
DateTimeException if this is empty.
Examples:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(NegInfInterval!Date(Date(1996, 1, 2))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(NegInfInterval!Date(Date(2000, 1, 2))));
--------------------
+/
bool isAdjacent(in NegInfInterval!TP interval) const pure
{
_enforceNotEmpty();
return _begin == interval._end;
}
/++
Returns the union of two intervals
Params:
interval = The interval to merge with this interval.
Throws:
DateTimeException if the two intervals do not intersect and are not
adjacent or if either interval is empty.
Examples:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) == Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(Interval!Date(Date(2012, 3, 1), Date(2013, 5, 7))) == Interval!Date(Date(1996, 1 , 2), Date(2013, 5, 7)));
--------------------
+/
Interval merge(in Interval interval) const
{
enforce(this.isAdjacent(interval) || this.intersects(interval),
new DateTimeException(format("%s and %s are not adjacent and do not intersect.", this, interval)));
auto begin = _begin < interval._begin ? _begin : interval._begin;
auto end = _end > interval._end ? _end : interval._end;
return Interval(begin, end);
}
/++
Returns the union of two intervals
Params:
interval = The interval to merge with this interval.
Throws:
DateTimeException if the two intervals do not intersect and are
not adjacent or if this interval is empty.
Examples:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(PosInfInterval!Date(Date(1990, 7, 6))) == PosInfInterval!Date(Date(1990, 7 , 6)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(PosInfInterval!Date(Date(2012, 3, 1))) == PosInfInterval!Date(Date(1996, 1 , 2)));
--------------------
+/
PosInfInterval!TP merge(in PosInfInterval!TP interval) const
{
enforce(this.isAdjacent(interval) || this.intersects(interval),
new DateTimeException(format("%s and %s are not adjacent and do not intersect.", this, interval)));
return PosInfInterval!TP(_begin < interval._begin ? _begin : interval._begin);
}
/++
Returns the union of two intervals
Params:
interval = The interval to merge with this interval.
Throws:
DateTimeException if the two intervals do not intersect and are not
adjacent or if this interval is empty.
Examples:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(NegInfInterval!Date(Date(1996, 1, 2))) == NegInfInterval!Date(Date(2012, 3 , 1)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(NegInfInterval!Date(Date(2013, 1, 12))) == NegInfInterval!Date(Date(2013, 1 , 12)));
--------------------
+/
NegInfInterval!TP merge(in NegInfInterval!TP interval) const
{
enforce(this.isAdjacent(interval) || this.intersects(interval),
new DateTimeException(format("%s and %s are not adjacent and do not intersect.", this, interval)));
return NegInfInterval!TP(_end > interval._end ? _end : interval._end);
}
/++
Returns an interval that covers from the earliest time point of two
intervals up to (but not including) the latest time point of two intervals.
Params:
interval = The interval to create a span together with this interval.
Throws:
DateTimeException if either interval is empty.
Examples:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(Interval!Date(Date(1990, 7, 6), Date(1991, 1, 8))) == Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(Interval!Date(Date(2012, 3, 1), Date(2013, 5, 7))) == Interval!Date(Date(1996, 1 , 2), Date(2013, 5, 7)));
--------------------
+/
Interval span(in Interval interval) const pure
{
_enforceNotEmpty();
interval._enforceNotEmpty();
auto begin = _begin < interval._begin ? _begin : interval._begin;
auto end = _end > interval._end ? _end : interval._end;
return Interval(begin, end);
}
/++
Returns an interval that covers from the earliest time point of two
intervals up to (but not including) the latest time point of two intervals.
Params:
interval = The interval to create a span together with this interval.
Throws:
DateTimeException if this interval is empty.
Examples:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(PosInfInterval!Date(Date(1990, 7, 6))) == PosInfInterval!Date(Date(1990, 7 , 6)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(PosInfInterval!Date(Date(2050, 1, 1))) == PosInfInterval!Date(Date(1996, 1 , 2)));
--------------------
+/
PosInfInterval!TP span(in PosInfInterval!TP interval) const pure
{
_enforceNotEmpty();
return PosInfInterval!TP(_begin < interval._begin ? _begin : interval._begin);
}
/++
Returns an interval that covers from the earliest time point of two
intervals up to (but not including) the latest time point of two intervals.
Params:
interval = The interval to create a span together with this interval.
Throws:
DateTimeException if this interval is empty.
Examples:
--------------------
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(NegInfInterval!Date(Date(1602, 5, 21))) == NegInfInterval!Date(Date(2012, 3 , 1)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(NegInfInterval!Date(Date(2013, 1, 12))) == NegInfInterval!Date(Date(2013, 1 , 12)));
--------------------
+/
NegInfInterval!TP span(in NegInfInterval!TP interval) const pure
{
_enforceNotEmpty();
return NegInfInterval!TP(_end > interval._end ? _end : interval._end);
}
/++
Shifts the interval forward or backwards in time by the given duration
(a positive duration shifts the interval forward; a negative duration
shifts it backward). Effectively, it does $(D begin += duration) and
$(D end += duration).
Params:
duration = The duration to shift the interval by.
Throws:
DateTimeException if empty is true or if the resulting interval
would be invalid.
Examples:
--------------------
auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 4, 5));
auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 4, 5));
interval1.shift(dur!"days"(50));
assert(interval1 == Interval!Date(Date(1996, 2, 21), Date(2012, 5, 25)));
interval2.shift(dur!"days"(-50));
assert(interval2 == Interval!Date(Date(1995, 11, 13), Date(2012, 2, 15)));
--------------------
+/
void shift(D)(D duration) pure
if(__traits(compiles, begin + duration))
{
_enforceNotEmpty();
auto begin = _begin + duration;
auto end = _end + duration;
if(!_valid(begin, end))
throw new DateTimeException("Argument would result in an invalid Interval.");
_begin = begin;
_end = end;
}
static if(__traits(compiles, begin.add!"months"(1)) &&
__traits(compiles, begin.add!"years"(1)))
{
/++
Shifts the interval forward or backwards in time by the given number
of years and/or months (a positive number of years and months shifts
the interval forward; a negative number shifts it backward).
It adds the years the given years and months to both begin and end.
It effectively calls $(D add!"years"()) and then $(D add!"months"())
on begin and end with the given number of years and months.
Params:
years = The number of years to shift the interval by.
months = The number of months to shift the interval by.
allowOverflow = Whether the days should be allowed to overflow
on begin and end, causing their month to increment.
Throws:
DateTimeException if empty is true or if the resulting interval
would be invalid.
Examples:
--------------------
auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
interval1.shift(2);
assert(interval1 == Interval!Date(Date(1998, 1, 2), Date(2014, 3, 1)));
interval2.shift(-2);
assert(interval2 == Interval!Date(Date(1994, 1, 2), Date(2010, 3, 1)));
--------------------
+/
void shift(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
if(isIntegral!T)
{
_enforceNotEmpty();
auto begin = _begin;
auto end = _end;
begin.add!"years"(years, allowOverflow);
begin.add!"months"(months, allowOverflow);
end.add!"years"(years, allowOverflow);
end.add!"months"(months, allowOverflow);
enforce(_valid(begin, end), new DateTimeException("Argument would result in an invalid Interval."));
_begin = begin;
_end = end;
}
}
/++
Expands the interval forwards and/or backwards in time. Effectively,
it does $(D begin -= duration) and/or $(D end += duration). Whether
it expands forwards and/or backwards in time is determined by the
$(D dir) parameter.
Params:
duration = The duration to expand the interval by.
dir = The direction in time to expand the interval.
Throws:
DateTimeException if empty is true or if the resulting interval would
be invalid.
Examples:
--------------------
auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
interval1.expand(2);
assert(interval1 == Interval!Date(Date(1994, 1, 2), Date(2014, 3, 1)));
interval2.expand(-2);
assert(interval2 == Interval!Date(Date(1998, 1, 2), Date(2010, 3, 1)));
--------------------
+/
void expand(D)(D duration, Direction dir = Direction.both) pure
if(__traits(compiles, begin + duration))
{
_enforceNotEmpty();
switch(dir)
{
case Direction.both:
{
auto begin = _begin - duration;
auto end = _end + duration;
if(!_valid(begin, end))
throw new DateTimeException("Argument would result in an invalid Interval.");
_begin = begin;
_end = end;
return;
}
case Direction.fwd:
{
auto end = _end + duration;
if(!_valid(_begin, end))
throw new DateTimeException("Argument would result in an invalid Interval.");
_end = end;
return;
}
case Direction.bwd:
{
auto begin = _begin - duration;
if(!_valid(begin, _end))
throw new DateTimeException("Argument would result in an invalid Interval.");
_begin = begin;
return;
}
default:
assert(0, "Invalid Direction.");
}
}
static if(__traits(compiles, begin.add!"months"(1)) &&
__traits(compiles, begin.add!"years"(1)))
{
/++
Expands the interval forwards and/or backwards in time. Effectively,
it subtracts the given number of months/years from begin and adds
them to end. Whether it expands forwards and/or backwards in time
is determined by the dir parameter.
Params:
years = The number of years to expand the interval by.
months = The number of months to expand the interval by.
allowOverflow = Whether the days should be allowed to overflow
on begin and end, causing their month to increment.
Throws:
DateTimeException if empty is true or if the resulting interval
would be invalid.
Examples:
--------------------
auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
interval1.expand(2);
assert(interval1 == Interval!Date(Date(1994, 1, 2), Date(2014, 3, 1)));
interval2.expand(-2);
assert(interval2 == Interval!Date(Date(1998, 1, 2), Date(2010, 3, 1)));
--------------------
+/
void expand(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes, Direction dir = Direction.both)
if(isIntegral!T)
{
_enforceNotEmpty();
switch(dir)
{
case Direction.both:
{
auto begin = _begin;
auto end = _end;
begin.add!"years"(-years, allowOverflow);
begin.add!"months"(-months, allowOverflow);
end.add!"years"(years, allowOverflow);
end.add!"months"(months, allowOverflow);
enforce(_valid(begin, end), new DateTimeException("Argument would result in an invalid Interval."));
_begin = begin;
_end = end;
return;
}
case Direction.fwd:
{
auto end = _end;
end.add!"years"(years, allowOverflow);
end.add!"months"(months, allowOverflow);
enforce(_valid(_begin, end), new DateTimeException("Argument would result in an invalid Interval."));
_end = end;
return;
}
case Direction.bwd:
{
auto begin = _begin;
begin.add!"years"(-years, allowOverflow);
begin.add!"months"(-months, allowOverflow);
enforce(_valid(begin, _end), new DateTimeException("Argument would result in an invalid Interval."));
_begin = begin;
return;
}
default:
assert(0, "Invalid Direction.");
}
}
}
/++
Returns a range which iterates forward over the interval, starting
at begin, using $(D func) to generate each successive time point.
The range's $(D front) is the interval's $(D begin). $(D func) is used
to generate the next $(D front) when $(D popFront()) is called. If
$(D popFirst) is $(D PopFirst.yes), then $(D popFront()) is called
before the range is returned (so that front is a time point which
$(D func) would generate).
If $(D func) ever generates a time point less than or equal to the
current front of the range, then a DateTimeException will be thrown.
The range will be empty and iteration complete when $(D func) generates
a time point equal to or beyond the end of the interval.
There are helper functions in this module which generate common delegates
to pass to $(D fwdRange()). Their documentation starts with
"Generates a range-generating function for intervals," so you can easily
search for them.
Params:
func = The function used to generate the time points of the
range over the interval.
popFirst = Whether $(D popFront()) should be called on the range
before returning it.
Throws:
DateTimeException if the interval is empty.
Warning:
func must be logically pure. Ideally, $(D func) would be a function
pointer to a pure function, but forcing func to be pure is far too
restrictive to be useful, and in order to have the ease of use of
having functions which generate functions to pass to $(D fwdRange()),
$(D func) must be a delegate.
If $(D func) retains state which changes as it is called, then some
algorithms will not work correctly, because the range's $(D save)
will have failed to have really saved the range's state. So, if you
want to avoid such bugs, don't pass a delegate which is not
logically pure to $(D fwdRange()). If $(D func) is given the same
time point with two different calls, it must return the same result
both times.
Of course, none of the functions in this module have this problem, so
it's only relevant if you're creating your own delegate.
Examples:
--------------------
auto interval = Interval!Date(Date(2010, 9, 1), Date(2010, 9, 9));
auto func = (in Date date) //For iterating over even-numbered days.
{
if((date.day & 1) == 0)
return date + dur!"days"(2);
return date + dur!"days"(1);
};
auto range = interval.fwdRange(func);
assert(range.front == Date(2010, 9, 1)); //An odd day. Using PopFirst.yes would have made this Date(2010, 9, 2).
range.popFront();
assert(range.front == Date(2010, 9, 2));
range.popFront();
assert(range.front == Date(2010, 9, 4));
range.popFront();
assert(range.front == Date(2010, 9, 6));
range.popFront();
assert(range.front == Date(2010, 9, 8));
range.popFront();
assert(range.empty);
--------------------
+/
IntervalRange!(TP, Direction.fwd) fwdRange(TP delegate(in TP) func, PopFirst popFirst = PopFirst.no) const
{
_enforceNotEmpty();
auto range = IntervalRange!(TP, Direction.fwd)(this, func);
if(popFirst == PopFirst.yes)
range.popFront();
return range;
}
/++
Returns a range which iterates backwards over the interval, starting
at end, using $(D func) to generate each successive time point.
The range's $(D front) is the interval's $(D end). $(D func) is used
to generate the next $(D front) when $(D popFront()) is called. If
$(D popFirst) is $(D PopFirst.yes), then $(D popFront()) is called
before the range is returned (so that $(D front) is a time point which
$(D func) would generate).
If $(D func) ever generates a time point greater than or equal to the
current $(D front) of the range, then a DateTimeException will be thrown.
The range will be empty and iteration complete when $(D func) generates
a time point equal to or less than the $(D begin) of the interval.
There are helper functions in this module which generate common delegates
to pass to $(D bwdRange()). Their documentation starts with
"Generates a range-generating function for intervals," so you can easily
search for them.
Params:
func = The function used to generate the time points of the range
over the interval.
popFirst = Whether $(D popFront()) should be called on the range before
returning it.
Throws:
DateTimeException if the interval is empty.
Warning:
func must be logically pure. Ideally, $(D func) would be a function
pointer to a pure function, but forcing func to be pure is far too
restrictive to be useful, and in order to have the ease of use of
having functions which generate functions to pass to $(D fwdRange()),
$(D func) must be a delegate.
If $(D func) retains state which changes as it is called, then some
algorithms will not work correctly, because the range's $(D save)
will have failed to have really saved the range's state. So, if you
want to avoid such bugs, don't pass a delegate which is not
logically pure to $(D fwdRange()). If $(D func) is given the same
time point with two different calls, it must return the same result
both times.
Of course, none of the functions in this module have this problem, so
it's only relevant if you're creating your own delegate.
Examples:
--------------------
auto interval = Interval!Date(Date(2010, 9, 1), Date(2010, 9, 9));
auto func = (in Date date) //For iterating over even-numbered days.
{
if((date.day & 1) == 0)
return date - dur!"days"(2);
return date - dur!"days"(1);
};
auto range = interval.bwdRange(func);
assert(range.front == Date(2010, 9, 9)); //An odd day. Using PopFirst.yes would have made this Date(2010, 9, 8).
range.popFront();
assert(range.front == Date(2010, 9, 8));
range.popFront();
assert(range.front == Date(2010, 9, 6));
range.popFront();
assert(range.front == Date(2010, 9, 4));
range.popFront();
assert(range.front == Date(2010, 9, 2));
range.popFront();
assert(range.empty);
--------------------
+/
IntervalRange!(TP, Direction.bwd) bwdRange(TP delegate(in TP) func, PopFirst popFirst = PopFirst.no) const
{
_enforceNotEmpty();
auto range = IntervalRange!(TP, Direction.bwd)(this, func);
if(popFirst == PopFirst.yes)
range.popFront();
return range;
}
/+
Converts this interval to a string.
+/
//Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
//have versions of toString() with extra modifiers, so we define one version
//with modifiers and one without.
string toString()
{
return _toStringImpl();
}
/++
Converts this interval to a string.
+/
//Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
//have versions of toString() with extra modifiers, so we define one version
//with modifiers and one without.
string toString() const nothrow
{
return _toStringImpl();
}
private:
/++
Since we have two versions of toString(), we have _toStringImpl()
so that they can share implementations.
+/
string _toStringImpl() const nothrow
{
try
return format("[%s - %s)", _begin, _end);
catch(Exception e)
assert(0, "format() threw.");
}
/++
Throws:
DateTimeException if empty is true.
+/
void _enforceNotEmpty(size_t line = __LINE__) const pure
{
if(empty)
throw new DateTimeException("Invalid operation for an empty Interval.", __FILE__, line);
}
/++
Whether the given values form a valid time interval.
Params:
begin = The begin point of the interval.
end = The end point of the interval.
+/
static bool _valid(in TP begin, in TP end) pure nothrow
{
return begin <= end;
}
pure invariant()
{
assert(_valid(_begin, _end), "Invariant Failure: begin is not before or equal to end.");
}
TP _begin;
TP _end;
}
//Test Interval's constructors.
unittest
{
assertThrown!DateTimeException(Interval!Date(Date(2010, 1, 1), Date(1, 1, 1)));
Interval!Date(Date.init, Date.init);
Interval!TimeOfDay(TimeOfDay.init, TimeOfDay.init);
Interval!DateTime(DateTime.init, DateTime.init);
Interval!SysTime(SysTime(0), SysTime(0));
Interval!DateTime(DateTime.init, dur!"days"(7));
//Verify Examples.
Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
assert(Interval!Date(Date(1996, 1, 2), dur!"weeks"(3)) == Interval!Date(Date(1996, 1, 2), Date(1996, 1, 23)));
assert(Interval!Date(Date(1996, 1, 2), dur!"days"(3)) == Interval!Date(Date(1996, 1, 2), Date(1996, 1, 5)));
assert(Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), dur!"hours"(3)) == Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), DateTime(1996, 1, 2, 15, 0, 0)));
assert(Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), dur!"minutes"(3)) == Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), DateTime(1996, 1, 2, 12, 3, 0)));
assert(Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), dur!"seconds"(3)) == Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), DateTime(1996, 1, 2, 12, 0, 3)));
assert(Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), dur!"msecs"(3000)) == Interval!DateTime(DateTime(1996, 1, 2, 12, 0, 0), DateTime(1996, 1, 2, 12, 0, 3)));
}
//Test Interval's begin.
unittest
{
assertPred!"=="(Interval!Date(Date(1, 1, 1), Date(2010, 1, 1)).begin, Date(1, 1, 1));
assertPred!"=="(Interval!Date(Date(2010, 1, 1), Date(2010, 1, 1)).begin, Date(2010, 1, 1));
assertPred!"=="(Interval!Date(Date(1997, 12, 31), Date(1998, 1, 1)).begin, Date(1997, 12, 31));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static assert(__traits(compiles, cInterval.begin));
static assert(__traits(compiles, iInterval.begin));
//Verify Examples.
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).begin == Date(1996, 1, 2));
}
//Test Interval's end.
unittest
{
assertPred!"=="(Interval!Date(Date(1, 1, 1), Date(2010, 1, 1)).end, Date(2010, 1, 1));
assertPred!"=="(Interval!Date(Date(2010, 1, 1), Date(2010, 1, 1)).end, Date(2010, 1, 1));
assertPred!"=="(Interval!Date(Date(1997, 12, 31), Date(1998, 1, 1)).end, Date(1998, 1, 1));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static assert(__traits(compiles, cInterval.end));
static assert(__traits(compiles, iInterval.end));
//Verify Examples.
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).end == Date(2012, 3, 1));
}
//Test Interval's length.
unittest
{
assertPred!"=="(Interval!Date(Date(2010, 1, 1), Date(2010, 1, 1)).length, dur!"days"(0));
assertPred!"=="(Interval!Date(Date(2010, 1, 1), Date(2010, 4, 1)).length, dur!"days"(90));
assertPred!"=="(Interval!TimeOfDay(TimeOfDay(0, 30, 0), TimeOfDay(12, 22, 7)).length, dur!"seconds"(42_727));
assertPred!"=="(Interval!DateTime(DateTime(2010, 1, 1, 0, 30, 0), DateTime(2010, 1, 2, 12, 22, 7)).length, dur!"seconds"(129_127));
assertPred!"=="(Interval!SysTime(SysTime(DateTime(2010, 1, 1, 0, 30, 0)), SysTime(DateTime(2010, 1, 2, 12, 22, 7))).length, dur!"seconds"(129_127));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static assert(__traits(compiles, cInterval.length));
static assert(__traits(compiles, iInterval.length));
//Verify Examples.
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).length == dur!"days"(5903));
}
//Test Interval's empty.
unittest
{
assert(Interval!Date(Date(2010, 1, 1), Date(2010, 1, 1)).empty);
assert(!Interval!Date(Date(2010, 1, 1), Date(2010, 4, 1)).empty);
assert(!Interval!TimeOfDay(TimeOfDay(0, 30, 0), TimeOfDay(12, 22, 7)).empty);
assert(!Interval!DateTime(DateTime(2010, 1, 1, 0, 30, 0), DateTime(2010, 1, 2, 12, 22, 7)).empty);
assert(!Interval!SysTime(SysTime(DateTime(2010, 1, 1, 0, 30, 0)), SysTime(DateTime(2010, 1, 2, 12, 22, 7))).empty);
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static assert(__traits(compiles, cInterval.empty));
static assert(__traits(compiles, iInterval.empty));
//Verify Examples.
assert(Interval!Date(Date(1996, 1, 2), Date(1996, 1, 2)).empty);
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).empty);
}
//Test Interval's contains(time point).
unittest
{
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).contains(Date(2010, 7, 4)));
assert(!interval.contains(Date(2009, 7, 4)));
assert(!interval.contains(Date(2010, 7, 3)));
assert(interval.contains(Date(2010, 7, 4)));
assert(interval.contains(Date(2010, 7, 5)));
assert(interval.contains(Date(2011, 7, 1)));
assert(interval.contains(Date(2012, 1, 6)));
assert(!interval.contains(Date(2012, 1, 7)));
assert(!interval.contains(Date(2012, 1, 8)));
assert(!interval.contains(Date(2013, 1, 7)));
const cdate = Date(2010, 7, 6);
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static assert(__traits(compiles, interval.contains(cdate)));
static assert(__traits(compiles, cInterval.contains(cdate)));
static assert(__traits(compiles, iInterval.contains(cdate)));
//Verify Examples.
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Date(1994, 12, 24)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Date(2000, 1, 5)));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Date(2012, 3, 1)));
}
//Test Interval's contains(Interval).
unittest
{
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assertThrown!DateTimeException(interval.contains(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).contains(interval));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).contains(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assert(interval.contains(interval));
assert(!interval.contains(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assert(!interval.contains(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
assert(!interval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
assert(!interval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
assert(!interval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
assert(!interval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
assert(interval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
assert(interval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
assert(interval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
assert(!interval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
assert(!interval.contains(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
assert(!interval.contains(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assert(!Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).contains(interval));
assert(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).contains(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).contains(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).contains(interval));
assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).contains(interval));
assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).contains(interval));
assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).contains(interval));
assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).contains(interval));
assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).contains(interval));
assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).contains(interval));
assert(!Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).contains(interval));
assert(!Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).contains(interval));
assert(!interval.contains(PosInfInterval!Date(Date(2010, 7, 3))));
assert(!interval.contains(PosInfInterval!Date(Date(2010, 7, 4))));
assert(!interval.contains(PosInfInterval!Date(Date(2010, 7, 5))));
assert(!interval.contains(PosInfInterval!Date(Date(2012, 1, 6))));
assert(!interval.contains(PosInfInterval!Date(Date(2012, 1, 7))));
assert(!interval.contains(PosInfInterval!Date(Date(2012, 1, 8))));
assert(!interval.contains(NegInfInterval!Date(Date(2010, 7, 3))));
assert(!interval.contains(NegInfInterval!Date(Date(2010, 7, 4))));
assert(!interval.contains(NegInfInterval!Date(Date(2010, 7, 5))));
assert(!interval.contains(NegInfInterval!Date(Date(2012, 1, 6))));
assert(!interval.contains(NegInfInterval!Date(Date(2012, 1, 7))));
assert(!interval.contains(NegInfInterval!Date(Date(2012, 1, 8))));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, interval.contains(interval)));
static assert(__traits(compiles, interval.contains(cInterval)));
static assert(__traits(compiles, interval.contains(iInterval)));
static assert(__traits(compiles, interval.contains(posInfInterval)));
static assert(__traits(compiles, interval.contains(cPosInfInterval)));
static assert(__traits(compiles, interval.contains(iPosInfInterval)));
static assert(__traits(compiles, interval.contains(negInfInterval)));
static assert(__traits(compiles, interval.contains(cNegInfInterval)));
static assert(__traits(compiles, interval.contains(iNegInfInterval)));
static assert(__traits(compiles, cInterval.contains(interval)));
static assert(__traits(compiles, cInterval.contains(cInterval)));
static assert(__traits(compiles, cInterval.contains(iInterval)));
static assert(__traits(compiles, cInterval.contains(posInfInterval)));
static assert(__traits(compiles, cInterval.contains(cPosInfInterval)));
static assert(__traits(compiles, cInterval.contains(iPosInfInterval)));
static assert(__traits(compiles, cInterval.contains(negInfInterval)));
static assert(__traits(compiles, cInterval.contains(cNegInfInterval)));
static assert(__traits(compiles, cInterval.contains(iNegInfInterval)));
static assert(__traits(compiles, iInterval.contains(interval)));
static assert(__traits(compiles, iInterval.contains(cInterval)));
static assert(__traits(compiles, iInterval.contains(iInterval)));
static assert(__traits(compiles, iInterval.contains(posInfInterval)));
static assert(__traits(compiles, iInterval.contains(cPosInfInterval)));
static assert(__traits(compiles, iInterval.contains(iPosInfInterval)));
static assert(__traits(compiles, iInterval.contains(negInfInterval)));
static assert(__traits(compiles, iInterval.contains(cNegInfInterval)));
static assert(__traits(compiles, iInterval.contains(iNegInfInterval)));
//Verify Examples.
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(PosInfInterval!Date(Date(1999, 5, 4))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).contains(NegInfInterval!Date(Date(1996, 5, 4))));
}
//Test Interval's isBefore(time point).
unittest
{
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isBefore(Date(2010, 7, 4)));
assert(!interval.isBefore(Date(2009, 7, 3)));
assert(!interval.isBefore(Date(2010, 7, 3)));
assert(!interval.isBefore(Date(2010, 7, 4)));
assert(!interval.isBefore(Date(2010, 7, 5)));
assert(!interval.isBefore(Date(2011, 7, 1)));
assert(!interval.isBefore(Date(2012, 1, 6)));
assert(interval.isBefore(Date(2012, 1, 7)));
assert(interval.isBefore(Date(2012, 1, 8)));
assert(interval.isBefore(Date(2013, 1, 7)));
const cdate = Date(2010, 7, 6);
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static assert(__traits(compiles, interval.isBefore(cdate)));
static assert(__traits(compiles, cInterval.isBefore(cdate)));
static assert(__traits(compiles, iInterval.isBefore(cdate)));
//Verify Examples.
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Date(1994, 12, 24)));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Date(2000, 1, 5)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Date(2012, 3, 1)));
}
//Test Interval's isBefore(Interval).
unittest
{
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assertThrown!DateTimeException(interval.isBefore(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isBefore(interval));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isBefore(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assert(!interval.isBefore(interval));
assert(!interval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assert(!interval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
assert(!interval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
assert(!interval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
assert(!interval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
assert(!interval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
assert(!interval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
assert(!interval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
assert(!interval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
assert(!interval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
assert(interval.isBefore(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
assert(interval.isBefore(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assert(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).isBefore(interval));
assert(!Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).isBefore(interval));
assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).isBefore(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).isBefore(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).isBefore(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).isBefore(interval));
assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).isBefore(interval));
assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).isBefore(interval));
assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).isBefore(interval));
assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).isBefore(interval));
assert(!Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).isBefore(interval));
assert(!Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).isBefore(interval));
assert(!interval.isBefore(PosInfInterval!Date(Date(2010, 7, 3))));
assert(!interval.isBefore(PosInfInterval!Date(Date(2010, 7, 4))));
assert(!interval.isBefore(PosInfInterval!Date(Date(2010, 7, 5))));
assert(!interval.isBefore(PosInfInterval!Date(Date(2012, 1, 6))));
assert(interval.isBefore(PosInfInterval!Date(Date(2012, 1, 7))));
assert(interval.isBefore(PosInfInterval!Date(Date(2012, 1, 8))));
assert(!interval.isBefore(NegInfInterval!Date(Date(2010, 7, 3))));
assert(!interval.isBefore(NegInfInterval!Date(Date(2010, 7, 4))));
assert(!interval.isBefore(NegInfInterval!Date(Date(2010, 7, 5))));
assert(!interval.isBefore(NegInfInterval!Date(Date(2012, 1, 6))));
assert(!interval.isBefore(NegInfInterval!Date(Date(2012, 1, 7))));
assert(!interval.isBefore(NegInfInterval!Date(Date(2012, 1, 8))));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, interval.isBefore(interval)));
static assert(__traits(compiles, interval.isBefore(cInterval)));
static assert(__traits(compiles, interval.isBefore(iInterval)));
static assert(__traits(compiles, interval.isBefore(posInfInterval)));
static assert(__traits(compiles, interval.isBefore(cPosInfInterval)));
static assert(__traits(compiles, interval.isBefore(iPosInfInterval)));
static assert(__traits(compiles, interval.isBefore(negInfInterval)));
static assert(__traits(compiles, interval.isBefore(cNegInfInterval)));
static assert(__traits(compiles, interval.isBefore(iNegInfInterval)));
static assert(__traits(compiles, cInterval.isBefore(interval)));
static assert(__traits(compiles, cInterval.isBefore(cInterval)));
static assert(__traits(compiles, cInterval.isBefore(iInterval)));
static assert(__traits(compiles, cInterval.isBefore(posInfInterval)));
static assert(__traits(compiles, cInterval.isBefore(cPosInfInterval)));
static assert(__traits(compiles, cInterval.isBefore(iPosInfInterval)));
static assert(__traits(compiles, cInterval.isBefore(negInfInterval)));
static assert(__traits(compiles, cInterval.isBefore(cNegInfInterval)));
static assert(__traits(compiles, cInterval.isBefore(iNegInfInterval)));
static assert(__traits(compiles, iInterval.isBefore(interval)));
static assert(__traits(compiles, iInterval.isBefore(cInterval)));
static assert(__traits(compiles, iInterval.isBefore(iInterval)));
static assert(__traits(compiles, iInterval.isBefore(posInfInterval)));
static assert(__traits(compiles, iInterval.isBefore(cPosInfInterval)));
static assert(__traits(compiles, iInterval.isBefore(iPosInfInterval)));
static assert(__traits(compiles, iInterval.isBefore(negInfInterval)));
static assert(__traits(compiles, iInterval.isBefore(cNegInfInterval)));
static assert(__traits(compiles, iInterval.isBefore(iNegInfInterval)));
//Verify Examples.
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(Interval!Date(Date(2012, 3, 1), Date(2013, 5, 1))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(PosInfInterval!Date(Date(1999, 5, 4))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(PosInfInterval!Date(Date(2013, 3, 7))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isBefore(NegInfInterval!Date(Date(1996, 5, 4))));
}
//Test Interval's isAfter(time point).
unittest
{
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isAfter(Date(2010, 7, 4)));
assert(interval.isAfter(Date(2009, 7, 4)));
assert(interval.isAfter(Date(2010, 7, 3)));
assert(!interval.isAfter(Date(2010, 7, 4)));
assert(!interval.isAfter(Date(2010, 7, 5)));
assert(!interval.isAfter(Date(2011, 7, 1)));
assert(!interval.isAfter(Date(2012, 1, 6)));
assert(!interval.isAfter(Date(2012, 1, 7)));
assert(!interval.isAfter(Date(2012, 1, 8)));
assert(!interval.isAfter(Date(2013, 1, 7)));
const cdate = Date(2010, 7, 6);
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static assert(__traits(compiles, interval.isAfter(cdate)));
static assert(__traits(compiles, cInterval.isAfter(cdate)));
static assert(__traits(compiles, iInterval.isAfter(cdate)));
//Verify Examples.
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Date(1994, 12, 24)));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Date(2000, 1, 5)));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Date(2012, 3, 1)));
}
//Test Interval's isAfter(Interval).
unittest
{
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assertThrown!DateTimeException(interval.isAfter(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isAfter(interval));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).isAfter(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assert(!interval.isAfter(interval));
assert(interval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assert(!interval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
assert(interval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
assert(!interval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
assert(!interval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
assert(!interval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
assert(!interval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
assert(!interval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
assert(!interval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
assert(!interval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
assert(!interval.isAfter(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
assert(!interval.isAfter(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assert(!Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).isAfter(interval));
assert(!Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).isAfter(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).isAfter(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).isAfter(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).isAfter(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).isAfter(interval));
assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).isAfter(interval));
assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).isAfter(interval));
assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).isAfter(interval));
assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).isAfter(interval));
assert(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).isAfter(interval));
assert(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).isAfter(interval));
assert(!interval.isAfter(PosInfInterval!Date(Date(2010, 7, 3))));
assert(!interval.isAfter(PosInfInterval!Date(Date(2010, 7, 4))));
assert(!interval.isAfter(PosInfInterval!Date(Date(2010, 7, 5))));
assert(!interval.isAfter(PosInfInterval!Date(Date(2012, 1, 6))));
assert(!interval.isAfter(PosInfInterval!Date(Date(2012, 1, 7))));
assert(!interval.isAfter(PosInfInterval!Date(Date(2012, 1, 8))));
assert(interval.isAfter(NegInfInterval!Date(Date(2010, 7, 3))));
assert(interval.isAfter(NegInfInterval!Date(Date(2010, 7, 4))));
assert(!interval.isAfter(NegInfInterval!Date(Date(2010, 7, 5))));
assert(!interval.isAfter(NegInfInterval!Date(Date(2012, 1, 6))));
assert(!interval.isAfter(NegInfInterval!Date(Date(2012, 1, 7))));
assert(!interval.isAfter(NegInfInterval!Date(Date(2012, 1, 8))));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, interval.isAfter(interval)));
static assert(__traits(compiles, interval.isAfter(cInterval)));
static assert(__traits(compiles, interval.isAfter(iInterval)));
static assert(__traits(compiles, interval.isAfter(posInfInterval)));
static assert(__traits(compiles, interval.isAfter(cPosInfInterval)));
static assert(__traits(compiles, interval.isAfter(iPosInfInterval)));
static assert(__traits(compiles, interval.isAfter(negInfInterval)));
static assert(__traits(compiles, interval.isAfter(cNegInfInterval)));
static assert(__traits(compiles, interval.isAfter(iNegInfInterval)));
static assert(__traits(compiles, cInterval.isAfter(interval)));
static assert(__traits(compiles, cInterval.isAfter(cInterval)));
static assert(__traits(compiles, cInterval.isAfter(iInterval)));
static assert(__traits(compiles, cInterval.isAfter(posInfInterval)));
static assert(__traits(compiles, cInterval.isAfter(cPosInfInterval)));
static assert(__traits(compiles, cInterval.isAfter(iPosInfInterval)));
static assert(__traits(compiles, cInterval.isAfter(negInfInterval)));
static assert(__traits(compiles, cInterval.isAfter(cNegInfInterval)));
static assert(__traits(compiles, cInterval.isAfter(iNegInfInterval)));
static assert(__traits(compiles, iInterval.isAfter(interval)));
static assert(__traits(compiles, iInterval.isAfter(cInterval)));
static assert(__traits(compiles, iInterval.isAfter(iInterval)));
static assert(__traits(compiles, iInterval.isAfter(posInfInterval)));
static assert(__traits(compiles, iInterval.isAfter(cPosInfInterval)));
static assert(__traits(compiles, iInterval.isAfter(iPosInfInterval)));
static assert(__traits(compiles, iInterval.isAfter(negInfInterval)));
static assert(__traits(compiles, iInterval.isAfter(cNegInfInterval)));
static assert(__traits(compiles, iInterval.isAfter(iNegInfInterval)));
//Verify Examples.
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(PosInfInterval!Date(Date(1999, 5, 4))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAfter(NegInfInterval!Date(Date(1996, 1, 2))));
}
//Test Interval's intersects().
unittest
{
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assertThrown!DateTimeException(interval.intersects(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).intersects(interval));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).intersects(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assert(interval.intersects(interval));
assert(!interval.intersects(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assert(interval.intersects(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
assert(!interval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
assert(interval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
assert(interval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
assert(interval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
assert(interval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
assert(interval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
assert(interval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
assert(interval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
assert(!interval.intersects(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
assert(!interval.intersects(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assert(!Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).intersects(interval));
assert(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).intersects(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).intersects(interval));
assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).intersects(interval));
assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).intersects(interval));
assert(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).intersects(interval));
assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).intersects(interval));
assert(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).intersects(interval));
assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).intersects(interval));
assert(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).intersects(interval));
assert(!Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).intersects(interval));
assert(!Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).intersects(interval));
assert(interval.intersects(PosInfInterval!Date(Date(2010, 7, 3))));
assert(interval.intersects(PosInfInterval!Date(Date(2010, 7, 4))));
assert(interval.intersects(PosInfInterval!Date(Date(2010, 7, 5))));
assert(interval.intersects(PosInfInterval!Date(Date(2012, 1, 6))));
assert(!interval.intersects(PosInfInterval!Date(Date(2012, 1, 7))));
assert(!interval.intersects(PosInfInterval!Date(Date(2012, 1, 8))));
assert(!interval.intersects(NegInfInterval!Date(Date(2010, 7, 3))));
assert(!interval.intersects(NegInfInterval!Date(Date(2010, 7, 4))));
assert(interval.intersects(NegInfInterval!Date(Date(2010, 7, 5))));
assert(interval.intersects(NegInfInterval!Date(Date(2012, 1, 6))));
assert(interval.intersects(NegInfInterval!Date(Date(2012, 1, 7))));
assert(interval.intersects(NegInfInterval!Date(Date(2012, 1, 8))));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, interval.intersects(interval)));
static assert(__traits(compiles, interval.intersects(cInterval)));
static assert(__traits(compiles, interval.intersects(iInterval)));
static assert(__traits(compiles, interval.intersects(posInfInterval)));
static assert(__traits(compiles, interval.intersects(cPosInfInterval)));
static assert(__traits(compiles, interval.intersects(iPosInfInterval)));
static assert(__traits(compiles, interval.intersects(negInfInterval)));
static assert(__traits(compiles, interval.intersects(cNegInfInterval)));
static assert(__traits(compiles, interval.intersects(iNegInfInterval)));
static assert(__traits(compiles, cInterval.intersects(interval)));
static assert(__traits(compiles, cInterval.intersects(cInterval)));
static assert(__traits(compiles, cInterval.intersects(iInterval)));
static assert(__traits(compiles, cInterval.intersects(posInfInterval)));
static assert(__traits(compiles, cInterval.intersects(cPosInfInterval)));
static assert(__traits(compiles, cInterval.intersects(iPosInfInterval)));
static assert(__traits(compiles, cInterval.intersects(negInfInterval)));
static assert(__traits(compiles, cInterval.intersects(cNegInfInterval)));
static assert(__traits(compiles, cInterval.intersects(iNegInfInterval)));
static assert(__traits(compiles, iInterval.intersects(interval)));
static assert(__traits(compiles, iInterval.intersects(cInterval)));
static assert(__traits(compiles, iInterval.intersects(iInterval)));
static assert(__traits(compiles, iInterval.intersects(posInfInterval)));
static assert(__traits(compiles, iInterval.intersects(cPosInfInterval)));
static assert(__traits(compiles, iInterval.intersects(iPosInfInterval)));
static assert(__traits(compiles, iInterval.intersects(negInfInterval)));
static assert(__traits(compiles, iInterval.intersects(cNegInfInterval)));
static assert(__traits(compiles, iInterval.intersects(iNegInfInterval)));
//Verify Examples.
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(PosInfInterval!Date(Date(1999, 5, 4))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(PosInfInterval!Date(Date(2012, 3, 1))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(NegInfInterval!Date(Date(1996, 1, 2))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersects(NegInfInterval!Date(Date(2000, 1, 2))));
}
//Test Interval's intersection().
unittest
{
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
assertThrown!DateTimeException(interval.intersection(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).intersection(interval));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 4), dur!"days"(0)).intersection(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertThrown!DateTimeException(interval.intersection(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assertThrown!DateTimeException(interval.intersection(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
assertThrown!DateTimeException(interval.intersection(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
assertThrown!DateTimeException(interval.intersection(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).intersection(interval));
assertThrown!DateTimeException(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).intersection(interval));
assertThrown!DateTimeException(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).intersection(interval));
assertThrown!DateTimeException(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).intersection(interval));
assertThrown!DateTimeException(interval.intersection(PosInfInterval!Date(Date(2012, 1, 7))));
assertThrown!DateTimeException(interval.intersection(PosInfInterval!Date(Date(2012, 1, 8))));
assertThrown!DateTimeException(interval.intersection(NegInfInterval!Date(Date(2010, 7, 3))));
assertThrown!DateTimeException(interval.intersection(NegInfInterval!Date(Date(2010, 7, 4))));
assertPred!"=="(interval.intersection(interval), interval);
assertPred!"=="(interval.intersection(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assertPred!"=="(interval.intersection(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))),
Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)));
assertPred!"=="(interval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assertPred!"=="(interval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assertPred!"=="(interval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))),
Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)));
assertPred!"=="(interval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))),
Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)));
assertPred!"=="(interval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))),
Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
assertPred!"=="(interval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))),
Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
assertPred!"=="(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).intersection(interval),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assertPred!"=="(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).intersection(interval),
Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)));
assertPred!"=="(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).intersection(interval),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assertPred!"=="(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).intersection(interval),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assertPred!"=="(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).intersection(interval),
Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)));
assertPred!"=="(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).intersection(interval),
Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)));
assertPred!"=="(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).intersection(interval),
Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
assertPred!"=="(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).intersection(interval),
Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
assertPred!"=="(interval.intersection(PosInfInterval!Date(Date(2010, 7, 3))),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assertPred!"=="(interval.intersection(PosInfInterval!Date(Date(2010, 7, 4))),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assertPred!"=="(interval.intersection(PosInfInterval!Date(Date(2010, 7, 5))),
Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)));
assertPred!"=="(interval.intersection(PosInfInterval!Date(Date(2012, 1, 6))),
Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
assertPred!"=="(interval.intersection(NegInfInterval!Date(Date(2010, 7, 5))),
Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)));
assertPred!"=="(interval.intersection(NegInfInterval!Date(Date(2012, 1, 6))),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 6)));
assertPred!"=="(interval.intersection(NegInfInterval!Date(Date(2012, 1, 7))),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assertPred!"=="(interval.intersection(NegInfInterval!Date(Date(2012, 1, 8))),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, interval.intersection(interval)));
static assert(__traits(compiles, interval.intersection(cInterval)));
static assert(__traits(compiles, interval.intersection(iInterval)));
static assert(__traits(compiles, interval.intersection(posInfInterval)));
static assert(__traits(compiles, interval.intersection(cPosInfInterval)));
static assert(__traits(compiles, interval.intersection(iPosInfInterval)));
static assert(__traits(compiles, interval.intersection(negInfInterval)));
static assert(__traits(compiles, interval.intersection(cNegInfInterval)));
static assert(__traits(compiles, interval.intersection(iNegInfInterval)));
static assert(__traits(compiles, cInterval.intersection(interval)));
static assert(__traits(compiles, cInterval.intersection(cInterval)));
static assert(__traits(compiles, cInterval.intersection(iInterval)));
static assert(__traits(compiles, cInterval.intersection(posInfInterval)));
static assert(__traits(compiles, cInterval.intersection(cPosInfInterval)));
static assert(__traits(compiles, cInterval.intersection(iPosInfInterval)));
static assert(__traits(compiles, cInterval.intersection(negInfInterval)));
static assert(__traits(compiles, cInterval.intersection(cNegInfInterval)));
static assert(__traits(compiles, cInterval.intersection(iNegInfInterval)));
static assert(__traits(compiles, iInterval.intersection(interval)));
static assert(__traits(compiles, iInterval.intersection(cInterval)));
static assert(__traits(compiles, iInterval.intersection(iInterval)));
static assert(__traits(compiles, iInterval.intersection(posInfInterval)));
static assert(__traits(compiles, iInterval.intersection(cPosInfInterval)));
static assert(__traits(compiles, iInterval.intersection(iPosInfInterval)));
static assert(__traits(compiles, iInterval.intersection(negInfInterval)));
static assert(__traits(compiles, iInterval.intersection(cNegInfInterval)));
static assert(__traits(compiles, iInterval.intersection(iNegInfInterval)));
//Verify Examples.
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) == Interval!Date(Date(1996, 1 , 2), Date(2000, 8, 2)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) == Interval!Date(Date(1999, 1 , 12), Date(2011, 9, 17)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(PosInfInterval!Date(Date(1990, 7, 6))) == Interval!Date(Date(1996, 1 , 2), Date(2012, 3, 1)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(PosInfInterval!Date(Date(1999, 1, 12))) == Interval!Date(Date(1999, 1 , 12), Date(2012, 3, 1)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(NegInfInterval!Date(Date(1999, 7, 6))) == Interval!Date(Date(1996, 1 , 2), Date(1999, 7, 6)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).intersection(NegInfInterval!Date(Date(2013, 1, 12))) == Interval!Date(Date(1996, 1 , 2), Date(2012, 3, 1)));
}
//Test Interval's isAdjacent().
unittest
{
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static void testInterval(in Interval!Date interval1, in Interval!Date interval2)
{
interval1.isAdjacent(interval2);
}
assertThrown!DateTimeException(testInterval(interval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), interval));
assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assert(!interval.isAdjacent(interval));
assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
assert(interval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
assert(!interval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
assert(!interval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
assert(!interval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
assert(interval.isAdjacent(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
assert(!interval.isAdjacent(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assert(!Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).isAdjacent(interval));
assert(!Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).isAdjacent(interval));
assert(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).isAdjacent(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).isAdjacent(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).isAdjacent(interval));
assert(!Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).isAdjacent(interval));
assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).isAdjacent(interval));
assert(!Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).isAdjacent(interval));
assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).isAdjacent(interval));
assert(!Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).isAdjacent(interval));
assert(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).isAdjacent(interval));
assert(!Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).isAdjacent(interval));
assert(!interval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 3))));
assert(!interval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 4))));
assert(!interval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 5))));
assert(!interval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 6))));
assert(interval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 7))));
assert(!interval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 8))));
assert(!interval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 3))));
assert(interval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 4))));
assert(!interval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 5))));
assert(!interval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 6))));
assert(!interval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 7))));
assert(!interval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 8))));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, interval.isAdjacent(interval)));
static assert(__traits(compiles, interval.isAdjacent(cInterval)));
static assert(__traits(compiles, interval.isAdjacent(iInterval)));
static assert(__traits(compiles, interval.isAdjacent(posInfInterval)));
static assert(__traits(compiles, interval.isAdjacent(cPosInfInterval)));
static assert(__traits(compiles, interval.isAdjacent(iPosInfInterval)));
static assert(__traits(compiles, interval.isAdjacent(negInfInterval)));
static assert(__traits(compiles, interval.isAdjacent(cNegInfInterval)));
static assert(__traits(compiles, interval.isAdjacent(iNegInfInterval)));
static assert(__traits(compiles, cInterval.isAdjacent(interval)));
static assert(__traits(compiles, cInterval.isAdjacent(cInterval)));
static assert(__traits(compiles, cInterval.isAdjacent(iInterval)));
static assert(__traits(compiles, cInterval.isAdjacent(posInfInterval)));
static assert(__traits(compiles, cInterval.isAdjacent(cPosInfInterval)));
static assert(__traits(compiles, cInterval.isAdjacent(iPosInfInterval)));
static assert(__traits(compiles, cInterval.isAdjacent(negInfInterval)));
static assert(__traits(compiles, cInterval.isAdjacent(cNegInfInterval)));
static assert(__traits(compiles, cInterval.isAdjacent(iNegInfInterval)));
static assert(__traits(compiles, iInterval.isAdjacent(interval)));
static assert(__traits(compiles, iInterval.isAdjacent(cInterval)));
static assert(__traits(compiles, iInterval.isAdjacent(iInterval)));
static assert(__traits(compiles, iInterval.isAdjacent(posInfInterval)));
static assert(__traits(compiles, iInterval.isAdjacent(cPosInfInterval)));
static assert(__traits(compiles, iInterval.isAdjacent(iPosInfInterval)));
static assert(__traits(compiles, iInterval.isAdjacent(negInfInterval)));
static assert(__traits(compiles, iInterval.isAdjacent(cNegInfInterval)));
static assert(__traits(compiles, iInterval.isAdjacent(iNegInfInterval)));
//Verify Examples.
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(1990, 7, 6), Date(1996, 1, 2))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(2012, 3, 1), Date(2013, 9, 17))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(1989, 3, 1), Date(2012, 3, 1))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(PosInfInterval!Date(Date(1999, 5, 4))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(PosInfInterval!Date(Date(2012, 3, 1))));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(NegInfInterval!Date(Date(1996, 1, 2))));
assert(!Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).isAdjacent(NegInfInterval!Date(Date(2000, 1, 2))));
}
//Test Interval's merge().
unittest
{
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static void testInterval(I)(in Interval!Date interval1, in I interval2)
{
interval1.merge(interval2);
}
assertThrown!DateTimeException(testInterval(interval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), interval));
assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertThrown!DateTimeException(testInterval(interval, Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assertThrown!DateTimeException(testInterval(interval, Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)), interval));
assertThrown!DateTimeException(testInterval(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)), interval));
assertThrown!DateTimeException(testInterval(interval, PosInfInterval!Date(Date(2012, 1, 8))));
assertThrown!DateTimeException(testInterval(interval, NegInfInterval!Date(Date(2010, 7, 3))));
assertPred!"=="(interval.merge(interval), interval);
assertPred!"=="(interval.merge(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))),
Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)));
assertPred!"=="(interval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))),
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assertPred!"=="(interval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))),
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assertPred!"=="(interval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))),
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assertPred!"=="(interval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))),
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)));
assertPred!"=="(interval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assertPred!"=="(interval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assertPred!"=="(interval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assertPred!"=="(interval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
assertPred!"=="(interval.merge(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
assertPred!"=="(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).merge(interval),
Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)));
assertPred!"=="(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).merge(interval),
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assertPred!"=="(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).merge(interval),
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assertPred!"=="(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).merge(interval),
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assertPred!"=="(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).merge(interval),
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)));
assertPred!"=="(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).merge(interval),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assertPred!"=="(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).merge(interval),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assertPred!"=="(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).merge(interval),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assertPred!"=="(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).merge(interval),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
assertPred!"=="(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).merge(interval),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
assertPred!"=="(interval.merge(PosInfInterval!Date(Date(2010, 7, 3))),
PosInfInterval!Date(Date(2010, 7, 3)));
assertPred!"=="(interval.merge(PosInfInterval!Date(Date(2010, 7, 4))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(interval.merge(PosInfInterval!Date(Date(2010, 7, 5))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(interval.merge(PosInfInterval!Date(Date(2012, 1, 6))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(interval.merge(PosInfInterval!Date(Date(2012, 1, 7))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(interval.merge(NegInfInterval!Date(Date(2010, 7, 4))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(interval.merge(NegInfInterval!Date(Date(2010, 7, 5))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(interval.merge(NegInfInterval!Date(Date(2012, 1, 6))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(interval.merge(NegInfInterval!Date(Date(2012, 1, 7))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(interval.merge(NegInfInterval!Date(Date(2012, 1, 8))),
NegInfInterval!Date(Date(2012, 1, 8)));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, interval.merge(interval)));
static assert(__traits(compiles, interval.merge(cInterval)));
static assert(__traits(compiles, interval.merge(iInterval)));
static assert(__traits(compiles, interval.merge(posInfInterval)));
static assert(__traits(compiles, interval.merge(cPosInfInterval)));
static assert(__traits(compiles, interval.merge(iPosInfInterval)));
static assert(__traits(compiles, interval.merge(negInfInterval)));
static assert(__traits(compiles, interval.merge(cNegInfInterval)));
static assert(__traits(compiles, interval.merge(iNegInfInterval)));
static assert(__traits(compiles, cInterval.merge(interval)));
static assert(__traits(compiles, cInterval.merge(cInterval)));
static assert(__traits(compiles, cInterval.merge(iInterval)));
static assert(__traits(compiles, cInterval.merge(posInfInterval)));
static assert(__traits(compiles, cInterval.merge(cPosInfInterval)));
static assert(__traits(compiles, cInterval.merge(iPosInfInterval)));
static assert(__traits(compiles, cInterval.merge(negInfInterval)));
static assert(__traits(compiles, cInterval.merge(cNegInfInterval)));
static assert(__traits(compiles, cInterval.merge(iNegInfInterval)));
static assert(__traits(compiles, iInterval.merge(interval)));
static assert(__traits(compiles, iInterval.merge(cInterval)));
static assert(__traits(compiles, iInterval.merge(iInterval)));
static assert(__traits(compiles, iInterval.merge(posInfInterval)));
static assert(__traits(compiles, iInterval.merge(cPosInfInterval)));
static assert(__traits(compiles, iInterval.merge(iPosInfInterval)));
static assert(__traits(compiles, iInterval.merge(negInfInterval)));
static assert(__traits(compiles, iInterval.merge(cNegInfInterval)));
static assert(__traits(compiles, iInterval.merge(iNegInfInterval)));
//Verify Examples.
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) == Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(Interval!Date(Date(2012, 3, 1), Date(2013, 5, 7))) == Interval!Date(Date(1996, 1 , 2), Date(2013, 5, 7)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(PosInfInterval!Date(Date(1990, 7, 6))) == PosInfInterval!Date(Date(1990, 7 , 6)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(PosInfInterval!Date(Date(2012, 3, 1))) == PosInfInterval!Date(Date(1996, 1 , 2)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(NegInfInterval!Date(Date(1996, 1, 2))) == NegInfInterval!Date(Date(2012, 3 , 1)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).merge(NegInfInterval!Date(Date(2013, 1, 12))) == NegInfInterval!Date(Date(2013, 1 , 12)));
}
//Test Interval's span().
unittest
{
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static void testInterval(in Interval!Date interval1, in Interval!Date interval2)
{
interval1.span(interval2);
}
assertThrown!DateTimeException(testInterval(interval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), interval));
assertThrown!DateTimeException(testInterval(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertPred!"=="(interval.span(interval), interval);
assertPred!"=="(interval.span(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))),
Interval!Date(Date(2010, 7, 1), Date(2012, 1, 7)));
assertPred!"=="(interval.span(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))),
Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)));
assertPred!"=="(interval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))),
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assertPred!"=="(interval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))),
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assertPred!"=="(interval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))),
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assertPred!"=="(interval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))),
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)));
assertPred!"=="(interval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assertPred!"=="(interval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assertPred!"=="(interval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assertPred!"=="(interval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
assertPred!"=="(interval.span(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
assertPred!"=="(interval.span(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 9)));
assertPred!"=="(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)).span(interval),
Interval!Date(Date(2010, 7, 1), Date(2012, 1, 7)));
assertPred!"=="(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)).span(interval),
Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3)));
assertPred!"=="(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)).span(interval),
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assertPred!"=="(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)).span(interval),
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assertPred!"=="(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)).span(interval),
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assertPred!"=="(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)).span(interval),
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8)));
assertPred!"=="(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)).span(interval),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assertPred!"=="(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)).span(interval),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assertPred!"=="(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)).span(interval),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assertPred!"=="(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)).span(interval),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
assertPred!"=="(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)).span(interval),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
assertPred!"=="(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)).span(interval),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 9)));
assertPred!"=="(interval.span(PosInfInterval!Date(Date(2010, 7, 3))),
PosInfInterval!Date(Date(2010, 7, 3)));
assertPred!"=="(interval.span(PosInfInterval!Date(Date(2010, 7, 4))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(interval.span(PosInfInterval!Date(Date(2010, 7, 5))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(interval.span(PosInfInterval!Date(Date(2012, 1, 6))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(interval.span(PosInfInterval!Date(Date(2012, 1, 7))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(interval.span(PosInfInterval!Date(Date(2012, 1, 8))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(interval.span(NegInfInterval!Date(Date(2010, 7, 3))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(interval.span(NegInfInterval!Date(Date(2010, 7, 4))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(interval.span(NegInfInterval!Date(Date(2010, 7, 5))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(interval.span(NegInfInterval!Date(Date(2012, 1, 6))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(interval.span(NegInfInterval!Date(Date(2012, 1, 7))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(interval.span(NegInfInterval!Date(Date(2012, 1, 8))),
NegInfInterval!Date(Date(2012, 1, 8)));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, interval.span(interval)));
static assert(__traits(compiles, interval.span(cInterval)));
static assert(__traits(compiles, interval.span(iInterval)));
static assert(__traits(compiles, interval.span(posInfInterval)));
static assert(__traits(compiles, interval.span(cPosInfInterval)));
static assert(__traits(compiles, interval.span(iPosInfInterval)));
static assert(__traits(compiles, interval.span(negInfInterval)));
static assert(__traits(compiles, interval.span(cNegInfInterval)));
static assert(__traits(compiles, interval.span(iNegInfInterval)));
static assert(__traits(compiles, cInterval.span(interval)));
static assert(__traits(compiles, cInterval.span(cInterval)));
static assert(__traits(compiles, cInterval.span(iInterval)));
static assert(__traits(compiles, cInterval.span(posInfInterval)));
static assert(__traits(compiles, cInterval.span(cPosInfInterval)));
static assert(__traits(compiles, cInterval.span(iPosInfInterval)));
static assert(__traits(compiles, cInterval.span(negInfInterval)));
static assert(__traits(compiles, cInterval.span(cNegInfInterval)));
static assert(__traits(compiles, cInterval.span(iNegInfInterval)));
static assert(__traits(compiles, iInterval.span(interval)));
static assert(__traits(compiles, iInterval.span(cInterval)));
static assert(__traits(compiles, iInterval.span(iInterval)));
static assert(__traits(compiles, iInterval.span(posInfInterval)));
static assert(__traits(compiles, iInterval.span(cPosInfInterval)));
static assert(__traits(compiles, iInterval.span(iPosInfInterval)));
static assert(__traits(compiles, iInterval.span(negInfInterval)));
static assert(__traits(compiles, iInterval.span(cNegInfInterval)));
static assert(__traits(compiles, iInterval.span(iNegInfInterval)));
//Verify Examples.
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(Interval!Date(Date(1990, 7, 6), Date(1991, 1, 8))) == Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(Interval!Date(Date(2012, 3, 1), Date(2013, 5, 7))) == Interval!Date(Date(1996, 1 , 2), Date(2013, 5, 7)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(PosInfInterval!Date(Date(1990, 7, 6))) == PosInfInterval!Date(Date(1990, 7 , 6)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(PosInfInterval!Date(Date(2050, 1, 1))) == PosInfInterval!Date(Date(1996, 1 , 2)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(NegInfInterval!Date(Date(1602, 5, 21))) == NegInfInterval!Date(Date(2012, 3 , 1)));
assert(Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1)).span(NegInfInterval!Date(Date(2013, 1, 12))) == NegInfInterval!Date(Date(2013, 1 , 12)));
}
//Test Interval's shift(duration).
unittest
{
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static void testIntervalFail(Interval!Date interval, in Duration duration)
{
interval.shift(duration);
}
assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), dur!"days"(1)));
static void testInterval(I)(I interval, in Duration duration, in I expected, size_t line = __LINE__)
{
interval.shift(duration);
assertPred!"=="(interval, expected, "", __FILE__, line);
}
testInterval(interval, dur!"days"(22), Interval!Date(Date(2010, 7, 26), Date(2012, 1, 29)));
testInterval(interval, dur!"days"(-22), Interval!Date(Date(2010, 6, 12), Date(2011, 12, 16)));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static assert(!__traits(compiles, cInterval.shift(dur!"days"(5))));
static assert(!__traits(compiles, iInterval.shift(dur!"days"(5))));
//Verify Examples.
auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 4, 5));
auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 4, 5));
interval1.shift(dur!"days"(50));
assert(interval1 == Interval!Date(Date(1996, 2, 21), Date(2012, 5, 25)));
interval2.shift(dur!"days"(-50));
assert(interval2 == Interval!Date(Date(1995, 11, 13), Date(2012, 2, 15)));
}
//Test Interval's shift(int, int, AllowDayOverflow).
unittest
{
{
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static void testIntervalFail(Interval!Date interval, int years, int months)
{
interval.shift(years, months);
}
assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), 1, 0));
static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow, in I expected, size_t line = __LINE__)
{
interval.shift(years, months, allow);
assertPred!"=="(interval, expected, "", __FILE__, line);
}
testInterval(interval, 5, 0, AllowDayOverflow.yes, Interval!Date(Date(2015, 7, 4), Date(2017, 1, 7)));
testInterval(interval, -5, 0, AllowDayOverflow.yes, Interval!Date(Date(2005, 7, 4), Date(2007, 1, 7)));
auto interval2 = Interval!Date(Date(2000, 1, 29), Date(2010, 5, 31));
testInterval(interval2, 1, 1, AllowDayOverflow.yes, Interval!Date(Date(2001, 3, 1), Date(2011, 7, 1)));
testInterval(interval2, 1, -1, AllowDayOverflow.yes, Interval!Date(Date(2000, 12, 29), Date(2011, 5, 1)));
testInterval(interval2, -1, -1, AllowDayOverflow.yes, Interval!Date(Date(1998, 12, 29), Date(2009, 5, 1)));
testInterval(interval2, -1, 1, AllowDayOverflow.yes, Interval!Date(Date(1999, 3, 1), Date(2009, 7, 1)));
testInterval(interval2, 1, 1, AllowDayOverflow.no, Interval!Date(Date(2001, 2, 28), Date(2011, 6, 30)));
testInterval(interval2, 1, -1, AllowDayOverflow.no, Interval!Date(Date(2000, 12, 29), Date(2011, 4, 30)));
testInterval(interval2, -1, -1, AllowDayOverflow.no, Interval!Date(Date(1998, 12, 29), Date(2009, 4, 30)));
testInterval(interval2, -1, 1, AllowDayOverflow.no, Interval!Date(Date(1999, 2, 28), Date(2009, 6, 30)));
}
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static assert(!__traits(compiles, cInterval.shift(5)));
static assert(!__traits(compiles, iInterval.shift(5)));
//Verify Examples.
auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
interval1.shift(2);
assert(interval1 == Interval!Date(Date(1998, 1, 2), Date(2014, 3, 1)));
interval2.shift(-2);
assert(interval2 == Interval!Date(Date(1994, 1, 2), Date(2010, 3, 1)));
}
//Test Interval's expand(Duration).
unittest
{
auto interval = Interval!Date(Date(2000, 7, 4), Date(2012, 1, 7));
static void testIntervalFail(I)(I interval, in Duration duration)
{
interval.expand(duration);
}
assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), dur!"days"(1)));
assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)), dur!"days"(-5)));
static void testInterval(I)(I interval, in Duration duration, in I expected, size_t line = __LINE__)
{
interval.expand(duration);
assertPred!"=="(interval, expected, "", __FILE__, line);
}
testInterval(interval, dur!"days"(22), Interval!Date(Date(2000, 6, 12), Date(2012, 1, 29)));
testInterval(interval, dur!"days"(-22), Interval!Date(Date(2000, 7, 26), Date(2011, 12, 16)));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static assert(!__traits(compiles, cInterval.expand(dur!"days"(5))));
static assert(!__traits(compiles, iInterval.expand(dur!"days"(5))));
//Verify Examples.
auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
interval1.expand(dur!"days"(2));
assert(interval1 == Interval!Date(Date(1995, 12, 31), Date(2012, 3, 3)));
interval2.expand(dur!"days"(-2));
assert(interval2 == Interval!Date(Date(1996, 1, 4), Date(2012, 2, 28)));
}
//Test Interval's expand(int, int, AllowDayOverflow, Direction)
unittest
{
{
auto interval = Interval!Date(Date(2000, 7, 4), Date(2012, 1, 7));
static void testIntervalFail(Interval!Date interval, int years, int months)
{
interval.expand(years, months);
}
assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), dur!"days"(0)), 1, 0));
assertThrown!DateTimeException(testIntervalFail(Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)), -5, 0));
static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow, Direction dir, in I expected, size_t line = __LINE__)
{
interval.expand(years, months, allow, dir);
assertPred!"=="(interval, expected, "", __FILE__, line);
}
testInterval(interval, 5, 0, AllowDayOverflow.yes, Direction.both, Interval!Date(Date(1995, 7, 4), Date(2017, 1, 7)));
testInterval(interval, -5, 0, AllowDayOverflow.yes, Direction.both, Interval!Date(Date(2005, 7, 4), Date(2007, 1, 7)));
testInterval(interval, 5, 0, AllowDayOverflow.yes, Direction.fwd, Interval!Date(Date(2000, 7, 4), Date(2017, 1, 7)));
testInterval(interval, -5, 0, AllowDayOverflow.yes, Direction.fwd, Interval!Date(Date(2000, 7, 4), Date(2007, 1, 7)));
testInterval(interval, 5, 0, AllowDayOverflow.yes, Direction.bwd, Interval!Date(Date(1995, 7, 4), Date(2012, 1, 7)));
testInterval(interval, -5, 0, AllowDayOverflow.yes, Direction.bwd, Interval!Date(Date(2005, 7, 4), Date(2012, 1, 7)));
auto interval2 = Interval!Date(Date(2000, 1, 29), Date(2010, 5, 31));
testInterval(interval2, 1, 1, AllowDayOverflow.yes, Direction.both, Interval!Date(Date(1998, 12, 29), Date(2011, 7, 1)));
testInterval(interval2, 1, -1, AllowDayOverflow.yes, Direction.both, Interval!Date(Date(1999, 3, 1), Date(2011, 5, 1)));
testInterval(interval2, -1, -1, AllowDayOverflow.yes, Direction.both, Interval!Date(Date(2001, 3, 1), Date(2009, 5, 1)));
testInterval(interval2, -1, 1, AllowDayOverflow.yes, Direction.both, Interval!Date(Date(2000, 12, 29), Date(2009, 7, 1)));
testInterval(interval2, 1, 1, AllowDayOverflow.no, Direction.both, Interval!Date(Date(1998, 12, 29), Date(2011, 6, 30)));
testInterval(interval2, 1, -1, AllowDayOverflow.no, Direction.both, Interval!Date(Date(1999, 2, 28), Date(2011, 4, 30)));
testInterval(interval2, -1, -1, AllowDayOverflow.no, Direction.both, Interval!Date(Date(2001, 2, 28), Date(2009, 4, 30)));
testInterval(interval2, -1, 1, AllowDayOverflow.no, Direction.both, Interval!Date(Date(2000, 12, 29), Date(2009, 6, 30)));
testInterval(interval2, 1, 1, AllowDayOverflow.yes, Direction.fwd, Interval!Date(Date(2000, 1, 29), Date(2011, 7, 1)));
testInterval(interval2, 1, -1, AllowDayOverflow.yes, Direction.fwd, Interval!Date(Date(2000, 1, 29), Date(2011, 5, 1)));
testInterval(interval2, -1, -1, AllowDayOverflow.yes, Direction.fwd, Interval!Date(Date(2000, 1, 29), Date(2009, 5, 1)));
testInterval(interval2, -1, 1, AllowDayOverflow.yes, Direction.fwd, Interval!Date(Date(2000, 1, 29), Date(2009, 7, 1)));
testInterval(interval2, 1, 1, AllowDayOverflow.no, Direction.fwd, Interval!Date(Date(2000, 1, 29), Date(2011, 6, 30)));
testInterval(interval2, 1, -1, AllowDayOverflow.no, Direction.fwd, Interval!Date(Date(2000, 1, 29), Date(2011, 4, 30)));
testInterval(interval2, -1, -1, AllowDayOverflow.no, Direction.fwd, Interval!Date(Date(2000, 1, 29), Date(2009, 4, 30)));
testInterval(interval2, -1, 1, AllowDayOverflow.no, Direction.fwd, Interval!Date(Date(2000, 1, 29), Date(2009, 6, 30)));
testInterval(interval2, 1, 1, AllowDayOverflow.yes, Direction.bwd, Interval!Date(Date(1998, 12, 29), Date(2010, 5, 31)));
testInterval(interval2, 1, -1, AllowDayOverflow.yes, Direction.bwd, Interval!Date(Date(1999, 3, 1), Date(2010, 5, 31)));
testInterval(interval2, -1, -1, AllowDayOverflow.yes, Direction.bwd, Interval!Date(Date(2001, 3, 1), Date(2010, 5, 31)));
testInterval(interval2, -1, 1, AllowDayOverflow.yes, Direction.bwd, Interval!Date(Date(2000, 12, 29), Date(2010, 5, 31)));
testInterval(interval2, 1, 1, AllowDayOverflow.no, Direction.bwd, Interval!Date(Date(1998, 12, 29), Date(2010, 5, 31)));
testInterval(interval2, 1, -1, AllowDayOverflow.no, Direction.bwd, Interval!Date(Date(1999, 2, 28), Date(2010, 5, 31)));
testInterval(interval2, -1, -1, AllowDayOverflow.no, Direction.bwd, Interval!Date(Date(2001, 2, 28), Date(2010, 5, 31)));
testInterval(interval2, -1, 1, AllowDayOverflow.no, Direction.bwd, Interval!Date(Date(2000, 12, 29), Date(2010, 5, 31)));
}
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static assert(!__traits(compiles, cInterval.expand(5)));
static assert(!__traits(compiles, iInterval.expand(5)));
//Verify Examples.
auto interval1 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
auto interval2 = Interval!Date(Date(1996, 1, 2), Date(2012, 3, 1));
interval1.expand(2);
assert(interval1 == Interval!Date(Date(1994, 1, 2), Date(2014, 3, 1)));
interval2.expand(-2);
assert(interval2 == Interval!Date(Date(1998, 1, 2), Date(2010, 3, 1)));
}
//Test Interval's fwdRange.
unittest
{
{
auto interval = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 21));
static void testInterval1(Interval!Date interval)
{
interval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
}
assertThrown!DateTimeException(testInterval1(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
static void testInterval2(Interval!Date interval)
{
interval.fwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).popFront();
}
assertThrown!DateTimeException(testInterval2(interval));
assert(!interval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).empty);
assert(interval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri), PopFirst.yes).empty);
assertPred!"=="(Interval!Date(Date(2010, 9, 12), Date(2010, 10, 1)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).front,
Date(2010, 9, 12));
assertPred!"=="(Interval!Date(Date(2010, 9, 12), Date(2010, 10, 1)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri), PopFirst.yes).front,
Date(2010, 9, 17));
}
//Verify Examples.
{
auto interval = Interval!Date(Date(2010, 9, 1), Date(2010, 9, 9));
auto func = (in Date date)
{
if((date.day & 1) == 0)
return date + dur!"days"(2);
return date + dur!"days"(1);
};
auto range = interval.fwdRange(func);
assert(range.front == Date(2010, 9, 1)); //An odd day. Using PopFirst.yes would have made this Date(2010, 9, 2).
range.popFront();
assert(range.front == Date(2010, 9, 2));
range.popFront();
assert(range.front == Date(2010, 9, 4));
range.popFront();
assert(range.front == Date(2010, 9, 6));
range.popFront();
assert(range.front == Date(2010, 9, 8));
range.popFront();
assert(range.empty);
}
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static assert(__traits(compiles, cInterval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri))));
static assert(__traits(compiles, iInterval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri))));
}
//Test Interval's bwdRange.
unittest
{
{
auto interval = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 21));
static void testInterval1(Interval!Date interval)
{
interval.bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
}
assertThrown!DateTimeException(testInterval1(Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
static void testInterval2(Interval!Date interval)
{
interval.bwdRange(everyDayOfWeek!(Date, Direction.fwd)(DayOfWeek.fri)).popFront();
}
assertThrown!DateTimeException(testInterval2(interval));
assert(!interval.bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).empty);
assert(interval.bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri), PopFirst.yes).empty);
assertPred!"=="(Interval!Date(Date(2010, 9, 19), Date(2010, 10, 1)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).front,
Date(2010, 10, 1));
assertPred!"=="(Interval!Date(Date(2010, 9, 19), Date(2010, 10, 1)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri), PopFirst.yes).front,
Date(2010, 9, 24));
}
//Verify Examples.
{
auto interval = Interval!Date(Date(2010, 9, 1), Date(2010, 9, 9));
auto func = (in Date date)
{
if((date.day & 1) == 0)
return date - dur!"days"(2);
return date - dur!"days"(1);
};
auto range = interval.bwdRange(func);
assert(range.front == Date(2010, 9, 9)); //An odd day. Using PopFirst.yes would have made this Date(2010, 9, 8).
range.popFront();
assert(range.front == Date(2010, 9, 8));
range.popFront();
assert(range.front == Date(2010, 9, 6));
range.popFront();
assert(range.front == Date(2010, 9, 4));
range.popFront();
assert(range.front == Date(2010, 9, 2));
range.popFront();
assert(range.empty);
}
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static assert(__traits(compiles, cInterval.bwdRange(everyDayOfWeek!Date(DayOfWeek.fri))));
static assert(__traits(compiles, iInterval.bwdRange(everyDayOfWeek!Date(DayOfWeek.fri))));
}
//Test Interval's toString().
unittest
{
assertPred!"=="(Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).toString(), "[2010-Jul-04 - 2012-Jan-07)");
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static assert(__traits(compiles, cInterval.toString()));
static assert(__traits(compiles, iInterval.toString()));
}
/++
Represents an interval of time which has positive infinity as its end point.
Any ranges which iterate over a $(D PosInfInterval) are infinite. So, the
main purpose of using $(D PosInfInterval) is to create an infinite range
which starts at a fixed point in time and goes to positive infinity.
+/
struct PosInfInterval(TP)
{
public:
/++
Params:
begin = The time point which begins the interval.
Examples:
--------------------
auto interval = PosInfInterval!Date(Date(1996, 1, 2));
--------------------
+/
this(in TP begin) pure nothrow
{
_begin = cast(TP)begin;
}
/++
Params:
rhs = The PosInfInterval to assign to this one.
+/
/+ref+/ PosInfInterval opAssign(const ref PosInfInterval rhs) pure nothrow
{
_begin = cast(TP)rhs._begin;
return this;
}
/++
Params:
rhs = The PosInfInterval to assign to this one.
+/
/+ref+/ PosInfInterval opAssign(PosInfInterval rhs) pure nothrow
{
_begin = cast(TP)rhs._begin;
return this;
}
/++
The begin point of the interval. It is included in the interval.
Examples:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).begin == Date(1996, 1, 2));
--------------------
+/
@property TP begin() const pure nothrow
{
return cast(TP)_begin;
}
/++
The begin point of the interval. It is included in the interval.
Params:
timePoint = The time point to set begin to.
+/
@property void begin(TP timePoint) pure nothrow
{
_begin = timePoint;
}
/++
Whether the interval's length is 0. Always returns false.
Examples:
--------------------
assert(!PosInfInterval!Date(Date(1996, 1, 2)).empty);
--------------------
+/
@property bool empty() const pure nothrow
{
return false;
}
/++
Whether the given time point is within this interval.
Params:
timePoint = The time point to check for inclusion in this interval.
Examples:
--------------------
assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(Date(1994, 12, 24)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(Date(2000, 1, 5)));
--------------------
+/
bool contains(TP timePoint) const pure nothrow
{
return timePoint >= _begin;
}
/++
Whether the given interval is completely within this interval.
Params:
interval = The interval to check for inclusion in this interval.
Throws:
DateTimeException if the given interval is empty.
Examples:
--------------------
assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
--------------------
+/
bool contains(in Interval!TP interval) const pure
{
interval._enforceNotEmpty();
return interval._begin >= _begin;
}
/++
Whether the given interval is completely within this interval.
Params:
interval = The interval to check for inclusion in this interval.
Examples:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(PosInfInterval!Date(Date(1999, 5, 4))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(PosInfInterval!Date(Date(1995, 7, 2))));
--------------------
+/
bool contains(in PosInfInterval interval) const pure nothrow
{
return interval._begin >= _begin;
}
/++
Whether the given interval is completely within this interval.
Always returns false because an interval going to positive infinity
can never contain an interval beginning at negative infinity.
Params:
interval = The interval to check for inclusion in this interval.
Examples:
--------------------
assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(NegInfInterval!Date(Date(1996, 5, 4))));
--------------------
+/
bool contains(in NegInfInterval!TP interval) const pure nothrow
{
return false;
}
/++
Whether this interval is before the given time point.
Always returns false because an interval going to positive infinity
can never be before any time point.
Params:
timePoint = The time point to check whether this interval is before it.
Examples:
--------------------
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Date(1994, 12, 24)));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Date(2000, 1, 5)));
--------------------
+/
bool isBefore(in TP timePoint) const pure nothrow
{
return false;
}
/++
Whether this interval is before the given interval and does not intersect
with it.
Always returns false (unless the given interval is empty) because an
interval going to positive infinity can never be before any other interval.
Params:
interval = The interval to check for against this interval.
Throws:
DateTimeException if either Interval is empty.
Examples:
--------------------
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
--------------------
+/
bool isBefore(in Interval!TP interval) const pure
{
interval._enforceNotEmpty();
return false;
}
/++
Whether this interval is before the given interval and does not intersect
with it.
Always returns false because an interval going to positive infinity can
never be before any other interval.
Params:
interval = The interval to check for against this interval.
Examples:
--------------------
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(PosInfInterval!Date(Date(1992, 5, 4))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(PosInfInterval!Date(Date(2013, 3, 7))));
--------------------
+/
bool isBefore(in PosInfInterval interval) const pure nothrow
{
return false;
}
/++
Whether this interval is before the given interval and does not intersect
with it.
Always returns false because an interval going to positive infinity can
never be before any other interval.
Params:
interval = The interval to check for against this interval.
Examples:
--------------------
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(NegInfInterval!Date(Date(1996, 5, 4))));
--------------------
+/
bool isBefore(in NegInfInterval!TP interval) const pure nothrow
{
return false;
}
/++
Whether this interval is after the given time point.
Params:
timePoint = The time point to check whether this Interval is after it.
Examples:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Date(1994, 12, 24)));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Date(2000, 1, 5)));
--------------------
+/
bool isAfter(in TP timePoint) const pure nothrow
{
return timePoint < _begin;
}
/++
Whether this interval is after the given interval and does not intersect
with it.
Params:
interval = The interval to check against this interval.
Throws:
DateTimeException if the given interval is empty.
Examples:
--------------------
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
--------------------
+/
bool isAfter(in Interval!TP interval) const pure
{
interval._enforceNotEmpty();
return _begin >= interval._end;
}
/++
Whether this interval is after the given interval and does not intersect
with it.
Always returns false because an interval going to positive infinity can
never be after another interval going to positive infinity.
Params:
interval = The interval to check against this interval.
Examples:
--------------------
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(PosInfInterval!Date(Date(1990, 1, 7))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(PosInfInterval!Date(Date(1999, 5, 4))));
--------------------
+/
bool isAfter(in PosInfInterval interval) const pure nothrow
{
return false;
}
/++
Whether this interval is after the given interval and does not intersect
with it.
Params:
interval = The interval to check against this interval.
Examples:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(NegInfInterval!Date(Date(1996, 1, 2))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(NegInfInterval!Date(Date(2000, 7, 1))));
--------------------
+/
bool isAfter(in NegInfInterval!TP interval) const pure nothrow
{
return _begin >= interval._end;
}
/++
Whether the given interval overlaps with this interval.
Params:
interval = The interval to check for intersection with this interval.
Throws:
DateTimeException if the given interval is empty.
Examples:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).intersects(Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
--------------------
+/
bool intersects(in Interval!TP interval) const pure
{
interval._enforceNotEmpty();
return interval._end > _begin;
}
/++
Whether the given interval overlaps with this interval.
Always returns true because two intervals going to positive infinity
always overlap.
Params:
interval = The interval to check for intersection with this interval.
Examples:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(PosInfInterval!Date(Date(1990, 1, 7))));
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(PosInfInterval!Date(Date(1999, 5, 4))));
--------------------
+/
bool intersects(in PosInfInterval interval) const pure nothrow
{
return true;
}
/++
Whether the given interval overlaps with this interval.
Params:
interval = The interval to check for intersection with this interval.
Examples:
--------------------
assert(!PosInfInterval!Date(Date(1996, 1, 2)).intersects(NegInfInterval!Date(Date(1996, 1, 2))));
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(NegInfInterval!Date(Date(2000, 7, 1))));
--------------------
+/
bool intersects(in NegInfInterval!TP interval) const pure nothrow
{
return _begin < interval._end;
}
/++
Returns the intersection of two intervals
Params:
interval = The interval to intersect with this interval.
Throws:
DateTimeException if the two intervals do not intersect or if the
given interval is empty.
Examples:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) == Interval!Date(Date(1996, 1 , 2), Date(2000, 8, 2)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) == Interval!Date(Date(1999, 1 , 12), Date(2011, 9, 17)));
--------------------
+/
Interval!TP intersection(in Interval!TP interval) const
{
enforce(this.intersects(interval), new DateTimeException(format("%s and %s do not intersect.", this, interval)));
auto begin = _begin > interval._begin ? _begin : interval._begin;
return Interval!TP(begin, interval._end);
}
/++
Returns the intersection of two intervals
Params:
interval = The interval to intersect with this interval.
Examples:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(PosInfInterval!Date(Date(1990, 7, 6))) == PosInfInterval!Date(Date(1996, 1 , 2)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(PosInfInterval!Date(Date(1999, 1, 12))) == PosInfInterval!Date(Date(1999, 1 , 12)));
--------------------
+/
PosInfInterval intersection(in PosInfInterval interval) const pure nothrow
{
return PosInfInterval(_begin < interval._begin ? interval._begin : _begin);
}
/++
Returns the intersection of two intervals
Params:
interval = The interval to intersect with this interval.
Throws:
DateTimeException if the two intervals do not intersect.
Examples:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(NegInfInterval!Date(Date(1999, 7, 6))) == Interval!Date(Date(1996, 1 , 2), Date(1999, 7, 6)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(NegInfInterval!Date(Date(2013, 1, 12))) == Interval!Date(Date(1996, 1 , 2), Date(2013, 1, 12)));
--------------------
+/
Interval!TP intersection(in NegInfInterval!TP interval) const
{
enforce(this.intersects(interval), new DateTimeException(format("%s and %s do not intersect.", this, interval)));
return Interval!TP(_begin, interval._end);
}
/++
Whether the given interval is adjacent to this interval.
Params:
interval = The interval to check whether its adjacent with this
interval.
Throws:
DateTimeException if the given interval is empty.
Examples:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
assert(!PosInfInterval!Date(Date(1999, 1, 12)).isAdjacent(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
--------------------
+/
bool isAdjacent(in Interval!TP interval) const pure
{
interval._enforceNotEmpty();
return _begin == interval._end;
}
/++
Whether the given interval is adjacent to this interval.
Always returns false because two intervals going to positive infinity
can never be adjacent to one another.
Params:
interval = The interval to check whether its adjacent with this
interval.
Examples:
--------------------
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(PosInfInterval!Date(Date(1990, 1, 7))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(PosInfInterval!Date(Date(1996, 1, 2))));
--------------------
+/
bool isAdjacent(in PosInfInterval interval) const pure nothrow
{
return false;
}
/++
Whether the given interval is adjacent to this interval.
Params:
interval = The interval to check whether its adjacent with this
interval.
Examples:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(NegInfInterval!Date(Date(1996, 1, 2))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(NegInfInterval!Date(Date(2000, 7, 1))));
--------------------
+/
bool isAdjacent(in NegInfInterval!TP interval) const pure nothrow
{
return _begin == interval._end;
}
/++
Returns the union of two intervals
Params:
interval = The interval to merge with this interval.
Throws:
DateTimeException if the two intervals do not intersect and are not
adjacent or if the given interval is empty.
Note:
There is no overload for $(D merge()) which takes a NegInfInterval. This
is because you can't have an interval which goes from negative
infinity to positive infinity.
Examples:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) == PosInfInterval!Date(Date(1990, 7 , 6)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) == PosInfInterval!Date(Date(1996, 1 , 2)));
--------------------
+/
PosInfInterval merge(in Interval!TP interval) const
{
enforce(this.isAdjacent(interval) || this.intersects(interval),
new DateTimeException(format("%s and %s are not adjacent and do not intersect.", this, interval)));
return PosInfInterval(_begin < interval._begin ? _begin : interval._begin);
}
/++
Returns the union of two intervals
Params:
interval = The interval to merge with this interval.
Note:
There is no overload for $(D merge()) which takes a NegInfInterval.
This is because you can't have an interval which goes from negative
infinity to positive infinity.
Examples:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(PosInfInterval!Date(Date(1990, 7, 6))) == PosInfInterval!Date(Date(1990, 7 , 6)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(PosInfInterval!Date(Date(1999, 1, 12))) == PosInfInterval!Date(Date(1996, 1 , 2)));
--------------------
+/
PosInfInterval merge(in PosInfInterval interval) const pure nothrow
{
return PosInfInterval(_begin < interval._begin ? _begin : interval._begin);
}
/++
Returns an interval that covers from the earliest time point of two
intervals up to (but not including) the latest time point of two
intervals.
Params:
interval = The interval to create a span together with this
interval.
Throws:
DateTimeException if the given interval is empty.
Note:
There is no overload for $(D span()) which takes a NegInfInterval.
This is because you can't have an interval which goes from negative
infinity to positive infinity.
Examples:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).span(Interval!Date(Date(500, 8, 9), Date(1602, 1, 31))) == PosInfInterval!Date(Date(500, 8, 9)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).span(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) == PosInfInterval!Date(Date(1990, 7 , 6)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).span(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) == PosInfInterval!Date(Date(1996, 1 , 2)));
--------------------
+/
PosInfInterval span(in Interval!TP interval) const pure
{
interval._enforceNotEmpty();
return PosInfInterval(_begin < interval._begin ? _begin : interval._begin);
}
/++
Returns an interval that covers from the earliest time point of two
intervals up to (but not including) the latest time point of two
intervals.
Params:
interval = The interval to create a span together with this interval.
Note:
There is no overload for $(D span()) which takes a NegInfInterval.
This is because you can't have an interval which goes from negative
infinity to positive infinity.
Examples:
--------------------
assert(PosInfInterval!Date(Date(1996, 1, 2)).span(PosInfInterval!Date(Date(1990, 7, 6))) == PosInfInterval!Date(Date(1990, 7 , 6)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).span(PosInfInterval!Date(Date(1999, 1, 12))) == PosInfInterval!Date(Date(1996, 1 , 2)));
--------------------
+/
PosInfInterval span(in PosInfInterval interval) const pure nothrow
{
return PosInfInterval(_begin < interval._begin ? _begin : interval._begin);
}
/++
Shifts the begin of this interval forward or backwards in time by the
given duration (a positive duration shifts the interval forward; a
negative duration shifts it backward). Effectively, it does
$(D begin += duration).
Params:
duration = The duration to shift the interval by.
Examples:
--------------------
auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
interval1.shift(dur!"days"(50));
assert(interval1 == PosInfInterval!Date(Date(1996, 2, 21)));
interval2.shift(dur!"days"(-50));
assert(interval2 == PosInfInterval!Date(Date(1995, 11, 13)));
--------------------
+/
void shift(D)(D duration) pure nothrow
if(__traits(compiles, begin + duration))
{
_begin += duration;
}
static if(__traits(compiles, begin.add!"months"(1)) &&
__traits(compiles, begin.add!"years"(1)))
{
/++
Shifts the begin of this interval forward or backwards in time by
the given number of years and/or months (a positive number of years
and months shifts the interval forward; a negative number shifts it
backward). It adds the years the given years and months to begin.
It effectively calls $(D add!"years"()) and then $(D add!"months"())
on begin the given number of years and months.
Params:
years = The number of years to shift the interval by.
months = The number of months to shift the interval by.
allowOverflow = Whether the days should be allowed to overflow
on begin, causing its month to increment.
Throws:
DateTimeException if empty is true or if the resulting interval
would be invalid.
Examples:
--------------------
auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
interval1.shift(dur!"days"(50));
assert(interval1 == PosInfInterval!Date(Date(1996, 2, 21)));
interval2.shift(dur!"days"(-50));
assert(interval2 == PosInfInterval!Date(Date(1995, 11, 13)));
--------------------
+/
void shift(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
if(isIntegral!T)
{
auto begin = _begin;
begin.add!"years"(years, allowOverflow);
begin.add!"months"(months, allowOverflow);
_begin = begin;
}
}
/++
Expands the interval backwards in time. Effectively, it does
$(D begin -= duration).
Params:
duration = The duration to expand the interval by.
dir = The direction in time to expand the interval.
Examples:
--------------------
auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
interval1.expand(dur!"days"(2));
assert(interval1 == PosInfInterval!Date(Date(1995, 12, 31)));
interval2.expand(dur!"days"(-2));
assert(interval2 == PosInfInterval!Date(Date(1996, 1, 4)));
--------------------
+/
void expand(D)(D duration) pure nothrow
if(__traits(compiles, begin + duration))
{
_begin -= duration;
}
static if(__traits(compiles, begin.add!"months"(1)) &&
__traits(compiles, begin.add!"years"(1)))
{
/++
Expands the interval forwards and/or backwards in time. Effectively,
it subtracts the given number of months/years from begin.
Params:
years = The number of years to expand the interval by.
months = The number of months to expand the interval by.
allowOverflow = Whether the days should be allowed to overflow
on begin, causing its month to increment.
Throws:
DateTimeException if empty is true or if the resulting interval
would be invalid.
Examples:
--------------------
auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
interval1.expand(2);
assert(interval1 == PosInfInterval!Date(Date(1994, 1, 2)));
interval2.expand(-2);
assert(interval2 == PosInfInterval!Date(Date(1998, 1, 2)));
--------------------
+/
void expand(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
if(isIntegral!T)
{
auto begin = _begin;
begin.add!"years"(-years, allowOverflow);
begin.add!"months"(-months, allowOverflow);
_begin = begin;
return;
}
}
/++
Returns a range which iterates forward over the interval, starting
at begin, using $(D func()) to generate each successive time point.
The range's front is the interval's begin. $(D func()) is used
to generate the next front when $(D popFront()) is called. If
$(D popFirst) is true, then $(D popFront()) is called before the
range is returned (so that front is a time point which $(D func())
would generate).
If $(D func()) ever generates a time point less than or equal to the
current front of the range, then a DateTimeException will be thrown.
There are helper functions in this module which generate common delegates
to pass to $(D fwdRange()). Their documentation starts with
"Generates a range-generating function for intervals," so you can easily
search for them.
Params:
func = The function used to generate the time points of the
range over the interval.
popFirst = Whether popFront() should be called on the range before
returning it.
Warning:
func must be logically pure. Ideally, $(D func) would be a function
pointer to a pure function, but forcing func to be pure is far too
restrictive to be useful, and in order to have the ease of use of
having functions which generate functions to pass to $(D fwdRange()),
$(D func) must be a delegate.
If $(D func) retains state which changes as it is called, then some
algorithms will not work correctly, because the range's $(D save)
will have failed to have really saved the range's state. So, if you
want to avoid such bugs, don't pass a delegate which is not
logically pure to $(D fwdRange()). If $(D func) is given the same
time point with two different calls, it must return the same result
both times.
Of course, none of the functions in this module have this problem, so
it's only relevant if you're creating your own delegate.
Examples:
--------------------
auto interval = PosInfInterval!Date(Date(2010, 9, 1));
auto func = (in Date date) //For iterating over even-numbered days.
{
if((date.day & 1) == 0)
return date + dur!"days"(2);
return date + dur!"days"(1);
};
auto range = interval.fwdRange(func);
assert(range.front == Date(2010, 9, 1)); //An odd day. Using PopFirst.yes would have made this Date(2010, 9, 2).
range.popFront();
assert(range.front == Date(2010, 9, 2));
range.popFront();
assert(range.front == Date(2010, 9, 4));
range.popFront();
assert(range.front == Date(2010, 9, 6));
range.popFront();
assert(range.front == Date(2010, 9, 8));
range.popFront();
assert(!range.empty);
--------------------
+/
PosInfIntervalRange!(TP) fwdRange(TP delegate(in TP) func, PopFirst popFirst = PopFirst.no) const
{
auto range = PosInfIntervalRange!(TP)(this, func);
if(popFirst == PopFirst.yes)
range.popFront();
return range;
}
/+
Converts this interval to a string.
+/
//Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
//have versions of toString() with extra modifiers, so we define one version
//with modifiers and one without.
string toString()
{
return _toStringImpl();
}
/++
Converts this interval to a string.
+/
//Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
//have versions of toString() with extra modifiers, so we define one version
//with modifiers and one without.
string toString() const nothrow
{
return _toStringImpl();
}
private:
/++
Since we have two versions of toString(), we have _toStringImpl()
so that they can share implementations.
+/
string _toStringImpl() const nothrow
{
try
return format("[%s - ∞)", _begin);
catch(Exception e)
assert(0, "format() threw.");
}
TP _begin;
}
//Test PosInfInterval's constructor.
unittest
{
PosInfInterval!Date(Date.init);
PosInfInterval!TimeOfDay(TimeOfDay.init);
PosInfInterval!DateTime(DateTime.init);
PosInfInterval!SysTime(SysTime(0));
//Verify Examples.
auto interval = PosInfInterval!Date(Date(1996, 1, 2));
}
//Test PosInfInterval's begin.
unittest
{
assertPred!"=="(PosInfInterval!Date(Date(1, 1, 1)).begin, Date(1, 1, 1));
assertPred!"=="(PosInfInterval!Date(Date(2010, 1, 1)).begin, Date(2010, 1, 1));
assertPred!"=="(PosInfInterval!Date(Date(1997, 12, 31)).begin, Date(1997, 12, 31));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
static assert(__traits(compiles, cPosInfInterval.begin));
static assert(__traits(compiles, iPosInfInterval.begin));
//Verify Examples.
assert(PosInfInterval!Date(Date(1996, 1, 2)).begin == Date(1996, 1, 2));
}
//Test PosInfInterval's empty.
unittest
{
assert(!PosInfInterval!Date(Date(2010, 1, 1)).empty);
assert(!PosInfInterval!TimeOfDay(TimeOfDay(0, 30, 0)).empty);
assert(!PosInfInterval!DateTime(DateTime(2010, 1, 1, 0, 30, 0)).empty);
assert(!PosInfInterval!SysTime(SysTime(DateTime(2010, 1, 1, 0, 30, 0))).empty);
const cPosInfInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iPosInfInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
static assert(__traits(compiles, cPosInfInterval.empty));
static assert(__traits(compiles, iPosInfInterval.empty));
//Verify Examples.
assert(!PosInfInterval!Date(Date(1996, 1, 2)).empty);
}
//Test PosInfInterval's contains(time point).
unittest
{
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
assert(!posInfInterval.contains(Date(2009, 7, 4)));
assert(!posInfInterval.contains(Date(2010, 7, 3)));
assert(posInfInterval.contains(Date(2010, 7, 4)));
assert(posInfInterval.contains(Date(2010, 7, 5)));
assert(posInfInterval.contains(Date(2011, 7, 1)));
assert(posInfInterval.contains(Date(2012, 1, 6)));
assert(posInfInterval.contains(Date(2012, 1, 7)));
assert(posInfInterval.contains(Date(2012, 1, 8)));
assert(posInfInterval.contains(Date(2013, 1, 7)));
const cdate = Date(2010, 7, 6);
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
static assert(__traits(compiles, posInfInterval.contains(cdate)));
static assert(__traits(compiles, cPosInfInterval.contains(cdate)));
static assert(__traits(compiles, iPosInfInterval.contains(cdate)));
//Verify Examples.
assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(Date(1994, 12, 24)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(Date(2000, 1, 5)));
}
//Test PosInfInterval's contains(Interval).
unittest
{
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
static void testInterval(in PosInfInterval!Date posInfInterval, in Interval!Date interval)
{
posInfInterval.contains(interval);
}
assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assert(posInfInterval.contains(posInfInterval));
assert(!posInfInterval.contains(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assert(!posInfInterval.contains(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
assert(!posInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
assert(!posInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
assert(!posInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
assert(!posInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
assert(posInfInterval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
assert(posInfInterval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
assert(posInfInterval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
assert(posInfInterval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
assert(posInfInterval.contains(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
assert(posInfInterval.contains(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assert(!posInfInterval.contains(PosInfInterval!Date(Date(2010, 7, 3))));
assert(posInfInterval.contains(PosInfInterval!Date(Date(2010, 7, 4))));
assert(posInfInterval.contains(PosInfInterval!Date(Date(2010, 7, 5))));
assert(posInfInterval.contains(PosInfInterval!Date(Date(2012, 1, 6))));
assert(posInfInterval.contains(PosInfInterval!Date(Date(2012, 1, 7))));
assert(posInfInterval.contains(PosInfInterval!Date(Date(2012, 1, 8))));
assert(PosInfInterval!Date(Date(2010, 7, 3)).contains(posInfInterval));
assert(PosInfInterval!Date(Date(2010, 7, 4)).contains(posInfInterval));
assert(!PosInfInterval!Date(Date(2010, 7, 5)).contains(posInfInterval));
assert(!PosInfInterval!Date(Date(2012, 1, 6)).contains(posInfInterval));
assert(!PosInfInterval!Date(Date(2012, 1, 7)).contains(posInfInterval));
assert(!PosInfInterval!Date(Date(2012, 1, 8)).contains(posInfInterval));
assert(!posInfInterval.contains(NegInfInterval!Date(Date(2010, 7, 3))));
assert(!posInfInterval.contains(NegInfInterval!Date(Date(2010, 7, 4))));
assert(!posInfInterval.contains(NegInfInterval!Date(Date(2010, 7, 5))));
assert(!posInfInterval.contains(NegInfInterval!Date(Date(2012, 1, 6))));
assert(!posInfInterval.contains(NegInfInterval!Date(Date(2012, 1, 7))));
assert(!posInfInterval.contains(NegInfInterval!Date(Date(2012, 1, 8))));
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, posInfInterval.contains(interval)));
static assert(__traits(compiles, posInfInterval.contains(cInterval)));
static assert(__traits(compiles, posInfInterval.contains(iInterval)));
static assert(__traits(compiles, posInfInterval.contains(posInfInterval)));
static assert(__traits(compiles, posInfInterval.contains(cPosInfInterval)));
static assert(__traits(compiles, posInfInterval.contains(iPosInfInterval)));
static assert(__traits(compiles, posInfInterval.contains(negInfInterval)));
static assert(__traits(compiles, posInfInterval.contains(cNegInfInterval)));
static assert(__traits(compiles, posInfInterval.contains(iNegInfInterval)));
static assert(__traits(compiles, cPosInfInterval.contains(interval)));
static assert(__traits(compiles, cPosInfInterval.contains(cInterval)));
static assert(__traits(compiles, cPosInfInterval.contains(iInterval)));
static assert(__traits(compiles, cPosInfInterval.contains(posInfInterval)));
static assert(__traits(compiles, cPosInfInterval.contains(cPosInfInterval)));
static assert(__traits(compiles, cPosInfInterval.contains(iPosInfInterval)));
static assert(__traits(compiles, cPosInfInterval.contains(negInfInterval)));
static assert(__traits(compiles, cPosInfInterval.contains(cNegInfInterval)));
static assert(__traits(compiles, cPosInfInterval.contains(iNegInfInterval)));
static assert(__traits(compiles, iPosInfInterval.contains(interval)));
static assert(__traits(compiles, iPosInfInterval.contains(cInterval)));
static assert(__traits(compiles, iPosInfInterval.contains(iInterval)));
static assert(__traits(compiles, iPosInfInterval.contains(posInfInterval)));
static assert(__traits(compiles, iPosInfInterval.contains(cPosInfInterval)));
static assert(__traits(compiles, iPosInfInterval.contains(iPosInfInterval)));
static assert(__traits(compiles, iPosInfInterval.contains(negInfInterval)));
static assert(__traits(compiles, iPosInfInterval.contains(cNegInfInterval)));
static assert(__traits(compiles, iPosInfInterval.contains(iNegInfInterval)));
//Verify Examples.
assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
assert(PosInfInterval!Date(Date(1996, 1, 2)).contains(PosInfInterval!Date(Date(1999, 5, 4))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(PosInfInterval!Date(Date(1995, 7, 2))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).contains(NegInfInterval!Date(Date(1996, 5, 4))));
}
//Test PosInfInterval's isBefore(time point).
unittest
{
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
assert(!posInfInterval.isBefore(Date(2009, 7, 3)));
assert(!posInfInterval.isBefore(Date(2010, 7, 3)));
assert(!posInfInterval.isBefore(Date(2010, 7, 4)));
assert(!posInfInterval.isBefore(Date(2010, 7, 5)));
assert(!posInfInterval.isBefore(Date(2011, 7, 1)));
assert(!posInfInterval.isBefore(Date(2012, 1, 6)));
assert(!posInfInterval.isBefore(Date(2012, 1, 7)));
assert(!posInfInterval.isBefore(Date(2012, 1, 8)));
assert(!posInfInterval.isBefore(Date(2013, 1, 7)));
const cdate = Date(2010, 7, 6);
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
static assert(__traits(compiles, posInfInterval.isBefore(cdate)));
static assert(__traits(compiles, cPosInfInterval.isBefore(cdate)));
static assert(__traits(compiles, iPosInfInterval.isBefore(cdate)));
//Verify Examples.
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Date(1994, 12, 24)));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Date(2000, 1, 5)));
}
//Test PosInfInterval's isBefore(Interval).
unittest
{
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
static void testInterval(in PosInfInterval!Date posInfInterval, in Interval!Date interval)
{
posInfInterval.isBefore(interval);
}
assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assert(!posInfInterval.isBefore(posInfInterval));
assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
assert(!posInfInterval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
assert(!posInfInterval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
assert(!posInfInterval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
assert(!posInfInterval.isBefore(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
assert(!posInfInterval.isBefore(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assert(!posInfInterval.isBefore(PosInfInterval!Date(Date(2010, 7, 3))));
assert(!posInfInterval.isBefore(PosInfInterval!Date(Date(2010, 7, 4))));
assert(!posInfInterval.isBefore(PosInfInterval!Date(Date(2010, 7, 5))));
assert(!posInfInterval.isBefore(PosInfInterval!Date(Date(2012, 1, 6))));
assert(!posInfInterval.isBefore(PosInfInterval!Date(Date(2012, 1, 7))));
assert(!posInfInterval.isBefore(PosInfInterval!Date(Date(2012, 1, 8))));
assert(!PosInfInterval!Date(Date(2010, 7, 3)).isBefore(posInfInterval));
assert(!PosInfInterval!Date(Date(2010, 7, 4)).isBefore(posInfInterval));
assert(!PosInfInterval!Date(Date(2010, 7, 5)).isBefore(posInfInterval));
assert(!PosInfInterval!Date(Date(2012, 1, 6)).isBefore(posInfInterval));
assert(!PosInfInterval!Date(Date(2012, 1, 7)).isBefore(posInfInterval));
assert(!PosInfInterval!Date(Date(2012, 1, 8)).isBefore(posInfInterval));
assert(!posInfInterval.isBefore(NegInfInterval!Date(Date(2010, 7, 3))));
assert(!posInfInterval.isBefore(NegInfInterval!Date(Date(2010, 7, 4))));
assert(!posInfInterval.isBefore(NegInfInterval!Date(Date(2010, 7, 5))));
assert(!posInfInterval.isBefore(NegInfInterval!Date(Date(2012, 1, 6))));
assert(!posInfInterval.isBefore(NegInfInterval!Date(Date(2012, 1, 7))));
assert(!posInfInterval.isBefore(NegInfInterval!Date(Date(2012, 1, 8))));
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, posInfInterval.isBefore(interval)));
static assert(__traits(compiles, posInfInterval.isBefore(cInterval)));
static assert(__traits(compiles, posInfInterval.isBefore(iInterval)));
static assert(__traits(compiles, posInfInterval.isBefore(posInfInterval)));
static assert(__traits(compiles, posInfInterval.isBefore(cPosInfInterval)));
static assert(__traits(compiles, posInfInterval.isBefore(iPosInfInterval)));
static assert(__traits(compiles, posInfInterval.isBefore(negInfInterval)));
static assert(__traits(compiles, posInfInterval.isBefore(cNegInfInterval)));
static assert(__traits(compiles, posInfInterval.isBefore(iNegInfInterval)));
static assert(__traits(compiles, cPosInfInterval.isBefore(interval)));
static assert(__traits(compiles, cPosInfInterval.isBefore(cInterval)));
static assert(__traits(compiles, cPosInfInterval.isBefore(iInterval)));
static assert(__traits(compiles, cPosInfInterval.isBefore(posInfInterval)));
static assert(__traits(compiles, cPosInfInterval.isBefore(cPosInfInterval)));
static assert(__traits(compiles, cPosInfInterval.isBefore(iPosInfInterval)));
static assert(__traits(compiles, cPosInfInterval.isBefore(negInfInterval)));
static assert(__traits(compiles, cPosInfInterval.isBefore(cNegInfInterval)));
static assert(__traits(compiles, cPosInfInterval.isBefore(iNegInfInterval)));
static assert(__traits(compiles, iPosInfInterval.isBefore(interval)));
static assert(__traits(compiles, iPosInfInterval.isBefore(cInterval)));
static assert(__traits(compiles, iPosInfInterval.isBefore(iInterval)));
static assert(__traits(compiles, iPosInfInterval.isBefore(posInfInterval)));
static assert(__traits(compiles, iPosInfInterval.isBefore(cPosInfInterval)));
static assert(__traits(compiles, iPosInfInterval.isBefore(iPosInfInterval)));
static assert(__traits(compiles, iPosInfInterval.isBefore(negInfInterval)));
static assert(__traits(compiles, iPosInfInterval.isBefore(cNegInfInterval)));
static assert(__traits(compiles, iPosInfInterval.isBefore(iNegInfInterval)));
//Verify Examples.
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(PosInfInterval!Date(Date(1992, 5, 4))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(PosInfInterval!Date(Date(2013, 3, 7))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isBefore(NegInfInterval!Date(Date(1996, 5, 4))));
}
//Test PosInfInterval's isAfter(time point).
unittest
{
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
assert(posInfInterval.isAfter(Date(2009, 7, 3)));
assert(posInfInterval.isAfter(Date(2010, 7, 3)));
assert(!posInfInterval.isAfter(Date(2010, 7, 4)));
assert(!posInfInterval.isAfter(Date(2010, 7, 5)));
assert(!posInfInterval.isAfter(Date(2011, 7, 1)));
assert(!posInfInterval.isAfter(Date(2012, 1, 6)));
assert(!posInfInterval.isAfter(Date(2012, 1, 7)));
assert(!posInfInterval.isAfter(Date(2012, 1, 8)));
assert(!posInfInterval.isAfter(Date(2013, 1, 7)));
const cdate = Date(2010, 7, 6);
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
static assert(__traits(compiles, posInfInterval.isAfter(cdate)));
static assert(__traits(compiles, cPosInfInterval.isAfter(cdate)));
static assert(__traits(compiles, iPosInfInterval.isAfter(cdate)));
//Verify Examples.
assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Date(1994, 12, 24)));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Date(2000, 1, 5)));
}
//Test PosInfInterval's isAfter(Interval).
unittest
{
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
static void testInterval(in PosInfInterval!Date posInfInterval, in Interval!Date interval)
{
posInfInterval.isAfter(interval);
}
assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assert(!posInfInterval.isAfter(posInfInterval));
assert(posInfInterval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assert(!posInfInterval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
assert(posInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
assert(!posInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
assert(!posInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
assert(!posInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
assert(!posInfInterval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
assert(!posInfInterval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
assert(!posInfInterval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
assert(!posInfInterval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
assert(!posInfInterval.isAfter(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
assert(!posInfInterval.isAfter(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assert(!posInfInterval.isAfter(PosInfInterval!Date(Date(2010, 7, 3))));
assert(!posInfInterval.isAfter(PosInfInterval!Date(Date(2010, 7, 4))));
assert(!posInfInterval.isAfter(PosInfInterval!Date(Date(2010, 7, 5))));
assert(!posInfInterval.isAfter(PosInfInterval!Date(Date(2012, 1, 6))));
assert(!posInfInterval.isAfter(PosInfInterval!Date(Date(2012, 1, 7))));
assert(!posInfInterval.isAfter(PosInfInterval!Date(Date(2012, 1, 8))));
assert(!PosInfInterval!Date(Date(2010, 7, 3)).isAfter(posInfInterval));
assert(!PosInfInterval!Date(Date(2010, 7, 4)).isAfter(posInfInterval));
assert(!PosInfInterval!Date(Date(2010, 7, 5)).isAfter(posInfInterval));
assert(!PosInfInterval!Date(Date(2012, 1, 6)).isAfter(posInfInterval));
assert(!PosInfInterval!Date(Date(2012, 1, 7)).isAfter(posInfInterval));
assert(!PosInfInterval!Date(Date(2012, 1, 8)).isAfter(posInfInterval));
assert(posInfInterval.isAfter(NegInfInterval!Date(Date(2010, 7, 3))));
assert(posInfInterval.isAfter(NegInfInterval!Date(Date(2010, 7, 4))));
assert(!posInfInterval.isAfter(NegInfInterval!Date(Date(2010, 7, 5))));
assert(!posInfInterval.isAfter(NegInfInterval!Date(Date(2012, 1, 6))));
assert(!posInfInterval.isAfter(NegInfInterval!Date(Date(2012, 1, 7))));
assert(!posInfInterval.isAfter(NegInfInterval!Date(Date(2012, 1, 8))));
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, posInfInterval.isAfter(interval)));
static assert(__traits(compiles, posInfInterval.isAfter(cInterval)));
static assert(__traits(compiles, posInfInterval.isAfter(iInterval)));
static assert(__traits(compiles, posInfInterval.isAfter(posInfInterval)));
static assert(__traits(compiles, posInfInterval.isAfter(cPosInfInterval)));
static assert(__traits(compiles, posInfInterval.isAfter(iPosInfInterval)));
static assert(__traits(compiles, posInfInterval.isAfter(negInfInterval)));
static assert(__traits(compiles, posInfInterval.isAfter(cNegInfInterval)));
static assert(__traits(compiles, posInfInterval.isAfter(iNegInfInterval)));
static assert(__traits(compiles, cPosInfInterval.isAfter(interval)));
static assert(__traits(compiles, cPosInfInterval.isAfter(cInterval)));
static assert(__traits(compiles, cPosInfInterval.isAfter(iInterval)));
static assert(__traits(compiles, cPosInfInterval.isAfter(posInfInterval)));
static assert(__traits(compiles, cPosInfInterval.isAfter(cPosInfInterval)));
static assert(__traits(compiles, cPosInfInterval.isAfter(iPosInfInterval)));
static assert(__traits(compiles, cPosInfInterval.isAfter(negInfInterval)));
static assert(__traits(compiles, cPosInfInterval.isAfter(cNegInfInterval)));
static assert(__traits(compiles, cPosInfInterval.isAfter(iNegInfInterval)));
static assert(__traits(compiles, iPosInfInterval.isAfter(interval)));
static assert(__traits(compiles, iPosInfInterval.isAfter(cInterval)));
static assert(__traits(compiles, iPosInfInterval.isAfter(iInterval)));
static assert(__traits(compiles, iPosInfInterval.isAfter(posInfInterval)));
static assert(__traits(compiles, iPosInfInterval.isAfter(cPosInfInterval)));
static assert(__traits(compiles, iPosInfInterval.isAfter(iPosInfInterval)));
static assert(__traits(compiles, iPosInfInterval.isAfter(negInfInterval)));
static assert(__traits(compiles, iPosInfInterval.isAfter(cNegInfInterval)));
static assert(__traits(compiles, iPosInfInterval.isAfter(iNegInfInterval)));
//Verify Examples.
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(PosInfInterval!Date(Date(1990, 1, 7))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(PosInfInterval!Date(Date(1999, 5, 4))));
assert(PosInfInterval!Date(Date(1996, 1, 2)).isAfter(NegInfInterval!Date(Date(1996, 1, 2))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAfter(NegInfInterval!Date(Date(2000, 7, 1))));
}
//Test PosInfInterval's intersects().
unittest
{
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
static void testInterval(in PosInfInterval!Date posInfInterval, in Interval!Date interval)
{
posInfInterval.intersects(interval);
}
assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assert(posInfInterval.intersects(posInfInterval));
assert(!posInfInterval.intersects(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assert(posInfInterval.intersects(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
assert(!posInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
assert(posInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
assert(posInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
assert(posInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
assert(posInfInterval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
assert(posInfInterval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
assert(posInfInterval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
assert(posInfInterval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
assert(posInfInterval.intersects(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
assert(posInfInterval.intersects(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assert(posInfInterval.intersects(PosInfInterval!Date(Date(2010, 7, 3))));
assert(posInfInterval.intersects(PosInfInterval!Date(Date(2010, 7, 4))));
assert(posInfInterval.intersects(PosInfInterval!Date(Date(2010, 7, 5))));
assert(posInfInterval.intersects(PosInfInterval!Date(Date(2012, 1, 6))));
assert(posInfInterval.intersects(PosInfInterval!Date(Date(2012, 1, 7))));
assert(posInfInterval.intersects(PosInfInterval!Date(Date(2012, 1, 8))));
assert(PosInfInterval!Date(Date(2010, 7, 3)).intersects(posInfInterval));
assert(PosInfInterval!Date(Date(2010, 7, 4)).intersects(posInfInterval));
assert(PosInfInterval!Date(Date(2010, 7, 5)).intersects(posInfInterval));
assert(PosInfInterval!Date(Date(2012, 1, 6)).intersects(posInfInterval));
assert(PosInfInterval!Date(Date(2012, 1, 7)).intersects(posInfInterval));
assert(PosInfInterval!Date(Date(2012, 1, 8)).intersects(posInfInterval));
assert(!posInfInterval.intersects(NegInfInterval!Date(Date(2010, 7, 3))));
assert(!posInfInterval.intersects(NegInfInterval!Date(Date(2010, 7, 4))));
assert(posInfInterval.intersects(NegInfInterval!Date(Date(2010, 7, 5))));
assert(posInfInterval.intersects(NegInfInterval!Date(Date(2012, 1, 6))));
assert(posInfInterval.intersects(NegInfInterval!Date(Date(2012, 1, 7))));
assert(posInfInterval.intersects(NegInfInterval!Date(Date(2012, 1, 8))));
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, posInfInterval.intersects(interval)));
static assert(__traits(compiles, posInfInterval.intersects(cInterval)));
static assert(__traits(compiles, posInfInterval.intersects(iInterval)));
static assert(__traits(compiles, posInfInterval.intersects(posInfInterval)));
static assert(__traits(compiles, posInfInterval.intersects(cPosInfInterval)));
static assert(__traits(compiles, posInfInterval.intersects(iPosInfInterval)));
static assert(__traits(compiles, posInfInterval.intersects(negInfInterval)));
static assert(__traits(compiles, posInfInterval.intersects(cNegInfInterval)));
static assert(__traits(compiles, posInfInterval.intersects(iNegInfInterval)));
static assert(__traits(compiles, cPosInfInterval.intersects(interval)));
static assert(__traits(compiles, cPosInfInterval.intersects(cInterval)));
static assert(__traits(compiles, cPosInfInterval.intersects(iInterval)));
static assert(__traits(compiles, cPosInfInterval.intersects(posInfInterval)));
static assert(__traits(compiles, cPosInfInterval.intersects(cPosInfInterval)));
static assert(__traits(compiles, cPosInfInterval.intersects(iPosInfInterval)));
static assert(__traits(compiles, cPosInfInterval.intersects(negInfInterval)));
static assert(__traits(compiles, cPosInfInterval.intersects(cNegInfInterval)));
static assert(__traits(compiles, cPosInfInterval.intersects(iNegInfInterval)));
static assert(__traits(compiles, iPosInfInterval.intersects(interval)));
static assert(__traits(compiles, iPosInfInterval.intersects(cInterval)));
static assert(__traits(compiles, iPosInfInterval.intersects(iInterval)));
static assert(__traits(compiles, iPosInfInterval.intersects(posInfInterval)));
static assert(__traits(compiles, iPosInfInterval.intersects(cPosInfInterval)));
static assert(__traits(compiles, iPosInfInterval.intersects(iPosInfInterval)));
static assert(__traits(compiles, iPosInfInterval.intersects(negInfInterval)));
static assert(__traits(compiles, iPosInfInterval.intersects(cNegInfInterval)));
static assert(__traits(compiles, iPosInfInterval.intersects(iNegInfInterval)));
//Verify Examples.
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).intersects(Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(PosInfInterval!Date(Date(1990, 1, 7))));
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(PosInfInterval!Date(Date(1999, 5, 4))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).intersects(NegInfInterval!Date(Date(1996, 1, 2))));
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersects(NegInfInterval!Date(Date(2000, 7, 1))));
}
//Test PosInfInterval's intersection().
unittest
{
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
static void testInterval(I, J)(in I interval1, in J interval2)
{
interval1.intersection(interval2);
}
assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
assertThrown!DateTimeException(testInterval(posInfInterval, NegInfInterval!Date(Date(2010, 7, 3))));
assertThrown!DateTimeException(testInterval(posInfInterval, NegInfInterval!Date(Date(2010, 7, 4))));
assertPred!"=="(posInfInterval.intersection(posInfInterval),
posInfInterval);
assertPred!"=="(posInfInterval.intersection(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))),
Interval!Date(Date(2010, 7, 4), Date(2013, 7, 3)));
assertPred!"=="(posInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))),
Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)));
assertPred!"=="(posInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assertPred!"=="(posInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
assertPred!"=="(posInfInterval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))),
Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)));
assertPred!"=="(posInfInterval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))),
Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)));
assertPred!"=="(posInfInterval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))),
Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
assertPred!"=="(posInfInterval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))),
Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8)));
assertPred!"=="(posInfInterval.intersection(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))),
Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8)));
assertPred!"=="(posInfInterval.intersection(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))),
Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9)));
assertPred!"=="(posInfInterval.intersection(PosInfInterval!Date(Date(2010, 7, 3))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(posInfInterval.intersection(PosInfInterval!Date(Date(2010, 7, 4))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(posInfInterval.intersection(PosInfInterval!Date(Date(2010, 7, 5))),
PosInfInterval!Date(Date(2010, 7, 5)));
assertPred!"=="(posInfInterval.intersection(PosInfInterval!Date(Date(2012, 1, 6))),
PosInfInterval!Date(Date(2012, 1, 6)));
assertPred!"=="(posInfInterval.intersection(PosInfInterval!Date(Date(2012, 1, 7))),
PosInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(posInfInterval.intersection(PosInfInterval!Date(Date(2012, 1, 8))),
PosInfInterval!Date(Date(2012, 1, 8)));
assertPred!"=="(PosInfInterval!Date(Date(2010, 7, 3)).intersection(posInfInterval),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(PosInfInterval!Date(Date(2010, 7, 4)).intersection(posInfInterval),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(PosInfInterval!Date(Date(2010, 7, 5)).intersection(posInfInterval),
PosInfInterval!Date(Date(2010, 7, 5)));
assertPred!"=="(PosInfInterval!Date(Date(2012, 1, 6)).intersection(posInfInterval),
PosInfInterval!Date(Date(2012, 1, 6)));
assertPred!"=="(PosInfInterval!Date(Date(2012, 1, 7)).intersection(posInfInterval),
PosInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(PosInfInterval!Date(Date(2012, 1, 8)).intersection(posInfInterval),
PosInfInterval!Date(Date(2012, 1, 8)));
assertPred!"=="(posInfInterval.intersection(NegInfInterval!Date(Date(2010, 7, 5))),
Interval!Date(Date(2010, 7, 4), Date(2010, 7, 5)));
assertPred!"=="(posInfInterval.intersection(NegInfInterval!Date(Date(2012, 1, 6))),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 6)));
assertPred!"=="(posInfInterval.intersection(NegInfInterval!Date(Date(2012, 1, 7))),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)));
assertPred!"=="(posInfInterval.intersection(NegInfInterval!Date(Date(2012, 1, 8))),
Interval!Date(Date(2010, 7, 4), Date(2012, 1, 8)));
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, posInfInterval.intersection(interval)));
static assert(__traits(compiles, posInfInterval.intersection(cInterval)));
static assert(__traits(compiles, posInfInterval.intersection(iInterval)));
static assert(__traits(compiles, posInfInterval.intersection(posInfInterval)));
static assert(__traits(compiles, posInfInterval.intersection(cPosInfInterval)));
static assert(__traits(compiles, posInfInterval.intersection(iPosInfInterval)));
static assert(__traits(compiles, posInfInterval.intersection(negInfInterval)));
static assert(__traits(compiles, posInfInterval.intersection(cNegInfInterval)));
static assert(__traits(compiles, posInfInterval.intersection(iNegInfInterval)));
static assert(__traits(compiles, cPosInfInterval.intersection(interval)));
static assert(__traits(compiles, cPosInfInterval.intersection(cInterval)));
static assert(__traits(compiles, cPosInfInterval.intersection(iInterval)));
static assert(__traits(compiles, cPosInfInterval.intersection(posInfInterval)));
static assert(__traits(compiles, cPosInfInterval.intersection(cPosInfInterval)));
static assert(__traits(compiles, cPosInfInterval.intersection(iPosInfInterval)));
static assert(__traits(compiles, cPosInfInterval.intersection(negInfInterval)));
static assert(__traits(compiles, cPosInfInterval.intersection(cNegInfInterval)));
static assert(__traits(compiles, cPosInfInterval.intersection(iNegInfInterval)));
static assert(__traits(compiles, iPosInfInterval.intersection(interval)));
static assert(__traits(compiles, iPosInfInterval.intersection(cInterval)));
static assert(__traits(compiles, iPosInfInterval.intersection(iInterval)));
static assert(__traits(compiles, iPosInfInterval.intersection(posInfInterval)));
static assert(__traits(compiles, iPosInfInterval.intersection(cPosInfInterval)));
static assert(__traits(compiles, iPosInfInterval.intersection(iPosInfInterval)));
static assert(__traits(compiles, iPosInfInterval.intersection(negInfInterval)));
static assert(__traits(compiles, iPosInfInterval.intersection(cNegInfInterval)));
static assert(__traits(compiles, iPosInfInterval.intersection(iNegInfInterval)));
//Verify Examples.
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) == Interval!Date(Date(1996, 1 , 2), Date(2000, 8, 2)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) == Interval!Date(Date(1999, 1 , 12), Date(2011, 9, 17)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(PosInfInterval!Date(Date(1990, 7, 6))) == PosInfInterval!Date(Date(1996, 1 , 2)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(PosInfInterval!Date(Date(1999, 1, 12))) == PosInfInterval!Date(Date(1999, 1 , 12)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(NegInfInterval!Date(Date(1999, 7, 6))) == Interval!Date(Date(1996, 1 , 2), Date(1999, 7, 6)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).intersection(NegInfInterval!Date(Date(2013, 1, 12))) == Interval!Date(Date(1996, 1 , 2), Date(2013, 1, 12)));
}
//Test PosInfInterval's isAdjacent().
unittest
{
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
static void testInterval(in PosInfInterval!Date posInfInterval, in Interval!Date interval)
{
posInfInterval.isAdjacent(interval);
}
assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assert(!posInfInterval.isAdjacent(posInfInterval));
assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
assert(posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
assert(!posInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
assert(!posInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
assert(!posInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
assert(!posInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
assert(!posInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assert(!posInfInterval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 3))));
assert(!posInfInterval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 4))));
assert(!posInfInterval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 5))));
assert(!posInfInterval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 6))));
assert(!posInfInterval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 7))));
assert(!posInfInterval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 8))));
assert(!PosInfInterval!Date(Date(2010, 7, 3)).isAdjacent(posInfInterval));
assert(!PosInfInterval!Date(Date(2010, 7, 4)).isAdjacent(posInfInterval));
assert(!PosInfInterval!Date(Date(2010, 7, 5)).isAdjacent(posInfInterval));
assert(!PosInfInterval!Date(Date(2012, 1, 6)).isAdjacent(posInfInterval));
assert(!PosInfInterval!Date(Date(2012, 1, 7)).isAdjacent(posInfInterval));
assert(!PosInfInterval!Date(Date(2012, 1, 8)).isAdjacent(posInfInterval));
assert(!posInfInterval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 3))));
assert(posInfInterval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 4))));
assert(!posInfInterval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 5))));
assert(!posInfInterval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 6))));
assert(!posInfInterval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 7))));
assert(!posInfInterval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 8))));
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, posInfInterval.isAdjacent(interval)));
static assert(__traits(compiles, posInfInterval.isAdjacent(cInterval)));
static assert(__traits(compiles, posInfInterval.isAdjacent(iInterval)));
static assert(__traits(compiles, posInfInterval.isAdjacent(posInfInterval)));
static assert(__traits(compiles, posInfInterval.isAdjacent(cPosInfInterval)));
static assert(__traits(compiles, posInfInterval.isAdjacent(iPosInfInterval)));
static assert(__traits(compiles, posInfInterval.isAdjacent(negInfInterval)));
static assert(__traits(compiles, posInfInterval.isAdjacent(cNegInfInterval)));
static assert(__traits(compiles, posInfInterval.isAdjacent(iNegInfInterval)));
static assert(__traits(compiles, cPosInfInterval.isAdjacent(interval)));
static assert(__traits(compiles, cPosInfInterval.isAdjacent(cInterval)));
static assert(__traits(compiles, cPosInfInterval.isAdjacent(iInterval)));
static assert(__traits(compiles, cPosInfInterval.isAdjacent(posInfInterval)));
static assert(__traits(compiles, cPosInfInterval.isAdjacent(cPosInfInterval)));
static assert(__traits(compiles, cPosInfInterval.isAdjacent(iPosInfInterval)));
static assert(__traits(compiles, cPosInfInterval.isAdjacent(negInfInterval)));
static assert(__traits(compiles, cPosInfInterval.isAdjacent(cNegInfInterval)));
static assert(__traits(compiles, cPosInfInterval.isAdjacent(iNegInfInterval)));
static assert(__traits(compiles, iPosInfInterval.isAdjacent(interval)));
static assert(__traits(compiles, iPosInfInterval.isAdjacent(cInterval)));
static assert(__traits(compiles, iPosInfInterval.isAdjacent(iInterval)));
static assert(__traits(compiles, iPosInfInterval.isAdjacent(posInfInterval)));
static assert(__traits(compiles, iPosInfInterval.isAdjacent(cPosInfInterval)));
static assert(__traits(compiles, iPosInfInterval.isAdjacent(iPosInfInterval)));
static assert(__traits(compiles, iPosInfInterval.isAdjacent(negInfInterval)));
static assert(__traits(compiles, iPosInfInterval.isAdjacent(cNegInfInterval)));
static assert(__traits(compiles, iPosInfInterval.isAdjacent(iNegInfInterval)));
//Verify Examples.
assert(PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(Interval!Date(Date(1989, 3, 1), Date(1996, 1, 2))));
assert(!PosInfInterval!Date(Date(1999, 1, 12)).isAdjacent(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(PosInfInterval!Date(Date(1990, 1, 7))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(PosInfInterval!Date(Date(1996, 1, 2))));
assert(PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(NegInfInterval!Date(Date(1996, 1, 2))));
assert(!PosInfInterval!Date(Date(1996, 1, 2)).isAdjacent(NegInfInterval!Date(Date(2000, 7, 1))));
}
//Test PosInfInterval's merge().
unittest
{
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
static void testInterval(in PosInfInterval!Date posInfInterval, in Interval!Date interval)
{
posInfInterval.merge(interval);
}
assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assertPred!"=="(posInfInterval.merge(posInfInterval),
posInfInterval);
assertPred!"=="(posInfInterval.merge(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))),
PosInfInterval!Date(Date(2010, 7, 1)));
assertPred!"=="(posInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))),
PosInfInterval!Date(Date(2010, 7, 3)));
assertPred!"=="(posInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))),
PosInfInterval!Date(Date(2010, 7, 3)));
assertPred!"=="(posInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))),
PosInfInterval!Date(Date(2010, 7, 3)));
assertPred!"=="(posInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))),
PosInfInterval!Date(Date(2010, 7, 3)));
assertPred!"=="(posInfInterval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(posInfInterval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(posInfInterval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(posInfInterval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(posInfInterval.merge(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(posInfInterval.merge(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(posInfInterval.merge(PosInfInterval!Date(Date(2010, 7, 3))),
PosInfInterval!Date(Date(2010, 7, 3)));
assertPred!"=="(posInfInterval.merge(PosInfInterval!Date(Date(2010, 7, 4))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(posInfInterval.merge(PosInfInterval!Date(Date(2010, 7, 5))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(posInfInterval.merge(PosInfInterval!Date(Date(2012, 1, 6))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(posInfInterval.merge(PosInfInterval!Date(Date(2012, 1, 7))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(posInfInterval.merge(PosInfInterval!Date(Date(2012, 1, 8))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(PosInfInterval!Date(Date(2010, 7, 3)).merge(posInfInterval),
PosInfInterval!Date(Date(2010, 7, 3)));
assertPred!"=="(PosInfInterval!Date(Date(2010, 7, 4)).merge(posInfInterval),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(PosInfInterval!Date(Date(2010, 7, 5)).merge(posInfInterval),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(PosInfInterval!Date(Date(2012, 1, 6)).merge(posInfInterval),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(PosInfInterval!Date(Date(2012, 1, 7)).merge(posInfInterval),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(PosInfInterval!Date(Date(2012, 1, 8)).merge(posInfInterval),
PosInfInterval!Date(Date(2010, 7, 4)));
static assert(!__traits(compiles, posInfInterval.merge(NegInfInterval!Date(Date(2010, 7, 3)))));
static assert(!__traits(compiles, posInfInterval.merge(NegInfInterval!Date(Date(2010, 7, 4)))));
static assert(!__traits(compiles, posInfInterval.merge(NegInfInterval!Date(Date(2010, 7, 5)))));
static assert(!__traits(compiles, posInfInterval.merge(NegInfInterval!Date(Date(2012, 1, 6)))));
static assert(!__traits(compiles, posInfInterval.merge(NegInfInterval!Date(Date(2012, 1, 7)))));
static assert(!__traits(compiles, posInfInterval.merge(NegInfInterval!Date(Date(2012, 1, 8)))));
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, posInfInterval.merge(interval)));
static assert(__traits(compiles, posInfInterval.merge(cInterval)));
static assert(__traits(compiles, posInfInterval.merge(iInterval)));
static assert(__traits(compiles, posInfInterval.merge(posInfInterval)));
static assert(__traits(compiles, posInfInterval.merge(cPosInfInterval)));
static assert(__traits(compiles, posInfInterval.merge(iPosInfInterval)));
static assert(!__traits(compiles, posInfInterval.merge(negInfInterval)));
static assert(!__traits(compiles, posInfInterval.merge(cNegInfInterval)));
static assert(!__traits(compiles, posInfInterval.merge(iNegInfInterval)));
static assert(__traits(compiles, cPosInfInterval.merge(interval)));
static assert(__traits(compiles, cPosInfInterval.merge(cInterval)));
static assert(__traits(compiles, cPosInfInterval.merge(iInterval)));
static assert(__traits(compiles, cPosInfInterval.merge(posInfInterval)));
static assert(__traits(compiles, cPosInfInterval.merge(cPosInfInterval)));
static assert(__traits(compiles, cPosInfInterval.merge(iPosInfInterval)));
static assert(!__traits(compiles, cPosInfInterval.merge(negInfInterval)));
static assert(!__traits(compiles, cPosInfInterval.merge(cNegInfInterval)));
static assert(!__traits(compiles, cPosInfInterval.merge(iNegInfInterval)));
static assert(__traits(compiles, iPosInfInterval.merge(interval)));
static assert(__traits(compiles, iPosInfInterval.merge(cInterval)));
static assert(__traits(compiles, iPosInfInterval.merge(iInterval)));
static assert(__traits(compiles, iPosInfInterval.merge(posInfInterval)));
static assert(__traits(compiles, iPosInfInterval.merge(cPosInfInterval)));
static assert(__traits(compiles, iPosInfInterval.merge(iPosInfInterval)));
static assert(!__traits(compiles, iPosInfInterval.merge(negInfInterval)));
static assert(!__traits(compiles, iPosInfInterval.merge(cNegInfInterval)));
static assert(!__traits(compiles, iPosInfInterval.merge(iNegInfInterval)));
//Verify Examples.
assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) == PosInfInterval!Date(Date(1990, 7 , 6)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) == PosInfInterval!Date(Date(1996, 1 , 2)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(PosInfInterval!Date(Date(1990, 7, 6))) == PosInfInterval!Date(Date(1990, 7 , 6)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).merge(PosInfInterval!Date(Date(1999, 1, 12))) == PosInfInterval!Date(Date(1996, 1 , 2)));
}
//Test PosInfInterval's span().
unittest
{
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
static void testInterval(in PosInfInterval!Date posInfInterval, in Interval!Date interval)
{
posInfInterval.span(interval);
}
assertThrown!DateTimeException(testInterval(posInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertPred!"=="(posInfInterval.span(posInfInterval),
posInfInterval);
assertPred!"=="(posInfInterval.span(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))),
PosInfInterval!Date(Date(2010, 7, 1)));
assertPred!"=="(posInfInterval.span(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))),
PosInfInterval!Date(Date(2010, 7, 1)));
assertPred!"=="(posInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))),
PosInfInterval!Date(Date(2010, 7, 3)));
assertPred!"=="(posInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))),
PosInfInterval!Date(Date(2010, 7, 3)));
assertPred!"=="(posInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))),
PosInfInterval!Date(Date(2010, 7, 3)));
assertPred!"=="(posInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))),
PosInfInterval!Date(Date(2010, 7, 3)));
assertPred!"=="(posInfInterval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(posInfInterval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(posInfInterval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(posInfInterval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(posInfInterval.span(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(posInfInterval.span(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(posInfInterval.span(PosInfInterval!Date(Date(2010, 7, 3))),
PosInfInterval!Date(Date(2010, 7, 3)));
assertPred!"=="(posInfInterval.span(PosInfInterval!Date(Date(2010, 7, 4))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(posInfInterval.span(PosInfInterval!Date(Date(2010, 7, 5))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(posInfInterval.span(PosInfInterval!Date(Date(2012, 1, 6))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(posInfInterval.span(PosInfInterval!Date(Date(2012, 1, 7))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(posInfInterval.span(PosInfInterval!Date(Date(2012, 1, 8))),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(PosInfInterval!Date(Date(2010, 7, 3)).span(posInfInterval),
PosInfInterval!Date(Date(2010, 7, 3)));
assertPred!"=="(PosInfInterval!Date(Date(2010, 7, 4)).span(posInfInterval),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(PosInfInterval!Date(Date(2010, 7, 5)).span(posInfInterval),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(PosInfInterval!Date(Date(2012, 1, 6)).span(posInfInterval),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(PosInfInterval!Date(Date(2012, 1, 7)).span(posInfInterval),
PosInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(PosInfInterval!Date(Date(2012, 1, 8)).span(posInfInterval),
PosInfInterval!Date(Date(2010, 7, 4)));
static assert(!__traits(compiles, posInfInterval.span(NegInfInterval!Date(Date(2010, 7, 3)))));
static assert(!__traits(compiles, posInfInterval.span(NegInfInterval!Date(Date(2010, 7, 4)))));
static assert(!__traits(compiles, posInfInterval.span(NegInfInterval!Date(Date(2010, 7, 5)))));
static assert(!__traits(compiles, posInfInterval.span(NegInfInterval!Date(Date(2012, 1, 6)))));
static assert(!__traits(compiles, posInfInterval.span(NegInfInterval!Date(Date(2012, 1, 7)))));
static assert(!__traits(compiles, posInfInterval.span(NegInfInterval!Date(Date(2012, 1, 8)))));
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, posInfInterval.span(interval)));
static assert(__traits(compiles, posInfInterval.span(cInterval)));
static assert(__traits(compiles, posInfInterval.span(iInterval)));
static assert(__traits(compiles, posInfInterval.span(posInfInterval)));
static assert(__traits(compiles, posInfInterval.span(cPosInfInterval)));
static assert(__traits(compiles, posInfInterval.span(iPosInfInterval)));
static assert(!__traits(compiles, posInfInterval.span(negInfInterval)));
static assert(!__traits(compiles, posInfInterval.span(cNegInfInterval)));
static assert(!__traits(compiles, posInfInterval.span(iNegInfInterval)));
static assert(__traits(compiles, cPosInfInterval.span(interval)));
static assert(__traits(compiles, cPosInfInterval.span(cInterval)));
static assert(__traits(compiles, cPosInfInterval.span(iInterval)));
static assert(__traits(compiles, cPosInfInterval.span(posInfInterval)));
static assert(__traits(compiles, cPosInfInterval.span(cPosInfInterval)));
static assert(__traits(compiles, cPosInfInterval.span(iPosInfInterval)));
static assert(!__traits(compiles, cPosInfInterval.span(negInfInterval)));
static assert(!__traits(compiles, cPosInfInterval.span(cNegInfInterval)));
static assert(!__traits(compiles, cPosInfInterval.span(iNegInfInterval)));
static assert(__traits(compiles, iPosInfInterval.span(interval)));
static assert(__traits(compiles, iPosInfInterval.span(cInterval)));
static assert(__traits(compiles, iPosInfInterval.span(iInterval)));
static assert(__traits(compiles, iPosInfInterval.span(posInfInterval)));
static assert(__traits(compiles, iPosInfInterval.span(cPosInfInterval)));
static assert(__traits(compiles, iPosInfInterval.span(iPosInfInterval)));
static assert(!__traits(compiles, iPosInfInterval.span(negInfInterval)));
static assert(!__traits(compiles, iPosInfInterval.span(cNegInfInterval)));
static assert(!__traits(compiles, iPosInfInterval.span(iNegInfInterval)));
//Verify Examples.
assert(PosInfInterval!Date(Date(1996, 1, 2)).span(Interval!Date(Date(500, 8, 9), Date(1602, 1, 31))) == PosInfInterval!Date(Date(500, 8, 9)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).span(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) == PosInfInterval!Date(Date(1990, 7 , 6)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).span(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))) == PosInfInterval!Date(Date(1996, 1 , 2)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).span(PosInfInterval!Date(Date(1990, 7, 6))) == PosInfInterval!Date(Date(1990, 7 , 6)));
assert(PosInfInterval!Date(Date(1996, 1, 2)).span(PosInfInterval!Date(Date(1999, 1, 12))) == PosInfInterval!Date(Date(1996, 1 , 2)));
}
//Test PosInfInterval's shift().
unittest
{
auto interval = PosInfInterval!Date(Date(2010, 7, 4));
static void testInterval(I)(I interval, in Duration duration, in I expected, size_t line = __LINE__)
{
interval.shift(duration);
assertPred!"=="(interval, expected, "", __FILE__, line);
}
testInterval(interval, dur!"days"(22), PosInfInterval!Date(Date(2010, 7, 26)));
testInterval(interval, dur!"days"(-22), PosInfInterval!Date(Date(2010, 6, 12)));
const cInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iInterval = PosInfInterval!Date(Date(2010, 7, 4));
static assert(!__traits(compiles, cInterval.shift(dur!"days"(5))));
static assert(!__traits(compiles, iInterval.shift(dur!"days"(5))));
//Verify Examples.
auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
interval1.shift(dur!"days"(50));
assert(interval1 == PosInfInterval!Date(Date(1996, 2, 21)));
interval2.shift(dur!"days"(-50));
assert(interval2 == PosInfInterval!Date(Date(1995, 11, 13)));
}
//Test PosInfInterval's shift(int, int, AllowDayOverflow).
unittest
{
{
auto interval = PosInfInterval!Date(Date(2010, 7, 4));
static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow, in I expected, size_t line = __LINE__)
{
interval.shift(years, months, allow);
assertPred!"=="(interval, expected, "", __FILE__, line);
}
testInterval(interval, 5, 0, AllowDayOverflow.yes, PosInfInterval!Date(Date(2015, 7, 4)));
testInterval(interval, -5, 0, AllowDayOverflow.yes, PosInfInterval!Date(Date(2005, 7, 4)));
auto interval2 = PosInfInterval!Date(Date(2000, 1, 29));
testInterval(interval2, 1, 1, AllowDayOverflow.yes, PosInfInterval!Date(Date(2001, 3, 1)));
testInterval(interval2, 1, -1, AllowDayOverflow.yes, PosInfInterval!Date(Date(2000, 12, 29)));
testInterval(interval2, -1, -1, AllowDayOverflow.yes, PosInfInterval!Date(Date(1998, 12, 29)));
testInterval(interval2, -1, 1, AllowDayOverflow.yes, PosInfInterval!Date(Date(1999, 3, 1)));
testInterval(interval2, 1, 1, AllowDayOverflow.no, PosInfInterval!Date(Date(2001, 2, 28)));
testInterval(interval2, 1, -1, AllowDayOverflow.no, PosInfInterval!Date(Date(2000, 12, 29)));
testInterval(interval2, -1, -1, AllowDayOverflow.no, PosInfInterval!Date(Date(1998, 12, 29)));
testInterval(interval2, -1, 1, AllowDayOverflow.no, PosInfInterval!Date(Date(1999, 2, 28)));
}
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
static assert(!__traits(compiles, cPosInfInterval.shift(1)));
static assert(!__traits(compiles, iPosInfInterval.shift(1)));
//Verify Examples.
auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
interval1.shift(2);
assert(interval1 == PosInfInterval!Date(Date(1998, 1, 2)));
interval2.shift(-2);
assert(interval2 == PosInfInterval!Date(Date(1994, 1, 2)));
}
//Test PosInfInterval's expand().
unittest
{
auto interval = PosInfInterval!Date(Date(2000, 7, 4));
static void testInterval(I)(I interval, in Duration duration, in I expected, size_t line = __LINE__)
{
interval.expand(duration);
assertPred!"=="(interval, expected, "", __FILE__, line);
}
testInterval(interval, dur!"days"(22), PosInfInterval!Date(Date(2000, 6, 12)));
testInterval(interval, dur!"days"(-22), PosInfInterval!Date(Date(2000, 7, 26)));
const cInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iInterval = PosInfInterval!Date(Date(2010, 7, 4));
static assert(!__traits(compiles, cInterval.expand(dur!"days"(5))));
static assert(!__traits(compiles, iInterval.expand(dur!"days"(5))));
//Verify Examples.
auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
interval1.expand(dur!"days"(2));
assert(interval1 == PosInfInterval!Date(Date(1995, 12, 31)));
interval2.expand(dur!"days"(-2));
assert(interval2 == PosInfInterval!Date(Date(1996, 1, 4)));
}
//Test PosInfInterval's expand(int, int, AllowDayOverflow).
unittest
{
{
auto interval = PosInfInterval!Date(Date(2000, 7, 4));
static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow, in I expected, size_t line = __LINE__)
{
interval.expand(years, months, allow);
assertPred!"=="(interval, expected, "", __FILE__, line);
}
testInterval(interval, 5, 0, AllowDayOverflow.yes, PosInfInterval!Date(Date(1995, 7, 4)));
testInterval(interval, -5, 0, AllowDayOverflow.yes, PosInfInterval!Date(Date(2005, 7, 4)));
auto interval2 = PosInfInterval!Date(Date(2000, 1, 29));
testInterval(interval2, 1, 1, AllowDayOverflow.yes, PosInfInterval!Date(Date(1998, 12, 29)));
testInterval(interval2, 1, -1, AllowDayOverflow.yes, PosInfInterval!Date(Date(1999, 3, 1)));
testInterval(interval2, -1, -1, AllowDayOverflow.yes, PosInfInterval!Date(Date(2001, 3, 1)));
testInterval(interval2, -1, 1, AllowDayOverflow.yes, PosInfInterval!Date(Date(2000, 12, 29)));
testInterval(interval2, 1, 1, AllowDayOverflow.no, PosInfInterval!Date(Date(1998, 12, 29)));
testInterval(interval2, 1, -1, AllowDayOverflow.no, PosInfInterval!Date(Date(1999, 2, 28)));
testInterval(interval2, -1, -1, AllowDayOverflow.no, PosInfInterval!Date(Date(2001, 2, 28)));
testInterval(interval2, -1, 1, AllowDayOverflow.no, PosInfInterval!Date(Date(2000, 12, 29)));
}
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
static assert(!__traits(compiles, cPosInfInterval.expand(1)));
static assert(!__traits(compiles, iPosInfInterval.expand(1)));
//Verify Examples.
auto interval1 = PosInfInterval!Date(Date(1996, 1, 2));
auto interval2 = PosInfInterval!Date(Date(1996, 1, 2));
interval1.expand(2);
assert(interval1 == PosInfInterval!Date(Date(1994, 1, 2)));
interval2.expand(-2);
assert(interval2 == PosInfInterval!Date(Date(1998, 1, 2)));
}
//Test PosInfInterval's fwdRange().
unittest
{
auto posInfInterval = PosInfInterval!Date(Date(2010, 9, 19));
static void testInterval(PosInfInterval!Date posInfInterval)
{
posInfInterval.fwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).popFront();
}
assertThrown!DateTimeException(testInterval(posInfInterval));
assertPred!"=="(PosInfInterval!Date(Date(2010, 9, 12)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri)).front,
Date(2010, 9, 12));
assertPred!"=="(PosInfInterval!Date(Date(2010, 9, 12)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri), PopFirst.yes).front,
Date(2010, 9, 17));
//Verify Examples.
auto interval = PosInfInterval!Date(Date(2010, 9, 1));
auto func = (in Date date)
{
if((date.day & 1) == 0)
return date + dur!"days"(2);
return date + dur!"days"(1);
};
auto range = interval.fwdRange(func);
assert(range.front == Date(2010, 9, 1)); //An odd day. Using PopFirst.yes would have made this Date(2010, 9, 2).
range.popFront();
assert(range.front == Date(2010, 9, 2));
range.popFront();
assert(range.front == Date(2010, 9, 4));
range.popFront();
assert(range.front == Date(2010, 9, 6));
range.popFront();
assert(range.front == Date(2010, 9, 8));
range.popFront();
assert(!range.empty);
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
static assert(__traits(compiles, cPosInfInterval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri))));
static assert(__traits(compiles, iPosInfInterval.fwdRange(everyDayOfWeek!Date(DayOfWeek.fri))));
}
//Test PosInfInterval's toString().
unittest
{
assertPred!"=="(PosInfInterval!Date(Date(2010, 7, 4)).toString(), "[2010-Jul-04 - ∞)");
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
static assert(__traits(compiles, cPosInfInterval.toString()));
static assert(__traits(compiles, iPosInfInterval.toString()));
}
/++
Represents an interval of time which has negative infinity as its begin point.
Any ranges which iterate over a $(D NegInfInterval) are infinite. So, the
main purpose of using $(D NegInfInterval) is to create an infinite range
which starts at negative infinity and goes to a fixed end point. You would
then iterate over it in reverse.
+/
struct NegInfInterval(TP)
{
public:
/++
Params:
begin = The time point which begins the interval.
Examples:
--------------------
auto interval = PosInfInterval!Date(Date(1996, 1, 2));
--------------------
+/
this(in TP end) pure nothrow
{
_end = cast(TP)end;
}
/++
Params:
rhs = The NegInfInterval to assign to this one.
+/
/+ref+/ NegInfInterval opAssign(const ref NegInfInterval rhs) pure nothrow
{
_end = cast(TP)rhs._end;
return this;
}
/++
Params:
rhs = The NegInfInterval to assign to this one.
+/
/+ref+/ NegInfInterval opAssign(NegInfInterval rhs) pure nothrow
{
_end = cast(TP)rhs._end;
return this;
}
/++
The end point of the interval. It is excluded from the interval.
Examples:
--------------------
assert(NegInfInterval!Date(Date(2012, 3, 1)).end == Date(2012, 3, 1));
--------------------
+/
@property TP end() const pure nothrow
{
return cast(TP)_end;
}
/++
The end point of the interval. It is excluded from the interval.
Params:
timePoint = The time point to set end to.
+/
@property void end(TP timePoint) pure nothrow
{
_end = timePoint;
}
/++
Whether the interval's length is 0. Always returns false.
Examples:
--------------------
assert(!NegInfInterval!Date(Date(1996, 1, 2)).empty);
--------------------
+/
@property bool empty() const pure nothrow
{
return false;
}
/++
Whether the given time point is within this interval.
Params:
timePoint = The time point to check for inclusion in this interval.
Examples:
--------------------
assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Date(1994, 12, 24)));
assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Date(2000, 1, 5)));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(Date(2012, 3, 1)));
--------------------
+/
bool contains(TP timePoint) const pure nothrow
{
return timePoint < _end;
}
/++
Whether the given interval is completely within this interval.
Params:
interval = The interval to check for inclusion in this interval.
Throws:
DateTimeException if the given interval is empty.
Examples:
--------------------
assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
--------------------
+/
bool contains(in Interval!TP interval) const pure
{
interval._enforceNotEmpty();
return interval._end <= _end;
}
/++
Whether the given interval is completely within this interval.
Always returns false because an interval beginning at negative infinity
can never contain an interval going to positive infinity.
Params:
interval = The interval to check for inclusion in this interval.
Examples:
--------------------
assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(PosInfInterval!Date(Date(1999, 5, 4))));
--------------------
+/
bool contains(in PosInfInterval!TP interval) const pure nothrow
{
return false;
}
/++
Whether the given interval is completely within this interval.
Params:
interval = The interval to check for inclusion in this interval.
Examples:
--------------------
assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(NegInfInterval!Date(Date(1996, 5, 4))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(NegInfInterval!Date(Date(2013, 7, 9))));
--------------------
+/
bool contains(in NegInfInterval interval) const pure nothrow
{
return interval._end <= _end;
}
/++
Whether this interval is before the given time point.
Params:
timePoint = The time point to check whether this interval is
before it.
Examples:
--------------------
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Date(1994, 12, 24)));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Date(2000, 1, 5)));
assert(NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Date(2012, 3, 1)));
--------------------
+/
bool isBefore(in TP timePoint) const pure nothrow
{
return timePoint >= _end;
}
/++
Whether this interval is before the given interval and does not
intersect with it.
Params:
interval = The interval to check for against this interval.
Throws:
DateTimeException if the given interval is empty
Examples:
--------------------
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
--------------------
+/
bool isBefore(in Interval!TP interval) const pure
{
interval._enforceNotEmpty();
return _end <= interval._begin;
}
/++
Whether this interval is before the given interval and does not
intersect with it.
Params:
interval = The interval to check for against this interval.
Examples:
--------------------
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(PosInfInterval!Date(Date(1999, 5, 4))));
assert(NegInfInterval!Date(Date(2012, 3, 1)).isBefore(PosInfInterval!Date(Date(2012, 3, 1))));
--------------------
+/
bool isBefore(in PosInfInterval!TP interval) const pure nothrow
{
return _end <= interval._begin;
}
/++
Whether this interval is before the given interval and does not
intersect with it.
Always returns false because an interval beginning at negative
infinity can never be before another interval beginning at negative
infinity.
Params:
interval = The interval to check for against this interval.
Examples:
--------------------
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(NegInfInterval!Date(Date(1996, 5, 4))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(NegInfInterval!Date(Date(2013, 7, 9))));
--------------------
+/
bool isBefore(in NegInfInterval interval) const pure nothrow
{
return false;
}
/++
Whether this interval is after the given time point.
Always returns false because an interval begginning at negative infinity
can never be after any time point.
Params:
timePoint = The time point to check whether this Interval is after it.
Examples:
--------------------
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Date(1994, 12, 24)));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Date(2000, 1, 5)));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Date(2012, 3, 1)));
--------------------
+/
bool isAfter(in TP timePoint) const pure nothrow
{
return false;
}
/++
Whether this interval is after the given interval and does not
intersect with it.
Always returns false (unless the given interval is empty) because an
interval beginning at negative infinity can never be after any other
interval.
Params:
interval = The interval to check against this interval.
Throws:
DateTimeException if the given interval is empty.
Examples:
--------------------
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
--------------------
+/
bool isAfter(in Interval!TP interval) const pure
{
interval._enforceNotEmpty();
return false;
}
/++
Whether this interval is after the given interval and does not intersect
with it.
Always returns false because an interval beginning at negative infinity
can never be after any other interval.
Params:
interval = The interval to check against this interval.
Examples:
--------------------
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(PosInfInterval!Date(Date(1999, 5, 4))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(PosInfInterval!Date(Date(2012, 3, 1))));
--------------------
+/
bool isAfter(in PosInfInterval!TP interval) const pure nothrow
{
return false;
}
/++
Whether this interval is after the given interval and does not intersect
with it.
Always returns false because an interval beginning at negative infinity
can never be after any other interval.
Params:
interval = The interval to check against this interval.
Examples:
--------------------
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(NegInfInterval!Date(Date(1996, 5, 4))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(NegInfInterval!Date(Date(2013, 7, 9))));
--------------------
+/
bool isAfter(in NegInfInterval interval) const pure nothrow
{
return false;
}
/++
Whether the given interval overlaps with this interval.
Params:
interval = The interval to check for intersection with this interval.
Throws:
DateTimeException if the given interval is empty.
Examples:
--------------------
assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).intersects(Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
--------------------
+/
bool intersects(in Interval!TP interval) const pure
{
interval._enforceNotEmpty();
return interval._begin < _end;
}
/++
Whether the given interval overlaps with this interval.
Params:
interval = The interval to check for intersection with this interval.
Examples:
--------------------
assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(PosInfInterval!Date(Date(1999, 5, 4))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).intersects(PosInfInterval!Date(Date(2012, 3, 1))));
--------------------
+/
bool intersects(in PosInfInterval!TP interval) const pure nothrow
{
return interval._begin < _end;
}
/++
Whether the given interval overlaps with this interval.
Always returns true because two intervals beginning at negative infinity
always overlap.
Params:
interval = The interval to check for intersection with this interval.
Examples:
--------------------
assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(NegInfInterval!Date(Date(1996, 5, 4))));
assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(NegInfInterval!Date(Date(2013, 7, 9))));
--------------------
+/
bool intersects(in NegInfInterval!TP interval) const pure nothrow
{
return true;
}
/++
Returns the intersection of two intervals
Params:
interval = The interval to intersect with this interval.
Throws:
DateTimeException if the two intervals do not intersect or if the
given interval is empty.
Examples:
--------------------
assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) == Interval!Date(Date(1990, 7 , 6), Date(2000, 8, 2)));
assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(Interval!Date(Date(1999, 1, 12), Date(2015, 9, 2))) == Interval!Date(Date(1999, 1 , 12), Date(2012, 3, 1)));
--------------------
+/
Interval!TP intersection(in Interval!TP interval) const
{
enforce(this.intersects(interval), new DateTimeException(format("%s and %s do not intersect.", this, interval)));
auto end = _end < interval._end ? _end : interval._end;
return Interval!TP(interval._begin, end);
}
/++
Returns the intersection of two intervals
Params:
interval = The interval to intersect with this interval.
Throws:
DateTimeException if the two intervals do not intersect.
Examples:
--------------------
assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(PosInfInterval!Date(Date(1990, 7, 6))) == Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(PosInfInterval!Date(Date(1999, 1, 12))) == Interval!Date(Date(1999, 1 , 12), Date(2012, 3, 1)));
--------------------
+/
Interval!TP intersection(in PosInfInterval!TP interval) const
{
enforce(this.intersects(interval), new DateTimeException(format("%s and %s do not intersect.", this, interval)));
return Interval!TP(interval._begin, _end);
}
/++
Returns the intersection of two intervals
Params:
interval = The interval to intersect with this interval.
Examples:
--------------------
assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(NegInfInterval!Date(Date(1999, 7, 6))) == NegInfInterval!Date(Date(1999, 7 , 6)));
assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(NegInfInterval!Date(Date(2013, 1, 12))) == NegInfInterval!Date(Date(2012, 3 , 1)));
--------------------
+/
NegInfInterval intersection(in NegInfInterval interval) const nothrow
{
return NegInfInterval(_end < interval._end ? _end : interval._end);
}
/++
Whether the given interval is adjacent to this interval.
Params:
interval = The interval to check whether its adjacent with this
interval.
Throws:
DateTimeException if the given interval is empty.
Examples:
--------------------
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(1999, 1, 12), Date(2012, 3, 1))));
assert(NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(2012, 3, 1), Date(2019, 2, 2))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
--------------------
+/
bool isAdjacent(in Interval!TP interval) const pure
{
interval._enforceNotEmpty();
return interval._begin == _end;
}
/++
Whether the given interval is adjacent to this interval.
Params:
interval = The interval to check whether its adjacent with this
interval.
Examples:
--------------------
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(PosInfInterval!Date(Date(1999, 5, 4))));
assert(NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(PosInfInterval!Date(Date(2012, 3, 1))));
--------------------
+/
bool isAdjacent(in PosInfInterval!TP interval) const pure nothrow
{
return interval._begin == _end;
}
/++
Whether the given interval is adjacent to this interval.
Always returns false because two intervals beginning at negative
infinity can never be adjacent to one another.
Params:
interval = The interval to check whether its adjacent with this
interval.
Examples:
--------------------
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(NegInfInterval!Date(Date(1996, 5, 4))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(NegInfInterval!Date(Date(2012, 3, 1))));
--------------------
+/
bool isAdjacent(in NegInfInterval interval) const pure nothrow
{
return false;
}
/++
Returns the union of two intervals
Params:
interval = The interval to merge with this interval.
Throws:
DateTimeException if the two intervals do not intersect and are
not adjacent or if the given interval is empty.
Note:
There is no overload for $(D merge()) which takes a PosInfInterval.
This is because you can't have an interval which goes from negative
infinity to positive infinity.
Examples:
--------------------
assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) == NegInfInterval!Date(Date(2012, 3 , 1)));
assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(Interval!Date(Date(1999, 1, 12), Date(2015, 9, 2))) == NegInfInterval!Date(Date(2015, 9 , 2)));
--------------------
+/
NegInfInterval merge(in Interval!TP interval) const
{
enforce(this.isAdjacent(interval) || this.intersects(interval),
new DateTimeException(format("%s and %s are not adjacent and do not intersect.", this, interval)));
return NegInfInterval(_end > interval._end ? _end : interval._end);
}
/++
Returns the union of two intervals
Params:
interval = The interval to merge with this interval.
Note:
There is no overload for $(D merge()) which takes a PosInfInterval.
This is because you can't have an interval which goes from negative
infinity to positive infinity.
Examples:
--------------------
assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(NegInfInterval!Date(Date(1999, 7, 6))) == NegInfInterval!Date(Date(2012, 3 , 1)));
assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(NegInfInterval!Date(Date(2013, 1, 12))) == NegInfInterval!Date(Date(2013, 1 , 12)));
--------------------
+/
NegInfInterval merge(in NegInfInterval interval) const pure nothrow
{
return NegInfInterval(_end > interval._end ? _end : interval._end);
}
/++
Returns an interval that covers from the earliest time point of two
intervals up to (but not including) the latest time point of two
intervals.
Params:
interval = The interval to create a span together with this
interval.
Throws:
DateTimeException if the given interval is empty.
Note:
There is no overload for $(D span()) which takes a PosInfInterval.
This is because you can't have an interval which goes from negative
infinity to positive infinity.
Examples:
--------------------
assert(NegInfInterval!Date(Date(2012, 3, 1)).span(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) == NegInfInterval!Date(Date(2012, 3 , 1)));
assert(NegInfInterval!Date(Date(2012, 3, 1)).span(Interval!Date(Date(1999, 1, 12), Date(2015, 9, 2))) == NegInfInterval!Date(Date(2015, 9 , 2)));
assert(NegInfInterval!Date(Date(1600, 1, 7)).span(Interval!Date(Date(2012, 3, 11), Date(2017, 7, 1))) == NegInfInterval!Date(Date(2017, 7 , 1)));
--------------------
+/
NegInfInterval span(in Interval!TP interval) const pure
{
interval._enforceNotEmpty();
return NegInfInterval(_end > interval._end ? _end : interval._end);
}
/++
Returns an interval that covers from the earliest time point of two
intervals up to (but not including) the latest time point of two
intervals.
Params:
interval = The interval to create a span together with this interval.
Note:
There is no overload for $(D span()) which takes a PosInfInterval.
This is because you can't have an interval which goes from negative
infinity to positive infinity.
Examples:
--------------------
assert(NegInfInterval!Date(Date(2012, 3, 1)).span(NegInfInterval!Date(Date(1999, 7, 6))) == NegInfInterval!Date(Date(2012, 3 , 1)));
assert(NegInfInterval!Date(Date(2012, 3, 1)).span(NegInfInterval!Date(Date(2013, 1, 12))) == NegInfInterval!Date(Date(2013, 1 , 12)));
--------------------
+/
NegInfInterval span(in NegInfInterval interval) const pure nothrow
{
return NegInfInterval(_end > interval._end ? _end : interval._end);
}
/++
Shifts the end of this interval forward or backwards in time by the
given duration (a positive duration shifts the interval forward; a
negative duration shifts it backward). Effectively, it does
$(D end += duration).
Params:
duration = The duration to shift the interval by.
Examples:
--------------------
auto interval1 = NegInfInterval!Date(Date(2012, 4, 5));
auto interval2 = NegInfInterval!Date(Date(2012, 4, 5));
interval1.shift(dur!"days"(50));
assert(interval1 == NegInfInterval!Date(Date(2012, 5, 25)));
interval2.shift(dur!"days"(-50));
assert(interval2 == NegInfInterval!Date( Date(2012, 2, 15)));
--------------------
+/
void shift(D)(D duration) pure nothrow
if(__traits(compiles, end + duration))
{
_end += duration;
}
static if(__traits(compiles, end.add!"months"(1)) &&
__traits(compiles, end.add!"years"(1)))
{
/++
Shifts the end of this interval forward or backwards in time by the
given number of years and/or months (a positive number of years and
months shifts the interval forward; a negative number shifts it
backward). It adds the years the given years and months to end. It
effectively calls $(D add!"years"()) and then $(D add!"months"())
on end with the given number of years and months.
Params:
years = The number of years to shift the interval by.
months = The number of months to shift the interval by.
allowOverflow = Whether the days should be allowed to overflow on end, causing its month to increment.
Throws:
DateTimeException if empty is true or if the resulting interval would be invalid.
Examples:
--------------------
auto interval1 = NegInfInterval!Date(Date(2012, 3, 1));
auto interval2 = NegInfInterval!Date(Date(2012, 3, 1));
interval1.shift(2);
assert(interval1 == NegInfInterval!Date(Date(2014, 3, 1)));
interval2.shift(-2);
assert(interval2 == NegInfInterval!Date(Date(2010, 3, 1)));
--------------------
+/
void shift(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
if(isIntegral!T)
{
auto end = _end;
end.add!"years"(years, allowOverflow);
end.add!"months"(months, allowOverflow);
_end = end;
}
}
/++
Expands the interval forwards in time. Effectively, it does
$(D end += duration).
Params:
duration = The duration to expand the interval by.
dir = The direction in time to expand the interval.
Examples:
--------------------
auto interval1 = NegInfInterval!Date(Date(2012, 3, 1));
auto interval2 = NegInfInterval!Date(Date(2012, 3, 1));
interval1.expand(dur!"days"(2));
assert(interval1 == NegInfInterval!Date(Date(2012, 3, 3)));
interval2.expand(dur!"days"(-2));
assert(interval2 == NegInfInterval!Date(Date(2012, 2, 28)));
--------------------
+/
void expand(D)(D duration) pure nothrow
if(__traits(compiles, end + duration))
{
_end += duration;
}
static if(__traits(compiles, end.add!"months"(1)) &&
__traits(compiles, end.add!"years"(1)))
{
/++
Expands the interval forwards and/or backwards in time. Effectively,
it adds the given number of months/years to end.
Params:
years = The number of years to expand the interval by.
months = The number of months to expand the interval by.
allowOverflow = Whether the days should be allowed to overflow
on end, causing their month to increment.
Throws:
DateTimeException if empty is true or if the resulting interval
would be invalid.
Examples:
--------------------
auto interval1 = NegInfInterval!Date(Date(2012, 3, 1));
auto interval2 = NegInfInterval!Date(Date(2012, 3, 1));
interval1.expand(2);
assert(interval1 == NegInfInterval!Date(Date(2014, 3, 1)));
interval2.expand(-2);
assert(interval2 == NegInfInterval!Date(Date(2010, 3, 1)));
--------------------
+/
void expand(T)(T years, T months = 0, AllowDayOverflow allowOverflow = AllowDayOverflow.yes)
if(isIntegral!T)
{
auto end = _end;
end.add!"years"(years, allowOverflow);
end.add!"months"(months, allowOverflow);
_end = end;
return;
}
}
/++
Returns a range which iterates backwards over the interval, starting
at end, using $(D func()) to generate each successive time point.
The range's front is the interval's end. $(D func) is used to generate
the next front when $(D popFront()) is called. If $(D popFirst)
is true, then $(D popFront()) is called before the range is returned
(so that front is a time point which $(D func()) would generate).
If $(D func()) ever generates a time point less than or equal to the
current front of the range, then a DateTimeException will be thrown.
There are helper functions in this module which generate common delegates
to pass to $(D bwdRange()). Their documentation starts with
"Generates a range-generating function for intervals," so you can easily
search for them.
Params:
func = The function used to generate the time points of the
range over the interval.
popFirst = Whether popFront() should be called on the range before
returning it.
Warning:
func must be logically pure. Ideally, $(D func) would be a function
pointer to a pure function, but forcing func to be pure is far too
restrictive to be useful, and in order to have the ease of use of
having functions which generate functions to pass to $(D fwdRange()),
$(D func) must be a delegate.
If $(D func) retains state which changes as it is called, then some
algorithms will not work correctly, because the range's $(D save)
will have failed to have really saved the range's state. So, if you
want to avoid such bugs, don't pass a delegate which is not
logically pure to $(D fwdRange()). If $(D func) is given the same
time point with two different calls, it must return the same result
both times.
Of course, none of the functions in this module have this problem, so
it's only relevant if you're creating your own delegate.
Examples:
--------------------
auto interval = NegInfInterval!Date(Date(2010, 9, 9));
auto func = (in Date date) //For iterating over even-numbered days.
{
if((date.day & 1) == 0)
return date - dur!"days"(2);
return date - dur!"days"(1);
};
auto range = interval.bwdRange(func);
assert(range.front == Date(2010, 9, 9)); //An odd day. Using PopFirst.yes would have made this Date(2010, 9, 8).
range.popFront();
assert(range.front == Date(2010, 9, 8));
range.popFront();
assert(range.front == Date(2010, 9, 6));
range.popFront();
assert(range.front == Date(2010, 9, 4));
range.popFront();
assert(range.front == Date(2010, 9, 2));
range.popFront();
assert(!range.empty);
--------------------
+/
NegInfIntervalRange!(TP) bwdRange(TP delegate(in TP) func, PopFirst popFirst = PopFirst.no) const
{
auto range = NegInfIntervalRange!(TP)(this, func);
if(popFirst == PopFirst.yes)
range.popFront();
return range;
}
/+
Converts this interval to a string.
+/
//Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
//have versions of toString() with extra modifiers, so we define one version
//with modifiers and one without.
string toString()
{
return _toStringImpl();
}
/++
Converts this interval to a string.
+/
//Due to bug http://d.puremagic.com/issues/show_bug.cgi?id=3715 , we can't
//have versions of toString() with extra modifiers, so we define one version
//with modifiers and one without.
string toString() const nothrow
{
return _toStringImpl();
}
private:
/++
Since we have two versions of toString(), we have _toStringImpl()
so that they can share implementations.
+/
string _toStringImpl() const nothrow
{
try
return format("[-∞ - %s)", _end);
catch(Exception e)
assert(0, "format() threw.");
}
TP _end;
}
//Test NegInfInterval's constructor.
unittest
{
NegInfInterval!Date(Date.init);
NegInfInterval!TimeOfDay(TimeOfDay.init);
NegInfInterval!DateTime(DateTime.init);
NegInfInterval!SysTime(SysTime(0));
}
//Test NegInfInterval's end.
unittest
{
assertPred!"=="(NegInfInterval!Date(Date(2010, 1, 1)).end, Date(2010, 1, 1));
assertPred!"=="(NegInfInterval!Date(Date(2010, 1, 1)).end, Date(2010, 1, 1));
assertPred!"=="(NegInfInterval!Date(Date(1998, 1, 1)).end, Date(1998, 1, 1));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, cNegInfInterval.end));
static assert(__traits(compiles, iNegInfInterval.end));
//Verify Examples.
assert(NegInfInterval!Date(Date(2012, 3, 1)).end == Date(2012, 3, 1));
}
//Test NegInfInterval's empty.
unittest
{
assert(!NegInfInterval!Date(Date(2010, 1, 1)).empty);
assert(!NegInfInterval!TimeOfDay(TimeOfDay(0, 30, 0)).empty);
assert(!NegInfInterval!DateTime(DateTime(2010, 1, 1, 0, 30, 0)).empty);
assert(!NegInfInterval!SysTime(SysTime(DateTime(2010, 1, 1, 0, 30, 0))).empty);
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, cNegInfInterval.empty));
static assert(__traits(compiles, iNegInfInterval.empty));
//Verify Examples.
assert(!NegInfInterval!Date(Date(1996, 1, 2)).empty);
}
//Test NegInfInterval's contains(time point).
unittest
{
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
assert(negInfInterval.contains(Date(2009, 7, 4)));
assert(negInfInterval.contains(Date(2010, 7, 3)));
assert(negInfInterval.contains(Date(2010, 7, 4)));
assert(negInfInterval.contains(Date(2010, 7, 5)));
assert(negInfInterval.contains(Date(2011, 7, 1)));
assert(negInfInterval.contains(Date(2012, 1, 6)));
assert(!negInfInterval.contains(Date(2012, 1, 7)));
assert(!negInfInterval.contains(Date(2012, 1, 8)));
assert(!negInfInterval.contains(Date(2013, 1, 7)));
const cdate = Date(2010, 7, 6);
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, negInfInterval.contains(cdate)));
static assert(__traits(compiles, cNegInfInterval.contains(cdate)));
static assert(__traits(compiles, iNegInfInterval.contains(cdate)));
//Verify Examples.
assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Date(1994, 12, 24)));
assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Date(2000, 1, 5)));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(Date(2012, 3, 1)));
}
//Test NegInfInterval's contains(Interval).
unittest
{
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static void testInterval(in NegInfInterval!Date negInfInterval, in Interval!Date interval)
{
negInfInterval.contains(interval);
}
assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assert(negInfInterval.contains(negInfInterval));
assert(negInfInterval.contains(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assert(!negInfInterval.contains(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
assert(negInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
assert(negInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
assert(negInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
assert(!negInfInterval.contains(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
assert(negInfInterval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
assert(negInfInterval.contains(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
assert(negInfInterval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
assert(!negInfInterval.contains(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
assert(!negInfInterval.contains(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
assert(!negInfInterval.contains(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assert(negInfInterval.contains(NegInfInterval!Date(Date(2010, 7, 3))));
assert(negInfInterval.contains(NegInfInterval!Date(Date(2010, 7, 4))));
assert(negInfInterval.contains(NegInfInterval!Date(Date(2010, 7, 5))));
assert(negInfInterval.contains(NegInfInterval!Date(Date(2012, 1, 6))));
assert(negInfInterval.contains(NegInfInterval!Date(Date(2012, 1, 7))));
assert(!negInfInterval.contains(NegInfInterval!Date(Date(2012, 1, 8))));
assert(!NegInfInterval!Date(Date(2010, 7, 3)).contains(negInfInterval));
assert(!NegInfInterval!Date(Date(2010, 7, 4)).contains(negInfInterval));
assert(!NegInfInterval!Date(Date(2010, 7, 5)).contains(negInfInterval));
assert(!NegInfInterval!Date(Date(2012, 1, 6)).contains(negInfInterval));
assert(NegInfInterval!Date(Date(2012, 1, 7)).contains(negInfInterval));
assert(NegInfInterval!Date(Date(2012, 1, 8)).contains(negInfInterval));
assert(!negInfInterval.contains(PosInfInterval!Date(Date(2010, 7, 3))));
assert(!negInfInterval.contains(PosInfInterval!Date(Date(2010, 7, 4))));
assert(!negInfInterval.contains(PosInfInterval!Date(Date(2010, 7, 5))));
assert(!negInfInterval.contains(PosInfInterval!Date(Date(2012, 1, 6))));
assert(!negInfInterval.contains(PosInfInterval!Date(Date(2012, 1, 7))));
assert(!negInfInterval.contains(PosInfInterval!Date(Date(2012, 1, 8))));
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, negInfInterval.contains(interval)));
static assert(__traits(compiles, negInfInterval.contains(cInterval)));
static assert(__traits(compiles, negInfInterval.contains(iInterval)));
static assert(__traits(compiles, negInfInterval.contains(posInfInterval)));
static assert(__traits(compiles, negInfInterval.contains(cPosInfInterval)));
static assert(__traits(compiles, negInfInterval.contains(iPosInfInterval)));
static assert(__traits(compiles, negInfInterval.contains(negInfInterval)));
static assert(__traits(compiles, negInfInterval.contains(cNegInfInterval)));
static assert(__traits(compiles, negInfInterval.contains(iNegInfInterval)));
static assert(__traits(compiles, cNegInfInterval.contains(interval)));
static assert(__traits(compiles, cNegInfInterval.contains(cInterval)));
static assert(__traits(compiles, cNegInfInterval.contains(iInterval)));
static assert(__traits(compiles, cNegInfInterval.contains(posInfInterval)));
static assert(__traits(compiles, cNegInfInterval.contains(cPosInfInterval)));
static assert(__traits(compiles, cNegInfInterval.contains(iPosInfInterval)));
static assert(__traits(compiles, cNegInfInterval.contains(negInfInterval)));
static assert(__traits(compiles, cNegInfInterval.contains(cNegInfInterval)));
static assert(__traits(compiles, cNegInfInterval.contains(iNegInfInterval)));
static assert(__traits(compiles, iNegInfInterval.contains(interval)));
static assert(__traits(compiles, iNegInfInterval.contains(cInterval)));
static assert(__traits(compiles, iNegInfInterval.contains(iInterval)));
static assert(__traits(compiles, iNegInfInterval.contains(posInfInterval)));
static assert(__traits(compiles, iNegInfInterval.contains(cPosInfInterval)));
static assert(__traits(compiles, iNegInfInterval.contains(iPosInfInterval)));
static assert(__traits(compiles, iNegInfInterval.contains(negInfInterval)));
static assert(__traits(compiles, iNegInfInterval.contains(cNegInfInterval)));
static assert(__traits(compiles, iNegInfInterval.contains(iNegInfInterval)));
//Verify Examples.
assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(Interval!Date(Date(1998, 2, 28), Date(2013, 5, 1))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(PosInfInterval!Date(Date(1999, 5, 4))));
assert(NegInfInterval!Date(Date(2012, 3, 1)).contains(NegInfInterval!Date(Date(1996, 5, 4))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).contains(NegInfInterval!Date(Date(2013, 7, 9))));
}
//Test NegInfInterval's isBefore(time point).
unittest
{
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
assert(!negInfInterval.isBefore(Date(2009, 7, 4)));
assert(!negInfInterval.isBefore(Date(2010, 7, 3)));
assert(!negInfInterval.isBefore(Date(2010, 7, 4)));
assert(!negInfInterval.isBefore(Date(2010, 7, 5)));
assert(!negInfInterval.isBefore(Date(2011, 7, 1)));
assert(!negInfInterval.isBefore(Date(2012, 1, 6)));
assert(negInfInterval.isBefore(Date(2012, 1, 7)));
assert(negInfInterval.isBefore(Date(2012, 1, 8)));
assert(negInfInterval.isBefore(Date(2013, 1, 7)));
const cdate = Date(2010, 7, 6);
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, negInfInterval.isBefore(cdate)));
static assert(__traits(compiles, cNegInfInterval.isBefore(cdate)));
static assert(__traits(compiles, iNegInfInterval.isBefore(cdate)));
//Verify Examples.
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Date(1994, 12, 24)));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Date(2000, 1, 5)));
assert(NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Date(2012, 3, 1)));
}
//Test NegInfInterval's isBefore(Interval).
unittest
{
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static void testInterval(in NegInfInterval!Date negInfInterval, in Interval!Date interval)
{
negInfInterval.isBefore(interval);
}
assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assert(!negInfInterval.isBefore(negInfInterval));
assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
assert(!negInfInterval.isBefore(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
assert(!negInfInterval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
assert(!negInfInterval.isBefore(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
assert(negInfInterval.isBefore(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
assert(negInfInterval.isBefore(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assert(!negInfInterval.isBefore(NegInfInterval!Date(Date(2010, 7, 3))));
assert(!negInfInterval.isBefore(NegInfInterval!Date(Date(2010, 7, 4))));
assert(!negInfInterval.isBefore(NegInfInterval!Date(Date(2010, 7, 5))));
assert(!negInfInterval.isBefore(NegInfInterval!Date(Date(2012, 1, 6))));
assert(!negInfInterval.isBefore(NegInfInterval!Date(Date(2012, 1, 7))));
assert(!negInfInterval.isBefore(NegInfInterval!Date(Date(2012, 1, 8))));
assert(!NegInfInterval!Date(Date(2010, 7, 3)).isBefore(negInfInterval));
assert(!NegInfInterval!Date(Date(2010, 7, 4)).isBefore(negInfInterval));
assert(!NegInfInterval!Date(Date(2010, 7, 5)).isBefore(negInfInterval));
assert(!NegInfInterval!Date(Date(2012, 1, 6)).isBefore(negInfInterval));
assert(!NegInfInterval!Date(Date(2012, 1, 7)).isBefore(negInfInterval));
assert(!NegInfInterval!Date(Date(2012, 1, 8)).isBefore(negInfInterval));
assert(!negInfInterval.isBefore(PosInfInterval!Date(Date(2010, 7, 3))));
assert(!negInfInterval.isBefore(PosInfInterval!Date(Date(2010, 7, 4))));
assert(!negInfInterval.isBefore(PosInfInterval!Date(Date(2010, 7, 5))));
assert(!negInfInterval.isBefore(PosInfInterval!Date(Date(2012, 1, 6))));
assert(negInfInterval.isBefore(PosInfInterval!Date(Date(2012, 1, 7))));
assert(negInfInterval.isBefore(PosInfInterval!Date(Date(2012, 1, 8))));
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, negInfInterval.isBefore(interval)));
static assert(__traits(compiles, negInfInterval.isBefore(cInterval)));
static assert(__traits(compiles, negInfInterval.isBefore(iInterval)));
static assert(__traits(compiles, negInfInterval.isBefore(posInfInterval)));
static assert(__traits(compiles, negInfInterval.isBefore(cPosInfInterval)));
static assert(__traits(compiles, negInfInterval.isBefore(iPosInfInterval)));
static assert(__traits(compiles, negInfInterval.isBefore(negInfInterval)));
static assert(__traits(compiles, negInfInterval.isBefore(cNegInfInterval)));
static assert(__traits(compiles, negInfInterval.isBefore(iNegInfInterval)));
static assert(__traits(compiles, cNegInfInterval.isBefore(interval)));
static assert(__traits(compiles, cNegInfInterval.isBefore(cInterval)));
static assert(__traits(compiles, cNegInfInterval.isBefore(iInterval)));
static assert(__traits(compiles, cNegInfInterval.isBefore(posInfInterval)));
static assert(__traits(compiles, cNegInfInterval.isBefore(cPosInfInterval)));
static assert(__traits(compiles, cNegInfInterval.isBefore(iPosInfInterval)));
static assert(__traits(compiles, cNegInfInterval.isBefore(negInfInterval)));
static assert(__traits(compiles, cNegInfInterval.isBefore(cNegInfInterval)));
static assert(__traits(compiles, cNegInfInterval.isBefore(iNegInfInterval)));
static assert(__traits(compiles, iNegInfInterval.isBefore(interval)));
static assert(__traits(compiles, iNegInfInterval.isBefore(cInterval)));
static assert(__traits(compiles, iNegInfInterval.isBefore(iInterval)));
static assert(__traits(compiles, iNegInfInterval.isBefore(posInfInterval)));
static assert(__traits(compiles, iNegInfInterval.isBefore(cPosInfInterval)));
static assert(__traits(compiles, iNegInfInterval.isBefore(iPosInfInterval)));
static assert(__traits(compiles, iNegInfInterval.isBefore(negInfInterval)));
static assert(__traits(compiles, iNegInfInterval.isBefore(cNegInfInterval)));
static assert(__traits(compiles, iNegInfInterval.isBefore(iNegInfInterval)));
//Verify Examples.
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(NegInfInterval!Date(Date(2012, 3, 1)).isBefore(Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(PosInfInterval!Date(Date(1999, 5, 4))));
assert(NegInfInterval!Date(Date(2012, 3, 1)).isBefore(PosInfInterval!Date(Date(2012, 3, 1))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(NegInfInterval!Date(Date(1996, 5, 4))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isBefore(NegInfInterval!Date(Date(2013, 7, 9))));
}
//Test NegInfInterval's isAfter(time point).
unittest
{
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
assert(!negInfInterval.isAfter(Date(2009, 7, 4)));
assert(!negInfInterval.isAfter(Date(2010, 7, 3)));
assert(!negInfInterval.isAfter(Date(2010, 7, 4)));
assert(!negInfInterval.isAfter(Date(2010, 7, 5)));
assert(!negInfInterval.isAfter(Date(2011, 7, 1)));
assert(!negInfInterval.isAfter(Date(2012, 1, 6)));
assert(!negInfInterval.isAfter(Date(2012, 1, 7)));
assert(!negInfInterval.isAfter(Date(2012, 1, 8)));
assert(!negInfInterval.isAfter(Date(2013, 1, 7)));
const cdate = Date(2010, 7, 6);
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, negInfInterval.isAfter(cdate)));
static assert(__traits(compiles, cNegInfInterval.isAfter(cdate)));
static assert(__traits(compiles, iNegInfInterval.isAfter(cdate)));
}
//Test NegInfInterval's isAfter(Interval).
unittest
{
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static void testInterval(in NegInfInterval!Date negInfInterval, in Interval!Date interval)
{
negInfInterval.isAfter(interval);
}
assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assert(!negInfInterval.isAfter(negInfInterval));
assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
assert(!negInfInterval.isAfter(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
assert(!negInfInterval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
assert(!negInfInterval.isAfter(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
assert(!negInfInterval.isAfter(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
assert(!negInfInterval.isAfter(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assert(!negInfInterval.isAfter(NegInfInterval!Date(Date(2010, 7, 3))));
assert(!negInfInterval.isAfter(NegInfInterval!Date(Date(2010, 7, 4))));
assert(!negInfInterval.isAfter(NegInfInterval!Date(Date(2010, 7, 5))));
assert(!negInfInterval.isAfter(NegInfInterval!Date(Date(2012, 1, 6))));
assert(!negInfInterval.isAfter(NegInfInterval!Date(Date(2012, 1, 7))));
assert(!negInfInterval.isAfter(NegInfInterval!Date(Date(2012, 1, 8))));
assert(!NegInfInterval!Date(Date(2010, 7, 3)).isAfter(negInfInterval));
assert(!NegInfInterval!Date(Date(2010, 7, 4)).isAfter(negInfInterval));
assert(!NegInfInterval!Date(Date(2010, 7, 5)).isAfter(negInfInterval));
assert(!NegInfInterval!Date(Date(2012, 1, 6)).isAfter(negInfInterval));
assert(!NegInfInterval!Date(Date(2012, 1, 7)).isAfter(negInfInterval));
assert(!NegInfInterval!Date(Date(2012, 1, 8)).isAfter(negInfInterval));
assert(!negInfInterval.isAfter(PosInfInterval!Date(Date(2010, 7, 3))));
assert(!negInfInterval.isAfter(PosInfInterval!Date(Date(2010, 7, 4))));
assert(!negInfInterval.isAfter(PosInfInterval!Date(Date(2010, 7, 5))));
assert(!negInfInterval.isAfter(PosInfInterval!Date(Date(2012, 1, 6))));
assert(!negInfInterval.isAfter(PosInfInterval!Date(Date(2012, 1, 7))));
assert(!negInfInterval.isAfter(PosInfInterval!Date(Date(2012, 1, 8))));
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, negInfInterval.isAfter(interval)));
static assert(__traits(compiles, negInfInterval.isAfter(cInterval)));
static assert(__traits(compiles, negInfInterval.isAfter(iInterval)));
static assert(__traits(compiles, negInfInterval.isAfter(posInfInterval)));
static assert(__traits(compiles, negInfInterval.isAfter(cPosInfInterval)));
static assert(__traits(compiles, negInfInterval.isAfter(iPosInfInterval)));
static assert(__traits(compiles, negInfInterval.isAfter(negInfInterval)));
static assert(__traits(compiles, negInfInterval.isAfter(cNegInfInterval)));
static assert(__traits(compiles, negInfInterval.isAfter(iNegInfInterval)));
static assert(__traits(compiles, cNegInfInterval.isAfter(interval)));
static assert(__traits(compiles, cNegInfInterval.isAfter(cInterval)));
static assert(__traits(compiles, cNegInfInterval.isAfter(iInterval)));
static assert(__traits(compiles, cNegInfInterval.isAfter(posInfInterval)));
static assert(__traits(compiles, cNegInfInterval.isAfter(cPosInfInterval)));
static assert(__traits(compiles, cNegInfInterval.isAfter(iPosInfInterval)));
static assert(__traits(compiles, cNegInfInterval.isAfter(negInfInterval)));
static assert(__traits(compiles, cNegInfInterval.isAfter(cNegInfInterval)));
static assert(__traits(compiles, cNegInfInterval.isAfter(iNegInfInterval)));
static assert(__traits(compiles, iNegInfInterval.isAfter(interval)));
static assert(__traits(compiles, iNegInfInterval.isAfter(cInterval)));
static assert(__traits(compiles, iNegInfInterval.isAfter(iInterval)));
static assert(__traits(compiles, iNegInfInterval.isAfter(posInfInterval)));
static assert(__traits(compiles, iNegInfInterval.isAfter(cPosInfInterval)));
static assert(__traits(compiles, iNegInfInterval.isAfter(iPosInfInterval)));
static assert(__traits(compiles, iNegInfInterval.isAfter(negInfInterval)));
static assert(__traits(compiles, iNegInfInterval.isAfter(cNegInfInterval)));
static assert(__traits(compiles, iNegInfInterval.isAfter(iNegInfInterval)));
//Verify Examples.
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Date(1994, 12, 24)));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Date(2000, 1, 5)));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Date(2012, 3, 1)));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(PosInfInterval!Date(Date(1999, 5, 4))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(PosInfInterval!Date(Date(2012, 3, 1))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(NegInfInterval!Date(Date(1996, 5, 4))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAfter(NegInfInterval!Date(Date(2013, 7, 9))));
}
//Test NegInfInterval's intersects().
unittest
{
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static void testInterval(in NegInfInterval!Date negInfInterval, in Interval!Date interval)
{
negInfInterval.intersects(interval);
}
assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assert(negInfInterval.intersects(negInfInterval));
assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
assert(negInfInterval.intersects(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
assert(negInfInterval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
assert(negInfInterval.intersects(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
assert(!negInfInterval.intersects(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
assert(!negInfInterval.intersects(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assert(negInfInterval.intersects(NegInfInterval!Date(Date(2010, 7, 3))));
assert(negInfInterval.intersects(NegInfInterval!Date(Date(2010, 7, 4))));
assert(negInfInterval.intersects(NegInfInterval!Date(Date(2010, 7, 5))));
assert(negInfInterval.intersects(NegInfInterval!Date(Date(2012, 1, 6))));
assert(negInfInterval.intersects(NegInfInterval!Date(Date(2012, 1, 7))));
assert(negInfInterval.intersects(NegInfInterval!Date(Date(2012, 1, 8))));
assert(NegInfInterval!Date(Date(2010, 7, 3)).intersects(negInfInterval));
assert(NegInfInterval!Date(Date(2010, 7, 4)).intersects(negInfInterval));
assert(NegInfInterval!Date(Date(2010, 7, 5)).intersects(negInfInterval));
assert(NegInfInterval!Date(Date(2012, 1, 6)).intersects(negInfInterval));
assert(NegInfInterval!Date(Date(2012, 1, 7)).intersects(negInfInterval));
assert(NegInfInterval!Date(Date(2012, 1, 8)).intersects(negInfInterval));
assert(negInfInterval.intersects(PosInfInterval!Date(Date(2010, 7, 3))));
assert(negInfInterval.intersects(PosInfInterval!Date(Date(2010, 7, 4))));
assert(negInfInterval.intersects(PosInfInterval!Date(Date(2010, 7, 5))));
assert(negInfInterval.intersects(PosInfInterval!Date(Date(2012, 1, 6))));
assert(!negInfInterval.intersects(PosInfInterval!Date(Date(2012, 1, 7))));
assert(!negInfInterval.intersects(PosInfInterval!Date(Date(2012, 1, 8))));
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, negInfInterval.intersects(interval)));
static assert(__traits(compiles, negInfInterval.intersects(cInterval)));
static assert(__traits(compiles, negInfInterval.intersects(iInterval)));
static assert(__traits(compiles, negInfInterval.intersects(posInfInterval)));
static assert(__traits(compiles, negInfInterval.intersects(cPosInfInterval)));
static assert(__traits(compiles, negInfInterval.intersects(iPosInfInterval)));
static assert(__traits(compiles, negInfInterval.intersects(negInfInterval)));
static assert(__traits(compiles, negInfInterval.intersects(cNegInfInterval)));
static assert(__traits(compiles, negInfInterval.intersects(iNegInfInterval)));
static assert(__traits(compiles, cNegInfInterval.intersects(interval)));
static assert(__traits(compiles, cNegInfInterval.intersects(cInterval)));
static assert(__traits(compiles, cNegInfInterval.intersects(iInterval)));
static assert(__traits(compiles, cNegInfInterval.intersects(posInfInterval)));
static assert(__traits(compiles, cNegInfInterval.intersects(cPosInfInterval)));
static assert(__traits(compiles, cNegInfInterval.intersects(iPosInfInterval)));
static assert(__traits(compiles, cNegInfInterval.intersects(negInfInterval)));
static assert(__traits(compiles, cNegInfInterval.intersects(cNegInfInterval)));
static assert(__traits(compiles, cNegInfInterval.intersects(iNegInfInterval)));
static assert(__traits(compiles, iNegInfInterval.intersects(interval)));
static assert(__traits(compiles, iNegInfInterval.intersects(cInterval)));
static assert(__traits(compiles, iNegInfInterval.intersects(iInterval)));
static assert(__traits(compiles, iNegInfInterval.intersects(posInfInterval)));
static assert(__traits(compiles, iNegInfInterval.intersects(cPosInfInterval)));
static assert(__traits(compiles, iNegInfInterval.intersects(iPosInfInterval)));
static assert(__traits(compiles, iNegInfInterval.intersects(negInfInterval)));
static assert(__traits(compiles, iNegInfInterval.intersects(cNegInfInterval)));
static assert(__traits(compiles, iNegInfInterval.intersects(iNegInfInterval)));
//Verify Examples.
assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(Interval!Date(Date(1999, 1, 12), Date(2011, 9, 17))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).intersects(Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(PosInfInterval!Date(Date(1999, 5, 4))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).intersects(PosInfInterval!Date(Date(2012, 3, 1))));
assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(NegInfInterval!Date(Date(1996, 5, 4))));
assert(NegInfInterval!Date(Date(2012, 3, 1)).intersects(NegInfInterval!Date(Date(2013, 7, 9))));
}
//Test NegInfInterval's intersection().
unittest
{
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static void testInterval(I, J)(in I interval1, in J interval2)
{
interval1.intersection(interval2);
}
assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assertThrown!DateTimeException(testInterval(negInfInterval, PosInfInterval!Date(Date(2012, 1, 7))));
assertThrown!DateTimeException(testInterval(negInfInterval, PosInfInterval!Date(Date(2012, 1, 8))));
assertPred!"=="(negInfInterval.intersection(negInfInterval),
negInfInterval);
assertPred!"=="(negInfInterval.intersection(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))),
Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3)));
assertPred!"=="(negInfInterval.intersection(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))),
Interval!Date(Date(2010, 7, 1), Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))),
Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4)));
assertPred!"=="(negInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))),
Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5)));
assertPred!"=="(negInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))),
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.intersection(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))),
Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))),
Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6)));
assertPred!"=="(negInfInterval.intersection(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))),
Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))),
Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.intersection(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))),
Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.intersection(NegInfInterval!Date(Date(2010, 7, 3))),
NegInfInterval!Date(Date(2010, 7, 3)));
assertPred!"=="(negInfInterval.intersection(NegInfInterval!Date(Date(2010, 7, 4))),
NegInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(negInfInterval.intersection(NegInfInterval!Date(Date(2010, 7, 5))),
NegInfInterval!Date(Date(2010, 7, 5)));
assertPred!"=="(negInfInterval.intersection(NegInfInterval!Date(Date(2012, 1, 6))),
NegInfInterval!Date(Date(2012, 1, 6)));
assertPred!"=="(negInfInterval.intersection(NegInfInterval!Date(Date(2012, 1, 7))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.intersection(NegInfInterval!Date(Date(2012, 1, 8))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(NegInfInterval!Date(Date(2010, 7, 3)).intersection(negInfInterval),
NegInfInterval!Date(Date(2010, 7, 3)));
assertPred!"=="(NegInfInterval!Date(Date(2010, 7, 4)).intersection(negInfInterval),
NegInfInterval!Date(Date(2010, 7, 4)));
assertPred!"=="(NegInfInterval!Date(Date(2010, 7, 5)).intersection(negInfInterval),
NegInfInterval!Date(Date(2010, 7, 5)));
assertPred!"=="(NegInfInterval!Date(Date(2012, 1, 6)).intersection(negInfInterval),
NegInfInterval!Date(Date(2012, 1, 6)));
assertPred!"=="(NegInfInterval!Date(Date(2012, 1, 7)).intersection(negInfInterval),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(NegInfInterval!Date(Date(2012, 1, 8)).intersection(negInfInterval),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.intersection(PosInfInterval!Date(Date(2010, 7, 3))),
Interval!Date(Date(2010, 7, 3), Date(2012, 1 ,7)));
assertPred!"=="(negInfInterval.intersection(PosInfInterval!Date(Date(2010, 7, 4))),
Interval!Date(Date(2010, 7, 4), Date(2012, 1 ,7)));
assertPred!"=="(negInfInterval.intersection(PosInfInterval!Date(Date(2010, 7, 5))),
Interval!Date(Date(2010, 7, 5), Date(2012, 1 ,7)));
assertPred!"=="(negInfInterval.intersection(PosInfInterval!Date(Date(2012, 1, 6))),
Interval!Date(Date(2012, 1, 6), Date(2012, 1 ,7)));
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, negInfInterval.intersection(interval)));
static assert(__traits(compiles, negInfInterval.intersection(cInterval)));
static assert(__traits(compiles, negInfInterval.intersection(iInterval)));
static assert(__traits(compiles, negInfInterval.intersection(posInfInterval)));
static assert(__traits(compiles, negInfInterval.intersection(cPosInfInterval)));
static assert(__traits(compiles, negInfInterval.intersection(iPosInfInterval)));
static assert(__traits(compiles, negInfInterval.intersection(negInfInterval)));
static assert(__traits(compiles, negInfInterval.intersection(cNegInfInterval)));
static assert(__traits(compiles, negInfInterval.intersection(iNegInfInterval)));
static assert(__traits(compiles, cNegInfInterval.intersection(interval)));
static assert(__traits(compiles, cNegInfInterval.intersection(cInterval)));
static assert(__traits(compiles, cNegInfInterval.intersection(iInterval)));
static assert(__traits(compiles, cNegInfInterval.intersection(posInfInterval)));
static assert(__traits(compiles, cNegInfInterval.intersection(cPosInfInterval)));
static assert(__traits(compiles, cNegInfInterval.intersection(iPosInfInterval)));
static assert(__traits(compiles, cNegInfInterval.intersection(negInfInterval)));
static assert(__traits(compiles, cNegInfInterval.intersection(cNegInfInterval)));
static assert(__traits(compiles, cNegInfInterval.intersection(iNegInfInterval)));
static assert(__traits(compiles, iNegInfInterval.intersection(interval)));
static assert(__traits(compiles, iNegInfInterval.intersection(cInterval)));
static assert(__traits(compiles, iNegInfInterval.intersection(iInterval)));
static assert(__traits(compiles, iNegInfInterval.intersection(posInfInterval)));
static assert(__traits(compiles, iNegInfInterval.intersection(cPosInfInterval)));
static assert(__traits(compiles, iNegInfInterval.intersection(iPosInfInterval)));
static assert(__traits(compiles, iNegInfInterval.intersection(negInfInterval)));
static assert(__traits(compiles, iNegInfInterval.intersection(cNegInfInterval)));
static assert(__traits(compiles, iNegInfInterval.intersection(iNegInfInterval)));
//Verify Examples.
assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) == Interval!Date(Date(1990, 7 , 6), Date(2000, 8, 2)));
assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(Interval!Date(Date(1999, 1, 12), Date(2015, 9, 2))) == Interval!Date(Date(1999, 1 , 12), Date(2012, 3, 1)));
assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(PosInfInterval!Date(Date(1990, 7, 6))) == Interval!Date(Date(1990, 7 , 6), Date(2012, 3, 1)));
assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(PosInfInterval!Date(Date(1999, 1, 12))) == Interval!Date(Date(1999, 1 , 12), Date(2012, 3, 1)));
assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(NegInfInterval!Date(Date(1999, 7, 6))) == NegInfInterval!Date(Date(1999, 7 , 6)));
assert(NegInfInterval!Date(Date(2012, 3, 1)).intersection(NegInfInterval!Date(Date(2013, 1, 12))) == NegInfInterval!Date(Date(2012, 3 , 1)));
}
//Test NegInfInterval's isAdjacent().
unittest
{
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static void testInterval(in NegInfInterval!Date negInfInterval, in Interval!Date interval)
{
negInfInterval.isAdjacent(interval);
}
assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assert(!negInfInterval.isAdjacent(negInfInterval));
assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))));
assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))));
assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))));
assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))));
assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))));
assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))));
assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))));
assert(!negInfInterval.isAdjacent(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))));
assert(!negInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))));
assert(!negInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))));
assert(negInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))));
assert(!negInfInterval.isAdjacent(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assert(!negInfInterval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 3))));
assert(!negInfInterval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 4))));
assert(!negInfInterval.isAdjacent(NegInfInterval!Date(Date(2010, 7, 5))));
assert(!negInfInterval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 6))));
assert(!negInfInterval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 7))));
assert(!negInfInterval.isAdjacent(NegInfInterval!Date(Date(2012, 1, 8))));
assert(!NegInfInterval!Date(Date(2010, 7, 3)).isAdjacent(negInfInterval));
assert(!NegInfInterval!Date(Date(2010, 7, 4)).isAdjacent(negInfInterval));
assert(!NegInfInterval!Date(Date(2010, 7, 5)).isAdjacent(negInfInterval));
assert(!NegInfInterval!Date(Date(2012, 1, 6)).isAdjacent(negInfInterval));
assert(!NegInfInterval!Date(Date(2012, 1, 7)).isAdjacent(negInfInterval));
assert(!NegInfInterval!Date(Date(2012, 1, 8)).isAdjacent(negInfInterval));
assert(!negInfInterval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 3))));
assert(!negInfInterval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 4))));
assert(!negInfInterval.isAdjacent(PosInfInterval!Date(Date(2010, 7, 5))));
assert(!negInfInterval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 6))));
assert(negInfInterval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 7))));
assert(!negInfInterval.isAdjacent(PosInfInterval!Date(Date(2012, 1, 8))));
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, negInfInterval.isAdjacent(interval)));
static assert(__traits(compiles, negInfInterval.isAdjacent(cInterval)));
static assert(__traits(compiles, negInfInterval.isAdjacent(iInterval)));
static assert(__traits(compiles, negInfInterval.isAdjacent(posInfInterval)));
static assert(__traits(compiles, negInfInterval.isAdjacent(cPosInfInterval)));
static assert(__traits(compiles, negInfInterval.isAdjacent(iPosInfInterval)));
static assert(__traits(compiles, negInfInterval.isAdjacent(negInfInterval)));
static assert(__traits(compiles, negInfInterval.isAdjacent(cNegInfInterval)));
static assert(__traits(compiles, negInfInterval.isAdjacent(iNegInfInterval)));
static assert(__traits(compiles, cNegInfInterval.isAdjacent(interval)));
static assert(__traits(compiles, cNegInfInterval.isAdjacent(cInterval)));
static assert(__traits(compiles, cNegInfInterval.isAdjacent(iInterval)));
static assert(__traits(compiles, cNegInfInterval.isAdjacent(posInfInterval)));
static assert(__traits(compiles, cNegInfInterval.isAdjacent(cPosInfInterval)));
static assert(__traits(compiles, cNegInfInterval.isAdjacent(iPosInfInterval)));
static assert(__traits(compiles, cNegInfInterval.isAdjacent(negInfInterval)));
static assert(__traits(compiles, cNegInfInterval.isAdjacent(cNegInfInterval)));
static assert(__traits(compiles, cNegInfInterval.isAdjacent(iNegInfInterval)));
static assert(__traits(compiles, iNegInfInterval.isAdjacent(interval)));
static assert(__traits(compiles, iNegInfInterval.isAdjacent(cInterval)));
static assert(__traits(compiles, iNegInfInterval.isAdjacent(iInterval)));
static assert(__traits(compiles, iNegInfInterval.isAdjacent(posInfInterval)));
static assert(__traits(compiles, iNegInfInterval.isAdjacent(cPosInfInterval)));
static assert(__traits(compiles, iNegInfInterval.isAdjacent(iPosInfInterval)));
static assert(__traits(compiles, iNegInfInterval.isAdjacent(negInfInterval)));
static assert(__traits(compiles, iNegInfInterval.isAdjacent(cNegInfInterval)));
static assert(__traits(compiles, iNegInfInterval.isAdjacent(iNegInfInterval)));
//Verify Examples.
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(1999, 1, 12), Date(2012, 3, 1))));
assert(NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(2012, 3, 1), Date(2019, 2, 2))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(Interval!Date(Date(2022, 10, 19), Date(2027, 6, 3))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(PosInfInterval!Date(Date(1999, 5, 4))));
assert(NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(PosInfInterval!Date(Date(2012, 3, 1))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(NegInfInterval!Date(Date(1996, 5, 4))));
assert(!NegInfInterval!Date(Date(2012, 3, 1)).isAdjacent(NegInfInterval!Date(Date(2012, 3, 1))));
}
//Test NegInfInterval's merge().
unittest
{
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static void testInterval(I, J)(in I interval1, in J interval2)
{
interval1.merge(interval2);
}
assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))));
assertPred!"=="(negInfInterval.merge(negInfInterval),
negInfInterval);
assertPred!"=="(negInfInterval.merge(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.merge(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))),
NegInfInterval!Date(Date(2013, 7, 3)));
assertPred!"=="(negInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.merge(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))),
NegInfInterval!Date(Date(2012, 1, 8)));
assertPred!"=="(negInfInterval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.merge(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.merge(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))),
NegInfInterval!Date(Date(2012, 1, 8)));
assertPred!"=="(negInfInterval.merge(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))),
NegInfInterval!Date(Date(2012, 1, 8)));
assertPred!"=="(negInfInterval.merge(NegInfInterval!Date(Date(2010, 7, 3))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.merge(NegInfInterval!Date(Date(2010, 7, 4))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.merge(NegInfInterval!Date(Date(2010, 7, 5))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.merge(NegInfInterval!Date(Date(2012, 1, 6))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.merge(NegInfInterval!Date(Date(2012, 1, 7))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.merge(NegInfInterval!Date(Date(2012, 1, 8))),
NegInfInterval!Date(Date(2012, 1, 8)));
assertPred!"=="(NegInfInterval!Date(Date(2010, 7, 3)).merge(negInfInterval),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(NegInfInterval!Date(Date(2010, 7, 4)).merge(negInfInterval),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(NegInfInterval!Date(Date(2010, 7, 5)).merge(negInfInterval),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(NegInfInterval!Date(Date(2012, 1, 6)).merge(negInfInterval),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(NegInfInterval!Date(Date(2012, 1, 7)).merge(negInfInterval),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(NegInfInterval!Date(Date(2012, 1, 8)).merge(negInfInterval),
NegInfInterval!Date(Date(2012, 1, 8)));
static assert(!__traits(compiles, negInfInterval.merge(PosInfInterval!Date(Date(2010, 7, 3)))));
static assert(!__traits(compiles, negInfInterval.merge(PosInfInterval!Date(Date(2010, 7, 4)))));
static assert(!__traits(compiles, negInfInterval.merge(PosInfInterval!Date(Date(2010, 7, 5)))));
static assert(!__traits(compiles, negInfInterval.merge(PosInfInterval!Date(Date(2012, 1, 6)))));
static assert(!__traits(compiles, negInfInterval.merge(PosInfInterval!Date(Date(2012, 1, 7)))));
static assert(!__traits(compiles, negInfInterval.merge(PosInfInterval!Date(Date(2012, 1, 8)))));
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, negInfInterval.merge(interval)));
static assert(__traits(compiles, negInfInterval.merge(cInterval)));
static assert(__traits(compiles, negInfInterval.merge(iInterval)));
static assert(!__traits(compiles, negInfInterval.merge(posInfInterval)));
static assert(!__traits(compiles, negInfInterval.merge(cPosInfInterval)));
static assert(!__traits(compiles, negInfInterval.merge(iPosInfInterval)));
static assert(__traits(compiles, negInfInterval.merge(negInfInterval)));
static assert(__traits(compiles, negInfInterval.merge(cNegInfInterval)));
static assert(__traits(compiles, negInfInterval.merge(iNegInfInterval)));
static assert(__traits(compiles, cNegInfInterval.merge(interval)));
static assert(__traits(compiles, cNegInfInterval.merge(cInterval)));
static assert(__traits(compiles, cNegInfInterval.merge(iInterval)));
static assert(!__traits(compiles, cNegInfInterval.merge(posInfInterval)));
static assert(!__traits(compiles, cNegInfInterval.merge(cPosInfInterval)));
static assert(!__traits(compiles, cNegInfInterval.merge(iPosInfInterval)));
static assert(__traits(compiles, cNegInfInterval.merge(negInfInterval)));
static assert(__traits(compiles, cNegInfInterval.merge(cNegInfInterval)));
static assert(__traits(compiles, cNegInfInterval.merge(iNegInfInterval)));
static assert(__traits(compiles, iNegInfInterval.merge(interval)));
static assert(__traits(compiles, iNegInfInterval.merge(cInterval)));
static assert(__traits(compiles, iNegInfInterval.merge(iInterval)));
static assert(!__traits(compiles, iNegInfInterval.merge(posInfInterval)));
static assert(!__traits(compiles, iNegInfInterval.merge(cPosInfInterval)));
static assert(!__traits(compiles, iNegInfInterval.merge(iPosInfInterval)));
static assert(__traits(compiles, iNegInfInterval.merge(negInfInterval)));
static assert(__traits(compiles, iNegInfInterval.merge(cNegInfInterval)));
static assert(__traits(compiles, iNegInfInterval.merge(iNegInfInterval)));
//Verify Examples.
assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) == NegInfInterval!Date(Date(2012, 3 , 1)));
assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(Interval!Date(Date(1999, 1, 12), Date(2015, 9, 2))) == NegInfInterval!Date(Date(2015, 9 , 2)));
assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(NegInfInterval!Date(Date(1999, 7, 6))) == NegInfInterval!Date(Date(2012, 3 , 1)));
assert(NegInfInterval!Date(Date(2012, 3, 1)).merge(NegInfInterval!Date(Date(2013, 1, 12))) == NegInfInterval!Date(Date(2013, 1 , 12)));
}
//Test NegInfInterval's span().
unittest
{
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static void testInterval(I, J)(in I interval1, in J interval2)
{
interval1.span(interval2);
}
assertThrown!DateTimeException(testInterval(negInfInterval, Interval!Date(Date(2010, 7, 4), dur!"days"(0))));
assertPred!"=="(negInfInterval.span(negInfInterval),
negInfInterval);
assertPred!"=="(negInfInterval.span(Interval!Date(Date(2010, 7, 1), Date(2010, 7, 3))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.span(Interval!Date(Date(2010, 7, 1), Date(2013, 7, 3))),
NegInfInterval!Date(Date(2013, 7, 3)));
assertPred!"=="(negInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 4))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2010, 7, 5))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 7))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.span(Interval!Date(Date(2010, 7, 3), Date(2012, 1, 8))),
NegInfInterval!Date(Date(2012, 1, 8)));
assertPred!"=="(negInfInterval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 6))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.span(Interval!Date(Date(2010, 7, 5), Date(2012, 1, 7))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 7))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.span(Interval!Date(Date(2012, 1, 6), Date(2012, 1, 8))),
NegInfInterval!Date(Date(2012, 1, 8)));
assertPred!"=="(negInfInterval.span(Interval!Date(Date(2012, 1, 7), Date(2012, 1, 8))),
NegInfInterval!Date(Date(2012, 1, 8)));
assertPred!"=="(negInfInterval.span(Interval!Date(Date(2012, 1, 8), Date(2012, 1, 9))),
NegInfInterval!Date(Date(2012, 1, 9)));
assertPred!"=="(negInfInterval.span(NegInfInterval!Date(Date(2010, 7, 3))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.span(NegInfInterval!Date(Date(2010, 7, 4))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.span(NegInfInterval!Date(Date(2010, 7, 5))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.span(NegInfInterval!Date(Date(2012, 1, 6))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.span(NegInfInterval!Date(Date(2012, 1, 7))),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(negInfInterval.span(NegInfInterval!Date(Date(2012, 1, 8))),
NegInfInterval!Date(Date(2012, 1, 8)));
assertPred!"=="(NegInfInterval!Date(Date(2010, 7, 3)).span(negInfInterval),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(NegInfInterval!Date(Date(2010, 7, 4)).span(negInfInterval),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(NegInfInterval!Date(Date(2010, 7, 5)).span(negInfInterval),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(NegInfInterval!Date(Date(2012, 1, 6)).span(negInfInterval),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(NegInfInterval!Date(Date(2012, 1, 7)).span(negInfInterval),
NegInfInterval!Date(Date(2012, 1, 7)));
assertPred!"=="(NegInfInterval!Date(Date(2012, 1, 8)).span(negInfInterval),
NegInfInterval!Date(Date(2012, 1, 8)));
static assert(!__traits(compiles, negInfInterval.span(PosInfInterval!Date(Date(2010, 7, 3)))));
static assert(!__traits(compiles, negInfInterval.span(PosInfInterval!Date(Date(2010, 7, 4)))));
static assert(!__traits(compiles, negInfInterval.span(PosInfInterval!Date(Date(2010, 7, 5)))));
static assert(!__traits(compiles, negInfInterval.span(PosInfInterval!Date(Date(2012, 1, 6)))));
static assert(!__traits(compiles, negInfInterval.span(PosInfInterval!Date(Date(2012, 1, 7)))));
static assert(!__traits(compiles, negInfInterval.span(PosInfInterval!Date(Date(2012, 1, 8)))));
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
const cInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
immutable iInterval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
immutable iPosInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, negInfInterval.span(interval)));
static assert(__traits(compiles, negInfInterval.span(cInterval)));
static assert(__traits(compiles, negInfInterval.span(iInterval)));
static assert(!__traits(compiles, negInfInterval.span(posInfInterval)));
static assert(!__traits(compiles, negInfInterval.span(cPosInfInterval)));
static assert(!__traits(compiles, negInfInterval.span(iPosInfInterval)));
static assert(__traits(compiles, negInfInterval.span(negInfInterval)));
static assert(__traits(compiles, negInfInterval.span(cNegInfInterval)));
static assert(__traits(compiles, negInfInterval.span(iNegInfInterval)));
static assert(__traits(compiles, cNegInfInterval.span(interval)));
static assert(__traits(compiles, cNegInfInterval.span(cInterval)));
static assert(__traits(compiles, cNegInfInterval.span(iInterval)));
static assert(!__traits(compiles, cNegInfInterval.span(posInfInterval)));
static assert(!__traits(compiles, cNegInfInterval.span(cPosInfInterval)));
static assert(!__traits(compiles, cNegInfInterval.span(iPosInfInterval)));
static assert(__traits(compiles, cNegInfInterval.span(negInfInterval)));
static assert(__traits(compiles, cNegInfInterval.span(cNegInfInterval)));
static assert(__traits(compiles, cNegInfInterval.span(iNegInfInterval)));
static assert(__traits(compiles, iNegInfInterval.span(interval)));
static assert(__traits(compiles, iNegInfInterval.span(cInterval)));
static assert(__traits(compiles, iNegInfInterval.span(iInterval)));
static assert(!__traits(compiles, iNegInfInterval.span(posInfInterval)));
static assert(!__traits(compiles, iNegInfInterval.span(cPosInfInterval)));
static assert(!__traits(compiles, iNegInfInterval.span(iPosInfInterval)));
static assert(__traits(compiles, iNegInfInterval.span(negInfInterval)));
static assert(__traits(compiles, iNegInfInterval.span(cNegInfInterval)));
static assert(__traits(compiles, iNegInfInterval.span(iNegInfInterval)));
//Verify Examples.
assert(NegInfInterval!Date(Date(2012, 3, 1)).span(Interval!Date(Date(1990, 7, 6), Date(2000, 8, 2))) == NegInfInterval!Date(Date(2012, 3 , 1)));
assert(NegInfInterval!Date(Date(2012, 3, 1)).span(Interval!Date(Date(1999, 1, 12), Date(2015, 9, 2))) == NegInfInterval!Date(Date(2015, 9 , 2)));
assert(NegInfInterval!Date(Date(1600, 1, 7)).span(Interval!Date(Date(2012, 3, 11), Date(2017, 7, 1))) == NegInfInterval!Date(Date(2017, 7 , 1)));
assert(NegInfInterval!Date(Date(2012, 3, 1)).span(NegInfInterval!Date(Date(1999, 7, 6))) == NegInfInterval!Date(Date(2012, 3 , 1)));
assert(NegInfInterval!Date(Date(2012, 3, 1)).span(NegInfInterval!Date(Date(2013, 1, 12))) == NegInfInterval!Date(Date(2013, 1 , 12)));
}
//Test NegInfInterval's shift().
unittest
{
auto interval = NegInfInterval!Date(Date(2012, 1, 7));
static void testInterval(I)(I interval, in Duration duration, in I expected, size_t line = __LINE__)
{
interval.shift(duration);
assertPred!"=="(interval, expected, "", __FILE__, line);
}
testInterval(interval, dur!"days"(22), NegInfInterval!Date(Date(2012, 1, 29)));
testInterval(interval, dur!"days"(-22), NegInfInterval!Date(Date(2011, 12, 16)));
const cInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(!__traits(compiles, cInterval.shift(dur!"days"(5))));
static assert(!__traits(compiles, iInterval.shift(dur!"days"(5))));
//Verify Examples.
auto interval1 = NegInfInterval!Date(Date(2012, 4, 5));
auto interval2 = NegInfInterval!Date(Date(2012, 4, 5));
interval1.shift(dur!"days"(50));
assert(interval1 == NegInfInterval!Date(Date(2012, 5, 25)));
interval2.shift(dur!"days"(-50));
assert(interval2 == NegInfInterval!Date( Date(2012, 2, 15)));
}
//Test NegInfInterval's shift(int, int, AllowDayOverflow).
unittest
{
{
auto interval = NegInfInterval!Date(Date(2012, 1, 7));
static void testIntervalFail(I)(I interval, int years, int months)
{
interval.shift(years, months);
}
static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow, in I expected, size_t line = __LINE__)
{
interval.shift(years, months, allow);
assertPred!"=="(interval, expected, "", __FILE__, line);
}
testInterval(interval, 5, 0, AllowDayOverflow.yes, NegInfInterval!Date(Date(2017, 1, 7)));
testInterval(interval, -5, 0, AllowDayOverflow.yes, NegInfInterval!Date(Date(2007, 1, 7)));
auto interval2 = NegInfInterval!Date(Date(2010, 5, 31));
testInterval(interval2, 1, 1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2011, 7, 1)));
testInterval(interval2, 1, -1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2011, 5, 1)));
testInterval(interval2, -1, -1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2009, 5, 1)));
testInterval(interval2, -1, 1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2009, 7, 1)));
testInterval(interval2, 1, 1, AllowDayOverflow.no, NegInfInterval!Date(Date(2011, 6, 30)));
testInterval(interval2, 1, -1, AllowDayOverflow.no, NegInfInterval!Date(Date(2011, 4, 30)));
testInterval(interval2, -1, -1, AllowDayOverflow.no, NegInfInterval!Date(Date(2009, 4, 30)));
testInterval(interval2, -1, 1, AllowDayOverflow.no, NegInfInterval!Date(Date(2009, 6, 30)));
}
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(!__traits(compiles, cNegInfInterval.shift(1)));
static assert(!__traits(compiles, iNegInfInterval.shift(1)));
//Verify Examples.
auto interval1 = NegInfInterval!Date(Date(2012, 3, 1));
auto interval2 = NegInfInterval!Date(Date(2012, 3, 1));
interval1.shift(2);
assert(interval1 == NegInfInterval!Date(Date(2014, 3, 1)));
interval2.shift(-2);
assert(interval2 == NegInfInterval!Date(Date(2010, 3, 1)));
}
//Test NegInfInterval's expand().
unittest
{
auto interval = NegInfInterval!Date(Date(2012, 1, 7));
static void testInterval(I)(I interval, in Duration duration, in I expected, size_t line = __LINE__)
{
interval.expand(duration);
assertPred!"=="(interval, expected, "", __FILE__, line);
}
testInterval(interval, dur!"days"(22), NegInfInterval!Date(Date(2012, 1, 29)));
testInterval(interval, dur!"days"(-22), NegInfInterval!Date(Date(2011, 12, 16)));
const cInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(!__traits(compiles, cInterval.expand(dur!"days"(5))));
static assert(!__traits(compiles, iInterval.expand(dur!"days"(5))));
//Verify Examples.
auto interval1 = NegInfInterval!Date(Date(2012, 3, 1));
auto interval2 = NegInfInterval!Date(Date(2012, 3, 1));
interval1.expand(dur!"days"(2));
assert(interval1 == NegInfInterval!Date(Date(2012, 3, 3)));
interval2.expand(dur!"days"(-2));
assert(interval2 == NegInfInterval!Date(Date(2012, 2, 28)));
}
//Test NegInfInterval's expand(int, int, AllowDayOverflow).
unittest
{
{
auto interval = NegInfInterval!Date(Date(2012, 1, 7));
static void testInterval(I)(I interval, int years, int months, AllowDayOverflow allow, in I expected, size_t line = __LINE__)
{
interval.expand(years, months, allow);
assertPred!"=="(interval, expected, "", __FILE__, line);
}
testInterval(interval, 5, 0, AllowDayOverflow.yes, NegInfInterval!Date(Date(2017, 1, 7)));
testInterval(interval, -5, 0, AllowDayOverflow.yes, NegInfInterval!Date(Date(2007, 1, 7)));
auto interval2 = NegInfInterval!Date(Date(2010, 5, 31));
testInterval(interval2, 1, 1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2011, 7, 1)));
testInterval(interval2, 1, -1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2011, 5, 1)));
testInterval(interval2, -1, -1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2009, 5, 1)));
testInterval(interval2, -1, 1, AllowDayOverflow.yes, NegInfInterval!Date(Date(2009, 7, 1)));
testInterval(interval2, 1, 1, AllowDayOverflow.no, NegInfInterval!Date(Date(2011, 6, 30)));
testInterval(interval2, 1, -1, AllowDayOverflow.no, NegInfInterval!Date(Date(2011, 4, 30)));
testInterval(interval2, -1, -1, AllowDayOverflow.no, NegInfInterval!Date(Date(2009, 4, 30)));
testInterval(interval2, -1, 1, AllowDayOverflow.no, NegInfInterval!Date( Date(2009, 6, 30)));
}
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(!__traits(compiles, cNegInfInterval.expand(1)));
static assert(!__traits(compiles, iNegInfInterval.expand(1)));
//Verify Examples.
auto interval1 = NegInfInterval!Date(Date(2012, 3, 1));
auto interval2 = NegInfInterval!Date(Date(2012, 3, 1));
interval1.expand(2);
assert(interval1 == NegInfInterval!Date(Date(2014, 3, 1)));
interval2.expand(-2);
assert(interval2 == NegInfInterval!Date(Date(2010, 3, 1)));
}
//Test NegInfInterval's bwdRange().
unittest
{
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static void testInterval(NegInfInterval!Date negInfInterval)
{
negInfInterval.bwdRange(everyDayOfWeek!(Date, Direction.fwd)(DayOfWeek.fri)).popFront();
}
assertThrown!DateTimeException(testInterval(negInfInterval));
assertPred!"=="(NegInfInterval!Date(Date(2010, 10, 1)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri)).front,
Date(2010, 10, 1));
assertPred!"=="(NegInfInterval!Date(Date(2010, 10, 1)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri), PopFirst.yes).front,
Date(2010, 9, 24));
//Verify Examples.
auto interval = NegInfInterval!Date(Date(2010, 9, 9));
auto func = (in Date date)
{
if((date.day & 1) == 0)
return date - dur!"days"(2);
return date - dur!"days"(1);
};
auto range = interval.bwdRange(func);
assert(range.front == Date(2010, 9, 9)); //An odd day. Using PopFirst.yes would have made this Date(2010, 9, 8).
range.popFront();
assert(range.front == Date(2010, 9, 8));
range.popFront();
assert(range.front == Date(2010, 9, 6));
range.popFront();
assert(range.front == Date(2010, 9, 4));
range.popFront();
assert(range.front == Date(2010, 9, 2));
range.popFront();
assert(!range.empty);
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, cNegInfInterval.bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri))));
static assert(__traits(compiles, iNegInfInterval.bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri))));
}
//Test NegInfInterval's toString().
unittest
{
assertPred!"=="(NegInfInterval!Date(Date(2012, 1, 7)).toString(), "[-∞ - 2012-Jan-07)");
const cNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
immutable iNegInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
static assert(__traits(compiles, cNegInfInterval.toString()));
static assert(__traits(compiles, iNegInfInterval.toString()));
}
/++
Generates a range-generating function for intervals.
Returns a delegate which returns the next time point with the given
DayOfWeek in a range.
Using this delegate allows you to iterate over successive time points
which are all the same day of the week. e.g. passing DayOfWeek.mon
to $(D everyDayOfWeek()) would result in a delegate which could be used
to iterate over all of the Mondays in a range.
Params:
dir = The direction to iterate in. If passing the return value
to $(D fwdRange()), use $(D Direction.fwd). If passing
it to $(D bwdRange()), use $(D Direction.bwd).
dayOfWeek = The week that each time point in the range will be.
Examples:
--------------------
auto interval = Interval!Date(Date(2010, 9, 2), Date(2010, 9, 27));
auto func = everyDayOfWeek!Date(DayOfWeek.mon);
auto range = interval.fwdRange(func);
assert(range.front == Date(2010, 9, 2)); //A Thursday. Using PopFirst.yes would have made this Date(2010, 9, 6).
range.popFront();
assert(range.front == Date(2010, 9, 6));
range.popFront();
assert(range.front == Date(2010, 9, 13));
range.popFront();
assert(range.front == Date(2010, 9, 20));
range.popFront();
assert(range.empty);
--------------------
+/
static TP delegate(in TP) everyDayOfWeek(TP, Direction dir = Direction.fwd)(DayOfWeek dayOfWeek) nothrow
if(isTimePoint!TP &&
(dir == Direction.fwd || dir == Direction.bwd) &&
__traits(hasMember, TP, "dayOfWeek") &&
!__traits(isStaticFunction, TP.dayOfWeek) &&
is(ReturnType!(TP.dayOfWeek) == DayOfWeek) &&
(functionAttributes!(TP.dayOfWeek) & FunctionAttribute.PROPERTY) &&
(functionAttributes!(TP.dayOfWeek) & FunctionAttribute.NOTHROW))
{
TP func(in TP tp)
{
TP retval = cast(TP)tp;
immutable days = daysToDayOfWeek(retval.dayOfWeek, dayOfWeek);
static if(dir == Direction.fwd)
immutable adjustedDays = days == 0 ? 7 : days;
else
immutable adjustedDays = days == 0 ? -7 : days - 7;
return retval += dur!"days"(adjustedDays);
}
return &func;
}
unittest
{
auto funcFwd = everyDayOfWeek!Date(DayOfWeek.mon);
auto funcBwd = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.mon);
assertPred!"=="(funcFwd(Date(2010, 8, 28)), Date(2010, 8, 30));
assertPred!"=="(funcFwd(Date(2010, 8, 29)), Date(2010, 8, 30));
assertPred!"=="(funcFwd(Date(2010, 8, 30)), Date(2010, 9, 6));
assertPred!"=="(funcFwd(Date(2010, 8, 31)), Date(2010, 9, 6));
assertPred!"=="(funcFwd(Date(2010, 9, 1)), Date(2010, 9, 6));
assertPred!"=="(funcFwd(Date(2010, 9, 2)), Date(2010, 9, 6));
assertPred!"=="(funcFwd(Date(2010, 9, 3)), Date(2010, 9, 6));
assertPred!"=="(funcFwd(Date(2010, 9, 4)), Date(2010, 9, 6));
assertPred!"=="(funcFwd(Date(2010, 9, 5)), Date(2010, 9, 6));
assertPred!"=="(funcFwd(Date(2010, 9, 6)), Date(2010, 9, 13));
assertPred!"=="(funcFwd(Date(2010, 9, 7)), Date(2010, 9, 13));
assertPred!"=="(funcBwd(Date(2010, 8, 28)), Date(2010, 8, 23));
assertPred!"=="(funcBwd(Date(2010, 8, 29)), Date(2010, 8, 23));
assertPred!"=="(funcBwd(Date(2010, 8, 30)), Date(2010, 8, 23));
assertPred!"=="(funcBwd(Date(2010, 8, 31)), Date(2010, 8, 30));
assertPred!"=="(funcBwd(Date(2010, 9, 1)), Date(2010, 8, 30));
assertPred!"=="(funcBwd(Date(2010, 9, 2)), Date(2010, 8, 30));
assertPred!"=="(funcBwd(Date(2010, 9, 3)), Date(2010, 8, 30));
assertPred!"=="(funcBwd(Date(2010, 9, 4)), Date(2010, 8, 30));
assertPred!"=="(funcBwd(Date(2010, 9, 5)), Date(2010, 8, 30));
assertPred!"=="(funcBwd(Date(2010, 9, 6)), Date(2010, 8, 30));
assertPred!"=="(funcBwd(Date(2010, 9, 7)), Date(2010, 9, 6));
static assert(!__traits(compiles, everyDayOfWeek!(TimeOfDay)(DayOfWeek.mon)));
static assert(__traits(compiles, everyDayOfWeek!(DateTime)(DayOfWeek.mon)));
static assert(__traits(compiles, everyDayOfWeek!(SysTime)(DayOfWeek.mon)));
//Verify Examples.
auto interval = Interval!Date(Date(2010, 9, 2), Date(2010, 9, 27));
auto func = everyDayOfWeek!Date(DayOfWeek.mon);
auto range = interval.fwdRange(func);
assert(range.front == Date(2010, 9, 2)); //A Thursday. Using PopFirst.yes would have made this Date(2010, 9, 6).
range.popFront();
assert(range.front == Date(2010, 9, 6));
range.popFront();
assert(range.front == Date(2010, 9, 13));
range.popFront();
assert(range.front == Date(2010, 9, 20));
range.popFront();
assert(range.empty);
}
/++
Generates a range-generating function for intervals.
Returns a delegate which returns the next time point with the given
month which would be reached by adding months to the given time
point.
So, using this delegate allows you to iterate over successive time
points which are in the same month but different years. For example,
you could iterate over each successive December 25th in an interval
by starting with a date which had the 25th as its day and passed
$(D Month.dec) to $(D everyMonth()) to create the delegate.
Since it wouldn't really make sense to be iterating over a specific
month and end up with some of the time points in the succeeding month
or two years after the previous time point, $(D AllowDayOverflow.no)
is always used when calculating the next time point.
Params:
dir = The direction to iterate in. If passing the return value
to $(D fwdRange()), use $(D Direction.fwd). If passing
it to $(D bwdRange()), use $(D Direction.bwd).
month = The month that each time point in the range will be in.
Examples:
--------------------
auto interval = Interval!Date(Date(2000, 1, 30), Date(2004, 8, 5));
auto func = everyMonth!(Date)(Month.feb);
auto range = interval.fwdRange(func);
assert(range.front == Date(2000, 1, 30)); //Using PopFirst.yes would have made this Date(2010, 2, 29).
range.popFront();
assert(range.front == Date(2000, 2, 29));
range.popFront();
assert(range.front == Date(2001, 2, 28));
range.popFront();
assert(range.front == Date(2002, 2, 28));
range.popFront();
assert(range.front == Date(2003, 2, 28));
range.popFront();
assert(range.front == Date(2004, 2, 28));
range.popFront();
assert(range.empty);
--------------------
+/
static TP delegate(in TP) everyMonth(TP, Direction dir = Direction.fwd)(int month)
if(isTimePoint!TP &&
(dir == Direction.fwd || dir == Direction.bwd) &&
__traits(hasMember, TP, "month") &&
!__traits(isStaticFunction, TP.month) &&
is(ReturnType!(TP.month) == Month) &&
(functionAttributes!(TP.month) & FunctionAttribute.PROPERTY) &&
(functionAttributes!(TP.month) & FunctionAttribute.NOTHROW))
{
enforceValid!"months"(month);
TP func(in TP tp)
{
TP retval = cast(TP)tp;
immutable months = monthsToMonth(retval.month, month);
static if(dir == Direction.fwd)
immutable adjustedMonths = months == 0 ? 12 : months;
else
immutable adjustedMonths = months == 0 ? -12 : months - 12;
retval.add!"months"(adjustedMonths, AllowDayOverflow.no);
if(retval.month != month)
{
retval.add!"months"(-1);
assert(retval.month == month);
}
return retval;
}
return &func;
}
unittest
{
auto funcFwd = everyMonth!Date(Month.jun);
auto funcBwd = everyMonth!(Date, Direction.bwd)(Month.jun);
assertPred!"=="(funcFwd(Date(2010, 5, 31)), Date(2010, 6, 30));
assertPred!"=="(funcFwd(Date(2010, 6, 30)), Date(2011, 6, 30));
assertPred!"=="(funcFwd(Date(2010, 7, 31)), Date(2011, 6, 30));
assertPred!"=="(funcFwd(Date(2010, 8, 31)), Date(2011, 6, 30));
assertPred!"=="(funcFwd(Date(2010, 9, 30)), Date(2011, 6, 30));
assertPred!"=="(funcFwd(Date(2010, 10, 31)), Date(2011, 6, 30));
assertPred!"=="(funcFwd(Date(2010, 11, 30)), Date(2011, 6, 30));
assertPred!"=="(funcFwd(Date(2010, 12, 31)), Date(2011, 6, 30));
assertPred!"=="(funcFwd(Date(2011, 1, 31)), Date(2011, 6, 30));
assertPred!"=="(funcFwd(Date(2011, 2, 28)), Date(2011, 6, 28));
assertPred!"=="(funcFwd(Date(2011, 3, 31)), Date(2011, 6, 30));
assertPred!"=="(funcFwd(Date(2011, 4, 30)), Date(2011, 6, 30));
assertPred!"=="(funcFwd(Date(2011, 5, 31)), Date(2011, 6, 30));
assertPred!"=="(funcFwd(Date(2011, 6, 30)), Date(2012, 6, 30));
assertPred!"=="(funcFwd(Date(2011, 7, 31)), Date(2012, 6, 30));
assertPred!"=="(funcBwd(Date(2010, 5, 31)), Date(2009, 6, 30));
assertPred!"=="(funcBwd(Date(2010, 6, 30)), Date(2009, 6, 30));
assertPred!"=="(funcBwd(Date(2010, 7, 31)), Date(2010, 6, 30));
assertPred!"=="(funcBwd(Date(2010, 8, 31)), Date(2010, 6, 30));
assertPred!"=="(funcBwd(Date(2010, 9, 30)), Date(2010, 6, 30));
assertPred!"=="(funcBwd(Date(2010, 10, 31)), Date(2010, 6, 30));
assertPred!"=="(funcBwd(Date(2010, 11, 30)), Date(2010, 6, 30));
assertPred!"=="(funcBwd(Date(2010, 12, 31)), Date(2010, 6, 30));
assertPred!"=="(funcBwd(Date(2011, 1, 31)), Date(2010, 6, 30));
assertPred!"=="(funcBwd(Date(2011, 2, 28)), Date(2010, 6, 28));
assertPred!"=="(funcBwd(Date(2011, 3, 31)), Date(2010, 6, 30));
assertPred!"=="(funcBwd(Date(2011, 4, 30)), Date(2010, 6, 30));
assertPred!"=="(funcBwd(Date(2011, 5, 31)), Date(2010, 6, 30));
assertPred!"=="(funcBwd(Date(2011, 6, 30)), Date(2010, 6, 30));
assertPred!"=="(funcBwd(Date(2011, 7, 30)), Date(2011, 6, 30));
static assert(!__traits(compiles, everyMonth!(TimeOfDay)(Month.jan)));
static assert(__traits(compiles, everyMonth!(DateTime)(Month.jan)));
static assert(__traits(compiles, everyMonth!(SysTime)(Month.jan)));
//Verify Examples.
auto interval = Interval!Date(Date(2000, 1, 30), Date(2004, 8, 5));
auto func = everyMonth!(Date)(Month.feb);
auto range = interval.fwdRange(func);
assert(range.front == Date(2000, 1, 30)); //Using PopFirst.yes would have made this Date(2010, 2, 29).
range.popFront();
assert(range.front == Date(2000, 2, 29));
range.popFront();
assert(range.front == Date(2001, 2, 28));
range.popFront();
assert(range.front == Date(2002, 2, 28));
range.popFront();
assert(range.front == Date(2003, 2, 28));
range.popFront();
assert(range.front == Date(2004, 2, 28));
range.popFront();
assert(range.empty);
}
/++
Generates a range-generating function for intervals.
Returns a delegate which returns the next time point which is the given
duration later.
Using this delegate allows you to iterate over successive time points
which are apart by the given duration e.g. passing $(D dur!"days"(3)) to
$(D everyDuration()) would result in a delegate which could be
used to iterate over a range of days which are each 3 days apart.
Params:
dir = The direction to iterate in. If passing the return value
to $(D fwdRange()), use $(D Direction.fwd). If passing it
to $(D bwdRange()), use $(D Direction.bwd).
duration = The duration which separates each successive time point
in the range.
Examples:
--------------------
auto interval = Interval!Date(Date(2010, 9, 2), Date(2010, 9, 27));
auto func = everyDuration!Date(dur!"days"(8));
auto range = interval.fwdRange(func);
assert(range.front == Date(2010, 9, 2)); //Using PopFirst.yes would have made this Date(2010, 9, 10).
range.popFront();
assert(range.front == Date(2010, 9, 10));
range.popFront();
assert(range.front == Date(2010, 9, 18));
range.popFront();
assert(range.front == Date(2010, 9, 26));
range.popFront();
assert(range.empty);
--------------------
+/
static TP delegate(in TP) everyDuration(TP, Direction dir = Direction.fwd, D)
(D duration) nothrow
if(isTimePoint!TP &&
__traits(compiles, TP.init + duration) &&
(dir == Direction.fwd || dir == Direction.bwd))
{
TP func(in TP tp)
{
static if(dir == Direction.fwd)
return tp + duration;
else
return tp - duration;
}
return &func;
}
unittest
{
auto funcFwd = everyDuration!Date(dur!"days"(27));
auto funcBwd = everyDuration!(Date, Direction.bwd)(dur!"days"(27));
assertPred!"=="(funcFwd(Date(2009, 12, 25)), Date(2010, 1, 21));
assertPred!"=="(funcFwd(Date(2009, 12, 26)), Date(2010, 1, 22));
assertPred!"=="(funcFwd(Date(2009, 12, 27)), Date(2010, 1, 23));
assertPred!"=="(funcFwd(Date(2009, 12, 28)), Date(2010, 1, 24));
assertPred!"=="(funcBwd(Date(2010, 1, 21)), Date(2009, 12, 25));
assertPred!"=="(funcBwd(Date(2010, 1, 22)), Date(2009, 12, 26));
assertPred!"=="(funcBwd(Date(2010, 1, 23)), Date(2009, 12, 27));
assertPred!"=="(funcBwd(Date(2010, 1, 24)), Date(2009, 12, 28));
static assert(__traits(compiles, everyDuration!Date(dur!"hnsecs"(1))));
static assert(__traits(compiles, everyDuration!TimeOfDay(dur!"hnsecs"(1))));
static assert(__traits(compiles, everyDuration!DateTime(dur!"hnsecs"(1))));
static assert(__traits(compiles, everyDuration!SysTime(dur!"hnsecs"(1))));
//Verify Examples.
auto interval = Interval!Date(Date(2010, 9, 2), Date(2010, 9, 27));
auto func = everyDuration!Date(dur!"days"(8));
auto range = interval.fwdRange(func);
assert(range.front == Date(2010, 9, 2)); //Using PopFirst.yes would have made this Date(2010, 9, 10).
range.popFront();
assert(range.front == Date(2010, 9, 10));
range.popFront();
assert(range.front == Date(2010, 9, 18));
range.popFront();
assert(range.front == Date(2010, 9, 26));
range.popFront();
assert(range.empty);
}
/++
Generates a range-generating function for intervals.
Returns a delegate which returns the next time point which is the given
number of years, month, and duration later.
The difference between this version of $(D everyDuration()) and the
version which just takes a $(D Duration) is that this one also takes the
number of years and months (along with an AllowDayOverflow to indicate
whether adding years and months should allow the days to overflow).
Note that if iterating forward, $(D add!"years"()) is called on the given
time point, then $(D add!"months"()), and finally the duration is added
to it. However, if iterating backwards, the duration is added first, then
$(D add!"months"()) is called, and finally $(D add!"years"()) is called.
That way, going backwards generates close to the same time points that
iterating forward does, but since adding years and months is not entirely
reversible (due to possible day overflow, regardless of whether
AllowDayOverflow.yes or AllowDayOverflow.no is used), it can't be
guaranteed that iterating backwards will give you the same time points as
iterating forward would have (even assuming that the end of the range is a
time point which would be returned by the delegate when iterating forward
from begin).
Params:
dir = The direction to iterate in. If passing the return
value to $(D fwdRange()), use $(D Direction.fwd).
If passing it to $(D bwdRange()), use $(D Direction.bwd).
years = The number of years to add to the time point passed
to the delegate.
months = The number of months to add to the time point passed to
the delegate.
allowOverflow = Whether the days should be allowed to overflow on begin
and end, causing their month to increment.
duration = The duration to add to the time point passed to the
delegate.
Examples:
--------------------
auto interval = Interval!Date(Date(2010, 9, 2), Date(2025, 9, 27));
auto func = everyDuration!Date(4, 1, AllowDayOverflow.yes, dur!"days"(2));
auto range = interval.fwdRange(func);
assert(range.front == Date(2010, 9, 2)); //Using PopFirst.yes would have made this Date(2014, 10, 12).
range.popFront();
assert(range.front == Date(2014, 10, 4));
range.popFront();
assert(range.front == Date(2018, 11, 6));
range.popFront();
assert(range.front == Date(2022, 12, 8));
range.popFront();
assert(range.empty);
--------------------
+/
static TP delegate(in TP) everyDuration(TP, Direction dir = Direction.fwd, D)
(int years,
int months = 0,
AllowDayOverflow allowOverflow = AllowDayOverflow.yes,
D duration = dur!"days"(0)) nothrow
if(isTimePoint!TP &&
__traits(compiles, TP.init + duration) &&
__traits(compiles, TP.init.add!"years"(years)) &&
__traits(compiles, TP.init.add!"months"(months)) &&
(dir == Direction.fwd || dir == Direction.bwd))
{
TP func(in TP tp)
{
static if(dir == Direction.fwd)
{
TP retval = cast(TP)tp;
retval.add!"years"(years, allowOverflow);
retval.add!"months"(months, allowOverflow);
return retval + duration;
}
else
{
TP retval = tp - duration;
retval.add!"months"(-months, allowOverflow);
retval.add!"years"(-years, allowOverflow);
return retval;
}
}
return &func;
}
unittest
{
{
auto funcFwd = everyDuration!Date(1, 2, AllowDayOverflow.yes, dur!"days"(3));
auto funcBwd = everyDuration!(Date, Direction.bwd)(1, 2, AllowDayOverflow.yes, dur!"days"(3));
assertPred!"=="(funcFwd(Date(2009, 12, 25)), Date(2011, 2, 28));
assertPred!"=="(funcFwd(Date(2009, 12, 26)), Date(2011, 3, 1));
assertPred!"=="(funcFwd(Date(2009, 12, 27)), Date(2011, 3, 2));
assertPred!"=="(funcFwd(Date(2009, 12, 28)), Date(2011, 3, 3));
assertPred!"=="(funcFwd(Date(2009, 12, 29)), Date(2011, 3, 4));
assertPred!"=="(funcBwd(Date(2011, 2, 28)), Date(2009, 12, 25));
assertPred!"=="(funcBwd(Date(2011, 3, 1)), Date(2009, 12, 26));
assertPred!"=="(funcBwd(Date(2011, 3, 2)), Date(2009, 12, 27));
assertPred!"=="(funcBwd(Date(2011, 3, 3)), Date(2009, 12, 28));
assertPred!"=="(funcBwd(Date(2011, 3, 4)), Date(2010, 1, 1));
}
{
auto funcFwd = everyDuration!Date(1, 2, AllowDayOverflow.no, dur!"days"(3));
auto funcBwd = everyDuration!(Date, Direction.bwd)(1, 2, AllowDayOverflow.yes, dur!"days"(3));
assertPred!"=="(funcFwd(Date(2009, 12, 25)), Date(2011, 2, 28));
assertPred!"=="(funcFwd(Date(2009, 12, 26)), Date(2011, 3, 1));
assertPred!"=="(funcFwd(Date(2009, 12, 27)), Date(2011, 3, 2));
assertPred!"=="(funcFwd(Date(2009, 12, 28)), Date(2011, 3, 3));
assertPred!"=="(funcFwd(Date(2009, 12, 29)), Date(2011, 3, 3));
assertPred!"=="(funcBwd(Date(2011, 2, 28)), Date(2009, 12, 25));
assertPred!"=="(funcBwd(Date(2011, 3, 1)), Date(2009, 12, 26));
assertPred!"=="(funcBwd(Date(2011, 3, 2)), Date(2009, 12, 27));
assertPred!"=="(funcBwd(Date(2011, 3, 3)), Date(2009, 12, 28));
assertPred!"=="(funcBwd(Date(2011, 3, 4)), Date(2010, 1, 1));
}
static assert(__traits(compiles, everyDuration!Date(1, 2, AllowDayOverflow.yes, dur!"hnsecs"(1))));
static assert(!__traits(compiles, everyDuration!TimeOfDay(1, 2, AllowDayOverflow.yes, dur!"hnsecs"(1))));
static assert(__traits(compiles, everyDuration!DateTime(1, 2, AllowDayOverflow.yes, dur!"hnsecs"(1))));
static assert(__traits(compiles, everyDuration!SysTime(1, 2, AllowDayOverflow.yes, dur!"hnsecs"(1))));
//Verify Examples.
auto interval = Interval!Date(Date(2010, 9, 2), Date(2025, 9, 27));
auto func = everyDuration!Date(4, 1, AllowDayOverflow.yes, dur!"days"(2));
auto range = interval.fwdRange(func);
assert(range.front == Date(2010, 9, 2)); //Using PopFirst.yes would have made this Date(2014, 10, 12).
range.popFront();
assert(range.front == Date(2014, 10, 4));
range.popFront();
assert(range.front == Date(2018, 11, 6));
range.popFront();
assert(range.front == Date(2022, 12, 8));
range.popFront();
assert(range.empty);
}
//TODO Add function to create a range generating function based on a date recurrence pattern string.
// This may or may not involve creating a date recurrence pattern class of some sort - probably
// yes if we want to make it easy to build them. However, there is a standard recurrence
// pattern string format which we'd want to support with a range generator (though if we have
// the class/struct, we'd probably want a version of the range generating function which took
// that rather than a string).
//==============================================================================
// Section with ranges.
//==============================================================================
/++
A range over an $(D Interval).
$(D IntervalRange) is only ever constructed by $(D Interval). However, when
it is constructed, it is given a function, $(D func), which is used to generate
the time points which are iterated over. $(D func()) takes a time point and
returns a time point of the same type. So, for instance, if you had an
$(D Interval!Date), and you wanted to iterate over all of the days in that
interval, you would pass a function to $(D Interval)'s $(D fwdRange()) where
that function took a $(D Date) and returned a $(D Date) which was one day
later. That function would then be used by $(D IntervalRange)'s $(D popFront())
to iterate over the $(D Date)s in the interval.
If $(D dir == Direction.fwd), then a range iterates forward in time, while if
$(D dir == Direction.bwd), then it iterates backwards in time. So, if
$(D dir == Direction.fwd) then $(D front == interval.begin), while if
$(D dir == Direction.bwd) then $(D front == interval.end). $(D func) must generate
a time point going in the proper direction of iteration, or a
$(D DateTimeException) will be thrown. So, if you're iterating forward in time,
the time point that func generates must be later in time than the one passed
to it. If it's either identical or earlier in time, then a $(D DateTimeException)
will be thrown. If you're iterating backwards, then the generated time point
must be before the time point which was passed in.
If the generated time point is ever passed the edge of the range in the proper
direction, then the edge of that range will be used instead. So, if iterating
forward, and the generated time point is past the interval's end, then front
becomes end. If iterating backwards, and the generated time point is before
begin, then front becomes begin. In either case, the range would then be empty.
Also note that while normally the begin of an interval is included in it and
its end is excluded from it, if $(D dir == Direction.bwd), then begin is
treated as excluded and end is treated as included. This allows for the same
behavior in both directions. This works because none of $(D Interval)'s functions
which care about whether begin or end is included or excluded are ever called
by $(D IntervalRange). $(D interval) returns a normal interval, regardless of
whether $(D dir == Direction.fwd) or if $(D dir == Direction.bwd), so any
$(D Interval) functions which are called on it which care about whether begin
or end are included or excluded will treat begin as included and end as excluded.
+/
struct IntervalRange(TP, Direction dir)
if(isTimePoint!TP && dir != Direction.both)
{
public:
/++
Params:
rhs = The IntervalRange to assign to this one.
+/
/+ref+/ IntervalRange opAssign(ref IntervalRange rhs) pure nothrow
{
_interval = rhs._interval;
_func = rhs._func;
return this;
}
/++
Whether this IntervalRange is empty.
+/
@property bool empty() const pure nothrow
{
return _interval.empty;
}
/++
The first time point in the range.
Throws:
DateTimeException if empty is true.
+/
@property TP front() const pure
{
_enforceNotEmpty();
static if(dir == Direction.fwd)
return _interval.begin;
else
return _interval.end;
}
/++
Pops front from the range, using $(D func()) to generate the next time
point in the range. If the generated time point is beyond the edge of
the range, then front is set to that edge, end the range is then empty.
So, if iterating forwards, and the generated time point is greater
than the interval's end, then front is set to end. If iterating
backwards, and the generated time point is less than the interval's
begin, then front is set to begin.
Throws:
DateTimeException if empty is true or if the generated time point is
in the wrong direction (i.e. if you're iterating forward and the
generated time point is before front, or if you're iterating
backwards, and the generated time point is after front).
+/
void popFront()
{
_enforceNotEmpty();
static if(dir == Direction.fwd)
{
auto begin = _func(_interval.begin);
if(begin > _interval.end)
begin = _interval.end;
_enforceCorrectDirection(begin);
_interval.begin = begin;
}
else
{
auto end = _func(_interval.end);
if(end < _interval.begin)
end = _interval.begin;
_enforceCorrectDirection(end);
_interval.end = end;
}
}
/++
Returns a copy of $(D this).
+/
@property IntervalRange save() pure nothrow
{
return this;
}
/++
The interval that this IntervalRange currently covers.
+/
@property Interval!TP interval() const pure nothrow
{
return cast(Interval!TP)_interval;
}
/++
The function used to generate the next time point in the range.
+/
TP delegate(in TP) func() pure nothrow @property
{
return _func;
}
/++
The Direction that this range iterates in.
+/
@property Direction direction() const pure nothrow
{
return dir;
}
private:
/+
Params:
interval = The interval that this range covers.
func = The function used to generate the time points which are iterated over.
+/
this(in Interval!TP interval, TP delegate(in TP) func) pure nothrow
{
_func = func;
_interval = interval;
}
/++
Throws:
DateTimeException if empty is true.
+/
void _enforceNotEmpty(size_t line = __LINE__) const pure
{
if(empty)
throw new DateTimeException("Invalid operation for an empty IntervalRange.", __FILE__, line);
}
/++
Throws:
DateTimeException if newTP is in the wrong direction.
+/
void _enforceCorrectDirection(in TP newTP, size_t line = __LINE__) const
{
static if(dir == Direction.fwd)
{
enforce(newTP > _interval._begin,
new DateTimeException(format("Generated time point is before previous begin: prev [%s] new [%s]",
interval._begin,
newTP),
__FILE__,
line));
}
else
{
enforce(newTP < _interval._end,
new DateTimeException(format("Generated time point is after previous end: prev [%s] new [%s]",
interval._end,
newTP),
__FILE__,
line));
}
}
Interval!TP _interval;
TP delegate(in TP) _func;
}
//Test that IntervalRange satisfies the range predicates that it's supposed to satisfy.
unittest
{
static assert(isInputRange!(IntervalRange!(Date, Direction.fwd)));
static assert(isForwardRange!(IntervalRange!(Date, Direction.fwd)));
//Commented out due to bug http://d.puremagic.com/issues/show_bug.cgi?id=4895
//static assert(!isOutputRange!(IntervalRange!(Date, Direction.fwd), Date));
static assert(!isBidirectionalRange!(IntervalRange!(Date, Direction.fwd)));
static assert(!isRandomAccessRange!(IntervalRange!(Date, Direction.fwd)));
static assert(!hasSwappableElements!(IntervalRange!(Date, Direction.fwd)));
static assert(!hasAssignableElements!(IntervalRange!(Date, Direction.fwd)));
static assert(!hasLength!(IntervalRange!(Date, Direction.fwd)));
static assert(!isInfinite!(IntervalRange!(Date, Direction.fwd)));
static assert(!hasSlicing!(IntervalRange!(Date, Direction.fwd)));
static assert(is(ElementType!(IntervalRange!(Date, Direction.fwd)) == Date));
static assert(is(ElementType!(IntervalRange!(TimeOfDay, Direction.fwd)) == TimeOfDay));
static assert(is(ElementType!(IntervalRange!(DateTime, Direction.fwd)) == DateTime));
static assert(is(ElementType!(IntervalRange!(SysTime, Direction.fwd)) == SysTime));
}
//Test construction of IntervalRange.
unittest
{
{
Date dateFunc(in Date date)
{
return date;
}
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto ir = IntervalRange!(Date, Direction.fwd)(interval, &dateFunc);
}
{
TimeOfDay todFunc(in TimeOfDay tod)
{
return tod;
}
auto interval = Interval!TimeOfDay(TimeOfDay(12, 1, 7), TimeOfDay(14, 0, 0));
auto ir = IntervalRange!(TimeOfDay, Direction.fwd)(interval, &todFunc);
}
{
DateTime dtFunc(in DateTime dt)
{
return dt;
}
auto interval = Interval!DateTime(DateTime(2010, 7, 4, 12, 1, 7), DateTime(2012, 1, 7, 14, 0, 0));
auto ir = IntervalRange!(DateTime, Direction.fwd)(interval, &dtFunc);
}
{
SysTime stFunc(in SysTime st)
{
return cast(SysTime)st;
}
auto interval = Interval!SysTime(SysTime(DateTime(2010, 7, 4, 12, 1, 7)), SysTime(DateTime(2012, 1, 7, 14, 0, 0)));
auto ir = IntervalRange!(SysTime, Direction.fwd)(interval, &stFunc);
}
}
//Test IntervalRange's empty().
unittest
{
//fwd
{
auto range = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 21)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
assert(!range.empty);
range.popFront();
assert(range.empty);
const cRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
static assert(__traits(compiles, cRange.empty));
//Apparently, creating an immutable IntervalRange!Date doesn't work, so we can't test if
//empty works with it. However, since an immutable range is pretty useless, it's no great loss.
}
//bwd
{
auto range = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 21)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
assert(!range.empty);
range.popFront();
assert(range.empty);
const cRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
static assert(__traits(compiles, cRange.empty));
//Apparently, creating an immutable IntervalRange!Date doesn't work, so we can't test if
//empty works with it. However, since an immutable range is pretty useless, it's no great loss.
}
}
//Test IntervalRange's front.
unittest
{
//fwd
{
auto emptyRange = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 20)).fwdRange(everyDayOfWeek!Date(DayOfWeek.wed), PopFirst.yes);
assertThrown!DateTimeException((in IntervalRange!(Date, Direction.fwd) range){range.front;}(emptyRange));
auto range = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).fwdRange(everyDayOfWeek!Date(DayOfWeek.wed));
assertPred!"=="(range.front, Date(2010, 7, 4));
auto poppedRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).fwdRange(everyDayOfWeek!Date(DayOfWeek.wed), PopFirst.yes);
assertPred!"=="(poppedRange.front, Date(2010, 7, 7));
const cRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
static assert(__traits(compiles, cRange.front));
}
//bwd
{
auto emptyRange = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 20)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed), PopFirst.yes);
assertThrown!DateTimeException((in IntervalRange!(Date, Direction.bwd) range){range.front;}(emptyRange));
auto range = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed));
assertPred!"=="(range.front, Date(2012, 1, 7));
auto poppedRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed), PopFirst.yes);
assertPred!"=="(poppedRange.front, Date(2012, 1, 4));
const cRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
static assert(__traits(compiles, cRange.front));
}
}
//Test IntervalRange's popFront().
unittest
{
//fwd
{
auto emptyRange = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 20)).fwdRange(everyDayOfWeek!Date(DayOfWeek.wed), PopFirst.yes);
assertThrown!DateTimeException((IntervalRange!(Date, Direction.fwd) range){range.popFront();}(emptyRange));
auto range = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).fwdRange(everyDayOfWeek!Date(DayOfWeek.wed), PopFirst.yes);
auto expected = range.front;
foreach(date; range)
{
assertPred!"=="(date, expected);
expected += dur!"days"(7);
}
assertPred!"=="(walkLength(range), 79);
const cRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
static assert(__traits(compiles, cRange.front));
}
//bwd
{
auto emptyRange = Interval!Date(Date(2010, 9, 19), Date(2010, 9, 20)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed), PopFirst.yes);
assertThrown!DateTimeException((IntervalRange!(Date, Direction.bwd) range){range.popFront();}(emptyRange));
auto range = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed), PopFirst.yes);
auto expected = range.front;
foreach(date; range)
{
assertPred!"=="(date, expected);
expected += dur!"days"(-7);
}
assertPred!"=="(walkLength(range), 79);
const cRange = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
static assert(!__traits(compiles, cRange.popFront()));
}
}
//Test IntervalRange's save.
unittest
{
//fwd
{
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto func = everyDayOfWeek!Date(DayOfWeek.fri);
auto range = interval.fwdRange(func);
assert(range.save == range);
}
//bwd
{
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto func = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri);
auto range = interval.bwdRange(func);
assert(range.save == range);
}
}
//Test IntervalRange's interval.
unittest
{
//fwd
{
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto func = everyDayOfWeek!Date(DayOfWeek.fri);
auto range = interval.fwdRange(func);
assert(range.interval == interval);
const cRange = range;
static assert(__traits(compiles, cRange.interval));
}
//bwd
{
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto func = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri);
auto range = interval.bwdRange(func);
assert(range.interval == interval);
const cRange = range;
static assert(__traits(compiles, cRange.interval));
}
}
//Test IntervalRange's func.
unittest
{
//fwd
{
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto func = everyDayOfWeek!Date(DayOfWeek.fri);
auto range = interval.fwdRange(func);
assert(range.func == func);
}
//bwd
{
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto func = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri);
auto range = interval.bwdRange(func);
assert(range.func == func);
}
}
//Test IntervalRange's direction.
unittest
{
//fwd
{
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto func = everyDayOfWeek!Date(DayOfWeek.fri);
auto range = interval.fwdRange(func);
assert(range.direction == Direction.fwd);
const cRange = range;
static assert(__traits(compiles, cRange.direction));
}
//bwd
{
auto interval = Interval!Date(Date(2010, 7, 4), Date(2012, 1, 7));
auto func = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri);
auto range = interval.bwdRange(func);
assert(range.direction == Direction.bwd);
const cRange = range;
static assert(__traits(compiles, cRange.direction));
}
}
/++
A range over a $(D PosInfInterval). It is an infinite range.
$(D PosInfIntervalRange) is only ever constructed by $(D PosInfInterval).
However, when it is constructed, it is given a function, $(D func()), which
is used to generate the time points which are iterated over. $(D func())
takes a time point and returns a time point of the same type. So, for instance,
if you had a $(D PosInfInterval!Date), and you wanted to iterate over all
of the days in that interval, you would pass a function to $(D PosInfInterval)'s
$(D fwdRange()) where that function took a $(D Date) and returned a $(D Date)
which was one day later. That function would then be used by
$(D PosInfIntervalRange)'s $(D popFront()) to iterate over the $(D Date)s in
the interval. Though obviously, since the range is infinite, you would use a
function such as $(D std.range.take()) with it rather than iterating over
*all* of the dates.
As the interval goes to positive infinity, the range is always iterated over
forwards, never backwards. $(D func()) must generate a time point going in
the proper direction of iteration, or a $(D DateTimeException) will be thrown.
So, the time points that $(D func()) generates must be later in time than
the one passed to it. If it's either identical or earlier in time, then a
$(D DateTimeException) will be thrown.
+/
struct PosInfIntervalRange(TP)
if(isTimePoint!TP)
{
public:
/++
Params:
rhs = The PosInfIntervalRange to assign to this one.
+/
/+ref+/ PosInfIntervalRange opAssign(ref PosInfIntervalRange rhs) pure nothrow
{
_interval = rhs._interval;
_func = rhs._func;
return this;
}
/++
This is an infinite range, so it is never empty.
+/
enum bool empty = false;
/++
The first time point in the range.
+/
@property TP front() const pure nothrow
{
return _interval.begin;
}
/++
Pops front from the range, using func to generate the next time point
in the range.
Throws:
DateTimeException if the generated time point is less than than
front.
+/
void popFront()
{
auto begin = _func(_interval.begin);
_enforceCorrectDirection(begin);
_interval.begin = begin;
}
/++
Returns a copy of $(D this).
+/
@property PosInfIntervalRange save() pure nothrow
{
return this;
}
/++
The interval that this range currently covers.
+/
@property PosInfInterval!TP interval() const pure nothrow
{
return cast(PosInfInterval!TP)_interval;
}
/++
The function used to generate the next time point in the range.
+/
TP delegate(in TP) func() pure nothrow @property
{
return _func;
}
private:
/++
Params:
interval = The interval that this range covers.
func = The function used to generate the time points which are
iterated over.
+/
this(in PosInfInterval!TP interval, TP delegate(in TP) func) pure nothrow
{
_func = func;
_interval = interval;
}
/++
Throws:
DateTimeException if newTP is in the wrong direction.
+/
void _enforceCorrectDirection(in TP newTP, size_t line = __LINE__) const
{
enforce(newTP > _interval._begin,
new DateTimeException(format("Generated time point is before previous begin: prev [%s] new [%s]",
interval._begin,
newTP),
__FILE__,
line));
}
PosInfInterval!TP _interval;
TP delegate(in TP) _func;
}
//Test that PosInfIntervalRange satisfies the range predicates that it's supposed to satisfy.
unittest
{
static assert(isInputRange!(PosInfIntervalRange!Date));
static assert(isForwardRange!(PosInfIntervalRange!Date));
static assert(isInfinite!(PosInfIntervalRange!Date));
//Commented out due to bug http://d.puremagic.com/issues/show_bug.cgi?id=4895
//static assert(!isOutputRange!(PosInfIntervalRange!Date, Date));
static assert(!isBidirectionalRange!(PosInfIntervalRange!Date));
static assert(!isRandomAccessRange!(PosInfIntervalRange!Date));
static assert(!hasSwappableElements!(PosInfIntervalRange!Date));
static assert(!hasAssignableElements!(PosInfIntervalRange!Date));
static assert(!hasLength!(PosInfIntervalRange!Date));
static assert(!hasSlicing!(PosInfIntervalRange!Date));
static assert(is(ElementType!(PosInfIntervalRange!Date) == Date));
static assert(is(ElementType!(PosInfIntervalRange!TimeOfDay) == TimeOfDay));
static assert(is(ElementType!(PosInfIntervalRange!DateTime) == DateTime));
static assert(is(ElementType!(PosInfIntervalRange!SysTime) == SysTime));
}
//Test construction of PosInfIntervalRange.
unittest
{
{
Date dateFunc(in Date date)
{
return date;
}
auto posInfInterval = PosInfInterval!Date(Date(2010, 7, 4));
auto ir = PosInfIntervalRange!Date(posInfInterval, &dateFunc);
}
{
TimeOfDay todFunc(in TimeOfDay tod)
{
return tod;
}
auto posInfInterval = PosInfInterval!TimeOfDay(TimeOfDay(12, 1, 7));
auto ir = PosInfIntervalRange!(TimeOfDay)(posInfInterval, &todFunc);
}
{
DateTime dtFunc(in DateTime dt)
{
return dt;
}
auto posInfInterval = PosInfInterval!DateTime(DateTime(2010, 7, 4, 12, 1, 7));
auto ir = PosInfIntervalRange!(DateTime)(posInfInterval, &dtFunc);
}
{
SysTime stFunc(in SysTime st)
{
return cast(SysTime)st;
}
auto posInfInterval = PosInfInterval!SysTime(SysTime(DateTime(2010, 7, 4, 12, 1, 7)));
auto ir = PosInfIntervalRange!(SysTime)(posInfInterval, &stFunc);
}
}
//Test PosInfIntervalRange's front.
unittest
{
auto range = PosInfInterval!Date(Date(2010, 7, 4)).fwdRange(everyDayOfWeek!Date(DayOfWeek.wed));
assertPred!"=="(range.front, Date(2010, 7, 4));
auto poppedRange = PosInfInterval!Date(Date(2010, 7, 4)).fwdRange(everyDayOfWeek!Date(DayOfWeek.wed), PopFirst.yes);
assertPred!"=="(poppedRange.front, Date(2010, 7, 7));
const cRange = PosInfInterval!Date(Date(2010, 7, 4)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
static assert(__traits(compiles, cRange.front));
}
//Test PosInfIntervalRange's popFront().
unittest
{
auto range = PosInfInterval!Date(Date(2010, 7, 4)).fwdRange(everyDayOfWeek!Date(DayOfWeek.wed), PopFirst.yes);
auto expected = range.front;
foreach(date; take(range, 79))
{
assertPred!"=="(date, expected);
expected += dur!"days"(7);
}
const cRange = PosInfInterval!Date(Date(2010, 7, 4)).fwdRange(everyDayOfWeek!Date(DayOfWeek.fri));
static assert(!__traits(compiles, cRange.popFront()));
}
//Test PosInfIntervalRange's save.
unittest
{
auto interval = PosInfInterval!Date(Date(2010, 7, 4));
auto func = everyDayOfWeek!Date(DayOfWeek.fri);
auto range = interval.fwdRange(func);
assert(range.save == range);
}
//Test PosInfIntervalRange's interval.
unittest
{
auto interval = PosInfInterval!Date(Date(2010, 7, 4));
auto func = everyDayOfWeek!Date(DayOfWeek.fri);
auto range = interval.fwdRange(func);
assert(range.interval == interval);
const cRange = range;
static assert(__traits(compiles, cRange.interval));
}
//Test PosInfIntervalRange's func.
unittest
{
auto interval = PosInfInterval!Date(Date(2010, 7, 4));
auto func = everyDayOfWeek!Date(DayOfWeek.fri);
auto range = interval.fwdRange(func);
assert(range.func == func);
}
/++
A range over a $(D NegInfInterval). It is an infinite range.
$(D NegInfIntervalRange) is only ever constructed by $(D NegInfInterval).
However, when it is constructed, it is given a function, $(D func()), which
is used to generate the time points which are iterated over. $(D func())
takes a time point and returns a time point of the same type. So, for instance,
if you had a $(D NegInfInterval!Date), and you wanted to iterate over all
of the days in that interval, you would pass a function to $(D NegInfInterval)'s
$(D bwdRange()) where that function took a $(D Date) and returned a $(D Date)
which was one day earlier. That function would then be used by
$(D NegInfIntervalRange)'s $(D popFront()) to iterate over the $(D Date)s in
the interval. Though obviously, since the range is infinite, you would use a
function such as $(D std.range.take()) with it rather than iterating over
*all* of the dates.
As the interval goes to negative infinity, the range is always iterated over
backwards, never forwards. $(D func()) must generate a time point going in
the proper direction of iteration, or a $(D DateTimeException) will be thrown.
So, the time points that $(D func()) generates must be earlier in time than
the one passed to it. If it's either identical or later in time, then a
$(D DateTimeException) will be thrown.
Also note that while normally the end of an interval is excluded from it,
$(D NegInfIntervalRange) treats it as if it were included. This allows for
the same behavior as you get with $(D PosInfIntervalRange). This works
because none of $(D NegInfInterval)'s functions which care about whether
end is included or excluded are ever called by $(D NegInfIntervalRange).
$(D interval) returns a normal interval, so any $(D NegInfInterval)
functions which are called on it which care about whether end is included
or excluded will treat end as excluded.
+/
struct NegInfIntervalRange(TP)
if(isTimePoint!TP)
{
public:
/++
Params:
rhs = The NegInfIntervalRange to assign to this one.
+/
/+ref+/ NegInfIntervalRange opAssign(ref NegInfIntervalRange rhs) pure nothrow
{
_interval = rhs._interval;
_func = rhs._func;
return this;
}
/++
This is an infinite range, so it is never empty.
+/
enum bool empty = false;
/++
The first time point in the range.
+/
@property TP front() const pure nothrow
{
return _interval.end;
}
/++
Pops front from the range, using func to generate the next time point
in the range.
Throws:
DateTimeException if the generated time point is greater than than
front.
+/
void popFront()
{
auto end = _func(_interval.end);
_enforceCorrectDirection(end);
_interval.end = end;
}
/++
Returns a copy of $(D this).
+/
@property NegInfIntervalRange save() pure nothrow
{
return this;
}
/++
The interval that this range currently covers.
+/
@property NegInfInterval!TP interval() const pure nothrow
{
return cast(NegInfInterval!TP)_interval;
}
/++
The function used to generate the next time point in the range.
+/
TP delegate(in TP) func() pure nothrow @property
{
return _func;
}
private:
/+
Params:
interval = The interval that this range covers.
func = The function used to generate the time points which are
iterated over.
+/
this(in NegInfInterval!TP interval, TP delegate(in TP) func) pure nothrow
{
_func = func;
_interval = interval;
}
/+
Throws:
DateTimeException if newTP is in the wrong direction.
+/
void _enforceCorrectDirection(in TP newTP, size_t line = __LINE__) const
{
enforce(newTP < _interval._end,
new DateTimeException(format("Generated time point is before previous end: prev [%s] new [%s]",
interval._end,
newTP),
__FILE__,
line));
}
NegInfInterval!TP _interval;
TP delegate(in TP) _func;
}
//Test that NegInfIntervalRange satisfies the range predicates that it's supposed to satisfy.
unittest
{
static assert(isInputRange!(NegInfIntervalRange!Date));
static assert(isForwardRange!(NegInfIntervalRange!Date));
static assert(isInfinite!(NegInfIntervalRange!Date));
//Commented out due to bug http://d.puremagic.com/issues/show_bug.cgi?id=4895
//static assert(!isOutputRange!(NegInfIntervalRange!Date, Date));
static assert(!isBidirectionalRange!(NegInfIntervalRange!Date));
static assert(!isRandomAccessRange!(NegInfIntervalRange!Date));
static assert(!hasSwappableElements!(NegInfIntervalRange!Date));
static assert(!hasAssignableElements!(NegInfIntervalRange!Date));
static assert(!hasLength!(NegInfIntervalRange!Date));
static assert(!hasSlicing!(NegInfIntervalRange!Date));
static assert(is(ElementType!(NegInfIntervalRange!Date) == Date));
static assert(is(ElementType!(NegInfIntervalRange!TimeOfDay) == TimeOfDay));
static assert(is(ElementType!(NegInfIntervalRange!DateTime) == DateTime));
}
//Test construction of NegInfIntervalRange.
unittest
{
{
Date dateFunc(in Date date)
{
return date;
}
auto negInfInterval = NegInfInterval!Date(Date(2012, 1, 7));
auto ir = NegInfIntervalRange!Date(negInfInterval, &dateFunc);
}
{
TimeOfDay todFunc(in TimeOfDay tod)
{
return tod;
}
auto negInfInterval = NegInfInterval!TimeOfDay(TimeOfDay(14, 0, 0));
auto ir = NegInfIntervalRange!(TimeOfDay)(negInfInterval, &todFunc);
}
{
DateTime dtFunc(in DateTime dt)
{
return dt;
}
auto negInfInterval = NegInfInterval!DateTime(DateTime(2012, 1, 7, 14, 0, 0));
auto ir = NegInfIntervalRange!(DateTime)(negInfInterval, &dtFunc);
}
{
SysTime stFunc(in SysTime st)
{
return cast(SysTime)(st);
}
auto negInfInterval = NegInfInterval!SysTime(SysTime(DateTime(2012, 1, 7, 14, 0, 0)));
auto ir = NegInfIntervalRange!(SysTime)(negInfInterval, &stFunc);
}
}
//Test NegInfIntervalRange's front.
unittest
{
auto range = NegInfInterval!Date(Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed));
assertPred!"=="(range.front, Date(2012, 1, 7));
auto poppedRange = NegInfInterval!Date(Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed), PopFirst.yes);
assertPred!"=="(poppedRange.front, Date(2012, 1, 4));
const cRange = NegInfInterval!Date(Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
static assert(__traits(compiles, cRange.front));
}
//Test NegInfIntervalRange's popFront().
unittest
{
auto range = NegInfInterval!Date(Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.wed), PopFirst.yes);
auto expected = range.front;
foreach(date; take(range, 79))
{
assertPred!"=="(date, expected);
expected += dur!"days"(-7);
}
const cRange = NegInfInterval!Date(Date(2012, 1, 7)).bwdRange(everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri));
static assert(!__traits(compiles, cRange.popFront()));
}
//Test NegInfIntervalRange's save.
unittest
{
auto interval = NegInfInterval!Date(Date(2012, 1, 7));
auto func = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri);
auto range = interval.bwdRange(func);
assert(range.save == range);
}
//Test NegInfIntervalRange's interval.
unittest
{
auto interval = NegInfInterval!Date(Date(2012, 1, 7));
auto func = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri);
auto range = interval.bwdRange(func);
assert(range.interval == interval);
const cRange = range;
static assert(__traits(compiles, cRange.interval));
}
//Test NegInfIntervalRange's func.
unittest
{
auto interval = NegInfInterval!Date(Date(2012, 1, 7));
auto func = everyDayOfWeek!(Date, Direction.bwd)(DayOfWeek.fri);
auto range = interval.bwdRange(func);
assert(range.func == func);
}
//==============================================================================
// Section with time zones.
//==============================================================================
/++
Represents a time zone. It is used with SysTime to indicate the time zone of
a SysTime.
+/
abstract class TimeZone
{
public:
/++
The name of the time zone per the TZ database. This is the name used to
get a TimeZone by name with TimeZone.getTimeZone().
See_Also:
Wikipedia entry on TZ database
List of Time Zones
+/
@property string name() const nothrow
{
return _name;
}
/++
Typically, the abbreviation (generally 3 or 4 letters) for the time zone
when DST is $(I not) in effect (e.g. PST). It is not necessarily unique.
However, on Windows, it may be the unabbreviated name (e.g. Pacific
Standard Time). Regardless, it is not the same as name.
+/
@property string stdName() const nothrow
{
return _stdName;
}
/++
Typically, the abbreviation (generally 3 or 4 letters) for the time zone
when DST $(I is) in effect (e.g. PDT). It is not necessarily unique.
However, on Windows, it may be the unabbreviated name (e.g. Pacific
Daylight Time). Regardless, it is not the same as name.
+/
@property string dstName() const nothrow
{
return _dstName;
}
/++
Whether this time zone has Daylight Savings Time at any point in time.
Note that for some time zone types it may not have DST for current dates
but will still return true for hasDST because the time zone did at some
point have DST.
+/
@property abstract bool hasDST() const nothrow;
/++
Takes the number of hecto-nanoseconds (100 ns) since midnight, January 1st,
1 A.D. in UTC time (i.e. std time) and returns whether DST is effect in
this time zone at the given point in time.
Params:
stdTime = The UTC time that needs to be checked for DST in this time zone.
+/
abstract bool dstInEffect(long stdTime) const nothrow;
/++
Takes the number of hecto-nanoseconds (100 ns) since midnight, January 1st,
1 A.D. in UTC time (i.e. std time) and converts it to this time zone's time.
Params:
stdTime = The UTC time that needs to be adjusted to this time zone's
time.
+/
abstract long utcToTZ(long stdTime) const nothrow;
/++
Takes the number of hecto-nanoseconds (100 ns) since midnight, January 1st,
1 A.D. in this time zone's time and converts it to UTC (i.e. std time).
Params:
adjTime = The time in this time zone that needs to be adjusted to
UTC time.
+/
abstract long tzToUTC(long adjTime) const nothrow;
/++
Returns a TimeZone with the give name per the TZ database.
This returns a PosixTimeZone on Posix systems and a WindowsTimeZone on
Windows systems. If you want a PosixTimeZone on Windows, then call
$(D PosixTimeZone.getTimeZone()) directly and give it the location of
the TZ database time zone files on disk.
See_Also:
Wikipedia entry on TZ database
List of Time Zones
Params:
name = The TZ database name of the time zone that you're looking for.
Throws:
DateTimeException if the given time zone could not be found.
Examples:
--------------------
auto tz = TimeZone.getTimeZone("America/Los_Angeles");
--------------------
+/
static immutable(TimeZone) getTimeZone(string name)
{
version(Posix)
return PosixTimeZone.getTimeZone(name);
else version(Windows)
return WindowsTimeZone.getTimeZone(name);
}
unittest
{
//Verify Example.
auto tz = TimeZone.getTimeZone("America/Los_Angeles");
}
/++
Returns a list of the names of the time zones installed on the system.
You can provide a sub-name to narrow down the list of time zones (which
will likely be in the thousands if you get them all). For example,
if you pass in "America" as the sub-name, then only the time zones which
begin with "America" will be returned.
Params:
subname = The first part of the time zones that you want.
Throws:
FileException on Posix systems if it fails to read from disk.
DateTimeException on Windows systems if it fails to read the registry.
+/
static string[] getInstalledTZNames(string subname = "")
{
version(Posix)
return PosixTimeZone.getInstalledTZNames(subname);
else version(Windows)
return WindowsTimeZone.getInstalledTZNames(subname);
}
private:
/++
Params:
name = The TZ database name for the time zone.
stdName = The abbreviation for the time zone during std time.
dstName = The abbreviation for the time zone during DST.
+/
this(string name, string stdName, string dstName) immutable pure
{
_name = name;
_stdName = stdName;
_dstName = dstName;
}
immutable string _name;
immutable string _stdName;
immutable string _dstName;
}
version(Posix)
{
//This should be in core.stdc.time, but it isn't, so
//we're declaring it here.
extern(C)
{
extern __gshared char* tzname[2];
extern __gshared int daylight;
}
}
/++
A TimeZone which represents the current local time zone on
the system running your program.
This uses the underlying C calls to adjust the time rather
than using specific D code based off of system settings to calculate
the time such as PosixTimeZone and WindowsTimeZone do. That also
means that it will use whatever the current time zone is on the system,
even if the system's time zone changes while the program is running.
+/
final class LocalTime : TimeZone
{
public:
/++
LocalTime is a singleton class. $(D LocalTime()) returns its only instance.
+/
static immutable(LocalTime) opCall() pure nothrow
{
return _localTime;
}
version(D_Ddoc)
{
/++
The name of the time zone per the TZ database. This is the name used to
get a TimeZone by name with $(D TimeZone.getTimeZone()).
Note that this always returns the empty string. This is because time
zones cannot be uniquely identified by the attributes given by the OS
(such as the stdName and dstName), and neither Posix systems nor
Windows systems provide an easy way to get the TZ database name of
the local time zone.
See_Also:
Wikipedia entry on TZ database
List of Time Zones
+/
@property override string name() const nothrow
{
return super.name;
}
}
/++
Typically, the abbreviation (generally 3 or 4 letters) for the time zone
when DST is $(I not) in effect (e.g. PST). It is not necessarily unique.
However, on Windows, it may be the unabbreviated name (e.g. Pacific
Standard Time). Regardless, it is not the same as name.
This property is overridden because the local time of the system could
change while the program is running and we need to determine it dynamically
rather than it being fixed like it would be with most time zones.
+/
@property override string stdName() const nothrow
{
version(Posix)
{
try
return to!string(tzname[0]);
catch(Exception e)
assert(0, "to!string(tzname[0]) failed.");
}
else version(Windows)
{
try
{
TIME_ZONE_INFORMATION tzInfo;
GetTimeZoneInformation(&tzInfo);
//Cannot use to!string() like this should, probably due to bug http://d.puremagic.com/issues/show_bug.cgi?id=5016
//return to!string(tzInfo.StandardName);
wchar[32] str;
foreach(i, ref wchar c; str)
c = tzInfo.StandardName[i];
string retval;
foreach(dchar c; str)
{
if(c == '\0')
break;
retval ~= c;
}
return retval;
}
catch(Exception e)
assert(0, "GetTimeZoneInformation() threw.");
}
}
unittest
{
assert(LocalTime().stdName !is null);
version(Posix)
{
scope(exit) clearTZEnvVar();
setTZEnvVar("America/Los_Angeles");
assertPred!"=="(LocalTime().stdName, "PST");
setTZEnvVar("America/New_York");
assertPred!"=="(LocalTime().stdName, "EST");
}
}
/++
Typically, the abbreviation (generally 3 or 4 letters) for the time zone
when DST $(I is) in effect (e.g. PDT). It is not necessarily unique.
However, on Windows, it may be the unabbreviated name (e.g. Pacific
Daylight Time). Regardless, it is not the same as name.
This property is overridden because the local time of the system could
change while the program is running and we need to determine it
dynamically rather than it being fixed like it would be with most time
zones.
+/
@property override string dstName() const nothrow
{
version(Posix)
{
try
return to!string(tzname[1]);
catch(Exception e)
assert(0, "to!string(tzname[0]) failed.");
}
else version(Windows)
{
try
{
TIME_ZONE_INFORMATION tzInfo;
GetTimeZoneInformation(&tzInfo);
//Cannot use to!string() like this should, probably due to bug http://d.puremagic.com/issues/show_bug.cgi?id=5016
//return to!string(tzInfo.DaylightName);
wchar[32] str;
foreach(i, ref wchar c; str)
c = tzInfo.DaylightName[i];
string retval;
foreach(dchar c; str)
{
if(c == '\0')
break;
retval ~= c;
}
return retval;
}
catch(Exception e)
assert(0, "GetTimeZoneInformation() threw.");
}
}
unittest
{
assert(LocalTime().dstName !is null);
version(Posix)
{
scope(exit) clearTZEnvVar();
setTZEnvVar("America/Los_Angeles");
assertPred!"=="(LocalTime().dstName, "PDT");
setTZEnvVar("America/New_York");
assertPred!"=="(LocalTime().dstName, "EDT");
}
}
/++
Whether this time zone has Daylight Savings Time at any point in time.
Note that for some time zone types it may not have DST for current
dates but will still return true for hasDST because the time zone did
at some point have DST.
+/
@property override bool hasDST() const nothrow
{
version(Posix)
return cast(bool)(daylight);
else version(Windows)
{
try
{
TIME_ZONE_INFORMATION tzInfo;
GetTimeZoneInformation(&tzInfo);
return tzInfo.DaylightDate.wMonth != 0;
}
catch(Exception e)
assert(0, "GetTimeZoneInformation() threw.");
}
}
unittest
{
LocalTime().hasDST;
version(Posix)
{
scope(exit) clearTZEnvVar();
setTZEnvVar("America/Los_Angeles");
assert(LocalTime().hasDST);
setTZEnvVar("America/New_York");
assert(LocalTime().hasDST);
}
}
/++
Takes the number of hecto-nanoseconds (100 ns) since midnight, January
1st, 1 A.D. in UTC time (i.e. std time) and returns whether DST is in
effect in this time zone at the given point in time.
Params:
stdTime = The UTC time that needs to be checked for DST in this time zone.
+/
override bool dstInEffect(long stdTime) const nothrow
{
time_t unixTime = stdTimeToUnixTime(stdTime);
version(Posix)
{
tm* timeInfo = localtime(&unixTime);
return cast(bool)(timeInfo.tm_isdst);
}
else version(Windows)
{
//Apparently Windows isn't smart enough to deal with negative time_t.
if(unixTime >= 0)
{
tm* timeInfo = localtime(&unixTime);
if(timeInfo)
return cast(bool)(timeInfo.tm_isdst);
}
TIME_ZONE_INFORMATION tzInfo;
try
GetTimeZoneInformation(&tzInfo);
catch(Exception e)
assert(0, "The impossible happened. GetTimeZoneInformation() threw.");
return WindowsTimeZone._dstInEffect(&tzInfo, stdTime);
}
}
unittest
{
auto currTime = Clock.currStdTime;
LocalTime().dstInEffect(currTime);
version(Posix)
{
scope(exit) clearTZEnvVar();
auto std = SysTime(DateTime(2010, 1, 1, 12, 0, 0), LocalTime());
auto dst = SysTime(DateTime(2010, 7, 1, 12, 0, 0), LocalTime());
setTZEnvVar("America/Los_Angeles");
assert(!LocalTime().dstInEffect(std.stdTime));
assert(LocalTime().dstInEffect(dst.stdTime));
assert(!std.dstInEffect);
assert(dst.dstInEffect);
setTZEnvVar("America/New_York");
assert(!LocalTime().dstInEffect(std.stdTime));
assert(LocalTime().dstInEffect(dst.stdTime));
assert(!std.dstInEffect);
assert(dst.dstInEffect);
}
}
/++
Returns hnsecs in the local time zone using the standard C function calls
on Posix systems and the standard Windows system calls on Windows systems
to adjust the time to the appropriate time zone from std time.
Params:
stdTime = The UTC time that needs to be adjusted to this time zone's
time.
See_Also:
TimeZone.utcToTZ()
+/
override long utcToTZ(long stdTime) const nothrow
{
version(Posix)
{
time_t unixTime = stdTimeToUnixTime(stdTime);
tm* timeInfo = localtime(&unixTime);
return stdTime + convert!("seconds", "hnsecs")(timeInfo.tm_gmtoff);
}
else version(Windows)
{
TIME_ZONE_INFORMATION tzInfo;
try
GetTimeZoneInformation(&tzInfo);
catch(Exception e)
assert(0, "GetTimeZoneInformation() threw.");
return WindowsTimeZone._utcToTZ(&tzInfo, stdTime, hasDST);
}
}
unittest
{
LocalTime().utcToTZ(0);
version(Posix)
{
scope(exit) clearTZEnvVar();
{
setTZEnvVar("America/Los_Angeles");
auto std = SysTime(Date(2010, 1, 1));
auto dst = SysTime(Date(2010, 7, 1));
assertPred!"=="(LocalTime().utcToTZ(std.stdTime), SysTime(DateTime(2009, 12, 31, 16, 0, 0)).stdTime);
assertPred!"=="(LocalTime().utcToTZ(dst.stdTime), SysTime(DateTime(2010, 6, 30, 17, 0, 0)).stdTime);
}
{
setTZEnvVar("America/New_York");
auto std = SysTime(Date(2010, 1, 1));
auto dst = SysTime(Date(2010, 7, 1));
assertPred!"=="(LocalTime().utcToTZ(std.stdTime), SysTime(DateTime(2009, 12, 31, 19, 0, 0)).stdTime);
assertPred!"=="(LocalTime().utcToTZ(dst.stdTime), SysTime(DateTime(2010, 6, 30, 20, 0, 0)).stdTime);
}
}
}
/++
Returns std time using the standard C function calls on Posix systems
and the standard Windows system calls on Windows systems to adjust the
time to UTC from the appropriate time zone.
See_Also:
TimeZone.tzToUTC()
Params:
adjTime = The time in this time zone that needs to be adjusted to
UTC time.
+/
override long tzToUTC(long adjTime) const nothrow
{
version(Posix)
{
time_t unixTime = stdTimeToUnixTime(adjTime);
tm* timeInfo = localtime(&unixTime);
return adjTime - convert!("seconds", "hnsecs")(timeInfo.tm_gmtoff);
}
else version(Windows)
{
TIME_ZONE_INFORMATION tzInfo;
try
GetTimeZoneInformation(&tzInfo);
catch(Exception e)
assert(0, "GetTimeZoneInformation() threw.");
return WindowsTimeZone._tzToUTC(&tzInfo, adjTime, hasDST);
}
}
unittest
{
LocalTime().tzToUTC(0);
assertPred!"=="(LocalTime().tzToUTC(LocalTime().utcToTZ(0)), 0);
assertPred!"=="(LocalTime().utcToTZ(LocalTime().tzToUTC(0)), 0);
version(Posix)
{
scope(exit) clearTZEnvVar();
{
setTZEnvVar("America/Los_Angeles");
auto std = SysTime(DateTime(2009, 12, 31, 16, 0, 0));
auto dst = SysTime(DateTime(2010, 6, 30, 17, 0, 0));
assertPred!"=="(LocalTime().tzToUTC(std.stdTime), SysTime(Date(2010, 1, 1)).stdTime);
assertPred!"=="(LocalTime().tzToUTC(dst.stdTime), SysTime(Date(2010, 7, 1)).stdTime);
}
{
setTZEnvVar("America/New_York");
auto std = SysTime(DateTime(2009, 12, 31, 19, 0, 0));
auto dst = SysTime(DateTime(2010, 6, 30, 20, 0, 0));
assertPred!"=="(LocalTime().tzToUTC(std.stdTime), SysTime(Date(2010, 1, 1)).stdTime);
assertPred!"=="(LocalTime().tzToUTC(dst.stdTime), SysTime(Date(2010, 7, 1)).stdTime);
}
}
}
private:
this() immutable pure
{
super("", "", "");
}
static immutable LocalTime _localTime;
static this()
{
tzset();
_localTime = new immutable(LocalTime)();
}
}
/++
A TimeZone which represents UTC.
+/
final class UTC : TimeZone
{
public:
/++
UTC is a singleton class. $(D UTC()) returns its only instance.
+/
static immutable(UTC) opCall() pure nothrow
{
return _utc;
}
/++
Always returns false.
+/
@property override bool hasDST() const nothrow
{
return false;
}
/++
Always returns false.
+/
override bool dstInEffect(long stdTime) const nothrow
{
return false;
}
/++
Returns the given hnsecs without changing them at all.
Params:
stdTime = The UTC time that needs to be adjusted to this time zone's
time.
See_Also:
TimeZone.utcToTZ()
+/
override long utcToTZ(long stdTime) const nothrow
{
return stdTime;
}
unittest
{
assertPred!"=="(UTC().utcToTZ(0), 0);
version(Posix)
{
scope(exit) clearTZEnvVar();
setTZEnvVar("UTC");
auto std = SysTime(Date(2010, 1, 1));
auto dst = SysTime(Date(2010, 7, 1));
assertPred!"=="(UTC().utcToTZ(std.stdTime), std.stdTime);
assertPred!"=="(UTC().utcToTZ(dst.stdTime), dst.stdTime);
}
}
/++
Returns the given hnsecs without changing them at all.
See_Also:
TimeZone.tzToUTC()
Params:
adjTime = The time in this time zone that needs to be adjusted to
UTC time.
+/
override long tzToUTC(long adjTime) const nothrow
{
return adjTime;
}
unittest
{
assertPred!"=="(UTC().tzToUTC(0), 0);
version(Posix)
{
scope(exit) clearTZEnvVar();
setTZEnvVar("UTC");
auto std = SysTime(Date(2010, 1, 1));
auto dst = SysTime(Date(2010, 7, 1));
assertPred!"=="(UTC().tzToUTC(std.stdTime), std.stdTime);
assertPred!"=="(UTC().tzToUTC(dst.stdTime), dst.stdTime);
}
}
private:
this() immutable pure
{
super("UTC", "UTC", "UTC");
}
static immutable UTC _utc;
static this()
{
_utc = new immutable(UTC)();
}
}
/++
Represents a time zone with an offset (in minutes, west is negative) from
UTC but no DST.
It's primarily used as the time zone in the result of $(D SysTime)'s
$(D fromISOString()), $(D fromISOExtendedString()), and
$(D fromSimpleString()).
$(D name) and $(D dstName) are always the empty string since this time zone
has no DST and while it may be meant to represent a time zone which is in
the TZ database, obviously it's not likely to be following the exact rules
of any of the time zones in the TZ database, so it makes no sense to set it.
+/
final class SimpleTimeZone : TimeZone
{
public:
/++
Always returns false.
+/
@property override bool hasDST() const nothrow
{
return false;
}
/++
Always returns false.
+/
override bool dstInEffect(long stdTime) const nothrow
{
return false;
}
/++
Takes the number of hecto-nanoseconds (100 ns) since midnight, January
1st, 1 A.D. in UTC time (i.e. std time) and converts it to this time
zone's time.
Params:
stdTime = The UTC time that needs to be adjusted to this time
zone's time.
+/
override long utcToTZ(long stdTime) const nothrow
{
return stdTime + convert!("minutes", "hnsecs")(utcOffset);
}
unittest
{
assertPred!"=="((new SimpleTimeZone(-8 * 60)).utcToTZ(0), -288_000_000_000L);
assertPred!"=="((new SimpleTimeZone(8 * 60)).utcToTZ(0), 288_000_000_000L);
assertPred!"=="((new SimpleTimeZone(-8 * 60)).utcToTZ(54_321_234_567_890L), 54_033_234_567_890L);
auto stz = new SimpleTimeZone(-8 * 60);
const cstz = new SimpleTimeZone(-8 * 60);
static assert(__traits(compiles, stz.utcToTZ(50002)));
static assert(__traits(compiles, cstz.utcToTZ(50002)));
}
/++
Takes the number of hecto-nanoseconds (100 ns) since midnight, January
1st, 1 A.D. in this time zone's time and converts it to UTC
(i.e. std time).
Params:
adjTime = The time in this time zone that needs to be adjusted to
UTC time.
+/
override long tzToUTC(long adjTime) const nothrow
{
return adjTime - convert!("minutes", "hnsecs")(utcOffset);
}
unittest
{
assertPred!"=="((new SimpleTimeZone(-8 * 60)).tzToUTC(-288_000_000_000L), 0);
assertPred!"=="((new SimpleTimeZone(8 * 60)).tzToUTC(288_000_000_000L), 0);
assertPred!"=="((new SimpleTimeZone(-8 * 60)).tzToUTC(54_033_234_567_890L), 54_321_234_567_890L);
auto stz = new SimpleTimeZone(-8 * 60);
const cstz = new SimpleTimeZone(-8 * 60);
static assert(__traits(compiles, stz.tzToUTC(20005)));
static assert(__traits(compiles, cstz.tzToUTC(20005)));
}
/++
Params:
utcOffset = This time zone's offset from UTC in minutes with west
of UTC being negative (it is added to UTC to get the
adjusted time).
stdName = The stdName for this time zone.
+/
this(int utcOffset, string stdName = "") immutable
{
enforce(abs(utcOffset) < 1440, new DateTimeException("Offset from UTC must be within range (-24:00 - 24:00)."));
super("", stdName, "");
this.utcOffset = utcOffset;
}
unittest
{
auto stz = new SimpleTimeZone(-8 * 60, "PST");
assertPred!"=="(stz.name, "");
assertPred!"=="(stz.stdName, "PST");
assertPred!"=="(stz.dstName, "");
assertPred!"=="(stz.utcOffset, -8 * 60);
}
/++
The number of minutes the offset from UTC is (negative is west of UTC,
positive is east).
+/
immutable int utcOffset;
private:
/++
Returns a time zone as a string with an offset from UTC.
Time zone offsets will be in the form +HH:MM or -HH:MM.
Params:
utcOffset = The number of minutes offset from UTC (negative means
west).
+/
static string toISOString(int utcOffset)
{
immutable absOffset = abs(utcOffset);
enforce(absOffset < 1440, new DateTimeException("Offset from UTC must be within range (-24:00 - 24:00)."));
immutable hours = convert!("minutes", "hours")(absOffset);
immutable minutes = absOffset - convert!("hours", "minutes")(hours);
if(utcOffset < 0)
return format("-%02d:%02d", hours, minutes);
return format("+%02d:%02d", hours, minutes);
}
unittest
{
static string testSTZInvalid(int offset)
{
return SimpleTimeZone.toISOString(offset);
}
assertThrown!DateTimeException(testSTZInvalid(1440));
assertThrown!DateTimeException(testSTZInvalid(-1440));
assertPred!"=="(toISOString(0), "+00:00");
assertPred!"=="(toISOString(1), "+00:01");
assertPred!"=="(toISOString(10), "+00:10");
assertPred!"=="(toISOString(59), "+00:59");
assertPred!"=="(toISOString(60), "+01:00");
assertPred!"=="(toISOString(90), "+01:30");
assertPred!"=="(toISOString(120), "+02:00");
assertPred!"=="(toISOString(480), "+08:00");
assertPred!"=="(toISOString(1439), "+23:59");
assertPred!"=="(toISOString(-1), "-00:01");
assertPred!"=="(toISOString(-10), "-00:10");
assertPred!"=="(toISOString(-59), "-00:59");
assertPred!"=="(toISOString(-60), "-01:00");
assertPred!"=="(toISOString(-90), "-01:30");
assertPred!"=="(toISOString(-120), "-02:00");
assertPred!"=="(toISOString(-480), "-08:00");
assertPred!"=="(toISOString(-1439), "-23:59");
}
/++
Takes a time zone as a string with an offset from UTC and returns a
$(D SimpleTimeZone) which matches.
The accepted formats for time zone offsets are +H, -H, +HH, -HH, +H:MM,
-H:MM, +HH:MM, and -HH:MM.
Params:
isoString = A string which represents a time zone in the ISO format.
+/
static immutable(SimpleTimeZone) fromISOString(S)(S isoString)
if(isSomeString!(S))
{
auto dstr = to!dstring(strip(isoString));
enforce(dstr.startsWith("-") || dstr.startsWith("+"), new DateTimeException("Invalid ISO String"));
auto sign = dstr.startsWith("-") ? -1 : 1;
dstr.popFront();
enforce(!dstr.empty, new DateTimeException("Invalid ISO String"));
immutable colon = dstr.indexOf(":");
dstring hoursStr;
dstring minutesStr;
if(colon != -1)
{
hoursStr = dstr[0 .. colon];
minutesStr = dstr[colon + 1 .. $];
enforce(minutesStr.length == 2, new DateTimeException(format("Invalid ISO String: %s", dstr)));
}
else
hoursStr = dstr;
enforce(!canFind!((dchar c){return !isdigit(c);})(hoursStr), new DateTimeException(format("Invalid ISO String: %s", dstr)));
enforce(!canFind!((dchar c){return !isdigit(c);})(minutesStr), new DateTimeException(format("Invalid ISO String: %s", dstr)));
immutable hours = to!int(hoursStr);
immutable minutes = minutesStr.empty ? 0 : to!int(minutesStr);
return new SimpleTimeZone(sign * cast(int)(convert!("hours", "minutes")(hours) + minutes));
}
unittest
{
assertThrown!DateTimeException(SimpleTimeZone.fromISOString(""));
assertThrown!DateTimeException(SimpleTimeZone.fromISOString("Z"));
assertThrown!DateTimeException(SimpleTimeZone.fromISOString("-"));
assertThrown!DateTimeException(SimpleTimeZone.fromISOString("+"));
assertThrown!DateTimeException(SimpleTimeZone.fromISOString("-:"));
assertThrown!DateTimeException(SimpleTimeZone.fromISOString("+:"));
assertThrown!DateTimeException(SimpleTimeZone.fromISOString("-1:"));
assertThrown!DateTimeException(SimpleTimeZone.fromISOString("+1:"));
assertThrown!DateTimeException(SimpleTimeZone.fromISOString("1"));
assertThrown!DateTimeException(SimpleTimeZone.fromISOString("-24:00"));
assertThrown!DateTimeException(SimpleTimeZone.fromISOString("+24:00"));
assertThrown!DateTimeException(SimpleTimeZone.fromISOString("+1:0"));
assertPred!"=="(SimpleTimeZone.fromISOString("+00:00").utcOffset, (new SimpleTimeZone(0)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("+00:01").utcOffset, (new SimpleTimeZone(1)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("+00:10").utcOffset, (new SimpleTimeZone(10)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("+00:59").utcOffset, (new SimpleTimeZone(59)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("+01:00").utcOffset, (new SimpleTimeZone(60)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("+01:30").utcOffset, (new SimpleTimeZone(90)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("+02:00").utcOffset, (new SimpleTimeZone(120)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("+08:00").utcOffset, (new SimpleTimeZone(480)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("+23:59").utcOffset, (new SimpleTimeZone(1439)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("-00:01").utcOffset, (new SimpleTimeZone(-1)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("-00:10").utcOffset, (new SimpleTimeZone(-10)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("-00:59").utcOffset, (new SimpleTimeZone(-59)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("-01:00").utcOffset, (new SimpleTimeZone(-60)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("-01:30").utcOffset, (new SimpleTimeZone(-90)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("-02:00").utcOffset, (new SimpleTimeZone(-120)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("-08:00").utcOffset, (new SimpleTimeZone(-480)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("-23:59").utcOffset, (new SimpleTimeZone(-1439)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("+0").utcOffset, (new SimpleTimeZone(0)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("+1").utcOffset, (new SimpleTimeZone(60)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("+2").utcOffset, (new SimpleTimeZone(120)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("+23").utcOffset, (new SimpleTimeZone(1380)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("+2").utcOffset, (new SimpleTimeZone(120)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("+0").utcOffset, (new SimpleTimeZone(0)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("+1").utcOffset, (new SimpleTimeZone(60)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("+2").utcOffset, (new SimpleTimeZone(120)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("+23").utcOffset, (new SimpleTimeZone(1380)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("+1:00").utcOffset, (new SimpleTimeZone(60)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("+1:01").utcOffset, (new SimpleTimeZone(61)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("-0").utcOffset, (new SimpleTimeZone(0)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("-1").utcOffset, (new SimpleTimeZone(-60)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("-2").utcOffset, (new SimpleTimeZone(-120)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("-23").utcOffset, (new SimpleTimeZone(-1380)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("-1:00").utcOffset, (new SimpleTimeZone(-60)).utcOffset);
assertPred!"=="(SimpleTimeZone.fromISOString("-1:01").utcOffset, (new SimpleTimeZone(-61)).utcOffset);
}
//Test that converting from an ISO string to a SimpleTimeZone to an ISO String works properly.
unittest
{
static void testSTZ(in string isoString, int expectedOffset, size_t line = __LINE__)
{
auto stz = SimpleTimeZone.fromISOString(isoString);
assertPred!"=="(stz.utcOffset, expectedOffset, "", __FILE__, line);
auto result = SimpleTimeZone.toISOString(stz.utcOffset);
assertPred!"=="(result, isoString, "", __FILE__, line);
}
testSTZ("+00:00", 0);
testSTZ("+00:01", 1);
testSTZ("+00:10", 10);
testSTZ("+00:59", 59);
testSTZ("+01:00", 60);
testSTZ("+01:30", 90);
testSTZ("+02:00", 120);
testSTZ("+08:00", 480);
testSTZ("+08:00", 480);
testSTZ("+23:59", 1439);
testSTZ("-00:01", -1);
testSTZ("-00:10", -10);
testSTZ("-00:59", -59);
testSTZ("-01:00", -60);
testSTZ("-01:30", -90);
testSTZ("-02:00", -120);
testSTZ("-08:00", -480);
testSTZ("-08:00", -480);
testSTZ("-23:59", -1439);
}
}
/++
Represents a time zone from a TZ database time zone file. Files from the TZ
database are how Posix systems hold their time zone information. Unfortunately,
Windows does not use the TZ database, though it does name its time zones
using the TZ database names. You can, however, use PosixTimeZone (which reads
its information from the TZ database files on disk) on Windows if you provide
the TZ database files
( Repository with the TZ database files (tzdata) )
yourself and tell $(D PosixTimeZone.getTimeZone()) where the directory holding
them is.
TZ database files hold DST transitions for a large interval of the time
covered by time_t. So, barring errors in the information in the TZ database
files, it will use the correct DST rules for any date. Windows, on the other
hand, maintains only the current DST rules, so historical dates will use the
current DST rules (and therefore potentially be incorrect). So, if you want
the DST rules that you use to be more accurate, or if you're looking for your
program to act consistently on both Posix and Windows systems, then, as
mentioned above, you'll need to include the TZ database files with your program
and give $(D PosixTimeZone.getTimeZone()) the directory on disk where they
are located.
To get a PosixTimeZone, either call $(D PosixTimeZone.getTimeZone()) (which
will allow you to specify the location the time zone files) or call
$(D TimeZone.getTimeZone()) (which will give you a PosixTimeZone on Posix
systems and a WindowsTimeZone on Windows systems).
Note:
Unless your system's local time zone deals with leap seconds (which is
highly unlikely), then only way that you will get a time zone which takes
leap seconds into account is if you use PosixTimeZone with a time zone
whose name starts with "right/". Those time zone files do include leap
seconds, and PosixTimeZone will take them into account (though posix
systems which use a "right/" time zone as their local time zone will
*not* take leap seconds into account even though they're in the file).
See_Also:
Wikipedia entry on TZ database
List of Time Zones
+/
final class PosixTimeZone : TimeZone
{
public:
/++
Whether this time zone has Daylight Savings Time at any point in time.
Note that for some time zone types it may not have DST for current
dates but will still return true for hasDST because the time zone did
at some point have DST.
+/
@property override bool hasDST() const nothrow
{
return _hasDST;
}
/++
Takes the number of hecto-nanoseconds (100 ns) since midnight, January
1st, 1 A.D. in UTC time (i.e. std time) and returns whether DST is in
effect in this time zone at the given point in time.
Params:
stdTime = The UTC time that needs to be checked for DST in this time zone.
+/
override bool dstInEffect(long stdTime) const nothrow
{
assert(!_transitions.empty);
try
{
immutable unixTime = stdTimeToUnixTime(stdTime);
if(_transitions.front.timeT >= unixTime)
return _transitions.front.ttInfo.isDST;
//Okay, casting is a hack, but indexOf shouldn't be changing it, and it would be
//too inefficient to have to keep duping it every time we have to calculate the time.
//Hopefully, indexOf will properly support immutable ranges at some point.
auto found = std.algorithm.indexOf!"b < a.timeT"(cast(Transition[])_transitions, unixTime);
if(found == -1)
return _transitions.back.ttInfo.isDST;
auto transition = found == 0 ? _transitions[0] : _transitions[found - 1];
return transition.ttInfo.isDST;
}
catch(Exception e)
assert(0, format("Nothing in calculateLeapSeconds() should be throwing. Caught Exception: %s", e));
}
/++
Takes the number of hecto-nanoseconds (100 ns) since midnight, January 1st,
1 A.D. in UTC time (i.e. std time) and converts it to this time zone's time.
Params:
stdTime = The UTC time that needs to be adjusted to this time zone's time.
+/
override long utcToTZ(long stdTime) const nothrow
{
assert(!_transitions.empty);
try
{
immutable leapSecs = calculateLeapSeconds(stdTime);
immutable unixTime = stdTimeToUnixTime(stdTime);
if(_transitions.front.timeT >= unixTime)
return stdTime + convert!("seconds", "hnsecs")(_transitions.front.ttInfo.utcOffset + leapSecs);
//Okay, casting is a hack, but indexOf shouldn't be changing it, and it would be
//too inefficient to have to keep duping it every time we have to calculate the time.
//Hopefully, indexOf will properly support immutable ranges at some point.
auto found = std.algorithm.indexOf!"b < a.timeT"(cast(Transition[])_transitions, unixTime);
if(found == -1)
return stdTime + convert!("seconds", "hnsecs")(_transitions.back.ttInfo.utcOffset + leapSecs);
auto transition = found == 0 ? _transitions[0] : _transitions[found - 1];
return stdTime + convert!("seconds", "hnsecs")(transition.ttInfo.utcOffset + leapSecs);
}
catch(Exception e)
assert(0, format("Nothing in calculateLeapSeconds() should be throwing. Caught Exception: %s", e));
}
/++
Takes the number of hecto-nanoseconds (100 ns) since midnight, January
1st, 1 A.D. in this time zone's time and converts it to UTC
(i.e. std time).
Params:
adjTime = The time in this time zone that needs to be adjusted to UTC time.
+/
override long tzToUTC(long adjTime) const nothrow
{
assert(!_transitions.empty);
try
{
immutable leapSecs = calculateLeapSeconds(adjTime);
immutable unixTime = stdTimeToUnixTime(adjTime);
if(_transitions.front.timeT >= unixTime)
return adjTime - convert!("seconds", "hnsecs")(_transitions.front.ttInfo.utcOffset + leapSecs);
//Okay, casting is a hack, but indexOf shouldn't be changing it, and it would be
//too inefficient to have to keep duping it every time we have to calculate the time.
//Hopefully, indexOf will properly support immutable ranges at some point.
auto found = std.algorithm.indexOf!"b < a.timeT"(cast(Transition[])_transitions, unixTime);
if(found == -1)
return adjTime - convert!("seconds", "hnsecs")(_transitions.back.ttInfo.utcOffset + leapSecs);
auto transition = found == 0 ? _transitions[0] : _transitions[found - 1];
return adjTime - convert!("seconds", "hnsecs")(transition.ttInfo.utcOffset + leapSecs);
}
catch(Exception e)
assert(0, format("Nothing in calculateLeapSeconds() should be throwing. Caught Exception: %s", e));
}
version(Posix)
/// The default directory where the TZ database files are. It's empty for Windows, since Windows doesn't have them.
enum defaultTZDatabaseDir = "/usr/share/zoneinfo/";
else version(Windows)
/// The default directory where the TZ database files are. It's empty for Windows, since Windows doesn't have them.
enum defaultTZDatabaseDir = "";
/++
Returns a TimeZone with the give name per the TZ database. The time zone
information is fetched from the TZ database time zone files in the given
directory.
See_Also:
Wikipedia entry on TZ database
List of Time Zones
Params:
name = The TZ database name of the time zone that you're
looking for.
tzDatabaseDir = The directory where the TZ database files are located.
Because these files are not located on Windows systems,
you will need to provide them yourself and give their
location here if you wish to use PosixTimeZones.
Throws:
DateTimeException if the given time zone could not be found or
FileException if the TZ database file could not be opened.
Examples:
--------------------
auto tz = PosixTimeZone.getTimeZone("America/Los_Angeles");
assert(tz.name == "America/Los_Angeles");
assert(tz.stdName == "PST");
assert(tz.dstName == "PDT");
--------------------
+/
//TODO make it possible for tzDatabaseDir to be gzipped tar file rather than an uncompressed
// directory.
static immutable(PosixTimeZone) getTimeZone(string name, string tzDatabaseDir = defaultTZDatabaseDir)
{
name = strip(name);
enforce(tzDatabaseDir.exists, new DateTimeException(format("Directory %s does not exist.", tzDatabaseDir)));
enforce(tzDatabaseDir.isdir, new DateTimeException(format("%s is not a directory.", tzDatabaseDir)));
version(Posix)
auto file = tzDatabaseDir ~ sep ~ name;
else version(Windows)
auto file = tzDatabaseDir ~ sep ~ replace(strip(name), "/", sep);
enforce(file.exists, new DateTimeException(format("File %s does not exist.", file)));
enforce(file.isfile, new DateTimeException(format("%s is not a file.", file)));
auto tzFile = File(file);
immutable gmtZone = file.canFind("GMT");
try
{
_enforceValidTZFile(readVal!(char[])(tzFile, 4) == "TZif");
immutable char tzFileVersion = readVal!char(tzFile);
_enforceValidTZFile(tzFileVersion == '\0' || tzFileVersion == '2');
{
auto zeroBlock = readVal!(ubyte[])(tzFile, 15);
bool allZeroes = true;
foreach(val; zeroBlock)
{
if(val != 0)
{
allZeroes = false;
break;
}
}
_enforceValidTZFile(allZeroes);
}
//The number of UTC/local indicators stored in the file.
auto tzh_ttisgmtcnt = readVal!int(tzFile);
//The number of standard/wall indicators stored in the file.
auto tzh_ttisstdcnt = readVal!int(tzFile);
//The number of leap seconds for which data is stored in the file.
auto tzh_leapcnt = readVal!int(tzFile);
//The number of "transition times" for which data is stored in the file.
auto tzh_timecnt = readVal!int(tzFile);
//The number of "local time types" for which data is stored in the file (must not be zero).
auto tzh_typecnt = readVal!int(tzFile);
_enforceValidTZFile(tzh_typecnt != 0);
//The number of characters of "timezone abbreviation strings" stored in the file.
auto tzh_charcnt = readVal!int(tzFile);
//time_ts where DST transitions occur.
auto transitionTimeTs = new long[](tzh_timecnt);
foreach(ref transition; transitionTimeTs)
transition = readVal!int(tzFile);
//Indices into ttinfo structs indicating the changes
//to be made at the corresponding DST transition.
auto ttInfoIndices = new ubyte[](tzh_timecnt);
foreach(ref ttInfoIndex; ttInfoIndices)
ttInfoIndex = readVal!ubyte(tzFile);
//ttinfos which give info on DST transitions.
auto tempTTInfos = new TempTTInfo[](tzh_typecnt);
foreach(ref ttInfo; tempTTInfos)
ttInfo = readVal!TempTTInfo(tzFile);
//The array of time zone abbreviation characters.
auto tzAbbrevChars = readVal!(char[])(tzFile, tzh_charcnt);
auto leapSeconds = new LeapSecond[](tzh_leapcnt);
foreach(ref leapSecond; leapSeconds)
{
//The time_t when the leap second occurs.
auto timeT = readVal!int(tzFile);
//The total number of leap seconds to be applied after
//the corresponding leap second.
auto total = readVal!int(tzFile);
leapSecond = LeapSecond(timeT, total);
}
//Indicate whether each corresponding DST transition were specified
//in standard time or wall clock time.
auto transitionIsStd = new bool[](tzh_ttisstdcnt);
foreach(ref isStd; transitionIsStd)
isStd = readVal!bool(tzFile);
//Indicate whether each corresponding DST transition associated with
//local time types are specified in UTC or local time.
auto transitionInUTC = new bool[](tzh_ttisgmtcnt);
foreach(ref inUTC; transitionInUTC)
inUTC = readVal!bool(tzFile);
_enforceValidTZFile(!tzFile.eof());
//If version 2, the information is duplicated in 64-bit.
if(tzFileVersion == '2')
{
_enforceValidTZFile(readVal!(char[])(tzFile, 4) == "TZif");
_enforceValidTZFile(readVal!(char)(tzFile) == '2');
{
auto zeroBlock = readVal!(ubyte[])(tzFile, 15);
bool allZeroes = true;
foreach(val; zeroBlock)
{
if(val != 0)
{
allZeroes = false;
break;
}
}
_enforceValidTZFile(allZeroes);
}
//The number of UTC/local indicators stored in the file.
tzh_ttisgmtcnt = readVal!int(tzFile);
//The number of standard/wall indicators stored in the file.
tzh_ttisstdcnt = readVal!int(tzFile);
//The number of leap seconds for which data is stored in the file.
tzh_leapcnt = readVal!int(tzFile);
//The number of "transition times" for which data is stored in the file.
tzh_timecnt = readVal!int(tzFile);
//The number of "local time types" for which data is stored in the file (must not be zero).
tzh_typecnt = readVal!int(tzFile);
_enforceValidTZFile(tzh_typecnt != 0);
//The number of characters of "timezone abbreviation strings" stored in the file.
tzh_charcnt = readVal!int(tzFile);
//time_ts where DST transitions occur.
transitionTimeTs = new long[](tzh_timecnt);
foreach(ref transition; transitionTimeTs)
transition = readVal!long(tzFile);
//Indices into ttinfo structs indicating the changes
//to be made at the corresponding DST transition.
ttInfoIndices = new ubyte[](tzh_timecnt);
foreach(ref ttInfoIndex; ttInfoIndices)
ttInfoIndex = readVal!ubyte(tzFile);
//ttinfos which give info on DST transitions.
tempTTInfos = new TempTTInfo[](tzh_typecnt);
foreach(ref ttInfo; tempTTInfos)
ttInfo = readVal!TempTTInfo(tzFile);
//The array of time zone abbreviation characters.
tzAbbrevChars = readVal!(char[])(tzFile, tzh_charcnt);
leapSeconds = new LeapSecond[](tzh_leapcnt);
foreach(ref leapSecond; leapSeconds)
{
//The time_t when the leap second occurs.
auto timeT = readVal!long(tzFile);
//The total number of leap seconds to be applied after
//the corresponding leap second.
auto total = readVal!int(tzFile);
leapSecond = LeapSecond(timeT, total);
}
//Indicate whether each corresponding DST transition were specified
//in standard time or wall clock time.
transitionIsStd = new bool[](tzh_ttisstdcnt);
foreach(ref isStd; transitionIsStd)
isStd = readVal!bool(tzFile);
//Indicate whether each corresponding DST transition associated with
//local time types are specified in UTC or local time.
transitionInUTC = new bool[](tzh_ttisgmtcnt);
foreach(ref inUTC; transitionInUTC)
inUTC = readVal!bool(tzFile);
}
_enforceValidTZFile(tzFile.readln().strip().empty());
auto posixEnvStr = tzFile.readln().strip();
_enforceValidTZFile(tzFile.readln().strip().empty());
_enforceValidTZFile(tzFile.eof());
auto transitionTypes = new TransitionType*[](tempTTInfos.length);
foreach(i, ref ttype; transitionTypes)
{
bool isStd = false;
if(i < transitionIsStd.length && !transitionIsStd.empty)
isStd = transitionIsStd[i];
bool inUTC = false;
if(i < transitionInUTC.length && !transitionInUTC.empty)
inUTC = transitionInUTC[i];
ttype = new TransitionType(isStd, inUTC);
}
auto ttInfos = new immutable(TTInfo)*[](tempTTInfos.length);
foreach(i, ref ttInfo; ttInfos)
{
auto tempTTInfo = tempTTInfos[i];
if(gmtZone)
tempTTInfo.tt_gmtoff = -tempTTInfo.tt_gmtoff;
auto abbrevChars = tzAbbrevChars[tempTTInfo.tt_abbrind .. $];
string abbrev = abbrevChars[0 .. std.string.indexOf(abbrevChars, "\0")].idup;
ttInfo = new immutable(TTInfo)(tempTTInfos[i], abbrev);
}
auto tempTransitions = new TempTransition[](transitionTimeTs.length);
foreach(i, ref tempTransition; tempTransitions)
{
immutable ttiIndex = ttInfoIndices[i];
auto transitionTimeT = transitionTimeTs[i];
auto ttype = transitionTypes[ttiIndex];
auto ttInfo = ttInfos[ttiIndex];
tempTransition = TempTransition(transitionTimeT, ttInfo, ttype);
}
if(tempTransitions.empty)
{
_enforceValidTZFile(ttInfos.length == 1 && transitionTypes.length == 1);
tempTransitions ~= TempTransition(0, ttInfos[0], transitionTypes[0]);
}
sort!"a.timeT < b.timeT"(tempTransitions);
sort!"a.timeT < b.timeT"(leapSeconds);
auto transitions = new Transition[](tempTransitions.length);
foreach(i, ref transition; transitions)
{
auto tempTransition = tempTransitions[i];
auto transitionTimeT = tempTransition.timeT;
auto ttInfo = tempTransition.ttInfo;
auto ttype = tempTransition.ttype;
_enforceValidTZFile(i == 0 || transitionTimeT > tempTransitions[i - 1].timeT);
transition = Transition(transitionTimeT, ttInfo);
}
string stdName;
string dstName;
bool hasDST = false;
foreach(transition; retro(transitions))
{
auto ttInfo = transition.ttInfo;
if(ttInfo.isDST)
{
if(dstName.empty)
dstName = ttInfo.abbrev;
hasDST = true;
}
else
{
if(stdName.empty)
stdName = ttInfo.abbrev;
}
if(!stdName.empty && !dstName.empty)
break;
}
return new PosixTimeZone(transitions.idup, leapSeconds.idup, name, stdName, dstName, hasDST);
}
catch(DateTimeException dte)
throw dte;
catch(Exception e)
throw new DateTimeException("Not a valid TZ data file", __FILE__, __LINE__, e);
}
//Since reading in the time zone files could be expensive, most unit tests
//are consolidated into this one unittest block which minimizes how often it
//reads a time zone file.
unittest
{
version(Posix)
{
scope(exit) clearTZEnvVar();
//Test for "America/Los_Angeles".
{
//Verify Example for getTimeZone().
auto tz = PosixTimeZone.getTimeZone("America/Los_Angeles");
assert(tz.name == "America/Los_Angeles");
assert(tz.stdName == "PST");
assert(tz.dstName == "PDT");
assert(tz.hasDST);
//Continue testing passed example.
auto std = SysTime(DateTime(2010, 1, 1, 12, 0, 0), tz);
auto dst = SysTime(DateTime(2010, 7, 1, 12, 0, 0), tz);
assert(!std.dstInEffect);
assert(dst.dstInEffect);
setTZEnvVar("America/Los_Angeles");
{
time_t unixTime = std.toUnixTime();
tm* osTimeInfo = localtime(&unixTime);
tm ourTimeInfo = std.toTM();
assertPred!"=="(ourTimeInfo.tm_sec, osTimeInfo.tm_sec);
assertPred!"=="(ourTimeInfo.tm_min, osTimeInfo.tm_min);
assertPred!"=="(ourTimeInfo.tm_hour, osTimeInfo.tm_hour);
assertPred!"=="(ourTimeInfo.tm_min, osTimeInfo.tm_min);
assertPred!"=="(ourTimeInfo.tm_mday, osTimeInfo.tm_mday);
assertPred!"=="(ourTimeInfo.tm_mon, osTimeInfo.tm_mon);
assertPred!"=="(ourTimeInfo.tm_year, osTimeInfo.tm_year);
assertPred!"=="(ourTimeInfo.tm_wday, osTimeInfo.tm_wday);
assertPred!"=="(ourTimeInfo.tm_yday, osTimeInfo.tm_yday);
assertPred!"=="(ourTimeInfo.tm_isdst, osTimeInfo.tm_isdst);
assertPred!"=="(ourTimeInfo.tm_gmtoff, osTimeInfo.tm_gmtoff);
assertPred!"=="(to!string(ourTimeInfo.tm_zone), to!string(osTimeInfo.tm_zone));
}
{
time_t unixTime = dst.toUnixTime();
tm* osTimeInfo = localtime(&unixTime);
tm ourTimeInfo = dst.toTM();
assertPred!"=="(ourTimeInfo.tm_sec, osTimeInfo.tm_sec);
assertPred!"=="(ourTimeInfo.tm_min, osTimeInfo.tm_min);
assertPred!"=="(ourTimeInfo.tm_hour, osTimeInfo.tm_hour);
assertPred!"=="(ourTimeInfo.tm_min, osTimeInfo.tm_min);
assertPred!"=="(ourTimeInfo.tm_mday, osTimeInfo.tm_mday);
assertPred!"=="(ourTimeInfo.tm_mon, osTimeInfo.tm_mon);
assertPred!"=="(ourTimeInfo.tm_year, osTimeInfo.tm_year);
assertPred!"=="(ourTimeInfo.tm_wday, osTimeInfo.tm_wday);
assertPred!"=="(ourTimeInfo.tm_yday, osTimeInfo.tm_yday);
assertPred!"=="(ourTimeInfo.tm_isdst, osTimeInfo.tm_isdst);
assertPred!"=="(ourTimeInfo.tm_gmtoff, osTimeInfo.tm_gmtoff);
assertPred!"=="(to!string(ourTimeInfo.tm_zone), to!string(osTimeInfo.tm_zone));
}
auto leapTZ = PosixTimeZone.getTimeZone("right/America/Los_Angeles");
assert(leapTZ.name == "right/America/Los_Angeles");
assert(leapTZ.stdName == "PST");
assert(leapTZ.dstName == "PDT");
assert(leapTZ.hasDST);
auto leapSTD = SysTime(std.stdTime, leapTZ);
auto leapDST = SysTime(dst.stdTime, leapTZ);
assert(!leapSTD.dstInEffect);
assert(leapDST.dstInEffect);
assertPred!"=="(leapSTD.stdTime, std.stdTime);
assertPred!"=="(leapDST.stdTime, dst.stdTime);
assertPred!"=="(leapSTD.adjTime - convert!("seconds", "hnsecs")(24), std.adjTime);
assertPred!"=="(leapDST.adjTime - convert!("seconds", "hnsecs")(24), dst.adjTime);
}
//Test for "Europe/Paris".
{
auto tz = PosixTimeZone.getTimeZone("Europe/Paris");
assertPred!"=="(tz.name, "Europe/Paris");
assertPred!"=="(tz.stdName, "CET");
assertPred!"=="(tz.dstName, "CEST");
assertPred!"=="(tz.hasDST, true);
auto std = SysTime(DateTime(2010, 1, 1, 12, 0, 0), tz);
auto dst = SysTime(DateTime(2010, 7, 1, 12, 0, 0), tz);
assert(!std.dstInEffect);
assert(dst.dstInEffect);
setTZEnvVar("Europe/Paris");
{
time_t unixTime = std.toUnixTime();
tm* osTimeInfo = localtime(&unixTime);
tm ourTimeInfo = std.toTM();
assertPred!"=="(ourTimeInfo.tm_sec, osTimeInfo.tm_sec);
assertPred!"=="(ourTimeInfo.tm_min, osTimeInfo.tm_min);
assertPred!"=="(ourTimeInfo.tm_hour, osTimeInfo.tm_hour);
assertPred!"=="(ourTimeInfo.tm_min, osTimeInfo.tm_min);
assertPred!"=="(ourTimeInfo.tm_mday, osTimeInfo.tm_mday);
assertPred!"=="(ourTimeInfo.tm_mon, osTimeInfo.tm_mon);
assertPred!"=="(ourTimeInfo.tm_year, osTimeInfo.tm_year);
assertPred!"=="(ourTimeInfo.tm_wday, osTimeInfo.tm_wday);
assertPred!"=="(ourTimeInfo.tm_yday, osTimeInfo.tm_yday);
assertPred!"=="(ourTimeInfo.tm_isdst, osTimeInfo.tm_isdst);
assertPred!"=="(ourTimeInfo.tm_gmtoff, osTimeInfo.tm_gmtoff);
assertPred!"=="(to!string(ourTimeInfo.tm_zone), to!string(osTimeInfo.tm_zone));
}
{
time_t unixTime = dst.toUnixTime();
tm* osTimeInfo = localtime(&unixTime);
tm ourTimeInfo = dst.toTM();
assertPred!"=="(ourTimeInfo.tm_sec, osTimeInfo.tm_sec);
assertPred!"=="(ourTimeInfo.tm_min, osTimeInfo.tm_min);
assertPred!"=="(ourTimeInfo.tm_hour, osTimeInfo.tm_hour);
assertPred!"=="(ourTimeInfo.tm_min, osTimeInfo.tm_min);
assertPred!"=="(ourTimeInfo.tm_mday, osTimeInfo.tm_mday);
assertPred!"=="(ourTimeInfo.tm_mon, osTimeInfo.tm_mon);
assertPred!"=="(ourTimeInfo.tm_year, osTimeInfo.tm_year);
assertPred!"=="(ourTimeInfo.tm_wday, osTimeInfo.tm_wday);
assertPred!"=="(ourTimeInfo.tm_yday, osTimeInfo.tm_yday);
assertPred!"=="(ourTimeInfo.tm_isdst, osTimeInfo.tm_isdst);
assertPred!"=="(ourTimeInfo.tm_gmtoff, osTimeInfo.tm_gmtoff);
assertPred!"=="(to!string(ourTimeInfo.tm_zone), to!string(osTimeInfo.tm_zone));
}
auto leapTZ = PosixTimeZone.getTimeZone("right/Europe/Paris");
assert(leapTZ.name == "right/Europe/Paris");
assert(leapTZ.stdName == "CET");
assert(leapTZ.dstName == "CEST");
assert(leapTZ.hasDST);
auto leapSTD = SysTime(std.stdTime, leapTZ);
auto leapDST = SysTime(dst.stdTime, leapTZ);
assert(!leapSTD.dstInEffect);
assert(leapDST.dstInEffect);
assertPred!"=="(leapSTD.stdTime, std.stdTime);
assertPred!"=="(leapDST.stdTime, dst.stdTime);
assertPred!"=="(leapSTD.adjTime - convert!("seconds", "hnsecs")(24), std.adjTime);
assertPred!"=="(leapDST.adjTime - convert!("seconds", "hnsecs")(24), dst.adjTime);
}
//Test for "UTC".
{
auto tz = PosixTimeZone.getTimeZone("UTC");
assertPred!"=="(tz.name, "UTC");
assertPred!"=="(tz.stdName, "UTC");
assertPred!"=="(tz.dstName, "UTC");
assertPred!"=="(tz.hasDST, false);
auto std = SysTime(DateTime(2010, 1, 1, 12, 0, 0), tz);
auto dst = SysTime(DateTime(2010, 7, 1, 12, 0, 0), tz);
assert(!std.dstInEffect);
assert(!dst.dstInEffect);
setTZEnvVar("UTC");
{
time_t unixTime = std.toUnixTime();
tm* osTimeInfo = localtime(&unixTime);
tm ourTimeInfo = std.toTM();
assertPred!"=="(ourTimeInfo.tm_sec, osTimeInfo.tm_sec);
assertPred!"=="(ourTimeInfo.tm_min, osTimeInfo.tm_min);
assertPred!"=="(ourTimeInfo.tm_hour, osTimeInfo.tm_hour);
assertPred!"=="(ourTimeInfo.tm_min, osTimeInfo.tm_min);
assertPred!"=="(ourTimeInfo.tm_mday, osTimeInfo.tm_mday);
assertPred!"=="(ourTimeInfo.tm_mon, osTimeInfo.tm_mon);
assertPred!"=="(ourTimeInfo.tm_year, osTimeInfo.tm_year);
assertPred!"=="(ourTimeInfo.tm_wday, osTimeInfo.tm_wday);
assertPred!"=="(ourTimeInfo.tm_yday, osTimeInfo.tm_yday);
assertPred!"=="(ourTimeInfo.tm_isdst, osTimeInfo.tm_isdst);
assertPred!"=="(ourTimeInfo.tm_gmtoff, osTimeInfo.tm_gmtoff);
assertPred!"=="(to!string(ourTimeInfo.tm_zone), to!string(osTimeInfo.tm_zone));
}
{
time_t unixTime = dst.toUnixTime();
tm* osTimeInfo = localtime(&unixTime);
tm ourTimeInfo = dst.toTM();
assertPred!"=="(ourTimeInfo.tm_sec, osTimeInfo.tm_sec);
assertPred!"=="(ourTimeInfo.tm_min, osTimeInfo.tm_min);
assertPred!"=="(ourTimeInfo.tm_hour, osTimeInfo.tm_hour);
assertPred!"=="(ourTimeInfo.tm_min, osTimeInfo.tm_min);
assertPred!"=="(ourTimeInfo.tm_mday, osTimeInfo.tm_mday);
assertPred!"=="(ourTimeInfo.tm_mon, osTimeInfo.tm_mon);
assertPred!"=="(ourTimeInfo.tm_year, osTimeInfo.tm_year);
assertPred!"=="(ourTimeInfo.tm_wday, osTimeInfo.tm_wday);
assertPred!"=="(ourTimeInfo.tm_yday, osTimeInfo.tm_yday);
assertPred!"=="(ourTimeInfo.tm_isdst, osTimeInfo.tm_isdst);
assertPred!"=="(ourTimeInfo.tm_gmtoff, osTimeInfo.tm_gmtoff);
assertPred!"=="(to!string(ourTimeInfo.tm_zone), to!string(osTimeInfo.tm_zone));
}
auto leapTZ = PosixTimeZone.getTimeZone("right/UTC");
assert(leapTZ.name == "right/UTC");
assert(leapTZ.stdName == "UTC");
assert(leapTZ.dstName == "UTC");
assert(!leapTZ.hasDST);
auto leapSTD = SysTime(std.stdTime, leapTZ);
auto leapDST = SysTime(dst.stdTime, leapTZ);
assert(!leapSTD.dstInEffect);
assert(!leapDST.dstInEffect);
assertPred!"=="(leapSTD.stdTime, std.stdTime);
assertPred!"=="(leapDST.stdTime, dst.stdTime);
assertPred!"=="(leapSTD.adjTime - convert!("seconds", "hnsecs")(24), std.adjTime);
assertPred!"=="(leapDST.adjTime - convert!("seconds", "hnsecs")(24), dst.adjTime);
}
}
}
/++
Returns a list of the names of the time zones installed on the system.
You can provide a sub-name to narrow down the list of time zones (which
will likely be in the thousands if you get them all). For example,
if you pass in "America" as the sub-name, then only the time zones which
begin with "America" will be returned.
Params:
subname = The first part of the time zones that you want.
Throws:
FileException if it fails to read from disk.
+/
static string[] getInstalledTZNames(string subname = "", string tzDatabaseDir = defaultTZDatabaseDir)
{
version(Posix)
subname = strip(subname);
else version(Windows)
subname = replace(strip(subname), "/", sep);
if(!tzDatabaseDir.endsWith(sep))
tzDatabaseDir ~= sep;
enforce(tzDatabaseDir.exists, new DateTimeException(format("Directory %s does not exist.", tzDatabaseDir)));
enforce(tzDatabaseDir.isdir, new DateTimeException(format("%s is not a directory.", tzDatabaseDir)));
auto timezones = appender!(string[])();
foreach(DirEntry dentry; dirEntries(tzDatabaseDir, SpanMode.depth))
{
if(dentry.isfile)
{
auto tzName = dentry.name[tzDatabaseDir.length .. $];
if(!tzName.getExt().empty())
continue;
if(!tzName.startsWith(subname))
continue;
timezones.put(tzName);
}
}
sort(timezones.data);
return timezones.data;
}
unittest
{
version(Posix)
{
static void testPTZSuccess(string tzName)
{
scope(failure) writefln("TZName which threw: %s", tzName);
PosixTimeZone.getTimeZone(tzName);
}
static void testPTZFailure(string tzName)
{
scope(success) writefln("TZName which was supposed to throw: %s", tzName);
PosixTimeZone.getTimeZone(tzName);
}
auto tzNames = getInstalledTZNames();
foreach(tzName; tzNames)
assertNotThrown!DateTimeException(testPTZSuccess(tzName));
foreach(DirEntry dentry; dirEntries(defaultTZDatabaseDir, SpanMode.depth))
{
if(dentry.isfile)
{
auto tzName = dentry.name[defaultTZDatabaseDir.length .. $];
if(!canFind(tzNames, tzName))
assertThrown!DateTimeException(testPTZFailure(tzName));
}
}
}
}
private:
/++
Holds information on when a time transition occures (usually a
transition to or from DST) as well as a pointer to the
TTInfo which holds information on the utc offset passed the
transition.
+/
struct Transition
{
this(long timeT, immutable (TTInfo)* ttInfo)
{
this.timeT = timeT;
this.ttInfo = ttInfo;
}
long timeT;
immutable (TTInfo)* ttInfo;
}
/++
Holds information on when a leap second occurs.
+/
struct LeapSecond
{
this(long timeT, int total)
{
this.timeT = timeT;
this.total = total;
}
long timeT;
int total;
}
/++
Holds information on the utc offset after a transition as well as
whether DST is in effect after that transition.
+/
struct TTInfo
{
this(in TempTTInfo tempTTInfo, string abbrev) immutable
{
utcOffset = tempTTInfo.tt_gmtoff;
isDST = tempTTInfo.tt_isdst;
this.abbrev = abbrev;
}
immutable int utcOffset; /// Offset from UTC.
immutable bool isDST; /// Whether DST is in effect.
immutable string abbrev; /// The current abbreviation for the time zone.
}
/++
Struct used to hold information relating to TTInfo while organizing
the time zone information prior to putting it in its final form.
+/
struct TempTTInfo
{
this(int gmtOff, bool isDST, ubyte abbrInd)
{
tt_gmtoff = gmtOff;
tt_isdst = isDST;
tt_abbrind = abbrInd;
}
int tt_gmtoff;
bool tt_isdst;
ubyte tt_abbrind;
}
/++
Struct used to hold information relating to Transition while organizing
the time zone information prior to putting it in its final form.
+/
struct TempTransition
{
this(long timeT, immutable (TTInfo)* ttInfo, TransitionType* ttype)
{
this.timeT = timeT;
this.ttInfo = ttInfo;
this.ttype = ttype;
}
long timeT;
immutable (TTInfo)* ttInfo;
TransitionType* ttype;
}
/++
Struct used to hold information relating to Transition and TTInfo while
organizing the time zone information prior to putting it in its final form.
+/
struct TransitionType
{
this(bool isStd, bool inUTC)
{
this.isStd = isStd;
this.inUTC = inUTC;
}
bool isStd; /// Whether the transition is in std time (as opposed to wall clock time).
bool inUTC; /// Whether the transition is in UTC (as opposed to local time).
}
/++
Reads an int from a TZ file.
+/
static T readVal(T)(ref File tzFile)
if(is(T == int))
{
T[1] buff;
_enforceValidTZFile(!tzFile.eof());
tzFile.rawRead(buff);
return cast(int)ntohl(buff[0]);
}
/++
Reads a long from a TZ file.
+/
static T readVal(T)(ref File tzFile)
if(is(T == long))
{
T[1] buff;
_enforceValidTZFile(!tzFile.eof());
tzFile.rawRead(buff);
return cast(long)ntoh64(buff[0]);
}
/++
Reads an array of values from a TZ file.
+/
static T readVal(T)(ref File tzFile, size_t length)
if(isArray!T)
{
auto buff = new T(length);
_enforceValidTZFile(!tzFile.eof());
tzFile.rawRead(buff);
return buff;
}
/++
Reads a TempTTInfo from a TZ file.
+/
static T readVal(T)(ref File tzFile)
if(is(T == TempTTInfo))
{
return TempTTInfo(readVal!int(tzFile),
readVal!bool(tzFile),
readVal!ubyte(tzFile));
}
/++
Reads a value from a TZ file.
+/
static T readVal(T)(ref File tzFile)
if(!is(T == int) &&
!is(T == long) &&
!is(T == char[]) &&
!is(T == TempTTInfo))
{
T[1] buff;
_enforceValidTZFile(!tzFile.eof());
tzFile.rawRead(buff);
return buff[0];
}
/++
64 bit version of ntoh. Unfortunately, for some reason, most systems
provide only 16 and 32 bit versions of this, so we need to provide it
ourselves. We really should declare a version of this in core somewhere.
+/
static ulong ntoh64(ulong val)
{
static if(endian == Endian.LittleEndian)
return endianSwap64(val);
else
return val;
}
/++
Swaps the endianness of a 64-bit value. We really should declare a
version of this in core somewhere.
+/
static ulong endianSwap64(ulong val)
{
return ((val & 0xff00000000000000UL) >> 56) |
((val & 0x00ff000000000000UL) >> 40) |
((val & 0x0000ff0000000000UL) >> 24) |
((val & 0x000000ff00000000UL) >> 8) |
((val & 0x00000000ff000000UL) << 8) |
((val & 0x0000000000ff0000UL) << 24) |
((val & 0x000000000000ff00UL) << 40) |
((val & 0x00000000000000ffUL) << 56);
}
/++
Throws:
DateTimeException if $(D result) is false.
+/
static void _enforceValidTZFile(bool result, size_t line = __LINE__)
{
if(!result)
throw new DateTimeException("Not a valid tzdata file.", __FILE__, line);
}
int calculateLeapSeconds(long stdTime) const nothrow
{
try
{
if(_leapSeconds.empty)
return 0;
immutable unixTime = stdTimeToUnixTime(stdTime);
if(_leapSeconds.front.timeT >= unixTime)
return 0;
//Okay, casting is a hack, but indexOf shouldn't be changing it, and it would be
//too inefficient to have to keep duping it every time we have to calculate the time.
//Hopefully, indexOf will properly support immutable ranges at some point.
auto found = std.algorithm.indexOf!"b < a.timeT"(cast(LeapSecond[])_leapSeconds, unixTime);
if(found == -1)
return _leapSeconds.back.total;
auto leapSecond = found == 0 ? _leapSeconds[0] : _leapSeconds[found - 1];
return leapSecond.total;
}
catch(Exception e)
assert(0, format("Nothing in calculateLeapSeconds() should be throwing. Caught Exception: %s", e));
}
this(immutable Transition[] transitions,
immutable LeapSecond[] leapSeconds,
string name,
string stdName,
string dstName,
bool hasDST) immutable
{
if(dstName.empty && !stdName.empty)
dstName = stdName;
else if(stdName.empty && !dstName.empty)
stdName = dstName;
super(name, stdName, dstName);
if(!transitions.empty)
{
foreach(i, transition; transitions[0 .. $-1])
_enforceValidTZFile(transition.timeT < transitions[i + 1].timeT);
}
foreach(i, leapSecond; leapSeconds)
_enforceValidTZFile(i == leapSeconds.length - 1 || leapSecond.timeT < leapSeconds[i + 1].timeT);
_transitions = transitions;
_leapSeconds = leapSeconds;
_hasDST = hasDST;
}
immutable Transition[] _transitions; /// List of times when the utc offset changes.
immutable LeapSecond[] _leapSeconds; /// List of leap second occurrences.
immutable bool _hasDST; /// Whether DST is in effect for this time zone at any point in time.
}
version(Windows)
{
//Should be in core.sys.windows.windows, but for some reason it isn't.
extern(Windows)
{
export LONG RegQueryValueExA(HKEY hKey, LPCSTR name, LPDWORD reserved, LPDWORD type, LPBYTE data, LPDWORD count);
struct REG_TZI_FORMAT
{
LONG Bias;
LONG StandardBias;
LONG DaylightBias;
SYSTEMTIME StandardDate;
SYSTEMTIME DaylightDate;
}
}
/++
Represents a time zone from the Windows registry. Unfortunately, Windows
does not use the TZ database, though it does name its time zones using the
TZ database names. You can, however, use PosixTimeZone (which reads its
information from the TZ database files on disk) on Windows if you provide
the TZ database files
( Repository with the TZ database files (tzdata) )
yourself and tell $(D PosixTimeZone.getTimeZone()) where the directory
holding them is.
TZ database files hold DST transitions for a large interval of the time
covered by time_t. So, barring errors in the information in the TZ database
files, it will use the correct DST rules for any date. Windows, on the other
hand, maintains only the current DST rules, so historical dates will use
the current DST rules (and therefore potentially be incorrect). So, if you
want the DST rules that you use to be more accurate, or if you're looking for
your program to act consistently on both Posix and Windows systems, then, as
mentioned above, you'll need to include the TZ database files with your
program and give $(D PosixTimeZone.getTimeZone()) the directory on disk
where they are located.
However, if all you care about is whether current times use the correct DST
rules, or if you don't care whether the DST rules are historically accurate,
then you can just use WindowsTimeZone on Windows. WindowsTimeZone does not
exist on Posix systems.
To get a WindowsTimeZone, either call $(D WindowsTimeZone.getTimeZone()) or
call $(D TimeZone.getTimeZone()) (which will give you a PosixTimeZone on Posix
systems and a WindowsTimeZone on Windows systems).
+/
final class WindowsTimeZone : TimeZone
{
public:
/++
Whether this time zone has Daylight Savings Time at any point in time. Note that for some time zone types
it may not have DST for current dates but will still return true for hasDST because the time zone did at some
point have DST.
+/
@property override bool hasDST() const nothrow
{
return _tzInfo.DaylightDate.wMonth != 0;
}
/++
Takes the number of hecto-nanoseconds (100 ns) since midnight, January
1st, 1 A.D. in UTC time (i.e. std time) and returns whether DST is in
effect in this time zone at the given point in time.
Params:
stdTime = The UTC time that needs to be checked for DST in this time
zone.
+/
override bool dstInEffect(long stdTime) const nothrow
{
return _dstInEffect(&_tzInfo, stdTime);
}
/++
Takes the number of hecto-nanoseconds (100 ns) since midnight, January
1st, 1 A.D. in UTC time (i.e. std time) and converts it to this time
zone's time.
Params:
stdTime = The UTC time that needs to be adjusted to this time zone's time.
+/
override long utcToTZ(long stdTime) const nothrow
{
return _utcToTZ(&_tzInfo, stdTime, hasDST);
}
/++
Takes the number of hecto-nanoseconds (100 ns) since midnight, January
1st, 1 A.D. in this time zone's time and converts it to UTC
(i.e. std time).
Params:
adjTime = The time in this time zone that needs to be adjusted to
UTC time.
+/
override long tzToUTC(long adjTime) const nothrow
{
return _tzToUTC(&_tzInfo, adjTime, hasDST);
}
/++
Returns a TimeZone with the give name per the TZ database. The time zone
information is fetched from the Windows registry.
See_Also:
Wikipedia entry on TZ database
List of Time Zones
Params:
name = The TZ database name of the time zone that you're looking for.
Throws:
DateTimeException if the given time zone could not be found.
Examples:
--------------------
auto tz = TimeZone.getTimeZone("America/Los_Angeles");
--------------------
+/
static immutable(WindowsTimeZone) getTimeZone(string name)
{
auto keyStr = "Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\0";
HKEY baseKey;
{
auto result = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keyStr.ptr, 0, KEY_READ, &baseKey);
if(result != ERROR_SUCCESS)
throw new DateTimeException(format("Failed to open registry. Error: %s", result));
}
scope(exit) RegCloseKey(baseKey);
char[1024] keyName;
auto nameLen = keyName.length;
int result;
for(DWORD index = 0;
(result = RegEnumKeyExA(baseKey, index, keyName.ptr, &nameLen, null, null, null, null)) != ERROR_NO_MORE_ITEMS;
++index, nameLen = keyName.length)
{
if(result == ERROR_SUCCESS)
{
HKEY tzKey;
if(RegOpenKeyExA(baseKey, keyName.ptr, 0, KEY_READ, &tzKey) == ERROR_SUCCESS)
{
scope(exit) RegCloseKey(tzKey);
char[1024] strVal;
auto strValLen = strVal.length;
bool queryStringValue(string name, size_t lineNum = __LINE__)
{
strValLen = strVal.length;
return RegQueryValueExA(tzKey, name.ptr, null, null, cast(ubyte*)strVal.ptr, &strValLen) == ERROR_SUCCESS;
}
if(queryStringValue("Display\0"))
{
auto displayName = to!string(strVal.ptr);
if(displayName == name)
{
if(queryStringValue("Std\0"))
{
//Cannot use to!wstring(char*), probably due to bug http://d.puremagic.com/issues/show_bug.cgi?id=5016
static wstring conv(char* cstr, size_t strValLen)
{
cstr[strValLen - 1] = '\0';
string retval;
for(;; ++cstr)
{
if(*cstr == '\0')
break;
retval ~= *cstr;
}
return to!wstring(retval);
}
//auto stdName = to!wstring(strVal.ptr);
auto stdName = conv(strVal.ptr, strValLen);
if(queryStringValue("Dlt\0"))
{
//auto dstName = to!wstring(strVal.ptr);
auto dstName = conv(strVal.ptr, strValLen);
enum tzi = "TZI\0";
REG_TZI_FORMAT binVal;
auto binValLen = REG_TZI_FORMAT.sizeof;
if(RegQueryValueExA(tzKey, tzi.ptr, null, null, cast(ubyte*)&binVal, &binValLen) == ERROR_SUCCESS)
{
TIME_ZONE_INFORMATION tzInfo;
auto stdNameLen = stdName.length > 32 ? 32 : stdName.length;
auto dstNameLen = dstName.length > 32 ? 32 : dstName.length;
tzInfo.Bias = binVal.Bias;
tzInfo.StandardName[0 .. stdNameLen] = stdName[0 .. stdNameLen];
tzInfo.StandardName[stdNameLen .. $] = '\0';
tzInfo.StandardDate = binVal.StandardDate;
tzInfo.StandardBias = binVal.StandardBias;
tzInfo.DaylightName[0 .. dstNameLen] = dstName[0 .. dstNameLen];
tzInfo.DaylightName[dstNameLen .. $] = '\0';
tzInfo.DaylightDate = binVal.DaylightDate;
tzInfo.DaylightBias = binVal.DaylightBias;
return new WindowsTimeZone(name, tzInfo);
}
}
}
}
}
}
}
}
throw new DateTimeException(format("Failed to find time zone: %s", name));
}
unittest
{
//Verify Example.
auto tz = TimeZone.getTimeZone("America/Los_Angeles");
}
/++
Returns a list of the names of the time zones installed on the system.
You can provide a sub-name to narrow down the list of time zones (which
will likely be in the thousands if you get them all). For example,
if you pass in "America" as the sub-name, then only the time zones which
begin with "America" will be returned.
Params:
subname = The first part of the time zones that you want.
Throws:
DateTimeException if it fails to read the registry.
+/
static string[] getInstalledTZNames(string subname = "")
{
auto timezones = appender!(string[])();
auto keyStr = "Software\\Microsoft\\Windows NT\\CurrentVersion\\Time Zones\0";
HKEY baseKey;
{
auto result = RegOpenKeyExA(HKEY_LOCAL_MACHINE, keyStr.ptr, 0, KEY_READ, &baseKey);
if(result != ERROR_SUCCESS)
throw new DateTimeException(format("Failed to open registry. Error: %s", result));
}
scope(exit) RegCloseKey(baseKey);
char[1024] keyName;
auto nameLen = keyName.length;
int result;
for(DWORD index = 0;
(result = RegEnumKeyExA(baseKey, index, keyName.ptr, &nameLen, null, null, null, null)) != ERROR_NO_MORE_ITEMS;
++index, nameLen = keyName.length)
{
if(result == ERROR_SUCCESS)
{
HKEY tzKey;
if(RegOpenKeyExA(baseKey, keyName.ptr, 0, KEY_READ, &tzKey) == ERROR_SUCCESS)
{
scope(exit) RegCloseKey(tzKey);
char[1024] strVal;
auto strValLen = strVal.length;
bool queryStringValue(string name, size_t lineNum = __LINE__)
{
strValLen = strVal.length;
return RegQueryValueExA(tzKey, name.ptr, null, null, cast(ubyte*)strVal.ptr, &strValLen) == ERROR_SUCCESS;
}
if(queryStringValue("Display\0"))
{
auto displayName = to!string(strVal.ptr);
if(displayName.startsWith(subname))
timezones.put(displayName);
}
}
}
}
sort(timezones.data);
return timezones.data;
}
unittest
{
WindowsTimeZone.getInstalledTZNames();
}
private:
static bool _dstInEffect(const TIME_ZONE_INFORMATION* tzInfo, long stdTime) nothrow
{
try
{
if(tzInfo.DaylightDate.wMonth == 0)
return false;
auto utcDateTime = cast(DateTime)SysTime(stdTime, UTC());
//The limits of what SystemTimeToTZSpecificLocalTime() will accept.
if(utcDateTime.year < 1601)
{
if(utcDateTime.month == Month.feb && utcDateTime.day == 29)
utcDateTime.day = 28;
utcDateTime.year = 1601;
}
else if(utcDateTime.year > 30_827)
{
if(utcDateTime.month == Month.feb && utcDateTime.day == 29)
utcDateTime.day = 28;
utcDateTime.year = 30_827;
}
//SystemTimeToTZSpecificLocalTime() doesn't act correctly at the beginning
//or end of the year (bleh). Unless some bizarre time zone changes
//DST on January 1st or December 31st, this should fix the problem.
if(utcDateTime.month == Month.jan)
{
if(utcDateTime.day == 1)
utcDateTime.day = 2;
}
else if(utcDateTime.month == Month.dec && utcDateTime.day == 31)
utcDateTime.day = 30;
SYSTEMTIME utcTime = void;
SYSTEMTIME otherTime = void;
utcTime.wYear = utcDateTime.year;
utcTime.wMonth = utcDateTime.month;
utcTime.wDay = utcDateTime.day;
utcTime.wHour = utcDateTime.hour;
utcTime.wMinute = utcDateTime.minute;
utcTime.wSecond = utcDateTime.second;
SystemTimeToTzSpecificLocalTime(cast(TIME_ZONE_INFORMATION*)tzInfo, &utcTime, &otherTime);
immutable otherDateTime = DateTime(otherTime.wYear,
otherTime.wMonth,
otherTime.wDay,
otherTime.wHour,
otherTime.wMinute,
otherTime.wSecond);
immutable diff = utcDateTime - otherDateTime;
immutable minutes = diff.total!"minutes"() - tzInfo.Bias;
if(minutes == tzInfo.DaylightBias)
return true;
assert(minutes == tzInfo.StandardBias);
return false;
}
catch(Exception e)
assert(0, e.toString());
//assert(0, "DateTime's constructor threw.");
}
unittest
{
TIME_ZONE_INFORMATION tzInfo;
GetTimeZoneInformation(&tzInfo);
WindowsTimeZone._dstInEffect(&tzInfo, SysTime(DateTime(1600, 1, 1)).stdTime);
WindowsTimeZone._dstInEffect(&tzInfo, SysTime(DateTime(1601, 1, 1)).stdTime);
WindowsTimeZone._dstInEffect(&tzInfo, SysTime(DateTime(30_827, 1, 1)).stdTime);
WindowsTimeZone._dstInEffect(&tzInfo, SysTime(DateTime(30_828, 1, 1)).stdTime);
}
static long _utcToTZ(const TIME_ZONE_INFORMATION* tzInfo, long stdTime, bool hasDST) nothrow
{
if(hasDST && WindowsTimeZone._dstInEffect(tzInfo, stdTime))
return stdTime - convert!("minutes", "hnsecs")(tzInfo.Bias + tzInfo.DaylightBias);
return stdTime - convert!("minutes", "hnsecs")(tzInfo.Bias + tzInfo.StandardBias);
}
static long _tzToUTC(const TIME_ZONE_INFORMATION* tzInfo, long adjTime, bool hasDST) nothrow
{
if(hasDST)
{
try
{
auto localTime = cast(DateTime)SysTime(adjTime, UTC());
DateTime getTransitionTime(const ref SYSTEMTIME transition)
{
DateTime switchDate;
if(transition.wYear == 0)
switchDate.year = localTime.year;
else
switchDate.year = transition.wYear;
switchDate.month = cast(Month)transition.wMonth;
DayOfWeek dow = cast(DayOfWeek)transition.wDayOfWeek;
int occurrence = transition.wDay;
if(occurrence < 5)
{
Date date = localTime.date;
date.day = 1;
date.day = cast(int)(date.day + daysToDayOfWeek(date.dayOfWeek, dow) + convert!("weeks", "days")(occurrence - 1));
switchDate.day = date.day;
}
else
{
Date date = localTime.date.endOfMonth;
switchDate.day = date.day - daysToDayOfWeek(dow, date.dayOfWeek);
}
switchDate.hour = transition.wHour;
switchDate.minute = transition.wMinute;
return switchDate;
}
auto stdSwitch = getTransitionTime(tzInfo.StandardDate);
auto dstSwitch = getTransitionTime(tzInfo.DaylightDate);
bool isDST = false;
if(localTime < stdSwitch)
isDST = localTime < dstSwitch ? stdSwitch < dstSwitch : true;
else
isDST = localTime < dstSwitch ? false : dstSwitch > stdSwitch;
if(isDST)
return adjTime + convert!("minutes", "hnsecs")(tzInfo.Bias + tzInfo.DaylightBias);
}
catch(Exception e)
assert(0, "SysTime's constructor threw.");
}
return adjTime + convert!("minutes", "hnsecs")(tzInfo.Bias + tzInfo.StandardBias);
}
this(string name, TIME_ZONE_INFORMATION tzInfo) immutable
{
//Cannot use to!string(wchar*), probably due to bug http://d.puremagic.com/issues/show_bug.cgi?id=5016
static string conv(wchar* wcstr)
{
wcstr[31] = '\0';
wstring retval;
for(;; ++wcstr)
{
if(*wcstr == '\0')
break;
retval ~= *wcstr;
}
return to!string(retval);
}
//super(name, to!string(tzInfo.StandardName.ptr), to!string(tzInfo.DaylightName.ptr));
super(name, conv(tzInfo.StandardName.ptr), conv(tzInfo.DaylightName.ptr));
_tzInfo = tzInfo;
}
TIME_ZONE_INFORMATION _tzInfo;
}
}
else version(D_Ddoc)
{
/++
Represents a time zone from the Windows registry. Unfortunately, Windows
does not use the TZ database, though it does name its time zones using the
TZ database names. You can, however, use PosixTimeZone (which reads its
information from the TZ database files on disk) on Windows if you provide
the TZ database files
( Repository with the TZ database files (tzdata) )
yourself and tell $(D PosixTimeZone.getTimeZone()) where the directory
holding them is.
TZ database files hold DST transitions for a large interval of the time
covered by time_t. So, barring errors in the information in the TZ database
files, it will use the correct DST rules for any date. Windows, on the other
hand, maintains only the current DST rules, so historical dates will use
the current DST rules (and therefore potentially be incorrect). So, if you
want the DST rules that you use to be more accurate, or if you're looking for
your program to act consistently on both Posix and Windows systems, then, as
mentioned above, you'll need to include the TZ database files with your
program and give $(D PosixTimeZone.getTimeZone()) the directory on disk
where they are located.
However, if all you care about is whether current times use the correct DST
rules, or if you don't care whether the DST rules are historically accurate,
then you can just use WindowsTimeZone on Windows. WindowsTimeZone does not
exist on Posix systems.
To get a WindowsTimeZone, either call $(D WindowsTimeZone.getTimeZone()) or
call $(D TimeZone.getTimeZone()) (which will give you a PosixTimeZone on Posix
systems and a WindowsTimeZone on Windows systems).
+/
final class WindowsTimeZone : TimeZone
{
public:
/++
Whether this time zone has Daylight Savings Time at any point in time.
Note that for some time zone types it may not have DST for current dates
but will still return true for hasDST because the time zone did at some
point have DST.
+/
@property override bool hasDST() const nothrow
{
assert(0, "No implementation. Function exists only for DDoc generation");
}
/++
Takes the number of hecto-nanoseconds (100 ns) since midnight, January
1st, 1 A.D. in UTC time (i.e. std time) and returns whether DST is in
effect in this time zone at the given point in time.
Params:
stdTime = The UTC time that needs to be checked for DST in this
time zone.
+/
override bool dstInEffect(long stdTime) const nothrow
{
assert(0, "No implementation. Function exists only for DDoc generation");
}
/++
Takes the number of hecto-nanoseconds (100 ns) since midnight, January
1st, 1 A.D. in UTC time (i.e. std time) and converts it to this time
zone's time.
Params:
stdTime = The UTC time that needs to be adjusted to this time zone's time.
+/
override long utcToTZ(long stdTime) const nothrow
{
assert(0, "No implementation. Function exists only for DDoc generation");
}
/++
Takes the number of hecto-nanoseconds (100 ns) since midnight, January
1st, 1 A.D. in this time zone's time and converts it to UTC
(i.e. std time).
Params:
adjTime = The time in this time zone that needs to be adjusted to UTC time.
+/
override long tzToUTC(long adjTime) const nothrow
{
assert(0, "No implementation. Function exists only for DDoc generation");
}
/++
Returns a TimeZone with the give name per the TZ database. The time zone
information is fetched from the Windows registry.
See_Also:
Wikipedia entry on TZ database
List of Time Zones
Params:
name = The TZ database name of the time zone that you're looking for.
Throws:
DateTimeException if the given time zone could not be found.
Examples:
--------------------
auto tz = TimeZone.getTimeZone("America/Los_Angeles");
--------------------
+/
static immutable(WindowsTimeZone) getTimeZone(string name)
{
assert(0, "No implementation. Function exists only for DDoc generation");
}
/++
Returns a list of the names of the time zones installed on the system.
You can provide a sub-name to narrow down the list of time zones (which
will likely be in the thousands if you get them all). For example,
if you pass in "America" as the sub-name, then only the time zones which
begin with "America" will be returned.
Params:
subname = The first part of the time zones that you want.
+/
static string[] getInstalledTZNames(string subname = "")
{
assert(0, "No implementation. Function exists only for DDoc generation");
}
private:
this() immutable pure
{
super("", "", "");
assert(0, "No implementation. Function exists only for DDoc generation");
}
}
}
version(Posix)
{
/++
Allows you to set the local time zone on Posix systems with the TZ
database name by setting the TZ environment variable.
Unfortunately, there is no way to do it on Windows using the TZ
database name, so this function only exists on Posix systems.
+/
void setTZEnvVar(string tzDatabaseName) nothrow
{
try
{
char[] env = to!(char[])("TZ=:" ~ PosixTimeZone.defaultTZDatabaseDir ~ tzDatabaseName ~ "\0");
putenv(env.ptr);
tzset();
}
catch(Exception e)
assert(0, "to!(char[]) threw when it shouldn't have.");
}
/++
Clears the TZ environment variable.
Only on Posix.
+/
void clearTZEnvVar() nothrow
{
try
{
char[] env = to!(char[])("TZ\0");
unsetenv(env.ptr);
tzset();
}
catch(Exception e)
assert(0, "to!(char[]) threw when it shouldn't have.");
}
}
else version(D_Ddoc)
{
/++
Allows you to set the local time zone on Posix systems with the TZ
database name by setting the TZ environment variable.
Unfortunately, there is no way to do it on Windows using the TZ
database name, so this function only exists on Posix systems.
+/
void setTZEnvVar(string tzDatabaseName)
{
assert(0, "No implementation. Function exists only for DDoc generation");
}
/++
Clears the TZ environment variable.
Only on Posix.
+/
void clearTZEnvVar()
{
assert(0, "No implementation. Function exists only for DDoc generation");
}
}
//==============================================================================
// Section with StopWatch and Benchmark Code.
//==============================================================================
/++
StopWatch's AutoStart flag
+/
enum autoStart = AutoStart.yes;
/++
StopWatch measures time as precisely as possible.
This class uses a high-performance counter. On Windows systems, it uses
$(D QueryPerformanceCounter), and on Posix systems, it uses $(D clock_gettime())
if available, and $(D gettimeofday()) otherwise.
But the accuracy of StopWatch differs from system to system. It is impossible
to for it to be the same from system to system since the precision of the
system clock varies from system to system, and other system-dependent and
situation-dependent stuff (such as the overhead of a context switching between
threads) can also affect StopWatch's accuracy.
Examples:
--------------------
void foo() {
StopWatch sw;
static immutable N = 100;
TickDuration[N] times;
TickDuration last = TickDuration.from!"seconds"(0);
foreach (i; 0..N) {
sw.start(); // start/resume mesuring.
foreach (Unused; 0..1000000) bar();
sw.stop(); // stop/pause mesuring.
// Return value of peek() after having stopped are the always same.
writeln((i+1)*1000000, " times done, lap time: ",
sw.peek().msec, "[ms]");
times[i] = sw.peek() - last;
last = sw.peek();
}
real sum = 0;
// When you want to know the number of seconds of the fact,
// you can use properties of TickDuration.
// (seconds, mseconds, useconds, hnsecs)
foreach (e; times) sum += e.hnsecs;
writeln("Average time: ", sum/N, " hnsecs");
}
--------------------
+/
struct StopWatch
{
@safe:// @@@BUG@@@ workaround for bug 4211
private:
// true if observing.
bool m_FlagStarted = false;
// TickDuration at the time of StopWatch starting measurement.
TickDuration m_TimeStart;
// Total time that StopWatch ran.
TickDuration m_TimeMeasured;
public:
/++
auto start with constructor
+/
this(AutoStart autostart)
{
if (autostart)
{
start();
}
}
unittest
{
auto sw = StopWatch(autoStart);
sw.stop();
}
/++
Reset the stop watch.
+/
@safe
void reset()
{
if (m_FlagStarted)
{
// Set current system time if StopWatch is measuring.
m_TimeStart = Clock.currSystemTick;
}
else
{
// Set zero if StopWatch is not measuring.
m_TimeStart.length = 0;
}
m_TimeMeasured.length = 0;
}
unittest
{
StopWatch sw;
sw.start();
sw.stop();
sw.reset();
assert(sw.peek().to!("seconds", real) == 0);
}
/++
Start the stop watch.
+/
@safe
void start()
{
assert(!m_FlagStarted);
StopWatch sw;
m_FlagStarted = true;
m_TimeStart = Clock.currSystemTick;
}
unittest
{
StopWatch sw;
sw.start();
auto t1 = sw.peek();
bool doublestart = true;
try sw.start();
catch (Error e) doublestart = false;
assert(!doublestart);
sw.stop();
assert((t1 - sw.peek()).to!("seconds", real) <= 0);
}
/++
Stop the stop watch.
+/
@safe
void stop()
{
assert(m_FlagStarted);
m_FlagStarted = false;
m_TimeMeasured += Clock.currSystemTick - m_TimeStart;
}
unittest
{
StopWatch sw;
sw.start();
sw.stop();
auto t1 = sw.peek();
bool doublestop = true;
try sw.stop();
catch (Error e) doublestop = false;
assert(!doublestop);
assert((t1 - sw.peek()).to!("seconds", real) == 0);
}
/++
Peek at the amount of time which has passed since the stop watch was
started.
+/
@safe
TickDuration peek() const
{
if(m_FlagStarted)
{
return Clock.currSystemTick - m_TimeStart + m_TimeMeasured;
}
return m_TimeMeasured;
}
unittest
{
StopWatch sw;
sw.start();
auto t1 = sw.peek();
sw.stop();
auto t2 = sw.peek();
auto t3 = sw.peek();
assert(t1 <= t2);
assert(t2 == t3);
}
}
// workaround for bug4886
@safe
size_t lengthof(aliases...)() pure nothrow
{
return aliases.length;
}
/++
Benchmarks code for speed assessment and comparison.
Params:
fun = aliases of callable objects (e.g. function names). Each should
take no arguments.
times = The number of times each function is to be executed.
Returns:
An array of $(D n) $(D uint)s. Element at slot $(D i) contains the
number of milliseconds spent in calling the $(D i)th function $(D
times) times.
Examples:
--------------------
int a;
void f0() { }
void f1() { auto b = a; }
void f2() { auto b = to!(string)(a); }
auto r = benchmark!(f0, f1, f2)(10_000_000);
--------------------
+/
@safe
TickDuration[lengthof!(fun)()] benchmark(fun...)(uint times)
if(areAllSafe!fun)
{
TickDuration[lengthof!(fun)()] result;
StopWatch sw;
sw.start();
foreach (i, Unused; fun)
{
sw.reset();
foreach (j; 0 .. times)
{
fun[i]();
}
result[i] = sw.peek();
}
return result;
}
@system
TickDuration[lengthof!(fun)()] benchmark(fun...)(uint times)
if(!areAllSafe!fun)
{
TickDuration[lengthof!(fun)()] result;
StopWatch sw;
sw.start();
foreach (i, Unused; fun)
{
sw.reset();
foreach (j; 0 .. times)
{
fun[i]();
}
result[i] = sw.peek();
}
return result;
}
unittest
{
int a;
void f0() { }
//void f1() { auto b = to!(string)(a); }
void f2() { auto b = (a); }
auto r = benchmark!(f0, f2)(100);
}
/++
Return value of benchmark with two functions comparing.
+/
immutable struct ComparingBenchmarkResult
{
@safe:
private TickDuration m_tmBase;
private TickDuration m_tmTarget;
/++
Evaluation value
This returns the evaluation value of performance as the ratio that is
compared between BaseFunc's time and TargetFunc's time.
If performance is high, this returns a high value.
+/
@property
real point() immutable pure
{
// @@@BUG@@@ workaround for bug 4689
long t = m_tmTarget.length;
return m_tmBase.length / cast(real)t;
}
/++
The time required of the target function
+/
@property
public TickDuration targetTime() immutable pure
{
return m_tmTarget;
}
/++
The time required of the base function
+/
@property
public TickDuration baseTime() immutable pure
{
return m_tmBase;
}
}
/++
Benchmark with two functions comparing.
Params:
baseFunc = The function to become the base of the speed.
targetFunc = The function that wants to measure speed.
times = The number of times each function is to be executed.
Examples:
--------------------
void f1() {
// ...
}
void f2() {
// ...
}
void main() {
auto b = comparingBenchmark!(f1, f2, 0x80);
writeln(b.point);
}
--------------------
+/
@safe
ComparingBenchmarkResult comparingBenchmark(
alias baseFunc, alias targetFunc, int times = 0xfff)()
if (isSafe!baseFunc && isSafe!targetFunc)
{
auto t = benchmark!(baseFunc, targetFunc)(times);
return ComparingBenchmarkResult(t[0], t[1]);
}
/// ditto
@system
ComparingBenchmarkResult comparingBenchmark(
alias baseFunc, alias targetFunc, int times = 0xfff)()
if (!(isSafe!baseFunc && isSafe!targetFunc))
{
auto t = benchmark!(baseFunc, targetFunc)(times);
return ComparingBenchmarkResult(t[0], t[1]);
}
@safe
unittest
{
@system void f1x() { }
@system void f2x() { }
@safe void f1o() { }
@safe void f2o() { }
auto b1 = comparingBenchmark!(f1o, f2o, 1); // OK
//static auto b2 = comparingBenchmark!(f1x, f2x, 1); // NG
}
@system
unittest
{
@system void f1x() { }
@system void f2x() { }
@safe void f1o() { }
@safe void f2o() { }
auto b1 = comparingBenchmark!(f1o, f2o, 1); // OK
auto b2 = comparingBenchmark!(f1x, f2x, 1); // OK
}
//==============================================================================
// Section with other types.
//==============================================================================
/++
Exception type used by std.datetime.
+/
alias TimeException DateTimeException;
/++
Effectively a namespace to make it clear where its methods are getting
their time from. It cannot be instantiated.
+/
final class Clock
{
public:
/++
Returns the current time in the local timezone.
+/
static SysTime currTime(immutable TimeZone tz = LocalTime())
{
return SysTime(currStdTime, tz);
}
unittest
{
//Verify that currTime() at least gives a time
//which isn't way off in the past (like if the
//conversions between epochs in currStdTime() was off).
assert(currTime > SysTime(Date(2010, 11, 1)));
assert(currTime(UTC()).timezone is UTC());
}
/++
Returns the number of hnsecs since midnight, January 1st, 1 A.D. for the
current time.
Throws:
ErrnoException (on Posix) or Exception (on Windows) if it fails to
get the time of day.
+/
@trusted
static @property long currStdTime()
{
enum hnsecsToUnixEpoch = 621_355_968_000_000_000L;
version(Windows)
{
enum adjustmentFromFileTime = 116_444_736_000_000_000L;
FILETIME fileTime;
GetSystemTimeAsFileTime(&fileTime);
ulong tempHNSecs = fileTime.dwHighDateTime;
tempHNSecs <<= 32;
tempHNSecs |= fileTime.dwLowDateTime;
return cast(long)tempHNSecs - adjustmentFromFileTime + hnsecsToUnixEpoch;
}
else version(Posix)
{
static if(is(typeof(clock_gettime)))
{
timespec ts;
if(clock_gettime(CLOCK_REALTIME, &ts) != 0)
throw new TimeException("Failed in clock_gettime().");
return convert!("seconds", "hnsecs")(ts.tv_sec) +
ts.tv_nsec / 100 +
hnsecsToUnixEpoch;
}
else
{
timeval tv;
if(gettimeofday(&tv, null) != 0)
throw new TimeException("Failed in gettimeofday().");
return convert!("seconds", "hnsecs")(tv.tv_sec) +
convert!("usecs", "hnsecs")(tv.tv_usec) +
hnsecsToUnixEpoch;
}
}
}
/++
The current system tick. The number of ticks per second varies from
system to system. This uses a monotonic clock, so it's intended for
precision timing by comparing relative time values, not for getting
the current system time.
Warning:
On some systems, the monotonic clock may stop counting when
the computer goes to sleep or hibernates. So, the monotonic
clock could be off if that occurs. This is known to happen
on Mac OS X. It has not been tested whether it occurs on
either Windows or on Linux.
Throws:
TimeException if it fails to get the time.
+/
@safe
static @property TickDuration currSystemTick()
{
return TickDuration.currSystemTick();
}
unittest
{
auto t = Clock.currSystemTick;
assert(t.length > 0);
}
/++
The current number of system ticks since the application started.
The number of ticks per second varies from system to system.
This uses a monotonic clock.
Warning:
On some systems, the monotonic clock may stop counting when
the computer goes to sleep or hibernates. So, the monotonic
clock could be off if that occurs. This is known to happen
on Mac OS X. It has not been tested whether it occurs on
either Windows or on Linux.
Throws:
ErrnoException (on Posix) or Exception (on Windows) if it fails to
get the time of day.
+/
@safe
static @property TickDuration currAppTick()
{
return currSystemTick - TickDuration.appOrigin;
}
unittest
{
auto a = Clock.currSystemTick;
auto b = Clock.currAppTick;
assert(a.length);
assert(a != b);
}
//TODO Add support for monotonic clocks.
private:
@disable this() {}
}
//==============================================================================
// Section with public helper functions and templates.
//==============================================================================
/++
Whether the given type defines all of the necessary functions for it to
function as a time point.
+/
template isTimePoint(T)
{
enum isTimePoint = hasMin!T &&
hasMax!T &&
hasOverloadedOpBinaryWithDuration!T &&
hasOverloadedOpAssignWithDuration!T &&
hasOverloadedOpBinaryWithSelf!T;
}
unittest
{
static assert(isTimePoint!(Date));
static assert(isTimePoint!(DateTime));
static assert(isTimePoint!(TimeOfDay));
static assert(isTimePoint!(SysTime));
static assert(isTimePoint!(const Date));
static assert(isTimePoint!(const DateTime));
static assert(isTimePoint!(const TimeOfDay));
static assert(isTimePoint!(const SysTime));
static assert(isTimePoint!(immutable Date));
static assert(isTimePoint!(immutable DateTime));
static assert(isTimePoint!(immutable TimeOfDay));
static assert(isTimePoint!(immutable SysTime));
}
/++
Whether the given Gregorian Year is a leap year.
Params:
year = The year to to be tested.
+/
static bool yearIsLeapYear(int year) pure nothrow
{
if(year % 400 == 0)
return true;
if(year % 100 == 0)
return false;
return year % 4 == 0;
}
unittest
{
//Test A.D.
assert(!yearIsLeapYear(1));
assert(!yearIsLeapYear(2));
assert(!yearIsLeapYear(3));
assert(yearIsLeapYear(4));
assert(!yearIsLeapYear(5));
assert(!yearIsLeapYear(6));
assert(!yearIsLeapYear(7));
assert(yearIsLeapYear(8));
assert(!yearIsLeapYear(100));
assert(!yearIsLeapYear(200));
assert(!yearIsLeapYear(300));
assert(yearIsLeapYear(400));
assert(!yearIsLeapYear(500));
assert(!yearIsLeapYear(600));
assert(!yearIsLeapYear(700));
assert(yearIsLeapYear(800));
assert(yearIsLeapYear(1996));
assert(!yearIsLeapYear(1997));
assert(!yearIsLeapYear(1998));
assert(!yearIsLeapYear(1999));
assert(yearIsLeapYear(2000));
assert(!yearIsLeapYear(2001));
assert(!yearIsLeapYear(2002));
assert(!yearIsLeapYear(2003));
assert(yearIsLeapYear(2004));
assert(!yearIsLeapYear(2005));
assert(!yearIsLeapYear(2006));
assert(!yearIsLeapYear(2007));
assert(yearIsLeapYear(2008));
assert(!yearIsLeapYear(2009));
assert(!yearIsLeapYear(2010));
//Test B.C.
assert(yearIsLeapYear(0));
assert(!yearIsLeapYear(-1));
assert(!yearIsLeapYear(-2));
assert(!yearIsLeapYear(-3));
assert(yearIsLeapYear(-4));
assert(!yearIsLeapYear(-5));
assert(!yearIsLeapYear(-6));
assert(!yearIsLeapYear(-7));
assert(yearIsLeapYear(-8));
assert(!yearIsLeapYear(-100));
assert(!yearIsLeapYear(-200));
assert(!yearIsLeapYear(-300));
assert(yearIsLeapYear(-400));
assert(!yearIsLeapYear(-500));
assert(!yearIsLeapYear(-600));
assert(!yearIsLeapYear(-700));
assert(yearIsLeapYear(-800));
assert(yearIsLeapYear(-1996));
assert(!yearIsLeapYear(-1997));
assert(!yearIsLeapYear(-1998));
assert(!yearIsLeapYear(-1999));
assert(yearIsLeapYear(-2000));
assert(!yearIsLeapYear(-2001));
assert(!yearIsLeapYear(-2002));
assert(!yearIsLeapYear(-2003));
assert(yearIsLeapYear(-2004));
assert(!yearIsLeapYear(-2005));
assert(!yearIsLeapYear(-2006));
assert(!yearIsLeapYear(-2007));
assert(yearIsLeapYear(-2008));
assert(!yearIsLeapYear(-2009));
assert(!yearIsLeapYear(-2010));
}
/++
Converts a time_t (which uses midnight, January 1st, 1970 UTC as its epoch
and seconds as its units) to std time (which uses midnight, January 1st,
1 A.D. UTC and hnsecs as its units).
Params:
unixTime = The time_t to convert.
+/
long unixTimeToStdTime(time_t unixTime) pure nothrow
{
return 621355968000000000L + convert!("seconds", "hnsecs")(unixTime);
}
unittest
{
assertPred!"=="(unixTimeToStdTime(0), 621355968000000000L); //Midnight, January 1st, 1970
assertPred!"=="(unixTimeToStdTime(86_400), 621355968000000000L + 864_000_000_000L); //Midnight, January 2nd, 1970
assertPred!"=="(unixTimeToStdTime(-86_400), 621355968000000000L - 864_000_000_000L); //Midnight, December 31st, 1969
assertPred!"=="(unixTimeToStdTime(0), (Date(1970, 1, 1) - Date(1, 1, 1)).total!"hnsecs");
assertPred!"=="(unixTimeToStdTime(0), (DateTime(1970, 1, 1) - DateTime(1, 1, 1)).total!"hnsecs");
}
/++
Converts std time (which uses midnight, January 1st, 1 A.D. UTC as its epoch
and hnsecs as its units) to time_t (which uses midnight, January 1st, 1970 UTC
as its epoch and seconds as its units). If time_t is 32 bits, rather than 64,
and the result can't fit in a 32-bit value, then the closest value that can
be held in 32 bits will be used (so time_t.max if it goes over or time_t.min
if it goes under).
Note:
While Windows systems require that time_t be non-negative (in spite of
time_t being signed), this function still returns negative numbers on
Windows, since it's more flexible to allow negative time_t for those
who need it. So, if you're on Windows and are using the standard C
functions or Win32 API functions which take a time_t, you may want to
check whether the return value of $(D stdTimeToUnixTime()) is non-negative.
Params:
stdTime = The std time to convert.
+/
time_t stdTimeToUnixTime(long stdTime) pure nothrow
{
immutable hnsecsAtUnixTimeEpoch = convert!("hnsecs", "seconds")(stdTime - 621355968000000000L);
static if(time_t.sizeof >= long.sizeof)
return cast(time_t)hnsecsAtUnixTimeEpoch;
else
{
if(hnsecsAtUnixTimeEpoch > 0)
{
if(hnsecsAtUnixTimeEpoch > time_t.max)
return time_t.max;
return cast(time_t)hnsecsAtUnixTimeEpoch;
}
if(hnsecsAtUnixTimeEpoch < time_t.min)
return time_t.min;
return cast(time_t)hnsecsAtUnixTimeEpoch;
}
}
unittest
{
assertPred!"=="(stdTimeToUnixTime(621355968000000000L), 0); //Midnight, January 1st, 1970
assertPred!"=="(stdTimeToUnixTime(621355968000000000L + 864_000_000_000L), 86_400); //Midnight, January 2nd, 1970
assertPred!"=="(stdTimeToUnixTime(621355968000000000L - 864_000_000_000L), -86_400); //Midnight, December 31st, 1969
assertPred!"=="(stdTimeToUnixTime((Date(1970, 1, 1) - Date(1, 1, 1)).total!"hnsecs"), 0);
assertPred!"=="(stdTimeToUnixTime((DateTime(1970, 1, 1) - DateTime(1, 1, 1)).total!"hnsecs"), 0);
}
version(Windows)
{
/++
On Windows, this converts a SYSTEMTIME struct to a SysTime.
Params:
st = The SYSTEMTIME struct to convert.
tz = The time zone that the time in the SYSTEMTIME struct
is assumed to be (if the SYSTEMTIME was supplied by a
Windows system call, the SYSTEMTIME will either be in
local time or UTC, depending on the call).
Throws:
DateTimeException if the given SYSTEMTIME will not fit in a SysTime,
which is highly unlikely to happen given that SysTime.max is in 29,228 A.D.
and the maximum SYSTEMTIME is in 30,827 A.D.
+/
SysTime SYSTEMTIMEToSysTime(const SYSTEMTIME* st, immutable TimeZone tz = LocalTime()) pure
{
const max = SysTime.max;
static void throwLaterThanMax()
{
throw new DateTimeException("The given SYSTEMTIME is for a date greater than SysTime.max.");
}
if(st.wYear > max.year)
throwLaterThanMax();
else if(st.wYear == max.year)
{
if(st.wMonth > max.month)
throwLaterThanMax();
else if(st.wMonth == max.month)
{
if(st.wDay > max.day)
throwLaterThanMax();
else if(st.wDay == max.day)
{
if(st.wHour > max.hour)
throwLaterThanMax();
else if(st.wHour == max.hour)
{
if(st.wMinute > max.minute)
throwLaterThanMax();
else if(st.wMinute == max.minute)
{
if(st.wSecond > max.second)
throwLaterThanMax();
else if(st.wSecond == max.second)
{
if(st.wMilliseconds > max.fracSec.msecs)
throwLaterThanMax();
}
}
}
}
}
}
auto dt = DateTime(st.wYear, st.wMonth, st.wDay,
st.wHour, st.wMinue, st.wSecond);
return SysTime(dt, FracSec.from!"msecs"(st.wMilliseconds), tz);
}
unittest
{
auto sysTime = Clock.currTime(UTC());
SYSTEMTIME st = void;
GetSystemTime(&st);
auto converted = SYSTEMTIMEToSystemTime(&st);
assertPred!"<="(sysTime, converted);
assertPred!"<="(converted - sysTime, dur!"msecs"(10));
}
/++
On Windows, this converts a SysTime to a SYSTEMTIME struct.
The SYSTEMTIME will be set using the given SysTime's time zone, so
if you want the SYSTEMTIME to be in UTC, set the SysTime's time zone
to UTC.
Params:
sysTime = The SysTime to convert.
st = The SYSTEMTIME struct to fill in with the date and
time from sysTime.
Throws:
DateTimeException if the given SysTime will not fit in a SYSTEMTIME.
This will only happen if the SysTime's date is prior to 1601 A.D.
+/
void SysTimeToSYSTEMTIME(in SysTime sysTime, SYSTEMTIME* st) pure
{
immutable dt = cast(DateTime)sysTime;
if(dt.year < 1601)
throw new DateTimeException("SYSTEMTIME cannot hold dates prior to the year 1601.");
st.wYear = dt.year;
st.wMonth = dt.month;
st.wDayOfWeek = dt.dayOfWeek;
st.wDay = dt.day;
st.wHour = dt.hour;
st.wMinute = dt.minute;
st.wSecond = dt.second;
st.wMilliseconds = sysTime.fracSec.msecs;
}
unittest
{
SYSTEMTIME st = void;
GetSystemTime(&st);
auto sysTime = SYSTEMTIMEToSysTime(&st, UTC());
SYSTEMTIME result = void;
SysTimeToSYSTEMTIME(sysTime, &result);
assertPred!"=="(st.wYear, result.wYear);
assertPred!"=="(st.wMonth, result.wMonth);
assertPred!"=="(st.wDayOfWeek, result.wDayOfWeek);
assertPred!"=="(st.wDay, result.wDay);
assertPred!"=="(st.wHour, result.wHour);
assertPred!"=="(st.wMinute, result.wMinute);
assertPred!"=="(st.wSecond, result.wSecond);
assertPred!"=="(st.wMillisecond, result.wMillisecond);
}
/++
On Windows, this converts a FILETIME struct to a SysTime.
Params:
ft = The FILETIME struct to convert.
tz = The time zone that the SysTime will be in (FILETIMEs are
in UTC).
Throws:
DateTimeException if the given FILETIME will not fit in a SysTime or
if the FILETIME cannot be converted to a SYSTEMTIME.
+/
SysTime FILETIMEToSysTime(const FILETIME* ft, immutable TimeZone tz = LocalTime()) pure
{
SYSTEMTIME st = void;
if(!FileTimeToSystemTime(ft, &st))
throw new DateTimeException("FileTimeToSystemTime() failed.");
auto sysTime = SYSTEMTIMEToSysTime(&st, UTC());
sysTime.timezone = tz;
return sysTime;
}
unittest
{
auto sysTime = Clock.currTime(UTC());
SYSTEMTIME st = void;
GetSystemTime(&st);
FILETIME ft = void;
SystemTimeToFileTime(&st, &ft);
auto converted = FILETIMEToSysTime(&ft);
assertPred!"<="(sysTime, converted);
assertPred!"<="(converted - sysTime, dur!"msecs"(10));
}
/++
On Windows, this converts a SysTime to a FILETIME struct.
Params:
sysTime = The SysTime to convert.
ft = The FILETIME struct to fill in with the date and
time from sysTime.
Throws:
DateTimeException if the given SysTime will not fit in a FILETIME.
+/
void SysTimeToFILETIME(SysTime sysTime, FILETIME* ft) pure
{
sysTime.timezone = UTC();
immutable dt = cast(DateTime)sysTime;
SYSTEMTIME st = void;
SysTimeToSYSTEMTIME(sysTime, st);
SystemTimeToFileTime(&st, ft);
}
unittest
{
SYSTEMTIME st = void;
GetSystemTime(&st);
FILETIME ft = void;
SystemTimeToFileTime(&st, &ft);
auto sysTime = FILETIMEToSysTime(&ft, UTC());
FILETIME result = void;
SysTimeToFILETIME(sysTime, &result);
assertPred!"=="(ft.dwLowDateTime, result.fwLowDateTime);
assertPred!"=="(ft.dwHighDateTime, result.fwHighDateTime);
}
}
else version(D_Ddoc)
{
//These types don't exist outside of Windows.
alias int SYSTEMTIME;
alias int FILETIME;
/++
On Windows, this converts a SYSTEMTIME struct to a SysTime.
Params:
st = The SYSTEMTIME struct to convert.
tz = The time zone that the time in the SYSTEMTIME struct
is assumed to be (if the SYSTEMTIME was supplied by a
Windows system call, the SYSTEMTIME will either be in
local time or UTC, depending on the call).
Throws:
DateTimeException if the given SYSTEMTIME will not fit in a SysTime,
which is highly unlikely to happen given that SysTime.max is in 29,228 A.D.
and the maximum SYSTEMTIME is in 30,827 A.D.
+/
SysTime SYSTEMTIMEToSysTime(const SYSTEMTIME* st, immutable TimeZone tz = LocalTime()) pure
{
assert(0, "No implementation. Function exists only for DDoc generation");
}
/++
On Windows, this converts a SysTime to a SYSTEMTIME struct.
The SYSTEMTIME will be set using the given SysTime's time zone, so
if you want the SYSTEMTIME to be in UTC, set the SysTime's time zone
to UTC.
Params:
sysTime = The SysTime to convert.
st = The SYSTEMTIME struct to fill in with the date and
time from sysTime.
Throws:
DateTimeException if the given SysTime will not fit in a SYSTEMTIME.
This will only happen if the SysTime's date is prior to 1601 A.D.
+/
void SysTimeToSYSTEMTIME(in SysTime sysTime, SYSTEMTIME* st) pure
{
assert(0, "No implementation. Function exists only for DDoc generation");
}
/++
On Windows, this converts a FILETIME struct to a SysTime.
Params:
ft = The FILETIME struct to convert.
tz = The time zone that the SysTime will be in (FILETIMEs are
in UTC).
Throws:
DateTimeException if the given FILETIME will not fit in a SysTime or
if the FILETIME cannot be converted to a SYSTEMTIME.
+/
SysTime FILETIMEToSysTime(const FILETIME* ft, immutable TimeZone tz = LocalTime()) pure
{
assert(0, "No implementation. Function exists only for DDoc generation");
}
/++
On Windows, this converts a SysTime to a FILETIME struct.
Params:
sysTime = The SysTime to convert.
ft = The FILETIME struct to fill in with the date and
time from sysTime.
Throws:
DateTimeException if the given SysTime will not fit in a FILETIME.
+/
void SysTimeToFILETIME(SysTime sysTime, FILETIME* ft) pure
{
assert(0, "No implementation. Function exists only for DDoc generation");
}
}
/++
Type representing the DOS file date/time format.
+/
typedef uint DosFileTime;
/++
Converts from DOS file date/time to SysTime.
Params:
dft = The DOS file time to convert.
tz = The time zone which the DOS file time is assumed to be in.
Throws:
DateTimeException if the DosFileTime is invalid.
+/
SysTime DosFileTimeToSysTime(DosFileTime dft, immutable TimeZone tz = LocalTime())
{
uint dt = cast(uint)dft;
if(dt == 0)
throw new DateTimeException("Invalid DosFileTime.");
int year = ((dt >> 25) & 0x7F) + 1980;
int month = ((dt >> 21) & 0x0F) - 1; // 1..12
int dayOfMonth = ((dt >> 16) & 0x1F); // 1..31
int hour = (dt >> 11) & 0x1F; // 0..23
int minute = (dt >> 5) & 0x3F; // 0..59
int second = (dt << 1) & 0x3E; // 0..58 (in 2 second increments)
SysTime sysTime = void;
try
return SysTime(DateTime(year, month, dayOfMonth, hour, minute, second), tz);
catch(DateTimeException dte)
throw new DateTimeException("Invalid DosFileTime", __FILE__, __LINE__, dte);
}
/++
Converts from SysTime to DOS file date/time.
Params:
sysTime = The SysTime to convert.
Throws:
DateTimeException if the given SysTime cannot be converted to
a DosFileTime.
+/
DosFileTime SysTimeToDosFileTime(SysTime sysTime)
{
auto dateTime = cast(DateTime)sysTime;
if(dateTime.year < 1980)
throw new DateTimeException("DOS File Times cannot hold dates prior to 1980.");
if(dateTime.year > 2107)
throw new DateTimeException("DOS File Times cannot hold dates passed 2107.");
uint retval = 0;
retval = (dateTime.year - 1980) << 25;
retval |= ((dateTime.month + 1) & 0x0F) << 21;
retval |= (dateTime.day & 0x1F) << 16;
retval |= (dateTime.hour & 0x1F) << 11;
retval |= (dateTime.minute & 0x3F) << 5;
retval |= (dateTime.second >> 1) & 0x1F;
return cast(DosFileTime)retval;
}
/++
Whether all of the given strings are valid units of time.
"nsecs" is not considered a valid unit of time. Nothing in
std.datetime can handle precision greater than hnsecs, and
the few functions in core.time which deal with "nsecs"
deal with it explicitly.
+/
bool validTimeUnits(string[] units...)
{
foreach(str; units)
{
if(!canFind(timeStrings.dup, str))
return false;
}
return true;
}
/++
Compares two TimeStrings. "years" are the largest units and "hnsecs" are
the smallest.
Returns:
$(TABLE
$(TR $(TD this < rhs) $(TD < 0))
$(TR $(TD this == rhs) $(TD 0))
$(TR $(TD this > rhs) $(TD > 0))
)
Throws:
DateTimeException if either of the given strings is not a valid time
unit string.
+/
int cmpTimeUnits(string lhs, string rhs)
{
auto tstrings = timeStrings.dup;
immutable indexOfLHS = std.algorithm.indexOf(tstrings, lhs);
immutable indexOfRHS = std.algorithm.indexOf(tstrings, rhs);
enforce(indexOfLHS != -1, format("%s is not a valid TimeString", lhs));
enforce(indexOfRHS != -1, format("%s is not a valid TimeString", rhs));
if(indexOfLHS < indexOfRHS)
return -1;
if(indexOfLHS > indexOfRHS)
return 1;
return 0;
}
unittest
{
foreach(i, outerUnits; timeStrings)
{
assertPred!"=="(cmpTimeUnits(outerUnits, outerUnits), 0);
//For some reason, $ won't compile.
foreach(innerUnits; timeStrings[i+1 .. timeStrings.length])
assertPred!"=="(cmpTimeUnits(outerUnits, innerUnits), -1);
}
foreach(i, outerUnits; timeStrings)
{
foreach(innerUnits; timeStrings[0 .. i])
assertPred!"=="(cmpTimeUnits(outerUnits, innerUnits), 1);
}
}
/++
Compares two time unit strings at compile time. "years" are the largest
units and "hnsecs" are the smallest.
This template is used instead of $(D cmpTimeUnits()) because exceptions
can't be thrown at compile-time and $(D cmpTimeUnits()) must enforce that
the strings it's given are valid time unit strings. This template uses a
template constraint instead.
Returns:
$(TABLE
$(TR $(TD this < rhs) $(TD < 0))
$(TR $(TD this == rhs) $(TD 0))
$(TR $(TD this > rhs) $(TD > 0))
)
+/
template CmpTimeUnits(string lhs, string rhs)
if(validTimeUnits(lhs, rhs))
{
enum CmpTimeUnits = cmpTimeUnitsCTFE(lhs, rhs);
}
/+
Helper function for CmpTimeUnits.
+/
private int cmpTimeUnitsCTFE(string lhs, string rhs)
{
auto tstrings = timeStrings.dup;
immutable indexOfLHS = std.algorithm.indexOf(tstrings, lhs);
immutable indexOfRHS = std.algorithm.indexOf(tstrings, rhs);
if(indexOfLHS < indexOfRHS)
return -1;
if(indexOfLHS > indexOfRHS)
return 1;
return 0;
}
unittest
{
static string genTest(size_t index)
{
auto currUnits = timeStrings[index];
auto test = `assertPred!"=="(CmpTimeUnits!("` ~ currUnits ~ `", "` ~ currUnits ~ `"), 0); `;
//For some reason, $ won't compile.
foreach(units; timeStrings[index + 1 .. timeStrings.length])
test ~= `assertPred!"=="(CmpTimeUnits!("` ~ currUnits ~ `", "` ~ units ~ `"), -1); `;
foreach(units; timeStrings[0 .. index])
test ~= `assertPred!"=="(CmpTimeUnits!("` ~ currUnits ~ `", "` ~ units ~ `"), 1); `;
return test;
}
mixin(genTest(0));
mixin(genTest(1));
mixin(genTest(2));
mixin(genTest(3));
mixin(genTest(4));
mixin(genTest(5));
mixin(genTest(6));
mixin(genTest(7));
mixin(genTest(8));
mixin(genTest(9));
}
/++
Returns whether the given value is valid for the given unit type when in a
time point. Naturally, a duration is not held to a particular range, but
the values in a time point are (e.g. a month must be in the range of
1 - 12 inclusive).
Params:
units = The units of time to validate.
value = The number to validate.
Examples:
--------------------
assert(valid!"hours"(12));
assert(!valid!"hours"(32));
assert(valid!"months"(12));
assert(!valid!"months"(13));
--------------------
+/
bool valid(string units)(int value) pure nothrow
if(units == "months" ||
units == "hours" ||
units == "minutes" ||
units == "seconds")
{
static if(units == "months")
return value >= Month.jan && value <= Month.dec;
else static if(units == "hours")
return value >= 0 && value <= TimeOfDay.maxHour;
else static if(units == "minutes")
return value >= 0 && value <= TimeOfDay.maxMinute;
else static if(units == "seconds")
return value >= 0 && value <= TimeOfDay.maxSecond;
}
unittest
{
//Verify Examples.
assert(valid!"hours"(12));
assert(!valid!"hours"(32));
assert(valid!"months"(12));
assert(!valid!"months"(13));
}
/++
Returns whether the given day is valid for the given year and month.
Params:
units = The units of time to validate.
year = The year of the day to validate.
month = The month of the day to validate.
day = The day to validate.
+/
bool valid(string units)(int year, int month, int day) pure nothrow
if(units == "days")
{
return day > 0 && day <= maxDay(year, month);
}
/++
Params:
units = The units of time to validate.
value = The number to validate.
file = The file that the DateTimeException will list if thrown.
line = The line number that the DateTimeException will list if thrown.
Throws:
DateTimeException if valid!units(value) is false.
+/
void enforceValid(string units)(int value, string file = __FILE__, size_t line = __LINE__) pure
if(units == "months" ||
units == "hours" ||
units == "minutes" ||
units == "seconds")
{
static if(units == "months")
{
if(!valid!units(value))
throw new DateTimeException(numToString(value) ~ " is not a valid month of the year.", file, line);
}
else static if(units == "hours")
{
if(!valid!units(value))
throw new DateTimeException(numToString(value) ~ " is not a valid hour of the day.", file, line);
}
else static if(units == "minutes")
{
if(!valid!units(value))
throw new DateTimeException(numToString(value) ~ " is not a valid minute of an hour.", file, line);
}
else static if(units == "seconds")
{
if(!valid!units(value))
throw new DateTimeException(numToString(value) ~ " is not a valid second of a minute.", file, line);
}
}
/++
Params:
units = The units of time to validate.
year = The year of the day to validate.
month = The month of the day to validate.
day = The day to validate.
file = The file that the DateTimeException will list if thrown.
line = The line number that the DateTimeException will list if thrown.
Throws:
DateTimeException if valid!"days"(year, month, day) is false.
+/
void enforceValid(string units)(int year, Month month, int day, string file = __FILE__, size_t line = __LINE__) pure
if(units == "days")
{
if(!valid!"days"(year, month, day))
{
throw new DateTimeException(numToString(day) ~
" is not a valid day in " ~
monthToString(month) ~
" in " ~
numToString(year), file, line);
}
}
/++
Returns the number of months from the current months of the year to the
given month of the year. If they are the same, then the result is 0.
Params:
currMonth = The current month of the year.
month = The month of the year to get the number of months to.
+/
static int monthsToMonth(int currMonth, int month) pure
{
enforceValid!"months"(currMonth);
enforceValid!"months"(month);
if(currMonth == month)
return 0;
if(currMonth < month)
return month - currMonth;
return (Month.dec - currMonth) + month;
}
unittest
{
assertPred!"=="(monthsToMonth(Month.jan, Month.jan), 0);
assertPred!"=="(monthsToMonth(Month.jan, Month.feb), 1);
assertPred!"=="(monthsToMonth(Month.jan, Month.mar), 2);
assertPred!"=="(monthsToMonth(Month.jan, Month.apr), 3);
assertPred!"=="(monthsToMonth(Month.jan, Month.may), 4);
assertPred!"=="(monthsToMonth(Month.jan, Month.jun), 5);
assertPred!"=="(monthsToMonth(Month.jan, Month.jul), 6);
assertPred!"=="(monthsToMonth(Month.jan, Month.aug), 7);
assertPred!"=="(monthsToMonth(Month.jan, Month.sep), 8);
assertPred!"=="(monthsToMonth(Month.jan, Month.oct), 9);
assertPred!"=="(monthsToMonth(Month.jan, Month.nov), 10);
assertPred!"=="(monthsToMonth(Month.jan, Month.dec), 11);
assertPred!"=="(monthsToMonth(Month.may, Month.jan), 8);
assertPred!"=="(monthsToMonth(Month.may, Month.feb), 9);
assertPred!"=="(monthsToMonth(Month.may, Month.mar), 10);
assertPred!"=="(monthsToMonth(Month.may, Month.apr), 11);
assertPred!"=="(monthsToMonth(Month.may, Month.may), 0);
assertPred!"=="(monthsToMonth(Month.may, Month.jun), 1);
assertPred!"=="(monthsToMonth(Month.may, Month.jul), 2);
assertPred!"=="(monthsToMonth(Month.may, Month.aug), 3);
assertPred!"=="(monthsToMonth(Month.may, Month.sep), 4);
assertPred!"=="(monthsToMonth(Month.may, Month.oct), 5);
assertPred!"=="(monthsToMonth(Month.may, Month.nov), 6);
assertPred!"=="(monthsToMonth(Month.may, Month.dec), 7);
assertPred!"=="(monthsToMonth(Month.oct, Month.jan), 3);
assertPred!"=="(monthsToMonth(Month.oct, Month.feb), 4);
assertPred!"=="(monthsToMonth(Month.oct, Month.mar), 5);
assertPred!"=="(monthsToMonth(Month.oct, Month.apr), 6);
assertPred!"=="(monthsToMonth(Month.oct, Month.may), 7);
assertPred!"=="(monthsToMonth(Month.oct, Month.jun), 8);
assertPred!"=="(monthsToMonth(Month.oct, Month.jul), 9);
assertPred!"=="(monthsToMonth(Month.oct, Month.aug), 10);
assertPred!"=="(monthsToMonth(Month.oct, Month.sep), 11);
assertPred!"=="(monthsToMonth(Month.oct, Month.oct), 0);
assertPred!"=="(monthsToMonth(Month.oct, Month.nov), 1);
assertPred!"=="(monthsToMonth(Month.oct, Month.dec), 2);
assertPred!"=="(monthsToMonth(Month.dec, Month.jan), 1);
assertPred!"=="(monthsToMonth(Month.dec, Month.feb), 2);
assertPred!"=="(monthsToMonth(Month.dec, Month.mar), 3);
assertPred!"=="(monthsToMonth(Month.dec, Month.apr), 4);
assertPred!"=="(monthsToMonth(Month.dec, Month.may), 5);
assertPred!"=="(monthsToMonth(Month.dec, Month.jun), 6);
assertPred!"=="(monthsToMonth(Month.dec, Month.jul), 7);
assertPred!"=="(monthsToMonth(Month.dec, Month.aug), 8);
assertPred!"=="(monthsToMonth(Month.dec, Month.sep), 9);
assertPred!"=="(monthsToMonth(Month.dec, Month.oct), 10);
assertPred!"=="(monthsToMonth(Month.dec, Month.nov), 11);
assertPred!"=="(monthsToMonth(Month.dec, Month.dec), 0);
}
/++
Returns the number of days from the current day of the week to the given
day of the week. If they are the same, then the result is 0.
Params:
currDoW = The current day of the week.
dow = The day of the week to get the number of days to.
+/
static int daysToDayOfWeek(DayOfWeek currDoW, DayOfWeek dow) pure nothrow
{
if(currDoW == dow)
return 0;
if(currDoW < dow)
return dow - currDoW;
return (DayOfWeek.sat - currDoW) + dow + 1;
}
unittest
{
assertPred!"=="(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.sun), 0);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.mon), 1);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.tue), 2);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.wed), 3);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.thu), 4);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.fri), 5);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.sat), 6);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.sun), 6);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.mon), 0);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.tue), 1);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.wed), 2);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.thu), 3);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.fri), 4);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.sat), 5);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.sun), 5);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.mon), 6);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.tue), 0);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.wed), 1);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.thu), 2);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.fri), 3);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.sat), 4);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.sun), 4);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.mon), 5);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.tue), 6);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.wed), 0);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.thu), 1);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.fri), 2);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.sat), 3);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.sun), 3);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.mon), 4);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.tue), 5);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.wed), 6);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.thu), 0);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.fri), 1);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.sat), 2);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.sun), 2);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.mon), 3);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.tue), 4);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.wed), 5);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.thu), 6);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.fri), 0);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.sat), 1);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.sun), 1);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.mon), 2);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.tue), 3);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.wed), 4);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.thu), 5);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.fri), 6);
assertPred!"=="(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.sat), 0);
}
//This should be removed as soon the bug with auto return functions not
//showing up in the documentation generated by ddoc is fixed.
version(D_Ddoc)
{
//Here purely to make it so that TemporaryValue is defined and will compile.
alias long TemporaryValue;
/++
Function for starting to a stop watch time when the function is called
and stopping it when its return value goes out of scope and is destroyed.
When the value that is returned by this function is destroyed,
$(D func()) will run. $(D func()) is a unary function that takes a
TickDuration.
Examples:
--------------------
writeln("benchmark start!");
{
auto mt = measureTime!((a){assert(a.seconds);});
doSomething();
}
writeln("benchmark end!");
--------------------
+/
TemporaryValue measureTime(alias func)();
}
else
{
@safe
{
auto measureTime(alias func)()
if(isSafe!func)
{
struct TMP
{
private StopWatch sw = void;
this(StopWatch.AutoStart as)
{
sw = StopWatch(as);
}
~this()
{
unaryFun!(func)(sw.peek());
}
}
return TMP(autoStart);
}
}
@system
{
auto measureTime(alias func)()
if (!isSafe!func)
{
struct TMP
{
private StopWatch sw = void;
this(AutoStart as)
{
sw = StopWatch(as);
}
~this()
{
unaryFun!(func)(sw.peek());
}
}
return TMP(autoStart);
}
}
}
@system
unittest
{
{
auto mt = measureTime!((a){assert(a.to!("seconds", real) <>= 0);});
}
/+
with (measureTime!((a){assert(a.seconds);}))
{
// doSomething();
// @@@BUG@@@ doesn't work yet.
}
+/
}
//==============================================================================
// Private Section.
//
// Note that the templates in the private section are documented but do _not_
// have both +'s to begin their documentation comment blocks. This is because
// of bug 2775 ( http://d.puremagic.com/issues/show_bug.cgi?id=2775 ) which
// makes it so that all templates are actually public. Ideally, most (if not all)
// of these templates would be inside of isTimePoint, but bug 4675
// ( http://d.puremagic.com/issues/show_bug.cgi?id=4675 ) which currently prevents
// putting more that the enum with the template's name inside of an eponymous
// template.
//==============================================================================
private:
//==============================================================================
// Section with private enums and constants.
//==============================================================================
enum daysInYear = 365; /// The number of days in a non-leap year.
enum daysInLeapYear = 366; /// The numbef or days in a leap year.
enum daysIn4Years = daysInYear * 3 + daysInLeapYear; /// Number of days in 4 years.
enum daysIn100Years = daysIn4Years * 25 - 1; /// The number of days in 100 years.
enum daysIn400Years = daysIn100Years * 4 + 1; /// The number of days in 400 years.
//==============================================================================
// Section with private helper functions and templates.
//==============================================================================
/+
Template to help with converting between time units.
+/
template hnsecsPer(string units)
if(CmpTimeUnits!(units, "months") < 0)
{
static if(units == "hnsecs")
enum hnsecsPer = 1L;
else static if(units == "usecs")
enum hnsecsPer = 10L;
else static if(units == "msecs")
enum hnsecsPer = 1000 * hnsecsPer!"usecs";
else static if(units == "seconds")
enum hnsecsPer = 1000 * hnsecsPer!"msecs";
else static if(units == "minutes")
enum hnsecsPer = 60 * hnsecsPer!"seconds";
else static if(units == "hours")
enum hnsecsPer = 60 * hnsecsPer!"minutes";
else static if(units == "days")
enum hnsecsPer = 24 * hnsecsPer!"hours";
else static if(units == "weeks")
enum hnsecsPer = 7 * hnsecsPer!"days";
}
/+
Splits out a particular unit from hnsecs and gives you the value for that
unit and the remaining hnsecs. It really shouldn't be used unless unless
all units larger than the given units have already been split out.
Params:
units = The units to split out.
hnsecs = The current total hnsecs. Upon returning, it is the hnsecs left
after splitting out the given units.
Returns:
The number of the given units from converting hnsecs to those units.
Examples:
--------------------
auto hnsecs = 2595000000007L;
immutable days = splitUnitsFromHNSecs!"days"(hnsecs);
assert(days == 3);
assert(hnsecs == 3000000007);
immutable minutes = splitUnitsFromHNSecs!"minutes"(hnsecs);
assert(minutes == 5);
assert(hnsecs == 7);
--------------------
+/
long splitUnitsFromHNSecs(string units)(ref long hnsecs) pure nothrow
if(validTimeUnits(units) &&
CmpTimeUnits!(units, "months") < 0)
{
immutable value = convert!("hnsecs", units)(hnsecs);
hnsecs -= convert!(units, "hnsecs")(value);
return value;
}
unittest
{
//Verify Example.
auto hnsecs = 2595000000007L;
immutable days = splitUnitsFromHNSecs!"days"(hnsecs);
assert(days == 3);
assert(hnsecs == 3000000007);
immutable minutes = splitUnitsFromHNSecs!"minutes"(hnsecs);
assert(minutes == 5);
assert(hnsecs == 7);
}
/+
This function is used to split out the units without getting the remaining
hnsecs.
See_Also:
splitUnitsFromHNSecs()
Params:
units = The units to split out.
hnsecs = The current total hnsecs.
Returns:
The split out value.
Examples:
--------------------
auto hnsecs = 2595000000007L;
immutable days = getUnitsFromHNSecs!"days"(hnsecs);
assert(days == 3);
assert(hnsecs == 2595000000007L);
--------------------
+/
long getUnitsFromHNSecs(string units)(long hnsecs) pure nothrow
if(validTimeUnits(units) &&
CmpTimeUnits!(units, "months") < 0)
{
return convert!("hnsecs", units)(hnsecs);
}
unittest
{
//Verify Example.
auto hnsecs = 2595000000007L;
immutable days = getUnitsFromHNSecs!"days"(hnsecs);
assert(days == 3);
assert(hnsecs == 2595000000007L);
}
/+
This function is used to split out the units without getting the units but
just the remaining hnsecs.
See_Also:
splitUnitsFromHNSecs()
Params:
units = The units to split out.
hnsecs = The current total hnsecs.
Returns:
The remaining hnsecs.
Examples:
--------------------
auto hnsecs = 2595000000007L;
auto returned = removeUnitsFromHNSecs!"days"(hnsecs);
assert(returned == 3000000007);
assert(hnsecs == 2595000000007L);
--------------------
+/
long removeUnitsFromHNSecs(string units)(long hnsecs) pure nothrow
if(validTimeUnits(units) &&
CmpTimeUnits!(units, "months") < 0)
{
immutable value = convert!("hnsecs", units)(hnsecs);
return hnsecs - convert!(units, "hnsecs")(value);
}
unittest
{
//Verify Example.
auto hnsecs = 2595000000007L;
auto returned = removeUnitsFromHNSecs!"days"(hnsecs);
assert(returned == 3000000007);
assert(hnsecs == 2595000000007L);
}
/+
The maximum valid Day in the given month in the given year.
Params:
year = The year to get the day for.
month = The month of the Gregorian Calendar to get the day for.
+/
static ubyte maxDay(int year, int month) pure nothrow
in
{
assert(valid!"months"(month));
}
body
{
switch(month)
{
case Month.jan, Month.mar, Month.may, Month.jul, Month.aug, Month.oct, Month.dec:
return 31;
case Month.feb:
return yearIsLeapYear(year) ? 29 : 28;
case Month.apr, Month.jun, Month.sep, Month.nov:
return 30;
default:
assert(0, "Invalid month.");
}
}
unittest
{
//Test A.D.
assertPred!"=="(maxDay(1999, 1), 31);
assertPred!"=="(maxDay(1999, 2), 28);
assertPred!"=="(maxDay(1999, 3), 31);
assertPred!"=="(maxDay(1999, 4), 30);
assertPred!"=="(maxDay(1999, 5), 31);
assertPred!"=="(maxDay(1999, 6), 30);
assertPred!"=="(maxDay(1999, 7), 31);
assertPred!"=="(maxDay(1999, 8), 31);
assertPred!"=="(maxDay(1999, 9), 30);
assertPred!"=="(maxDay(1999, 10), 31);
assertPred!"=="(maxDay(1999, 11), 30);
assertPred!"=="(maxDay(1999, 12), 31);
assertPred!"=="(maxDay(2000, 1), 31);
assertPred!"=="(maxDay(2000, 2), 29);
assertPred!"=="(maxDay(2000, 3), 31);
assertPred!"=="(maxDay(2000, 4), 30);
assertPred!"=="(maxDay(2000, 5), 31);
assertPred!"=="(maxDay(2000, 6), 30);
assertPred!"=="(maxDay(2000, 7), 31);
assertPred!"=="(maxDay(2000, 8), 31);
assertPred!"=="(maxDay(2000, 9), 30);
assertPred!"=="(maxDay(2000, 10), 31);
assertPred!"=="(maxDay(2000, 11), 30);
assertPred!"=="(maxDay(2000, 12), 31);
//Test B.C.
assertPred!"=="(maxDay(-1999, 1), 31);
assertPred!"=="(maxDay(-1999, 2), 28);
assertPred!"=="(maxDay(-1999, 3), 31);
assertPred!"=="(maxDay(-1999, 4), 30);
assertPred!"=="(maxDay(-1999, 5), 31);
assertPred!"=="(maxDay(-1999, 6), 30);
assertPred!"=="(maxDay(-1999, 7), 31);
assertPred!"=="(maxDay(-1999, 8), 31);
assertPred!"=="(maxDay(-1999, 9), 30);
assertPred!"=="(maxDay(-1999, 10), 31);
assertPred!"=="(maxDay(-1999, 11), 30);
assertPred!"=="(maxDay(-1999, 12), 31);
assertPred!"=="(maxDay(-2000, 1), 31);
assertPred!"=="(maxDay(-2000, 2), 29);
assertPred!"=="(maxDay(-2000, 3), 31);
assertPred!"=="(maxDay(-2000, 4), 30);
assertPred!"=="(maxDay(-2000, 5), 31);
assertPred!"=="(maxDay(-2000, 6), 30);
assertPred!"=="(maxDay(-2000, 7), 31);
assertPred!"=="(maxDay(-2000, 8), 31);
assertPred!"=="(maxDay(-2000, 9), 30);
assertPred!"=="(maxDay(-2000, 10), 31);
assertPred!"=="(maxDay(-2000, 11), 30);
assertPred!"=="(maxDay(-2000, 12), 31);
}
/+
Returns the day of the week for the given day of the Gregorian Calendar.
Params:
day = The day of the Gregorian Calendar for which to get the day of
the week.
+/
DayOfWeek getDayOfWeek(int day) pure nothrow
{
//January 1st, 1 A.D. was a Monday
if(day >= 0)
return cast(DayOfWeek)(day % 7);
else
{
immutable dow = cast(DayOfWeek)((day % 7) + 7);
if(dow == 7)
return DayOfWeek.sun;
else
return dow;
}
}
unittest
{
//Test A.D.
assertPred!"=="(getDayOfWeek(SysTime(Date(1, 1, 1)).dayOfGregorianCal), DayOfWeek.mon);
assertPred!"=="(getDayOfWeek(SysTime(Date(1, 1, 2)).dayOfGregorianCal), DayOfWeek.tue);
assertPred!"=="(getDayOfWeek(SysTime(Date(1, 1, 3)).dayOfGregorianCal), DayOfWeek.wed);
assertPred!"=="(getDayOfWeek(SysTime(Date(1, 1, 4)).dayOfGregorianCal), DayOfWeek.thu);
assertPred!"=="(getDayOfWeek(SysTime(Date(1, 1, 5)).dayOfGregorianCal), DayOfWeek.fri);
assertPred!"=="(getDayOfWeek(SysTime(Date(1, 1, 6)).dayOfGregorianCal), DayOfWeek.sat);
assertPred!"=="(getDayOfWeek(SysTime(Date(1, 1, 7)).dayOfGregorianCal), DayOfWeek.sun);
assertPred!"=="(getDayOfWeek(SysTime(Date(1, 1, 8)).dayOfGregorianCal), DayOfWeek.mon);
assertPred!"=="(getDayOfWeek(SysTime(Date(1, 1, 9)).dayOfGregorianCal), DayOfWeek.tue);
assertPred!"=="(getDayOfWeek(SysTime(Date(2, 1, 1)).dayOfGregorianCal), DayOfWeek.tue);
assertPred!"=="(getDayOfWeek(SysTime(Date(3, 1, 1)).dayOfGregorianCal), DayOfWeek.wed);
assertPred!"=="(getDayOfWeek(SysTime(Date(4, 1, 1)).dayOfGregorianCal), DayOfWeek.thu);
assertPred!"=="(getDayOfWeek(SysTime(Date(5, 1, 1)).dayOfGregorianCal), DayOfWeek.sat);
assertPred!"=="(getDayOfWeek(SysTime(Date(2000, 1, 1)).dayOfGregorianCal), DayOfWeek.sat);
assertPred!"=="(getDayOfWeek(SysTime(Date(2010, 8, 22)).dayOfGregorianCal), DayOfWeek.sun);
assertPred!"=="(getDayOfWeek(SysTime(Date(2010, 8, 23)).dayOfGregorianCal), DayOfWeek.mon);
assertPred!"=="(getDayOfWeek(SysTime(Date(2010, 8, 24)).dayOfGregorianCal), DayOfWeek.tue);
assertPred!"=="(getDayOfWeek(SysTime(Date(2010, 8, 25)).dayOfGregorianCal), DayOfWeek.wed);
assertPred!"=="(getDayOfWeek(SysTime(Date(2010, 8, 26)).dayOfGregorianCal), DayOfWeek.thu);
assertPred!"=="(getDayOfWeek(SysTime(Date(2010, 8, 27)).dayOfGregorianCal), DayOfWeek.fri);
assertPred!"=="(getDayOfWeek(SysTime(Date(2010, 8, 28)).dayOfGregorianCal), DayOfWeek.sat);
assertPred!"=="(getDayOfWeek(SysTime(Date(2010, 8, 29)).dayOfGregorianCal), DayOfWeek.sun);
//Test B.C.
assertPred!"=="(getDayOfWeek(SysTime(Date(0, 12, 31)).dayOfGregorianCal), DayOfWeek.sun);
assertPred!"=="(getDayOfWeek(SysTime(Date(0, 12, 30)).dayOfGregorianCal), DayOfWeek.sat);
assertPred!"=="(getDayOfWeek(SysTime(Date(0, 12, 29)).dayOfGregorianCal), DayOfWeek.fri);
assertPred!"=="(getDayOfWeek(SysTime(Date(0, 12, 28)).dayOfGregorianCal), DayOfWeek.thu);
assertPred!"=="(getDayOfWeek(SysTime(Date(0, 12, 27)).dayOfGregorianCal), DayOfWeek.wed);
assertPred!"=="(getDayOfWeek(SysTime(Date(0, 12, 26)).dayOfGregorianCal), DayOfWeek.tue);
assertPred!"=="(getDayOfWeek(SysTime(Date(0, 12, 25)).dayOfGregorianCal), DayOfWeek.mon);
assertPred!"=="(getDayOfWeek(SysTime(Date(0, 12, 24)).dayOfGregorianCal), DayOfWeek.sun);
assertPred!"=="(getDayOfWeek(SysTime(Date(0, 12, 23)).dayOfGregorianCal), DayOfWeek.sat);
}
/++
Returns the string representation of the given month.
Params:
useLongName = Whether the long or short version of the month name should
be used.
plural = Whether the string should be plural or not.
Throws:
DateTimeException if the given month is not a valid month.
+/
string monthToString(Month month, bool useLongName = true) pure
{
if(useLongName == true)
{
switch(month)
{
case Month.jan:
return "January";
case Month.feb:
return "February";
case Month.mar:
return "March";
case Month.apr:
return "April";
case Month.may:
return "May";
case Month.jun:
return "June";
case Month.jul:
return "July";
case Month.aug:
return "August";
case Month.sep:
return "September";
case Month.oct:
return "October";
case Month.nov:
return "November";
case Month.dec:
return "December";
default:
throw new DateTimeException("Invalid month: " ~ numToString(month));
}
}
else
{
switch(month)
{
case Month.jan:
return "Jan";
case Month.feb:
return "Feb";
case Month.mar:
return "Mar";
case Month.apr:
return "Apr";
case Month.may:
return "May";
case Month.jun:
return "Jun";
case Month.jul:
return "Jul";
case Month.aug:
return "Aug";
case Month.sep:
return "Sep";
case Month.oct:
return "Oct";
case Month.nov:
return "Nov";
case Month.dec:
return "Dec";
default:
throw new DateTimeException("Invalid month: " ~ numToString(month));
}
}
}
unittest
{
static void testMTSInvalid(Month month, bool useLongName)
{
monthToString(month, useLongName);
}
assertThrown!DateTimeException(testMTSInvalid(cast(Month)0, true));
assertThrown!DateTimeException(testMTSInvalid(cast(Month)0, false));
assertThrown!DateTimeException(testMTSInvalid(cast(Month)13, true));
assertThrown!DateTimeException(testMTSInvalid(cast(Month)13, false));
assertPred!"=="(monthToString(Month.jan), "January");
assertPred!"=="(monthToString(Month.feb), "February");
assertPred!"=="(monthToString(Month.mar), "March");
assertPred!"=="(monthToString(Month.apr), "April");
assertPred!"=="(monthToString(Month.may), "May");
assertPred!"=="(monthToString(Month.jun), "June");
assertPred!"=="(monthToString(Month.jul), "July");
assertPred!"=="(monthToString(Month.aug), "August");
assertPred!"=="(monthToString(Month.sep), "September");
assertPred!"=="(monthToString(Month.oct), "October");
assertPred!"=="(monthToString(Month.nov), "November");
assertPred!"=="(monthToString(Month.dec), "December");
assertPred!"=="(monthToString(Month.jan, false), "Jan");
assertPred!"=="(monthToString(Month.feb, false), "Feb");
assertPred!"=="(monthToString(Month.mar, false), "Mar");
assertPred!"=="(monthToString(Month.apr, false), "Apr");
assertPred!"=="(monthToString(Month.may, false), "May");
assertPred!"=="(monthToString(Month.jun, false), "Jun");
assertPred!"=="(monthToString(Month.jul, false), "Jul");
assertPred!"=="(monthToString(Month.aug, false), "Aug");
assertPred!"=="(monthToString(Month.sep, false), "Sep");
assertPred!"=="(monthToString(Month.oct, false), "Oct");
assertPred!"=="(monthToString(Month.nov, false), "Nov");
assertPred!"=="(monthToString(Month.dec, false), "Dec");
}
/++
Returns the Month corresponding to the given string. Casing is ignored.
Params:
monthStr = The string representation of the month to get the Month for.
Throws:
DateTimeException if the given month is not a valid month string.
+/
Month monthFromString(string monthStr)
{
switch(tolower(monthStr))
{
case "january":
case "jan":
return Month.jan;
case "february":
case "feb":
return Month.feb;
case "march":
case "mar":
return Month.mar;
case "april":
case "apr":
return Month.apr;
case "may":
return Month.may;
case "june":
case "jun":
return Month.jun;
case "july":
case "jul":
return Month.jul;
case "august":
case "aug":
return Month.aug;
case "september":
case "sep":
return Month.sep;
case "october":
case "oct":
return Month.oct;
case "november":
case "nov":
return Month.nov;
case "december":
case "dec":
return Month.dec;
default:
throw new DateTimeException(format("Invalid month %s", monthStr));
}
}
unittest
{
static void testMFSInvalid(string monthStr)
{
monthFromString(monthStr);
}
assertThrown!DateTimeException(testMFSInvalid("Ja"));
assertThrown!DateTimeException(testMFSInvalid("Janu"));
assertThrown!DateTimeException(testMFSInvalid("Januar"));
assertThrown!DateTimeException(testMFSInvalid("Januarys"));
assertThrown!DateTimeException(testMFSInvalid("JJanuary"));
assertPred!"=="(monthFromString(monthToString(Month.jan)), Month.jan);
assertPred!"=="(monthFromString(monthToString(Month.feb)), Month.feb);
assertPred!"=="(monthFromString(monthToString(Month.mar)), Month.mar);
assertPred!"=="(monthFromString(monthToString(Month.apr)), Month.apr);
assertPred!"=="(monthFromString(monthToString(Month.may)), Month.may);
assertPred!"=="(monthFromString(monthToString(Month.jun)), Month.jun);
assertPred!"=="(monthFromString(monthToString(Month.jul)), Month.jul);
assertPred!"=="(monthFromString(monthToString(Month.aug)), Month.aug);
assertPred!"=="(monthFromString(monthToString(Month.sep)), Month.sep);
assertPred!"=="(monthFromString(monthToString(Month.oct)), Month.oct);
assertPred!"=="(monthFromString(monthToString(Month.nov)), Month.nov);
assertPred!"=="(monthFromString(monthToString(Month.dec)), Month.dec);
assertPred!"=="(monthFromString(monthToString(Month.jan, false)), Month.jan);
assertPred!"=="(monthFromString(monthToString(Month.feb, false)), Month.feb);
assertPred!"=="(monthFromString(monthToString(Month.mar, false)), Month.mar);
assertPred!"=="(monthFromString(monthToString(Month.apr, false)), Month.apr);
assertPred!"=="(monthFromString(monthToString(Month.may, false)), Month.may);
assertPred!"=="(monthFromString(monthToString(Month.jun, false)), Month.jun);
assertPred!"=="(monthFromString(monthToString(Month.jul, false)), Month.jul);
assertPred!"=="(monthFromString(monthToString(Month.aug, false)), Month.aug);
assertPred!"=="(monthFromString(monthToString(Month.sep, false)), Month.sep);
assertPred!"=="(monthFromString(monthToString(Month.oct, false)), Month.oct);
assertPred!"=="(monthFromString(monthToString(Month.nov, false)), Month.nov);
assertPred!"=="(monthFromString(monthToString(Month.dec, false)), Month.dec);
assertPred!"=="(monthFromString("JANUARY"), Month.jan);
assertPred!"=="(monthFromString("JAN"), Month.jan);
assertPred!"=="(monthFromString("january"), Month.jan);
assertPred!"=="(monthFromString("jan"), Month.jan);
assertPred!"=="(monthFromString("jaNuary"), Month.jan);
assertPred!"=="(monthFromString("jaN"), Month.jan);
assertPred!"=="(monthFromString("jaNuaRy"), Month.jan);
assertPred!"=="(monthFromString("jAn"), Month.jan);
}
/+
The time units which are one step smaller than the given units.
Examples:
--------------------
assert(nextSmallerTimeUnits!"years" == "months");
assert(nextSmallerTimeUnits!"usecs" == "hnsecs");
--------------------
+/
template nextSmallerTimeUnits(string units)
if(validTimeUnits(units) &&
timeStrings.front != units)
{
enum nextSmallerTimeUnits = timeStrings[std.algorithm.indexOf(timeStrings.dup, units) - 1];
}
unittest
{
assertPred!"=="(nextSmallerTimeUnits!"months", "weeks");
assertPred!"=="(nextSmallerTimeUnits!"weeks", "days");
assertPred!"=="(nextSmallerTimeUnits!"days", "hours");
assertPred!"=="(nextSmallerTimeUnits!"hours", "minutes");
assertPred!"=="(nextSmallerTimeUnits!"minutes", "seconds");
assertPred!"=="(nextSmallerTimeUnits!"seconds", "msecs");
assertPred!"=="(nextSmallerTimeUnits!"msecs", "usecs");
static assert(!__traits(compiles, nextSmallerTimeUnits!"hnsecs"));
//Verify Examples
assert(nextSmallerTimeUnits!"years" == "months");
assert(nextSmallerTimeUnits!"usecs" == "hnsecs");
}
/+
The time units which are one step larger than the given units.
Examples:
--------------------
assert(nextLargerTimeUnits!"months" == "years");
assert(nextLargerTimeUnits!"hnsecs" == "usecs");
--------------------
+/
template nextLargerTimeUnits(string units)
if(validTimeUnits(units) &&
timeStrings.back != units)
{
enum nextLargerTimeUnits = timeStrings[std.algorithm.indexOf(timeStrings.dup, units) + 1];
}
unittest
{
assertPred!"=="(nextLargerTimeUnits!"usecs", "msecs");
assertPred!"=="(nextLargerTimeUnits!"msecs", "seconds");
assertPred!"=="(nextLargerTimeUnits!"seconds", "minutes");
assertPred!"=="(nextLargerTimeUnits!"minutes", "hours");
assertPred!"=="(nextLargerTimeUnits!"hours", "days");
assertPred!"=="(nextLargerTimeUnits!"days", "weeks");
assertPred!"=="(nextLargerTimeUnits!"weeks", "months");
static assert(!__traits(compiles, nextLargerTimeUnits!"years"));
//Verify Examples
assert(nextLargerTimeUnits!"months" == "years");
assert(nextLargerTimeUnits!"hnsecs" == "usecs");
}
/++
Returns the given hnsecs as an ISO string of fractional seconds.
+/
static string fracSecToISOString(int hnsecs) nothrow
in
{
assert(hnsecs >= 0);
}
body
{
try
{
string isoString = format(".%07d", hnsecs);
while(isoString.endsWith("0"))
isoString.popBack();
if(isoString.length == 1)
return "";
return isoString;
}
catch(Exception e)
assert(0, "format() threw.");
}
unittest
{
assertPred!"=="(fracSecToISOString(0), "");
assertPred!"=="(fracSecToISOString(1), ".0000001");
assertPred!"=="(fracSecToISOString(10), ".000001");
assertPred!"=="(fracSecToISOString(100), ".00001");
assertPred!"=="(fracSecToISOString(1000), ".0001");
assertPred!"=="(fracSecToISOString(10_000), ".001");
assertPred!"=="(fracSecToISOString(100_000), ".01");
assertPred!"=="(fracSecToISOString(1_000_000), ".1");
assertPred!"=="(fracSecToISOString(1_000_001), ".1000001");
assertPred!"=="(fracSecToISOString(1_001_001), ".1001001");
assertPred!"=="(fracSecToISOString(1_071_601), ".1071601");
assertPred!"=="(fracSecToISOString(1_271_641), ".1271641");
assertPred!"=="(fracSecToISOString(9_999_999), ".9999999");
assertPred!"=="(fracSecToISOString(9_999_990), ".999999");
assertPred!"=="(fracSecToISOString(9_999_900), ".99999");
assertPred!"=="(fracSecToISOString(9_999_000), ".9999");
assertPred!"=="(fracSecToISOString(9_990_000), ".999");
assertPred!"=="(fracSecToISOString(9_900_000), ".99");
assertPred!"=="(fracSecToISOString(9_000_000), ".9");
assertPred!"=="(fracSecToISOString(999), ".0000999");
assertPred!"=="(fracSecToISOString(9990), ".000999");
assertPred!"=="(fracSecToISOString(99_900), ".00999");
assertPred!"=="(fracSecToISOString(999_000), ".0999");
}
/++
Returns a FracSec corresponding to to the given ISO string of
fractional seconds.
+/
static FracSec fracSecFromISOString(S)(in S isoString)
if(isSomeString!S)
{
if(isoString.empty)
return FracSec.from!"hnsecs"(0);
auto dstr = to!dstring(isoString);
enforce(dstr.startsWith("."), new DateTimeException("Invalid ISO String"));
dstr.popFront();
enforce(!dstr.empty && dstr.length <= 7, new DateTimeException("Invalid ISO String"));
enforce(!canFind!((dchar c){return !isdigit(c);})(dstr), new DateTimeException("Invalid ISO String"));
dchar[7] fullISOString;
foreach(i, ref dchar c; fullISOString)
{
if(i < dstr.length)
c = dstr[i];
else
c = '0';
}
return FracSec.from!"hnsecs"(to!int(fullISOString[]));
}
unittest
{
static void testFSInvalid(string isoString)
{
fracSecFromISOString(isoString);
}
assertThrown!DateTimeException(testFSInvalid("."));
assertThrown!DateTimeException(testFSInvalid("0."));
assertThrown!DateTimeException(testFSInvalid("0"));
assertThrown!DateTimeException(testFSInvalid("0000000"));
assertThrown!DateTimeException(testFSInvalid(".00000000"));
assertThrown!DateTimeException(testFSInvalid(".00000001"));
assertThrown!DateTimeException(testFSInvalid("T"));
assertThrown!DateTimeException(testFSInvalid("T."));
assertThrown!DateTimeException(testFSInvalid(".T"));
assertPred!"=="(fracSecFromISOString(""), FracSec.from!"hnsecs"(0));
assertPred!"=="(fracSecFromISOString(".0000001"), FracSec.from!"hnsecs"(1));
assertPred!"=="(fracSecFromISOString(".000001"), FracSec.from!"hnsecs"(10));
assertPred!"=="(fracSecFromISOString(".00001"), FracSec.from!"hnsecs"(100));
assertPred!"=="(fracSecFromISOString(".0001"), FracSec.from!"hnsecs"(1000));
assertPred!"=="(fracSecFromISOString(".001"), FracSec.from!"hnsecs"(10_000));
assertPred!"=="(fracSecFromISOString(".01"), FracSec.from!"hnsecs"(100_000));
assertPred!"=="(fracSecFromISOString(".1"), FracSec.from!"hnsecs"(1_000_000));
assertPred!"=="(fracSecFromISOString(".1000001"), FracSec.from!"hnsecs"(1_000_001));
assertPred!"=="(fracSecFromISOString(".1001001"), FracSec.from!"hnsecs"(1_001_001));
assertPred!"=="(fracSecFromISOString(".1071601"), FracSec.from!"hnsecs"(1_071_601));
assertPred!"=="(fracSecFromISOString(".1271641"), FracSec.from!"hnsecs"(1_271_641));
assertPred!"=="(fracSecFromISOString(".9999999"), FracSec.from!"hnsecs"(9_999_999));
assertPred!"=="(fracSecFromISOString(".9999990"), FracSec.from!"hnsecs"(9_999_990));
assertPred!"=="(fracSecFromISOString(".999999"), FracSec.from!"hnsecs"(9_999_990));
assertPred!"=="(fracSecFromISOString(".9999900"), FracSec.from!"hnsecs"(9_999_900));
assertPred!"=="(fracSecFromISOString(".99999"), FracSec.from!"hnsecs"(9_999_900));
assertPred!"=="(fracSecFromISOString(".9999000"), FracSec.from!"hnsecs"(9_999_000));
assertPred!"=="(fracSecFromISOString(".9999"), FracSec.from!"hnsecs"(9_999_000));
assertPred!"=="(fracSecFromISOString(".9990000"), FracSec.from!"hnsecs"(9_990_000));
assertPred!"=="(fracSecFromISOString(".999"), FracSec.from!"hnsecs"(9_990_000));
assertPred!"=="(fracSecFromISOString(".9900000"), FracSec.from!"hnsecs"(9_900_000));
assertPred!"=="(fracSecFromISOString(".9900"), FracSec.from!"hnsecs"(9_900_000));
assertPred!"=="(fracSecFromISOString(".99"), FracSec.from!"hnsecs"(9_900_000));
assertPred!"=="(fracSecFromISOString(".9000000"), FracSec.from!"hnsecs"(9_000_000));
assertPred!"=="(fracSecFromISOString(".9"), FracSec.from!"hnsecs"(9_000_000));
assertPred!"=="(fracSecFromISOString(".0000999"), FracSec.from!"hnsecs"(999));
assertPred!"=="(fracSecFromISOString(".0009990"), FracSec.from!"hnsecs"(9990));
assertPred!"=="(fracSecFromISOString(".000999"), FracSec.from!"hnsecs"(9990));
assertPred!"=="(fracSecFromISOString(".0099900"), FracSec.from!"hnsecs"(99_900));
assertPred!"=="(fracSecFromISOString(".00999"), FracSec.from!"hnsecs"(99_900));
assertPred!"=="(fracSecFromISOString(".0999000"), FracSec.from!"hnsecs"(999_000));
assertPred!"=="(fracSecFromISOString(".0999"), FracSec.from!"hnsecs"(999_000));
}
/+
Whether the given type defines the static property min which returns the
minimum value for the type.
+/
template hasMin(T)
{
enum hasMin = __traits(hasMember, T, "min") &&
__traits(isStaticFunction, T.min) &&
is(ReturnType!(T.min) == Unqual!T) &&
(functionAttributes!(T.min) & FunctionAttribute.PROPERTY) &&
(functionAttributes!(T.min) & FunctionAttribute.NOTHROW);
//(functionAttributes!(T.min) & FunctionAttribute.PURE); //Ideally this would be the case, but SysTime's min() can't currently be pure.
}
unittest
{
static assert(hasMin!(Date));
static assert(hasMin!(TimeOfDay));
static assert(hasMin!(DateTime));
static assert(hasMin!(SysTime));
static assert(hasMin!(const Date));
static assert(hasMin!(const TimeOfDay));
static assert(hasMin!(const DateTime));
static assert(hasMin!(const SysTime));
static assert(hasMin!(immutable Date));
static assert(hasMin!(immutable TimeOfDay));
static assert(hasMin!(immutable SysTime));
}
/+
Whether the given type defines the static property max which returns the
maximum value for the type.
+/
template hasMax(T)
{
enum hasMax = __traits(hasMember, T, "max") &&
__traits(isStaticFunction, T.max) &&
is(ReturnType!(T.max) == Unqual!T) &&
(functionAttributes!(T.max) & FunctionAttribute.PROPERTY) &&
(functionAttributes!(T.max) & FunctionAttribute.NOTHROW);
//(functionAttributes!(T.max) & FunctionAttribute.PURE); //Ideally this would be the case, but SysTime's max() can't currently be pure.
}
unittest
{
static assert(hasMax!(Date));
static assert(hasMax!(TimeOfDay));
static assert(hasMax!(DateTime));
static assert(hasMax!(SysTime));
static assert(hasMax!(const Date));
static assert(hasMax!(const TimeOfDay));
static assert(hasMax!(const DateTime));
static assert(hasMax!(const SysTime));
static assert(hasMax!(immutable Date));
static assert(hasMax!(immutable TimeOfDay));
static assert(hasMax!(immutable DateTime));
static assert(hasMax!(immutable SysTime));
}
/+
Whether the given type defines the overloaded opBinary operators that a time
point is supposed to define which work with time durations. Namely:
$(TABLE
$(TR $(TD TimePoint opBinary"+"(duration)))
$(TR $(TD TimePoint opBinary"-"(duration)))
)
+/
template hasOverloadedOpBinaryWithDuration(T)
{
enum hasOverloadedOpBinaryWithDuration = __traits(compiles, T.init + dur!"days"(5)) &&
is(typeof(T.init + dur!"days"(5)) == Unqual!T) &&
__traits(compiles, T.init - dur!"days"(5)) &&
is(typeof(T.init - dur!"days"(5)) == Unqual!T) &&
__traits(compiles, T.init + TickDuration.from!"hnsecs"(5)) &&
is(typeof(T.init + TickDuration.from!"hnsecs"(5)) == Unqual!T) &&
__traits(compiles, T.init - TickDuration.from!"hnsecs"(5)) &&
is(typeof(T.init - TickDuration.from!"hnsecs"(5)) == Unqual!T);
}
unittest
{
static assert(hasOverloadedOpBinaryWithDuration!(Date));
static assert(hasOverloadedOpBinaryWithDuration!(TimeOfDay));
static assert(hasOverloadedOpBinaryWithDuration!(DateTime));
static assert(hasOverloadedOpBinaryWithDuration!(SysTime));
static assert(hasOverloadedOpBinaryWithDuration!(const Date));
static assert(hasOverloadedOpBinaryWithDuration!(const TimeOfDay));
static assert(hasOverloadedOpBinaryWithDuration!(const DateTime));
static assert(hasOverloadedOpBinaryWithDuration!(const SysTime));
static assert(hasOverloadedOpBinaryWithDuration!(immutable Date));
static assert(hasOverloadedOpBinaryWithDuration!(immutable TimeOfDay));
static assert(hasOverloadedOpBinaryWithDuration!(immutable DateTime));
static assert(hasOverloadedOpBinaryWithDuration!(immutable SysTime));
}
/+
Whether the given type defines the overloaded opOpAssign operators that a time point is supposed
to define. Namely:
$(TABLE
$(TR $(TD TimePoint opOpAssign"+"(duration)))
$(TR $(TD TimePoint opOpAssign"-"(duration)))
)
+/
template hasOverloadedOpAssignWithDuration(T)
{
enum hasOverloadedOpAssignWithDuration = __traits(compiles, T.init += dur!"days"(5)) &&
is(typeof(T.init += dur!"days"(5)) == Unqual!T) &&
__traits(compiles, T.init -= dur!"days"(5)) &&
is(typeof(T.init -= dur!"days"(5)) == Unqual!T) &&
__traits(compiles, T.init += TickDuration.from!"hnsecs"(5)) &&
is(typeof(T.init += TickDuration.from!"hnsecs"(5)) == Unqual!T) &&
__traits(compiles, T.init -= TickDuration.from!"hnsecs"(5)) &&
is(typeof(T.init -= TickDuration.from!"hnsecs"(5)) == Unqual!T);
}
unittest
{
static assert(hasOverloadedOpAssignWithDuration!(Date));
static assert(hasOverloadedOpAssignWithDuration!(TimeOfDay));
static assert(hasOverloadedOpAssignWithDuration!(DateTime));
static assert(hasOverloadedOpAssignWithDuration!(SysTime));
static assert(hasOverloadedOpAssignWithDuration!(const Date));
static assert(hasOverloadedOpAssignWithDuration!(const TimeOfDay));
static assert(hasOverloadedOpAssignWithDuration!(const DateTime));
static assert(hasOverloadedOpAssignWithDuration!(const SysTime));
static assert(hasOverloadedOpAssignWithDuration!(immutable Date));
static assert(hasOverloadedOpAssignWithDuration!(immutable TimeOfDay));
static assert(hasOverloadedOpAssignWithDuration!(immutable DateTime));
static assert(hasOverloadedOpAssignWithDuration!(immutable SysTime));
}
/+
Whether the given type defines the overloaded opBinary operator that a time point is supposed
to define which works with itself. Namely:
$(TABLE
$(TR $(TD duration opBinary"-"(Date)))
)
+/
template hasOverloadedOpBinaryWithSelf(T)
{
enum hasOverloadedOpBinaryWithSelf = __traits(compiles, T.init - T.init) &&
is(Unqual!(typeof(T.init - T.init)) == Duration);
}
unittest
{
static assert(hasOverloadedOpBinaryWithSelf!(Date));
static assert(hasOverloadedOpBinaryWithSelf!(TimeOfDay));
static assert(hasOverloadedOpBinaryWithSelf!(DateTime));
static assert(hasOverloadedOpBinaryWithSelf!(SysTime));
static assert(hasOverloadedOpBinaryWithSelf!(const Date));
static assert(hasOverloadedOpBinaryWithSelf!(const TimeOfDay));
static assert(hasOverloadedOpBinaryWithSelf!(const DateTime));
static assert(hasOverloadedOpBinaryWithSelf!(const SysTime));
static assert(hasOverloadedOpBinaryWithSelf!(immutable Date));
static assert(hasOverloadedOpBinaryWithSelf!(immutable TimeOfDay));
static assert(hasOverloadedOpBinaryWithSelf!(immutable DateTime));
static assert(hasOverloadedOpBinaryWithSelf!(immutable SysTime));
}
/++
Unfortunately, to!string() is not pure, so here's a way to convert
a number to a string which is. Once to!string() is properly pure
(like it hopefully will be at some point), this function should
be removed in favor of using to!string().
+/
string numToString(long value) pure nothrow
{
try
{
immutable negative = value < 0;
char[25] str;
size_t i = str.length;
if(negative)
value = -value;
while(1)
{
char digit = cast(char)('0' + value % 10);
value /= 10;
str[--i] = digit;
assert(i > 0);
if(value == 0)
break;
}
if(negative)
return "-" ~ str[i .. $].idup;
else
return str[i .. $].idup;
}
catch(Exception e)
assert(0, "Something threw when nothing can throw.");
}
/+
A temporary replacement for Rebindable!() until bug http://d.puremagic.com/issues/show_bug.cgi?id=4977
is fixed.
+/
template DTRebindable(T) if (is(T == class) || is(T == interface) || isArray!(T))
{
static if(!is(T X == const(U), U) && !is(T X == immutable(U), U))
{
alias T DTRebindable;
}
else static if(isArray!(T))
{
alias const(ElementType!(T))[] DTRebindable;
}
else
{
struct DTRebindable
{
private union
{
T original;
U stripped;
}
void opAssign(T another) pure nothrow
{
stripped = cast(U) another;
}
void opAssign(DTRebindable another) pure nothrow
{
stripped = another.stripped;
}
static if(is(T == const U))
{
// safely assign immutable to const
void opAssign(DTRebindable!(immutable U) another) pure nothrow
{
stripped = another.stripped;
}
}
this(T initializer) pure nothrow
{
opAssign(initializer);
}
@property ref T get() pure nothrow
{
return original;
}
@property ref T get() const pure nothrow
{
return original;
}
alias get this;
T opDot() pure nothrow
{
return original;
}
T opDot() const pure nothrow
{
return original;
}
}
}
}
//==============================================================================
// Unit testing functions.
//
// Hopefully a version of these will end up in std.exception soon, and these
// will be able to be removed. Not all of the functions currently under review
// are here, just the ones which std.datetime uses.
//==============================================================================
void assertThrown(T : Throwable = Exception, F)
(lazy F funcToCall, string msg = null, string file = __FILE__, size_t line = __LINE__)
{
bool thrown = false;
try
funcToCall();
catch(T t)
thrown = true;
if(!thrown)
{
if(msg.empty)
throw new AssertError(format("assertThrown failed: No %s was thrown.", T.stringof), file, line);
else
throw new AssertError(format("assertThrown failed: No %s was thrown: %s", T.stringof, msg), file, line);
}
}
unittest
{
void throwEx(Throwable t)
{
throw t;
}
void nothrowEx()
{
}
try
assertThrown!Exception(throwEx(new Exception("It's an Exception")));
catch(AssertError)
assert(0);
try
assertThrown!Exception(throwEx(new Exception("It's an Exception")), "It's a message");
catch(AssertError)
assert(0);
try
assertThrown!AssertError(throwEx(new AssertError("It's an AssertError", __FILE__, __LINE__)));
catch(AssertError)
assert(0);
try
assertThrown!AssertError(throwEx(new AssertError("It's an AssertError", __FILE__, __LINE__)), "It's a message");
catch(AssertError)
assert(0);
{
bool thrown = false;
try
assertThrown!Exception(nothrowEx());
catch(AssertError)
thrown = true;
assert(thrown);
}
{
bool thrown = false;
try
assertThrown!Exception(nothrowEx(), "It's a message");
catch(AssertError)
thrown = true;
assert(thrown);
}
{
bool thrown = false;
try
assertThrown!AssertError(nothrowEx());
catch(AssertError)
thrown = true;
assert(thrown);
}
{
bool thrown = false;
try
assertThrown!AssertError(nothrowEx(), "It's a message");
catch(AssertError)
thrown = true;
assert(thrown);
}
//Verify Examples.
void timeFunc(int hour, int minute, int second)
{
enforce(hour >= 0 && hour <= 23);
enforce(minute >= 0 && minute <= 59);
enforce(second >= 0 && second <= 59);
//...
}
assertThrown!Exception(timeFunc(-1, 15, 30));
assertThrown!Exception(timeFunc(12, 60, 30));
assertThrown(timeFunc(12, 15, 60)); //Exception is default.
void nameFunc(string name)
{
enforce(!name.empty);
enforce(name.length < 30);
//...
}
assertThrown(nameFunc(""));
assertThrown(nameFunc("1234567890123456789012345678901"));
void assertPlease()
{
}
assert(collectExceptionMsg(assertThrown!AssertError(assertPlease())) ==
"assertThrown failed: No AssertError was thrown.");
assert(collectExceptionMsg(assertThrown!AssertError(assertPlease(), "error!")) ==
"assertThrown failed: No AssertError was thrown: error!");
}
void assertPred(string op, L, R)
(L lhs, R rhs, lazy string msg = null, string file = __FILE__, size_t line = __LINE__)
if((op == "<" ||
op == "<=" ||
op == "==" ||
op == "!=" ||
op == ">=" ||
op == ">") &&
__traits(compiles, mixin("lhs " ~ op ~ " rhs")) &&
isPrintable!L &&
isPrintable!R)
{
immutable result = mixin("lhs " ~ op ~ " rhs");
if(!result)
{
if(msg.empty)
throw new AssertError(format(`assertPred!"%s" failed: [%s] is not %s [%s].`, op, lhs, op, rhs), file, line);
else
throw new AssertError(format(`assertPred!"%s" failed: [%s] is not %s [%s]: %s`, op, lhs, op, rhs, msg), file, line);
}
}
unittest
{
struct IntWrapper
{
int value;
this(int value)
{
this.value = value;
}
string toString()
{
return to!string(value);
}
}
//Test ==.
assertNotThrown!AssertError(assertPred!"=="(6, 6));
assertNotThrown!AssertError(assertPred!"=="(6, 6.0));
assertNotThrown!AssertError(assertPred!"=="(IntWrapper(6), IntWrapper(6)));
assertThrown!AssertError(assertPred!"=="(6, 7));
assertThrown!AssertError(assertPred!"=="(6, 6.1));
assertThrown!AssertError(assertPred!"=="(IntWrapper(6), IntWrapper(7)));
assertThrown!AssertError(assertPred!"=="(IntWrapper(7), IntWrapper(6)));
assertPred!"=="(collectExceptionMsg(assertPred!"=="(6, 7)),
`assertPred!"==" failed: [6] is not == [7].`);
assertPred!"=="(collectExceptionMsg(assertPred!"=="(6, 7, "It failed!")),
`assertPred!"==" failed: [6] is not == [7]: It failed!`);
//Test !=.
assertNotThrown!AssertError(assertPred!"!="(6, 7));
assertNotThrown!AssertError(assertPred!"!="(6, 6.1));
assertNotThrown!AssertError(assertPred!"!="(IntWrapper(6), IntWrapper(7)));
assertNotThrown!AssertError(assertPred!"!="(IntWrapper(7), IntWrapper(6)));
assertThrown!AssertError(assertPred!"!="(6, 6));
assertThrown!AssertError(assertPred!"!="(6, 6.0));
assertThrown!AssertError(assertPred!"!="(IntWrapper(6), IntWrapper(6)));
assertPred!"=="(collectExceptionMsg(assertPred!"!="(6, 6)),
`assertPred!"!=" failed: [6] is not != [6].`);
assertPred!"=="(collectExceptionMsg(assertPred!"!="(6, 6, "It failed!")),
`assertPred!"!=" failed: [6] is not != [6]: It failed!`);
//Test <, <=, >=, >.
assertNotThrown!AssertError(assertPred!"<"(5, 7));
assertNotThrown!AssertError(assertPred!"<="(5, 7));
assertNotThrown!AssertError(assertPred!"<="(5, 5));
assertNotThrown!AssertError(assertPred!">="(7, 7));
assertNotThrown!AssertError(assertPred!">="(7, 5));
assertNotThrown!AssertError(assertPred!">"(7, 5));
assertThrown!AssertError(assertPred!"<"(7, 5));
assertThrown!AssertError(assertPred!"<="(7, 5));
assertThrown!AssertError(assertPred!">="(5, 7));
assertThrown!AssertError(assertPred!">"(5, 7));
assertPred!"=="(collectExceptionMsg(assertPred!"<"(7, 5)),
`assertPred!"<" failed: [7] is not < [5].`);
assertPred!"=="(collectExceptionMsg(assertPred!"<"(7, 5, "It failed!")),
`assertPred!"<" failed: [7] is not < [5]: It failed!`);
//Verify Examples.
//Equivalent to assert(5 / 2 + 4 < 27);
assertPred!"<"(5 / 2 + 4, 27);
//Equivalent to assert(4 <= 5);
assertPred!"<="(4, 5);
//Equivalent to assert(1 * 2.1 == 2.1);
assertPred!"=="(1 * 2.1, 2.1);
//Equivalent to assert("hello " ~ "world" != "goodbye world");
assertPred!"!="("hello " ~ "world", "goodbye world");
//Equivalent to assert(14.2 >= 14);
assertPred!">="(14.2, 14);
//Equivalent to assert(15 > 2 + 1);
assertPred!">"(15, 2 + 1);
assert(collectExceptionMsg(assertPred!"=="("hello", "goodbye")) ==
`assertPred!"==" failed: [hello] is not == [goodbye].`);
assert(collectExceptionMsg(assertPred!"<"(5, 2, "My test failed!")) ==
`assertPred!"<" failed: [5] is not < [2]: My test failed!`);
}
void assertNotThrown(T : Throwable = Exception, F)
(lazy F funcToCall, string msg = null, string file = __FILE__, size_t line = __LINE__)
{
try
funcToCall();
catch(T t)
{
if(msg.empty)
throw new AssertError(format("assertNotThrown failed: %s was thrown.", T.stringof), file, line);
else
throw new AssertError(format("assertNotThrown failed: %s was thrown: %s", T.stringof, msg), file, line);
}
}
unittest
{
void throwEx(Throwable t)
{
throw t;
}
void nothrowEx()
{
}
try
assertNotThrown!Exception(nothrowEx());
catch(AssertError)
assert(0);
try
assertNotThrown!Exception(nothrowEx(), "It's a message");
catch(AssertError)
assert(0);
try
assertNotThrown!AssertError(nothrowEx());
catch(AssertError)
assert(0);
try
assertNotThrown!AssertError(nothrowEx(), "It's a message");
catch(AssertError)
assert(0);
{
bool thrown = false;
try
assertNotThrown!Exception(throwEx(new Exception("It's an Exception")));
catch(AssertError)
thrown = true;
assert(thrown);
}
{
bool thrown = false;
try
assertNotThrown!Exception(throwEx(new Exception("It's an Exception")), "It's a message");
catch(AssertError)
thrown = true;
assert(thrown);
}
{
bool thrown = false;
try
assertNotThrown!AssertError(throwEx(new AssertError("It's an AssertError", __FILE__, __LINE__)));
catch(AssertError)
thrown = true;
assert(thrown);
}
{
bool thrown = false;
try
assertNotThrown!AssertError(throwEx(new AssertError("It's an AssertError", __FILE__, __LINE__)), "It's a message");
catch(AssertError)
thrown = true;
assert(thrown);
}
//Verify Examples.
void timeFunc(int hour, int minute, int second)
{
enforce(hour >= 0 && hour <= 23);
enforce(minute >= 0 && minute <= 59);
enforce(second >= 0 && second <= 59);
//...
}
assertNotThrown!Exception(timeFunc(0, 0, 0));
assertNotThrown!Exception(timeFunc(12, 15, 30));
assertNotThrown(timeFunc(23, 59, 59)); //Exception is default.
void nameFunc(string name)
{
enforce(!name.empty);
enforce(name.length < 30);
//...
}
assertNotThrown(nameFunc("Walter Bright"));
assertNotThrown(nameFunc("Andrei Alexandrescu"));
void assertPlease()
{
assert(1 == 0);
}
assert(collectExceptionMsg(assertNotThrown!AssertError(assertPlease())) ==
"assertNotThrown failed: AssertError was thrown.");
assert(collectExceptionMsg(assertNotThrown!AssertError(assertPlease(), "error!")) ==
"assertNotThrown failed: AssertError was thrown: error!");
}
void assertPred(string func, string expected, L, R)
(L lhs, R rhs, lazy string msg = null, string file = __FILE__, size_t line = __LINE__)
if(func == "opCmp" &&
(expected == "<" ||
expected == "==" ||
expected == ">") &&
__traits(compiles, lhs.opCmp(rhs)) &&
isPrintable!L &&
isPrintable!R)
{
immutable result = lhs.opCmp(rhs);
static if(expected == "<")
{
if(result < 0)
return;
if(result == 0)
{
if(msg.empty)
throw new AssertError(format(`assertPred!("opCmp", "<") failed: [%s] == [%s].`, lhs, rhs), file, line);
else
throw new AssertError(format(`assertPred!("opCmp", "<") failed: [%s] == [%s]: %s`, lhs, rhs, msg), file, line);
}
else
{
if(msg.empty)
throw new AssertError(format(`assertPred!("opCmp", "<") failed: [%s] > [%s].`, lhs, rhs), file, line);
else
throw new AssertError(format(`assertPred!("opCmp", "<") failed: [%s] > [%s]: %s`, lhs, rhs, msg), file, line);
}
}
else static if(expected == "==")
{
if(result == 0)
return;
if(result < 0)
{
if(msg.empty)
throw new AssertError(format(`assertPred!("opCmp", "==") failed: [%s] < [%s].`, lhs, rhs), file, line);
else
throw new AssertError(format(`assertPred!("opCmp", "==") failed: [%s] < [%s]: %s`, lhs, rhs, msg), file, line);
}
else
{
if(msg.empty)
throw new AssertError(format(`assertPred!("opCmp", "==") failed: [%s] > [%s].`, lhs, rhs), file, line);
else
throw new AssertError(format(`assertPred!("opCmp", "==") failed: [%s] > [%s]: %s`, lhs, rhs, msg), file, line);
}
}
else static if(expected == ">")
{
if(result > 0)
return;
if(result < 0)
{
if(msg.empty)
throw new AssertError(format(`assertPred!("opCmp", ">") failed: [%s] < [%s].`, lhs, rhs), file, line);
else
throw new AssertError(format(`assertPred!("opCmp", ">") failed: [%s] < [%s]: %s`, lhs, rhs, msg), file, line);
}
else
{
if(msg.empty)
throw new AssertError(format(`assertPred!("opCmp", ">") failed: [%s] == [%s].`, lhs, rhs), file, line);
else
throw new AssertError(format(`assertPred!("opCmp", ">") failed: [%s] == [%s]: %s`, lhs, rhs, msg), file, line);
}
}
else
static assert(0);
}
void assertPred(string op, L, R, E)
(L lhs, R rhs, E expected, lazy string msg = null, string file = __FILE__, size_t line = __LINE__)
if((op == "+=" ||
op == "-=" ||
op == "*=" ||
op == "/=" ||
op == "%=" ||
op == "^^=" ||
op == "&=" ||
op == "|=" ||
op == "^=" ||
op == "<<=" ||
op == ">>=" ||
op == ">>>=" ||
op == "~=") &&
__traits(compiles, mixin("lhs " ~ op ~ " rhs")) &&
__traits(compiles, mixin("(lhs " ~ op ~ " rhs) == expected")) &&
isPrintable!L &&
isPrintable!R)
{
immutable origLHSStr = to!string(lhs);
const result = mixin("lhs " ~ op ~ " rhs");
if(lhs != expected)
{
if(msg.empty)
{
throw new AssertError(format(`assertPred!"%s" failed: After [%s] %s [%s], lhs was assigned to [%s] instead of [%s].`,
op,
origLHSStr,
op,
rhs,
lhs,
expected),
file,
line);
}
else
{
throw new AssertError(format(`assertPred!"%s" failed: After [%s] %s [%s], lhs was assigned to [%s] instead of [%s]: %s`,
op,
origLHSStr,
op,
rhs,
lhs,
expected,
msg),
file,
line);
}
}
if(result != expected)
{
if(msg.empty)
{
throw new AssertError(format(`assertPred!"%s" failed: Return value of [%s] %s [%s] was [%s] instead of [%s].`,
op,
origLHSStr,
op,
rhs,
result,
expected),
file,
line);
}
else
{
throw new AssertError(format(`assertPred!"%s" failed: Return value of [%s] %s [%s] was [%s] instead of [%s]: %s`,
op,
origLHSStr,
op,
rhs,
result,
expected,
msg),
file,
line);
}
}
}
unittest
{
assertNotThrown!AssertError(assertPred!"+="(7, 5, 12));
assertNotThrown!AssertError(assertPred!"-="(7, 5, 2));
assertNotThrown!AssertError(assertPred!"*="(7, 5, 35));
assertNotThrown!AssertError(assertPred!"/="(7, 5, 1));
assertNotThrown!AssertError(assertPred!"%="(7, 5, 2));
assertNotThrown!AssertError(assertPred!"^^="(7, 5, 16_807));
assertNotThrown!AssertError(assertPred!"&="(7, 5, 5));
assertNotThrown!AssertError(assertPred!"|="(7, 5, 7));
assertNotThrown!AssertError(assertPred!"^="(7, 5, 2));
assertNotThrown!AssertError(assertPred!"<<="(7, 1, 14));
assertNotThrown!AssertError(assertPred!">>="(7, 1, 3));
assertNotThrown!AssertError(assertPred!">>>="(-7, 1, 2_147_483_644));
assertNotThrown!AssertError(assertPred!"~="("hello ", "world", "hello world"));
assertThrown!AssertError(assertPred!"+="(7, 5, 0));
assertThrown!AssertError(assertPred!"-="(7, 5, 0));
assertThrown!AssertError(assertPred!"*="(7, 5, 0));
assertThrown!AssertError(assertPred!"/="(7, 5, 0));
assertThrown!AssertError(assertPred!"%="(7, 5, 0));
assertThrown!AssertError(assertPred!"^^="(7, 5, 0));
assertThrown!AssertError(assertPred!"&="(7, 5, 0));
assertThrown!AssertError(assertPred!"|="(7, 5, 0));
assertThrown!AssertError(assertPred!"^="(7, 5, 0));
assertThrown!AssertError(assertPred!"<<="(7, 1, 0));
assertThrown!AssertError(assertPred!">>="(7, 1, 0));
assertThrown!AssertError(assertPred!">>>="(-7, 1, 0));
assertThrown!AssertError(assertPred!"~="("hello ", "world", "goodbye world"));
assertPred!"=="(collectExceptionMsg(assertPred!"+="(7, 5, 11)),
`assertPred!"+=" failed: After [7] += [5], lhs was assigned to [12] instead of [11].`);
assertPred!"=="(collectExceptionMsg(assertPred!"+="(7, 5, 11, "It failed!")),
`assertPred!"+=" failed: After [7] += [5], lhs was assigned to [12] instead of [11]: It failed!`);
assertPred!"=="(collectExceptionMsg(assertPred!"^^="(7, 5, 42)),
`assertPred!"^^=" failed: After [7] ^^= [5], lhs was assigned to [16807] instead of [42].`);
assertPred!"=="(collectExceptionMsg(assertPred!"^^="(7, 5, 42, "It failed!")),
`assertPred!"^^=" failed: After [7] ^^= [5], lhs was assigned to [16807] instead of [42]: It failed!`);
assertPred!"=="(collectExceptionMsg(assertPred!"~="("hello ", "world", "goodbye world")),
`assertPred!"~=" failed: After [hello ] ~= [world], lhs was assigned to [hello world] instead of [goodbye world].`);
assertPred!"=="(collectExceptionMsg(assertPred!"~="("hello ", "world", "goodbye world", "It failed!")),
`assertPred!"~=" failed: After [hello ] ~= [world], lhs was assigned to [hello world] instead of [goodbye world]: It failed!`);
struct IntWrapper
{
int value;
this(int value)
{
this.value = value;
}
IntWrapper opOpAssign(string op)(IntWrapper rhs)
{
mixin("this.value " ~ op ~ "= rhs.value;");
return this;
}
string toString()
{
return to!string(value);
}
}
struct IntWrapper_BadAssign
{
int value;
this(int value)
{
this.value = value;
}
IntWrapper_BadAssign opOpAssign(string op)(IntWrapper_BadAssign rhs)
{
auto old = this.value;
mixin("this.value " ~ op ~ "= -rhs.value;");
return IntWrapper_BadAssign(mixin("old " ~ op ~ " rhs.value"));
}
string toString()
{
return to!string(value);
}
}
struct IntWrapper_BadReturn
{
int value;
this(int value)
{
this.value = value;
}
IntWrapper_BadReturn opOpAssign(string op)(IntWrapper_BadReturn rhs)
{
mixin("this.value " ~ op ~ "= rhs.value;");
return IntWrapper_BadReturn(rhs.value);
}
string toString()
{
return to!string(value);
}
}
assertNotThrown!AssertError(assertPred!"+="(IntWrapper(5), IntWrapper(2), IntWrapper(7)));
assertNotThrown!AssertError(assertPred!"*="(IntWrapper(5), IntWrapper(2), IntWrapper(10)));
assertThrown!AssertError(assertPred!"+="(IntWrapper_BadAssign(5), IntWrapper_BadAssign(2), IntWrapper_BadAssign(7)));
assertThrown!AssertError(assertPred!"+="(IntWrapper_BadReturn(5), IntWrapper_BadReturn(2), IntWrapper_BadReturn(7)));
assertThrown!AssertError(assertPred!"*="(IntWrapper_BadAssign(5), IntWrapper_BadAssign(2), IntWrapper_BadAssign(10)));
assertThrown!AssertError(assertPred!"*="(IntWrapper_BadReturn(5), IntWrapper_BadReturn(2), IntWrapper_BadReturn(10)));
assertPred!"=="(collectExceptionMsg(assertPred!"+="(IntWrapper_BadAssign(5), IntWrapper_BadAssign(2), IntWrapper_BadAssign(7))),
`assertPred!"+=" failed: After [5] += [2], lhs was assigned to [3] instead of [7].`);
assertPred!"=="(collectExceptionMsg(assertPred!"+="(IntWrapper_BadAssign(5), IntWrapper_BadAssign(2), IntWrapper_BadAssign(7), "It failed!")),
`assertPred!"+=" failed: After [5] += [2], lhs was assigned to [3] instead of [7]: It failed!`);
assertPred!"=="(collectExceptionMsg(assertPred!"+="(IntWrapper_BadReturn(5), IntWrapper_BadReturn(2), IntWrapper_BadReturn(7))),
`assertPred!"+=" failed: Return value of [5] += [2] was [2] instead of [7].`);
assertPred!"=="(collectExceptionMsg(assertPred!"+="(IntWrapper_BadReturn(5), IntWrapper_BadReturn(2), IntWrapper_BadReturn(7), "It failed!")),
`assertPred!"+=" failed: Return value of [5] += [2] was [2] instead of [7]: It failed!`);
assertPred!"=="(collectExceptionMsg(assertPred!"*="(IntWrapper_BadAssign(5), IntWrapper_BadAssign(2), IntWrapper_BadAssign(10))),
`assertPred!"*=" failed: After [5] *= [2], lhs was assigned to [-10] instead of [10].`);
assertPred!"=="(collectExceptionMsg(assertPred!"*="(IntWrapper_BadAssign(5), IntWrapper_BadAssign(2), IntWrapper_BadAssign(10), "It failed!")),
`assertPred!"*=" failed: After [5] *= [2], lhs was assigned to [-10] instead of [10]: It failed!`);
assertPred!"=="(collectExceptionMsg(assertPred!"*="(IntWrapper_BadReturn(5), IntWrapper_BadReturn(2), IntWrapper_BadReturn(10))),
`assertPred!"*=" failed: Return value of [5] *= [2] was [2] instead of [10].`);
assertPred!"=="(collectExceptionMsg(assertPred!"*="(IntWrapper_BadReturn(5), IntWrapper_BadReturn(2), IntWrapper_BadReturn(10), "It failed!")),
`assertPred!"*=" failed: Return value of [5] *= [2] was [2] instead of [10]: It failed!`);
}
string collectExceptionMsg(T)(lazy T funcCall)
{
try
{
funcCall();
return cast(string)null;
}
catch(Throwable t)
return t.msg;
}
unittest
{
//Verify Example.
void throwFunc() {throw new Exception("My Message.");}
assert(collectExceptionMsg(throwFunc()) == "My Message.");
void nothrowFunc() {}
assert(collectExceptionMsg(nothrowFunc()) is null);
}
template isPrintable(T...)
{
static if(T.length == 0)
enum isPrintable = true;
else static if(T.length == 1)
{
enum isPrintable = (!isArray!(T[0]) && __traits(compiles, to!string(T[0].init))) ||
(isArray!(T[0]) && __traits(compiles, to!string(T[0].init[0])));
}
else
{
enum isPrintable = isPrintable!(T[0]) && isPrintable!(T[1 .. $]);
}
}