获得毫秒到午夜

时间:2012-08-16 14:36:30

标签: java android date milliseconds

我正在创建一个我想在午夜每晚更新的Android小部件。我使用的是AlarmManager,我需要知道从当前时间到午夜剩下多少毫秒。这是我的代码:

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

如何计算到午夜剩余的毫秒数?

提前谢谢。

6 个答案:

答案 0 :(得分:51)

使用日历计算它:

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

答案 1 :(得分:13)

TL;博士

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

java.time

Java 8及更高版本内置了java.time框架。这些新类取代了与Java捆绑在一起的旧日期时间类(java.util.Date/.Calendar)。也取代了Joda-Time,由同一个人开发。许多java.time功能都被反向移植到Java 6& 7,并进一步适应Android(见下文)。

时区对于确定日期至关重要。对于任何给定的时刻,日期在全球范围内因地区而异。例如,在Paris France午夜后的几分钟是新的一天,而Montréal Québec中仍然是“昨天”。

continent/region的格式指定proper time zone name,例如America/MontrealAfrica/CasablancaPacific/Auckland。切勿使用诸如ESTIST之类的3-4字母缩写,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)。

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

我们希望获得第二天的第一时刻,但不包括第二时刻的毫秒数。

我们必须通过LocalDate课程才能获得一天的第一时间。因此,我们从ZonedDateTime开始获取LocalDate,然后获得另一个ZonedDateTime。关键是在LocalDate上调用atStartOfDay

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

请参阅此code run live at IdeOne.com

  

now.toString():2017-05-02T12:13:59.379-04:00 [美国/蒙特利尔]

     

tomorrowStart.toString():2017-05-03T00:00-04:00 [美国/蒙特利尔]

     

millisecondsUntilTomorrow:42360621

关于 java.time

java.time框架内置于Java 8及更高版本中。这些类取代了麻烦的旧legacy日期时间类,例如java.util.DateCalendar和& SimpleDateFormat

现在位于Joda-Timemaintenance mode项目建议迁移到java.time类。

要了解详情,请参阅Oracle Tutorial。并搜索Stack Overflow以获取许多示例和解释。规范是JSR 310

您可以直接与数据库交换 java.time 对象。使用符合JDBC driver或更高版本的JDBC 4.2。不需要字符串,不需要java.sql.*类。

从哪里获取java.time类?

约达时间

更新 Joda-Time项目现在位于maintenance mode,团队建议迁移到java.time课程。为了历史原因,我保留此部分的完整性,但建议使用java.time和ThreeTenABP,如上所述。

在Android中,你应该使用Joda-Time库而不是臭名昭着的麻烦的Java.util.Date/.Calendar类。

Joda-Time提供milliseconds-of-day command。但我们并不需要这里。

相反,我们只需要一个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 ms。

答案 2 :(得分:2)

尝试以下方法:

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

答案 3 :(得分:0)

这会有用吗?

long MILLIS_IN_DAY = 86400000;

long currentTime = System.currentTimeInMillis();

long millisTillNow = currentTime % MILLIS_IN_DAY;

long millisecondsUntilMidnight = MILLIS_IN_DAY - millisTillNow;

答案 4 :(得分:0)

您可以使用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
);

答案 5 :(得分:0)

使用以下方式,无需担心设置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()));