Android Room查询日期范围时如何包含结束日期?
解决Room查询不包含结束日任务的问题
你的问题核心是:用BETWEEN :from AND :to查询时,结束日当天的任务因为start_time(比如4月30日10点的时间戳)大于to(4月30日0点的时间戳),所以被排除了。这里给你两种靠谱的解决方法:
方法一:调整查询条件,用「小于结束日下一天0点」替代「小于等于结束日0点」
修改DAO的查询语句,把BETWEEN改成范围判断,确保包含结束日当天所有时间的任务:
@Query("SELECT * FROM tasks WHERE start_time >= :from AND start_time < :toExclusive") List<TimeEntity> getChoosenTimes(long from, long toExclusive);
调用这个方法时,把用户选择的结束日期加一天,转成对应时间戳(比如用Java的LocalDate或者Calendar处理):
// 假设用户选的结束日期是endDate(LocalDate类型) long toExclusive = endDate.plusDays(1).atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli();
这种方式用时间戳直接比较,数据库查询效率最高,还能避免夏令时等时间计算问题。
方法二:用SQLite日期函数直接比较日期
如果不想修改传入的参数,也可以利用SQLite的日期函数,把时间戳转成日期字符串再比较,这样不管start_time是当天的哪个时刻,都会被纳入结束日的范围:
@Query("SELECT * FROM tasks WHERE date(start_time / 1000, 'unixepoch') BETWEEN date(:from / 1000, 'unixepoch') AND date(:to / 1000, 'unixepoch')") List<TimeEntity> getChoosenTimes(long from, long to);
注意这里要把毫秒级时间戳除以1000转成秒级,因为SQLite的unixepoch是基于秒的。这种方式可读性更强,适合数据量不大的场景。
为什么原来的语句不行?
你用TypeConverter把日期转成Long存储时,选的结束日期(比如4月30日)对应的是当天0点的时间戳,但任务的start_time是任务实际开始的时间(比如4月30日14:30),这个时间戳肯定比0点的大,所以BETWEEN会把它排除在外。
内容的提问来源于stack exchange,提问作者steeveKA1
相关产品推荐
相关产品推荐

