rianjs / ical.net

ical.NET - an open source iCal library for .NET
MIT License
779 stars 230 forks source link

Serialization fails for "Pacific/Kiritimati" timezone #467

Open bigfighter opened 4 years ago

bigfighter commented 4 years ago

This can be reproduced on the master branch by running this new unit test:

[Test, Category("VTimeZone")]
public void VTimeZonePacificKiritimatiShouldSerializeProperly()
{
    var iCal = CreateTestCalendar("Pacific/Kiritimati");
    var serializer = new CalendarSerializer();
    Assert.DoesNotThrow(() => serializer.SerializeToString(iCal));
}

(A good place for the test would be \net-core\Ical.Net.CoreUnitTests\VTimeZoneTest.cs).

The error I'm getting is this: image

It looks to me like NodaTime cannot handle the difference between {-10} and {+14} in VTimeZone.cs:139.

(I don't know if it matters, but I'm running the test on a computer that is set to "(UTC +12:00) Auckland, Wellington".)

bigfighter commented 4 years ago

A potential (admittedly hacky) fix could be to replace delta = (previousInterval.WallOffset - oldestInterval.WallOffset).ToTimeSpan(); with this: delta = new TimeSpan(0, 0, previousInterval.WallOffset.Seconds - oldestInterval.WallOffset.Seconds);

bigfighter commented 4 years ago

I've created a pull request for this: https://github.com/rianjs/ical.net/pull/468

andreysavihin commented 3 years ago

Found another problem with "Pacific/Kiritimati" timezone. I'm trying serialize calendar to ical string.

var iCalendar = new Calendar();
iCalendar.AddTimeZone(TimeZoneInfo.FindSystemTimeZoneById("Line Islands Standard Time"));
var serializer = new CalendarSerializer();
var iCalendarString = serializer.SerializeToString(iCalendar);

As a result, i get the following

BEGIN:VCALENDAR
PRODID:-//github.com/rianjs/ical.net//NONSGML ical.net 4.0//EN
VERSION:2.0
BEGIN:VTIMEZONE
TZID:Line Islands Standard Time
X-LIC-LOCATION:Pacific/Kiritimati
BEGIN:STANDARD
DTSTART:19950102T010000
RRULE:FREQ=YEARLY;BYDAY=1MO;BYMONTH=1
TZNAME:+14
TZOFFSETFROM:+1500
TZOFFSETTO:+1400
END:STANDARD
END:VTIMEZONE
END:VCALENDAR

There is no daylight saving time in the "Pacific/Kiritimati" time zone, so the offset is +1500 incorrect. TZOFFSETFROM should be equal +1400. When I'm trying to deserialize this calendar

var calendarCollection = CalendarCollection.Load(iCalendarString);

I'm get an error

System.FormatException: '15 is not a valid UTC offset'

Similarly, I'm get the wrong offset for other time zones without daylight savings time. For example "Europe/Moscow" received +0400 but offset should be +0300.