File Coverage

src/dt_core.c
Criterion Covered Total %
statement 92 106 86.7
branch 75 114 65.7
condition n/a
subroutine n/a
pod n/a
total 167 220 75.9


line stmt bran cond sub pod time code
1             /*
2             * Copyright (c) 2012-2014 Christian Hansen
3             *
4             * All rights reserved.
5             *
6             * Redistribution and use in source and binary forms, with or without
7             * modification, are permitted provided that the following conditions are met:
8             *
9             * 1. Redistributions of source code must retain the above copyright notice, this
10             * list of conditions and the following disclaimer.
11             * 2. Redistributions in binary form must reproduce the above copyright notice,
12             * this list of conditions and the following disclaimer in the documentation
13             * and/or other materials provided with the distribution.
14             *
15             * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
16             * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
17             * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
18             * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR
19             * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
20             * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
21             * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
22             * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23             * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
24             * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25             */
26             #include
27             #include "dt_core.h"
28              
29             #define LEAP_YEAR(y) \
30             (((y) & 3) == 0 && ((y) % 100 != 0 || (y) % 400 == 0))
31              
32             #define DAYS_IN_YEAR(y) \
33             (LEAP_YEAR(y) ? 366 : 365)
34              
35             static const int days_preceding_month[2][13] = {
36             { 0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334 },
37             { 0, 0, 31, 60, 91, 121, 152, 182, 213, 244, 274, 305, 335 }
38             };
39              
40             static const int days_preceding_quarter[2][5] = {
41             { 0, 0, 90, 181, 273 },
42             { 0, 0, 91, 182, 274 }
43             };
44              
45             dt_t
46 9887           dt_from_rdn(int n) {
47 9887           return n + DT_EPOCH_OFFSET;
48             }
49              
50             dt_t
51 1143           dt_from_yd(int y, int d) {
52 1143           y--;
53 1143 50         if (y < 0) {
54 0           const int n400 = 1 - y/400;
55 0           y += n400 * 400;
56 0           d -= n400 * 146097;
57             }
58 1143           return 365 * y + y/4 - y/100 + y/400 + d + DT_EPOCH_OFFSET;
59             }
60              
61             dt_t
62 641           dt_from_ymd(int y, int m, int d) {
63 641 100         if (m < 1 || m > 12) {
    100          
64 79           y += m / 12;
65 79           m %= 12;
66 79 100         if (m < 1)
67 58           y--, m += 12;
68             }
69 641 50         assert(m >= 1);
70 641 50         assert(m <= 12);
71 641 100         return dt_from_yd(y, days_preceding_month[LEAP_YEAR(y)][m] + d);
    100          
    100          
72             }
73              
74             dt_t
75 111           dt_from_yqd(int y, int q, int d) {
76 111 50         if (q < 1 || q > 4) {
    100          
77 3           y += q / 4;
78 3           q %= 4;
79 3 50         if (q < 1)
80 0           y--, q += 4;
81             }
82 111 50         assert(q >= 1);
83 111 50         assert(q <= 4);
84 111 100         return dt_from_yd(y, days_preceding_quarter[LEAP_YEAR(y)][q] + d);
    50          
    0          
85             }
86              
87             dt_t
88 9           dt_from_ywd(int y, int w, int d) {
89             dt_t dt;
90              
91 9           dt = dt_from_yd(y, 4);
92 9           dt -= dt_dow(dt);
93 9           dt += w * 7 + d - 7;
94 9           return dt;
95             }
96              
97              
98             #ifndef DT_NO_SHORTCUTS
99             static const dt_t DT1901 = 693961 + DT_EPOCH_OFFSET; /* 1901-01-01 */
100             static const dt_t DT2099 = 766644 + DT_EPOCH_OFFSET; /* 2099-12-31 */
101             #endif
102              
103             void
104 9603           dt_to_yd(dt_t d, int *yp, int *dp) {
105             int y, n100, n1;
106              
107 9603           y = 0;
108             #ifndef DT_NO_SHORTCUTS
109             /* Shortcut dates between the years 1901-2099 inclusive */
110 9603 100         if (d >= DT1901 && d <= DT2099) {
    100          
111 8278           d -= DT1901 - 1;
112 8278           y += (4 * d - 1) / 1461;
113 8278           d -= (1461 * y) / 4;
114 8278           y += 1901;
115             }
116             else
117             #endif
118             {
119 1325           d -= DT_EPOCH_OFFSET;
120 1325 50         if (d < 1) {
121 0           const int n400 = 1 - d/146097;
122 0           y -= n400 * 400;
123 0           d += n400 * 146097;
124             }
125 1325           d--;
126 1325           y += 400 * (d / 146097);
127 1325           d %= 146097;
128              
129 1325           n100 = d / 36524;
130 1325           y += 100 * n100;
131 1325           d %= 36524;
132              
133 1325           y += 4 * (d / 1461);
134 1325           d %= 1461;
135              
136 1325           n1 = d / 365;
137 1325           y += n1;
138 1325           d %= 365;
139              
140 1325 50         if (n100 == 4 || n1 == 4)
    50          
141 0           d = 366;
142             else
143 1325           y++, d++;
144             }
145 9603 100         if (yp) *yp = y;
146 9603 100         if (dp) *dp = (int)d;
147 9603           }
148              
149             void
150 7237           dt_to_ymd(dt_t dt, int *yp, int *mp, int *dp) {
151             int y, doy, m, l;
152              
153 7237           dt_to_yd(dt, &y, &doy);
154 7237 100         l = LEAP_YEAR(y);
    100          
    100          
155 7237 100         m = doy < 32 ? 1 : 1 + (5 * (doy - 59 - l) + 303) / 153;
156              
157 7237 50         assert(m >= 1);
158 7237 50         assert(m <= 12);
159              
160 7237 100         if (yp) *yp = y;
161 7237 100         if (mp) *mp = m;
162 7237 100         if (dp) *dp = doy - days_preceding_month[l][m];
163 7237           }
164              
165             void
166 221           dt_to_yqd(dt_t dt, int *yp, int *qp, int *dp) {
167             int y, doy, q, l;
168              
169 221           dt_to_yd(dt, &y, &doy);
170 221 100         l = LEAP_YEAR(y);
    50          
    0          
171 221 100         q = doy < 91 ? 1 : 1 + (5 * (doy - 59 - l) + 303) / 459;
172              
173 221 50         assert(q >= 1);
174 221 50         assert(q <= 4);
175              
176 221 100         if (yp) *yp = y;
177 221 100         if (qp) *qp = q;
178 221 100         if (dp) *dp = doy - days_preceding_quarter[l][q];
179 221           }
180              
181             void
182 48           dt_to_ywd(dt_t dt, int *yp, int *wp, int *dp) {
183             int y, doy, dow;
184              
185 48           dt_to_yd(dt, &y, &doy);
186 48           dow = dt_dow(dt);
187 48           doy = doy + 4 - dow;
188 48 50         if (doy < 1) {
189 0           y--;
190 0 0         doy += DAYS_IN_YEAR(y);
    0          
    0          
191             }
192 48 50         else if (doy > 365) {
193 0 0         const int diy = DAYS_IN_YEAR(y);
    0          
    0          
194 0 0         if (doy > diy) {
195 0           doy -= diy;
196 0           y++;
197             }
198             }
199 48 100         if (yp) *yp = y;
200 48 100         if (wp) *wp = (doy + 6) / 7;
201 48 50         if (dp) *dp = dow;
202 48           }
203              
204             int
205 1077           dt_rdn(dt_t dt) {
206 1077           return dt - DT_EPOCH_OFFSET;
207             }
208              
209             dt_dow_t
210 321           dt_dow(dt_t dt) {
211 321           int dow = (dt - DT_EPOCH_OFFSET) % 7;
212 321 100         if (dow < 1)
213 30           dow += 7;
214 321 50         assert(dow >= 1);
215 321 50         assert(dow <= 7);
216 321           return dow;
217             }
218