在编写web应用程序时,将(服务器端)所有日期时间作为UTC时间戳存储在DB中是有意义的。
当我注意到在JavaScript中无法在时区操作方面原生做很多事情时,我感到很惊讶。
我稍微扩展了Date对象。这个函数有意义吗?基本上,每次我向服务器发送任何东西,它都将是一个用这个函数格式化的时间戳…
这里有什么主要问题吗?或者换个角度解决?
Date.prototype.getUTCTime = function(){
return new Date(
this.getUTCFullYear(),
this.getUTCMonth(),
this.getUTCDate(),
this.getUTCHours(),
this.getUTCMinutes(),
this.getUTCSeconds()
).getTime();
}
我只是觉得有点费解。我对表现也不是很确定。
以这种方式构造的日期使用本地时区,使得构造的日期不正确。要设置某个日期对象的时区,就要从包含该时区的日期字符串构造它。(我在旧版Android浏览器上运行时遇到了问题。)
注意,getTime()返回毫秒,而不是普通的秒。
对于UTC/Unix时间戳,以下内容就足够了:
Math.floor((new Date()).getTime() / 1000)
它将把当前时区偏移量考虑到结果中。对于字符串表示,David Ellis的答案是可行的。
澄清:
new Date(Y, M, D, h, m, s)
该输入被视为本地时间。如果传入UTC时间,结果将有所不同。观察(我现在在GMT +02:00,现在是07:50):
> var d1 = new Date();
> d1.toUTCString();
"Sun, 18 Mar 2012 05:50:34 GMT" // two hours less than my local time
> Math.floor(d1.getTime()/ 1000)
1332049834
> var d2 = new Date( d1.getUTCFullYear(), d1.getUTCMonth(), d1.getUTCDate(), d1.getUTCHours(), d1.getUTCMinutes(), d1.getUTCSeconds() );
> d2.toUTCString();
"Sun, 18 Mar 2012 03:50:34 GMT" // four hours less than my local time, and two hours less than the original time - because my GMT+2 input was interpreted as GMT+0!
> Math.floor(d2.getTime()/ 1000)
1332042634
还要注意,getUTCDate()不能取代getUTCDay()。这是因为getUTCDate()返回月份的日期;而getUTCDay()返回星期几。
I actually think Date values in js are far better than say the C# DateTime objects. The C# DateTime objects have a Kind property, but no strict underlying time zone as such, and time zone conversions are difficult to track if you are converting between two non UTC and non local times. In js, all Date values have an underlying UTC value which is passed around and known regardless of the offest or time zone conversions that you do. My biggest complaint about the Date object is the amount of undefined behaviour that browser implementers have chosen to include, which can confuse people who attack dates in js with trial and error than reading the spec. Using something like iso8601.js solves this varying behaviour by defining a single implementation of the Date object.
默认情况下,规范说您可以使用扩展的ISO 8601日期格式创建日期,如
var someDate = new Date('2010-12-12T12:00Z');
因此,您可以通过这种方式推断出准确的UTC时间。
当您希望将Date值传递回服务器时,您将调用
someDate.toISOString();
或者如果您更愿意使用毫秒时间戳(从UTC 1970年1月1日开始的毫秒数)
someDate.getTime();
ISO 8601 is a standard. You can't be confused about what a date string means if you include the date offset. What this means for you as a developer is that you never have to deal with local time conversions yourself. The local time values exist purely for the benefit of the user, and date values by default display in their local time. All the local time manipulations allow you to display something sensible to the user and to convert strings from user input. It's good practice to convert to UTC as soon as you can, and the js Date object makes this fairly trivial.
缺点是,没有太多的范围可以强制客户端的时区或地区(据我所知),这对于特定于网站的设置来说是很烦人的,但我猜这背后的原因是,这是一个不应该被触及的用户配置。
因此,简而言之,没有很多本地时区操作支持的原因只是因为您不想这样做。
编辑:下面的代码不工作。我总是假设new Date(). gettime()返回自1970年1月1日在当前时区的秒数。事实并非如此:getTime()返回UTC的秒数。因此,下面的代码会过度调整。谢谢大家!]
首先,感谢你的精彩见解。
我想我的问题标题错了……它应该是“获取现有日期的UTC Unix时间戳”。
如果我有一个date对象
var d = new Date(2009,01,31)
我在寻找一个函数,它会告诉我“UTC Unix时间戳”。
这个函数似乎是真正的诀窍:
Date.prototype.getUTCUnixTime = function (){
return Math.floor( new Date(
this.getUTCFullYear(),
this.getUTCMonth(),
this.getUTCDate(),
this.getUTCHours(),
this.getUTCMinutes(),
this.getUTCSeconds()
).getTime() / 1000);
}
注意,它对“this”有效,这意味着我可以做:
var n = new Date(2008,10,10)
...
...
n.getUTCUnixTime();
并获得自1970年1月1日以来在Unix时间内的秒数。
对吧?
这有点疯狂,对我来说,Javascript在UTC时间存储所有东西,但为了得到这个数字,我必须创建一个新的Date对象,传递各个UTC getter,然后最后调用getTime()…
芝加哥商业交易所。
您通常不需要在客户端做太多的“时区操作”。作为一项规则,我尝试以刻度或“自1970年1月1日午夜以来的毫秒数”的形式存储和使用UTC日期。这确实简化了存储、排序和偏移量的计算,最重要的是,使您摆脱了“日光节约时间”调整的麻烦。下面是我使用的一小段JavaScript代码。
获取当前UTC时间:
function getCurrentTimeUTC()
{
//RETURN:
// = number of milliseconds between current UTC time and midnight of January 1, 1970
var tmLoc = new Date();
//The offset is in minutes -- convert it to ms
return tmLoc.getTime() + tmLoc.getTimezoneOffset() * 60000;
}
然后,通常需要为最终用户按照他们的本地时区和格式格式化日期/时间。下面的代码处理了客户端计算机上所有复杂的日期和时间格式:
function formatDateTimeFromTicks(nTicks)
{
//'nTicks' = number of milliseconds since midnight of January 1, 1970
//RETURN:
// = Formatted date/time
return new Date(nTicks).toLocaleString();
}
function formatDateFromTicks(nTicks)
{
//'nTicks' = number of milliseconds since midnight of January 1, 1970
//RETURN:
// = Formatted date
return new Date(nTicks).toLocaleDateString();
}
function formatTimeFromTicks(nTicks)
{
//'nTicks' = number of milliseconds since midnight of January 1, 1970
//RETURN:
// = Formatted time
return new Date(nTicks).toLocaleTimeString();
}
下面这个例子:
var ticks = getCurrentTimeUTC(); //Or get it from the server
var __s = "ticks=" + ticks +
", DateTime=" + formatDateTimeFromTicks(ticks) +
", Date=" + formatDateFromTicks(ticks) +
", Time=" + formatTimeFromTicks(ticks);
document.write("<span>" + __s + "</span>");
返回以下内容(对于我的美国英语地区):
蜱=1409103400661,日期时间=8/26/2014下午6:36:40,日期=8/26/2014,
时间= 6:36:40点
以常规格式获取UTC时间的最简单方法如下:
> new Date().toISOString()
"2016-06-03T23:15:33.008Z"
如果需要EPOC时间戳,则将日期传递给date。解析方法
> Date.parse(new Date)
1641241000000
> Date.parse('2022-01-03T20:18:05.833Z')
1641241085833
或者可以使用+进行从Date到Int的类型转换
> +new Date
1641921156671
EPOC时间戳,以秒为单位。
> parseInt(Date.parse('2022-01-03T20:18:05.833Z') / 1000)
1641241085
> parseInt(new Date / 1000)
1643302523