Rename
This commit is contained in:
1 parent
b86d90021c
commit
6c0757c91b
972 files changed
+6885
-7321
No files matched your search
@@ -0,0 +1,370 @@
|
||||
package io.legato.kazusa.utils
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.text.TextUtils.isEmpty
|
||||
import android.util.Base64
|
||||
import java.io.ByteArrayInputStream
|
||||
import java.io.ByteArrayOutputStream
|
||||
import java.io.IOException
|
||||
import java.text.DecimalFormat
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.Calendar
|
||||
import java.util.Locale
|
||||
import java.util.regex.Matcher
|
||||
import java.util.regex.Pattern
|
||||
import java.util.zip.GZIPInputStream
|
||||
import java.util.zip.GZIPOutputStream
|
||||
import kotlin.math.abs
|
||||
|
||||
|
||||
@Suppress("unused", "MemberVisibilityCanBePrivate")
|
||||
object 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 wordCountFormatter by lazy {
|
||||
DecimalFormat("#.#")
|
||||
}
|
||||
|
||||
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(source: String, pattern: String): String {
|
||||
val format = SimpleDateFormat(pattern, Locale.getDefault())
|
||||
val calendar = Calendar.getInstance()
|
||||
kotlin.runCatching {
|
||||
val date = format.parse(source) ?: return ""
|
||||
val curTime = calendar.timeInMillis
|
||||
calendar.time = date
|
||||
//将MISC 转换成 sec
|
||||
val difSec = 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) {
|
||||
//比日期:昨天今天和明天
|
||||
return when {
|
||||
difDate == 0L -> "今天"
|
||||
difDate < DAY_OF_YESTERDAY -> "昨天"
|
||||
else -> {
|
||||
@SuppressLint("SimpleDateFormat")
|
||||
val convertFormat = SimpleDateFormat("yyyy-MM-dd")
|
||||
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)
|
||||
}
|
||||
}
|
||||
}.onFailure {
|
||||
it.printOnDebug()
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
/**
|
||||
* 首字母大写
|
||||
*/
|
||||
@SuppressLint("DefaultLocale")
|
||||
fun toFirstCapital(str: String): String {
|
||||
return str.substring(0, 1).uppercase(Locale.getDefault()) + str.substring(1)
|
||||
}
|
||||
|
||||
/**
|
||||
* 将文本中的半角字符,转换成全角字符
|
||||
*/
|
||||
fun halfToFull(input: String): String {
|
||||
val c = input.toCharArray()
|
||||
for (i in c.indices) {
|
||||
if (c[i].code == 32)
|
||||
//半角空格
|
||||
{
|
||||
c[i] = 12288.toChar()
|
||||
continue
|
||||
}
|
||||
//根据实际情况,过滤不需要转换的符号
|
||||
//if (c[i] == 46) //半角点号,不转换
|
||||
// continue;
|
||||
|
||||
if (c[i].code in 33..126)
|
||||
//其他符号都转换为全角
|
||||
c[i] = (c[i].code + 65248).toChar()
|
||||
}
|
||||
return String(c)
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串全角转换为半角
|
||||
*/
|
||||
fun fullToHalf(input: String): String {
|
||||
val c = input.toCharArray()
|
||||
for (i in c.indices) {
|
||||
if (c[i].code == 12288)
|
||||
//全角空格
|
||||
{
|
||||
c[i] = 32.toChar()
|
||||
continue
|
||||
}
|
||||
|
||||
if (c[i].code in 65281..65374)
|
||||
c[i] = (c[i].code - 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))
|
||||
}
|
||||
|
||||
// "一千零二十五", "一千二" 形式
|
||||
return kotlin.runCatching {
|
||||
for (i in cn.indices) {
|
||||
val tmpNum = ChnMap[cn[i]]!!
|
||||
when {
|
||||
tmpNum == 100000000 -> {
|
||||
result += tmp
|
||||
result *= tmpNum
|
||||
billion = billion * 100000000 + result
|
||||
result = 0
|
||||
tmp = 0
|
||||
}
|
||||
|
||||
tmpNum == 10000 -> {
|
||||
result += tmp
|
||||
result *= tmpNum
|
||||
tmp = 0
|
||||
}
|
||||
|
||||
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
|
||||
result
|
||||
}.getOrDefault(-1)
|
||||
}
|
||||
|
||||
/**
|
||||
* 字符串转数字
|
||||
*/
|
||||
fun stringToInt(str: String?): Int {
|
||||
if (str != null) {
|
||||
val num = fullToHalf(str).replace("\\s+".toRegex(), "")
|
||||
return kotlin.runCatching {
|
||||
Integer.parseInt(num)
|
||||
}.getOrElse {
|
||||
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()
|
||||
}
|
||||
|
||||
fun wordCountFormat(words: Int): String {
|
||||
var wordsS = ""
|
||||
if (words > 0) {
|
||||
if (words > 10000) {
|
||||
val df = wordCountFormatter
|
||||
wordsS = df.format(words * 1.0f / 10000f.toDouble()) + "万字"
|
||||
} else {
|
||||
wordsS = words.toString() + "字"
|
||||
}
|
||||
}
|
||||
return wordsS
|
||||
}
|
||||
|
||||
fun wordCountFormat(wc: String?): String {
|
||||
if (wc == null) return ""
|
||||
var wordsS = ""
|
||||
if (isNumeric(wc)) {
|
||||
val words: Int = wc.toInt()
|
||||
if (words > 0) {
|
||||
if (words > 10000) {
|
||||
val df = wordCountFormatter
|
||||
wordsS = df.format(words * 1.0f / 10000f.toDouble()) + "万字"
|
||||
} else {
|
||||
wordsS = words.toString() + "字"
|
||||
}
|
||||
}
|
||||
} else {
|
||||
wordsS = wc
|
||||
}
|
||||
return wordsS
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除字符串首尾空字符的高效方法(利用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].code <= 0x20 || s[start] == ' ')) {
|
||||
++start
|
||||
}
|
||||
while (start < end && (s[end].code <= 0x20 || s[end] == ' ')) {
|
||||
--end
|
||||
}
|
||||
++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()
|
||||
}
|
||||
|
||||
/**
|
||||
* 移除UTF头
|
||||
*/
|
||||
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 compress(str: String): Result<String> {
|
||||
return kotlin.runCatching {
|
||||
if (str.isEmpty()) {
|
||||
return@runCatching str
|
||||
}
|
||||
val out = ByteArrayOutputStream()
|
||||
var gzip: GZIPOutputStream? = null
|
||||
return@runCatching try {
|
||||
gzip = GZIPOutputStream(out)
|
||||
gzip.write(str.toByteArray())
|
||||
Base64.encodeToString(out.toByteArray(), Base64.NO_WRAP)
|
||||
} finally {
|
||||
gzip?.runCatching {
|
||||
close()
|
||||
}
|
||||
out.runCatching {
|
||||
close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 解压字符串
|
||||
*/
|
||||
@Throws(IOException::class)
|
||||
fun unCompress(str: String): Result<String> {
|
||||
return kotlin.runCatching {
|
||||
val outputStream = ByteArrayOutputStream()
|
||||
var inputStream: ByteArrayInputStream? = null
|
||||
var ginZip: GZIPInputStream? = null
|
||||
return@runCatching try {
|
||||
val compressed = Base64.decode(str, Base64.NO_WRAP)
|
||||
inputStream = ByteArrayInputStream(compressed)
|
||||
ginZip = GZIPInputStream(inputStream)
|
||||
ginZip.copyTo(outputStream)
|
||||
outputStream.toString()
|
||||
} finally {
|
||||
ginZip?.runCatching {
|
||||
close()
|
||||
}
|
||||
inputStream?.runCatching {
|
||||
close()
|
||||
}
|
||||
outputStream.runCatching {
|
||||
close()
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
Reference in new issue
Block a user