Получать миллисекунды до полуночи
Я создаю виджет Android, который я хочу обновлять каждую ночь в полночь. Я использую AlarmManager , и мне нужно выяснить, сколько миллисекунд осталось от текущего времени до полуночи. Здесь мой код:
AlarmManager mAlarmManager = (AlarmManager)context.getSystemService(android.content.Context.ALARM_SERVICE); mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, millisecondsUntilMidnight, mSrvcPendingingIntent);
Как рассчитать, сколько миллисекунд осталось до полуночи?
ОТВЕТЫ
Ответ 1
Используйте Календар для его вычисления:
Calendar c = Calendar.getInstance(); c.add(Calendar.DAY_OF_MONTH, 1); c.set(Calendar.HOUR_OF_DAY, 0); c.set(Calendar.MINUTE, 0); c.set(Calendar.SECOND, 0); c.set(Calendar.MILLISECOND, 0); long howMany = (c.getTimeInMillis()-System.currentTimeMillis());
Ответ 2
TL;DR
Duration.between( now , tomorrowStart ) .toMillis()
java.time
Java 8 и более поздние версии поставляются с java.time framework. Эти новые классы заменяют старые классы времени (java.util.Date/.Calendar) в комплекте с Java. Также вытесняет Joda-Time, разработанный теми же людьми. Большая часть функциональности java.time портирована на Java 6 и 7 и далее адаптирована к Android (см. Ниже).
Часовой пояс имеет решающее значение для определения даты. В любой данный момент дата изменяется по всему миру по зонам. Например, через несколько минут после полуночи в Париж Франция — это новый день, пока еще «вчера» в Монреаль Квебек.
Укажите имя часового пояса в формате continent/region , например America/Montreal , Africa/Casablanca или Pacific/Auckland . Никогда не используйте аббревиатуру 3-4 буквы, например EST или IST , поскольку они не являются настоящими часовыми поясами, а не стандартизированы и даже не уникальны (!).
ZoneId z = ZoneId.of( "America/Montreal" ); ZonedDateTime now = ZonedDateTime.now( z );
Мы хотим получить число миллисекунд, которое будет работать, но не включая первый момент следующего дня.
Мы должны пройти класс LocalDate , чтобы попасть в первый момент дня. Итак, здесь мы начинаем с ZonedDateTime , чтобы получить LocalDate , а затем получим еще один ZonedDateTime . Ключ вызывает atStartOfDay на LocalDate .
LocalDate tomorrow = now.toLocalDate().plusDays(1); ZonedDateTime tomorrowStart = tomorrow.atStartOfDay( z );
Обратите внимание, что мы не жестко кодируем время в 00:00:00. Из-за аномалий, таких как летнее время (DST), день может начинаться в другое время, например, 01:00:00. Пусть java.time определяет первый момент.
Теперь мы можем рассчитать прошедшее время. В java.time мы используем класс Duration . Рамка java.time имеет более тонкое разрешение наносекунд, а не более грубые миллисекунды, используемые как java.util.Date, так и Joda-Time. Но Duration включает удобный getMillis метод, как запросил Вопрос.
Duration duration = Duration.between( now , tomorrowStart ); long millisecondsUntilTomorrow = duration.toMillis();
now.toString(): 2017-05-02T12: 13: 59.379-04: 00 [Америка/Монреаль]
tomorrowStart.toString(): 2017-05-03T00: 00-04: 00 [Америка/Монреаль]
millisecondsUntilTomorrow: 42360621
О java.time
Структура java.time встроена в Java 8 и более поздних версий. Эти классы вытесняют неприятные старые legacy классы времени, такие как java.util.Date , Calendar и SimpleDateFormat .
Проект Joda-Time, теперь режим обслуживания, советуем перейти к классам java.time.
Чтобы узнать больше, см. Учебник Oracle. И поиск Qaru для многих примеров и объяснений. Спецификация JSR 310.
Где получить классы java.time?
- Java SE 8, Java SE 9, а затем
- Встроенный.
- Часть стандартного Java API с объединенной реализацией.
- Java 9 добавляет некоторые незначительные функции и исправления.
- Большая часть функциональных возможностей java.time обратно переносится на Java 6 и 7 в ThreeTen-Backport.
- Проект ThreeTenABP адаптирует ThreeTen-Backport (упомянутый выше) специально для Android.
- См. Как использовать ThreeTenABP. .
Joda времени
ОБНОВЛЕНИЕ: Joda-Timeтеперь проект находится в режиме обслуживания, при этом команда советует перейти на java.time. Я оставляю этот раздел неповрежденным для истории, но рекомендую использовать java.time и ThreeTenABP, как описано выше.
В Android вы должны использовать Joda-Time библиотеку, а не печально известные классы Java.util.Date/.Calendar.
Joda-Time предлагает команду миллисекунды дня. Но нам это действительно не нужно.
Вместо этого нам нужен объект Duration , чтобы отображать промежуток времени до первого момента следующего дня.
Часовой пояс здесь имеет решающее значение, чтобы определить, когда начинается «завтра». Обычно лучше указывать, чем полагаться неявно на текущий часовой пояс JVM, который может меняться в любой момент. Если вы действительно хотите использовать JVM по умолчанию, попросите это явно с вызовом DateTimeZone.getDefault , чтобы сделать ваш код самодокументированным.
DateTime now = DateTime.now( DateTimeZone.forID( "America/Montreal" ) ); long milliSecondsUntilTomorrow = new Duration( now , now.plusDays( 1 ).withTimeAtStartOfDay() ).getMillis();
DateTimeZone zone = DateTimeZone.forID( "America/Montreal" ); // Or, DateTimeZone.getDefault() DateTime now = DateTime.now( zone ); DateTime tomorrow = now.plusDays( 1 ).withTimeAtStartOfDay(); // FYI the day does not *always* start at 00:00:00.0 time. Duration untilTomorrow = new Duration( now , tomorrow ); long millisecondsUntilTomorrow = untilTomorrow.getMillis();
System.out.println( "From now : " + now + " until tomorrow : " + tomorrow + " is " + millisecondsUntilTomorrow + " ms." );
Отныне: 2015-09-20T19: 45: 43.432-04: 00 до завтра: 2015-09-21T00: 00: 00.000-04: 00 — 15256568 мс.
Ответ 3
Calendar c = Calendar.getInstance(); long now = c.getTimeInMillis(); c.add(Calendar.DATE, 1); c.set(Calendar.HOUR_OF_DAY, 0); c.set(Calendar.MINUTE, 0); c.set(Calendar.SECOND, 0); c.set(Calendar.MILLISECOND, 0); long millisecondsUntilMidnight = c.getTimeInMillis() - now; AlarmManager mAlarmManager = (AlarmManager)context.getSystemService(android.content.Context.ALARM_SERVICE); mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, millisecondsUntilMidnight, mSrvcPendingingIntent);
Ответ 4
long MILLIS_IN_DAY = 86400000; long currentTime = System.currentTimeInMillis(); long millisTillNow = currentTime % MILLIS_IN_DAY; long millisecondsUntilMidnight = MILLIS_IN_DAY - millisTillNow;
Ответ 5
Вы можете использовать AlarmManager.RTC вместо AlarmManager.ELAPSED_REALTIME и просто установить календарь на нужное вам время:
// Create a calendar for midnight Calendar todayMidnight = Calendar.getInstance(); todayMidnight.add(Calendar.DATE, 1); todayMidnight.set(Calendar.HOUR_OF_DAY, 0); todayMidnight.set(Calendar.MINUTE, 0); todayMidnight.set(Calendar.SECOND, 0); // Create an alarm going off at midnight mAlarmManager.set( AlarmManager.RTC, todayMidnight.getTimeInMillis(), mSrvcPendingingIntent );
Ответ 6
Используя следующий способ, вам не нужно беспокоиться о настройке DAY_OF_MONTH.
long msInDay = 86400000; Calendar c = Calendar.getInstance(); c.set(Calendar.HOUR_OF_DAY, 0); c.set(Calendar.MINUTE, 0); c.set(Calendar.SECOND, 0); c.set(Calendar.MILLISECOND, 0); System.out.print(msInDay - (System.currentTimeMillis() - c.getTimeInMillis()));
Расчет секунд до полуночи определенного часового пояса
Я пытаюсь написать код, который вычисляет, сколько времени в секундах осталось до полуночи в определенном часовом поясе.
Часовой пояс, на который я нацеливаюсь, — EDT, это «GMT-04:00».
Я обнаружил, что многие темы охватывают расчет времени, но ни одна из них не помогла мне понять, как вычислить секунды, оставшиеся до полуночи в определенном часовом поясе.
Может кто-то указать мне верное направление?
2 ответа
Я полагаю, что это логика, которую вы ищете? (Не смотрите на вопрос, только первый ответ, ссылаясь на календарь, локали и часовые пояса)
Используя Календарь и часовые пояса, чтобы вычислить точное время, затем просто используйте этот объект календаря, чтобы найти разницу между другим установленным объектом календаря в полночь:)
long разность InMillis = midnightCalendarObject.getTimeInMillis () — calendarObject.getTimeInMillis ();
long secondsUntilMidnight = TimeUnit.toSeconds (diffInMillis);
java.time
ZoneId zone = ZoneId.of("America/New_York"); ZonedDateTime now = ZonedDateTime.now(zone); ZonedDateTime midnight = now.toLocalDate().plusDays(1).atStartOfDay(zone); long secondsLeftTillMidnight = Duration.between(now, midnight).getSeconds(); System.out.println("Seconds till midnight: " + secondsLeftTillMidnight + ". Time now: " + now + '.');
Секунды до полуночи: 34801. Время: 2018-10-01T14:19:58.651572-04:00[Америка / Нью-Йорк].
Вопрос: Могу ли я использовать java.time на андроид?
Да, java.time прекрасно работает на устройствах Android. Это просто требует как минимум Java 6.
- В Java 8 и более поздних версиях, а также на новых устройствах Android (от 26 уровня API, как мне говорят) новый API поставляется встроенным.
- В Java 6 и 7 получают ThreeTen Backport, бэкпорт новых классов (ThreeTen для JSR 310, где впервые был описан современный API).
- На (более старой) версии Android используйте версию Android ThreeTen Backport. Это называется ThreeTenABP. Убедитесь, что вы импортируете классы даты и времени из пакета org.threeten.bp и подпакеты.
связи
- Учебник Oracle: Дата и время, объясняя, как использовать java.time ,
- Проект ThreeTen Backport
- ThreeTenABP, Android-версия ThreeTen Backport
- Вопрос: Как использовать ThreeTenABP в Android Project, с очень подробным объяснением.
- Запрос спецификации Java (JSR) 310.