Menu

Durations only parsed as milliseconds?

2005-06-17
2013-06-05
  • tim brennan

    tim brennan - 2005-06-17

    It looks to me like the DurationFormat class only knows how to parse durations into milliseconds.  While I certainly like the simplicity of it, I don't think you can get away with it from a correctness standpoint.

    For instance, imagine an event starting at 9am with duration of 1 day that crosses a Daylight/Standard time flip.  Using your duration parsing code, the client would make the event 24hrs long instead of 23 or 25 (depending on which way the clock shifted). 

    Unfortunately, because there is "lost" information in the parsing, I don't see a way to 'get it right' using your parsing code. 

    Am I missing something here (definitely possible)?

     
    • Mike DOuglass

      Mike DOuglass - 2005-06-20

      The rfc states "The format can represent durations in terms of weeks, days, hours, minutes, and seconds"

      An int array or class consisting of those values would allow us to use the calendar classes to calculate a correct new alarm time.

       
    • Ben Fortuna

      Ben Fortuna - 2005-06-20

      Hi guys,

      Yup I agree. I'm going to create a new class to represent a duration, as it is used in more than just the Duration property (i.e. Trigger and Period also use this).

      regards,
      ben

       
    • tim brennan

      tim brennan - 2005-06-20

      I suspect that you're going to run into a similar problem with DtStart and DtEnd --> the current implementations implicitly convert the values into java Date objects which are always in the local timezone....this appears to lead to another case of lost information if the event is created in another timezone. 

      In the DtStart case this causes problems with Recurrences: if someone in Indiana (most of which is in Eastern time zone but does *not* observe daylight savings time) schedules an appointment with me (in Pacific time zone) I will calculate incorrect Recurrence Instances if I simply convert their DtStart to Pacific and expand out from there... when the recurrence expansion crosses the clock-change it will change the start time, since my local time changed -- however the Organizer's time did *NOT* change.

      I think what you need here is some kind of data structure which holds a DateTime-Timezone pair..(maybe a java.util.Calendar object?)  ....unfortunately you probably need percolate this change through various other APIs and it might be somewhat painful, but I don't quite see how to get it right without doing this (hopefully I'm wrong here)...

      Note that some times in iCal are _always_ specified in GMT (e.g. recurrence instances and free-busy times) so those can go ahead and use Date() or long values.

       
      • Ben Fortuna

        Ben Fortuna - 2005-06-20

        Hi Tim,

        I think this relates to a conversation I've had earlier with another iCal4j user. To save time I'll paste my response here:

        You need to ensure the java timezone is correct for your date arguments to setTime().ie.

        1. For creating a DtStart in utc time:

        // might have to check that timezone id.. i'm just guessing
        Date time = java.util.Calendar.getInstance(TimeZone.getTimeZone("UTC")).getTime();
        dtstart.setTime(time);
        dtstart.setUtc(true);

        2. For creating a local (timezone-specific) DtStart:

        // uses default timezone..
        Date time = java.util.Calendar.getInstance().getTime();
        dtstart.setTime(time);
        dtstart.setUtc(false);
        dtstart.getParameters().add(tzIdParam); // where tzIdParam represents
        your local timezone

        3. For a local DtStart (not tied to any timezone):

        // timezone does not matter in this case..
        Date time = java.util.Calendar.getInstance().getTime();
        dtstart.setTime(time);
        dtstart.setUtc(false);
        // no tzIdParam specified so its a "floating" local time..

        It does seem cumbersome, but I don't want to disregard the timezone information supplied by Java. Perhaps there is room for convenience methods for common approaches to this problem..

        regards,
        ben

         
      • Ben Fortuna

        Ben Fortuna - 2005-06-25

        Tim,

        Just to let you know I am going to implement something along the lines of your suggestion (holding timezone information). I think it probably will be a painful change, but I think its best to get it right sooner rather than later..

        b.

         
    • tim brennan

      tim brennan - 2005-06-21

      Right - it works OK on the sending side, but on the receiving side how do I retreive the specified TimeZone?  Sure, I can call getDate() but that returns me msecs time GMT, it doesn't tell me what TimeZone the request came in.  I guess I could manually look at the TZID parameter, but then I have to go parse through the VTimezones specified and then construct a java TimeZone from that....

       
      • Ben Fortuna

        Ben Fortuna - 2005-06-21

        Hi Tim,

        Currently all dates parsed by iCal4j (DateFormat/DateTimeFormat) are either in "UTC" time, or in your local timezone, as we don't actually check for the TzId parameter when parsing dates in local time.

        The main implication of this is that the Java timezone associated with a date does not necessarily correlate to the iCalendar timezone for that date property. This shouldn't impact basic calendar use (i.e. they will display correctly), but could have implications if you plan to perform comparisons between dates in different timezones.

        I may look into reconciling the Java timezone with the iCalendar timezone, however this would mean that you will need to ensure the correct (multiple) timezones are used when displaying these dates.

        I welcome feedback or suggestions on how to approach this (or leave it the way it is).

        regards,
        ben

         
      • Ben Fortuna

        Ben Fortuna - 2005-06-21

        ..to answer your original question, about how to retrieve the specified timezone:

        You will need to use the TzId parameter. You should be able to do something like this:

        TzId tzId = (TzId) property.getParameters().getParameter(Parameter.TZID);
        java.util.TimeZone timezone = java.util.TimeZone.getTimeZone(tzId.getValue());

        I haven't tested it, but I think the iCalendar timezone IDs are the same as Java.

        regards,
        ben

         
    • tim brennan

      tim brennan - 2005-06-21

      OK this makes sense (that part about iCal4j not interpreting the passed-in timezone). 

      This will actually end up making your recurrence-expansion incorrect in cases where the remote timezone doesn't follow the same daylight/standard rules as the local timezone.  This is not a very common case, but as far as I can tell this is the entire reason that RFC2445 has the TimeZone model that it has -- outside of Recurrences you can do just about everything just using GMT and an offset.

       
    • tim brennan

      tim brennan - 2005-06-21

      Oh -- and the TZID name is **NOT** the same as the Java timezone identifier...

      The RFC-writing folks went to great lengths to make it clear they were not addressing the "globally unique timezone identifier" issue and the TZID is only guaranteed to refer to a VTIMEZONE definition unless it begins with "/" in which case:  "TZID represents a unique ID in a globally defined time zone registry (when such registry is defined)"

      I'll take a stab at writing a Java Timezone subclass which can be initialized from a VTIMEZONE -- it looks doable.  I'll let you know how it turns out.

       
      • Ben Fortuna

        Ben Fortuna - 2005-06-22

        Tim,

        Whilst technically the TzId may not match a Java timezone, for calendars generated with iCal4j this is most likely the case.

        The reason for this is that when retrieving a VTimeZone for a corresponding Java timezone, the Java timezone id is used to either load a definition from the classpath or create a new VTimeZone based on the Java timezone's properties (see VTimeZone.getVTimeZone(TimeZone)). Of course any loaded VTimeZone definitions may contain a different TzId, however I haven't seen examples of this yet (see libical for some VTimeZone definitions).

        I understand this probably needs improving to make it technically correct, but just thought I'd clarify idea behind the current implementation.

        regards,
        ben

         
    • Ben Fortuna

      Ben Fortuna - 2005-06-23

      Hi guys,

      Just thought I'd announce the introduction of a new type to represent durations: net.fortuna.ical4j.model.Dur.

      I've performed some very basic testing, and so far it seems ok (I don't think its broken any of the unit tests). If you are feeling impatient you can check it out from CVS, otherwise it will be in the next release.

      As usual try your hardest to break it, and if you have any additions to unit tests that would also be appreciated.

      As a side note, I've noticed that an example in the RFC displays a duration with zero (0) minutes as follows:

      P15DT5H0M20S

      Currently iCal4j doesn't do this, although it quite easily could. I'm just a little unsure as to the rules for displaying duration components with a zero value (i.e. should it just be display if the values either side are non-zero?). Feedback is appreciated.

      regards,
      ben

       

Log in to post a comment.