javakotlindatetimeformatter

DateTimeFormatter in Android not parsing a Timestamp properly


I am trying to parse a timestamp that looks like this according to the error I was given. Attached below is my code for parsing, I followed the documentation regarding the symbols like u,y,M,h,H in DateTimeFormatter so I am quite confused why it is not working? Thank you.

java.time.format.DateTimeParseException: Text '2022-12-26T14:52:02+08:00' could not be parsed at index 19

@Composable
fun ExpandedBusStop(
    modifier: Modifier = Modifier,
    currentBusStopService: SingaporeBusServices,

) {
    // Determine the Current Timestamp as LocalDateTime
    var currentTimestamp = LocalDateTime.now() //.format(DateTimeFormatter.ofPattern("yyyy-MM-dd hh:mm:ss"))
    val datetimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZ")
//    datetimeFormatter.setTimeZone(TimeZone.getTimeZone("GMT+14"))
    var nextBusEtaArray = Array<String>(3) { "" }
    var nextBusOccupancyArray = Array<String>(3) { "" }

    val currentBusService = currentBusStopService.busServiceNumber


    for (i: Int in 0..2) {
        // Determining the ETA of the Next 3 Buses in Minutes
        val nextBus = currentBusStopService.nextBus1
        val nextBusTimestampString = nextBus.estimatedArrival  // In the Event there are no longer any buses
        val nextBusTimestamp = LocalDateTime.parse(nextBusTimestampString, datetimeFormatter)
        val nextBusETA = Duration.between(currentTimestamp, nextBusTimestamp)
        // Round down to Nearest Minute and Convert into a String
        nextBusEtaArray[i] = nextBusETA.toString().toInt().toString()

        // Determining the Occupancy Rates of the Next 3 Buses
        val nextBusOccupancy = nextBus.busOccupancyLevels
        nextBusOccupancyArray[i] = nextBusOccupancy
    }


    Divider(thickness = 2.dp)
    Row {
        // Bus Service Number
        Text(
            text = currentBusService,
            style = MaterialTheme.typography.h5,
            modifier = modifier.weight(2f)
        )

        Spacer(modifier = modifier.weight(1f))

        // Waiting Time + Occupancy Rate for each Incoming Bus
        Column() {
            Text(
                text = nextBusEtaArray[0],
                style = MaterialTheme.typography.body2
            )

            // TODO Replace with Infographic
            Text(
                text = nextBusOccupancyArray[0],
                style = MaterialTheme.typography.body2
            )

        }

        Column() {
            Text(
                text = nextBusEtaArray[1],
                style = MaterialTheme.typography.body2
            )

            // TODO Replace with Infographic
            Text(
                text = nextBusOccupancyArray[0],
                style = MaterialTheme.typography.body2
            )
        }

        Column() {
            Text(
                text = nextBusEtaArray[2],
                style = MaterialTheme.typography.body2
            )

            // TODO Replace with Infographic
            Text(
                text = nextBusOccupancyArray[0],
                style = MaterialTheme.typography.body2
            )
        }
    }
    Divider(thickness = 2.dp)

}

Solution

  • You do not need a DateTimeFormatter

    java.time API is based on ISO 8601 and therefore you do not need a DateTimeFormatter to parse a date-time string which is already in ISO 8601 format (e.g. your date-time string, 2022-12-26T14:52:02+08:00).

    Demo:

    import java.time.OffsetDateTime;
    
    class Main {
        public static void main(String args[]) {
            String strDateTime = "2022-12-26T14:52:02+08:00";
            OffsetDateTime odt = OffsetDateTime.parse(strDateTime);
            System.out.println(odt);
        }
    }
    

    Output:

    2022-12-26T14:52:02+08:00
    

    Learn more about the modern Date-Time API from Trail: Date Time.