Dates7 min readExamples run on PHP 8.5.10

date_isodate_set()

Learn how date_isodate_set() moves a DateTime to an ISO 8601 year, week and weekday, with runnable UTC examples, overflow behavior and common mistakes.

Signature

date_isodate_set(DateTime $object, int $year, int $week, int $dayOfWeek = 1): DateTime
Available since PHP 5.2.07.48.08.18.28.38.48.5All versions →

Purpose

date_isodate_set() is the procedural alias of DateTime::setISODate(). It changes the calendar date of an existing DateTime object so that it falls on a given ISO 8601 week-date: an ISO year, a week number and a day of the week. The time of day is left alone.

This is useful for scheduling code that thinks in weeks, such as "Wednesday of week 10", where converting by hand to a month and day would be error-prone. ISO weeks start on Monday, and week 1 is the week that contains the first Thursday of the year. That means the ISO year can differ from the calendar year around New Year.

Signature

Parameters and defaults

  • $object: the DateTime to modify. It is changed in place. A DateTimeImmutable is not accepted by this procedural function and causes a TypeError.
  • $year: the ISO year, not necessarily the calendar year.
  • $week: the ISO week number. Normal values are 1 to 52 or 53, but out-of-range values are allowed and roll over.
  • $dayOfWeek: the day within the week, where 1 is Monday and 7 is Sunday. It defaults to 1.

Return value and failure cases

The function returns the same DateTime object that you passed in, so the result is identical (===) to the argument. The object is modified, not copied. Wrong argument types, such as passing an array or a DateTimeImmutable, throw a TypeError rather than returning a failure value.

Example 1: moving to a week and weekday

The first example starts on a Monday morning and moves to Wednesday of ISO week 10 in 2024. Notice that the time 10:30:00 survives.

Example
<?php
date_default_timezone_set('UTC');
$date = date_create('2024-01-01 10:30:00');
date_isodate_set($date, 2024, 10, 3);
echo $date->format('Y-m-d H:i:s'), "\n";
Output
2024-03-06 10:30:00

Example 2: the default weekday and ISO year boundaries

When you omit $dayOfWeek, you get Monday. The second example asks for week 53 in two different years. The year 2020 really has 53 ISO weeks, so its week 53 Monday is in December 2020. The year 2021 has only 52, so week 53 rolls over into the next calendar year.

Example
<?php
date_default_timezone_set('UTC');
$a = date_create('2021-06-15');
date_isodate_set($a, 2021, 53);
$b = date_create('2020-06-15');
date_isodate_set($b, 2020, 53);
echo json_encode([$a->format('Y-m-d'), $b->format('Y-m-d')]), PHP_EOL;
Output
["2022-01-03","2020-12-28"]

Example 3: return value and day overflow

The returned object is the one you passed in, which allows chaining but also means the original variable changes. A $dayOfWeek of 8 moves into the next week, and 0 moves back to the Sunday before Monday.

Example
<?php
date_default_timezone_set('UTC');
$date = date_create('2024-01-01 08:00:00');
$result = date_isodate_set($date, 2024, 10, 8);
$first = [$result === $date, $date->format('Y-m-d H:i')];
$sunday = date_create('2024-01-01');
date_isodate_set($sunday, 2024, 10, 0);
echo json_encode([$first[0], $first[1], $sunday->format('Y-m-d')]), PHP_EOL;
Output
[true,"2024-03-11 08:00","2024-03-03"]

Edge cases

  • ISO year versus calendar year. Dates in late December can belong to week 1 of the next ISO year, and early January dates can belong to week 52 or 53 of the previous one. Pair this function with the o format character (ISO year), not Y, when you read values back.
  • Overflow is arithmetic. A week or day outside the normal range is not rejected; it is counted forward or backward from the base of the given ISO year and week. This is handy for "add N weeks" logic but hides typos.
  • Time is preserved. Only the date part changes. If you need midnight, call setTime() or date_time_set() afterwards.
  • In-place mutation. Cloning first is the way to keep the original date.

Common mistakes

  1. Using the calendar year. Passing 2021 for a date that is in ISO year 2020 gives a different date than expected near New Year.
  2. Treating Sunday as 0 as the first day. In ISO numbering Monday is 1 and Sunday is 7. A value of 0 works only as an overflow into the previous Sunday.
  3. Assuming a copy is returned. The function returns the same mutable object, so earlier references observe the change.
  4. Passing an immutable object. Use the DateTimeImmutable::setISODate() method if you work with immutable dates; it returns a new object.
  5. Forgetting the time zone. The date is interpreted in the object's own time zone, so set it explicitly when examples must be deterministic.
  • DateTime::setISODate(): the method form of this alias.
  • DateTimeImmutable::setISODate(): the non-mutating counterpart.
  • date_date_set(): set a year, month and day instead of an ISO week-date.
  • date_time_set(): change the time of day.
  • date_create(): create the DateTime that you pass in.

Recap

date_isodate_set() takes a DateTime, an ISO year, a week and an optional ISO weekday (default 1, Monday). It mutates the object, keeps its time of day, rolls out-of-range values over and returns the same object. Remember that the ISO year can differ from the calendar year, and use the method form when you prefer an object-oriented style.

Tested examples

Move a date to Wednesday of ISO week 10
<?php
date_default_timezone_set('UTC');
$date = date_create('2024-01-01 10:30:00');
date_isodate_set($date, 2024, 10, 3);
echo $date->format('Y-m-d H:i:s'), "\n";
Output
2024-03-06 10:30:00
Default weekday and week 53 across ISO years
<?php
date_default_timezone_set('UTC');
$a = date_create('2021-06-15');
date_isodate_set($a, 2021, 53);
$b = date_create('2020-06-15');
date_isodate_set($b, 2020, 53);
echo json_encode([$a->format('Y-m-d'), $b->format('Y-m-d')]), PHP_EOL;
Output
["2022-01-03","2020-12-28"]
Same object returned and day overflow
<?php
date_default_timezone_set('UTC');
$date = date_create('2024-01-01 08:00:00');
$result = date_isodate_set($date, 2024, 10, 8);
$first = [$result === $date, $date->format('Y-m-d H:i')];
$sunday = date_create('2024-01-01');
date_isodate_set($sunday, 2024, 10, 0);
echo json_encode([$first[0], $first[1], $sunday->format('Y-m-d')]), PHP_EOL;
Output
[true,"2024-03-11 08:00","2024-03-03"]