Date Object Simpledateformat Not Parsing Timestamp String Correctly in Java (Android) Environment

SimpleDateFormat not parsing time correctly

This is one of the problems with the obsolete Date, Calendar and SimpleDateFormat classes. You shouldn't use it, for it's supplanted by the new Date and Time API in Java 8. It is available in the java.time package.

String str = "2018-11-01T18:07:55.6725292Z";
String pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSSSSS'Z'";

LocalDateTime ts = LocalDateTime.parse(str, DateTimeFormatter.ofPattern(pattern));
System.out.println("Text 2018-11-01T18:07:55.6725292Z parses as " + ts);

It seems that SimpleDateFormat is only able to read up to three millisecond digits. The parsing process works if one truncates the fraction portion of the date to three digits, i.e. "2018-11-01T18:07:55.672" instead of "2018-11-01T18:07:55.6725292Z", and also changes the according 'S' pattern specifiers, i.e. "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'".

SimpleDateFormat java giving wrong output

tl;dr

LocalDateTime                             // Represent a date wih time-of-day but lacking he context of a time zone or offset.
.parse( "2010-01-01T00:43:54.776000" ) // Parse your standard ISO 8691 text with microseconds. Returns a `LocalDateTime` object. This is *not* a moment, *not* a point on the timeline.
.atOffset( ZoneOffset.UTC ) // Apply an offset to determine a moment. Returns an `OffsetDateTime` object.
.toString() // Generate text in standard ISO 8691 format.

java.time

Stop using terrible date-time classes that were supplanted years ago by the modern java.time classes.

Always search Stack Overflow thoroughly before posting. All this has been covered many times already, so I’ll be brief.

LocalDateTime ldt = LocalDateTime.parse( "2010-01-01T00:43:54.776000" ) ;
OffsetDateTime odt = ldt.atOffset( ZoneOffset.UTC ) ;

Generate text in the standard ISO 8601 format.

String output = odt.toString() ;

Table of all date-time types in Java, both modern and legacy



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. Hibernate 5 & JPA 2.2 support java.time.

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 brought 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 (26+) bundle implementations of the java.time classes.
    • For earlier Android (<26), a process known as API desugaring brings a subset of the java.time functionality not originally built into Android.
      • If the desugaring does not offer what you need, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above) to Android. See How to use ThreeTenABP….

parsing date using simpleDateFormat java

The SimpleDateFormat does not have precision beyond milliseconds (.SSS).

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

public class Main {
public static void main(String[] args) throws ParseException {
SimpleDateFormat df = new SimpleDateFormat("dd-MMM-yy hh.mm.ss.SSS a", Locale.ENGLISH);
Date date1 = df.parse("17-DEC-19 05.40.39.364 PM");
System.out.println(date1);
}
}

Output:

Tue Dec 17 17:40:39 GMT 2019

Note that the java.util date-time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API* .

Using modern date-time API:

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.util.Locale;

public class Main {
public static void main(String[] args) {
DateTimeFormatter df = new DateTimeFormatterBuilder()
.parseCaseInsensitive() // For case-insensitive (e.g. AM/am) parsing
.appendPattern("dd-MMM-yy hh.mm.ss.n a")
.toFormatter(Locale.ENGLISH);

LocalDateTime ldt = LocalDateTime.parse("17-DEC-19 05.40.39.364000000 PM", df);
System.out.println(ldt);
}
}

Output:

2019-12-17T17:40:39.364

Learn more about the modern date-time API from Trail: Date Time.


* For any reason, if you have to stick to Java 6 or Java 7, you can use ThreeTen-Backport which backports most of the java.time functionality to Java 6 & 7. If you are working for an Android project and your Android API level is still not compliant with Java-8, check Java 8+ APIs available through desugaring and How to use ThreeTenABP in Android Project.

SimpleDateFormat parsing issue for dateFormat using milliseconds

As Other have mentionned in comment, other thread answers this well: https://stackoverflow.com/a/6157860/5190019

The fact is that SSSSSS doesn't exist as a format for this class, it expects only 3 number for milliseconds. So it is interpreted as such. DateFormat will interpret 712754 as 712754/1000 seconds rather than 0.712754 seconds.
And if you do the calculus it's 11,86. minutes, which mean 11mn52 seconds.
So 33:08+11:52, is 45:00, the result you get.

As for the solution, you can either strip the rest of the milliseconds part because you don't need it anyway (as you did) or use another class (all comments from Ole V.V are on point).

Java problem with Java.util.Date and Java.util.TimeZone

tl;dr

java.time.OffsetDateTime.parse( "2020-04-11T14:52:34.8121672+00:00" ) 

See this code run live at IdeOne.com.

Details

Never use java.util.Date. That flawed class was supplanted years ago by the modern java.time classes defined in JSR 310. Specifically replaced by java.time.Instant.

Avoid setting the JVM’s current default time zone. Doing so immediately affects all other code in all threads of all apps running in that JVM. Write your code such that you never depend on the default time zone. Always specify your desired/expected time zone.

No need to define this custom formatting pattern: "yyyy-MM-dd'T'HH:mm:ss.SSSSSSSXXX". That format is defined in the ISO 8601 standard, used by default in java.time when parsing/generating text.

By convention, the decimal fractions are written in groups of three digits. So suggest to the publisher of your data writing that textual value as 2020-04-11T14:52:34.812167200+00:00 rather than 2020-04-11T14:52:34.8121672+00:00. And congratulate the publisher on using both the hours and the minutes of the offset, as well as the colon. While technically optional in ISO 8601, including them maximizes compatibility with various date-time handling libraries in the real world.

Your format is asking for hundreds of nanoseconds. But the legacy date-time types resolve to mere milliseconds (thousandths of a second). So you were pressing a square peg into a round hole. Fortunately, java.time resolves to nanoseconds (billionths of a second). So we can handle parsing your input.

Parse your particular input as a OffsetDateTime.

OffsetDateTime odt = OffsetDateTime.parse( "2020-04-11T14:52:34.8121672+00:00" ) ;

Generate a string in standard ISO 8601 format.

String output = odt.toString() ;

2020-04-11T14:52:34.812167200Z

Convert to the terrible legacy java.util.Date only if you must. Find new conversion methods added to the old classes.

java.util.Date juDate = Date.from( odt.toInstant() ) ;

All of this has been addressed many many times on Stack Overflow. Please search more thoroughly before posting. And, search to learn more.

Simple Date format gives wrong info from epoch timestamp

The java.util.Date constructor accepts milliseconds since the Epoch, not seconds:

Allocates a Date object and initializes it to represent the specified number of milliseconds since the standard base time known as "the epoch", namely January 1, 1970, 00:00:00 GMT.

The following code which uses ms is working:

String timestamp = "1538970640000";   // use ms NOT s
SimpleDateFormat formatter = new SimpleDateFormat("dd MMM 'at' hh:mm a z" );
String dateString = formatter.format(new Date(Long.parseLong(timestamp)));

08 Oct at 05:50 AM CEST

Demo

Part of the problem you were facing is that your date format omitted the year component, which was actually coming up as 1970.



Related Topics



Leave a reply



Submit