如何处理客户端时区以检索数据?

How to handle client timezone for retrieving data?

提问人:robinhood 提问时间:10/3/2022 更新时间:10/3/2022 访问量:477

问:

我将来自不同运动的事件存储到我的数据库中。

例:

{
  "sport": "NBA",
  "name": "Warrios v Wizards",
  "date": "2022-10-01 02:00:00"
}

所有日期/时间都以 UTC 存储。通过 API (Node.js - Express),客户端将请求当天的事件。我很难理解如何根据客户端时区从服务器/数据库请求/查询事件。

例:

以下 API 路由返回特定日期的事件。 具有 UTC 偏移量的用户应从具有 UTC 偏移量的用户那里获得不同的数据,尤其是对于每个用户午夜时间之后或之前的事件。api/events/?date=2022-10-01(−10:00)(+12:00)

我认为的一个选择是在客户端级别确定时区,然后将数据传递给服务器,并使用该数据根据该时区转换和查询数据库。

还有更好的方法吗?

JavaScript 日期 时区 服务器端客户端

评论

2赞 Konrad 10/3/2022
我会从客户那里发送2022-09-30T14:00:00Z
0赞 Dean Van Greunen 10/3/2022
只需发送时区偏移量,例如 GMT + where is,或者在查询数据库时计算服务器上的偏移量XX-2+2
0赞 Dean Van Greunen 10/3/2022
X 可以是任何有效值
0赞 RobG 10/3/2022
@KonradLinkowski——不。OP 说“所有日期和时间都存储为 UTC”,因此“2022-10-01 02:00:00”是“2022-10-01T02:00:00Z”,应该发送给客户端。然后,客户端应根据主机设置将其转换为本地设置(对于实际地理位置可能不正确)。

答:

2赞 RobG 10/3/2022 #1

如果所有数据都存储为 UTC,则应将 UTC 发送到客户端并在那里转换为本地数据。

若要获取特定日期的所有事件,请使用客户端计算一天的开始和结束 UTC,并获取该范围内的事件。

例如,以下内容根据主机设置以 ISO 8601 格式返回一天的开始和结束时间,并以 UTC 格式显示。然后,可以在服务器上使用它来获取范围内的事件。在客户端上,可以将 UTC 值转换为本地值。

/* Return UTC values for start and end of local day
 *
 * @param {string} date - format yyyy-mm-dd
 * @returns {Array<string>} start and end of day as UTC in 
 *          ISO 8601 format
 *          endOfDay is 1ms before midnight
 */
function getLocalDayRange(date) {
  let [Y, M, D] = date.split(/\D/);
  let startOfDay = new Date(Y, M-1, D);
  let endOfDay =  new Date(Y, M-1, Number(D)+1, 0, 0, 0, -1);
  return [startOfDay.toISOString(),
          endOfDay.toISOString()];
}

// Start and end of 30 Sep 2022 based on client settings
console.log('Start and end for 30 Sep 2022:\n' +
            getLocalDayRange('2022-09-30').join('\n')
);

// Current date in YYYY-MM-DD format
let d = new Date().toLocaleDateString('en-ca');
console.log('Start and end for today (' + d + '):\n' +
            getLocalDayRange(d).join('\n')
);

在显示值时,始终包括假定的时区名称和/或偏移量,以便客户端可以确认它们对于其位置是正确的。