[php-src] Issue #7965: [ The reason inside ] DateTime\DateTimeImmutable\DateTimeInterface.... how much more?
| From: | 6562680 | Date: | Tue, 18 Jan 2022 18:16:52 +0000 |
| Subject: | [php-src] Issue #7965: [ The reason inside ] DateTime\DateTimeImmutable\DateTimeInterface.... how much more? | ||
| Groups: | php.bugs | ||
| Request: | Send a blank email to php-bugs+get-239107@lists.php.net to get a copy of this message | ||
Issue: https://github.com/php/php-src/issues/7965
Author: 6562680
### Description
```
/**
* @author gzhegow > 12 years of PHP experience
*/
```
> There are guys who wants Psr/Clock/ClockInterface with just one method ->now()...
1. \DateTime, \DateTimezone, \DateInterval marked with \Exception. Most used editor PHPStorm
highlights it. Since it is very internal method - using native \DateTime forces highlight all the
code. Highlighting means "PLEASE TRY CATCH IT". So since 50% percent of tasks needs dates
inside their logic - you have try/catch in 50% code just to hide damn exception and throw \Runtime
instead. Its still an exception. But hidden one. So we have guys who wants ClockInterface
2. Next one - Relative Date vs Absolute date. In PHP we have the date as single feature (but with 3?
or more implementations) - functional way, object way, etc. The point is TIMEZONE. I dont know how
exactly initial timezone comes inside PHP (while no one in config) - but i saw 10+ servers where
unix commands show that the timezone is UTC, but PHP shows timezone as "Helsinki" or
something. Yes it could be fixed with
php.ini.
But with next things:
(1) You still have timezone in your database that could be different from your Unix. And with your
php. And you WILL dance with that +1 -2 +3 -4 every time. Best configuration - same timezone
everywhere. To do that you should be at least amateur in linux/docker/(mysql|postgres)/php+fpm.
Usually this amateur is a guy known as dev-ops, he is clever guy, he wants 3000 USD/month to work
only 10minutes per month in case your app falls down. Most product companies prefers outsourcing,
and now you CANT ask this guy about this timezone without democratic negotiations.
(2) You know about timezone difference in maybe 2-3 months after project published. It always has a
database for maybe 100k-1m records minimum with failed dates. And now you get the task "i dont
know, but we differs in 2 hours"
The reason of above is IMPORTANT difference between relative and absolute date.
Relative date comes from your CPU clock. You write "today" or "yesterday" and
you'll get for me (now):
2022-01-18 20:00:00 UTC+2
Ok, lets remember your server (and your postgres configured with UTC). You apply new
\DateTimeZone('UTC') one of this way:
1. new \DateTime($date, $timezoneUTC)
2. (new \DateTime($date))->setTimezone($timezoneUTC)
3. (new \DateTime($date, $timezone))->setTimezone($timezoneUTC)
4. default_timezone_set($timezoneUTC); new \DateTime($date);
5. ....want some more??
You ALWAYS get unexpected difference in (for me) 2 hours. So the time will be:
2022-01-18 18:00:00 UTC+0
But wait, now you should do that in your brain on every math operation, and try to remember it.
How to get same date as you see in your mac/windows/ubuntu tray, huh, developer?
Tada:
```
new \DateTime((new \DateTime())->format('Y-m-d H:i:s.u'), $timezoneUTC);
```
How many hours newbie should spent to research that ?? The point is difference between RELATIVE and
ABSOLUTE dates. If you pass timezone as 2nd parameter with relative date - it will be applied like
"create date, then - change timezone", instead of "create date in described
timezone", do you get that?
BUT, we want to apologize, but "today midnight" isnt a RELATIVE date. Actually not fully
relative. It creates the date with 00:00:00 timestamp. And it will surprise you only if date been
created inside UTC difference (for me) 2 hours from UTC. There will be previous day, but server
awaits next one.
**How about create DIFFERENT classes for Relative date and Absolute date?**
Or fix the behavior - "today, UTC" means "GET MY TIME IN UTC, I KNOW ITS A MISTAKE,
BUT IT WILL HELP ME" :DD
And the next point.
When we serialize date into some storage, we need DATE_ATOM or maybe sql date format.
But while we're in the code - we need objects.
So creating date with new \DateTime() (and actually twice, and actually with timezone,
and actually with trycatch in each class) - it wont respects use case "we already have the date
object" so we need everywhere write that damn instanceof stuff:
````
$date = $date instanceof \DateTimeInterface // @gzhegow > whoops, interface doesnt have
setTimezone, we need to write
```
/**
* @param null|string|\DateTimeInterface $date
* @param null|string|\DateTimeZone $timezone
*
* @return null|string|\DateTimeInterface
*/
private function newDate($date = null, $timezone = null) : \DateTimeInterface
{
$date = $date ?? 'now';
$timezone = $timezone ?? 'UTC';
$timezone = $timezone instanceof \DateTimeZone
? $timezone
: new \DateTimeZone($timezone);
try {
$date = null
?? ( $date instanceof \DateTime ? $date->setTimezone($timezone) : null )
?? ( $date instanceof \DateTimeImmutable ? $date->setTimezone($timezone) : null )
?? ( new \DateTime(
( new \DateTime($date) )->format('Y-m-d H:i:s.u'), $timezone
) );
}
catch ( \Exception $e ) {
throw new \RuntimeException($e->getMessage(), null, $e);
}
return $date;
}
```
To create date in PHP safely you need to always write that construct. In each class you need dates.
And am not speaking about humanize date stuff, localize
today/yesterday/tomorrow', localize ago dates` (ohh, you will MEET the
\IntlFormatterLibrary, and spent 3-4 hrs to remember it for the time, am sure)
Lets fix at least relative date stuff. Just to reduce syntax.
Other stuff we could speak later.
Thanks for your time, folks. Be safe.