Time abstraction and scheduler for Dart. A port of the time4k Kotlin library, providing controllable clocks and deterministic scheduling for testing.
- 🕐 Time Abstractions - Functional time sources with
Clocktypedef - 🔄 Production Scheduling -
SchedulerServicefor real async scheduling - ⏱️ Test Time Control -
FixedClockandAutoTickingClockfor deterministic testing - 📅 Deterministic Scheduling -
DeterministicSchedulerfor predictable task execution in tests - 🧪 Testing Support - Full control over time progression in tests
- 🎯 Dart Idiomatic - Uses
Future,Duration,DateTimeand sound null safety
Add to your pubspec.yaml:
dependencies:
time4d: ^1.0.0
dev_dependencies:
time4d: ^1.0.0 # for testing utilitiesimport 'package:time4d/time4d.dart';
// Basic UTC Clock
final clock = utcSystemTime;
print('Current time: ${clock()}');
// Deterministic testing
final scheduler = DeterministicScheduler.epoch();
scheduler.scheduleVoid(() => print('Task executed!'), Duration(seconds: 1));
scheduler.tick(Duration(seconds: 1)); // Execute scheduled tasksA Clock is simply a function that returns the current time:
typedef Clock = DateTime Function();
// System time
final systemClock = utcSystemTime; // Uses DateTime.now.toUtc
// Ticking clock (truncates to specified unit)
final secondClock = tickingClock(utcSystemTime, unit: Duration(seconds: 1));Control time in your tests with tickable clocks:
final fixed = FixedClock(time: DateTime.fromMillisecondsSinceEpoch(0, isUtc: true));
print(fixed()); // 1970-01-01 00:00:00.000Z
fixed.tick(); // Manually advance time
print(fixed()); // 1970-01-01 00:00:01.000ZFor deterministic testing and production scheduling:
// Testing - controllable time
final scheduler = DeterministicScheduler.epoch();
scheduler.scheduleVoid(() => print('Task executed!'), Duration(seconds: 1));
scheduler.tick(Duration(seconds: 1)); // Execute scheduled tasks
// Production - real async scheduling
final prodScheduler = SchedulerService();
await prodScheduler.schedule(() async => 'result', Duration(seconds: 1));Time4d operates exclusively with UTC DateTime objects for deterministic testing and cross-platform consistency. Convert to local time at the presentation layer:
final utcTime = utcSystemTime(); // Always UTC
final localTime = utcTime.toLocal(); // Convert for display- Use factory constructors:
DeterministicScheduler.epoch()for tests - Inject schedulers: Always make clocks and schedulers dependencies for testability
- Clean shutdown: Always call
shutdown()on production schedulers - Test time control: Use
tick()andrunUntilIdle()to control test execution - Avoid real time in tests: Use
DeterministicSchedulerinstead ofSchedulerService - Keep UTC in business logic: Convert to local timezone only at the presentation layer
📁 Complete working examples - See the /example folder for comprehensive demos of all features including:
- Clock usage patterns
- Deterministic scheduler testing
- Production scheduler setup
- UTC timezone handling
- Real-world usage scenarios
Contributions are welcome! Please feel free to submit a Pull Request.
- Fork the repository
- Create a feature branch
- Add tests for your changes
- Ensure all tests pass:
dart test - Submit a pull request
This project is licensed under the Apache 2.0 License - see the LICENSE file for details.
- Original time4k Kotlin library by the fork-handles team
- Inspiration from Java's
ScheduledExecutorServiceandClockabstractions - The Dart community for excellent async/await patterns