【问题标题】:Date year value showing valid when invalid [duplicate]无效时显示有效的日期年份值[重复]
【发布时间】:2018-08-11 15:03:44
【问题描述】:

我正在开发一个日期应用程序,用户将在其中输入日期并且我正在验证该日期。日期格式为dd/MM/yyyy。这是我的代码

import java.util.*;
import java.text.SimpleDateFormat;
import java.text.ParseException;

public class HelloWorld {
  public static void main(String[] args) {
 //Scanner sc = new Scanner(System.in);
  String dat = "02/1/2018";
  try {
             SimpleDateFormat df = new SimpleDateFormat("dd/MM/yyyy");
                df.setLenient(false);
                df.parse(dat);
                System.out.print("valid");
            } catch (ParseException e) {
                System.out.print("invalid");
            }

   }
 }

这是完美的,并且可以验证我的日期,但是当我输入我的日期时,比如22/02/2-19,这也是有效的。但它应该是无效的,因为我的年份是2-19

【问题讨论】:

标签: java validation date


【解决方案1】:

java.time

您正在使用多年前被 java.time 类取代的糟糕的旧日期时间类。

对于仅日期值,请使用仅日期类:LocalDate

使用DateTimeFormatter 类定义您的格式化模式。搜索 Stack Overflow 以获取更多讨论和示例,因为这已被多次讨论。

解析时,捕获DateTimeParseException以确定是否无效。

String input = "22/02/2-19";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "dd/MM/uuuu" );
LocalDate ld = null;
try {
    ld = LocalDate.parse( input , f );
    System.out.println( "VALID: " + ld.toString() );
} catch ( DateTimeParseException e ) {
    System.out.println( "INVALID: " + input );
    e.printStackTrace();
}

无效:22/02/2-19

java.time.format.DateTimeParseException:无法在索引 6 处解析文本“22/02/2-19”...


关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。

从哪里获得 java.time 类?

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

【讨论】:

    【解决方案2】:

    根据javadocSimpleDateFormat

    对于解析,如果模式字母的数量超过 2 个,则按字面解释年份,而不考虑位数。所以使用模式“MM/dd/yyyy”,“01/11/12”解析到公元 12 年 1 月 11 日

    这就是为什么输入22/02/2-19 不会抛出解析异常。它以 2 作为年份,忽略其余部分。

    【讨论】:

    【解决方案3】:

    java.time

    Basil Bourque’s excellent answer 已经为您的问题提供了最佳解决方案。我不是在重复这一点。如果使用该答案,您希望像第一个示例02/1/2018 那样接受 1 位数的月份,您应该在格式模式字符串中只提供一个 M。然后101 都将被接受。类似地,d 将同时接受 202 表示月份中的某天。

    你的代码出了什么问题

    SimpleDateFormat 尽可能多地从您的字符串中读取以匹配格式模式,但很高兴没有读取所有内容。在您的第二个示例22/02/2-19 中,它将22/02/2 解析为 CET 2 Mon Jan 02 00:00:00 的Date(确切结果取决于您的时区),这是 2016 年前的事了。由于这是一个有效的日期,它不会抛出任何异常。然后它会忽略字符串的最后三个字符。

    【讨论】:

      猜你喜欢
      • 2020-02-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-11
      • 1970-01-01
      • 1970-01-01
      • 2018-10-06
      相关资源
      最近更新 更多