Suppose my app is something like StackOverflow.
That is how I'm doing ...
I have a few questions about it ...
About my server (single server) ... should it be running with a "neutral" UTC (+00:00)? And what if, in the future, we move to a farm where servers run on different locations?
Currently, I'm storing just date as
DateTimeOffset. I'm reading about saving the
TimeZoneID but I'm seeing no use at all for this. Am I missing something?
Or should I store date as
DateTimeUtc with a
TimeZoneID and manually convert every date with the
Is it safe to convert data on the client? Or date conversions should be always on the server side?
Using my current approach. Will DST be respected?
One very important thing to understand about date/time is that there is no one right way for doing everything. The common answer "use UTC" is not always applicable. Context is very important, and there are different techniques and approaches based on what the values you are working with are representing. If you could elaborate on what they are used for in your application, I will update my answer accordingly. In the meantime, I'll try to address the specific points you have brought up already:
Keeping your server at UTC is a best practice, and it is what you can expect from cloud providers like Azure or AWS also. But it isn't something that you should be dependent on. Your server should be able to be set to any time zone without it affecting your application. As long as the clock is in sync with an NTP server, choice of time zone should not matter.
So how do you ensure that? Simple, just make sure your application avoids all of the following:
TimeZone(the entire class)
DateTime.ToUniversalTime()(because it assumes the input is local)
TimeZoneInfo.ConvertTimeToUtc(DateTime)(this particular overload doesn't take a time zone, so it assumes the local time zone)
See also my blog post: The Case Against DateTime.Now.
Note that I didn't include
DateTimeOffset.Now in the list. Although it's a little bit of a design smell, it is still "safe" to use.
I suggest you read my answer to DateTime vs DateTimeOffset. It should clarify some things. Without regurgitating the whole thing, the main point is that while both represent a point in time accurately, a
DateTimeOffset provides perspective, while a UTC
DateTime does not.
You also asked when you should store a
TimeZoneInfo.Id. There are at least two scenarios where this is required:
If you are recording events in the past or present, and you plan on allowing modifications to the recorded timestamps. You need the time zone to determine what the new offset should be, or how the new input converts back to UTC.
If you are scheduling time out into the future, you will need the time zone as part of the recurrence pattern (even for a single occurrence). See here and here also, (while for other languages, the same principles apply).
Again, the exact answer depends on what exactly the timestamps represent. There is no one ring to rule them all.
Date, so they still have issues. (Side note - I'm working on a JS library that will counter this, but it is not ready to share yet).
Conversions on the server side are a much better choice, as long as you can ask the user for their time zone. Most of the time, I think this is doable.
You might consider asking using a map-based timezone picker, such as this one or this one. Both of which will require you use IANA time zones, which for .NET means using Noda Time, which is a great idea anyway (IMHO).
With your current approach, DST will be respected within the definition of the current DST rules for the time zone the user has set for their local browser. (Again, refer to my blog post for why this is the case).
A conversion from any value with an offset (whether
Z) that passes through the
Date object (which I believe an Angular filter will do), will properly convert to the specific unix timestamp.
The errors that would crop up with DST conversions for prior DST rules are because going from the unix timestamp inside the
Date object to the local time zone will always assume that the current DST rule is applicable, even if the time fell into a period that had a different rule.
This actually depends on the actual application you're writing, but the most simple/robust approach IMO is to store/compute all your dates using UTC, and convert it back to the local time zone when you display it to the user.