-5

how to compare three date/time values in java?

Currently i use Date objects

I mean: Date1 - today, 10:00PM Date2 - tomorrow, 5:00AM Date3 - current time

Is date3 between date1 and date2, respect date AND time?

date1.compareTo(date3) * date2.compareTo(date3) > 0

and

date1.after(date3) && date2.before(date3)

are not working.

I use this code in Android App, and if i set my time to 11.30AM, it still returns true for above conditions. If i use Time-objects and 2nd method, it doesn't recognise my time span is between 2 days.

Any idea?

EDIT: To make it exact, here is my current code. app is something like an alarm clock.

            // Current Date/Time
        Date now = Calendar.getInstance().getTime();

        // Time when user goes to bed (current day)
        Date sleep = new Date(now.getYear(), now.getMonth(), now.getDate(), Shours, Sminutes);

        // Time when user wakes up (next day)
        // Get Next Day's Date and set Time
        Calendar wk = Calendar.getInstance();
        wk.setTime(sleep);
        wk.set(Calendar.HOUR_OF_DAY, Whours);
        wk.set(Calendar.MINUTE, Wminutes);
        // tomorrow
        wk.add(Calendar.DATE, 1);
        // and convert to date
        Date wake = wk.getTime();

        // Compare
        if(now.after(sleep) && now.before(wake)) {
                Log.d("uSleep", "Debug: Night time");
        }
        else {
            Log.d("uSleep", "Debug: Day Time");
        }

Maybe it's still too hard to understand. Image you go to bed at 10PM and you get up at 5AM. Now how to find out if you're sleeping by comparing your "go to bed"-time and you "get up"-time to the current time. I need to use "tomorrow" for your "get up"-time, otherwise java seems to compare all times for the same day, which is impossible.

Xorg
  • 1
  • 2
  • 1
    You're saying date/time comparison in Java is fundamentally broken? I'm having a hard time understanding exactly what you're asking. – Dave Newton Nov 21 '14 at 14:22
  • It doesn't help that "today" isn't a point in time. A short but complete program demonstrating the problem would make it a lot easier to help you. It's also not clear *how* you're using `Time` objects... – Jon Skeet Nov 21 '14 at 14:23
  • "Is it now later than 10pm but earlier than 5am next day" – Xorg Nov 21 '14 at 14:23
  • If `date2` is tomorrow, why you're testing if it is `before` `date3`? – Tom Nov 21 '14 at 14:26
  • @Tom the time is important for me – Xorg Nov 21 '14 at 14:28
  • @DaveNewton I added exact code – Xorg Nov 21 '14 at 14:29
  • @Xorg If you want to test `date1 < date3 < date2`, then you should use `date1.before(date3)` and `date2.after(date3)`. – Tom Nov 21 '14 at 14:30
  • @JonSkeet I added exact code – Xorg Nov 21 '14 at 14:31
  • 2
    You claim that it fails when using the `Time` class - but your code doesn't appear to *use* the `Time` class. (It's also not a complete program... it would be really helpful if you'd try to reproduce this as a desktop Java console app, if possible.) – Jon Skeet Nov 21 '14 at 14:44

1 Answers1

1

tl;dr

Interval.of( 
    start , 
    stop 
).contains( 
    ZonedDateTime.now( ZoneId.of( "America/Montreal" ) )
                 .toInstant() 
)

Details

The question is confusing, but seems to be…

How do I tell if a particular moment occurs within a span of time?

java.time

I mean: Date1 - today, 10:00PM Date2 - tomorrow, 5:00AM Date3 - current time

A time zone is crucial in determining “today” and “tomorrow”. 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 as America/Montreal, Africa/Casablanca, or Pacific/Auckland. Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

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

To get the same date with another time-of-day, extract LocalDate. The LocalDate class represents a date-only value without time-of-day and without time zone. Specify desired time-of-day with LocalTime. Combine with ZoneId to get a ZonedDateTime.

LocalDate today = now.toLocalDate() ;
LocalTime tenPm = LocalTime.of( 22 , 0 ) ;  // 10 PM is 22:00.
ZonedDateTime tenPmToday = ZonedDateTime.of( today , tenPm , z ) ;

To get tomorrow, add one day to today's date.

LocalDate tomorrow = ld.plusDays( 1 ) ;
LocalTime fiveAm = LocalTime.of( 5 , 0 ) ;
ZonedDateTime fiveAmTomorrow = ZonedDateTime.of( tomorrow ,fiveAm , z ) ;

Compare

To compare, call the isBefore, isEqual, and isAfter methods.

Boolean contains = ( ! now.isBefore( tenPmToday ) ) && now.isBefore( fiveAmTomorrow ) ;

Of course, now will always be before tomorrow, so I'm not sure of your intentions here.

org.threeten.extra.Interval

You may find the Interval class useful for this work, from the ThreeTen-Extra project listed below. This class stores a pair of Instant objects, and has some handy comparison methods such as contains.

The Instant class represents a moment on the timeline in UTC with a resolution of nanoseconds (up to nine (9) digits of a decimal fraction).

Interval interval = Interval.of( tenPmToday.toInstant() , fiveAmTomorrow.toInstant() ) ;
Boolean contains = interval.contains( now.toInstant() ) ;

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.

Joda-Time

Update: the Joda-Time project is now in maintenance mode, with the team advising migration to the java.time classes.

The best way is to use the Joda-Time library, rather than the java.util.Date/.Calendar classes which are notoriously troublesome, confusing, and flawed.

Span Of Time

In Joda-Time you can represent a span of time in three ways: Interval, Period, and Duration. In this case, we need Interval, defined by a pair of specific points in the timeline, with the half-open [) approach where the beginning is inclusive and the ending exclusive.

The pair of specific points, as well as the current moment now, are all represented by the DateTime class. Unlike a java.util.Date, a DateTime knows its own assigned time zone. If unspecified, the JVM’s current default time zone will be applied. So generally better to specify.

Example Code

Some example code using Joda-Time 2.5.

DateTimeZone zone = DateTimeZone.forID( "America/Montreal" );
DateTime now = DateTime.now( zone );
DateTime bedtime = now.withTime( 22, 0, 0, 0 );  // Today’s bedtime. May be past, future, or this very moment now.
DateTime risetime = bedtime.plusHours( 7 ); // 05:00 next morning.
Interval sleepInterval = new Interval( bedtime, risetime ); 
boolean asleep = sleepInterval.contains( now );  // Half-Open "[)" comparison, beginning is inclusive, ending exclusive.
Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154