How to Obtain Zoneddatetime from Temporalaccessor Using Datetimeformatter and Zoneddatetime in Java 8

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:

  1. 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]
  2. 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



Leave a reply



Submit