【问题标题】:Room LocalDateTime TypeConverter房间 LocalDateTime 类型转换器
【发布时间】:2019-02-28 14:27:42
【问题描述】:

我需要能够使用 Rooms TypeConverters 在我的 sqlite 数据库上存储和检索 LocalDateTime 属性。

经过一些研究,我实现了以下转换器。但是,此转换器似乎仅存储默认日期时间 (1970-01-01)。所以转换不正确有没有人有一个工作的 LocalDateTime 转换器?或者对此有什么改进?

public class LocalDateTimeConverter {
@TypeConverter
public static LocalDateTime toDate(Long timestamp) {
    LocalDateTime ldt;
    if (timestamp == null){
        return null;
    }else{
        ldt = Instant.ofEpochMilli(timestamp).atZone(ZoneId.systemDefault()).toLocalDateTime();
    }
    return ldt;
}

@TypeConverter
public static Long toTimestamp(LocalDateTime date) {
    if (date == null){
        return  null;
    }else {
        return date.getLong(ChronoField.CLOCK_HOUR_OF_DAY);
    }
}}

【问题讨论】:

  • LocalDateTime 是用于此目的的错误类。缺少任何时区或与 UTC 偏移的概念意味着此类不能代表一个时刻。跟踪时刻(例如自 1970-01-01T00:00:00Z 以来的毫秒数)时,请使用 Instant 或 OffsetDateTime 或 ZonedDateTime 类。这三个类do 代表一个时刻,而LocalDateTime 代表not。 Instant.ofEpochMilli( milliseconds )
  • @BasilBourque 你会推荐什么作为转到 DateTime(将在 c# 中)参数类型?
  • 正如我在评论末尾的代码中所示,Instant 是 java.time 的基本构建块类。根据定义,Instant 始终采用 UTC。对于其他偏移量,请使用OffsetDateTime。对于完整时区而不是单纯的偏移,请使用ZonedDateTime。仅限日期,LocalDate。这已经在 Stack Overflow 上讨论过很多次了,所以请搜索更多信息。您可以从昨天的my Answer 开始。然后使用 DuckDuckGo/Google/Bing 中的 site:stackoverflow.com 技巧在 Stack Overflow 中搜索类名。

标签: java android android-room


【解决方案1】:

我在我的库中实现了一个LocalDateTimeConverter,手提箱,here。请记住,这扩展了我的BaseConverter 类here。注意:这一切都在 Kotlin 中。

如果你想自己实现,我建议存储为字符串而不是时间戳。如果您查看上面的链接,您会看到我首先使用toString() 将日期转换为字符串,然后使用parse() 函数将日期转换回LocalDateTime。

这里是Java:

public class LocalDateTimeConverter {

    @TypeConverter
    public static LocalDateTime toDate(String dateString) {
        if (dateString == null) {
            return null;
        } else {
            return LocalDateTime.parse(dateString); 
        }
    }

    @TypeConverter
    public static String toDateString(LocalDateTime date) {
        if (date == null) {
            return null;
        } else {
            return date.toString();
        }
    }
}

编辑:

您在上面使用的代码不起作用的原因是,在您的toTimestamp() 函数中,您只是要求将一天中的小时作为Long。因此,给定 LocalDateTime,即 2019 年 1 月 1 日下午 12:00,您将存储 12。所以在toDate 中,您要求将时间戳12 转换为LocalDateTime,即1970 年1 月1 日午夜之后的12 毫秒。

您可以选择继续使用时间戳来存储您的日期,只需将toTimestamp() 中的那一行更改为date.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()。这将为您提供当前时区中LocalDateTime 的实际时间戳。请注意此处的时区:由于您使用系统的默认时区来保存/加载到/从数据库中,如果系统更改时区,您可能会得到错误的值。如果我在纽约使用您的应用程序,然后在旧金山重新打开该应用程序,所有时间将关闭 3 小时。最好使用设置的时区来保存/加载,然后将其转换为设备的当前时区。

【讨论】:

  • 简洁明了:我的原始代码使任务过于复杂。
  • LocalDateTime.parse(dateString) 仅在 api 26 中可用。任何向后兼容的替代方案?我有 minSdk 24
  • 我通常使用AndroidThreeTen,它允许您在向后兼容的情况下使用这些类。然而,谷歌似乎正计划在 Android Studio 4.0 中添加这种向后兼容性,如您所见here。
  • @Gober,尝试使用库去糖 - android 的一项新功能(截至今天)。 developer.android.com/studio/write/…
猜你喜欢
  • 2018-07-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-04-07
  • 1970-01-01
  • 2019-04-06
相关资源
最近更新 更多