The pit of Java SimpleDateFormat expression

Today is December 30, 2019. I logged into our online server and found that the log became "localhost_access_log.2020-12-30.log", which was a whole year away. All the monitoring graphs based on this log were scrapped, and I was panicked. I quickly debugged and found the SimpleDateFormat pit.
Let me talk about our environment first: springboot2.1.7 && built-in tomcat 9.0.22, and configured access log for tomcat, the specific configuration is as follows

server.tomcat.accesslog.enabled=true
server.tomcat.accesslog.pattern=********
server.tomcat.accesslog.prefix=localhost_access_log
server.tomcat.accesslog.suffix=.log
server.tomcat.accesslog.file-date-format=.YYYY-MM-dd
server.tomcat.accesslog.rotate=true
server.tomcat.accesslog.directory=logs
server.tomcat.basedir=./

Screenshot of the online log.
Insert picture description hereAccording to the log, debug tomcat all the way to initialize the application, and it turns out that the file in AccessLogValve

    @Override
    protected synchronized void startInternal() throws LifecycleException {

        // Initialize the Date formatters
        String format = getFileDateFormat();
        fileDateFormatter = new SimpleDateFormat(format, Locale.US);
        fileDateFormatter.setTimeZone(TimeZone.getDefault());
        dateStamp = fileDateFormatter.format(new Date(System.currentTimeMillis())); // **出问题的地方**
        if (rotatable && renameOnRotate) {
            restore();
        }
        open();

        super.startInternal();
    }

Then manually wrote the test class, the problem reappeared

public static void main(String[] args) {
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYYY-MM-dd", Locale.US);
        long time = System.currentTimeMillis();
        time = 1577601170000l; // 2019-12-29 14:32:50
        String dateStamp = simpleDateFormat.format(new Date(time));
        System.out.println(dateStamp);
    }

Insert picture description hereLater, I looked at the jdk official website and found that there was a problem
Insert picture description herewith the time formatting expression . There are two Year and Week years in the figure above. Year is the year on the normal calendar, the latter refers to the official document . Simply put, December 30, 2019 is exactly the first day of the first week of the 2020 Week-year. So the result of "YYYY" is 2019.
After modifying the code, SimpleDateFormat df = new SimpleDateFormat(".yyyy.MM.dd");, you can get the correct result,
similar to "D" and "d". Therefore, "y" and "d" should be used in most cases.
As follows:

public static void main(String[] args) {
//        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("YYYY-MM-dd", Locale.US);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd", Locale.US);
        long time = System.currentTimeMillis();
        time = 1577601170000l; // 2019-12-29 14:32:50
        String dateStamp = simpleDateFormat.format(new Date(time));
        System.out.println(dateStamp);
    }

Insert picture description hereThis detail is usually not paid attention to. Fortunately, it only appears on the log name today, otherwise the impact cannot be assessed.

Guess you like

Origin blog.csdn.net/jerry_player/article/details/103766677