Java: почему Calendral.setTimeInMillis (0) устанавливает неправильное время - PullRequest
0 голосов
/ 20 марта 2020
Приложение

My Android (в java, в Android Studio) использует класс `Calendar '. После

Calendar cal=Calendar.getInstance();
cal.setTimeInMillis(0);
Log.i("Interim",cal.getTime().toString());

выдается такой вывод: I/Interim: Thu Jan 01 03:00:00 GMT+02:00 1970. Мой часовой пояс GMT + 02: 00 (Киев, Украина), DST в январе не применяется. Почему календарное время установлено на 03:00? Я ожидаю 00:00 (без учета часового пояса) или 02:00 (с учетом часового пояса), но почему 03:00?

Заранее спасибо за любую идею

PS Чтобы прояснить обстоятельства, Я установил Calendar часовой пояс на GMT и получил значение часа:

Calendar cal=Calendar.getInstance(TimeZone.getTimeZone("GMT"));
cal.setTimeInMillis(0);
Log.i("Interim hours",Integer.toString(cal[i].get(Calendar.HOUR)));
Log.i("Interim",cal.getTime().toString());

В отличие от ожидаемого, вывод:

I / Промежуточные часы: 0

I / Interim: Чт 01 января 03:00:00 GMT + 02: 00 1970

Итак, значение поля часа равно 0, а время - 03:00. Я только что услышал о 1-часовой смене в 13.06.1975 (см. Ответ ниже), но, похоже, это касается только Вьетнама, не так ли?

Ответы [ 2 ]

2 голосов
/ 20 марта 2020

Пожалуйста, сделайте различие между часовым поясом и смещением . Ваш часовой пояс - Европа / Киев (на английском языке используется написание названий мест в идентификаторах часовых поясов, если существует написание на английском языке sh). Европа / Киев находится в смещении +02: 00 здесь в январе. Это было по смещению +03: 00 до 27 октября и будет снова с 29 марта из-за летнего времени (летнее время, летнее время). И что может удивить некоторых, это было по смещению +03: 00 постоянно с 1944 по 1980 год. Так что в эпоху - 1 января 1970 года 00:00 UT C - время в Украине было 3 часа. Так что для Украины эта часть вашего вывода верна.

Короче говоря: часовой пояс охватывает историю c, настоящие и известные будущие смещения от UTC / GMT, используемые в этом часовом поясе. GMT + 02: 00 - это смещение, а не часовой пояс.

java .time и ThreeTenABP

Вот современный способ получения того, что я думаю, что вы после:

    ZonedDateTime epochInUkraine = Instant.EPOCH.atZone(ZoneId.of("Europe/Kiev"));
    System.out.println(epochInUkraine);

Выходные данные из этих строк:

1970-01-01T03: 00 + 03: 00 [Европа / Киев]

Если вам нужна распечатка, похожая на ту, что вы получили при печати старомодного java.util.Date объекта:

    DateTimeFormatter formatter = DateTimeFormatter.ofPattern(
            "EEE MMM dd HH:mm:ss zzz yyyy", Locale.ROOT);
    System.out.println(epochInUkraine.format(formatter));

Чт 01 января 03:00:00 EET 1970

Возможно, вы можете найти выходной формат, который еще лучше подходит вашей аудитории. Я оставляю эту часть себе.

Что пошло не так?

Почему Calendar.setTimeInMillis(0) устанавливает неправильное время?

Это не так. Класс Calendar и его подклассы плохо разработаны и давно устарели, но setTimeInMillis(0) устанавливает правильное время. Вы также уже заметили, что, когда ваш Calendar находится в UT C, его часы утром или днем ​​(0 по 11) равны 0. Как вы получили выходные данные 03:00:00 GMT+02:00 с противоречием между 03:00 и +02: 00? Возможные объяснения включают:

  • Скорее всего, ошибка на вашей стороне. Либо это не из-за Calendar, который вы установили в 0, либо из-за того, что вы неверно скопировали вывод при вводе вопроса. Если вы еще раз проверите, можете ли вы воспроизвести этот вывод, мне было бы любопытно услышать.
  • Менее вероятно, ошибка в Date.toString(), которая вызывается неявно, когда вы печатаете Date, который вы получаете от cal.getTime().
  • Еще менее вероятно, ошибка в Calendar.getTime(), которая дает вам неправильный Date объект из Calendar.

Вопрос: Не java .time требуют Android API-уровень 26?

java .time прекрасно работает как на старых, так и на новых Android устройствах. Для этого требуется как минимум Java 6 .

  • В Java 8 и более поздних версиях, а также на более новых Android устройствах (от уровня API 26) современный встроенный API -in.
  • В не- Android Java 6 и 7 получите ThreeTen Backport, бэкпорт современных классов (ThreeTen для JSR 310; см. ссылки внизу).
  • Вкл. (Старше) Android используйте версию Android ThreeTen Backport. Это называется ThreeTenABP. И убедитесь, что вы импортируете дату и время классов из org.threeten.bp с подпакетами.

Ссылки

0 голосов
/ 20 марта 2020

Если ваш ввод до 13/06/1975, результат всегда +1 час. В этот день 25 часов. Вы можете проверить это https://currentmillis.com/. Если ввести 13.06.1975, мы получили 171824400000, а 12.06.1975 мы получили 171734400000.

171824400000 - 171734400000 = 90000000.

90000000 / (60 * 60 * 1000) = 25 ( ???)

Так что я думаю, что вы можете добавить 1 час, если ваш вклад до 13/06/1975

...