在Android中,ISO8601日期字符串为Long

时间:2014-10-29 06:59:49

标签: java android date datetime gson

在我的Android应用程序中,我从ReST API中提取数据,该API使用ISO8601格式作为日期。一个例子是"2014-04-24T21:56:50.443Z"。有时,时区用Z表示,有时用signHH:mm表示(例如-08:00)。

我从api收到的日期会在日期插入我的数据库时转换为long。目前我通过在insert语句中使用以下命令实现此目的,该语句将iso8601String转换为Julian日期,随后将其转换为长时间戳,该时间戳给出了自epoch以来的毫秒数(这是我可以提出的唯一命令有了这将给我毫秒精度,这对我的应用来说非常重要)

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

现在出现了一个场景,要求我将传入的iso8601String转换为其长时间戳,甚至在它进入数据库之前。必须提供给Android的SimpleDateFormat以使用此字符串的模式为yyyy-MM-dd'T'HH:mm:ss.SSSZZZZZ,但遗憾的是,Android版本中不支持ZZZZZ< 4.3(但我必须支持所有运行> = 4.0(api level 14)的设备)!!

无论如何,我可以在不依赖SimpleDateFormat的情况下解析/格式化iso8601String与时间戳之间的关系吗? (我不能使用JodaTime作为一个很大的依赖,而且它在Android上的表现并不为人所知)

转换将在我的自定义GSON序列化器/反序列化器中完成,以将Date转换为Long s

1 个答案:

答案 0 :(得分: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;
    }
}