【问题标题】:JSON UTC date string to local date string using apache commonJSON UTC日期字符串到本地日期字符串使用apache common
【发布时间】:2016-07-26 11:48:58
【问题描述】:

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

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

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

【问题讨论】:

    标签: java android json date apache-commons


    【解决方案1】:

    使用 Apache Commons v3.3.2 库中的 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-8 中的 java.time.format-package)、ThreetenABP(向后移植到 Android)、Joda-Time -Android 和 Time4A(我自己的库,显然是最快的 - 大约是两倍的速度)。因此,如果您也关心性能,我认为值得考虑这些其他库替代方案。

    更新:

    我现在已经成功下载并测试了 v3.4 版本,所以我无法在此处复制您的评论。如果有的话,我也不希望在非主要版本中删除如此重要的方法。也许您只是认为您拥有 v3.4 但另一个旧版本处于活动状态。

    使用其他库的示例:

    Threeten-ABP(JSR-310 的 backport 适配 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(Joda-Time for Android 的改编)

    解析比 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
    }
    

    【讨论】:

    • 我正在使用 ApacheCommons v3.4 并且没有 parse() 方法让我很麻烦。如果我使用parseObject(),那么它将 Date 对象从 catch 块返回为 null。
    • 我使用的是 Java-7,所以不能使用 JSR-310。如果我找不到解决方案,那么我会尝试 Joda。关于 ThreeTenABP 和 Time4A 我不明白如何在我的模型和日期适配器中使用它们来满足我的要求。如果你能提供样品,那将对我有帮助。
    • @RajanSharma v3.4官方API提到method,下载后会尽快测试。
    • 一定要检查一下。我不知道为什么我得到红色的parse()(无法解析方法)
    • @RajanSharma 请检查您的类路径和/或依赖项。我现在已经测试了 v3.4
    【解决方案2】:
    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`
            }
    
        }
    

    【讨论】:

    • 仔细阅读我的要求。我必须避免使用 SimpleDateFormat。
    猜你喜欢
    • 1970-01-01
    • 2018-09-27
    • 2015-05-07
    • 2021-04-19
    • 2020-02-03
    • 2014-11-14
    • 1970-01-01
    • 2019-12-09
    • 2020-07-18
    相关资源
    最近更新 更多