Unexplained zero added when going from java.util.Date to java.sql.Timestamp

折月煮酒 提交于 2019-12-11 04:59:44

问题


Consider the following test code (Try it here yourself on ideone.com - an online Java compiler):

class Main {
    public static void main (String[] args) throws Exception {
        Main m = new Main();
        m.test1();
        System.out.println();
        m.test2();
    }

    void test1() throws Exception {
        System.out.println("TEST 1: ");

        String strTimestamp = "1957-04-27 00:00:00.01";
        System.out.println(strTimestamp + " [Original String]");

        String format = "yyyy-MM-dd HH:mm:ss.SS";
        System.out.println(format + " [Format used]");
        java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat(format);

        // Convert String to Date:
        java.util.Date date = formatter.parse(strTimestamp);
        long time = date.getTime();
        System.out.println(formatter.format(time) + " [Date#getTime() with same format]");

        java.sql.Timestamp timestamp = new java.sql.Timestamp(time);
        System.out.println(timestamp + " [Timestamp]");
    }

    void test2() throws Exception {
        System.out.println("TEST 2: ");

        String strTimestamp = "1957-04-27 00:00:00.001";
        System.out.println(strTimestamp + " [Original String]");

        String format = "yyyy-MM-dd HH:mm:ss.SSS";
        System.out.println(format + " [Format used]");
        java.text.SimpleDateFormat formatter = new java.text.SimpleDateFormat(format);

        // Convert String to Date:
        java.util.Date date = formatter.parse(strTimestamp);
        long time = date.getTime();
        System.out.println(formatter.format(time) + " [Date#getTime() with same format]");

        java.sql.Timestamp timestamp = new java.sql.Timestamp(time);
        System.out.println(timestamp + " [Timestamp]");
    }
}

The code above gives the following output:

TEST 1: 
1957-04-27 00:00:00.01 [Original String]
yyyy-MM-dd HH:mm:ss.SS [Format used]
1957-04-27 00:00:00.01 [Date#getTime() with same format]
1957-04-27 00:00:00.001 [Timestamp]

TEST 2: 
1957-04-27 00:00:00.001 [Original String]
yyyy-MM-dd HH:mm:ss.SSS [Format used]
1957-04-27 00:00:00.001 [Date#getTime() with same format]
1957-04-27 00:00:00.001 [Timestamp]

In TEST 1 I was expecting the [Original String], [Date#getTime() with same format] AND [Timestamp] to all have the same output just like at TEST 2.

Why does the [Timestamp] in TEST 1 have an extra zero compared to the Date?


回答1:


tl;dr

Your old code and Question are now moot. Use java.time classes instead.

LocalDateTime.parse( 
    "1957-04-27 00:00:00.01".replace( " " , "T" ) 
).toString()

java.time

The troublesome java.util.Date and java.sql.Timestamp classes you are using are now legacy, supplanted by the java.time classes.

Your input string is close to standard ISO 8601 format. Comply by replacing the SPACE in the middle with a T. The java.time classes use ISO 8601 formats by default when parsing/generating strings.

String input = "1957-04-27 00:00:00.01".replace( " " , "T" ) ;

Parse as a LocalDateTime object given that your input lacks any indicator of time zone or offset-from-UTC.

LocalDateTime ldt = LocalDateTime.parse( input ) ;

To generate a string in ISO 8601 format, simply call toString(). The default formatter uses 0-3 groups of three digits as needed to display the fractional second, up to the nine digits of decimal fraction for nanoseconds.

String output = ldt.toString() ;

1957-04-27T00:00:00.010

You can exchange your LocalDateTime object directly with your database column of type TIMESTAMP WITHOUT TIME ZONE using JDBC 4.2 and later.

myPreparedStatement.setObject( … , ldt ) ;

And retrieval.

LocalDateTime ldt = myResultSet.getObject( … , LocalDateTime.class ) ;

About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.

To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.

Where to obtain the java.time classes?

  • Java SE 8, Java SE 9, and later
    • Built-in.
    • Part of the standard Java API with a bundled implementation.
    • Java 9 adds some minor features and fixes.
  • Java SE 6 and Java SE 7
    • Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
  • Android
    • Later versions of Android bundle implementations of the java.time classes.
    • For earlier Android, the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.




回答2:


You're forgetting to format the timestamp values when printing them in both of your test methods - the fact that your first test succeeds at all is just a coincidence.

Change:

System.out.println(timestamp + " [Timestamp]");

To:

System.out.println(formatter.format(timestamp) + " [Timestamp]");

And you should get the result you expect.



来源:https://stackoverflow.com/questions/42372261/unexplained-zero-added-when-going-from-java-util-date-to-java-sql-timestamp

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!