【问题标题】:How can I work with Date and Time at Room如何在房间使用日期和时间
【发布时间】:2019-08-02 20:39:33
【问题描述】:

我有以下模型,其中有 datetime 字段

import androidx.room.Entity
import androidx.room.PrimaryKey
import java.time.LocalDate
import java.time.LocalTime

@Entity
data class Assignment(
    @PrimaryKey(autoGenerate = true) val tid: Int,

   // @PrimaryKey val uid: Int,
    @ColumnInfo(name = "id") val id: Int,
    @ColumnInfo(name = "task") val task: String?,
    @ColumnInfo(name = "address") val address: String?,
    @ColumnInfo(name = "datePicker") val datePicker: LocalDate?,
    @ColumnInfo(name = "timePicker") val timePicker: LocalTime?,
    @ColumnInfo(name = "status") val status: String?
)

但我收到以下错误:

无法弄清楚如何将此字段保存到数据库中。你可以 考虑为它添加一个类型转换器。

所以,我写了下面的转换器:

import java.sql.Date
import java.time.LocalDate
import javax.persistence.AttributeConverter
import javax.persistence.Converter
import java.time.ZoneId.systemDefault

@Converter(autoApply = true)
class LocalDateAttributeConverter : AttributeConverter<LocalDate, Date> {

    override fun convertToDatabaseColumn(locDate: LocalDate?): Date? {
        return if (locDate == null) null else Date.valueOf(locDate.toString())
    }

    override fun convertToEntityAttribute(sqlDate: Date?): LocalDate? {
        val defaultZoneId = systemDefault()
        val instant = sqlDate?.toInstant()
        return instant?.atZone(defaultZoneId)?.toLocalDate()
    }
}

但不知道如何将这个convertor 与数据库model 一起使用?

更新 根据收到的答案,我将代码更改为如下,但仍然出现相同的错误:

转换器:

import androidx.room.TypeConverter
import java.sql.Date
import java.time.LocalDate
import java.time.ZoneId.systemDefault

class Converters {
    @TypeConverter
    fun convertToDatabaseColumn(locDate: LocalDate?): Date? {
        return locDate?.let { Date.valueOf(locDate.toString()) }
    }

    @TypeConverter
    fun convertToEntityAttribute(sqlDate: Date?): LocalDate? {
        val defaultZoneId = systemDefault()
        val instant = sqlDate?.toInstant()
        return instant?.atZone(defaultZoneId)?.toLocalDate()
    }
}

数据库:

import android.content.Context
import androidx.room.Database
import androidx.room.Room
import androidx.room.RoomDatabase
import androidx.room.TypeConverters
import kotlinx.coroutines.CoroutineScope

@Database(entities = [Assignment::class], version = 1)
@TypeConverters(Converters::class)
abstract class AppDatabase : RoomDatabase() {
    abstract fun assignmentDao(): AssignmentDao

    companion object {
        @Volatile
        var INSTANCE: AppDatabase? = null

        fun getDatabase(context: Context,
                        scope: CoroutineScope
        ): AppDatabase {
            val tempInstance = INSTANCE
            if (tempInstance != null) {
                return tempInstance
            }
            synchronized(this) {
                val instance = Room.databaseBuilder(
                    context.applicationContext,
                    AppDatabase::class.java,
                    "database-name"
                ).addCallback(AppDatabaseCallback(scope))
                    .build()
                INSTANCE = instance
                return instance
            }
        }
    }
}

import androidx.room.ColumnInfo
import androidx.room.Entity
import androidx.room.PrimaryKey
import androidx.room.TypeConverters
import java.time.LocalDate
import java.time.LocalTime
//import javax.persistence.Convert

@Entity
data class Assignment(
    @PrimaryKey(autoGenerate = true) val tid: Int,

   // @PrimaryKey val uid: Int,
    @ColumnInfo(name = "id") val id: Int,
    @ColumnInfo(name = "task") val task: String?,
    @ColumnInfo(name = "address") val address: String?,
    @ColumnInfo(name = "timePicker") val timePicker: LocalTime?,
    @ColumnInfo(name = "status") val status: String?,

    @TypeConverters(Converters::class)
    @ColumnInfo(name = "datePicker") val datePicker: LocalDate?
)

【问题讨论】:

  • 从您的日期获取 long 值(时间)并保存,然后从该长值重新创建日期
  • @a_local_nobody 请查看我更新的问题
  • 将时间的数据库变量设置为 long,并在为其赋值时,通过 System.currentTimeMillis() 将时间值转换为 long。您甚至可以在插入之前将它们转换为秒
  • @Psycho 能否提供示例代码。
  • 我不知道这个的 kotlin 语法。我会显示 java 语法吗?

标签: android kotlin android-room


【解决方案1】:
long time = new Date().getTime();
long sysTime = System.currentTimeMillis();

以上两者都将返回相同的值,即 long 类型。因此,您可以只使用其中之一。甚至可以像这样转换为小时、分钟或秒(这在分配值时很有用):

int hours = (int) TimeUnit.MILLISECONDS.toHours(System.currentTimeMillis());
int minutes = (int) TimeUnit.MILLISECONDS.toMinutes(System.currentTimeMillis());
int seconds = (int) TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis());

int date = new Date().getDate();
String formatedDate = new SimpleDateFormat("dd-MM-yyyy").format(new Date());

这里,date 将返回值作为 int(今天为 3),formatedDate 将返回值作为 String(今天为 03-08-2019)。

所以,您可以在房间数据库类中做些什么,为时间声明 long 类型变量,为日期声明 int/String(您喜欢的)。然后,在为这些变量赋值时,使用上述技术。

在 Kotlin 中可以这样做:

button.setOnClickListener {
       val formatedDate = SimpleDateFormat("yyyy-MM-dd").format(Date())
       val formatedTime = SimpleDateFormat("HH:mm").format(Date())
       val DateTime = "$formatedDate  $formatedTime"
       appViewModel.updateLastUpdateById(this, task_id, DateTime)
}

在模型/房间中,如:

@Entity
data class Assignment(
    @ColumnInfo(name = "lastUpdate") val lastUpdate: String?
)

【讨论】:

    【解决方案2】:

    但不知道如何将此转换器与数据库模型一起使用?

    您没有使用正确的注释。 Android SDK 中不存在javax.persistence — 我希望您的代码无法编译。

    该错误消息指的是Room's @TypeConverter and @TypeConverters annotations

    因此,将上面显示的类切换为使用@TypeConverter。然后,将 @TypeConverters(LocalDateAttributeConverter::class) 添加到您的 Assignment 实体。或者,如果您愿意,可以将 @TypeConverters(LocalDateAttributeConverter::class) 添加到您的 RoomDatabase 子类中,这将允许您在任何实体中使用 LocalDate 属性。

    【讨论】:

    • 不明白这个switch your class shown above to use @TypeConverter
    • @HasanAYousef:在您的问题中,您有一个 LocalDateAttributeConverter Kotlin 课程。这没有使用正确的注释。按照the documentation 中的说明,将LocalDateAttributeConverter 更改为使用@TypeConverter
    • @HasanAYousef:您还需要一个LocalTime? 转换器。 FWIW,请参阅 here 获取示例 Kotlin @TypeConverter 类和 here 了解我如何将其应用于数据库。
    【解决方案3】:

    这就是我使用类型转换器的方式

    @Database(
    entities = [EventCategory::class, Workshop::class, EventDetails::class, UserProfile::class, Message::class],
    version = 2,
    exportSchema = false
    )
    @TypeConverters(EventListConverter::class, WorkshopConverter::class, UserProfileConverter::class)
    abstract class MyDatabase : RoomDatabase() {
    @TypeConverters(EventListConverter::class)
    abstract fun eventCategoryDao(): EventCategoryDao
    
    @TypeConverters(WorkshopConverter::class)
    abstract fun workshopListDao(): WorkshopListDao
    
    abstract fun eventDetailsDao(): EventDetailsDao
    
    @TypeConverters(UserProfileConverter::class)
    abstract fun userProfileDao(): UserProfileDao
    
    abstract fun confessionDao(): ConfessionDao
    }
    
    val db = Room.databaseBuilder(App.instance, MyDatabase::class.java, "database")
    .allowMainThreadQueries()
    .fallbackToDestructiveMigration()
    .build()
    

    你可以为不同的 Dao 使用不同的类型转换器

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-10-23
      • 2019-05-26
      • 2023-03-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-05-31
      • 1970-01-01
      相关资源
      最近更新 更多