C# 使用DateTimeOffset双向转换Unix时间戳出现1小时偏差如何解决
问题原因确认
你关于时区偏差的判断完全正确,问题本质是DateTime类型丢失时区标识后的隐式转换规则导致的:
DateTimeOffset.FromUnixTimeSeconds(timestamp)生成的是UTC时区的DateTimeOffset对象,值为2021-11-10 21:17:43 +00:00- 调用
.DateTime属性时,返回的DateTime对象Kind属性为Unspecified,仅保留时间数值,丢失了时区关联信息 - 将
Kind=Unspecified的DateTime强制转换为DateTimeOffset时,C#默认会将其判定为设备本地时区的时间,你的设备时区为UTC+1,因此生成的DateTimeOffset为2021-11-10 21:17:43 +01:00 - 调用
ToUnixTimeSeconds()时会自动转换为UTC时间计算,对应UTC时间为2021-11-10 20:17:43,最终时间戳比原始值少3600秒。
正确双向转换方案
方案1:全程使用DateTimeOffset(推荐)
避免转换为DateTime丢失时区信息,是最稳妥的实现:
[Fact] public void Convert_to_and_from_unix_timestamp() { // Arrange var timestamp = 1636579063; var dateOffset = DateTimeOffset.FromUnixTimeSeconds(timestamp); // Act var unixTimeSeconds = dateOffset.ToUnixTimeSeconds(); // Assert Assert.Equal(expected: timestamp, actual: unixTimeSeconds); }
方案2:必须使用DateTime时,明确指定UTC标识
如果业务需要依赖DateTime类型,全程使用UTC时区的DateTime,保留Kind属性:
[Fact] public void Convert_to_and_from_unix_timestamp() { // Arrange var timestamp = 1636579063; // 取UtcDateTime,返回的DateTime Kind为Utc,不会丢失时区标识 var utcDate = DateTimeOffset.FromUnixTimeSeconds(timestamp).UtcDateTime; // Act // 转换时会自动识别Kind=Utc,不会代入本地时区 var unixTimeSeconds = new DateTimeOffset(utcDate).ToUnixTimeSeconds(); // Assert Assert.Equal(expected: timestamp, actual: unixTimeSeconds); }
方案3:需要使用本地时间的场景,明确指定偏移量
如果业务确实需要使用本地时区的时间,转换时手动指定偏移量,不要依赖默认规则:
// 以UTC+1时区为例 var localDate = DateTimeOffset.FromUnixTimeSeconds(timestamp).ToOffset(TimeSpan.FromHours(1)).DateTime; // 转回时明确指定时区偏移 var unixTimeSeconds = new DateTimeOffset(localDate, TimeSpan.FromHours(1)).ToUnixTimeSeconds();
内容的提问来源于stack exchange,提问作者Muflix
相关产品推荐
相关产品推荐

