Jump to content

When should DateTime be injected with DateTimeZone?


NotionCommotion

Recommended Posts

It is my belief that when storing time in the DB, it should always be at UTC.  Agree?  My question is whether one should work with DateTimes with a specific time zone or only do so when displaying the time to the user?

For example, if I have multiple users which have a timezone string property based on their physical location as well as a datatime property when some event occurred for the given user, and need to implement some logic if the event occurred more than a given duration from the current time, which of the following approaches should be used?

$currentTime = new DateTimeImmutable();
$userEventTime = new DateTime($queryResults['theEventField']);
if($currentTime->sub(new DateInterval('P10D')) < $userEventTime) {
    //Display time to the user
    $displayEventTime = new DateTime('@'.$userEventTime->getTimestamp(), new DateTimeZone($queryResults['userTimeZone']))->format('Y-m-d H:i:sP');
}

 

$currentTime = new DateTimeImmutable('now', new DateTimeZone($queryResults['userTimeZone']));
$userEventTime = new DateTime($queryResults['theEventField'], new DateTimeZone($queryResults['userTimeZone']));
if($currentTime->sub(new DateInterval('P10D')) < $userEventTime) {
    //Display time to the user
    $displayEventTime = $userEventTime->format('Y-m-d H:i:sP');
}


 

 

Link to comment
Share on other sites

1 hour ago, NotionCommotion said:

It is my belief that when storing time in the DB, it should always be at UTC.  Agree?

Agreed.

 

1 hour ago, NotionCommotion said:

My question is whether one should work with DateTimes with a specific time zone or only do so when displaying the time to the user?

I would rather work with them in UTC and alter how they're displayed to the user by literally altering how they're displayed to the user.

So the first one.

Play it safe:
1. Make sure your database abstraction can handle DateTime objects and will translate them to UTC before serializing for storage, then use DateTime instances everywhere
2. Give yourself one or more functions that can display dates to the user that will adjust the timezone as needed. This is a great way to ensure you display dates uniformly across the site, too.

Note that if you're working with Immutables, you can do

$userEventTime->setTimezone(new DateTimeZone(...))->format(...)

But only if they're immutable. So it might be better to clone instead:

(clone $userEventTime)->setTimezone(new DateTimeZone(...))->format(...)

 

Link to comment
Share on other sites

Thanks requinix,

Haven't spent much time with time zones before now.  When using "now", everything made sense, but was first confused with my results when injecting DateTime with a timestamp.  In addition to what you already said, I found another important thing to always do:  inject the users time zone into DateTime if they provide a time.

While DateTime is smart enough for the math to work without changing the timezone to UTC, I will always convert to UTC right after creating the DateTime and not when saving the data as using "now" doesn't require such.

All good and thanks again.

<?php
ini_set("display_errors", 1);

function test($time, $timezone) {
    $date = new DateTimeImmutable($time);
    echo "(new DateTimeImmutable('$time'))->format('Y-m-d H:i:s e'):<br>".$date->format('Y-m-d H:i:s e').'<br>';
    echo "(new DateTimeImmutable('$time'))->setTimezone(new DateTimeZone('$timezone'))->format('Y-m-d H:i:s e'):<br>".$date->setTimezone(new DateTimeZone($timezone))->format('Y-m-d H:i:s e').'<br>';
    $date = new DateTimeImmutable($time, new DateTimeZone($timezone));
    echo "(new DateTimeImmutable('$time', new DateTimeZone('$timezone')))->format('Y-m-d H:i:s e'):<br>".$date->format('Y-m-d H:i:s e').'<br>';
    echo "(new DateTimeImmutable('$time', new DateTimeZone('$timezone')))->setTimezone(new DateTimeZone('utc'))->format('Y-m-d H:i:s e'):<br>".$date->setTimezone(new DateTimeZone('utc'))->format('Y-m-d H:i:s e').'<br><hr>';
}
test("now", "America/Los_Angeles");
test("2020-11-03 00:00:00", "America/Los_Angeles");
test("now", "America/New_York");
test("2020-11-03 00:00:00", "America/New_York");

 

Quote

(new DateTimeImmutable('now'))->format('Y-m-d H:i:s e'):
2020-12-05 16:00:30 UTC
(new DateTimeImmutable('now'))->setTimezone(new DateTimeZone('America/Los_Angeles'))->format('Y-m-d H:i:s e'):
2020-12-05 08:00:30 America/Los_Angeles
(new DateTimeImmutable('now', new DateTimeZone('America/Los_Angeles')))->format('Y-m-d H:i:s e'):
2020-12-05 08:00:30 America/Los_Angeles
(new DateTimeImmutable('now', new DateTimeZone('America/Los_Angeles')))->setTimezone(new DateTimeZone('utc'))->format('Y-m-d H:i:s e'):
2020-12-05 16:00:30 UTC
(new DateTimeImmutable('2020-11-03 00:00:00'))->format('Y-m-d H:i:s e'):
2020-11-03 00:00:00 UTC
(new DateTimeImmutable('2020-11-03 00:00:00'))->setTimezone(new DateTimeZone('America/Los_Angeles'))->format('Y-m-d H:i:s e'):
2020-11-02 16:00:00 America/Los_Angeles
(new DateTimeImmutable('2020-11-03 00:00:00', new DateTimeZone('America/Los_Angeles')))->format('Y-m-d H:i:s e'):
2020-11-03 00:00:00 America/Los_Angeles
(new DateTimeImmutable('2020-11-03 00:00:00', new DateTimeZone('America/Los_Angeles')))->setTimezone(new DateTimeZone('utc'))->format('Y-m-d H:i:s e'):
2020-11-03 08:00:00 UTC
(new DateTimeImmutable('now'))->format('Y-m-d H:i:s e'):
2020-12-05 16:00:30 UTC
(new DateTimeImmutable('now'))->setTimezone(new DateTimeZone('America/New_York'))->format('Y-m-d H:i:s e'):
2020-12-05 11:00:30 America/New_York
(new DateTimeImmutable('now', new DateTimeZone('America/New_York')))->format('Y-m-d H:i:s e'):
2020-12-05 11:00:30 America/New_York
(new DateTimeImmutable('now', new DateTimeZone('America/New_York')))->setTimezone(new DateTimeZone('utc'))->format('Y-m-d H:i:s e'):
2020-12-05 16:00:30 UTC
(new DateTimeImmutable('2020-11-03 00:00:00'))->format('Y-m-d H:i:s e'):
2020-11-03 00:00:00 UTC
(new DateTimeImmutable('2020-11-03 00:00:00'))->setTimezone(new DateTimeZone('America/New_York'))->format('Y-m-d H:i:s e'):
2020-11-02 19:00:00 America/New_York
(new DateTimeImmutable('2020-11-03 00:00:00', new DateTimeZone('America/New_York')))->format('Y-m-d H:i:s e'):
2020-11-03 00:00:00 America/New_York
(new DateTimeImmutable('2020-11-03 00:00:00', new DateTimeZone('America/New_York')))->setTimezone(new DateTimeZone('utc'))->format('Y-m-d H:i:s e'):
2020-11-03 05:00:00 UTC

 

Link to comment
Share on other sites

This thread is more than a year old. Please don't revive it unless you have something important to add.

Join the conversation

You can post now and register later. If you have an account, sign in now to post with your account.

Guest
Reply to this topic...

×   Pasted as rich text.   Restore formatting

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

×
×
  • Create New...

Important Information

We have placed cookies on your device to help make this website better. You can adjust your cookie settings, otherwise we'll assume you're okay to continue.