[英]Parsing leap year day without year always fails in C#
我正在尝试以d/M
格式解析生日,但未指定任何年份。
大多数情况下DateTime.TryParseExact(birthday, "d/M", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime birthdayDate)
使用DateTime.TryParseExact(birthday, "d/M", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime birthdayDate)
可以正常工作,除非生日在leap年日(aka 29/2
),并且解析时永远不会成功,因为它默认为当前年份。 使用DatTimeStyles.NoCurrentDateDefault
也不起作用,因为它默认为year = 1 ,这不是a年。
我该如何进行解析,以使其不涉及破解(我不想手动解析或手动添加任意一年以将其解析为完整日期,它们都很难看并且可能很脆弱),并且仍然可以正常工作所有可能的日期,包括leap日? 现有的问题根本没有帮助,因为没有人会费心检查它们是否在leap日工作。 我尝试了所有这些,但没有一个起作用。
这个问题缺少适当的细节,但是
如果只想解析出生日期和月份(包括leap年日期),则只需在日期末尾添加a年。
我不确定您打算在这里做什么,但是您可以尝试一下
birthday = $"{birthday}/2016"; // leap year
DateTime.TryParseExact(birthday, "d/M/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime birthdayDate);
更新资料
我的问题是如何不以某种方式手动覆盖TryParseExact来自动假定年份
为了在此处具有技术性, 如果您像示例中那样专门解析a年月份和日期 ,则不必在字符串中指定the年。
TryParseExact
方法有很多检查和平衡方法,但是这里是重要的部分。
简而言之,它使用当前年份或年份1,并且无法告诉它具体选择choose年
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;
}
一天零一个月不会成为日期-因此,如果不假设年份,则不能将它们解析为DateTime
值。 .NET Framework假定年份是当前年份或年份1-正是因为2/29仅在leap年有效-这是一个非常合理的假设。
.Net框架没有提供一种内置的方式来存储日/月值,但是Noda Time却提供了-查看AnnualDate
它存储了一天零一个月但没有年份。
但是,它没有Parse
或TryParse
方法-因此,您仍然需要手动操作输入字符串并添加年份(如2016年是leap年)才能使用DateTime
的TryParseExact
方法。
更新资料
正如Matt Johnson在其评论中所写,Noda Time确实提供了一种使用AnnualDatePattern
类将文本解析为AnnualDate
方法。
该文档有一个称为AnnualDate值的模式页面,其中列出了受支持的模式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.