File Coverage

DateTime.xs
Criterion Covered Total %
statement 103 107 96.2
branch 83 134 61.9
condition n/a
subroutine n/a
pod n/a
total 186 241 77.1


line stmt bran cond sub pod time code
1             #include "EXTERN.h"
2             #include "perl.h"
3             #include "XSUB.h"
4             #include "ppport.h"
5              
6             #include <stdlib.h>
7              
8             /* This file is generated by tools/leap_seconds_header.pl */
9             #include "leap_seconds.h"
10              
11             # if defined(WIN32)
12             # if PERL_VERSION_GE(5, 22, 0)
13             # define dt_isfinite Perl_isfinite
14             # endif
15             # else
16             # define dt_isfinite Perl_isfinite
17             # endif
18              
19             #define DAYS_PER_400_YEARS 146097
20             #define DAYS_PER_4_YEARS 1461
21             #define MARCH_1 306
22              
23             #define SECONDS_PER_DAY 86400
24              
25             const int PREVIOUS_MONTH_DOY[12] = { 0,
26             31,
27             59,
28             90,
29             120,
30             151,
31             181,
32             212,
33             243,
34             273,
35             304,
36             334 };
37              
38             const int PREVIOUS_MONTH_DOLY[12] = { 0,
39             31,
40             60,
41             91,
42             121,
43             152,
44             182,
45             213,
46             244,
47             274,
48             305,
49             335 };
50              
51              
52             IV
53 97841           _real_is_leap_year(IV y) {
54             /* See http://www.perlmonks.org/?node_id=274247 for where this silliness
55             comes from */
56 97841 100         return (y % 4) ? 0 : (y % 100) ? 1 : (y % 400) ? 0 : 1;
    100          
    100          
57             }
58              
59              
60             MODULE = DateTime PACKAGE = DateTime
61              
62             PROTOTYPES: ENABLE
63              
64             void
65             _rd2ymd(self, d, extra = 0)
66             IV d;
67             IV extra;
68              
69             PREINIT:
70             IV y, m;
71             IV c;
72             IV quarter;
73 320633           IV yadj = 0;
74             IV dow, doy, doq;
75             IV rd_days;
76              
77             PPCODE:
78 320633           rd_days = d;
79              
80 320633           d += MARCH_1;
81              
82 320633 100         if (d <= 0) {
83 115721           yadj = -1 * (((-1 * d) / DAYS_PER_400_YEARS) + 1);
84 115721           d -= yadj * DAYS_PER_400_YEARS;
85             }
86              
87             /* c is century */
88 320633           c = ((d * 4) - 1) / DAYS_PER_400_YEARS;
89 320633           d -= c * DAYS_PER_400_YEARS / 4;
90 320633           y = ((d * 4) - 1) / DAYS_PER_4_YEARS;
91 320633           d -= y * DAYS_PER_4_YEARS / 4;
92 320633           m = ((d * 12) + 1093) / 367;
93 320633           d -= ((m * 367) - 1094) / 12;
94 320633           y += (c * 100) + (yadj * 400);
95              
96 320633 100         if (m > 12) {
97 39717           ++y;
98 39717           m -= 12;
99             }
100              
101 320633 100         EXTEND(SP, extra ? 7 : 3);
    50          
    0          
102 320633           mPUSHi(y);
103 320633           mPUSHi(m);
104 320633           mPUSHi(d);
105              
106 320633 100         if (extra) {
107 57707           quarter = ( ( 1.0 / 3.1 ) * m ) + 1;
108              
109 57707           dow = rd_days % 7;
110 57707 100         if ( dow <= 0 ) {
111 25433           dow += 7;
112             }
113              
114 57707           mPUSHi(dow);
115              
116 57707 100         if (_real_is_leap_year(y)) {
117 14195           doy = PREVIOUS_MONTH_DOLY[m - 1] + d;
118 14195           doq = doy - PREVIOUS_MONTH_DOLY[ (3 * quarter) - 3 ];
119             } else {
120 43512           doy = PREVIOUS_MONTH_DOY[m - 1] + d;
121 43512           doq = doy - PREVIOUS_MONTH_DOY[ (3 * quarter ) - 3 ];
122             }
123              
124 57707           mPUSHi(doy);
125 57707           mPUSHi(quarter);
126 57707           mPUSHi(doq);
127             }
128              
129             void
130             _ymd2rd(self, y, m, d)
131             IV y;
132             IV m;
133             IV d;
134              
135             PREINIT:
136             IV adj;
137              
138             PPCODE:
139 288602 100         if (m <= 2) {
140 39394           adj = (14 - m) / 12;
141 39394           y -= adj;
142 39394           m += 12 * adj;
143 249208 100         } else if (m > 14) {
144 409           adj = (m - 3) / 12;
145 409           y += adj;
146 409           m -= 12 * adj;
147             }
148              
149 288602 100         if (y < 0) {
150 115724           adj = (399 - y) / 400;
151 115724           d -= DAYS_PER_400_YEARS * adj;
152 115724           y += 400 * adj;
153             }
154              
155 577204           d += (m * 367 - 1094) /
156 288602           12 + y % 100 * DAYS_PER_4_YEARS /
157 288602           4 + (y / 100 * 36524 + y / 400) - MARCH_1;
158              
159 288602 50         EXTEND(SP, 1);
160 288602           mPUSHi(d);
161              
162             void
163             _seconds_as_components(self, secs, utc_secs = 0, secs_modifier = 0)
164             IV secs;
165             IV utc_secs;
166             IV secs_modifier;
167              
168             PREINIT:
169             IV h, m, s;
170              
171             PPCODE:
172 89652           secs -= secs_modifier;
173              
174 89652           h = secs / 3600;
175 89652           secs -= h * 3600;
176              
177 89652           m = secs / 60;
178              
179 89652           s = secs - (m * 60);
180              
181 89652 100         if (utc_secs >= SECONDS_PER_DAY) {
182 53 50         if (utc_secs >= SECONDS_PER_DAY + 1) {
183             /* If we just use %d and the IV, we get a warning that IV is
184             not an int. */
185 0 0         croak("Invalid UTC RD seconds value: %s", SvPV_nolen(newSViv(utc_secs)));
186             }
187              
188 53           s += (utc_secs - SECONDS_PER_DAY) + 60;
189 53           m = 59;
190 53           h--;
191              
192 53 100         if (h < 0) {
193 1           h = 23;
194             }
195             }
196              
197 89652 50         EXTEND(SP, 3);
198 89652           mPUSHi(h);
199 89652           mPUSHi(m);
200 89652           mPUSHi(s);
201              
202             #ifdef dt_isfinite
203             void
204             _normalize_tai_seconds(self, days, secs)
205             SV* days;
206             SV* secs;
207              
208             PPCODE:
209 113544 100         if (dt_isfinite(SvNV(days)) && dt_isfinite(SvNV(secs))) {
    100          
    50          
    50          
210 113448 50         IV d = SvIV(days);
211 113448 50         IV s = SvIV(secs);
212             IV adj;
213              
214 113448 100         if (s < 0) {
215 56           adj = (s - (SECONDS_PER_DAY - 1)) / SECONDS_PER_DAY;
216             } else {
217 113392           adj = s / SECONDS_PER_DAY;
218             }
219              
220 113448           d += adj;
221 113448           s -= adj * SECONDS_PER_DAY;
222              
223 113448           sv_setiv(days, (IV) d);
224 113448           sv_setiv(secs, (IV) s);
225             }
226              
227             void
228             _normalize_leap_seconds(self, days, secs)
229             SV* days;
230             SV* secs;
231              
232             PPCODE:
233 75 50         if (dt_isfinite(SvNV(days)) && dt_isfinite(SvNV(secs))) {
    50          
    50          
    50          
234 75 50         IV d = SvIV(days);
235 75 50         IV s = SvIV(secs);
236             IV day_length;
237              
238 499 100         while (s < 0) {
239 424           SET_DAY_LENGTH(d - 1, day_length);
240              
241 424           s += day_length;
242 424           d--;
243             }
244              
245 75           SET_DAY_LENGTH(d, day_length);
246              
247 584457 100         while (s > day_length - 1) {
248 584382           s -= day_length;
249 584382           d++;
250 584382           SET_DAY_LENGTH(d, day_length);
251             }
252              
253 75           sv_setiv(days, (IV) d);
254 75           sv_setiv(secs, (IV) s);
255             }
256              
257             #endif /* ifdef dt_isfinite */
258              
259             void
260             _time_as_seconds(self, h, m, s)
261             IV h;
262             IV m;
263             IV s;
264              
265             PPCODE:
266 57554 50         EXTEND(SP, 1);
267 57554           mPUSHi(h * 3600 + m * 60 + s);
268              
269             void
270             _is_leap_year(self, y)
271             IV y;
272              
273             PPCODE:
274 40134 50         EXTEND(SP, 1);
275 40134           mPUSHi(_real_is_leap_year(y));
276              
277             void
278             _day_length(self, utc_rd)
279             IV utc_rd;
280              
281             PPCODE:
282             IV day_length;
283 151           SET_DAY_LENGTH(utc_rd, day_length);
284              
285 151 50         EXTEND(SP, 1);
286 151           mPUSHi(day_length);
287              
288             void
289             _day_has_leap_second(self, utc_rd)
290             IV utc_rd;
291              
292             PPCODE:
293             IV day_length;
294 0           SET_DAY_LENGTH(utc_rd, day_length);
295              
296 0 0         EXTEND(SP, 1);
297 0 0         mPUSHi(day_length > 86400 ? 1 : 0);
298              
299             void
300             _accumulated_leap_seconds(self, utc_rd)
301             IV utc_rd;
302              
303             PPCODE:
304             IV leap_seconds;
305 14 50         SET_LEAP_SECONDS(utc_rd, leap_seconds);
    50          
    50          
    50          
    50          
    100          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
    50          
306              
307 14 50         EXTEND(SP, 1);
308 14           mPUSHi(leap_seconds);