Назад Зміст Вперед

10.8. Класи Date, Locale

Клас Date

Має два конструктора: перший не має параметрів і привласнює об'єкту поточну дату і час, другий встановлює їх за допомогою завдання в параметрі кількості мілісекунд, що пройшли З 01.01.1970. Має основні методи  after, before, clone, getTime  (повернення мілісекунд) і SetTime (встановлення мілісекунд). Метод ToString присутній майже у всіх об'єктів.

Клас Date має чорно-біле минуле. Його API дизайн не призначений для інтернаціоналізації завдань. В даний час більшість методів класу вилучені, і для більшості задач доцільніше користуватись класом Calendar замість класу  Date

Клас Date: його традиційний код є дійсно легким для швидкого знаходження поточної дати і часу, універсального часу, що не залежить від часових зон, і, нарешті, він є тимчасовим містком для форматування об’єкту Calendar із використанням класу DateFormat.
Як вже згадано вище, екземпляр класу Date представляє відлік дати і часу, що збережені як примітиви типу long. Особливістю є те, що long вміщує кількість мілісекунд (в одній секунді міститься 1000 мілісекунд) між заданою датою і 1 січня 1970 року.

Для того, щоб збагнути наскільки дійсно великими є ці числа, використаємо клас Date для визначення періоду в трильйон мілісекунд, починаючи з 1 січня, 1970:

import java.util.*;
class TestDates {
  public static void main(String[] args) {
    Date d1 = new Date(1000000000000L);  // трильйон!
    System.out.println("1st date " + d1.toString());
  }
}

На JVM із американською локацією сформується вивід:
1st date Sat Sep 08 19:46:40 MDT 2001

Тобто, для майбутніх справок запам’ятаємо, що трильйон мілісекунд збігає за кожні 31 і 2/3 роки.
Незважаючи на те, що більшість методів Date's видалені, дотепер можна використати методи getTime і setTime , хоча і не без складнощів.

Додамо 1 годину до екземпляру d1 об’єкту Date з попереднього прикладу:

import java.util.*;
class TestDates {
  public static void main(String[] args) {
    Date d1 = new Date(1000000000000L);  // трильйон!
System.out.println("1st date " + d1.toString());
    d1.setTime(d1.getTime() + 3600000); // 3600000 мс/год.
    System.out.println("new time " + d1.toString());
  }
}

що видає на тій самій JVM:
1st date Sat Sep 08 19:46:40 MDT 2001
new time Sat Sep 08 20:46:40 MDT 2001

Відмітимо, що методи setTime() і getTime() використовували доступну мілісекундну шкалу. Таким чином, маніпулювання датами на основі класу Date не є найкращим вибором, враховуючи розмірність чисел, що використовуються, наприклад, при додаванні  року до заданої дати.
Необхідно запам’ятати єдину річ: при створенні екземпляру Date, що представляє поточний момент, застосовується конструктор без аргументів:

Date now = new Date();

(При виклику now.getTime(), отримується число в межах між одним і двома трильйонами).

Клас Locale

Потрібен для визначення мовного регіону. Містить кілька констант з назвами різних країн, наприклад GERMANY і ITALY. У конструкторі можна вказати мову і країну. За допомогою статичного методу SetDefault можна встановити регіон за замовчуванням. За допомогою методу getDisplayCountry () можна отримати назву країни, а за допомогою методу getDisplayLanguage () - мова.

Як було показано раніше, цей клас, в основному, допомагає робити базові інтернаціоналізаційні завдання, тобто є квитком до влади над світом”. Обидва класи, DateFormat та NumberFormat, який буде розглянуто наступним, можуть використовувати екземпляри Locale для вибору відформатованого виводу, специфічного для заданої місцевості (локації). Як Java визначає місцеву специфіку? В API вказано, що локація є "специфічним географічним, політичним, або культурним регіоном." 

Locale(String language)
Locale(String language, String country)

String аргумент мови представлений вимогами ISO 639 Language Code, отже при неохідності, наприклад, відформатувати дати і числа в Walloon (мова, що колись використовувалась на півдні Бельгії), використовується "wa" як String аргумент мови. Є більше 500 мовних кодів згідно ISO Language сodes.

Повернемось до застосовування цих кодів. Для представлення базової італійської у програмі все, що потрібно - це код мови. Якщо, з іншого боку, для представлення італійської мови, якою користуються у Швейцарії, необхідно вказати, що країна -  Швейцарія ( код Швейцарії - "CH"), але мова - італійська:

Locale locPT = new Locale("it");        // Italian
Locale locBR = new Locale("it", "CH");  // Switzerland

Використання цих двох локацій для дати виведе приблизно наступне:

sabato 1 ottobre 2005
sabato, 1. ottobre 2005

Наступний код створює об’єкт Calendar, задає йому дату, потім конвертує в Date. Отриманий об’єкт Date друкується із використанням локацій з усього світу:

Calendar c = Calendar.getInstance();
c.set(2010, 11, 14);      // December 14,2010 (month is 0-based)
Date d2 = c.getTime();
Locale locIT = new Locale("it", "IT");  // Italy
Locale locPT = new Locale("pt");        // Portugal
Locale locBR = new Locale("pt", "BR");  // Brazil
Locale locIN = new Locale("hi", "IN");  // India
Locale locJA = new Locale("ja");        // Japan
DateFormat dfUS = DateFormat.getInstance();
System.out.println("US" + dfUS.format(d2));
DateFormat dfUSfull=DateFormat.getDateInstance(DateFormat.FULL);
System.out.println("US full" + dfUSfull.format(d2));   
DateFormat dfIT = DateFormat.getDateInstance(
                                        DateFormat.FULL, locIT);
System.out.println("Italy" + dfIT.format(d2));
DateFormat dfPT = DateFormat.getDateInstance(
                                        DateFormat.FULL, locPT);
System.out.println("Portugal" + dfPT.format(d2));
DateFormat dfBR = DateFormat.getDateInstance(
                                        DateFormat.FULL, locBR);
System.out.println("Brazil" + dfBR.format(d2));   
DateFormat dfIN = DateFormat.getDateInstance(
                                        DateFormat.FULL, locIN);
System.out.println("India" + dfIN.format(d2));
DateFormat dfJA = DateFormat.getDateInstance(
                                        DateFormat.FULL, locJA);
System.out.println("Japan" + dfJA.format(d2));

Варіант виводу:
US       12/14/10 3:32 PM
US full  Sunday, December 14, 2010
Italy    domenica 14 dicembre 2010
Portugal Domingo, 14 de Dezembro de 2010
Brazil   Domingo, 14 de Dezembro de 2010
India    ??????, ?? ??????, ????
Japan    2010?12?14?

Використана JVM не сконфігурувала підтримку для локацій India (Індії) та Japan (Японії), проте видно, як єдиний об’єкт Date форматується для роботи на багатьох локаціях.

Об’єкти обидвох класів DateFormat і NumberFormat можуть встановлювати локацію тільки в час ініціалізації. Слідкуйте за кодом, який намагається змінити локацію існуючого екземпляру класу — не існує таких методів!

Є методи класу  Locale (getDisplayCountry() і getDisplayLanguage()), які дозволяють створювати Strings, що представляють собою країну і мову заданої локації в перекладі локації, заданої за замовчуванням або будь-якої іншої локації:

Calendar c = Calendar.getInstance();
c.set(2010, 11, 14);
Date d2 = c.getTime();
Locale locBR = new Locale("pt", "BR");  // Brazil
Locale locDK = new Locale("da", "DK");  // Denmark
Locale locIT = new Locale("it", "IT");  // Italy
System.out.println("def " + locBR.getDisplayCountry());
System.out.println("loc " + locBR.getDisplayCountry(locBR));
System.out.println("def " + locDK.getDisplayLanguage());
System.out.println("loc " + locDK.getDisplayLanguage(locDK));
System.out.println("D>I " + locDK.getDisplayLanguage(locIT));

Вивід:
def Brazil
loc Brasil
def Danish
loc dansk
D>I danese

Для використаної JVM локація за замовчування є США, в якій країна Бразилія є "Brazil", і мова в Данії є "Danish". В самій Бразилії країна називається "Brasil", датська мова в Данії називається "dansk". Нарешті, для забави показано, що в Італії датська мова називається "danese".

Shildt, ст.529
Shildt, ст.537
.