0

I am looking for a solution that lets me turn a string containing an iso basic date format, such as 20190330 into a formatted date such as 2019-03-30 (Eur format) or 30/03/2019 (UK format) or 03/30/2019 (US format). The format depends on the format that the user selects. The libraries java.time.LocalDate and java.time.format.DateTimeFormatter seem to offer possibilities of a solution but I find the documentation of these libraries incoherent and confusing and I’m not sure if a solution is possible from these sources.

I have tried the four solutions contained in the return statements shown in the code.

import java.time.LocalDate;
import java.time.format.DateTimeFormatter;

public class DateFormatter {
  private static final String EU_PATTERN = "yyyy-MM-dd";
  private static final String UK_PATTERN= "dd/MM/yyyy";
  private static final String US_PATTERN= "MM/dd/yyyy";
  private static final int EU = 1;
  private static final int UK = 2;
  private static final int US = 3;

  private static String formattedDate(int fmt, String isobasic){
    String pattern = null;
    switch(fmt) {
      case EU: {pattern = EU_PATTERN; break;} 
      case UK: {pattern = UK_PATTERN; break;}
      case US: {pattern = US_PATTERN; break;}
    }
    DateTimeFormatter dateFormatter =     DateTimeFormatter.ofPattern(pattern);
        //    return dateFormatter.format(isobasic); // String cannot be         converted to Temporal Accessor
//    return (String)dateFormatter.format(isobasic); // String cannot be     converted to Temporal Accessor
//    return LocalDate.parse(isobasic, dateFormatter); // LocalDate     cannot be converted to String
      return (String)LocalDate.parse(isobasic, dateFormatter); //     LocalDate cannot be converted to String
  }

  /**
   * @param args the command line arguments
   */
  public static void main(String[] args) {
    System.out.println(formattedDate(EU, "20180927"));
    System.out.println(formattedDate(UK, "20190131"));
    System.out.println(formattedDate(US,  "20171225"));
  }

The expected result would be three formatted dates according tp the format selected: 2018-09-27 31/01/2019 12/25/2017 The actual results are the syntax errors shown after the return codes following the case statement.

My workaround is to rewrite the case statement and use clumsy statements like the following (for the EU format):

case EU: { return isobasic.substring(0,4) + "-" + isobasic.substring(4,6) +     "-" + isobasic.substring(6,8);}

If that’s the only solution I will live with that but I want to check out first of the formatter/localdate libraries offer a more elegant approach.

Rusty
  • 93
  • 1
  • 14
  • It's always better to post the exceptions you get separately. Also don't just cast the result to (String), call either .toString(foo) or String.valueOf(foo) as you're not sure it actually is a String – DGK Jan 23 '19 at 15:16
  • 1
    You try to get a String from a String, so you first have to parse your input with the correct format ( "yyyyMMdd" ) then format the result with one of your pattern. – Xavier Falempin Jan 23 '19 at 17:13
  • Conversion from one string format to another string format generally requires two (2) formatters, one specifying the source format (for parsing) and one for the desired format (for formatting). – Ole V.V. Jan 25 '19 at 12:00
  • I know that many of the answers to the linked original questions use the troublesome and outdated `SimpleDateFormat` class. Don’t do that. Seek out the answers using java.time like you do yourself already. It’s so much nicer to work with (in spite of the beginner’s trouble you seem to have had with it). – Ole V.V. Jan 25 '19 at 12:03
  • Supplementary suggestions: Consider `DateTimeFormatter.ofLocalizedDate` for the appropriate date format for each country (and language). If you do want to handle just Europe, UK and US, use an `enum` for those three rather than `int` constants. And an `EnumMap` for holding your format pattern strings. – Ole V.V. Jan 25 '19 at 12:14

1 Answers1

1

Following my comment, you should try using your iso format to get a TemporalAccessor from your String and then format it to the desired pattern.

I just made minimal changes in your code to achieve the result, you can try it

public class DateFormatter {
    private static final String ISO = "yyyyMMdd";
    private static final String EU_PATTERN = "yyyy-MM-dd";
    private static final String UK_PATTERN = "dd/MM/yyyy";
    private static final String US_PATTERN = "MM/dd/yyyy";
    private static final int EU = 1;
    private static final int UK = 2;
    private static final int US = 3;

    private static String formattedDate(int fmt, String isobasic) {
        String pattern = null;
        switch (fmt) {
            case EU: {
                pattern = EU_PATTERN;
                break;
            }
            case UK: {
                pattern = UK_PATTERN;
                break;
            }
            case US: {
                pattern = US_PATTERN;
                break;
            }
        }
        DateTimeFormatter parser = DateTimeFormatter.ofPattern(ISO);
        TemporalAccessor parsedDate = parser.parse(isobasic);
        return DateTimeFormatter.ofPattern(pattern).format(parsedDate);
    }

    /**
     * @param args the command line arguments
     */
    public static void main(String[] args) {
        System.out.println(formattedDate(EU, "20180927"));
        System.out.println(formattedDate(UK, "20190131"));
        System.out.println(formattedDate(US, "20171225"));
    }
}
Xavier Falempin
  • 1,186
  • 7
  • 19
  • I'm very grateful for your pointer to the TemporalAssessor class, which provides the solution I was looking for. The use of this class is usually not described in examples and tutorials so your solution provides valuable additional information. – Rusty Jan 23 '19 at 18:36
  • There are other libraries to achieve the same result without TemporalAccessor, but most of them behave the same when you want to convert your dates from a String to another format String you first have to parse it specifying a pattern then format the result with the target pattern. If your issue has been solved by my answer can you please mark it as accepted so people with the same issue can find a response more easily, if it is not solved feel free to add info about what is not working. – Xavier Falempin Jan 24 '19 at 10:24
  • 1
    I really see no reason for using `TemporalAccessor` over `LocalDate`. I’d rather recommend the latter. – Ole V.V. Jan 25 '19 at 12:16