Search code examples
c#datetimetimezoneutclocaltime

Working with DateTime Time Zones


I am writing some code where I have a DateTime in UTC and I need to display this as a LocalTime where I have a Culture object for two timezones.

Here is my code:

public void CultureDateTimeLocalTime()
{
    DateTime dateTimeUtcNow = DateTime.UtcNow;
    DateTime convertedDate = DateTime.SpecifyKind(dateTimeUtcNow, DateTimeKind.Utc);
    DateTime dateTimeLocalTime = convertedDate.ToLocalTime();

    String format = "MM/dd/yyyy hh:mm:sszzz";

    string localTime = dateTimeLocalTime.ToString(format);

    CultureInfo cultureNZ = new CultureInfo("en-NZ");
    CultureInfo cultureUS = new CultureInfo("en-US");

    DateTime DateTimeNZ;
    bool parseNZ = DateTime.TryParse(localTime, cultureNZ, DateTimeStyles.None, out DateTimeNZ);
    string outputNZ = DateTimeNZ.ToString("F");

    DateTime DateTimeUS;
    bool parseUS = DateTime.TryParse(localTime, cultureUS, DateTimeStyles.None, out DateTimeUS);
    string outputUS = DateTimeUS.ToString("F");
}

public void CultureDateTimeLocalTime2()
{
    DateTime dateTimeUtcNow = DateTime.UtcNow;
    DateTime convertedDate = DateTime.SpecifyKind(dateTimeUtcNow, DateTimeKind.Utc);
    DateTime dateTimeLocalTime = convertedDate.ToLocalTime();

    String format = "MM/dd/yyyy hh:mm:sszzz";

    string localTime = dateTimeLocalTime.ToString(format);

    CultureInfo cultureNZ = new CultureInfo("en-NZ");
    CultureInfo cultureUS = new CultureInfo("en-US");

    DateTime DateTimeNZ = DateTime.ParseExact(localTime, format, cultureNZ.DateTimeFormat);
    string outputNZ = DateTimeNZ.ToString("F");

    DateTime DateTimeUS = DateTime.ParseExact(localTime, format, cultureUS.DateTimeFormat);
    string outputUS = DateTimeUS.ToString("F");
}

In both functions, the outputNZ and outputUS are the same. Why is this?

Thanks in advance.


Solution

  • CultureInfo contains rules for formatting date, times and numbers for a specific culture. There are no rules about the time zone of that culture because for most cultures and time zones there are no one-to-one correspondance so you cannot use a CultureInfo to magically take time zones into account when a date is formatted as a string.

    What you need is a New Zealand TimeZoneInfo:

    var nzTimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById("New Zealand Standard Time");
    var utcNow = DateTime.UtcNow;
    var nzNow = TimeZoneInfo.ConvertTimeFromUtc(utcNow, nzTimeZoneInfo);
    var outputNz = nzNow.ToString("F", CultureInfo.GetCultureInfo("en-NZ"));
    

    You can use the same logic to convert to a US time zone but here it becomes obvious that you cannot infer a time zone from a CultureInfo because the US has many time zones and you have to decide which to use.

    Also, when working with date and times you should only convert to string format in the last step. Your code happens to work because you carefully control the format you are using to round-trip to a string but this round-trip is unecessary and I have fixed many bugs where this round-trip code had an implicit assumption about the regional settings of the computer that was not always true when the code executed in another environment.