Gregorian Date to Date - java

This should be quite simple
customerSearch.get("DateOfBirth") where customerSearch is a HashMap<String, Object> and it's a Gregorian Date.
But I need a normal Date object.
I tried
Date dateOfBirth = new Date(
((GregorianCalendar) customerSearch.get("DateOfBirth")).getTimeInMillis());
but said Gregorian Date cannot be cast to Date.
Any help?

tl;dr
( (GregorianCalendar) customerSearch.get( "DateOfBirth" ) ) // Retrieve and cast object of legacy class `GregorianCalendar`.
.toZonedDateTime() // Convert from terrible legacy class to modern *java.time* class.
.toLocalDate() // Extract the date-only portion, omitting time-of-day and time zone.
java.time
You are using, and possibly abusing, terrible date-time classes that were supplanted years ago by the java.time classes defined by JSR 310.
ZonedDateTime replaces GregorianCalendar
Instant replaces java.util.Date
LocalDate replaces java.sql.Date
If you must interoperate with old code not yet updated to java.time, you can convert back-and-forth. Call new conversion methods added to the old classes.
GregorianCalendar gc = customerSearch… ;
ZonedDateTime zdt = gt.toZonedDateTime() ;
If you want just the date without the time-of-day and without the time zone, extract a LocalDate.
LocalDate dateOfBirth = zdt.toLocalDate() ;
If by Date you meant, java.sql.Date class, the above line should be used instead making use of LocalDate.
If by Date you meant java.util.Date, that would be the wrong class to use there. That class represents a moment in UTC. By adjusting from the zoned moment in GregorianCalendar/ZonedDateTime to UTC, you could be changing the date.
Converting
If you need a java.util.Date object to interoperate with old code not yet updated for java.time, you can convert. A java.util.Date represents a moment in UTC, so we need the equivalent in java.time, Instant, also a moment in UTC but with a finer resolution of nanoseconds rather than milliseconds.
We can extract an Instant from our ZonedDateTime seen above. Effectively, this is simply adjusting from a zoned value to a UTC value. Same moment, same point on the timeline, different wall-clock time.
Instant instant = zdt.toInstant() ; // Extract a `Instant`, adjusting from zone to UTC.
Use new conversion methods on the old class.
java.util.Date myJavaUtilDate = java.util.Date.from( instant ) ; // Beware of possible data-loss in the fractional second, truncating from nanos to millis.
If you need go the other direction, from legacy to modern.
Instant instant = myJavaUtilDate.toInstant() ;
Use appropriate types
If you are trying to represent a date-of-birth is is commonly done, with just a date without time-of-day and without zone, then use LocalDate in your map. The classes GregorianCalendar, java.util.Date, and ZonedDateTime all represent a moment, a specific point on the timeline. They should never be used for a date-only.
The java.sql.Date class pretends to be a date-only, but through a terrible design decision as a subclass of java.util.Date actually does indeed carry a time-of-day and offset/zone. This class, as noted above, has been replaced with LocalDate.
normal Date object
There is nothing more “normal” about either java.util.Date or java.sql.Date than any other date-time class.
java.util.Date represents a moment in UTC, always UTC, despite what its terribly designed toString method tells you (a lie). Use java.time.Instant instead when you need a moment in UTC.
java.sql.Date is meant to represent a date-only, but as discussed, actually carries internally a time and zone/offset. Use java.time.LocalDate instead to represent a date rather than a moment.
GregorianCalendar represents a moment as seen in the wall-clock time used by the people of a specific region (a time zone). Instead use ZonedDateTime for this purpose.
java.sql.Timestamp represents a moment in UTC but with a finer resolution of nanoseconds rather than milliseconds. All the moment-related classes in java.time use a resolution of nanoseconds. So for a moment in UTC with a resolution of UTC, use java.time.Instant instead of Timestamp.
As of JDBC 4.2, we can directly exchange java.time classes with a database. So no need to ever touch java.sql.Date or java.sql.Timestamp again for your database work.
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.

There is no java class GregorianDate. Unless it is your own class which if so you didn't mention. So, just in case is Gregorian Date just a regular Date as most of the world today uses Gregorian calendar? So instances of what class does your map holds in your HashMap<String, Object>? If it is just a regular Date then your code should be just:
Date dateOfBirth = (Date)(customerSearch.get("DateOfBirth"));

Related

Converting time to UTC time goes the opposite way

I'm trying to parse an offset time using Java 8 DateTimeFormatter.
I live in EST time which is UTC-5, so when I try to convert
2019-01-22T13:09:54.620-05:00 should be --> 2019-01-22T18:09:54.620
However, with my code, it gets the current time and goes back 5 hours, resulting in 2019-01-22 08:09:54.620
Code:
import java.sql.Timestamp
import java.time._
import java.time.format.DateTimeFormatter
import scala.util.{Failure, Success, Try}
class MyTimeFormatter(parser: DateTimeFormatter) {
def parse(input: String): Try[Timestamp] = {
Try(new Timestamp(Instant.from(parser.withZone(ZoneOffset.UTC).parse(input)).toEpochMilli))
}
}
Test:
new MyTimeFormatter(DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSSxxx")).parse("2019-01-22T13:09:54.620-05:00") shouldEqual Timestamp.valueOf("2019-01-22T18:09:54.620")
where parser is of type DateTimeFormatter and input string is just "2019-01-22T13:09:54.620-05:00"
I want to use this parser.parse method and not with specific temporalAccessors like OffsetDateTime.parse(input, parser) so I can handle all cases like LocalTime, LocalDateTime, ZonedDateTime, OffsetDateTime, etc..
It seems like the code just grabs the time, subtracts the offset, and brands it as UTC instead of calculating the offset with respect to UTC.
Also, is there a way to apply this UTC conversion only if the input format is of ZonedDateTime/OffsetDateTime format? If I input a LocalDateTime (which doesn't have an offset) such as 2017-01-01 12:45:00 the parser will still apply the UTC offset conversion because I told the parser to parse with zone UTC.
tl;dr
Use modern java.time classes. Convert to legacy class only if necessary to work with old code.
Specifically, parse your input string as a OffsetDateTime object, adjust to UTC by extracting an Instant, and lastly, convert to java.sql.Timestamp (only if you must).
java.sql.Timestamp ts = // Avoid using this badly-designed legacy class if at all possible.
Timestamp // You can convert back-and-forth between legacy and modern classes.
.from( // New method added to legacy class to convert from modern class.
OffsetDateTime // Represents a moment with an offset-of-UTC, a number of some hours-minutes-seconds ahead or behind UTC.
.parse( "2019-01-22T13:09:54.620-05:00" ) // Text in standard ISO 8601 format can be parsed by default, without a formatting pattern.
.toInstant() // Adjust from an offset to UTC (an offset of zero) by extracting an `Instant`.
) // Returns a `Timestamp` object. Same moment as both the `OffsetDateTime` and `Instant` objects.
;
See this code run live at IdeOne.com, resulting in:
ts.toString(): 2019-01-22 18:09:54.62
If using JDBC 4.2 or later, skip the Timestamp altogether.
myPreparedStatement.setObject( … , myOffsetDateTime ) ;
Zulu
2019-01-22T13:09:54.620-05:00 should be --> 2019-01-22T18:09:54.620
If you meant that second value to represent a moment in UTC, append the offset-from-UTC to indicate that fact. Either +00:00 or Z (pronounced “Zulu”): 2019-01-22T18:09:54.620Z.
Reporting a moment without an offset-from-UTC or time zone indicator is like reporting an amount of money without a currency indicator.
OffsetDateTime
A string with an offset-from-UTC should be parsed as a OffsetDateTime object.
Your input string happens to comply with the ISO 8601 standard formats for textual date-time values. The java.time classes use ISO 8601 formats by default when parsing/generating strings. So no need to specify a formatting pattern.
OffsetDateTime odt = OffsetDateTime.parse( "2019-01-22T13:09:54.620-05:00" ) ;
Timestamp
Apparently you want a java.sql.Timestamp object. This is one of the terrible date-time classes bundled with the earliest versions of Java. These classes are now legacy, supplanted entirely by the modern java.time classes with the adoption of JSR 310. Avoid these legacy classes whenever possible.
If you must have a Timestamp to interoperate with old code not yet updated to work with java.time, you can convert. To convert, call new methods added to the old classes.
Instant
The java.sql.Timestamp class carries a from( Instant ) method. An Instant is a moment in UTC. To adjust from the offset of our OffsetDateTime to UTC, just extract an Instant.
Instant instant = odt.toInstant() ;
java.sql.Timestamp ts = Timestamp.from( instant ) ;
We have three objects ( odt, instant, & ts ) that all represent the same moment. The first has a different wall-clock time. But all three are the same simultaneous point on the timeline.
JDBC 4.2
As of JDBC 4.2, we can directly exchange java.time objects with the database. So no need to use Timestamp.
myPreparedStatement.setObject( … , odt ) ;
…and…
OffsetDateTime odt = myResultSet.getObject( … , OffsetDateTime.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, 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.
While I cannot reproduce your issue precisely (even with changing my clock to EST), this is what I am observing:
Instant instant = Instant.from(parser.withZone(ZoneOffset.UTC).parse("2019-01-22T13:09:54.620-05:00"));
This is producing the time you would expect (2019-01-22T18:09:54.620Z).
Timestamp ts = new Timestamp(instant.toEpochMilli());
Because this is based on java.util.Date, which displays as your local time.
A better way to convert an Instant to a Timestamp is via the LocalDateTime, like so:
Timestamp ts = Timestamp.valueOf(instant.atZone(ZoneOffset.UTC).toLocalDateTime());

why does Timestamp print difference between run model and debug model in unit test?

java.sql.Date date = java.sql.Date.valueOf("1900-01-01");
//-2209017600000
System.out.println(date.getTime());
java.sql.Timestamp timestamp = new Timestamp(date.getTime());
System.out.println(timestamp);
if directly running in unit test, the result will be 1900-01-01 00:00:00.0
if running with debug in unit test, the result will be 1970-01-01 07:30:00.0
How does it output 1900-01-01 00:00:00.0? Where is it stored?
Why not output 1970-01-01 00:00:00.0 ? becase I saw the comment of Timestamp constructor says milliseconds since January 1, 1970, 00:00:00 GMT. A negative number is the number of milliseconds before January 1, 1970, 00:00:00 GMT.
tl;dr
Avoid the terrible old date-time classes. Use java.time. Poof, all the bizarre behavior you are seeing is gone, and your question is moot.
LocalDate // A class to represent a date-only value, without time-of-day, without time zone. Replaces `java.sql.Date` which only pretends to be date-only but actually has both a time-of-day and a time zone.
.parse( "1900-01-01" ) // Standard ISO 8601 formatted strings are parsed directly by the *java.time* classes.
.atStartOfDay( // Let java.time determine the first moment of a day.
ZoneId.of( "Pacific/Auckland" )
) // Returns a `ZonedDateTime` object.
.toString() // Generates a `String` with text in standard ISO 8601 format, wisely extended by appending the name of the time zone in square brackets.
1900-01-01T00:00+11:30[Pacific/Auckland]
You are torturing yourself with these Questions about the legacy date-time classes. Sun, Oracle, and the JCP community all gave up on those classes years ago when adopting JSR 310. I suggest you do the same.
Never use java.sql.Date
This class is part of the terrible old date-time classes that were supplanted years ago by java.time classes. This java.sql.Date in particular is especially badly designed. It extends java.util.Date while the documentation tells us to ignore the fact of that inheritance. As a subclass, it pretends to be a date-only value but actually has a time-of-day inherited from the other Date, which in turn is misnamed having both a date and a time-of-day. In addition, a time zone lurks deep within these classes, though inaccessible without any getter or setter method. Confusing? Yes, an awful mess. Never use java.sql.Date.
Instead, use java.time.LocalDate.
LocalDate ld = LocalDate.parse( "1900-01-01" ) ;
ld.toString(): 1900-01-01
Never use java.sql.Timestamp
As with java.sql.Date, the java.sql.Timestamp class was replaced years ago. Use java.time.Instant. If handed a Timestamp, immediately convert using the new conversion methods added to the old classes.
If you want the first moment of the day for a particular date, let LocalDate determine that. The first moment is not always 00:00:00, so never assume that. Specify the time zone of the region whose people use the particular wall-clock time you care about.
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( "Pacific/Auckland" ) ;
ZonedDateTime zdt = ld.atStartOfDay( z ) ;
To see the same moment in UTC, extract a Instant. 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).
Instant instant = zdt.toInstant() ;
If you wanted the first moment of the day in UTC, use OffsetDateTime.
OffsetDateTime odt = ld.atOffset( ZoneOffset.UTC ) ;
Conversion
If you must interoperate with old code not yet updated to java.time classes, you can convert back-and-forth. Call new methods added to the old classes.
java.sql.Timestamp ts = Timestamp.from( instant ) ;
…and…
Instant instant = ts.toInstant() ;
Ditto for date.
java.sql.Date d = java.sql.Date.valueOf( ld ) ;
…and…
LocalDate ld = d.toLocalDate() ;
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.

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.

Java8 java.util.Date conversion to java.time.ZonedDateTime

I am getting the following exception while trying to convert java.util.Date to java.time.LocalDate.
java.time.DateTimeException: Unable to obtain ZonedDateTime from TemporalAccessor: 2014-08-19T05:28:16.768Z of type java.time.Instant
The code is as follow:
public static Date getNearestQuarterStartDate(Date calculateFromDate){
int[] quaterStartMonths={1,4,7,10};
Date startDate=null;
ZonedDateTime d=ZonedDateTime.from(calculateFromDate.toInstant());
int frmDateMonth=d.getMonth().getValue();
Is there something wrong in the way I am using the ZonedDateTime class?
As per documentation, this should convert a java.util.Date object to ZonedDateTime. The date format above is standard Date?
Do I have to fallback on Joda time?
If someone could provide some suggestion, it would be great.
To transform an Instant to a ZonedDateTime, ZonedDateTime offers the method ZonedDateTime.ofInstant(Instant, ZoneId). So
So, assuming you want a ZonedDateTime in the default timezone, your code should be
ZonedDateTime d = ZonedDateTime.ofInstant(calculateFromDate.toInstant(),
ZoneId.systemDefault());
To obtain a ZonedDateTime from a Date you can use:
calculateFromDate.toInstant().atZone(ZoneId.systemDefault())
You can then call the toLocalDate method if you need a LocalDate. See also: Convert java.util.Date to java.time.LocalDate
The Answer by assylias and the Answer by JB Nizet are both correct:
Call the new conversion method added to the legacy class, java.util.Date::toInstant.
Call Instant::atZone, passing a ZoneId, resulting in a ZonedDateTime.
But your code example is aimed at quarters. For that, read on.
Quarters
No need to roll-your-own handling of quarters. Use a class already written and tested.
org.threeten.extra.YearQuarter
The java.time classes are extended by the ThreeTen-Extra project. Among the many handy classes provided in that library you will find Quarter and YearQuarter.
First get your ZonedDateTime.
ZonedId z = ZoneID.of( "Africa/Tunis" ) ;
ZonedDateTime zdt = myJavaUtilDate.toInstant().atZone( z ) ;
Determine the year-quarter for that particular date.
YearQuarter yq = YearQuarter.from( zdt ) ;
Next we need the start date of that quarter.
LocalDate quarterStart = yq.atDay( 1 ) ;
While I do not necessarily recommend doing so, you could use a single line of code rather than implement a method.
LocalDate quarterStart = // Represent a date-only, without time-of-day and without time zone.
YearQuarter // Represent a specific quarter using the ThreeTen-Extra class `org.threeten.extra.YearQuarter`.
.from( // Given a moment, determine its year-quarter.
myJavaUtilDate // Terrible legacy class `java.util.Date` represents a moment in UTC as a count of milliseconds since the epoch of 1970-01-01T00:00:00Z. Avoid using this class if at all possible.
.toInstant() // New method on old class to convert from legacy to modern. `Instant` represents a moment in UTC as a count of nanoseconds since the epoch of 1970-01-01T00:00:00Z.
.atZone( // Adjust from UTC to the wall-clock time used by the people of a particular region (a time zone). Same moment, same point on the timeline, different wall-clock time.
ZoneID.of( "Africa/Tunis" ) // Specify a time zone using proper `Continent/Region` format. Never use 2-4 letter pseudo-zone such as `PST` or `EST` or `IST`.
) // Returns a `ZonedDateTime` object.
) // Returns a `YearQuarter` object.
.atDay( 1 ) // Returns a `LocalDate` object, the first day of the quarter.
;
By the way, if you can phase out your use of java.util.Date altogether, do so. It is a terrible class, along with its siblings such as Calendar. Use Date only where you must, when you are interfacing with old code not yet updated to java.time.
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 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 answer didn't work for me on Java 10 storing util.Date in UTC.
Date.toInstant() seems to convert the EpochMillis into the local time zone of the server.
ZDT.ofInstant(instant, zoneId) and instant.atZone(zoneId) seem to just tag on a TZ on the instant, but it's already messed up with.
I couldn't find a way to prevent Date.toInstant() from messing with the UTC time with the system time zone.
The only way I found to work around this was to go through the sql.Timestamp class:
new java.sql.Timestamp(date.getTime()).toLocalDateTime()
.atZone(ZoneId.of("UTC"))
.withZoneSameInstant(desiredTZ)

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.

Categories