miércoles, febrero 13, 2008

Validar números de cédulas de Nicaragua con Java

Validar números de cédulas de Nicaragua con Java

A continuación comparto un pequeño código Java para validar si una cadena de texto es un número de cédula válido en Nicaragua.

Siéntanse en la libertad de usarlo, modificarlo, copiarlo o compartirlo. Se ha liberado como L-GPL3 y software de dominio público.

Esta es la versión del 10 de agosto del 2013. Con el aporte de Filgrados Correos.

http://sites.google.com/site/denisjtorresg/cedula.zip

Ver versión para JavaScript.


package denisjtorresg.info;

import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

import javax.swing.JOptionPane;

/**
 * Validador de Número de Cédula Nicaraguense
* Este programa es software libre: usted lo puede redistribuir y/o modificar * bajo los términos de la GPL version 3 y/o software de dominio público.
* * blog.denisjtorresg.info * * Con colaboración de: * - Filgrados Correos. *
* * @autor: denisjtorresg@gmail.com * @version: 10/08/2013 * * */ public class ValidarCedula { private final String LETRAS = "ABCDEFGHJKLMNPQRSTUVWXY"; private String cedula = null; /** * Para Pruebas * @param args */ public static void main(String[] args){ String tempo = null; boolean gui = false; ValidarCedula cedula = new ValidarCedula(); if(args.length==0){ cedula.setCedula(JOptionPane.showInputDialog( "Indique la cédula a validar" )); gui = true; } else cedula.setCedula(args[0]); tempo = "Cédula a Validar: " + cedula.getCedula() + "\n"; tempo+= "Prefijo a Validar: " + cedula.getPrefijoCedula()+ "\n"; tempo+= "Fecha a Validar: " + cedula.getFechaCedula()+ "\n"; tempo+= "Sufijo a Validar: " + cedula.getSufijoCedula()+ "\n"; tempo+= "Letra a Validar: " + cedula.getLetraCedula()+ "\n"; tempo+= "¿Es Cédula Válida?: " + (cedula.isCedulaValida()?"SI":"NO")+ "\n"; tempo+= "¿Es Prefijo Válido?: " + (cedula.isPrefijoValido()?"SI":"NO")+ "\n"; tempo+= "¿Es Fecha Válida?: " + (cedula.isFechaValida()?"SI":"NO")+ "\n"; tempo+= "¿Es Sufijo Válido?: " + (cedula.isSufijoValido()?"SI":"NO")+ "\n"; tempo+= "¿Es Letra Válida?: " + (cedula.isLetraValida()?"SI":"NO")+ "\n"; tempo+= "La letra esperada es: " + cedula.calcularLetra() + "\n"; if(gui) JOptionPane.showMessageDialog(null,tempo); else System.out.println(tempo); } /** * Retorna true si la cédula es válida * false en caso contrario * * @return */ public boolean isCedulaValida(){ if(!isPrefijoValido()) return false; if(!isFechaValida()) return false; if(!isSufijoValido()) return false; if(!isLetraValida()) return false; return true; } /** * Retorna true si el prefijo de la cédula es válida * false en caso contrario * * @return */ public boolean isPrefijoValido(){ String prefijo = this.getPrefijoCedula(); if(prefijo==null) return false; Pattern p = Pattern.compile("^[0-9]{3}$"); Matcher m = p.matcher(prefijo); if (!m.find()) return false; return true; } /** * Retorna true si la fecha de la cédula es válida * false en caso contrario * * @return */ public boolean isFechaValida(){ String fecha = this.getFechaCedula(); if(fecha == null) return false; Pattern p = Pattern.compile("^(0[1-9]|[12][0-9]|3[01])(0[1-9]|1[012])([0-9]{2})$"); Matcher m = p.matcher(fecha); if (!m.find()) return false; // verificar si la fecha existe en el calendario try { DateFormat df = new SimpleDateFormat("ddMMyy"); if(!fecha.equals(df.format(df.parse(fecha)))){ return false; } } catch (ParseException ex) { return false; } return true; } /** * Retorna true si el sufijo de la cédula es válida * false en caso contrario * * @return */ public boolean isSufijoValido(){ String sufijo = this.getSufijoCedula(); if(sufijo == null) return false; Pattern p = Pattern.compile("^[0-9]{4}[A-Y]$"); Matcher m = p.matcher(sufijo); if (!m.find()) return false; return true; } /** * Retorna true si la letra de la cédula es válida * false en caso contrario * * @return */ public boolean isLetraValida(){ String letraValida = null; String letra = this.getLetraCedula(); if(letra == null) return false; letraValida = String.valueOf(this.calcularLetra()); return letraValida.equals(letra); } /** * Retorna un entero que representa la posición en la cadena LETRAS * de la letra final de una cédula * * @return */ public int getPosicionLetra(){ int posicionLetra = 0; String cedulaSinLetra = this.getCedulaSinLetra(); long numeroSinLetra = 0; if(cedulaSinLetra == null) return -1; try{ numeroSinLetra = Long.parseLong(cedulaSinLetra); }catch(NumberFormatException e){ return -1; } posicionLetra = (int)(numeroSinLetra - Math.floor((double)numeroSinLetra/23.0) * 23); return posicionLetra; } /** * * Calcular la letra al final de la cédula nicaraguense. *
* Basado en el trabajo de: Arnoldo Suarez Bonilla - arsubo@yahoo.es *
* http://espanol.groups.yahoo.com/group/ptic-nic/message/873 * Mie, 6 de Feb, 2008 2:39 pm *
* Es correcto, los ultimos 4 numeros de la cédula son un consecutivo de las personas que nacen en la misma fecha y municipio. * La letra se calcula con el siguiente algoritmo (yo se los envío en SQL). *
*
     * declare  @cedula      varchar(20),
     *          @val         numeric(13, 0),
     *          @letra       char(1),
     *          @Letras      varchar(20)
     *          
     *          select @Letras = 'ABCDEFGHJKLMNPQRSTUVWXY'
     *          select @cedula = '0012510750012' --PARTE NUMERICA DE LA CEDULA SIN GUIONES
     *          --CALCULO DE LA LETRA DE LA CEDULA   
     *          select @val = convert(numeric(13, 0), @cedula) - floor(convert(numeric(13, 0), @cedula) / 23) * 23
     *          select @letra = SUBSTRING(@Letras, @val + 1, 1)
     *          select @letra
     * 
* @return Letra válida de cédula dada */ public char calcularLetra(){ int posicionLetra = getPosicionLetra(); if(posicionLetra <0 posicionletra="">= LETRAS.length()) return '?'; return LETRAS.charAt(posicionLetra); } /** * Fiajr el Número de Cédula * * @param cedula Número de Cédula con o sin guiones */ public void setCedula(String cedula) { cedula = cedula.trim().replaceAll("-",""); if(cedula == null || cedula.length() != 14) this.cedula = null; else this.cedula = cedula.trim().replaceAll("-","").toUpperCase(); } /** * Retorna el Número de Cédula * @return */ public String getCedula() { return cedula; } /** * Retorna el prefijo de la cédula * @return */ public String getPrefijoCedula(){ if(cedula!=null) return cedula.substring(0,3); else return null; } /** * Retorna la fecha en la cédula * @return */ public String getFechaCedula(){ if(cedula!=null) return cedula.substring(3,9); else return null; } /** * Retorna el sufijo en la cédula * @return */ public String getSufijoCedula(){ if(cedula!=null) return cedula.substring(9,14); else return null; } /** * Retorna la letra de la cédula * @return */ public String getLetraCedula(){ if(cedula!=null) return cedula.substring(13,14); else return null; } /** * Retorna la cédula sin la letra de validación * @return */ public String getCedulaSinLetra(){ if(cedula!=null) return cedula.substring(0,13); else return null; } }

7 comentarios:

  1. Buenisima validacion, estoy seguro que voy hacer uso de ella, gracias.

    PD: no sabia que existia un algoritmo para generar la letra como sale en la validacion, pero es bueno saber.

    ResponderEliminar
  2. Aquí te dejo algo que realice en Excel para un string sin guiones:

    =SI((EXTRAE(A2,14,1)=EXTRAE("ABCDEFGHJKLMNPQRSTUVWXY",(VALOR(EXTRAE(A2,1,13))-TRUNCAR(VALOR(EXTRAE(A2,1,13))/23)*23)+1,1)),"Numero Correcto", "Numero Incorrecto")

    Prácticamente para validar la ultima letra

    Saludos Hector Alvarez C.

    ResponderEliminar
  3. Con tu permiso, he mejorado el método isFechaValida ya que cuando introduces 310968 te dice que es valida, o cuando ingresas 310268 también te dice que es fecha valida.

    public boolean isFechaValida(){
    String fecha = this.getFechaCedula();

    if(fecha == null) return false;
    Pattern p = Pattern.compile("^(0[1-9]|[12][0-9]|3[01])(0[1-9]|1[012])([0-9]{2})$");
    Matcher m = p.matcher(fecha);
    if (!m.find())
    return false;
    else {
    DateFormat df = new SimpleDateFormat("ddMMyy");
    try {
    if (!fecha.equals(df.format(df.parse(fecha)))){ return false;}
    else { return true;}

    } catch (ParseException ex) {
    return false;
    }
    }
    }

    ResponderEliminar
  4. Muchas gracias Filgrados Correos, es una excelente colaboración de tu parte.

    He publicado una nueva versión con tus aportes.

    Saludos

    ResponderEliminar
  5. Aqui un méthodo en Java para calcular la letra de control:

    public String getLetraControlCedula(long cedula){
    String letra ="";
    long control = cedula%23;
    //System.out.println("Control="+control);
    if (7=13) control+=2;
    letra = String.valueOf(((char)(control+65)));
    //System.out.println("Cedula "+cedula+" --> "+ letra);
    return letra;
    }

    ResponderEliminar
  6. No entiendo porque hacer la validación de la lettra en SQL server de Micro$oft :S,

    Pero gracias por el aporte :D

    ResponderEliminar
  7. Muchas gracias por el codigo Denis, me he tomado a la tarea de traducirlo a C#, si a alguien le interesa, por favor escribir a: danielesmar@gmail.com

    ResponderEliminar