date-fnsで過去の日付を現在時刻との差で分かりやすく表示する「formatDistanceToNow」


"date-fns"ライブラリは、JavaScriptにおける日付操作を簡素化する便利なツールです。"Common Helpers"と呼ばれる機能群には、よく使用される日付処理関数が多数含まれています。その中でも、**"formatDistanceToNow"**は、指定された日付と現在時刻との差を、人間に分かりやすい表現に変換するものです。

本解説では、"formatDistanceToNow"のプログラミングについて、分かりやすく詳細に説明していきます。

"formatDistanceToNow"の基本的な使い方

import { formatDistanceToNow } from 'date-fns';

const date = new Date(2024, 5, 19); // 過去の任意の日付
const distance = formatDistanceToNow(date);
console.log(distance); // 例: "43 days ago"

上記のコード例では、formatDistanceToNow関数に過去の任意の日付を代入し、現在時刻との差を文字列として取得しています。結果は"43 days ago"となり、指定された日付が現在から43日前であることが分かります。

"formatDistanceToNow"のオプション

formatDistanceToNow関数には、出力形式をカスタマイズするためのオプションが用意されています。主なオプションは以下の通りです。

  • locale: 使用するロケールを指定します。デフォルトはブラウザのロケールです。
  • includeSeconds: trueに設定すると、秒数を含むようにします。デフォルトはfalseです。
  • addSuffix: trueに設定すると、"ago"や"from now"などの接尾辞を追加します。デフォルトはfalseです。
import { formatDistanceToNow } from 'date-fns';

const date = new Date(2024, 5, 19);
const distance1 = formatDistanceToNow(date); // 例: "43 days ago"
const distance2 = formatDistanceToNow(date, { addSuffix: true, includeSeconds: true }); // 例: "43 days and 2 hours ago"
const distance3 = formatDistanceToNow(date, { locale: 'ja' }); // 例: "43日前"
console.log(distance1);
console.log(distance2);
console.log(distance3);

上記のように、オプションを組み合わせることで、様々な形式で差を表示することができます。

"formatDistanceToNow"の活用例

  • チャットアプリにおけるメッセージの送信時間表示
  • ニュース記事の公開日時表示
  • ソーシャルメディアのタイムスタンプ表示

"formatDistanceToNow"は、ユーザーインターフェースにおける日付表現をより自然で分かりやすくするのに役立ちます。



import { formatDistanceToNow } from 'date-fns';

const now = new Date();
const pastDate = new Date(2024, 5, 19); // 過去の任意の日付
const futureDate = new Date(2024, 6, 20); // 未来の任意の日付

console.log(formatDistanceToNow(pastDate)); // 例: "44 days ago"
console.log(formatDistanceToNow(futureDate)); // 例: "1 day from now"
console.log(formatDistanceToNow(now)); // 例: "just now"

オプションを活用した例

import { formatDistanceToNow } from 'date-fns';

const now = new Date();
const pastDate = new Date(2024, 5, 19);

console.log(formatDistanceToNow(pastDate, { addSuffix: true })); // 例: "44 days ago"
console.log(formatDistanceToNow(pastDate, { addSuffix: true, includeSeconds: true })); // 例: "44 days and 2 hours ago"
console.log(formatDistanceToNow(pastDate, { locale: 'ja' })); // 例: "44日前"

特定の期間を強調する例

import { formatDistanceToNow } from 'date-fns';

const now = new Date();
const dates = [
  new Date(2024, 6, 19), // 1日前
  new Date(2024, 6, 12), // 1週間前
  new Date(2024, 5, 19), // 1ヶ月前
  new Date(2023, 12, 31), // 半年前
];

for (const date of dates) {
  const distance = formatDistanceToNow(date);
  const isLessThanWeek = distance.includes('week');
  const isLessThanMonth = distance.includes('month');

  console.log(`${date} - ${distance}`);

  if (isLessThanWeek) {
    console.log('  - この1週間以内に発生した出来事');
  } else if (isLessThanMonth) {
    console.log('  - この1ヶ月以内に発生した出来事');
  }
}

上記コードでは、配列に格納された過去の各日付と現在時刻との差を表示し、それぞれが1週間以内、1ヶ月以内の経過時間かどうかを判定してログ出力しています。

  • "formatDistanceToNow"はあくまでも目安として利用し、より詳細な時間表現が必要な場合は、他の日付操作関数と組み合わせて利用することを検討しましょう。
  • 具体的な利用シーンに合わせて、オプションを組み合わせたり、独自のロジックを追加したりすることで、より柔軟な表現が可能になります。


ここでは、"formatDistanceToNow"の代替方法として検討すべき2つのアプローチを紹介します。

Intl.DateTimeFormatの利用

ブラウザの標準機能であるIntl.DateTimeFormatを利用することで、"formatDistanceToNow"と同様の機能を実現することができます。Intl.DateTimeFormatは、ロケールに合わせた日付書式を簡単に生成することができます。

const now = new Date();
const pastDate = new Date(2024, 5, 19);

const relativeFormatter = new Intl.RelativeTimeFormat('ja', {
  units: ['second', 'minute', 'hour', 'day', 'week', 'month', 'year'],
});

const distance = relativeFormatter.format(now - pastDate, 'long');
console.log(distance); // 例: 44日前

上記コードでは、Intl.RelativeTimeFormatを使用して、過去の日付と現在時刻との差を"44日前"という形式で出力しています。

利点

  • ロケールに合わせた自然な表現を生成できます。
  • ブラウザの標準機能なので、ライブラリの追加インストールが不要です。

欠点

  • 一部の古いブラウザではサポートされていない可能性がある。
  • "formatDistanceToNow"ほど詳細なオプションが用意されていない。

手動の計算と文字列操作

比較的単純な表現が必要な場合は、手動で計算と文字列操作を行う方法もあります。

const now = new Date();
const pastDate = new Date(2024, 5, 19);

const milliseconds = now - pastDate;
const seconds = Math.floor(milliseconds / 1000);
const minutes = Math.floor(seconds / 60);
const hours = Math.floor(minutes / 60);
const days = Math.floor(hours / 24);

let distance;

if (days === 0) {
  if (hours === 0) {
    if (minutes === 0) {
      distance = `${seconds}秒前`;
    } else {
      distance = `${minutes}分前`;
    }
  } else {
    distance = `${hours}時間前`;
  }
} else {
  distance = `${days}日前`;
}

console.log(distance); // 例: 44日前

上記コードでは、現在時刻と過去の日付との差をミリ秒単位で取得し、秒、分、時、日の単位に変換しています。その後、それぞれの値に基づいて差を文字列として組み立てています。

利点

  • 古いブラウザでも動作します。
  • 完全な制御が可能で、必要な情報のみを出力することができます。

欠点

  • ロケールに合わせた調整が必要になる場合がある。
  • ロジックが複雑になりやすく、メンテナンスが大変になる可能性がある。

適切な方法の選択

どの方法が適切かは、具体的な要件や状況によって異なります。

  • いずれの方法を選択する場合も、パフォーマンスと可読性を考慮することが重要です。
  • より詳細な表現が必要な場合や、古いブラウザでの動作が必須の場合は、"formatDistanceToNow"または手動の計算と文字列操作を検討しましょう。
  • シンプルで標準的な表現が必要な場合は、Intl.DateTimeFormatの利用を検討しましょう。
  • 必要に応じて、複数の方法を組み合わせることも可能です。
  • 上記以外にも、Moment.jsやLuxonなどのライブラリを利用する方法もあります。