Completes DateTimeFormat support

This commit is contained in:
konsoletyper 2014-06-26 18:06:31 +04:00
parent 52ed32e9aa
commit b94d711732
11 changed files with 230 additions and 101 deletions

View File

@ -0,0 +1,50 @@
/*
* 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.impl.unicode;
/**
*
* @author Alexey Andreev
*/
public class CLDRDateFormats {
private String shortFormat;
private String mediumFormat;
private String longFormat;
private String fullFormat;
CLDRDateFormats(String shortFormat, String mediumFormat, String longFormat, String fullFormat) {
this.shortFormat = shortFormat;
this.mediumFormat = mediumFormat;
this.longFormat = longFormat;
this.fullFormat = fullFormat;
}
public String getShortFormat() {
return shortFormat;
}
public String getMediumFormat() {
return mediumFormat;
}
public String getLongFormat() {
return longFormat;
}
public String getFullFormat() {
return fullFormat;
}
}

View File

@ -108,33 +108,26 @@ 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) { public static DateFormatCollection resolveDateFormats(String language, String country) {
return resolveFormatSymbols(getDateFormatMap(), language, country); return resolveDateFormats(getDateFormatMap(), language, country);
} }
@MetadataProvider(DateFormatMetadataGenerator.class) @MetadataProvider(DateFormatMetadataGenerator.class)
private static native ResourceMap<StringResource> getDateFormatMap(); private static native ResourceMap<DateFormatCollection> getDateFormatMap();
public static String resolveFullDateFormat(String language, String country) { public static DateFormatCollection resolveTimeFormats(String language, String country) {
return resolveFormatSymbols(getFullDateFormatMap(), language, country); return resolveDateFormats(getTimeFormatMap(), language, country);
} }
@MetadataProvider(DateFormatMetadataGenerator.class) @MetadataProvider(DateFormatMetadataGenerator.class)
private static native ResourceMap<StringResource> getFullDateFormatMap(); private static native ResourceMap<DateFormatCollection> getTimeFormatMap();
public static String resolveLongDateFormat(String language, String country) { public static DateFormatCollection resolveDateTimeFormats(String language, String country) {
return resolveFormatSymbols(getLongDateFormatMap(), language, country); return resolveDateFormats(getDateTimeFormatMap(), language, country);
} }
@MetadataProvider(DateFormatMetadataGenerator.class) @MetadataProvider(DateFormatMetadataGenerator.class)
private static native ResourceMap<StringResource> getLongDateFormatMap(); private static native ResourceMap<DateFormatCollection> getDateTimeFormatMap();
public static String resolveShortDateFormat(String language, String country) {
return resolveFormatSymbols(getShortDateFormatMap(), language, country);
}
@MetadataProvider(DateFormatMetadataGenerator.class)
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);
@ -154,6 +147,12 @@ public class CLDRHelper {
private static native ResourceMap<StringResource> getPercentFormatMap(); private static native ResourceMap<StringResource> getPercentFormatMap();
private static DateFormatCollection resolveDateFormats(ResourceMap<DateFormatCollection> map,
String language, String country) {
String localeCode = getCode(language, country);
return map.has(localeCode) ? map.get(localeCode) : map.has(language) ? map.get(language) : map.get("root");
}
private static String resolveFormatSymbols(ResourceMap<StringResource> map, String language, String country) { private static String resolveFormatSymbols(ResourceMap<StringResource> map, String language, String country) {
String localeCode = getCode(language, country); String localeCode = getCode(language, country);
StringResource res = map.has(localeCode) ? map.get(localeCode) : map.has(language) ? map.get(language) : StringResource res = map.has(localeCode) ? map.get(localeCode) : map.has(language) ? map.get(language) :

View File

@ -33,10 +33,9 @@ public class CLDRLocale {
String[] shortMonths; String[] shortMonths;
String[] weekdays; String[] weekdays;
String[] shortWeekdays; String[] shortWeekdays;
String shortDateFormat; CLDRDateFormats dateFormats;
String mediumDateFormat; CLDRDateFormats timeFormats;
String longDateFormat; CLDRDateFormats dateTimeFormats;
String fullDateFormat;
public Map<String, String> getLanguages() { public Map<String, String> getLanguages() {
return Collections.unmodifiableMap(languages); return Collections.unmodifiableMap(languages);
@ -70,19 +69,15 @@ public class CLDRLocale {
return Arrays.copyOf(shortWeekdays, shortWeekdays.length); return Arrays.copyOf(shortWeekdays, shortWeekdays.length);
} }
public String getShortDateFormat() { public CLDRDateFormats getDateFormats() {
return shortDateFormat; return dateFormats;
} }
public String getMediumDateFormat() { public CLDRDateFormats getTimeFormats() {
return mediumDateFormat; return timeFormats;
} }
public String getLongDateFormat() { public CLDRDateFormats getDateTimeFormats() {
return longDateFormat; return dateTimeFormats;
}
public String getFullDateFormat() {
return fullDateFormat;
} }
} }

View File

@ -109,6 +109,8 @@ public class CLDRReader {
readWeekdays(localeName, localeInfo, root); readWeekdays(localeName, localeInfo, root);
readShortWeekdays(localeName, localeInfo, root); readShortWeekdays(localeName, localeInfo, root);
readDateFormats(localeName, localeInfo, root); readDateFormats(localeName, localeInfo, root);
readTimeFormats(localeName, localeInfo, root);
readDateTimeFormats(localeName, localeInfo, root);
break; break;
} }
} }
@ -209,10 +211,27 @@ public class CLDRReader {
JsonObject formatsJson = root.get("main").getAsJsonObject().get(localeCode).getAsJsonObject() JsonObject formatsJson = root.get("main").getAsJsonObject().get(localeCode).getAsJsonObject()
.get("dates").getAsJsonObject().get("calendars").getAsJsonObject() .get("dates").getAsJsonObject().get("calendars").getAsJsonObject()
.get("gregorian").getAsJsonObject().get("dateFormats").getAsJsonObject(); .get("gregorian").getAsJsonObject().get("dateFormats").getAsJsonObject();
locale.shortDateFormat = formatsJson.get("short").getAsString(); locale.dateFormats = new CLDRDateFormats(formatsJson.get("short").getAsString(),
locale.mediumDateFormat = formatsJson.get("medium").getAsString(); formatsJson.get("medium").getAsString(), formatsJson.get("long").getAsString(),
locale.longDateFormat = formatsJson.get("long").getAsString(); formatsJson.get("full").getAsString());
locale.fullDateFormat = formatsJson.get("full").getAsString(); }
private void readTimeFormats(String localeCode, CLDRLocale locale, JsonObject root) {
JsonObject formatsJson = root.get("main").getAsJsonObject().get(localeCode).getAsJsonObject()
.get("dates").getAsJsonObject().get("calendars").getAsJsonObject()
.get("gregorian").getAsJsonObject().get("timeFormats").getAsJsonObject();
locale.timeFormats = new CLDRDateFormats(formatsJson.get("short").getAsString(),
formatsJson.get("medium").getAsString(), formatsJson.get("long").getAsString(),
formatsJson.get("full").getAsString());
}
private void readDateTimeFormats(String localeCode, CLDRLocale locale, JsonObject root) {
JsonObject formatsJson = root.get("main").getAsJsonObject().get(localeCode).getAsJsonObject()
.get("dates").getAsJsonObject().get("calendars").getAsJsonObject()
.get("gregorian").getAsJsonObject().get("dateTimeFormats").getAsJsonObject();
locale.dateTimeFormats = new CLDRDateFormats(formatsJson.get("short").getAsString(),
formatsJson.get("medium").getAsString(), formatsJson.get("long").getAsString(),
formatsJson.get("full").getAsString());
} }
private void readWeekData(InputStream input) { private void readWeekData(InputStream input) {

View File

@ -0,0 +1,40 @@
/*
* 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.impl.unicode;
import org.teavm.platform.metadata.Resource;
/**
*
* @author Alexey Andreev
*/
public interface DateFormatCollection extends Resource {
String getShortFormat();
void setShortFormat(String format);
String getMediumFormat();
void setMediumFormat(String format);
String getLongFormat();
void setLongFormat(String format);
String getFullFormat();
void setFullFormat(String format);
}

View File

@ -29,26 +29,20 @@ public class DateFormatMetadataGenerator implements MetadataGenerator {
switch (method.getName()) { switch (method.getName()) {
case "getDateFormatMap": case "getDateFormatMap":
return getDateFormatMap(context, new FormatExtractor() { return getDateFormatMap(context, new FormatExtractor() {
@Override public String extract(CLDRLocale locale) { @Override public CLDRDateFormats extract(CLDRLocale locale) {
return locale.getMediumDateFormat(); return locale.getDateFormats();
} }
}); });
case "getShortDateFormatMap": case "getTimeFormatMap":
return getDateFormatMap(context, new FormatExtractor() { return getDateFormatMap(context, new FormatExtractor() {
@Override public String extract(CLDRLocale locale) { @Override public CLDRDateFormats extract(CLDRLocale locale) {
return locale.getShortDateFormat(); return locale.getTimeFormats();
} }
}); });
case "getLongDateFormatMap": case "getDateTimeFormatMap":
return getDateFormatMap(context, new FormatExtractor() { return getDateFormatMap(context, new FormatExtractor() {
@Override public String extract(CLDRLocale locale) { @Override public CLDRDateFormats extract(CLDRLocale locale) {
return locale.getLongDateFormat(); return locale.getDateTimeFormats();
}
});
case "getFullDateFormatMap":
return getDateFormatMap(context, new FormatExtractor() {
@Override public String extract(CLDRLocale locale) {
return locale.getFullDateFormat();
} }
}); });
default: default:
@ -58,16 +52,20 @@ public class DateFormatMetadataGenerator implements MetadataGenerator {
private Resource getDateFormatMap(MetadataGeneratorContext context, FormatExtractor extractor) { private Resource getDateFormatMap(MetadataGeneratorContext context, FormatExtractor extractor) {
CLDRReader reader = context.getService(CLDRReader.class); CLDRReader reader = context.getService(CLDRReader.class);
ResourceMap<StringResource> result = context.createResourceMap(); ResourceMap<DateFormatCollection> result = context.createResourceMap();
for (Map.Entry<String, CLDRLocale> entry : reader.getKnownLocales().entrySet()) { for (Map.Entry<String, CLDRLocale> entry : reader.getKnownLocales().entrySet()) {
StringResource formatRes = context.createResource(StringResource.class); DateFormatCollection formatRes = context.createResource(DateFormatCollection.class);
formatRes.setValue(extractor.extract(entry.getValue())); CLDRDateFormats formats = extractor.extract(entry.getValue());
formatRes.setShortFormat(formats.getShortFormat());
formatRes.setMediumFormat(formats.getMediumFormat());
formatRes.setLongFormat(formats.getLongFormat());
formatRes.setFullFormat(formats.getFullFormat());
result.put(entry.getKey(), formatRes); result.put(entry.getKey(), formatRes);
} }
return result; return result;
} }
interface FormatExtractor { interface FormatExtractor {
String extract(CLDRLocale locale); CLDRDateFormats extract(CLDRLocale locale);
} }
} }

View File

@ -400,7 +400,7 @@ public class TString extends TObject implements TSerializable, TComparable<TStri
int sz = length() - target.length(); int sz = length() - target.length();
int i = 0; int i = 0;
outer: outer:
for (; i < sz; ++i) { for (; i <= sz; ++i) {
for (int j = 0; j < target.length(); ++j) { for (int j = 0; j < target.length(); ++j) {
if (charAt(i + j) != target.charAt(j)) { if (charAt(i + j) != target.charAt(j)) {
sb.append(charAt(i)); sb.append(charAt(i));

View File

@ -18,6 +18,7 @@
package org.teavm.classlib.java.text; package org.teavm.classlib.java.text;
import org.teavm.classlib.impl.unicode.CLDRHelper; import org.teavm.classlib.impl.unicode.CLDRHelper;
import org.teavm.classlib.impl.unicode.DateFormatCollection;
import org.teavm.classlib.java.util.*; import org.teavm.classlib.java.util.*;
public abstract class TDateFormat extends TFormat { public abstract class TDateFormat extends TFormat {
@ -95,52 +96,63 @@ public abstract class TDateFormat extends TFormat {
return calendar; return calendar;
} }
public final static TDateFormat getDateInstance() { public static TDateFormat getDateInstance() {
return getDateInstance(DEFAULT); return getDateInstance(DEFAULT);
} }
public final static TDateFormat getDateInstance(int style) { public static TDateFormat getDateInstance(int style) {
checkDateStyle(style);
return getDateInstance(style, TLocale.getDefault()); return getDateInstance(style, TLocale.getDefault());
} }
public final static TDateFormat getDateInstance(int style, TLocale locale) { public static TDateFormat getDateInstance(int style, TLocale locale) {
return new TSimpleDateFormat(getDateFormatString(style, locale), locale);
}
private static String getDateFormatString(int style, TLocale locale) {
DateFormatCollection formats = CLDRHelper.resolveDateFormats(locale.getLanguage(), locale.getCountry());
switch (style) { switch (style) {
case SHORT: case SHORT:
return new TSimpleDateFormat(CLDRHelper.resolveShortDateFormat( return formats.getShortFormat();
locale.getLanguage(), locale.getCountry()), locale);
case MEDIUM: case MEDIUM:
return new TSimpleDateFormat(CLDRHelper.resolveDateFormat( return formats.getMediumFormat();
locale.getLanguage(), locale.getCountry()), locale);
case LONG: case LONG:
return new TSimpleDateFormat(CLDRHelper.resolveLongDateFormat( return formats.getLongFormat();
locale.getLanguage(), locale.getCountry()), locale);
case FULL: case FULL:
return new TSimpleDateFormat(CLDRHelper.resolveFullDateFormat( return formats.getFullFormat();
locale.getLanguage(), locale.getCountry()), locale);
default: default:
throw new IllegalArgumentException("Unknown style: " + style); throw new IllegalArgumentException("Unknown style: " + style);
} }
} }
public final static TDateFormat getDateTimeInstance() { public static TDateFormat getDateTimeInstance() {
return getDateTimeInstance(DEFAULT, DEFAULT); return getDateTimeInstance(DEFAULT, DEFAULT);
} }
public final static TDateFormat getDateTimeInstance(int dateStyle, int timeStyle) { public static TDateFormat getDateTimeInstance(int dateStyle, int timeStyle) {
checkTimeStyle(timeStyle);
checkDateStyle(dateStyle);
return getDateTimeInstance(dateStyle, timeStyle, TLocale.getDefault()); return getDateTimeInstance(dateStyle, timeStyle, TLocale.getDefault());
} }
public final static TDateFormat getDateTimeInstance(int dateStyle, int timeStyle, TLocale locale) { public static TDateFormat getDateTimeInstance(int dateStyle, int timeStyle, TLocale locale) {
/*checkTimeStyle(timeStyle); String pattern = getDateTimeFormatString(Math.max(dateStyle, timeStyle), locale);
checkDateStyle(dateStyle); pattern = pattern.replace("{0}", getTimeFormatString(dateStyle, locale))
com.ibm.icu.text.DateFormat icuFormat = com.ibm.icu.text.DateFormat.getDateTimeInstance(dateStyle, timeStyle, .replace("{1}", getDateFormatString(timeStyle, locale));
locale); return new TSimpleDateFormat(pattern, locale);
return new SimpleDateFormat(locale, (com.ibm.icu.text.SimpleDateFormat) icuFormat);*/ }
// TODO: implement
return null; public static String getDateTimeFormatString(int style, TLocale locale) {
DateFormatCollection formats = CLDRHelper.resolveDateTimeFormats(locale.getLanguage(), locale.getCountry());
switch (style) {
case SHORT:
return formats.getShortFormat();
case MEDIUM:
return formats.getMediumFormat();
case LONG:
return formats.getLongFormat();
case FULL:
return formats.getFullFormat();
default:
throw new IllegalArgumentException("Unknown style: " + style);
}
} }
public final static TDateFormat getInstance() { public final static TDateFormat getInstance() {
@ -172,19 +184,29 @@ public abstract class TDateFormat extends TFormat {
return getTimeInstance(DEFAULT); return getTimeInstance(DEFAULT);
} }
public final static TDateFormat getTimeInstance(int style) { public static TDateFormat getTimeInstance(int style) {
checkTimeStyle(style);
return getTimeInstance(style, TLocale.getDefault()); return getTimeInstance(style, TLocale.getDefault());
} }
public final static TDateFormat getTimeInstance(int style, TLocale locale) { public static TDateFormat getTimeInstance(int style, TLocale locale) {
/*checkTimeStyle(style); return new TSimpleDateFormat(getTimeFormatString(style, locale), locale);
com.ibm.icu.text.DateFormat icuFormat = com.ibm.icu.text.DateFormat.getTimeInstance(style, locale);
return new SimpleDateFormat(locale, (com.ibm.icu.text.SimpleDateFormat) icuFormat);*/
// TODO: implement
return null;
} }
private static String getTimeFormatString(int style, TLocale locale) {
DateFormatCollection formats = CLDRHelper.resolveTimeFormats(locale.getLanguage(), locale.getCountry());
switch (style) {
case SHORT:
return formats.getShortFormat();
case MEDIUM:
return formats.getMediumFormat();
case LONG:
return formats.getLongFormat();
case FULL:
return formats.getFullFormat();
default:
throw new IllegalArgumentException("Unknown style: " + style);
}
}
@Override @Override
public int hashCode() { public int hashCode() {
@ -263,16 +285,4 @@ public abstract class TDateFormat extends TFormat {
return table.get(new Integer(calendarField)); 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)) {
throw new IllegalArgumentException("Illegal time style: " + style);
}
}
} }

View File

@ -37,7 +37,7 @@ public class TSimpleDateFormat extends TDateFormat {
private static String getDefaultPattern() { private static String getDefaultPattern() {
TLocale locale = TLocale.getDefault(); TLocale locale = TLocale.getDefault();
return CLDRHelper.resolveDateFormat(locale.getLanguage(), locale.getCountry()); return CLDRHelper.resolveDateFormats(locale.getLanguage(), locale.getCountry()).getMediumFormat();
} }
public TSimpleDateFormat(String pattern) { public TSimpleDateFormat(String pattern) {

View File

@ -55,7 +55,7 @@ class TSimpleDatePatternParser {
case 'y': case 'y':
case 'Y': { case 'Y': {
int rep = parseRepetitions(); int rep = parseRepetitions();
if (rep <= 2) { if (rep == 2) {
elements.add(new TDateFormatElement.Year(TCalendar.YEAR)); elements.add(new TDateFormatElement.Year(TCalendar.YEAR));
} else { } else {
elements.add(new TDateFormatElement.Numeric(TCalendar.YEAR, rep)); elements.add(new TDateFormatElement.Numeric(TCalendar.YEAR, rep));

View File

@ -612,6 +612,24 @@ LongInt_add = function(a, b) {
a.hi = (a_hilo & 0xFFFF) | (a_hihi << 16); a.hi = (a_hilo & 0xFFFF) | (a_hihi << 16);
a.sup = sup; a.sup = sup;
} }
LongInt_inc = function(a) {
a.lo = (a.lo + 1) | 0;
if (a.lo == 0) {
a.hi = (a.hi + 1) | 0;
if (a.hi == 0) {
a.sup = (a.sup + 1) | 0xFFFF;
}
}
}
LongInt_dec = function(a) {
a.lo = (a.lo - 1) | 0;
if (a.lo == -1) {
a.hi = (a.hi - 1) | 0;
if (a.hi == -1) {
a.sup = (a.sup - 1) | 0xFFFF;
}
}
}
LongInt_ucompare = function(a, b) { LongInt_ucompare = function(a, b) {
var r = (a.sup - b.sup); var r = (a.sup - b.sup);
if (r != 0) { if (r != 0) {
@ -696,7 +714,7 @@ LongInt_div = function(a, b) {
if (LongInt_ucompare(t, a) >= 0) { if (LongInt_ucompare(t, a) >= 0) {
while (LongInt_ucompare(t, a) > 0) { while (LongInt_ucompare(t, a) > 0) {
LongInt_sub(t, b); LongInt_sub(t, b);
q = (q - 1) | 0; --digit;
} }
} else { } else {
while (true) { while (true) {
@ -706,7 +724,7 @@ LongInt_div = function(a, b) {
break; break;
} }
t = nextT; t = nextT;
q = (q + 1) | 0; ++digit;
} }
} }
LongInt_sub(a, t); LongInt_sub(a, t);