📄 format.java
字号:
/*
// $Id: //open/mondrian/src/main/mondrian/util/Format.java#14 $
// This software is subject to the terms of the Common Public License
// Agreement, available at the following URL:
// http://www.opensource.org/licenses/cpl.html.
// Copyright (C) 2000-2005 Kana Software, Inc. and others.
// All Rights Reserved.
// You must accept the terms of that agreement to use this software.
//
// jhyde, 2 November, 2000
*/
package mondrian.util;
import mondrian.olap.Util;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.math.BigDecimal;
import java.math.BigInteger;
import java.util.*;
/**
* <code>Format</code> formats numbers, strings and dates according to the
* same specification as Visual Basic's
* <code>format()</code> function. This function is described in more detail
* <a href="http://www.apostate.com/programming/vb-format.html">here</a>. We
* have made the following enhancements to this specification:<ul>
*
* <li>if the international currency symbol (¤) occurs in a format
* string, it is translated to the locale's currency symbol.</li>
*
* <li>the format string "Currency" is translated to the locale's currency
* format string. Negative currency values appear in parentheses.</li>
*
* <li>the string "USD" (abbreviation for U.S. Dollars) may occur in a format
* string.</li>
*
* </ul>
*
* <p>One format object can be used to format multiple values, thereby
* amortizing the time required to parse the format string. Example:</p>
*
* <pre><code>
* double[] values;
* Format format = new Format("##,##0.###;(##,##0.###);;Nil");
* for (int i = 0; i < values.length; i++) {
* System.out.println("Value #" + i + " is " + format.format(values[i]));
* }
* </code></pre>
*
* <p>Still to be implemented:<ul>
*
* <li>String formatting (upper-case, lower-case, fill from left/right)</li>
*
* <li>Use client's timezone for printing times.</li>
*
* </ul>
**/
public class Format {
private String formatString;
private BasicFormat format;
private FormatLocale locale;
/**
* Maps (formatString, locale) pairs to Format objects.
*/
private static Map cache = new HashMap();
static final char[] digits = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
};
static final char thousandSeparator_en = ',';
static final char decimalPlaceholder_en = '.';
static final String dateSeparator_en = "/";
static final String timeSeparator_en = ":";
static final String currencySymbol_en = "$";
static final String currencyFormat_en = "$#,##0.00";
static final String[] daysOfWeekShort_en = {
"Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"
};
static final String[] daysOfWeekLong_en = {
"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday",
"Saturday"
};
static final String[] monthsShort_en = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun",
"Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
};
static final String[] monthsLong_en = {
"January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
};
static final char intlCurrencySymbol = '\u08a4';
/**
* Maps strings representing locales (for example, "en_US_Boston",
* "en_US", "en", or "" for the default) to a {@link FormatLocale}.
*/
static final Map mapLocaleToFormatLocale = new HashMap();
/**
* Locale for US English, also the default for English and for all
* locales.
*/
static final FormatLocale locale_US = createLocale(
'\0', '\0', null, null, null, null, null, null, null, null,
Locale.US);
private static LocaleFormatFactory localeFormatFactory;
public static void main(String[] args)
{
PrintWriter pw = new PrintWriter(
new java.io.OutputStreamWriter(System.out));
/*
String[] timeZones = TimeZone.getAvailableIDs();
for (int i = 0; i < timeZones.length; i++) {
TimeZone tz = TimeZone.getTimeZone(timeZones[i]);
pw.println(
"Id=" + tz.getID() +
", offset=" + tz.getRawOffset() / (60 * 60 * 1000) +
", daylight=" + tz.useDaylightTime());
}
pw.flush();
*/
String[] numberFormats = {
// format +6 -6 0 .6 null
// ===================== =========== ============ =========== =========== =========
"", "6", "-6", "0", "0.6", "",
"0", "6", "-6", "0", "1", "",
"0.00", "6.00", "-6.00", "0.00", "0.60", "",
"#,##0", "6", "-6", "0", "1", "",
"#,##0.00;;;Nil", "6.00", "-6.00", "0.00", "0.60", "Nil",
"$#,##0;($#,##0)", "$6", "($6)", "$0", "$1", "",
"$#,##0.00;($#,##0.00)", "$6.00", "($6.00)", "$0.00", "$0.60", "",
"0%", "600%", "-600%", "0%", "60%", "",
"0.00%", "600.00%", "-600.00%", "0.00%", "60.00%", "",
"0.00E+00", "6.00E+00", "-6.00E+00", "0.00E+00", "6.00E-01", "",
"0.00E-00", "6.00E00", "-6.00E00", "0.00E00", "6.00E-01", "",
"$#,##0;;\\Z\\e\\r\\o", "$6", "$-6", "Zero", "$1", "",
"#,##0.0 USD", "6.0 USD", "-6.0 USD", "0.0 USD", "0.6 USD", "",
"General Number", "6", "-6", "0", "0.6", "",
"Currency", "$6.00", "($6.00)", "$0.00", "$0.60", "",
"Fixed", "6", "-6", "0", "1", "",
"Standard", "6", "-6", "0", "1", "",
"Percent", "600%", "-600%", "0%", "60%", "",
"Scientific", "6.00e+00", "-6.00e+00", "0.00e+00", "6.00e-01", "",
"True/False", "True", "True", "False", "True", "False",
"On/Off", "On", "On", "Off", "On", "Off",
"Yes/No", "Yes", "Yes", "No", "Yes", "No",
};
String[] dateFormats = {
"dd-mmm-yy",
"h:mm:ss AM/PM",
"hh:mm",
"Long Date",
"Medium Date",
"Short Date",
"Long Time",
"Medium Time",
"Short Time",
};
FormatLocale localeFra = createLocale(
'.', // thousandSeparator = ',' in en
',', // decimalPlaceholder = '.' in en
"-", // dateSeparator = "/" in en
"#", // timeSeparator = ":" in en
"FF", // currencySymbol = "$" in en
"#.##0-00FF", // currencyFormat = "$#,##0.##" in en
new String[] {
"Dim", "Lun", "Mar", "Mer", "Jeu", "Ven", "Sam"},
new String[] {
"Dimanche", "Lundi", "Mardi", "Mercredi", "Jeudi", "Vendredi",
"Samedi"},
new String[] {
"Jan", "Fev", "Mar", "Avr", "Mai", "Jui", "Jui", "Aou", "Sep",
"Oct", "Nov", "Dec"},
new String[] {
"Janvier", "Fevrier", "Mars", "Avril", "Mai", "Juin",
"Juillet", "Aout", "Septembre", "Octobre", "Novembre",
"Decembre"},
Locale.FRENCH);
Object[] numbers = {
new Double(6), new Double(-6), new Double(0), new Double(.6),
null,
new Long(6), new Long(-6), new Long(0)};
Double d = new Double(3141592.653589793);
java.util.Calendar calendar = java.util.Calendar.getInstance();
calendar.set(1969, 3, 29, 20, 9, 6); // note that month #3 == April
java.util.Date date = calendar.getTime();
calendar.set(2010, 8, 7, 6, 5, 4); // 06:05:04 am, 7th sep 2010
java.util.Date date2 = calendar.getTime();
pw.println("Start test of mondrian.util.Format.");
// testFormat(pw, null, date2, "mm/##/yy", "09/##/10");
// testFormat(pw, null, new Double(123.45), "E+", "1E2");
// testFormat(pw, null, new Long(0), "0.00E+00", "0.00E+00");
// testFormat(pw, null, new Double(0), "0.00E+00", "0.00E+00");
// testFormat(pw, null, new Double(0), "0.00", "0.00");
// testFormat(pw, new Double(-5.0), "#,##0.00;;;Nil", "1");
// testFormat(pw, date, "m", null);
// testFormat(pw, date, "", null);
// testFormat(pw, null, new Double(0), "0%", "0%");
// testFormat(pw, null, new Double(1.2), "" + intlCurrencySymbol + "#", "$1");
// testFormat(pw, localeFra, d, "Currency", null);
pw.println();
pw.println("Exhaustive tests on various numbers.");
for (int i = 0; i < numberFormats.length / 6; i++) {
String format = numberFormats[i * 6];
for (int j = 0; j < numbers.length; j++) {
int x = (j < 5 ? j + 1 : j - 4);
String result = numberFormats[i * 6 + x];
testFormat(pw, null, numbers[j], format, result);
}
}
pw.println();
pw.println("Numbers in French.");
for (int i = 0; i < numberFormats.length / 6; i++) {
String format = numberFormats[i * 6];
testFormat(pw, localeFra, d, format, null);
}
pw.println();
pw.println("Some tricky numbers.");
testFormat(pw, null, new Double(40.385), "##0.0#", "40.38");
testFormat(pw, null, new Double(40.386), "##0.0#", "40.39");
testFormat(pw, null, new Double(40.384), "##0.0#", "40.38");
testFormat(pw, null, new Double(40.385), "##0.#", "40.4");
testFormat(pw, null, new Double(40.38), "##0.0#", "40.38");
testFormat(pw, null, new Double(-40.38), "##0.0#", "-40.38");
testFormat(pw, null, new Double(0.040385), "#0.###", "0.04");
testFormat(pw, null, new Double(0.040385), "#0.000", "0.040");
testFormat(pw, null, new Double(0.040385), "#0.####", "0.0404");
testFormat(pw, null, new Double(0.040385), "00.####", "00.0404");
testFormat(pw, null, new Double(0.040385), ".00#", ".04");
testFormat(pw, null, new Double(0.040785), ".00#", ".041");
testFormat(pw, null, new Double(99.9999), "##.####", "99.9999");
testFormat(pw, null, new Double(99.9999), "##.###", "100");
testFormat(pw, null, new Double(99.9999), "##.00#", "100.00");
testFormat(pw, null, new Double(.00099), "#.00", ".00");
testFormat(pw, null, new Double(.00099), "#.00#", ".001");
testFormat(pw, null, new Double(12.34), "#.000##", "12.340");
// "Standard" must use thousands separator, and round
testFormat(pw, null, new Double(1234567.89), "Standard", "1,234,568");
// must use correct alternate for 0
testFormat(pw, null, new Double(0), "$#,##0;;\\Z\\e\\r\\o", "Zero");
// an existing bug
pw.println(
"The following case illustrates an outstanding bug. " +
"Should be able to override '.' to '-', " +
"so result should be '3.141.592-65 FF'.");
testFormat(pw, localeFra, d, "#.##0-00 FF", null);
pw.println();
pw.println("Test several date formats on one date.");
for (int i = 0; i < dateFormats.length; i++) {
String format = dateFormats[i];
testFormat(pw, null, date, format, null);
}
pw.println();
pw.println("Dates in French.");
for (int i = 0; i < dateFormats.length; i++) {
String format = dateFormats[i];
testFormat(pw, localeFra, date, format, null);
}
pw.println();
pw.println("Test all possible tokens.");
for (int i = 0; i < tokens.length; i++) {
Token fe = tokens[i];
Object o;
if (fe.isNumeric()) {
o = d;
} else if (fe.isDate()) {
o = date;
} else if (fe.isString()) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -