SimpleDateFormat parsing wrong date

三世轮回 提交于 2021-01-28 08:11:48

问题


Here I am trying to compare 3 dates, for that, I have passed a date and two string to a function. And I am using simple date format to make 3 dates of the same format so that I can compare them. But for the two string value, I am getting the wrong date when I parse it. Can anyone please help?

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);
}

The values that I get after parsing is :

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

Can anyone tell where did I go wrong? And due to this issue, I am not able to properly compare them.


回答1:


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".
    )
)

Smart objects, not dumb strings

You said:

make 3 dates of the same format so that I can compare them

Use objects with comparison methods, rather than comparing text of strings.

We have a class for dates built into Java: LocalDate.

java.time

You are using Date which is one of the terrible date-time classes bundled with the earliest versions of Java. These classes are now obsolete, supplanted years ago with the adoption of JSR 310 that defines the java.time classes.

I have passed a date

When encountering a java.util.Date object, immediately convert to its modern replacement, java.time.Instant. Use the new conversion method toInstant added to the old class.

Instant instant = myJavaUtilDate.toInstant() ;

Both java.util.Date and java.time.Instant represent a moment in UTC. Is that how you want to perceive the date, in UTC with an offset of zero hours-minutes-seconds from the prime meridian? Keep in mind that for any given moment the date varies around the globe by zone. A moment may be "tomorrow" in Tokyo Japan while still "yesterday" in Toledo Ohio US.

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

Extract the date.

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

Or did you want to perceive that date in a particular zone?

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.

and two string to a function

Define a formatting pattern to match your inputs.

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

Now compare, using methods isEqual, isAfter, isBefore.

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

java.util.Date::toString tells a lie

You asked:

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

Can anyone tell where did I go wrong?

Your main problem is that your formatting pattern is not defined to match your intention. This is correctly identified in the Answer by Chris and the Answer by Arvind Kumar Avinash.

In addition, you have another issue. Among the many problems with java.util.Date is that its toString method on-the-fly applies the JVM’s current default time zone while generating text to represent the content of the object. This creates the illusion of that zone being stored within the object. When perceiving your Date object’s UTC value after adjusting to a time zone, the date may differ from the date as seen in UTC. This was discussed above.

➥ Never use java.util.Date.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

  • Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - Part of the standard Java API with a bundled implementation.
    • Java 9 adds some minor features and fixes.
  • Java SE 6 and Java SE 7
    • Most of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android
    • Later versions of Android bundle implementations of the java.time classes.
    • For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….



回答2:


Your format is day then month then year, but presumably your strings are month then day then year, looking at tDate, which has 25 in the middle and so cannot be a month




回答3:


The problem is because of the mismatch in the format and the date strings. Your formatter is as follows:

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

whereas your date strings e.g. 03/10/2020 or 03/25/2020 are in MM/dd/yyyy format.

Change either of them to match the other one.

I also recommend you use Modern date/time API instead of broken Date and SimpleDateFormatclasses.



来源:https://stackoverflow.com/questions/60857872/simpledateformat-parsing-wrong-date

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!