Unable to obtain ZonedDateTime from TemporalAccessor using DateTimeFormatter and ZonedDateTime in Java 8
This does not work because your input (and your Formatter) do not have time zone information. A simple way is to parse your date as a LocalDate
first (without time or time zone information) then create a ZonedDateTime
:
public static ZonedDateTime convertirAFecha(String fecha) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
LocalDate date = LocalDate.parse(fecha, formatter);
ZonedDateTime resultado = date.atStartOfDay(ZoneId.systemDefault());
return resultado;
}
Java8- ZonedDateTime with DateTimeFormatter not recognizing the format
Well, you want to create a ZonedDateTime
which always refers to a timezone but your input does not contain such an information, and you have also not instructed your formatter to use a default timezone if the input is missing a zone. There are two solutions for your problem:
Instruct your parser to use a timezone (here using the system tz as example):
String oraceDt = "1970-01-01 00:00:00.0";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S");
ZonedDateTime zdt =
ZonedDateTime.parse(oraceDt, formatter.withZone(ZoneId.systemDefault()));
System.out.println(zdt); // in my default zone => 1970-01-01T00:00+01:00[Europe/Berlin]Use another result type which does not need a timezone (here
LocalDateTime
):String oraceDt = "1970-01-01 00:00:00.0";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.S");
LocalDateTime ldt = LocalDateTime.parse(oraceDt, formatter);
System.out.println(ldt); // 1970-01-01T00:00
java.time.format.DateTimeParseException: Unable to obtain ZonedDateTime from TemporalAccessor in format ddMMyyyyhhmmss
You want:
String test = ZonedDateTime.now().format(formatter);
Unable to obtain ZonedDateTime from TemporalAccessor:
A zoned date time, as the name suggests, needs a zone. Your timestamp format does not include one, so the parsing fails.
You should parse into a LocalDateTime
and then apply the correct zone. For example:
String dateString = "2018-11-08 08:17:18.696124";
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss.SSSSSS");
LocalDateTime dateTime = LocalDateTime.parse(dateString, fmt);
ZonedDateTime london = dateTime.atZone(ZoneId.of("Europe/London"));
Unable to obtain ZonedDateTime from TemporalAccessor when parsing a Date
You are forgetting to set a time.
If you compare my answer with your code, you can notice that the only difference is that the time information missing. A ZonedDateTime
contains a time information and since your current formatter does not handle it, an instance of ZonedDateTime
can't be formed.
You can also see it in the stacktrace, that contains
Caused by: java.time.DateTimeException: Unable to obtain LocalTime from TemporalAccessor: {},ISO,Europe/Berlin resolved to 2015-11-13 of type java.time.format.Parsed
at java.time.LocalTime.from(LocalTime.java:409)
at java.time.ZonedDateTime.from(ZonedDateTime.java:560)
... 5 more
Depending on what you want, you could build a custom formatter with DateTimeFormatterBuilder
and call parseDefaulting
to provide a default values for each time chrono fields. If you want to default to midnight, you can set NANO_OF_DAY
to 0. A sample example would be
public static void main(String[] args) {
DateTimeFormatter formatter =
new DateTimeFormatterBuilder().appendPattern("yyyyMMdd")
.parseDefaulting(ChronoField.NANO_OF_DAY, 0)
.toFormatter()
.withZone(ZoneId.of("Europe/Berlin"));
OffsetDateTime offsetDateTime = ZonedDateTime.parse("20151113", formatter).toOffsetDateTime();
System.out.println(offsetDateTime.format(DateTimeFormatter.ISO_DATE));
}
Another possible solution would be to parse the text as a LocalDate
and then construct a ZoneDateTime
with it:
public static void main(String[] args) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyyMMdd");
LocalDate parsed = LocalDate.parse("20151113", formatter);
ZonedDateTime zonedDateTime = ZonedDateTime.of(parsed, LocalTime.MIDNIGHT, ZoneId.of("Europe/Berlin"));
// get OffsetDateTime similarly
}
how to convert Sting to ZonedDateTime in java
A ZonedDateTime
is an object aware of zone, date and time. You haven't provided any information about the time, so the String
can just be parsed to an object aware of the date only.
However, you can use the beginning of a day in order to create a ZonedDateTime
from a parsed LocalDate
like this:
public static void main(String[] args) {
String formatter = "yyyy-MM-dd";
String zone = "Europe/London";
String date = ZonedDateTime.now(ZoneId.of(zone))
.format(DateTimeFormatter.ofPattern(formatter));
System.out.println("date: " + date);
// create a LocalDate first
LocalDate localDate = LocalDate.parse(date);
// then use that and the start of that day (00:00:00) in order to parse a ZonedDateTime
ZonedDateTime dateTime = localDate.atStartOfDay(ZoneId.systemDefault());
String after = dateTime.plusDays(1).format(DateTimeFormatter.ofPattern(formatter));
System.out.println("after: " + after);
}
which outputs
date: 2019-12-17
after: 2019-12-18
Converting Date String to ZonedDateTime
I want to conver this to java.util.Calendar / java.util.GregorianCalendar formmat.
That seems silly; Calendar/GregorianCalendar is obsolete, and the API is horrendous. Why use a broken screwdriver when there's a shiny new one right there in the toolbox? Don't do this.
So my idea is converto: String -> ZonedDateTime -> Calendar.
That seems silly. The string does not contain a ZonedDateTime
. It doesn't even contain a LocalDateTime
. It is clearly a LocalDate
. So, convert it to a localdate, and you go from there.
The power of the java.time
package is that each different concept in time has a matching type in the j.t package that is properly named. For example, java.util.Date
is a lie: It is a timestamp, and it has nothing whatsoever to do with dates; asking a Date object for 'what year is it', is broken (try it, you get a warning).
Calendar, similarly, is an utter falsehood. It does not represent a calendar at all; it, too, represents a timestamp.
LocalDate
on the other hand is perfect truth: It represents a date (not a time), and it does not include timezone or other localizing information: It makes sense only as 'locally'.
Each stop should just make sense, on its own:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("uuuu-MM-dd");
LocalDate date = LocalDate.parse("2022-10-01", formatter);
So far, so good. I'd just stop there - why lie? Why return a Calendar which is both API wise a lie (that class does not represent calendars), and even if someone knows exactly what Calendar is, it's still a lie: A calendar implies it has exact time and a timezone. You do not have a time, and also don't have a timezone. Why return something that suggests stuff that isn't there?
But, if you MUST, then explicitly add a timezone and a time, and THEN go for it:
ZonedDateTime zdt = someLocalDate.atStartOfDay().atZone(ZoneId.of("Europe/Amsterdam"));
GregorianCalendar gc = GregorianCalendar.from(zdt);
This code is clear and legible: It makes crystal clear that the code picks a time, and picks a zone.
But, again, now you ended up with a horrible, horrible object you should not be using, for anything.
How do you set a date in yyyy-MM-dd format and then be able to print it out later on in the same format in Java 1.8?
1994-03-24 does not have timezone information and therefore it can not be parsed into ZonedDateTime
until you provide the timezone information. Also, you will need to default the time units.
1994-03-24 can be directly parsed into LocalDate
as the modern Date-Time API is based on ISO 8601 and does not require using a DateTimeFormatter
object explicitly as long as the Date-Time string conforms to the ISO 8601 standards.
import java.time.LocalDate;
public class Main {
public static void main(String[] args) {
System.out.println(LocalDate.parse("1994-03-24"));
}
}
Output:
1994-03-24
ONLINE DEMO
Demo of parsing with default time unit and a specific timezone:
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.temporal.ChronoField;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
DateTimeFormatter dtf = new DateTimeFormatterBuilder()
.appendPattern("u-M-d[ H]")
.parseDefaulting(ChronoField.HOUR_OF_DAY, 0)
.toFormatter(Locale.ENGLISH)
.withZone(ZoneId.systemDefault());
ZonedDateTime zdt = ZonedDateTime.parse("1994-03-24", dtf);
System.out.println(zdt);
}
}
Output:
1994-03-24T00:00Z[Europe/London]
ONLINE DEMO
Note: ZoneId.systemDefault()
returns the JVM's ZoneId
. Replace it with the applicable ZoneId
e.g. ZoneId.of("America/New_York")
. Also, notice the optional pattern inside the square bracket which has been defaulted to 0.
Learn more about the modern Date-Time API from Trail: Date Time.
Related Topics
Java 7 String - Substring Complexity
Jpa: What Is the Proper Pattern for Iterating Over Large Result Sets
Can Spring Security Use @Preauthorize on Spring Controllers Methods
Default Fetch Type for One-To-One, Many-To-One and One-To-Many in Hibernate
Difference Between One-To-Many, Many-To-One and Many-To-Many
How to Convert/Parse from String to Char in Java
Inter Thread Communication in Java
Arrays.Aslist(Int[]) Not Working
Random "Element Is No Longer Attached to the Dom" Staleelementreferenceexception
Spring Data: Override Save Method
Why Is Java.Util.Observable Not an Abstract Class
Selenium Webdriver: Wait for Complex Page with JavaScript to Load
Implementation Difference Between Aggregation and Composition in Java