|  |  |  | @ -0,0 +1,255 @@ | 
			
		
	
		
			
				
					|  |  |  |  | package io.legado.app.utils | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | import android.annotation.SuppressLint | 
			
		
	
		
			
				
					|  |  |  |  | import android.text.TextUtils | 
			
		
	
		
			
				
					|  |  |  |  | import android.text.TextUtils.isEmpty | 
			
		
	
		
			
				
					|  |  |  |  | import java.text.ParseException | 
			
		
	
		
			
				
					|  |  |  |  | import java.text.SimpleDateFormat | 
			
		
	
		
			
				
					|  |  |  |  | import java.util.* | 
			
		
	
		
			
				
					|  |  |  |  | import java.util.regex.Matcher | 
			
		
	
		
			
				
					|  |  |  |  | import java.util.regex.Pattern | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  | object StringUtils { | 
			
		
	
		
			
				
					|  |  |  |  |     private val TAG = "StringUtils" | 
			
		
	
		
			
				
					|  |  |  |  |     private const val HOUR_OF_DAY = 24 | 
			
		
	
		
			
				
					|  |  |  |  |     private const val DAY_OF_YESTERDAY = 2 | 
			
		
	
		
			
				
					|  |  |  |  |     private const val TIME_UNIT = 60 | 
			
		
	
		
			
				
					|  |  |  |  |     private val ChnMap = chnMap | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     private val chnMap: HashMap<Char, Int> | 
			
		
	
		
			
				
					|  |  |  |  |         get() { | 
			
		
	
		
			
				
					|  |  |  |  |             val map = HashMap<Char, Int>() | 
			
		
	
		
			
				
					|  |  |  |  |             var cnStr = "零一二三四五六七八九十" | 
			
		
	
		
			
				
					|  |  |  |  |             var c = cnStr.toCharArray() | 
			
		
	
		
			
				
					|  |  |  |  |             for (i in 0..10) { | 
			
		
	
		
			
				
					|  |  |  |  |                 map[c[i]] = i | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             cnStr = "〇壹贰叁肆伍陆柒捌玖拾" | 
			
		
	
		
			
				
					|  |  |  |  |             c = cnStr.toCharArray() | 
			
		
	
		
			
				
					|  |  |  |  |             for (i in 0..10) { | 
			
		
	
		
			
				
					|  |  |  |  |                 map[c[i]] = i | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             map['两'] = 2 | 
			
		
	
		
			
				
					|  |  |  |  |             map['百'] = 100 | 
			
		
	
		
			
				
					|  |  |  |  |             map['佰'] = 100 | 
			
		
	
		
			
				
					|  |  |  |  |             map['千'] = 1000 | 
			
		
	
		
			
				
					|  |  |  |  |             map['仟'] = 1000 | 
			
		
	
		
			
				
					|  |  |  |  |             map['万'] = 10000 | 
			
		
	
		
			
				
					|  |  |  |  |             map['亿'] = 100000000 | 
			
		
	
		
			
				
					|  |  |  |  |             return map | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     //将时间转换成日期 | 
			
		
	
		
			
				
					|  |  |  |  |     fun dateConvert(time: Long, pattern: String): String { | 
			
		
	
		
			
				
					|  |  |  |  |         val date = Date(time) | 
			
		
	
		
			
				
					|  |  |  |  |         @SuppressLint("SimpleDateFormat") val format = SimpleDateFormat(pattern) | 
			
		
	
		
			
				
					|  |  |  |  |         return format.format(date) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     //将日期转换成昨天、今天、明天 | 
			
		
	
		
			
				
					|  |  |  |  |     fun dateConvert(source: String, pattern: String): String { | 
			
		
	
		
			
				
					|  |  |  |  |         @SuppressLint("SimpleDateFormat") val format = SimpleDateFormat(pattern) | 
			
		
	
		
			
				
					|  |  |  |  |         val calendar = Calendar.getInstance() | 
			
		
	
		
			
				
					|  |  |  |  |         try { | 
			
		
	
		
			
				
					|  |  |  |  |             val date = format.parse(source) | 
			
		
	
		
			
				
					|  |  |  |  |             val curTime = calendar.timeInMillis | 
			
		
	
		
			
				
					|  |  |  |  |             calendar.time = date | 
			
		
	
		
			
				
					|  |  |  |  |             //将MISC 转换成 sec | 
			
		
	
		
			
				
					|  |  |  |  |             val difSec = Math.abs((curTime - date.time) / 1000) | 
			
		
	
		
			
				
					|  |  |  |  |             val difMin = difSec / 60 | 
			
		
	
		
			
				
					|  |  |  |  |             val difHour = difMin / 60 | 
			
		
	
		
			
				
					|  |  |  |  |             val difDate = difHour / 60 | 
			
		
	
		
			
				
					|  |  |  |  |             val oldHour = calendar.get(Calendar.HOUR) | 
			
		
	
		
			
				
					|  |  |  |  |             //如果没有时间 | 
			
		
	
		
			
				
					|  |  |  |  |             if (oldHour == 0) { | 
			
		
	
		
			
				
					|  |  |  |  |                 //比日期:昨天今天和明天 | 
			
		
	
		
			
				
					|  |  |  |  |                 if (difDate == 0L) { | 
			
		
	
		
			
				
					|  |  |  |  |                     return "今天" | 
			
		
	
		
			
				
					|  |  |  |  |                 } else if (difDate < DAY_OF_YESTERDAY) { | 
			
		
	
		
			
				
					|  |  |  |  |                     return "昨天" | 
			
		
	
		
			
				
					|  |  |  |  |                 } else { | 
			
		
	
		
			
				
					|  |  |  |  |                     @SuppressLint("SimpleDateFormat") val convertFormat = SimpleDateFormat("yyyy-MM-dd") | 
			
		
	
		
			
				
					|  |  |  |  |                     return convertFormat.format(date) | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             return when { | 
			
		
	
		
			
				
					|  |  |  |  |                 difSec < TIME_UNIT -> difSec.toString() + "秒前" | 
			
		
	
		
			
				
					|  |  |  |  |                 difMin < TIME_UNIT -> difMin.toString() + "分钟前" | 
			
		
	
		
			
				
					|  |  |  |  |                 difHour < HOUR_OF_DAY -> difHour.toString() + "小时前" | 
			
		
	
		
			
				
					|  |  |  |  |                 difDate < DAY_OF_YESTERDAY -> "昨天" | 
			
		
	
		
			
				
					|  |  |  |  |                 else -> { | 
			
		
	
		
			
				
					|  |  |  |  |                     @SuppressLint("SimpleDateFormat") val convertFormat = SimpleDateFormat("yyyy-MM-dd") | 
			
		
	
		
			
				
					|  |  |  |  |                     convertFormat.format(date) | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |         } catch (e: ParseException) { | 
			
		
	
		
			
				
					|  |  |  |  |             e.printStackTrace() | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         return "" | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     @SuppressLint("DefaultLocale") | 
			
		
	
		
			
				
					|  |  |  |  |     fun toFirstCapital(str: String): String { | 
			
		
	
		
			
				
					|  |  |  |  |         return str.substring(0, 1).toUpperCase() + str.substring(1) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     /** | 
			
		
	
		
			
				
					|  |  |  |  |      * 将文本中的半角字符,转换成全角字符 | 
			
		
	
		
			
				
					|  |  |  |  |      */ | 
			
		
	
		
			
				
					|  |  |  |  |     fun halfToFull(input: String): String { | 
			
		
	
		
			
				
					|  |  |  |  |         val c = input.toCharArray() | 
			
		
	
		
			
				
					|  |  |  |  |         for (i in c.indices) { | 
			
		
	
		
			
				
					|  |  |  |  |             if (c[i].toInt() == 32) | 
			
		
	
		
			
				
					|  |  |  |  |             //半角空格 | 
			
		
	
		
			
				
					|  |  |  |  |             { | 
			
		
	
		
			
				
					|  |  |  |  |                 c[i] = 12288.toChar() | 
			
		
	
		
			
				
					|  |  |  |  |                 continue | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             //根据实际情况,过滤不需要转换的符号 | 
			
		
	
		
			
				
					|  |  |  |  |             //if (c[i] == 46) //半角点号,不转换 | 
			
		
	
		
			
				
					|  |  |  |  |             // continue; | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             if (c[i].toInt() in 33..126) | 
			
		
	
		
			
				
					|  |  |  |  |             //其他符号都转换为全角 | 
			
		
	
		
			
				
					|  |  |  |  |                 c[i] = (c[i].toInt() + 65248).toChar() | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         return String(c) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     //功能:字符串全角转换为半角 | 
			
		
	
		
			
				
					|  |  |  |  |     fun fullToHalf(input: String): String { | 
			
		
	
		
			
				
					|  |  |  |  |         val c = input.toCharArray() | 
			
		
	
		
			
				
					|  |  |  |  |         for (i in c.indices) { | 
			
		
	
		
			
				
					|  |  |  |  |             if (c[i].toInt() == 12288) | 
			
		
	
		
			
				
					|  |  |  |  |             //全角空格 | 
			
		
	
		
			
				
					|  |  |  |  |             { | 
			
		
	
		
			
				
					|  |  |  |  |                 c[i] = 32.toChar() | 
			
		
	
		
			
				
					|  |  |  |  |                 continue | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |             if (c[i].toInt() in 65281..65374) | 
			
		
	
		
			
				
					|  |  |  |  |                 c[i] = (c[i].toInt() - 65248).toChar() | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         return String(c) | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     fun chineseNumToInt(chNum: String): Int { | 
			
		
	
		
			
				
					|  |  |  |  |         var result = 0 | 
			
		
	
		
			
				
					|  |  |  |  |         var tmp = 0 | 
			
		
	
		
			
				
					|  |  |  |  |         var billion = 0 | 
			
		
	
		
			
				
					|  |  |  |  |         val cn = chNum.toCharArray() | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         // "一零二五" 形式 | 
			
		
	
		
			
				
					|  |  |  |  |         if (cn.size > 1 && chNum.matches("^[〇零一二三四五六七八九壹贰叁肆伍陆柒捌玖]$".toRegex())) { | 
			
		
	
		
			
				
					|  |  |  |  |             for (i in cn.indices) { | 
			
		
	
		
			
				
					|  |  |  |  |                 cn[i] = (48 + ChnMap[cn[i]]!!).toChar() | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             return Integer.parseInt(String(cn)) | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         // "一千零二十五", "一千二" 形式 | 
			
		
	
		
			
				
					|  |  |  |  |         try { | 
			
		
	
		
			
				
					|  |  |  |  |             for (i in cn.indices) { | 
			
		
	
		
			
				
					|  |  |  |  |                 val tmpNum = ChnMap[cn[i]]!! | 
			
		
	
		
			
				
					|  |  |  |  |                 if (tmpNum == 100000000) { | 
			
		
	
		
			
				
					|  |  |  |  |                     result += tmp | 
			
		
	
		
			
				
					|  |  |  |  |                     result *= tmpNum | 
			
		
	
		
			
				
					|  |  |  |  |                     billion = billion * 100000000 + result | 
			
		
	
		
			
				
					|  |  |  |  |                     result = 0 | 
			
		
	
		
			
				
					|  |  |  |  |                     tmp = 0 | 
			
		
	
		
			
				
					|  |  |  |  |                 } else if (tmpNum == 10000) { | 
			
		
	
		
			
				
					|  |  |  |  |                     result += tmp | 
			
		
	
		
			
				
					|  |  |  |  |                     result *= tmpNum | 
			
		
	
		
			
				
					|  |  |  |  |                     tmp = 0 | 
			
		
	
		
			
				
					|  |  |  |  |                 } else if (tmpNum >= 10) { | 
			
		
	
		
			
				
					|  |  |  |  |                     if (tmp == 0) | 
			
		
	
		
			
				
					|  |  |  |  |                         tmp = 1 | 
			
		
	
		
			
				
					|  |  |  |  |                     result += tmpNum * tmp | 
			
		
	
		
			
				
					|  |  |  |  |                     tmp = 0 | 
			
		
	
		
			
				
					|  |  |  |  |                 } else { | 
			
		
	
		
			
				
					|  |  |  |  |                     tmp = if (i >= 2 && i == cn.size - 1 && ChnMap[cn[i - 1]]!! > 10) | 
			
		
	
		
			
				
					|  |  |  |  |                         tmpNum * ChnMap[cn[i - 1]]!! / 10 | 
			
		
	
		
			
				
					|  |  |  |  |                     else | 
			
		
	
		
			
				
					|  |  |  |  |                         tmp * 10 + tmpNum | 
			
		
	
		
			
				
					|  |  |  |  |                 } | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  |             result += tmp + billion | 
			
		
	
		
			
				
					|  |  |  |  |             return result | 
			
		
	
		
			
				
					|  |  |  |  |         } catch (e: Exception) { | 
			
		
	
		
			
				
					|  |  |  |  |             return -1 | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     fun stringToInt(str: String?): Int { | 
			
		
	
		
			
				
					|  |  |  |  |         if (str != null) { | 
			
		
	
		
			
				
					|  |  |  |  |             val num = fullToHalf(str).replace("\\s".toRegex(), "") | 
			
		
	
		
			
				
					|  |  |  |  |             return try { | 
			
		
	
		
			
				
					|  |  |  |  |                 Integer.parseInt(num) | 
			
		
	
		
			
				
					|  |  |  |  |             } catch (e: Exception) { | 
			
		
	
		
			
				
					|  |  |  |  |                 chineseNumToInt(num) | 
			
		
	
		
			
				
					|  |  |  |  |             } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         return -1 | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     fun isContainNumber(company: String): Boolean { | 
			
		
	
		
			
				
					|  |  |  |  |         val p = Pattern.compile("[0-9]") | 
			
		
	
		
			
				
					|  |  |  |  |         val m = p.matcher(company) | 
			
		
	
		
			
				
					|  |  |  |  |         return m.find() | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     fun isNumeric(str: String): Boolean { | 
			
		
	
		
			
				
					|  |  |  |  |         val pattern = Pattern.compile("[0-9]*") | 
			
		
	
		
			
				
					|  |  |  |  |         val isNum = pattern.matcher(str) | 
			
		
	
		
			
				
					|  |  |  |  |         return isNum.matches() | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     // 移除字符串首尾空字符的高效方法(利用ASCII值判断,包括全角空格) | 
			
		
	
		
			
				
					|  |  |  |  |     fun trim(s: String): String { | 
			
		
	
		
			
				
					|  |  |  |  |         if (isEmpty(s)) return "" | 
			
		
	
		
			
				
					|  |  |  |  |         var start = 0 | 
			
		
	
		
			
				
					|  |  |  |  |         val len = s.length | 
			
		
	
		
			
				
					|  |  |  |  |         var end = len - 1 | 
			
		
	
		
			
				
					|  |  |  |  |         while (start < end && (s[start].toInt() <= 0x20 || s[start] == ' ')) { | 
			
		
	
		
			
				
					|  |  |  |  |             ++start | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         while (start < end && (s[end].toInt() <= 0x20 || s[end] == ' ')) { | 
			
		
	
		
			
				
					|  |  |  |  |             --end | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         if (end < len) ++end | 
			
		
	
		
			
				
					|  |  |  |  |         return if (start > 0 || end < len) s.substring(start, end) else s | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     fun repeat(str: String, n: Int): String { | 
			
		
	
		
			
				
					|  |  |  |  |         val stringBuilder = StringBuilder() | 
			
		
	
		
			
				
					|  |  |  |  |         for (i in 0 until n) { | 
			
		
	
		
			
				
					|  |  |  |  |             stringBuilder.append(str) | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         return stringBuilder.toString() | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     fun removeUTFCharacters(data: String?): String? { | 
			
		
	
		
			
				
					|  |  |  |  |         if (data == null) return null | 
			
		
	
		
			
				
					|  |  |  |  |         val p = Pattern.compile("\\\\u(\\p{XDigit}{4})") | 
			
		
	
		
			
				
					|  |  |  |  |         val m = p.matcher(data) | 
			
		
	
		
			
				
					|  |  |  |  |         val buf = StringBuffer(data.length) | 
			
		
	
		
			
				
					|  |  |  |  |         while (m.find()) { | 
			
		
	
		
			
				
					|  |  |  |  |             val ch = Integer.parseInt(m.group(1), 16).toChar().toString() | 
			
		
	
		
			
				
					|  |  |  |  |             m.appendReplacement(buf, Matcher.quoteReplacement(ch)) | 
			
		
	
		
			
				
					|  |  |  |  |         } | 
			
		
	
		
			
				
					|  |  |  |  |         m.appendTail(buf) | 
			
		
	
		
			
				
					|  |  |  |  |         return buf.toString() | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | 
 | 
			
		
	
		
			
				
					|  |  |  |  |     fun formatHtml(html: String): String { | 
			
		
	
		
			
				
					|  |  |  |  |         return if (TextUtils.isEmpty(html)) "" else html.replace("(?i)<(br[\\s/]*|/*p.*?|/*div.*?)>".toRegex(), "\n")// 替换特定标签为换行符 | 
			
		
	
		
			
				
					|  |  |  |  |                 .replace("<[script>]*.*?>| ".toRegex(), "")// 删除script标签对和空格转义符 | 
			
		
	
		
			
				
					|  |  |  |  |                 .replace("\\s*\\n+\\s*".toRegex(), "\n  ")// 移除空行,并增加段前缩进2个汉字 | 
			
		
	
		
			
				
					|  |  |  |  |                 .replace("^[\\n\\s]+".toRegex(), "  ")//移除开头空行,并增加段前缩进2个汉字 | 
			
		
	
		
			
				
					|  |  |  |  |                 .replace("[\\n\\s]+$".toRegex(), "") //移除尾部空行 | 
			
		
	
		
			
				
					|  |  |  |  |     } | 
			
		
	
		
			
				
					|  |  |  |  | } |