- Prisma は DB に時間を書き込むとき DB, System の timezone に関わらず UTC で保存する。
- DB で時刻を持つときはすべて UTC を規定にする
prisma.use を使用して読み出すときは UTC 時間にして値を返す
// Subtract 9 hours from all the Date objects recursively
function subtract9Hours(obj: Record<string, unknown>) {
if (!obj) return
for (const key of Object.keys(obj)) {
const val = obj[key]
if (val instanceof Date) {
obj[key] = dayjs(val).subtract(9, 'hour').toDate()
} else if (!isPrimitive(val)) {
subtract9Hours(val as any)
}
}
}
function prismaTimeMod<T>(value: T): T {
if (value instanceof Date) {
return dayjs(value).subtract(9, 'hour').toDate() as any
}
if (isPrimitive(value)) {
return value
}
subtract9Hours(value as any)
return value
}
// Create a prisma client instance with timemod
const prisma = new PrismaClient()
prisma.$use(async (params, next) => {
const result = await next(params)
return prismaTimeMod(result)
})
}
prisma.xxx.create, update をするときは timezoneOffset が足された CustomDate を作りそれを使用する
const originDate = Date;
const HOURS_OFFSET = -9;
class DateWithOffset extends Date{
constructor(options) {
if (options) {
if (typeof options === 'string'){
const t = new originDate(options);
const d = new originDate(t.setHours(t.getHours()+HOURS_OFFSET));
super(d);
}else{
super(options);
}
} else {
super(originDate.now());
}
}
}
この例では、PSL定義のデフォルト値が1975-08-19T23:15:30+07:00であり、異なるタイプのdatetimeカラムで何が間違っているのかを観察しています。すべての場合において、クエリーエンジンは、挿入および更新ステートメントにおいて、値を 1975-08-19T16:15:30Z に変換しています。
Prismaは1975-08-19 16:15:30を挿入します。データベースには、他のシステムから挿入された値があり、データベースのデフォルト値である 1975-08-19 23:15:30 という値を尊重しています。この時点で、Prismaによってデータベースに2つの異なるデフォルト値が存在することになります。
これは、Prismaがデータタイムに使用するデフォルトのネイティブ型です。
Prismaはデフォルト値16:15:30を挿入します。他のシステムでは23:15:30が挿入されるため、データベースには2つの異なるデフォルト値が存在し、どちらが正しいのかが分からなくなります。
この例では、PSLにデフォルトの1975-08-19T00:05:30+01:00が格納されています。UTCへの変換により、この値は1975-08-18T23:05:30Zに変換されます。Prismaは1975-08-18という値を挿入し、データベースに書き込む他のシステムは1975-08-19という値を挿入します。
タイムスタンプ値は、常にUTCの1970-01-01 00:00:00からの(マイクロ)秒数である。タイムゾーン間で変換しても、基本的な値は変わりません。TIMESTAMPタイプは、ユーザーがUTC以外のタイムゾーンを使用している場合、Prismaによって間違って設定されない唯一のものです。