web-dev-qa-db-ja.com

Java:TemporalAccessorからLocalDateを取得できません

String日付の形式をEEEE MMMM dからMM/d/yyyyに変更しようとしています。最初にLocalDateに変換してから、別のフォーマッターを適用しますLocalDateを再度解析する前に、Stringにパターン化します。

ここに私のコードがあります:

private String convertDate(String stringDate) 
{
    //from EEEE MMMM d -> MM/dd/yyyy

    DateTimeFormatter formatter = new DateTimeFormatterBuilder()
            .parseCaseInsensitive()
            .append(DateTimeFormatter.ofPattern("EEEE MMMM d"))
            .toFormatter();

    LocalDate parsedDate = LocalDate.parse(stringDate, formatter);
    DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("MM/d/yyyy");

    String formattedStringDate = parsedDate.format(formatter2);

    return formattedStringDate;
}

しかし、私は本当に理解していないこの例外メッセージを受け取ります:

Exception in thread "main" Java.time.format.DateTimeParseException: Text 'TUESDAY JULY 25' could not be parsed: Unable to obtain LocalDate from TemporalAccessor: {DayOfWeek=2, MonthOfYear=7, DayOfMonth=25},ISO of type Java.time.format.Parsed
    at Java.time.format.DateTimeFormatter.createError(DateTimeFormatter.Java:1920)
7
user7049000

他の回答ですでに述べたように、LocalDateを作成するには、入力Stringにないyearが必要です。 daymonth、およびdaydayのみがあります。

完全なLocalDateを取得するには、dayおよびmonthを解析し、yearこのday/monthの組み合わせは、曜日と一致します。

もちろん、曜日を無視して、日付が常に現在のであると仮定することもできます。この場合、他の回答はすでに解決策を提供しています。しかし、dayと完全に一致するyearを見つけたい場合は、それが見つかるまでループする必要があります。

また、_Java.util.Locale_を使用してフォーマッタを作成し、monthおよびday of week英語の名前。ロケールを指定しない場合、システムのデフォルトが使用され、常に英語であるとは限りません(実行時にも予告なく変更される可能性があります)。

_DateTimeFormatter formatter = new DateTimeFormatterBuilder()
    .parseCaseInsensitive()
    .append(DateTimeFormatter.ofPattern("EEEE MMMM d"))
    // use English Locale to correctly parse month and day of week
    .toFormatter(Locale.ENGLISH);
// parse input
TemporalAccessor parsed = formatter.parse("TUESDAY JULY 25");
// get month and day
MonthDay md = MonthDay.from(parsed);
// get day of week
DayOfWeek dow = DayOfWeek.from(parsed);
LocalDate date;
// start with some arbitrary year, stop at some arbitrary value
for(int year = 2017; year > 1970; year--) {
    // get day and month at the year
    date = md.atYear(year);
    // check if the day of week is the same
    if (date.getDayOfWeek() == dow) {
        // found: 'date' is the correct LocalDate
        break;
    }
}
_

この例では、2017年に開始し、1970年までさかのぼって日付を見つけようとしましたが、ユースケースに適合する値に適応できます。

Year.now().getValue()を使用して、(固定された任意の値の代わりに)現在の年を取得することもできます。

4
user7605325

LocalDate のドキュメントには、

LocalDateは日付を表す不変の日時オブジェクトであり、多くの場合年月日として表示されます。たとえば、「2007年10月2日」という値はLocalDateに格納できます。

あなたの場合、入力StringにはLocalDateの重要なコンポーネント、つまり年がありません。基本的には月と日です。そのため、それに適したクラスを使用できます MonthDay 。それを使用して、コードを次のように変更できます。

DateTimeFormatter formatter = new DateTimeFormatterBuilder()
                .parseCaseInsensitive()
                .append(DateTimeFormatter.ofPattern("EEEE MMMM d"))
                .toFormatter();

 MonthDay monthDay = MonthDay.parse(stringDate, formatter);
 LocalDate parsedDate = monthDay.atYear(2017); // or whatever year you want it at
 DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("MM/d/yyyy");

 String formattedStringDate = parsedDate.format(formatter2);
 System.out.println(formattedStringDate); //For "TUESDAY JULY 25" input, it gives the output 07/25/2017 
10
Pallavi Sonal

実装する必要がある小さな変更は次のとおりです。

_private static String convertDate(String stringDate) 
{
    //from EEEE MMMM d -> MM/dd/yyyy

    DateTimeFormatter formatter = new DateTimeFormatterBuilder().appendPattern("EEEE MMMM dd")
                                        .parseDefaulting(ChronoField.YEAR, 2017)
                                        .toFormatter();

    LocalDate parsedDate = LocalDate.parse(stringDate, formatter);
    DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("MM/d/yyyy");

    String formattedStringDate = parsedDate.format(formatter2);

    return formattedStringDate;
}
_
  1. .parseDefaulting(ChronoField.YEAR, 2017)を使用して、フォーマッターにデフォルトの年を追加します

  2. 次のように引数_"Tuesday July 25"_を使用してメソッドを呼び出しますconvertDate("Tuesday July 25");

2
KayV

別のオプションは、次のことを行うことです(他の回答と同じように、ちょっとハッキーです)。もちろん、日付を現在の年にしたい場合は:

LocalDate localDate = LocalDate.parse(stringDate + " " +LocalDate.now().getYear(), DateTimeFormatter.ofPattern("EEEE MMMM d");
0
jwenting