time+
— A Better Way to Work with DateTime
and Duration
in Dart
After years of wrestling with Dart’s native DateTime
and Duration
APIs, I built time_plus
— a lightweight, zero-dependency extension package with 128 carefully designed APIs and over 700 tests validating edge cases, leap logic, conversions, and much more.
It consists of dozens of extensions I had written and used privately across various projects — until finally packaging them together into a single, cohesive package.
It’s precise, production-safe, and battle-tested in real-world apps — designed to give you expressive, reliable time math without the pitfalls or boilerplate.
If you’re working with time in Dart and want tools that just work, feel free to explore the full README — it’s packed with detailed docs, real examples, and everything this package has to offer.
Let me know what you think (:
100% pure Dart · Zero dependencies · 128 extensions · 700+ tests
https://pub.dev/packages/time_plus
All DateTime
Extensions in time_plus
time_plus
massively expands the power of DateTime
with over 60 precise, calendar-aware extensions — all tested, side-effect-free, and timezone-respecting.
Add Time
Add any unit to a DateTime
, safely and fluently — from microseconds to centuries.
Supports clamping for overflow dates (e.g. Feb 30 → Feb 28/29).
.addMillisecond(int) / .addMillisecond
.addSecond(int) / .addSecond
.addMinute(int) / .addMinute
.addHour(int) / .addHour
.addDay(int) / .addDay
.addWeek(int) / .addWeek
.addMonth(int) / .addMonth
.addYear(int) / .addYear
.addDecade(int) / .addDecade
.addCentury(int) / .addCentury
Subtract Time
Same methods as above, but with .subtractX()
/ .subtractX
equivalents.
All preserve the original time of day and calendar correctness.
Temporal Comparison
Check if two DateTime
s fall in the same unit (e.g. minute, day, decade).
.isSameMicrosecond(other)
.isSameMillisecond(other)
.isSameSecond(other)
.isSameMinute(other)
.isSameHour(other)
.isSameDay(other)
.isSameMonth(other)
.isSameYear(other)
.isSameDecade(other)
.isSameCentury(other)
Boundaries
Get the exact start or end of a unit.
.startOfMillisecond / .endOfMillisecond
.startOfSecond / .endOfSecond
.startOfMinute / .endOfMinute
.startOfHour / .endOfHour
.startOfDay / .endOfDay
.startOfWeek / .endOfWeek
.startOfMonth / .endOfMonth
.startOfYear / .endOfYear
.startOfDecade / .endOfDecade
.startOfCentury / .endOfCentury
Recurrence Helpers
Schedule the next matching DateTime
, forward-only.
.nextWeekdayTime(weekday, [hour, minute, ...])
.nextTimeOfDay(hour, [minute, ...])
Leap Year Logic
Expanded leap checks for clean calendar logic.
.isLeapYear // year has 366 days
.isLeapMonth // true only for February in leap year
.isLeapDay // true only for Feb 29
Calendar Info
Accurate day counts based on the current month/year.
.daysInMonth // 28–31
.daysInYear // 365 or 366
Relative Days
Simple helpers for working around “now”.
.yesterday
.tomorrow
.previousWeekday
.nextWeekday
All methods return new immutable instances, respect time zones, and are backed by unit tests. Built for readability, correctness, and production use.
All Duration
Extensions in time_plus
time_plus
takes Dart’s Duration
from basic to brilliant — with over 60 high-precision utilities for creating, converting, chaining, and analyzing time spans.
Add Duration Units
Add any time unit to a Duration
, including months, years, decades, and centuries — using .addX()
or .addX
for chainable syntax.
.addMicrosecond / .addMicroseconds(int)
.addMillisecond / .addMilliseconds(int)
.addSecond / .addSeconds(int)
.addMinute / .addMinutes(int)
.addHour / .addHours(int)
.addDay / .addDays(int)
.addWeek / .addWeeks(int)
.addMonth / .addMonths(int)
.addYear / .addYears(int)
.addDecade / .addDecades(int)
.addCentury / .addCenturies(int)
All use Gregorian calendar averages, making them ideal for scheduling and estimations.
Convert to Whole Units (inX
)
Convert durations into whole integer units, based on precise Gregorian averages.
.inWeeks
.inMonths
.inYears
.inDecades
.inCenturies
Great for analytics and consistent formatting (e.g., Duration(days: 750).inYears → 2
).
Convert to Fractional Units (asX
)
Get precise decimal representations with fractional support.
.asMilliseconds, .asSeconds, .asMinutes
.asHours, .asDays, .asWeeks
.asMonths, .asYears, .asDecades, .asCenturies
Ideal for charts, sliders, or estimation UIs.
Breakdown (onlyX
)
Extract leftover parts after removing larger units.
.onlyMicroseconds
.onlyMilliseconds
.onlySeconds
.onlyMinutes
.onlyHours
.onlyDays
Example: use .onlyHours
to display “3h 25m” style timers.
Strip Units (withoutX
)
Remove full units and isolate what’s left.
.withoutDays
.withoutHours
.withoutMinutes
.withoutSeconds
.withoutMilliseconds
Perfect for isolating “time since midnight” or converting full durations into segments.
int
→ Duration
Turn any int
into a readable Duration
— naturally.
5.milliseconds, 10.seconds, 2.hours
3.days, 4.weeks, 6.months, 1.years
Readable, chainable, and great for test code or configs.
double
→ Duration
Decompose fractions with full accuracy — no rounding loss.
1.5.seconds, 2.25.minutes, 0.5.hours
1.5.days, 0.33.months, 2.75.years
Smartly breaks values into actual Duration
components (2.5.days
→ 2 days + 12 hours).
Factories (DurationFrom
)
Construct durations programmatically with named units.
DurationFrom.days(10);
DurationFrom.year;
DurationFrom.centuries(2);
Includes constants like DurationFrom.week
, DurationFrom.month
, etc.
Why Not Just Use time
?
The Dart time
package is a simple utility—but it’s limited by design.
While it adds int.hours
and double.days
, it lacks precision, testing, and scalability:
- Tied to
clock
— adds runtime side effects to basic time logic - Integer math only —
2.5.days
≠ 2 days + 12 hours - Minimal coverage — only ~15 extensions
- No calendar support — no leap day, no month math, no
.startOfWeek()
- Fails precision tests — rounding errors on fractional durations
- No decomposition — can’t get
.onlyMinutes
or.withoutHours
time_plus
includes all that — and 10× more
Double-safe logic —
.5.days
→ decomposed into hours, minutes, secondsSmart
.int
and.double
extensions — readable, precise, and composable128+ extensions — for
DateTime
,Duration
,int
,double
, and factories717 tests — covering edge cases, DST transitions, and long-term accuracy
Cleaner API — zero side effects, no dependency on
clock
or global stateCalendar features — leap year detection,
.startOfMonth
,.isSameDay
, etc.
Small Example
final now = DateTime(2024, 2, 29);
final next = now.addYear.addMonth; // → 2025-03-29
final exact = 2.5.days; // → 2d 12h
final match = now.isSameMonth(DateTime(2024, 2, 1)); // true