我来自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)。
答案 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}}