timeSinceUntil
Returns the time difference between two dates in absolute or directional mode. If since
is true, it returns time elapsed from the past date to now. If since
is false, it returns time remaining from now to a future date.
1/**
2 * Returns the time difference between two dates in absolute or directional mode.
3 * If `since` is true, it returns time elapsed from the past date to now.
4 * If `since` is false, it returns time remaining from now to a future date.
5 *
6 * If the direction doesn't match the dates, returns all zeros.
7 *
8 * @param date - The target date for comparison.
9 * @param since - Whether to measure time since or until the date.
10 * @returns An object with time components (days, hours, etc.).
11 */
12export function timeSinceUntil(
13 date: Date,
14 since: boolean
15): {
16 days: number;
17 hours: number;
18 minutes: number;
19 seconds: number;
20 milliseconds: number;
21} {
22 const now = new Date();
23 const diff = (since ? now.getTime() - date.getTime() : date.getTime() - now.getTime());
24
25 if (diff <= 0) {
26 return { days: 0, hours: 0, minutes: 0, seconds: 0, milliseconds: 0 };
27 }
28
29 const msInSecond = 1000;
30 const msInMinute = msInSecond * 60;
31 const msInHour = msInMinute * 60;
32 const msInDay = msInHour * 24;
33
34 let remaining = diff;
35
36 const days = Math.floor(remaining / msInDay);
37 remaining %= msInDay;
38
39 const hours = Math.floor(remaining / msInHour);
40 remaining %= msInHour;
41
42 const minutes = Math.floor(remaining / msInMinute);
43 remaining %= msInMinute;
44
45 const seconds = Math.floor(remaining / msInSecond);
46 const milliseconds = remaining % msInSecond;
47
48 return { days, hours, minutes, seconds, milliseconds };
49}
Bidirectional Support
Handles both "time since" and "time until" modes with a single flag, making the function flexible for various temporal comparisons.
Comprehensive Output
Returns detailed breakdowns into days, hours, minutes, seconds, and milliseconds, suitable for both display and logic.
Zero-Safe Output
Automatically returns all-zero fields if the time direction is invalid or the event is in the past/future as applicable — reducing edge-case bugs.
Readable and Self-Contained
Uses clear constants and modular logic for converting milliseconds into time units, improving readability and maintainability.
Tests | Examples
1test('timeSinceUntil - time since 1d 2h 30m 20s 500ms ago', () => {
2 const now = new Date();
3 const past = new Date(now.getTime() -
4 1 * 24 * 60 * 60 * 1000 - // 1 day
5 2 * 60 * 60 * 1000 - // 2 hours
6 30 * 60 * 1000 - // 30 minutes
7 20 * 1000 - // 20 seconds
8 500 // 500 ms
9 );
10
11 const result = timeSinceUntil(past, true);
12
13 expect(result.days).toBe(1);
14 expect(result.hours).toBe(2);
15 expect(result.minutes).toBe(30);
16 expect(result.seconds).toBe(20);
17 expect(result.milliseconds).toBeGreaterThanOrEqual(490);
18 expect(result.milliseconds).toBeLessThanOrEqual(510);
19});
20
21test('timeSinceUntil - future date with "since" returns all zeros', () => {
22 const future = new Date(Date.now() + 5000);
23 expect(timeSinceUntil(future, true)).toEqual({
24 days: 0,
25 hours: 0,
26 minutes: 0,
27 seconds: 0,
28 milliseconds: 0,
29 });
30});
31
32test('timeSinceUntil - time until 1h 5m 20s 300ms from now', () => {
33 const future = new Date(Date.now() +
34 1 * 60 * 60 * 1000 + // 1 hour
35 5 * 60 * 1000 + // 5 minutes
36 20 * 1000 + // 20 seconds
37 300 // 300 ms
38 );
39
40 const result = timeSinceUntil(future, false);
41
42 expect(result.days).toBe(0);
43 expect(result.hours).toBe(1);
44 expect(result.minutes).toBe(5);
45 expect(result.seconds).toBe(20);
46 expect(result.milliseconds).toBeGreaterThanOrEqual(290);
47 expect(result.milliseconds).toBeLessThanOrEqual(310);
48});
Common Use Cases
Countdown Timers
Display how much time is left until an event (e.g. deadlines, launches, reminders).
Elapsed Time Display
Show how long ago something occurred (e.g. "last synced 3 hours ago").
Session or Trial Tracking
Calculate time remaining in sessions or trials to determine usage limits or expiration.
Event Progress Dashboards
Power time-based UI elements showing progression toward or since milestones.
Animation or Transition Timing
Use granular time breakdowns to trigger UI updates or timed transitions.