diff --git a/mvvmhabit/src/main/java/me/goldze/mvvmhabit/utils/RegexUtils.java b/mvvmhabit/src/main/java/me/goldze/mvvmhabit/utils/RegexUtils.java index 1da5ac6a..c6f0e3eb 100644 --- a/mvvmhabit/src/main/java/me/goldze/mvvmhabit/utils/RegexUtils.java +++ b/mvvmhabit/src/main/java/me/goldze/mvvmhabit/utils/RegexUtils.java @@ -1,6 +1,9 @@ package me.goldze.mvvmhabit.utils; +import android.support.v4.util.SimpleArrayMap; + import java.util.ArrayList; +import java.util.Collections; import java.util.List; import java.util.regex.Matcher; import java.util.regex.Pattern; @@ -13,6 +16,8 @@ */ public final class RegexUtils { + private final static SimpleArrayMap CITY_MAP = new SimpleArrayMap<>(); + private RegexUtils() { throw new UnsupportedOperationException("u can't instantiate me..."); } @@ -22,136 +27,231 @@ private RegexUtils() { /////////////////////////////////////////////////////////////////////////// /** - * 验证手机号(简单) + * Return whether input matches regex of simple mobile. * - * @param input 待验证文本 - * @return {@code true}: 匹配
{@code false}: 不匹配 + * @param input The input. + * @return {@code true}: yes
{@code false}: no */ public static boolean isMobileSimple(final CharSequence input) { return isMatch(RegexConstants.REGEX_MOBILE_SIMPLE, input); } /** - * 验证手机号(精确) + * Return whether input matches regex of exact mobile. * - * @param input 待验证文本 - * @return {@code true}: 匹配
{@code false}: 不匹配 + * @param input The input. + * @return {@code true}: yes
{@code false}: no */ public static boolean isMobileExact(final CharSequence input) { - return isMatch(RegexConstants.REGEX_MOBILE_EXACT, input); + return isMobileExact(input, null); } /** - * 验证电话号码 + * Return whether input matches regex of exact mobile. * - * @param input 待验证文本 - * @return {@code true}: 匹配
{@code false}: 不匹配 + * @param input The input. + * @param newSegments The new segments of mobile number. + * @return {@code true}: yes
{@code false}: no + */ + public static boolean isMobileExact(final CharSequence input, List newSegments) { + boolean match = isMatch(RegexConstants.REGEX_MOBILE_EXACT, input); + if (match) return true; + if (newSegments == null) return false; + if (input == null || input.length() != 11) return false; + String content = input.toString(); + for (char c : content.toCharArray()) { + if (!Character.isDigit(c)) { + return false; + } + } + for (String newSegment : newSegments) { + if (content.startsWith(newSegment)) { + return true; + } + } + return false; + } + + /** + * Return whether input matches regex of telephone number. + * + * @param input The input. + * @return {@code true}: yes
{@code false}: no */ public static boolean isTel(final CharSequence input) { return isMatch(RegexConstants.REGEX_TEL, input); } /** - * 验证身份证号码15位 + * Return whether input matches regex of id card number which length is 15. * - * @param input 待验证文本 - * @return {@code true}: 匹配
{@code false}: 不匹配 + * @param input The input. + * @return {@code true}: yes
{@code false}: no */ public static boolean isIDCard15(final CharSequence input) { return isMatch(RegexConstants.REGEX_ID_CARD15, input); } /** - * 验证身份证号码18位 + * Return whether input matches regex of id card number which length is 18. * - * @param input 待验证文本 - * @return {@code true}: 匹配
{@code false}: 不匹配 + * @param input The input. + * @return {@code true}: yes
{@code false}: no */ public static boolean isIDCard18(final CharSequence input) { return isMatch(RegexConstants.REGEX_ID_CARD18, input); } /** - * 验证邮箱 + * Return whether input matches regex of exact id card number which length is 18. + * + * @param input The input. + * @return {@code true}: yes
{@code false}: no + */ + public static boolean isIDCard18Exact(final CharSequence input) { + if (isIDCard18(input)) { + int[] factor = new int[]{7, 9, 10, 5, 8, 4, 2, 1, 6, 3, 7, 9, 10, 5, 8, 4, 2}; + char[] suffix = new char[]{'1', '0', 'X', '9', '8', '7', '6', '5', '4', '3', '2'}; + if (CITY_MAP.isEmpty()) { + CITY_MAP.put("11", "北京"); + CITY_MAP.put("12", "天津"); + CITY_MAP.put("13", "河北"); + CITY_MAP.put("14", "山西"); + CITY_MAP.put("15", "内蒙古"); + + CITY_MAP.put("21", "辽宁"); + CITY_MAP.put("22", "吉林"); + CITY_MAP.put("23", "黑龙江"); + + CITY_MAP.put("31", "上海"); + CITY_MAP.put("32", "江苏"); + CITY_MAP.put("33", "浙江"); + CITY_MAP.put("34", "安徽"); + CITY_MAP.put("35", "福建"); + CITY_MAP.put("36", "江西"); + CITY_MAP.put("37", "山东"); + + CITY_MAP.put("41", "河南"); + CITY_MAP.put("42", "湖北"); + CITY_MAP.put("43", "湖南"); + CITY_MAP.put("44", "广东"); + CITY_MAP.put("45", "广西"); + CITY_MAP.put("46", "海南"); + + CITY_MAP.put("50", "重庆"); + CITY_MAP.put("51", "四川"); + CITY_MAP.put("52", "贵州"); + CITY_MAP.put("53", "云南"); + CITY_MAP.put("54", "西藏"); + + CITY_MAP.put("61", "陕西"); + CITY_MAP.put("62", "甘肃"); + CITY_MAP.put("63", "青海"); + CITY_MAP.put("64", "宁夏"); + CITY_MAP.put("65", "新疆"); + + CITY_MAP.put("71", "台湾老"); + CITY_MAP.put("81", "香港"); + CITY_MAP.put("82", "澳门"); + CITY_MAP.put("83", "台湾新"); + CITY_MAP.put("91", "国外"); + } + if (CITY_MAP.get(input.subSequence(0, 2).toString()) != null) { + int weightSum = 0; + for (int i = 0; i < 17; ++i) { + weightSum += (input.charAt(i) - '0') * factor[i]; + } + int idCardMod = weightSum % 11; + char idCardLast = input.charAt(17); + return idCardLast == suffix[idCardMod]; + } + } + return false; + } + + /** + * Return whether input matches regex of email. * - * @param input 待验证文本 - * @return {@code true}: 匹配
{@code false}: 不匹配 + * @param input The input. + * @return {@code true}: yes
{@code false}: no */ public static boolean isEmail(final CharSequence input) { return isMatch(RegexConstants.REGEX_EMAIL, input); } /** - * 验证URL + * Return whether input matches regex of url. * - * @param input 待验证文本 - * @return {@code true}: 匹配
{@code false}: 不匹配 + * @param input The input. + * @return {@code true}: yes
{@code false}: no */ public static boolean isURL(final CharSequence input) { return isMatch(RegexConstants.REGEX_URL, input); } /** - * 验证汉字 + * Return whether input matches regex of Chinese character. * - * @param input 待验证文本 - * @return {@code true}: 匹配
{@code false}: 不匹配 + * @param input The input. + * @return {@code true}: yes
{@code false}: no */ public static boolean isZh(final CharSequence input) { return isMatch(RegexConstants.REGEX_ZH, input); } /** - * 验证用户名 - *

取值范围为a-z,A-Z,0-9,"_",汉字,不能以"_"结尾,用户名必须是6-20位

+ * Return whether input matches regex of username. + *

scope for "a-z", "A-Z", "0-9", "_", "Chinese character"

+ *

can't end with "_"

+ *

length is between 6 to 20

. * - * @param input 待验证文本 - * @return {@code true}: 匹配
{@code false}: 不匹配 + * @param input The input. + * @return {@code true}: yes
{@code false}: no */ public static boolean isUsername(final CharSequence input) { return isMatch(RegexConstants.REGEX_USERNAME, input); } /** - * 验证yyyy-MM-dd格式的日期校验,已考虑平闰年 + * Return whether input matches regex of date which pattern is "yyyy-MM-dd". * - * @param input 待验证文本 - * @return {@code true}: 匹配
{@code false}: 不匹配 + * @param input The input. + * @return {@code true}: yes
{@code false}: no */ public static boolean isDate(final CharSequence input) { return isMatch(RegexConstants.REGEX_DATE, input); } /** - * 验证IP地址 + * Return whether input matches regex of ip address. * - * @param input 待验证文本 - * @return {@code true}: 匹配
{@code false}: 不匹配 + * @param input The input. + * @return {@code true}: yes
{@code false}: no */ public static boolean isIP(final CharSequence input) { return isMatch(RegexConstants.REGEX_IP, input); } /** - * 判断是否匹配正则 + * Return whether input matches the regex. * - * @param regex 正则表达式 - * @param input 要匹配的字符串 - * @return {@code true}: 匹配
{@code false}: 不匹配 + * @param regex The regex. + * @param input The input. + * @return {@code true}: yes
{@code false}: no */ public static boolean isMatch(final String regex, final CharSequence input) { return input != null && input.length() > 0 && Pattern.matches(regex, input); } /** - * 获取正则匹配的部分 + * Return the list of input matches the regex. * - * @param regex 正则表达式 - * @param input 要匹配的字符串 - * @return 正则匹配的部分 + * @param regex The regex. + * @param input The input. + * @return the list of input matches the regex */ public static List getMatches(final String regex, final CharSequence input) { - if (input == null) return null; + if (input == null) return Collections.emptyList(); List matches = new ArrayList<>(); Pattern pattern = Pattern.compile(regex); Matcher matcher = pattern.matcher(input); @@ -162,40 +262,50 @@ public static List getMatches(final String regex, final CharSequence inp } /** - * 获取正则匹配分组 + * Splits input around matches of the regex. * - * @param input 要分组的字符串 - * @param regex 正则表达式 - * @return 正则匹配分组 + * @param input The input. + * @param regex The regex. + * @return the array of strings computed by splitting input around matches of regex */ public static String[] getSplits(final String input, final String regex) { - if (input == null) return null; + if (input == null) return new String[0]; return input.split(regex); } /** - * 替换正则匹配的第一部分 + * Replace the first subsequence of the input sequence that matches the + * regex with the given replacement string. * - * @param input 要替换的字符串 - * @param regex 正则表达式 - * @param replacement 代替者 - * @return 替换正则匹配的第一部分 + * @param input The input. + * @param regex The regex. + * @param replacement The replacement string. + * @return the string constructed by replacing the first matching + * subsequence by the replacement string, substituting captured + * subsequences as needed */ - public static String getReplaceFirst(final String input, final String regex, final String replacement) { - if (input == null) return null; + public static String getReplaceFirst(final String input, + final String regex, + final String replacement) { + if (input == null) return ""; return Pattern.compile(regex).matcher(input).replaceFirst(replacement); } /** - * 替换所有正则匹配的部分 + * Replace every subsequence of the input sequence that matches the + * pattern with the given replacement string. * - * @param input 要替换的字符串 - * @param regex 正则表达式 - * @param replacement 代替者 - * @return 替换所有正则匹配的部分 + * @param input The input. + * @param regex The regex. + * @param replacement The replacement string. + * @return the string constructed by replacing each matching subsequence + * by the replacement string, substituting captured subsequences + * as needed */ - public static String getReplaceAll(final String input, final String regex, final String replacement) { - if (input == null) return null; + public static String getReplaceAll(final String input, + final String regex, + final String replacement) { + if (input == null) return ""; return Pattern.compile(regex).matcher(input).replaceAll(replacement); } }