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

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

Mark directories to be deleted based on their date-stamp

This Ruby code selects file directories which are older than a certain date and outputs an XML file naming all the directories to be removed. It does this by reading a directory listing formatted within the XML file 'dir.xml', all directories are named by a date-stamp, which is used to determine if the directory should be removed.

This example is used to maintain the webcamera (named 'pear') which saves it's images to a date-stamped directory daily. Any directory which is older than 14 days will be marked for deletion.

  def directory_housekeeping()
    lifespan = 14
    format_mask = 'm_d_y'
    separator = format_mask.match(/[\_*\-]/).to_s
    
    earliest_date = Time.now + (60 * 60 * 24) * -lifespan
    cut_off_date = Date.new(y=earliest_date.year,m=earliest_date.month,d=earliest_date.day)
        
    a_format = Array.new
    a_format[0] = format_mask.match(/^[y,m,d]*/).to_s
    a_format[1] = format_mask.match(separator + '[y,m,d]*').to_s.gsub(separator,'')
    a_format[2] = format_mask.match('[y,m,d]$').to_s
    
    file = File.new('../housekeeping/webcam_pear/dir.xml')
    ddoc = REXML::Document.new(file)
    file.close
    
    file_delete = File.new('../housekeeping/webcam_pear/files2delete.xml', 'w')
    doc_delete = Document.new()
    doc_delete.add_element('files')
    
    ddoc.root.elements.each('file') do |file_node|
      sfile = file_node.text
      idate = Array.new
      idate[0] = sfile.match(/^\d*/).to_s.to_i
      idate[1] = sfile.match(/\_\d*/).to_s.gsub(separator,'').to_i
      idate[2] = sfile.match(/\_\d*\d$/).to_s.gsub(separator,'').to_i

      h = Hash.new
      0.upto(2) {|i| h[a_format[i]] = idate[i]}

      file_date = Date.new(y=h['y'], m=h['m'], d=h['d'])

      if file_date < cut_off_date
        o_file2delete = Element.new('file')
        o_file2delete.text = file_date.strftime(dformat)
        doc_delete.root.add_element o_file2delete
      end
    end
    file_delete.puts doc_delete
  end



file: dir.xml
<dir>
  <file>11_4_2007</file>
  <file>11_5_2007</file>
  <file>11_6_2007</file>
  <file>11_7_2007</file>
  <file>11_8_2007</file>
  <file>11_9_2007</file>
  <file>12_10_2007</file>
  <file>12_11_2007</file>
  <file>12_1_2007</file>
  <file>12_12_2007</file>
  <file>12_13_2007</file>
  <file>12_14_2007</file>
  <file>12_15_2007</file>
  <file>12_16_2007</file>
  <file>12_17_2007</file>
  <file>12_18_2007</file>
  <file>12_19_2007</file>
  <file>12_20_2007</file>
  <file>12_21_2007</file>
  <file>12_2_2007</file>
  <file>12_22_2007</file>
  <file>12_23_2007</file>
  <file>12_24_2007</file>
  <file>12_25_2007</file>
  <file>12_26_2007</file>
  <file>12_27_2007</file>
  <file>12_28_2007</file>
  <file>12_3_2007</file>
  <file>12_4_2007</file>
  <file>12_5_2007</file>
  <file>12_6_2007</file>
  <file>12_7_2007</file>
  <file>12_8_2007</file>
  <file>12_9_2007</file>
 </dir>

file: files2delete.xml
<files>
  <file>11_4_2007</file>
  <file>11_5_2007</file>
  <file>11_6_2007</file>
  <file>11_7_2007</file>
  <file>11_8_2007</file>
  <file>11_9_2007</file>
  <file>12_10_2007</file>
  <file>12_11_2007</file>
  <file>12_1_2007</file>
  <file>12_12_2007</file>
  <file>12_13_2007</file>
  <file>12_14_2007</file>
  <file>12_15_2007</file>
  <file>12_2_2007</file>
  <file>12_3_2007</file>
  <file>12_4_2007</file>
  <file>12_5_2007</file>
  <file>12_6_2007</file>
  <file>12_7_2007</file>
  <file>12_8_2007</file>
  <file>12_9_2007</file>
 </files>

Format strings like PRINT USING, for Ruby

This is an extension to Ruby's String class. Just put this code in a file and include it. This basically takes a string and adds literals and padding to it. For example, you can format a phone number like this:

"5445556747".using('(###) ###-####', '', true)
   => (544) 555-6747


require 'strscan'

class String

  # Returns the string formatted according to a pattern.
  #
  # The pattern consists of placeholders and literals. The string is placed in
  # the placeholders, leaving the literals as they are. The result may be
  # truncated or padded if there are more placeholders than strings.
  #
  # Placeholders are '#' or '&'. Each '#' is replaced by one character from
  # the string, or the filler character if the string has no characters left.
  # The '&' is replaced by any remaining characters, or left out of the result
  # if there are no remaining characters. There can only be one '&' in the
  # pattern. If there is no '&', remaining characters are discarded.
  # 
  # '#' or '&' may be replaced by other characters if they are needed as
  # literals.
  #
  # Examples:
  # "123456789".using('###-##-####')
  #    => "123-45-6789"
  # "12345".using('###-##-####')
  #    => "123-45"
  # "12345".using('###-##-####', nil)
  #    => "12345"
  # "12345".using('###-##-####', ' ')
  #    => "123-45-    "
  # "5551212".using ('(###) ###-####', '', true)
  #    => "555-1212"
  # "873555121276668".using ('(###) ###-#### ext &', '', true)
  #    => "(873) 555-1212 ext 76668"
  # "KB5774X".using ('##-&-#')
  #    => "KB-5774-X"
  #
  # Parameters:
  # pattern -- The format string, see above.
  # fill    -- A string for padding. If the empty string, then the pattern is
  #            filled as much as possible, and the rest of the pattern is
  #            truncated. If nil, and the string does not fill the pattern,
  #            the string is returned unchanged.  Otherwise, the string is
  #            padded to fill the pattern, which is not truncated. Defaults to
  #            the empty string.
  # right   -- If true, the pattern is filled from right-to-left instead of
  #            from left-to-right, and truncated on the left instead of the
  #            right if needed. Default is false.
  # fixchar -- The single-character placeholder. Default is '#'.
  # remchar -- The remaining-character placeholder. Default is '&'.
  #
  def using(pattern, fill='', right=false, fixchar='#', remchar='&')

    remCount = pattern.count(remchar)
    raise ArgumentError.new("Too many #{remchar}") if remCount > 1
    raise ArgumentError.new("#{fixchar} too long") if fixchar.length > 1
    raise ArgumentError.new("#{remchar} too long") if remchar.length > 1
    raise ArgumentError.new("#{fill} too long")    if fill.length > 1
    remaining = remCount != 0
    slots = pattern.count(fixchar)

    # Return the string if it doesn't fit and we shouldn't even try,
    if fill.nil?
      return self if self.length < slots
      return self if self.length > slots and !remaining
    end

    # Pad and clone the string if necessary.
    source =  if fill.nil? || fill.empty? then
                self
              elsif right then
                self.rjust(slots, fill)
              else
                self.ljust(slots, fill)
              end
    
    # Truncate the string if necessary.
    if source.length > slots && !remaining then
      source = right ? source[-source.length, source.length] :
                       source[0, source.length]
    end

    # Truncate pattern if needed.
    if !fill.nil? && fill.empty? then
      
      if source.length < slots  # implies '&' can be ignored
        keepCount = source.length # Number of placeholders we are keeping
        leftmost, rightmost = 0, pattern.length - 1
        if right then
          # Look right-to-left until we find the last '#' to keep.
          # Loop starts at 1 because 0th placeholder is in the inject param.
          leftmost = (1...keepCount).inject(pattern.rindex(fixchar)) {
            |leftmost, n| pattern.rindex(fixchar, leftmost - 1) }
        else
          # Look left-to-right until we find the last '#' to keep.
          rightmost = (1...keepCount).inject(pattern.index(fixchar)) {
            |rightmost, n| pattern.index(fixchar, rightmost + 1) }
        end
        pattern = pattern[leftmost..rightmost]
        slots = pattern.count(fixchar)
      end
    
      # Trim empty '&' up to nearest placeholder. If a '&' goes empty, the
      # literals between it and the nearest '#' are probably also unnecessary.
      if source.length == slots then
        if pattern.match("^#{Regexp.escape(remchar)}") then
          pattern = pattern[pattern.index(fixchar) || 0 ... pattern.length]
        elsif pattern.match("#{Regexp.escape(remchar)}$") then
          pattern = pattern[0 ... (pattern.rindex(fixchar) + fixchar.length) || pattern.length]
        end
      end

    end
      
    # Figure out how long the remainder will be when we get to it.
    remSize = source.length - slots
    if remSize < 0 then remSize = 0; end
    
    # Make the result.
    scanner = ::StringScanner.new(pattern)
    sourceIndex = 0
    result = ''
    fixRegexp = Regexp.new(Regexp.escape(fixchar))
    remRegexp = Regexp.new(Regexp.escape(remchar))
    while not scanner.eos?
      if scanner.scan(fixRegexp) then
        result += source[sourceIndex].chr
        sourceIndex += 1
      elsif scanner.scan(remRegexp) then
        result += source[sourceIndex, remSize]
        sourceIndex += remSize
      else
        result += scanner.getch
      end
    end
    
    result
  end
end

vimrc for 2 space tab replacements

~/.vimrc:
set softtabstop=2
set shiftwidth=2
set tabstop=2
set expandtab

Number to Engineering format

Engineering format lists the exponent in powers of three

def number_to_engineering(value, precision=3)
  expof10 = ((Math.log10(value)/3.0).floor)*3
  value *= 10**(-expof10)
  case 
    when value>=1000.0 : 
      value /= 1000.0
      expof10 +=3 
    when value>=100.0 :  precision -= 2 
    when value>=10.0 :  precision -= 1 
  end
  "%.*fe%d" % [precision-1, value, expof10]
end

number_to_engineering(15000) => "15e3"


Helper to format numbers using scientific notation

For those of us who can't remember the formatting codes

def number_to_scientific(num,precision=3)
	"%.#{precision}e" % num
end

number_to_scientific(10000) => 1.000e004

in some cases it might be better to use the 'g' code instead of the 'e' code.

Helper to print numbers as ordinals (1st, 2nd, 3rd...)

def number_to_ordinal(num)
  num = num.to_i
  if (10...20)===num
    "#{num}th"
  else
    g = %w{ th st nd rd th th th th th th }
    a = num.to_s
    c=a[-1..-1].to_i
    a + g[c]
  end
end

number_to_ordinal(12) => "12th"
number_to_ordinal(7) => "7th"


Note that floats will be converted to ints (without rounding) before processing.

Write out an array as a list with commas and an 'and'

Actually, you can customize the separators to your needs.

def text_list(listtext,sep1=", ", sep2=", and ")
  n=listtext.size
  if n>1 : (listtext.first(n-1)).join(sep1) + sep2 +listtext.last 
  else listtext.first end
end

text_list(["cat", "dog", "bird"]) => "cat, dog, and bird"

split value from units

this is a very basic script for seperating out values and units. this is helpful for changing values such as style.top or border.

if element.style.top => '15px'
splitUnit( element.style.top ) => [15,'px']

function splitUnit(e)
/*
*	takes a string and seperates 'px or 'em' from it
*
*	could be streamlined to simply seperate the last two characters, but that could cause errors if used sloppily
*/
{
	if( e && ( length = e.search( /px/ ) ) ) {var eUnit = 'px'; var eValue = e.substr( 0, length );}
	else if( e && ( length = e.search( /em/ ) ) ) {var eUnit = 'em'; var eValue = e.substr( 0, length );}
	else return false;
	
	return new Array( eValue, eUnit );
}

leftZeroPad

var MANY_ZEROS = "000000000000000000";

function leftZeroPad(val, minLength) {
    if (typeof(val) != "string")
        val = String(val);
    return (MANY_ZEROS.substring(0, minLength - val.length)) + val;
}


leftZeroPad(3, 2) ==> "03"
« Newer Snippets
Older Snippets »
Showing 1-9 of 9 total  RSS