Saving time with PHP and date math

Saving time with PHP and date math

You may have cringed when reading the term “date math,” which sounds both cumbersome and difficult. It brings to mind the addition and subtraction of tricky numbers like 7, 29, and 31; and concepts like “two weeks from now,” “yesterday,” and “next month.” And if you’ve every tried to build a system that tracks relative dates you know such things can be a hassle.

So why bother? Because date math is very useful! For example, suppose you manage a website that includes due dates, submission deadlines, and priority registration periods that recur. If you’re me, you manage a site that’s full of such dates that recur every academic quarter. Keeping these dates in sync is a task that PHP‘s date math functions were born written to do.

A simple example

To illustrate, let’s use the example of a university’s quarterly due date for grades. We’ll assume there’s an FAQ page that outlines the policies and instructions for faculty grade submissions and that page contains a grade deadline. That deadline changes each quarter. Setting a PHP variable for the key dates on the page (e.g, the end of the quarter or the first day of the grading submission period), makes maintaining dates so much simpler, as in this example:

< ?php
$quarterEnds = "March 26";
$gradesDue = "March 29";
?>
... the end of the quarter is Friday, < ?= $quarterEnds ?> and don't forget, grades are due < ?= $gradesDue ?>.

When it’s time to change the dates, you change them once in an site-wide variables file (and include it on every page in the site) where the key dates and their values are defined. “What’s wrong with just changing the date in the code?” you may ask. Nothing at all. But when that date is used on many pages throughout a large site, changing it in multiple places becomes tedious (and it’s easy to forget one).

“Phsaw!” you scoff. “I’d do a find-and-replace in my editor to quickly change them all. “Touché,” I respond. But what about when that date is presented in multiple ways depending on its context? The example above used just one format: dates in a paragraph of text. But dates in a list might be presented as “Mar. 29, 2010″ or “3/29/2010.” And if you had localized (translated) version of the content, the date format might change, too: “29 March 2010.” The representations of dates are numerous, even more so when you consider the formats for days of the week: Monday, Mon., or just M. Find-and-replacing all those variations is a real chore (and very easy to miss one).

A more realistic example

Based on those various date formatting needs of a website, it’s clear our key-date variable should be simply a data point point (i.e., the date in question) and handle the presentation of that data (i.e., the date’s format) when it’s used in the site. Let’s first change our key-date variable to include a year, which will be useful later:

< ?php
$quarterEnds = "03/26/2010";
$gradesDue = "03/29/2010";
?>

Then, when you display this date on the site, format it using two PHP functions, date() and strtotime(). Both are incredibly useful and sophisticated, so I refer curious readers to their respective pages on PHP’s website for full details. Briefly, though:

  • date() takes some formatting instructions and a timestamp—an integer number used by Unix computer systems to represent a time—and returns a properly-formatted date, with or without a time.
  • strtotime(), which means “string to time,” takes (just about) any written description of a date—a “string”—and turns it into the timestamp format. Some example strings it can handle: “yesterday,” “+1 week”, and “last Monday.” It’s pretty amazing what inputs it can make sense of.

With these two tools, you can easily display dates in any context throughout your site, and change them site-wide just by changing the date in one place: your site-wide variables file. Let’s write the examples above using strtotime() to generate a timestamp that’s passed to date() along with a formatting variables (output shown in the HTML comments):

Important dates

  • Quarter ends < ?= date("m/d/y", strtotime( $quarterEnds ) ) ?>
  • Grades due < ?= date("m/d/y", strtotime( $gradesDue ) ) ?>
  • The end of the quarter is < ?= date("l, F j", strtotime( $quarterEnds ) ) ?> and don't forget, grades are due the < ?= date("jS \o\f F", strtotime( $gradesDue ) ) ?>.

The output of the sentence above is: “The end of the quarter is Friday, March 26 and don’t forget, grades are due the 29th of March.” Two notes about how date() was used here. First, the “l” parameter took the place of hard-coding “Friday” in the text. Sure, the quarter may always end on a Friday, but if it didn’t, date() would properly display the correct day for that date. (That’s why we added the year to the site’s date variable; the year avoids any ambiguity for PHP so it can correctly display the day for that date.) Second, the final date() call included the word “of,” which required the letters be escaped with slashes so date() knew to ignore them. The variations on display are limitless; lots of examples on PHP’s date() page.

Another step forward, and cleaning up

“That’s all dandy,” you may retort if you’re not yet convinced of the utility of this approach. “But what about date ranges? Due dates aren’t always a day, they could be a three-day period or a week or whatever!” Good point! From the examples above, I hope you can see how strtotime() can solve the issue of date ranges, too. Here’s the example from above taken a step further: grades are due within five days following the end of the quarter:

< ?php
  • Grades due between < ?= date("m/d/y", strtotime( $gradesDue ) ) ?> and < ?= date("m/d/y", strtotime( $gradesDue . " +5 days" ) ) ?>
  • Much can be done with these simple and incredibly useful date-math functions PHP offers (as I assume ASP and other languages do, too). A few more notes to wrap-up:

    • Time - This approach works for time, too. If you had a submission cut-off at 5pm, you could add or subtract time to create a range of minutes or hours.
    • “New Year’s Eve” error – Watch out for the dreaded Dec. 31, 1969 date in your display. It appears when an invalid timestamp is passed to date(). If it shows up, something must be wrong with the date string passed to strtotime(), which in turn gives an invalid timestamp to date().
    • Streamlined code – The example code above could be cleaned up by using strtotime() to assign the initial value to the site-wide key-variable date. That way, it can be used directly with date() without having to nest strtotime() within it.
    1. The Abyss is out of date We all know the earth is warming up, much like...
    2. Tricking an HTML form to POST with unselected radio inputs This web-development situation confused me: why wasn't my simple form,...
    3. How .htaccess, PHP & PEAR, and PDFs saved the day (and thousands of dollars) PHP, .htaccess, PDFs, Acrobat, Word, Exchange... that's quite an alphabet...

    Leave a Reply