比较 MMYY 格式的日期

Comparing dates in MMYY format

所以我正在制作一个 Java 程序来处理用户的假信用卡,并且我正在尝试制作过期验证条件语句。然而,当我 运行 我的程序时,我得到一个 "String cannot be converted to int" 错误。我想知道我应该如何使用当前的月份和年份来检查用户输入的日期是否已经过期。

do {
  System.out.print("Enter the expiration date mmyy: ");
  expiration = expnum.nextInt();

  DateFormat dateformat = new SimpleDateFormat("MMyy");
  Date date = new Date();
  System.out.println(dateformat.format(date));
  int currentdate = dateformat.format(date);

  if (currentdate <= expiration) {
    check = check + 1;
  } else {
    check = 1;
  }
} while (check == 1);

这不是整数。这是一个字符串。这是错误的:

int currentdate = dateformat.format(date);

如果你真的想要一个整数,那么将它转换成一个整数:

int currentdate = Integer.parseInt(dateformat.format(date));

但是,它不会是一个非常明智的 int。如果你想让它成为一个更明智的 int 来进行比较,那么你必须把年份放在第一位,然后是月份(格式:yyMM 或 yyyyMM)。这样,这将是一个连续的数字比较,可以与其他信用卡日期进行比较。或者,您可以简单地将其转换为 DateCalendar 并使用日期比较。

此外,您应该使变量 check 成为布尔值。你不需要它是一个数值。

你可以替换expnum.nextInt();用 Integer.parseInt(expnum.nextLine());这将获取输入字符串,并将其转换为 int。如果他们不放一个 int ,它会通过一个异常,所以你可以把它放在一个 try-catch 语句中(然后把它放在 while 循环或其他东西中这样它会一直询问直到他们以正确的格式回答如果你愿意的话)。

虽然@ManoDestra 的解决方案可行,但我更愿意保持 types/data 合理。因此,与其将现有日期转换为 int(这有点荒谬,format 后跟 parse 感觉很讨厌),我更愿意将过期解析为日期然后直接比较。像这样:

expiration = expnum.nextInt();
DateFormat dateformat = new SimpleDateFormat("MMyy");
Date expiryDate = dateFormat.parse(expiration);

Date currentDate = new Date();

if (currentDate.isAfter(expiryDate)) {
   // card has expired
} else {
   // card is still active
}

您可能需要根据您认为到期实际发生的时间进行调整。如果到期指定为“0816”是 01-Aug-2016 00:00:00.00031-Aug-2016 23:59:59.999 还是介于两者之间的某个点?

这是您必须进行的调用(可能通过查看信用卡规范),但这是此方法与 int 转换方法相比的另一件事:它不仅仅是 "using proper types" 的抽象意义,但它也转化为现实世界。通过将过期字符串转换为 Date,您需要考虑 确切地 代表什么时间点,以及 "now" 的哪些值应该算作过期而哪些不应该。

YearMonth class

YearMonth class 代表一年零一个月。

java.time

此 class 是 java.time framework built into Java 8 and later. These classes supplant the old troublesome date-time classes such as java.util.Date. See Oracle Tutorial. Much of the functionality has been back-ported to Java 6 & 7 in ThreeTen-Backport and further adapted to Android in ThreeTenABP 的一部分。

解析字符串

使用 DateTimeFormatter 解析您的输入字符串。如果省略世纪,则假定为 21 世纪 20

String input = "0616";

DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "MMyy" );
YearMonth expiration = YearMonth.parse ( input , formatter );

转储到控制台。

System.out.println ( "yearMonth = " + yearMonth );

yearMonth = 2016-06

时区

与当前 YearMonth 比较。确定当前年月意味着获取当前日期。确定当前日期需要一个时区。问题和其他答案忽略了这个关键问题。对于任何给定时刻,日期在全球各地因时区而异。巴黎之后的几分钟是新的一天,而蒙特利尔仍然是“昨天”。

如果作为可选参数省略,则 JVM 当前的默认时区将被隐式应用。当前默认 can change at any time,即使在运行时(!)。最好指定 expected/desired 时区。

ZoneId zoneId = ZoneId.of( "America/Montreal" );
YearMonth currentYearMonth = YearMonth.now( zoneId );

如果您的业务规则碰巧使用 UTC as the time zone, pass the handy constant ZoneOffset.UTC 作为时区参数。

比较

最后,我们使用isBeforeisAfter, or equals

进行比较
Boolean expired = currentYearMonth.isAfter( expiration );

与其传递代表年月的字符串或整数,不如传递这些 YearMonth 对象。您将获得类型安全、有保证的有效值和更多自我记录代码的好处。

将其作为 yyMM 形式的字符串进行比较,其自然顺序是正确的:

int expiration; // MMyy
String expirationStr = String.format("%02d%02d", expiration % 100, expiration / 100);
String now = new SimpleDateFormat("yyMM").format(new Date());
if (expirationStr.compareTo(now) < 0)
    // expired