Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I work with Date and Time at Room

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?
)
like image 892
Hasan A Yousef Avatar asked Mar 03 '23 15:03

Hasan A Yousef


1 Answers

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?
)
like image 147
Farhan Ibn Wahid Avatar answered Mar 16 '23 11:03

Farhan Ibn Wahid