3

I am using SimpleDateFormat in order to parse a String. Here is an example:

private static final SimpleDateFormat longStringFormat = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'");
[some code here]
Date dirDate = longStringFormat.parse("2014-04-03T06:00:00.376542900Z");

When I check dirDate in debug mode, or print it, the date I get is Mon Apr 07 14:35:42 FET 2014.

Why do I get such an offset? It cannot be counted as a timezone offset(although it seems already wrong to apply an offset). How can I obtain a Date object depicting the exact same time as the String?

Dragos
  • 2,911
  • 12
  • 39
  • 55

2 Answers2

4

Well, the problem is that you're specifying this value for the number of milliseconds: 376542900. That's 104 hours, 35 minutes, 42 seconds and 900 milliseconds... hence the issue.

Unfortunately, it looks like SimpleDateFormat doesn't have a way of understanding that you're giving it "fractions of a second" instead of "a number of milliseconds". I strongly suspect (although I haven't tried it) that Java 8 would work properly (possibly with a longer pattern) and that Joda Time may also handle it - are either of those an option? Otherwise, you'll need to use string manipulation to get the string into a more manageable form.

(As an aside, you should also set the SimpleDateFormat's time zone to UTC, as that's what's being specified in the text.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • None of them is an option. Other suggestions except .substring() or .split()? – Dragos Apr 03 '14 at 15:35
  • 1
    @Dragos: I'd use `substring` to get rid of the extra digits, basically. – Jon Skeet Apr 03 '14 at 15:37
  • More accurately, SimpleDateFormat can't handle microseconds. If you reduce it down to 3 decimal places it is fine (though it would lead to a less accurate time value maybe) – Engineer2021 Apr 03 '14 at 15:45
  • You can use `Timestamp` like this answer: https://stackoverflow.com/a/2132605/2591612 – Engineer2021 Apr 03 '14 at 15:49
  • @staticx: It's not just microseconds in this case - it's nanoseconds. I assumed that Dragos just wanted to parse the value and get a reduced-accuracy `Date`. – Jon Skeet Apr 03 '14 at 15:51
  • True, I was not accurate in my statement. That being said, you can truncate all but the last three using `substring` and get the date needed. – Engineer2021 Apr 03 '14 at 15:52
1

java.time

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

Also, quoted below is a notice from the home page of Joda-Time:

Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project.

Solution using java.time, the modern Date-Time API:

import java.time.Instant;

public class Main {
    public static void main(String[] args) {
        Instant instant = Instant.parse("2014-04-03T06:00:00.376542900Z");
        System.out.println(instant);
    }
}

Output:

2014-04-03T06:00:00.376542900Z

An Instant represents an instantaneous point on the timeline in UTC. The Z in the output is the timezone designator for a zero-timezone offset. It stands for Zulu and specifies the Etc/UTC timezone (which has the timezone offset of +00:00 hours).

For any reason, if you need to convert this object of Instant to an object of java.util.Date, you can do so as follows:

Date date = Date.from(instant);

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.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110