2015-09-22 19 views
3

如何轉換具有下列格式轉換日期序數(11日,22日等)

2015年9月22日的日期,上午10點39分42秒

2015年9月22日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(); 
} 
+0

您正在使用哪個Java版本? Java SE 8? – Puce

+1

你有試過任何東西嗎? – Satya

+0

@Puce,是的我正在使用Java SE 8 – Sourabh

回答

1

您需要2種日期格式(而且基本上你需要兩個步驟來執行任務):

  1. 解析使用相關的日期格式字符串的日期September 22nd 2015, 10:39:42 am爲了獲得/將其轉換爲日期對象
  2. 格式化所需的dd/MM/yyyy HH:mm:ss格式的日期對象以獲取日期輸出。

我正在離開實施細節供您學習和探索。

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

+0

以下是使用新日期和時間API解析和格式化的教程:http://docs.oracle.com/javase/tutorial/datetime/iso/format.html – Puce

6

格式的棘手的部分是處理序數(如22nd),即處理的權利後綴。沒有內置模式。爲此,我們必須在DateTimeFormatterBuilder的幫助下建立自己的DateTimeFormatter

DateTimeFormatterBuilder有一個方法appendText(field, textLookup)其目標是在給定的映射中查找讀取的文本並將其替換爲與此值關聯的鍵。這意味着我們需要建立一個包含所有可能日期(1到31)的地圖及其相應的後綴。

我從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"; 
    } 
} 
+0

幾乎正確,但高舉你的努力。請將分析器的「HH」改爲「hh」。否則它沒關係(雖然我敢說我的圖書館[Time4J](http://time4j.net/javadoc-en/net/time4j/format/expert/ChronoFormatter.Builder.html#addEnglishOrdinal-net.time4j.engine 。ChronoElement-)可以實現一個更短,更優雅的解決方案,它也可以與Java-8互操作)。 –

+0

@MenoHochschild你說得對,我編輯了我的文章 – Tunaki

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 

只有一點需要注意:建議的解析器也可能會接受可笑輸入,比如」 ... .. 22ndst 「等等,但我認爲這可以忽略不計。