Complete Guide to ICU Time Formatting - Locale-Aware Time Display
The time parameter type formats time values according to locale conventions. Different regions have distinct ways of representing times, including 12-hour vs 24-hour formats, AM/PM indicators, and varying levels of detail.
Content: "Meeting at @{time}"
Params:
{
"paramName": "time",
"type": "time",
"style": "medium",
"zoneId": "America/New_York"
}
Expected Output:
en-US → "Meeting at 3:30:00 PM"de-DE → "Meeting at 15:30:00"ja-JP → "Meeting at 15:30:00"The generator supports the following style values:
| Style | Output Format | Description | Example (24h locale) |
|---|---|---|---|
short |
HH:mm | Hours and minutes only | 15:30 |
medium |
HH:mm:ss | Hours, minutes and seconds | 15:30:00 |
long |
HH:mm:ss | Same as medium | 15:30:00 |
custom |
style value directly | Custom format string | Any custom pattern |
The time parameter is defined in the params array of your translation definition:
{
"paramName": "meetingTime",
"type": "time",
"style": "medium",
"zoneId": "America/New_York"
}
Available style values: short, medium, long, or any custom format string
Optional zoneId: IANA timezone identifier (e.g., "America/New_York", "Asia/Tokyo")
| Property | Type | Description | Default |
|---|---|---|---|
style |
string | Format style: "short", "medium", "long", or custom format | "HH:mm" (if empty) |
format |
string | Custom format string (used when style is empty/non-standard) | "HH:mm" |
zoneId |
string | IANA timezone identifier for timezone-aware formatting | none (local time) |
United States uses 12-hour format with AM/PM indicators:
{
"paramName": "eventTime",
"type": "time",
"style": "short"
}
Most European countries use 24-hour format without AM/PM:
{
"paramName": "eventTime",
"type": "time",
"style": "short"
}
Most Asian locales use 24-hour format:
United Kingdom uses 24-hour format similar to Europe:
Time formatting relies on the locale parameter passed to the formatting function. Without locale context, the system cannot determine whether to use 12-hour or 24-hour format. Always pass the appropriate locale when formatting times.
The zoneId parameter enables timezone-aware time formatting using IANA timezone identifiers:
{
"paramName": "meetingTime",
"type": "time",
"style": "medium",
"zoneId": "America/New_York"
}
Supported zoneId values include:
America/New_York - US Eastern TimeAmerica/Los_Angeles - US Pacific TimeEurope/London - UK TimeEurope/Paris - Central European TimeAsia/Tokyo - Japan TimeAsia/Shanghai - China TimeUTC - Coordinated Universal TimeDifferent programming languages handle time formatting with varying levels of ICU support.
| Language | 12h/24h Support | AM/PM Support | Timezone Support | Notes |
|---|---|---|---|---|
| TypeScript | ✅ | ✅ | ✅ | Full ICU time formatting via Intl.DateTimeFormat with caching |
| JavaScript | ✅ | ✅ | ✅ | Full ICU time formatting via Intl.DateTimeFormat |
| Java | ✅ | ✅ | ✅ | Uses DateTimeFormatter with locale |
| Kotlin | ✅ | ✅ | ✅ | Uses DateTimeFormatter with locale |
| Swift | ✅ | ✅ | ✅ | Uses DateFormatter with locale and timezone |
| Python | ✅ | ✅ | ✅ | Uses datetime with locale via Babel |
| Go | ✅ | ✅ | ✅ | Uses time.Time with LoadLocation |
| Rust | ✅ | ✅ | ✅ | Uses chrono with locale support |
| Dart | ✅ | ✅ | ✅ | Uses DateFormat from intl package |
The generated code uses Intl.DateTimeFormat for locale-aware time formatting with caching:
function formatTime(value: Date, p: any, locale: string): string {
const date = value instanceof Date ? value : new Date(value);
const style = p?.style || "";
const zoneId = p?.zoneId;
const cacheKey = locale + "_" + style + "_" + (zoneId || "");
if (!(_timeFormatCache as any)[cacheKey]) {
const intlOptions: Intl.DateTimeFormatOptions = {};
if (zoneId) { intlOptions.timeZone = zoneId; }
if (style === "short") {
(_timeFormatCache as any)[cacheKey] = new Intl.DateTimeFormat(locale, { hour: "2-digit", minute: "2-digit", ...intlOptions });
} else {
(_timeFormatCache as any)[cacheKey] = new Intl.DateTimeFormat(locale, { hour: "2-digit", minute: "2-digit", second: "2-digit", ...intlOptions });
}
}
return (_timeFormatCache as any)[cacheKey].format(date);
}
The generated code uses DateFormatter with format string and timezone support:
static func formatTime(_ value: Any, _ p: I18NParam) -> String {
var format = ""
let style = p.style ?? ""
let zoneId = p.zoneId
if !style.isEmpty {
switch style {
case "short": format = "HH:mm"
case "medium", "long": format = "HH:mm:ss"
default: format = style
}
} else {
format = p.format ?? "HH:mm"
}
if let date = value as? Date {
return getDateFormatter(format, zoneId).string(from: date)
}
return "\(value)"
}
Choose the appropriate time style based on the use case:
Never hardcode a specific time format like "HH:mm" or "h:mm a". Always use the style parameter and let the locale determine the actual display pattern.
{
"strings": [
{
"key": "meeting.schedule",
"translations": {
"en-US": {
"content": "Meeting scheduled for @{startTime}",
"params": [
{
"paramName": "startTime",
"type": "time",
"style": "medium",
"zoneId": "America/New_York"
}
]
},
"de-DE": {
"content": "Besprechung geplant für @{startTime}",
"params": [
{
"paramName": "startTime",
"type": "time",
"style": "medium",
"zoneId": "Europe/Berlin"
}
]
},
"ja-JP": {
"content": "会議は@{startTime}に予定されています",
"params": [
{
"paramName": "startTime",
"type": "time",
"style": "medium",
"zoneId": "Asia/Tokyo"
}
]
}
}
}
]
}
When displaying times across timezones:
zoneId parameter when timezone awareness is important