0

我们将日期作为字符串存储在 created_at 列中,格式2019-10-09T15:29:28.000+08:00如下Moor

我们想编写一个选择查询,以检索月份为 10 月且年份为 2019 的数据。

 Future<ABC> selectReadingBasedOnMonth(
      int month, int year) {
    return (select(abcs)
          ..where((t) {
            final sqliteDate = FunctionCallExpression<DateTime, DateTimeType>(
                'date', [t.createdAt]);

            return sqliteDate.year.equals(year) &
                sqliteDate.month.equals(month);
          }))
        .getSingle();
  }

但我们没有得到任何数据。这是日志中显示的查询

I/flutter (12004): Moor: Sent SELECT * FROM abcs WHERE (CAST(strftime("%Y", date(created_at), "unixepoch") AS INTEGER)) = ? AND (CAST(strftime("%m", date(created_at), "unixepoch") AS INTEGER)) = ?; 带参数 [2019, 10]

4

2 回答 2

1

unixepoch修饰符只能用于纯数字的日期/时间字符串

“unixepoch”修饰符 (11) 仅在它紧跟在 DDDDDDDDDD 格式的时间字符串之后才有效。

此修饰符导致 DDDDDDDDDD 不像通常那样被解释为儒略日数,而是 Unix 时间 - 自 1970 年以来的秒数。

如果“unixepoch”修饰符不遵循 DDDDDDDDDD 形式的时间字符串,它表示自 1970 年以来的秒数,或者如果其他修饰符将“unixepoch”修饰符与之前的 DDDDDDDDDD 分开,则行为未定义。

对于 3.16.0 (2017-01-02) 之前的 SQLite 版本,“unixepoch”修饰符仅适用于 0000-01-01 00:00:00 和 5352-11-01 10:52:47 之间的日期(unix 时间为-62167219200 到 106751991167)。

日期和时间函数

例如考虑以下(根据您的查询):-

DROP TABLE IF EXISTS abcs;
CREATE TABLE IF NOT EXISTS abcs (created_at TEXT);
INSERT INTO abcs VALUES ('2019-10-09T15:29:28.000+08:00');

SELECT *, 
    CAST(strftime('%Y', date(created_at)/*, 'unixepoch'*/) AS INTEGER) AS year_nounixepoch,
    CAST(strftime('%m', date(created_at)/*, 'unixepoch'*/) AS INTEGER) AS month_nounixepoch,
    CAST(strftime('%Y', date(created_at), 'unixepoch') AS INTEGER) AS year_invalid,
    CAST(strftime('%m', date(created_at), 'unixepoch') AS INTEGER) AS month_invalid,
    
    CAST(strftime('%Y', strftime('%s',date(created_at)), 'unixepoch') AS INTEGER) AS year_unixepoch,
    CAST(strftime('%m', strftime('%s',date(created_at)), 'unixepoch') AS INTEGER) AS month_unixepoch
    
FROM abcs 
WHERE CAST(strftime('%Y', strftime('%s',date(created_at)), 'unixepoch') AS INTEGER) = 2019 AND CAST(strftime('%m', strftime('%s',date(created_at)), 'unixepoch') AS INTEGER) = 10;
DROP TABLE IF EXISTS abcs; /* cleanup test environment */ 
  • 请注意,单引号已用于替换双引号,这将是正确的 SQL,尽管这种差异可能是由于消息的输出方式造成的。

这导致: -

在此处输入图像描述

  • 即,在使用unixepoch修饰符的地方,它会导致 null 因为日期/时间不仅仅是数字。
  • 选择标准,通过unixepochstrftime('%s',.....预期工作。
于 2020-01-02T05:30:04.670 回答
0

感谢simolus3 提供的答案

 final asDate = FunctionCallExpression('date', [t.createdAt]);
 final year = FunctionCallExpression<String, StringType>(
      'strftime', [const Constant<String, StringType>('%Y'), asDate]);
 final month = FunctionCallExpression<String, StringType>(
      'strftime', [const Constant<String, StringType>('%m'), asDate]);

  return year.equals('2019') & month.equals('07');
于 2020-01-06T17:12:37.830 回答