我正在尝试从字符串中解析日期,然后将其保存到数据库,但是有时有时在检查数据库时年份值错误。
private SimpleDateFormat simpleDateFormatTimestampJPOS = new SimpleDateFormat("yyyyMMddHHmmssSSS");
private Date findTxnDate() throws ParseException
{
Date date;
String timeStamp = "20181115040613555";
date = simpleDateFormatTimestampJPOS.parse(timeStamp);
return date;
}
我不知道会发生什么,这是SimpleDateFormat,服务器等的问题。有人可以帮助我吗?
1018,我期望的是2018
服务器上的fyi Java版本
java版本“ 1.8.0_111”
Java(TM)SE运行时环境(内部版本1.8.0_111-b14)
Java HotSpot(TM)64位服务器VM(内部版本25.111-b14,混合模式)
答案 0 :(得分:2)
SimpleDateFormat是线程不安全的,如果在多个线程中使用同一实例,则可能导致此类错误。
每次使用新实例,或使用一些线程安全的替代方法(例如FastDateFormat)
答案 1 :(得分:1)
我不知道这是否是您失败的原因,但如果是用于存储在数据库中,则用于存储时间的数据类型为TimeStamp
,而不是Date
。
您提供的代码片段是以前在Java早期版本中使用的方式,正如其他人已经提到的那样,SimpleDateFormat不是线程安全的。
我也可以向您介绍另一种实现相同目标的方法,它使用来自线程安全的java.time
包中的新的且对程序员更友好的类:
LocalDateTime newDate = null;
String dateTime = "20181115040613555";
DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyyMMddHHmmssSSS", Locale.ENGLISH);
try {
newDate = LocalDateTime.parse(dateTime, dtf);
} catch (DateTimeParseException e) {
throw new InvalidInputException("Invalid date input.");
}
更多信息可以在这里找到:https://docs.oracle.com/javase/8/docs/api/java/time/format/DateTimeFormatter.html
答案 2 :(得分:0)
如果在多线程方案中使用代码,则可能会得到错误的结果,因为SimpleDateFormat
不是线程安全的类。如果您使用Java8 +,请改用DateTimeFormatter
。这是一个测试代码,用于验证SimpleDateFormat
不是线程安全的类,希望对您有所帮助。
public class MultiThreadSimpleDateFormatClient {
public static void main(String[] args) {
HandleDate handleDate = new HandleDate();
Random random = new Random();
Set<String> randomStrs = new HashSet<>();
Thread thread1 = new Thread(() -> {
while (true) {
int partOfYear = random.nextInt(10);
handleDate.verifyNotThreadSafe("201" + partOfYear + "1115040613555");
}
});
Thread thread2 = new Thread(() -> {
while (true) {
int partOfYear = random.nextInt(10);
handleDate.verifyNotThreadSafe("201" + partOfYear + "1115040613555");
}
});
Thread thread3 = new Thread(() -> {
while (true) {
int partOfYear = random.nextInt(10);
handleDate.verifyNotThreadSafe("201" + partOfYear + "1115040613555");
}
});
Thread thread4 = new Thread(() -> {
while (true) {
int partOfYear = random.nextInt(10);
handleDate.verifyNotThreadSafe("201" + partOfYear + "1115040613555");
}
});
Thread thread5 = new Thread(() -> {
while (true) {
int partOfYear = random.nextInt(10);
handleDate.verifyNotThreadSafe("201" + partOfYear + "1115040613555");
}
});
Thread thread6 = new Thread(() -> {
while (true) {
int partOfYear = random.nextInt(10);
handleDate.verifyNotThreadSafe("201" + partOfYear + "1115040613555");
}
});
Thread thread7 = new Thread(() -> {
while (true) {
int partOfYear = random.nextInt(10);
handleDate.verifyNotThreadSafe("201" + partOfYear + "1115040613555");
}
});
Thread thread8 = new Thread(() -> {
while (true) {
int partOfYear = random.nextInt(10);
handleDate.verifyNotThreadSafe("201" + partOfYear + "1115040613555");
}
});
Thread thread9 = new Thread(() -> {
while (true) {
int partOfYear = random.nextInt(10);
handleDate.verifyNotThreadSafe("201" + partOfYear + "1115040613555");
}
});
Thread thread10 = new Thread(() -> {
while (true) {
int partOfYear = random.nextInt(10);
handleDate.verifyNotThreadSafe("201" + partOfYear + "1115040613555");
}
});
thread1.start();
thread2.start();
thread3.start();
thread4.start();
thread5.start();
thread6.start();
thread7.start();
thread8.start();
thread9.start();
thread10.start();
}
}
public class HandleDate {
// this is not thread safe
private SimpleDateFormat simpleDateFormatTimestampJPOS = new SimpleDateFormat("yyyyMMddHHmmssSSS");
public void verifyNotThreadSafe(String timeStamp) {
try {
// this is thread safe
//SimpleDateFormat simpleDateFormatTimestampJPOS = new SimpleDateFormat("yyyyMMddHHmmssSSS");
Date date = simpleDateFormatTimestampJPOS.parse(timeStamp);
LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
String expectedYear = timeStamp.substring(0, 4);
String actualYear = String.valueOf(localDateTime.getYear());
if (!expectedYear.equals(actualYear)) {
System.out.println("expected:" + expectedYear + ", but real:" + actualYear);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}