如果我将日期存储为字符串 yyyy-mm--dd,如何通过比较 Room 数据库中的日期字段来进行更复杂的查询?

问题描述 投票:0回答:1

我当前的问题是 ROOM 数据库如何管理日期和时间戳?在我当前的项目中,我刚刚发现,如果我将日期字段存储为字符串(更准确地说是 yyyy-mm-dd),我将无法进行比较日期字段的查询,因为ROOM 不知道如何使用字符串。更准确地说,我希望能够进行查询,在其中获取表中当前存储为字符串的开始日期和结束日期之间的所有条目。我查看了文档:

使用 Room 引用复杂数据

并发现解决方案是使用 TypeConverters 并相应地注释您的特定实体。然而,文档和一些堆栈溢出答案:

使用日期字段的房间

字符串日期到长整型的类型转换器

似乎只关注从 Long 转换为 Date 的情况,反之亦然。我理解这种情况,但我的具体情况是,我在数据库中手动引入交易日期作为字符串。我想知道一种将 yyyy-mm-dd 格式的字符串转换为 Long 的方法,然后我可以使用其他提示。

如有任何帮助,我们将不胜感激。

android database kotlin timestamp android-room
1个回答
0
投票

我将无法进行比较日期字段的查询,因为 ROOM 不知道如何使用字符串。

然而,由于 Room 是 SQLite 的包装器,并且 SQLite 具有内置的日期和时间函数,其中包括处理 yyyy-mm-dd 格式的日期,你可以,只要日期可以被视为有效/接受的日期时间格式,在字符串值上使用此类函数

时间值可以采用如下所示的任何格式。该值通常是一个字符串,但在格式 12 的情况下它可以是整数或浮点数。

1. YYYY-MM-DD
....

因此,如果日期存储为 yyyy-mm-dd,则可以对存储的值使用 BETWEEN。

也许考虑以下 SQLite 演示:-

DROP TABLE IF EXISTS ex01;
/* Creeate the table with just the one column */
CREATE TABLE IF NOT EXISTS ex01 (dateAsString TEXT);
/* Load the table with 1000 rows each have a date that is 1 day after the previous date */
WITH
    /* use a CTE (Common Table Expresssion aka a tempt table that exists for the duration of the execution) */
    cte(thedate) AS (
        SELECT '2024-03-01' /* The first date */
        UNION ALL SELECT date(thedate,'+1 days') /* recursively add rows */ 
        FROM cte
        LIMIT 1000 /* stop when 1000 rows have been processed/added */
    )
INSERT INTO ex01 SELECT * FROM cte;

/* Now select the date in various formats for a given range */
SELECT 
    *, /* actual stored data */
    datetime(dateAsString) AS string_ts, /* as datetime i.e. yyyy-mm-dd hh:MM:ss*/
    strftime('%s',dateasstring) AS long_ts, /* as Long (timestamp) */
    date(dateasstring) AS string_date /* converted to itself */
FROM ex01
WHERE dateasstring BETWEEN '2024-03-05' AND '2024-03-10' /* showing that SQLite can handle date as yyyy-mm-dd in a BETWEEN */
UNION SELECT '','','',max(dateasstring) FROM ex01 /* Add a row that is JUST the date of the highest(latest) row */
UNION SELECT '','','',min(dateasstring) FROM ex01 /* Add a row that is JUST the data of the lowest(earliest) row */
;

/* Final selection of a range */
SELECT * FROM ex01 WHERE dateasstring BETWEEN '2024-06-05' /*e.g. :fromDate in Room*/ AND '2024-06-10' /* e.g. :toDate in Room */;
/* Cleanup demo */
DROP TABLE IF EXISTS ex01;

第一个 SELECT(添加最低和最高日期的行)显示:-

enter image description here

    • 显示的第一行是最低日期(最后一列)
    • 下一行是最高日期
    • 其他行是查询中日期之间的行,但显示了如何轻松地以其他格式提取它们

第二个 SELECT 更类似于您可能会使用的内容,结果是:-

enter image description here

在房间中,第二个选择可以是,例如:-

@Query("SELECT * FROM ex01 WHERE dateAsAstring BETWEEN :fromDate and :toDate")
fun getTheDates(fromDate: String, toDate: String): List<Ex01>
© www.soinside.com 2019 - 2024. All rights reserved.