Home > Software engineering >  C# Parse DateTime using DateTime.TryParseExact() multiple format
C# Parse DateTime using DateTime.TryParseExact() multiple format

Time:12-15

I have a string text that i want to parse/convert to DateTime,
the text can have a different formats (depending on the user who write it),
it can be "dd/MM/yyyy" or it can be "MM/dd/yyyy".

I am using DateTime.TryParseExact(string, formats[], provider, dateTimeStyles, out result)
as descripted here TryParseExact

Now the problem happens in the following cases
if (for example) string text = "06/01/2023"

The text could have two meanings
1st  --> Day: 06, Month: 01, Year: 2023
2nd --> Day: 01, Month: 06, Year: 2023

My Question is when does the Method TryParseExact() return true
does it return true for the first format that matches text ?
or does it evalute all/each format inside the formats[] array ?

i have tried to search for a similar question, but i didn't seem to find one,
i have tried read this reference TryParseExactMultiple
i have tried this question

Thank you for your help in advance.

My code:

string text = "06/01/2023";

string[] formatsArray = new string[]
{
  "yyyyMMdd",
  "dd/MM/yyyy",
  "dd-MMM-yy",
  "MM/dd/yyyy",
  "MM-dd-yyyy"
};

DateTime result;

DateTime.TryParseExact(text, formatsArray, System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out result)

Output is:
result = Day: 06, Month: 01, Year: 2023

CodePudding user response:

It seems that source code is pretty clear - TryParseExact calls TryParseExactMultiple which cycles formats in provided order and returns first one that succeeds:

internal static bool TryParseExactMultiple(ReadOnlySpan<char> s, string?[]? formats,
    DateTimeFormatInfo dtfi, DateTimeStyles style, scoped ref DateTimeResult result)
{
    // ...

    // Do a loop through the provided formats and see if we can parse successfully in
    // one of the formats.
    for (int i = 0; i < formats.Length; i  )
    {
        string? format = formats[i];
        // ...
        if (TryParseExact(s, format, dtfi, style, ref innerResult))
        {
            result.parsedDate = innerResult.parsedDate;
            result.timeZoneOffset = innerResult.timeZoneOffset;
            return true;
        }
    }

    result.SetBadDateTimeFailure();
    return false;
}

Since documentation does not specify behaviour for I would not recommend to rely on it, if it is possible, or possibly wrap this into helper method which will be tested for your particular requirements.

In general - when accepting data from somewhere you need to agree on data format, if the source of the data is not under your control - contact the vendor to clarify it otherwise sooner or later the situation like this are bound to happen (in theory not only related to dates).

CodePudding user response:

The TryParseExact method will return true if any of the formats in the formats array match the input string. It will not evaluate all the formats in the array, but will instead return true as soon as it finds a matching format.

In your example, the input string "06/01/2023" matches the format "dd/MM/yyyy", so the method will return true and the resulting DateTime object will have a value of Day: 06, Month: 01, Year: 2023.

If you want to make sure that the input string matches only one of the formats in the array, you can check the resulting DateTime object's Kind property. If the Kind property is Unspecified, it means that the input string matched multiple formats and the resulting DateTime object is not a specific date and time value. In that case, you can decide how to handle the ambiguity. For example, you can try parsing the input string again using a different set of formats, or you can prompt the user for more information.

Here is how you can use the Kind attribute:

if (DateTime.TryParseExact(text, formatsArray, System.Globalization.CultureInfo.InvariantCulture, System.Globalization.DateTimeStyles.None, out result))
{
    if (result.Kind == DateTimeKind.Unspecified)
    {
        // Handle ambiguous input here
        Console.WriteLine("The input string could not be parsed to a specific date and time value.");
    }
    else
    {
        Console.WriteLine(result);
    }
}
else
{
    Console.WriteLine("The input string could not be parsed to a date and time value using any of the specified formats.");
}

CodePudding user response:

According to the documentation, TryParseExact does not provide an indication for which format was used. My general recommendation is to allow users to send only one date format.

  • Related