Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Time interval localization in Java

I need to represent a time interval as localized string like this: 10 hours 25 minutes 1 second depending on Locale. It is pretty easy to realize by hand in English: String hourStr = hours == 1 ? "hour" : "hours" etc.

But I need some "out-of-the-box" Java (maybe Java8) mechanism according to rules of different languages. Does Java have it, or I need to realize it for each Locale used in app by myself?

like image 754
ferrerverck Avatar asked Jul 02 '14 06:07

ferrerverck


People also ask

What is locale time?

Locale determines the human language and cultural norms used when generating a String to represent a date-time value.

What is date time format in Java?

Represents a date (year, month, day (yyyy-MM-dd)) LocalTime. Represents a time (hour, minute, second and nanoseconds (HH-mm-ss-ns)) LocalDateTime. Represents both a date and a time (yyyy-MM-dd-HH-mm-ss-ns)


1 Answers

Look at Joda-Time. It supports the languages English, Danish, Dutch, French, German, Japanese, Polish, Portuguese and Spanish with version 2.5.

Period period = new Period(new LocalDate(2013, 4, 11), LocalDate.now());
PeriodFormatter formatter = PeriodFormat.wordBased(Locale.GERMANY);
System.out.println(formatter.print(period)); // output: 1 Jahr, 2 Monate und 3 Wochen

formatter = formatter.withLocale(Locale.ENGLISH);
System.out.println(formatter.print(period)); // output: 1 Jahr, 2 Monate und 3 Wochen (bug???)

formatter = PeriodFormat.wordBased(Locale.ENGLISH);
System.out.println(formatter.print(period)); // output: 1 year, 2 months and 3 weeks

You might to adjust the interpunctuation chars however. To do this you might need to copy and edit the messages-resource-files in your classpath which have this format (here english variant):

PeriodFormat.space=\ 
PeriodFormat.comma=,
PeriodFormat.commandand=,and 
PeriodFormat.commaspaceand=, and 
PeriodFormat.commaspace=, 
PeriodFormat.spaceandspace=\ and 
PeriodFormat.year=\ year
PeriodFormat.years=\ years
PeriodFormat.month=\ month
PeriodFormat.months=\ months
PeriodFormat.week=\ week
PeriodFormat.weeks=\ weeks
PeriodFormat.day=\ day
PeriodFormat.days=\ days
PeriodFormat.hour=\ hour
PeriodFormat.hours=\ hours
PeriodFormat.minute=\ minute
PeriodFormat.minutes=\ minutes
PeriodFormat.second=\ second
PeriodFormat.seconds=\ seconds
PeriodFormat.millisecond=\ millisecond
PeriodFormat.milliseconds=\ milliseconds

Since version 2.5 it might be also possible to apply complex regular expressions to model more complex plural rules. Personally I see it as user-unfriendly, and regular expressions might not be sufficient for languages like Arabic (my first impression). There are also other limitations with localization, see this pull request in debate.

Side notice: Java 8 is definitely not able to do localized duration formatting.

UPDATE from 2015-08-26:

With the version of my library Time4J-v4.3 (available in Maven Central) following more powerful solution is possible which supports currently 45 languages:

import static net.time4j.CalendarUnit.*;
import static net.time4j.ClockUnit.*;

// the input for creating the duration (in Joda-Time called Period)
IsoUnit[] units = {YEARS, MONTHS, DAYS, HOURS, MINUTES, SECONDS};
PlainTimestamp start = PlainDate.of(2013, 4, 11).atTime(13, 45, 21);
PlainTimestamp end = SystemClock.inLocalView().now();

// create the duration
Duration<?> duration = Duration.in(units).between(start, end);

// print the duration (here not abbreviated, but with full unit names)
String s = PrettyTime.of(Locale.US).print(duration, TextWidth.WIDE);

System.out.println(s);
// example output: 1 year, 5 months, 7 days, 3 hours, 25 minutes, and 49 seconds

Why is Time4J better for your problem?

  • It has a more expressive way to say in which units a duration should be calculated.
  • It supports 45 languages.
  • It supports the sometimes complex plural rules of languages inclusive right-to-left scripts like in Arabic without any need for manual configuration
  • It supports locale-dependent list patterns (usage of comma, space or words like "and")
  • It supports 3 different text widths: WIDE, ABBREVIATED (SHORT) and NARROW
  • The interoperability with Java-8 is better because Java-8-types like java.time.Period or java.time.Duration are understood by Time4J.
like image 192
Meno Hochschild Avatar answered Oct 11 '22 17:10

Meno Hochschild