0

在过去的几天里,我一直在试图解决这个问题,但只是因为它而失去了头发。

我正在使用下面的javascript作为计时器,该计时器使用时间戳作为开始日期进行计数。我正在使用数据库中的时间戳,该时间戳在计时器启动时保存,因为该时间戳是相对于用户的时区保存的,该时区是在他们的个人资料中选择的。

我的服务器 php 时区设置为“America/Los_Angeles”。我的用户个人资料时区也设置为此。这也是保存时区的格式。

但是,当我运行计时器时,即使我的 php 根据保存的时区显示正确的保存时间,即。'05/29/2013 6:05:49',计时器从一开始就有额外的时间。所以它看起来像“0 天 12 小时 0 分钟 13 秒”而不是“0 天 0 小时 0 分钟 13 秒”。

这一定是由于 javascript 时区所致?因为如果我将 TZ 设置为“America/New_York”,例如,它将是“0 天 9 小时 0 分钟 13 秒”,对吗?

我将如何解决这个问题?

JS

<script type="text/javascript">
function DaysHMSCounter(initDate, id){
    this.counterDate = new Date(initDate);
    this.container = document.getElementById(id);
    this.update();
}

DaysHMSCounter.prototype.calculateUnit=function(secDiff, unitSeconds){
    var tmp = Math.abs((tmp = secDiff/unitSeconds)) < 1? 0 : tmp;
    return Math.abs(tmp < 0 ? Math.ceil(tmp) : Math.floor(tmp));
}

DaysHMSCounter.prototype.calculate=function(){
    var secDiff = Math.abs(Math.round(((new Date()) - this.counterDate)/1000));
    this.days = this.calculateUnit(secDiff,86400);
    this.hours = this.calculateUnit((secDiff-(this.days*86400)),3600);
    this.mins = this.calculateUnit((secDiff-(this.days*86400)-(this.hours*3600)),60);
    this.secs = this.calculateUnit((secDiff-(this.days*86400)-(this.hours*3600)-(this.mins*60)),1);
}

DaysHMSCounter.prototype.update=function(){ 
    this.calculate();
    this.container.innerHTML =
    " <strong>" + this.days + "</strong> " + (this.days == 1? "day" : "days") +
    " <strong>" + this.hours + "</strong> " + (this.hours == 1? "hour" : "hours") +
    " <strong>" + this.mins + "</strong> " + (this.mins == 1? "min" : "mins") +
    " <strong>" + this.secs + "</strong> " + (this.secs == 1? "sec" : "secs");
    var self = this;
    setTimeout(function(){self.update();}, (1000));
}

window.onload=function(){ new DaysHMSCounter('05/29/2013 6:05:49', 'timer'); }

</script>

HTML

<div id="timer"></div>
4

2 回答 2

0

Your problem is that you are passing in the date in text format without the timezone. Thus the date is created in your local timezone.

If you instead have your server send the number of milliseconds past epoch (instead of string formatted date), then you can use new Date( millisPastEpoch ) and all should be good.

Alternatively, if you are guaranteed to know the user's timezone, then you can send the date formatted in the user's timezone instead of the server's.

于 2013-05-30T01:41:59.680 回答
0

首先,您需要考虑您是否有兴趣从特定时刻启动计时器。由于以下原因,您不能使用本地日历日期时间来表示05/29/2013 6:05:49

  • 用户可能在不同的时区
  • 用户可以使用不同的日期格式(MM/DD/YYYYvs DD/MM/YYYY
  • 由于夏令时转换,时间可能不明确

因此,您应该将 UTC 值传递给您的用户。浏览器会自动调整用户的本地时区。

您可以将该值表示为 UTC 1970 年 1 月 1 日之后的整数毫秒数,或者您可以将其表示为标准化格式,例如 ISO8601,例如2013-05-29T13:05:49Z2013-05-29T06:05:49-07:00。PHP 确实具有生成任何这些表示的工具。例如,您可以使用gmdate. 有关示例,请参见此答案。

如果您选择使用 ISO8601 格式,您应该知道它是 JavaScript 的后期添加,并非所有浏览器都原生支持。大多数较新的浏览器都支持它,但如果您想要最好的兼容性,您将需要使用诸如moment.js 之类的库(它还提供许多其他出色的功能)。

如果使用整数值,则不需要库并且可以将其直接传递给Date构造函数,但您可能会发现调试起来更加困难。

此外,由于本文中提到的原因,您可能希望将服务器时区设置为UTC而不是America/Los_Angeles.

于 2013-05-30T02:00:39.397 回答