Room类型转换器问题:如何将字符串日期转为Long存储?
问题分析与解决方案
看起来你搞反了TypeConverter的转换方向,而且方法命名也容易混淆——Room的TypeConverter是用来把实体类中使用的类型转换成数据库能存储的类型,反之亦然。你的需求是:实体类里用String类型的日期,数据库里存储对应的Long时间戳,所以当前的转换器逻辑完全弄反了,这就是为什么数据库里还是存的字符串。
修正后的类型转换器
首先,我们要明确两个转换方向:
- 当把实体类的
String日期存入数据库时,要转成Long时间戳(这是实体→数据库的转换) - 从数据库读取
Long时间戳时,要转回String日期(这是数据库→实体的转换)
另外,SimpleDateFormat是线程不安全的,而且直接调用parse()不处理异常会导致崩溃,建议加上异常处理,或者改用Java 8+的DateTimeFormatter(更安全)。下面是两种方案:
方案1:修复SimpleDateFormat版本的转换器
object DateTypeConverter { // 实体类的String日期 → 数据库存储的Long时间戳 @TypeConverter fun stringDateToLong(dateString: String?): Long? { if (dateString.isNullOrEmpty()) return null return try { val sdf = SimpleDateFormat(Constants.YYYY_MM_DD_HH_MM_SS, Locale.ENGLISH) sdf.parse(dateString)?.time } catch (e: ParseException) { e.printStackTrace() null // 或者根据业务需求返回默认值 } } // 数据库的Long时间戳 → 实体类的String日期 @TypeConverter fun longToStringDate(timestamp: Long?): String? { if (timestamp == null) return null val sdf = SimpleDateFormat(Constants.YYYY_MM_DD_HH_MM_SS, Locale.ENGLISH) return sdf.format(Date(timestamp)) } }
方案2:推荐使用Java 8+的日期API(更安全)
如果你的项目支持Java 8,可以用DateTimeFormatter代替SimpleDateFormat,它是线程安全的:
object DateTypeConverter { private val formatter = DateTimeFormatter.ofPattern(Constants.YYYY_MM_DD_HH_MM_SS, Locale.ENGLISH) @TypeConverter fun stringDateToLong(dateString: String?): Long? { return dateString?.let { try { LocalDateTime.parse(it, formatter).atZone(ZoneId.systemDefault()).toInstant().toEpochMilli() } catch (e: DateTimeParseException) { e.printStackTrace() null } } } @TypeConverter fun longToStringDate(timestamp: Long?): String? { return timestamp?.let { Instant.ofEpochMilli(it) .atZone(ZoneId.systemDefault()) .format(formatter) } } }
关键步骤:注册转换器
别忘了在你的Room Database类上添加@TypeConverters注解,让Room知道这个转换器的存在:
@Database(entities = [YourEntity::class], version = 1) @TypeConverters(DateTypeConverter::class) abstract class AppDatabase : RoomDatabase() { // DAO定义 }
实体类字段示例
确保你的实体类中日期字段的类型是String:
@Entity(tableName = "your_table") data class YourEntity( @PrimaryKey val id: Int, val date: String? // 这里是String类型,数据库会自动转成Long存储 )
这样修改后,Room就会把实体类中的String日期转换成Long时间戳存入数据库,读取时再转回String日期,完美符合你的需求。
内容的提问来源于stack exchange,提问作者AndroidDev123
相关产品推荐
相关产品推荐

