OfficeDev / ews-java-api

A java client library to access Exchange web services. The API works against Office 365 Exchange Online as well as on premises Exchange.
MIT License
869 stars 560 forks source link

Appointment . setIsAllDayEvent seems not to work correctly #328

Open svettermann opened 9 years ago

svettermann commented 9 years ago

Hi there.

Creating Appointments, Tasks, Contacts, CheckDelegates working fine, but not using setIsAllDayEvent(true) of the appointment.

Using:

Problem: Setting start as first day and end at same day of the appoiment. This shows 2:00 first day to 2:00 next day (watching this on outlook). Also Outlook not set the checkbox for allDay so it seems not to be setup correctly.

Any workaround?

My code:

try (ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010_SP2);) {
    service.setUrl(new URI(url));
    service.setCredentials(new WebCredentials(username, password));

    Appointment appointment = new Appointment(service);
    appointment.setSubject(subject);
    appointment.setBody(MessageBody.getMessageBodyFromText(content));

    appointment.setStart(startDate);
    appointment.setEnd(endDate);

    appointment.setIsAllDayEvent(isAllDay);

    appointment.setLocation(location);

    for(String recipient : recipients) {
            appointment.getRequiredAttendees().add(recipient);
     }

     appointment.save(new FolderId(WellKnownFolderName.Calendar, new Mailbox(sender)), SendInvitationsMode.SendToAllAndSaveCopy);

      return MSG_OK;
  } catch (Exception|Error ex) {
      return ex.getMessage();
  }
evpaassen commented 9 years ago

Could you provide some information about the timezones you're using? Server, API client, Outlook?

svettermann commented 9 years ago

Server: Exchange 2013 - UTC+1

Client: Outlook 2013 - UTC+1

System where code is going to running: CEST

(But still test the code on client brings the same result)

Api: Version taken: 19/05/2015 05:18 PM (yesterday) No TimeZone set


if I try to setup the timezone (based on http://www.independentsoft.de/jwebservices/tutorial/createalldayappointment.html)

TimeZoneDefinition choosenTimeZone = null;
for (TimeZoneDefinition timeZone : service.getServerTimeZones()) {
    if (timeZone.getId().indexOf("Berlin") > 0) {
        choosenTimeZone = timeZone;
        break;
    }
}

appointment.setStartTimeZone(choosenTimeZone);
appointment.setEndTimeZone(choosenTimeZone);

it crashed on save (but not causes choosenTimeZone is null, just invalid):

microsoft.exchange.webservices.data.core.exception.service.remote.ServiceRequestException: The request failed. null
at microsoft.exchange.webservices.data.core.request.SimpleServiceRequestBase.internalExecute(SimpleServiceRequestBase.java:74)
at microsoft.exchange.webservices.data.core.request.MultiResponseServiceRequest.execute(MultiResponseServiceRequest.java:158)
at microsoft.exchange.webservices.data.core.ExchangeService.internalCreateItems(ExchangeService.java:593)
at microsoft.exchange.webservices.data.core.ExchangeService.createItem(ExchangeService.java:652)
at microsoft.exchange.webservices.data.core.service.item.Item.internalCreate(Item.java:247)
at microsoft.exchange.webservices.data.core.service.item.Appointment.save(Appointment.java:392)

Caused by: microsoft.exchange.webservices.data.core.exception.service.local.InvalidOrUnsupportedTimeZoneDefinitionException
at microsoft.exchange.webservices.data.property.complex.time.TimeZoneDefinition.validate(TimeZoneDefinition.java:334)
at microsoft.exchange.webservices.data.core.PropertyBag.validatePropertyValue(PropertyBag.java:741)
at microsoft.exchange.webservices.data.core.PropertyBag.validate(PropertyBag.java:719)
at microsoft.exchange.webservices.data.core.service.ServiceObject.validate(ServiceObject.java:283)
at microsoft.exchange.webservices.data.core.service.item.Item.validate(Item.java:505)
at microsoft.exchange.webservices.data.core.service.item.Appointment.validate(Appointment.java:245)
at microsoft.exchange.webservices.data.core.request.CreateItemRequest.validate(CreateItemRequest.java:79)
at microsoft.exchange.webservices.data.core.request.ServiceRequestBase.validateAndEmitRequest(ServiceRequestBase.java:633)
at microsoft.exchange.webservices.data.core.request.SimpleServiceRequestBase.internalExecute(SimpleServiceRequestBase.java:62)
svettermann commented 9 years ago

This hacks works for me:

if(isAllDay) {
    SimpleDateFormat dateFormatter = new SimpleDateFormat("yyyy-MM-dd");
    startDate = dateFormatter.parse(dateFormatter.format(startDate));

    endDate = dateFormatter.parse(dateFormatter.format(endDate));
    endDate = new Date(endDate.getTime() + TimeUnit.DAYS.toMillis(1));
}

instead of:

appointment.setIsAllDayEvent(isAllDay);
Neq commented 9 years ago

Are there any news on this matter? I ran into the same problem, but can't find a workaround to the solution, since the time is always set incorrectly while using the appointment.setIsAllDayEvent()-method. If i set the time correctly i can't set the checkbox in exchange.

evpaassen commented 9 years ago

https://msdn.microsoft.com/en-us/library/office/dn756538(v=exchg.150).aspx states:

By definition, all-day events start at midnight on a specific day, and end 24 hours (or a multiple of 24 hours) later. However, the EWS Managed API and EWS allow you to specify times other than midnight when creating all day events. This can lead to unintended behavior if you're not aware of how these times get translated on the server.

And:

The following example shows an EWS CreateItem operation request to create an all-day event. The appointment is created in the Eastern time zone, as indicated by the TimeZoneContext element. Notice that the time portion of the values of the Start and End elements are both 04:00Z, which converts to midnight in the Eastern time zone during daylight saving time.

Also interesting is this StackOverflow answer by Jason Johnston. Although it's about the O365 REST API, the same method seems to apply to EWS.

It seems like I'm able to create all-day events by specifying the StartTimeZone and EndTimeZone, and ensuring the Start and End are on midnight in these timezones. To specify the timezone, I'm using the OlsonTimeZoneDefinition introduced by @kentongray in #264 to convert to a Java TimeZone to a Microsoft TimeZone identifier.

For example:

appointment.setStartTimeZone(new OlsonTimeZoneDefinition(TimeZone.getDefault()));