Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

DateTime.TryParseExact with "ddd" format fails for all days except current

Tags:

date

c#

datetime

I encountered a strange issue. It's Wednesday now, and:

DateTime date;
DateTime.TryParseExact(
   "Wed", "ddd", null, System.Globalization.DateTimeStyles.None, out date); // true

DateTime.TryParseExact(
   "Mon", "ddd", null, System.Globalization.DateTimeStyles.None, out date); // false

When I change local date on computer to Monday output swaps to 'false-true'.

Why does the parser depend on current date?

like image 798
Artur Udod Avatar asked Dec 06 '25 05:12

Artur Udod


2 Answers

I suspect the problem is that you've got a very incomplete date format there. Usually, DateTime.TryParseExact will use the current time and date for any fields that aren't specified. Here, you're specifying the day of the week, which isn't really enough information to get to a real date... so I suspect that the text value is only being used to validate that it's a reasonable date, after defaulting the DateTime to "now". (In the cases where it does manage to parse based on just the day name, you end up with today's date.)

I've just done another test where we specify the day-of-month value as well, and that ends up with interesting results - it appears to use the first month of the current year:

using System;
using System.Globalization;

class Test
{    
    public static void Main (string[] args)
    {
        // Note: All tests designed for 2015.
        // January 1st 2015 was a Thursday.
        TryParse("01 Wed"); // False
        TryParse("01 Thu"); // True - 2015-01-01
        TryParse("02 Thu"); // False
        TryParse("02 Fri"); // True - 2015-01-02
    }

    private static void TryParse(string text)
    {
        DateTime date;
        bool result = DateTime.TryParseExact(
            text, "dd ddd", CultureInfo.InvariantCulture, 0, out date);
        Console.WriteLine("{0}: {1} {2:yyyy-MM-dd}", text, result, date);
    }
}

Changing the system date to 2016 gave results consistent with finding dates in January 2016.

Fundamentally, trying to parse such incomplete as this is inherently odd. Think carefully about what you're really trying to achieve.

like image 79
Jon Skeet Avatar answered Dec 07 '25 18:12

Jon Skeet


Why not use regex if you are wanting validating part of a date?

https://dotnetfiddle.net/ieokVz

using System;
using System.Text.RegularExpressions;

public class Program
{
public static void Main()
{

    string pattern = "(Mon|Tue|Wed|Thu|Fri|Sat|Sun)";

    string[] values = {"Mon","Tue","Wed","Thu","Fri","Sat","Sun","Bun","Boo","Moo"};

    Console.WriteLine("");


    foreach(var val in values){

        Console.WriteLine("{0} ? {1}",val,Regex.IsMatch(val,pattern));

    }
    }
}

As per @Jon's comments https://dotnetfiddle.net/I4R2ZT

    using System;
using System.Collections.Generic;

public class Program
{
    public static void Main()
    {

        var matches = new HashSet<String>(System.Threading.Thread.CurrentThread.CurrentCulture.DateTimeFormat.AbbreviatedDayNames,StringComparer.OrdinalIgnoreCase);

        string[] values = {"Mon","Tue","Wed","Thu","Fri","Sat","Sun","Bun","Boo","Moo","Foo","Bar"};


        foreach(var val in values){

            Console.WriteLine("{0} ? {1}", val, matches.Contains(val));

        }
    }
}
like image 35
Mark Avatar answered Dec 07 '25 18:12

Mark



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!