I've the below model, which have among others, date
and time
fields
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?
)
But I got the below error:
Cannot figure out how to save this field into database. You can consider adding a type converter for it.
So, I wrote the below convertor:
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()
}
}
But did not know how to use this convertor
with the database model
?
UPDATE Based on the received answers, I changed the code to be as below, but still getting the same error:
Converter:
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()
}
}
DataBase:
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
}
}
}
}
And
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 time = new Date().getTime();
long sysTime = System.currentTimeMillis();
Both above will return the same value which is long type. So, you can just use one of them. Which can even be converted to Hours, Minutes or Seconds like this (which can be useful when assigning values):
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());
here, date will return the value as int (3 for today) and formatedDate will return the value as String (03-08-2019 for today).
So, what you can do in you room database class, declare long type variable for time and int/String (which you prefer) for date. Then, and when assigning values to those variables, use the above techniques.
In Kotlin can be done as:
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)
}
And in the Model/Room, as:
@Entity
data class Assignment(
@ColumnInfo(name = "lastUpdate") val lastUpdate: String?
)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With