2017-08-18 28 views
2

我需要解析不同的時間格式到BASIC_ISO_DATE。眼下,有4種類型的日期格式:如何使用DateTimeFormatter統一日期格式

  • 2016-10-01(ISO_LOCAL_DATE)
  • 2016T
  • 201610T
  • 2016-02-07T22:03:39.937Z(ISO 8601)

需要解析到20161001和打印出,默認日爲01,默認月份爲Jan。例子:

  • 2016T - >20160101
  • 201610T - >20161001

如何使用DateTimeFormatter實現這一目標?

+1

在所有情況下你只需要日期(LocalDate)嗎?或者當你需要一天的時間(最後一個例子)? –

+0

我不明白'20161001'的月份可能是一月份嗎?一個錯字? –

+1

@ OleV.V。我認爲這不是一個錯字。如果有一個月(在這種情況下,'10'),則只有一天默認爲'1'。如果沒有月份,則默認爲1月份。 –

回答

3

只是爲了補充@Flown's answer(這完全BTW工作),你也可以使用可選模式(由[]分隔):

DateTimeFormatter parser = new DateTimeFormatterBuilder() 
    // optional ISO8601 date/time and offset 
    .appendOptional(DateTimeFormatter.ISO_OFFSET_DATE_TIME) 
    // optional yyyy-MM-dd or yyyyT or yyyyMMT 
    .appendPattern("[yyyy-MM-dd][yyyy'T'][yyyyMM'T']") 
    // default day is 1 
    .parseDefaulting(ChronoField.DAY_OF_MONTH, 1L) 
    // default month is January 
    .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1L) 
    // create formatter 
    .toFormatter(); 

這工作方式完全相同。您可以選擇哪一個更清晰或更容易維護。如果有不同的模式,使用[]可能最終會更混亂,國際海事組織。

請注意,我用ISO_OFFSET_DATE_TIME而不是ISO_ZONED_DATE_TIME。唯一的區別是ISO_ZONED_DATE_TIME最後也接受時區名稱(如[Europe/London]),而ISO_OFFSET_DATE_TIME不接受。 Check the javadoc欲瞭解更多信息。

1

嘗試這樣:

public LocalDate parse(String str) { 
    // Might want to add some checks here... 
    String text = (str.replaceAll("[\-T]", "") + "0101").substring(0, 8); 
    return LocalDate.parse(text, DateTimeFormatter.ofPattern("yyyyMMdd")); 
} 
2

你可以建立自己的DateTimeFormatter

DateTimeFormatter dateTimeFormatter = new DateTimeFormatterBuilder() 
    .appendOptional(DateTimeFormatter.ISO_ZONED_DATE_TIME) 
    .appendOptional(DateTimeFormatter.ISO_LOCAL_DATE) 
    .appendOptional(new DateTimeFormatterBuilder() 
    .appendValue(ChronoField.YEAR, 4) 
    .optionalStart() 
     .appendValue(ChronoField.MONTH_OF_YEAR) 
    .optionalEnd() 
    .appendLiteral('T') 
    .parseDefaulting(ChronoField.MONTH_OF_YEAR, 1L) 
    .parseDefaulting(ChronoField.DAY_OF_MONTH, 1L) 
    .toFormatter()) 
    .toFormatter(); 
String[] strings = {"2016-10-01", "2016T", "201610T", "2016-02-07T22:03:39.937Z"}; 
for (String s : strings) { 
    System.out.println(LocalDate.parse(s, dateTimeFormatter) 
     .format(DateTimeFormatter.BASIC_ISO_DATE)); 
} 
1

如果你只想要一個DateTimeFormatterFlown’s answer是經過深思熟慮的,並且其本身相當不錯,以增加更多可能的格式或改變在其他方面的要求。

我認爲一個簡單的選擇是,你使用三個或四個DateTimeFormatter對象,並依次嘗試它們,直到一個對象工作。

對於2016T,可以選擇使用parseDefaulting()作爲空運過來的答案,或者只是解析爲Year,然後使用例如.atDay(1)201610T同樣如此:一種選擇是解析爲YearMonth並使用其atDay()

我的解決方案可能不太優雅,但可能更清晰。