#include "PDateRel.h"
PDateRel::PDateRel () : _sec(0), _min(0), _hour(0), _day(0), _month(0), _year(0) {};
PDateRel::PDateRel (PDateRel* from) {
_sec = from->sec();
_min = from->min();
_hour = from->hour();
_day = from->day();
_month = from->month();
_year = from->year();
}
PDateRel::PDateRel (SV* arg) { setFrom(arg); }
PDateRel::PDateRel (struct tm &from, struct tm &till) { setFrom(from, till); }
PDateRel::PDateRel (SV* fromSV, SV* tillSV) { setFrom(fromSV, tillSV); }
void PDateRel::setFrom (SV* fromSV, SV* tillSV) {
static PDate from((time_t) 0);
static PDate till((time_t) 0);
from.setFrom(fromSV);
till.setFrom(tillSV);
setFrom(*(from.data()), *(till.data()));
}
void PDateRel::setFrom (struct tm &from, struct tm &till) {
_sec = 0, _min = 0, _hour = 0, _day = 0, _month = 0, _year = 0;
bool reverse = false;
if (tm_compare(from, till) > 0) {
reverse = true;
struct tm tmp = from;
from = till;
till = tmp;
}
_sec = till.tm_sec - from.tm_sec;
if (_sec < 0) { _sec += 60; _min--; }
_min += till.tm_min - from.tm_min;
if (_min < 0) { _min += 60; _hour--; }
_hour += till.tm_hour - from.tm_hour;
if (_hour < 0) { _hour += 24; _day--; }
_day += till.tm_mday - from.tm_mday;
if (_day < 0) {
int tmpy = till.tm_year;
int tmpm = till.tm_mon-1;
if (tmpm < 0) { tmpm += 12; tmpy--; }
int days = days_in_month(tmpy+1900, tmpm+1);
_day += days;
_month--;
}
_month += till.tm_mon - from.tm_mon;
if (_month < 0) { _month += 12; _year --; }
_year += till.tm_year - from.tm_year;
if (reverse) negativeME();
}
void PDateRel::setFrom (SV* arg) {
_sec = 0; _min = 0; _hour = 0; _day = 0; _month = 0; _year = 0;
if (!SvOK(arg)) return;
if (SvROK(arg)) {
if (sv_isobject(arg) && sv_isa(arg, PDATE_REL_CLASS)) setFrom((PDateRel *) SvIV(SvRV(arg)));
else {
SV* rarg = SvRV(arg);
if (SvTYPE(rarg) == SVt_PVHV) setFrom((HV*) rarg);
else if (SvTYPE(rarg) == SVt_PVAV) setFrom((AV*) rarg);
else croak("Panda::Date::Rel - cannot create object - unknown argument passed");
}
}
else if (looks_like_number(arg)) {
_sec = SvIV(arg);
}
else {
STRLEN len;
const char* str = SvPV(arg, len);
setFrom(str, len);
}
}
void PDateRel::setFrom (PDateRel* from) {
_sec = from->sec();
_min = from->min();
_hour = from->hour();
_day = from->day();
_month = from->month();
_year = from->year();
}
int64_t PDateRel::sec () { return _sec; }
void PDateRel::sec (int64_t val) { _sec = val; }
int64_t PDateRel::min () { return _min; }
void PDateRel::min (int64_t val) { _min = val; }
int64_t PDateRel::hour () { return _hour; }
void PDateRel::hour (int64_t val) { _hour = val; }
int64_t PDateRel::day () { return _day; }
void PDateRel::day (int64_t val) { _day = val; }
int64_t PDateRel::month () { return _month; }
void PDateRel::month (int64_t val) { _month = val; }
int64_t PDateRel::year () { return _year; }
void PDateRel::year (int64_t val) { _year = val; }
void PDateRel::setFrom (HV* from) {
SV** ref;
ref = hv_fetch(from, "year", 4, 0);
if (ref != NULL) _year = SvIV(*ref);
ref = hv_fetch(from, "month", 5, 0);
if (ref != NULL) _month = SvIV(*ref);
ref = hv_fetch(from, "day", 3, 0);
if (ref != NULL) _day = SvIV(*ref);
ref = hv_fetch(from, "hour", 4, 0);
if (ref != NULL) _hour = SvIV(*ref);
ref = hv_fetch(from, "min", 3, 0);
if (ref != NULL) _min = SvIV(*ref);
ref = hv_fetch(from, "sec", 3, 0);
if (ref != NULL) _sec = SvIV(*ref);
}
void PDateRel::setFrom (AV* from) {
I32 len = av_len(from)+1;
SV** ref;
if (len > 0) { ref = av_fetch(from, 0, 0); if (ref != NULL) _year = SvIV(*ref); }
if (len > 1) { ref = av_fetch(from, 1, 0); if (ref != NULL) _month = SvIV(*ref); }
if (len > 2) { ref = av_fetch(from, 2, 0); if (ref != NULL) _day = SvIV(*ref); }
if (len > 3) { ref = av_fetch(from, 3, 0); if (ref != NULL) _hour = SvIV(*ref); }
if (len > 4) { ref = av_fetch(from, 4, 0); if (ref != NULL) _min = SvIV(*ref); }
if (len > 5) { ref = av_fetch(from, 5, 0); if (ref != NULL) _sec = SvIV(*ref); }
}
void PDateRel::setFrom (const char* str, size_t len) {
struct tm data;
uint8_t error = parse_relative(str, len, data);
if (error != E_OK) return;
_year = data.tm_year;
_month = data.tm_mon;
_day = data.tm_mday;
_hour = data.tm_hour;
_min = data.tm_min;
_sec = data.tm_sec;
}
const char* PDateRel::toString () {
RELSTR_START(65);
if (_year != 0) { RELSTR_VAL(_year, 'Y') }
if (_month != 0) { RELSTR_VAL(_month, 'M') }
if (_day != 0) { RELSTR_VAL(_day, 'D') }
if (_hour != 0) { RELSTR_VAL(_hour, 'h') }
if (_min != 0) { RELSTR_VAL(_min, 'm') }
if (_sec != 0) { RELSTR_VAL(_sec, 's') }
RELSTR_END;
}
bool PDateRel::empty () { return _sec == 0 && _min == 0 && _hour == 0 && _day == 0 && _month == 0 && _year == 0; }
bool PDateRel::hasMPart () { return _year != 0 || _month != 0; }
bool PDateRel::hasSPart () { return _sec != 0 || _min != 0 || _hour != 0 || _day != 0; }
int64_t PDateRel::toSec () { return _sec + _min*60 + _hour*3600 + _day * 86400 + (_month + 12*_year) * 2629744; }
double PDateRel::toMin () { return (double) toSec() / 60; }
double PDateRel::toHour () { return (double) toSec() / 3600; }
double PDateRel::toDay () { return (double) toSec() / 86400; }
double PDateRel::toMonth () { return (double) toSec() / 2629744; }
double PDateRel::toYear () { return toMonth() / 12; }
PDateRel* PDateRel::clone () { return new PDateRel(this); }
PDateRel* PDateRel::multiply (double koef) { return clone()->multiplyME(koef); }
PDateRel* PDateRel::multiplyME (double koef) {
if (fabs(koef) < 1 && koef != 0) return divideME(1/koef);
_sec *= koef;
_min *= koef;
_hour *= koef;
_day *= koef;
_month *= koef;
_year *= koef;
return this;
}
PDateRel* PDateRel::divide (double koef) { return clone()->divideME(koef); }
PDateRel* PDateRel::divideME (double koef) {
if (fabs(koef) <= 1) return multiplyME(1/koef);
double td;
int64_t tmp;
tmp = _year;
_year /= koef;
td = (tmp - _year*koef)*12;
tmp = td;
_month += tmp;
td = (td - tmp)*((double)2629744/86400);
tmp = td;
_day += tmp;
td = (td - tmp)*24;
tmp = td;
_hour += tmp;
td = (td - tmp)*60;
tmp = td;
_min += tmp;
td = (td - tmp)*60;
_sec += td;
tmp = _month;
_month /= koef;
td = (tmp - _month*koef)*((double)2629744/86400);
tmp = td;
_day += tmp;
td = (td - tmp)*24;
tmp = td;
_hour += tmp;
td = (td - tmp)*60;
tmp = td;
_min += tmp;
td = (td - tmp)*60;
_sec += td;
tmp = _day;
_day /= koef;
td = (tmp - _day*koef)*24;
tmp = td;
_hour += tmp;
td = (td - tmp)*60;
tmp = td;
_min += tmp;
td = (td - tmp)*60;
_sec += td;
tmp = _hour;
_hour /= koef;
td = (tmp - _hour*koef)*60;
tmp = td;
_min += tmp;
td = (td - tmp)*60;
_sec += td;
tmp = _min;
_min /= koef;
_sec += (tmp - _min*koef)*60;
_sec /= koef;
return this;
}
PDateRel* PDateRel::add (PDateRel* operand) { return clone()->addME(operand); }
PDateRel* PDateRel::addME (PDateRel* operand) {
_sec += operand->sec();
_min += operand->min();
_hour += operand->hour();
_day += operand->day();
_month += operand->month();
_year += operand->year();
return this;
}
PDateRel* PDateRel::subtract (PDateRel* operand) { return clone()->subtractME(operand); }
PDateRel* PDateRel::subtractME (PDateRel* operand) {
_sec -= operand->sec();
_min -= operand->min();
_hour -= operand->hour();
_day -= operand->day();
_month -= operand->month();
_year -= operand->year();
return this;
}
PDateRel* PDateRel::negative () { return clone()->negativeME(); }
PDateRel* PDateRel::negativeME () {
_sec = -_sec;
_min = -_min;
_hour = -_hour;
_day = -_day;
_month = -_month;
_year = -_year;
return this;
}
int PDateRel::compare (PDateRel* operand) {
int64_t valME = toSec();
int64_t valO = operand->toSec();
return valME > valO ? 1 : (valME == valO ? 0 : -1);
}
bool PDateRel::equals (PDateRel* operand) {
return _sec == operand->sec() && _min == operand->min() && _hour == operand->hour() &&
_day == operand->day() && _month == operand->month() && _year == operand->year();
}
PDateRel::~PDateRel () {};