blob: 83da8ce778f217587f876bee9be4fe0f79ef0879 [file] [log] [blame]
// © 2016 and later: Unicode, Inc. and others.
// License & terms of use: http://www.unicode.org/copyright.html#License
/*
*******************************************************************************
* Copyright (C) 2009,2016 International Business Machines Corporation and
* others. All Rights Reserved.
*******************************************************************************
*/
package com.ibm.icu.impl;
import java.util.Locale;
import java.util.Map;
import java.util.MissingResourceException;
import java.util.TreeMap;
import com.ibm.icu.util.ULocale;
import com.ibm.icu.util.UResourceBundle;
/**
* Calendar utilities.
*
* Date/time format service classes in com.ibm.icu.text packages
* sometimes need to access calendar internal APIs. But calendar
* classes are in com.ibm.icu.util package, so the package local
* cannot be used. This class is added in com.ibm.icu.impl
* package for sharing some calendar internal code for calendar
* and date format.
*/
public final class CalendarUtil {
private static final String CALKEY = "calendar";
private static final String DEFCAL = "gregorian";
/**
* Returns a calendar type for the given locale.
* When the given locale has calendar keyword, the
* value of calendar keyword is returned. Otherwise,
* the default calendar type for the locale is returned.
* @param loc The locale
* @return Calendar type string, such as "gregorian"
*/
public static String getCalendarType(ULocale loc) {
String calType = loc.getKeywordValue(CALKEY);
if (calType != null) {
// Convert to lower case, because getKeywordValue does not
// canonicalize keyword value.
return calType.toLowerCase(Locale.ROOT);
}
// Canonicalize, so grandfathered variant will be transformed to keywords
ULocale canonical = ULocale.createCanonical(loc.toString());
calType = canonical.getKeywordValue(CALKEY);
if (calType != null) {
return calType;
}
// When calendar keyword is not available, use the locale's
// region to get the default calendar type
String region = ULocale.getRegionForSupplementalData(canonical, true);
return CalendarPreferences.INSTANCE.getCalendarTypeForRegion(region);
}
private static final class CalendarPreferences extends UResource.Sink {
private static final CalendarPreferences INSTANCE = new CalendarPreferences();
// A TreeMap should be good because we expect very few entries.
Map<String, String> prefs = new TreeMap<String, String>();
CalendarPreferences() {
try {
ICUResourceBundle rb = (ICUResourceBundle)UResourceBundle.getBundleInstance(
ICUData.ICU_BASE_NAME, "supplementalData");
rb.getAllItemsWithFallback("calendarPreferenceData", this);
} catch (MissingResourceException mre) {
// Always use "gregorian".
}
}
String getCalendarTypeForRegion(String region) {
String type = prefs.get(region);
return type == null ? DEFCAL : type;
}
@Override
public void put(UResource.Key key, UResource.Value value, boolean noFallback) {
UResource.Table calendarPreferenceData = value.getTable();
for (int i = 0; calendarPreferenceData.getKeyAndValue(i, key, value); ++i) {
UResource.Array types = value.getArray();
// The first calendar type is the default for the region.
if (types.getValue(0, value)) {
String type = value.getString();
if (!type.equals(DEFCAL)) {
prefs.put(key.toString(), type);
}
}
}
}
}
}