【问题标题】:Calculating alarm time for alarm clock计算闹钟的闹钟时间
【发布时间】:2018-05-03 09:18:12
【问题描述】:

我正在尝试制作闹钟应用程序,但无法设置闹钟响起的时间。我的应用程序让用户选择他们希望闹钟响起的日期,类似于 android 闹钟,用一个 7 的布尔数组来表示这一点。

我的想法是将时钟设置为最近的一天,即如果今天是星期一并且闹钟设置为星期三和星期五,则闹钟将在星期三响起,然后在星期五自行重置。

我想知道日历是否可以返回一周,我认为这会让事情变得更容易。

【问题讨论】:

    标签: java android calendar alarmmanager


    【解决方案1】:

    避免使用旧的日期时间类

    避免使用麻烦的旧旧日期时间类。而是使用 java.time 类。

    DayOfWeek 枚举 & EnumMap

    DayOfWeekenum 为每周 7 天(周一至周日)的每一天预定义了七个对象。

    EnumSetEnumMapSetMap 的非常快速和低内存的实现,用于处理枚举值的集合。在您的情况下,您可以定义一个包含所有 7 天的 EnumMap,每个映射到一个 LocalTime 以表示何时触发警报(或 null 表示当天没有警报)。

    EnumMap< DayOfWeek , LocalTime > dowToTimeMap = new EnumMap< DayOfWeek , LocalTime >( DayOfWeek.class );
    
    dowToTimeMap.put( DayOfWeek.MONDAY , LocalTime.of( 6 , 0 ) );  // 6 AM.
    dowToTimeMap.put( DayOfWeek.TUESDAY , LocalTime.of( 6 , 0 ) );
    …
    dowToTimeMap.put( DayOfWeek.SATURDAY , LocalTime.of( 8 , 0 ) ); // Sleep in until 8 AM on Saturday.
    dowToTimeMap.put( DayOfWeek.SUNDAY , LocalTime.of( 7 , 0 ) );
    

    要获取当前日期,请指定时区 (ZoneId)。 LocalDate 类表示没有时间和时区的仅日期值。

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

    向地图询问今天星期几的闹钟时间。

    LocalTime alarmTimeToday = dowToTimeMap.get( today.getDayOfWeek() );
    

    您可能会发现 ZonedDateTimeInstantDuration 类可用于确定下一次警报之前的经过时间。

    ZoneId z = ZoneId.of( "America/Montreal" );
    LocalDate today = LocalDate.now( z );
    LocalDate tomorrow = today.plusDays( 1 );
    LocalTime alarmTimeTomorrow = dowToTimeMap.get( tomorrow.getDayOfWeek() );
    ZonedDateTime nextAlarmZdt = ZonedDateTime.of( tomorrow , alarmTimeTomorrow , z );
    Instant now = Instant.now();
    Duration duration = Duration.between( now , nextAlarmZdt.toInstant() );
    

    检查持续时间是否为负数,即时间倒退。这意味着下一个闹钟时间要么在现在之前,要么在这段代码运行时已经过期。

    if( duration.isNegative() ) {
        // Oops, the next alarm was within a second or so of current time, a shorter time than it took to execute this code.
        …  // Handle the problem.
    }
    

    您还可以验证今天和明天,因为如果此代码在午夜执行,情况可能会发生变化。

    然后,您可以在整秒、毫秒或纳秒内询问Duration,无论您需要设置什么闹钟。


    关于java.time

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

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

    要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

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

    从哪里获得 java.time 类?

    ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

    【讨论】:

      【解决方案2】:

      您可以像这样获取当前日期和月份:

      Calendar c = Calendar.getInstance();
      int day = c.get(Calendar.DAY_OF_MONTH);
      int month = c.get(Calendar.MONTH);
      

      和星期几(如星期一、星期二...)与

      int day = c.get(Calendar.DAY_OF_WEEK);
      

      http://developer.android.com/reference/java/util/Calendar.html#DAY_OF_WEEK

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-06-10
        • 1970-01-01
        • 2012-07-21
        • 2011-08-21
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多