Skip to content

Consider sub-second precision #70

@edwardloveall

Description

@edwardloveall

ActiveSupport's TimeWithZone (and ruby's Time) class support sub-second precision if the host system supports it:

require "rrule"
ruby_time = Time.now # 2025-09-17 12:02:59.535244 -0400
Time.zone = "America/New_York"
time_with_zone = Time.zone.now # Wed, 17 Sep 2025 12:03:18.962661000 EDT -04:00

But rrule does not:

require "rrule"
ruby_time = Time.now # 2025-09-17 12:05:43.144258 -0400
rrule = RRule::Rule.new('FREQ=DAILY;COUNT=5', dtstart: ruby_time)
rrule.all
#[Wed, 17 Sep 2025 16:05:43.000000000 UTC +00:00,
# Thu, 18 Sep 2025 16:05:43.000000000 UTC +00:00,
# Fri, 19 Sep 2025 16:05:43.000000000 UTC +00:00,
# Sat, 20 Sep 2025 16:05:43.000000000 UTC +00:00,
# Sun, 21 Sep 2025 16:05:43.000000000 UTC +00:00]

This can cause some subtle bugs if you're expecting times to match exactly. One example would be generating rrule instances from a set time, adding a duration to that time, and trying to find the matching rrule instance:

require "rrule"
Time.zone = "America/New_York"
time = Time.zone.now # Wed, 17 Sep 2025 12:17:33.014852000 EDT -04:00
rrule = RRule::Rule.new('FREQ=DAILY;COUNT=5', dtstart: time, tzid: "America/New_York")
rrule.all[2]    # Fri, 19 Sep 2025 12:17:33.000000000 EDT -04:00
(time + 2.days) # Fri, 19 Sep 2025 12:17:33.014852000 EDT -04:00
rrule.all[2] == (time + 2.days) # false
rrule.all[2] == (time + 2.days).floor # true

You have to .floor the time which loses precision and is likely not obvious to the developer.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions