My website has a few places where I share how many years have passed since something happened. For example:
- How long The Outfit has been in business
- How long ago a photo was taken
- How far back I can remember the books I’ve read
Nobody has figured out how to stop time, so I needed to deal with the fact that those year numbers won’t stay accurate for very long. Here’s how I did it:
- I use JavaScript to calculate how many years have passed since a specified date
- My website is built with Eleventy, so I use that JavaScript in an Eleventy shortcode, which makes it easy to utilize anywhere I need it
- My website automatically rebuilds itself once per day, and it’s during this rebuild that the JavaScript recalculates all of the year numbers
How it works
In a directory named /src/_shortcodes
is a file called years-since.js
:
export default function yearsSince(dateString) {
// Is the passed-in value (dateString) really a string? Is it formatted as required?
if (typeof dateString !== 'string' || !/^\d{4}-\d{2}-\d{2}$/.test(dateString)) {
throw new Error('The `yearsSince` function requires a valid date string in the format "YYYY-MM-DD".');
}
// Convert dateString into a Date object.
const startDate = new Date(dateString);
// Is the new Date object (startDate) a valid, parsable date?
if (isNaN(startDate.getTime())) {
throw new Error(`Invalid date string passed to "yearsSince": ${dateString}`);
}
// Extract the year from startDate.
const startYear = startDate.getFullYear();
// Get the current date.
const now = new Date();
// Extract the year from the current date.
const currentYear = now.getFullYear();
// Calculate the difference between the current year and the start year.
let years = currentYear - startYear;
// Determine if the anniversary of the passed-in date has already occurred this year.
const hasCompletedThisYear =
now.getMonth() > startDate.getMonth() ||
(now.getMonth() === startDate.getMonth() && now.getDate() >= startDate.getDate());
// If the anniversary has already occurred this year, return the full number of years,
// otherwise subtract 1 since the current year’s anniversary hasn’t been reached yet.
return hasCompletedThisYear ? years : years - 1;
}
years-since.js
is imported into the eleventy.config.js
file:
// …
import YearsSince from './src/_shortcodes/years-since.js';
// …
export default async function (eleventyConfig) {
// …
eleventyConfig.addShortcode('yearsSince', YearsSince);
// …
};
Finally, I use that shortcode in my content. For example:
…running The Outfit for {% yearsSince '2012-06-01' %} years and…
My JavaScript and Eleventy skills aren’t the greatest, so I welcome all feedback, criticism, etc.: marcamos@gmail.com.