Skip to Content
Course content

96: DateInterval and DatePeriod

Click on the "Edit" button in the top corner of the screen to edit your slide content.

How do I define a specific duration of time without a fixed date?

You've probably spent a lot of time with DateTime, but DateTime is a point in time. When you want to describe a duration—like "three weeks" or "two months and five days"—that's where DateInterval comes in. It doesn't know what today is; it only knows how much time has passed or needs to pass.

The trickiest part about DateInterval is the constructor. It uses the ISO 8601 duration format, which looks like a secret code at first. It starts with 'P' (for Period), followed by the years, months, days, etc. Here is how I usually handle it:

// 'P1M2D' means Period: 1 Month and 2 Days
$interval = new DateInterval('P1M2D');

$now = new DateTime();
$futureDate = $now->add($interval);

echo "If you wait 1 month and 2 days from now, it will be: " . $futureDate->format('Y-m-d');

I'll be honest: memorizing those strings (P1Y, P1M, P1D) is a pain. If you find it confusing, you can also pass an associative array to the constructor using keys like 'days' or 'months', but the string format is what you'll see most often in professional codebases.

I have a start and end date; how do I get every day in between?

If you're building something like a booking calendar or a project timeline, you don't want to write a while loop and manually add days to a date object. That's tedious and error-prone. Instead, use DatePeriod.

DatePeriod is an iterator. It takes a start date, an interval, and an end date, and then lets you loop through the resulting dates as if they were a simple array. Check this out:

$start = new DateTime('2023-12-01');
$end = new DateTime('2023-12-10');
$interval = new DateInterval('P1D'); // One day intervals

$period = new DatePeriod($start, $interval, $end);

foreach ($period as $date) {
    echo $date->format('Y-m-d') . "\n";
}

Notice that the end date is exclusive. In the example above, December 10th won't actually show up in the loop. If you need the end date included, you'll have to add one day to your end date object before passing it into the DatePeriod constructor.

Can I use this for recurring events, like a monthly subscription?

Absolutely. One of the coolest things about DatePeriod is that you don't actually need an end date. You can tell it exactly how many times to repeat the interval instead.

This is perfect for things like generating a payment schedule for a customer. If a user signs up for a 6-month plan, you don't need to calculate the end date first; just tell PHP to repeat the "one month" interval six times.

$startDate = new DateTime('first day of this month');
$interval = new DateInterval('P1M'); // Monthly
$recurrences = 6;

// Note: we omit the end date and pass the number of recurrences instead
$period = new DatePeriod($startDate, $interval, $recurrences);

foreach ($period as $date) {
    echo "Payment due on: " . $date->format('F j, Y') . "\n";
}

I prefer this approach for subscriptions because it avoids the "off-by-one" errors that often happen when calculating end dates manually.




📋 Practical Task

Exercise: Generating a 12-Month Membership Milestone Map

Imagine you are building a membership portal. When a user joins, you want to show them a list of the exact dates they will hit their 1-month, 2-month, ..., and 12-month milestones.

Your Task:

  • Create a DateTime object representing the user's join date (you can use any date from the past or present).
  • Create a DateInterval for exactly one month.
  • Use DatePeriod to generate a sequence of 12 dates starting from the join date.
  • Loop through the period and print each date in the format: "Milestone [X]: [Date]" (where [X] is the month number from 1 to 12).
Rating
0 0

There are no comments for now.

to be the first to leave a comment.