How to unify date format using DateTimeFormatter

爷,独闯天下 提交于 2019-11-28 05:58:36

问题


I need to parse different time format into BASIC_ISO_DATE. Right now, there are 4 types of date format:

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

Need to parse to 20161001 and print out, with default day is 01, default month Jan. Examples:

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

How can I use DateTimeFormatter to achieve this?


回答1:


Just to complement @Flown's answer (which works perfectly BTW), you can also use optional patterns (delimited by []):

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();

This works exactly the same way. You can choose which one is clearer or easier to maintain. If there are lots of different patterns, using [] might end up being more confusing, IMO.

Note that I used ISO_OFFSET_DATE_TIME instead of ISO_ZONED_DATE_TIME. The only difference is that ISO_ZONED_DATE_TIME also accepts a timezone name in the end (like [Europe/London]), while ISO_OFFSET_DATE_TIME doesn't. Check the javadoc for more info.




回答2:


You could build your own 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));
}



回答3:


Try something like this:

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"));
}



回答4:


If you want just one DateTimeFormatter, Flown’s answer is well thought out and lends itself pretty well to adding more possible formats or changing the requirements in other ways.

I think a simple alternative is that you use three or four DateTimeFormatter objects and try them in turn until one works.

For 2016T, you may either use parseDefaulting() as in Flown’s answer or just parse into a Year and then use for example .atDay(1). Similarly for 201610T: one option is to parse into a YearMonth and use its atDay().

My solution may be less elegant, but possibly clearer to read.



来源:https://stackoverflow.com/questions/45748065/how-to-unify-date-format-using-datetimeformatter

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!