Skip to content

Commit 7d1692c

Browse files
committed
feat:Add reflection-based handling for java.sql.Timestamp to avoid module dependency
- Introduce static reflection initialization for Timestamp class/method - Use isTimestamp() to check instance type without direct dependency - Extract nanoseconds via reflection in extractNanosFromSqlTimestamp() - Gracefully handle absence of java.sql module with null checks and exception handling - Maintain existing functionality for converting Timestamps to LocalDateTime with nanosecond precision - Ensure compatibility with both modular (JPMS) and non-modular environments - Remove unused Instant import in test class for cleaner imports Signed-off-by: finger <finger.xie@foxmail.com>
1 parent f7928be commit 7d1692c

File tree

2 files changed

+52
-4
lines changed

2 files changed

+52
-4
lines changed

src/main/java/org/apache/commons/lang3/time/DateUtils.java

Lines changed: 52 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,8 @@
1616
*/
1717
package org.apache.commons.lang3.time;
1818

19-
import java.sql.Timestamp;
19+
import java.lang.reflect.InvocationTargetException;
20+
import java.lang.reflect.Method;
2021
import java.text.ParseException;
2122
import java.text.ParsePosition;
2223
import java.time.Instant;
@@ -205,6 +206,28 @@ private enum ModifyType {
205206
* A month range, the week starting on Monday.
206207
*/
207208
public static final int RANGE_MONTH_MONDAY = 6;
209+
/**
210+
* The {@link Class} for {@link java.sql.Timestamp}.
211+
*/
212+
private static final Class<?> timestampClass;
213+
/**
214+
* The {@link Method} for {@link java.sql.Timestamp#getNanos()}.
215+
*/
216+
private static final Method timestampGetNanosMethod;
217+
218+
static {
219+
Class<?> clazz;
220+
Method method;
221+
try {
222+
clazz = Class.forName("java.sql.Timestamp");
223+
method = clazz.getMethod("getNanos");
224+
} catch (ClassNotFoundException | NoSuchMethodException ex) {
225+
clazz = null;
226+
method = null;
227+
}
228+
timestampClass = clazz;
229+
timestampGetNanosMethod = method;
230+
}
208231

209232
/**
210233
* Adds to a date returning a new object.
@@ -1651,12 +1674,38 @@ public static LocalDateTime toLocalDateTime(final Date date, final TimeZone tz)
16511674
Objects.requireNonNull(date, "date");
16521675
Objects.requireNonNull(tz, "tz");
16531676
final LocalDateTime localDateTime = LocalDateTime.ofInstant(Instant.ofEpochMilli(date.getTime()), tz.toZoneId());
1654-
if (date instanceof java.sql.Timestamp) {
1655-
return localDateTime.withNano(((Timestamp) date).getNanos());
1677+
if (isTimestamp(date)) {
1678+
return localDateTime.withNano(extractNanosFromSqlTimestamp(date));
16561679
}
16571680
return localDateTime;
16581681
}
16591682

1683+
/**
1684+
* Get the nanosecond part in the {@link java.sql.Timestamp} object. without requiring the java.sql module.
1685+
*
1686+
* @param date The date is a {@link java.sql.Timestamp} object.
1687+
* If it is not a {@link java.sql.Timestamp} object,
1688+
* it will return 0.
1689+
* @return The nanosecond part of the {@link java.sql.Timestamp} object.
1690+
*/
1691+
private static int extractNanosFromSqlTimestamp(Date date){
1692+
if (timestampClass==null){
1693+
return 0;
1694+
}
1695+
try {
1696+
return (int)timestampGetNanosMethod.invoke(date);
1697+
} catch (IllegalAccessException | InvocationTargetException e) {
1698+
return 0;
1699+
}
1700+
}
1701+
1702+
/**
1703+
* Check to see if obj is an instance of {@link java.sql.Timestamp} without requiring the java.sql module.
1704+
*/
1705+
private static boolean isTimestamp(final Date date) {
1706+
return timestampClass != null && timestampClass.isAssignableFrom(date.getClass());
1707+
}
1708+
16601709
/**
16611710
* Truncates a date, leaving the field specified as the most
16621711
* significant field.

src/test/java/org/apache/commons/lang3/time/DateUtilsTest.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,6 @@
2828
import java.text.DateFormat;
2929
import java.text.ParseException;
3030
import java.text.SimpleDateFormat;
31-
import java.time.Instant;
3231
import java.time.LocalDateTime;
3332
import java.time.ZoneOffset;
3433
import java.util.Calendar;

0 commit comments

Comments
 (0)