插件窝 干货文章 Prisma 创建数据时间丢失 8 小时:如何避免时区差异?

Prisma 创建数据时间丢失 8 小时:如何避免时区差异?

时间 Prisma params 应用层 951    来源:    2025-04-01

Prisma 数据时间丢失8小时问题解决方案

问题分析

当使用Prisma创建数据时出现时间丢失8小时的情况,这通常是由于时区配置不一致导致的。中国标准时间(CST)是UTC+8,而数据库可能默认使用UTC时间,因此会出现8小时的差异。

解决方案

1. 数据库层面配置

MySQL/MariaDB:

-- 设置数据库时区
SET GLOBAL time_zone = '+8:00';
SET time_zone = '+8:00';

PostgreSQL:

-- 设置数据库时区
SET TIME ZONE 'Asia/Shanghai';

2. Prisma客户端配置

在创建Prisma客户端时指定时区:

const prisma = new PrismaClient({
  datasources: {
    db: {
      url: "mysql://user:password@localhost:3306/db?connection_limit=5&timezone=Asia%2FShanghai"
    }
  }
});

3. 应用层处理

方案一:在应用层转换时间

// 存储前转换为UTC
const now = new Date();
const utcDate = new Date(now.getTime() - now.getTimezoneOffset() * 60000);

// 读取时转换回本地时间
const dbDate = new Date(utcDate.getTime() + 8 * 60 * 60 * 1000);

方案二:使用中间件自动处理

prisma.$use(async (params, next) => {
  if (['create', 'update'].includes(params.action)) {
    for (const key in params.args.data) {
      if (params.args.data[key] instanceof Date) {
        params.args.data[key] = new Date(params.args.data[key].getTime() - params.args.data[key].getTimezoneOffset() * 60000);
      }
    }
  }
  const result = await next(params);
  return result;
});

4. 最佳实践建议

  1. 统一使用UTC时间存储:在数据库中统一存储UTC时间,只在展示层转换为本地时间
  2. 明确文档说明:在团队文档中明确时间处理规范
  3. 使用ISO8601格式:在API传输中使用ISO格式时间字符串

验证方法

创建测试数据后,检查数据库中的时间戳和应用层获取的时间是否一致:

const test = await prisma.test.create({
  data: {
    createdAt: new Date()
  }
});

console.log('应用层时间:', test.createdAt);
// 直接查询数据库比较存储的时间

通过以上方法,您应该能够解决Prisma中时间丢失8小时的问题。