C# DateTime.ParseExact适用于非常规年份

C# DateTime.ParseExact适用于非常规年份,c#,date,C#,Date,我尝试使用单个格式字符串读取以下格式的日期: "1000.12.31" "999.12.31" "99.12.31" 这些日期对应于公元1000年、公元999年和公元99年 我尝试了以下格式字符串: yyyy.M.d。这在999年和99年都失败了 yy.M.d。这在1000和999时失败。它还将99解释为1999年 我打算手动解析它(这很简单),但我很好奇这样的事情是否可以用DateTime.ParseExact,或者用另一个内置方法来实现?我认为最简单的方法是取现有的字符串,在年份前加几个零

我尝试使用单个格式字符串读取以下格式的日期:

"1000.12.31"
"999.12.31"
"99.12.31"
这些日期对应于公元1000年、公元999年和公元99年

我尝试了以下格式字符串:

yyyy.M.d
。这在999年和99年都失败了

yy.M.d
。这在1000和999时失败。它还将99解释为1999年


我打算手动解析它(这很简单),但我很好奇这样的事情是否可以用
DateTime.ParseExact
,或者用另一个内置方法来实现?

我认为最简单的方法是取现有的字符串,在年份前加几个零,并使用现有的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
无论您如何实现它,我都会使用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

这对于手动解析来说是微不足道的;我认为尝试将其调整为使用
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]);

由于当前区域性的
DateTimeFormatInfo
值,它将99解释为1999。如果要更改解析行为,则必须更改
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);

DateTimeFormatInfo
的新实例共享相同的
Calendar
对象;如果你想自定义特定的实例,你必须
克隆它。

然后它在
“1.1.1”
:*(这是假设月和日总是用两位数表示。@Matthew:也忽略了一位数的年;pSorry,月和日并不总是两位数,这就是
M.d
-部分所说的;)完全正确,我忘记了个位数的月份和天数。参见编辑。“99.12.31”对人类来说也是模棱两可的。没有人会说“啊,那当然是马库斯·乌尔皮乌斯·内尔瓦·特拉亚努斯·奥古斯都统治的99年”。每年1999年。使用机器也不会变得更好。@leppie:no,结果与
yy.M.d
iirc相同@汉斯对我来说,在这种情况下,这并不含糊。我知道我一直希望99是99,而不是1999,我只是不能具体说明。就像天和月一样,它们可能是不明确的(1/2,是2月1日还是1月2日?),但如果您知道会发生什么,您可以在格式字符串中指定它。