Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

About this user

Matt Powell

« Newer Snippets
Older Snippets »
Showing 1-3 of 3 total  RSS 

Obfuscate email addresses in TextMate

// Textmate / e command for obfuscating email addresses

#!/usr/bin/env ruby

email = STDIN.read
url_email = email.gsub(/./) { |c| '%' + c.unpack('H2' * c.size).join('%').upcase }
html_email = url_email[1..-1].split(/%/).collect { |c| sprintf("&#%03d;", c.to_i(16)) }.join

print "<a href=\"mailto:#{url_email}\">#{html_email}</a>"

Partial iCal RECUR analogue in Ruby

// Implements salient bits of section 4.3.10 of the iCal spec (RFC2445)
// Doesn't support recurrence granularities of less than a day,
// or BYYEARDAY or BYWEEKNO, because... well, I couldn't be bothered ;)
// See also http://www.ietf.org/rfc/rfc2445.txt

require 'date'
require 'profiler' # for testing

class RecurringEvent
  def initialize(options = {})
    @options = check_options(options)
    @options[:freq] ||= :daily
    @options[:interval] ||= 1
    @options[:start_time] ||= Time.now - Time.now.sec
    @options[:by_month] = [ @options[:by_month] ].flatten if @options[:by_month]
    @options[:by_month_day] = [ @options[:by_month_day] ].flatten if @options[:by_month_day]
    @options[:by_day] = [ @options[:by_day] ].flatten if @options[:by_day]
    @options[:by_set_pos] = [ @options[:by_set_pos] ].flatten if @options[:by_set_pos]
    Date::DAYNAMES
  end
  
  def start_time
    @options[:start_time]
  end
  
  def start_date
    @start_date ||= Date.civil(start_time.year, start_time.month, start_time.day)
  end
  
  def frequency
    @options[:freq]
  end
  
  def each(from = nil, to = nil)
    from ||= Date.today - Date.today.mday
    to ||= (from >> 1) - 1
    times = in_range(from, to)
    
    times.each { |t| yield t } if block_given?
    times
  end
  
  alias_method :each_in, :each
  
private
  def in_range(from, to)
    window_from = from << 1
    window_to = to >> 1
    
    start = Date.civil(start_time.year, start_time.month, start_time.day)
    interval = @options[:interval] || 1

    s_year = start.year % interval
    s_month = (start.year * 12 + start.month) % interval
    s_week = start.week % interval
    s_day = start.julian_day % interval
    
    dates = (window_from..window_to).select { |d|
      in_interval = (interval == 1) or case frequency
      when :yearly  then d.year % interval == s_year
      when :monthly then (d.year * 12 + d.month) % interval == s_month
      when :weekly  then d.week % interval == s_week
      when :daily   then d.julian_day % interval == s_day
      end
    
      if in_interval
        match_by_parts(d)
      else
        false
      end
    }
    
    hours = @options[:by_hour] ? @options[:by_hour] : [ start_time.hour ]
    minutes = @options[:by_minute] ? @options[:by_minute] : [ start_time.min ]
    times = dates.collect { |d|
      hours.collect { |h|
        minutes.collect { |m|
          DateTime.civil(d.year, d.month, d.day, h, m, 0)
        }
      }
    }.flatten
    
    if @options[:by_set_pos]
      grouped_times = case frequency
      when :yearly then times.group_by { |t| t.year }
      when :monthly then times.group_by { |t| t.month }
      when :weekly then times.group_by { |t| t.week }
      when :daily then times.group_by { |t| t.day }
      end
      
      times = grouped_times.collect { |group|
        @options[:by_set_pos].collect { |i| group.at(i) }.compact
      }.flatten
    end
    
    times = times.first(@options[:count]) if @options[:count]
    to = @options[:until] if @options[:until] and @options[:until] < to
    range = (from..to)
    times.select { |t| range.include? t }
  end
  
  def match_by_parts(d)
    case frequency
    when :yearly, :daily then
      begin
        (@options[:by_month] ? @options[:by_month].include?(d.month) : d.month == start.month) and 
        (@options[:by_month_day] ? @options[:by_month_day].include?(d.day) : d.day == start.day) and
        (@options[:by_day].nil? or @options[:by_day].include?(d.week_day))
      end
    when :monthly then
      begin
        if @options[:by_month_day]
          @options[:by_month_day].include?(d.day)
        elsif @options[:by_day]
          @options[:by_day].include?(d.week_day)
        else
          d.day == start.day
        end
      end
    when :weekly then
      begin
        (@options[:by_month].nil? or @options[:by_month].include?(d.month)) and 
        (@options[:by_day] ? @options[:by_day].include?(d.week_day) : d.week_day == start.week_day)
      end
    else
      true
    end
  end
  
  def check_options(options)
    options
  end
end

class Date
  def week
    @week ||= julian_day / 7
  end
  
  def week_day
    @week_day ||= wday
  end
  
  def julian_day
    @julian_day ||= mjd
  end
end

class Array
  def group_by # => Array
    current_key = nil
    results = []
    current_set = []
    each do |item|
      key = yield(item)
      if key != current_key
        results << current_set unless current_set.empty?
        current_set = []
        current_key = key
      end
      current_set << item unless key === false
    end
    results << current_set unless current_set.empty?
    results
  end
end

Profiler__::start_profile
e = RecurringEvent.new :start_time => Time.local(2007, 1, 1, 12, 34), :freq => :monthly, :by_day => [1], :by_set_pos => [ 1 ]
e.each(Date.today, Date.today + 365) do |d|
  print "#{d.strftime('%I:%M %a %d %b %Y')}\n"
end
Profiler__::stop_profile
Profiler__::print_profile($stdout)

One-line shuffle in Ruby

  class Enumerable
    def shuffle
      sort { rand(3) - 1 }
    end
  end
« Newer Snippets
Older Snippets »
Showing 1-3 of 3 total  RSS