当前位置:  开发笔记 > 编程语言 > 正文

如何在Java中检查日期

如何解决《如何在Java中检查日期》经验,为你挑选了8个好方法。

我发现很奇怪Date在Java中创建对象的最明显的方法已经被弃用,并且似乎被"替换"了一个不太明显的使用宽松日历.

如何检查日期,月份和年份组合的日期是否为有效日期?

例如,2008-02-31(如yyyy-mm-dd)将是无效日期.



1> Aravind R. Y..:

键是df.setLenient(false); .这对于简单的案例来说已经足够了.如果您正在寻找更强大(我怀疑)和/或替代库,如joda-time,那么请用户"tardate"查看答案

final static String DATE_FORMAT = "dd-MM-yyyy";

public static boolean isDateValid(String date) 
{
        try {
            DateFormat df = new SimpleDateFormat(DATE_FORMAT);
            df.setLenient(false);
            df.parse(date);
            return true;
        } catch (ParseException e) {
            return false;
        }
}


仅供参考,非常麻烦的旧日期时间类,如[`java.util.Date`](https://docs.oracle.com/javase/10/docs/api/java/util/Date.html),[ `java.util.Calendar`](https://docs.oracle.com/javase/10/docs/api/java/util/Calendar.html)和`java.text.SimpleDateFormat`现在是[遗产]( https://en.wikipedia.org/wiki/Legacy_system),由[*java.time*]取代(https://docs.oracle.com/javase/10/docs/api/java/time/package- summary.html)Java 8及更高版本中内置的类.请参阅[*Tutorial*by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html).

2> tardate..:

如@Maglob所示,基本方法是使用SimpleDateFormat.parse测试从字符串到日期的转换.这将捕获无效的日/月组合,如2008-02-31.

然而,在实践中,由于SimpleDateFormat.parse非常自由,因此很少.您可能会关注两种行为:

日期字符串中的字符无效 令人惊讶的是,2008-02-2x将作为有效日期"传递",例如,语言环境格式="yyyy-MM-dd".即使isLenient == false.

年份:2,3或4位数? 您可能还希望强制执行4位数年而不是允许默认的SimpleDateFormat行为(根据您的格式是"yyyy-MM-dd"还是"yy-MM-dd",它将以不同的方式解释"12-02-31" )

标准库的严格解决方案

因此,完整的字符串到目前为止测试可能如下所示:正则表达式匹配的组合,然后是强制日期转换.正则表达式的技巧是使它对语言环境友好.

  Date parseDate(String maybeDate, String format, boolean lenient) {
    Date date = null;

    // test date string matches format structure using regex
    // - weed out illegal characters and enforce 4-digit year
    // - create the regex based on the local format string
    String reFormat = Pattern.compile("d+|M+").matcher(Matcher.quoteReplacement(format)).replaceAll("\\\\d{1,2}");
    reFormat = Pattern.compile("y+").matcher(reFormat).replaceAll("\\\\d{4}");
    if ( Pattern.compile(reFormat).matcher(maybeDate).matches() ) {

      // date string matches format structure, 
      // - now test it can be converted to a valid date
      SimpleDateFormat sdf = (SimpleDateFormat)DateFormat.getDateInstance();
      sdf.applyPattern(format);
      sdf.setLenient(lenient);
      try { date = sdf.parse(maybeDate); } catch (ParseException e) { }
    } 
    return date;
  } 

  // used like this:
  Date date = parseDate( "21/5/2009", "d/M/yyyy", false);

请注意,正则表达式假定格式字符串仅包含日,月,年和分隔符.除此之外,格式可以是任何语言环境格式:"d/MM/yy","yyyy-MM-dd"等.可以像这样获取当前语言环境的格式字符串:

Locale locale = Locale.getDefault();
SimpleDateFormat sdf = (SimpleDateFormat)DateFormat.getDateInstance(DateFormat.SHORT, locale );
String format = sdf.toPattern();

Joda时间 - 更好的选择?

我最近听说过joda时间,并且认为我会比较.两点:

    与SimpleDateFormat不同,似乎更擅长对日期字符串中的无效字符进行严格处理

    还没有看到用它强制执行4位数年份的方法(但我猜你可以为此目的创建自己的DateTimeFormatter)

它使用起来非常简单:

import org.joda.time.format.*;
import org.joda.time.DateTime;

org.joda.time.DateTime parseDate(String maybeDate, String format) {
  org.joda.time.DateTime date = null;
  try {
    DateTimeFormatter fmt = DateTimeFormat.forPattern(format);
    date =  fmt.parseDateTime(maybeDate);
  } catch (Exception e) { }
  return date;
}



3> Maglob..:

您可以使用SimpleDateFormat

例如:

boolean isLegalDate(String s) {
    SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
    sdf.setLenient(false);
    return sdf.parse(s, new ParsePosition(0)) != null;
}



4> AdamC..:

目前的方法是使用日历类.它有setLenient方法,如果它超出范围,将验证日期和抛出以及异常.

忘记添加:如果您获得日历实例并使用日期设置时间,这就是您获得验证的方式.

Calendar cal = Calendar.getInstance();
cal.setLenient(false);
cal.setTime(yourDate);
try {
    cal.getTime();
}
catch (Exception e) {
  System.out.println("Invalid date");
}


示例代码有3个问题:1.获取Calendar实例后,必须调用cal.setLenient(false).否则,像2007年2月31日这样的日期将被视为有效.2. cal.setTime()不会抛出异常.您必须在setTime()调用之后调用cal.getTime(),这会在无效日期引发异常.错字:在捕获之前缺少'}'.
仅供参考,麻烦的旧日期时间类,如[`java.util.Date`](https://docs.oracle.com/javase/10/docs/api/java/util/Date.html),[` java.util.Calendar`](https://docs.oracle.com/javase/10/docs/api/java/util/Calendar.html)和`java.text.SimpleDateFormat`现在是[遗产](https ://en.wikipedia.org/wiki/Legacy_system),由[*java.time*]取代(https://docs.oracle.com/javase/10/docs/api/java/time/package-summary .html)Java 8及更高版本中内置的类.请参阅[*Tutorial*by Oracle](https://docs.oracle.com/javase/tutorial/datetime/TOC.html).
不要认为这完全按原样运作.Calendar.setTime采用java.util.Date,因此当您获得"yourDate"对象时,已经发生了从字符串的转换.
无法验证2月31日这样的日期

5> Basil Bourqu..:
TL;博士

使用严格模式上java.time.DateTimeFormatter,以解析LocalDate.陷阱DateTimeParseException.

LocalDate.parse(                   // Represent a date-only value, without time-of-day and without time zone.
    "31/02/2000" ,                 // Input string.
    DateTimeFormatter              // Define a formatting pattern to match your input string.
    .ofPattern ( "dd/MM/uuuu" )
    .withResolverStyle ( ResolverStyle.STRICT )  // Specify leniency in tolerating questionable inputs.
)

解析后,您可能会检查合理的值.例如,过去一百年内的出生日期.

birthDate.isAfter( LocalDate.now().minusYears( 100 ) )
避免遗留日期时间类

避免使用最早版本的Java附带的麻烦的旧日期时间类.现在取代了java.time类.

LocalDate&DateTimeFormatter&ResolverStyle

LocalDate级表示没有时间一天和不同时区的日期,唯一的价值.

String input = "31/02/2000";
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "dd/MM/uuuu" );
try {
    LocalDate ld = LocalDate.parse ( input , f );
    System.out.println ( "ld: " + ld );
} catch ( DateTimeParseException e ) {
    System.out.println ( "ERROR: " + e );
}

java.time.DateTimeFormatter类可以被设置与任何在定义了三种模式从宽解析字符串ResolverStyle枚举.我们在上面的代码中插入一行来尝试每种模式.

f = f.withResolverStyle ( ResolverStyle.LENIENT );

结果:

ResolverStyle.LENIENT
ld:2000-03-02

ResolverStyle.SMART
ld:2000-02-29

ResolverStyle.STRICT
错误:java.time.format.DateTimeParseException:无法解析文本'31/02/2000':无效日期'FEBRUARY 31'

我们可以看到在ResolverStyle.LENIENT模式下,无效日期向前移动相同的天数.在ResolverStyle.SMART模式(默认值)下,做出逻辑决定,将日期保持在月份内,并在2月29日的闰年中与当月的最后一天保持一致,因为该月没有第31天.该ResolverStyle.STRICT模式抛出异常,抱怨没有这样的日期.

根据您的业务问题和政策,所有这三项都是合理的.在您的情况下,您希望严格模式拒绝无效日期而不是调整它.


关于java.time

java.time框架是建立在Java 8和更高版本.这些类取代麻烦的老传统日期时间类,如java.util.Date,Calendar,和SimpleDateFormat.

现在处于维护模式的Joda-Time项目建议迁移到java.time类.

要了解更多信息,请参阅Oracle教程.并搜索Stack Overflow以获取许多示例和解释.规范是JSR 310.

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

从哪里获取java.time类?

Java SE 8, Java SE 9及更高版本

内置.

带有捆绑实现的标准Java API的一部分.

Java 9增加了一些小功能和修复.

Java SE 6 Java SE 7

许多java.time功能都被反向移植到ThreeTen-Backport中的 Java 6和7 .

Android的

更高版本的Android捆绑java.time类的实现.

对于早期的Android(<26),ThreeTenABP项目采用ThreeTen-Backport(如上所述).请参阅如何使用ThreeTenABP ....

ThreeTen-额外项目与其他类扩展java.time.该项目是未来可能添加到java.time的试验场.您可以在此比如找到一些有用的类Interval,YearWeek,YearQuarter,和更多.



6> Matthias Bra..:
java.time

使用Java 8及更高版本中内置的Date和Time API(java.time类),您可以使用LocalDate该类.

public static boolean isDateValid(int year, int month, int day) {
    boolean dateIsValid = true;
    try {
        LocalDate.of(year, month, day);
    } catch (DateTimeException e) {
        dateIsValid = false;
    }
    return dateIsValid;
}


默认情况下,此代码使用`ResolverStyle.SMART`将结果值调整为有效日期而不是抛出异常.所以这段代码不会完成问题的目标.例如,参见[我的答案](http://stackoverflow.com/a/39649815/642706)和使用`ResolverStyle.STRICT`的解决方案.

7> Sufian..:

建立在应允@Pangea来解决这个问题所指出的@ceklock,我添加了一个方法来验证dateString不包含任何无效字符.

我是这样做的:

private boolean isDateCorrect(String dateString) {
    try {
        Date date = mDateFormatter.parse(dateString);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        return matchesOurDatePattern(dateString);    //added my method
    }
    catch (ParseException e) {
        return false;
    }
}

/**
 * This will check if the provided string matches our date format
 * @param dateString
 * @return true if the passed string matches format 2014-1-15 (YYYY-MM-dd)
 */
private boolean matchesDatePattern(String dateString) {
    return dateString.matches("^\\d+\\-\\d+\\-\\d+");
}



8> 小智..:

使用标准库的另一种严格解决方案是执行以下操作:

1)使用您的模式创建严格的SimpleDateFormat

2)尝试使用format对象解析用户输入的值

3)如果成功,使用相同的日期格式(从(1))重新格式化由(2)得到的日期

4)将重新格式化的日期与用户输入的原始值进行比较.如果它们相等,则输入的值严格匹配您的模式.

这样,您不需要创建复杂的正则表达式 - 在我的情况下,我需要支持所有SimpleDateFormat的模式语法,而不是仅限于某些类型,例如几天,几个月和几年.

推荐阅读
小色米虫_524
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有