将UTC转换为本地时间 - 如何存储/推断数据捕获的本地时间

时间:2016-05-11 10:55:21

标签: c# datetime timezone datetimeoffset

我有一个应用程序,它接收来自几个数据收集点的数据,可能部署在世界任何地方。它们发布到Azure Service Bus中的队列,Console应用程序从队列中读取并使用UTC时间戳和表示其来源的Id来存储此数据。

我有一个基于输入数据运行反动事件的服务,每20秒刷新一次,因此它会查看以下数据窗口:

var window = DateTime.UtcNow.AddSeconds(-20);

var events = context.MyTable.Where(x => x.Timestamp >= window).ToList();

//Process the events

这可以正常工作,因为时间标准化为UTC。

然而,我还需要能够根据当地时间断言有关此数据的统计数据,并考虑夏令时(DST),例如:

  

"此类事件发生的平均时间是09:30:00"。

在此示例中,09:30:00表示当地时间,无论是在PST,GMT还是其他任何地方,都考虑了DST。

正如我所说,事件存储的是位置ID,它与表示此数据来源的位置的对象相关:

public class Location
{
    public int id { get; set; }
    public string name { get; set; }
    public Organisation organisation { get; set; }
}

一旦设置这些位置是永久性的,即它们不会移动到不同的时区,但它们的当地时间可能会随着夏令时的变化而变化。

我需要将哪些字段(以及格式)添加到我的Location对象中,以便推断出我的UTC标准化事件发生的当地时间,以及如何使用它将UTC转换为本地事件发生时的时间。

e.g。如果我有3个来自西班牙(+ 1),GMT(+0)和PST(-8)的赛事,当地时间12点发生。他们基本上存储为下午1点,中午12点和凌晨4点。我需要能够断言平均时间是一天上午9点。

2 个答案:

答案 0 :(得分:2)

您应该在Location记录中添加一个名为TimeZone的字符串值。您需要使用时区标识符填充它,该标识符可以是Windows时区ID或IANA时区ID。有关差异的说明,请参阅the timezone tag wiki。然后,您可以使用该时区来确定适用于相应UTC时间的本地时间。

我的建议是使用IANA时区,因为它们可以跨平台和语言使用,而不仅仅是被锁定到Windows和.NET。这是时区的事实上的标准。要在.NET中使用它们,请使用Noda Time库:

using NodaTime;
...
DateTimeZone tz = DateTimeZoneProviders.Tzdb[location.TimeZone];
Instant instant = Instant.FromDateTimeUtc(theUtcDateTime);
LocalTime localTime = instant.InZone(tz).TimeOfDay;

另一种方法是将Windows时区与.NET附带的TimeZoneInfo对象一起使用:

TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById(location.TimeZone);
DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(theUtcDateTime, tz);
TimeSpan localTime = localDateTime.TimeOfDay;

答案 1 :(得分:-1)

我认为您应该能够将您收集的日期保存为UTC时间,然后使用DateTime.ToLocalTime()将它们更改为您需要显示它们的地方时间。