Question

Hello!

I was confused in the problem of time zones. I am writing a web application that will contain some news with dates of publication, and I want the client to see the date of publication of the news in the form of corresponding local time. However, I do not know in which time zone the client is located.

I have three questions.

I have to ask just in case: does DateTimeOffset.UtcNow always returns the correct UTC date and time, regardless of whether the server is dependent on daylight savings time? For example, if the first time I get the value of this property for two minutes before daylight savings time (or before the transition from daylight saving time back) and the second time in 2 minutes after the transfer, whether the value of properties in all cases differ by only 4 minutes? Or here require any further logic? (Question #1)

Please see the following example and tell me what you think.

I posted the news on the site. I assume that DateTimeOffset.UtcNow takes into account the time zone of the server and the daylight savings time, and so I immediately get the correct UTC server time when pressing the button "Submit". I write this value to a MS SQL database in the field of type datetime2(0).

Then the user opens a page with news and no matter how long after publication. This may occur even after many years. I did not ask him to enter his time zone. Instead, I get the offset of his current local time from UTC using the javascript function following way:

function GetUserTimezoneOffset()
{
    var offset = new Date().getTimezoneOffset();
    return offset;
}

Next I make the calculation of the date and time of publication, which will show the user:

public static DateTime Get_Publication_Date_In_User_Local_DateTime(
    DateTime Publication_Utc_Date_Time_From_DataBase,
    int User_Time_Zone_Offset_Returned_by_Javascript)
{
    int userTimezoneOffset = User_Time_Zone_Offset_Returned_by_Javascript; // For
        // example Javascript returns a value equal to -300, which means the
        // current user's time differs from UTC to 300 minutes. Ie offset
        // is UTC +6. In this case, it may be the time zone UTC +5 which
        // currently operates summer time or UTC +6 which currently operates the
        // standard time.
        // Right? (Question #2)

    DateTimeOffset utcPublicationDateTime =
        new DateTimeOffset(Publication_Utc_Date_Time_From_DataBase,
            TimeSpan.Zero); // get an instance of type DateTimeOffset for the
                // date and time of publication for further calculations

    DateTimeOffset publication_DateTime_In_User_Local_DateTime =
       utcPublicationDateTime.ToOffset(new TimeSpan(0, - userTimezoneOffset, 0));

    return publication_DateTime_In_User_Local_DateTime.DateTime;// return to user
}

Is the value obtained correct? Is this the right approach to solving this problem? (Question #3)

UPDATED Oct 19 at 6:58 (I tried post it as a comment but it's too long by 668 characters)

Matt Johnson, Thank You for such a detailed answer despite that of the fact that you are doing this not the first time. Thank you for taking the time to explain this particular case, and not just provide links to other posts.

I have read the information that you have provided. Maybe I'm still not fully aware of all the details, but if I understand it right, for the right convertion of DateTime (which was written many years ago in the database) from UTC to the same user's moment, I need to know UTC offset which he had at that moment. And it is difficult taking into account that transfer rules for DST change constantly. And even now, though the platform ".NET" contains some TZDB that is used for the TimeZoneInfo type, I can't take advantage of it without the exact position of the user.

But what if I am only interested in the date and time of starting this year, and only in Russia, where DST was canceled in 2011? As I understand it, this means that if properly configured clock on user's computer, located in Russia, this approach will always give the correct result. And since 2011, the offset to UTC of user's clock should always be the same. Accordingly, the shift indicators in different browsers will not be different for the Russian user's.

Was it helpful?

Solution

Answer to Question 1

... does DateTimeOffset.UtcNow always returns the correct UTC date and time, regardless of whether the server is dependent on daylight savings time?

Yes. As long is your clock is set correctly, UtcNow always refers to the UTC time. The time zone settings of the server will not affect it. The value in your example will always be 4 minutes, regardless of DST.

Answer to Question 2

var offset = new Date().getTimezoneOffset();

Since new Date() returns the current date and time, this will return you the current offset. You then proceed to apply this current offset to some past value, which may or may not be the correct offset for that specific time. Please read the timezone tag wiki, especially the section titled "Time Zone != Offset".

Answer to Question 3

Is the value obtained correct? Is this the right approach to solving this problem?

No. This is not the correct approach. You have a few options:

First Option

  • Just pass the UTC value to JavaScript without modification.
  • Send it in ISO8601 format, such as 2013-10-18T12:34:56.000Z. You can get this in .Net easily using yourDateTime.ToString("o").
    • Be sure the DateTime you are starting with has .Kind == DateTimeKind.Utc, otherwise it won't get the Z on the end, which is essential.
    • If you are targeting older browsers that can't parse ISO8601, then you will need a library such as moment.js to parse it for you.
  • Alternatively, you could pass the number of milliseconds since 1/1/1970 UTC as a number and load that into a JavaScript Date instead of parsing.
  • Now you can just display the Date object using JavaScript. Let the browser convert it from UTC to the users local time.

Warning, with this approach, some conversions might be incorrect due to the problem I describe here.

Second Option

  • Like the first option, pass the UTC timestamp to JavaScript
  • Use that to get the offset for that timestamp.
  • Pass the offset back to the server in a postback or ajax call.
  • Apply the offset on the server
  • Output the local time zone

I don't particularly like this option because of the round trip. You might as well calculate it in JavaScript like the first option.

Third Option

  • Get the user's time zone. The best way is to ask them for it, usually on a user setting page.
  • Use it to convert from the UTC time to their local time completely on the server.
  • You can use Windows time zones and the TimeZoneInfo class to do the conversions.
  • Or you can use IANA/Olson time zones and the Noda Time library.

This approach is more accurate, but requires more user interaction.

Also, please in future posts, ask just one question at a time. And please search before you post - I've written most of this in one form or another many times before.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top