410013796724260
• Webmoney
R335386147728
Z369087728698
Классы Date, Calendar, TimeZoneДля удобной работы с датой и временем в Java используются классы Date и Calendar. Оба класса находятся в библиотеке java.util. Класс TimeZone используется совместно с классами Calendar и DateFormat Класс SimpleDateFormat является подклассом класса DateFormat и позволяет определять собственные шаблоны форматирования для отображения даты и времени. На странице рассмотрены следующие классы :
Класс DateКласс Date хранит время в миллисекундах начиная с 1 января 1970 года. Данный класс имеет конструктор по умолчанию, который возвращает текущее время. Кроме этого можно создать объект Date используя конструктор, который принимает количество миллисекунд начиная с 1 января 1970 года. Для получения этого внутреннего времени используется метод getTime(). Кроме этого уже после создания экземпляра класса можно изменить время с помощью setTime(long date). Конструкторы класса Date : Date() Date(long milliseconds) Первый конструктор без параметров инициализирует объект текущей датой и временем. Во втором конструкторе можно указать количество миллисекунд, прошедших с полуночи 1 января 1970 года. Методы класса Date:
Простой пример использования Date для вывода даты в консоль. Date date = new Date(); System.out.println(date.toString()); С помощью метода getTime() можно отобразить количество миллисекунд, прошедших с 1 января 1970 года. Date date = new Date(); long millis = date.getTime(); System.out.println(String.valueOf(millis)); Класс SimpleDateFormatДля того, чтобы отображать дату и время в удобном формате можно использовать класс SimpleDataFormat : package ru.test; import java.util.Date; import java.text.SimpleDateFormat; public class Test { public void test() { Date d = new Date(); SimpleDateFormat format1; SimpleDateFormat format2; format1 = new SimpleDateFormat( "dd.MM.yyyy hh:mm"); format2 = new SimpleDateFormat( "День dd Месяц MM Год yyyy Время hh:mm"); System.out.println( format1.format(d) // 25.02.2013 09:03 ); System.out.println( format2.format(d) // День 25 Месяц 02 Год 2013 Время 09:03 ); } } При создании шаблона представления даты SimpleDateFormat использовались следующие параметры :
В качестве разделитель можно использовать любой текст. Класс SimpleDateFormat является подклассом класса DateFormat и позволяет определять собственные шаблоны форматирования для отображения даты и времени. Символы форматирования строки
Количество повторений символа определяет способ представления даты. Например, можно указать hh:mm:ss, а можно h:m:s. В первом случае при необходимости для чисел 0..9 будет отображаться ноль перед цифрой. Класс CalendarВ документации представлено множество методов для получения или установки отдельных компонентов времени и даты, например, getMinutes()/setMinutes() и др. Все они являются устаревшими и вместо них следует использовать класс Calendar. Абстрактный класс Calendar позволяет работать с датой в рамках календаря, т.е он умеет прибавлять день, при этом учитывать високосные год и прочее, а также позволяет преобразовать время в миллисекундах в более удобном виде - год, месяц, день, часы, минуты, секунды. Единственной реализацией Calendar является класс GregorianCalendar, также как и у даты конструктор по умолчанию возвращает календарь на текущий день, но можно задать его явно указав все параметры : Пример использования классов Calendar и GregorianCalendarimport java.util.Date; import java.util.Calendar; import java.util.GregorianCalendar; import java.text.SimpleDateFormat; public class Test { public void test() { // календарь на текущую дату Calendar c = new GregorianCalendar(); // календарь на 21.12.2014 Calendar c2 = new GregorianCalendar(2014, 12, 21); // увеличиваем дату на 1 день c2.add(Calendar.DAY_OF_YEAR, 1); System.out.println(c2.getTime()); // 22.12.2014 // уменьшаем дату на 1 день c2.add(Calendar.DAY_OF_YEAR, -1); } } Поля класса Calendar
Методы класса Calendar
Календарь достаточно мощный класс, который позволяет получать названия месяцев и дней недели, увеличивать или уменьшать различные параметры текущей даты, а также получать их. Для удобства работы с ним нужно просто разобраться с типами данных, с которыми он работает:
Пример Calendar, GregorianCalendarimport java.util.Date; import java.util.Calendar; import java.util.GregorianCalendar; import java.text.SimpleDateFormat; public class Test { public void test() { // календарь на 25.01.2015 Calendar c = new GregorianCalendar(2015, 01, 25); System.out.println(c.get(Calendar.MONTH)); // 01 System.out.println(c.get(Calendar.YEAR)); // 2015 System.out.println( c.get(Calendar.DAY_OF_WEEK_IN_MONTH)); System.out.println( c.get(Calendar.DAY_OF_WEEK)); System.out.println( c.get(Calendar.DAY_OF_YEAR)); System.out.println( c.get(Calendar.DAY_OF_MONTH)); } } Класс GregorianCalendarКласс GregorianCalendar является подклассом Calendar, который представляет обычный Григорианский календарь. Метод getInstance() класса Calendar обычно возвращает объект класса GregorianCalendar, инициированный текущей датой и временем согласно региональным настройкам. У класса есть два поля AD и BC - до нашей эры и наша эра. Кроме стандартных методов, которые есть в классе Calendar, у GregorianCalendar есть метод isLeapYear() для проверки високосного года: boolean isLeapYear(int year) Если год високосный, то возвращается true. Отсчёт месяцев идёт от нуля, поэтому декабрь будет одиннадцатым месяцем. Чтобы не путаться с такими случаями, проще использовать понятные константы: GregorianCalendar calendar; calendar = new GregorianCalendar(2012,Calendar.DECEMBER,31); А получать нужные отрезки времени можно через метод get (). Например, узнать, какой месяц содержится в созданной нами дате можно так: int month = calendar.get(Calendar.MONTH); System.out.println(month); // вернёт 11 Изменить состояние объекта можно через метод set (). Например, установим новую дату у нашего объекта. GregorianCalendar calendar; calendar = new GregorianCalendar(2012,Calendar.DECEMBER,31); calendar.set(2013, Calendar.FEBRUARY, 23); // Убедимся, что возвращает 1 - февраль System.out.println(calendar.get(Calendar.MONTH)); Можно сдвинуть дату на определённый период с помощью метода add (). Отодвинем дату на два месяца. GregorianCalendar calendar; calendar = new GregorianCalendar(2012,Calendar.DECEMBER,31); calendar.add(Calendar.MONTH, 2); System.out.println(calendar.get(Calendar.MONTH)); Методы getTime() и setTime() работают с объектами Date и полезны для преобразования. GregorianCalendar calendar; calendar = new GregorianCalendar(year, month, day); Date hireDay = calendar.getTime(); Класс TimeZoneКласс TimeZone предназначен для совместного использования с классами Calendar и DateFormat. Этот класс абстрактный, поэтому от него порождать объекты нельзя. Вместо этого определен статический метод getDefault(), который возвращает экземпляр наследника TimeZone с настройками, взятыми из операционной системы, под управлением которой работает JVM. TimeZone имеет статический метод getTimeZone(String ID), используя который можно указать наименование конкретного временного пояса, для которого необходимо получить объект TimeZone. Набор полей, определяющих возможный набор параметров для getTimeZone, нигде явно не описывается. Но имеется статический метод getAvailableIds(), возвращающий список возможных значений наименование временных зон типа String[], который можно использовать в методе getTimeZone. Так можно определить набор возможных параметров для конкретного временного пояса относительно Гринвича String[] getAvailableIds(int offset). Рассмотрим пример, в котором на консоль последовательно выводятся: Пример получения списка TimeZoneimport java.util.Arrays; import java.util.TimeZone; public class TimeZoneList { private final int hour = 1000 * 60 * 60; private final String TEMPL_TZ = "%s (%s)"; private final String TEMPL_OFFS = "hour offset=(%d)"; String align(String str, int len) { if (len - str.length() > 0){ char[] buf = new char[len - str.length()]; Arrays.fill (buf, ' '); return str + new String(buf); } else return str.substring(0, len); } private void drawTimeZoneParam(final TimeZone tz) { String line = null; line = String.format(TEMPL_TZ, tz.getID(), tz.getDisplayName()); line = align(line, 64); line += String.format(TEMPL_OFFS, tz.getRawOffset() / hour); System.out.println(line); } public TimeZoneList() { TimeZone tz = TimeZone.getDefault(); int rawOffset = tz.getRawOffset(); System.out.println("Текущая TimeZone : " + tz.getID() + " (" + tz.getDisplayName() + ")\n"); // Display all available TimeZones System.out.println("Доступные TimeZone\n"); String[] timezones = TimeZone.getAvailableIDs(); for (int cnt = 0; cnt < timezones.length; cnt++){ tz = TimeZone.getTimeZone(timezones[cnt]); drawTimeZoneParam(tz); } // All available TimeZones same as for Moscow System.out.println( "Список TimeZone, соответствующие текущей"); timezones = TimeZone.getAvailableIDs(rawOffset); for(int cnt = 0;cnt < timezones.length;cnt++){ tz = TimeZone.getTimeZone(timezones[cnt]); drawTimeZoneParam(tz); } } public static void main(String[] args) { new TimeZoneList(); System.exit(0); } } Код программы несложный. Метод align выполняет выравнивание для отображения смещения по времени TimeZone от среднего времени по Гринвичу GMT — времени меридиана, проходящего через прежнее место расположения Гринвичской обсерватории около Лондона. Метод drawTimeZoneParam отображает параметры TimeZone. В конструкторе класса TimeZoneList сначала определяется текущая TimeZone, после чего выводится список возможных TimeZone. И в заключении, используя метод getAvailableIDs получаем список TimeZone, у которых смещение по времени соответствует текущей зоне. В результате работы программы в консоль будет выведена следующая информация (первый список в усеченном виде): Текущая TimeZone : Europe/Moscow (Moscow Standard Time) Доступные TimeZone Etc/GMT+12 (GMT-12:00) hour offset=(-12) Etc/GMT+11 (GMT-11:00) hour offset=(-11) Pacific/Midway (Samoa Standard Time) hour offset=(-11) Pacific/Niue (Niue Time) hour offset=(-11) Pacific/Pago_Pago (Samoa Standard Time) hour offset=(-11) Pacific/Samoa (Samoa Standard Time) hour offset=(-11) US/Samoa (Samoa Standard Time) hour offset=(-11) . . . Список TimeZone, соответствующие текущей Asia/Baku (Azerbaijan Time) hour offset=(4) Asia/Dubai (Gulf Standard Time) hour offset=(4) Asia/Muscat (Gulf Standard Time) hour offset=(4) Asia/Tbilisi (Georgia Time) hour offset=(4) Asia/Yerevan (Armenia Time) hour offset=(4) Etc/GMT-4 (GMT+04:00) hour offset=(4) Europe/Moscow (Moscow Standard Time) hour offset=(4) Europe/Samara (Samara Time) hour offset=(4) Europe/Simferopol (Moscow Standard Time) hour offset=(4) Europe/Volgograd (Volgograd Time) hour offset=(4) Indian/Mahe (Seychelles Time) hour offset=(4) Indian/Mauritius (Mauritius Time) hour offset=(4) Indian/Reunion (Reunion Time) hour offset=(4) NET (Armenia Time) hour offset=(4) W-SU (Moscow Standard Time) hour offset=(4) TimeZone UTCВ практике не часто приходится использовать различные TimeZone. Задачи, где разработчику приходится учитывать временной сдвиг, относятся к специфической деятельности человечества. Так, например, в расписании движения пассажирских поездов РФ указывается привязка к московскому и местному времени. А по какому времени ведет пассажирский состав машинист дальнего следования? Эта несложная задача решается в рамках министерства ЖД транспорта. Если состав выходит за пределы страны, то время движения (расписание) должно быть согласовано с соответствующей стороной. Аналогично это касается и полетов воздушного транспорта, где все согласования между различными аэропортами выполняются по времени UTC - всеми́рное координи́рованное вре́мя (Coordinated Universal Time). UTC было введено вместо устаревшего среднего времени по Гринвичу (GMT), поскольку GMT является неравномерной шкалой и связана с суточным вращением Земли. Шкала UTC основана на равномерной шкале атомного времени и является более удобной для гражданского использования. Как может влиять TimeZone, с точки зрения разработчика, на результаты работы программы? Давайте представим себе ситуацию, что время формируется на сервере (объект типа Date) и отправляется удаленному пользователю по сети. Это типично для WEB-приложений, у которых сервер и пользователи (браузеры) могут быть расположены в разных временных зонах. Для отправки объекта Date по сети (Internet) используется сериализация, позволяющая упаковать объект в набор байт на сервере и восстановить объект типа Date на клиенте (браузере). И вот здесь Вас может ожидать «засада». Если сервер и клиент имеют разные TimeZone (часовые пояса), то на клиенте будет восстановлен объект Date с временем сервера. И наоборот, если объект будет отправлен с клиента на сервер, то на сервере объект десериализуется с временем клиента. Конечно, объект Date можно конвертировать не сервере в текстовый вид, используя DateFormat, и на клиенте его восстановить. Но Java позволяет учитывать различные TimeZone, не оказывающие влияние на сериализацию/десериализацию объектов типа Date. Давайте рассмотрим пример TimeZoneExample (код представлен ниже), в котором время будем привязывать к одной из сторон (желательно серверной), а на компьютере устанавливать различные зоны (UTC, Москва, Владивосток). Для установки определенной временной зоны необходимо открыть в панели управления окно «Date and Time» и выбрать соответствующую TimeZone. import java.util.Date; import java.util.TimeZone; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; public class TimeZoneExample { private final String TIMEZONE_utc ; private final String TIMEZONE_msc ; private final String DATETIME_format; //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public TimeZoneExample() { // TimeZone.setDefault( // TimeZone.getTimeZone(TIMEZONE_utc)); TIMEZONE_utc = "UTC"; TIMEZONE_msc = "Europe/Moscow"; DATETIME_format = "yyyy-MM-dd HH:mm:ss.SS"; Date date = new Date(); Date dt_msk = null; TimeZone tm_curr = TimeZone.getDefault(); System.out.println ("Current TimeZone : \"" + tm_curr.getID() + "\" (" + tm_curr.getDisplayName() + ")"); System.out.println ("useDaylightTime : " + tm_curr.useDaylightTime() + "\n"); TimeZone tm_utc; TimeZone tm_msk; tm_utc = TimeZone.getTimeZone(TIMEZONE_utc); tm_msk = TimeZone.getTimeZone(TIMEZONE_msc); DateFormat df_utc; DateFormat df_msk; df_utc = new SimpleDateFormat(DATETIME_format); df_msk = new SimpleDateFormat(DATETIME_format); df_utc.setTimeZone(tm_utc); df_msk.setTimeZone(tm_msk); String date_utc = df_utc.format(date); String date_msk = df_msk.format(date); try { dt_msk = df_msk.parse(date_msk); } catch (ParseException e) {} System.out.println ("UTC\n" + date); System.out.println (date_utc); System.out.println (tm_utc.getRawOffset()); System.out.println (); System.out.println ("Moscow\n" + dt_msk); System.out.println (date_msk); } //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ public static void main(String[] args) { new TimeZoneExample(); System.exit(0); } } В примере используется три TimeZone (tm_curr, tm_utc, tm_msk - текущая, зона UTC, зона Москвы). Для двух временных зон (tm_utc, tm_msk) выводим в консоль объект Date без форматирования и с форматированием с использованием tm_utc, tm_msk и DateFormat/SimpleDateFormat. Первоначально на компьютере устанавливаем зону UTC и получаем в консоли следующий текст : Current TimeZone : "UTC" (Coordinated Universal Time) useDaylightTime : false UTC Fri Dec 23 08:50:24 UTC 2016 2016-12-23 08:50:24.547 Moscow Fri Dec 23 08:50:24 UTC 2016 2016-12-23 11:50:24.547 Здесь следует сказать, что для зоны UTC и для зоны Москвы неформатированные даты (date, dt_msk) совпадают, но вот с учетом временной зоны форматированные даты отличаются на соответствующие 3 часа. Теперь установим зону на компьютере зону Москвы и получим в консоли следующий текст : Current TimeZone : "Europe/Moscow" (Moscow Standard Time) useDaylightTime : false UTC Fri Dec 23 11:51:18 MSK 2016 2016-12-23 08:51:18.915 Moscow Fri Dec 23 11:51:18 MSK 2016 2016-12-23 11:51:18.915 Все как по науке - смещения по времени для дат UTC и Москвы поменялись местами. В заключении устанавливаем временную зону Владивостока : Current TimeZone : "Asia/Vladivostok" (Vladivostok Time) useDaylightTime : false UTC Fri Dec 23 19:55:35 VLAT 2016 2016-12-23 09:55:35.924 Moscow Fri Dec 23 19:55:35 VLAT 2016 2016-12-23 12:55:35.924 Все соответствует действительности - объект даты создается во временной зоне Владивостока. Время для TimeZone Москвы и UTC соответствуют. Если приложение должно работать в определенной временной зоне TimeZone, то можно, используя метод setDefault класса TimeZone, установить соответствующую временную зону в приложении при работе с датой. В примере можно было бы снять комментарий с первой строки и установить сответствующую временную зону в приложении, не оказывая влияния на временную зону в настройках компьютера. Скачать исходный код примераИсходный код рассмотренных примеров можно скачать здесь (6.69 Кб). Наверх |