用时区和夏令时确定一天的开始

fre*_*hie 8 c# asp.net

我在会话中将用户的时区存储为小数.例如,如果用户在EST时区,我就有

UserTimeZone = -5.00;
Run Code Online (Sandbox Code Playgroud)

数据库中的数据以UTC格式存储,因此我想计算该用户当天的开始和结束时间,以便当用户想要特定日期的数据时,记录会按时区进行调整.

这就是我正在做的事情:

DateTime StartDate =  DateTime.Now.ToUniversalTime();

StartDate = StartDate.AddHours((double)UserTimeZone);
StartDate = StartDate.Date;
StartDate = StartDate.AddHours((double)UserTimeZone);

DateTime EndDate = StartDate.AddHours(24);
Run Code Online (Sandbox Code Playgroud)

我遇到的问题是,这不考虑夏令时,所以即使考虑到EST时间比UTC晚了5个小时,目前由于夏令时的变化,它实际上落后于UTC 4小时.

你有什么建议吗?谢谢.

Jon*_*Jon 9

要进行此类计算,您需要使用TimeZoneInfoDateTimeOffset类.

首先,我们需要为TimeZoneInfo本地时间和用户的本地时间获取一个实例:

var localTimezone = TimeZoneInfo.Local;
var userTimezone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
Run Code Online (Sandbox Code Playgroud)

这里需要注意的是,你需要知道用户本地时区的id(你目前的偏移量是不够的).您可以获取TimeZoneInfo系统识别的所有实例的列表TimeZoneInfo.GetSystemTimeZones,然后您需要一种方法将用户提供的时区与其中一个匹配.

对于这个例子,我有硬编码的EST.

然后你需要DateTimeOffset在当地时区获得今天午夜(一天开始)的实例:

var todayDate = DateTime.Today;
var todayLocal = new DateTimeOffset(todayDate,
                                    localTimezone.GetUtcOffset(todayDate));
Run Code Online (Sandbox Code Playgroud)

鉴于此,您可以DateTimeOffset在用户的时区中计算表示"今天"的午夜(基于您当地时间)的实例.请注意,根据时区,这可能实际上是用户时区的未来!

var todayUser = TimeZoneInfo.ConvertTime(todayLocal, userTimezone);
Run Code Online (Sandbox Code Playgroud)

最后,您可以为这两个日期创建时间戳,如下所示:

var epochStart = DateTime.Parse("01/01/1970 00:00:00");
var todayLocalTs = (todayLocal.Ticks - epochStart.Ticks)/TimeSpan.TicksPerSecond;
var todayUserTs = (todayUser.Ticks - epochStart.Ticks) / TimeSpan.TicksPerSecond;
Run Code Online (Sandbox Code Playgroud)