Write relativeTime(date, now). It describes how long before or after now the moment date is, the way feeds and comments do: 3 minutes ago, or in 2 days.
date and now are each a Date or a timestamp: a number of milliseconds, like the ones Date.now() returns. If either is an invalid date, such as new Date("oops") or NaN, throw a RangeError.
When the two are less than a minute apart, either way, return "just now".
Otherwise, use the largest of these units that fits into the difference at least once: year (365 days), month (30 days), week (7 days), day, hour, and minute. Count whole units and drop the rest: 119 seconds is 1 minute, and 13 days is 1 week.
Write the count, a space, and the unit, adding an s when the count isn't 1. If date is before now, add ago, as in 1 hour ago. If it's after now, put in in front, as in in 2 hours.
Write it without Intl.
const now = new Date("2024-05-01T12:00:00Z");
relativeTime(new Date("2024-05-01T11:57:30Z"), now); // "2 minutes ago"
relativeTime(new Date("2024-05-01T15:00:00Z"), now); // "in 3 hours"
relativeTime(new Date("2024-04-21T12:00:00Z"), now); // "1 week ago"
relativeTime(now.getTime() - 20_000, now); // "just now"
const now = Date.UTC(2024, 4, 1, 12);
expect(relativeTime(now, now)).toBe("just now");
expect(relativeTime(now - 59_999, now)).toBe("just now");
expect(relativeTime(now + 59_999, now)).toBe("just now");
const now = Date.UTC(2024, 4, 1, 12);
const minute = 60 * 1000;
const hour = 60 * minute;
expect(relativeTime(now - minute, now)).toBe("1 minute ago");
expect(relativeTime(now - 150 * 1000, now)).toBe("2 minutes ago");
expect(relativeTime(now - (hour - 1), now)).toBe("59 minutes ago");
expect(relativeTime(now - hour, now)).toBe("1 hour ago");
expect(relativeTime(now - (24 * hour - 1), now)).toBe("23 hours ago");
const now = Date.UTC(2024, 4, 1, 12);
const day = 24 * 60 * 60 * 1000;
expect(relativeTime(now - day, now)).toBe("1 day ago");
expect(relativeTime(now - (7 * day - 1), now)).toBe("6 days ago");
expect(relativeTime(now - 7 * day, now)).toBe("1 week ago");
expect(relativeTime(now - 29 * day, now)).toBe("4 weeks ago");
expect(relativeTime(now - 30 * day, now)).toBe("1 month ago");
expect(relativeTime(now - 364 * day, now)).toBe("12 months ago");
expect(relativeTime(now - 365 * day, now)).toBe("1 year ago");
expect(relativeTime(now - 1000 * day, now)).toBe("2 years ago");
const now = Date.UTC(2024, 4, 1, 12);
const hour = 60 * 60 * 1000;
const day = 24 * hour;
expect(relativeTime(now - 2 * 60 * 1000, now)).toBe("2 minutes ago");
expect(relativeTime(now - hour, now)).toBe("1 hour ago");
expect(relativeTime(now - 5 * hour, now)).toBe("5 hours ago");
expect(relativeTime(now - 14 * day, now)).toBe("2 weeks ago");
expect(relativeTime(now - 45 * day, now)).toBe("1 month ago");
expect(relativeTime(now - 90 * day, now)).toBe("3 months ago");
expect(relativeTime(now - 3650 * day, now)).toBe("10 years ago");
const now = Date.UTC(2024, 4, 1, 12);
const hour = 60 * 60 * 1000;
const day = 24 * hour;
expect(relativeTime(now + 3 * hour, now)).toBe("in 3 hours");
expect(relativeTime(now + day, now)).toBe("in 1 day");
expect(relativeTime(now + 14 * day, now)).toBe("in 2 weeks");
expect(relativeTime(now + 400 * day, now)).toBe("in 1 year");
const now = Date.UTC(2024, 4, 1, 12);
const day = 24 * 60 * 60 * 1000;
expect(relativeTime(now + 90 * 1000, now)).toBe("in 1 minute");
expect(relativeTime(now + (2 * day - 1), now)).toBe("in 1 day");
expect(relativeTime(now + 13 * day, now)).toBe("in 1 week");
const now = new Date("2024-05-01T12:00:00Z");
expect(relativeTime(new Date("2024-05-01T11:57:30Z"), now)).toBe("2 minutes ago");
expect(relativeTime(new Date("2024-05-01T15:00:00Z"), now.getTime())).toBe("in 3 hours");
expect(relativeTime(Date.UTC(2024, 3, 21, 12), now)).toBe("1 week ago");
const now = Date.UTC(2024, 4, 1, 12);
expect(() => relativeTime(new Date("not a date"), now)).toThrow(RangeError);
expect(() => relativeTime(now, new Date(NaN))).toThrow(RangeError);
expect(() => relativeTime(NaN, now)).toThrow(RangeError);
const now = Date.UTC(2024, 4, 1, 12);
const { RelativeTimeFormat, PluralRules } = Intl;
Intl.RelativeTimeFormat = function () {
throw new Error("relativeTime must not use Intl.RelativeTimeFormat");
};
Intl.PluralRules = function () {
throw new Error("relativeTime must not use Intl.PluralRules");
};
let results;
try {
results = [relativeTime(now - 3 * 60 * 1000, now), relativeTime(now + 2 * 24 * 60 * 60 * 1000, now)];
} finally {
// Put the built-ins back even when relativeTime throws, before expect runs.
Intl.RelativeTimeFormat = RelativeTimeFormat;
Intl.PluralRules = PluralRules;
}
expect(results).toEqual(["3 minutes ago", "in 2 days"]);
Run tests runs every test on your code, here in your browser. The problem is solved when they all pass.
Ctrl + Enter runs the tests (⌘ + Enter on a Mac).
I'm here to help with Relative time. I give hints, never the solution, so you get to solve it yourself. Ask for a hint, select code to ask about it, or press Ask Tuto why on a failing test.
Your first 3 answers need no account. for free to keep asking.