mirror of
https://github.com/unicode-org/icu.git
synced 2025-04-20 20:19:32 +00:00
ICU-6303 initial checkin
X-SVN-Rev: 24015
This commit is contained in:
parent
342953342c
commit
9d6234899d
4 changed files with 343 additions and 0 deletions
49
icu4j/src/com/ibm/icu/dev/test/format/TimeUnitTest.java
Normal file
49
icu4j/src/com/ibm/icu/dev/test/format/TimeUnitTest.java
Normal file
|
@ -0,0 +1,49 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2008, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package com.ibm.icu.dev.test.format;
|
||||
|
||||
import java.text.ParseException;
|
||||
|
||||
import com.ibm.icu.dev.test.TestFmwk;
|
||||
import com.ibm.icu.text.TimeUnitFormat;
|
||||
import com.ibm.icu.util.TimeUnit;
|
||||
import com.ibm.icu.util.TimeUnitAmount;
|
||||
import com.ibm.icu.util.ULocale;
|
||||
|
||||
/**
|
||||
* @author markdavis
|
||||
*
|
||||
*/
|
||||
public class TimeUnitTest extends TestFmwk {
|
||||
public static void main(String[] args) throws Exception{
|
||||
new TimeUnitTest().run(args);
|
||||
}
|
||||
|
||||
public void TestBasic() {
|
||||
TimeUnitFormat format = new TimeUnitFormat();
|
||||
format.setLocale(ULocale.ENGLISH);
|
||||
final TimeUnit[] values = TimeUnit.values();
|
||||
for (int j = 0; j < values.length; ++j) {
|
||||
final TimeUnit timeUnit = values[j];
|
||||
double[] tests = {0, 0.5, 1, 1.5, 2, 5, 101.35};
|
||||
for (int i = 0; i < tests.length; ++i) {
|
||||
TimeUnitAmount source = new TimeUnitAmount(tests[i], timeUnit);
|
||||
String formatted = format.format(source);
|
||||
logln(tests[i] + " => " + formatted);
|
||||
try {
|
||||
TimeUnitAmount result = (TimeUnitAmount) format.parseObject(formatted);
|
||||
if (result == null || !source.equals(result)) {
|
||||
errln("No round trip: " + source + " => " + formatted + " => " + result);
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
errln(e.getMessage());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
180
icu4j/src/com/ibm/icu/text/TimeUnitFormat.java
Normal file
180
icu4j/src/com/ibm/icu/text/TimeUnitFormat.java
Normal file
|
@ -0,0 +1,180 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2008, Google, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package com.ibm.icu.text;
|
||||
|
||||
import java.text.FieldPosition;
|
||||
import java.text.ParsePosition;
|
||||
import java.util.HashMap;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import com.ibm.icu.util.TimeUnit;
|
||||
import com.ibm.icu.util.TimeUnitAmount;
|
||||
import com.ibm.icu.util.ULocale;
|
||||
|
||||
/**
|
||||
* Format or parse a TimeUnitAmount, using plural rules for the units where available.
|
||||
* @see TimeUnitAmount
|
||||
* @see TimeUnitFormat
|
||||
* @author markdavis
|
||||
* @draft ICU 4.0
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
*/
|
||||
public class TimeUnitFormat extends MeasureFormat {
|
||||
|
||||
private NumberFormat format;
|
||||
private ULocale locale;
|
||||
private transient Map timeUnitToCountToPatterns = new HashMap();
|
||||
private transient PluralRules pluralRules;
|
||||
private transient boolean needToBuild = true;
|
||||
|
||||
/**
|
||||
* Create empty format. Use setLocale and/or setFormat to modify.
|
||||
* @draft ICU 4.0
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
*/
|
||||
public TimeUnitFormat() {}
|
||||
|
||||
/**
|
||||
* Set the locale used for formatting or parsing.
|
||||
* @return this, for chaining.
|
||||
* @draft ICU 4.0
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
*/
|
||||
public TimeUnitFormat setLocale(ULocale locale) {
|
||||
this.locale = locale;
|
||||
needToBuild = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the locale used for formatting or parsing.
|
||||
* @return this, for chaining.
|
||||
* @draft ICU 4.0
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
*/
|
||||
public TimeUnitFormat setLocale(Locale locale) {
|
||||
this.locale = ULocale.forLocale(locale);
|
||||
needToBuild = true;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the format used for formatting or parsing. If null or not available, use the getNumberInstance(locale).
|
||||
* @return this, for chaining.
|
||||
* @draft ICU 4.0
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
*/
|
||||
public TimeUnitFormat setNumberFormat(NumberFormat format) {
|
||||
this.format = format;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Format a TimeUnitAmount.
|
||||
* @see java.text.Format#format(java.lang.Object, java.lang.StringBuffer, java.text.FieldPosition)
|
||||
*/
|
||||
public StringBuffer format(Object obj, StringBuffer toAppendTo,
|
||||
FieldPosition pos) {
|
||||
if (needToBuild) setup();
|
||||
TimeUnitAmount amount = (TimeUnitAmount) obj;
|
||||
Map countToPattern = (Map) timeUnitToCountToPatterns.get(amount.getTimeUnit());
|
||||
double number = amount.getNumber().doubleValue();
|
||||
String count = pluralRules.select(number);
|
||||
MessageFormat pattern = (MessageFormat) countToPattern.get(count);
|
||||
return pattern.format(new Object[]{amount.getNumber()}, toAppendTo, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a TimeUnitAmount.
|
||||
*/
|
||||
public Object parseObject(String source, ParsePosition pos) {
|
||||
if (needToBuild) setup();
|
||||
Number resultNumber = null;
|
||||
TimeUnit resultTimeUnit = null;
|
||||
int oldPos = pos.getIndex();
|
||||
int newPos = -1;
|
||||
// we don't worry too much about speed on parsing, but this can be optimized later if needed.
|
||||
for (Iterator it = timeUnitToCountToPatterns.keySet().iterator(); it.hasNext();) {
|
||||
TimeUnit timeUnit = (TimeUnit) it.next();
|
||||
Map countToPattern = (Map) timeUnitToCountToPatterns.get(timeUnit);
|
||||
for (Iterator it2 = countToPattern.keySet().iterator(); it2.hasNext();) {
|
||||
String count = (String) it2.next();
|
||||
MessageFormat pattern = (MessageFormat) countToPattern.get(count);
|
||||
pos.setIndex(oldPos);
|
||||
// see if we can parse
|
||||
Object parsed = pattern.parseObject(source, pos);
|
||||
if (parsed == null) {
|
||||
continue;
|
||||
}
|
||||
// check to make sure that the timeUnit is consistent
|
||||
Number temp = (Number)((Object[])parsed)[0];
|
||||
String select = pluralRules.select(temp.doubleValue());
|
||||
if (!count.equals(select)) {
|
||||
continue;
|
||||
}
|
||||
resultNumber = temp;
|
||||
resultTimeUnit = timeUnit;
|
||||
newPos = pos.getIndex();
|
||||
}
|
||||
}
|
||||
if (resultNumber == null) {
|
||||
return null;
|
||||
}
|
||||
pos.setIndex(newPos);
|
||||
pos.setErrorIndex(-1);
|
||||
return new TimeUnitAmount(resultNumber, resultTimeUnit);
|
||||
}
|
||||
|
||||
// *********************** Stubbed until we get CLDR data *******************************
|
||||
|
||||
// just do English for now
|
||||
private static Object[][] data = {
|
||||
{TimeUnit.SECOND, "one", "{0} second", "other", "{0} seconds"},
|
||||
{TimeUnit.MINUTE, "one", "{0} minute", "other", "{0} minutes"},
|
||||
{TimeUnit.HOUR, "one", "{0} hour", "other", "{0} hours"},
|
||||
{TimeUnit.DAY, "one", "{0} day", "other", "{0} days"},
|
||||
{TimeUnit.WEEK, "one", "{0} week", "other", "{0} weeks"},
|
||||
{TimeUnit.MONTH, "one", "{0} month", "other", "{0} months"},
|
||||
{TimeUnit.YEAR, "one", "{0} year", "other", "{0} years"}
|
||||
};
|
||||
|
||||
// Initally, we are storing all of these as MessageFormats.
|
||||
// I think it might actually be simpler to make them Decimal Formats later.
|
||||
private void setup() {
|
||||
if (locale == null) {
|
||||
if (format != null) {
|
||||
locale = format.getLocale(null);
|
||||
}
|
||||
if (locale == null) {
|
||||
locale = ULocale.getDefault();
|
||||
}
|
||||
}
|
||||
if (format == null) {
|
||||
format = NumberFormat.getNumberInstance(locale);
|
||||
}
|
||||
pluralRules = PluralRules.forLocale(locale);
|
||||
for (int i = 0; i < data.length; ++i) {
|
||||
Map temp = new TreeMap();
|
||||
for (int j = 1; j < data[i].length; j += 2) {
|
||||
final MessageFormat messageFormat = new MessageFormat((String)data[i][j+1], locale);
|
||||
if (format != null) {
|
||||
messageFormat.setFormatByArgumentIndex(0, format);
|
||||
}
|
||||
temp.put(data[i][j], messageFormat);
|
||||
}
|
||||
timeUnitToCountToPatterns.put((TimeUnit)data[i][0], temp);
|
||||
}
|
||||
// it's an internal error if we get a count that we can't handle
|
||||
// so check here to make sure that the rules are all covered
|
||||
// TODO
|
||||
needToBuild = false;
|
||||
}
|
||||
|
||||
}
|
66
icu4j/src/com/ibm/icu/util/TimeUnit.java
Normal file
66
icu4j/src/com/ibm/icu/util/TimeUnit.java
Normal file
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2008, Google, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package com.ibm.icu.util;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import com.ibm.icu.text.TimeUnitFormat;
|
||||
|
||||
/**
|
||||
* Measurement unit for time units.
|
||||
* @see TimeUnitAmount
|
||||
* @see TimeUnit
|
||||
* @author markdavis
|
||||
* @draft ICU 4.0
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
*/
|
||||
public class TimeUnit extends MeasureUnit {
|
||||
/**
|
||||
* Supports selected time duration units
|
||||
*/
|
||||
private String name;
|
||||
|
||||
private static TimeUnit[] values = new TimeUnit[7]; // adjust count if new items are added
|
||||
private static int valueCount = 0;
|
||||
|
||||
/**
|
||||
* Constant value for supported time unit.
|
||||
* @draft ICU 4.0
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
*/
|
||||
public static TimeUnit
|
||||
SECOND = new TimeUnit("SECOND"),
|
||||
MINUTE = new TimeUnit("MINUTE"),
|
||||
HOUR = new TimeUnit("HOUR"),
|
||||
DAY = new TimeUnit("DAY"),
|
||||
WEEK = new TimeUnit("WEEK"),
|
||||
MONTH = new TimeUnit("MONTH"),
|
||||
YEAR = new TimeUnit("YEAR");
|
||||
|
||||
private TimeUnit(String name) {
|
||||
this.name = name;
|
||||
values[valueCount++] = this; // store in values array
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the available values
|
||||
* @draft ICU 4.0
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
*/
|
||||
public static TimeUnit[] values() {
|
||||
return values.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
* A string representation for debugging.
|
||||
* @draft ICU 4.0
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
*/
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
48
icu4j/src/com/ibm/icu/util/TimeUnitAmount.java
Normal file
48
icu4j/src/com/ibm/icu/util/TimeUnitAmount.java
Normal file
|
@ -0,0 +1,48 @@
|
|||
/*
|
||||
*******************************************************************************
|
||||
* Copyright (C) 2008, Google, International Business Machines Corporation and *
|
||||
* others. All Rights Reserved. *
|
||||
*******************************************************************************
|
||||
*/
|
||||
package com.ibm.icu.util;
|
||||
|
||||
import com.ibm.icu.text.TimeUnitFormat;
|
||||
|
||||
/**
|
||||
* Express a duration as a time unit and number. Patterned after Currency.
|
||||
* <p>Immutable.
|
||||
* @see TimeUnitAmount
|
||||
* @see TimeUnitFormat
|
||||
* @author markdavis
|
||||
* @draft ICU 4.0
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
*/
|
||||
public class TimeUnitAmount extends Measure {
|
||||
|
||||
/**
|
||||
* Create from a number and unit.
|
||||
* @draft ICU 4.0
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
*/
|
||||
public TimeUnitAmount(Number number, TimeUnit unit) {
|
||||
super(number, unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Create from a number and unit.
|
||||
* @draft ICU 4.0
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
*/
|
||||
public TimeUnitAmount(double number, TimeUnit unit) {
|
||||
super(new Double(number), unit);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the unit (convenience to avoid cast).
|
||||
* @draft ICU 4.0
|
||||
* @provisional This API might change or be removed in a future release.
|
||||
*/
|
||||
public TimeUnit getTimeUnit() {
|
||||
return (TimeUnit) getUnit();
|
||||
}
|
||||
}
|
Loading…
Add table
Reference in a new issue