View Issue Details

IDProjectCategoryView StatusLast Update
0003822SOGoActiveSyncpublic2016-10-03 09:12
Reporterrogiervandervelde Assigned Toludovic  
PrioritynormalSeverityminorReproducibilityalways
Status resolvedResolutionfixed 
Platform[Server] LinuxOSRHEL/CentOSOS Version6
Product Version3.1.5 
Target Version3.2.0Fixed in Version3.2.0 
Summary0003822: Recurring events with timezones are not on the correct time in Outlook
Description

When creating and event in the webcalendar, the timezone in Outlook is displayed as (UTC+09:00) Jakoetsk, althought the timezone is Asia/Tokyo (also +9:00) on the server and client. It is displayed at the correct time however. When changing this event to a recurring event in the webcalendar, the event jumps back 9 hours in Outlook. This also is happening when creating a new recurring event in the webcalendar.

Additional Information

This machine has moved from Europe to Japan, so there are also old events with a different timezone in the database. But I've just tried with a fresh install and the result is the same, the event jumps back 9 hours after changing it to a recurring event.

TagsNo tags attached.

Activities

rogiervandervelde

rogiervandervelde

2016-09-27 02:49

reporter  

collection_event.txt (2,587 bytes)   
  <Collection>
   <Class>Calendar</Class>
   <SyncKey>1474957993</SyncKey>
   <CollectionId>vevent%2Fpersonal</CollectionId>
   <Status>1</Status>
   <Commands>
    <Add>
     <ServerId>1B2-57EA1280-1-417A8880</ServerId>
     <ApplicationData>
      <AllDayEvent xmlns="Calendar:">0</AllDayEvent>
      <DTStamp xmlns="Calendar:">20160927T063313Z</DTStamp>
      <StartTime xmlns="Calendar:">20160929T060000Z</StartTime>
      <EndTime xmlns="Calendar:">20160929T064500Z</EndTime>
      <TimeZone xmlns="Calendar:">5P3//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADoXAAA8H8AAOhc8/LwfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD
QnVvv8H8AAOhc8/LwfwAAHAIAAA==</TimeZone>
      <MeetingStatus xmlns="Calendar:">0</MeetingStatus>
      <Subject xmlns="Calendar:">test</Subject>
      <Location xmlns="Calendar:">test</Location>
      <UID xmlns="Calendar:">1B2-57EA1280-1-417A8880</UID>
      <Sensitivity xmlns="Calendar:">0</Sensitivity>
      <NativeBodyType xmlns="AirSyncBase:">1</NativeBodyType>
     </ApplicationData>
    </Add>
   </Commands>
  </Collection>




  <Collection>
   <Class>Calendar</Class>
   <SyncKey>1474958060</SyncKey>
   <CollectionId>vevent%2Fpersonal</CollectionId>
   <Status>1</Status>
   <Commands>
    <Change>
     <ServerId>1B2-57EA1280-1-417A8880</ServerId>
     <ApplicationData>
      <AllDayEvent xmlns="Calendar:">0</AllDayEvent>
      <DTStamp xmlns="Calendar:">20160927T063313Z</DTStamp>
      <StartTime xmlns="Calendar:">20160929T060000Z</StartTime>
      <EndTime xmlns="Calendar:">20160929T064500Z</EndTime>
      <TimeZone xmlns="Calendar:">5P3//wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADIiwAA8H8AAMiL6vLwfwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD
QnVvv8H8AAMiL6vLwfwAAHAIAAA==</TimeZone>
      <MeetingStatus xmlns="Calendar:">0</MeetingStatus>
      <Subject xmlns="Calendar:">test</Subject>
      <Location xmlns="Calendar:">test</Location>
      <UID xmlns="Calendar:">1B2-57EA1280-1-417A8880</UID>
      <Recurrence xmlns="Calendar:">
       <Recurrence_DayOfWeek>16</Recurrence_DayOfWeek>
       <Recurrence_Interval>1</Recurrence_Interval>
       <Recurrence_Type>1</Recurrence_Type>
      </Recurrence>
      <Sensitivity xmlns="Calendar:">0</Sensitivity>
      <NativeBodyType xmlns="AirSyncBase:">1</NativeBodyType>
     </ApplicationData>
    </Change>
   </Commands>
  </Collection>
collection_event.txt (2,587 bytes)   
tfu

tfu

2016-09-30 03:43

reporter   ~0010709

Can you please show the raw ics data of the events.
Are you in the position to test a patch (i.e. compile form source)?

rogiervandervelde

rogiervandervelde

2016-09-30 04:37

reporter  

TEST (web).ics (604 bytes)   
BEGIN:VCALENDAR
PRODID:-//Inverse inc./SOGo 3.1.5//EN
VERSION:2.0
BEGIN:VTIMEZONE
TZID:Asia/Tokyo
X-LIC-LOCATION:Asia/Tokyo
BEGIN:STANDARD
TZOFFSETFROM:+0900
TZOFFSETTO:+0900
TZNAME:JST
DTSTART:19700101T000000
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
UID:64A-57EE2300-1-323C4640
SUMMARY:TEST
LOCATION:test
DESCRIPTION:TEST
CLASS:PUBLIC
X-SOGO-SEND-APPOINTMENT-NOTIFICATIONS:NO
RRULE:FREQ=WEEKLY
DTSTART;TZID=Asia/Tokyo:20160930T150000
DTEND;TZID=Asia/Tokyo:20160930T160000
CREATED:20160930T083123Z
DTSTAMP:20160930T083123Z
LAST-MODIFIED:20160930T083123Z
END:VEVENT
END:VCALENDAR
TEST (web).ics (604 bytes)   
rogiervandervelde

rogiervandervelde

2016-09-30 04:37

reporter  

TEST (Outlook).ics (973 bytes)   
BEGIN:VCALENDAR
PRODID:-//Microsoft Corporation//Outlook 16.0 MIMEDIR//EN
VERSION:2.0
METHOD:PUBLISH
X-MS-OLK-FORCEINSPECTOROPEN:TRUE
BEGIN:VTIMEZONE
TZID:Yakutsk Standard Time
BEGIN:STANDARD
DTSTART:16010101T000000
TZOFFSETFROM:+0900
TZOFFSETTO:+0900
END:STANDARD
END:VTIMEZONE
BEGIN:VEVENT
CLASS:PUBLIC
CREATED:20160930T083435Z
DESCRIPTION:TEST
DTEND;TZID="Yakutsk Standard Time":20160930T070000
DTSTAMP:20160930T083435Z
DTSTART;TZID="Yakutsk Standard Time":20160930T060000
LAST-MODIFIED:20160930T083435Z
LOCATION:test
RRULE:FREQ=WEEKLY;BYDAY=FR
SEQUENCE:0
SUMMARY:TEST
UID:64A-57EE2300-1-323C4640
X-ALT-DESC;FMTTYPE=text/html:<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2//E
	N">\n<HTML>\n<HEAD>\n<META NAME="Generator" CONTENT="MS Exchange Server ve
	rsion rmj.rmm.rup.rpr">\n<TITLE></TITLE>\n</HEAD>\n<BODY>\n<!-- Converted 
	from text/plain format -->\n\n<P><FONT SIZE=2>TEST</FONT>\n</P>\n\n</BODY>
	\n</HTML>
END:VEVENT
END:VCALENDAR
TEST (Outlook).ics (973 bytes)   
rogiervandervelde

rogiervandervelde

2016-09-30 04:41

reporter   ~0010710

I've uploaded the same event twice, one is the ics data from the web interface (web), the other from Outlook. The timezone is different (the happens to non-recurring events as well, if you want an example of this, I can upload them as well).

Compiling from source is no problem, currently running a selfcompiled version from the 3.1.5 source.

tfu

tfu

2016-09-30 17:04

reporter  

3822.diff (3,627 bytes)   
diff --git a/ActiveSync/iCalRecurrenceRule+ActiveSync.m b/ActiveSync/iCalRecurrenceRule+ActiveSync.m
index 621d6f8..66c778c 100644
--- a/ActiveSync/iCalRecurrenceRule+ActiveSync.m
+++ b/ActiveSync/iCalRecurrenceRule+ActiveSync.m
@@ -37,6 +37,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #import <NGCards/iCalEvent.h>
 #import <NGCards/iCalByDayMask.h>
 
+#import <NGCards/iCalDateTime.h>
+#import <NGCards/iCalTimeZone.h>
+
 #import "NSCalendarDate+ActiveSync.h"
 #import "NSDate+ActiveSync.h"
 
@@ -90,7 +93,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
         {
           // No byDayMask, we take the event's start date to compute the DayOfWeek
           // 0 == Sunday, 6 == Saturday
-          v = (1 << [[[self parent] startDate] dayOfWeek]);
+          v = (1 << [[[(iCalDateTime *)[[self parent] firstChildWithTag: @"dtstart"] timeZone] computedDateForDate: [[self parent] startDate]] dayOfWeek]);
         }
 
       [s appendFormat: @"<Recurrence_DayOfWeek xmlns=\"Calendar:\">%d</Recurrence_DayOfWeek>", v];
@@ -140,7 +143,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
           // Simple reccurrence rule of type "Monthly"
           type = 2;
           [s appendFormat: @"<Recurrence_DayOfMonth xmlns=\"Calendar:\">%d</Recurrence_DayOfMonth>",
-             (int)[[[self parent] startDate] dayOfMonth]];
+             (int)[[[(iCalDateTime *)[[self parent] firstChildWithTag: @"dtstart"] timeZone] computedDateForDate: [[self parent] startDate]] dayOfMonth]];
         }
     }
   else if ([self frequency] == iCalRecurrenceFrequenceYearly)
@@ -179,9 +182,9 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
         {
           type = 5;
           [s appendFormat: @"<Recurrence_DayOfMonth xmlns=\"Calendar:\">%d</Recurrence_DayOfMonth>",
-             (int)[[[self parent] startDate] dayOfMonth]];
+             (int)[[[(iCalDateTime *)[[self parent] firstChildWithTag: @"dtstart"] timeZone] computedDateForDate: [[self parent] startDate]] dayOfMonth]];
           [s appendFormat: @"<Recurrence_MonthOfYear xmlns=\"Calendar:\">%d</Recurrence_MonthOfYear>",
-             (int)[[[self parent] startDate] monthOfYear]];
+             (int)[[[(iCalDateTime *)[[self parent] firstChildWithTag: @"dtstart"] timeZone] computedDateForDate: [[self parent] startDate]] monthOfYear]];
 
         }
     }
diff --git a/ActiveSync/iCalTimeZone+ActiveSync.m b/ActiveSync/iCalTimeZone+ActiveSync.m
index c4c0071..0842535 100644
--- a/ActiveSync/iCalTimeZone+ActiveSync.m
+++ b/ActiveSync/iCalTimeZone+ActiveSync.m
@@ -128,7 +128,7 @@ struct SYSTEMTIME {
   //uint16_t wStandardYear;
   struct SYSTEMTIME stStandardDate;
   //uint16_t wDaylightYear;
-  struct SYSTEMTIME stDaylightDate;
+  struct SYSTEMTIME stDaylightDate ={0,0,0,0,0,0,0,0};
 
   char standardName[64], daylightName[64];
 
@@ -144,13 +144,17 @@ struct SYSTEMTIME {
 
   period = [self _mostRecentPeriodWithName: @"DAYLIGHT"];  
   if (!period)
-    stStandardDate.wMonth = 0;
-
-  lDaylightBias = (uint32_t) -([period secondsOffsetFromGMT] / 60) - lBias;
-  [period _fillTZDate: &stDaylightDate];
-  //wStandardYear = stStandardDate.wYear;
-  //wDaylightYear = stDaylightDate.wYear;
-
+    {
+      stStandardDate.wMonth = 0;
+      lDaylightBias = 0;
+    }
+  else
+    {
+      lDaylightBias = (uint32_t) -([period secondsOffsetFromGMT] / 60) - lBias;
+      [period _fillTZDate: &stDaylightDate];
+      //wStandardYear = stStandardDate.wYear;
+      //wDaylightYear = stDaylightDate.wYear;
+    }
 
   // We build the timezone
   [bytes appendBytes: &lBias  length: 4];
3822.diff (3,627 bytes)   
tfu

tfu

2016-09-30 17:08

reporter   ~0010712

Please test attached patch and provide feedback.

tfu

tfu

2016-10-01 03:26

reporter  

3822-2.diff (3,988 bytes)   
diff --git a/ActiveSync/iCalRecurrenceRule+ActiveSync.m b/ActiveSync/iCalRecurrenceRule+ActiveSync.m
index 621d6f8..786a31e 100644
--- a/ActiveSync/iCalRecurrenceRule+ActiveSync.m
+++ b/ActiveSync/iCalRecurrenceRule+ActiveSync.m
@@ -37,11 +37,25 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #import <NGCards/iCalEvent.h>
 #import <NGCards/iCalByDayMask.h>
 
+#import <NGCards/iCalDateTime.h>
+#import <NGCards/iCalTimeZone.h>
+
 #import "NSCalendarDate+ActiveSync.h"
 #import "NSDate+ActiveSync.h"
 
 @implementation iCalRecurrenceRule (ActiveSync)
 
+- (NSCalendarDate *) _getAdjustedStartDate
+{
+  iCalTimeZone *timeZone;
+
+  timeZone = [(iCalDateTime *)[[self parent] firstChildWithTag: @"dtstart"] timeZone];
+  if (timeZone)
+    return [timeZone computedDateForDate: [[self parent] startDate]];
+  else
+    return [[self parent] startDate];
+}
+
 - (NSString *) activeSyncRepresentationInContext: (WOContext *) context
 {
   NSMutableString *s;
@@ -90,7 +104,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
         {
           // No byDayMask, we take the event's start date to compute the DayOfWeek
           // 0 == Sunday, 6 == Saturday
-          v = (1 << [[[self parent] startDate] dayOfWeek]);
+          v = (1 << [[self _getAdjustedStartDate] dayOfWeek]);
         }
 
       [s appendFormat: @"<Recurrence_DayOfWeek xmlns=\"Calendar:\">%d</Recurrence_DayOfWeek>", v];
@@ -139,8 +153,7 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
         {
           // Simple reccurrence rule of type "Monthly"
           type = 2;
-          [s appendFormat: @"<Recurrence_DayOfMonth xmlns=\"Calendar:\">%d</Recurrence_DayOfMonth>",
-             (int)[[[self parent] startDate] dayOfMonth]];
+          [s appendFormat: @"<Recurrence_DayOfMonth xmlns=\"Calendar:\">%d</Recurrence_DayOfMonth>", [[self _getAdjustedStartDate] dayOfMonth]];
         }
     }
   else if ([self frequency] == iCalRecurrenceFrequenceYearly)
@@ -178,10 +191,8 @@ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
       else
         {
           type = 5;
-          [s appendFormat: @"<Recurrence_DayOfMonth xmlns=\"Calendar:\">%d</Recurrence_DayOfMonth>",
-             (int)[[[self parent] startDate] dayOfMonth]];
-          [s appendFormat: @"<Recurrence_MonthOfYear xmlns=\"Calendar:\">%d</Recurrence_MonthOfYear>",
-             (int)[[[self parent] startDate] monthOfYear]];
+          [s appendFormat: @"<Recurrence_DayOfMonth xmlns=\"Calendar:\">%d</Recurrence_DayOfMonth>", [[self _getAdjustedStartDate] dayOfMonth]];
+          [s appendFormat: @"<Recurrence_MonthOfYear xmlns=\"Calendar:\">%d</Recurrence_MonthOfYear>", [[self _getAdjustedStartDate] monthOfYear]]; 
 
         }
     }
diff --git a/ActiveSync/iCalTimeZone+ActiveSync.m b/ActiveSync/iCalTimeZone+ActiveSync.m
index c4c0071..0842535 100644
--- a/ActiveSync/iCalTimeZone+ActiveSync.m
+++ b/ActiveSync/iCalTimeZone+ActiveSync.m
@@ -128,7 +128,7 @@ struct SYSTEMTIME {
   //uint16_t wStandardYear;
   struct SYSTEMTIME stStandardDate;
   //uint16_t wDaylightYear;
-  struct SYSTEMTIME stDaylightDate;
+  struct SYSTEMTIME stDaylightDate ={0,0,0,0,0,0,0,0};
 
   char standardName[64], daylightName[64];
 
@@ -144,13 +144,17 @@ struct SYSTEMTIME {
 
   period = [self _mostRecentPeriodWithName: @"DAYLIGHT"];  
   if (!period)
-    stStandardDate.wMonth = 0;
-
-  lDaylightBias = (uint32_t) -([period secondsOffsetFromGMT] / 60) - lBias;
-  [period _fillTZDate: &stDaylightDate];
-  //wStandardYear = stStandardDate.wYear;
-  //wDaylightYear = stDaylightDate.wYear;
-
+    {
+      stStandardDate.wMonth = 0;
+      lDaylightBias = 0;
+    }
+  else
+    {
+      lDaylightBias = (uint32_t) -([period secondsOffsetFromGMT] / 60) - lBias;
+      [period _fillTZDate: &stDaylightDate];
+      //wStandardYear = stStandardDate.wYear;
+      //wDaylightYear = stDaylightDate.wYear;
+    }
 
   // We build the timezone
   [bytes appendBytes: &lBias  length: 4];
3822-2.diff (3,988 bytes)   
tfu

tfu

2016-10-01 03:27

reporter   ~0010713

Modified patch to also deal with allday-events.

rogiervandervelde

rogiervandervelde

2016-10-01 11:39

reporter   ~0010714

I've tried the patch (both) on my test system, and it seems to solve the problem. The calendar shows on the correct date/timezone in Outlook, but timezone changes in Outlook are converted to localtime on the backend however, so timezone information is lost (although the time itself is correct).

tfu

tfu

2016-10-01 17:40

reporter   ~0010715

Currently the timezone sent by the client is not used during the event update, user's timezone specified in SOGo is used instead.

rogiervandervelde

rogiervandervelde

2016-10-02 08:57

reporter   ~0010716

Then the problem is solved as far as I can tell, thank you very much!

ludovic

ludovic

2016-10-03 09:12

administrator   ~0010718

Applied a slightly modified version of the patch.

Related Changesets

sogo: master 23fa9c0e

2016-10-03 08:59:37

ludovic

Details Diff
(fix) fixed recurring events with timezones for EAS (fixes 0003822) Affected Issues
0003822
mod - ActiveSync/iCalRecurrenceRule+ActiveSync.m Diff File
mod - ActiveSync/iCalTimeZone+ActiveSync.m Diff File

sogo: v2 665367f8

2016-10-03 08:59:37

ludovic

Details Diff
(fix) fixed recurring events with timezones for EAS (fixes 0003822) Affected Issues
0003822
mod - ActiveSync/iCalRecurrenceRule+ActiveSync.m Diff File
mod - ActiveSync/iCalTimeZone+ActiveSync.m Diff File

Issue History

Date Modified Username Field Change
2016-09-27 00:29 rogiervandervelde New Issue
2016-09-27 02:49 rogiervandervelde File Added: collection_event.txt
2016-09-30 03:43 tfu Note Added: 0010709
2016-09-30 04:37 rogiervandervelde File Added: TEST (web).ics
2016-09-30 04:37 rogiervandervelde File Added: TEST (Outlook).ics
2016-09-30 04:41 rogiervandervelde Note Added: 0010710
2016-09-30 17:04 tfu File Added: 3822.diff
2016-09-30 17:08 tfu Note Added: 0010712
2016-10-01 03:26 tfu File Added: 3822-2.diff
2016-10-01 03:27 tfu Note Added: 0010713
2016-10-01 11:39 rogiervandervelde Note Added: 0010714
2016-10-01 17:40 tfu Note Added: 0010715
2016-10-02 08:57 rogiervandervelde Note Added: 0010716
2016-10-02 09:46 ludovic Target Version => 3.2.0
2016-10-03 09:02 ludovic Changeset attached => sogo master 23fa9c0e
2016-10-03 09:02 ludovic Assigned To => ludovic
2016-10-03 09:02 ludovic Resolution open => fixed
2016-10-03 09:03 ludovic Changeset attached => sogo v2 665367f8
2016-10-03 09:12 ludovic Note Added: 0010718
2016-10-03 09:12 ludovic Status new => resolved
2016-10-03 09:12 ludovic Fixed in Version => 3.2.0