generated from mingliqiye/lib-tem
refactor(time): 重构 DateTime 类并添加新功能
- 从 Java 文件中删除了旧的 DateTime 类 - 新增 Kotlin 版本的 DateTime 类,具有以下改进: - 添加了时间格式化枚举类 Formatter - 新增时间位移类 DateTimeOffset - 重构了 parse 和 format 方法,支持新的 Formatter 枚举 - 优化了文件时间转换方法,使用纳秒精度 - 删除了旧的 DateTimeJsonConverter 类
This commit is contained in:
parent
dc129c016f
commit
7526b2e787
@ -16,7 +16,7 @@
|
|||||||
* ProjectName mingli-utils
|
* ProjectName mingli-utils
|
||||||
* ModuleName mingli-utils
|
* ModuleName mingli-utils
|
||||||
* CurrentFile build.gradle.kts
|
* CurrentFile build.gradle.kts
|
||||||
* LastUpdate 2025-09-14 22:32:52
|
* LastUpdate 2025-09-15 11:20:04
|
||||||
* UpdateUser MingLiPro
|
* UpdateUser MingLiPro
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -31,7 +31,6 @@ plugins {
|
|||||||
kotlin("jvm") version "2.2.20"
|
kotlin("jvm") version "2.2.20"
|
||||||
id("org.jetbrains.dokka") version "2.0.0"
|
id("org.jetbrains.dokka") version "2.0.0"
|
||||||
}
|
}
|
||||||
|
|
||||||
val GROUPSID = project.properties["GROUPSID"] as String
|
val GROUPSID = project.properties["GROUPSID"] as String
|
||||||
val VERSIONS = project.properties["VERSIONS"] as String
|
val VERSIONS = project.properties["VERSIONS"] as String
|
||||||
val ARTIFACTID = project.properties["ARTIFACTID"] as String
|
val ARTIFACTID = project.properties["ARTIFACTID"] as String
|
||||||
|
|||||||
@ -16,10 +16,10 @@
|
|||||||
# ProjectName mingli-utils
|
# ProjectName mingli-utils
|
||||||
# ModuleName mingli-utils
|
# ModuleName mingli-utils
|
||||||
# CurrentFile gradle.properties
|
# CurrentFile gradle.properties
|
||||||
# LastUpdate 2025-09-15 09:25:10
|
# LastUpdate 2025-09-15 11:19:10
|
||||||
# UpdateUser MingLiPro
|
# UpdateUser MingLiPro
|
||||||
#
|
#
|
||||||
JDKVERSIONS=1.8
|
JDKVERSIONS=1.8
|
||||||
GROUPSID=com.mingliqiye.utils
|
GROUPSID=com.mingliqiye.utils
|
||||||
ARTIFACTID=mingli-utils
|
ARTIFACTID=mingli-utils
|
||||||
VERSIONS=4.0.0-pre
|
VERSIONS=4.0.1
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
* ProjectName mingli-utils
|
* ProjectName mingli-utils
|
||||||
* ModuleName mingli-utils.main
|
* ModuleName mingli-utils.main
|
||||||
* CurrentFile Main.java
|
* CurrentFile Main.java
|
||||||
* LastUpdate 2025-09-15 09:24:07
|
* LastUpdate 2025-09-15 11:18:12
|
||||||
* UpdateUser MingLiPro
|
* UpdateUser MingLiPro
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|||||||
@ -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<Object, Future<?>> 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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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<P, P1, P2, P3, P4, P5, P6, P7, P8, P9> {
|
|
||||||
void call(
|
|
||||||
P p,
|
|
||||||
P1 p1,
|
|
||||||
P2 p2,
|
|
||||||
P3 p3,
|
|
||||||
P4 p4,
|
|
||||||
P5 p5,
|
|
||||||
P6 p6,
|
|
||||||
P7 p7,
|
|
||||||
P8 p8,
|
|
||||||
P9 p9
|
|
||||||
);
|
|
||||||
}
|
|
||||||
@ -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<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, R> {
|
|
||||||
R call(P p, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8, P9 p9);
|
|
||||||
}
|
|
||||||
@ -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<P> {
|
|
||||||
void call(P p);
|
|
||||||
}
|
|
||||||
@ -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<P, R> {
|
|
||||||
R call(P p);
|
|
||||||
}
|
|
||||||
@ -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<P, P1> {
|
|
||||||
void call(P p, P1 p1);
|
|
||||||
}
|
|
||||||
@ -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<P, P1, R> {
|
|
||||||
R call(P p, P1 p1);
|
|
||||||
}
|
|
||||||
@ -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<P, P1, P2> {
|
|
||||||
void call(P p, P1 p1, P2 p2);
|
|
||||||
}
|
|
||||||
@ -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<P, P1, P2, R> {
|
|
||||||
R call(P p, P1 p1, P2 p2);
|
|
||||||
}
|
|
||||||
@ -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<P, P1, P2, P3> {
|
|
||||||
void call(P p, P1 p1, P2 p2, P3 p3);
|
|
||||||
}
|
|
||||||
@ -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<P, P1, P2, P3, R> {
|
|
||||||
R call(P p, P1 p1, P2 p2, P3 p3);
|
|
||||||
}
|
|
||||||
@ -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<P, P1, P2, P3, P4> {
|
|
||||||
void call(P p, P1 p1, P2 p2, P3 p3, P4 p4);
|
|
||||||
}
|
|
||||||
@ -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<P, P1, P2, P3, P4, R> {
|
|
||||||
R call(P p, P1 p1, P2 p2, P3 p3, P4 p4);
|
|
||||||
}
|
|
||||||
@ -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<P, P1, P2, P3, P4, P5> {
|
|
||||||
void call(P p, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5);
|
|
||||||
}
|
|
||||||
@ -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<P, P1, P2, P3, P4, P5, R> {
|
|
||||||
R call(P p, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5);
|
|
||||||
}
|
|
||||||
@ -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<P, P1, P2, P3, P4, P5, P6> {
|
|
||||||
void call(P p, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6);
|
|
||||||
}
|
|
||||||
@ -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<P, P1, P2, P3, P4, P5, P6, R> {
|
|
||||||
R call(P p, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6);
|
|
||||||
}
|
|
||||||
@ -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<P, P1, P2, P3, P4, P5, P6, P7> {
|
|
||||||
void call(P p, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7);
|
|
||||||
}
|
|
||||||
@ -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<P, P1, P2, P3, P4, P5, P6, P7, P8> {
|
|
||||||
void call(P p, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8);
|
|
||||||
}
|
|
||||||
@ -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<P, P1, P2, P3, P4, P5, P6, P7, P8, R> {
|
|
||||||
R call(P p, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7, P8 p8);
|
|
||||||
}
|
|
||||||
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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<br>
|
|
||||||
* Iterable 可遍历对象<br>
|
|
||||||
* 类似 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<Integer>, ClosedRange<Integer>, OpenEndRange<Integer> {
|
|
||||||
|
|
||||||
private final int start;
|
|
||||||
private final int end;
|
|
||||||
private final int step;
|
|
||||||
private int current;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建一个范围 <br>
|
|
||||||
* 最大值{@code Integer.MAX_VALUE = 2147483647 } <br>
|
|
||||||
* 最小值{@code Integer.MIN_VALUE = -2147483648} <br>
|
|
||||||
* @param start 开始 (包含)
|
|
||||||
* @param end 完毕 (包含)
|
|
||||||
* @see Integer
|
|
||||||
*/
|
|
||||||
public Range(int start, int end) {
|
|
||||||
this(start, end, 1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建一个范围 <br>
|
|
||||||
* 最大值{@code Integer.MAX_VALUE = 2147483647 } <br>
|
|
||||||
* 最小值{@code Integer.MIN_VALUE = -2147483648} <br>
|
|
||||||
* @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}<br>
|
|
||||||
* 最大值{@code Integer.MAX_VALUE = 2147483647 } <br>
|
|
||||||
* 最小值{@code Integer.MIN_VALUE = -2147483648} <br>
|
|
||||||
* @param range 完毕 (包含)
|
|
||||||
* @see Integer
|
|
||||||
*/
|
|
||||||
public Range(int range) {
|
|
||||||
this(0, range);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建一个范围 {@code 0 - range}<br>
|
|
||||||
* 最大值{@code Integer.MAX_VALUE = 2147483647 } <br>
|
|
||||||
* 最小值{@code Integer.MIN_VALUE = -2147483648} <br>
|
|
||||||
* @param range 完毕 (包含)
|
|
||||||
* @see Integer
|
|
||||||
* @return Range 对象
|
|
||||||
*/
|
|
||||||
public static Range of(int range) {
|
|
||||||
return new Range(range);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建一个范围 <br>
|
|
||||||
* 最大值{@code Integer.MAX_VALUE = 2147483647 } <br>
|
|
||||||
* 最小值{@code Integer.MIN_VALUE = -2147483648} <br>
|
|
||||||
* @param start 开始 (包含)
|
|
||||||
* @param end 完毕 (包含)
|
|
||||||
* @see Integer
|
|
||||||
* @return Range 对象
|
|
||||||
*/
|
|
||||||
public static Range of(int start, int end) {
|
|
||||||
return new Range(start, end);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建一个范围 <br>
|
|
||||||
* 最大值{@code Integer.MAX_VALUE = 2147483647 } <br>
|
|
||||||
* 最小值{@code Integer.MIN_VALUE = -2147483648} <br>
|
|
||||||
* @param start 开始 (包含)
|
|
||||||
* @param end 完毕 (包含)
|
|
||||||
* @param step 步长
|
|
||||||
* @see Integer
|
|
||||||
*/
|
|
||||||
public static Range of(int start, int end, int step) {
|
|
||||||
return new Range(start, end, step);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建一个范围 <br>
|
|
||||||
* 最大值{@code Integer.MAX_VALUE = 2147483647 } <br>
|
|
||||||
* 最小值{@code Integer.MIN_VALUE = -2147483648} <br>
|
|
||||||
* @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}<br>
|
|
||||||
* 最大值{@code Integer.MAX_VALUE = 2147483647 } <br>
|
|
||||||
* 最小值{@code Integer.MIN_VALUE = -2147483648} <br>
|
|
||||||
* @param range 完毕 (包含)
|
|
||||||
* @see Integer
|
|
||||||
* @return Range 对象
|
|
||||||
*/
|
|
||||||
public static Range range(int range) {
|
|
||||||
return new Range(range);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 创建一个范围 <br>
|
|
||||||
* 最大值{@code Integer.MAX_VALUE = 2147483647 } <br>
|
|
||||||
* 最小值{@code Integer.MIN_VALUE = -2147483648} <br>
|
|
||||||
* @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<Integer> iterator() {
|
|
||||||
return new Iterator<Integer>() {
|
|
||||||
@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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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;
|
package com.mingliqiye.utils.json;
|
||||||
|
|
||||||
import com.google.gson.*;
|
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 {
|
public class GsonJsonApi implements JsonApi {
|
||||||
|
|
||||||
private final Gson gson;
|
private Gson gsonUnicode;
|
||||||
private final Gson gsonUnicode;
|
private Gson gsonPretty;
|
||||||
private final Gson gsonPretty;
|
private Gson gsonPrettyUnicode;
|
||||||
private final Gson gsonPrettyUnicode;
|
private Gson gson;
|
||||||
|
|
||||||
public GsonJsonApi() {
|
public GsonJsonApi() {
|
||||||
gson = new GsonBuilder()
|
gson = new GsonBuilder()
|
||||||
@ -184,4 +209,41 @@ public class GsonJsonApi implements JsonApi {
|
|||||||
String json = gson.toJson(source);
|
String json = gson.toJson(source);
|
||||||
return gson.fromJson(json, destinationType.getType());
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
* ProjectName mingli-utils
|
* ProjectName mingli-utils
|
||||||
* ModuleName mingli-utils.main
|
* ModuleName mingli-utils.main
|
||||||
* CurrentFile JacksonJsonApi.java
|
* CurrentFile JacksonJsonApi.java
|
||||||
* LastUpdate 2025-09-09 09:31:31
|
* LastUpdate 2025-09-15 11:16:53
|
||||||
* UpdateUser MingLiPro
|
* UpdateUser MingLiPro
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -28,6 +28,10 @@ import com.fasterxml.jackson.databind.JsonNode;
|
|||||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||||
import com.fasterxml.jackson.databind.ObjectReader;
|
import com.fasterxml.jackson.databind.ObjectReader;
|
||||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
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.io.IOException;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
@ -338,4 +342,14 @@ public class JacksonJsonApi implements JsonApi {
|
|||||||
objectMapper.constructType(destinationType.getType())
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 <T> 泛型参数,表示目标对象的类型
|
|
||||||
* @return 解析后的对象实例
|
|
||||||
*/
|
|
||||||
<T> T parse(String json, Class<T> clazz);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将JSON字符串解析为指定泛型类型对象
|
|
||||||
*
|
|
||||||
* @param json 待解析的JSON字符串
|
|
||||||
* @param type 目标对象的Type类型(支持泛型)
|
|
||||||
* @param <T> 泛型参数,表示目标对象的类型
|
|
||||||
* @return 解析后的对象实例
|
|
||||||
*/
|
|
||||||
<T> T parse(String json, JsonTypeReference<T> type);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将对象格式化为JSON字符串
|
|
||||||
*
|
|
||||||
* @param object 待格式化的对象
|
|
||||||
* @return 格式化后的JSON字符串
|
|
||||||
*/
|
|
||||||
String format(Object object);
|
|
||||||
|
|
||||||
String formatUnicode(Object object);
|
|
||||||
|
|
||||||
default <T> T parseFrom(String path, Class<T> clazz) throws IOException {
|
|
||||||
return parseFrom(Paths.get(path), clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
default <T> T parseFrom(Path path, Class<T> clazz) throws IOException {
|
|
||||||
return parseFrom(path.toFile(), clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
default <T> T parseFrom(File file, Class<T> clazz) throws IOException {
|
|
||||||
try (InputStream inputStream = Files.newInputStream(file.toPath())) {
|
|
||||||
return parseFrom(inputStream, clazz);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
default <T> T parseFrom(InputStream inputStream, Class<T> 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> T parseFrom(String path, JsonTypeReference<T> type)
|
|
||||||
throws IOException {
|
|
||||||
return parseFrom(Paths.get(path), type);
|
|
||||||
}
|
|
||||||
|
|
||||||
default <T> T parseFrom(Path path, JsonTypeReference<T> type)
|
|
||||||
throws IOException {
|
|
||||||
return parseFrom(path.toFile(), type);
|
|
||||||
}
|
|
||||||
|
|
||||||
default <T> T parseFrom(File file, JsonTypeReference<T> type)
|
|
||||||
throws IOException {
|
|
||||||
try (InputStream inputStream = Files.newInputStream(file.toPath())) {
|
|
||||||
return parseFrom(inputStream, type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
default <T> T parseFrom(InputStream inputStream, JsonTypeReference<T> 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 <T> 泛型参数,表示目标对象的类型
|
|
||||||
* @return 解析后的对象实例
|
|
||||||
*/
|
|
||||||
default <T> T parse(byte[] json, Class<T> clazz) {
|
|
||||||
return parse(new String(json), clazz);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将字节数组形式的JSON解析为指定泛型类型对象
|
|
||||||
*
|
|
||||||
* @param json 待解析的JSON字节数组
|
|
||||||
* @param type 目标对象的Type类型(支持泛型)
|
|
||||||
* @param <T> 泛型参数,表示目标对象的类型
|
|
||||||
* @return 解析后的对象实例
|
|
||||||
*/
|
|
||||||
default <T> T parse(byte[] json, JsonTypeReference<T> type) {
|
|
||||||
return parse(new String(json), type);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将JSON字符串解析为指定类型的对象,解析失败时返回默认值
|
|
||||||
*
|
|
||||||
* @param json 待解析的JSON字符串
|
|
||||||
* @param clazz 目标对象的Class类型
|
|
||||||
* @param defaultValue 解析失败时返回的默认值
|
|
||||||
* @param <T> 泛型参数,表示目标对象的类型
|
|
||||||
* @return 解析后的对象实例或默认值
|
|
||||||
*/
|
|
||||||
default <T> T parse(String json, Class<T> clazz, T defaultValue) {
|
|
||||||
try {
|
|
||||||
return parse(json, clazz);
|
|
||||||
} catch (Exception e) {
|
|
||||||
return defaultValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将JSON字符串解析为指定泛型类型对象,解析失败时返回默认值
|
|
||||||
*
|
|
||||||
* @param json 待解析的JSON字符串
|
|
||||||
* @param type 目标对象的Type类型(支持泛型)
|
|
||||||
* @param defaultValue 解析失败时返回的默认值
|
|
||||||
* @param <T> 泛型参数,表示目标对象的类型
|
|
||||||
* @return 解析后的对象实例或默认值
|
|
||||||
*/
|
|
||||||
default <T> T parse(
|
|
||||||
String json,
|
|
||||||
JsonTypeReference<T> 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 <T> 泛型参数,表示List中元素的类型
|
|
||||||
* @return 解析后的List集合
|
|
||||||
*/
|
|
||||||
default <T> List<T> parseList(String json, Class<T> elementType) {
|
|
||||||
return parse(json, JsonTypeUtils.listType(elementType));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将JSON字符串解析为指定键值类型的Map集合
|
|
||||||
*
|
|
||||||
* @param json 待解析的JSON字符串
|
|
||||||
* @param keyType Map中键的类型
|
|
||||||
* @param valueType Map中值的类型
|
|
||||||
* @param <K> 泛型参数,表示Map中键的类型
|
|
||||||
* @param <V> 泛型参数,表示Map中值的类型
|
|
||||||
* @return 解析后的Map集合
|
|
||||||
*/
|
|
||||||
default <K, V> Map<K, V> parseMap(
|
|
||||||
String json,
|
|
||||||
Class<K> keyType,
|
|
||||||
Class<V> valueType
|
|
||||||
) {
|
|
||||||
JsonTypeReference<Map<K, V>> mapType = new JsonTypeReference<
|
|
||||||
Map<K, V>
|
|
||||||
>() {};
|
|
||||||
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);
|
|
||||||
|
|
||||||
<T, D> D convert(T source, Class<D> destinationClass);
|
|
||||||
|
|
||||||
<T, D> D convert(T source, JsonTypeReference<D> destinationType);
|
|
||||||
}
|
|
||||||
@ -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<DateTime> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<DateTime> 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
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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>,
|
|
||||||
TT
|
|
||||||
> {
|
|
||||||
|
|
||||||
private final JsonStringConverter<TT> jsonStringConverter;
|
|
||||||
|
|
||||||
public FastjsonJsonStringConverterAdapter(T jsonStringConverter) {
|
|
||||||
this.jsonStringConverter = jsonStringConverter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <
|
|
||||||
T extends JsonStringConverter<TT>,
|
|
||||||
TT
|
|
||||||
> FastjsonJsonStringConverterAdapter<T, TT> of(T t) {
|
|
||||||
return new FastjsonJsonStringConverterAdapter<>(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取FastJson对象写入器
|
|
||||||
*
|
|
||||||
* @return FastJson的ObjectWriter实例
|
|
||||||
*/
|
|
||||||
public ObjectWriter<T> 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<TT> getFastJsonObjectReader() {
|
|
||||||
return (
|
|
||||||
JSONReader reader,
|
|
||||||
Type fieldType,
|
|
||||||
Object fieldName,
|
|
||||||
long features
|
|
||||||
) -> {
|
|
||||||
String value = reader.readString();
|
|
||||||
return jsonStringConverter.deConvert(value);
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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>,
|
|
||||||
TT
|
|
||||||
> {
|
|
||||||
|
|
||||||
private final JsonStringConverter<TT> jsonStringConverter;
|
|
||||||
|
|
||||||
public GsonJsonStringConverterAdapter(T jsonStringConverter) {
|
|
||||||
this.jsonStringConverter = jsonStringConverter;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <
|
|
||||||
T extends JsonStringConverter<TT>,
|
|
||||||
TT
|
|
||||||
> GsonJsonStringConverterAdapter<T, TT> of(T t) {
|
|
||||||
return new GsonJsonStringConverterAdapter<>(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取Gson类型适配器
|
|
||||||
*
|
|
||||||
* @return Gson的TypeAdapter实例
|
|
||||||
*/
|
|
||||||
public TypeAdapter<TT> getGsonTypeAdapter() {
|
|
||||||
return new TypeAdapter<TT>() {
|
|
||||||
@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);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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 <T> JSON转换器
|
|
||||||
* @param <TT> JSON转换器的泛型
|
|
||||||
* @author MingLiPro
|
|
||||||
*/
|
|
||||||
public class JacksonJsonStringConverterAdapter<
|
|
||||||
T extends JsonStringConverter<TT>,
|
|
||||||
TT
|
|
||||||
> {
|
|
||||||
|
|
||||||
private final JsonStringConverter<TT> jsonStringConverter;
|
|
||||||
|
|
||||||
private JacksonJsonStringConverterAdapter(T jsonStringConverter) {
|
|
||||||
this.jsonStringConverter = jsonStringConverter;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
*
|
|
||||||
* @param t JSON转换器实例
|
|
||||||
* @return JSON转换器的适配器
|
|
||||||
* @param <T> JSON转换器
|
|
||||||
* @param <TT> JSON转换器的泛型
|
|
||||||
*/
|
|
||||||
public static <
|
|
||||||
T extends JsonStringConverter<TT>,
|
|
||||||
TT
|
|
||||||
> JacksonJsonStringConverterAdapter<T, TT> of(T t) {
|
|
||||||
return new JacksonJsonStringConverterAdapter<>(t);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取Jackson反序列化器
|
|
||||||
*
|
|
||||||
* @return Jackson的JsonDeserializer实例
|
|
||||||
*/
|
|
||||||
public JsonDeserializer<TT> getJacksonJsonDeserializer() {
|
|
||||||
return new JsonDeserializer<TT>() {
|
|
||||||
@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<TT> getJacksonJsonSerializer() {
|
|
||||||
return new JsonSerializer<TT>() {
|
|
||||||
@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<TT> tClass = jsonStringConverter.getTClass();
|
|
||||||
SimpleModule m = new SimpleModule(tClass.getSimpleName());
|
|
||||||
m.addSerializer(tClass, getJacksonJsonSerializer());
|
|
||||||
m.addDeserializer(tClass, getJacksonJsonDeserializer());
|
|
||||||
return m;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,60 +0,0 @@
|
|||||||
package com.mingliqiye.utils.json.converters;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* JSON转换器接口,提供对象与字符串之间的相互转换功能,并支持多种JSON库
|
|
||||||
*
|
|
||||||
* @param <T> 需要转换的对象类型
|
|
||||||
*/
|
|
||||||
public abstract class JsonStringConverter<T> {
|
|
||||||
|
|
||||||
public abstract Class<T> getTClass();
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将对象转换为字符串
|
|
||||||
*
|
|
||||||
* @param obj 待转换的对象
|
|
||||||
* @return 转换后的字符串
|
|
||||||
*/
|
|
||||||
abstract String convert(T obj);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 将字符串转换为对象
|
|
||||||
*
|
|
||||||
* @param string 待转换的字符串
|
|
||||||
* @return 转换后的对象
|
|
||||||
*/
|
|
||||||
abstract T deConvert(String string);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取 Fastjson 的适配器
|
|
||||||
* @return 适配器实例
|
|
||||||
*/
|
|
||||||
public FastjsonJsonStringConverterAdapter<
|
|
||||||
JsonStringConverter<T>,
|
|
||||||
T
|
|
||||||
> getFastjsonJsonStringConverterAdapter() {
|
|
||||||
return FastjsonJsonStringConverterAdapter.of(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取 Gson 的适配器
|
|
||||||
* @return 适配器实例
|
|
||||||
*/
|
|
||||||
public GsonJsonStringConverterAdapter<
|
|
||||||
JsonStringConverter<T>,
|
|
||||||
T
|
|
||||||
> getGsonJsonStringConverterAdapter() {
|
|
||||||
return GsonJsonStringConverterAdapter.of(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 获取 Jackson 的适配器
|
|
||||||
* @return 适配器实例
|
|
||||||
*/
|
|
||||||
public JacksonJsonStringConverterAdapter<
|
|
||||||
JsonStringConverter<T>,
|
|
||||||
T
|
|
||||||
> getJacksonJsonStringConverterAdapter() {
|
|
||||||
return JacksonJsonStringConverterAdapter.of(this);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,27 +0,0 @@
|
|||||||
package com.mingliqiye.utils.json.converters;
|
|
||||||
|
|
||||||
import com.mingliqiye.utils.uuid.UUID;
|
|
||||||
|
|
||||||
public class UUIDJsonStringConverter extends JsonStringConverter<UUID> {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Class<UUID> 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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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 等类型的互转。
|
|
||||||
*<br>
|
|
||||||
* 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());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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; // 近似值
|
|
||||||
}
|
|
||||||
@ -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;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 时间格式化枚举类
|
|
||||||
* <p>
|
|
||||||
* 定义了常用的时间格式化模式,用于日期时间的解析和格式化操作
|
|
||||||
* 每个枚举常量包含对应的格式化字符串和字符串长度
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -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> {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 设置非空参数值
|
|
||||||
* 将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);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -16,15 +16,17 @@
|
|||||||
* ProjectName mingli-utils
|
* ProjectName mingli-utils
|
||||||
* ModuleName mingli-utils.main
|
* ModuleName mingli-utils.main
|
||||||
* CurrentFile Main.kt
|
* CurrentFile Main.kt
|
||||||
* LastUpdate 2025-09-15 08:56:35
|
* LastUpdate 2025-09-15 09:53:43
|
||||||
* UpdateUser MingLiPro
|
* UpdateUser MingLiPro
|
||||||
*/
|
*/
|
||||||
package com.mingliqiye.utils
|
package com.mingliqiye.utils
|
||||||
|
|
||||||
import com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration
|
import com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration
|
||||||
|
import com.mingliqiye.utils.time.DateTime
|
||||||
|
|
||||||
fun main() {
|
fun main() {
|
||||||
AutoConfiguration.printBanner()
|
AutoConfiguration.printBanner()
|
||||||
|
println(DateTime.now())
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
|
|||||||
181
src/main/kotlin/com/mingliqiye/utils/functions/Functions.kt
Normal file
181
src/main/kotlin/com/mingliqiye/utils/functions/Functions.kt
Normal file
@ -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<Any, Future<*>> = 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<P> {
|
||||||
|
fun call(p: P)
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
fun interface P1RFunction<P, R> {
|
||||||
|
fun call(p: P): R
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
fun interface P2Function<P, P1> {
|
||||||
|
fun call(p: P, p1: P1)
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
fun interface P2RFunction<P, P1, R> {
|
||||||
|
fun call(p: P, p1: P1): R
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
fun interface P3Function<P, P1, P2> {
|
||||||
|
fun call(p: P, p1: P1, p2: P2)
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
fun interface P3RFunction<P, P1, P2, R> {
|
||||||
|
fun call(p: P, p1: P1, p2: P2): R
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
fun interface P4Function<P, P1, P2, P3> {
|
||||||
|
fun call(p: P, p1: P1, p2: P2, p3: P3)
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
fun interface P4RFunction<P, P1, P2, P3, R> {
|
||||||
|
fun call(p: P, p1: P1, p2: P2, p3: P3): R
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
fun interface P5Function<P, P1, P2, P3, P4> {
|
||||||
|
fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4)
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
fun interface P5RFunction<P, P1, P2, P3, P4, R> {
|
||||||
|
fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4): R
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
fun interface P6Function<P, P1, P2, P3, P4, P5> {
|
||||||
|
fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5)
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
fun interface P6RFunction<P, P1, P2, P3, P4, P5, R> {
|
||||||
|
fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5): R
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
fun interface P7Function<P, P1, P2, P3, P4, P5, P6> {
|
||||||
|
fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6)
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
fun interface P7RFunction<P, P1, P2, P3, P4, P5, P6, R> {
|
||||||
|
fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6): R
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
fun interface P8Function<P, P1, P2, P3, P4, P5, P6, P7> {
|
||||||
|
fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7)
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
fun interface P8RFunction<P, P1, P2, P3, P4, P5, P6, P7, R> {
|
||||||
|
fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7): R
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
fun interface P9Function<P, P1, P2, P3, P4, P5, P6, P7, P8> {
|
||||||
|
fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8)
|
||||||
|
}
|
||||||
|
|
||||||
|
@FunctionalInterface
|
||||||
|
fun interface P9RFunction<P, P1, P2, P3, P4, P5, P6, P7, P8, R> {
|
||||||
|
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<P, P1, P2, P3, P4, P5, P6, P7, P8, P9> {
|
||||||
|
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<P, P1, P2, P3, P4, P5, P6, P7, P8, P9, R> {
|
||||||
|
fun call(p: P, p1: P1, p2: P2, p3: P3, p4: P4, p5: P5, p6: P6, p7: P7, p8: P8, p9: P9): R
|
||||||
|
}
|
||||||
107
src/main/kotlin/com/mingliqiye/utils/hash/HashUtils.kt
Normal file
107
src/main/kotlin/com/mingliqiye/utils/hash/HashUtils.kt
Normal file
@ -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)
|
||||||
|
}
|
||||||
393
src/main/kotlin/com/mingliqiye/utils/json/JsonApi.kt
Normal file
393
src/main/kotlin/com/mingliqiye/utils/json/JsonApi.kt
Normal file
@ -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 <T> 泛型参数,表示目标对象的类型
|
||||||
|
* @return 解析后的对象实例
|
||||||
|
</T> */
|
||||||
|
fun <T> parse(json: String, clazz: Class<T>): T
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将JSON字符串解析为指定泛型类型对象
|
||||||
|
*
|
||||||
|
* @param json 待解析的JSON字符串
|
||||||
|
* @param type 目标对象的Type类型(支持泛型)
|
||||||
|
* @param <T> 泛型参数,表示目标对象的类型
|
||||||
|
* @return 解析后的对象实例
|
||||||
|
</T> */
|
||||||
|
fun <T> parse(json: String, type: JsonTypeReference<T>): T
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将对象格式化为JSON字符串
|
||||||
|
*
|
||||||
|
* @param obj 待格式化的对象
|
||||||
|
* @return 格式化后的JSON字符串
|
||||||
|
*/
|
||||||
|
fun format(obj: Any): String
|
||||||
|
|
||||||
|
fun formatUnicode(obj: Any): String
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
fun <T> parseFrom(path: String, clazz: Class<T>): T {
|
||||||
|
return parseFrom(Paths.get(path), clazz)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
fun <T> parseFrom(path: Path, clazz: Class<T>): T {
|
||||||
|
return parseFrom(path.toFile(), clazz)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
fun <T> parseFrom(file: File, clazz: Class<T>): T {
|
||||||
|
Files.newInputStream(file.toPath()).use { inputStream ->
|
||||||
|
return parseFrom(inputStream, clazz)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
fun <T> parseFrom(inputStream: InputStream, clazz: Class<T>): 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 <T> parseFrom(path: String, type: JsonTypeReference<T>): T {
|
||||||
|
return parseFrom(Paths.get(path), type)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
fun <T> parseFrom(path: Path, type: JsonTypeReference<T>): T {
|
||||||
|
return parseFrom(path.toFile(), type)
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
fun <T> parseFrom(file: File, type: JsonTypeReference<T>): T {
|
||||||
|
Files.newInputStream(file.toPath()).use { inputStream ->
|
||||||
|
return parseFrom<T>(inputStream, type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Throws(IOException::class)
|
||||||
|
fun <T> parseFrom(inputStream: InputStream, type: JsonTypeReference<T>): 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 <T> 泛型参数,表示目标对象的类型
|
||||||
|
* @return 解析后的对象实例
|
||||||
|
</T> */
|
||||||
|
fun <T> parse(json: ByteArray, clazz: Class<T>): T {
|
||||||
|
return parse(String(json), clazz)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将字节数组形式的JSON解析为指定泛型类型对象
|
||||||
|
*
|
||||||
|
* @param json 待解析的JSON字节数组
|
||||||
|
* @param type 目标对象的Type类型(支持泛型)
|
||||||
|
* @param <T> 泛型参数,表示目标对象的类型
|
||||||
|
* @return 解析后的对象实例
|
||||||
|
</T> */
|
||||||
|
fun <T> parse(json: ByteArray, type: JsonTypeReference<T>): T {
|
||||||
|
return parse(String(json), type)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将JSON字符串解析为指定类型的对象,解析失败时返回默认值
|
||||||
|
*
|
||||||
|
* @param json 待解析的JSON字符串
|
||||||
|
* @param clazz 目标对象的Class类型
|
||||||
|
* @param defaultValue 解析失败时返回的默认值
|
||||||
|
* @param <T> 泛型参数,表示目标对象的类型
|
||||||
|
* @return 解析后的对象实例或默认值
|
||||||
|
</T> */
|
||||||
|
fun <T> parse(json: String, clazz: Class<T>, defaultValue: T): T {
|
||||||
|
try {
|
||||||
|
return parse(json, clazz)
|
||||||
|
} catch (e: Exception) {
|
||||||
|
return defaultValue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将JSON字符串解析为指定泛型类型对象,解析失败时返回默认值
|
||||||
|
*
|
||||||
|
* @param json 待解析的JSON字符串
|
||||||
|
* @param type 目标对象的Type类型(支持泛型)
|
||||||
|
* @param defaultValue 解析失败时返回的默认值
|
||||||
|
* @param <T> 泛型参数,表示目标对象的类型
|
||||||
|
* @return 解析后的对象实例或默认值
|
||||||
|
**/
|
||||||
|
fun <T> parse(
|
||||||
|
json: String,
|
||||||
|
type: JsonTypeReference<T>,
|
||||||
|
defaultValue: T
|
||||||
|
): T {
|
||||||
|
try {
|
||||||
|
return parse<T>(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 <T> 泛型参数,表示List中元素的类型
|
||||||
|
* @return 解析后的List集合
|
||||||
|
</T> */
|
||||||
|
fun <T> parseList(json: String, elementType: Class<T>): MutableList<T> {
|
||||||
|
return parse<MutableList<T>>(json, JsonTypeUtils.listType<T>(elementType))
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 将JSON字符串解析为指定键值类型的Map集合
|
||||||
|
*
|
||||||
|
* @param json 待解析的JSON字符串
|
||||||
|
* @param keyType Map中键的类型
|
||||||
|
* @param valueType Map中值的类型
|
||||||
|
* @param <K> 泛型参数,表示Map中键的类型
|
||||||
|
* @param <V> 泛型参数,表示Map中值的类型
|
||||||
|
* @return 解析后的Map集合
|
||||||
|
</V></K> */
|
||||||
|
fun <K, V> parseMap(
|
||||||
|
json: String,
|
||||||
|
keyType: Class<K>,
|
||||||
|
valueType: Class<V>
|
||||||
|
): MutableMap<K, V> {
|
||||||
|
val mapType: JsonTypeReference<MutableMap<K, V>> = object : JsonTypeReference<MutableMap<K, V>>() {}
|
||||||
|
return parse<MutableMap<K, V>>(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 <T, D> convert(source: T, destinationClass: Class<D>): D
|
||||||
|
|
||||||
|
fun <T, D> convert(source: T, destinationType: JsonTypeReference<D>): D
|
||||||
|
|
||||||
|
fun addJsonConverter(c: JsonConverter<*, *>)
|
||||||
|
fun addJsonStringConverter(c: JsonStringConverter<*>)
|
||||||
|
}
|
||||||
@ -15,14 +15,22 @@
|
|||||||
*
|
*
|
||||||
* ProjectName mingli-utils
|
* ProjectName mingli-utils
|
||||||
* ModuleName mingli-utils.main
|
* ModuleName mingli-utils.main
|
||||||
* CurrentFile P8RFunction.java
|
* CurrentFile JsonConverter.kt
|
||||||
* LastUpdate 2025-09-09 08:37:34
|
* LastUpdate 2025-09-15 11:12:07
|
||||||
* UpdateUser MingLiPro
|
* UpdateUser MingLiPro
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package com.mingliqiye.utils.functions;
|
package com.mingliqiye.utils.json.converters
|
||||||
|
|
||||||
@FunctionalInterface
|
interface JsonConverter<F, T> {
|
||||||
public interface P8RFunction<P, P1, P2, P3, P4, P5, P6, P7, R> {
|
fun convert(obj: F?): T?
|
||||||
R call(P p, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7);
|
fun deConvert(obj: T?): F?
|
||||||
|
val tClass: Class<F>
|
||||||
|
|
||||||
|
fun getStringConverter(): JsonStringConverter<F>? {
|
||||||
|
if (this is JsonStringConverter<*>) {
|
||||||
|
return this as JsonStringConverter<F>
|
||||||
|
}
|
||||||
|
return null
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@ -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 <T> 需要转换的对象类型
|
||||||
|
</T> */
|
||||||
|
abstract class JsonStringConverter<T> : JsonConverter<T, String> {
|
||||||
|
val fastjsonJsonStringConverterAdapter: FastjsonJsonStringConverterAdapter<JsonStringConverter<T>, T>
|
||||||
|
/**
|
||||||
|
* 获取 Fastjson 的适配器
|
||||||
|
* @return 适配器实例
|
||||||
|
*/
|
||||||
|
get() = FastjsonJsonStringConverterAdapter.of(this)
|
||||||
|
|
||||||
|
val gsonJsonStringConverterAdapter: GsonJsonStringConverterAdapter<JsonStringConverter<T>, T>
|
||||||
|
/**
|
||||||
|
* 获取 Gson 的适配器
|
||||||
|
* @return 适配器实例
|
||||||
|
*/
|
||||||
|
get() = GsonJsonStringConverterAdapter.of(this)
|
||||||
|
|
||||||
|
val jacksonJsonStringConverterAdapter: JacksonJsonStringConverterAdapter<JsonStringConverter<T>, T>
|
||||||
|
/**
|
||||||
|
* 获取 Jackson 的适配器
|
||||||
|
* @return 适配器实例
|
||||||
|
*/
|
||||||
|
get() = JacksonJsonStringConverterAdapter.of(this)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class JacksonJsonStringConverterAdapter<T : JsonStringConverter<TT>, TT
|
||||||
|
> private constructor(val jsonStringConverter: T) {
|
||||||
|
|
||||||
|
val jacksonJsonDeserializer: JsonDeserializer<TT?>
|
||||||
|
/**
|
||||||
|
* 获取Jackson反序列化器
|
||||||
|
*
|
||||||
|
* @return Jackson的JsonDeserializer实例
|
||||||
|
*/
|
||||||
|
get() = object : JsonDeserializer<TT?>() {
|
||||||
|
@Throws(IOException::class)
|
||||||
|
override fun deserialize(p: JsonParser, ctxt: DeserializationContext?): TT? {
|
||||||
|
if (p.isNaN) return null
|
||||||
|
return jsonStringConverter.deConvert(p.valueAsString)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
val jacksonJsonSerializer: JsonSerializer<TT?>
|
||||||
|
/**
|
||||||
|
* 获取Jackson序列化器
|
||||||
|
*
|
||||||
|
* @return Jackson的JsonSerializer实例
|
||||||
|
*/
|
||||||
|
get() = object : JsonSerializer<TT?>() {
|
||||||
|
@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<TT?>(tClass, this.jacksonJsonSerializer)
|
||||||
|
m.addDeserializer<TT?>(tClass, this.jacksonJsonDeserializer)
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param t JSON转换器实例
|
||||||
|
* @return JSON转换器的适配器
|
||||||
|
* @param <T> JSON转换器
|
||||||
|
* @param <TT> JSON转换器的泛型
|
||||||
|
**/
|
||||||
|
fun <T : JsonStringConverter<TT>, TT
|
||||||
|
> of(t: T): JacksonJsonStringConverterAdapter<T, TT> {
|
||||||
|
return JacksonJsonStringConverterAdapter(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class GsonJsonStringConverterAdapter<T : JsonStringConverter<TT>, TT
|
||||||
|
>(val jsonStringConverter: T) {
|
||||||
|
|
||||||
|
val gsonTypeAdapter: TypeAdapter<TT?>
|
||||||
|
/**
|
||||||
|
* 获取Gson类型适配器
|
||||||
|
*
|
||||||
|
* @return Gson的TypeAdapter实例
|
||||||
|
*/
|
||||||
|
get() = object : TypeAdapter<TT?>() {
|
||||||
|
@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 <T : JsonStringConverter<TT>, TT
|
||||||
|
> of(t: T): GsonJsonStringConverterAdapter<T, TT> {
|
||||||
|
return GsonJsonStringConverterAdapter(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class FastjsonJsonStringConverterAdapter<T : JsonConverter<TT, String>, TT
|
||||||
|
>(val jsonStringConverter: T) {
|
||||||
|
@Suppress("UNCHECKED_CAST")
|
||||||
|
val fastJsonObjectWriter: ObjectWriter<T>
|
||||||
|
/**
|
||||||
|
* 获取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<TT>
|
||||||
|
/**
|
||||||
|
* 获取FastJson对象读取器
|
||||||
|
*
|
||||||
|
* @return FastJson的ObjectReader实例
|
||||||
|
*/
|
||||||
|
get() = ObjectReader { reader: JSONReader?, _: Type?, _: Any?, _: Long
|
||||||
|
->
|
||||||
|
val value = reader!!.readString()
|
||||||
|
jsonStringConverter.deConvert(value)
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
fun <T : JsonConverter<TT, String>, TT
|
||||||
|
> of(t: T): FastjsonJsonStringConverterAdapter<T, TT> {
|
||||||
|
return FastjsonJsonStringConverterAdapter(t)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class DateTimeJsonConverter : JsonStringConverter<DateTime>() {
|
||||||
|
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<UUID>() {
|
||||||
|
override val tClass: Class<UUID> = 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)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
@ -16,15 +16,13 @@
|
|||||||
* ProjectName mingli-utils
|
* ProjectName mingli-utils
|
||||||
* ModuleName mingli-utils.main
|
* ModuleName mingli-utils.main
|
||||||
* CurrentFile RandomBytes.kt
|
* CurrentFile RandomBytes.kt
|
||||||
* LastUpdate 2025-09-15 00:08:18
|
* LastUpdate 2025-09-15 09:54:33
|
||||||
* UpdateUser MingLiPro
|
* UpdateUser MingLiPro
|
||||||
*/
|
*/
|
||||||
@file:JvmName("RandomBytes")
|
@file:JvmName("RandomBytes")
|
||||||
|
|
||||||
package com.mingliqiye.utils.random
|
package com.mingliqiye.utils.random
|
||||||
|
|
||||||
import com.mingliqiye.utils.iterator.Range
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 生成指定长度的随机字节数组
|
* 生成指定长度的随机字节数组
|
||||||
* @param length 数组长度
|
* @param length 数组长度
|
||||||
@ -32,7 +30,9 @@ import com.mingliqiye.utils.iterator.Range
|
|||||||
*/
|
*/
|
||||||
fun randomBytes(length: Int): ByteArray {
|
fun randomBytes(length: Int): ByteArray {
|
||||||
val bytes = ByteArray(length)
|
val bytes = ByteArray(length)
|
||||||
Range(0, length - 1).forEach { i: Int -> bytes[i] = randomByte(0x00.toByte(), 0xff.toByte()) }
|
for (i in 0..<length) {
|
||||||
|
bytes[i] = randomByte(0x00.toByte(), 0xff.toByte())
|
||||||
|
}
|
||||||
return bytes
|
return bytes
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
* ProjectName mingli-utils
|
* ProjectName mingli-utils
|
||||||
* ModuleName mingli-utils.main
|
* ModuleName mingli-utils.main
|
||||||
* CurrentFile GsonAutoConfiguration.kt
|
* CurrentFile GsonAutoConfiguration.kt
|
||||||
* LastUpdate 2025-09-14 22:06:47
|
* LastUpdate 2025-09-15 10:29:30
|
||||||
* UpdateUser MingLiPro
|
* UpdateUser MingLiPro
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -58,16 +58,16 @@ open class GsonAutoConfiguration {
|
|||||||
try {
|
try {
|
||||||
return gsonBuilder
|
return gsonBuilder
|
||||||
.registerTypeAdapter(
|
.registerTypeAdapter(
|
||||||
uuidJsonStringConverter.getTClass(),
|
uuidJsonStringConverter.tClass,
|
||||||
dateTimeJsonConverter
|
uuidJsonStringConverter
|
||||||
.getGsonJsonStringConverterAdapter()
|
.gsonJsonStringConverterAdapter
|
||||||
.getGsonTypeAdapter()
|
.gsonTypeAdapter
|
||||||
)
|
)
|
||||||
.registerTypeAdapter(
|
.registerTypeAdapter(
|
||||||
dateTimeJsonConverter.getTClass(),
|
dateTimeJsonConverter.tClass,
|
||||||
dateTimeJsonConverter
|
dateTimeJsonConverter
|
||||||
.getGsonJsonStringConverterAdapter()
|
.gsonJsonStringConverterAdapter
|
||||||
.getGsonTypeAdapter()
|
.gsonTypeAdapter
|
||||||
)
|
)
|
||||||
} finally {
|
} finally {
|
||||||
log.info("MingliUtils GsonBuilder TypeAdapter add")
|
log.info("MingliUtils GsonBuilder TypeAdapter add")
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
* ProjectName mingli-utils
|
* ProjectName mingli-utils
|
||||||
* ModuleName mingli-utils.main
|
* ModuleName mingli-utils.main
|
||||||
* CurrentFile JacksonAutoConfiguration.kt
|
* CurrentFile JacksonAutoConfiguration.kt
|
||||||
* LastUpdate 2025-09-14 22:10:08
|
* LastUpdate 2025-09-15 10:29:02
|
||||||
* UpdateUser MingLiPro
|
* UpdateUser MingLiPro
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@ -49,12 +49,12 @@ open class JacksonAutoConfiguration(objectMapper: ObjectMapper) {
|
|||||||
.registerModule(
|
.registerModule(
|
||||||
DateTimeJsonConverter()
|
DateTimeJsonConverter()
|
||||||
.jacksonJsonStringConverterAdapter
|
.jacksonJsonStringConverterAdapter
|
||||||
.getJacksonModule()
|
.jacksonModule
|
||||||
)
|
)
|
||||||
.registerModule(
|
.registerModule(
|
||||||
UUIDJsonStringConverter()
|
UUIDJsonStringConverter()
|
||||||
.jacksonJsonStringConverterAdapter
|
.jacksonJsonStringConverterAdapter
|
||||||
.getJacksonModule()
|
.jacksonModule
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -16,7 +16,7 @@
|
|||||||
* ProjectName mingli-utils
|
* ProjectName mingli-utils
|
||||||
* ModuleName mingli-utils.main
|
* ModuleName mingli-utils.main
|
||||||
* CurrentFile SystemUtil.kt
|
* CurrentFile SystemUtil.kt
|
||||||
* LastUpdate 2025-09-15 08:50:23
|
* LastUpdate 2025-09-15 11:18:34
|
||||||
* UpdateUser MingLiPro
|
* UpdateUser MingLiPro
|
||||||
*/
|
*/
|
||||||
@file:JvmName("SystemUtils")
|
@file:JvmName("SystemUtils")
|
||||||
@ -66,7 +66,7 @@ fun isUnix(): Boolean {
|
|||||||
*
|
*
|
||||||
* @return JDK版本号字符串
|
* @return JDK版本号字符串
|
||||||
*/
|
*/
|
||||||
fun getJdkVersion(): String {
|
fun getJdkVersion(): String? {
|
||||||
return System.getProperty("java.specification.version")
|
return System.getProperty("java.specification.version")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
678
src/main/kotlin/com/mingliqiye/utils/time/DateTime.kt
Normal file
678
src/main/kotlin/com/mingliqiye/utils/time/DateTime.kt
Normal file
@ -0,0 +1,678 @@
|
|||||||
|
/*
|
||||||
|
* 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.kt
|
||||||
|
* LastUpdate 2025-09-15 09:57:50
|
||||||
|
* UpdateUser MingLiPro
|
||||||
|
*/
|
||||||
|
|
||||||
|
package com.mingliqiye.utils.time
|
||||||
|
|
||||||
|
import com.mingliqiye.utils.jna.FILETIME_EPOCH_OFFSET
|
||||||
|
import com.mingliqiye.utils.jna.NANOS_PER_100NS
|
||||||
|
import com.mingliqiye.utils.jna.WinKernel32Api
|
||||||
|
import com.mingliqiye.utils.jna.getWinKernel32Apis
|
||||||
|
import com.mingliqiye.utils.logger.mingLiLoggerFactory
|
||||||
|
import com.mingliqiye.utils.system.getJavaVersionAsInteger
|
||||||
|
import com.mingliqiye.utils.system.isWindows
|
||||||
|
import org.slf4j.Logger
|
||||||
|
import java.io.Serializable
|
||||||
|
import java.time.LocalDateTime
|
||||||
|
import java.time.ZoneId
|
||||||
|
import java.time.format.DateTimeFormatter
|
||||||
|
import java.time.temporal.ChronoUnit
|
||||||
|
import java.util.*
|
||||||
|
import kotlin.time.ExperimentalTime
|
||||||
|
import kotlin.time.Instant
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时间位移 类
|
||||||
|
*
|
||||||
|
* @author MingLiPro
|
||||||
|
*/
|
||||||
|
class DateTimeOffset private constructor(
|
||||||
|
val offsetType: ChronoUnit,
|
||||||
|
val offset: Long
|
||||||
|
) {
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
/**
|
||||||
|
* 创建一个新的DateTimeOffset实例
|
||||||
|
*
|
||||||
|
* @param offsetType 偏移量的单位类型,指定偏移量的计算单位
|
||||||
|
* @param offset 偏移量的数值,可以为正数、负数或零
|
||||||
|
* @return 返回一个新的DateTimeOffset对象,包含指定的偏移量信息
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun of(offsetType: ChronoUnit, offset: Long): DateTimeOffset {
|
||||||
|
return DateTimeOffset(offsetType, offset)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 创建一个 DateTimeOffset 实例
|
||||||
|
*
|
||||||
|
* @param offset 偏移量数值
|
||||||
|
* @param offsetType 偏移量的时间单位类型
|
||||||
|
* @return 返回一个新的 DateTimeOffset 实例
|
||||||
|
*/
|
||||||
|
@JvmStatic
|
||||||
|
fun of(offset: Long, offsetType: ChronoUnit): DateTimeOffset {
|
||||||
|
return DateTimeOffset(offsetType, offset)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时间格式化枚举类
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* 定义了常用的时间格式化模式,用于日期时间的解析和格式化操作
|
||||||
|
* 每个枚举常量包含对应的格式化字符串和字符串长度
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
enum class Formatter(private val value: String) {
|
||||||
|
/**
|
||||||
|
* 标准日期时间格式: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");
|
||||||
|
|
||||||
|
private val len: Int = value.length
|
||||||
|
|
||||||
|
fun getLen(): Int {
|
||||||
|
return this.len
|
||||||
|
}
|
||||||
|
|
||||||
|
fun getValue(): String {
|
||||||
|
return this.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 时间类,用于处理日期时间的转换、格式化等操作。
|
||||||
|
* 提供了多种静态方法来创建 DateTime 实例,并支持与 Date、LocalDateTime 等类型的互转。
|
||||||
|
*<br>
|
||||||
|
* 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
|
||||||
|
}
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user