我有一个应用程序,它接收来自几个数据收集点的数据,可能部署在世界任何地方。它们发布到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点。
答案 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()将它们更改为您需要显示它们的地方时间。