expo-localization と Intl を使ってUTCの時刻文字列をローカル時刻に変換する

new Date() を使って作成した日付オブジェクトで toISOString() を呼び出すと、 ISO 8601 形式の文字列を返します。YYYY-MM-DDTHH:mm:ss.sssZ の形の文字列となり、タイムゾーンは常に 0 UTC オフセットとなります。

Date.prototype.toISOString()

端末に表示するときは、その端末のロケールに合わせた時刻を表示しなければならないこともあるかと思います。

日本の場合は UTC + 9時間なので、UTCのまま表示してしまうと、日付がずれてしまうこともあります。

そのため、表示前に変換が必要となるでしょう。

ISO8601の時刻文字列をタイムゾーンに合わせた日付に変換する

expo-localization を使ってロケールとタイムゾーンを取得します。

以下はタイムゾーンを考慮して、ISO8601の文字列を現地日付に変換する関数です。例では yyyy-mm-dd で返していますが、yyyy-mm-dd:hh:mm:ss とすることもできます。

function convertUtcToLocalDate(utcString: string) {
  const date = new Date(utcString);

  // ロケールとタイムゾーンを取得
  const locale = Localization.locale;

  // deprecated の件はブログにまとめる
  // const timeZone = Localization.timezone;
  const timeZone = Localization.getCalendars()[0].timeZone;

  // DateTimeFormatオプションを設定
  const options: Intl.DateTimeFormatOptions = {
    year: 'numeric',
    month: '2-digit',
    day: '2-digit',
    timeZone: timeZone ?? Localization.timezone,
  };

  const formatter = new Intl.DateTimeFormat(locale, options);

  // フォーマットされたローカル日付を返す
  const parts = formatter.formatToParts(date);
  let year = '';
  let month = '';
  let day = '';
  for (const part of parts) {
    switch (part.type) {
      case 'year':
        year = part.value;
        break;
      case 'month':
        month = part.value;
        break;
      case 'day':
        day = part.value;
        break;
    }
  }
  return `${year}-${month}-${day}`;
}

ISO8601の時刻文字列を mm月dd日 hh:mm:ss の形式で返す

expo-localizationLocalization.locale; を使えば、端末のロケール情報を取得できます。

ロケール情報を活用して、各国に合わせた形に日付をフォーマットできます。

import * as Localization from 'expo-localization';

export function formatToLocalDateTime(utcDateString: string) {
  // UTCの日付文字列をDateオブジェクトに変換
  const date = new Date(utcDateString);

  // 現在のロケールを取得(expo-localizationを使用)
  const locale = Localization.locale;

  // Intl.DateTimeFormatを使用してローカルの日付と時刻のフォーマットを作成
  const formatter = new Intl.DateTimeFormat(locale, {
    month: 'long',
    day: 'numeric',
    hour: '2-digit',
    minute: '2-digit',
    second: '2-digit',
    hour12: false,
  });

  // フォーマットされた文字列を返す
  return formatter.format(date);
}

Localization.timezone が deprecated になっている罠

Localization.timezone は deprecated になっています。Use Localization.getLocales() というメッセージが出ますが、 Localization.getLocales() では timezone は取れません。コメントのミスです。

timezone は以下のように取得しましょう。

const timeZone = Localization.getCalendars()[0].timeZone;