jsonEncodeDurationToISO8601 function

String jsonEncodeDurationToISO8601(
  1. Duration duration
)

Converts a Duration to ISO 8601 duration format string.

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

  • P: Period designator (required)
  • 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 converts a Duration to the most appropriate ISO 8601 format by prioritizing larger units (years, months, weeks, days) for readability. It's commonly used in:

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

Examples:

  • Duration(days: 365) → "P1Y"
  • Duration(days: 180) → "P6M"
  • Duration(days: 14) → "P2W"
  • Duration(days: 30) → "P30D"
  • Duration(days: 540) → "P1Y6M"

Note: This implementation uses approximate conversions:

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

Returns "P0D" for zero or negative durations.

jsonEncodeDurationToISO8601(Duration(days: 365)); // "P1Y"
jsonEncodeDurationToISO8601(Duration(days: 180)); // "P6M"
jsonEncodeDurationToISO8601(Duration(days: 14)); // "P2W"
jsonEncodeDurationToISO8601(Duration(days: 30)); // "P30D"
jsonEncodeDurationToISO8601(Duration.zero); // "P0D"

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

Implementation

String jsonEncodeDurationToISO8601(final Duration duration) {
  if (duration.isNegative || duration.inDays == 0) {
    return 'P0D';
  }

  final totalDays = duration.inDays;

  // Calculate years (365 days each)
  final years = totalDays ~/ 365;
  final remainingDaysAfterYears = totalDays % 365;

  // Calculate months (30 days each) from remaining days
  final months = remainingDaysAfterYears ~/ 30;
  final remainingDaysAfterMonths = remainingDaysAfterYears % 30;

  // Calculate weeks (7 days each) from remaining days
  final weeks = remainingDaysAfterMonths ~/ 7;
  final remainingDaysAfterWeeks = remainingDaysAfterMonths % 7;

  // Build the ISO 8601 string
  final buffer = StringBuffer('P');

  if (years > 0) {
    buffer.write('${years}Y');
  }

  if (months > 0) {
    buffer.write('${months}M');
  }

  if (weeks > 0) {
    buffer.write('${weeks}W');
  }

  if (remainingDaysAfterWeeks > 0) {
    buffer.write('${remainingDaysAfterWeeks}D');
  }

  // If no components were added, return P0D
  if (buffer.length == 1) {
    return 'P0D';
  }

  return buffer.toString();
}