Parse DateTime with time zone of form PST/CEST/UTC/etc

C#.NetParsingDatetimeTimezone

C# Problem Overview


I'm trying to parse an international datetime string similar to:

24-okt-08 21:09:06 CEST

So far I've got something like:

CultureInfo culture = CultureInfo.CreateSpecificCulture("nl-BE");
DateTime dt = DateTime.ParseExact("24-okt-08 21:09:06 CEST",
    "dd-MMM-yy HH:mm:ss ...", culture);

The problem is what should I use for the '...' in the format string? Looking at the http://msdn.microsoft.com/en-us/library/8kb3ddd4.aspx">Custom Date and Time Format String MSDN page doesn't seem to list a format string for parsing timezones in PST/CEST/GMT/UTC form.

C# Solutions


Solution 1 - C#

AFAIK the time zone abbreviations are not recognized. However if you replace the abbreviation with the time zone offset, it will be OK. E.g.:

DateTime dt1 = DateTime.ParseExact("24-okt-08 21:09:06 CEST".Replace("CEST", "+2"), "dd-MMM-yy HH:mm:ss z", culture);
DateTime dt2 = DateTime.ParseExact("24-okt-08 21:09:06 CEST".Replace("CEST", "+02"), "dd-MMM-yy HH:mm:ss zz", culture);
DateTime dt3 = DateTime.ParseExact("24-okt-08 21:09:06 CEST".Replace("CEST", "+02:00"), "dd-MMM-yy HH:mm:ss zzz", culture);

Solution 2 - C#

The quick answer is, you can't do it.


Here is why,

There is a definitive database of world timezones, you can get it from the IANA here.

The problem is, the 3 or 4 letter abbreviations have a many-to-one association with the IANA timezones. For instance "AMT" means different things, depending on your culture, what part of the world you are in and the context of your application.

AMT "Armenia Time" Asia          UTC + 4 hours 
AMT "Amazon Time"  South America UTC - 4 hours 

If you really want to tackle this, I suggest using Noda Time to represent your Instances. You'll have to write some code to convert the abbreviations to a standard IANA timezone.

We can't do this for you, it depends on the context of your application.


Another good example is "CST".

CST "China Standard Time"   Asia            UTC + 8 hours 
CST "Central Standard Time" Central America UTC - 6 hours 
CST "Cuba Standard Time"    Caribbean       UTC - 5 hours 
CST "Central Standard Time" North America   UTC - 6 hours 

Solution 3 - C#

Dictionary of abbreviations if you decide to go the search&replace route (I did).

Dictionary<string, string> _timeZones = new Dictionary<string, string>() {
            {"ACDT", "+1030"},
            {"ACST", "+0930"},
            {"ADT", "-0300"},
            {"AEDT", "+1100"},
            {"AEST", "+1000"},
            {"AHDT", "-0900"},
            {"AHST", "-1000"},
            {"AST", "-0400"},
            {"AT", "-0200"},
            {"AWDT", "+0900"},
            {"AWST", "+0800"},
            {"BAT", "+0300"},
            {"BDST", "+0200"},
            {"BET", "-1100"},
            {"BST", "-0300"},
            {"BT", "+0300"},
            {"BZT2", "-0300"},
            {"CADT", "+1030"},
            {"CAST", "+0930"},
            {"CAT", "-1000"},
            {"CCT", "+0800"},
            {"CDT", "-0500"},
            {"CED", "+0200"},
            {"CET", "+0100"},
            {"CEST", "+0200"},
            {"CST", "-0600"},
            {"EAST", "+1000"},
            {"EDT", "-0400"},
            {"EED", "+0300"},
            {"EET", "+0200"},
            {"EEST", "+0300"},
            {"EST", "-0500"},
            {"FST", "+0200"},
            {"FWT", "+0100"},
            {"GMT", "GMT"},
            {"GST", "+1000"},
            {"HDT", "-0900"},
            {"HST", "-1000"},
            {"IDLE", "+1200"},
            {"IDLW", "-1200"},
            {"IST", "+0530"},
            {"IT", "+0330"},
            {"JST", "+0900"},
            {"JT", "+0700"},
            {"MDT", "-0600"},
            {"MED", "+0200"},
            {"MET", "+0100"},
            {"MEST", "+0200"},
            {"MEWT", "+0100"},
            {"MST", "-0700"},
            {"MT", "+0800"},
            {"NDT", "-0230"},
            {"NFT", "-0330"},
            {"NT", "-1100"},
            {"NST", "+0630"},
            {"NZ", "+1100"},
            {"NZST", "+1200"},
            {"NZDT", "+1300"},
            {"NZT", "+1200"},
            {"PDT", "-0700"},
            {"PST", "-0800"},
            {"ROK", "+0900"},
            {"SAD", "+1000"},
            {"SAST", "+0900"},
            {"SAT", "+0900"},
            {"SDT", "+1000"},
            {"SST", "+0200"},
            {"SWT", "+0100"},
            {"USZ3", "+0400"},
            {"USZ4", "+0500"},
            {"USZ5", "+0600"},
            {"USZ6", "+0700"},
            {"UT", "-0000"},
            {"UTC", "-0000"},
            {"UZ10", "+1100"},
            {"WAT", "-0100"},
            {"WET", "-0000"},
            {"WST", "+0800"},
            {"YDT", "-0800"},
            {"YST", "-0900"},
            {"ZP4", "+0400"},
            {"ZP5", "+0500"},
            {"ZP6", "+0600"}
        };

Solution 4 - C#

I have two answers because I'm not exactly sure what you are asking.

  1. I see you are using CultureInfo, so if you just want to format the date and time to be culture specific, I would separate the date/time and timezone, apply culture method on the date/time and append the timezone. If "CEST" is different for different cultures, you will have to change it by listing all the options (maybe in a case statement).

  2. If you want date/time to be converted to another timezone, you can't use CultureInfo,

I suggest reading: http://msdn.microsoft.com/en-us/library/ms973825.aspx

You can also use the .net framework 3.5 class TimeZoneInfo (different from TimeZone) to make your life easier.

http://msdn.microsoft.com/en-us/library/system.timezoneinfo.aspx

Solution 5 - C#

This is how:

  1. Get the string (precondition: format: ddd, dd MMM yyyy HH:mm:ss zzz)
  2. Get the last whitespace
  3. Remove zzz from string, but save value of zzz
  4. Lookup offset for zzz
  5. Add offset to string

> string dateString = reader.ReadContentAsString(); > int timeZonePos = dateString.LastIndexOf(' ') + 1; > string tz = dateString.Substring(timeZonePos); > dateString = dateString.Substring(0, dateString.Length - tz.Length ); > dateString += s_timeZoneOffsets[tz]; >
> // https://msdn.microsoft.com/en-us/library/w2sa9yss(v=vs.110).aspx > //string es = reader.ReadElementString("pubDate"); > this.m_value = System.DateTime.ParseExact(dateString, "ddd, dd MMM yyyy HH:mm zzz", System.Globalization.CultureInfo.InvariantCulture);

with

private static System.Collections.Generic.Dictionary<string, string> s_timeZoneOffsets =
    new System.Collections.Generic.Dictionary<string, string>() {
    {"ACDT", "+10:30"},
    {"ACST", "+09:30"},
    {"ADT", "-03:00"},
    {"AEDT", "+11:00"},
    {"AEST", "+10:00"},
    {"AHDT", "-09:00"},
    {"AHST", "-10:00"},
    {"AST", "-04:00"},
    {"AT", "-02:00"},
    {"AWDT", "+09:00"},
    {"AWST", "+08:00"},
    {"BAT", "+03:00"},
    {"BDST", "+02:00"},
    {"BET", "-11:00"},
    {"BST", "-03:00"},
    {"BT", "+03:00"},
    {"BZT2", "-03:00"},
    {"CADT", "+10:30"},
    {"CAST", "+09:30"},
    {"CAT", "-10:00"},
    {"CCT", "+08:00"},
    {"CDT", "-05:00"},
    {"CED", "+02:00"},
    {"CET", "+01:00"},
    {"CEST", "+02:00"},
    {"CST", "-06:00"},
    {"EAST", "+10:00"},
    {"EDT", "-04:00"},
    {"EED", "+03:00"},
    {"EET", "+02:00"},
    {"EEST", "+03:00"},
    {"EST", "-05:00"},
    {"FST", "+02:00"},
    {"FWT", "+01:00"},
    {"GMT", "+00:00"},
    {"GST", "+10:00"},
    {"HDT", "-09:00"},
    {"HST", "-10:00"},
    {"IDLE", "+12:00"},
    {"IDLW", "-12:00"},
    {"IST", "+05:30"},
    {"IT", "+03:30"},
    {"JST", "+09:00"},
    {"JT", "+07:00"},
    {"MDT", "-06:00"},
    {"MED", "+02:00"},
    {"MET", "+01:00"},
    {"MEST", "+02:00"},
    {"MEWT", "+01:00"},
    {"MST", "-07:00"},
    {"MT", "+08:00"},
    {"NDT", "-02:30"},
    {"NFT", "-03:30"},
    {"NT", "-11:00"},
    {"NST", "+06:30"},
    {"NZ", "+11:00"},
    {"NZST", "+12:00"},
    {"NZDT", "+13:00"},
    {"NZT", "+12:00"},
    {"PDT", "-07:00"},
    {"PST", "-08:00"},
    {"ROK", "+09:00"},
    {"SAD", "+10:00"},
    {"SAST", "+09:00"},
    {"SAT", "+09:00"},
    {"SDT", "+10:00"},
    {"SST", "+02:00"},
    {"SWT", "+01:00"},
    {"USZ3", "+04:00"},
    {"USZ4", "+05:00"},
    {"USZ5", "+06:00"},
    {"USZ6", "+07:00"},
    {"UT", "-00:00"},
    {"UTC", "-00:00"},
    {"UZ10", "+11:00"},
    {"WAT", "-01:00"},
    {"WET", "-00:00"},
    {"WST", "+08:00"},
    {"YDT", "-08:00"},
    {"YST", "-09:00"},
    {"ZP4", "+04:00"},
    {"ZP5", "+05:00"},
    {"ZP6", "+06:00"}
};

Solution 6 - C#

Here's what I had to do.

I receive the datetime from javascript and then pass it on to ASP.NET to store in Oracle database. Here is my C# code for Eastern and Central times.

string datetimevalue = hidfileDateTime.Value; 
            
datetimevalue= datetimevalue.Replace("EDT", "EST"); 
datetimevalue = datetimevalue.Replace("CDT", "CST");
if (datetimevalue.Contains("CST"))
{
    filedt = DateTime.ParseExact(datetimevalue, "ddd MMM d HH:mm:ss CST yyyy", provider).ToUniversalTime().AddHours(1).ToLocalTime();
}
else
{
    filedt = DateTime.ParseExact(datetimevalue, "ddd MMM d HH:mm:ss EST yyyy", provider);
}

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionthelsdjView Question on Stackoverflow
Solution 1 - C#PanosView Answer on Stackoverflow
Solution 2 - C#JodrellView Answer on Stackoverflow
Solution 3 - C#Jussi PaloView Answer on Stackoverflow
Solution 4 - C#makstaksView Answer on Stackoverflow
Solution 5 - C#Stefan SteigerView Answer on Stackoverflow
Solution 6 - C#Deep KumarView Answer on Stackoverflow