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

ep6jt1vc  于 2023-05-28  发布在  Node.js
关注(0)|答案(4)|浏览(253)

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

mzsu5hc0

mzsu5hc01#

如果你控制客户端,你可以do this with client-side JavaScript
如果你不这样做(例如你正在构建一个服务器端组件,比如API),那么你就不能把它从HTTP请求中拉出来(除非你正在使用会话,但即使这样也不一定可靠)。
从好的方面来说,如果只是服务器端,你也不必担心:将所有日期对象设置为UTC或Unix时间戳,并将其留给客户端开发人员来处理时区。

wgmfuz8q

wgmfuz8q2#

正如其他人所提到的,通过HTTP无法获得客户端浏览器/操作系统时区偏移,因此您需要从客户端发送此数据。
在我的例子中,我有一个需要登录的应用程序……所以我可以存储用户的偏好。默认情况下使用浏览器时区,但用户也可以配置特定时区以使用所有时间,而不是存储在其用户配置文件中(例如America/DallasEurope/Amsterdam)。
我不相信浏览器时间是正确的。用户可能也搞砸了他们的操作系统时区设置……所以时区偏移也可能不正确。然而,大多数现代操作系统会根据Geo-IP隐含的位置自动设置时区......因此,对于许多用户来说,能够在世界各地旅行并登录应用程序并查看他们碰巧所在的任何当地时区的日期/时间的便利性对于用户体验来说是值得的。总是希望看到特定时区的用户可以配置,我们将使用该首选项。
我做这件事的方法如下...在登录表单上添加一个隐藏字段并使用javascript设置值。当用户登录时,将此时区偏移存储在会话中。如果用户没有设置首选时区,那么我们在呈现日期/时间时使用此偏移量。这意味着,如果你有长时间的会话,并且用户可以在国家之间旅行...他们仍然会显示旧的时区偏移,直到下一次注销/登录。你当然可以更频繁地获取这些数据,如果你愿意的话,甚至可以在每次请求时获取这些数据......但是对于我来说,在登录时获取这些数据就足够了。我的会话在IP地址更改时过期...所以是的。当然,如果他们的会话跨越夏令时交换机,那么直到下一次登录时偏移量才是准确的(假设他们的操作系统/浏览器TZ首先是正确的)。
当然,没有什么可以阻止您在每次页面加载时(或在单个页面应用程序的事件间隔时)使用客户端javascript检查浏览器时区,并在检测到浏览器时区偏移量自上次使用的值以来已更改时调用服务器端API。对我来说,这是矫枉过正,但对一些应用程序来说,这可能是一个更好的方法。

客户端

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

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

服务端

然后在服务器端(express),如果有一个成功的登录,我会将该tzOffset值粘贴到会话中。
然后,当用moment-timezone化express中的日期时,我可以做如下事情。这个函数是一个“格式化器”,我可以将它暴露给pug/views,然后用用户正确的时区/格式格式化任何随机的日期对象。

function formatDateTimeForUser (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(date).utcOffset(userTZoffset).format(userDateFormat+' '+userTimeFormat+' ZZ');
}

ZZ用于以数字偏移格式显示时区(当我们使用来自客户端的固定数字偏移时相关。
zz用于以字符格式显示时区(例如PDT、PST、EST等),当我们使用欧洲/柏林等时区而不是固定的数值偏移时,这是相关的。

另一种方法

将原始日期推送到客户端并进行客户端格式化。缺点是更少的控制和一致性,更多的js推送到浏览器。如果你喜欢,moment也会运行客户端。
我只是基于用户区域设置和用户首选项配置我的服务器端格式化程序,然后公开这些格式化程序,以便在express中的pug模板中使用。到目前为止,它对我来说工作得很好。

搞笑故事

我有一个同事在他们的电脑上手动设置了错误的时区,所以时间是错误的。他们没有固定时区,而是禁用了网络时间,手动将时间设置为“正确”时间。
然后,当每个人都出现在他们安排的会议上一个小时后,他们变得脾气暴躁。
所以是的...不保证客户端时间或时区偏移是正确的。

t40tm48m

t40tm48m3#

现实是,即使你有时区偏移,这并不意味着你有正确的时间在客户端,考虑到一些地区有“夏令时”。
但是,您可以“猜测”用户处于哪个时区,考虑以下数据:

  1. req.get('Accept-Language'),用户现在可能居住在哪个国家;
    1.在数据库中搜索并找出大致位置;
  2. client-side(new Date).getTimezoneOffset(),表示时区偏移量;
    最后,通过以上结果的计算,你的猜测应该差不多了。时区应该存储在类似'America/New_约克'的字符串中,而不是时区偏移量。
    http://momentjs.com/timezone/应该是处理时区的好工具。
    保存“几乎正确”的时区后,不要忘记留下一个用户可以更改它的位置。
p3rjfoxz

p3rjfoxz4#

有些人喜欢使用momentJS库来处理任何与时间有关的事情,但我相信JavaScript中的Date对象足以满足您的需求,并且不需要库。getTimezoneOffset是你所需要的。我希望这对你有帮助!让我知道如果你有其他问题!

相关问题