DateTime class vs. native PHP date-functions
Asked Answered
R

4

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
Ruella answered 22/12, 2011 at 14:52 Comment(0)
D
49

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.

Devora answered 22/12, 2011 at 14:58 Comment(14)
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 happyPurse
I see the 'handyness' of DateTime, but would you also use it for simple things like the ones I just added to my question ?Ruella
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.Devora
@Mark: PHP's DateTime class isn't near as spiffy as .net's in that regard. At least not yet. Far as i'm seeing, it's limited to 4-digit years (probably because it uses PHP's old date/time functions to parse the date)...though that does give you the range of -9999 to 9999...Nafis
Sadly, most bugs were NOT fixed by 5.4. bugs.php.net/bug.php?id=40743 bugs.php.net/bug.php?id=49914 bugs.php.net/bug.php?id=51051 bugs.php.net/bug.php?id=51557 bugs.php.net/bug.php?id=52480 bugs.php.net/bug.php?id=54340 bugs.php.net/bug.php?id=54655 bugs.php.net/bug.php?id=55253 bugs.php.net/bug.php?id=60873 bugs.php.net/bug.php?id=60960 bugs.php.net/bug.php?id=61022 bugs.php.net/bug.php?id=61311 bugs.php.net/bug.php?id=61530 bugs.php.net/bug.php?id=61955Ensconce
Even creating 1 million DateTime objects shouldn't be significantly worse than calling strtotime() 1 million times. The parsing of a string into a date is going to be the bigger burden by many orders of magnitude than any overhead instantiating an object. I'm not sure about the additional storage requirements for a DateTime over an int, but it won't be much, and you're benefitting from the ability to store years before 1902 or after 2037. In short, PHP's old way of treating dates as ints is more broken than using DateTime and being not broken trumps small performance differences.Schmo
You may well want to use DateTimeImmutable in preference to DateTime as of PHP 5.5 . See derickrethans.nl/immutable-datetime.html for more infoAq
@Ensconce after reading the bug reports, it seems that DateTime is only safe to get the current moment, increments relative to the current moment, and compare values (not to calculate the difference). Date arithmetic is wrong, intervals are not safe, it is better to stick to a single time zone and use setTimeZone to set it. It should also be noted that the time zone only affects the formatting and is not taked into account in comparisons.Transpicuous
I agree with "If it makes sense to use DateTime class in order to perform certain date calculations, then use it."Tuyere
PHP's date and mktime() allow me to easily create the versatile and dynamic date and time calculations I need using simple arithmetic operators. most cases even in one line. However I use them to the point I see a significant slowdown. Only then I look for alternate methods. If you are looking for speed in a specific function or need, it's always worth a google search.Tuyere
Here is my benchmark on my i7 8Go Win 7 running PHP 7.1 on XAMPP server : date function : 4.1662380695343 DateTime class : 7.1334080696106. Here is the code I used to run this test (for 1 million loops).Syck
You say unless you do something crazy such as creating 1 million DateTime objects. What would be a limit for you? I have a few thousand reccords where I want to run DateTime. Is that to many ( for performance / speed op the app)Himmler
@Himmler 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 :)Devora
I have tried like you said. 250k records ran in about 1second. This is on PHP53. We are migrating to 72 atm, so by the time this hits production it should run even faster.Himmler
R
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"
}
Rathenau answered 2/12, 2018 at 12:21 Comment(5)
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.Halfbaked
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)Malraux
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...Himyaritic
In your example, if you are not storing timezone with your string, it will not work if your application is used in different timezones.Clamor
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 timezoneRathenau
C
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.

Clamor answered 2/5, 2019 at 17:3 Comment(0)
A
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).

Ambriz answered 27/6, 2021 at 16:25 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.