问题
So I am making a Java program that processes a user's fake credit card and I am trying to make an expiration verification conditional statement. However, when I run my program, I get a "String cannot be converted to int" error. I would like to know how should I use the current month and year to check if the date entered by the user has actually expired.
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);
回答1:
While @ManoDestra's solution will work, I would prefer to keep the types/data sensible. Thus, rather than convert the existing date into a int (which is kind of nonsensical, and the format followed by parse feels nasty), I would prefer to parse the expiration into a date and then compare directly. Something like this:
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
}
You'll probably need to tweak this depending on when you think the expiry actually happens. If the expiry is specified as "0816" is that 01-Aug-2016 00:00:00.000, or 31-Aug-2016 23:59:59.999, or some point in between?
It's a call you have to make (probably by looking at the credit card spec), but that's another thing this approach has compared to the int-converting one: it's not just an abstract sense of "using proper types", but it translates to the real world too. By converting the expiration string to a Date, you need to think about exactly what instant in time that represents, and exactly which values of "now" should count as expired and which should not.
回答2:
YearMonth class
The YearMonth class represents, well, a year and a month.
java.time
This class is part of the 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.
Parsing a String
Use a DateTimeFormatter to parse your input string. When the century is omitted the 21st century 20 is assumed.
String input = "0616";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern ( "MMyy" );
YearMonth expiration = YearMonth.parse ( input , formatter );
Dump to console.
System.out.println ( "yearMonth = " + yearMonth );
yearMonth = 2016-06
Time Zone
Compare to the current YearMonth. Determining the current year-month means getting the current date. And determining the current date requires a time zone. The Question and other Answers ignore this crucial issue. For any given moment the date varies around the globe by time zone. A few minutes after Paris is a new day while still “yesterday” in Montréal.
If omitted as an optional argument, the JVM’s current default time zone is silently implicitly applied. The current default can change at any time, even during runtime(!). Better to specify the expected/desired time zone.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
YearMonth currentYearMonth = YearMonth.now( zoneId );
If your business rules happen to use UTC as the time zone, pass the handy constant ZoneOffset.UTC as the time zone argument.
Compare
Lastly, we compare using isBefore, isAfter, or equals.
Boolean expired = currentYearMonth.isAfter( expiration );
Rather than passing around strings or integers for the year and month, pass around these YearMonth objects. You get the benefits of type safety, guaranteed valid values, and more self-documenting code.
回答3:
Compare it as a String in the form yyMM, whose natural ordering is correct:
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
回答4:
It's not an int. It's a string. This is wrong:
int currentdate = dateformat.format(date);
If you really WANT an int, then convert it to an int:
int currentdate = Integer.parseInt(dateformat.format(date));
However, it won't be a terribly sensible int. If you wish to make this a more sensible int for comparison, then you'd have to put the year first, THEN the month (format: yyMM, or yyyyMM). That way, it will be a consecutive numerical comparison that CAN be compared against other credit card dates. Or, you could simply convert it to a Date or Calendar instead and use date comparisons.
Also, you should make the variable, check, a Boolean value. You have no need for it to be an numeric value.
回答5:
You can replace expnum.nextInt(); with Integer.parseInt(expnum.nextLine()); This will take the input string, and convert it to an int. If they don't put an int though, it will through an exception, so you can put that inside a try-catch statement (and put that in like in a while loop or something so it keeps asking till they answer in the proper format if you want).
来源:https://stackoverflow.com/questions/38134680/comparing-dates-in-mmyy-format