Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Java 8 LocalDate and DateTime compatibility #59

Open
krzykrucz opened this issue Nov 18, 2016 · 10 comments
Open

Java 8 LocalDate and DateTime compatibility #59

krzykrucz opened this issue Nov 18, 2016 · 10 comments

Comments

@krzykrucz
Copy link

There could be added LocalDateIteratorFactory and DateTimeIteratorFactory as java.time support. In google-rfc-2445 there are already implemented similar iterators for jodatime compatibility.

@rozhok
Copy link

rozhok commented Dec 14, 2016

It would be awesome to add JodaTime/DateTime api support because now I have to mess between my code which uses new apis and old awkward java.time APIs

@marcelstoer
Copy link

Indeed, having to pass a java.util.Date to vEvent.setDateStart() makes me shudder. It's tough to figure out how you need to define a vEvent based on ZonedDateTime or OffsetDateTime so that the calendar event has the correct timestamps and timezone data.

@LEODPEN
Copy link

LEODPEN commented Feb 28, 2020

Indeed, having to pass a java.util.Date to vEvent.setDateStart() makes me shudder. It's tough to figure out how you need to define a vEvent based on ZonedDateTime or OffsetDateTime so that the calendar event has the correct timestamps and timezone data.

Hi here, I do the transformation like this

        LocalDateTime start = event.getStartl();
        Instant startInstant = start.atZone(zoneId).toInstant();
        vEvent.setDateStart(Date.from(startInstant));

Please let me know if there's a better way!

@pcornelissen
Copy link

Ideally the new date / time classes would be supported directly ;-)

@mangstadt
Copy link
Owner

Would it break Android compatibility if the new date/time classes were used?

@AndrewBedscastle
Copy link

Android 8 features are supported without changing the minimum API level for android apps by using desugaring, see:
https://developer.android.com/studio/write/java8-support-table

So quick answer would be: It depends
Long answer would be: No, it's just fine, but you have to add the coreLibraryDesugaring to your build.gradle file

@mangstadt
Copy link
Owner

mangstadt commented May 29, 2022

The fact that timezones are involved complicates this greatly.

iCalendar files usually come with their own timezone definition data. In order to be fully compliant, biweekly would need to convert these VTIMEZONE components into custom ZoneId objects so that date values can be represented as ZonedDateTime instances. biweekly is currently able to do this using a custom java.util.TimeZone implementation.

A workaround would be to have the user supply their own TZID-to-ZoneId mapping so that biweekly can use ZoneId instances supplied by Java. Of course, this would be a step backward since biweekly is currently able to read the timezone data in VTIMEZONE components. It would also be a major inconvenience to the user, as they would have to know the TZID values that the iCalendar uses ahead of time. (TZID values are simply unique identifiers and can technically be any random string)

File file = new File("event.ics");
ICalenar ical = Biweekly.parse(file)
  .timezone("Eastern Standard Time", ZoneId.of("America/New_York"))
  .go();

The code that generates dates from recurrence rules would also need to be overhauled. biweekly uses the old google-rfc-2445 project for this.

@runnermann
Copy link

After spending some time implementing this into a multi-threaded server. I removed it for this very reason as well as the need to save an .ics file to the hard drive. Any plans to replace the old Java Date class with Java.ZonedDateTime ?

@runnermann
Copy link

runnermann commented Sep 7, 2023

After a few hours of research in understanding how to convert this using Java 8+. The class below will convert a ZonedDateTime to the desired format for calendar coordination/invites.

The users ZoneID can be obtained by using either:
ZoneId zId = ZoneId.systemDefault();
or
ZonedDateTime now = ZonedDateTime.now(ZoneOffset.UTC):.

a ZonedDateTime can be created from several options. Conveniently if one has already created a LocalDateTime object then:

ZonedDateTime zdtOne = ZonedDateTime.of(localDateTime, zoneId);

public static String from(ZonedDateTime zdt) {
DateTimeFormatter fmtr1 = DateTimeFormatter.ofPattern("yyyyMMdd");
DateTimeFormatter fmtr2 = DateTimeFormatter.ofPattern("hhmmss");

    String str1 = zdt.format(fmtr1);
    String str2 = zdt.format(fmtr2);
    String zoneId = zdt.getZone().toString();
    return  zoneId + ":" + str1 + "T" + str2;

}

@pcornelissen
Copy link

pcornelissen commented Sep 8, 2023

FYI, you don't need the second formatter:

import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;

import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.ZoneOffset;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
import java.util.stream.Stream;

import static org.assertj.core.api.Assertions.assertThat;
import static org.junit.jupiter.params.provider.Arguments.of;

public class FormatterTest {

    public static Stream<Arguments> zdtProvider() {
        return Stream.of(
                of(ZonedDateTime.of(LocalDateTime.of(1977, 9, 20, 16, 12), ZoneId.of("GMT+2"))),
                of(ZonedDateTime.of(LocalDateTime.of(1979, 9, 9, 9, 2), ZoneId.of("GMT+12"))),
                of(ZonedDateTime.of(LocalDateTime.of(2019, 6, 23, 6, 23), ZoneId.systemDefault())),
                of(ZonedDateTime.now(ZoneOffset.systemDefault())),
                of(ZonedDateTime.now(ZoneOffset.UTC))
        );
    }

    @ParameterizedTest
    @MethodSource("zdtProvider")
    void verifyEquality(ZonedDateTime zdtOne) {
        assertThat(from1(zdtOne)).isEqualTo(from2(zdtOne));
    }


    public static String from1(java.time.ZonedDateTime zdt) {
        DateTimeFormatter fmtr1 = DateTimeFormatter.ofPattern("yyyyMMdd'T'hhmmss");

        String str1 = zdt.format(fmtr1);
        String zoneId = zdt.getZone().toString();
        return zoneId + ":" + str1;

    }

    public static String from2(java.time.ZonedDateTime zdt) {
        DateTimeFormatter fmtr1 = DateTimeFormatter.ofPattern("yyyyMMdd");
        DateTimeFormatter fmtr2 = DateTimeFormatter.ofPattern("hhmmss");

        String str1 = zdt.format(fmtr1);
        String str2 = zdt.format(fmtr2);
        String zoneId = zdt.getZone().toString();
        return zoneId + ":" + str1 + "T" + str2;
    }
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

8 participants