Convert date with ordinal numbers (11th, 22nd, etc.)

前端 未结 3 1583
闹比i
闹比i 2021-01-14 09:15

How to convert a date having the following format

September 22nd 2015, 10:39:42 am

to

09/22/2015 10:39:42

相关标签:
3条回答
  • 2021-01-14 09:47

    Here a shorter Java-8-only solution without an external library:

    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
    

    There is only one caveat: The suggested parser might also accept funny inputs like "...22ndst..." etc. but I think this can be neglected here.

    0 讨论(0)
  • 2021-01-14 09:53

    The tricky part of the format is to handle ordinal numbers (like 22nd), i.e. handle the right suffix. There is not built-in pattern. For this, we have to build our own DateTimeFormatter with the help of DateTimeFormatterBuilder.

    DateTimeFormatterBuilder has a method appendText(field, textLookup) whose goal is to look for the read text in the given map and replace it by the key associated to this value. This means we need to build a Map of all possibles days (1 to 31) with their corresponding suffix.

    I took the conversion code from this answer.

    We also need to make sure to parse the AM/PM identifier ignoring the case (by default, it looks for AM and PM in uppercase but yours are in lowercase). This is done by calling parseCaseInsensitive before appending the pattern for this.

    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";
        }
    }
    
    0 讨论(0)
  • 2021-01-14 10:00

    You need 2 date formats (and essentially you need 2 steps to perform the task) :

    1. Parsing the date September 22nd 2015, 10:39:42 am using a relevant date format string in order to get/convert it to date object
    2. Formatting the date object for your desired dd/MM/yyyy HH:mm:ss format to get the date output.

    I am leaving the implementation details for you to learn and explore.

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

    0 讨论(0)
提交回复
热议问题