convertDaysToYearsAndMonths static method

String? convertDaysToYearsAndMonths(
  1. int? days, {
  2. bool includeRemainingDays = false,
})

Converts an integer representing days into a human-readable string format of years, months, and optionally remaining days.

This method uses average values that account for leap years:

  • Average days per year: 365.25 (accounts for leap years)
  • Average days per month: 30.4375 (365.25 / 12)

Args: days (int?): The number of days to convert. Returns null if null or < 1. includeRemainingDays (bool): If true, includes remaining days in the output when they don't form a complete month. Defaults to false.

Returns: String?: A human-readable string representing the duration, or null if days is null or less than 1.

Example:

convertDaysToYearsAndMonths(400); // '1 year and 1 month'
convertDaysToYearsAndMonths(365); // '1 year'
convertDaysToYearsAndMonths(45); // '1 month'
convertDaysToYearsAndMonths(45, includeRemainingDays: true); // '1 month and 14 days'
convertDaysToYearsAndMonths(10); // '0 days'
convertDaysToYearsAndMonths(10, includeRemainingDays: true); // '10 days'

Implementation

static String? convertDaysToYearsAndMonths(
  int? days, {
  bool includeRemainingDays = false,
}) {
  if (days == null || days < 1) {
    return null;
  }

  // Calculate years using average days per year (365.25 to account for leap years)
  final int years = (days / _avgDaysPerYear).floor();
  double remainingDays = days - (years * _avgDaysPerYear);

  // Calculate months from remaining days using average days per month
  final int months = (remainingDays / _avgDaysPerMonth).floor();
  remainingDays = remainingDays - (months * _avgDaysPerMonth);

  // Round remaining days
  final int remainingDaysInt = remainingDays.round();

  // Determine whether to use singular or plural forms
  final String yearStr = (years == 1) ? 'year' : 'years';
  final String monthStr = (months == 1) ? 'month' : 'months';
  final String dayStr = (remainingDaysInt == 1) ? 'day' : 'days';

  // Build result parts
  final List<String> parts = <String>[];

  if (years > 0) {
    parts.add('$years $yearStr');
  }

  if (months > 0) {
    parts.add('$months $monthStr');
  }

  if (includeRemainingDays && remainingDaysInt > 0) {
    parts.add('$remainingDaysInt $dayStr');
  }

  // Handle case where we have no years or months
  if (parts.isEmpty) {
    if (includeRemainingDays && remainingDaysInt > 0) {
      return '$remainingDaysInt $dayStr';
    }
    return '0 days';
  }

  // Join parts with 'and' for readability
  if (parts.length == 1) {
    return parts[0];
  } else if (parts.length == 2) {
    return '${parts[0]} and ${parts[1]}';
  } else {
    // For 3 parts: "X years, Y months, and Z days"
    return '${parts[0]}, ${parts[1]}, and ${parts[2]}';
  }
}