Почему час добавляется в java.util.Date для дат до 1 ноября 1971 года? - PullRequest
18 голосов
/ 06 августа 2009

Следующий код демонстрирует ошибку в java.util.Date, из-за которой добавляется час, если местное время установлено на GMT с настройкой DST, а время до 1 ноября 1971 года. Мое первое предположение всегда таково Я неправильно понял. Кто-нибудь может увидеть, что не так (или это действительно ошибка Java)? Что значительного в 1 ноября 1971 года?

import java.text.SimpleDateFormat;
import java.util.Locale;
import java.util.TimeZone;

class JavaUtilDateBug
{
    private static void demo() throws Exception
    {
        // UK developers usually have the clock on their development machines set
        // to "Europe/London" (i.e. GMT with daylight saving). Set it explicitly 
        // here so readers in other countries can see the problem too.
        TimeZone.setDefault(TimeZone.getTimeZone("Europe/London"));
        Locale.setDefault(Locale.ENGLISH);

        SimpleDateFormat dateFormat = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
        String strJan1st1970Expected = "Thu Jan 01 00:00:00 GMT 1970";
        String strJan1st1970Actual = dateFormat.parse(strJan1st1970Expected).toString();
        System.out.println("strJan1st1970Actual: " + strJan1st1970Actual); // -> "Thu Jan 01 01:00:00 GMT 1970"
        boolean jvmHasDateBug = !strJan1st1970Expected.equals(strJan1st1970Actual);
        System.out.println("jvmHasDateBug: " + jvmHasDateBug); // -> true

        // The anomaly only seems to affect times before 1 Nov 1971.
        final String strNov1st1971 = "Mon Nov 01 00:00:00 GMT 1971";
        assert strNov1st1971.equals(dateFormat.parse(strNov1st1971).toString());
    }

    public static void main(String[] args)
    {
        try
        {
            demo();
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
    }
}

Моя среда Java:

  java version "1.6.0_13"
  Java(TM) SE Runtime Environment (build 1.6.0_13-b03)
  Java HotSpot(TM) Client VM (build 11.3-b02, mixed mode, sharing)

Ответы [ 4 ]

21 голосов
/ 06 августа 2009

Между 27 октября 1968 года и 31 октября 1971 года было проведено судебное разбирательство по Британскому стандартному времени, которое, как я подозреваю, является причиной этой проблемы.

Здесь есть некоторые подробности процесса:

http://en.wikipedia.org/wiki/British_Summer_Time#Single.2FDouble_Summer_Time

Часовой пояс для Европы / Лондона 1 января 1970 года был британским стандартным временем (GMT + 1), поэтому, когда вы используете java.text.SimpleDateFormat для анализа 01 января 00:00:00 по Гринвичу 1970, он генерирует правильное значение эпохи, равное ян 01 01:00:00 1970 в BST.

Затем, из-за дерьма java.util.Date, когда вы звоните java.util.Date.toString(), он использует часовой пояс по умолчанию для текущего локального с сейчас , который изменился на GMT, и вы получите Jan 01 01 : 00: 00 GMT 1970.

13 голосов
/ 06 августа 2009

Это локаль. От http://en.wikipedia.org/wiki/British_Summer_Time

Схема британского стандартного времени была опробована в период с 27 октября 1968 г. по 31 октября 1971 г., когда Британия оставалась на GMT + 1 в течение всего года.

5 голосов
/ 06 августа 2009

Я обнаружил совпадающую ошибку в базе данных ошибок Sun. Похоже, они считают это «исторической неточностью» (форматирование, очевидно, должно выдавать «BST» как часовой пояс, а не «GMT» - тогда час будет правильным) и не исправит это, потому что в глубине реализация TimeZone не может обрабатывать места переключение названия своего часового пояса.

В качестве обходного пути вы можете явно установить часовой пояс в GMT, а не в «Европа / Лондон». Затем проблема исчезает.

0 голосов
/ 28 июня 2013

Это не ошибка.

Вы установили часовой пояс по умолчанию на BST, который равен (GMT + 1), GMT дата Jan 1 1970 00:00:00, когда вы анализируете эту дату, используя часовой пояс BST по умолчанию, он всегда отображает время на основе текущий часовой пояс (авто применяет смещение от GMT).

В данном случае это был GMT + 1, поэтому ваш результат был на час оторван.

...