I'm using @TypeConverter
in Room to convert string to Date (datetime). Here is the code
public class DateTimeConverter {
@TypeConverter
public static Date stringToDate(String value) {
DateFormat df = new SimpleDateFormat(Constants.SQLITE_DATE_TIMEFORMAT, Locale.US);
if (value != null) {
try {
return df.parse(value);
} catch (ParseException e) {
e.printStackTrace();
}
}
return null;
}
@TypeConverter
public static String dateToString(Date value) {
DateFormat df = new SimpleDateFormat(Constants.SQLITE_DATE_TIMEFORMAT, Locale.US);
if (value != null) {
return df.format(value);
} else {
return null;
}
}
}
@Entity
@TypeConverters(DateTimeConverter::class)
data class Entity(
var writeDate: Date = Date() // java.util.Date
)
My current issues is
stringtoDate
receivesvalue = null
which results inEntity.writeDate
to be null which is a run-time exception
Question
- How to convert string to Date with null safety? The value of
writeDate
in the table is never null, butstringToDate
still receivesvalue = null
.
Note:
- Using SDK > 23. So can't use
DateTimeFormatter.ofPattern
CodePudding user response:
The value of writeDate in the table is never null, but stringToDate still receives value = null.
You issue would be to determine why the writeDate is being extracted as null and that would be within the functions in classes that are annotated with @Dao.
However, you could us the following to ensure that nulls are never returned:-
public class DateTimeConverter {
@TypeConverter
public static Date stringToDate(String value) {
Date defaultDate = new Date(0); //1970-01-01 00:00:00
DateFormat df = new SimpleDateFormat(Constants.SQLITE_DATE_TIMEFORMAT, Locale.US);
if (value != null) {
try {
return df.parse(value);
} catch (ParseException e) {
e.printStackTrace();
}
}
return defaultDate;
}
@TypeConverter
public static String dateToString(Date value) {
DateFormat df = new SimpleDateFormat(Constants.SQLITE_DATE_TIMEFORMAT, Locale.US);
if (value != null) {
return df.format(value);
} else {
return "1970-01-01 00:00:00";
}
}
}
Here's a demonstration that uses the above in conjunction with:-
The @Dao class AllDao :-
@Dao
abstract class AllDao {
@Insert(onConflict = IGNORE)
abstract fun insert(entity: Entity)
/* Delete all rows */
@Query("DELETE FROM entity")
abstract fun clear()
/* get inserted data */
@Query("SELECT * FROM entity")
abstract fun getAllFromEntity(): List<Entity>
/* purposefully get 2 invalid dates (1 rubbish date, 1 NULL) */
@Query("SELECT -999 AS id,'invaliddate' AS writeDate UNION SELECT -123 AS id, NULL as writeDate")
abstract fun getMessedUpDate(): List<Entity>
}
- The getMessedUpDate designed to do as it says and get dates that would result in nulls by the TypeConverters in the question but not by the modified TypeConverters in the Answer.
and then using :-
db = TheDatabase.getInstance(this)
dao = db.getAllDao()
dao.clear()
dao.insert(Entity())
var dateInt = (System.currentTimeMillis())
dao.insert(Entity(writeDate = Date(dateInt)))
dao.insert(Entity(1000,Date((System.currentTimeMillis()) - (100 /*days*/ * 24 /*hours*/ * 60 /*mins*/ * 60 /*secs*/ * 1000))))
for (e: Entity in dao.getAllFromEntity()) {
Log.d("DBINFO","Date is ${e.writeDate} ID is ${e.id}")
}
for (e: Entity in dao.getMessedUpDate()) {
Log.d("DBINFO","Date is ${e.writeDate} ID is ${e.id}")
}
The log includes :-
2021-11-06 07:40:38.063 D/DBINFO: Date is Sat Nov 06 07:40:38 GMT 11:00 2021 ID is 1
2021-11-06 07:40:38.064 D/DBINFO: Date is Sat Nov 06 07:40:38 GMT 11:00 2021 ID is 2
2021-11-06 07:40:38.064 D/DBINFO: Date is Fri Nov 05 17:46:12 GMT 11:00 2021 ID is 1000
2021-11-06 07:40:38.069 D/DBINFO: Date is Thu Jan 01 10:00:00 GMT 10:00 1970 ID is -999
2021-11-06 07:40:38.069 D/DBINFO: Date is Thu Jan 01 10:00:00 GMT 10:00 1970 ID is -123
- i.e. the 4th and 5th lines have returned the "default date" rather than null.