我正在开展一个Android
项目,我正在实施本地化。
我将获得区域设置和时区。使用这些信息,我写了下面的代码:
String []locale= User.getInstance().getLanguage().split("-");//Assume, locale[0]=hi, locale[1]=IN
Calendar choosenDate = Calendar.getInstance(new Locale(locale[0],locale[1]));
SimpleDateFormat Dformat = new SimpleDateFormat("MMMM dd yyyy",new Locale(locale[0],locale[1]));
Log.d("MY_APP","***********Newly converted date:"+Dformat.format(choosenDate.getTime()));
我从上面的代码中得到的日志是:
**********Newly converted date:सितंबर 07 2016
所以,基本上我面临的问题只是"MMMM"
,即:月份部分被转换为指定的区域设置(在上面的语言中它是印地语(hi-IN))。但是,"dd yyyy"
未转换为印地语。
有人能告诉我我做错了什么,或者我怎样才能确保即使是dd和yyyy部分也会转换为指定的语言环境。
答案 0 :(得分:2)
看起来很有效:
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
public class Main {
public static void main(String[] args) {
System.out.println("Hello World!");
String []locale = {"hi", "IN"};
Calendar choosenDate = Calendar.getInstance(new Locale(locale[0],locale[1]));
SimpleDateFormat Dformat = new SimpleDateFormat("MMMM dd yyyy",new Locale(locale[0],locale[1]));
System.out.println("MY_APP***********Newly converted date:"+ Dformat.format(choosenDate.getTime() ));
}
}
测试:
/usr/lib/jvm/java-1.8.0-openjdk-amd64/bin/java -agentlib:jdwp=transport=dt_socket,address=127.0.0.1:32790,suspend=y,server=n -Dfile.encoding=UTF-8 -classpath /usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/lib/charsets.jar:/usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/lib/ext/cldrdata.jar:/usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/lib/ext/dnsns.jar:/usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/lib/ext/icedtea-sound.jar:/usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/lib/ext/jaccess.jar:/usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/lib/ext/localedata.jar:/usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/lib/ext/nashorn.jar:/usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/lib/ext/sunec.jar:/usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/lib/ext/sunjce_provider.jar:/usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/lib/ext/sunpkcs11.jar:/usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/lib/ext/zipfs.jar:/usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/lib/jce.jar:/usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/lib/jsse.jar:/usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/lib/management-agent.jar:/usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/lib/resources.jar:/usr/lib/jvm/java-1.8.0-openjdk-amd64/jre/lib/rt.jar:/home/dac/proj/javatest2016/out/production/javatest2016:/home/dac/Downloads/idea-IU-145.972.3/lib/idea_rt.jar Main
Connected to the target VM, address: '127.0.0.1:32790', transport: 'socket'
Hello World!
MY_APP***********Newly converted date:सितंबर ०७ २०१६
Disconnected from the target VM, address: '127.0.0.1:32790', transport: 'socket'
Process finished with exit code 0
您可以尝试使用该计划online。
答案 1 :(得分:2)
显然您希望将数字从阿拉伯风格转换为印度风格,如此Wikipedia article on Arabic-Hindu numerals所示。 (不是我知道关于这个主题的任何。请原谅在这里使用任何语言/国家/传统术语的不当。)
你的问题并没有明显表明你是在追求数字数字的替代方式;发布到Stack Overflow时请更加小心。
仅供参考,我使用现代java.time类运行以下代码,而不是问题中使用的麻烦的遗留日期时间类。我只得到阿拉伯风格的数字。
我遍历任意Locale
个对象的集合。对于每个I循环遍历所有四个FormatStyle
对象,以指定用于自动本地化当前时刻输出的缩写长度。
ZoneId z = ZoneId.of ( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.now ( z );
List<Locale> locales = new ArrayList<> ();
locales.add ( Locale.US );
locales.add ( Locale.CANADA_FRENCH );
locales.add ( Locale.TAIWAN );
locales.add ( new Locale ( "hi" , "IN" ) ); // Hindi, India.
// locales.add ( new Locale ( "ar" , "MA" ) ); // Arabic, Morocco
EnumSet<FormatStyle> formatStyles = EnumSet.allOf ( FormatStyle.class );
for ( Locale locale : locales ) {
System.out.println ( "—————" );
System.out.println ( "Locale: " + locale );
for ( FormatStyle formatStyle : formatStyles ) {
DateTimeFormatter f = DateTimeFormatter.ofLocalizedDateTime ( formatStyle ).withLocale ( locale );
System.out.println ( String.format ( "%1$-" + 20 + "s" , "FormatStyle: " + formatStyle ) + " → " + zdt.format ( f ) );
}
}
System.out.println ( "—————" );
在macOS上运行Java SE 8 Update 102的Oracle实现时。
—————
Locale: en_US
FormatStyle: FULL → Wednesday, September 7, 2016 6:46:00 PM EDT
FormatStyle: LONG → September 7, 2016 6:46:00 PM EDT
FormatStyle: MEDIUM → Sep 7, 2016 6:46:00 PM
FormatStyle: SHORT → 9/7/16 6:46 PM
—————
Locale: fr_CA
FormatStyle: FULL → mercredi 7 septembre 2016 18 h 46 EDT
FormatStyle: LONG → 7 septembre 2016 18:46:00 EDT
FormatStyle: MEDIUM → 2016-09-07 18:46:00
FormatStyle: SHORT → 16-09-07 18:46
—————
Locale: zh_TW
FormatStyle: FULL → 2016年9月7日 星期三 下午06時46分00秒 EDT
FormatStyle: LONG → 2016年9月7日 下午06時46分00秒
FormatStyle: MEDIUM → 2016/9/7 下午 06:46:00
FormatStyle: SHORT → 2016/9/7 下午 6:46
—————
Locale: hi_IN
FormatStyle: FULL → बुधवार, 7 सितंबर, 2016 6:46:00 अपराह्न EDT
FormatStyle: LONG → 7 सितंबर, 2016 6:46:00 अपराह्न EDT
FormatStyle: MEDIUM → 7 सितंबर, 2016 6:46:00 अपराह्न
FormatStyle: SHORT → 7/9/16 6:46 अपराह्न
—————
奇怪的是,当我使用问题中的确切源代码时,我也得到与the Answer by Dac Saunders Hindu/Indian-style numerals中看到的输出相同的输出。
所以我简化了代码。当实际上正在格式化java.util.Calendar
对象时,该源代码实际上是在实例化java.util.Date
对象。所以我完全删除了Calendar
。
Locale l = new Locale ( "hi" , "IN" );
// java.time
DateTimeFormatter f = DateTimeFormatter.ofPattern ( "MMMM dd uuuu" ).withLocale ( l );
System.out.println ( ZonedDateTime.now ().format ( f ) );
// Legacy date-time classes.
SimpleDateFormat dFormat = new SimpleDateFormat ( "MMMM dd yyyy" , l );
System.out.println ( dFormat.format ( new java.util.Date () ) );
सितंबर07 2016
सितंबर07 2016
虽然我不完全理解这种行为,但似乎我们可以根据Zax的Android行为,Dac Saunders的Ubuntu Linux体验以及我在macOS上的经验得出两个结论:
java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧日期时间类,例如java.util.Date
,.Calendar
和&amp; java.text.SimpleDateFormat
。
现在位于Joda-Time的maintenance mode项目建议迁移到java.time。
要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。
大部分java.time功能都被反向移植到Java 6&amp; ThreeTen-Backport中的7,并进一步适应Android中的ThreeTenABP(见How to use…)。
ThreeTen-Extra项目使用其他类扩展java.time。该项目是未来可能添加到java.time的试验场。您可以在此处找到一些有用的课程,例如Interval
,YearWeek
,YearQuarter
等。
答案 2 :(得分:2)
SimpleDateFormat
或DateTimeFormatter
(在Java 8上)后面的格式引擎使用最初基于Common Locale Date Repository (CLDR)的The Unicode Consortium数据的本地化资源。在旧的CLDR数据(例如v17)中,我们发现了印地语(iso-639-code hi)的默认编号系统:
<defaultNumberingSystem>deva</defaultNumberingSystem>
但是最新的CLDR-version v29 shows:
<defaultNumberingSystem>latn</defaultNumberingSystem>
CLDR代码字&#34; deva&#34;和&#34; latn&#34;表示印度数字(从代码点0x966开始)。阿拉伯数字0-9。因此,Java或Android平台的行为取决于版本。旧版本的平台使用旧数据,而较新版本使用更新的CLDR数据。 对于手机来说,很难甚至无法预测Android会真正使用哪些数据。并非每个用户都会用来更新Android版本,有时制造商也会操纵资源。
YES!我展示了三种方式。
a) java.text.SimpleDateFormat
Locale hindi = new Locale("hi", "IN");
DecimalFormatSymbols dfs = DecimalFormatSymbols.getInstance(hindi);
char required = '०'; // copied from your comment
DecimalFormat numberFormat = new DecimalFormat();
dfs.setZeroDigit(required); // or any other zero digit like '0'
numberFormat.setDecimalFormatSymbols(dfs);
SimpleDateFormat sdf = new SimpleDateFormat("MMMM dd yyyy", hindi);
sdf.setNumberFormat(numberFormat);
System.out.println("SimpleDateFormat: " + sdf.format(new Date())); // सितंबर २३ २०१६
b) java.time.format.DateTimeFormatter (在Android上,您可以使用ThreetenABP代替)
Locale hindi = new Locale("hi", "IN");
char required = '०'; // copied from your comment
DecimalStyle style = DecimalStyle.of(hindi).withZeroDigit(required);
DateTimeFormatter dtf =
DateTimeFormatter.ofPattern("MMMM dd yyyy", hindi).withDecimalStyle(style);
System.out.println("java.time: " + LocalDate.now().format(dtf)); // सितंबर २३ २०१६
注意:此解决方案仍然使用Android平台的资源(例如在Android中查找月份名称)。
c)我的图书馆 Time4A (管理自己独立的i18n资源)
Locale hindi = new Locale("hi", "IN");
ChronoFormatter<PlainDate> cf =
ChronoFormatter.ofDatePattern("MMMM dd yyyy", PatternType.CLDR, hindi).with(
Attributes.NUMBER_SYSTEM,
NumberSystem.DEVANAGARI
);
System.out.println("Time4A: " + cf.format(PlainDate.nowInSystemTime())); // सितंबर २३ २०१६