Skip to content

Instantly share code, notes, and snippets.

@DominikMostek
Forked from banterCZ/RCValidator.java
Created December 3, 2012 20:59
Show Gist options
  • Save DominikMostek/4197980 to your computer and use it in GitHub Desktop.
Save DominikMostek/4197980 to your computer and use it in GitHub Desktop.
Validator of national identification number used in the Czech Republic.
import static java.util.Calendar.DAY_OF_MONTH;
import static java.util.Calendar.MONTH;
import static java.util.Calendar.YEAR;
import java.util.Calendar;
/**
*
* Validator of national identification number used in the Czech Republic.
*
* See wiki <a href="http://cs.wikipedia.org/wiki/Rodn%C3%A9_%C4%8D%C3%ADslo">http://cs.wikipedia.org/wiki/Rodn%C3%A9_%C4%8D%C3%ADslo</a>
*
* @author banterCZ
*/
public class RCValidator {
/**
* Validates the given national identification number.
*
* @param value to validate (without slash, e.g. 7310285169), may be <code>null</code> or an empty string but returns <code>false</code> in that case
* @return <code>true</code> when number is valid, <code>false</code> otherwise
*/
public boolean isValid(String value) {
if (value == null) {
return false;
}
if (value.length() < 9 || value.length() > 10) {
return false;
}
int year;
int month;
int day;
try {
year = Integer.parseInt(value.substring(0, 2));
month = Integer.parseInt(value.substring(2, 4));
day = Integer.parseInt(value.substring(4, 6));
} catch (NumberFormatException e) {
return false;
}
if (value.length() == 9 && (year >= 54)) {
return false;
}
if (value.length() == 10) {
long mod = Long.parseLong(value.substring(0, 9)) % 11;
int lastNumber = Integer.parseInt(value.substring(9));
if (mod == 10) {
if (lastNumber != 0) {
return false;
}
} else if (lastNumber != mod) {
return false;
}
}
return isDayAndMonthValid(value, year, month, day);
}
private boolean isDayAndMonthValid(String value, int year, int month, int day) {
year = getYearWithHunders(year, value);
month = getRealMonth(year, month);
if (month == 0 || month > 12) {
return false;
}
if (day == 0) {
return false;
}
Calendar calendar = Calendar.getInstance();
calendar.clear();
calendar.set(YEAR, year);
calendar.set(MONTH, month - 1);
int daysInMonth = calendar.getActualMaximum(DAY_OF_MONTH);
if (daysInMonth < day) {
return false;
}
return true;
}
/**
* Removes possible offset (20, 50, or 70).
*
* @param year
* @param month may be with offset
* @return month without offset
*/
private int getRealMonth(int year, int month) {
if ((month > 70) && (year > 2003)) {
month -= 70;
} else if (month > 50) {
month -= 50;
} else if ((month > 20) && (year > 2003)) {
month -= 20;
}
return month;
}
/**
* Possible problem. People born before 1954 usually have the national identification number of length 9 but might be also 10.
* Little bit risky for somebody who is hundred-year old.
*
* @param year
* @param value
* @return
*/
private int getYearWithHunders(int year, String value) {
if (value.length() == 9) {
return year + 1900;
}
if (year > Calendar.getInstance().get(YEAR) % 100) {
return year + 1900;
} else {
return year + 2000;
}
}
}
@RunWith(Parameterized.class)
public class RCValidatorTest {
private RCValidator validator;
private String rcToTest;
private boolean expectedResult;
private String errorMessage;
@Before
public void setUp() {
validator = new RCValidator();
}
public RCValidatorTest(String rc, boolean expect, String errorMessage) {
this.rcToTest = rc;
this.expectedResult = expect;
this.errorMessage = errorMessage;
}
@Test
public void tesRc() {
boolean actual = validator.isValid(rcToTest);
assertEquals(errorMessage, expectedResult, actual);
}
@Parameters
public static Collection rcData() {
return Arrays.asList(new Object[][] {
{"", false, "empty"},
{null, false, "null value"},
{"x123456789", false, "wrong number format"},
{"8405011330", true, "valid mod 11"},
{"73602851", false, "too short"},
{"73102851691", false, "too long"},
{"7310285169", true, "normal man"},
{"7360005158", false, "zero day"},
{"7360335158", false, "invalid day"},
{"1202300011", false, "invalid day in february"},
{"1102290002", false, "invalid day in leap year"},
{"1202290001", true, "valid leap year"},
{"8356078656", false, "invalid" },
{"5305061234", true, "old valid"},
{"530506123", true, "old valid 2"},
{"1202031237", true, "valid after 2K"},
{"1200010009", false, "invalid month"}
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment