Android Calendar.getInstance() 今天午夜后没有得到

Android Calendar.getInstance() does not get today after midnight

我有以下代码:

Calendar nextSchedule = Calendar.getInstance();
nextSchedule.set(Calendar.HOUR_OF_DAY, 0);
nextSchedule.set(Calendar.MINUTE, 0);
nextSchedule.set(Calendar.SECOND, 10);
nextSchedule.set(Calendar.MILLISECOND, 0);
nextSchedule.add(Calendar.DAY_OF_YEAR, 1);
Calendar cal = Calendar.getInstance();

long diff = nextSchedule.getTimeInMillis() - cal.getTimeInMillis();
long seconds = diff / 1000;
long minutes = seconds / 60;
long hours = minutes / 60;

正如预期的那样,上午 11 点左右它给了我 13/12 小时但是在小部件中执行以下操作时:

Calendar nextSchedule = Calendar.getInstance();
nextSchedule.set(Calendar.HOUR_OF_DAY, 0);
nextSchedule.set(Calendar.MINUTE, 0);
nextSchedule.set(Calendar.SECOND, 10);
nextSchedule.set(Calendar.MILLISECOND, 0);
nextSchedule.add(Calendar.DAY_OF_YEAR, 1);
alarmManager.setExact(AlarmManager.RTC_WAKEUP, nextSchedule.getTimeInMillis(), pendingIntent);

1:30am左右,依旧没有更新。只有在凌晨 2 点到 9 点之间(我睡着了)它才更新。

其他地方也发生了类似的怪事。我有一个带有以下代码的日历视图 (applandeo):cvCalendar.setOnDayClickListener(eventDay -> showDateItems(eventDay,lvCalendar));

private void showDateItems(EventDay eventDay, ListView lvCalendar) {
    Calendar cal = Calendar.getInstance();
    Calendar cal2 = Calendar.getInstance();
    cal.set(eventDay.getCalendar().get(Calendar.YEAR),eventDay.getCalendar().get(Calendar.MONTH),eventDay.getCalendar().get(Calendar.DATE));
    cal2.set(eventDay.getCalendar().get(Calendar.YEAR),eventDay.getCalendar().get(Calendar.MONTH),1);
    cal2.add(Calendar.MONTH, -1);
    ArrayList<String> items = new ArrayList<>();
    String line;
    for (ItemsHistoryItem item: Utils.getInstance().itemsHistory) {
        if (item.getxDay() < Utils.getInstance().calenderToEpoch(cal2) && item.getyDay() < Utils.getInstance().calenderToEpoch(cal2)) break;
        if (item.getxDay() != Utils.getInstance().calenderToEpoch(cal) && item.getyDay() != Utils.getInstance().calenderToEpoch(cal)) continue;
        line = item.getItemId() + ": $" + item.getAmount();
        if (item.getxDay() == Utils.getInstance().calenderToEpoch(cal))
            line += " (x day)";
        else
            line += " (y day)";
        items.add(line);
    }
    ArrayAdapter<String> lcAdapter = new ArrayAdapter<>(requireActivity(), android.R.layout.simple_list_item_1, items);
    lvCalendar.setAdapter(lcAdapter);
}

long calenderToEpoch(Calendar cal2) {
    return TimeUnit.MILLISECONDS.toDays(cal2.getTimeInMillis());
}

基本上,上面的代码扫描项目的日期,当用户 select 某个日期时,他会得到一个项目列表,其中日期(x 和 y)属于该日期。在白天这样做时,它会起作用。当在 1:30am 中这样做时(例如),它会提前一天移动,因此如果用户单击 12-oct,他将获得 11-oct 的项目。在凌晨 2 点到 9 点之间,它 "shifts" 返回并按预期工作。

知道这里出了什么问题吗?

如果你希望它在你想要的时间准确触发,我有一个正确使用 alarmmanager 的建议,否则当设备处于深度睡眠模式并延迟时它不会按时触发:

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        // use setAlarmClock function of AlarmManager
        // but this function will show an alarm icon on statusbar
        // if you dont want to show that icon you can use
        // setExactAndAllowWhileIdle function but that will not be 
        // perfectly exact
    }
    else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
        // use setExact function of AlarmManager
    }
    else {
        // use set function of AlarmManager
    }

显然 Calendar.getInstance() 在我的情况下的默认时区是 GMT+3,所以在凌晨 3 点显示项目的日期并且更新了小部件。要修复它,我只需执行以下操作:

Calendar cal = Calendar.getInstance();
cal.setTimeZone(TimeZone.getTimeZone("UTC"));