gmlacrosse
gmlacrosse

Reputation: 402

What is wrong with this DateTime string?

This string is being generated by an application that I'm trying to debug. DateTime.Parse works but DateTime.ParseExact doesn't. Keeps throwing a bad format exception.

// test
string dateTimeFormatted = "2014-11-10T14:49:24-06:00";

try
{
    //yyyy-MM-ddTHH:mm:sszzz 2014-11-10T14:49:24-06:00 
    DateTime myDate = DateTime.ParseExact(dateTimeFormatted, 
               "yyyy-MM-ddTHH:mm:sszzz", System.Globalization.CultureInfo.InvariantCulture, DateTimeStyles.None);
                return myDate;
            }
            catch (Exception)
            {
                try
                {
                    // This works
                    DateTime myDate2 = DateTime.Parse(dateTimeFormatted);

                    return myDate2;
                }
                catch (Exception)
                {

                    throw;
                }
            }

Edit:

This is the final method that I wrote that seems to work flawlessly. Since the method is called shortly after the application generates this timestamp, it will just use Datetime.Now if both DateTime.ParseExact and DateTime.Parse fail.

public DateTime GetDateTimeFromFormattedString(string dateTimeFormatted)
{
    try
    {
        //test data 2014-11-10T14:49:24-06:00 
        DateTime myDate;
        bool bIsParsed = DateTime.TryParseExact(dateTimeFormatted.Trim(), 
          "yyyy'-'MM'-'dd'T'HH':'mm':'sszzz", System.Globalization.CultureInfo.InvariantCulture, DateTimeStyles.None, out myDate);
        if (bIsParsed)
            return myDate;
        else
            bIsParsed = DateTime.TryParse(dateTimeFormatted.Trim(), out myDate);

        if (bIsParsed)
            return myDate;
        else
            return DateTime.Now;
    }
    catch (Exception e)
    {
        Console.WriteLine(e.StackTrace);
        return DateTime.Now;
    }
}

Another edit:

This works too

        DateTimeOffset dto;
        bool bIsParsed = DateTimeOffset.TryParseExact(dateTimeFormatted.Trim(), "yyyy-MM-ddTHH:mm:sszzz",
                            System.Globalization.CultureInfo.InvariantCulture,
                            DateTimeStyles.AdjustToUniversal, out dto);
        if (bIsParsed)
            return dto.DateTime;

Upvotes: 1

Views: 489

Answers (2)

Soner Gönül
Soner Gönül

Reputation: 98750

Your code does not throw FormatException. But I wish it can..

First of all, don't use "zzz" custom format specifier on DateTime parsing. It is not recomended. Since a DateTime does not store any UTC Offset value, there is no point to use it.

From documentation;

With DateTime values, the "zzz" custom format specifier represents the signed offset of the local operating system's time zone from UTC, measured in hours and minutes. It does not reflect the value of an instance's DateTime.Kind property. For this reason, the "zzz" format specifier is not recommended for use with DateTime values.

If your string have offset part, would be better to parse it to DateTimeOffset instead of a DateTime.

Since you use DateTimeStyles.None, this will parse your string as a Local time. That means it adds your current time zone offset value to you result.

For example, I live in Turkey and now time zone is UTC +02:00 in here. That's why if I use DateTimeStyles.None as you did, result's time part will be 22:49:24 not 20:49:24. If I use DateTimeStyles.AdjustToUniversal, it will be 20:49:24.

Here a DateTimeOffset parsing;

string s = "2014-11-10T14:49:24-06:00";
DateTimeOffset dto;
if(DateTimeOffset.TryParseExact(s, "yyyy-MM-ddTHH:mm:sszzz",
                                CultureInfo.InvariantCulture,
                                DateTimeStyles.AdjustToUniversal, out dto))
{
    Console.WriteLine(dto.DateTime) // 10/11/2014 20:49:24
}

Upvotes: 1

LittleSweetSeas
LittleSweetSeas

Reputation: 7054

Try adding quotes around specific characters in your format string:

DateTime myDate = DateTime.ParseExact(dateTimeFormatted, 
               "yyyy'-'MM'-'dd'T'HH':'mm':'sszzz", System.Globalization.CultureInfo.InvariantCulture, DateTimeStyles.None);

Upvotes: 2

Related Questions