mirror of
https://github.com/dlang/phobos.git
synced 2025-04-28 06:00:35 +03:00
419 lines
9.8 KiB
D
419 lines
9.8 KiB
D
// Written in the D programming language.
|
|
|
|
/**
|
|
$(RED Scheduled for deprecation. Please use std.datetime instead.)
|
|
|
|
Macros:
|
|
WIKI = Phobos/StdGregorian
|
|
|
|
Copyright: Copyright Andrei Alexandrescu 2008 - 2009.
|
|
License: <a href="http://www.boost.org/LICENSE_1_0.txt">Boost License 1.0</a>.
|
|
Authors: $(WEB erdani.org, Andrei Alexandrescu)
|
|
Source: $(PHOBOSSRC std/_gregorian.d)
|
|
*/
|
|
/*
|
|
Copyright Andrei Alexandrescu 2010-.
|
|
Distributed under the Boost Software License, Version 1.0.
|
|
(See accompanying file LICENSE_1_0.txt or copy at
|
|
http://www.boost.org/LICENSE_1_0.txt)
|
|
*/
|
|
module std.gregorian;
|
|
|
|
pragma(msg, "std.gregorian has been scheduled for deprecation. "
|
|
"Please use std.datetime instead.");
|
|
|
|
version(posix) import core.sys.posix.time;
|
|
import std.typecons;
|
|
import std.conv;
|
|
version(unittest) import std.stdio;
|
|
|
|
version(none) unittest
|
|
{
|
|
auto d = Date(2010, May, 1);
|
|
auto d1 = d;
|
|
assert(d.year == 2010);
|
|
assert(d.month == May);
|
|
assert(d.day == 1);
|
|
assert(d.dayOfWeek == 6);
|
|
assert(d.dayOfYear == 121);
|
|
assert(Date(2010, Jan, 5).dayOfYear == 5);
|
|
}
|
|
|
|
version(none) unittest
|
|
{
|
|
auto d1 = Date(negInfin);
|
|
auto d2 = Date(posInfin);
|
|
auto d3 = Date(notADateTime);
|
|
auto d4 = Date(maxDateTime);
|
|
auto d5 = Date(minDateTime);
|
|
}
|
|
|
|
version(none) unittest
|
|
{
|
|
auto d1 = fromString("2002-1-25");
|
|
auto d2 = fromUndelimitedString("20020125");
|
|
}
|
|
|
|
version(none) unittest
|
|
{
|
|
auto d1 = dayClockLocalDay();
|
|
auto d2 = dayClockUniversalDay();
|
|
}
|
|
|
|
alias ushort GregYear;
|
|
alias ushort GregMonth;
|
|
alias ushort GregDay;
|
|
alias uint GregDayOfWeek;
|
|
alias uint GregDayOfYear;
|
|
|
|
enum { Jan = 1, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec }
|
|
|
|
// Special constants
|
|
struct Special { ulong value; }
|
|
static immutable
|
|
notADateTime = Special(0),
|
|
negInfin = Special(1),
|
|
posInfin = Special(2),
|
|
minDateTime = Special(3),
|
|
maxDateTime = Special(4),
|
|
notSpecial = Special(5);
|
|
|
|
struct Date
|
|
{
|
|
this(uint year, uint month, uint day)
|
|
{
|
|
immutable
|
|
a = cast(ushort)((14-month)/12),
|
|
y = cast(ushort)(year + 4800 - a),
|
|
m = cast(ushort)(month + 12*a - 3);
|
|
days_ = day + ((153*m + 2)/5) + 365*y + (y/4)
|
|
- (y/100) + (y/400) - 32045;
|
|
}
|
|
|
|
this(Special s)
|
|
{
|
|
}
|
|
|
|
// Accessors
|
|
@property GregYear year() const
|
|
{
|
|
immutable
|
|
a = days_ + 32044,
|
|
b = (4*a + 3)/146097,
|
|
c = a-((146097*b)/4),
|
|
d = (4*c + 3)/1461,
|
|
e = c - (1461*d)/4,
|
|
m = (5*e + 2)/153;
|
|
//auto day = cast(ushort) (e - ((153*m + 2)/5) + 1);
|
|
//auto month = cast(ushort) (m + 3 - 12 * (m/10));
|
|
immutable year = cast(ushort) (100*b + d - 4800 + (m/10));
|
|
|
|
return year;
|
|
}
|
|
|
|
@property GregMonth month() const
|
|
{
|
|
immutable
|
|
a = days_ + 32044,
|
|
b = (4*a + 3)/146097,
|
|
c = a-((146097*b)/4),
|
|
d = (4*c + 3)/1461,
|
|
e = c - (1461*d)/4,
|
|
m = (5*e + 2)/153;
|
|
//auto day = cast(ushort) (e - ((153*m + 2)/5) + 1);
|
|
immutable month = cast(ushort) (m + 3 - 12 * (m/10));
|
|
//auto year = cast(ushort) (100*b + d - 4800 + (m/10));
|
|
|
|
return month;
|
|
}
|
|
|
|
@property GregDay day() const
|
|
{
|
|
immutable
|
|
a = days_ + 32044,
|
|
b = (4*a + 3)/146097,
|
|
c = a-((146097*b)/4),
|
|
d = (4*c + 3)/1461,
|
|
e = c - (1461*d)/4,
|
|
m = (5*e + 2)/153,
|
|
day = cast(ushort) (e - ((153*m + 2)/5) + 1);
|
|
//auto month = cast(ushort) (m + 3 - 12 * (m/10));
|
|
//auto year = cast(ushort) (100*b + d - 4800 + (m/10));
|
|
|
|
return day;
|
|
}
|
|
|
|
@property Tuple!(GregYear, GregMonth, GregDay)
|
|
yearMonthDay() const
|
|
{
|
|
immutable
|
|
a = days_ + 32044,
|
|
b = (4*a + 3)/146097,
|
|
c = a-((146097*b)/4),
|
|
d = (4*c + 3)/1461,
|
|
e = c - (1461*d)/4,
|
|
m = (5*e + 2)/153;
|
|
auto day = cast(ushort) (e - ((153*m + 2)/5) + 1);
|
|
auto month = cast(ushort) (m + 3 - 12 * (m/10));
|
|
auto year = cast(ushort) (100*b + d - 4800 + (m/10));
|
|
|
|
return tuple(year, month, day);
|
|
}
|
|
|
|
@property GregDayOfWeek dayOfWeek() const
|
|
{
|
|
immutable
|
|
ymd = yearMonthDay,
|
|
a = cast(ushort) ((14-ymd._1)/12),
|
|
y = cast(ushort) (ymd._0 - a),
|
|
m = cast(ushort) (ymd._1 + 12*a - 2),
|
|
d = cast(ushort) ((ymd._2 + y + (y/4) - (y/100) +
|
|
(y/400) + (31*m)/12) % 7);
|
|
return d;
|
|
}
|
|
|
|
@property GregDayOfYear dayOfYear() const
|
|
{
|
|
const start_of_year = Date(year(), 1, 1);
|
|
auto doy = cast(ushort) ((this - start_of_year).days() + 1);
|
|
return cast(GregDayOfYear) doy;
|
|
}
|
|
|
|
@property Date endOfMonth() const
|
|
{
|
|
assert(0);
|
|
}
|
|
|
|
@property bool isInfinity() const
|
|
{
|
|
return isNegInfinity || isPosInfinity;
|
|
}
|
|
|
|
@property bool isNegInfinity() const
|
|
{
|
|
return days_ == negInfin.value;
|
|
}
|
|
|
|
@property bool isPosInfinity() const
|
|
{
|
|
return days_ == posInfin.value;
|
|
}
|
|
|
|
@property bool isNotADate() const
|
|
{
|
|
return days_ == notADateTime.value;
|
|
}
|
|
|
|
@property bool isSpecial() const
|
|
{
|
|
return isNotADate || isInfinity;
|
|
}
|
|
|
|
@property Special asSpecial() const
|
|
{
|
|
return days_ < notSpecial.value
|
|
? Special(days_)
|
|
: notSpecial;
|
|
}
|
|
|
|
@property long modJulianDay() const
|
|
{
|
|
auto ymd = yearMonthDay();
|
|
return julianDay(ymd) - 2400001; //prerounded
|
|
}
|
|
|
|
static @property long julianDay(Tuple!(ushort, ushort, ushort) ymd)
|
|
{
|
|
immutable
|
|
a = cast(ushort) ((14-ymd._1)/12),
|
|
y = cast(ushort) (ymd._0 + 4800 - a),
|
|
m = cast(ushort) (ymd._1 + 12*a - 3),
|
|
d = ymd._2 + ((153*m + 2)/5) + 365*y + (y/4) - (y/100)
|
|
+ (y/400) - 32045;
|
|
return d;
|
|
}
|
|
|
|
static bool isLeapYear(uint year)
|
|
{
|
|
//divisible by 4, not if divisible by 100, but true if
|
|
//divisible by 400
|
|
return (!(year % 4)) && ((year % 100) || (!(year % 400)));
|
|
}
|
|
|
|
@property int weekNumber() const
|
|
{
|
|
auto
|
|
ymd = yearMonthDay,
|
|
julianbegin = julianDay(tuple(cast(ushort)ymd._0,
|
|
cast(ushort)1, cast(ushort)1)),
|
|
juliantoday = julianDay(ymd);
|
|
long day = (julianbegin + 3) % 7;
|
|
ulong week = (juliantoday + day - julianbegin + 4)/7;
|
|
|
|
if ((week >= 1) && (week <= 52))
|
|
{
|
|
return cast(int) week;
|
|
}
|
|
|
|
if ((week == 53))
|
|
{
|
|
if((day==6) ||(day == 5 && isLeapYear(ymd._0)))
|
|
{
|
|
return cast(int) week; //under these circumstances week == 53.
|
|
}
|
|
else
|
|
{
|
|
return 1; //monday - wednesday is in week 1 of next year
|
|
}
|
|
}
|
|
|
|
//if the week is not in current year recalculate using the
|
|
//previous year as the beginning year
|
|
else
|
|
if (week == 0)
|
|
{
|
|
julianbegin = julianDay(
|
|
tuple(cast(ushort) (ymd._0 - 1), cast(ushort) 1,
|
|
cast(ushort) 1));
|
|
juliantoday = julianDay(ymd);
|
|
day = (julianbegin + 3) % 7;
|
|
week = (juliantoday + day - julianbegin + 4)/7;
|
|
return cast(int) week;
|
|
}
|
|
return cast(int) week; //not reachable -- well except if day == 5 and
|
|
//is_leap_year != true
|
|
}
|
|
|
|
@property uint endOfMonthDay() const
|
|
{
|
|
switch (month) {
|
|
case 2:
|
|
if (isLeapYear(year)) {
|
|
return 29;
|
|
} else {
|
|
return 28;
|
|
};
|
|
case 4:
|
|
case 6:
|
|
case 9:
|
|
case 11:
|
|
return 30;
|
|
default:
|
|
return 31;
|
|
}
|
|
}
|
|
|
|
@property string toSimpleString() const
|
|
{
|
|
auto ymd = yearMonthDay;
|
|
return text(ymd._0, '-', ymd._1, '-', ymd._2);
|
|
}
|
|
|
|
@property string toIsoString() const
|
|
{
|
|
assert(0);
|
|
}
|
|
|
|
@property string toIsoExtendedString() const
|
|
{
|
|
assert(0);
|
|
}
|
|
|
|
bool opEquals(ref const Date rhs) const
|
|
{
|
|
return days_ == rhs.days_;
|
|
}
|
|
|
|
int opCmp(in Date rhs) const
|
|
{
|
|
return days_ < rhs.days_ ? -1 : days_ > rhs.days_ ? 1 : 0;
|
|
}
|
|
|
|
// Date opBinary(string op)(const Date d) const
|
|
// if (op == "-")
|
|
// {
|
|
// }
|
|
|
|
Days opBinary(string op)(const Date d) const
|
|
if (op == "-")
|
|
{
|
|
if (!isSpecial && !d.isSpecial)
|
|
{
|
|
return Days(days_ - d.days_);
|
|
}
|
|
else
|
|
{
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
static if (is(tm))
|
|
{
|
|
tm toTm()
|
|
{
|
|
assert(0);
|
|
}
|
|
}
|
|
|
|
private ulong days_;
|
|
}
|
|
|
|
struct Days
|
|
{
|
|
private long days_;
|
|
this(long d) { days_ = d; }
|
|
this(Special s) { }
|
|
@property long days() const { return days_; }
|
|
@property bool isNegative() const { return days_ < 0; }
|
|
@property static Days unit() { return Days(1); }
|
|
@property bool isSpecial()
|
|
{
|
|
assert(0);
|
|
}
|
|
bool opEquals(ref const Days rhs) const
|
|
{
|
|
return days_ == rhs.days_;
|
|
}
|
|
|
|
int opCmp(in Days rhs) const
|
|
{
|
|
return days_ < rhs.days_ ? -1 : days_ > rhs.days_ ? 1 : 0;
|
|
}
|
|
|
|
Days opBinary(string op)(Days d) const
|
|
if (op == "+" || op == "-")
|
|
{
|
|
}
|
|
}
|
|
|
|
Date fromString(in char[] s)
|
|
{
|
|
Date result;
|
|
return result;
|
|
}
|
|
|
|
Date fromUndelimitedString(in char[] s)
|
|
{
|
|
Date result;
|
|
return result;
|
|
}
|
|
|
|
Date dayClockLocalDay()
|
|
{
|
|
Date result;
|
|
return result;
|
|
}
|
|
|
|
Date dayClockUniversalDay()
|
|
{
|
|
Date result;
|
|
return result;
|
|
}
|
|
|
|
static if (is(tm))
|
|
{
|
|
Date dateFromTm(tm)
|
|
{
|
|
assert(0);
|
|
}
|
|
}
|