-->

Incorrect time zone displayed in Outlook after upd

2019-08-09 07:30发布

问题:

I'm having an issue with time zones when updating an appointment.

Step 1, create a single event, works fine

First I create a single event, running from 10:00 to 11:00 local time (Amsterdam DST, so UTC+2).
My Exchange server 2010 (SP2) knows the "W. Europe Standard Time" timezone.
No issue there, here's the event in Outlook 2007:

This is the XML that creates the event:

<soapenv:Envelope
  xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:typ="http://schemas.microsoft.com/exchange/services/2006/types"
  xmlns:mes="http://schemas.microsoft.com/exchange/services/2006/messages">
<soapenv:Header>
  <typ:RequestServerVersion Version="Exchange2007_SP1"/>
  <typ:MailboxCulture>en-US</typ:MailboxCulture>
  <typ:TimeZoneContext>
     <typ:TimeZoneDefinition Id="W. Europe Standard Time"/>
  </typ:TimeZoneContext>
</soapenv:Header>
<soapenv:Body>
   <mes:CreateItem SendMeetingInvitations="SendToNone">
      <mes:SavedItemFolderId>
         <typ:DistinguishedFolderId Id="calendar">
            <typ:Mailbox>
               <typ:EmailAddress>developer@timetellbv.nl</typ:EmailAddress>
            </typ:Mailbox>
         </typ:DistinguishedFolderId>
      </mes:SavedItemFolderId>
      <mes:Items>
         <typ:CalendarItem>
           <typ:Subject>New event 10:00-11:00</typ:Subject>
           <typ:Body BodyType="Text"></typ:Body>
           <typ:Categories>
             <typ:String>TimeTell</typ:String>
           </typ:Categories>
           <typ:ReminderIsSet>false</typ:ReminderIsSet>
           <typ:Start>2014-08-19T10:00:00.000+02:00</typ:Start>
           <typ:End>2014-08-19T11:00:00.000+02:00</typ:End>
           <typ:IsAllDayEvent>false</typ:IsAllDayEvent>
           <typ:LegacyFreeBusyStatus>Busy</typ:LegacyFreeBusyStatus>
           <typ:Location></typ:Location>
           <typ:MeetingTimeZone TimeZoneName="W. Europe Standard Time"/>
         </typ:CalendarItem>
      </mes:Items>
   </mes:CreateItem>
</soapenv:Body>
</soapenv:Envelope>

Note that I specify the MeetingTimeZone, and give Start/Finish an explicit time zone, so that Exchange Server knows how to convert it to UTC without having to rely on the server time zone (see Best Practices for Using Exchange Web Services for Calendaring Tasks).
I tried leaving out all time zone info when creating the event, but this immediately gives me the 'Reykjavik effect' of step 2. Anyway, step 1 works fine.

Step 2, update the single event, fails: changes timezone as displayed in Outlook

Now I modify the event caption only; I need to specify all items again (my code has no idea what changed):

<soapenv:Envelope
  xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
  xmlns:typ="http://schemas.microsoft.com/exchange/services/2006/types"
  xmlns:mes="http://schemas.microsoft.com/exchange/services/2006/messages">
<soapenv:Header>
  <typ:RequestServerVersion Version="Exchange2007_SP1"/>
  <typ:MailboxCulture>en-US</typ:MailboxCulture>
  <typ:TimeZoneContext>
     <typ:TimeZoneDefinition Id="W. Europe Standard Time"/>
  </typ:TimeZoneContext>
</soapenv:Header>
<soapenv:Body>
<mes:UpdateItem ConflictResolution="AlwaysOverwrite" SendMeetingInvitationsOrCancellations="SendToNone">
   <mes:ItemChanges>
      <typ:ItemChange>
         <typ:ItemId Id="AQMkAZ[snip]hgAAAA==" ChangeKey="DwAAA[snip]yy5AX"/>
         <typ:Updates>
            <typ:SetItemField>
               <typ:FieldURI FieldURI="item:Subject"/>
               <typ:CalendarItem>
                 <typ:Subject>New event 10:00-11:00 (modified)</typ:Subject>
               </typ:CalendarItem>
            </typ:SetItemField>
            <typ:SetItemField>
               <typ:FieldURI FieldURI="item:Sensitivity"/>
               <typ:CalendarItem>
                 <typ:Sensitivity>Normal</typ:Sensitivity>
               </typ:CalendarItem>
            </typ:SetItemField>
            <typ:SetItemField>
               <typ:FieldURI FieldURI="item:Categories"/>
               <typ:CalendarItem>
                  <typ:Categories>
                     <typ:String>TimeTell</typ:String>
                  </typ:Categories>
               </typ:CalendarItem>
            </typ:SetItemField>
            <typ:SetItemField>
               <typ:FieldURI FieldURI="item:Body"/>
               <typ:CalendarItem>
                 <typ:Body BodyType="Text"></typ:Body>
               </typ:CalendarItem>
            </typ:SetItemField>
            <typ:SetItemField>
               <typ:FieldURI FieldURI="calendar:Location"/>
               <typ:CalendarItem>
                 <typ:Location></typ:Location>
               </typ:CalendarItem>
            </typ:SetItemField>
            <typ:SetItemField>
               <typ:FieldURI FieldURI="item:ReminderIsSet"/>
               <typ:CalendarItem>
                 <typ:ReminderIsSet>false</typ:ReminderIsSet>
               </typ:CalendarItem>
            </typ:SetItemField>
            <typ:SetItemField>
               <typ:FieldURI FieldURI="calendar:IsAllDayEvent"/>
               <typ:CalendarItem>
                 <typ:IsAllDayEvent>false</typ:IsAllDayEvent>
               </typ:CalendarItem>
            </typ:SetItemField>
            <typ:SetItemField>
               <typ:FieldURI FieldURI="calendar:Start"/>
               <typ:CalendarItem>
                 <typ:Start>2014-08-19T10:00:00.000+02:00</typ:Start>
               </typ:CalendarItem>
            </typ:SetItemField>
            <typ:SetItemField>
               <typ:FieldURI FieldURI="calendar:End"/>
               <typ:CalendarItem>
                 <typ:End>2014-08-19T11:00:00.000+02:00</typ:End>
               </typ:CalendarItem>
            </typ:SetItemField>
            <typ:SetItemField>
               <typ:FieldURI FieldURI="calendar:LegacyFreeBusyStatus"/>
               <typ:CalendarItem>
                 <typ:LegacyFreeBusyStatus>Busy</typ:LegacyFreeBusyStatus>
               </typ:CalendarItem>
            </typ:SetItemField>
            <typ:SetItemField>
               <typ:ExtendedFieldURI DistinguishedPropertySetId="PublicStrings" PropertyName="TimeTellID" PropertyType="Integer"/>
               <typ:CalendarItem>
                  <typ:ExtendedProperty>
                     <typ:ExtendedFieldURI DistinguishedPropertySetId="PublicStrings" PropertyName="TimeTellID" PropertyType="Integer"/>
                     <typ:Value>10722</typ:Value>
                  </typ:ExtendedProperty>
               </typ:CalendarItem>
            </typ:SetItemField>
            <typ:SetItemField>
               <typ:ExtendedFieldURI DistinguishedPropertySetId="PublicStrings" PropertyName="TimeTellSyncTime" PropertyType="SystemTime"/>
               <typ:CalendarItem>
                  <typ:ExtendedProperty>
                     <typ:ExtendedFieldURI DistinguishedPropertySetId="PublicStrings" PropertyName="TimeTellSyncTime" PropertyType="SystemTime"/>
                     <typ:Value>2014-08-19T16:22:22.094+02:00</typ:Value>
                  </typ:ExtendedProperty>
               </typ:CalendarItem>
            </typ:SetItemField>
            <typ:SetItemField>
               <typ:ExtendedFieldURI DistinguishedPropertySetId="PublicStrings" PropertyName="TimeTellSyncVer" PropertyType="Integer"/>
               <typ:CalendarItem>
                  <typ:ExtendedProperty>
                     <typ:ExtendedFieldURI DistinguishedPropertySetId="PublicStrings" PropertyName="TimeTellSyncVer" PropertyType="Integer"/>
                     <typ:Value>80000</typ:Value>
                  </typ:ExtendedProperty>
               </typ:CalendarItem>
            </typ:SetItemField>
            <typ:SetItemField>
               <typ:ExtendedFieldURI DistinguishedPropertySetId="PublicStrings" PropertyName="TimeTellSyncID" PropertyType="String"/>
               <typ:CalendarItem>
                  <typ:ExtendedProperty>
                     <typ:ExtendedFieldURI DistinguishedPropertySetId="PublicStrings" PropertyName="TimeTellSyncID" PropertyType="String"/>
                     <typ:Value>0000000082ADE26393957649AD9C74BF97109BC2070084A6175871FF6A40850053554066620A000000000021000084A6175871FF6A40850053554066620A000232CB43830000</typ:Value>
                  </typ:ExtendedProperty>
               </typ:CalendarItem>
            </typ:SetItemField>
         </typ:Updates>
      </typ:ItemChange>
   </mes:ItemChanges>
 </mes:UpdateItem>
</soapenv:Body>
</soapenv:Envelope>

but now I get this:
The event shows properly in the calender overview

but when I open it I suddenly get incorrect 'Reykjavik' times:

Note that the header of the UpdateItem call still has the

<typ:TimeZoneContext>
   <typ:TimeZoneDefinition Id="W. Europe Standard Time"/>
</typ:TimeZoneContext>

but there is no

<typ:MeetingTimeZone TimeZoneName="W. Europe Standard Time"/>

in the call, as there was in the CreateItem call.

If I try to put it in like this I get an error "The specified object was not found in the store":

<typ:SetItemField>
   <typ:FieldURI FieldURI="calendar:Start"/>
   <typ:CalendarItem>
     <typ:Start>2014-08-19T10:00:00.000+02:00</typ:Start>
     <typ:MeetingTimeZone TimeZoneName="W. Europe Standard Time"/>
   </typ:CalendarItem>
</typ:SetItemField>
<typ:SetItemField>
   <typ:FieldURI FieldURI="calendar:End"/>
   <typ:CalendarItem>
     <typ:End>2014-08-19T11:00:00.000+02:00</typ:End>
     <typ:MeetingTimeZone TimeZoneName="W. Europe Standard Time"/>
   </typ:CalendarItem>
</typ:SetItemField>

I have tried placing MeetingTimeZone at other locations in the file but keep getting syntax errors.

Leaving the TimeZoneContext out of the header of the UpdateItem does not solve the issue (and from what I understand in TimeZoneContext documentation I should use it).

I need to use MeetingTimeZone for backward compatibility to Exchange Server 2007 SP1 (for later versions MeetingTimeZone is deprecated and we should use StartImeZone/EndTimeZone).

Question: How can I change the UpdateItem call to make sure my Outlook events keep having the correct time(zone)?

Background information:

  • Exchange server version returns:

<ServerVersionInfo MajorVersion="14" MinorVersion="3" MajorBuildNumber="195" MinorBuildNumber="1" Version="Exchange2010_SP2"/>

  • Local Outlook setting is Amsterdam timezone (currently UTC+2 because of DST).

  • Here is an EWS Managed API user experiencing similar problems but with no solution.

回答1:

I got it! Thanks to this EWS Calendar Recurrence Item Update - TimeZone problem post.

Indeed you cannot just insert a

<typ:MeetingTimeZone TimeZoneName="W. Europe Standard Time"/>

line somewhere in the SOAP request, but you also have to specify MeetingTimeZone as a CalendarItem element that you want to change.
So this additional item has to be inserted into the call:

<typ:SetItemField>
   <typ:FieldURI FieldURI="calendar:MeetingTimeZone"/>
   <typ:CalendarItem>
      <typ:MeetingTimeZone TimeZoneName="W. Europe Standard Time" />
   </typ:CalendarItem>               
</typ:SetItemField>

And make sure to put it at the right place, because the items have to be specified in the order as defined in the CalendarItem type