| /* ==================================================================== |
| Licensed to the Apache Software Foundation (ASF) under one or more |
| contributor license agreements. See the NOTICE file distributed with |
| this work for additional information regarding copyright ownership. |
| The ASF licenses this file to You under the Apache License, Version 2.0 |
| (the "License"); you may not use this file except in compliance with |
| the License. You may obtain a copy of the License at |
| |
| http://www.apache.org/licenses/LICENSE-2.0 |
| |
| Unless required by applicable law or agreed to in writing, software |
| distributed under the License is distributed on an "AS IS" BASIS, |
| WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| See the License for the specific language governing permissions and |
| limitations under the License. |
| ==================================================================== */ |
| |
| package org.apache.poi.ss.formula.functions; |
| |
| import java.util.Calendar; |
| |
| import org.apache.poi.ss.formula.eval.ErrorEval; |
| import org.apache.poi.ss.formula.eval.EvaluationException; |
| import org.apache.poi.ss.formula.eval.NumberEval; |
| import org.apache.poi.ss.formula.eval.OperandResolver; |
| import org.apache.poi.ss.formula.eval.ValueEval; |
| import org.apache.poi.ss.usermodel.DateUtil; |
| |
| /** |
| * Implementation of Excel functions Date parsing functions: |
| * Date - DAY, MONTH and YEAR |
| * Time - HOUR, MINUTE and SECOND |
| */ |
| public final class CalendarFieldFunction extends Fixed1ArgFunction { |
| public static final Function YEAR = new CalendarFieldFunction(Calendar.YEAR); |
| public static final Function MONTH = new CalendarFieldFunction(Calendar.MONTH); |
| public static final Function DAY = new CalendarFieldFunction(Calendar.DAY_OF_MONTH); |
| public static final Function HOUR = new CalendarFieldFunction(Calendar.HOUR_OF_DAY); |
| public static final Function MINUTE = new CalendarFieldFunction(Calendar.MINUTE); |
| public static final Function SECOND = new CalendarFieldFunction(Calendar.SECOND); |
| |
| private final int _dateFieldId; |
| |
| private CalendarFieldFunction(int dateFieldId) { |
| _dateFieldId = dateFieldId; |
| } |
| |
| public final ValueEval evaluate(int srcRowIndex, int srcColumnIndex, ValueEval arg0) { |
| double val; |
| try { |
| ValueEval ve = OperandResolver.getSingleValue(arg0, srcRowIndex, srcColumnIndex); |
| val = OperandResolver.coerceValueToDouble(ve); |
| } catch (EvaluationException e) { |
| return e.getErrorEval(); |
| } |
| if (val < 0) { |
| return ErrorEval.NUM_ERROR; |
| } |
| return new NumberEval(getCalField(val)); |
| } |
| |
| private int getCalField(double serialDate) { |
| // For some reason, a date of 0 in Excel gets shown |
| // as the non existant 1900-01-00 |
| if (((int)serialDate) == 0) { |
| switch (_dateFieldId) { |
| case Calendar.YEAR: return 1900; |
| case Calendar.MONTH: return 1; |
| case Calendar.DAY_OF_MONTH: return 0; |
| } |
| // They want time, that's normal |
| } |
| |
| // TODO Figure out if we're in 1900 or 1904 |
| // EXCEL functions round up nearly a half second (probably to prevent floating point |
| // rounding issues); use UTC here to prevent daylight saving issues for HOUR |
| Calendar c = DateUtil.getJavaCalendarUTC(serialDate + 0.4995 / DateUtil.SECONDS_PER_DAY, false); |
| int result = c.get(_dateFieldId); |
| |
| // Month is a special case due to C semantics |
| if (_dateFieldId == Calendar.MONTH) { |
| result++; |
| } |
| |
| return result; |
| } |
| } |