duration Duration Parameter

Complete Guide to ICU Duration Formatting - Digital/Short/Long/Narrow Styles

Overview

The duration parameter type formats time durations such as seconds, minutes, and hours. Unlike date or time parameters which represent a point in time, duration parameters represent a length of time that can be displayed in various styles.

Basic Example

Content: "Video length: @{length}"

ICU Equivalent: "Video length: @{length, duration, style=short}"

Params:

{
  "paramName": "length",
  "type": "duration",
  "style": "short"
}

Expected Output:

JSON Structure

Duration parameters are defined in the params array with type: "duration" and specify the style option.

Duration Parameter Definition

{
  "paramName": "length",
  "type": "duration",
  "style": "short"
}

Style Options

Duration formatting supports different styles for localization:

Style Description Example Output
digital Digital clock format (HH:MM:SS) "01:02:03"
short Abbreviated format with conditional components "1h 2m 3s" or "2m 3s" or "3s"
long Same as short - abbreviated format with conditional components "1h 2m 3s" or "2m 3s" or "3s"
narrow Compact format with all components always shown "1h 2m 3s"
default Falls back to "short" style Varies based on value

⚠️ Important: Input Unit

Duration values are provided in seconds. The style determines how the value is formatted. A value of 3600 with style short will display as "1h".

Style Behavior Details

Digital Style

The digital style displays time in HH:MM:SS format with zero-padding:

3723 seconds → "01:02:03"
 3600 seconds → "01:00:00"
   65 seconds → "00:01:05"

Short/Long Style

The short and long styles show only non-zero components. If all components would be zero, the seconds are shown:

3723 seconds → "1h 2m 3s"
  120 seconds → "2m"
    0 seconds → "0s"

Narrow Style

The narrow style always shows all components with spaces between them:

3723 seconds → "1h 2m 3s"
  120 seconds → "0h 2m 0s"
    0 seconds → "0h 0m 0s"

Language Implementation Comparison

Different programming languages handle duration formatting with consistent style-based approaches.

Language digital short/long narrow Notes
TypeScript Limited to digital and basic "Xh Xm" format
JavaScript Limited to digital and basic "Xh Xm" format
Java Conditional display of components
Kotlin Conditional display of components
Swift Full support for all styles
Dart Limited to digital and basic "Xh Xm" format

Generated Code Implementation

Swift Implementation

The Swift implementation provides full support for all duration styles:

static func formatDuration(_ value: Int, _ p: I18NParam) -> String {
    let format = p.style ?? "short"
    let hours = value / 3600
    let minutes = (value % 3600) / 60
    let seconds = value % 60
    switch format {
    case "digital":
        return String(format: "%02d:%02d:%02d", hours, minutes, seconds)
    case "short", "long":
        var result = ""
        if hours > 0 { result += String(hours) + "h " }
        if minutes > 0 { result += String(minutes) + "m " }
        if seconds > 0 || result.isEmpty { result += String(seconds) + "s" }
        return result.trimmingCharacters(in: .whitespaces)
    case "narrow":
        return String(hours) + "h " + String(minutes) + "m " + String(seconds) + "s"
    default:
        return "\(value)"
    }
}

TypeScript Implementation

function formatDuration(value: number, p: any): string {
    const hours = Math.floor(value / 3600);
    const minutes = Math.floor((value % 3600) / 60);
    const secs = value % 60;
    const style = p?.style || "short";
    if (style === "digital") {
        return [hours, minutes, secs].map(n => String(n).padStart(2, "0")).join(":");
    }
    return hours + "h " + minutes + "m";
}

JavaScript Implementation

static formatDuration(value, p) {
    const hours = Math.floor(value / 3600);
    const minutes = Math.floor((value % 3600) / 60);
    const secs = value % 60;
    const style = p?.style || "short";
    if (style === "digital") {
        return [hours, minutes, secs].map(n => String(n).padStart(2, "0")).join(":");
    }
    return hours + "h " + minutes + "m";
}

Java Implementation

private static String formatDuration(int seconds, I18NParam p) {
    String style = p != null ? p.style : "short";
    int hours = seconds / 3600;
    int minutes = (seconds % 3600) / 60;
    int secs = seconds % 60;
    if ("digital".equals(style)) {
        return String.format("%02d:%02d:%02d", hours, minutes, secs);
    }
    if (hours > 0) {
        return String.format("%dh %dm", hours, minutes);
    }
    if (minutes > 0) {
        return String.format("%dm", minutes);
    }
    return String.format("%ds", secs);
}

Kotlin Implementation

fun formatDuration(seconds: Int, p: I18NParam): String {
    val style = p.style ?: "short"
    val hours = seconds / 3600
    val minutes = (seconds % 3600) / 60
    val secs = seconds % 60
    if (style == "digital") {
        return String.format("%02d:%02d:%02d", hours, minutes, secs)
    }
    if (hours > 0) {
        return "${hours}h ${minutes}m"
    }
    if (minutes > 0) {
        return "${minutes}m"
    }
    return "${secs}s"
}

Dart Implementation

static String formatDuration(int seconds, Map p) {
  final style = p['style'] ?? 'short';
  final hours = seconds ~/ 3600;
  final minutes = (seconds % 3600) ~/ 60;
  final secs = seconds % 60;
  if (style == 'digital') {
    return hours.toString().padLeft(2, '0') + ':' +
           minutes.toString().padLeft(2, '0') + ':' +
           secs.toString().padLeft(2, '0');
  }
  return hours.toString() + 'h ' + minutes.toString() + 'm';
}

Best Practices

✅ Do: Choose the Right Style for Your Use Case

Select the appropriate style based on the context:

⚠️ Don't: Rely on narrow Style Across All Languages

The narrow style is only fully supported in Swift. For other languages, use short or long to get conditional component display.

Complete Import Example

{
  "strings": [
    {
      "key": "video.duration",
      "translations": {
        "en-US": {
          "content": "The video is @{length, duration, style=short}",
          "params": [
            {
              "paramName": "length",
              "type": "duration",
              "style": "short"
            }
          ]
        },
        "zh-CN": {
          "content": "视频时长为@{length, duration, style=short}",
          "params": [
            {
              "paramName": "length",
              "type": "duration",
              "style": "short"
            }
          ]
        },
        "ja-JP": {
          "content": "動画時間は@{length, duration, style=short}です",
          "params": [
            {
              "paramName": "length",
              "type": "duration",
              "style": "short"
            }
          ]
        }
      }
    }
  ]
}

Video Timestamp Example

{
  "strings": [
    {
      "key": "video.timestamp",
      "translations": {
        "en-US": {
          "content": "Current position: @{pos, duration, style=digital}",
          "params": [
            {
              "paramName": "pos",
              "type": "duration",
              "style": "digital"
            }
          ]
        },
        "zh-CN": {
          "content": "当前进度:@{pos, duration, style=digital}",
          "params": [
            {
              "paramName": "pos",
              "type": "duration",
              "style": "digital"
            }
          ]
        }
      }
    }
  ]
}