如何处理服务器和客户端之间的时区?

时间:2013-08-08 11:07:14

标签: php javascript mysql timezone client-side

我正在开发一个网站,我必须处理来自用户的不同时区。这成为一个很大的问题,因为该网站举办拍卖等时间微妙的活动。

服务器上的所有日期/时间均为UTC。数据库以UTC时间戳存储所有内容。 PHP默认时区也设置为UTC(date_default_timezone_set('UTC');)。

现在,我的问题是我应该如何与用户互动,无论我是只显示日期,还是更重要的是,我正在阅读用户输入的日期/时间。

一个具体的例子:

  • 拍卖有截止日期,我将其作为UTC存储在数据库中。
  • 当我在网站上查看竞价时,javascript计时器使用Date对象来计算剩余时间。它会自动将时区转换为GMT + 0100(我的本地时区)。因此,如果截止日期为'2013-08-08 10:46:08'(UTC),则javascript日期对象将返回Aug 08 2013 11:26:15 GMT+0100 (GMT Standard Time)
  • 如果当前时间大于11:46:08,则计时器表示剩余时间为00:00(这是正确的)。
  • 但是,如果我尝试插入出价,服务器会接受,因为MySQL INSERT上的条件评估为true

    INSERT INTO Bids ... WHERE ... AND auction_deadline>现在()......

(因为auction_deadline = '2013-08-08 10:46:08'和NOW()= '2013-08-08 10:26:50'

所有这些巨大的时区都融化了我的大脑。我在这里错过了什么?我几乎可以肯定在数据库中以UTC格式存储所有日期/时间是最好的。我只是不清楚如何在用户和数据库之间处理它。

6 个答案:

答案 0 :(得分:3)

您的问题根本不涉及时区,只是客户可以转动时钟或使时钟偏差很大。为此,修复方法是每隔一段时间轮询一次服务器,以便在计算中使用偏移修正。

实际上,您甚至不需要日期对象。拍卖结束时有一个普遍的时刻。我们说它是1375960662823。现在,通用时刻是1375960669199,因此我们看到拍卖以6秒(1375960662823 - 1375960669199 ~ 6000)结束。无论我是在摩洛哥还是日本,它都将在6秒内结束。你了解它吗?

要生成这些号码,您可以在客户端拨打var now = Date.now() + skewFix,其中skewFix是需要应用的更正,以防客户端出现时间偏差或手动将计算机设置为错误的时间。

在PHP中,您可以使用$now = time() * 1000;

生成它

答案 1 :(得分:1)

JavaScript中的日期使用本地时区。您应该为用户获得UTC时间并将其发送到服务器

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"

这将解决服务器和客户端之间的时区问题。

答案 2 :(得分:1)

你说

  

(因为auction_deadline ='2013-08-08 10:46:08'和NOW()='2013-08-08 10:26:50')

在MySQL中 - NOW返回服务器的本地时区(docs)中的当前时间。

您可能需要UTC_TIMESTAMP之类的内容,以UTC (docs)的形式返回当前时间。

此外 - 您可能根本不应接受来自客户端JavaScript的任何输入时间。只相信自己的时钟。出价时,请在MySQL或PHP中使用服务器上的时间。不要接受它作为输入。

答案 3 :(得分:0)

您可以执行以下操作

加载页面后,向服务器发送ajax请求,其中包含用户的时区偏移量。您可以使用以下代码获取时区偏移量。

var curdate = new Date()
var offset = curdate.getTimezoneOffset()

偏移是以分钟为单位的时区偏移量。

我认为这会有所帮助。

答案 4 :(得分:0)

这是一个典型的主题,但大多数人都很难理解。首先,你永远不会提到DAYLIGHT SAVING。是的,我正在增加你的紧张情绪:)。

现在让我们看看我们如何做到这一点。您通过保存UTC时间做得很好。现在,我希望您已注册会员,并且每个会员都有能力设置他们的首选时区,否则您将向他们显示服务器的基于时区的时间。

当您通过“开始时间”发送给用户时,您必须在将UTC时间转换为他们的时间之后发送它们,类似地,当您从浏览器接受TIME时,用户操作或javascript您需要将该时间转换为UTC,考虑到用户的事实是他为自己的个人资料选择的时区。

希望明确你错在哪里的想法?请仔细阅读日间保存,因为当您继续使用其他逻辑时,它也将发挥重要作用。

编辑:

您可以使用javascript的时区偏移量,根据他的设置自动提交和用户输入。

答案 5 :(得分:0)

每次从客户端获取日期时,您都可以使用getUTC转换为UTC日期,即:

var todayDate = new Date(); 

var todayDateInUTC = new Date(todayDate.getUTCFullYear(), todayDate.getUTCMonth(), todayDate.getUTCDate(),  todayDate.getUTCHours(), todayDate.getUTCMinutes(), todayDate.getUTCSeconds());

所以在您将出价日期插入数据库之前,请使用getUTC函数将其转换为UTC格式。