簡體   English   中英

在 ExpressJS 中獲取客戶端的時區偏移量

[英]Get client's timezone offset in ExpressJS

我正在尋找一種在 ExpressJS 中獲取客戶端時區偏移的方法(例如,使用 req 對象會非常棒)。

如果您控制客戶端,則可以使用客戶端 JavaScript 執行此操作

如果您不這樣做(例如,您正在構建像 API 這樣的服務器端組件),那么您就無法將其從 HTTP 請求中拉出(除非您使用的是會話,但即使這樣也不一定可靠)。

從好的方面來說,如果它只是服務器端,您也不應該擔心:將所有日期對象設置為 UTC 或 Unix 時間戳,並將其留給客戶端開發人員來處理時區。

正如其他人所提到的,無法通過 HTTP 獲取客戶端瀏覽器/操作系統時區偏移量,因此您需要從客戶端發送此數據。

就我而言,我有一個需要登錄的應用程序……所以我可以存儲用戶的首選項。 默認是使用瀏覽器時區,但用戶也可以配置一個特定的時區來使用所有的時間,而不是存儲在他們的用戶配置文件中(例如America/DallasEurope/Amsterdam )。

我不相信瀏覽器時間是正確的。 用戶也可能搞砸了他們的操作系統時區設置……所以時區偏移也可能不正確。 然而,大多數現代操作系統會根據 Geo-IP 隱含位置自動設置時區……因此,對於許多用戶而言,可以方便地環游世界並登錄應用程序並查看他們碰巧所在的本地時區的日期/時間為用戶體驗付出的努力是值得的。 總是想要查看特定時區的用戶可以配置它,我們將改用該首選項。

我這樣做的方法如下......在登錄表單上添加一個隱藏字段並使用javascript設置值。 當用戶登錄時,將此時區偏移量存儲在會話中。 如果用戶沒有設置首選時區,那么我們在渲染日期/時間時使用這個偏移量。 這意味着如果您的會話時間很長並且用戶可以在國家/地區之間旅行......他們仍然會顯示舊時區偏移量,直到下一次注銷/登錄。 如果您願意,您當然可以更頻繁地或什至在每次請求時獲取這些數據……但對我而言,在登錄時獲取此數據就足夠了。 無論如何,我的會話已因 IP 地址更改而過期...所以是的。 當然,如果他們的會話跨越了夏令時開關,那么在下次登錄之前偏移量不會准確(假設他們的操作系統/瀏覽器 TZ 首先是正確的)。

客戶端

<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 來自本地的偏移量 vs 來自 utc 的本地偏移量)。 您也可以在服務器端執行此操作。 在使用它之前,您可能也應該驗證這個數字......這里只是最少的示例代碼。

服務器端

然后在服務器端(快速)如果登錄成功,我會在會話中保留該 tzOffset 值。

然后,當使用moment-timezone格式化 express 日期moment-timezone我可以執行以下操作。 這個函數是一個“格式化程序”,我可以將它公開給 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 模板。 到目前為止,它對我來說效果很好。

好笑的故事

我有一個同事在他們的電腦上手動設置了錯誤的時區,所以時間是錯誤的。 他們沒有修復時區,而是禁用網絡時間並手動將時間設置為“正確”時間。

然后,當每個人都遲到一個小時參加他們安排的會議時,他們變得脾氣暴躁。

所以是的......不能保證客戶端時間或時區偏移量是正確的。

現實是,即使您有時區偏移量,也並不意味着您在客戶端擁有正確的時間,考慮到某些地區有“夏令時”。

但是,考慮到以下數據,您可以“猜測”用戶所在的時區:

  1. req.get('Accept-Language'),用戶現在可能居住在哪個國家;
  2. req.ip,在數據庫中搜索並找出大概位置;
  3. 客戶端 (new Date).getTimezoneOffset(),用於時區偏移;

最后,通過以上結果的計算,你的猜測應該差不多了。 時區應該存儲在像 'America/New_York' 這樣的字符串中,而不是時區偏移數字。

http://momentjs.com/timezone/應該是處理時區的好工具。

保存“幾乎正確”的時區后,不要忘記留下一個用戶可以更改它的地方。

有些人喜歡將庫momentJS用於處理時間的任何事情,但我相信 Javascript 中的Date對象足以滿足您的需求,並且不需要庫。 getTimezoneOffset正是您所需要的。 我希望這有幫助! 如果您有其他問題,請告訴我!

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM