Speak numbers in Java

Today I got some “feedback” about previous post, and “feedback” was: I can’t read Russian. So, now I will try to write the same in English 🙂

The problem is: sometimes in formal documents we mustn’t use numbers – only words are accepted, i.e. instead of writing something like “this document is valid until November 16, 2016” I must write something like “this document is valid until the sixteenth of November, twenty sixteen” or “this document is valid until November the sixteenth, twenty sixteen”, unfortunately example above is unable to express the complexity of the problem for Russian, because in Russian besides ordinal/cardinal numbers and grammatical gender we also have grammatical cases, and the most close writing for “November 16, 2016” in Russian would be: “sixteenth of November of two thousand sixteenth year” – actually instead of “of November” and “of year” I need to use genitive case of corresponding words, moreover for “sixteenth” I also need to use genitive case. So, what to do? Actually for cardinal numbers the algorithm seems to be trivial: in case of Russia we need to define writing for following “illogical” numbers: 1-20 with step of 1, 30-90 with step of 10, 100-900 with step of 100, 1000, 1000^2, 1000^3, etc, and after that write an algorithm which will divide numbers and concatenate strings. However ordinal numbers and genitive case complicate everything (for example, writing for ordinal 2000 is not “two thousandth” but something like “twothousandth”), so I decided to check whether someone already did the same and have found that the guys from ICU project already implemented everything I was looking for:

ULocale locale = new ULocale("en");
SimpleDateFormat dateFmt = new SimpleDateFormat("'the' d 'of' MMMM, yyyy", locale);
RuleBasedNumberFormat dayFmt = new RuleBasedNumberFormat(locale, RuleBasedNumberFormat.SPELLOUT);
dayFmt.setDefaultRuleSet("%spellout-ordinal");
dateFmt.setNumberFormat("d", dayFmt);
RuleBasedNumberFormat yearFmt = new RuleBasedNumberFormat(locale, RuleBasedNumberFormat.SPELLOUT);
yearFmt.setDefaultRuleSet("%spellout-numbering-year");
dateFmt.setNumberFormat("y", yearFmt);
System.out.println(dateFmt.format(new Date()));

produces:

the sixteenth of November, twenty sixteen

Russian example:

ULocale locale = new ULocale("ru");
SimpleDateFormat dateFmt = new SimpleDateFormat("d MMMM yyyy 'года'", locale);
RuleBasedNumberFormat dayFmt = new RuleBasedNumberFormat(locale, RuleBasedNumberFormat.SPELLOUT);
dayFmt.setDefaultRuleSet("%spellout-ordinal-neuter-genitive");
dateFmt.setNumberFormat("d", dayFmt);
RuleBasedNumberFormat yearFmt = new RuleBasedNumberFormat(locale, RuleBasedNumberFormat.SPELLOUT);
yearFmt.setDefaultRuleSet("%spellout-numbering-year");
dateFmt.setNumberFormat("y", yearFmt);
System.out.println(dateFmt.format(new Date()));

produces:

шестнадцатого ноября две тысячи шестнадцатого года

2 thoughts on “Speak numbers in Java

  1. Pingback: MS Word templates | Documentum in a (nuts)HELL

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s