How to convert from Instant to LocalDate - java-8

I have an Instant coming from a source that should, according to the specs, be a LocalDate, but don't see any methods in the LocalDate class to convert the Instant to a LocalDate.
What is the best way to do this?

Java 9+
LocalDate.ofInstant(...) arrived in Java 9.
Instant instant = Instant.parse("2020-01-23T00:00:00Z");
ZoneId zone = ZoneId.of("America/Edmonton");
LocalDate date = LocalDate.ofInstant(instant, zone);
See code run live at IdeOne.com.
Notice the date is 22nd rather than 23rd as that time zone uses an offset several hours before UTC.
2020-01-22
Java 8
If you are using Java 8, then you could use ZonedDateTime's toLocalDate() method:
yourInstant.atZone(yourZoneId).toLocalDate()

Other answers provided the mechanics for the transformation, but I wanted to add some background on the meaning of such transformation which hopefully helps explain why it works the way it works.
LocalDate and Instant seem similar – they both hold date(/time) information without the time zone information. However, they have quite a different meaning.
Instant represents a point in time unambiguously. The representation does not explicitly contain any time zone, but implicitly it refers to the UTC time line.
LocalDateTime (and LocalDate) is ambiguous, because it represents a point in the local timeline, which implicitly refers to the local time zone.
So, in order to correctly transform an Instant into a LocalDateTime (conceptually – some of these steps are bundled together into a single operation in the implementation) you need to:
1. convert the Instant into a ZonedDateTime by applying the UTC time zone info
2. change the time zone from UTC to the local time zone (which implies applying the relevant time zone offset) which gives you another ZonedDateTime (with different time zone)
3. convert the ZonedDateTime into a LocalDateTime which makes the time zone implicit (local) by removing the time zone info.
Finally, you can drop the time-part of LocalDateTime and end up with the LocalDate.

If using java 8 you can do the following
Instant instantOfNow = Instant.now();
LocalDate localDate
= LocalDateTime.ofInstant(instantOfNow, ZoneOffset.UTC).toLocalDate();

You need to ask yourself at what zone offset you want to transform it to most probably and when you know the answer to that:
LocalDate.ofInstant(yourInstant, yourZoneOffSet)
EDIT
just realized that this is only possible since java-9, for a pre-java9 see the other answer

Complete running example, Java 8 compatible:
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
class Scratch {
public static void main(String[] args) {
Instant now = Instant.now();
LocalDateTime ldt = now.atZone(ZoneId.systemDefault()).toLocalDateTime();
System.out.println(ldt);
}
}

Instant instant = Instant.now();
LocalDate localDate = LocalDate.ofInstant(instant, ZoneOffset.UTC);
the above code worked for me.

Related

Does anyone know what TimezoneOffset does on LuisPredictionOptions?

I'm sending LUIS a query that is based on a time value (e.g. "what is the time 10 minutes from now" - just an example). I want the time to come back in the local timezone, so on the LuisPredictionOptions object (C#) I set the TimezoneOffset (as an example I set it to 2 hours ahead, or 120 minutes).
In Fiddler I can see when it calls the LUIS endpoint it's correctly adding "timezoneOffset=120.0".
However, the timezone comes back as UTC - it doesn't matter whether the timezoneOffset is set, or even what it is set to, the time always comes back UTC, using the builtin datetimeV2 entity.
Does anyone know what the TimezoneOffset property is for? Am I just using it incorrectly? Is there another way perhaps to get a local time from LUIS?
[Update]: Here are some examples: https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/[AppId]?verbose=true&timezoneOffset=0&subscription-key=[subscriptionkey]&q=/luis/v2.0/apps/c1be57f4-3850-489e-8266-db376b82c011?timezoneOffset=120&log=true
https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/[AppId]?verbose=true&timezoneOffset=0&subscription-key=[subscriptionkey]&q=/luis/v2.0/apps/c1be57f4-3850-489e-8266-db376b82c011?timezoneOffset=240&log=true
and I'm trying the following example utterance: "in 10 minutes".
When I do this, the timex is in UTC (e.g. timex=2020-01-11T16:08:25) and the "value" comes back with the same value, minus the "T", as follows: value=2020-01-11 16:08:25
I could understand perhaps if the timex is in UTC, but then possibly "value" should be adjusted by the timezoneOffset?
It looks like there's an incorrect question mark in your URL, right before timezoneOffset.
Using the same query I was able to get the expected behavior, where the returned value is different by 10 minutes.
Which SDK are you using? Perhaps you're using the V3 Runtime SDK which uses the V3 endpoint that doesn't use timeZoneOffset but instead uses datetimeReference, and need to use the V2 Runtime SDK instead.
https://westus.api.cognitive.microsoft.com/luis/v2.0/apps/[app-id]?verbose=true&timezoneOffset=10&subscription-key=[key]&q=in 10 minutes
The TimeZoneInfo class's FindSystemTimeZoneById method can be used to determine the correct timezoneOffset based on system time. An example in C# is shown below:
// Get CST zone id
TimeZoneInfo targetZone = TimeZoneInfo.FindSystemTimeZoneById("Central Standard Time");
// Get local machine's value of Now
DateTime utcDatetime = DateTime.UtcNow;
// Get Central Standard Time value of Now
DateTime cstDatetime = TimeZoneInfo.ConvertTimeFromUtc(utcDatetime, targetZone);
// Find timezoneOffset
int timezoneOffset = (int)((cstDatetime - utcDatetime).TotalMinutes);
Reference:
https://learn.microsoft.com/en-us/azure/cognitive-services/luis/luis-concept-data-alteration?tabs=V2#c-code-determines-correct-value-of-timezoneoffset

Jackson is changing date to one day old in spring boot rest application.

I have created a simple application with spring boot 1.5.2. I am passing date and already mentioned the date format in application.properties file as follwoing :
spring.jackson.joda-date-time-format=yyyy-MM-dd
But while calling the rest rest service using any client for POST(Insert) or PUT(Update), date is changing to on day old. Example 2017-03-21 will change to 2017-03-20.
I had the same issue and I solved it in that way:
In your entitiy, add theses annotations:
#Temporal(TemporalType.DATE)
#JsonFormat(shape = JsonFormat.Shape.STRING, locale = "fr-FR", timezone = "Europe/Paris")
private Date yourDate;
Or you can add theses line to application.properties file:
spring.jackson.time-zone=Europe/Paris
spring.jackson.locale=fr_FR
If you are in another country you can change locale and timezone, but even if you keep France, it will work.
Just set the timezone to UTC like below
SpringApplication.run(Application.class, args);
TimeZone.setDefault(TimeZone.getTimeZone("UTC"));
It solved my problem.

setFormatter for timepicker type Display.PICKER_TYPE_TIME is not working in codename one

i am using time picker and date picker in my code. i am setting the format for date picker using setFormatter method it's working fine but while setting the format for time picker it's not taking the given format and it shows Illegal Argument Exception while running my code.it shows 24 hours format while opening time after click on set it shows 12 hours format. but i need while opening the time picker dialog it shows 12 hours format only.anything is wrong in my code.
Here is my code,
SimpleDateFormat dateFormatter = new SimpleDateFormat("MM/dd/yyyy");
datePicker = new Picker();
datePicker.setType(Display.PICKER_TYPE_DATE);
datePicker.setFormatter(dateFormatter);
SimpleDateFormat timeFormatter = new SimpleDateFormat("h:mm a");
timePicker = new Picker();
timePicker.setType(Display.PICKER_TYPE_TIME);
timePicker.setShowMeridiem(Boolean.TRUE);
timePicker.setFormatter(timeFormatter);
Container c = new Container(new BoxLayout(BoxLayout.X_AXIS));
c.add(datePicker);
c.add(timePicker);
dialogtimeForm.add(c);
please find the below image
Thanks in advance.
Time picker doesn't work with a Date object, it works with an integer representing time from midnight since Date is pretty bad at representing the abstract timezone insensitive time concept.
So the formatter is ignored for all types that aren't date or date & time (which is different from date).
You can do any custom formatting you want to the value by overwriting updateValue in the Picker class & calling setText(String) with the formatted value.

PersistentLocalDateTimeAsString results in DateTimeParseException

In the hibernate model when using jadira-usertype org.jadira.usertype.dateandtime.threeten.PersistentLocalDateTimeAsString as Type, the conversion is not reversible.
#Column(name="requested_start")
#Type(type="org.jadira.usertype.dateandtime.threeten.PersistentLocalDateTimeAsString")
private LocalDateTime requestedStartDate;
When creating object with datetime in following format;
myObject.setRequestedStartDate(LocalDateTime.parse("2014-12-28T19:30:00"));
is stored in DB (MariaDB) as "2014-12-28T19:30" ignoring the seconds part (don't know why).
when querying back the data, I'm getting the following exception
java.time.format.DateTimeParseException: Text '2014-12-28T19:30' could not be parsed at index 16
But, If I set date as "2014-12-28T19:30:01" with seconds set to "01", it is working fine.
I also tried setting the springframework's DateTimeFormat, still facing the same exception.
#Column(name="requested_start")
#Type(type="org.jadira.usertype.dateandtime.threeten.PersistentLocalDateTimeAsString")
#DateTimeFormat(pattern="yyyy-MM-dd'T'HH:mm:ss")
private LocalDateTime requestedStartDate;
You can try this modified pattern "yyyy-MM-dd'T'HH:mm[:ss]".
The meaning of the square brackets is indicating an optional part during parsing - see javadoc.

#DateTimeFormat in Spring produces off-by-one day error

I am currently using #DateTimeFormat in a domain object as follows:
#DateTimeFormat(pattern = "MM/dd/yyyy")
private Date startDate = new Date();
In a Spring MVC Controller, I am posting today's date: 10/19/2011 using the jQuery UI Date picker, and I confirm that this is being sent as an HTTP Post parameter using firebug as follows:
startDate=10%2F19%2F2011
Unfortunately, once it gets to Spring on the server, it stores the date as 10/18/2011 - there is an off-by-one day error.
There is nothing in my code that even remotely touches the date - there is no calculations or anything going on with regards to this date.
Is there something about #DateTimeFormat that I should be aware of?
Could something in Hibernate be responsible for changing the date too?
I'm also looking at the my database for this application. I am storing another date, called creationDate which is an actual timestamp and differs from user input. In most cases, the dates are the same but the client wanted the ability to set it differently so that is what startDate is for.
Start Date Creation Date (actual timestamp, not user input)
2011-04-17 19:00:00 2011-04-17 21:32:27
2011-04-18 19:00:00 2011-04-18 21:14:01
2011-04-20 19:00:00 2011-04-20 23:06:47
2011-04-26 19:00:00 2011-04-26 23:24:34
2011-04-28 19:00:00 2011-04-28 20:07:06
2011-05-01 19:00:00 2011-05-02 13:35:37
2011-06-21 19:00:00 2011-06-22 15:06:36
2011-07-28 19:00:00 2011-07-29 15:32:35
2011-09-03 19:00:00 2011-09-04 13:11:45
2011-10-11 19:00:00 2011-10-12 11:45:14
2011-10-11 19:00:00 2011-10-12 11:49:55
2011-10-18 19:00:00 2011-10-19 02:20:43
At first it seems like it was a bug started in May, but then I realized that the date is correct if it was over 19:00:00, and it's off-by-one if it's under 19:00:00.
I hate Java :(
The problem seems to occur when Spring creates a date given 10/19/2011 - it seems to translate that user input and formats it to 2011-10-18 19:00:00.
What is the simplest solution?
Thanks
It seems very likely to me that this is actually a matter of time zones. A Date object represents an instant in time - I suspect if you look at the exact value that you've got (e.g. in UTC, to keep things clear) you'll get a better idea of what's going on. Chances are that where you're seeing "10/18/2011" you're interpreting it in a different time zone.
If Spring supports converting to Joda Time types I'd suggest using that instead - then you can use LocalDate which really does mean a date instead of an instant in time.
I've found that starting your JVM with your local timezone specified in the arguments solves this issue. For me it was just adding this line to the run configuration:
-Duser.timezone="Asia/Dhaka"

Resources