web-dev-qa-db-fra.com

Obtenez des millisecondes jusqu'à minuit

Je crée un Android que je veux mettre à jour tous les soirs à minuit. J'utilise un AlarmManager et j'ai besoin de savoir combien de millisecondes il reste du courant jusqu'à minuit. Voici mon code:

AlarmManager mAlarmManager = (AlarmManager)context.getSystemService(Android.content.Context.ALARM_SERVICE);
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, millisecondsUntilMidnight, mSrvcPendingingIntent);

Comment puis-je calculer le nombre de millisecondes restantes jusqu'à minuit?

Merci d'avance.

30
SZH

Utilisez un calendrier pour le calculer:

        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());
51
Denys Séguret

tl; dr

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

Java.time

Java 8 et versions ultérieures sont livrées avec le framework Java.time intégré. Ces nouvelles classes remplacent les anciennes classes date-heure (Java.util.Date/.Calendar) fournies avec Java. Remplace également Joda-Time, développé par les mêmes personnes. Une grande partie de la fonctionnalité Java.time est rétroportée vers Java 6 & 7, et adaptée à Android (voir ci-dessous).

Un fuseau horaire est crucial pour déterminer une date. Pour un moment donné, la date varie dans le monde par zone. Par exemple, quelques minutes après minuit à Paris France est un nouveau jour alors qu'il est encore "hier" à Montréal Québec .

Spécifiez un nom de fuseau horaire correct au format continent/region, tel que America/Montreal , Africa/Casablanca ou Pacific/Auckland. N'utilisez jamais l'abréviation de 3-4 lettres telle que EST ou IST car ils sont pas les vrais fuseaux horaires, non standardisés et même pas uniques (!).

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

Nous voulons obtenir le nombre de millisecondes qui s'écoule jusqu'au premier moment du lendemain, sans l'inclure.

Nous devons passer par la classe LocalDate pour obtenir au premier moment d'une journée. Donc, ici, nous commençons par un ZonedDateTime pour obtenir un LocalDate, et après cela, un autre ZonedDateTime. La clé appelle atStartOfDay sur le LocalDate.

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

Notez que nous ne codons pas en dur une heure à 00:00:00. En raison d'anomalies telles que l'heure d'été (DST), la journée peut commencer à une autre heure telle que 01:00:00. Laissez Java.time déterminer le premier moment.

Maintenant, nous pouvons calculer le temps écoulé. Dans Java.time, nous utilisons la classe Duration . Le cadre Java.time a une résolution plus fine de nanosecondes plutôt que les millisecondes plus grossières utilisées par Java.util.Date et Joda-Time. Mais Duration inclut une méthode pratique getMillis , comme le demandait la question.

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

Voir ceci code exécuté en direct sur IdeOne.com .

now.toString (): 2017-05-02T12: 13: 59.379-04: 00 [Amérique/Montréal]

tomStart.toString (): 2017-05-03T00: 00-04: 00 [Amérique/Montréal]

millisecondesJusqu'à Demain: 42360621


À propos de Java.time

Le cadre Java.time est intégré à Java 8 et versions ultérieures. Ces classes supplantent l'ancien hérité classes date-heure telles que Java.util.Date , Calendar , & SimpleDateFormat .

Le projet Joda-Time , désormais en mode maintenance , conseille la migration vers Java.time = classes.

Pour en savoir plus, consultez le Oracle Tutorial . Et recherchez Stack Overflow pour de nombreux exemples et explications. La spécification est JSR 31 .

Vous pouvez échanger des objets Java.time directement avec votre base de données. Utilisez un pilote JDBC compatible avec JDBC 4.2 ou version ultérieure. Pas besoin de chaînes, pas besoin de Java.sql.* Des classes.

Où obtenir les classes Java.time?


Joda-Time

MISE À JOUR: Le projet Joda-Time est maintenant en mode maintenance , l'équipe conseillant la migration aux classes Java.time . Je laisse cette section intacte pour des raisons d'historique, mais je recommande d'utiliser Java.time et ThreeTenABP comme indiqué ci-dessus.

Dans Android Android, vous devriez utiliser la bibliothèque Joda-Time plutôt que les classes Java.util.Date/.Calendar notoirement gênantes.

Joda-Time propose une commande en millisecondes du jour . Mais nous n'en avons pas vraiment besoin ici.

Au lieu de cela, nous avons juste besoin d'un objet Duration pour représenter l'intervalle de temps jusqu'au premier moment du jour suivant.

Le fuseau horaire est essentiel ici pour déterminer quand "demain" commence. Il est généralement préférable de spécifier que de se fier implicitement au fuseau horaire par défaut de la JVM, qui peut changer à tout moment. Ou si vous voulez vraiment la valeur par défaut de la JVM, demandez-la explicitement en appelant à DateTimeZone.getDefault pour rendre votre code auto-documenté.

Pourrait être un deux lignes.

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

Prenons cela à part.

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

Dump sur console.

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

Lors de l'exécution.

À partir de maintenant: 2015-09-20T19: 45: 43.432-04: 00 jusqu'à demain: 2015-09-21T00: 00: 00.000-04: 00 est 15256568 ms.

13
Basil Bourque

Essayez ce qui suit:

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
Korhan Ozturk

Vous pouvez utiliser AlarmManager.RTC au lieu de AlarmManager.ELAPSED_REALTIME, et définissez simplement un calendrier à l'heure souhaitée:

// 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
nicopico

De la manière suivante, vous n'avez pas à vous soucier de définir 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
Youness

Est-ce que cela fonctionnerait?

long MILLIS_IN_DAY = 86400000;

long currentTime = System.currentTimeInMillis();

long millisTillNow = currentTime % MILLIS_IN_DAY;

long millisecondsUntilMidnight = MILLIS_IN_DAY - millisTillNow;
0
sgp15