mirror of
https://github.com/dlang/phobos.git
synced 2025-04-29 14:40:30 +03:00
Move several items from std/datetime/package.d to std/datetime/common.d.
This commit is contained in:
parent
e532c4f155
commit
f9da3c1c13
2 changed files with 575 additions and 552 deletions
|
@ -8,3 +8,578 @@
|
||||||
LREF2=<a href="#$1">$(D $2)</a>
|
LREF2=<a href="#$1">$(D $2)</a>
|
||||||
+/
|
+/
|
||||||
module std.datetime.common;
|
module std.datetime.common;
|
||||||
|
|
||||||
|
import core.time : TimeException;
|
||||||
|
import std.typecons : Flag;
|
||||||
|
|
||||||
|
|
||||||
|
/++
|
||||||
|
Exception type used by std.datetime. It's an alias to $(REF TimeException, core,time).
|
||||||
|
Either can be caught without concern about which
|
||||||
|
module it came from.
|
||||||
|
+/
|
||||||
|
alias DateTimeException = TimeException;
|
||||||
|
|
||||||
|
|
||||||
|
/++
|
||||||
|
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.
|
||||||
|
|
||||||
|
If set to $(D AllowDayOverflow.no), then day overflow is not allowed.
|
||||||
|
|
||||||
|
Otherwise, if set to $(D AllowDayOverflow.yes), then day overflow is
|
||||||
|
allowed.
|
||||||
|
+/
|
||||||
|
alias AllowDayOverflow = Flag!"allowDayOverflow";
|
||||||
|
|
||||||
|
|
||||||
|
/++
|
||||||
|
Array of the strings representing time units, starting with the smallest
|
||||||
|
unit and going to the largest. It does not include $(D "nsecs").
|
||||||
|
|
||||||
|
Includes $(D "hnsecs") (hecto-nanoseconds (100 ns)),
|
||||||
|
$(D "usecs") (microseconds), $(D "msecs") (milliseconds), $(D "seconds"),
|
||||||
|
$(D "minutes"), $(D "hours"), $(D "days"), $(D "weeks"), $(D "months"), and
|
||||||
|
$(D "years")
|
||||||
|
+/
|
||||||
|
immutable string[] timeStrings = ["hnsecs", "usecs", "msecs", "seconds", "minutes",
|
||||||
|
"hours", "days", "weeks", "months", "years"];
|
||||||
|
|
||||||
|
|
||||||
|
/++
|
||||||
|
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.
|
||||||
|
+/
|
||||||
|
bool valid(string units)(int value) @safe 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 <= 23;
|
||||||
|
else static if (units == "minutes")
|
||||||
|
return value >= 0 && value <= 59;
|
||||||
|
else static if (units == "seconds")
|
||||||
|
return value >= 0 && value <= 59;
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
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) @safe 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 $(LREF DateTimeException) will list if thrown.
|
||||||
|
line = The line number that the $(LREF DateTimeException) will list if
|
||||||
|
thrown.
|
||||||
|
|
||||||
|
Throws:
|
||||||
|
$(LREF DateTimeException) if $(D valid!units(value)) is false.
|
||||||
|
+/
|
||||||
|
void enforceValid(string units)(int value, string file = __FILE__, size_t line = __LINE__) @safe pure
|
||||||
|
if (units == "months" ||
|
||||||
|
units == "hours" ||
|
||||||
|
units == "minutes" ||
|
||||||
|
units == "seconds")
|
||||||
|
{
|
||||||
|
import std.format : format;
|
||||||
|
|
||||||
|
static if (units == "months")
|
||||||
|
{
|
||||||
|
if (!valid!units(value))
|
||||||
|
throw new DateTimeException(format("%s is not a valid month of the year.", value), file, line);
|
||||||
|
}
|
||||||
|
else static if (units == "hours")
|
||||||
|
{
|
||||||
|
if (!valid!units(value))
|
||||||
|
throw new DateTimeException(format("%s is not a valid hour of the day.", value), file, line);
|
||||||
|
}
|
||||||
|
else static if (units == "minutes")
|
||||||
|
{
|
||||||
|
if (!valid!units(value))
|
||||||
|
throw new DateTimeException(format("%s is not a valid minute of an hour.", value), file, line);
|
||||||
|
}
|
||||||
|
else static if (units == "seconds")
|
||||||
|
{
|
||||||
|
if (!valid!units(value))
|
||||||
|
throw new DateTimeException(format("%s is not a valid second of a minute.", value), 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 $(LREF DateTimeException) will list if thrown.
|
||||||
|
line = The line number that the $(LREF DateTimeException) will list if
|
||||||
|
thrown.
|
||||||
|
|
||||||
|
Throws:
|
||||||
|
$(LREF DateTimeException) if $(D valid!"days"(year, month, day)) is false.
|
||||||
|
+/
|
||||||
|
void enforceValid(string units)
|
||||||
|
(int year, Month month, int day, string file = __FILE__, size_t line = __LINE__) @safe pure
|
||||||
|
if (units == "days")
|
||||||
|
{
|
||||||
|
import std.format : format;
|
||||||
|
if (!valid!"days"(year, month, day))
|
||||||
|
throw new DateTimeException(format("%s is not a valid day in %s in %s", day, month, year), file, line);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/++
|
||||||
|
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.
|
||||||
|
+/
|
||||||
|
int daysToDayOfWeek(DayOfWeek currDoW, DayOfWeek dow) @safe pure nothrow
|
||||||
|
{
|
||||||
|
if (currDoW == dow)
|
||||||
|
return 0;
|
||||||
|
if (currDoW < dow)
|
||||||
|
return dow - currDoW;
|
||||||
|
return (DayOfWeek.sat - currDoW) + dow + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.sun) == 0);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.mon) == 1);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.tue) == 2);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.wed) == 3);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.thu) == 4);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.fri) == 5);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.sat) == 6);
|
||||||
|
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.sun) == 6);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.mon) == 0);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.tue) == 1);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.wed) == 2);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.thu) == 3);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.fri) == 4);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.sat) == 5);
|
||||||
|
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.sun) == 5);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.mon) == 6);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.tue) == 0);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.wed) == 1);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.thu) == 2);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.fri) == 3);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.sat) == 4);
|
||||||
|
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.sun) == 4);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.mon) == 5);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.tue) == 6);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.wed) == 0);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.thu) == 1);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.fri) == 2);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.sat) == 3);
|
||||||
|
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.sun) == 3);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.mon) == 4);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.tue) == 5);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.wed) == 6);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.thu) == 0);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.fri) == 1);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.sat) == 2);
|
||||||
|
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.sun) == 2);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.mon) == 3);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.tue) == 4);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.wed) == 5);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.thu) == 6);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.fri) == 0);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.sat) == 1);
|
||||||
|
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.sun) == 1);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.mon) == 2);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.tue) == 3);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.wed) == 4);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.thu) == 5);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.fri) == 6);
|
||||||
|
assert(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.sat) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/++
|
||||||
|
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.
|
||||||
|
+/
|
||||||
|
int monthsToMonth(int currMonth, int month) @safe pure
|
||||||
|
{
|
||||||
|
enforceValid!"months"(currMonth);
|
||||||
|
enforceValid!"months"(month);
|
||||||
|
|
||||||
|
if (currMonth == month)
|
||||||
|
return 0;
|
||||||
|
if (currMonth < month)
|
||||||
|
return month - currMonth;
|
||||||
|
return (Month.dec - currMonth) + month;
|
||||||
|
}
|
||||||
|
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
assert(monthsToMonth(Month.jan, Month.jan) == 0);
|
||||||
|
assert(monthsToMonth(Month.jan, Month.feb) == 1);
|
||||||
|
assert(monthsToMonth(Month.jan, Month.mar) == 2);
|
||||||
|
assert(monthsToMonth(Month.jan, Month.apr) == 3);
|
||||||
|
assert(monthsToMonth(Month.jan, Month.may) == 4);
|
||||||
|
assert(monthsToMonth(Month.jan, Month.jun) == 5);
|
||||||
|
assert(monthsToMonth(Month.jan, Month.jul) == 6);
|
||||||
|
assert(monthsToMonth(Month.jan, Month.aug) == 7);
|
||||||
|
assert(monthsToMonth(Month.jan, Month.sep) == 8);
|
||||||
|
assert(monthsToMonth(Month.jan, Month.oct) == 9);
|
||||||
|
assert(monthsToMonth(Month.jan, Month.nov) == 10);
|
||||||
|
assert(monthsToMonth(Month.jan, Month.dec) == 11);
|
||||||
|
|
||||||
|
assert(monthsToMonth(Month.may, Month.jan) == 8);
|
||||||
|
assert(monthsToMonth(Month.may, Month.feb) == 9);
|
||||||
|
assert(monthsToMonth(Month.may, Month.mar) == 10);
|
||||||
|
assert(monthsToMonth(Month.may, Month.apr) == 11);
|
||||||
|
assert(monthsToMonth(Month.may, Month.may) == 0);
|
||||||
|
assert(monthsToMonth(Month.may, Month.jun) == 1);
|
||||||
|
assert(monthsToMonth(Month.may, Month.jul) == 2);
|
||||||
|
assert(monthsToMonth(Month.may, Month.aug) == 3);
|
||||||
|
assert(monthsToMonth(Month.may, Month.sep) == 4);
|
||||||
|
assert(monthsToMonth(Month.may, Month.oct) == 5);
|
||||||
|
assert(monthsToMonth(Month.may, Month.nov) == 6);
|
||||||
|
assert(monthsToMonth(Month.may, Month.dec) == 7);
|
||||||
|
|
||||||
|
assert(monthsToMonth(Month.oct, Month.jan) == 3);
|
||||||
|
assert(monthsToMonth(Month.oct, Month.feb) == 4);
|
||||||
|
assert(monthsToMonth(Month.oct, Month.mar) == 5);
|
||||||
|
assert(monthsToMonth(Month.oct, Month.apr) == 6);
|
||||||
|
assert(monthsToMonth(Month.oct, Month.may) == 7);
|
||||||
|
assert(monthsToMonth(Month.oct, Month.jun) == 8);
|
||||||
|
assert(monthsToMonth(Month.oct, Month.jul) == 9);
|
||||||
|
assert(monthsToMonth(Month.oct, Month.aug) == 10);
|
||||||
|
assert(monthsToMonth(Month.oct, Month.sep) == 11);
|
||||||
|
assert(monthsToMonth(Month.oct, Month.oct) == 0);
|
||||||
|
assert(monthsToMonth(Month.oct, Month.nov) == 1);
|
||||||
|
assert(monthsToMonth(Month.oct, Month.dec) == 2);
|
||||||
|
|
||||||
|
assert(monthsToMonth(Month.dec, Month.jan) == 1);
|
||||||
|
assert(monthsToMonth(Month.dec, Month.feb) == 2);
|
||||||
|
assert(monthsToMonth(Month.dec, Month.mar) == 3);
|
||||||
|
assert(monthsToMonth(Month.dec, Month.apr) == 4);
|
||||||
|
assert(monthsToMonth(Month.dec, Month.may) == 5);
|
||||||
|
assert(monthsToMonth(Month.dec, Month.jun) == 6);
|
||||||
|
assert(monthsToMonth(Month.dec, Month.jul) == 7);
|
||||||
|
assert(monthsToMonth(Month.dec, Month.aug) == 8);
|
||||||
|
assert(monthsToMonth(Month.dec, Month.sep) == 9);
|
||||||
|
assert(monthsToMonth(Month.dec, Month.oct) == 10);
|
||||||
|
assert(monthsToMonth(Month.dec, Month.nov) == 11);
|
||||||
|
assert(monthsToMonth(Month.dec, Month.dec) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/++
|
||||||
|
Whether the given Gregorian Year is a leap year.
|
||||||
|
|
||||||
|
Params:
|
||||||
|
year = The year to to be tested.
|
||||||
|
+/
|
||||||
|
bool yearIsLeapYear(int year) @safe pure nothrow
|
||||||
|
{
|
||||||
|
if (year % 400 == 0)
|
||||||
|
return true;
|
||||||
|
if (year % 100 == 0)
|
||||||
|
return false;
|
||||||
|
return year % 4 == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import std.format : format;
|
||||||
|
foreach (year; [1, 2, 3, 5, 6, 7, 100, 200, 300, 500, 600, 700, 1998, 1999,
|
||||||
|
2001, 2002, 2003, 2005, 2006, 2007, 2009, 2010, 2011])
|
||||||
|
{
|
||||||
|
assert(!yearIsLeapYear(year), format("year: %s.", year));
|
||||||
|
assert(!yearIsLeapYear(-year), format("year: %s.", year));
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (year; [0, 4, 8, 400, 800, 1600, 1996, 2000, 2004, 2008, 2012])
|
||||||
|
{
|
||||||
|
assert(yearIsLeapYear(year), format("year: %s.", year));
|
||||||
|
assert(yearIsLeapYear(-year), format("year: %s.", year));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/++
|
||||||
|
Whether the given type defines all of the necessary functions for it to
|
||||||
|
function as a time point.
|
||||||
|
|
||||||
|
1. $(D T) must define a static property named $(D min) which is the smallest
|
||||||
|
value of $(D T) as $(Unqual!T).
|
||||||
|
|
||||||
|
2. $(D T) must define a static property named $(D max) which is the largest
|
||||||
|
value of $(D T) as $(Unqual!T).
|
||||||
|
|
||||||
|
3. $(D T) must define an $(D opBinary) for addition and subtraction that
|
||||||
|
accepts $(REF Duration, core,time) and returns $(D Unqual!T).
|
||||||
|
|
||||||
|
4. $(D T) must define an $(D opOpAssign) for addition and subtraction that
|
||||||
|
accepts $(REF Duration, core,time) and returns $(D ref Unqual!T).
|
||||||
|
|
||||||
|
5. $(D T) must define a $(D opBinary) for subtraction which accepts $(D T)
|
||||||
|
and returns returns $(REF Duration, core,time).
|
||||||
|
+/
|
||||||
|
template isTimePoint(T)
|
||||||
|
{
|
||||||
|
import core.time : Duration;
|
||||||
|
import std.traits : FunctionAttribute, functionAttributes, Unqual;
|
||||||
|
|
||||||
|
enum isTimePoint = hasMin &&
|
||||||
|
hasMax &&
|
||||||
|
hasOverloadedOpBinaryWithDuration &&
|
||||||
|
hasOverloadedOpAssignWithDuration &&
|
||||||
|
hasOverloadedOpBinaryWithSelf &&
|
||||||
|
!is(U == Duration);
|
||||||
|
|
||||||
|
private:
|
||||||
|
|
||||||
|
alias U = Unqual!T;
|
||||||
|
|
||||||
|
enum hasMin = __traits(hasMember, T, "min") &&
|
||||||
|
is(typeof(T.min) == U) &&
|
||||||
|
is(typeof({static assert(__traits(isStaticFunction, T.min));}));
|
||||||
|
|
||||||
|
enum hasMax = __traits(hasMember, T, "max") &&
|
||||||
|
is(typeof(T.max) == U) &&
|
||||||
|
is(typeof({static assert(__traits(isStaticFunction, T.max));}));
|
||||||
|
|
||||||
|
enum hasOverloadedOpBinaryWithDuration = is(typeof(T.init + Duration.init) == U) &&
|
||||||
|
is(typeof(T.init - Duration.init) == U);
|
||||||
|
|
||||||
|
enum hasOverloadedOpAssignWithDuration = is(typeof(U.init += Duration.init) == U) &&
|
||||||
|
is(typeof(U.init -= Duration.init) == U) &&
|
||||||
|
is(typeof(
|
||||||
|
{
|
||||||
|
// Until the overload with TickDuration is removed, this is ambiguous.
|
||||||
|
//alias add = U.opOpAssign!"+";
|
||||||
|
//alias sub = U.opOpAssign!"-";
|
||||||
|
U u;
|
||||||
|
auto ref add() { return u += Duration.init; }
|
||||||
|
auto ref sub() { return u -= Duration.init; }
|
||||||
|
alias FA = FunctionAttribute;
|
||||||
|
static assert((functionAttributes!add & FA.ref_) != 0);
|
||||||
|
static assert((functionAttributes!sub & FA.ref_) != 0);
|
||||||
|
}));
|
||||||
|
|
||||||
|
enum hasOverloadedOpBinaryWithSelf = is(typeof(T.init - T.init) == Duration);
|
||||||
|
}
|
||||||
|
|
||||||
|
///
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import core.time : Duration;
|
||||||
|
import std.datetime : Date, DateTime, Interval, SysTime, TimeOfDay; // temporary
|
||||||
|
/+
|
||||||
|
import std.datetime.date : Date;
|
||||||
|
import std.datetime.datetime : DateTime;
|
||||||
|
import std.datetime.interval : Interval;
|
||||||
|
import std.datetime.systime : SysTime;
|
||||||
|
import std.datetime.timeofday : TimeOfDay;
|
||||||
|
+/
|
||||||
|
|
||||||
|
static assert(isTimePoint!Date);
|
||||||
|
static assert(isTimePoint!DateTime);
|
||||||
|
static assert(isTimePoint!SysTime);
|
||||||
|
static assert(isTimePoint!TimeOfDay);
|
||||||
|
|
||||||
|
static assert(!isTimePoint!int);
|
||||||
|
static assert(!isTimePoint!Duration);
|
||||||
|
static assert(!isTimePoint!(Interval!SysTime));
|
||||||
|
}
|
||||||
|
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
import core.time;
|
||||||
|
import std.datetime : Date, DateTime, Interval, NegInfInterval, PosInfInterval, SysTime, TimeOfDay; // temporary
|
||||||
|
/+
|
||||||
|
import std.datetime.date;
|
||||||
|
import std.datetime.datetime;
|
||||||
|
import std.datetime.interval;
|
||||||
|
import std.datetime.systime;
|
||||||
|
import std.datetime.timeofday;
|
||||||
|
+/
|
||||||
|
import std.meta : AliasSeq;
|
||||||
|
|
||||||
|
foreach (TP; AliasSeq!(Date, DateTime, SysTime, TimeOfDay))
|
||||||
|
{
|
||||||
|
static assert(isTimePoint!(const TP), TP.stringof);
|
||||||
|
static assert(isTimePoint!(immutable TP), TP.stringof);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (T; AliasSeq!(float, string, Duration, Interval!Date, PosInfInterval!Date, NegInfInterval!Date))
|
||||||
|
static assert(!isTimePoint!T, T.stringof);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
package:
|
||||||
|
|
||||||
|
/+
|
||||||
|
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.
|
||||||
|
+/
|
||||||
|
ubyte maxDay(int year, int month) @safe 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.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@safe unittest
|
||||||
|
{
|
||||||
|
// Test A.D.
|
||||||
|
assert(maxDay(1999, 1) == 31);
|
||||||
|
assert(maxDay(1999, 2) == 28);
|
||||||
|
assert(maxDay(1999, 3) == 31);
|
||||||
|
assert(maxDay(1999, 4) == 30);
|
||||||
|
assert(maxDay(1999, 5) == 31);
|
||||||
|
assert(maxDay(1999, 6) == 30);
|
||||||
|
assert(maxDay(1999, 7) == 31);
|
||||||
|
assert(maxDay(1999, 8) == 31);
|
||||||
|
assert(maxDay(1999, 9) == 30);
|
||||||
|
assert(maxDay(1999, 10) == 31);
|
||||||
|
assert(maxDay(1999, 11) == 30);
|
||||||
|
assert(maxDay(1999, 12) == 31);
|
||||||
|
|
||||||
|
assert(maxDay(2000, 1) == 31);
|
||||||
|
assert(maxDay(2000, 2) == 29);
|
||||||
|
assert(maxDay(2000, 3) == 31);
|
||||||
|
assert(maxDay(2000, 4) == 30);
|
||||||
|
assert(maxDay(2000, 5) == 31);
|
||||||
|
assert(maxDay(2000, 6) == 30);
|
||||||
|
assert(maxDay(2000, 7) == 31);
|
||||||
|
assert(maxDay(2000, 8) == 31);
|
||||||
|
assert(maxDay(2000, 9) == 30);
|
||||||
|
assert(maxDay(2000, 10) == 31);
|
||||||
|
assert(maxDay(2000, 11) == 30);
|
||||||
|
assert(maxDay(2000, 12) == 31);
|
||||||
|
|
||||||
|
// Test B.C.
|
||||||
|
assert(maxDay(-1999, 1) == 31);
|
||||||
|
assert(maxDay(-1999, 2) == 28);
|
||||||
|
assert(maxDay(-1999, 3) == 31);
|
||||||
|
assert(maxDay(-1999, 4) == 30);
|
||||||
|
assert(maxDay(-1999, 5) == 31);
|
||||||
|
assert(maxDay(-1999, 6) == 30);
|
||||||
|
assert(maxDay(-1999, 7) == 31);
|
||||||
|
assert(maxDay(-1999, 8) == 31);
|
||||||
|
assert(maxDay(-1999, 9) == 30);
|
||||||
|
assert(maxDay(-1999, 10) == 31);
|
||||||
|
assert(maxDay(-1999, 11) == 30);
|
||||||
|
assert(maxDay(-1999, 12) == 31);
|
||||||
|
|
||||||
|
assert(maxDay(-2000, 1) == 31);
|
||||||
|
assert(maxDay(-2000, 2) == 29);
|
||||||
|
assert(maxDay(-2000, 3) == 31);
|
||||||
|
assert(maxDay(-2000, 4) == 30);
|
||||||
|
assert(maxDay(-2000, 5) == 31);
|
||||||
|
assert(maxDay(-2000, 6) == 30);
|
||||||
|
assert(maxDay(-2000, 7) == 31);
|
||||||
|
assert(maxDay(-2000, 8) == 31);
|
||||||
|
assert(maxDay(-2000, 9) == 30);
|
||||||
|
assert(maxDay(-2000, 10) == 31);
|
||||||
|
assert(maxDay(-2000, 11) == 30);
|
||||||
|
assert(maxDay(-2000, 12) == 31);
|
||||||
|
}
|
||||||
|
|
|
@ -172,54 +172,6 @@ else version(Posix)
|
||||||
// Section with public enums and constants.
|
// 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.
|
|
||||||
|
|
||||||
If set to $(D AllowDayOverflow.no), then day overflow is not allowed.
|
|
||||||
|
|
||||||
Otherwise, if set to $(D AllowDayOverflow.yes), then day overflow is
|
|
||||||
allowed.
|
|
||||||
+/
|
|
||||||
alias AllowDayOverflow = Flag!"allowDayOverflow";
|
|
||||||
|
|
||||||
/++
|
/++
|
||||||
Indicates a direction in time. One example of its use is $(LREF2 .Interval, Interval)'s
|
Indicates a direction in time. One example of its use is $(LREF2 .Interval, Interval)'s
|
||||||
$(LREF expand, expand) function which uses it to indicate whether the interval should
|
$(LREF expand, expand) function which uses it to indicate whether the interval should
|
||||||
|
@ -282,30 +234,11 @@ alias PopFirst = Flag!"popFirst";
|
||||||
+/
|
+/
|
||||||
alias AutoStart = Flag!"autoStart";
|
alias AutoStart = Flag!"autoStart";
|
||||||
|
|
||||||
/++
|
|
||||||
Array of the strings representing time units, starting with the smallest
|
|
||||||
unit and going to the largest. It does not include $(D "nsecs").
|
|
||||||
|
|
||||||
Includes $(D "hnsecs") (hecto-nanoseconds (100 ns)),
|
|
||||||
$(D "usecs") (microseconds), $(D "msecs") (milliseconds), $(D "seconds"),
|
|
||||||
$(D "minutes"), $(D "hours"), $(D "days"), $(D "weeks"), $(D "months"), and
|
|
||||||
$(D "years")
|
|
||||||
+/
|
|
||||||
immutable string[] timeStrings = ["hnsecs", "usecs", "msecs", "seconds", "minutes",
|
|
||||||
"hours", "days", "weeks", "months", "years"];
|
|
||||||
|
|
||||||
|
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
// Section with other types.
|
// Section with other types.
|
||||||
//==============================================================================
|
//==============================================================================
|
||||||
|
|
||||||
/++
|
|
||||||
Exception type used by std.datetime. It's an alias to $(REF TimeException, core,time).
|
|
||||||
Either can be caught without concern about which
|
|
||||||
module it came from.
|
|
||||||
+/
|
|
||||||
alias DateTimeException = TimeException;
|
|
||||||
|
|
||||||
/++
|
/++
|
||||||
Effectively a namespace to make it clear that the methods it contains are
|
Effectively a namespace to make it clear that the methods it contains are
|
||||||
getting the time from the system clock. It cannot be instantiated.
|
getting the time from the system clock. It cannot be instantiated.
|
||||||
|
@ -32121,131 +32054,6 @@ ComparingBenchmarkResult comparingBenchmark(alias baseFunc,
|
||||||
// Section with public helper functions and templates.
|
// 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.
|
|
||||||
|
|
||||||
1. $(D T) must define a static property named $(D min) which is the smallest
|
|
||||||
value of $(D T) as $(Unqual!T).
|
|
||||||
|
|
||||||
2. $(D T) must define a static property named $(D max) which is the largest
|
|
||||||
value of $(D T) as $(Unqual!T).
|
|
||||||
|
|
||||||
3. $(D T) must define an $(D opBinary) for addition and subtraction that
|
|
||||||
accepts $(REF Duration, core,time) and returns $(D Unqual!T).
|
|
||||||
|
|
||||||
4. $(D T) must define an $(D opOpAssign) for addition and subtraction that
|
|
||||||
accepts $(REF Duration, core,time) and returns $(D ref Unqual!T).
|
|
||||||
|
|
||||||
5. $(D T) must define a $(D opBinary) for subtraction which accepts $(D T)
|
|
||||||
and returns returns $(REF Duration, core,time).
|
|
||||||
+/
|
|
||||||
template isTimePoint(T)
|
|
||||||
{
|
|
||||||
import std.traits : FunctionAttribute, functionAttributes;
|
|
||||||
enum isTimePoint = hasMin &&
|
|
||||||
hasMax &&
|
|
||||||
hasOverloadedOpBinaryWithDuration &&
|
|
||||||
hasOverloadedOpAssignWithDuration &&
|
|
||||||
hasOverloadedOpBinaryWithSelf &&
|
|
||||||
!is(U == Duration);
|
|
||||||
|
|
||||||
private:
|
|
||||||
|
|
||||||
alias U = Unqual!T;
|
|
||||||
|
|
||||||
enum hasMin = __traits(hasMember, T, "min") &&
|
|
||||||
is(typeof(T.min) == U) &&
|
|
||||||
is(typeof({static assert(__traits(isStaticFunction, T.min));}));
|
|
||||||
|
|
||||||
enum hasMax = __traits(hasMember, T, "max") &&
|
|
||||||
is(typeof(T.max) == U) &&
|
|
||||||
is(typeof({static assert(__traits(isStaticFunction, T.max));}));
|
|
||||||
|
|
||||||
enum hasOverloadedOpBinaryWithDuration = is(typeof(T.init + Duration.init) == U) &&
|
|
||||||
is(typeof(T.init - Duration.init) == U);
|
|
||||||
|
|
||||||
enum hasOverloadedOpAssignWithDuration = is(typeof(U.init += Duration.init) == U) &&
|
|
||||||
is(typeof(U.init -= Duration.init) == U) &&
|
|
||||||
is(typeof(
|
|
||||||
{
|
|
||||||
// Until the overload with TickDuration is removed, this is ambiguous.
|
|
||||||
//alias add = U.opOpAssign!"+";
|
|
||||||
//alias sub = U.opOpAssign!"-";
|
|
||||||
U u;
|
|
||||||
auto ref add() { return u += Duration.init; }
|
|
||||||
auto ref sub() { return u -= Duration.init; }
|
|
||||||
alias FA = FunctionAttribute;
|
|
||||||
static assert((functionAttributes!add & FA.ref_) != 0);
|
|
||||||
static assert((functionAttributes!sub & FA.ref_) != 0);
|
|
||||||
}));
|
|
||||||
|
|
||||||
enum hasOverloadedOpBinaryWithSelf = is(typeof(T.init - T.init) == Duration);
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
@safe unittest
|
|
||||||
{
|
|
||||||
static assert(isTimePoint!Date);
|
|
||||||
static assert(isTimePoint!DateTime);
|
|
||||||
static assert(isTimePoint!SysTime);
|
|
||||||
static assert(isTimePoint!TimeOfDay);
|
|
||||||
|
|
||||||
static assert(!isTimePoint!int);
|
|
||||||
static assert(!isTimePoint!Duration);
|
|
||||||
static assert(!isTimePoint!(Interval!SysTime));
|
|
||||||
}
|
|
||||||
|
|
||||||
@safe unittest
|
|
||||||
{
|
|
||||||
import std.meta : AliasSeq;
|
|
||||||
|
|
||||||
foreach (TP; AliasSeq!(Date, DateTime, SysTime, TimeOfDay))
|
|
||||||
{
|
|
||||||
static assert(isTimePoint!(const TP), TP.stringof);
|
|
||||||
static assert(isTimePoint!(immutable TP), TP.stringof);
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (T; AliasSeq!(float, string, Duration, Interval!Date, PosInfInterval!Date, NegInfInterval!Date))
|
|
||||||
static assert(!isTimePoint!T, T.stringof);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/++
|
|
||||||
Whether the given Gregorian Year is a leap year.
|
|
||||||
|
|
||||||
Params:
|
|
||||||
year = The year to to be tested.
|
|
||||||
+/
|
|
||||||
static bool yearIsLeapYear(int year) @safe pure nothrow
|
|
||||||
{
|
|
||||||
if (year % 400 == 0)
|
|
||||||
return true;
|
|
||||||
|
|
||||||
if (year % 100 == 0)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
return year % 4 == 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
@safe unittest
|
|
||||||
{
|
|
||||||
import std.format : format;
|
|
||||||
foreach (year; [1, 2, 3, 5, 6, 7, 100, 200, 300, 500, 600, 700, 1998, 1999,
|
|
||||||
2001, 2002, 2003, 2005, 2006, 2007, 2009, 2010, 2011])
|
|
||||||
{
|
|
||||||
assert(!yearIsLeapYear(year), format("year: %s.", year));
|
|
||||||
assert(!yearIsLeapYear(-year), format("year: %s.", year));
|
|
||||||
}
|
|
||||||
|
|
||||||
foreach (year; [0, 4, 8, 400, 800, 1600, 1996, 2000, 2004, 2008, 2012])
|
|
||||||
{
|
|
||||||
assert(yearIsLeapYear(year), format("year: %s.", year));
|
|
||||||
assert(yearIsLeapYear(-year), format("year: %s.", year));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/++
|
/++
|
||||||
Converts from unix time (which uses midnight, January 1st, 1970 UTC as its
|
Converts from unix time (which uses midnight, January 1st, 1970 UTC as its
|
||||||
epoch and seconds as its units) to "std time" (which uses midnight,
|
epoch and seconds as its units) to "std time" (which uses midnight,
|
||||||
|
@ -33710,280 +33518,6 @@ private int cmpTimeUnitsCTFE(string lhs, string rhs) @safe pure nothrow
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/++
|
|
||||||
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.
|
|
||||||
+/
|
|
||||||
bool valid(string units)(int value) @safe 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;
|
|
||||||
}
|
|
||||||
|
|
||||||
///
|
|
||||||
@safe unittest
|
|
||||||
{
|
|
||||||
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) @safe 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 $(LREF DateTimeException) will list if thrown.
|
|
||||||
line = The line number that the $(LREF DateTimeException) will list if
|
|
||||||
thrown.
|
|
||||||
|
|
||||||
Throws:
|
|
||||||
$(LREF DateTimeException) if $(D valid!units(value)) is false.
|
|
||||||
+/
|
|
||||||
void enforceValid(string units)(int value, string file = __FILE__, size_t line = __LINE__) @safe pure
|
|
||||||
if (units == "months" ||
|
|
||||||
units == "hours" ||
|
|
||||||
units == "minutes" ||
|
|
||||||
units == "seconds")
|
|
||||||
{
|
|
||||||
import std.format : format;
|
|
||||||
|
|
||||||
static if (units == "months")
|
|
||||||
{
|
|
||||||
if (!valid!units(value))
|
|
||||||
throw new DateTimeException(format("%s is not a valid month of the year.", value), file, line);
|
|
||||||
}
|
|
||||||
else static if (units == "hours")
|
|
||||||
{
|
|
||||||
if (!valid!units(value))
|
|
||||||
throw new DateTimeException(format("%s is not a valid hour of the day.", value), file, line);
|
|
||||||
}
|
|
||||||
else static if (units == "minutes")
|
|
||||||
{
|
|
||||||
if (!valid!units(value))
|
|
||||||
throw new DateTimeException(format("%s is not a valid minute of an hour.", value), file, line);
|
|
||||||
}
|
|
||||||
else static if (units == "seconds")
|
|
||||||
{
|
|
||||||
if (!valid!units(value))
|
|
||||||
throw new DateTimeException(format("%s is not a valid second of a minute.", value), 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 $(LREF DateTimeException) will list if thrown.
|
|
||||||
line = The line number that the $(LREF DateTimeException) will list if
|
|
||||||
thrown.
|
|
||||||
|
|
||||||
Throws:
|
|
||||||
$(LREF DateTimeException) if $(D valid!"days"(year, month, day)) is false.
|
|
||||||
+/
|
|
||||||
void enforceValid(string units)
|
|
||||||
(int year, Month month, int day, string file = __FILE__, size_t line = __LINE__) @safe pure
|
|
||||||
if (units == "days")
|
|
||||||
{
|
|
||||||
import std.format : format;
|
|
||||||
if (!valid!"days"(year, month, day))
|
|
||||||
throw new DateTimeException(format("%s is not a valid day in %s in %s", day, month, 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) @safe pure
|
|
||||||
{
|
|
||||||
enforceValid!"months"(currMonth);
|
|
||||||
enforceValid!"months"(month);
|
|
||||||
|
|
||||||
if (currMonth == month)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (currMonth < month)
|
|
||||||
return month - currMonth;
|
|
||||||
|
|
||||||
return (Month.dec - currMonth) + month;
|
|
||||||
}
|
|
||||||
|
|
||||||
@safe unittest
|
|
||||||
{
|
|
||||||
assert(monthsToMonth(Month.jan, Month.jan) == 0);
|
|
||||||
assert(monthsToMonth(Month.jan, Month.feb) == 1);
|
|
||||||
assert(monthsToMonth(Month.jan, Month.mar) == 2);
|
|
||||||
assert(monthsToMonth(Month.jan, Month.apr) == 3);
|
|
||||||
assert(monthsToMonth(Month.jan, Month.may) == 4);
|
|
||||||
assert(monthsToMonth(Month.jan, Month.jun) == 5);
|
|
||||||
assert(monthsToMonth(Month.jan, Month.jul) == 6);
|
|
||||||
assert(monthsToMonth(Month.jan, Month.aug) == 7);
|
|
||||||
assert(monthsToMonth(Month.jan, Month.sep) == 8);
|
|
||||||
assert(monthsToMonth(Month.jan, Month.oct) == 9);
|
|
||||||
assert(monthsToMonth(Month.jan, Month.nov) == 10);
|
|
||||||
assert(monthsToMonth(Month.jan, Month.dec) == 11);
|
|
||||||
|
|
||||||
assert(monthsToMonth(Month.may, Month.jan) == 8);
|
|
||||||
assert(monthsToMonth(Month.may, Month.feb) == 9);
|
|
||||||
assert(monthsToMonth(Month.may, Month.mar) == 10);
|
|
||||||
assert(monthsToMonth(Month.may, Month.apr) == 11);
|
|
||||||
assert(monthsToMonth(Month.may, Month.may) == 0);
|
|
||||||
assert(monthsToMonth(Month.may, Month.jun) == 1);
|
|
||||||
assert(monthsToMonth(Month.may, Month.jul) == 2);
|
|
||||||
assert(monthsToMonth(Month.may, Month.aug) == 3);
|
|
||||||
assert(monthsToMonth(Month.may, Month.sep) == 4);
|
|
||||||
assert(monthsToMonth(Month.may, Month.oct) == 5);
|
|
||||||
assert(monthsToMonth(Month.may, Month.nov) == 6);
|
|
||||||
assert(monthsToMonth(Month.may, Month.dec) == 7);
|
|
||||||
|
|
||||||
assert(monthsToMonth(Month.oct, Month.jan) == 3);
|
|
||||||
assert(monthsToMonth(Month.oct, Month.feb) == 4);
|
|
||||||
assert(monthsToMonth(Month.oct, Month.mar) == 5);
|
|
||||||
assert(monthsToMonth(Month.oct, Month.apr) == 6);
|
|
||||||
assert(monthsToMonth(Month.oct, Month.may) == 7);
|
|
||||||
assert(monthsToMonth(Month.oct, Month.jun) == 8);
|
|
||||||
assert(monthsToMonth(Month.oct, Month.jul) == 9);
|
|
||||||
assert(monthsToMonth(Month.oct, Month.aug) == 10);
|
|
||||||
assert(monthsToMonth(Month.oct, Month.sep) == 11);
|
|
||||||
assert(monthsToMonth(Month.oct, Month.oct) == 0);
|
|
||||||
assert(monthsToMonth(Month.oct, Month.nov) == 1);
|
|
||||||
assert(monthsToMonth(Month.oct, Month.dec) == 2);
|
|
||||||
|
|
||||||
assert(monthsToMonth(Month.dec, Month.jan) == 1);
|
|
||||||
assert(monthsToMonth(Month.dec, Month.feb) == 2);
|
|
||||||
assert(monthsToMonth(Month.dec, Month.mar) == 3);
|
|
||||||
assert(monthsToMonth(Month.dec, Month.apr) == 4);
|
|
||||||
assert(monthsToMonth(Month.dec, Month.may) == 5);
|
|
||||||
assert(monthsToMonth(Month.dec, Month.jun) == 6);
|
|
||||||
assert(monthsToMonth(Month.dec, Month.jul) == 7);
|
|
||||||
assert(monthsToMonth(Month.dec, Month.aug) == 8);
|
|
||||||
assert(monthsToMonth(Month.dec, Month.sep) == 9);
|
|
||||||
assert(monthsToMonth(Month.dec, Month.oct) == 10);
|
|
||||||
assert(monthsToMonth(Month.dec, Month.nov) == 11);
|
|
||||||
assert(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) @safe pure nothrow
|
|
||||||
{
|
|
||||||
if (currDoW == dow)
|
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (currDoW < dow)
|
|
||||||
return dow - currDoW;
|
|
||||||
|
|
||||||
return (DayOfWeek.sat - currDoW) + dow + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
@safe unittest
|
|
||||||
{
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.sun) == 0);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.mon) == 1);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.tue) == 2);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.wed) == 3);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.thu) == 4);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.fri) == 5);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.sun, DayOfWeek.sat) == 6);
|
|
||||||
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.sun) == 6);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.mon) == 0);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.tue) == 1);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.wed) == 2);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.thu) == 3);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.fri) == 4);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.mon, DayOfWeek.sat) == 5);
|
|
||||||
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.sun) == 5);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.mon) == 6);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.tue) == 0);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.wed) == 1);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.thu) == 2);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.fri) == 3);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.tue, DayOfWeek.sat) == 4);
|
|
||||||
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.sun) == 4);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.mon) == 5);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.tue) == 6);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.wed) == 0);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.thu) == 1);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.fri) == 2);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.wed, DayOfWeek.sat) == 3);
|
|
||||||
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.sun) == 3);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.mon) == 4);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.tue) == 5);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.wed) == 6);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.thu) == 0);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.fri) == 1);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.thu, DayOfWeek.sat) == 2);
|
|
||||||
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.sun) == 2);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.mon) == 3);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.tue) == 4);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.wed) == 5);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.thu) == 6);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.fri) == 0);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.fri, DayOfWeek.sat) == 1);
|
|
||||||
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.sun) == 1);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.mon) == 2);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.tue) == 3);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.wed) == 4);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.thu) == 5);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.fri) == 6);
|
|
||||||
assert(daysToDayOfWeek(DayOfWeek.sat, DayOfWeek.sat) == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/++
|
/++
|
||||||
Function for starting to a stop watch time when the function is called
|
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.
|
and stopping it when its return value goes out of scope and is destroyed.
|
||||||
|
@ -34293,92 +33827,6 @@ if (validTimeUnits(units) &&
|
||||||
assert(hnsecs == 2595000000007L);
|
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) @safe 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.");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@safe unittest
|
|
||||||
{
|
|
||||||
//Test A.D.
|
|
||||||
assert(maxDay(1999, 1) == 31);
|
|
||||||
assert(maxDay(1999, 2) == 28);
|
|
||||||
assert(maxDay(1999, 3) == 31);
|
|
||||||
assert(maxDay(1999, 4) == 30);
|
|
||||||
assert(maxDay(1999, 5) == 31);
|
|
||||||
assert(maxDay(1999, 6) == 30);
|
|
||||||
assert(maxDay(1999, 7) == 31);
|
|
||||||
assert(maxDay(1999, 8) == 31);
|
|
||||||
assert(maxDay(1999, 9) == 30);
|
|
||||||
assert(maxDay(1999, 10) == 31);
|
|
||||||
assert(maxDay(1999, 11) == 30);
|
|
||||||
assert(maxDay(1999, 12) == 31);
|
|
||||||
|
|
||||||
assert(maxDay(2000, 1) == 31);
|
|
||||||
assert(maxDay(2000, 2) == 29);
|
|
||||||
assert(maxDay(2000, 3) == 31);
|
|
||||||
assert(maxDay(2000, 4) == 30);
|
|
||||||
assert(maxDay(2000, 5) == 31);
|
|
||||||
assert(maxDay(2000, 6) == 30);
|
|
||||||
assert(maxDay(2000, 7) == 31);
|
|
||||||
assert(maxDay(2000, 8) == 31);
|
|
||||||
assert(maxDay(2000, 9) == 30);
|
|
||||||
assert(maxDay(2000, 10) == 31);
|
|
||||||
assert(maxDay(2000, 11) == 30);
|
|
||||||
assert(maxDay(2000, 12) == 31);
|
|
||||||
|
|
||||||
//Test B.C.
|
|
||||||
assert(maxDay(-1999, 1) == 31);
|
|
||||||
assert(maxDay(-1999, 2) == 28);
|
|
||||||
assert(maxDay(-1999, 3) == 31);
|
|
||||||
assert(maxDay(-1999, 4) == 30);
|
|
||||||
assert(maxDay(-1999, 5) == 31);
|
|
||||||
assert(maxDay(-1999, 6) == 30);
|
|
||||||
assert(maxDay(-1999, 7) == 31);
|
|
||||||
assert(maxDay(-1999, 8) == 31);
|
|
||||||
assert(maxDay(-1999, 9) == 30);
|
|
||||||
assert(maxDay(-1999, 10) == 31);
|
|
||||||
assert(maxDay(-1999, 11) == 30);
|
|
||||||
assert(maxDay(-1999, 12) == 31);
|
|
||||||
|
|
||||||
assert(maxDay(-2000, 1) == 31);
|
|
||||||
assert(maxDay(-2000, 2) == 29);
|
|
||||||
assert(maxDay(-2000, 3) == 31);
|
|
||||||
assert(maxDay(-2000, 4) == 30);
|
|
||||||
assert(maxDay(-2000, 5) == 31);
|
|
||||||
assert(maxDay(-2000, 6) == 30);
|
|
||||||
assert(maxDay(-2000, 7) == 31);
|
|
||||||
assert(maxDay(-2000, 8) == 31);
|
|
||||||
assert(maxDay(-2000, 9) == 30);
|
|
||||||
assert(maxDay(-2000, 10) == 31);
|
|
||||||
assert(maxDay(-2000, 11) == 30);
|
|
||||||
assert(maxDay(-2000, 12) == 31);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/+
|
/+
|
||||||
Returns the day of the week for the given day of the Gregorian Calendar.
|
Returns the day of the week for the given day of the Gregorian Calendar.
|
||||||
|
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue