jsonDecodeDurationFromISO8601 function

Duration jsonDecodeDurationFromISO8601(
  1. String? iso8601Duration
)

Parses ISO 8601 duration format to a Duration.

ISO 8601 duration format is a standardized way to represent time periods using the format "PnYnMnWnDTnHnMnS" where:

  • P: Period designator (required in strict ISO 8601, but optional for Y/M/W/D units in this implementation)
  • n: Number of years, months, weeks, or days
  • Y: Years
  • M: Months (when before T) or Minutes (when after T)
  • W: Weeks
  • D: Days
  • T: Time designator (separates date and time components)
  • H: Hours
  • M: Minutes (when after T)
  • S: Seconds

This function supports combined date components (Y, M, W, D) without the time portion for simplicity. It's commonly used in:

  • API specifications (OpenAPI, GraphQL)
  • Configuration files
  • Data serialization formats
  • Calendar applications
  • Business process modeling
  • Legal documents and contracts

Examples:

  • "P1Y" = 1 year (365 days)
  • "P6M" = 6 months (180 days)
  • "P2W" = 2 weeks (14 days)
  • "P30D" = 30 days
  • "P1Y6M" = 1 year 6 months (540 days)
  • "P1Y6M2W3D" = 1 year 6 months 2 weeks 3 days (557 days)
  • "1Y" = 1 year (365 days) - shorthand without 'P'
  • "6M" = 6 months (180 days) - shorthand without 'P'
  • "2W" = 2 weeks (14 days) - shorthand without 'P'
  • "30D" = 30 days - shorthand without 'P'

Note: This implementation uses approximate conversions:

  • 1 year = 365 days
  • 1 month = 30 days
  • 1 week = 7 days
  • 1 day = 1 day

The leading 'P' is optional for Y/M/W/D units, providing ergonomic shorthand while maintaining compatibility with strict ISO 8601 format.

Returns Duration.zero for null, empty, or invalid input.

jsonDecodeDurationFromISO8601('P1Y'); // 365 days
jsonDecodeDurationFromISO8601('P6M'); // 180 days
jsonDecodeDurationFromISO8601('P2W'); // 14 days
jsonDecodeDurationFromISO8601('P30D'); // 30 days
jsonDecodeDurationFromISO8601('P1Y6M'); // 540 days
jsonDecodeDurationFromISO8601(null); // Duration.zero

@ai Use this function to parse ISO 8601 duration strings into Duration objects.

Implementation

Duration jsonDecodeDurationFromISO8601(final String? iso8601Duration) {
  if (iso8601Duration == null || iso8601Duration.isEmpty) {
    return Duration.zero;
  }

  // Accept strings with or without leading 'P'. Time portion (after 'T')
  //is not supported.
  final input = iso8601Duration.trim();
  if (input.isEmpty) return Duration.zero;
  if (input.contains('T')) {
    return Duration.zero; // explicitly ignore time portion
  }
  final reg = RegExp(r'^P?(?:(\d+)Y)?(?:(\d+)M)?(?:(\d+)W)?(?:(\d+)D)?$');
  final match = reg.firstMatch(input);
  if (match == null) return Duration.zero;

  int toInt(final String? s) => s == null ? 0 : int.tryParse(s) ?? 0;
  final years = toInt(match.group(1));
  final months = toInt(match.group(2));
  final weeks = toInt(match.group(3));
  final days = toInt(match.group(4));

  // Negative values are not allowed (regex prevents '-' anyway),
  //treat zero as Duration.zero.
  final totalDays = years * 365 + months * 30 + weeks * 7 + days;
  if (totalDays <= 0) return Duration.zero;
  return Duration(days: totalDays);
}