简体   繁体   English

处理生日和时区的 Javascript

[英]Javascript dealing with birthdays and timezones

I'm building a web app where I need to store the user's birthday in the database and then display it on their profile.我正在构建一个网络应用程序,我需要将用户的生日存储在数据库中,然后将其显示在他们的个人资料中。 Naturally, birthdays shouldn't depend on the timezone.当然,生日不应该取决于时区。

My problem is on the javascript client, the new Date() object operates on the user's local timezone even if the underlying date is in UTC.我的问题是在 javascript 客户端上,即使基础日期是 UTC, new Date()对象也会在用户的本地时区上运行。

If the user is in the GMT+02:00 timezone and selects a birthday of January 1, 2000 00:00 , that date in UTC will be December 31, 1999 23:00 .如果用户在 GMT+02:00 时区并选择生日January 1, 2000 00:00 ,则该日期在 UTC 中将为December 31, 1999 23:00

The problem is displaying that date back to the user on their profile.问题是在他们的个人资料上向用户显示该日期。 What if the user suddenly travels to a different timezone, say GMT-05:00 and looks at their profile?如果用户突然旅行到不同的时区,比如 GMT-05:00 并查看他们的个人资料怎么办? They will see December 31, 1999 as their birthday.他们将把December 31, 1999视为他们的生日。

How does one deal with dates that should be the same regardless of timezone within a Javascript frontend and a server?无论 Javascript 前端和服务器中的时区如何,如何处理应该相同的日期? In what format should they be stored in the database?它们应该以什么格式存储在数据库中? And how do you display them indifferent of current timezone?以及如何显示它们与当前时区无关?

Unfortunately ECMAScript parses ISO 8601 date–only forms as UTC, but you can easily parse them as local with a simple function.不幸的是,ECMAScript 将 ISO 8601 日期格式解析为 UTC,但您可以使用简单的函数轻松地将它们解析为本地格式。 Store the dates however you want, but send an ISO 8601 date–only timestamp to the client like "2020-09-23", then parse and display as local, eg根据需要存储日期,但向客户端发送一个 ISO 8601 日期时间戳,如“2020-09-23”,然后解析并显示为本地,例如

 function parseISOLocal(s) { let [y, m, d] = s.split('-'); return new Date(y, m-1, d); } let timestamp = '2020-09-23'; // Wed Sep 23 2020 or similar console.log(parseISOLocal(timestamp).toDateString());

The way I ended up approaching it is slightly similar to @RobG's answer.我最终接近它的方式与@RobG 的回答略有相似。

I created this function to convert my date object to yyyy-mm-dd , based on the user's local timezone:我创建了这个函数来根据用户的本地时区将我的日期对象转换为yyyy-mm-dd

export const formatDateISO = (date: Date) => {
  let month = "" + (date.getMonth() + 1);
  let day = "" + date.getDate();
  let year = date.getFullYear();

  if (month.length < 2) month = "0" + month;
  if (day.length < 2) day = "0" + day;

  return [year, month, day].join("-");
};

In the backend, I converted that to yyyy-mm-dd 00:00 UTC and got the unix timestamp for it, which I stored in the database.在后端,我将其转换为yyyy-mm-dd 00:00 UTC并为其获取 unix 时间戳,并将其存储在数据库中。

To display the value back to the user, I used:为了向用户显示该值,我使用了:

new Date(unixTimestamp * 1000).toLocaleDateString('en-US', { timezone: 'UTC' })

This way, the user selects a date based on their timezone, and that gets translated to a 00:00 UTC timestamp in the database.这样,用户根据他们的时区选择一个日期,然后将其转换为数据库中的 00:00 UTC 时间戳。

Note: This only works for use cases where you want to display the same date no matter the time zone.注意:这仅适用于您想要显示相同日期而不受时区影响的用例。 Usually, this is not what you want.通常,这不是您想要的。

You usually want to display the time converted to the user's local timezone, eg an online event's date and time should be according to the user's timezone.您通常希望显示转换为用户本地时区的时间,例如在线活动的日期和时间应根据用户的时区。 A birthday should not.生日不应该。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM