TL;DR I’d like:
-
Duration
to have a formalto_formatted_s
method to more finely control output, - methods that generate
Range
s withTimeWithZone
s at either end (similar toall_day
) - flexibility in one or both of the above to handle non-overlapping ranges (
all_day
isn’t exactly24.hours
long) - a method to determine the
Duration
of aRange
.
I’ve been working on a class that is concerned with a range of time. This can either be relative to the current time (e.g. the past 1.hour
), or a fixed window (Time.zone.now.all_day
). In either case, I also want to represent this range of time to the user (e.g. to say In the last 1 hour
or every 24 hours
).
Some things I’ve come up against with this include:
-
converting between a
Duration
and aRange
. In the same way that there is1.hour.ago
, it would be nice to have similar methods that semantically capture differences in time as ranges. Where I’ve done so manually, especially relative to the current time, I’ve needed to usethen
to make sure I’m working relative to the same moment in time if I’m usingTime.zone.now
:Time.zone.now.then { |time| duration.before(time).advance(subsec: FRACTION_OF_A_SECOND)..time }
-
converting
Duration
s toString
s. For my use case, it’s been fine to useduration.in_hours.ceil
(more on theceil
later) to capture a number of hours. But it’d be good to have all the flexibility ofActiveSupport::Duration#inspect
to hand, as the logic is there to create much nicer output, potentially. For example, in the following scenario:ActiveSupport::Duration.build(36.hours.in_seconds).inspect => "1 day and 12 hours"
It would be nice to be able to set some upper limit on
build
to make sure it doesn’t coerce what could be24.hours
into1.day
and return the string36 hours
. -
combinations of the above. Where I’ve manually created
Range
s based onDuration
s, e.g.:Time.zone.now.then { |time| duration.before(time).advance(subsec: FRACTION_OF_A_SECOND)..time }
I’ve needed to do as I’ve done in that example there and advance the start or end of the range forwards or backwards by a fraction of a second so that it’s not an overlapping period of time. That is to say,
Time.zone.now.then { 24.hours.after(_1).._1 }
is not equivalent toall_day
when called precisely at midnight, because theend
of the range will be exactly midnight the next day, as opposed to a split-second before (23:59:59.999...
) as we see inall_day
.This is something that I hope methods that generate
Range
s bounded byTimeWithZone
s would take into account and allow me not to worry about, so that I don’t need aFRACTION_OF_A_SECOND
constant in my app.
I’m happy to write failing tests for this and perhaps even resolve it upstream if there’s demand.