mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-22 16:14:10 -08:00
Adds formatting classes from the java.text package
This commit is contained in:
parent
0cd1ddedc5
commit
2e97872496
|
@ -0,0 +1,35 @@
|
|||
/*
|
||||
* 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.teavm.classlib.java.text;
|
||||
|
||||
public class Annotation {
|
||||
private Object value;
|
||||
|
||||
public Annotation(Object attribute) {
|
||||
value = attribute;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getName() + "[value=" + value + ']';
|
||||
}
|
||||
}
|
|
@ -0,0 +1,144 @@
|
|||
/*
|
||||
* 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.teavm.classlib.java.text;
|
||||
|
||||
import org.teavm.classlib.java.io.TSerializable;
|
||||
import org.teavm.classlib.java.util.TMap;
|
||||
import org.teavm.classlib.java.util.TSet;
|
||||
|
||||
public interface AttributedCharacterIterator extends CharacterIterator {
|
||||
|
||||
public static class Attribute implements TSerializable {
|
||||
public static final Attribute INPUT_METHOD_SEGMENT = new Attribute(
|
||||
"input_method_segment");
|
||||
|
||||
public static final Attribute LANGUAGE = new Attribute("language");
|
||||
|
||||
public static final Attribute READING = new Attribute("reading");
|
||||
|
||||
private String name;
|
||||
|
||||
protected Attribute(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean equals(Object object) {
|
||||
return this == object;
|
||||
}
|
||||
|
||||
protected String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int hashCode() {
|
||||
return super.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getName() + '(' + getName() + ')';
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a set of attributes present in the {@code
|
||||
* AttributedCharacterIterator}. An empty set is returned if no attributes
|
||||
* were defined.
|
||||
*
|
||||
* @return a set of attribute keys; may be empty.
|
||||
*/
|
||||
public TSet<Attribute> getAllAttributeKeys();
|
||||
|
||||
/**
|
||||
* Returns the value stored in the attribute for the current character. If
|
||||
* the attribute was not defined then {@code null} is returned.
|
||||
*
|
||||
* @param attribute the attribute for which the value should be returned.
|
||||
* @return the value of the requested attribute for the current character or
|
||||
* {@code null} if it was not defined.
|
||||
*/
|
||||
public Object getAttribute(Attribute attribute);
|
||||
|
||||
/**
|
||||
* Returns a map of all attributes of the current character. If no
|
||||
* attributes were defined for the current character then an empty map is
|
||||
* returned.
|
||||
*
|
||||
* @return a map of all attributes for the current character or an empty
|
||||
* map.
|
||||
*/
|
||||
public TMap<Attribute, Object> getAttributes();
|
||||
|
||||
/**
|
||||
* Returns the index of the last character in the run having the same
|
||||
* attributes as the current character.
|
||||
*
|
||||
* @return the index of the last character of the current run.
|
||||
*/
|
||||
public int getRunLimit();
|
||||
|
||||
/**
|
||||
* Returns the index of the last character in the run that has the same
|
||||
* attribute value for the given attribute as the current character.
|
||||
*
|
||||
* @param attribute
|
||||
* the attribute which the run is based on.
|
||||
* @return the index of the last character of the current run.
|
||||
*/
|
||||
public int getRunLimit(Attribute attribute);
|
||||
|
||||
/**
|
||||
* Returns the index of the last character in the run that has the same
|
||||
* attribute values for the attributes in the set as the current character.
|
||||
*
|
||||
* @param attributes
|
||||
* the set of attributes which the run is based on.
|
||||
* @return the index of the last character of the current run.
|
||||
*/
|
||||
public int getRunLimit(TSet<? extends Attribute> attributes);
|
||||
|
||||
/**
|
||||
* Returns the index of the first character in the run that has the same
|
||||
* attributes as the current character.
|
||||
*
|
||||
* @return the index of the last character of the current run.
|
||||
*/
|
||||
public int getRunStart();
|
||||
|
||||
/**
|
||||
* Returns the index of the first character in the run that has the same
|
||||
* attribute value for the given attribute as the current character.
|
||||
*
|
||||
* @param attribute
|
||||
* the attribute which the run is based on.
|
||||
* @return the index of the last character of the current run.
|
||||
*/
|
||||
public int getRunStart(Attribute attribute);
|
||||
|
||||
/**
|
||||
* Returns the index of the first character in the run that has the same
|
||||
* attribute values for the attributes in the set as the current character.
|
||||
*
|
||||
* @param attributes
|
||||
* the set of attributes which the run is based on.
|
||||
* @return the index of the last character of the current run.
|
||||
*/
|
||||
public int getRunStart(TSet<? extends Attribute> attributes);
|
||||
}
|
|
@ -0,0 +1,630 @@
|
|||
/*
|
||||
* 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.teavm.classlib.java.text;
|
||||
|
||||
import org.teavm.classlib.java.text.AttributedCharacterIterator.Attribute;
|
||||
import org.teavm.classlib.java.util.*;
|
||||
|
||||
public class AttributedString {
|
||||
|
||||
String text;
|
||||
|
||||
TMap<AttributedCharacterIterator.Attribute, TList<Range>> attributeMap;
|
||||
|
||||
static class Range {
|
||||
int start;
|
||||
|
||||
int end;
|
||||
|
||||
Object value;
|
||||
|
||||
Range(int s, int e, Object v) {
|
||||
start = s;
|
||||
end = e;
|
||||
value = v;
|
||||
}
|
||||
}
|
||||
|
||||
static class AttributedIterator implements AttributedCharacterIterator {
|
||||
|
||||
private int begin, end, offset;
|
||||
|
||||
private AttributedString attrString;
|
||||
|
||||
private THashSet<Attribute> attributesAllowed;
|
||||
|
||||
AttributedIterator(AttributedString attrString) {
|
||||
this.attrString = attrString;
|
||||
begin = 0;
|
||||
end = attrString.text.length();
|
||||
offset = 0;
|
||||
}
|
||||
|
||||
AttributedIterator(AttributedString attrString, AttributedCharacterIterator.Attribute[] attributes, int begin,
|
||||
int end) {
|
||||
if (begin < 0 || end > attrString.text.length() || begin > end) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
this.begin = begin;
|
||||
this.end = end;
|
||||
offset = begin;
|
||||
this.attrString = attrString;
|
||||
if (attributes != null) {
|
||||
THashSet<Attribute> set = new THashSet<>((attributes.length * 4 / 3) + 1);
|
||||
for (int i = attributes.length; --i >= 0;) {
|
||||
set.add(attributes[i]);
|
||||
}
|
||||
attributesAllowed = set;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
public Object clone() {
|
||||
try {
|
||||
AttributedIterator clone = (AttributedIterator) super.clone();
|
||||
if (attributesAllowed != null) {
|
||||
clone.attributesAllowed = (THashSet<Attribute>) attributesAllowed.clone();
|
||||
}
|
||||
return clone;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public char current() {
|
||||
if (offset == end) {
|
||||
return DONE;
|
||||
}
|
||||
return attrString.text.charAt(offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public char first() {
|
||||
if (begin == end) {
|
||||
return DONE;
|
||||
}
|
||||
offset = begin;
|
||||
return attrString.text.charAt(offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBeginIndex() {
|
||||
return begin;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getEndIndex() {
|
||||
return end;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIndex() {
|
||||
return offset;
|
||||
}
|
||||
|
||||
private boolean inRange(Range range) {
|
||||
if (!(range.value instanceof Annotation)) {
|
||||
return true;
|
||||
}
|
||||
return range.start >= begin && range.start < end && range.end > begin && range.end <= end;
|
||||
}
|
||||
|
||||
private boolean inRange(TList<Range> ranges) {
|
||||
TIterator<Range> it = ranges.iterator();
|
||||
while (it.hasNext()) {
|
||||
Range range = it.next();
|
||||
if (range.start >= begin && range.start < end) {
|
||||
return !(range.value instanceof Annotation) || (range.end > begin && range.end <= end);
|
||||
} else if (range.end > begin && range.end <= end) {
|
||||
return !(range.value instanceof Annotation) || (range.start >= begin && range.start < end);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public TSet<AttributedIterator.Attribute> getAllAttributeKeys() {
|
||||
if (begin == 0 && end == attrString.text.length() && attributesAllowed == null) {
|
||||
return attrString.attributeMap.keySet();
|
||||
}
|
||||
|
||||
TSet<AttributedIterator.Attribute> result = new THashSet<>((attrString.attributeMap.size() * 4 / 3) + 1);
|
||||
TIterator<TMap.Entry<Attribute, TList<Range>>> it = attrString.attributeMap.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
TMap.Entry<Attribute, TList<Range>> entry = it.next();
|
||||
if (attributesAllowed == null || attributesAllowed.contains(entry.getKey())) {
|
||||
TList<Range> ranges = entry.getValue();
|
||||
if (inRange(ranges)) {
|
||||
result.add(entry.getKey());
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private Object currentValue(TList<Range> ranges) {
|
||||
TIterator<Range> it = ranges.iterator();
|
||||
while (it.hasNext()) {
|
||||
Range range = it.next();
|
||||
if (offset >= range.start && offset < range.end) {
|
||||
return inRange(range) ? range.value : null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object getAttribute(AttributedCharacterIterator.Attribute attribute) {
|
||||
if (attributesAllowed != null && !attributesAllowed.contains(attribute)) {
|
||||
return null;
|
||||
}
|
||||
TArrayList<Range> ranges = (TArrayList<Range>) attrString.attributeMap.get(attribute);
|
||||
if (ranges == null) {
|
||||
return null;
|
||||
}
|
||||
return currentValue(ranges);
|
||||
}
|
||||
|
||||
@Override
|
||||
public TMap<Attribute, Object> getAttributes() {
|
||||
TMap<Attribute, Object> result = new THashMap<>((attrString.attributeMap.size() * 4 / 3) + 1);
|
||||
TIterator<TMap.Entry<Attribute, TList<Range>>> it = attrString.attributeMap.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
TMap.Entry<Attribute, TList<Range>> entry = it.next();
|
||||
if (attributesAllowed == null || attributesAllowed.contains(entry.getKey())) {
|
||||
Object value = currentValue(entry.getValue());
|
||||
if (value != null) {
|
||||
result.put(entry.getKey(), value);
|
||||
}
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRunLimit() {
|
||||
return getRunLimit(getAllAttributeKeys());
|
||||
}
|
||||
|
||||
private int runLimit(TList<Range> ranges) {
|
||||
int result = end;
|
||||
TListIterator<Range> it = ranges.listIterator(ranges.size());
|
||||
while (it.hasPrevious()) {
|
||||
Range range = it.previous();
|
||||
if (range.end <= begin) {
|
||||
break;
|
||||
}
|
||||
if (offset >= range.start && offset < range.end) {
|
||||
return inRange(range) ? range.end : result;
|
||||
} else if (offset >= range.end) {
|
||||
break;
|
||||
}
|
||||
result = range.start;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRunLimit(AttributedCharacterIterator.Attribute attribute) {
|
||||
if (attributesAllowed != null && !attributesAllowed.contains(attribute)) {
|
||||
return end;
|
||||
}
|
||||
TArrayList<Range> ranges = (TArrayList<Range>) attrString.attributeMap.get(attribute);
|
||||
if (ranges == null) {
|
||||
return end;
|
||||
}
|
||||
return runLimit(ranges);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRunLimit(TSet<? extends Attribute> attributes) {
|
||||
int limit = end;
|
||||
TIterator<? extends Attribute> it = attributes.iterator();
|
||||
while (it.hasNext()) {
|
||||
AttributedCharacterIterator.Attribute attribute = it.next();
|
||||
int newLimit = getRunLimit(attribute);
|
||||
if (newLimit < limit) {
|
||||
limit = newLimit;
|
||||
}
|
||||
}
|
||||
return limit;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRunStart() {
|
||||
return getRunStart(getAllAttributeKeys());
|
||||
}
|
||||
|
||||
private int runStart(TList<Range> ranges) {
|
||||
int result = begin;
|
||||
TIterator<Range> it = ranges.iterator();
|
||||
while (it.hasNext()) {
|
||||
Range range = it.next();
|
||||
if (range.start >= end) {
|
||||
break;
|
||||
}
|
||||
if (offset >= range.start && offset < range.end) {
|
||||
return inRange(range) ? range.start : result;
|
||||
} else if (offset < range.start) {
|
||||
break;
|
||||
}
|
||||
result = range.end;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRunStart(AttributedCharacterIterator.Attribute attribute) {
|
||||
if (attributesAllowed != null && !attributesAllowed.contains(attribute)) {
|
||||
return begin;
|
||||
}
|
||||
TArrayList<Range> ranges = (TArrayList<Range>) attrString.attributeMap.get(attribute);
|
||||
if (ranges == null) {
|
||||
return begin;
|
||||
}
|
||||
return runStart(ranges);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getRunStart(TSet<? extends Attribute> attributes) {
|
||||
int start = begin;
|
||||
TIterator<? extends Attribute> it = attributes.iterator();
|
||||
while (it.hasNext()) {
|
||||
AttributedCharacterIterator.Attribute attribute = it.next();
|
||||
int newStart = getRunStart(attribute);
|
||||
if (newStart > start) {
|
||||
start = newStart;
|
||||
}
|
||||
}
|
||||
return start;
|
||||
}
|
||||
|
||||
@Override
|
||||
public char last() {
|
||||
if (begin == end) {
|
||||
return DONE;
|
||||
}
|
||||
offset = end - 1;
|
||||
return attrString.text.charAt(offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public char next() {
|
||||
if (offset >= (end - 1)) {
|
||||
offset = end;
|
||||
return DONE;
|
||||
}
|
||||
return attrString.text.charAt(++offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public char previous() {
|
||||
if (offset == begin) {
|
||||
return DONE;
|
||||
}
|
||||
return attrString.text.charAt(--offset);
|
||||
}
|
||||
|
||||
@Override
|
||||
public char setIndex(int location) {
|
||||
if (location < begin || location > end) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
offset = location;
|
||||
if (offset == end) {
|
||||
return DONE;
|
||||
}
|
||||
return attrString.text.charAt(offset);
|
||||
}
|
||||
}
|
||||
|
||||
public AttributedString(AttributedCharacterIterator iterator) {
|
||||
if (iterator.getBeginIndex() > iterator.getEndIndex()) {
|
||||
throw new IllegalArgumentException("Invalid substring range");
|
||||
}
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
for (int i = iterator.getBeginIndex(); i < iterator.getEndIndex(); i++) {
|
||||
buffer.append(iterator.current());
|
||||
iterator.next();
|
||||
}
|
||||
text = buffer.toString();
|
||||
TSet<AttributedCharacterIterator.Attribute> attributes = iterator.getAllAttributeKeys();
|
||||
if (attributes == null) {
|
||||
return;
|
||||
}
|
||||
attributeMap = new THashMap<>((attributes.size() * 4 / 3) + 1);
|
||||
|
||||
TIterator<Attribute> it = attributes.iterator();
|
||||
while (it.hasNext()) {
|
||||
AttributedCharacterIterator.Attribute attribute = it.next();
|
||||
iterator.setIndex(0);
|
||||
while (iterator.current() != CharacterIterator.DONE) {
|
||||
int start = iterator.getRunStart(attribute);
|
||||
int limit = iterator.getRunLimit(attribute);
|
||||
Object value = iterator.getAttribute(attribute);
|
||||
if (value != null) {
|
||||
addAttribute(attribute, value, start, limit);
|
||||
}
|
||||
iterator.setIndex(limit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private AttributedString(AttributedCharacterIterator iterator, int start, int end, TSet<Attribute> attributes) {
|
||||
if (start < iterator.getBeginIndex() || end > iterator.getEndIndex() || start > end) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
if (attributes == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
StringBuilder buffer = new StringBuilder();
|
||||
iterator.setIndex(start);
|
||||
while (iterator.getIndex() < end) {
|
||||
buffer.append(iterator.current());
|
||||
iterator.next();
|
||||
}
|
||||
text = buffer.toString();
|
||||
attributeMap = new THashMap<>((attributes.size() * 4 / 3) + 1);
|
||||
|
||||
TIterator<Attribute> it = attributes.iterator();
|
||||
while (it.hasNext()) {
|
||||
AttributedCharacterIterator.Attribute attribute = it.next();
|
||||
iterator.setIndex(start);
|
||||
while (iterator.getIndex() < end) {
|
||||
Object value = iterator.getAttribute(attribute);
|
||||
int runStart = iterator.getRunStart(attribute);
|
||||
int limit = iterator.getRunLimit(attribute);
|
||||
if ((value instanceof Annotation && runStart >= start && limit <= end) ||
|
||||
(value != null && !(value instanceof Annotation))) {
|
||||
addAttribute(attribute, value, (runStart < start ? start : runStart) - start, (limit > end ? end
|
||||
: limit) - start);
|
||||
}
|
||||
iterator.setIndex(limit);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public AttributedString(AttributedCharacterIterator iterator, int start, int end) {
|
||||
this(iterator, start, end, iterator.getAllAttributeKeys());
|
||||
}
|
||||
|
||||
public AttributedString(AttributedCharacterIterator iterator, int start, int end,
|
||||
AttributedCharacterIterator.Attribute[] attributes) {
|
||||
this(iterator, start, end, new THashSet<>(TArrays.asList(attributes)));
|
||||
}
|
||||
|
||||
public AttributedString(String value) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
text = value;
|
||||
attributeMap = new THashMap<>(11);
|
||||
}
|
||||
|
||||
public AttributedString(String value, TMap<? extends AttributedCharacterIterator.Attribute, ?> attributes) {
|
||||
if (value == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
if (value.length() == 0 && !attributes.isEmpty()) {
|
||||
throw new IllegalArgumentException("Cannot add attributes to empty string");
|
||||
}
|
||||
text = value;
|
||||
attributeMap = new THashMap<>((attributes.size() * 4 / 3) + 1);
|
||||
TIterator<?> it = attributes.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
TMap.Entry<?, ?> entry = (TMap.Entry<?, ?>) it.next();
|
||||
TArrayList<Range> ranges = new TArrayList<>(1);
|
||||
ranges.add(new Range(0, text.length(), entry.getValue()));
|
||||
attributeMap.put((AttributedCharacterIterator.Attribute) entry.getKey(), ranges);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a given attribute to this string.
|
||||
*
|
||||
* @param attribute
|
||||
* the attribute that will be applied to this string.
|
||||
* @param value
|
||||
* the value of the attribute that will be applied to this
|
||||
* string.
|
||||
* @throws IllegalArgumentException
|
||||
* if the length of this attributed string is 0.
|
||||
* @throws NullPointerException
|
||||
* if {@code attribute} is {@code null}.
|
||||
*/
|
||||
public void addAttribute(AttributedCharacterIterator.Attribute attribute, Object value) {
|
||||
if (null == attribute) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
if (text.length() == 0) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
TList<Range> ranges = attributeMap.get(attribute);
|
||||
if (ranges == null) {
|
||||
ranges = new TArrayList<Range>(1);
|
||||
attributeMap.put(attribute, ranges);
|
||||
} else {
|
||||
ranges.clear();
|
||||
}
|
||||
ranges.add(new Range(0, text.length(), value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a given attribute to the given range of this string.
|
||||
*
|
||||
* @param attribute
|
||||
* the attribute that will be applied to this string.
|
||||
* @param value
|
||||
* the value of the attribute that will be applied to this
|
||||
* string.
|
||||
* @param start
|
||||
* the start of the range where the attribute will be applied.
|
||||
* @param end
|
||||
* the end of the range where the attribute will be applied.
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code start < 0}, {@code end} is greater than the length
|
||||
* of this string, or if {@code start >= end}.
|
||||
* @throws NullPointerException
|
||||
* if {@code attribute} is {@code null}.
|
||||
*/
|
||||
public void addAttribute(AttributedCharacterIterator.Attribute attribute, Object value, int start, int end) {
|
||||
if (null == attribute) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
if (start < 0 || end > text.length() || start >= end) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
TList<Range> ranges = attributeMap.get(attribute);
|
||||
if (ranges == null) {
|
||||
ranges = new TArrayList<>(1);
|
||||
ranges.add(new Range(start, end, value));
|
||||
attributeMap.put(attribute, ranges);
|
||||
return;
|
||||
}
|
||||
TListIterator<Range> it = ranges.listIterator();
|
||||
while (it.hasNext()) {
|
||||
Range range = it.next();
|
||||
if (end <= range.start) {
|
||||
it.previous();
|
||||
break;
|
||||
} else if (start < range.end || (start == range.end && value.equals(range.value))) {
|
||||
Range r1 = null, r3;
|
||||
it.remove();
|
||||
r1 = new Range(range.start, start, range.value);
|
||||
r3 = new Range(end, range.end, range.value);
|
||||
|
||||
while (end > range.end && it.hasNext()) {
|
||||
range = it.next();
|
||||
if (end <= range.end) {
|
||||
if (end > range.start || (end == range.start && value.equals(range.value))) {
|
||||
it.remove();
|
||||
r3 = new Range(end, range.end, range.value);
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
it.remove();
|
||||
}
|
||||
}
|
||||
|
||||
if (value.equals(r1.value)) {
|
||||
if (value.equals(r3.value)) {
|
||||
it.add(new Range(r1.start < start ? r1.start : start, r3.end > end ? r3.end : end, r1.value));
|
||||
} else {
|
||||
it.add(new Range(r1.start < start ? r1.start : start, end, r1.value));
|
||||
if (r3.start < r3.end) {
|
||||
it.add(r3);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (value.equals(r3.value)) {
|
||||
if (r1.start < r1.end) {
|
||||
it.add(r1);
|
||||
}
|
||||
it.add(new Range(start, r3.end > end ? r3.end : end, r3.value));
|
||||
} else {
|
||||
if (r1.start < r1.end) {
|
||||
it.add(r1);
|
||||
}
|
||||
it.add(new Range(start, end, value));
|
||||
if (r3.start < r3.end) {
|
||||
it.add(r3);
|
||||
}
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
it.add(new Range(start, end, value));
|
||||
}
|
||||
|
||||
/**
|
||||
* Applies a given set of attributes to the given range of the string.
|
||||
*
|
||||
* @param attributes
|
||||
* the set of attributes that will be applied to this string.
|
||||
* @param start
|
||||
* the start of the range where the attribute will be applied.
|
||||
* @param end
|
||||
* the end of the range where the attribute will be applied.
|
||||
* @throws IllegalArgumentException
|
||||
* if {@code start < 0}, {@code end} is greater than the length
|
||||
* of this string, or if {@code start >= end}.
|
||||
*/
|
||||
public void addAttributes(TMap<? extends AttributedCharacterIterator.Attribute, ?> attributes, int start, int end) {
|
||||
TIterator<?> it = attributes.entrySet().iterator();
|
||||
while (it.hasNext()) {
|
||||
TMap.Entry<?, ?> entry = (TMap.Entry<?, ?>) it.next();
|
||||
addAttribute((AttributedCharacterIterator.Attribute) entry.getKey(), entry.getValue(), start, end);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@code AttributedCharacterIterator} that gives access to the
|
||||
* complete content of this attributed string.
|
||||
*
|
||||
* @return the newly created {@code AttributedCharacterIterator}.
|
||||
*/
|
||||
public AttributedCharacterIterator getIterator() {
|
||||
return new AttributedIterator(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@code AttributedCharacterIterator} that gives access to the
|
||||
* complete content of this attributed string. Only attributes contained in
|
||||
* {@code attributes} are available from this iterator if they are defined
|
||||
* for this text.
|
||||
*
|
||||
* @param attributes
|
||||
* the array containing attributes that will be in the new
|
||||
* iterator if they are defined for this text.
|
||||
* @return the newly created {@code AttributedCharacterIterator}.
|
||||
*/
|
||||
public AttributedCharacterIterator getIterator(AttributedCharacterIterator.Attribute[] attributes) {
|
||||
return new AttributedIterator(this, attributes, 0, text.length());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an {@code AttributedCharacterIterator} that gives access to the
|
||||
* contents of this attributed string starting at index {@code start} up to
|
||||
* index {@code end}. Only attributes contained in {@code attributes} are
|
||||
* available from this iterator if they are defined for this text.
|
||||
*
|
||||
* @param attributes
|
||||
* the array containing attributes that will be in the new
|
||||
* iterator if they are defined for this text.
|
||||
* @param start
|
||||
* the start index of the iterator on the underlying text.
|
||||
* @param end
|
||||
* the end index of the iterator on the underlying text.
|
||||
* @return the newly created {@code AttributedCharacterIterator}.
|
||||
*/
|
||||
public AttributedCharacterIterator getIterator(AttributedCharacterIterator.Attribute[] attributes, int start,
|
||||
int end) {
|
||||
return new AttributedIterator(this, attributes, start, end);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
/*
|
||||
* 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.teavm.classlib.java.text;
|
||||
|
||||
public interface CharacterIterator extends Cloneable {
|
||||
public static final char DONE = '\uffff';
|
||||
|
||||
public Object clone();
|
||||
|
||||
public char current();
|
||||
|
||||
public char first();
|
||||
|
||||
public int getBeginIndex();
|
||||
|
||||
public int getEndIndex();
|
||||
|
||||
public int getIndex();
|
||||
|
||||
public char last();
|
||||
|
||||
public char next();
|
||||
|
||||
public char previous();
|
||||
|
||||
public char setIndex(int location);
|
||||
}
|
|
@ -0,0 +1,280 @@
|
|||
/*
|
||||
* 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.teavm.classlib.java.text;
|
||||
|
||||
import org.teavm.classlib.java.util.*;
|
||||
|
||||
public abstract class DateFormat extends Format {
|
||||
protected Calendar calendar;
|
||||
protected NumberFormat numberFormat;
|
||||
public final static int DEFAULT = 2;
|
||||
public final static int FULL = 0;
|
||||
public final static int LONG = 1;
|
||||
public final static int MEDIUM = 2;
|
||||
public final static int SHORT = 3;
|
||||
public final static int ERA_FIELD = 0;
|
||||
public final static int YEAR_FIELD = 1;
|
||||
public final static int MONTH_FIELD = 2;
|
||||
public final static int DATE_FIELD = 3;
|
||||
public final static int HOUR_OF_DAY1_FIELD = 4;
|
||||
public final static int HOUR_OF_DAY0_FIELD = 5;
|
||||
public final static int MINUTE_FIELD = 6;
|
||||
public final static int SECOND_FIELD = 7;
|
||||
public final static int MILLISECOND_FIELD = 8;
|
||||
public final static int DAY_OF_WEEK_FIELD = 9;
|
||||
public final static int DAY_OF_YEAR_FIELD = 10;
|
||||
public final static int DAY_OF_WEEK_IN_MONTH_FIELD = 11;
|
||||
public final static int WEEK_OF_YEAR_FIELD = 12;
|
||||
public final static int WEEK_OF_MONTH_FIELD = 13;
|
||||
public final static int AM_PM_FIELD = 14;
|
||||
public final static int HOUR1_FIELD = 15;
|
||||
public final static int HOUR0_FIELD = 16;
|
||||
public final static int TIMEZONE_FIELD = 17;
|
||||
|
||||
protected DateFormat() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() {
|
||||
DateFormat clone = (DateFormat) super.clone();
|
||||
clone.calendar = (Calendar) calendar.clone();
|
||||
clone.numberFormat = (NumberFormat) numberFormat.clone();
|
||||
return clone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (this == object) {
|
||||
return true;
|
||||
}
|
||||
if (!(object instanceof DateFormat)) {
|
||||
return false;
|
||||
}
|
||||
DateFormat dateFormat = (DateFormat) object;
|
||||
return numberFormat.equals(dateFormat.numberFormat) &&
|
||||
calendar.getTimeZone().equals(dateFormat.calendar.getTimeZone()) &&
|
||||
calendar.getFirstDayOfWeek() == dateFormat.calendar.getFirstDayOfWeek() &&
|
||||
calendar.getMinimalDaysInFirstWeek() == dateFormat.calendar.getMinimalDaysInFirstWeek() &&
|
||||
calendar.isLenient() == dateFormat.calendar.isLenient();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final StringBuffer format(Object object, StringBuffer buffer, FieldPosition field) {
|
||||
if (object instanceof Date) {
|
||||
return format((Date) object, buffer, field);
|
||||
}
|
||||
if (object instanceof Number) {
|
||||
return format(new Date(((Number) object).longValue()), buffer, field);
|
||||
}
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
public final String format(Date date) {
|
||||
return format(date, new StringBuffer(), new FieldPosition(0)).toString();
|
||||
}
|
||||
|
||||
public abstract StringBuffer format(Date date, StringBuffer buffer, FieldPosition field);
|
||||
|
||||
public static TLocale[] getAvailableLocales() {
|
||||
return TLocale.getAvailableLocales();
|
||||
}
|
||||
|
||||
public Calendar getCalendar() {
|
||||
return calendar;
|
||||
}
|
||||
|
||||
public final static DateFormat getDateInstance() {
|
||||
return getDateInstance(DEFAULT);
|
||||
}
|
||||
|
||||
public final static DateFormat getDateInstance(int style) {
|
||||
checkDateStyle(style);
|
||||
return getDateInstance(style, TLocale.getDefault());
|
||||
}
|
||||
|
||||
public final static DateFormat getDateInstance(int style, TLocale locale) {
|
||||
checkDateStyle(style);
|
||||
com.ibm.icu.text.DateFormat icuFormat = com.ibm.icu.text.DateFormat.getDateInstance(style, locale);
|
||||
return new SimpleDateFormat(locale, (com.ibm.icu.text.SimpleDateFormat) icuFormat);
|
||||
}
|
||||
|
||||
public final static DateFormat getDateTimeInstance() {
|
||||
return getDateTimeInstance(DEFAULT, DEFAULT);
|
||||
}
|
||||
|
||||
public final static DateFormat getDateTimeInstance(int dateStyle, int timeStyle) {
|
||||
checkTimeStyle(timeStyle);
|
||||
checkDateStyle(dateStyle);
|
||||
return getDateTimeInstance(dateStyle, timeStyle, TLocale.getDefault());
|
||||
}
|
||||
|
||||
public final static DateFormat getDateTimeInstance(int dateStyle, int timeStyle, TLocale locale) {
|
||||
checkTimeStyle(timeStyle);
|
||||
checkDateStyle(dateStyle);
|
||||
com.ibm.icu.text.DateFormat icuFormat = com.ibm.icu.text.DateFormat.getDateTimeInstance(dateStyle, timeStyle,
|
||||
locale);
|
||||
return new SimpleDateFormat(locale, (com.ibm.icu.text.SimpleDateFormat) icuFormat);
|
||||
}
|
||||
|
||||
public final static DateFormat getInstance() {
|
||||
return getDateTimeInstance(SHORT, SHORT);
|
||||
}
|
||||
|
||||
public NumberFormat getNumberFormat() {
|
||||
return numberFormat;
|
||||
}
|
||||
|
||||
static String getStyleName(int style) {
|
||||
String styleName;
|
||||
switch (style) {
|
||||
case SHORT:
|
||||
styleName = "SHORT";
|
||||
break;
|
||||
case MEDIUM:
|
||||
styleName = "MEDIUM";
|
||||
break;
|
||||
case LONG:
|
||||
styleName = "LONG";
|
||||
break;
|
||||
case FULL:
|
||||
styleName = "FULL";
|
||||
break;
|
||||
default:
|
||||
styleName = "";
|
||||
}
|
||||
return styleName;
|
||||
}
|
||||
|
||||
public final static DateFormat getTimeInstance() {
|
||||
return getTimeInstance(DEFAULT);
|
||||
}
|
||||
|
||||
public final static DateFormat getTimeInstance(int style) {
|
||||
checkTimeStyle(style);
|
||||
return getTimeInstance(style, TLocale.getDefault());
|
||||
}
|
||||
|
||||
public final static DateFormat getTimeInstance(int style, TLocale locale) {
|
||||
checkTimeStyle(style);
|
||||
com.ibm.icu.text.DateFormat icuFormat = com.ibm.icu.text.DateFormat.getTimeInstance(style, locale);
|
||||
return new SimpleDateFormat(locale, (com.ibm.icu.text.SimpleDateFormat) icuFormat);
|
||||
}
|
||||
|
||||
public TimeZone getTimeZone() {
|
||||
return calendar.getTimeZone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return calendar.getFirstDayOfWeek() + calendar.getMinimalDaysInFirstWeek() + calendar.getTimeZone().hashCode() +
|
||||
(calendar.isLenient() ? 1231 : 1237) + numberFormat.hashCode();
|
||||
}
|
||||
|
||||
public boolean isLenient() {
|
||||
return calendar.isLenient();
|
||||
}
|
||||
|
||||
public Date parse(String string) throws ParseException {
|
||||
ParsePosition position = new ParsePosition(0);
|
||||
Date date = parse(string, position);
|
||||
if (position.getIndex() == 0) {
|
||||
throw new ParseException("Unparseable date" + string, position.getErrorIndex());
|
||||
}
|
||||
return date;
|
||||
}
|
||||
|
||||
public abstract Date parse(String string, ParsePosition position);
|
||||
|
||||
@Override
|
||||
public Object parseObject(String string, ParsePosition position) {
|
||||
return parse(string, position);
|
||||
}
|
||||
|
||||
public void setCalendar(Calendar cal) {
|
||||
calendar = cal;
|
||||
}
|
||||
|
||||
public void setLenient(boolean value) {
|
||||
calendar.setLenient(value);
|
||||
}
|
||||
|
||||
public void setNumberFormat(NumberFormat format) {
|
||||
numberFormat = format;
|
||||
}
|
||||
|
||||
public void setTimeZone(TimeZone timezone) {
|
||||
calendar.setTimeZone(timezone);
|
||||
}
|
||||
|
||||
public static class Field extends Format.Field {
|
||||
private static THashMap<Integer, Field> table = new THashMap<>();
|
||||
public final static Field ERA = new Field("era", Calendar.ERA);
|
||||
public final static Field YEAR = new Field("year", Calendar.YEAR);
|
||||
public final static Field MONTH = new Field("month", Calendar.MONTH);
|
||||
public final static Field HOUR_OF_DAY0 = new Field("hour of day", Calendar.HOUR_OF_DAY);
|
||||
public final static Field HOUR_OF_DAY1 = new Field("hour of day 1", -1);
|
||||
public final static Field MINUTE = new Field("minute", Calendar.MINUTE);
|
||||
public final static Field SECOND = new Field("second", Calendar.SECOND);
|
||||
public final static Field MILLISECOND = new Field("millisecond", Calendar.MILLISECOND);
|
||||
public final static Field DAY_OF_WEEK = new Field("day of week", Calendar.DAY_OF_WEEK);
|
||||
public final static Field DAY_OF_MONTH = new Field("day of month", Calendar.DAY_OF_MONTH);
|
||||
public final static Field DAY_OF_YEAR = new Field("day of year", Calendar.DAY_OF_YEAR);
|
||||
public final static Field DAY_OF_WEEK_IN_MONTH = new Field("day of week in month",
|
||||
Calendar.DAY_OF_WEEK_IN_MONTH);
|
||||
public final static Field WEEK_OF_YEAR = new Field("week of year", Calendar.WEEK_OF_YEAR);
|
||||
public final static Field WEEK_OF_MONTH = new Field("week of month", Calendar.WEEK_OF_MONTH);
|
||||
public final static Field AM_PM = new Field("am pm", Calendar.AM_PM);
|
||||
public final static Field HOUR0 = new Field("hour", Calendar.HOUR);
|
||||
public final static Field HOUR1 = new Field("hour 1", -1);
|
||||
public final static Field TIME_ZONE = new Field("time zone", -1);
|
||||
private int calendarField = -1;
|
||||
|
||||
protected Field(String fieldName, int calendarField) {
|
||||
super(fieldName);
|
||||
this.calendarField = calendarField;
|
||||
if (calendarField != -1 && table.get(new Integer(calendarField)) == null) {
|
||||
table.put(new Integer(calendarField), this);
|
||||
}
|
||||
}
|
||||
|
||||
public int getCalendarField() {
|
||||
return calendarField;
|
||||
}
|
||||
|
||||
public static Field ofCalendarField(int calendarField) {
|
||||
if (calendarField < 0 || calendarField >= Calendar.FIELD_COUNT) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
return table.get(new Integer(calendarField));
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkDateStyle(int style) {
|
||||
if (!(style == SHORT || style == MEDIUM || style == LONG || style == FULL || style == DEFAULT)) {
|
||||
throw new IllegalArgumentException("Illegal date style: " + style);
|
||||
}
|
||||
}
|
||||
|
||||
private static void checkTimeStyle(int style) {
|
||||
if (!(style == SHORT || style == MEDIUM || style == LONG || style == FULL || style == DEFAULT)) {
|
||||
// text.0F=Illegal time style: {0}
|
||||
throw new IllegalArgumentException("Illegal time style: " + style);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,240 @@
|
|||
/*
|
||||
* 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.teavm.classlib.java.text;
|
||||
|
||||
import java.util.Arrays;
|
||||
import org.teavm.classlib.java.io.TSerializable;
|
||||
import org.teavm.classlib.java.util.TLocale;
|
||||
|
||||
public class DateFormatSymbols implements TSerializable, Cloneable {
|
||||
|
||||
private static final long serialVersionUID = -5987973545549424702L;
|
||||
|
||||
private String localPatternChars;
|
||||
|
||||
String[] ampms, eras, months, shortMonths, shortWeekdays, weekdays;
|
||||
|
||||
String[][] zoneStrings;
|
||||
|
||||
transient private com.ibm.icu.text.DateFormatSymbols icuSymbols;
|
||||
|
||||
public DateFormatSymbols() {
|
||||
this(TLocale.getDefault());
|
||||
}
|
||||
|
||||
public DateFormatSymbols(TLocale locale) {
|
||||
this(locale, new com.ibm.icu.text.DateFormatSymbols(locale));
|
||||
}
|
||||
|
||||
DateFormatSymbols(TLocale locale, com.ibm.icu.text.DateFormatSymbols icuSymbols) {
|
||||
this.icuSymbols = icuSymbols;
|
||||
localPatternChars = icuSymbols.getLocalPatternChars();
|
||||
ampms = icuSymbols.getAmPmStrings();
|
||||
eras = icuSymbols.getEras();
|
||||
months = icuSymbols.getMonths();
|
||||
shortMonths = icuSymbols.getShortMonths();
|
||||
shortWeekdays = icuSymbols.getShortWeekdays();
|
||||
weekdays = icuSymbols.getWeekdays();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() {
|
||||
if (zoneStrings == null) {
|
||||
zoneStrings = icuSymbols.getZoneStrings();
|
||||
}
|
||||
try {
|
||||
DateFormatSymbols symbols = (DateFormatSymbols) super.clone();
|
||||
symbols.ampms = ampms.clone();
|
||||
symbols.eras = eras.clone();
|
||||
symbols.months = months.clone();
|
||||
symbols.shortMonths = shortMonths.clone();
|
||||
symbols.shortWeekdays = shortWeekdays.clone();
|
||||
symbols.weekdays = weekdays.clone();
|
||||
symbols.zoneStrings = new String[zoneStrings.length][];
|
||||
for (int i = 0; i < zoneStrings.length; i++) {
|
||||
symbols.zoneStrings[i] = zoneStrings[i].clone();
|
||||
}
|
||||
return symbols;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (this == object) {
|
||||
return true;
|
||||
}
|
||||
if (!(object instanceof DateFormatSymbols)) {
|
||||
return false;
|
||||
}
|
||||
if (zoneStrings == null) {
|
||||
zoneStrings = icuSymbols.getZoneStrings();
|
||||
}
|
||||
|
||||
DateFormatSymbols obj = (DateFormatSymbols) object;
|
||||
|
||||
if (obj.zoneStrings == null) {
|
||||
obj.zoneStrings = obj.icuSymbols.getZoneStrings();
|
||||
}
|
||||
if (!localPatternChars.equals(obj.localPatternChars)) {
|
||||
return false;
|
||||
}
|
||||
if (!Arrays.equals(ampms, obj.ampms)) {
|
||||
return false;
|
||||
}
|
||||
if (!Arrays.equals(eras, obj.eras)) {
|
||||
return false;
|
||||
}
|
||||
if (!Arrays.equals(months, obj.months)) {
|
||||
return false;
|
||||
}
|
||||
if (!Arrays.equals(shortMonths, obj.shortMonths)) {
|
||||
return false;
|
||||
}
|
||||
if (!Arrays.equals(shortWeekdays, obj.shortWeekdays)) {
|
||||
return false;
|
||||
}
|
||||
if (!Arrays.equals(weekdays, obj.weekdays)) {
|
||||
return false;
|
||||
}
|
||||
if (zoneStrings.length != obj.zoneStrings.length) {
|
||||
return false;
|
||||
}
|
||||
for (String[] element : zoneStrings) {
|
||||
if (element.length != element.length) {
|
||||
return false;
|
||||
}
|
||||
for (int j = 0; j < element.length; j++) {
|
||||
if (element[j] != element[j] && !(element[j].equals(element[j]))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public String[] getAmPmStrings() {
|
||||
return ampms.clone();
|
||||
}
|
||||
|
||||
public String[] getEras() {
|
||||
return eras.clone();
|
||||
}
|
||||
|
||||
public String getLocalPatternChars() {
|
||||
return localPatternChars;
|
||||
}
|
||||
|
||||
public String[] getMonths() {
|
||||
return months.clone();
|
||||
}
|
||||
|
||||
public String[] getShortMonths() {
|
||||
return shortMonths.clone();
|
||||
}
|
||||
|
||||
public String[] getShortWeekdays() {
|
||||
return shortWeekdays.clone();
|
||||
}
|
||||
|
||||
public String[] getWeekdays() {
|
||||
return weekdays.clone();
|
||||
}
|
||||
|
||||
public String[][] getZoneStrings() {
|
||||
if (zoneStrings == null) {
|
||||
zoneStrings = icuSymbols.getZoneStrings();
|
||||
}
|
||||
String[][] clone = new String[zoneStrings.length][];
|
||||
for (int i = zoneStrings.length; --i >= 0;) {
|
||||
clone[i] = zoneStrings[i].clone();
|
||||
}
|
||||
return clone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (zoneStrings == null) {
|
||||
zoneStrings = icuSymbols.getZoneStrings();
|
||||
}
|
||||
int hashCode;
|
||||
hashCode = localPatternChars.hashCode();
|
||||
for (String element : ampms) {
|
||||
hashCode += element.hashCode();
|
||||
}
|
||||
for (String element : eras) {
|
||||
hashCode += element.hashCode();
|
||||
}
|
||||
for (String element : months) {
|
||||
hashCode += element.hashCode();
|
||||
}
|
||||
for (String element : shortMonths) {
|
||||
hashCode += element.hashCode();
|
||||
}
|
||||
for (String element : shortWeekdays) {
|
||||
hashCode += element.hashCode();
|
||||
}
|
||||
for (String element : weekdays) {
|
||||
hashCode += element.hashCode();
|
||||
}
|
||||
for (String[] element : zoneStrings) {
|
||||
for (int j = 0; j < element.length; j++) {
|
||||
if (element[j] != null) {
|
||||
hashCode += element[j].hashCode();
|
||||
}
|
||||
}
|
||||
}
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
public void setAmPmStrings(String[] data) {
|
||||
ampms = data.clone();
|
||||
}
|
||||
|
||||
public void setEras(String[] data) {
|
||||
eras = data.clone();
|
||||
}
|
||||
|
||||
public void setLocalPatternChars(String data) {
|
||||
if (data == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
localPatternChars = data;
|
||||
}
|
||||
|
||||
public void setMonths(String[] data) {
|
||||
months = data.clone();
|
||||
}
|
||||
|
||||
public void setShortMonths(String[] data) {
|
||||
shortMonths = data.clone();
|
||||
}
|
||||
|
||||
public void setShortWeekdays(String[] data) {
|
||||
shortWeekdays = data.clone();
|
||||
}
|
||||
|
||||
public void setWeekdays(String[] data) {
|
||||
weekdays = data.clone();
|
||||
}
|
||||
|
||||
public void setZoneStrings(String[][] data) {
|
||||
zoneStrings = data.clone();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,432 @@
|
|||
/*
|
||||
* 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.teavm.classlib.java.text;
|
||||
|
||||
import org.teavm.classlib.java.util.TLocale;
|
||||
|
||||
|
||||
public class DecimalFormat extends NumberFormat {
|
||||
|
||||
private static final long serialVersionUID = 864413376551465018L;
|
||||
|
||||
private transient boolean parseBigDecimal = false;
|
||||
|
||||
private transient DecimalFormatSymbols symbols;
|
||||
|
||||
private transient com.ibm.icu.text.DecimalFormat dform;
|
||||
|
||||
private transient com.ibm.icu.text.DecimalFormatSymbols icuSymbols;
|
||||
|
||||
private static final int CURRENT_SERIAL_VERTION = 3;
|
||||
|
||||
private transient int serialVersionOnStream = 3;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code DecimalFormat} for formatting and parsing numbers
|
||||
* for the default locale.
|
||||
*/
|
||||
public DecimalFormat() {
|
||||
TLocale locale = TLocale.getDefault();
|
||||
icuSymbols = new com.ibm.icu.text.DecimalFormatSymbols(locale);
|
||||
symbols = new DecimalFormatSymbols(locale);
|
||||
dform = new com.ibm.icu.text.DecimalFormat();
|
||||
|
||||
super.setMaximumFractionDigits(dform.getMaximumFractionDigits());
|
||||
super.setMaximumIntegerDigits(dform.getMaximumIntegerDigits());
|
||||
super.setMinimumFractionDigits(dform.getMinimumFractionDigits());
|
||||
super.setMinimumIntegerDigits(dform.getMinimumIntegerDigits());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code DecimalFormat} using the specified non-localized
|
||||
* pattern and the {@code DecimalFormatSymbols} for the default Locale.
|
||||
*
|
||||
* @param pattern
|
||||
* the non-localized pattern.
|
||||
* @throws IllegalArgumentException
|
||||
* if the pattern cannot be parsed.
|
||||
*/
|
||||
public DecimalFormat(String pattern) {
|
||||
TLocale locale = TLocale.getDefault();
|
||||
icuSymbols = new com.ibm.icu.text.DecimalFormatSymbols(locale);
|
||||
symbols = new DecimalFormatSymbols(locale);
|
||||
dform = new com.ibm.icu.text.DecimalFormat(pattern, icuSymbols);
|
||||
|
||||
super.setMaximumFractionDigits(dform.getMaximumFractionDigits());
|
||||
super.setMaximumIntegerDigits(dform.getMaximumIntegerDigits());
|
||||
super.setMinimumFractionDigits(dform.getMinimumFractionDigits());
|
||||
super.setMinimumIntegerDigits(dform.getMinimumIntegerDigits());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new {@code DecimalFormat} using the specified non-localized
|
||||
* pattern and {@code DecimalFormatSymbols}.
|
||||
*
|
||||
* @param pattern
|
||||
* the non-localized pattern.
|
||||
* @param value
|
||||
* the DecimalFormatSymbols.
|
||||
* @throws IllegalArgumentException
|
||||
* if the pattern cannot be parsed.
|
||||
*/
|
||||
public DecimalFormat(String pattern, DecimalFormatSymbols value) {
|
||||
symbols = (DecimalFormatSymbols) value.clone();
|
||||
TLocale locale = symbols.getLocale();
|
||||
icuSymbols = new com.ibm.icu.text.DecimalFormatSymbols(locale);
|
||||
copySymbols(icuSymbols, symbols);
|
||||
|
||||
dform = new com.ibm.icu.text.DecimalFormat(pattern, icuSymbols);
|
||||
|
||||
super.setMaximumFractionDigits(dform.getMaximumFractionDigits());
|
||||
super.setMaximumIntegerDigits(dform.getMaximumIntegerDigits());
|
||||
super.setMinimumFractionDigits(dform.getMinimumFractionDigits());
|
||||
super.setMinimumIntegerDigits(dform.getMinimumIntegerDigits());
|
||||
}
|
||||
|
||||
DecimalFormat(String pattern, DecimalFormatSymbols value, com.ibm.icu.text.DecimalFormat icuFormat) {
|
||||
symbols = value;
|
||||
icuSymbols = value.getIcuSymbols();
|
||||
dform = icuFormat;
|
||||
|
||||
super.setMaximumFractionDigits(dform.getMaximumFractionDigits());
|
||||
super.setMaximumIntegerDigits(dform.getMaximumIntegerDigits());
|
||||
super.setMinimumFractionDigits(dform.getMinimumFractionDigits());
|
||||
super.setMinimumIntegerDigits(dform.getMinimumIntegerDigits());
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the pattern of this decimal format to the specified pattern which
|
||||
* uses localized pattern characters.
|
||||
*
|
||||
* @param pattern
|
||||
* the localized pattern.
|
||||
* @throws IllegalArgumentException
|
||||
* if the pattern cannot be parsed.
|
||||
*/
|
||||
public void applyLocalizedPattern(String pattern) {
|
||||
dform.applyLocalizedPattern(pattern);
|
||||
super.setMaximumFractionDigits(dform.getMaximumFractionDigits());
|
||||
super.setMaximumIntegerDigits(dform.getMaximumIntegerDigits());
|
||||
super.setMinimumFractionDigits(dform.getMinimumFractionDigits());
|
||||
super.setMinimumIntegerDigits(dform.getMinimumIntegerDigits());
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the pattern of this decimal format to the specified pattern which
|
||||
* uses non-localized pattern characters.
|
||||
*
|
||||
* @param pattern
|
||||
* the non-localized pattern.
|
||||
* @throws IllegalArgumentException
|
||||
* if the pattern cannot be parsed.
|
||||
*/
|
||||
public void applyPattern(String pattern) {
|
||||
|
||||
dform.applyPattern(pattern);
|
||||
super.setMaximumFractionDigits(dform.getMaximumFractionDigits());
|
||||
super.setMaximumIntegerDigits(dform.getMaximumIntegerDigits());
|
||||
super.setMinimumFractionDigits(dform.getMinimumFractionDigits());
|
||||
super.setMinimumIntegerDigits(dform.getMinimumIntegerDigits());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new instance of {@code DecimalFormat} with the same pattern and
|
||||
* properties as this decimal format.
|
||||
*
|
||||
* @return a shallow copy of this decimal format.
|
||||
* @see java.lang.Cloneable
|
||||
*/
|
||||
@Override
|
||||
public Object clone() {
|
||||
DecimalFormat clone = (DecimalFormat) super.clone();
|
||||
clone.dform = (com.ibm.icu.text.DecimalFormat) dform.clone();
|
||||
clone.symbols = (DecimalFormatSymbols) symbols.clone();
|
||||
return clone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (this == object) {
|
||||
return true;
|
||||
}
|
||||
if (!(object instanceof DecimalFormat)) {
|
||||
return false;
|
||||
}
|
||||
DecimalFormat format = (DecimalFormat) object;
|
||||
return (this.dform == null ? format.dform == null : this.dform
|
||||
.equals(format.dform));
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributedCharacterIterator formatToCharacterIterator(Object object) {
|
||||
if (object == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
return dform.formatToCharacterIterator(object);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringBuffer format(double value, StringBuffer buffer,
|
||||
FieldPosition position) {
|
||||
return dform.format(value, buffer, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringBuffer format(long value, StringBuffer buffer,
|
||||
FieldPosition position) {
|
||||
return dform.format(value, buffer, position);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final StringBuffer format(Object number, StringBuffer toAppendTo,
|
||||
FieldPosition pos) {
|
||||
if (!(number instanceof Number)) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
if (toAppendTo == null || pos == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
if (number instanceof BigInteger || number instanceof BigDecimal) {
|
||||
return dform.format(number, toAppendTo, pos);
|
||||
}
|
||||
return super.format(number, toAppendTo, pos);
|
||||
}
|
||||
|
||||
public DecimalFormatSymbols getDecimalFormatSymbols() {
|
||||
return (DecimalFormatSymbols) symbols.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Currency getCurrency() {
|
||||
final com.ibm.icu.util.Currency cur = dform.getCurrency();
|
||||
final String code = (cur == null) ? "XXX" : cur.getCurrencyCode(); //$NON-NLS-1$
|
||||
|
||||
return Currency.getInstance(code);
|
||||
}
|
||||
|
||||
public int getGroupingSize() {
|
||||
return dform.getGroupingSize();
|
||||
}
|
||||
|
||||
public int getMultiplier() {
|
||||
return dform.getMultiplier();
|
||||
}
|
||||
|
||||
public String getNegativePrefix() {
|
||||
return dform.getNegativePrefix();
|
||||
}
|
||||
|
||||
public String getNegativeSuffix() {
|
||||
return dform.getNegativeSuffix();
|
||||
}
|
||||
|
||||
public String getPositivePrefix() {
|
||||
return dform.getPositivePrefix();
|
||||
}
|
||||
|
||||
public String getPositiveSuffix() {
|
||||
return dform.getPositiveSuffix();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return dform.hashCode();
|
||||
}
|
||||
|
||||
public boolean isDecimalSeparatorAlwaysShown() {
|
||||
return dform.isDecimalSeparatorAlwaysShown();
|
||||
}
|
||||
|
||||
public boolean isParseBigDecimal() {
|
||||
return this.parseBigDecimal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setParseIntegerOnly(boolean value) {
|
||||
// In this implementation, com.ibm.icu.text.DecimalFormat is wrapped to
|
||||
// fulfill most of the format and parse feature. And this method is
|
||||
// delegated to the wrapped instance of com.ibm.icu.text.DecimalFormat.
|
||||
|
||||
dform.setParseIntegerOnly(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isParseIntegerOnly() {
|
||||
return dform.isParseIntegerOnly();
|
||||
}
|
||||
|
||||
private static final Double NEGATIVE_ZERO_DOUBLE = new Double(-0.0);
|
||||
|
||||
@Override
|
||||
public Number parse(String string, ParsePosition position) {
|
||||
Number number = dform.parse(string, position);
|
||||
if (null == number) {
|
||||
return null;
|
||||
}
|
||||
if (this.isParseBigDecimal()) {
|
||||
if (number instanceof Long) {
|
||||
return new BigDecimal(number.longValue());
|
||||
}
|
||||
if ((number instanceof Double) && !((Double) number).isInfinite()
|
||||
&& !((Double) number).isNaN()) {
|
||||
|
||||
return new BigDecimal(number.doubleValue());
|
||||
}
|
||||
if (number instanceof BigInteger) {
|
||||
return new BigDecimal(number.doubleValue());
|
||||
}
|
||||
if (number instanceof com.ibm.icu.math.BigDecimal) {
|
||||
return new BigDecimal(number.toString());
|
||||
}
|
||||
return number;
|
||||
}
|
||||
if ((number instanceof com.ibm.icu.math.BigDecimal)
|
||||
|| (number instanceof BigInteger)) {
|
||||
return new Double(number.doubleValue());
|
||||
}
|
||||
|
||||
if (this.isParseIntegerOnly() && number.equals(NEGATIVE_ZERO_DOUBLE)) {
|
||||
return new Long(0);
|
||||
}
|
||||
return number;
|
||||
|
||||
}
|
||||
|
||||
public void setDecimalFormatSymbols(DecimalFormatSymbols value) {
|
||||
if (value != null) {
|
||||
symbols = (DecimalFormatSymbols) value.clone();
|
||||
icuSymbols = dform.getDecimalFormatSymbols();
|
||||
copySymbols(icuSymbols, symbols);
|
||||
dform.setDecimalFormatSymbols(icuSymbols);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCurrency(Currency currency) {
|
||||
dform.setCurrency(com.ibm.icu.util.Currency.getInstance(currency
|
||||
.getCurrencyCode()));
|
||||
symbols.setCurrency(currency);
|
||||
}
|
||||
|
||||
public void setDecimalSeparatorAlwaysShown(boolean value) {
|
||||
dform.setDecimalSeparatorAlwaysShown(value);
|
||||
}
|
||||
|
||||
public void setGroupingSize(int value) {
|
||||
dform.setGroupingSize(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setGroupingUsed(boolean value) {
|
||||
dform.setGroupingUsed(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isGroupingUsed() {
|
||||
return dform.isGroupingUsed();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaximumFractionDigits(int value) {
|
||||
super.setMaximumFractionDigits(value);
|
||||
dform.setMaximumFractionDigits(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMaximumIntegerDigits(int value) {
|
||||
super.setMaximumIntegerDigits(value);
|
||||
dform.setMaximumIntegerDigits(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMinimumFractionDigits(int value) {
|
||||
super.setMinimumFractionDigits(value);
|
||||
dform.setMinimumFractionDigits(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setMinimumIntegerDigits(int value) {
|
||||
super.setMinimumIntegerDigits(value);
|
||||
dform.setMinimumIntegerDigits(value);
|
||||
}
|
||||
|
||||
public void setMultiplier(int value) {
|
||||
dform.setMultiplier(value);
|
||||
}
|
||||
|
||||
public void setNegativePrefix(String value) {
|
||||
dform.setNegativePrefix(value);
|
||||
}
|
||||
|
||||
public void setNegativeSuffix(String value) {
|
||||
dform.setNegativeSuffix(value);
|
||||
}
|
||||
|
||||
public void setPositivePrefix(String value) {
|
||||
dform.setPositivePrefix(value);
|
||||
}
|
||||
|
||||
public void setPositiveSuffix(String value) {
|
||||
dform.setPositiveSuffix(value);
|
||||
}
|
||||
|
||||
public void setParseBigDecimal(boolean newValue) {
|
||||
this.parseBigDecimal = newValue;
|
||||
}
|
||||
|
||||
public String toLocalizedPattern() {
|
||||
return dform.toLocalizedPattern();
|
||||
}
|
||||
|
||||
public String toPattern() {
|
||||
return dform.toPattern();
|
||||
}
|
||||
|
||||
/*
|
||||
* Copies decimal format symbols from text object to ICU one.
|
||||
*
|
||||
* @param icu the object which receives the new values. @param dfs the
|
||||
* object which contains the new values.
|
||||
*/
|
||||
private void copySymbols(final com.ibm.icu.text.DecimalFormatSymbols icu,
|
||||
final DecimalFormatSymbols dfs) {
|
||||
Currency currency = dfs.getCurrency();
|
||||
if (currency == null) {
|
||||
icu.setCurrency(com.ibm.icu.util.Currency.getInstance("XXX")); //$NON-NLS-1$
|
||||
} else {
|
||||
icu.setCurrency(com.ibm.icu.util.Currency.getInstance(dfs
|
||||
.getCurrency().getCurrencyCode()));
|
||||
}
|
||||
|
||||
icu.setCurrencySymbol(dfs.getCurrencySymbol());
|
||||
icu.setDecimalSeparator(dfs.getDecimalSeparator());
|
||||
icu.setDigit(dfs.getDigit());
|
||||
icu.setGroupingSeparator(dfs.getGroupingSeparator());
|
||||
icu.setInfinity(dfs.getInfinity());
|
||||
icu
|
||||
.setInternationalCurrencySymbol(dfs
|
||||
.getInternationalCurrencySymbol());
|
||||
icu.setMinusSign(dfs.getMinusSign());
|
||||
icu.setMonetaryDecimalSeparator(dfs.getMonetaryDecimalSeparator());
|
||||
icu.setNaN(dfs.getNaN());
|
||||
icu.setPatternSeparator(dfs.getPatternSeparator());
|
||||
icu.setPercent(dfs.getPercent());
|
||||
icu.setPerMill(dfs.getPerMill());
|
||||
icu.setZeroDigit(dfs.getZeroDigit());
|
||||
}
|
||||
}
|
|
@ -0,0 +1,280 @@
|
|||
/*
|
||||
* 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.teavm.classlib.java.text;
|
||||
|
||||
import java.util.Arrays;
|
||||
import org.teavm.classlib.java.io.TSerializable;
|
||||
import org.teavm.classlib.java.lang.TCloneable;
|
||||
import org.teavm.classlib.java.util.TLocale;
|
||||
|
||||
public final class DecimalFormatSymbols implements TCloneable, TSerializable {
|
||||
|
||||
private final int ZeroDigit = 0, Digit = 1, DecimalSeparator = 2,
|
||||
GroupingSeparator = 3, PatternSeparator = 4, Percent = 5,
|
||||
PerMill = 6, Exponent = 7, MonetaryDecimalSeparator = 8,
|
||||
MinusSign = 9;
|
||||
|
||||
transient char[] patternChars;
|
||||
|
||||
private transient Currency currency;
|
||||
|
||||
private transient TLocale locale;
|
||||
|
||||
private String infinity, NaN, currencySymbol, intlCurrencySymbol;
|
||||
|
||||
/**
|
||||
* Constructs a new {@code DecimalFormatSymbols} containing the symbols for
|
||||
* the default locale. Best practice is to create a {@code DecimalFormat}
|
||||
* and then to get the {@code DecimalFormatSymbols} from that object by
|
||||
* calling {@link DecimalFormat#getDecimalFormatSymbols()}.
|
||||
*/
|
||||
public DecimalFormatSymbols() {
|
||||
this(TLocale.getDefault());
|
||||
}
|
||||
|
||||
/**
|
||||
* Constructs a new DecimalFormatSymbols containing the symbols for the
|
||||
* specified Locale. Best practice is to create a {@code DecimalFormat}
|
||||
* and then to get the {@code DecimalFormatSymbols} from that object by
|
||||
* calling {@link DecimalFormat#getDecimalFormatSymbols()}.
|
||||
*
|
||||
* @param locale
|
||||
* the locale.
|
||||
*/
|
||||
public DecimalFormatSymbols(TLocale locale) {
|
||||
this(locale, new com.ibm.icu.text.DecimalFormatSymbols(locale));
|
||||
}
|
||||
|
||||
transient private com.ibm.icu.text.DecimalFormatSymbols icuSymbols;
|
||||
|
||||
DecimalFormatSymbols(TLocale locale, com.ibm.icu.text.DecimalFormatSymbols icuSymbols) {
|
||||
this.icuSymbols = icuSymbols;
|
||||
infinity = icuSymbols.getInfinity();
|
||||
NaN = icuSymbols.getNaN();
|
||||
this.locale = locale;
|
||||
currencySymbol = icuSymbols.getCurrencySymbol();
|
||||
intlCurrencySymbol = icuSymbols.getInternationalCurrencySymbol();
|
||||
if (locale.getCountry().length() == 0) {
|
||||
currency = Currency.getInstance("XXX"); //$NON-NLS-1$
|
||||
} else {
|
||||
currency = Currency.getInstance(locale);
|
||||
}
|
||||
patternChars = new char[10];
|
||||
patternChars[ZeroDigit] = icuSymbols.getZeroDigit();
|
||||
patternChars[Digit] = icuSymbols.getDigit();
|
||||
patternChars[DecimalSeparator] = icuSymbols.getDecimalSeparator();
|
||||
patternChars[GroupingSeparator] = icuSymbols.getGroupingSeparator();
|
||||
patternChars[PatternSeparator] = icuSymbols.getPatternSeparator();
|
||||
patternChars[Percent] = icuSymbols.getPercent();
|
||||
patternChars[PerMill] = icuSymbols.getPerMill();
|
||||
patternChars[Exponent] = icuSymbols.getExponentSeparator().charAt(0);
|
||||
patternChars[MonetaryDecimalSeparator] = icuSymbols
|
||||
.getMonetaryDecimalSeparator();
|
||||
patternChars[MinusSign] = icuSymbols.getMinusSign();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() {
|
||||
try {
|
||||
DecimalFormatSymbols symbols = (DecimalFormatSymbols) super.clone();
|
||||
symbols.patternChars = patternChars.clone();
|
||||
return symbols;
|
||||
} catch (CloneNotSupportedException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (this == object) {
|
||||
return true;
|
||||
}
|
||||
if (!(object instanceof DecimalFormatSymbols)) {
|
||||
return false;
|
||||
}
|
||||
DecimalFormatSymbols obj = (DecimalFormatSymbols) object;
|
||||
return Arrays.equals(patternChars, obj.patternChars)
|
||||
&& infinity.equals(obj.infinity) && NaN.equals(obj.NaN)
|
||||
&& currencySymbol.equals(obj.currencySymbol)
|
||||
&& intlCurrencySymbol.equals(obj.intlCurrencySymbol);
|
||||
}
|
||||
|
||||
public Currency getCurrency() {
|
||||
return currency;
|
||||
}
|
||||
|
||||
public String getInternationalCurrencySymbol() {
|
||||
return intlCurrencySymbol;
|
||||
}
|
||||
|
||||
public String getCurrencySymbol() {
|
||||
return currencySymbol;
|
||||
}
|
||||
|
||||
public char getDecimalSeparator() {
|
||||
return patternChars[DecimalSeparator];
|
||||
}
|
||||
|
||||
public char getDigit() {
|
||||
return patternChars[Digit];
|
||||
}
|
||||
|
||||
public char getGroupingSeparator() {
|
||||
return patternChars[GroupingSeparator];
|
||||
}
|
||||
|
||||
public String getInfinity() {
|
||||
return infinity;
|
||||
}
|
||||
|
||||
String getLocalPatternChars() {
|
||||
// Don't include the MonetaryDecimalSeparator or the MinusSign
|
||||
return new String(patternChars, 0, patternChars.length - 2);
|
||||
}
|
||||
|
||||
public char getMinusSign() {
|
||||
return patternChars[MinusSign];
|
||||
}
|
||||
|
||||
public char getMonetaryDecimalSeparator() {
|
||||
return patternChars[MonetaryDecimalSeparator];
|
||||
}
|
||||
|
||||
public String getNaN() {
|
||||
return NaN;
|
||||
}
|
||||
|
||||
public char getPatternSeparator() {
|
||||
return patternChars[PatternSeparator];
|
||||
}
|
||||
|
||||
public char getPercent() {
|
||||
return patternChars[Percent];
|
||||
}
|
||||
|
||||
public char getPerMill() {
|
||||
return patternChars[PerMill];
|
||||
}
|
||||
|
||||
public char getZeroDigit() {
|
||||
return patternChars[ZeroDigit];
|
||||
}
|
||||
|
||||
char getExponential() {
|
||||
return patternChars[Exponent];
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return new String(patternChars).hashCode() + infinity.hashCode()
|
||||
+ NaN.hashCode() + currencySymbol.hashCode()
|
||||
+ intlCurrencySymbol.hashCode();
|
||||
}
|
||||
|
||||
public void setCurrency(Currency currency) {
|
||||
if (currency == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
if (currency == this.currency) {
|
||||
return;
|
||||
}
|
||||
this.currency = currency;
|
||||
intlCurrencySymbol = currency.getCurrencyCode();
|
||||
currencySymbol = currency.getSymbol(locale);
|
||||
}
|
||||
|
||||
public void setInternationalCurrencySymbol(String value) {
|
||||
if (value == null) {
|
||||
currency = null;
|
||||
intlCurrencySymbol = null;
|
||||
return;
|
||||
}
|
||||
|
||||
if (value.equals(intlCurrencySymbol)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
currency = Currency.getInstance(value);
|
||||
currencySymbol = currency.getSymbol(locale);
|
||||
} catch (IllegalArgumentException e) {
|
||||
currency = null;
|
||||
}
|
||||
intlCurrencySymbol = value;
|
||||
}
|
||||
|
||||
public void setCurrencySymbol(String value) {
|
||||
currencySymbol = value;
|
||||
}
|
||||
|
||||
public void setDecimalSeparator(char value) {
|
||||
patternChars[DecimalSeparator] = value;
|
||||
}
|
||||
|
||||
public void setDigit(char value) {
|
||||
patternChars[Digit] = value;
|
||||
}
|
||||
|
||||
public void setGroupingSeparator(char value) {
|
||||
patternChars[GroupingSeparator] = value;
|
||||
}
|
||||
|
||||
public void setInfinity(String value) {
|
||||
infinity = value;
|
||||
}
|
||||
|
||||
public void setMinusSign(char value) {
|
||||
patternChars[MinusSign] = value;
|
||||
}
|
||||
|
||||
public void setMonetaryDecimalSeparator(char value) {
|
||||
patternChars[MonetaryDecimalSeparator] = value;
|
||||
}
|
||||
|
||||
public void setNaN(String value) {
|
||||
NaN = value;
|
||||
}
|
||||
|
||||
public void setPatternSeparator(char value) {
|
||||
patternChars[PatternSeparator] = value;
|
||||
}
|
||||
|
||||
public void setPercent(char value) {
|
||||
patternChars[Percent] = value;
|
||||
}
|
||||
|
||||
public void setPerMill(char value) {
|
||||
patternChars[PerMill] = value;
|
||||
}
|
||||
|
||||
public void setZeroDigit(char value) {
|
||||
patternChars[ZeroDigit] = value;
|
||||
}
|
||||
|
||||
void setExponential(char value) {
|
||||
patternChars[Exponent] = value;
|
||||
}
|
||||
|
||||
TLocale getLocale(){
|
||||
return locale;
|
||||
}
|
||||
|
||||
com.ibm.icu.text.DecimalFormatSymbols getIcuSymbols() {
|
||||
return icuSymbols;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* 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.teavm.classlib.java.text;
|
||||
|
||||
public class FieldPosition {
|
||||
private int myField, beginIndex, endIndex;
|
||||
private Format.Field myAttribute;
|
||||
|
||||
public FieldPosition(int field) {
|
||||
myField = field;
|
||||
}
|
||||
|
||||
public FieldPosition(Format.Field attribute) {
|
||||
myAttribute = attribute;
|
||||
myField = -1;
|
||||
}
|
||||
|
||||
public FieldPosition(Format.Field attribute, int field) {
|
||||
myAttribute = attribute;
|
||||
myField = field;
|
||||
}
|
||||
|
||||
void clear() {
|
||||
beginIndex = endIndex = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (!(object instanceof FieldPosition)) {
|
||||
return false;
|
||||
}
|
||||
FieldPosition pos = (FieldPosition) object;
|
||||
return myField == pos.myField && myAttribute == pos.myAttribute && beginIndex == pos.beginIndex &&
|
||||
endIndex == pos.endIndex;
|
||||
}
|
||||
|
||||
public int getBeginIndex() {
|
||||
return beginIndex;
|
||||
}
|
||||
|
||||
public int getEndIndex() {
|
||||
return endIndex;
|
||||
}
|
||||
|
||||
public int getField() {
|
||||
return myField;
|
||||
}
|
||||
|
||||
public Format.Field getFieldAttribute() {
|
||||
return myAttribute;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int attributeHash = (myAttribute == null) ? 0 : myAttribute.hashCode();
|
||||
return attributeHash + myField * 10 + beginIndex * 100 + endIndex;
|
||||
}
|
||||
|
||||
public void setBeginIndex(int index) {
|
||||
beginIndex = index;
|
||||
}
|
||||
|
||||
public void setEndIndex(int index) {
|
||||
endIndex = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getName() + "[attribute=" + myAttribute + ", field=" + myField + ", beginIndex=" +
|
||||
beginIndex + ", endIndex=" + endIndex + "]";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,137 @@
|
|||
/*
|
||||
* 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.teavm.classlib.java.text;
|
||||
|
||||
import org.teavm.classlib.java.io.TSerializable;
|
||||
import org.teavm.classlib.java.lang.TCloneable;
|
||||
|
||||
public abstract class Format implements TSerializable, TCloneable {
|
||||
public Format() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() {
|
||||
try {
|
||||
return super.clone();
|
||||
} catch (CloneNotSupportedException e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
String convertPattern(String template, String fromChars, String toChars, boolean check) {
|
||||
if (!check && fromChars.equals(toChars)) {
|
||||
return template;
|
||||
}
|
||||
boolean quote = false;
|
||||
StringBuilder output = new StringBuilder();
|
||||
int length = template.length();
|
||||
for (int i = 0; i < length; i++) {
|
||||
int index;
|
||||
char next = template.charAt(i);
|
||||
if (next == '\'') {
|
||||
quote = !quote;
|
||||
}
|
||||
if (!quote && (index = fromChars.indexOf(next)) != -1) {
|
||||
output.append(toChars.charAt(index));
|
||||
} else if (check && !quote && ((next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'))) {
|
||||
throw new IllegalArgumentException("Invalid pattern char" + next + " in " + template);
|
||||
} else {
|
||||
output.append(next);
|
||||
}
|
||||
}
|
||||
if (quote) {
|
||||
throw new IllegalArgumentException("Unterminated quote");
|
||||
}
|
||||
return output.toString();
|
||||
}
|
||||
|
||||
public final String format(Object object) {
|
||||
return format(object, new StringBuffer(), new FieldPosition(0)).toString();
|
||||
}
|
||||
|
||||
public abstract StringBuffer format(Object object, StringBuffer buffer, FieldPosition field);
|
||||
|
||||
public AttributedCharacterIterator formatToCharacterIterator(Object object) {
|
||||
return new AttributedString(format(object)).getIterator();
|
||||
}
|
||||
|
||||
public Object parseObject(String string) throws ParseException {
|
||||
ParsePosition position = new ParsePosition(0);
|
||||
Object result = parseObject(string, position);
|
||||
if (position.getIndex() == 0) {
|
||||
throw new ParseException("Format.parseObject(String) parse failure", position.getErrorIndex());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public abstract Object parseObject(String string, ParsePosition position);
|
||||
|
||||
static boolean upTo(String string, ParsePosition position, StringBuffer buffer, char stop) {
|
||||
int index = position.getIndex(), length = string.length();
|
||||
boolean lastQuote = false, quote = false;
|
||||
while (index < length) {
|
||||
char ch = string.charAt(index++);
|
||||
if (ch == '\'') {
|
||||
if (lastQuote) {
|
||||
buffer.append('\'');
|
||||
}
|
||||
quote = !quote;
|
||||
lastQuote = true;
|
||||
} else if (ch == stop && !quote) {
|
||||
position.setIndex(index);
|
||||
return true;
|
||||
} else {
|
||||
lastQuote = false;
|
||||
buffer.append(ch);
|
||||
}
|
||||
}
|
||||
position.setIndex(index);
|
||||
return false;
|
||||
}
|
||||
|
||||
static boolean upToWithQuotes(String string, ParsePosition position, StringBuffer buffer, char stop, char start) {
|
||||
int index = position.getIndex(), length = string.length(), count = 1;
|
||||
boolean quote = false;
|
||||
while (index < length) {
|
||||
char ch = string.charAt(index++);
|
||||
if (ch == '\'') {
|
||||
quote = !quote;
|
||||
}
|
||||
if (!quote) {
|
||||
if (ch == stop) {
|
||||
count--;
|
||||
}
|
||||
if (count == 0) {
|
||||
position.setIndex(index);
|
||||
return true;
|
||||
}
|
||||
if (ch == start) {
|
||||
count++;
|
||||
}
|
||||
}
|
||||
buffer.append(ch);
|
||||
}
|
||||
throw new IllegalArgumentException("Unmatched braces in the pattern");
|
||||
}
|
||||
|
||||
public static class Field extends AttributedCharacterIterator.Attribute {
|
||||
protected Field(String fieldName) {
|
||||
super(fieldName);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,263 @@
|
|||
/*
|
||||
* 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.teavm.classlib.java.text;
|
||||
|
||||
import org.teavm.classlib.java.util.TLocale;
|
||||
|
||||
public abstract class NumberFormat extends Format {
|
||||
|
||||
private static final long serialVersionUID = -2308460125733713944L;
|
||||
public static final int INTEGER_FIELD = 0;
|
||||
public static final int FRACTION_FIELD = 1;
|
||||
|
||||
private boolean groupingUsed = true, parseIntegerOnly = false;
|
||||
|
||||
private int maximumIntegerDigits = 40, minimumIntegerDigits = 1,
|
||||
maximumFractionDigits = 3, minimumFractionDigits = 0;
|
||||
|
||||
public NumberFormat() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() {
|
||||
return super.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (object == this) {
|
||||
return true;
|
||||
}
|
||||
if (!(object instanceof NumberFormat)) {
|
||||
return false;
|
||||
}
|
||||
NumberFormat obj = (NumberFormat) object;
|
||||
return groupingUsed == obj.groupingUsed
|
||||
&& parseIntegerOnly == obj.parseIntegerOnly
|
||||
&& maximumFractionDigits == obj.maximumFractionDigits
|
||||
&& maximumIntegerDigits == obj.maximumIntegerDigits
|
||||
&& minimumFractionDigits == obj.minimumFractionDigits
|
||||
&& minimumIntegerDigits == obj.minimumIntegerDigits;
|
||||
}
|
||||
|
||||
public final String format(double value) {
|
||||
return format(value, new StringBuffer(), new FieldPosition(0))
|
||||
.toString();
|
||||
}
|
||||
|
||||
public abstract StringBuffer format(double value, StringBuffer buffer,
|
||||
FieldPosition field);
|
||||
|
||||
public final String format(long value) {
|
||||
return format(value, new StringBuffer(), new FieldPosition(0))
|
||||
.toString();
|
||||
}
|
||||
public abstract StringBuffer format(long value, StringBuffer buffer,
|
||||
FieldPosition field);
|
||||
|
||||
@Override
|
||||
public StringBuffer format(Object object, StringBuffer buffer,
|
||||
FieldPosition field) {
|
||||
if (object instanceof Number) {
|
||||
double dv = ((Number) object).doubleValue();
|
||||
long lv = ((Number) object).longValue();
|
||||
if (dv == lv) {
|
||||
return format(lv, buffer, field);
|
||||
}
|
||||
return format(dv, buffer, field);
|
||||
}
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
public static TLocale[] getAvailableLocales() {
|
||||
return TLocale.getAvailableLocales();
|
||||
}
|
||||
|
||||
public Currency getCurrency() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public final static NumberFormat getCurrencyInstance() {
|
||||
return getCurrencyInstance(TLocale.getDefault());
|
||||
}
|
||||
|
||||
public static NumberFormat getCurrencyInstance(TLocale locale) {
|
||||
com.ibm.icu.text.DecimalFormat icuFormat = (com.ibm.icu.text.DecimalFormat) com.ibm.icu.text.NumberFormat
|
||||
.getCurrencyInstance(locale);
|
||||
String pattern = icuFormat.toPattern();
|
||||
return new DecimalFormat(pattern, new DecimalFormatSymbols(locale));
|
||||
}
|
||||
|
||||
public final static NumberFormat getIntegerInstance() {
|
||||
return getIntegerInstance(TLocale.getDefault());
|
||||
}
|
||||
|
||||
public static NumberFormat getIntegerInstance(TLocale locale) {
|
||||
com.ibm.icu.text.DecimalFormat icuFormat = (com.ibm.icu.text.DecimalFormat) com.ibm.icu.text.NumberFormat
|
||||
.getIntegerInstance(locale);
|
||||
String pattern = icuFormat.toPattern();
|
||||
DecimalFormat format = new DecimalFormat(pattern, new DecimalFormatSymbols(locale));
|
||||
format.setParseIntegerOnly(true);
|
||||
return format;
|
||||
|
||||
}
|
||||
|
||||
public final static NumberFormat getInstance() {
|
||||
return getNumberInstance();
|
||||
}
|
||||
|
||||
public static NumberFormat getInstance(TLocale locale) {
|
||||
return getNumberInstance(locale);
|
||||
}
|
||||
|
||||
public int getMaximumFractionDigits() {
|
||||
return maximumFractionDigits;
|
||||
}
|
||||
|
||||
public int getMaximumIntegerDigits() {
|
||||
return maximumIntegerDigits;
|
||||
}
|
||||
|
||||
public int getMinimumFractionDigits() {
|
||||
return minimumFractionDigits;
|
||||
}
|
||||
|
||||
public int getMinimumIntegerDigits() {
|
||||
return minimumIntegerDigits;
|
||||
}
|
||||
|
||||
public final static NumberFormat getNumberInstance() {
|
||||
return getNumberInstance(TLocale.getDefault());
|
||||
}
|
||||
|
||||
public static NumberFormat getNumberInstance(TLocale locale) {
|
||||
com.ibm.icu.text.DecimalFormat icuFormat = (com.ibm.icu.text.DecimalFormat) com.ibm.icu.text.NumberFormat
|
||||
.getNumberInstance(locale);
|
||||
String pattern = icuFormat.toPattern();
|
||||
return new DecimalFormat(pattern, new DecimalFormatSymbols(locale, icuFormat.getDecimalFormatSymbols()), icuFormat);
|
||||
}
|
||||
|
||||
public final static NumberFormat getPercentInstance() {
|
||||
return getPercentInstance(TLocale.getDefault());
|
||||
}
|
||||
|
||||
public static NumberFormat getPercentInstance(TLocale locale) {
|
||||
com.ibm.icu.text.DecimalFormat icuFormat = (com.ibm.icu.text.DecimalFormat) com.ibm.icu.text.NumberFormat
|
||||
.getPercentInstance(locale);
|
||||
String pattern = icuFormat.toPattern();
|
||||
return new DecimalFormat(pattern, new DecimalFormatSymbols(locale));
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (groupingUsed ? 1231 : 1237) + (parseIntegerOnly ? 1231 : 1237)
|
||||
+ maximumFractionDigits + maximumIntegerDigits
|
||||
+ minimumFractionDigits + minimumIntegerDigits;
|
||||
}
|
||||
|
||||
public boolean isGroupingUsed() {
|
||||
return groupingUsed;
|
||||
}
|
||||
|
||||
public boolean isParseIntegerOnly() {
|
||||
return parseIntegerOnly;
|
||||
}
|
||||
|
||||
public Number parse(String string) throws ParseException {
|
||||
ParsePosition pos = new ParsePosition(0);
|
||||
Number number = parse(string, pos);
|
||||
if (pos.getIndex() == 0) {
|
||||
throw new ParseException("Unparseable number: " + string, pos.getErrorIndex());
|
||||
}
|
||||
return number;
|
||||
}
|
||||
|
||||
public abstract Number parse(String string, ParsePosition position);
|
||||
|
||||
@Override
|
||||
public final Object parseObject(String string, ParsePosition position) {
|
||||
if (position == null) {
|
||||
throw new NullPointerException("position is null");
|
||||
}
|
||||
|
||||
try {
|
||||
return parse(string, position);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public void setCurrency(Currency currency) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public void setGroupingUsed(boolean value) {
|
||||
groupingUsed = value;
|
||||
}
|
||||
|
||||
public void setMaximumFractionDigits(int value) {
|
||||
maximumFractionDigits = value < 0 ? 0 : value;
|
||||
if (maximumFractionDigits < minimumFractionDigits) {
|
||||
minimumFractionDigits = maximumFractionDigits;
|
||||
}
|
||||
}
|
||||
|
||||
public void setMaximumIntegerDigits(int value) {
|
||||
maximumIntegerDigits = value < 0 ? 0 : value;
|
||||
if (maximumIntegerDigits < minimumIntegerDigits) {
|
||||
minimumIntegerDigits = maximumIntegerDigits;
|
||||
}
|
||||
}
|
||||
|
||||
public void setMinimumFractionDigits(int value) {
|
||||
minimumFractionDigits = value < 0 ? 0 : value;
|
||||
if (maximumFractionDigits < minimumFractionDigits) {
|
||||
maximumFractionDigits = minimumFractionDigits;
|
||||
}
|
||||
}
|
||||
|
||||
public void setMinimumIntegerDigits(int value) {
|
||||
minimumIntegerDigits = value < 0 ? 0 : value;
|
||||
if (maximumIntegerDigits < minimumIntegerDigits) {
|
||||
maximumIntegerDigits = minimumIntegerDigits;
|
||||
}
|
||||
}
|
||||
|
||||
public void setParseIntegerOnly(boolean value) {
|
||||
parseIntegerOnly = value;
|
||||
}
|
||||
|
||||
|
||||
public static class Field extends Format.Field {
|
||||
public static final Field SIGN = new Field("sign");
|
||||
public static final Field INTEGER = new Field("integer");
|
||||
public static final Field FRACTION = new Field("fraction");
|
||||
public static final Field EXPONENT = new Field("exponent");
|
||||
public static final Field EXPONENT_SIGN = new Field("exponent sign");
|
||||
public static final Field EXPONENT_SYMBOL = new Field("exponent symbol");
|
||||
public static final Field DECIMAL_SEPARATOR = new Field("decimal separator");
|
||||
public static final Field GROUPING_SEPARATOR = new Field("grouping separator");
|
||||
public static final Field PERCENT = new Field("percent");
|
||||
public static final Field PERMILLE = new Field("per mille");
|
||||
public static final Field CURRENCY = new Field("currency");
|
||||
|
||||
protected Field(String fieldName) {
|
||||
super(fieldName);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/*
|
||||
* 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.teavm.classlib.java.text;
|
||||
|
||||
/**
|
||||
* Thrown when the string being parsed is not in the correct form.
|
||||
*/
|
||||
public class ParseException extends Exception {
|
||||
|
||||
private static final long serialVersionUID = 2703218443322787634L;
|
||||
|
||||
private int errorOffset;
|
||||
|
||||
/**
|
||||
* Constructs a new instance of this class with its stack trace, detail
|
||||
* message and the location of the error filled in.
|
||||
*
|
||||
* @param detailMessage
|
||||
* the detail message for this exception.
|
||||
* @param location
|
||||
* the index at which the parse exception occurred.
|
||||
*/
|
||||
public ParseException(String detailMessage, int location) {
|
||||
super(detailMessage);
|
||||
errorOffset = location;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index at which this parse exception occurred.
|
||||
*
|
||||
* @return the location of this exception in the parsed string.
|
||||
*/
|
||||
public int getErrorOffset() {
|
||||
return errorOffset;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/*
|
||||
* 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.teavm.classlib.java.text;
|
||||
|
||||
public class ParsePosition {
|
||||
|
||||
private int currentPosition, errorIndex = -1;
|
||||
|
||||
public ParsePosition(int index) {
|
||||
currentPosition = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (!(object instanceof ParsePosition)) {
|
||||
return false;
|
||||
}
|
||||
ParsePosition pos = (ParsePosition) object;
|
||||
return currentPosition == pos.currentPosition && errorIndex == pos.errorIndex;
|
||||
}
|
||||
|
||||
public int getErrorIndex() {
|
||||
return errorIndex;
|
||||
}
|
||||
|
||||
public int getIndex() {
|
||||
return currentPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return currentPosition + errorIndex;
|
||||
}
|
||||
|
||||
public void setErrorIndex(int index) {
|
||||
errorIndex = index;
|
||||
}
|
||||
|
||||
public void setIndex(int index) {
|
||||
currentPosition = index;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return getClass().getName() + "[index=" + currentPosition + ", errorIndex=" + errorIndex + "]";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,597 @@
|
|||
/*
|
||||
* 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.teavm.classlib.java.text;
|
||||
|
||||
import org.teavm.classlib.java.util.*;
|
||||
|
||||
public class SimpleDateFormat extends DateFormat {
|
||||
|
||||
private static final long serialVersionUID = 4774881970558875024L;
|
||||
|
||||
private static final String patternChars = "GyMdkHmsSEDFwWahKzYeugAZvcLQqV"; //$NON-NLS-1$
|
||||
|
||||
private String pattern;
|
||||
|
||||
private DateFormatSymbols formatData;
|
||||
|
||||
transient private int creationYear;
|
||||
|
||||
private Date defaultCenturyStart;
|
||||
|
||||
private transient String tzId;
|
||||
|
||||
private transient com.ibm.icu.text.SimpleDateFormat icuFormat;
|
||||
|
||||
public SimpleDateFormat() {
|
||||
this(TLocale.getDefault());
|
||||
icuFormat = new com.ibm.icu.text.SimpleDateFormat();
|
||||
icuFormat.setTimeZone(com.ibm.icu.util.TimeZone.getTimeZone(tzId));
|
||||
pattern = (String) getInternalField("pattern", icuFormat);
|
||||
formatData = new DateFormatSymbols(TLocale.getDefault());
|
||||
}
|
||||
|
||||
public SimpleDateFormat(String pattern) {
|
||||
this(pattern, TLocale.getDefault());
|
||||
}
|
||||
|
||||
private void validateFormat(char format) {
|
||||
int index = patternChars.indexOf(format);
|
||||
if (index == -1) {
|
||||
throw new IllegalArgumentException("Unknown pattern character - " + format);
|
||||
}
|
||||
}
|
||||
|
||||
private void validatePattern(String template) {
|
||||
boolean quote = false;
|
||||
int next, last = -1, count = 0;
|
||||
|
||||
final int patternLength = template.length();
|
||||
for (int i = 0; i < patternLength; i++) {
|
||||
next = (template.charAt(i));
|
||||
if (next == '\'') {
|
||||
if (count > 0) {
|
||||
validateFormat((char) last);
|
||||
count = 0;
|
||||
}
|
||||
if (last == next) {
|
||||
last = -1;
|
||||
} else {
|
||||
last = next;
|
||||
}
|
||||
quote = !quote;
|
||||
continue;
|
||||
}
|
||||
if (!quote && (last == next || (next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'))) {
|
||||
if (last == next) {
|
||||
count++;
|
||||
} else {
|
||||
if (count > 0) {
|
||||
validateFormat((char) last);
|
||||
}
|
||||
last = next;
|
||||
count = 1;
|
||||
}
|
||||
} else {
|
||||
if (count > 0) {
|
||||
validateFormat((char) last);
|
||||
count = 0;
|
||||
}
|
||||
last = -1;
|
||||
}
|
||||
}
|
||||
if (count > 0) {
|
||||
validateFormat((char) last);
|
||||
}
|
||||
|
||||
if (quote) {
|
||||
throw new IllegalArgumentException("Unterminated quote");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public SimpleDateFormat(String template, DateFormatSymbols value) {
|
||||
this(TLocale.getDefault());
|
||||
validatePattern(template);
|
||||
icuFormat = new com.ibm.icu.text.SimpleDateFormat(template, Locale.getDefault());
|
||||
icuFormat.setTimeZone(com.ibm.icu.util.TimeZone.getTimeZone(tzId));
|
||||
pattern = template;
|
||||
formatData = (DateFormatSymbols) value.clone();
|
||||
}
|
||||
|
||||
private void copySymbols(DateFormatSymbols value, com.ibm.icu.text.DateFormatSymbols icuSymbols) {
|
||||
icuSymbols.setAmPmStrings(value.getAmPmStrings());
|
||||
icuSymbols.setEras(value.getEras());
|
||||
icuSymbols.setLocalPatternChars(value.getLocalPatternChars());
|
||||
icuSymbols.setMonths(value.getMonths());
|
||||
icuSymbols.setShortMonths(value.getShortMonths());
|
||||
icuSymbols.setShortWeekdays(value.getShortWeekdays());
|
||||
icuSymbols.setWeekdays(value.getWeekdays());
|
||||
icuSymbols.setZoneStrings(value.getZoneStrings());
|
||||
}
|
||||
|
||||
public SimpleDateFormat(String template, TLocale locale) {
|
||||
this(locale);
|
||||
validatePattern(template);
|
||||
icuFormat = new com.ibm.icu.text.SimpleDateFormat(template, locale);
|
||||
icuFormat.setTimeZone(com.ibm.icu.util.TimeZone.getTimeZone(tzId));
|
||||
pattern = template;
|
||||
formatData = new DateFormatSymbols(locale, icuFormat.getDateFormatSymbols());
|
||||
}
|
||||
|
||||
SimpleDateFormat(TLocale locale, com.ibm.icu.text.SimpleDateFormat icuFormat) {
|
||||
this(locale);
|
||||
this.icuFormat = icuFormat;
|
||||
this.icuFormat.setTimeZone(com.ibm.icu.util.TimeZone.getTimeZone(tzId));
|
||||
pattern = (String) Format.getInternalField("pattern", icuFormat);
|
||||
formatData = new DateFormatSymbols(locale);
|
||||
}
|
||||
|
||||
private SimpleDateFormat(TLocale locale) {
|
||||
numberFormat = NumberFormat.getInstance(locale);
|
||||
numberFormat.setParseIntegerOnly(true);
|
||||
numberFormat.setGroupingUsed(false);
|
||||
calendar = new GregorianCalendar(locale);
|
||||
calendar.add(Calendar.YEAR, -80);
|
||||
tzId = calendar.getTimeZone().getID();
|
||||
creationYear = calendar.get(Calendar.YEAR);
|
||||
defaultCenturyStart = calendar.getTime();
|
||||
}
|
||||
|
||||
public void applyLocalizedPattern(String template) {
|
||||
icuFormat.applyLocalizedPattern(template);
|
||||
pattern = icuFormat.toPattern();
|
||||
}
|
||||
|
||||
public void applyPattern(String template) {
|
||||
validatePattern(template);
|
||||
/*
|
||||
* ICU spec explicitly mentions that "ICU interprets a single 'y'
|
||||
* differently than Java." We need to do a trick here to follow Java
|
||||
* spec.
|
||||
*/
|
||||
String templateForICU = patternForICU(template);
|
||||
icuFormat.applyPattern(templateForICU);
|
||||
pattern = template;
|
||||
}
|
||||
|
||||
@SuppressWarnings("nls")
|
||||
private String patternForICU(String p) {
|
||||
String[] subPatterns = p.split("'");
|
||||
boolean quote = false;
|
||||
boolean first = true;
|
||||
StringBuilder result = new StringBuilder();
|
||||
for (String subPattern : subPatterns) {
|
||||
if (!quote) {
|
||||
// replace 'y' with 'yy' for ICU to follow Java spec
|
||||
result.append((first ? "" : "'") + subPattern.replaceAll("(?<!y)y(?!y)", "yy"));
|
||||
first = false;
|
||||
} else {
|
||||
result.append("'" + subPattern);
|
||||
}
|
||||
quote = !quote;
|
||||
}
|
||||
if (p.endsWith("'")) {
|
||||
result.append("'");
|
||||
}
|
||||
return result.toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object clone() {
|
||||
SimpleDateFormat clone = (SimpleDateFormat) super.clone();
|
||||
clone.formatData = (DateFormatSymbols) formatData.clone();
|
||||
clone.defaultCenturyStart = new Date(defaultCenturyStart.getTime());
|
||||
clone.tzId = tzId;
|
||||
return clone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object object) {
|
||||
if (this == object) {
|
||||
return true;
|
||||
}
|
||||
if (!(object instanceof SimpleDateFormat)) {
|
||||
return false;
|
||||
}
|
||||
SimpleDateFormat simple = (SimpleDateFormat) object;
|
||||
return super.equals(object) && pattern.equals(simple.pattern) && formatData.equals(simple.formatData);
|
||||
}
|
||||
|
||||
@Override
|
||||
public AttributedCharacterIterator formatToCharacterIterator(Object object) {
|
||||
if (object == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
if (object instanceof Date) {
|
||||
return formatToCharacterIteratorImpl((Date) object);
|
||||
}
|
||||
if (object instanceof Number) {
|
||||
return formatToCharacterIteratorImpl(new Date(((Number) object).longValue()));
|
||||
}
|
||||
throw new IllegalArgumentException();
|
||||
|
||||
}
|
||||
|
||||
private AttributedCharacterIterator formatToCharacterIteratorImpl(Date date) {
|
||||
StringBuffer buffer = new StringBuffer();
|
||||
TList<FieldPosition> fields = new TArrayList<>();
|
||||
|
||||
// format the date, and find fields
|
||||
formatImpl(date, buffer, null, fields);
|
||||
|
||||
// create and AttributedString with the formatted buffer
|
||||
AttributedString as = new AttributedString(buffer.toString());
|
||||
|
||||
// add DateFormat field attributes to the AttributedString
|
||||
for (int i = 0; i < fields.size(); i++) {
|
||||
FieldPosition pos = fields.get(i);
|
||||
Format.Field attribute = pos.getFieldAttribute();
|
||||
as.addAttribute(attribute, attribute, pos.getBeginIndex(), pos.getEndIndex());
|
||||
}
|
||||
|
||||
// return the CharacterIterator from AttributedString
|
||||
return as.getIterator();
|
||||
}
|
||||
|
||||
private StringBuffer formatImpl(Date date, StringBuffer buffer, FieldPosition field, TList<FieldPosition> fields) {
|
||||
|
||||
boolean quote = false;
|
||||
int next, last = -1, count = 0;
|
||||
calendar.setTime(date);
|
||||
if (field != null) {
|
||||
field.clear();
|
||||
}
|
||||
|
||||
final int patternLength = pattern.length();
|
||||
for (int i = 0; i < patternLength; i++) {
|
||||
next = (pattern.charAt(i));
|
||||
if (next == '\'') {
|
||||
if (count > 0) {
|
||||
append(buffer, field, fields, (char) last, count);
|
||||
count = 0;
|
||||
}
|
||||
if (last == next) {
|
||||
buffer.append('\'');
|
||||
last = -1;
|
||||
} else {
|
||||
last = next;
|
||||
}
|
||||
quote = !quote;
|
||||
continue;
|
||||
}
|
||||
if (!quote && (last == next || (next >= 'a' && next <= 'z') || (next >= 'A' && next <= 'Z'))) {
|
||||
if (last == next) {
|
||||
count++;
|
||||
} else {
|
||||
if (count > 0) {
|
||||
append(buffer, field, fields, (char) last, count);
|
||||
}
|
||||
last = next;
|
||||
count = 1;
|
||||
}
|
||||
} else {
|
||||
if (count > 0) {
|
||||
append(buffer, field, fields, (char) last, count);
|
||||
count = 0;
|
||||
}
|
||||
last = -1;
|
||||
buffer.append((char) next);
|
||||
}
|
||||
}
|
||||
if (count > 0) {
|
||||
append(buffer, field, fields, (char) last, count);
|
||||
}
|
||||
return buffer;
|
||||
}
|
||||
|
||||
private void append(StringBuffer buffer, FieldPosition position, TList<FieldPosition> fields, char format, int count) {
|
||||
int field = -1;
|
||||
int index = patternChars.indexOf(format);
|
||||
if (index == -1) {
|
||||
throw new IllegalArgumentException("Unknown pattern character - " + format);
|
||||
}
|
||||
|
||||
int beginPosition = buffer.length();
|
||||
Field dateFormatField = null;
|
||||
switch (index) {
|
||||
case ERA_FIELD:
|
||||
dateFormatField = Field.ERA;
|
||||
buffer.append(formatData.eras[calendar.get(Calendar.ERA)]);
|
||||
break;
|
||||
case YEAR_FIELD:
|
||||
dateFormatField = Field.YEAR;
|
||||
int year = calendar.get(Calendar.YEAR);
|
||||
if (count < 4) {
|
||||
appendNumber(buffer, 2, year % 100);
|
||||
} else {
|
||||
appendNumber(buffer, count, year);
|
||||
}
|
||||
break;
|
||||
case MONTH_FIELD:
|
||||
dateFormatField = Field.MONTH;
|
||||
int month = calendar.get(Calendar.MONTH);
|
||||
if (count <= 2) {
|
||||
appendNumber(buffer, count, month + 1);
|
||||
} else if (count == 3) {
|
||||
buffer.append(formatData.shortMonths[month]);
|
||||
} else {
|
||||
buffer.append(formatData.months[month]);
|
||||
}
|
||||
break;
|
||||
case DATE_FIELD:
|
||||
dateFormatField = Field.DAY_OF_MONTH;
|
||||
field = Calendar.DATE;
|
||||
break;
|
||||
case HOUR_OF_DAY1_FIELD: // k
|
||||
dateFormatField = Field.HOUR_OF_DAY1;
|
||||
int hour = calendar.get(Calendar.HOUR_OF_DAY);
|
||||
appendNumber(buffer, count, hour == 0 ? 24 : hour);
|
||||
break;
|
||||
case HOUR_OF_DAY0_FIELD: // H
|
||||
dateFormatField = Field.HOUR_OF_DAY0;
|
||||
field = Calendar.HOUR_OF_DAY;
|
||||
break;
|
||||
case MINUTE_FIELD:
|
||||
dateFormatField = Field.MINUTE;
|
||||
field = Calendar.MINUTE;
|
||||
break;
|
||||
case SECOND_FIELD:
|
||||
dateFormatField = Field.SECOND;
|
||||
field = Calendar.SECOND;
|
||||
break;
|
||||
case MILLISECOND_FIELD:
|
||||
dateFormatField = Field.MILLISECOND;
|
||||
int value = calendar.get(Calendar.MILLISECOND);
|
||||
appendNumber(buffer, count, value);
|
||||
break;
|
||||
case DAY_OF_WEEK_FIELD:
|
||||
dateFormatField = Field.DAY_OF_WEEK;
|
||||
int day = calendar.get(Calendar.DAY_OF_WEEK);
|
||||
if (count < 4) {
|
||||
buffer.append(formatData.shortWeekdays[day]);
|
||||
} else {
|
||||
buffer.append(formatData.weekdays[day]);
|
||||
}
|
||||
break;
|
||||
case DAY_OF_YEAR_FIELD:
|
||||
dateFormatField = Field.DAY_OF_YEAR;
|
||||
field = Calendar.DAY_OF_YEAR;
|
||||
break;
|
||||
case DAY_OF_WEEK_IN_MONTH_FIELD:
|
||||
dateFormatField = Field.DAY_OF_WEEK_IN_MONTH;
|
||||
field = Calendar.DAY_OF_WEEK_IN_MONTH;
|
||||
break;
|
||||
case WEEK_OF_YEAR_FIELD:
|
||||
dateFormatField = Field.WEEK_OF_YEAR;
|
||||
field = Calendar.WEEK_OF_YEAR;
|
||||
break;
|
||||
case WEEK_OF_MONTH_FIELD:
|
||||
dateFormatField = Field.WEEK_OF_MONTH;
|
||||
field = Calendar.WEEK_OF_MONTH;
|
||||
break;
|
||||
case AM_PM_FIELD:
|
||||
dateFormatField = Field.AM_PM;
|
||||
buffer.append(formatData.ampms[calendar.get(Calendar.AM_PM)]);
|
||||
break;
|
||||
case HOUR1_FIELD: // h
|
||||
dateFormatField = Field.HOUR1;
|
||||
hour = calendar.get(Calendar.HOUR);
|
||||
appendNumber(buffer, count, hour == 0 ? 12 : hour);
|
||||
break;
|
||||
case HOUR0_FIELD: // K
|
||||
dateFormatField = Field.HOUR0;
|
||||
field = Calendar.HOUR;
|
||||
break;
|
||||
case TIMEZONE_FIELD: // z
|
||||
dateFormatField = Field.TIME_ZONE;
|
||||
appendTimeZone(buffer, count, true);
|
||||
break;
|
||||
case com.ibm.icu.text.DateFormat.TIMEZONE_RFC_FIELD: // Z
|
||||
dateFormatField = Field.TIME_ZONE;
|
||||
appendTimeZone(buffer, count, false);
|
||||
break;
|
||||
}
|
||||
if (field != -1) {
|
||||
appendNumber(buffer, count, calendar.get(field));
|
||||
}
|
||||
|
||||
if (fields != null) {
|
||||
position = new FieldPosition(dateFormatField);
|
||||
position.setBeginIndex(beginPosition);
|
||||
position.setEndIndex(buffer.length());
|
||||
fields.add(position);
|
||||
} else {
|
||||
// Set to the first occurrence
|
||||
if ((position.getFieldAttribute() == dateFormatField || (position.getFieldAttribute() == null && position
|
||||
.getField() == index)) && position.getEndIndex() == 0) {
|
||||
position.setBeginIndex(beginPosition);
|
||||
position.setEndIndex(buffer.length());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void appendTimeZone(StringBuffer buffer, int count, boolean generalTimezone) {
|
||||
// cannot call TimeZone.getDisplayName() because it would not use
|
||||
// the DateFormatSymbols of this SimpleDateFormat
|
||||
|
||||
if (generalTimezone) {
|
||||
String id = calendar.getTimeZone().getID();
|
||||
String[][] zones = formatData.getZoneStrings();
|
||||
String[] zone = null;
|
||||
for (String[] element : zones) {
|
||||
if (id.equals(element[0])) {
|
||||
zone = element;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (zone == null) {
|
||||
int offset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET);
|
||||
char sign = '+';
|
||||
if (offset < 0) {
|
||||
sign = '-';
|
||||
offset = -offset;
|
||||
}
|
||||
buffer.append("GMT");
|
||||
buffer.append(sign);
|
||||
appendNumber(buffer, 2, offset / 3600000);
|
||||
buffer.append(':');
|
||||
appendNumber(buffer, 2, (offset % 3600000) / 60000);
|
||||
} else {
|
||||
int daylight = calendar.get(Calendar.DST_OFFSET) == 0 ? 0 : 2;
|
||||
if (count < 4) {
|
||||
buffer.append(zone[2 + daylight]);
|
||||
} else {
|
||||
buffer.append(zone[1 + daylight]);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
int offset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET);
|
||||
char sign = '+';
|
||||
if (offset < 0) {
|
||||
sign = '-';
|
||||
offset = -offset;
|
||||
}
|
||||
buffer.append(sign);
|
||||
appendNumber(buffer, 2, offset / 3600000);
|
||||
appendNumber(buffer, 2, (offset % 3600000) / 60000);
|
||||
}
|
||||
}
|
||||
|
||||
private void appendNumber(StringBuffer buffer, int count, int value) {
|
||||
int minimumIntegerDigits = numberFormat.getMinimumIntegerDigits();
|
||||
numberFormat.setMinimumIntegerDigits(count);
|
||||
numberFormat.format(new Integer(value), buffer, new FieldPosition(0));
|
||||
numberFormat.setMinimumIntegerDigits(minimumIntegerDigits);
|
||||
}
|
||||
|
||||
@Override
|
||||
public StringBuffer format(Date date, StringBuffer buffer, FieldPosition fieldPos) {
|
||||
String id = calendar.getTimeZone().getID();
|
||||
if (!tzId.equals(id)) {
|
||||
tzId = id;
|
||||
icuFormat.setTimeZone(com.ibm.icu.util.TimeZone.getTimeZone(tzId));
|
||||
}
|
||||
// As ICU has its own implementation for DateFormat.Field, we need to
|
||||
// pass an ICU instance of DateFormat.Field to the FieldPosition to get
|
||||
// the begin and end index.
|
||||
StringBuffer result = null;
|
||||
Format.Field attribute = fieldPos.getFieldAttribute();
|
||||
if (attribute instanceof DateFormat.Field) {
|
||||
com.ibm.icu.text.DateFormat.Field icuAttribute = toICUField((DateFormat.Field) attribute);
|
||||
int field = fieldPos.getField();
|
||||
FieldPosition icuFieldPos = new FieldPosition(icuAttribute, field);
|
||||
result = icuFormat.format(date, buffer, icuFieldPos);
|
||||
fieldPos.setBeginIndex(icuFieldPos.getBeginIndex());
|
||||
fieldPos.setEndIndex(icuFieldPos.getEndIndex());
|
||||
return result;
|
||||
}
|
||||
return icuFormat.format(date, buffer, fieldPos);
|
||||
}
|
||||
|
||||
private com.ibm.icu.text.DateFormat.Field toICUField(DateFormat.Field attribute) {
|
||||
com.ibm.icu.text.DateFormat.Field icuAttribute = null;
|
||||
|
||||
if (attribute == DateFormat.Field.ERA) {
|
||||
icuAttribute = com.ibm.icu.text.DateFormat.Field.ERA;
|
||||
} else if (attribute == DateFormat.Field.YEAR) {
|
||||
icuAttribute = com.ibm.icu.text.DateFormat.Field.YEAR;
|
||||
} else if (attribute == DateFormat.Field.MONTH) {
|
||||
icuAttribute = com.ibm.icu.text.DateFormat.Field.MONTH;
|
||||
} else if (attribute == DateFormat.Field.HOUR_OF_DAY0) {
|
||||
icuAttribute = com.ibm.icu.text.DateFormat.Field.HOUR_OF_DAY0;
|
||||
} else if (attribute == DateFormat.Field.HOUR_OF_DAY1) {
|
||||
icuAttribute = com.ibm.icu.text.DateFormat.Field.HOUR_OF_DAY1;
|
||||
} else if (attribute == DateFormat.Field.MINUTE) {
|
||||
icuAttribute = com.ibm.icu.text.DateFormat.Field.MINUTE;
|
||||
} else if (attribute == DateFormat.Field.SECOND) {
|
||||
icuAttribute = com.ibm.icu.text.DateFormat.Field.SECOND;
|
||||
} else if (attribute == DateFormat.Field.MILLISECOND) {
|
||||
icuAttribute = com.ibm.icu.text.DateFormat.Field.MILLISECOND;
|
||||
} else if (attribute == DateFormat.Field.DAY_OF_WEEK) {
|
||||
icuAttribute = com.ibm.icu.text.DateFormat.Field.DAY_OF_WEEK;
|
||||
} else if (attribute == DateFormat.Field.DAY_OF_MONTH) {
|
||||
icuAttribute = com.ibm.icu.text.DateFormat.Field.DAY_OF_MONTH;
|
||||
} else if (attribute == DateFormat.Field.DAY_OF_YEAR) {
|
||||
icuAttribute = com.ibm.icu.text.DateFormat.Field.DAY_OF_YEAR;
|
||||
} else if (attribute == DateFormat.Field.DAY_OF_WEEK_IN_MONTH) {
|
||||
icuAttribute = com.ibm.icu.text.DateFormat.Field.DAY_OF_WEEK_IN_MONTH;
|
||||
} else if (attribute == DateFormat.Field.WEEK_OF_YEAR) {
|
||||
icuAttribute = com.ibm.icu.text.DateFormat.Field.WEEK_OF_YEAR;
|
||||
} else if (attribute == DateFormat.Field.WEEK_OF_MONTH) {
|
||||
icuAttribute = com.ibm.icu.text.DateFormat.Field.WEEK_OF_MONTH;
|
||||
} else if (attribute == DateFormat.Field.AM_PM) {
|
||||
icuAttribute = com.ibm.icu.text.DateFormat.Field.AM_PM;
|
||||
} else if (attribute == DateFormat.Field.HOUR0) {
|
||||
icuAttribute = com.ibm.icu.text.DateFormat.Field.HOUR0;
|
||||
} else if (attribute == DateFormat.Field.HOUR1) {
|
||||
icuAttribute = com.ibm.icu.text.DateFormat.Field.HOUR1;
|
||||
} else if (attribute == DateFormat.Field.TIME_ZONE) {
|
||||
icuAttribute = com.ibm.icu.text.DateFormat.Field.TIME_ZONE;
|
||||
}
|
||||
|
||||
return icuAttribute;
|
||||
}
|
||||
|
||||
public Date get2DigitYearStart() {
|
||||
return defaultCenturyStart;
|
||||
}
|
||||
|
||||
public DateFormatSymbols getDateFormatSymbols() {
|
||||
// Return a clone so the arrays in the ResourceBundle are not modified
|
||||
return (DateFormatSymbols) formatData.clone();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return super.hashCode() + pattern.hashCode() + formatData.hashCode() + creationYear;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Date parse(String string, ParsePosition position) {
|
||||
String id = calendar.getTimeZone().getID();
|
||||
if (!tzId.equals(id)) {
|
||||
tzId = id;
|
||||
icuFormat.setTimeZone(com.ibm.icu.util.TimeZone.getTimeZone(tzId));
|
||||
}
|
||||
icuFormat.setLenient(calendar.isLenient());
|
||||
return icuFormat.parse(string, position);
|
||||
}
|
||||
|
||||
public void set2DigitYearStart(Date date) {
|
||||
icuFormat.set2DigitYearStart(date);
|
||||
defaultCenturyStart = date;
|
||||
Calendar cal = new GregorianCalendar();
|
||||
cal.setTime(date);
|
||||
creationYear = cal.get(Calendar.YEAR);
|
||||
}
|
||||
|
||||
public void setDateFormatSymbols(DateFormatSymbols value) {
|
||||
com.ibm.icu.text.DateFormatSymbols icuSymbols = new com.ibm.icu.text.DateFormatSymbols();
|
||||
copySymbols(value, icuSymbols);
|
||||
icuFormat.setDateFormatSymbols(icuSymbols);
|
||||
formatData = (DateFormatSymbols) value.clone();
|
||||
}
|
||||
|
||||
public String toLocalizedPattern() {
|
||||
return icuFormat.toLocalizedPattern();
|
||||
}
|
||||
|
||||
public String toPattern() {
|
||||
return pattern;
|
||||
}
|
||||
}
|
|
@ -32,12 +32,12 @@
|
|||
|
||||
package org.teavm.classlib.java.util;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.DateFormatSymbols;
|
||||
import java.text.SimpleDateFormat;
|
||||
import org.teavm.classlib.java.io.TSerializable;
|
||||
import org.teavm.classlib.java.lang.TCloneable;
|
||||
import org.teavm.classlib.java.lang.TComparable;
|
||||
import org.teavm.classlib.java.text.DateFormat;
|
||||
import org.teavm.classlib.java.text.DateFormatSymbols;
|
||||
import org.teavm.classlib.java.text.SimpleDateFormat;
|
||||
|
||||
public class Date implements TSerializable, TCloneable, TComparable<Date> {
|
||||
|
||||
|
@ -104,6 +104,7 @@ public class Date implements TSerializable, TCloneable, TComparable<Date> {
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Date date) {
|
||||
if (milliseconds < date.milliseconds) {
|
||||
return -1;
|
||||
|
|
|
@ -271,20 +271,6 @@ public abstract class TimeZone implements TSerializable, TCloneable {
|
|||
|
||||
private static void setICUDefaultTimeZone(TimeZone timezone) {
|
||||
final com.ibm.icu.util.TimeZone icuTZ = com.ibm.icu.util.TimeZone.getTimeZone(timezone.getID());
|
||||
|
||||
AccessController.doPrivileged(new PrivilegedAction<java.lang.reflect.Field>() {
|
||||
public java.lang.reflect.Field run() {
|
||||
java.lang.reflect.Field field = null;
|
||||
try {
|
||||
field = com.ibm.icu.util.TimeZone.class.getDeclaredField("defaultZone");
|
||||
field.setAccessible(true);
|
||||
field.set("defaultZone", icuTZ);
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
return field;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void setID(String name) {
|
||||
|
|
Loading…
Reference in New Issue
Block a user