Как к проверке работоспособности дата в Java

78
задан Matthias Braun 15 January 2018 в 16:53
поделиться

6 ответов

Текущий путь состоит в том, чтобы использовать календарный класс. Это имеет метод setLenient , который проверит дату и бросок и исключение, если это будет вне диапазона как в Вашем примере.

Забыл добавлять: Если Вы получаете календарный экземпляр и устанавливаете время с помощью даты, это - то, как Вы получаете проверку.

Calendar cal = Calendar.getInstance();
cal.setLenient(false);
cal.setTime(yourDate);
try {
    cal.getTime();
}
catch (Exception e) {
  System.out.println("Invalid date");
}
33
ответ дан Mateus Viccari 24 November 2019 в 10:24
поделиться

Можно использовать SimpleDateFormat

, Например, что-то как:

boolean isLegalDate(String s) {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    sdf.setLenient(false);
    return sdf.parse(s, new ParsePosition(0)) != null;
}
38
ответ дан Maglob 24 November 2019 в 10:24
поделиться

С форматом даты 'прежней версии' мы можем отформатировать результат и сравнить его назад с источником.

    public boolean isValidFormat(String source, String pattern) {
    SimpleDateFormat sd = new SimpleDateFormat(pattern);
    sd.setLenient(false);
    try {
        Date date = sd.parse(source);
        return date != null && sd.format(date).equals(source);
    } catch (Exception e) {
        return false;
    }
}

Этот execerpt говорит 'ложь' source=01.01.04 с шаблоном '01.01.2004'

0
ответ дан 24 November 2019 в 10:24
поделиться

Два комментария по использованию SimpleDateFormat.

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

IME, который лучше, чем создание экземпляра для каждого синтаксического анализа даты.

1
ответ дан 24 November 2019 в 10:24
поделиться

Как показано @Maglob, основной подход состоит в том, чтобы протестировать преобразование строки в дату с помощью SimpleDateFormat.parse . При этом будут обнаружены недопустимые комбинации дня / месяца, например 31 февраля 2008 г.

Однако на практике этого бывает достаточно редко, поскольку SimpleDateFormat.parse чрезвычайно либерален. Вы можете быть обеспокоены двумя вариантами поведения:

Недействительные символы в строке даты Удивительно, но 2008-02-2x будет "проходить" как допустимую дату с locale format = "yyyy-MM-dd", например. Даже если isLenient == false.

Годы: 2, 3 или 4 цифры? Вы также можете использовать 4-значные годы вместо того, чтобы разрешать поведение SimpleDateFormat по умолчанию (которое будет интерпретировать «12-02-31» по-разному в зависимости от того, был ли ваш формат «yyyy-MM-dd» или «yy-MM-dd» )

Строгое решение со стандартной библиотекой

Таким образом, полная проверка строки до даты может выглядеть так: комбинация совпадения регулярного выражения и последующего принудительного преобразования даты. Уловка с регулярным выражением состоит в том, чтобы сделать его совместимым с локалью.

  Date parseDate(String maybeDate, String format, boolean lenient) {
    Date date = null;

    // test date string matches format structure using regex
    // - weed out illegal characters and enforce 4-digit year
    // - create the regex based on the local format string
    String reFormat = Pattern.compile("d+|M+").matcher(Matcher.quoteReplacement(format)).replaceAll("\\\\d{1,2}");
    reFormat = Pattern.compile("y+").matcher(reFormat).replaceAll("\\\\d{4}");
    if ( Pattern.compile(reFormat).matcher(maybeDate).matches() ) {

      // date string matches format structure, 
      // - now test it can be converted to a valid date
      SimpleDateFormat sdf = (SimpleDateFormat)DateFormat.getDateInstance();
      sdf.applyPattern(format);
      sdf.setLenient(lenient);
      try { date = sdf.parse(maybeDate); } catch (ParseException e) { }
    } 
    return date;
  } 

  // used like this:
  Date date = parseDate( "21/5/2009", "d/M/yyyy", false);

Обратите внимание, что регулярное выражение предполагает, что строка формата содержит только день, месяц, год и символы-разделители. Кроме того, формат может быть в любом формате локали: «д / ММ / гг», «гггг-ММ-дд» и так далее. Строку формата для текущего языкового стандарта можно получить следующим образом:

Locale locale = Locale.getDefault();
SimpleDateFormat sdf = (SimpleDateFormat)DateFormat.getDateInstance(DateFormat.SHORT, locale );
String format = sdf.toPattern();

Joda Time - Лучшая альтернатива?

I ' Я недавно слышал о joda time и решил сравнить. Два момента:

  1. Кажется, лучше быть строгим в отношении недопустимых символов в строке даты, в отличие от SimpleDateFormat
  2. . Пока не вижу способа принудительно использовать 4-значные годы с его помощью (но я думаю, вы могли бы создать свои собственные ] DateTimeFormatter для этой цели)

Это довольно просто использовать:

import org.joda.time.format.*;
import org.joda.time.DateTime;

org.joda.time.DateTime parseDate(String maybeDate, String format) {
  org.joda.time.DateTime date = null;
  try {
    DateTimeFormatter fmt = DateTimeFormat.forPattern(format);
    date =  fmt.parseDateTime(maybeDate);
  } catch (Exception e) { }
  return date;
}
48
ответ дан 24 November 2019 в 10:24
поделиться

Альтернативным строгим решением с использованием стандартной библиотеки является выполнение следующего:

1) Создайте строгий SimpleDateFormat, используя свой шаблон

2) Попытка для синтаксического анализа введенного пользователем значения с использованием объекта формата

3) В случае успеха переформатируйте дату, полученную из (2), используя тот же формат даты (из (1))

4) Сравните переформатированную дату с исходной, введенное пользователем значение. Если они равны, то введенное значение строго соответствует вашему шаблону.

Таким образом, вам не нужно создавать сложные регулярные выражения - в моем случае мне нужно было поддерживать весь синтаксис шаблона SimpleDateFormat, а не ограничиваться определенными типами, такими как дни, месяцы и годы.

6
ответ дан 24 November 2019 в 10:24
поделиться
Другие вопросы по тегам:

Похожие вопросы: