问题描述
- 前端发送 timezoneOffsetInMinutes
var timezoneOffsetInMinutes = new Date().getTimezoneOffset();
console.log(timezoneOffsetInMinutes);
-
Api 接收偏移量
public DateTimeOffset GetDateTimeOffsetAtTimezone(int timezoneOffsetInMinutes) { var utc = DateTime.UtcNow; utc.AddMinutes(timezoneOffsetInMinutes); //Apply the offset var result = new DateTimeOffset(utc,TimeSpan.FromMinutes(timezoneOffsetInMinutes)); //Set the offset return result; }
出于某种原因,我收到此错误消息
"The UTC Offset for Utc DateTime instances must be 0. (Parameter 'offset')"
我不想使用 NodaTime,因为我已经有了 timezoneOffset,我只需要应用它。除非我错了,我应该使用 NodaTime。
如果您知道这样做的正确方法,那将非常有帮助。
解决方法
直接回答您的问题:
public DateTimeOffset GetDateTimeOffsetAtTimezone(int timezoneOffsetInMinutes)
{
// Start out with the current UTC time as a DateTimeOffset
DateTimeOffset utc = DateTimeOffset.UtcNow;
// Get the offset as a TimeSpan
TimeSpan offset = TimeSpan.FromMinutes(timezoneOffsetInMinutes);
// Apply the offset to the UTC time to calculate the resulting DateTimeOffset
DateTimeOffset result = utc.ToOffset(offset);
return result;
}
也就是说 - 请确保您仅在中继 当前 时区偏移量时才这样做 - 时区偏移量 现在 在客户端上有效,并且 现在在服务器上(合理的传输延迟是可以接受的)。要了解为什么,请参阅 the timezone tag wiki 中的“时区 != 偏移”。
如果您还需要使用现在以外的时间,那么您需要从客户端收集时区 ID,而不是偏移量。
var timeZoneId = Intl.DateTimeFormat().resolvedOptions().timeZone;
console.log(timeZoneId);
这将返回 IANA 时区标识符,例如 America/Los_Angeles
。
在服务器端,您有选择:
-
在非 Windows 系统(Linux、OSX 等)上:
public DateTimeOffset ConvertDateTimeOffsetToTimeZone(DateTimeOffset dto,string ianaTimeZoneId) { // Get the time zone by its identifier TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById(ianaTimeZoneId); // Convert the input value to the time zone DateTimeOffset result = TimeZoneInfo.ConvertTime(dto,tz); return result; }
-
在使用我的 TimeZoneConverter 库的任何操作系统(包括 Windows)上:
using TimeZoneConverter; public DateTimeOffset ConvertDateTimeOffsetToTimeZone(DateTimeOffset dto,tz); return result; }
-
在使用 Noda Time 库的任何操作系统(包括 Windows)上:
using NodaTime; public DateTimeOffset ConvertDateTimeOffsetToTimeZone(DateTimeOffset dto,string ianaTimeZoneId) { // Get the time zone by its identifier DateTimeZone tz = DateTimeZoneProviders.Tzdb[ianaTimeZoneId]; // Convert the input value to the time zone DateTimeOffset result = OffsetDateTime.FromDateTimeOffset(dto) .InZone(tz) .ToDateTimeOffset(); return result; }
当然,如果您在整个项目中都使用 Noda Time,那么您可能更愿意保留 Noda Time 的类型,而不是来回转换。