# DateTime improvement

- Thread: https://externals.io/message/64232
- Original archive: https://news-web.php.net/php.internals/64232
- Started by Nikita Nefedov on 2012-12-10T15:18:06+00:00
- Messages: 34
- Page 1 of 2: messages 1 to 25 (25 per page, add `?page=N` to the URL)
- Next page: https://externals.io/message/64232.md?page=2
- Reply by email to internals@lists.php.net
- More for agents: search with https://externals.io/search.md?q={query} · JSON API at https://externals.io/api · documentation at https://externals.io/llms.txt

---

## #64232 — Nikita Nefedov — 2012-12-10T15:18:06+00:00

URL: https://externals.io/message/64232#64232

So there had been at least two or three messages (subjects) about DateTime  
object and everytime there was this problem - people tend to take DateTime  
object as mutable object and it really is.
As long as we know, it's not so good - date is immutable by nature. I  
don't want to write here why it's so, I will just throw this link:  
http://www.ibm.com/developerworks/java/library/j-jtp02183/index.html

I don't want to change any existing functionality, because some people  
already use it, but I just wanted to point out that current DateTime class  
is forcing people to think about it as mutable.
My main concerns are DateTime#add() and DateTime#sub(). The problem is -  
they both change current object and return it.
I think we could add methods to DateTime like add() and sub(), let's say  
plus() and minus(), but they would behave differently in the way that they  
would return new DateTime objects and won't change current object.

Here's gist to make it clear: https://gist.github.com/4250785

Also, there's methods compareTo, createFromTimestamp and createFromDay, it  
could be another proposal. I think we are very often create DateTime  
objects just from timestamp or year-month-day. So we could introduce this  
methods that could not rely on timelib's parsing, and instead just take  
numbers directly.
And I think DateTime lack comparing method. For now I can compare DateTime  
objects only by getting their timestamps, but I though that the idea of  
DateTime was to go away from using timestamps and instead use well thought  
out api.
Anyway, I think this three methods should be considered as another  
proposal (because they are solve different problems).

Even if this proposal doesn't go far, I think we should do something with  
DateTime. I think I'm going to create user-land library for dealing with  
some of this problems.
But if it pass, I will make patch.

---

## #64233 — keisial@gmail.com — 2012-12-10T19:39:40+00:00

URL: https://externals.io/message/64232#64233 · In reply to: #64232

> So there had been at least two or three messages (subjects) about
> DateTime object and everytime there was this problem - people tend to
> take DateTime object as mutable object and it really is.
> As long as we know, it's not so good - date is immutable by nature. I
> don't want to write here why it's so, I will just throw this link:
> http://www.ibm.com/developerworks/java/library/j-jtp02183/index.html
>
> I don't want to change any existing functionality, because some people
> already use it, but I just wanted to point out that current DateTime
> class is forcing people to think about it as mutable.
> My main concerns are DateTime#add() and DateTime#sub(). The problem is
> - they both change current object and return it.
> I think we could add methods to DateTime like add() and sub(), let's
> say plus() and minus(), but they would behave differently in the way
> that they would return new DateTime objects and won't change current
> object.
That will make it even more inconsistent.
You have add() and plus() but one changes the object and the other doesn't.

If we were going to rewrite php or the DateTime class, it could be a
good idea to make those methods  (or its equivalents) not modify the object.
But I don't think it'd be a win to do such thing now.

---

## #64235 — Herman Radtke — 2012-12-10T19:59:19+00:00

URL: https://externals.io/message/64232#64235 · In reply to: #64233

> 
> > […]
> That will make it even more inconsistent.
> You have add() and plus() but one changes the object and the other doesn't.
>
> If we were going to rewrite php or the DateTime class, it could be a
> good idea to make those methods  (or its equivalents) not modify the object.
> But I don't think it'd be a win to do such thing now.
>

Another option is to make an ImmutableDateTime class. The DateTime
class could actually be changed to inherit the ImmutableDateTime
class. The only extensions on the DateTime class would be the mutable
methods.


-- 
Herman Radtke
hermanradtke@gmail.com | http://hermanradtke.com

---

## #64242 — David Muir — 2012-12-10T23:32:04+00:00

URL: https://externals.io/message/64232#64242 · In reply to: #64235

> 
> > […]
> Another option is to make an ImmutableDateTime class. The DateTime
> class could actually be changed to inherit the ImmutableDateTime
> class. The only extensions on the DateTime class would be the mutable
> methods.
>
>

Would love to see ImmutableDateTime!

David

---

## #64246 — Stas Malyshev — 2012-12-11T01:51:13+00:00

URL: https://externals.io/message/64232#64246 · In reply to: #64232

Hi!

> As long as we know, it's not so good - date is immutable by nature. I  
> don't want to write here why it's so, I will just throw this link:  
> http://www.ibm.com/developerworks/java/library/j-jtp02183/index.html

Date is immutable, but there's no reason why date object should be able
to represent only one date. Reference to Java is not exactly applicable
here, as many problems existing in Java (thread safety, long-living
object references, etc.) do not exist in PHP.

> I don't want to change any existing functionality, because some people  
> already use it, but I just wanted to point out that current DateTime class  
> is forcing people to think about it as mutable.

It does not - if you don't need it mutable, don't use modify() or
override modify() with method that would clone the object and return
modified clone. This can easily be done in userspace if you require an
immutable object, which most of the users actually do not.

> Also, there's methods compareTo, createFromTimestamp and createFromDay, it  
> could be another proposal. I think we are very often create DateTime  
> objects just from timestamp or year-month-day. So we could introduce this  
> methods that could not rely on timelib's parsing, and instead just take  
> numbers directly.

Timestamp doesn't need any timelib parsing AFAIK, but YMD certainly does
- you need to calculate the actual timestamp according to current
timezone, etc.

> And I think DateTime lack comparing method. For now I can compare DateTime  
> objects only by getting their timestamps, but I though that the idea of  

DateTime objects can be compared directly, why do you think you can
compare only timestamps?
-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

---

## #64247 — Derick Rethans — 2012-12-11T02:17:06+00:00

URL: https://externals.io/message/64232#64247 · In reply to: #64235

> 
> > […]

Yes, that's horrible - and might not even work with the current design.

> > […]
> 
> Another option is to make an ImmutableDateTime class. The DateTime
> class could actually be changed to inherit the ImmutableDateTime
> class. The only extensions on the DateTime class would be the mutable
> methods.

I'm not really against that, but we do need to use the Date namespace - 
so DateTimeImmutable. It might be trickier to do than it sounds 
though...

cheers,
Derick

-- 
http://derickrethans.nl | http://xdebug.org
Like Xdebug? Consider a donation: http://xdebug.org/donate.php
twitter: @derickr and @xdebug
Posted with an email client that doesn't mangle email: alpine

---

## #64248 — Nikita Nefedov — 2012-12-11T09:01:12+00:00

URL: https://externals.io/message/64232#64248 · In reply to: #64246

Hi!

> Date is immutable, but there's no reason why date object should be able
> to represent only one date. Reference to Java is not exactly applicable
> here, as many problems existing in Java (thread safety, long-living
> object references, etc.) do not exist in PHP.

Say we have a blog post entity, it looks like this:
Post Object
(
     [title] => Qwerty
     [body] => Lorem ipsum
     [craetedAt] => DateTime Object
         (
             [date] => 2010-10-23 00:00:00
             [timezone_type] => 3
             [timezone] => Europe/Moscow
         )
)

Now we have some third-party service that we need to use to send our post  
somewhere, it has a method that accepts title, body and DateTime object  
when the post was created. So we pass our DateTime object to that method  
and it can do with that object whatever it wants. When our script ends, it  
tries to persist all changes to entities and this date will end up in the  
database.
Or we can watch at that problem from ORM's side - when it fetches rows and  
maps them to objects, it should "remember" original state of that data, so  
it can distinguish what objects need to be UPDATE-d in database in the  
end. So there's to ways for ORM to think about dates - as  
strings/timestamps (it could be database's representation of date like  
"2010-10-23" or just integer with timestamp) or it could be objects of  
DateTime. More efficient and logical way would be objects, but that way  
you must aware users that they shouldn't modify values of DateTime  
objects, and instead they should create new instance when they want to  
change value of datetime type. And it's just bad that there could be  
situations when the entity will represent different data, after  
persisting, than database.

> It does not - if you don't need it mutable, don't use modify() or
> override modify() with method that would clone the object and return
> modified clone. This can easily be done in userspace if you require an
> immutable object, which most of the users actually do not.

I was speaking not about modify() but about add() and sub(). Actually I  
don't like these two methods (plus and minus) that I proposed too, but how  
can we solve this problem differently?

What about user-land implementation - there's one problem: I can't just  
extend DateTime object, because it has factory methods like  
createFromFormat, so I need to use decorator pattern and from that point  
hell begins.

> Timestamp doesn't need any timelib parsing AFAIK, but YMD certainly does
> - you need to calculate the actual timestamp according to current
> timezone, etc.

I meant I must either call create new DateTime and pass to constructor  
timestamp string starting with @ (and there would be parsing involved) or  
call createFromFormat and pass "U" as second parameter and timestamp as  
first one.

> DateTime objects can be compared directly, why do you think you can
> compare only timestamps?

My fault, didn't know about that.

---

## #64249 — Marco Pivetta — 2012-12-11T09:08:45+00:00

URL: https://externals.io/message/64232#64249 · In reply to: #64248

As Nikita says, from an ORM perspective, an object is always immutable (at
least with current implementations I know of), and that's because they can
simply use the object hashes to identify two different objects.

While this may be a niche to many of you, I've encountered a quite big
amount of people just modifying their DateTime objects with the existing
API and then complaining about their date not being saved to DB.

I don't believe (at all) in "if you don't need it mutable, don't use
modify() oroverride modify()". If the API is there, people will use it. We
tried to implement an immutable DateTime in userland, but it doesn't work
out well...

Marco Pivetta

http://twitter.com/Ocramius

http://ocramius.github.com/

---

## #64258 — Stas Malyshev — 2012-12-11T17:06:05+00:00

URL: https://externals.io/message/64232#64258 · In reply to: #64249

Hi!

> As Nikita says, from an ORM perspective, an object is always immutable
> (at least with current implementations I know of), and that's because
> they can simply use the object hashes to identify two different objects.

Why for ORM Date is even an object? In most databases, date is a basic
value type, and should be accepted by value, not as a complex object.
So, it should also be identified as the value - for number 1, you do not
need additional identity or hash except it being number 1, same should
be for dates.

> I don't believe (at all) in "if you don't need it mutable, don't use
> modify() oroverride modify()". If the API is there, people will use it.
> We tried to implement an immutable DateTime in userland, but it doesn't
> work out well...

Why it doesn't work well and why PHP needs to be changed because of it?
-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

---

## #64259 — Daniel Ribeiro Gomes — 2012-12-11T17:10:50+00:00

URL: https://externals.io/message/64232#64259 · In reply to: #64258

People tend to desire API changes that go on the same directions they are
going.

That's nature...


Daniel Ribeiro Gomes Pereira
Twitter <https://twitter.com/#!/drgomesp> |
Facebook<https://www.facebook.com/profile.php?id=100000407054469>
 | LinkedIn <http://www.linkedin.com/pub/daniel-ribeiro-gomes/21/414/39>
iPhone: +55 (48) 9111-0931



2012/12/11 Stas Malyshev <smalyshev@sugarcrm.com>

> Hi!
>
> > […]
>
> Why for ORM Date is even an object? In most databases, date is a basic
> value type, and should be accepted by value, not as a complex object.
> So, it should also be identified as the value - for number 1, you do not
> need additional identity or hash except it being number 1, same should
> be for dates.
>
> > […]
>
> Why it doesn't work well and why PHP needs to be changed because of it?
> --
> Stanislav Malyshev, Software Architect
> SugarCRM: http://www.sugarcrm.com/
> (408)454-6900 ext. 227

---

## #64260 — Marco Pivetta — 2012-12-11T17:11:28+00:00

URL: https://externals.io/message/64232#64260 · In reply to: #64258

@Stas a DateTime object is the perfect representation of what in DB world
has dozens of different representations. The reasoning behind it is exactly
the same as having a DateTime object vs having a date+time string.

Marco Pivetta

http://twitter.com/Ocramius

http://ocramius.github.com/

---

## #64261 — Stas Malyshev — 2012-12-11T17:13:19+00:00

URL: https://externals.io/message/64232#64261 · In reply to: #64248

Hi!

> strings/timestamps (it could be database's representation of date like  
> "2010-10-23" or just integer with timestamp) or it could be objects of  
> DateTime. More efficient and logical way would be objects, but that way  
> you must aware users that they shouldn't modify values of DateTime  
> objects, and instead they should create new instance when they want to  
> change value of datetime type. And it's just bad that there could be  
> situations when the entity will represent different data, after  
> persisting, than database.

You need not be aware of anything unless your database identifies dates
by object identities, which is usually wrong since DateTime is a value
type in most systems, and should be identified by value, as I already
noted. If your data are mutable (which I assume they are, since
otherwise the question of saving would not arise), you have to treat
changes in title, body, etc. fields - treat the changes in createdAt
field the same way.

> What about user-land implementation - there's one problem: I can't just  
> extend DateTime object, because it has factory methods like  
> createFromFormat, so I need to use decorator pattern and from that point  
> hell begins.

It is true that createFromFormat and other factory methods could use an
extension that allows to instantiate child classes, however working
around it is pretty trivial, not sure what "hell" begins there.

> I meant I must either call create new DateTime and pass to constructor  
> timestamp string starting with @ (and there would be parsing involved) or  
> call createFromFormat and pass "U" as second parameter and timestamp as  
> first one.

Yes, but what's wrong with that? It works just fine.
-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

---

## #64262 — Stas Malyshev — 2012-12-11T17:15:15+00:00

URL: https://externals.io/message/64232#64262 · In reply to: #64260

Hi!

> @Stas a DateTime object is the perfect representation of what in DB
> world has dozens of different representations. The reasoning behind it
> is exactly the same as having a DateTime object vs having a date+time
> string.

You are confusing internal PHP representation with object identity vs.
value treatment. There's no reason for dates to be treated as non-value
types having complex structure, and if you do not, mutability is not a
question.
-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

---

## #64263 — inefedor@gmail.com — 2012-12-11T17:20:15+00:00

URL: https://externals.io/message/64232#64263 · In reply to: #64258

Stas Malyshev <smalyshev@sugarcrm.com> писал(а) в своём письме Tue, 11 Dec  
2012 21:06:05 +0400:

> Hi!
>
> > […]
>
> Why for ORM Date is even an object? In most databases, date is a basic
> value type, and should be accepted by value, not as a complex object.
> So, it should also be identified as the value - for number 1, you do not
> need additional identity or hash except it being number 1, same should
> be for dates.

Then why do we even need DateTime class? We could stay with functions. I  
think if we want to bring some OOP in php, then we need to do it right way.

> > […]
>
> Why it doesn't work well and why PHP needs to be changed because of it?

Because of some DateTime's limitations - you will end up making brand new  
DateTime class, reimplementing *all* the features that were implemented in  
DateTime. At first - you can't just extend DateTime, because of  
factory-methods - so that way you will need to use decorator, but even  
with this approach (pretty shitty approach I must say) there would be  
problems with diff() method (if you want to use DateTime's diff, you will  
need to implement getDateTime method of your own DateTime class (because  
diff accepts DateTime), so you will end with mutable object again, because  
one can just execute $yourDate->getDateTime()->modify(*whatever you  
want*)).

I think it should be changed (or implemented another one, like someone  
said, DateTimeImmutable) because date is atomic value.

---

## #64296 — Derick Rethans — 2012-12-16T12:21:47+00:00

URL: https://externals.io/message/64232#64296 · In reply to: #64247

> 
> 
> > […]
> 
> I'm not really against that, but we do need to use the Date namespace - 
> so DateTimeImmutable. It might be trickier to do than it sounds 
> though...

I've started hacking on this - with some luck I'm done before PHP 5.5 
beta1.

cheers,
Derick

---

## #64297 — Lars Strojny — 2012-12-16T12:24:48+00:00

URL: https://externals.io/message/64232#64297 · In reply to: #64296

This is so cool, thanks Derick! If you need help with testing or anything else, let me know.

Am 16.12.2012 um 13:21 schrieb Derick Rethans <derick@php.net>:

> 
> 
> > […]
> 
> I've started hacking on this - with some luck I'm done before PHP 5.5 
> beta1.
> 
> cheers,
> Derick

---

## #64298 — Lester Caine — 2012-12-16T13:46:48+00:00

URL: https://externals.io/message/64232#64298 · In reply to: #64297

> > […]

Am I missing something here?
Isn't this just making the object content read only?
Haven't we been having a separate discussion on that?

On the whole I'm only using DateTime objects when I need to display the content 
in a different timezone, so the timezone needs to be changeable, but the base 
date is read only. Alternatively I'm building a calendar so need 'all the days 
for month x' as an array, and then use those dates to generate the database 
query. If it's a 'local' calendar then there will be a time offset incorporated 
as well.

In Firebird, the dates are stored as a numeric value, with the whole part the 
number of days, and the fraction the time of day. Two 32bit values. When doing 
comparisons there is no point converting to a DateTime object, one converts FROM 
the DateTime to parameter suitable for the database, and leave the database to 
do the filtering.

-- 
Lester Caine - G8HFL
-----------------------------
Contact - http://lsces.co.uk/wiki/?page=contact
L.S.Caine Electronic Services - http://lsces.co.uk
EnquirySolve - http://enquirysolve.com/
Model Engineers Digital Workshop - http://medw.co.uk
Rainbow Digital Media - http://rainbowdigitalmedia.co.uk

---

## #64303 — inefedor@gmail.com — 2012-12-16T19:26:06+00:00

URL: https://externals.io/message/64232#64303 · In reply to: #64296

I have actually started too, but I made it w/o inheritance from DateTime,  
and I made many of inline functions to avoid code repetition, so I don't  
know how good is it. The code on my work computer, so I can show it  
tomorrow.

Derick Rethans <derick@php.net> писал(а) в своём письме Sun, 16 Dec 2012  
16:21:47 +0400:

> 
>
> > […]
>
> I've started hacking on this - with some luck I'm done before PHP 5.5
> beta1.
>
> cheers,
> Derick

---

## #64310 — Derick Rethans — 2012-12-16T21:17:55+00:00

URL: https://externals.io/message/64232#64310 · In reply to: #64298

> > […]
> 
> Am I missing something here?
> Isn't this just making the object content read only?

Sortof. But as that is how things work, making an immutable variant 
isn't that easy.

> Haven't we been having a separate discussion on that?
> 
> On the whole I'm only using DateTime objects when I need to display the
> content in a different timezone, so the timezone needs to be changeable, but
> the base date is read only. Alternatively I'm building a calendar so need 'all
> the days for month x' as an array, and then use those dates to generate the
> database query. If it's a 'local' calendar then there will be a time offset
> incorporated as well.

Al the methods will *still* return the modified DateTime object - it's 
just that the one that you *call* f.e. ->modify() on won't change 
anymore.

cheers,
Derick

---

## #64311 — Stas Malyshev — 2012-12-16T21:37:02+00:00

URL: https://externals.io/message/64232#64311 · In reply to: #64310

Hi!

> Al the methods will *still* return the modified DateTime object - it's 
> just that the one that you *call* f.e. ->modify() on won't change 
> anymore.

Doesn't it mean you can just call `clone()` on it in modifier methods
before doing anything else?
-- 
Stanislav Malyshev, Software Architect
SugarCRM: http://www.sugarcrm.com/
(408)454-6900 ext. 227

---

## #64312 — Derick Rethans — 2012-12-16T21:39:57+00:00

URL: https://externals.io/message/64232#64312 · In reply to: #64311

> > […]
> 
> Doesn't it mean you can just call `clone()` on it in modifier methods 
> before doing anything else?

Yeah, I think so. I tried that but I got some errors. It's something for 
me to sort out. So far, I've just created all the helper methods etc. 
 `clone()` however is not a method, but a language construct... so it's not 
that trivial.

cheers,
Derick

---

## #64322 — Derick Rethans — 2012-12-17T16:48:37+00:00

URL: https://externals.io/message/64232#64322 · In reply to: #64297

> Am 16.12.2012 um 13:21 schrieb Derick Rethans <derick@php.net>:
> 
> > […]

> This is so cool, thanks Derick! If you need help with testing or 
> anything else, let me know.

I've just pushed it to the "immutable-date" branch:
http://git.php.net/?p=php-src.git;a=shortlog;h=refs/heads/immutable-date

I went for DateTimePoint. Point as in "Point in time". I am not too 
happy with the name, but I think it works better than DateTimeImmutable 
as that just sounds quircky. I'm still fixing up a few things and adding 
some test cases. I think I need to make it work with DatePeriod too - 
but I haven't looked at that yet.

cheers,
Derick

---

## #64323 — Benjamin Eberlei — 2012-12-17T18:42:52+00:00

URL: https://externals.io/message/64232#64323 · In reply to: #64322

>
> I went for DateTimePoint. Point as in "Point in time". I am not too
> happy with the name, but I think it works better than DateTimeImmutable
> as that just sounds quircky. I'm still fixing up a few things and adding
> some test cases. I think I need to make it work with DatePeriod too -
> but I haven't looked at that yet.


some suggestions:

DateTimeValue
DateTimeImmutable
DateImmutable
DateFixed
DateStatic
(and as a bonus: DateTime2)

---

## #64324 — Lars Strojny — 2012-12-17T20:52:51+00:00

URL: https://externals.io/message/64232#64324 · In reply to: #64323

Hi Derick,

I would go with DateTimeValue or DateTimeImmutable as well.

Am 17.12.2012 um 19:42 schrieb Benjamin Eberlei <kontakt@beberlei.de>:

> 
> I went for DateTimePoint. Point as in "Point in time". I am not too
> happy with the name, but I think it works better than DateTimeImmutable
> as that just sounds quircky. I'm still fixing up a few things and adding
> some test cases. I think I need to make it work with DatePeriod too -
> but I haven't looked at that yet.
>  
> some suggestions:
> 
> DateTimeValue
> DateTimeImmutable
> DateImmutable
> DateFixed
> DateStatic
> (and as a bonus: DateTime2)

---

## #64329 — Adam Harvey — 2012-12-18T00:10:44+00:00

URL: https://externals.io/message/64232#64329 · In reply to: #64324

> I would go with DateTimeValue or DateTimeImmutable as well.

+1. I'd prefer DateTimeImmutable personally because it describes what
it is better than the other options.

Adam "bikeshed" Harvey

---

Next page: https://externals.io/message/64232.md?page=2
