NotionCommotion Posted December 2, 2020 Share Posted December 2, 2020 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'); } Quote Link to comment https://forums.phpfreaks.com/topic/311793-when-should-datetime-be-injected-with-datetimezone/ Share on other sites More sharing options...
requinix Posted December 2, 2020 Share Posted December 2, 2020 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(...) Quote Link to comment https://forums.phpfreaks.com/topic/311793-when-should-datetime-be-injected-with-datetimezone/#findComment-1582765 Share on other sites More sharing options...
NotionCommotion Posted December 5, 2020 Author Share Posted December 5, 2020 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 Quote Link to comment https://forums.phpfreaks.com/topic/311793-when-should-datetime-be-injected-with-datetimezone/#findComment-1582839 Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.