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.
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());
Duration.between( now , tomorrowStart )
.toMillis()
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
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?
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.
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);
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
);
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()));
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;