File Coverage

xs/Date.xs
Criterion Covered Total %
statement 248 266 93.2
branch 404 838 48.2
condition n/a
subroutine n/a
pod n/a
total 652 1104 59.0


line stmt bran cond sub pod time code
1             #include
2             #include
3             #include "private.h"
4              
5             using namespace xs;
6             using namespace xs::date;
7             using panda::string;
8             using panda::string_view;
9              
10             #ifdef _WIN32
11             const auto LT_FORMAT = string_view("%a %b %d %H:%M:%S %Y");
12             #else
13             const auto LT_FORMAT = string_view("%a %b %e %H:%M:%S %Y");
14             #endif
15            
16             static const unsigned char relchars[256] = {
17             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
18             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1,
19             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 0,
20             0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
21             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
22             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
23             0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
24             };
25              
26             // arguments overloading for new_ymd(), date_ymd(), ->set_ymd()
27 32           static inline Date xs_date_ymd (SV** args, I32 items) {
28 32           ptime_t vals[8] = {1970, 1, 1, 0, 0, 0, 0, -1};
29 64 50         auto tz = list2vals(args, items, vals);
30 32 50         auto ret = Date(vals[0], vals[1], vals[2], vals[3], vals[4], vals[5], vals[6], vals[7], tz);
31 32 100         if (ret.error() && is_strict_mode()) throw xs::out(ret.error());
    50          
    50          
    50          
    100          
    50          
    0          
32 58           return ret;
33             }
34              
35             MODULE = Date::Date PACKAGE = Date
36             PROTOTYPES: DISABLE
37              
38             BOOT {
39 94 50         Stash stash(__PACKAGE__);
40            
41 1128 50         xs::exp::create_constants(stash, {
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    100          
    0          
42             {"FORMAT_ISO", (int)Date::Format::iso},
43             {"FORMAT_ISO_TZ", (int)Date::Format::iso_tz},
44             {"FORMAT_ISO_DATE", (int)Date::Format::iso_date},
45             {"FORMAT_ISO8601", (int)Date::Format::iso8601},
46             {"FORMAT_ISO8601_NOTZ", (int)Date::Format::iso8601_notz},
47             {"FORMAT_RFC1123", (int)Date::Format::rfc1123},
48             {"FORMAT_COOKIE", (int)Date::Format::cookie},
49             {"FORMAT_RFC850", (int)Date::Format::rfc850},
50             {"FORMAT_ANSI_C", (int)Date::Format::ansi_c},
51             {"FORMAT_YMD", (int)Date::Format::ymd},
52             {"FORMAT_DOT", (int)Date::Format::dot},
53             {"FORMAT_HMS", (int)Date::Format::hms},
54             {"FORMAT_CLF", (int)Date::Format::clf},
55             {"FORMAT_CLF_BRACKETS", (int)Date::Format::clfb},
56            
57             {"INPUT_FORMAT_ALL", Date::InputFormat::all},
58             {"INPUT_FORMAT_ISO", Date::InputFormat::iso},
59             {"INPUT_FORMAT_ISO8601", Date::InputFormat::iso8601},
60             {"INPUT_FORMAT_RFC1123", Date::InputFormat::rfc1123},
61             {"INPUT_FORMAT_RFC850", Date::InputFormat::rfc850},
62             {"INPUT_FORMAT_ANSI_C", Date::InputFormat::ansi_c},
63             {"INPUT_FORMAT_DOT", Date::InputFormat::dot},
64             {"INPUT_FORMAT_CLF", Date::InputFormat::clf},
65 1081 50         });
66            
67 94 50         Stash ecstash("Date::Error", GV_ADD);
68 282 50         xs::exp::create_constants(ecstash, {
    50          
    50          
    100          
    0          
69 94 50         {"parser_error", xs::out(make_error_code(errc::parser_error))},
70 94 50         {"out_of_range", xs::out(make_error_code(errc::out_of_range))},
71 141 50         });
72            
73 47 50         stash.add_const_sub("error_category", xs::out(&error_category));
    50          
74             }
75              
76             #///////////////////////////// STATIC FUNCTIONS ///////////////////////////////////
77              
78 32           const Timezone* tzget (string_view zonename = {})
79 16 50          
80 82 50         void tzset (TimezoneSP newzone = {})
81              
82             string tzdir (SV* newdir = NULL) {
83 0 0         if (newdir) {
84 0 0         tzdir(xs::in(newdir));
    0          
85 0           XSRETURN_UNDEF;
86             }
87 0 0         RETVAL = tzdir();
    0          
88             }
89              
90 47 50         string tzsysdir ()
    50          
91              
92             string tzembededdir(SV* newdir = NULL) {
93 97 100         if (newdir) {
94 72 50         tzembededdir(xs::in(newdir));
    50          
95 72           XSRETURN_UNDEF;
96             }
97 25 50         RETVAL = tzembededdir();
    50          
98             }
99              
100             void available_timezones () {
101 2 50         auto list = available_timezones();
102 1 50         if (list.size()) EXTEND(SP, (int)list.size());
    50          
    50          
    50          
    0          
103 1213 100         for (auto& name : list) {
104 1212 50         mPUSHs(xs::out(name).detach());
    50          
105             }
106 1           XSRETURN(list.size());
107             }
108              
109 0           void use_system_timezones ()
110              
111 72           void use_embed_timezones ()
112              
113             void gmtime (SV* epochSV = {}, TimezoneSP tz = {}) : ALIAS(localtime=1, anytime=2) {
114             ptime_t epoch;
115 7 50         if (epochSV) epoch = xs::in(epochSV);
    50          
116 0           else epoch = (ptime_t) ::time(NULL);
117              
118             datetime date;
119 7           bool success = false;
120 7           switch (ix) {
121 2 50         case 0: success = gmtime(epoch, &date); break;
122 5 50         case 1: success = localtime(epoch, &date); break;
123 0 0         case 2: success = anytime(epoch, &date, tz ? tz : tzlocal()); break;
    0          
    0          
124             }
125              
126 7 50         if (GIMME_V == G_ARRAY) {
    0          
    100          
127 5 50         if (!success) XSRETURN_EMPTY;
128 5 50         EXTEND(SP, 9);
    0          
129 5 50         EXTEND_MORTAL(9);
    0          
130 5 50         mPUSHu(date.sec);
    50          
131 5 50         mPUSHu(date.min);
    50          
132 5 50         mPUSHu(date.hour);
    50          
133 5 50         mPUSHu(date.mday);
    50          
134 5 50         mPUSHu(date.mon);
    50          
135 5 50         mPUSHi(date.year);
    50          
136 5 50         mPUSHu(date.wday);
    50          
137 5 50         mPUSHu(date.yday);
    50          
138 5 50         mPUSHu(date.isdst);
    50          
139 5           XSRETURN(9);
140             } else {
141 2 50         EXTEND(SP, 1);
    0          
142 2 50         if (!success) XSRETURN_UNDEF;
143 2 50         mPUSHs(xs::out(strftime(LT_FORMAT, date)).detach());
    50          
    50          
144 2           XSRETURN(1);
145             }
146             }
147              
148             ptime_t timegm (SV* sec, SV* min, SV* hour, SV* mday, SV* mon, SV* year, SV* isdst = {}, TimezoneSP tz = {}) : ALIAS(timelocal=1, timeany=2, timegmn=3, timelocaln=4, timeanyn=5) {
149 19           datetime date;
150             date.sec = xs::in(sec);
151 10 50         date.min = xs::in(min);
152 10 50         date.hour = xs::in(hour);
153 10 50         date.mday = xs::in(mday);
154 10 50         date.mon = xs::in(mon);
155 10 50         date.year = xs::in(year);
156 10 50          
157             if (isdst) date.isdst = SvIV(isdst);
158 10 100         else date.isdst = -1;
    50          
    0          
159 6            
160             switch (ix) {
161 10           case 0: RETVAL = timegml(&date); break;
162 1 50         case 1: RETVAL = timelocall(&date); break;
163 5 50         case 2: RETVAL = timeanyl(&date, tz ? tz : tzlocal()); break;
164 0 0         case 3: RETVAL = timegm(&date); break;
    0          
    0          
165 2 50         case 4: RETVAL = timelocal(&date); break;
166 2 50         case 5: RETVAL = timeany(&date, tz ? tz : tzlocal()); break;
167 0 0         default: croak("not reached");
    0          
    0          
168 0           }
169              
170             if (ix >= 3) {
171 10 100         sv_setiv(sec, date.sec);
172 4 50         sv_setiv(min, date.min);
173 3 50         sv_setiv(hour, date.hour);
174 3 50         sv_setiv(mday, date.mday);
175 3 50         sv_setiv(mon, date.mon);
176 3 50         sv_setiv(year, date.year);
177 3 50         if (isdst) sv_setiv(isdst, date.isdst);
178 3 100         }
    50          
179             }
180              
181             Date* now () {
182 10           RETVAL = new Date(Date::now());
183 5 50         }
    50          
    50          
184              
185             Date* now_hires () {
186 4           RETVAL = new Date(Date::now_hires());
187 2 50         }
    50          
    50          
188              
189             Date* today () {
190 4           RETVAL = new Date(Date::today());
191 2 50         }
    50          
    50          
192              
193             ptime_t today_epoch () {
194 2           RETVAL = Date::today_epoch();
195 1 50         }
196              
197             Date* date (SV* val = {}, TimezoneSP tz = {}, int fmt = Date::InputFormat::all) {
198 604           RETVAL = new Date(sv2date(val, tz, fmt));
199 302 100         }
    50          
    50          
200              
201             Date* date_ymd (...) {
202 34           RETVAL = new Date(xs_date_ymd(&ST(0), items));
203 17 100         }
    50          
    50          
204              
205             bool range_check (Simple newval = Simple()) {
206 5 100         if (newval) Date::range_check(newval.defined() && newval.is_true());
    50          
    50          
    100          
207 5           RETVAL = Date::range_check();
208             }
209              
210             #///////////////////////////// OBJECT METHODS ///////////////////////////////////
211              
212             Date* new (SV*, SV* val = {}, TimezoneSP tz = {}, int fmt = Date::InputFormat::all) {
213 78           RETVAL = new Date(sv2date(val, tz, fmt));
214 39 100         }
    50          
    50          
215              
216             Date* new_ymd (...) {
217 24           RETVAL = new Date(xs_date_ymd(&ST(1), items - 1));
218 12 100         }
    50          
    50          
219              
220             void Date::set (SV* val = {}, TimezoneSP tz = {}, int fmt = Date::InputFormat::all) {
221 7 100         THIS->set(sv2date(val, tz, fmt));
    50          
222             }
223              
224             void Date::set_ymd (...) {
225 3 100         THIS->set(xs_date_ymd(&ST(1), items - 1));
    50          
226             }
227              
228             void Date::epoch (SV* newval = NULL) {
229 205 100         if (newval) {
230 1 50         if (SvNOK(newval)) THIS->epoch((double)SvNV(newval));
    50          
    0          
    50          
231 0 0         else THIS->epoch(xs::in(newval));
    0          
232 1           XSRETURN(1);
233             }
234 204 50         dXSTARG; XSprePUSH;
    0          
235 204 100         if (THIS->mksec()) PUSHn(THIS->epoch_mks());
    50          
    50          
    50          
236 176 50         else PUSHi(THIS->epoch());
    100          
    50          
237             }
238              
239             ptime_t Date::epoch_sec () {
240 0           RETVAL = THIS->epoch();
241 0 0         }
242              
243             int32_t Date::year (SV* newval = NULL) {
244 22 100         if (newval) THIS->year(xs::in(newval));
    50          
    50          
245 22 50         RETVAL = THIS->year();
246             }
247              
248             int32_t Date::c_year (SV* newval = NULL) : ALIAS(_year=1) {
249             PERL_UNUSED_VAR(ix);
250 3 50         if (newval) THIS->c_year(xs::in(newval));
    0          
    0          
251 3 50         RETVAL = THIS->c_year();
252             }
253              
254             int8_t Date::yr (SV* newval = NULL) {
255 3 50         if (newval) THIS->yr(xs::in(newval));
    0          
    0          
256 3 50         RETVAL = THIS->yr();
257             }
258              
259             uint8_t Date::month (SV* newval = NULL) : ALIAS(mon=1) {
260             PERL_UNUSED_VAR(ix);
261 16 50         if (newval) THIS->month(xs::in(newval));
    0          
    0          
262 16 50         RETVAL = THIS->month();
263             }
264              
265             uint8_t Date::c_month (SV* newval = NULL) : ALIAS(c_mon=1, _mon=2, _month=3) {
266             PERL_UNUSED_VAR(ix);
267 2 50         if (newval) THIS->c_month(xs::in(newval));
    0          
    0          
268 2 50         RETVAL = THIS->c_month();
269             }
270              
271             uint8_t Date::day (SV* newval = NULL) : ALIAS(mday=1, day_of_month=2) {
272             PERL_UNUSED_VAR(ix);
273 26 100         if (newval) THIS->day(xs::in(newval));
    50          
    50          
274 26 50         RETVAL = THIS->day();
275             }
276              
277             uint8_t Date::hour (SV* newval = NULL) {
278 7 50         if (newval) THIS->hour(xs::in(newval));
    0          
    0          
279 7 50         RETVAL = THIS->hour();
280             }
281              
282             uint8_t Date::min (SV* newval = NULL) : ALIAS(minute=1) {
283             PERL_UNUSED_VAR(ix);
284 8 50         if (newval) THIS->min(xs::in(newval));
    0          
    0          
285 8 50         RETVAL = THIS->min();
286             }
287              
288             uint8_t Date::sec (SV* newval = NULL) : ALIAS(second=1) {
289             PERL_UNUSED_VAR(ix);
290 8 50         if (newval) THIS->sec(xs::in(newval));
    0          
    0          
291 8 50         RETVAL = THIS->sec();
292             }
293              
294             uint32_t Date::mksec (SV* newval = NULL) {
295 8 50         if (newval) THIS->mksec(xs::in(newval));
    0          
    0          
296 8           RETVAL = THIS->mksec();
297             }
298              
299             uint8_t Date::wday (SV* newval = NULL) : ALIAS(day_of_week=1) {
300             PERL_UNUSED_VAR(ix);
301 4 50         if (newval) THIS->wday(xs::in(newval));
    0          
    0          
302 4 50         RETVAL = THIS->wday();
303             }
304              
305             uint8_t Date::c_wday (SV* newval = NULL) : ALIAS(_wday=1) {
306             PERL_UNUSED_VAR(ix);
307 2 50         if (newval) THIS->c_wday(xs::in(newval));
    0          
    0          
308 2 50         RETVAL = THIS->c_wday();
309             }
310              
311             uint8_t Date::ewday (SV* newval = NULL) {
312 2 50         if (newval) THIS->ewday(xs::in(newval));
    0          
    0          
313 2 50         RETVAL = THIS->ewday();
314             }
315              
316             uint16_t Date::yday (SV* newval = NULL) : ALIAS(day_of_year=1) {
317             PERL_UNUSED_VAR(ix);
318 2 50         if (newval) THIS->yday(xs::in(newval));
    0          
    0          
319 2 50         RETVAL = THIS->yday();
320             }
321              
322             uint16_t Date::c_yday (SV* newval = NULL) : ALIAS(_yday=1) {
323             PERL_UNUSED_VAR(ix);
324 1 50         if (newval) THIS->c_yday(xs::in(newval));
    0          
    0          
325 1 50         RETVAL = THIS->c_yday();
326             }
327              
328             bool Date::isdst () : ALIAS(daylight_savings=1) {
329             PERL_UNUSED_VAR(ix);
330 6 50         RETVAL = THIS->isdst();
331             }
332              
333             string Date::to_string (int format = (int)Date::Format::iso) {
334 47 100         if (THIS->error()) XSRETURN_UNDEF;
335 45 50         RETVAL = THIS->to_string((Date::Format)format);
    50          
336             }
337              
338             string Date::_op_str (...) {
339 8 50         if (THIS->error()) XSRETURN_UNDEF;
340 8 50         RETVAL = THIS->to_string();
    50          
341             }
342              
343             #// $date->strftime($format)
344             #// Date::strftime($format, $epoch, [$timezone])
345             #// Date::strftime($format, $sec, $min, $hour, $mday, $mon, $year, [$isdst], [$timezone])
346             string strftime (Sv arg0, SV* arg1, ...) {
347 11 100         if (items == 2 && arg0.is_object_ref()) {
    100          
    100          
348 1 50         auto THIS = xs::in(arg0);
349 1 50         RETVAL = THIS->strftime(xs::in(arg1));
    50          
    50          
350             }
351             else {
352 10 50         string_view format = xs::in(arg0);
353 10           TimezoneSP tz;
354             datetime date;
355 10           date.isdst = -1;
356            
357 10           switch (items) {
358 2 50         case 9: tz = xs::in(ST(8)); // fall through
359 2 50         case 8: date.isdst = SvIV(ST(7)); // fall through
    0          
360             case 7:
361 5 50         date.sec = xs::in(ST(1));
362 5 50         date.min = xs::in(ST(2));
363 5 50         date.hour = xs::in(ST(3));
364 5 50         date.mday = xs::in(ST(4));
365 5 50         date.mon = xs::in(ST(5));
366 5 50         date.year = xs::in(ST(6));
367 5 100         timeany(&date, tz ? tz : tzlocal());
    50          
    50          
368 5           break;
369 2 50         case 3: tz = xs::in(ST(2)); // fall through
370             case 2: {
371 5 50         auto epoch = xs::in(arg1);
372 5 100         if (!anytime(epoch, &date, tz ? tz : tzlocal())) XSRETURN_UNDEF;
    50          
    50          
    50          
373 5           break;
374             }
375             default:
376 0           throw "wrong number of arguments";
377             }
378 10 50         RETVAL = strftime(format, date);
    50          
    50          
379             }
380             }
381              
382             bool Date::to_bool (...) {
383 3 50         RETVAL = THIS->error() ? false : true;
384             }
385              
386             ptime_t Date::to_number (...) {
387 14           RETVAL = THIS->error() ? 0 : THIS->epoch();
388 7 100         }
    50          
389              
390             string_view Date::month_name () : ALIAS(monname=1, monthname=2) {
391             PERL_UNUSED_VAR(ix);
392 0 0         RETVAL = THIS->month_name();
393             }
394              
395 0 0         string_view Date::month_sname ()
396              
397             string_view Date::wday_name () : ALIAS(day_of_weekname=1, wdayname=2) {
398             PERL_UNUSED_VAR(ix);
399 0 0         RETVAL = THIS->wday_name();
400             }
401              
402 0 0         string_view Date::wday_sname ()
403              
404 3 50         int Date::gmtoff ()
405              
406 101 50         string_view Date::tzabbr ()
407              
408             #// Date::tzname()
409             #// $date->tzname()
410             string tzname (Date* date = nullptr) {
411 31 100         auto& zone = date ? date->timezone() : tzlocal();
    50          
    50          
412 31 50         RETVAL = zone->name;
413             }
414              
415             bool Date::tzlocal () {
416 15 50         RETVAL = THIS->timezone()->is_local;
417             }
418              
419             TimezoneSP Date::timezone (TimezoneSP newzone = {}) : ALIAS(tz=1, zone=2) {
420 34 100         if (newzone) {
421 17 100         THIS->timezone(newzone);
422 2 50         XSRETURN_UNDEF;
423 2           }
424             RETVAL = THIS->timezone();
425 15 50         PERL_UNUSED_VAR(ix);
    50          
426             }
427              
428             void Date::to_timezone (TimezoneSP newzone) : ALIAS(to_tz=1, to_zone=2) {
429 3 50         THIS->to_timezone(newzone);
430             PERL_UNUSED_VAR(ix);
431             }
432              
433             void Date::array () {
434 2 50         auto cnt = THIS->mksec() ? 7 : 6;
435 2 50         EXTEND(SP, cnt);
    50          
    0          
436 2 50         mPUSHi(THIS->year());
    50          
    50          
437 2 50         mPUSHu(THIS->month());
    50          
    50          
438 2 50         mPUSHu(THIS->day());
    50          
    50          
439 2 50         mPUSHu(THIS->hour());
    50          
    50          
440 2 50         mPUSHu(THIS->min());
    50          
    50          
441 2 50         mPUSHu(THIS->sec());
    50          
    50          
442 2 50         if (THIS->mksec()) mPUSHu(THIS->mksec());
    0          
    0          
443 2           XSRETURN(cnt);
444             }
445              
446             void Date::struct () {
447 1 50         EXTEND(SP, 9);
448 1           mPUSHu(THIS->sec());
449 1           mPUSHu(THIS->min());
450 1           mPUSHu(THIS->hour());
451 1           mPUSHu(THIS->day());
452 1           mPUSHu(THIS->c_month());
453 1           mPUSHi(THIS->c_year());
454 1           mPUSHu(THIS->c_wday());
455 1           mPUSHu(THIS->c_yday());
456 1 50         mPUSHu(THIS->isdst() ? 1 : 0);
457 1           XSRETURN(9);
458             }
459              
460             Date* Date::clone (...) {
461 36           if (items > 1) {
462 18 100         ptime_t vals[] = {-1, -1, -1, -1, -1, -1, -1, -1};
463 12           auto tz = list2vals(&ST(1), items - 1, vals);
464 24 50         RETVAL = new Date(THIS->clone(vals[0], vals[1], vals[2], vals[3], vals[4], vals[5], vals[6], vals[7], tz));
465 12 50         }
    50          
    50          
466             else RETVAL = new Date(*THIS);
467 6 50        
    50          
468             if (RETVAL->error() && is_strict_mode()) {
469 18 100         auto err = RETVAL->error();
    50          
    50          
    50          
    100          
    0          
470 1           delete RETVAL;
471 1 50         throw xs::out(err);
472 1 50         }
473            
474             PROTO = Object(ST(0)).stash();
475 17 50         }
    50          
476              
477             SV* Date::month_begin () {
478 1           THIS->month_begin();
479 1           XSRETURN(1);
480             }
481              
482             Date* Date::month_begin_new () {
483 8           RETVAL = new Date(THIS->month_begin_new());
484 4 50         PROTO = Object(ST(0)).stash();
    50          
    50          
485 4 50         }
    50          
486              
487             SV* Date::month_end () {
488 1           THIS->month_end();
489 1           XSRETURN(1);
490             }
491              
492             Date* Date::month_end_new () {
493 8           RETVAL = new Date(THIS->month_end_new());
494 4 50         PROTO = Object(ST(0)).stash();
    50          
    50          
495 4 50         }
    50          
496              
497             int Date::days_in_month () {
498 4 50         RETVAL = THIS->days_in_month();
499             }
500              
501 11 50         uint8_t Date::week_of_month ()
502              
503 8 50         uint8_t Date::weeks_in_year ()
504              
505             void Date::week_of_year () {
506 16 50         auto info = THIS->week_of_year();
507 16           int rcnt = 1;
508 16 50         if (GIMME_V == G_ARRAY) {
    0          
    100          
509 8 50         mXPUSHi(info.year);
    0          
    50          
    50          
510 8           rcnt = 2;
511             }
512 16 50         mXPUSHu(info.week);
    0          
    50          
    50          
513 16           XSRETURN(rcnt);
514             }
515              
516 248           std::error_code Date::error ()
517 124            
518             SV* Date::truncate () {
519 1           THIS->truncate();
520 1           XSRETURN(1);
521             }
522              
523             Date* Date::truncated () {
524 2           RETVAL = new Date(THIS->truncated());
525 1 50         PROTO = Object(ST(0)).stash();
    50          
    50          
526 1 50         }
    50          
527              
528             int Date::compare (Sv arg, bool reverse = false) {
529 144 100         if (arg.is_ref() && !arg.is_object_ref()) XSRETURN_IV(-1); // avoid exception in typemap for wrong types
    100          
    100          
    50          
    50          
530 142 50         RETVAL = THIS->compare(sv2date(arg, THIS->timezone()));
    100          
    50          
531 140 100         if (reverse) RETVAL = -RETVAL;
532 140 100         if (RETVAL < 0) RETVAL = -1;
533 120 100         else if (RETVAL > 0) RETVAL = 1;
534             }
535              
536             Date* Date::sum (Sv arg, ...) {
537 30           RETVAL = new Date(*THIS + sv2daterel(arg));
538 15 100         PROTO = Object(ST(0)).stash();
    50          
    50          
    50          
539 13 50         }
    50          
540              
541             SV* Date::add (Sv arg, ...) {
542 6 100         *THIS += sv2daterel(arg);
    50          
543 5 50         XSRETURN(1);
544             }
545              
546             Sv Date::difference (Sv arg, bool reverse = false) {
547 5 100         bool is_date = arg.is_object_ref() && Object(arg).stash().name() == "Date";
    50          
    50          
    50          
    100          
    100          
    100          
    0          
    0          
548 5 100         if (is_date) RETVAL = xs::out(new DateRel(*xs::in(arg), *THIS));
    50          
    50          
    50          
    50          
549 4 50         else if (reverse) throw "wrong date operation";
550 4 50         else RETVAL = xs::out(new Date(*THIS - sv2daterel(arg)), Object(ST(0)).stash());
    50          
    100          
    50          
    50          
    50          
    50          
551             }
552              
553             SV* Date::subtract (Sv arg, ...) {
554 3 100         *THIS -= sv2daterel(arg);
    50          
555 2 50         XSRETURN(1);
556             }
557              
558             void __assign_stub (...) {
559 48 50         if (!items) throw "should not happen";
560 48           XSRETURN(1);
561             }