The Problem Every Flutter Developer Faces
You're building a chat app. You need to show "2 hours ago" next to each message. Simple enough — you write a quick function:
dart
String getTimeAgo(DateTime date) {
final diff = DateTime.now().difference(date);
if (diff.inSeconds < 60) return '${diff.inSeconds} seconds ago';
if (diff.inMinutes < 60) return '${diff.inMinutes} minutes ago';
if (diff.inHours < 24) return '${diff.inHours} hours ago';
return '${diff.inDays} days ago';
}
Works great. Ship it.
Then your designer asks for "Yesterday" instead of "24 hours ago". Then your PM wants "Last week". Then a new requirement — the app needs Hindi support. Then you need a date range picker for the analytics dashboard. Then holiday-aware working day calculations for the HR module.
Before you know it, you have 3 packages in your pubspec and 200 lines of scattered utility code — duplicated across every project.
I've been there. That's exactly why I built smart_date_formatter.
What Is smart_date_formatter?
smart_date_formatter is a zero-dependency Flutter package that handles everything DateTime-related in one place.
yaml
dependencies:
smart_date_formatter: ^2.6.0
That's it. No intl. No timeago. No manual utility functions.
Feature 1 — Relative Time That Actually Makes Sense
dart
DateTime.now().subtract(Duration(seconds: 5)).timeAgo // "Just now"
DateTime.now().subtract(Duration(minutes: 25)).timeAgo // "25 minutes ago"
DateTime.now().subtract(Duration(days: 1)).timeAgo // "Yesterday"
DateTime.now().subtract(Duration(days: 9)).timeAgo // "Last week"
DateTime.now().add(Duration(days: 1)).timeAgo // "Tomorrow"
DateTime.now().add(Duration(days: 4)).timeAgo // "in 4 days"
Not just "24 hours ago" — actual human-readable strings that your users will understand.
Feature 2 — Custom Format Patterns
No more depending on intl just for date formatting:
dart
DateTime.now().format('dd-MM-yyyy') // "22-08-2026"
DateTime.now().format('EEE, dd MMM yyyy') // "Sat, 22 Aug 2026"
DateTime.now().format('hh:mm a') // "11:30 PM"
DateTime.now().toReadable // "Saturday, 22 August 2026"
DateTime.now().toISO // "2026-08-22T23:30:00"
Feature 3 — 16 Languages Out of the Box 🌍
This is where it gets interesting. Most date packages support English only. smart_date_formatter supports 16 languages — including 9 Indian languages:
dart
date.timeAgoIn(SdfLocale.hi) // "2 घंटे पहले" Hindi
date.timeAgoIn(SdfLocale.mr) // "2 तास पूर्वी" Marathi
date.timeAgoIn(SdfLocale.gu) // "2 કલાક પહેલાં" Gujarati
date.timeAgoIn(SdfLocale.bn) // "2 ঘন্টা আগে" Bengali
date.timeAgoIn(SdfLocale.ta) // "2 மணி நேரம் முன்பு" Tamil
date.timeAgoIn(SdfLocale.te) // "2 గంటలు క్రితం" Telugu
date.timeAgoIn(SdfLocale.kn) // "2 ಗಂಟೆಗಳ ಹಿಂದೆ" Kannada
date.timeAgoIn(SdfLocale.pa) // "2 ਘੰਟੇ ਪਹਿਲਾਂ" Punjabi
date.timeAgoIn(SdfLocale.de) // "2 Stunden her" German
date.timeAgoIn(SdfLocale.ja) // "2 時間前" Japanese
Feature 4 — Natural Language Parser 🔍
This one surprised even me when I built it. You can parse natural language strings into DateTime:
dart
SmartParser.parse("tomorrow") // DateTime
SmartParser.parse("next monday") // DateTime
SmartParser.parse("in 3 days") // DateTime
SmartParser.parse("first monday of month") // DateTime
SmartParser.parse("2 mondays ago") // DateTime
SmartParser.parse("end of this month") // DateTime
SmartParser.parse("q2") // DateTime (April)
// And in Indian languages!
SmartParser.parse("कल") // Hindi tomorrow
SmartParser.parse("उद्या") // Marathi tomorrow
SmartParser.parse("நாளை") // Tamil tomorrow
SmartParser.parse("আগামীকাল") // Bengali tomorrow
SmartParser.parse("આવતી કાલ") // Gujarati tomorrow
Feature 5 — Flutter Widgets
TimeAgoText — Auto Refreshing
dart
// No setState. No Timer. Just works.
TimeAgoText(
date: message.sentAt,
locale: SdfLocale.hi,
refreshRate: Duration(seconds: 30),
)
CountdownText — Live Countdown
dart
CountdownText(
target: saleEndsAt,
format: '{hh}:{mm}:{ss}',
finishedText: 'Sale Ended!',
onFinished: () => hideSaleBanner(),
)
SmartCalendar — Full Featured Calendar
dart
SmartCalendar(
events: myEvents,
initialView: CalendarView.month, // month/week/day/agenda
themeMode: ThemeMode.dark,
showWeekNumbers: true,
rangeSelectionMode: true,
markerStyle: EventMarkerStyle.both,
onDateSelected: (date, events) => print(date),
onRangeSelected: (start, end) => print('$start → $end'),
cellBuilder: (date, events, isSelected, isToday) {
// Fully custom cell UI
return MyCustomCell(date: date);
},
)
SmartDateField — Smart Date Input
dart
SmartDateField(
label: 'Due Date',
enableTimePicker: true,
enableNaturalLanguage: true, // type "next monday"!
showSuggestions: true,
validator: (date) {
if (date == null) return 'Required';
if (date.isPast) return 'Must be future date';
return null;
},
onChanged: (date) => setState(() => _dueDate = date),
)
SmartDateRangePicker — Visual Range Picker
dart
SmartDateRangePicker(
primaryColor: Colors.teal,
rangeHighlightColor: Colors.teal.withOpacity(0.15),
weekendColor: Colors.orange,
cellBorderRadius: 20,
presets: [
DateRangePreset.last7Days,
DateRangePreset.last30Days,
DateRangePreset.thisMonth,
],
onRangeSelected: (range) {
print('${range.start} → ${range.end}');
print('${range.days} days');
print(range.contains(DateTime.now())); // true
},
)
Feature 6 — Analytics Tools 📊
Streak Calculator
dart
// Perfect for habit trackers
StreakCalculator.currentStreak(dates) // 7
StreakCalculator.longestStreak(dates) // 21
StreakCalculator.isTodayCompleted(dates) // true
StreakCalculator.completionRate(
dates,
start: monthStart,
end: monthEnd,
) // 0.83
Date Grouper
dart
`DateGrouper.byMonth(activityDates)
// {'2026-06': [...], '2026-07': [...]}
DateGrouper.mostActiveWeekday(dates) // "Monday"
DateGrouper.mostActiveHour(dates) // 14
DateGrouper.averageGap(dates) // Duration(days: 2)
Feature 7 — Holiday-Aware Calculations 🎄
dart
final holidays = HolidayHelper.indianHolidays(2026);
// Is today a holiday?
DateTime.now().isHoliday(holidays: holidays)
// Add 5 working days, skipping holidays
date.addWorkingDaysWithHolidays(5, holidays: holidays)
// Working days between two dates
HolidayHelper.workingDaysBetween(
projectStart,
deadline,
holidays: holidays,
)`
Feature 8 — Date Range Helper 🗄️
Perfect for database queries and analytics filters:
dart
`final range = DateRangeHelper.thisMonth();
// SQLite
await db.query(
'orders',
where: 'created_at BETWEEN ? AND ?',
whereArgs: [
range.start.toIso8601String(),
range.end.toIso8601String(),
],
);
// Available ranges
DateRangeHelper.today()
DateRangeHelper.thisWeek()
DateRangeHelper.lastNDays(30)
DateRangeHelper.quarter(2)
DateRangeHelper.currentQuarter()`
Before vs After
Before:
yaml
dependencies:
timeago: ^3.6.0
intl: ^0.18.0
# + 200 lines of manual utility code
# + copy-pasted across every project
After:
yaml
dependencies:
smart_date_formatter: ^2.6.0
# done.
The Numbers
📦 Zero external dependencies
🌍 16 languages supported
🧪 300+ tests
⭐ 160/160 pub points (perfect score)
📱 All platforms: Android, iOS, Web, Windows, macOS, Linux
🔄 20+ versions released
Try It Live
Before adding it to your project, try every feature interactively:
👉 Live Playground
No installation. No setup. Just open and explore.
Get Started
bash
dart pub add smart_date_formatter
dart
import 'package:smart_date_formatter/smart_date_formatter.dart';
// That's it. Start using it.
DateTime.now().timeAgo // "Just now"
DateTime.now().calendar // "Today"
DateTime.now().toReadable // "Saturday, 22 August 2026"
Resources
📦 pub.dev: pub.dev
💻 GitHub: Github
🌐 Live Playground: Live
🐛 Issues: GitHub Issues
If this saved you time, please ⭐ the repo and 👍 like it on pub.dev — it helps other Flutter developers discover it.
— Harsh Yadav, Flutter Developer
Top comments (0)