プログラム内部のDateをUTCに統一する
Dateは2つの軸で問題がある
タイムゾーンを統一するかどうか
UTC? JST?
日付のフォーマットを統一するかどうか
ISO8601? UnixTime?
「外部」をどこまでと見なすか
パターン1
内部: プログラム内部
外部: DB, View
パターン2
内部: プログラム内部, DB
外部: View
これは状況にもよる
DBが他のシステムからもアクセスされるならパターン1だろうし、
そうじゃないならパターン2のほうが単純
内部のデータ構造の要件
他の型と識別できる
TSならbranded typeなど
serializeできる
TSならDateは無理
結論の例
Prismaを使っているような状況だとする
プログラムの内部では、
UTCを使用する
フォーマットはISO8601に準拠する
UnixTimeより可読性が高いので
例えば以下のようなモジュールを用意する
code:ts
import { z } from 'zod';
import dayjs from 'dayjs';
import utc from 'dayjs/plugin/utc';
import timezone from 'dayjs/plugin/timezone';
dayjs.extend(utc);
dayjs.extend(timezone);
// ISO8601 (UTC)
export type UTC = z.infer<typeof UTC>;
export const UTC = z.string().datetime().brand<'UTC'>();
export const mkUTC = (date: string | Date): UTC => {
if (date instanceof Date) {
const utcDate = dayjs(date).tz('UTC').format();
return UTC.parse(utcDate);
}
if (!date.includes('T')) {
throw new Error(
'Invalid date format. Expected a combined date and time in the ISO 8601 format.',
);
}
if (date.endsWith('Z')) {
return UTC.parse(date);
}
if (date.includes('+') || date.includes('-')) {
const utcDate = dayjs(date).tz('UTC').format();
return UTC.parse(utcDate);
}
throw new Error('Invalid input type. Expected string or Date.');
};
export const toJSTFormat = (utc: UTC, template: string): string => {
return dayjs(utc).tz('Asia/Tokyo').format(template);
};
例えばEntityのcreatedAtなど、プログラム内の全ての日付にUTC型を使用する
Viewなどに日付を表示する際はtoJSTFormatを使う
現在の時刻を出力する例
code:ts
toJSTFormat(mkUTC(new Date()), 'YYYY/MM/DD HH:mm:ss')
以下のような事を気にする必要がなくなる
client/serverの両方でUTCに統一される