【问题标题】:Changing dates of particuler item in listView更改 listView 中特定项目的日期
【发布时间】:2017-10-26 08:33:47
【问题描述】:

我的应用程序中有一个重新安排按钮,按下它会自动将待办事项的过去日期更改为当前日期,但问题是使用以下代码,它还会将未来日期更改为当前日期一,我在 else-if 下没有任何代码,但它仍然会用当前日期更改未来日期。

public void updateDates2() {
    SQLiteDatabase db = mHelper.getWritableDatabase();
    Cursor cursor = null;
    Calendar c = Calendar.getInstance();
    List<String> array = new ArrayList<String>();
    SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
    cursor = db.query(TaskContract.TaskEntry.TABLE_NAME,
            new String[]{TaskContract.TaskEntry._ID,
                    TaskContract.TaskEntry.COLUMN_DATE,
            },
            null, null, null, null, null);

    String formattedDate = formatter.format(c.getTime());

    while (cursor.moveToNext()) {
        //Getting dates into the array using Cursor.
        String datesfromdb = cursor.getString(cursor.getColumnIndex("date"));
        array.add(datesfromdb);
    }
    ContentValues cv = new ContentValues();
    String TEMPPCOLNAME = "checkdate";
    Cursor csr = db.query(TaskContract.TaskEntry.TABLE_NAME, new String[]{
                    // All existing columns
                    "*",
                    "rowid as uid",
                    // generate reformatted date column named checkdate usable by date functions
                    // i.e. converts dd/mm/yyyy to yyyy-mm-yy
                    "substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",7,4)||'-'||" +
                            "substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",4,2)||'-'||" +
                            "substr( " + TaskContract.TaskEntry.COLUMN_DATE + ",1,2) AS " + TEMPPCOLNAME},
            // where clause to only include properly formatted dates and those who date is less
            // than or equaly to today's date
            TEMPPCOLNAME + "<= date('now') AND " +
                    "substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",3,1) = '/' AND " +
                    "substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",6,1) = '/'",
            null, null, null, null
    );


    Toast.makeText(this, csr.toString() , Toast.LENGTH_SHORT).show();
    while (csr.moveToNext()) {
        for (int i = 0; i < array.size(); i++) {
            if (array.get(i).equals(formattedDate)) {
                //If comparision matches, then incrementing the current date by one.
                c.add(Calendar.DATE, 1);
                formattedDate = formatter.format(c.getTime());
            } else {
                //if the date doesn't matches then returning the date to the db.update to set this date to the current task.
                cv.put(TaskContract.TaskEntry.COLUMN_DATE, formattedDate);
            }
        }

        if (

                db.update(TaskContract.TaskEntry.TABLE_NAME, cv, "rowid=?", new String[]{
                        String.valueOf(csr.getLong(csr.getColumnIndex("uid")))}
                ) > 0) {
            Log.d("UPDT2", "Row Updated OK.");
        } else {
            Log.d("UPDT2", "Update failed.");
        }

    }

【问题讨论】:

  • 你有没有调试代码来检查更新数据库中的日期?

标签: android sqlite date listview


【解决方案1】:

我相信您的问题,正如您所描述的,与这一行有关:-

db.update(TaskContract.TaskEntry.TABLE_NAME, cv, String.valueOf(idx1), null);

特别是第三个(WHERE 子句)参数,即String.valueOf(idx1)

您实际上是在说 WHERE n(n 是列 TaskContract.TaskEntry.COLUMN_DATE 的偏移量/索引)。如果此列索引大于 0,则表达式将有效地为真,因此将更新每一行。

因此,此更新只需执行一次,如果列索引大于 0 (true),它将更新所有行。这似乎是您所描述的行为。

您需要参数类似于TaskContract.TaskEntry.COLUMN_DATE = 'CurrentDate'

或者最好是TaskContract.TaskEntry.COLUMN_DATE=?,第四个参数解析 ? 占位符,例如newString[]{dateDB}.

这将使用该日期更新所有行,这可能会导致不必要的更新尝试。例如,如果您有两个相同的过去日期,则当光标到达该行和到达另一行时,两者都会更新。

我建议只提取要更新的行,这并不容易,因为您似乎将日期存储为 dd/mm/yyyy(根据日期顺序不容易排序)。但是,您可以通过在提取的光标中创建一个列来重新格式化日期并允许对其进行检查来解决此问题。

这看起来有点复杂,这里有一个例子:-

String TEMPPCOLNAME = "checkdate";
        Cursor csr = db.query(TBNAME,new String[]{
                // All existing columns
                "*",
                "rowid as uid",
                // generate reformatted date column named checkdate usable by date functions
                // i.e. converts dd/mm/yyyy to yyyy-mm-yy
                "substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",7,4)||'-'||" +
                        "substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",4,2)||'-'||" +
                        "substr( " + TaskContract.TaskEntry.COLUMN_DATE + ",1,2) AS " + TEMPPCOLNAME },
                // where clause to only include properly formatted dates and those who date is less
                // than or equaly to today's date
                TEMPPCOLNAME + "<= date('now') AND " +
                        "substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",3,1) = '/' AND " +
                        "substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",6,1) = '/'",
                null,null,null,null
                );

这是说得到一个包含表中所有列的游标 (*),使游标有一个名为 uid 的列,它是 rowid 的别名,并且使光标有一个名为 checkdate 的列(名称根据 TEMPCOLNAME)。 checkdate 是重新格式化的日期(现在是 SQLite 喜欢的 yyyy-mm-dd)

WHERE 子句(第三个参数)用于仅选择小于或等于第四个参数中定义的日期的日期,该参数将替换 ? 占位符。

WHERE 参数还将所选行限制为日期在位置 3 和 6 处具有 / 的行(仅作为预防措施)。

更新非常简单,重要的是特定于单行(因此提取列 uid 的原因):-

    while (csr.moveToNext()) {
        ContentValues cv = new ContentValues();
        cv.put(TaskContract.TaskEntry.COLUMN_DATE,
                new SimpleDateFormat("dd/MM/yyyy").format(Calendar.getInstance().getTime()));
        db.update(TBNAME,cv,"rowid=?",new String[]{
                String.valueOf(csr.getLong(csr.getColumnIndex("uid")))}
                ); 
    }
    csr.close();

结合两者,您可以:-

public void updateDates2() {
    String TEMPPCOLNAME = "checkdate";
    Cursor csr = db.query(TaskContract.TaskEntry.TABLE_NAME,new String[]{
            // All existing columns
            "*",
            "rowid as uid",
            // generate reformatted date column named checkdate usable by date functions
            // i.e. converts dd/mm/yyyy to yyyy-mm-yy
            "substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",7,4)||'-'||" +
                    "substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",4,2)||'-'||" +
                    "substr( " + TaskContract.TaskEntry.COLUMN_DATE + ",1,2) AS " + TEMPPCOLNAME },
            // where clause to only include properly formatted dates and those who date is less
            // than or equaly to today's date
            TEMPPCOLNAME + "<= date('now') AND " +
                    "substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",3,1) = '/' AND " +
                    "substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",6,1) = '/'",
            null,null,null,null
            );
    while (csr.moveToNext()) {
        ContentValues cv = new ContentValues();
        cv.put(TaskContract.TaskEntry.COLUMN_DATE,
                new SimpleDateFormat("dd/MM/yyyy").format(Calendar.getInstance().getTime()));
        if (
        db.update(TBNAME,cv,"rowid=?",new String[]{
                String.valueOf(csr.getLong(csr.getColumnIndex("uid")))}
                ) > 0) {
            Log.d("UPDT2","Row Updated OK.");
        } else {
            Log.d("UPDT2", "Update failed.");
        }
    }
    csr.close();
}

使用上述测试提供了以下结果:-

10-27 09:32:51.482 4259-4259/? D/EVENTDATA: Row 1 - Event Name is Event1 Starts on 01/03/2011 Ends on 2021-03-21
10-27 09:32:51.482 4259-4259/? D/EVENTDATA: Row 2 - Event Name is Event2 Starts on 14/08/2014 Ends on 2020-03-21
10-27 09:32:51.482 4259-4259/? D/EVENTDATA: Row 3 - Event Name is Event3 Starts on 26/10/2017 Ends on 2017-12-21
10-27 09:32:51.482 4259-4259/? D/EVENTDATA: Row 4 - Event Name is Event4 Starts on 28/10/2017 Ends on 2018-21-31
10-27 09:32:51.482 4259-4259/? D/EVENTDATA: Row 5 - Event Name is Event5 Starts on 01/01/2018 Ends on 2018-12-31
10-27 09:32:51.482 4259-4259/? D/EVENTDATA: Row 6 - Event Name is Event6 Starts on 27/10/2018 Ends on 2018-12-31
10-27 09:32:51.482 4259-4259/? D/EVENTDATA: Row 7 - Event Name is Event7 Starts on garbage Ends on 2018-12-31
10-27 09:32:51.483 4259-4259/? D/UPDT2: Extracted Row for Event Event1 StartDate Stored = 01/03/2011 Converted to = 2011-03-01
10-27 09:32:51.487 4259-4259/? D/UPDT2: Row Updated OK.
10-27 09:32:51.487 4259-4259/? D/UPDT2: Extracted Row for Event Event2 StartDate Stored = 14/08/2014 Converted to = 2014-08-14
10-27 09:32:51.491 4259-4259/? D/UPDT2: Row Updated OK.
10-27 09:32:51.491 4259-4259/? D/UPDT2: Extracted Row for Event Event3 StartDate Stored = 26/10/2017 Converted to = 2017-10-26
10-27 09:32:51.495 4259-4259/? D/UPDT2: Row Updated OK.
10-27 09:32:51.495 4259-4259/? D/EVENTDATA: Row 1 - Event Name is Event1 Starts on 27/10/2017 Ends on 2021-03-21
10-27 09:32:51.495 4259-4259/? D/EVENTDATA: Row 2 - Event Name is Event2 Starts on 27/10/2017 Ends on 2020-03-21
10-27 09:32:51.495 4259-4259/? D/EVENTDATA: Row 3 - Event Name is Event3 Starts on 27/10/2017 Ends on 2017-12-21
10-27 09:32:51.495 4259-4259/? D/EVENTDATA: Row 4 - Event Name is Event4 Starts on 28/10/2017 Ends on 2018-21-31
10-27 09:32:51.495 4259-4259/? D/EVENTDATA: Row 5 - Event Name is Event5 Starts on 01/01/2018 Ends on 2018-12-31
10-27 09:32:51.495 4259-4259/? D/EVENTDATA: Row 6 - Event Name is Event6 Starts on 27/10/2018 Ends on 2018-12-31
10-27 09:32:51.495 4259-4259/? D/EVENTDATA: Row 7 - Event Name is Event7 Starts on garbage Ends on 2018-12-31

前 7 行是上述运行之前的数据,后 7 行是运行之后的数据。之间的 6 行是更新本身的形式 (我删除了生成提取行的代码.....,转换为是 checkdate 的值,即重新格式化的日期)

但是,也许最好的方法是进行一次更新,从而无需使用游标来提取行:-

public void updateDates() {
    Calendar c = Calendar.getInstance();
    SimpleDateFormat formatter = new SimpleDateFormat("dd/MM/yyyy");
    String formattedDate = formatter.format(c.getTime());

    ContentValues cv = new ContentValues();
    cv.put(TaskContract.TaskEntry.COLUMN_DATE,formattedDate);

    String whereclause =
            " substr(" + TaskContract.TaskEntry.COLUMN_DATE +  ",7,4)||" +
                    " substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",4,2)||" +
                    " substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",1,2) " +
                    " <= date('now') " +
                    " AND substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",3,1) = '/'" +
                    " AND substr(" + TaskContract.TaskEntry.COLUMN_DATE + ",6,1) = '/'";
    db.update(TaskContract.TaskEntry.TABLE_NAME,cv,whereclause,null);
}

测试数据:-

10-27 11:25:52.331 5250-5250/? D/EVENTDATA: Row 1 - Event Name is Event1 Starts on 01/03/2011 Ends on 2021-03-21
10-27 11:25:52.331 5250-5250/? D/EVENTDATA: Row 2 - Event Name is Event2 Starts on 14/08/2014 Ends on 2020-03-21
10-27 11:25:52.331 5250-5250/? D/EVENTDATA: Row 3 - Event Name is Event3 Starts on 26/10/2017 Ends on 2017-12-21
10-27 11:25:52.331 5250-5250/? D/EVENTDATA: Row 4 - Event Name is Event4 Starts on 28/10/2017 Ends on 2018-21-31
10-27 11:25:52.331 5250-5250/? D/EVENTDATA: Row 5 - Event Name is Event5 Starts on 01/01/2018 Ends on 2018-12-31
10-27 11:25:52.331 5250-5250/? D/EVENTDATA: Row 6 - Event Name is Event6 Starts on 27/10/2018 Ends on 2018-12-31
10-27 11:25:52.332 5250-5250/? D/EVENTDATA: Row 7 - Event Name is Event7 Starts on garbage Ends on 2018-12-31
10-27 11:25:52.335 5250-5250/? D/EVENTDATA: Row 1 - Event Name is Event1 Starts on 27/10/2017 Ends on 2021-03-21
10-27 11:25:52.335 5250-5250/? D/EVENTDATA: Row 2 - Event Name is Event2 Starts on 27/10/2017 Ends on 2020-03-21
10-27 11:25:52.335 5250-5250/? D/EVENTDATA: Row 3 - Event Name is Event3 Starts on 26/10/2017 Ends on 2017-12-21
10-27 11:25:52.335 5250-5250/? D/EVENTDATA: Row 4 - Event Name is Event4 Starts on 28/10/2017 Ends on 2018-21-31
10-27 11:25:52.335 5250-5250/? D/EVENTDATA: Row 5 - Event Name is Event5 Starts on 01/01/2018 Ends on 2018-12-31
10-27 11:25:52.335 5250-5250/? D/EVENTDATA: Row 6 - Event Name is Event6 Starts on 27/10/2018 Ends on 2018-12-31
10-27 11:25:52.335 5250-5250/? D/EVENTDATA: Row 7 - Event Name is Event7 Starts on garbage Ends on 2018-12-31

【讨论】:

  • db.update(TaskContract.TaskEntry.TABLE_NAME, cv,"strftime('%d/%m/%Y', DATE) 处出现错误
  • 已编辑答案(再次未经测试)第 4 个参数需要是占位符替换的字符串数组。
  • @Birdielove 抱歉,经过测试,以前的方法不行。我现在已经用测试显示的代码编辑了代码。
  • 非常感谢,你是我的救命稻草,真的无法用言语表达我的快乐和感谢。像你这样的人让 StackOverflow 变得更好。
  • 我在 updateDate2 方法中添加了更多功能,我想做的是将过去日期更改为当前日期,但如果当前日期已经有条目,那么它应该增加当前日期和设置它。
猜你喜欢
  • 2014-02-05
  • 2016-10-20
  • 1970-01-01
  • 2021-01-06
  • 1970-01-01
  • 2012-08-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多