java - 解析和格式化日期

标签 java android datetime datetime-format datetime-parsing

<分区>

我有以下代码以字符串形式获取日期 yyyy-MM-dd HH:mm:ss (UTC 时区)并将其转换为 EEEE d(st , nd, rd, th) MMMM yyyy HH:mm(设备的默认时区)。

但是,我的问题是代码看起来凌乱且效率低下。有没有一种方法可以实现我想要的,而无需多次格式化和解析相同的日期以提高效率?或者其他改进?

最好支持 Android API 级别 14。


String inputExample = "2017-06-28 22:44:55";

//Converts UTC to Device Default (Local)
private String convertUTC(String dateStr) {
    try {
        SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        df.setTimeZone(TimeZone.getTimeZone("UTC"));
        Date temp = df.parse(dateStr);
        df.setTimeZone(TimeZone.getDefault());
        String local = df.format(temp);
        Date localDate = df.parse(dateStr);
        SimpleDateFormat outputDF1 = new SimpleDateFormat("EEEE ");
        SimpleDateFormat outputDF2 = new SimpleDateFormat(" MMMM yyyy HH:mm");
        return outputDF1.format(temp) + prefix(local) + outputDF2.format(temp);
    } catch(java.text.ParseException pE) {
        Log.e("", "Parse Exception", pE);
        return null;
    }
}

private String prefix(String dateStr) {
    try {
        SimpleDateFormat outputDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        Date temp = outputDF.parse(dateStr);
        SimpleDateFormat df = new SimpleDateFormat("d");
        int d = Integer.parseInt(df.format(temp));
        if(1 <= d && d <= 31) {
            if(11 <= d && d <= 13)
                return d + "th";
            switch (d % 10) {
                case 1: return d + "st";
                case 2: return d + "nd";
                case 3: return d + "rd";
                default: return d + "th";
            }
        }
        Log.e("", "Null Date");
        return null;
    } catch(java.text.ParseException pE) {
        Log.e("", "Parse Exception", pE);
        return null;
    }
}

最佳答案

使用 SimpleDateFormat 可能没有太多需要改进的地方。由于您的输出格式有 EEEE(星期几)和 MMMM(月份名称),您必须解析日期才能知道这些日期的值。如果不使用日期格式化程序,您将不得不执行大量的 if 操作来获取每个值的相应名称。


在 Android 中,作为 SimpleDateFormat 的替代方案,您可以使用 ThreeTen Backport ,Java 8 的新日期/时间类的一个很好的反向移植,以及 ThreeTenABP (更多关于如何使用它的信息 here)。

所有类都在 org.threeten.bp 包下。在下面的代码中,我还使用了 Locale.ENGLISH,否则它将使用系统的默认设置(因为我的不是英语,我假设你的是):

String inputExample = "2017-06-28 22:44:55";
// parser for input
DateTimeFormatter parser = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss", Locale.ENGLISH);
// parse the date and set to UTC
ZonedDateTime z = LocalDateTime.parse(inputExample, parser).atZone(ZoneOffset.UTC);

// map of custom values - map each numeric value to its string with suffix (st, nd...)
Map<Long, String> textLookup = new HashMap<Long, String>();
for (int i = 1; i <= 31; i++) {
    String suffix = "";
    switch (i) {
    case 1:
    case 21:
    case 31:
        suffix = "st";
        break;
    case 2:
    case 22:
        suffix = "nd";
        break;
    case 3:
    case 23:
        suffix = "rd";
        break;
    default:
        suffix = "th";
    }
    textLookup.put((long) i, i + suffix);
}
// output formatter
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
    // day of week
    .appendPattern("EEEE ")
    // append day with suffix (use map of custom values)
    .appendText(ChronoField.DAY_OF_MONTH, textLookup)
    // rest of pattern
    .appendPattern(" MMMM yyyy HH:mm")
    // create formatter with English locale
    .toFormatter(Locale.ENGLISH);

// print date, convert it to device default timezone
System.out.println(fmt.format(z.withZoneSameInstant(ZoneId.systemDefault())));

输出将是:

Wednesday 28th June 2017 19:44

时间设置为 19:44 因为我的默认时区是 America/Sao_Paulo(UTC-03:00)。

不确定它是否对您来说足够简洁,但至少在我看来,它比 SimpleDateFormat 清晰得多。只创建了 2 个格式化程序(一个用于输出,另一个用于输出)。当然还有 textLookup 映射,但它只有 31 个条目,格式化程序也可以重复使用。

SimpleDateFormat is not thread safe , 而 the new API is .

关于java - 解析和格式化日期,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44813309/

相关文章:

java - 对我的 if 循环没有运行感到有点困惑?

java - 在场景已加载/显示后,如何将复选框添加到 GridPane?

android - firebase API 中的 MismatchSenderID 错误

javascript - 日期-fns |如何格式化为 UTC

python - 符合 ISO 8601 的日期时间,包含时间

java - JPA/Hibernate 批量(批量)插入

java - RxJava : onErrorReturn cast problem when it returns a Set

android - Jersey REST 服务器安全和安卓客户端安全

android - ActionBar 在 Android KitKat 上不可见

c# - 如何使用日期时间获取前一天