001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017: package org.apache.poi.hssf.record.formula.functions;
018:
019: import java.util.Calendar;
020: import java.util.GregorianCalendar;
021:
022: import org.apache.poi.hssf.usermodel.HSSFDateUtil;
023:
024: import org.apache.poi.hssf.record.formula.eval.Eval;
025: import org.apache.poi.hssf.record.formula.eval.RefEval;
026: import org.apache.poi.hssf.record.formula.eval.BlankEval;
027: import org.apache.poi.hssf.record.formula.eval.ErrorEval;
028: import org.apache.poi.hssf.record.formula.eval.ValueEval;
029: import org.apache.poi.hssf.record.formula.eval.NumberEval;
030: import org.apache.poi.hssf.record.formula.eval.NumericValueEval;
031:
032: /**
033: * @author Pavel Krupets (pkrupets at palmtreebusiness dot com)
034: */
035: public class Date extends NumericFunction {
036: /**
037: * @see org.apache.poi.hssf.record.formula.functions.Function#evaluate(org.apache.poi.hssf.record.formula.eval.Eval[], int, short)
038: */
039: public Eval evaluate(Eval[] operands, int srcCellRow,
040: short srcCellCol) {
041: if (operands.length == 3) {
042: ValueEval ve[] = new ValueEval[3];
043:
044: ve[0] = singleOperandEvaluate(operands[0], srcCellRow,
045: srcCellCol);
046: ve[1] = singleOperandEvaluate(operands[1], srcCellRow,
047: srcCellCol);
048: ve[2] = singleOperandEvaluate(operands[2], srcCellRow,
049: srcCellCol);
050:
051: if (validValues(ve)) {
052: int year = getYear(ve[0]);
053: int month = (int) ((NumericValueEval) ve[1])
054: .getNumberValue() - 1;
055: int day = (int) ((NumericValueEval) ve[2])
056: .getNumberValue();
057:
058: if (year < 0 || month < 0 || day < 0) {
059: return ErrorEval.VALUE_INVALID;
060: }
061:
062: if (year == 1900 && month == Calendar.FEBRUARY
063: && day == 29) {
064: return new NumberEval(60.0);
065: }
066:
067: if (year == 1900) {
068: if ((month == Calendar.JANUARY && day >= 60)
069: || (month == Calendar.FEBRUARY && day >= 30)) {
070: day--;
071: }
072: }
073:
074: Calendar c = new GregorianCalendar();
075:
076: c.set(year, month, day, 0, 0, 0);
077: c.set(Calendar.MILLISECOND, 0);
078:
079: return new NumberEval(HSSFDateUtil.getExcelDate(c
080: .getTime(), false)); // XXX fix 1900/1904 problem
081: }
082: }
083:
084: return ErrorEval.VALUE_INVALID;
085: }
086:
087: private int getYear(ValueEval ve) {
088: int year = (int) ((NumericValueEval) ve).getNumberValue();
089:
090: if (year < 0) {
091: return -1;
092: }
093:
094: return year < 1900 ? 1900 + year : year;
095: }
096:
097: private boolean validValues(ValueEval[] values) {
098: for (int i = 0; i < values.length; i++) {
099: ValueEval value = values[i];
100:
101: if (value instanceof RefEval) {
102: RefEval re = (RefEval) value;
103: ValueEval ive = re.getInnerValueEval();
104:
105: if (ive instanceof BlankEval) {
106: value = new NumberEval(0);
107: } else if (ive instanceof NumericValueEval) {
108: value = ive;
109: } else {
110: return false;
111: }
112: }
113:
114: if (!(value instanceof NumericValueEval)) {
115: return false;
116: }
117: }
118:
119: return true;
120: }
121: }
|