Adds first SimpleDataFormat test

This commit is contained in:
konsoletyper 2014-06-24 18:18:34 +04:00
parent 2127ae4280
commit 9e292eb7e5
7 changed files with 411 additions and 150 deletions

View File

@ -108,6 +108,30 @@ public class CLDRHelper {
@MetadataProvider(FirstDayOfWeekMetadataGenerator.class) @MetadataProvider(FirstDayOfWeekMetadataGenerator.class)
public static native ResourceMap<IntResource> getFirstDayOfWeek(); public static native ResourceMap<IntResource> getFirstDayOfWeek();
public static String resolveDateFormat(String language, String country) {
return resolveFormatSymbols(getDateFormatMap(), language, country);
}
private static native ResourceMap<StringResource> getDateFormatMap();
public static String resolveFullDateFormat(String language, String country) {
return resolveFormatSymbols(getFullDateFormatMap(), language, country);
}
private static native ResourceMap<StringResource> getFullDateFormatMap();
public static String resolveLongDateFormat(String language, String country) {
return resolveFormatSymbols(getLongDateFormatMap(), language, country);
}
private static native ResourceMap<StringResource> getLongDateFormatMap();
public static String resolveShortDateFormat(String language, String country) {
return resolveFormatSymbols(getShortDateFormatMap(), language, country);
}
private static native ResourceMap<StringResource> getShortDateFormatMap();
public static String resolveNumberFormat(String language, String country) { public static String resolveNumberFormat(String language, String country) {
return resolveFormatSymbols(getNumberFormatMap(), language, country); return resolveFormatSymbols(getNumberFormatMap(), language, country);
} }

View File

@ -1,120 +0,0 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed 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.ArrayList;
import java.util.List;
/**
*
* @author Alexey Andreev
*/
class SimpleDatePatternParser {
private TDateFormatSymbols symbols;
private List<DateFormatElement> elements = new ArrayList<>();
private int index;
private String pattern;
public SimpleDatePatternParser(TDateFormatSymbols symbols) {
this.symbols = symbols;
}
public void parsePattern(String pattern) {
this.pattern = pattern;
for (index = 0; index < pattern.length(); ++index) {
char c = pattern.charAt(index);
switch (c) {
case '\'': {
++index;
parseQuoted();
break;
}
case 'G':
parseRepetitions();
elements.add(new DateFormatElement.EraText(symbols));
break;
case 'y':
break;
default: {
StringBuilder sb = new StringBuilder();
while (index < pattern.length() && isControl(pattern.charAt(index))) {
sb.append(pattern.charAt(index++));
}
break;
}
}
}
}
private boolean isControl(char c) {
switch (c) {
case '\'':
case 'G':
case 'y':
case 'Y':
case 'M':
case 'w':
case 'W':
case 'D':
case 'd':
case 'F':
case 'E':
case 'u':
case 'a':
case 'H':
case 'k':
case 'K':
case 'h':
case 'm':
case 's':
case 'S':
case 'z':
case 'Z':
case 'X':
return true;
default:
return false;
}
}
private void parseQuoted() {
StringBuilder sb = new StringBuilder();
while (index < pattern.length()) {
char c = pattern.charAt(index++);
if (c == '\'') {
if (index < pattern.length() && pattern.charAt(index) == '\'') {
sb.append('\'');
++index;
} else {
break;
}
} else {
sb.append(c);
}
}
elements.add(new DateFormatElement.ConstantText(sb.toString()));
}
private int parseRepetitions() {
int count = 1;
char orig = pattern.charAt(index++);
while (index < pattern.length() && pattern.charAt(index) == orig) {
++index;
++count;
}
return count;
}
}

View File

@ -17,6 +17,7 @@
package org.teavm.classlib.java.text; package org.teavm.classlib.java.text;
import org.teavm.classlib.impl.unicode.CLDRHelper;
import org.teavm.classlib.java.util.*; import org.teavm.classlib.java.util.*;
public abstract class TDateFormat extends TFormat { public abstract class TDateFormat extends TFormat {
@ -58,9 +59,11 @@ public abstract class TDateFormat extends TFormat {
return clone; return clone;
} }
// TODO: implement
/*
@Override @Override
public boolean equals(Object object) { public boolean equals(Object object) {
/*if (this == object) { if (this == object) {
return true; return true;
} }
if (!(object instanceof DateFormat)) { if (!(object instanceof DateFormat)) {
@ -70,10 +73,11 @@ public abstract class TDateFormat extends TFormat {
return numberFormat.equals(dateFormat.numberFormat) && return numberFormat.equals(dateFormat.numberFormat) &&
calendar.getFirstDayOfWeek() == dateFormat.calendar.getFirstDayOfWeek() && calendar.getFirstDayOfWeek() == dateFormat.calendar.getFirstDayOfWeek() &&
calendar.getMinimalDaysInFirstWeek() == dateFormat.calendar.getMinimalDaysInFirstWeek() && calendar.getMinimalDaysInFirstWeek() == dateFormat.calendar.getMinimalDaysInFirstWeek() &&
calendar.isLenient() == dateFormat.calendar.isLenient();*/ calendar.isLenient() == dateFormat.calendar.isLenient();
// TODO: implement
return false; return false;
} }
*/
@Override @Override
public final StringBuffer format(Object object, StringBuffer buffer, TFieldPosition field) { public final StringBuffer format(Object object, StringBuffer buffer, TFieldPosition field) {
@ -110,11 +114,22 @@ public abstract class TDateFormat extends TFormat {
} }
public final static TDateFormat getDateInstance(int style, TLocale locale) { public final static TDateFormat getDateInstance(int style, TLocale locale) {
/*checkDateStyle(style); switch (style) {
com.ibm.icu.text.DateFormat icuFormat = com.ibm.icu.text.DateFormat.getDateInstance(style, locale); case SHORT:
return new SimpleDateFormat(locale, (com.ibm.icu.text.SimpleDateFormat) icuFormat);*/ return new TSimpleDateFormat(CLDRHelper.resolveShortDateFormat(
// TODO: implement locale.getLanguage(), locale.getCountry()), locale);
return null; case MEDIUM:
return new TSimpleDateFormat(CLDRHelper.resolveDateFormat(
locale.getLanguage(), locale.getCountry()), locale);
case LONG:
return new TSimpleDateFormat(CLDRHelper.resolveLongDateFormat(
locale.getLanguage(), locale.getCountry()), locale);
case FULL:
return new TSimpleDateFormat(CLDRHelper.resolveFullDateFormat(
locale.getLanguage(), locale.getCountry()), locale);
default:
throw new IllegalArgumentException("Unknown style: " + style);
}
} }
public final static TDateFormat getDateTimeInstance() { public final static TDateFormat getDateTimeInstance() {
@ -184,13 +199,14 @@ public abstract class TDateFormat extends TFormat {
} }
@Override // TODO: implement
/*@Override
public int hashCode() { public int hashCode() {
/*return calendar.getFirstDayOfWeek() + calendar.getMinimalDaysInFirstWeek() + return calendar.getFirstDayOfWeek() + calendar.getMinimalDaysInFirstWeek() +
(calendar.isLenient() ? 1231 : 1237) + numberFormat.hashCode();*/ (calendar.isLenient() ? 1231 : 1237) + numberFormat.hashCode();
// TODO: implement
return 0; return 0;
} }*/
public boolean isLenient() { public boolean isLenient() {
return calendar.isLenient(); return calendar.isLenient();
@ -276,7 +292,6 @@ public abstract class TDateFormat extends TFormat {
private static void checkTimeStyle(int style) { private static void checkTimeStyle(int style) {
if (!(style == SHORT || style == MEDIUM || style == LONG || style == FULL || style == DEFAULT)) { if (!(style == SHORT || style == MEDIUM || style == LONG || style == FULL || style == DEFAULT)) {
// text.0F=Illegal time style: {0}
throw new IllegalArgumentException("Illegal time style: " + style); throw new IllegalArgumentException("Illegal time style: " + style);
} }
} }

View File

@ -22,7 +22,7 @@ import org.teavm.classlib.java.util.TGregorianCalendar;
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
abstract class DateFormatElement { abstract class TDateFormatElement {
public abstract void format(TCalendar date, StringBuffer buffer); public abstract void format(TCalendar date, StringBuffer buffer);
public abstract void parse(String text, TCalendar date, TParsePosition position); public abstract void parse(String text, TCalendar date, TParsePosition position);
@ -49,7 +49,7 @@ abstract class DateFormatElement {
return -1; return -1;
} }
public static class MonthText extends DateFormatElement { public static class MonthText extends TDateFormatElement {
String[] months; String[] months;
String[] shortMonths; String[] shortMonths;
boolean abbreviated; boolean abbreviated;
@ -80,7 +80,7 @@ abstract class DateFormatElement {
} }
} }
public static class WeekdayText extends DateFormatElement { public static class WeekdayText extends TDateFormatElement {
String[] weeks; String[] weeks;
String[] shortWeeks; String[] shortWeeks;
boolean abbreviated; boolean abbreviated;
@ -111,7 +111,7 @@ abstract class DateFormatElement {
} }
} }
public static class EraText extends DateFormatElement { public static class EraText extends TDateFormatElement {
String[] eras; String[] eras;
public EraText(TDateFormatSymbols symbols) { public EraText(TDateFormatSymbols symbols) {
@ -135,7 +135,7 @@ abstract class DateFormatElement {
} }
} }
public static class AmPmText extends DateFormatElement { public static class AmPmText extends TDateFormatElement {
String[] ampms; String[] ampms;
public AmPmText(TDateFormatSymbols symbols) { public AmPmText(TDateFormatSymbols symbols) {
@ -159,20 +159,18 @@ abstract class DateFormatElement {
} }
} }
public static class Numeric extends DateFormatElement { public static class Numeric extends TDateFormatElement {
private int field; private int field;
private int length; private int length;
private int offset;
public Numeric(int field, int length, int offset) { public Numeric(int field, int length) {
this.field = field; this.field = field;
this.length = length; this.length = length;
this.offset = offset;
} }
@Override @Override
public void format(TCalendar date, StringBuffer buffer) { public void format(TCalendar date, StringBuffer buffer) {
int number = date.get(field) + offset; int number = processBeforeFormat(date.get(field));
String str = Integer.toString(number); String str = Integer.toString(number);
for (int i = str.length(); i < length; ++i) { for (int i = str.length(); i < length; ++i) {
buffer.append('0'); buffer.append('0');
@ -200,11 +198,70 @@ abstract class DateFormatElement {
return; return;
} }
position.setIndex(pos); position.setIndex(pos);
date.set(field, num - offset); date.set(field, processAfterParse(num));
}
protected int processBeforeFormat(int num) {
return num;
}
protected int processAfterParse(int num) {
return num;
} }
} }
public static class Year extends DateFormatElement { public static class NumericMonth extends Numeric {
public NumericMonth(int length) {
super(TCalendar.MONTH, length);
}
@Override
protected int processBeforeFormat(int num) {
return num + 1;
}
@Override
protected int processAfterParse(int num) {
return num - 1;
}
}
public static class NumericWeekday extends Numeric {
public NumericWeekday(int length) {
super(TCalendar.DAY_OF_WEEK, length);
}
@Override
protected int processBeforeFormat(int num) {
return num == 1 ? 7 : num - 1;
}
@Override
protected int processAfterParse(int num) {
return num == 7 ? 1 : num + 1;
}
}
public static class NumericHour extends Numeric {
private int limit;
public NumericHour(int field, int length, int limit) {
super(field, length);
this.limit = limit;
}
@Override
protected int processBeforeFormat(int num) {
return num == 0 ? limit : num;
}
@Override
protected int processAfterParse(int num) {
return num == limit ? 0 : num;
}
}
public static class Year extends TDateFormatElement {
private int field; private int field;
public Year(int field) { public Year(int field) {
@ -255,7 +312,7 @@ abstract class DateFormatElement {
} }
} }
public static class ConstantText extends DateFormatElement { public static class ConstantText extends TDateFormatElement {
private String textConstant; private String textConstant;
public ConstantText(String textConstant) { public ConstantText(String textConstant) {

View File

@ -15,32 +15,69 @@
*/ */
package org.teavm.classlib.java.text; package org.teavm.classlib.java.text;
import org.teavm.classlib.impl.unicode.CLDRHelper;
import org.teavm.classlib.java.util.TCalendar; import org.teavm.classlib.java.util.TCalendar;
import org.teavm.classlib.java.util.TDate; import org.teavm.classlib.java.util.TDate;
import org.teavm.classlib.java.util.TGregorianCalendar; import org.teavm.classlib.java.util.TGregorianCalendar;
import org.teavm.classlib.java.util.TLocale;
/** /**
* *
* @author Alexey Andreev * @author Alexey Andreev
*/ */
public class TSimpleDateFormat extends TDateFormat { public class TSimpleDateFormat extends TDateFormat {
private DateFormatElement[] elements; private TDateFormatSymbols dateFormatSymbols;
private TDateFormatElement[] elements;
private String pattern;
public TSimpleDateFormat() {
this(getDefaultPattern());
}
private static String getDefaultPattern() {
TLocale locale = TLocale.getDefault();
return CLDRHelper.resolveDateFormat(locale.getLanguage(), locale.getCountry());
}
public TSimpleDateFormat(String pattern) {
this(pattern, TLocale.getDefault());
}
public TSimpleDateFormat(String pattern, TLocale locale) {
this(pattern, new TDateFormatSymbols(locale));
}
public TSimpleDateFormat(String pattern, TDateFormatSymbols dateFormatSymbols) {
dateFormatSymbols = (TDateFormatSymbols)dateFormatSymbols.clone();
applyPattern(pattern);
}
@Override @Override
public StringBuffer format(TDate date, StringBuffer buffer, TFieldPosition field) { public StringBuffer format(TDate date, StringBuffer buffer, TFieldPosition field) {
TCalendar calendar = new TGregorianCalendar(); TCalendar calendar = new TGregorianCalendar();
calendar.setTime(date); calendar.setTime(date);
for (DateFormatElement element : elements) { for (TDateFormatElement element : elements) {
element.format(calendar, buffer); element.format(calendar, buffer);
} }
return buffer; return buffer;
} }
public void applyPattern(String pattern) {
this.pattern = pattern;
reparsePattern();
}
private void reparsePattern() {
TSimpleDatePatternParser parser = new TSimpleDatePatternParser(dateFormatSymbols);
parser.parsePattern(pattern);
elements = parser.getElements().toArray(new TDateFormatElement[0]);
}
@Override @Override
public TDate parse(String string, TParsePosition position) { public TDate parse(String string, TParsePosition position) {
TCalendar calendar = new TGregorianCalendar(); TCalendar calendar = new TGregorianCalendar();
calendar.set(0, 0, 0, 0, 0, 0); calendar.set(0, 0, 0, 0, 0, 0);
for (DateFormatElement element : elements) { for (TDateFormatElement element : elements) {
if (position.getIndex() > string.length()) { if (position.getIndex() > string.length()) {
position.setErrorIndex(position.getErrorIndex()); position.setErrorIndex(position.getErrorIndex());
return null; return null;
@ -52,4 +89,25 @@ public class TSimpleDateFormat extends TDateFormat {
} }
return calendar.getTime(); return calendar.getTime();
} }
@Override
public Object clone() {
TSimpleDateFormat copy = (TSimpleDateFormat)super.clone();
copy.dateFormatSymbols = (TDateFormatSymbols)dateFormatSymbols.clone();
copy.elements = elements.clone();
return copy;
}
public TDateFormatSymbols getDateFormatSymbols() {
return (TDateFormatSymbols)dateFormatSymbols.clone();
}
public void setDateFormatSymbols(TDateFormatSymbols newFormatSymbols) {
dateFormatSymbols = (TDateFormatSymbols)newFormatSymbols.clone();
reparsePattern();
}
public String toPattern() {
return pattern;
}
} }

View File

@ -0,0 +1,194 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed 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.ArrayList;
import java.util.List;
import org.teavm.classlib.java.util.TCalendar;
/**
*
* @author Alexey Andreev
*/
class TSimpleDatePatternParser {
private TDateFormatSymbols symbols;
private List<TDateFormatElement> elements = new ArrayList<>();
private int index;
private String pattern;
public TSimpleDatePatternParser(TDateFormatSymbols symbols) {
this.symbols = symbols;
}
public List<TDateFormatElement> getElements() {
return elements;
}
public void parsePattern(String pattern) {
elements.clear();
this.pattern = pattern;
for (index = 0; index < pattern.length();) {
char c = pattern.charAt(index);
switch (c) {
case '\'': {
++index;
parseQuoted();
break;
}
case 'G':
parseRepetitions();
elements.add(new TDateFormatElement.EraText(symbols));
break;
case 'y':
case 'Y': {
int rep = parseRepetitions();
if (rep <= 2) {
elements.add(new TDateFormatElement.Year(TCalendar.YEAR));
} else {
elements.add(new TDateFormatElement.Numeric(TCalendar.YEAR, rep));
}
break;
}
case 'M':
case 'L': {
int rep = parseRepetitions();
if (rep <= 2) {
elements.add(new TDateFormatElement.NumericMonth(rep));
} else {
elements.add(new TDateFormatElement.MonthText(symbols, rep == 3));
}
break;
}
case 'w': {
int rep = parseRepetitions();
elements.add(new TDateFormatElement.Numeric(TCalendar.WEEK_OF_YEAR, rep));
break;
}
case 'W': {
int rep = parseRepetitions();
elements.add(new TDateFormatElement.Numeric(TCalendar.WEEK_OF_MONTH, rep));
break;
}
case 'D': {
int rep = parseRepetitions();
elements.add(new TDateFormatElement.Numeric(TCalendar.DAY_OF_YEAR, rep));
break;
}
case 'd': {
int rep = parseRepetitions();
elements.add(new TDateFormatElement.Numeric(TCalendar.DAY_OF_MONTH, rep));
break;
}
case 'F': {
int rep = parseRepetitions();
elements.add(new TDateFormatElement.Numeric(TCalendar.DAY_OF_WEEK_IN_MONTH, rep));
break;
}
case 'E':
case 'c': {
int rep = parseRepetitions();
elements.add(new TDateFormatElement.WeekdayText(symbols, rep <= 3));
break;
}
case 'u': {
int rep = parseRepetitions();
elements.add(new TDateFormatElement.NumericWeekday(rep));
break;
}
case 'a': {
parseRepetitions();
elements.add(new TDateFormatElement.AmPmText(symbols));
break;
}
case 'H': {
int rep = parseRepetitions();
elements.add(new TDateFormatElement.Numeric(TCalendar.HOUR_OF_DAY, rep));
break;
}
case 'k': {
int rep = parseRepetitions();
elements.add(new TDateFormatElement.NumericHour(TCalendar.HOUR_OF_DAY, rep, 24));
break;
}
case 'K': {
int rep = parseRepetitions();
elements.add(new TDateFormatElement.Numeric(TCalendar.HOUR, rep));
break;
}
case 'h': {
int rep = parseRepetitions();
elements.add(new TDateFormatElement.NumericHour(TCalendar.HOUR, rep, 12));
break;
}
case 'm': {
int rep = parseRepetitions();
elements.add(new TDateFormatElement.Numeric(TCalendar.MINUTE, rep));
break;
}
case 's': {
int rep = parseRepetitions();
elements.add(new TDateFormatElement.Numeric(TCalendar.SECOND, rep));
break;
}
case 'S': {
int rep = parseRepetitions();
elements.add(new TDateFormatElement.Numeric(TCalendar.MILLISECOND, rep));
break;
}
default: {
StringBuilder sb = new StringBuilder();
while (index < pattern.length() && !isControl(pattern.charAt(index))) {
sb.append(pattern.charAt(index++));
}
elements.add(new TDateFormatElement.ConstantText(sb.toString()));
break;
}
}
}
}
private boolean isControl(char c) {
return c == '\'' || c >= 'a' && c <= 'z' || c >= 'A' && c <= 'Z';
}
private void parseQuoted() {
StringBuilder sb = new StringBuilder();
while (index < pattern.length()) {
char c = pattern.charAt(index++);
if (c == '\'') {
if (index < pattern.length() && pattern.charAt(index) == '\'') {
sb.append('\'');
++index;
} else {
break;
}
} else {
sb.append(c);
}
}
elements.add(new TDateFormatElement.ConstantText(sb.toString()));
}
private int parseRepetitions() {
int count = 1;
char orig = pattern.charAt(index++);
while (index < pattern.length() && pattern.charAt(index) == orig) {
++index;
++count;
}
return count;
}
}

View File

@ -0,0 +1,33 @@
/*
* Copyright 2014 Alexey Andreev.
*
* Licensed 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 static org.junit.Assert.*;
import java.text.SimpleDateFormat;
import java.util.Date;
import org.junit.Test;
/**
*
* @author Alexey Andreev
*/
public class SimpleDateTimeFormatTest {
@Test
public void fieldsFormatted() {
SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
assertEquals("2014-06-24 17:33:49", format.format(new Date(1403616829504L)));
}
}