Class: Slk::Support::TimeRangeParser

Inherits:
Object
  • Object
show all
Defined in:
lib/slk/support/time_range_parser.rb

Overview

Parses a scheduling window ("1:30p-3:30p", "2026-08-04 13:30-15:30") into a [start, end] pair of Unix timestamps.

Unlike DateParser, which resolves an input to a point in the past, this always resolves forward: a bare time at or before now rolls to tomorrow, and an end before the start rolls to the next day so overnight windows ("11p-1a") work.

The start date is written once and the end can only reach the following day, so this cannot express a multi-day window — slk status schedule --start/--end is the general form for that.

Constant Summary collapse

RANGE_PATTERN =
/\A(?:(\d{4}-\d{2}-\d{2})\s+)?#{TimeParser::TIME}\s*-\s*#{TimeParser::TIME}\z/i
EXAMPLE =
'1:30p-3:30p or 2026-08-04 13:30-15:30'
MAX_GUESSED_OVERNIGHT_MINUTES =

Longest overnight window accepted when a reading had to be guessed. Twelve hours is not a policy about window length — an explicit "8p-9a" is longer and fine — it is the point past which a guessed crossing can no longer be what the user meant.

12 * 60

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(now: Time.now) ⇒ TimeRangeParser

Returns a new instance of TimeRangeParser.



38
39
40
41
# File 'lib/slk/support/time_range_parser.rb', line 38

def initialize(now: Time.now)
  @now = now
  @clock = TimeParser.new(now: now)
end

Class Method Details

.match?(input) ⇒ Boolean

True when input looks like a time range, used to pick it out of argv.

Returns:

  • (Boolean)


36
# File 'lib/slk/support/time_range_parser.rb', line 36

def self.match?(input) = RANGE_PATTERN.match?(input.to_s.strip)

.parse(input, now: Time.now) ⇒ Array(Integer, Integer)

Returns start and end Unix timestamps.

Parameters:

  • input (String)

    the range to parse

  • now (Time) (defaults to: Time.now)

    reference point for rolling bare times forward

Returns:

  • (Array(Integer, Integer))

    start and end Unix timestamps



33
# File 'lib/slk/support/time_range_parser.rb', line 33

def self.parse(input, now: Time.now) = new(now: now).parse(input)

Instance Method Details

#parse(input) ⇒ Object

Raises:



43
44
45
46
47
48
49
50
51
52
53
54
# File 'lib/slk/support/time_range_parser.rb', line 43

def parse(input)
  match = RANGE_PATTERN.match(input.to_s.strip)
  raise TimeFormatError, "Invalid time range: #{input}. Use #{EXAMPLE}" unless match

  start_parts, end_parts = infer_meridiems(match)
  validate_range(input, start_parts, end_parts)

  date = start_date(match, start_parts)
  start_at = @clock.at(date, *start_parts)

  [start_at.to_i, end_time(date, start_at, end_parts).to_i]
end