26
26
#include "timelib_private.h"
27
27
#include <math.h>
28
28
29
- timelib_rel_time * timelib_diff (timelib_time * one , timelib_time * two )
29
+ static void swap_times (timelib_time * * one , timelib_time * * two , timelib_rel_time * rt )
30
30
{
31
- timelib_rel_time * rt ;
32
31
timelib_time * swp ;
33
- timelib_sll dst_corr = 0 , dst_h_corr = 0 , dst_m_corr = 0 ;
34
- timelib_time_offset * trans = NULL ;
35
32
33
+ swp = * two ;
34
+ * two = * one ;
35
+ * one = swp ;
36
+ rt -> invert = 1 ;
37
+ }
36
38
37
- rt = timelib_rel_time_ctor ();
38
- rt -> invert = 0 ;
39
+ static void swap_if_negative (timelib_rel_time * rt )
40
+ {
41
+ if (rt -> y == 0 && rt -> m == 0 && rt -> d == 0 && rt -> h == 0 && rt -> i == 0 && rt -> s == 0 && rt -> us == 0 ) {
42
+ return ;
43
+ }
44
+ if (rt -> y >= 0 && rt -> m >= 0 && rt -> d >= 0 && rt -> h >= 0 && rt -> i >= 0 && rt -> s >= 0 && rt -> us >= 0 ) {
45
+ return ;
46
+ }
47
+
48
+ rt -> invert = 1 - rt -> invert ;
49
+ rt -> y = 0 - rt -> y ;
50
+ rt -> m = 0 - rt -> m ;
51
+ rt -> d = 0 - rt -> d ;
52
+ rt -> h = 0 - rt -> h ;
53
+ rt -> i = 0 - rt -> i ;
54
+ rt -> s = 0 - rt -> s ;
55
+ rt -> us = 0 - rt -> us ;
56
+ }
57
+
58
+ static void sort_old_to_new (timelib_time * * one , timelib_time * * two , timelib_rel_time * rt )
59
+ {
60
+ /* Check whether date/times need to be inverted. If both times are
61
+ * TIMELIB_ZONETYPE_ID times with the same TZID, we use the y-s + us fields. */
39
62
if (
40
- (one -> sse > two -> sse ) ||
41
- (one -> sse == two -> sse && one -> us > two -> us )
63
+ (* one )-> zone_type == TIMELIB_ZONETYPE_ID &&
64
+ (* two )-> zone_type == TIMELIB_ZONETYPE_ID &&
65
+ (strcmp ((* one )-> tz_info -> name , (* two )-> tz_info -> name ) != 0 )
42
66
) {
43
- swp = two ;
44
- two = one ;
45
- one = swp ;
46
- rt -> invert = 1 ;
67
+ if (
68
+ ((* one )-> y > (* two )-> y ) ||
69
+ ((* one )-> y == (* two )-> y && (* one )-> m > (* two )-> m ) ||
70
+ ((* one )-> y == (* two )-> y && (* one )-> m == (* two )-> m && (* one )-> d > (* two )-> d ) ||
71
+ ((* one )-> y == (* two )-> y && (* one )-> m == (* two )-> m && (* one )-> d == (* two )-> d && (* one )-> h > (* two )-> h ) ||
72
+ ((* one )-> y == (* two )-> y && (* one )-> m == (* two )-> m && (* one )-> d == (* two )-> d && (* one )-> h == (* two )-> h && (* one )-> i > (* two )-> i ) ||
73
+ ((* one )-> y == (* two )-> y && (* one )-> m == (* two )-> m && (* one )-> d == (* two )-> d && (* one )-> h == (* two )-> h && (* one )-> i == (* two )-> i && (* one )-> s > (* two )-> s ) ||
74
+ ((* one )-> y == (* two )-> y && (* one )-> m == (* two )-> m && (* one )-> d == (* two )-> d && (* one )-> h == (* two )-> h && (* one )-> i == (* two )-> i && (* one )-> s == (* two )-> s && (* one )-> us > (* two )-> us )
75
+ ) {
76
+ swap_times (one , two , rt );
77
+ }
78
+ return ;
47
79
}
48
80
81
+ /* Fall back to using the SSE instead to rearrange */
82
+ if (
83
+ ((* one )-> sse > (* two )-> sse ) ||
84
+ ((* one )-> sse == (* two )-> sse && (* one )-> us > (* two )-> us )
85
+ ) {
86
+ swap_times (one , two , rt );
87
+ }
88
+ }
89
+
90
+ static timelib_rel_time * timelib_diff_with_tzid (timelib_time * one , timelib_time * two )
91
+ {
92
+ timelib_rel_time * rt ;
93
+ timelib_sll dst_corr = 0 , dst_h_corr = 0 , dst_m_corr = 0 ;
94
+ timelib_time_offset * trans = NULL ;
95
+
96
+ rt = timelib_rel_time_ctor ();
97
+ rt -> invert = 0 ;
98
+
99
+ sort_old_to_new (& one , & two , rt );
100
+
49
101
/* Calculate correction for UTC offset changes between first and second SSE */
50
102
dst_corr = two -> z - one -> z ;
51
103
dst_h_corr = dst_corr / 3600 ;
@@ -64,10 +116,10 @@ timelib_rel_time *timelib_diff(timelib_time *one, timelib_time *two)
64
116
/* Fall Back: Cater for transition period, where rt->invert is 0, but there are negative numbers */
65
117
if (one -> dst == 1 && two -> dst == 0 ) {
66
118
/* First for two "Type 3" times */
67
- if (one -> zone_type == 3 && two -> zone_type == 3 ) {
119
+ if (one -> zone_type == TIMELIB_ZONETYPE_ID && two -> zone_type == TIMELIB_ZONETYPE_ID ) {
68
120
trans = timelib_get_time_zone_info (two -> sse , two -> tz_info );
69
121
if (trans ) {
70
- if (one -> sse >= trans -> transition_time + dst_corr && one -> sse < trans -> transition_time ) {
122
+ if (one -> sse < trans -> transition_time && one -> sse >= trans -> transition_time + dst_corr ) {
71
123
timelib_sll flipped = SECS_PER_HOUR + (rt -> i * 60 ) + (rt -> s );
72
124
rt -> h = flipped / SECS_PER_HOUR ;
73
125
rt -> i = (flipped - rt -> h * SECS_PER_HOUR ) / 60 ;
@@ -89,8 +141,8 @@ timelib_rel_time *timelib_diff(timelib_time *one, timelib_time *two)
89
141
90
142
timelib_do_rel_normalize (rt -> invert ? one : two , rt );
91
143
92
- /* Do corrections for "Type 3" times */
93
- if (one -> zone_type == 3 && two -> zone_type == 3 && strcmp (one -> tz_info -> name , two -> tz_info -> name ) == 0 ) {
144
+ /* Do corrections for "Type 3" times with the same TZID */
145
+ if (one -> zone_type == TIMELIB_ZONETYPE_ID && two -> zone_type == TIMELIB_ZONETYPE_ID && strcmp (one -> tz_info -> name , two -> tz_info -> name ) == 0 ) {
94
146
if (one -> dst == 1 && two -> dst == 0 ) { /* Fall Back */
95
147
if (two -> tz_info ) {
96
148
trans = timelib_get_time_zone_info (two -> sse , two -> tz_info );
@@ -129,14 +181,11 @@ timelib_rel_time *timelib_diff(timelib_time *one, timelib_time *two)
129
181
}
130
182
}
131
183
} else {
132
- /* Then for all the others */
133
- if (one -> zone_type == 3 && two -> zone_type == 3 ) {
134
- rt -> h -= dst_h_corr ;
135
- } else {
136
- rt -> h -= dst_h_corr + (two -> dst - one -> dst );
137
- }
184
+ rt -> h -= dst_h_corr ;
138
185
rt -> i -= dst_m_corr ;
139
186
187
+ swap_if_negative (rt );
188
+
140
189
timelib_do_rel_normalize (rt -> invert ? one : two , rt );
141
190
}
142
191
@@ -147,6 +196,40 @@ timelib_rel_time *timelib_diff(timelib_time *one, timelib_time *two)
147
196
return rt ;
148
197
}
149
198
199
+ timelib_rel_time * timelib_diff (timelib_time * one , timelib_time * two )
200
+ {
201
+ timelib_rel_time * rt ;
202
+
203
+ if (one -> zone_type == TIMELIB_ZONETYPE_ID && two -> zone_type == TIMELIB_ZONETYPE_ID ) {
204
+ return timelib_diff_with_tzid (one , two );
205
+ }
206
+
207
+ rt = timelib_rel_time_ctor ();
208
+ rt -> invert = 0 ;
209
+
210
+ sort_old_to_new (& one , & two , rt );
211
+
212
+ rt -> y = two -> y - one -> y ;
213
+ rt -> m = two -> m - one -> m ;
214
+ rt -> d = two -> d - one -> d ;
215
+ rt -> h = two -> h - one -> h ;
216
+ if (one -> zone_type != TIMELIB_ZONETYPE_ID ) {
217
+ rt -> h = rt -> h + one -> dst ;
218
+ }
219
+ if (two -> zone_type != TIMELIB_ZONETYPE_ID ) {
220
+ rt -> h = rt -> h - two -> dst ;
221
+ }
222
+ rt -> i = two -> i - one -> i ;
223
+ rt -> s = two -> s - one -> s - two -> z + one -> z ;
224
+ rt -> us = two -> us - one -> us ;
225
+
226
+ rt -> days = timelib_diff_days (one , two );
227
+
228
+ timelib_do_rel_normalize (rt -> invert ? one : two , rt );
229
+
230
+ return rt ;
231
+ }
232
+
150
233
151
234
int timelib_diff_days (timelib_time * one , timelib_time * two )
152
235
{
0 commit comments