Bubblewrap
Bubblewrap

Reputation: 7516

DateTime.ParseExact for non-conventional years

I'm trying to read dates in the following format using a single format string:

"1000.12.31"
"999.12.31"
"99.12.31"

These would correspond to dates in the years 1000 AD, 999 AD and 99 AD.

I've tried the following format strings:

yyyy.M.d. This fails for the years 999 and 99.

yy.M.d. This fails for 1000 and 999. It also interprets 99 as 1999.

I'm about to resort to parsing it manually (it's simple enough for that), but i'm curious if something like this is even possible with DateTime.ParseExact, or perhaps with another built-in method?

Upvotes: 2

Views: 441

Answers (3)

Dour High Arch
Dour High Arch

Reputation: 21712

It interprets 99 as 1999 because of the current culture's DateTimeFormatInfo values. If you want to change the parsing behavior you must change the DateTimeFormatInfo:

string eg = "9.1.2";
DateTime dt;

var fi = new System.Globalization.DateTimeFormatInfo();
fi.Calendar = (System.Globalization.Calendar)fi.Calendar.Clone();
fi.Calendar.TwoDigitYearMax = 99;
fi.ShortDatePattern = "y.M.d";
bool b = DateTime.TryParse(eg, fi, System.Globalization.DateTimeStyles.None, out dt);

New instances of DateTimeFormatInfo share the same Calendar object; you have to Clone it if you want to customize specific instances.

Upvotes: 2

Douglas
Douglas

Reputation: 54887

This is trivial to parse manually; I don’t think it’s worth the effort trying to adapt it to work with DateTime.ParseExact.

string str = "99.12.31";
int[] parts = str.Split('.').Select(int.Parse).ToArray();
DateTime date = new DateTime(parts[0], parts[1], parts[2]);

Upvotes: 2

David Yaw
David Yaw

Reputation: 27864

I think the easiest way would be to take the existing string, stick a few zeros in front of the year, and use your existing DateTime.ParseExact.

However you implement it, I'd go with doing a little manual string massaging, and doing the heavy lifting with DateTime.ParseExact.

static DateTime ParseExactYear(string input)
{
    switch (input.IndexOf('.'))
    {
        case 1: input = "000" + input; break;
        case 2: input = "00" + input; break;
        case 3: input = "0" + input; break;
    }

    return DateTime.ParseExact(input, "yyyy.M.d", null);
}

Debug.WriteLine(ParseExactYear("1000.12.31"));
Debug.WriteLine(ParseExactYear("999.12.31"));
Debug.WriteLine(ParseExactYear("99.12.31"));
Debug.WriteLine(ParseExactYear("9.12.31"));

Debug.WriteLine(ParseExactYear("1000.1.1"));
Debug.WriteLine(ParseExactYear("999.1.1"));
Debug.WriteLine(ParseExactYear("99.1.1"));
Debug.WriteLine(ParseExactYear("9.1.1"));

Output:
12/31/1000 12:00:00 AM
12/31/0999 12:00:00 AM
12/31/0099 12:00:00 AM
12/31/0009 12:00:00 AM
1/1/1000 12:00:00 AM
1/1/0999 12:00:00 AM
1/1/0099 12:00:00 AM
1/1/0009 12:00:00 AM

Upvotes: 2

Related Questions