5

I try to convert string from JSON to ZonedDateTime just like

static String getWatchTime(JSONObject aJson, JSONObject bJson) {
    long difference = 0 ;
    try {
        String aTime = aJson.getString("time_utc_8");
        String bTime = bJson.getString("time_utc_8");

        String pattern = "yyyy-MM-dd HH:mm:ss.SSSSSS";
        DateTimeFormatter Parser = DateTimeFormatter.ofPattern(pattern).ISO_DATE;

        System.out.println(aTime);

        ZonedDateTime a = ZonedDateTime.parse(aTime, Parser);
        ZonedDateTime b = ZonedDateTime.parse(bTime, Parser);

        ChronoUnit unit = null;
        difference = unit.between(a, b);

        System.out.println(difference);

    } catch (JSONException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }

    String t = difference +"";
    return t;

}

and always get the error

Exception in thread "main" java.time.format.DateTimeParseException: Text '2016-06-28 22:29:44.700228' could not be parsed: Unable to obtain OffsetDateTime from TemporalAccessor: {},ISO resolved to 2016-06-28T22:29:44.700228 of type java.time.format.Parsed
at java.time.format.DateTimeFormatter.createError(Unknown Source)
at java.time.format.DateTimeFormatter.parse(Unknown Source)
at java.time.OffsetDateTime.parse(Unknown Source)
at Q2.getWatchTime(Q2.java:321)
at Q2.WatchTime(Q2.java:265)
at Q2.main(Q2.java:31)

I want to get the difference between these two date. I've tried SimpleDateFormat but it will get the error result, for the mills.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
Zi-yan Tseng
  • 184
  • 1
  • 1
  • 14
  • 3
    It doesn't make much sense to create a `Parser`, and then immediately call `ISO_DATE` on it. – Oliver Charlesworth Jun 11 '17 at 18:10
  • without the `Parser` and `ISO_DATE` will also get DateTimePareseException – Zi-yan Tseng Jun 11 '17 at 18:14
  • 1
    What I'm saying is that `DateTimeFormatter.ofPattern(pattern).ISO_DATE` is equivalent to `DateTimeFormatter.ISO_DATE`. – Oliver Charlesworth Jun 11 '17 at 18:16
  • thanks for your message , i googled the problem and find one of the solution is adding `ISO_DATE` , i will try another ways – Zi-yan Tseng Jun 11 '17 at 18:18
  • 2
    Your input string does not contain time zone information, so you need to parse to `LocalDateTime`, not `ZonedDateTime`. Alternatively, specify a default time zone on the parser, but I'd suggest parsing to `LocalDateTime`. You can always call `atZone(ZoneId.systemDefault())` to get a `ZonedDateTime`, if that's what you really need. – Andreas Jun 11 '17 at 18:33
  • 1
    Your string, `2016-06-28 22:29:44.700228`, does conform to the format pattern string your are using. What happens if you simply delete `.ISO_DATE`? – Ole V.V. Jun 11 '17 at 19:06
  • Next, calling `unit.between(a, b)` right after you have initialized `unit` to `null` is bound to cause a `NullPointerException`. – Ole V.V. Jun 11 '17 at 19:07

2 Answers2

7

I think it’s already all in the comments, so this is just to sum up.

(1) Your format pattern string is correct. You just need to delete .ISO_DATE from the following line, so it becomes:

          DateTimeFormatter Parser = DateTimeFormatter.ofPattern(pattern);

(ISO_DATE accepts for example '2011-12-03+01:00' or '2011-12-03', a date without time with or without an offset from UTC; you’ve got nothing to use it for here as far as I can tell.)

(2) Since your string seems to have neither time zone nor offset, use LocalDateTime:

          LocalDateTime a = LocalDateTime.parse(aTime, Parser);
          LocalDateTime b = LocalDateTime.parse(bTime, Parser);

If you need to take summer time (DST) or the like into account when calculating the difference, convert the time after parsing:

          ZoneId timeZone = ZoneId.systemDefault();
          ZonedDateTime a = LocalDateTime.parse(aTime, Parser).atZone(timeZone);
          ZonedDateTime b = LocalDateTime.parse(bTime, Parser).atZone(timeZone);

Please think twice about the time zone to use for conversion so you are sure to get the expected result.

(3) A ChronoUnit of null won’t work. I don’t know which one you intended, so this option is picked rather at random:

          ChronoUnit unit = ChronoUnit.DAYS;

With these three changes your method executes nicely on my computer. In one run it printed:

2016-06-28 22:29:44.700228
365

In the same run it returned a string of 365.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
4

i get the answer by Andreas(in comment) i used this code to achieve my goal finally

    static String getWatchTime(JSONObject aJson, JSONObject bJson) {
    double difference = 0 ;
    try {
        String aTime = aJson.getString("time_utc_8");
        String bTime = bJson.getString("time_utc_8");

          String pattern = "yyyy-MM-dd HH:mm:ss.SSSSSS";
          DateTimeFormatter Parser = DateTimeFormatter.ofPattern(pattern).withZone(ZoneId.systemDefault());

          System.out.println(aTime);


          ZonedDateTime a = ZonedDateTime.parse(aTime,Parser);
          ZonedDateTime b = ZonedDateTime.parse(bTime,Parser);

          System.out.println(a);
          System.out.println(b);
          //ChronoUnit unit = null ;
          difference = ChronoUnit.MICROS.between(a, b);


    } catch (JSONException e) {
        e.printStackTrace();
    } /*catch (ParseException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }*/

    String t = difference +"";
    return t;

}

I didn't set the TimeZone, so can't convert the input as string to ZonedDateTime. And I need to get the microssecond , hence i use ChronoUnit.MICROS.between() Thanks for answers

Zi-yan Tseng
  • 184
  • 1
  • 1
  • 14