首页 文章

获取Java中的所有夜晚时间

提问于
浏览
0

我一直试图对犯罪列表进行排序,并将对象分类为白天和夜间列表 . 所以白天可以在早上6点到晚上10点之间,晚上时间可以在晚上10点到早上6点之间 . 我写了一个if语句试图填写一系列夜间犯罪 .

if(data.getDate().getHours() < 6 && data.getDate().getHours() > 22) {
            System.out.println(data.getDate().toLocaleString());
            nightCrimes.add(data);
    }

虽然没有打印出来但列表仍然是空的 . 我注意到逻辑显然是错误的,因为一个特定的整数(小时)不能超过22且小于6.有没有更好的方法来解决这个问题?

2 回答

  • 4

    您需要更改的唯一内容是将&&替换为|| . 这是新的if语句

    if(data.getDate().getHours() < 6 || data.getDate().getHours() > 22)
    
  • 1

    tl;博士

    正如George Fox所说的那样,你问题的直接答案是使用逻辑OR而不是AND .

    但是您的代码还有其他问题:

    • 忽略 time zone 的关键问题

    • 使用血腥 awful date-time classes ,现在已经过时了 .

    代码段:

    data
    .getDate()                         // Using terrible old `java.time.Date` class.
    .toInstant()                       // Convert from legacy class to modern class.
    .atZone(                           // Adjust from UTC to your own local time zone.
        ZoneId.of( "Africa/Tunis" )    // Use proper time zone name in `Continent/Region` format.
    )                                  // Returns a `ZonedDateTime` object, a moment as seen through the wall-clock time used by the people of a particular region (a time zone). 
    .getHour()                         // Returns an `int` for hour-of-day.
    

    ...(等于或大于22)或(小于6)=夜间值 .

    java.time

    显然你正在使用可怕的旧日期时间类,推断你对 getHours 的调用是java.util.Date::getHours .

    几年前,业界领先的java.time类取代了这些遗留类 .

    顺便说一句, Date::getHours 也被弃用了 .

    时区

    如果您正在使用 java.util.Date ,那么您忽略了时区的关键问题 . Date 表示UTC中的时刻,根据定义始终为UTC .

    因此,除非您居住在冰岛,否则请求UTC中的当天时间与您当地的白天和黑夜时间不符 .

    首先将您的 Date 转换为现代java.time.Instant . 为此,您可以使用添加到旧类的新方法 .

    Instant instant = myJavaUtilDate.toInstant() ;  // Convert from legacy class to modern class.
    

    然后为您所在地区应用时区,以获得ZonedDateTime .

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

    ZoneId z = ZoneId.of( "Pacific/Auckland" ) ;
    ZonedDateTime zdt = instant.atZone( z ) ;
    

    比较您的问题中的时间 .

    static final int MORNING_HOUR = 6 ;
    static final int EVENING_HOUR = 22 ;
    …
    int hour = zdt.getHour() ;
    boolean isNighttime = 
        ( hour >= EVENING_HOUR )  // Include this hour.
        || 
        ( hour < MORNING_HOUR )   // Exclude this hour.
    ;
    

    您可以将它们收集到 Map 中,其中键是字符串“nighttime”或“daytime”,值是 SetCrime 对象 . Set 消除了重复 . 如果您想要对犯罪进行排序,请使用 SortedSet .

    Map < String, SortedSet < Crime > > dayOrNight = new HashMap <>( 2 );
    dayOrNight.put( "daytime" , new TreeSet <>() );
    dayOrNight.put( "nighttime" , new TreeSet <>() );
    

    搜集 .

    if( isNighttime ) { 
        dayOrNight.get( "nighttime" ).add( crime ) ;
    } else {  // Else, must be daytime.
        dayOrNight.get( "daytime" ).add( crime ) ;
    }
    

    让我们接下来将该代码转换为使用时间而不是一天中的时间,以防您的业务规则被重新定义为部分小时 .

    通常使用半开放方法最好地定义时间 Span . 开头是包容性的,而结尾是独家的 . 因此,夜晚时间从晚上10点的第一个时刻开始,一直持续到但不包括上午6点的第一个时刻 .

    提示:询问“是否等于或晚于晚上10点”的较短方式是“如果不是之前

    LocalTime morning = LocalTime.of( 6 , 0 ) ;
    LocalTime evening = LocalTime.of( 22 , 0 ) ;
    
    LocalTime lt = zdt.toLocalTime() ;
    boolean isNighttime = ( ! lt.isBefore( evening ) ) || lt.isBefore( morning ) ;
    
    if( isNighttime ) { 
        dayOrNight.get( "nighttime" ).add( crime ) ;
    } else {  // Else, must be daytime.
        dayOrNight.get( "daytime" ).add( crime ) ;
    }
    

    关于java.time

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

    现在位于maintenance modeJoda-Time项目建议迁移到java.time类 .

    要了解更多信息,请参阅Oracle Tutorial . 并搜索Stack Overflow以获取许多示例和解释 . 规格是JSR 310 .

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

    从哪里获取java.time类?

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

相关问题