2

I have a few questions about the java Date class, it's really confusing me.

I have two problems:

  • I have a date object, and I want to see if the date stored in it is later than the begin of the current day or not? So if it's later than today 00:00am or not?

  • The second problem is, I want to group several date objects by day. But again, I don't understand how I should check if it's within the 24 hours of a specific date.

I think they're kind of related, once I have the 'day' for a date object it can't be to hard?

Any help is really appreciated, the Date class is really confusing me..

3 Answers3

1

I have a date object, and I want to see if the date stored in it is later than the begin of the current day or not? So if it's later than today 00:00am or not?

  1. Create a date for today
  2. Reset hours minutes seconds etc
  3. Use the before method to compare.

The second problem is, I want to group several date objects by day. But again, I don't understand how I should check if it's within the 24 hours of a specific date.

Just group by year, month and date field, or reset the hours, minutes and seconds fields.

aioobe
  • 413,195
  • 112
  • 811
  • 826
  • The thing is I don't know how to group my objects in general. Should I create an ArrayList for every day that occurs or something? –  May 07 '11 at 23:49
  • I would probably use a `Map>`. – aioobe May 08 '11 at 05:15
1

The java Date / Calendar classes are really poorly implemented.

Sounds like you should use joda time - specificly LocalDate.

http://joda-time.sourceforge.net/key_partial.html

http://joda-time.sourceforge.net/api-release/org/joda/time/LocalDate.html

This should solve both #1 and #2.

FYI - JodaTime will be replacing the JDK dates eventually (jsr 310) Rough grouping solution:

public Map<LocalDate, List<Foo>> groupByDate(List<Foo> foos) {
  Map<LocalDate, List<Foo>> groupedFoo = new HashMap()<..>
  for(Foo foo : foos) {
    Date javaDate = foo.getDate();
    LocalDate jodaDate = new LocalDate(javaDate);
    List<Foo> dateGroupedFoos = groupedFoo.get(jodaDate);
    if (null == dateGroupedFoos) {
      dateGroupedFoos = new ArrayList()<..>;
      groupedFoo.put(jodaDate, dateGroupedFoos);
    }
    dateGroupedFoos.add(foo);
  }
}
TWK
  • 36
  • 1
  • This looks really good, I'll have a look at it. Android should've used this –  May 07 '11 at 20:19
  • FYI, the [Joda-Time](http://www.joda.org/joda-time/) project is now in maintenance mode, with the team advising migration to the [java.time](http://docs.oracle.com/javase/9/docs/api/java/time/package-summary.html) classes. Much of the java.time functionality is back-ported to Java 6 & Java 7 in the [***ThreeTen-Backport***](http://www.threeten.org/threetenbp/) project. Further adapted for earlier Android in the [***ThreeTenABP***](https://github.com/JakeWharton/ThreeTenABP) project. See [*How to use ThreeTenABP…*](http://stackoverflow.com/q/38922754/642706). – Basil Bourque Jan 23 '18 at 03:18
0

Days do not always start at 00:00

So if it's later than today 00:00am or not

Be aware that in some time zones on some dates, the day does not begin at 00:00:00. Anomalies such as Daylight Saving Time (DST) mean the day may start at another time, such as 01:00:00.

Time zone

Determining the start of the day requires a date. Determining a date requires a time zone.

A time zone is crucial in determining a date. 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 pseudo-zones such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

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

LocalDate

The LocalDate class represents a date-only value without time-of-day and without time zone.

LocalDate today = LocalDate.now( z ) ;

ZonedDateTime

Let java.time determine the first moment of that date. Specify a ZoneId to get a ZonedDateTime object.

ZonedDateTime todayStart = today.atStartOfDay( z ) ;  // Determine the first moment of the day in a particular time zone.

Comparison

I want to see if the date stored in it is later than the begin of the current day or not?

Use the comparison methods, isBefore, isAfter, and isEqual.

boolean isFuture = ! ( someZdt.isBefore( todayStart ) ) ; // A shorter way to say "is equal to or later" --> "is NOT before". 

Map & Set

I want to group several date objects by day … I don't understand how I should check if it's within the 24 hours of a specific date.

First of all, remember that days are not always 24 hours long. Because of anomalies such as DST, they may be 23 or 25 hours long, or some other length.

So if you want to track them by date, use LocalDate rather than hours. You can interrogate each ZonedDateTime for its LocalDate.

Use a Map, with the date-only portion (LocalDate) as a key, and with the ZonedDateTime objects for that date kept in a Collection such as Set for the map entry’s value.

Map < LocalDate, Set < ZonedDateTime > > map = new HashMap <>( );

Here's a full snippet of example code. You can run this code live at IdeOne.com.

Map < LocalDate, Set < ZonedDateTime > > map = new HashMap <>( );
Set < ZonedDateTime > set = null;

ZoneId z = ZoneId.of( "Africa/Tunis" );
LocalDate today = LocalDate.now( z );
ZonedDateTime todayStart = today.atStartOfDay( z );  // Determine the first moment of the day in a particular time zone.
map.putIfAbsent( todayStart.toLocalDate( ) , new HashSet <>( ) );
set = map.get( todayStart.toLocalDate( )  ) ;
set.add( todayStart );

ZonedDateTime zdt1 = todayStart.plusHours( 6 );
map.putIfAbsent( zdt1.toLocalDate( ) , new HashSet <>( ) );
set = map.get( zdt1.toLocalDate( )  ) ;
set.add( zdt1 );

ZonedDateTime zdt2 = todayStart.plusDays( 2 );
map.putIfAbsent( zdt2.toLocalDate( ) , new HashSet <>( ) );
set = map.get( zdt2.toLocalDate( )  ) ;
set.add( zdt2 );

ZonedDateTime zdt3 = todayStart.plusMonths( 4 );
map.putIfAbsent( zdt3.toLocalDate( ) , new HashSet <>( ) );
set = map.get( zdt3.toLocalDate( )  ) ;
set.add( zdt3 );

System.out.println( "map.toString(): " + map );

We expect to see 3 entries in the map, with one of those values being a set of two items while the other two values are a set of one item each. Read this output carefully, as a HashSet does not return items by the order in which they were put.

map.toString(): {2018-01-25=[2018-01-25T00:00+01:00[Africa/Tunis]], 2018-01-23=[2018-01-23T00:00+01:00[Africa/Tunis], 2018-01-23T06:00+01:00[Africa/Tunis]], 2018-05-23=[2018-05-23T00:00+01:00[Africa/Tunis]]}

Let's break that apart for clarity. We see that January 23 has a pair of values in its set, while January 25 and May 23 both have a single.

2018-01-25=[2018-01-25T00:00+01:00[Africa/Tunis]]

2018-01-23=[2018-01-23T00:00+01:00[Africa/Tunis], 2018-01-23T06:00+01:00[Africa/Tunis]],

2018-05-23=[2018-05-23T00:00+01:00[Africa/Tunis]]


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?

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154