问题
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 SimpleDateFormat
classes.
来源:https://stackoverflow.com/questions/60857872/simpledateformat-parsing-wrong-date