Reputation: 186572
I have a website where I setup appointments for a spa that resides in the western USA, eg PST time.
When the user selects a spot for say, 10:00 AM @ Mar 20, 2010 the date object that gets created from the client-side on my desktop which uses EDT time is:
timestamp: 1395324000000
utc string: Thu Mar 20 2014 10:00:00 GMT-0400 (EDT)
I need to store this on the server-side. Currently, I'm passing the timestamp from JS to PHP via XHR and dividing by 1000:
ajax url: ajax.php?timestamp=1395324000000
php code:
$time = $_GET['timestamp'] / 1000;
Because my default timezone is manually set to be America/New_York
, and my client-side time is in EDT, they are consistent and so the rightful time is displayed:
echo date('M d Y H:i:s', $time); // Mar 20 2014 10:00:00
But ideally I was thinking I should really be setting the server-side date time to be America/Los_Angeles.. however this would make the echo date
display the wrong date, since it'd be PST
and not EDT
anymore:
date_default_timezone_set('America/Los_Angeles');
Mar 20 2014 07:00:00
It has now become 7:00 AM when the user originally chose 10:00 AM, and that obviously leads to confusion... I need it to be 10:00 AM if the user picked 10:00 AM.
Another worry of mine is that, what if the user's client-side time is not of EDT? Would it not be consistent with America/New_York
or America/Los_Angeles
?
Should I be doing something like saving the UTC string through .toUTCString
in Javascript and then storing the time in UTC, and set the default timezone to be UTC and then convert it to PST time when I need to display PST time?
By the way, I can't use DateTimeZone
or DateTime
since I'm dealing with php < 5.3
Upvotes: 3
Views: 1551
Reputation: 18775
Bear in mind that this advice has been tested only with a Microsoft web service and generated proxy and may not apply to other arrangements.
I found that datetime values are interpreted by JS in the browser timezone.
In the following sample, boundsResult is the dataset received by the web method invocation's success handler. START and END are date time values that left the server as UTC.
var offset_milliseconds = boundsResult[0].START.getTimezoneOffset() * 60000;
var startTime = new Date(boundsResult[0].START.getTime() - offset_milliseconds);
var endTime = new Date(boundsResult[0].END.getTime() - offset_milliseconds);
This fix depends on values always leaving the server as UTC. This is not an unreasonable expectation; a universal timeframe is the only straightforward way to cope with multiple client timezones. Storing localised values is asking for trouble.
For whatever reason, conversion the other way seems to be automatic.
You can wrap it up like this:
function utcDate(date) {
return new Date(date.getTime() - 60000 * date.getTimezoneOffset());
}
and then the sample would look like this
var startTime = utcDate(boundsResult[0].START);
var endTime = utcDate(boundsResult[0].END);
Upvotes: 0
Reputation: 92284
You should always store the timestamps on the server. The only time you need to care about the timezone is when inputting or outputting a date into/from a string by first calling date_default_timezone_set with the timezone that the date was input in (or is going to be output in)
If you need to create a time string (or parse) on the server, you need to find the client timezone offset and adjust it accordingly.
If you are displaying the times with JS on the client, the times will automatically be displayed/input in the local time zone. There's no way to tell the browser to use a different timezone. You can only use the local timezone (default) or call the getUTCxxxx
methods to get the GMT time and adjust it yourself (if you know the timezone offset you want to display it in). The timestamp is always the same, no matter what time zone.
The real problem is when you need account for daylight savings. That is a BIG problem for a different question.
Upvotes: 0
Reputation: 481
I've done this appointment thing . It gets confusing.
My solution was (as you suggested) to store everything as UTC, and when needed convert this to the user's time zone.
I did the main JS coding with date.js : http://www.datejs.com/.
Converting UTC date from the server into local for user
var d = new Date();
var offset = d.getTimezoneOffset();
var hours = parseInt(offset / -60);
var minutes = (offset % 60) * -1;
appointment_date = Date.parse(utc_date).add({minutes: minutes, hours:hours})
Of course utc_date has to be in the right format - but that should be easy with a date_format mysql function.
I would always store the UTC date and the user's version of that date in the database - so when I email them I'm not having to work out calculations based on their TZ
appointment_id utc_date user_date
1 2011-10-01 10:00 2011-10-01 16:00
I'm sure you get the idea.
Hope this helps.
Upvotes: 1