将日历设置为特定日期?

Set the Calendar to a specific date?

我想在特定日期设置提醒通知。然后我目前正在将 AlarmManager 与 NotificationManager 一起使用。当我从 dateDialog 设置选定日期时,提醒有效。如何将日历值放在固定时间的闹钟上?我从这里得到当前日期和时间:

Calendar calendar =  Calendar.getInstance();

然后我可以像下面那样手动设置日历并且它正在运行:

calendar.set(Calendar.SECOND, 0);
calendar.set(Calendar.MINUTE, 13);
calendar.set(Calendar.HOUR, 7);
calendar.set(Calendar.AM_PM, Calendar.AM);
calendar.set(Calendar.MONTH, Calendar.JANUARY);
calendar.set(Calendar.DAY_OF_MONTH, 8);
calendar.set(Calendar.YEAR,2015);
long when = calendar.getTimeInMillis();

但我的问题是如何将日历设置为明天和 9:00 上午,或者将日历精确设置为当前日期之后的特定月份(或年份)?我的意思是这样的:

calendar.add(Calendar.DAY_OF_MONTH, 1);

但它不起作用。

要通过示例添加一个小时,您可以这样做:

calendar.set(Calendar.HOUR, calendar.get(Calendar.HOUR) + 1);

对我来说,这在桌面上工作得很好,虽然无法在Android上测试它。
更新: 刚刚使用 AIDE 在我的 Android phone 上测试了这个,得到了完全相同的结果。

import java.util.Calendar;

public class CalendarTest {

    public static void main(String[] args) {

        Calendar calendar = Calendar.getInstance();

        System.out.println(calendar.getTimeInMillis() + " -> " + calendar.getTime());

        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 13);
        calendar.set(Calendar.HOUR, 7);
        calendar.set(Calendar.AM_PM, Calendar.AM);
        calendar.set(Calendar.MONTH, Calendar.JANUARY);
        calendar.set(Calendar.DAY_OF_MONTH, 9);
        calendar.set(Calendar.YEAR, 2015);

        System.out.println(calendar.getTimeInMillis() + " -> " + calendar.getTime());

        calendar.add(Calendar.DAY_OF_MONTH, 1);
        calendar.add(Calendar.YEAR, 1);

        System.out.println(calendar.getTimeInMillis() + " -> " + calendar.getTime());
    }

对于此测试,我的输出正是您所期望的:

1420705649927 -> Thu Jan 08 09:27:29 CET 2015
1420783980927 -> Fri Jan 09 07:13:00 CET 2015
1452406380927 -> Sun Jan 10 07:13:00 CET 2016

乔达时间

更新: Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes. See Tutorial by Oracle

尝试使用更好的日期时间库,例如 Joda-Time。

在 Joda-Time 中,您可以在保持时间的同时更改日期。或者,反之亦然,在保留日期的同时保留时间。

DateTime now = DateTime.now( DateTimeZone.forID( "America/Montreal" ) ) ;
DateTime todayNoon = now.withTime( 12, 0, 0, 0 ) ;
DateTime midMarchSameYearSameTimeAsNow = now.withDate(  now.getYear(), DateTimeConstants.MARCH, 15 );
DateTime tomorrowSameTime = now.plusDays( 1 );

tl;博士

ZonedDateTime.of(
    LocalDate.of( 2015 , Month.JANUARY , 8 ) ,
    LocalTime.of( 7 , 13 , 0 ) ,
    ZoneId.of( "Africa/Tunis" ) 
)
.toInstant()
.toEpochMilli()

1420697580000

java.time

现代方法使用 java.time 类 取代麻烦的旧遗留 date-time 类。 所以现在更容易、更干净了。

您的代码含糊不清,因为您没有解决时区这一关键问题。由于您没有明确指定时区,因此将隐式应用 JVM 当前的默认时区。我强烈建议 始终 指定您的 desired/expected 时区。

指定 proper time zone name in the format of continent/region, such as America/Montreal, Africa/CasablancaPacific/Auckland。切勿使用 3-4 字母 pseudo-zones,例如 ESTIST,因为它们 不是 真实时区,未标准化,甚至不唯一(!)。

LocalDate ld = LocalDate.of( 2015 , Month.JANUARY , 8 ) ;
LocalTime lt = LocalTime.of( 7 , 13 , 0 ) ;
ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
ZonedDateTime zdt = ZonedDateTime.of( ld , lt , z ) ;

您也可以使用组合因子法。

ZonedDateTime zdt = ZonedDateTime.of( 2015 , Month.JANUARY , 8 , 7 , 13 , 0 , 0 , ZoneId.of( "Pacific/Auckland" ) ) ;

我通常建议不要将 date-time 作为 count-from-epoch 进行跟踪。但这似乎是您的情况的要求。

首先我们可以提取一个 Instant,一个 UTC 时刻。 Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds(最多九 (9) 位小数)。

Instant instant = zdt.toInstant() ;  // Convert from a zoned value to a UTC value.

然后您可以查询自 UTC 1970 年第一时刻的纪元参考以来的毫秒数,1970-01-01T00:00:00Z。当心可能的数据丢失,因为 Instant 中的任何微秒或纳秒在仅报告毫秒时将被忽略。

long millis = instant.toEpochMilli() ;  // Count of milliseconds since 1970-01-01T00:00:00Z.

关于java.time

java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.

Joda-Time project, now in maintenance mode, advises migration to the java.time 类.

要了解更多信息,请参阅 Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310

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

在哪里获取java.time类?

  • Java SE 8, Java SE 9,及以后
    • Built-in。
    • 标准 Java API 的一部分,带有捆绑实施。
    • Java 9 添加了一些小功能和修复。
  • Java SE 6 and Java SE 7
    • java.time 的大部分功能是 back-ported 到 Java ThreeTen-Backport 中的 6 和 7。
  • Android
    • Android 的更高版本 java.time 类 的捆绑实施。
    • 对于较早的 Android,ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See

ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.