2014-10-29 58 views
0

在我的Android應用程序中,我從一個使用ISO8601格式日期的ReST API中提取數據。一個例子是"2014-04-24T21:56:50.443Z"。有時,時區用Z表示,有時用signHH:mm(例如-08:00)表示。ISO8601日期字符串在Android中的Long

從api收到的日期在日期插入到我的數據庫中時轉換爲long。目前,我通過在insert語句中使用以下命令來實現此目的,該語句將iso8601String轉換爲Julian日期,隨後將其轉換爲一個長時間戳,該時間戳記給出了自紀元以來的毫秒數(這是我能想出的唯一命令,我精確到毫秒這是超級重要的,我的應用程序)

"CAST(((strftime('%J', '" + iso8601String + "') - 2440587.5) * 86400000) AS INTEGER)" 

現在的情形已經拿出這要求我輸入iso8601String轉換成其長時間戳它進入數據庫之前也。必須提供給Android的SimpleDateFormat以使用此字符串的模式是yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ,但不幸的是ZZZZZ在Android版本< 4.3中不受支持(但我必須支持所有運行> = 4.0(api level 14)的設備)!

有無論如何我可以解析/格式化iso8601String往返時間戳而不依賴於SimpleDateFormat? (我不能用JodaTime作爲它的一個重要的依賴,它也沒有爲它在Android上的性能知)

轉換將在我的自定義GSON串行/解串器可以做Date秒值進行轉換成Long小號

回答

2

我想出了我自己的答案!其概念是將日期字符串轉換爲SimpleDateFormat(> = api level 14)的所有版本都可以理解的格式,即yyyy-MM-dd'T'HH:mm:ss.SSSZ。因此,當需要序列化日期時,反序列化字符串必須從yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ轉換爲yyyy-MM-dd'T'HH:mm:ss.SSSZ,反之亦然。

這可以通過使用自定義的串行/解串器的GSON

public class GsonIso8601Datelizer implements JsonSerializer<Date>, JsonDeserializer<Date> { 

private static final String COMPAT_FORMAT_STRING = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"; 
private static final char COLON = ':'; 
private static final char ISO8601_TZ_INFO_IS_JUST_Z = 'Z'; 
private static final int ISO8601_COLON_INDEX = 26; 

private final SimpleDateFormat mSimpleDateFormat; 

public GsonIso8601Datelizer() { 
    mSimpleDateFormat = new SimpleDateFormat(COMPAT_FORMAT_STRING); 
} 


@Override 
public JsonElement serialize(Date src, Type typeOfSrc, JsonSerializationContext context) { 
    if (src == null) { 
     return null; 
    } else { 
     StringBuilder stringBuilder; 
     synchronized (this) { 
      stringBuilder = new StringBuilder(mSimpleDateFormat.format(src)); 
     } 

     stringBuilder.insert(ISO8601_COLON_INDEX, COLON); 
     return new JsonPrimitive(stringBuilder.toString()); 
    } 
} 


@Override 
public Date deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context) throws JsonParseException { 
    if (json.isJsonNull() || TextUtils.isEmpty(json.getAsString())) { 
     return null; 
    } else { 
     StringBuilder stringBuilder = new StringBuilder(json.getAsString().trim()); 
     if (stringBuilder.charAt(stringBuilder.length() - 1) == ISO8601_TZ_INFO_IS_JUST_Z) { 
      stringBuilder.replace(stringBuilder.length() - 1, stringBuilder.length(), "+0000"); 
     } else { 
      stringBuilder.deleteCharAt(ISO8601_COLON_INDEX); 
     } 

     Date date; 
     synchronized (this) { 
      try { 
       date = mSimpleDateFormat.parse(stringBuilder.toString()); 
      } catch (ParseException e) { 
       throw new IllegalArgumentException("Couldn't parse date string. " + 
         "Original: " + json.getAsString() + "; " + 
         "After custom processing: " + stringBuilder.toString()); 
      } 
     } 
     return date; 
    } 
} 
完成