繁体   English   中英

在C#中没有年份的leap年解析总是失败

[英]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它存储了一天零一个月但没有年份。

但是,它没有ParseTryParse方法-因此,您仍然需要手动操作输入字符串并添加年份(如2016年是leap年)才能使用DateTimeTryParseExact方法。

更新资料

正如Matt Johnson在其评论中所写,Noda Time确实提供了一种使用AnnualDatePattern类将文本解析为AnnualDate方法。
该文档有一个称为AnnualDate值的模式页面,其中列出了受支持的模式。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM