16

When I insert a SQL DateTime to the database I get 2007-02-07 12:00:00.00

But I made the Date object like this : 2007-02-07 17:29:46.00

How to get the value of the seconds in the database. It always changes it back to 12:00:00.00

date.setYear(Integer.valueOf(parsedDate[2].replaceAll(" ", "")) - 1900);
date.setMonth(Integer.valueOf(parsedDate[0].replaceAll(" ", "")));
date.setDate(Integer.valueOf(parsedDate[1].replaceAll(" ", "")));
...
java.sql.Date sqlDate = new java.sql.Date(date.getTime());

Should I use any formatters?

Ry-
  • 218,210
  • 55
  • 464
  • 476
Elbek
  • 3,434
  • 6
  • 37
  • 49
  • 1
    A "Date" (a number representing some point in time) is INDEPENDENT of it's format (the *same* number can be represented as "2007-02-07" or "2007-07-02" or "2/7/2007". It's also independent of your time zone (the same number can be "2/7/2007" in Los Angeles, and "2/8/2007" in London). Finally a "date" (e.g. "2/7/2007") has a different value than a datetime (e.g. "2/7/2007 09:15am"). My guess is that you're probably using "date", where you mean to use "datetime". – paulsm4 Dec 16 '11 at 06:34
  • PS: java.util.date means either "date" or "datetime". java.sql.date is only "date". And for databases like MS Sql Server, "date" or "datetime" is DIFFERENT from "timestamp". http://stackoverflow.com/questions/2305973/java-util-date-vs-java-sql-date – paulsm4 Dec 16 '11 at 06:50
  • PPS: In MS Sql Server (if that's what you're using), a "timestamp" is emphatically NOT a date or datetime: http://www.sqlteam.com/article/timestamps-vs-datetime-data-types. If you want a date (irrespective of time of day), make your SQL column "date". If you want time of day (irrespective of calendar date), make it "time". Under NO CIRCUMSTANCES use a SQL Server "timestamp" to hold logical time/date columns. – paulsm4 Dec 16 '11 at 06:51
  • then i can not save date and time in the same column as i mentioned above 2007-02-07 17:29:46.00? must i separate them into two columns? By the way i am using ms sql server – Elbek Dec 16 '11 at 06:59
  • Noooooo! It means if you want to save "2007-02-07 17:29", then you should define the column in MSSQL as "datetime". If you want to save only "2007-02-07", then you should define the column as MSSQL "date". Java's "java.sql.Date" is date-only. Java's "java.util.Date" does both date and date/time. And MSSQL "timestamp" is NEITHER date nor time - avoid MSSQL timestamp unless you KNOW you need it. Q: Are you using MS Sql Server? Or are you using a different database (e.g. DB2 or MySQL)? – paulsm4 Dec 16 '11 at 16:27
  • I am using ms sql. I did it wich a bit difficult way. I make stored procedure with takes param also date as string then converts it and inserts. Bad way. lool – Elbek Dec 17 '11 at 09:05
  • However i can not use java.util.Date with ps.setDate(). – Elbek Dec 17 '11 at 09:50

2 Answers2

31

java.sql.Date represents a date, not a date and time. From the docs:

To conform with the definition of SQL DATE, the millisecond values wrapped by a java.sql.Date instance must be 'normalized' by setting the hours, minutes, seconds, and milliseconds to zero in the particular time zone with which the instance is associated.

If you want to store a date and time, you should look for another type - e.g. java.sql.Timestamp. EDIT: That's not suggesting you use a TIMESTAMP column type - as paulsm4 says in the comments, that's a different thing. However, as far as I can see, JDBC only supports:

  • Date (no, you want a time too)
  • Time (no, you want a date too)
  • Timestamp (includes a date and time, but you don't want TIMESTAMP SQL semantics)

I would expect using the Java Timestamp type with a DATETIME column to work, although without the level of precision that Timestamp provides.

EDIT: After a bit more research, it looks like you may want to use the java.sql.Time type, but with special driver parameters - at least if you're using the Microsoft driver. See these docs on configuring JDBC for more information.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • then how to reach to this date? Is there any other option? – Elbek Dec 16 '11 at 06:29
  • @elbek: See my edit - basically, don't use `Date` here, use a different type. – Jon Skeet Dec 16 '11 at 06:30
  • if i do the column type timestamp i can not change it manually? – Elbek Dec 16 '11 at 06:46
  • when i do with timestamp i got this error: Cannot insert an explicit value into a timestamp column. Use INSERT with a column list to exclude the timestamp column, or insert a DEFAULT into the timestamp column. – Elbek Dec 16 '11 at 06:47
  • @elbek: You should try using a DATETIME column, but java.sql.Timestamp as the Java type. – Jon Skeet Dec 16 '11 at 07:02
  • @elbek: You've got to start being more precise. Whenever you get an error, tell us what that error is. – Jon Skeet Dec 16 '11 at 07:04
  • @elbek: If it's talking about a TIMESTAMP column, then you clearly *haven't* followed my suggestion of using a DATETIME column instead. – Jon Skeet Dec 16 '11 at 07:09
  • @elbek: No, chat doesn't work well for my workflow I'm afraid. – Jon Skeet Dec 16 '11 at 07:09
  • Yeah i am using date time in db and even i can create the value like that: 12/16/2011 9:12:00 PM in db, But my problem is i can not create this value through the jdbc using preparedStatements – Elbek Dec 16 '11 at 07:11
  • @elbek: See my latest edit, which should give you some more information - although it's specific to the MS JDBC driver. Which driver are you using? – Jon Skeet Dec 16 '11 at 07:16
  • i downloaded it from site of microsfot: com/microsoft/sqlserver/jdbc – Elbek Dec 16 '11 at 07:18
  • @elbek: So if you're using the Microsoft JDBC driver, you should be able to use `Time` as described in the link near the bottom of my answer. You shouldn't have to resort to using strings. – Jon Skeet Dec 16 '11 at 07:59
  • 1
    @elbek: "The JDBC driver has been designed specifically to use features introduced with SQL Server 2005, but it is backward-compatible with SQL Server 2000, including the 64-bit version. JDBC Driver 3.0 supports the new date and time types, large user-defined types, and sparse columns in SQL Server 2008." (From the System Requirements for the 3.0 drivers.) – Jon Skeet Dec 16 '11 at 08:24
  • Modern comment: JDBC 4.2 supports `java.time` types, for example with the `PreparedStatement.setObject` method and the `ResultSet.getObject` method. We no longer need to use the old `java.sql` types, but may use `Instant`, `LocalDate`, `LocalTime`, `LocalDateTime` and friends. – Ole V.V. May 24 '18 at 14:38
3

tl;dr

You are likely confused by not understanding that java.util.Date is a date-with-time type while its subclass java.sql.Date pretends to be a date-only class but actually has its time-of-day set to zero. Bloody awful design. Avoid both these classes entirely. Use java.time classes only.

For a date-only column in your database, define the column as the SQL-standard DATE type.

myPreparedStatement.setObject(
    … ,
    LocalDateTime.parse( "2007-02-07 17:29:46.00".replace( " " , "T" ) )
    .toLocalDate()
)

java.time

The modern approach uses the java.time classes added to Java 8 and later.

When I insert a SQL DateTime to the database I get 2007-02-07 12:00:00.00

There is no such thing as a SQL-standard type as DateTime, nor any such class in Java. So I do not know your intention there.

As for the input string, 2007-02-07 17:29:46.00, parse that as a LocalDateTime because it lacks any indicator of time zone or offset-from-UTC.

That SQL-style format almost complies with the ISO 8601 standard. To fully comply, replace the SPACE in the middle with a T. The java.time classes use the ISO 8601 formats by default when parsing/generating strings.

String input = "2007-02-07 17:29:46.00".replace( " " , "T" ) ;

Parse.

LocalDateTime ldt = LocalDateTime.parse( input ) ;

A LocalDateTime does not represent a moment, is not a point on the timeline. It represents potential moments along a range of about 26-27 hours.

Standard SQL does offer a data type for such a value, TIMESTAMP WITHOUT TIME ZONE.

Smart objects, not dumb strings

Your entire approach is misguided, wrangling text and using the legacy date-time classes. Instead, exchange java.time objects.

As of JDBC 4.2, you need not ever use the troublesome old java.sql types such as java.sql.Date or java.sql.Timestamp. You can directly exchange java.time objects with your database via setObject/getObject methods.

myPreparedStatement.setObject( … , ldt ) ;

And retrieval.

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

If you are trying to work with date-only values, use the SQL-standard type DATE and the Java class LocalDate.

LocalDate ld = ldt.toLocalDate() ;
myPreparedStatement.setObject( … , ld ) ;

How to get the value of the seconds in the database

Not sure what you mean by "value of the seconds".

Perhaps you want a count of seconds from the epoch reference of first moment of 1970 in UTC.

long secondsSinceEpoch = ldt.toEpochSecond() ;

If your goal was merely to instantiate a java.sql.Date, don’t bother. Never use that class again. But, FYI, your specific issue is likely a side-effect of the awful design used for that class. The java.sql.Date class inherits from java.util.Date which is a date-with-time type. The java.sql.Date class pretends to be a date-only value, but actually has its time-of-day set to 00:00:00. Even worse, the documentation tells us to ignore the fact of its being a subclass. Don’t bother trying to understand it; just use java.time instead.

If you are trying to work with the time-of-day alone, extract a LocalTime object.

LocalTime lt = ldt.toLocalTime() ;

If you want to set the time-of-day to zeros, then you likely want a date-only value. If so, use the LocalDate class for a date value without a time-of-day and without a time zone.

LocalDate ld = ldt.toLocalDate() :

If you do want the first moment of the day on that date, call LocalDate::atStartOfDay.

LocalDateTime ldtStart = ldt.toLocalDate().atStartOfDay() ;

BEWARE: If you are trying to track actual moments, specific points on the timeline, then all this code above is wrong. Search Stack Overflow to learn about Instant, ZoneId, and ZonedDateTime classes. Search both Stack Overflow and dba.StackExchange.com to learn about the SQL-standard type TIMESTAMP WITH TIME ZONE.


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.

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

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.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
  • Re: the Joda recommendation to migrate to `java.time`, here is a quote from their page as of today: **"Note that from Java SE 8 onwards, users are asked to migrate to java.time (JSR-310) - a core part of the JDK which replaces this project."** – Danny Bullis May 31 '18 at 16:53