class Buryspam::DateRange

Specialized form of Range to represent a time span between two dates. This is used primarily to limit the amount of mail used to initialize the Bayesian database. (The dates are actually represented internally as Time objects.)

Constants

ABS_DATE_RE
MAX_DATE
MIN_DATE
REL_DATE_RE

Public Class Methods

new(range) click to toggle source

Creates an appropriate date range for the following range parameters:

1. range = nil || ""         => MIN_DATE..MAX_DATE
2. range = "<date>..<date>"  => <date>..<date>
3. range = "-<date>"         => MIN_DATE..<date>
4. range = "<date>"          => <date>..MAX_DATE

Where <date> is either an absolute date or date relative to today. See ::to_date for expected date formats.

If a date range string is given (2, above) then negative relative dates refer to dates in the past and positive relative dates are in the future. A negative sign prefixing an absolute date is ignored. The two dates are swapped if they are out of order.

If only one date is given (3 and 4, above), then a negative date (relative or absolute) will generate a range from MIN_DATE to the specified date, whereas a positive date (relative or absolute) will generate a range from the specified date to MAX_DATE. In both cases a relative date is always in the past. (e.g., "1m" refers to one month ago).

MIN_DATE         NOW             MAX_DATE
 |                |               |
            -1m                           (negative relative date)
 |===========|
             |====================|
             1m                           (positive relative date)

        -2005-03-02                       (negative absolute date)
 |===========|
             |====================|
         2005-03-02                       (positive absolute date)
# File buryspam.rb, line 509
def initialize(range)
  begin
    # 1.
    if range.nil? || range.strip.empty?
      super(MIN_DATE, MAX_DATE)
    # 2.
    elsif /^(.*)\s*\.\.\s*(.*)$/.match(range)
      start, finish = to_date(range.first), to_date(range.last)
      start, finish = finish, start if start > finish
      super(start, finish)
    # 3.
    elsif range[0] == --
      super(MIN_DATE, DateRange.to_date(range))
    # 4.
    else
      super(DateRange.to_date("-" + range), MAX_DATE)
    end
  rescue ArgumentError
    raise "#$!: #{range}"
  end
end

Private Class Methods

to_date(date, base = Time.now) click to toggle source

Converts a string representing a date to a Time object. The date may either be absolute date of the form:

-?YYYY-MM-DD

(the minus sign is ignored) or a date relative to the given base date (which defaults to today).

Relative dates are of the form:

-?<num>(d|w|m|y)

where the units d, w, m, y stand for days, weeks, months and years, respectively. Negative relative dates refer to dates before the base date.

# File buryspam.rb, line 545
def self.to_date(date, base = Time.now)
  if ABS_DATE_RE.match(date)
    # Note that any '-' prefix is ignored.
    return Time.mktime($1.to_i, $2.to_i, $3.to_i)
  elsif REL_DATE_RE.match(date)
    sign, num, units = $1, $2.to_i, $3
    num = -num if sign == "-"
    base = DateTime.parse(base.to_s)
    date = case units
             when "d" then base + num
             when "w" then base + 7 * num
             when "m" then base >> num
             when "y" then base >> 12 * num
           end
    return Time.mktime(date.year, date.month, date.day,
                       date.hour, date.min, date.sec)
  else
    raise ArgumentError, "Invalid date"
  end
end