Java中查看当前时间是否落在当天的特定时间范围内
我确信这已经在 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");
}
我正在寻找的是
- 性能
- 更好、外观
- 正确的
代码我不是在寻找
- 第三方库
- 异常处理辩论
- 变量命名约定
- 方法修饰符问题
I am sure this was done 1000 times in 1000 different places. The question is I want to know if there is a better/standard/faster way to check if current "time" is between two time values given in hh:mm:ss
format. For example, my big business logic should not run between 18:00:00 and 18:30:00
. So here is what I had in mind:
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));
}
Example test case:
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");
}
What I am looking for is code that is better
- in performance
- in looks
- in correctness
What I am not looking for
- third-party libraries
- Exception handling debate
- variable naming conventions
- method modifier issues
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(6)
这就是您需要做的全部,此方法与输入松散耦合且高度一致。
如何获取开始和结束的 Date 对象与比较它们无关。通过传递
String
表示,您使事情变得比您需要的更加复杂。这是获取开始日期和结束日期的更好方法,同样松散耦合且高度一致。
现在您可以进行两个命名良好的方法调用,这将是非常自记录的。
this is all you should need to do, this method is loosely coupled from the input and highly coherent.
how you get the Date objects for start and end is irrelevant to comparing them. You are making things way more complicated than you need to with passing
String
representations around.Here is a better way to get the start and end dates, again loosely coupled and highly coherent.
Now you can make two well named method calls that will be pretty self documenting.
tl;dr
使用 java.time
您正在使用旧的日期时间类,这些类已被证明设计不佳、令人困惑且麻烦。它们现在是遗留,被 java.time 类取代。
LocalTime
不要仅传递表示时间值的字符串。我们现在有一个类型,即
LocalTime
类。将这些实例传递给您的实用程序方法。该方法不必执行任何解析,因此无需抛出解析异常。
ZonedDateTime
时区对于确定当前日期和时间至关重要。对于任何特定时刻,全球各地的日期都会因地区而异。例如,在法国巴黎午夜过后几分钟,又是新的一天“昨天”在魁北克蒙特利尔。
以
大陆/地区
格式指定正确的时区名称 ,例如America/Montreal
、非洲/卡萨布兰卡
,或太平洋/奥克兰
。切勿使用 3-4 个字母的缩写,例如EST
或IST
,因为它们不是真正的时区,不是标准化的,甚至不是唯一的( !)。为了比较现在的时间,我们可以简单地从
ZonedDateTime
中提取LocalTime
。但我们面临着异常问题,例如夏令时 (DST) 和政客重新定义时区。特定日期可能没有下午 6 点。此难题的解决方案取决于您的业务环境和业务规则。您可以忽略这个难题,直接询问当前时间是否在目标起止时间之间。或者,您可以将时区应用于一天中的起止时间,并让ZonedDateTime
类根据需要进行调整。让我们看看这两种方法。忽略异常
首先,忽略任何异常。简单地按字面意思询问当前时间是否在目标开始时间和停止时间之间。
我们可以从分区日期时间对象中提取一天中的时间对象。
将其与我们一天中的启停时间进行比较。请注意,我们在这里使用半开放方法来定义时间跨度。在这种方法中,开头是包含,而结尾是排除。这种方法在约会工作中很常见,通常是明智的选择。
考虑异常
接下来我们考虑任何异常。我们将一天中的开始和停止时间应用于同一时区内的当前日期。我们从分区日期时间对象中提取仅日期。
研究类文档以了解
ZonedDateTime.of
解决无效的时间值。没有完美的方法来解决不存在的时间值,因此您必须确定此类的方法是否满足您的业务规则。应用与我们上面看到的相同的比较逻辑。
进行比较的另一种方法是使用 ThreeTen-Extra 项目中方便的
Interval
类。该类需要使用Instant
对象,您可以从ZonedDateTime
对象中提取这些对象。即时
类代表 UTC 中时间轴上的时刻,分辨率为 纳秒(最多九 (9) 位小数)。关于 java.time
java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧遗留日期时间类,例如
java.util.Date
,日历
, & ;SimpleDateFormat
。Joda-Time 项目,现已在 维护模式,建议迁移到 java.time 类。
要了解更多信息,请参阅 Oracle 教程。并在 Stack Overflow 上搜索许多示例和解释。规范为 JSR 310。
从哪里获取 java.time 类?
ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是 java.time 未来可能添加的内容的试验场。您可能会在这里找到一些有用的类,例如
间隔
,YearWeek
,<代码>YearQuarter,以及更多 。tl;dr
Using java.time
You are using old date-time classes that have proven to be poorly designed, confusing, and troublesome. They are now legacy, supplanted by the java.time classes.
LocalTime
Do not pass mere strings representing time-of-day values. We now have a type for that, the
LocalTime
class.Pass those instances to your utility method. That method should not have to do any parsing, so no need to throw the parsing exception.
ZonedDateTime
A time zone is crucial in determining the current date and time-of-day. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec.
Specify a proper time zone name in the format of
continent/region
, such asAmerica/Montreal
,Africa/Casablanca
, orPacific/Auckland
. Never use the 3-4 letter abbreviation such asEST
orIST
as they are not true time zones, not standardized, and not even unique(!).To compare the time-of-day of now, we could simply extract a
LocalTime
from thatZonedDateTime
. But we have the problem of anomalies, such as Daylight Saving Time (DST) and politicians redefining time zones. There may not be any 6 PM hour on a particular date. The solution to this conundrum depends on your business context and your business rules. You could either ignore the conundrum and stick with literally asking if the current time is between your target start-stop time. Or you could apply the time zone to your start-stop times-of-day of day and letZonedDateTime
class make adjustments as it sees fit. Let's look at both approaches.Ignore anomalies
First, ignore any anomalies. Ask simply and literally if the current time-of-day is between the target start and stop times-of-day.
We can extract a time-of-day object from the zoned date-time object.
Compare that to our stop-start times-of-day. Note that we use here the Half-Open approach to defining a span of time. In this approach the beginning is inclusive while the ending is exclusive. This approach is common in date-time work and generally is the wise way to go.
Consider anomalies
Next we consider any anomalies. We apply the start and stop times-of-day to the current date within the same time zone. We extract the date-only from the zoned date-time object.
Study the class documentation to understand the behavior of
ZonedDateTime.of
in resolving invalid time-of-day values. There is no perfect way to resolve nonexistent time-of-day values, so you must decide if this class’ way meets your business rules.Apply the same comparison logic as we saw above.
Alternative way to make the comparison is to use the handy
Interval
class from the ThreeTen-Extra project. That class takes a pain ofInstant
objects, which you can extract from yourZonedDateTime
objects. TheInstant
class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).About java.time
The 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
.The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
Where to obtain the java.time classes?
The 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.正如 Kevin 所指出的,Fuzzy Lollipop 的正则表达式不会获取 14:00 到 19:00 之间的时间。
要获得完整的 24 小时时钟,您可以使用以下命令:
As pointed out by Kevin, Fuzzy Lollipop's Regex won't pick up times between 14:00 and 19:00.
To get match a full 24 hour clock, you can use this:
下面的类是我刚刚根据其他答案的一些代码创建的。它封装了“时间段”的行为,与特定日期无关。我们的系统使用此类来检查当前时间是否在我们指定的维护窗口之一内。即 05:00:00 - 07:00:00
The following Class is something I just created out of some of the code from other answers. It encapsulates the behavior of a 'time period' without relating to specific days. Our system is using this Class to check if the current time is within one of our designated maintenance windows. i.e. 05:00:00 - 07:00:00
午夜问题
其他答案没有提到它 - 并且OP也没有问 - 但你应该真正考虑间隔跨越午夜。
时间很困难。我故意留下了代码的“长”版本,并且没有缩写逻辑条件,以尽可能清楚地说明是什么和为什么。
冗长并不总是错误的。这个方法将被隐藏在一个实用程序类中,两年后你会感谢自己理解它的作用!
The Midnight Problem
Other answers fail to mention it - and the OP doesn't ask - but you should really consider when the interval spans across midnight.
Time is difficult. I purposely left the "long" version of the code and didn't abbreviate logical conditions to make it as clear as possible the what's and the why's.
Verbosity is not always wrong. This method will be buried in a utility class and two years from now you'll thank yourself for understanding what it does!
dateFromHourMinSec 方法如所写的那样存在缺陷。它不允许第二位数字大于 3 的任何时间,例如 18:00:00。如果将其更改为允许 [0-2][0-9],它将允许 29:00:00 等时间。
有解决办法吗?
The dateFromHourMinSec method is flawed as written. It won't allow any hours where the seconde digit is greater than 3, e.g. 18:00:00. If you change it to allow [0-2][0-9] it will allow times such as 29:00:00.
Have a fix for that?