Getting Wrong Date from Dateformat

SimpleDateFormat parsing wrong date

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….

Simple date format giving wrong time

In your example, you are using time 1618274313 and you are assuming that it is in milliseconds. However, when I entered the same time on https://www.epochconverter.com/, I got below results:

Please notice the site mentions: Assuming that this timestamp is in seconds.


Now if we use that number multiplied by 1000 (1618274313000) as the input so that the site considers it in milliseconds, we get below results:

Please notice the site now mentions: Assuming that this timestamp is in milliseconds.


Now, when you will use 1618274313000 (correct time in milliseconds) in Java with SimpleDateFormat, you should get your expected result (instead of 23:01:14):

SimpleDateFormat sdf=new SimpleDateFormat("HH:mm:ss", Locale.getDefault());
System.out.println(sdf.format(new Date(1618274313000)));

Simple Date format returns Wrong date intermittently

I'm sure that if you don't use that static instance of SimpleDateFormat you will have no problem:

public static String getCurrentDateTime() {
SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date d = new Date();
String datetime = sdf.format(d);
return datetime;
}

See these links:

Why is Java's SimpleDateFormat not thread-safe?

"Java DateFormat is not threadsafe" what does this leads to?

Getting Wrong Date from dateFormat

As per the @MartinR suggestion
settinginputFormatter.defaultDate to current date or Date(timeIntervalSinceReferenceDate: 0) its worked fine

let str = "00/01/01"

let inputFormatter = DateFormatter()
inputFormatter.defaultDate = Date(timeIntervalSinceReferenceDate: 0)
inputFormatter.dateFormat = "yy/MM/dd"
if let showDate = inputFormatter.date(from: str) {
inputFormatter.dateFormat = "dd/MM/yyyy"
let resultString = inputFormatter.string(from: showDate)
print(resultString)
}

Swift date format returning wrong date

The code in your question is muddled up. You try to convert a string into a string in the first example and something unspecified into a Date in the second example.

Here's how to convert a Date into a String:

import Foundation

let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXXXX"
let string: String = formatter.string(from: Date())

print(string) // prints for example 2020-10-18T10:54:07+01:00

Here's how to convert a string into a date

let formatter = DateFormatter()
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd' 'HH:mm:ssZ"
let date: Date = formatter.date(from: "2020-10-18 10:59:56+0100")! // In real life, handle the optional properly
print(date) // prints 2020-10-18 09:59:56 +0000

When you print a Date directly, it automatically uses UTC as the time zone. This is why it changed it in the code above.

In the examples, I explicitly specified the type of string and date to show what type they are. Type inference means you can omit these in normal code.

As a general rule when handling dates:

  • always use Date in your code. Date is a type that stores the number of seconds since Jan 1st 1970 UTC.
  • Only convert dates to strings when displaying them to the user or communicating with an external system.
  • When calculating periods etc, always use a Calendar to get things like date components and intervals in units other than seconds. You might think to get "the same time tomorrow" you could just add 24 * 60 * 60 to a Date but in many countries, like mine, that will work on only 363 days in the year. Calendar will correctly handle things like daylight saving and leap years.

Simple Date time gives the wrong format of date

java.time through desugaring

Consider using java.time, the modern Java date and time API, for your date work.

To get the first day of the current year — excuse my Java syntax:

    LocalDate firstDayOfThisYear
= LocalDate.now(ZoneId.systemDefault()).withDayOfYear(1);
System.out.println("First day of the year: " + firstDayOfThisYear);

Output so far:

First day of the year: 2021-01-01

To format into your desired format:

    String formattedDate = firstDayOfThisYear.atStartOfDay()
.format(RECORD_DTM_FORMAT);
System.out.println("Formatted date: " + formattedDate);

I used this static formatter:

private static final DateTimeFormatter RECORD_DTM_FORMAT
= DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH);

Formatted date: 2021-01-01 00:00:00

What went wrong in your code?

One error is in this line:

    calendar.set(Calendar.YEAR,0,1)

You were finding the first day, not of this year, but of year 1 AD (2020 years ago). You were using the constant Calendar.YEAR incorrectly. It’s a constant to use for accessing the year field of a Calendar object and has the value 1. So you were specifying year 1. It was a common mistake with Calendar. In your output you can see that you get year 1 (the digit 1 at the end):

last Tue Jan 01 13:09:48 GMT+05:30 1

You also notice that the call to set() has not got rid of the time of day, which you might have wanted to.

This method call effectively does nothing (or really very little):

    recordDtmFormat.parse(recordDtmFormat.format(date))

You are formatting a Date object into a String only to parse it back into a Date object again. What you get is a Date object equal to the one you had. Only the millisecond of the second has been discarded because they are not in your string format. It’s the only difference.

A couple of further details that don’t contribute to your unexpected output, but you still might like to know: You have commented out this line:

// private val recordDtmFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'", Locale("en","IN"))

Hardcoding T as a literal in your format pattern string is correct since there should always be a T there and it doesn’t carry any semantics. The Z carries semantics: it’s an offset of 0 from UTC. So you must never hardcode it as a literal in your format pattern string. You need to parse it as an offset, or you will get an incorrect result.

Also in your output it seems that you have set your default time zone to GMT+05:30. This is incorrect for India. You need to set it to Asia/Kolkata. Always use the region/city format for time zones. While both give the same results for dates in this year, there are differences for historic dates and there may come differences again for future dates if the Indian politicians decide to change India’s time zone offset again some time. Experiences from other parts of the world say that this happens a lot.

Question: Doesn’t java.time require Android API level 26?

java.time works nicely on both older and newer Android devices. It just requires at least Java 6.

  • On newer Android devices (from API level 26) the modern API comes built-in.
  • On older Android use desugaring. See the link below.

Links

  • Oracle tutorial: Date Time explaining how to use java.time.
  • Java 8+ APIs available through desugaring


Related Topics



Leave a reply



Submit