DateTime.TryParse century control C#

2020-01-25 10:38发布

The result of the following snippet is "12/06/1930 12:00:00". How do I control the implied century so that "12 Jun 30" becomes 2030 instead?

    string dateString = "12 Jun 30"; //from user input
    DateTime result;
    DateTime.TryParse(dateString, new System.Globalization.CultureInfo("en-GB"),System.Globalization.DateTimeStyles.None,out result);
    Console.WriteLine(result.ToString());

Please set aside, for the moment, the fact that a correct solution is to specify the date correctly in the first place.

Note: The result is independant of the system datetime for the pc running the code.

Answer: Thanks Deeksy

    for (int i = 0; i <= 9; i++)
    {
        string dateString = "12 Jun " + ((int)i * 10).ToString();
        Console.WriteLine("Parsing " + dateString);
        DateTime result;
        System.Globalization.CultureInfo cultureInfo = new System.Globalization.CultureInfo("en-GB");
        cultureInfo.Calendar.TwoDigitYearMax = 2099;
        DateTime.TryParse(dateString, cultureInfo , System.Globalization.DateTimeStyles.None, out result);
        Console.WriteLine(result.ToString());
    }

5条回答
在下西门庆
2楼-- · 2020-01-25 11:20
result = year.ToString().Length == 1 
      || year.ToString().Length == 2 ? "1" 
       : (Convert.ToInt32(year.ToString()
          .Substring(0, (year.ToString().Length - 2))) + 1).ToString();
查看更多
倾城 Initia
3楼-- · 2020-01-25 11:26

It's tricky, because the way two digit years work with TryParse is based on the TwoDigitYearMax property of the Calendar property of the CultureInfo object that you are using. (CultureInfo->Calendar->TwoDigitYearMax)

In order to make two digit years have 20 prepended, you'll need to manually create a CultureInfo object which has a Calendar object with 2099 set as the TwoDigitYearMax property. Unfortunately, this means that any two digit date parsed will have 20 prepended (including 98, 99 etc.) which is probably not what you want.

I suspect that your best option is to use a 3rd party date parsing library instead of the standard tryparse that will use the +50/-50 year rule for 2 digit years. (that a 2 digit year should be translated into a range between 50 years before this year and 50 years greater than this year).

Alternatively, you could override the ToFourDigitYear method on the calendar object (it's virtual) and use that to implement the -50/+50 rule.

查看更多
劫难
4楼-- · 2020-01-25 11:31

I'd write a re-usable function:

public static object ConvertCustomDate(string input)
{
    //Create a new culture based on our current one but override the two
    //digit year max.
    CultureInfo ci = new CultureInfo(CultureInfo.CurrentCulture.LCID);
    ci.Calendar.TwoDigitYearMax = 2099;
    //Parse the date using our custom culture.
    DateTime dt = DateTime.ParseExact(input, "MMM-yy", ci);
    return new { Month=dt.ToString("MMMM"), Year=dt.ToString("yyyy") };
}

Here's my list of quasi-date strings

List<string> dates = new List<string>(new []{
    "May-10",
    "Jun-30",
    "Jul-10",
    "Apr-08",
    "Mar-07"
});

Scan over it like so:

foreach(object obj in dates.Select(d => ConvertCustomDate(d)))
{
    Console.WriteLine(obj);
}

Notice that it handles 30 as 2030 now instead of 1930...

查看更多
老娘就宠你
5楼-- · 2020-01-25 11:39

I had a similar problem and I solved it with a Regex. In your case it would look like that:

private static readonly Regex DateRegex = new Regex(
@"^[0-9][0-9] (Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec) [0-9][0-9]$",
RegexOptions.Compiled | RegexOptions.ExplicitCapture);

private static string Beautify(string date)
{
    var match = DateRegex.Match(date);
    if (match.Success)
    {
        // Maybe further checks for correct day
        return date.Insert("dd-MMM-".Length, "20");
    }

    return date;
}
查看更多
干净又极端
6楼-- · 2020-01-25 11:44

You're looking for the Calendar.TwoDigitYearMax Property.

Jon Skeet has posted something on this you will likely find useful.

查看更多
登录 后发表回答