2

I have this code but the runValidations isn't checking if the day month and year are actually correct. The compiler isn't showing any errors or whatsoever. I've read the code over and over and don't see how I can fix this validation, I would appreciate a lot your help.

I've tried every possible thing i could think of but i haven't gotten anywhere.

 {

    ActivityMainBinding binding;
    boolean isPasswordHidden = true;

    public static final String USER_EXTRA = "USER_EXTRA";

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        binding = ActivityMainBinding.inflate(getLayoutInflater());
        setContentView(binding.getRoot());
        binding.button.setOnClickListener(this::runValidations);
        binding.ivHidden.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                isPasswordHidden = !isPasswordHidden;
                if (isPasswordHidden) {
                    binding.ivHidden.setImageResource(R.drawable.ic_baseline_visibility_off_24);
                    binding.etPassword.setTransformationMethod(new PasswordTransformationMethod());
                } else {
                    binding.ivHidden.setImageResource(R.drawable.ic_baseline_visibility_24);
                    binding.etPassword.setTransformationMethod(null);
                }
                binding.etPassword.setSelection(binding.etPassword.getText().length());
            }
        });
        binding.cbTerms.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
            @Override
            public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) {
                binding.button.setEnabled(isChecked);
            }
        });
    }


    public void runValidations(View view) {

        boolean isEverythingOk = verifyForEmptyField(binding.etName)
                && verifyForEmptyField(binding.etLastName)
                && verifyForEmptyField(binding.etMail)
                && verifyForEmptyField(binding.etPassword)
                && verifyForEmptyField(binding.etDays)
                && verifyForEmptyField(binding.etMonths)
                && verifyForEmptyField(binding.etYears)
                && validateEmailAddressField()
                && validatePasswordLength()
                && validateDay()
                && validateMonth()
                && validateYear();

        if (isEverythingOk) {
            Intent intent = new Intent(this, SuccessActivity.class);
            User user = new User(
                    getTrimmedText(binding.etName),
                    getTrimmedText(binding.etLastName),
                    getTrimmedText(binding.etMail),
                    getTrimmedText(binding.etPassword),
                    "", ""
            );
            intent.putExtra(USER_EXTRA, user);
            startActivity(intent);
            finish();
        }
    }


    private boolean verifyForEmptyField(EditText editText) {
        String fieldContent = getTrimmedText(editText);
        boolean isValid = !fieldContent.isEmpty();
        if (!isValid) {
            editText.setError(getString(R.string.error_empty_field));
        }
        return isValid;
    }

    private String getTrimmedText(EditText editText) {
        return editText.getText().toString().trim();
    }

    private boolean validateEmailAddressField() {
        boolean isValid = Patterns.EMAIL_ADDRESS.matcher(getTrimmedText(binding.etMail)).matches();
        if (!isValid) {
            binding.etMail.setError(getString(R.string.error_invalid_email));
        }
        return isValid;
    }

    private boolean validatePasswordLength() {
        String password = getTrimmedText(binding.etPassword);
        boolean isValid = password.length() >= 10;
        if (!isValid) {
            binding.etPassword.setError(getString(R.string.error_password_lenght));
        }
        return isValid;
    }

    private int parseETtoInt(EditText editText) {
        try {
            String content =getTrimmedText(editText);
            return Integer.parseInt(content);
        } catch (NumberFormatException e) {
            return -1;
        }
    }

    public boolean validateDay() {
        int valueD= parseETtoInt(binding.etDays);
        boolean isValid = (valueD <= 31 && valueD > 0);
        if (!isValid){
            binding.etDays.setError(getString(R.string.error_invalid_day));
        }
        return isValid;
    }

    public boolean validateMonth() {
        int valueM= parseETtoInt(binding.etMonths);
        boolean isValid = (valueM >=1 && valueM <= 12);
        if (!isValid){
            binding.etMonths.setError(getString(R.string.error_invalid_month));
        }
        return isValid;
    }

    public boolean validateYear() {
        int valueY= parseETtoInt(binding.etYears);
        boolean isValid = (valueY < 2021 && valueY > 1900);
        if (!isValid){
            binding.etYears.setError(getString(R.string.error_invalid_year));
        }
        return isValid;
    }

}

It runs validations for name, lastname, mail, password. Everything except for the date, running the avd I can put in any value on the date and no error shows when I introduce a wrong value.

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • 1
    It runs validations for name, lastname, mail, password. Everything except for the date, running the avd I can put in any value on the date and no error shows when I introduce a wrong value. – Michelle Sastre Feb 26 '21 at 21:08
  • Are you sure that the resources exist? `getString(R.string.error_invalid_day)` will throw an exception of no resource with that ID exists, causing your error not to be reported to the user. – Ole V.V. Feb 27 '21 at 13:15

2 Answers2

2

Validating the year, month and day separately will be not only complex but also error-prone. I recommend you validate the complete date string which you can form by combining the values from binding.etYears, binding.etMonths, and binding.etDays.

Demo:

import java.time.DateTimeException;
import java.time.LocalDate;
import java.time.format.DateTimeFormatter;
import java.time.format.ResolverStyle;
import java.util.Locale;

class Main {
    // Simulating year, month and day
    static String etYears = "2020";
    static String etMonths = "2";
    static String etDays = "23";

    public static void main(String[] args) {
        // Tests

        System.out.println(isValidDate());

        etDays = "30";
        System.out.println(isValidDate());

        etMonths = "13";
        etDays = "23";
        System.out.println(isValidDate());

        etYears = "1855";
        etMonths = "2";
        System.out.println(isValidDate());
    }

    static boolean isValidDate() {
        DateTimeFormatter dtf = DateTimeFormatter.ofPattern("uuuu-M-d", Locale.ENGLISH)
                                            .withResolverStyle(ResolverStyle.STRICT);

        String strDate = etYears + "-" + etMonths + "-" + etDays;
        System.out.println(strDate);

        try {
            LocalDate date = LocalDate.parse(strDate, dtf);
            int year = date.getYear();
            return year < 2021 && year > 1900;
        } catch (DateTimeException e) {
            return false;
        }
    }
}

Output:

2020-2-23
true
2020-2-30
false
2020-13-23
false
1855-2-23
false

Learn more about the modern date-time API from Trail: Date Time.

Note: The java.util date-time API and their formatting API, SimpleDateFormat are outdated and error-prone. It is recommended to stop using them completely and switch to the modern date-time API.

Arvind Kumar Avinash
  • 71,965
  • 6
  • 74
  • 110
0

You should use Datepicker but if you want to use EditText I suggest to create a Calendar Instance and try to set day, month and year to it. I dont think that boolean isValid = (valueD <= 31 && valueD > 0); is a good option for day validation. Not all the months have 31 days.

Gorks
  • 120
  • 9