Разбор високосного дня без года всегда не получается в C # - PullRequest
0 голосов
/ 20 ноября 2018

Я пытаюсь разобрать дни рождения в формате d/M без указания какого-либо года.

Использование DateTime.TryParseExact(birthday, "d/M", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime birthdayDate) работает большую часть времени, за исключением случаев, когда день рождения приходится на день високосного года (он же 29/2), и синтаксический анализ никогда не выполняется, так как по умолчанию используется текущий год.Использование DatTimeStyles.NoCurrentDateDefault также не работает, поскольку по умолчанию имеет год = 1 , который не является високосным годом.

Как выполнить синтаксический анализ, чтобы он не включал взлом (яне хотите анализировать его вручную или вручную добавлять произвольный год, чтобы проанализировать его как полную дату, все они уродливы и потенциально хрупки) и все еще работают во всех возможных датах, включая високосный день? Существующие вопросы вообще не помогает, поскольку никто не удосуживается проверить, работают ли они вообще на високосный день.Я попробовал все из них, и ни один из них не работал.

Ответы [ 2 ]

0 голосов
/ 20 ноября 2018

День и месяц не являются датой, поэтому они не могут быть проанализированы как значение DateTime без указания года..NET Framework предполагает год, который является либо текущим, либо годом 1 - именно потому, что 2/29 действует только в високосные годы - и это очень разумное предположение.

.NET Framework не предоставляетвстроенный способ хранения значений дня / месяца, но Noda Time делает - взгляните на AnnualDate - он хранит день и месяц, но не год.

Однако у него нет методов Parse или TryParse - для этого вам все равно нужно вручную манипулировать строкой ввода и добавить год (то есть високосный год, как 2016), чтобы использовать DateTime TryParseExact метод.

Обновление

Как писал Мэтт Джонсон в своем комментарии, Noda Time действительно предоставляет способ синтаксического анализа текста как AnnualDateс использованием класса AnnualDatePattern.
В документации имеется страница с именем Patterns для значений AnnualDate , в которой перечислены поддерживаемые шаблоны.

0 голосов
/ 20 ноября 2018

В этом вопросе отсутствуют соответствующие детали, однако

Если вы просто хотите проанализировать дату рождения и месяц , включая даты високосного года, то просто добавьте високосный год в конецдата.

Я не уверен, что вы ожидаете здесь сделать, однако вы можете попробовать это

birthday = $"{birthday}/2016"; // leap year

DateTime.TryParseExact(birthday, "d/M/yyyy", CultureInfo.InvariantCulture, DateTimeStyles.None, out DateTime birthdayDate);

Обновление

myвопрос в том, как не заставить TryParseExact автоматически принимать год, переопределяя его вручную каким-либо образом

Чтобы быть техническим, здесь нет необходимости указывать високосный год в строке , если вы анализируетемесяц и день високосного года исключительно , как в вашем примере

Существует множество сдержек и противовесов, которые делает метод TryParseExact, однако здесь есть важные биты.

Короче, он использует текущий год или год 1, и нет никакого способа сказать ему, чтобы он выбирал високосный год специально

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;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...