Skip to content

SeriesResource.airTime is a wall-clock time parsed as a Duration; "21:00" becomes 21 minutes #36

Description

@egg82

What happened?

SeriesResource.airTime is a wall-clock time, but it's typed as a Duration and parsed with DurationParser. Sonarr sends airTime as "21:00" meaning 9pm; DurationParser reads that as minutes-and-seconds, so once the groupCount guards are fixed it comes out as PT21M — 21 minutes.

Both readings of "21:00" are legitimate, which is the problem: for a runTime it really is 21 minutes, and for an airTime it's 9pm. One parser can't tell them apart, because the ambiguity is in the field's meaning rather than in the string.

What did you expect to happen?

airTime to come back as a time of day. "21:00" → 21:00 local, not a 21-minute duration.

Steps to reproduce

  1. mvn -pl Lib install (or use Lib/target/classes)
  2. Call DurationParser.parse("21:00", true)
  3. Result is PT-24H-39M today; PT21M once the guard bug is fixed. Either way it isn't 9pm.

Relevant logs or screenshots

parse("21:00")      = PT-24H-39M    (current; PT21M with the guards fixed)
parse("5:30")       = PT-24H-54M-30S
parse("1:02:03:04") = PT99H1M2S     (4d 3h 1m 2s)

Suspected root cause

Type confusion rather than a parsing bug — SeriesResource.java:25 declares private final Duration airTime; and :73 fills it from DurationParser.get. A LocalTime and a separate parser alongside the existing InstantParser would keep the two meanings apart, and airTime() would stop handing plugins a Duration that means a clock time.

Two smaller things in the same area, both only visible once the guards are fixed, and I'm less sure about these:

  • Three- and four-field values read mm:ss:hh and mm:ss:hh:dd, since groups map left-to-right from the first field. Two-field mm:ss matches the usual short-duration convention, but the longer forms are normally hh:mm:ss / dd:hh:mm:ss. Anchoring the assignment from the right, based on how many groups actually matched, would give the shifting behaviour.
  • Whether any runTime/duration field actually arrives in colon form is worth confirming before changing that — the *arr APIs send most of them as integer minutes, which take the parseInt path and never reach this block.

Environment

  • Fetcharr version: repo at 23b0e6c261137afe1a7d5badd983b88629833e18 (main)
  • Not running the app — called the built Lib/target/classes directly
  • JDK 25 (class files are 21), tinylog + unirest from ~/.m2
  • OS: AlmaLinux 9

Other context

Separate from #35, though they touch the same block — fixing the guards makes this one visible rather than fixing it.

Claude Code

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions