使用apache common将JSON UTC日期字符串转换为本地日期字符串

时间:2016-07-26 11:48:58

标签: java android json date apache-commons

我来自Java的另一个背景。这个问题可能看起来很傻,但我无法用现有的技能来解决它​​。

我的服务器将UTC日期作为json字符串返回。我使用Gson和自定义类型适配器,并使用SimpleDateFormat将其转换为所需的日期格式(加上本地时区)。但是由于SimpleDateFormat不是线程安全的,所以我试图使用Apache常见的lang库来获得我失败的相同内容。

    //private final SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static final FastDateFormat fdf = FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss", TimeZone.getTimeZone("UTC"));

    @Override
    public Date deserialize(JsonElement element, Type arg1, JsonDeserializationContext arg2) throws JsonParseException {

        try {
            return DateUtils.parseDate(element.getAsString(), "yyyy-MM-dd HH:mm:ss");
        } catch (ParseException e) {
            return null;
        }
        /*
        sdf.setTimeZone(TimeZone.getTimeZone("UTC"));

        try {
            return sdf.parse(element.getAsString());
        } catch (ParseException e) {
            return null;
        }
        */
    }

我期待像fdf.parse()这样的东西将UTC日期字符串转换为本地日期,并且不知道我应该使用什么。

在我的模特中:

public class UserData {
    ...
    private Date dt;

    private final SimpleDateFormat sdf = new SimpleDateFormat("MMM dd, yyyy hh:mm a");

    public String getTime() {
        //return dt == null ? "" : sdf.format(dt);
        return DateFormatUtils.format(dt, "MMM dd, yyyy hh:mm a");
    }
}

我的要求是使用Apache common(Thread safe)将UTC日期字符串转换为本地日期字符串。此外,如果有优化代码来执行相同的操作,那将更加重要。

此外,我不需要将日期作为日期数据类型,因此如果日期可以显示为所需格式,则可以将其转换为字符串/删除自定义类型适配器(" MMM dd,yyyy hh:mm a&# 34)。

2 个答案:

答案 0 :(得分:1)

使用库中的FastDateFormat类Apache Commons v3.3.2以这种方式为我工作:

FastDateFormat parser =
    FastDateFormat.getInstance("yyyy-MM-dd HH:mm:ss", TimeZone.getTimeZone("UTC"));
Date d = parser.parse("2015-11-17 19:29:39");
System.out.println(d); // in my time zone Europe/Berlin: Tue Nov 17 20:29:39 CET 2015

FastDateFormat printer =
    FastDateFormat.getInstance(
        "MMM dd, yyyy hh:mm a",
        TimeZone.getDefault(),
        Locale.ENGLISH
    );
System.out.println(printer.format(d)); // Nov 17, 2015 08:29 PM

一些注意事项:

是的,Apache称它是线程安全版本的SimpleDateFormat ,这意味着您可以将其用作临时替换(类似API)并将格式对象存储在静态最终常量。因此,在多线程环境中可以期待更好的性能。但请不要对性能抱有太高的期望。 与旧的SimpleDateFormat相比,它只会更快。

根据我自己的测试,其他更现代的库似乎更快并且也是线程安全的:JSR-310(Java-8中的java.time.format-package),ThreetenABP(向后移植到Android),Joda-Time -Android和Time4A(我自己的库,显然是最快的 - 大致是双倍的速度)。因此,如果您关心性能,我认为值得考虑其他库替代方案。

<强>更新

我已成功下载并测试了v3.4版本,因此我无法在此处重现您的评论。如果有的话,我也不希望在非主要版本中删除这样一个重要的方法。也许你只是相信你有v3.4但另一个旧版本是活跃的。

使用其他库的示例:

Threeten-ABP(将JSR-310的后端改编为Android)

与Apache Commons Lang

大致相同的解析速度
static final DateTimeFormatter PARSER =
    DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss").withZone(
        ZoneOffset.UTC
    );
static final DateTimeFormatter PRINTER =
    DateTimeFormatter.ofPattern("MMM dd, yyyy hh:mm a", Locale.ENGLISH)
    .withZone(ZoneId.systemDefault());

public static String toLocaleZone(String utc) {
  ZonedDateTime zdt = ZonedDateTime.parse("2015-11-17 19:29:39", PARSER);      
  return PRINTER.format(zdt);
}

Joda-Time-Android(适用于Android的Joda-Time)

比ThreetenABP或Apache Commons快一点解析

static final DateTimeFormatter PARSER =
    DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").withZoneUTC();
static final DateTimeFormatter PRINTER =
    DateTimeFormat.forPattern("MMM dd, yyyy hh:mm a").withLocale(Locale.ENGLISH).withZone(
        DateTimeZone.getDefault()
    );

public static String toLocaleZone(String utc) {
  DateTime dt = PARSER.parseDateTime("2015-11-17 19:29:39");
  return PRINTER.print(dt);
}

Time4A(将Time4J改编为Android)

最快的方法(大约是解析器的两倍速度)

static final ChronoFormatter<Moment> PARSER =
    ChronoFormatter.ofMomentPattern(
        "yyyy-MM-dd HH:mm:ss",
        PatternType.CLDR,
        Locale.ROOT,
        ZonalOffset.UTC
    );
static final ChronoFormatter<PlainTimestamp> PRINTER =
    ChronoFormatter.ofTimestampPattern(
        "MMM dd, yyyy hh:mm a",
        PatternType.CLDR,
        Locale.ENGLISH
    );

public static String toLocaleZone(String utc) throws ParseException {
  Moment m = PARSER.parse(utc); // "2015-11-17 19:29:39"
  return PRINTER.format(m.toLocalTimestamp()); // Nov 17, 2015 08:29 pm
}

答案 1 :(得分:0)

{{1}}