Travelling through Date and Time, part I

This is the first part of a series (of yet-to-be-determined length) dealing with date and time in PHP (and FLOW3).

This first part will cover the very basics of this complex and often very weird topic. Please note that what you’ll read here is often not the whole story, and will be completed in the next parts.

So why am I doing this? Well, I’m trying to put together a calendar package for FLOW3. The calendar should be able to handle events which have a beginning and an optional end. A beginning consists of a date (year, month and day) and, again optional, a time (hour and minute, no seconds). The same applies for the end of an event. Furthermore, when creating an event, the admin should be able to specify the timezone of the dates entered (one timezone for both dates).

This blog post will only deal with the handling of date and time in PHP and FLOW3, I’ll leave the timezone handling for another time.
So, what do we have? Basically, when using date and time in PHP, we use DateTime. DateTime was introduced in PHP 5.2 and provides a way of dealing with, well, date and time. Unfortunately, DateTime is a bit weird. For example, there are at least 3 options to set the date and time of a DateTime objects.
One is to hand it a UNIX timestamp (since 5.3, via setTimestamp). This is the number of elapsed seconds since January 1st 1970, 00:00. In PHP, an integer is used for timestamps. On 32-bit systems, this will mean we’ll run into problems in 2038 because too many seconds will have passed by then to be hold in an 32-bit signed integer. Of course, probably all systems will be 64-bit by then, so not to worry on the PHP part here in my opinion.
A second option is to create the DateTime object with a string like 2010-04-15 17:06:02. You can use any string that you could also pass to strtotime. When you create a DateTime object with no arguments, the string "now" is assumed and you’ll get an object which represents the current date and time.
Weird enough, there is no method similar to setTimestamp to do the same thing later on an object, you have to use the static method DateTime::createFromFormat or use something like the add/sub methods to change the DateTime object later on …
Thirdly, you can use setDate and setTime to modify parts of a DateTime object.

Ok, now on to the next topic: Gettting the date and time back from the object. format() exists for this purpose, which takes a format string (with the same options as for date()). Unfortunately, there is no locale aware format method, but again, more on this in another blog post.

With this covered, what about FLOW3? Basically, handling DateTime objects is baked right into the persistence layer. But how is it persisted? Well, let’s take a step back and have a look at MySQL for a second.
There, you have several options: You can store a regular INTEGER (unix timestamp), or a DATETIME value (and some other options as well). The latter stores a STRING representation of a date and time, but has the advantage that you can do several operations in SQL like comparisons. The INTEGER version of course has the disadvantage that it could run into the 2038 problem mentiond earlier.
Now, back to FLOW3: The persistence backend is generating all SQL queries from the query object, so we can’t use the date/time comparisons. Also, some of these things are MySQL only anyway, so usage of them is not an option for FLOW3 which aims to be more or less backend independent. That means FLOW3 turns the DateTime object into a unix timestamp before persisting it (in an INTEGER field), and converts it back upon reconstitution.

Enough for today. The plan is to write more about handling and comparing DateTime values in FLOW3 in the next part. The third part will probably deal with timezones and then, we’ll have a look at localization.

filed under , , posted on April 15, 2010

Comments are closed.