正しくないフォーマットの日付を検証できない場合がある

文書番号 : 39532     文書種別 : 制限事項     登録日 : 2016/08/23     最終更新日 : 2016/08/23
文書を印刷する
対象製品
SpreadJS 9J
発生環境
SP1(9.20161.0), FireFox, Internet Explorer
詳細
日付データの"月"や"日"に該当する部分に最終月、最終日を上回る(もしくは下回る)数字を設定した場合に、これを正しく検証できない現象が発生します。

【現象再現コード】
----------------------------------------
var condition = GC.Spread.Sheets.ConditionalFormatting.ComparisonOperators.between;
var startDate = new Date(2016, 0, 1);
var endDate = Date(2016, 11, 31);
var validator = GC.Spread.Sheets.DataValidation.createDateValidator(condition, startDate, endDate);
----------------------------------------

上記のような検証設定(日付有効範囲:2016/1/1 - 2016/12/31)を行ったセルで、以下のようなデータが正しく検証されません。(不正なデータとならず、正常なデータと判断されます。)

【正しく検証できない日付の例】

・2016/0/32
・2016/0/397
・2016/13/0
・2016/1/32

本現象は、Internet ExplorerおよびFireFoxにおけるJavaScriptの標準処理が、上記【正しく検証できない日付の例】を正しい日付として処理する動作に起因しており、製品の内部動作からこれを制御し、"正しくない日付"として扱うことができません。
回避方法
下記のようなカスタム検証を作成することで、現象の回避が可能です。

----------------------------------------
window.onload = function(){
  // 初期化処理
  var spread = new GC.Spread.Sheets.Workbook(document.getElementById("ss"));
  var sheet = spread.getActiveSheet();

  // 検証の設定
  var startDate = new Date(2016, 0, 1);
  var endDate = new Date(2016, 11, 31);
  var validator = new GC.Spread.Sheets.DataValidation.DefaultDataValidator(new CustomDateCondition(startDate, endDate));
  validator.type(GC.Spread.Sheets.DataValidation.CriteriaType.custom);
  sheet.getCell(3, 3).backColor('yellow').validator(validator);
  
  // 検証エラー発生時の処理
  sheet.bind(GC.Spread.Sheets.Events.ValidationError, function (sendar, args) {
    args.validationResult = GC.Spread.Sheets.DataValidation.DataValidationResult.discard;
    setTimeout(function () {
      alert("無効なデータです");
    }, 0);
  })
}

//--------------------------------------------------
// カスタム検証処理【回避コード】
//--------------------------------------------------
function CustomDateCondition(date1, date2) {
  var con1 = new
  GC.Spread.Sheets.ConditionalFormatting.Condition(GC.Spread.Sheets.ConditionalFormatting.ConditionType.dateCondition, {
    compareType: GC.Spread.Sheets.ConditionalFormatting.DateCompareType.afterEqualsTo,
    expected: date1
  });
  var con2 = new
  GC.Spread.Sheets.ConditionalFormatting.Condition(GC.Spread.Sheets.ConditionalFormatting.ConditionType.dateCondition, {
    compareType: GC.Spread.Sheets.ConditionalFormatting.DateCompareType.beforeEqualsTo,
    expected: date2
  });
  GC.Spread.Sheets.ConditionalFormatting.Condition.call(this, GC.Spread.Sheets.ConditionalFormatting.ConditionType.relationCondition,
                             {compareType: GC.Spread.Sheets.ConditionalFormatting.LogicalOperators.and, item1: con1, item2: con2});
  
}

CustomDateCondition.prototype = new GC.Spread.Sheets.ConditionalFormatting.Condition();
CustomDateCondition.prototype.evaluate = function (evaluator, baseRow, baseColumn, actualObj) {
  if(actualObj){
    if(this._isValidDateString(actualObj)){
      return GC.Spread.Sheets.ConditionalFormatting.Condition.prototype.evaluate.apply(this, arguments);
    }
    return false;
  }
  return false;
}

CustomDateCondition.prototype._isValidDateString = function (dateObj) {
  if(typeof(dateObj)==="string"){
    //"yyyy/mm/dd", "yyy-mm-dd", "dd/mm/yyyy"を検証する処理
    var arr = dateObj.split("/");
    if (arr.length !== 3) {
      return false;
    }
    var year = +arr[0], month = +arr[1], day = +arr[2];
    var date = new Date(dateObj);
    if (date.getFullYear() === year &&
      date.getMonth() === month - 1 &&
      date.getDate() === day) {
      return true;
    }
    return false;
  }
  return true;
}
----------------------------------------