Reputation: 1153
I have an application which receives data from several data gathering points, potentially deployed anywhere in the world. They post to a queue in an Azure Service Bus and a Console application reads from the queue and stores this data with a UTC timestamp and an Id representing the location it came from.
I have a service which runs reactionary events based on the input data, refreshing every 20 seconds, and so it looks at the data window of:
var window = DateTime.UtcNow.AddSeconds(-20);
var events = context.MyTable.Where(x => x.Timestamp >= window).ToList();
//Process the events
This works fine as the time is standardised to UTC.
I also however need to be able to assert statistics about this data relative to local time as well, taking into account Daylight Savings Time (DST), for example:
"The average time of day that this type of event occurs is 09:30:00".
In this example, 09:30:00
means local time, whether it occured in PST, GMT or whatever, also taking into account DST.
As I said the events are stored with a Location Id, which relates to an object which represents the Locations that this data comes from:
public class Location
{
public int id { get; set; }
public string name { get; set; }
public Organisation organisation { get; set; }
}
Once set up these locations are permanent, i.e. they don't move to different time zones, but their local time may change with DST.
What field(s) (and of what format) do I need to add to my Location object in order to deduce the local time that my UTC standardised events occured at, and how would I use it to convert the UTC to local time at the time of the event.
e.g. if I have 3 events from Spain (+1), GMT(+0) and PST(-8) that occured at 12pm local time. They basically get stored as 1pm, 12pm and 4am. I need to be able to assert that the average was 9am time of day.
Upvotes: 1
Views: 767
Reputation: 241920
You should add to your Location
record a string value called TimeZone
. You would need to populate it with a time zone identifier, which would be either a Windows time zone ID or an IANA time zone ID. See the timezone tag wiki for an explanation of the differences. You then use that time zone to determine the local time that applies for the corresponding UTC time.
My recommendation is to use an IANA time zones, as they are available across platforms and languages, rather than just being locked down to Windows and .NET. The are the de facto standard for time zones. To use them in .NET, use the Noda Time library:
using NodaTime;
...
DateTimeZone tz = DateTimeZoneProviders.Tzdb[location.TimeZone];
Instant instant = Instant.FromDateTimeUtc(theUtcDateTime);
LocalTime localTime = instant.InZone(tz).TimeOfDay;
The alternative is to use Windows time zones with the TimeZoneInfo
object that comes with .NET:
TimeZoneInfo tz = TimeZoneInfo.FindSystemTimeZoneById(location.TimeZone);
DateTime localDateTime = TimeZoneInfo.ConvertTimeFromUtc(theUtcDateTime, tz);
TimeSpan localTime = localDateTime.TimeOfDay;
Upvotes: 2
Reputation: 149
I think you should be able to just save the dates you're gathering as UTC Time, and then use DateTime.ToLocalTime() to change them to local time when / where you need them to be displayed.
Upvotes: -1