JavaScript
Completed
-
Section 1: Getting Started
-
Section 2: Core Syntax and Types
-
Section 3: Strings and Numbers in Depth
-
Section 4: Control Flow
-
Section 5: Functions
-
Section 6: Objects and Arrays
-
Section 7: Maps, Sets, and Symbols
-
Section 8: Asynchronous JavaScript
-
Section 9: Object-Oriented and Prototypes
-
Section 10: The DOM
-
Section 11: Browser APIs
-
Section 12: Modern JavaScript (ES2015-ES2025)
-
Section 13: Functional Programming Patterns
-
Section 14: Error Handling and Debugging
-
Section 15: Testing
-
Section 16: Accessibility for JavaScript Developers
-
Section 17: Internationalization and Localization
-
Section 18: Performance
-
Section 19: Node.js Fundamentals
-
Section 20: Regular Expressions
-
Section 21: Design Patterns in JavaScript
-
Section 22: Security Basics
-
Section 23: Data Structures and Algorithms in JavaScript
-
Section 24: Practical Projects
-
Section 25: More Advanced Async Patterns
-
Section 26: More Object and Class Practice
-
Section 27: Working with Dates and Internationalization
-
Section 28: Web Components
-
Section 29: More DOM and Browser Practice
-
Section 30: Build Tooling for Vanilla JavaScript
-
Section 31: More Practice Projects
-
Section 32: Interview and Algorithm Practice
-
Section 33: Error Objects (MDN Reference)
-
Section 34: TypedArrays and Binary Data
-
Section 35: Reflection and Metaprogramming (MDN Reference)
-
Section 36: More Global Functions (MDN Reference)
205: Working with Relative Time Formatting
Imagine you're meeting a friend for coffee. If they text you and say, "I'll be there on October 14th at 2:15 PM," and today is October 14th, you'd probably think they were a bit weird. In a real conversation, they'd just say, "I'll be there in 15 minutes." We naturally think in offsets from "now" rather than absolute coordinates on a calendar.
In JavaScript, we have the Intl.RelativeTimeFormat object to help us mimic this human behavior. It's essentially a translation layer. You give it a number (the offset) and a unit (like days or seconds), and it gives you back a string that makes sense to a human being in their own language.
Turning Numbers into Human Language
The core of this API is the format method. You don't pass it a Date object—which is a common point of confusion I see—you pass it the difference between two dates.
const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'always' });
console.log(rtf.format(-1, 'day')); // "1 day ago"
console.log(rtf.format(2, 'hour')); // "in 2 hours"
console.log(rtf.format(-5, 'minute')); // "5 minutes ago"
Notice how negative numbers represent the past and positive numbers represent the future. It's a simple mapping: -1 day is yesterday; 1 day is tomorrow. I usually recommend initializing the RelativeTimeFormat object once and reusing it throughout your app rather than creating a new one every time you format a string. It's much better for performance.
The Magic of the 'auto' Style
One of my favorite parts of this API is the numeric option. If you set it to 'always', you get the literal number (e.g., "1 day ago"). But if you set it to 'auto', JavaScript will use a more natural term if one exists in that language.
const rtfAuto = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });
console.log(rtfAuto.format(-1, 'day')); // "yesterday"
console.log(rtfAuto.format(0, 'day')); // "today"
console.log(rtfAuto.format(1, 'day')); // "tomorrow"
This is where the Intl object really shines. If you change the locale to 'es' (Spanish), -1, 'day' automatically becomes "ayer". You don't have to write a massive switch statement or maintain a translation JSON file for basic time phrases.
Bridging the Gap Between Dates and Relative Strings
Here is the catch: Intl.RelativeTimeFormat doesn't actually do any date math. It doesn't know what "now" is; it just knows how to format a number you give it. To make this useful in a real app—like a social media feed—you have to calculate the difference yourself.
I usually handle this by subtracting the timestamps (in milliseconds) and dividing by the appropriate constant. Here is a quick way to handle a "posted X minutes ago" scenario:
function formatRelativeTime(date) {
const now = new Date();
const diffInSeconds = Math.floor((date - now) / 1000);
const rtf = new Intl.RelativeTimeFormat('en', { numeric: 'auto' });
// We can check the magnitude to decide which unit to use
if (Math.abs(diffInSeconds) < 60) {
return rtf.format(diffInSeconds, 'second');
}
const diffInMinutes = Math.floor(diffInSeconds / 60);
return rtf.format(diffInMinutes, 'minute');
}
const postDate = new Date(Date.now() - 120000); // 2 minutes ago
console.log(formatRelativeTime(postDate)); // "2 minutes ago"
You'll notice I used Math.abs(). This is important because whether the date is in the past or future, you need to know the absolute scale of the difference to decide if you should be talking in seconds, minutes, or days.
📋 Practical Task
Build a Dynamic Social Media Timestamp Formatter
Create a function called getSmartTimestamp(date). This function should take a Date object as an argument and return a human-readable relative string using Intl.RelativeTimeFormat with the numeric: 'auto' option.
Your function must implement the following logic to choose the correct unit:
- If the difference is less than 60 seconds, use
'second'. - If the difference is less than 60 minutes, use
'minute'. - If the difference is less than 24 hours, use
'hour'. - Otherwise, use
'day'.
Test your function with these three scenarios:
- A date from 30 seconds ago.
- A date from 3 hours ago.
- A date from exactly 1 day ago (should return "yesterday").
There are no comments for now.