Convert a date string to a DateTime object in C# I was just wondering if my code contains defects or if there was a more efficient or general way to convert string to DateTime object. In the input, I have a string in the UTC format.

public static DateTime ParseDateTime(string dateString)
    {
        DateTime dateTime;
        if (!DateTime.TryParse(dateString, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out dateTime))
        {
            if (!DateTime.TryParse(dateString, CultureInfo.CurrentCulture, DateTimeStyles.AssumeUniversal, out dateTime))
            {
                try
                {
                    dateTime = DateTime.Parse(dateString, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal);
                }
                catch (FormatException)
                {
                    // Try to extract at least year from the string (the longest digits substring)
                    var yearMatch = Regex.Matches(dateString, @"\d{4}").Cast&lt;Match&gt;().FirstOrDefault();
                    if (yearMatch == null || string.IsNullOrWhiteSpace(yearMatch.Value))
                    {
                        throw;
                    }

                    // Only year really matters for Max and Min values of DateTime
                    var year = int.Parse(yearMatch.Value, CultureInfo.InvariantCulture);

                    // Try to determine what do we have (Min or Max value)
                    if (year == DateTime.MaxValue.Year)
                    {
                        dateTime = DateTime.MaxValue;
                    }
                    else
                    {
                        if (year == DateTime.MinValue.Year)
                        {
                            dateTime = DateTime.MinValue;
                        }
                        else
                        {
                            throw;
                        }
                    }
                }
            }
        }

        dateTime = dateTime.ToUniversalTime();
        return dateTime;
    }
Nesting if-blocks like you do is a way that leads to "arrow code", code that has deeply indented structures/blocks.

In your case, I will assume that you can't use the more simple 1-try TryParse(dateString, datetime) option, and that you have to try the invariant and local cultures in that order.

So, consider this code:

    DateTime dateTime;

    if (DateTime.TryParse(dateString, CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal, out dateTime))
    {
        return dateTime.ToUniversalTime();
    }

    if (DateTime.TryParse(dateString, CultureInfo.CurrentCulture, DateTimeStyles.AssumeUniversal, out dateTime))
    {
        return dateTime.ToUniversalTime();
    }

    if (DateTime.TryParse(dateString, CultureInfo.InvariantCulture, DateTimeStyles.AssumeLocal, out dateTime))
    {
        return dateTime.ToUniversalTime();
    }


Now the logic progression between your format attempts is clear. It also makes it easier to add a new attempt in there just by adding 4 lines.

If your attempts are not successful, though, your code pulls out a year. This code is broken because it does not actually return a datetime for valid years...

If the year is between min and max dates, it does not set the datetime at all...