Home > Back-end >  Convert String to Date with null safety
Convert String to Date with null safety

Time:11-06

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

  1. stringtoDate receives value = null which results in Entity.writeDate to be null which is a run-time exception

Question

  1. How to convert string to Date with null safety? The value of writeDate in the table is never null, but stringToDate still receives value = null.

Note:

  1. 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.
  • Related