Create jodatime LocalDate from java.sql.Time - java

I'm new to joda-time and I didn't find anywhere examples to do some simple things.
I want to make an object where to save a time value read from a table in a database (a java.sql.Time - e.g. "18:30:00") I don't care about time zone, so I think that I need LocalDate. But the problem is that I couldn't create a LocalDate object based on that Time object.
I tried with no success LocalDate.fromDateFields(), DateTimeParser.parseInto(), DateTimeParser.parseDateTime().
EDIT:
I should have used LocalTime.
These work:
java.sql.Time time = Time.valueOf("18:30:00");
LocalTime lt1 = LocalTime.fromDateFields(time);
LocalTime lt2 = new LocalTime(time);

According to the documentation, you should be able to construct a LocalDate directly by passing it a java.util.Date as the sole constructor argument. Since a java.sql.Time extends java.util.Date, you should be able to
final LocalDate ld = new LocalDate(mySqlTime);
This works for me:
System.out.println(new LocalDate(Time.valueOf("18:30:00")));
On the other hand, it's not a meaningful thing to do, since you'll always get January 1, 1970. But I imagine you know what you're doing.

Related

UnsupportedOperationException - Why can't you call toInstant() on a java.sql.Date?

The java.util.Date class has a method called toInstant() that converts the Date instance to a java.time.Instant.
The java.sql.Date class extends the java.util.Date class, but when I attempt to call toInstant() on a java.sql.Date, I receive an UnsupportedOperationException.
Why is toInstant() an unsupported operation on java.sql.Date?
And what is the "correct" way to convert a java.sql.Date to a java.time.Instant?
The correct mapping between java.sql.Date and java.time is LocalDate:
LocalDate date = sqlDate.toLocalDate();
If you really must, you can then derive an Instant, although the extra information (time) will be arbitrary. For example:
Instant i = date.atStartOfDay(ZoneOffset.UTC).toInstant();
According to the JavaDoc
Since sql.Date does not have a time component, there is no possibility to convert it to time.Instant
This method always throws an UnsupportedOperationException and should
not be used because SQL Date values do not have a time component.
java.sql.Date supports only Date components (date, month, year). It does NOT support time components (hour, minute, second, millisecond). toInstant requires both Date and Time components, so toInstant on java.sql.Date instance throws UnsupportedOperationException exception.
toInstant Java doc
This method always throws an
UnsupportedOperationException and should not be used because SQL Date
values do not have a time component.
java.util.Date OR java.sql.Timestamp has both Date/Time components, so toInstant() works!
You can do like this:
// Time is 00:00:00.000
new java.util.Date(sqlDate.getTime()).toInstant()
Updated:
Instant.ofEpochMilli(sqlDate.getTime());
// and
new java.util.Date(sqlDate.getTime()).toInstant();
will return the same result because the toInstant() method calls Instant.ofEpochMilli(getTime()) internally.
public Instant toInstant() {
return Instant.ofEpochMilli(getTime());
}
The answers given so far until now concentrate on the detail that java.sql.Date has no time information. That is correct but not the real or sufficient reason why this type cannot offer a direct conversion to Instant. Unfortunatly the documentation of Java-8 does make the same mistake to let users think the problem is just because of missing time information.
Conceptually, the type java.sql.Date represents a local type. It models a calendar date which can be different in any region of our globe. But an Instant is the same on our globe around. So users need a timezone or a timezone offset to do the conversion.
Tragically, the type java.sql.Date inherits from java.util.Date which is a global type (instant-like). However, this inheritance really denotes implementation inheritance, and not type inheritance. One more reason to consider the design of these old JDBC-classes to be broken. Therefore it is indeed possible to use the hack to wrap the java.sql.Date via its method getTime() inside an instance of java.util.Date which finally allows direct conversion to an instant. But: This conversion implicitly uses the default timezone of the system.
So how to correctly convert in a pedantic way? Let's consider the documentation of Java-8 again which here points into the right direction:
java.sql.Date sqlDate = ...;
LocalDate calendarDate = sqlDate.toLocalDate();
ZonedDateTime zdt = calendarDate.atStartOfDay(ZoneId.of("Europe/Paris"));
Instant instant = zdt.toInstant();
If you don't have time in your Date - convert it to millis:
Instant.ofEpochMilli(date.getTime())
.atZone(ZoneId.systemDefault())
.toLocalDate();
The implementation of java.sql.Date (imho) is really not perfect.
In order to convert java.util.Date to LocalDate the web is full of code blocks like this:
dateToConvert.toInstant()
.atZone(ZoneId.systemDefault())
.toLocalDate();
above code works perfect for java.util.Date because of the way it implements toInstant(). (As expected " return Instant.ofEpochMilli(getTime())")
As java.sql.Date is a subclass of java.util.Date code operating on the Date object might now know it operates on a java.sql.Date. (Hey - that's one aspect of object orientation, right??). So if it gets java.util.Date code works well, if it gets java.sql.Date it fails.
Code could now explicitly check for the Date type, and then (if it operates on java.sql.Date) it could do a downcast to java.sql.Date and use the toLocalDate() method. Needless to say, that this is ugly.
As developer I'd like to have one method working properly - toLocalDate (internally using deprectated methods) only exists for java.sql.Date so cannot be used on java.util.Date, and toInstant fails on java.sql.Date.
I changed my "Date to LocalDate" conversion code to this:
public static LocalDate asLocalDate(java.util.Date date) {
return date == null ? null : LocalDate.ofInstant(Instant.ofEpochMilli(date.getTime()), ZoneId.systemDefault());
}
This works independent of the date type passed in. Basically it means "dont call java.util.Date.toInstant() as you might get a java.sql.Date, which then breaks your code.
I really don't understand why they implement such traps on purpose within the JDK.

Convert LocalTime (Java 8) to Date

I'm trying to convert a java.time.LocalTime object to java.util.Date but can't find any suitable method. What's the correct way to do this?
Is there any reason why java doesn't seem to ship with a built-in direct conversion method?
To possible duplicates:
How to convert joda time - Doesn't work for me, probably I'm missing some "joda" libraries?
How to convert Date to LocalTime? - This adresses conversion the other way around.
LocalTime actually can't be converted to a Date, because it only contains the time part of DateTime. Like 11:00. But no day is known. You have to supply it manually:
LocalTime lt = ...;
Instant instant = lt.atDate(LocalDate.of(A_YEAR, A_MONTH, A_DAY)).
atZone(ZoneId.systemDefault()).toInstant();
Date time = Date.from(instant);
Here's a blog post which explains all the conversions between the new and the old API.
There's no simple built-in conversion method, because these APIs approach the idea of date and time in completely different way.
LocalTime lt = ...;
Instant instant = lt.atDate(LocalDate.of(A_YEAR, A_MONTH, A_DAY)).
atZone(ZoneId.systemDefault()).toInstant();
Date time = Date.from(instant);
From :
http://blog.progs.be/542/date-to-java-time
I added the data (hour, minute, second) one by one (from localtime to date):
reta.setHours(vol.getRetard().getHour());
reta.setMinutes(vol.getRetard().getMinute());
reta.setSeconds(vol.getRetard().getSecond());
Note :
reta: Date veriabble ;
vol.getRetard (): localtime variable
As others have said, it’s a problematic question in that a LocalTime and a Date really represent quite different and almost unrelated concepts. A LocalTime is a time of day without time zone, such as 19:45 (or 7:45 PM). A Date is a point on the time line; if it happens to coincide with 19:45 on some date in some time zone, it will not in other time zones.
I believe that the conventional way of misusing (indeed) a Date for an hour of day is setting it to that time of day on January 1, 1970 in the default time zone of the JVM. This practice carries all of the liabilities already mentioned. In particular the JVM default time zone setting can be changed at any time from another part of your program or any other program running in the same JVM. This means that a completely unrelated program may suddenly cause your Date to indicate a different time of day than the one you had initialized it to.
There’s nothing better we can do, so here goes:
LocalTime time = LocalTime.of(11, 0);
Instant timeOnEpochDayInDefaultTimeZone = LocalDate.EPOCH
.atTime(time)
.atZone(ZoneId.systemDefault())
.toInstant();
Date oldfashionedDateObject = Date.from(timeOnEpochDayInDefaultTimeZone);
System.out.println(oldfashionedDateObject);
In my time zone output from this snippet is:
Thu Jan 01 11:00:00 CET 1970
Here is another approach:
We can add a LocalDate to the LocalTime in order to make it a LocalDateTime and then convert it to Date using the valueOf method of java.sql.Timestamp like this:
LocalTime localTime = LocalTime.now();
Date date = java.sql.Timestamp.valueOf(localTime.atDate(LocalDate.now()));
As #Dariusz said, we cannot convert LocalTime to Date directly as it contains only time part but Date must contain all the value along with the timeZone.
In order to get the date part, we can use LocalDate.now(). It will give us LocalDate object with today's date.
Now, we have both LocalDate and LocalTime, we can now use the LocalDateTime.of(date: LocalDate, time: LocalTime) or localTime.atDate(date: LocalDate) to get the LocalDateTime object.
And now we can convert the LocalDateTime to Date using below kotlin extension function.
fun LocalDateTime.toDate(): Date {
return Date.from(this.atZone(ZoneId.systemDefault()).toInstant())
}

What is the most efficient way to create Date Object in Java

I am creating Date object in java.
First way:
By using Calender
Date today = Calendar.getInstance().getTime();
Second way:
with Date class
Date today1 = new Date();
Which one is most effective way here?
Since Java 8 you should go for LocalDateTime or LocalDate:
LocalDateTime timePoint = LocalDateTime.now(
); // The current date and time
LocalDate.of(2012, Month.DECEMBER, 12); // from values
LocalDate theDate = timePoint.toLocalDate(); // or
theDate = LocalDate.now(); //
Fromt the documentation:
[For example, the existing classes (such as java.util.Date and
SimpleDateFormatter) aren’t thread-safe, leading to potential
concurrency issues for users—not something the average developer would
expect to deal with when writing date-handling code.
Some of the date and time classes also exhibit quite poor API design.
For example, years in java.util.Date start at 1900, months start at 1,
and days start at 0—not very intuitive.]1
If you have to decide between the two. Take the new Date(). As the Calendar.getInstance().getTime() would create a Calendar instance which you could not use afterwards.
You can use this too!
Date newDate = new GregorianCalendar(year, month, day).getTime();
Within your options, I will prefer the first alternative.

Java - Creating a Calendar without a TimeZone

I would like to start by saying that I've read several threads similar to this one, but none of them really solved my problem.
I would also like to state that I've tried to use SimpleDateFormat and joda.DateTime without any success.
The problem is the following:
I have a Calendar object that holds the information about a specific date: 2008-04-30T00:00:00Z
When using the calendar.getTime() method I can get different results because I know that that method is looking for the local value
Thus:
UK: 2008-04-30T01:00:00.000+0100
US: 2008-04-30T20:00:00.000-0400
But I would like to get a Date object that holds just the Date and Time values "2008-04-30T00:00:00" ignoring completely any timezone.
How can I do that?
As I mentioned before I tried to use
SimpleDateFormat sf = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss")
but I always end up with the same results.
Any help would be really appreciated
Cheers.
Found out that you can clear the Timezone by using code below:
Calendar cal = Calendar.getInstance();
cal.clear(Calendar.ZONE_OFFSET);
Calendars and Dates mean nothing without a TimeZone.
Calendars and dates cannot exist without a timezone.
You can't ignore completely any timezone.
You can create a Calendar for Greenwich Mean Time (offset zero) like this:
TimeZone zone = TimeZone.getTimeZone("Etc/GMT");
Calendar cal = Calendar.getInstance(zone);
This represents a Date/Calendar that is only meaningful in the GMT timezone.
It sounds like you want a timestamp, which represents an instant in time.
As others have pointed out, Calendar and Date objects cannot exist without a time zone.
I believe you may want to use the LocalDateTime class introduced in Java 8 with the new time API:
LocalDateTime literal = LocalDateTime.of(2008, 4, 30, 0, 0, 0);
LocalDateTime parsed = LocalDateTime.parse("2008-04-30T00:00:00"); // ISO-8601 by default
Assert.assertEquals(literal, parsed);
Do you use a standard constructor for initializing Calendar? What if you used the constructor which allows to specify the time zone and locale?
protected Calendar(TimeZone zone, Locale aLocale)
Old, but still incorrect.
"When using the calendar.getTime() method I can get different results because I know that that method is looking for the local value"
That is a misconception. getTime() will get the Milliseconds only. Countet as GMT.
ONLY during formatting of the Output the time zone becomes relevant. Sind the original poster did not show the code, it can not be decided, where the error occurs.

Converting joda LocalTime to sql Time

I want to convert a LocalTime object to a java.sql.Time object.
java.sql.Time time = new java.sql.Time(new LocalTime(1,0,0,0).getMillisOfDay());
System.out.println(time); //20:00:00
The above code, instead of creating a Time object with a value equal to 01:00:00, creates an object with a time of 20:00:00. The local time is eastern time.
What steps should I take?
Time(..) accepts a timestamp starting from 1970. So you should pass that:
new Time(new LocalTime(...).toDateTimeToday().getMillis())
I consider the currently accepted answer to be incorrect. Although java.sql.Time implies that its date fields are set to 1970-1-1, this is not true. If you use the conversion
new java.sql.Time(new LocalTime(...).toDateTimeToday().getMillis())
then the internal millesecond representation of the java.sql.Time object will reflect today's date. This leads to unexpected behavior when comparing java.sql.Time objects.
Comparisons are performed on the millisecond value, and if the underlying dates are different, the time fields are irrelevant to the comparison result
A better method, is to explicitly work with the time-fields, using the deprecated constructor and methods in java.sql.Time:
LocalTime localTime = new LocalTime(1,0,0,0);
java.sql.Time sqlTime = new java.sql.Time(localTime.getHourOfDay(), localTime.getMinuteOfHour(), localTime.getSecondOfMinute())
Similarly, in the other direction
java.sql.Time sqlTime = new java.sql.Time(1,0,0);
LocalTime localTime = new LocalTime(sqlTime.getHours(), sqlTime.getMinues(), sqlTime.getSeconds());
This seems like a hole in the Joda Time API. Right now getLocalMillis() is protected, but that's exactly the method I'd want to use.
However, if you want to avoid deprecated methods, you can figure out time on January 1, 1970:
LocalTime lt = new LocalTime(1, 23, 45, 678);
long millis = lt.toDateTimeToday().withDate(1970, 1, 1).getMillis()
java.sql.Time time = new java.sql.Time(millis);
This seems to work. Interestingly, I tried figuring out the millis by multiplying the values of the fields out. That produced the right long value, but when I passed it to the Time constructor, something weird happened with the time zone. (I think, at least. The Time value ended up five hours before the value I passed in, and I'm on Eastern Daylight Time, so I think that's what happened.)
i found another way to convert the java.time.LocalTime to java.time.LocalTime
LocalTime localTime = LocalTime.now();
Time time = Time.valueOf(localTime);

Categories