Skip to content

Commit b66b04d

Browse files
committed
Merge remote-tracking branch 'derickr/timelib-sync-tests' into PHP-8.1
2 parents c2bdaa4 + 557e02b commit b66b04d

File tree

8 files changed

+291
-130
lines changed

8 files changed

+291
-130
lines changed

ext/date/lib/interval.c

Lines changed: 105 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -26,26 +26,78 @@
2626
#include "timelib_private.h"
2727
#include <math.h>
2828

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)
3030
{
31-
timelib_rel_time *rt;
3231
timelib_time *swp;
33-
timelib_sll dst_corr = 0, dst_h_corr = 0, dst_m_corr = 0;
34-
timelib_time_offset *trans = NULL;
3532

33+
swp = *two;
34+
*two = *one;
35+
*one = swp;
36+
rt->invert = 1;
37+
}
3638

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. */
3962
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)
4266
) {
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;
4779
}
4880

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+
49101
/* Calculate correction for UTC offset changes between first and second SSE */
50102
dst_corr = two->z - one->z;
51103
dst_h_corr = dst_corr / 3600;
@@ -64,10 +116,10 @@ timelib_rel_time *timelib_diff(timelib_time *one, timelib_time *two)
64116
/* Fall Back: Cater for transition period, where rt->invert is 0, but there are negative numbers */
65117
if (one->dst == 1 && two->dst == 0) {
66118
/* 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) {
68120
trans = timelib_get_time_zone_info(two->sse, two->tz_info);
69121
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) {
71123
timelib_sll flipped = SECS_PER_HOUR + (rt->i * 60) + (rt->s);
72124
rt->h = flipped / SECS_PER_HOUR;
73125
rt->i = (flipped - rt->h * SECS_PER_HOUR) / 60;
@@ -89,8 +141,8 @@ timelib_rel_time *timelib_diff(timelib_time *one, timelib_time *two)
89141

90142
timelib_do_rel_normalize(rt->invert ? one : two, rt);
91143

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) {
94146
if (one->dst == 1 && two->dst == 0) { /* Fall Back */
95147
if (two->tz_info) {
96148
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)
129181
}
130182
}
131183
} 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;
138185
rt->i -= dst_m_corr;
139186

187+
swap_if_negative(rt);
188+
140189
timelib_do_rel_normalize(rt->invert ? one : two, rt);
141190
}
142191

@@ -147,6 +196,40 @@ timelib_rel_time *timelib_diff(timelib_time *one, timelib_time *two)
147196
return rt;
148197
}
149198

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

151234
int timelib_diff_days(timelib_time *one, timelib_time *two)
152235
{

0 commit comments

Comments
 (0)