0

I have a list of timed intervals given as strings in a CSV file.
For example, one has the value of "7:30" (7 minutes and 30 seconds).

Spark offers the DateType or the TimestampType, but it's not these ones that are interesting me, there.
At least, I have to treat this "7:30" value as a time (without date), and the best would be that it would be considered like a duration. But then, I don't know what is the best Java or Spark class to carry it.

But currently, my problem is that my code understands the string as a time in the day :

LocalTime.parse("7:30", DateTimeFormatter.ofPattern("m:ss"))

and fails with a DateTimeParseException whose message "Unable to obtain LocalTime from TemporalAccessor" is hinting that the parser cannot tell if it is in front of an AM or PM hour.

java.time.format.DateTimeParseException: Text '7:30' could not be parsed: Unable to obtain LocalTime from TemporalAccessor: {MilliOfSecond=0, SecondOfMinute=30, NanoOfSecond=0, MicroOfSecond=0, MinuteOfHour=7},ISO of type java.time.format.Parsed
  at java.base/java.time.format.DateTimeFormatter.createError(DateTimeFormatter.java:2017)
  at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1952)
  at java.base/java.time.LocalTime.parse(LocalTime.java:463)
  ... 96 elided

It would be perfect if it didn't bother about it... But well, it does. How can I circumvent the problem and adapt my code so that, for example, I can tell the parser that all the given times are AM?


But maybe I'm wrong. I should parse with a DateTimeFormatter, yes, but maybe into another java.time.* object than one of class LocalTime that is made for "hour of the day" and not for durations.

If it's the case, which one should I use instead?
And how can I create it from text parsing?

Marc Le Bihan
  • 2,308
  • 2
  • 23
  • 41
  • It looks like `Duration` doesn't support the format you want to parse and I'm not sure there is a ready to use formatter. However, you could try to split at the colon and parse the resulting substrings to long. Then feed those to `Duration.ofMinutes(...).plusSeconds(...)`. – Thomas Mar 15 '22 at 07:15
  • 1
    Currently, the nearest I can go is : convert to a LocalTime `LocalTime t = LocalTime.parse("07:30")`, then ask for the difference between this time and the 0 hour time : `Duration d = Duration.between(LocalTime.MIDNIGHT, t)`. It returns `println(t) => 07:30`, `println(d) => PT7H30M`. But I wonder if it's a good way to do things. – Marc Le Bihan Mar 15 '22 at 07:34
  • 2
    Hint: `LocalTime.MIDNIGHT` (or `.MIN`) instead of `.of(0,0)` – user16320675 Mar 15 '22 at 07:36
  • You could do that as well but might run into problems if the duration is larger than an hour. Assuming your format will always be `minutes:seconds` could there be durations like `172:59` or would those then include hours as well? – Thomas Mar 15 '22 at 07:41
  • @Thomas You are right, and it's another problem that, first : as soon as I replace `LocalTime.parse("07:30")` by a `LocalTime.parse("07:30", , DateTimeFormatter.ofPattern("mm:ss"))` it fails with the message `"Unable to obtain LocalTime from TemporalAccessor"` I'd wrote, and second that I can't tell in advance if I will receive hours or minutes being right padded with zeroes or not (but it seems not : I'm receiving `"7:30"` instead of `"07:30"`). I think it will for a complemental topic on SO, because creating a datetime format that handles many cases isn't easy. – Marc Le Bihan Mar 15 '22 at 07:51
  • Can this be fitted to answer your question? [How to convert HH:mm:ss.SSS to milliseconds?](https://stackoverflow.com/questions/8826270/how-to-convert-hhmmss-sss-to-milliseconds) I am immodest enough to recommend that you look at the two options that I present in [my answer there](https://stackoverflow.com/a/70224294/5772882). Under no circumstances use `SimpleDateFormat` (presented in a couple of answers). – Ole V.V. Mar 15 '22 at 08:00
  • Using java.time as you already tried: `Duration.parse("7:30".replaceFirst("^(\\d+):(\\d{2})$", "PT$1M$2S"))` yields a `java.time.Duration`. It prints in ISO 8601 format, `PT7M30S` for 7 minutes 30 seconds. – Ole V.V. Mar 15 '22 at 08:06
  • If you want the detour via `LocalTime` (which I would not want), use the following formatter: `new DateTimeFormatterBuilder().appendPattern("m:ss").parseDefaulting(ChronoField.HOUR_OF_DAY, 0).toFormatter(Locale.ROOT)`. It will not work for minutes greater than 59. – Ole V.V. Mar 15 '22 at 08:13
  • *Currently, the nearest I can go is* It also gives you 7 hours 30 minutes where I think you wanted 7 minutes 30 seconds. – Ole V.V. Mar 15 '22 at 08:15
  • @OleV.V. I won't use any `split` or `regex` expression to parse the string received. I'm not responsible of their format and won't go into low level functions. No : the `PT7M30S` I get is the 7 min 30 seconds I'm willing to have. – Marc Le Bihan Mar 15 '22 at 08:19
  • I understand that. So my best suggestion is using [Time4J](http://time4j.net/) as in the first half of [the answer I linked to](https://stackoverflow.com/a/70224294/5772882). Liability: it’s an external dependency. – Ole V.V. Mar 15 '22 at 08:22

0 Answers0