TL;DR I’d like:
-
Durationto have a formalto_formatted_smethod to more finely control output, - methods that generate
Ranges withTimeWithZones at either end (similar toall_day) - flexibility in one or both of the above to handle non-overlapping ranges (
all_dayisn’t exactly24.hourslong) - a method to determine the
Durationof 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
Durationand 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 usethento 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
Durations toStrings. For my use case, it’s been fine to useduration.in_hours.ceil(more on theceillater) to capture a number of hours. But it’d be good to have all the flexibility ofActiveSupport::Duration#inspectto 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
buildto make sure it doesn’t coerce what could be24.hoursinto1.dayand return the string36 hours. -
combinations of the above. Where I’ve manually created
Ranges based onDurations, 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_daywhen called precisely at midnight, because theendof 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
Ranges bounded byTimeWithZones would take into account and allow me not to worry about, so that I don’t need aFRACTION_OF_A_SECONDconstant in my app.
I’m happy to write failing tests for this and perhaps even resolve it upstream if there’s demand.