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