Skip to content

Commit 03ff333

Browse files
committed
ext/date: drop conditional branches in modify() microsecond handling
Always fold microseconds into seconds before SSE arithmetic instead of guarding with if-checks. Handle negative remainders correctly.
1 parent fbbdafb commit 03ff333

1 file changed

Lines changed: 17 additions & 32 deletions

File tree

ext/date/php_date.c

Lines changed: 17 additions & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -3288,7 +3288,7 @@ static bool php_date_modify(zval *object, char *modify, size_t modify_len) /* {{
32883288
php_date_obj *dateobj;
32893289
timelib_time *tmp_time;
32903290
timelib_error_container *err = NULL;
3291-
timelib_sll rel_h, rel_i, rel_s, rel_us;
3291+
timelib_sll rel_h, rel_i, rel_s, rel_us;
32923292

32933293
dateobj = Z_PHPDATE_P(object);
32943294

@@ -3357,10 +3357,8 @@ static bool php_date_modify(zval *object, char *modify, size_t modify_len) /* {{
33573357

33583358
timelib_time_dtor(tmp_time);
33593359

3360-
/* Strip relative h/i/s/us before timelib_update_ts() so that
3361-
* do_adjust_relative() does not add them to wall-clock fields.
3362-
* Wall-clock addition breaks at DST boundaries; SSE arithmetic
3363-
* (applied below) is always correct. */
3360+
/* do_adjust_relative() applies h/i/s as wall-clock, which breaks across
3361+
* DST. Strip them before timelib_update_ts and re-apply via SSE below. */
33643362
rel_h = dateobj->time->relative.h;
33653363
rel_i = dateobj->time->relative.i;
33663364
rel_s = dateobj->time->relative.s;
@@ -3373,34 +3371,21 @@ static bool php_date_modify(zval *object, char *modify, size_t modify_len) /* {{
33733371
timelib_update_ts(dateobj->time, NULL);
33743372
timelib_update_from_sse(dateobj->time);
33753373

3376-
/* Fold microsecond overflow into seconds so that the seconds
3377-
* component goes through SSE arithmetic, not wall-clock.
3378-
* Matches timelib_add_wall()'s do_range_limit() call
3379-
* (interval.c:317). */
3380-
if (rel_us >= 1000000 || rel_us <= -1000000) {
3381-
rel_s += rel_us / 1000000;
3382-
rel_us = rel_us % 1000000;
3383-
}
3384-
3385-
/* Apply h/i/s via SSE (Unix timestamp) arithmetic, matching
3386-
* the approach in timelib_add_wall() (interval.c:312). */
3387-
if (rel_h || rel_i || rel_s) {
3388-
dateobj->time->sse +=
3389-
timelib_hms_to_seconds(rel_h, rel_i, rel_s);
3390-
timelib_update_from_sse(dateobj->time);
3391-
}
3392-
3393-
/* Apply remaining sub-second microseconds. After the above
3394-
* normalization rel_us is in (-1000000, 1000000), so the
3395-
* cascade into seconds is at most +/-1s -- safe to go through
3396-
* wall-clock normalize + update_ts (have_relative is already
3397-
* cleared by the first timelib_update_ts call). */
3398-
if (rel_us) {
3399-
dateobj->time->us += rel_us;
3400-
timelib_do_normalize(dateobj->time);
3401-
timelib_update_ts(dateobj->time, NULL);
3402-
timelib_update_from_sse(dateobj->time);
3374+
/* Normalize microseconds: fold full seconds into rel_s, keep rel_us >= 0 */
3375+
rel_s += rel_us / 1000000;
3376+
rel_us = rel_us % 1000000;
3377+
if (rel_us < 0) {
3378+
rel_s--;
3379+
rel_us += 1000000;
3380+
}
3381+
3382+
dateobj->time->sse += timelib_hms_to_seconds(rel_h, rel_i, rel_s);
3383+
dateobj->time->us += rel_us;
3384+
if (dateobj->time->us >= 1000000) {
3385+
dateobj->time->us -= 1000000;
3386+
dateobj->time->sse++;
34033387
}
3388+
timelib_update_from_sse(dateobj->time);
34043389

34053390
dateobj->time->have_relative = 0;
34063391
memset(&dateobj->time->relative, 0, sizeof(dateobj->time->relative));

0 commit comments

Comments
 (0)