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 11-15 of 15 total

Verify Dates in Rails

From http://www.railtie.net/articles/2006/09/07/validate-dates-in-your-models:
>>>

The thing I find really nice is that if you pass it a malformed date, it returns nil. This means, in your model validations, you can add:
require 'chronic'

class Meeting < ActiveRecord::Base

  def validation
    errors.add :meeting_date, 'is not a valid date' if Chronic.parse(meeting_date.to_s).nil?
  end

end

<<<
Other Chronic examples:
>>>
mojombo in #caboose, just released his first version of Chronic, a new Ruby Gem for natural language processing of Dates and Times.
gem install chronic

irb:>
Chronic.parse('tomorrow')
    #=> Mon Aug 28 12:00:00 PDT 2006

Chronic.parse('monday', :context => :past)
    #=> Mon Aug 21 12:00:00 PDT 2006

Chronic.parse('this tuesday 5:00')
    #=> Tue Aug 29 17:00:00 PDT 2006

Chronic.parse('this tuesday 5:00', :ambiguous_time_range => :none)
    #=> Tue Aug 29 05:00:00 PDT 2006

Chronic.parse('may 27th', :now => Time.local(2000, 1, 1))
    #=> Sat May 27 12:00:00 PDT 2000

Chronic.parse('may 27th', :guess => false)
    #=> Sun May 27 00:00:00 PDT 2007..Mon May 28 00:00:00 PDT 2007


<<<

Validate URIs by Pinging the Server

require 'open-uri'

class ActiveRecord::Base
  def self.validates_uri_existence_of(*attr_names)
    configuration = { :message => "is not a valid web address" }
    configuration.update(attr_names.pop) if attr_names.last.is_a?(Hash)
    validates_each attr_names do |m, a, v|
      begin
        # Try to open the URI
        open v
      rescue
        # Report the error if it throws an exception
        m.errors.add(a, configuration[:message])
      end
    end
  end
end


Details on my blog.

PHP email validation function

// Simple function to check if an given email adddress is valid

function is_valid_email($email) {
  $result = TRUE;
  if(!eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,4})$", $email)) {
    $result = FALSE;
  }
  return $result;
}

Javascript IntegerBoxControl

In input forms on web pages you often have to validate input as an integer or more precisely a positive integer greater than zero. Here is a control implementation of sorts.

// Integer Box Control
// 
// Notes
// To create an integer box control, call the SetupIntegerBoxControl function.
// It should be passed an input element with type of text.
// The onchange event of the input element will invoke the validation function.
// The validation function ensures only positive integer data is entered.
//
// History
// 09/08/2005 - WSR : created based on dateboxcontrol

// hooks functionality up to given textbox
function SetupIntegerBoxControl( ctlIntegerBox )
   {

   // if a valid object was given
   if (ctlIntegerBox)
      {

      // validate current contents
      IntegerBoxControl_Validate( ctlIntegerBox );

      // hook up event handlers
      ctlIntegerBox.onchange = function () { IntegerBoxControl_Validate(this); };
      
      }

   }


// validates the input
function IntegerBoxControl_Validate( ctlIntegerBox )
   {

   // parse the input as an integer
   var intValue = parseInt(ctlIntegerBox.value, 10);

   // if this is not an integer
   if (isNaN(intValue))
      {

      // clear text box
      ctlIntegerBox.value = '';

      }
   // if this is an integer
   else
      {
   
      switch (true)
         {
         case (intValue == 0) :

            // clear text box
            ctlIntegerBox.value = '';

            break;
         case (intValue > 0) :

            // put the parsed integer value in the text box
            ctlIntegerBox.value = intValue.toString();

            break;
         case (intValue < 0) :

            // put the positive parsed integer value in the text box
            ctlIntegerBox.value = (-1 * intValue).toString();

            break;
         }
      
      }

   }


I forgot to mention before how to hook it up in code.
I usually add an attribute bvr-datatype="integer" to the input element. bvr stands for behaviour. I hook up the control in the onload event. Here is a recent example.
// set window load event handler
window.onload = window_load;

// ----------------------------------------------------------------------------
// window_load
// Description: event handler for window load event
// Arguments: none
// Dependencies:
//    SetupDateBoxControl (dateboxcontrol.js)
//    SetupIntegerBoxControl (integerboxcontrol.js)
//    frmSearch_submit
//    cmdRequesting_click
//    txtRequesting_change
//    frmRecent_submit
//
function window_load()
   {

   // get input elements in document
   var arrInputs = document.getElementsByTagName('INPUT');

   // cycle through input elements
   for ( var i = 0; i < arrInputs.length; i++ ) 
      {

      // if this is a datebox control
      if ( 'date' == arrInputs[i].getAttribute('bvr-datatype') && 'text' == arrInputs[i].getAttribute('type') )
         {

         // setup the control
         SetupDateBoxControl( arrInputs[i] );

         }

      // if this is a integerbox control
      if ( 'integer' == arrInputs[i].getAttribute('bvr-datatype') && 'text' == arrInputs[i].getAttribute('type') )
         {

         // setup the control
         SetupIntegerBoxControl( arrInputs[i] );

         }

      }

   // get reference to search form
   var elForm = document.getElementById('frmSearch');
   if (elForm)
      {

      // set submit event handler
      elForm.onsubmit = frmSearch_submit;

      // set cmdTimekeeperLookup click event handler
      var elToWire = document.getElementById('cmdTimekeeperLookup');
      if (elToWire)
         {

         elToWire.onclick = cmdRequesting_click;
         elToWire.textbox = document.getElementById('txtRequestingTimekeeper');

         // set textbox change events
         if (elToWire.textbox)
            {

            elToWire.textbox.onchange = txtRequesting_change;
            elToWire.textbox.onblur = txtRequesting_change;
            elToWire.textbox.label = document.getElementById('lblTimekeeperName');

            if ( typeof window.strRequesting == 'undefined' )
               window.strRequesting = ''; 

            }

         }

      }

   // get reference to recent form
   elForm = document.getElementById('frmRecent');
   if (elForm)
      {

      // set submit event handler
      elForm.onsubmit = frmRecent_submit;

      }

   }
//
// window_load
// ----------------------------------------------------------------------------

JavaScript DateBoxControl

In input forms on web pages you often have to validate dates and users are always entering something off the wall. Simon Incutio came up with a script to parse the dates. I added some stuff and turned it into a control of sorts. It is sort of US centric with date entering but it does accept iso style entries.

// Date Box Control
// 
// based on:
//  'Magic' date parsing, by Simon Willison (6th October 2003)
//   http://simon.incutio.com/archive/2003/10/06/betterDateInput
// 
// Notes
// To create a date box control, call the SetupDateBoxControl function.
// It should be passed an input element with type of text.
// This will first create a div after the input box.
// Then it will associate the div with the input element.
// The div will use the css classes: DateBoxControlMsg, DateBoxControlErrorMsg.
// Then the div is associated with the input element.
// Then the contents are validated so the div will get populated initially.
// The onchange event of the input element will invoke the validation function.
// The validation function populates the div.
// If a successfully parsed date, the div gets a nicely formatted date.
// If an unsuccessfully parse date, the div gets an error message.
//
// History
// 02/03/2005 - WSR : modified for use as datebox control
// 09/09/2005 - WSR : datebox is not required anymore (blank input is valid)
//                  : added style class to datebox itself

// hooks functionality up to given textbox
function SetupDateBoxControl( ctlDateBox )
   {

   // if a valid object was given
   if (ctlDateBox)
      {

      // add div after control for messages
      var divMessage = document.createElement('div');
      divMessage.className = 'DateBoxControlMsg';

      // if there is a next sibling
      if (ctlDateBox.nextSibling)
         {

         // insert before next sibling
		   ctlDateBox.parentNode.insertBefore( divMessage, ctlDateBox.nextSibling );

         }
      // if there is not a next sibling
      else
         {

         // append child to parent
         ctlDateBox.parentNode.appendChild( divMessage );         

         }

      // link message div to textbox for easy script access
      ctlDateBox.message = divMessage;

      // validate current contents
      DateBoxControl_Validate( ctlDateBox );

      // hook up event handlers
      ctlDateBox.onchange = function () { DateBoxControl_Validate(this); };
      
      }

   }

// add indexOf function to Array type
// finds the index of the first occurence of item in the array, or -1 if not found
Array.prototype.indexOf = function(item) {
    for (var i = 0; i < this.length; i++) {
        if (this[i] == item) {
            return i;
        }
    }
    return -1;
};

// add filter function to Array type
// returns an array of items judged true by the passed in test function
Array.prototype.filter = function(test) {
    var matches = [];
    for (var i = 0; i < this.length; i++) {
        if (test(this[i])) {
            matches[matches.length] = this[i];
        }
    }
    return matches;
};

// add right function to String type
// returns the rightmost x characters
String.prototype.right = function( intLength ) {
   if (intLength >= this.length)
      return this;
   else
      return this.substr( this.length - intLength, intLength );
};

// add trim function to String type
// trims leading and trailing whitespace
String.prototype.trim = function() { return this.replace(/^\s+|\s+$/, ''); };

// arrays for month and weekday names
var monthNames = "January February March April May June July August September October November December".split(" ");
var weekdayNames = "Sunday Monday Tuesday Wednesday Thursday Friday Saturday".split(" ");

/* Takes a string, returns the index of the month matching that string, throws
   an error if 0 or more than 1 matches
*/
function parseMonth(month) {
    var matches = monthNames.filter(function(item) { 
        return new RegExp("^" + month, "i").test(item);
    });
    if (matches.length == 0) {
        throw new Error("Invalid month string");
    }
    if (matches.length < 1) {
        throw new Error("Ambiguous month");
    }
    return monthNames.indexOf(matches[0]);
}

/* Same as parseMonth but for days of the week */
function parseWeekday(weekday) {
    var matches = weekdayNames.filter(function(item) {
        return new RegExp("^" + weekday, "i").test(item);
    });
    if (matches.length == 0) {
        throw new Error("Invalid day string");
    }
    if (matches.length < 1) {
        throw new Error("Ambiguous weekday");
    }
    return weekdayNames.indexOf(matches[0]);
}

function DateInRange( yyyy, mm, dd )
   {

   // if month out of range
   if ( mm < 0 || mm > 11 )
      throw new Error('Invalid month value.  Valid months values are 1 to 12');

   // get last day in month
   var d = (11 == mm) ? new Date(yyyy + 1, 0, 0) : new Date(yyyy, mm + 1, 0);

   // if date out of range
   if ( dd < 1 || dd > d.getDate() )
      throw new Error('Invalid date value.  Valid date values for ' + monthNames[mm] + ' are 1 to ' + d.getDate().toString());

   return true;

   }

/* Array of objects, each has 're', a regular expression and 'handler', a 
   function for creating a date from something that matches the regular 
   expression. Handlers may throw errors if string is unparseable. 
*/
var dateParsePatterns = [
    // Today
    {   re: /^today/i,
        handler: function() { 
            return new Date();
        } 
    },
    // Tomorrow
    {   re: /^tomorrow/i,
        handler: function() {
            var d = new Date(); 
            d.setDate(d.getDate() + 1); 
            return d;
        }
    },
    // Yesterday
    {   re: /^yesterday/i,
        handler: function() {
            var d = new Date();
            d.setDate(d.getDate() - 1);
            return d;
        }
    },
    // mmddyyyy (American style)
    {   re: /(\d{2})(\d{2})(\d{4})/,
        handler: function(bits) {

            var yyyy = parseInt(bits[3], 10);
            var dd = parseInt(bits[2], 10);
            var mm = parseInt(bits[1], 10) - 1;

            if ( DateInRange( yyyy, mm, dd ) )
               return new Date(yyyy, mm, dd);

        }
    },
    // mmddyy (American style) short year
    {   re: /(\d{2})(\d{2})(\d{2})/,
        handler: function(bits) {

            var d = new Date();
            var yyyy = d.getFullYear() - (d.getFullYear() % 100) + parseInt(bits[3], 10);
            var dd = parseInt(bits[2], 10);
            var mm = parseInt(bits[1], 10) - 1;

            if ( DateInRange(yyyy, mm, dd) )
               return new Date(yyyy, mm, dd);

        }
    },
    // 4th
    {   re: /^(\d{1,2})(st|nd|rd|th)?$/i, 
        handler: function(bits) {

            var d = new Date();
            var yyyy = d.getFullYear();
            var dd = parseInt(bits[1], 10);
            var mm = d.getMonth();

            if ( DateInRange( yyyy, mm, dd ) )
               return new Date(yyyy, mm, dd);

        }
    },
    // 4th Jan
    {   re: /^(\d{1,2})(?:st|nd|rd|th)? (\w+)$/i, 
        handler: function(bits) {

            var d = new Date();
            var yyyy = d.getFullYear();
            var dd = parseInt(bits[1], 10);
            var mm = parseMonth(bits[2]);

            if ( DateInRange( yyyy, mm, dd ) )
               return new Date(yyyy, mm, dd);

        }
    },
    // 4th Jan 2003
    {   re: /^(\d{1,2})(?:st|nd|rd|th)? (\w+),? (\d{4})$/i,
        handler: function(bits) {

            var yyyy = parseInt(bits[3], 10);
            var dd = parseInt(bits[1], 10);
            var mm = parseMonth(bits[2]);

            if ( DateInRange( yyyy, mm, dd ) )
               return new Date(yyyy, mm, dd);

        }
    },
    // Jan 4th
    {   re: /^(\w+) (\d{1,2})(?:st|nd|rd|th)?$/i, 
        handler: function(bits) {

            var d = new Date();
            var yyyy = d.getFullYear(); 
            var dd = parseInt(bits[2], 10);
            var mm = parseMonth(bits[1]);

            if ( DateInRange( yyyy, mm, dd ) )
               return new Date(yyyy, mm, dd);

        }
    },
    // Jan 4th 2003
    {   re: /^(\w+) (\d{1,2})(?:st|nd|rd|th)?,? (\d{4})$/i,
        handler: function(bits) {

            var yyyy = parseInt(bits[3], 10); 
            var dd = parseInt(bits[2], 10);
            var mm = parseMonth(bits[1]);

            if ( DateInRange( yyyy, mm, dd ) )
               return new Date(yyyy, mm, dd);

        }
    },
    // next Tuesday - this is suspect due to weird meaning of "next"
    {   re: /^next (\w+)$/i,
        handler: function(bits) {

            var d = new Date();
            var day = d.getDay();
            var newDay = parseWeekday(bits[1]);
            var addDays = newDay - day;
            if (newDay <= day) {
                addDays += 7;
            }
            d.setDate(d.getDate() + addDays);
            return d;

        }
    },
    // last Tuesday
    {   re: /^last (\w+)$/i,
        handler: function(bits) {

            var d = new Date();
            var wd = d.getDay();
            var nwd = parseWeekday(bits[1]);
         
            // determine the number of days to subtract to get last weekday
            // calculates 0 if weekdays are the same so we have to change this to 7
            var addDays = (wd == nwd) ? -7 : (-1 * (wd + 7 - nwd)) % 7;
            
            // adjust date and return
            d.setDate(d.getDate() + addDays);
            return d;

        }
    },
    // Tuesday
    {   re: /^(\w+)$/i,
        handler: function(bits) {

            var d = new Date();
            var wd = d.getDay();
            var nwd = parseWeekday(bits[1]);
         
            // if same weekday, return date         
            if (nwd == wd)
               return d;

            // if new weekday is before current weekday
            if (nwd < wd )
               {
 
               // calculate last weekday
               d.setDate(d.getDate() + ((wd == nwd) ? -7 : (-1 * (wd + 7 - nwd)) % 7));

               }
            // if new weekday is after current weekday
            else
               {

               // calculate next weekday
               d.setDate(d.getDate() + (nwd - wd));

               }
               
            return d;

        }
    },
    // mm/dd/yyyy (American style)
    {   re: /(\d{1,2})\/(\d{1,2})\/(\d{4})/,
        handler: function(bits) {

            var yyyy = parseInt(bits[3], 10);
            var dd = parseInt(bits[2], 10);
            var mm = parseInt(bits[1], 10) - 1;

            if ( DateInRange( yyyy, mm, dd ) )
               return new Date(yyyy, mm, dd);

        }
    },
    // mm/dd/yy (American style) short year
    {   re: /(\d{1,2})\/(\d{1,2})\/(\d{1,2})/,
        handler: function(bits) {

            var d = new Date();
            var yyyy = d.getFullYear() - (d.getFullYear() % 100) + parseInt(bits[3], 10);
            var dd = parseInt(bits[2], 10);
            var mm = parseInt(bits[1], 10) - 1;

            if ( DateInRange(yyyy, mm, dd) )
               return new Date(yyyy, mm, dd);

        }
    },
    // mm/dd (American style) omitted year
    {   re: /(\d{1,2})\/(\d{1,2})/,
        handler: function(bits) {

            var d = new Date();
            var yyyy = d.getFullYear();
            var dd = parseInt(bits[2], 10);
            var mm = parseInt(bits[1], 10) - 1;

            if ( DateInRange(yyyy, mm, dd) )
               return new Date(yyyy, mm, dd);

        }
    },
    // yyyy-mm-dd (ISO style)
    {   re: /(\d{4})-(\d{1,2})-(\d{1,2})/,
        handler: function(bits) {

            var yyyy = parseInt(bits[1], 10);
            var dd = parseInt(bits[3], 10);
            var mm = parseInt(bits[2], 10) - 1;

            if ( DateInRange( yyyy, mm, dd ) )
               return new Date(yyyy, mm, dd);

        }
    },
    // yy-mm-dd (ISO style) short year
    {   re: /(\d{1,2})-(\d{1,2})-(\d{1,2})/,
        handler: function(bits) {

            var d = new Date();
            var yyyy = d.getFullYear() - (d.getFullYear() % 100) + parseInt(bits[1], 10);
            var dd = parseInt(bits[3], 10);
            var mm = parseInt(bits[2], 10) - 1;

            if ( DateInRange( yyyy, mm, dd ) )
               return new Date(yyyy, mm, dd);

        }
    },
    // mm-dd (ISO style) omitted year
    {   re: /(\d{1,2})-(\d{1,2})/,
        handler: function(bits) {

            var d = new Date();
            var yyyy = d.getFullYear();
            var dd = parseInt(bits[2], 10);
            var mm = parseInt(bits[1], 10) - 1;

            if ( DateInRange( yyyy, mm, dd ) )
               return new Date(yyyy, mm, dd);

        }
    }
];

// parses date string input
function parseDateString( strDateInput )
   {
   
   // cycle through date parse patterns
   for (var i = 0; i < dateParsePatterns.length; i++)
      {

      // get regular expression for this pattern
      var re = dateParsePatterns[i].re;

      // get handler function for this pattern
      var handler = dateParsePatterns[i].handler;

      // parse input using regular expression
      var bits = re.exec(strDateInput);

      // if there was a match
      if