在 Knex dateTime()/MySQL DATETIME 字段中存储 Node.js 日期
Storing a Node.js Date in a Knex dateTime()/MySQL DATETIME field
我在寻找 Node.js、knex 和 MySQL(通过 Bookshelf)通用的日期格式时遇到了一些问题。
我使用 Knex 架构构建器设置了 table:
knex.schema.createTableIfNotExists("examples", function (table) {
...
table.dateTime("some_datetime");
})
这将在 MySQL 中创建一个具有 DATETIME
类型的列。
我有一个 Bookshelf 模型来表示这个(这里省略了所有样板文件),我尝试使用内置的 Date.now()
作为值:
exampleModel.save({
some_datetime: Date.now()
})
在 Knex 中打开调试后,我看到查询实际上是在尝试插入一个以毫秒为单位的纪元时间戳(“...”为简洁起见,我的):
{ ...
bindings: [ 1485644012453, ... ],
sql: 'update `examples` set `some_datetime` = ? where `id` = ?' }
但这是不正确的,因为在这种情况下 MySQL expects you to use FROM_UNIXTIME
,因此数据库中的结果日期当然是好的 0000-00-00 00:00:00
。
我应该在这里做什么才能使这一切保持一致?
- 创建 table 时,我应该在架构构建器中使用不同的类型吗?
- 或者,除了
Date.now()
之外,我还应该使用其他方法来获取日期吗?
- 或者,别的东西?
我在这里找不到共同点。我的直觉是在 Knex 中使用 dateTime
,在 Node 中使用 Date.now()
,在 MySQL 中使用 DATETIME
,但这是不正确的。
需要说明的是:这个问题不一定关注什么是哲学上正确的——目前我实际上无法弄清楚如何在 [=42] 的数据库中存储 date/times =]全部。我正在寻找一个 工作 组合,语义正确性只是一个奖励。
Javascript 函数 Date.now()
returns 以毫秒为单位的纪元。 Mysql 驱动程序,knex
用于发送查询,希望您将 ISO8061 字符串或 Date()
对象传递到 DATETIME
列。
Date objects are converted to 'YYYY-mm-dd HH:ii:ss' strings
https://github.com/mysqljs/mysql
所以不用 Date.now()
使用 new Date()
或 new Date().toISOString()
编辑:
只是检查 mysql 是否真的接受 .toISOString()
输出,因为我无法从文档中找到关于它的提及 https://dev.mysql.com/doc/refman/5.7/en/date-and-time-type-overview.html
MariaDB [(none)]> select CAST('2017-01-30T16:49:19.278Z' AS DATETIME);
+----------------------------------------------+
| CAST('2017-01-30T16:49:19.278Z' AS DATETIME) |
+----------------------------------------------+
| 2017-01-30 16:49:19 |
+----------------------------------------------+
1 row in set, 1 warning (0.00 sec)
看起来确实如此。耶!一切顺利。
EDIT2:实际上,在某些情况下,使用 .toISOString()
会导致警告和错误,因此插入 UTC DATETIME 列 .toISOString().replace('Z','').replace('T', ' ')
应该......或任何其他首选方法使 UTC 日期时间对象转换为 yyyy-MM-dd HH:mm:ss
.
格式
此外,如果您使用的是 TIMESTAMP 列类型并且想要将 UTC 时间插入数据库,那么将数据库会话设置为 UTC 也很重要。否则,javascript 时间戳将被解释为本地数据库时间,并在存储之前将其转换为 UTC。
CREATE TABLE test (descr TEXT, dt DATETIME, ts TIMESTAMP);
SET time_zone = '+8:00';
INSERT INTO test (descr, dt, ts) VALUES
('session tz +08:00 insert local times', '2020-01-01T00:00:00', '2020-01-01T00:00:00');
SET time_zone = '+0:00';
INSERT INTO test (descr, dt, ts) VALUES
('session tz +00:00 insert local times', '2020-01-01 00:00:00', '2020-01-01 00:00:00');
SET time_zone = '+02:00';
select 'server local time:', now();
select * from test;
SET time_zone = '+08:00';
select 'server local time:', now();
select * from test;
---
**Query #1**
SET time_zone = '+02:00';
There are no results to be displayed.
---
**Query #2**
select 'server local time:', now();
| server local time: | now() |
| ------------------ | ------------------- |
| server local time: | 2020-05-10 16:38:26 |
---
**Query #3**
select * from test;
| descr | dt | ts |
| ------------------------------------ | ------------------- | ------------------- |
| session tz +08:00 insert local times | 2020-01-01 00:00:00 | 2019-12-31 18:00:00 |
| session tz +00:00 insert local times | 2020-01-01 00:00:00 | 2020-01-01 02:00:00 |
---
**Query #4**
SET time_zone = '+08:00';
There are no results to be displayed.
---
**Query #5**
select 'server local time:', now();
| server local time: | now() |
| ------------------ | ------------------- |
| server local time: | 2020-05-10 22:38:26 |
---
**Query #6**
select * from test;
| descr | dt | ts |
| ------------------------------------ | ------------------- | ------------------- |
| session tz +08:00 insert local times | 2020-01-01 00:00:00 | 2020-01-01 00:00:00 |
| session tz +00:00 insert local times | 2020-01-01 00:00:00 | 2020-01-01 08:00:00 |
---
显示如何存储和读取 TIMESTAMP 实际上总是作为当地时间处理,DATATIME 独立于 time_zone 数据库会话的设置。
通过快速测试,即使在 mysql 8.
上,我也无法使 yyyy-MM-dd HH:mm:ss+zz:zz
类型的时间戳/日期时间正常工作
您可以使用 Knex.js 的内置 now()
函数代替 Date.now()
:
const knexfile = require('../../knexfile');
const knex = require('knex')(knexfile.development);
const date = knex.fn.now();
选择:
const knexfile = require('../../knexfile');
const knex = require('knex')(knexfile.development);
knex.raw('CURRENT_TIMESTAMP');
我在寻找 Node.js、knex 和 MySQL(通过 Bookshelf)通用的日期格式时遇到了一些问题。
我使用 Knex 架构构建器设置了 table:
knex.schema.createTableIfNotExists("examples", function (table) {
...
table.dateTime("some_datetime");
})
这将在 MySQL 中创建一个具有 DATETIME
类型的列。
我有一个 Bookshelf 模型来表示这个(这里省略了所有样板文件),我尝试使用内置的 Date.now()
作为值:
exampleModel.save({
some_datetime: Date.now()
})
在 Knex 中打开调试后,我看到查询实际上是在尝试插入一个以毫秒为单位的纪元时间戳(“...”为简洁起见,我的):
{ ...
bindings: [ 1485644012453, ... ],
sql: 'update `examples` set `some_datetime` = ? where `id` = ?' }
但这是不正确的,因为在这种情况下 MySQL expects you to use FROM_UNIXTIME
,因此数据库中的结果日期当然是好的 0000-00-00 00:00:00
。
我应该在这里做什么才能使这一切保持一致?
- 创建 table 时,我应该在架构构建器中使用不同的类型吗?
- 或者,除了
Date.now()
之外,我还应该使用其他方法来获取日期吗? - 或者,别的东西?
我在这里找不到共同点。我的直觉是在 Knex 中使用 dateTime
,在 Node 中使用 Date.now()
,在 MySQL 中使用 DATETIME
,但这是不正确的。
需要说明的是:这个问题不一定关注什么是哲学上正确的——目前我实际上无法弄清楚如何在 [=42] 的数据库中存储 date/times =]全部。我正在寻找一个 工作 组合,语义正确性只是一个奖励。
Javascript 函数 Date.now()
returns 以毫秒为单位的纪元。 Mysql 驱动程序,knex
用于发送查询,希望您将 ISO8061 字符串或 Date()
对象传递到 DATETIME
列。
Date objects are converted to 'YYYY-mm-dd HH:ii:ss' strings
https://github.com/mysqljs/mysql
所以不用 Date.now()
使用 new Date()
或 new Date().toISOString()
编辑:
只是检查 mysql 是否真的接受 .toISOString()
输出,因为我无法从文档中找到关于它的提及 https://dev.mysql.com/doc/refman/5.7/en/date-and-time-type-overview.html
MariaDB [(none)]> select CAST('2017-01-30T16:49:19.278Z' AS DATETIME);
+----------------------------------------------+
| CAST('2017-01-30T16:49:19.278Z' AS DATETIME) |
+----------------------------------------------+
| 2017-01-30 16:49:19 |
+----------------------------------------------+
1 row in set, 1 warning (0.00 sec)
看起来确实如此。耶!一切顺利。
EDIT2:实际上,在某些情况下,使用 .toISOString()
会导致警告和错误,因此插入 UTC DATETIME 列 .toISOString().replace('Z','').replace('T', ' ')
应该......或任何其他首选方法使 UTC 日期时间对象转换为 yyyy-MM-dd HH:mm:ss
.
此外,如果您使用的是 TIMESTAMP 列类型并且想要将 UTC 时间插入数据库,那么将数据库会话设置为 UTC 也很重要。否则,javascript 时间戳将被解释为本地数据库时间,并在存储之前将其转换为 UTC。
CREATE TABLE test (descr TEXT, dt DATETIME, ts TIMESTAMP);
SET time_zone = '+8:00';
INSERT INTO test (descr, dt, ts) VALUES
('session tz +08:00 insert local times', '2020-01-01T00:00:00', '2020-01-01T00:00:00');
SET time_zone = '+0:00';
INSERT INTO test (descr, dt, ts) VALUES
('session tz +00:00 insert local times', '2020-01-01 00:00:00', '2020-01-01 00:00:00');
SET time_zone = '+02:00';
select 'server local time:', now();
select * from test;
SET time_zone = '+08:00';
select 'server local time:', now();
select * from test;
---
**Query #1**
SET time_zone = '+02:00';
There are no results to be displayed.
---
**Query #2**
select 'server local time:', now();
| server local time: | now() |
| ------------------ | ------------------- |
| server local time: | 2020-05-10 16:38:26 |
---
**Query #3**
select * from test;
| descr | dt | ts |
| ------------------------------------ | ------------------- | ------------------- |
| session tz +08:00 insert local times | 2020-01-01 00:00:00 | 2019-12-31 18:00:00 |
| session tz +00:00 insert local times | 2020-01-01 00:00:00 | 2020-01-01 02:00:00 |
---
**Query #4**
SET time_zone = '+08:00';
There are no results to be displayed.
---
**Query #5**
select 'server local time:', now();
| server local time: | now() |
| ------------------ | ------------------- |
| server local time: | 2020-05-10 22:38:26 |
---
**Query #6**
select * from test;
| descr | dt | ts |
| ------------------------------------ | ------------------- | ------------------- |
| session tz +08:00 insert local times | 2020-01-01 00:00:00 | 2020-01-01 00:00:00 |
| session tz +00:00 insert local times | 2020-01-01 00:00:00 | 2020-01-01 08:00:00 |
---
显示如何存储和读取 TIMESTAMP 实际上总是作为当地时间处理,DATATIME 独立于 time_zone 数据库会话的设置。
通过快速测试,即使在 mysql 8.
上,我也无法使yyyy-MM-dd HH:mm:ss+zz:zz
类型的时间戳/日期时间正常工作
您可以使用 Knex.js 的内置 now()
函数代替 Date.now()
:
const knexfile = require('../../knexfile');
const knex = require('knex')(knexfile.development);
const date = knex.fn.now();
选择:
const knexfile = require('../../knexfile');
const knex = require('knex')(knexfile.development);
knex.raw('CURRENT_TIMESTAMP');