blob: 777063b2c151798dfabf267842e44abb7742e5aa [file] [log] [blame]
// Copyright (C) 1999-2005 Open Source Telecom Corporation.
// Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
//
// As a special exception, you may use this file as part of a free software
// library without restriction. Specifically, if other files instantiate
// templates or use macros or inline functions from this file, or you compile
// this file and link it with other files to produce an executable, this
// file does not by itself cause the resulting executable to be covered by
// the GNU General Public License. This exception does not however
// invalidate any other reasons why the executable file might be covered by
// the GNU General Public License.
//
// This exception applies only to the code released under the name GNU
// Common C++. If you copy code from other releases into a copy of GNU
// Common C++, as the General Public License permits, the exception does
// not apply to the code that you add in this way. To avoid misleading
// anyone as to the status of such modified files, you must delete
// this exception notice from them.
//
// If you write modifications of your own for GNU Common C++, it is your choice
// whether to permit this exception to apply to your modifications.
// If you do not wish that, delete this exception notice.
//
#include <cc++/config.h>
#include <cc++/exception.h>
#include <cc++/thread.h>
#include <cc++/export.h>
#include <cc++/numbers.h>
#include <cstdlib>
#include <cstdio>
#include <iostream>
#include <ctime>
#include <cmath>
#ifdef WIN32
#include "time.h"
#endif
#ifdef CCXX_NAMESPACES
namespace ost {
using namespace std;
#ifdef __BORLANDC__
using std::time_t;
using std::tm;
using std::localtime;
#endif
#endif
Date::Date()
{
time_t now = SysTime::getTime();
struct tm dt;
SysTime::getLocalTime(&now, &dt);
toJulian(dt.tm_year + 1900, dt.tm_mon + 1, dt.tm_mday);
}
Date::Date(struct tm *dt)
{
toJulian(dt->tm_year + 1900, dt->tm_mon + 1, dt->tm_mday);
}
Date::Date(time_t tm)
{
struct tm dt;
SysTime::getLocalTime(&tm, &dt);
toJulian(dt.tm_year + 1900, dt.tm_mon + 1, dt.tm_mday);
}
Date::Date(char *str, size_t size)
{
setDate(str, size);
}
Date::~Date()
{
}
void Date::setDate(const char *str, size_t size)
{
time_t now = SysTime::getTime();
struct tm dt;
SysTime::getLocalTime(&now, &dt);
int year = 0;
const char *mstr = str;
const char *dstr = str;
if(!size)
size = strlen(str);
//0000
if(size == 4) {
#ifdef DEBUG
cout << "Date::SetDate(): 0000" << endl;
#endif
year = dt.tm_year + 1900;
mstr = str;
dstr = str + 2;
}
//00/00
else if(size == 5) {
#ifdef DEBUG
cout << "Date::SetDate(): 00/00" << endl;
#endif
year = dt.tm_year + 1900;
mstr = str;
dstr = str + 3;
}
//000000
else if(size == 6) {
#ifdef DEBUG
cout << "Date::SetDate(): 000000" << endl;
#endif
ZNumber nyear((char*)str, 2);
year = ((dt.tm_year + 1900) / 100) * 100 + nyear();
mstr = str + 2;
dstr = str + 4;
}
//00000000
else if(size == 8 && str[2] >= '0' && str[2] <= '9' && str[5] >= '0' && str[5] <= '9') {
#ifdef DEBUG
cout << "Date::SetDate(): 00000000" << endl;
#endif
ZNumber nyear((char*)str, 4);
year = nyear();
mstr = str + 4;
dstr = str + 6;
}
//00/00/00
else if(size == 8) {
#ifdef DEBUG
cout << "Date::SetDate(): 00/00/00" << endl;
#endif
ZNumber nyear((char*)str, 2);
year = ((dt.tm_year + 1900) / 100) * 100 + nyear();
mstr = str + 3;
dstr = str + 6;
}
//0000/00/00
else if(size == 10) {
#ifdef DEBUG
cout << "Date::SetDate(): 0000-00-00" << endl;
#endif
ZNumber nyear((char*)str, 4);
year = nyear();
mstr = str + 5;
dstr = str + 8;
}
#ifdef CCXX_EXCEPTIONS
else if(Thread::getException() == Thread::throwObject) {
throw this;
}
#ifdef COMMON_STD_EXCEPTION
else if(Thread::getException() == Thread::throwException) {
throw Exception("Date::setDate(): Invalid date.");
}
#endif
#endif
else {
julian = 0x7fffffffl;
return;
}
ZNumber nmonth((char*)mstr, 2);
ZNumber nday((char*)dstr, 2);
toJulian(year, nmonth(), nday());
}
Date::Date(int year, unsigned month, unsigned day)
{
toJulian(year, month, day);
}
void Date::update(void)
{
}
bool Date::isValid(void) const
{
if(julian == 0x7fffffffl)
return false;
return true;
}
char *Date::getDate(char *buf) const
{
fromJulian(buf);
return buf;
}
time_t Date::getDate(tm* dt) const
{
char buf[11];
memset(dt, 0, sizeof(tm));
fromJulian(buf);
Number nyear(buf, 4);
Number nmonth(buf + 5, 2);
Number nday(buf + 8, 2);
dt->tm_year = nyear() - 1900;
dt->tm_mon = nmonth() - 1;
dt->tm_mday = nday();
return mktime(dt); // to fill in day of week etc.
}
time_t Date::getDate(void) const
{
struct tm dt;
return getDate(&dt);
}
int Date::getYear(void) const
{
char buf[11];
fromJulian(buf);
Number num(buf, 4);
return num();
}
unsigned Date::getMonth(void) const
{
char buf[11];
fromJulian(buf);
Number num(buf + 5, 2);
return num();
}
unsigned Date::getDay(void) const
{
char buf[11];
fromJulian(buf);
Number num(buf + 8, 2);
return num();
}
unsigned Date::getDayOfWeek(void) const
{
return (unsigned)((julian + 1l) % 7l);
}
String Date::operator()() const
{
char buf[11];
fromJulian(buf);
String date(buf);
return date;
}
long Date::getValue(void) const
{
char buf[11];
fromJulian(buf);
return atol(buf) * 10000 + atol(buf + 5) * 100 + atol(buf + 8);
}
Date& Date::operator++()
{
++julian;
update();
return *this;
}
Date& Date::operator--()
{
--julian;
update();
return *this;
}
Date& Date::operator+=(const long val)
{
julian += val;
update();
return *this;
}
Date& Date::operator-=(long val)
{
julian -= val;
update();
return *this;
}
int Date::operator==(const Date &d)
{
return julian == d.julian;
}
int Date::operator!=(const Date &d)
{
return julian != d.julian;
}
int Date::operator<(const Date &d)
{
return julian < d.julian;
}
int Date::operator<=(const Date &d)
{
return julian <= d.julian;
}
int Date::operator>(const Date &d)
{
return julian > d.julian;
}
int Date::operator>=(const Date &d)
{
return julian >= d.julian;
}
void Date::toJulian(long year, long month, long day)
{
julian = 0x7fffffffl;
if(month < 1 || month > 12 || day < 1 || day > 31 || year == 0) {
#ifdef CCXX_EXCEPTIONS
if(Thread::getException() == Thread::throwObject) {
throw this;
}
#ifdef COMMON_STD_EXCEPTION
else if(Thread::getException() == Thread::throwException) {
throw Exception("Date::toJulian(): Invalid date.");
}
#endif
#endif
return;
}
if(year < 0)
year--;
julian = day - 32075l +
1461l * (year + 4800l + ( month - 14l) / 12l) / 4l +
367l * (month - 2l - (month - 14l) / 12l * 12l) / 12l -
3l * ((year + 4900l + (month - 14l) / 12l) / 100l) / 4l;
}
void Date::fromJulian(char *buffer) const
{
// The following conversion algorithm is due to
// Henry F. Fliegel and Thomas C. Van Flandern:
ZNumber nyear(buffer, 4);
buffer[4] = '-';
ZNumber nmonth(buffer + 5, 2);
buffer[7] = '-';
ZNumber nday(buffer + 8, 2);
double i, j, k, l, n;
l = julian + 68569.0;
n = int( 4 * l / 146097.0);
l = l - int( (146097.0 * n + 3)/ 4 );
i = int( 4000.0 * (l+1)/1461001.0);
l = l - int(1461.0*i/4.0) + 31.0;
j = int( 80 * l/2447.0);
k = l - int( 2447.0 * j / 80.0);
l = int(j/11);
j = j+2-12*l;
i = 100*(n - 49) + i + l;
nyear = int(i);
nmonth = int(j);
nday = int(k);
buffer[10] = '\0';
}
Date operator+(const Date &date, const long val)
{
Date d = date;
d.julian += val;
d.update();
return d;
}
Date operator+(const long val, const Date &date)
{
Date d = date;
d.julian += val;
d.update();
return d;
}
Date operator-(const Date &date, const long val)
{
Date d = date;
d.julian -= val;
d.update();
return d;
}
Date operator-(const long val, const Date &date)
{
Date d = date;
d.julian -= val;
d.update();
return d;
}
Time::Time()
{
time_t now = SysTime::getTime();
struct tm dt;
SysTime::getLocalTime(&now, &dt);
toSeconds(dt.tm_hour, dt.tm_min, dt.tm_sec);
}
Time::Time(struct tm *dt)
{
toSeconds(dt->tm_hour, dt->tm_min, dt->tm_sec);
}
Time::Time(time_t tm)
{
struct tm dt;
SysTime::getLocalTime(&tm, &dt);
toSeconds(dt.tm_hour, dt.tm_min, dt.tm_sec);
}
Time::Time(char *str, size_t size)
{
setTime(str, size);
}
Time::Time(int hour, int minute, int second)
{
toSeconds(hour, minute, second);
}
Time::~Time()
{
}
bool Time::isValid(void) const
{
if(seconds == -1)
return false;
return true;
}
char *Time::getTime(char *buf) const
{
fromSeconds(buf);
return buf;
}
time_t Time::getTime(void) const
{
return static_cast<time_t>(seconds);
}
int Time::getHour(void) const
{
char buf[7];
fromSeconds(buf);
ZNumber num(buf, 2);
return num();
}
int Time::getMinute(void) const
{
char buf[7];
fromSeconds(buf);
ZNumber num(buf + 2, 2);
return num();
}
int Time::getSecond(void) const
{
char buf[7];
fromSeconds(buf);
ZNumber num(buf + 4, 2);
return num();
}
void Time::update(void)
{
}
void Time::setTime(char *str, size_t size)
{
int sec = 00;
if(!size)
size = strlen(str);
//00:00
if (size == 5) {
sec = 00;
}
//00:00:00
else if (size == 8) {
ZNumber nsecond(str + 6, 2);
sec = nsecond();
}
#ifdef CCXX_EXCEPTIONS
else if(Thread::getException() == Thread::throwObject) {
throw this;
}
#ifdef COMMON_STD_EXCEPTION
else if(Thread::getException() == Thread::throwException) {
throw Exception("Time::setTime(): Invalid time.");
}
#endif
#endif
else {
return;
}
ZNumber nhour(str, 2);
ZNumber nminute(str+3, 2);
toSeconds(nhour(), nminute(), sec);
}
String Time::operator()() const
{
char buf[7];
fromSeconds(buf);
String strTime(buf);
return strTime;
}
long Time::getValue(void) const
{
return seconds;
}
Time& Time::operator++()
{
++seconds;
update();
return *this;
}
Time& Time::operator--()
{
--seconds;
update();
return *this;
}
Time& Time::operator+=(const int val)
{
seconds += val;
update();
return *this;
}
Time& Time::operator-=(const int val)
{
seconds -= val;
update();
return *this;
}
int Time::operator==(const Time &t)
{
return seconds == t.seconds;
}
int Time::operator!=(const Time &t)
{
return seconds != t.seconds;
}
int Time::operator<(const Time &t)
{
return seconds < t.seconds;
}
int Time::operator<=(const Time &t)
{
return seconds <= t.seconds;
}
int Time::operator>(const Time &t)
{
return seconds > t.seconds;
}
int Time::operator>=(const Time &t)
{
return seconds >= t.seconds;
}
void Time::toSeconds(int hour, int minute, int second)
{
seconds = -1;
if (hour > 23 ||minute > 59 ||second > 59) {
#ifdef CCXX_EXCEPTIONS
if(Thread::getException() == Thread::throwObject) {
throw this;
}
#ifdef COMMON_STD_EXCEPTION
else if(Thread::getException() == Thread::throwException) {
throw Exception("Time::toSeconds(): Invalid time.");
}
#endif
#endif
return;
}
seconds = 3600 * hour + 60 * minute + second;
}
void Time::fromSeconds(char *buffer) const
{
ZNumber hour(buffer, 2);
ZNumber minute(buffer + 2, 2);
ZNumber second(buffer + 4, 2);
hour = seconds / 3600;
minute = (seconds - (3600 * hour())) / 60;
second = seconds - (3600 * hour()) - (60 * minute());
buffer[6] = '\0';
}
Time operator+(const Time &time1, const Time &time2)
{
Time t;
t.seconds = time1.seconds + time2.seconds;
t.update();
return t;
}
Time operator-(const Time &time1, const Time &time2)
{
Time t;
t.seconds = time1.seconds - time2.seconds;
t.update();
return t;
}
Time operator+(const Time &time, const int val)
{
Time t = time;
t.seconds += val;
t.update();
return t;
}
Time operator+(const int val, const Time &time)
{
Time t = time;
t.seconds += val;
t.update();
return t;
}
Time operator-(const Time &time, const int val)
{
Time t = time;
t.seconds -= val;
t.update();
return t;
}
Time operator-(const int val, const Time &time)
{
Time t = time;
t.seconds -= val;
t.update();
return t;
}
Datetime::Datetime(time_t tm)
{
struct tm dt;
SysTime::getLocalTime(&tm, &dt);
toJulian(dt.tm_year + 1900, dt.tm_mon + 1, dt.tm_mday);
toSeconds(dt.tm_hour, dt.tm_min, dt.tm_sec);
}
Datetime::Datetime(tm *dt) :
Date(dt), Time(dt)
{}
Datetime::Datetime(const char *a_str, size_t size)
{
char *timestr;
if (!size)
size = strlen(a_str);
char *str = new char[size+1];
strncpy(str, a_str, size);
str[size]=0;
// 00/00 00:00
if (size == 11) {
timestr = str + 6;
setDate(str, 5);
setTime(timestr, 5);
}
// 00/00/00 00:00
else if (size == 14) {
timestr = str + 9;
setDate(str, 8);
setTime(timestr,5);
}
// 00/00/00 00:00:00
else if (size == 17) {
timestr = str + 9;
setDate(str, 8);
setTime(timestr,8);
}
// 0000/00/00 00:00:00
else if (size == 19) {
timestr = str + 11;
setDate(str, 10);
setTime(timestr,8);
}
#ifdef CCXX_EXCEPTIONS
else if(Thread::getException() == Thread::throwObject) {
delete str;
throw this;
}
#ifdef COMMON_STD_EXCEPTION
else if(Thread::getException() == Thread::throwException) {
delete str;
throw Exception("Datetime::Datetime(): Invalid time.");
}
#endif
#endif
delete str;
}
Datetime::Datetime(int year, unsigned month, unsigned day,
int hour, int minute, int second) :
Date(year, month, day), Time(hour, minute, second)
{}
Datetime::Datetime() : Date(), Time()
{
time_t now = SysTime::getTime();
struct tm dt;
SysTime::getLocalTime(&now, &dt);
toSeconds(dt.tm_hour, dt.tm_min, dt.tm_sec);
toJulian(dt.tm_year + 1900, dt.tm_mon + 1, dt.tm_mday);
}
Datetime::~Datetime()
{
}
bool Datetime::isValid(void) const
{
return Date::isValid() && Time::isValid();
}
char *Datetime::getDatetime(char *buf) const
{
fromJulian(buf);
buf[10] = ' ';
fromSeconds(buf+11);
return buf;
}
time_t Datetime::getDatetime(void) const
{
char buf[11];
struct tm dt;
memset(&dt, 0, sizeof(dt));
fromJulian(buf);
ZNumber nyear(buf, 4);
ZNumber nmonth(buf + 5, 2);
ZNumber nday(buf + 8, 2);
dt.tm_year = nyear() - 1900;
dt.tm_mon = nmonth() - 1;
dt.tm_mday = nday();
fromSeconds(buf);
ZNumber nhour(buf, 2);
ZNumber nminute(buf + 2, 2);
ZNumber nsecond(buf + 4, 2);
dt.tm_hour = nhour();
dt.tm_min = nminute();
dt.tm_sec = nsecond();
dt.tm_isdst = -1;
return mktime(&dt);
}
Datetime& Datetime::operator=(const Datetime datetime)
{
julian = datetime.julian;
seconds = datetime.seconds;
return *this;
}
Datetime& Datetime::operator+=(const Datetime &datetime)
{
seconds += datetime.seconds;
julian += datetime.julian;
Date::update();
Time::update();
return *this;
}
Datetime& Datetime::operator-=(const Datetime &datetime)
{
seconds -= datetime.seconds;
julian -= datetime.julian;
Date::update();
Time::update();
return *this;
}
Datetime& Datetime::operator+=(const Time &time)
{
seconds += time.getValue();
Date::update();
Time::update();
return *this;
}
Datetime& Datetime::operator-=(const Time &time)
{
seconds -= time.getValue();
Date::update();
Time::update();
return *this;
}
int Datetime::operator==(const Datetime &d)
{
return (julian == d.julian) && (seconds == d.seconds);
}
int Datetime::operator!=(const Datetime &d)
{
return (julian != d.julian) || (seconds != d.seconds);
}
int Datetime::operator<(const Datetime &d)
{
if (julian != d.julian) {
return (julian < d.julian);
}
else {
return (seconds < d.seconds);
}
}
int Datetime::operator<=(const Datetime &d)
{
if (julian != d.julian) {
return (julian < d.julian);
}
else {
return (seconds <= d.seconds);
}
}
int Datetime::operator>(const Datetime &d)
{
if (julian != d.julian) {
return (julian > d.julian);
}
else {
return (seconds > d.seconds);
}
}
int Datetime::operator>=(const Datetime &d)
{
if (julian != d.julian) {
return (julian > d.julian);
}
else {
return (seconds >= d.seconds);
}
}
bool Datetime::operator!() const
{
return !(Date::isValid() && Time::isValid());
}
String Datetime::strftime(const char *format) const
{
char buffer[64];
size_t last;
time_t t;
tm tbp;
String retval;
t = getDatetime();
SysTime::getLocalTime(&t, &tbp);
#ifdef WIN32
last = ::strftime(buffer, 64, format, &tbp);
#else
last = std::strftime(buffer, 64, format, &tbp);
#endif
buffer[last] = '\0';
retval = buffer;
return retval;
}
DateNumber::DateNumber(char *str) :
Number(str, 10), Date(str, 10)
{}
DateNumber::~DateNumber()
{}
#ifdef CCXX_NAMESPACES
}
#endif