Java simpledateformat.parse 给出的年份不正确
Java simpledateformat.parse is giving incorrect year
我试图从字符串中解析日期,然后保存到数据库中,但是有时在检查数据库时,年份值是错误的。
private SimpleDateFormat simpleDateFormatTimestampJPOS = new SimpleDateFormat("yyyyMMddHHmmssSSS");
private Date findTxnDate() throws ParseException
{
Date date;
String timeStamp = "20181115040613555";
date = simpleDateFormatTimestampJPOS.parse(timeStamp);
return date;
}
我不知道发生了什么,这是来自 SimpleDateFormat、服务器等的问题。有人可以帮助我吗?
1018 and what i expected is 2018
fyi java 服务器上的版本
java version "1.8.0_111"
Java(TM) SE Runtime Environment (build 1.8.0_111-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode)
SimpleDateFormat 是线程不安全的,如果在多个线程中使用同一个实例,可能会导致此类错误。
每次都使用新实例或一些线程安全的替代方法(例如 FastDateFormat)
我不知道这是不是你失败的原因,但如果是存储在数据库中,存储时间的数据类型是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
如果您在多线程场景中使用您的代码,您可能会得到错误的结果,因为 SimpleDateFormat
不是线程安全的 class。如果您使用 Java8+,请改用 DateTimeFormatter
。这是验证 SimpleDateFormat
不是线程安全的 class 的测试代码,希望对您有所帮助。
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();
}
}
}
我试图从字符串中解析日期,然后保存到数据库中,但是有时在检查数据库时,年份值是错误的。
private SimpleDateFormat simpleDateFormatTimestampJPOS = new SimpleDateFormat("yyyyMMddHHmmssSSS");
private Date findTxnDate() throws ParseException
{
Date date;
String timeStamp = "20181115040613555";
date = simpleDateFormatTimestampJPOS.parse(timeStamp);
return date;
}
我不知道发生了什么,这是来自 SimpleDateFormat、服务器等的问题。有人可以帮助我吗?
1018 and what i expected is 2018
fyi java 服务器上的版本
java version "1.8.0_111"
Java(TM) SE Runtime Environment (build 1.8.0_111-b14)
Java HotSpot(TM) 64-Bit Server VM (build 25.111-b14, mixed mode)
SimpleDateFormat 是线程不安全的,如果在多个线程中使用同一个实例,可能会导致此类错误。
每次都使用新实例或一些线程安全的替代方法(例如 FastDateFormat)
我不知道这是不是你失败的原因,但如果是存储在数据库中,存储时间的数据类型是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
如果您在多线程场景中使用您的代码,您可能会得到错误的结果,因为 SimpleDateFormat
不是线程安全的 class。如果您使用 Java8+,请改用 DateTimeFormatter
。这是验证 SimpleDateFormat
不是线程安全的 class 的测试代码,希望对您有所帮助。
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();
}
}
}