将日期保存到 Room 数据库时,TypeConverter 会打乱数据

Joe*_*oey 0 java sqlite android android-room

我已经为此工作了几个小时,但我似乎无法弄清楚如何将日期保存到我的 Room Sqllite 数据库中。我基本上是从 Android 文档中复制代码来进行批量处理。

这就是我所拥有的。

数据库:

@Database(entities = {Review.class},
        version = 3,
        exportSchema=false)
@TypeConverters(DateTypeConverter.class)
public abstract class NotecardDatabase extends RoomDatabase {
...etc...
}
Run Code Online (Sandbox Code Playgroud)

实体:

    @Entity(tableName = "review",
        indices = {
                @Index(value = "next_review"),
        }
public class Review {
...Other columns...
    @TypeConverters(DateTypeConverter.class)
    @ColumnInfo(name ="next_review")
    @NonNull
    private Date nextReview;
}
Run Code Online (Sandbox Code Playgroud)

接下来,我的转换器:

public class DateTypeConverter {

    private static Logger log = Logger.getLogger("DateTypeConverter");
    @TypeConverter
    public static Date fromTimestamp(Long value) {
        if(value != null) {
            log.info("Incoming long: " + value + "\nTo Date: " + new Date(value));
        }
        return value == null ? null : new Date(value);

    }

    @TypeConverter
    public static Long dateToTimestamp(Date date) {
        if(date != null) {
            log.info("Incoming date: " + date + "\n to Long: " + date.getTime());
        }
        return date == null ? null : date.getTime();
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,当我尝试创建一些 Review 对象时,这是我从运行中得到的输出:

06-18 18:13:38.522 7081-7098/DateTypeConverter: 传入日期:Mon Jun 18 18:13:38 PDT 2018 to Long:1529370818524

06-18 18:13:38.522 7081-7106/DateTypeConverter: Incoming long: 1529370818 To Date: Sun Jan 18 08:49:30 PST 1970

所以它似乎保存正确(请参阅第一个日志语句),但是当我从数据库中取出东西时,long 的最后 3 位数字被简单地砍掉,返回 1970 年的日期。

帮助?

Joe*_*oey 5

好的,经过大量工作,我找到了问题所在。感谢所有为此提供帮助的人。

我从日期更改为日历,尽管这不是解决此问题的方法。

真正的问题是有两个时间戳:Linux 时间戳,它是自纪元以来的毫秒数,以及 Java/Sqllite 时间戳,它是自纪元以来的秒数

为了让所有东西都能很好地与 Sqllite 函数一起使用并正确保存和读取,这是我的工作代码:

public class DateTypeConverter {
 @TypeConverter
    public static Calendar calendarFromTimestamp(String value) {
        if(value == null) {
            return null;
        }
        Calendar cal = new GregorianCalendar();
        cal.setTimeInMillis(NumberUtils.toLong(value)*1000);
        return cal;
    }

    @TypeConverter
    public static String dateToTimestamp(Calendar cal) {
        if(cal == null) {
            return null;
        }
        return "" + cal.getTimeInMillis()/1000;
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意 cal.getTimeInMillis() 函数的用法,该函数明确指出我们正在执行毫秒时间戳。然后保存到数据库时,我们除以1000保存时间戳,因为Sqllite日期函数处理的是时间戳。

另请注意,您可能也可以使用 Longs 而不是 Strings,但 Strings 对我有用。