From 7526b2e787d60fe01eae219144a728d96400847b Mon Sep 17 00:00:00 2001 From: minglipro Date: Mon, 15 Sep 2025 11:20:08 +0800 Subject: [PATCH] =?UTF-8?q?refactor(time):=20=E9=87=8D=E6=9E=84=20DateTime?= =?UTF-8?q?=20=E7=B1=BB=E5=B9=B6=E6=B7=BB=E5=8A=A0=E6=96=B0=E5=8A=9F?= =?UTF-8?q?=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 从 Java 文件中删除了旧的 DateTime 类 - 新增 Kotlin 版本的 DateTime 类,具有以下改进: - 添加了时间格式化枚举类 Formatter - 新增时间位移类 DateTimeOffset - 重构了 parse 和 format 方法,支持新的 Formatter 枚举 - 优化了文件时间转换方法,使用纳秒精度 - 删除了旧的 DateTimeJsonConverter 类 --- build.gradle.kts | 3 +- gradle.properties | 4 +- src/main/java/com/mingliqiye/utils/Main.java | 2 +- .../mingliqiye/utils/functions/Debouncer.java | 93 --- .../utils/functions/P10Function.java | 39 - .../utils/functions/P10RFunction.java | 28 - .../utils/functions/P1Function.java | 28 - .../utils/functions/P1RFunction.java | 28 - .../utils/functions/P2Function.java | 28 - .../utils/functions/P2RFunction.java | 28 - .../utils/functions/P3Function.java | 28 - .../utils/functions/P3RFunction.java | 28 - .../utils/functions/P4Function.java | 28 - .../utils/functions/P4RFunction.java | 28 - .../utils/functions/P5Function.java | 28 - .../utils/functions/P5RFunction.java | 28 - .../utils/functions/P6Function.java | 28 - .../utils/functions/P6RFunction.java | 28 - .../utils/functions/P7Function.java | 28 - .../utils/functions/P7RFunction.java | 28 - .../utils/functions/P8Function.java | 28 - .../utils/functions/P9Function.java | 28 - .../utils/functions/P9RFunction.java | 28 - .../com/mingliqiye/utils/hash/HashUtils.java | 114 --- .../com/mingliqiye/utils/iterator/Range.java | 227 ------ .../mingliqiye/utils/json/GsonJsonApi.java | 70 +- .../mingliqiye/utils/json/JacksonJsonApi.java | 16 +- .../com/mingliqiye/utils/json/JsonApi.java | 390 ---------- .../converters/DateTimeJsonConverter.java | 32 - .../FastjsonJsonStringConverterAdapter.java | 88 --- .../GsonJsonStringConverterAdapter.java | 72 -- .../JacksonJsonStringConverterAdapter.java | 91 --- .../json/converters/JsonStringConverter.java | 60 -- .../converters/UUIDJsonStringConverter.java | 27 - .../com/mingliqiye/utils/time/DateTime.java | 561 --------------- .../mingliqiye/utils/time/DateTimeOffset.java | 65 -- .../mingliqiye/utils/time/DateTimeUnit.java | 65 -- .../com/mingliqiye/utils/time/Formatter.java | 115 --- .../typehandlers/DateTimeTypeHandler.java | 128 ---- src/main/kotlin/com/mingliqiye/utils/Main.kt | 4 +- .../mingliqiye/utils/functions/Functions.kt | 181 +++++ .../com/mingliqiye/utils/hash/HashUtils.kt | 107 +++ .../com/mingliqiye/utils/json/JsonApi.kt | 393 ++++++++++ .../utils/json/converters/JsonConverter.kt} | 20 +- .../json/converters/JsonStringConverter.kt | 254 +++++++ .../mingliqiye/utils/random/RandomBytes.kt | 8 +- .../autoconfigure/GsonAutoConfiguration.kt | 16 +- .../autoconfigure/JacksonAutoConfiguration.kt | 6 +- .../com/mingliqiye/utils/system/SystemUtil.kt | 4 +- .../com/mingliqiye/utils/time/DateTime.kt | 678 ++++++++++++++++++ 50 files changed, 1732 insertions(+), 2705 deletions(-) delete mode 100644 src/main/java/com/mingliqiye/utils/functions/Debouncer.java delete mode 100644 src/main/java/com/mingliqiye/utils/functions/P10Function.java delete mode 100644 src/main/java/com/mingliqiye/utils/functions/P10RFunction.java delete mode 100644 src/main/java/com/mingliqiye/utils/functions/P1Function.java delete mode 100644 src/main/java/com/mingliqiye/utils/functions/P1RFunction.java delete mode 100644 src/main/java/com/mingliqiye/utils/functions/P2Function.java delete mode 100644 src/main/java/com/mingliqiye/utils/functions/P2RFunction.java delete mode 100644 src/main/java/com/mingliqiye/utils/functions/P3Function.java delete mode 100644 src/main/java/com/mingliqiye/utils/functions/P3RFunction.java delete mode 100644 src/main/java/com/mingliqiye/utils/functions/P4Function.java delete mode 100644 src/main/java/com/mingliqiye/utils/functions/P4RFunction.java delete mode 100644 src/main/java/com/mingliqiye/utils/functions/P5Function.java delete mode 100644 src/main/java/com/mingliqiye/utils/functions/P5RFunction.java delete mode 100644 src/main/java/com/mingliqiye/utils/functions/P6Function.java delete mode 100644 src/main/java/com/mingliqiye/utils/functions/P6RFunction.java delete mode 100644 src/main/java/com/mingliqiye/utils/functions/P7Function.java delete mode 100644 src/main/java/com/mingliqiye/utils/functions/P7RFunction.java delete mode 100644 src/main/java/com/mingliqiye/utils/functions/P8Function.java delete mode 100644 src/main/java/com/mingliqiye/utils/functions/P9Function.java delete mode 100644 src/main/java/com/mingliqiye/utils/functions/P9RFunction.java delete mode 100644 src/main/java/com/mingliqiye/utils/hash/HashUtils.java delete mode 100644 src/main/java/com/mingliqiye/utils/iterator/Range.java delete mode 100644 src/main/java/com/mingliqiye/utils/json/JsonApi.java delete mode 100644 src/main/java/com/mingliqiye/utils/json/converters/DateTimeJsonConverter.java delete mode 100644 src/main/java/com/mingliqiye/utils/json/converters/FastjsonJsonStringConverterAdapter.java delete mode 100644 src/main/java/com/mingliqiye/utils/json/converters/GsonJsonStringConverterAdapter.java delete mode 100644 src/main/java/com/mingliqiye/utils/json/converters/JacksonJsonStringConverterAdapter.java delete mode 100644 src/main/java/com/mingliqiye/utils/json/converters/JsonStringConverter.java delete mode 100644 src/main/java/com/mingliqiye/utils/json/converters/UUIDJsonStringConverter.java delete mode 100644 src/main/java/com/mingliqiye/utils/time/DateTime.java delete mode 100644 src/main/java/com/mingliqiye/utils/time/DateTimeOffset.java delete mode 100644 src/main/java/com/mingliqiye/utils/time/DateTimeUnit.java delete mode 100644 src/main/java/com/mingliqiye/utils/time/Formatter.java delete mode 100644 src/main/java/com/mingliqiye/utils/time/typehandlers/DateTimeTypeHandler.java create mode 100644 src/main/kotlin/com/mingliqiye/utils/functions/Functions.kt create mode 100644 src/main/kotlin/com/mingliqiye/utils/hash/HashUtils.kt create mode 100644 src/main/kotlin/com/mingliqiye/utils/json/JsonApi.kt rename src/main/{java/com/mingliqiye/utils/functions/P8RFunction.java => kotlin/com/mingliqiye/utils/json/converters/JsonConverter.kt} (62%) create mode 100644 src/main/kotlin/com/mingliqiye/utils/json/converters/JsonStringConverter.kt create mode 100644 src/main/kotlin/com/mingliqiye/utils/time/DateTime.kt diff --git a/build.gradle.kts b/build.gradle.kts index 41a9c3a..7b28c14 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -16,7 +16,7 @@ * ProjectName mingli-utils * ModuleName mingli-utils * CurrentFile build.gradle.kts - * LastUpdate 2025-09-14 22:32:52 + * LastUpdate 2025-09-15 11:20:04 * UpdateUser MingLiPro */ @@ -31,7 +31,6 @@ plugins { kotlin("jvm") version "2.2.20" id("org.jetbrains.dokka") version "2.0.0" } - val GROUPSID = project.properties["GROUPSID"] as String val VERSIONS = project.properties["VERSIONS"] as String val ARTIFACTID = project.properties["ARTIFACTID"] as String diff --git a/gradle.properties b/gradle.properties index ff10dbb..8348b3f 100644 --- a/gradle.properties +++ b/gradle.properties @@ -16,10 +16,10 @@ # ProjectName mingli-utils # ModuleName mingli-utils # CurrentFile gradle.properties -# LastUpdate 2025-09-15 09:25:10 +# LastUpdate 2025-09-15 11:19:10 # UpdateUser MingLiPro # JDKVERSIONS=1.8 GROUPSID=com.mingliqiye.utils ARTIFACTID=mingli-utils -VERSIONS=4.0.0-pre +VERSIONS=4.0.1 diff --git a/src/main/java/com/mingliqiye/utils/Main.java b/src/main/java/com/mingliqiye/utils/Main.java index 7b8d6d2..4faa62b 100644 --- a/src/main/java/com/mingliqiye/utils/Main.java +++ b/src/main/java/com/mingliqiye/utils/Main.java @@ -16,7 +16,7 @@ * ProjectName mingli-utils * ModuleName mingli-utils.main * CurrentFile Main.java - * LastUpdate 2025-09-15 09:24:07 + * LastUpdate 2025-09-15 11:18:12 * UpdateUser MingLiPro */ diff --git a/src/main/java/com/mingliqiye/utils/functions/Debouncer.java b/src/main/java/com/mingliqiye/utils/functions/Debouncer.java deleted file mode 100644 index 6e02bac..0000000 --- a/src/main/java/com/mingliqiye/utils/functions/Debouncer.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile Debouncer.java - * LastUpdate 2025-09-09 08:37:34 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.functions; - -import java.util.concurrent.*; - -/** - * 防抖器类,用于实现防抖功能,防止在短时间内重复执行相同任务 - * - * @author MingLiPro - */ -public class Debouncer { - - private final ScheduledExecutorService scheduler = - Executors.newSingleThreadScheduledExecutor(); - private final ConcurrentHashMap> delayedMap = - new ConcurrentHashMap<>(); - private final long delay; - - /** - * 构造函数,创建一个防抖器实例 - * - * @param delay 延迟时间 - * @param unit 时间单位 - */ - public Debouncer(long delay, TimeUnit unit) { - this.delay = unit.toMillis(delay); - } - - /** - * 执行防抖操作,如果在指定延迟时间内再次调用相同key的任务,则取消之前的任务并重新计时 - * - * @param key 任务的唯一标识符,用于区分不同任务 - * @param task 要执行的任务 - */ - public void debounce(final Object key, final Runnable task) { - // 提交新任务并获取之前可能存在的任务 - final Future prev = delayedMap.put( - key, - scheduler.schedule( - () -> { - try { - task.run(); - } finally { - // 任务执行完成后从映射中移除 - delayedMap.remove(key); - } - }, - delay, - TimeUnit.MILLISECONDS - ) - ); - - // 如果之前存在任务,则取消它 - if (prev != null) { - prev.cancel(true); - } - } - - /** - * 关闭防抖器,取消所有待执行的任务并关闭调度器 - */ - public void shutdown() { - // 先取消所有延迟任务 - for (Future future : delayedMap.values()) { - future.cancel(true); - } - delayedMap.clear(); - - // 再关闭调度器 - scheduler.shutdownNow(); - } -} diff --git a/src/main/java/com/mingliqiye/utils/functions/P10Function.java b/src/main/java/com/mingliqiye/utils/functions/P10Function.java deleted file mode 100644 index 769f828..0000000 --- a/src/main/java/com/mingliqiye/utils/functions/P10Function.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile P10Function.java - * LastUpdate 2025-09-09 08:37:33 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.functions; - -@FunctionalInterface -public interface P10Function { - void call( - P p, - P1 p1, - P2 p2, - P3 p3, - P4 p4, - P5 p5, - P6 p6, - P7 p7, - P8 p8, - P9 p9 - ); -} diff --git a/src/main/java/com/mingliqiye/utils/functions/P10RFunction.java b/src/main/java/com/mingliqiye/utils/functions/P10RFunction.java deleted file mode 100644 index a2a119c..0000000 --- a/src/main/java/com/mingliqiye/utils/functions/P10RFunction.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile P10RFunction.java - * LastUpdate 2025-09-09 08:37:33 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.functions; - -@FunctionalInterface -public interface P10RFunction { - R call(P p, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9); -} diff --git a/src/main/java/com/mingliqiye/utils/functions/P1Function.java b/src/main/java/com/mingliqiye/utils/functions/P1Function.java deleted file mode 100644 index d9da94f..0000000 --- a/src/main/java/com/mingliqiye/utils/functions/P1Function.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile P1Function.java - * LastUpdate 2025-09-09 08:37:33 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.functions; - -@FunctionalInterface -public interface P1Function

{ - void call(P p); -} diff --git a/src/main/java/com/mingliqiye/utils/functions/P1RFunction.java b/src/main/java/com/mingliqiye/utils/functions/P1RFunction.java deleted file mode 100644 index 05d6f8d..0000000 --- a/src/main/java/com/mingliqiye/utils/functions/P1RFunction.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile P1RFunction.java - * LastUpdate 2025-09-09 08:37:34 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.functions; - -@FunctionalInterface -public interface P1RFunction { - R call(P p); -} diff --git a/src/main/java/com/mingliqiye/utils/functions/P2Function.java b/src/main/java/com/mingliqiye/utils/functions/P2Function.java deleted file mode 100644 index 5cdca88..0000000 --- a/src/main/java/com/mingliqiye/utils/functions/P2Function.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile P2Function.java - * LastUpdate 2025-09-09 08:37:33 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.functions; - -@FunctionalInterface -public interface P2Function { - void call(P p, P1 p1); -} diff --git a/src/main/java/com/mingliqiye/utils/functions/P2RFunction.java b/src/main/java/com/mingliqiye/utils/functions/P2RFunction.java deleted file mode 100644 index 4fb00ca..0000000 --- a/src/main/java/com/mingliqiye/utils/functions/P2RFunction.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile P2RFunction.java - * LastUpdate 2025-09-09 08:37:34 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.functions; - -@FunctionalInterface -public interface P2RFunction { - R call(P p, P1 p1); -} diff --git a/src/main/java/com/mingliqiye/utils/functions/P3Function.java b/src/main/java/com/mingliqiye/utils/functions/P3Function.java deleted file mode 100644 index cc8a285..0000000 --- a/src/main/java/com/mingliqiye/utils/functions/P3Function.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile P3Function.java - * LastUpdate 2025-09-09 08:37:33 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.functions; - -@FunctionalInterface -public interface P3Function { - void call(P p, P1 p1, P2 p2); -} diff --git a/src/main/java/com/mingliqiye/utils/functions/P3RFunction.java b/src/main/java/com/mingliqiye/utils/functions/P3RFunction.java deleted file mode 100644 index ff4b06c..0000000 --- a/src/main/java/com/mingliqiye/utils/functions/P3RFunction.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile P3RFunction.java - * LastUpdate 2025-09-09 08:37:33 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.functions; - -@FunctionalInterface -public interface P3RFunction { - R call(P p, P1 p1, P2 p2); -} diff --git a/src/main/java/com/mingliqiye/utils/functions/P4Function.java b/src/main/java/com/mingliqiye/utils/functions/P4Function.java deleted file mode 100644 index 8fa1b26..0000000 --- a/src/main/java/com/mingliqiye/utils/functions/P4Function.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile P4Function.java - * LastUpdate 2025-09-09 08:37:33 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.functions; - -@FunctionalInterface -public interface P4Function { - void call(P p, P1 p1, P2 p2, P3 p3); -} diff --git a/src/main/java/com/mingliqiye/utils/functions/P4RFunction.java b/src/main/java/com/mingliqiye/utils/functions/P4RFunction.java deleted file mode 100644 index 3635b63..0000000 --- a/src/main/java/com/mingliqiye/utils/functions/P4RFunction.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile P4RFunction.java - * LastUpdate 2025-09-09 08:37:34 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.functions; - -@FunctionalInterface -public interface P4RFunction { - R call(P p, P1 p1, P2 p2, P3 p3); -} diff --git a/src/main/java/com/mingliqiye/utils/functions/P5Function.java b/src/main/java/com/mingliqiye/utils/functions/P5Function.java deleted file mode 100644 index b447986..0000000 --- a/src/main/java/com/mingliqiye/utils/functions/P5Function.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile P5Function.java - * LastUpdate 2025-09-09 08:37:33 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.functions; - -@FunctionalInterface -public interface P5Function { - void call(P p, P1 p1, P2 p2, P3 p3, P4 p4); -} diff --git a/src/main/java/com/mingliqiye/utils/functions/P5RFunction.java b/src/main/java/com/mingliqiye/utils/functions/P5RFunction.java deleted file mode 100644 index b680a91..0000000 --- a/src/main/java/com/mingliqiye/utils/functions/P5RFunction.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile P5RFunction.java - * LastUpdate 2025-09-09 08:37:33 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.functions; - -@FunctionalInterface -public interface P5RFunction { - R call(P p, P1 p1, P2 p2, P3 p3, P4 p4); -} diff --git a/src/main/java/com/mingliqiye/utils/functions/P6Function.java b/src/main/java/com/mingliqiye/utils/functions/P6Function.java deleted file mode 100644 index 7fb3967..0000000 --- a/src/main/java/com/mingliqiye/utils/functions/P6Function.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile P6Function.java - * LastUpdate 2025-09-09 08:37:33 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.functions; - -@FunctionalInterface -public interface P6Function { - void call(P p, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5); -} diff --git a/src/main/java/com/mingliqiye/utils/functions/P6RFunction.java b/src/main/java/com/mingliqiye/utils/functions/P6RFunction.java deleted file mode 100644 index 4dd9d8d..0000000 --- a/src/main/java/com/mingliqiye/utils/functions/P6RFunction.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile P6RFunction.java - * LastUpdate 2025-09-09 08:37:33 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.functions; - -@FunctionalInterface -public interface P6RFunction { - R call(P p, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5); -} diff --git a/src/main/java/com/mingliqiye/utils/functions/P7Function.java b/src/main/java/com/mingliqiye/utils/functions/P7Function.java deleted file mode 100644 index 8929fb6..0000000 --- a/src/main/java/com/mingliqiye/utils/functions/P7Function.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile P7Function.java - * LastUpdate 2025-09-09 08:37:34 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.functions; - -@FunctionalInterface -public interface P7Function { - void call(P p, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6); -} diff --git a/src/main/java/com/mingliqiye/utils/functions/P7RFunction.java b/src/main/java/com/mingliqiye/utils/functions/P7RFunction.java deleted file mode 100644 index 1b32910..0000000 --- a/src/main/java/com/mingliqiye/utils/functions/P7RFunction.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile P7RFunction.java - * LastUpdate 2025-09-09 08:37:33 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.functions; - -@FunctionalInterface -public interface P7RFunction { - R call(P p, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6); -} diff --git a/src/main/java/com/mingliqiye/utils/functions/P8Function.java b/src/main/java/com/mingliqiye/utils/functions/P8Function.java deleted file mode 100644 index f296789..0000000 --- a/src/main/java/com/mingliqiye/utils/functions/P8Function.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile P8Function.java - * LastUpdate 2025-09-09 08:37:34 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.functions; - -@FunctionalInterface -public interface P8Function { - void call(P p, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7); -} diff --git a/src/main/java/com/mingliqiye/utils/functions/P9Function.java b/src/main/java/com/mingliqiye/utils/functions/P9Function.java deleted file mode 100644 index 65ad573..0000000 --- a/src/main/java/com/mingliqiye/utils/functions/P9Function.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile P9Function.java - * LastUpdate 2025-09-09 08:37:33 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.functions; - -@FunctionalInterface -public interface P9Function { - void call(P p, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8); -} diff --git a/src/main/java/com/mingliqiye/utils/functions/P9RFunction.java b/src/main/java/com/mingliqiye/utils/functions/P9RFunction.java deleted file mode 100644 index 93f1979..0000000 --- a/src/main/java/com/mingliqiye/utils/functions/P9RFunction.java +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile P9RFunction.java - * LastUpdate 2025-09-09 08:37:33 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.functions; - -@FunctionalInterface -public interface P9RFunction { - R call(P p, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8); -} diff --git a/src/main/java/com/mingliqiye/utils/hash/HashUtils.java b/src/main/java/com/mingliqiye/utils/hash/HashUtils.java deleted file mode 100644 index b2121a5..0000000 --- a/src/main/java/com/mingliqiye/utils/hash/HashUtils.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile HashUtils.java - * LastUpdate 2025-09-09 08:37:33 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.hash; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.security.Security; -import org.bouncycastle.jce.provider.BouncyCastleProvider; -import org.mindrot.jbcrypt.BCrypt; - -/** - * 提供常用的哈希计算工具方法,包括文件哈希值计算、BCrypt 加密等。 - * - * @author MingLiPro - */ -public class HashUtils { - - static { - Security.addProvider(new BouncyCastleProvider()); - } - - /** - * 计算指定文件的哈希值。 - * - * @param file 要计算哈希值的文件对象 - * @param algorithm 使用的哈希算法名称(如 SHA-256、MD5 等) - * @return 文件的十六进制格式哈希值字符串 - * @throws IOException 当文件不存在或读取过程中发生 I/O 错误时抛出 - * @throws NoSuchAlgorithmException 当指定的哈希算法不可用时抛出 - */ - public static String calculateFileHash(File file, String algorithm) - throws IOException, NoSuchAlgorithmException { - // 检查文件是否存在 - if (!file.exists()) { - throw new IOException("File not found: " + file.getAbsolutePath()); - } - - MessageDigest digest = MessageDigest.getInstance(algorithm); - - try (FileInputStream fis = new FileInputStream(file)) { - byte[] buffer = new byte[8192]; - int bytesRead; - - // 分块读取文件内容并更新摘要 - while ((bytesRead = fis.read(buffer)) != -1) { - digest.update(buffer, 0, bytesRead); - } - } - - return bytesToHex(digest.digest()); - } - - /** - * 将字节数组转换为十六进制字符串表示。 - * - * @param bytes 输入的字节数组 - * @return 对应的十六进制字符串 - */ - private static String bytesToHex(byte[] bytes) { - StringBuilder hexString = new StringBuilder(2 * bytes.length); - for (byte b : bytes) { - String hex = Integer.toHexString(0xff & b); - if (hex.length() == 1) { - hexString.append('0'); - } - hexString.append(hex); - } - return hexString.toString(); - } - - /** - * 使用 BCrypt 算法对字符串进行加密。 - * - * @param string 需要加密的明文字符串 - * @return 加密后的 BCrypt 哈希字符串 - */ - public static String bcrypt(String string) { - return BCrypt.hashpw(string, BCrypt.gensalt()); - } - - /** - * 验证给定字符串与 BCrypt 哈希是否匹配。 - * - * @param string 明文字符串 - * @param bcrypted 已经使用 BCrypt 加密的哈希字符串 - * @return 如果匹配返回 true,否则返回 false - */ - public static boolean checkBcrypt(String string, String bcrypted) { - return BCrypt.checkpw(string, bcrypted); - } -} diff --git a/src/main/java/com/mingliqiye/utils/iterator/Range.java b/src/main/java/com/mingliqiye/utils/iterator/Range.java deleted file mode 100644 index 1ddd73e..0000000 --- a/src/main/java/com/mingliqiye/utils/iterator/Range.java +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile Range.java - * LastUpdate 2025-09-15 09:22:02 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.iterator; - -import kotlin.ranges.ClosedRange; -import kotlin.ranges.OpenEndRange; -import lombok.Getter; -import lombok.val; -import org.jetbrains.annotations.NotNull; - -import java.util.Iterator; - -/** - * 范围 Range
- * Iterable 可遍历对象
- * 类似 KT的 {@code 0..10 = Range.of(0,10)} {@code 0..10 step 2 = Range.of(0,10,2)} - * @author MingLiPro - * @since 3.2.6 - */ -@Getter -public class Range - implements Iterable, ClosedRange, OpenEndRange { - - private final int start; - private final int end; - private final int step; - private int current; - - /** - * 创建一个范围
- * 最大值{@code Integer.MAX_VALUE = 2147483647 }
- * 最小值{@code Integer.MIN_VALUE = -2147483648}
- * @param start 开始 (包含) - * @param end 完毕 (包含) - * @see Integer - */ - public Range(int start, int end) { - this(start, end, 1); - } - - /** - * 创建一个范围
- * 最大值{@code Integer.MAX_VALUE = 2147483647 }
- * 最小值{@code Integer.MIN_VALUE = -2147483648}
- * @param start 开始 (包含) - * @param end 完毕 (包含) - * @param step 步长 - * @see Integer - */ - public Range(int start, int end, int step) { - this.start = start; - this.current = start; - this.step = step; - this.end = end + 1; - } - - /** - * 创建一个范围 {@code 0 - range}
- * 最大值{@code Integer.MAX_VALUE = 2147483647 }
- * 最小值{@code Integer.MIN_VALUE = -2147483648}
- * @param range 完毕 (包含) - * @see Integer - */ - public Range(int range) { - this(0, range); - } - - /** - * 创建一个范围 {@code 0 - range}
- * 最大值{@code Integer.MAX_VALUE = 2147483647 }
- * 最小值{@code Integer.MIN_VALUE = -2147483648}
- * @param range 完毕 (包含) - * @see Integer - * @return Range 对象 - */ - public static Range of(int range) { - return new Range(range); - } - - /** - * 创建一个范围
- * 最大值{@code Integer.MAX_VALUE = 2147483647 }
- * 最小值{@code Integer.MIN_VALUE = -2147483648}
- * @param start 开始 (包含) - * @param end 完毕 (包含) - * @see Integer - * @return Range 对象 - */ - public static Range of(int start, int end) { - return new Range(start, end); - } - - /** - * 创建一个范围
- * 最大值{@code Integer.MAX_VALUE = 2147483647 }
- * 最小值{@code Integer.MIN_VALUE = -2147483648}
- * @param start 开始 (包含) - * @param end 完毕 (包含) - * @param step 步长 - * @see Integer - */ - public static Range of(int start, int end, int step) { - return new Range(start, end, step); - } - - /** - * 创建一个范围
- * 最大值{@code Integer.MAX_VALUE = 2147483647 }
- * 最小值{@code Integer.MIN_VALUE = -2147483648}
- * @param start 开始 (包含) - * @param end 完毕 (包含) - * @param step 步长 - * @see Integer - */ - public static Range range(int start, int end, int step) { - return new Range(start, end, step); - } - - /** - * 创建一个范围 {@code 0 - range}
- * 最大值{@code Integer.MAX_VALUE = 2147483647 }
- * 最小值{@code Integer.MIN_VALUE = -2147483648}
- * @param range 完毕 (包含) - * @see Integer - * @return Range 对象 - */ - public static Range range(int range) { - return new Range(range); - } - - /** - * 创建一个范围
- * 最大值{@code Integer.MAX_VALUE = 2147483647 }
- * 最小值{@code Integer.MIN_VALUE = -2147483648}
- * @param start 开始 (包含) - * @param end 完毕 (包含) - * @see Integer - * @return Range 对象 - */ - public static Range range(int start, int end) { - return new Range(start, end); - } - - /** - * 获取迭代器 - * @return 迭代器 - */ - @Override - public @NotNull Iterator iterator() { - return new Iterator() { - @Override - public boolean hasNext() { - return current < end; - } - - @Override - public Integer next() { - if (current >= end) { - return null; - } - - try { - return current; - } finally { - current = current + step; - } - } - }; - } - - @Override - public boolean isEmpty() { - return current < end; - } - - @Override - public @NotNull Integer getEndInclusive() { - val va = end - step; - return Math.max(va, 0); - } - - @Override - public boolean contains(@NotNull Integer integer) { - if (step == 0) return false; - if (step > 0) { - if (integer < start || integer > end) return false; - } else { - if (integer > start || integer < end) return false; - } - return (integer - start) % step == 0; - } - - @Override - public @NotNull Integer getEndExclusive() { - return end; - } - - @Override - public @NotNull Integer getStart() { - return start; - } - - @Override - public String toString() { - return String.format("Range(start=%s,end=%s,step=%s)", start, end, step); - } -} diff --git a/src/main/java/com/mingliqiye/utils/json/GsonJsonApi.java b/src/main/java/com/mingliqiye/utils/json/GsonJsonApi.java index 455a64e..5465335 100644 --- a/src/main/java/com/mingliqiye/utils/json/GsonJsonApi.java +++ b/src/main/java/com/mingliqiye/utils/json/GsonJsonApi.java @@ -1,13 +1,38 @@ +/* + * Copyright 2025 mingliqiye + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + * + * ProjectName mingli-utils + * ModuleName mingli-utils.main + * CurrentFile GsonJsonApi.java + * LastUpdate 2025-09-15 11:20:04 + * UpdateUser MingLiPro + */ + package com.mingliqiye.utils.json; import com.google.gson.*; +import com.mingliqiye.utils.json.converters.JsonConverter; +import com.mingliqiye.utils.json.converters.JsonStringConverter; +import org.jetbrains.annotations.NotNull; public class GsonJsonApi implements JsonApi { - private final Gson gson; - private final Gson gsonUnicode; - private final Gson gsonPretty; - private final Gson gsonPrettyUnicode; + private Gson gsonUnicode; + private Gson gsonPretty; + private Gson gsonPrettyUnicode; + private Gson gson; public GsonJsonApi() { gson = new GsonBuilder() @@ -184,4 +209,41 @@ public class GsonJsonApi implements JsonApi { String json = gson.toJson(source); return gson.fromJson(json, destinationType.getType()); } + + @Override + public void addJsonConverter(@NotNull JsonConverter c) { + gson = gson + .newBuilder() + .registerTypeAdapter( + c.getTClass(), + c.getStringConverter().getGsonJsonStringConverterAdapter() + ) + .create(); + gsonUnicode = gsonUnicode + .newBuilder() + .registerTypeAdapter( + c.getTClass(), + c.getStringConverter().getGsonJsonStringConverterAdapter() + ) + .create(); + gsonPretty = gsonPretty + .newBuilder() + .registerTypeAdapter( + c.getTClass(), + c.getStringConverter().getGsonJsonStringConverterAdapter() + ) + .create(); + gsonPrettyUnicode = gsonPrettyUnicode + .newBuilder() + .registerTypeAdapter( + c.getTClass(), + c.getStringConverter().getGsonJsonStringConverterAdapter() + ) + .create(); + } + + @Override + public void addJsonStringConverter(@NotNull JsonStringConverter c) { + addJsonConverter(c); + } } diff --git a/src/main/java/com/mingliqiye/utils/json/JacksonJsonApi.java b/src/main/java/com/mingliqiye/utils/json/JacksonJsonApi.java index 67830e0..5021b67 100644 --- a/src/main/java/com/mingliqiye/utils/json/JacksonJsonApi.java +++ b/src/main/java/com/mingliqiye/utils/json/JacksonJsonApi.java @@ -16,7 +16,7 @@ * ProjectName mingli-utils * ModuleName mingli-utils.main * CurrentFile JacksonJsonApi.java - * LastUpdate 2025-09-09 09:31:31 + * LastUpdate 2025-09-15 11:16:53 * UpdateUser MingLiPro */ @@ -28,6 +28,10 @@ import com.fasterxml.jackson.databind.JsonNode; import com.fasterxml.jackson.databind.ObjectMapper; import com.fasterxml.jackson.databind.ObjectReader; import com.fasterxml.jackson.databind.node.ObjectNode; +import com.mingliqiye.utils.json.converters.JsonConverter; +import com.mingliqiye.utils.json.converters.JsonStringConverter; +import org.jetbrains.annotations.NotNull; + import java.io.IOException; import java.util.List; import java.util.Map; @@ -338,4 +342,14 @@ public class JacksonJsonApi implements JsonApi { objectMapper.constructType(destinationType.getType()) ); } + + @Override + public void addJsonConverter(@NotNull JsonConverter c) { + objectMapper.registerModule(c.getStringConverter().getJacksonJsonStringConverterAdapter().getJacksonModule()); + } + + @Override + public void addJsonStringConverter(@NotNull JsonStringConverter c) { + addJsonConverter(c); + } } diff --git a/src/main/java/com/mingliqiye/utils/json/JsonApi.java b/src/main/java/com/mingliqiye/utils/json/JsonApi.java deleted file mode 100644 index 4c500a8..0000000 --- a/src/main/java/com/mingliqiye/utils/json/JsonApi.java +++ /dev/null @@ -1,390 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile JsonApi.java - * LastUpdate 2025-09-09 09:22:02 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.json; - -import java.io.*; -import java.nio.file.Files; -import java.nio.file.Path; -import java.nio.file.Paths; -import java.util.List; -import java.util.Map; - -/** - * JSON处理接口,提供JSON字符串与Java对象之间的相互转换功能 - */ -public interface JsonApi { - /** - * 将JSON字符串解析为指定类型的对象 - * - * @param json 待解析的JSON字符串 - * @param clazz 目标对象的Class类型 - * @param 泛型参数,表示目标对象的类型 - * @return 解析后的对象实例 - */ - T parse(String json, Class clazz); - - /** - * 将JSON字符串解析为指定泛型类型对象 - * - * @param json 待解析的JSON字符串 - * @param type 目标对象的Type类型(支持泛型) - * @param 泛型参数,表示目标对象的类型 - * @return 解析后的对象实例 - */ - T parse(String json, JsonTypeReference type); - - /** - * 将对象格式化为JSON字符串 - * - * @param object 待格式化的对象 - * @return 格式化后的JSON字符串 - */ - String format(Object object); - - String formatUnicode(Object object); - - default T parseFrom(String path, Class clazz) throws IOException { - return parseFrom(Paths.get(path), clazz); - } - - default T parseFrom(Path path, Class clazz) throws IOException { - return parseFrom(path.toFile(), clazz); - } - - default T parseFrom(File file, Class clazz) throws IOException { - try (InputStream inputStream = Files.newInputStream(file.toPath())) { - return parseFrom(inputStream, clazz); - } - } - - default T parseFrom(InputStream inputStream, Class clazz) - throws IOException { - if (inputStream == null) { - throw new IllegalArgumentException("inputStream cannot be null"); - } - if (clazz == null) { - throw new IllegalArgumentException("clazz cannot be null"); - } - byte[] bytes = new byte[1024]; - try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) { - int readlength; - while ((readlength = inputStream.read(bytes)) != -1) { - bos.write(bytes, 0, readlength); - } - return parse(bos.toByteArray(), clazz); - } - } - - default T parseFrom(String path, JsonTypeReference type) - throws IOException { - return parseFrom(Paths.get(path), type); - } - - default T parseFrom(Path path, JsonTypeReference type) - throws IOException { - return parseFrom(path.toFile(), type); - } - - default T parseFrom(File file, JsonTypeReference type) - throws IOException { - try (InputStream inputStream = Files.newInputStream(file.toPath())) { - return parseFrom(inputStream, type); - } - } - - default T parseFrom(InputStream inputStream, JsonTypeReference type) - throws IOException { - if (inputStream == null) { - throw new IllegalArgumentException("inputStream cannot be null"); - } - if (type == null) { - throw new IllegalArgumentException("type cannot be null"); - } - byte[] bytes = new byte[1024]; - try (ByteArrayOutputStream bos = new ByteArrayOutputStream()) { - int readlength; - while ((readlength = inputStream.read(bytes)) != -1) { - bos.write(bytes, 0, readlength); - } - return parse(bos.toByteArray(), type); - } - } - - /** - * 将字节数组形式的JSON解析为指定类型的对象 - * - * @param json 待解析的JSON字节数组 - * @param clazz 目标对象的Class类型 - * @param 泛型参数,表示目标对象的类型 - * @return 解析后的对象实例 - */ - default T parse(byte[] json, Class clazz) { - return parse(new String(json), clazz); - } - - /** - * 将字节数组形式的JSON解析为指定泛型类型对象 - * - * @param json 待解析的JSON字节数组 - * @param type 目标对象的Type类型(支持泛型) - * @param 泛型参数,表示目标对象的类型 - * @return 解析后的对象实例 - */ - default T parse(byte[] json, JsonTypeReference type) { - return parse(new String(json), type); - } - - /** - * 将JSON字符串解析为指定类型的对象,解析失败时返回默认值 - * - * @param json 待解析的JSON字符串 - * @param clazz 目标对象的Class类型 - * @param defaultValue 解析失败时返回的默认值 - * @param 泛型参数,表示目标对象的类型 - * @return 解析后的对象实例或默认值 - */ - default T parse(String json, Class clazz, T defaultValue) { - try { - return parse(json, clazz); - } catch (Exception e) { - return defaultValue; - } - } - - /** - * 将JSON字符串解析为指定泛型类型对象,解析失败时返回默认值 - * - * @param json 待解析的JSON字符串 - * @param type 目标对象的Type类型(支持泛型) - * @param defaultValue 解析失败时返回的默认值 - * @param 泛型参数,表示目标对象的类型 - * @return 解析后的对象实例或默认值 - */ - default T parse( - String json, - JsonTypeReference type, - T defaultValue - ) { - try { - return parse(json, type); - } catch (Exception e) { - return defaultValue; - } - } - - /** - * 将对象格式化为美化格式的JSON字符串(带缩进和换行) - * - * @param object 待格式化的对象 - * @return 格式化后的美化JSON字符串 - */ - String formatPretty(Object object); - - default byte[] formatPrettyBytes(Object object) { - return formatPretty(object).getBytes(); - } - - String formatPrettyUnicode(Object object); - - default byte[] formatPrettyUnicodeBytes(Object object) { - return formatPrettyUnicode(object).getBytes(); - } - - default void formatPretty(Object object, String file) throws IOException { - formatPretty(object, Paths.get(file)); - } - - default void formatPretty(Object object, Path file) throws IOException { - formatPretty(object, file.toFile()); - } - - default void formatPretty(Object object, File file) throws IOException { - try (FileOutputStream fos = new FileOutputStream(file)) { - formatPretty(object, fos); - } - } - - default void formatPretty(Object object, OutputStream stream) - throws IOException { - stream.write(formatPrettyBytes(object)); - } - - default void formatPrettyUnicode(Object object, String file) - throws IOException { - formatPrettyUnicode(object, Paths.get(file)); - } - - default void formatPrettyUnicode(Object object, Path file) - throws IOException { - formatPrettyUnicode(object, file.toFile()); - } - - default void formatPrettyUnicode(Object object, File file) - throws IOException { - try (FileOutputStream fos = new FileOutputStream(file)) { - formatPrettyUnicode(object, fos); - } - } - - default void formatPrettyUnicode(Object object, OutputStream stream) - throws IOException { - stream.write(formatPrettyUnicodeBytes(object)); - } - - default byte[] formatBytes(Object object) { - return format(object).getBytes(); - } - - default byte[] formatUnicodeBytes(Object object) { - return formatUnicode(object).getBytes(); - } - - default void format(Object object, String file) throws IOException { - format(object, Paths.get(file)); - } - - default void format(Object object, Path file) throws IOException { - format(object, file.toFile()); - } - - default void format(Object object, File file) throws IOException { - try (FileOutputStream fos = new FileOutputStream(file)) { - format(object, fos); - } - } - - default void format(Object object, OutputStream stream) throws IOException { - stream.write(formatPrettyBytes(object)); - } - - default void formatUnicode(Object object, String file) throws IOException { - formatUnicode(object, Paths.get(file)); - } - - default void formatUnicode(Object object, Path file) throws IOException { - formatUnicode(object, file.toFile()); - } - - default void formatUnicode(Object object, File file) throws IOException { - try (FileOutputStream fos = new FileOutputStream(file)) { - formatUnicode(object, fos); - } - } - - default void formatUnicode(Object object, OutputStream stream) - throws IOException { - stream.write(formatPrettyUnicodeBytes(object)); - } - - /** - * 将JSON字符串解析为指定元素类型的List集合 - * - * @param json 待解析的JSON字符串 - * @param elementType List中元素的类型 - * @param 泛型参数,表示List中元素的类型 - * @return 解析后的List集合 - */ - default List parseList(String json, Class elementType) { - return parse(json, JsonTypeUtils.listType(elementType)); - } - - /** - * 将JSON字符串解析为指定键值类型的Map集合 - * - * @param json 待解析的JSON字符串 - * @param keyType Map中键的类型 - * @param valueType Map中值的类型 - * @param 泛型参数,表示Map中键的类型 - * @param 泛型参数,表示Map中值的类型 - * @return 解析后的Map集合 - */ - default Map parseMap( - String json, - Class keyType, - Class valueType - ) { - JsonTypeReference> mapType = new JsonTypeReference< - Map - >() {}; - return parse(json, mapType); - } - - /** - * 验证字符串是否为有效的JSON格式 - * - * @param json 待验证的字符串 - * @return 如果是有效的JSON格式返回true,否则返回false - */ - boolean isValidJson(String json); - - /** - * 将对象转换为JSON字节数组 - * - * @param object 待转换的对象 - * @return 转换后的JSON字节数组 - */ - default byte[] toBytes(Object object) { - return format(object).getBytes(); - } - - /** - * 将对象转换为美化格式的JSON字节数组 - * - * @param object 待转换的对象 - * @return 转换后的美化格式JSON字节数组 - */ - default byte[] toBytesPretty(Object object) { - return formatPretty(object).getBytes(); - } - - /** - * 合并多个JSON字符串为一个JSON对象 - * - * @param jsons 待合并的JSON字符串数组 - * @return 合并后的JSON字符串 - */ - String merge(String... jsons); - - /** - * 获取JSON字符串中指定路径节点的值 - * - * @param json JSON字符串 - * @param path 节点路径(如:"user.name") - * @return 节点值的字符串表示 - */ - String getNodeValue(String json, String path); - - /** - * 更新JSON字符串中指定路径节点的值 - * - * @param json 原始JSON字符串 - * @param path 节点路径(如:"user.name") - * @param newValue 新的节点值 - * @return 更新后的JSON字符串 - */ - String updateNodeValue(String json, String path, Object newValue); - - D convert(T source, Class destinationClass); - - D convert(T source, JsonTypeReference destinationType); -} diff --git a/src/main/java/com/mingliqiye/utils/json/converters/DateTimeJsonConverter.java b/src/main/java/com/mingliqiye/utils/json/converters/DateTimeJsonConverter.java deleted file mode 100644 index f804e10..0000000 --- a/src/main/java/com/mingliqiye/utils/json/converters/DateTimeJsonConverter.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.mingliqiye.utils.json.converters; - -import com.mingliqiye.utils.time.DateTime; -import com.mingliqiye.utils.time.Formatter; - -public class DateTimeJsonConverter extends JsonStringConverter { - - @Override - public Class getTClass() { - return DateTime.class; - } - - @Override - public String convert(DateTime obj) { - if (obj == null) { - return null; - } - return obj.format(Formatter.STANDARD_DATETIME); - } - - @Override - public DateTime deConvert(String string) { - if (string == null) { - return null; - } - return DateTime.parse( - string, - Formatter.STANDARD_DATETIME_MILLISECOUND7, - true - ); - } -} diff --git a/src/main/java/com/mingliqiye/utils/json/converters/FastjsonJsonStringConverterAdapter.java b/src/main/java/com/mingliqiye/utils/json/converters/FastjsonJsonStringConverterAdapter.java deleted file mode 100644 index 420466d..0000000 --- a/src/main/java/com/mingliqiye/utils/json/converters/FastjsonJsonStringConverterAdapter.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile FastjsonJsonStringConverterAdapter.java - * LastUpdate 2025-09-14 22:12:16 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.json.converters; - -import com.alibaba.fastjson2.JSONReader; -import com.alibaba.fastjson2.JSONWriter; -import com.alibaba.fastjson2.reader.ObjectReader; -import com.alibaba.fastjson2.writer.ObjectWriter; - -import java.lang.reflect.Type; - -public class FastjsonJsonStringConverterAdapter< - T extends JsonStringConverter, - TT -> { - - private final JsonStringConverter jsonStringConverter; - - public FastjsonJsonStringConverterAdapter(T jsonStringConverter) { - this.jsonStringConverter = jsonStringConverter; - } - - public static < - T extends JsonStringConverter, - TT - > FastjsonJsonStringConverterAdapter of(T t) { - return new FastjsonJsonStringConverterAdapter<>(t); - } - - /** - * 获取FastJson对象写入器 - * - * @return FastJson的ObjectWriter实例 - */ - public ObjectWriter getFastJsonObjectWriter() { - return ( - JSONWriter writer, - Object object, - Object fieldName, - Type fieldType, - long features - ) -> { - // 如果对象为null则写入null - if (object == null) { - writer.writeNull(); - return; - } - writer.writeString(jsonStringConverter.convert((TT) object)); - }; - } - - /** - * 获取FastJson对象读取器 - * - * @return FastJson的ObjectReader实例 - */ - public ObjectReader getFastJsonObjectReader() { - return ( - JSONReader reader, - Type fieldType, - Object fieldName, - long features - ) -> { - String value = reader.readString(); - return jsonStringConverter.deConvert(value); - }; - } -} diff --git a/src/main/java/com/mingliqiye/utils/json/converters/GsonJsonStringConverterAdapter.java b/src/main/java/com/mingliqiye/utils/json/converters/GsonJsonStringConverterAdapter.java deleted file mode 100644 index 59ba8c8..0000000 --- a/src/main/java/com/mingliqiye/utils/json/converters/GsonJsonStringConverterAdapter.java +++ /dev/null @@ -1,72 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile GsonJsonStringConverterAdapter.java - * LastUpdate 2025-09-14 22:12:16 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.json.converters; - -import com.google.gson.TypeAdapter; -import com.google.gson.stream.JsonReader; -import com.google.gson.stream.JsonWriter; - -import java.io.IOException; - -public class GsonJsonStringConverterAdapter< - T extends JsonStringConverter, - TT -> { - - private final JsonStringConverter jsonStringConverter; - - public GsonJsonStringConverterAdapter(T jsonStringConverter) { - this.jsonStringConverter = jsonStringConverter; - } - - public static < - T extends JsonStringConverter, - TT - > GsonJsonStringConverterAdapter of(T t) { - return new GsonJsonStringConverterAdapter<>(t); - } - - /** - * 获取Gson类型适配器 - * - * @return Gson的TypeAdapter实例 - */ - public TypeAdapter getGsonTypeAdapter() { - return new TypeAdapter() { - @Override - public void write(JsonWriter out, TT value) throws IOException { - if (value == null) { - out.nullValue(); - return; - } - out.value(jsonStringConverter.convert(value)); - } - - @Override - public TT read(JsonReader in) throws IOException { - String value = in.nextString(); - return jsonStringConverter.deConvert(value); - } - }; - } -} diff --git a/src/main/java/com/mingliqiye/utils/json/converters/JacksonJsonStringConverterAdapter.java b/src/main/java/com/mingliqiye/utils/json/converters/JacksonJsonStringConverterAdapter.java deleted file mode 100644 index d787c0f..0000000 --- a/src/main/java/com/mingliqiye/utils/json/converters/JacksonJsonStringConverterAdapter.java +++ /dev/null @@ -1,91 +0,0 @@ -package com.mingliqiye.utils.json.converters; - -import com.fasterxml.jackson.core.JsonGenerator; -import com.fasterxml.jackson.core.JsonParser; -import com.fasterxml.jackson.databind.*; -import com.fasterxml.jackson.databind.module.SimpleModule; -import java.io.IOException; - -/** - * JSON转换器的适配器 - * @param JSON转换器 - * @param JSON转换器的泛型 - * @author MingLiPro - */ -public class JacksonJsonStringConverterAdapter< - T extends JsonStringConverter, - TT -> { - - private final JsonStringConverter jsonStringConverter; - - private JacksonJsonStringConverterAdapter(T jsonStringConverter) { - this.jsonStringConverter = jsonStringConverter; - } - - /** - * - * @param t JSON转换器实例 - * @return JSON转换器的适配器 - * @param JSON转换器 - * @param JSON转换器的泛型 - */ - public static < - T extends JsonStringConverter, - TT - > JacksonJsonStringConverterAdapter of(T t) { - return new JacksonJsonStringConverterAdapter<>(t); - } - - /** - * 获取Jackson反序列化器 - * - * @return Jackson的JsonDeserializer实例 - */ - public JsonDeserializer getJacksonJsonDeserializer() { - return new JsonDeserializer() { - @Override - public TT deserialize(JsonParser p, DeserializationContext ctxt) - throws IOException { - if (p.isNaN()) return null; - return jsonStringConverter.deConvert(p.getValueAsString()); - } - }; - } - - /** - * 获取Jackson序列化器 - * - * @return Jackson的JsonSerializer实例 - */ - public JsonSerializer getJacksonJsonSerializer() { - return new JsonSerializer() { - @Override - public void serialize( - TT value, - JsonGenerator gen, - SerializerProvider serializers - ) throws IOException { - if (value == null) { - gen.writeNull(); - return; - } - gen.writeString(jsonStringConverter.convert(value)); - } - }; - } - - /** - * - * 获取 Jackson 的格式化模块 - * - * @return 格式化模块 - */ - public Module getJacksonModule() { - Class tClass = jsonStringConverter.getTClass(); - SimpleModule m = new SimpleModule(tClass.getSimpleName()); - m.addSerializer(tClass, getJacksonJsonSerializer()); - m.addDeserializer(tClass, getJacksonJsonDeserializer()); - return m; - } -} diff --git a/src/main/java/com/mingliqiye/utils/json/converters/JsonStringConverter.java b/src/main/java/com/mingliqiye/utils/json/converters/JsonStringConverter.java deleted file mode 100644 index bd17915..0000000 --- a/src/main/java/com/mingliqiye/utils/json/converters/JsonStringConverter.java +++ /dev/null @@ -1,60 +0,0 @@ -package com.mingliqiye.utils.json.converters; - -/** - * JSON转换器接口,提供对象与字符串之间的相互转换功能,并支持多种JSON库 - * - * @param 需要转换的对象类型 - */ -public abstract class JsonStringConverter { - - public abstract Class getTClass(); - - /** - * 将对象转换为字符串 - * - * @param obj 待转换的对象 - * @return 转换后的字符串 - */ - abstract String convert(T obj); - - /** - * 将字符串转换为对象 - * - * @param string 待转换的字符串 - * @return 转换后的对象 - */ - abstract T deConvert(String string); - - /** - * 获取 Fastjson 的适配器 - * @return 适配器实例 - */ - public FastjsonJsonStringConverterAdapter< - JsonStringConverter, - T - > getFastjsonJsonStringConverterAdapter() { - return FastjsonJsonStringConverterAdapter.of(this); - } - - /** - * 获取 Gson 的适配器 - * @return 适配器实例 - */ - public GsonJsonStringConverterAdapter< - JsonStringConverter, - T - > getGsonJsonStringConverterAdapter() { - return GsonJsonStringConverterAdapter.of(this); - } - - /** - * 获取 Jackson 的适配器 - * @return 适配器实例 - */ - public JacksonJsonStringConverterAdapter< - JsonStringConverter, - T - > getJacksonJsonStringConverterAdapter() { - return JacksonJsonStringConverterAdapter.of(this); - } -} diff --git a/src/main/java/com/mingliqiye/utils/json/converters/UUIDJsonStringConverter.java b/src/main/java/com/mingliqiye/utils/json/converters/UUIDJsonStringConverter.java deleted file mode 100644 index 8fac8f3..0000000 --- a/src/main/java/com/mingliqiye/utils/json/converters/UUIDJsonStringConverter.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.mingliqiye.utils.json.converters; - -import com.mingliqiye.utils.uuid.UUID; - -public class UUIDJsonStringConverter extends JsonStringConverter { - - @Override - public Class getTClass() { - return UUID.class; - } - - @Override - public String convert(UUID obj) { - if (obj == null) { - return null; - } - return obj.toUUIDString(); - } - - @Override - public UUID deConvert(String string) { - if (string == null) { - return null; - } - return UUID.of(string); - } -} diff --git a/src/main/java/com/mingliqiye/utils/time/DateTime.java b/src/main/java/com/mingliqiye/utils/time/DateTime.java deleted file mode 100644 index f3ef9da..0000000 --- a/src/main/java/com/mingliqiye/utils/time/DateTime.java +++ /dev/null @@ -1,561 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile DateTime.java - * LastUpdate 2025-09-14 22:12:16 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.time; - -import com.mingliqiye.utils.jna.WinKernel32Api; -import com.mingliqiye.utils.jna.WinKernel32ApiFactory; -import com.mingliqiye.utils.system.SystemUtils; -import lombok.Getter; -import lombok.Setter; -import lombok.val; -import lombok.var; -import org.jetbrains.annotations.NotNull; -import org.slf4j.Logger; - -import java.io.Serializable; -import java.time.Instant; -import java.time.LocalDateTime; -import java.time.ZoneId; -import java.time.format.DateTimeFormatter; -import java.time.temporal.ChronoUnit; -import java.util.Date; - -import static com.mingliqiye.utils.jna.WinKernel32ApiFactory.FILETIME_EPOCH_OFFSET; -import static com.mingliqiye.utils.jna.WinKernel32ApiFactory.NANOS_PER_100NS; -import static com.mingliqiye.utils.logger.Loggers.getMingLiLoggerFactory; - -/** - * 时间类,用于处理日期时间的转换、格式化等操作。 - * 提供了多种静态方法来创建 DateTime 实例,并支持与 Date、LocalDateTime 等类型的互转。 - *
- * windows java 1.8 及以下 使用windows Api 获取高精度时间 - * - * @author MingLiPro - * @see java.time - * @see LocalDateTime - * @see ChronoUnit - * @see Date - * @see DateTimeFormatter - * @see ZoneId - * @see Instant - */ -@Setter -public final class DateTime implements Serializable { - - private static final WinKernel32Api WIN_KERNEL_32_API; - - static { - if ( - SystemUtils.getJavaVersionAsInteger() == 8 && - SystemUtils.isWindows() - ) { - final Logger log = getMingLiLoggerFactory().getLogger( - "mingli-utils DateTime" - ); - val a = WinKernel32ApiFactory.getWinKernel32Apis(); - - if (a.size() > 1) { - log.warn( - "Multiple Size:{} WinKernel32Api implementations found.", - a.size() - ); - a.forEach(api -> - log.warn( - "Found WinKernel32Api: {}", - api.getClass().getName() - ) - ); - } - - if (a.isEmpty()) { - WIN_KERNEL_32_API = null; - log.warn( - "No WinKernel32Api implementation found. Use Jdk1.8 LocalDateTime" - ); - } else { - WIN_KERNEL_32_API = a.get(a.size() - 1); - log.info( - "Found and Use WinKernel32Api: {}", - WIN_KERNEL_32_API.getClass().getName() - ); - } - } else { - WIN_KERNEL_32_API = null; - } - } - - @Getter - private ZoneId zoneId = ZoneId.systemDefault(); - - @Getter - private LocalDateTime localDateTime; - - /** - * 私有构造函数,使用指定的 LocalDateTime 初始化实例。 - * - * @param time LocalDateTime 对象 - */ - private DateTime(LocalDateTime time) { - setLocalDateTime(time); - } - - /** - * 私有构造函数,使用当前系统时间初始化实例。 - */ - private DateTime() { - setLocalDateTime(LocalDateTime.now()); - } - - /** - * 获取当前时间的 DateTime 实例。 - * 如果运行在 Java 1.8 环境下,则通过 WinKernel32 获取高精度时间。 - * - * @return 返回当前时间的 DateTime 实例 - */ - public static DateTime now() { - if (WIN_KERNEL_32_API != null) { - return DateTime.of( - WIN_KERNEL_32_API.getTime() - .atZone(ZoneId.systemDefault()) - .toLocalDateTime() - ); - } - return new DateTime(); - } - - /** - * 将 Date 对象转换为 DateTime 实例。 - * - * @param zoneId 时区信息 - * @param date Date 对象 - * @return 返回对应的 DateTime 实例 - */ - public static DateTime of(Date date, ZoneId zoneId) { - return new DateTime(date.toInstant().atZone(zoneId).toLocalDateTime()); - } - - /** - * 将 Date 对象转换为 DateTime 实例,使用系统默认时区。 - * - * @param date Date 对象 - * @return 返回对应的 DateTime 实例 - */ - public static DateTime of(Date date) { - return new DateTime( - date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime() - ); - } - - /** - * 根据 LocalDateTime 创建 DateTime 实例。 - * - * @param localDateTime LocalDateTime 对象 - * @return 返回对应的 DateTime 实例 - */ - public static DateTime of(LocalDateTime localDateTime) { - return new DateTime(localDateTime); - } - - /** - * 解析时间字符串并生成 DateTime 实例。 - * - * @param timestr 时间字符串 - * @param formatter 格式化模板 - * @param fillZero 是否补零到模板长度 - * @return 返回解析后的 DateTime 实例 - */ - public static DateTime parse( - String timestr, - String formatter, - boolean fillZero - ) { - return new DateTime( - LocalDateTime.parse( - fillZero ? getFillZeroByLen(timestr, formatter) : timestr, - DateTimeFormatter.ofPattern(formatter) - ) - ); - } - - /** - * 使用 Formatter 枚举解析时间字符串并生成 DateTime 实例。 - * - * @param timestr 时间字符串 - * @param formatter 格式化模板枚举 - * @param fillZero 是否补零到模板长度 - * @return 返回解析后的 DateTime 实例 - */ - public static DateTime parse( - String timestr, - Formatter formatter, - boolean fillZero - ) { - return parse(timestr, formatter.getValue(), fillZero); - } - - /** - * 使用 Formatter 枚举解析时间字符串并生成 DateTime 实例,默认不补零。 - * - * @param timestr 时间字符串 - * @param formatter 格式化模板枚举 - * @return 返回解析后的 DateTime 实例 - */ - public static DateTime parse(String timestr, Formatter formatter) { - return parse(timestr, formatter.getValue()); - } - - /** - * 解析时间字符串并生成 DateTime 实例,默认不补零。 - * - * @param timestr 时间字符串 - * @param formatter 格式化模板 - * @return 返回解析后的 DateTime 实例 - */ - public static DateTime parse(String timestr, String formatter) { - return parse(timestr, formatter, false); - } - - /** - * 补零处理时间字符串以匹配格式化模板长度。 - * - * @param dstr 原始时间字符串 - * @param formats 格式化模板 - * @return 补零后的时间字符串 - */ - private static String getFillZeroByLen(String dstr, String formats) { - if (dstr.length() == formats.length()) { - return dstr; - } - if (formats.length() > dstr.length()) { - if (dstr.length() == 19) { - dstr += "."; - } - var sb = new StringBuilder(dstr); - for (int i = 0; i < formats.length() - dstr.length(); i++) { - sb.append("0"); - } - return sb.toString(); - } - throw new IllegalArgumentException( - String.format( - "Text: '%s' len %s < %s %s", - dstr, - dstr.length(), - formats, - formats.length() - ) - ); - } - - /** - * 根据年、月、日创建 DateTime 实例 - * - * @param year 年份 - * @param month 月份 (1-12) - * @param day 日期 (1-31) - * @return 返回指定日期的 DateTime 实例(时间部分为 00:00:00) - */ - public static DateTime of(int year, int month, int day) { - return new DateTime(LocalDateTime.of(year, month, day, 0, 0)); - } - - /** - * 根据年、月、日、时、分创建 DateTime 实例 - * - * @param year 年份 - * @param month 月份 (1-12) - * @param day 日期 (1-31) - * @param hour 小时 (0-23) - * @param minute 分钟 (0-59) - * @return 返回指定日期时间的 DateTime 实例(秒部分为 00) - */ - public static DateTime of( - int year, - int month, - int day, - int hour, - int minute - ) { - return new DateTime(LocalDateTime.of(year, month, day, hour, minute)); - } - - /** - * 将 FILETIME 转换为 LocalDateTime。 - * - * @param fileTime FILETIME 时间戳(100纳秒单位自1601年1月1日起) - * @return 转换后的 LocalDateTime 实例 - */ - public static LocalDateTime fileTimeToLocalDateTime(long fileTime) { - // 1. 将 FILETIME (100ns间隔 since 1601) 转换为 Unix 时间戳 (纳秒 since 1970) - long unixNanos = (fileTime + FILETIME_EPOCH_OFFSET) * NANOS_PER_100NS; - - // 2. 从纳秒时间戳创建 Instant - Instant instant = Instant.ofEpochSecond( - unixNanos / 1_000_000_000L, - unixNanos % 1_000_000_000L - ); - - // 3. 转换为系统默认时区的 LocalDateTime - return instant.atZone(ZoneId.systemDefault()).toLocalDateTime(); - } - - /** - * 根据年、月、日、时、分、秒创建 DateTime 实例 - * - * @param year 年份 - * @param month 月份 (1-12) - * @param day 日期 (1-31) - * @param hour 小时 (0-23) - * @param minute 分钟 (0-59) - * @param second 秒 (0-59) - * @return 返回指定日期时间的 DateTime 实例 - */ - public static DateTime of( - int year, - int month, - int day, - int hour, - int minute, - int second - ) { - return new DateTime( - LocalDateTime.of(year, month, day, hour, minute, second) - ); - } - - /** - * 根据年、月、日、时、分、秒、纳秒创建 DateTime 实例 - * - * @param year 年份 - * @param month 月份 (1-12) - * @param day 日期 (1-31) - * @param hour 小时 (0-23) - * @param minute 分钟 (0-59) - * @param second 秒 (0-59) - * @param nano 纳秒 (0-999,999,999) - * @return 返回指定日期时间的 DateTime 实例 - */ - public static DateTime of( - int year, - int month, - int day, - int hour, - int minute, - int second, - int nano - ) { - return new DateTime( - LocalDateTime.of(year, month, day, hour, minute, second, nano) - ); - } - - /** - * 根据毫秒时间戳创建 DateTime 实例 - * - * @param epochMilli 毫秒时间戳 - * @return 返回对应时间的 DateTime 实例 - */ - public static DateTime of(long epochMilli) { - return new DateTime( - Instant.ofEpochMilli(epochMilli) - .atZone(ZoneId.systemDefault()) - .toLocalDateTime() - ); - } - - /** - * 根据毫秒时间戳和时区创建 DateTime 实例 - * - * @param epochMilli 毫秒时间戳 - * @param zoneId 时区信息 - * @return 返回对应时间的 DateTime 实例 - */ - public static DateTime of(long epochMilli, ZoneId zoneId) { - return new DateTime( - Instant.ofEpochMilli(epochMilli).atZone(zoneId).toLocalDateTime() - ); - } - - /** - * 将当前 DateTime 转换为 Date 对象。 - * - * @return 返回对应的 Date 对象 - */ - public Date toDate() { - return Date.from(localDateTime.atZone(getZoneId()).toInstant()); - } - - /** - * 获取当前 DateTime 中的 LocalDateTime 实例。 - * - * @return 返回 LocalDateTime 对象 - */ - public LocalDateTime toLocalDateTime() { - return localDateTime; - } - - /** - * 在当前时间基础上增加指定的时间偏移量。 - * - * @param dateTimeOffset 时间偏移对象 - * @return 返回修改后的 DateTime 实例 - */ - public DateTime add(DateTimeOffset dateTimeOffset) { - return new DateTime( - this.localDateTime.plus( - dateTimeOffset.getOffset(), - dateTimeOffset.getOffsetType() - ) - ); - } - - /** - * 在当前时间基础上减少指定的时间偏移量。 - * - * @param dateTimeOffset 时间偏移对象 - * @return 返回修改后的 DateTime 实例 - */ - public DateTime sub(DateTimeOffset dateTimeOffset) { - return new DateTime( - this.localDateTime.plus( - -dateTimeOffset.getOffset(), - dateTimeOffset.getOffsetType() - ) - ); - } - - /** - * 使用指定格式化模板将当前时间格式化为字符串。 - * - * @param formatter 格式化模板 - * @return 返回格式化后的时间字符串 - */ - public String format(String formatter) { - return format(formatter, false); - } - - /** - * 使用 Formatter 枚举将当前时间格式化为字符串。 - * - * @param formatter 格式化模板枚举 - * @return 返回格式化后的时间字符串 - */ - public String format(Formatter formatter) { - return format(formatter.getValue()); - } - - /** - * 使用指定格式化模板将当前时间格式化为字符串,并可选择是否去除末尾多余的零。 - * - * @param formatter 格式化模板 - * @param repcZero 是否去除末尾多余的零 - * @return 返回格式化后的时间字符串 - */ - public String format(String formatter, boolean repcZero) { - var formatted = DateTimeFormatter.ofPattern(formatter).format( - toLocalDateTime() - ); - if (repcZero) { - // 处理小数点后多余的0 - formatted = formatted.replaceAll("(\\.\\d*?)0+\\b", "$1"); - formatted = formatted.replaceAll("\\.$", ""); - } - return formatted; - } - - /** - * 使用 Formatter 枚举将当前时间格式化为字符串,并可选择是否去除末尾多余的零。 - * - * @param formatter 格式化模板枚举 - * @param repcZero 是否去除末尾多余的零 - * @return 返回格式化后的时间字符串 - */ - public String format(Formatter formatter, boolean repcZero) { - return format(formatter.getValue(), repcZero); - } - - /** - * 返回当前时间的标准字符串表示形式。 - * - * @return 返回标准格式的时间字符串 - */ - @Override - public String toString() { - return String.format( - "DateTime(%s)", - format(Formatter.STANDARD_DATETIME_MILLISECOUND7, true) - ); - } - - /** - * 比较当前DateTime对象与指定对象是否相等 - * - * @param obj 要比较的对象 - * @return 如果对象相等则返回true,否则返回false - */ - @Override - public boolean equals(Object obj) { - // 检查对象类型是否为DateTime - if (obj instanceof DateTime) { - // 比较两个DateTime对象转换为LocalDateTime后的值 - return toLocalDateTime().equals(((DateTime) obj).toLocalDateTime()); - } - return false; - } - - /** - * 将当前 DateTime 转换为 Instant 对象。 - * - * @return 返回 Instant 对象 - */ - @NotNull - public Instant toInstant() { - return localDateTime.atZone(zoneId).toInstant(); - } - - /** - * 判断当前时间是否在指定时间之后。 - * - * @param dateTime 指定时间 - * @return 如果当前时间在指定时间之后则返回 true,否则返回 false - */ - public boolean isAfter(DateTime dateTime) { - if (dateTime == null) { - return false; - } - return toInstant().isAfter(dateTime.toInstant()); - } - - /** - * 判断当前时间是否在指定时间之前。 - * - * @param dateTime 指定时间 - * @return 如果当前时间在指定时间之前则返回 true,否则返回 false - */ - public boolean isBefore(DateTime dateTime) { - if (dateTime == null) { - return false; - } - return toInstant().isBefore(dateTime.toInstant()); - } -} diff --git a/src/main/java/com/mingliqiye/utils/time/DateTimeOffset.java b/src/main/java/com/mingliqiye/utils/time/DateTimeOffset.java deleted file mode 100644 index b7acd54..0000000 --- a/src/main/java/com/mingliqiye/utils/time/DateTimeOffset.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile DateTimeOffset.java - * LastUpdate 2025-09-09 08:37:33 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.time; - -import java.time.temporal.ChronoUnit; -import lombok.Getter; - -/** - * 时间位移 类 - * - * @author MingLiPro - */ -@Getter -public class DateTimeOffset { - - private final ChronoUnit offsetType; - private final Long offset; - - private DateTimeOffset(ChronoUnit offsetType, Long offset) { - this.offsetType = offsetType; - this.offset = offset; - } - - /** - * 创建一个新的DateTimeOffset实例 - * - * @param offsetType 偏移量的单位类型,指定偏移量的计算单位 - * @param offset 偏移量的数值,可以为正数、负数或零 - * @return 返回一个新的DateTimeOffset对象,包含指定的偏移量信息 - */ - public static DateTimeOffset of(ChronoUnit offsetType, Long offset) { - return new DateTimeOffset(offsetType, offset); - } - - /** - * 创建一个 DateTimeOffset 实例 - * - * @param offset 偏移量数值 - * @param offsetType 偏移量的时间单位类型 - * @return 返回一个新的 DateTimeOffset 实例 - */ - public static DateTimeOffset of(Long offset, ChronoUnit offsetType) { - return new DateTimeOffset(offsetType, offset); - } -} diff --git a/src/main/java/com/mingliqiye/utils/time/DateTimeUnit.java b/src/main/java/com/mingliqiye/utils/time/DateTimeUnit.java deleted file mode 100644 index e1f959b..0000000 --- a/src/main/java/com/mingliqiye/utils/time/DateTimeUnit.java +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile DateTimeUnit.java - * LastUpdate 2025-09-09 08:37:33 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.time; - -/** - * 时间单位常量定义 - * - * @author MingLiPro - */ -public interface DateTimeUnit { - // 时间单位常量 - String YEAR = "year"; - String MONTH = "month"; - String WEEK = "week"; - String DAY = "day"; - String HOUR = "hour"; - String MINUTE = "minute"; - String SECOND = "second"; - String MILLISECOND = "millisecond"; - String MICROSECOND = "microsecond"; - String NANOSECOND = "nanosecond"; - - // 时间单位缩写 - String YEAR_ABBR = "y"; - String MONTH_ABBR = "M"; - String WEEK_ABBR = "w"; - String DAY_ABBR = "d"; - String HOUR_ABBR = "h"; - String MINUTE_ABBR = "m"; - String SECOND_ABBR = "s"; - String MILLISECOND_ABBR = "ms"; - String MICROSECOND_ABBR = "μs"; - String NANOSECOND_ABBR = "ns"; - - // 时间单位转换系数(毫秒为基准) - long MILLIS_PER_SECOND = 1000L; - long MILLIS_PER_MINUTE = 60 * MILLIS_PER_SECOND; - long MILLIS_PER_HOUR = 60 * MILLIS_PER_MINUTE; - long MILLIS_PER_DAY = 24 * MILLIS_PER_HOUR; - long MILLIS_PER_WEEK = 7 * MILLIS_PER_DAY; - - // 月份和年的毫秒数仅为近似值 - long MILLIS_PER_MONTH = 30 * MILLIS_PER_DAY; // 近似值 - long MILLIS_PER_YEAR = 365 * MILLIS_PER_DAY; // 近似值 -} diff --git a/src/main/java/com/mingliqiye/utils/time/Formatter.java b/src/main/java/com/mingliqiye/utils/time/Formatter.java deleted file mode 100644 index fd9cb3a..0000000 --- a/src/main/java/com/mingliqiye/utils/time/Formatter.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile Formatter.java - * LastUpdate 2025-09-09 08:37:33 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.time; - -import lombok.Getter; - -/** - * 时间格式化枚举类 - *

- * 定义了常用的时间格式化模式,用于日期时间的解析和格式化操作 - * 每个枚举常量包含对应的格式化字符串和字符串长度 - *

- */ -public enum Formatter { - /** - * 标准日期时间格式:yyyy-MM-dd HH:mm:ss - */ - STANDARD_DATETIME("yyyy-MM-dd HH:mm:ss"), - - /** - * 标准日期时间格式(7位毫秒):yyyy-MM-dd HH:mm:ss.SSSSSSS - */ - STANDARD_DATETIME_MILLISECOUND7("yyyy-MM-dd HH:mm:ss.SSSSSSS"), - - /** - * 标准日期时间格式(6位毫秒):yyyy-MM-dd HH:mm:ss.SSSSSS - */ - STANDARD_DATETIME_MILLISECOUND6("yyyy-MM-dd HH:mm:ss.SSSSSS"), - - /** - * 标准日期时间格式(5位毫秒):yyyy-MM-dd HH:mm:ss.SSSSS - */ - STANDARD_DATETIME_MILLISECOUND5("yyyy-MM-dd HH:mm:ss.SSSSS"), - - /** - * 标准日期时间格式(4位毫秒):yyyy-MM-dd HH:mm:ss.SSSS - */ - STANDARD_DATETIME_MILLISECOUND4("yyyy-MM-dd HH:mm:ss.SSSS"), - - /** - * 标准日期时间格式(3位毫秒):yyyy-MM-dd HH:mm:ss.SSS - */ - STANDARD_DATETIME_MILLISECOUND3("yyyy-MM-dd HH:mm:ss.SSS"), - - /** - * 标准日期时间格式(2位毫秒):yyyy-MM-dd HH:mm:ss.SS - */ - STANDARD_DATETIME_MILLISECOUND2("yyyy-MM-dd HH:mm:ss.SS"), - - /** - * 标准日期时间格式(1位毫秒):yyyy-MM-dd HH:mm:ss.S - */ - STANDARD_DATETIME_MILLISECOUND1("yyyy-MM-dd HH:mm:ss.S"), - - /** - * 标准ISO格式:yyyy-MM-dd'T'HH:mm:ss.SSS'Z' - */ - STANDARD_ISO("yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"), - - /** - * 标准日期时间秒格式:yyyy-MM-dd HH:mm:ss - */ - STANDARD_DATETIME_SECOUND("yyyy-MM-dd HH:mm:ss"), - - /** - * 标准日期格式:yyyy-MM-dd - */ - STANDARD_DATE("yyyy-MM-dd"), - - /** - * ISO8601格式:yyyy-MM-dd'T'HH:mm:ss.SSS'000' - */ - ISO8601("yyyy-MM-dd'T'HH:mm:ss.SSS'000'"), - - /** - * 紧凑型日期时间格式:yyyyMMddHHmmss - */ - COMPACT_DATETIME("yyyyMMddHHmmss"); - - @Getter - private final String value; - - @Getter - private final int len; - - /** - * 构造函数 - * - * @param value 格式化模式字符串 - */ - Formatter(String value) { - this.value = value; - this.len = value.length(); - } -} diff --git a/src/main/java/com/mingliqiye/utils/time/typehandlers/DateTimeTypeHandler.java b/src/main/java/com/mingliqiye/utils/time/typehandlers/DateTimeTypeHandler.java deleted file mode 100644 index 737e5a3..0000000 --- a/src/main/java/com/mingliqiye/utils/time/typehandlers/DateTimeTypeHandler.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright 2025 mingliqiye - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * 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. - * - * ProjectName mingli-utils - * ModuleName mingli-utils.main - * CurrentFile DateTimeTypeHandler.java - * LastUpdate 2025-09-09 08:37:33 - * UpdateUser MingLiPro - */ - -package com.mingliqiye.utils.time.typehandlers; - -import com.mingliqiye.utils.time.DateTime; -import com.mingliqiye.utils.time.Formatter; -import java.sql.*; -import org.apache.ibatis.type.BaseTypeHandler; -import org.apache.ibatis.type.JdbcType; -import org.apache.ibatis.type.MappedJdbcTypes; -import org.apache.ibatis.type.MappedTypes; - -/** - * DateTime类型处理器类 - * 用于在MyBatis中处理DateTime类型与数据库VARCHAR类型之间的转换 - */ -@MappedTypes({ DateTime.class }) -@MappedJdbcTypes(JdbcType.VARCHAR) -public class DateTimeTypeHandler extends BaseTypeHandler { - - /** - * 设置非空参数值 - * 将DateTime对象转换为Timestamp并设置到PreparedStatement中 - * - * @param ps PreparedStatement对象 - * @param i 参数索引位置 - * @param parameter DateTime参数值 - * @param jdbcType JDBC类型 - * @throws SQLException SQL异常 - */ - @Override - public void setNonNullParameter( - PreparedStatement ps, - int i, - DateTime parameter, - JdbcType jdbcType - ) throws SQLException { - ps.setTimestamp(i, Timestamp.valueOf(parameter.getLocalDateTime())); - } - - /** - * 从ResultSet中获取可为空的结果值 - * 根据列名获取字符串值并解析为DateTime对象 - * - * @param rs ResultSet对象 - * @param columnName 列名 - * @return DateTime对象,如果值为null则返回null - * @throws SQLException SQL异常 - */ - @Override - public DateTime getNullableResult(ResultSet rs, String columnName) - throws SQLException { - return parse(rs.getString(columnName)); - } - - /** - * 从ResultSet中获取可为空的结果值 - * 根据列索引获取字符串值并解析为DateTime对象 - * - * @param rs ResultSet对象 - * @param columnIndex 列索引 - * @return DateTime对象,如果值为null则返回null - * @throws SQLException SQL异常 - */ - @Override - public DateTime getNullableResult(ResultSet rs, int columnIndex) - throws SQLException { - return parse(rs.getString(columnIndex)); - } - - /** - * 从CallableStatement中获取可为空的结果值 - * 根据列索引获取字符串值并解析为DateTime对象 - * - * @param cs CallableStatement对象 - * @param columnIndex 列索引 - * @return DateTime对象,如果值为null则返回null - * @throws SQLException SQL异常 - */ - @Override - public DateTime getNullableResult(CallableStatement cs, int columnIndex) - throws SQLException { - return parse(cs.getString(columnIndex)); - } - - /** - * 解析字符串为DateTime对象 - * - * @param s 待解析的字符串 - * @return DateTime对象,如果字符串为null则返回null - */ - public DateTime parse(String s) { - if (s == null) { - return null; - } - return DateTime.parse(s, Formatter.STANDARD_DATETIME_MILLISECOUND7); - } - - /** - * 格式化DateTime对象为字符串 - * - * @param t DateTime对象 - * @return 格式化后的字符串 - */ - public String format(DateTime t) { - return t.format(Formatter.STANDARD_DATETIME_MILLISECOUND7); - } -} diff --git a/src/main/kotlin/com/mingliqiye/utils/Main.kt b/src/main/kotlin/com/mingliqiye/utils/Main.kt index 082bd5d..d989b68 100644 --- a/src/main/kotlin/com/mingliqiye/utils/Main.kt +++ b/src/main/kotlin/com/mingliqiye/utils/Main.kt @@ -16,15 +16,17 @@ * ProjectName mingli-utils * ModuleName mingli-utils.main * CurrentFile Main.kt - * LastUpdate 2025-09-15 08:56:35 + * LastUpdate 2025-09-15 09:53:43 * UpdateUser MingLiPro */ package com.mingliqiye.utils import com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration +import com.mingliqiye.utils.time.DateTime fun main() { AutoConfiguration.printBanner() + println(DateTime.now()) } fun test() { diff --git a/src/main/kotlin/com/mingliqiye/utils/functions/Functions.kt b/src/main/kotlin/com/mingliqiye/utils/functions/Functions.kt new file mode 100644 index 0000000..e1560a1 --- /dev/null +++ b/src/main/kotlin/com/mingliqiye/utils/functions/Functions.kt @@ -0,0 +1,181 @@ +/* + * Copyright 2025 mingliqiye + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + * + * ProjectName mingli-utils + * ModuleName mingli-utils.main + * CurrentFile Functions.kt + * LastUpdate 2025-09-15 09:56:54 + * UpdateUser MingLiPro + */ + +package com.mingliqiye.utils.functions + +import java.util.concurrent.* + +/** + * 防抖器类,用于实现防抖功能,防止在短时间内重复执行相同任务 + * + * @author MingLiPro + */ +class Debouncer(private val delay: Long, unit: TimeUnit) { + + private val scheduler: ScheduledExecutorService = Executors.newSingleThreadScheduledExecutor() + private val delayedMap: ConcurrentHashMap> = ConcurrentHashMap() + private val delayMillis: Long = unit.toMillis(delay) + + /** + * 执行防抖操作,如果在指定延迟时间内再次调用相同key的任务,则取消之前的任务并重新计时 + * + * @param key 任务的唯一标识符,用于区分不同任务 + * @param task 要执行的任务 + */ + fun debounce(key: Any, task: Runnable) { + // 提交新任务并获取之前可能存在的任务 + val prev = delayedMap.put( + key, + scheduler.schedule( + { + try { + task.run() + } finally { + // 任务执行完成后从映射中移除 + delayedMap.remove(key) + } + }, + delayMillis, + TimeUnit.MILLISECONDS + ) + ) + + // 如果之前存在任务,则取消它 + if (prev != null) { + prev.cancel(true) + } + } + + /** + * 关闭防抖器,取消所有待执行的任务并关闭调度器 + */ + fun shutdown() { + // 先取消所有延迟任务 + for (future in delayedMap.values) { + future.cancel(true) + } + delayedMap.clear() + + // 再关闭调度器 + scheduler.shutdownNow() + } +} + +@FunctionalInterface +fun interface P1Function

{ + fun call(p: P) +} + +@FunctionalInterface +fun interface P1RFunction { + fun call(p: P): R +} + +@FunctionalInterface +fun interface P2Function { + fun call(p: P, p1: P1) +} + +@FunctionalInterface +fun interface P2RFunction { + fun call(p: P, p1: P1): R +} + +@FunctionalInterface +fun interface P3Function { + fun call(p: P, p1: P1, p2: P2) +} + +@FunctionalInterface +fun interface P3RFunction { + fun call(p: P, p1: P1, p2: P2): R +} + +@FunctionalInterface +fun interface P4Function { + fun call(p: P, p1: P1, p2: P2, p3: P3) +} + +@FunctionalInterface +fun interface P4RFunction { + fun call(p: P, p1: P1, p2: P2, p3: P3): R +} + +@FunctionalInterface +fun interface P5Function { + fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4) +} + +@FunctionalInterface +fun interface P5RFunction { + fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4): R +} + +@FunctionalInterface +fun interface P6Function { + fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5) +} + +@FunctionalInterface +fun interface P6RFunction { + fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5): R +} + +@FunctionalInterface +fun interface P7Function { + fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6) +} + +@FunctionalInterface +fun interface P7RFunction { + fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6): R +} + +@FunctionalInterface +fun interface P8Function { + fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7) +} + +@FunctionalInterface +fun interface P8RFunction { + fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7): R +} + +@FunctionalInterface +fun interface P9Function { + fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8) +} + +@FunctionalInterface +fun interface P9RFunction { + fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8): R +} + +@FunctionalInterface +fun interface P10Function { + fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9) +} + +@FunctionalInterface +fun interface P10RFunction { + fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9): R +} diff --git a/src/main/kotlin/com/mingliqiye/utils/hash/HashUtils.kt b/src/main/kotlin/com/mingliqiye/utils/hash/HashUtils.kt new file mode 100644 index 0000000..7e2e3f2 --- /dev/null +++ b/src/main/kotlin/com/mingliqiye/utils/hash/HashUtils.kt @@ -0,0 +1,107 @@ +/* + * Copyright 2025 mingliqiye + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + * + * ProjectName mingli-utils + * ModuleName mingli-utils.main + * CurrentFile HashUtils.kt + * LastUpdate 2025-09-15 09:38:04 + * UpdateUser MingLiPro + */ +@file:JvmName("HashUtils") + +package com.mingliqiye.utils.hash + +import org.bouncycastle.jce.provider.BouncyCastleProvider +import org.mindrot.jbcrypt.BCrypt +import java.io.File +import java.io.FileInputStream +import java.io.IOException +import java.security.MessageDigest +import java.security.NoSuchAlgorithmException +import java.security.Security + +private val _addProvider = run { + Security.addProvider(BouncyCastleProvider()) +} + +/** + * 计算指定文件的哈希值。 + * + * @param file 要计算哈希值的文件对象 + * @param algorithm 使用的哈希算法名称(如 SHA-256、MD5 等) + * @return 文件的十六进制格式哈希值字符串 + * @throws IOException 当文件不存在或读取过程中发生 I/O 错误时抛出 + * @throws NoSuchAlgorithmException 当指定的哈希算法不可用时抛出 + */ +@Throws(IOException::class, NoSuchAlgorithmException::class) +fun calculateFileHash(file: File, algorithm: String): String { + // 检查文件是否存在 + if (!file.exists()) { + throw IOException("File not found: " + file.absolutePath) + } + + val digest = MessageDigest.getInstance(algorithm) + + FileInputStream(file).use { fis -> + val buffer = ByteArray(8192) + var bytesRead: Int + + // 分块读取文件内容并更新摘要 + while (fis.read(buffer).also { bytesRead = it } != -1) { + digest.update(buffer, 0, bytesRead) + } + } + + return bytesToHex(digest.digest()) +} + +/** + * 将字节数组转换为十六进制字符串表示。 + * + * @param bytes 输入的字节数组 + * @return 对应的十六进制字符串 + */ +private fun bytesToHex(bytes: ByteArray): String { + val hexString = StringBuilder(2 * bytes.size) + for (b in bytes) { + val hex = Integer.toHexString(0xff and b.toInt()) + if (hex.length == 1) { + hexString.append('0') + } + hexString.append(hex) + } + return hexString.toString() +} + +/** + * 使用 BCrypt 算法对字符串进行加密。 + * + * @param string 需要加密的明文字符串 + * @return 加密后的 BCrypt 哈希字符串 + */ +fun bcrypt(string: String): String { + return BCrypt.hashpw(string, BCrypt.gensalt()) +} + +/** + * 验证给定字符串与 BCrypt 哈希是否匹配。 + * + * @param string 明文字符串 + * @param bcrypted 已经使用 BCrypt 加密的哈希字符串 + * @return 如果匹配返回 true,否则返回 false + */ +fun checkBcrypt(string: String, bcrypted: String): Boolean { + return BCrypt.checkpw(string, bcrypted) +} diff --git a/src/main/kotlin/com/mingliqiye/utils/json/JsonApi.kt b/src/main/kotlin/com/mingliqiye/utils/json/JsonApi.kt new file mode 100644 index 0000000..bb253eb --- /dev/null +++ b/src/main/kotlin/com/mingliqiye/utils/json/JsonApi.kt @@ -0,0 +1,393 @@ +/* + * Copyright 2025 mingliqiye + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + * + * ProjectName mingli-utils + * ModuleName mingli-utils.main + * CurrentFile JsonApi.kt + * LastUpdate 2025-09-15 11:10:59 + * UpdateUser MingLiPro + */ + +package com.mingliqiye.utils.json + +import com.mingliqiye.utils.json.converters.JsonConverter +import com.mingliqiye.utils.json.converters.JsonStringConverter +import java.io.* +import java.nio.file.Files +import java.nio.file.Path +import java.nio.file.Paths + + +/** + * JSON处理接口,提供JSON字符串与Java对象之间的相互转换功能 + */ +interface JsonApi { + /** + * 将JSON字符串解析为指定类型的对象 + * + * @param json 待解析的JSON字符串 + * @param clazz 目标对象的Class类型 + * @param 泛型参数,表示目标对象的类型 + * @return 解析后的对象实例 + */ + fun parse(json: String, clazz: Class): T + + /** + * 将JSON字符串解析为指定泛型类型对象 + * + * @param json 待解析的JSON字符串 + * @param type 目标对象的Type类型(支持泛型) + * @param 泛型参数,表示目标对象的类型 + * @return 解析后的对象实例 + */ + fun parse(json: String, type: JsonTypeReference): T + + /** + * 将对象格式化为JSON字符串 + * + * @param obj 待格式化的对象 + * @return 格式化后的JSON字符串 + */ + fun format(obj: Any): String + + fun formatUnicode(obj: Any): String + + @Throws(IOException::class) + fun parseFrom(path: String, clazz: Class): T { + return parseFrom(Paths.get(path), clazz) + } + + @Throws(IOException::class) + fun parseFrom(path: Path, clazz: Class): T { + return parseFrom(path.toFile(), clazz) + } + + @Throws(IOException::class) + fun parseFrom(file: File, clazz: Class): T { + Files.newInputStream(file.toPath()).use { inputStream -> + return parseFrom(inputStream, clazz) + } + } + + @Throws(IOException::class) + fun parseFrom(inputStream: InputStream, clazz: Class): T { + val bytes = ByteArray(1024) + ByteArrayOutputStream().use { bos -> + var readlength: Int + while ((inputStream.read(bytes).also { readlength = it }) != -1) { + bos.write(bytes, 0, readlength) + } + return parse(bos.toByteArray(), clazz) + } + } + + @Throws(IOException::class) + fun parseFrom(path: String, type: JsonTypeReference): T { + return parseFrom(Paths.get(path), type) + } + + @Throws(IOException::class) + fun parseFrom(path: Path, type: JsonTypeReference): T { + return parseFrom(path.toFile(), type) + } + + @Throws(IOException::class) + fun parseFrom(file: File, type: JsonTypeReference): T { + Files.newInputStream(file.toPath()).use { inputStream -> + return parseFrom(inputStream, type) + } + } + + @Throws(IOException::class) + fun parseFrom(inputStream: InputStream, type: JsonTypeReference): T { + val bytes = ByteArray(1024) + ByteArrayOutputStream().use { bos -> + var readlength: Int + while ((inputStream.read(bytes).also { readlength = it }) != -1) { + bos.write(bytes, 0, readlength) + } + return parse(bos.toByteArray(), type) + } + } + + /** + * 将字节数组形式的JSON解析为指定类型的对象 + * + * @param json 待解析的JSON字节数组 + * @param clazz 目标对象的Class类型 + * @param 泛型参数,表示目标对象的类型 + * @return 解析后的对象实例 + */ + fun parse(json: ByteArray, clazz: Class): T { + return parse(String(json), clazz) + } + + /** + * 将字节数组形式的JSON解析为指定泛型类型对象 + * + * @param json 待解析的JSON字节数组 + * @param type 目标对象的Type类型(支持泛型) + * @param 泛型参数,表示目标对象的类型 + * @return 解析后的对象实例 + */ + fun parse(json: ByteArray, type: JsonTypeReference): T { + return parse(String(json), type) + } + + /** + * 将JSON字符串解析为指定类型的对象,解析失败时返回默认值 + * + * @param json 待解析的JSON字符串 + * @param clazz 目标对象的Class类型 + * @param defaultValue 解析失败时返回的默认值 + * @param 泛型参数,表示目标对象的类型 + * @return 解析后的对象实例或默认值 + */ + fun parse(json: String, clazz: Class, defaultValue: T): T { + try { + return parse(json, clazz) + } catch (e: Exception) { + return defaultValue + } + } + + /** + * 将JSON字符串解析为指定泛型类型对象,解析失败时返回默认值 + * + * @param json 待解析的JSON字符串 + * @param type 目标对象的Type类型(支持泛型) + * @param defaultValue 解析失败时返回的默认值 + * @param 泛型参数,表示目标对象的类型 + * @return 解析后的对象实例或默认值 + **/ + fun parse( + json: String, + type: JsonTypeReference, + defaultValue: T + ): T { + try { + return parse(json, type) + } catch (e: Exception) { + return defaultValue + } + } + + /** + * 将对象格式化为美化格式的JSON字符串(带缩进和换行) + * + * @param object 待格式化的对象 + * @return 格式化后的美化JSON字符串 + */ + fun formatPretty(obj: Any): String + + fun formatPrettyBytes(obj: Any): ByteArray { + return formatPretty(obj)!!.toByteArray() + } + + fun formatPrettyUnicode(obj: Any): String + + fun formatPrettyUnicodeBytes(obj: Any): ByteArray { + return formatPrettyUnicode(obj)!!.toByteArray() + } + + @Throws(IOException::class) + fun formatPretty(obj: Any, file: String) { + formatPretty(obj, Paths.get(file)) + } + + @Throws(IOException::class) + fun formatPretty(obj: Any, file: Path) { + formatPretty(obj, file.toFile()) + } + + @Throws(IOException::class) + fun formatPretty(obj: Any, file: File) { + FileOutputStream(file).use { fos -> + formatPretty(obj, fos) + } + } + + @Throws(IOException::class) + fun formatPretty(obj: Any, stream: OutputStream) { + stream.write(formatPrettyBytes(obj)) + } + + @Throws(IOException::class) + fun formatPrettyUnicode(obj: Any, file: String) { + formatPrettyUnicode(obj, Paths.get(file)) + } + + @Throws(IOException::class) + fun formatPrettyUnicode(obj: Any, file: Path) { + formatPrettyUnicode(obj, file.toFile()) + } + + @Throws(IOException::class) + fun formatPrettyUnicode(obj: Any, file: File) { + FileOutputStream(file).use { fos -> + formatPrettyUnicode(obj, fos) + } + } + + @Throws(IOException::class) + fun formatPrettyUnicode(obj: Any, stream: OutputStream) { + stream.write(formatPrettyUnicodeBytes(obj)) + } + + fun formatBytes(obj: Any): ByteArray { + return format(obj)!!.toByteArray() + } + + fun formatUnicodeBytes(obj: Any): ByteArray { + return formatUnicode(obj)!!.toByteArray() + } + + @Throws(IOException::class) + fun format(obj: Any, file: String) { + format(obj, Paths.get(file)) + } + + @Throws(IOException::class) + fun format(obj: Any, file: Path) { + format(obj, file.toFile()) + } + + @Throws(IOException::class) + fun format(obj: Any, file: File) { + FileOutputStream(file).use { fos -> + format(obj, fos) + } + } + + @Throws(IOException::class) + fun format(obj: Any, stream: OutputStream) { + stream.write(formatPrettyBytes(obj)) + } + + @Throws(IOException::class) + fun formatUnicode(obj: Any, file: String) { + formatUnicode(obj, Paths.get(file)) + } + + @Throws(IOException::class) + fun formatUnicode(obj: Any, file: Path) { + formatUnicode(obj, file.toFile()) + } + + @Throws(IOException::class) + fun formatUnicode(obj: Any, file: File) { + FileOutputStream(file).use { fos -> + formatUnicode(obj, fos) + } + } + + @Throws(IOException::class) + fun formatUnicode(obj: Any, stream: OutputStream) { + stream.write(formatPrettyUnicodeBytes(obj)) + } + + /** + * 将JSON字符串解析为指定元素类型的List集合 + * + * @param json 待解析的JSON字符串 + * @param elementType List中元素的类型 + * @param 泛型参数,表示List中元素的类型 + * @return 解析后的List集合 + */ + fun parseList(json: String, elementType: Class): MutableList { + return parse>(json, JsonTypeUtils.listType(elementType)) + } + + /** + * 将JSON字符串解析为指定键值类型的Map集合 + * + * @param json 待解析的JSON字符串 + * @param keyType Map中键的类型 + * @param valueType Map中值的类型 + * @param 泛型参数,表示Map中键的类型 + * @param 泛型参数,表示Map中值的类型 + * @return 解析后的Map集合 + */ + fun parseMap( + json: String, + keyType: Class, + valueType: Class + ): MutableMap { + val mapType: JsonTypeReference> = object : JsonTypeReference>() {} + return parse>(json, mapType) + } + + /** + * 验证字符串是否为有效的JSON格式 + * + * @param json 待验证的字符串 + * @return 如果是有效的JSON格式返回true,否则返回false + */ + fun isValidJson(json: String): Boolean + + /** + * 将对象转换为JSON字节数组 + * + * @param object 待转换的对象 + * @return 转换后的JSON字节数组 + */ + fun toBytes(obj: Any): ByteArray { + return format(obj)!!.toByteArray() + } + + /** + * 将对象转换为美化格式的JSON字节数组 + * + * @param object 待转换的对象 + * @return 转换后的美化格式JSON字节数组 + */ + fun toBytesPretty(obj: Any): ByteArray { + return formatPretty(obj)!!.toByteArray() + } + + /** + * 合并多个JSON字符串为一个JSON对象 + * + * @param jsons 待合并的JSON字符串数组 + * @return 合并后的JSON字符串 + */ + fun merge(vararg jsons: String): String + + /** + * 获取JSON字符串中指定路径节点的值 + * + * @param json JSON字符串 + * @param path 节点路径(如:"user.name") + * @return 节点值的字符串表示 + */ + fun getNodeValue(json: String, path: String): String + + /** + * 更新JSON字符串中指定路径节点的值 + * + * @param json 原始JSON字符串 + * @param path 节点路径(如:"user.name") + * @param newValue 新的节点值 + * @return 更新后的JSON字符串 + */ + fun updateNodeValue(json: String, path: String, newValue: Any): String + + fun convert(source: T, destinationClass: Class): D + + fun convert(source: T, destinationType: JsonTypeReference): D + + fun addJsonConverter(c: JsonConverter<*, *>) + fun addJsonStringConverter(c: JsonStringConverter<*>) +} diff --git a/src/main/java/com/mingliqiye/utils/functions/P8RFunction.java b/src/main/kotlin/com/mingliqiye/utils/json/converters/JsonConverter.kt similarity index 62% rename from src/main/java/com/mingliqiye/utils/functions/P8RFunction.java rename to src/main/kotlin/com/mingliqiye/utils/json/converters/JsonConverter.kt index 6c97d56..32f00f0 100644 --- a/src/main/java/com/mingliqiye/utils/functions/P8RFunction.java +++ b/src/main/kotlin/com/mingliqiye/utils/json/converters/JsonConverter.kt @@ -15,14 +15,22 @@ * * ProjectName mingli-utils * ModuleName mingli-utils.main - * CurrentFile P8RFunction.java - * LastUpdate 2025-09-09 08:37:34 + * CurrentFile JsonConverter.kt + * LastUpdate 2025-09-15 11:12:07 * UpdateUser MingLiPro */ -package com.mingliqiye.utils.functions; +package com.mingliqiye.utils.json.converters -@FunctionalInterface -public interface P8RFunction { - R call(P p, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7); +interface JsonConverter { + fun convert(obj: F?): T? + fun deConvert(obj: T?): F? + val tClass: Class + + fun getStringConverter(): JsonStringConverter? { + if (this is JsonStringConverter<*>) { + return this as JsonStringConverter + } + return null + } } diff --git a/src/main/kotlin/com/mingliqiye/utils/json/converters/JsonStringConverter.kt b/src/main/kotlin/com/mingliqiye/utils/json/converters/JsonStringConverter.kt new file mode 100644 index 0000000..4797533 --- /dev/null +++ b/src/main/kotlin/com/mingliqiye/utils/json/converters/JsonStringConverter.kt @@ -0,0 +1,254 @@ +/* + * Copyright 2025 mingliqiye + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * 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. + * + * ProjectName mingli-utils + * ModuleName mingli-utils.main + * CurrentFile JsonStringConverter.kt + * LastUpdate 2025-09-15 11:03:53 + * UpdateUser MingLiPro + */ + +package com.mingliqiye.utils.json.converters + +import com.alibaba.fastjson2.JSONReader +import com.alibaba.fastjson2.JSONWriter +import com.alibaba.fastjson2.reader.ObjectReader +import com.alibaba.fastjson2.writer.ObjectWriter +import com.fasterxml.jackson.core.JsonGenerator +import com.fasterxml.jackson.core.JsonParser +import com.fasterxml.jackson.databind.* +import com.fasterxml.jackson.databind.module.SimpleModule +import com.google.gson.TypeAdapter +import com.google.gson.stream.JsonReader +import com.google.gson.stream.JsonWriter +import com.mingliqiye.utils.time.DateTime +import com.mingliqiye.utils.time.DateTime.Companion.parse +import com.mingliqiye.utils.time.Formatter +import com.mingliqiye.utils.uuid.UUID +import com.mingliqiye.utils.uuid.UUID.Companion.of +import java.io.IOException +import java.lang.reflect.Type + +/** + * JSON转换器接口,提供对象与字符串之间的相互转换功能,并支持多种JSON库 + * + * @param 需要转换的对象类型 + */ +abstract class JsonStringConverter : JsonConverter { + val fastjsonJsonStringConverterAdapter: FastjsonJsonStringConverterAdapter, T> + /** + * 获取 Fastjson 的适配器 + * @return 适配器实例 + */ + get() = FastjsonJsonStringConverterAdapter.of(this) + + val gsonJsonStringConverterAdapter: GsonJsonStringConverterAdapter, T> + /** + * 获取 Gson 的适配器 + * @return 适配器实例 + */ + get() = GsonJsonStringConverterAdapter.of(this) + + val jacksonJsonStringConverterAdapter: JacksonJsonStringConverterAdapter, T> + /** + * 获取 Jackson 的适配器 + * @return 适配器实例 + */ + get() = JacksonJsonStringConverterAdapter.of(this) +} + + +class JacksonJsonStringConverterAdapter, TT + > private constructor(val jsonStringConverter: T) { + + val jacksonJsonDeserializer: JsonDeserializer + /** + * 获取Jackson反序列化器 + * + * @return Jackson的JsonDeserializer实例 + */ + get() = object : JsonDeserializer() { + @Throws(IOException::class) + override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): TT? { + if (p.isNaN) return null + return jsonStringConverter.deConvert(p.valueAsString) + } + } + + val jacksonJsonSerializer: JsonSerializer + /** + * 获取Jackson序列化器 + * + * @return Jackson的JsonSerializer实例 + */ + get() = object : JsonSerializer() { + @Throws(IOException::class) + override fun serialize( + value: TT?, + gen: JsonGenerator, + serializers: SerializerProvider? + ) { + if (value == null) { + gen.writeNull() + return + } + gen.writeString(jsonStringConverter.convert(value)) + } + } + + val jacksonModule: Module + /** + * + * 获取 Jackson 的格式化模块 + * + * @return 格式化模块 + */ + get() { + val tClass = jsonStringConverter.tClass + val m = SimpleModule(tClass.getSimpleName()) + m.addSerializer(tClass, this.jacksonJsonSerializer) + m.addDeserializer(tClass, this.jacksonJsonDeserializer) + return m + } + + companion object { + /** + * + * @param t JSON转换器实例 + * @return JSON转换器的适配器 + * @param JSON转换器 + * @param JSON转换器的泛型 + **/ + fun , TT + > of(t: T): JacksonJsonStringConverterAdapter { + return JacksonJsonStringConverterAdapter(t) + } + } +} + +class GsonJsonStringConverterAdapter, TT + >(val jsonStringConverter: T) { + + val gsonTypeAdapter: TypeAdapter + /** + * 获取Gson类型适配器 + * + * @return Gson的TypeAdapter实例 + */ + get() = object : TypeAdapter() { + @Throws(IOException::class) + override fun write(out: JsonWriter, value: TT?) { + if (value == null) { + out.nullValue() + return + } + out.value(jsonStringConverter.convert(value)) + } + + @Throws(IOException::class) + override fun read(`in`: JsonReader): TT? { + val value = `in`.nextString() + return jsonStringConverter.deConvert(value) + } + } + + companion object { + fun , TT + > of(t: T): GsonJsonStringConverterAdapter { + return GsonJsonStringConverterAdapter(t) + } + } +} + +class FastjsonJsonStringConverterAdapter, TT + >(val jsonStringConverter: T) { + @Suppress("UNCHECKED_CAST") + val fastJsonObjectWriter: ObjectWriter + /** + * 获取FastJson对象写入器 + * + * @return FastJson的ObjectWriter实例 + */ + get() = ObjectWriter { writer: JSONWriter?, obj: Any?, _: Any?, _: Type?, _: Long + -> + // 如果对象为null则写入null + if (obj == null) { + writer!!.writeNull() + return@ObjectWriter + } + writer!!.writeString(jsonStringConverter.convert(obj as TT)) + } + + val fastJsonObjectReader: ObjectReader + /** + * 获取FastJson对象读取器 + * + * @return FastJson的ObjectReader实例 + */ + get() = ObjectReader { reader: JSONReader?, _: Type?, _: Any?, _: Long + -> + val value = reader!!.readString() + jsonStringConverter.deConvert(value) + } + + companion object { + fun , TT + > of(t: T): FastjsonJsonStringConverterAdapter { + return FastjsonJsonStringConverterAdapter(t) + } + } +} + + +class DateTimeJsonConverter : JsonStringConverter() { + override val tClass = DateTime::class.java + + override fun convert(obj: DateTime?): String? { + if (obj == null) { + return null + } + return obj.format(Formatter.STANDARD_DATETIME) + } + + override fun deConvert(obj: String?): DateTime? { + if (obj == null) { + return null + } + return parse( + obj, + Formatter.STANDARD_DATETIME_MILLISECOUND7, + true + ) + } +} + +class UUIDJsonStringConverter : JsonStringConverter() { + override val tClass: Class = UUID::class.java + + override fun convert(obj: UUID?): String? { + if (obj == null) { + return null + } + return obj.getString() + } + + override fun deConvert(obj: String?): UUID? { + if (obj == null) { + return null + } + return of(obj) + } + +} diff --git a/src/main/kotlin/com/mingliqiye/utils/random/RandomBytes.kt b/src/main/kotlin/com/mingliqiye/utils/random/RandomBytes.kt index 9877528..5ca427e 100644 --- a/src/main/kotlin/com/mingliqiye/utils/random/RandomBytes.kt +++ b/src/main/kotlin/com/mingliqiye/utils/random/RandomBytes.kt @@ -16,15 +16,13 @@ * ProjectName mingli-utils * ModuleName mingli-utils.main * CurrentFile RandomBytes.kt - * LastUpdate 2025-09-15 00:08:18 + * LastUpdate 2025-09-15 09:54:33 * UpdateUser MingLiPro */ @file:JvmName("RandomBytes") package com.mingliqiye.utils.random -import com.mingliqiye.utils.iterator.Range - /** * 生成指定长度的随机字节数组 * @param length 数组长度 @@ -32,7 +30,9 @@ import com.mingliqiye.utils.iterator.Range */ fun randomBytes(length: Int): ByteArray { val bytes = ByteArray(length) - Range(0, length - 1).forEach { i: Int -> bytes[i] = randomByte(0x00.toByte(), 0xff.toByte()) } + for (i in 0.. + * windows java 1.8 及以下 使用windows Api 获取高精度时间 + * + * @author MingLiPro + * @see java.time + * @see LocalDateTime + * @see ChronoUnit + * @see Date + * @see DateTimeFormatter + * @see ZoneId + * @see Instant + */ +class DateTime private constructor( + private var localDateTime: LocalDateTime, + private val zoneId: ZoneId = ZoneId.systemDefault() +) : Serializable { + + companion object { + private val WIN_KERNEL_32_API: WinKernel32Api? = if ( + getJavaVersionAsInteger() == 8 && + isWindows() + ) { + val log: Logger = mingLiLoggerFactory.getLogger("mingli-utils DateTime") + val a = getWinKernel32Apis() + + if (a.size > 1) { + log.warn("Multiple Size:{} WinKernel32Api implementations found.", a.size) + a.forEach { api -> + log.warn("Found WinKernel32Api: {}", api.javaClass.name) + } + } + + if (a.isEmpty()) { + log.warn("No WinKernel32Api implementation found. Use Jdk1.8 LocalDateTime") + null + } else { + log.info("Found and Use WinKernel32Api: {}", a[a.size - 1].javaClass.name) + a[a.size - 1] + } + } else { + null + } + + /** + * 获取当前时间的 DateTime 实例。 + * 如果运行在 Java 1.8 环境下,则通过 WinKernel32 获取高精度时间。 + * + * @return 返回当前时间的 DateTime 实例 + */ + @JvmStatic + fun now(): DateTime { + if (WIN_KERNEL_32_API != null) { + return DateTime( + WIN_KERNEL_32_API.getTime() + .atZone(ZoneId.systemDefault()) + .toLocalDateTime() + ) + } + return DateTime(LocalDateTime.now()) + } + + /** + * 将 Date 对象转换为 DateTime 实例。 + * + * @param zoneId 时区信息 + * @param date Date 对象 + * @return 返回对应的 DateTime 实例 + */ + @JvmStatic + fun of(date: Date, zoneId: ZoneId): DateTime { + return DateTime(date.toInstant().atZone(zoneId).toLocalDateTime(), zoneId) + } + + /** + * 将 Date 对象转换为 DateTime 实例,使用系统默认时区。 + * + * @param date Date 对象 + * @return 返回对应的 DateTime 实例 + */ + @JvmStatic + fun of(date: Date): DateTime { + return DateTime( + date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime() + ) + } + + /** + * 根据 LocalDateTime 创建 DateTime 实例。 + * + * @param localDateTime LocalDateTime 对象 + * @return 返回对应的 DateTime 实例 + */ + @JvmStatic + fun of(localDateTime: LocalDateTime): DateTime { + return DateTime(localDateTime) + } + + /** + * 解析时间字符串并生成 DateTime 实例。 + * + * @param timestr 时间字符串 + * @param formatter 格式化模板 + * @param fillZero 是否补零到模板长度 + * @return 返回解析后的 DateTime 实例 + */ + @JvmStatic + fun parse( + timestr: String, + formatter: String, + fillZero: Boolean + ): DateTime { + return DateTime( + LocalDateTime.parse( + if (fillZero) getFillZeroByLen(timestr, formatter) else timestr, + DateTimeFormatter.ofPattern(formatter) + ) + ) + } + + /** + * 使用 Formatter 枚举解析时间字符串并生成 DateTime 实例。 + * + * @param timestr 时间字符串 + * @param formatter 格式化模板枚举 + * @param fillZero 是否补零到模板长度 + * @return 返回解析后的 DateTime 实例 + */ + @JvmStatic + fun parse( + timestr: String, + formatter: Formatter, + fillZero: Boolean + ): DateTime { + return parse(timestr, formatter.getValue(), fillZero) + } + + /** + * 使用 Formatter 枚举解析时间字符串并生成 DateTime 实例,默认不补零。 + * + * @param timestr 时间字符串 + * @param formatter 格式化模板枚举 + * @return 返回解析后的 DateTime 实例 + */ + @JvmStatic + fun parse(timestr: String, formatter: Formatter): DateTime { + return parse(timestr, formatter.getValue()) + } + + /** + * 解析时间字符串并生成 DateTime 实例,默认不补零。 + * + * @param timestr 时间字符串 + * @param formatter 格式化模板 + * @return 返回解析后的 DateTime 实例 + */ + @JvmStatic + fun parse(timestr: String, formatter: String): DateTime { + return parse(timestr, formatter, false) + } + + /** + * 补零处理时间字符串以匹配格式化模板长度。 + * + * @param dstr 原始时间字符串 + * @param formats 格式化模板 + * @return 补零后的时间字符串 + */ + private fun getFillZeroByLen(dstr: String, formats: String): String { + if (dstr.length == formats.length) { + return dstr + } + if (formats.length > dstr.length) { + var modifiedDstr = dstr + if (dstr.length == 19) { + modifiedDstr += "." + } + val sb = StringBuilder(modifiedDstr) + for (i in 0 until formats.length - dstr.length) { + sb.append("0") + } + return sb.toString() + } + throw IllegalArgumentException( + String.format( + "Text: '%s' len %s < %s %s", + dstr, + dstr.length, + formats, + formats.length + ) + ) + } + + /** + * 根据年、月、日创建 DateTime 实例 + * + * @param year 年份 + * @param month 月份 (1-12) + * @param day 日期 (1-31) + * @return 返回指定日期的 DateTime 实例(时间部分为 00:00:00) + */ + @JvmStatic + fun of(year: Int, month: Int, day: Int): DateTime { + return DateTime(LocalDateTime.of(year, month, day, 0, 0)) + } + + /** + * 根据年、月、日、时、分创建 DateTime 实例 + * + * @param year 年份 + * @param month 月份 (1-12) + * @param day 日期 (1-31) + * @param hour 小时 (0-23) + * @param minute 分钟 (0-59) + * @return 返回指定日期时间的 DateTime 实例(秒部分为 00) + */ + @JvmStatic + fun of( + year: Int, + month: Int, + day: Int, + hour: Int, + minute: Int + ): DateTime { + return DateTime(LocalDateTime.of(year, month, day, hour, minute)) + } + + /** + * 将 FILETIME 转换为 LocalDateTime。 + * + * @param fileTime FILETIME 时间戳(100纳秒单位自1601年1月1日起) + * @return 转换后的 LocalDateTime 实例 + */ + @OptIn(ExperimentalTime::class) + @JvmStatic + fun fileTimeToLocalDateTime(fileTime: Long): LocalDateTime { + // 1. 将 FILETIME (100ns间隔 since 1601) 转换为 Unix 时间戳 (纳秒 since 1970) + val unixNanos = (fileTime + FILETIME_EPOCH_OFFSET) * NANOS_PER_100NS + + // 2. 从纳秒时间戳创建 Instant + val instant = java.time.Instant.ofEpochSecond( + unixNanos / 1_000_000_000L, + unixNanos % 1_000_000_000L + ) + + // 3. 转换为系统默认时区的 LocalDateTime + return instant.atZone(ZoneId.systemDefault()).toLocalDateTime() + } + + /** + * 根据年、月、日、时、分、秒创建 DateTime 实例 + * + * @param year 年份 + * @param month 月份 (1-12) + * @param day 日期 (1-31) + * @param hour 小时 (0-23) + * @param minute 分钟 (0-59) + * @param second 秒 (0-59) + * @return 返回指定日期时间的 DateTime 实例 + */ + @JvmStatic + fun of( + year: Int, + month: Int, + day: Int, + hour: Int, + minute: Int, + second: Int + ): DateTime { + return DateTime( + LocalDateTime.of(year, month, day, hour, minute, second) + ) + } + + /** + * 根据年、月、日、时、分、秒、纳秒创建 DateTime 实例 + * + * @param year 年份 + * @param month 月份 (1-12) + * @param day 日期 (1-31) + * @param hour 小时 (0-23) + * @param minute 分钟 (0-59) + * @param second 秒 (0-59) + * @param nano 纳秒 (0-999,999,999) + * @return 返回指定日期时间的 DateTime 实例 + */ + @JvmStatic + fun of( + year: Int, + month: Int, + day: Int, + hour: Int, + minute: Int, + second: Int, + nano: Int + ): DateTime { + return DateTime( + LocalDateTime.of(year, month, day, hour, minute, second, nano) + ) + } + + /** + * 根据毫秒时间戳创建 DateTime 实例 + * + * @param epochMilli 毫秒时间戳 + * @return 返回对应时间的 DateTime 实例 + */ + @JvmStatic + fun of(epochMilli: Long): DateTime { + return DateTime( + java.time.Instant.ofEpochMilli(epochMilli) + .atZone(ZoneId.systemDefault()) + .toLocalDateTime() + ) + } + + /** + * 根据毫秒时间戳和时区创建 DateTime 实例 + * + * @param epochMilli 毫秒时间戳 + * @param zoneId 时区信息 + * @return 返回对应时间的 DateTime 实例 + */ + @JvmStatic + fun of(epochMilli: Long, zoneId: ZoneId): DateTime { + return DateTime( + java.time.Instant.ofEpochMilli(epochMilli).atZone(zoneId).toLocalDateTime(), + zoneId + ) + } + } + + /** + * 将当前 DateTime 转换为 Date 对象。 + * + * @return 返回对应的 Date 对象 + */ + fun toDate(): Date { + return Date.from(localDateTime.atZone(zoneId).toInstant()) + } + + /** + * 获取当前 DateTime 中的 LocalDateTime 实例。 + * + * @return 返回 LocalDateTime 对象 + */ + fun toLocalDateTime(): LocalDateTime { + return localDateTime + } + + /** + * 在当前时间基础上增加指定的时间偏移量。 + * + * @param dateTimeOffset 时间偏移对象 + * @return 返回修改后的 DateTime 实例 + */ + fun add(dateTimeOffset: DateTimeOffset): DateTime { + return DateTime( + this.localDateTime.plus( + dateTimeOffset.offset, + dateTimeOffset.offsetType + ) + ) + } + + /** + * 在当前时间基础上减少指定的时间偏移量。 + * + * @param dateTimeOffset 时间偏移对象 + * @return 返回修改后的 DateTime 实例 + */ + fun sub(dateTimeOffset: DateTimeOffset): DateTime { + return DateTime( + this.localDateTime.plus( + -dateTimeOffset.offset, + dateTimeOffset.offsetType + ) + ) + } + + /** + * 使用指定格式化模板将当前时间格式化为字符串。 + * + * @param formatter 格式化模板 + * @return 返回格式化后的时间字符串 + */ + fun format(formatter: String): String { + return format(formatter, false) + } + + /** + * 使用 Formatter 枚举将当前时间格式化为字符串。 + * + * @param formatter 格式化模板枚举 + * @return 返回格式化后的时间字符串 + */ + fun format(formatter: Formatter): String { + return format(formatter.getValue()) + } + + /** + * 使用指定格式化模板将当前时间格式化为字符串,并可选择是否去除末尾多余的零。 + * + * @param formatter 格式化模板 + * @param repcZero 是否去除末尾多余的零 + * @return 返回格式化后的时间字符串 + */ + fun format(formatter: String, repcZero: Boolean): String { + var formatted = DateTimeFormatter.ofPattern(formatter).format( + toLocalDateTime() + ) + if (repcZero) { + // 处理小数点后多余的0 + formatted = formatted.replace(Regex("(\\.\\d*?)0+\\b"), "$1") + formatted = formatted.replace(Regex("\\.$"), "") + } + return formatted + } + + /** + * 使用 Formatter 枚举将当前时间格式化为字符串,并可选择是否去除末尾多余的零。 + * + * @param formatter 格式化模板枚举 + * @param repcZero 是否去除末尾多余的零 + * @return 返回格式化后的时间字符串 + */ + fun format(formatter: Formatter, repcZero: Boolean): String { + return format(formatter.getValue(), repcZero) + } + + /** + * 返回当前时间的标准字符串表示形式。 + * + * @return 返回标准格式的时间字符串 + */ + override fun toString(): String { + return String.format( + "DateTime(%s)", + format(Formatter.STANDARD_DATETIME_MILLISECOUND7, true) + ) + } + + /** + * 比较当前DateTime对象与指定对象是否相等 + * + * @param other 要比较的对象 + * @return 如果对象相等则返回true,否则返回false + */ + override fun equals(other: Any?): Boolean { + // 检查对象类型是否为DateTime + if (other is DateTime) { + // 比较两个DateTime对象转换为LocalDateTime后的值 + return toLocalDateTime() == other.toLocalDateTime() + } + return false + } + + /** + * 获取对象的哈希码 + * + * @return 哈希码 + */ + override fun hashCode(): Int { + return localDateTime.hashCode() + } + + /** + * 将当前 DateTime 转换为 Instant 对象。 + * + * @return 返回 Instant 对象 + */ + fun toInstant(): java.time.Instant { + return localDateTime.atZone(zoneId).toInstant() + } + + /** + * 判断当前时间是否在指定时间之后。 + * + * @param dateTime 指定时间 + * @return 如果当前时间在指定时间之后则返回 true,否则返回 false + */ + fun isAfter(dateTime: DateTime?): Boolean { + if (dateTime == null) { + return false + } + return toInstant().isAfter(dateTime.toInstant()) + } + + /** + * 判断当前时间是否在指定时间之前。 + * + * @param dateTime 指定时间 + * @return 如果当前时间在指定时间之前则返回 true,否则返回 false + */ + fun isBefore(dateTime: DateTime?): Boolean { + if (dateTime == null) { + return false + } + return toInstant().isBefore(dateTime.toInstant()) + } + + /** + * 获取时区ID + * + * @return ZoneId对象 + */ + fun getZoneId(): ZoneId { + return zoneId + } +}