What is difference between java.utill.Time and java.sql.time [duplicate] - java

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.

Related

Datetime fields in json

How do we store postgres datetime objects in java pojo classes for json objects? I am trying to sort them and want to check if I should be comparing datetime or strings? Date compareTo doesn't work but strings comparTo works fine for datetime objects
private Date fieldA;
private Date fieldB;
fieldA.compareTo(fieldB);
tl;dr
How do we store postgres datetime objects in java pojo classes for json objects?
It depends.
For a Postgres column of TIMESTAMP WITH TIME ZONE, use the java.time.Instant class.
For a Postgres column of TIMESTAMP WITHOUT TIME ZONE, use the java.time.LocalDateTime class.
As for JSON, there are no JSON data types for date-time values. Generate strings in standard ISO 8601 format.
I am trying to sort them
The java.time classes know how to sort themselves, implementing the Comparable interface.
if I should be comparing datetime or strings?
Always use smart objects, not dumb strings. That is why you have JDBC technology and JDBC drivers.
Date compareTo doesn't work
Never use the java.util.Date class. Never use the java.sql.Date class. Use only java.time classes.
strings comparTo works fine for datetime objects
Nope. Date-time strings can come in all kinds of formats, using all kinds of human languages and cultural norms, with various time zones or offsets-from-UTC applied. Strings are not appropriate for sorting date-time values. Use smart java.time objects, not dumb strings.
Or do your sorting on the database side, where Postgres is optimized for such chores.
private Date fieldA; private Date fieldB;
Make that:
private Instant fieldA, fieldB ;
…
boolean isAEarlier = fieldA.isBefore( fieldB ) ;
boolean isAtheSame = fieldA.equals( fieldB ) ; // Note that some other java.time classes have `isEqual` method as well as `equals` method.
boolean isALater = fieldA.isAfter( fieldB ) ;
boolean isAEqualToOrLaterThan = ( ! fieldA.isBefore( fieldB ) ) ; // "Is equal to or later than" is a common use-case. "Not before" is a logical shortcut with the same effect.
java.time
The Date class is now legacy, part of the terribly troublesome old date-time classes that were supplanted by the java.time classes years ago. Never use Date, Calendar, SimpleDateFormat, and such.
Your Question is a duplicate of many others, so I'll be brief here. Search Stack Overflow to learn more.
Attached to the timeline
For the database column type TIMESTAMP WITH TIME ZONE defined in the SQL standard and used in Postgres, that represents a moment, a specific point on the timeline.
In Postgres, this type has a resolution of microseconds and is always in UTC. Any inputs with an indicator of time zone or offset-from-UTC are adjusted into UTC, and the zone/offset then discarded. So the type is a bit of a misnomer, as the original zone/offset is forgotten and the stored value is always in UTC. Other databases may vary in this behavior, so beware, as the SQL spec barely touches on the subject of date-time.
Beware that when using tools other than JDBC, your tool may be injecting a time zone or offset-from-UTC after retrieving the stored UTC value; this can be quite misleading and confusing to a novice (and is an unfortunate design decision in my opinion).
In Java, generally best to work in UTC. As a programmer, learn to think, store, and exchange moments as UTC. Generally, use the Instant class for this. For defining member variables in your classes, Instant is your go-to class.
Instant instant = Instant.now() ; // Capture the current moment in UTC, with a resolution as fine as nanoseconds.
You may want to truncate any nanoseconds to microseconds to match retrieved values from Postgres. Specify resolution with ChronoUnit.
Instant instant = Instant.now().truncatedTo( ChronoUnit.MICROS ) ;
For presentation to the user in their desired/expected time zone, assign a ZonedId to get a ZonedDateTime.
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" ) ;
ZonedDateTime zdt = instant.atZone( z ) ;
To get back to UTC, extract a Instant.
Instant instant = zdt.toInstant() ;
To generate localized text representing the value of the ZonedDateTime object, use DateTimeFormatter. Search Stack Overflow for much more info.
Not attached to the timeline
The database type TIMESTAMP WITHOUT TIME ZONE purposely lacks any concept of time zone or offset-from-UTC. As such it does not represent a moment, is not a point on the timeline, and is not what you likely want in a business app except when:
Scheduling appointments out into the future.
Representing the concept of a date and time to every zone or any zone, not a particular zone.
In Postgres, any zone or offset accompanying input is ignored. The date and the time-of-day are stored as-is with no adjustment.
The matching type in Java is LocalDateTime.
The “Local” in this class name does not mean “a particular locality”. Just the opposite! It means every locality, or any locality, but not a particular locality. If you do not understand this, do some study, read the class doc, and search Stack Overflow.
Database
Use smart objects rather than dumb strings to exchange date-time values with your database.
As of JDBC 4.2, you can directly exchange java.time objects with the database. Never use java.sql.Timestamp, java.sql.Date, and java.sql.Time.
Storage.
myPreparedStatement.setObject( … , instant ) ;
Retrieval.
Instant instant = myResultSet.getObject( … , Instant.class ) ;
JSON
The JSON spec defines very few data types, and none of them are date-time related. You are on your own there. Ditto for XML.
ISO 8601
When serializing date-time values as text, use the standard ISO 8601 formats. These are designed to be practical and useful, and to avoid ambiguities. They are designed to be easy to parse by machine, while also being easy to read by humans across cultures.
The java.time classes use these standard formats by default when parsing/generating date-time strings. Just call parse and toString on the various classes.
Instant instant = Instant.parse( "2018-01-23T01:23:45.123456Z" ) ;
String output = instant.toString() ;
The ISO 8601 format for a moment happen to be similar to the usual SQL format except that in SQL uses a SPACE in the middle rather than a T. That fact is largely irrelevant as you should be using objects rather than strings between Java and your database, as mentioned above.
Half-Open
Related to the topic of comparing… When working with spans of time, learn to consistently use the Half-Open approach where the beginning is inclusive while the ending is exclusive. Search Stack Overflow to learn more.
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.
You should use the java.time.LocalDateTime class. This is the new (Java 8) class for representing a date and time without any specific time zone or offset.
In other words, you can think of it as holding a year, month, day, hour, minute, second and millisecond. But because there's no time zone or offset specified, it doesn't actually correspond to a particular Instant - that is, a particular moment in time.
It seems to me that of all the Java 8 date/time related classes, this is the one that's closest in intent to what you'd store in a database's DateTime field.
Further reading: Basil Bourque's answer to this question
Thanks. I have used java.sql Timestamp and it works fine. I couldn't see LocalDatetime supported by Json Jackson library. – JEE_program Jul 3 at 21:47

How to parse a String YYYYMMDD_HHMMSSZ in Java 8

I need to parse a UTC date and time string, e.g. 20180531_132001Z into a Java 8 date and time object. How do I go about doing this using Java 8's new date and time libraries? Most examples I see is for LocalDateTime, like this:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss'Z'");
LocalDateTime localDateTime = LocalDateTime.parse("20180531_132001Z", formatter);
System.out.println(localDateTime);
System.out.println(localDateTime.atOffset(ZoneOffset.UTC));
The code outputs:
2018-05-31T13:20:01
2018-05-31T13:20:01Z
Is this considered local time or UTC time? The string value I am parsing is based on UTC, so I am wondering if I need to do anything further before persisting to the database.
If the former, how do I convert that to UTC date and time?
I ultimately need to persist this to a SQL Server database table (column type is [datetime2](7), using [Spring] JDBC.
Update: Based on the comments and answers, I think my question is not well thought out. Putting it another way, if I get an input string and I parse it without factoring any zone or offset, I will get a LocalDateTime object. How do I take that object and convert the encapsulated value to UTC date and time?
LocalDateTime can be misleading. It doesn't represent your local date/time, it represents a local date/time.
It carries no time zone info at all.
That is, it just says for example "it's 13:20". It doesn't say where it's 13:20. It's up to you to interpret the where part.
Due to this LocalDateTime is usually not very useful for carrying timestamps, it's only useful for situations when the timezone is dependent on some context.1
When working with timestamps it's better to use ZonedDateTime or OffsetDateTime instead. These carry the date, time and offset.
So localDateTime.atOffset(ZoneOffset.UTC) will actually return an instance of OffsetDateTime, by interpreting localDateTime as UTC time.
One could argue that you can avoid the interpreting part by parsing with the timezone info in the first place (even though it's always Z):
String example = "20180531_132001Z";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmssX");
OffsetDateTime dateTime = OffsetDateTime.parse(example, formatter);
System.out.println(dateTime); // look ma, no hardcoded UTC
Will print:
2018-05-31T13:20:01Z
The added value is that your code automatically supports timezones (e.g. "20180531_132001+05").
JDBC 4.2 compliant driver may be able to directly address java.time types by calling setObject.
For older JDBC drivers you can convert dateTime to a java.sql.Timestamp or java.util.Date:
java.sql.Timestamp.from(dateTime.toInstant());
java.util.Date.from(dateTime.toInstant());
1 There is almost always some context in which LocalDateTime operates. For example "Flight KL1302 arrives at airport X tomorrow at 13:20". Here the context of "tomorrow at 13:20" is the local time at airport X; it can be determined by looking up the time zone of X.
tl;dr
myPreparedStatement.setObject( // Pass java.time objects directly to database, as of JDBC 4.2.
… , // Indicate which placeholder in your SQL statement text.
OffsetDateTime.parse( // Parse input string as a `OffsetDateTime` as it indicates an offset-from-UTC but not a time zone.
"20180531_132001Z" , // Define a formatting pattern to match your particular input.
DateTimeFormatter.ofPattern( "uuuuMMdd_HHmmssX" ) // TIP: When exchanging date-time values as text, use use standard ISO 8601 formats rather than inventing your own.
) // Returns a `OffsetDateTime` object.
.toInstant() // Returns a `Instant` object, always in UTC by definition.
)
Details
There is some helpful information in the other Answers, but all of them have some misinformation which I tried to correct by posting comments.
Most importantly, your code is using the wrong Java class and the wrong database data type for that given input.
Below is explanation along with a complete code example, using the modern java.time classes with JDBC 4.2 or later.
Z = UTC
DateTimeFormatter.ofPattern("yyyyMMdd_HHmmss'Z'")
Never put single-quotes around vital parts of your input such as you did here with Z. That Z means UTC and is pronounced “Zulu”. It tells us the text of the date and time-of-day should be interpreted as using the wall-clock time of UTC rather than, say, America/Montreal or Pacific/Auckland time zones.
Do not use the LocalDateTime for such inputs. That class lacks any concept of time zone or offset-from-UTC. As such, this class does not represent a moment, and is not a point on the timeline. A LocalDateTime represents the set of potential moments along a range of about 26-27 hours (across all time zones). Use LocalDateTime when you mean any or all time zones rather than one particular zone/offset. In contrast, the Z tells us this input uses the wall-clock time of UTC specifically.
Parsing
Define a formatting pattern to match all important parts of your input string.
String input = "20180531_132001Z" ;
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuuMMdd_HHmmssX" ) ;
By the way, whenever possible, use standard ISO 8601 formats rather than a custom format as seen in your Question. Those formats are wisely designed to be easy to parse by machine and easy to read by humans across cultures while eliminating ambiguity.
Parse as a OffsetDateTime because your input indicates an offset-from-UTC (of zero hours). An offset-from-UTC is merely a number of hours and minutes, nothing more, nothing less.
Use the ZonedDateTime class only if the input string indicates a time zone. A time zone has a Contintent/Region name such as Africa/Tunis. A zone represents the history of past, present, and future changes in the offset used by the people of a particular region.
OffsetDateTime odt = OffsetDateTime.parse( input , f ) ;
odt.toString(): 2018-05-31T13:20:01Z
Database
To communicate this moment to a database using JDBC 4.2 and later, we can directly pass the java.time object.
myPreparedStatement.setObject( … , odt ) ;
If your JDBC driver does not accept the OffsetDateTime, extract the simpler class Instant. An Instant is in UTC always, by definition.
Instant instant = odt.toInstant() ;
myPreparedStatement.setObject( … , instant ) ;
And retrieval.
Instant instant = myResultSet.getObject( … , Instant.class ) ;
Beware - Wrong datatype in your database
I am not a MS SQL Server user, but according to this documentation, the column data type DATETIME2 is not appropriate to your input. That data type seems to be equivalent to the SQL-standard type DATETIME WITHOUT TIME ZONE. Such a type should never be used when recording a specific moment in history.
Lacking any concept of time zone or offset-from-UTC, that column type should only be used for three situations:
The zone or offset is unknown.This is bad. This is faulty data. Analogous to having a price/cost without knowing the currency. You should be rejecting such data, not storing it.
The intention is “everywhere”, as in, every time zone.Example, a corporate policy that states “All our factories will break for lunch at 12:30" means the factory in Delhi will break hours before the factory in Düsseldorf which breaks hours before the factory in Detroit.
A specific moment in the future is intended, but we are afraid of politicians redefining the time zone.Governments change the rules of their time zones with surprising frequency and with surprisingly little warning (even [no warning at all][10]). So if you want to book an appointment at 3 PM on a certain date, and you really mean 3 PM regardless of any crazy decision a government might make in the interim, then store a LocalDateTime. To print a report or display a calendar, dynamically apply a time zone (ZoneId) to generate a specific moment (ZonedDateTime or Instant). This must be done on-the-fly rather than storing the value.
Since your input is a specific moment, a certain point on the timeline, you should be storing it in the database using a column type akin to 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?
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.
Maybe this can help you.
public static void main(String... strings) {
OffsetDateTime utc = OffsetDateTime.now(ZoneOffset.UTC);
System.out.println(utc.toString());
DateTimeFormatter format = DateTimeFormatter.ofPattern("yyyy mm dd hh:mm a");
System.out.println(utc.format(format));
}
While you certainly can use LocalDateTime and format it to look like a zoned date time using offset, it would be easier to use an Object designed to store time zone.
ZonedDateTime zonedDateTime = ZonedDateTime.parse("20180531_132001Z", DateTimeFormatter.ofPattern("yyyMMdd_HHmmssX"));
This gives you the option to use Instant to convert to SQL timestamp or any other format without having to hard-code the time zone, especially if time zone is added in the future or changes.
java.sql.Timestamp timestamp = new java.sql.Timestamp(zonedDateTime.toInstant().toEpochMilli());
You can view the timestamp's instant and compare it to the toString, which should be pegged to your timezone, and instant.toString, which pegs to UTC.
System.out.print(timestamp + " " + timestamp.toInstant().toString());
this should do the trick to parse string to LocalDateTime :
String example = "20180531_132001Z";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd_HHmmssX");
ZonedDateTime dateTime = ZonedDateTime.parse(example, formatter);
See that code run live in IdeOne.com.
dateTime.toString(): 2018-05-31T13:20:01Z
Timestamp timestamp = Timestamp.from(dateTime.toInstant());
Timestamp then is saved into db

SQL database (JDBC): A column of type date only stores date values and not time values

I have a database like this where lastEdited is a date field.
I connected this database to a Java web application by using "RESTFUL web-services from database"
This automatically generated a class called ThreadChat for my THREADCHAT column. Given here is the getter and setter for the lastEdited part.
lastEdited is a java.util.Date object.
public Date getLastedited() {
return lastedited;
}
public void setLastedited(Date lastedited) {
this.lastedited = lastedited;
}
Here, I am creating a new ThreadChat object and adding the data to the database. Argument for lastEdited is a java.util.Date object.
ThreadChat thread = new ThreadChat(threadName, new Date(), loginIdInt);
threadChatFacadeREST.create(thread);
This would update the table like this.
This method returns all the records in the THREADCHAT table.
List<ThreadChat> list = getAllThreads();
However, getLastEdited() returns a XMLGregorianCalender object instead of a Date object as in the getter method above.
If I print this object to the console, the date part is there but I get 00:00 for the minutes and hours part every time.
2018-04-10T00:00:00+05:30
How do I store Date + Time in a JDBC database and retrieve both?
The type of your field in your database is DATE so DATE only stores YYYY-MM-DD.
If you want to store also the time you must change the type of your field in your database to DATETIME. The representation of this is: YYYY-MM-DD HH:MI:SS
More information in: https://www.w3schools.com/sql/sql_datatypes.asp
tl;dr
You are using a date-only type to hold a date-time value – trying to fit a square peg into a round hole.
How do I store Date + Time in a JDBC database and retrieve both?
To store a moment, a date-time value, use a date-time type:
TIMESTAMP WITH TIME ZONE in your database.
Instant in Java.
You are using terribly confusing legacy classes. Use only java.time classes instead.
Databases vary
Databases vary widely in their date-time data types and their behavior. You do not specify your database, so we can only guess or abide by the SQL standard.
The SQL standard barely touches on the subject of date-time handling, unfortunately. The standard briefly defines:
DATE as a date-only value without time-of-day.
A TIMESTAMP WITHOUT TIME ZONE is a date and a time-of-day, but lacks any concept of time zone or offset-from-UTC, so it does not represent actual moments.
For actual moments, use TIMESTAMP WITH TIME ZONE. That type name can be misleading as some implementations such as Postgres do not store a zone with the value, but instead use any passed zone information to adjust into a UTC value for storage.
java.time
You are using terrible old date-time classes from the earliest versions of Java. Those were supplanted in Java 8 and later by the java.time classes. Never use Date or Calendar again.
Generally best to think, work, store, log, and exchange date-time values in UTC unless specifically required by the business logic or user-interface. So generally you should focus on the Instant class. The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction). This class replaces java.util.Date.
Capture the current moment in UTC.
Instant instant = Instant.now() ; // Capture the current moment in UTC.
Store this Instant in a database column of SQL-standard type TIMESTAMP WITH TIME ZONE or whatever is akin to that in your particular database.
JDBC 4.2
As of JDBC 4.2 and later, you can directly exchange java.time objects with your database.
myPreparedStatement.setObject( … , instant ) ;
Retrieval.
Instant instant = myResultSet.getObject( … , Instant.class ) ;
Converting
If handed an obsolete XMLGregorianCalendar, immediately convert into java.time ZonedDateTime by way of the obsolete GregorianCalendar class.
ZonedDateTime zdt = myXmlGregCal.toGregorianCalendar().toZonedDateTime() ; // Convert from legacy classes to modern java.time class.
If you want to see that same moment in UTC rather than the wall-clock time used by the people of that particular region (time zone), extract an Instant.
Instant instant = zdt.toInstant() ; // Adjust from zoned moment to UTC. Same moment, same point on the timeline, different wall-clock time.
If you must inter-operate with old code not yet updated to java.time, you can convert back and forth. Tip: Try to stay within java.time as much as possible. The legacy classes are an awful mess of poor design.
java.util.Date myJavaUtilDate = java.util.Date.from( instant ) ;
And, going the other direction.
Instant instant = myJavaUtilDate.toInstant() ;
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.
You are looking for a DATA_TYPE TIMESTAMP. You should change your Database if you can.

Choosing between java.util.Date or java.sql.Date

Should I use java.util.Date or java.sql.Date?
I have a VisualFox database and I have retrieved the entities with the IntelliJ Idea wizard using an appropiate jdbc type 4 driver.
The ide (or the driver) has created the date fields as Timestamp. However, the date fields are not timestamps but Date fields, they store year, month and day only.
So I wonder if I should switch to java.util.Date or java.sql.Date. At first glance I thought that java.sql.Date should be the appropiate one, but it has many methods declared as deprecated.
tl;dr
Should I use java.util.Date or java.sql.Date?
Neither.
Both are obsolete as of JDBC 4.2 and later. Use java.time classes instead.
date-only valueFor a database type akin to SQL-standard DATE, use java.time.LocalDate.
LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;
myPreparedStatement.setObject( ld , … ) ;
date with time-of-day in UTC valueFor a database type akin to SQL-standard TIMESTAMP WITH TIME ZONE, use java.time.Instant.
Instant instant = myResultSet.getObject( … , Instant.class ) ;
myPreparedStatement.setObject( instant , … ) ;
Details
The question and other answers seem to be over-thinking the issue. A java.sql.Date is merely a java.util.Date with its time set to 00:00:00.
From the java.sql.Date doc (italicized text is mine)…
Class Date
java.lang.Object
    java.util.Date        ← Inherits from j.u.Date
        java.sql.Date
…
A thin wrapper around a millisecond value that allows JDBC to identify this as an SQL DATE value. A milliseconds value represents the number of milliseconds that have passed since January 1, 1970 00:00:00.000 GMT.  ← Time-of-day set to Zero, midnight GMT/UTC
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.
Date-Only versus Date-Time
The core problem is:
SQLIn SQL, the DATE data type stores a date-only, without a time-of-day.
JAVAIn the badly designed date-time library bundled with the early versions of Java, they failed to include a class to represent a date-only.
Instead of creating a date-only class, the Java team made a terrible hack. They took their date-time class (the misnamed java.util.Date class, containing both date and time) and extended it to have an instance set its time-of-day to midnight UTC, 00:00:00. That hack, that subclass of j.u.Date, is java.sql.Date.
All this hacking, poor design, and misnaming has made a confusing mess.
Which To Use
So when to use which? Simple, after cutting through the confusion.
When reading or writing to a database’s date-only column, use java.sql.Date as it clumsily tries to mask its time-of-day.
Everywhere else in Java, where you need a time-of-day along with your date, use java.util.Date.
When you have a java.sql.Date in hand but need a java.util.Date, simply pass the java.sql.Date. As a subclass, a java.sql.Date is a java.util.Date.
Even Better
In modern Java, you now have a choice of decent date-time libraries to supplant the old and notoriously troublesome java.util.Date, Calendar, SimpleTextFormat, and java.sql.Date classes bundled with Java. The main choices are:
Joda-Time
java.time(inspired by Joda-Time, defined by JSR 310, bundled with Java 8, extended by the ThreeTen-Extra project)
Both offer a LocalDate class to represent a date only, with no time-of-day and no time zone.
A JDBC driver updated to JDBC 4.2 or later can be used to directly exchange java.time objects with the database. Then we can completely abandon the ugly mess that is the date-time classes in the java.util.* and java.sql.* packages.
setObject | getObject
This article published by Oracle explains that the JDBC in Java 8 has been updated transparently to map a SQL DATE value to the new java.time.LocalDate type if you call getObject and setObject methods.
In obtuse language, the bottom of the JDBC 4.2 update spec confirms that article, with new mappings added to the getObject and setObject methods.
myPreparedStatement.setObject( … , myLocalDate ) ;
…and…
LocalDate myLocalDate = myResultSet.getObject( … , LocalDate.class ) ;
Convert
The spec also says new methods have been added to the java.sql.Date class to convert back and forth to java.time.LocalDate.
public java.time.instant toInstant()
public java.time.LocalDate toLocalDate()
public static java.sql.Date valueOf(java.time.LocalDate)
Time Zone
The old java.util.Date, java.sql.Date, and java.sql.Timestamp are always in UTC. The first two (at least) have a time zone buried deep in their source code but is used only under-the-surface such as the equals method, and has no getter/setter.
More confusingly, their toString methods apply the JVM’s current default time zone. So to the naïve programmer it seems like they have a time zone but they do not.
Both the buried time zone and the toString behavior are two of many reasons to avoid these troublesome old legacy classes.
Write your business logic using java.time (Java 8 and later). Where java.time lacks, use Joda-Time. Both java.time and Joda-Time have convenient methods for going back and forth with the old classes where need be.
Replacements:
java.util.Date is replaced by java.time.Instant
java.sql.Timestamp is replaced by java.time.Instant
java.sql.Date is replaced by java.time.LocalDate.
java.sql.Time is replaced by java.time.LocalTime.
The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).
All three java.time.Local… classes are all lacking any concept of time zone or offset-from-UTC.
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.
Well, according to this article you can use javax.sql.Date without #Temporal annotation which can save some coding from you. However java.util.Date is easier to use across your whole application.
So I would use
#Column(name = "date")
#Temporal(TemporalType.DATE)
private java.util.Date date;
In general, I find it advisable to use the java.util.Date, since you can use it anywhere in your program without either converting the type or polluting your application with SQL-specific code.
I am not aware of a scenario where 'java.sql.Date' would be a better fit.
According to Java doc, it is suggested to use appropriate Date type as per underlying database.
However, with Java 8, a rich set of classes under java.time package have been provided and it must be used if application is written with Java 8.
The class javaxjava.sql.Date extends java.util.Date with minor changes for miliseconds container so that it can support the Database DATE type effectively. This, we can save the #Temporal annotation typing from entity class.
However, java.util.Date could be used for better scalability in entire application so that it can be easily used to store time along with date.

java sql date time

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?
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.
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?
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.

Categories

Resources