Формат данных Java работает не во всех сценариях

#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. да, хорошее и правильное объяснение. Я даю за это положительный отзыв.