无法使用Javascript验证两位数月份

时间:2012-10-04 02:07:10

标签: javascript html

我有一个HTML表单,我允许用户输入日期来打印报告。但是,如果该日期在当前日期的3天之内,我会设置告诉用户他们必须等待3天。出于某种原因,当我输入类似“09/30/2012”的内容时,代码会起作用,但是当我输入“10/01/2012”时,错误检查会跳过。看来,如果它是一个两位数的月份(10,11和12),它会完全跳过错误检查。如果您有任何想法,请告诉我。感谢

JS代码:

var date = myForm.SC_date.value;
var d = new Date(date);
var varBegin = (d.getMonth()+1) + "-" + (d.getDate()-3) + "-" + d.getFullYear()
re = /^\d{1,2}\/\d{1,2}\/\d{4}$/;

if (myForm.SC_date.value == "")
    window.alert("Please enter the requested date of variance.  NOTE: Date must be 3 days prior to today's date.")

            //Here is where I am having issues  
/*else if(new Date(date) > new Date(varBegin))
    window.alert("Invalid date.  You must wait at least 3 days before you can request a report.")*/

else if(!myForm.SC_date.value.match(re))
    window.alert("Invalid date.  Please enter the date as follows: mm/dd/yyyy.")

HTML代码:

<td>Date of Variance </td>
    <td colspan="2"><input name="SC_date:*" id="SC_date" type="text" tabindex="06">
      </textarea><b><span class="style3">*</span>&nbsp;&nbsp;</b><span class="style2">(mm/dd/yyyy)</span>
    </td>

3 个答案:

答案 0 :(得分:2)

我认为您不想通过操纵字符串来构建“3天前”日期。即,这个片段在这里:

var varBegin = (d.getMonth()+1) + "-" + (d.getDate()-3) + "-" + d.getFullYear()

首先,当你在输入字段中使用正斜杠作为分隔符时,我不确定为什么你在这里使用连字符作为分隔符?

在任何情况下,这都不是构建日期的可靠方法。当您将字符串提供给Date对象的构造函数时,您实际上正在调用Date.parse()。在不同的浏览器上表现不同。

检查出来:

> new Date('1-1-2012');
Sun Jan 01 2012 00:00:00 GMT-0800 (PST)

> new Date('01-01-2012');
Sun Jan 01 2012 00:00:00 GMT-0800 (PST)

> new Date('2012-1-1');
Sun Jan 01 2012 00:00:00 GMT-0800 (PST)

看起来很不错吧?但那是在Chrome上。

现在查看最新版本的Firefox中发生的情况,并使用完全相同的调用:

> new Date('1-1-2012');
Date {Invalid Date}

> new Date('01-01-2012');
Date {Invalid Date}

> new Date('2012-1-1');
Date {Invalid Date}

> new Date('2012-01-01');
Date {Sat Dec 31 2011 16:00:00 GMT-0800 (PST)}

此外,请在两种浏览器中查看此行为:

> new Date('2012-01-01');
Sat Dec 31 2011 16:00:00 GMT-0800 (PST)

简单地将零添加到月份和日期数字会导致时间扭曲!你必须设置时间和时区(对我来说,PST)才能消失:

> new Date('2012-01-01T00:00:00-08:00')
Sun Jan 01 2012 00:00:00 GMT-0800 (PST)

基本上,处理日期字符串解析很麻烦。您不希望对thisthisthis等规范进行摘要和说明。

所以,这是一个更好的选择 - 将年,月和日期值(按此顺序)传递给Date对象的构造函数。这将为您可靠地创建日期,因此您的比较是有效的。

像这样,针对您的具体示例:

var WARNING_PERIOD_IN_DAYS = 3;
// Extract month, day, year from form input, 'trimming' whitespace.
var re = /^\s*(\d{1,2})\/(\d{1,2})\/(\d{4})\s*$/;
var match = re.exec(inputVal); // from "myForm.SC_date.value".
if (match) {
  var month = parseInt(match[1]) - 1; // Zero-indexed months.
  var date = parseInt(match[2]);
  var year = parseInt(match[3]);
  var inputDate = new Date(year, month, date);
  var currentDate = new Date();
  var threeDaysAgo = new Date(currentDate.getFullYear(), currentDate.getMonth(), currentDate.getDay() - WARNING_PERIOD_IN_DAYS);
  console.log((inputDate > threeDaysAgo) ? 'Within warning period' : 'No warning needed');
}

说到规格,这里有一个很酷的注意事项,那就是在JavaScript中,你可以“包装”日期值(它可能太大或者为负),结果日期仍然有效且正确。原因如下:

根据ECMAScript 262规范,这是您致电setDate()时会发生什么:

**15.9.5.36 Date.prototype.setDate (date)**
1. Let t be the result of LocalTime(this time value).
2. Let dt be ToNumber(date).
3. Let newDate be MakeDate(MakeDay(YearFromTime(t), MonthFromTime(t), dt), TimeWithinDay(t)).
4. Let u be TimeClip(UTC(newDate)).
5. Set the [[PrimitiveValue]] internal property of this Date object to u.
6. Return u.

这是关键点:MakeDay(YearFromTime(t), MonthFromTime(t), dt)

MakeDay从Date对象的当前时间值(以纪元时间的毫秒为单位)获取年份和月份,并执行以下操作:

**15.9.1.12 MakeDay (year, month, date)**
The operator MakeDay calculates a number of days from its three arguments, which must be ECMAScript Number values. This operator functions as follows:
1. If year is not finite or month is not finite or date is not finite, return NaN.
2. Let y be ToInteger(year).
3. Let m be ToInteger(month).
4. Let dt be ToInteger(date).
5. Let ym be y + floor(m /12).
6. Let mn be m modulo 12.
7. Find a value t such that YearFromTime(t) == ym and MonthFromTime(t) == mn and DateFromTime(t) == 1;
but if this is not possible (because some argument is out of range), return NaN. 
8. Return Day(t) + dt - 1.

这看起来很复杂,但基本上就是:

  • floormodulodate==1位处理月份翻转(负数或大于12的月份)。
  • 在纪元时间内产生的瞬间转换为若干天。
  • 您的日期值会添加到该天数。如果您的日期值为负数,那就没问题,只会减去它。
  • 结果传回setDate()。
  • setDate调用MakeDate(),它将天数加上日内时间转换为以纪元为单位的毫秒数。
  • Date对象的内部时间设置为此新纪元时间。

这就是为什么你可以做这样的事情(来自V8 JS引擎项目中MakeDay() function的评论):

//     MakeDay(2007, -4, 20) --> MakeDay(2006, 8, 20)
//     MakeDay(2007, -33, 1) --> MakeDay(2004, 3, 1)
//     MakeDay(2007, 14, -50) --> MakeDay(2007, 8, 11)

好的,因此对于这个特殊问题来说几乎肯定是太多细节......但我只是想弄清楚幕后真的发生了什么。谢谢你的耐心等待。

而且......最后一件事......

您的HTML代码段中有一个随机的</textarea>。如果在它之前的某个地方有一个开口<textarea>,那么它会错误地包含你的其他一些元素。如果没有空缺<textarea>,请将其删除。

答案 1 :(得分:0)

如果您不关心一天中的时间,我建议您执行以下操作:

var dUser = new Date(date); //just like you did before
var dVarBegin = new Date("10/05/2012"); //here you do whatever is the date you are setting.
var diff = dVarBegin.getTime() - dUser.getTime();
//now diff is the difference in milliseconds!

我不完全理解您对3天的要求。但是,如果你需要的是比较日期,现在你可以!我希望这适合你。如果你还需要更多东西,请在3天内详细说明。

答案 2 :(得分:0)

使用可让您控制所接受日期格式的库,例如Globalize.js或Date.js.然后定义您希望执行的确切测试,尤其是当天的时间是否重要以及测试是否应该相对于用户系统中的当前时间(这是您使用new Date()无参数获得的)。你可以,例如计算@Mamsaac概述的时差,并使用简单的算术将毫秒转换为天。

使用Date()是不合逻辑的,然后在不检查结果的情况下,开始对输入进行模式匹配。此外,Date()根据定义是系统相关的,很少使用。无法保证它会接受像mm / dd / yyyy这样的格式。