Skip to content

Instantly share code, notes, and snippets.

@dedeexe
Created December 30, 2017 12:53
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dedeexe/5a4a41c6e9f41bbfc82554c5de9622b4 to your computer and use it in GitHub Desktop.
Save dedeexe/5a4a41c6e9f41bbfc82554c5de9622b4 to your computer and use it in GitHub Desktop.
Validate CPF and Create CPF digits
//
// CPF.swift
//
// Created by dede.exe on 30/12/17.
// Copyright © 2017 dede.exe. All rights reserved.
//
import Foundation
///
/// Create an CPF Object
///
public struct CPF {
private (set) public var number : String = ""
/// Create a new CPF entity with number
public init(number:String) {
self.number = number
}
/// Get CPF digits verification
var digits : String {
return calculateCPFDigits() ?? ""
}
/// Check if it is a valida CPF
var isValid : Bool {
if number.count != 11 { return false }
if isAnException { return false }
return self.number.hasSuffix(digits)
}
// MARK: - Helpers
private var isAnException : Bool {
for n in 0...9 {
let number = String(repeating: String(n), count: 11)
if self.number == number { return true }
}
return false
}
private func calculateCPFDigits() -> String? {
var result : String = ""
guard canCalculate() else { return nil }
let startIndex = self.number.startIndex
let endIndex = self.number.index(startIndex, offsetBy: 9)
let number = String(self.number[startIndex..<endIndex])
result = calculateDigit(for: number)
result = result + calculateDigit(for: number + result)
return result
}
private func calculateDigit(for number:String) -> String {
let firstDigitSize = 9
let secondDigitSize = 10
let numberSize = number.count
var values : [Int] = []
if numberSize < firstDigitSize || numberSize > secondDigitSize {
return ""
}
let factor = (numberSize == firstDigitSize) ? firstDigitSize + 1 : secondDigitSize + 1
for (index,char) in number.enumerated() {
let v = (Int(String(char)) ?? 0) * (factor - index)
values.append(v)
}
var result = values.reduce(0) { $0 + $1 }
result = result * 10 % 11
result = (result < 10) ? result : 0
return String(result)
}
private func canCalculate() -> Bool {
return number.count >= 9
}
}
//Usage
let cpf1 = CPF(number: "123123123").digits // "87"
let cpf2 = CPF(number: "12312312387").isValid // true
let cpf3 = CPF(number: "12312312387").isValid // true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment