Laboratory Training 2
Working with Dates and Text. Localization
1 Training Tasks
1.1 Individual Task
Design and implement classes to represent the entities of the third laboratory training of the Java Basic Programming Course. The solution should be based on the previously created class hierarchy.
The program should implement
          the support of various localizations, in particular, Ukrainian and English (American). It is necessary to provide
        for the translation of text, the output of numbers, as well as dates and times, taking into account different localizations.
          Add (modify) search for words in comments (or other text) using regular expressions. Sort the entities alphabetically
          using the Collator class. 
Create a derived class from the class that represents the second entity. Add the time and
        date when a certain event occurs as a field. To represent the time and date, use classes of java.time  package(taking
        into account the time zone). If the class that represented the second entity of the individual task did not contain
        a  String type
        field, you should add a field, e.g. a comment to the event. For a new (or existing) text field, provide for the
        possibility of output in Ukrainian or English, depending on localization.
The program must demonstrate:
- presentation of the implementation of tasks of laboratory trainings # 3 and # 4 of the Java Basic Programming Course; use regular expressions to search for text;
- formatting numerical data in various ways, as well as taking into account localization;
- output of data about dates and times of events taking into account localization;
- output of comments in Ukrainian and English;
- the ability to sort alphabetically using a Collatorclass;
- calculation and output of time intervals between events related to the second essence of the task; finding and output the smallest of the intervals.
1.2 Date Entering
Implement a program in which the user enters a string. The program checks whether the string corresponds to the
        date representation accepted in Ukraine. The  regular expressions must be used for checking. If the string does
        not meet the requirements, an error message is displayed. Otherwise, objects of types Date, GregorianCalendar and        LocalDate are
        created and output to the console.
1.3 Phone Number Verification
Develop a program to verify the correctness of the fact that the string is the telephone number of the Kyivstar operator. Use regular expressions.
1.4 Checking the Password String
Develop a program for checking password compliance with the requirements:
- the password can contain letters of the Latin alphabet, numbers and special symbols: _ - *;
- there must be at least one lowercase letter;
- there must be at least one capital letter;
- must be at least one digit;
- there must be at least one special character.
Use regular expressions.
1.5 Obtaining an Array of Substrings (Advanced Task)
A string longer than 20 characters contains letters and numbers. Get from this string an array of substrings that contain letters between numbers (groups of numbers). Define numbers as separators.
2 Instructions
2.1 Working with Dates and Times
2.1.1 Overview
Working with dates and times is of great importance in information systems. Date and time are usually important information stored in databases as well as data warehouses.
Almost all software platforms provide facilities for working with dates and times. In particular, in the Java standard, work with dates and times is implemented at three levels:
- class Date;
- class Calendarand its descendants;
- package java.time.
2.1.2 Using the Date Class
Classes Calendar and Date from the java.util package provide methods for
        working with date and time. The class Date object stores the number of milliseconds that have passed since January 1, 1970
      00:00:00 GMT. This is the "birthday" of Unix, it is called "Epoch". 
The Date class implements two constructors. The Date() constructor puts the current date
        and time into the object in the format of the current regional settings: 
Date date1 =new Date();
The Date(long millisec) constructor creates the object using the specified number of milliseconds.
        For example, you can get the number of milliseconds that have passed since the Epoch using a static method System.currentTimeMillis():
Date date2 =new Date(System.currentTimeMillis());
Class Date methods: 
- long- getTime()returns the value stored in the object;
- void- setTime(long newTime)sets a new value;
- boolean- after(Date when)returns- trueif the time- whenis less than the value stored in the object;
- boolean- before(Date when)returns- trueif the time- whenis greater than the value stored in the object.
Many of constructors and methods of Date class are deprecated because the class does not provide
        application of internationalization capabilities. 
2.1.3 Using the Calendar Class
You should use the Calendar class to define dates.
 Conversion of milliseconds stored in objects of the Date class to the current time and date is carried out by
        the methods of the Calendar class. This is an abstract class that provides methods for converting a
        moment of time to a set of calendar fields (year, month, day of the month, hour, etc.) and for working with calendar
      fields.
The Calendar class defines integer constants MONDAY ... SUNDAY (days of the
      week), as well as methods to read or set the first day of the week, time, time zone, etc.
 The constants in the range 0..11 are used to determine the months. To avoid confusion, it is advisable to use
      constants defined in the Calendar class:
public static final int JANUARY = 0;public static final int FEBRUARY = 1;public static final int MARCH = 2;public static final int APRIL = 3;public static final int MAY = 4;public static final int JUNE = 5;public static final int JULY = 6;public static final int AUGUST = 7;public static final int SEPTEMBER = 8;public static final int OCTOBER = 9;public static final int NOVEMBER = 10;public static final int DECEMBER = 11;
Java provides the only implementation of Calendar class: GregorianCalendar class derived
        from Calendar. You can create a GregorianCalendar object using a static method getInstance():
Calendar gregorianCalendar = Calendar.getInstance();// or Calendar gregorianCalendar = GregorianCalendar.getInstance(); 
The class GregorianCalendar provides constructors that create a calendar object by specifying the date
      and time as integer values:
GregorianCalendar() GregorianCalendar(int year,int month,int date) GregorianCalendar(int year,int month,int date,int hour,int minute) GregorianCalendar(int year,int month,int date,int hour,int minute,int second)
This is an example of working with classes Date and Calendar:
package ua.inf.iwanoff.java.advanced.second;import java.util.Calendar;import java.util.GregorianCalendar;import java.util.Date;public class DateTest {public static void main(String[] args) {// Setting the time using a Date instance: Date date =new Date(System.currentTimeMillis()); Calendar calendar = GregorianCalendar.getInstance(); calendar.setTime(date); System.out.println(calendar.getTime());// Call the getter and setter methods of the Calendar object: calendar.set(Calendar.MONTH, Calendar.AUGUST); calendar.set(Calendar.DAY_OF_MONTH, 24); calendar.set(Calendar.YEAR, 1991); calendar.set(Calendar.HOUR, 21); calendar.set(Calendar.MINUTE, 00); calendar.set(Calendar.SECOND, 01); System.out.println(calendar.getTime()); System.out.println("The YEAR is: " + calendar.get(Calendar.YEAR)); System.out.println("The MONTH is: " + calendar.get(Calendar.MONTH)); System.out.println("The DAY is: " + calendar.get(Calendar.DATE)); System.out.println("The HOUR is: " + calendar.get(Calendar.HOUR)); System.out.println("The MINUTE is: " + calendar.get(Calendar.MINUTE)); System.out.println("The SECOND is: " + calendar.get(Calendar.SECOND)); System.out.println("The AM_PM indicator is: " + calendar.get(Calendar.AM_PM)); } }
2.1.4 Using java.time Tools
Standard Java tools (up to JDK 7 inclusive) for working with dates and times have a number of disadvantages related to the inconvenience of their use, which led to the appearance of alternative (non-standard) libraries, such as the Joda-Time library that was very popular among programmers. In order to correct this situation, Java 8 added new classes and tools to support working with dates and calendar. The new date and time library is very similar to Joda-Time.
The package java.time defines classes for date and time representation:
- LocalDate(day, month, year);
- LocalTime(time of day only);
- LocalDateTime(date and time).
These three classes are used in cases where the explained time is not taken into account. You can create objects
      using static now() functions that return the current time:
LocalDate date = LocalDate.now(); LocalTime time = LocalTime.now(); LocalDateTime dateTime = LocalDateTime.now();
Other ways to create an object are to use an of() static function that accepts hours, minutes, and
      seconds as parameters:
time = LocalTime.of(11, 15, 0); date = LocalDate.of(2023, 3, 8); dateTime = LocalDateTime.of(2023, Month.MARCH, 8, 11, 15, 0); dateTime = LocalDateTime.of(date, time);// another option 
Note: unlike a Calendar class, classes of java.time package use month numbers in a range 1..12.
 As can be seen from the example, both integer values and constants of java.time.Month enumeration
        can be used to define months. You can create an object of type LocalDateTime from an existing object
        of type LocalDate        using the atTime() method:
dateTime = date.atTime(time);
Using the plus() and minus() methods, you can change the date and time values of existing objects. You can set
        the unit of measurement using the java.time.temporal.ChronoUnit enumeration. The following example
      sets the time two hours later than the current time:
LocalTime now = LocalTime.now(); LocalTime later = now.plus(2, ChronoUnit.HOURS); System.out.println(later);
There are also addition and subtraction methods plusHours(), minusHours(), plusMinutes(), minusMinutes(), plusSeconds(), minusSeconds(), plusNanos() and minusNanos() with
        integer parameters. Similarly, the LocalDate class provides methods  plusDays(), plusMonths(), minusDays() and minusMonths().
        Example:
LocalDate today = LocalDate.now(); LocalDate thirtyDaysFromNow = today.plusDays(30); LocalDate nextMonth = today.plusMonths(1); LocalDate aMonthAgo = today.minusMonths(1);
Identification of time zones is carried out by means of the ZoneId class. The easiest way to get the
      identifier of the default time zone is to use a static function systemDefault():
ZoneId myZone = ZoneId.systemDefault();
You can get the time zone identifier using a string constant. The set of possible constants can be obtained using
      the ZoneId.getAvailableZoneIds() static method. The following code shows the constants for European zones:
import java.time.ZoneId;public class AvailableZoneIds {public static void main(String[] args) {for (String zone: ZoneId.getAvailableZoneIds()) {if (zone.startsWith("Europe")) { System.out.println(zone); } } } }
The listed constants can be used in the of() method, for example:
        ZoneId germanZone = ZoneId.of("Europe/Berlin");
      
      To work with time, taking into account the time zone, the ZonedDateTime class is used. Its use is
        similar to LocalTime,
        but if you define an object of type ZoneId as a parameter of the method now(), you can
      work with the time of the corresponding time zone:
ZonedDateTime germanTime = ZonedDateTime.now(germanZone); System.out.println(germanTime);
You can also use the Clock class to work with the zoned time.
        Clock clock = Clock.system(ZoneId.of("Europe/Kiev"));
LocalTime kyivTime = LocalTime.now(clock);
System.out.println(kyivTime);
      
      Java 8 defines two classes, Period and Duration, that allow defining intervals between
        dates and times, respectively. For this, the following between() methods are used:
Period p = Period.between(date1, date2); Duration d = Duration.between(time1, time2);
Objects of these classes can also be created using static methods, for example:
Duration twoHours = Duration.ofHours(2); Duration tenMinutes = Duration.ofMinutes(10); Duration thirtySecs = Duration.ofSeconds(30);
The class java.time.temporal.TemporalAdjusters contains useful methods such asfirstDayOfMonth(), firstDayOfNextMonth(), firstInMonth(DayOfWeek), lastDayOfMont(), next(DayOfWeek), nextOrSame(DayOfWeek), previous(DayOfWeek), previousOrSame(DayOfWeek), etc. 
The Instant class represents a moment in time measured in nanoseconds. Using a nanosecond representation,
        the new library provides backward compatibility . The Date and Calendar classes previous
        versions of Java provide a method
        toInstant(), the result of which can be used to create objects of LocalDateTime or ZonedDateTime classes.
 The following example demonstrates the possibilities of converting different date and time formats::
package ua.inf.iwanoff.java.advanced.second;import java.time.LocalDateTime;import java.time.ZoneId;import java.util.Calendar;import java.util.Date;import java.util.GregorianCalendar;public class DateConversion {static Date fromLocalDateTimeDate(LocalDateTime localDateTime) {return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant()); }static LocalDateTime fromDateToLocalDateTime(Date date) {return date.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime(); }public static void main(String[] args) { LocalDateTime dateTime = LocalDateTime.now(); System.out.println(dateTime); Date date = fromLocalDateTimeDate(dateTime); System.out.println(date); Calendar calendar = GregorianCalendar.getInstance(); calendar.setTime(date); calendar.add(Calendar.YEAR, 1); date.setTime(calendar.getTimeInMillis()); System.out.println(date); dateTime = fromDateToLocalDateTime(date); System.out.println(dateTime); } }
2.2 Working with Text in Java
2.2.1 Common Principles of Working with String Class
The Java Basic Programming Course covered the basic concepts of working with the String. In particular,
      the following main features of working with strings were determined: 
- the string contains a sequence of Unicode characters;
- strings actually appear in all programs in the Java language;
- it is possible to create a string both with the help of a constructor and by directly assigning a string literal
          (a sequence of characters in quotes) to a reference of type String;
- you can get a representation of each object (or variable of a primitive type) by appending a string using the + operator to the left or to the right;
- arrays of strings can be sorted alphabetically by default;
- an object of the Stringtype cannot be changed after it was created.
To effectively replace individual characters of strings and add new characters, you should use special classes
        StringBuffer and StringBuilder. 
Next, we will consider additional options for working with text data - text blocks, localization, sorting, formatting, iteration and regular expressions.
2.2.2 Working with Text Blocks
Working with strings causes certain inconveniences when one object of String type contains many lines, as well as other symbols for which special escape sequences must be used. For greater convenience when working with such strings, Java 15 version added a special syntactic construct: a text block.
The syntax of the text block is as follows: the block begins with three characters """,
        then you must jump to a new line, then place the necessary text in one or more lines and close the block with """.
        The compiler automatically creates an object of the String type from such a block:
        String block = """
        Hello, block!""";
      
      In the previous example, it would be easier to use a plain literal. The real need arises when the text must occupy several lines, or if you want to place quotation marks inside, etc. Example:
        String block = """
        Hello, block!
        This is the same string.
        We can add use "quotes" without backslash.
            We can indent.""";
      
      Very often, fragments of HTML text or program code in other programming languages are added to the Java code in this way.
2.3 Localization
2.3.1 Overview
Internationalization (internationalization, i18n) is the principle of designing and implementing software in such a way as to ensure the possibility of further adaptation to different languages and regions without constructive changes. Compliance with internationalization requirements greatly simplifies the future process of adapting the software product to regional and national requirements.
Localization (localization, l10n) is the process of adapting software to national standards and regulations, such as, for example:
- language;
- alphabetical sorting rules;
- format for representing numbers, date and time;
- time zone;
- currency format;
- unit of measurement;
- the direction of writing the text;
- paper format.
Java uses class objects to set and store localization information java.util.Locale. There are several options
        for creating an object of type Locale. The easiest option is to get the locale that is already defined for the
        Java virtual machine:
Locale locale = Locale.getDefault();
You can define localization using constructors, for example:
Locale locale1 =new Locale("en", "US"); Locale locale2 =new Locale("en", "GB"); Locale locale3 =new Locale("uk");// language is set, region is not set 
 To identify languages and countries, the class Locale uses identifiers according to the IETF BCP
        47 standard
 (https://en.wikipedia.org/wiki/IETF_language_tag).
 You can also use a static method forLanguageTag(), for example:
        Locale locale4 = Locale.forLanguageTag("en-US");
      
       You can "build" an object using a nested class Locale.Builder:
Locale Locale5 =new Locale.Builder().setLanguage("en").setRegion("US").build();
The Java platform does not require just one localization for the entire application. This flexibility allows you
        to develop multilingual applications. For some countries, regional parameters are set using constants, for example:
        Locale.US, Locale.FRANCE, Locale.CANADA. For other countries, the Locale        object
        must be created using a constructor, for example, new Locale("ua", "UA").
You can get information about the language and region for localization:
Locale locale =new Locale("uk", "UA"); System.out.println(locale.getCountry());//region code System.out.println(locale.getDisplayCountry());//region name System.out.println(locale.getLanguage());//region language code System.out.println(locale.getDisplayLanguage());//name of the language of the region 
It is possible to set the required default localization for an application, e.g.
Locale.setDefault(Locale.US);
The SimpleTimeZone class that implements the abstract class TimeZone, allows you to
        work with time zones in the Gregorian calendar. This class takes daylight saving into account. 
      
      
The class GregorianCalendar has constructors that allow you to define a calendar by time zone and
      localization:
GregorianCalendar(Locale locale) GregorianCalendar(TimeZone timeZone) GregorianCalendar(TimeZone timeZone, Locale locale)
2.3.2 Creation of Applications with Support for Several Languages
The most important use of internationalization and localization is to create applications that support the output
        of texts (messages) in different languages without significant reworking of the code, preferably without recompilation.
        In this case, it is important to keep strings in different languages separate from the source code. The standard
        solution for Java applications is to use capabilities of java.util.ResourceBundle class. This class
        is responsible for "bundle of  resources" – a logically connected set of data, in particular, files.
The ResourceBundle class is abstract. At the standard level, two derived classes are
        implemented: PropertyResourceBundle and ListResourceBundle. The PropertyResourceBundle class
        provides work with the properties file. A properties file is a plain text file that contains the names and values
        of the properties (strings). Properties files are not part of the Java source code. The ListResourceBundle class
        manages resources put into list; it receives data from the .class file. This allows you to store any locale-specific
        objects, not just strings. 
To get the corresponding resource file, you should call the ResourceBundle.getBundle() method. This
        is a factory method that attempts to create an object of ListResourceBundle type and, if no matching resources are
        available, creates an object of PropertyResourceBundle class. If the resource bundle is not found, an exception
        MissingResourceException is thrown. 
Properties files that belong to the same bundle have a common base name and different "suffixes". For example, "strings_en.properties", "strings_uk.properties",
        etc. You can also use more complex suffixes: "strings_en_US.properties", "strings_uk_UA.properties",
        etc. 
The file format is very simple. These are text files that consist of the following lines:
property=value
 For example, you can create the following files with strings for the English and German localizations, respectively words_en.properties 
word1=one word2=two word3=three
and words_de.properties: 
word1=eins word2=zwei word3=drei
The tools of the IntelliJ IDEA environment allow you to create a whole bundle of properties files at once. In the IntelliJ IDEA project, the resource bundle should be located in the out | production | <project name>.
Note: in Maven projects, property files are located in the resources project folder; Maven projects
        will be discussed later. 
In order to more conveniently edit property files in IntelliJ IDEA projects, you can (but not necessarily) additionally download the Resource Bundle Editor plugin.
There is a problem related to the use of Cyrillic in properties files. Such files must use the ISO 8859-1 code
        table, which does not support Cyrillic characters. Therefore, instead of using Cyrillic characters directly, it
      is necessary to specify their Unicode table codes. For example, in a  words_uk.properties file instead
      of text
word1=один word2=два word3=три
the following text must be placed:
word1=\u043E\u0434\u0438\u043D word2=\u0434\u0432\u0430 word3=\u0442\u0440\u0438
Such text is very inconvenient to encode and enter manually. There are special utilities for transcoding files
        .properties that contain Cyrillic characters, for example, native2ascii. But the easiest
        way is to use the built-in capabilities of IntelliJ IDEA. First, in Settings... | Editors| File Encodings,
        after the line Default encoding for properties files, select the option Transparent native-to-ascii
        conversion. After
        that, the Cyrillic text that we enter or edit in the properties files will be automatically encoded into the
      required representation. 
The program  that uses prepared resources, contains creation of an object of type ResourceBundle with
        loading of a bundle using the getBundle() function, specifying as parameters the base name of the
        bundle and the required locale. Now you can get the necessary strings by calling the getString() method
        with necessary property as parameter. 
Suppose, the program should display the string "Hello, world!" or "Привіт, світ!",
        depending on the localization. We create a bundle of resources from two files. The hello_en.properties file:
message=Hello, world!
 The text of the hello_uk.properties  file that we type in the IntelliJ IDEA environment will be
        as follows :
message=Привіт, світ!
 In fact, the contents of the hello_uk.properties file  will be:
message=\u041F\u0440\u0438\u0432\u0456\u0442, \u0441\u0432\u0456\u0442!
The program, which sequentially displays messages using different localizations, will look like this :
package ua.inf.iwanoff.java.advanced.second;import java.util.Locale;import java.util.ResourceBundle;public class HelloResourceBundle {public static void main(String[] args) { ResourceBundle bundle = ResourceBundle.getBundle("hello",new Locale("en")); String msg = bundle.getString("message"); System.out.println(msg); bundle = ResourceBundle.getBundle("hello",new Locale("uk")); msg = bundle.getString("message"); System.out.println(msg); } }
As can be seen from the given example, unlike keys (property names), property values can contain spaces and any characters.
2.4 Using the java.text Package
2.4.1 Strings Sorting
The package java.text provides classes and interfaces for handling text, dates, and numeric values independently
        of language and other national characteristics. This means that a program can be written for language-independent
        operation, and locale-specific resources can be connected dynamically. This allows flexibility to add new app localizations
      later. 
The classes in this package are designed for formatting dates, numbers, and messages, parsing, searching, and sorting strings, and iterating through characters, words, sentences, and strings. This package contains three main groups of classes and interfaces, which respectively solve the following groups of problems:
- strings sorting;
- formatting and parsing into tokens;
- iteration over text.
Sorting is provided by the class Collator. With the help of an instance of the Collator class,
        you can sort strings with dynamic localization. For example, if you sort Ukrainian texts by conventional means,
        there is a problem with specific Ukrainian letters, such as  ґ, є, і, and ї, because their codes are located separately
        from the codes of other symbols of the Ukrainian alphabet. To correctly sort arrays of lines with Ukrainian text,
        it is necessary to create an instance of the Collator class using the function getInstance()        whose
        parameter is the required localization.
The example below demonstrates sorting an array of strings first without using  Collator, and then
        with the creation of an object of  Collator type  that takes into account the Ukrainian localization.
        To determine the sort order, we create an anonymous inner class.
import java.text.Collator;import java.util.Arrays;import java.util.Comparator;import java.util.Locale;public class SortDemo {public static void main(String[] args) { String[] words = { "воля", "воїн", "возити" };// Perform default sorting: Arrays.sort(words); System.out.println(Arrays.asList(words));// [возити, воля, воїн] // Sort based on localization: Arrays.sort(words,new Comparator<String>() { Collator collator = Collator.getInstance(new Locale("uk")); @Overridepublic int compare(String s1, String s2) {return collator.compare(s1, s2); } }); System.out.println(Arrays.asList(words));// [возити, воїн, воля] } }
2.4.2 Formatting
Localization-aware data formatting is provided by the abstract class java.text.Format. Derived classes NumberFormat, DateFormat and MessageFormat allow
        formatting of numbers, dates, and messages, respectively. The Format class declares a format() method
      that converts the parameter into a string in the specified format. 
The following example demonstrates output of a value of type double given the specified
        locale:
import java.text.NumberFormat;import java.util.Locale;import java.util.Scanner;public class NumberPrinter {public static void main(String[] args) { NumberFormat form = NumberFormat.getInstance(new Locale("uk")); Scanner scan =new Scanner(System.in);double x = scan.nextDouble(); System.out.println(form.format(x)); } }
To format integers, you can get an object using the getIntegerInstance() method. Similarly, you can
        obtain getCurrencyInstance() for the output of monetary amounts, getPercentInstance() for the output
        of percents, etc. 
In order to convert information into regional standards, you should create an object of NumberFormat class
        with a constructor that accepts  as a parameter an object of Locale class, or with a constructor without
        parameters (for the default localization):
NumberFormat nf = NumberFormat.getInstance(new Locale("uk")); NumberFormat nf = NumberFormat.getInstance();
The code below demonstrates converting a string containing a number to different regional standards.
import java.text.NumberFormat;import java.text.ParseException;import java.util.Locale;public class DemoNumberFormat {public static void main(String[] args) { NumberFormat nfGe = NumberFormat.getInstance(Locale.GERMAN); NumberFormat nfUs = NumberFormat.getInstance(Locale.US); NumberFormat nfFr = NumberFormat.getInstance(Locale.FRANCE); NumberFormat nfUa = NumberFormat.getInstance(new Locale("ua", "UA"));double iGe = 0, iUs = 0, iFr = 0, iUa = 0; String str = "1.245,999";try {// convert string to German standard: System.out.println(iGe = nfGe.parse(str).doubleValue());// convert string to US standard: System.out.println(iUs = nfUs.parse(str).doubleValue());// convert string to French standard: System.out.println(iFr = nfFr.parse(str).doubleValue());// convert string to the Ukrainian standard: System.out.println(iUa = nfUa.parse(str).doubleValue()); }catch (ParseException e) { e.printStackTrace(); } System.out.println(); String sUs = nfUs.format(iGe);//number conversion from German to American standard String sFr = nfFr.format(iGe);//number conversion from German to French standard String sUa = nfUa.format(iGe);//number conversion from German to Ukrainian standard System.out.println(sUs + "\n" + sFr + "\n" + sUa); } }
 Here, the NumberFormat parse(String source) and String format(double number) methods
        and are used to convert strings into numbers and back.
      
 The java.text.DateFormat class helps solve the task of supporting national specifics in displaying
        the date and time in different countries and regions of the world. When creating an object
        of this class, a specific locale can be specified or the default locale for this environment can be used:
DateFormat df = DateFormat.getDateInstance(DateFormat.MEDIUM,new Locale("Uk")); DateFormat df = DateFormat.getDateInstance();
 The abstract DateFormat class  and its subclass SimpleDateFormat of the java.text package contain
        methods that allow different ways to format date and time representations. The DateFormat class offers
        the following date and time representation styles: 
- SHORTstyle represents the date and time in short numeric form:- 27.04.01 17:32;
- MEDIUMstyle sets the year in four digits and shows the seconds:- 27.04.2001 17:32:45;
- LONGstyle represents the month as a word and adds the time zone:- 27 квітень 2001 р. 17:32:45 GMT+03.-00;
- FULLstyle is the same as- LONG;
- DEFAULTstyle is the same as- MEDIUM.
For example, the following code creates a formatted date string with a default format for the current region:
DateFormat dateFormatter = DateFormat.getDateInstance(DateFormat.DEFAULT); Date today =new Date(); String formattedDate = dateFormatter.format(today); System.out.println(formattedDate);
 In addition to the DateFormat.getDateInstance() method, DateFormat.getTimeInstance() and DateFormat.getDateTimeInstance()
        functions can be used for time formatting, as well as for formatting both date and time.
Similarly, you can format the dates and time of the java.time package.
A child class SimpleDateFormat of an abstract DateFormat class can be used to define
        custom user formats. When creating an object of SimpleDateFormat you can specify a template in the
        constructor that defines any other format, for example: 
SimpleDateFormat sdf =new SimpleDateFormat("dd-MM-yyyy hh mm"); System.out.println(sdf.format(new Date()));
In the template, the letter d means the number of the day of the month, M is the number
        of the month, y is the number of the year, h is the number of the hour, m is
        the number of minutes. 
      
For example, the following code will output a date in the format "04/29/2013": 
Date today =new Date(); SimpleDateFormat formatter =new SimpleDateFormat("MM/dd/yyyy"); String formattedDate = formatter.format(today); System.out.println(formattedDate);
To set the symbols for any date or time component, use the DateFormatSymbols  class:
DateFormatSymbols symbols =new DateFormatSymbols(); String[] oddMonthAbbreviations =new String[] {"Ja","Fe","Mh","Ap","My","Jn","Jy","Au","Se","Oc","No","De" }; symbols.setShortMonths(oddMonthAbbreviations); formatter =new SimpleDateFormat("MMM dd, yyyy", symbols); formattedDate = formatter.format(today); System.out.println(formattedDate);
The constructor of SimpleDateFormat takes a template string and a DateFormatSymbols object. 
      
You can get a presentation of the current date in all possible regional standards as follows:
Date d =new Date(); Locale[] locales = DateFormat.getAvailableLocales(); for (Locale loc : locales) { DateFormat df = DateFormat.getDateInstance(DateFormat.FULL, loc); System.out.println(loc.toString() + "-> " + df.format(d)); }
The java.util.Formatter class is responsible for presentation-level formatting in terms of output field width,
      alignment, presence of a + sign in front of numbers, etc. 
A format() static method format of the String class allows you to get a string that represents
        the data according to a format, for example:
double d = 3.5;int i = 12; String result = String.format("%f %d%n", d, i); System.out.print(result);
A similar method is declared in classes PrintStream and PrintWriter. In addition, these
        classes declare a printf() method with parameters identical to the parameters of the format() method
        that performs the formatted output of the stream. This way you can get direct output formatting using the System.out.printf() function:
double d = 3.5;int i = 12; System.out.printf("%f %d%n", d, i);
The following format specifiers are used during formatting:
| Format specifier | Formatting | 
|---|---|
| %a | A floating-point hexadecimal value | 
| %b | Logical (Boolean) value of the argument | 
| %c | Symbolic presentation of the argument | 
| %d | The decimal integer value of the argument | 
| %h | The hash code of the argument | 
| %e | Exponential presentation of the argument | 
| %f | Floating point decimal value | 
| %g | A shorter option of the two:  | 
| %o | The octal integer value of the argument | 
| %n | Insert a newline character | 
| %t | Time and date | 
| %x | The hexadecimal integer value of the argument | 
| %% |  Insert symbol  | 
 Specifiers with capital letters are also possible: %A (equivalent to %a). Formatting
        with capital letters ensures that characters are converted to upper case.
import java.util.Formatter;public class SimpleFormatString {public static void main(String[] args) { Formatter f =new Formatter(); f.format("%s %c %nBasics of Java Application Development %S ", "Module",'2',"se"); System.out.print(f); } }
A precision specifier can be applied to floating-point data (specifiers %f, %e, %g)
        and strings (specifier %s).
        It specifies the number of characters to be output. For example, the specifier %10.3f outputs a number
        with a field width of 10 characters and three decimal places (fixed precision is equal to six decimal places). The
        precision specifier applied to strings determines the maximum length of the output field. For example, %.15s outputs
        a string with a length of 15 characters, a specifier %3.7s outputs a string with a length of at least
        three and more than seven characters. If the string is longer, the trailing characters are discarded. It is possible
        to set flags that allow you to implement additional formatting options:
import java.util.Formatter;public class SimpleFormatString {public static void main(String[] args) { Formatter f =new Formatter(); f.format("|%10.2f|", 123.123);// align right System.out.println(f); f =new Formatter();// align left f.format("|%-10.2f|", 123.123);// apply the '-' flag System.out.println(f); f =new Formatter(); f.format("%,.2f", 123456789.34);// apply the ',' flag System.out.println(f); f =new Formatter(); f.format("%.4f", 1111.1111111);// set representation precision for numbers System.out.println(f); f =new Formatter(); f.format("%.6s", "Working with text data.");// set representation precision for strings System.out.println(f); } }
There are also specifiers for date and time formatting that can only be used for types long, Long, Calendar, Date,
      for example:
import java.util.*;public class Time {public static void main(String args[]) { Formatter f =new Formatter(); Calendar calendar = Calendar.getInstance(); f.format("%tr", calendar);// output in 12-hour time format System.out.println(f); f =new Formatter(); f.format("%tc", calendar);// full-format output of time and date System.out.println(f); f =new Formatter(); f.format("%tl:%tM", calendar, calendar);// display the current hour and minute System.out.println(f); f =new Formatter(); f.format("%tB %tb %tm", calendar, calendar, calendar);// various month output options System.out.println(f); } }
2.4.3 Iteration over String Characters
The java.text.CharacterIterator interface provides means for bidirectional traversal of a string
        using an iterator. The StringCharacterIterator class implements the java.text.CharacterIterator interface.
        Methods
        getBeginIndex() and getEndIndex() allow you to return the indices of the first and last
        characters of the line. The index of the current character can be obtained using the getIndex() method.
        Calling the
        setIndex(int index) method moves the iterator to a new position. The previous() and next()        methods
        move the iterator to the previous and next position. If the limits of the range are reached, these methods will
        return DONE. The first() and last() and methods set the iterator
        to the first and last positions, respectively, by returning the character at that position. In the following example,
        we use a CharacterIterator  iterator of StringCharacterIterator class to traverse the string from the starting index
        to the end of the string.
import java.text.CharacterIterator;import java.text.StringCharacterIterator;public class StringCharacterExample {private static final String text = "Jackdaws love my big sphinx of quartz";public static void main(String[] args) { CharacterIterator it =new StringCharacterIterator(text);for (char ch = it.first(); ch != CharacterIterator.DONE; ch = it.next()) { System.out.print(ch); } } }
 Since the Character class takes localization into account, it is advisable to use it instead of char
      applications designed for internationalization and localization.
2.5 Regular Expressions
Regular expressions are a way to describe many strings based on common characteristics. Regular expressions can be used to search, edit, or manipulate text and data. The syntax of regular expressions is the same in different programming languages.
The work with regular expressions in Java is implemented in the package java.util.regex, in particular,
        by classes Pattern and Matcher. A special exception class PatternSyntaxException is
        also defined. 
A Pattern object  is a compiled representation of regular expressions. This class does not provide
        public constructors. To create an object of Pattern type, you must first call one of the static compile() methods
        compile(), each of which creates a Pattern object and returns a reference to it. These methods take
        a regular expression as the first argument. Example:
Pattern pattern = Pattern.compile(ex);// ex is a string that defines a regular expression 
After the Pattern object is created, it is used to initialize the Matcher object:
Matcher matcher = pattern.matcher(s);// s is the line to be checked 
You can then use functions of Matcher class to compare strings  (matches()), find substrings
        (find()), and so on. 
In the simplest case, a regular expression is a string containing a sequence of characters. This means that when
        comparing strings, their equivalence is checked, and when searching, the full text of the regular expression is
        found. The following program prints true to the console window: 
package ua.inf.iwanoff.java.advanced.second;import java.util.regex.*;public class FirstRegex {public static void main(String[] args) { Pattern pattern = Pattern.compile("text"); Matcher matcher = pattern.matcher("text"); System.out.println(matcher.matches()); } }
If the second string differs in length, or at least one character, the result will be false. 
Instead of comparing, you can search for the first occurrence of the pattern in the string. Example:
        Pattern pattern = Pattern.compile("text");
Matcher matcher = pattern.matcher("textual");
System.out.println(matcher.find());  
      
      Now the result will be true. The result will also be true,
        if we check strings like "the text", "context" etc. 
In order to sequentially find all occurrences of a substring, you can use the following loop:
while (matcher.find()) { System.out.printf("Text found" + " \"%s\" starting at position" + "%d and ending with position %d.%n", matcher.group(), matcher.start(), matcher.end()); }
In the given example, the group() function returns a sequence of characters that satisfy the search
        conditions. The start() and end() function return the start and end
        positions of the found sequence in the string.
Escape sequences that begin with a backslash (\) can be added to regular expressions. For example,
        you can define characters by their code::
| Representation | Explanation | Coding | 
|---|---|---|
| \0n | n is an octal number from 0 to 377 | 8 bit | 
| \xdd | d s a hexadecimal number | |
| \udddd | 16 bit (Unicode) | 
You can also use escape sequences:
| Representation | Symbol | 
|---|---|
| \t | Tabulation | 
| \v | Vertical tab | 
| \r | Cursor return | 
| \n | New line | 
| \f | End of page | 
| \a | Bell | 
| \e | Escape symbol | 
| \b | Backspace Note: Backspace must be placed inside square brackets (otherwise interpreted as a word boundary). | 
| \cA ... \cZ | Ctrl+A ... Ctrl+ZEquivalent to \x01 ... \x1A (\cA = \001,\cZ = \032) | 
To create complex regular expressions, so-called metacharacters are used. These are special characters that can be used to create character classes, quantifiers, control sequences, etc. These are the following symbols:
[ ] \ ^ $ . | ? * + ( ) { }
      The meaning of characters depends on their position in the expression. To display a metacharacter as a regular
        text character, it must be preceded by a backslash (\). To get the character directly \, you need
        to use two backslash characters (\\). 
The set of characters in square brackets [ ] is the so-called character class. It allows you to specify
        that one of the listed characters can be placed at this position. For example, [abc] specifies the
        possibility of one of the three specified symbols appearing in the text, [1234567890] determines the
        correspondence of one of the numbers. You can specify a range of characters: for example, [A-Za-z] matches
        all letters of the Latin alphabet. If you want to specify characters that are not included in the specified set,
        you can use the character ^ inside the square brackets. Example, [^0-9] is any character other than
        numbers. 
An example of using the [ ] expression: "[bcr]at" match the lines ""bat", "cat" and "rat";
        these
        lines do not match the expression "[^bcr]at", but a string "hat" does. 
To create a  character class that combines two or more different character classes, union is used. To
        create a union, one class is nested inside another: [0-3[7-9]], which corresponds to the numbers 0,
        1, 2, 3, 7, 8, 9. 
It is possible to create an intersection – a single character class that defines strings that match both nested
        classes. For example, the expression [0-9&&[234]] matches the numbers 2, 3, and 4. 
Subtraction is used to negate one or more symbols of a class, for example, the expression [0-9&&[^345]]        creates a class that matches the digits 0 through 9 except for the digits 3, 4, and 5. 
Escape sequences are also used to denote some character classes:
| Representation | Equivalent | Value | 
|---|---|---|
| \d | [0-9] | Digit | 
| \D | [^\d] | Any character except a number | 
| \w | [A-Za-zа-Яа-Я0-9_] | Characters that make up a "word" (letters, numbers, and an underscore) | 
| \W | [^\w] | Symbols that do not form "words" | 
| \s | [ \t\v\r\n\f] | Separator | 
| \S | [^\s] | Not a separator | 
You can specify the number of repetitions of characters in braces, for example:
- {2}(exactly two characters),
- {2, 4}(from two to four),
- {1,}(one or more).
- a dot is exactly one (any) character,
- *zero or more
- +one or more
- ?zero or one.
For example, an expression "A*" matches any number of consecutive characters A.
        An empty line will also match this pattern. The expression "A+" matches a string with at
        least one character A. The expression "A
        {1,4}" corresponds
        to the lines "A", "AA", "AAA", "AAAA".
        The expression "AB?" will correspond to the strings "A" and "AB".
        An expression "." matches any string consisting of one character. The expression ".+" will
        match any text (one or more arbitrary characters). The expression "A.+" matches any string that begins
        with a letter "A". 
There are special characters that do not match any character being checked in a string, but some place in that
        string.The beginning of the line is determined by the ^ symbol, and the end of the line by the symbol $. For example,
      the expression "^this" matches a string that begins with "this". 
The sequence \b indicates the word boundary, that is, the space between a word and a space. The expression "\bis" corresponds
        to the second "is" in the string "this is". The string "\b\w\w\w\w\b" corresponds
        to a four-letter word. The sequence "\B" matches
        all places except word boundaries. The expression "\Bis" corresponds to the first "is" in "this
        is". 
You can use the character "|" ("OR"), when it is necessary to specify several options that a string can correspond to:
        Pattern pattern = Pattern.compile("Ivanov|Petrov");
Matcher matcher = pattern.matcher("These are Ivanov and Petrov and another Ivanov");
while  (matcher.find()) {
    System.out.printf( "\"%s\"", matcher.group());
}
      
      In the above example, each of the options will be matched ("Ivanov" "Petrov" "Ivanov").
If the character "|" is not used separately, but in combination with other elements, then the expression with this symbol must be enclosed in parentheses.
Some class functions of String class use regular expressions. For example, functions replaceFirst() and replaceAll()        return strings for which search and replacement are implemented by regular expressions. 
For example, you need to remove spaces at the beginning and end of a string:
    Pattern p = Pattern.compile("^\\s+"); // all spaces at the beginning of the string 
String s = p.matcher("  These are Ivanov and Petrov and another Ivanov  ").replaceFirst("");
p = Pattern.compile("\\s+$");         // all spaces at the end of the string 
s = p.matcher(s).replaceAll("");
System.out.println(s);
      3 Sample Programs
3.1 View Available Localizations
The getAvailableLocales() method allows us to view the available localizations. The toString() method
        returns a short representation of the localization. With the help of the function getDisplayName() we
      can get more detailed information:
package ua.inf.iwanoff.java.advanced.second;import java.util.Locale;import java.text.NumberFormat;public class AvailableLocales {public static void main(String[] args) { Locale list[] = NumberFormat.getAvailableLocales();for (Locale locale : list) { System.out.printf("%-25s %s%n", locale.toString(), locale.getDisplayName()); } } }
3.2 The First Substring that Matches the Pattern
The following program finds the first substring that matches the pattern.
package ua.inf.iwanoff.java.advanced.second;import java.util.Scanner;import java.util.regex.Pattern;import java.util.regex.Matcher;public class RegexTest {public static void main(String[] args) { Scanner scan =new Scanner(System.in); System.out.printf("%nEnter the regular expression: "); String ex = scan.nextLine(); Pattern pattern = Pattern.compile(ex); System.out.printf("Enter string to search: "); Matcher matcher = pattern.matcher(scan.nextLine());if (matcher.find()) { System.out.printf("Text found " + "\"%s\", starting at position " + "%d and ending with position %d.%n", matcher.group(), matcher.start(), matcher.end()); } } }
3.3 Checking the Phone Number Format
Suppose we need to write a program that checks the entered string for compliance with the format of a landline phone number of the Kharkiv telephone network. Assume that numbers should be written as groups of numbers separated by hyphens. A phone number without a country or city code can be seven or six digits long. Only the last six or seven digits are mandatory for input. Note that the number may contain the country code (three digits), with a "+" sign at the beginning and the city code (57- for seven-digit numbers or 572- for six-digit numbers).
package ua.inf.iwanoff.java.advanced.second;import java.util.Scanner;import java.util.regex.Pattern;import java.util.regex.Matcher;public class RegexTest {public static void main(String[] args) { Scanner scan =new Scanner(System.in); System.out.printf("%nEnter a Phone Number: "); String phone = scan.nextLine(); Pattern p = Pattern.compile("\\+?(380-)?((57-)?\\d{3}|(572-)?\\d{2})-\\d{2}-\\d{2}$"); Matcher m = p.matcher(phone);if (m.matches()) { System.out.println("\"" + phone + "\" - correct number format"); }else { System.out.println("\"" + phone + "\" - wrong number format"); } } }
3.4 Output Words of Sentence
Suppose it is necessary to enter a sentence from the keyboard and output its words in separate lines. We
      will use the split() method of the String class:
package ua.inf.iwanoff.java.advanced.second;import java.util.Scanner;public class UsingSplit {public static void main(String[] args) { Scanner scan =new Scanner(System.in); String sentence = scan.nextLine(); String[] words = sentence.split("\\s");for (String word : words) { System.out.println(word); } } }
A regular expression is specified in the split() method call, which defines the delimiter between
      words.
3.5 "Country" and "Census" Classes
In the examples from the Java Basic Programming Course, class hierarchies to represent country
        and population censuses were considered. In laboratory training
        # 3 of this course, an abstract class AbstractCountry was created,
        as well as concrete classes Census and CountryWithArray. Next, in laboratory
      training # 4, classes CountryWithList and CountryWithSet were created.
Now, using the classes CountryWithList and Census, we will create an application that 
- reproduces the sorting defined in work example laboratory training # 3 of the Java Basic Programming Course;
- performs formatting of numerical data in various ways, as well as taking into account localization;
- outputs data about dates and times of events taking into account localization;
- outputs text in English and Ukrainian;
- implements the ability to sort alphabetically using the Collatorclass;
- provides verification of the occurrence of words in the comment using regular expressions.
Before starting the implementation of the program, it is advisable to determine the bundle of resources with all
        necessary strings. File censuses_en.properties:
Ukraine=Ukraine area=Area unit=sq.km. densityIn1979=Population density in 1979 census=Census year=Year population=Population comments=Comments commentsDate=Date and time of adding comments firstPostwarCensus=The first census after World War II populationIncreases=Population increases noComments=No comments lastSovietCensus=The last soviet census firstCensusInIndependentUkraine=The first census in the independent Ukraine yearWithMaximumPopulation=The year with the maximum population sortingByPopulation=Sorting by population sortingByComments=Sorting by comments word=The word isNotPresentInTheComments=is not present in the comments isPresentInTheComments=is present in the comments
 The code of the censuses_uk.properties file typed in the IntelliJ IDEA environment 
 with the Transparent
      native-to-ascii conversion option enabled:
Ukraine=Україна area=Територія unit=кв. км. densityIn1979=Густота населення у 1979 році census=Перепис year=Рік population=Населення comments=Коментар commentsDate=Дата і час додавання коментаря firstPostwarCensus=Перший перепис після другої світової війни populationIncreases=Нас побільшало noComments=Просто перепис lastSovietCensus=Останній радянський перепис firstCensusInIndependentUkraine=Перший перепис у незалежній Україні yearWithMaximumPopulation=Рік з найбільшим населенням sortingByPopulation=Сортування за кількістю населення sortingByComments=Сортування за алфавітом коментарів word=Слово isNotPresentInTheComments=не міститься в коментарях isPresentInTheComments=міститься в коментарях
The actual content of the censuses_uk.properties file will be different and will contain the codes
      of Ukrainian letters. 
In the new CensusWithDates class, we add a field timeOfEditing of
        type ZonedDateTime for
        storing the date and time of comment editing. The source code of the CensusWithDates class will be
        as follows:
package ua.inf.iwanoff.java.advanced.second;import ua.inf.iwanoff.java.third.Census;import java.time.ZonedDateTime;/** * The class is responsible for presenting the census. * Added comment editing time */ public class CensusWithDatesextends Census {private ZonedDateTime timeOfEditing;/** * Constructor initializes the object with default values */ public CensusWithDates() { }/** * Constructor initializes the object with given values * * @param year year of census * @param population population in the specified year * @param comments the text of the comment * @param timeOfEditing time of comment editing */ public CensusWithDates(int year,int population, String comments, ZonedDateTime timeOfEditing) {super (year, population, comments);this .timeOfEditing = timeOfEditing; }/** * Returns time of comment editing * * @return time of comment editing of a ZonedDateTime object */ public ZonedDateTime getTimeOfEditing() {return timeOfEditing; }/** * Sets the time of comment editing * * @param timeOfEditing the time of comment editing in the form of a ZonedDateTime object */ public void setTimeOfEditing(ZonedDateTime timeOfEditing) {this .timeOfEditing = timeOfEditing; } }
 In the StringsWithLocalization class we define methods for obtaining string representation of census
        and country data, taking into account localization:
package ua.inf.iwanoff.java.advanced.second;import ua.inf.iwanoff.java.fourth.CountryWithArrayList;import java.time.format.DateTimeFormatter;import java.time.format.FormatStyle;import java.util.Locale;import java.util.ResourceBundle;/** * A class that allows getting representation * of various application objects in the form of strings */ public class StringsWithLocalization {/** * Provides a census data in the form of a string * * @param census reference to a census * @return string representation of a census data */ public static String toString(CensusWithDates census) { ResourceBundle bundle = ResourceBundle.getBundle("censuses"); DateTimeFormatter dateFormatter = DateTimeFormatter.ofLocalizedDate(FormatStyle.FULL). withLocale(Locale.getDefault());return String.format(Locale.getDefault(), bundle.getString("census") + ". " + bundle.getString("year") + ": %d, " + bundle.getString("population") + ": %d, " + bundle.getString("comments") + ": %s, " + bundle.getString("commentsDate") + ": %s ", census.getYear(), census.getPopulation(), bundle.getString(census.getComments()), census.getTimeOfEditing().format(dateFormatter)); }/** * Returns a string representation of the country * * @param country reference to a country * @return a string representation of the country */ public static String toString(CountryWithArrayList country) { ResourceBundle bundle = ResourceBundle.getBundle("censuses"); StringBuilder result =new StringBuilder(String.format(Locale.getDefault(), "%s. %s:%10.1f %s", bundle.getString(country.getName()), bundle.getString("area"), country.getArea(), bundle.getString("unit"))); country.getList().forEach(census -> result.append("\n") .append(toString((CensusWithDates)census)));return result.toString(); } }
In the CountryProcessorWithLocalization class we implement methods for searching for words in comments
        and sorting them alphabetically:
package ua.inf.iwanoff.java.advanced.second;import ua.inf.iwanoff.java.fourth.CountryWithArrayList;import ua.inf.iwanoff.java.third.Census;import java.text.Collator;import java.util.*;import java.util.regex.Pattern;/** * Class for processing data about the country and censuses * taking into account localization and working with regular expressions */ public class CountryProcessorWithLocalization {/** * Checks whether the word can be found in the comment text * taking into account localization. * The use of regular expression are used * * @param census reference to a census * @param word a word that should be found in a comment * @return {@code true}, if the word is contained in the comment text * {@code false} otherwise */ public static boolean containsWord(Census census, String word) { ResourceBundle bundle = ResourceBundle.getBundle("censuses");// (?iu) means i (case-insensitive) + u (Unicode for Cyrillic) // Pattern.quote() escapes special characters in a word, if any // The Pattern.UNICODE_CHARACTER_CLASS parameter is required for // support Unicode characters in the expression template Pattern pattern = Pattern.compile("(?iu)\\b" + Pattern.quote(word) + "\\b", Pattern.UNICODE_CHARACTER_CLASS);return pattern.matcher(bundle.getString(census.getComments())).find(); }/** * Creates and returns an array of censuses with the specified word in the comments * * @param country reference to a country * @param word a word that should be found * @return array of censuses with the specified word in the comments */ public static Census[] findWord(CountryWithArrayList country, String word) {return country.getList().stream() .filter(c -> containsWord(c, word)) .toArray(Census[]::new ); }/** * Sorts the sequence of censuses in the alphabetic order of comment * taking into account localization * * @param reference to a country */ public static void sortByComments(CountryWithArrayList country) { ResourceBundle bundle = ResourceBundle.getBundle("censuses"); List<CensusWithDates> arr =new ArrayList<>(); country.getList().forEach(census -> arr.add((CensusWithDates) census)); arr.sort(new Comparator<>() { Collator collator = Collator.getInstance(Locale.getDefault()); @Overridepublic int compare(CensusWithDates c1, CensusWithDates c2) {return collator.compare(bundle.getString(c1.getComments()), bundle.getString(c2.getComments())); } }); country.setList(new ArrayList<>()); country.getList().addAll(arr); } }
The CountryWithLocalizationDemo class demonstrates the capabilities of the new solution:
package ua.inf.iwanoff.java.advanced.second;import ua.inf.iwanoff.java.advanced.first.CountryProcessorWithStreams;import ua.inf.iwanoff.java.fourth.CountryWithArrayList;import ua.inf.iwanoff.java.third.Census;import java.time.*;import java.util.Locale;import java.util.ResourceBundle;import static ua.inf.iwanoff.java.advanced.second.CountryProcessorWithLocalization.sortByComments;/** * Country class workability testing program * taking into account localization and working with time and dates */ public class CountryWithLocalizationDemo {/** * Displays census data that contain a specific word in the comments * * @param country reference to a country * @param word a word that should be found */ public static void printWord(CountryWithArrayList country, String word) { ResourceBundle bundle = ResourceBundle.getBundle("censuses"); Census[] result = CountryProcessorWithLocalization.findWord(country, word);if (result.length == 0) { System.out.println(String.format("%s \"%s\" %s.", bundle.getString("word"), word, bundle.getString("isNotPresentInTheComments"))); }else { String s = bundle.getString("word") + " \"" + word + "\" " + bundle.getString("isPresentInTheComments"); System.out.println(s);for (Census census : result) { System.out.println(StringsWithLocalization.toString((CensusWithDates) census)); } } }/** * Tests search methods * * @param country reference to a country */ public static void testSearch(CountryWithArrayList country) { ResourceBundle bundle = ResourceBundle.getBundle("censuses"); System.out.println(String.format(Locale.getDefault(), "%s:%5.1f", bundle.getString("densityIn1979"), CountryProcessorWithStreams.density(country, 1979))); System.out.println(String.format(Locale.getDefault(), "%s: %d", bundle.getString("yearWithMaximumPopulation"), CountryProcessorWithStreams.maxYear(country))); printWord(country, "census"); printWord(country, "cens"); }/** * Tests sorting methods * * @param country reference to a country */ public static void testSorting(CountryWithArrayList country) { ResourceBundle bundle = ResourceBundle.getBundle("censuses"); CountryProcessorWithStreams.sortByPopulation(country); System.out.println("\n" + bundle.getString("sortingByPopulation")); System.out.println(StringsWithLocalization.toString(country)); sortByComments(country); System.out.println("\n" + bundle.getString("sortingByComments")); System.out.println(StringsWithLocalization.toString(country)); }/** * Auxiliary function of creating a new country object * * @return reference to the new country object */ public static CountryWithArrayList setCountryData() { CountryWithArrayList country =new CountryWithArrayList(); country.setName("Ukraine"); country.setArea(603628); country.addCensus(new CensusWithDates(1959, 41869000, "firstPostwarCensus", ZonedDateTime.of(2025, Month.MARCH.getValue(), 1, 10, 0, 0, 0, ZoneId.of("Europe/Kiev")))); country.addCensus(new CensusWithDates(1970, 47126500, "populationIncreases", ZonedDateTime.of(2025, Month.MARCH.getValue(), 3, 10, 30, 0, 0, ZoneId.of("Europe/Kiev")))); country.addCensus(new CensusWithDates(1979, 49754600, "noComments", ZonedDateTime.of(2025, Month.MARCH.getValue(), 1, 11, 30, 0, 0, ZoneId.of("Europe/Kiev")))); country.addCensus(new CensusWithDates(1989, 51706700, "lastSovietCensus", ZonedDateTime.of(2025, Month.MARCH.getValue(), 2, 14, 0, 0, 0, ZoneId.of("Europe/Kiev")))); country.addCensus(new CensusWithDates(2001, 48475100, "firstCensusInIndependentUkraine", ZonedDateTime.of(2025, Month.MARCH.getValue(), 4, 10, 0, 0, 0, ZoneId.of("Europe/Kiev"))));return country; }/** * Demonstration of functions' work * * @param args command line arguments (not used) */ public static void main(String[] args) { Locale.setDefault(Locale.US); System.out.println(Locale.getDefault()); CountryWithArrayList country = setCountryData(); testSearch(country); testSorting(country); System.out.println("--------------------------------------"); Locale.setDefault(new Locale("uk")); System.out.println(Locale.getDefault()); country = setCountryData(); testSearch(country); testSorting(country); } }
As expected, the word "census" is in the comments only if we are working with the English localization .
4 Exercises
- Display information about all time zones.
- Read a string from the keyboard and check the correct representation of the monetary amount using regular expressions.
- Read a string from the keyboard and check the correctness of the time representation using regular expressions.
5 Quiz
- Name the main components of the Java SE platform.
- What is the difference between classes CalendarandDate?
- How to create an instance of GregorianCalendar?
- What tools for working with the calendar does Java 8 provide?
- What facilities for working with time zones does Java 8 provide?
- What is the difference between internationalization and localization?
- How is a class ResourceBundleused to internationalize and localize applications?
- What is the general purpose of the java.textpackage?
- What are the advantages of sorting by Collator class?
- What is data formatting?
- How is localization-sensitive data formatting done?
- What is a regular expression?
- How to work with regular expressions in Java?
- What are the methods of dividing the text into tokens?
- What is the advantage of using the method split()compared to means ofStringTokenizer?
