Skip to content

Instantly share code, notes, and snippets.

@jplazcano87
Last active January 16, 2023 23:44
Show Gist options
  • Save jplazcano87/d74b9fb4e93e9fb49cda8f254b6dd80c to your computer and use it in GitHub Desktop.
Save jplazcano87/d74b9fb4e93e9fb49cda8f254b6dd80c to your computer and use it in GitHub Desktop.
Rut validator chile
import Foundation
enum RutError: ErrorType{
case InvalidRut(message : String)
}
class FormValidator: NSObject {
static func validateRut(value : String) throws ->String {
//clean rut
var rut = value.stringByReplacingOccurrencesOfString(".", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
rut = rut.stringByReplacingOccurrencesOfString("-", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
rut = rut.uppercaseString
//check length
if (rut.characters.count < 8 || rut.characters.count > 9 ) {
throw RutError.InvalidRut(message: "Rut ingresado no válido")
}
let rutRegEx = "^(\\d{1,3}(\\.?\\d{3}){2})\\-?([\\dkK])$"
let rutTest = NSPredicate(format:"SELF MATCHES %@", rutRegEx)
if (!rutTest.evaluateWithObject(rut)) {
throw RutError.InvalidRut(message: "Rut ingresado no válido")
}
let rutToValidate = getRutAndDv(rut)
let rutWithoutVerifier = rutToValidate.0
let verifiedDigit = rutToValidate.1
let calculatedVerifiedDigit = getVerifiedDigit(rutWithoutVerifier)
if (verifiedDigit != calculatedVerifiedDigit) {
throw RutError.InvalidRut(message: "Rut ingresado no válido")
}
return rut
}
static func getRutAndDv (value : String) -> (String, String) {
if (value.isEmpty || value.characters.count < 2) {
return ("","")
}
var rut = value.stringByReplacingOccurrencesOfString(".", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
rut = rut.stringByReplacingOccurrencesOfString("-", withString: "", options: NSStringCompareOptions.LiteralSearch, range: nil)
let verifiedDigit = Array(rut.characters)[rut.characters.count-1]
let range : Range<String.Index> = rut.startIndex..<rut.endIndex.advancedBy(-1)
let rutWithoutVerifiedDigit = rut.substringWithRange(range)
return (rutWithoutVerifiedDigit, String(verifiedDigit))
}
static func getVerifiedDigit (rut : String) -> String {
var acumulado : Int = 0
var ti : Int = 2
for index in (rut.characters.count-1).stride(through: 0, by: -1) {
let n = Array(rut.characters)[index]
let nl = String(n)
guard let vl = Int(nl) else {
return ""
}
acumulado += vl * ti
if (ti == 7) {
ti = 1
}
ti += 1
}
let resto : Int = acumulado % 11
let numericDigit : Int = 11 - resto
var digito : String = ""
if (numericDigit <= 9){
digito = String(numericDigit);
}else if (numericDigit == 10){
digito = "K"
}else{
digito = "0"
}
return digito
}
}
//para invocar
do{
let validator = try FormValidator.validateRut("16242343-5") //cambiar por string de rut a validar
}catch RutError.InvalidRut(let message) {
showMessage("Error", message: message, action: nil)
}catch{
DDLogError("an error ocurred during rut validation")
}
@themakunga
Copy link

update a swift 4

static func validadorRut(input: String!)  throws -> String?{
        var rut = input.replacingOccurrences(of: ".", with: "", options: NSString.CompareOptions.literal, range : nil)
        rut = rut.replacingOccurrences(of: "-", with: "", options: NSString.CompareOptions.literal, range : nil)
        rut = rut.uppercased()
        
        if (rut.count < 8 || rut.count > 10){
            throw rutErrors.invalidRut(message: "Largo de RUT no válido")
        }
        
        let rutRegex = "^(\\d{1,3}(\\.?\\d{3}){2})\\-?([\\dkK])$"
        
        let rutTest = NSPredicate(format: "SELF MATCHES %@", rutRegex)
        
        if (!rutTest.evaluate(with: rut)) {
            throw rutErrors.invalidRut(message: "RUT con fomato no válido")
        }
        
        let runTovalidate = getRutDv(value: input)
        
        let rutNumber = runTovalidate.0
        let rutDV = runTovalidate.1
        
        let calculatedDV = validateDV(rut: rutNumber)
        print(runTovalidate)
        print(calculatedDV!)
        if (rutDV != calculatedDV){
            throw rutErrors.invalidRut(message: "Digito verificador no válido")
        }
        
        return rut
    }
    
    static func getRutDv(value: String) -> (String, String){
        if (value.isEmpty || value.count < 2){
            return ("", "")
        }
        
        var rut = value.replacingOccurrences(of: ".", with: "", options: NSString.CompareOptions.literal, range: nil)
        rut = rut.replacingOccurrences(of: "-", with: "", options: NSString.CompareOptions.literal, range: nil)
        
        let dv: String = String(rut.last!)
        let run: String = String(rut.dropLast())
        
        return (run, dv)
    }
    
    static func validateDV(rut: String) -> String?{
        var acumulado : Int = 0
        var ti : Int = 2
        print(rut.count)
        for index in stride(from: rut.count-1, through: 0, by: -1) {
            let n = Array(rut)[index]
            let nl = String(n)
            guard let vl = Int(nl) else {
                return ""
            }
            
            
            acumulado += vl * ti
            
            if (ti == 7) {
                ti = 1
            }
            ti += 1
        }

        let resto : Int = acumulado % 11
        let numericDigit : Int = 11 - resto
        var digito : String = ""

        
        if (numericDigit <= 9){
            digito = String(numericDigit);
        }else if (numericDigit == 10){
            digito = "K"
        }else{
            digito = "0"
        }
        
        return digito
    }

@danielrobleM
Copy link

danielrobleM commented Jul 28, 2021

Hola , gracias por compartir el gist !

Como la expresión regular acepta k y K y la función validateDV returna siempre K
Este if puede marcar como invalido los rut que tengan la k en minúscula 👀

if (rutDV != calculatedDV){

Saludos 👋

@jplazcano87
Copy link
Author

Hola , gracias por compartir el gist !

Como la expresión regular acepta k y K y la función validateDV returna siempre K
Este if puede marcar como invalido los rut que tengan la k en minúscula 👀

if (rutDV != calculatedDV){

Saludos 👋

bastaría un uppercase dentro de la función para que no se vea afectada por eso, gracias por notarlo

Saludos

@escurradeveloper
Copy link

y ¿ Cómo puedo escribir en el textfield y vaya apareciendo automaticamente esto: 22.435.545-K ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment