Incorrect time of the modified event's occurrence in PST file

aspose-email-21.12
After adding of an exception to a Calendar’s reccurent event and saving to .pst file start/end date of the modified occurence is incorrect.
modified occurrence.png (3.5 KB)

This is the code to reproduce the issue:

import com.aspose.email.*;
import org.junit.jupiter.api.Test;

import java.io.File;
import java.util.Date;

import static org.apache.commons.lang.time.DateUtils.addDays;
import static org.apache.commons.lang.time.DateUtils.addHours;
import static org.junit.jupiter.api.Assertions.assertEquals;

class MapiCalendarExceptionInfoTest {

	@Test
	void test() {
		Date startDate = addHours(new Date(), 1);
		Date endDate = addHours(startDate, 1);

		// Create the meeting
		MapiCalendar meeting = new MapiCalendar("", "Meeting", "root", startDate,
			endDate, "", new MapiRecipientCollection());

		// Set timeZone
		MapiCalendarTimeZone timeZone = new MapiCalendarTimeZone("EST");
		meeting.setStartDateTimeZone(timeZone);
		meeting.setEndDateTimeZone(timeZone);

		// Create the recurrence
		MapiCalendarEventRecurrence recurrence = new MapiCalendarEventRecurrence();
		recurrence.setRecurrencePattern(new MapiCalendarDailyRecurrencePattern());
		MapiCalendarRecurrencePattern pattern = recurrence.getRecurrencePattern();
		pattern.setPatternType(MapiCalendarRecurrencePatternType.Day);
		pattern.setPeriod(1);
		pattern.setWeekStartDay(DayOfWeek.Sunday);
		pattern.setOccurrenceCount(5);
		pattern.setEndType(MapiCalendarRecurrenceEndType.EndAfterNOccurrences);
		meeting.setRecurrence(recurrence);

		// Modify the occurrence
		MapiCalendarExceptionInfo exceptionInfo = new MapiCalendarExceptionInfo();
		Date exceptionStartDate = addDays(startDate, 1);
		Date exceptionEndDate = addHours(exceptionStartDate, 1);
		exceptionInfo.setBody("Modified description");
		exceptionInfo.setOriginalStartDate(exceptionStartDate);
		exceptionInfo.setStartDateTime(exceptionStartDate);
		exceptionInfo.setEndDateTime(exceptionEndDate);
		pattern.getModifiedInstanceDates().addItem(exceptionStartDate);
		pattern.getDeletedInstanceDates().addItem(exceptionStartDate);
		pattern.getExceptions().addItem(exceptionInfo);

		// Store to PST
		String file = System.getProperty("java.io.tmpdir") + File.separator + "MapiCalendarToPST" + System.currentTimeMillis() + " _out.pst";
		String calendarName = "Calendar";
		FolderInfo calendarFolder;
		try (PersonalStorage pst = PersonalStorage.create(file, FileFormatVersion.Unicode)) {
			calendarFolder = pst.createPredefinedFolder(calendarName, StandardIpmFolder.Appointments);
			calendarFolder.addMapiMessageItem(meeting);
		}

		// Load from PST
		PersonalStorage storage = PersonalStorage.fromFile(file);
		FolderInfo folderInfo = storage.getRootFolder().getSubFolder(calendarName);
		MessageInfoCollection messageInfoCollection = folderInfo.getContents();
		String diffMessage = "Occurrence start date:\nExpected:%s\nActual\t:%s";
		for (MessageInfo messageInfo : messageInfoCollection) {
			MapiCalendar calendar = (MapiCalendar) storage.extractMessage(messageInfo).toMapiMessageItem();
			assertEquals(calendar.getStartDate().getTime(), calendar.getRecurrence().getRecurrencePattern().getStartDate().getTime(),
				String.format(diffMessage, calendar.getStartDate(), calendar.getRecurrence().getRecurrencePattern().getStartDate())
			);
			assertEquals(calendar.getEndDate().getTime(), calendar.getRecurrence().getRecurrencePattern().getEndDate().getTime(),
				String.format(diffMessage, calendar.getEndDate(), calendar.getRecurrence().getRecurrencePattern().getEndDate())
			);
		}
	}
}

@SergeiNikitin

Could you please ZIP and attach the JAR files that you are using at your end to reproduce the same issue at our end? Thanks for your cooperation.

This is the code without any third party imports:

import com.aspose.email.*;

import java.io.File;
import java.util.Calendar;
import java.util.Date;

class MapiCalendarExceptionInfoTest {

	public static void main(String[] args) throws Exception {
		new MapiCalendarExceptionInfoTest().test();
	}

	void test() throws Exception {
		Date startDate = addHours(new Date(), 1);
		Date endDate = addHours(startDate, 1);

		// Create the meeting
		MapiCalendar meeting = new MapiCalendar("", "Meeting", "root", startDate,
			endDate, "", new MapiRecipientCollection());

		// Set timeZone
		MapiCalendarTimeZone timeZone = new MapiCalendarTimeZone("EST");
		meeting.setStartDateTimeZone(timeZone);
		meeting.setEndDateTimeZone(timeZone);

		// Create the recurrence
		MapiCalendarEventRecurrence recurrence = new MapiCalendarEventRecurrence();
		recurrence.setRecurrencePattern(new MapiCalendarDailyRecurrencePattern());
		MapiCalendarRecurrencePattern pattern = recurrence.getRecurrencePattern();
		pattern.setPatternType(MapiCalendarRecurrencePatternType.Day);
		pattern.setPeriod(1);
		pattern.setWeekStartDay(DayOfWeek.Sunday);
		pattern.setOccurrenceCount(5);
		pattern.setEndType(MapiCalendarRecurrenceEndType.EndAfterNOccurrences);
		meeting.setRecurrence(recurrence);

		// Modify the occurrence
		MapiCalendarExceptionInfo exceptionInfo = new MapiCalendarExceptionInfo();
		Date exceptionStartDate = addHours(startDate, 24);
		Date exceptionEndDate = addHours(exceptionStartDate, 1);
		exceptionInfo.setBody("Modified description");
		exceptionInfo.setOriginalStartDate(exceptionStartDate);
		exceptionInfo.setStartDateTime(exceptionStartDate);
		exceptionInfo.setEndDateTime(exceptionEndDate);
		pattern.getModifiedInstanceDates().addItem(exceptionStartDate);
		pattern.getDeletedInstanceDates().addItem(exceptionStartDate);
		pattern.getExceptions().addItem(exceptionInfo);

		// Store to PST
		String file = System.getProperty("java.io.tmpdir") + File.separator + "MapiCalendarToPST" + System.currentTimeMillis() + " _out.pst";
		String calendarName = "Calendar";
		FolderInfo calendarFolder;
		try (PersonalStorage pst = PersonalStorage.create(file, FileFormatVersion.Unicode)) {
			calendarFolder = pst.createPredefinedFolder(calendarName, StandardIpmFolder.Appointments);
			calendarFolder.addMapiMessageItem(meeting);
		}

		// Load from PST
		PersonalStorage storage = PersonalStorage.fromFile(file);
		FolderInfo folderInfo = storage.getRootFolder().getSubFolder(calendarName);
		MessageInfoCollection messageInfoCollection = folderInfo.getContents();
		String diffMessage = "Occurrence %s date:\nExpected:%s\nActual\t:%s";
		for (MessageInfo messageInfo : messageInfoCollection) {
			MapiCalendar calendar = (MapiCalendar) storage.extractMessage(messageInfo).toMapiMessageItem();
			if (calendar.getStartDate() != calendar.getRecurrence().getRecurrencePattern().getStartDate()) {
				throw new Exception(String.format(diffMessage, "start", calendar.getStartDate(), calendar.getRecurrence().getRecurrencePattern().getStartDate()));
			}
			if (calendar.getStartDate() != calendar.getRecurrence().getRecurrencePattern().getEndDate()) {
				throw new Exception(String.format(diffMessage, "end", calendar.getEndDate(), calendar.getRecurrence().getRecurrencePattern().getEndDate()));
			}
		}
	}

	private Date addHours(Date date, int amount) {
		java.util.Calendar cal = Calendar.getInstance();
		cal.setTime(date);
		cal.add(Calendar.HOUR, amount);
		return cal.getTime();
	}
}

@SergeiNikitin

We have logged this problem in our issue tracking system as EMAILJAVA-35019. You will be notified via this forum thread once this issue is resolved.

We apologize for your inconvenience.

Is this issue already resolved? I didn’t find any information about it in the release notes.

Hello, @SergeiNikitin

I will check it and let you know the details. Thanks.

Hi,
This is is long time not resolved, we’re paying customers and this issue makes your library not useful.
Please fix this ASAP !!!

@slavago

We are in communication with our product team about the ETA of this issue. We will inform you once there is an update available on it. We apologize for your inconvenience.

@slavago

Hopefully, the fix of this issue will be available in the next version of Aspose.Email for Java i.e. 22.12. Please note that this ETA is not final at the moment. We will be sure to inform you once there is an update available on it.

Thanks, will wait

@slavago, @SergeiNikitin

We have prepared hotfix release to test this issue on the your side. Please use this release and let us know how it goes on your side.

Also, you need to use “Eastern Standard Time” time zone ID instead of “EST”. The Outlook does not recognize “EST” time zone properly.

MapiCalendarTimeZone timeZone = new MapiCalendarTimeZone("Eastern Standard Time");

Hi, Thanks.
Seems that this hotfix is working, is this the stable version or should we expect usual build on your usual release cycle ?

@slavago

Thanks for your feedback. You can use this hotfix at your end for your issue. However, we suggest you please wait for next release of Aspose.Email i.e. 22.12 and use it. It will contain fix of many issues and features also.

Thanks, any ETA for 22.12 ?

@slavago

The next release of Aspose.Email for .NET will be published by the end of this month (December 2022).

Thanks,
Is java version will be released also next days ?

@slavago

Hopefully, the next release of Aspose.Email for Java will be published in the first week of January 2023. We will inform you via this forum thread once it is released.

Hi, is there any update about the release ?
Thanks

Hello @slavago,

Thanks.