首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >LocalDate解析抛出异常‽

LocalDate解析抛出异常‽
EN

Stack Overflow用户
提问于 2019-12-28 09:35:37
回答 4查看 4.6K关注 0票数 3

我正在进行以下编程练习:不幸的日子。声明如下:

星期五13号或黑色星期五被认为是不吉利的一天。计算出一年中有多少不幸的日子。 找出给定年份的星期五13号的号码。 输入:年份为整数。 输出:一年中黑色星期五的数目为整数。 示例: unluckyDays(2015年) == 3 unluckyDays(1986年) == 1

首先,我尝试了以下代码:

代码语言:javascript
复制
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;
  }
}

在这里我们得到了以下例外:

代码语言:javascript
复制
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)

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

然后,我决定将格式改为“-”而不是“/”。

代码语言:javascript
复制
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;
  }
}

对于前面的代码,抛出的例外情况是:

代码语言:javascript
复制
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,即只有一个数字的月份:

代码语言:javascript
复制
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");

因为我试过:

代码语言:javascript
复制
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;
  }
}

作为非常有趣的输出:

代码语言:javascript
复制
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解析抛出异常‽

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2019-12-28 09:58:04

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

  • 要么使用DateTimeFormatter并将其传递给您的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是12月。基本上,你很适合这样做。你不需要DateTimeFormatter或者String.format...

我试过你的代码,两种方法都有效。

编辑:

我想回答你的最后一个问题。每次调用LocalDate.parse("anyStringRepresentingADate")时,在引擎盖下面发生的是LocalDate使用默认的DateTimeFormatter

代码语言:javascript
复制
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")时,您的字符串不匹配默认格式,因此出现异常。

票数 4
EN

Stack Overflow用户

发布于 2019-12-28 09:44:17

必须将格式化程序作为第二个参数传递。

代码语言:javascript
复制
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd-M-yyyy");
LocalDate date = LocalDate.parse("01-1-2019", formatter);
票数 1
EN

Stack Overflow用户

发布于 2019-12-29 00:29:36

溪流与羔羊

其他答案是正确的。为了好玩,这里有几种使用lambda语法、流和谓词的方法。

月流

Ole V.V.的评论。中,该解决方案使用从枚举类中通过Arrays实用工具类(1月至12月)获取的一个Month对象流。对于每个月,我们可以问,某一年的第13天是否是星期五。

我们正在动态地实例化一个LocalDate,这是一个日期唯一的值,没有一天的时间,也没有时区。

代码语言:javascript
复制
int year = 2020 ;
long count = 
        Arrays                            // Utility class, `java.util.Arrays`.
        .stream(                          // Generate a stream from an array.
            Month.values()                // Generate an array from all the objects defined on this enum `Month`: An object for January, and February, and so on.
        )                                 // Returns a `Stream` object.
        .filter(                          // Applies a `Predicate` to test each object produced by the stream. Those that pass the test are fed into a new second stream.
            ( Month month ) ->            // For each `Month` enum object.
            LocalDate                     // Represent a date-only value, a year-month-day.
            .of( year , month , 13 )      // Instantiate a `LocalDate` from inputs for year number, `Month` enum object, and day number.
            .getDayOfWeek()               // Interrogate for the `DayOfWeek` enum object that represents the day-of-week for that particular date.
            .equals( DayOfWeek.FRIDAY )   // Ask if the day-of-week for this date is a Friday.
        )                                 // Returns a new 2nd `Stream` object.
        .count()                          // Returns the number of Friday-the-13th dates are being produced by this second stream. The year 2020 has two such dates.
;

看这个在IdeOne.com现场运行的代码

日期流

在另一个解决方案中,我们得到一个Stream of LocalDate对象,用于开始和停止之间的每个日期。请注意,日期范围为半打开,其中开始包含在包含,而结束是排他性的。所以一年从一年的第一天开始,一直持续到第二年的第一年,但不包括第一年。

对于流中的每个日期,我们使用Predicate检查是否(a)月日为13,(b) DayOfWeek为周五。所有通过测试的LocalDate对象都被放入一个新生成的List中。

代码语言:javascript
复制
int input = 2020;
Year year = Year.of( input );
LocalDate start = year.atDay( 1 );
LocalDate stop = year.plusYears( 1 ).atDay( 1 );

List < LocalDate > fridayThe13ths =
        start
                .datesUntil( stop )
                .filter(
                        ( LocalDate localDate ) ->
                                ( localDate.getDayOfMonth() == 13 )
                                        &&
                                        localDate.getDayOfWeek().equals( DayOfWeek.FRIDAY )
                )
                .collect( Collectors.toList() )
;

转储到控制台。生成标准ISO 8601格式的文本。

代码语言:javascript
复制
System.out.println( "fridayThe13ths = " + fridayThe13ths );

fridayThe13ths = 2020-03-13,2020年-11-13

为了验证这些结果确实是星期五-13号,让我们生成表示它们的值的字符串。我们定义了一个格式化程序,用于自动本地化输出,其中包括每周一天。

代码语言:javascript
复制
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDate( FormatStyle.FULL ).withLocale( Locale.US );
fridayThe13ths.forEach( ( LocalDate localDate ) -> System.out.println( localDate.format( f ) ) );

二00二年三月十三日(星期五) 二00二年十一月十三日(星期五)

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/59509685

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档