Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DTSTAMP should be in UTC without TimeZone property #89

Closed
kdaveid opened this issue Aug 4, 2016 · 7 comments
Closed

DTSTAMP should be in UTC without TimeZone property #89

kdaveid opened this issue Aug 4, 2016 · 7 comments

Comments

@kdaveid
Copy link
Collaborator

kdaveid commented Aug 4, 2016

As of RFC 4.8.7.2 Date/Time Stamp here or here the DTSTAMP property should be of UTC but without the TimeZone property.

Unfortunately (as I see it) we have no influence on this particular DateTime property during serialization.

Or do you have any ideas how to strip the TZID when serialize this property?

EnsureProperties() method
Additionally and in this matter I propose the followin code change for the default value of DTSTAMP:

if (DtStamp == null)
{
var now = DateTime.SpecifyKind(DateTime.Today.Add(DateTime.UtcNow.TimeOfDay), DateTimeKind.Utc);
DtStamp = new CalDateTime(now);
}

This way the CalDateTime() variable has the property IsUniversalTime set true.

Original:

if (DtStamp == null)
{
  // Here, we don't simply set to DateTime.Now because DateTime.Now contains milliseconds, and
  // the iCalendar standard doesn't care at all about milliseconds.  Therefore, when comparing
  // two calendars, one generated, and one loaded from file, they may be functionally identical,
  // but be determined to be different due to millisecond differences.
  var now = DateTime.Now;
  DtStamp = new CalDateTime(now.Year, now.Month, now.Day, now.Hour, now.Minute, now.Second);
}

From here.

The problem is we get the followin output when serializing:

BEGIN:VCALENDAR
PRODID:TESTCAL
VERSION:2.0
X-WR-CALNAME:X-WR-CALNAME:Test
BEGIN:VEVENT
DESCRIPTION:Description
DTEND;TZID=W. Europe Standard Time:20160804T150000
DTSTAMP;TZID=UTC:20160804T110635Z
DTSTART;TZID=W. Europe Standard Time:20160804T140000
SEQUENCE:0
SUMMARY:Test-Event
UID:1234
END:VEVENT
END:VCALENDAR

With ical-validator we get Parser error at line 8: Cannot set timezone for UTC properties.

When removed we have no errors.

@rianjs
Copy link
Collaborator

rianjs commented Aug 12, 2016

(Apologies for the delayed response; I have been on a long holiday out of the country.)

Looks like you have a concrete proposal. Can you open a pull request with these changes, making sure the existing unit tests pass? Once Khalid merges #87, all tests should be green.

@jhsowter
Copy link

Hi everyone

I ran into this issue as well, so I've attempted a fix. Let me know if there's anything I can do to help get this in. Cheers.

@kdaveid
Copy link
Collaborator Author

kdaveid commented Aug 17, 2016

Hi Jack
Thanks for your contribution. Your solution is right within spec:

The TZID property parameter MUST NOT be applied to DATE-TIME or TIME
properties whose time values are specified in UTC.

Problem is that TZID is now being serialized just without value. This is not solving the problem. The output is now:

BEGIN:VCALENDAR
PRODID:TESTCAL
VERSION:2.0
X-WR-CALNAME:TENANT (Test)
BEGIN:VEVENT
CATEGORIES:Vacation
CLASS:PRIVATE
DESCRIPTION:Description
DTEND;TZID=W. Europe Standard Time:20160817T100000
DTSTAMP;TZID=:20160817T063231Z
DTSTART;TZID=W. Europe Standard Time:20160817T090000
LOCATION:Island on Bahamas
PRIORITY:1
SEQUENCE:0
SUMMARY:Test-Event
UID:1ccaf7dd-9d47-430e-9e26-2c1d21a95b76
X-MICROSOFT-CDO-BUSYSTATUS:BUSY
END:VEVENT
END:VCALENDAR

Which is is validated as Parser error at line 10: [DTSTAMP] Unparseable date: ""

Therefore the method should remove the previsously* added TZID like so:

if(dt.IsUniversalTime)
{
    dt.Parameters.Remove("TZID");
}
    else if (dt.TzId != null)
{
   dt.Parameters.Set("TZID", dt.TzId);
}

Your test TZIDPropertyMustNotBeAppliedToUtcDateTime() will always be true because it does not check for the TZID property - you're just comparing the string value.

I've updated your test in a rather clumsy way but it passes.

[Test]
public void TZIDPropertyMustNotBeAppliedToUtcDateTime()
{
    var ical = new Ical.Net.Calendar();
    var evt = new Ical.Net.Event();
    evt.DtStamp = new CalDateTime(new DateTime(2016, 8, 17, 2, 30, 0, DateTimeKind.Utc));
    ical.Events.Add(evt);

    var serializer = new Ical.Net.Serialization.iCalendar.Serializers.CalendarSerializer();
    var serializedCalendar = serializer.SerializeToString(ical);

    var lines = serializedCalendar.Split(new string[] { "\r\n" }, StringSplitOptions.RemoveEmptyEntries).ToList();
    var result = lines.First(s => s.StartsWith("DTSTAMP"));
    Assert.AreEqual("DTSTAMP:20160817T023000Z", result);
}

I'll create a merge request for this - with your parts in it if you're ok with it.

*Initialization of DateTime: Initialize(value, tzId, null); where tzId defaults to null but will be added as parameter.

@khalidabuhakmeh
Copy link
Collaborator

I reviewed the PRs and they LGTM. It would be nice to have an CI build going which I can setup on AppVeyor if you would like at some point. #86

@rianjs
Copy link
Collaborator

rianjs commented Aug 17, 2016

@kdaveid - Can this be closed with the merger of your PRs?

@rianjs rianjs changed the title Date/Time Stamp should be in UTC without TimeZone property DTSTAMP should be in UTC without TimeZone property Aug 17, 2016
@jhsowter
Copy link

Thanks guys, really appreciated :)

@kdaveid
Copy link
Collaborator Author

kdaveid commented Aug 18, 2016

@rianjs Sure Rian, go ahead and close it.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants