页面上一个日期计算的小东东

      客户的要求(查看图片),点击Range,可以选择一个日期范围,点击Calc可以选择日期的计算,计算完后,结果会同时显示在后面的input里,可以看下图片。因为考虑到很多地方要用到,所以写到help方法里了。感觉这个东西以后还会用,估计其他的同学也有可能会用到类似的功能,所以发出来,大家看看。计算日期用ruby代码来写很方便,用js代码来写,就很麻烦。
_time_period.html.erb
<% prefix << '_' unless prefix.blank? %>
<a onclick="$('<%= prefix %>unequal').style.display=($('<%= prefix %>unequal').style.display=='none' ? '' : 'none');$('<%= prefix %>widget').style.display='none';$('<%= prefix %>change_type').value = '';$('<%= prefix %>_num').value='';$('<%= prefix %>time_type').value='';$('#<%= prefix %>big').value = '';$('<%= prefix %>less').value='';" >Range</a>&nbsp;&nbsp;
<a onclick="$('<%= prefix %>widget').style.display=($('<%= prefix %>widget').style.display=='none' ? '' : 'none');$('<%= prefix %>unequal').style.display='none';$('<%= prefix %>big').value = '';$('<%= prefix %>less').value='';$('<%= prefix %>change_type').value = '';$('<%= prefix %>time_num').value='';$('<%= prefix %>time_type').value='';" >Calc</a><span> =
  <%= calendar_date_select_tag("#{prefix}equal",nil,:style => "width: 80px;",:embedded => false,:year_range => 30.years.ago..-30.years.ago) %>
</span><span id='<%= prefix %>unequal' style='display: none;'>>
  <%= calendar_date_select_tag("#{prefix}big",nil,:style => "width: 80px;",:embedded => false,:year_range => 30.years.ago..-30.years.ago) %>
  <
  <%= calendar_date_select_tag("#{prefix}less",nil,:style => "width: 80px;",:embedded => false,:year_range => 30.years.ago..-30.years.ago ) %>
</span>
<span id='<%= prefix %>widget' style='display:none;'>
  <script type="text/javascript">

    var equal = $('<%= prefix %>equal');
    var change_type = $('<%= prefix %>change_type');
    var time_num = $('<%= prefix %>time_num');
    var time_type = $('<%= prefix %>time_type');

    equal.observe('change', function(event){
      count_date();
    });
    change_type.observe('change', function(event){
      count_date();
      enter_equal();
    });
    time_num.observe('change', function(event){
      count_date();
      enter_equal();
    });
    time_type.observe('change', function(event){
      count_date();
      enter_equal();
    });

    function enter_equal(){
      if($F('<%= prefix %>equal')==''){alert('Please enter a date first!');}
    }

    function count_date(){
      if((!equal.value.blank()) && (!change_type.value.blank()) && (!time_num.value.blank()) && (!time_type.value.blank())){
        var time_num_number = Number(time_num.value);
        if (/^\d+$/.test(String(time_num.value)) && IsDate(equal.value)) {
          var r = equal.value.match(/^(\d{1,4})([-|\/])(\d{1,2})\2(\d{1,2})$/);
          var year = Number(r[1]);
          var month = Number(r[3]);
          var day = Number(r[4]);
          if(time_type.value == 0){
            $('<%= prefix %>result').value = equal.value;
          } else {
            if(change_type.value == 'plus' && time_type.value == 'days'){
              day = day + time_num_number;
            } else if (change_type.value == 'plus' && time_type.value == 'months') {
              month = month + time_num_number;
            } else if (change_type.value == 'plus' && time_type.value == 'years'){
              year = year + time_num_number;
            } else if (change_type.value == 'minus' && time_type.value == 'days'){
              day = day - time_num_number;
            } else if (change_type.value == 'minus' && time_type.value == 'months'){
              month = month - time_num_number;
            } else if (change_type.value == 'minus' && time_type.value == 'years'){
              year = year - time_num_number;
            }
            var result = correct_date(Number(year),Number(month),Number(day));
            $('<%= prefix %>result').value = result;
          }
        } else {
          $('<%= prefix %>result').value = '';
        }
      } else {
        $('<%= prefix %>result').value = '';
      }
    }
  </script>
  <select id='<%= prefix %>change_type' style='width: 80px;'>
    <option value=''>(+/-)</option>
    <option value='plus'>+</option>
    <option value='minus'>-</option>
  </select>
  <%= text_field_tag("#{prefix}time_num",nil,:style => 'width: 80px;' ) %>
  <select id='<%= prefix %>time_type' style='width: 80px;' >
    <option value=''>(d/m/y)</option>
    <option value='days'>Days</option>
    <option value='months'>Months</option>
    <option value='years'>Years</option>
  </select>
  <input type='text' readonly='readonly' id='<%= prefix %>result' value='' size=10 />
</span>


         <%= render :partial => 'time_period',:locals => { :prefix => ''}  %>

//匹配//yyyy-mm-dd || yyyy/mm/dd
function IsDate(str)
{
    var r = str.match(/^(\d{1,4})(-|\/)(\d{1,2})\2(\d{1,2})$/);
    if(r==null)return false; var d = new Date(r[1], r[3]-1, r[4]);
    return (d.getFullYear()==r[1]&&(d.getMonth()+1)==r[3]&&d.getDate()==r[4]);
}

//修正日期
//这里一直想不到很好的实现方法
function correct_date(year,month,day){
    var stand_day = day_max(year,month);
    if(day > stand_day){
        day = day - stand_day;
        month = month + 1;
    }
    if(month > 12){
        month = month - 12;
        year = year + 1;
    }
    if(day <= 0){
        var last_stand_day = day_max(year, month - 1);
        month = month - 1;
        day = day + last_stand_day;
    }
    if(month <= 0){
        month = month + 12;
        year = year - 1;
    }
    if(year <= 0){
        alert('invalid year!');
        return false;
    }
    var str_month = (month >= 10) ? String(month) : '0'+ String(month);
    var str_day = (day >= 10) ? String(day) : '0'+ String(day);
    var str = String(year)+'-'+str_month+'-'+str_day;
    if(IsDate(str)){
        return str;
    } else {
        return correct_date(year,month,day);
    }
}

//当月的最大日期
function day_max(year,month){
    if(month==4 || month==6 || month==9 || month==11){
        return 30;
    } else if(month==1 || month==3 || month==5 || month==7 || month==8 || month==10 || month==12){
        return 31;
    } else {
        if(isleap(year)){
            return 29;
        } else {
            return 28;
        }
    }
}

//是否是闰年
function isleap(year){
    return (year % 4 == 0 || (year % 100 == 0 && year % 400 == 0))
}

      关于这段js代码,其实一直在后台有ruby实现的,相对而言,简单很多
          if params[:change_type] == "plus"
            date = params[:equal].to_date + params[:time_num].to_i
          elsif params[:change_type] == "minus"
            date = params[:equal].to_date - params[:time_num].to_i
          end
          if params[:change_type] == "plus"
            date = date.months_since(params[:time_num].to_i)
          elsif params[:change_type] == "minus"
            date = date.months_ago(params[:time_num].to_i)
          end

      但是考虑到,如果用js的话,可以避免多余的和后台通信,而且以后复用的话,不用在加很多代码。
关于这段js日期计算,冥冥之中感觉应该还有比较更好的写法,对js日期这块不熟悉,希望有经验的能提出意见。
就是他了,year,month,day在这里其实每次只有一个值在变,但是变化的范围不确定。
//修正日期
function correct_date(year,month,day){
    var stand_day = day_max(year,month);
    if(day > stand_day){
        day = day - stand_day;
        month = month + 1;
    }
    if(month > 12){
        month = month - 12;
        year = year + 1;
    }
    if(day <= 0){
        var last_stand_day = day_max(year, month - 1);
        month = month - 1;
        day = day + last_stand_day;
    }
    if(month <= 0){
        month = month + 12;
        year = year - 1;
    }
    if(year <= 0){
        alert('invalid year!');
        return false;
    }
    var str_month = (month >= 10) ? String(month) : '0'+ String(month);
    var str_day = (day >= 10) ? String(day) : '0'+ String(day);
    var str = String(year)+'-'+str_month+'-'+str_day;
    if(IsDate(str)){
        return str;
    } else {
        return correct_date(year,month,day);
    }
}

你可能感兴趣的:(JavaScript,html,F#,Ruby)