为什么东部时间和中部时间的日期-时间偏移相同



我创建了一个小应用程序来测试UTC偏移量的存储时间。我不明白结果。如果我在今天14:01运行程序,我会得到这个:

此:

InsertPunch(new Employee { Id = 10, TimeZoneId = "Central Standard Time" });

在DB:中生成此

2021-01-0813:01:06.3594141-05:00

这:

InsertPunch(new Employee { Id = 12, TimeZoneId = "Eastern Standard Time" });

在DB:中生成此

2021-01-0814:01:07.5587251-05:00

时间是正确的;第一个确实是CT,第二个确实是ET。但是为什么两者的偏移量都是-5?CT的偏移量不应该是-6吗?我以为我们可以看到这样的时刻:

2021-01-08 14:01:07.5587251-05:00

。。。我们知道UTC时间是19:01(14:01+5:00(。这是正确的。但CT的结果不正确:13:01+5:00=18:01,当前UTC时间实际上是19:01。

我理解错了吗?或者我做错了什么?

static void Main(string[] args)
{
InsertPunch(new Employee { Id = 10, TimeZoneId = "Central Standard Time" });
InsertPunch(new Employee { Id = 12, TimeZoneId = "Eastern Standard Time" });
Console.WriteLine("Press any key to end.");
Console.ReadKey();
}
private static void InsertPunch(Employee employee)
{
var punchTimeUtc = DateTime.UtcNow; // Need timestamp in UTC to properly convert to employee's time zone.
var timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(employee.TimeZoneId); // Reference the employee's time zone.

var punchTimeInUsersZone = TimeZoneInfo.ConvertTimeFromUtc(punchTimeUtc, timeZoneInfo);
var punch = new Punch
{
EmployeeId = employee.Id,
PunchTime = punchTimeInUsersZone
};
string sql = "INSERT INTO [time].[Punch] ([EmployeeId],[PunchTime]) VALUES (@EmployeeId, @PunchTime)";
using (IDbConnection db = new SqlConnection(_connectionString))
{
db.Execute(sql, new { punch.EmployeeId, punch.PunchTime });
}
}

我相信发生的情况是,数据库中的字段是datetimeoffset类型(粘贴的示例中出现的偏移量证明了这一点(,但您正在传递。NETDateTime值插入该字段。

在这种情况下,SQL客户端将使用与中所述相同的效果静默地强制这些值。NET的DateTimeDateTimeOffset隐式转换运算符。来自这些文档:

。。。生成的DateTimeOffset对象的偏移量取决于dateTime参数的DateTime.Kind属性的值:

  • 如果DateTime.Kind属性的值为DateTimeKind.Utc,则DateTimeOffset对象的日期和时间设置为等于dateTime,并且其Offset属性设置为等于0。

  • 如果DateTime.Kind属性的值为DateTimeKind.LocalDateTimeKind.Unspecified,则DateTimeOffset对象的日期和时间设置为等于dateTime,并且其Offset属性设置为等于本地系统当前时区的偏移量。

在您给出的代码中,punchTimeInUsersZone.Kind将始终是DateTimeKind.Unspecified,因此在决定应用哪个偏移时将使用系统本地时区。因此,您存储-5是因为您在东部时区,并且日期属于标准时间段。

决议是使用。NETDateTimeOffset而不是DateTime

  • 首先,将Punch类的PunchTime属性更改为DateTimeOffset

  • 然后更改InsertPunch方法中的转换逻辑,如下所示:

    DateTimeOffset punchTimeUtc = DateTimeOffset.UtcNow;
    TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(employee.TimeZoneId);
    DateTimeOffset punchTimeInUsersZone = TimeZoneInfo.ConvertTime(punchTimeUtc, timeZoneInfo);
    

其余的都很好。

最新更新