Search code examples
javaandroidjava-timedatetime-parsingzoneddatetime

Problem converting time from String to ZonedDateTime in Android studio


I solved the problem itself, but I wanted to know why this is happening.

The problem is this: Initially, a date and time with a time zone in String format ("dd-MM-yyyy HH:mm:ss:SSSS OOOO") is sent to the database. The application receives this date in the same format, through the mapper this date is converted to ZonnedDateTime ("dd-MM-yyyy HH:mm:ss:SSSS OOOO"), and from it back to a String in the date and time format ("dd-MM -yyyy HH:mm"). In Intellij IDEA this code works perfectly, but in Android studio an error pops up. The problem was solved by changing the format when converting time from the database to ZonnedDateTime ("dd-MM-yyyy HH:mm:ss:SSSS zzzz").

I would like to know why this is happening.

Code in Android studio:

ZonedDateTime zonedDateTime = ZonedDateTime.parse(
                "22-12-2022 15:05:49:1200 GMT+10:00",
                DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss:SSSS OOOO")
        );

Error:

2022-12-23 12:18:13.558 24464-24464/com.example.sendmessages E/AndroidRuntime: FATAL EXCEPTION: main
    Process: com.example.sendmessages, PID: 24464
    java.time.format.DateTimeParseException: Text '22-12-2022 15:05:49:1200 GMT+10:00' could not be parsed: length=34; index=34
        at java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:1920)
        at java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1855)
        at java.time.ZonedDateTime.parse(ZonedDateTime.java:591)
        at com.example.sendmessages.Mapping.MessageMapper.getEntityToDto(MessageMapper.java:18)

Same code in intellij IDEA:

ZonedDateTime zonedDateTime = ZonedDateTime.parse(
                    "22-12-2022 15:05:49:1200 GMT+10:00",
                    DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss:SSSS OOOO")
            );
            System.out.print(dateTimeFormatter.format(zonedDateTime));

# 22-12-2022 15:05

How the problem was solved:

ZonedDateTime zonedDateTime = ZonedDateTime.parse(
                "22-12-2022 15:05:49:1200 GMT+10:00",
                DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss:SSSS zzzz")
        );

# 22-12-2022 15:05

Solution

  • OffsetDateTime, not ZonedDateTime

    GMT+10:00 is not a time zone. It is an offset-from-UTC, simply a number of hours-minutes-seconds ahead of or behind the temporal prime meridian of UTC (GMT, same thing for general business purposes).

    A time zone is much more. A time zone is a named history of the past, present, and future changes to the offset used by the people of a particular region as decided by their politicians.

    Since your input contains an offset, but not a time zone, you should be using OffsetDateTime class rather than ZonedDateTime.

    Java

    Let's run some code on the Java platform before trying Android.

    String input = "22-12-2022 15:05:49:1200 GMT+10:00";
    DateTimeFormatter f = null;
    f = DateTimeFormatter.ofPattern( "dd-MM-yyyy HH:mm:ss:SSSS OOOO" );
    OffsetDateTime odt = OffsetDateTime.parse( input , f );
    System.out.println( "odt = " + odt );
    String input2 = odt.format( f );
    OffsetDateTime odt2 = OffsetDateTime.parse( input2 , f );
    System.out.println( "input2 = " + input2 );
    System.out.println( "odt2 = " + odt2 );
    

    When run with Java 19.0.1+10:

    odt = 2022-12-22T15:05:49.120+10:00

    input2 = 22-12-2022 15:05:49:1200 GMT+10:00

    odt2 = 2022-12-22T15:05:49.120+10:00

    Android Studio

    While I do not do Android work, I installed Android Studio just to verify your problem. The JetBrains Toolbox app installed version Dolphin 2021.3.1 Patch 1 on my MacBook Pro with M1 Pro chip.

    I created a project using the "Phone and Tablet" template named Basic Activity. I used all defaults except switching the language from Kotlin to Java. After waiting a long while for downloads to complete, I was able to execute Make Project, and then run the default emulator.

    I added code to the onCreate method of MainActivity:

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    
        String input = "22-12-2022 15:05:49:1200 GMT+10:00";
        DateTimeFormatter f = null;
        if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
            f = DateTimeFormatter.ofPattern("dd-MM-yyyy HH:mm:ss:SSSS OOOO");
            OffsetDateTime odt = OffsetDateTime.parse(input, f);
            System.out.println("odt = " + odt);
            String input2 = odt.format(f);
            OffsetDateTime odt2 = OffsetDateTime.parse(input2, f);
            System.out.println("input2 = " + input2);
            System.out.println("odt2 = " + odt2);
        }
    …
    

    The result on the console is:

    I/System.out: odt = 2022-12-22T15:05:49.120+10:00

    I/System.out: input2 = 22-12-2022 15:05:49:1200 GMT+10:00

    I/System.out: odt2 = 2022-12-22T15:05:49.120+10:00

    👉 So I cannot recreate your issue when using the appropriate class. Runs correctly.