我正在尝试以d/M
的格式解析生日,而未指定任何年份。
大多数情况下,使用DateTime.TryParseExact(birthday, "d/M", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime birthdayDate)
起作用,除非生日在birthday年日(又名29/2
),并且解析永远不会成功,因为它默认为当前年份。自it defaults to year = 1(这不是年)以来,使用DatTimeStyles.NoCurrentDateDefault
都不起作用。
我该如何进行解析,以使其不涉及破解(我不想手动解析或手动添加任意年份以将其解析为完整日期,它们都很难看并且可能很脆弱),并且还在所有可能的日期(包括leap日)上工作? Existing questions完全没有帮助,因为没有人会费心检查他们是否在leap日工作。我尝试了所有这些,但没有一个起作用。
答案 0 :(得分:2)
这个问题缺少适当的细节,但是
如果您只想解析包含strong年日期的出生日期和月份,则只需在日期末尾添加a年。
我不确定您打算在这里做什么,但是您可以尝试一下
birthday = $"{birthday}/2016"; // leap year
DateTime.TryParseExact(birthday, "d/M/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime birthdayDate);
更新
我的问题是如何不让TryParseExact假定年份 通过以某种方式手动覆盖它来自动
这里是技术性的,如果您仅解析a年的月份和日期,则不必在字符串中指定the年
TryParseExact
方法确实有很多检查和平衡方法,但是这里是重要的部分。
简而言之,它使用当前年份或年份1,无法告诉它专门选择a年
private static bool CheckDefaultDateTime(ref DateTimeResult result, ref Calendar cal, DateTimeStyles styles)
{
if ((result.flags & ParseFlags.CaptureOffset) != (ParseFlags) 0 && (result.Month != -1 || result.Day != -1) && ((result.Year == -1 || (result.flags & ParseFlags.YearDefault) != (ParseFlags) 0) && (result.flags & ParseFlags.TimeZoneUsed) != (ParseFlags) 0))
{
result.SetFailure(ParseFailureKind.Format, "Format_MissingIncompleteDate", (object) null);
return false;
}
if (result.Year == -1 || result.Month == -1 || result.Day == -1)
{
DateTime dateTimeNow = DateTimeParse.GetDateTimeNow(ref result, ref styles);
if (result.Month == -1 && result.Day == -1)
{
if (result.Year == -1)
{
if ((styles & DateTimeStyles.NoCurrentDateDefault) != DateTimeStyles.None)
{
cal = GregorianCalendar.GetDefaultInstance();
result.Year = result.Month = result.Day = 1;
}
else
{
result.Year = cal.GetYear(dateTimeNow);
result.Month = cal.GetMonth(dateTimeNow);
result.Day = cal.GetDayOfMonth(dateTimeNow);
}
}
else
{
result.Month = 1;
result.Day = 1;
}
}
else
{
if (result.Year == -1)
result.Year = cal.GetYear(dateTimeNow);
if (result.Month == -1)
result.Month = 1;
if (result.Day == -1)
result.Day = 1;
}
}
if (result.Hour == -1)
result.Hour = 0;
if (result.Minute == -1)
result.Minute = 0;
if (result.Second == -1)
result.Second = 0;
if (result.era == -1)
result.era = 0;
return true;
}
答案 1 :(得分:2)
一天零一个月不算日期-因此,如果不假设年份,则不能将它们解析为DateTime
值。 .NET Framework假定年份为当前年份或第一年-正是因为2/29仅在leap年才有效-这是一个非常合理的假设。
.Net框架没有提供存储日/月值的内置方式,但是Noda Time可以-看一下AnnualDate
-它存储了一天零一个月但没有年份。
但是,它没有Parse
或TryParse
方法-因此,您仍然需要手动操作输入字符串并按顺序添加年份(如2016年的leap年)使用DateTime
的{{1}}方法。
更新
正如马特·约翰逊(Matt Johnson)在评论中所写,“野田时间”确实提供了一种使用AnnualDatePattern
类将文本解析为TryParseExact
的方法。
该文档有一个名为Patterns for AnnualDate values的页面,其中列出了受支持的模式。