From 4b67b9a91fdb25fcafa905e9894f454fb5a3e221 Mon Sep 17 00:00:00 2001 From: smallchill Date: Thu, 27 Dec 2018 17:23:44 +0800 Subject: [PATCH] =?UTF-8?q?:zap:=20=E6=A0=B9=E6=8D=AEP3C=E4=BC=98=E5=8C=96?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../config/RedisTemplateConfiguration.java | 2 +- .../core/boot/file/BladeFileUtil.java | 40 +- ...ce.java => ConsulLauncherServiceImpl.java} | 2 +- .../core/launch/props/BladeProperties.java | 7 +- .../core/log/publisher/ApiLogPublisher.java | 2 +- .../core/log/publisher/BladeLogPublisher.java | 2 +- .../core/mp/support/BaseEntityWrapper.java | 15 + .../core/secure/utils/SecureUtil.java | 57 +- .../core/tool/constant/SystemConstant.java | 4 +- .../core/tool/date/BetweenFormater.java | 157 -- .../core/tool/date/ConcurrentDateFormat.java | 70 - .../core/tool/date/DateBetween.java | 153 -- .../core/tool/date/DateException.java | 31 - .../springblade/core/tool/date/DateField.java | 130 -- .../core/tool/date/DatePattern.java | 71 - .../springblade/core/tool/date/DateTime.java | 753 --------- .../springblade/core/tool/date/DateUnit.java | 33 - .../springblade/core/tool/date/DateUtil.java | 1471 ----------------- .../org/springblade/core/tool/date/Month.java | 118 -- .../springblade/core/tool/date/Season.java | 61 - .../core/tool/date/TimeInterval.java | 109 -- .../org/springblade/core/tool/date/Week.java | 120 -- .../tool/date/format/AbstractDateBasic.java | 64 - .../core/tool/date/format/DateBasic.java | 33 - .../core/tool/date/format/DateParser.java | 68 - .../core/tool/date/format/DatePrinter.java | 78 - .../core/tool/date/format/FastDateFormat.java | 392 ----- .../core/tool/date/format/FastDateParser.java | 822 --------- .../tool/date/format/FastDatePrinter.java | 1320 --------------- .../core/tool/date/format/FormatCache.java | 252 --- .../core/tool/jackson/JsonUtil.java | 13 +- .../org/springblade/core/tool/node/INode.java | 14 +- .../core/tool/support/StrSpliter.java | 21 +- .../springblade/core/tool/support/Try.java | 6 + .../tool/utils/{AESUtil.java => AesUtil.java} | 12 +- .../core/tool/utils/DateTimeUtil.java | 8 +- .../core/tool/utils/Exceptions.java | 2 + .../org/springblade/core/tool/utils/Func.java | 21 +- .../core/tool/utils/ImageUtil.java | 31 +- .../tool/utils/{IOUtil.java => IoUtil.java} | 12 +- .../{OKHttpUtil.java => OkHttpUtil.java} | 2 +- .../core/tool/utils/StringPool.java | 4 + .../core/tool/utils/StringUtil.java | 28 +- .../core/tool/utils/SuffixFileFilter.java | 2 + .../tool/utils/{URLUtil.java => UrlUtil.java} | 6 +- .../springblade/core/tool/utils/WebUtil.java | 18 +- .../springblade/core/tool/utils/XmlUtil.java | 10 +- 47 files changed, 207 insertions(+), 6440 deletions(-) rename blade-core-launch/src/main/java/org/springblade/core/launch/consul/{ConsulLauncherService.java => ConsulLauncherServiceImpl.java} (95%) delete mode 100644 blade-core-tool/src/main/java/org/springblade/core/tool/date/BetweenFormater.java delete mode 100644 blade-core-tool/src/main/java/org/springblade/core/tool/date/ConcurrentDateFormat.java delete mode 100644 blade-core-tool/src/main/java/org/springblade/core/tool/date/DateBetween.java delete mode 100644 blade-core-tool/src/main/java/org/springblade/core/tool/date/DateException.java delete mode 100644 blade-core-tool/src/main/java/org/springblade/core/tool/date/DateField.java delete mode 100644 blade-core-tool/src/main/java/org/springblade/core/tool/date/DatePattern.java delete mode 100644 blade-core-tool/src/main/java/org/springblade/core/tool/date/DateTime.java delete mode 100644 blade-core-tool/src/main/java/org/springblade/core/tool/date/DateUnit.java delete mode 100644 blade-core-tool/src/main/java/org/springblade/core/tool/date/DateUtil.java delete mode 100644 blade-core-tool/src/main/java/org/springblade/core/tool/date/Month.java delete mode 100644 blade-core-tool/src/main/java/org/springblade/core/tool/date/Season.java delete mode 100644 blade-core-tool/src/main/java/org/springblade/core/tool/date/TimeInterval.java delete mode 100644 blade-core-tool/src/main/java/org/springblade/core/tool/date/Week.java delete mode 100644 blade-core-tool/src/main/java/org/springblade/core/tool/date/format/AbstractDateBasic.java delete mode 100644 blade-core-tool/src/main/java/org/springblade/core/tool/date/format/DateBasic.java delete mode 100644 blade-core-tool/src/main/java/org/springblade/core/tool/date/format/DateParser.java delete mode 100644 blade-core-tool/src/main/java/org/springblade/core/tool/date/format/DatePrinter.java delete mode 100644 blade-core-tool/src/main/java/org/springblade/core/tool/date/format/FastDateFormat.java delete mode 100644 blade-core-tool/src/main/java/org/springblade/core/tool/date/format/FastDateParser.java delete mode 100644 blade-core-tool/src/main/java/org/springblade/core/tool/date/format/FastDatePrinter.java delete mode 100644 blade-core-tool/src/main/java/org/springblade/core/tool/date/format/FormatCache.java rename blade-core-tool/src/main/java/org/springblade/core/tool/utils/{AESUtil.java => AesUtil.java} (94%) rename blade-core-tool/src/main/java/org/springblade/core/tool/utils/{IOUtil.java => IoUtil.java} (91%) rename blade-core-tool/src/main/java/org/springblade/core/tool/utils/{OKHttpUtil.java => OkHttpUtil.java} (99%) rename blade-core-tool/src/main/java/org/springblade/core/tool/utils/{URLUtil.java => UrlUtil.java} (90%) diff --git a/blade-core-boot/src/main/java/org/springblade/core/boot/config/RedisTemplateConfiguration.java b/blade-core-boot/src/main/java/org/springblade/core/boot/config/RedisTemplateConfiguration.java index 5ff6f04..a8b8f66 100644 --- a/blade-core-boot/src/main/java/org/springblade/core/boot/config/RedisTemplateConfiguration.java +++ b/blade-core-boot/src/main/java/org/springblade/core/boot/config/RedisTemplateConfiguration.java @@ -72,7 +72,7 @@ public class RedisTemplateConfiguration { @Bean public CacheManager cacheManager(RedisConnectionFactory redisConnectionFactory) { RedisCacheConfiguration redisCacheConfiguration = RedisCacheConfiguration.defaultCacheConfig() - .entryTtl(Duration.ofHours(1)); // 设置缓存有效期一小时 + .entryTtl(Duration.ofHours(1)); return RedisCacheManager .builder(RedisCacheWriter.nonLockingRedisCacheWriter(redisConnectionFactory)) .cacheDefaults(redisCacheConfiguration).build(); diff --git a/blade-core-boot/src/main/java/org/springblade/core/boot/file/BladeFileUtil.java b/blade-core-boot/src/main/java/org/springblade/core/boot/file/BladeFileUtil.java index bdbaed5..01cbe43 100644 --- a/blade-core-boot/src/main/java/org/springblade/core/boot/file/BladeFileUtil.java +++ b/blade-core-boot/src/main/java/org/springblade/core/boot/file/BladeFileUtil.java @@ -15,6 +15,7 @@ */ package org.springblade.core.boot.file; +import org.springblade.core.tool.utils.StringPool; import org.springblade.core.tool.utils.StringUtil; import org.springframework.web.multipart.MultipartFile; @@ -31,6 +32,9 @@ public class BladeFileUtil { * 定义允许上传的文件扩展名 */ private static HashMap extMap = new HashMap(); + private static String IS_DIR = "is_dir"; + private static String FILE_NAME = "filename"; + private static String FILE_SIZE = "filesize"; /** * 图片扩展名 @@ -53,7 +57,7 @@ public class BladeFileUtil { * @return String 返回类型 */ public static String getFileExt(String fileName) { - return fileName.substring(fileName.lastIndexOf('.'), fileName.length()); + return fileName.substring(fileName.lastIndexOf(StringPool.DOT)); } /** @@ -75,7 +79,21 @@ public class BladeFileUtil { * 文件管理排序 */ public enum FileSort { - size, type, name; + + /** + * 大小 + */ + size, + + /** + * 类型 + */ + type, + + /** + * 名称 + */ + name; /** * 文本排序转换成枚举 @@ -97,12 +115,12 @@ public class BladeFileUtil { public int compare(Object a, Object b) { Hashtable hashA = (Hashtable) a; Hashtable hashB = (Hashtable) b; - if (((Boolean) hashA.get("is_dir")) && !((Boolean) hashB.get("is_dir"))) { + if (((Boolean) hashA.get(IS_DIR)) && !((Boolean) hashB.get(IS_DIR))) { return -1; - } else if (!((Boolean) hashA.get("is_dir")) && ((Boolean) hashB.get("is_dir"))) { + } else if (!((Boolean) hashA.get(IS_DIR)) && ((Boolean) hashB.get(IS_DIR))) { return 1; } else { - return ((String) hashA.get("filename")).compareTo((String) hashB.get("filename")); + return ((String) hashA.get(FILE_NAME)).compareTo((String) hashB.get(FILE_NAME)); } } } @@ -112,14 +130,14 @@ public class BladeFileUtil { public int compare(Object a, Object b) { Hashtable hashA = (Hashtable) a; Hashtable hashB = (Hashtable) b; - if (((Boolean) hashA.get("is_dir")) && !((Boolean) hashB.get("is_dir"))) { + if (((Boolean) hashA.get(IS_DIR)) && !((Boolean) hashB.get(IS_DIR))) { return -1; - } else if (!((Boolean) hashA.get("is_dir")) && ((Boolean) hashB.get("is_dir"))) { + } else if (!((Boolean) hashA.get(IS_DIR)) && ((Boolean) hashB.get(IS_DIR))) { return 1; } else { - if (((Long) hashA.get("filesize")) > ((Long) hashB.get("filesize"))) { + if (((Long) hashA.get(FILE_SIZE)) > ((Long) hashB.get(FILE_SIZE))) { return 1; - } else if (((Long) hashA.get("filesize")) < ((Long) hashB.get("filesize"))) { + } else if (((Long) hashA.get(FILE_SIZE)) < ((Long) hashB.get(FILE_SIZE))) { return -1; } else { return 0; @@ -133,9 +151,9 @@ public class BladeFileUtil { public int compare(Object a, Object b) { Hashtable hashA = (Hashtable) a; Hashtable hashB = (Hashtable) b; - if (((Boolean) hashA.get("is_dir")) && !((Boolean) hashB.get("is_dir"))) { + if (((Boolean) hashA.get(IS_DIR)) && !((Boolean) hashB.get(IS_DIR))) { return -1; - } else if (!((Boolean) hashA.get("is_dir")) && ((Boolean) hashB.get("is_dir"))) { + } else if (!((Boolean) hashA.get(IS_DIR)) && ((Boolean) hashB.get(IS_DIR))) { return 1; } else { return ((String) hashA.get("filetype")).compareTo((String) hashB.get("filetype")); diff --git a/blade-core-launch/src/main/java/org/springblade/core/launch/consul/ConsulLauncherService.java b/blade-core-launch/src/main/java/org/springblade/core/launch/consul/ConsulLauncherServiceImpl.java similarity index 95% rename from blade-core-launch/src/main/java/org/springblade/core/launch/consul/ConsulLauncherService.java rename to blade-core-launch/src/main/java/org/springblade/core/launch/consul/ConsulLauncherServiceImpl.java index 3e7b419..1084666 100644 --- a/blade-core-launch/src/main/java/org/springblade/core/launch/consul/ConsulLauncherService.java +++ b/blade-core-launch/src/main/java/org/springblade/core/launch/consul/ConsulLauncherServiceImpl.java @@ -26,7 +26,7 @@ import java.util.Properties; * * @author smallchil */ -public class ConsulLauncherService implements LauncherService { +public class ConsulLauncherServiceImpl implements LauncherService { @Override public void launcher(SpringApplicationBuilder builder, String appName, String profile) { diff --git a/blade-core-launch/src/main/java/org/springblade/core/launch/props/BladeProperties.java b/blade-core-launch/src/main/java/org/springblade/core/launch/props/BladeProperties.java index b9bc744..70b21cf 100644 --- a/blade-core-launch/src/main/java/org/springblade/core/launch/props/BladeProperties.java +++ b/blade-core-launch/src/main/java/org/springblade/core/launch/props/BladeProperties.java @@ -162,12 +162,7 @@ public class BladeProperties { String value = prop.get(key); if (value != null) { value = value.toLowerCase().trim(); - if ("true".equals(value)) { - return Boolean.TRUE; - } else if ("false".equals(value)) { - return Boolean.FALSE; - } - throw new RuntimeException("The value can not parse to Boolean : " + value); + return Boolean.parseBoolean(value); } return defaultValue; } diff --git a/blade-core-log/src/main/java/org/springblade/core/log/publisher/ApiLogPublisher.java b/blade-core-log/src/main/java/org/springblade/core/log/publisher/ApiLogPublisher.java index 7476c17..b29e408 100644 --- a/blade-core-log/src/main/java/org/springblade/core/log/publisher/ApiLogPublisher.java +++ b/blade-core-log/src/main/java/org/springblade/core/log/publisher/ApiLogPublisher.java @@ -43,7 +43,7 @@ public class ApiLogPublisher { logApi.setTime(String.valueOf(time)); logApi.setMethodClass(methodClass); logApi.setMethodName(methodName); - Map event = new HashMap<>(); + Map event = new HashMap<>(16); event.put(EventConstant.EVENT_LOG, logApi); event.put(EventConstant.EVENT_REQUEST, request); SpringUtil.publishEvent(new ApiLogEvent(event)); diff --git a/blade-core-log/src/main/java/org/springblade/core/log/publisher/BladeLogPublisher.java b/blade-core-log/src/main/java/org/springblade/core/log/publisher/BladeLogPublisher.java index c851dab..9990019 100644 --- a/blade-core-log/src/main/java/org/springblade/core/log/publisher/BladeLogPublisher.java +++ b/blade-core-log/src/main/java/org/springblade/core/log/publisher/BladeLogPublisher.java @@ -39,7 +39,7 @@ public class BladeLogPublisher { logBlade.setLogLevel(level); logBlade.setLogId(id); logBlade.setLogData(data); - Map event = new HashMap<>(); + Map event = new HashMap<>(16); event.put(EventConstant.EVENT_LOG, logBlade); event.put(EventConstant.EVENT_REQUEST, request); SpringUtil.publishEvent(new BladeLogEvent(event)); diff --git a/blade-core-mybatis/src/main/java/org/springblade/core/mp/support/BaseEntityWrapper.java b/blade-core-mybatis/src/main/java/org/springblade/core/mp/support/BaseEntityWrapper.java index ecee08e..f277216 100644 --- a/blade-core-mybatis/src/main/java/org/springblade/core/mp/support/BaseEntityWrapper.java +++ b/blade-core-mybatis/src/main/java/org/springblade/core/mp/support/BaseEntityWrapper.java @@ -28,12 +28,27 @@ import java.util.stream.Collectors; */ public abstract class BaseEntityWrapper { + /** + * 单个实体类包装 + * @param entity + * @return + */ public abstract V entityVO(E entity); + /** + * 实体类集合包装 + * @param list + * @return + */ public List listVO(List list) { return list.stream().map(this::entityVO).collect(Collectors.toList()); } + /** + * 分页实体类集合包装 + * @param pages + * @return + */ public IPage pageVO(IPage pages) { List records = listVO(pages.getRecords()); IPage pageVo = new Page<>(pages.getCurrent(), pages.getSize(), pages.getTotal()); diff --git a/blade-core-secure/src/main/java/org/springblade/core/secure/utils/SecureUtil.java b/blade-core-secure/src/main/java/org/springblade/core/secure/utils/SecureUtil.java index f64323f..9d4880b 100644 --- a/blade-core-secure/src/main/java/org/springblade/core/secure/utils/SecureUtil.java +++ b/blade-core-secure/src/main/java/org/springblade/core/secure/utils/SecureUtil.java @@ -20,9 +20,6 @@ import io.jsonwebtoken.JwtBuilder; import io.jsonwebtoken.Jwts; import io.jsonwebtoken.SignatureAlgorithm; import org.springblade.core.secure.BladeUser; -import org.springblade.core.tool.date.DateField; -import org.springblade.core.tool.date.DateTime; -import org.springblade.core.tool.date.DateUtil; import org.springblade.core.tool.utils.Func; import org.springblade.core.tool.utils.StringPool; import org.springblade.core.tool.utils.WebUtil; @@ -31,6 +28,7 @@ import javax.crypto.spec.SecretKeySpec; import javax.servlet.http.HttpServletRequest; import javax.xml.bind.DatatypeConverter; import java.security.Key; +import java.util.Calendar; import java.util.Date; import java.util.Map; @@ -42,16 +40,17 @@ import java.util.Map; public class SecureUtil { public static final String BLADE_USER_REQUEST_ATTR = "_BLADE_USER_REQUEST_ATTR_"; - public final static String header = "Authorization"; - public final static String bearer = "bearer"; - public final static String account = "account"; - public final static String userId = "userId"; - public final static String roleId = "roleId"; - public final static String userName = "userName"; - public final static String roleName = "roleName"; - private static String base64Security = DatatypeConverter.printBase64Binary("SpringBlade".getBytes()); + public final static String HEADER = "Authorization"; + public final static String BEARER = "bearer"; + public final static String ACCOUNT = "account"; + public final static String USER_ID = "userId"; + public final static String ROLE_ID = "roleId"; + public final static String USER_NAME = "userName"; + public final static String ROLE_NAME = "roleName"; + public final static Integer AUTH_LENGTH = 7; + private static String BASE64_SECURITY = DatatypeConverter.printBase64Binary("SpringBlade".getBytes()); - /** + /**6 * 获取用户信息 * * @return @@ -80,10 +79,10 @@ public class SecureUtil { if (claims == null) { return null; } - Integer userId = Func.toInt(claims.get(SecureUtil.userId)); - String roleId = Func.toStr(claims.get(SecureUtil.roleId)); - String account = Func.toStr(claims.get(SecureUtil.account)); - String roleName = Func.toStr(claims.get(SecureUtil.roleName)); + Integer userId = Func.toInt(claims.get(SecureUtil.USER_ID)); + String roleId = Func.toStr(claims.get(SecureUtil.ROLE_ID)); + String account = Func.toStr(claims.get(SecureUtil.ACCOUNT)); + String roleName = Func.toStr(claims.get(SecureUtil.ROLE_NAME)); BladeUser bladeUser = new BladeUser(); bladeUser.setAccount(account); bladeUser.setUserId(userId); @@ -135,10 +134,10 @@ public class SecureUtil { * @return */ public static Claims getClaims(HttpServletRequest request) { - String auth = request.getHeader(SecureUtil.header); - if ((auth != null) && (auth.length() > 7)) { - String HeadStr = auth.substring(0, 6).toLowerCase(); - if (HeadStr.compareTo(SecureUtil.bearer) == 0) { + String auth = request.getHeader(SecureUtil.HEADER); + if ((auth != null) && (auth.length() > AUTH_LENGTH)) { + String headStr = auth.substring(0, 6).toLowerCase(); + if (headStr.compareTo(SecureUtil.BEARER) == 0) { auth = auth.substring(7); return SecureUtil.parseJWT(auth); } @@ -162,7 +161,7 @@ public class SecureUtil { * @return */ public static String getHeader(HttpServletRequest request) { - return request.getHeader(header); + return request.getHeader(HEADER); } /** @@ -174,7 +173,7 @@ public class SecureUtil { public static Claims parseJWT(String jsonWebToken) { try { Claims claims = Jwts.parser() - .setSigningKey(DatatypeConverter.parseBase64Binary(base64Security)) + .setSigningKey(DatatypeConverter.parseBase64Binary(BASE64_SECURITY)) .parseClaimsJws(jsonWebToken).getBody(); return claims; } catch (Exception ex) { @@ -198,7 +197,7 @@ public class SecureUtil { Date now = new Date(nowMillis); //生成签名密钥 - byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(base64Security); + byte[] apiKeySecretBytes = DatatypeConverter.parseBase64Binary(BASE64_SECURITY); Key signingKey = new SecretKeySpec(apiKeySecretBytes, signatureAlgorithm.getJcaName()); //添加构成JWT的类 @@ -227,9 +226,13 @@ public class SecureUtil { * @return */ public static long getExpire() { - DateTime dateTime = DateUtil.endOfDay(new Date()); - DateTime offset = DateUtil.offset(dateTime, DateField.HOUR, 3); - - return offset.getTime() - System.currentTimeMillis(); + Calendar cal = Calendar.getInstance(); + cal.add(Calendar.DAY_OF_YEAR, 1); + cal.set(Calendar.HOUR_OF_DAY, 3); + cal.set(Calendar.SECOND, 0); + cal.set(Calendar.MINUTE, 0); + cal.set(Calendar.MILLISECOND, 0); + return cal.getTimeInMillis() - System.currentTimeMillis(); } + } diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/constant/SystemConstant.java b/blade-core-tool/src/main/java/org/springblade/core/tool/constant/SystemConstant.java index 1918b38..f1277c2 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/constant/SystemConstant.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/constant/SystemConstant.java @@ -81,14 +81,14 @@ public class SystemConstant { */ private String contextPath = "/"; - private static final SystemConstant me = new SystemConstant(); + private static final SystemConstant ME = new SystemConstant(); private SystemConstant() { } public static SystemConstant me() { - return me; + return ME; } public String getUploadRealPath() { diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/date/BetweenFormater.java b/blade-core-tool/src/main/java/org/springblade/core/tool/date/BetweenFormater.java deleted file mode 100644 index c3b32da..0000000 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/date/BetweenFormater.java +++ /dev/null @@ -1,157 +0,0 @@ -package org.springblade.core.tool.date; - -/** - * 时长格式化器 - * @author Looly - * - */ -public class BetweenFormater { - - /** 时长毫秒数 */ - private long betweenMs; - /** 格式化级别 */ - private Level level; - /** 格式化级别的最大个数 */ - private int levelMaxCount; - - /** - * 构造 - * @param betweenMs 日期间隔 - * @param level 级别,按照天、小时、分、秒、毫秒分为5个等级,根据传入等级,格式化到相应级别 - */ - public BetweenFormater(long betweenMs, Level level) { - this(betweenMs, level, 0); - } - - /** - * 构造 - * @param betweenMs 日期间隔 - * @param level 级别,按照天、小时、分、秒、毫秒分为5个等级,根据传入等级,格式化到相应级别 - * @param levelMaxCount 格式化级别的最大个数,假如级别个数为1,但是级别到秒,那只显示一个级别 - */ - public BetweenFormater(long betweenMs, Level level, int levelMaxCount) { - this.betweenMs = betweenMs; - this.level = level; - this.levelMaxCount = levelMaxCount; - } - - /** - * 格式化日期间隔输出
- * - * @return 格式化后的字符串 - */ - public String format(){ - if(betweenMs == 0){ - return "0"; - } - - long day = betweenMs / DateUnit.DAY.getMillis(); - long hour = betweenMs / DateUnit.HOUR.getMillis() - day * 24; - long minute = betweenMs / DateUnit.MINUTE.getMillis() - day * 24 * 60 - hour * 60; - long second = betweenMs / DateUnit.SECOND.getMillis() - ((day * 24 + hour) * 60 + minute) * 60; - long millisecond = betweenMs - (((day * 24 + hour) * 60 + minute) * 60 + second) * 1000; - - StringBuilder sb = new StringBuilder(); - final int level = this.level.value; - int levelCount = 0; - - if(isLevelCountValid(levelCount) && 0 != day && level > 0){ - sb.append(day).append("天"); - levelCount++; - } - if(isLevelCountValid(levelCount) && 0 != hour && level > 1){ - sb.append(hour).append("小时"); - levelCount++; - } - if(isLevelCountValid(levelCount) && 0 != minute && level > 2){ - sb.append(minute).append("分"); - levelCount++; - } - if(isLevelCountValid(levelCount) && 0 != second && level > 3){ - sb.append(second).append("秒"); - levelCount++; - } - if(isLevelCountValid(levelCount) && 0 != millisecond && level > 4){ - sb.append(millisecond).append("毫秒"); - levelCount++; - } - - return sb.toString(); - } - - /** - * 获得 时长毫秒数 - * @return 时长毫秒数 - */ - public long getBetweenMs() { - return betweenMs; - } - - /** - * 设置 时长毫秒数 - * @param betweenMs 时长毫秒数 - */ - public void setBetweenMs(long betweenMs) { - this.betweenMs = betweenMs; - } - - /** - * 获得 格式化级别 - * @return 格式化级别 - */ - public Level getLevel() { - return level; - } - - /** - * 设置格式化级别 - * @param level 格式化级别 - */ - public void setLevel(Level level) { - this.level = level; - } - - /** - * 格式化等级枚举
- * @author Looly - */ - public static enum Level { - - /** 天 */ - DAY(1), - /** 小时 */ - HOUR(2), - /** 分钟 */ - MINUTE(3), - /** 秒 */ - SECOND(4), - /** 毫秒 */ - MILLSECOND(5); - - private int value; - - private Level(int value) { - this.value = value; - } - - public int getValue() { - return this.value; - } - } - - @Override - public String toString() { - return format(); - } - - /** - * 等级数量是否有效
- * 有效的定义是:levelMaxCount大于0(被设置),当前等级数量没有超过这个最大值 - * - * @param levelCount 登记数量 - * @return 是否有效 - */ - private boolean isLevelCountValid(int levelCount){ - return this.levelMaxCount <= 0 || levelCount < this.levelMaxCount; - } -} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/date/ConcurrentDateFormat.java b/blade-core-tool/src/main/java/org/springblade/core/tool/date/ConcurrentDateFormat.java deleted file mode 100644 index be576c1..0000000 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/date/ConcurrentDateFormat.java +++ /dev/null @@ -1,70 +0,0 @@ -package org.springblade.core.tool.date; - -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; -import java.util.Queue; -import java.util.TimeZone; -import java.util.concurrent.ConcurrentLinkedQueue; - -/** - * 参考tomcat8中的并发DateFormat - *

- * {@link SimpleDateFormat}的线程安全包装器。 - * 不使用ThreadLocal,创建足够的SimpleDateFormat对象来满足并发性要求。 - * - * @author L.cm - */ -public class ConcurrentDateFormat { - private final String format; - private final Locale locale; - private final TimeZone timezone; - private final Queue queue = new ConcurrentLinkedQueue<>(); - - private ConcurrentDateFormat(String format, Locale locale, TimeZone timezone) { - this.format = format; - this.locale = locale; - this.timezone = timezone; - SimpleDateFormat initial = createInstance(); - queue.add(initial); - } - - public static ConcurrentDateFormat of(String format) { - return new ConcurrentDateFormat(format, Locale.getDefault(), TimeZone.getDefault()); - } - - public static ConcurrentDateFormat of(String format, TimeZone timezone) { - return new ConcurrentDateFormat(format, Locale.getDefault(), timezone); - } - - public static ConcurrentDateFormat of(String format, Locale locale, TimeZone timezone) { - return new ConcurrentDateFormat(format, locale, timezone); - } - - public String format(Date date) { - SimpleDateFormat sdf = queue.poll(); - if (sdf == null) { - sdf = createInstance(); - } - String result = sdf.format(date); - queue.add(sdf); - return result; - } - - public Date parse(String source) throws ParseException { - SimpleDateFormat sdf = queue.poll(); - if (sdf == null) { - sdf = createInstance(); - } - Date result = sdf.parse(source); - queue.add(sdf); - return result; - } - - private SimpleDateFormat createInstance() { - SimpleDateFormat sdf = new SimpleDateFormat(format, locale); - sdf.setTimeZone(timezone); - return sdf; - } -} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/date/DateBetween.java b/blade-core-tool/src/main/java/org/springblade/core/tool/date/DateBetween.java deleted file mode 100644 index d86a2f8..0000000 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/date/DateBetween.java +++ /dev/null @@ -1,153 +0,0 @@ -package org.springblade.core.tool.date; - -import java.util.Calendar; -import java.util.Date; - -/** - * 日期间隔 - * - * @author Looly - * - */ -public class DateBetween { - - /** 开始日期 */ - private Date begin; - /** 结束日期 */ - private Date end; - - /** - * 创建
- * 在前的日期做为起始时间,在后的做为结束时间,间隔只保留绝对值正数 - * - * @param begin 起始时间 - * @param end 结束时间 - * @return {@link DateBetween} - * @since 3.2.3 - */ - public static DateBetween create(Date begin, Date end) { - return new DateBetween(begin, end); - } - - /** - * 创建
- * 在前的日期做为起始时间,在后的做为结束时间,间隔只保留绝对值正数 - * - * @param begin 起始时间 - * @param end 结束时间 - * @param isAbs 日期间隔是否只保留绝对值正数 - * @return {@link DateBetween} - * @since 3.2.3 - */ - public static DateBetween create(Date begin, Date end, boolean isAbs) { - return new DateBetween(begin, end, isAbs); - } - - /** - * 构造
- * 在前的日期做为起始时间,在后的做为结束时间,间隔只保留绝对值正数 - * - * @param begin 起始时间 - * @param end 结束时间 - */ - public DateBetween(Date begin, Date end) { - this(begin, end, true); - } - - /** - * 构造
- * 在前的日期做为起始时间,在后的做为结束时间 - * - * @param begin 起始时间 - * @param end 结束时间 - * @param isAbs 日期间隔是否只保留绝对值正数 - * @since 3.1.1 - */ - public DateBetween(Date begin, Date end, boolean isAbs) { - if (isAbs && begin.after(end)) { - // 间隔只为正数的情况下,如果开始日期晚于结束日期,置换之 - this.begin = end; - this.end = begin; - } else { - this.begin = begin; - this.end = end; - } - } - - /** - * 判断两个日期相差的时长
- * 返回 给定单位的时长差 - * - * @param unit 相差的单位:相差 天{@link DateUnit#DAY}、小时{@link DateUnit#HOUR} 等 - * @return 时长差 - */ - public long between(DateUnit unit) { - long diff = end.getTime() - begin.getTime(); - return diff / unit.getMillis(); - } - - /** - * 计算两个日期相差月数
- * 在非重置情况下,如果起始日期的天小于结束日期的天,月数要少算1(不足1个月) - * - * @param isReset 是否重置时间为起始时间(重置天时分秒) - * @return 相差月数 - * @since 3.0.8 - */ - public long betweenMonth(boolean isReset) { - final Calendar beginCal = DateUtil.calendar(begin); - final Calendar endCal = DateUtil.calendar(end); - - final int betweenYear = endCal.get(Calendar.YEAR) - beginCal.get(Calendar.YEAR); - final int betweenMonthOfYear = endCal.get(Calendar.MONTH) - beginCal.get(Calendar.MONTH); - - int result = betweenYear * 12 + betweenMonthOfYear; - if (false == isReset) { - endCal.set(Calendar.YEAR, beginCal.get(Calendar.YEAR)); - endCal.set(Calendar.MONTH, beginCal.get(Calendar.MONTH)); - long between = endCal.getTimeInMillis() - beginCal.getTimeInMillis(); - if (between < 0) { - return result - 1; - } - } - return result; - } - - /** - * 计算两个日期相差年数
- * 在非重置情况下,如果起始日期的月小于结束日期的月,年数要少算1(不足1年) - * - * @param isReset 是否重置时间为起始时间(重置月天时分秒) - * @return 相差年数 - * @since 3.0.8 - */ - public long betweenYear(boolean isReset) { - final Calendar beginCal = DateUtil.calendar(begin); - final Calendar endCal = DateUtil.calendar(end); - - int result = endCal.get(Calendar.YEAR) - beginCal.get(Calendar.YEAR); - if (false == isReset) { - endCal.set(Calendar.YEAR, beginCal.get(Calendar.YEAR)); - long between = endCal.getTimeInMillis() - beginCal.getTimeInMillis(); - if (between < 0) { - return result - 1; - } - } - return result; - } - - /** - * 格式化输出时间差
- * - * @param level 级别 - * @return 字符串 - */ - public String toString(BetweenFormater.Level level) { - return DateUtil.formatBetween(between(DateUnit.MS), level); - } - - @Override - public String toString() { - return toString(BetweenFormater.Level.MILLSECOND); - } -} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/date/DateException.java b/blade-core-tool/src/main/java/org/springblade/core/tool/date/DateException.java deleted file mode 100644 index 05faf83..0000000 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/date/DateException.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.springblade.core.tool.date; - -import org.springblade.core.tool.utils.StringUtil; - -/** - * 工具类异常 - * @author xiaoleilu - */ -public class DateException extends RuntimeException{ - private static final long serialVersionUID = 8247610319171014183L; - - public DateException(Throwable e) { - super(StringUtil.format("{}: {}", e.getClass().getSimpleName(), e.getMessage()), e); - } - - public DateException(String message) { - super(message); - } - - public DateException(String messageTemplate, Object... params) { - super(StringUtil.format(messageTemplate, params)); - } - - public DateException(String message, Throwable throwable) { - super(message, throwable); - } - - public DateException(Throwable throwable, String messageTemplate, Object... params) { - super(StringUtil.format(messageTemplate, params), throwable); - } -} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/date/DateField.java b/blade-core-tool/src/main/java/org/springblade/core/tool/date/DateField.java deleted file mode 100644 index f53f982..0000000 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/date/DateField.java +++ /dev/null @@ -1,130 +0,0 @@ -package org.springblade.core.tool.date; - -import java.util.Calendar; - -/** - * 日期各个部分的枚举
- * 与Calendar相应值对应 - * - * @author Looly - * - */ -public enum DateField { - - /** - * 年 - * @see Calendar#YEAR - */ - YEAR(Calendar.YEAR), - /** - * 月 - * @see Calendar#MONTH - */ - MONTH(Calendar.MONTH), - /** - * 一年中第几周 - * @see Calendar#WEEK_OF_YEAR - */ - WEEK_OF_YEAR(Calendar.WEEK_OF_YEAR), - /** - * 一月中第几周 - * @see Calendar#WEEK_OF_MONTH - */ - WEEK_OF_MONTH(Calendar.WEEK_OF_MONTH), - /** - * 一月中的第几天 - * @see Calendar#DAY_OF_MONTH - */ - DAY_OF_MONTH(Calendar.DAY_OF_MONTH), - /** - *一年中的第几天 - * @see Calendar#DAY_OF_YEAR - */ - DAY_OF_YEAR(Calendar.DAY_OF_YEAR), - /** - *周几,1表示周日,2表示周一 - * @see Calendar#DAY_OF_WEEK - */ - DAY_OF_WEEK(Calendar.DAY_OF_WEEK), - /** - * 天所在的周是这个月的第几周 - * @see Calendar#DAY_OF_WEEK_IN_MONTH - */ - DAY_OF_WEEK_IN_MONTH(Calendar.DAY_OF_WEEK_IN_MONTH), - /** - * 上午或者下午 - * @see Calendar#AM_PM - */ - AM_PM(Calendar.AM_PM), - /** - * 小时,用于12小时制 - * @see Calendar#HOUR - */ - HOUR(Calendar.HOUR), - /** - * 小时,用于24小时制 - * @see Calendar#HOUR - */ - HOUR_OF_DAY(Calendar.HOUR_OF_DAY), - /** - * 分钟 - * @see Calendar#MINUTE - */ - MINUTE(Calendar.MINUTE), - /** - * 秒 - * @see Calendar#SECOND - */ - SECOND(Calendar.SECOND), - /** - * 毫秒 - * @see Calendar#MILLISECOND - */ - MILLISECOND(Calendar.MILLISECOND); - - // --------------------------------------------------------------- - private int value; - - private DateField(int value) { - this.value = value; - } - - public int getValue() { - return this.value; - } - - /** - * 将 {@link Calendar}相关值转换为DatePart枚举对象
- * - * @param calendarPartIntValue Calendar中关于Week的int值 - * @return {@link DateField} - */ - public static DateField of(int calendarPartIntValue) { - switch (calendarPartIntValue) { - case Calendar.YEAR: - return YEAR; - case Calendar.MONTH: - return MONTH; - case Calendar.WEEK_OF_YEAR: - return WEEK_OF_YEAR; - case Calendar.WEEK_OF_MONTH: - return WEEK_OF_MONTH; - case Calendar.DAY_OF_MONTH: - return DAY_OF_MONTH; - case Calendar.DAY_OF_YEAR: - return DAY_OF_YEAR; - case Calendar.DAY_OF_WEEK: - return DAY_OF_WEEK; - case Calendar.DAY_OF_WEEK_IN_MONTH: - return DAY_OF_WEEK_IN_MONTH; - case Calendar.MINUTE: - return MINUTE; - case Calendar.SECOND: - return SECOND; - case Calendar.MILLISECOND: - return MILLISECOND; - default: - return null; - } - } -} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/date/DatePattern.java b/blade-core-tool/src/main/java/org/springblade/core/tool/date/DatePattern.java deleted file mode 100644 index 24d1b76..0000000 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/date/DatePattern.java +++ /dev/null @@ -1,71 +0,0 @@ -package org.springblade.core.tool.date; - - -import org.springblade.core.tool.date.format.FastDateFormat; - -/** - * 日期格式化类,提供常用的日期格式化对象 - * - * @author Looly - * - */ -public class DatePattern { - - //-------------------------------------------------------------------------------------------------------------------------------- Normal - /** 标准日期格式:yyyy-MM-dd */ - public final static String NORM_DATE_PATTERN = "yyyy-MM-dd"; - /** 标准日期格式 {@link FastDateFormat}:yyyy-MM-dd */ - public final static FastDateFormat NORM_DATE_FORMAT = FastDateFormat.getInstance(NORM_DATE_PATTERN); - - /** 标准时间格式:HH:mm:ss */ - public final static String NORM_TIME_PATTERN = "HH:mm:ss"; - /** 标准时间格式 {@link FastDateFormat}:HH:mm:ss */ - public final static FastDateFormat NORM_TIME_FORMAT = FastDateFormat.getInstance(NORM_TIME_PATTERN); - - /** 标准日期时间格式,精确到分:yyyy-MM-dd HH:mm */ - public final static String NORM_DATETIME_MINUTE_PATTERN = "yyyy-MM-dd HH:mm"; - /** 标准日期时间格式,精确到分 {@link FastDateFormat}:yyyy-MM-dd HH:mm */ - public final static FastDateFormat NORM_DATETIME_MINUTE_FORMAT = FastDateFormat.getInstance(NORM_DATETIME_MINUTE_PATTERN); - - /** 标准日期时间格式,精确到秒:yyyy-MM-dd HH:mm:ss */ - public final static String NORM_DATETIME_PATTERN = "yyyy-MM-dd HH:mm:ss"; - /** 标准日期时间格式,精确到秒 {@link FastDateFormat}:yyyy-MM-dd HH:mm:ss */ - public final static FastDateFormat NORM_DATETIME_FORMAT = FastDateFormat.getInstance(NORM_DATETIME_PATTERN); - - /** 标准日期时间格式,精确到毫秒:yyyy-MM-dd HH:mm:ss.SSS */ - public final static String NORM_DATETIME_MS_PATTERN = "yyyy-MM-dd HH:mm:ss.SSS"; - /** 标准日期时间格式,精确到毫秒 {@link FastDateFormat}:yyyy-MM-dd HH:mm:ss.SSS */ - public final static FastDateFormat NORM_DATETIME_MS_FORMAT = FastDateFormat.getInstance(NORM_DATETIME_MS_PATTERN); - - //-------------------------------------------------------------------------------------------------------------------------------- Pure - /** 标准日期格式:yyyyMMdd */ - public final static String PURE_DATE_PATTERN = "yyyyMMdd"; - /** 标准日期格式 {@link FastDateFormat}:yyyyMMdd */ - public final static FastDateFormat PURE_DATE_FORMAT = FastDateFormat.getInstance(PURE_DATE_PATTERN); - - /** 标准日期格式:HHmmss */ - public final static String PURE_TIME_PATTERN = "HHmmss"; - /** 标准日期格式 {@link FastDateFormat}:HHmmss */ - public final static FastDateFormat PURE_TIME_FORMAT = FastDateFormat.getInstance(PURE_TIME_PATTERN); - - /** 标准日期格式:yyyyMMddHHmmss */ - public final static String PURE_DATETIME_PATTERN = "yyyyMMddHHmmss"; - /** 标准日期格式 {@link FastDateFormat}:yyyyMMddHHmmss */ - public final static FastDateFormat PURE_DATETIME_FORMAT = FastDateFormat.getInstance(PURE_DATETIME_PATTERN); - - /** 标准日期格式:yyyyMMddHHmmssSSS */ - public final static String PURE_DATETIME_MS_PATTERN = "yyyyMMddHHmmssSSS"; - /** 标准日期格式 {@link FastDateFormat}:yyyyMMddHHmmssSSS */ - public final static FastDateFormat PURE_DATETIME_MS_FORMAT = FastDateFormat.getInstance(PURE_DATETIME_MS_PATTERN); - - //-------------------------------------------------------------------------------------------------------------------------------- Others - /** HTTP头中日期时间格式:EEE, dd MMM yyyy HH:mm:ss z */ - public final static String HTTP_DATETIME_PATTERN = "EEE, dd MMM yyyy HH:mm:ss z"; - /** HTTP头中日期时间格式 {@link FastDateFormat}:EEE, dd MMM yyyy HH:mm:ss z */ - public final static FastDateFormat HTTP_DATETIME_FORMAT = FastDateFormat.getInstance(HTTP_DATETIME_PATTERN); - - /** HTTP头中日期时间格式:EEE MMM dd HH:mm:ss zzz yyyy */ - public final static String JDK_DATETIME_PATTERN = "EEE MMM dd HH:mm:ss zzz yyyy"; - /** HTTP头中日期时间格式 {@link FastDateFormat}:EEE MMM dd HH:mm:ss zzz yyyy */ - public final static FastDateFormat JDK_DATETIME_FORMAT = FastDateFormat.getInstance(JDK_DATETIME_PATTERN); -} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/date/DateTime.java b/blade-core-tool/src/main/java/org/springblade/core/tool/date/DateTime.java deleted file mode 100644 index 0190362..0000000 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/date/DateTime.java +++ /dev/null @@ -1,753 +0,0 @@ -package org.springblade.core.tool.date; - -import org.springblade.core.tool.date.format.DateParser; -import org.springblade.core.tool.date.format.DatePrinter; -import org.springblade.core.tool.date.format.FastDateFormat; -import org.springblade.core.tool.utils.Func; -import org.springblade.core.tool.utils.StringUtil; -import org.springframework.util.Assert; - -import java.sql.Timestamp; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Calendar; -import java.util.Date; -import java.util.Locale; -import java.util.TimeZone; - - -/** - * 包装java.util.Date - * - * @author xiaoleilu - * - */ -public class DateTime extends Date { - private static final long serialVersionUID = -5395712593979185936L; - - /** 是否可变对象 */ - private boolean mutable = true; - /** 一周的第一天,默认是周一, 在设置或获得 WEEK_OF_MONTH 或 WEEK_OF_YEAR 字段时,Calendar 必须确定一个月或一年的第一个星期,以此作为参考点。 */ - private Week firstDayOfWeek = Week.MONDAY; - - /** - * 转换JDK date为 DateTime - * - * @param date JDK Date - * @return DateTime - */ - public static DateTime of(Date date) { - if(date instanceof DateTime) { - return (DateTime)date; - } - return new DateTime(date); - } - - /** - * 转换 {@link Calendar} 为 DateTime - * - * @param calendar {@link Calendar} - * @return DateTime - */ - public static DateTime of(Calendar calendar) { - return new DateTime(calendar); - } - - /** - * 构造 - * - * @see DatePattern - * @param dateStr Date字符串 - * @param format 格式 - * @return {@link DateTime} - */ - public static DateTime of(String dateStr, String format) { - return new DateTime(dateStr, format); - } - - /** - * 现在的时间 - * - * @return 现在的时间 - */ - public static DateTime now() { - return new DateTime(); - } - - // -------------------------------------------------------------------- Constructor start - /** - * 当前时间 - */ - public DateTime() { - super(); - } - - /** - * 给定日期的构造 - * - * @param date 日期 - */ - public DateTime(Date date) { - this(date.getTime()); - } - - /** - * 给定日期的构造 - * - * @param calendar {@link Calendar} - */ - public DateTime(Calendar calendar) { - this(calendar.getTime()); - } - - /** - * 给定日期毫秒数的构造 - * - * @param timeMillis 日期毫秒数 - */ - public DateTime(long timeMillis) { - super(timeMillis); - } - - /** - * 构造 - * - * @see DatePattern - * @param dateStr Date字符串 - * @param format 格式 - */ - public DateTime(String dateStr, String format) { - this(dateStr, new SimpleDateFormat(format)); - } - - /** - * 构造 - * - * @see DatePattern - * @param dateStr Date字符串 - * @param dateFormat 格式化器 {@link SimpleDateFormat} - */ - public DateTime(String dateStr, DateFormat dateFormat) { - this(parse(dateStr, dateFormat)); - } - - /** - * 构造 - * - * @see DatePattern - * @param dateStr Date字符串 - * @param dateParser 格式化器 {@link DateParser},可以使用 {@link FastDateFormat} - */ - public DateTime(String dateStr, DateParser dateParser) { - this(parse(dateStr, dateParser)); - } - - // -------------------------------------------------------------------- Constructor end - - // -------------------------------------------------------------------- offset start - /** - * 调整日期和时间
- * 如果此对象为可变对象,返回自身,否则返回新对象,设置是否可变对象见{@link #setMutable(boolean)} - * - * @param datePart 调整的部分 {@link DateField} - * @param offset 偏移量,正数为向后偏移,负数为向前偏移 - * @return 如果此对象为可变对象,返回自身,否则返回新对象 - */ - public DateTime offset(DateField datePart, int offset) { - final Calendar cal = toCalendar(); - cal.add(datePart.getValue(), offset); - - DateTime dt = mutable ? this : Func.clone(this); - return dt.setTimeInternal(cal.getTimeInMillis()); - } - - /** - * 调整日期和时间
- * 返回调整后的新{@link DateTime},不影响原对象 - * - * @param datePart 调整的部分 {@link DateField} - * @param offset 偏移量,正数为向后偏移,负数为向前偏移 - * @return 如果此对象为可变对象,返回自身,否则返回新对象 - * @since 3.0.9 - */ - public DateTime offsetNew(DateField datePart, int offset) { - final Calendar cal = toCalendar(); - cal.add(datePart.getValue(), offset); - - DateTime dt = Func.clone(this); - return dt.setTimeInternal(cal.getTimeInMillis()); - } - // -------------------------------------------------------------------- offset end - - // -------------------------------------------------------------------- Part of Date start - /** - * 获得日期的某个部分
- * 例如获得年的部分,则使用 getField(DatePart.YEAR) - * - * @param field 表示日期的哪个部分的枚举 {@link DateField} - * @return 某个部分的值 - */ - public int getField(DateField field) { - return getField(field.getValue()); - } - - /** - * 获得日期的某个部分
- * 例如获得年的部分,则使用 getField(Calendar.YEAR) - * - * @param field 表示日期的哪个部分的int值 {@link Calendar} - * @return 某个部分的值 - */ - public int getField(int field) { - return toCalendar().get(field); - } - - /** - * 设置日期的某个部分
- * 如果此对象为可变对象,返回自身,否则返回新对象,设置是否可变对象见{@link #setMutable(boolean)} - * - * @param field 表示日期的哪个部分的枚举 {@link DateField} - * @param value 值 - * @return {@link DateTime} - */ - public DateTime setField(DateField field, int value) { - return setField(field.getValue(), value); - } - - /** - * 设置日期的某个部分
- * 如果此对象为可变对象,返回自身,否则返回新对象,设置是否可变对象见{@link #setMutable(boolean)} - * - * @param field 表示日期的哪个部分的int值 {@link Calendar} - * @param value 值 - * @return {@link DateTime} - */ - public DateTime setField(int field, int value) { - Calendar calendar = toCalendar(); - calendar.set(field, value); - - DateTime dt = this; - if (false == mutable) { - dt = Func.clone(this); - } - return dt.setTimeInternal(calendar.getTimeInMillis()); - } - - @Override - public void setTime(long time) { - if (mutable) { - super.setTime(time); - } else { - throw new DateException("This is not a mutable object !"); - } - } - - /** - * 获得年的部分 - * - * @return 年的部分 - */ - public int year() { - return getField(DateField.YEAR); - } - - /** - * 获得当前日期所属季度
- * 1:第一季度
- * 2:第二季度
- * 3:第三季度
- * 4:第四季度
- * - * @return 第几个季度 - */ - public int season() { - return monthStartFromOne() / 4 + 1; - } - - /** - * 获得当前日期所属季度
- * - * @return 第几个季度 {@link Season} - */ - public Season seasonEnum() { - return Season.of(season()); - } - - /** - * 获得月份,从0开始计数 - * - * @return 月份 - */ - public int month() { - return getField(DateField.MONTH); - } - - /** - * 获得月份,从1开始计数
- * 由于{@link Calendar} 中的月份按照0开始计数,导致某些需求容易误解,因此如果想用1表示一月,2表示二月则调用此方法 - * - * @return 月份 - */ - public int monthStartFromOne() { - return month() + 1; - } - - /** - * 获得月份 - * - * @return {@link Month} - */ - public Month monthEnum() { - return Month.of(month()); - } - - /** - * 获得指定日期是所在年份的第几周
- * 此方法返回值与一周的第一天有关,比如:
- * 2016年1月3日为周日,如果一周的第一天为周日,那这天是第二周(返回2)
- * 如果一周的第一天为周一,那这天是第一周(返回1) - * - * @return 周 - * @see #setFirstDayOfWeek(Week) - */ - public int weekOfYear() { - return getField(DateField.WEEK_OF_YEAR); - } - - /** - * 获得指定日期是所在月份的第几周
- * 此方法返回值与一周的第一天有关,比如:
- * 2016年1月3日为周日,如果一周的第一天为周日,那这天是第二周(返回2)
- * 如果一周的第一天为周一,那这天是第一周(返回1) - * - * @return 周 - * @see #setFirstDayOfWeek(Week) - */ - public int weekOfMonth() { - return getField(DateField.WEEK_OF_MONTH); - } - - /** - * 获得指定日期是这个日期所在月份的第几天
- * - * @return 天 - */ - public int dayOfMonth() { - return getField(DateField.DAY_OF_MONTH); - } - - /** - * 获得指定日期是星期几,1表示周日,2表示周一 - * - * @return 星期几 - */ - public int dayOfWeek() { - return getField(DateField.DAY_OF_WEEK); - } - - /** - * 获得天所在的周是这个月的第几周 - * - * @return 天 - */ - public int dayOfWeekInMonth() { - return getField(DateField.DAY_OF_WEEK_IN_MONTH); - } - - /** - * 获得指定日期是星期几 - * - * @return {@link Week} - */ - public Week dayOfWeekEnum() { - return Week.of(dayOfWeek()); - } - - /** - * 获得指定日期的小时数部分
- * - * @param is24HourClock 是否24小时制 - * @return 小时数 - */ - public int hour(boolean is24HourClock) { - return getField(is24HourClock ? DateField.HOUR_OF_DAY : DateField.HOUR); - } - - /** - * 获得指定日期的分钟数部分
- * 例如:10:04:15.250 =》 4 - * - * @return 分钟数 - */ - public int minute() { - return getField(DateField.MINUTE); - } - - /** - * 获得指定日期的秒数部分
- * - * @return 秒数 - */ - public int second() { - return getField(DateField.SECOND); - } - - /** - * 获得指定日期的毫秒数部分
- * - * @return 毫秒数 - */ - public int millsecond() { - return getField(DateField.MILLISECOND); - } - - /** - * 是否为上午 - * - * @return 是否为上午 - */ - public boolean isAM() { - return Calendar.AM == getField(DateField.AM_PM); - } - - /** - * 是否为下午 - * - * @return 是否为下午 - */ - public boolean isPM() { - return Calendar.PM == getField(DateField.AM_PM); - } - // -------------------------------------------------------------------- Part of Date end - - /** - * 是否闰年 - * - * @see DateUtil#isLeapYear(int) - * @return 是否闰年 - */ - public boolean isLeapYear() { - return DateUtil.isLeapYear(year()); - } - - /** - * 转换为Calendar,默认{@link TimeZone},默认 {@link Locale} - * - * @return {@link Calendar} - */ - public Calendar toCalendar() { - final Calendar cal = Calendar.getInstance(); - cal.setFirstDayOfWeek(firstDayOfWeek.getValue()); - cal.setTime(this); - return cal; - } - - /** - * 转换为Calendar - * - * @param locale 地域 {@link Locale} - * @return {@link Calendar} - */ - public Calendar toCalendar(Locale locale) { - final Calendar cal = Calendar.getInstance(locale); - cal.setFirstDayOfWeek(firstDayOfWeek.getValue()); - cal.setTime(this); - return cal; - } - - /** - * 转换为Calendar - * - * @param zone 时区 {@link TimeZone} - * @return {@link Calendar} - */ - public Calendar toCalendar(TimeZone zone) { - return toCalendar(zone, Locale.getDefault(Locale.Category.FORMAT)); - } - - /** - * 转换为Calendar - * - * @param zone 时区 {@link TimeZone} - * @param locale 地域 {@link Locale} - * @return {@link Calendar} - */ - public Calendar toCalendar(TimeZone zone, Locale locale) { - final Calendar cal = Calendar.getInstance(zone, locale); - cal.setFirstDayOfWeek(firstDayOfWeek.getValue()); - cal.setTime(this); - return cal; - } - - /** - * 转换为 {@link Date}
- * 考虑到很多框架(例如Hibernate)的兼容性,提供此方法返回JDK原生的Date对象 - * - * @return {@link Date} - * @since 3.2.2 - */ - public Date toJdkDate() { - return new Date(this.getTime()); - } - - /** - * 转为{@link Timestamp} - * - * @return {@link Timestamp} - */ - public Timestamp toTimestamp() { - return new Timestamp(this.getTime()); - } - - /** - * 转为 {@link java.sql.Date} - * - * @return {@link java.sql.Date} - */ - public java.sql.Date toSqlDate() { - return new java.sql.Date(getTime()); - } - - /** - * 计算相差时长 - * - * @param date 对比的日期 - * @return {@link DateBetween} - */ - public DateBetween between(Date date) { - return new DateBetween(this, date); - } - - /** - * 计算相差时长 - * - * @param date 对比的日期 - * @param unit 单位 {@link DateUnit} - * @return 相差时长 - */ - public long between(Date date, DateUnit unit) { - return new DateBetween(this, date).between(unit); - } - - /** - * 计算相差时长 - * - * @param date 对比的日期 - * @param unit 单位 {@link DateUnit} - * @param formatLevel 格式化级别 - * @return 相差时长 - */ - public String between(Date date, DateUnit unit, BetweenFormater.Level formatLevel) { - return new DateBetween(this, date).toString(formatLevel); - } - - /** - * 当前日期是否在日期指定范围内
- * 起始日期和结束日期可以互换 - * - * @param beginDate 起始日期 - * @param endDate 结束日期 - * @return 是否在范围内 - * @since 3.0.8 - */ - public boolean isIn(Date beginDate, Date endDate) { - long beginMills = beginDate.getTime(); - long endMills = endDate.getTime(); - long thisMills = this.getTime(); - - return thisMills >= Math.min(beginMills, endMills) && thisMills <= Math.max(beginMills, endMills); - } - - /** - * 是否在给定日期之前或与给定日期相等 - * - * @param date 日期 - * @return 是否在给定日期之前或与给定日期相等 - * @since 3.0.9 - */ - public boolean isBeforeOrEquals(Date date) { - if (null == date) { - throw new NullPointerException("Date to compare is null !"); - } - return compareTo(date) <= 0; - } - - /** - * 是否在给定日期之后或与给定日期相等 - * - * @param date 日期 - * @return 是否在给定日期之后或与给定日期相等 - * @since 3.0.9 - */ - public boolean isAfterOrEquals(Date date) { - if (null == date) { - throw new NullPointerException("Date to compare is null !"); - } - return compareTo(date) >= 0; - } - - /** - * 对象是否可变
- * 如果为不可变对象,以下方法将返回新方法: - *

    - *
  • {@link DateTime#offset(DateField, int)}
  • - *
  • {@link DateTime#setField(DateField, int)}
  • - *
  • {@link DateTime#setField(int, int)}
  • - *
- * 如果为不可变对象,{@link DateTime#setTime(long)}将抛出异常 - * - * @return 对象是否可变 - */ - public boolean isMutable() { - return mutable; - } - - /** - * 设置对象是否可变 如果为不可变对象,以下方法将返回新方法: - *
    - *
  • {@link DateTime#offset(DateField, int)}
  • - *
  • {@link DateTime#setField(DateField, int)}
  • - *
  • {@link DateTime#setField(int, int)}
  • - *
- * 如果为不可变对象,{@link DateTime#setTime(long)}将抛出异常 - * - * @param mutable 是否可变 - * @return this - */ - public DateTime setMutable(boolean mutable) { - this.mutable = mutable; - return this; - } - - /** - * 获得一周的第一天,默认为周一 - * - * @return 一周的第一天 - */ - public Week getFirstDayOfWeek() { - return firstDayOfWeek; - } - - /** - * 设置一周的第一天
- * JDK的Calendar中默认一周的第一天是周日,Hutool中将此默认值设置为周一
- * 设置一周的第一天主要影响{@link #weekOfMonth()}和{@link #weekOfYear()} 两个方法 - * - * @param firstDayOfWeek 一周的第一天 - * @return this - * @see #weekOfMonth() - * @see #weekOfYear() - */ - public DateTime setFirstDayOfWeek(Week firstDayOfWeek) { - this.firstDayOfWeek = firstDayOfWeek; - return this; - } - - // -------------------------------------------------------------------- toString start - /** - * 转为"yyyy-MM-dd yyyy-MM-dd HH:mm:ss " 格式字符串 - * - * @return "yyyy-MM-dd yyyy-MM-dd HH:mm:ss " 格式字符串 - */ - @Override - public String toString() { - return toString(DatePattern.NORM_DATETIME_FORMAT); - } - - /** - * 转为"yyyy-MM-dd " 格式字符串 - * - * @return "yyyy-MM-dd " 格式字符串 - * @since 4.0.0 - */ - public String toDateStr() { - return toString(DatePattern.NORM_DATE_PATTERN); - } - - /** - * 转为字符串 - * - * @param format 日期格式,常用格式见: {@link DatePattern} - * @return String - */ - public String toString(String format) { - return toString(FastDateFormat.getInstance(format)); - } - - /** - * 转为字符串 - * - * @param format {@link DatePrinter} 或 {@link FastDateFormat} - * @return String - */ - public String toString(DatePrinter format) { - return format.format(this); - } - - /** - * 转为字符串 - * - * @param format {@link SimpleDateFormat} - * @return String - */ - public String toString(DateFormat format) { - return format.format(this); - } - - /** - * @return 输出精确到毫秒的标准日期形式 - */ - public String toMsStr() { - return toString(DatePattern.NORM_DATETIME_MS_FORMAT); - } - // -------------------------------------------------------------------- toString end - - /** - * 转换字符串为Date - * - * @param dateStr 日期字符串 - * @param dateFormat {@link SimpleDateFormat} - * @return {@link Date} - */ - private static Date parse(String dateStr, DateFormat dateFormat) { - try { - return dateFormat.parse(dateStr); - } catch (Exception e) { - String pattern; - if (dateFormat instanceof SimpleDateFormat) { - pattern = ((SimpleDateFormat) dateFormat).toPattern(); - } else { - pattern = dateFormat.toString(); - } - throw new DateException(StringUtil.format("Parse [{}] with format [{}] error!", dateStr, pattern), e); - } - } - - /** - * 转换字符串为Date - * - * @param dateStr 日期字符串 - * @param parser {@link FastDateFormat} - * @return {@link Date} - */ - private static Date parse(String dateStr, DateParser parser) { - Assert.notNull(parser, "Parser or DateFromat must be not null !"); - //Assert.notBlank(dateStr, "Date String must be not blank !"); - try { - return parser.parse(dateStr); - } catch (Exception e) { - throw new DateException("Parse [{}] with format [{}] error!", dateStr, parser.getPattern(), e); - } - } - - /** - * 设置日期时间 - * - * @param time 日期时间毫秒 - * @return this - */ - private DateTime setTimeInternal(long time) { - super.setTime(time); - return this; - } -} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/date/DateUnit.java b/blade-core-tool/src/main/java/org/springblade/core/tool/date/DateUnit.java deleted file mode 100644 index 1fd507e..0000000 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/date/DateUnit.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.springblade.core.tool.date; - -/** - * 日期时间单位,每个单位都是以毫秒为基数 - * @author Looly - * - */ -public enum DateUnit { - /** 一毫秒 */ - MS(1), - /** 一秒的毫秒数 */ - SECOND(1000), - /**一分钟的毫秒数 */ - MINUTE(SECOND.getMillis() * 60), - /**一小时的毫秒数 */ - HOUR(MINUTE.getMillis() * 60), - /**一天的毫秒数 */ - DAY(HOUR.getMillis() * 24), - /**一周的毫秒数 */ - WEEK(DAY.getMillis() * 7); - - private long millis; - DateUnit(long millis){ - this.millis = millis; - } - - /** - * @return 单位对应的毫秒数 - */ - public long getMillis(){ - return this.millis; - } -} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/date/DateUtil.java b/blade-core-tool/src/main/java/org/springblade/core/tool/date/DateUtil.java deleted file mode 100644 index b37d6c4..0000000 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/date/DateUtil.java +++ /dev/null @@ -1,1471 +0,0 @@ -package org.springblade.core.tool.date; - -import org.springblade.core.tool.date.format.DateParser; -import org.springblade.core.tool.date.format.DatePrinter; -import org.springblade.core.tool.date.format.FastDateFormat; -import org.springblade.core.tool.utils.Func; -import org.springblade.core.tool.utils.Exceptions; -import org.springblade.core.tool.utils.StringPool; -import org.springblade.core.tool.utils.StringUtil; - -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.*; - -/** - * 时间工具类 - * - * @author xiaoleilu - */ -public class DateUtil { - - /** - * 转换为{@link DateTime}对象 - * - * @return 当前时间 - */ - public static DateTime date() { - return new DateTime(); - } - - /** - * {@link Date}类型时间转为{@link DateTime} - * - * @param date Long类型Date(Unix时间戳) - * @return 时间对象 - * @since 3.0.7 - */ - public static DateTime date(Date date) { - if (date instanceof DateTime) { - return (DateTime) date; - } - return new DateTime(date); - } - - /** - * Long类型时间转为{@link DateTime}
- * 同时支持10位秒级别时间戳和13位毫秒级别时间戳 - * - * @param date Long类型Date(Unix时间戳) - * @return 时间对象 - */ - public static DateTime date(long date) { - return new DateTime(date); - } - - /** - * {@link Calendar}类型时间转为{@link DateTime} - * - * @param calendar {@link Calendar} - * @return 时间对象 - */ - public static DateTime date(Calendar calendar) { - return new DateTime(calendar); - } - - /** - * 转换为Calendar对象 - * - * @param date 日期对象 - * @return Calendar对象 - */ - public static Calendar calendar(Date date) { - return calendar(date.getTime()); - } - - /** - * 转换为Calendar对象 - * - * @param millis 时间戳 - * @return Calendar对象 - */ - public static Calendar calendar(long millis) { - final Calendar cal = Calendar.getInstance(); - cal.setTimeInMillis(millis); - return cal; - } - - /** - * 当前时间,格式 yyyy-MM-dd HH:mm:ss - * - * @return 当前时间的标准形式字符串 - */ - public static String now() { - return formatDateTime(new DateTime()); - } - - /** - * 当前时间long - * - * @param isNano 是否为高精度时间 - * @return 时间 - */ - public static long current(boolean isNano) { - return isNano ? System.nanoTime() : System.currentTimeMillis(); - } - - /** - * 当前时间秒数 - * - * @return 当前时间秒数 - * @since 4.0.0 - */ - public static long currentSeconds() { - return System.currentTimeMillis() / 1000; - } - - /** - * 当前日期,格式 yyyy-MM-dd - * - * @return 当前日期的标准形式字符串 - */ - public static String today() { - return formatDate(new DateTime()); - } - - // -------------------------------------------------------------- Part of Date start - /** - * 获得年的部分 - * - * @param date 日期 - * @return 年的部分 - */ - public static int year(Date date) { - return DateTime.of(date).year(); - } - - /** - * 获得指定日期所属季节 - * - * @param date 日期 - * @return 第几个季节 - */ - public static int season(Date date) { - return DateTime.of(date).season(); - } - - /** - * 获得月份,从0开始计数 - * - * @param date 日期 - * @return 月份,从0开始计数 - */ - public static int month(Date date) { - return DateTime.of(date).month(); - } - - /** - * 获得月份 - * - * @param date 日期 - * @return {@link Month} - */ - public static Month monthEnum(Date date) { - return DateTime.of(date).monthEnum(); - } - - /** - * 获得指定日期是所在年份的第几周
- * - * @param date 日期 - * @return 周 - */ - public static int weekOfYear(Date date) { - return DateTime.of(date).weekOfYear(); - } - - /** - * 获得指定日期是所在月份的第几周
- * - * @param date 日期 - * @return 周 - */ - public static int weekOfMonth(Date date) { - return DateTime.of(date).weekOfMonth(); - } - - /** - * 获得指定日期是这个日期所在月份的第几天
- * - * @param date 日期 - * @return 天 - */ - public static int dayOfMonth(Date date) { - return DateTime.of(date).dayOfMonth(); - } - - /** - * 获得指定日期是星期几,1表示周日,2表示周一 - * - * @param date 日期 - * @return 天 - */ - public static int dayOfWeek(Date date) { - return DateTime.of(date).dayOfWeek(); - } - - /** - * 获得指定日期是星期几 - * - * @param date 日期 - * @return {@link Week} - */ - public static Week dayOfWeekEnum(Date date) { - return DateTime.of(date).dayOfWeekEnum(); - } - - /** - * 获得指定日期的小时数部分
- * - * @param date 日期 - * @param is24HourClock 是否24小时制 - * @return 小时数 - */ - public static int hour(Date date, boolean is24HourClock) { - return DateTime.of(date).hour(is24HourClock); - } - - /** - * 获得指定日期的分钟数部分
- * 例如:10:04:15.250 =》 4 - * - * @param date 日期 - * @return 分钟数 - */ - public static int minute(Date date) { - return DateTime.of(date).minute(); - } - - /** - * 获得指定日期的秒数部分
- * - * @param date 日期 - * @return 秒数 - */ - public static int second(Date date) { - return DateTime.of(date).second(); - } - - /** - * 获得指定日期的毫秒数部分
- * - * @param date 日期 - * @return 毫秒数 - */ - public static int millsecond(Date date) { - return DateTime.of(date).millsecond(); - } - - /** - * 是否为上午 - * - * @param date 日期 - * @return 是否为上午 - */ - public static boolean isAM(Date date) { - return DateTime.of(date).isAM(); - } - - /** - * 是否为下午 - * - * @param date 日期 - * @return 是否为下午 - */ - public static boolean isPM(Date date) { - return DateTime.of(date).isPM(); - } - - /** - * @return 今年 - */ - public static int thisYear() { - return year(date()); - } - - /** - * @return 当前月份 - */ - public static int thisMonth() { - return month(date()); - } - - /** - * @return 当前月份 {@link Month} - */ - public static Month thisMonthEnum() { - return monthEnum(date()); - } - - /** - * @return 当前日期所在年份的第几周 - */ - public static int thisWeekOfYear() { - return weekOfYear(date()); - } - - /** - * @return 当前日期所在年份的第几周 - */ - public static int thisWeekOfMonth() { - return weekOfMonth(date()); - } - - /** - * @return 当前日期是这个日期所在月份的第几天 - */ - public static int thisDayOfMonth() { - return dayOfMonth(date()); - } - - /** - * @return 当前日期是星期几 - */ - public static int thisDayOfWeek() { - return dayOfWeek(date()); - } - - /** - * @return 当前日期是星期几 {@link Week} - */ - public static Week thisDayOfWeekEnum() { - return dayOfWeekEnum(date()); - } - - /** - * @param is24HourClock 是否24小时制 - * @return 当前日期的小时数部分
- */ - public static int thisHour(boolean is24HourClock) { - return hour(date(), is24HourClock); - } - - /** - * @return 当前日期的分钟数部分
- */ - public static int thisMinute() { - return minute(date()); - } - - /** - * @return 当前日期的秒数部分
- */ - public static int thisSecond() { - return second(date()); - } - - /** - * @return 当前日期的毫秒数部分
- */ - public static int thisMillsecond() { - return millsecond(date()); - } - // -------------------------------------------------------------- Part of Date end - - /** - * 获得指定日期年份和季节
- * 格式:[20131]表示2013年第一季度 - * - * @param date 日期 - * @return Season ,类似于 20132 - */ - public static String yearAndSeason(Date date) { - return yearAndSeason(calendar(date)); - } - - /** - * 获得指定日期区间内的年份和季节
- * - * @param startDate 起始日期(包含) - * @param endDate 结束日期(包含) - * @return Season列表 ,元素类似于 20132 - */ - public static LinkedHashSet yearAndSeasons(Date startDate, Date endDate) { - final LinkedHashSet seasons = new LinkedHashSet(); - if (startDate == null || endDate == null) { - return seasons; - } - - final Calendar cal = Calendar.getInstance(); - cal.setTime(startDate); - while (true) { - // 如果开始时间超出结束时间,让结束时间为开始时间,处理完后结束循环 - if (startDate.after(endDate)) { - startDate = endDate; - } - - seasons.add(yearAndSeason(cal)); - - if (startDate.equals(endDate)) { - break; - } - - cal.add(Calendar.MONTH, 3); - startDate = cal.getTime(); - } - - return seasons; - } - - // ------------------------------------ Format start ---------------------------------------------- - /** - * 根据特定格式格式化日期 - * - * @param date 被格式化的日期 - * @param format 日期格式,常用格式见: {@link DatePattern} - * @return 格式化后的字符串 - */ - public static String format(Date date, String format) { - if(null == date || StringUtil.isBlank(format)) { - return null; - } - return format(date, FastDateFormat.getInstance(format)); - } - - /** - * 根据特定格式格式化日期 - * - * @param date 被格式化的日期 - * @param format {@link DatePrinter} 或 {@link FastDateFormat} - * @return 格式化后的字符串 - */ - public static String format(Date date, DatePrinter format) { - if(null == format || null == date) { - return null; - } - return format.format(date); - } - - /** - * 根据特定格式格式化日期 - * - * @param date 被格式化的日期 - * @param format {@link SimpleDateFormat} - * @return 格式化后的字符串 - */ - public static String format(Date date, DateFormat format) { - if(null == format || null == date) { - return null; - } - return format.format(date); - } - - /** - * 格式化日期时间
- * 格式 yyyy-MM-dd HH:mm:ss - * - * @param date 被格式化的日期 - * @return 格式化后的日期 - */ - public static String formatDateTime(Date date) { - if (null == date) { - return null; - } - return DatePattern.NORM_DATETIME_FORMAT.format(date); - } - - /** - * 格式化日期部分(不包括时间)
- * 格式 yyyy-MM-dd - * - * @param date 被格式化的日期 - * @return 格式化后的字符串 - */ - public static String formatDate(Date date) { - if (null == date) { - return null; - } - return DatePattern.NORM_DATE_FORMAT.format(date); - } - - /** - * 格式化时间
- * 格式 HH:mm:ss - * - * @param date 被格式化的日期 - * @return 格式化后的字符串 - * @since 3.0.1 - */ - public static String formatTime(Date date) { - if (null == date) { - return null; - } - return DatePattern.NORM_TIME_FORMAT.format(date); - } - - /** - * 格式化为Http的标准日期格式 - * - * @param date 被格式化的日期 - * @return HTTP标准形式日期字符串 - */ - public static String formatHttpDate(Date date) { - if (null == date) { - return null; - } - return DatePattern.HTTP_DATETIME_FORMAT.format(date); - } - // ------------------------------------ Format end ---------------------------------------------- - - // ------------------------------------ Parse start ---------------------------------------------- - - /** - * 构建DateTime对象 - * - * @param dateStr Date字符串 - * @param dateFormat 格式化器 {@link SimpleDateFormat} - * @return DateTime对象 - */ - public static DateTime parse(String dateStr, DateFormat dateFormat) { - return new DateTime(dateStr, dateFormat); - } - - /** - * 构建DateTime对象 - * - * @param dateStr Date字符串 - * @param parser 格式化器,{@link FastDateFormat} - * @return DateTime对象 - */ - public static DateTime parse(String dateStr, DateParser parser) { - return new DateTime(dateStr, parser); - } - - /** - * 将特定格式的日期转换为Date对象 - * - * @param dateStr 特定格式的日期 - * @param format 格式,例如yyyy-MM-dd - * @return 日期对象 - */ - public static DateTime parse(String dateStr, String format) { - return new DateTime(dateStr, format); - } - - /** - * 将字符串转换为时间 - * - * @param dateStr 时间字符串 - * @param format ConcurrentDateFormat - * @return 时间 - */ - public static Date parse(String dateStr, ConcurrentDateFormat format) { - try { - return format.parse(dateStr); - } catch (ParseException e) { - throw Exceptions.unchecked(e); - } - } - - /** - * 格式yyyy-MM-dd HH:mm:ss - * - * @param dateString 标准形式的时间字符串 - * @return 日期对象 - */ - public static DateTime parseDateTime(String dateString) { - dateString = normalize(dateString); - return parse(dateString, DatePattern.NORM_DATETIME_FORMAT); - } - - /** - * 格式yyyy-MM-dd - * - * @param dateString 标准形式的日期字符串 - * @return 日期对象 - */ - public static DateTime parseDate(String dateString) { - dateString = normalize(dateString); - return parse(dateString, DatePattern.NORM_DATE_FORMAT); - } - - /** - * 解析时间,格式HH:mm:ss,默认为1970-01-01 - * - * @param timeString 标准形式的日期字符串 - * @return 日期对象 - */ - public static DateTime parseTime(String timeString) { - timeString = normalize(timeString); - return parse(timeString, DatePattern.NORM_TIME_FORMAT); - } - - /** - * 解析时间,格式HH:mm:ss,日期默认为今天 - * - * @param timeString 标准形式的日期字符串 - * @return 日期对象 - * @since 3.1.1 - */ - public static DateTime parseTimeToday(String timeString) { - timeString = StringUtil.format("{} {}", today(), timeString); - return parse(timeString, DatePattern.NORM_TIME_FORMAT); - } - - /** - * 将日期字符串转换为{@link DateTime}对象,格式:
- *
    - *
  1. yyyy-MM-dd HH:mm:ss
  2. - *
  3. yyyy/MM/dd HH:mm:ss
  4. - *
  5. yyyy.MM.dd HH:mm:ss
  6. - *
  7. yyyy年MM月dd日 HH时mm分ss秒
  8. - *
  9. yyyy-MM-dd
  10. - *
  11. yyyy/MM/dd
  12. - *
  13. yyyy.MM.dd
  14. - *
  15. HH:mm:ss
  16. - *
  17. HH时mm分ss秒
  18. - *
  19. yyyy-MM-dd HH:mm
  20. - *
  21. yyyy-MM-dd HH:mm:ss.SSS
  22. - *
  23. yyyyMMddHHmmss
  24. - *
  25. yyyyMMddHHmmssSSS
  26. - *
  27. yyyyMMdd
  28. - *
- * - * @param dateStr 日期字符串 - * @return 日期 - */ - public static DateTime parse(String dateStr) { - if (null == dateStr) { - return null; - } - //去掉两边空格并去掉中文日期中的“日”,以规范长度 - dateStr = dateStr.trim().replace("日", ""); - int length = dateStr.length(); - - if(Func.isNumeric(dateStr)) { - //纯数字形式 - if(length == DatePattern.PURE_DATETIME_PATTERN.length()) { - return parse(dateStr, DatePattern.PURE_DATETIME_FORMAT); - } else if(length == DatePattern.PURE_DATETIME_MS_PATTERN.length()) { - return parse(dateStr, DatePattern.PURE_DATETIME_MS_FORMAT); - } else if(length == DatePattern.PURE_DATE_PATTERN.length()) { - return parse(dateStr, DatePattern.PURE_DATE_FORMAT); - } else if(length == DatePattern.PURE_TIME_PATTERN.length()) { - return parse(dateStr, DatePattern.PURE_TIME_FORMAT); - } - } - - if (length == DatePattern.NORM_DATETIME_PATTERN.length() || length == DatePattern.NORM_DATETIME_PATTERN.length()+1) { - return parseDateTime(dateStr); - } else if (length == DatePattern.NORM_DATE_PATTERN.length()) { - return parseDate(dateStr); - } else if (length == DatePattern.NORM_TIME_PATTERN.length() || length == DatePattern.NORM_TIME_PATTERN.length()+1) { - return parseTime(dateStr); - } else if (length == DatePattern.NORM_DATETIME_MINUTE_PATTERN.length() || length == DatePattern.NORM_DATETIME_MINUTE_PATTERN.length()+1) { - return parse(normalize(dateStr), DatePattern.NORM_DATETIME_MINUTE_PATTERN); - } else if (length >= DatePattern.NORM_DATETIME_MS_PATTERN.length() - 2) { - return parse(normalize(dateStr), DatePattern.NORM_DATETIME_MS_PATTERN); - } - - // 没有更多匹配的时间格式 - throw new DateException("No format fit for date String [{}] !", dateStr); - } - - // ------------------------------------ Parse end ---------------------------------------------- - - // ------------------------------------ Offset start ---------------------------------------------- - /** - * 获取某天的开始时间 - * - * @param date 日期 - * @return {@link DateTime} - */ - public static DateTime beginOfDay(Date date) { - return new DateTime(beginOfDay(calendar(date))); - } - - /** - * 获取某天的结束时间 - * - * @param date 日期 - * @return {@link DateTime} - */ - public static DateTime endOfDay(Date date) { - return new DateTime(endOfDay(calendar(date))); - } - - /** - * 获取某天的开始时间 - * - * @param calendar 日期 {@link Calendar} - * @return {@link Calendar} - */ - public static Calendar beginOfDay(Calendar calendar) { - calendar.set(Calendar.HOUR_OF_DAY, 0); - calendar.set(Calendar.MINUTE, 0); - calendar.set(Calendar.SECOND, 0); - calendar.set(Calendar.MILLISECOND, 0); - return calendar; - } - - /** - * 获取某天的结束时间 - * - * @param calendar 日期 {@link Calendar} - * @return {@link Calendar} - */ - public static Calendar endOfDay(Calendar calendar) { - calendar.set(Calendar.HOUR_OF_DAY, 23); - calendar.set(Calendar.MINUTE, 59); - calendar.set(Calendar.SECOND, 59); - calendar.set(Calendar.MILLISECOND, 999); - return calendar; - } - - /** - * 获取某周的开始时间 - * - * @param date 日期 - * @return {@link DateTime} - */ - public static DateTime beginOfWeek(Date date) { - return new DateTime(beginOfWeek(calendar(date))); - } - - /** - * 获取某周的结束时间 - * - * @param date 日期 - * @return {@link DateTime} - */ - public static DateTime endOfWeek(Date date) { - return new DateTime(endOfWeek(calendar(date))); - } - - /** - * 获取某周的开始时间 - * - * @param calendar 日期 {@link Calendar} - * @return {@link Calendar} - */ - public static Calendar beginOfWeek(Calendar calendar) { - return beginOfWeek(calendar, true); - } - - /** - * 获取某周的开始时间,周一定为一周的开始时间 - * - * @param calendar 日期 {@link Calendar} - * @param isMondayAsFirstDay 是否周一做为一周的第一天(false表示周日做为第一天) - * @return {@link Calendar} - * @since 3.1.2 - */ - public static Calendar beginOfWeek(Calendar calendar, boolean isMondayAsFirstDay) { - if(isMondayAsFirstDay) { - //设置周一为一周开始 - calendar.setFirstDayOfWeek(Week.MONDAY.getValue()); - calendar.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY); - }else { - calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); - } - return beginOfDay(calendar); - } - - /** - * 获取某周的结束时间,周日定为一周的结束 - * - * @param calendar 日期 {@link Calendar} - * @return {@link Calendar} - */ - public static Calendar endOfWeek(Calendar calendar) { - return endOfWeek(calendar, true); - } - - /** - * 获取某周的结束时间 - * - * @param calendar 日期 {@link Calendar} - * @param isSundayAsLastDay 是否周日做为一周的最后一天(false表示周六做为最后一天) - * @return {@link Calendar} - * @since 3.1.2 - */ - public static Calendar endOfWeek(Calendar calendar, boolean isSundayAsLastDay) { - if(isSundayAsLastDay) { - //设置周一为一周开始 - calendar.setFirstDayOfWeek(Week.MONDAY.getValue()); - calendar.set(Calendar.DAY_OF_WEEK, Calendar.SUNDAY); - }else { - calendar.set(Calendar.DAY_OF_WEEK, Calendar.SATURDAY); - } - return endOfDay(calendar); - } - - /** - * 获取某月的开始时间 - * - * @param date 日期 - * @return {@link DateTime} - */ - public static DateTime beginOfMonth(Date date) { - return new DateTime(beginOfMonth(calendar(date))); - } - - /** - * 获取某月的结束时间 - * - * @param date 日期 - * @return {@link DateTime} - */ - public static DateTime endOfMonth(Date date) { - return new DateTime(endOfMonth(calendar(date))); - } - - /** - * 获取某月的开始时间 - * - * @param calendar 日期 {@link Calendar} - * @return {@link Calendar} - */ - public static Calendar beginOfMonth(Calendar calendar) { - calendar.set(Calendar.DAY_OF_MONTH, 1); - return beginOfDay(calendar); - } - - /** - * 获取某月的结束时间 - * - * @param calendar 日期 {@link Calendar} - * @return {@link Calendar} - */ - public static Calendar endOfMonth(Calendar calendar) { - calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH)); - return endOfDay(calendar); - } - - /** - * 获取某年的开始时间 - * - * @param date 日期 - * @return {@link DateTime} - */ - public static DateTime beginOfYear(Date date) { - return new DateTime(beginOfYear(calendar(date))); - } - - /** - * 获取某年的结束时间 - * - * @param date 日期 - * @return {@link DateTime} - */ - public static DateTime endOfYear(Date date) { - return new DateTime(endOfYear(calendar(date))); - } - - /** - * 获取某年的开始时间 - * - * @param calendar 日期 {@link Calendar} - * @return {@link Calendar} - */ - public static Calendar beginOfYear(Calendar calendar) { - calendar.set(Calendar.MONTH, Calendar.JANUARY); - return beginOfMonth(calendar); - } - - /** - * 获取某年的结束时间 - * - * @param calendar 日期 {@link Calendar} - * @return {@link Calendar} - */ - public static Calendar endOfYear(Calendar calendar) { - calendar.set(Calendar.MONTH, Calendar.DECEMBER); - return endOfMonth(calendar); - } - - // --------------------------------------------------- Offset for now - /** - * 昨天 - * - * @return 昨天 - */ - public static DateTime yesterday() { - return offsetDay(new DateTime(), -1); - } - - /** - * 明天 - * - * @return 明天 - * @since 3.0.1 - */ - public static DateTime tomorrow() { - return offsetDay(new DateTime(), 1); - } - - /** - * 上周 - * - * @return 上周 - */ - public static DateTime lastWeek() { - return offsetWeek(new DateTime(), -1); - } - - /** - * 下周 - * - * @return 下周 - * @since 3.0.1 - */ - public static DateTime nextWeek() { - return offsetWeek(new DateTime(), 1); - } - - /** - * 上个月 - * - * @return 上个月 - */ - public static DateTime lastMonth() { - return offsetMonth(new DateTime(), -1); - } - - /** - * 下个月 - * - * @return 下个月 - * @since 3.0.1 - */ - public static DateTime nextMonth() { - return offsetMonth(new DateTime(), 1); - } - - /** - * 偏移毫秒数 - * - * @param date 日期 - * @param offset 偏移毫秒数,正数向未来偏移,负数向历史偏移 - * @return 偏移后的日期 - */ - public static DateTime offsetMillisecond(Date date, int offset) { - return offset(date, DateField.MILLISECOND, offset); - } - - /** - * 偏移秒数 - * - * @param date 日期 - * @param offset 偏移秒数,正数向未来偏移,负数向历史偏移 - * @return 偏移后的日期 - */ - public static DateTime offsetSecond(Date date, int offset) { - return offset(date, DateField.SECOND, offset); - } - - /** - * 偏移分钟 - * - * @param date 日期 - * @param offset 偏移分钟数,正数向未来偏移,负数向历史偏移 - * @return 偏移后的日期 - */ - public static DateTime offsetMinute(Date date, int offset) { - return offset(date, DateField.MINUTE, offset); - } - - /** - * 偏移小时 - * - * @param date 日期 - * @param offset 偏移小时数,正数向未来偏移,负数向历史偏移 - * @return 偏移后的日期 - */ - public static DateTime offsetHour(Date date, int offset) { - return offset(date, DateField.HOUR_OF_DAY, offset); - } - - /** - * 偏移天 - * - * @param date 日期 - * @param offset 偏移天数,正数向未来偏移,负数向历史偏移 - * @return 偏移后的日期 - */ - public static DateTime offsetDay(Date date, int offset) { - return offset(date, DateField.DAY_OF_YEAR, offset); - } - - /** - * 偏移周 - * - * @param date 日期 - * @param offset 偏移周数,正数向未来偏移,负数向历史偏移 - * @return 偏移后的日期 - */ - public static DateTime offsetWeek(Date date, int offset) { - return offset(date, DateField.WEEK_OF_YEAR, offset); - } - - /** - * 偏移月 - * - * @param date 日期 - * @param offset 偏移月数,正数向未来偏移,负数向历史偏移 - * @return 偏移后的日期 - */ - public static DateTime offsetMonth(Date date, int offset) { - return offset(date, DateField.MONTH, offset); - } - - /** - * 获取指定日期偏移指定时间后的时间 - * - * @param date 基准日期 - * @param dateField 偏移的粒度大小(小时、天、月等){@link DateField} - * @param offset 偏移量,正数为向后偏移,负数为向前偏移 - * @return 偏移后的日期 - */ - public static DateTime offset(Date date, DateField dateField, int offset) { - Calendar cal = Calendar.getInstance(); - cal.setTime(date); - cal.add(dateField.getValue(), offset); - return new DateTime(cal.getTime()); - } - - /** - * 获取指定日期偏移指定时间后的时间 - * - * @param date 基准日期 - * @param dateField 偏移的粒度大小(小时、天、月等){@link DateField} - * @param offset 偏移量,正数为向后偏移,负数为向前偏移 - * @return 偏移后的日期 - * @deprecated please use {@link DateUtil#offset(Date, DateField, int)} - */ - @Deprecated - public static DateTime offsetDate(Date date, DateField dateField, int offset) { - return offset(date, dateField, offset); - } - // ------------------------------------ Offset end ---------------------------------------------- - - /** - * 判断两个日期相差的时长,只保留绝对值 - * - * @param beginDate 起始日期 - * @param endDate 结束日期 - * @param unit 相差的单位:相差 天{@link DateUnit#DAY}、小时{@link DateUnit#HOUR} 等 - * @return 日期差 - */ - public static long between(Date beginDate, Date endDate, DateUnit unit) { - return between(beginDate, endDate, unit, true); - } - - /** - * 判断两个日期相差的时长 - * - * @param beginDate 起始日期 - * @param endDate 结束日期 - * @param unit 相差的单位:相差 天{@link DateUnit#DAY}、小时{@link DateUnit#HOUR} 等 - * @param isAbs 日期间隔是否只保留绝对值正数 - * @return 日期差 - * @since 3.3.1 - */ - public static long between(Date beginDate, Date endDate, DateUnit unit, boolean isAbs) { - return new DateBetween(beginDate, endDate, isAbs).between(unit); - } - - /** - * 判断两个日期相差的毫秒数 - * - * @param beginDate 起始日期 - * @param endDate 结束日期 - * @return 日期差 - * @since 3.0.1 - */ - public static long betweenMs(Date beginDate, Date endDate) { - return new DateBetween(beginDate, endDate).between(DateUnit.MS); - } - - /** - * 判断两个日期相差的天数
- * - *
-	 * 有时候我们计算相差天数的时候需要忽略时分秒。
-	 * 比如:2016-02-01 23:59:59和2016-02-02 00:00:00相差一秒
-	 * 如果isReset为false相差天数为0。
-	 * 如果isReset为true相差天数将被计算为1
-	 * 
- * - * @param beginDate 起始日期 - * @param endDate 结束日期 - * @param isReset 是否重置时间为起始时间 - * @return 日期差 - * @since 3.0.1 - */ - public static long betweenDay(Date beginDate, Date endDate, boolean isReset) { - if (isReset) { - beginDate = beginOfDay(beginDate); - endDate = beginOfDay(endDate); - } - return between(beginDate, endDate, DateUnit.DAY); - } - - /** - * 计算两个日期相差月数
- * 在非重置情况下,如果起始日期的天小于结束日期的天,月数要少算1(不足1个月) - * - * @param beginDate 起始日期 - * @param endDate 结束日期 - * @param isReset 是否重置时间为起始时间(重置天时分秒) - * @return 相差月数 - * @since 3.0.8 - */ - public static long betweenMonth(Date beginDate, Date endDate, boolean isReset) { - return new DateBetween(beginDate, endDate).betweenMonth(isReset); - } - - /** - * 计算两个日期相差年数
- * 在非重置情况下,如果起始日期的月小于结束日期的月,年数要少算1(不足1年) - * - * @param beginDate 起始日期 - * @param endDate 结束日期 - * @param isReset 是否重置时间为起始时间(重置月天时分秒) - * @return 相差年数 - * @since 3.0.8 - */ - public static long betweenYear(Date beginDate, Date endDate, boolean isReset) { - return new DateBetween(beginDate, endDate).betweenYear(isReset); - } - - /** - * 格式化日期间隔输出 - * - * @param beginDate 起始日期 - * @param endDate 结束日期 - * @param level 级别,按照天、小时、分、秒、毫秒分为5个等级 - * @return XX天XX小时XX分XX秒 - */ - public static String formatBetween(Date beginDate, Date endDate, BetweenFormater.Level level) { - return formatBetween(between(beginDate, endDate, DateUnit.MS), level); - } - - /** - * 格式化日期间隔输出,精确到毫秒 - * - * @param beginDate 起始日期 - * @param endDate 结束日期 - * @return XX天XX小时XX分XX秒 - * @since 3.0.1 - */ - public static String formatBetween(Date beginDate, Date endDate) { - return formatBetween(between(beginDate, endDate, DateUnit.MS)); - } - - /** - * 格式化日期间隔输出 - * - * @param betweenMs 日期间隔 - * @param level 级别,按照天、小时、分、秒、毫秒分为5个等级 - * @return XX天XX小时XX分XX秒XX毫秒 - */ - public static String formatBetween(long betweenMs, BetweenFormater.Level level) { - return new BetweenFormater(betweenMs, level).format(); - } - - /** - * 格式化日期间隔输出,精确到毫秒 - * - * @param betweenMs 日期间隔 - * @return XX天XX小时XX分XX秒XX毫秒 - * @since 3.0.1 - */ - public static String formatBetween(long betweenMs) { - return new BetweenFormater(betweenMs, BetweenFormater.Level.MILLSECOND).format(); - } - - /** - * 当前日期是否在日期指定范围内
- * 起始日期和结束日期可以互换 - * - * @param date 被检查的日期 - * @param beginDate 起始日期 - * @param endDate 结束日期 - * @return 是否在范围内 - * @since 3.0.8 - */ - public static boolean isIn(Date date, Date beginDate, Date endDate) { - if (date instanceof DateTime) { - return ((DateTime) date).isIn(beginDate, endDate); - } else { - return new DateTime(date).isIn(beginDate, endDate); - } - } - - /** - * 计时,常用于记录某段代码的执行时间,单位:纳秒 - * - * @param preTime 之前记录的时间 - * @return 时间差,纳秒 - */ - public static long spendNt(long preTime) { - return System.nanoTime() - preTime; - } - - /** - * 计时,常用于记录某段代码的执行时间,单位:毫秒 - * - * @param preTime 之前记录的时间 - * @return 时间差,毫秒 - */ - public static long spendMs(long preTime) { - return System.currentTimeMillis() - preTime; - } - - /** - * 格式化成yyMMddHHmm后转换为int型 - * - * @param date 日期 - * @return int - */ - public static int toIntSecond(Date date) { - return Integer.parseInt(DateUtil.format(date, "yyMMddHHmm")); - } - - /** - * 计算指定指定时间区间内的周数 - * - * @param start 开始时间 - * @param end 结束时间 - * @return 周数 - */ - public static int weekCount(Date start, Date end) { - final Calendar startCalendar = Calendar.getInstance(); - startCalendar.setTime(start); - final Calendar endCalendar = Calendar.getInstance(); - endCalendar.setTime(end); - - final int startWeekofYear = startCalendar.get(Calendar.WEEK_OF_YEAR); - final int endWeekofYear = endCalendar.get(Calendar.WEEK_OF_YEAR); - - int count = endWeekofYear - startWeekofYear + 1; - - if (Calendar.SUNDAY != startCalendar.get(Calendar.DAY_OF_WEEK)) { - count--; - } - - return count; - } - - /** - * 计时器
- * 计算某个过程花费的时间,精确到毫秒 - * - * @return Timer - */ - public static TimeInterval timer() { - return new TimeInterval(); - - } - - /** - * 生日转为年龄,计算法定年龄 - * - * @param birthDay 生日,标准日期字符串 - * @return 年龄 - */ - public static int ageOfNow(String birthDay) { - return ageOfNow(parse(birthDay)); - } - - /** - * 生日转为年龄,计算法定年龄 - * - * @param birthDay 生日 - * @return 年龄 - */ - public static int ageOfNow(Date birthDay) { - return age(birthDay, date()); - } - - /** - * 计算相对于dateToCompare的年龄,长用于计算指定生日在某年的年龄 - * - * @param birthDay 生日 - * @param dateToCompare 需要对比的日期 - * @return 年龄 - */ - public static int age(Date birthDay, Date dateToCompare) { - Calendar cal = Calendar.getInstance(); - cal.setTime(dateToCompare); - - if (cal.before(birthDay)) { - throw new IllegalArgumentException(StringUtil.format("Birthday is after date {}!", formatDate(dateToCompare))); - } - - int year = cal.get(Calendar.YEAR); - int month = cal.get(Calendar.MONTH); - int dayOfMonth = cal.get(Calendar.DAY_OF_MONTH); - - cal.setTime(birthDay); - int age = year - cal.get(Calendar.YEAR); - - int monthBirth = cal.get(Calendar.MONTH); - if (month == monthBirth) { - int dayOfMonthBirth = cal.get(Calendar.DAY_OF_MONTH); - if (dayOfMonth < dayOfMonthBirth) { - // 如果生日在当月,但是未达到生日当天的日期,年龄减一 - age--; - } - } else if (month < monthBirth) { - // 如果当前月份未达到生日的月份,年龄计算减一 - age--; - } - - return age; - } - - /** - * 是否闰年 - * - * @param year 年 - * @return 是否闰年 - */ - public static boolean isLeapYear(int year) { - return new GregorianCalendar().isLeapYear(year); - } - - /** - * 判定给定开始时间经过某段时间后是否过期 - * - * @param startDate 开始时间 - * @param dateField 时间单位 - * @param timeLength 时长 - * @param checkedDate 被比较的时间。如果经过时长后的时间晚于被检查的时间,就表示过期 - * @return 是否过期 - * @since 3.1.1 - */ - public static boolean isExpired(Date startDate, DateField dateField, int timeLength, Date checkedDate) { - final Date endDate = offset(startDate, dateField, timeLength); - return endDate.after(checkedDate); - } - - /** - * 时间格式字符串转为秒数
- * 参考:https://github.com/iceroot - * - * @param timeStr 字符串时分秒(HH:mm:ss)格式 - * @return 时分秒转换后的秒数 - * @since 3.1.2 - */ - public static int timeToSecond(String timeStr) { - if(StringUtil.isEmpty(timeStr)) { - return 0; - } - - final List hms = StringUtil.splitTrim(timeStr, StringPool.COLON, 3); - int lastIndex = hms.size() - 1; - - int result = 0; - for(int i = lastIndex; i >= 0; i--) { - result += Integer.parseInt(hms.get(i)) * Math.pow(60, (lastIndex - i)); - } - return result; - } - - /** - * 秒数转为时间格式(HH:mm:ss)
- * 参考:https://github.com/iceroot - * - * @param seconds 需要转换的秒数 - * @return 转换后的字符串 - * @since 3.1.2 - */ - public static String secondToTime(int seconds) { - if(seconds < 0) { - throw new IllegalArgumentException("Seconds must be a positive number!"); - } - - int hour = seconds / 3600; - int other = seconds % 3600; - int minute = other / 60; - int second = other % 60; - final StringBuilder sb = new StringBuilder(); - if (hour < 10) { - sb.append("0"); - } - sb.append(hour); - sb.append(":"); - if (minute < 10) { - sb.append("0"); - } - sb.append(minute); - sb.append(":"); - if (second < 10) { - sb.append("0"); - } - sb.append(second); - return sb.toString(); - } - - // ------------------------------------------------------------------------ Private method start - /** - * 获得指定日期年份和季节
- * 格式:[20131]表示2013年第一季度 - * - * @param cal 日期 - */ - private static String yearAndSeason(Calendar cal) { - return new StringBuilder().append(cal.get(Calendar.YEAR)).append(cal.get(Calendar.MONTH) / 3 + 1).toString(); - } - - /** - * 标准化日期,默认处理以空格区分的日期时间格式,空格前为日期,空格后为时间:
- * 将以下字符替换为"-" - *
-	 * "."
-	 * "/"
-	 * "年"
-	 * "月"
-	 * 
- * - * 将以下字符去除 - *
-	 * "日"
-	 * 
- * - * 将以下字符替换为":" - *
-	 * "时"
-	 * "分"
-	 * "秒"
-	 * 
- * 当末位是":"时去除之(不存在毫秒时) - * - * @param dateStr 日期时间字符串 - * @return 格式化后的日期字符串 - */ - private static String normalize(String dateStr) { - if(StringUtil.isBlank(dateStr)) { - return dateStr; - } - - //日期时间分开处理 - final List dateAndTime = StringUtil.splitTrim(dateStr, ' '); - final int size = dateAndTime.size(); - if(size < 1 || size > 2) { - //非可被标准处理的格式 - return dateStr; - } - - final StringBuilder builder = new StringBuilder(); - - //日期部分("\"、"/"、"."、"年"、"月"都替换为"-") - String datePart = dateAndTime.get(0).replaceAll("[\\/.年月]", "-"); - datePart = StringUtil.removeSuffix(datePart, "日"); - builder.append(datePart); - - //时间部分 - if(size == 2) { - builder.append(' '); - String timePart = dateAndTime.get(1).replaceAll("[时分秒]", ":"); - timePart = StringUtil.removeSuffix(timePart, ":"); - builder.append(timePart); - } - - return builder.toString(); - } - // ------------------------------------------------------------------------ Private method end -} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/date/Month.java b/blade-core-tool/src/main/java/org/springblade/core/tool/date/Month.java deleted file mode 100644 index f4358bf..0000000 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/date/Month.java +++ /dev/null @@ -1,118 +0,0 @@ -package org.springblade.core.tool.date; - -import java.util.Calendar; - -/** - * 月份枚举
- * 与Calendar中的月份int值对应 - * - * @see Calendar#JANUARY - * @see Calendar#FEBRUARY - * @see Calendar#MARCH - * @see Calendar#APRIL - * @see Calendar#MAY - * @see Calendar#JUNE - * @see Calendar#JULY - * @see Calendar#AUGUST - * @see Calendar#SEPTEMBER - * @see Calendar#OCTOBER - * @see Calendar#NOVEMBER - * @see Calendar#DECEMBER - * @see Calendar#UNDECIMBER - * - * @author Looly - * - */ -public enum Month { - - /** 一月 */ - JANUARY(Calendar.JANUARY), - /** 二月 */ - FEBRUARY(Calendar.FEBRUARY), - /** 三月 */ - MARCH(Calendar.MARCH), - /** 四月 */ - APRIL(Calendar.APRIL), - /** 五月 */ - MAY(Calendar.MAY), - /** 六月 */ - JUNE(Calendar.JUNE), - /** 七月 */ - JULY(Calendar.JULY), - /** 八月 */ - AUGUST(Calendar.AUGUST), - /** 九月 */ - SEPTEMBER(Calendar.SEPTEMBER), - /** 十月 */ - OCTOBER(Calendar.OCTOBER), - /** 十一月 */ - NOVEMBER(Calendar.NOVEMBER), - /** 十二月 */ - DECEMBER(Calendar.DECEMBER), - /** 十三月,仅用于农历 */ - UNDECIMBER(Calendar.UNDECIMBER); - - // --------------------------------------------------------------- - private int value; - - private Month(int value) { - this.value = value; - } - - public int getValue() { - return this.value; - } - - /** - * 将 {@link Calendar}月份相关值转换为Month枚举对象
- * - * @see Calendar#JANUARY - * @see Calendar#FEBRUARY - * @see Calendar#MARCH - * @see Calendar#APRIL - * @see Calendar#MAY - * @see Calendar#JUNE - * @see Calendar#JULY - * @see Calendar#AUGUST - * @see Calendar#SEPTEMBER - * @see Calendar#OCTOBER - * @see Calendar#NOVEMBER - * @see Calendar#DECEMBER - * @see Calendar#UNDECIMBER - * - * @param calendarMonthIntValue Calendar中关于Month的int值 - * @return {@link Month} - */ - public static Month of(int calendarMonthIntValue) { - switch (calendarMonthIntValue) { - case Calendar.JANUARY: - return JANUARY; - case Calendar.FEBRUARY: - return FEBRUARY; - case Calendar.MARCH: - return MARCH; - case Calendar.APRIL: - return APRIL; - case Calendar.MAY: - return MAY; - case Calendar.JUNE: - return JUNE; - case Calendar.JULY: - return JULY; - case Calendar.AUGUST: - return AUGUST; - case Calendar.SEPTEMBER: - return SEPTEMBER; - case Calendar.OCTOBER: - return OCTOBER; - case Calendar.NOVEMBER: - return NOVEMBER; - case Calendar.DECEMBER: - return DECEMBER; - case Calendar.UNDECIMBER: - return UNDECIMBER; - default: - return null; - } - } -} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/date/Season.java b/blade-core-tool/src/main/java/org/springblade/core/tool/date/Season.java deleted file mode 100644 index 9cb0e75..0000000 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/date/Season.java +++ /dev/null @@ -1,61 +0,0 @@ -package org.springblade.core.tool.date; - -/** - * 季度枚举
- * - * @see #SPRING - * @see #SUMMER - * @see #AUTUMN - * @see #WINTER - * - * @author Looly - * - */ -public enum Season { - - /** 春季(第一季度) */ - SPRING(1), - /** 夏季(第二季度) */ - SUMMER(2), - /** 秋季(第三季度) */ - AUTUMN(3), - /** 冬季(第四季度) */ - WINTER(4); - - // --------------------------------------------------------------- - private int value; - - private Season(int value) { - this.value = value; - } - - public int getValue() { - return this.value; - } - - /** - * 将 季度int转换为Season枚举对象
- * - * @see #SPRING - * @see #SUMMER - * @see #AUTUMN - * @see #WINTER - * - * @param intValue 季度int表示 - * @return {@link Season} - */ - public static Season of(int intValue) { - switch (intValue) { - case 1: - return SPRING; - case 2: - return SUMMER; - case 3: - return AUTUMN; - case 4: - return WINTER; - default: - return null; - } - } -} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/date/TimeInterval.java b/blade-core-tool/src/main/java/org/springblade/core/tool/date/TimeInterval.java deleted file mode 100644 index 0d6ec58..0000000 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/date/TimeInterval.java +++ /dev/null @@ -1,109 +0,0 @@ -package org.springblade.core.tool.date; - -/** - * 计时器
- * 计算某个过程花费的时间,精确到毫秒 - * - * @author Looly - * - */ -public class TimeInterval { - private long time; - private boolean isNano; - - public TimeInterval() { - this(false); - } - - public TimeInterval(boolean isNano) { - this.isNano = isNano; - start(); - } - - /** - * @return 开始计时并返回当前时间 - */ - public long start() { - time = DateUtil.current(isNano); - return time; - } - - /** - * @return 重新计时并返回从开始到当前的持续时间 - */ - public long intervalRestart() { - long now = DateUtil.current(isNano); - long d = now - time; - time = now; - return d; - } - - /** - * 重新开始计算时间(重置开始时间) - * @return this - * @since 3.0.1 - */ - public TimeInterval restart(){ - time = DateUtil.current(isNano); - return this; - } - - //----------------------------------------------------------- Interval - /** - * 从开始到当前的间隔时间(毫秒数)
- * 如果使用纳秒计时,返回纳秒差,否则返回毫秒差 - * @return 从开始到当前的间隔时间(毫秒数) - */ - public long interval() { - return DateUtil.current(isNano) - time; - } - - /** - * 从开始到当前的间隔时间(毫秒数) - * @return 从开始到当前的间隔时间(毫秒数) - */ - public long intervalMs() { - return isNano ? interval() / 1000000L : interval(); - } - - /** - * 从开始到当前的间隔秒数,取绝对值 - * @return 从开始到当前的间隔秒数,取绝对值 - */ - public long intervalSecond(){ - return intervalMs() / DateUnit.SECOND.getMillis(); - } - - /** - * 从开始到当前的间隔分钟数,取绝对值 - * @return 从开始到当前的间隔分钟数,取绝对值 - */ - public long intervalMinute(){ - return intervalMs() / DateUnit.MINUTE.getMillis(); - } - - /** - * 从开始到当前的间隔小时数,取绝对值 - * @return 从开始到当前的间隔小时数,取绝对值 - */ - public long intervalHour(){ - return intervalMs() / DateUnit.HOUR.getMillis(); - } - - /** - * 从开始到当前的间隔天数,取绝对值 - * @return 从开始到当前的间隔天数,取绝对值 - */ - public long intervalDay(){ - return intervalMs() / DateUnit.DAY.getMillis(); - } - - /** - * 从开始到当前的间隔周数,取绝对值 - * @return 从开始到当前的间隔周数,取绝对值 - */ - public long intervalWeek(){ - return intervalMs() / DateUnit.WEEK.getMillis(); - } - -} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/date/Week.java b/blade-core-tool/src/main/java/org/springblade/core/tool/date/Week.java deleted file mode 100644 index caaa504..0000000 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/date/Week.java +++ /dev/null @@ -1,120 +0,0 @@ -package org.springblade.core.tool.date; - -import java.util.Calendar; - -/** - * 星期枚举
- * 与Calendar中的星期int值对应 - * - * @see #SUNDAY - * @see #MONDAY - * @see #TUESDAY - * @see #WEDNESDAY - * @see #THURSDAY - * @see #FRIDAY - * @see #SATURDAY - * - * @author Looly - * - */ -public enum Week { - - /** 周日 */ - SUNDAY(Calendar.SUNDAY), - /** 周一 */ - MONDAY(Calendar.MONDAY), - /** 周二 */ - TUESDAY(Calendar.TUESDAY), - /** 周三 */ - WEDNESDAY(Calendar.WEDNESDAY), - /** 周四 */ - THURSDAY(Calendar.THURSDAY), - /** 周五 */ - FRIDAY(Calendar.FRIDAY), - /** 周六 */ - SATURDAY(Calendar.SATURDAY); - - // --------------------------------------------------------------- - /** 星期对应{@link Calendar} 中的Week值 */ - private int value; - - /** - * 构造 - * - * @param value 星期对应{@link Calendar} 中的Week值 - */ - private Week(int value) { - this.value = value; - } - - /** - * 获得星期对应{@link Calendar} 中的Week值 - * - * @return 星期对应{@link Calendar} 中的Week值 - */ - public int getValue() { - return this.value; - } - - /** - * 转换为中文名 - * - * @return 星期的中文名 - * @since 3.3.0 - */ - public String toChinese() { - switch (this) { - case SUNDAY: - return "星期日"; - case MONDAY: - return "星期一"; - case TUESDAY: - return "星期二"; - case WEDNESDAY: - return "星期三"; - case THURSDAY: - return "星期四"; - case FRIDAY: - return "星期五"; - case SATURDAY: - return "星期六"; - default: - return null; - } - } - - /** - * 将 {@link Calendar}星期相关值转换为Week枚举对象
- * - * @see #SUNDAY - * @see #MONDAY - * @see #TUESDAY - * @see #WEDNESDAY - * @see #THURSDAY - * @see #FRIDAY - * @see #SATURDAY - * - * @param calendarWeekIntValue Calendar中关于Week的int值 - * @return {@link Week} - */ - public static Week of(int calendarWeekIntValue) { - switch (calendarWeekIntValue) { - case Calendar.SUNDAY: - return SUNDAY; - case Calendar.MONDAY: - return MONDAY; - case Calendar.TUESDAY: - return TUESDAY; - case Calendar.WEDNESDAY: - return WEDNESDAY; - case Calendar.THURSDAY: - return THURSDAY; - case Calendar.FRIDAY: - return FRIDAY; - case Calendar.SATURDAY: - return SATURDAY; - default: - return null; - } - } -} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/date/format/AbstractDateBasic.java b/blade-core-tool/src/main/java/org/springblade/core/tool/date/format/AbstractDateBasic.java deleted file mode 100644 index 2c2d10e..0000000 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/date/format/AbstractDateBasic.java +++ /dev/null @@ -1,64 +0,0 @@ -package org.springblade.core.tool.date.format; - -import java.io.Serializable; -import java.util.Locale; -import java.util.TimeZone; - -public abstract class AbstractDateBasic implements DateBasic, Serializable { - private static final long serialVersionUID = 6333136319870641818L; - - /** The pattern */ - protected final String pattern; - /** The time zone. */ - protected final TimeZone timeZone; - /** The locale. */ - protected final Locale locale; - - /** - * 构造,内部使用 - * @param pattern 使用{@link java.text.SimpleDateFormat} 相同的日期格式 - * @param timeZone 非空时区{@link TimeZone} - * @param locale 非空{@link Locale} 日期地理位置 - */ - protected AbstractDateBasic(final String pattern, final TimeZone timeZone, final Locale locale) { - this.pattern = pattern; - this.timeZone = timeZone; - this.locale = locale; - } - - // ----------------------------------------------------------------------- Accessors - @Override - public String getPattern() { - return pattern; - } - - @Override - public TimeZone getTimeZone() { - return timeZone; - } - - @Override - public Locale getLocale() { - return locale; - } - - // ----------------------------------------------------------------------- Basics - @Override - public boolean equals(final Object obj) { - if (obj instanceof FastDatePrinter == false) { - return false; - } - final AbstractDateBasic other = (AbstractDateBasic) obj; - return pattern.equals(other.pattern) && timeZone.equals(other.timeZone) && locale.equals(other.locale); - } - - @Override - public int hashCode() { - return pattern.hashCode() + 13 * (timeZone.hashCode() + 13 * locale.hashCode()); - } - - @Override - public String toString() { - return "FastDatePrinter[" + pattern + "," + locale + "," + timeZone.getID() + "]"; - } -} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/date/format/DateBasic.java b/blade-core-tool/src/main/java/org/springblade/core/tool/date/format/DateBasic.java deleted file mode 100644 index 5dc9463..0000000 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/date/format/DateBasic.java +++ /dev/null @@ -1,33 +0,0 @@ -package org.springblade.core.tool.date.format; - -import java.util.Locale; -import java.util.TimeZone; - -/** - * 日期基本信息获取接口 - * - * @author Looly - * @since 2.16.2 - */ -public interface DateBasic { - /** - * 获得日期格式化或者转换的格式 - * - * @return {@link java.text.SimpleDateFormat}兼容的格式 - */ - String getPattern(); - - /** - * 获得时区 - * - * @return {@link TimeZone} - */ - TimeZone getTimeZone(); - - /** - * 获得 日期地理位置 - * - * @return {@link Locale} - */ - Locale getLocale(); -} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/date/format/DateParser.java b/blade-core-tool/src/main/java/org/springblade/core/tool/date/format/DateParser.java deleted file mode 100644 index edc05be..0000000 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/date/format/DateParser.java +++ /dev/null @@ -1,68 +0,0 @@ -package org.springblade.core.tool.date.format; - -import java.text.ParseException; -import java.text.ParsePosition; -import java.util.Calendar; -import java.util.Date; - -/** - * 日期解析接口,用于解析日期字符串为 {@link Date} 对象
- * Thanks to Apache Commons Lang 3.5 - * @since 2.16.2 - */ -public interface DateParser extends DateBasic { - - /** - * 将日期字符串解析并转换为 {@link Date} 对象
- * 等价于 {@link java.text.DateFormat#parse(String)} - * - * @param source 日期字符串 - * @return {@link Date} - * @throws ParseException 转换异常,被转换的字符串格式错误。 - */ - Date parse(String source) throws ParseException; - - /** - * 将日期字符串解析并转换为 {@link Date} 对象
- * 等价于 {@link java.text.DateFormat#parse(String, ParsePosition)} - * - * @param source 日期字符串 - * @param pos {@link ParsePosition} - * @return {@link Date} - */ - Date parse(String source, ParsePosition pos); - - /** - * 根据给定格式转换日期字符串 - * Updates the Calendar with parsed fields. Upon success, the ParsePosition index is updated to indicate how much of the source text was consumed. - * Not all source text needs to be consumed. - * Upon parse failure, ParsePosition error index is updated to the offset of the source text which does not match the supplied format. - * - * @param source 被转换的日期字符串 - * @param pos 定义开始转换的位置,转换结束后更新转换到的位置 - * @param calendar The calendar into which to set parsed fields. - * @return true, if source has been parsed (pos parsePosition is updated); otherwise false (and pos errorIndex is updated) - * @throws IllegalArgumentException when Calendar has been set to be not lenient, and a parsed field is out of range. - */ - boolean parse(String source, ParsePosition pos, Calendar calendar); - - /** - * 将日期字符串解析并转换为 {@link Date} 对象
- * - * @param source A String whose beginning should be parsed. - * @return a java.util.Date object - * @throws ParseException if the beginning of the specified string cannot be parsed. - * @see java.text.DateFormat#parseObject(String) - */ - Object parseObject(String source) throws ParseException; - - /** - * 根据 {@link ParsePosition} 给定将日期字符串解析并转换为 {@link Date} 对象
- * - * @param source A String whose beginning should be parsed. - * @param pos the parse position - * @return a java.util.Date object - * @see java.text.DateFormat#parseObject(String, ParsePosition) - */ - Object parseObject(String source, ParsePosition pos); -} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/date/format/DatePrinter.java b/blade-core-tool/src/main/java/org/springblade/core/tool/date/format/DatePrinter.java deleted file mode 100644 index decc2ef..0000000 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/date/format/DatePrinter.java +++ /dev/null @@ -1,78 +0,0 @@ -package org.springblade.core.tool.date.format; - -import java.util.Calendar; -import java.util.Date; - -/** - * 日期格式化输出接口
- * Thanks to Apache Commons Lang 3.5 - * @author Looly - * @since 2.16.2 - */ -public interface DatePrinter extends DateBasic { - - /** - * 格式化日期表示的毫秒数 - * - * @param millis 日期毫秒数 - * @return the formatted string - * @since 2.1 - */ - String format(long millis); - - /** - * 使用 {@code GregorianCalendar} 格式化 {@code Date} - * - * @param date 日期 {@link Date} - * @return 格式化后的字符串 - */ - String format(Date date); - - /** - *

- * Formats a {@code Calendar} object. - *

- * 格式化 {@link Calendar} - * - * @param calendar {@link Calendar} - * @return 格式化后的字符串 - */ - String format(Calendar calendar); - - /** - *

- * Formats a millisecond {@code long} value into the supplied {@code Appendable}. - *

- * - * @param millis the millisecond value to format - * @param buf the buffer to format into - * @param the Appendable class type, usually StringBuilder or StringBuffer. - * @return the specified string buffer - */ - B format(long millis, B buf); - - /** - *

- * Formats a {@code Date} object into the supplied {@code Appendable} using a {@code GregorianCalendar}. - *

- * - * @param date the date to format - * @param buf the buffer to format into - * @param the Appendable class type, usually StringBuilder or StringBuffer. - * @return the specified string buffer - */ - B format(Date date, B buf); - - /** - *

- * Formats a {@code Calendar} object into the supplied {@code Appendable}. - *

- * The TimeZone set on the Calendar is only used to adjust the time offset. The TimeZone specified during the construction of the Parser will determine the TimeZone used in the formatted string. - * - * @param calendar the calendar to format - * @param buf the buffer to format into - * @param the Appendable class type, usually StringBuilder or StringBuffer. - * @return the specified string buffer - */ - B format(Calendar calendar, B buf); -} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/date/format/FastDateFormat.java b/blade-core-tool/src/main/java/org/springblade/core/tool/date/format/FastDateFormat.java deleted file mode 100644 index dfc685d..0000000 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/date/format/FastDateFormat.java +++ /dev/null @@ -1,392 +0,0 @@ -package org.springblade.core.tool.date.format; - -import java.text.*; -import java.util.Calendar; -import java.util.Date; -import java.util.Locale; -import java.util.TimeZone; - -/** - *

- * FastDateFormat 是一个线程安全的 {@link SimpleDateFormat} 实现。 - *

- * - *

- * 通过以下静态方法获得此对象:
- * {@link #getInstance(String, TimeZone, Locale)}
- * {@link #getDateInstance(int, TimeZone, Locale)}
- * {@link #getTimeInstance(int, TimeZone, Locale)}
- * {@link #getDateTimeInstance(int, int, TimeZone, Locale)} - *

- * - * Thanks to Apache Commons Lang 3.5 - * @since 2.16.2 - */ -public class FastDateFormat extends Format implements DateParser, DatePrinter { - private static final long serialVersionUID = 8097890768636183236L; - - /** FULL locale dependent date or time style. */ - public static final int FULL = DateFormat.FULL; - /** LONG locale dependent date or time style. */ - public static final int LONG = DateFormat.LONG; - /** MEDIUM locale dependent date or time style. */ - public static final int MEDIUM = DateFormat.MEDIUM; - /** SHORT locale dependent date or time style. */ - public static final int SHORT = DateFormat.SHORT; - - private static final FormatCache cache = new FormatCache(){ - @Override - protected FastDateFormat createInstance(final String pattern, final TimeZone timeZone, final Locale locale) { - return new FastDateFormat(pattern, timeZone, locale); - } - }; - - private final FastDatePrinter printer; - private final FastDateParser parser; - - // ----------------------------------------------------------------------- - /** - * 获得 {@link FastDateFormat} 实例,使用默认格式和地区 - * - * @return {@link FastDateFormat} - */ - public static FastDateFormat getInstance() { - return cache.getInstance(); - } - - /** - * 获得 {@link FastDateFormat} 实例,使用默认地区
- * 支持缓存 - * - * @param pattern 使用{@link SimpleDateFormat} 相同的日期格式 - * @return {@link FastDateFormat} - * @throws IllegalArgumentException 日期格式问题 - */ - public static FastDateFormat getInstance(final String pattern) { - return cache.getInstance(pattern, null, null); - } - - /** - * 获得 {@link FastDateFormat} 实例
- * 支持缓存 - * - * @param pattern 使用{@link SimpleDateFormat} 相同的日期格式 - * @param timeZone 时区{@link TimeZone} - * @return {@link FastDateFormat} - * @throws IllegalArgumentException 日期格式问题 - */ - public static FastDateFormat getInstance(final String pattern, final TimeZone timeZone) { - return cache.getInstance(pattern, timeZone, null); - } - - /** - * 获得 {@link FastDateFormat} 实例
- * 支持缓存 - * - * @param pattern 使用{@link SimpleDateFormat} 相同的日期格式 - * @param locale {@link Locale} 日期地理位置 - * @return {@link FastDateFormat} - * @throws IllegalArgumentException 日期格式问题 - */ - public static FastDateFormat getInstance(final String pattern, final Locale locale) { - return cache.getInstance(pattern, null, locale); - } - - /** - * 获得 {@link FastDateFormat} 实例
- * 支持缓存 - * - * @param pattern 使用{@link SimpleDateFormat} 相同的日期格式 - * @param timeZone 时区{@link TimeZone} - * @param locale {@link Locale} 日期地理位置 - * @return {@link FastDateFormat} - * @throws IllegalArgumentException 日期格式问题 - */ - public static FastDateFormat getInstance(final String pattern, final TimeZone timeZone, final Locale locale) { - return cache.getInstance(pattern, timeZone, locale); - } - - // ----------------------------------------------------------------------- - /** - * 获得 {@link FastDateFormat} 实例
- * 支持缓存 - * - * @param style date style: FULL, LONG, MEDIUM, or SHORT - * @return 本地化 {@link FastDateFormat} - */ - public static FastDateFormat getDateInstance(final int style) { - return cache.getDateInstance(style, null, null); - } - - /** - * 获得 {@link FastDateFormat} 实例
- * 支持缓存 - * - * @param style date style: FULL, LONG, MEDIUM, or SHORT - * @param locale {@link Locale} 日期地理位置 - * @return 本地化 {@link FastDateFormat} - */ - public static FastDateFormat getDateInstance(final int style, final Locale locale) { - return cache.getDateInstance(style, null, locale); - } - - /** - * 获得 {@link FastDateFormat} 实例
- * 支持缓存 - * - * @param style date style: FULL, LONG, MEDIUM, or SHORT - * @param timeZone 时区{@link TimeZone} - * @return 本地化 {@link FastDateFormat} - */ - public static FastDateFormat getDateInstance(final int style, final TimeZone timeZone) { - return cache.getDateInstance(style, timeZone, null); - } - - /** - * 获得 {@link FastDateFormat} 实例
- * 支持缓存 - * - * @param style date style: FULL, LONG, MEDIUM, or SHORT - * @param timeZone 时区{@link TimeZone} - * @param locale {@link Locale} 日期地理位置 - * @return 本地化 {@link FastDateFormat} - */ - public static FastDateFormat getDateInstance(final int style, final TimeZone timeZone, final Locale locale) { - return cache.getDateInstance(style, timeZone, locale); - } - - // ----------------------------------------------------------------------- - /** - * 获得 {@link FastDateFormat} 实例
- * 支持缓存 - * - * @param style time style: FULL, LONG, MEDIUM, or SHORT - * @return 本地化 {@link FastDateFormat} - */ - public static FastDateFormat getTimeInstance(final int style) { - return cache.getTimeInstance(style, null, null); - } - - /** - * 获得 {@link FastDateFormat} 实例
- * 支持缓存 - * - * @param style time style: FULL, LONG, MEDIUM, or SHORT - * @param locale {@link Locale} 日期地理位置 - * @return 本地化 {@link FastDateFormat} - */ - public static FastDateFormat getTimeInstance(final int style, final Locale locale) { - return cache.getTimeInstance(style, null, locale); - } - - /** - * 获得 {@link FastDateFormat} 实例
- * 支持缓存 - * - * @param style time style: FULL, LONG, MEDIUM, or SHORT - * @param timeZone optional time zone, overrides time zone of formatted time - * @return 本地化 {@link FastDateFormat} - */ - public static FastDateFormat getTimeInstance(final int style, final TimeZone timeZone) { - return cache.getTimeInstance(style, timeZone, null); - } - - /** - * 获得 {@link FastDateFormat} 实例
- * 支持缓存 - * - * @param style time style: FULL, LONG, MEDIUM, or SHORT - * @param timeZone optional time zone, overrides time zone of formatted time - * @param locale {@link Locale} 日期地理位置 - * @return 本地化 {@link FastDateFormat} - */ - public static FastDateFormat getTimeInstance(final int style, final TimeZone timeZone, final Locale locale) { - return cache.getTimeInstance(style, timeZone, locale); - } - - // ----------------------------------------------------------------------- - /** - * 获得 {@link FastDateFormat} 实例
- * 支持缓存 - * - * @param dateStyle date style: FULL, LONG, MEDIUM, or SHORT - * @param timeStyle time style: FULL, LONG, MEDIUM, or SHORT - * @return 本地化 {@link FastDateFormat} - */ - public static FastDateFormat getDateTimeInstance(final int dateStyle, final int timeStyle) { - return cache.getDateTimeInstance(dateStyle, timeStyle, null, null); - } - - /** - * 获得 {@link FastDateFormat} 实例
- * 支持缓存 - * - * @param dateStyle date style: FULL, LONG, MEDIUM, or SHORT - * @param timeStyle time style: FULL, LONG, MEDIUM, or SHORT - * @param locale {@link Locale} 日期地理位置 - * @return 本地化 {@link FastDateFormat} - */ - public static FastDateFormat getDateTimeInstance(final int dateStyle, final int timeStyle, final Locale locale) { - return cache.getDateTimeInstance(dateStyle, timeStyle, null, locale); - } - - /** - * 获得 {@link FastDateFormat} 实例
- * 支持缓存 - * - * @param dateStyle date style: FULL, LONG, MEDIUM, or SHORT - * @param timeStyle time style: FULL, LONG, MEDIUM, or SHORT - * @param timeZone 时区{@link TimeZone} - * @return 本地化 {@link FastDateFormat} - */ - public static FastDateFormat getDateTimeInstance(final int dateStyle, final int timeStyle, final TimeZone timeZone) { - return getDateTimeInstance(dateStyle, timeStyle, timeZone, null); - } - - /** - * 获得 {@link FastDateFormat} 实例
- * 支持缓存 - * - * @param dateStyle date style: FULL, LONG, MEDIUM, or SHORT - * @param timeStyle time style: FULL, LONG, MEDIUM, or SHORT - * @param timeZone 时区{@link TimeZone} - * @param locale {@link Locale} 日期地理位置 - * @return 本地化 {@link FastDateFormat} - */ - public static FastDateFormat getDateTimeInstance(final int dateStyle, final int timeStyle, final TimeZone timeZone, final Locale locale) { - return cache.getDateTimeInstance(dateStyle, timeStyle, timeZone, locale); - } - - // ----------------------------------------------------------------------- Constructor start - /** - * 构造 - * - * @param pattern 使用{@link SimpleDateFormat} 相同的日期格式 - * @param timeZone 非空时区 {@link TimeZone} - * @param locale {@link Locale} 日期地理位置 - * @throws NullPointerException if pattern, timeZone, or locale is null. - */ - protected FastDateFormat(final String pattern, final TimeZone timeZone, final Locale locale) { - this(pattern, timeZone, locale, null); - } - - /** - * 构造 - * - * @param pattern 使用{@link SimpleDateFormat} 相同的日期格式 - * @param timeZone 非空时区 {@link TimeZone} - * @param locale {@link Locale} 日期地理位置 - * @param centuryStart The start of the 100 year period to use as the "default century" for 2 digit year parsing. If centuryStart is null, defaults to now - 80 years - * @throws NullPointerException if pattern, timeZone, or locale is null. - */ - protected FastDateFormat(final String pattern, final TimeZone timeZone, final Locale locale, final Date centuryStart) { - printer = new FastDatePrinter(pattern, timeZone, locale); - parser = new FastDateParser(pattern, timeZone, locale, centuryStart); - } - // ----------------------------------------------------------------------- Constructor end - - // ----------------------------------------------------------------------- Format methods - @Override - public StringBuffer format(final Object obj, final StringBuffer toAppendTo, final FieldPosition pos) { - return toAppendTo.append(printer.format(obj)); - } - - @Override - public String format(final long millis) { - return printer.format(millis); - } - - @Override - public String format(final Date date) { - return printer.format(date); - } - - @Override - public String format(final Calendar calendar) { - return printer.format(calendar); - } - - @Override - public B format(final long millis, final B buf) { - return printer.format(millis, buf); - } - - @Override - public B format(final Date date, final B buf) { - return printer.format(date, buf); - } - - @Override - public B format(final Calendar calendar, final B buf) { - return printer.format(calendar, buf); - } - - // ----------------------------------------------------------------------- Parsing - @Override - public Date parse(final String source) throws ParseException { - return parser.parse(source); - } - - @Override - public Date parse(final String source, final ParsePosition pos) { - return parser.parse(source, pos); - } - - @Override - public boolean parse(final String source, final ParsePosition pos, final Calendar calendar) { - return parser.parse(source, pos, calendar); - } - - @Override - public Object parseObject(final String source, final ParsePosition pos) { - return parser.parseObject(source, pos); - } - - // ----------------------------------------------------------------------- Accessors - @Override - public String getPattern() { - return printer.getPattern(); - } - - @Override - public TimeZone getTimeZone() { - return printer.getTimeZone(); - } - - @Override - public Locale getLocale() { - return printer.getLocale(); - } - - /** - *估算生成的日期字符串长度
- * 实际生成的字符串长度小于或等于此值 - * - * @return 日期字符串长度 - */ - public int getMaxLengthEstimate() { - return printer.getMaxLengthEstimate(); - } - - // Basics - // ----------------------------------------------------------------------- - @Override - public boolean equals(final Object obj) { - if (obj instanceof FastDateFormat == false) { - return false; - } - final FastDateFormat other = (FastDateFormat) obj; - // no need to check parser, as it has same invariants as printer - return printer.equals(other.printer); - } - - @Override - public int hashCode() { - return printer.hashCode(); - } - - @Override - public String toString() { - return "FastDateFormat[" + printer.getPattern() + "," + printer.getLocale() + "," + printer.getTimeZone().getID() + "]"; - } -} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/date/format/FastDateParser.java b/blade-core-tool/src/main/java/org/springblade/core/tool/date/format/FastDateParser.java deleted file mode 100644 index 95a0717..0000000 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/date/format/FastDateParser.java +++ /dev/null @@ -1,822 +0,0 @@ -package org.springblade.core.tool.date.format; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.text.DateFormatSymbols; -import java.text.ParseException; -import java.text.ParsePosition; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * {@link java.text.SimpleDateFormat} 的线程安全版本,用于解析日期字符串并转换为 {@link Date} 对象
- * Thanks to Apache Commons Lang 3.5 - * - * @since 2.16.2 - * @see FastDatePrinter - */ -class FastDateParser extends AbstractDateBasic implements DateParser { - private static final long serialVersionUID = -3199383897950947498L; - - static final Locale JAPANESE_IMPERIAL = new Locale("ja", "JP", "JP"); - - /** 世纪:2000年前为19, 之后为20 */ - private final int century; - private final int startYear; - - // derived fields - private transient List patterns; - - // comparator used to sort regex alternatives - // alternatives should be ordered longer first, and shorter last. ('february' before 'feb') - // all entries must be lowercase by locale. - private static final Comparator LONGER_FIRST_LOWERCASE = new Comparator(){ - @Override - public int compare(final String left, final String right) { - return right.compareTo(left); - } - }; - - /** - *

- * Constructs a new FastDateParser. - *

- * - * Use {@link FastDateFormat#getInstance(String, TimeZone, Locale)} or another variation of the factory methods of {@link FastDateFormat} to get a cached FastDateParser instance. - * - * @param pattern non-null {@link java.text.SimpleDateFormat} compatible pattern - * @param timeZone non-null time zone to use - * @param locale non-null locale - */ - protected FastDateParser(final String pattern, final TimeZone timeZone, final Locale locale) { - this(pattern, timeZone, locale, null); - } - - /** - *

- * Constructs a new FastDateParser. - *

- * - * @param pattern non-null {@link java.text.SimpleDateFormat} compatible pattern - * @param timeZone non-null time zone to use - * @param locale non-null locale - * @param centuryStart The start of the century for 2 digit year parsing - */ - protected FastDateParser(final String pattern, final TimeZone timeZone, final Locale locale, final Date centuryStart) { - super(pattern, timeZone, locale); - final Calendar definingCalendar = Calendar.getInstance(timeZone, locale); - - int centuryStartYear; - if (centuryStart != null) { - definingCalendar.setTime(centuryStart); - centuryStartYear = definingCalendar.get(Calendar.YEAR); - } else if (locale.equals(JAPANESE_IMPERIAL)) { - centuryStartYear = 0; - } else { - // from 80 years ago to 20 years from now - definingCalendar.setTime(new Date()); - centuryStartYear = definingCalendar.get(Calendar.YEAR) - 80; - } - century = centuryStartYear / 100 * 100; - startYear = centuryStartYear - century; - - init(definingCalendar); - } - - /** - * Initialize derived fields from defining fields. This is called from constructor and from readObject (de-serialization) - * - * @param definingCalendar the {@link Calendar} instance used to initialize this FastDateParser - */ - private void init(final Calendar definingCalendar) { - patterns = new ArrayList<>(); - - final StrategyParser fm = new StrategyParser(definingCalendar); - for (;;) { - final StrategyAndWidth field = fm.getNextStrategy(); - if (field == null) { - break; - } - patterns.add(field); - } - } - - // helper classes to parse the format string - // ----------------------------------------------------------------------- - - /** - * Holds strategy and field width - */ - private static class StrategyAndWidth { - final Strategy strategy; - final int width; - - StrategyAndWidth(final Strategy strategy, final int width) { - this.strategy = strategy; - this.width = width; - } - - int getMaxWidth(final ListIterator lt) { - if (!strategy.isNumber() || !lt.hasNext()) { - return 0; - } - final Strategy nextStrategy = lt.next().strategy; - lt.previous(); - return nextStrategy.isNumber() ? width : 0; - } - } - - /** - * Parse format into Strategies - */ - private class StrategyParser { - final private Calendar definingCalendar; - private int currentIdx; - - StrategyParser(final Calendar definingCalendar) { - this.definingCalendar = definingCalendar; - } - - StrategyAndWidth getNextStrategy() { - if (currentIdx >= pattern.length()) { - return null; - } - - final char c = pattern.charAt(currentIdx); - if (isFormatLetter(c)) { - return letterPattern(c); - } - return literal(); - } - - private StrategyAndWidth letterPattern(final char c) { - final int begin = currentIdx; - while (++currentIdx < pattern.length()) { - if (pattern.charAt(currentIdx) != c) { - break; - } - } - - final int width = currentIdx - begin; - return new StrategyAndWidth(getStrategy(c, width, definingCalendar), width); - } - - private StrategyAndWidth literal() { - boolean activeQuote = false; - - final StringBuilder sb = new StringBuilder(); - while (currentIdx < pattern.length()) { - final char c = pattern.charAt(currentIdx); - if (!activeQuote && isFormatLetter(c)) { - break; - } else if (c == '\'' && (++currentIdx == pattern.length() || pattern.charAt(currentIdx) != '\'')) { - activeQuote = !activeQuote; - continue; - } - ++currentIdx; - sb.append(c); - } - - if (activeQuote) { - throw new IllegalArgumentException("Unterminated quote"); - } - - final String formatField = sb.toString(); - return new StrategyAndWidth(new CopyQuotedStrategy(formatField), formatField.length()); - } - } - - private static boolean isFormatLetter(final char c) { - return c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z'; - } - - // Serializing - // ----------------------------------------------------------------------- - /** - * Create the object after serialization. This implementation reinitializes the transient properties. - * - * @param in ObjectInputStream from which the object is being deserialized. - * @throws IOException if there is an IO issue. - * @throws ClassNotFoundException if a class cannot be found. - */ - private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException { - in.defaultReadObject(); - - final Calendar definingCalendar = Calendar.getInstance(timeZone, locale); - init(definingCalendar); - } - - @Override - public Object parseObject(final String source) throws ParseException { - return parse(source); - } - - @Override - public Date parse(final String source) throws ParseException { - final ParsePosition pp = new ParsePosition(0); - final Date date = parse(source, pp); - if (date == null) { - // Add a note re supported date range - if (locale.equals(JAPANESE_IMPERIAL)) { - throw new ParseException("(The " + locale + " locale does not support dates before 1868 AD)\n" + "Unparseable date: \"" + source, pp.getErrorIndex()); - } - throw new ParseException("Unparseable date: " + source, pp.getErrorIndex()); - } - return date; - } - - @Override - public Object parseObject(final String source, final ParsePosition pos) { - return parse(source, pos); - } - - @Override - public Date parse(final String source, final ParsePosition pos) { - // timing tests indicate getting new instance is 19% faster than cloning - final Calendar cal = Calendar.getInstance(timeZone, locale); - cal.clear(); - - return parse(source, pos, cal) ? cal.getTime() : null; - } - - @Override - public boolean parse(final String source, final ParsePosition pos, final Calendar calendar) { - final ListIterator lt = patterns.listIterator(); - while (lt.hasNext()) { - final StrategyAndWidth strategyAndWidth = lt.next(); - final int maxWidth = strategyAndWidth.getMaxWidth(lt); - if (!strategyAndWidth.strategy.parse(this, calendar, source, pos, maxWidth)) { - return false; - } - } - return true; - } - - // Support for strategies - // ----------------------------------------------------------------------- - - private static StringBuilder simpleQuote(final StringBuilder sb, final String value) { - for (int i = 0; i < value.length(); ++i) { - final char c = value.charAt(i); - switch (c) { - case '\\': - case '^': - case '$': - case '.': - case '|': - case '?': - case '*': - case '+': - case '(': - case ')': - case '[': - case '{': - sb.append('\\'); - default: - sb.append(c); - } - } - return sb; - } - - /** - * Get the short and long values displayed for a field - * - * @param cal The calendar to obtain the short and long values - * @param locale The locale of display names - * @param field The field of interest - * @param regex The regular expression to build - * @return The map of string display names to field values - */ - private static Map appendDisplayNames(final Calendar cal, final Locale locale, final int field, final StringBuilder regex) { - final Map values = new HashMap<>(); - - final Map displayNames = cal.getDisplayNames(field, Calendar.ALL_STYLES, locale); - final TreeSet sorted = new TreeSet<>(LONGER_FIRST_LOWERCASE); - for (final Map.Entry displayName : displayNames.entrySet()) { - final String key = displayName.getKey().toLowerCase(locale); - if (sorted.add(key)) { - values.put(key, displayName.getValue()); - } - } - for (final String symbol : sorted) { - simpleQuote(regex, symbol).append('|'); - } - return values; - } - - /** - * 使用当前的世纪调整两位数年份为四位数年份 - * - * @param twoDigitYear 两位数年份 - * @return A value between centuryStart(inclusive) to centuryStart+100(exclusive) - */ - private int adjustYear(final int twoDigitYear) { - final int trial = century + twoDigitYear; - return twoDigitYear >= startYear ? trial : trial + 100; - } - - /** - * 单个日期字段的分析策略 - */ - private static abstract class Strategy { - /** - * Is this field a number? The default implementation returns false. - * - * @return true, if field is a number - */ - boolean isNumber() { - return false; - } - - abstract boolean parse(FastDateParser parser, Calendar calendar, String source, ParsePosition pos, int maxWidth); - } - - /** - * A strategy to parse a single field from the parsing pattern - */ - private static abstract class PatternStrategy extends Strategy { - - private Pattern pattern; - - void createPattern(final StringBuilder regex) { - createPattern(regex.toString()); - } - - void createPattern(final String regex) { - this.pattern = Pattern.compile(regex); - } - - /** - * Is this field a number? The default implementation returns false. - * - * @return true, if field is a number - */ - @Override - boolean isNumber() { - return false; - } - - @Override - boolean parse(final FastDateParser parser, final Calendar calendar, final String source, final ParsePosition pos, final int maxWidth) { - final Matcher matcher = pattern.matcher(source.substring(pos.getIndex())); - if (!matcher.lookingAt()) { - pos.setErrorIndex(pos.getIndex()); - return false; - } - pos.setIndex(pos.getIndex() + matcher.end(1)); - setCalendar(parser, calendar, matcher.group(1)); - return true; - } - - abstract void setCalendar(FastDateParser parser, Calendar cal, String value); - } - - /** - * Obtain a Strategy given a field from a SimpleDateFormat pattern - * - * @param formatField A sub-sequence of the SimpleDateFormat pattern - * @param definingCalendar The calendar to obtain the short and long values - * @return The Strategy that will handle parsing for the field - */ - private Strategy getStrategy(final char f, final int width, final Calendar definingCalendar) { - switch (f) { - default: - throw new IllegalArgumentException("Format '" + f + "' not supported"); - case 'D': - return DAY_OF_YEAR_STRATEGY; - case 'E': - return getLocaleSpecificStrategy(Calendar.DAY_OF_WEEK, definingCalendar); - case 'F': - return DAY_OF_WEEK_IN_MONTH_STRATEGY; - case 'G': - return getLocaleSpecificStrategy(Calendar.ERA, definingCalendar); - case 'H': // Hour in day (0-23) - return HOUR_OF_DAY_STRATEGY; - case 'K': // Hour in am/pm (0-11) - return HOUR_STRATEGY; - case 'M': - return width >= 3 ? getLocaleSpecificStrategy(Calendar.MONTH, definingCalendar) : NUMBER_MONTH_STRATEGY; - case 'S': - return MILLISECOND_STRATEGY; - case 'W': - return WEEK_OF_MONTH_STRATEGY; - case 'a': - return getLocaleSpecificStrategy(Calendar.AM_PM, definingCalendar); - case 'd': - return DAY_OF_MONTH_STRATEGY; - case 'h': // Hour in am/pm (1-12), i.e. midday/midnight is 12, not 0 - return HOUR12_STRATEGY; - case 'k': // Hour in day (1-24), i.e. midnight is 24, not 0 - return HOUR24_OF_DAY_STRATEGY; - case 'm': - return MINUTE_STRATEGY; - case 's': - return SECOND_STRATEGY; - case 'u': - return DAY_OF_WEEK_STRATEGY; - case 'w': - return WEEK_OF_YEAR_STRATEGY; - case 'y': - case 'Y': - return width > 2 ? LITERAL_YEAR_STRATEGY : ABBREVIATED_YEAR_STRATEGY; - case 'X': - return ISO8601TimeZoneStrategy.getStrategy(width); - case 'Z': - if (width == 2) { - return ISO8601TimeZoneStrategy.ISO_8601_3_STRATEGY; - } - //$FALL-THROUGH$ - case 'z': - return getLocaleSpecificStrategy(Calendar.ZONE_OFFSET, definingCalendar); - } - } - - @SuppressWarnings("unchecked") // OK because we are creating an array with no entries - private static final ConcurrentMap[] caches = new ConcurrentMap[Calendar.FIELD_COUNT]; - - /** - * Get a cache of Strategies for a particular field - * - * @param field The Calendar field - * @return a cache of Locale to Strategy - */ - private static ConcurrentMap getCache(final int field) { - synchronized (caches) { - if (caches[field] == null) { - caches[field] = new ConcurrentHashMap<>(3); - } - return caches[field]; - } - } - - /** - * Construct a Strategy that parses a Text field - * - * @param field The Calendar field - * @param definingCalendar The calendar to obtain the short and long values - * @return a TextStrategy for the field and Locale - */ - private Strategy getLocaleSpecificStrategy(final int field, final Calendar definingCalendar) { - final ConcurrentMap cache = getCache(field); - Strategy strategy = cache.get(locale); - if (strategy == null) { - strategy = field == Calendar.ZONE_OFFSET ? new TimeZoneStrategy(locale) : new CaseInsensitiveTextStrategy(field, definingCalendar, locale); - final Strategy inCache = cache.putIfAbsent(locale, strategy); - if (inCache != null) { - return inCache; - } - } - return strategy; - } - - /** - * A strategy that copies the static or quoted field in the parsing pattern - */ - private static class CopyQuotedStrategy extends Strategy { - - final private String formatField; - - /** - * Construct a Strategy that ensures the formatField has literal text - * - * @param formatField The literal text to match - */ - CopyQuotedStrategy(final String formatField) { - this.formatField = formatField; - } - - /** - * {@inheritDoc} - */ - @Override - boolean isNumber() { - return false; - } - - @Override - boolean parse(final FastDateParser parser, final Calendar calendar, final String source, final ParsePosition pos, final int maxWidth) { - for (int idx = 0; idx < formatField.length(); ++idx) { - final int sIdx = idx + pos.getIndex(); - if (sIdx == source.length()) { - pos.setErrorIndex(sIdx); - return false; - } - if (formatField.charAt(idx) != source.charAt(sIdx)) { - pos.setErrorIndex(sIdx); - return false; - } - } - pos.setIndex(formatField.length() + pos.getIndex()); - return true; - } - } - - /** - * A strategy that handles a text field in the parsing pattern - */ - private static class CaseInsensitiveTextStrategy extends PatternStrategy { - private final int field; - final Locale locale; - private final Map lKeyValues; - - /** - * Construct a Strategy that parses a Text field - * - * @param field The Calendar field - * @param definingCalendar The Calendar to use - * @param locale The Locale to use - */ - CaseInsensitiveTextStrategy(final int field, final Calendar definingCalendar, final Locale locale) { - this.field = field; - this.locale = locale; - - final StringBuilder regex = new StringBuilder(); - regex.append("((?iu)"); - lKeyValues = appendDisplayNames(definingCalendar, locale, field, regex); - regex.setLength(regex.length() - 1); - regex.append(")"); - createPattern(regex); - } - - /** - * {@inheritDoc} - */ - @Override - void setCalendar(final FastDateParser parser, final Calendar cal, final String value) { - final Integer iVal = lKeyValues.get(value.toLowerCase(locale)); - cal.set(field, iVal.intValue()); - } - } - - /** - * A strategy that handles a number field in the parsing pattern - */ - private static class NumberStrategy extends Strategy { - private final int field; - - /** - * Construct a Strategy that parses a Number field - * - * @param field The Calendar field - */ - NumberStrategy(final int field) { - this.field = field; - } - - /** - * {@inheritDoc} - */ - @Override - boolean isNumber() { - return true; - } - - @Override - boolean parse(final FastDateParser parser, final Calendar calendar, final String source, final ParsePosition pos, final int maxWidth) { - int idx = pos.getIndex(); - int last = source.length(); - - if (maxWidth == 0) { - // if no maxWidth, strip leading white space - for (; idx < last; ++idx) { - final char c = source.charAt(idx); - if (!Character.isWhitespace(c)) { - break; - } - } - pos.setIndex(idx); - } else { - final int end = idx + maxWidth; - if (last > end) { - last = end; - } - } - - for (; idx < last; ++idx) { - final char c = source.charAt(idx); - if (!Character.isDigit(c)) { - break; - } - } - - if (pos.getIndex() == idx) { - pos.setErrorIndex(idx); - return false; - } - - final int value = Integer.parseInt(source.substring(pos.getIndex(), idx)); - pos.setIndex(idx); - - calendar.set(field, modify(parser, value)); - return true; - } - - /** - * Make any modifications to parsed integer - * - * @param parser The parser - * @param iValue The parsed integer - * @return The modified value - */ - int modify(final FastDateParser parser, final int iValue) { - return iValue; - } - - } - - private static final Strategy ABBREVIATED_YEAR_STRATEGY = new NumberStrategy(Calendar.YEAR){ - /** - * {@inheritDoc} - */ - @Override - int modify(final FastDateParser parser, final int iValue) { - return iValue < 100 ? parser.adjustYear(iValue) : iValue; - } - }; - - /** - * A strategy that handles a timezone field in the parsing pattern - */ - static class TimeZoneStrategy extends PatternStrategy { - private static final String RFC_822_TIME_ZONE = "[+-]\\d{4}"; - private static final String GMT_OPTION = "GMT[+-]\\d{1,2}:\\d{2}"; - - private final Locale locale; - private final Map tzNames = new HashMap<>(); - - private static class TzInfo { - TimeZone zone; - int dstOffset; - - TzInfo(final TimeZone tz, final boolean useDst) { - zone = tz; - dstOffset = useDst ? tz.getDSTSavings() : 0; - } - } - - /** - * Index of zone id - */ - private static final int ID = 0; - - /** - * Construct a Strategy that parses a TimeZone - * - * @param locale The Locale - */ - TimeZoneStrategy(final Locale locale) { - this.locale = locale; - - final StringBuilder sb = new StringBuilder(); - sb.append("((?iu)" + RFC_822_TIME_ZONE + "|" + GMT_OPTION); - - final Set sorted = new TreeSet<>(LONGER_FIRST_LOWERCASE); - - final String[][] zones = DateFormatSymbols.getInstance(locale).getZoneStrings(); - for (final String[] zoneNames : zones) { - // offset 0 is the time zone ID and is not localized - final String tzId = zoneNames[ID]; - if (tzId.equalsIgnoreCase("GMT")) { - continue; - } - final TimeZone tz = TimeZone.getTimeZone(tzId); - // offset 1 is long standard name - // offset 2 is short standard name - final TzInfo standard = new TzInfo(tz, false); - TzInfo tzInfo = standard; - for (int i = 1; i < zoneNames.length; ++i) { - switch (i) { - case 3: // offset 3 is long daylight savings (or summertime) name - // offset 4 is the short summertime name - tzInfo = new TzInfo(tz, true); - break; - case 5: // offset 5 starts additional names, probably standard time - tzInfo = standard; - break; - } - if (zoneNames[i] != null) { - final String key = zoneNames[i].toLowerCase(locale); - // ignore the data associated with duplicates supplied in - // the additional names - if (sorted.add(key)) { - tzNames.put(key, tzInfo); - } - } - } - } - // order the regex alternatives with longer strings first, greedy - // match will ensure longest string will be consumed - for (final String zoneName : sorted) { - simpleQuote(sb.append('|'), zoneName); - } - sb.append(")"); - createPattern(sb); - } - - /** - * {@inheritDoc} - */ - @Override - void setCalendar(final FastDateParser parser, final Calendar cal, final String value) { - if (value.charAt(0) == '+' || value.charAt(0) == '-') { - final TimeZone tz = TimeZone.getTimeZone("GMT" + value); - cal.setTimeZone(tz); - } else if (value.regionMatches(true, 0, "GMT", 0, 3)) { - final TimeZone tz = TimeZone.getTimeZone(value.toUpperCase()); - cal.setTimeZone(tz); - } else { - final TzInfo tzInfo = tzNames.get(value.toLowerCase(locale)); - cal.set(Calendar.DST_OFFSET, tzInfo.dstOffset); - cal.set(Calendar.ZONE_OFFSET, tzInfo.zone.getRawOffset()); - } - } - } - - private static class ISO8601TimeZoneStrategy extends PatternStrategy { - // Z, +hh, -hh, +hhmm, -hhmm, +hh:mm or -hh:mm - - /** - * Construct a Strategy that parses a TimeZone - * - * @param pattern The Pattern - */ - ISO8601TimeZoneStrategy(final String pattern) { - createPattern(pattern); - } - - /** - * {@inheritDoc} - */ - @Override - void setCalendar(final FastDateParser parser, final Calendar cal, final String value) { - if (value.equals("Z")) { - cal.setTimeZone(TimeZone.getTimeZone("UTC")); - } else { - cal.setTimeZone(TimeZone.getTimeZone("GMT" + value)); - } - } - - private static final Strategy ISO_8601_1_STRATEGY = new ISO8601TimeZoneStrategy("(Z|(?:[+-]\\d{2}))"); - private static final Strategy ISO_8601_2_STRATEGY = new ISO8601TimeZoneStrategy("(Z|(?:[+-]\\d{2}\\d{2}))"); - private static final Strategy ISO_8601_3_STRATEGY = new ISO8601TimeZoneStrategy("(Z|(?:[+-]\\d{2}(?::)\\d{2}))"); - - /** - * Factory method for ISO8601TimeZoneStrategies. - * - * @param tokenLen a token indicating the length of the TimeZone String to be formatted. - * @return a ISO8601TimeZoneStrategy that can format TimeZone String of length {@code tokenLen}. If no such strategy exists, an IllegalArgumentException will be thrown. - */ - static Strategy getStrategy(final int tokenLen) { - switch (tokenLen) { - case 1: - return ISO_8601_1_STRATEGY; - case 2: - return ISO_8601_2_STRATEGY; - case 3: - return ISO_8601_3_STRATEGY; - default: - throw new IllegalArgumentException("invalid number of X"); - } - } - } - - private static final Strategy NUMBER_MONTH_STRATEGY = new NumberStrategy(Calendar.MONTH){ - @Override - int modify(final FastDateParser parser, final int iValue) { - return iValue - 1; - } - }; - private static final Strategy LITERAL_YEAR_STRATEGY = new NumberStrategy(Calendar.YEAR); - private static final Strategy WEEK_OF_YEAR_STRATEGY = new NumberStrategy(Calendar.WEEK_OF_YEAR); - private static final Strategy WEEK_OF_MONTH_STRATEGY = new NumberStrategy(Calendar.WEEK_OF_MONTH); - private static final Strategy DAY_OF_YEAR_STRATEGY = new NumberStrategy(Calendar.DAY_OF_YEAR); - private static final Strategy DAY_OF_MONTH_STRATEGY = new NumberStrategy(Calendar.DAY_OF_MONTH); - private static final Strategy DAY_OF_WEEK_STRATEGY = new NumberStrategy(Calendar.DAY_OF_WEEK){ - @Override - int modify(final FastDateParser parser, final int iValue) { - return iValue != 7 ? iValue + 1 : Calendar.SUNDAY; - } - }; - private static final Strategy DAY_OF_WEEK_IN_MONTH_STRATEGY = new NumberStrategy(Calendar.DAY_OF_WEEK_IN_MONTH); - private static final Strategy HOUR_OF_DAY_STRATEGY = new NumberStrategy(Calendar.HOUR_OF_DAY); - private static final Strategy HOUR24_OF_DAY_STRATEGY = new NumberStrategy(Calendar.HOUR_OF_DAY){ - @Override - int modify(final FastDateParser parser, final int iValue) { - return iValue == 24 ? 0 : iValue; - } - }; - private static final Strategy HOUR12_STRATEGY = new NumberStrategy(Calendar.HOUR){ - @Override - int modify(final FastDateParser parser, final int iValue) { - return iValue == 12 ? 0 : iValue; - } - }; - private static final Strategy HOUR_STRATEGY = new NumberStrategy(Calendar.HOUR); - private static final Strategy MINUTE_STRATEGY = new NumberStrategy(Calendar.MINUTE); - private static final Strategy SECOND_STRATEGY = new NumberStrategy(Calendar.SECOND); - private static final Strategy MILLISECOND_STRATEGY = new NumberStrategy(Calendar.MILLISECOND); -} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/date/format/FastDatePrinter.java b/blade-core-tool/src/main/java/org/springblade/core/tool/date/format/FastDatePrinter.java deleted file mode 100644 index 82f5298..0000000 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/date/format/FastDatePrinter.java +++ /dev/null @@ -1,1320 +0,0 @@ -package org.springblade.core.tool.date.format; - -import java.io.IOException; -import java.io.ObjectInputStream; -import java.text.DateFormatSymbols; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -/** - * {@link java.text.SimpleDateFormat} 的线程安全版本,用于将 {@link Date} 格式化输出
- * Thanks to Apache Commons Lang 3.5 - * - * @since 2.16.2 - * @see FastDateParser - */ -class FastDatePrinter extends AbstractDateBasic implements DatePrinter { - private static final long serialVersionUID = -6305750172255764887L; - - /** 规则列表. */ - private transient Rule[] rules; - /** 估算最大长度. */ - private transient int mMaxLengthEstimate; - - // Constructor - // ----------------------------------------------------------------------- - /** - * 构造,内部使用
- * - * @param pattern 使用{@link java.text.SimpleDateFormat} 相同的日期格式 - * @param timeZone 非空时区{@link TimeZone} - * @param locale 非空{@link Locale} 日期地理位置 - */ - protected FastDatePrinter(final String pattern, final TimeZone timeZone, final Locale locale) { - super(pattern, timeZone, locale); - init(); - } - - /** - * 初始化 - */ - private void init() { - final List rulesList = parsePattern(); - rules = rulesList.toArray(new Rule[rulesList.size()]); - - int len = 0; - for (int i = rules.length; --i >= 0;) { - len += rules[i].estimateLength(); - } - - mMaxLengthEstimate = len; - } - - // Parse the pattern - // ----------------------------------------------------------------------- - /** - *

- * Returns a list of Rules given a pattern. - *

- * - * @return a {@code List} of Rule objects - * @throws IllegalArgumentException if pattern is invalid - */ - protected List parsePattern() { - final DateFormatSymbols symbols = new DateFormatSymbols(locale); - final List rules = new ArrayList<>(); - - final String[] ERAs = symbols.getEras(); - final String[] months = symbols.getMonths(); - final String[] shortMonths = symbols.getShortMonths(); - final String[] weekdays = symbols.getWeekdays(); - final String[] shortWeekdays = symbols.getShortWeekdays(); - final String[] AmPmStrings = symbols.getAmPmStrings(); - - final int length = pattern.length(); - final int[] indexRef = new int[1]; - - for (int i = 0; i < length; i++) { - indexRef[0] = i; - final String token = parseToken(pattern, indexRef); - i = indexRef[0]; - - final int tokenLen = token.length(); - if (tokenLen == 0) { - break; - } - - Rule rule; - final char c = token.charAt(0); - - switch (c) { - case 'G': // era designator (text) - rule = new TextField(Calendar.ERA, ERAs); - break; - case 'y': // year (number) - case 'Y': // week year - if (tokenLen == 2) { - rule = TwoDigitYearField.INSTANCE; - } else { - rule = selectNumberRule(Calendar.YEAR, tokenLen < 4 ? 4 : tokenLen); - } - if (c == 'Y') { - rule = new WeekYear((NumberRule) rule); - } - break; - case 'M': // month in year (text and number) - if (tokenLen >= 4) { - rule = new TextField(Calendar.MONTH, months); - } else if (tokenLen == 3) { - rule = new TextField(Calendar.MONTH, shortMonths); - } else if (tokenLen == 2) { - rule = TwoDigitMonthField.INSTANCE; - } else { - rule = UnpaddedMonthField.INSTANCE; - } - break; - case 'd': // day in month (number) - rule = selectNumberRule(Calendar.DAY_OF_MONTH, tokenLen); - break; - case 'h': // hour in am/pm (number, 1..12) - rule = new TwelveHourField(selectNumberRule(Calendar.HOUR, tokenLen)); - break; - case 'H': // hour in day (number, 0..23) - rule = selectNumberRule(Calendar.HOUR_OF_DAY, tokenLen); - break; - case 'm': // minute in hour (number) - rule = selectNumberRule(Calendar.MINUTE, tokenLen); - break; - case 's': // second in minute (number) - rule = selectNumberRule(Calendar.SECOND, tokenLen); - break; - case 'S': // millisecond (number) - rule = selectNumberRule(Calendar.MILLISECOND, tokenLen); - break; - case 'E': // day in week (text) - rule = new TextField(Calendar.DAY_OF_WEEK, tokenLen < 4 ? shortWeekdays : weekdays); - break; - case 'u': // day in week (number) - rule = new DayInWeekField(selectNumberRule(Calendar.DAY_OF_WEEK, tokenLen)); - break; - case 'D': // day in year (number) - rule = selectNumberRule(Calendar.DAY_OF_YEAR, tokenLen); - break; - case 'F': // day of week in month (number) - rule = selectNumberRule(Calendar.DAY_OF_WEEK_IN_MONTH, tokenLen); - break; - case 'w': // week in year (number) - rule = selectNumberRule(Calendar.WEEK_OF_YEAR, tokenLen); - break; - case 'W': // week in month (number) - rule = selectNumberRule(Calendar.WEEK_OF_MONTH, tokenLen); - break; - case 'a': // am/pm marker (text) - rule = new TextField(Calendar.AM_PM, AmPmStrings); - break; - case 'k': // hour in day (1..24) - rule = new TwentyFourHourField(selectNumberRule(Calendar.HOUR_OF_DAY, tokenLen)); - break; - case 'K': // hour in am/pm (0..11) - rule = selectNumberRule(Calendar.HOUR, tokenLen); - break; - case 'X': // ISO 8601 - rule = Iso8601_Rule.getRule(tokenLen); - break; - case 'z': // time zone (text) - if (tokenLen >= 4) { - rule = new TimeZoneNameRule(timeZone, locale, TimeZone.LONG); - } else { - rule = new TimeZoneNameRule(timeZone, locale, TimeZone.SHORT); - } - break; - case 'Z': // time zone (value) - if (tokenLen == 1) { - rule = TimeZoneNumberRule.INSTANCE_NO_COLON; - } else if (tokenLen == 2) { - rule = Iso8601_Rule.ISO8601_HOURS_COLON_MINUTES; - } else { - rule = TimeZoneNumberRule.INSTANCE_COLON; - } - break; - case '\'': // literal text - final String sub = token.substring(1); - if (sub.length() == 1) { - rule = new CharacterLiteral(sub.charAt(0)); - } else { - rule = new StringLiteral(sub); - } - break; - default: - throw new IllegalArgumentException("Illegal pattern component: " + token); - } - - rules.add(rule); - } - - return rules; - } - - /** - *

- * Performs the parsing of tokens. - *

- * - * @param pattern the pattern - * @param indexRef index references - * @return parsed token - */ - protected String parseToken(final String pattern, final int[] indexRef) { - final StringBuilder buf = new StringBuilder(); - - int i = indexRef[0]; - final int length = pattern.length(); - - char c = pattern.charAt(i); - if (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z') { - // Scan a run of the same character, which indicates a time - // pattern. - buf.append(c); - - while (i + 1 < length) { - final char peek = pattern.charAt(i + 1); - if (peek == c) { - buf.append(c); - i++; - } else { - break; - } - } - } else { - // This will identify token as text. - buf.append('\''); - - boolean inLiteral = false; - - for (; i < length; i++) { - c = pattern.charAt(i); - - if (c == '\'') { - if (i + 1 < length && pattern.charAt(i + 1) == '\'') { - // '' is treated as escaped ' - i++; - buf.append(c); - } else { - inLiteral = !inLiteral; - } - } else if (!inLiteral && (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z')) { - i--; - break; - } else { - buf.append(c); - } - } - } - - indexRef[0] = i; - return buf.toString(); - } - - /** - *

- * Gets an appropriate rule for the padding required. - *

- * - * @param field the field to get a rule for - * @param padding the padding required - * @return a new rule with the correct padding - */ - protected NumberRule selectNumberRule(final int field, final int padding) { - switch (padding) { - case 1: - return new UnpaddedNumberField(field); - case 2: - return new TwoDigitNumberField(field); - default: - return new PaddedNumberField(field, padding); - } - } - - // Format methods - // ----------------------------------------------------------------------- - - /** - *

- * Formats a {@code Date}, {@code Calendar} or {@code Long} (milliseconds) object. - *

- * - * @param obj the object to format - * @return The formatted value. - */ - String format(final Object obj) { - if (obj instanceof Date) { - return format((Date) obj); - } else if (obj instanceof Calendar) { - return format((Calendar) obj); - } else if (obj instanceof Long) { - return format(((Long) obj).longValue()); - } else { - throw new IllegalArgumentException("Unknown class: " + (obj == null ? "" : obj.getClass().getName())); - } - } - - @Override - public String format(final long millis) { - final Calendar c = Calendar.getInstance(timeZone, locale); - c.setTimeInMillis(millis); - return applyRulesToString(c); - } - - @Override - public String format(final Date date) { - final Calendar c = Calendar.getInstance(timeZone, locale); - c.setTime(date); - return applyRulesToString(c); - } - - @Override - public String format(final Calendar calendar) { - return format(calendar, new StringBuilder(mMaxLengthEstimate)).toString(); - } - - @Override - public B format(final long millis, final B buf) { - final Calendar c = Calendar.getInstance(timeZone, locale); - c.setTimeInMillis(millis); - return applyRules(c, buf); - } - - @Override - public B format(final Date date, final B buf) { - final Calendar c = Calendar.getInstance(timeZone, locale); - c.setTime(date); - return applyRules(c, buf); - } - - @Override - public B format(Calendar calendar, final B buf) { - // do not pass in calendar directly, this will cause TimeZone of FastDatePrinter to be ignored - if (!calendar.getTimeZone().equals(timeZone)) { - calendar = (Calendar) calendar.clone(); - calendar.setTimeZone(timeZone); - } - return applyRules(calendar, buf); - } - - /** - * Creates a String representation of the given Calendar by applying the rules of this printer to it. - * - * @param c the Calender to apply the rules to. - * @return a String representation of the given Calendar. - */ - private String applyRulesToString(final Calendar c) { - return applyRules(c, new StringBuilder(mMaxLengthEstimate)).toString(); - } - - /** - *

- * Performs the formatting by applying the rules to the specified calendar. - *

- * - * @param calendar the calendar to format - * @param buf the buffer to format into - * @param the Appendable class type, usually StringBuilder or StringBuffer. - * @return the specified string buffer - */ - private B applyRules(final Calendar calendar, final B buf) { - try { - for (final Rule rule : this.rules) { - rule.appendTo(buf, calendar); - } - } catch (final IOException e) { - throw new RuntimeException(e); - } - return buf; - } - - /** - *估算生成的日期字符串长度
- * 实际生成的字符串长度小于或等于此值 - * - * @return 日期字符串长度 - */ - public int getMaxLengthEstimate() { - return mMaxLengthEstimate; - } - - // Serializing - // ----------------------------------------------------------------------- - /** - * Create the object after serialization. This implementation reinitializes the transient properties. - * - * @param in ObjectInputStream from which the object is being deserialized. - * @throws IOException if there is an IO issue. - * @throws ClassNotFoundException if a class cannot be found. - */ - private void readObject(final ObjectInputStream in) throws IOException, ClassNotFoundException { - in.defaultReadObject(); - init(); - } - - /** - * Appends two digits to the given buffer. - * - * @param buffer the buffer to append to. - * @param value the value to append digits from. - */ - private static void appendDigits(final Appendable buffer, final int value) throws IOException { - buffer.append((char) (value / 10 + '0')); - buffer.append((char) (value % 10 + '0')); - } - - private static final int MAX_DIGITS = 10; // log10(Integer.MAX_VALUE) ~= 9.3 - - /** - * Appends all digits to the given buffer. - * - * @param buffer the buffer to append to. - * @param value the value to append digits from. - */ - private static void appendFullDigits(final Appendable buffer, int value, int minFieldWidth) throws IOException { - // specialized paths for 1 to 4 digits -> avoid the memory allocation from the temporary work array - // see LANG-1248 - if (value < 10000) { - // less memory allocation path works for four digits or less - - int nDigits = 4; - if (value < 1000) { - --nDigits; - if (value < 100) { - --nDigits; - if (value < 10) { - --nDigits; - } - } - } - // left zero pad - for (int i = minFieldWidth - nDigits; i > 0; --i) { - buffer.append('0'); - } - - switch (nDigits) { - case 4: - buffer.append((char) (value / 1000 + '0')); - value %= 1000; - case 3: - if (value >= 100) { - buffer.append((char) (value / 100 + '0')); - value %= 100; - } else { - buffer.append('0'); - } - case 2: - if (value >= 10) { - buffer.append((char) (value / 10 + '0')); - value %= 10; - } else { - buffer.append('0'); - } - case 1: - buffer.append((char) (value + '0')); - } - } else { - // more memory allocation path works for any digits - - // build up decimal representation in reverse - final char[] work = new char[MAX_DIGITS]; - int digit = 0; - while (value != 0) { - work[digit++] = (char) (value % 10 + '0'); - value = value / 10; - } - - // pad with zeros - while (digit < minFieldWidth) { - buffer.append('0'); - --minFieldWidth; - } - - // reverse - while (--digit >= 0) { - buffer.append(work[digit]); - } - } - } - - // Rules - // ----------------------------------------------------------------------- - /** - * 规则 - */ - private interface Rule { - /** - * Returns the estimated length of the result. - * - * @return the estimated length - */ - int estimateLength(); - - /** - * Appends the value of the specified calendar to the output buffer based on the rule implementation. - * - * @param buf the output buffer - * @param calendar calendar to be appended - * @throws IOException if an I/O error occurs - */ - void appendTo(Appendable buf, Calendar calendar) throws IOException; - } - - /** - *

- * Inner class defining a numeric rule. - *

- */ - private interface NumberRule extends Rule { - /** - * Appends the specified value to the output buffer based on the rule implementation. - * - * @param buffer the output buffer - * @param value the value to be appended - * @throws IOException if an I/O error occurs - */ - void appendTo(Appendable buffer, int value) throws IOException; - } - - /** - *

- * Inner class to output a constant single character. - *

- */ - private static class CharacterLiteral implements Rule { - private final char mValue; - - /** - * Constructs a new instance of {@code CharacterLiteral} to hold the specified value. - * - * @param value the character literal - */ - CharacterLiteral(final char value) { - mValue = value; - } - - @Override - public int estimateLength() { - return 1; - } - - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - buffer.append(mValue); - } - } - - /** - *

- * Inner class to output a constant string. - *

- */ - private static class StringLiteral implements Rule { - private final String mValue; - - /** - * Constructs a new instance of {@code StringLiteral} to hold the specified value. - * - * @param value the string literal - */ - StringLiteral(final String value) { - mValue = value; - } - - /** - * {@inheritDoc} - */ - @Override - public int estimateLength() { - return mValue.length(); - } - - /** - * {@inheritDoc} - */ - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - buffer.append(mValue); - } - } - - /** - *

- * Inner class to output one of a set of values. - *

- */ - private static class TextField implements Rule { - private final int mField; - private final String[] mValues; - - /** - * Constructs an instance of {@code TextField} with the specified field and values. - * - * @param field the field - * @param values the field values - */ - TextField(final int field, final String[] values) { - mField = field; - mValues = values; - } - - /** - * {@inheritDoc} - */ - @Override - public int estimateLength() { - int max = 0; - for (int i = mValues.length; --i >= 0;) { - final int len = mValues[i].length(); - if (len > max) { - max = len; - } - } - return max; - } - - /** - * {@inheritDoc} - */ - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - buffer.append(mValues[calendar.get(mField)]); - } - } - - /** - *

- * Inner class to output an unpadded number. - *

- */ - private static class UnpaddedNumberField implements NumberRule { - private final int mField; - - /** - * Constructs an instance of {@code UnpadedNumberField} with the specified field. - * - * @param field the field - */ - UnpaddedNumberField(final int field) { - mField = field; - } - - /** - * {@inheritDoc} - */ - @Override - public int estimateLength() { - return 4; - } - - /** - * {@inheritDoc} - */ - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - appendTo(buffer, calendar.get(mField)); - } - - /** - * {@inheritDoc} - */ - @Override - public final void appendTo(final Appendable buffer, final int value) throws IOException { - if (value < 10) { - buffer.append((char) (value + '0')); - } else if (value < 100) { - appendDigits(buffer, value); - } else { - appendFullDigits(buffer, value, 1); - } - } - } - - /** - *

- * Inner class to output an unpadded month. - *

- */ - private static class UnpaddedMonthField implements NumberRule { - static final UnpaddedMonthField INSTANCE = new UnpaddedMonthField(); - - /** - * Constructs an instance of {@code UnpaddedMonthField}. - * - */ - UnpaddedMonthField() { - super(); - } - - /** - * {@inheritDoc} - */ - @Override - public int estimateLength() { - return 2; - } - - /** - * {@inheritDoc} - */ - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - appendTo(buffer, calendar.get(Calendar.MONTH) + 1); - } - - /** - * {@inheritDoc} - */ - @Override - public final void appendTo(final Appendable buffer, final int value) throws IOException { - if (value < 10) { - buffer.append((char) (value + '0')); - } else { - appendDigits(buffer, value); - } - } - } - - /** - *

- * Inner class to output a padded number. - *

- */ - private static class PaddedNumberField implements NumberRule { - private final int mField; - private final int mSize; - - /** - * Constructs an instance of {@code PaddedNumberField}. - * - * @param field the field - * @param size size of the output field - */ - PaddedNumberField(final int field, final int size) { - if (size < 3) { - // Should use UnpaddedNumberField or TwoDigitNumberField. - throw new IllegalArgumentException(); - } - mField = field; - mSize = size; - } - - /** - * {@inheritDoc} - */ - @Override - public int estimateLength() { - return mSize; - } - - /** - * {@inheritDoc} - */ - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - appendTo(buffer, calendar.get(mField)); - } - - /** - * {@inheritDoc} - */ - @Override - public final void appendTo(final Appendable buffer, final int value) throws IOException { - appendFullDigits(buffer, value, mSize); - } - } - - /** - *

- * Inner class to output a two digit number. - *

- */ - private static class TwoDigitNumberField implements NumberRule { - private final int mField; - - /** - * Constructs an instance of {@code TwoDigitNumberField} with the specified field. - * - * @param field the field - */ - TwoDigitNumberField(final int field) { - mField = field; - } - - /** - * {@inheritDoc} - */ - @Override - public int estimateLength() { - return 2; - } - - /** - * {@inheritDoc} - */ - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - appendTo(buffer, calendar.get(mField)); - } - - /** - * {@inheritDoc} - */ - @Override - public final void appendTo(final Appendable buffer, final int value) throws IOException { - if (value < 100) { - appendDigits(buffer, value); - } else { - appendFullDigits(buffer, value, 2); - } - } - } - - /** - *

- * Inner class to output a two digit year. - *

- */ - private static class TwoDigitYearField implements NumberRule { - static final TwoDigitYearField INSTANCE = new TwoDigitYearField(); - - /** - * Constructs an instance of {@code TwoDigitYearField}. - */ - TwoDigitYearField() { - super(); - } - - /** - * {@inheritDoc} - */ - @Override - public int estimateLength() { - return 2; - } - - /** - * {@inheritDoc} - */ - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - appendTo(buffer, calendar.get(Calendar.YEAR) % 100); - } - - /** - * {@inheritDoc} - */ - @Override - public final void appendTo(final Appendable buffer, final int value) throws IOException { - appendDigits(buffer, value); - } - } - - /** - *

- * Inner class to output a two digit month. - *

- */ - private static class TwoDigitMonthField implements NumberRule { - static final TwoDigitMonthField INSTANCE = new TwoDigitMonthField(); - - /** - * Constructs an instance of {@code TwoDigitMonthField}. - */ - TwoDigitMonthField() { - super(); - } - - /** - * {@inheritDoc} - */ - @Override - public int estimateLength() { - return 2; - } - - /** - * {@inheritDoc} - */ - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - appendTo(buffer, calendar.get(Calendar.MONTH) + 1); - } - - /** - * {@inheritDoc} - */ - @Override - public final void appendTo(final Appendable buffer, final int value) throws IOException { - appendDigits(buffer, value); - } - } - - /** - *

- * Inner class to output the twelve hour field. - *

- */ - private static class TwelveHourField implements NumberRule { - private final NumberRule mRule; - - /** - * Constructs an instance of {@code TwelveHourField} with the specified {@code NumberRule}. - * - * @param rule the rule - */ - TwelveHourField(final NumberRule rule) { - mRule = rule; - } - - /** - * {@inheritDoc} - */ - @Override - public int estimateLength() { - return mRule.estimateLength(); - } - - /** - * {@inheritDoc} - */ - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - int value = calendar.get(Calendar.HOUR); - if (value == 0) { - value = calendar.getLeastMaximum(Calendar.HOUR) + 1; - } - mRule.appendTo(buffer, value); - } - - /** - * {@inheritDoc} - */ - @Override - public void appendTo(final Appendable buffer, final int value) throws IOException { - mRule.appendTo(buffer, value); - } - } - - /** - *

- * Inner class to output the twenty four hour field. - *

- */ - private static class TwentyFourHourField implements NumberRule { - private final NumberRule mRule; - - /** - * Constructs an instance of {@code TwentyFourHourField} with the specified {@code NumberRule}. - * - * @param rule the rule - */ - TwentyFourHourField(final NumberRule rule) { - mRule = rule; - } - - /** - * {@inheritDoc} - */ - @Override - public int estimateLength() { - return mRule.estimateLength(); - } - - /** - * {@inheritDoc} - */ - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - int value = calendar.get(Calendar.HOUR_OF_DAY); - if (value == 0) { - value = calendar.getMaximum(Calendar.HOUR_OF_DAY) + 1; - } - mRule.appendTo(buffer, value); - } - - /** - * {@inheritDoc} - */ - @Override - public void appendTo(final Appendable buffer, final int value) throws IOException { - mRule.appendTo(buffer, value); - } - } - - /** - *

- * Inner class to output the numeric day in week. - *

- */ - private static class DayInWeekField implements NumberRule { - private final NumberRule mRule; - - DayInWeekField(final NumberRule rule) { - mRule = rule; - } - - @Override - public int estimateLength() { - return mRule.estimateLength(); - } - - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - final int value = calendar.get(Calendar.DAY_OF_WEEK); - mRule.appendTo(buffer, value != Calendar.SUNDAY ? value - 1 : 7); - } - - @Override - public void appendTo(final Appendable buffer, final int value) throws IOException { - mRule.appendTo(buffer, value); - } - } - - /** - *

- * Inner class to output the numeric day in week. - *

- */ - private static class WeekYear implements NumberRule { - private final NumberRule mRule; - - WeekYear(final NumberRule rule) { - mRule = rule; - } - - @Override - public int estimateLength() { - return mRule.estimateLength(); - } - - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - mRule.appendTo(buffer, calendar.getWeekYear()); - } - - @Override - public void appendTo(final Appendable buffer, final int value) throws IOException { - mRule.appendTo(buffer, value); - } - } - - // ----------------------------------------------------------------------- - - private static final ConcurrentMap cTimeZoneDisplayCache = new ConcurrentHashMap<>(7); - - /** - *

- * Gets the time zone display name, using a cache for performance. - *

- * - * @param tz the zone to query - * @param daylight true if daylight savings - * @param style the style to use {@code TimeZone.LONG} or {@code TimeZone.SHORT} - * @param locale the locale to use - * @return the textual name of the time zone - */ - static String getTimeZoneDisplay(final TimeZone tz, final boolean daylight, final int style, final Locale locale) { - final TimeZoneDisplayKey key = new TimeZoneDisplayKey(tz, daylight, style, locale); - String value = cTimeZoneDisplayCache.get(key); - if (value == null) { - // This is a very slow call, so cache the results. - value = tz.getDisplayName(daylight, style, locale); - final String prior = cTimeZoneDisplayCache.putIfAbsent(key, value); - if (prior != null) { - value = prior; - } - } - return value; - } - - /** - *

- * Inner class to output a time zone name. - *

- */ - private static class TimeZoneNameRule implements Rule { - private final Locale mLocale; - private final int mStyle; - private final String mStandard; - private final String mDaylight; - - /** - * Constructs an instance of {@code TimeZoneNameRule} with the specified properties. - * - * @param timeZone the time zone - * @param locale the locale - * @param style the style - */ - TimeZoneNameRule(final TimeZone timeZone, final Locale locale, final int style) { - mLocale = locale; - mStyle = style; - - mStandard = getTimeZoneDisplay(timeZone, false, style, locale); - mDaylight = getTimeZoneDisplay(timeZone, true, style, locale); - } - - /** - * {@inheritDoc} - */ - @Override - public int estimateLength() { - // We have no access to the Calendar object that will be passed to - // appendTo so base estimate on the TimeZone passed to the - // constructor - return Math.max(mStandard.length(), mDaylight.length()); - } - - /** - * {@inheritDoc} - */ - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - final TimeZone zone = calendar.getTimeZone(); - if (calendar.get(Calendar.DST_OFFSET) != 0) { - buffer.append(getTimeZoneDisplay(zone, true, mStyle, mLocale)); - } else { - buffer.append(getTimeZoneDisplay(zone, false, mStyle, mLocale)); - } - } - } - - /** - *

- * Inner class to output a time zone as a number {@code +/-HHMM} or {@code +/-HH:MM}. - *

- */ - private static class TimeZoneNumberRule implements Rule { - static final TimeZoneNumberRule INSTANCE_COLON = new TimeZoneNumberRule(true); - static final TimeZoneNumberRule INSTANCE_NO_COLON = new TimeZoneNumberRule(false); - - final boolean mColon; - - /** - * Constructs an instance of {@code TimeZoneNumberRule} with the specified properties. - * - * @param colon add colon between HH and MM in the output if {@code true} - */ - TimeZoneNumberRule(final boolean colon) { - mColon = colon; - } - - /** - * {@inheritDoc} - */ - @Override - public int estimateLength() { - return 5; - } - - /** - * {@inheritDoc} - */ - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - - int offset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET); - - if (offset < 0) { - buffer.append('-'); - offset = -offset; - } else { - buffer.append('+'); - } - - final int hours = offset / (60 * 60 * 1000); - appendDigits(buffer, hours); - - if (mColon) { - buffer.append(':'); - } - - final int minutes = offset / (60 * 1000) - 60 * hours; - appendDigits(buffer, minutes); - } - } - - /** - *

- * Inner class to output a time zone as a number {@code +/-HHMM} or {@code +/-HH:MM}. - *

- */ - private static class Iso8601_Rule implements Rule { - - // Sign TwoDigitHours or Z - static final Iso8601_Rule ISO8601_HOURS = new Iso8601_Rule(3); - // Sign TwoDigitHours Minutes or Z - static final Iso8601_Rule ISO8601_HOURS_MINUTES = new Iso8601_Rule(5); - // Sign TwoDigitHours : Minutes or Z - static final Iso8601_Rule ISO8601_HOURS_COLON_MINUTES = new Iso8601_Rule(6); - - /** - * Factory method for Iso8601_Rules. - * - * @param tokenLen a token indicating the length of the TimeZone String to be formatted. - * @return a Iso8601_Rule that can format TimeZone String of length {@code tokenLen}. If no such rule exists, an IllegalArgumentException will be thrown. - */ - static Iso8601_Rule getRule(final int tokenLen) { - switch (tokenLen) { - case 1: - return Iso8601_Rule.ISO8601_HOURS; - case 2: - return Iso8601_Rule.ISO8601_HOURS_MINUTES; - case 3: - return Iso8601_Rule.ISO8601_HOURS_COLON_MINUTES; - default: - throw new IllegalArgumentException("invalid number of X"); - } - } - - final int length; - - /** - * Constructs an instance of {@code Iso8601_Rule} with the specified properties. - * - * @param length The number of characters in output (unless Z is output) - */ - Iso8601_Rule(final int length) { - this.length = length; - } - - /** - * {@inheritDoc} - */ - @Override - public int estimateLength() { - return length; - } - - /** - * {@inheritDoc} - */ - @Override - public void appendTo(final Appendable buffer, final Calendar calendar) throws IOException { - int offset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET); - if (offset == 0) { - buffer.append("Z"); - return; - } - - if (offset < 0) { - buffer.append('-'); - offset = -offset; - } else { - buffer.append('+'); - } - - final int hours = offset / (60 * 60 * 1000); - appendDigits(buffer, hours); - - if (length < 5) { - return; - } - - if (length == 6) { - buffer.append(':'); - } - - final int minutes = offset / (60 * 1000) - 60 * hours; - appendDigits(buffer, minutes); - } - } - - // ---------------------------------------------------------------------- - /** - *

- * Inner class that acts as a compound key for time zone names. - *

- */ - private static class TimeZoneDisplayKey { - private final TimeZone mTimeZone; - private final int mStyle; - private final Locale mLocale; - - /** - * Constructs an instance of {@code TimeZoneDisplayKey} with the specified properties. - * - * @param timeZone the time zone - * @param daylight adjust the style for daylight saving time if {@code true} - * @param style the timezone style - * @param locale the timezone locale - */ - TimeZoneDisplayKey(final TimeZone timeZone, final boolean daylight, final int style, final Locale locale) { - mTimeZone = timeZone; - if (daylight) { - mStyle = style | 0x80000000; - } else { - mStyle = style; - } - mLocale = locale; - } - - /** - * {@inheritDoc} - */ - @Override - public int hashCode() { - return (mStyle * 31 + mLocale.hashCode()) * 31 + mTimeZone.hashCode(); - } - - /** - * {@inheritDoc} - */ - @Override - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj instanceof TimeZoneDisplayKey) { - final TimeZoneDisplayKey other = (TimeZoneDisplayKey) obj; - return mTimeZone.equals(other.mTimeZone) && mStyle == other.mStyle && mLocale.equals(other.mLocale); - } - return false; - } - } -} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/date/format/FormatCache.java b/blade-core-tool/src/main/java/org/springblade/core/tool/date/format/FormatCache.java deleted file mode 100644 index 0d8924a..0000000 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/date/format/FormatCache.java +++ /dev/null @@ -1,252 +0,0 @@ -package org.springblade.core.tool.date.format; - -import java.text.DateFormat; -import java.text.Format; -import java.text.SimpleDateFormat; -import java.util.Arrays; -import java.util.Locale; -import java.util.TimeZone; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; - -/** - * 日期格式化器缓存
- * Thanks to Apache Commons Lang 3.5 - * - * @since 2.16.2 - */ -abstract class FormatCache { - - /** - * No date or no time. Used in same parameters as DateFormat.SHORT or DateFormat.LONG - */ - static final int NONE = -1; - - private final ConcurrentMap cInstanceCache = new ConcurrentHashMap<>(7); - - private static final ConcurrentMap cDateTimeInstanceCache = new ConcurrentHashMap<>(7); - - /** - * 使用默认的pattern、timezone和locale获得缓存中的实例 - * @return a date/time formatter - */ - public F getInstance() { - return getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, TimeZone.getDefault(), Locale.getDefault()); - } - - /** - * 使用 pattern, time zone and locale 获得对应的 格式化器 - * - * @param pattern 非空日期格式,使用与 {@link SimpleDateFormat}相同格式 - * @param timeZone 时区,默认当前时区 - * @param locale 地区,默认使用当前地区 - * @return 格式化器 - * @throws IllegalArgumentException pattern 无效或null - */ - public F getInstance(final String pattern, TimeZone timeZone, Locale locale) { - if (pattern == null) { - throw new NullPointerException("pattern must not be null"); - } - if (timeZone == null) { - timeZone = TimeZone.getDefault(); - } - if (locale == null) { - locale = Locale.getDefault(); - } - final MultipartKey key = new MultipartKey(pattern, timeZone, locale); - F format = cInstanceCache.get(key); - if (format == null) { - format = createInstance(pattern, timeZone, locale); - final F previousValue = cInstanceCache.putIfAbsent(key, format); - if (previousValue != null) { - // another thread snuck in and did the same work - // we should return the instance that is in ConcurrentMap - format = previousValue; - } - } - return format; - } - - /** - * 创建格式化器 - * - * @param pattern 非空日期格式,使用与 {@link SimpleDateFormat}相同格式 - * @param timeZone 时区,默认当前时区 - * @param locale 地区,默认使用当前地区 - * @return 格式化器 - * @throws IllegalArgumentException pattern 无效或null - */ - abstract protected F createInstance(String pattern, TimeZone timeZone, Locale locale); - - /** - *

- * Gets a date/time formatter instance using the specified style, time zone and locale. - *

- * - * @param dateStyle date style: FULL, LONG, MEDIUM, or SHORT, null indicates no date in format - * @param timeStyle time style: FULL, LONG, MEDIUM, or SHORT, null indicates no time in format - * @param timeZone optional time zone, overrides time zone of formatted date, null means use default Locale - * @param locale optional locale, overrides system locale - * @return a localized standard date/time formatter - * @throws IllegalArgumentException if the Locale has no date/time pattern defined - */ - // This must remain private, see LANG-884 - private F getDateTimeInstance(final Integer dateStyle, final Integer timeStyle, final TimeZone timeZone, Locale locale) { - if (locale == null) { - locale = Locale.getDefault(); - } - final String pattern = getPatternForStyle(dateStyle, timeStyle, locale); - return getInstance(pattern, timeZone, locale); - } - - /** - *

- * Gets a date/time formatter instance using the specified style, time zone and locale. - *

- * - * @param dateStyle date style: FULL, LONG, MEDIUM, or SHORT - * @param timeStyle time style: FULL, LONG, MEDIUM, or SHORT - * @param timeZone optional time zone, overrides time zone of formatted date, null means use default Locale - * @param locale optional locale, overrides system locale - * @return a localized standard date/time formatter - * @throws IllegalArgumentException if the Locale has no date/time pattern defined - */ - // package protected, for access from FastDateFormat; do not make public or protected - F getDateTimeInstance(final int dateStyle, final int timeStyle, final TimeZone timeZone, final Locale locale) { - return getDateTimeInstance(Integer.valueOf(dateStyle), Integer.valueOf(timeStyle), timeZone, locale); - } - - /** - *

- * Gets a date formatter instance using the specified style, time zone and locale. - *

- * - * @param dateStyle date style: FULL, LONG, MEDIUM, or SHORT - * @param timeZone optional time zone, overrides time zone of formatted date, null means use default Locale - * @param locale optional locale, overrides system locale - * @return a localized standard date/time formatter - * @throws IllegalArgumentException if the Locale has no date/time pattern defined - */ - // package protected, for access from FastDateFormat; do not make public or protected - F getDateInstance(final int dateStyle, final TimeZone timeZone, final Locale locale) { - return getDateTimeInstance(Integer.valueOf(dateStyle), null, timeZone, locale); - } - - /** - *

- * Gets a time formatter instance using the specified style, time zone and locale. - *

- * - * @param timeStyle time style: FULL, LONG, MEDIUM, or SHORT - * @param timeZone optional time zone, overrides time zone of formatted date, null means use default Locale - * @param locale optional locale, overrides system locale - * @return a localized standard date/time formatter - * @throws IllegalArgumentException if the Locale has no date/time pattern defined - */ - // package protected, for access from FastDateFormat; do not make public or protected - F getTimeInstance(final int timeStyle, final TimeZone timeZone, final Locale locale) { - return getDateTimeInstance(null, Integer.valueOf(timeStyle), timeZone, locale); - } - - /** - *

- * Gets a date/time format for the specified styles and locale. - *

- * - * @param dateStyle date style: FULL, LONG, MEDIUM, or SHORT, null indicates no date in format - * @param timeStyle time style: FULL, LONG, MEDIUM, or SHORT, null indicates no time in format - * @param locale The non-null locale of the desired format - * @return a localized standard date/time format - * @throws IllegalArgumentException if the Locale has no date/time pattern defined - */ - // package protected, for access from test code; do not make public or protected - static String getPatternForStyle(final Integer dateStyle, final Integer timeStyle, final Locale locale) { - final MultipartKey key = new MultipartKey(dateStyle, timeStyle, locale); - - String pattern = cDateTimeInstanceCache.get(key); - if (pattern == null) { - try { - DateFormat formatter; - if (dateStyle == null) { - formatter = DateFormat.getTimeInstance(timeStyle.intValue(), locale); - } else if (timeStyle == null) { - formatter = DateFormat.getDateInstance(dateStyle.intValue(), locale); - } else { - formatter = DateFormat.getDateTimeInstance(dateStyle.intValue(), timeStyle.intValue(), locale); - } - pattern = ((SimpleDateFormat) formatter).toPattern(); - final String previous = cDateTimeInstanceCache.putIfAbsent(key, pattern); - if (previous != null) { - // even though it doesn't matter if another thread put the pattern - // it's still good practice to return the String instance that is - // actually in the ConcurrentMap - pattern = previous; - } - } catch (final ClassCastException ex) { - throw new IllegalArgumentException("No date time pattern for locale: " + locale); - } - } - return pattern; - } - - // ---------------------------------------------------------------------- - /** - *

- * Helper class to hold multi-part Map keys - *

- */ - private static class MultipartKey { - private final Object[] keys; - private int hashCode; - - /** - * Constructs an instance of MultipartKey to hold the specified objects. - * - * @param keys the set of objects that make up the key. Each key may be null. - */ - public MultipartKey(final Object... keys) { - this.keys = keys; - } - - /** - * {@inheritDoc} - */ - @Override - public boolean equals(final Object obj) { - if (this == obj) { - return true; - } - if (obj == null) { - return false; - } - if (getClass() != obj.getClass()) { - return false; - } - final MultipartKey other = (MultipartKey) obj; - if (false == Arrays.equals(keys, other.keys)) { - return false; - } - return true; - } - - - - /** - * {@inheritDoc} - */ - @Override - public int hashCode() { - if (hashCode == 0) { - int rc = 0; - for (final Object key : keys) { - if (key != null) { - rc = rc * 7 + key.hashCode(); - } - } - hashCode = rc; - } - return hashCode; - } - } - -} diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/JsonUtil.java b/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/JsonUtil.java index f4ac752..8215686 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/JsonUtil.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/jackson/JsonUtil.java @@ -23,8 +23,9 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.SerializationFeature; import lombok.extern.slf4j.Slf4j; -import org.springblade.core.tool.date.DatePattern; +import org.springblade.core.tool.utils.DateUtil; import org.springblade.core.tool.utils.Exceptions; +import org.springblade.core.tool.utils.StringPool; import org.springblade.core.tool.utils.StringUtil; import java.io.IOException; @@ -35,6 +36,8 @@ import java.util.*; /** * Jackson工具类 + * + * @author smallchill */ @Slf4j public class JsonUtil { @@ -177,8 +180,8 @@ public class JsonUtil { public static List parseArray(String content, Class valueTypeRef) { try { - if (!StringUtil.startsWithIgnoreCase(content, "[")) { - content = "[" + content + "]"; + if (!StringUtil.startsWithIgnoreCase(content, StringPool.LEFT_SQ_BRACKET)) { + content = StringPool.LEFT_SQ_BRACKET + content + StringPool.RIGHT_SQ_BRACKET; } List> list = getInstance().readValue(content, new TypeReference>() { @@ -207,7 +210,7 @@ public class JsonUtil { try { Map> map = getInstance().readValue(content, new TypeReference>() { }); - Map result = new HashMap<>(); + Map result = new HashMap<>(16); for (Map.Entry> entry : map.entrySet()) { result.put(entry.getKey(), toPojo(entry.getValue(), valueTypeRef)); } @@ -300,7 +303,7 @@ public class JsonUtil { //设置为中国上海时区 super.setTimeZone(TimeZone.getTimeZone(ZoneId.systemDefault())); //序列化时,日期的统一格式 - super.setDateFormat(new SimpleDateFormat(DatePattern.NORM_DATETIME_PATTERN, Locale.CHINA)); + super.setDateFormat(new SimpleDateFormat(DateUtil.PATTERN_DATETIME, Locale.CHINA)); //序列化处理 super.configure(JsonParser.Feature.ALLOW_UNQUOTED_CONTROL_CHARS, true); super.configure(JsonParser.Feature.ALLOW_BACKSLASH_ESCAPING_ANY_CHARACTER, true); diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/node/INode.java b/blade-core-tool/src/main/java/org/springblade/core/tool/node/INode.java index dd62b3c..29aa2d9 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/node/INode.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/node/INode.java @@ -24,10 +24,22 @@ import java.util.List; */ public interface INode { + /** + * 主键 + * @return + */ Integer getId(); - Integer getParentId(); + /** + * 父主键 + * @return + */ + Integer getParentId(); + /** + * 子孙节点 + * @return + */ List getChildren(); } diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/support/StrSpliter.java b/blade-core-tool/src/main/java/org/springblade/core/tool/support/StrSpliter.java index 3057230..2fa920e 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/support/StrSpliter.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/support/StrSpliter.java @@ -157,11 +157,11 @@ public class StrSpliter { final ArrayList list = new ArrayList<>(limit > 0 ? limit : 16); int len = str.length(); - int start = 0;//切分后每个部分的起始 + int start = 0; for (int i = 0; i < len; i++) { if (Func.equals(separator, str.charAt(i))) { addToList(list, str.substring(start, i), isTrim, ignoreEmpty); - start = i + 1;//i+1同时将start与i保持一致 + start = i + 1; //检查是否超出范围(最大允许limit-1个,剩下一个留给末尾字符串) if (limit > 0 && list.size() > limit - 2) { @@ -169,7 +169,7 @@ public class StrSpliter { } } } - return addToList(list, str.substring(start, len), isTrim, ignoreEmpty);//收尾 + return addToList(list, str.substring(start, len), isTrim, ignoreEmpty); } /** @@ -294,9 +294,9 @@ public class StrSpliter { return addToList(new ArrayList(1), str, isTrim, ignoreEmpty); } - if (StringUtil.isEmpty(separator)) {//分隔符为空时按照空白符切分 + if (StringUtil.isEmpty(separator)) { return split(str, limit); - } else if (separator.length() == 1) {//分隔符只有一个字符长度时按照单分隔符切分 + } else if (separator.length() == 1) { return split(str, separator.charAt(0), limit, isTrim, ignoreEmpty, ignoreCase); } @@ -358,19 +358,17 @@ public class StrSpliter { final ArrayList list = new ArrayList<>(); int len = str.length(); - int start = 0;//切分后每个部分的起始 + int start = 0; for (int i = 0; i < len; i++) { if (Func.isEmpty(str.charAt(i))) { addToList(list, str.substring(start, i), true, true); - start = i + 1;//i+1同时将start与i保持一致 - - //检查是否超出范围(最大允许limit-1个,剩下一个留给末尾字符串) + start = i + 1; if (limit > 0 && list.size() > limit - 2) { break; } } } - return addToList(list, str.substring(start, len), true, true);//收尾 + return addToList(list, str.substring(start, len), true, true); } /** @@ -406,7 +404,7 @@ public class StrSpliter { return addToList(new ArrayList(1), str, isTrim, ignoreEmpty); } - if (null == separatorPattern) {//分隔符为空时按照空白符切分 + if (null == separatorPattern) { return split(str, limit); } @@ -418,7 +416,6 @@ public class StrSpliter { addToList(list, str.substring(start, matcher.start()), isTrim, ignoreEmpty); start = matcher.end(); - //检查是否超出范围(最大允许limit-1个,剩下一个留给末尾字符串) if (limit > 0 && list.size() > limit - 2) { break; } diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/support/Try.java b/blade-core-tool/src/main/java/org/springblade/core/tool/support/Try.java index 215a0a5..7666122 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/support/Try.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/support/Try.java @@ -26,6 +26,12 @@ public class Try { @FunctionalInterface public interface UncheckedFunction { + /** + * 调用 + * @param t + * @return + * @throws Exception + */ R apply(T t) throws Exception; } } diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/AESUtil.java b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/AesUtil.java similarity index 94% rename from blade-core-tool/src/main/java/org/springblade/core/tool/utils/AESUtil.java rename to blade-core-tool/src/main/java/org/springblade/core/tool/utils/AesUtil.java index 478a4aa..5b51897 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/AESUtil.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/AesUtil.java @@ -28,9 +28,9 @@ import java.util.Arrays; * * @author L.cm */ -public class AESUtil { +public class AesUtil { - private AESUtil() { + private AesUtil() { } public static String genAesKey() { @@ -68,7 +68,7 @@ public class AESUtil { SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES"); IvParameterSpec iv = new IvParameterSpec(aesKey, 0, 16); cipher.init(Cipher.ENCRYPT_MODE, keySpec, iv); - return cipher.doFinal(PKCS7Encoder.encode(content)); + return cipher.doFinal(Pkcs7Encoder.encode(content)); } catch (Exception e) { throw Exceptions.unchecked(e); } @@ -81,7 +81,7 @@ public class AESUtil { SecretKeySpec keySpec = new SecretKeySpec(aesKey, "AES"); IvParameterSpec iv = new IvParameterSpec(Arrays.copyOfRange(aesKey, 0, 16)); cipher.init(Cipher.DECRYPT_MODE, keySpec, iv); - return PKCS7Encoder.decode(cipher.doFinal(encrypted)); + return Pkcs7Encoder.decode(cipher.doFinal(encrypted)); } catch (Exception e) { throw Exceptions.unchecked(e); } @@ -90,7 +90,7 @@ public class AESUtil { /** * 提供基于PKCS7算法的加解密接口. */ - static class PKCS7Encoder { + static class Pkcs7Encoder { static int BLOCK_SIZE = 32; static byte[] encode(byte[] src) { @@ -115,7 +115,7 @@ public class AESUtil { static byte[] decode(byte[] decrypted) { int pad = (int) decrypted[decrypted.length - 1]; - if (pad < 1 || pad > 32) { + if (pad < 1 || pad > BLOCK_SIZE) { pad = 0; } if (pad > 0) { diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/DateTimeUtil.java b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/DateTimeUtil.java index dff685c..5ef96f3 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/DateTimeUtil.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/DateTimeUtil.java @@ -15,8 +15,6 @@ */ package org.springblade.core.tool.utils; -import org.springblade.core.tool.date.DatePattern; - import java.time.Instant; import java.time.LocalDateTime; import java.time.ZoneId; @@ -29,9 +27,9 @@ import java.time.temporal.TemporalAccessor; * @author L.cm */ public class DateTimeUtil { - public static final DateTimeFormatter DATETIME_FORMAT = DateTimeFormatter.ofPattern(DatePattern.NORM_DATETIME_PATTERN); - public static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern(DatePattern.NORM_DATE_PATTERN); - public static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern(DatePattern.NORM_TIME_PATTERN); + public static final DateTimeFormatter DATETIME_FORMAT = DateTimeFormatter.ofPattern(DateUtil.PATTERN_DATETIME); + public static final DateTimeFormatter DATE_FORMAT = DateTimeFormatter.ofPattern(DateUtil.PATTERN_DATE); + public static final DateTimeFormatter TIME_FORMAT = DateTimeFormatter.ofPattern(DateUtil.PATTERN_TIME); /** * 日期时间格式化 diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/Exceptions.java b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/Exceptions.java index 5898960..d9bba66 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/Exceptions.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/Exceptions.java @@ -23,6 +23,8 @@ import java.lang.reflect.UndeclaredThrowableException; /** * 异常处理工具类 + * + * @author L.cm */ public class Exceptions { diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/Func.java b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/Func.java index 3c95f46..470f89d 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/Func.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/Func.java @@ -18,8 +18,6 @@ package org.springblade.core.tool.utils; import com.fasterxml.jackson.core.JsonParser; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.JsonNode; -import org.springblade.core.tool.date.ConcurrentDateFormat; -import org.springblade.core.tool.date.DateUtil; import org.springblade.core.tool.jackson.JsonUtil; import org.springframework.beans.BeansException; import org.springframework.core.MethodParameter; @@ -608,12 +606,7 @@ public class Func { if (value != null) { String val = String.valueOf(value); val = val.toLowerCase().trim(); - if ("true".equalsIgnoreCase(val)) { - return true; - } else if ("false".equalsIgnoreCase(val)) { - return false; - } - throw new RuntimeException("The value can not parse to Boolean : " + val); + return Boolean.parseBoolean(val); } return defaultValue; } @@ -905,7 +898,7 @@ public class Func { * @param closeable 自动关闭 */ public static void closeQuietly(@Nullable Closeable closeable) { - IOUtil.closeQuietly(closeable); + IoUtil.closeQuietly(closeable); } /** @@ -916,7 +909,7 @@ public class Func { * @throws NullPointerException if the input is null */ public static String toString(InputStream input) { - return IOUtil.toString(input); + return IoUtil.toString(input); } /** @@ -928,11 +921,11 @@ public class Func { * @throws NullPointerException if the input is null */ public static String toString(@Nullable InputStream input, Charset charset) { - return IOUtil.toString(input, charset); + return IoUtil.toString(input, charset); } public static byte[] toByteArray(@Nullable InputStream input) { - return IOUtil.toByteArray(input); + return IoUtil.toByteArray(input); } /** @@ -1078,7 +1071,7 @@ public class Func { * @return the encoded String */ public static String encode(String source) { - return URLUtil.encode(source, Charsets.UTF_8); + return UrlUtil.encode(source, Charsets.UTF_8); } /** @@ -1093,7 +1086,7 @@ public class Func { * @return the encoded String */ public static String encode(String source, Charset charset) { - return URLUtil.encode(source, charset); + return UrlUtil.encode(source, charset); } /** diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/ImageUtil.java b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/ImageUtil.java index 0066291..6856c81 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/ImageUtil.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/ImageUtil.java @@ -1,4 +1,18 @@ - +/** + * Copyright (c) 2018-2028, Chill Zhuang 庄骞 (smallchill@163.com). + *

+ * Licensed under the GNU LESSER GENERAL PUBLIC LICENSE; + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * http://www.gnu.org/licenses/lgpl.html + *

+ * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ package org.springblade.core.tool.utils; import org.slf4j.Logger; @@ -14,6 +28,11 @@ import java.awt.image.*; import java.io.*; import java.net.URL; +/** + * 图片工具类 + * + * @author smallchill + */ public final class ImageUtil { /** @@ -130,12 +149,12 @@ public final class ImageUtil { Image image = src.getScaledInstance(width, height, Image.SCALE_DEFAULT); BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics g = tag.getGraphics(); - // 绘制缩小后的图 + g.drawImage(image, 0, 0, null); g.dispose(); - // 输出为文件 + ImageIO.write(tag, defaultString(type, DEFAULT_IMG_TYPE), output); - // 关闭流 + output.close(); } catch (IOException e) { LOGGER.error("Error in zoom image", e); @@ -154,7 +173,7 @@ public final class ImageUtil { */ public final static void zoomFixed(BufferedImage src, OutputStream output, String type, int height, int width, boolean bb, Color fillColor) { try { - double ratio = 0.0; // 缩放比例 + double ratio = 0.0; Image itemp = src.getScaledInstance(width, height, BufferedImage.SCALE_SMOOTH); // 计算比例 if (src.getHeight() > src.getWidth()) { @@ -212,7 +231,7 @@ public final class ImageUtil { Image img = Toolkit.getDefaultToolkit().createImage(new FilteredImageSource(image.getSource(), cropFilter)); BufferedImage tag = new BufferedImage(width, height, BufferedImage.TYPE_INT_RGB); Graphics g = tag.getGraphics(); - g.drawImage(img, 0, 0, width, height, null); // 绘制切割后的图 + g.drawImage(img, 0, 0, width, height, null); g.dispose(); // 输出为文件 ImageIO.write(tag, defaultString(type, DEFAULT_IMG_TYPE), output); diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/IOUtil.java b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/IoUtil.java similarity index 91% rename from blade-core-tool/src/main/java/org/springblade/core/tool/utils/IOUtil.java rename to blade-core-tool/src/main/java/org/springblade/core/tool/utils/IoUtil.java index b4047ad..55bcd04 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/IOUtil.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/IoUtil.java @@ -23,11 +23,11 @@ import java.io.InputStream; import java.io.OutputStream; /** - * IOUtil + * IoUtil * * @author L.cm */ -public class IOUtil extends org.springframework.util.StreamUtils { +public class IoUtil extends org.springframework.util.StreamUtils { /** * closeQuietly @@ -63,21 +63,21 @@ public class IOUtil extends org.springframework.util.StreamUtils { */ public static String toString(@Nullable InputStream input, java.nio.charset.Charset charset) { try { - return IOUtil.copyToString(input, charset); + return IoUtil.copyToString(input, charset); } catch (IOException e) { throw Exceptions.unchecked(e); } finally { - IOUtil.closeQuietly(input); + IoUtil.closeQuietly(input); } } public static byte[] toByteArray(@Nullable InputStream input) { try { - return IOUtil.copyToByteArray(input); + return IoUtil.copyToByteArray(input); } catch (IOException e) { throw Exceptions.unchecked(e); } finally { - IOUtil.closeQuietly(input); + IoUtil.closeQuietly(input); } } diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/OKHttpUtil.java b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/OkHttpUtil.java similarity index 99% rename from blade-core-tool/src/main/java/org/springblade/core/tool/utils/OKHttpUtil.java rename to blade-core-tool/src/main/java/org/springblade/core/tool/utils/OkHttpUtil.java index 4eaef6b..2e4f5cc 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/OKHttpUtil.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/OkHttpUtil.java @@ -26,7 +26,7 @@ import java.util.Map; * @author smallchill */ @Slf4j -public class OKHttpUtil { +public class OkHttpUtil { public static MediaType JSON = MediaType.parse("application/json; charset=utf-8"); public static MediaType XML = MediaType.parse("application/xml; charset=utf-8"); diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/StringPool.java b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/StringPool.java index 440828b..07b9eed 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/StringPool.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/StringPool.java @@ -78,5 +78,9 @@ public interface StringPool { String ONE = "1"; String ZERO = "0"; String DOLLAR_LEFT_BRACE= "${"; + char U_A = 'A'; + char L_A = 'a'; + char U_Z = 'Z'; + char L_Z = 'z'; } diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/StringUtil.java b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/StringUtil.java index 19e2773..59b27fb 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/StringUtil.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/StringUtil.java @@ -199,10 +199,10 @@ public class StringUtil extends org.springframework.util.StringUtils { return txt.replaceAll("[  `·•�\\f\\t\\v\\s]", ""); } - // 随机字符串 - private static final String _INT = "0123456789"; - private static final String _STR = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; - private static final String _ALL = _INT + _STR; + + private static final String S_INT = "0123456789"; + private static final String S_STR = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"; + private static final String S_ALL = S_INT + S_STR; /** * 随机数生成 @@ -230,11 +230,11 @@ public class StringUtil extends org.springframework.util.StringUtils { char[] buffer = new char[count]; for (int i = 0; i < count; i++) { if (RandomType.INT == randomType) { - buffer[i] = _INT.charAt(random.nextInt(_INT.length())); + buffer[i] = S_INT.charAt(random.nextInt(S_INT.length())); } else if (RandomType.STRING == randomType) { - buffer[i] = _STR.charAt(random.nextInt(_STR.length())); + buffer[i] = S_STR.charAt(random.nextInt(S_STR.length())); } else { - buffer[i] = _ALL.charAt(random.nextInt(_ALL.length())); + buffer[i] = S_ALL.charAt(random.nextInt(S_ALL.length())); } } return new String(buffer); @@ -749,7 +749,7 @@ public class StringUtil extends org.springframework.util.StringUtils { final String str2 = str.toString(); if (str2.startsWith(prefix.toString())) { - return subSuf(str2, prefix.length());// 截取后半段 + return subSuf(str2, prefix.length()); } return str2; } @@ -768,7 +768,7 @@ public class StringUtil extends org.springframework.util.StringUtils { final String str2 = str.toString(); if (str2.toLowerCase().startsWith(prefix.toString().toLowerCase())) { - return subSuf(str2, prefix.length());// 截取后半段 + return subSuf(str2, prefix.length()); } return str2; } @@ -787,7 +787,7 @@ public class StringUtil extends org.springframework.util.StringUtils { final String str2 = str.toString(); if (str2.endsWith(suffix.toString())) { - return subPre(str2, str2.length() - suffix.length());// 截取前半段 + return subPre(str2, str2.length() - suffix.length()); } return str2; } @@ -830,9 +830,9 @@ public class StringUtil extends org.springframework.util.StringUtils { */ public static String lowerFirst(String str) { char firstChar = str.charAt(0); - if (firstChar >= 'A' && firstChar <= 'Z') { + if (firstChar >= StringPool.U_A && firstChar <= StringPool.U_Z) { char[] arr = str.toCharArray(); - arr[0] += ('a' - 'A'); + arr[0] += (StringPool.L_A - StringPool.U_A); return new String(arr); } return str; @@ -846,9 +846,9 @@ public class StringUtil extends org.springframework.util.StringUtils { */ public static String upperFirst(String str) { char firstChar = str.charAt(0); - if (firstChar >= 'a' && firstChar <= 'z') { + if (firstChar >= StringPool.L_A && firstChar <= StringPool.L_Z) { char[] arr = str.toCharArray(); - arr[0] -= ('a' - 'A'); + arr[0] -= (StringPool.L_A - StringPool.U_A); return new String(arr); } return str; diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/SuffixFileFilter.java b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/SuffixFileFilter.java index 6dd74bc..8cf1257 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/SuffixFileFilter.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/SuffixFileFilter.java @@ -23,6 +23,8 @@ import java.io.Serializable; /** * 文件后缀过滤器 + * + * @author smalchill */ public class SuffixFileFilter implements FileFilter, Serializable { diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/URLUtil.java b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/UrlUtil.java similarity index 90% rename from blade-core-tool/src/main/java/org/springblade/core/tool/utils/URLUtil.java rename to blade-core-tool/src/main/java/org/springblade/core/tool/utils/UrlUtil.java index a9c1a2b..bfcaabb 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/URLUtil.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/UrlUtil.java @@ -24,7 +24,7 @@ import java.nio.charset.Charset; * * @author L.cm */ -public class URLUtil extends org.springframework.web.util.UriUtils { +public class UrlUtil extends org.springframework.web.util.UriUtils { /** * url 编码,同js decodeURIComponent @@ -34,7 +34,7 @@ public class URLUtil extends org.springframework.web.util.UriUtils { * @return 编码后的url */ public static String encodeURL(String source, Charset charset) { - return URLUtil.encode(source, charset.name()); + return UrlUtil.encode(source, charset.name()); } /** @@ -45,7 +45,7 @@ public class URLUtil extends org.springframework.web.util.UriUtils { * @return 解码url */ public static String decodeURL(String source, Charset charset) { - return URLUtil.decode(source, charset.name()); + return UrlUtil.decode(source, charset.name()); } /** diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/WebUtil.java b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/WebUtil.java index cdc17a4..bae516f 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/WebUtil.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/WebUtil.java @@ -43,6 +43,8 @@ import java.util.Enumeration; public class WebUtil extends org.springframework.web.util.WebUtils { public static final String USER_AGENT_HEADER = "user-agent"; + + public static final String UN_KNOWN = "unknown"; /** * 判断是否ajax请求 @@ -164,22 +166,22 @@ public class WebUtil extends org.springframework.web.util.WebUtils { public static String getIP(HttpServletRequest request) { Assert.notNull(request, "HttpServletRequest is null"); String ip = request.getHeader("X-Requested-For"); - if (StringUtil.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) { + if (StringUtil.isBlank(ip) || UN_KNOWN.equalsIgnoreCase(ip)) { ip = request.getHeader("X-Forwarded-For"); } - if (StringUtil.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) { + if (StringUtil.isBlank(ip) || UN_KNOWN.equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); } - if (StringUtil.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) { + if (StringUtil.isBlank(ip) || UN_KNOWN.equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); } - if (StringUtil.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) { + if (StringUtil.isBlank(ip) || UN_KNOWN.equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_CLIENT_IP"); } - if (StringUtil.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) { + if (StringUtil.isBlank(ip) || UN_KNOWN.equalsIgnoreCase(ip)) { ip = request.getHeader("HTTP_X_FORWARDED_FOR"); } - if (StringUtil.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) { + if (StringUtil.isBlank(ip) || UN_KNOWN.equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } return StringUtil.isBlank(ip) ? null : ip.split(",")[0]; @@ -227,7 +229,7 @@ public class WebUtil extends org.springframework.web.util.WebUtils { if (contentLength < 0) { return null; } - byte buffer[] = new byte[contentLength]; + byte[] buffer = new byte[contentLength]; for (int i = 0; i < contentLength; ) { int readlen = request.getInputStream().read(buffer, i, contentLength - i); @@ -247,7 +249,7 @@ public class WebUtil extends org.springframework.web.util.WebUtils { * @return * @throws IOException */ - public static String getRequestStr(HttpServletRequest request, byte buffer[]) throws IOException { + public static String getRequestStr(HttpServletRequest request, byte[] buffer) throws IOException { String charEncoding = request.getCharacterEncoding(); if (charEncoding == null) { charEncoding = StringPool.UTF_8; diff --git a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/XmlUtil.java b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/XmlUtil.java index 0e9e9e5..9403ed5 100644 --- a/blade-core-tool/src/main/java/org/springblade/core/tool/utils/XmlUtil.java +++ b/blade-core-tool/src/main/java/org/springblade/core/tool/utils/XmlUtil.java @@ -75,7 +75,7 @@ public class XmlUtil { StringReader sr = new StringReader(xmlStr.trim()); InputSource inputSource = new InputSource(sr); XmlUtil xmlUtil = create(inputSource); - IOUtil.closeQuietly(sr); + IoUtil.closeQuietly(sr); return xmlUtil; } @@ -201,7 +201,7 @@ public class XmlUtil { */ public Map toMap() { Element root = doc.getDocumentElement(); - Map params = new HashMap(); + Map params = new HashMap<>(16); // 将节点封装成map形式 NodeList list = root.getChildNodes(); @@ -224,7 +224,11 @@ public class XmlUtil { return dbf; } - // https://pay.weixin.qq.com/wiki/doc/api/jsapi.php?chapter=23_5 + /** + * preventXXE + * @param dbf + * @throws ParserConfigurationException + */ private static void preventXXE(DocumentBuilderFactory dbf) throws ParserConfigurationException { // This is the PRIMARY defense. If DTDs (doctypes) are disallowed, almost all XML entity attacks are prevented // Xerces 2 only - http://xerces.apache.org/xerces2-j/features.html#disallow-doctype-decl