Про непереносимость
Не переношу запаха (да и вкуса тоже) горчицы. А больше всего не переношу непереносимость. К счастью, программируя на java, об этом можно сильно не беспокоиться. К несчастью, когда об этом сильно не беспокоишься, получаешь то что больше всего не переносишь.
Задача: J2SE 1.4.x, необходим объект java.util.Date, представляющий дату текущего дня с точностью то числа.
Решение 1: Создать java.util.Calendar, выставить в нем значения необходимых полей, а остальные очистить. Делаем:
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Locale;
public class TestClearCalendar {
public static void main(String[] args) {
final int[] fields = new int[] {
Calendar.MILLISECOND,
Calendar.SECOND,
Calendar.MINUTE,
Calendar.HOUR_OF_DAY,
};
final Locale locale = new Locale("ru", "RU");
final Calendar cal = Calendar.getInstance(locale);
final DateFormat format = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss SSS ", locale);
for (int i = 0; i < fields.length; i++) {
cal.clear(fields[i]);
}
System.out.println(format.format(cal.getTime()));
}
}
Пускаем и получаем дату, но с точностью до часа:
10.01.2006 15:00:00 000.
После этого обнаруживаем, что проблема то давно известная, и по понятным/непонятным причинам, вовсе не является багом, а всего-лишь неясность в документации. Ок. Воспользуемся первой заплаткой, добавив Calendar.HOUR в массив обновляемых полей. Пускаем, смотрим, все хорошо:
10.01.2006 00:00:00 000.
Прошло n дней…
И мы перешли на Java SE 5.0. И вдруг замечаем что что-то в нашей системе творится неладное, и работает она как оборотень, только наоборот - днем с ней происходят странные вещи. После нескольких часов/дней в отладчике вдруг выясняется, что наш код в разное время суток (до и после полуночи) работает по-разному:
final Calendar cal = Calendar.getInstance(locale);
final Calendar cal2 = (Calendar) cal.clone();
cal2.add(Calendar.HOUR_OF_DAY, 12);
final DateFormat format = new SimpleDateFormat("dd.MM.yyyy HH:mm:ss SSS ", locale);
for (int i = 0; i < fields.length; i++) {
cal.clear(fields[i]);
cal2.clear(fields[i]);
}
System.out.println(format.format(cal.getTime()));
System.out.println(format.format(cal2.getTime()));
в итоге дает
10.01.2006 12:00:00 000
11.01.2006 00:00:00 000
Читаем баг-репорт внимательнее и находим, что оказывается час в календаре определяется тремя независимыми полями, и если хоть одно из них не очищено - час дня вычисляется исходя из его значения. Судя по всему инженеры из SUN не только поправили документацию, но и немного исправили реализацию календаря согласно ей, и теперь после полудня наше врямя сбрасывается в полудень. После правки по настоянию “солнцеподобных”, похоже все приходит в норму.
Итак, если необходимо получить дату без времени, необходимо вызвать clear для полей Calendar.MILLISECOND, Calendar.SECOND, Calendar.MINUTE, Calendar.HOUR_OF_DAY, Calendar.HOUR и Calendar.AM_PM.
Даже если вас съели, у вас есть два выхода (© народное)
Конечно можно воспользоваться и второй заплаткой, установив значения полей Calendar.MILLISECOND, Calendar.SECOND, Calendar.MINUTE и Calendar.HOUR_OF_DAY в 0.
Однако если понадобится получить объект java.util.Date с точностью до месяца, то необходимо помнить, что минимальное значение поля Calendar.DATE и других полей, определяющих день недели/месяца/года - это 1, и использовать нужно именно его, иначе получим или последнее число предыдущего месяца или еще чего доброго исключение.
Изменен

Аноним заявил:
Добавлено 1 февраля, 2006 в 15:53Спасибо.
Очень информативно и довольно поэтично
Игорь заявил:
Добавлено 28 июля, 2006 в 15:12Как вариант можно просто создать новый Calendar и скопировать значения полей YEAR, MONTH и DAY_OF_MONTH
А ещё можно использовать библиотеку Joda Time, которая содержит более внятные примитивы для работы с временем и временными интервалами, чем JDK.
lucker (чел в теме) заявил:
Добавлено 11 августа, 2006 в 17:00Нельзя по той простой причине, что новый календарь установлен в текущее время системы. Т.е. в любом случае надо некоторые поля календаря очистить.
Про Joda Time слышал - неплохая вешь, но не всегда есть смысл тащить в проект еще одну зависимость, когда достаточно сделать пару утилитных классов/методов для достижения нужного результата.