SimpleDateFormat неправильно обрабатывает дату - PullRequest
1 голос
/ 26 марта 2020

Здесь я пытаюсь сравнить 3 даты, для этого я передал дату и две строки в функцию. И я использую простой формат даты, чтобы сделать 3 даты того же формата, чтобы я мог сравнить их. Но для двух строкового значения я получаю неправильную дату при разборе. Может кто-нибудь, пожалуйста, помогите?

Private boolean compareDate(Date cdate, String fdate, String date) {
    //cdate = 2020-03-25 09:05:47
    //fdate = 03/10/2020
    //tdate = 03/25/2020

    SimpleDateFormat sd= new SimpleDateFormat("dd/MM/yyyy");
    String s=sd.format(cdate);
    Date d1=sd.parse(s);
    Date d2=sd.parse(fdate);
    Date d3=sd.parse(tdate);
}

Значения, которые я получаю после анализа:

D1 = wed Mar 25 00:00:00 IST 2020
D2 = sat Oct 03 00:00:00 IST 2020 //wrong date fdate was 03/10/2020
D3 = Mon Jan 03 00:00:00 IST2020 //wrong date  tdate was 03/25/2020

Может кто-нибудь сказать, где я go ошибся? И из-за этой проблемы я не могу их правильно сравнить.

Ответы [ 3 ]

3 голосов
/ 26 марта 2020

tl; dr

myJavaUtilDate 
.toInstant()
.atZone
(
    ZoneId.of( "Asia/Kolkata" ) 
)
.toLocalDate()
.isEqual
(
    LocalDate
    .parse
    (
        "03/10/2020" ,                              // Do you mean March 10th, or October 3rd? 
        DateTimeFormatter.ofPattern( "dd/MM/uuuu" ) // Or "MM/dd/uuuu".
    )
)

Смарт-объекты, а не тупые строки

Вы сказали:

сделать 3 даты в одном формате, чтобы я мог сравнивать их

Использовать объекты с методами сравнения, а не сравнивать текст строк.

У нас есть класс для дат, встроенный в Java: LocalDate.

java .time

Вы используете Date который является одним из ужасных классов даты и времени в комплекте с самыми ранними версиями Java. Эти классы теперь устарели, вытеснив годы на go с принятием JSR 310, который определяет java .time классов.

Я прошел дату

При обнаружении объекта java.util.Date немедленно преобразуйте его в современную замену java.time.Instant. Используйте новый метод преобразования toInstant, добавленный к старому классу.

Instant instant = myJavaUtilDate.toInstant() ;

И java.util.Date, и java.time.Instant представляют момент в UT C. Это то, как вы хотите воспринимать дату в UT C со смещением нуля часов-минут-секунд от основного меридиана? Имейте в виду, что в любой данный момент дата меняется по всему земному шару в зависимости от зоны. Моментом может стать «завтра» в Токио, Япония, и еще «вчера» в Толедо, штат Огайо, США.

OffsetDateTime odt = instant.atOffset( ZoneOffset.UTC ) ;

Извлечение даты.

LocalDate ld = odt.toLocalDate() ;  // Extract the date only, omitting the time-of-day and the offset-from-UTC.

Или вы хотите воспринимать эту дату в определенной зоне?

ZoneId z = ZoneId.of( "Asia/Tokyo" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
LocalDate ld = zdt.toLocalDate() ;  // Extract the date only, omitting the time-of-day and the zone.

и две строки к функции

Определите шаблон форматирования для соответствия вашим вводам.

String input = "03/10/2020" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd/MM/uuuu" ) ;
LocalDate ld = LocalDate.parse( input , f ) ;  // Throws `DateTimeParseException` if input is faulty.

Теперь сравните, используя методы isEqual, isAfter, isBefore.

boolean datesMatch = ld1.isEqual( ld2 ) && ld2.isEqual( ld3 ) ;

java.util.Date::toString говорит ie

Вы спросили:

D2 = sat Oct 03 00:00:00 IST 2020 //wrong date fdate was 03/10/2020

Может кто-нибудь сказать, где я go неправильно?

Ваша основная проблема заключается в том, что ваш шаблон форматирования не соответствует вашим намерениям. Это правильно определено в Ответе Криса и Ответе Арвинда Кумара Авина sh.

Кроме того, у вас есть еще одна проблема. Среди многих проблем с java.util.Date является то, что его метод toString на лету применяет текущий часовой пояс JVM по умолчанию при генерации текста для представления содержимого объекта. Это создает иллюзию того, что эта зона хранится внутри объекта. При восприятии значения UT C объекта Date после настройки на часовой пояс дата может отличаться от даты, указанной в UT C. Это обсуждалось выше.

➥ Никогда не использовать java.util.Date.


О java .time

java .time Framework встроен в Java 8 и более поздние версии. Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date, Calendar, & SimpleDateFormat.

Чтобы узнать больше, см. Учебник Oracle . И поиск переполнения стека для многих примеров и объяснений. Спецификация: JSR 310 .

Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на java .time классов.

Вы можете обмениваться java .time объектами непосредственно с вашей базой данных. Используйте JDB C драйвер , совместимый с JDB C 4.2 или более поздней версией. Нет необходимости в строках, нет необходимости в java.sql.* классах.

Где взять классы java .time?

  • Java SE 8 , Java SE 9 , Java SE 10 , Java SE 11 и более поздних версий - часть стандартного API Java со связанной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и Java SE 7
    • Большинство функций java .time перенесено на Java 6 & 7 в ThreeTen-Backport .
  • Android
    • Более поздние версии Android комплектных реализаций классов java .time .
    • Для более ранних Android (<26) <a href="https://github.com/JakeWharton/ThreeTenABP" rel="nofollow noreferrer"> ThreeTenABP проект адаптируется ThreeTen-Backport (упомянуто выше). См. Как использовать ThreeTenABP… .
1 голос
/ 26 марта 2020

Проблема из-за несоответствия формата и строк даты. Ваш форматтер выглядит следующим образом:

SimpleDateFormat sd= new SimpleDateFormat("dd/MM/yyyy");

, тогда как строки даты, например 03/10/2020 или 03/25/2020, имеют формат MM/dd/yyyy.

Измените одно из них, чтобы оно совпадало с другим.

Я также рекомендую использовать Современный API даты / времени вместо сломанных Date и SimpleDateFormat классов.

1 голос
/ 26 марта 2020

Ваш формат: день, месяц, год, но, вероятно, ваши строки - месяц, день, год, если посмотреть на tDate, у которого 25 в середине и поэтому он не может быть месяцем

...