Android 如何使用Room library正确使用strftime和datetime?

Android 如何使用Room library正确使用strftime和datetime?,android,sqlite,android-sqlite,android-room,Android,Sqlite,Android Sqlite,Android Room,我有一个实体Memo类。我使用@TypeConverter将gregoriacalendar转换为Long Memo.java @Entity public class Memo { @Ignore public static final int TYPE_EXPENSE = 0; @Ignore public static final int TYPE_INCOME = 1; @PrimaryKey(autoGenerate = true) p

我有一个实体
Memo
类。我使用
@TypeConverter
gregoriacalendar
转换为
Long

Memo.java

@Entity
public class Memo {
    @Ignore
    public static final int TYPE_EXPENSE = 0;
    @Ignore
    public static final int TYPE_INCOME = 1;

    @PrimaryKey(autoGenerate = true)
    public int id;

    public int type;
    @ColumnInfo(name = "item_name")
    public String itemName;
    @ColumnInfo(name = "category_name")
    public String categoryName;
    public String note;
    public double dollar;
    public GregorianCalendar date;
    public String photoPath;

    @Ignore
    public Memo(int type) {
        this.type = type;
        itemName = "";
        categoryName = "";
        note = "";
        dollar = 0d;
        date = new GregorianCalendar();
        photoPath = "";
    }

    public Memo() {
        this(TYPE_EXPENSE);
    }

    @Ignore
    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("id = " + id);
        builder.append(", itemName = " + itemName);
        builder.append(", type = " + type);
        builder.append(", categoryName = " + categoryName);
        builder.append(", note = " + note);
        builder.append(", date = " + date.getTimeInMillis());
        return builder.toString();
    }
}
java

public class Converters {
    @TypeConverter
    public static GregorianCalendar fromTimestamp(Long value) {
        if (value == null)
            return new GregorianCalendar();
        else {
            GregorianCalendar calendar = new GregorianCalendar();
            calendar.setTimeInMillis(value);
            return calendar;
        }
    }

    @TypeConverter
    public static Long millisToTimestamp(GregorianCalendar calendar) {
        return calendar == null ? null : calendar.getTimeInMillis();
    }
}
我想获取数据库中的第一条和最后一条记录,并作为结果获取
MemosWithTimestamp
对象

public class MemoWithTimestamp {
    public int year;
    public int month;
    @Embedded
    public Memo memo;

    @Ignore
    @Override
    public String toString() {
        StringBuilder builder = new StringBuilder();
        builder.append("year=" + year);
        builder.append(", month=" + month);
        builder.append(", memo=[ "+memo.toString()+"]");
        return builder.toString();
    }
}
查询方法:

    @Query("SELECT *, CAST(strftime('%Y', datetime(date)) AS int) AS year, CAST(strftime('%m', datetime(date)) AS int) AS month FROM memo ORDER BY date DESC LIMIT 1")
    MemoWithTimestamp getTheLastMemo();

    @Query("SELECT *, CAST(strftime('%Y', datetime(date)) AS int) AS year, CAST(strftime('%m', datetime(date)) AS int) AS month FROM memo ORDER BY date ASC LIMIT 1")
    MemoWithTimestamp getTheFirstMemo();
Logcat中数据库中的数据:

id = 1, itemName = memo-2015-1-0, type = 0, categoryName = , note = , date = 1422634536401 <=first
....
id = 197, itemName = memo-2017-12-9, type = 0, categoryName = , note = , date = 1515428136414 <=last
firstMemo= year=0, month=0, memo=[ id = 1, itemName = memo-2015-1-0, type = 0, categoryName = , note = , date = 1422634536401]

lastMemo= year=0, month=0, memo=[ id = 197, itemName = memo-2017-12-9, type = 0, categoryName = , note = , date = 1515428136414]
但是年和月字段总是在有或没有
CAST
的情况下得到0


如何解决这个问题?

您在这里错过了两件事:

1)
datetime()
函数获取秒数,而您正在传递毫秒数。将该值除以1000

2) 您应该将第二个参数作为“unixepoch”传递给
datetime()
函数

因此,您的查询如下所示:

CAST(strftime('%Y', datetime(date/1000, 'unixepoch')) AS int) AS year
月份相同:

CAST(strftime('%m', datetime(date/1000, 'unixepoch')) AS int) AS month 

我更改了查询,但它返回
lastmome=year=2018,month=1,memo=[id=197,itemName=memo-2017-12-9,type=0,categoryName=,note=,date=1515428136414]
。另一个问题是
是否真的需要CAST
?系统是否已将字符串值(
strftime
函数)转换为Int?一切都是正确的,您有:
date=1515428136414
,现在是2018年1月8日(
year=2018,month=1
),因此您的查询年份和月份是正确的
itemName
不同,可能是因为它已更新(它是字符串)。但在我的回答中,从日期字段(时间戳)中提取年和月是正确的。关于第二个问题,您不需要强制转换为int,因为%Y为您提供了
string
number,它将被正确转换。但是函数通常会提供字符串,例如strftime(%Y-%m)会提供
'2018-01'
。谢谢您的帮助。我忘了在itemName中添加1到month。只是一个简短的说明。如果将
STRFTIME
的返回值与
int
进行比较,则需要
CAST