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