javascript - 我们可以始终使用 knex 和 postgres 将日期列作为字符串(varchar)获取吗?
问题描述
我在 postgres 数据库中有一个类型为date
. 它是一个类似于生日的列,它只是一个日期,不需要有时间部分。
使用 knex 获取此列时,结果是一个 javascript Date 对象。大概是在做new Date(row.birthday)
,这是发送给客户端的结果。
现在的问题是客户端收到的值是标准 ISO 8601 格式,带有时间部分和Z
. 当客户端尝试从此字符串创建新的 Date 对象时,客户端可能会根据客户端所在的位置具有错误的日期值。
例如:
Date: 2018-06-15
Date sent to client: 2018-06-15T00:00:00Z
Client in +5:00 | Client in -5:00
2018-06-16 05:00:00 | 2018-05-15 10:00:00
如果服务器在 UTC 中,这很好,我们可以添加客户端的时区偏移量并获取原始日期,但这感觉有点脆弱,并且在本地开发期间会中断(不是 UTC)。
一个简单的解决方案是将日期部分作为字符串发送给客户端。但这需要将日期存储varchar
在服务器中,我们不想这样做。我们将失去日期格式的约束,并且会使使用 SQL 进行基于日期的计算变得更加困难。
我们可以像varchar
选择列时那样转换列,但是每次获取此表时我们都需要有心去做。这也意味着我们需要绕过 ORM(书架)来处理这个表。
是否有一种简单的方法可以在 knex 或 bookshelf 或 postgres 本身中指定一个列需要存储为date
,并带有所有随附的约束,但始终被获取为varchar
?
解决方案
node-postgres 驱动程序是从日期列发送的数据实际创建 Date() 对象的部分(https://node-postgres.com/features/types#date-timestamp-timestamptz)
使用 postgres,您可以修改 node-pg 的类型解析器,如https://github.com/brianc/node-pg-types中所述
日期类型类型的 oid 为 1082 可以通过以下查询获取
select typname, oid, typarray from pg_type where typname = 'date' order by oid;
因此,要覆盖要作为字符串传递的日期类型,在设置数据库连接之前执行此操作就足够了(我想可以在 knexfile.js 中执行此操作):
var types = require('pg').types;
// override parsing date column to Date()
types.setTypeParser(1082, val => val);
推荐阅读
- laravel - 如何在主管中动态更改 numprocs
- java - 使用 JPA Criteria API 将子查询 SELECT 作为字段
- c++ - 就地合并向量的 N 段 C++
- angular - 在`npm update`之后得到`error TS2304: Cannot find name 'module'`
- php - 卷曲到 yii1.1 动作返回空结果
- javascript - 如何使用 React Native JS 将一个页面重定向到另一个页面
- gdb - 如何使用 gdb 闯入正在运行的程序?
- c - Windows 是否有 sigaltstack 和 sigaction 的替代品?
- c# - 如何注册装饰器以解析装饰器
- python-3.x - 需要帮助关闭自动打开的 Internet Explorer 网页