formatRelativeTime function
Formats relative time intervals (e.g. "just now", "5 minutes ago", "in 2 hours", "yesterday") in pure Dart.
Evaluates date relative to relativeTo (which defaults to DateTime.now()).
If numeric is true, produces numeric representations like "1 day ago" instead of "yesterday".
Supports translations for English, French, German, Spanish, Japanese, and Chinese, falling back to English.
final fiveMinAgo = DateTime.now().subtract(const Duration(minutes: 5));
formatRelativeTime(fiveMinAgo, locale: 'en-US'); // "5 minutes ago"
formatRelativeTime(fiveMinAgo, locale: 'fr-FR'); // "il y a 5 minutes"
See also:
- BloomDateTimeClientI18n.toLocalizedRelativeTime, extension method on DateTime.
- localizedRelativeTime, top-level convenience shorthand.
Implementation
String formatRelativeTime(
DateTime date, {
DateTime? relativeTo,
String? locale,
bool numeric = false,
}) {
final now = relativeTo ?? DateTime.now();
final diff = now.difference(date);
final isPast = !diff.isNegative;
final absSeconds = diff.inSeconds.abs();
final loc = (locale ?? BloomI18n.instance.locale.value).replaceAll('_', '-').toLowerCase();
final lang = loc.split('-').first;
if (absSeconds < 45) {
if (lang == 'fr') return 'à l\'instant';
if (lang == 'de') return 'gerade eben';
if (lang == 'es') return 'hace un momento';
if (lang == 'ja') return 'たった今';
if (lang == 'zh') return '刚刚';
return 'just now';
}
final minutes = (absSeconds / 60).round();
if (minutes < 45) {
return _formatRelativeUnit(minutes, 'minute', isPast, lang);
}
final hours = (absSeconds / 3600).round();
if (hours < 22) {
return _formatRelativeUnit(hours, 'hour', isPast, lang);
}
final days = (absSeconds / 86400).round();
if (days == 1 && !numeric) {
if (isPast) {
if (lang == 'fr') return 'hier';
if (lang == 'de') return 'gestern';
if (lang == 'es') return 'ayer';
if (lang == 'ja') return '昨日';
if (lang == 'zh') return '昨天';
return 'yesterday';
} else {
if (lang == 'fr') return 'demain';
if (lang == 'de') return 'morgen';
if (lang == 'es') return 'mañana';
if (lang == 'ja') return '明日';
if (lang == 'zh') return '明天';
return 'tomorrow';
}
}
if (days < 26) {
return _formatRelativeUnit(days, 'day', isPast, lang);
}
final months = (days / 30).round();
if (months < 11) {
return _formatRelativeUnit(months, 'month', isPast, lang);
}
final years = (days / 365).round();
return _formatRelativeUnit(years, 'year', isPast, lang);
}