在编写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();
}
我只是觉得有点费解。我对表现也不是很确定。
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.
缺点是,没有太多的范围可以强制客户端的时区或地区(据我所知),这对于特定于网站的设置来说是很烦人的,但我猜这背后的原因是,这是一个不应该被触及的用户配置。
因此,简而言之,没有很多本地时区操作支持的原因只是因为您不想这样做。
以常规格式获取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
以这种方式构造的日期使用本地时区,使得构造的日期不正确。要设置某个日期对象的时区,就要从包含该时区的日期字符串构造它。(我在旧版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()返回星期几。