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

Timezone issue #352

Closed
crudolf opened this issue Sep 16, 2019 · 9 comments
Closed

Timezone issue #352

crudolf opened this issue Sep 16, 2019 · 9 comments

Comments

@crudolf
Copy link

crudolf commented Sep 16, 2019

Describe the bug
Google Mail/Calendar: Time in ICS file is correct (MESZ)

To Reproduce
Add appended ICS file to apple calendar

Expected behavior
Time zone is correctly used

Actual result
2 hours difference in appointment start date within apple calendar.
Appointment should be from 3 to 4 PM, but in apple calendar it is from shown to be from 5 to 6 PM.

What is the preferred way of making the time zone works correctly on as many as possible devices?

testappointment.ics.zip

Bildschirmfoto 2019-09-16 um 13 29 01

@benfortuna
Copy link
Member

This appears to be an issue with Apple iCal. The attached file appears to be ok, so could only suggest to check the timezone settings on the Apple device.

@crudolf
Copy link
Author

crudolf commented Sep 19, 2019

I resolved the issue by adding timezone to dtstart and dtend:

    meeting.getProperties().add(new net.fortuna.ical4j.model.property.DtStart(startDate.format("yyyyMMdd'T'HHmm00"), timezone));

This seems to make it easier for apple calendar. I would like to propose that this is the default behaviour, if time zone was set?

@benfortuna
Copy link
Member

Ah yes sorry I missed that. In fact you shouldn't have the TZID property in a VEVENT object as this is used for TIMEZONE definitions.

Instead you must explicitly set the timezone on the date-based property, otherwise it will be treated as "floating" time and will assume the local timezone wherever it is used.

Because floating time is a valid option, we don't automatically set the timezone on date-based properties.

@crudolf
Copy link
Author

crudolf commented Sep 19, 2019

But isn't this the 99% use case? What is the use case for floating event times?

@benfortuna
Copy link
Member

Actually in some cases it will automatically set the timezone parameter, but not with the String-based constructor you just described. You didn't share the original code so I can't comment on that, but you should try this (assuming start date is a java.util.Date):

meeting.getProperties().add(new DtStart(new DateTime(startDate)));

@crudolf
Copy link
Author

crudolf commented Sep 19, 2019

I used this code:

    TimeZoneRegistry registry = TimeZoneRegistryFactory.getInstance().createRegistry();
    TimeZone timezone = registry.getTimeZone("Europe/Berlin");
    VTimeZone tz = timezone.getVTimeZone();

    Date slotFromDate = appointment.getFromDateForClients()

    java.util.Calendar startDate = new GregorianCalendar();
    startDate.setTimeZone(timezone);
    startDate.set(java.util.Calendar.MONTH, slotFromDate[java.util.Calendar.MONTH]);
    startDate.set(java.util.Calendar.DAY_OF_MONTH, slotFromDate[java.util.Calendar.DAY_OF_MONTH]);
    startDate.set(java.util.Calendar.YEAR, slotFromDate[java.util.Calendar.YEAR]);
    startDate.set(java.util.Calendar.HOUR_OF_DAY, slotFromDate[java.util.Calendar.HOUR_OF_DAY]);
    startDate.set(java.util.Calendar.MINUTE, slotFromDate[java.util.Calendar.MINUTE]);
    startDate.set(java.util.Calendar.SECOND, slotFromDate[java.util.Calendar.SECOND]);

    Date slotUntilDate = appointment.getUntilDateForClients()

    java.util.Calendar endDate = new GregorianCalendar();
    endDate.setTimeZone(timezone);
    endDate.set(java.util.Calendar.MONTH, slotUntilDate[java.util.Calendar.MONTH]);
    endDate.set(java.util.Calendar.DAY_OF_MONTH, slotUntilDate[java.util.Calendar.DAY_OF_MONTH]);
    endDate.set(java.util.Calendar.YEAR, slotUntilDate[java.util.Calendar.YEAR]);
    endDate.set(java.util.Calendar.HOUR_OF_DAY, slotUntilDate[java.util.Calendar.HOUR_OF_DAY]);
    endDate.set(java.util.Calendar.MINUTE, slotUntilDate[java.util.Calendar.MINUTE]);
    endDate.set(java.util.Calendar.SECOND, slotUntilDate[java.util.Calendar.SECOND]);

    DateTime start = new DateTime(startDate.getTime());
    DateTime end = new DateTime(endDate.getTime());
    VEvent meeting = new VEvent(start, end, "..");

@benfortuna
Copy link
Member

benfortuna commented Sep 19, 2019

Ok so the problem is that java.util.Date doesn't encapsulate the timezone, so even though you are setting it on the java.util.Calendar instance, the date resulting from startDate.getTime() has lost the zone information.

Ideally the DateTime should really be constructed from a Calendar instance, however we are currently refactoring the whole library to support the new date/time api.

The best workaround right now is to use the DateTime constructor with string and timezone as arguments: DateTime(String value, TimeZone timezone) - which I think is basically what you have done anyway.

ps. i can add some more convenience constructors to DateTime to support calendar instances, should make it a little easier.

@crudolf
Copy link
Author

crudolf commented Sep 19, 2019

Thanks for clarifying this, I will look for a place in the wiki (?) to add an example for this!

@benfortuna
Copy link
Member

New DateTime constructor included in 3.0.10 release

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

No branches or pull requests

2 participants