Swift:如何验证社会安全号码(SSN)?

时间:2018-03-22 18:59:09

标签: ios swift regex

如何使用Swift验证String是否使用类似123-45-6789的模式编码有效的美国社会安全号码(SSN)?

验证意味着检查给定字符串是否与模式123-45-6789匹配。

2 个答案:

答案 0 :(得分:4)

<强>简单地:

步骤1。创建一个方法:

func isValidSsn(_ ssn: String) -> Bool {
  let ssnRegext = "^(?!(000|666|9))\\d{3}-(?!00)\\d{2}-(?!0000)\\d{4}$"
  return ssn.range(of: ssnRegext, options: .regularExpression, range: nil, locale: nil) != nil
}

第二步。使用它:

let ssn = "123-45-6789"
validateSsn(ssn) // true

希望它有所帮助!

答案 1 :(得分:0)

最好为此使用自定义类型。它有一个可用的初始值设定项,可用于从String初始化它。一旦你有一个非零的SSN实例,你知道它是一个有效的SSN,你永远不需要再次检查。

我正在将SSN解析为UInt32,并在必要时将其序列化为字符串。这可以防止与分配和传递字符串相关的ARC和堆存储开销。这是实施:

import Foundation

struct SSN {
    // Stores aaa-bb-ccc as aaabbbccc
    let ssn: UInt32

    init?(_ string: String) {
        let segments = string.split(separator: "-")

        guard segments.lazy.map({ $0.count }) == [3, 2, 3] else {
            debugPrint("SSN segments must be lenght 3, 2, 3 (e.g. 123-45-678).")
            return nil
        }


        guard !zip(segments, ["000", "00", "000"]).contains(where: {$0.0 == $0.1}) else {
            debugPrint("SSN segments cannot be all zeros.")
            return nil
        }

        let firstSegment = segments[0]
        guard firstSegment != "666", !firstSegment.hasPrefix("9") else {
            debugPrint("The first SSN segment (\(firstSegment)) cannot be 666, or be in the range 900-999.")
            return nil
        }
        let dashesRemoved = string.replacingOccurrences(of: "-", with: "")

        self.ssn = UInt32(dashesRemoved)!
    }
}

extension SSN: ExpressibleByStringLiteral {
    init(stringLiteral literalString: String) {
        self.init(literalString)!
    }
}

extension SSN: CustomStringConvertible {
    var description: String {
        let formatter = NumberFormatter()

        formatter.minimumIntegerDigits = 3
        let segment1 = formatter.string(from: NSNumber(value: self.ssn / 100000))!


        formatter.minimumIntegerDigits = 2
        let segment2 = formatter.string(from: NSNumber(value: (self.ssn / 1000) % 100))!

        formatter.minimumIntegerDigits = 3
        let segment3 = formatter.string(from: NSNumber(value: self.ssn % 1000))!
        return "\(segment1)-\(segment2)-\(segment3)"
    }
}

还有一些测试:

let testSSNString = "123-45-678"
let optionalTestSSN = SSN(testSSNString)

guard let testSSN = optionalTestSSN else {
    assertionFailure("Valid SSN (\(testSSNString)) wasn't successfully parsed.")
    fatalError()
}

assert(testSSN.description == testSSNString, "SSN (\(testSSN)) was not correctly converted back to String.")

func assertSSNShouldBeNil(_ string: String, because reason: String) {
    assert(SSN(string) == nil, reason + " should be nil.")
}


assertSSNShouldBeNil("123-45-678-9",    because: "SSN with too many segment")
assertSSNShouldBeNil("123-45",          because: "SSN with too few segments")
assertSSNShouldBeNil("",                because: "Empty SSN")


assertSSNShouldBeNil("000-12-345",      because: "SSN with all-zero segment 1")
assertSSNShouldBeNil("123-00-456",      because: "SSN with all-zero segment 2")
assertSSNShouldBeNil("123-45-000",      because: "SSN with all-zero segment 3")

assertSSNShouldBeNil("666-12-345",      because: "SSN starting with 666")
assertSSNShouldBeNil("900-12-345",      because: "SSN starting with number in range 900-999")
assertSSNShouldBeNil("999-12-345",      because: "SSN starting with number in range 900-999")