为什么东部时间和中部时间的日期时间偏移相同?
Why is the date time offset the same for eastern and central time?
我创建了一个小应用程序来测试使用 UTC 偏移量的存储时间。我不明白结果。如果我 运行 今天在 14:01 的程序,我得到这个:
这个:
InsertPunch(new Employee { Id = 10, TimeZoneId = "Central Standard Time" });
在数据库中生成这个:
2021-01-08 13:01:06.3594141 -05:00
这个:
InsertPunch(new Employee { Id = 12, TimeZoneId = "Eastern Standard Time" });
在数据库中生成这个:
2021-01-08 14: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
类型(正如您粘贴的示例中出现的偏移量所证明的那样),但您传递的是 .NET DateTime
将数据插入该字段时将值添加到参数中。
在这种情况下,SQL 客户端将使用与 .NET 的 DateTime
到 DateTimeOffset
隐式转换运算符所描述的相同效果静默强制这些值。来自 those docs:
... The offset of the resulting DateTimeOffset
object depends on the value of the DateTime.Kind
property of the dateTime
parameter:
If the value of the DateTime.Kind
property is DateTimeKind.Utc
, the date and time of the DateTimeOffset
object is set equal to dateTime
, and its Offset
property is set equal to 0.
If the value of the DateTime.Kind
property is DateTimeKind.Local
or DateTimeKind.Unspecified
, the date and time of the DateTimeOffset
object is set equal to dateTime
, and its Offset
property is set equal to the offset of the local system's current time zone.
在您提供的代码中,punchTimeInUsersZone.Kind
将始终为 DateTimeKind.Unspecified
,因此在决定应用哪个偏移量时将使用系统本地时区。因此你存储 -5 因为你在东部时区并且日期属于标准时间段。
解决方案是在代码中使用 .NET DateTimeOffset
类型而不是 DateTime
。
首先,将 Punch
class 上的 PunchTime
属性 更改为 DateTimeOffset
。
然后在你的InsertPunch
方法中改变转换逻辑如下:
DateTimeOffset punchTimeUtc = DateTimeOffset.UtcNow;
TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(employee.TimeZoneId);
DateTimeOffset punchTimeInUsersZone = TimeZoneInfo.ConvertTime(punchTimeUtc, timeZoneInfo);
其他都可以。
我创建了一个小应用程序来测试使用 UTC 偏移量的存储时间。我不明白结果。如果我 运行 今天在 14:01 的程序,我得到这个:
这个:
InsertPunch(new Employee { Id = 10, TimeZoneId = "Central Standard Time" });
在数据库中生成这个:
2021-01-08 13:01:06.3594141 -05:00
这个:
InsertPunch(new Employee { Id = 12, TimeZoneId = "Eastern Standard Time" });
在数据库中生成这个:
2021-01-08 14: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
类型(正如您粘贴的示例中出现的偏移量所证明的那样),但您传递的是 .NET DateTime
将数据插入该字段时将值添加到参数中。
在这种情况下,SQL 客户端将使用与 .NET 的 DateTime
到 DateTimeOffset
隐式转换运算符所描述的相同效果静默强制这些值。来自 those docs:
... The offset of the resulting
DateTimeOffset
object depends on the value of theDateTime.Kind
property of thedateTime
parameter:
If the value of the
DateTime.Kind
property isDateTimeKind.Utc
, the date and time of theDateTimeOffset
object is set equal todateTime
, and itsOffset
property is set equal to 0.If the value of the
DateTime.Kind
property isDateTimeKind.Local
orDateTimeKind.Unspecified
, the date and time of theDateTimeOffset
object is set equal todateTime
, and itsOffset
property is set equal to the offset of the local system's current time zone.
在您提供的代码中,punchTimeInUsersZone.Kind
将始终为 DateTimeKind.Unspecified
,因此在决定应用哪个偏移量时将使用系统本地时区。因此你存储 -5 因为你在东部时区并且日期属于标准时间段。
解决方案是在代码中使用 .NET DateTimeOffset
类型而不是 DateTime
。
首先,将
Punch
class 上的PunchTime
属性 更改为DateTimeOffset
。然后在你的
InsertPunch
方法中改变转换逻辑如下:DateTimeOffset punchTimeUtc = DateTimeOffset.UtcNow; TimeZoneInfo timeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(employee.TimeZoneId); DateTimeOffset punchTimeInUsersZone = TimeZoneInfo.ConvertTime(punchTimeUtc, timeZoneInfo);
其他都可以。