Timezone Definition Problem

30 views
Skip to first unread message

Adam Williams

unread,
Nov 4, 2009, 12:13:25 PM11/4/09
to rica...@googlegroups.com
Hello,

I'm experiencing a problem where the events for one customer are
showing an hour behind their actual time. That is, the times are
correct in the application, but when the events are exported with
ri_cal and imported into iCal.app, the times of the events are an hour
earlier than they should be. All the other feeds I've tried are fine.

The problem can be resolved by changing two lines. In the DAYLIGHT
component of the single VTIMEZONE (America/New_York) of the document,

Times are behind an hour (exhibit A):

DTSTART:20090308T030000
RDATE:20090308T030000,20100314T030000

Times are correct (taken from a 'correct' feed, exhibit B):

DTSTART:20080309T030000
RDATE:20080309T030000,20090308T030000,20100314T030000

All the other properties are the same in the two documents.


I don't understand how the different DTSTART and extra RDATE make
things correct. Any insight would be greatly appreciated.


Adam Williams

Rick DeNatale

unread,
Nov 4, 2009, 12:41:12 PM11/4/09
to rica...@googlegroups.com
what's an example of a DTSTART from an event which is incorrect?

Is it between 20080309T030000 and 20090308T030000 ?

If so this would indicate a bug in figuring out which periods to
export in the VTIMEZONE
--
Rick DeNatale

Blog: http://talklikeaduck.denhaven2.com/
Twitter: http://twitter.com/RickDeNatale
WWR: http://www.workingwithrails.com/person/9021-rick-denatale
LinkedIn: http://www.linkedin.com/in/rickdenatale

Adam Williams

unread,
Nov 4, 2009, 12:58:41 PM11/4/09
to rica...@googlegroups.com
On Nov 4, 2009, at 12:41 PM, Rick DeNatale wrote:

DTEND;TZID=America/New_York;VALUE=DATE-TIME:20091029T094000
DTSTART;TZID=America/New_York;VALUE=DATE-TIME:20091029T092500

That event shows up as 9:25 AM, which is CORRECT.

> what's an example of a DTSTART from an event which is incorrect?

DTEND;TZID=America/New_York;VALUE=DATE-TIME:20091102T094000
DTSTART;TZID=America/New_York;VALUE=DATE-TIME:20091102T092500

That event shows up as 8:25 AM, which is INCORRECT.


Here is the complete definition of the VTIMEZONE:

BEGIN:VCALENDAR
PRODID;X-RICAL-TZSOURCE=TZINFO:-//com.denhaven2/NONSGML ri_cal gem//EN
CALSCALE:GREGORIAN
VERSION:2.0
BEGIN:VTIMEZONE
TZID;X-RICAL-TZSOURCE=TZINFO:America/New_York
BEGIN:STANDARD
DTSTART:20081102T010000
RDATE:20081102T010000,20091101T010000
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
TZNAME:EST
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:20090308T030000
RDATE:20090308T030000,20100314T030000
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
TZNAME:EDT
END:DAYLIGHT
END:VTIMEZONE

> Is it between 20080309T030000 and 20090308T030000 ?

Doesn't look like it.

> If so this would indicate a bug in figuring out which periods to
> export in the VTIMEZONE

Should I be looking for something wrong in our event data? Is it the
events that cause the additional information in the VTIMEZONE that
works:

DTSTART:20080309T030000
RDATE:20080309T030000,20090308T030000,20100314T030000

Based on my understanding of the RFC, I don't see how the older
DTSTART in that, or the additional RDATE of 20080309T030000, would
make any difference. iCal.app should be choosing the STANDARD
observance, shouldn't it? I suppose I don't really understand why it's
shifting the event's 20091102T092500 start time at all.

Thanks for such a great library, and your assistance in this, Rick.

Adam Williams

Rick DeNatale

unread,
Nov 4, 2009, 2:30:46 PM11/4/09
to rica...@googlegroups.com
I'll have to take a closer look when I have a bit more spare time.

dwayne purper

unread,
Nov 6, 2009, 2:15:23 PM11/6/09
to rica...@googlegroups.com
Hi folks:

I'm having trouble figuring out the best way to set up an RRULE.

Here's my setup:

Borrowing from your Eventually app, I have an Event model that has an ical() method, which returns the RiCal::Event.


------------------------------------------------------------------------------------------------

def ical
  @ical ||= RiCal.parse_string(ical_string || '').first || RiCal.Event
end
------------------------------------------------------------------------------------------------

I have a method for adding an rrule, where I just pass a hash to ical.add_rule.


------------------------------------------------------------------------------------------------
def add_rrule
  remove_rrule
  rules = { :freq => frequency, :wkst => wkst }
  ical.add_rrule rules
end
------------------------------------------------------------------------------------------------

I'm not allowing my users to do anything complicated at this point, so I only keep one rrule at a time. (That's why the "remove_rrule" method is there.)

What I want to do is add a "BYDAY" line, to allow recurrences like "every Tuesday and Thursday."

I see from the source that there's a RecurringDay class. How do I use that to set (and get) the BYDAY property in the RRULE?

Thanks for any pointers.

--

Dwayne Purper


Adam Williams

unread,
Nov 6, 2009, 2:47:04 PM11/6/09
to rica...@googlegroups.com
On Nov 6, 2009, at 2:15 PM, dwayne purper wrote:

> I have a method for adding an rrule, where I just pass a hash to
> ical.add_rule.
>
> ------------------------------------------------------------------------------------------------
> def add_rrule
> remove_rrule
> rules = { :freq => frequency, :wkst => wkst }
> ical.add_rrule rules
> end
> ------------------------------------------------------------------------------------------------
>
> I'm not allowing my users to do anything complicated at this point,
> so I only keep one rrule at a time. (That's why the "remove_rrule"
> method is there.)

I believe you can simply use event.rrule=, with the value being the
hash, if you want to have only one rule.

> What I want to do is add a "BYDAY" line, to allow recurrences like
> "every Tuesday and Thursday."

I have in my hash:

hash[:byday] = ["2","4"]

> I see from the source that there's a RecurringDay class. How do I
> use that to set (and get) the BYDAY property in the RRULE?

When I read an imported document, I use this:

rules = event.rrule_property.first
rules.by_rule_list(:byday)


HTH,

Adam Williams

dwayne purper

unread,
Nov 6, 2009, 4:35:48 PM11/6/09
to rica...@googlegroups.com
Perfect!

Thanks, Adam, that's just what I needed.


--

Dwayne Purper


Rick DeNatale

unread,
Nov 6, 2009, 7:41:19 PM11/6/09
to rica...@googlegroups.com
On Fri, Nov 6, 2009 at 2:15 PM, dwayne purper <dwa...@futuracreative.com> wrote:

It looks like Adam got you over the hump, but...

> I see from the source that there's a RecurringDay class. How do I use that
> to set (and get) the BYDAY property in the RRULE?

I highly recommend NOT mucking with or directly using any RiCal
classes which aren't subclasses of RiCal::Component

Classes like RecuringDay are used internally for enumerating
occurrences and are subject to change, and will almost certainly
confuse you if you try to understand them. I know that they do me.
<G>

dwayne purper

unread,
Nov 7, 2009, 11:09:18 AM11/7/09
to rica...@googlegroups.com
Thanks, Rick, yes, I'd much rather use whichever public methods you set up; that would cause the least friction in the long run. I just didn't know what they were.

Since I've seen very little real-world tutorial type stuff on RiCal, I might write this up when I'm finished.

--

Dwayne Purper


Rick DeNatale

unread,
Nov 8, 2009, 6:28:24 PM11/8/09
to rica...@googlegroups.com

Okay,

I wrote the following spec. At first I thought I had a bug because I
had the expectations backward on what the offset should be for EDT vs
EST which made it look like the offsets were getting reversed, but
after trying in vain to 'debug' this realized that it should be -4
houts for EDT and -5 hours for EST not the other way around.

With that straightened out, all of the following passes without any
changes to RiCal itself. So I guess the net is that I can't seem to
reproduce your problem:

context "Adam's bug" do
before(:each) do
cal_string = <<ENDCAL


BEGIN:VCALENDAR
PRODID;X-RICAL-TZSOURCE=TZINFO:-//com.denhaven2/NONSGML ri_cal gem//EN
CALSCALE:GREGORIAN
VERSION:2.0
BEGIN:VTIMEZONE
TZID;X-RICAL-TZSOURCE=TZINFO:America/New_York
BEGIN:STANDARD
DTSTART:20081102T010000
RDATE:20081102T010000,20091101T010000
TZOFFSETFROM:-0400
TZOFFSETTO:-0500
TZNAME:EST
END:STANDARD
BEGIN:DAYLIGHT
DTSTART:20090308T030000
RDATE:20090308T030000,20100314T030000
TZOFFSETFROM:-0500
TZOFFSETTO:-0400
TZNAME:EDT
END:DAYLIGHT
END:VTIMEZONE

BEGIN:VEVENT
DESCRIPTION:First Event


DTEND;TZID=America/New_York;VALUE=DATE-TIME:20091029T094000
DTSTART;TZID=America/New_York;VALUE=DATE-TIME:20091029T092500

END:VEVENT
BEGIN:VEVENT
DESCRIPTION:Second Event


DTEND;TZID=America/New_York;VALUE=DATE-TIME:20091102T094000
DTSTART;TZID=America/New_York;VALUE=DATE-TIME:20091102T092500

END:VEVENT
END:VCALENDAR
ENDCAL
@cal = RiCal.parse_string(cal_string).first
@event1 = @cal.events.find {|e| e.description == "First Event"}
# Event 1 starts on 10/29/2009 which is in EDT
@event2 = @cal.events.find {|e| e.description == "Second Event"}
# Event 2 starts on 11/02/2009 at 09:25 local which is in EST
end

context "the timezone" do
before(:each) do
@tz = @cal.timezones.first
end

context "period for local time 20091029T092500" do
before(:each) do
@period = @tz.period_for_local(DateTime.parse("20091029T092500"))
end
it "should be a daylight period " do
@period.should be_dst
end

it "should have a tzoffsetto of -0400" do
@period.tzoffsetto.should == "-0400"
end
end
context "period for local time 20091029T092500" do
before(:each) do
@period = @tz.period_for_local(DateTime.parse("20091102T0925"))
end

it "should be a standard period" do
@period.should_not be_dst
end

it "should have a tzoffsetto of -0500" do
@period.tzoffsetto.should == "-0500"
end
end
end

context "event 1 which starts in EDT" do
before(:each) do
@start = @event1.dtstart
end

it "should be on October 29" do
@start.mon.should == 10
@start.day.should == 29
end

it "should be at 9:25" do
@start.hour.should == 9
@start.min.should == 25
end

it "should have the right 'zone'" do
# Which one depends on whether ActiveSupport is included
["-04:00", "EDT"].should include(@start.zone)
end

it "should have the right tzid" do
@start.tzid.should == "America/New_York"
end
end

context "event 2 which starts in EST" do
before(:each) do
@start = @event2.dtstart
end

it "should be on November 2" do
@start.mon.should == 11
@start.day.should == 2
end

it "should be at 9:25" do
@start.hour.should == 9
@start.min.should == 25
end

it "should have a right 'zone'" do
["-05:00", "EST"].should include(@start.zone)
end

it "should have the right tzid" do
@start.tzid.should == "America/New_York"
end
end
end

Adam Williams

unread,
Nov 10, 2009, 11:37:28 AM11/10/09
to rica...@googlegroups.com
Rick,

Thanks a ton for the investigation. I apologize for the late reply.

The feed that was suffering the problem is working again. Here is a
diff of the STANDARD VTIMEZONE component, where the left side is the
old one, and the right side is the new:

< BEGIN:STANDARD
< DTSTART:20081102T010000
< RDATE:20081102T010000,20091101T010000
< TZOFFSETFROM:-0400
< TZOFFSETTO:-0500
< TZNAME:EST
< END:STANDARD

21a15,21
> BEGIN:STANDARD
> DTSTART:20091101T010000
> RDATE:20091101T010000


> TZOFFSETFROM:-0400
> TZOFFSETTO:-0500
> TZNAME:EST
> END:STANDARD

So, without any changes to code, something is causing it to behave
differently. At this point, I would suspect that is has something to
do with the events. We are only including events that occur two weeks
ago forward - there are events that would not be in the feed now
(DTSTAMP;TZID=America/New_York;VALUE=DATE-TIME:20091110T112903) that
were then (DTSTAMP;TZID=America/New_York;VALUE=DATE-TIME:
20091104T112256) - for that reason and simply because the user has
added more events. Do you think it would be worthwhile to analyze the
data of the events that would have been found 6 days ago that are not
found today?

Adam Williams

Rick DeNatale

unread,
Nov 10, 2009, 1:02:49 PM11/10/09
to rica...@googlegroups.com
Well the change to standard time was a week or two ago wasn't it.

If you want to look at the older data, and you find a problem could
you please report it in the form of a failing spec or spec. Since
I've got a job now, I don't have as much time to reconstruct stuff
from small data snippets and diffs.

Adam Williams

unread,
Nov 10, 2009, 1:11:29 PM11/10/09
to rica...@googlegroups.com
On Nov 10, 2009, at 1:02 PM, Rick DeNatale wrote:

> Well the change to standard time was a week or two ago wasn't it.

It was indeed.

> If you want to look at the older data, and you find a problem could
> you please report it in the form of a failing spec or spec.

Yes, if I dig into it, I will.

> Since
> I've got a job now, I don't have as much time to reconstruct stuff
> from small data snippets and diffs.

Understood. Thanks again for your help.

Adam Williams

Reply all
Reply to author
Forward
0 new messages