Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to create Java time instant from pattern?

Tags:

java

java-time

Consider a code:

TemporalAccessor date = DateTimeFormatter.ofPattern("yyyy-MM-dd").parse("9999-12-31"); Instant.from(date); 

The last line throws an exception:

Unable to obtain Instant from TemporalAccessor: {},ISO resolved to 9999-12-31 of type java.time.format.Parsed 

How to create Instant from yyyy-MM-dd pattern?

like image 221
Cherry Avatar asked Jun 07 '16 06:06

Cherry


People also ask

How do you get Instant string?

The parse() method of Instant class help to get an instance of Instant from a string value passed as parameter. This string is an instant in the UTC time zone. It is parsed using DateTimeFormatter. ISO_INSTANT.

How do I get Instant Java?

The current instant from the system UTC clock can be obtained using the now() method in the Instant class in Java. This method requires no parameters and it returns the current instant from the system UTC clock.

How do you make an Instant?

Creating an Instant You create an Instant instance using one of the Instant class factory methods: static Instant now(): Obtains the current instant from the system clock. static Instant now(Clock clock): Obtains the current instant from the specified clock.


2 Answers

The string "9999-12-31" only contains information about a date. It does not contain any information about the time-of-day or offset. As such, there is insufficient information to create an Instant. (Other date and time libraries are more lenient, but java.time avoids defaulting these values)

Your first choice is to use a LocalDate instead of an `Instant:

LocalDate date = LocalDate.parse("9999-12-31"); 

Your second choice is to post process the date to convert it to an instant, which requires a time-zone, here chosen to be Paris:

LocalDate date = LocalDate.parse("9999-12-31"); Instant instant = date.atStartOfDay(ZoneId.of("Europe/Paris")).toInstant(); 

Your third choice is to add the time-zone to the formatter, and default the time-of-day:

static final DateTimeFormatter FMT = new DateTimeFormatterBuilder()     .appendPattern("yyyy-MM-dd")     .parseDefaulting(ChronoField.NANO_OF_DAY, 0)     .toFormatter()     .withZone(ZoneId.of("Europe/Paris")); Instant instant = FMT.parse("9999-31-12", Instant::from); 

(If this doesn't work, ensure you have the latest JDK 8 release as a bug was fixed in this area).

It is worth noting that none of these possibilities use TemporalAccessor directly, because that type is a low-level framework interface, not one for most application developers to use.

like image 200
JodaStephen Avatar answered Sep 25 '22 12:09

JodaStephen


The problem isn't the fact that you are using the year 9999. The Instant.MAX field evaluates to the timestamp 1000000000-12-31T23:59:59.999999999Z, so 9999 as a year is fine.

Dealing with TemporalAccessors instead of the more semantically rich types like LocalDateTime or ZonedDateTime is like using a Map to model an object and its properties instead of writing a class -- you have to assure that the value has the fields (like seconds, nanoseconds, etc) that are expected by something receiving it, rather than depending on formally declared operations in a higher level class to prevent dependencies from going unmet.

In your case it is likely that the temporal accessor contained the parsed date fields it was given, but didn't have a "seconds" field that the Instant needed. It is best to use the more semantically rich types like LocalDateTime in most instances.

Since you only have date fields, you should parse it as a date, then add the time fields before converting it to an Instant. Here is one way, using LocalDate to parse the date:

LocalDate localDate = LocalDate.parse("2016-04-17"); LocalDateTime localDateTime = localDate.atStartOfDay(); Instant instant = localDateTime.toInstant(ZoneOffset.UTC); 
like image 37
Hank D Avatar answered Sep 24 '22 12:09

Hank D