Skip to content

Commit

Permalink
[se]Fix bug 49355 (#3908)
Browse files Browse the repository at this point in the history
* [se]Fix bug 49355
  • Loading branch information
DimitryOrlov authored Oct 18, 2023
1 parent 874a354 commit 2c53771
Show file tree
Hide file tree
Showing 3 changed files with 203 additions and 33 deletions.
67 changes: 34 additions & 33 deletions cell/model/FormulaObjects/dateandtimeFunctions.js
Original file line number Diff line number Diff line change
Expand Up @@ -898,58 +898,59 @@
cDAYS.prototype.isXLFN = true;
cDAYS.prototype.argumentsType = [argType.number, argType.number];
cDAYS.prototype.Calculate = function (arg) {
var oArguments = this._prepareArguments(arg, arguments[1], true);
var argClone = oArguments.args;
let oArguments = this._prepareArguments(arg, arguments[1], true);
let argClone = oArguments.args;

var calulateDay = function(curArg) {
var val;
if (curArg instanceof cArray) {
const calulateDay = function(curArg) {
let val;
if (curArg.type === cElementType.cell || curArg.type === cElementType.cell3D) {
curArg = curArg.getValue();
} else if (curArg.type === cElementType.array) {
curArg = curArg.getElement(0);
} else if (curArg instanceof cArea || curArg instanceof cArea3D) {
curArg = curArg.cross(arguments[1]).tocNumber();
val = curArg.tocNumber().getValue();
} else if (curArg.type === cElementType.cellsRange || curArg.type === cElementType.cellsRange3D) {
curArg = curArg.cross(arguments[1]);
}

if (curArg instanceof cError) {
return curArg;
} else if (curArg instanceof cNumber || curArg instanceof cBool || curArg instanceof cEmpty) {
val = curArg.tocNumber().getValue();
} else if (curArg instanceof cRef || curArg instanceof cRef3D) {
val = curArg.getValue().tocNumber();
if (val instanceof cNumber || val instanceof cBool || curArg instanceof cEmpty) {
val = curArg.tocNumber().getValue();
} else {
return new cError(cErrorType.wrong_value_type);
}
} else if (curArg instanceof cString) {
val = curArg.tocNumber();
if (val instanceof cError || val instanceof cEmpty) {
var d = new cDate(curArg.getValue());
val = curArg ? curArg : new cNumber(0);

if (val.type === cElementType.error) {
return val;
} else if (val.type === cElementType.number || val.type === cElementType.bool || val.type === cElementType.empty) {
val = val.tocNumber().getValue();
} else if (val.type === cElementType.string) {
val = val.tocNumber();
if (val.type === cElementType.error || val.type === cElementType.empty) {
let d = new cDate(val.getValue());
if (isNaN(d)) {
return new cError(cErrorType.wrong_value_type);
} else {
val = Math.floor(( d.getTime() / 1000 - d.getTimezoneOffset() * 60 ) / c_sPerDay +
( AscCommonExcel.c_DateCorrectConst + (AscCommon.bDate1904 ? 0 : 1) ));
}
} else {
val = curArg.tocNumber().getValue();
val = val.tocNumber().getValue();
}
}

return val;
};

var calulateDays = function (argArray) {
var val = calulateDay(argArray[0]);
var val1 = calulateDay(argArray[1]);
if(val instanceof cError) {
return val;
} else if(val1 instanceof cError) {
return val1;
} else if (val < 0 || val1 < 0) {
const calulateDays = function (argArray) {
let end_date = calulateDay(argArray[0]);
let start_date = calulateDay(argArray[1]);
if (end_date.type === cElementType.error) {
return end_date;
} else if (start_date.type === cElementType.error) {
return start_date;
}

if (end_date < 0 || start_date < 0) {
return new cError(cErrorType.not_numeric);
} else {
return new cNumber(val - val1);
let endInteger = Math.floor(end_date);
let startInteger = Math.floor(start_date);
return new cNumber(endInteger - startInteger);

}
};

Expand Down
3 changes: 3 additions & 0 deletions common/NumFormat.js
Original file line number Diff line number Diff line change
Expand Up @@ -1656,6 +1656,8 @@ NumFormat.prototype =
year = 1900;
dayWeek = 3;
}
// todo test converting all positive fractional values less than one into dates
// else if(numberAbs === 0 || (numberAbs > 0 && numberAbs < 1))
else if(numberAbs === 0)
{
//TODO необходимо использовать cDate везде
Expand All @@ -1669,6 +1671,7 @@ NumFormat.prototype =
{
stDate = new Date(Date.UTC(1899,11,31,0,0,0));
if(d.val)
// setUTCDate doesn't consider the transition from 1899 to 1900 when adding d.val
stDate.setUTCDate( stDate.getUTCDate() + d.val );
day = stDate.getUTCDate();
dayWeek = ( stDate.getUTCDay() > 0) ? stDate.getUTCDay() - 1 : 6;
Expand Down
166 changes: 166 additions & 0 deletions tests/cell/spreadsheet-calculation/FormulaTests.js
Original file line number Diff line number Diff line change
Expand Up @@ -4181,6 +4181,7 @@ $(function () {
});

QUnit.test("Test: DAYS", function (assert) {
let array;
ws.getRange2("A2").setValue("12/31/2011");
ws.getRange2("A3").setValue("1/1/2011");

Expand All @@ -4204,6 +4205,171 @@ $(function () {
assert.ok(oParser.parse());
assert.strictEqual(oParser.calculate().getValue(), -2);

ws.getRange2("B3").setValue("44229.4673611111");
ws.getRange2("B4").setValue("44229.46875");
ws.getRange2("B5").setValue("1");
ws.getRange2("B6").setValue("1.9");
ws.getRange2("B7").setValue("2.1");
ws.getRange2("B8").setValue("10");

oParser = new parserFormula('DAYS(B4,B3)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(B4,B3)');
assert.strictEqual(oParser.calculate().getValue(), 0, 'Result of DAYS(B4,B3)');

oParser = new parserFormula('DAYS(B5,B8)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(B5,B8)');
assert.strictEqual(oParser.calculate().getValue(), -9, 'Result of DAYS(B5,B8)');

oParser = new parserFormula('DAYS(1,10)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(1,10)');
assert.strictEqual(oParser.calculate().getValue(), -9, 'Result of DAYS(1,10)');

oParser = new parserFormula('DAYS(B6,B8)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(B6,B8)');
assert.strictEqual(oParser.calculate().getValue(), -9, 'Result of DAYS(B6,B8)');

oParser = new parserFormula('DAYS(1.9,10)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(1.9,10)');
assert.strictEqual(oParser.calculate().getValue(), -9, 'Result of DAYS(1.9,10)');

oParser = new parserFormula('DAYS(B7,B8)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(B7,B8)');
assert.strictEqual(oParser.calculate().getValue(), -8, 'Result of DAYS(B7,B8)');

oParser = new parserFormula('DAYS(2.1,10)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(2.1,10)');
assert.strictEqual(oParser.calculate().getValue(), -8, 'Result of DAYS(2.1,10)');

oParser = new parserFormula('DAYS(2.1,10.1)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(2.1,10.1)');
assert.strictEqual(oParser.calculate().getValue(), -8, 'Result of DAYS(2.1,10.1)');

oParser = new parserFormula('DAYS(2.1,10.9)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(2.1,10.9)');
assert.strictEqual(oParser.calculate().getValue(), -8, 'Result of DAYS(2.1,10.9)');

oParser = new parserFormula('DAYS(2.1,-10.9)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(2.1,-10.9)');
assert.strictEqual(oParser.calculate().getValue(), "#NUM!", 'Result of DAYS(2.1,-10.9)');

oParser = new parserFormula('DAYS(-2.1,10.9)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(-2.1,10.9)');
assert.strictEqual(oParser.calculate().getValue(), "#NUM!", 'Result of DAYS(2.1,10.9)');

oParser = new parserFormula('DAYS(-2.1,-10.9)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(-2.1,-10.9)');
assert.strictEqual(oParser.calculate().getValue(), "#NUM!", 'Result of DAYS(-2.1,-10.9)');

oParser = new parserFormula('DAYS(,10.9)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(,10.9)');
assert.strictEqual(oParser.calculate().getValue(), -10, 'Result of DAYS(,10.9)');

oParser = new parserFormula('DAYS(2.1,)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(2.1,)');
assert.strictEqual(oParser.calculate().getValue(), 2, 'Result of DAYS(2.1,)');

oParser = new parserFormula('DAYS(,)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(,)');
assert.strictEqual(oParser.calculate().getValue(), 0, 'Result of DAYS(,)');

// string
oParser = new parserFormula('DAYS("1","10")', "A1", ws);
assert.ok(oParser.parse(), 'DAYS("1","10")');
assert.strictEqual(oParser.calculate().getValue(), -9, 'Result of DAYS("1","10")');

oParser = new parserFormula('DAYS("1s","10")', "A1", ws);
assert.ok(oParser.parse(), 'DAYS("1s","10")');
assert.strictEqual(oParser.calculate().getValue(), "#VALUE!", 'Result of DAYS("1s","10")');

oParser = new parserFormula('DAYS("1","10s")', "A1", ws);
assert.ok(oParser.parse(), 'DAYS("1","10s")');
assert.strictEqual(oParser.calculate().getValue(), "#VALUE!", 'Result of DAYS("1","10s")');

// bool
oParser = new parserFormula('DAYS(TRUE,10)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(TRUE,10)');
assert.strictEqual(oParser.calculate().getValue(), -9, 'Result of DAYS(TRUE,10)');

oParser = new parserFormula('DAYS(FALSE,10)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(FALSE,10)');
assert.strictEqual(oParser.calculate().getValue(), -10, 'Result of DAYS(FALSE,10)');

oParser = new parserFormula('DAYS(1,TRUE)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(1,TRUE)');
assert.strictEqual(oParser.calculate().getValue(), 0, 'Result of DAYS(1,TRUE)');

oParser = new parserFormula('DAYS(1,FALSE)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(1,FALSE)');
assert.strictEqual(oParser.calculate().getValue(), 1, 'Result of DAYS(1,FALSE)');

oParser = new parserFormula('DAYS(TRUE,TRUE)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(TRUE,TRUE)');
assert.strictEqual(oParser.calculate().getValue(), 0, 'Result of DAYS(TRUE,TRUE)');

// errors
ws.getRange2("B100").setValue("#N/A");
ws.getRange2("B101").setValue("#NUM!");

oParser = new parserFormula('DAYS(#N/A,10)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(#N/A,10)');
assert.strictEqual(oParser.calculate().getValue(), "#N/A", 'Result of DAYS(#N/A,10)');

oParser = new parserFormula('DAYS(B100,10)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(B100,10)');
assert.strictEqual(oParser.calculate().getValue(), "#N/A", 'Result of DAYS(B100,10)');

oParser = new parserFormula('DAYS(#N/A,#NUM!)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(#N/A,#NUM!)');
assert.strictEqual(oParser.calculate().getValue(), "#N/A", 'Result of DAYS(#N/A,#NUM!)');

oParser = new parserFormula('DAYS(B100,B101)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(B100,B101)');
assert.strictEqual(oParser.calculate().getValue(), "#N/A", 'Result of DAYS(B100,B101)');

oParser = new parserFormula('DAYS(#NUM!,#N/A)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(#NUM!,#N/A)');
assert.strictEqual(oParser.calculate().getValue(), "#NUM!", 'Result of DAYS(#NUM!,#N/A)');

oParser = new parserFormula('DAYS(B101,B100)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS(B101,B100)');
assert.strictEqual(oParser.calculate().getValue(), "#NUM!", 'Result of DAYS(B101,B100)');

// array
oParser = new parserFormula('DAYS({1;2;3},10)', "A1", ws);
assert.ok(oParser.parse(), 'DAYS({1;2;3},10)');
assert.strictEqual(oParser.calculate().getValue(), -9, 'Result of DAYS({1;2;3},10)');

oParser = new parserFormula('DAYS({1;2;3},10)', "A1", ws);
oParser.setArrayFormulaRef(ws.getRange2("F106:I109").bbox);
assert.ok(oParser.parse(), 'DAYS({1;2;3},10)');
array = oParser.calculate();
assert.strictEqual(array.getElementRowCol(0, 0).getValue(), -9, 'Result of DAYS({1;2;3},10)[0,0]');
assert.strictEqual(array.getElementRowCol(1, 0).getValue(), -8, 'Result of DAYS({1;2;3},10)[1,0]');
assert.strictEqual(array.getElementRowCol(2, 0).getValue(), -7, 'Result of DAYS({1;2;3},10)[2,0]');

oParser = new parserFormula('DAYS({1;2;3},{10;9;8})', "A1", ws);
oParser.setArrayFormulaRef(ws.getRange2("F106:I109").bbox);
assert.ok(oParser.parse(), 'DAYS({1;2;3},{10;9;8})');
array = oParser.calculate();
assert.strictEqual(array.getElementRowCol(0, 0).getValue(), -9, 'Result of DAYS({1;2;3},{10;9;8})[0,0]');
assert.strictEqual(array.getElementRowCol(1, 0).getValue(), -7, 'Result of DAYS({1;2;3},{10;9;8})[1,0]');
assert.strictEqual(array.getElementRowCol(2, 0).getValue(), -5, 'Result of DAYS({1;2;3},{10;9;8})[2,0]');

// range
ws.getRange2("A25").setValue("1");
ws.getRange2("A26").setValue("2");
ws.getRange2("A27").setValue("3");
ws.getRange2("B25").setValue("10");
ws.getRange2("B26").setValue("9");
ws.getRange2("B27").setValue("8");

oParser = new parserFormula('DAYS(A25:A27,B25:B27)', "A1", ws);
oParser.setArrayFormulaRef(ws.getRange2("F106:I109").bbox);
assert.ok(oParser.parse(), 'DAYS(A25:A27,B25:B27)');
array = oParser.calculate();
assert.strictEqual(array.getElementRowCol(0, 0).getValue(), -9, "Result of DAYS(A25:A27,B25:B27)[0,0]");
assert.strictEqual(array.getElementRowCol(1, 0).getValue(), -7, "Result of DAYS(A25:A27,B25:B27)[1,0]");
assert.strictEqual(array.getElementRowCol(2, 0).getValue(), -5, "Result of DAYS(A25:A27,B25:B27)[2,0]");

testArrayFormula2(assert, "DAYS", 2, 2);
});
Expand Down

0 comments on commit 2c53771

Please sign in to comment.