查看当前时间是否在Java中当前日期的特定时间范围内

查看当前时间是否在Java中当前日期的特定时间范围内,java,datetime,date,temporal,Java,Datetime,Date,Temporal,我确信这在1000个不同的地方做了1000次。问题是我想知道是否有更好/标准/更快的方法来检查当前“时间”是否在hh:mm:ss格式中给出的两个时间值之间。例如,我的大业务逻辑不应该在18:00:00和18:30:00之间运行。以下是我的想法: public static boolean isCurrentTimeBetween(String starthhmmss, String endhhmmss) throws ParseException{ DateFormat hhmmssFo

我确信这在1000个不同的地方做了1000次。问题是我想知道是否有更好/标准/更快的方法来检查当前“时间”是否在
hh:mm:ss
格式中给出的两个时间值之间。例如,我的大业务逻辑不应该在
18:00:00和18:30:00
之间运行。以下是我的想法:

 public static  boolean isCurrentTimeBetween(String starthhmmss, String endhhmmss) throws ParseException{
  DateFormat hhmmssFormat = new SimpleDateFormat("yyyyMMddhh:mm:ss");
  Date now = new Date();
  String yyyMMdd = hhmmssFormat.format(now).substring(0, 8);

  return(hhmmssFormat.parse(yyyMMdd+starthhmmss).before(now) &&
    hhmmssFormat.parse(yyyMMdd+endhhmmss).after(now));
 }
示例测试用例:

  String doNotRunBetween="18:00:00,18:30:00";//read from props file
  String[] hhmmss = downTime.split(",");
  if(isCurrentTimeBetween(hhmmss[0], hhmmss[1])){
   System.out.println("NOT OK TO RUN");
  }else{
   System.out.println("OK TO RUN");
  }
我要找的是更好的代码

  • 表演中
  • 相貌
  • 正确地
我不是在找什么

  • 第三方图书馆
  • 异常处理辩论
  • 变量命名约定
  • 方法修改器问题

这是您需要做的全部工作,此方法与输入松散耦合且高度一致

boolean isNowBetweenDateTime(final Date s, final Date e)
{
    final Date now = new Date();
    return now.after(s) && now.before(e);
}
private Date dateFromHourMinSec(final String hhmmss)
{
    if (hhmmss.matches("^[0-2][0-9]:[0-5][0-9]:[0-5][0-9]$"))
    {
        final String[] hms = hhmmss.split(":");
        final GregorianCalendar gc = new GregorianCalendar();
        gc.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hms[0]));
        gc.set(Calendar.MINUTE, Integer.parseInt(hms[1]));
        gc.set(Calendar.SECOND, Integer.parseInt(hms[2]));
        gc.set(Calendar.MILLISECOND, 0);
        return gc.getTime();
    }
    else
    {
        throw new IllegalArgumentException(hhmmss + " is not a valid time, expecting HH:MM:SS format");
    }
}
如何获取开始和结束的日期对象与比较它们无关。通过传递
String
表示,您正在使事情变得比您需要的更复杂

这里有一个更好的方法来获得开始和结束日期,同样是松散耦合和高度一致的

boolean isNowBetweenDateTime(final Date s, final Date e)
{
    final Date now = new Date();
    return now.after(s) && now.before(e);
}
private Date dateFromHourMinSec(final String hhmmss)
{
    if (hhmmss.matches("^[0-2][0-9]:[0-5][0-9]:[0-5][0-9]$"))
    {
        final String[] hms = hhmmss.split(":");
        final GregorianCalendar gc = new GregorianCalendar();
        gc.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hms[0]));
        gc.set(Calendar.MINUTE, Integer.parseInt(hms[1]));
        gc.set(Calendar.SECOND, Integer.parseInt(hms[2]));
        gc.set(Calendar.MILLISECOND, 0);
        return gc.getTime();
    }
    else
    {
        throw new IllegalArgumentException(hhmmss + " is not a valid time, expecting HH:MM:SS format");
    }
}

现在,您可以进行两个命名良好的方法调用,这将是非常自我记录的。

dateFromHourMinSec方法在编写时存在缺陷。它不允许秒位数大于3的任何小时,例如18:00:00。如果将其更改为允许[0-2][0-9],则将允许29:00:00等时间。
有解决办法吗?

正如凯文所指出的,Fuzzy Lollipop的Regex不会在14:00到19:00之间提取时间

要获得一个完整的24小时时钟,您可以使用:

if (hhmmss.matches("^([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$"))
{
    // Do stuff here
}

下面的类是我刚刚从其他答案的一些代码中创建的。它封装了“时间段”的行为,而与特定的日期无关。我们的系统正在使用此类来检查当前时间是否在指定的维护窗口内。i、 e.05:00:00-07:00:00

import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;

/**
*
* @author Adam Yocum
*/
public class ExclusionTimePeriod {
    private String timeStart;
    private String timeEnd;

    /**
    * @return the timeStart
    */
    public String getTimeStart() {
        return timeStart;
    }

    /**
    * @param timeStart the timeStart to set
    */
    public void setTimeStart(String timeStart) {
        if (timeStart.matches("^([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$"))
        {
            this.timeStart = timeStart;
        }
        else
        {
            throw new IllegalArgumentException(timeStart + " is not a valid time, expecting HH:MM:SS format");
        }

    }

    /**
    * @return the timeEnd
    */
    public String getTimeEnd() {
        return timeEnd;
    }

    /**
    * @param timeEnd the timeEnd to set
    */
    public void setTimeEnd(String timeEnd) {
        if (timeEnd.matches("^([0-1][0-9]|2[0-3]):([0-5][0-9]):([0-5][0-9])$"))
        {
            this.timeEnd = timeEnd;
        }
        else
        {
            throw new IllegalArgumentException(timeEnd + " is not a valid time, expecting HH:MM:SS format");
        }
    }

    private Date toDate(String hhmmss){
        final String[] hms = hhmmss.split(":");
        final GregorianCalendar gc = new GregorianCalendar();
        gc.set(Calendar.HOUR_OF_DAY, Integer.parseInt(hms[0]));
        gc.set(Calendar.MINUTE, Integer.parseInt(hms[1]));
        gc.set(Calendar.SECOND, Integer.parseInt(hms[2]));
        gc.set(Calendar.MILLISECOND, 0);
        Date date = gc.getTime();
        return date;
    }

    public boolean isNowInPeriod()
    {
        final Date now = new Date();
        return now.after(toDate(getTimeStart())) && now.before(toDate(getTimeEnd()));
    }

    public static void main(String[] args){

        //Test All possible hours
        for(int hour=0;hour<=23;hour++){

            String hourStr = "";
            if(hour<=9){
                hourStr = "0"+hour;
            }else{
                hourStr = ""+hour;
            }

            for(int min=0;min<60;min++){
                String minStr = "";
                if(min<=9){
                    minStr = "0"+min;
                }else{
                    minStr = ""+min;
                }

                for(int sec=0;sec<60;sec++){
                    String secStr = "";
                    if(sec<=9){
                        secStr = "0"+sec;
                    }else{
                        secStr = ""+sec;
                    }

                    String hhmmss = hourStr+":"+minStr+":"+secStr;

                    ExclusionTimePeriod period = new ExclusionTimePeriod();
                    period.setTimeStart(hhmmss);
                    period.setTimeEnd(hhmmss);

                    System.out.println(hhmmss+" Ok");
                }
            }
        }


        //Test isInPeriod functionality
        ExclusionTimePeriod isInTest = new ExclusionTimePeriod();
        isInTest.setTimeStart("10:00:00");
        isInTest.setTimeEnd("10:43:00");

        System.out.println((new Date())+" is between "+isInTest.getTimeStart()+" and "+isInTest.getTimeEnd()+" = "+isInTest.isNowInPeriod());

    }
}
import java.util.Calendar;
导入java.util.Date;
导入java.util.GregorianCalendar;
/**
*
*@作者亚当·尤库姆
*/
公共类排除时间段{
私有字符串时间启动;
私有字符串时间结束;
/**
*@返回timeStart
*/
公共字符串getTimeStart(){
返回时间开始;
}
/**
*@param timeStart要设置的timeStart
*/
公共void setTimeStart(字符串timeStart){
如果(timeStart.matches(“^([0-1][0-9]| 2[0-3]):([0-5][0-9]):([0-5][0-9]):([0-5][0-9])$”)
{
this.timeStart=timeStart;
}
其他的
{
抛出新的IllegalArgumentException(timeStart+“不是有效时间,应为HH:MM:SS格式”);
}
}
/**
*@返回时间结束
*/
公共字符串getTimeEnd(){
返回时间结束;
}
/**
*@param timeEnd要设置的timeEnd
*/
公共void setTimeEnd(字符串timeEnd){
如果(timeEnd.matches(“^([0-1][0-9]| 2[0-3]):([0-5][0-9]):([0-5][0-9]):([0-5][0-9])$”)
{
this.timeEnd=timeEnd;
}
其他的
{
抛出新的IllegalArgumentException(timeEnd+“不是有效时间,应为HH:MM:SS格式”);
}
}
私有日期toDate(字符串hhmmss){
最后一个字符串[]hms=hhmmss.split(“:”);
最终GregorianCalendar gc=新的GregorianCalendar();
gc.set(Calendar.HOUR\u OF_DAY,Integer.parseInt(hms[0]));
gc.set(Calendar.MINUTE,Integer.parseInt(hms[1]);
gc.set(Calendar.SECOND,Integer.parseInt(hms[2]);
gc.set(日历毫秒,0);
Date-Date=gc.getTime();
返回日期;
}
公共布尔值IsNoInPeriod()
{
现在的最终日期=新日期();
返回now.after(toDate(getTimeStart())&now.before(toDate(getTimeEnd());
}
公共静态void main(字符串[]args){
//测试所有可能的时间
对于(整小时=0;小时;dr
使用java.time
您正在使用的旧日期时间类被证明是设计糟糕、令人困惑和麻烦的。它们现在被java.time类所取代

LocalTime
不要只传递表示一天时间值的字符串。我们现在有了一种类型,即
LocalTime

LocalTime start = LocalTime.of( 18 , 0 );
LocalTime stop = LocalTime.of( 18 , 30 );
将这些实例传递给实用程序方法。该方法不必进行任何解析,因此无需引发解析异常

public static  boolean isCurrentTimeBetween( LocalTime start , LocalTime stop ) {
…
ZoneDateTime
时区对于确定一天中的当前日期和时间至关重要。对于任何给定的时刻,全球各地的日期因区域而异。例如,中午夜后几分钟是新的一天,而中仍然是“昨天”

请以
大陆/地区
的格式指定一个,例如,或
太平洋/奥克兰
。切勿使用3-4个字母的缩写,例如
EST
IST
,因为它们不是真正的时区,不是标准化的,甚至不是唯一的(!)

为了比较现在一天中的时间,我们可以简单地从
ZonedDateTime
中提取一个
LocalTime
。但是我们有异常的问题,比如夏令时(DST)政客重新定义时区。在特定日期可能没有任何下午6点的时间。这个难题的解决方案取决于您的业务环境和业务规则。您可以忽略这个难题,坚持逐字询问当前时间是否在您的目标起止时间之间。或者您可以将时区应用于y我们每天的起止时间,让
ZoneDateTime
类根据需要进行调整。让我们看看这两种方法

忽略异常 首先,忽略任何异常现象。简单而准确地询问当前时间是否在一天的目标开始时间和停止时间之间

我们可以从分区日期时间对象中提取一个时间对象

LocalTime localTimeNow = zdt.toLocalTime(); // Extract a time-of-day from the zoned date-time object.
LocalDate localDateToday = zdt.toLocalDate();
ZonedDateTime zdtStart = ZonedDateTime.of( localDateToday , start , z );
ZonedDateTime zdtStop = ZonedDateTime.of( localDateToday , stop , z );
请注意,我们在这里使用半开放的方法来定义时间跨度
LocalDate localDateToday = zdt.toLocalDate();
ZonedDateTime zdtStart = ZonedDateTime.of( localDateToday , start , z );
ZonedDateTime zdtStop = ZonedDateTime.of( localDateToday , stop , z );
Boolean isNowOnOrAfterStart = ( ! zdt.isBefore( zdtStart ) ) ;  // A briefer way of asking "is equal to OR is after" is "is not before". 
Boolean isNowBeforeStop = zdt.isBefore( zdtStop );
Boolean isNowInTargetZone = ( isNowOnOrAfterStart && isNowBeforeStop ); // Half-Open: beginning is inclusive while ending is exclusive.
Interval interval = Interval.of( zdtStart.toInstant() , zdtStop.toInstant() );
Boolean isNowInTargetZone = interval.contains( zdt.toInstant() );
/**
 * Takes into consideration that the interval may span accross midnight
 *
 * @param clock to make unit testing easier, just replace for Clock.systemUTC() in your code 
 * @param start the interval start
 * @param end the interval end
 * @return true if "now" is inside the specified interval
 */
static boolean isNowBetweenLocalTime(Clock clock, final LocalTime start, final LocalTime end) {
    LocalTime now = LocalTime.now(clock);

    // if interval crosses midnight
    if (end.isBefore(start)) {
        if (now.isAfter(start) && now.isAfter(end)) {
            return true;
        }
        if (now.isBefore(start) && now.isBefore(end)) {
            return true;
        }
        return false;
    }

    // if interval does not cross midnight
    if (end.isAfter(start)) {
        if (now.isAfter(start) && now.isBefore(end)) {
            return true;
        }
        return false;
    }

    return false; // interval is 0 so start and end always outside interval
}