How convert LocalDate to ChronoZonedDateTime? - java

In the code bellow, i'm getting an error in my "if" comparisson. The message says "isBefore(java.time.chrono.ChronoZonedDateTime<?>) in ChronoZonedDateTime cannot be applied to (java.time.LocalDate)". How convert LocalDate to ChronoZonedDateTime?
LocalDate taxBegin = tax.getBeginAt();
if(contract.getBeginAt().isBefore(taxBegin)){
//do something
}
I tried wrapping like ChronoZonedDateTime.from(taxBegin) but didn't work, it gave me "DateTimeException: Unable to obtain ZoneId from TemporalAccessor: 2019-12-01 of type java.time.LocalDat"

In order to convert a ZonedDateTime object into a LocalDate, you can use toLocalDate() method. Thus, the following code should work for you:
LocalDate taxBegin = tax.getBeginAt();
if(contract.getBeginAt().toLocalDate().isBefore(taxBegin)){
//do something
}
Check https://howtodoinjava.com/java/date-time/localdate-zoneddatetime-conversion/ for an example of converting between ZonedDateTime and LocalDate.

You could use atStartOfDay(ZoneId)
I.E.
public static ZonedDateTime convertLocalDate(final LocalDate ld) {
return ld.atStartOfDay(ZoneId.systemDefault());
}
You could either use ZoneId.systemDefault() or ZoneOffset.UTC.
Documentation states: If the zone ID is a ZoneOffset, then the result always has a time of midnight.
So your code'll be
if (contract.getBeginAt().isBefore(convertLocalDate(taxBegin))) {
//do something
}
If you want to convert it to a specific time, you should use
taxBegin.atTime(LocalTime).atZone(ZoneId).

If you had LocalDateTime instead of LocalDate, it would have worked just fine. But since you have LocalDate, you lost time. Now the only way is to convert the existing ChronoZonedDateTime to LocalDate and compare. However, this may not always work if the time zones are different.
Same timezone:
contract.getBeginAt().toLocalDate().isBefore(taxBegin)

Related

How to convert an Epoch timestamp into an object of type java.time.Instant Accurately in Java?

I have a Spring Boot JPA Application that interacts with a 3rd party API.
The response payload of the API has a key
"created_at": 1591988071
I need to parse this field into java.time.Instant so that I can do some comparisons with the value I have in the Database.
I have learned that I can use the below mentioned piece of code.
Instant instant = Instant.ofEpochSecond(1591988071);
Output :
2020-06-12T18:54:31Z
But to be honest, this output is off by a couple of hours.
I found another approach, wherein if I use
String dateAsText = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss")
.format(new Date(1591988071 * 1000L));
System.out.println(dateAsText);
I get the desired output but in String format.
2020-06-13 00:24:31
Can someone tell me how to obtain the above String output but converted into type java.time.Instant ?
It is likely you're in a different timezone than UTC. The instant is giving you time in UTC. That's indicated by the Z at the end of your first output.
You would want to look at atZone
Instant instant = Instant.ofEpochSecond(1591988071);
System.out.println(instant);
final ZonedDateTime losAngeles = instant.atZone(ZoneId.of("America/Los_Angeles"));
System.out.println(losAngeles);
final ZonedDateTime mumbai = instant.atZone(ZoneId.of("UTC+0530"));
System.out.println(mumbai);
This gives you something you might expect
2020-06-12T18:54:31Z
2020-06-12T11:54:31-07:00[America/Los_Angeles]
2020-06-13T00:24:31+05:30[UTC+05:30]

Java date handling in improper format

Firstly, I'm a C# dev learning Java. I'm converting a program I wrote in C# as an exercise and am having problems with parsing a date being submitted from an html form. The form is sent as an email and the java program reads the emails and parses the body. I have a drop down calendar for my peeps to select a date from but there's always some jerk who has to type it in and mess everything up. Currently I am doing this in my code:
public void SetDatePlayed(String datePlayed)
{
this.datePlayed = LocalDate.parse(datePlayed);
}
datePlayed being passed in is a string usually formatted as yyyy-MM-dd but of course someone typed in 3/7 instead of using the calendar drop down on the form. this.datePlayed is a LocalDate. In C# I would just end up with a date that assumed 2020 for the year - no problem. LocalDate really wants it in the yyyy-MM-dd format and I don't know what the best practice here is with Java. I've been googling it all morning and haven't come across this as being an issue for anyone else. I don't care if I'm using LocalDate but I do need it to be a date datatype so I can do date checks, sorts, searches, etc later on.
You can use DateTimeFormatterBuilder and parseDefaulting() to supply default value for the year.
Building on the answer by Sweeper, it can be done like this:
static LocalDate parseLoosely(String text) {
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
.appendPattern("[uuuu-M-d][M/d/uuuu][M/d]")
.parseDefaulting(ChronoField.YEAR, Year.now().getValue())
.toFormatter();
return LocalDate.parse(text, fmt);
}
Warning: Do not cache the formatter in e.g. a static field, since it snapshots the year, if the program might be running across New Year's Eve, which a webapp would, unless you add logic to make the cache auto-refresh on year change.
Test
System.out.println(parseLoosely("2019-04-07"));
System.out.println(parseLoosely("2019-4-7"));
System.out.println(parseLoosely("4/7/2019"));
System.out.println(parseLoosely("4/7"));
Output
2019-04-07
2019-04-07
2019-04-07
2020-04-07
I see two possible interpretations of your question. I'm not sure which one it is, so I'll answer both.
How do I parse a date string in a format that has no year, such as M/d (3/7), to a LocalDate?
You don't. A LocalDate by definition must have year, month, and day. If you only have a month and a day, that's a MonthDay:
MonthDay md = MonthDay.parse("3/7", DateTimeFormatter.ofPattern("M/d"));
If you want the current year added to it, you can do it later:
LocalDate ld = md.atYear(Year.now(/*optionally insert time zone*/).getValue());
How do I handle both yyyy-MM-dd and M/d patterns?
Here's one way: create a DateTimeFormatter that recognises both patterns, parse the string to a TemporalAccessor, check if the TemporalAccessor supports the "year" field:
TemporalAccessor ta = DateTimeFormatter.ofPattern("[M/d][yyyy-MM-dd]").parse("3/7");
if (ta.isSupported(ChronoField.YEAR_OF_ERA)) { // yyyy-MM-dd
LocalDate ld = LocalDate.from(ta);
} else if (ta.isSupported(ChronoField.MONTH_OF_YEAR)) { // M/d
MonthDay md = MonthDay.from(ta);
} else {
// user has entered an empty string, handle error...
}

get tomorrow date 1:00pm in UNIX timestrap

Can't find any solution how to get tomorrow's date 13:00.
For example: today is 16.01.2019, I need to find how in unix timestrap is 17.01.2019 13:00.
tried this:
LocalDateTime tomorrowWithTime =
LocalDateTime.of(LocalDate.now().plusDays(1), 13:00);
to set manually 13:00, add it to tomorrows date and then convert to unix timestrap, but no luck :(
You were very close to it. To get the LocalDateTime it's
LocalDateTime tomorrowWithTime = LocalDateTime.of(LocalDate.now().plusDays(1), LocalTime.of(13, 0));
Then to convert it to unix timestamp please have a look at this question. In summary you have to give a ZoneId: (to give a working answer I'll use your system zoneId):
ZoneId zoneId = ZoneId.systemDefault(); //Or the appropriate zone
long timestamp = tomorrowWithTime.atZone(zoneId).toEpochSecond();
By the way, if your issue was that you didn't know what to give as parameters to LocalDateTime.of(), your first reflex should be to have a look at the API to see what parameters it accepts.

JDK8 adjust time of a java.time.Instant

I'm trying to adjust the time of a java.time.Instant.
I tried this code:
Instant validFrom = //from my method parameter
validFrom = validFrom.with(ChronoField.HOUR_OF_DAY, 19).with(ChronoField.MINUTE_OF_DAY, 00)
.with(ChronoField.SECOND_OF_DAY, 00).with(ChronoField.MILLI_OF_DAY, 00);
But I've an exception:
java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: HourOfDay
at java.time.Instant.with(Instant.java:720)
This is quite expected reading the documentation and checking the source code.
It's not really clear to me why I can't do that. Is there another way to to this operation without incurring in many conversions?
This is because Instant has no timezone information. 19:00 hours doesn't represent anything useful, unless you attach a timezone to it.
You can convert it to a ZonedDateTime object, and then convert it back to an Instant like this:
public void testInstant(){
Instant now = Instant.now();
ZonedDateTime utc = now.atZone(ZoneId.of("UTC"));
ZonedDateTime zonedDateTime = utc.withHour(19)
.withMinute(0)
.withSecond(0);
Instant instant = zonedDateTime.toInstant();
}

Joda DateTime,, Formatting, and Mysql Timestamp

After a week of going through so many examples, and moving from Java Date,
to Calendar, to Joda. I have decided to seek help from other sources.
The problem:
Our table has two fields Date (Timestamp), and TZ (String). The idea is to store
the user's UTC in timestamp, and timezone, well, you get the idea. So basically
we think in UTC, and present the user with the time converted to their
timezone on the front end (ie, using the value store in table.TZ)
Another requirement is to use the proper Object (Date, DateTime whatever).
And not pass a String representation of the date around. The best would
be a valid Long that will be correctly translated by MySQL, without having
to use the FROM_UNIXTIME mysql function in our query.
Code we are using:
public DateTime convertTimezone(LocalDateTime date, DateTimeZone srcTZ, DateTimeZone dstTZ, Locale l) {
DateTimeFormatter formatter = DateTimeFormat.forPattern("yyyy-MM-dd HH:mm:ss").withLocale(l);
DateTime srcDateTime = date.toDateTime(srcTZ);
DateTime dstDateTime = srcDateTime.toDateTime(dstTZ);
System.out.println(formatter.print(dstDateTime));
System.out.println(formatter.parseDateTime(dstDateTime.toString()));
return formatter.parseDateTime(formatter.print(dstDateTime));
}
The String output is exactly what we need (ie UTC time, 2013-08-23 18:19:12),
but the formatter.parseDateTime(dstDateTime.toString() is crashing with the following
error. Probably because of the UTC timezone independent info, and milleseconds?:
Exception in thread "main" java.lang.IllegalArgumentException: Invalid format: "2013-08- 23T18:19:12.515Z" is malformed at "T18:19:12.515Z"
at org.joda.time.format.DateTimeFormatter.parseDateTime(DateTimeFormatter.java:873)
at com.example.business.rate.RateDeck.convertTimezone(RateDeck.java:75)
at com.example.business.rate.RateDeck.WriteData(RateDeck.java:143)
at com.example.business.rate.RateDeck.main(RateDeck.java:64)
Search engine enriched question:
How to format UTC for Joda DateTime.
PS My first SO post, and it feels nice? :)
Thanks in Advance,
The new fixed version:
public Timestamp convertTimezone(LocalDateTime date, DateTimeZone srcTZ, DateTimeZone dstTZ, Locale l) {
DateTime srcDateTime = date.toDateTime(srcTZ);
DateTime dstDateTime = srcDateTime.toDateTime(dstTZ);
return new Timestamp(dstDateTime.getMillis());
}
Nick.
It's simply crashing because the format of the parsed string doesn't match with the format of the formatter.
The formatter parses using the format yyyy-MM-dd HH:mm:ss, and the toString() method of DateTime formats the date it using (as documented) the ISO8601 format (yyyy-MM-ddTHH:mm:ss.SSSZZ).

Categories