1. Locale, Date and Time
In almost all exercises we have screen outputs, and whoever writes in everyday life, for example, Chinese, Spanish or Arabic, will probably prefer program outputs in this language as well. However, in some places, a wrong format might appear, e.g., when decimal places in floating-point numbers are not separated correctly. The decimal separator is only one of many examples of how different the standards are in the countries: Currencies sometimes precede and then follow the number; for dates, the format is year-month-day in some countries, day-month-year in others, and then month-day-year again.
This chapter focuses on exercises around internationalization (how to make programs language-independent in principle) and localization (adaptation to a specific language). After all, if our software is to be successful, it must, of course, run anywhere on the planet at any time of day. Java can easily accommodate many language specifics, and we’ll look at that in the exercises, so that Captain CiaoCiao and Bonny Brain can also do their business anywhere and everyone understands their "language".
Prerequisites
know
Locale
class and constants, likeLocale.US
be able to recognize the need for country-specific formatting
know temporal data types
LocalDate
,LocalDateTime
, `Duration
Data types used in this chapter:
1.1. Languages and countries
For the Java library to parse and format floating-point numbers and dates, as well as translate text, there is a data type called Locale
that represents a language with an optional region. We want to use this data type to solve some exercises that show well where Locale
occurs everywhere.
1.1.1. Apply country/language specific formatting for random number. ⭐
Bonny Brain is preparing a new email scam: Bitcoins are to be "sold" well below their price. It prepares subject lines for this, which look like this, for example
Buy 𝑩𝒊𝒕𝒄𝒐𝒊𝒏 for just $11,937.70 💰
Of course, the crew is planning a worldwide scam, and that’s where it’s important to format the number according to the rules of the different countries.
The printf(…)
method is overloaded, as is String.format(…)
:
With
Locale
as the first parameter.Without
Locale
. If noLocale
object is passed, the default locale applies. This leads to the fact that the Java Virtual Machine under let’s say an operating system language Spanish, this language adopts and with the output withSystem.out.printf(…)
and a floating-point number by default a comma as a decimal separator is used. If you have an English-language operating system, the point is used as a separator by default because decimal places are separated with a point in English-speaking countries.
Exercise:
Create a random number of type
double
between 10 000 (inclusive) and 12 000 (exclusive); decimal places are desired.To format a floating-point number with two decimal places and a thousand separator, employ the
String.format(String format, Object... args)
method.Get all
Locale
objects of the system, and use them as arguments to theString.format(Locale l, String format, Object... args)
method, so that the floating-point number is formatted "locally" in each case. Output the string.
As a general rule, it can be stated that all methods implementing language-dependent formatting, or parsing strings, usually accept a |
1.2. Date and time classes
At first glance, it looks like the date consists only of year, month, and day. However, you would expect an API to be able to answer more questions: Is a day a Wednesday? If a party goes for three days on February 27, when does it end? When does week 12 start? If I leave Beijing at 09:30 on December 31, 2021, and arrive in Miami after 11 hours, what time is it when I get there?
The Java library has evolved over the years, and so there are various types for date and time calculation:
java.util.Date
since Java 1.0java.util.Calendar
,java.util.GregorianCalendar
,java.util.TimeZone
since Java 1.1package
java.time
since Java 8 with classes likeLocalDate
,LocalTime
,LocalDateTime
,Duration
.
For a date with time part, there are three possibilities at once; however, Date
and Calendar
are no longer popular since Java 8 because they are causing several problems. However, these data types can still be found in many written examples, especially online. We should stay away from these "old" types, and therefore this section specifically trains how to use the current data types from java.time
.
1.2.1. Formatting date output in different languages ⭐
September 19 marks the return of International Talk Like a Pirate Day. Bonny Brain is planning a party and preparing invitations, and the date is to be formatted for the languages Locale.CHINESE
, Locale.ITALIAN
and new Locale("th")
; Germans, for example, write Day.Month.Year
, but what about in the other languages?
Exercise:
Create a
LocalDate
object for September 19:LocalDate now = LocalDate.of( Year.now().getValue(), Month.SEPTEMBER, 19 );
Call the
toString()
method; what is the output?Call
format(DateTimeFormatter.ofLocalizedDate(FormatStyle.MEDIUM))
on theLocalDate
; what is the output?There are four
FormatStyle
styles in total — try them all. Which pattern is shown?On the
DateTimeFormatter
object, you can callwithLocale(Locale)
and change the language; try this for different languages.
1.2.2. On which day does Sir Francis Beaufort celebrate his birthday? ⭐
Captain CiaoCiao celebrates the birthday of Sir Francis Beaufort every year, who was born on May 27, 1774.
Exercise:
Given a
LocalDate
with Francis` birthday:LocalDate beaufortBday = LocalDate.of( 1774, Month.MAY, 27 );
Starting from
beaufortBday
, develop a newLocalDate
object with the current year, where the current year should not be hard-coded but dynamically obtained from the system.Create an output on which day of the week Francis celebrates his birthday this year. In which form the weekday is output, i.e., number or string or which language, is not relevant.
Example:
For the year 2020 the output could be:
WEDNESDAY 3 Wednesday
1.2.3. Find all Friday the 13th. ⭐
Every Friday the 13th, Captain CiaoCiao feels uncomfortable sailing. On such days, he does not set sail and sends Bravius Gritty instead.
Task:
Write a program that lists all Fridays that fall on the 13th for a given year.
Bonus: For this, write a
TemporalAdjuster
that returns the next Friday the 13th for aTemporal
object.
Examples:
For the year 1925, the output may look like this:
1925-02-13 1925-03-13 1925-11-13
For 2024:
2024-09-13 2024-12-13
1.2.4. Get average duration of karaoke nights ⭐
Karaoke nights with rum, dancing, and singing are popular among the crew. Often the parties go on until dawn, and this disturbs Bonny Brain because the crew is dozy the next day.
To find out how many hours the excesses go on average, Bonny Brain wants to keep a record of statistics. She writes down the start and end times and can calculate the average later. For example, the note sheets say "2022-03-12, 20:20 - 2022-03-12, 23:50".
Exercise:
Write a program that evaluates a string in the format above, finds the average party duration, and prints it out.
The program does not need to consider time zones, leap seconds, or other special cases — a day can be exactly 24 hours long.
Example:
For the string
2022-03-12, 20:20 - 2022-03-12, 23:50 2022-04-01, 21:30 - 2022-04-02, 01:20
the output should look like this:
3 h 40 m
For time differences, the class |
1.2.5. Parse different date formats ⭐⭐⭐
A date can be specified as absolute or relative, and there are several ways to specify dates. A few examples:
2020-10-10 2020-12-2 1/3/1976 1/3/20 tomorrow today yesterday 1 day ago 2234 days ago
Exercise:
Write a method
Optional<LocalDate> parseDate(String string)
that recognizes the above formats.If the string is in one of the formats, the method should parse the string, convert it to a
LocalDate
and return it inOptional
.If no format could be parsed, the return is
Optional.empty().