Parsing ISO 8601 like duration in Luxon

I have duration string that looks like:

1:16.352

where 1 is minutes part, 16 is seconds part and 352 is millisecond part.

I wanted to use Duration.fromISOTime but I get:

{
  "reason": "unparsable",
  "explanation": "the input \"1:16.352\" can't be parsed as ISO 8601"
}

Is there a clean way of parsing such duration in Luxon?

3 thoughts on “Parsing ISO 8601 like duration in Luxon”

  1. Similarly to @VincenzoC I adjusted my input string:

    const Duration = luxon.Duration;
    
    var output;
    const durationInput = "1:16.352"
    
    if (durationInput.match(/:/g) || [].length === 1) {
      const semicolonLocation = durationInput.indexOf(":");
    
      if (semicolonLocation === 1) {
        output = "00:0" + durationInput;
      }
    
      if (semicolonLocation === 2) {
        output = "00:" + durationInput;
      }
    }
    
    console.log(Duration.fromISOTime(output));
    <script src="https://cdn.jsdelivr.net/npm/luxon@1.26.0/build/global/luxon.js"></script>
    Reply
  2. Duration.fromISOTime does not work since 1:16.352 is not an ISO 8601 time string, the hour part is missing (see ISO 8601 Times).

    A workaround to build a Luxon Duration object could be the following:

    const DateTime = luxon.DateTime;
    const Duration = luxon.Duration;
    
    const startOfHour = DateTime.local().startOf('hour').toMillis();
    const dt = DateTime.fromFormat("1:16.352", "m:ss.SSS"). toMillis();
    const dur = Duration.fromMillis(dt - startOfHour);
    console.log(dur.toFormat("m 'minute' s 'second' S 'millis'"));
    <script src="https://cdn.jsdelivr.net/npm/luxon@1.26.0/build/global/luxon.js"></script>
    Reply
  3. As I mentioned in the comments, you can use the fromObject static method combined with simply splitting the input into minutes, seconds, and milliseconds configuration options. In your case a trivial regular expression (\d+):(\d+)\.(\d+) should do the trick, no temporary dates or normalization required.

    const { Duration } = luxon;
    const durationInput = "1:16.352";
    
    const fromCustom = (input) => {
      const [, minutes, seconds, milliseconds ] = input.match(/(\d+):(\d+)\.(\d+)/);
        
      return Duration.fromObject({
        minutes, seconds, milliseconds
      });
    };
    
    console.log(fromCustom(durationInput));
    <script src="https://cdn.jsdelivr.net/npm/luxon@1.26.0/build/global/luxon.js"></script>
    Reply

Leave a Comment