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
|
|
|
|
|
|