javascript 在 ExpressJS 中获取客户端的时区偏移量

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/31595641/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-28 14:02:08  来源:igfitidea点击:

Get client's timezone offset in ExpressJS

javascriptnode.jsexpresstimezone

提问by Ziad

I'm searching for a way to get client's timezone offset in ExpressJS (with req object, for example, would be really great).

我正在寻找一种在 ExpressJS 中获取客户端时区偏移量的方法(例如,使用 req 对象会非常棒)。

回答by brandonscript

If you control the client, you can do this with client-side JavaScript.

如果您控制客户端,则可以使用客户端 JavaScript 执行此操作

If you don't (e.g. you're building a server-side component like an API), then you can't pull it out of the HTTP request (unless you're using sessions, but even that's not necessarily reliable).

如果您不这样做(例如,您正在构建像 API 这样的服务器端组件),那么您就无法将其从 HTTP 请求中拉出(除非您正在使用会话,但即使这样也不一定可靠)。

On the upside, if it's only server-side, you shouldn't worry about it either: set all your date objects as UTC or a Unix timestamp and leave it to the client developer to handle timezones.

从好的方面来说,如果它只是服务器端,您也不应该担心:将所有日期对象设置为 UTC 或 Unix 时间戳,并将其留给客户端开发人员来处理时区。

回答by mattpr

As others have mentioned, getting the client-side browser/OS timezone offset is not available via HTTP, so you need to send this data from the client side.

正如其他人所提到的,无法通过 HTTP 获取客户端浏览器/操作系统时区偏移量,因此您需要从客户端发送此数据。

In my case I have an app that requires login...so I can store a user's preferences. The default is to use browser timezone, but the user can also configure a specific timezone to use all the time instead which is stored in their user profile (e.g. America/Dallasor Europe/Amsterdam).

就我而言,我有一个需要登录的应用程序……所以我可以存储用户的首选项。默认是使用浏览器时区,但用户也可以配置一个特定的时区来使用所有的时间,而不是存储在他们的用户配置文件中(例如America/DallasEurope/Amsterdam)。

I don't trust browser time to be correct. The user may have also screwed up their OS timezone setting...so timezone offset may also not be correct. However most modern OSes set timezone automatically based on Geo-IP implied location...so for many users the convenience of being able to travel around the world and login to the app and see date/time in whatever local timezone they happen to be in is worth the effort for the user experience. Users that always want to see a specific timezone can configure that and we will use that preference instead.

我不相信浏览器时间是正确的。用户也可能搞砸了他们的操作系统时区设置……所以时区偏移也可能不正确。然而,大多数现代操作系统根据 Geo-IP 隐含位置自动设置时区......因此对于许多用户来说,能够方便地环游世界并登录应用程序并查看他们碰巧所在的本地时区的日期/时间为用户体验付出的努力是值得的。总是想要查看特定时区的用户可以配置它,我们将改用该首选项。

The way I do this is the following... on the login form add a hidden field and set the value with javascript. When the user logs in, store this timezone offset in the session. If the user hasn't set a preferred timezone, then we use this offset when rendering date/time. This means that if you have long sessions and a user can travel around between countries...they will still show the old timezone offset until the next logout/login. You can of course get this data more frequently or even on every request if you want...but for my purposes getting this on login is enough. My sessions are expired on IP address change anyway...so yeah. Of course if their session crosses a daylight savings switch then the offset won't be accurate until the next login (assuming their OS/browser TZ is correct in the first place).

我这样做的方法如下......在登录表单上添加一个隐藏字段并使用javascript设置值。当用户登录时,将此时区偏移量存储在会话中。如果用户没有设置首选时区,那么我们在渲染日期/时间时使用这个偏移量。这意味着,如果您的会话时间很长并且用户可以在国家/地区之间旅行……他们仍将显示旧时区偏移量,直到下一次注销/登录。如果您愿意,您当然可以更频繁地获取这些数据,甚至可以在每次请求时获取这些数据……但就我而言,在登录时获取这些数据就足够了。无论如何,我的会话已因 IP 地址更改而过期...所以是的。当然,如果他们的会话跨越了夏令时开关,那么在下次登录之前偏移量不会准确(假设他们的操作系统/浏览器 TZ 首先是正确的)。

Client Side

客户端

<input type="hidden" name="tzOffset" id="tzOffset">
<!-- ... -->
<script>
var tzOffset = new Date().getTimezoneOffset(),
    tzInput = document.getElementById('tzOffset');
tzInput.value = tzOffset*(-1);
</script>

Note that I multiple it by -1because I am going to use moment.js for formatting on the express end and the offset is backwards (utc offset from local vs local offset from utc). You could also do this on the server end. You should probably validate this number as well before using it...just minimal example code here.

请注意,我将其乘以倍数,-1因为我将使用 moment.js 在 express 端进行格式化,并且偏移量是向后的(来自本地的 utc 偏移量与来自 utc 的本地偏移量)。您也可以在服务器端执行此操作。在使用它之前,您可能也应该验证这个数字......这里只是最少的示例代码。

Server Side

服务器端

Then on the server side (express) if there is a successful login, I stick that tzOffset value in the session.

然后在服务器端(快速)如果登录成功,我会在会话中粘贴该 tzOffset 值。

Then when formatting dates in express with moment-timezoneI can do something like the following:

然后当用 express 格式化日期时,moment-timezone我可以执行以下操作:

function (date) {
    var userTZ,     // user specified TZ like Europe/Berlin
        userTZoffset, // tzOffset we got from login form
        userDateFormat,  // user specified date format (or default)
        userTimeFormat; // user specified time format (or default)

    if (userTZ)
        return moment(date).tz(userTZ).format(userDateFormat+' '+userTimeFormat+' zz');
    else
        return moment(d).utcOffset(userTZoffset).format(userDateFormat+' '+userTimeFormat+' ZZ');
}

The ZZformat is for showing timezone in numeric offset format (relevant when we use a fixed numeric offset from client.

ZZ格式用于以数字偏移格式显示时区(当我们使用来自客户端的固定数字偏移时相关。

The zzformat is for showing timezone in character format (e.g. PDT, PST, EST, etc) which is relevant when we have a timezone like Europe/Berlin instead of a fixed numerical offset.

zz格式用于以字符格式(例如 PDT、PST、EST 等)显示时区,当我们有一个像欧洲/柏林这样的时区而不是固定的数字偏移时,这是相关的。

Another approach

另一种方法

Push raw dates to client and do client-side formatting. Downside is less control and consistency and more js to push to the browser. moment will also run client side if you like.

将原始日期推送到客户端并进行客户端格式化。缺点是更少的控制和一致性以及更多的 js 推送到浏览器。如果您愿意,moment 也将运行客户端。

I just configure my formatters server-side based on user locale and user prefs and then expose those formatters for use in my pug templates in express. So far it works pretty well for me.

我只是根据用户区域设置和用户首选项配置我的格式化程序服务器端,然后公开这些格式化程序以用于我在 express 中的 pug 模板。到目前为止,它对我来说效果很好。

Funny Story

好笑的故事

I had a co-worker that manually set the wrong timezone on their computer and so the time was wrong. Instead of fixing the timezone they disabled network time and manually set the time to be the "correct" time.

我有一个同事在他们的电脑上手动设置了错误的时区,所以时间是错误的。他们没有修复时区,而是禁用网络时间并手动将时间设置为“正确”时间。

Then they got grumpy when everyone was showing up to meetings they scheduled an hour late.

然后,当每个人都迟到一个小时参加他们安排的会议时,他们变得脾气暴躁。

So yeah...no guarantees the client-side time or timezone offset will be correct.

所以是的......不能保证客户端时间或时区偏移量是正确的。

回答by alphakevin

The thing is even if you have got the timezone offset, it doesn't mean you have the the correct time on client side, considering some area have "daylight saving time".

问题是即使您有时区偏移,也不意味着您在客户端有正确的时间,考虑到某些地区有“夏令时”。

But, you could "guess" which timezone the user is in, considering the following data:

但是,考虑到以下数据,您可以“猜测”用户所在的时区:

  1. req.get('Accept-Language'), for which country is the user may live in now;
  2. req.ip, to search in a database and find out the approximate location;
  3. client-side (new Date).getTimezoneOffset(), for timezone offset;
  1. req.get('Accept-Language'),用户现在可能居住在哪个国家;
  2. req.ip,在数据库中搜索并找出大概位置;
  3. 客户端 (new Date).getTimezoneOffset(),用于时区偏移;

Finally, through the calculation of the above result, your guess should be almost there. The timezone should store in string like 'America/New_York' but not a timezone offset number.

最后,通过以上结果的计算,你的猜测应该差不多了。时区应该存储在像 'America/New_York' 这样的字符串中,而不是时区偏移数字。

http://momentjs.com/timezone/should be a good tool to deal with timezone.

http://momentjs.com/timezone/应该是处理时区的好工具。

After you save the "almost correct" timezone, don't forget to leave a place where user can change it .

保存“几乎正确”的时区后,不要忘记留下一个用户可以更改它的地方。

回答by Stephan Genyk

Some people like using the library momentJSfor anything dealing with time, but I believe the Dateobject in Javascript suffices what you are looking for and does not require a library. The getTimezoneOffsetis what you will need. I hope this helps! Let me know if you have other questions!

有些人喜欢将库momentJS用于处理时间的任何事情,但我相信Javascript 中的Date对象足以满足您的需求,并且不需要库。在使用getTimezoneOffset是你所需要的。我希望这有帮助!如果您有其他问题,请告诉我!