Next.js(Pages Router)v16で異なるロケールの日付をフォーマットする方法

地域固有の形式で日付を表示する

問題

日付の表記形式は世界共通ではありません。例えば、10/12/2025という表記はアメリカでは10月12日を意味しますが、イギリスでは12月10日を意味します。「Oct 12, 2025」と書くと、英語の月名と特定の順序の慣習を前提としています。各地域には、構成要素の順序、区切り文字、月名を単語として表示するか数字として表示するかなど、日付形式に関する独自の期待があります。

日付を単一の形式で表示すると、その形式の地域外のユーザーにとってアプリケーションが違和感を与えます。ユーザーは日付を誤解したり、読みにくいと感じたりする可能性があります。ある対象者にとって明確な日付が、別の対象者にとっては混乱や曖昧さを招くことがあります。

解決策

ユーザーのロケールに基づいて日付をフォーマットし、日付の値を地域ルールに従った順序、区切り文字、月名を持つ文字列に変換します。ブラウザのIntl.DateTimeFormat APIは、ロケールとオプションのフォーマット設定が与えられると、ロケール固有のフォーマットルールを自動的に処理します。

react-intlは、このAPIをラップしアプリケーションのロケールコンテキストと統合するコンポーネントとフックを提供します。これらのツールに日付の値とフォーマットオプションを渡すことで、ユーザーの言語と地域に合わせて明確で自然な方法で日付がレンダリングされます。

ステップ

1. FormattedDateを使用して日付フォーマットコンポーネントを作成する

FormattedDateコンポーネントは日付の値とIntl.DateTimeFormatOptionsに準拠するフォーマットオプションを受け入れます。希望する詳細レベルで日付を表示するコンポーネントを作成します。

import { FormattedDate } from "react-intl";

interface EventDateProps {
  date: Date;
}

export function EventDate({ date }: EventDateProps) {
  return (
    <time dateTime={date.toISOString()}>
      <FormattedDate value={date} year="numeric" month="long" day="numeric" />
    </time>
  );
}

FormattedDateはIntlProviderコンテキストからロケールを読み取り、それに応じて日付をフォーマットします。このコンポーネントはen-USでは「October 12, 2025」、en-GBでは「12 October 2025」と表示されます。

2. useIntlを使用して命令的に日付をフォーマットする

Reactコンポーネントが使用できないケース(テキスト属性の設定など)では、useIntlフックを使用してformatDateメソッドにアクセスします。

import { useIntl } from "react-intl";

interface ArticleImageProps {
  src: string;
  publishedAt: Date;
}

export function ArticleImage({ src, publishedAt }: ArticleImageProps) {
  const intl = useIntl();

  const formattedDate = intl.formatDate(publishedAt, {
    year: "numeric",
    month: "short",
    day: "numeric",
  });

  return <img src={src} alt={`${formattedDate}に公開された記事`} />;
}

formatDateメソッドはフォーマットされた日付文字列を返し、DateTimeFormatOptionsに準拠したオプションを受け入れます。このアプローチは属性、サーバーサイドコード、またはパフォーマンスが重要なシナリオに役立ちます。

3. 標準オプションでフォーマットの詳細を調整する

year、month、day、weekdayなどのオプションに「numeric」、「2-digit」、「long」、「short」、「narrow」などの値を指定することで、日付コンポーネントの表示を制御します。

import { FormattedDate } from "react-intl";

export function FullEventDate({ date }: { date: Date }) {
  return (
    <FormattedDate
      value={date}
      weekday="long"
      year="numeric"
      month="long"
      day="numeric"
    />
  );
}

export function CompactDate({ date }: { date: Date }) {
  return (
    <FormattedDate value={date} year="2-digit" month="2-digit" day="2-digit" />
  );
}

FullEventDateコンポーネントはen-USでは「Monday, October 12, 2025」、de-DEでは「Montag, 12. Oktober 2025」と表示されます。CompactDateコンポーネントは、テーブルや限られたスペースに適した短い数値形式を生成します。

4. 再利用可能な日付フォーマッターヘルパーを作成する

複数のページで一貫した日付フォーマットを実現するために、一般的なフォーマットパターンをカプセル化するヘルパー関数を作成します。

import { useIntl } from "react-intl";

export function useDateFormatters() {
  const intl = useIntl();

  return {
    formatShortDate: (date: Date) =>
      intl.formatDate(date, {
        year: "numeric",
        month: "short",
        day: "numeric",
      }),

    formatLongDate: (date: Date) =>
      intl.formatDate(date, {
        weekday: "long",
        year: "numeric",
        month: "long",
        day: "numeric",
      }),

    formatMonthYear: (date: Date) =>
      intl.formatDate(date, {
        year: "numeric",
        month: "long",
      }),
  };
}

このフックをページコンポーネントにインポートして使用することで、オプションを繰り返すことなく一貫した日付フォーマットを実現できます。

5. ページコンポーネントでヘルパーを使用する

Next.jsのページでデートフォーマッターヘルパーを適用して、ロケールに対応した日付を表示します。

import { GetStaticProps } from "next";
import { useDateFormatters } from "../lib/useDateFormatters";

interface Post {
  title: string;
  publishedAt: string;
  content: string;
}

interface BlogPostPageProps {
  post: Post;
}

export default function BlogPostPage({ post }: BlogPostPageProps) {
  const { formatLongDate } = useDateFormatters();
  const publishedDate = new Date(post.publishedAt);

  return (
    <article>
      <h1>{post.title}</h1>
      <p>Published: {formatLongDate(publishedDate)}</p>
      <div>{post.content}</div>
    </article>
  );
}

export const getStaticProps: GetStaticProps = async () => {
  const post = {
    title: "Understanding Internationalization",
    publishedAt: "2025-10-12T00:00:00Z",
    content: "Content here...",
  };

  return {
    props: { post },
  };
};

このページは、ユーザーのロケール形式で公開日を表示し、どの地域の読者にとっても日付がすぐに理解でき、親しみやすいものになります。