generated from mingliqiye/lib-tem
refactor(time): 重构 DateTime 类并添加新功能 #3
@ -16,7 +16,7 @@
|
||||
* ProjectName mingli-utils
|
||||
* ModuleName mingli-utils
|
||||
* CurrentFile build.gradle.kts
|
||||
* LastUpdate 2025-09-14 22:32:52
|
||||
* LastUpdate 2025-09-15 11:20:04
|
||||
* UpdateUser MingLiPro
|
||||
*/
|
||||
|
||||
@ -31,7 +31,6 @@ plugins {
|
||||
kotlin("jvm") version "2.2.20"
|
||||
id("org.jetbrains.dokka") version "2.0.0"
|
||||
}
|
||||
|
||||
val GROUPSID = project.properties["GROUPSID"] as String
|
||||
val VERSIONS = project.properties["VERSIONS"] as String
|
||||
val ARTIFACTID = project.properties["ARTIFACTID"] as String
|
||||
|
||||
@ -16,10 +16,10 @@
|
||||
# ProjectName mingli-utils
|
||||
# ModuleName mingli-utils
|
||||
# CurrentFile gradle.properties
|
||||
# LastUpdate 2025-09-15 09:25:10
|
||||
# LastUpdate 2025-09-15 11:19:10
|
||||
# UpdateUser MingLiPro
|
||||
#
|
||||
JDKVERSIONS=1.8
|
||||
GROUPSID=com.mingliqiye.utils
|
||||
ARTIFACTID=mingli-utils
|
||||
VERSIONS=4.0.0-pre
|
||||
VERSIONS=4.0.1
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
* ProjectName mingli-utils
|
||||
* ModuleName mingli-utils.main
|
||||
* CurrentFile Main.java
|
||||
* LastUpdate 2025-09-15 09:24:07
|
||||
* LastUpdate 2025-09-15 11:18:12
|
||||
* UpdateUser MingLiPro
|
||||
*/
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
import com.google.gson.*;
|
||||
import com.mingliqiye.utils.json.converters.JsonConverter;
|
||||
import com.mingliqiye.utils.json.converters.JsonStringConverter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
public class GsonJsonApi implements JsonApi {
|
||||
|
||||
private final Gson gson;
|
||||
private final Gson gsonUnicode;
|
||||
private final Gson gsonPretty;
|
||||
private final Gson gsonPrettyUnicode;
|
||||
private Gson gsonUnicode;
|
||||
private Gson gsonPretty;
|
||||
private Gson gsonPrettyUnicode;
|
||||
private Gson gson;
|
||||
|
||||
public GsonJsonApi() {
|
||||
gson = new GsonBuilder()
|
||||
@ -184,4 +209,41 @@ public class GsonJsonApi implements JsonApi {
|
||||
String json = gson.toJson(source);
|
||||
return gson.fromJson(json, destinationType.getType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addJsonConverter(@NotNull JsonConverter<?, ?> c) {
|
||||
gson = gson
|
||||
.newBuilder()
|
||||
.registerTypeAdapter(
|
||||
c.getTClass(),
|
||||
c.getStringConverter().getGsonJsonStringConverterAdapter()
|
||||
)
|
||||
.create();
|
||||
gsonUnicode = gsonUnicode
|
||||
.newBuilder()
|
||||
.registerTypeAdapter(
|
||||
c.getTClass(),
|
||||
c.getStringConverter().getGsonJsonStringConverterAdapter()
|
||||
)
|
||||
.create();
|
||||
gsonPretty = gsonPretty
|
||||
.newBuilder()
|
||||
.registerTypeAdapter(
|
||||
c.getTClass(),
|
||||
c.getStringConverter().getGsonJsonStringConverterAdapter()
|
||||
)
|
||||
.create();
|
||||
gsonPrettyUnicode = gsonPrettyUnicode
|
||||
.newBuilder()
|
||||
.registerTypeAdapter(
|
||||
c.getTClass(),
|
||||
c.getStringConverter().getGsonJsonStringConverterAdapter()
|
||||
)
|
||||
.create();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addJsonStringConverter(@NotNull JsonStringConverter<?> c) {
|
||||
addJsonConverter(c);
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
* ProjectName mingli-utils
|
||||
* ModuleName mingli-utils.main
|
||||
* CurrentFile JacksonJsonApi.java
|
||||
* LastUpdate 2025-09-09 09:31:31
|
||||
* LastUpdate 2025-09-15 11:16:53
|
||||
* UpdateUser MingLiPro
|
||||
*/
|
||||
|
||||
@ -28,6 +28,10 @@ import com.fasterxml.jackson.databind.JsonNode;
|
||||
import com.fasterxml.jackson.databind.ObjectMapper;
|
||||
import com.fasterxml.jackson.databind.ObjectReader;
|
||||
import com.fasterxml.jackson.databind.node.ObjectNode;
|
||||
import com.mingliqiye.utils.json.converters.JsonConverter;
|
||||
import com.mingliqiye.utils.json.converters.JsonStringConverter;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
@ -338,4 +342,14 @@ public class JacksonJsonApi implements JsonApi {
|
||||
objectMapper.constructType(destinationType.getType())
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addJsonConverter(@NotNull JsonConverter<?, ?> c) {
|
||||
objectMapper.registerModule(c.getStringConverter().getJacksonJsonStringConverterAdapter().getJacksonModule());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addJsonStringConverter(@NotNull JsonStringConverter<?> c) {
|
||||
addJsonConverter(c);
|
||||
}
|
||||
}
|
||||
|
||||
@ -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
|
||||
* ModuleName mingli-utils.main
|
||||
* CurrentFile Main.kt
|
||||
* LastUpdate 2025-09-15 08:56:35
|
||||
* LastUpdate 2025-09-15 09:53:43
|
||||
* UpdateUser MingLiPro
|
||||
*/
|
||||
package com.mingliqiye.utils
|
||||
|
||||
import com.mingliqiye.utils.springboot.autoconfigure.AutoConfiguration
|
||||
import com.mingliqiye.utils.time.DateTime
|
||||
|
||||
fun main() {
|
||||
AutoConfiguration.printBanner()
|
||||
println(DateTime.now())
|
||||
}
|
||||
|
||||
fun test() {
|
||||
|
||||
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
|
||||
* ModuleName mingli-utils.main
|
||||
* CurrentFile P8RFunction.java
|
||||
* LastUpdate 2025-09-09 08:37:34
|
||||
* CurrentFile JsonConverter.kt
|
||||
* LastUpdate 2025-09-15 11:12:07
|
||||
* UpdateUser MingLiPro
|
||||
*/
|
||||
|
||||
package com.mingliqiye.utils.functions;
|
||||
package com.mingliqiye.utils.json.converters
|
||||
|
||||
@FunctionalInterface
|
||||
public interface P8RFunction<P, P1, P2, P3, P4, P5, P6, P7, R> {
|
||||
R call(P p, P1 p1, P2 p2, P3 p3, P4 p4, P5 p5, P6 p6, P7 p7);
|
||||
interface JsonConverter<F, T> {
|
||||
fun convert(obj: F?): T?
|
||||
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
|
||||
* ModuleName mingli-utils.main
|
||||
* CurrentFile RandomBytes.kt
|
||||
* LastUpdate 2025-09-15 00:08:18
|
||||
* LastUpdate 2025-09-15 09:54:33
|
||||
* UpdateUser MingLiPro
|
||||
*/
|
||||
@file:JvmName("RandomBytes")
|
||||
|
||||
package com.mingliqiye.utils.random
|
||||
|
||||
import com.mingliqiye.utils.iterator.Range
|
||||
|
||||
/**
|
||||
* 生成指定长度的随机字节数组
|
||||
* @param length 数组长度
|
||||
@ -32,7 +30,9 @@ import com.mingliqiye.utils.iterator.Range
|
||||
*/
|
||||
fun randomBytes(length: Int): ByteArray {
|
||||
val bytes = ByteArray(length)
|
||||
Range(0, length - 1).forEach { i: Int -> bytes[i] = randomByte(0x00.toByte(), 0xff.toByte()) }
|
||||
for (i in 0..<length) {
|
||||
bytes[i] = randomByte(0x00.toByte(), 0xff.toByte())
|
||||
}
|
||||
return bytes
|
||||
}
|
||||
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
* ProjectName mingli-utils
|
||||
* ModuleName mingli-utils.main
|
||||
* CurrentFile GsonAutoConfiguration.kt
|
||||
* LastUpdate 2025-09-14 22:06:47
|
||||
* LastUpdate 2025-09-15 10:29:30
|
||||
* UpdateUser MingLiPro
|
||||
*/
|
||||
|
||||
@ -58,16 +58,16 @@ open class GsonAutoConfiguration {
|
||||
try {
|
||||
return gsonBuilder
|
||||
.registerTypeAdapter(
|
||||
uuidJsonStringConverter.getTClass(),
|
||||
dateTimeJsonConverter
|
||||
.getGsonJsonStringConverterAdapter()
|
||||
.getGsonTypeAdapter()
|
||||
uuidJsonStringConverter.tClass,
|
||||
uuidJsonStringConverter
|
||||
.gsonJsonStringConverterAdapter
|
||||
.gsonTypeAdapter
|
||||
)
|
||||
.registerTypeAdapter(
|
||||
dateTimeJsonConverter.getTClass(),
|
||||
dateTimeJsonConverter.tClass,
|
||||
dateTimeJsonConverter
|
||||
.getGsonJsonStringConverterAdapter()
|
||||
.getGsonTypeAdapter()
|
||||
.gsonJsonStringConverterAdapter
|
||||
.gsonTypeAdapter
|
||||
)
|
||||
} finally {
|
||||
log.info("MingliUtils GsonBuilder TypeAdapter add")
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
* ProjectName mingli-utils
|
||||
* ModuleName mingli-utils.main
|
||||
* CurrentFile JacksonAutoConfiguration.kt
|
||||
* LastUpdate 2025-09-14 22:10:08
|
||||
* LastUpdate 2025-09-15 10:29:02
|
||||
* UpdateUser MingLiPro
|
||||
*/
|
||||
|
||||
@ -49,12 +49,12 @@ open class JacksonAutoConfiguration(objectMapper: ObjectMapper) {
|
||||
.registerModule(
|
||||
DateTimeJsonConverter()
|
||||
.jacksonJsonStringConverterAdapter
|
||||
.getJacksonModule()
|
||||
.jacksonModule
|
||||
)
|
||||
.registerModule(
|
||||
UUIDJsonStringConverter()
|
||||
.jacksonJsonStringConverterAdapter
|
||||
.getJacksonModule()
|
||||
.jacksonModule
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@ -16,7 +16,7 @@
|
||||
* ProjectName mingli-utils
|
||||
* ModuleName mingli-utils.main
|
||||
* CurrentFile SystemUtil.kt
|
||||
* LastUpdate 2025-09-15 08:50:23
|
||||
* LastUpdate 2025-09-15 11:18:34
|
||||
* UpdateUser MingLiPro
|
||||
*/
|
||||
@file:JvmName("SystemUtils")
|
||||
@ -66,7 +66,7 @@ fun isUnix(): Boolean {
|
||||
*
|
||||
* @return JDK版本号字符串
|
||||
*/
|
||||
fun getJdkVersion(): String {
|
||||
fun getJdkVersion(): String? {
|
||||
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