123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215 |
- /* ====================================================================
- 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.format;
-
- import java.util.ArrayList;
- import java.util.Formatter;
- import java.util.List;
- import java.util.ListIterator;
- import java.util.regex.Matcher;
- import java.util.regex.Pattern;
-
- /**
- * This class implements printing out an elapsed time format.
- *
- * @author Ken Arnold, Industrious Media LLC
- */
- public class CellElapsedFormatter extends CellFormatter {
- private final List<TimeSpec> specs;
- private TimeSpec topmost;
- private final String printfFmt;
-
- private static final Pattern PERCENTS = Pattern.compile("%");
-
- private static final double HOUR__FACTOR = 1.0 / 24.0;
- private static final double MIN__FACTOR = HOUR__FACTOR / 60.0;
- private static final double SEC__FACTOR = MIN__FACTOR / 60.0;
-
- private static class TimeSpec {
- final char type;
- final int pos;
- final int len;
- final double factor;
- double modBy;
-
- public TimeSpec(char type, int pos, int len, double factor) {
- this.type = type;
- this.pos = pos;
- this.len = len;
- this.factor = factor;
- modBy = 0;
- }
-
- public long valueFor(double elapsed) {
- double val;
- if (modBy == 0)
- val = elapsed / factor;
- else
- val = elapsed / factor % modBy;
- if (type == '0')
- return Math.round(val);
- else
- return (long) val;
- }
- }
-
- private class ElapsedPartHandler implements CellFormatPart.PartHandler {
- // This is the one class that's directly using printf, so it can't use
- // the default handling for quoted strings and special characters. The
- // only special character for this is '%', so we have to handle all the
- // quoting in this method ourselves.
-
- public String handlePart(Matcher m, String part, CellFormatType type,
- StringBuffer desc) {
-
- int pos = desc.length();
- char firstCh = part.charAt(0);
- switch (firstCh) {
- case '[':
- if (part.length() < 3)
- break;
- if (topmost != null)
- throw new IllegalArgumentException(
- "Duplicate '[' times in format");
- part = part.toLowerCase();
- int specLen = part.length() - 2;
- topmost = assignSpec(part.charAt(1), pos, specLen);
- return part.substring(1, 1 + specLen);
-
- case 'h':
- case 'm':
- case 's':
- case '0':
- part = part.toLowerCase();
- assignSpec(part.charAt(0), pos, part.length());
- return part;
-
- case '\n':
- return "%n";
-
- case '\"':
- part = part.substring(1, part.length() - 1);
- break;
-
- case '\\':
- part = part.substring(1);
- break;
-
- case '*':
- if (part.length() > 1)
- part = CellFormatPart.expandChar(part);
- break;
-
- // An escape we can let it handle because it can't have a '%'
- case '_':
- return null;
- }
- // Replace ever "%" with a "%%" so we can use printf
- return PERCENTS.matcher(part).replaceAll("%%");
- }
- }
-
- /**
- * Creates a elapsed time formatter.
- *
- * @param pattern The pattern to parse.
- */
- public CellElapsedFormatter(String pattern) {
- super(pattern);
-
- specs = new ArrayList<TimeSpec>();
-
- StringBuffer desc = CellFormatPart.parseFormat(pattern,
- CellFormatType.ELAPSED, new ElapsedPartHandler());
-
- ListIterator<TimeSpec> it = specs.listIterator(specs.size());
- while (it.hasPrevious()) {
- TimeSpec spec = it.previous();
- desc.replace(spec.pos, spec.pos + spec.len, "%0" + spec.len + "d");
- if (spec.type != topmost.type) {
- spec.modBy = modFor(spec.type, spec.len);
- }
- }
-
- printfFmt = desc.toString();
- }
-
- private TimeSpec assignSpec(char type, int pos, int len) {
- TimeSpec spec = new TimeSpec(type, pos, len, factorFor(type, len));
- specs.add(spec);
- return spec;
- }
-
- private static double factorFor(char type, int len) {
- switch (type) {
- case 'h':
- return HOUR__FACTOR;
- case 'm':
- return MIN__FACTOR;
- case 's':
- return SEC__FACTOR;
- case '0':
- return SEC__FACTOR / Math.pow(10, len);
- default:
- throw new IllegalArgumentException(
- "Uknown elapsed time spec: " + type);
- }
- }
-
- private static double modFor(char type, int len) {
- switch (type) {
- case 'h':
- return 24;
- case 'm':
- return 60;
- case 's':
- return 60;
- case '0':
- return Math.pow(10, len);
- default:
- throw new IllegalArgumentException(
- "Uknown elapsed time spec: " + type);
- }
- }
-
- /** {@inheritDoc} */
- public void formatValue(StringBuffer toAppendTo, Object value) {
- double elapsed = ((Number) value).doubleValue();
-
- if (elapsed < 0) {
- toAppendTo.append('-');
- elapsed = -elapsed;
- }
-
- Object[] parts = new Long[specs.size()];
- for (int i = 0; i < specs.size(); i++) {
- parts[i] = specs.get(i).valueFor(elapsed);
- }
-
- Formatter formatter = new Formatter(toAppendTo);
- formatter.format(printfFmt, parts);
- }
-
- /**
- * {@inheritDoc}
- * <p/>
- * For a date, this is <tt>"mm/d/y"</tt>.
- */
- public void simpleValue(StringBuffer toAppendTo, Object value) {
- formatValue(toAppendTo, value);
- }
- }
|