2

I got this from https://stackoverflow.com/a/18217193/6727914

val df1: DateFormat = SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSZ")
val string1 = "2022-12-29T19:59:20.783357Z"
val result1: Date = df1.parse(string1)

But it does not work:

Exception in thread "main" java.text.ParseException: Unparseable date: "2022-12-29T19:59:20.783357Z" at java.text.DateFormat.parse (:-1)
at FileKt.main (File.kt:13) at FileKt.main (File.kt:-1)

I can't use Instant.parse(date)

The date "2022-12-29T19:59:20.783357Z" is a valid Iso8601String where 783 is the milliseconds and 357 is the micro seconds

TSR
  • 17,242
  • 27
  • 93
  • 197
  • 1
    It doesn't match the format you provide; it's not clear what you expect. `S` is for milliseconds, there's 1000 of them per second, and `783357 > 1000`. – Dave Newton Dec 29 '22 at 20:07
  • Did you consider looking at https://api.flutter.dev/flutter/dart-core/DateTime/parse.html? It's not clear why this is tagged Java/Kotlin if you're using Dart references :shrug: – Dave Newton Dec 29 '22 at 20:12
  • @DaveNewton The questions title is how to parse ISO date in kotlin, the expectation is thus having the date parsed. The date provided is a valid ISO date, not sure what is not clear – TSR Dec 29 '22 at 20:13
  • The biggest point of misclarity is why microseconds are included in your string, but completely absent from the format string (I don't know if `SDF` handles microseconds, but the format string ignores them, hence the error). – Dave Newton Dec 29 '22 at 20:15
  • 1
    _I can't use Instant.parse(date)_ Why not? SimpleDateFormat does not offer microsecond precision. – Sotirios Delimanolis Dec 29 '22 at 20:15
  • Due to API requirement 26, my app is 21. Can't upgrade it due to various constraints – TSR Dec 29 '22 at 20:16
  • So you either need to not add microseconds (do you really need microsecond "precision"?), or you need to handle it manually. – Dave Newton Dec 29 '22 at 20:17
  • @DaveNewton I don't need microsecond tbh, but the data is coming from another app that generates it with a built in function of the language that includes the microsecond by default, no option to exclude that – TSR Dec 29 '22 at 20:19
  • Then you'll need to handle it manually--yank anything between the `SSS` and the last char and parse normally, optionally filling the micros back in? – Dave Newton Dec 29 '22 at 20:22
  • Can you use [desugaring](https://developer.android.com/studio/write/java8-support#library-desugaring)? It will make (most of) java.time available to you also when developing for API 21. See [this answer by Arpit Bhoi](https://stackoverflow.com/a/73023269/5772882). – Ole V.V. Dec 29 '22 at 20:54

1 Answers1

3

SimpleDateFormat can not handle fraction-of-second up to microseconds resolution, its limit is up to millisecond resolution. If you try to parse it as it is, you will get the wrong result as explained in this answer.

You have two choices:

  1. Truncate fraction of second up to milliseconds resolution.
  2. Use ThreeTenABP or Android desugaring support as explained in this post. You can then use Instant#parse to parse your date-time string into an Instant.

Note: You need to use X instead of Z in your pattern.

Demo:

import java.text.ParseException;
import java.text.SimpleDateFormat;

public class Main {
    public static void main(String[] args) throws ParseException {
        var df1 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSX");
        var string1 = "2022-12-29T19:59:20.783357Z";
        string1 = string1.replaceAll("(\\.\\d{3})\\d+", "$1");
        var result1 = df1.parse(string1);
        System.out.println(result1);
    }
}

Output in my time zone, Europe/London:

Thu Dec 29 19:59:20 GMT 2022

Solution using java.time API

import java.time.Instant;
import java.util.Date;

public class Main {
    public static void main(String[] args) {
        var instant = Instant.parse("2022-12-29T19:59:20.783357Z");
        System.out.println(instant);

        // For any reason, if you need java.util.Date
        var date = Date.from(instant);
        System.out.println(date);
    }
}

ONLINE DEMO

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
  • The recommended java.time solution is available for API level 21 through [desugaring](https://developer.android.com/studio/write/java8-support#library-desugaring). – Ole V.V. Dec 31 '22 at 08:51