#include <xs/time.h>
#include <xs/date.h>
using namespace xs;
using namespace xs::date;
using panda::string;
using panda::string_view;
MODULE = Date::Date PACKAGE = Date
PROTOTYPES: DISABLE
#///////////////////////////// STATIC FUNCTIONS ///////////////////////////////////
Date* now () {
RETVAL = new Date(Date::now());
}
Date* now_hires () {
RETVAL = new Date(Date::now_hires());
}
Date* today () {
RETVAL = new Date(Date::today());
}
ptime_t today_epoch () {
datetime date;
localtime(::time(NULL), &date);
date.sec = 0;
date.min = 0;
date.hour = 0;
RETVAL = timelocall(&date);
}
Date* date (SV* date = NULL, SV* zone = NULL) {
RETVAL = new Date(sv2date(date, tzget_optional(zone)));
}
string string_format (Simple newval = Simple()) {
if (newval) {
if (newval.defined()) Date::string_format(string((string_view)newval));
else Date::string_format(string());
}
RETVAL = Date::string_format();
if (!RETVAL) XSRETURN_UNDEF;
}
bool range_check (Simple newval = Simple()) {
if (newval) Date::range_check(newval.defined() && newval.is_true());
RETVAL = Date::range_check();
}
#///////////////////////////// OBJECT METHODS ///////////////////////////////////
Date* new (SV*, SV* date = NULL, SV* zone = NULL) {
RETVAL = new Date(sv2date(date, tzget_optional(zone)));
}
void Date::set (SV* arg, SV* zone = NULL) {
THIS->set(sv2date(arg, tzget_optional(zone)));
}
void Date::epoch (SV* newval = NULL) {
if (newval) {
if (SvNOK(newval)) THIS->epoch((double)SvNV(newval));
else THIS->epoch(xs::in<ptime_t>(newval));
XSRETURN(1);
}
dXSTARG; XSprePUSH;
if (THIS->mksec()) PUSHn(THIS->epoch_mks());
else PUSHi(THIS->epoch());
}
ptime_t Date::epoch_sec () {
RETVAL = THIS->epoch();
}
int32_t Date::year (SV* newval = NULL) {
if (newval) THIS->year(xs::in<ptime_t>(newval));
RETVAL = THIS->year();
}
int32_t Date::c_year (SV* newval = NULL) : ALIAS(_year=1) {
PERL_UNUSED_VAR(ix);
if (newval) THIS->c_year(xs::in<ptime_t>(newval));
RETVAL = THIS->c_year();
}
int8_t Date::yr (SV* newval = NULL) {
if (newval) THIS->yr(xs::in<ptime_t>(newval));
RETVAL = THIS->yr();
}
uint8_t Date::month (SV* newval = NULL) : ALIAS(mon=1) {
PERL_UNUSED_VAR(ix);
if (newval) THIS->month(xs::in<ptime_t>(newval));
RETVAL = THIS->month();
}
uint8_t Date::c_month (SV* newval = NULL) : ALIAS(c_mon=1, _mon=2, _month=3) {
PERL_UNUSED_VAR(ix);
if (newval) THIS->c_month(xs::in<ptime_t>(newval));
RETVAL = THIS->c_month();
}
uint8_t Date::day (SV* newval = NULL) : ALIAS(mday=1, day_of_month=2) {
PERL_UNUSED_VAR(ix);
if (newval) THIS->day(xs::in<ptime_t>(newval));
RETVAL = THIS->day();
}
uint8_t Date::hour (SV* newval = NULL) {
if (newval) THIS->hour(xs::in<ptime_t>(newval));
RETVAL = THIS->hour();
}
uint8_t Date::min (SV* newval = NULL) : ALIAS(minute=1) {
PERL_UNUSED_VAR(ix);
if (newval) THIS->min(xs::in<ptime_t>(newval));
RETVAL = THIS->min();
}
uint8_t Date::sec (SV* newval = NULL) : ALIAS(second=1) {
PERL_UNUSED_VAR(ix);
if (newval) THIS->sec(xs::in<ptime_t>(newval));
RETVAL = THIS->sec();
}
uint32_t Date::mksec (SV* newval = NULL) {
if (newval) THIS->mksec(xs::in<ptime_t>(newval));
RETVAL = THIS->mksec();
}
uint8_t Date::wday (SV* newval = NULL) : ALIAS(day_of_week=1) {
PERL_UNUSED_VAR(ix);
if (newval) THIS->wday(xs::in<ptime_t>(newval));
RETVAL = THIS->wday();
}
uint8_t Date::c_wday (SV* newval = NULL) : ALIAS(_wday=1) {
PERL_UNUSED_VAR(ix);
if (newval) THIS->c_wday(xs::in<ptime_t>(newval));
RETVAL = THIS->c_wday();
}
uint8_t Date::ewday (SV* newval = NULL) {
if (newval) THIS->ewday(xs::in<ptime_t>(newval));
RETVAL = THIS->ewday();
}
uint16_t Date::yday (SV* newval = NULL) : ALIAS(day_of_year=1) {
PERL_UNUSED_VAR(ix);
if (newval) THIS->yday(xs::in<ptime_t>(newval));
RETVAL = THIS->yday();
}
uint16_t Date::c_yday (SV* newval = NULL) : ALIAS(_yday=1) {
PERL_UNUSED_VAR(ix);
if (newval) THIS->c_yday(xs::in<ptime_t>(newval));
RETVAL = THIS->c_yday();
}
bool Date::isdst () : ALIAS(daylight_savings=1) {
PERL_UNUSED_VAR(ix);
RETVAL = THIS->isdst();
}
string Date::to_string (...) : ALIAS(as_string=1, string=2) {
PERL_UNUSED_VAR(ix);
if (THIS->error()) XSRETURN_UNDEF;
RETVAL = THIS->to_string();
}
bool Date::to_bool (...) {
RETVAL = THIS->error() == E_OK ? true : false;
}
ptime_t Date::to_number (...) {
RETVAL = THIS->error() == E_OK ? THIS->epoch() : 0;
}
string Date::strftime (const char* format) {
RETVAL = THIS->strftime(format, NULL);
}
string Date::monthname () : ALIAS(monname=1) {
RETVAL = THIS->strftime("%B", NULL);
PERL_UNUSED_VAR(ix);
}
string Date::wdayname () : ALIAS(day_of_weekname=1) {
RETVAL = THIS->strftime("%A", NULL);
PERL_UNUSED_VAR(ix);
}
string Date::iso () : ALIAS(sql=1) {
RETVAL = THIS->iso();
PERL_UNUSED_VAR(ix);
}
string Date::iso_sec ()
string Date::mysql ()
string Date::hms ()
string Date::ymd ()
string Date::mdy ()
string Date::dmy ()
string Date::ampm ()
string Date::meridiam ()
int Date::gmtoff ()
string_view Date::tzabbr ()
string Date::tzname () {
RETVAL = THIS->timezone()->name;
}
bool Date::tzlocal () {
RETVAL = THIS->timezone()->is_local;
}
TimezoneSP Date::tz (SV* newzone = NULL) : ALIAS(timezone=1, zone=2) {
if (newzone) {
THIS->timezone(tzget_required(newzone));
XSRETURN_UNDEF;
}
RETVAL = THIS->timezone();
PERL_UNUSED_VAR(ix);
}
void Date::to_tz (SV* newzone) : ALIAS(to_timezone=1, to_zone=2) {
THIS->to_timezone(tzget_required(newzone));
PERL_UNUSED_VAR(ix);
}
void Date::array () {
auto cnt = THIS->mksec() ? 7 : 6;
EXTEND(SP, cnt);
mPUSHi(THIS->year());
mPUSHu(THIS->month());
mPUSHu(THIS->day());
mPUSHu(THIS->hour());
mPUSHu(THIS->min());
mPUSHu(THIS->sec());
if (THIS->mksec()) mPUSHu(THIS->mksec());
XSRETURN(cnt);
}
Array Date::aref () {
RETVAL = Array::create();
auto cnt = THIS->mksec() ? 7 : 6;
RETVAL.reserve(cnt);
RETVAL.store(0, Simple(THIS->year()));
RETVAL.store(1, Simple(THIS->month()));
RETVAL.store(2, Simple(THIS->day()));
RETVAL.store(3, Simple(THIS->hour()));
RETVAL.store(4, Simple(THIS->min()));
RETVAL.store(5, Simple(THIS->sec()));
if (THIS->mksec()) RETVAL.store(6, Simple(THIS->mksec()));
}
void Date::struct () {
EXTEND(SP, 9);
mPUSHu(THIS->sec());
mPUSHu(THIS->min());
mPUSHu(THIS->hour());
mPUSHu(THIS->day());
mPUSHu(THIS->c_month());
mPUSHi(THIS->c_year());
mPUSHu(THIS->c_wday());
mPUSHu(THIS->c_yday());
mPUSHu(THIS->isdst() ? 1 : 0);
XSRETURN(9);
}
Array Date::sref () {
RETVAL = Array::create();
RETVAL.reserve(8);
RETVAL.store(0, Simple(THIS->sec()));
RETVAL.store(1, Simple(THIS->min()));
RETVAL.store(2, Simple(THIS->hour()));
RETVAL.store(3, Simple(THIS->day()));
RETVAL.store(4, Simple(THIS->c_month()));
RETVAL.store(5, Simple(THIS->c_year()));
RETVAL.store(6, Simple(THIS->c_wday()));
RETVAL.store(7, Simple(THIS->c_yday()));
RETVAL.store(8, Simple(THIS->isdst() ? 1 : 0));
}
void Date::hash () {
int cnt = 12;
if (THIS->mksec()) cnt = 14;
EXTEND(SP, cnt);
mPUSHp("year", 4);
mPUSHi(THIS->year());
mPUSHp("month", 5);
mPUSHu(THIS->month());
mPUSHp("day", 3);
mPUSHu(THIS->day());
mPUSHp("hour", 4);
mPUSHu(THIS->hour());
mPUSHp("min", 3);
mPUSHu(THIS->min());
mPUSHp("sec", 3);
mPUSHu(THIS->sec());
if (THIS->mksec()) {
mPUSHp("mksec", 5);
mPUSHu(THIS->mksec());
}
XSRETURN(cnt);
}
Hash Date::href () {
RETVAL = Hash::create();
RETVAL.store("year", Simple(THIS->year()));
RETVAL.store("month", Simple(THIS->month()));
RETVAL.store("day", Simple(THIS->day()));
RETVAL.store("hour", Simple(THIS->hour()));
RETVAL.store("min", Simple(THIS->min()));
RETVAL.store("sec", Simple(THIS->sec()));
if (THIS->mksec()) RETVAL.store("mksec", Simple(THIS->mksec()));
}
Date* Date::clone (SV* diff = NULL, SV* zoneSV = NULL) {
if (diff) {
auto zone = tzget_optional(zoneSV);
if (SvOK(diff)) {
if (!SvRV(diff)) throw "bad argument type";
diff = SvRV(diff);
ptime_t vals[] = {-1, -1, -1, -1, -1, -1, -1, -1};
if (SvTYPE(diff) == SVt_PVHV) {
Hash hash = (HV*)diff;
hash2vals(hash, vals, &zone);
}
else if (SvTYPE(diff) == SVt_PVAV) {
Array arr = (AV*)diff;
array2vals(arr, vals);
}
else throw "bad argument type";
RETVAL = new Date(THIS->clone(vals[0], vals[1], vals[2], vals[3], vals[4], vals[5], vals[6], vals[7], zone));
}
else RETVAL = new Date(*THIS, zone);
}
else RETVAL = new Date(*THIS);
PROTO = Object(ST(0)).stash();
}
SV* Date::month_begin () {
THIS->month_begin();
XSRETURN(1);
}
Date* Date::month_begin_new () {
RETVAL = new Date(THIS->month_begin_new());
PROTO = Object(ST(0)).stash();
}
SV* Date::month_end () {
THIS->month_end();
XSRETURN(1);
}
Date* Date::month_end_new () {
RETVAL = new Date(THIS->month_end_new());
PROTO = Object(ST(0)).stash();
}
int Date::days_in_month () {
RETVAL = THIS->days_in_month();
}
uint8_t Date::error () {
RETVAL = (uint8_t) THIS->error();
}
string_view Date::errstr ()
SV* Date::truncate () {
THIS->truncate();
XSRETURN(1);
}
Date* Date::truncated () : ALIAS(truncate_new=1) {
if (ix == 1) warn("truncate_new() is deprecated, use truncated() instead");
RETVAL = new Date(THIS->truncated());
PROTO = Object(ST(0)).stash();
}
int Date::compare (Sv arg, bool reverse = false) {
RETVAL = THIS->compare(sv2date(arg, THIS->timezone(), true, true));
if (reverse) RETVAL = -RETVAL;
if (RETVAL < 0) RETVAL = -1;
else if (RETVAL > 0) RETVAL = 1;
}
Date* Date::sum (Sv arg, ...) : ALIAS(add_new=1) {
if (ix == 1) warn("add_new() is deprecated, use sum() instead");
RETVAL = new Date(*THIS + sv2daterel(arg));
PROTO = Object(ST(0)).stash();
}
SV* Date::add (Sv arg, ...) {
*THIS += sv2daterel(arg);
XSRETURN(1);
}
Sv Date::difference (Sv arg, bool reverse = false) : ALIAS(subtract_new=1) {
if (ix == 1) warn("subtract_new() is deprecated, use difference() instead");
if (arg.is_object_ref()) { // reverse is impossible here
if (Object(arg).stash().name() == "Date::Rel")
RETVAL = xs::out(new Date(*THIS - *xs::in<const DateRel*>(arg)), Object(ST(0)).stash());
else
RETVAL = xs::out(new DateInt(*xs::in<Date*>(arg), *THIS));
}
else if (reverse) { // only date supported for reverse
RETVAL = xs::out(new DateInt(*THIS, sv2date(arg, THIS->timezone())));
}
else if (looks_like_number(arg)) {
auto ret = new Date(*THIS);
ret->epoch(ret->epoch() - xs::in<ptime_t>(arg));
RETVAL = xs::out(ret, Object(ST(0)).stash());
}
else { // date or rdate scalar
if (looks_like_relative(xs::in<string_view>(arg))) { // not a date -> reldate
RETVAL = xs::out(new Date(*THIS - sv2daterel(arg)), Object(ST(0)).stash());
} else { // date
RETVAL = xs::out(new DateInt(sv2date(arg, THIS->timezone()), *THIS));
}
}
}
SV* Date::subtract (Sv arg, ...) {
*THIS -= sv2daterel(arg);
XSRETURN(1);
}
void __assign_stub (...) {
if (!items) throw "should not happen";
XSRETURN(1);
}