File Coverage

src/panda/time.cc
Criterion Covered Total %
statement 82 86 95.3
branch 33 42 78.5
condition n/a
subroutine n/a
pod n/a
total 115 128 89.8


line stmt bran cond sub pod time code
1             #include
2             #include
3             #include
4              
5             namespace panda { namespace time {
6              
7 26           static const int64_t ZONE_N_GMT = *((int64_t*)"GMT\0\0\0\0");
8              
9             #define __PTIME_TRANS_BINFIND(VAR, FIELD) \
10             int index = -1; \
11             int low = 0; \
12             int high = zone->trans_cnt; \
13             while (high - low > 1) { \
14             int mid = (high+low)/2; \
15             if (zone->trans[mid].FIELD > VAR) high = mid; \
16             else if (zone->trans[mid].FIELD < VAR) low = mid; \
17             else { index = mid; break; } \
18             } \
19             if (index < 0) index = high - 1;
20              
21             #define _PTIME_LT_LEAPSEC_CORR(source) \
22             if (epoch < source.leap_end) result->sec = 60 + epoch - source.start;
23              
24              
25 26899           static inline void _gmtime (ptime_t epoch, datetime* result) {
26 26899           ptime_t sec_remainder = (epoch + OUTLIM_EPOCH_BY_86400) % 86400;
27 26899           ptime_t delta_days = (epoch - sec_remainder)/86400;
28 26899           result->wday = (OUTLIM_DAY_BY_7 + EPOCH_WDAY + delta_days) % 7;
29 26899           result->hour = sec_remainder/3600;
30 26899           sec_remainder %= 3600;
31 26899           result->min = sec_remainder/60;
32 26899           result->sec = sec_remainder % 60;
33              
34             int32_t year;
35             int32_t remainder;
36 26899           christ_year(EPOCH_CHRIST_DAYS + delta_days, year, remainder);
37              
38 26899           int leap = is_leap_year(year);
39 26899           result->yday = remainder;
40 26899           result->mon = YDAY2MON[leap][remainder];
41 26899           result->mday = YDAY2MDAY[leap][remainder];
42 26899           result->gmtoff = 0;
43 26899           result->n_zone = ZONE_N_GMT;
44 26899           result->isdst = 0;
45 26899           result->year = year;
46 26899           }
47              
48 47534 100         static inline bool is_epoch_valid(ptime_t epoch) { return (epoch <= EPOCH_MAX) && (epoch >= EPOCH_MIN); }
    100          
49              
50 31341           static inline ptime_t _timegmll (const datetime* date) {
51 31341           int leap = is_leap_year(date->year);
52 31341           ptime_t delta_days = christ_days(date->year) + MON2YDAY[leap][date->mon] + date->mday - 1 - EPOCH_CHRIST_DAYS;
53 31341           return delta_days * 86400 + date->hour * 3600 + date->min * 60 + date->sec;
54             }
55              
56 23827           static inline ptime_t _timegml (datetime* date) {
57 23827           ptime_t mon_remainder = (date->mon + OUTLIM_MONTH_BY_12) % 12;
58 23827           date->year += (date->mon - mon_remainder) / 12;
59 23827           date->mon = mon_remainder;
60 23827           return _timegmll(date);
61             }
62              
63 5           static inline ptime_t _timegm (datetime* date) {
64 5           ptime_t result = _timegml(date);
65 5           _gmtime(result, date);
66 5           return result;
67             }
68              
69 4727           bool gmtime (ptime_t epoch, datetime* result) {
70 4727 100         if (is_epoch_valid(epoch)){
71 4723           _gmtime(epoch, result);
72 4723           return true;
73             };
74 4           return false;
75             }
76 10           ptime_t timegm (datetime *date) { return _timegm(date); }
77 9446           ptime_t timegml (datetime *date) { return _timegml(date); }
78              
79 7514           static inline ptime_t _calc_rule_epoch (int is_leap, const datetime* curdate, datetime border) {
80 7514           border.mday = (border.wday + curdate->yday - MON2YDAY[is_leap][border.mon] - curdate->wday + 378) % 7 + 7*border.yday - 6;
81 7514 50         if (border.mday > DAYS_IN_MONTH[is_leap][border.mon]) border.mday -= 7;
82 7514           border.year = curdate->year;
83 7514           return _timegmll(&border);
84             }
85              
86 19040           bool anytime (ptime_t epoch, datetime* result, const Timezone* zone) {
87 19040           bool r = is_epoch_valid(epoch);
88 19040 100         if (r) {
89 19038 100         if (epoch < zone->ltrans.start) {
90 118293 100         __PTIME_TRANS_BINFIND(epoch, start);
    100          
    100          
    100          
91 14545           _gmtime(epoch + zone->trans[index].offset, result);
92 14545           result->gmtoff = zone->trans[index].gmt_offset;
93 14545           result->n_zone = zone->trans[index].n_abbrev;
94 14545           result->isdst = zone->trans[index].isdst;
95 14545 100         _PTIME_LT_LEAPSEC_CORR(zone->trans[index]);
96             }
97 4493 100         else if (!zone->future.hasdst) { // future with no DST
98 2520           _gmtime(epoch + zone->future.outer.offset, result);
99 2520           result->n_zone = zone->future.outer.n_abbrev;
100 2520           result->gmtoff = zone->future.outer.gmt_offset;
101 2520           result->isdst = zone->future.outer.isdst; // some zones stay in dst in future (when no POSIX string and last trans is in dst)
102 2520 50         _PTIME_LT_LEAPSEC_CORR(zone->ltrans);
103             }
104             else {
105 1973           _gmtime(epoch + zone->future.outer.offset, result);
106 1973           int is_leap = is_leap_year(result->year);
107              
108 3512 100         if ((epoch >= _calc_rule_epoch(is_leap, result, zone->future.outer.end) - zone->future.outer.offset) &&
109 1539           (epoch < _calc_rule_epoch(is_leap, result, zone->future.inner.end) - zone->future.inner.offset)) {
110 1104           _gmtime(epoch + zone->future.inner.offset, result);
111 1104           result->isdst = zone->future.inner.isdst;
112 1104           result->n_zone = zone->future.inner.n_abbrev;
113 1104           result->gmtoff = zone->future.inner.gmt_offset;
114             } else {
115 869           result->isdst = zone->future.outer.isdst;
116 869           result->n_zone = zone->future.outer.n_abbrev;
117 869           result->gmtoff = zone->future.outer.gmt_offset;
118             }
119 19038 50         _PTIME_LT_LEAPSEC_CORR(zone->ltrans);
120             }
121             };
122 19040           return r;
123             }
124              
125 30           ptime_t timeany (datetime* date, const Timezone* zone) {
126             # define PTIME_ANY_NORMALIZE
127 30 100         if (date->isdst > 0) {
128             # undef PTIME_AMBIGUOUS_LATER
129             # include
130             } else {
131             # define PTIME_AMBIGUOUS_LATER
132             # include
133             }
134             # undef PTIME_ANY_NORMALIZE
135             }
136              
137 19069           ptime_t timeanyl (datetime* date, const Timezone* zone) {
138 19069 100         if (date->isdst > 0) {
139             # undef PTIME_AMBIGUOUS_LATER
140             # include
141             } else {
142             # define PTIME_AMBIGUOUS_LATER
143             # include
144             }
145             }
146              
147 11           size_t strftime (char* buf, size_t maxsize, const char* format, const datetime* timeptr) {
148             tm systm;
149 11           dt2tm(systm, *timeptr);
150 11           return strftime(buf, maxsize, format, &systm);
151             }
152              
153 0           void printftime (const char* format, const datetime* timeptr) {
154             char buf[150];
155 0 0         strftime(buf, 150, format, timeptr);
156 0 0         printf("%s", buf);
157 0           }
158              
159 104 50         }}
    50