【问题标题】:Bootstrap Datepicker defaults to 1900's when entered with 2 digit year当输入 2 位数年份时,Bootstrap Datepicker 默认为 1900 年
【发布时间】:2013-12-30 03:34:36
【问题描述】:

我在我的 Bootstrap 应用程序的模式窗口中使用日期选择器。我正在使用 Stefan Petre 的原始 Datepicker。我使用鼠标在桌面和移动设备上构建它,它运行良好。

最近我有一个用户请求,允许它也可以使用键盘。我删除了只读属性以允许用户在输入字段中输入日期。日期格式设置为“mm/dd/yyyy”。

当我输入像今天这样的日期时,例如“12/11/13”,那么它将默认为 1913。这没什么大不了的,因为我可以训练用户使用 4 位数字,但我会而是让它默认到本世纪。

注意:这似乎只发生在 4 位数年份的日期格式中。在 Stefan 的代码的较新分支中,这似乎也以相同的方式发生。

注意:我使用的是 Bootstrap 2.0.4。我正在使用 Firefox 进行测试。

这是它的样子:

【问题讨论】:

    标签: datepicker bootstrap-datepicker


    【解决方案1】:

    在 JavaScript 中,将 datepicker 的 assumeNearbyYear 属性设置为 true,如下所示:

    $("#dp").datepicker({
        assumeNearbyYear: true
    });
    

    【讨论】:

    • 这可能是一个较新的功能,但它是完美的答案。
    • 太棒了!几个小时的研究结束了。它在文档中,但我一辈子都找不到。
    【解决方案2】:

    这是因为 Bootstrap 日期选择器正在使用 JavaScript Date objects。当你创建一个新的 Date 对象并传入一个两位数的年份时,它将输出 1900+年(参见Why does Javascript evaluate a 2-digit year of 00 as 1900 instead of 2000?

    您可以尝试调整日期选择器源代码,但这可能太复杂了。

    根据我在http://www.eyecon.ro/bootstrap-datepicker/ 上看到的信息,没有设置可选日期范围的选项,但您可以更改格式以使用两位数年份。

    在您的屏幕截图中,我可以看到,您正在使用“到达日期”的日期选择器,我认为这是在未来。在网站上有一个关于如何禁用过去日期的示例。

    希望对你有帮助。


    更新

    我已经为您的问题编写了一个事件处理程序,应该可以解决问题。

    http://jsfiddle.net/pCYbd/1/ 上的 JavaScript

    $("#dp").datepicker();
    
    $("#dp").on("keyup", function(e) {
      var date, day, month, newYear, value, year;
      value = e.target.value;
      if (value.search(/(.*)\/(.*)\/(.*)/) !== -1) {
        date = e.target.value.split("/");
        month = date[0];
        day = date[1];
        year = date[2];
        if (year === "") {
          year = "0";
        }
        if (year.length < 4) {
          newYear = String(2000 + parseInt(year));
          $(this).datepicker("setValue", "" + month + "/" + day + "/" + newYear);
          if (year === "0") {
            year = "";
          }
          return $(this).val("" + month + "/" + day + "/" + year);
        }
      }
    });
    

    http://jsfiddle.net/pCYbd/2/ 上的 CoffeeScript

    $("#dp").datepicker()
    $("#dp").on "keyup", (e) ->
      value = e.target.value
      if value.search(/(.*)\/(.*)\/(.*)/) != -1
        date = value.split("/")
        month = date[0]
        day = date[1]
        year = date[2]      
        year = "0" if year == ""
        if year.length < 4
          newYear = String(2000 + parseInt(year))
          $(@).datepicker("setValue", "#{month}/#{day}/#{newYear}")
          year = "" if year == "0"
          $(@).val("#{month}/#{day}/#{year}")
    

    我的 JavaScript 技能不是最好的,但这应该可以。

    【讨论】:

    • 谢谢,我害怕这个。我需要一整天的时间才能真正理解 javascript 在做什么,所以我认为这不值得。我将保持开放状态,看看是否有其他人知道,如果几天后我没有得到更多答案,则接受它。谢谢!
    • 我知道你可以排除过去的值,但是日期选择器仍然可以追溯到上个世纪,即使你不能选择任何东西。如果我决定继续使用这个日期选择器,我会补充一点。
    • 你从哪里下载了日期选择器?实际上有两个版本:eyecon.ro/bootstrap-datepicker 上来自 Stefan Petre 的原始版本和bootstrap-datepicker.readthedocs.org/en/latest 上的分叉和改进版本。
    • 我使用的是 Stefan Petre 的原件,我实际上是在去年 6 月建造的,当时我不确定是否有替代方案。今天,我考虑使用较新的 bootstrap-datepicker,但它也有同样的问题。我可能会这样做,以便用户按下一个按钮来查看日期选择器,目前我在点击该字段时加载它。我发现这对移动设备更友好,但我必须找到一个快乐的媒体。
    • 作为提醒,您声明了您的value 变量,但随后不再使用它。进入循环后,您返回并再次引用 e.target.value
    【解决方案3】:

    更新 bootstrap-datepicker.js 如本文所示为我解决了这个问题https://github.com/eternicode/bootstrap-datepicker/pull/1461/commits/2ea16adad27cbc4d4dfa20b924addfb480e5b036

    yyyy: function(d,v){                      
       if (format.parts.indexOf('yyyy') > -1 && v < 1000) v = 2000+v; // this line ***
       return d.setUTCFullYear(v);
    },
    

    【讨论】:

      【解决方案4】:

      我正在使用 bootstrap-datepicker v1.5.1,如果您查看它执行年份映射的第 1741 行,您会注意到:

       yyyy: function (d, v) {
           return d.setUTCFullYear(v);
       },
       yy: function (d, v) {
           return d.setUTCFullYear(2000 + v);
       },
      

      当您指定控件使用四年日期“yyyy”时,它只会执行return d.setUTCFullYear(v);,这将为您提供JavaScript 为您提供的上一个世纪。当您指定它使用两年日期“yy”时,它将执行当前世纪所需的正确 2000+。

      因此,如果您希望正确的两年日期为 2016 年、2017 年等,则需要将日期选择器设置为使用“yy”,如下所示:

        $('#tbPurchaseDate').datepicker({
            format: 'mm/dd/yy',
            autoclose: true,
            todayBtn: 'linked',
            todayHighlight: true,
            orientation: 'bottom auto'
        });
      

      或者您可以更改 bootstrap-datepicker.js 中的“yyyy”设置以匹配“yy”版本,但是您必须记住每次通过 nuget 更新 datepicker js 文件时都要这样做。更改格式设置要容易得多。

      当然,如果您希望在控件中显示完整的 4 位数年份,那么您可能想尝试此处列出的精心修复之一,或者只需将“yyyy”设置为 js 中的“yy”文件。

      或者只是将您的代码更新到最新版本(现在是 1.6.4),并且“yyyy”和“yy”是相同的,并且您使用assumeNearbyYear: true,如另一个答案中所述。

      【讨论】:

        【解决方案5】:

        对我来说,最好的解决方案是直接在 bootstrap-datepicker.js 文件中自定义 parseDate 函数。在函数内部,有一个带有 yyyy 属性的变量 setters_map,我对其进行了一些修改。这是我的解决方案:

        yyyy: function(d,v) {
            if (v.toString().length == 2 && v <= 30) {
                v = 2000 + parseInt(v);
            }
            return d.setUTCFullYear(v);
        },
        

        在我的情况下,只需要转换小于或等于 30 的年份。

        【讨论】:

          【解决方案6】:

          在 bootstrap-datepicker.js 的更新函数中我添加了这段代码:

          var str = this.element.prop('value');
          var defaulted = false;
          if (str.lastIndexOf("/") >= 0 && (str.match(/\//g) || []).length == 2)
          {
              var yr = str.substring(str.lastIndexOf("/") + 1);
              if (yr.length <= 2)
              defaulted = true;
          }   
          if (this.date.getFullYear() < 2000 && defaulted) {
              this.date.setFullYear(this.date.getFullYear() + 100);
          }
          

          就在此行设置查看日期之前:

          this.viewDate = new Date(this.date.getFullYear(), this.date.getMonth(), 1, 0, 0, 0, 0);
          

          【讨论】:

            【解决方案7】:

            如果您在 bootstrap-datepicker.js 核心文件的 UTCDate() 中的两行以下更新,它将 100% 工作:

            函数 UTCDate(){

            /* 如果输入的日期年份小于 4 位,则日期默认日期从 2000 年开始*/
            if(arguments!=null && arguments[0].toString().length

                 return new Date(Date.UTC.apply(Date, arguments));
            

            }

            【讨论】:

            • 点评来源: 请正确格式化您的答案。另外,请避免使用 cmets 进行代码解释。
            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多