| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > Java: Общие вопросы > Работа с датами |
| Автор: LSD 13.9.2005, 20:56 |
| Работа с датами в Java. Календарь - система времясчисления. Основанием К. служат астрономические явления: обращение земли вокруг солнца (солнечный К.), луны вокруг земли (лунный К.) и земли вокруг своей оси. Малый энциклопедический словарь Брокгауза и Ефрона В Древнем Риме К. сначала называли книги, в которые кредиторы записывали проценты, вносившиеся ежемесячно в дни календ (отсюда название), позднее К. стали именовать книги, расписывающие культовые празднества, дни рождения императоров, дни собраний сената. Большая советская энциклопедия Базовым классом для хранения даты в Java, является java.util.Date. От него унаследовано несколько классов java.sql.Date, java.sql.Time, java.sql.Timestamp, которые предназначены для работы с базами данных. Для манипулирования датами предназначен класс java.util.Calendar, он позволяет для любой даты узнать такие вещи как: день недели, месяц, номер недели в году и месяце, номер дня в году и т.п. Еще одним важным классом для работы с датой является java.util.TimeZone. Класс TimeZone представляет собой временную зону. Временная зона характеризует насколько время в данном регионе, смещено относительно некой нулевой точки. В качестве нулевой точки выбрано время на гринвичском меридиане GMT (Greenwich Mean Time), иначе его называют - UTC (Universal Coordinated Time - всеобщее скоординированное время). Все остальные пояса указывают как смещение от GMT, например Москва это GMT+03:00, что означает, что для получения московского времени, надо к времени по Гринвичу прибавить 3 часа 0 минут. Временная зона это не одно и то же, что и часовой пояс: не везде временная зона совпадает с часовым поясом, в часовом поясе нет понятия зимнего/летнего времени. Часовой пояс характеризует только географическое положение территории, но не используемое на ней время. Существует несколько стандартных имен временных зон:
Класс Calendar предназначен для манипулирования датами. Сам класс Calendar абстрактный, и служит базовым классом для реализации других календарей. Получить умолчальный календарь можно с помощью Calendar.getInstance(), можно получить календарь для указанного часового пояса и региона (Locale). У Calendar есть список полей, которые характеризуют дату, это:
Теперь собственно о том, как происходит работа с датой, установить дату можно двумя способами. Первый методами setTime(<дата>) и setTimeInMillis(<миллисекунды>), можно просто установить время, при этом будут вычислены и установлены все поля. Потом можно будет получить или изменить любое поле. Другой способ состоит в том, чтобы устанавливать значения полей и затем на основе этих данных получить дату. Поля могут принимать взаимоисключающие значения, тогда во внимание принимается последнее изменение, например можно установить месяц, а затем установить день в году, тогда даты будет считаться исходя из номера дня в году, независимо от того какой месяц мы до этого установили. А вот если попробовать наоборот, то тут посложнее, когда мы установим день года, то автоматом будут вычислены месяц и день месяца, изменив месяц, день месяца останется неизменным. Если какое то поле не было установлено, явно или опосредованно, то оно принимает значение по умолчанию, как правило это первое число, первый месяц и т.д. Теперь рассмотрим один тонкий момент, при установки одного значения значение другого поля может стать не корректным. Например, был дата 31 января, мы установили месяц в февраль, 31 число месяца стало не действительным. Что при этом произойдет от того, какое значение имеет свойство lenient, если оно установлено в true, то лишние дни будут "перенесены" на следующий месяц (в нашем примере мы получим 3 марта, для не високосного года), если оно установлено в false, то будет вызвано исключение IllegalArgumentException. По умолчанию lenient установлено в true. Есть еще несколько вспомогательных методов по работе с полями. Метод clear(<поле>) устанавливает поле в умолчальное значение, clear() устанавливает все поля в умолчальные значения (в результате мы получим 00:00:00.000 31 Январь 2005 н.э. GMT). Узнать было ли поле установлено явно или не явно, можно с помощью isSet(<поле>), false возвращается для полей, которые вообще не были установлены явно или не явно. Функция add(<поле>,<значение>) добавляет к указанному полю, указанную величину (прибавлять можно и отрицательные величины), при этом могут измениться и другие поля, например если для 31 января вызвать add(Calendar.DAY_OF_MONTH, 2), то получим 2 февраля. Есть функция roll(<поле>,<значение>), схожая с add, но отличающаяся тем что при изменении поля "старшие" поля меняться не будут, в нашем примере roll(Calendar.DAY_OF_MONTH, 2) поменяет дату с 31 января на 2 января. Несмотря на то что старшие поля не меняются, младшие будут меняться если для 31 января выполнить roll(Calendar.MONTH, 1), то получим 28 февраля (или 29 для високостного года). Это основные понятия по работе с датой, осталось рассмотреть временные интервалы. В Java нет особого класса для работы с временными интервалами. Если нужно вычислить время прошедшее между двумя датами, то это делается достаточно просто: (dateTill.getTime() - dateFrom.getTime()) и получим количество миллисекунд прошедших с первого момента времени до второго. Чтобы получить например количество часов, надо полученную величину разделить на 3 600 000. Если же надо вычислить количество календарных суток, прошедших с первого момента до второго, то надо использовать Calendar и его функции по работе с полями. Добавлено @ 20:57 Готов выслушать пожелания по даработке статьи |
| Автор: batigoal 13.9.2005, 22:50 |
| Для начала выслушай "спасибу" Если через пару дней никаких изменений не предложат, добаим в ФАК. |
| Автор: LSD 13.9.2005, 23:08 | ||
Bitte |
| Автор: Zandr 14.9.2005, 08:39 | ||||
| Здорово! Замечены (возможные) очепятки:
|
| Автор: LSD 14.9.2005, 09:18 | ||
Fixed Добавлено @ 09:19 Сюда желательно добавить какие нибудь примерчики, но у меня нет идей по этому поводу. Может кто что подкинет? |
| Автор: AntonSaburov 14.9.2005, 11:17 |
| Статья приятная. Наверно в качестве примеров надо привести возможности по обработке дат. Например: 1. Какая дата была 10 дней назад (послезавтра) 2. Какой день недели был такого-то числа. 3. Получить разницу дат в днях/месяцах/годах/часах |
| Автор: Stampede 14.9.2005, 21:57 | ||||
Отличная статья, спасибо.
Смеялся
Сколько себя помню, для меня всегда было большой морокой выполнять манипуляции с датами. В частности, частыми задачами являются: - составление даты по числу, месяцу и году; - округление текущей даты до года, месяца и т. д. - получение максимальной даты заданного месяца. Вот такие пожелания. |
| Автор: jer1 16.9.2005, 13:36 | ||||
| Думаю при работе с датой/временем возникает ещё задача перевода онной в текстовый вид и обратно. Для облегчения работы с текстом сущесвует пакет java.text, для нашего случая это классы данного пакета: java.text.DateFormat, java.text.SimpleDateFormat Кроме того в jdk 1.5 появился класс java.util.Formatter, который также можно использовать для представления даты в нужном текстовом виде следующая программа это демонстрирует:
а вот ещё одна программа по работе с датой:
|
| Автор: LSD 18.9.2005, 01:52 | ||||||||||||||
| Итак примерчики: Посчитать дату на N дней вперед/назад от указанной
Установить временную составляющую в начало суток:
Получить день недели:
Получить день недели в текстовом виде, на французком языке:
Получить дату по году, месяцу и дню месяца:
Получить максимальный день месяца:
Ну и на последок простенькая TableModel отображающая календарь на указанный месяц:
|
| Автор: batigoal 18.9.2005, 09:45 | ||||||||||||||||||
| В FAQ можно добавлять только один пост, поэтому, если не возражаете, я объединю все в одно сообщение: Работа с датами в Java. Календарь - система времясчисления. Основанием К. служат астрономические явления: обращение земли вокруг солнца (солнечный К.), луны вокруг земли (лунный К.) и земли вокруг своей оси. Малый энциклопедический словарь Брокгауза и Ефрона В Древнем Риме К. сначала называли книги, в которые кредиторы записывали проценты, вносившиеся ежемесячно в дни календ (отсюда название), позднее К. стали именовать книги, расписывающие культовые празднества, дни рождения императоров, дни собраний сената. Большая советская энциклопедия Базовым классом для хранения даты в Java, является java.util.Date. От него унаследовано несколько классов java.sql.Date, java.sql.Time, java.sql.Timestamp, которые предназначены для работы с базами данных. Для манипулирования датами предназначен класс java.util.Calendar, он позволяет для любой даты узнать такие вещи как: день недели, месяц, номер недели в году и месяце, номер дня в году и т.п. Еще одним важным классом для работы с датой является java.util.TimeZone. Класс TimeZone представляет собой временную зону. Временная зона характеризует насколько время в данном регионе, смещено относительно некой нулевой точки. В качестве нулевой точки выбрано время на гринвичском меридиане GMT (Greenwich Mean Time), иначе его называют - UTC (Universal Coordinated Time - всеобщее скоординированное время). Все остальные пояса указывают как смещение от GMT, например Москва это GMT+03:00, что означает, что для получения московского времени, надо к времени по Гринвичу прибавить 3 часа 0 минут. Временная зона это не одно и то же, что и часовой пояс: не везде временная зона совпадает с часовым поясом, в часовом поясе нет понятия зимнего/летнего времени. Часовой пояс характеризует только географическое положение территории, но не используемое на ней время. Существует несколько стандартных имен временных зон:
Класс Calendar предназначен для манипулирования датами. Сам класс Calendar абстрактный, и служит базовым классом для реализации других календарей. Получить умолчальный календарь можно с помощью Calendar.getInstance(), можно получить календарь для указанного часового пояса и региона (Locale). У Calendar есть список полей, которые характеризуют дату, это:
Теперь собственно о том, как происходит работа с датой, установить дату можно двумя способами. Первый методами setTime(<дата>) и setTimeInMillis(<миллисекунды>), можно просто установить время, при этом будут вычислены и установлены все поля. Потом можно будет получить или изменить любое поле. Другой способ состоит в том, чтобы устанавливать значения полей и затем на основе этих данных получить дату. Поля могут принимать взаимоисключающие значения, тогда во внимание принимается последнее изменение, например можно установить месяц, а затем установить день в году, тогда даты будет считаться исходя из номера дня в году, независимо от того какой месяц мы до этого установили. А вот если попробовать наоборот, то тут посложнее, когда мы установим день года, то автоматом будут вычислены месяц и день месяца, изменив месяц, день месяца останется неизменным. Если какое то поле не было установлено, явно или опосредованно, то оно принимает значение по умолчанию, как правило это первое число, первый месяц и т.д. Теперь рассмотрим один тонкий момент, при установки одного значения значение другого поля может стать не корректным. Например, был дата 31 января, мы установили месяц в февраль, 31 число месяца стало не действительным. Что при этом произойдет от того, какое значение имеет свойство lenient, если оно установлено в true, то лишние дни будут "перенесены" на следующий месяц (в нашем примере мы получим 3 марта, для не високосного года), если оно установлено в false, то будет вызвано исключение IllegalArgumentException. По умолчанию lenient установлено в true. Есть еще несколько вспомогательных методов по работе с полями. Метод clear(<поле>) устанавливает поле в умолчальное значение, clear() устанавливает все поля в умолчальные значения (в результате мы получим 00:00:00.000 31 Январь 2005 н.э. GMT). Узнать было ли поле установлено явно или не явно, можно с помощью isSet(<поле>), false возвращается для полей, которые вообще не были установлены явно или не явно. Функция add(<поле>,<значение>) добавляет к указанному полю, указанную величину (прибавлять можно и отрицательные величины), при этом могут измениться и другие поля, например если для 31 января вызвать add(Calendar.DAY_OF_MONTH, 2), то получим 2 февраля. Есть функция roll(<поле>,<значение>), схожая с add, но отличающаяся тем что при изменении поля "старшие" поля меняться не будут, в нашем примере roll(Calendar.DAY_OF_MONTH, 2) поменяет дату с 31 января на 2 января. Несмотря на то что старшие поля не меняются, младшие будут меняться если для 31 января выполнить roll(Calendar.MONTH, 1), то получим 28 февраля (или 29 для високостного года). Это основные понятия по работе с датой, осталось рассмотреть временные интервалы. В Java нет особого класса для работы с временными интервалами. Если нужно вычислить время прошедшее между двумя датами, то это делается достаточно просто: (dateTill.getTime() - dateFrom.getTime()) и получим количество миллисекунд прошедших с первого момента времени до второго. Чтобы получить например количество часов, надо полученную величину разделить на 3 600 000. Если же надо вычислить количество календарных суток, прошедших с первого момента до второго, то надо использовать Calendar и его функции по работе с полями. Примеры использования: Посчитать дату на N дней вперед/назад от указанной
Установить временную составляющую в начало суток:
Получить день недели:
Получить день недели в текстовом виде, на французком языке:
Получить дату по году, месяцу и дню месяца:
Получить максимальный день месяца:
Ну и на последок простенькая TableModel отображающая календарь на указанный месяц:
При работе с датой/временем возникает задача перевода оной в текстовый вид и обратно. Для облегчения работы с текстом сущесвует пакет java.text, для нашего случая это классы данного пакета: java.text.DateFormat, java.text.SimpleDateFormat Кроме того, в JDK 5.0 появился класс java.util.Formatter, который также можно использовать для представления даты в нужном текстовом виде. Пример 1:
Пример 2:
|
| Автор: LSD 18.9.2005, 10:57 |
| Да, еще одно дополнение, в конец метода set(int,int), надо вставить fireTableStructureChanged() иначе JTable не узнает что надо обновиться. |
| Автор: batigoal 18.9.2005, 12:15 |
| Добавил. |
| Автор: AntonSaburov 19.9.2005, 12:06 |
| Статья находится в FAQ - Java->Статьи |