Skip to content

Fix #61642: modify("+5 weekdays") returns Sunday #122

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
75 changes: 36 additions & 39 deletions ext/date/lib/tm2unixtime.c
Original file line number Diff line number Diff line change
Expand Up @@ -220,55 +220,52 @@ static void do_adjust_relative(timelib_time* time)

static void do_adjust_special_weekday(timelib_time* time)
{
timelib_sll current_dow, count;
timelib_sll count, dow, rem;

count = time->relative.special.amount;
dow = timelib_day_of_week(time->y, time->m, time->d);

current_dow = timelib_day_of_week(time->y, time->m, time->d);
if (count == 0) {
/* skip over saturday and sunday */
if (current_dow == 6) {
time->d += 2;
}
/* skip over sunday */
if (current_dow == 0) {
time->d += 1;
}
} else if (count > 0) {
/* skip over saturday and sunday */
if (current_dow == 5) {
time->d += 2;
}
/* skip over sunday */
if (current_dow == 6) {
/* Add increments of 5 weekdays as a week, leaving the DOW unchanged. */
time->d += (count / 5) * 7;

/* Deal with the remainder. */
rem = (count % 5);

if (count > 0) {
if (rem == 0) {
/* Head back to Friday if we stop on the weekend. */
if (dow == 0) {
time->d -= 2;
} else if (dow == 6) {
time->d -= 1;
}
} else if (dow == 6) {
/* We ended up on Saturday, but there's still work to do, so move
* to Sunday and continue from there. */
time->d += 1;
}
/* add increments of 5 weekdays as a week */
time->d += (count / 5) * 7;
/* if current DOW plus the remainder > 5, add two days */
current_dow = timelib_day_of_week(time->y, time->m, time->d);
time->d += (count % 5);
if ((count % 5) + current_dow > 5) {
} else if (dow + rem > 5) {
/* We're on a weekday, but we're going past Friday, so skip right
* over the weekend. */
time->d += 2;
}
} else if (count < 0) {
/* skip over sunday and saturday */
if (current_dow == 1) {
time->d -= 2;
}
/* skip over satruday */
if (current_dow == 0 ) {
} else {
/* Completely mirror the forward direction. This also covers the 0
* case, since if we start on the weekend, we want to move forward as
* if we stopped there while going backwards. */
if (rem == 0) {
if (dow == 6) {
time->d += 2;
} else if (dow == 0) {
time->d += 1;
}
} else if (dow == 0) {
time->d -= 1;
}
/* subtract increments of 5 weekdays as a week */
time->d += (count / 5) * 7;
/* if current DOW minus the remainder < 0, subtract two days */
current_dow = timelib_day_of_week(time->y, time->m, time->d);
time->d += (count % 5);
if ((count % 5) + current_dow < 1) {
} else if (dow + rem < 1) {
time->d -= 2;
}
}

time->d += rem;
}

static void do_adjust_special(timelib_time* time)
Expand Down
62 changes: 62 additions & 0 deletions ext/date/tests/bug61642.phpt
Original file line number Diff line number Diff line change
@@ -0,0 +1,62 @@
--TEST--
Bug #61642 (modify("+5 weekdays") returns Sunday)
--INI--
date.timezone=UTC
--FILE--
<?php
// ±5 and ±10 (and any non-zero multiple of 5) is broken, but everything else
// should already work correctly.
$weekdays = range(-11, 11);
$dates = array('2012-03-29', '2012-03-30', '2012-03-31', '2012-04-01', '2012-04-02', '2012-04-03', '2012-04-04', '2012-04-05');

$header = array();

foreach ($dates as $startdate) {
$date = new DateTime($startdate);

$header[] = $date->format('Y-m-d D');
}

echo '### ', implode(' ', $header), "\n\n";

foreach ($weekdays as $days) {
$line = array();

printf('%+3d ', $days);

foreach ($dates as $startdate) {
$date = new DateTime($startdate);
$date->modify("{$days} weekdays");

$line[] = $date->format('Y-m-d D');
}

echo implode(' ', $line), "\n";
}
?>
--EXPECTF--
### 2012-03-29 Thu 2012-03-30 Fri 2012-03-31 Sat 2012-04-01 Sun 2012-04-02 Mon 2012-04-03 Tue 2012-04-04 Wed 2012-04-05 Thu

-11 2012-03-14 Wed 2012-03-15 Thu 2012-03-16 Fri 2012-03-16 Fri 2012-03-16 Fri 2012-03-19 Mon 2012-03-20 Tue 2012-03-21 Wed
-10 2012-03-15 Thu 2012-03-16 Fri 2012-03-19 Mon 2012-03-19 Mon 2012-03-19 Mon 2012-03-20 Tue 2012-03-21 Wed 2012-03-22 Thu
-9 2012-03-16 Fri 2012-03-19 Mon 2012-03-20 Tue 2012-03-20 Tue 2012-03-20 Tue 2012-03-21 Wed 2012-03-22 Thu 2012-03-23 Fri
-8 2012-03-19 Mon 2012-03-20 Tue 2012-03-21 Wed 2012-03-21 Wed 2012-03-21 Wed 2012-03-22 Thu 2012-03-23 Fri 2012-03-26 Mon
-7 2012-03-20 Tue 2012-03-21 Wed 2012-03-22 Thu 2012-03-22 Thu 2012-03-22 Thu 2012-03-23 Fri 2012-03-26 Mon 2012-03-27 Tue
-6 2012-03-21 Wed 2012-03-22 Thu 2012-03-23 Fri 2012-03-23 Fri 2012-03-23 Fri 2012-03-26 Mon 2012-03-27 Tue 2012-03-28 Wed
-5 2012-03-22 Thu 2012-03-23 Fri 2012-03-26 Mon 2012-03-26 Mon 2012-03-26 Mon 2012-03-27 Tue 2012-03-28 Wed 2012-03-29 Thu
-4 2012-03-23 Fri 2012-03-26 Mon 2012-03-27 Tue 2012-03-27 Tue 2012-03-27 Tue 2012-03-28 Wed 2012-03-29 Thu 2012-03-30 Fri
-3 2012-03-26 Mon 2012-03-27 Tue 2012-03-28 Wed 2012-03-28 Wed 2012-03-28 Wed 2012-03-29 Thu 2012-03-30 Fri 2012-04-02 Mon
-2 2012-03-27 Tue 2012-03-28 Wed 2012-03-29 Thu 2012-03-29 Thu 2012-03-29 Thu 2012-03-30 Fri 2012-04-02 Mon 2012-04-03 Tue
-1 2012-03-28 Wed 2012-03-29 Thu 2012-03-30 Fri 2012-03-30 Fri 2012-03-30 Fri 2012-04-02 Mon 2012-04-03 Tue 2012-04-04 Wed
+0 2012-03-29 Thu 2012-03-30 Fri 2012-04-02 Mon 2012-04-02 Mon 2012-04-02 Mon 2012-04-03 Tue 2012-04-04 Wed 2012-04-05 Thu
+1 2012-03-30 Fri 2012-04-02 Mon 2012-04-02 Mon 2012-04-02 Mon 2012-04-03 Tue 2012-04-04 Wed 2012-04-05 Thu 2012-04-06 Fri
+2 2012-04-02 Mon 2012-04-03 Tue 2012-04-03 Tue 2012-04-03 Tue 2012-04-04 Wed 2012-04-05 Thu 2012-04-06 Fri 2012-04-09 Mon
+3 2012-04-03 Tue 2012-04-04 Wed 2012-04-04 Wed 2012-04-04 Wed 2012-04-05 Thu 2012-04-06 Fri 2012-04-09 Mon 2012-04-10 Tue
+4 2012-04-04 Wed 2012-04-05 Thu 2012-04-05 Thu 2012-04-05 Thu 2012-04-06 Fri 2012-04-09 Mon 2012-04-10 Tue 2012-04-11 Wed
+5 2012-04-05 Thu 2012-04-06 Fri 2012-04-06 Fri 2012-04-06 Fri 2012-04-09 Mon 2012-04-10 Tue 2012-04-11 Wed 2012-04-12 Thu
+6 2012-04-06 Fri 2012-04-09 Mon 2012-04-09 Mon 2012-04-09 Mon 2012-04-10 Tue 2012-04-11 Wed 2012-04-12 Thu 2012-04-13 Fri
+7 2012-04-09 Mon 2012-04-10 Tue 2012-04-10 Tue 2012-04-10 Tue 2012-04-11 Wed 2012-04-12 Thu 2012-04-13 Fri 2012-04-16 Mon
+8 2012-04-10 Tue 2012-04-11 Wed 2012-04-11 Wed 2012-04-11 Wed 2012-04-12 Thu 2012-04-13 Fri 2012-04-16 Mon 2012-04-17 Tue
+9 2012-04-11 Wed 2012-04-12 Thu 2012-04-12 Thu 2012-04-12 Thu 2012-04-13 Fri 2012-04-16 Mon 2012-04-17 Tue 2012-04-18 Wed
+10 2012-04-12 Thu 2012-04-13 Fri 2012-04-13 Fri 2012-04-13 Fri 2012-04-16 Mon 2012-04-17 Tue 2012-04-18 Wed 2012-04-19 Thu
+11 2012-04-13 Fri 2012-04-16 Mon 2012-04-16 Mon 2012-04-16 Mon 2012-04-17 Tue 2012-04-18 Wed 2012-04-19 Thu 2012-04-20 Fri