PHP/MySQL Timezone when working only with Date not Time - php

My question is more on the concept side.
I'm wondering how to deal with dates only based information. For example, when you have a day to take a vacation or something like that on February 24th and you store on the database as 2015-02-24 00:00:00 right.... how do I deal with conversions in this case?
I already now how to convert timezones, it works with no problem in cases where the user selects a time too. But when I use 00:00:00 in cases only the date matters I'm having problems to figure it out.
For example:
Let's say I setup my vacation to be on the 24th of February and I'm on EST right, and the system is saving all times on EST. It will convert and it will be saved as 2015-02-24 00:00:00
Then somebody on PST time will check it out, and when it convert to them it will be 2015-02-23 21:00:00 ... and it will show my vacation in their point of you it will be on the 23rd.
Is that a correct logic? How should I save on the database the time in that case? Keep it as 00:00:00?
I hope I was able to explain myself.
Thanks

You can save the date in unix timestamp in the database (always save the current time in GMT even if you are in EST).
And when displaying the date, convert it to the user's timezone.

Related

How to calculate average time of day taking into account timezone differences?

I'm using Laravel/PHP/MySQL and storing all dates and times in UTC.
The user can select a timezone (for example Eastern), enter a date and time, and the date and time will be converted to UTC before storing. On retrieval it will be converted to user's selected timezone.
My question is how can you get the average time of day from a series of records taking into account the timezone (preferably in the database query)? The following question addresses average time of day in PHP, but not the timezone issue.
How to calculate average time
Here is what I'm doing:
SEC_TO_TIME( AVG( TIME_TO_SEC( TIME(flights.departed_at) ) ) ) ) AS average_time
This works except for records that span daylight saving/standard time in a region that observes it.
FOR EXAMPLE: You may have a record with the UTC datetime of 2015-08-18 11:00:00 that was entered by a user in EDT at 2015-08-18 07:00:00. Then you have a second record entered with the UTC datetime of 2015-11-10 12:00:00 by a user in EST at 2015-11-10 07:00:00. If you try to calculate the average time of day it should equate to 07:00:00 but instead the result is 07:30:00.
Any ideas how to overcome this? Am I approaching this all wrong?
Thanks in advance.
In short, your code is working correctly. Once the date is in UTC, you'd have to re-calculate whether or not it was entered (1) during daylight savings time, (2) by someone actually observing daylight savings time, and (3) in a place that recognizes daylight savings time.
I can really only think of one way to approach this.
Add some kind of flag when the data is saved to mark the timestamp as DST. You can use this flag to adjust for the hour difference. How you generate this flag is up to you.
If you have all your times stored in Z, and if your MySQL database has the timezones loaded correctly, you can use the zoneinfo timezone name to retrieve your local times. For example,
SELECT CONVERT_TZ('2015-08-01 11:00', 'UTC', 'America/New_York'),
CONVERT_TZ('2015-12-01 12:00', 'UTC', 'America/New_York')
yields
2015-08-01 07:00 2015-12-01 07:00
The point is, the zoneinfo database knows to use daylight saving time or standard time for each datetime value. It doesn't use the current offset, it uses the offset in effect on the date in question.
So, you can retrieve the time of day, in local time, with an expression like this:
TIME(CONVERT_TZ(utc_time_column, 'UTC', 'America/New_York'))
Then, you average those times-of-day in the usual way.

What is the best way to store Due Dates?

I have an application that needs to store due dates. So if Bob in the UK creates a task and says it's due on Feb 20, I want it to show as Feb 20 on the Calendar regardless of timezones of other users.
Storing it as UTC as DATETIME in MySQL presents the problem that if Bob created the task at 1am Feb 20, then Jane in California would see the task as due Feb 19.
So my other thought is to store it as DATE but I couldn't find any literature on how DATE is affected by the TimeZone.
So my question is, if my app is PHP and my storage is MYSQL and I want to implement Calendars that only store dates and not date/time and I want events to show as a certain date globally, how should I go about it?
Aside from my particular needs, I'm also curious on how other people implement date specific events (do you just let the date be different on different users calendars?) - For example how does Google Calendar/Outlook handle "all day events"?
You can just store the date as a DATE field. Since you want all users to see the same date there's no need to worry about timezones or the like. I.e. storing 2014-10-11 in the column and then showing that value to users.
The safest way to do this is to store both the unix timestamp and the timezone of the job creator. Then, when displaying the date for other users, use that timezone for displaying the time:
$timestamp=1413027859;
$timezone='Australia/Sydney';
$dt=new DateTime();
$dt->setTimestamp($timestamp);
$dt->setTimezone(new DateTimeZone($timezone));
$day=$dt->format('Y-m-d');

DATE_ICAL and strtotime in PHP

I have dates in my database in local British times (i.e. GMT in the winter and BST in the summer). I want to convert them to DATE_ICAL for displaying into iCalendar format. I have tried both the following.
date(DATE_ICAL, strtotime($row['FixtureDate']);
date(DATE_ICAL, strtotime($row['FixtureDate'].' UTC');
My first date for example is 12:45 BST. If I use the first statement I get 20140809T124500Z and the second I get 20140809T134500Z. Neither shows the right date in Google.
The second is obviously wrong because my time is not a UTC time, I think I need to convert my time to a UTC time as that's what DATE_ICAL wants? But how do I do that?
My server is British. I only care about British times and British users.
Finally figured it out, I needed to use GMDATE not DATE with ICAL format
define('DATE_ICAL', 'Ymd\THis\Z');
GMDATE(DATE_ICAL, strtotime($row['FixtureDate']));

How to deal with timezones between server and client?

I'm developing a website where I have to deal with different possible timezones from the users. This becomes a great problem since the website hosts time-delicate events like auctions.
All dates/times on the server are in UTC. Database stores everything in UTC timestamps. PHP default timezone is set to UTC too (date_default_timezone_set('UTC');).
Now, my problem is how I should interact with the users, whether I'm only showing a date or, more important, I'm reading a date/time from user input.
A concrete example:
An auction has a deadline, which I store in database as UTC.
When I view the auction on the website, a javascript timer uses a Date object to calculate the remaining time. It automatically converts the timezone to GMT+0100 (my local timezone). So if the deadline is '2013-08-08 10:46:08' (UTC), the javascript date object will return Aug 08 2013 11:26:15 GMT+0100 (GMT Standard Time).
If the current time is greater than 11:46:08 then the timer says that the remaining time is 00:00 (which is correct).
But if I try to insert a bid, the server accepts since the condition on the MySQL INSERT evaluates to true:
INSERT INTO Bids ... WHERE ... AND auction_deadline > NOW() ...
( because auction_deadline = '2013-08-08 10:46:08' and NOW() = '2013-08-08 10:26:50')
All this mumbo jumbo of timezone melts my brains. What am I missing here? I'm almost certain that storing all dates/times in UTC inside the database is the best. I just can't think crystal clear how do deal with it between the user and the database.
Your problem doesn't involve timezones at all, just the fact that clients can turn their clocks or have their clock skewed considerably. For that the fix is to poll the server every once in a while for an offset fix to use in calculations.
In fact, you don't even need date objects. There is a certain universal instant in time when the auction ends. Let's say it is 1375960662823. Right now, the universal instant in time is 1375960669199, so from that we see that the auction ends in 6 seconds (1375960662823 - 1375960669199 ~ 6000 ). It will end in 6 seconds regardless if I am in Morocco or Japan. Do you understand it yet?
To generate these numbers, on the client side you can call var now = Date.now() + skewFix where skewFix is the correction that needs to applied in case client has time skew or manually set their computer to wrong time.
In PHP, you can generate it with $now = time() * 1000;
This is rather a typical subject yet very complex for most to understand. First thing, you never mention the DAYLIGHT SAVING. yeah I am increasing your tension :).
Now let us see how we can do this. You did a good job by saving the Time in UTC. Now, I hope you have registered members and that each member has ability to set their preferred timezone, otherwise you will show Server' timezone based time to them.
When you through "start time" to user you must send them after converting UTC time to their time, similarly when you accept TIME from browser be it user action or javascript you need to convert that time to UTC considering the fact that user is that time zone that he select for his profile.
Hope that clear the idea on where you are going wrong? Please read through day light saving as that will play an important role too when you move ahead with other logic on same.
EDIT:
You can use javascript's Timezone offset, for auto submission and user input based on his settings.
Date in JavaScript uses local timezone. You should get UTC time for the user and send it to the server
new Date
Thu Aug 08 2013 17:00:14 GMT+0530 (India Standard Time)
(new Date("Thu Aug 08 2013 17:00:14")).toUTCString();
"Thu, 08 Aug 2013 11:30:14 GMT"
This will resolve the timezone issue between the server and client.
You said
( because auction_deadline = '2013-08-08 10:46:08' and NOW() = '2013-08-08 10:26:50')
In MySQL - NOW returns the current time in the server's local time zone (docs).
You probably want something like UTC_TIMESTAMP which returns the current time in UTC (docs).
Also - you probably shouldn't accept any input time from the client JavaScript at all. Only trust your own clock. When a bid is placed, use the time on your server in MySQL or in PHP. Don't accept it as input.
You can do the following
once page is loaded, send an ajax request to server with timezone offset of user. You can get timezone offset using the following code.
var curdate = new Date()
var offset = curdate.getTimezoneOffset()
offset is timezone offset in minute.
I think it will help.
everytime when you get the date from the clientside, you can use the getUTC to convert to UTC date ie:
var todayDate = new Date();
var todayDateInUTC = new Date(todayDate.getUTCFullYear(), todayDate.getUTCMonth(), todayDate.getUTCDate(), todayDate.getUTCHours(), todayDate.getUTCMinutes(), todayDate.getUTCSeconds());
so right before you insert the bid date to database, use the getUTC functions to convert it into UTC format.

Twitter timezone & created_at (utc time) values to calculate what time zone the user is in

I'm trying to estimate a twitter user's location based on the time_zone or created_at value in a given tweet object. However it seems that all created_at values I've come across are just in a pointless localised time and the time zone they supply isn't in the most helpful format
example tweet
"created_at":"Thu Jun 02 14:41:24 +0000 2011"
"time_zone":null
OR
"created_at":"Sun Jan 09 05:03:52 +0000 2011"
"time_zone":"Mountain Time (US & Canada)"
Both of these times aren't in UTC time and the time_zone isn't in any particular standard format with the rest of the world
I'm probably coming across really annoying, I'm tired and hot and been looking for this solution for too long :|
thanks,
Andy
This answer details how to convert a Twitter date into something PHP can work with; synopsis below.
strtotime("dateString"); gets it into
the native PHP date format, then you
can work with the date() function to
get it printed out how you'd like it.
As for the time zone, you can use the value of the utc_offset property of the user object to calculate it. For example, my profile's utc_offset is:
"utc_offset":-21600
Just divide that value by 3600 and that will give you -6, which is the US Central time zone. These will be absolute offsets and will not change whether the time zone honors daylight savings time.

Categories