时区
您问题中的示例代码忽略了时区的关键问题。日期,即一天的开始和结束点,由时区定义。
java.util.Calendar 和 java.util.Date 都没有指定时区。它们代表 UTC/GMT 中的日期和时间。
因此,您需要应用与您的应用和数据的上下文相关的所需时区。这意味着您需要一个不错的日期时间库。除了 java.util.Date/Calendar、java.text.SimpleDateFormat 和它们的兄弟类之外的东西,因为它们是出了名的麻烦。使用Joda-Time或与 Java 8 捆绑在一起的新java.time.* 包(受 Joda-Time 启发,由 JSR 310 定义)。
注意使用方法withTimeAtStartOfDay
。这是一天的第一刻。这通常是时间 00:00:00,但并非总是如此。夏令时 (DST) 或其他异常情况可能会产生不同的时间。该方法巧妙地处理了此类问题。
今天=时间跨度
从技术上讲,在使用日期时间值时,特定的“日期”实际上是一个时间跨度。定义该跨度的最常见且通常有用的方法是“半开”,其中开头是包含的,结尾是排除的。这意味着,对于当前日期,我们想要今天的第一刻(包括)到明天的第一刻(不包括)。然后我们询问目标日期时间是否在该范围内。
还有其他方法可以完成这项工作。我展示这种方法是因为它适用于“今天”问题之外的情况。
乔达时间
Joda-Time 提供了三个类来定义时间跨度:Interval、Period 和 Duration。
示例代码
设置我们的输入数据,一个日历对象。
// Create a Calendar object to simulate input.
java.util.Date date = DateTime.now().minusDays( 3 ).toDate();
java.util.Calendar cal = java.util.Calendar.getInstance();
cal.setTime( date );
将“今天”定义为一个时间跨度,并查看目标日期时间是否在该跨度内。
DateTimeZone timeZone = DateTimeZone.forID( "Asia/Kolkata" );
DateTime dateTimeInQuestion = new DateTime( cal.getTimeInMillis(), timeZone );
DateTime now = new DateTime( timeZone );
Interval today = new Interval( now.withTimeAtStartOfDay(), now.plusDays( 1 ).withTimeAtStartOfDay() );
boolean isDateTimeInQuestionInInterval = today.contains( dateTimeInQuestion );
转储到控制台...</p>
System.out.println( "cal: " + cal.getTime() );
System.out.println( "dateTimeInQuestion: " + dateTimeInQuestion );
System.out.println( "now: " + now );
System.out.println( "today: " + today );
System.out.println( "isDateTimeInQuestionInInterval: " + isDateTimeInQuestionInInterval );
运行时……</p>
cal: Wed Feb 12 22:46:04 PST 2014
dateTimeInQuestion: 2014-02-13T12:16:04.369+05:30
now: 2014-02-16T12:16:04.497+05:30
today: 2014-02-16T00:00:00.000+05:30/2014-02-17T00:00:00.000+05:30
isDateTimeInQuestionInInterval: false