X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Ftime%2Fdatetime.cpp;h=86238863282340996339071236f51b4a212e193f;hb=5b0c36c9c6c9c30f1eb42186fed7acc7e99faf3e;hp=4fcec9641f4bf23a2ac25c4c17c5f23c24bd7bd9;hpb=80bbee2f401b4af71cb1b80508bdb0d2bb61fa40;p=libs%2Fcore.git diff --git a/source/time/datetime.cpp b/source/time/datetime.cpp index 4fcec96..8623886 100644 --- a/source/time/datetime.cpp +++ b/source/time/datetime.cpp @@ -1,18 +1,26 @@ -/* $Id$ */ +/* $Id$ + +This file is part of libmspcore +Copyright © 2006 Mikko Rasa, Mikkosoft Productions +Distributed under the LGPL +*/ + +#include #include #include -#include +#include "../core/except.h" #include "datetime.h" #include "timestamp.h" +#include "units.h" using namespace std; namespace { -inline bool is_leap_year(int32_t y) +inline bool is_leap_year(int y) { return y%4==0 && (y%100 || y%400==0); } -inline uint8_t month_days(int32_t y, uint8_t m) +inline unsigned char month_days(int y, unsigned char m) { switch(m) { @@ -40,40 +48,41 @@ inline int cmp_(T a, T b) } -#include -using namespace std; - namespace Msp { namespace Time { -DateTime::DateTime(const TimeStamp &ts): - year(1970), - month(1), - mday(1), - hour(0), - minute(0), - second(0), - usec(0) +DateTime::DateTime(const TimeStamp &ts) { - add_raw(ts.raw()); + init(ts); +} + +DateTime::DateTime(const TimeStamp &ts, const TimeZone &tz) +{ + init(ts); + convert_timezone(tz); +} + +DateTime::DateTime(int y, unsigned char m, unsigned char d) +{ + init(y, m, d, 0, 0, 0, 0); +} + +DateTime::DateTime(int y, unsigned char m, unsigned char d, unsigned char h, unsigned char n, unsigned char s) +{ + init(y, m, d, h, n, s, 0); +} + +DateTime::DateTime(int y, unsigned char m, unsigned char d, unsigned char h, unsigned char n, unsigned char s, unsigned u) +{ + init(y, m, d, h, n, s, u); } -DateTime::DateTime(int32_t y, uint8_t m, uint8_t d): - year(y), - month(m), - mday(d), - hour(0), - minute(0), - second(0), - usec(0) -{ } - -void DateTime::add_days(int32_t days) +void DateTime::add_days(int days) { - unsigned new_year=year; + int new_year=year; /* Leap years have a 400 year cycle, so any 400 consecutive years have a - constant number of days */ + constant number of days (400*365+97=146097) */ new_year+=days/146097*400; days%=146097; @@ -93,6 +102,7 @@ void DateTime::add_days(int32_t days) new_year+=cycles*4; // See how many non-leap-years we counted as leap years and reclaim the lost days + // XXX This breaks with negative years unsigned missed_leap_days=((year-fudge)%100+cycles*4)/100; if((year-fudge)%400+cycles*4>=400) --missed_leap_days; @@ -110,8 +120,8 @@ void DateTime::add_days(int32_t days) // We passed a leap year - decrement days if(days==0) { + days=is_leap_year(new_year-fudge)?365:364; --new_year; - days=is_leap_year(new_year)?365:364; } else --days; @@ -134,6 +144,17 @@ void DateTime::add_days(int32_t days) mday+=days; } +void DateTime::set_timezone(const TimeZone &tz) +{ + zone=tz; +} + +void DateTime::convert_timezone(const TimeZone &tz) +{ + add_raw((zone.get_offset()-tz.get_offset()).raw()); + zone=tz; +} + DateTime DateTime::operator+(const TimeDelta &td) const { DateTime dt(*this); @@ -147,6 +168,19 @@ DateTime &DateTime::operator+=(const TimeDelta &td) return *this; } +DateTime DateTime::operator-(const TimeDelta &td) const +{ + DateTime dt(*this); + dt.add_raw(-td.raw()); + return dt; +} + +DateTime &DateTime::operator-=(const TimeDelta &td) +{ + add_raw(-td.raw()); + return *this; +} + int DateTime::cmp(const DateTime &dt) const { if(int c=cmp_(year, dt.year)) @@ -169,9 +203,9 @@ int DateTime::cmp(const DateTime &dt) const TimeStamp DateTime::get_timestamp() const { if(year<-289701 || year>293641) - throw Exception("DateTime is not representable as a TimeStamp"); + throw InvalidState("DateTime is not representable as a TimeStamp"); - int64_t raw=(((hour*60LL)+minute)*60+second)*1000000+usec; + RawTime raw=(((hour*60LL)+minute)*60+second)*1000000+usec; int days=(year-1970)*365; days+=(year-1)/4-(year-1)/100+(year-1)/400-477; for(unsigned i=1; i(offs/Time::min)); + ss<<(offs(raw/86400000000LL); raw%=86400000000LL; if(raw<0) { - ++days; + --days; raw+=86400000000LL; } @@ -263,5 +337,21 @@ void DateTime::normalize() } } +void DateTime::validate() const +{ + if(usec>=1000000) + throw InvalidParameterValue("Microseconds out of range"); + if(second>=60) + throw InvalidParameterValue("Seconds out of range"); + if(minute>=60) + throw InvalidParameterValue("Minutes out of range"); + if(hour>=24) + throw InvalidParameterValue("Hours out of range"); + if(month<1 || month>12) + throw InvalidParameterValue("Month out of range"); + if(mday<1 || mday>month_days(year, month)) + throw InvalidParameterValue("Day of month out of range"); +} + } // namespace Time } // namespace Msp