Androidウィジェットを毎晩深夜に更新するように作成しています。AlarmManager
を使用していて、現在から何ミリ秒残っているかを調べる必要があります真夜中までの時間です。これが私のコードです。
AlarmManager mAlarmManager = (AlarmManager)context.getSystemService(Android.content.Context.ALARM_SERVICE);
mAlarmManager.set(AlarmManager.ELAPSED_REALTIME, millisecondsUntilMidnight, mSrvcPendingingIntent);
深夜までに残っているミリ秒数を計算するにはどうすればよいですか?
前もって感謝します。
カレンダーを使用して計算します。
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以降には、 Java.time フレームワークが組み込まれています。これらの新しいクラスは、Javaにバンドルされた古い日時クラス(Java.util.Date/.Calendar)に取って代わります。また、同じ人々によって開発されたJoda-Timeに取って代わります。 Java.time機能の多くはJava 6&7にバックポートされており、さらにAndroid(下記参照)に対応しています。
日付を決定するには、タイムゾーンが重要です。いつでも、日付はゾーンごとに世界中で異なります。たとえば、 パリの真夜中の数分後 は新しい日ですが、 モントリオールケベック の「昨日」です。
continent/region
、 America/Montreal
、またはAfrica/Casablanca
などのPacific/Auckland
の形式で 適切なタイムゾーン名 を指定します。 EST
やIST
などの3〜4文字の略語は、not真のタイムゾーンであり、標準化されておらず、一意ではないため、決して使用しないでください。 (!).
ZoneId z = ZoneId.of( "America/Montreal" );
ZonedDateTime now = ZonedDateTime.now( z );
翌日の最初の瞬間までのミリ秒数を取得する必要があります。
1日の最初の瞬間に取得するには、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();
この IdeOne.comでライブで実行されるコード を参照してください。
now.toString():2017-05-02T12:13:59.379-04:00 [アメリカ/モントリオール]
tomorrowStart.toString():2017-05-03T00:00-04:00 [アメリカ/モントリオール]
ミリ秒UntilTomorrow:42360621
Java.time フレームワークはJava 8以降に組み込まれています。これらのクラスは厄介な古い レガシーに取って代わりますJava.util.Date
、 Calendar
、& SimpleDateFormat
などの日時クラス.
Joda-Time プロジェクトは現在 メンテナンスモード であり、 Java.time クラスへの移行を推奨しています。
詳細については、 Oracleチュートリアル を参照してください。スタックオーバーフローで多くの例と説明を検索してください。仕様は JSR 310 です。
Java.timeオブジェクトをデータベースと直接交換できます。 JDBC 4.2 以降に準拠した JDBCドライバー を使用します。文字列も、Java.sql.*
クラスも必要ありません。
Java.timeクラスはどこで入手できますか?
UPDATE:Joda-Time プロジェクトは メンテナンスモード になり、チームは Javaへの移行をアドバイスしています.time クラス。歴史上、このセクションはそのままにしておきますが、前述のようにJava.timeとThreeTenABPを使用することをお勧めします。
Androidでは、悪名高い厄介なJava.util.Date/.Calendarクラスではなく、 Joda-Time ライブラリを使用する必要があります。
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ミリ秒です。
以下を試してください:
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);
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
);
次の方法を使用すると、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()));
これはうまくいくでしょうか?
long MILLIS_IN_DAY = 86400000;
long currentTime = System.currentTimeInMillis();
long millisTillNow = currentTime % MILLIS_IN_DAY;
long millisecondsUntilMidnight = MILLIS_IN_DAY - millisTillNow;