This is an automated email from the ASF dual-hosted git repository.
imbajin pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/hugegraph-toolchain.git
The following commit(s) were added to refs/heads/master by this push:
new bf8a46a0 fix(loader): enhance DateUtil with concurrent date parsing
(#734)
bf8a46a0 is described below
commit bf8a46a064c65943b7b7e5ca4752148ff6a5b7e7
Author: Jason <[email protected]>
AuthorDate: Wed May 6 19:51:57 2026 +0800
fix(loader): enhance DateUtil with concurrent date parsing (#734)
---------
Signed-off-by: Jason <[email protected]>
---
.../org/apache/hugegraph/loader/util/DateUtil.java | 19 ++++----
.../hugegraph/loader/test/unit/DateUtilTest.java | 54 ++++++++++++++++++++++
2 files changed, 63 insertions(+), 10 deletions(-)
diff --git
a/hugegraph-loader/src/main/java/org/apache/hugegraph/loader/util/DateUtil.java
b/hugegraph-loader/src/main/java/org/apache/hugegraph/loader/util/DateUtil.java
index 670c70a0..caeada15 100644
---
a/hugegraph-loader/src/main/java/org/apache/hugegraph/loader/util/DateUtil.java
+++
b/hugegraph-loader/src/main/java/org/apache/hugegraph/loader/util/DateUtil.java
@@ -18,16 +18,16 @@
package org.apache.hugegraph.loader.util;
import java.util.Date;
-import java.util.Map;
+import java.util.HashMap;
import java.util.TimeZone;
-import java.util.concurrent.ConcurrentHashMap;
import org.apache.hugegraph.date.SafeDateFormat;
import org.apache.hugegraph.loader.constant.Constants;
public final class DateUtil {
- private static final Map<String, SafeDateFormat> DATE_FORMATS = new
ConcurrentHashMap<>();
+ private static final ThreadLocal<HashMap<String, SafeDateFormat>>
DATE_FORMATS =
+ ThreadLocal.withInitial(HashMap::new);
public static Date parse(String source, String df) {
return parse(source, df, Constants.TIME_ZONE);
@@ -35,19 +35,16 @@ public final class DateUtil {
public static Date parse(String source, String df, String timeZone) {
SafeDateFormat dateFormat = getDateFormat(df);
- // parse date with specified timezone
dateFormat.setTimeZone(timeZone);
return dateFormat.parse(source);
}
private static SafeDateFormat getDateFormat(String df) {
- SafeDateFormat dateFormat = DATE_FORMATS.get(df);
+ HashMap<String, SafeDateFormat> formats = DATE_FORMATS.get();
+ SafeDateFormat dateFormat = formats.get(df);
if (dateFormat == null) {
dateFormat = new SafeDateFormat(df);
- SafeDateFormat previous = DATE_FORMATS.putIfAbsent(df, dateFormat);
- if (previous != null) {
- dateFormat = previous;
- }
+ formats.put(df, dateFormat);
}
return dateFormat;
}
@@ -58,7 +55,9 @@ public final class DateUtil {
}
public static String now(String df) {
- return getDateFormat(df).format(new Date());
+ SafeDateFormat dateFormat = getDateFormat(df);
+ dateFormat.setTimeZone(Constants.TIME_ZONE);
+ return dateFormat.format(new Date());
}
public static boolean checkTimeZone(String timeZone) {
diff --git
a/hugegraph-loader/src/test/java/org/apache/hugegraph/loader/test/unit/DateUtilTest.java
b/hugegraph-loader/src/test/java/org/apache/hugegraph/loader/test/unit/DateUtilTest.java
index 6370c897..08d2ab2a 100644
---
a/hugegraph-loader/src/test/java/org/apache/hugegraph/loader/test/unit/DateUtilTest.java
+++
b/hugegraph-loader/src/test/java/org/apache/hugegraph/loader/test/unit/DateUtilTest.java
@@ -17,6 +17,12 @@
package org.apache.hugegraph.loader.test.unit;
+import java.util.Date;
+import java.util.concurrent.CountDownLatch;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
+import java.util.concurrent.atomic.AtomicInteger;
+
import org.apache.hugegraph.loader.util.DateUtil;
import org.junit.Test;
@@ -24,6 +30,13 @@ import org.apache.hugegraph.testutil.Assert;
public class DateUtilTest {
+ @Test
+ public void testNowUsesDefaultTimeZone() {
+ String pattern = "Z";
+ DateUtil.parse("+0000", pattern, "GMT");
+ Assert.assertEquals("+0800", DateUtil.now(pattern));
+ }
+
@Test
public void testCheckTimeZone() {
Assert.assertTrue(DateUtil.checkTimeZone("JST"));
@@ -70,4 +83,45 @@ public class DateUtilTest {
// minutes 00-59 only
Assert.assertFalse(DateUtil.checkTimeZone("GMT+13:60"));
}
+
+ @Test
+ public void testConcurrentParseDateWithDifferentTimeZones() throws
InterruptedException {
+ int threads = 10;
+ int iterations = 100;
+ ExecutorService executor = Executors.newFixedThreadPool(threads);
+ CountDownLatch latch = new CountDownLatch(threads);
+ AtomicInteger errors = new AtomicInteger(0);
+
+ String dateStr = "2024-01-15 12:00:00";
+ String pattern = "yyyy-MM-dd HH:mm:ss";
+ long expectedEpochGMT8 = DateUtil.parse(dateStr, pattern,
"GMT+8").getTime();
+ long expectedEpochGMT0 = DateUtil.parse(dateStr, pattern,
"GMT+0").getTime();
+ long expectedDiff = 8 * 60 * 60 * 1000;
+
+ for (int i = 0; i < threads; i++) {
+ final int threadId = i;
+ executor.submit(() -> {
+ try {
+ String timeZone = threadId % 2 == 0 ? "GMT+8" : "GMT+0";
+ long expectedEpoch = threadId % 2 == 0 ? expectedEpochGMT8
: expectedEpochGMT0;
+ for (int j = 0; j < iterations; j++) {
+ Date result = DateUtil.parse(dateStr, pattern,
timeZone);
+ if (result == null || result.getTime() !=
expectedEpoch) {
+ errors.incrementAndGet();
+ }
+ }
+ } catch (Exception e) {
+ errors.incrementAndGet();
+ } finally {
+ latch.countDown();
+ }
+ });
+ }
+
+ latch.await();
+ executor.shutdown();
+
+ Assert.assertEquals(0, errors.get());
+ Assert.assertEquals(expectedDiff, expectedEpochGMT0 -
expectedEpochGMT8);
+ }
}