使用序数转换日期(第11,22等)

时间:2015-09-22 13:23:16

标签: java java-8 java-time

如何转换具有以下格式的日期

  

2015年9月22日,上午10:39:42

  

09/22/2015 10:39:42

在Java 8中

我目前的代码:

String value = "September 22nd 2015, 10:39:42 am";
String format = "dd/MM/yyyy HH:mm:ss"; 
SimpleDateFormat sdf = new SimpleDateFormat(format); 
try { 
  Date date = sdf.parse(value); 
  System.out.println(date); 
  System.out.println(sdf.format(date)); 
}
catch (ParseException ex) {
   ex.printStackTrace(); 
}

3 个答案:

答案 0 :(得分:7)

格式的棘手部分是处理序数(如22nd),即处理正确的后缀。没有内置模式。为此,我们必须在DateTimeFormatter的帮助下构建自己的DateTimeFormatterBuilder

DateTimeFormatterBuilder有一个方法appendText(field, textLookup),其目标是在给定的地图中查找读取文本,并将其替换为与此值相关联的键。这意味着我们需要使用相应的后缀构建所有可能日期(1到31)的Map。

我从this answer获取了转换代码。

我们还需要确保解析忽略大小写的AM / PM标识符(默认情况下,它以大写形式查找AM和PM,但是您的大小写为小写)。这是通过在为此添加模式之前调用parseCaseInsensitive来完成的。

private static final Map<Long, String> DAYS_LOOKUP =
        IntStream.rangeClosed(1, 31).boxed().collect(toMap(Long::valueOf, i -> getOrdinal(i)));

public static void main(String[] args) throws Exception {
    DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendPattern("MMMM")
                                .appendLiteral(" ")
                                .appendText(ChronoField.DAY_OF_MONTH, DAYS_LOOKUP)
                                .appendLiteral(" ")
                                .appendPattern("yyyy")
                                .appendLiteral(", ")
                                .appendPattern("hh")
                                .appendLiteral(":")
                                .appendPattern("mm")
                                .appendLiteral(":")
                                .appendPattern("ss")
                                .appendLiteral(" ")
                                .parseCaseInsensitive()
                                .appendPattern("a")
                                .toFormatter(Locale.ENGLISH);
    LocalDateTime dateTime = formatter.parse("September 22nd 2015, 10:39:42 am", LocalDateTime::from);
    String text = DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm:ss").format(dateTime);
    System.out.println(text);
}

private static String getOrdinal(int n) {
    if (n >= 11 && n <= 13) {
        return n + "th";
    }
    switch (n % 10) {
        case 1:  return n + "st";
        case 2:  return n + "nd";
        case 3:  return n + "rd";
        default: return n + "th";
    }
}

答案 1 :(得分:1)

您需要2种日期格式(基本上您需要2个步骤来执行任务):

  1. 使用相关的日期格式字符串解析日期September 22nd 2015, 10:39:42 am,以便将其转换/转换为日期对象
  2. 格式化所需dd/MM/yyyy HH:mm:ss格式的日期对象以获取日期输出。
  3. 我将离开实施细节供您学习和探索。

    Tutorial for parsing & formatting using the new Date & Time API

答案 2 :(得分:1)

这里是一个没有外部库的简短Java-8解决方案:

DateTimeFormatter formatter = 
  DateTimeFormatter.ofPattern(
    "MMMM d['st']['nd']['rd']['th'] yyyy, hh:mm:ss a", Locale.ENGLISH);
formatter = 
  new DateTimeFormatterBuilder().parseCaseInsensitive().append(formatter).toFormatter();
LocalDateTime dateTime = 
  formatter.parse("September 22nd 2015, 10:39:42 am", LocalDateTime::from);
String text = DateTimeFormatter.ofPattern("MM/dd/yyyy HH:mm:ss").format(dateTime);
System.out.println(text); // 09/22/2015 10:39:42

只有一点需要注意:建议的解析器也可能接受有趣的输入,例如&#34; ... 22ndst ...&#34;等等,但我认为这可以忽略不计。