如何忽略用户的时区并强制Date()使用特定的时区

在JS应用程序中,我从服务器(Ajax)收到时间戳( 1270544790922 )。

基于这个时间戳我创buildDate对象使用:

 var _date = new Date(); _date.setTime(1270544790922); 

现在,在当前用户区域设置时区中_date解码时间戳。 我不要那个。

我希望_ date将此时间戳转换为欧洲赫尔辛基市的当前时间(不考虑用户的当前时区)。

我怎样才能做到这一点?

date对象的基础值实际上是UTC。 为了certificate这一点,请注意,如果您inputnew Date(0)您将看到如下所示的内容: Wed Dec 31 1969 16:00:00 GMT-0800 (PST) 。 在GMT中0被视为0,但.toString()方法显示当地时间。

值得注意的是,UTC代表世界时间码。 目前在2个不同地方的时间是相同的UTC,但输出格式可能不同。

我们需要的是一些格式

 var _date = new Date(1270544790922); // outputs > "Tue Apr 06 2010 02:06:30 GMT-0700 (PDT)", for me _date.toLocaleString('fi-FI', { timeZone: 'Europe/Helsinki' }); // outputs > "6.4.2010 klo 12.06.30" _date.toLocaleString('en-US', { timeZone: 'Europe/Helsinki' }); // outputs > "4/6/2010, 12:06:30 PM" 

这可以工作,但是….你不能真正使用任何其他的date方法为你的目的,因为他们描述了用户的时区。 你想要的是一个与赫尔辛基时区有关的date对象。 你现在的select是使用一些第三方库(我推荐这个),或者修改date对象,这样你就可以使用它的大部分方法。

选项1 – 像时刻的第三方

 moment(1270544790922).tz('Europe/Helsinki').format('YYYY-MM-DD HH:mm:ss') // outputs > 2010-04-06 12:06:30 moment(1270544790922).tz('Europe/Helsinki').hour() // outputs > 12 

这看起来比我们接下来要做的更优雅。

选项2 – 破解date对象

 var currentHelsinkiHoursOffset = 2; // sometimes it is 3 var date = new Date(1270544790922); var helsenkiOffset = currentHelsinkiHoursOffset*60*60000; var userOffset = _date.getTimezoneOffset()*60000; // [min*60000 = ms] var helsenkiTime = new Date(date.getTime()+ helsenkiOffset + userOffset); // Outputs > Tue Apr 06 2010 12:06:30 GMT-0700 (PDT) 

它仍然认为是GMT-0700(PDT),但是如果你不太注意,你可能会错误地认为这是一个对你有用的date对象。

我方便地跳过了一部分。 您需要能够定义currentHelsinkiOffset 。 如果您可以在服务器端使用date.getTimezoneOffset() ,或者只是使用一些if语句来描述何时会发生时区更改,那么应该可以解决您的问题。

结论 – 我认为特别是为了这个目的,你应该使用一个date库像时刻 。

要考虑毫秒和用户的时区,请使用以下内容:

 var _userOffset = _date.getTimezoneOffset()*60*1000; // user's offset time var _centralOffset = 6*60*60*1000; // 6 for central time - use whatever you need _date = new Date(_date.getTime() - _userOffset + _centralOffset); // redefine variable 

我怀疑, 答案没有给出正确的结果。 在提问者希望将时间戳从服务器转换为当前时间在赫尔辛基,无视当前用户的时区。

事实上,用户的时区可能是我们无法相信的。

如果 时间戳是1270544790922,我们有一个function:

 var _date = new Date(); _date.setTime(1270544790922); var _helsenkiOffset = 2*60*60;//maybe 3 var _userOffset = _date.getTimezoneOffset()*60*60; var _helsenkiTime = new Date(_date.getTime()+_helsenkiOffset+_userOffset); 

当纽约客访问该页面时,alert(_helsenkiTi​​me)会打印:

 Tue Apr 06 2010 05:21:02 GMT-0400 (EDT) 

当Finlander访问该页面时,alert(_helsenkiTi​​me)会打印:

 Tue Apr 06 2010 11:55:50 GMT+0300 (EEST) 

所以这个function是正确的,只有当页面访问者在他的计算机中有目标时区(欧洲/赫尔辛基),但几乎在世界其他任何地方都失败了。 而且由于服务器时间戳通常是UNIX时间戳,它是按照UTC定义的自从Unix Epoch(1970年1月1日00:00:00 GMT)以来的秒数,所以我们无法从时间戳确定DST或非DST。

所以解决的办法是DISREGARD当前用户的时区,并实现一些方法来计算UTC偏移是否在DSTdate。 JavaScript没有本地方法来确定其他时区的DST转换历史logging,而不是当前用户的时区。 我们可以使用服务器端脚本来简单地实现这一点,因为我们可以很容易地访问服务器的时区数据库和所有时区的整个转换历史logging。

但是,如果您无法访问服务器(或任何其他服务器)的时区数据库并且时间戳采用UTC,则可以通过在JavaScript中对DST规则进行硬编码来获得类似的function。

为了涵盖1998 – 2099年在欧洲/赫尔辛基的date,您可以使用以下函数( jsfiddled ):

 function timestampToHellsinki(server_timestamp) { function pad(num) { num = num.toString(); if (num.length == 1) return "0" + num; return num; } var _date = new Date(); _date.setTime(server_timestamp); var _year = _date.getUTCFullYear(); // Return false, if DST rules have been different than nowadays: if (_year<=1998 && _year>2099) return false; // Calculate DST start day, it is the last sunday of March var start_day = (31 - ((((5 * _year) / 4) + 4) % 7)); var SUMMER_start = new Date(Date.UTC(_year, 2, start_day, 1, 0, 0)); // Calculate DST end day, it is the last sunday of October var end_day = (31 - ((((5 * _year) / 4) + 1) % 7)) var SUMMER_end = new Date(Date.UTC(_year, 9, end_day, 1, 0, 0)); // Check if the time is between SUMMER_start and SUMMER_end // If the time is in summer, the offset is 2 hours // else offset is 3 hours var hellsinkiOffset = 2 * 60 * 60 * 1000; if (_date > SUMMER_start && _date < SUMMER_end) hellsinkiOffset = 3 * 60 * 60 * 1000; // Add server timestamp to midnight January 1, 1970 // Add Hellsinki offset to that _date.setTime(server_timestamp + hellsinkiOffset); var hellsinkiTime = pad(_date.getUTCDate()) + "." + pad(_date.getUTCMonth()) + "." + _date.getUTCFullYear() + " " + pad(_date.getUTCHours()) + ":" + pad(_date.getUTCMinutes()) + ":" + pad(_date.getUTCSeconds()); return hellsinkiTime; } 

用法示例:

 var server_timestamp = 1270544790922; document.getElementById("time").innerHTML = "The timestamp " + server_timestamp + " is in Hellsinki " + timestampToHellsinki(server_timestamp); server_timestamp = 1349841923 * 1000; document.getElementById("time").innerHTML += "<br><br>The timestamp " + server_timestamp + " is in Hellsinki " + timestampToHellsinki(server_timestamp); var now = new Date(); server_timestamp = now.getTime(); document.getElementById("time").innerHTML += "<br><br>The timestamp is now " + server_timestamp + " and the current local time in Hellsinki is " + timestampToHellsinki(server_timestamp);​ 

而且这个打印下面不pipe用户时区如下:

 The timestamp 1270544790922 is in Hellsinki 06.03.2010 12:06:30 The timestamp 1349841923000 is in Hellsinki 10.09.2012 07:05:23 The timestamp is now 1349853751034 and the current local time in Hellsinki is 10.09.2012 10:22:31 

当然,如果你可以用偏移量(DST或非DST的)已经添加到服务器上的时间戳的forms返回时间戳,你不必在客户端计算它,你可以简化这个function。 但记得不要使用timezoneOffset(),因为那么你必须处理用户时区,这不是想要的行为。

只是另一种方法

 function parseTimestamp(timestampStr) { return new Date(new Date(timestampStr).getTime() + (new Date().getTimezoneOffset() * 60 * 1000)); }; //Sun Jan 01 2017 12:00:00 var timestamp = 1483272000000; date = parseTimestamp(timestamp); document.write(date); 

你可以使用setUTCMilliseconds()

 var _date = new Date(); _date.setUTCMilliseconds(1270544790922); 

假设你在赫尔辛基时间获得时间戳,我将创build一个date对象设置为1970年1月1日午夜UTC(忽略浏览器的本地时区设置)。 然后只需要添加所需的毫秒数。

 var _date = new Date( Date.UTC(1970, 0, 1, 0, 0, 0, 0) ); _date.setUTCMilliseconds(1270544790922); alert(_date); //date shown shifted corresponding to local time settings alert(_date.getUTCFullYear()); //the UTC year value alert(_date.getUTCMonth()); //the UTC month value alert(_date.getUTCDate()); //the UTC day of month value alert(_date.getUTCHours()); //the UTC hour value alert(_date.getUTCMinutes()); //the UTC minutes value