【问题标题】:Difficulty getting data from Sqlite database between two days两天之间难以从 Sqlite 数据库中获取数据
【发布时间】:2026-01-25 17:45:01
【问题描述】:

我正在做一个 Android 应用程序,它会为当前日期和过去 7 天之间的日期生成销售报告。效果很好,代码如下:

Calendar calendar = Calendar.getInstance();
calendar.add(Calendar.DAY_OF_YEAR,-7);

String currentDate = new SimpleDateFormat("dd-MM-yyyy").format(new Date());

SimpleDateFormat sdf = new SimpleDateFormat("dd-MM-yyyy");

String sevenDayAgo = sdf.format(calendar.getTime());

Cursor weeklyIncome = db.getResult("select sum(price) as total_income from sales where date between '"+sevenDayAgo+"' and '"+currentDate+"'");
Cursor weeklyCost = db.getResult("select sum(purchase_price * quantity) as total_cost from sales where date between '"+sevenDayAgo+"' and '"+currentDate+"'");

比如说currentDate = 31-08-2018sevenDayAgo = 24-08-2018 这一切都很好,但是当我将系统日期更改为下个月的第二天并且currentDate 变为01-09-2018 时,查询不会从数据库,它应该返回25-08-201801-09-2018 之间的记录,这之间有7天。不知何故,当 7 天在两个不同的月份时,查询不起作用。我不知道发生了什么以及如何解决它。

附言sales 表中的date 列的类型为TEXT

【问题讨论】:

  • 添加DAY_OF_YEAR 是错误的;相反,您应该使用 add 和 DATE,下面详细解释...
  • 顺便考虑扔掉长期过时且臭名昭著的麻烦SimpleDateFormat和朋友,并将ThreeTenABP添加到您的Android项目中,以便使用java.time,现代Java日期和时间API .与它一起工作要好得多。另外LocalDate.toString 会给你例如2018-09-01,它可以作为字符串排序,因此无需格式化程序就可以解决你的问题。

标签: android sqlite date android-sqlite


【解决方案1】:

问题是您用于日期的格式 (dd-mm-yyyy) 不是按字典顺序排列的。字符串 '25-08-2018' 比较大于 '01-09-2018'x BETWEEN y AND z 等价于 x >= y AND x <= z。对于使用您的格式的该范围内的日期,该条件将不成立(请记住,它们只是字符串。sqlite 没有date type

您应该使用 ISO-8601 格式,例如 yyyy-mm-dd。这些将正确排序 ('2018-08-25' < '2018-09-01') 并允许您在它们上使用 sqlite3 date and time functions

【讨论】:

    【解决方案2】:

    假设用户在 31/08/2018 这个格式中输入了出生日期:

    像这样解析它:

    String[] parts = BirthField.getText().toString().trim().split("/");
    int CAL_DAY, CAL_MONTH, CAL_YEAR;
    if(parts.length == 3)
    {
        CAL_DAY = Integer.parseInt(parts[0]);
        CAL_MONTH = Integer.parseInt(parts[1]);
        CAL_YEAR = Integer.parseInt(parts[2]);
    }
    

    您可以检查用户是否输入了一个好的日期:

    if( CAL_DAY > 0 && CAL_DAY < 32 && CAL_MONTH > 0 && CAL_MONTH < 13 && CAL_YEAR > 1900 )
    

    在数据库表中存储时,请注意以下事项:

    Calendar CalendarEvent = Calendar.getInstance(TimeZone.getDefault(), Locale.getDefault());
    CalendarEvent.set(Calendar.DATE, CAL_DAY);
    CalendarEvent.set(Calendar.MONTH, CAL_MONTH - 1);
    CalendarEvent.set(Calendar.HOUR_OF_DAY, Integer.parseInt(ScheduleTime) );
    CalendarEvent.set(Calendar.MINUTE, 00);
    CalendarEvent.set(Calendar.SECOND, 00);
    SimpleDateFormat format = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss Z", Locale.getDefault());
    String DayConsidered = format.format(CalendarEvent.getTime());
    

    请注意CAL_MONTH - 1,因为系统从 0 到 11 开始月份

    SystemTime的数据库中存储存储时像:

    SYSTIME = CalendarEvent.getTimeInMillis();
    

    当再次使用它时,从数据库中检索它并用它初始化日历事件:

    Calendar CalendarEvent = Calendar.getInstance();
    CalendarEvent.setTimeInMillis( Long.parseLong(SYSTIME) );
    
    int CAL_DAY = CalendarEvent.get(Calendar.DAY);
    CalendarEvent.set(Calendar.DATE, CAL_DAY - 7);
    

    即使您从任何日期更改了几天/几个月/甚至您更改年份,它也将开始工作;它总是显示小于 7 天的日期

    希望它有所帮助,让我知道它是如何工作的,因为我正在快速回答它......

    编辑:2

    我在我的项目中使用并完美运行的更好和最有效的方法是:

    Log.d("ADDING A MONTH :", "ADDING 1 MONTH....\n");
    CalendarEvent.add(Calendar.MONTH, 1);
    
    Log.d("NEGATING 7 DAYS :", "NEGATING 7 DAYS....\n");
    CalendarEvent.add(Calendar.DATE, -7);
    

    【讨论】:

    • 谢谢,但我没有收到用户的任何输入。我使用 dd-MM-yyyy 格式将日期数据存储在数据库中,因此我必须使用相同的格式来检索它。不要你觉得呢?我尝试像你说的那样在月份中添加一个并从 DAY_OF_YEAR 更改为 DATE,但它似乎不起作用
    • 是的,它可以工作...更新您将数据放入数据库的代码,您如何检索以及如何否定 7 天 .. 这三件事的完整代码
    • 感谢您的帮助,我能够通过将格式从 dd-MM-yyyy 更改为 yyyy-MM-dd 来解决它,就像 Shawn 在另一个答案中建议的那样