Compare commits
16
Commits
v0.0.7
..
11f7f50603
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
11f7f50603 | ||
|
|
3fb1363d8e | ||
|
|
f354c232fe | ||
|
|
66fc228d1f | ||
|
|
92e60b9c5b | ||
|
|
c75b1b895c | ||
|
|
810b184e53 | ||
|
|
06abba8765 | ||
|
|
21480a37a2 | ||
|
|
4e8351fee9 | ||
|
|
1017129c1a | ||
|
|
50d9296952 | ||
|
|
4162b75de9 | ||
|
|
97809cd321 | ||
|
|
801a945991 | ||
|
|
112e6290f0 |
@@ -6,7 +6,7 @@
|
||||
|
||||
<groupId>com.imyeyu.utils</groupId>
|
||||
<artifactId>timi-utils</artifactId>
|
||||
<version>0.0.7</version>
|
||||
<version>0.0.13</version>
|
||||
|
||||
<properties>
|
||||
<maven.test.skip>true</maven.test.skip>
|
||||
@@ -49,7 +49,7 @@
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.36</version>
|
||||
<version>1.18.46</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
@@ -91,7 +91,7 @@
|
||||
<dependency>
|
||||
<groupId>com.imyeyu.java</groupId>
|
||||
<artifactId>timi-java</artifactId>
|
||||
<version>0.0.4</version>
|
||||
<version>0.0.7</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>de.mkammerer</groupId>
|
||||
@@ -108,7 +108,7 @@
|
||||
<dependency>
|
||||
<groupId>org.projectlombok</groupId>
|
||||
<artifactId>lombok</artifactId>
|
||||
<version>1.18.34</version>
|
||||
<version>1.18.46</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
|
||||
@@ -52,8 +52,8 @@ public class Regex {
|
||||
/** 用户名 (4-16 位字母、数字、下划线) */
|
||||
public static final String USERNAME = "^[a-zA-Z0-9_]{4,16}$";
|
||||
|
||||
/** 密码 (6-18 位,包含字母和数字) */
|
||||
public static final String PASSWORD = "^(?=.*[a-zA-Z])(?=.*\\d)[a-zA-Z0-9]{6,18}$";
|
||||
/** 密码 (6-18 位,包含字母和数字,允许特殊字符) */
|
||||
public static final String PASSWORD = "^(?=.*[a-zA-Z])(?=.*\\d)[a-zA-Z0-9!#$%&()*+,\\-./:;<=>?@\\[\\]\\^_`{|}~]{6,32}$";
|
||||
|
||||
/** 中文字符 */
|
||||
public static final String CHINESE_CHAR = "^[\\u4e00-\\u9fa5]+$";
|
||||
|
||||
@@ -15,8 +15,16 @@ import java.util.UUID;
|
||||
*/
|
||||
public class Text {
|
||||
|
||||
public static String LETTER_POOL = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
|
||||
|
||||
public static String NUMBER_POOL = "0123456789";
|
||||
|
||||
public static String LETTER_NUMBER_POOL = LETTER_POOL + NUMBER_POOL;
|
||||
|
||||
public static String PASSWORD_CHAR_POOL = LETTER_NUMBER_POOL + "!@#$%^&*-_=+[]{}|;:./?";
|
||||
|
||||
/** 十六进制小写 */
|
||||
public static char[] HEX_DIGITS_LOWER = "0123456789abcdef".toCharArray();
|
||||
public static char[] HEX_DIGITS_LOWER = (NUMBER_POOL + "abcdef").toCharArray();
|
||||
|
||||
/**
|
||||
* 是否为半角字符
|
||||
@@ -150,18 +158,38 @@ public class Text {
|
||||
}
|
||||
|
||||
public static String randomString(int length) {
|
||||
return randomString("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789", length);
|
||||
return randomString(LETTER_NUMBER_POOL, length);
|
||||
}
|
||||
|
||||
public static String randomString(String pool, int length) {
|
||||
SecureRandom r = new SecureRandom();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (int i = 0; i < length; i++) {
|
||||
sb.append(pool.charAt(r.nextInt(pool.length() - 1)));
|
||||
sb.append(pool.charAt(r.nextInt(pool.length())));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public static String randomPassword(int length) {
|
||||
if (length < 6 || 32 < length) {
|
||||
throw new IllegalArgumentException("Password length must be between 6 and 32");
|
||||
}
|
||||
SecureRandom r = new SecureRandom();
|
||||
char[] chars = new char[length];
|
||||
chars[0] = LETTER_POOL.charAt(r.nextInt(LETTER_POOL.length()));
|
||||
chars[1] = NUMBER_POOL.charAt(r.nextInt(NUMBER_POOL.length()));
|
||||
for (int i = 2; i < length; i++) {
|
||||
chars[i] = PASSWORD_CHAR_POOL.charAt(r.nextInt(PASSWORD_CHAR_POOL.length()));
|
||||
}
|
||||
for (int i = chars.length - 1; 0 < i; i--) {
|
||||
int j = r.nextInt(i + 1);
|
||||
char temp = chars[i];
|
||||
chars[i] = chars[j];
|
||||
chars[j] = temp;
|
||||
}
|
||||
return new String(chars);
|
||||
}
|
||||
|
||||
/**
|
||||
* 较短的临时 UUID,如果使用在庞大的数据里,很可能会发生重复
|
||||
*
|
||||
@@ -407,4 +435,8 @@ public class Text {
|
||||
public static String bizClassName(Class<?> clazz) {
|
||||
return underscoreClassName(clazz).toUpperCase();
|
||||
}
|
||||
|
||||
public static String normalize(String text) {
|
||||
return TimiJava.defaultIfEmpty(text, null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
package com.imyeyu.utils;
|
||||
|
||||
import com.imyeyu.java.TimiJava;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.Instant;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.ZoneId;
|
||||
import java.time.temporal.ChronoUnit;
|
||||
import java.util.Date;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
@@ -77,6 +75,9 @@ public class Time {
|
||||
/** 格式化 yyyy-MM-dd'T'HH:mm:ss */
|
||||
public static final SimpleDateFormat dateTimeT = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
|
||||
/** 格式化 yyyy-MM-dd HH:mm:ss */
|
||||
public static final SimpleDateFormat serialize = new SimpleDateFormat("yyyyMMddHHmmss");
|
||||
|
||||
// ---------- 长整型时间戳 ----------
|
||||
|
||||
/** 1 秒时间戳 */
|
||||
@@ -105,31 +106,6 @@ public class Time {
|
||||
/** 1 天时间戳(整型) */
|
||||
public static final int DI = HI * 24;
|
||||
|
||||
/**
|
||||
* 计算两个时间戳精确的日期时间差
|
||||
*
|
||||
* @param begin 开始时间戳
|
||||
* @param end 结束时间戳
|
||||
* @return 时差
|
||||
*/
|
||||
public static Between between(long begin, long end) {
|
||||
if (end < begin) {
|
||||
throw new IllegalArgumentException("end time must greater than begin time:" + end + " < " + begin);
|
||||
}
|
||||
LocalDateTime ldtBegin = toLocalDateTime(begin);
|
||||
LocalDateTime ldtEnd = toLocalDateTime(end);
|
||||
|
||||
Between between = new Between();
|
||||
between.year = (int) ChronoUnit.YEARS.between(ldtBegin, ldtEnd);
|
||||
between.month = (int) ChronoUnit.MONTHS.between(ldtBegin, ldtEnd) % 12;
|
||||
between.day = (int) ChronoUnit.DAYS.between(ldtBegin.plusMonths(between.year * 12L + between.month), ldtEnd);
|
||||
between.hour = (int) (ChronoUnit.HOURS.between(ldtBegin, ldtEnd) - ChronoUnit.DAYS.between(ldtBegin, ldtEnd) * 24);
|
||||
between.minute = (int) ChronoUnit.MINUTES.between(ldtBegin, ldtEnd) % 60;
|
||||
between.second = (int) ChronoUnit.SECONDS.between(ldtBegin, ldtEnd) % 60;
|
||||
between.millis = (int) ((end - begin) % 1000);
|
||||
return between;
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取此刻毫秒
|
||||
*
|
||||
@@ -154,7 +130,11 @@ public class Time {
|
||||
* @return 昨天零时时间戳
|
||||
*/
|
||||
public static long yesterday() {
|
||||
return today() - D;
|
||||
return yesterday(now());
|
||||
}
|
||||
|
||||
public static long yesterday(long time) {
|
||||
return today(time) - D;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -163,9 +143,11 @@ public class Time {
|
||||
* @return 今天零时时间戳
|
||||
*/
|
||||
public static long today() {
|
||||
long now = now();
|
||||
final long H8 = H * 8;
|
||||
return ((now + H8 - (now + H8) % (H * 24)) - H8);
|
||||
return today(now());
|
||||
}
|
||||
|
||||
public static long today(long time) {
|
||||
return Instant.ofEpochMilli(time).atZone(ZoneId.systemDefault()).toLocalDate().atStartOfDay(ZoneId.systemDefault()).toInstant().toEpochMilli();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,7 +156,11 @@ public class Time {
|
||||
* @return 明天零时时间戳
|
||||
*/
|
||||
public static long tomorrow() {
|
||||
return today() + D;
|
||||
return tomorrow(now());
|
||||
}
|
||||
|
||||
public static long tomorrow(long time) {
|
||||
return today(time) + D;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -380,35 +366,4 @@ public class Time {
|
||||
return String.format("%d:%02d:%02d.%03d", h, s / 60 - h * 60, s % 60, millis % 1000);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 时差
|
||||
*
|
||||
* @author 夜雨
|
||||
* @version 2022-10-12 14:46
|
||||
*/
|
||||
@Getter
|
||||
public static class Between {
|
||||
|
||||
/** 年 */
|
||||
int year;
|
||||
|
||||
/** 月 */
|
||||
int month;
|
||||
|
||||
/** 天 */
|
||||
int day;
|
||||
|
||||
/** 小时 */
|
||||
int hour;
|
||||
|
||||
/** 分钟 */
|
||||
int minute;
|
||||
|
||||
/** 秒 */
|
||||
int second;
|
||||
|
||||
/** 毫秒 */
|
||||
int millis;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
package test;
|
||||
|
||||
import com.imyeyu.utils.Regex;
|
||||
import com.imyeyu.utils.Text;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import static org.junit.jupiter.api.Assertions.assertThrows;
|
||||
|
||||
/**
|
||||
* @author 夜雨
|
||||
* @since 2026-06-11 14:00
|
||||
*/
|
||||
public class TestRegex {
|
||||
|
||||
@Test
|
||||
public void testPassword() {
|
||||
assert Regex.isMatch(Regex.PASSWORD, "abc123");
|
||||
assert Regex.isMatch(Regex.PASSWORD, "abc123!");
|
||||
assert Regex.isMatch(Regex.PASSWORD, "Abc123[]^_`{|}~");
|
||||
assert Regex.isMatch(Regex.PASSWORD, "A1!#$%&*+,-./:@?");
|
||||
for (int i = 0; i < 20; i++) {
|
||||
assert Regex.isMatch(Regex.PASSWORD, Text.randomPassword(20));
|
||||
}
|
||||
|
||||
assert Regex.isNotMatch(Regex.PASSWORD, "abcdef!");
|
||||
assert Regex.isNotMatch(Regex.PASSWORD, "123456!");
|
||||
assert Regex.isNotMatch(Regex.PASSWORD, "Ab1!");
|
||||
assert Regex.isNotMatch(Regex.PASSWORD, "Abcdefghijklmnopqrstuvwxzy123456!");
|
||||
assert Regex.isNotMatch(Regex.PASSWORD, "Abc123\\");
|
||||
assert Regex.isNotMatch(Regex.PASSWORD, "Abc123\"");
|
||||
assert Regex.isNotMatch(Regex.PASSWORD, "Abc123'");
|
||||
assert Regex.isNotMatch(Regex.PASSWORD, "Abc123 ");
|
||||
assertThrows(IllegalArgumentException.class, () -> Text.randomPassword(5));
|
||||
assertThrows(IllegalArgumentException.class, () -> Text.randomPassword(33));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user