😺
DBから取り出した日時データが画面上でUTCで扱われる場合の対処法(Next.js)
DB上に登録されているTIMESTAMP型のデータはタイムゾーン情報を持たないためUTCとして解釈される。
テーブルから取り出すと下記のように「000Z」=「UTC」となる。
2025-04-10T03:00:00.000Z
PostgreSQLで明示的にTimeZoneを指定する場合は
TIMESTAMPTZ(timestamp with time zone)型を使うこともできるようだが、今回は(色々試行錯誤して結果として)API側でテーブルから抜き出した後にタイムゾーンを付けた。
●変換の関数
function toJSTISOString(dateObj) {
// UTC → JST に変換して ISO 文字列で返す
return DateTime.fromJSDate(dateObj, { zone: 'Asia/Tokyo' }).toISO();
}
データを取り出す処理。jstStartとjstEndにJST変換後のTIMEデータが入っている。
const result = await pool.query('SELECT * FROM events');
const events = result.rows.map(row => {
console.log("raw start_time:", row.start_time);
const jstStart = toJSTISOString(row.start_time);
const jstEnd = toJSTISOString(row.end_time);
console.log("JST start_time:", jstStart);
return {
id: row.id,
title: row.title,
start: jstStart,
end: jstEnd,
booking_status: row.booking_status,
};
raw start_time: 2025-04-10T03:00:00.000Z (rawデータ)
JST start_time: 2025-04-10T12:00:00.000+09:00 (JSTに変更後)
これで明示的にTimeZoneを設定できているため、
ローカル環境/デプロイ環境関わらず、JSTで表示されるはず。
(試していないが)恐らく登録する時も下記のようにtimeZoneを指定する必要あり。(JST→UTC)
const tokyoTime = new Date().toLocaleString('sv-SE', { timeZone: 'Asia/Tokyo' });
因みに、TimeZone名は下記から確認可能です。Asia/Tokyoが多いと思いますが。
🌍 IANA公式リスト(Wikipedia):
🌐 Developer向けタイムゾーン一覧:
※ライブラリ Luxon のドキュメントですが、タイムゾーンIDは共通です。参考になれば幸いです。
Discussion