How to deal with timezones between server and clie

2019-04-26 17:29发布

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.

6条回答
Ridiculous、
2楼-- · 2019-04-26 18:07

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.

查看更多
来,给爷笑一个
3楼-- · 2019-04-26 18:07

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.

查看更多
Anthone
4楼-- · 2019-04-26 18:08

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.

查看更多
家丑人穷心不美
5楼-- · 2019-04-26 18:09

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.

查看更多
ら.Afraid
6楼-- · 2019-04-26 18:14

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.

查看更多
冷血范
7楼-- · 2019-04-26 18:24

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;

查看更多
登录 后发表回答