File Coverage

src/panda/time.cc
Criterion Covered Total %
statement 75 79 94.9
branch 25 34 73.5
condition n/a
subroutine n/a
pod n/a
total 100 113 88.5


line stmt bran cond sub pod time code
1             #include
2             #include
3             #include
4              
5             namespace panda { namespace time {
6              
7 18           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 26894           static inline void _gmtime (ptime_t epoch, datetime* result) {
25 26894           ptime_t sec_remainder = (epoch + OUTLIM_EPOCH_BY_86400) % 86400;
26 26894           ptime_t delta_days = (epoch - sec_remainder)/86400;
27 26894           result->wday = (OUTLIM_DAY_BY_7 + EPOCH_WDAY + delta_days) % 7;
28 26894           result->hour = sec_remainder/3600;
29 26894           sec_remainder %= 3600;
30 26894           result->min = sec_remainder/60;
31 26894           result->sec = sec_remainder % 60;
32              
33             int32_t year;
34             int32_t remainder;
35 26894           christ_year(EPOCH_CHRIST_DAYS + delta_days, year, remainder);
36              
37 26894           int leap = is_leap_year(year);
38 26894           result->yday = remainder;
39 26894           result->mon = YDAY2MON[leap][remainder];
40 26894           result->mday = YDAY2MDAY[leap][remainder];
41 26894           result->gmtoff = 0;
42 26894           result->n_zone = ZONE_N_GMT;
43 26894           result->isdst = 0;
44 26894           result->year = year;
45 26894           }
46              
47 31340           static inline ptime_t _timegmll (const datetime* date) {
48 31340           int leap = is_leap_year(date->year);
49 31340           ptime_t delta_days = christ_days(date->year) + MON2YDAY[leap][date->mon] + date->mday - 1 - EPOCH_CHRIST_DAYS;
50 31340           return delta_days * 86400 + date->hour * 3600 + date->min * 60 + date->sec;
51             }
52              
53 23826           static inline ptime_t _timegml (datetime* date) {
54 23826           ptime_t mon_remainder = (date->mon + OUTLIM_MONTH_BY_12) % 12;
55 23826           date->year += (date->mon - mon_remainder) / 12;
56 23826           date->mon = mon_remainder;
57 23826           return _timegmll(date);
58             }
59              
60 5           static inline ptime_t _timegm (datetime* date) {
61 5           ptime_t result = _timegml(date);
62 5           _gmtime(result, date);
63 5           return result;
64             }
65              
66 9446           void gmtime (ptime_t epoch, datetime* result) { return _gmtime(epoch, result); }
67 10           ptime_t timegm (datetime *date) { return _timegm(date); }
68 9446           ptime_t timegml (datetime *date) { return _timegml(date); }
69              
70 7514           static inline ptime_t _calc_rule_epoch (int is_leap, const datetime* curdate, datetime border) {
71 7514           border.mday = (border.wday + curdate->yday - MON2YDAY[is_leap][border.mon] - curdate->wday + 378) % 7 + 7*border.yday - 6;
72 7514 50         if (border.mday > DAYS_IN_MONTH[is_leap][border.mon]) border.mday -= 7;
73 7514           border.year = curdate->year;
74 7514           return _timegmll(&border);
75             }
76              
77 19033           void anytime (ptime_t epoch, datetime* result, const Timezone* zone) {
78 19033 100         if (epoch < zone->ltrans.start) {
79 118283 100         __PTIME_TRANS_BINFIND(epoch, start);
    100          
    100          
    100          
80 14544           _gmtime(epoch + zone->trans[index].offset, result);
81 14544           result->gmtoff = zone->trans[index].gmt_offset;
82 14544           result->n_zone = zone->trans[index].n_abbrev;
83 14544           result->isdst = zone->trans[index].isdst;
84 14544 100         _PTIME_LT_LEAPSEC_CORR(zone->trans[index]);
85             }
86 4489 100         else if (!zone->future.hasdst) { // future with no DST
87 2516           _gmtime(epoch + zone->future.outer.offset, result);
88 2516           result->n_zone = zone->future.outer.n_abbrev;
89 2516           result->gmtoff = zone->future.outer.gmt_offset;
90 2516           result->isdst = zone->future.outer.isdst; // some zones stay in dst in future (when no POSIX string and last trans is in dst)
91 2516 50         _PTIME_LT_LEAPSEC_CORR(zone->ltrans);
92             }
93             else {
94 1973           _gmtime(epoch + zone->future.outer.offset, result);
95 1973           int is_leap = is_leap_year(result->year);
96              
97 3512 100         if ((epoch >= _calc_rule_epoch(is_leap, result, zone->future.outer.end) - zone->future.outer.offset) &&
98 1539           (epoch < _calc_rule_epoch(is_leap, result, zone->future.inner.end) - zone->future.inner.offset)) {
99 1104           _gmtime(epoch + zone->future.inner.offset, result);
100 1104           result->isdst = zone->future.inner.isdst;
101 1104           result->n_zone = zone->future.inner.n_abbrev;
102 1104           result->gmtoff = zone->future.inner.gmt_offset;
103             } else {
104 869           result->isdst = zone->future.outer.isdst;
105 869           result->n_zone = zone->future.outer.n_abbrev;
106 869           result->gmtoff = zone->future.outer.gmt_offset;
107             }
108 1973 50         _PTIME_LT_LEAPSEC_CORR(zone->ltrans);
109             }
110 19033           }
111              
112 30           ptime_t timeany (datetime* date, const Timezone* zone) {
113             # define PTIME_ANY_NORMALIZE
114 30 100         if (date->isdst > 0) {
115             # undef PTIME_AMBIGUOUS_LATER
116             # include
117             } else {
118             # define PTIME_AMBIGUOUS_LATER
119             # include
120             }
121             # undef PTIME_ANY_NORMALIZE
122             }
123              
124 19068           ptime_t timeanyl (datetime* date, const Timezone* zone) {
125 19068 100         if (date->isdst > 0) {
126             # undef PTIME_AMBIGUOUS_LATER
127             # include
128             } else {
129             # define PTIME_AMBIGUOUS_LATER
130             # include
131             }
132             }
133              
134 9           size_t strftime (char* buf, size_t maxsize, const char* format, const datetime* timeptr) {
135             tm systm;
136 9           dt2tm(systm, *timeptr);
137 9           return strftime(buf, maxsize, format, &systm);
138             }
139              
140 0           void printftime (const char* format, const datetime* timeptr) {
141             char buf[150];
142 0 0         strftime(buf, 150, format, timeptr);
143 0 0         printf("%s", buf);
144 0           }
145              
146 72 50         }}
    50