Вызов Java Calendar.getTime () необходим для обновления объекта? - PullRequest
5 голосов
/ 10 сентября 2009

Я наткнулся на комментарий в каком-то Java-коде, в котором говорится, что getTime() должен быть вызван для обновления объекта Calendar. Это правда? Я не могу найти ничего, что говорит о том, что это необходимо.

Вот код:

Calendar cal = new GregorianCalendar();
cal.setFirstDayOfWeek(Calendar.SUNDAY);
cal.set(2009, 9 - 1, 10, 2, 30);
// Get Time needs to be called to update the Calendar object
cal.getTime();

Ответы [ 5 ]

9 голосов
/ 08 октября 2013

cal.getTime() действительно нужно вызывать, чтобы пересчитать его внутренности. Это очень странное поведение для API, но в Calendar javadocs это прямо указано:

Получение и установка значений полей календаря

Значения полей календаря можно установить, вызвав методы set. любой значения полей, установленные в календаре, не будут интерпретироваться до тех пор, пока это не потребуется рассчитать его значение времени (миллисекунды от эпохи) или значения поля календаря. Вызов get, getTimeInMillis, getTime, add и бросок включает в себя такой расчет.

...

Манипуляция полем

Поля календаря можно изменить тремя способами: set (), add (), и катиться (). set (f, value) меняет поле календаря f на значение. В Кроме того, он устанавливает внутреннюю переменную-член, чтобы указать, что поле календаря f было изменено. Хотя поле календаря F изменилось сразу, значение времени календаря в миллисекундах не пересчитывается до следующего вызова get (), getTime (), getTimeInMillis (), add () или roll () сделан. Таким образом, множественные вызовы set () не запускаются несколько ненужных вычислений. В результате смены календаря поле с помощью set (), другие поля календаря также могут меняться, в зависимости от поле календаря, значение поля календаря и система календаря. Кроме того, get (f) не обязательно вернет значение, установленное вызовом к методу set после пересчета полей календаря. особенности определяются конкретным календарным классом.

Поведение является неожиданным и не всегда происходит, но следующие модульные тесты должны иллюстрировать это поведение и всегда происходить.

/**
 * Fails the assertion due to missing getTime()
 * @throws ParseException 
 */
public class DateTest {

    @Test
    public void testNoGetTime() throws ParseException {

        DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
        Date testDate = df.parse("04/15/2013");
        Calendar testCal = Calendar.getInstance();
        testCal.setTime(testDate);
        Date expectedDate = df.parse("04/04/2013");
        Date actualDate = null;

        testCal.set(Calendar.DAY_OF_MONTH, testCal.getMinimum(Calendar.DAY_OF_MONTH));
        //testCal.getTime();
        testCal.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
        testCal.add(Calendar.DAY_OF_MONTH, -1);
        actualDate = testCal.getTime();
        assertEquals("Dates should be equal", expectedDate.toString(), actualDate.toString());
    }

    @Test
    public void testWithGetTime() throws ParseException {

        DateFormat df = new SimpleDateFormat("MM/dd/yyyy");
        Date testDate = df.parse("04/15/2013");
        Calendar testCal = Calendar.getInstance();
        testCal.setTime(testDate);
        Date expectedDate = df.parse("04/04/2013");
        Date actualDate = null;

        testCal.set(Calendar.DAY_OF_MONTH, testCal.getMinimum(Calendar.DAY_OF_MONTH));
        testCal.getTime();
        testCal.set(Calendar.DAY_OF_WEEK, Calendar.FRIDAY);
        testCal.add(Calendar.DAY_OF_MONTH, -1);
        actualDate = testCal.getTime();
        assertEquals("Dates should be equal", expectedDate.toString(), actualDate.toString());
    }
}
2 голосов
/ 11 ноября 2016

@ skaffman Ответ - НЕ ПРАВИЛЬНО .

Вот пример, который подтверждает то, что я говорю.

//Create an Calendar object set to todays date & time
Calendar calendar = Calendar.getInstance();
Log.d(Tag, "Now : "+ calendar.toString());

//Set the Calendar to the first day of Month
calendar.set(Calendar.DAY_OF_MONTH,1);
Log.d(Tag, "Calendar.DAY_OF_MONTH,1: "+ calendar.toString());

Это вывод Log.d:

Now : java.util.GregorianCalendar[time=1478834995641,areFieldsSet=true,lenient=true,zone=America/Chicago,firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2016,MONTH=10,WEEK_OF_YEAR=46,WEEK_OF_MONTH=2,DAY_OF_MONTH=10,DAY_OF_YEAR=315,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR=9,HOUR_OF_DAY=21,MINUTE=29,SECOND=55,MILLISECOND=641,ZONE_OFFSET=-21600000,DST_OFFSET=0] Calendar.DAY_OF_MONTH,1: 
Calendar.DAY_OF_MONTH,1: java.util.GregorianCalendar[time=?,areFieldsSet=false,lenient=true,zone=America/Chicago,firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2016,MONTH=10,WEEK_OF_YEAR=46,WEEK_OF_MONTH=2,DAY_OF_MONTH=1,DAY_OF_YEAR=315,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR=9,HOUR_OF_DAY=21,MINUTE=29,SECOND=55,MILLISECOND=641,ZONE_OFFSET=-21600000,DST_OFFSET=0]

Если вы потратите время, чтобы проверить это: Календарь в начале показывает:

time=1478834995641
DAY_OF_MONTH=10  
DAY_OF_YEAR=315

Однако, если вы установите его на первый день месяца:

time=?
DAY_OF_MONTH=1  
DAY_OF_YEAR=315

Да, первый день месяца изменился так, как мы хотели, но некоторые атрибуты остались прежними. Например, как это получается, мы устанавливаем календарь на DAY_OF_MONTH=1, но мы все еще находимся в DAY_OF_YEAR=315.

Если мы используем любую из следующих функций, это заставит Календарь обновляться.

Вызов get, getTimeInMillis, getTime, add and roll.

Из класса календаря в Javadocs Проверьте: Получение и установка значений полей календаря

Чтобы исправить это, мы добавляем следующий код calendar.getTimeInMillis();, который заставляет Календарь обновлять свои атрибуты.

//Create an Calendar object set to todays date & time
Calendar calendar = Calendar.getInstance();
Log.d(Tag, "Now : "+ calendar.toString());

//Set the Calendar to the first day of Month
calendar.set(Calendar.DAY_OF_MONTH,1);
//UPDATE BY CALLING getTimeInMillis() or any of the previously mentioned functions
calendar.getTimeInMillis();
Log.d(Tag, "Calendar.DAY_OF_MONTH,1: "+ calendar.toString());

Теперь давайте проверим результаты:

Now : java.util.GregorianCalendar[time=1478836452183,areFieldsSet=true,lenient=true,zone=America/Chicago,firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2016,MONTH=10,WEEK_OF_YEAR=46,WEEK_OF_MONTH=2,DAY_OF_MONTH=10,DAY_OF_YEAR=315,DAY_OF_WEEK=5,DAY_OF_WEEK_IN_MONTH=2,AM_PM=1,HOUR=9,HOUR_OF_DAY=21,MINUTE=54,SECOND=12,MILLISECOND=183,ZONE_OFFSET=-21600000,DST_OFFSET=0]
Calendar.DAY_OF_MONTH,1: java.util.GregorianCalendar[time=1478055252183,areFieldsSet=true,lenient=true,zone=America/Chicago,firstDayOfWeek=1,minimalDaysInFirstWeek=1,ERA=1,YEAR=2016,MONTH=10,WEEK_OF_YEAR=45,WEEK_OF_MONTH=1,DAY_OF_MONTH=1,DAY_OF_YEAR=306,DAY_OF_WEEK=3,DAY_OF_WEEK_IN_MONTH=1,AM_PM=1,HOUR=9,HOUR_OF_DAY=21,MINUTE=54,SECOND=12,MILLISECOND=183,ZONE_OFFSET=-21600000,DST_OFFSET=3600000]

Следовательно, @skaffman Ответ неправильный, поскольку для вашего вопроса Calendar.getTime(); действительно необходим, если вы не хотите получать странные значения в какой-то момент.

2 голосов
/ 10 сентября 2009

Возможно, вы нажали ID ошибки 4851640

Вызов get (...) / getTime () для экземпляра Calendar делает isSet (...) бесполезным!

0 голосов
/ 10 сентября 2009

Нет, в этом не должно быть необходимости.

Был ли календарь сериализован сразу после этого?

Я поймал ошибку с сериализацией Календаря в более старых jvms.

Ошибка парада ошибок # 4328747

Вызов getTime перед сериализацией может быть достаточным, чтобы обойти ошибку, хотя у меня не установлена ​​достаточно старая JVM, чтобы подтвердить это.

0 голосов
/ 10 сентября 2009

Нет, это не так.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...