Module: Familia::Features::Quantization::ModelClassMethods

Defined in:
lib/familia/features/quantization.rb

Overview

Familia::Quantization::ModelClassMethods

Instance Method Summary collapse

Instance Method Details

#in_bucket?(timestamp, quantum, bucket_time) ⇒ Boolean

Check if a timestamp falls within a quantized bucket

Examples:

Check if event falls in hourly bucket

event_time = Time.parse('2023-01-01 14:37:42')
bucket_time = Time.parse('2023-01-01 14:00:00')
User.in_bucket?(event_time, 1.hour, bucket_time)  # => true

Parameters:

  • timestamp (Time, Integer)

    The timestamp to check

  • quantum (Numeric)

    The quantum interval

  • bucket_time (Time, Integer)

    The bucket reference time

Returns:

  • (Boolean)

    true if timestamp falls in the bucket



348
349
350
351
352
353
354
355
# File 'lib/familia/features/quantization.rb', line 348

def in_bucket?(timestamp, quantum, bucket_time)
  timestamp = timestamp.to_i if timestamp.respond_to?(:to_i)
  bucket_time = bucket_time.to_i if bucket_time.respond_to?(:to_i)
  bucket_start = qstamp(quantum, time: Time.at(bucket_time))
  bucket_end = bucket_start + quantum - 1

  timestamp.between?(bucket_start, bucket_end)
end

#qstamp(quantum = nil, pattern: nil, time: nil) ⇒ Integer, String

Generates a quantized timestamp based on the given parameters

This method rounds the current time to the nearest quantum and optionally formats it according to the given pattern. It's useful for creating time-based buckets or keys with reduced granularity.

Examples:

Generate hourly bucket timestamp

User.qstamp(1.hour)  # => 1672531200 (rounded to hour boundary)

Generate formatted timestamp

User.qstamp(1.hour, pattern: '%Y%m%d%H')  # => "2023010114"

Using array syntax

User.qstamp([1.hour, '%Y%m%d%H'])  # => "2023010114"

With custom time reference

custom_time = Time.parse('2023-06-15 14:30:45')
User.qstamp(1.hour, time: custom_time)  # => 1686834000

Parameters:

  • quantum (Numeric, Array, nil) (defaults to: nil)

    The time quantum in seconds or an array of [quantum, pattern]

  • pattern (String, nil) (defaults to: nil)

    The strftime pattern to format the timestamp

  • time (Time, nil) (defaults to: nil)

    The reference time (default: current time)

Returns:

  • (Integer, String)

    A unix timestamp or formatted timestamp string

Raises:

  • (ArgumentError)

    If quantum is not positive



288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
# File 'lib/familia/features/quantization.rb', line 288

def qstamp(quantum = nil, pattern: nil, time: nil)
  # Handle array input format: [quantum, pattern]
  quantum, pattern = quantum if quantum.is_a?(Array)

  # Use default quantum if none specified
  # Priority: provided quantum > class default_expiration > 10.minutes fallback
  quantum ||= default_expiration || 10.minutes

  # Validate quantum value
  unless quantum.is_a?(Numeric) && quantum.positive?
    raise ArgumentError, "Quantum must be positive (#{quantum.inspect} given)"
  end

  # Delegate to Familia.qstamp for the actual calculation
  Familia.qstamp(quantum, pattern: pattern, time: time)
end

#qstamp_range(start_time, end_time, quantum, pattern: nil) ⇒ Array

Generate multiple quantized timestamps for a time range

Examples:

Generate hourly buckets for a day

start_time = Time.parse('2023-01-01 00:00:00')
end_time = Time.parse('2023-01-01 23:59:59')
User.qstamp_range(start_time, end_time, 1.hour)
# => [1672531200, 1672534800, 1672538400, ...] (24 hourly buckets)

Parameters:

  • start_time (Time)

    Start of the time range

  • end_time (Time)

    End of the time range

  • quantum (Numeric)

    Time quantum in seconds

  • pattern (String, nil) (defaults to: nil)

    Optional strftime pattern

Returns:

  • (Array)

    Array of quantized timestamps



319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
# File 'lib/familia/features/quantization.rb', line 319

def qstamp_range(start_time, end_time, quantum, pattern: nil)
  timestamps = []
  current = qstamp(quantum, time: start_time)
  end_bucket = qstamp(quantum, time: end_time)

  while current <= end_bucket
    timestamps << if pattern
                    Time.at(current).strftime(pattern)
                  else
                    current
                  end
    current += quantum
  end

  timestamps
end