Created
October 29, 2020 06:27
-
-
Save subdan/06d076e90de214226de8dd3162bd7c31 to your computer and use it in GitHub Desktop.
Phone number formatter
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Cocoa | |
extension String { | |
func charAt(at: Int) -> Character { | |
let charIndex = index(startIndex, offsetBy: at) | |
return self[charIndex] | |
} | |
} | |
protocol PhoneNumberFormattable { | |
/// Код страны. Например: "7", "1" или "373" | |
var countryCode: String { get } | |
/// Кол-во цифр в номере телефона, исключая код страны | |
var numberCount: Int { get } | |
/// Маска для форматирования номера телефона исключая код страны. Например "### ###-##-##" | |
var mask: String { get } | |
/// Форматирует номер телефона | |
func format(rawNumber: String) -> String? | |
} | |
struct RussiaPhoneFormatter: PhoneNumberFormattable { | |
let countryCode = "7" | |
var numberCount: Int = 10 | |
let mask: String = "### ###-##-##" | |
} | |
struct BelarusPhoneFormatter: PhoneNumberFormattable { | |
let countryCode = "375" | |
var numberCount: Int = 9 | |
let mask: String = "## ###-##-##" | |
} | |
struct MoldovaPhoneFormatter: PhoneNumberFormattable { | |
let countryCode = "373" | |
var numberCount: Int = 8 | |
let mask: String = "# ###-##-##" | |
} | |
struct KyrgyzstanPhoneFormatter: PhoneNumberFormattable { | |
let countryCode = "996" | |
var numberCount: Int = 9 | |
let mask: String = "## ###-##-##" | |
} | |
extension PhoneNumberFormattable { | |
var countryCodeCount: Int { countryCode.count } | |
var totalCount: Int { numberCount + countryCodeCount } | |
func format(rawNumber: String) -> String? { | |
let rawNumber = rawNumber.filter { $0.isNumber } | |
guard rawNumber.count == totalCount else { return nil } | |
guard rawNumber.prefix(countryCodeCount) == countryCode else { return nil } | |
// numbers without country code | |
let numbers = String(rawNumber.dropFirst(countryCodeCount)) | |
guard numbers.count == numberCount else { return nil } | |
var index = 0 | |
var result = "" | |
mask.forEach { element in | |
if element == "#" { | |
result.append(numbers.charAt(at: index)) | |
index += 1 | |
} else { | |
result.append(element) | |
} | |
} | |
return "+\(countryCode) \(result)" | |
} | |
} | |
func formatPhoneNumber(_ string: String) -> String? { | |
let formatters: [PhoneNumberFormattable] = [ | |
RussiaPhoneFormatter(), | |
BelarusPhoneFormatter(), | |
MoldovaPhoneFormatter(), | |
KyrgyzstanPhoneFormatter() | |
] | |
for formatter in formatters { | |
if let phone = formatter.format(rawNumber: string) { | |
return phone | |
} | |
} | |
return nil | |
} | |
print(formatPhoneNumber("71234567890") == "+7 123 456-78-90") // true | |
print(formatPhoneNumber("+996 12 345-67-89") == "+996 12 345-67-89") // true | |
print(formatPhoneNumber("+996123456789") == "+996 12 345-67-89") // true | |
print(formatPhoneNumber("37399999999") == "+373 9 999-99-99") // true |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment