Obtener milisegundos hasta la medianoche


Estoy creando un widget de Android que quiero actualizar todas las noches a medianoche. Estoy usando un AlarmManager y necesito averiguar cuántos milisegundos quedan desde 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?

Gracias de antemano.

Author: SZH, 2012-08-16

6 answers

Usa 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());
 48
Author: Denys Séguret,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-04-14 11:33:45

Tl;dr

Duration.between( now , tomorrowStart )
        .toMillis()

Java.time

Java 8 y posterior viene con el java.time framework integrado. Estas nuevas clases suplantan a las antiguas clases de fecha y hora (java.útil.Fecha/.Calendario) incluido con Java. También suplanta a Joda-Time, desarrollado por las mismas personas. Gran parte del java.la funcionalidad de time está retroadaptada a Java 6 y 7, y adaptada a Android (ver más abajo).

Una zona horaria es crucial para determinar una fecha. Para un momento dado, la fecha varía alrededor del mundo por zona. Por ejemplo, unos minutos después de la medianoche en París Francia es un nuevo día mientras que todavía "ayer" en Montreal Québec.

Especificar un apropiado nombre de la zona horaria en el formato continent/region, tales como America/Montreal, Africa/Casablanca, o Pacific/Auckland. Nunca use la abreviatura de 3-4 letras como EST o IST ya que son no zonas horarias verdaderas, no estandarizadas y ni siquiera únicas (!).

ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now( z );

Queremos obtener el número de milisegundos que corren hasta, pero sin incluir, el primer momento del día siguiente.

Debemos pasar por la clase LocalDate para llegar en el primer momento de un día. Así que aquí comenzamos con un ZonedDateTime para obtener un LocalDate, y después de eso obtenemos otro ZonedDateTime. La clave está llamando atStartOfDay en el LocalDate.

LocalDate tomorrow = now.toLocalDate().plusDays(1);
ZonedDateTime tomorrowStart = tomorrow.atStartOfDay( z );

Observe 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. Vamos java.el tiempo determina el primer momento.

Ahora podemos calcular el tiempo transcurrido. En java.tiempo que usamos el Duration clase. Java.time framework tiene una resolución más fina de nanosegundos en lugar de los milisegundos más gruesos utilizados por ambos Java.útil.Fecha y Joda-Hora. Pero Duration incluye un práctico getMillis método, como la Pregunta solicitada.

Duration duration = Duration.between( now , tomorrowStart );
long millisecondsUntilTomorrow = duration.toMillis();

Ver este código ejecutar en vivo en IdeOne.com .

Ahora.toString(): 2017-05-02T12:13:59.379-04: 00[América/Montreal]

Mañana empieza.toString (): 2017-05-03T00:00-04: 00[America/Montreal]

Milisegundos hasta mañana: 42360621


Acerca de java.tiempo

El java.hora el framework está integrado en Java 8 y versiones posteriores. Estas clases suplantan a las problemáticas antiguas legacy clases de fecha y hora como java.util.Date, Calendar, & SimpleDateFormat.

El Joda-Tiempo project, ahora en modo de mantenimiento , aconseja la migración a java .tiempo clases.

Para obtener más información, consulte el Oracle Tutorial. Y desbordamiento de pila de búsqueda para muchos ejemplos y explicaciones. La especificación es JSR 310.

Puede intercambiar java.time objetos directamente con su base de datos. Utilice un controlador JDBC compatible con JDBC 4.2 o posterior. No hay necesidad de cadenas, no hay necesidad de clases java.sql.*.

Dónde obtener java.clases de tiempo?


Joda-Tiempo

ACTUALIZACIÓN: El proyecto Joda-Time está ahora en modo de mantenimiento , con el equipo asesorando la migración a la java.tiempo clases. Dejo esta sección intacta por el bien de la historia, pero recomiendo usar java.time and ThreeTenABP as discussed arriba.

En Android deberías usar la biblioteca Joda-Time en lugar de la notoriamente problemática Java.útil.Fecha/.Clases de calendario.

Joda-Time ofrece un comando milisegundos del día. Pero realmente no necesitamos eso aquí.

En su lugar, solo necesitamos un Duration objeto 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 mejor a especificar que confiar implícitamente en la zona horaria predeterminada actual de la JVM que puede cambiar en cualquier momento. O si realmente desea el valor predeterminado de la JVM, pídalo explícitamente con call to DateTimeZone.getDefault para hacer que su código se documente automáticamente.

Podría ser de dos líneas.

DateTime now = DateTime.now( DateTimeZone.forID( "America/Montreal" ) );
long milliSecondsUntilTomorrow = new Duration( now , now.plusDays( 1 ).withTimeAtStartOfDay() ).getMillis();

Vamos a desmontar eso.

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();

Volcar a la consola.

System.out.println( "From now : " + now + " until tomorrow : " + tomorrow + " is " + millisecondsUntilTomorrow + " ms." );

Cuando se ejecuta.

Desde ahora : 2015-09-20T19:45:43.432-04:00 hasta mañana : 2015-09-21T00:00:00.000-04:00 es 15256568 ms.

 13
Author: Basil Bourque,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-07-06 18:39:47

Intente 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);
 2
Author: Korhan Ozturk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-16 14:49:13

Funcionaría esto?

long MILLIS_IN_DAY = 86400000;

long currentTime = System.currentTimeInMillis();

long millisTillNow = currentTime % MILLIS_IN_DAY;

long millisecondsUntilMidnight = MILLIS_IN_DAY - millisTillNow;
 0
Author: sgp15,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-08-16 14:44:31

Usted podría utilizar AlarmManager.RTC en lugar de AlarmManager.ELAPSED_REALTIME, y simplemente establezca 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
);
 0
Author: nicopico,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-06-14 14:55:04

Usando la siguiente manera, no hay necesidad de preocuparse por configurar 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()));
 0
Author: Youness,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-20 08:19:24