Skip to content

Commit 88067b6

Browse files
committed
Merge branch 'PHP-5.4' into PHP-5.5
Conflicts: ext/date/php_date.c
2 parents 4587ef5 + c1eb219 commit 88067b6

13 files changed

+607
-409
lines changed

ext/date/lib/interval.c

Lines changed: 98 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ timelib_rel_time *timelib_diff(timelib_time *one, timelib_time *two)
2525
{
2626
timelib_rel_time *rt;
2727
timelib_time *swp;
28-
timelib_sll dst_h_corr = 0, dst_m_corr = 0;
28+
timelib_sll dst_corr = 0 ,dst_h_corr = 0, dst_m_corr = 0;
2929
timelib_time one_backup, two_backup;
3030

3131
rt = timelib_rel_time_ctor();
@@ -43,8 +43,9 @@ timelib_rel_time *timelib_diff(timelib_time *one, timelib_time *two)
4343
&& (strcmp(one->tz_info->name, two->tz_info->name) == 0)
4444
&& (one->z != two->z))
4545
{
46-
dst_h_corr = (two->z - one->z) / 3600;
47-
dst_m_corr = ((two->z - one->z) % 3600) / 60;
46+
dst_corr = two->z - one->z;
47+
dst_h_corr = dst_corr / 3600;
48+
dst_m_corr = (dst_corr % 3600) / 60;
4849
}
4950

5051
/* Save old TZ info */
@@ -57,16 +58,108 @@ timelib_rel_time *timelib_diff(timelib_time *one, timelib_time *two)
5758
rt->y = two->y - one->y;
5859
rt->m = two->m - one->m;
5960
rt->d = two->d - one->d;
60-
rt->h = two->h - one->h + dst_h_corr;
61-
rt->i = two->i - one->i + dst_m_corr;
61+
rt->h = two->h - one->h;
62+
rt->i = two->i - one->i;
6263
rt->s = two->s - one->s;
64+
if (one_backup.dst == 0 && two_backup.dst == 1 && two->sse >= one->sse + 86400 - dst_corr) {
65+
rt->h += dst_h_corr;
66+
rt->i += dst_m_corr;
67+
}
68+
6369
rt->days = abs(floor((one->sse - two->sse - (dst_h_corr * 3600) - (dst_m_corr * 60)) / 86400));
6470

6571
timelib_do_rel_normalize(rt->invert ? one : two, rt);
6672

73+
/* We need to do this after normalisation otherwise we can't get "24H" */
74+
if (one_backup.dst == 1 && two_backup.dst == 0 && two->sse >= one->sse + 86400) {
75+
if (two->sse < one->sse + 86400 - dst_corr) {
76+
rt->d--;
77+
rt->h = 24;
78+
} else {
79+
rt->h += dst_h_corr;
80+
rt->i += dst_m_corr;
81+
}
82+
}
83+
6784
/* Restore old TZ info */
6885
memcpy(one, &one_backup, sizeof(one_backup));
6986
memcpy(two, &two_backup, sizeof(two_backup));
7087

7188
return rt;
7289
}
90+
91+
timelib_time *timelib_add(timelib_time *old_time, timelib_rel_time *interval)
92+
{
93+
int bias = 1;
94+
timelib_time *t = timelib_time_clone(old_time);
95+
96+
if (interval->have_weekday_relative || interval->have_special_relative) {
97+
memcpy(&t->relative, interval, sizeof(struct timelib_rel_time));
98+
} else {
99+
if (interval->invert) {
100+
bias = -1;
101+
}
102+
memset(&t->relative, 0, sizeof(struct timelib_rel_time));
103+
t->relative.y = interval->y * bias;
104+
t->relative.m = interval->m * bias;
105+
t->relative.d = interval->d * bias;
106+
t->relative.h = interval->h * bias;
107+
t->relative.i = interval->i * bias;
108+
t->relative.s = interval->s * bias;
109+
}
110+
t->have_relative = 1;
111+
t->sse_uptodate = 0;
112+
113+
timelib_update_ts(t, NULL);
114+
115+
// printf("%lld %lld %d\n", old_time->dst, t->dst, (t->sse - old_time->sse));
116+
/* Adjust for backwards DST changeover */
117+
if (old_time->dst == 1 && t->dst == 0 && !interval->y && !interval->m && !interval->d) {
118+
t->sse -= old_time->z;
119+
t->sse += t->z;
120+
}
121+
122+
timelib_update_from_sse(t);
123+
t->have_relative = 0;
124+
125+
return t;
126+
}
127+
128+
timelib_time *timelib_sub(timelib_time *old_time, timelib_rel_time *interval)
129+
{
130+
int bias = 1;
131+
timelib_time *t = timelib_time_clone(old_time);
132+
133+
if (interval->invert) {
134+
bias = -1;
135+
}
136+
137+
memset(&t->relative, 0, sizeof(struct timelib_rel_time));
138+
t->relative.y = 0 - (interval->y * bias);
139+
t->relative.m = 0 - (interval->m * bias);
140+
t->relative.d = 0 - (interval->d * bias);
141+
t->relative.h = 0 - (interval->h * bias);
142+
t->relative.i = 0 - (interval->i * bias);
143+
t->relative.s = 0 - (interval->s * bias);
144+
t->have_relative = 1;
145+
t->sse_uptodate = 0;
146+
147+
timelib_update_ts(t, NULL);
148+
149+
/* Adjust for backwards DST changeover */
150+
if (old_time->dst == 1 && t->dst == 0 && !interval->y && !interval->m && !interval->d) {
151+
t->sse -= old_time->z;
152+
t->sse += t->z;
153+
}
154+
/* Adjust for forwards DST changeover */
155+
if (old_time->dst == 0 && t->dst == 1 && !interval->y && !interval->m && !interval->d ) {
156+
t->sse -= old_time->z;
157+
t->sse += t->z;
158+
}
159+
160+
timelib_update_from_sse(t);
161+
162+
t->have_relative = 0;
163+
164+
return t;
165+
}

ext/date/lib/timelib.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -138,5 +138,7 @@ int timelib_astro_rise_set_altitude(timelib_time *time, double lon, double lat,
138138

139139
/* from interval.c */
140140
timelib_rel_time *timelib_diff(timelib_time *one, timelib_time *two);
141+
timelib_time *timelib_add(timelib_time *t, timelib_rel_time *interval);
142+
timelib_time *timelib_sub(timelib_time *t, timelib_rel_time *interval);
141143

142144
#endif

ext/date/lib/unixtime2tm.c

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -137,19 +137,16 @@ void timelib_unixtime2gmt(timelib_time* tm, timelib_sll ts)
137137
void timelib_update_from_sse(timelib_time *tm)
138138
{
139139
timelib_sll sse;
140+
int z = tm->z;
141+
signed int dst = tm->dst;
140142

141143
sse = tm->sse;
142144

143145
switch (tm->zone_type) {
144146
case TIMELIB_ZONETYPE_ABBR:
145147
case TIMELIB_ZONETYPE_OFFSET: {
146-
int z = tm->z;
147-
signed int dst = tm->dst;
148-
149148
timelib_unixtime2gmt(tm, tm->sse - (tm->z * 60) + (tm->dst * 3600));
150149

151-
tm->z = z;
152-
tm->dst = dst;
153150
goto cleanup;
154151
}
155152

@@ -171,6 +168,8 @@ void timelib_update_from_sse(timelib_time *tm)
171168
tm->sse = sse;
172169
tm->is_localtime = 1;
173170
tm->have_zone = 1;
171+
tm->z = z;
172+
tm->dst = dst;
174173
}
175174

176175
void timelib_unixtime2local(timelib_time *tm, timelib_sll ts)

ext/date/php_date.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2610,6 +2610,7 @@ PHPAPI int php_date_initialize(php_date_obj *dateobj, /*const*/ char *time_str,
26102610

26112611
timelib_fill_holes(dateobj->time, now, TIMELIB_NO_CLONE);
26122612
timelib_update_ts(dateobj->time, tzi);
2613+
timelib_update_from_sse(dateobj->time);
26132614

26142615
dateobj->time->have_relative = 0;
26152616

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
--TEST--
2+
Test for Date/Time construction during a forward DST transition
3+
--FILE--
4+
<?php
5+
date_default_timezone_set('America/New_York');
6+
7+
$date = new DateTime('2010-03-14 01:30:00');
8+
echo $date->format('Y-m-d H:i:s T/e - U') . "\n";
9+
10+
$date = new DateTime('2010-03-14 02:00:00');
11+
echo $date->format('Y-m-d H:i:s T/e - U') . "\n";
12+
13+
$date = new DateTime('2010-03-14 02:30:00');
14+
echo $date->format('Y-m-d H:i:s T/e - U') . "\n";
15+
16+
$date = new DateTime('2010-03-14 03:00:00');
17+
echo $date->format('Y-m-d H:i:s T/e - U') . "\n";
18+
19+
$date = new DateTime('2010-03-14 03:30:00');
20+
echo $date->format('Y-m-d H:i:s T/e - U') . "\n";
21+
?>
22+
--EXPECT--
23+
2010-03-14 01:30:00 EST/America/New_York - 1268548200
24+
2010-03-14 03:00:00 EDT/America/New_York - 1268550000
25+
2010-03-14 03:30:00 EDT/America/New_York - 1268551800
26+
2010-03-14 03:00:00 EDT/America/New_York - 1268550000
27+
2010-03-14 03:30:00 EDT/America/New_York - 1268551800
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
--TEST--
2+
RFC: DateTime and Daylight Saving Time Transitions (zone type 3, ba)
3+
--CREDITS--
4+
Daniel Convissor <[email protected]>
5+
--FILE--
6+
<?php
7+
8+
date_default_timezone_set('America/New_York');
9+
$date_format = 'Y-m-d H:i:s T e';
10+
$interval_format = 'P%dDT%hH';
11+
12+
/*
13+
* Backward Transitions, add().
14+
*/
15+
16+
$start = new DateTime('2010-11-07 01:59:59');
17+
$interval_spec = 'PT1S';
18+
$interval = new DateInterval($interval_spec);
19+
echo 'ba1 ' . $start->format($date_format) . " + $interval_spec = "
20+
. $start->add($interval)->format($date_format) . "\n";
21+
22+
$start = new DateTime('2010-11-06 04:30:00');
23+
$interval_spec = 'P1D';
24+
$interval = new DateInterval($interval_spec);
25+
echo 'ba2 ' . $start->format($date_format) . " + $interval_spec = "
26+
. $start->add($interval)->format($date_format) . "\n";
27+
28+
$start = new DateTime('2010-11-06 04:30:00');
29+
$interval_spec = 'PT24H';
30+
$interval = new DateInterval($interval_spec);
31+
echo 'ba3 ' . $start->format($date_format) . " + $interval_spec = "
32+
. $start->add($interval)->format($date_format) . "\n";
33+
34+
$start = new DateTime('2010-11-06 04:30:00');
35+
$interval_spec = 'PT23H';
36+
$interval = new DateInterval($interval_spec);
37+
echo 'ba4 ' . $start->format($date_format) . " + $interval_spec = "
38+
. $start->add($interval)->format($date_format) . "\n";
39+
40+
$start = new DateTime('2010-11-06 04:30:00');
41+
$interval_spec = 'PT22H';
42+
$interval = new DateInterval($interval_spec);
43+
echo 'ba5 ' . $start->format($date_format) . " + $interval_spec = "
44+
. $start->add($interval)->format($date_format) . "\n";
45+
46+
$start = new DateTime('2010-11-06 04:30:00');
47+
$interval_spec = 'PT21H';
48+
$interval = new DateInterval($interval_spec);
49+
echo 'ba6 ' . $start->format($date_format) . " + $interval_spec = "
50+
. $start->add($interval)->format($date_format) . "\n";
51+
52+
$start = new DateTime('2010-11-06 01:30:00');
53+
$interval_spec = 'P1D';
54+
$interval = new DateInterval($interval_spec);
55+
echo 'ba7 ' . $start->format($date_format) . " + $interval_spec = "
56+
. $start->add($interval)->format($date_format) . "\n";
57+
58+
$start = new DateTime('2010-11-06 01:30:00');
59+
$interval_spec = 'P1DT1H';
60+
$interval = new DateInterval($interval_spec);
61+
echo 'ba8 ' . $start->format($date_format) . " + $interval_spec = "
62+
. $start->add($interval)->format($date_format) . "\n";
63+
64+
$start = new DateTime('2010-11-06 04:30:00');
65+
$interval_spec = 'PT25H';
66+
$interval = new DateInterval($interval_spec);
67+
echo 'ba9 ' . $start->format($date_format) . " + $interval_spec = "
68+
. $start->add($interval)->format($date_format) . "\n";
69+
70+
$start = new DateTime('2010-11-06 03:30:00');
71+
$interval_spec = 'P1D';
72+
$interval = new DateInterval($interval_spec);
73+
echo 'ba10 ' . $start->format($date_format) . " + $interval_spec = "
74+
. $start->add($interval)->format($date_format) . "\n";
75+
76+
$start = new DateTime('2010-11-06 02:30:00');
77+
$interval_spec = 'P1D';
78+
$interval = new DateInterval($interval_spec);
79+
echo 'ba11 ' . $start->format($date_format) . " + $interval_spec = "
80+
. $start->add($interval)->format($date_format) . "\n";
81+
82+
echo "\n";
83+
84+
?>
85+
--EXPECT--
86+
ba1 2010-11-07 01:59:59 EDT America/New_York + PT1S = 2010-11-07 01:00:00 EST America/New_York
87+
ba2 2010-11-06 04:30:00 EDT America/New_York + P1D = 2010-11-07 04:30:00 EST America/New_York
88+
ba3 2010-11-06 04:30:00 EDT America/New_York + PT24H = 2010-11-07 03:30:00 EST America/New_York
89+
ba4 2010-11-06 04:30:00 EDT America/New_York + PT23H = 2010-11-07 02:30:00 EST America/New_York
90+
ba5 2010-11-06 04:30:00 EDT America/New_York + PT22H = 2010-11-07 01:30:00 EST America/New_York
91+
ba6 2010-11-06 04:30:00 EDT America/New_York + PT21H = 2010-11-07 01:30:00 EDT America/New_York
92+
ba7 2010-11-06 01:30:00 EDT America/New_York + P1D = 2010-11-07 01:30:00 EDT America/New_York
93+
ba8 2010-11-06 01:30:00 EDT America/New_York + P1DT1H = 2010-11-07 02:30:00 EST America/New_York
94+
ba9 2010-11-06 04:30:00 EDT America/New_York + PT25H = 2010-11-07 04:30:00 EST America/New_York
95+
ba10 2010-11-06 03:30:00 EDT America/New_York + P1D = 2010-11-07 03:30:00 EST America/New_York
96+
ba11 2010-11-06 02:30:00 EDT America/New_York + P1D = 2010-11-07 02:30:00 EST America/New_York
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
--TEST--
2+
RFC: DateTime and Daylight Saving Time Transitions (zone type 3, bd1)
3+
--CREDITS--
4+
Daniel Convissor <[email protected]>
5+
--FILE--
6+
<?php
7+
8+
date_default_timezone_set('America/New_York');
9+
$date_format = 'Y-m-d H:i:s T e';
10+
$interval_format = 'P%dDT%hH';
11+
12+
/*
13+
* Backward Transitions, diff().
14+
*/
15+
16+
$end = new DateTime('2010-11-07 05:30:00');
17+
$start = new DateTime('2010-11-06 04:30:00');
18+
echo 'bd1 ' . $end->format($date_format) . ' - ' . $start->format($date_format)
19+
. ' = ' . $start->diff($end)->format($interval_format) . "\n";
20+
21+
$end = new DateTime('2010-11-07 04:30:00');
22+
$start = new DateTime('2010-11-06 04:30:00');
23+
echo 'bd2 ' . $end->format($date_format) . ' - ' . $start->format($date_format)
24+
. ' = ' . $start->diff($end)->format($interval_format) . "\n";
25+
26+
$end = new DateTime('2010-11-07 03:30:00');
27+
$start = new DateTime('2010-11-06 04:30:00');
28+
echo 'bd3 ' . $end->format($date_format) . ' - ' . $start->format($date_format)
29+
. ' = ' . $start->diff($end)->format($interval_format) . "\n";
30+
31+
$end = new DateTime('2010-11-07 02:30:00');
32+
$start = new DateTime('2010-11-06 04:30:00');
33+
echo 'bd4 ' . $end->format($date_format) . ' - ' . $start->format($date_format)
34+
. ' = ' . $start->diff($end)->format($interval_format) . "\n";
35+
36+
$end = new DateTime('2010-11-07 01:30:00');
37+
$start = new DateTime('2010-11-06 01:30:00');
38+
echo 'bd7 ' . $end->format($date_format) . ' - ' . $start->format($date_format)
39+
. ' = ' . $start->diff($end)->format($interval_format) . "\n";
40+
41+
echo "\n";
42+
?>
43+
--EXPECT--
44+
bd1 2010-11-07 05:30:00 EST America/New_York - 2010-11-06 04:30:00 EDT America/New_York = P1DT1H
45+
bd2 2010-11-07 04:30:00 EST America/New_York - 2010-11-06 04:30:00 EDT America/New_York = P1DT0H
46+
bd3 2010-11-07 03:30:00 EST America/New_York - 2010-11-06 04:30:00 EDT America/New_York = P0DT24H
47+
bd4 2010-11-07 02:30:00 EST America/New_York - 2010-11-06 04:30:00 EDT America/New_York = P0DT23H
48+
bd7 2010-11-07 01:30:00 EDT America/New_York - 2010-11-06 01:30:00 EDT America/New_York = P1DT0H

0 commit comments

Comments
 (0)