Locale ES_PE is not rendering number properly - java

Locale planet specified that the es_PE locale should use "." for decimal and "," for grouping. But when I run this unit test on the Oracle JVM it fails:
public class TestLocale extends TestCase {
public void test() {
Locale locale = new Locale("es", "PE");
DecimalFormatSymbols decimalFormatSymbols = new DecimalFormatSymbols(locale);
assertEquals('.', decimalFormatSymbols.getDecimalSeparator());
assertEquals(',', decimalFormatSymbols.getGroupingSeparator());
}
}
And it was reported by our support staff that numbers are no rendering correctly on WAS 8 either.
Any idea how to fix this at the JVM level? Do I need to juggle the locale management code in the application for this special case?

Change
Locale locale = new Locale("es", "PE");
to
Locale locale = new Locale("es_PE");
By the way, PE is from Peru (where I'm from).

Related

Use Android ICU NumberFormat with only the JVM

Android has the ICU library NumberFormat which allows formatting currencies in different ways, in my specific case I need it as ISOCURRENCYSTYLE. This works great but only works on Android.
Java as its own implementation of NumberFormat with an instance builder called getCurrencyInstance, which internally uses a default currency style and doesn't allow to specify it.
Some of the differences are:
BE_FR | Android: 123,12 EUR | Java: 123,12 €
BE_NL | Android: EUR 123,12 | Java: € 123,12
BE_EN | Android: EUR 123.12 | Java: €123,12
GE_GE | Android: EUR 123.12 | Java: €123.12
FR_FR | Android: 123,12 EUR | Java: 123,12 €
Is there a way to get the same Android output but only within the JVM, without using any external library?
A solution is to replace the prefix and the suffix of the DecimalFormat with the currency code:
import java.text.*;
import java.util.Locale;
public class Test
{
public static DecimalFormat geCurrencyFormat(Locale locale)
{
DecimalFormat df = (DecimalFormat)NumberFormat.getCurrencyInstance(locale);
String code = df.getCurrency().getCurrencyCode();
if(!df.getPositivePrefix().isEmpty())
{
df.setPositivePrefix(code + " ");
df.setNegativePrefix(code + " -");
}
if(!df.getPositiveSuffix().isEmpty())
{
df.setPositiveSuffix(" " + code);
df.setNegativeSuffix(" " + code);
}
return df;
}
public static void test(Locale locale)
{
DecimalFormat df = geCurrencyFormat(locale);
System.out.println(df.format(123.12));
}
public static void main(String args[])
{
test(new Locale("fr", "BE"));
test(new Locale("nl", "BE"));
test(new Locale("en", "GB"));
}
}
Output:
123,12 EUR
EUR 123,12
GBP 123.12
Unfortunately not. You can get the three-letter ISO 4217 codes using Currency and hand-craft things like:
Locale locale = Locale.FRANCE;
float amount = 123.1f;
NumberFormat nf = NumberFormat.getInstance(locale);
Currency currency = Currency.getInstance(locale);
String formattedAmount = nf.format(amount) + " " + currency.getCurrencyCode());
However, Android is using ICU code to correctly order the value and units in the currency string. This is not in the standard Java JDKs.
I understand you don't want to use a library, so this is out of scope of the required answer. However, should you choose to use a library, take a look at ICU4J https://unicode-org.github.io/icu/userguide/icu4j/. It includes a NumberFormat with ISOCURRENCYSTYLE matching the Android behaviour.

How do I set the date to the current day in Korea or anywhere else?

So, I got the time to be in Korean time with this code:
formatClock = new SimpleDateFormat("hh:mm:ss a");
formatClock.setTimeZone(TimeZone.getTimeZone("Asia/Seoul"));
However, how do I set the date to the current day in Korean?
For instance, I want it to output Sunday 7/23/2017.
Old API
Use another SimpleDateFormat with the desired format, and use java.util.Locale to explicity uses the English names for days of the week:
SimpleDateFormat sdf = new SimpleDateFormat("EEEE M/dd/yyyy", Locale.ENGLISH);
sdf.setTimeZone(TimeZone.getTimeZone("Asia/Seoul"));
System.out.println(sdf.format(new Date()));
The output will be:
Sunday 7/23/2017
If you don't specify the locale, it uses the system's default, which is not guaranteed to always be English (and it can also be changed without notice, even at runtime, so it's always better to make it explicit in your code by using a proper Locale, if you always want the days of the week in English - or in any other language).
Java new Date/Time API
The old classes (Date, Calendar and SimpleDateFormat) have lots of problems and design issues, and they're being replaced by the new APIs.
If you're using Java 8, consider using the new java.time API. It's easier, less bugged and less error-prone than the old APIs.
If you're using Java <= 7, you can use the ThreeTen Backport, a great backport for Java 8's new date/time classes. And for Android, there's the ThreeTenABP (more on how to use it here).
The code below works for both.
The only difference is the package names (in Java 8 is java.time and in ThreeTen Backport (or Android's ThreeTenABP) is org.threeten.bp), but the classes and methods names are the same.
To get the current date in a timezone, you can use a LocalDate (a date with day/month/year) with a ZoneId (a timezone), and you use a DateTimeFormatter to format it:
// Korean timezone
ZoneId zone = ZoneId.of("Asia/Seoul");
// current date in Korea timezone
LocalDate currentDateInKorea = LocalDate.now(zone);
// formatter (use English locale to correctly use English name for day of week)
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("EEEE M/dd/yyyy", Locale.ENGLISH);
System.out.println(fmt.format(currentDateInKorea));
The output will be:
Sunday 7/23/2017
Note: a java.util.Date itself has no format, it just represents the number of milliseconds since epoch (1970-01-01T00:00Z). What we're doing here is just changing the representation of this value in a specific format, for a specific timezone.
suppose you should try like this.
This should display 'Sun 7/23/2017':
new SimpleDateFormat("EEE dd/MM/yyyy").format(new Date());
This should display 'Sunday 7/23/2017':
new SimpleDateFormat("EEEE dd/MM/yyyy").format(new Date());
If you want leading zero in month then use MM else use M.
NOTE: View all valid time zones by TimeZone.getAvailableIDs()
import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Date;
import java.util.TimeZone;
public class Time {
/**
* #param args
*/
public static void main(String[] args) throws Exception {
// Day month/date/year
SimpleDateFormat formatClock = new SimpleDateFormat("EEEE MM/dd/yyyy");
formatClock.setTimeZone(TimeZone.getTimeZone("Asia/Seoul"));
System.out.println(formatClock.format(new Date()));
System.out.println();
// FYI You can check Available TimeZones as follows
System.out.println(Arrays.toString(TimeZone.getAvailableIDs()));
}
}
Sample Run
Sunday 07/23/2017
[Etc/GMT+12, Etc/GMT+11, Pacific/Midway, Pacific/Niue, Pacific/Pago_Pago, Pacific/Samoa, US/Samoa, America/Adak, America/Atka, Etc/GMT+10, HST, Pacific/Honolulu, Pacific/Johnston, Pacific/Rarotonga, Pacific/Tahiti, SystemV/HST10, US/Aleutian, US/Hawaii, Pacific/Marquesas, AST, America/Anchorage, America/Juneau, America/Nome, America/Sitka, America/Yakutat, Etc/GMT+9, Pacific/Gambier, SystemV/YST9, SystemV/YST9YDT, US/Alaska, America/Dawson, America/Ensenada, America/Los_Angeles, America/Metlakatla, America/Santa_Isabel, America/Tijuana, America/Vancouver, America/Whitehorse, Canada/Pacific, Canada/Yukon, Etc/GMT+8, Mexico/BajaNorte, PST, PST8PDT, Pacific/Pitcairn, SystemV/PST8, SystemV/PST8PDT, US/Pacific, US/Pacific-New, America/Boise, America/Cambridge_Bay, America/Chihuahua, America/Creston, America/Dawson_Creek, America/Denver, America/Edmonton, America/Hermosillo, America/Inuvik, America/Mazatlan, America/Ojinaga, America/Phoenix, America/Shiprock, America/Yellowknife, Canada/Mountain, Etc/GMT+7, MST, MST7MDT, Mexico/BajaSur, Navajo, PNT, SystemV/MST7, SystemV/MST7MDT, US/Arizona, US/Mountain, America/Bahia_Banderas, America/Belize, America/Cancun, America/Chicago, America/Costa_Rica, America/El_Salvador, America/Guatemala, America/Indiana/Knox, America/Indiana/Tell_City, America/Knox_IN, America/Managua, America/Matamoros, America/Menominee, America/Merida, America/Mexico_City, America/Monterrey, America/North_Dakota/Beulah, America/North_Dakota/Center, America/North_Dakota/New_Salem, America/Rainy_River, America/Rankin_Inlet, America/Regina, America/Resolute, America/Swift_Current, America/Tegucigalpa, America/Winnipeg, CST, CST6CDT, Canada/Central, Canada/East-Saskatchewan, Canada/Saskatchewan, Chile/EasterIsland, Etc/GMT+6, Mexico/General, Pacific/Easter, Pacific/Galapagos, SystemV/CST6, SystemV/CST6CDT, US/Central, US/Indiana-Starke, America/Atikokan, America/Bogota, America/Cayman, America/Coral_Harbour, America/Detroit, America/Fort_Wayne, America/Grand_Turk, America/Guayaquil, America/Havana, America/Indiana/Indianapolis, America/Indiana/Marengo, America/Indiana/Petersburg, America/Indiana/Vevay, America/Indiana/Vincennes, America/Indiana/Winamac, America/Indianapolis, America/Iqaluit, America/Jamaica, America/Kentucky/Louisville, America/Kentucky/Monticello, America/Lima, America/Louisville, America/Montreal, America/Nassau, America/New_York, America/Nipigon, America/Panama, America/Pangnirtung, America/Port-au-Prince, America/Thunder_Bay, America/Toronto, Canada/Eastern, Cuba, EST, EST5EDT, Etc/GMT+5, IET, Jamaica, SystemV/EST5, SystemV/EST5EDT, US/East-Indiana, US/Eastern, US/Michigan, America/Caracas, America/Anguilla, America/Antigua, America/Argentina/San_Luis, America/Aruba, America/Asuncion, America/Barbados, America/Blanc-Sablon, America/Boa_Vista, America/Campo_Grande, America/Cuiaba, America/Curacao, America/Dominica, America/Eirunepe, America/Glace_Bay, America/Goose_Bay, America/Grenada, America/Guadeloupe, America/Guyana, America/Halifax, America/Kralendijk, America/La_Paz, America/Lower_Princes, America/Manaus, America/Marigot, America/Martinique, America/Moncton, America/Montserrat, America/Port_of_Spain, America/Porto_Acre, America/Porto_Velho, America/Puerto_Rico, America/Rio_Branco, America/Santiago, America/Santo_Domingo, America/St_Barthelemy, America/St_Kitts, America/St_Lucia, America/St_Thomas, America/St_Vincent, America/Thule, America/Tortola, America/Virgin, Antarctica/Palmer, Atlantic/Bermuda, Brazil/Acre, Brazil/West, Canada/Atlantic, Chile/Continental, Etc/GMT+4, PRT, SystemV/AST4, SystemV/AST4ADT, America/St_Johns, CNT, Canada/Newfoundland, AGT, America/Araguaina, America/Argentina/Buenos_Aires, America/Argentina/Catamarca, America/Argentina/ComodRivadavia, America/Argentina/Cordoba, America/Argentina/Jujuy, America/Argentina/La_Rioja, America/Argentina/Mendoza, America/Argentina/Rio_Gallegos, America/Argentina/Salta, America/Argentina/San_Juan, America/Argentina/Tucuman, America/Argentina/Ushuaia, America/Bahia, America/Belem, America/Buenos_Aires, America/Catamarca, America/Cayenne, America/Cordoba, America/Fortaleza, America/Godthab, America/Jujuy, America/Maceio, America/Mendoza, America/Miquelon, America/Montevideo, America/Paramaribo, America/Recife, America/Rosario, America/Santarem, America/Sao_Paulo, Antarctica/Rothera, Atlantic/Stanley, BET, Brazil/East, Etc/GMT+3, America/Noronha, Atlantic/South_Georgia, Brazil/DeNoronha, Etc/GMT+2, America/Scoresbysund, Atlantic/Azores, Atlantic/Cape_Verde, Etc/GMT+1, Africa/Abidjan, Africa/Accra, Africa/Bamako, Africa/Banjul, Africa/Bissau, Africa/Casablanca, Africa/Conakry, Africa/Dakar, Africa/El_Aaiun, Africa/Freetown, Africa/Lome, Africa/Monrovia, Africa/Nouakchott, Africa/Ouagadougou, Africa/Sao_Tome, Africa/Timbuktu, America/Danmarkshavn, Atlantic/Canary, Atlantic/Faeroe, Atlantic/Faroe, Atlantic/Madeira, Atlantic/Reykjavik, Atlantic/St_Helena, Eire, Etc/GMT, Etc/GMT+0, Etc/GMT-0, Etc/GMT0, Etc/Greenwich, Etc/UCT, Etc/UTC, Etc/Universal, Etc/Zulu, Europe/Belfast, Europe/Dublin, Europe/Guernsey, Europe/Isle_of_Man, Europe/Jersey, Europe/Lisbon, Europe/London, GB, GB-Eire, GMT, GMT0, Greenwich, Iceland, Portugal, UCT, UTC, Universal, WET, Zulu, Africa/Algiers, Africa/Bangui, Africa/Brazzaville, Africa/Ceuta, Africa/Douala, Africa/Kinshasa, Africa/Lagos, Africa/Libreville, Africa/Luanda, Africa/Malabo, Africa/Ndjamena, Africa/Niamey, Africa/Porto-Novo, Africa/Tripoli, Africa/Tunis, Africa/Windhoek, Arctic/Longyearbyen, Atlantic/Jan_Mayen, CET, ECT, Etc/GMT-1, Europe/Amsterdam, Europe/Andorra, Europe/Belgrade, Europe/Berlin, Europe/Bratislava, Europe/Brussels, Europe/Budapest, Europe/Busingen, Europe/Copenhagen, Europe/Gibraltar, Europe/Ljubljana, Europe/Luxembourg, Europe/Madrid, Europe/Malta, Europe/Monaco, Europe/Oslo, Europe/Paris, Europe/Podgorica, Europe/Prague, Europe/Rome, Europe/San_Marino, Europe/Sarajevo, Europe/Skopje, Europe/Stockholm, Europe/Tirane, Europe/Vaduz, Europe/Vatican, Europe/Vienna, Europe/Warsaw, Europe/Zagreb, Europe/Zurich, Libya, MET, Poland, ART, Africa/Blantyre, Africa/Bujumbura, Africa/Cairo, Africa/Gaborone, Africa/Harare, Africa/Johannesburg, Africa/Kigali, Africa/Lubumbashi, Africa/Lusaka, Africa/Maputo, Africa/Maseru, Africa/Mbabane, Asia/Amman, Asia/Beirut, Asia/Damascus, Asia/Gaza, Asia/Hebron, Asia/Istanbul, Asia/Jerusalem, Asia/Nicosia, Asia/Tel_Aviv, CAT, EET, Egypt, Etc/GMT-2, Europe/Athens, Europe/Bucharest, Europe/Chisinau, Europe/Helsinki, Europe/Istanbul, Europe/Kiev, Europe/Mariehamn, Europe/Nicosia, Europe/Riga, Europe/Simferopol, Europe/Sofia, Europe/Tallinn, Europe/Tiraspol, Europe/Uzhgorod, Europe/Vilnius, Europe/Zaporozhye, Israel, Turkey, Africa/Addis_Ababa, Africa/Asmara, Africa/Asmera, Africa/Dar_es_Salaam, Africa/Djibouti, Africa/Juba, Africa/Kampala, Africa/Khartoum, Africa/Mogadishu, Africa/Nairobi, Antarctica/Syowa, Asia/Aden, Asia/Baghdad, Asia/Bahrain, Asia/Kuwait, Asia/Qatar, Asia/Riyadh, EAT, Etc/GMT-3, Europe/Kaliningrad, Europe/Minsk, Indian/Antananarivo, Indian/Comoro, Indian/Mayotte, Asia/Riyadh87, Asia/Riyadh88, Asia/Riyadh89, Mideast/Riyadh87, Mideast/Riyadh88, Mideast/Riyadh89, Asia/Tehran, Iran, Asia/Baku, Asia/Dubai, Asia/Muscat, Asia/Tbilisi, Asia/Yerevan, Etc/GMT-4, Europe/Moscow, Europe/Samara, Europe/Volgograd, Indian/Mahe, Indian/Mauritius, Indian/Reunion, NET, W-SU, Asia/Kabul, Antarctica/Mawson, Asia/Aqtau, Asia/Aqtobe, Asia/Ashgabat, Asia/Ashkhabad, Asia/Dushanbe, Asia/Karachi, Asia/Oral, Asia/Samarkand, Asia/Tashkent, Etc/GMT-5, Indian/Kerguelen, Indian/Maldives, PLT, Asia/Calcutta, Asia/Colombo, Asia/Kolkata, IST, Asia/Kathmandu, Asia/Katmandu, Antarctica/Vostok, Asia/Almaty, Asia/Bishkek, Asia/Dacca, Asia/Dhaka, Asia/Qyzylorda, Asia/Thimbu, Asia/Thimphu, Asia/Yekaterinburg, BST, Etc/GMT-6, Indian/Chagos, Asia/Rangoon, Indian/Cocos, Antarctica/Davis, Asia/Bangkok, Asia/Ho_Chi_Minh, Asia/Hovd, Asia/Jakarta, Asia/Novokuznetsk, Asia/Novosibirsk, Asia/Omsk, Asia/Phnom_Penh, Asia/Pontianak, Asia/Saigon, Asia/Vientiane, Etc/GMT-7, Indian/Christmas, VST, Antarctica/Casey, Asia/Brunei, Asia/Choibalsan, Asia/Chongqing, Asia/Chungking, Asia/Harbin, Asia/Hong_Kong, Asia/Kashgar, Asia/Krasnoyarsk, Asia/Kuala_Lumpur, Asia/Kuching, Asia/Macao, Asia/Macau, Asia/Makassar, Asia/Manila, Asia/Shanghai, Asia/Singapore, Asia/Taipei, Asia/Ujung_Pandang, Asia/Ulaanbaatar, Asia/Ulan_Bator, Asia/Urumqi, Australia/Perth, Australia/West, CTT, Etc/GMT-8, Hongkong, PRC, Singapore, Australia/Eucla, Asia/Dili, Asia/Irkutsk, Asia/Jayapura, Asia/Pyongyang, Asia/Seoul, Asia/Tokyo, Etc/GMT-9, JST, Japan, Pacific/Palau, ROK, ACT, Australia/Adelaide, Australia/Broken_Hill, Australia/Darwin, Australia/North, Australia/South, Australia/Yancowinna, AET, Antarctica/DumontDUrville, Asia/Khandyga, Asia/Yakutsk, Australia/ACT, Australia/Brisbane, Australia/Canberra, Australia/Currie, Australia/Hobart, Australia/Lindeman, Australia/Melbourne, Australia/NSW, Australia/Queensland, Australia/Sydney, Australia/Tasmania, Australia/Victoria, Etc/GMT-10, Pacific/Chuuk, Pacific/Guam, Pacific/Port_Moresby, Pacific/Saipan, Pacific/Truk, Pacific/Yap, Australia/LHI, Australia/Lord_Howe, Antarctica/Macquarie, Asia/Sakhalin, Asia/Ust-Nera, Asia/Vladivostok, Etc/GMT-11, Pacific/Efate, Pacific/Guadalcanal, Pacific/Kosrae, Pacific/Noumea, Pacific/Pohnpei, Pacific/Ponape, SST, Pacific/Norfolk, Antarctica/McMurdo, Antarctica/South_Pole, Asia/Anadyr, Asia/Kamchatka, Asia/Magadan, Etc/GMT-12, Kwajalein, NST, NZ, Pacific/Auckland, Pacific/Fiji, Pacific/Funafuti, Pacific/Kwajalein, Pacific/Majuro, Pacific/Nauru, Pacific/Tarawa, Pacific/Wake, Pacific/Wallis, NZ-CHAT, Pacific/Chatham, Etc/GMT-13, MIT, Pacific/Apia, Pacific/Enderbury, Pacific/Fakaofo, Pacific/Tongatapu, Etc/GMT-14, Pacific/Kiritimati]
Below is the code to do it
import java.text.SimpleDateFormat;
import java.util.Date;
public class Test {
public static void main(String[] args) {
// TODO Auto-generated method stub
SimpleDateFormat format = new SimpleDateFormat("E, dd/MM/yyyy");
// DateToStr = format.format(new Date());
System.out.println(format.format(new Date()));
}
}
Link for different formats https://examples.javacodegeeks.com/core-java/text/java-simpledateformat-example/

What does Java's SimpleDateFormat make with milli/micro-seconds?

I have simple test
#SuppressWarnings("deprecation")
#Test
public void test_NO_MILLIS() throws ParseException {
String rabbit = "22-OCT-15 06.37.35";
final String PATTERN = "dd-MMM-yy HH.mm.ss";
Date dateObject = new SimpleDateFormat(PATTERN).parse(rabbit);
Assert.assertNotNull(dateObject);
Assert.assertEquals(22, dateObject.getDate());
Assert.assertEquals(10, dateObject.getMonth() + 1);
Assert.assertEquals(2015, dateObject.getYear() + 1900);
Assert.assertEquals(6, dateObject.getHours());
Assert.assertEquals(37, dateObject.getMinutes());
Assert.assertEquals(35, dateObject.getSeconds());
}
And everything goes right. I get 22 as day in result.
But after I am adding microseconds both to pattern and to string value to be parsed
#Test
public void test_MILLIS() throws ParseException {
String rabbit = "22-OCT-15 06.37.35.586173000";
final String PATTERN = "dd-MMM-yy HH.mm.ss.SSSSSSSSS";
Date dateObject = new SimpleDateFormat(PATTERN).parse(rabbit);
Assert.assertNotNull(dateObject);
Assert.assertEquals(22, dateObject.getDate());
Assert.assertEquals(10, dateObject.getMonth() + 1);
Assert.assertEquals(2015, dateObject.getYear() + 1900);
Assert.assertEquals(6, dateObject.getHours());
Assert.assertEquals(37, dateObject.getMinutes());
Assert.assertEquals(35, dateObject.getSeconds());
}
I get an assert failure
junit.framework.AssertionFailedError: expected:<22> but was:<29>
at junit.framework.Assert.fail(Assert.java:57)
at junit.framework.Assert.failNotEquals(Assert.java:329)
at junit.framework.Assert.assertEquals(Assert.java:78)
at junit.framework.Assert.assertEquals(Assert.java:234)
at junit.framework.Assert.assertEquals(Assert.java:241)
at main.TestDateFormatTest.test_MILLIS(TestDateFormatTest.java:36)
...
Which means that day has become 29 instead of 22. What has gone wrong?
Tested
Platforms: mac osx 10.9, ubuntu, win7
jdk: 7,6
The format pattern S for milliseconds doesn't take into account mathematical placement values; it just sees 586173000 as the number of milliseconds to add to the rest of the date. That number is equivalent to about 6.784 days, so that explains why the date became 29 instead of 22.
Before parsing, cut off the milliseconds at 3 digits, e.g. "22-OCT-15 06.37.35.586", so it's interpreted as 586 milliseconds.

java: default number-formatting

I have a program that does algorithmic calculations with some number-output. I want this output to look nice and the program still being fast. I used the DecumalFormat but this makes it so slow, but works.
Is there a way to set the default number output so I wouldnt need DecimalFormat???
Locale deLocale = new Locale("de_DE");
// should be format: ###,###.### 123.456,789 de_DE
Locale.setDefault (deLocale);
double f=-123456.123458998;
System.out.println (""+f+""); // I wourld expect -123.456,123
// but the output is -123456.123458998
any ideas?? thanks!
chris
You need to look at the Customizing Format.
You need a ###,###.### - de_DE pattern.
String pattern= "###,###.###";
DecimalFormat myFormatter = new DecimalFormat(pattern);
double f=-123456.123458998;
String output = myFormatter.format(f);
System.out.println(f+ " " + pattern + " " + output);
EDIT : Use Predefined format, in case you don't want your own pattern.

non standard locale with java.util.Calendar

We have a customer in Sweden, using the software in English. So we set the Locale(en, SV). We did hope the Calendar class would adhere to the country settings, but it uses the language and with this locale it assumes US settings.
So I am now searching for a way to let the calendar get to know the new firstDayOfWeek and minimumDayinFirstWeek settings preferred by a standard way other than setting it manually and thus hardcoded.
For clarification: The 29. August 2010 is in Sweden in CW 34 (also in Germany and Great Britain) but in the US it is reported as CW 36. The different results from the fact that the 01.01.2010 is a Friday and the 29.08.2010 a Sunday.
I cannot change the language setting itself to Swedish and use the English fallback since we do not support Swedish as language, but Sun/Oracle/.. does, so the Swing UI would have a mixture of Swedish and English texts, which not acceptable.
And just adding a properties file named "sun.util.resources.CalendarData_en_SV.properties" does not work out: it does not get read! Manually as a ResourceBundle that's possible. Somehow LocaleData.getCalendarData(Locale) does its own magic in reading the resourcfiles which i cannot find out since the source of it is not available. The method is called here: java.util.Calendar.setWeekCountData(Locale).
I also found the java.util.spi package but it does not provide access to the firstDayOfWeek and minimumDaysInFirstWeek settings.
Perhaps I can try to intercept the calls to the resourcebundles and use the default fallback to English and only let the calls to CalendarData proceed!? But that sounds hacky.
package de.drews.i18n;
import java.util.Calendar;
import java.util.Locale;
import java.util.ResourceBundle;
public class Test {
/**
* #param args
*/
public static void main(String[] args) {
// en_GB = 34
// en_US = 36
// sv_SV = 34
// en_SV = 36 --> wrong
printTest("en", "GB", 34);
printTest("en", "US", 36);
printTest("sv", "SV", 34);
printTest("en", "SV", 34);
}
private static void printTest(String language, String country, int expected) {
Locale locale = new Locale(language, country);
Calendar cal = Calendar.getInstance(locale);
cal.set(Calendar.YEAR, 2010);
cal.set(Calendar.MONTH, Calendar.AUGUST);
cal.set(Calendar.DATE, 29);
int actual = cal.get(Calendar.WEEK_OF_YEAR);
System.out.println(actual + "\t" + expected + "\t"
+ ((actual == expected) ? "Yeah!" : "-") + "\t" + language
+ "\t" + country);
}
}
How about using getInstance(TimeZone zone, Locale aLocale) providing a timezone to select calendar behaviour and locale to define language?
One ugly workaround that I can offer is to reflectively obtain the cachedLocaleData static field of the Calendar class, and put there the following:
key = new Locale(..); // your english-swedish locale
value = new int[] {firstDayOfWeek, minimalDaysInFirstWeek};
This can be done at init-time and will work for the entire application

Categories