Date.toString() - sql vs util dates - java

I need to remove time from a Date Object. Here is my try,
Code:
System.out.println("date " + dbDate);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
System.out.println("formatter.format(dbDate) " + formatter.format(dbDate));
System.out.println("final " + formatter.parse(formatter.format(dbDate)));
Output:
date 2011-12-03 23:59:59.0
formatter.format(dbDate) 2011-12-03
final Sat Dec 03 00:00:00 IST 2011
I want to the final date to display in 2011-12-03. But after conversion toString() of that Date is in different format. I am missing something. Please help.
Update:
In my application, I have two different methods to get dbDate. EXPIRY_DATE column is type of DATE.
First query uses dbDate = (java.util.Date) rs.getDate("EXPIRY_DATE");.
For this dbDate, System.out.println("date " + dbDate); gives date 2011-12-03
Second query uses dbDate = rs.getTimestamp("EXPIRY_DATE");
For this dbDate, System.out.println("date " + dbDate); gives date 2011-12-03 23:59:59.0.
This is my problem. As I thought toString() was giving problem, I didn't mention the full problem.
Solution:
I did not have choices to avoid java.sql.Date as my application methods have multiple usages.
I tried the below and worked,
dbDate = new java.sql.Date(dbDate.getTime());

I need to remove time from a Date Object
You can't. The java.util.Date object contains both the date and time. Its toString() is also in a fixed format. If you want to represent it without time to humans, then you need to convert it to a String like as you already did. Or, if you intend to store it in the DB without the time (as the db part in the variable name dbDate suggests), then you need to convert it to java.sql.Date.
preparedStatement.setDate(1, new java.sql.Date(dbDate.getTime()));
// ...
Update as per your update, the ResultSet#getDate() returns an instance of java.sql.Date, not java.util.Date (but it is a subclass of java.util.Date, that's why the unnecessary cast worked; please note that casting is not the same as converting, a real conversion would be new java.util.Date(dbDate.getTime())). As you can read in the javadoc of the toString() method of java.sql.Date, it's indeed in yyyy-MM-dd format.
So, your concrete problem is that you're confusing java.sql.Date with java.util.Date and that you're misgrasping the internal workings of java.util.Date and been mislead by the toString() method. Everything is working as intented.
Related:
Handling MySQL datetimes and timestamps in Java

If what you want to do is remove the time part of the Date object:
Use a Calendar to remove the time part of your Date object. As pointed out in this question: Java Date cut off time information.
If you only want to obtain a String representation without the time part of the Date object:
You've got to use SimpleDateFormat.format(). You can't make Date.toString() return a different value, it will always use that pattern. Look at its source code.

When you last call formatter.parse() you get back a Date object; the concatenation then makes an implicit call to Date.toString(): the format returned by this call is the default for the locale set in the JVM.
What you must understand is that the Date object has no knowledge of the string representation, internally it's just an aggregate of inte

I have encountered similar problem for those who encounters the same problem as mine I write this entry:
The problem is the date value that is taken from database and passed to the web client is in format yyyy-mm-dd but in the application for the first entry there is not database value so we create date object and passed the value to web client which gives us timestamp value. The value that will be passed to web client must be in date format so SimpleDateFormat is not a good choice for me
So from this post ı understand the difference of java.sql.date and java.util.date and then create first object as
Date date = new java.sql.Date(1430454600000L);
which gives yyyy-mm-dd value for toString method.

java.time
The Answer by BalusC is correct: You cannot eliminate a time-of-day from a class object defined to hold a date plus a time-of-day.
Also, you are using troublesome old classes (java.util.Date and java.sql.Date) that are now obsolete, supplanted by the java.time classes.
Instead, use a date-only class for a date-only value. The LocalDate class represents a date-only value without time-of-day and without time zone. The java.sql.Date pretends to do the same, but actually does carry a time of day due to very poor design decision of inheriting from java.util.Date. Avoid java.sql.Date, and use only java.time.LocalDate instead.
You are starting with a java.util.Date object apparently. That represents a point on the timeline in UTC with a resolution in milliseconds. So using that to determine a date requires a time zone. The LocalDate class represents a date-only value without time-of-day and without time zone.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment, so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.
Specify a proper time zone name in the format of continent/region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the JVM’s current default is applied implicitly. Better to be explicit, as the default may be changed at any moment during runtime by any code in any thread of any app within the JVM.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
To get a date-only value from your java.util.Date, first convert to its java.time replacement, Instant. To convert back and forth, call new methods added to the old classes.
Instant instant = myJavaUtilDate.toInstant() ;
That value is in UTC by definition. Apply your desired time zone (ZoneId) to generate a ZonedDateTime.
ZonedDateTime zdt = instant.atZone( z ) ;
Finally, extract your desired LocalDate object from ZonedDateTime.
LocalDate ld = zdt.toLocalDate() ;
As of JDBC 4.2 and later, you can directly exchange java.time classes with your database. So no need to use the the java.sql classes such as java.sql.Date and java.sql.Timestamp.
myPreparedStatement.setObject( … , ld ) ;
Retrieval.
LocalDate ld = myResultSet.getObject( … , LocalDate.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.
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?
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 (<26), 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.

Related

Convert Calendar to Date - ignore timezone

We receive a GregorianCalendar object from a 3rd party library. We need to turn that into a Date for use in another 3rd party library. And we're on Java 1.6 so we don't have the new time/instant classes available.
The problem is calling Calendar.getTime() gives a different date, offset by (I think) our timezone. So the next day by 8 hours.
How can we do this without this shift?
Update: We get the date from an OData call. The date being returned is an employee birthdate (Northwind) and therefore shouldn't have a time. But it's returned as a GregorianCalendar object with a time of 1992-05-01 00:00:00. GMT timezone it appears.
And the getTime() is returning a Date of "Thu Apr 30 18:00:00 MDT 1992" - I'm in the Mountain Time Zone.
The problem is I need to get from the calendar object a Date object of 1992-05-01, not 1992-04-30. And preferably with the time offset matching too.
Get get the Date value in your default time zone, call setTimeZone().
GregorianCalendar cal = new GregorianCalendar(TimeZone.getTimeZone("GMT"));
cal.clear();
cal.set(1992,4,1); // 1992-05-01 00:00:00 GMT
// "Fix" time zone
cal.setTimeZone(TimeZone.getDefault());
System.out.println(cal.getTime());
Output
Fri May 01 00:00:00 EDT 1992
tl;dr
No shift
java.util.Date date = myGregorianCalendar.getTime() ; // Same moment, same point on the timeline. `Date` is in UTC, `GregorianCalendar` may be in some other time zone.
String output = date.toString() ; // This new string is a lie, dynamically applying the JVM’s current time zone while the `Date` is actually in UTC, always, by definition.
There is no shift. Calling GregorianCalendar.getTime produced a java.util.Date. The Date object is always in UTC, by definition. Unfortunately the Date::toString method lies, injecting the JVM’s current default time zone while producing a String.
Be clear that the Date and String are two separate distinct objects. One holds a moment in UTC, the other is a textual representation of that moment after being adjusted into some time zone.
The GregorianCalendar, the Date, and the String all represent the same moment, same point on the timeline, but different wall-clock time.
Use java.time for clarity
Date-time handling is much easier and clear if you use modern java.time classes rather than awful mess that is the legacy classes Date, Calendar, and GregorianCalendar.
java.time
The GregorianCalendar class is one of the troublesome old date-time classes supplanted by the java.time classes built into Java 8 and later. Much of the java.time functionality is back-ported to Java 6 and Java 7 in the ThreeTen-Backport project.
Convert from legacy class to modern java.time using new methods added to the old classes, specifically GregorianCalendar::toZonedDateTime. If using the back-port, use the DateTimeUtils class.
ZonedDateTime zdt = DateTimeUtils.toZonedDateTime( myCalendar ) ;
A ZonedDateTime object is the replacement for GregorianCalendar. This class is conceptually the combination of a Instant (a moment in UTC) with an assigned time zone, a ZoneId object.
If you want the same moment as seen in UTC, extract the Instant.
Instant instant = zdt.toInstant() ;
You can convert back to a java.util.Date from an Instant, for compatibility with old code not yet updated to java.time.
java.util.Date date = DateTimeUtils.toDate( instant ) ; // Convert from modern `Instant` class to legacy `Date` class.
If you want just the date portion, without the time-of-day and without the time zone, create a LocalDate object.
LocalDate ld = zdt.toLocalDate() ;
The problem is calling Calendar.getTime() gives a different date, offset by (I think) our timezone. So the next day by 8 hours.
How can we do this without this shift?
…
And the getTime() is returning a Date of "Thu Apr 30 18:00:00 MDT 1992" - I'm in the Mountain Time Zone.
What you are seeing is an illusion. The GregorianCalendar::getTime method returns to you a java.util.Date object. Then you implicitly called toString on that Date object. That java.util.Date::toString method has an unfortunate behavior of applying your JVM’s current default time zone while generating a string to represent its value. The value of the Date is actually UTC, always UTC, by definition. That toString method creates the illusion that the Date harbors a time zone when in fact it does not†.
†Actually, the java.util.Date class does harbor a time zone, but deep within its source code. Used for stuff like the equals method implementation. But the class has no getter or setter, so it seems invisible to us. And in the context of your Question, is irrelevant.
Confusing? Yes. This is one of many reasons to avoid these terrible old date-time classes. Use only java.time classes instead.
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?
Java SE 8, Java SE 9, Java SE 10, 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 (<26), 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.

incompatible types: java.util.Date cannot be converted to java.sql.Date jdbc preparedstatement [duplicate]

java.util.Date vs java.sql.Date: when to use which and why?
Congratulations, you've hit my favorite pet peeve with JDBC: Date class handling.
Basically databases usually support at least three forms of datetime fields which are date, time and timestamp. Each of these have a corresponding class in JDBC and each of them extend java.util.Date. Quick semantics of each of these three are the following:
java.sql.Date corresponds to SQL DATE which means it stores years, months and days while hour, minute, second and millisecond are ignored. Additionally sql.Date isn't tied to timezones.
java.sql.Time corresponds to SQL TIME and as should be obvious, only contains information about hour, minutes, seconds and milliseconds.
java.sql.Timestamp corresponds to SQL TIMESTAMP which is exact date to the nanosecond (note that util.Date only supports milliseconds!) with customizable precision.
One of the most common bugs when using JDBC drivers in relation to these three types is that the types are handled incorrectly. This means that sql.Date is timezone specific, sql.Time contains current year, month and day et cetera et cetera.
Finally: Which one to use?
Depends on the SQL type of the field, really. PreparedStatement has setters for all three values, #setDate() being the one for sql.Date, #setTime() for sql.Time and #setTimestamp() for sql.Timestamp.
Do note that if you use ps.setObject(fieldIndex, utilDateObject); you can actually give a normal util.Date to most JDBC drivers which will happily devour it as if it was of the correct type but when you request the data afterwards, you may notice that you're actually missing stuff.
I'm really saying that none of the Dates should be used at all.
What I am saying that save the milliseconds/nanoseconds as plain longs and convert them to whatever objects you are using (obligatory joda-time plug). One hacky way which can be done is to store the date component as one long and time component as another, for example right now would be 20100221 and 154536123. These magic numbers can be used in SQL queries and will be portable from database to another and will let you avoid this part of JDBC/Java Date API:s entirely.
LATE EDIT: Starting with Java 8 you should use neither java.util.Date nor java.sql.Date if you can at all avoid it, and instead prefer using the java.time package (based on Joda) rather than anything else. If you're not on Java 8, here's the original response:
java.sql.Date - when you call methods/constructors of libraries that use it (like JDBC). Not otherwise. You don't want to introduce dependencies to the database libraries for applications/modules that don't explicitly deal with JDBC.
java.util.Date - when using libraries that use it. Otherwise, as little as possible, for several reasons:
It's mutable, which means you have to make a defensive copy of it every time you pass it to or return it from a method.
It doesn't handle dates very well, which backwards people like yours truly, think date handling classes should.
Now, because j.u.D doesn't do it's job very well, the ghastly Calendar classes were introduced. They are also mutable, and awful to work with, and should be avoided if you don't have any choice.
There are better alternatives, like the Joda Time API (which might even make it into Java 7 and become the new official date handling API - a quick search says it won't).
If you feel it's overkill to introduce a new dependency like Joda, longs aren't all that bad to use for timestamp fields in objects, although I myself usually wrap them in j.u.D when passing them around, for type safety and as documentation.
tl;dr
Use neither.
java.time.Instant replaces java.util.Date
java.time.LocalDate replaces java.sql.Date
Neither
java.util.Date vs java.sql.Date: when to use which and why?
Both of these classes are terrible, flawed in design and in implementation. Avoid like the Plague Coronavirus.
Instead use java.time classes, defined in in JSR 310. These classes are an industry-leading framework for working with date-time handling. These supplant entirely the bloody awful legacy classes such as Date, Calendar, SimpleDateFormat, and such.
java.util.Date
The first, java.util.Date is meant to represent a moment in UTC, meaning an offset from UTC of zero hours-minutes-seconds.
java.time.Instant
Now replaced by java.time.Instant.
Instant instant = Instant.now() ; // Capture the current moment as seen in UTC.
java.time.OffsetDateTime
Instant is the basic building-block class of java.time. For more flexibility, use OffsetDateTime set to ZoneOffset.UTC for the same purpose: representing a moment in UTC.
OffsetDateTime odt = OffsetDateTime.now( ZoneOffset.UTC ) ;
You can send this object to a database by using PreparedStatement::setObject with JDBC 4.2 or later.
myPreparedStatement.setObject( … , odt ) ;
Retrieve.
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.class ) ;
java.sql.Date
The java.sql.Date class is also terrible and obsolete.
This class is meant to represent a date only, without a time-of-day and without a time zone. Unfortunately, in a terrible hack of a design, this class inherits from java.util.Date which represents a moment (a date with time-of-day in UTC). So this class is merely pretending to be date-only, while actually carrying a time-of-day and implicit offset of UTC. This causes so much confusion. Never use this class.
java.time.LocalDate
Instead, use java.time.LocalDate to track just a date (year, month, day-of-month) without any time-of-day nor any time zone or offset.
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
LocalDate ld = LocalDate.now( z ) ; // Capture the current date as seen in the wall-clock time used by the people of a particular region (a time zone).
Send to the database.
myPreparedStatement.setObject( … , ld ) ;
Retrieve.
LocalDate ld = myResultSet.getObject( … , LocalDate.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.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
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?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - 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
Most 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 (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The only time to use java.sql.Date is in a PreparedStatement.setDate. Otherwise, use java.util.Date. It's telling that ResultSet.getDate returns a java.sql.Date but it can be assigned directly to a java.util.Date.
I had the same issue, the easiest way i found to insert the current date into a prepared statement is this one:
preparedStatement.setDate(1, new java.sql.Date(new java.util.Date().getTime()));
The java.util.Date class in Java represents a particular moment in time (e,.g., 2013 Nov 25 16:30:45 down to milliseconds), but the DATE data type in the DB represents a date only (e.g., 2013 Nov 25). To prevent you from providing a java.util.Date object to the DB by mistake, Java doesn’t allow you to set a SQL parameter to java.util.Date directly:
PreparedStatement st = ...
java.util.Date d = ...
st.setDate(1, d); //will not work
But it still allows you to do that by force/intention (then hours and minutes will be ignored by the DB driver). This is done with the java.sql.Date class:
PreparedStatement st = ...
java.util.Date d = ...
st.setDate(1, new java.sql.Date(d.getTime())); //will work
A java.sql.Date object can store a moment in time (so that it’s easy to construct from a java.util.Date) but will throw an exception if you try to ask it for the hours (to enforce its concept of being a date only). The DB driver is expected to recognize this class and just use 0 for the hours. Try this:
public static void main(String[] args) {
java.util.Date d1 = new java.util.Date(12345);//ms since 1970 Jan 1 midnight
java.sql.Date d2 = new java.sql.Date(12345);
System.out.println(d1.getHours());
System.out.println(d2.getHours());
}
java.util.Date represents a specific instant in time with millisecond precision. It represents both date and time information without timezone. The java.util.Date class implements Serializable, Cloneable and Comparable interface. It is inherited by java.sql.Date, java.sql.Time and java.sql.Timestamp interfaces.
java.sql.Date extends java.util.Date class which represents date without time information and it should be used only when dealing with databases. 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.
It inherits all public methods of java.util.Date such as getHours(), getMinutes(), getSeconds(), setHours(), setMinutes(), setSeconds(). As java.sql.Date does not store the time information, it override all the time operations from java.util.Dateand all of these methods throw java.lang.IllegalArgumentException if invoked as evident from their implementation details.

Date constructor java

Hello I am trying to get the current date at java at a Class I created but everything fails. I've seen in many sites
e.g. http://www.mkyong.com/java/java-date-and-calendar-examples/
that the date constructor has no arguments
e.g. Date date = new Date();
Now in my project I try to use it like this and I get the error
that The constructor Date() is undefined
How is this possible? I give you the full code so far
import java.sql.Date;
import java.text.SimpleDateFormat;
public class Utility {
String title;
int ID;
Date date;
Utility(String t,int ID){
this.ID=ID+1;
title=t;
SimpleDateFormat sdf = new SimpleDateFormat("dd/M/yyyy");
Date a=new Date();// I get the error here
String date = sdf.format(a);
System.out.print(date);
}
}
I work at Eclipse IDE. Can you help me?
The examples you found are for java.util.Date while you are using java.sql.Date
java.sql.Date
has two constructors
Date(long date): Constructs a Date object using the given milliseconds time value.
Date(int year, int month, int day): which is deprecated
and no default Date() constructor.
java.util.Date
among others has a default constructor without arguments
Date(): Allocates a Date object and initializes it so that it represents the time at which it was allocated, measured to the nearest millisecond.
When importing classes, Eclipse will help you fining possible candidates but always check if the first suggestion is really what you want.
You are using the wrong Date class.
Have a look at your imports. Don't use java.sql.Date use java.util.Date instead.
You are importing java.sql.Date use java.util.Date
You have imported wrong class. It is java.util.Date and not java.sql.Date
You can also use use java.util.Calendar as follows:
Calendar c = Calendar.getInstance();
java.util.Date date = c.getTime();
tl;dr
Get today’s date:
LocalDate.now()
Generate text representing today’s date, in your desired format:
LocalDate
.now()
.format(
DateTimeFormatter.ofPattern( "d/M/uuuu" )
)
23/1/2019
Details
The answer by Matteo is correct. You are abusing the java.sql.Date class by treating it as java.util.Date.
But the answers suggesting using java.util.Calendar questions are misguided. Both java.util.Date & Calendar are notoriously bad classes, with poor design and implementation. They are outmoded by the modern java.time.* JSR 310 classes.
Also, when working with date-time you should always think about time zone. Otherwise you'll be getting default time zone with possibly varying behavior at runtime.
java.time
ZonedDateTime zonedDateTime = ZonedDateTime.now( ZoneId.of( "America/Montreal" ) );
If you want a date-only value, without a time-of-day and without a time zone, use LocalDate.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone or offset-from-UTC.
A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
If no time zone is specified, the JVM implicitly applies its current default time zone. That default may change at any moment during runtime(!), so your results may vary. Better to specify your desired/expected time zone explicitly as an argument.
Specify a proper time zone name in the format of Continent/Region, such as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 2-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).
ZoneId z = ZoneId.of( "America/Montreal" ) ;
LocalDate today = LocalDate.now( z ) ;
If you want to use the JVM’s current default time zone, ask for it and pass as an argument. If omitted, the code becomes ambiguous to read in that we do not know for certain if you intended to use the default or if you, like so many programmers, were unaware of the issue.
ZoneId z = ZoneId.systemDefault() ; // Get JVM’s current default time zone.
Or specify a date. You may set the month by a number, with sane numbering 1-12 for January-December.
LocalDate ld = LocalDate.of( 1986 , 2 , 23 ) ; // Years use sane direct numbering (1986 means year 1986). Months use sane numbering, 1-12 for January-December.
Or, better, use the Month enum objects pre-defined, one for each month of the year. Tip: Use these Month objects throughout your codebase rather than a mere integer number to make your code more self-documenting, ensure valid values, and provide type-safety. Ditto for Year & YearMonth.
LocalDate ld = LocalDate.of( 1986 , Month.FEBRUARY , 23 ) ;
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?
Java SE 8, Java SE 9, Java SE 10, Java SE 11, and later - 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
Most 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 (<26), 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.

Date vs TimeStamp vs calendar?

I sometimes get confused by the different Date types in java and their practical usage. Here
i am trying to summarize my understanding
java.sql.Date :- A thin wrapper around a millisecond value that allows JDBC to identify this as an SQL DATE value
java.sql.Timestamp :- A thin wrapper around java.util.Date that allows the JDBC API to identify this as an SQL
TIMESTAMP value. It adds the ability to hold the SQL TIMESTAMP fractional seconds value, by allowing the specification
of fractional seconds to a precision of nanoseconds
I have seen most of the projects prefer Timestamp instead of date. I think the main reason for this is that Timestamp can hold the value till
nano seconds precision whereas Data can hold till milli seconds. Correct?
Calendar :- This class is designed for date manipulation for example :- for converting between a specific instant in time and a
set of calendar fields such as YEAR, MONTH, DAY_OF_MONTH, HOUR, and so on, and for manipulating the calendar fields, such as getting
the date of the next week.Though i dont know why this class is abstract when only one implementation exists i.e GregorianCalendar.
java.sql.Timestamp A thin wrapper around java.util.Date that allows the JDBC API to identify this as an SQL TIMESTAMP value.
If you check java.sql.Timestamp JavaDoc, it is very explicit that this class extends from java.util.Date (as java.sql.Date does). And in real world projects you must plain java.util.Date when storing the data in your database and mostly java.sql.Timestamp since it stores date and time value, while java.sql.Date just stores date value.
On the other hand, java.util.Calendar is abstract since there are more implementations of this apart from java.util.GregorianCalendar. If you see the code of Calendar#getInstance from HotSpot, you will see that it calls createCalendar(TimeZone.getDefaultRef(), Locale.getDefault(Locale.Category.FORMAT)), and this method code uses 3 different calendars: BuddhistCalendar, JapaneseImperialCalendar and GregorianCalendar. This code is copied from JDK 7 source:
private static Calendar createCalendar(TimeZone zone,
Locale aLocale) {
Calendar cal = null;
String caltype = aLocale.getUnicodeLocaleType("ca");
if (caltype == null) {
// Calendar type is not specified.
// If the specified locale is a Thai locale,
// returns a BuddhistCalendar instance.
if ("th".equals(aLocale.getLanguage())
&& ("TH".equals(aLocale.getCountry()))) {
cal = new BuddhistCalendar(zone, aLocale);
} else {
cal = new GregorianCalendar(zone, aLocale);
}
} else if (caltype.equals("japanese")) {
cal = new JapaneseImperialCalendar(zone, aLocale);
} else if (caltype.equals("buddhist")) {
cal = new BuddhistCalendar(zone, aLocale);
} else {
// Unsupported calendar type.
// Use Gregorian calendar as a fallback.
cal = new GregorianCalendar(zone, aLocale);
}
return cal;
}
Now, why to work directly with Calendar instead of GregorianCalendar? Because you must work with abstract classes and interfaces when provided instead of working directly with implementations. This is better explained here: What does it mean to "program to an interface"?
Apart from this, if you will work with date and times, I recommend using a library like Joda-Time that already handles and solves lot of the problems with the current Java Date API and also provides methods to retrieve this date and times object in java.util.Date flavor.
java.time
You must first understand that those old date-time classes bundled with early versions of Java are a confusing mess of badly designed classes with hacks. They were the industry's first attempt at a sophisticated facility for date-time handling, and deserve credit for that. But ultimately they failed.
They have been supplanted by the new java.time framework built into Java 8 and later.
java.sql.Date — Use java.time.LocalDate instead
java.sql.Timestamp — Use java.time.Instant instead
java.util.Calendar & GregorianCalendar — Use java.time.ZonedDateTime instead
For date only, without time-of-day nor time zone, use java.time.LocalDate. For a moment on the timeline in UTC, use java.time.Instant. To assign a different time zone to an Instant, use java.time.ZonedDateTime.
Understand that an offset-from-UTC is merely a number of hours and minutes ahead of, or behind, UTC. A time zone is a history of past, present, and future changes to the offset used by the people of a certain region.
If you have a date-time value that has an offset-from-UTC rather than a time zone, represent that with the OffsetDateTime class. Then call its toInstant method to obtain a Instant object to be sent to your database in a column of type akin to the SQL-standard TIMESTAMP WITH TIME ZONE.
The SQL-standard type TIMESTAMP WITHOUT TIME ZONE (without, not with) purposely lacks any concept of time zone or offset-from-UTC. The legacy date-time classes had no way to represent such a value. Now, in java.time, we have LocalDateTime.
If your JDBC driver complies with JDBC 4.2 or later, you can directly exchange java.time objects with your database. No need to ever use the java.sql date-item types again.
myPreparedStatement.setObject( … , instant ) ;
And retrieval.
Instant instant = myResultSet.getObject( … , Instant.class ) ;
Adjust into the wall-clock time used by the people of a particular region (a time zone).
ZoneId z = ZoneId.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
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?
Java SE 8, Java SE 9, Java SE 10, 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 (<26), 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.
The first line in the original question contains the phrase " the different Date types in java and their practical usage"
The practical usage of the timestamp data type is exactly as it says - an timestamp used by the SQL to record a precise chronological value typically used for transactional ordering. Timestamps are usually only used internally... where nanoseconds count. There are use cases for external timestamp data, but they are relatively rare.
The date type handles 99% of external nonscientific data needs with millisecond precision.

Converting Joda LocalTime to java.sql.Date

To make a JDBC query I need to pass date to it. The date is kept in Date field type of PostgreSql database, which represents specific day without any time.
As I need only date, I decided to use specific object which represent only date without time, which is LocalDate from Joda-Time package. I thought it is important because if I used DateTime object, it would carry redundant time data as well as it might lead to bugs at end of daylight saving time when the clock are put backward one hour (though the situation is unprecedentedly rare, it's not impossible).
But when I started trying to square LocalDate object with accepted arguments of preparedStatement.setDate method, I didn't find a proper way to do it.
setDate accepts java.sql.Date as parameter. And the only option to construct java.sql.Date object is to pass it time in milliseconds.
But this defeats all the purpose of using LocalDate from Joda-Time package, as on this conversion we get back to milliseconds and, while these conversions happen, clock may be put back one hour and change the date to the previous date.
So, now I have this line in my code:
preparedStatement.setDate(1, new java.sql.Date(localDate.toDate().getTime()));
But is this the best way to convert LocalDate to accepted by setDate format?
Are my concerns related to daylight saving time and corresponding clock-shifts justified?
Is there a better way to pass date (and only date without time) to JDBC preparedStatement?
It should be safe to use your technique because all the timezone issues will be taken into account by LocalDate#toDate. The resulting millisecond instant you have is context-independent: it uniquely relates to a timezone valid at that point in time within the locale you are using for conversion. In other words, if you repeat the conversion of the exact same millisecond value throughout a year, you will consistently get the exact same answer, even if timezone regulations change for your place in the meantime, since JDK refers to a database documenting the complete history of all timezone changes around the world.
When reasoning about these issues it is important to remember that your current timezone has no effect on the conversion, which is parameterized by your locale and resolves the timezone only within the context of the instant being converted.
I wholeheartedly sympathize with the queasiness you fell about all this: it is turning a simple and straigtforward operation into a complex maze of calculations which does nothing but invite trouble. Hopefully things will take a positive turn with Java 8 and its new (yes, again!) Date/Time API, based firmly on JodaTime.
I got the same problem today. I'm using JDK 8. After spending some hours searching finally I found the answer at Java SE 8 Documentation. This is the solution :
statement.setDate(5, java.sql.Date.valueOf(personToUpdate.getBirthday()));
statement is PreparedStatement instance. "personToUpdate.getBirthday()" is type of LocalDate.
Since org.joda.time.toDateMidnight() and org.joda.time.toDateMidnight(DateTimeZone zone) have been deprecated, this is the solution that works perfectly for me.
My typical Class, to be persisted:
...
import org.joda.time.LocalDate;
...
public class MyObject implements Serializable {
...
private LocalDate startDate;
...
private EndDate startDate;
// Getters and Setters
...
...
}
Im my other Class where I persist startDate, I have:
myObject.setStartDate(new LocalDate(myObject.getStartDate().toDateTimeAtStartOfDay(DateTimeZone.getDefault())));
tl;dr
myPreparedStatement.setObject( // Pass java.time objects directly to database with JDBC 4.2 or later.
… ,
LocalDate.now() // Get current date today. Better to pass optional `ZoneId` time zone object explicitly than rely implicitly on JVM’s current default.
)
java.time
In Java 8 and later, the new java.time framework is now built-in. This successor to Joda-Time is defined by JSR 310 and extended by the ThreeTen-Extra project.
Hopefully we well eventually see the JDBC drivers updated to directly handle the new java.time types. But until then we continue to need the java.sql.* types. Fortunately, new methods have been added to conveniently convert between the types.
For a date-only, with no time-of-day and no time zone, the Java type is LocalDate (quite similar to Joda-Time).
As for your concern about time zone related to a LocalDate, it matters when your are translating a date-only to a date-time, to a moment on the timeline. A date-only is just a vague idea, with no real meaning, until you translate it to a time-span of moment on the timeline (midnight to midnight in some time zone). For example, determining "today" requires a time zone. In java.time we use the ZoneId class.
LocalDate today = LocalDate.now( ZoneId.of( "America/Montreal" ) );
If omitted, your JVM’s current default time zone is used in determining the date. In other words, the following two lines are equivalent.
LocalDate today = LocalDate.now();
LocalDate today = LocalDate.now( ZoneId.systemDefault() );
I consider the first version, now(), to be a poor API design choice. This implicit application of the JVM’s current default time zone causes no end of confusion, bugs, and misery among naïve developers. For one thing, the JVM's current default varies by machine, by host OS settings, and by sysadmins. Worse, the JVM’s current default can change at any moment, during runtime, by any code in any thread of any app within that JVM. So best practice is to always specify your desired/expected time zone.
Now that we have a java.time object for "today", how to get it into the database?
With JDBC 4.2 or later, directly exchange java.time objects with your database.
myPreparedStatement.setObject( … , today ) ;
To retrieve:
LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;
If you cannot upgrade yet to JDBC 4.2 or later: Use a java.sql.Date object. In Java 8, that old class gained new methods, toLocalDate and valueOf. The latter is our bridge from the java.time type to the java.sql type.
java.sql.Date sqlToday = java.sql.Date.valueOf( today );
From there do the usual PreparedStatement handling.
myPreparedStatement.setDate( 1 , sqlToday );
Date-only vs Date-time
Perhaps you have concerns about such a date-only fitting your business needs.
If you need to know, for example, if a contract was signed by the end of the day for legal reasons, then date-only is the wrong data-type if mean a specific moment such as the stroke of midnight in Montréal. A new day dawns earlier in Paris than in Montréal, so "today" in Paris is "yesterday" in Montréal. If your contract deadline is defined legally as the end of the day in Montréal, then you must apply a time zone. To apply a time zone, you must have a date-time rather than a date-only. You can make a jump from the LocalDate into a ZonedDateTime, but I consider that overly complex. Your database should have used a date-time type from the beginning.
In Postgres, a date-time type means the TIMESTAMP WITH TIME ZONE type. That name is a misnomer as the time zone is not actually stored. Think of it as “timestamp with respect for time zone”. Postgres uses any offset-from-UTC or time zone information accompanying incoming data to adjust to UTC, and that offset/zone info is then discarded. The other type, TIMESTAMP WITHOUT TIME ZONE, ignores the offset/zone info entirely, and this is the wrong behavior for most any business app.
I suspect many developers or DBAs may make the naïve mistake of thinking by intuition that the date-only has obvious meaning. But in fact if you have specific or strict moment-oriented needs, such as legalities regarding events such as “contract signed”, “invoice received”, or “company executive hired”, then a date-time value should be used rather than date-only.
In other words, regarding the Question’s author’s comment:
And I expected there should be a way to work with dates without resorting to time instances.
No, I would argue that is asking for trouble. If moments matter, use a date-time rather than a date-only.
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.
Try to Use LocalDate#toDateMidnight() which sets time to 0 and then DateMidnight#toDate().
Date date = localDate.toDateMidnight().toDate();
Or if you're using JodaTime 1.5 or newer, use LocalDate#toDateTimeAtStartOfDay() and then DateTime#toDate()
Hope that help

Categories