首页 > 解决方案 > LocalDate 解析抛出异常‽

问题描述

我正在做以下编程练习:Unlucky Days。声明是:

13 日星期五或黑色星期五被认为是不吉利的日子。计算给定年份有多少不吉利的日子。

查找给定年份中 13 日星期五的数字。

输入:年份为整数。

输出:一年中黑色星期五的数量,以整数表示。

例子:

不幸的日子(2015) == 3 不幸的日子(1986) == 1

首先我尝试了以下代码:

import java.time.*;
import java.time.format.*;
import java.util.Locale;

public class Kata {
  public static int unluckyDays/**/(int year) {
    System.out.println("\nyear: "+year);
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy/M/dd");
    for(int i = 1; i <= 12; i++){
      LocalDate date = LocalDate.parse(String.format("%d/%d/13",year,i));
      DayOfWeek dow = date.getDayOfWeek();
      String output = dow.getDisplayName(TextStyle.FULL, Locale.US);
      System.out.println("\noutput: "+output);
    }
    return 0;
  }
}

我们得到以下异常的地方:

java.time.format.DateTimeParseException: Text '2015/1/13' could not be parsed at index 4
    at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
    at java.base/java.time.LocalDate.parse(LocalDate.java:428)
    at java.base/java.time.LocalDate.parse(LocalDate.java:413)
    at Kata.unluckyDays(Kata.java:10)

如我们所见,用于 for 的字符串中索引 4 处的“/”LocalDate.parse(String.format("%d/%d/13",year,i));是错误的。

然后我决定将格式更改为使用'-'而不是'/'

import java.time.*;
import java.time.format.*;
import java.util.Locale;

public class Kata {
  public static int unluckyDays/**/(int year) {
    System.out.println("\nyear: "+year);
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-M-dd");
    for(int i = 1; i <= 12; i++){
      LocalDate date = LocalDate.parse(String.format("%d-%d-13",year,i));
      DayOfWeek dow = date.getDayOfWeek();
      String output = dow.getDisplayName(TextStyle.FULL, Locale.US);
      System.out.println("\noutput: "+output);
    }
    return 0;
  }
}

使用前面的代码,抛出的异常是:

java.time.format.DateTimeParseException: Text '2015-1-13' could not be parsed at index 5
    at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
    at java.base/java.time.LocalDate.parse(LocalDate.java:428)
    at java.base/java.time.LocalDate.parse(LocalDate.java:413)
    at Kata.unluckyDays(Kata.java:10)

因此,正如我们所见,一位数的月份“1”存在困难。

为了继续,我将条件用 0 填充那些只有一位数字的月份:

import java.time.*;
import java.time.format.*;
import java.util.Locale;

public class Kata {
  public static int unluckyDays/**/(int year) {
    System.out.println("\nyear: "+year);
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-M-dd");
    int count = 0;
    for(int i = 1; i <= 12; i++){
      LocalDate date = LocalDate.parse(String.format("%d-%s-13",year,String.valueOf(i).length() < 2 ? "0"+i : i));
      DayOfWeek dow = date.getDayOfWeek();
      String output = dow.getDisplayName(TextStyle.FULL, Locale.US);
      System.out.println("\noutput: "+output);
      if(output.equals("Friday")){
        count++;  
      }
    }
    return count;
  }
}

在这种情况下,它可以工作。但是,我们怎么能指出DateTimeFormatter.ofPattern("yyyy-M-dd");那几个月只能有一位数字。

另外,我们应该怎么做才能使用不同的日期格式,例如:DateTimeFormatter.ofPattern("dd-M-yyyy");

因为我试过:

import java.time.*;
import java.time.format.*;
import java.util.Locale;

public class Kata {
  public static int unluckyDays/**/(int year) {
    System.out.println("\nyear: "+year);
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-M-yyyy");
    int count = 0;
    for(int i = 1; i <= 12; i++){
      LocalDate date = LocalDate.parse(String.format("13-%s-%d",String.valueOf(i).length() < 2 ? "0"+i : i,year));
      DayOfWeek dow = date.getDayOfWeek();
      String output = dow.getDisplayName(TextStyle.FULL, Locale.US);
      System.out.println("\noutput: "+output);
      if(output.equals("Friday")){
        count++;  
      }
    }
    return count;
  }
}

作为输出非常有趣:

java.time.format.DateTimeParseException: Text '13-01-2015' could not be parsed at index 0
    at java.base/java.time.format.DateTimeFormatter.parseResolved0(DateTimeFormatter.java:2046)
    at java.base/java.time.format.DateTimeFormatter.parse(DateTimeFormatter.java:1948)
    at java.base/java.time.LocalDate.parse(LocalDate.java:428)
    at java.base/java.time.LocalDate.parse(LocalDate.java:413)
    at Kata.unluckyDays(Kata.java:11)

正如我们观察到的'13'几天导致异常,在索引0,我不明白。

另外我读过:

我们怎么知道,为什么 LocalDate 解析会抛出异常‽</p>

标签: javastringdatetimeint

解决方案


你离成功很近。您在这里有两个选择:

  • 使用 aDateTimeFormatter并将其传递给您的LocalDate.parseLocalDate date = LocalDate.parse("13/01/2019", new DateTimeFormatter("dd/MM/yyyy");
    查看此网站以获取更多信息: https ://www.baeldung.com/java-string-to-date
  • 或者,您可以使用方法LocalDate.of(year, month, day);:在您的情况下,这将是LocalDate date = LocalDate.of(year, i, 13);. 如果您检查 javadoc,您会看到对于月份参数,1 是一月,12 是十二月。基本上,你很好。你不需要 aDateTimeFormatter或 aString.format...

我试过你的代码,两种方法都可以。

编辑:
我想回答你的最后一个问题。每次调用时LocalDate.parse("anyStringRepresentingADate"),幕后发生的事情LocalDate是使用默认值DateTimeFormatter

public static LocalDate parse(CharSequence text) {
    return parse(text, DateTimeFormatter.ISO_LOCAL_DATE);
}

并且DateTimeFormatter.ISO_LOCAL_DATE'yyyy-MM-dd'
当您这样做时LocalDate.parse("13/1/2020"),您的字符串与默认格式不匹配,因此出现异常。


推荐阅读