2015-04-25 3 views
0

Я довольно новичок в Java, и я пытаюсь выяснить странность с GregorianCalendar. Кажется, что год быть установлен неправильноGregorianCalendar year неверно задан

Я сделал следующую функцию тест, чтобы проиллюстрировать эту проблему (иногда.):

public static void testTime(Calendar c) { 
    SimpleDateFormat sdf = 
     new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");  
    sdf.setTimeZone(TimeZone.getTimeZone("GMT+0")); 

    System.out.println("---------------------------------"); 
    c.setTimeInMillis(0); 
    Date d = c.getTime(); 
    System.out.println("Time 0: " + sdf.format(d) + 
     " (" + d.getTime() + ")"); 

    c.set(Calendar.YEAR, 2000); 
    d = c.getTime(); 
    System.out.println("Year 2000: " + sdf.format(d) + 
     " (" + d.getTime() + ")"); 
    System.out.println("---------------------------------"); 
} 

Эта функция принимает объект Calendar, и производит вывод, который должен выглядеть например:

--------------------------------- 
Time 0: 1970/01/01 00:00:00 (0) 
Year 2000: 2000/01/01 00:00:00 (946684800000) 
--------------------------------- 

Я вызываю функцию 3 раза, от основной; Код назвать это выглядит следующим образом:

Calendar c = GregorianCalendar.getInstance(); 
    testTime(c); 

    c.setTimeZone(TimeZone.getTimeZone("GMT+0")); 
    testTime(c); 

    c.setTimeZone(TimeZone.getTimeZone("America/Phoenix")); 
    testTime(c); 

И, наконец, вот выход:

--------------------------------- 
Time 0: 1970/01/01 00:00:00 (0) 
Year 2000: 2001/01/01 00:00:00 (978307200000) 
--------------------------------- 
--------------------------------- 
Time 0: 1970/01/01 00:00:00 (0) 
Year 2000: 2000/01/01 00:00:00 (946684800000) 
--------------------------------- 
--------------------------------- 
Time 0: 1970/01/01 00:00:00 (0) 
Year 2000: 2001/01/01 00:00:00 (978307200000) 
--------------------------------- 

Как вы можете видеть, когда я вызвать функцию, используя GregorianCalendar полученный из GetInstance(), или тот, у которого был установлен часовой пояс «Америка/Феникс» (мой местный часовой пояс), год выпускается как 2001. Когда я устанавливаю часовой пояс в GMT, год (правильно я считаю) выводит на .

Может кто-нибудь, пожалуйста, объясните мне, что мне не хватает? Я хотел бы использовать календарь, просто создав его, установив некоторые поля, используя некоторые переменные, которые у меня есть, и создаю дату. Тем не менее, мне нужно убедиться, что дата, которую я возвращаю, точно отражает то, что я настраиваю; Я немного сходил с ума от своих модульных тестов, пока не понял, что получаю даты, которые просто не совпадают с годом, в который я входил, поэтому я сделал вышеприведенный код для тестирования.

Редактировать: Чтобы быть ясным, меня не касается небольшого смещения из-за часового пояса. Это я могу понять и объяснить. Разница во времени +24 часа из-за часового пояса - это одно; Разница во времени года (2001 вместо 2000) - совсем другая.

Если это имеет значение, эта Java работает на 64-битной машине Linux; Команда java -showversion возвращает:

java version "1.8.0_40" 
Java(TM) SE Runtime Environment (build 1.8.0_40-b26) 
Java HotSpot(TM) 64-Bit Server VM (build 25.40-b25, mixed mode) 

Заранее благодарим за любую помощь. Я искал доски здесь и в Интернете, насколько могу, и не могу найти ничего, что близко к моей проблеме.

ответ

0

Проблема возникает, когда вы пытаетесь переназначить новое значение новым YEAR на объект Date. Этот код:

c.setTimeInMillis(0); 
     Date d = c.getTime(); 
     System.out.println("Time 0: " + sdf.format(d) + 
      " (" + d.getTime() + ")"); 

не работает. Но этот:

c.setTimeInMillis(0); 
     System.out.println("Time 0: " + sdf.format(c.getTime()) + 
      " (" + c.getTime() + ")"); 

работает для меня для случая «без часовой пояс».

Для случая Америка/Phoenix, эта линия была проблема:

c.setTimeInMillis(0); 

но вы можете заменить его

c = GregorianCalendar.getInstance(); 
c.setTimeInMillis(0); 

и он будет работать.

+0

Вещь, я получаю правильный год (2000), когда я указываю GMT + 0 (или GMT + 0000), но неверно, когда я не указываю никого или Америку/Феникс. Согласно документам на TimeZone, верно указать GMT + 0 в качестве часового пояса, поэтому я не думаю, что это проблема, и для getDefaultInstance() для календаря предполагается построить его со стандартным часовым поясом, а не с ним. Спасибо за ответ, но мне придется продолжать копать, я думаю, чтобы выяснить, что происходит. –

+0

Извините, я неправильно понял это. Вы правы GMT + 0 дает правильный результат. Я отредактирую свой ответ. –

1

Хорошо, я понял, что происходит.

Когда я установил год, он действительно установил год к 2000 году. Затем он обновляет остальные внутренние поля, используя часовой пояс, который у него есть.

Это означает, что когда я устанавливаю год 2000, он устанавливает это поле и вычисляет время (включая часовой пояс). Предыдущее время было 1 января 00:00:00 1970 года. Оно обновляет год до 2000, перемещает время назад 7 часов (мое смещение), которое дает время 31 декабря 17:00 MST. Год должен действительно вернуться к 1999 году, но он выходит из года в 2000 году, так как это я и установил. Таким образом, итоговая дата - 31 декабря 17:00 2000.

Когда я печатаю дату, я устанавливаю часовой пояс моего SimpleDateFormat равным GMT. Поэтому он перемещает время вперед 7 часов, до 1 января 2001 года 00:00:00.

Это действительно запутывает, но повторные тесты показывают, что это действительно так. Удивительно, но факт. Урок здесь (для меня) заключается в том, что я должен установить часовой пояс выходного объекта в соответствии с часовым поясом календаря. Затем будут показаны даты, соответствующие тому, что я вводил.

Смежные вопросы