Почему значение календаря отличается? - PullRequest
0 голосов
/ 20 февраля 2019

Мне нужно посчитать количество раз в зависимости от года, месяца, дня, часа, минуты (секунда унифицирована до нуля, секунда мне не нужна)

Я выбрал HashMap в качестве структуры данных.

HashMap<Calendar,Integer> arr_time; 

Если уже есть такое же время (год, месяц, день, час, минута), я хочу увеличить целое число или добавить новое время (год, месяц, день, час, минута).).

Calendar calendar = Calendar.getInstance();
calendar.set(mYear,mMonth,mDay,mHour,mMinute,0);
if(arr_time.containsKey(calendar)){
  // increase Integer value
  // ++1;
}else{
  // add new time 
  // arr_time.put(calendar,1);
}

Я думал, что он распознал бы тот же календарь, если бы год, месяц, день, час и минуты были одинаковыми.Но это не так.

В чем проблема?

Я не использовал «Дата».Это потому, что Android Devloper сказал так.

Дата (int год, int месяц, int дата, int hrs, int min, int sec) Этот конструктор устарел на уровне API 1. Начиная с JDKверсия 1.1, заменена Calendar.set (год + 1900, месяц, дата, часы, минуты, секунды) или GregorianCalendar (год + 1900, месяц, дата, часы, минуты, секунды).

Ответы [ 2 ]

0 голосов
/ 20 февраля 2019

java.time

    Map<LocalDateTime, Integer> arr_time = new HashMap<>();
    ZoneId zone = ZoneId.of("Antarctica/Vostok");

    for (int i = 0; i < 10; i++) {
        LocalDateTime now = LocalDateTime.now(zone).truncatedTo(ChronoUnit.MINUTES);
        arr_time.compute(now, (ldt, oldCount) -> oldCount == null ? Integer.valueOf(1) : oldCount + 1);

        TimeUnit.MILLISECONDS.sleep(103);
    }
    System.out.println(arr_time);

Когда я только что запустил код, я получил:

{2019-02-20T13: 42 = 10}

Я записал 10 раз, поспал между ними, чтобы убедиться, что они не совпадают.Но поскольку я урезал каждую до целых минут, все они оказались 2019-02-20T13:42 и были посчитаны вместе.

Чтобы создать LocalDateTime из int переменных:

    int mYear = 2019;
    int mMonth = Calendar.JANUARY;
    int mDay = 31;
    int mHour = 23;
    int mMinute = 45;
    LocalDateTime ldt = LocalDateTime.of(mYear, mMonth + 1, mDay, mHour, mMinute);
    System.out.println(ldt);

2019-01-31T23: 45

Поскольку вы использовали mMonth с Calendar, я предположил, что это 0.LocalDateTime числа месяцев от 1, как и у людей, поэтому мне нужно было добавить 1.

Что пошло не так в вашем коде?

calendar.set(mYear,mMonth,mDay,mHour,mMinute,0) устанавливает год, месяц, день, час, минута и секунда , но не устанавливает миллисекунды .Поскольку каждый объект Calendar создается с текущим временем, миллисекунды чаще всего будут отличаться, поэтому, даже если вы установите одинаковые значения, объекты Calendar все равно не равны.

Такое поведениеметод 6-arg set удивляет многих и является лишь второстепенной точкой среди множества точек, где класс плохо спроектирован.Вы не должны использовать это.У нас есть java.time с 2014 года, поэтому на самом деле нет причин для этого.

Вопрос: Могу ли я использовать java.time на Android?

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

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

Ссылки

0 голосов
/ 20 февраля 2019

Никогда не используйте Calendar

Ужасный класс Calendar был вытеснен java.time классами лет назад, в частности ZonedDateTime.

Часовой пояс

Вы игнорируете важнейшую проблему часового пояса.Дата и время суток не имеют реального значения, пока вы не укажете контекст часового пояса (или смещение от UTC).Например, полдень Europe/Paris намного позже, чем полдень в Asia/Tokyo и намного раньше, чем полдень в America/Montreal.

ZonedDateTime

Представляет дату и время суток с часовым поясом с классом ZonedDateTime.

ZoneID

Укажите собственное имя часового пояса в формате Continent/Region, например America/Montreal, Africa/Casablanca или Pacific/Auckland.Никогда не используйте 2-4 буквенные сокращения, такие как EST или IST, так как они не истинные часовые пояса, не стандартизированы и даже не уникальны (!).

ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdt = ZonedDateTime.now( z ) ;

truncatedTo

Если вы хотите установить вторую и дробную секунды как ноль, усечь до минуты.

ZonedDateTime zdt = ZonedDateTime.now( z ).truncatedTo( ChronoUnit.MINUTES ) ;  // Set the whole second and the fractional second both to zero.

LocalDateTime

Если для целей подсчета вы хотите учитывать только дату с временем суток, игнорируя часовой пояс, извлеките LocalDateTime.LocalDateTime - это просто дата с указанием времени суток, в которой отсутствует понятие часового пояса или смещения от UTC.

LocalDateTime ldt = zdt.toLocalDateTime() ;

MapSortedMapTreeMap

С LocalDateTime в руке вы можете считать.Сделайте Map, где ключ - LocalDateTime, а значение - Integer.

Полагаю, вы позаботитесь о отсортированном порядке клавиш даты и времени, поэтому используйте SortedMap.A TreeMap является одной из таких реализаций.

SortedMap< LocalDateTime , Integer > map = new TreeMap() ;

Для каждого LocalDateTime получить объект Integer из Map.Увеличьте счетчик чисел и замените старый объект Integer новым.

Использование Map уже много сотен, если не тысяч, уже было использовано при переполнении стека.Так что ищите, если вам нужно больше обсуждений и примеров этого.


О java.time

java.time Фреймворк встроен в Java 8 и новее.Эти классы вытесняют проблемные старые устаревшие классы даты и времени, такие как java.util.Date, Calendar, & SimpleDateFormat.

Чтобы узнать больше, см. Oracle Tutorial .И поиск переполнения стека для многих примеров и объяснений.Спецификация: JSR 310 .

Проект Joda-Time , теперь в режиме обслуживания , рекомендует перейти на java.time классы.

Вы можете обмениваться java.time объектами напрямую с вашей базой данных.Используйте драйвер JDBC , совместимый с JDBC 4.2 или более поздней версии.Нет необходимости в строках, нет необходимости в java.sql.* классах.

Где получить классы java.time?

  • Java SE 8 , Java SE 9 , Java SE 10, Java SE 11 и более поздние версии - часть стандартного Java API с связанной реализацией.
    • Java 9 добавляет некоторые незначительные функции и исправления.
  • Java SE 6 и JavaSE 7
    • Большинство функций java.time перенесено в Java 6 & 7 в ThreeTen-Backport .
  • Android
    • Более поздние версии реализации связки Android java.time классы.
    • Для более ранних версий Android (<26) проект <a href="https://github.com/JakeWharton/ThreeTenABP" rel="nofollow noreferrer"> ThreeTenABP адаптируется ThreeTen-Backport (упомянуто выше).См. Как использовать ThreeTenABP… .
...