mirror of
https://github.com/Eaglercraft-TeaVM-Fork/eagler-teavm.git
synced 2024-12-23 00:24:11 -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;
|
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.io.TSerializable;
|
||||||
import org.teavm.classlib.java.lang.TCloneable;
|
import org.teavm.classlib.java.lang.TCloneable;
|
||||||
import org.teavm.classlib.java.lang.TComparable;
|
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> {
|
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) {
|
public int compareTo(Date date) {
|
||||||
if (milliseconds < date.milliseconds) {
|
if (milliseconds < date.milliseconds) {
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -271,20 +271,6 @@ public abstract class TimeZone implements TSerializable, TCloneable {
|
||||||
|
|
||||||
private static void setICUDefaultTimeZone(TimeZone timezone) {
|
private static void setICUDefaultTimeZone(TimeZone timezone) {
|
||||||
final com.ibm.icu.util.TimeZone icuTZ = com.ibm.icu.util.TimeZone.getTimeZone(timezone.getID());
|
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) {
|
public void setID(String name) {
|
||||||
|
|
Loading…
Reference in New Issue
Block a user