📅 DateTime Helpers for Flutter
A powerful, modular, zero-dependency date/time library for Flutter
Pure Dart • Zero Dependencies • 7 Languages • 100+ Functions • Fully Modular
Features • Installation • Quick Start • Documentation • Examples

✨ Highlights
// 🌍 Multi-language support out of the box
DateFormatters.formatDateLong(DateTime.now()); // "December 1, 2025"
DateFormatters.formatDateLong(DateTime.now(), 'es_ES'); // "1 de Diciembre de 2025"
DateFormatters.formatDateLong(DateTime.now(), 'ar_SA'); // "1 ديسمبر 2025"
// ⏰ Smart relative time
RelativeTime.getRelativeTime(twoHoursAgo); // "2 hours ago"
RelativeTime.getRelativeTime(tomorrow, 'fr_FR'); // "dans 1 jour"
// 🧠 Context-aware formatting
SmartFormatters.formatSmart(DateTime.now()); // "Today at 2:30 PM"
SmartFormatters.formatSmart(yesterday); // "Yesterday at 2:30 PM"
// 🔢 Advanced calculations
DateCalculations.addBusinessDays(DateTime.now(), 5); // Skips weekends
DateCalculations.calculateAge(birthDate); // Age in years
🎯 Why Choose This Library?
| Feature | This Library | Others |
|---|---|---|
| 📦 Dependencies | ✅ Zero | ❌ External packages |
| 🌍 Languages | ✅ 7 built-in | ⚠️ Requires setup |
| 🧩 Modular | ✅ Import what you need | ❌ Monolithic |
| ⚡ Performance | ✅ Lightweight (<50KB) | ⚠️ Heavy packages |
| 🎨 Customizable | ✅ Pure Dart, modify easily | ⚠️ Limited |
| 📱 Platforms | ✅ All (Web, Mobile, Desktop) | ⚠️ Platform-specific |
| 🔧 Maintenance | ✅ No version conflicts | ⚠️ Breaking changes |
🚀 Features
📅 Date Formatting
- 14+ format functions - Short, medium, long, full, custom
- Multi-language - 7 languages with proper localization
- Custom patterns -
yyyy-MM-dd, ISO 8601, and more - Date ranges - Smart range formatting
- Ordinal dates - "1st", "2nd", "3rd" in English
⏰ Time Formatting
- 12/24-hour formats - With or without seconds
- Combined date/time - Multiple combined formats
- Milliseconds support - For precise timing
- Flexible display - AM/PM, military time, etc.
🔍 Date Comparisons
- 45+ comparison methods - Comprehensive date/time checks
- Smart checks - isToday, isYesterday, isTomorrow
- Period checks - isThisWeek, isThisMonth, isThisYear, isLastWeek, isNextWeek
- Weekday checks - isMonday through isSunday, isWeekend, isWeekday
- Time of day - isMorning, isAfternoon, isEvening, isNight
- Range checks - isBetween, isWithinDays, isWithinWeeks, isWithinMonths
- Relative checks - isPast, isFuture
- Precision checks - isSameHour, isSameMinute
- Period checks - isFirstHalfOfMonth, isSecondHalfOfMonth, quarter checks
- Leap year - isLeapYear, isLeapYearDate
🧮 Date Calculations
- 45+ calculation methods - Comprehensive date/time arithmetic
- Period boundaries - Start/end of day, week, month, year, quarter, hour, minute
- Business days - Add, subtract, count (skips weekends)
- Age calculation - From birthdate with proper handling
- Date arithmetic - Add/subtract years, months, weeks, days
- Month arithmetic - Handles edge cases (Jan 31 + 1 month = Feb 28)
- Date differences - Days/weeks/months/years between dates, daysUntil, daysSince
- Rounding utilities - roundToHour, roundToDay
- Weekday utilities - getNthWeekdayOfMonth, getLastWeekdayOfMonth, getNextWeekday
- Leap year support - Accurate calculations
- Week numbers - ISO week number calculation
- Timezone utilities - UTC conversion, offset formatting
- Utility functions - clamp, min, max for date comparisons
⏱️ Relative Time
- Past/Future - "2 hours ago", "in 3 days"
- Multi-language - Relative time in 5 languages
- Short format - "2h", "3d" for compact UI
- Duration formatting - Pretty duration strings
- Countdown - Time remaining to target date
- Verbose mode - "2 hours, 30 minutes" format
🎨 Smart Features
- Context-aware formatting - Adapts to date proximity
- Flexible parsing - Parse multiple date formats
- Date validation - Check if string is valid date
- File-safe formatting - For filenames (no special chars)
- Custom patterns - Extend easily for your needs
🌍 Supported Languages
- 🇬🇧 English (
en,en_US,en_GB) - 🇪🇸 Spanish (
es,es_ES) - 🇫🇷 French (
fr,fr_FR) - 🇩🇪 German (
de,de_DE) - 🇸🇦 Arabic (
ar,ar_SA) - RTL support - 🇯🇵 Japanese (
ja,ja_JP) - 🇨🇳 Chinese (
zh,zh_CN)
📦 Installation
Add this to your package's pubspec.yaml file:
dependencies:
save_points_intl: ^1.1.0
Then install it:
flutter pub get
Import
import 'package:save_points_intl/save_points_intl.dart';
// Or import specific modules
import 'package:save_points_intl/save_points_intl_date_formatters.dart';
import 'package:save_points_intl/save_points_intl_time_formatters.dart';
No external dependencies required! This package is 100% pure Dart with zero dependencies.
Package Structure
The package follows a modular architecture - import only what you need:
// Import everything (recommended for most use cases)
import 'package:save_points_intl/save_points_intl.dart';
// Or import specific modules to reduce bundle size
import 'package:save_points_intl/save_points_intl_date_formatters.dart';
import 'package:save_points_intl/save_points_intl_time_formatters.dart';
import 'package:save_points_intl/save_points_intl_date_comparisons.dart';
import 'package:save_points_intl/save_points_intl_date_calculations.dart';
import 'package:save_points_intl/save_points_intl_relative_time.dart';
import 'package:save_points_intl/save_points_intl_smart_formatters.dart';
import 'package:save_points_intl/save_points_intl_date_parsers.dart';
⚡ Quick Start
1. Import the Library
// Import everything (recommended)
import 'package:save_points_intl/save_points_intl.dart';
// Or import specific modules
import 'package:save_points_intl/save_points_intl_date_formatters.dart';
import 'package:save_points_intl/save_points_intl_time_formatters.dart';
2. Use It!
final now = DateTime.now();
// Date formatting
print(DateFormatters.formatDateLong(now)); // "December 1, 2025"
// Time formatting
print(TimeFormatters.formatTime12Hour(now)); // "2:30 PM"
// Relative time
final twoHoursAgo = now.subtract(Duration(hours: 2));
print(RelativeTime.getRelativeTime(twoHoursAgo)); // "2 hours ago"
// Date comparisons
if (DateComparisons.isToday(now)) {
print('It\'s today!');
}
// Date calculations
final nextWeek = DateCalculations.addBusinessDays(now, 5);
print(DateFormatters.formatDateMedium(nextWeek)); // Next business week
📚 Documentation
📖 Complete Guides
- EXAMPLES.md (1,286 lines) - Comprehensive examples with real-world use cases
- QUICK_START.md - Get started in 5 minutes
- MIGRATION_GUIDE.md - Upgrade from single-file version
- LIB_RECAP.md - Complete technical overview
- LIBRARY_STATUS.md - Current status & verification
📋 Quick Reference
Date Formatting Functions (14+)
DateFormatters.formatDateShort(date); // "12/1/2025"
DateFormatters.formatDateMedium(date); // "Dec 1, 2025"
DateFormatters.formatDateLong(date); // "December 1, 2025"
DateFormatters.formatDateFull(date); // "Monday, December 1, 2025"
DateFormatters.formatYear(date); // "2025"
DateFormatters.formatMonthYear(date); // "December 2025"
DateFormatters.formatDayMonth(date); // "December 1"
DateFormatters.formatDayName(date); // "Monday"
DateFormatters.formatMonthName(date); // "December"
DateFormatters.formatCustom(date, 'yyyy-MM-dd'); // "2025-12-01"
DateFormatters.formatIso8601(date); // ISO 8601 format
DateFormatters.formatForFileName(date); // File-safe format
DateFormatters.formatDateRange(start, end); // Date range
Time Formatting Functions (8+)
TimeFormatters.formatTime12Hour(date); // "2:30 PM"
TimeFormatters.formatTime24Hour(date); // "14:30"
TimeFormatters.formatTime12HourWithSeconds(date); // "2:30:45 PM"
TimeFormatters.formatTime24HourWithSeconds(date); // "14:30:45"
TimeFormatters.formatTimeWithMilliseconds(date); // "14:30:45.123"
TimeFormatters.formatDateTimeShort(date); // "12/1/2025 2:30 PM"
TimeFormatters.formatDateTimeMedium(date); // "Dec 1, 2025 2:30 PM"
TimeFormatters.formatDateTimeLong(date); // "December 1, 2025 at 2:30 PM"
Date Comparison Functions (13+)
DateComparisons.isSameDay(date1, date2); // Same day?
DateComparisons.isSameWeek(date1, date2); // Same week?
DateComparisons.isSameMonth(date1, date2); // Same month?
DateComparisons.isSameYear(date1, date2); // Same year?
DateComparisons.isToday(date); // Is today?
DateComparisons.isYesterday(date); // Is yesterday?
DateComparisons.isTomorrow(date); // Is tomorrow?
DateComparisons.isThisWeek(date); // In current week?
DateComparisons.isThisMonth(date); // In current month?
DateComparisons.isThisYear(date); // In current year?
DateComparisons.isPast(date); // In the past?
DateComparisons.isFuture(date); // In the future?
DateComparisons.isWeekend(date); // Saturday/Sunday?
DateComparisons.isWeekday(date); // Monday-Friday?
DateComparisons.isBetween(date, start, end); // In date range?
Date Calculation Functions (20+)
// Period boundaries
DateCalculations.startOfDay(date); // 00:00:00
DateCalculations.endOfDay(date); // 23:59:59.999
DateCalculations.startOfWeek(date); // Monday 00:00
DateCalculations.endOfWeek(date); // Sunday 23:59
DateCalculations.startOfMonth(date); // 1st day of month
DateCalculations.endOfMonth(date); // Last day of month
DateCalculations.startOfYear(date); // Jan 1st
DateCalculations.endOfYear(date); // Dec 31st
DateCalculations.startOfQuarter(date); // Quarter start
DateCalculations.endOfQuarter(date); // Quarter end
// Business days
DateCalculations.addBusinessDays(date, 5); // +5 weekdays
DateCalculations.subtractBusinessDays(date, 5); // -5 weekdays
DateCalculations.countBusinessDays(start, end); // Count weekdays
// Calculations
DateCalculations.calculateAge(birthDate); // Age in years
DateCalculations.getDaysInMonth(year, month); // Days in month
DateCalculations.isLeapYear(year); // Leap year?
DateCalculations.getQuarter(date); // Quarter number (1-4)
DateCalculations.getWeekNumber(date); // Week number in year
DateCalculations.addMonths(date, 3); // +3 months (smart)
DateCalculations.subtractMonths(date, 3); // -3 months
DateCalculations.getDifference(start, end); // Detailed difference
// Timezone
DateCalculations.toUTC(date); // Convert to UTC
DateCalculations.toLocal(date); // Convert to local
DateCalculations.formatTimezoneOffset(date); // "+05:30"
DateCalculations.getTimezoneName(date); // "PST"
Relative Time Functions (5+)
RelativeTime.getRelativeTime(date); // "2 hours ago"
RelativeTime.getRelativeTime(date, 'es_ES'); // "hace 2 horas"
RelativeTime.getRelativeTimeShort(date); // "2h"
RelativeTime.formatDuration(duration); // "2h 30m"
RelativeTime.formatTimeRemaining(targetDate); // Countdown
Smart & Parsing Functions (4+)
// Smart formatting
SmartFormatters.formatSmart(date); // Context-aware
// Parsing
DateParsers.parseDate(dateString); // Parse date
DateParsers.parseFlexible(dateString); // Try multiple formats
DateParsers.isValidDate(dateString); // Validate date string
💡 Examples
🎯 Real-World Use Cases
Chat/Messaging App
import 'package:save_points_intl/datetime.dart';
String formatMessageTimestamp(DateTime messageTime) {
if (DateComparisons.isToday(messageTime)) {
return TimeFormatters.formatTime12Hour(messageTime); // "2:30 PM"
} else if (DateComparisons.isYesterday(messageTime)) {
return 'Yesterday';
} else if (DateComparisons.isThisWeek(messageTime)) {
return DateFormatters.formatDayName(messageTime); // "Monday"
} else if (DateComparisons.isThisYear(messageTime)) {
return DateFormatters.formatDayMonth(messageTime); // "Nov 30"
} else {
return DateFormatters.formatDateShort(messageTime); // "11/30/2024"
}
}
// Usage
final timestamp = formatMessageTimestamp(messageDate);
print('Message sent: $timestamp');
Event Calendar
import 'package:save_points_intl/datetime.dart';
class Event {
final String title;
final DateTime startTime;
Event(this.title, this.startTime);
String getDisplayTime() {
if (DateComparisons.isToday(startTime)) {
return 'Today at ${TimeFormatters.formatTime12Hour(startTime)}';
} else if (DateComparisons.isTomorrow(startTime)) {
return 'Tomorrow at ${TimeFormatters.formatTime12Hour(startTime)}';
} else if (DateComparisons.isThisWeek(startTime)) {
return '${DateFormatters.formatDayName(startTime)} at ${TimeFormatters.formatTime12Hour(startTime)}';
} else {
return TimeFormatters.formatDateTimeMedium(startTime);
}
}
String getCountdown() {
return RelativeTime.getRelativeTime(startTime);
}
}
// Usage
final meeting = Event('Team Meeting', DateTime.now().add(Duration(hours: 3)));
print(meeting.getDisplayTime()); // "Today at 5:30 PM"
print(meeting.getCountdown()); // "in 3 hours"
Social Media Feed
import 'package:save_points_intl/datetime.dart';
class Post {
final String content;
final DateTime publishedAt;
Post(this.content, this.publishedAt);
String getTimestamp() {
final diff = DateTime.now().difference(publishedAt);
if (diff.inMinutes < 1) return 'Just now';
if (diff.inHours < 1) return '${diff.inMinutes}m';
if (diff.inHours < 24) return '${diff.inHours}h';
if (diff.inDays < 7) return '${diff.inDays}d';
return DateFormatters.formatDateMedium(publishedAt);
}
}
// Usage
final post = Post('Hello World!', DateTime.now().subtract(Duration(hours: 2)));
print(post.getTimestamp()); // "2h"
Booking System
import 'package:save_points_intl/datetime.dart';
class Reservation {
final DateTime checkIn;
final DateTime checkOut;
Reservation(this.checkIn, this.checkOut);
int get numberOfNights => checkOut.difference(checkIn).inDays;
int get businessDays =>
DateCalculations.countBusinessDays(checkIn, checkOut);
String getStayPeriod() =>
DateFormatters.formatDateRange(checkIn, checkOut);
String getStatus() {
if (DateComparisons.isToday(checkIn)) {
return 'Checking in today';
} else if (DateComparisons.isPast(checkIn) &&
DateComparisons.isFuture(checkOut)) {
return 'Currently staying';
} else if (DateComparisons.isPast(checkOut)) {
return 'Checked out';
} else {
return 'Checking in ${RelativeTime.getRelativeTime(checkIn)}';
}
}
}
// Usage
final reservation = Reservation(
DateTime.now().add(Duration(days: 3)),
DateTime.now().add(Duration(days: 8)),
);
print('Period: ${reservation.getStayPeriod()}');
print('Nights: ${reservation.numberOfNights}');
print('Status: ${reservation.getStatus()}');
Task Manager
import 'package:save_points_intl/datetime.dart';
class Task {
final String name;
final DateTime dueDate;
DateTime? completedDate;
Task(this.name, this.dueDate);
bool get isOverdue =>
completedDate == null && DateComparisons.isPast(dueDate);
bool get isDueToday =>
completedDate == null && DateComparisons.isToday(dueDate);
String getStatus() {
if (completedDate != null) {
return 'Completed ${RelativeTime.getRelativeTime(completedDate!)}';
}
if (isOverdue) {
final days = DateTime.now().difference(dueDate).inDays;
return '⚠️ Overdue by $days day${days == 1 ? '' : 's'}';
}
if (isDueToday) {
return '📅 Due today at ${TimeFormatters.formatTime12Hour(dueDate)}';
}
return '⏰ Due ${RelativeTime.getRelativeTime(dueDate)}';
}
}
// Usage
final task = Task('Submit report', DateTime.now().add(Duration(hours: 5)));
print(task.getStatus()); // "⏰ Due in 5 hours"
Multi-Language App
import 'package:save_points_intl/datetime.dart';
class LocalizedDateService {
final String locale;
LocalizedDateService(this.locale);
String formatDate(DateTime date) {
return DateFormatters.formatDateLong(date, locale);
}
String formatTime(DateTime date) {
return TimeFormatters.formatTime12Hour(date, locale);
}
String formatRelative(DateTime date) {
return RelativeTime.getRelativeTime(date, locale);
}
}
// Usage
final english = LocalizedDateService('en_US');
final spanish = LocalizedDateService('es_ES');
final arabic = LocalizedDateService('ar_SA');
final now = DateTime.now();
print(english.formatDate(now)); // "December 1, 2025"
print(spanish.formatDate(now)); // "1 de Diciembre de 2025"
print(arabic.formatDate(now)); // "1 ديسمبر 2025"
🎨 Advanced Usage
Custom Date Patterns
// ISO 8601
DateFormatters.formatCustom(date, 'yyyy-MM-dd'); // "2025-12-01"
// European format
DateFormatters.formatCustom(date, 'dd/MM/yyyy'); // "01/12/2025"
// American with time
DateFormatters.formatCustom(date, 'MM/dd/yyyy HH:mm'); // "12/01/2025 14:30"
// Custom format
DateFormatters.formatCustom(date, 'yyyy-MM-dd_HH-mm-ss'); // "2025-12-01_14-30-45"
Business Logic
// Get next business day
final tomorrow = DateTime.now().add(Duration(days: 1));
final nextBusinessDay = DateComparisons.isWeekend(tomorrow)
? DateCalculations.addBusinessDays(DateTime.now(), 1)
: tomorrow;
// Count working days in month
final startOfMonth = DateCalculations.startOfMonth(DateTime.now());
final endOfMonth = DateCalculations.endOfMonth(DateTime.now());
final workingDays = DateCalculations.countBusinessDays(startOfMonth, endOfMonth);
print('Working days this month: $workingDays');
// Calculate deadline (5 business days from now)
final deadline = DateCalculations.addBusinessDays(DateTime.now(), 5);
print('Deadline: ${DateFormatters.formatDateFull(deadline)}');
Period Reporting
// Current quarter info
final quarter = DateCalculations.getQuarter(DateTime.now());
final quarterStart = DateCalculations.startOfQuarter(DateTime.now());
final quarterEnd = DateCalculations.endOfQuarter(DateTime.now());
print('Q$quarter: ${DateFormatters.formatDateRange(quarterStart, quarterEnd)}');
// Financial year
final fyStart = DateTime(DateTime.now().year, 4, 1); // April 1st
final fyEnd = DateTime(DateTime.now().year + 1, 3, 31); // March 31st next year
final businessDaysInFY = DateCalculations.countBusinessDays(fyStart, fyEnd);
print('Business days in FY: $businessDaysInFY');
🛠️ Extending the Library
Adding New Languages
Edit lib/constants.dart:
static final Map<String, List<String>> monthNames = {
'en': ['January', 'February', ...],
'es': ['Enero', 'Febrero', ...],
'it': ['Gennaio', 'Febbraio', ...], // Add Italian
};
// Also add to monthNamesShort, dayNames, dayNamesShort
// And add relative time translations in getRelativeTimeTranslations()
Adding Custom Formatters
Create your own formatter class:
import 'package:save_points_intl/datetime.dart';
class MyCustomFormatters {
static String formatFinancialQuarter(DateTime date) {
final quarter = DateCalculations.getQuarter(date);
return 'FY Q$quarter ${date.year}';
}
static String formatWeekRange(DateTime date) {
final start = DateCalculations.startOfWeek(date);
final end = DateCalculations.endOfWeek(date);
return DateFormatters.formatDateRange(start, end);
}
}
📊 Performance
Benchmarks
| Operation | Time | Memory |
|---|---|---|
| Format date | <0.1ms | Minimal |
| Compare dates | <0.01ms | None |
| Calculate business days | ~0.1ms per day | Minimal |
| Parse date | <0.5ms | Minimal |
| Relative time | <0.1ms | Minimal |
Bundle Size Impact
- Core helpers: ~35KB
- With all languages: ~45KB
- Single module: ~5-10KB (tree-shakable)
No runtime overhead, all calculations are pure Dart.
❓ FAQ
Why not use the `intl` package?
While intl is great, this library offers:
- ✅ No external dependencies = no version conflicts
- ✅ Lighter weight = faster builds
- ✅ Fully customizable = modify for your needs
- ✅ More business logic = calculations, comparisons, etc.
- ✅ Simpler API = easier to use
Use intl if you need comprehensive i18n. Use this if you want lightweight date/time helpers.
Can I use this in production?
✅ Yes! This library is:
- Fully tested and verified
- Zero dependencies (no breaking changes risk)
- Type-safe with null safety
- Well documented
- Production-ready
How do I add more languages?
Edit lib/constants.dart and add your language to:
monthNamesmapmonthNamesShortmapdayNamesmapdayNamesShortmapgetRelativeTimeTranslations()method
See Extending the Library for details.
Does it support RTL languages?
✅ Yes! Arabic is included with proper translations. The library returns formatted strings; your UI framework handles RTL display.
Can I use only specific modules?
✅ Absolutely! Import only what you need:
import 'package:save_points_intl/date_formatters.dart';
import 'package:save_points_intl/date_comparisons.dart';
The library is fully modular and tree-shakable.
How do I handle timezones?
Use the timezone utilities in DateCalculations:
// Convert to UTC
final utc = DateCalculations.toUTC(localDate);
// Convert to local
final local = DateCalculations.toLocal(utcDate);
// Get offset
final offset = DateCalculations.formatTimezoneOffset(date); // "+05:30"
🔧 Troubleshooting
Import Issues
// ❌ Wrong
import 'datetime.dart';
// ✅ Correct
import 'package:save_points_intl/datetime.dart';
Type Issues
// ❌ Wrong - nullable without handling
DateTime? date = DateParsers.parseDate('invalid');
print(date.year); // Null error!
// ✅ Correct - handle nullable
DateTime? date = DateParsers.parseDate('2025-12-01');
if (date != null) {
print(date.year);
}
// ✅ Or use fallback
DateTime date = DateParsers.parseDate('2025-12-01') ?? DateTime.now();
Locale Not Working
// ❌ Wrong - invalid locale code
DateFormatters.formatDateLong(date, 'spanish');
// ✅ Correct - use proper locale codes
DateFormatters.formatDateLong(date, 'es_ES');
DateFormatters.formatDateLong(date, 'es'); // Also works
🤝 Contributing
Contributions are welcome! To contribute:
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
Areas for Contribution
- 🌍 More languages - Add translations for your language
- 📝 Documentation - Improve docs, add examples
- 🐛 Bug fixes - Report and fix issues
- ✨ Features - Suggest and implement new features
📜 License
This library is free to use in your Flutter projects.
MIT License - Use it, modify it, share it!
🙏 Acknowledgments
- Built with pure Dart
- Inspired by moment.js, date-fns, and intl package
- Community feedback and contributions
📞 Support
- 📖 Documentation: See EXAMPLES.md for comprehensive examples
- 🐛 Issues: Report bugs via GitHub issues
- 💬 Discussions: Start a discussion for questions
- ⭐ Star: If you like it, give it a star!
Made with ❤️ for the Flutter community
Libraries
- main
- Example demonstrating the save_points_intl package
- save_points_intl
- A comprehensive, modular, zero-dependency date/time library for Flutter
- save_points_intl_constants
- save_points_intl_date_calculations
- save_points_intl_date_comparisons
- save_points_intl_date_formatters
- save_points_intl_date_parsers
- save_points_intl_relative_time
- save_points_intl_smart_formatters
- save_points_intl_time_formatters