Pastebin launched a little side project called VERYVIRAL.com, check it out ;-) Want more features on Pastebin? Sign Up, it's FREE!
Guest

jQuery-Plugin "daterangepicker.jQuery.js" with onClose fix

By: a guest on Sep 9th, 2010  |  syntax: JavaScript  |  size: 47.61 KB  |  views: 504  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. /**
  2.  * --------------------------------------------------------------------
  3.  * jQuery-Plugin "daterangepicker.jQuery.js"
  4.  * by Scott Jehl, scott@filamentgroup.com
  5.  * http://www.filamentgroup.com
  6.  * reference article: http://www.filamentgroup.com/lab/update_date_range_picker_with_jquery_ui/
  7.  * demo page: http://www.filamentgroup.com/examples/daterangepicker/
  8.  *
  9.  * Copyright (c) 2008 Filament Group, Inc
  10.  * Dual licensed under the MIT (filamentgroup.com/examples/mit-license.txt) and GPL (filamentgroup.com/examples/gpl-license.txt) licenses.
  11.  *
  12.  * Dependencies: jquery, jquery UI datepicker, date.js library (included at bottom), jQuery UI CSS Framework
  13.  * Changelog:
  14.  *      10.23.2008 initial Version
  15.  *  11.12.2008 changed dateFormat option to allow custom date formatting (credit: http://alexgoldstone.com/)
  16.  *  01.04.09 updated markup to new jQuery UI CSS Framework
  17.  *  01.19.2008 changed presets hash to support different text
  18.  *  09.09.2010 fixed onClose handler firing at incorrect time (credit: IYS - code.by.iys at gmail)
  19.  *     Note: This change is not official and  is not reflected in the reference article and demo page listed above.
  20.  * --------------------------------------------------------------------
  21.  */
  22. jQuery.fn.daterangepicker = function(settings){
  23.         var rangeInput = jQuery(this);
  24.        
  25.         //defaults
  26.         var options = jQuery.extend({
  27.                 presetRanges: [
  28.                         {text: 'Today', dateStart: 'today', dateEnd: 'today' },
  29.                         {text: 'Last 7 days', dateStart: 'today-7days', dateEnd: 'today' },
  30.                         {text: 'Month to date', dateStart: function(){ return Date.parse('today').moveToFirstDayOfMonth();  }, dateEnd: 'today' },
  31.                         {text: 'Year to date', dateStart: function(){ var x= Date.parse('today'); x.setMonth(0); x.setDate(1); return x; }, dateEnd: 'today' },
  32.                         //extras:
  33.                         {text: 'The previous Month', dateStart: function(){ return Date.parse('1 month ago').moveToFirstDayOfMonth();  }, dateEnd: function(){ return Date.parse('1 month ago').moveToLastDayOfMonth();  } }
  34.                         //{text: 'Tomorrow', dateStart: 'Tomorrow', dateEnd: 'Tomorrow' },
  35.                         //{text: 'Ad Campaign', dateStart: '03/07/08', dateEnd: 'Today' },
  36.                         //{text: 'Last 30 Days', dateStart: 'Today-30', dateEnd: 'Today' },
  37.                         //{text: 'Next 30 Days', dateStart: 'Today', dateEnd: 'Today+30' },
  38.                         //{text: 'Our Ad Campaign', dateStart: '03/07/08', dateEnd: '07/08/08' }
  39.                 ],
  40.                 //presetRanges: array of objects for each menu preset.
  41.                 //Each obj must have text, dateStart, dateEnd. dateStart, dateEnd accept date.js string or a function which returns a date object
  42.                 presets: {
  43.                         specificDate: 'Specific Date',
  44.                         allDatesBefore: 'All Dates Before',
  45.                         allDatesAfter: 'All Dates After',
  46.                         dateRange: 'Date Range'
  47.                 },
  48.                 rangeStartTitle: 'Start date',
  49.                 rangeEndTitle: 'End date',
  50.                 nextLinkText: 'Next',
  51.                 prevLinkText: 'Prev',
  52.                 doneButtonText: 'Done',
  53.                 earliestDate: Date.parse('-15years'), //earliest date allowed
  54.                 latestDate: Date.parse('+15years'), //latest date allowed
  55.                 rangeSplitter: '-', //string to use between dates in single input
  56.                 dateFormat: 'm/d/yy', // date formatting. Available formats: http://docs.jquery.com/UI/Datepicker/%24.datepicker.formatDate
  57.                 closeOnSelect: true, //if a complete selection is made, close the menu
  58.                 arrows: false,
  59.                 posX: rangeInput.offset().left, // x position
  60.                 posY: rangeInput.offset().top + rangeInput.outerHeight(), // y position
  61.                 appendTo: 'body',
  62.                 onClose: function(){},
  63.                 onOpen: function(){},
  64.                 onChange: function(){},
  65.                 datepickerOptions: null //object containing native UI datepicker API options
  66.         }, settings);
  67.        
  68.  
  69.         //custom datepicker options, extended by options
  70.         var datepickerOptions = {
  71.                 onSelect: function() {
  72.                                 if(rp.find('.ui-daterangepicker-specificDate').is('.ui-state-active')){
  73.                                         rp.find('.range-end').datepicker('setDate', rp.find('.range-start').datepicker('getDate') );
  74.                                 }
  75.                                 var rangeA = fDate( rp.find('.range-start').datepicker('getDate') );
  76.                                 var rangeB = fDate( rp.find('.range-end').datepicker('getDate') );
  77.                                
  78.                                 //send back to input or inputs
  79.                                 if(rangeInput.length == 2){
  80.                                         rangeInput.eq(0).val(rangeA);
  81.                                         rangeInput.eq(1).val(rangeB);
  82.                                 }
  83.                                 else{
  84.                                         rangeInput.val((rangeA != rangeB) ? rangeA+' '+ options.rangeSplitter +' '+rangeB : rangeA);
  85.                                 }
  86.                                
  87.                                 options.onChange();
  88.                                
  89.                                 //if closeOnSelect is true
  90.                                 if(options.closeOnSelect && ($(this).get(0) == rp.find('.range-end').get(0))){
  91.                                         if(!rp.find('li.ui-state-active').is('.ui-daterangepicker-dateRange') && rp.data('state') != 'closed' ){
  92.                                                 closeRP();
  93.                                         }
  94.                                 }      
  95.                         },
  96.                         defaultDate: +0
  97.         };
  98.        
  99.         //change event fires both when a calendar is updated or a change event on the input is triggered
  100.         rangeInput.change(options.onChange);
  101.        
  102.        
  103.         //datepicker options from options
  104.         options.datepickerOptions = (settings) ? jQuery.extend(datepickerOptions, settings.datepickerOptions) : datepickerOptions;
  105.        
  106.         //Capture Dates from input(s)
  107.         var inputDateA, inputDateB = Date.parse('today');
  108.         var inputDateAtemp, inputDateBtemp;
  109.         if(rangeInput.size() == 2){
  110.                 inputDateAtemp = Date.parse( rangeInput.eq(0).val() );
  111.                 inputDateBtemp = Date.parse( rangeInput.eq(1).val() );
  112.                 if(inputDateAtemp == null){inputDateAtemp = inputDateBtemp;}
  113.                 if(inputDateBtemp == null){inputDateBtemp = inputDateAtemp;}
  114.         }
  115.         else {
  116.                 inputDateAtemp = Date.parse( rangeInput.val().split(options.rangeSplitter)[0] );
  117.                 inputDateBtemp = Date.parse( rangeInput.val().split(options.rangeSplitter)[1] );
  118.                 if(inputDateBtemp == null){inputDateBtemp = inputDateAtemp;} //if one date, set both
  119.         }
  120.         if(inputDateAtemp != null){inputDateA = inputDateAtemp;}
  121.         if(inputDateBtemp != null){inputDateB = inputDateBtemp;}
  122.  
  123.                
  124.         //build picker and
  125.         var rp = jQuery('<div class="ui-daterangepicker ui-widget ui-helper-clearfix ui-widget-content ui-corner-all"></div>');
  126.         var rpPresets = (function(){
  127.                 var ul = jQuery('<ul class="ui-widget-content"></ul>').appendTo(rp);
  128.                 jQuery.each(options.presetRanges,function(){
  129.                         jQuery('<li class="ui-daterangepicker-'+ this.text.replace(/ /g, '') +' ui-corner-all"><a href="#">'+ this.text +'</a></li>')
  130.                         .data('dateStart', this.dateStart)
  131.                         .data('dateEnd', this.dateEnd)
  132.                         .appendTo(ul);
  133.                 });
  134.                 var x=0;
  135.                 jQuery.each(options.presets, function(key, value) {
  136.                         jQuery('<li class="ui-daterangepicker-'+ key +' preset_'+ x +' ui-helper-clearfix ui-corner-all"><span class="ui-icon ui-icon-triangle-1-e"></span><a href="#">'+ value +'</a></li>')
  137.                         .appendTo(ul);
  138.                         x++;
  139.                 });
  140.                
  141.                 ul.find('li').hover(
  142.                                 function(){
  143.                                         jQuery(this).addClass('ui-state-hover');
  144.                                 },
  145.                                 function(){
  146.                                         jQuery(this).removeClass('ui-state-hover');
  147.                                 })
  148.                         .click(function(){
  149.                                 rp.find('.ui-state-active').removeClass('ui-state-active');
  150.                                 jQuery(this).addClass('ui-state-active').clickActions(rp, rpPickers, doneBtn);
  151.                                 return false;
  152.                         });
  153.                 return ul;
  154.         })();
  155.                                
  156.         //function to format a date string        
  157.         function fDate(date){
  158.            if(!date.getDate()){return '';}
  159.            var day = date.getDate();
  160.            var month = date.getMonth();
  161.            var year = date.getFullYear();
  162.            month++; // adjust javascript month
  163.            var dateFormat = options.dateFormat;
  164.            return jQuery.datepicker.formatDate( dateFormat, date );
  165.         }
  166.        
  167.        
  168.         jQuery.fn.restoreDateFromData = function(){
  169.                 if(jQuery(this).data('saveDate')){
  170.                         jQuery(this).datepicker('setDate', jQuery(this).data('saveDate')).removeData('saveDate');
  171.                 }
  172.                 return this;
  173.         }
  174.         jQuery.fn.saveDateToData = function(){
  175.                 if(!jQuery(this).data('saveDate')){
  176.                         jQuery(this).data('saveDate', jQuery(this).datepicker('getDate') );
  177.                 }
  178.                 return this;
  179.         }
  180.        
  181.         //show, hide, or toggle rangepicker
  182.         function showRP(){
  183.                 if(rp.data('state') == 'closed' || !rp.is(':visible')){
  184.                         rp.data('state', 'open');
  185.                         rp.fadeIn(300);
  186.                         options.onOpen();
  187.                 }
  188.         }
  189.        
  190.         function hideRP() {
  191.                 rp.fadeOut(300);
  192.         }
  193.        
  194.         function closeRP(){
  195.                 if(rp.data('state') == 'open'){
  196.                         rp.data('state', 'closed');
  197.                         hideRP();
  198.                         options.onClose();
  199.                 }
  200.         }
  201.         function toggleRP(){
  202.                 if( rp.data('state') == 'open' ){ hideRP(); }
  203.                 else { showRP(); }
  204.         }
  205.         rp.data('state', 'closed');
  206.                                        
  207.         //preset menu click events     
  208.         jQuery.fn.clickActions = function(rp, rpPickers, doneBtn){
  209.                
  210.                 if(jQuery(this).is('.ui-daterangepicker-specificDate')){
  211.                         doneBtn.hide();
  212.                         rpPickers.show();
  213.                         rp.find('.title-start').text( options.presets.specificDate );
  214.                         rp.find('.range-start').restoreDateFromData().show(400);
  215.                         rp.find('.range-end').restoreDateFromData().hide(400);
  216.                         setTimeout(function(){doneBtn.fadeIn();}, 400);
  217.                 }
  218.                 else if(jQuery(this).is('.ui-daterangepicker-allDatesBefore')){
  219.                         doneBtn.hide();
  220.                         rpPickers.show();
  221.                         rp.find('.title-end').text( options.presets.allDatesBefore );
  222.                         rp.find('.range-start').saveDateToData().datepicker('setDate', options.earliestDate).hide(400);
  223.                         rp.find('.range-end').restoreDateFromData().show(400);
  224.                         setTimeout(function(){doneBtn.fadeIn();}, 400);
  225.                 }
  226.                 else if(jQuery(this).is('.ui-daterangepicker-allDatesAfter')){
  227.                         doneBtn.hide();
  228.                         rpPickers.show();
  229.                         rp.find('.title-start').text( options.presets.allDatesAfter );
  230.                         rp.find('.range-start').restoreDateFromData().show(400);
  231.                         rp.find('.range-end').saveDateToData().datepicker('setDate', options.latestDate).hide(400);
  232.                         setTimeout(function(){doneBtn.fadeIn();}, 400);
  233.                 }
  234.                 else if(jQuery(this).is('.ui-daterangepicker-dateRange')){
  235.                         doneBtn.hide();
  236.                         rpPickers.show();
  237.                         rp.find('.title-start').text(options.rangeStartTitle);
  238.                         rp.find('.title-end').text(options.rangeEndTitle);
  239.                         rp.find('.range-start').restoreDateFromData().show(400);
  240.                         rp.find('.range-end').restoreDateFromData().show(400);
  241.                         setTimeout(function(){doneBtn.fadeIn();}, 400);
  242.                 }
  243.                 else {
  244.                         //custom date range
  245.                                 doneBtn.hide();
  246.                                 rp.find('.range-start, .range-end').hide(400, function(){
  247.                                         rpPickers.hide();
  248.                                 });
  249.                                 var dateStart = (typeof jQuery(this).data('dateStart') == 'string') ? Date.parse(jQuery(this).data('dateStart')) : jQuery(this).data('dateStart')();
  250.                                 var dateEnd = (typeof jQuery(this).data('dateEnd') == 'string') ? Date.parse(jQuery(this).data('dateEnd')) : jQuery(this).data('dateEnd')();
  251.                                 rp.find('.range-start').datepicker('setDate', dateStart).find('.ui-datepicker-current-day').trigger('click');
  252.                                 rp.find('.range-end').datepicker('setDate', dateEnd).find('.ui-datepicker-current-day').trigger('click');
  253.                 }
  254.                
  255.                 return false;
  256.         }      
  257.        
  258.  
  259.         //picker divs
  260.         var rpPickers = jQuery('<div class="ranges ui-widget-header ui-corner-all ui-helper-clearfix"><div class="range-start"><span class="title-start">Start Date</span></div><div class="range-end"><span class="title-end">End Date</span></div></div>').appendTo(rp);
  261.         rpPickers.find('.range-start, .range-end').datepicker(options.datepickerOptions);
  262.         rpPickers.find('.range-start').datepicker('setDate', inputDateA);
  263.         rpPickers.find('.range-end').datepicker('setDate', inputDateB);
  264.         var doneBtn = jQuery('<button class="btnDone ui-state-default ui-corner-all">'+ options.doneButtonText +'</button>')
  265.         .click(function(){
  266.                 rp.find('.ui-datepicker-current-day').trigger('click');
  267.                 closeRP();
  268.         })
  269.         .hover(
  270.                         function(){
  271.                                 jQuery(this).addClass('ui-state-hover');
  272.                         },
  273.                         function(){
  274.                                 jQuery(this).removeClass('ui-state-hover');
  275.                         }
  276.         )
  277.         .appendTo(rpPickers);
  278.        
  279.        
  280.        
  281.        
  282.         //inputs toggle rangepicker visibility
  283.         jQuery(this).click(function(){
  284.                 toggleRP();
  285.                 return false;
  286.         });
  287.         //hide em all
  288.         rpPickers.css('display', 'none').find('.range-start, .range-end, .btnDone').css('display', 'none');
  289.        
  290.         //inject rp
  291.         jQuery(options.appendTo).append(rp);
  292.        
  293.         //wrap and position
  294.         rp.wrap('<div class="ui-daterangepickercontain"></div>');
  295.         if(options.posX){
  296.                 rp.parent().css('left', options.posX);
  297.         }
  298.         if(options.posY){
  299.                 rp.parent().css('top', options.posY);
  300.         }
  301.  
  302.         //add arrows (only available on one input)
  303.         if(options.arrows && rangeInput.size()==1){
  304.                 var prevLink = jQuery('<a href="#" class="ui-daterangepicker-prev ui-corner-all" title="'+ options.prevLinkText +'"><span class="ui-icon ui-icon-circle-triangle-w">'+ options.prevLinkText +'</span></a>');
  305.                 var nextLink = jQuery('<a href="#" class="ui-daterangepicker-next ui-corner-all" title="'+ options.nextLinkText +'"><span class="ui-icon ui-icon-circle-triangle-e">'+ options.nextLinkText +'</span></a>');
  306.                 jQuery(this)
  307.                 .addClass('ui-rangepicker-input ui-widget-content')
  308.                 .wrap('<div class="ui-daterangepicker-arrows ui-widget ui-widget-header ui-helper-clearfix ui-corner-all"></div>')
  309.                 .before( prevLink )
  310.                 .before( nextLink )
  311.                 .parent().find('a').click(function(){
  312.                         var dateA = rpPickers.find('.range-start').datepicker('getDate');
  313.                         var dateB = rpPickers.find('.range-end').datepicker('getDate');
  314.                         var diff = Math.abs( new TimeSpan(dateA - dateB).getTotalMilliseconds() ) + 86400000; //difference plus one day
  315.                         if(jQuery(this).is('.ui-daterangepicker-prev')){ diff = -diff; }
  316.                        
  317.                         rpPickers.find('.range-start, .range-end ').each(function(){
  318.                                         var thisDate = jQuery(this).datepicker( "getDate");
  319.                                         if(thisDate == null){return false;}
  320.                                         jQuery(this).datepicker( "setDate", thisDate.add({milliseconds: diff}) ).find('.ui-datepicker-current-day').trigger('click');
  321.                         });
  322.                        
  323.                         return false;
  324.                 })
  325.                 .hover(
  326.                         function(){
  327.                                 jQuery(this).addClass('ui-state-hover');
  328.                         },
  329.                         function(){
  330.                                 jQuery(this).removeClass('ui-state-hover');
  331.                         })
  332.                 ;
  333.         }
  334.        
  335.        
  336.         jQuery(document).click(function(){
  337.                 if (rp.is(':visible')) {
  338.                         hideRP();
  339.                 }
  340.         });
  341.  
  342.         rp.click(function(){return false;}).hide();
  343.         return this;
  344. }
  345.  
  346.  
  347.  
  348.  
  349.  
  350. /**
  351.  * Version: 1.0 Alpha-1
  352.  * Build Date: 13-Nov-2007
  353.  * Copyright (c) 2006-2007, Coolite Inc. (http://www.coolite.com/). All rights reserved.
  354.  * License: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/.
  355.  * Website: http://www.datejs.com/ or http://www.coolite.com/datejs/
  356.  */
  357. Date.CultureInfo={name:"en-US",englishName:"English (United States)",nativeName:"English (United States)",dayNames:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],abbreviatedDayNames:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],shortestDayNames:["Su","Mo","Tu","We","Th","Fr","Sa"],firstLetterDayNames:["S","M","T","W","T","F","S"],monthNames:["January","February","March","April","May","June","July","August","September","October","November","December"],abbreviatedMonthNames:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"],amDesignator:"AM",pmDesignator:"PM",firstDayOfWeek:0,twoDigitYearMax:2029,dateElementOrder:"mdy",formatPatterns:{shortDate:"M/d/yyyy",longDate:"dddd, MMMM dd, yyyy",shortTime:"h:mm tt",longTime:"h:mm:ss tt",fullDateTime:"dddd, MMMM dd, yyyy h:mm:ss tt",sortableDateTime:"yyyy-MM-ddTHH:mm:ss",universalSortableDateTime:"yyyy-MM-dd HH:mm:ssZ",rfc1123:"ddd, dd MMM yyyy HH:mm:ss GMT",monthDay:"MMMM dd",yearMonth:"MMMM, yyyy"},regexPatterns:{jan:/^jan(uary)?/i,feb:/^feb(ruary)?/i,mar:/^mar(ch)?/i,apr:/^apr(il)?/i,may:/^may/i,jun:/^jun(e)?/i,jul:/^jul(y)?/i,aug:/^aug(ust)?/i,sep:/^sep(t(ember)?)?/i,oct:/^oct(ober)?/i,nov:/^nov(ember)?/i,dec:/^dec(ember)?/i,sun:/^su(n(day)?)?/i,mon:/^mo(n(day)?)?/i,tue:/^tu(e(s(day)?)?)?/i,wed:/^we(d(nesday)?)?/i,thu:/^th(u(r(s(day)?)?)?)?/i,fri:/^fr(i(day)?)?/i,sat:/^sa(t(urday)?)?/i,future:/^next/i,past:/^last|past|prev(ious)?/i,add:/^(\+|after|from)/i,subtract:/^(\-|before|ago)/i,yesterday:/^yesterday/i,today:/^t(oday)?/i,tomorrow:/^tomorrow/i,now:/^n(ow)?/i,millisecond:/^ms|milli(second)?s?/i,second:/^sec(ond)?s?/i,minute:/^min(ute)?s?/i,hour:/^h(ou)?rs?/i,week:/^w(ee)?k/i,month:/^m(o(nth)?s?)?/i,day:/^d(ays?)?/i,year:/^y((ea)?rs?)?/i,shortMeridian:/^(a|p)/i,longMeridian:/^(a\.?m?\.?|p\.?m?\.?)/i,timezone:/^((e(s|d)t|c(s|d)t|m(s|d)t|p(s|d)t)|((gmt)?\s*(\+|\-)\s*\d\d\d\d?)|gmt)/i,ordinalSuffix:/^\s*(st|nd|rd|th)/i,timeContext:/^\s*(\:|a|p)/i},abbreviatedTimeZoneStandard:{GMT:"-000",EST:"-0400",CST:"-0500",MST:"-0600",PST:"-0700"},abbreviatedTimeZoneDST:{GMT:"-000",EDT:"-0500",CDT:"-0600",MDT:"-0700",PDT:"-0800"}};
  358. Date.getMonthNumberFromName=function(name){var n=Date.CultureInfo.monthNames,m=Date.CultureInfo.abbreviatedMonthNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
  359. return-1;};Date.getDayNumberFromName=function(name){var n=Date.CultureInfo.dayNames,m=Date.CultureInfo.abbreviatedDayNames,o=Date.CultureInfo.shortestDayNames,s=name.toLowerCase();for(var i=0;i<n.length;i++){if(n[i].toLowerCase()==s||m[i].toLowerCase()==s){return i;}}
  360. return-1;};Date.isLeapYear=function(year){return(((year%4===0)&&(year%100!==0))||(year%400===0));};Date.getDaysInMonth=function(year,month){return[31,(Date.isLeapYear(year)?29:28),31,30,31,30,31,31,30,31,30,31][month];};Date.getTimezoneOffset=function(s,dst){return(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST[s.toUpperCase()]:Date.CultureInfo.abbreviatedTimeZoneStandard[s.toUpperCase()];};Date.getTimezoneAbbreviation=function(offset,dst){var n=(dst||false)?Date.CultureInfo.abbreviatedTimeZoneDST:Date.CultureInfo.abbreviatedTimeZoneStandard,p;for(p in n){if(n[p]===offset){return p;}}
  361. return null;};Date.prototype.clone=function(){return new Date(this.getTime());};Date.prototype.compareTo=function(date){if(isNaN(this)){throw new Error(this);}
  362. if(date instanceof Date&&!isNaN(date)){return(this>date)?1:(this<date)?-1:0;}else{throw new TypeError(date);}};Date.prototype.equals=function(date){return(this.compareTo(date)===0);};Date.prototype.between=function(start,end){var t=this.getTime();return t>=start.getTime()&&t<=end.getTime();};Date.prototype.addMilliseconds=function(value){this.setMilliseconds(this.getMilliseconds()+value);return this;};Date.prototype.addSeconds=function(value){return this.addMilliseconds(value*1000);};Date.prototype.addMinutes=function(value){return this.addMilliseconds(value*60000);};Date.prototype.addHours=function(value){return this.addMilliseconds(value*3600000);};Date.prototype.addDays=function(value){return this.addMilliseconds(value*86400000);};Date.prototype.addWeeks=function(value){return this.addMilliseconds(value*604800000);};Date.prototype.addMonths=function(value){var n=this.getDate();this.setDate(1);this.setMonth(this.getMonth()+value);this.setDate(Math.min(n,this.getDaysInMonth()));return this;};Date.prototype.addYears=function(value){return this.addMonths(value*12);};Date.prototype.add=function(config){if(typeof config=="number"){this._orient=config;return this;}
  363. var x=config;if(x.millisecond||x.milliseconds){this.addMilliseconds(x.millisecond||x.milliseconds);}
  364. if(x.second||x.seconds){this.addSeconds(x.second||x.seconds);}
  365. if(x.minute||x.minutes){this.addMinutes(x.minute||x.minutes);}
  366. if(x.hour||x.hours){this.addHours(x.hour||x.hours);}
  367. if(x.month||x.months){this.addMonths(x.month||x.months);}
  368. if(x.year||x.years){this.addYears(x.year||x.years);}
  369. if(x.day||x.days){this.addDays(x.day||x.days);}
  370. return this;};Date._validate=function(value,min,max,name){if(typeof value!="number"){throw new TypeError(value+" is not a Number.");}else if(value<min||value>max){throw new RangeError(value+" is not a valid value for "+name+".");}
  371. return true;};Date.validateMillisecond=function(n){return Date._validate(n,0,999,"milliseconds");};Date.validateSecond=function(n){return Date._validate(n,0,59,"seconds");};Date.validateMinute=function(n){return Date._validate(n,0,59,"minutes");};Date.validateHour=function(n){return Date._validate(n,0,23,"hours");};Date.validateDay=function(n,year,month){return Date._validate(n,1,Date.getDaysInMonth(year,month),"days");};Date.validateMonth=function(n){return Date._validate(n,0,11,"months");};Date.validateYear=function(n){return Date._validate(n,1,9999,"seconds");};Date.prototype.set=function(config){var x=config;if(!x.millisecond&&x.millisecond!==0){x.millisecond=-1;}
  372. if(!x.second&&x.second!==0){x.second=-1;}
  373. if(!x.minute&&x.minute!==0){x.minute=-1;}
  374. if(!x.hour&&x.hour!==0){x.hour=-1;}
  375. if(!x.day&&x.day!==0){x.day=-1;}
  376. if(!x.month&&x.month!==0){x.month=-1;}
  377. if(!x.year&&x.year!==0){x.year=-1;}
  378. if(x.millisecond!=-1&&Date.validateMillisecond(x.millisecond)){this.addMilliseconds(x.millisecond-this.getMilliseconds());}
  379. if(x.second!=-1&&Date.validateSecond(x.second)){this.addSeconds(x.second-this.getSeconds());}
  380. if(x.minute!=-1&&Date.validateMinute(x.minute)){this.addMinutes(x.minute-this.getMinutes());}
  381. if(x.hour!=-1&&Date.validateHour(x.hour)){this.addHours(x.hour-this.getHours());}
  382. if(x.month!==-1&&Date.validateMonth(x.month)){this.addMonths(x.month-this.getMonth());}
  383. if(x.year!=-1&&Date.validateYear(x.year)){this.addYears(x.year-this.getFullYear());}
  384. if(x.day!=-1&&Date.validateDay(x.day,this.getFullYear(),this.getMonth())){this.addDays(x.day-this.getDate());}
  385. if(x.timezone){this.setTimezone(x.timezone);}
  386. if(x.timezoneOffset){this.setTimezoneOffset(x.timezoneOffset);}
  387. return this;};Date.prototype.clearTime=function(){this.setHours(0);this.setMinutes(0);this.setSeconds(0);this.setMilliseconds(0);return this;};Date.prototype.isLeapYear=function(){var y=this.getFullYear();return(((y%4===0)&&(y%100!==0))||(y%400===0));};Date.prototype.isWeekday=function(){return!(this.is().sat()||this.is().sun());};Date.prototype.getDaysInMonth=function(){return Date.getDaysInMonth(this.getFullYear(),this.getMonth());};Date.prototype.moveToFirstDayOfMonth=function(){return this.set({day:1});};Date.prototype.moveToLastDayOfMonth=function(){return this.set({day:this.getDaysInMonth()});};Date.prototype.moveToDayOfWeek=function(day,orient){var diff=(day-this.getDay()+7*(orient||+1))%7;return this.addDays((diff===0)?diff+=7*(orient||+1):diff);};Date.prototype.moveToMonth=function(month,orient){var diff=(month-this.getMonth()+12*(orient||+1))%12;return this.addMonths((diff===0)?diff+=12*(orient||+1):diff);};Date.prototype.getDayOfYear=function(){return Math.floor((this-new Date(this.getFullYear(),0,1))/86400000);};Date.prototype.getWeekOfYear=function(firstDayOfWeek){var y=this.getFullYear(),m=this.getMonth(),d=this.getDate();var dow=firstDayOfWeek||Date.CultureInfo.firstDayOfWeek;var offset=7+1-new Date(y,0,1).getDay();if(offset==8){offset=1;}
  388. var daynum=((Date.UTC(y,m,d,0,0,0)-Date.UTC(y,0,1,0,0,0))/86400000)+1;var w=Math.floor((daynum-offset+7)/7);if(w===dow){y--;var prevOffset=7+1-new Date(y,0,1).getDay();if(prevOffset==2||prevOffset==8){w=53;}else{w=52;}}
  389. return w;};Date.prototype.isDST=function(){return this.toString().match(/(E|C|M|P)(S|D)T/)[2]=="D";};Date.prototype.getTimezone=function(){return Date.getTimezoneAbbreviation(this.getUTCOffset,this.isDST());};Date.prototype.setTimezoneOffset=function(s){var here=this.getTimezoneOffset(),there=Number(s)*-6/10;this.addMinutes(there-here);return this;};Date.prototype.setTimezone=function(s){return this.setTimezoneOffset(Date.getTimezoneOffset(s));};Date.prototype.getUTCOffset=function(){var n=this.getTimezoneOffset()*-10/6,r;if(n<0){r=(n-10000).toString();return r[0]+r.substr(2);}else{r=(n+10000).toString();return"+"+r.substr(1);}};Date.prototype.getDayName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedDayNames[this.getDay()]:Date.CultureInfo.dayNames[this.getDay()];};Date.prototype.getMonthName=function(abbrev){return abbrev?Date.CultureInfo.abbreviatedMonthNames[this.getMonth()]:Date.CultureInfo.monthNames[this.getMonth()];};Date.prototype._toString=Date.prototype.toString;Date.prototype.toString=function(format){var self=this;var p=function p(s){return(s.toString().length==1)?"0"+s:s;};return format?format.replace(/dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?/g,function(format){switch(format){case"hh":return p(self.getHours()<13?self.getHours():(self.getHours()-12));case"h":return self.getHours()<13?self.getHours():(self.getHours()-12);case"HH":return p(self.getHours());case"H":return self.getHours();case"mm":return p(self.getMinutes());case"m":return self.getMinutes();case"ss":return p(self.getSeconds());case"s":return self.getSeconds();case"yyyy":return self.getFullYear();case"yy":return self.getFullYear().toString().substring(2,4);case"dddd":return self.getDayName();case"ddd":return self.getDayName(true);case"dd":return p(self.getDate());case"d":return self.getDate().toString();case"MMMM":return self.getMonthName();case"MMM":return self.getMonthName(true);case"MM":return p((self.getMonth()+1));case"M":return self.getMonth()+1;case"t":return self.getHours()<12?Date.CultureInfo.amDesignator.substring(0,1):Date.CultureInfo.pmDesignator.substring(0,1);case"tt":return self.getHours()<12?Date.CultureInfo.amDesignator:Date.CultureInfo.pmDesignator;case"zzz":case"zz":case"z":return"";}}):this._toString();};
  390. Date.now=function(){return new Date();};Date.today=function(){return Date.now().clearTime();};Date.prototype._orient=+1;Date.prototype.next=function(){this._orient=+1;return this;};Date.prototype.last=Date.prototype.prev=Date.prototype.previous=function(){this._orient=-1;return this;};Date.prototype._is=false;Date.prototype.is=function(){this._is=true;return this;};Number.prototype._dateElement="day";Number.prototype.fromNow=function(){var c={};c[this._dateElement]=this;return Date.now().add(c);};Number.prototype.ago=function(){var c={};c[this._dateElement]=this*-1;return Date.now().add(c);};(function(){var $D=Date.prototype,$N=Number.prototype;var dx=("sunday monday tuesday wednesday thursday friday saturday").split(/\s/),mx=("january february march april may june july august september october november december").split(/\s/),px=("Millisecond Second Minute Hour Day Week Month Year").split(/\s/),de;var df=function(n){return function(){if(this._is){this._is=false;return this.getDay()==n;}
  391. return this.moveToDayOfWeek(n,this._orient);};};for(var i=0;i<dx.length;i++){$D[dx[i]]=$D[dx[i].substring(0,3)]=df(i);}
  392. var mf=function(n){return function(){if(this._is){this._is=false;return this.getMonth()===n;}
  393. return this.moveToMonth(n,this._orient);};};for(var j=0;j<mx.length;j++){$D[mx[j]]=$D[mx[j].substring(0,3)]=mf(j);}
  394. var ef=function(j){return function(){if(j.substring(j.length-1)!="s"){j+="s";}
  395. return this["add"+j](this._orient);};};var nf=function(n){return function(){this._dateElement=n;return this;};};for(var k=0;k<px.length;k++){de=px[k].toLowerCase();$D[de]=$D[de+"s"]=ef(px[k]);$N[de]=$N[de+"s"]=nf(de);}}());Date.prototype.toJSONString=function(){return this.toString("yyyy-MM-ddThh:mm:ssZ");};Date.prototype.toShortDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortDatePattern);};Date.prototype.toLongDateString=function(){return this.toString(Date.CultureInfo.formatPatterns.longDatePattern);};Date.prototype.toShortTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.shortTimePattern);};Date.prototype.toLongTimeString=function(){return this.toString(Date.CultureInfo.formatPatterns.longTimePattern);};Date.prototype.getOrdinal=function(){switch(this.getDate()){case 1:case 21:case 31:return"st";case 2:case 22:return"nd";case 3:case 23:return"rd";default:return"th";}};
  396. (function(){Date.Parsing={Exception:function(s){this.message="Parse error at '"+s.substring(0,10)+" ...'";}};var $P=Date.Parsing;var _=$P.Operators={rtoken:function(r){return function(s){var mx=s.match(r);if(mx){return([mx[0],s.substring(mx[0].length)]);}else{throw new $P.Exception(s);}};},token:function(s){return function(s){return _.rtoken(new RegExp("^\s*"+s+"\s*"))(s);};},stoken:function(s){return _.rtoken(new RegExp("^"+s));},until:function(p){return function(s){var qx=[],rx=null;while(s.length){try{rx=p.call(this,s);}catch(e){qx.push(rx[0]);s=rx[1];continue;}
  397. break;}
  398. return[qx,s];};},many:function(p){return function(s){var rx=[],r=null;while(s.length){try{r=p.call(this,s);}catch(e){return[rx,s];}
  399. rx.push(r[0]);s=r[1];}
  400. return[rx,s];};},optional:function(p){return function(s){var r=null;try{r=p.call(this,s);}catch(e){return[null,s];}
  401. return[r[0],r[1]];};},not:function(p){return function(s){try{p.call(this,s);}catch(e){return[null,s];}
  402. throw new $P.Exception(s);};},ignore:function(p){return p?function(s){var r=null;r=p.call(this,s);return[null,r[1]];}:null;},product:function(){var px=arguments[0],qx=Array.prototype.slice.call(arguments,1),rx=[];for(var i=0;i<px.length;i++){rx.push(_.each(px[i],qx));}
  403. return rx;},cache:function(rule){var cache={},r=null;return function(s){try{r=cache[s]=(cache[s]||rule.call(this,s));}catch(e){r=cache[s]=e;}
  404. if(r instanceof $P.Exception){throw r;}else{return r;}};},any:function(){var px=arguments;return function(s){var r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
  405. try{r=(px[i].call(this,s));}catch(e){r=null;}
  406. if(r){return r;}}
  407. throw new $P.Exception(s);};},each:function(){var px=arguments;return function(s){var rx=[],r=null;for(var i=0;i<px.length;i++){if(px[i]==null){continue;}
  408. try{r=(px[i].call(this,s));}catch(e){throw new $P.Exception(s);}
  409. rx.push(r[0]);s=r[1];}
  410. return[rx,s];};},all:function(){var px=arguments,_=_;return _.each(_.optional(px));},sequence:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;if(px.length==1){return px[0];}
  411. return function(s){var r=null,q=null;var rx=[];for(var i=0;i<px.length;i++){try{r=px[i].call(this,s);}catch(e){break;}
  412. rx.push(r[0]);try{q=d.call(this,r[1]);}catch(ex){q=null;break;}
  413. s=q[1];}
  414. if(!r){throw new $P.Exception(s);}
  415. if(q){throw new $P.Exception(q[1]);}
  416. if(c){try{r=c.call(this,r[1]);}catch(ey){throw new $P.Exception(r[1]);}}
  417. return[rx,(r?r[1]:s)];};},between:function(d1,p,d2){d2=d2||d1;var _fn=_.each(_.ignore(d1),p,_.ignore(d2));return function(s){var rx=_fn.call(this,s);return[[rx[0][0],r[0][2]],rx[1]];};},list:function(p,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return(p instanceof Array?_.each(_.product(p.slice(0,-1),_.ignore(d)),p.slice(-1),_.ignore(c)):_.each(_.many(_.each(p,_.ignore(d))),px,_.ignore(c)));},set:function(px,d,c){d=d||_.rtoken(/^\s*/);c=c||null;return function(s){var r=null,p=null,q=null,rx=null,best=[[],s],last=false;for(var i=0;i<px.length;i++){q=null;p=null;r=null;last=(px.length==1);try{r=px[i].call(this,s);}catch(e){continue;}
  418. rx=[[r[0]],r[1]];if(r[1].length>0&&!last){try{q=d.call(this,r[1]);}catch(ex){last=true;}}else{last=true;}
  419. if(!last&&q[1].length===0){last=true;}
  420. if(!last){var qx=[];for(var j=0;j<px.length;j++){if(i!=j){qx.push(px[j]);}}
  421. p=_.set(qx,d).call(this,q[1]);if(p[0].length>0){rx[0]=rx[0].concat(p[0]);rx[1]=p[1];}}
  422. if(rx[1].length<best[1].length){best=rx;}
  423. if(best[1].length===0){break;}}
  424. if(best[0].length===0){return best;}
  425. if(c){try{q=c.call(this,best[1]);}catch(ey){throw new $P.Exception(best[1]);}
  426. best[1]=q[1];}
  427. return best;};},forward:function(gr,fname){return function(s){return gr[fname].call(this,s);};},replace:function(rule,repl){return function(s){var r=rule.call(this,s);return[repl,r[1]];};},process:function(rule,fn){return function(s){var r=rule.call(this,s);return[fn.call(this,r[0]),r[1]];};},min:function(min,rule){return function(s){var rx=rule.call(this,s);if(rx[0].length<min){throw new $P.Exception(s);}
  428. return rx;};}};var _generator=function(op){return function(){var args=null,rx=[];if(arguments.length>1){args=Array.prototype.slice.call(arguments);}else if(arguments[0]instanceof Array){args=arguments[0];}
  429. if(args){for(var i=0,px=args.shift();i<px.length;i++){args.unshift(px[i]);rx.push(op.apply(null,args));args.shift();return rx;}}else{return op.apply(null,arguments);}};};var gx="optional not ignore cache".split(/\s/);for(var i=0;i<gx.length;i++){_[gx[i]]=_generator(_[gx[i]]);}
  430. var _vector=function(op){return function(){if(arguments[0]instanceof Array){return op.apply(null,arguments[0]);}else{return op.apply(null,arguments);}};};var vx="each any all".split(/\s/);for(var j=0;j<vx.length;j++){_[vx[j]]=_vector(_[vx[j]]);}}());(function(){var flattenAndCompact=function(ax){var rx=[];for(var i=0;i<ax.length;i++){if(ax[i]instanceof Array){rx=rx.concat(flattenAndCompact(ax[i]));}else{if(ax[i]){rx.push(ax[i]);}}}
  431. return rx;};Date.Grammar={};Date.Translator={hour:function(s){return function(){this.hour=Number(s);};},minute:function(s){return function(){this.minute=Number(s);};},second:function(s){return function(){this.second=Number(s);};},meridian:function(s){return function(){this.meridian=s.slice(0,1).toLowerCase();};},timezone:function(s){return function(){var n=s.replace(/[^\d\+\-]/g,"");if(n.length){this.timezoneOffset=Number(n);}else{this.timezone=s.toLowerCase();}};},day:function(x){var s=x[0];return function(){this.day=Number(s.match(/\d+/)[0]);};},month:function(s){return function(){this.month=((s.length==3)?Date.getMonthNumberFromName(s):(Number(s)-1));};},year:function(s){return function(){var n=Number(s);this.year=((s.length>2)?n:(n+(((n+2000)<Date.CultureInfo.twoDigitYearMax)?2000:1900)));};},rday:function(s){return function(){switch(s){case"yesterday":this.days=-1;break;case"tomorrow":this.days=1;break;case"today":this.days=0;break;case"now":this.days=0;this.now=true;break;}};},finishExact:function(x){x=(x instanceof Array)?x:[x];var now=new Date();this.year=now.getFullYear();this.month=now.getMonth();this.day=1;this.hour=0;this.minute=0;this.second=0;for(var i=0;i<x.length;i++){if(x[i]){x[i].call(this);}}
  432. this.hour=(this.meridian=="p"&&this.hour<13)?this.hour+12:this.hour;if(this.day>Date.getDaysInMonth(this.year,this.month)){throw new RangeError(this.day+" is not a valid value for days.");}
  433. var r=new Date(this.year,this.month,this.day,this.hour,this.minute,this.second);if(this.timezone){r.set({timezone:this.timezone});}else if(this.timezoneOffset){r.set({timezoneOffset:this.timezoneOffset});}
  434. return r;},finish:function(x){x=(x instanceof Array)?flattenAndCompact(x):[x];if(x.length===0){return null;}
  435. for(var i=0;i<x.length;i++){if(typeof x[i]=="function"){x[i].call(this);}}
  436. if(this.now){return new Date();}
  437. var today=Date.today();var method=null;var expression=!!(this.days!=null||this.orient||this.operator);if(expression){var gap,mod,orient;orient=((this.orient=="past"||this.operator=="subtract")?-1:1);if(this.weekday){this.unit="day";gap=(Date.getDayNumberFromName(this.weekday)-today.getDay());mod=7;this.days=gap?((gap+(orient*mod))%mod):(orient*mod);}
  438. if(this.month){this.unit="month";gap=(this.month-today.getMonth());mod=12;this.months=gap?((gap+(orient*mod))%mod):(orient*mod);this.month=null;}
  439. if(!this.unit){this.unit="day";}
  440. if(this[this.unit+"s"]==null||this.operator!=null){if(!this.value){this.value=1;}
  441. if(this.unit=="week"){this.unit="day";this.value=this.value*7;}
  442. this[this.unit+"s"]=this.value*orient;}
  443. return today.add(this);}else{if(this.meridian&&this.hour){this.hour=(this.hour<13&&this.meridian=="p")?this.hour+12:this.hour;}
  444. if(this.weekday&&!this.day){this.day=(today.addDays((Date.getDayNumberFromName(this.weekday)-today.getDay()))).getDate();}
  445. if(this.month&&!this.day){this.day=1;}
  446. return today.set(this);}}};var _=Date.Parsing.Operators,g=Date.Grammar,t=Date.Translator,_fn;g.datePartDelimiter=_.rtoken(/^([\s\-\.\,\/\x27]+)/);g.timePartDelimiter=_.stoken(":");g.whiteSpace=_.rtoken(/^\s*/);g.generalDelimiter=_.rtoken(/^(([\s\,]|at|on)+)/);var _C={};g.ctoken=function(keys){var fn=_C[keys];if(!fn){var c=Date.CultureInfo.regexPatterns;var kx=keys.split(/\s+/),px=[];for(var i=0;i<kx.length;i++){px.push(_.replace(_.rtoken(c[kx[i]]),kx[i]));}
  447. fn=_C[keys]=_.any.apply(null,px);}
  448. return fn;};g.ctoken2=function(key){return _.rtoken(Date.CultureInfo.regexPatterns[key]);};g.h=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2]|[1-9])/),t.hour));g.hh=_.cache(_.process(_.rtoken(/^(0[0-9]|1[0-2])/),t.hour));g.H=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3]|[0-9])/),t.hour));g.HH=_.cache(_.process(_.rtoken(/^([0-1][0-9]|2[0-3])/),t.hour));g.m=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.minute));g.mm=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.minute));g.s=_.cache(_.process(_.rtoken(/^([0-5][0-9]|[0-9])/),t.second));g.ss=_.cache(_.process(_.rtoken(/^[0-5][0-9]/),t.second));g.hms=_.cache(_.sequence([g.H,g.mm,g.ss],g.timePartDelimiter));g.t=_.cache(_.process(g.ctoken2("shortMeridian"),t.meridian));g.tt=_.cache(_.process(g.ctoken2("longMeridian"),t.meridian));g.z=_.cache(_.process(_.rtoken(/^(\+|\-)?\s*\d\d\d\d?/),t.timezone));g.zz=_.cache(_.process(_.rtoken(/^(\+|\-)\s*\d\d\d\d/),t.timezone));g.zzz=_.cache(_.process(g.ctoken2("timezone"),t.timezone));g.timeSuffix=_.each(_.ignore(g.whiteSpace),_.set([g.tt,g.zzz]));g.time=_.each(_.optional(_.ignore(_.stoken("T"))),g.hms,g.timeSuffix);g.d=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1]|\d)/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.dd=_.cache(_.process(_.each(_.rtoken(/^([0-2]\d|3[0-1])/),_.optional(g.ctoken2("ordinalSuffix"))),t.day));g.ddd=g.dddd=_.cache(_.process(g.ctoken("sun mon tue wed thu fri sat"),function(s){return function(){this.weekday=s;};}));g.M=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d|\d)/),t.month));g.MM=_.cache(_.process(_.rtoken(/^(1[0-2]|0\d)/),t.month));g.MMM=g.MMMM=_.cache(_.process(g.ctoken("jan feb mar apr may jun jul aug sep oct nov dec"),t.month));g.y=_.cache(_.process(_.rtoken(/^(\d\d?)/),t.year));g.yy=_.cache(_.process(_.rtoken(/^(\d\d)/),t.year));g.yyy=_.cache(_.process(_.rtoken(/^(\d\d?\d?\d?)/),t.year));g.yyyy=_.cache(_.process(_.rtoken(/^(\d\d\d\d)/),t.year));_fn=function(){return _.each(_.any.apply(null,arguments),_.not(g.ctoken2("timeContext")));};g.day=_fn(g.d,g.dd);g.month=_fn(g.M,g.MMM);g.year=_fn(g.yyyy,g.yy);g.orientation=_.process(g.ctoken("past future"),function(s){return function(){this.orient=s;};});g.operator=_.process(g.ctoken("add subtract"),function(s){return function(){this.operator=s;};});g.rday=_.process(g.ctoken("yesterday tomorrow today now"),t.rday);g.unit=_.process(g.ctoken("minute hour day week month year"),function(s){return function(){this.unit=s;};});g.value=_.process(_.rtoken(/^\d\d?(st|nd|rd|th)?/),function(s){return function(){this.value=s.replace(/\D/g,"");};});g.expression=_.set([g.rday,g.operator,g.value,g.unit,g.orientation,g.ddd,g.MMM]);_fn=function(){return _.set(arguments,g.datePartDelimiter);};g.mdy=_fn(g.ddd,g.month,g.day,g.year);g.ymd=_fn(g.ddd,g.year,g.month,g.day);g.dmy=_fn(g.ddd,g.day,g.month,g.year);g.date=function(s){return((g[Date.CultureInfo.dateElementOrder]||g.mdy).call(this,s));};g.format=_.process(_.many(_.any(_.process(_.rtoken(/^(dd?d?d?|MM?M?M?|yy?y?y?|hh?|HH?|mm?|ss?|tt?|zz?z?)/),function(fmt){if(g[fmt]){return g[fmt];}else{throw Date.Parsing.Exception(fmt);}}),_.process(_.rtoken(/^[^dMyhHmstz]+/),function(s){return _.ignore(_.stoken(s));}))),function(rules){return _.process(_.each.apply(null,rules),t.finishExact);});var _F={};var _get=function(f){return _F[f]=(_F[f]||g.format(f)[0]);};g.formats=function(fx){if(fx instanceof Array){var rx=[];for(var i=0;i<fx.length;i++){rx.push(_get(fx[i]));}
  449. return _.any.apply(null,rx);}else{return _get(fx);}};g._formats=g.formats(["yyyy-MM-ddTHH:mm:ss","ddd, MMM dd, yyyy H:mm:ss tt","ddd MMM d yyyy HH:mm:ss zzz","d"]);g._start=_.process(_.set([g.date,g.time,g.expression],g.generalDelimiter,g.whiteSpace),t.finish);g.start=function(s){try{var r=g._formats.call({},s);if(r[1].length===0){return r;}}catch(e){}
  450. return g._start.call({},s);};}());Date._parse=Date.parse;Date.parse=function(s){var r=null;if(!s){return null;}
  451. try{r=Date.Grammar.start.call({},s);}catch(e){return null;}
  452. return((r[1].length===0)?r[0]:null);};Date.getParseFunction=function(fx){var fn=Date.Grammar.formats(fx);return function(s){var r=null;try{r=fn.call({},s);}catch(e){return null;}
  453. return((r[1].length===0)?r[0]:null);};};Date.parseExact=function(s,fx){return Date.getParseFunction(fx)(s);};
  454.  
  455.  
  456. /**
  457.  * @version: 1.0 Alpha-1
  458.  * @author: Coolite Inc. http://www.coolite.com/
  459.  * @date: 2008-04-13
  460.  * @copyright: Copyright (c) 2006-2008, Coolite Inc. (http://www.coolite.com/). All rights reserved.
  461.  * @license: Licensed under The MIT License. See license.txt and http://www.datejs.com/license/.
  462.  * @website: http://www.datejs.com/
  463.  */
  464.  
  465. /*
  466.  * TimeSpan(milliseconds);
  467.  * TimeSpan(days, hours, minutes, seconds);
  468.  * TimeSpan(days, hours, minutes, seconds, milliseconds);
  469.  */
  470. var TimeSpan = function (days, hours, minutes, seconds, milliseconds) {
  471.     var attrs = "days hours minutes seconds milliseconds".split(/\s+/);
  472.    
  473.     var gFn = function (attr) {
  474.         return function () {
  475.             return this[attr];
  476.         };
  477.     };
  478.        
  479.     var sFn = function (attr) {
  480.         return function (val) {
  481.             this[attr] = val;
  482.             return this;
  483.         };
  484.     };
  485.        
  486.     for (var i = 0; i < attrs.length ; i++) {
  487.         var $a = attrs[i], $b = $a.slice(0, 1).toUpperCase() + $a.slice(1);
  488.         TimeSpan.prototype[$a] = 0;
  489.         TimeSpan.prototype["get" + $b] = gFn($a);
  490.         TimeSpan.prototype["set" + $b] = sFn($a);
  491.     }
  492.  
  493.     if (arguments.length == 4) {
  494.         this.setDays(days);
  495.         this.setHours(hours);
  496.         this.setMinutes(minutes);
  497.         this.setSeconds(seconds);
  498.     } else if (arguments.length == 5) {
  499.         this.setDays(days);
  500.         this.setHours(hours);
  501.         this.setMinutes(minutes);
  502.         this.setSeconds(seconds);
  503.         this.setMilliseconds(milliseconds);
  504.     } else if (arguments.length == 1 && typeof days == "number") {
  505.         var orient = (days < 0) ? -1 : +1;
  506.         this.setMilliseconds(Math.abs(days));
  507.        
  508.         this.setDays(Math.floor(this.getMilliseconds() / 86400000) * orient);
  509.         this.setMilliseconds(this.getMilliseconds() % 86400000);
  510.  
  511.         this.setHours(Math.floor(this.getMilliseconds() / 3600000) * orient);
  512.         this.setMilliseconds(this.getMilliseconds() % 3600000);
  513.  
  514.         this.setMinutes(Math.floor(this.getMilliseconds() / 60000) * orient);
  515.         this.setMilliseconds(this.getMilliseconds() % 60000);
  516.  
  517.         this.setSeconds(Math.floor(this.getMilliseconds() / 1000) * orient);
  518.         this.setMilliseconds(this.getMilliseconds() % 1000);
  519.  
  520.         this.setMilliseconds(this.getMilliseconds() * orient);
  521.     }
  522.  
  523.     this.getTotalMilliseconds = function () {
  524.         return (this.getDays() * 86400000) + (this.getHours() * 3600000) + (this.getMinutes() * 60000) + (this.getSeconds() * 1000);
  525.     };
  526.    
  527.     this.compareTo = function (time) {
  528.         var t1 = new Date(1970, 1, 1, this.getHours(), this.getMinutes(), this.getSeconds()), t2;
  529.         if (time === null) {
  530.             t2 = new Date(1970, 1, 1, 0, 0, 0);
  531.         }
  532.         else {
  533.             t2 = new Date(1970, 1, 1, time.getHours(), time.getMinutes(), time.getSeconds());
  534.         }
  535.         return (t1 < t2) ? -1 : (t1 > t2) ? 1 : 0;
  536.     };
  537.  
  538.     this.equals = function (time) {
  539.         return (this.compareTo(time) === 0);
  540.     };    
  541.  
  542.     this.add = function (time) {
  543.         return (time === null) ? this : this.addSeconds(time.getTotalMilliseconds() / 1000);
  544.     };
  545.  
  546.     this.subtract = function (time) {
  547.         return (time === null) ? this : this.addSeconds(-time.getTotalMilliseconds() / 1000);
  548.     };
  549.  
  550.     this.addDays = function (n) {
  551.         return new TimeSpan(this.getTotalMilliseconds() + (n * 86400000));
  552.     };
  553.  
  554.     this.addHours = function (n) {
  555.         return new TimeSpan(this.getTotalMilliseconds() + (n * 3600000));
  556.     };
  557.  
  558.     this.addMinutes = function (n) {
  559.         return new TimeSpan(this.getTotalMilliseconds() + (n * 60000));
  560.     };
  561.  
  562.     this.addSeconds = function (n) {
  563.         return new TimeSpan(this.getTotalMilliseconds() + (n * 1000));
  564.     };
  565.  
  566.     this.addMilliseconds = function (n) {
  567.         return new TimeSpan(this.getTotalMilliseconds() + n);
  568.     };
  569.  
  570.     this.get12HourHour = function () {
  571.         return (this.getHours() > 12) ? this.getHours() - 12 : (this.getHours() === 0) ? 12 : this.getHours();
  572.     };
  573.  
  574.     this.getDesignator = function () {
  575.         return (this.getHours() < 12) ? Date.CultureInfo.amDesignator : Date.CultureInfo.pmDesignator;
  576.     };
  577.  
  578.     this.toString = function (format) {
  579.         this._toString = function () {
  580.             if (this.getDays() !== null && this.getDays() > 0) {
  581.                 return this.getDays() + "." + this.getHours() + ":" + this.p(this.getMinutes()) + ":" + this.p(this.getSeconds());
  582.             }
  583.             else {
  584.                 return this.getHours() + ":" + this.p(this.getMinutes()) + ":" + this.p(this.getSeconds());
  585.             }
  586.         };
  587.        
  588.         this.p = function (s) {
  589.             return (s.toString().length < 2) ? "0" + s : s;
  590.         };
  591.        
  592.         var me = this;
  593.        
  594.         return format ? format.replace(/dd?|HH?|hh?|mm?|ss?|tt?/g,
  595.         function (format) {
  596.             switch (format) {
  597.             case "d":  
  598.                 return me.getDays();
  599.             case "dd": 
  600.                 return me.p(me.getDays());
  601.             case "H":  
  602.                 return me.getHours();
  603.             case "HH": 
  604.                 return me.p(me.getHours());
  605.             case "h":  
  606.                 return me.get12HourHour();
  607.             case "hh": 
  608.                 return me.p(me.get12HourHour());
  609.             case "m":  
  610.                 return me.getMinutes();
  611.             case "mm": 
  612.                 return me.p(me.getMinutes());
  613.             case "s":  
  614.                 return me.getSeconds();
  615.             case "ss": 
  616.                 return me.p(me.getSeconds());
  617.             case "t":  
  618.                 return ((me.getHours() < 12) ? Date.CultureInfo.amDesignator : Date.CultureInfo.pmDesignator).substring(0, 1);
  619.             case "tt": 
  620.                 return (me.getHours() < 12) ? Date.CultureInfo.amDesignator : Date.CultureInfo.pmDesignator;
  621.             }
  622.         }
  623.         ) : this._toString();
  624.     };
  625.     return this;
  626. };    
  627.  
  628. /**
  629.  * Gets the time of day for this date instances.
  630.  * @return {TimeSpan} TimeSpan
  631.  */
  632. Date.prototype.getTimeOfDay = function () {
  633.     return new TimeSpan(0, this.getHours(), this.getMinutes(), this.getSeconds(), this.getMilliseconds());
  634. };
  635.  
  636. /*
  637.  * TimePeriod(startDate, endDate);
  638.  * TimePeriod(years, months, days, hours, minutes, seconds, milliseconds);
  639.  */
  640. var TimePeriod = function (years, months, days, hours, minutes, seconds, milliseconds) {
  641.     var attrs = "years months days hours minutes seconds milliseconds".split(/\s+/);
  642.    
  643.     var gFn = function (attr) {
  644.         return function () {
  645.             return this[attr];
  646.         };
  647.     };
  648.        
  649.     var sFn = function (attr) {
  650.         return function (val) {
  651.             this[attr] = val;
  652.             return this;
  653.         };
  654.     };
  655.        
  656.     for (var i = 0; i < attrs.length ; i++) {
  657.         var $a = attrs[i], $b = $a.slice(0, 1).toUpperCase() + $a.slice(1);
  658.         TimePeriod.prototype[$a] = 0;
  659.         TimePeriod.prototype["get" + $b] = gFn($a);
  660.         TimePeriod.prototype["set" + $b] = sFn($a);
  661.     }
  662.    
  663.     if (arguments.length == 7) {
  664.         this.years = years;
  665.         this.months = months;
  666.         this.setDays(days);
  667.         this.setHours(hours);
  668.         this.setMinutes(minutes);
  669.         this.setSeconds(seconds);
  670.         this.setMilliseconds(milliseconds);
  671.     } else if (arguments.length == 2 && arguments[0] instanceof Date && arguments[1] instanceof Date) {
  672.         // startDate and endDate as arguments
  673.    
  674.         var d1 = years.clone();
  675.         var d2 = months.clone();
  676.    
  677.         var temp = d1.clone();
  678.         var orient = (d1 > d2) ? -1 : +1;
  679.        
  680.         this.years = d2.getFullYear() - d1.getFullYear();
  681.         temp.addYears(this.years);
  682.        
  683.         if (orient == +1) {
  684.             if (temp > d2) {
  685.                 if (this.years !== 0) {
  686.                     this.years--;
  687.                 }
  688.             }
  689.         } else {
  690.             if (temp < d2) {
  691.                 if (this.years !== 0) {
  692.                     this.years++;
  693.                 }
  694.             }
  695.         }
  696.        
  697.         d1.addYears(this.years);
  698.  
  699.         if (orient == +1) {
  700.             while (d1 < d2 && d1.clone().addDays(Date.getDaysInMonth(d1.getYear(), d1.getMonth()) ) < d2) {
  701.                 d1.addMonths(1);
  702.                 this.months++;
  703.             }
  704.         }
  705.         else {
  706.             while (d1 > d2 && d1.clone().addDays(-d1.getDaysInMonth()) > d2) {
  707.                 d1.addMonths(-1);
  708.                 this.months--;
  709.             }
  710.         }
  711.        
  712.         var diff = d2 - d1;
  713.  
  714.         if (diff !== 0) {
  715.             var ts = new TimeSpan(diff);
  716.             this.setDays(ts.getDays());
  717.             this.setHours(ts.getHours());
  718.             this.setMinutes(ts.getMinutes());
  719.             this.setSeconds(ts.getSeconds());
  720.             this.setMilliseconds(ts.getMilliseconds());
  721.         }
  722.     }
  723.     return this;
  724. };