I'm trying to figure out, how to do input validation of text field/s when I need for example a date input. It needs to be in format like 31.8.2016 and it has to be today's date or later. So that's two different checks.
Only way I can think off is creating boolean method which will check whether the date is past or future. But I would need to create a new method to check if it's in the right format which will be harder but I think this is not the right approach.
I usually create a date class which looks like this:
public class Date{
private boolean validDay = false;
private boolean validMonth = false;
private boolean validYear = false;
private int day;
private int month;
private int year;
private Calendar cal = Calendar.getInstance();
public Date(int day, int month, int year){
/*
*All of these conditions can also be individually used to check the conditions you
*want to check. simply create 3 texfields and put them in a HBox all values must be entered
*separately !
*/
if(day>=cal.get(Calendar.DAY_OF_MONTH) && day<=cal.getActualMaximum(Calendar.DAY_OF_MONTH)){
this.day = day;
this.validDay = true;
}
else{
//TODO: handle
}
if(month>=cal.get(Calendar.MONTH) && month<=12){
this.month = month;
this.validMonth= true;
}
else{
//TODO: handle
}
if(year>=cal.get(Calendar.YEAR)){
this.year = year;
this.validYear = true;
}
else{
//TODO: handle
}
}
public boolean isDateValid(){
return validDay && validMonth && validYear;
}
public String getDate(){
return day+"."+month+"."+year;
}
public int getDay() {
return day;
}
public int getMonth() {
return month;
}
public int getYear() {
return year;
}
}
you could split the input with a String splitter and crate date!
you could also add set methods!
there are many ways to do this!
I hope this helps!
Related
Scenario: I am currently attempting to make a calendar in Java, one of the methods I have created (getMonthSize) is to get the size of a month (as shown). My goal currently is to make the method respond regardless of whether the argument is defined by the user (give the current month size if argument left blank, and give the size of the inputted month if argument is defined).
Efforts: I have given quite a thorough search for an answer on the web, I have come across answers testing to see if the arg.length==0 (although it turns out that works only if the arg is a String), and answers using something along the lines of "arg!==undefined" (which I think may be for javascript), with no avail. I have also learned that if an integer is not initialized, its default value will be 0, so that is what I tried to take advantage of with my code shown, although it seemed that java still expects me to input "0" for the method to work.
Question: I am hoping there is some command that checks if the argument is left blank, allowing me to set 2 cases, and achieve what I want with the method.
package model;
import java.util.Calendar;
public class myCalendar {
private Calendar calendar=Calendar.getInstance();
private int day=calendar.get(Calendar.DAY_OF_WEEK);
private int date=this.calendar.get(Calendar.DAY_OF_MONTH);
private int month=calendar.get(Calendar.MONTH)+1;
private int year=calendar.get(Calendar.YEAR);
public void setCalendar(int Year, int Month, int Date){
this.calendar.set(Year,Month-1,Date);
}
public int getDay(){
return day;
}
public int getDate () {
return date;
}
public int getMonth(){
return month;
}
public int getYear() {
return year;
}
public int getFirstDay () {
Calendar test = this.calendar;
test.set(year, month-1, 1);
return test.get(Calendar.DAY_OF_WEEK)-1;
}
public int getMonthSize (int num) {
int Month=0;
int days=0;
if (num>0){
Month=num;
} else {
Month=month;
}
if(Month==1||Month==3||Month==5||Month==7
||Month==8||Month==10||Month==12){
days=31;
}
if(Month==4||Month==6||Month==9||Month==11)
{
days=30;
}
if(Month==2)
{
if(((year%4==0)&&(year%100!=0))||(year%400==0))
{
days=29;
}
else
{
days=28;
}
}
return days;
}
public String getNow () {
String monthNames[]={"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
String a=monthNames[month-1]+", "+String.valueOf(year);
return a;
}
}
I hope that I understood your problem correctly.
Your problem is that your user can start the method without a valid argument. If you have a frontend than you should catch it there too. But in the backend (java) you can work with a try-block or simply with if-else.
Cast the Integer to a String and then use regex (maybe something like this
String text = num + "";
if (text != null && text.matches("\\d+")) {
//...
}
Or you can cast your Integer to a String and use String.isEmpty().isEmpty returns true if, and only if, length() is 0. (https://docs.oracle.com/javase/7/docs/api/java/lang/String.html#isEmpty()).
Sting temp = num + "";
if (num.isEmpty()) {
//...
}
Or simply a try-catch Block where you cast your input to a new variable.
try {
Month = Integer.parseInt(num);
} catch (NumberFormatException e) {
// handle error
}
And please notice that your variable "Month" should be "month". In most programming communities everyone uses lowercase variables.
There are countless options how you can handle this situation and you can try every one of them. I hope that the ones I listed are all correct.
Edit:
Oh and I checked the other comments and I noticed that you are a beginner. Here are maybe some useful tips, so everyone in your class including the teacher can read easier your code. In most programming languages there is something like "checkstyle". It is hard to explain, but with some google you can find useful tips.
I will make a few "suggestions" to your code, which you can adopt or ignore. Like spaces between some characters some comments, etc.
But don't focus to hard on the quality. In some IDEs you can automatically format your code to "the standard". With Intellij it is. ctrl+alt+l
import java.util.Calendar;
public class myCalendar {
private Calendar calendar = Calendar.getInstance();
private int day = calendar.get(Calendar.DAY_OF_WEEK);
private int date = this.calendar.get(Calendar.DAY_OF_MONTH);
private int month = calendar.get(Calendar.MONTH) + 1;
private int year = calendar.get(Calendar.YEAR);
/**
* Description what the method does.
*
* #param Year what does the parameter?
* #param Month ""
* #param Date ""
*/
public void setCalendar(int Year, int Month, int Date) {
this.calendar.set(Year, Month - 1, Date);
}
public int getDay() {
return day;
}
public int getDate() {
return date;
}
public int getMonth() {
return month;
}
public int getYear() {
return year;
}
/**
* Description what the method does.
*
* #return value (short description)
*/
public int getFirstDay() {
Calendar test = this.calendar;
test.set(year, month - 1, 1);
return test.get(Calendar.DAY_OF_WEEK) - 1;
}
/**
* Description what the method does.
*
* #param num (short description)
* #return (short description)
*/
public int getMonthSize(int num) {
int month;
int days = 0; //My IDE tells me that need to be initialized, but why? Are there cases where the method returns 0?
//I think that num=100 returns 0, so maybe you can catch this case with if(num > 12) or something similar
if (num > 0) {
month = num;
} else {
month = this.month;
}
if (month == 1 || month == 3 || month == 5 || month == 7
|| month == 8 || month == 10 || month == 12) {
days = 31;
}
if (month == 4 || month == 6 || month == 9 || month == 11) {
days = 30;
}
if (month == 2) {
if (((year % 4 == 0) && (year % 100 != 0)) || (year % 400 == 0)) {
days = 29;
} else {
days = 28;
}
}
return days;
}
public String getNow() {
String monthNames[] = {"January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"};
String a = monthNames[month - 1] + ", " + String.valueOf(year);
return a;
}
}
Excel has a function named NETWORKDAYS.INTL. It receives a start date, an end date, a "type" of weekend and a list of holidays and calculates the number of working days between the two dates. The weekend flag is important because I can consider saturday as a working day. More info here:
http://office.microsoft.com/en-nz/excel-help/networkdays-intl-function-HA010354379.aspx
Is there something like NETWORKDAYS.INTL in Java? Using ObjectLab Kit, Joda and Jollyday I can keep my national holidays and check if the day is saturday, sunday or holiday, but to calculate like the function above I need to iterate over each day and check if valid.
I found nothing so I just code my own method. In my application all dates are saved as timestamp.
public boolean isHoliday(long date) {
return holidaysCalendar.isHoliday(new LocalDate(date));
}
public boolean isSaturday(long date) {
return (new LocalDate(date).dayOfWeek().get() == 7);
}
public boolean isSunday(long date) {
return (new LocalDate(date).dayOfWeek().get() == 1);
}
public boolean isValid(long date, boolean saturday, boolean sunday) {
boolean valid = true;
if (isHoliday(date)) {
valid = false;
} else {
if (!saturday && isSaturday(date)) {
valid = false;
}
if (!sunday && isSunday(date)) {
valid = false;
}
}
return valid;
}
public long addDays(long date, int days) {
return new LocalDate(date).plusDays(days).toDateTimeAtStartOfDay()
.getMillis();
}
public int validDaysBetweenDates(long date1, long date2,
boolean saturday, boolean sunday) {
date1 = addDias(date1, 1);
int cont = 0;
for (long dateTmp = date1; dataTmp <= date2; dataTmp = addDays(dataTmp, 1)) {
if (isValid(dataTmp, saturday, sunday))
cont++;
}
return cont;
}
Pre-notes:
Yes, this is homework.
Our school's tutor is out for the day
My book is useless
I'm not exactly sure what to search for on google for help with my confusion...
Question:
Anyway - The question / confusion that I have involves the first bit of code that I have in my program to test the compareTo method.
Would I use the variables at the top of the code as my variables in the static void main area, or assign new variables, like I do have?
The values in public Date()... <-- Is that the date that my code in static void main is comparing to? (If so, I have a piece of code that I want to use that uses the current date, rather than what's in Date()).
I may have more questions later on, but I hope that someone can clear up my confusion better than my book or google has proven thus far.
Code:
package date;
import java.util.*;
public class Date implements Comparable
{
static Scanner console = new Scanner(System.in);
private int dMonth; //Part a of confusion 1
private int dDay;
private int dYear;
public Date()
{
dMonth = 1; //Confusion 2
dDay = 1;
dYear = 1900;
}
public Date(int month, int day, int year)
{
dMonth = month;
dDay = day;
dYear = year;
}
public void setDate(int month, int day, int year)
{
dMonth = month;
dDay = day;
dYear = year;
}
public int getMonth()
{
return dMonth;
}
public int getDay()
{
return dDay;
}
public int getYear()
{
return dYear;
}
public String toString()
{
return (dMonth + "." + dDay + "." + dYear);
}
public boolean equals(Object otherDate)
{
Date temp = (Date) otherDate;
return (dYear == temp.dYear
&& dMonth == temp.dMonth
&& dDay == temp.dDay);
}
public int compareTo(Object otherDate)
{
Date temp = (Date) otherDate;
int yrDiff = dYear - temp.dYear;
if (yrDiff !=0)
return yrDiff;
int monthDiff = dMonth - temp.dMonth;
if (monthDiff !=0)
return monthDiff;
return dDay - temp.dDay;
}
public static void main(String[] args) //Part b of confusion 1
{
int month;
int day;
int year;
Date temp;
System.out.print("Enter date in the form of month day year");
month = console.nextInt();
day = console.nextInt();
year = console.nextInt();
System.out.println();
}
}
As mentioned in the comments, I think you need to read about the difference between static methods/attributes and the ones in instances. I think this is what you should be doing in the main method:
System.out.print("Enter date in the form of month day year");
Date date1 = new Date(console.nextInt(), console.nextInt(), console.nextInt());
System.out.print("Enter second date in the form of month day year");
Date date2 = new Date(console.nextInt(), console.nextInt(), console.nextInt());
System.out.println("Comparison result:");
System.out.println(date1.compareTo(date2));
Regarding your confusion points:
Class attributes
private int dMonth; //Part a of confusion 1
private int dDay;
private int dYear;
These are special variables. Each instance (that is, every object created with new Date) has its own value for dMonth, dDay and dYear. It is not accessible from the main because main is a static method, and thus doesn't have access to instance variables.
If you didn't understand, at least you know the names to search further.
Default constructor
public Date()
{
dMonth = 1; //Confusion 2
dDay = 1;
dYear = 1900;
}
Those values are used when you create a new Date object without specifying which month/day/year you want. So new Date(2, 3, 2013) means 2/3/2013, while new Date() means 1/1/1900.
No you can't, dMonth, dDay and dYear are member variables. If you want to use them directly inside your main method you will have to use the keyword static so that they become class variables. But no, that is not what you want.
Your main method is doing nothing useful really. Your confusion point 2 is a constructor:
Date d = new Date(); // Data Instance -> First constructor
d.getMonth(); // 1
d.getDay(); // 1
d.getYear(); // 1900
Date d2 = new Date(2, 2, 1901);
d2.getMonth(); // 2
d2.getDay(); // 2
d2.getYear(); // 1901
d2.setDate(3, 3, 1902);
d2.getMonth(); // 3
d2.getDay(); // 3
d2.getYear(); // 1902
d.getMonth(); // Still 1 since member variables of d are independent of d2
d.compareTo(d2); // -2 -> (1900 - 1902)
You can create date instances inside your main method and use code like the one above to access member variables (probably the whole point of your exercise).
Any idea why my code won't show the result? Maybe I messed up something, just new to programming by the way.
The goal of the program is to see if the date given by the main class is valid or not, it's not that specific on details such as the month of February and leap years so its pretty simple.
This is my DataRec.java :
public class DateRec {
int month, day, year;
boolean good;
public DateRec (){
month = 1;
day = 1;
year = 2008;
good = true;
}
public DateRec (int setMonth, int setDay, int setYear){
month = setMonth;
day = setDay;
year = setYear;
}
public void validate (){
if ((month < 0) || (month > 12)){
good = false;
if (year == 0)
good = false;
if ((day < 0) || (day > 31))
good = false;
}
}
#Override
public String toString() {
if (good = true) {
return String.format("%dd/%dd/%dddd", month, day, year);
} else {
return String.format("%dd/%dd/%dddd", month, day, year);
}
}
}
This is my main class DataRecTest.java:
public class DateRecTest {
public static void main (String[] args){
DateRec today = new DateRec(1,2,2014);
DateRec anyDay = new DateRec();
DateRec noDay = new DateRec(13,31,2014);
anyDay.validate();
today.validate();
noDay.validate();
today.toString();
anyDay.toString();
noDay.toString();
}
}
Default value of boolean (good) is false so you need to initialized good in constructor or validate() function i.e
good = true; // in constructor or validate function
To see the results you need to print them.
//To print in java use System.out.print() or println();
System.out.println(today.toString());
//or simply
System.out.println(today); // println will call today.toString() internally
[EDIT]
Since you are storing result in good I recommend the following:
public DateRec (int setMonth, int setDay, int setYear){
month = setMonth;
day = setDay;
year = setYear;
good = true;
validate();
}
Now you don't need to call validate() every-time; just check the value of good
your validate() is wrong.... It will always be set t false (default value) in whenever you use the 3- argument constructor. You are not setting it to true when date is correct.
change it to,
public void validate (){
if ((month <= 0) || (month > 12) || (year==0) || (day<=0) || (day>31)){
good = false;
}
else
{
good=true;
}
I have to validate the date,For example If I enter 31/2/2013,It should give an error as February doesn't contains 31 days,but I am stuck at how to achieve that,I tried to use the switch statement but still in vain.Help would be much appreciated.
public class Date
{
private int PDay;
private int PMonth;
private int PYear;
public Date(int day,int month,int year)
{
setDay(day);
setMonth(month);
setYear(year);
}
public Date(int month,int year)
{
this(1,month,year);
}
public Date(int year)
{
this(1,1,year);
}
public void setDay(int day)
{
PDay=day;
}
public int getDay()
{
return PDay;
}
public void setMonth(int month)
{
if(month>=1 && month<=12)
PMonth=month;
else
System.out.println("Month Invalid-Must be Between 1 & 12");
}
public int getMonth()
{
return PMonth;
}
public void setYear(int year)
{
if(year>=1950 && year<=2049)
PYear=year;
else
System.out.println("Year Invalid-Must be Between 1950 & 2049");
}
public int getYear()
{
return PYear;
}
public String toString()
{
return PDay+"/"+PMonth+"/"+PYear;
}
}
P.S. Its not Homework :P/>
Test Program is:
public class DateTest
{
public static void main(String[] args)
{
Date newDate = new Date(7,14,2012);
Date newDate1 = new Date(2152);
System.out.println(newDate);
System.out.println(newDate1);
}
}
In the constructor, set the day after the year and month:
public Date(int day, int month, int year) {
setYear(year);
setMonth(month);
setDay(day);
}
And in the method setDay() add the validation logic:
public void setDay(int day) {
if (pMonth == 1 && (day < 1 || day > 31)) {
// throw exception or handle error
throw new IllegalArgumentException("invalid number of days");
} else if (pMonth == 2 && (day < 1 || day > 28)) {
// same thing
}
// ... rest of validations
PDay = day;
}
If you want to be even more strict, you can use the year to determine if February has 28 or 29 days.
EDIT: Don't implement date handling on your own as long as there are existing frameworks fitting your needs.
But beware of the pitfalls of some of the existing frameworks: (end of EDIT)
Don't use java.util.Date for such checks. Nearly all of the methods of Date are buggy and have been declared as deprecated. Those setters and getters have been reimplemented in the java.util.Calendar classes. But since they are still buggy in some circumstances the best choice would be to use the new Date Time API of Java 8 if this is an option or to use the "third-party" Jodatime library for correct date handling.
If you just want to have some checks on input, then you may use java.text.SimpleDateFormat that handles the parsing and the checks.