Date Validation in Android
Asked Answered
P

7

6

I'm new to Android programming and I'm currently developing an app. Can someone help me on how to validate the date that is being input by the user if is it valid or not?

private Pattern pattern;
private Matcher matcher;

private static final String DATE_PATTERN = 
       "(0?[1-9]|1[012]) [/.-] (0?[1-9]|[12][0-9]|3[01]) [/.-] ((19|20)\\d\\d)";


/**
* Validate date format with regular expression
* @param date date address for validation
* @return true valid date format, false invalid date format
*/
public boolean validate(final String date){

  matcher = pattern.matcher(date);

  if(matcher.matches()){
      matcher.reset();

      if(matcher.find()){
          String day = matcher.group(1);
          String month = matcher.group(2);
          int year = Integer.parseInt(matcher.group(3));

          if (day.equals("31") && 
           (month.equals("4") || month .equals("6") || month.equals("9") ||
                   month.equals("11") || month.equals("04") || month .equals("06") ||
                   month.equals("09"))) {
             return false; // only 1,3,5,7,8,10,12 has 31 days
          }             
      }

      else{
           return false;
      }        
  }
  else{
      return false;
  }              
}
Pilotage answered 2/7, 2013 at 2:41 Comment(0)
N
9
private Pattern pattern;
private Matcher matcher;

private static final String DATE_PATTERN = 
       "(0?[1-9]|1[012]) [/.-] (0?[1-9]|[12][0-9]|3[01]) [/.-] ((19|20)\\d\\d)";


  /**
   * Validate date format with regular expression
   * @param date date address for validation
   * @return true valid date format, false invalid date format
   */
public boolean validate(final String date){

  matcher = pattern.matcher(date);

  if(matcher.matches()){
      matcher.reset();

      if(matcher.find()){
          String day = matcher.group(1);
          String month = matcher.group(2);
          int year = Integer.parseInt(matcher.group(3));

          if (day.equals("31") && 
            (month.equals("4") || month .equals("6") || month.equals("9") ||
                   month.equals("11") || month.equals("04") || month .equals("06") ||
                   month.equals("09"))) {
             return false; // only 1,3,5,7,8,10,12 has 31 days
          } 

          else if (month.equals("2") || month.equals("02")) {
               //leap year
               if(year % 4==0){
                   if(day.equals("30") || day.equals("31")){
                       return false;
                   }
                   else{
                       return true;
                   }
              }
              else{
                  if(day.equals("29")||day.equals("30")||day.equals("31")){
                      return false;
                  }
                  else{
                      return true;
                  }
              }
          }

          else{               
              return true;                
          }
      }

      else{
           return false;
      }        
  }
  else{
      return false;
  }              
}

and put these codes on your onClick():

matcher = Pattern.compile(DATE_PATTERN).matcher(Birthday);

//Birthday validator
    else if (!matcher.matches()) {
    Toast.makeText(getApplicationContext(), "Invalid Birthday!", Toast.LENGTH_SHORt).show();                    
}
Northumbria answered 2/7, 2013 at 2:50 Comment(1)
It doesn't validate '10-12-2000'. can you add the format that it will match?Wotan
S
4

DatePicker is quite painful to input birthday. Here is my solution:

Utils

public static final SimpleDateFormat BIRTHDAY_FORMAT_PARSER = new SimpleDateFormat("yyyy-MM-dd");
public static final String DASH_STRING = "-";
public static Calendar parseDateString(String date) {
        Calendar calendar = Calendar.getInstance();
        BIRTHDAY_FORMAT_PARSER.setLenient(false);
        try {
            calendar.setTime(BIRTHDAY_FORMAT_PARSER.parse(date));
        } catch (ParseException e) {}
        return calendar;
    }
public static boolean isValidBirthday(String birthday) {
        Calendar calendar = parseDateString(birthday);
        int year = calendar.get(Calendar.YEAR);
        int thisYear = Calendar.getInstance().get(Calendar.YEAR);
        return year >= 1900 && year < thisYear;
    }

Main Activity

private void setupBirthdayEditText() {
        mBirthdayEditText.addTextChangedListener(new TextWatcher() {
            int beforeTextChangedLength;
            @Override
            public void beforeTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                beforeTextChangedLength = charSequence.length();
            }

            @Override
            public void onTextChanged(CharSequence charSequence, int i, int i1, int i2) {
                if (!TextUtils.isEmpty(mBirthdayTextInputLayout.getError())) {
                    mBirthdayTextInputLayout.setError(null);
                    mBirthdayTextInputLayout.setErrorEnabled(false);
                }
            }

            @Override
            public void afterTextChanged(Editable editable) {
                int length = editable.length();
                // text is being removed
                if (beforeTextChangedLength > length) return;

                String str = editable.toString();
                String[] strArr = str.split(Utils.DASH_STRING);
                // only add dash after input year with zero dash and input month with one dash
                if ((length == YEAR_LENGTH && strArr.length == 1) || (length == YEAR_MONTH_LENGTH && strArr.length == 2)) {
                    mBirthdayEditText.setText(str + Utils.DASH_STRING);
                    mBirthdayEditText.setSelection(mBirthdayEditText.length());
                }
            }
        });
    }

protected boolean isAllFieldsValid() {
        String birthday = mBirthdayEditText.getText().toString().trim();
        if (!Utils.isValidBirthday(birthday)) {
            mBirthdayTextInputLayout.setError(getString(R.string.error_birth_date));
            return false;
        }

    return true;
}

activity_main.xml

<android.support.design.widget.TextInputLayout
                android:id="@+id/register_birthday_textinput_layout"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                app:errorTextAppearance="@style/ErrorTextInputLayout"
                >

                <android.support.design.widget.TextInputEditText
                    android:id="@+id/register_birthday_edittext"
                    android:hint="@string/birth_date"
                    android:backgroundTint="@color/white_12"
                    android:inputType="date"
                    style="@style/BaseEditText"
                    android:digits="1234567890"
                    android:maxLength="10"
                    />

            </android.support.design.widget.TextInputLayout>

This is not perfect as we shouldn't check validation with try catch and user have to look to the date format during typing, but it is simple and convenient if you want to avoid default date picker.

Sculptor answered 22/8, 2017 at 7:4 Comment(1)
We have the modern java.time classes for this work now or custom. I don't recommend to use SimpleDateFormatAminta
B
3

A better way would be to just show a DatePicker, which by default always provides a valid date.

Boelter answered 2/7, 2013 at 2:45 Comment(1)
While this is true, there is no additional validation if someone added additional characters to the date after it has been added.Quart
A
2

Date Validation(Check Format Of Date)

 public Boolean checkDateFormat(String date){
    if (date == null || !date.matches("^(1[0-9]|0[1-9]|3[0-1]|2[1-9])/(0[1-9]|1[0-2])/[0-9]{4}$"))
        return false;
        SimpleDateFormat format=new SimpleDateFormat("dd/MM/yyyy");
        try {
          format.parse(date);
          return true;
        }catch (ParseException e){
       return false;
    }
}
Attenuate answered 7/12, 2018 at 17:42 Comment(0)
B
2

I did it for MM/dd/yyyy format with Kotlin.

fun validateDate(date: String): Boolean {
        val regex = "^(0[0-9]||1[0-2])/([0-2][0-9]||3[0-1])/([0-9][0-9])?[0-9][0-9]$"
        val matcher = Pattern.compile(regex).matcher(date)
        return if (matcher.matches()) {
            matcher.reset()
            if (matcher.find()) {
                val dateDetails = date.split("/")
                val day: String = dateDetails[1]
                val month: String = dateDetails[0]
                val year: String = dateDetails[2]
                if (validateMonthWithMaxDate(day, month)) {
                    false
                } else if (isFebruaryMonth(month)) {
                    if (isLeapYear(year)) {
                        leapYearWith29Date(day)
                    } else {
                        notLeapYearFebruary(day)
                    }
                } else {
                    true
                }
            } else {
                false
            }
        } else {
            false
        }
    }

    private fun validateMonthWithMaxDate(day: String, month: String): Boolean = day == "31" && (month == "4" || month == "6" || month == "9" || month == "11" || month == "04" || month == "06" || month == "09")
    private fun isFebruaryMonth(month: String): Boolean = month == "2" || month == "02"
    private fun isLeapYear(year: String): Boolean = year.toInt() % 4 == 0
    private fun leapYearWith29Date(day: String): Boolean = !(day == "30" || day == "31")
    private fun notLeapYearFebruary(day: String): Boolean = !(day == "29" || day == "30" || day == "31")

Validated with unit test case.

@Test
    fun `it should validate date`() {
        Assert.assertTrue(subject.validateDate("12/01/2012"))
        Assert.assertTrue(subject.validateDate("01/12/2012"))
        Assert.assertFalse(subject.validateDate("13/12/2012"))
        Assert.assertFalse(subject.validateDate("13/01/2012"))
        Assert.assertFalse(subject.validateDate("12/32/2012"))
        Assert.assertFalse(subject.validateDate("14/01/2012"))
        Assert.assertFalse(subject.validateDate("15/43/2012"))
        Assert.assertTrue(subject.validateDate("02/28/2012"))
        Assert.assertTrue(subject.validateDate("02/29/2012"))
        Assert.assertFalse(subject.validateDate("02/29/2013"))
        Assert.assertFalse(subject.validateDate("02/29/2015"))
        Assert.assertTrue(subject.validateDate("02/29/2016"))
        Assert.assertFalse(subject.validateDate("02/30/2012"))
        Assert.assertTrue(subject.validateDate("02/29/2004"))
        Assert.assertFalse(subject.validateDate("02/31/2004"))
        Assert.assertFalse(subject.validateDate("14/30/2012"))
        Assert.assertFalse(subject.validateDate("01/32/2012"))
        Assert.assertFalse(subject.validateDate("13/03/2012"))
        Assert.assertTrue(subject.validateDate("10/12/2000"))
    }
Bout answered 25/7, 2020 at 6:17 Comment(0)
H
0
public Boolean checkDateFormat(String dateStr){
// dateStr in my case yyyyMMdd format
    String yearStr=dateStr.substring(0,4);
    String monthStr=dateStr.substring(4,6);
    String dayStr=dateStr.substring(dateStr.length() - 2);
  String   dateStrNew=yearStr+"/"+monthStr+"/"+dayStr;
SimpleDateFormat formatter=new SimpleDateFormat("yyyy/MM/dd");
 try {
            Date dateformat=formatter.parse(dateStrNew);
            SimpleDateFormat formatter1 = new SimpleDateFormat("yyyyMMdd");
           String sMMDate = formatter1.format(dateformat);
          
            if (dateStr.equals(sMMDate)) {
                return true;
            }
        } catch (ParseException e) {
            e.printStackTrace();

        }

        return false;
}
Hahnemann answered 1/11, 2022 at 11:14 Comment(0)
S
0
private fun validateDate(dateString: String): Boolean {
        val dateFormatter = DateTimeFormatter.ofPattern("dd.MM.uuuu")
        return try {
            val date = LocalDate.parse(dateString, dateFormatter.withResolverStyle(ResolverStyle.STRICT))
            val currentYear = LocalDate.now().year
            date.year in 1900..currentYear
        } catch (e: DateTimeParseException) {
            false
        }
    }
Swordbill answered 12/9 at 10:40 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.