File Coverage

Time.xs
Criterion Covered Total %
statement 110 121 90.9
branch 86 176 48.8
condition n/a
subroutine n/a
pod n/a
total 196 297 65.9


line stmt bran cond sub pod time code
1             #include
2             #include
3             using namespace panda::time;
4             using panda::string;
5             using xs::sv2string;
6              
7             #ifdef _WIN32
8             # define SYSTIMEGM(x) _mkgmtime(x)
9             # define SYSTIMELOCAL(x) mktime(x)
10             # define LT_FORMAT "%a %b %d %H:%M:%S %Y"
11             #else
12             # define SYSTIMEGM(x) timegm(x)
13             # define SYSTIMELOCAL(x) timelocal(x)
14             # define LT_FORMAT "%a %b %e %H:%M:%S %Y"
15             #endif
16              
17             #if IVSIZE >= 8
18             # define SvMIV(x) SvIV(x)
19             # define SvMUV(x) SvUV(x)
20             #else
21             # define SvMIV(x) ((int64_t)SvNV(x))
22             # define SvMUV(x) ((uint64_t)SvNV(x))
23             #endif
24              
25 102082           SV* export_transition (pTHX_ Timezone::Transition& trans, bool is_past) {
26 102082           HV* hv = newHV();
27 102082           hv_store(hv, "offset", 6, newSViv(trans.offset), 0);
28 102082           hv_store(hv, "abbrev", 6, newSVpv(trans.abbrev, 0), 0);
29 102082 100         if (!is_past) {
30 100829           hv_store(hv, "start", 5, newSViv(trans.start), 0);
31 100829           hv_store(hv, "isdst", 5, newSVuv(trans.isdst), 0);
32 100829           hv_store(hv, "gmt_offset", 10, newSViv(trans.gmt_offset), 0);
33 100829           hv_store(hv, "leap_corr", 9, newSViv(trans.leap_corr), 0);
34 100829           hv_store(hv, "leap_delta", 10, newSViv(trans.leap_delta), 0);
35             }
36 102082           return newRV_noinc((SV*)hv);
37             }
38              
39 1253           HV* export_timezone (pTHX_ const Timezone* zone) {
40 1253           HV* ret = newHV();
41            
42 1253           hv_store(ret, "name", 4, newSVpvn(zone->name.data(), zone->name.length()), 0);
43 1253 100         hv_store(ret, "is_local", 8, newSViv(zone->is_local ? 1 : 0), 0);
44            
45 1253           HV* future = newHV();
46 1253 100         hv_store(future, "hasdst", 6, newSVuv(zone->future.hasdst ? 1 : 0), 0);
47            
48 1253           HV* outer = newHV();
49 1253           hv_store(outer, "abbrev", 6, newSVpv(zone->future.outer.abbrev, 0), 0);
50 1253           hv_store(outer, "offset", 6, newSViv(zone->future.outer.offset), 0);
51 1253           hv_store(outer, "gmt_offset", 10, newSViv(zone->future.outer.gmt_offset), 0);
52 1253           hv_store(outer, "isdst", 5, newSViv(zone->future.outer.isdst), 0);
53 1253           hv_store(future, "outer", 5, newRV_noinc((SV*) outer), 0);
54            
55 1253 100         if (zone->future.hasdst) {
56 450           HV* inner = newHV();
57 450           hv_store(inner, "abbrev", 6, newSVpv(zone->future.inner.abbrev, 0), 0);
58 450           hv_store(inner, "offset", 6, newSViv(zone->future.inner.offset), 0);
59 450           hv_store(inner, "gmt_offset", 10, newSViv(zone->future.inner.gmt_offset), 0);
60 450           hv_store(inner, "isdst", 5, newSViv(zone->future.inner.isdst), 0);
61            
62 450           HV* outer_end = newHV();
63 450           hv_store(outer_end, "mon", 3, newSVuv(zone->future.outer.end.mon), 0);
64 450           hv_store(outer_end, "week", 4, newSVuv(zone->future.outer.end.yday), 0);
65 450           hv_store(outer_end, "day", 3, newSVuv(zone->future.outer.end.wday), 0);
66 450           hv_store(outer_end, "hour", 4, newSViv(zone->future.outer.end.hour), 0);
67 450           hv_store(outer_end, "min", 3, newSViv(zone->future.outer.end.min), 0);
68 450           hv_store(outer_end, "sec", 3, newSViv(zone->future.outer.end.sec), 0);
69 450           hv_store(outer, "end", 3, newRV_noinc((SV*) outer_end), 0);
70            
71 450           HV* inner_end = newHV();
72 450           hv_store(inner_end, "mon", 3, newSVuv(zone->future.inner.end.mon), 0);
73 450           hv_store(inner_end, "week", 4, newSVuv(zone->future.inner.end.yday), 0);
74 450           hv_store(inner_end, "day", 3, newSVuv(zone->future.inner.end.wday), 0);
75 450           hv_store(inner_end, "hour", 4, newSViv(zone->future.inner.end.hour), 0);
76 450           hv_store(inner_end, "min", 3, newSViv(zone->future.inner.end.min), 0);
77 450           hv_store(inner_end, "sec", 3, newSViv(zone->future.inner.end.sec), 0);
78 450           hv_store(inner, "end", 3, newRV_noinc((SV*) inner_end), 0);
79            
80 450           hv_store(future, "inner", 5, newRV_noinc((SV*) inner), 0);
81             }
82 1253           hv_store(ret, "future", 6, newRV_noinc((SV*) future), 0);
83            
84 1253           AV* trans = newAV();
85 102082 100         for (uint32_t i = 0; i < zone->trans_cnt; i++) av_push(trans, export_transition(aTHX_ zone->trans[i], false));
86 1253           hv_store(ret, "transitions", 11, newRV_noinc((SV*) trans), 0);
87            
88 1253           hv_store(ret, "past", 4, export_transition(aTHX_ zone->trans[0], true), 0);
89            
90 1253           return ret;
91             }
92              
93             MODULE = Panda::Time PACKAGE = Panda::Time
94             PROTOTYPES: DISABLE
95              
96             void tzset (string_view newzone = string_view()) {
97 102 50         panda::time::tzset(newzone);
98             }
99              
100             string tzdir (SV* newdirSV = NULL) {
101 21 100         if (newdirSV) {
102 36 50         string newdir = SvOK(newdirSV) ? sv2string(aTHX_ newdirSV) : string("");
    0          
    0          
    50          
103 18 50         if (tzdir(newdir)) RETVAL = "1";
    50          
    50          
104 18 50         else XSRETURN_UNDEF;
105             } else
106 3 50         RETVAL = tzdir();
    50          
107             }
108              
109             string tzsysdir () {
110 18 50         RETVAL = tzsysdir();
    50          
111             }
112            
113             void gmtime (SV* epochSV = NULL) : ALIAS(localtime=1) {
114             ptime_t epoch;
115 23756 50         if (epochSV) epoch = (ptime_t) SvMIV(epochSV);
    100          
    50          
116 0           else epoch = (ptime_t) time(NULL);
117            
118             datetime date;
119 23756 100         if (ix == 0) gmtime(epoch, &date);
    50          
120 19033 50         else localtime(epoch, &date);
121            
122 23756 50         if (GIMME_V == G_ARRAY) {
    0          
    100          
123 23747 50         EXTEND(SP, 9);
    0          
124 23747 50         EXTEND_MORTAL(9);
    0          
125 23747 50         mPUSHu(date.sec);
    50          
126 23747 50         mPUSHu(date.min);
    50          
127 23747 50         mPUSHu(date.hour);
    50          
128 23747 50         mPUSHu(date.mday);
    50          
129 23747 50         mPUSHu(date.mon);
    50          
130 23747 50         mPUSHi(date.year);
    50          
131 23747 50         mPUSHu(date.wday);
    50          
132 23747 50         mPUSHu(date.yday);
    50          
133 23747 50         mPUSHu(date.isdst);
    50          
134 23747           XSRETURN(9);
135             } else {
136 9 50         EXTEND(SP, 1);
    0          
137 9 50         SV* ret = newSV(1000);
138 9           SvPOK_on(ret);
139 9           char* str = SvPVX(ret);
140 9 50         size_t strlen = strftime(str, 1000, LT_FORMAT, &date);
141 9           SvCUR_set(ret, strlen);
142 9 50         mPUSHs(ret);
143 23756           XSRETURN(1);
144             }
145             }
146              
147             ptime_t timegm (SV* sec, SV* min, SV* hour, SV* mday, SV* mon, SV* year, SV* isdst = NULL) : ALIAS(timelocal=1, timegmn=2, timelocaln=3) {
148             datetime date;
149 23826 50         date.sec = SvMIV(sec);
    0          
150 23826 50         date.min = SvMIV(min);
    0          
151 23826 50         date.hour = SvMIV(hour);
    0          
152 23826 50         date.mday = SvMIV(mday);
    0          
153 23826 50         date.mon = SvMIV(mon);
    0          
154 23826 50         date.year = SvMIV(year);
    0          
155            
156 23826 100         if (isdst) date.isdst = SvIV(isdst);
    50          
    0          
157 33           else date.isdst = -1;
158            
159 23826           switch (ix) {
160             case 0:
161 4723 50         RETVAL = timegml(&date);
162 4723           break;
163             case 1:
164 19068 50         RETVAL = timelocall(&date);
165 19068           break;
166             case 2:
167 5 50         RETVAL = timegm(&date);
168 5           break;
169             case 3:
170 30 50         RETVAL = timelocal(&date);
171 30           break;
172 0           default: croak("not reached");
173             }
174            
175 23826 100         if (ix & 2) {
176 35 50         sv_setiv(sec, date.sec);
177 34 50         sv_setiv(min, date.min);
178 34 50         sv_setiv(hour, date.hour);
179 34 50         sv_setiv(mday, date.mday);
180 34 50         sv_setiv(mon, date.mon);
181 34 50         sv_setiv(year, date.year);
182 34 100         if (isdst) sv_setiv(isdst, date.isdst);
    50          
183             }
184             }
185              
186             time_t systimegm (int64_t sec, int64_t min, int64_t hour, int64_t mday, int64_t mon, int64_t year, int64_t isdst = -1) : ALIAS(systimelocal=1) {
187             struct tm date;
188 0           date.tm_sec = sec;
189 0           date.tm_min = min;
190 0           date.tm_hour = hour;
191 0           date.tm_mday = mday;
192 0           date.tm_mon = mon;
193 0           date.tm_year = year;
194 0           date.tm_isdst = isdst;
195 0 0         if (ix == 0) RETVAL = SYSTIMEGM(&date);
196 0           else RETVAL = SYSTIMELOCAL(&date);
197             }
198              
199             HV* tzget (string_view zonename = string_view()) {
200 1253 50         RETVAL = export_timezone(aTHX_ tzget(zonename));
    50          
201             }
202              
203             string tzname () {
204 15 50         RETVAL = tzlocal()->name;
    50          
205             }
206              
207             #ifdef TEST_FULL
208              
209             INCLUDE: test.xsi
210              
211             #endif