28

The DateTime class sure has some handy methods and seems overall superior to the native PHP date functions like strtotime, mktime and strftime (and more). But is there any drawback or a reason why I shouldn't use it ?

The only reason I can think of is that it might be more expensive to create a whole instance of a class than just using a function.

  • Would you agree with that ?
  • Does it make sense at all to use a DateTime object for simple stuff?
  • Are there any other drawbacks ?

It seems a bit confusing to switch between those two options all the time, so I'd like to have clearance what I should prefer doing.

Two examples for my decision would be:

  • Converting a date to a localized value
  • Calculating the time between two dates

4 Answers 4

50

If your worry is that creating a class instance is expensive and that it'll hinder performance, then I'm afraid you're barking at the wrong tree. One should never consider whether to use proven OO approach where it makes sense. If it makes sense to use DateTime class in order to perform certain date calculations, then use it. It's not expensive to the point where your app will feel it, unless you do something crazy such as creating 1 million DateTime objects.

Reason why DateTime is great is because it alleviates the worry of daylight savings by specifying the time zone when creating the object. It's also easy to obtain differences between dates or obtain intervals between different objects. It basically cuts down the amount of worry and coding required (but I will admit it is wrong sometimes, hopefully it'll get addressed in 5.4 release of PHP).

Bottom line - I'd always use it.

Sign up to request clarification or add additional context in comments.

14 Comments

plus the date range, even in a 32-bit PHP environment, is enough to keep a paleobiologist or a cosmologist studying the beginning or end of the universe happy
I would, because let's take mktime or strtotime functions - they require certain order of parameters representing the day, year, month, hour etc. With DateTime I can create the object using arbitrary parameters like $date = DateTime::createFromFormat('m H:s D-Y', $weird_user_input); which can then be formatted to unix timestamp or whatever other date format I wish. I can even specify the time zone immediately while creating the object. So yes, I'd definitely use it since I don't really see where procedural way would aid me better.
You may well want to use DateTimeImmutable in preference to DateTime as of PHP 5.5 . See derickrethans.nl/immutable-datetime.html for more info
@nclsvh you should measure, even creating a million datetime objects isn't farfetched these days - hardware is better, we have php 7.2 etc. However, it depends on what you're going to do with those objects. You can always create 1 DateTime object and set a different timestamp etc. Since you can literally measure what's going to happen in your case, you don't have to rely on my opinion. Here's a small test result I ran on my vagrant VM - to create 1 million DT objects, it took 0.88 seconds. TL;DR: just go for it :)
|
0

For the record, I did the mistake to use the class DateTime. It was a big mistake. While it has some nice features, but it is not worth the effort. I explain:

Let's say that you have a form (with a date-picker) and you are storing into the database, then you have 3 formats to represent the date.

  1. Internally, the variable is of the type DateTime()
  2. Visually, the variable displayed to the user is a string of the format dd-mm-yyyy or mm-dd-yyyy (it depends on the regional setting)
  3. In the database, the variable stored is also a string of the format yyyy-mm-dd (ANSI)

So, I am dealing with 3 different kinds of representation for the same type of data

Also, let's say that you want to serialize (json, xml or such), it is the serialization:

object(stdClass)#1 (1) {
  ["field1"]=>
  object(DateTime)#2 (3) {
    ["date"]=>
    string(26) "2018-12-02 09:14:09.216273"
    ["timezone_type"]=>
    int(3)
    ["timezone"]=>
    string(30) "America/Argentina/Buenos_Aires"
  }
}

It is a real pain to try to serialize. My alternative is simple, to store any temporal date as a string and I will convert it to DateTime only if it's needing.

object(stdClass)#3 (1) {
  ["field1"]=>
  string(19) "2018-12-02 09:14:09"
}

5 Comments

I completely agree that it requires much work to have DateTime on a business layer. In cases where it is worth it, I recommend to use different models for different layers. My view models have strings for dates, while I am working with DateTime on business layer. I can recommend AutomapperPlus to map the entities between layers. Good interface and support. Required only in complex cases, of course.
I think you're not in a better place by not using DateTime object because regardless you always have to consider those 3 layers: 1. How information is used in the code (OOP) 2. How information is stored in the database (DB native data type) 3. How information is displayed/presented to end user (formatting)
Isn't that exactly the benefit of using DateTime though? By dealing with an abstract representation of the date, you're always free to format() it for the case at hand. Usually, any object I'm going to serialize to JSON implements the JsonSerializable interface, so I can format any date properties to RFC date strings. For the database, I'll use ANSI dates, and so on - it's really less painful than having to cast from and to timestamps everywhere...
In your example, if you are not storing timezone with your string, it will not work if your application is used in different timezones.
And it is exactly the point. Let's say 10:15 AM StandardPacific Hour (GMT-8) and our system work globally. Then, let's say we want to read it under GMT-3, we we should read the 10:15 (gmt-8), then convert it to gtm-3 and show it as a local hour. The solution is to save it ZULU / GMT-0 (Greenwich) time, so the conversion is easy and we don't need to save the timezone
0

Using DateTime() makes the code more readable compared to the procedural approach of strtotime(), etc. functions.

if( strtotime( date( 'm/d/Y', strtotime( $strStartDate ) ) ) > strtotime( date( 'm/d/Y', strtotime( '+6 month', strtotime( $strEndDate ) ) ) ) ) {

vs

if( new DateTime( $strStartDate ) > ( new DateTime( $strEndDate ) )->modify( '+6 month' ) ) {

On Windows 64 bit development machines, PHP is still 32bit. It will give your weird results for dates beyond Fri, 13 Dec 1901 20:45:54 UTC to Tue, 19 Jan 2038 03:14:07 UTC

echo ( new DateTime( '20 Jan 2038' ) )->format( 'm/d/Y' ) . PHP_EOL; // gives 01/20/2038
echo strtotime( '20 Jan 2038' ); // returns false

https://www.php.net/manual/en/function.strtotime.php#refsect1-function.strtotime-notes

Note: The valid range of a timestamp is typically from Fri, 13 Dec 1901 20:45:54 UTC to Tue, 19 Jan 2038 03:14:07 UTC. (These are the dates that correspond to the minimum and maximum values for a 32-bit signed integer.) Prior to PHP 5.1.0, not all platforms support negative timestamps, therefore your date range may be limited to no earlier than the Unix epoch. This means that e.g. dates prior to Jan 1, 1970 will not work on Windows, some Linux distributions, and a few other operating systems. For 64-bit versions of PHP, the valid range of a timestamp is effectively infinite, as 64 bits can represent approximately 293 billion years in either direction.


I am not sure if daylight saving is properly handled with native date time functions.


I would recommend using DateTime() functions over native date time functions.

Comments

0

For the record, why you want to use the DateTime class.

@magallanes, your approach is good: convert all dates and times to GMT-0 before saving it to the DB (if applicable).

However, the problem is this: your users are global and therefore you don't know their current time zones and daylight-saving laws. Even if you use your server's own time to save the data in GMT-0, you still don't know how to convert it to the user's time - to correctly print it on his/her statement for example. And if you ask the user what time zone they are in, they might not know exactly; OR they might have forgotten about the daylight-saving rules that recently came into effect; OR their government might have changed their daylight-saving rules since the last time they provided you with their time zone information and therefore they now fall under a different time zone.

So, if new time zone or daylight-saving laws were implemented in the user's country (it happens), we might have the following scenario:
If a time is stored as 07:35 GMT-0 on your server on 1/January, it might be converted to 23:35 on 1/January for your user. But next year, that same server time of 07:35 GMT-0 might not convert to 23:35 for your user any more. In fact, it might even convert to a time on 2/January. That might play a vital role in determining things like: on what day was the transaction closed? ... was the user's insurance policy still effective when the incident occurred? etc.

PHP's DateTime class uses the IANA database to keep track of these changes in countries' time zone and daylight-saving laws. Have a look at the IANA database (www.iana.org/time-zones). It is massive. You will also see that countries that are on the same longitude might use different time zones, because they lean towards the longitudes of their major cities. PHP's DateTime class automatically applies the necessary adjustments when dates and times are converted from a country's current or historical time to GMT-0 and back. For me, that is the biggest plus point of the DateTime class, besides the fact that it can also perform the format conversions between the three layers (db, code, user).

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.