Obtenga milisegundos hasta la medianoche
Estoy creando un widget de Android que quiero actualizar cada noche a medianoche. Estoy usando un AlarmManager
y necesito saber cuántos milisegundos quedan de la hora actual hasta la medianoche. Aquí está mi código:
AlarmManager mAlarmManager = (AlarmManager)context.getSystemService(android.content.Context.ALARM_SERVICE); mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, millisecondsUntilMidnight, mSrvcPendingingIntent);
¿Cómo puedo calcular cuántos milisegundos quedan hasta la medianoche?
- ¿Cuál es la forma más segura de autorizar a un usuario en Android?
- Configuración de Proguard para Android Support v4 22.2.0
- Error de descifrado: Bloqueo de pad dañado
- Entero aleatorio: Android
- Descargar el archivo hace que la interfaz de usuario gague
Gracias de antemano.
- Un ligero retraso al hacer clic en un botón
- excepción java.lang.NoClassDefFoundError en algunos dispositivos
- Manteniendo una vista en la parte inferior con la biblioteca de SlidingUpPanel
- API de calendario de Android insertar evento recurrente
- El depurador de Android oculta una variable local
- Realizando operaciones de larga duración en onDestroy
- Android establece o restablece el código PIN de la tarjeta SIM mediante programación
- ¿Dónde detener / destruir subprocesos en la clase de servicio de Android?
Utilice un calendario para calcularlo:
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());
Tl dr
Duration.between( now , tomorrowStart ) .toMillis()
Java.time
Java 8 y versiones posteriores vienen con el marco java.time incorporado. Estas nuevas clases suplantan las viejas clases de fecha y hora (java.util.Date/.Calendar) incluidas en Java. También suplanta Joda-Time, desarrollado por la misma gente. Gran parte de la funcionalidad de java.time está retro-portada a Java 6 y 7, y adaptada además a Android (ver más abajo).
Una zona horaria es crucial para determinar una fecha. Para cualquier momento dado, la fecha varía alrededor del globo por la zona. Por ejemplo, unos pocos minutos después de la medianoche en París Francia es un nuevo día, mientras que todavía "ayer" en Montreal Quebec .
Especifique un nombre de zona horaria adecuado en el formato de continent/region
, como America/Montreal
, Africa/Casablanca
o Pacific/Auckland
. Nunca utilice la abreviatura de 3-4 letras como EST
o IST
ya que no son zonas horarias verdaderas, no están estandarizadas y ni siquiera son únicas (!).
ZoneId z = ZoneId.of( "America/Montreal" ); ZonedDateTime now = ZonedDateTime.now( z );
Queremos obtener el número de milisegundos en ejecución hasta, pero sin incluir, el primer momento del día siguiente.
Debemos pasar por la clase LocalDate
para llegar al primer momento de un día. Así que aquí empezamos con un ZonedDateTime
para obtener una LocalDate
, y después de eso obtener otro ZonedDateTime
. La clave está llamando atStartOfDay
en LocalDate
.
LocalDate tomorrow = now.toLocalDate().plusDays(1); ZonedDateTime tomorrowStart = tomorrow.atStartOfDay( z );
Tenga en cuenta que no codificamos una hora del día a las 00:00:00. Debido a anomalías como el horario de verano (DST), el día puede comenzar en otro momento, como 01:00:00. Deje que java.time determine el primer momento.
Ahora podemos calcular el tiempo transcurrido. En java.time usamos la clase Duration
. El marco java.time tiene una resolución más fina de nanosegundos en lugar de los milisegundos más gruesos utilizados por java.util.Date y Joda-Time. Pero Duration
incluye un práctico método getMillis
, como la Cuestión solicitada.
Duration duration = Duration.between( now , tomorrowStart ); long millisecondsUntilTomorrow = duration.toMillis();
Vea este código en directo en IdeOne.com .
Now.toString (): 2017-05-02T12: 13: 59.379-04: 00 [América / Montreal]
TomorrowStart.toString (): 2017-05-03T00: 00-04: 00 [América / Montreal]
MillisecondsUntilTomorrow: 42360621
Acerca de java.time
El framework java.time está integrado en Java 8 y posterior. Estas clases suplantan las viejas clases de fecha-hora heredadas , como java.util.Date
, Calendar
y SimpleDateFormat
.
El proyecto Joda-Time , ahora en modo de mantenimiento , recomienda la migración a las clases java.time .
Para obtener más información, consulte el Tutorial de Oracle . Y busca Stack Overflow para muchos ejemplos y explicaciones. La especificación es JSR 310 .
Dónde obtener las clases java.time?
- Java SE 8 , Java SE 9 y posterior
- Incorporado.
- Parte de la API Java estándar con una implementación integrada.
- Java 9 agrega algunas características y correcciones menores.
- Java SE 6 y Java SE 7
- Gran parte de la funcionalidad de java.time se retroporta a Java 6 & 7 en ThreeTen-Backport .
- Androide
- El proyecto ThreeTenABP adapta específicamente a ThreeTen-Backport (mencionado anteriormente) para Android.
- Consulte Cómo utilizar ThreeTenABP ….
Joda-Time
ACTUALIZACIÓN: El proyecto Joda-Time está ahora en modo de mantenimiento , con el equipo recomendando la migración a las clases java.time . Dejo esta sección intacta por el bien de la historia, pero recomiendo usar java.time y ThreeTenABP como se mencionó anteriormente.
En Android deberías usar la biblioteca Joda-Time en lugar de las clases Java.util.Date/.Calendar.
Joda-Time ofrece un comando de milisegundos de día . Pero en realidad no lo necesitamos aquí.
En su lugar sólo necesitamos un objeto de Duration
para representar el lapso de tiempo hasta el primer momento del día siguiente.
La zona horaria es crítica aquí para determinar cuándo comienza "mañana". Generalmente es mejor especificar que depender implícitamente de la zona horaria actual predeterminada de la JVM que puede cambiar en cualquier momento. O si realmente desea el valor predeterminado de la JVM, pídalo explícitamente con la llamada a DateTimeZone.getDefault
para que el código se auto-documente.
Podría ser un dos-línea.
DateTime now = DateTime.now( DateTimeZone.forID( "America/Montreal" ) ); long milliSecondsUntilTomorrow = new Duration( now , now.plusDays( 1 ).withTimeAtStartOfDay() ).getMillis();
Tomemos eso aparte.
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();
Descarga en la consola.
System.out.println( "From now : " + now + " until tomorrow : " + tomorrow + " is " + millisecondsUntilTomorrow + " ms." );
Cuando se ejecuta.
A partir de ahora: 2015-09-20T19: 45: 43.432-04: 00 hasta mañana: 2015-09-21T00: 00: 00.000-04: 00 es 15256568 ms.
Pruebe lo siguiente:
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);
¿Funcionaría esto?
long MILLIS_IN_DAY = 86400000; long currentTime = System.currentTimeInMillis(); long millisTillNow = currentTime % MILLIS_IN_DAY; long millisecondsUntilMidnight = MILLIS_IN_DAY - millisTillNow;
Puede utilizar AlarmManager.RTC
lugar de AlarmManager.ELAPSED_REALTIME
, y simplemente establecer un calendario a la hora que desee:
// 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 );
Usando la siguiente manera, no hay necesidad de preocuparse por establecer 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()));
- Dibujar el arco de borde redondeado en android con efecto grabado en relieve
- Android SupportLib – FrameLayout en CoordinatorLayout con AppBarLayout consumiendo toda la altura de la pantalla