#java #validation #simpledateformat #date-parsing
#java #проверка #simpledateformat #анализ даты
Вопрос:
Какую ошибку я допустил в приведенном ниже коде? Если мы не передаем формат даты, такой как гггг-ММ-дд, он должен выдать ошибку синтаксического анализа и вернуть false, но приведенный ниже сценарий не работает
- 2020-08-19—> Это работает нормально и возвращает true
- 2020-19-08—> Это работает нормально и возвращает false
- 20-08-19—> Это должно возвращать false. Он не работает и возвращает true
Я не понимаю, почему сбой третьего сценария.
Уточнение: Я спрашиваю: если мы передадим input: 20-19-08
, он должен возвращать false, верно? Но он возвращает true. Моя проблема в том, что если я передам 20 вместо 2020, он должен вернуть false.
Код
public static boolean validateDateFormat(String strDate) {
SimpleDateFormat sdfrmt = new SimpleDateFormat("yyyy-MM-dd");
sdfrmt.setLenient(false);
try {
sdfrmt.parse(strDate);
}
catch (ParseException e) {
return false;
}
return true;
}
Комментарии:
1. Выведите дату после того, как вы проанализировали ее, и посмотрите, что это такое.
2. Я рекомендую вам не использовать
SimpleDateFormat
. Этот класс, как известно, вызывает проблемы и давно устарел. Вместо этого используйтеLocalDate
иDateTimeFormatter
оба из java.time, современного Java date and time API .3. Привет, АбхиРам. Могу ли я попросить вас не добавлять сообщения с просьбой к вашим вопросам? Stack Overflow предназначен для того, чтобы быть полезным ресурсом вопросов и ответов для будущих разработчиков, и поэтому предпочтителен технический стиль написания. Обращение с просьбой обычно не работает на добровольцах в любом случае — придерживайтесь нейтрального тона, если можете.
Ответ №1:
20-19-08 не соответствует формату, потому что год не указан как четырехзначное число (хотя используемый вами форматировщик распознает как 20, так и 2020 как действительные годы, просто не один и тот же год), и ваше значение месяца в соответствии со строкой формата будет равно 19, что недопустимо.
Комментарии:
1. если я передам 20-19-08, это должно вызвать ошибку синтаксического анализа, но она не выдает
2. Ваш шаблон форматирования неверен. MM означает месяц, а в году нет 19 месяцев.
3. если мы не передаем year в виде 4 цифр, это должно вызвать ошибку синтаксического анализа, но она не выдает, вот в чем моя проблема
4. Шаблон форматирования такой же, как и до редактирования. Это ваша проблема, независимо от любой другой ошибки, которую вы можете видеть, а можете и не видеть. В качестве доказательства, код в другом ответе работает, и он функционально эквивалентен вашему, за исключением строки формата, которая отличается. Также ваш код улавливает ошибку, но возвращает только false и ничего не выдает.
5. Я не вижу, как этот ответ может ответить на заданный вопрос? Я склонен воспринимать то, что говорится в ответе, как причины, по которым можно ожидать исключения, но по-прежнему ни одно из них не выдается (и не перехватывается).
Ответ №2:
Вы не создаете исключение в блоке catch. следовательно, он ничего не выдает, просто возвращает значение false . Чтобы получить фактическое исключение, выбросьте его или printStackTrace() оно.
Этот подход должен работать для обоих условий :
import java.util.*;
import java.text.SimpleDateFormat;
public class Main{
public static void main(String[] args) {
String ss = "20-19-08";
if(validateDateFormat(ss)){
System.out.println("SUCCESS");
}else {
System.out.println("ERROR");
}
}
public static boolean validateDateFormat(String strDate) {
SimpleDateFormat sdfrmt = new SimpleDateFormat("yyyy-dd-MM");
sdfrmt.setLenient(false);
try {
Date date = sdfrmt.parse(strDate);
System.out.println("Formatted Date :: " date);
return true;
}
catch (Exception e) {
return false;
}
}
}
Результаты тестирования :
Input : 20-19-08
Output :
Formatted Date :: Mon Aug 19 00:00:00 UTC 20
SUCCESS
Input : 2020-19-08
Output :
Formatted Date :: Wed Aug 19 00:00:00 UTC 2020
SUCCESS
Комментарии:
1. @AbhiRam Это не выдаст никакой ОШИБКИ, потому что вы не используете исключение «throw» в своем коде. Вы просто перехватываете исключение и возвращаете оттуда false. Для создания любого исключения добавьте код для создания исключения.
2. я спрашиваю, передаем ли мы входные данные: 20-19-08, он должен правильно возвращать false, но возвращать true
3. @AbhiRam Вы сказали, что ваш второй сценарий терпит неудачу. Я не смог воспроизвести сценарий сбоя, который вы видите. Пожалуйста, покажите некоторые точные тестовые примеры, выводимые в операторах System.out.println(). Также, если вы сомневаетесь, он проанализирует 20 и 2020 оба
4. Моя проблема в том, что если вы передаете 20 вместо 2020, он должен возвращать false
5. @OleV.V.: Изначально вопрос был не очень ясен, теперь после редактирования все ясно. Я думал, что его код не работает 20-08-19, но теперь я понял его главное сомнение. Он использует
SimpleDateFormat
, который может дать странный результат, подобный этому.
Ответ №3:
java.time
Я не думаю, что SimpleDateFormat
может предоставить вам проверку, о которой вы просите. Что является тем же самым, поскольку этот класс, как известно, вызывает проблемы и давно устарел. Вы все равно не должны его использовать. Я рекомендую вам использовать java.time, современный Java date and time API, для всей вашей работы с датами. И он хорошо проверяет вашу строку даты. Используйте DateTimeFormatter.ISO_LOCAL_DATE
.
public static boolean validateDateFormat(String strDate) {
try {
DateTimeFormatter.ISO_LOCAL_DATE.parse(strDate);
}
catch (DateTimeParseException e) {
return false;
}
return true;
}
Попробуйте:
String candidate = "20-08-19";
boolean valid = validateDateFormat(candidate);
System.out.format("Is %s valid? %s%n", candidate, valid);
Вывод:
Is 20-08-19 valid? false
Мы можем попробовать и некоторые другие строки:
Is 2020-13-19 valid? false Is 2020-08-19 and some more text that should not be here valid? false
И допустимый:
Is 2020-08-19 valid? true
Почему ваш код не сработал?
я не понимаю, почему второй сценарий не удался, может кто-нибудь мне помочь, пожалуйста
Это способ SimpleDateFormat
разбора чисел. Из документации:
- Год: Если форматировщиком
Calendar
является григорианский календарь, применяются следующие правила.
- …
- При синтаксическом анализе, если количество букв шаблона больше 2, год интерпретируется буквально, независимо от количества цифр. Таким образом, используя шаблон «ММ / дд / гггг», «01/11/12» выполняется синтаксический анализ до 11 января 12 года нашей эры.
- …
Я думаю, что пример довольно хорошо соответствует вашей ситуации. Даже если вы используете yyyy
строку шаблона в формате, SimpleDateFormat
он с радостью будет проанализирован 20
как 20 год нашей эры. Это объясняет, почему не генерируется исключение, что, в свою очередь, приводит к тому, что ваш метод возвращает true .
Ссылка
Руководство по Oracle: Дата и время, объясняющее, как использовать java.time.
Комментарии:
1. да, хорошее и правильное объяснение. Я даю за это положительный отзыв.