0

I'm trying to display an incoming ISO Date like (2021-02-15T00:00:00.000Z) to a Textview in the following format: "dd MM yyyy". But I get the following error when parsing the date.

java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:549)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950)
         Caused by: java.lang.reflect.InvocationTargetException
            at java.lang.reflect.Method.invoke(Native Method)
            at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:539)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:950) 
         Caused by: java.text.ParseException: Unparseable date: "2021-02-15T00:00:00.000Z"
            at java.text.DateFormat.parse(DateFormat.java:362)

Here is the Kotlin code:

val format = SimpleDateFormat(
    "yyyy-MM-dd'T'HH:mm:ss'Z'",
    Locale.getDefault()
)
val initialConvertedDate = format.parse(customfield.value)

val simpleDateFormat = SimpleDateFormat(
    "dd MM yyyy",
    Locale.getDefault()
)
val finalDate = simpleDateFormat.format(initialConvertedDate)

tv2.text = finalDate
wawanopoulos
  • 9,614
  • 31
  • 111
  • 166
  • Did you try to use predefined formatters? https://developer.android.com/reference/kotlin/java/time/format/DateTimeFormatter#predefined-formatters – amtrax May 02 '21 at 10:45
  • As an aside consider throwing away the long outmoded and notoriously troublesome `SimpleDateFormat` and friends. See if you either can use [desugaring](https://developer.android.com/studio/write/java8-support-table) or add [ThreeTenABP](https://github.com/JakeWharton/ThreeTenABP) to your Android project, in order to use java.time, the modern Java date and time API. It is so much nicer to work with. – Ole V.V. May 04 '21 at 05:46

1 Answers1

3

Use the pattern, yyyy-MM-dd'T'HH:mm:ss.SSSXXX where X truly represents the timezone offset. In your date-time string, the timezone offset is Z which stands for Zulu and specifies UTC (timezone offset of +00:00 hours).

The format that you have used has two problems:

  1. It makes Z as a character literal and therefore it does not represent timezone offset.
  2. It does not specify fraction-of-second i.e. SSS.

Demo:

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

public class Main {
    public static void main(String args[]) throws ParseException {
        String strDateTime = "2021-02-15T00:00:00.000Z";
        SimpleDateFormat sdfInput = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.SSSXXX", Locale.getDefault());
        Date date = sdfInput.parse(strDateTime);
        SimpleDateFormat sdfOutput = new SimpleDateFormat("dd MM yyyy");
        sdfOutput.setTimeZone(TimeZone.getTimeZone("Etc/UTC"));
        String formatted = sdfOutput.format(date);
        System.out.println(formatted);
    }
}

Output:

15 02 2021

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

Demo using modern date-time API:

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String args[]) {
        String strDateTime = "2021-02-15T00:00:00.000Z";
        OffsetDateTime odt = OffsetDateTime.parse(strDateTime);
        System.out.println(odt);

        DateTimeFormatter dtfOutput = DateTimeFormatter.ofPattern("dd MM yyyy");
        String formatted = dtfOutput.format(odt);
        System.out.println(formatted);
    }
}

Output:

2021-02-15T00:00Z
15 02 2021

Note that the modern date-time API is based on ISO-8601 and therefore you do not need to use a DateTimeFormatter explicitly in order to parse a date-time string that is already in the ISO-8601 format.

Learn more about the 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