JSON 使用 apache 通用的 UTC 日期字符串到本地日期字符串

JSON UTC date string to local date string using apache common

我从另一个背景来到Java。这个问题可能看起来很傻,但我目前的技能无法解决它。

我的服务器 returns UTC 日期为 json 字符串。我将 Gson 与自定义类型适配器一起使用,并使用 SimpleDateFormat 将其转换为所需的日期格式(加上本地时区)。但是由于 SimpleDateFormat 不是线程安全的,所以我正在尝试使用 Apache 公共语言库来获得我失败的相同内容。

    //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 通用(线程安全)将 UTC 日期字符串转换为本地日期字符串。此外,如果有优化代码来执行相同的操作,那将不胜感激。

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

Use the below method for converting UTC date format to Local date Format
private void converUTCTOLocal(){
        String dateInput = "02/04/2016 12:22:11";
    //sdfIn is current date format
        SimpleDateFormat sdfIn  = new SimpleDateFormat("dd/mm/yyyy hh:mm:ss");
    //sdfOut is required date format
        SimpleDateFormat sdfOut  = new SimpleDateFormat("dd/mm/yyyy hh:mm:ss");
        sdfOut.setTimeZone(Calendar.getInstance().getTimeZone());
        TimeZone utcZone = TimeZone.getTimeZone("UTC");
        sdfIn.setTimeZone(utcZone);
        try {
            Date dateIn = sdfIn.parse(dateInput);
            String dateOut = sdfOut.format(dateIn);
            Log.i("dateOut",""+dateOut);


        }catch (ParseException e1){
            e1.printStackTrace();
        }catch (Exception e){
            e.printStackTrace();`enter code here`
        }

    }

使用库 Apache Commons v3.3.2 中的 class FastDateFormat 对我来说是这样的:

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.time.format-Java-8 中的包),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
}