在用 greendao 的時候遇到一個有意思的小問題,當把 sqlite 數據庫中的 timestamp 字段映射到 java 的 date 時,出現時間不正確,date 的值變成了 1970-00-00 00:00:xx
,而後查看了下 date 的 getTime()
方法,發現這個 epoch 值竟然是原來正確時間的年份 2018
, 剩下的部分都沒有轉換過來。在 stackoverflow 也有我的遇到相同的問題,見 https://stackoverflow.com/questions/22172331/greendao-date-type-returning-1-jan-1970。java
跟蹤了下代碼,發現問題其實挺簡單:在 dump 數據並放入到 sqlite 時,這個 timestamp 字段存成了 string ,值爲 2018-11-23 12:31:25
;greendao 在生成 dao 代碼時,date 字段會使用遊標的 getLong()
讀取(按 android 的 sqlite 標準,在讀取 timestamp 時,用 getLong()
),致使格式轉換時只取得了年份 2018 ,用了這個數做爲 epoch 值來建立 Date。android
以上過程可在 intellij 上,查 greendao 生成的 dao 的 readEntity()
方法的代碼, 文件位置爲 'build/generated/source/ <包名> /xxxDao'。 readEntity()
爲從遊標生成實體對象的方法,它會按照每字段從遊標中取數據並進行字段初始化。
sql
作一個通用的 StringDateConverter,把字符串格式轉換爲正確的日期:數據庫
public class StringDateConverter implements PropertyConverter<Date, String> { private final static List<String> FORMATS = Arrays.asList( "yyyy-MM-dd HH:mm:ss" ); @Override public Date convertToEntityProperty(String databaseValue) { Date date = null; for (String format : FORMATS) { try { date = DateUtils.parseDate(databaseValue, format); break; } catch (ParseException e) { // do nothing } } if (date == null) { date = new Date(0); } return date; } @Override public String convertToDatabaseValue(Date entityProperty) { SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); return format.format(entityProperty); } }
而後在每一個 Date 字段上,加一個轉換器:ide
@Entity(nameInDb = "t_user") public class User { ... @Property(nameInDb = "birthday") @Convert(converter = StringDateConverter.class, columnType = String.class) private Date birthday; ... }
從新生成 dao 代碼後,能夠看到對應的字段已作了轉換:ui
...birthdayConverter.convertToEntityProperty(cursor.getString(offset + 7));
數據的讀取已正常。code