【问题标题】:How can I dynamically set an end date based on a given start date and term duration?如何根据给定的开始日期和期限动态设置结束日期?
【发布时间】:2016-03-11 00:42:24
【问题描述】:

我想根据学期类型(年、半年、季度、月)和学期开始日期动态设置学期结束日期。

因此,如果我们将期限设置为年度,并且开始日期设置为 03/10/2016,则期限结束应设置为 03/10/2017。

到目前为止,这是我所拥有的,但不确定如何处理 Term Type(每年 == 12 个月等)。我还收到日期格式的控制台错误。任何帮助或指点将不胜感激。

.field
  = f.label :term_start_date, 'Term Start', class: 'label'
  .input
    = f.date_field :term_start_date, id: 'termStart'
.field
  = f.label :term_end_date, 'Term End', class: 'label'
  .input
    = f.date_field :term_end_date, id: 'termEnd'
    :javascript
      $("#termStart").val();
      $("#termEnd").val({
          onSelect: function () {
              var toDate = $(this).val('getDate');
              toDate.setDate(toDate.getDate()+7)
              $("#termStart").val("setDate", toDate);
          }
      });

指定的值“[object Object]”不符合要求的格式,“yyyy-MM-dd”。

【问题讨论】:

  • 如果你有一个 Date 对象,你可以简单地添加一年:date.setFullYear(date.getFullYear() + 1)。请注意,2 月 29 日加上一年将导致下一年的 3 月 1 日。如果你想要 2 月 28 日,你需要处理这个问题。您可以使用类似的方法来添加月、日、小时等。

标签: javascript ruby-on-rails date datepicker


【解决方案1】:

您正在尝试的事情并不难,但还有一些工作要做。日期库可以提供帮助,但编写自己的方法并不需要花费太多精力。你需要做几件事:

  1. 解析并验证输入的开始日期
  2. 获取期限并在开始日期上添加几个月
  3. 处理无效输入
  4. 显示结果

以下内容不使用任何 jQuery(您可以根据需要使用它,但它没有任何好处)并且应该让您对需要做什么有所了解。

var dLib = {

  // Given a date string in format m/d/y, return a Date instance
  parseMDY: function (s) {
    var b = s.split(/\D+/);
    var d = new Date(b[2], --b[0], b[1]);
    return /\d{1,2}\/\d{1,2}\/\d{1,4}/.test(s) &&
           d.getMonth() == b[0]? d : new Date(NaN);
  },

  // Given a Date, return date string formatted as mm/dd/yyyy
  formatMDY: function (date) {
    function z(n){return (n<10?'0':'')+n}
    if (isNaN(date)) return date.toString();
    return z(date.getMonth() + 1) + '/' + z(date.getDate()) + '/' + date.getFullYear();
  },

  // Add months to a date. If end date itn's equal to start date,
  // must have gone past end of month so set to last day of month
  addMonths: function (date, months) {
    var startDate = date.getDate();
    date = new Date(+date);
    date.setMonth(date.getMonth() + Number(months))
    if (date.getDate() != startDate) {
      date.setDate(0);
    }
    return date;
  },
};

function setTermEnd(el) {
  var form = el.form;
  var term = form.termInMonths.value;
  var startDate = dLib.parseMDY(form.termStart.value);
  
  // Check that a valid date was entered. If no date entered
  // yet, do nothing. Else, put error message in termEnd
  if (isNaN(startDate)) {
    form.termEnd.value = form.termStart.value == ''? '' : 'Term start date is invalid';
    
  // Add months and set term end
  } else {
    form.termEnd.value = dLib.formatMDY(dLib.addMonths(startDate, term));
  }
}

// Attach listeners and run to initialise
window.onload = function() {
  var form = document.forms[0];
  form.termInMonths.onchange = function() {setTermEnd(this)};
  form.termStart.onchange = function() {setTermEnd(this)};
  form.termStart.onchange(form.termStart);
}
.hint {
  color: #999999;
  font-size: 75%;
}
<form>
  <table>
   <tr><td>Term:<td><select name="termInMonths">
                      <option value="12" selected>Annual
                      <option value="6">Semi-annual
                      <option value="3">Quarter
                      <option value="1">Month
                    </select>
   <tr><td>Term start:<td><input name="termStart" value="1/31/2016"><span class="hint">m/d/y</span>
   <tr><td>Term End:<td><input name="termEnd" readonly><span class="hint">m/d/y</span>
  </table>
</form>

【讨论】:

  • 我实际上更喜欢香草 js。随着我继续学习 js,我喜欢了解发生了什么而不是使用库。你的回答很清楚,肯定帮助我理解了我需要做什么。谢谢!
【解决方案2】:

Javascript 的内置日期时间操作非常有限。

最好的办法是使用 javascript 日期时间库。 moment.js 不错

您的第二个最佳选择是以秒为单位处理时间,因为 javascript 就是这样做的。使用 Date.parse(toDate) 将其转换为自纪元以来的秒数,然后添加秒数,然后将其转换回日期。

【讨论】:

  • 不推荐使用 Date.parse (或 Date 构造函数,它们与解析等效)来解析字符串。 Date 对象具有非常强大的方法,可以在日期或时间的任何部分添加和减去值。它们确实缺乏像样的解析器、良好的格式和对多个时区的支持,但除此之外并没有太多缺失。
  • 我的立场是正确的。文档中实际上并没有明确说明将月份设置为“14”会导致将其设置为明年 3 月,这就是为什么我认为您会在保险箱中查看一些数学来弄乱它们方法。但是,出于此请求的目的,这确实可行。
  • “不清楚”是正确的,但可以按照§20.3.4.25中的算法推导出结果。真正的工作是在§20.3.1.13 中完成的,它允许月数大于 12,天数大于任何特定月份的长度。 :-)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-12-23
  • 2013-12-20
  • 2016-10-19
相关资源
最近更新 更多