Skip to content

Instantly share code, notes, and snippets.

@seanghay
Created December 9, 2020 08:34
Show Gist options
  • Select an option

  • Save seanghay/5686073caac91ff2e9ad1b4b9cab5f54 to your computer and use it in GitHub Desktop.

Select an option

Save seanghay/5686073caac91ff2e9ad1b4b9cab5f54 to your computer and use it in GitHub Desktop.
Format KH Phone Number
import androidx.annotation.VisibleForTesting
object PhoneNumberSanitizer {
@VisibleForTesting
internal const val COUNTRY_CODE = "+855"
const val FORMAT_COUNTRY_CODE = 1
const val FORMAT_NO_COUNTRY_CODE = 2
const val FORMAT_COUNTRY_CODE_NO_BRACES = 3
@Throws(IllegalStateException::class)
fun parse(value: String): PhoneNumber {
return PhoneNumber(parseString(value))
}
fun parseOrNull(value: String): PhoneNumber? {
return runCatching { parse(value) }.getOrNull()
}
private fun parseString(value: String): String {
val trimmedValue = value.trim().removeCharacters()
check(trimmedValue.isNotBlank()) { "value is blank or invalid" }
if (trimmedValue.startsWith("+")) {
if (trimmedValue.startsWith(COUNTRY_CODE)) return trimmedValue
else throw IllegalStateException("Other country code is not supported")
}
if (trimmedValue.startsWith("0")) return COUNTRY_CODE + trimmedValue.substring(1, trimmedValue.length)
return COUNTRY_CODE + trimmedValue
}
private fun String.removeCharacters(): String {
return replace("-", "")
.replace("[\\s\\-()a-zA-Z]*".toRegex(), "")
}
data class PhoneNumber(val value: String) {
val countryCode: String = value.substring(0, 4)
val phoneNumber: String = value.substring(4, value.length)
val phoneNumberWithZero: String = "0$phoneNumber"
val fullPhoneNumberWithoutPlusPrefix: String = value.substring(1, value.length)
init {
check(value.startsWith(COUNTRY_CODE))
check(value.length >= 12)
}
fun format(mode: Int): String {
return when (mode) {
FORMAT_COUNTRY_CODE -> "($COUNTRY_CODE) " + phoneNumber.formatNumber()
FORMAT_COUNTRY_CODE_NO_BRACES -> "$COUNTRY_CODE " + phoneNumber.formatNumber()
FORMAT_NO_COUNTRY_CODE -> phoneNumberWithZero.formatNumberWithoutCountryCode()
else -> throw IllegalArgumentException("mode is invalid")
}
}
private fun String.formatNumberWithoutCountryCode(): String {
if (length <= 4) return this
return substring(0, 3) + " " + substring(2, 5) + " " + substring(5, length)
}
private fun String.formatNumber(): String {
if (length <= 4) return this
return substring(0, 2) + " " + substring(2, 5) + " " + substring(5, length)
}
}
}
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNull
import org.junit.Test
import kotlin.jvm.Throws
class PhoneNumberSanitizerTest {
@Test
fun `COUNTRY_CODE should be +855`() {
assertEquals("+855", PhoneNumberSanitizer.COUNTRY_CODE)
}
@Test
fun `(phoneNumber with zero) should return a phone number object`() {
val value = "0964433112"
val result = PhoneNumberSanitizer.parse(value)
assertEquals("+855964433112", result.value)
assertEquals("855964433112", result.fullPhoneNumberWithoutPlusPrefix)
assertEquals("964433112", result.phoneNumber)
assertEquals("0964433112", result.phoneNumberWithZero)
assertEquals("+855", result.countryCode)
}
@Test
fun `(phoneNumber without zero) should return a phone number object`() {
val value = "964433112"
val result = PhoneNumberSanitizer.parse(value)
assertEquals("+855964433112", result.value)
assertEquals("0964433112", result.phoneNumberWithZero)
assertEquals("964433112", result.phoneNumber)
assertEquals("855964433112", result.fullPhoneNumberWithoutPlusPrefix)
assertEquals("+855", result.countryCode)
}
@Test
fun `(phoneNumber without countrycode) should return a phone number object`() {
val value = "+855964433112"
val result = PhoneNumberSanitizer.parse(value)
assertEquals("+855964433112", result.value)
assertEquals("0964433112", result.phoneNumberWithZero)
assertEquals("964433112", result.phoneNumber)
assertEquals("855964433112", result.fullPhoneNumberWithoutPlusPrefix)
assertEquals("+855", result.countryCode)
}
@Test
fun `should remove - chars from number`() {
val value = "+855-9644-33112"
val result = PhoneNumberSanitizer.parse(value)
assertEquals("+855964433112", result.value)
assertEquals("0964433112", result.phoneNumberWithZero)
assertEquals("964433112", result.phoneNumber)
assertEquals("+855", result.countryCode)
assertEquals("855964433112", result.fullPhoneNumberWithoutPlusPrefix)
}
@Test
fun `should remove whitespaces and chars from number`() {
val value = "+(855)-964 433 11"
val result = PhoneNumberSanitizer.parse(value)
assertEquals("+85596443311", result.value)
assertEquals("096443311", result.phoneNumberWithZero)
assertEquals("96443311", result.phoneNumber)
assertEquals("+855", result.countryCode)
assertEquals("85596443311", result.fullPhoneNumberWithoutPlusPrefix)
}
@Test(expected = IllegalStateException::class)
fun `should throw when invalid`() {
val invalidValue = "9134"
PhoneNumberSanitizer.parse(invalidValue)
}
@Test(expected = IllegalStateException::class)
fun `should throw when invalid when input other country`() {
val invalidValue = "+123485712398"
PhoneNumberSanitizer.parse(invalidValue)
}
@Test(expected = IllegalStateException::class)
fun `should throw when invalid when emptry`() {
val invalidValue = ""
PhoneNumberSanitizer.parse(invalidValue)
}
@Test
fun `should return null when invalid`() {
val invalidInput = "akjsdkjasd"
assertNull(PhoneNumberSanitizer.parseOrNull(invalidInput))
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment