将Prisma与SQLite DateTime数据类型一起使用
#javascript #node #database #prisma

tl; dr-对于sqlite中的DATETIME datatype,prisma读写并以毫秒为单位的unix时期时间。根据您的模式,如果Prisma模式将字段定义为DateTime

SQLITE和DateTime数据类型

根据SQLite documentation,它没有针对DATETIME的独特数据类型:

sqlite没有DATETIME数据类型。相反,日期和时间可以以这些方式存储:

  • 作为ISO-8601格式中的文本字符串。示例:'2018-04-02 12:13:46'。
  • 作为自1970年以来的整数秒数(也称为“ Unix Time”)。
  • 作为分数朱利安日号的真实价值。

SQLite的内置日期和时间函数在上面的所有格式中都可以理解日期/时间,并且可以在它们之间自由更改。您使用的哪种格式完全取决于您的应用程序。

要考虑到这一点,Prisma读写并为其DateTime support的数字数据类型。

prisma还支持SQLite TEXT数据类型,但是该格式必须在RFC 3339或RFC 2822格式中,SQLite不支持SQLITE,而是赞成ISO-8601。

碰巧的是,ISO-8601 is substantially similar to, but not identical to RFC 3339

几乎,是的-RFC 3339被列为ISO 8601的配置文件。最著名的RFC 3339指定了日期和时间的完整表示(仅分数秒是可选的)。 RFC还具有一些微妙的差异。例如,不允许使用仅有两位数字的年的截短表示形式-RFC 3339需要4位年份,而RFC仅允许使用周期字符作为分数秒的小数点。 RFC还允许“ t”替换为空间(或其他字符),而标准仅允许省略它(并且只有在所有各方使用代表之间达成协议时)。

虽然有关于ISO 8601支持的Prisma issue,但它已经开放了多年。

TEXT datatype读取日期

要阅读日期,您必须使用以下格式之一:

  • rfc2822:例如,Tue, 1 Jul 2003 10:52:37 +0200
  • rfc3339:例如,1996-12-19T16:39:57-08:00

我们可以通过查询每种日期格式的列来确认上述测试表。

首先,我们创建了一个使用TEXT datatype的新表:

CREATE TABLE test (iso8601 text, rfc2822 text, rfc3339 text, unix numeric);

接下来,我们定义了一个涵盖上述数据库模式的Prisma模式:

model Test {
  iso8601 DateTime
  rfc2822 DateTime
  rfc3339 DateTime
  unix DateTime @id
}

并用以下测试数据填充表:

sqlite> select * from test;
2016-09-01T10:11:12|Tue, 1 Jul 2003 10:52:37 +0200|1996-12-19T16:39:57-08:00|1472782272

接下来,我们单独查询每列的数据库:

const fields = ['iso8601', 'rfc2822', 'rfc3339', 'unix'];
for (const field of fields) {
  try {
    const obj = await prisma.test.findMany({
      select: {
        [field]: true,
      },
    });
    console.log(obj);
  } catch (e) {
    console.log(e.meta.message);
  }
}

脚本将以下输出到控制台:

Could not convert value "2016-09-01T10:11:12" of the field `iso8601` to type `DateTime`.
[ { rfc2822: 2003-07-01T08:52:37.000Z } ]
[ { rfc3339: 1996-12-20T00:39:57.000Z } ]
[ { unix: 1970-01-18T01:06:22.272Z } ]

值得注意的是,如果您从新的数据库开始,而不是现有的SQLITE数据库,则Prisma将在SQLITE中创建DateTime schema字段作为DATETIME DataType:

-- CreateTable
CREATE TABLE "Test" (
    "iso8601" DATETIME,
    "rfc2822" DATETIME,
    "rfc3339" DATETIME,
    "unix" DATETIME NOT NULL PRIMARY KEY
);

因此,在许多情况下,您可能会在毫秒中与Unix Epoch时间合作。但是如上所述,您可以在RFC 2822或RFC 3339格式中读取日期。

将人类可读的日期写入边车栏

编写人性化日期字段的一种方法是使用侧列列。例如,考虑以下内容:

CREATE TABLE mytable (unix DATETIME, sidecar TEXT);
CREATE TRIGGER mytable_insert AFTER INSERT ON mytable BEGIN
  UPDATE mytable SET sidecar = strftime('%Y-%m-%d %H:%M:%S', datetime(unix,'unixepoch', 'localtime')) WHERE unix = NEW.unix;
END;

现在,当您与Prisma插入日期时,也会插入人类可读日期:

sqlite> INSERT INTO mytable(unix) VALUES(1472782272);
sqlite> SELECT * FROM mytable;
1472782272|2016-09-01 22:11:12

参考