Skip to content

Instantly share code, notes, and snippets.

@sgr-ksmt
Last active March 1, 2016 01:28
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 sgr-ksmt/8e2385c53c595a7c8333 to your computer and use it in GitHub Desktop.
Save sgr-ksmt/8e2385c53c595a7c8333 to your computer and use it in GitHub Desktop.
マイナンバーのチェックデジットをSwiftで計算する ref: http://qiita.com/su_k/items/4b442e3094fdea031065
enum ValidationResult {
case Success
case Failure(ValidationErrorType)
}
enum ValidationErrorType: ErrorType {
case WrongLength(Int) // マイナンバーの桁数(文字数)が不正の場合
case NotANumber // 数字以外が含まれている場合
case InvalidNumber // 検査して不正なマイナンバーだった場合
}
// 便宜上関数名末尾に2をつけています。
func validateMyNumber2(numstr: String) -> ValidationResult {
let length = numstr.utf8.count
if length != 12 {
return ValidationResult.Failure(.WrongLength(length))
}
let exp = try! NSRegularExpression(pattern: "^[0-9]+$", options: [])
if exp.matchesInString(numstr, options: [], range: NSMakeRange(0, length)).count == 0 {
return ValidationResult.Failure(.NotANumber)
}
var characters = numstr.characters.map{ String($0) }
let checkDigit = Int(characters.removeLast())!
var pq = 0
for (index, num) in characters.reverse().enumerate() {
let n = index + 1
let p = Int(num)!
let q = (n >= 7) ? n - 5 : n + 1
pq += p * q
}
let remainder = pq % 11
let valid = (remainder <= 1) ? (checkDigit == 0) : (checkDigit == (11 - remainder))
return valid ? ValidationResult.Success : ValidationResult.Failure(.InvalidNumber)
}
func validateMyNumber(numstr: String) -> Bool {
// 桁数チェック
let length = numstr.utf8.count
if length != 12 {
return false
}
// 正規表現を使って数字のみかどうかチェック
let exp = try! NSRegularExpression(pattern: "^[0-9]+$", options: [])
if exp.matchesInString(numstr, options: [], range: NSMakeRange(0, length)).count == 0 {
return false
}
// 扱いやすいように一旦Stringを1文字ずつ分割
var characters = numstr.characters.map{ String($0) }
// チェックデジットをcharactersからpop
// pop後はcharactersの中身は12->11個になります。
let checkDigit = Int(characters.removeLast())!
// 検査用数字の計算
var pq = 0
for (index, num) in characters.reverse().enumerate() {
let n = index + 1
let p = Int(num)!
let q = (n >= 7) ? n - 5 : n + 1
pq += p * q
}
// 検査
let remainder = pq % 11
return (remainder <= 1) ? (checkDigit == 0) : (checkDigit == (11 - remainder))
}
// 上記ソースの後に貼っても動くように便宜上"__"をつけておきます。
func __validateMyNumber(numstr: String) throws -> Bool {
let length = numstr.utf8.count
if length != 12 {
throw ValidationErrorType.WrongLength(length)
}
let exp = try! NSRegularExpression(pattern: "^[0-9]+$", options: [])
if exp.matchesInString(numstr, options: [], range: NSMakeRange(0, length)).count == 0 {
throw ValidationErrorType.NotANumber
}
var characters = numstr.characters.map{ String($0) }
let checkDigit = Int(characters.removeLast())!
var pq = 0
for (index, num) in characters.reverse().enumerate() {
let n = index + 1
let p = Int(num)!
let q = (n >= 7) ? n - 5 : n + 1
pq += p * q
}
let remainder = pq % 11
return (remainder <= 1) ? (checkDigit == 0) : (checkDigit == (11 - remainder))
}
func tryValidation(numstr: String) {
do {
let valid = try __validateMyNumber(numstr)
print("\(numstr) is",(valid ? "valid" : "invalid"))
} catch ValidationErrorType.WrongLength(let length) {
print("\(numstr) is wrong length: \(length)")
} catch ValidationErrorType.NotANumber {
print("\(numstr) is not a number")
} catch {
print("unknown error occurred")
}
}
tryValidation("123456789012") // => "123456789012 is invalid\n"
validateMyNumber("1234567890123") // => false
validateMyNumber("123456789010") // => false
validateMyNumber("A23456789010") // => false
validateMyNumber("123456789010") // => false
validateMyNumber("123456789011") // => false
validateMyNumber("123456789012") // => false
validateMyNumber("123456789013") // => false
validateMyNumber("123456789014") // => false
validateMyNumber("123456789015") // => false
validateMyNumber("123456789016") // => false
validateMyNumber("123456789017") // => false
validateMyNumber("123456789018") // => true
validateMyNumber("123456789019") // => false
validateMyNumber("023456789013") // => true
validateMyNumber2("1234567890123") // -> Failure(ValidationErrorType.WrongLength(13))
validateMyNumber2("123456789010") // -> Failure(ValidationErrorType.WrongLength(36))
validateMyNumber2("A23456789010") // => Failure(ValidationErrorType.NotANumber)
validateMyNumber2("123456789010") // => Failure(ValidationErrorType.InvalidNumber)
validateMyNumber2("123456789011") // => Failure(ValidationErrorType.InvalidNumber)
validateMyNumber2("123456789012") // => Failure(ValidationErrorType.InvalidNumber)
validateMyNumber2("123456789013") // => Failure(ValidationErrorType.InvalidNumber)
validateMyNumber2("123456789014") // => Failure(ValidationErrorType.InvalidNumber)
validateMyNumber2("123456789015") // => Failure(ValidationErrorType.InvalidNumber)
validateMyNumber2("123456789016") // => Failure(ValidationErrorType.InvalidNumber)
validateMyNumber2("123456789017") // => Failure(ValidationErrorType.InvalidNumber)
validateMyNumber2("123456789018") // => Success
validateMyNumber2("123456789019") // => Failure(ValidationErrorType.InvalidNumber)
validateMyNumber2("023456789013") // => Success
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment