zackistumblr RSS

PHP Times and Dates for Beginners

Feb 27, 2010

preview

A key portion of programming is keeping track of when things occur. In this article we are going to look at a few basic components of working with times and dates in PHP, including creating, formatting, manipulating, & comparing.

This article assumes that you at least have some basic knowledge of PHP.

Tutorial Details

  • Program: PHP
  • Version: >= 4
  • Difficulty: 1
  • Estimated Completion Time: 40 Minutes

Introduction

There are several ways to keep track of times and dates in PHP, but the most common is Unix timestamps. Unix timestamps are simply the number of seconds that have elapsed since January 1st 1970. January 1st 1970 is very commonly called Epoch, and we will refer to it as such for the rest of the tutorial.

It is very important to realize that the larger the value of the timestamp, the more recent the date. 1234567890 happened before 1261629308. This can be somewhat confusing. For example someone with a birthday timestamp of a relatively smaller value, is actually older than someone with a birthday timestamp of a larger value.

Getting Current Time

When working in PHP, we get the current Unix timestamp by calling PHP’s time() function. time() returns an integer.

// returns the current unix timestamp

echo time();

This would print something like: 462949200

So what good does this do? How can I tell a user that they joined my site on 1234567890? You can’t, or at least, you shouldn’t. That’s why you need to format this date.

Formatting

PHP handles formatting dates with the date() function. The date() function takes two parameters. The first parameter is a string that defines the output formatting, and the second parameter is an optional timestamp. If no timestamp is supplied date() uses the current timestamp. The string is defined using several formatting options.

For example, we could display 1234567890 (Feb 13, 2009 @ 5:31:30) in the following ways:

$date = 1234567890;



echo date('M d, Y @ g:i:s', $date);

// prints "Feb 13, 2009 5:31:30"



$format_string = 'm/d/Y'; // obviously we can use a variable

echo date($format_string, $date);

// prints "02/13/2009"



echo date('g:i a', $date);

// prints "5:31 pm"



echo date('M d, Y', $date) . ' was a ' . date('l', $date);

// prints "Feb 13, 2009 was a Wednesday"

‘Making’ Time

Lots of times, we are not interested the current date, and we don’t know off hand how many seconds our user’s birthday was since Epoch, but we still need to work with this date. That’s where PHP’s mktime() function comes into play. mktime() is going to return the same integer that time() returns, except it isn’t based on the current time, it is based on the arguments that you specify.

mktime() takes 7 (well, actually 8) arguments, all integers, all optional, and then returns a timestamp. In order these arguments are: ‘Hour,’ ‘Minute,’ ‘Second,’ ‘Month’, ‘Day,’ and ‘Year.’ The function call looks like this:

				

// create a unix timestamp for September, 07 1985

// mktime(hour, minute, second, month, day, year)

$birthday = mktime(0, 0, 0, 09, 07, 1985);



echo $birthday;

// prints 494917200

This would store a timestamp in the variable $birthday. We could, of course, format this date using date() if we wanted to, but what if we need to find the timestamp for next years date?

Manipulation

Remember that time() & mktime() return simple integers? This is extremely convenient because this allows us to preform simple arithmetic on the timestamp. All we need to do is add or subtract the number of seconds in the given time period that we need results for. We can do this in a few ways:

Addition & Subtraction

This will give us the unix timestamp for one month from today.

$now = time();

// returns 1234567890 -> Feb, 13, 2009 @ 5:31:30



$next_week = $now + 604800;   // 7(days)*24(hours)*60(minutes)*60(seconds) = 604800(seconds)

// returns 1235176290 ->  02/20/09 @ 6:31:30pm 



$tomorrow  = $now + 86400;    // 24*60*60 = 86400

// returns 1234654290 ->  02/14/09 @ 5:31:30pm 



$last_year = $now - 31536000; // 265*24*60*60 = 31536000

// returns 1203031890 -> 02/14/08 @ 5:31:30pm 



mktime() & date()

We can also use mktime() with date() to do date manipulation. Consider this example:

$next_month = mktime(0, 0, 0, date('m') + 1, date('d'), date('Y'));

// outputs 1264226400 ->  01/23/10 @ 12:00:00am



Obviously, we can use the date() function to format these:

echo date('M d, Y g:i:s a', $next_month);

// output Feb 20, 2009 

So, now we have four completely different, and completely valid Unix timestamps, but that seems like a lot of work. What if there was an easier way to create dates? Something will a little less multiplying-by-60? Well There is.

strtotime()

The easiest way to work with and manipulate dates in PHP is with strtotime(). strtotime() takes two arguments, the first is a string, and second is an optional integer, which is a timestamp. We can pass strtotime() an amazing amount of strings, such as ‘now’, ‘tomorrow’, ‘next year’, ‘next thursday’, and ‘two weeks ago’. The list goes on for seemingly forever. The second argument is a timestamp for the string to be relative to. If no timestamp is provided, the current timestamp will be used.

Considering the following examples:

echo strtotime("now");

// prints 1261592896 ->  12/23/09 @ 12:28:16pm



echo strtotime("last week");

// prints 1260815349 ->  12/14/09 @ 12:29:09pm 



echo strtotime("+2 years", 1234567890);

// prints 1297639890 -> 02/13/11 @ 5:31:30pm

strtotime() will also accept dates formatted in several different ways, so you can go backwards from a pre-formatted date to a unix timestamp.

echo strtotime('02/15/2005 10:15am');

// prints 1108484100	

This is extremely powerful when you are getting dates from an unknown source, such as an RSS or ATOM feed. However, there are occasions when strtotime() can fail. In PHP versions less than 5.1, strtotime() returns -1 on failure. In PHP versions 5.1 or greater strtotime() returns false. You can check for failure in the following manor:

$bad_string = 'strtotime() cannot parse this';



if (($timestamp = strtotime($bad_string)) === false) {

	echo $bad_string . ' cannot be parsed';

} else {

	echo date('M d, Y', $timestamp);

}					

Comparison

Dates as integers become extremely useful when need to start comparing them against other dates. Very often it is necessary to see if one date occurs before a certain date, or if a date conflicts with another. For example, let’s write a little block of code to see if a user is old enough to access an alcohol related website.

$required_age = 21;

$required_dob = mktime(0, 0, 0, date('m'), date('d'), date('Y') - $required_age);



$user_dob = strtotime('Jan 07, 1992');



if ($user_dob > $required_dob) {

	$years_left = date('Y', $user_dob) - date('Y', $required_dob);

	echo 'sorry, you have ' . $years_left . ' years left' . "\n";

} else {

	echo 'time for a beer' . "\n";

}

This code is very simple, but shows the power of using dates as integers. Line 1 we just set a legal drinking age. Line 2 we use mktime() with date() to produce a legal drinking age. We are passing 0’s in as the first three parameters, because we don’t care about the time of birth. We then use the current month, the current day, and finally, take the current year and subtract 21. Line 4 is a date the user entered. This could have came from a database, or an input form. It doesn’t really matter.

The actual comparison happens on lines 6. We just see if the integer stored in $user_dob is greater than the legal birthday. This would mean the person was born after the required date, and fails the if condition.

As a little extra feature, we do a simple calculation to find out how many remaining years until the user is allowed in & satisfy the if condition on line 6.

We can also use date comparison to see if one date overlaps another date. Consider the following code.

$first_appointment_start = mktime(13, 0, 0, date('m'), date('d'), date('Y'));

$first_appointment_end = strtotime("+1 Hour", $appointment_start);



$second_appointment_start = mktime(13, 30, 0, date('m'), date('d'), date('Y'));

$second_appointment_end = strtotime("+1 Hour", $new_appointment_start);



if ( $second_appointment_start > $first_appointment_start && $second_appointment_start < $first_appointment_end ) {

	echo 'appointment conflict';

} else {

	echo 'appointment approved';

}

Here we are just defining a few arbitrary dates. $first_appointment_start is 1:00pm “today,” and $first_appointment_end is just one hour after $first_appointment_start, which is 2pm. $second_appointment_start is set to 1:30pm, and $second_appointment_end (which isn’t necessary, but included for completeness) is set for 2:30pm.

The if statement on line 7 first checks to see if the second appointment starts after the first appointment, and also starts before the first appointment is over. This particular appointment situation would print “appointment conflict.”

Conclusion

Thank you for taking a few minutes to read this article. Feel free to leave comments and complaints, I’ll do my best to address each and every one of them.

blog comments powered by Disqus

About the Author

Portrait photo for zackistumblr

Zack Kitzmiller is a Webdeveloper in Rockford, Il. I write Code in PHP and CodeIgniter. I make parts of streak.ly

Following:

jimkitzmiller spacedriver kylewritescode gary iwdrm forrst