Module: Timet::TimeHelper

Included in:
Application
Defined in:
lib/timet/time_helper.rb

Overview

This module provides helper functions for working with time and dates. It includes methods for:

  • formatting timestamps into a specific format

  • calculating the duration between two timestamps

  • converting a Date object to a timestamp

Class Method Summary collapse

Class Method Details

.append_tag_to_hour_blocks(hour_blocks, tag) ⇒ Hash

with that hour block.

Parameters:

  • hour_blocks (Hash)

    A hash where each key represents an hour block and the value is some data associated

  • tag (Object)

    The tag to append to each value in the hash.

Returns:

  • (Hash)

    The modified hash with the tag appended to each value.



229
230
231
232
233
234
# File 'lib/timet/time_helper.rb', line 229

def self.append_tag_to_hour_blocks(hour_blocks, tag)
  hour_blocks.each do |key, value|
    hour_blocks[key] = [value, tag]
  end
  hour_blocks
end

.beginning_of_day(time = Time.now) ⇒ Time

Returns a Time object representing the start of the given day (midnight).

Examples:

Get beginning of current day

TimeHelper.beginning_of_day # => 2024-12-07 00:00:00

Get beginning of specific day

time = Time.new(2024, 12, 7, 15, 30, 45)
TimeHelper.beginning_of_day(time) # => 2024-12-07 00:00:00

Parameters:

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

    The time for which to find the beginning of day (defaults to current time).

Returns:

  • (Time)

    A new Time object set to midnight (00:00:00) of the given day.



247
248
249
# File 'lib/timet/time_helper.rb', line 247

def self.beginning_of_day(time = Time.now)
  Time.new(time.year, time.month, time.day)
end

.calculate_block_end_time_and_seconds(current_time, end_time, hour_blocks) ⇒ Array<(Time, Hash)>

Calculates the end time of the current block and the number of seconds in the block. Additionally, it updates the ‘hour_blocks` hash with the number of seconds for the current hour block.

in that block. ‘hour_blocks` hash.

Parameters:

  • current_time (Time)

    The current time.

  • end_time (Time)

    The end time of the overall period.

  • hour_blocks (Hash)

    A hash where each key represents an hour block and the value is the number of seconds

Returns:

  • (Array<(Time, Hash)>)

    An array containing the end time of the current block and the updated



213
214
215
216
217
218
219
220
221
222
223
# File 'lib/timet/time_helper.rb', line 213

def self.calculate_block_end_time_and_seconds(current_time, end_time, hour_blocks)
  current_hour = current_time.hour
  next_hour_boundary = Time.new(current_time.year, current_time.month, current_time.day, current_hour + 1)

  block_end_time = [next_hour_boundary, end_time].min
  seconds_in_block = (block_end_time - current_time).to_i
  hour_block = current_time.strftime('%H')
  hour_blocks[hour_block] += seconds_in_block

  [block_end_time, hour_blocks]
end

.calculate_duration(start_time, end_time) ⇒ Integer

Calculates the duration between two timestamps.

Examples:

Calculate the duration between two timestamps

TimeHelper.calculate_duration(1633072800, 1633076400) # => 3600

Parameters:

  • start_time (Integer)

    The start timestamp.

  • end_time (Integer, nil)

    The end timestamp. If nil, the current timestamp is used.

Returns:

  • (Integer)

    The duration in seconds.



57
58
59
60
# File 'lib/timet/time_helper.rb', line 57

def self.calculate_duration(start_time, end_time)
  end_time = end_time ? Time.at(end_time) : current_timestamp
  (end_time - start_time).to_i
end

.calculate_end_time(start_date, end_date) ⇒ Integer

Calculates the end time based on the start date and end date.

Examples:

Calculate the end time

TimeHelper.calculate_end_time(Date.new(2021, 10, 1), Date.new(2021, 10, 2)) # => 1633159200

Parameters:

  • start_date (Date)

    The start date.

  • end_date (Date, nil)

    The end date. If nil, the start date + 1 day is used.

Returns:

  • (Integer)

    The end timestamp.



81
82
83
84
# File 'lib/timet/time_helper.rb', line 81

def self.calculate_end_time(start_date, end_date)
  end_date = end_date ? end_date + 1 : start_date + 1
  date_to_timestamp(end_date)
end

.count_seconds_per_hour_block(start_time, end_time, tag) ⇒ Hash

Counts the number of seconds for each hour block between the given start and end times.

This method calculates the number of seconds each event spans within each hour block and aggregates the results in a hash where the keys are the hour blocks (in ‘HH’ format) and the values are the total number of seconds for each hour block.

Examples:

start_time = 1728577349  # 8:30 AM
end_time = 1728579200    # 11:20 AM
result = count_seconds_per_hour_block(start_time, end_time)
# Output: {"08"=>1800, "09"=>1800, "10"=>3600, "11"=>1200}

Parameters:

  • start_time (Integer)

    The start time in seconds since the Unix epoch.

  • end_time (Integer)

    The end time in seconds since the Unix epoch. If not provided, the current time will be used.

Returns:

  • (Hash)

    A hash where the keys are the hour blocks (in ‘HH’ format) and the values are the total number of seconds for each hour block.



189
190
191
192
193
194
195
196
197
198
199
200
201
202
# File 'lib/timet/time_helper.rb', line 189

def self.count_seconds_per_hour_block(start_time, end_time, tag)
  hour_blocks = Hash.new(0)

  current_time = Time.at(start_time)
  end_time = Time.at(end_time || current_timestamp)

  while current_time < end_time
    block_end_time, hour_blocks = calculate_block_end_time_and_seconds(current_time, end_time, hour_blocks)

    current_time = block_end_time
  end

  append_tag_to_hour_blocks(hour_blocks, tag)
end

.create_new_datetime(base_date_time, parsed_time_component) ⇒ Time

Creates a new datetime object.

Parameters:

  • base_date_time (Time)

    The base date and time.

  • parsed_time_component (Time)

    The parsed time component.

Returns:

  • (Time)

    The new datetime object.



257
258
259
260
261
262
263
264
265
266
# File 'lib/timet/time_helper.rb', line 257

def self.create_new_datetime(base_date_time, parsed_time_component)
  Time.new(
    base_date_time.year,
    base_date_time.month,
    base_date_time.day,
    parsed_time_component.hour,
    parsed_time_component.min,
    parsed_time_component.sec
  )
end

.current_timestampInteger

Returns the current timestamp.

Examples:

Get the current timestamp

TimeHelper.current_timestamp

Returns:

  • (Integer)

    The current timestamp.



168
169
170
# File 'lib/timet/time_helper.rb', line 168

def self.current_timestamp
  Time.now.utc.to_i
end

.date_to_timestamp(date) ⇒ Integer

Converts a Date object to a timestamp.

Examples:

Convert a Date object to a timestamp

TimeHelper.date_to_timestamp(Date.new(2021, 10, 1)) # => 1633072800

Parameters:

  • date (Date)

    The Date object to convert.

Returns:

  • (Integer)

    The timestamp.



69
70
71
# File 'lib/timet/time_helper.rb', line 69

def self.date_to_timestamp(date)
  date.to_time.to_i
end

.extract_date(items, idx) ⇒ String?

Extracts the date from a list of items based on the index.

Examples:

Extract the date from a list of items

items = [[1, 1633072800], [2, 1633159200]]
TimeHelper.extract_date(items, 1) # => '2021-10-02'

Parameters:

  • items (Array)

    The list of items.

  • idx (Integer)

    The index of the current item.

Returns:

  • (String, nil)

    The date string in ‘YYYY-MM-DD’ format, or nil if the date is the same as the previous item.



95
96
97
98
99
100
101
# File 'lib/timet/time_helper.rb', line 95

def self.extract_date(items, idx)
  current_start_date = items[idx][1]
  date = TimeHelper.timestamp_to_date(current_start_date)

  last_start_date = items[idx - 1][1] if idx.positive?
  date if idx.zero? || date != TimeHelper.timestamp_to_date(last_start_date)
end

.format_time(timestamp) ⇒ String?

Formats a timestamp into a specific format.

Examples:

Format a timestamp

TimeHelper.format_time(1633072800) # => '2021-10-01 12:00:00'

Parameters:

  • timestamp (Integer)

    The timestamp to format.

Returns:

  • (String, nil)

    The formatted time string in ‘YYYY-MM-DD HH:MM:SS’ format, or nil if the timestamp is nil.



17
18
19
20
21
# File 'lib/timet/time_helper.rb', line 17

def self.format_time(timestamp)
  return nil unless timestamp

  Time.at(timestamp).strftime('%Y-%m-%d %H:%M:%S')
end

.format_time_string(input) ⇒ String?

Formats a time string into a standard HH:MM:SS format.

Examples:

Format a time string

TimeHelper.format_time_string('123456') # => "12:34:56"
TimeHelper.format_time_string('1234567') # => "12:34:56"
TimeHelper.format_time_string('1234') # => "12:34:00"
TimeHelper.format_time_string('123') # => "12:30:00"
TimeHelper.format_time_string('12') # => "12:00:00"
TimeHelper.format_time_string('1') # => "01:00:00"
TimeHelper.format_time_string('127122') # => nil
TimeHelper.format_time_string('abc') # => nil

Parameters:

  • input (String)

    The input string to format.

Returns:

  • (String, nil)

    The formatted time string in HH:MM:SS format, or nil if the input is invalid.



117
118
119
120
121
122
123
124
125
126
127
# File 'lib/timet/time_helper.rb', line 117

def self.format_time_string(input)
  return nil if input.nil? || input.empty?

  digits = input.gsub(/\D/, '')[0..5]
  return nil if digits.empty?

  hours, minutes, seconds = parse_time_components(digits)
  return nil unless valid_time?(hours, minutes, seconds)

  format('%<hours>02d:%<minutes>02d:%<seconds>02d', hours: hours, minutes: minutes, seconds: seconds)
end

.parse_time_components(digits) ⇒ Array

Parses time components from a string of digits.

Examples:

Parse time components

TimeHelper.parse_time_components('123456') # => [12, 34, 56]

Parameters:

  • digits (String)

    The string of digits to parse.

Returns:

  • (Array)

    An array containing the hours, minutes, and seconds.



136
137
138
139
140
141
142
143
144
145
146
# File 'lib/timet/time_helper.rb', line 136

def self.parse_time_components(digits)
  padded_digits = case digits.size
                  when 1 then "0#{digits}0000"
                  when 2 then "#{digits}0000"
                  when 3 then "#{digits}000"
                  when 4 then "#{digits}00"
                  else digits.ljust(6, '0')
                  end

  padded_digits.scan(/.{2}/).map(&:to_i)
end

.timestamp_to_date(timestamp) ⇒ String?

Converts a timestamp to a date string.

Examples:

Convert a timestamp to a date string

TimeHelper.timestamp_to_date(1633072800) # => '2021-10-01'

Parameters:

  • timestamp (Integer)

    The timestamp to convert.

Returns:

  • (String, nil)

    The date string in ‘YYYY-MM-DD’ format, or nil if the timestamp is nil.



30
31
32
33
34
# File 'lib/timet/time_helper.rb', line 30

def self.timestamp_to_date(timestamp)
  return nil unless timestamp

  Time.at(timestamp).strftime('%Y-%m-%d')
end

.timestamp_to_time(timestamp) ⇒ String?

Converts a timestamp to a time string.

Examples:

Convert a timestamp to a time string

TimeHelper.timestamp_to_time(1633072800) # => '12:00:00'

Parameters:

  • timestamp (Integer)

    The timestamp to convert.

Returns:

  • (String, nil)

    The time string in ‘HH:MM:SS’ format, or nil if the timestamp is nil.



43
44
45
46
47
# File 'lib/timet/time_helper.rb', line 43

def self.timestamp_to_time(timestamp)
  return nil unless timestamp

  Time.at(timestamp).strftime('%H:%M:%S')
end

.valid_time?(hours, minutes, seconds) ⇒ Boolean

Validates the time components.

Examples:

Validate time components

TimeHelper.valid_time?(12, 34, 56) # => true
TimeHelper.valid_time?(25, 34, 56) # => false

Parameters:

  • hours (Integer)

    The hours component.

  • minutes (Integer)

    The minutes component.

  • seconds (Integer)

    The seconds component.

Returns:

  • (Boolean)

    True if the time components are valid, otherwise false.



158
159
160
# File 'lib/timet/time_helper.rb', line 158

def self.valid_time?(hours, minutes, seconds)
  hours < 24 && minutes < 60 && seconds < 60
end