Convert UTC DateTime to another Time Zone

68,014

Solution 1

Have a look at the DateTimeOffset structure:

// user-specified time zone
TimeZoneInfo southPole =
    TimeZoneInfo.FindSystemTimeZoneById("Antarctica/South Pole Standard Time");

// an UTC DateTime
DateTime utcTime = new DateTime(2007, 07, 12, 06, 32, 00, DateTimeKind.Utc);

// DateTime with offset
DateTimeOffset dateAndOffset =
    new DateTimeOffset(utcTime, southPole.GetUtcOffset(utcTime));

Console.WriteLine(dateAndOffset);

For DST see the TimeZoneInfo.IsDaylightSavingTime method.

bool isDst = southpole.IsDaylightSavingTime(DateTime.UtcNow);

Solution 2

The best way to do this is simply to use TimeZoneInfo.ConvertTimeFromUtc.

// you said you had these already
DateTime utc = new DateTime(2014, 6, 4, 12, 34, 0);
TimeZoneInfo tzi = TimeZoneInfo.FindSystemTimeZoneById("Pacific Standard Time");

// it's a simple one-liner
DateTime pacific = TimeZoneInfo.ConvertTimeFromUtc(utc, tzi);

The only catch is that the incoming DateTime value may not have the DateTimeKind.Local kind. It must either be Utc, or Unspecified.

Solution 3

You can use a dedicated function within TimeZoneInfo if you want to convert a DateTimeOffset into another DateTimeOffset:

DateTimeOffset newTime = TimeZoneInfo.ConvertTime(
    DateTimeOffset.UtcNow, 
    TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time")
);

Solution 4

The Antartica answer only works for the timezones matching UTC. I'm quite traumatized with this DateTimeOffset function and after hours of trial and error, I've managed to produce a practical conversion extension function that works with all timezones.

static public class DateTimeFunctions
{
    static public DateTimeOffset ConvertUtcTimeToTimeZone(this DateTime dateTime, string toTimeZoneDesc)
    {
        if (dateTime.Kind != DateTimeKind.Utc) throw new Exception("dateTime needs to have Kind property set to Utc");
        var toUtcOffset = TimeZoneInfo.FindSystemTimeZoneById(toTimeZoneDesc).GetUtcOffset(dateTime);
        var convertedTime = DateTime.SpecifyKind(dateTime.Add(toUtcOffset), DateTimeKind.Unspecified);
        return new DateTimeOffset(convertedTime, toUtcOffset);
    }
}

Example:

var currentTimeInPacificTime = DateTime.UtcNow.ConvertUtcTimeToTimeZone("Pacific Standard Time");

Solution 5

Here's another gotcha: If you're running your code on a Linux server, you need to use the Linux system for timezone names. For example, "Central Standard Time" would be "America/Chicago". The tz list is here: https://en.wikipedia.org/wiki/List_of_tz_database_time_zones

Here's an example with the isWindows switch:

public static class DateTimeHelper
{
    public static string ConvertUtcToCst(this string dateTimeString)
    {
        if (string.IsNullOrWhiteSpace(dateTimeString))
        {
            return string.Empty;
        }

        if (DateTime.TryParse(dateTimeString, out DateTime outputDateTime))
        {
            try
            {
                var isWindows = RuntimeInformation.IsOSPlatform(OSPlatform.Windows);
                TimeZoneInfo cstZone = null;
                if (isWindows)
                {
                    cstZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
                }
                else
                {
                    cstZone = TimeZoneInfo.FindSystemTimeZoneById("America/Chicago");
                }

                var cstDateTime = TimeZoneInfo.ConvertTimeFromUtc(outputDateTime, cstZone);
                return cstDateTime.ToString();
            }
            catch (TimeZoneNotFoundException)
            {
                return "The registry does not define the Central Standard Time zone.";
            }
            catch (InvalidTimeZoneException)
            {
                return "Registry data on the Central Standard Time zone has been corrupted.";
            }
            catch (Exception ex)
            {
                return $"Error :: {ex.Message} :: {ex.ToString()}";
            }
        }

        return string.Empty;
    }
}
Share:
68,014
Mark Richman
Author by

Mark Richman

https://markrichman.com Mark offers a unique combination of deep technical and business expertise, and a strong track record of success. Mark has built, grown, and driven software engineering teams for organizations of all sizes. Mark has developed courses on a wide range of AWS topics for Linux Academy and Pluralsight. Mark is the coauthor of the 2001 book Professional XML Web Services. He’s a former contributor to XML Journal and Web Services Journal. Mark has been routinely quoted and mentioned in publications like the Palm Beach Post and more. Mark frequently mentors executive leadership in cloud technology concepts and techniques. He is an avid writer and speaker, delivering engaging seminars and webinars on a range of topics. Mark has held key roles in the IT industry, spanning development, project management, product management, and marketing. Mark holds a BS in Computer Science and an MBA with a specialization in Technology Management. Organizations that work with Mark can expect dramatic results such as: Successful migrations of on-premises applications into AWS Significant reduction in existing AWS costs Further cost reduction, faster execution, and risk reduction using infrastructure-as-code Improved cloud security posture with automated incident response procedures Fault-tolerant and highly available infrastructure that scales to meet demand Elimination of undifferentiated heavy lifting, such as application and cloud operations Ability continuously adapt your applications to reduce costs, increase uptimes, respond to business events, and exploit the pace of innovation in AWS. Areas of Expertise Include: Application Architecture Performance Optimization Migrations Security, Governance & Compliance Cloud Operations Cost Savings

Updated on July 09, 2022

Comments

  • Mark Richman
    Mark Richman almost 2 years

    I have a UTC DateTime value coming from a database record. I also have a user-specified time zone (an instance of TimeZoneInfo). How do I convert that UTC DateTime to the user's local time zone? Also, how do I determine if the user-specified time zone is currently observing DST? I'm using .NET 3.5.

    Thanks, Mark

  • Mark Richman
    Mark Richman about 14 years
    I have to go one extra step to get my local time: var offset = tzi.GetUtcOffset(utcTime); var siteLocalTime = utcTime.Add(offset); return siteLocalTime.ToString("MM/dd/yyyy HH:mm");
  • The Muffin Man
    The Muffin Man about 10 years
    This code doesn't compile. That time zone Id doesn't exist and if you replace it with a valid one then you get an error about The UTC Offset for Utc DateTime instances must be 0.
  • Chris Marisic
    Chris Marisic over 9 years
    static public? HERESY, BURN THE WITCH
  • Saneesh kunjunni
    Saneesh kunjunni over 6 years
    to avoid error in dateAndOffset choose DateTime cstTime = utcTime.AddTicks(southPole.BaseUtcOffset.Ticks);
  • MarkPflug
    MarkPflug over 2 years
    Ugh, if they had only made the Convert function a member of the tzi instance instead of a static I wouldn't have to come to stackoverflow to figure this out.