Home > Enterprise >  DateTimeFormatter in Android not parsing a Timestamp properly
DateTimeFormatter in Android not parsing a Timestamp properly

Time:12-26

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)

}

CodePudding user response:

According to the DateTimeFormatter docs:

Offset Z: This formats the offset based on the number of pattern letters. One, two or three letters outputs the hour and minute, without a colon, such as ' 0130'. The output will be ' 0000' when the offset is zero. Four letters outputs the full form of localized offset, equivalent to four letters of Offset-O. The output will be the corresponding localized offset text if the offset is zero. Five letters outputs the hour, minute, with optional second if non-zero, with colon. It outputs 'Z' if the offset is zero. Six or more letters throws IllegalArgumentException.

Hence the correct pattern you should use is this:

yyyy-MM-dd'T'HH:mm:ssZZZZZ

The snippet below works correctly and prints out "{OffsetSeconds=28800, InstantSeconds=1672037522},ISO resolved to 2022-12-26T14:52:02":

fun main() {
  val datetimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ssZZZZZ")
  println(datetimeFormatter.parse("2022-12-26T14:52:02 08:00"))
}

CodePudding user response:

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.

  • Related