#include "DateRel.h"
#include <panda/from_chars.h>
namespace panda { namespace date {
const DateRel YEAR (1);
const DateRel MONTH (0,1);
const DateRel WEEK (0,0,7);
const DateRel DAY (0,0,1);
const DateRel HOUR (0,0,0,1);
const DateRel MIN (0,0,0,0,1);
const DateRel SEC (0,0,0,0,0,1);
static inline void relstr_val (char* st, char*& ptr, ptime_t val, char units) {
if (ptr != st) *(ptr++) = ' ';
auto res = to_chars(ptr, ptr+20, val);
assert(!res.ec);
ptr = res.ptr;
*(ptr++) = units;
}
void DateRel::set (const Date& from_date, const Date& till_date) {
_sec = _min = _hour = _day = _month = _year = 0;
bool reverse = from_date > till_date;
auto& from = reverse ? till_date.date() : from_date.date();
auto& till = reverse ? from_date.date() : till_date.date();
_sec = till.sec - from.sec;
if (_sec < 0) { _sec += 60; _min--; }
_min += till.min - from.min;
if (_min < 0) { _min += 60; _hour--; }
_hour += till.hour - from.hour;
if (_hour < 0) { _hour += 24; _day--; }
_day += till.mday - from.mday;
if (_day < 0) {
int tmpy = till.year;
int tmpm = till.mon-1;
if (tmpm < 0) { tmpm += 12; tmpy--; }
int days = days_in_month(tmpy, tmpm);
_day += days;
_month--;
}
_month += till.mon - from.mon;
if (_month < 0) { _month += 12; _year--; }
_year += till.year - from.year;
if (reverse) negate();
}
string DateRel::to_string () const {
string ret(65);
auto ptr = ret.buf();
auto st = ptr;
if (_year != 0) { relstr_val(st, ptr, _year, 'Y'); }
if (_month != 0) { relstr_val(st, ptr, _month, 'M'); }
if (_day != 0) { relstr_val(st, ptr, _day, 'D'); }
if (_hour != 0) { relstr_val(st, ptr, _hour, 'h'); }
if (_min != 0) { relstr_val(st, ptr, _min, 'm'); }
if (_sec != 0) { relstr_val(st, ptr, _sec, 's'); }
ret.length(ptr - st);
return ret;
}
DateRel& DateRel::operator+= (const DateRel& op) {
_sec += op._sec;
_min += op._min;
_hour += op._hour;
_day += op._day;
_month += op._month;
_year += op._year;
return *this;
}
DateRel& DateRel::operator-= (const DateRel& op) {
_sec -= op._sec;
_min -= op._min;
_hour -= op._hour;
_day -= op._day;
_month -= op._month;
_year -= op._year;
return *this;
}
DateRel& DateRel::operator*= (double koef) {
if (fabs(koef) < 1 && koef != 0) return operator/=(1/koef);
_sec *= koef;
_min *= koef;
_hour *= koef;
_day *= koef;
_month *= koef;
_year *= koef;
return *this;
}
DateRel& DateRel::operator/= (double koef) {
if (fabs(koef) <= 1) return operator*=(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;
}
DateRel& DateRel::negate () {
_sec = -_sec;
_min = -_min;
_hour = -_hour;
_day = -_day;
_month = -_month;
_year = -_year;
return *this;
}
}}