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();
        }
    }
}