Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to convert LocalDateTime to GregorianCalendar?

Tags:

java

java-time

Why is it possible to pass a LocalDateTime object into the ZonedDateTime.from() method, if it's not possible to parse a simple DateTime, as follows?

@Test
public void test() throws Exception {
    GregorianCalendar.from(ZonedDateTime.from(LocalDateTime.parse("2016-08-31T23:00:59")));
}

Result:

java.time.DateTimeException: Unable to obtain ZonedDateTime from TemporalAccessor: 2016-08-31T23:00:59 of type java.time.LocalDateTime
    at java.time.ZonedDateTime.from(ZonedDateTime.java:565)
like image 733
membersound Avatar asked Aug 08 '16 07:08

membersound


People also ask

How do I convert LocalDateTime to another timezone?

The LocalDateTime has no time zone; to convert the LocalDateTime to ZonedDateTime , we can use . atZone(ZoneId. systemDefault()) to create a ZonedDateTime containing the system default time zone and convert it to another time zone using a predefined zone id or offset.

How do I convert LocalDateTime to epoch?

In Java, with a given LocalDateTime object we can use the LocalDateTime. toEpochSecond(ZoneOffset offset) method to convert it to an epoch seconds value which is the number of seconds from the epoch of 1970-01-01T00:00:00Z as the example Java code below. The output as below.

How do I parse LocalDateTime?

In order to create a LocalDateTime object from a string, you can use the static LocalDateTime. parse() method. It takes a String and a DateTimeFormatter as a parameter. The DateTimeFormatter argument is used to specify the date/time pattern.


2 Answers

Why is it possible to pass a LocalDateTime object into the ZonedDateTime.from() method if it's not possible to parse a simple datetime?

Both LocalDateTime and ZonedDateTime implement the interface called Temporal, which extends TemporalAccessor.

LocalDateTime is datetime without a time-zone in the ISO-8601 calendar system, such as 2007-12-03T10:15:30

ZonedDateTime is datetime with a time-zone in the ISO-8601 calendar system, such as 2007-12-03T10:15:30+01:00 Europe/Paris.

Now, if you see the implementation of from(TemporalAccessor temporal) method that is expecting the TemporalAccessor… Both LocalDateTime and ZonedDateTime implements the method of super interface TemporalAccessor (Temporal extends TemporalAccessor), which is normal (i.e. has a polymorphic behavior) to allow us to pass both the local as well as zoned datetime.

Code:

public static ZonedDateTime from(final TemporalAccessor temporal) {
    if (temporal instanceof ZonedDateTime) {
        return (ZonedDateTime) temporal;
    }

    try {
        final ZoneId zone = ZoneId.from(temporal);

        if (temporal.isSupported(INSTANT_SECONDS)) {
            long epochSecond = temporal.getLong(INSTANT_SECONDS);
            int nanoOfSecond = temporal.get(NANO_OF_SECOND);

            return create(epochSecond, nanoOfSecond, zone);
        } else {
            LocalDate date = LocalDate.from(temporal);
            LocalTime time = LocalTime.from(temporal);

            return of(date, time, zone);
        }
    } catch (final DateTimeException exception) {
        throw new DateTimeException(
            "Unable to obtain ZonedDateTime from TemporalAccessor: " +
            temporal + " of type " + temporal.getClass().getName(),
            exception
        );
    }
}

Now, we come to your problem.

You are passing LocalDateTime.parse("2016-08-31T23:00:59") to the from(TemporalAccessor temporal) method. So, the temporal is not an instance of ZonedDateTime, it comes ZoneId zone = ZoneId.from(temporal);.

So, your are getting the error since the LocalDateTime does not contain the timezone.

How to solve the issue?

Use the Zone ID with the ZonedDateTime:

LocalDateTime ldt = LocalDateTime.parse("2016-08-31T23:00:59");
ZoneId zoneId = ZoneId.of("Europe/Paris");
ZonedDateTime zdt = ldt.atZone(zoneId);
GregorianCalendar gc = GregorianCalendar.from(zdt);

with JUnit test

@Test
public void test() throws Exception {
    ZoneId zoneId = ZoneId.of("Europe/Paris");
    GregorianCalendar.from(LocalDateTime.parse("2016-08-31T23:00:59").atZone(zoneId));
}
like image 119
Unknown Avatar answered Sep 17 '22 23:09

Unknown


You will have to provide the ZoneId as well. I will have to look up on the behavior as to why this is. I will edit and post as soon as I see it.

LocalDateTime ldt = LocalDateTime.parse("2016-08-31T23:00:59");
GregorianCalendar gc = GregorianCalendar.from(ZonedDateTime.of(ldt, ZoneId.systemDefault()));
System.out.println(gc);

This results:

java.util.GregorianCalendar[time=1472664659000,areFieldsSet=true,areAllFieldsSet=true,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Asia/Calcutta",offset=19800000,dstSavings=0,useDaylight=false,transitions=6,lastRule=null],firstDayOfWeek=2,minimalDaysInFirstWeek=4,ERA=1,YEAR=2016,MONTH=7,WEEK_OF_YEAR=35,WEEK_OF_MONTH=5,DAY_OF_MONTH=31,DAY_OF_YEAR=244,DAY_OF_WEEK=4,DAY_OF_WEEK_IN_MONTH=5,AM_PM=1,HOUR=11,HOUR_OF_DAY=23,MINUTE=0,SECOND=59,MILLISECOND=0,ZONE_OFFSET=19800000,DST_OFFSET=0]

Edits: Just came across this interesting thread...

The Java 8 java.time.* package is a very strict package. It doesn't allow flexibility between types and inputs - if you want a ZonedDateTime object, you must construct it from an input that has a time zone, a date & a time.

like image 40
Ramachandran.A.G Avatar answered Sep 18 '22 23:09

Ramachandran.A.G