mirror of
https://github.com/konsoletyper/teavm.git
synced 2025-01-06 10:15:18 +08:00
Add localization for time zones
This commit is contained in:
parent
55212cbfe6
commit
7a2c2606aa
@ -129,7 +129,9 @@ public class DateTimeZoneProvider {
|
||||
}
|
||||
}
|
||||
|
||||
if (scoreTable.get(0).tz.previousTransition(time) == time) {
|
||||
if (scoreTable.size() == 1 || scoreTable.get(0).tz.previousTransition(time) == time) {
|
||||
return scoreTable.get(0).tz;
|
||||
} else if (scoreTable.size() > 1 && scoreTable.get(0).value + 48 * 7 < scoreTable.get(1).value) {
|
||||
return scoreTable.get(0).tz;
|
||||
}
|
||||
|
||||
|
@ -90,6 +90,34 @@ public class CLDRHelper {
|
||||
return result;
|
||||
}
|
||||
|
||||
public static String getTimeZoneName(String language, String country, String id) {
|
||||
String locale = getCode(language, country);
|
||||
if (!getTimeZoneLocalizationMap().has(locale)) {
|
||||
return null;
|
||||
}
|
||||
TimeZoneLocalization localization = getTimeZoneLocalizationMap().get(locale);
|
||||
|
||||
int separator = id.indexOf('/');
|
||||
if (separator < 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
String area = id.substring(0, separator);
|
||||
String territory = id.substring(separator + 1);
|
||||
if (!localization.getTimeZones().has(area)) {
|
||||
return null;
|
||||
}
|
||||
ResourceMap<StringResource> timeZones = localization.getTimeZones().get(area);
|
||||
|
||||
if (!timeZones.has(territory)) {
|
||||
return null;
|
||||
}
|
||||
return timeZones.get(territory).getValue();
|
||||
}
|
||||
|
||||
@MetadataProvider(TimeZoneLocalizationGenerator.class)
|
||||
public static native ResourceMap<TimeZoneLocalization> getTimeZoneLocalizationMap();
|
||||
|
||||
@MetadataProvider(LanguageMetadataGenerator.class)
|
||||
public static native ResourceMap<ResourceMap<StringResource>> getLanguagesMap();
|
||||
|
||||
|
@ -36,6 +36,7 @@ public class CLDRLocale {
|
||||
CLDRDateFormats dateFormats;
|
||||
CLDRDateFormats timeFormats;
|
||||
CLDRDateFormats dateTimeFormats;
|
||||
CLDRTimeZone[] timeZones;
|
||||
|
||||
public Map<String, String> getLanguages() {
|
||||
return Collections.unmodifiableMap(languages);
|
||||
@ -80,4 +81,8 @@ public class CLDRLocale {
|
||||
public CLDRDateFormats getDateTimeFormats() {
|
||||
return dateTimeFormats;
|
||||
}
|
||||
|
||||
public CLDRTimeZone[] getTimeZones() {
|
||||
return timeZones.clone();
|
||||
}
|
||||
}
|
||||
|
@ -111,6 +111,9 @@ public class CLDRReader {
|
||||
case "territories.json":
|
||||
readCountries(localeName, localeInfo, input);
|
||||
break;
|
||||
case "timeZoneNames.json":
|
||||
readTimeZones(localeName, localeInfo, input);
|
||||
break;
|
||||
case "ca-gregorian.json": {
|
||||
JsonObject root = (JsonObject)new JsonParser().parse(new InputStreamReader(input));
|
||||
readEras(localeName, localeInfo, root);
|
||||
@ -155,6 +158,36 @@ public class CLDRReader {
|
||||
}
|
||||
}
|
||||
|
||||
private void readTimeZones(String localeCode, CLDRLocale locale, InputStream input) {
|
||||
JsonObject root = (JsonObject)new JsonParser().parse(new InputStreamReader(input));
|
||||
JsonObject zonesJson = root.get("main").getAsJsonObject().get(localeCode).getAsJsonObject()
|
||||
.get("dates").getAsJsonObject().get("timeZoneNames").getAsJsonObject().get("zone")
|
||||
.getAsJsonObject();
|
||||
List<CLDRTimeZone> timeZones = new ArrayList<>();
|
||||
for (Map.Entry<String, JsonElement> area : zonesJson.entrySet()) {
|
||||
String areaName = area.getKey();
|
||||
for (Map.Entry<String, JsonElement> location : area.getValue().getAsJsonObject().entrySet()) {
|
||||
String locationName = location.getKey();
|
||||
JsonElement city = location.getValue().getAsJsonObject().get("exemplarCity");
|
||||
if (city != null) {
|
||||
CLDRTimeZone tz = new CLDRTimeZone(areaName, locationName, city.getAsString());
|
||||
timeZones.add(tz);
|
||||
} else {
|
||||
for (Map.Entry<String, JsonElement> sublocation : location.getValue()
|
||||
.getAsJsonObject().entrySet()) {
|
||||
city = location.getValue().getAsJsonObject().get("exemplarCity");
|
||||
if (city != null) {
|
||||
CLDRTimeZone tz = new CLDRTimeZone(areaName, locationName + "/" + sublocation.getKey(),
|
||||
city.getAsString());
|
||||
timeZones.add(tz);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
locale.timeZones = timeZones.toArray(new CLDRTimeZone[timeZones.size()]);
|
||||
}
|
||||
|
||||
private void readEras(String localeCode, CLDRLocale locale, JsonObject root) {
|
||||
JsonObject erasJson = root.get("main").getAsJsonObject().get(localeCode).getAsJsonObject()
|
||||
.get("dates").getAsJsonObject().get("calendars").getAsJsonObject()
|
||||
|
@ -0,0 +1,44 @@
|
||||
/*
|
||||
* Copyright 2015 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 CLDRTimeZone {
|
||||
String area;
|
||||
String location;
|
||||
String name;
|
||||
|
||||
CLDRTimeZone(String area, String location, String name) {
|
||||
this.area = area;
|
||||
this.location = location;
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getArea() {
|
||||
return area;
|
||||
}
|
||||
|
||||
public String getLocation() {
|
||||
return location;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
}
|
@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Copyright 2015 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;
|
||||
import org.teavm.platform.metadata.ResourceMap;
|
||||
import org.teavm.platform.metadata.StringResource;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public interface TimeZoneLocalization extends Resource {
|
||||
ResourceMap<ResourceMap<StringResource>> getTimeZones();
|
||||
|
||||
void setTimeZones(ResourceMap<ResourceMap<StringResource>> timeZones);
|
||||
}
|
@ -0,0 +1,51 @@
|
||||
/*
|
||||
* Copyright 2015 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 java.util.Map;
|
||||
import org.teavm.model.MethodReference;
|
||||
import org.teavm.platform.metadata.*;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Alexey Andreev
|
||||
*/
|
||||
public class TimeZoneLocalizationGenerator implements MetadataGenerator {
|
||||
@Override
|
||||
public Resource generateMetadata(MetadataGeneratorContext context, MethodReference method) {
|
||||
CLDRReader cldr = context.getService(CLDRReader.class);
|
||||
ResourceMap<TimeZoneLocalization> localizations = context.createResourceMap();
|
||||
for (Map.Entry<String, CLDRLocale> locale : cldr.getKnownLocales().entrySet()) {
|
||||
TimeZoneLocalization localization = context.createResource(TimeZoneLocalization.class);
|
||||
ResourceMap<ResourceMap<StringResource>> map = context.createResourceMap();
|
||||
localization.setTimeZones(map);
|
||||
localizations.put(locale.getKey(), localization);
|
||||
|
||||
for (CLDRTimeZone tz : locale.getValue().getTimeZones()) {
|
||||
ResourceMap<StringResource> area;
|
||||
if (!map.has(tz.getArea())) {
|
||||
area = context.createResourceMap();
|
||||
map.put(tz.getArea(), area);
|
||||
}
|
||||
area = map.get(tz.getArea());
|
||||
StringResource name = context.createResource(StringResource.class);
|
||||
name.setValue(tz.getName());
|
||||
area.put(tz.getLocation(), name);
|
||||
}
|
||||
}
|
||||
return localizations;
|
||||
}
|
||||
}
|
@ -22,6 +22,7 @@ import java.util.Arrays;
|
||||
import org.teavm.classlib.impl.tz.DateTimeZone;
|
||||
import org.teavm.classlib.impl.tz.DateTimeZoneProvider;
|
||||
import org.teavm.classlib.impl.tz.FixedDateTimeZone;
|
||||
import org.teavm.classlib.impl.unicode.CLDRHelper;
|
||||
|
||||
/**
|
||||
* {@code TimeZone} represents a time zone offset, taking into account
|
||||
@ -84,11 +85,11 @@ public abstract class TTimeZone implements Serializable, Cloneable {
|
||||
*/
|
||||
public static final int LONG = 1;
|
||||
|
||||
private static TTimeZone Default;
|
||||
private static TTimeZone defaultTz;
|
||||
|
||||
static TTimeZone GMT = new TIANATimeZone(new FixedDateTimeZone("GMT", 0, 0));
|
||||
|
||||
private String ID;
|
||||
private String id;
|
||||
|
||||
/**
|
||||
* Constructs a new instance of this class.
|
||||
@ -97,7 +98,7 @@ public abstract class TTimeZone implements Serializable, Cloneable {
|
||||
}
|
||||
|
||||
TTimeZone(String id) {
|
||||
this.ID = id;
|
||||
this.id = id;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -155,10 +156,10 @@ public abstract class TTimeZone implements Serializable, Cloneable {
|
||||
* @return the default time zone.
|
||||
*/
|
||||
public static TTimeZone getDefault() {
|
||||
if (Default == null) {
|
||||
Default = new TIANATimeZone(DateTimeZoneProvider.detectTimezone());
|
||||
if (defaultTz == null) {
|
||||
defaultTz = new TIANATimeZone(DateTimeZoneProvider.detectTimezone());
|
||||
}
|
||||
return (TTimeZone) Default.clone();
|
||||
return (TTimeZone) defaultTz.clone();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -216,8 +217,11 @@ public abstract class TTimeZone implements Serializable, Cloneable {
|
||||
* @return the {@code TimeZone} name.
|
||||
*/
|
||||
public String getDisplayName(boolean daylightTime, int style, TLocale locale) {
|
||||
// TODO: implement via CLDR
|
||||
return null;
|
||||
String name = CLDRHelper.getTimeZoneName(locale.getLanguage(), locale.getCountry(), id);
|
||||
if (name == null) {
|
||||
name = id;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -226,7 +230,7 @@ public abstract class TTimeZone implements Serializable, Cloneable {
|
||||
* @return the time zone ID string.
|
||||
*/
|
||||
public String getID() {
|
||||
return ID;
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -416,7 +420,7 @@ public abstract class TTimeZone implements Serializable, Cloneable {
|
||||
* a {@code TimeZone} object.
|
||||
*/
|
||||
public static void setDefault(TTimeZone timezone) {
|
||||
Default = timezone != null ? (TTimeZone)timezone.clone() : null;
|
||||
defaultTz = timezone != null ? (TTimeZone)timezone.clone() : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -429,7 +433,7 @@ public abstract class TTimeZone implements Serializable, Cloneable {
|
||||
if (name == null) {
|
||||
throw new NullPointerException();
|
||||
}
|
||||
ID = name;
|
||||
id = name;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -22,9 +22,9 @@ import static org.junit.Assert.assertNotSame;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.Locale;
|
||||
import java.util.TimeZone;
|
||||
import org.junit.Test;
|
||||
import org.teavm.classlib.impl.tz.DateTimeZoneProvider;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -36,6 +36,9 @@ public class TimeZoneTest {
|
||||
@Test
|
||||
public void test_getDefault() {
|
||||
assertNotSame("returns identical", TimeZone.getDefault(), TimeZone.getDefault());
|
||||
for (int i = 0; i < 30; ++i) {
|
||||
DateTimeZoneProvider.detectTimezone();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -100,12 +103,6 @@ public class TimeZoneTest {
|
||||
.getTimeZone("GMT-00").getID());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_getDisplayNameLjava_util_Locale() {
|
||||
TimeZone timezone = TimeZone.getTimeZone("Asia/Shanghai");
|
||||
assertEquals("\u4e2d\u56fd\u6807\u51c6\u65f6\u95f4", timezone.getDisplayName(Locale.CHINA));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_GetTimezoneOffset() {
|
||||
TimeZone tz = TimeZone.getTimeZone("America/Toronto");
|
||||
@ -114,23 +111,4 @@ public class TimeZoneTest {
|
||||
date = new GregorianCalendar(1999, 8, 1).getTime();
|
||||
assertEquals(-240 * 60_000, tz.getOffset(date.getTime()));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_getDisplayName() {
|
||||
TimeZone defaultZone = TimeZone.getDefault();
|
||||
Locale defaulLocal = Locale.getDefault();
|
||||
String defaultName = defaultZone.getDisplayName();
|
||||
String expectedName = defaultZone.getDisplayName(defaulLocal);
|
||||
assertEquals("getDispalyName() did not return the default Locale suitable name", expectedName, defaultName);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_getDisplayName_ZI() {
|
||||
TimeZone defaultZone = TimeZone.getDefault();
|
||||
Locale defaultLocale = Locale.getDefault();
|
||||
String actualName = defaultZone.getDisplayName(false, TimeZone.LONG);
|
||||
String expectedName = defaultZone.getDisplayName(false, TimeZone.LONG, defaultLocale);
|
||||
assertEquals("getDisplayName(daylight,style) did not return the default locale suitable name", expectedName,
|
||||
actualName);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user