liam.pm

Relative date time web component

A simple, progressive web component to show a relative "time ago" for a date time.

<html>
  <body>
    <h1>Relative time web component examples</h1>
    <p>
      Published
      <time is="relative-time" datetime="2024-01-22T12:00:00Z">
        January 22, 2024
      </time>
    </p>
    <p>
      Published
      <time is="relative-time" datetime="2024-01-15T12:00:00Z">
        January 15, 2024
      </time>
    </p>
    <h2>International Support</h2>
    <p>
      Publicado
      <time is="relative-time" datetime="2023-12-22T12:00:00Z" lang="es">
        22 de diciembre de 2023
      </time>
    </p>
    <script>
      class RelativeTime extends HTMLTimeElement {
        connectedCallback() {
          const date = new Date(this.dateTime);
          const now = new Date();
          const elapsed = now - date;
          const lang = this.lang || "en";

          const formatter = new Intl.RelativeTimeFormat(lang, {
            numeric: "auto",
          });

          const minutes = Math.floor(elapsed / 60000);
          const hours = Math.floor(elapsed / 3600000);
          const days = Math.floor(elapsed / 86400000);
          const weeks = Math.floor(elapsed / 604800000);
          const months = Math.floor(elapsed / 2628000000);
          const years = Math.floor(elapsed / 31540000000);

          let relativeTime;
          if (minutes < 1) {
            relativeTime = formatter.format(0, "minute");
          } else if (minutes < 60) {
            relativeTime = formatter.format(-minutes, "minute");
          } else if (hours < 24) {
            relativeTime = formatter.format(-hours, "hour");
          } else if (days < 7) {
            relativeTime = formatter.format(-days, "day");
          } else if (weeks < 4) {
            relativeTime = formatter.format(-weeks, "week");
          } else if (months < 12) {
            relativeTime = formatter.format(-months, "month");
          } else {
            relativeTime = formatter.format(-years, "year");
          }

          this.textContent = relativeTime;
        }
      }

      customElements.define("relative-time", RelativeTime, {
        extends: "time",
      });
    </script>
  </body>
</html>

Key features

Note: This calculates once when the component loads. For live updating times, you'd need to add an interval timer.