如果在新年后添加月份,字符串上的 TryParse/ParseExact 无法转换为格式 ("dddd dd MMMM")

TryParse/ParseExact on string fails to convert to format ("dddd dd MMMM") if adding months after the new year

我的目标是将格式为“dddd dd MMMM”的字符串参数转换为 DateTime 对象。字符串参数本身是从今天、未来几个月的相对日期中获取的,例如 DateTime.Now.AddMonths(5).ToString("dddd dd MMMM");。当使用 TryParse/ParseExact 方法将参数字符串转换回新年之后的日期时间(在本例中为 2019 年 1 月 1 日之后)时,出现以下错误:

System.FormatException: String was not recognized as a valid DateTime because the day of week was incorrect.*

当我尝试在新年前传递所需格式的参数时,它被接受为有效。可能与所需的闰年计算有关,还是有其他原因?

谢谢,

这与年份是闰年无关...今年的日期成功但明年的日期失败的原因是您的格式不包括年份,所以 .Net正在假设年份是 this 年,并且明年的某天、月-日和月份将不会解析。

例如:

"Saturday 16 March" -> 解析没有错误,因为这在 2019 年有效。

"Monday 16 March" -> 所描述的错误。这是 2020 年的日、月-日和月份的有效组合,但对今年 2019 年无效。

是正确的,因为星期几不匹配。这是正确答案。

但是 - 为了后代,我还要指出此类代码中仍然存在闰年错误。考虑以下因素:

DateTime dt = new DateTime(2020, 2, 29); // a leap day
string format = "MM/dd"; //any format with month and day but without year
string s = dt.ToString(format, CultureInfo.InvariantCulture);
DateTime result = DateTime.ParseExact(s, format, CultureInfo.InvariantCulture);

此代码似乎应该始终有效,因为在创建字符串和解析字符串时格式都是相同的。但是,由于年份不是格式的一部分,因此它仅在 运行 为闰年时才有效。在平年执行时,将抛出 FormatException 消息:

The DateTime represented by the string is not supported in calendar System.Globalization.GregorianCalendar

这是因为 DateTime 对象 必须 有一年,所以如果没有提供那么它使用 current 年。当我今天在 2019 年 运行 时,它试图创建不存在的日期 2019-02-29

顺便说一下,解析 XML 时也会发生同样的事情。 XSD 数据类型 gMonthDay 提供没有年份的月份和日期,通过在年份位置放置一个额外的连字符,例如 "--12-31" 可以使用 XmlConvert.ToDateTime 转换.它通常适用于一年中的所有日期,但 XmlConvert.ToDateTime("--02-29") 仅在当前年份是闰年时才有效 - 即使 XSD 规范明确允许它。