将时区从 Angular 应用程序传递到 ASP.NET Core 3.1 后端
Pass timezone from Angular app to ASP.NET Core 3.1 backend
我正在尝试获取以 UTC 时间保存的约会,例如通过日期。
问题是可以将约会保存为 UTC 6 月 1 日 10:00 下午,但是当用户位于德国时,该约会将是该用户当地时间的 6 月 2 日 12:00 上午。
当用户请求 6 月 1 日的所有约会时,该约会不应出现,但当请求 6 月 2 日时,它应该出现。
只要后端不知道应用哪个时区,它就会以相反的方式运行。
我知道后端有 ToLocalTime()
,但据我所知,只有当客户端与服务器处于同一时区时,它才会正确运行。
有人可能会说,我可以在客户端使用 getTimezoneOffset()
并以某种方式将其传递到后端。但这行不通,因为夏令时。
UTC 12 月 1 日 10:00 下午将导致德国当地时间为 12 月 1 日 11:00 下午,因此应用当前时区偏移没有帮助。
我发现,大多数浏览器都支持 Intl.DateTimeFormat().resolvedOptions().timeZone
以文本形式获取时区。但是将那个传递给后端也无济于事,因为当我检查后端 TimeZoneInfo.GetSystemTimeZones()
返回的支持时区列表时,我找不到与浏览器提供的字符串相同的字符串。 (浏览器returns'Europe/Berlin',后端id为'W. Europe Standard Time',其他字符串连本地化)
我知道我有点累了,因为处理日期和时间对我来说是今天反复出现的主题,但我是否错过了一些明显的东西?我该怎么做才能让后端知道相关时区?我如何获得该特定时区的日期时间?
关于时区转换,您的方向是正确的:
在浏览器中,获取 IANA 时区标识符:
const tzid = Intl.DateTimeFormat().resolvedOptions().timeZone;
将其传递给服务器
在 .NET 中,可以通过三种不同的方式使用 IANA 时区标识符:
您可以使用我的 TimeZoneConverter 库:
TimeZoneInfo tz = TZConvert.GetTimeZoneInfo(tzid);
您可以使用 Noda Time 库:
DateTimeZone tz = DateTimeZoneProviders.Tzdb[tzid];
没有图书馆,您可以在 Linux 上使用 IANA 时区标识符。 (这也将很快适用于从 .NET 6 开始的 Windows。)
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById(tzid);
然后您可以在 TimeZoneInfo
或 DateTimeZone
对象上使用转换方法在 UTC 和特定时区之间进行转换。
但是 - 您可能需要重新考虑存储约会时间的方法。你说:
... an appointment can be saved for UTC June 1st 10:00 PM, but when the user is located in Germany, that would be June 2nd 12:00 AM for that user's local time.
在大多数情况下,应根据与约会地点相关联的时区的日期和时间以及该时区的标识符来存储未来的约会。换句话说,不要以 UTC 格式存储上述约会。相反,存储“6 月 2 日,12:00 上午,Europe/Berlin”。需要时,将本地时间从转换为 UTC 或其他时区。
有些人喜欢说“始终使用 UTC”,但对于未来事件而言,该建议是不正确的。 UTC 最适合 past/present 事件,例如为销售交易或日志文件中的条目添加时间戳。
我正在尝试获取以 UTC 时间保存的约会,例如通过日期。 问题是可以将约会保存为 UTC 6 月 1 日 10:00 下午,但是当用户位于德国时,该约会将是该用户当地时间的 6 月 2 日 12:00 上午。 当用户请求 6 月 1 日的所有约会时,该约会不应出现,但当请求 6 月 2 日时,它应该出现。
只要后端不知道应用哪个时区,它就会以相反的方式运行。
我知道后端有 ToLocalTime()
,但据我所知,只有当客户端与服务器处于同一时区时,它才会正确运行。
有人可能会说,我可以在客户端使用 getTimezoneOffset()
并以某种方式将其传递到后端。但这行不通,因为夏令时。
UTC 12 月 1 日 10:00 下午将导致德国当地时间为 12 月 1 日 11:00 下午,因此应用当前时区偏移没有帮助。
我发现,大多数浏览器都支持 Intl.DateTimeFormat().resolvedOptions().timeZone
以文本形式获取时区。但是将那个传递给后端也无济于事,因为当我检查后端 TimeZoneInfo.GetSystemTimeZones()
返回的支持时区列表时,我找不到与浏览器提供的字符串相同的字符串。 (浏览器returns'Europe/Berlin',后端id为'W. Europe Standard Time',其他字符串连本地化)
我知道我有点累了,因为处理日期和时间对我来说是今天反复出现的主题,但我是否错过了一些明显的东西?我该怎么做才能让后端知道相关时区?我如何获得该特定时区的日期时间?
关于时区转换,您的方向是正确的:
在浏览器中,获取 IANA 时区标识符:
const tzid = Intl.DateTimeFormat().resolvedOptions().timeZone;
将其传递给服务器
在 .NET 中,可以通过三种不同的方式使用 IANA 时区标识符:
您可以使用我的 TimeZoneConverter 库:
TimeZoneInfo tz = TZConvert.GetTimeZoneInfo(tzid);
您可以使用 Noda Time 库:
DateTimeZone tz = DateTimeZoneProviders.Tzdb[tzid];
没有图书馆,您可以在 Linux 上使用 IANA 时区标识符。 (这也将很快适用于从 .NET 6 开始的 Windows。)
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById(tzid);
然后您可以在
TimeZoneInfo
或DateTimeZone
对象上使用转换方法在 UTC 和特定时区之间进行转换。
但是 - 您可能需要重新考虑存储约会时间的方法。你说:
... an appointment can be saved for UTC June 1st 10:00 PM, but when the user is located in Germany, that would be June 2nd 12:00 AM for that user's local time.
在大多数情况下,应根据与约会地点相关联的时区的日期和时间以及该时区的标识符来存储未来的约会。换句话说,不要以 UTC 格式存储上述约会。相反,存储“6 月 2 日,12:00 上午,Europe/Berlin”。需要时,将本地时间从转换为 UTC 或其他时区。
有些人喜欢说“始终使用 UTC”,但对于未来事件而言,该建议是不正确的。 UTC 最适合 past/present 事件,例如为销售交易或日志文件中的条目添加时间戳。